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