1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/delay.h>
18#include <linux/dma-mapping.h>
19#include <linux/firmware.h>
20#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <mach/npe.h>
24
25#define DEBUG_MSG 0
26#define DEBUG_FW 0
27
28#define NPE_COUNT 3
29#define MAX_RETRIES 1000
30#define NPE_42X_DATA_SIZE 0x800
31#define NPE_46X_DATA_SIZE 0x1000
32#define NPE_A_42X_INSTR_SIZE 0x1000
33#define NPE_B_AND_C_42X_INSTR_SIZE 0x800
34#define NPE_46X_INSTR_SIZE 0x1000
35#define REGS_SIZE 0x1000
36
37#define NPE_PHYS_REG 32
38
39#define FW_MAGIC 0xFEEDF00D
40#define FW_BLOCK_TYPE_INSTR 0x0
41#define FW_BLOCK_TYPE_DATA 0x1
42#define FW_BLOCK_TYPE_EOF 0xF
43
44
45#define CMD_NPE_STEP 0x01
46#define CMD_NPE_START 0x02
47#define CMD_NPE_STOP 0x03
48#define CMD_NPE_CLR_PIPE 0x04
49#define CMD_CLR_PROFILE_CNT 0x0C
50#define CMD_RD_INS_MEM 0x10
51#define CMD_WR_INS_MEM 0x11
52#define CMD_RD_DATA_MEM 0x12
53#define CMD_WR_DATA_MEM 0x13
54#define CMD_RD_ECS_REG 0x14
55#define CMD_WR_ECS_REG 0x15
56
57#define STAT_RUN 0x80000000
58#define STAT_STOP 0x40000000
59#define STAT_CLEAR 0x20000000
60#define STAT_ECS_K 0x00800000
61
62#define NPE_STEVT 0x1B
63#define NPE_STARTPC 0x1C
64#define NPE_REGMAP 0x1E
65#define NPE_CINDEX 0x1F
66
67#define INSTR_WR_REG_SHORT 0x0000C000
68#define INSTR_WR_REG_BYTE 0x00004000
69#define INSTR_RD_FIFO 0x0F888220
70#define INSTR_RESET_MBOX 0x0FAC8210
71
72#define ECS_BG_CTXT_REG_0 0x00
73#define ECS_BG_CTXT_REG_1 0x01
74#define ECS_BG_CTXT_REG_2 0x02
75#define ECS_PRI_1_CTXT_REG_0 0x04
76#define ECS_PRI_1_CTXT_REG_1 0x05
77#define ECS_PRI_1_CTXT_REG_2 0x06
78#define ECS_PRI_2_CTXT_REG_0 0x08
79#define ECS_PRI_2_CTXT_REG_1 0x09
80#define ECS_PRI_2_CTXT_REG_2 0x0A
81#define ECS_DBG_CTXT_REG_0 0x0C
82#define ECS_DBG_CTXT_REG_1 0x0D
83#define ECS_DBG_CTXT_REG_2 0x0E
84#define ECS_INSTRUCT_REG 0x11
85
86#define ECS_REG_0_ACTIVE 0x80000000
87#define ECS_REG_0_NEXTPC_MASK 0x1FFF0000
88#define ECS_REG_0_LDUR_BITS 8
89#define ECS_REG_0_LDUR_MASK 0x00000700
90#define ECS_REG_1_CCTXT_BITS 16
91#define ECS_REG_1_CCTXT_MASK 0x000F0000
92#define ECS_REG_1_SELCTXT_BITS 0
93#define ECS_REG_1_SELCTXT_MASK 0x0000000F
94#define ECS_DBG_REG_2_IF 0x00100000
95#define ECS_DBG_REG_2_IE 0x00080000
96
97
98#define WFIFO_VALID 0x80000000
99
100
101#define MSGSTAT_OFNE 0x00010000
102#define MSGSTAT_IFNF 0x00020000
103#define MSGSTAT_OFNF 0x00040000
104#define MSGSTAT_IFNE 0x00080000
105#define MSGSTAT_MBINT 0x00100000
106#define MSGSTAT_IFINT 0x00200000
107#define MSGSTAT_OFINT 0x00400000
108#define MSGSTAT_WFINT 0x00800000
109
110
111#define MSGCTL_OUT_FIFO 0x00010000
112#define MSGCTL_IN_FIFO 0x00020000
113#define MSGCTL_OUT_FIFO_WRITE 0x01000000
114#define MSGCTL_IN_FIFO_WRITE 0x02000000
115
116
117#define RESET_MBOX_STAT 0x0000F0F0
118
119const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
120
121#define print_npe(pri, npe, fmt, ...) \
122 printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
123
124#if DEBUG_MSG
125#define debug_msg(npe, fmt, ...) \
126 print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
127#else
128#define debug_msg(npe, fmt, ...)
129#endif
130
131static struct {
132 u32 reg, val;
133} ecs_reset[] = {
134 { ECS_BG_CTXT_REG_0, 0xA0000000 },
135 { ECS_BG_CTXT_REG_1, 0x01000000 },
136 { ECS_BG_CTXT_REG_2, 0x00008000 },
137 { ECS_PRI_1_CTXT_REG_0, 0x20000080 },
138 { ECS_PRI_1_CTXT_REG_1, 0x01000000 },
139 { ECS_PRI_1_CTXT_REG_2, 0x00008000 },
140 { ECS_PRI_2_CTXT_REG_0, 0x20000080 },
141 { ECS_PRI_2_CTXT_REG_1, 0x01000000 },
142 { ECS_PRI_2_CTXT_REG_2, 0x00008000 },
143 { ECS_DBG_CTXT_REG_0, 0x20000000 },
144 { ECS_DBG_CTXT_REG_1, 0x00000000 },
145 { ECS_DBG_CTXT_REG_2, 0x001E0000 },
146 { ECS_INSTRUCT_REG, 0x1003C00F },
147};
148
149static struct npe npe_tab[NPE_COUNT] = {
150 {
151 .id = 0,
152 .regs = (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT,
153 .regs_phys = IXP4XX_NPEA_BASE_PHYS,
154 }, {
155 .id = 1,
156 .regs = (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT,
157 .regs_phys = IXP4XX_NPEB_BASE_PHYS,
158 }, {
159 .id = 2,
160 .regs = (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT,
161 .regs_phys = IXP4XX_NPEC_BASE_PHYS,
162 }
163};
164
165int npe_running(struct npe *npe)
166{
167 return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
168}
169
170static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
171{
172 __raw_writel(data, &npe->regs->exec_data);
173 __raw_writel(addr, &npe->regs->exec_addr);
174 __raw_writel(cmd, &npe->regs->exec_status_cmd);
175}
176
177static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
178{
179 __raw_writel(addr, &npe->regs->exec_addr);
180 __raw_writel(cmd, &npe->regs->exec_status_cmd);
181
182
183
184 __raw_readl(&npe->regs->exec_data);
185 __raw_readl(&npe->regs->exec_data);
186 return __raw_readl(&npe->regs->exec_data);
187}
188
189static void npe_clear_active(struct npe *npe, u32 reg)
190{
191 u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
192 npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
193}
194
195static void npe_start(struct npe *npe)
196{
197
198 npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
199 npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
200 npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
201
202 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
203 __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
204}
205
206static void npe_stop(struct npe *npe)
207{
208 __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
209 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
210}
211
212static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
213 u32 ldur)
214{
215 u32 wc;
216 int i;
217
218
219 npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
220 ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
221
222
223
224
225
226
227 npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
228 (ctx << ECS_REG_1_CCTXT_BITS) |
229 (ctx << ECS_REG_1_SELCTXT_BITS));
230
231
232 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
233
234
235 npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
236
237
238
239 wc = __raw_readl(&npe->regs->watch_count);
240
241
242 __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
243
244
245 for (i = 0; i < MAX_RETRIES; i++) {
246 if (wc != __raw_readl(&npe->regs->watch_count))
247 return 0;
248 udelay(1);
249 }
250
251 print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
252 return -ETIMEDOUT;
253}
254
255static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
256 u8 val, u32 ctx)
257{
258
259 u32 instr = INSTR_WR_REG_BYTE |
260 addr << 9 |
261 (val & 0x1F) << 4 |
262 (val & ~0x1F) << (18 - 5);
263 return npe_debug_instr(npe, instr, ctx, 1);
264}
265
266static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
267 u16 val, u32 ctx)
268{
269
270 u32 instr = INSTR_WR_REG_SHORT |
271 addr << 9 |
272 (val & 0x1F) << 4 |
273 (val & ~0x1F) << (18 - 5);
274 return npe_debug_instr(npe, instr, ctx, 1);
275}
276
277static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
278 u32 val, u32 ctx)
279{
280
281 if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
282 return -ETIMEDOUT;
283 return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
284}
285
286static int npe_reset(struct npe *npe)
287{
288 u32 val, ctl, exec_count, ctx_reg2;
289 int i;
290
291 ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
292 0x3F3FFFFF;
293
294
295 __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
296
297
298
299 exec_count = __raw_readl(&npe->regs->exec_count);
300 __raw_writel(0, &npe->regs->exec_count);
301
302
303 ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
304 npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
305 ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
306
307
308 while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
309 ;
310 while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
311
312 print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
313 __raw_readl(&npe->regs->in_out_fifo));
314
315 while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
316
317
318 if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
319 return -ETIMEDOUT;
320
321
322 __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
323
324 if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
325 return -ETIMEDOUT;
326
327
328 for (val = 0; val < NPE_PHYS_REG; val++) {
329 if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
330 return -ETIMEDOUT;
331
332 if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
333 return -ETIMEDOUT;
334 }
335
336
337
338
339
340 val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
341 val &= ~ECS_REG_0_NEXTPC_MASK;
342 val |= (0 << 16) & ECS_REG_0_NEXTPC_MASK;
343 npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
344
345 for (i = 0; i < 16; i++) {
346 if (i) {
347
348 if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
349 return -ETIMEDOUT;
350 if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
351 return -ETIMEDOUT;
352 }
353
354 if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
355 return -ETIMEDOUT;
356 if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
357 return -ETIMEDOUT;
358 }
359
360
361
362 npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
363
364 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
365
366 __raw_writel(exec_count, &npe->regs->exec_count);
367 npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
368
369
370 for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
371 npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
372 ecs_reset[val].val);
373
374
375 __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
376
377 __raw_writel(0, &npe->regs->exec_count);
378 __raw_writel(0, &npe->regs->action_points[0]);
379 __raw_writel(0, &npe->regs->action_points[1]);
380 __raw_writel(0, &npe->regs->action_points[2]);
381 __raw_writel(0, &npe->regs->action_points[3]);
382 __raw_writel(0, &npe->regs->watch_count);
383
384 val = ixp4xx_read_feature_bits();
385
386 ixp4xx_write_feature_bits(val &
387 ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
388
389 ixp4xx_write_feature_bits(val |
390 (IXP4XX_FEATURE_RESET_NPEA << npe->id));
391 for (i = 0; i < MAX_RETRIES; i++) {
392 if (ixp4xx_read_feature_bits() &
393 (IXP4XX_FEATURE_RESET_NPEA << npe->id))
394 break;
395 udelay(1);
396 }
397 if (i == MAX_RETRIES)
398 return -ETIMEDOUT;
399
400 npe_stop(npe);
401
402
403 __raw_writel(ctl, &npe->regs->messaging_control);
404 return 0;
405}
406
407
408int npe_send_message(struct npe *npe, const void *msg, const char *what)
409{
410 const u32 *send = msg;
411 int cycles = 0;
412
413 debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
414 what, send[0], send[1]);
415
416 if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
417 debug_msg(npe, "NPE input FIFO not empty\n");
418 return -EIO;
419 }
420
421 __raw_writel(send[0], &npe->regs->in_out_fifo);
422
423 if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
424 debug_msg(npe, "NPE input FIFO full\n");
425 return -EIO;
426 }
427
428 __raw_writel(send[1], &npe->regs->in_out_fifo);
429
430 while ((cycles < MAX_RETRIES) &&
431 (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
432 udelay(1);
433 cycles++;
434 }
435
436 if (cycles == MAX_RETRIES) {
437 debug_msg(npe, "Timeout sending message\n");
438 return -ETIMEDOUT;
439 }
440
441#if DEBUG_MSG > 1
442 debug_msg(npe, "Sending a message took %i cycles\n", cycles);
443#endif
444 return 0;
445}
446
447int npe_recv_message(struct npe *npe, void *msg, const char *what)
448{
449 u32 *recv = msg;
450 int cycles = 0, cnt = 0;
451
452 debug_msg(npe, "Trying to receive message %s\n", what);
453
454 while (cycles < MAX_RETRIES) {
455 if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
456 recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
457 if (cnt == 2)
458 break;
459 } else {
460 udelay(1);
461 cycles++;
462 }
463 }
464
465 switch(cnt) {
466 case 1:
467 debug_msg(npe, "Received [%08X]\n", recv[0]);
468 break;
469 case 2:
470 debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
471 break;
472 }
473
474 if (cycles == MAX_RETRIES) {
475 debug_msg(npe, "Timeout waiting for message\n");
476 return -ETIMEDOUT;
477 }
478
479#if DEBUG_MSG > 1
480 debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
481#endif
482 return 0;
483}
484
485int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
486{
487 int result;
488 u32 *send = msg, recv[2];
489
490 if ((result = npe_send_message(npe, msg, what)) != 0)
491 return result;
492 if ((result = npe_recv_message(npe, recv, what)) != 0)
493 return result;
494
495 if ((recv[0] != send[0]) || (recv[1] != send[1])) {
496 debug_msg(npe, "Message %s: unexpected message received\n",
497 what);
498 return -EIO;
499 }
500 return 0;
501}
502
503
504int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
505{
506 const struct firmware *fw_entry;
507
508 struct dl_block {
509 u32 type;
510 u32 offset;
511 } *blk;
512
513 struct dl_image {
514 u32 magic;
515 u32 id;
516 u32 size;
517 union {
518 u32 data[0];
519 struct dl_block blocks[0];
520 };
521 } *image;
522
523 struct dl_codeblock {
524 u32 npe_addr;
525 u32 size;
526 u32 data[0];
527 } *cb;
528
529 int i, j, err, data_size, instr_size, blocks, table_end;
530 u32 cmd;
531
532 if ((err = request_firmware(&fw_entry, name, dev)) != 0)
533 return err;
534
535 err = -EINVAL;
536 if (fw_entry->size < sizeof(struct dl_image)) {
537 print_npe(KERN_ERR, npe, "incomplete firmware file\n");
538 goto err;
539 }
540 image = (struct dl_image*)fw_entry->data;
541
542#if DEBUG_FW
543 print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
544 image->magic, image->id, image->size, image->size * 4);
545#endif
546
547 if (image->magic == swab32(FW_MAGIC)) {
548 image->id = swab32(image->id);
549 image->size = swab32(image->size);
550 } else if (image->magic != FW_MAGIC) {
551 print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
552 image->magic);
553 goto err;
554 }
555 if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
556 print_npe(KERN_ERR, npe,
557 "inconsistent size of firmware file\n");
558 goto err;
559 }
560 if (((image->id >> 24) & 0xF ) != npe->id) {
561 print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
562 goto err;
563 }
564 if (image->magic == swab32(FW_MAGIC))
565 for (i = 0; i < image->size; i++)
566 image->data[i] = swab32(image->data[i]);
567
568 if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF )) {
569 print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
570 "IXP42x\n");
571 goto err;
572 }
573
574 if (npe_running(npe)) {
575 print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
576 "already running\n");
577 err = -EBUSY;
578 goto err;
579 }
580#if 0
581 npe_stop(npe);
582 npe_reset(npe);
583#endif
584
585 print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
586 "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
587 (image->id >> 8) & 0xFF, image->id & 0xFF);
588
589 if (cpu_is_ixp42x()) {
590 if (!npe->id)
591 instr_size = NPE_A_42X_INSTR_SIZE;
592 else
593 instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
594 data_size = NPE_42X_DATA_SIZE;
595 } else {
596 instr_size = NPE_46X_INSTR_SIZE;
597 data_size = NPE_46X_DATA_SIZE;
598 }
599
600 for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
601 blocks++)
602 if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
603 break;
604 if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
605 print_npe(KERN_INFO, npe, "firmware EOF block marker not "
606 "found\n");
607 goto err;
608 }
609
610#if DEBUG_FW
611 print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
612#endif
613
614 table_end = blocks * sizeof(struct dl_block) / 4 + 1 ;
615 for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
616 if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
617 || blk->offset < table_end) {
618 print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
619 "firmware block #%i\n", blk->offset, i);
620 goto err;
621 }
622
623 cb = (struct dl_codeblock*)&image->data[blk->offset];
624 if (blk->type == FW_BLOCK_TYPE_INSTR) {
625 if (cb->npe_addr + cb->size > instr_size)
626 goto too_big;
627 cmd = CMD_WR_INS_MEM;
628 } else if (blk->type == FW_BLOCK_TYPE_DATA) {
629 if (cb->npe_addr + cb->size > data_size)
630 goto too_big;
631 cmd = CMD_WR_DATA_MEM;
632 } else {
633 print_npe(KERN_INFO, npe, "invalid firmware block #%i "
634 "type 0x%X\n", i, blk->type);
635 goto err;
636 }
637 if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
638 print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
639 "fit in firmware image: type %c, start 0x%X,"
640 " length 0x%X\n", i,
641 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
642 cb->npe_addr, cb->size);
643 goto err;
644 }
645
646 for (j = 0; j < cb->size; j++)
647 npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
648 }
649
650 npe_start(npe);
651 if (!npe_running(npe))
652 print_npe(KERN_ERR, npe, "unable to start\n");
653 release_firmware(fw_entry);
654 return 0;
655
656too_big:
657 print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
658 "memory: type %c, start 0x%X, length 0x%X\n", i,
659 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
660 cb->npe_addr, cb->size);
661err:
662 release_firmware(fw_entry);
663 return err;
664}
665
666
667struct npe *npe_request(unsigned id)
668{
669 if (id < NPE_COUNT)
670 if (npe_tab[id].valid)
671 if (try_module_get(THIS_MODULE))
672 return &npe_tab[id];
673 return NULL;
674}
675
676void npe_release(struct npe *npe)
677{
678 module_put(THIS_MODULE);
679}
680
681
682static int __init npe_init_module(void)
683{
684
685 int i, found = 0;
686
687 for (i = 0; i < NPE_COUNT; i++) {
688 struct npe *npe = &npe_tab[i];
689 if (!(ixp4xx_read_feature_bits() &
690 (IXP4XX_FEATURE_RESET_NPEA << i)))
691 continue;
692 if (!(npe->mem_res = request_mem_region(npe->regs_phys,
693 REGS_SIZE,
694 npe_name(npe)))) {
695 print_npe(KERN_ERR, npe,
696 "failed to request memory region\n");
697 continue;
698 }
699
700 if (npe_reset(npe))
701 continue;
702 npe->valid = 1;
703 found++;
704 }
705
706 if (!found)
707 return -ENODEV;
708 return 0;
709}
710
711static void __exit npe_cleanup_module(void)
712{
713 int i;
714
715 for (i = 0; i < NPE_COUNT; i++)
716 if (npe_tab[i].mem_res) {
717 npe_reset(&npe_tab[i]);
718 release_resource(npe_tab[i].mem_res);
719 }
720}
721
722module_init(npe_init_module);
723module_exit(npe_cleanup_module);
724
725MODULE_AUTHOR("Krzysztof Halasa");
726MODULE_LICENSE("GPL v2");
727
728EXPORT_SYMBOL(npe_names);
729EXPORT_SYMBOL(npe_running);
730EXPORT_SYMBOL(npe_request);
731EXPORT_SYMBOL(npe_release);
732EXPORT_SYMBOL(npe_load_firmware);
733EXPORT_SYMBOL(npe_send_message);
734EXPORT_SYMBOL(npe_recv_message);
735EXPORT_SYMBOL(npe_send_recv_message);
736