0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/delay.h>
0015 #include <linux/dma-mapping.h>
0016 #include <linux/firmware.h>
0017 #include <linux/io.h>
0018 #include <linux/kernel.h>
0019 #include <linux/mfd/syscon.h>
0020 #include <linux/module.h>
0021 #include <linux/of.h>
0022 #include <linux/of_platform.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/soc/ixp4xx/npe.h>
0025 #include <linux/soc/ixp4xx/cpu.h>
0026
0027 #define DEBUG_MSG 0
0028 #define DEBUG_FW 0
0029
0030 #define NPE_COUNT 3
0031 #define MAX_RETRIES 1000
0032 #define NPE_42X_DATA_SIZE 0x800
0033 #define NPE_46X_DATA_SIZE 0x1000
0034 #define NPE_A_42X_INSTR_SIZE 0x1000
0035 #define NPE_B_AND_C_42X_INSTR_SIZE 0x800
0036 #define NPE_46X_INSTR_SIZE 0x1000
0037 #define REGS_SIZE 0x1000
0038
0039 #define NPE_PHYS_REG 32
0040
0041 #define FW_MAGIC 0xFEEDF00D
0042 #define FW_BLOCK_TYPE_INSTR 0x0
0043 #define FW_BLOCK_TYPE_DATA 0x1
0044 #define FW_BLOCK_TYPE_EOF 0xF
0045
0046
0047 #define CMD_NPE_STEP 0x01
0048 #define CMD_NPE_START 0x02
0049 #define CMD_NPE_STOP 0x03
0050 #define CMD_NPE_CLR_PIPE 0x04
0051 #define CMD_CLR_PROFILE_CNT 0x0C
0052 #define CMD_RD_INS_MEM 0x10
0053 #define CMD_WR_INS_MEM 0x11
0054 #define CMD_RD_DATA_MEM 0x12
0055 #define CMD_WR_DATA_MEM 0x13
0056 #define CMD_RD_ECS_REG 0x14
0057 #define CMD_WR_ECS_REG 0x15
0058
0059 #define STAT_RUN 0x80000000
0060 #define STAT_STOP 0x40000000
0061 #define STAT_CLEAR 0x20000000
0062 #define STAT_ECS_K 0x00800000
0063
0064 #define NPE_STEVT 0x1B
0065 #define NPE_STARTPC 0x1C
0066 #define NPE_REGMAP 0x1E
0067 #define NPE_CINDEX 0x1F
0068
0069 #define INSTR_WR_REG_SHORT 0x0000C000
0070 #define INSTR_WR_REG_BYTE 0x00004000
0071 #define INSTR_RD_FIFO 0x0F888220
0072 #define INSTR_RESET_MBOX 0x0FAC8210
0073
0074 #define ECS_BG_CTXT_REG_0 0x00
0075 #define ECS_BG_CTXT_REG_1 0x01
0076 #define ECS_BG_CTXT_REG_2 0x02
0077 #define ECS_PRI_1_CTXT_REG_0 0x04
0078 #define ECS_PRI_1_CTXT_REG_1 0x05
0079 #define ECS_PRI_1_CTXT_REG_2 0x06
0080 #define ECS_PRI_2_CTXT_REG_0 0x08
0081 #define ECS_PRI_2_CTXT_REG_1 0x09
0082 #define ECS_PRI_2_CTXT_REG_2 0x0A
0083 #define ECS_DBG_CTXT_REG_0 0x0C
0084 #define ECS_DBG_CTXT_REG_1 0x0D
0085 #define ECS_DBG_CTXT_REG_2 0x0E
0086 #define ECS_INSTRUCT_REG 0x11
0087
0088 #define ECS_REG_0_ACTIVE 0x80000000
0089 #define ECS_REG_0_NEXTPC_MASK 0x1FFF0000
0090 #define ECS_REG_0_LDUR_BITS 8
0091 #define ECS_REG_0_LDUR_MASK 0x00000700
0092 #define ECS_REG_1_CCTXT_BITS 16
0093 #define ECS_REG_1_CCTXT_MASK 0x000F0000
0094 #define ECS_REG_1_SELCTXT_BITS 0
0095 #define ECS_REG_1_SELCTXT_MASK 0x0000000F
0096 #define ECS_DBG_REG_2_IF 0x00100000
0097 #define ECS_DBG_REG_2_IE 0x00080000
0098
0099
0100 #define WFIFO_VALID 0x80000000
0101
0102
0103 #define MSGSTAT_OFNE 0x00010000
0104 #define MSGSTAT_IFNF 0x00020000
0105 #define MSGSTAT_OFNF 0x00040000
0106 #define MSGSTAT_IFNE 0x00080000
0107 #define MSGSTAT_MBINT 0x00100000
0108 #define MSGSTAT_IFINT 0x00200000
0109 #define MSGSTAT_OFINT 0x00400000
0110 #define MSGSTAT_WFINT 0x00800000
0111
0112
0113 #define MSGCTL_OUT_FIFO 0x00010000
0114 #define MSGCTL_IN_FIFO 0x00020000
0115 #define MSGCTL_OUT_FIFO_WRITE 0x01000000
0116 #define MSGCTL_IN_FIFO_WRITE 0x02000000
0117
0118
0119 #define RESET_MBOX_STAT 0x0000F0F0
0120
0121 #define NPE_A_FIRMWARE "NPE-A"
0122 #define NPE_B_FIRMWARE "NPE-B"
0123 #define NPE_C_FIRMWARE "NPE-C"
0124
0125 const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
0126
0127 #define print_npe(pri, npe, fmt, ...) \
0128 printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
0129
0130 #if DEBUG_MSG
0131 #define debug_msg(npe, fmt, ...) \
0132 print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
0133 #else
0134 #define debug_msg(npe, fmt, ...)
0135 #endif
0136
0137 static struct {
0138 u32 reg, val;
0139 } ecs_reset[] = {
0140 { ECS_BG_CTXT_REG_0, 0xA0000000 },
0141 { ECS_BG_CTXT_REG_1, 0x01000000 },
0142 { ECS_BG_CTXT_REG_2, 0x00008000 },
0143 { ECS_PRI_1_CTXT_REG_0, 0x20000080 },
0144 { ECS_PRI_1_CTXT_REG_1, 0x01000000 },
0145 { ECS_PRI_1_CTXT_REG_2, 0x00008000 },
0146 { ECS_PRI_2_CTXT_REG_0, 0x20000080 },
0147 { ECS_PRI_2_CTXT_REG_1, 0x01000000 },
0148 { ECS_PRI_2_CTXT_REG_2, 0x00008000 },
0149 { ECS_DBG_CTXT_REG_0, 0x20000000 },
0150 { ECS_DBG_CTXT_REG_1, 0x00000000 },
0151 { ECS_DBG_CTXT_REG_2, 0x001E0000 },
0152 { ECS_INSTRUCT_REG, 0x1003C00F },
0153 };
0154
0155 static struct npe npe_tab[NPE_COUNT] = {
0156 {
0157 .id = 0,
0158 }, {
0159 .id = 1,
0160 }, {
0161 .id = 2,
0162 }
0163 };
0164
0165 int npe_running(struct npe *npe)
0166 {
0167 return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
0168 }
0169
0170 static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
0171 {
0172 __raw_writel(data, &npe->regs->exec_data);
0173 __raw_writel(addr, &npe->regs->exec_addr);
0174 __raw_writel(cmd, &npe->regs->exec_status_cmd);
0175 }
0176
0177 static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
0178 {
0179 __raw_writel(addr, &npe->regs->exec_addr);
0180 __raw_writel(cmd, &npe->regs->exec_status_cmd);
0181
0182
0183
0184 __raw_readl(&npe->regs->exec_data);
0185 __raw_readl(&npe->regs->exec_data);
0186 return __raw_readl(&npe->regs->exec_data);
0187 }
0188
0189 static void npe_clear_active(struct npe *npe, u32 reg)
0190 {
0191 u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
0192 npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
0193 }
0194
0195 static void npe_start(struct npe *npe)
0196 {
0197
0198 npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
0199 npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
0200 npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
0201
0202 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
0203 __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
0204 }
0205
0206 static void npe_stop(struct npe *npe)
0207 {
0208 __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
0209 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
0210 }
0211
0212 static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
0213 u32 ldur)
0214 {
0215 u32 wc;
0216 int i;
0217
0218
0219 npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
0220 ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
0221
0222
0223
0224
0225
0226
0227 npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
0228 (ctx << ECS_REG_1_CCTXT_BITS) |
0229 (ctx << ECS_REG_1_SELCTXT_BITS));
0230
0231
0232 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
0233
0234
0235 npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
0236
0237
0238
0239 wc = __raw_readl(&npe->regs->watch_count);
0240
0241
0242 __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
0243
0244
0245 for (i = 0; i < MAX_RETRIES; i++) {
0246 if (wc != __raw_readl(&npe->regs->watch_count))
0247 return 0;
0248 udelay(1);
0249 }
0250
0251 print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
0252 return -ETIMEDOUT;
0253 }
0254
0255 static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
0256 u8 val, u32 ctx)
0257 {
0258
0259 u32 instr = INSTR_WR_REG_BYTE |
0260 addr << 9 |
0261 (val & 0x1F) << 4 |
0262 (val & ~0x1F) << (18 - 5);
0263 return npe_debug_instr(npe, instr, ctx, 1);
0264 }
0265
0266 static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
0267 u16 val, u32 ctx)
0268 {
0269
0270 u32 instr = INSTR_WR_REG_SHORT |
0271 addr << 9 |
0272 (val & 0x1F) << 4 |
0273 (val & ~0x1F) << (18 - 5);
0274 return npe_debug_instr(npe, instr, ctx, 1);
0275 }
0276
0277 static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
0278 u32 val, u32 ctx)
0279 {
0280
0281 if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
0282 return -ETIMEDOUT;
0283 return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
0284 }
0285
0286 static int npe_reset(struct npe *npe)
0287 {
0288 u32 reset_bit = (IXP4XX_FEATURE_RESET_NPEA << npe->id);
0289 u32 val, ctl, exec_count, ctx_reg2;
0290 int i;
0291
0292 ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
0293 0x3F3FFFFF;
0294
0295
0296 __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
0297
0298
0299
0300 exec_count = __raw_readl(&npe->regs->exec_count);
0301 __raw_writel(0, &npe->regs->exec_count);
0302
0303
0304 ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
0305 npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
0306 ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
0307
0308
0309 while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
0310 ;
0311 while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
0312
0313 print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
0314 __raw_readl(&npe->regs->in_out_fifo));
0315
0316 while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
0317
0318
0319 if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
0320 return -ETIMEDOUT;
0321
0322
0323 __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
0324
0325 if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
0326 return -ETIMEDOUT;
0327
0328
0329 for (val = 0; val < NPE_PHYS_REG; val++) {
0330 if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
0331 return -ETIMEDOUT;
0332
0333 if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
0334 return -ETIMEDOUT;
0335 }
0336
0337
0338
0339
0340
0341 val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
0342 val &= ~ECS_REG_0_NEXTPC_MASK;
0343 val |= (0 << 16) & ECS_REG_0_NEXTPC_MASK;
0344 npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
0345
0346 for (i = 0; i < 16; i++) {
0347 if (i) {
0348
0349 if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
0350 return -ETIMEDOUT;
0351 if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
0352 return -ETIMEDOUT;
0353 }
0354
0355 if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
0356 return -ETIMEDOUT;
0357 if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
0358 return -ETIMEDOUT;
0359 }
0360
0361
0362
0363 npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
0364
0365 __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
0366
0367 __raw_writel(exec_count, &npe->regs->exec_count);
0368 npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
0369
0370
0371 for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
0372 npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
0373 ecs_reset[val].val);
0374
0375
0376 __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
0377
0378 __raw_writel(0, &npe->regs->exec_count);
0379 __raw_writel(0, &npe->regs->action_points[0]);
0380 __raw_writel(0, &npe->regs->action_points[1]);
0381 __raw_writel(0, &npe->regs->action_points[2]);
0382 __raw_writel(0, &npe->regs->action_points[3]);
0383 __raw_writel(0, &npe->regs->watch_count);
0384
0385
0386
0387
0388
0389 val = cpu_ixp4xx_features(npe->rmap);
0390
0391 regmap_write(npe->rmap, IXP4XX_EXP_CNFG2, val & ~reset_bit);
0392
0393 regmap_write(npe->rmap, IXP4XX_EXP_CNFG2, val | reset_bit);
0394
0395 for (i = 0; i < MAX_RETRIES; i++) {
0396 val = cpu_ixp4xx_features(npe->rmap);
0397 if (val & reset_bit)
0398 break;
0399 udelay(1);
0400 }
0401 if (i == MAX_RETRIES)
0402 return -ETIMEDOUT;
0403
0404 npe_stop(npe);
0405
0406
0407 __raw_writel(ctl, &npe->regs->messaging_control);
0408 return 0;
0409 }
0410
0411
0412 int npe_send_message(struct npe *npe, const void *msg, const char *what)
0413 {
0414 const u32 *send = msg;
0415 int cycles = 0;
0416
0417 debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
0418 what, send[0], send[1]);
0419
0420 if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
0421 debug_msg(npe, "NPE input FIFO not empty\n");
0422 return -EIO;
0423 }
0424
0425 __raw_writel(send[0], &npe->regs->in_out_fifo);
0426
0427 if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
0428 debug_msg(npe, "NPE input FIFO full\n");
0429 return -EIO;
0430 }
0431
0432 __raw_writel(send[1], &npe->regs->in_out_fifo);
0433
0434 while ((cycles < MAX_RETRIES) &&
0435 (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
0436 udelay(1);
0437 cycles++;
0438 }
0439
0440 if (cycles == MAX_RETRIES) {
0441 debug_msg(npe, "Timeout sending message\n");
0442 return -ETIMEDOUT;
0443 }
0444
0445 #if DEBUG_MSG > 1
0446 debug_msg(npe, "Sending a message took %i cycles\n", cycles);
0447 #endif
0448 return 0;
0449 }
0450
0451 int npe_recv_message(struct npe *npe, void *msg, const char *what)
0452 {
0453 u32 *recv = msg;
0454 int cycles = 0, cnt = 0;
0455
0456 debug_msg(npe, "Trying to receive message %s\n", what);
0457
0458 while (cycles < MAX_RETRIES) {
0459 if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
0460 recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
0461 if (cnt == 2)
0462 break;
0463 } else {
0464 udelay(1);
0465 cycles++;
0466 }
0467 }
0468
0469 switch(cnt) {
0470 case 1:
0471 debug_msg(npe, "Received [%08X]\n", recv[0]);
0472 break;
0473 case 2:
0474 debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
0475 break;
0476 }
0477
0478 if (cycles == MAX_RETRIES) {
0479 debug_msg(npe, "Timeout waiting for message\n");
0480 return -ETIMEDOUT;
0481 }
0482
0483 #if DEBUG_MSG > 1
0484 debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
0485 #endif
0486 return 0;
0487 }
0488
0489 int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
0490 {
0491 int result;
0492 u32 *send = msg, recv[2];
0493
0494 if ((result = npe_send_message(npe, msg, what)) != 0)
0495 return result;
0496 if ((result = npe_recv_message(npe, recv, what)) != 0)
0497 return result;
0498
0499 if ((recv[0] != send[0]) || (recv[1] != send[1])) {
0500 debug_msg(npe, "Message %s: unexpected message received\n",
0501 what);
0502 return -EIO;
0503 }
0504 return 0;
0505 }
0506
0507
0508 int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
0509 {
0510 const struct firmware *fw_entry;
0511
0512 struct dl_block {
0513 u32 type;
0514 u32 offset;
0515 } *blk;
0516
0517 struct dl_image {
0518 u32 magic;
0519 u32 id;
0520 u32 size;
0521 union {
0522 u32 data[0];
0523 struct dl_block blocks[0];
0524 };
0525 } *image;
0526
0527 struct dl_codeblock {
0528 u32 npe_addr;
0529 u32 size;
0530 u32 data[0];
0531 } *cb;
0532
0533 int i, j, err, data_size, instr_size, blocks, table_end;
0534 u32 cmd;
0535
0536 if ((err = request_firmware(&fw_entry, name, dev)) != 0)
0537 return err;
0538
0539 err = -EINVAL;
0540 if (fw_entry->size < sizeof(struct dl_image)) {
0541 print_npe(KERN_ERR, npe, "incomplete firmware file\n");
0542 goto err;
0543 }
0544 image = (struct dl_image*)fw_entry->data;
0545
0546 #if DEBUG_FW
0547 print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
0548 image->magic, image->id, image->size, image->size * 4);
0549 #endif
0550
0551 if (image->magic == swab32(FW_MAGIC)) {
0552 image->id = swab32(image->id);
0553 image->size = swab32(image->size);
0554 } else if (image->magic != FW_MAGIC) {
0555 print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
0556 image->magic);
0557 goto err;
0558 }
0559 if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
0560 print_npe(KERN_ERR, npe,
0561 "inconsistent size of firmware file\n");
0562 goto err;
0563 }
0564 if (((image->id >> 24) & 0xF ) != npe->id) {
0565 print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
0566 goto err;
0567 }
0568 if (image->magic == swab32(FW_MAGIC))
0569 for (i = 0; i < image->size; i++)
0570 image->data[i] = swab32(image->data[i]);
0571
0572 if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF )) {
0573 print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
0574 "IXP42x\n");
0575 goto err;
0576 }
0577
0578 if (npe_running(npe)) {
0579 print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
0580 "already running\n");
0581 err = -EBUSY;
0582 goto err;
0583 }
0584 #if 0
0585 npe_stop(npe);
0586 npe_reset(npe);
0587 #endif
0588
0589 print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
0590 "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
0591 (image->id >> 8) & 0xFF, image->id & 0xFF);
0592
0593 if (cpu_is_ixp42x()) {
0594 if (!npe->id)
0595 instr_size = NPE_A_42X_INSTR_SIZE;
0596 else
0597 instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
0598 data_size = NPE_42X_DATA_SIZE;
0599 } else {
0600 instr_size = NPE_46X_INSTR_SIZE;
0601 data_size = NPE_46X_DATA_SIZE;
0602 }
0603
0604 for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
0605 blocks++)
0606 if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
0607 break;
0608 if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
0609 print_npe(KERN_INFO, npe, "firmware EOF block marker not "
0610 "found\n");
0611 goto err;
0612 }
0613
0614 #if DEBUG_FW
0615 print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
0616 #endif
0617
0618 table_end = blocks * sizeof(struct dl_block) / 4 + 1 ;
0619 for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
0620 if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
0621 || blk->offset < table_end) {
0622 print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
0623 "firmware block #%i\n", blk->offset, i);
0624 goto err;
0625 }
0626
0627 cb = (struct dl_codeblock*)&image->data[blk->offset];
0628 if (blk->type == FW_BLOCK_TYPE_INSTR) {
0629 if (cb->npe_addr + cb->size > instr_size)
0630 goto too_big;
0631 cmd = CMD_WR_INS_MEM;
0632 } else if (blk->type == FW_BLOCK_TYPE_DATA) {
0633 if (cb->npe_addr + cb->size > data_size)
0634 goto too_big;
0635 cmd = CMD_WR_DATA_MEM;
0636 } else {
0637 print_npe(KERN_INFO, npe, "invalid firmware block #%i "
0638 "type 0x%X\n", i, blk->type);
0639 goto err;
0640 }
0641 if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
0642 print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
0643 "fit in firmware image: type %c, start 0x%X,"
0644 " length 0x%X\n", i,
0645 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
0646 cb->npe_addr, cb->size);
0647 goto err;
0648 }
0649
0650 for (j = 0; j < cb->size; j++)
0651 npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
0652 }
0653
0654 npe_start(npe);
0655 if (!npe_running(npe))
0656 print_npe(KERN_ERR, npe, "unable to start\n");
0657 release_firmware(fw_entry);
0658 return 0;
0659
0660 too_big:
0661 print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
0662 "memory: type %c, start 0x%X, length 0x%X\n", i,
0663 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
0664 cb->npe_addr, cb->size);
0665 err:
0666 release_firmware(fw_entry);
0667 return err;
0668 }
0669
0670
0671 struct npe *npe_request(unsigned id)
0672 {
0673 if (id < NPE_COUNT)
0674 if (npe_tab[id].valid)
0675 if (try_module_get(THIS_MODULE))
0676 return &npe_tab[id];
0677 return NULL;
0678 }
0679
0680 void npe_release(struct npe *npe)
0681 {
0682 module_put(THIS_MODULE);
0683 }
0684
0685 static int ixp4xx_npe_probe(struct platform_device *pdev)
0686 {
0687 int i, found = 0;
0688 struct device *dev = &pdev->dev;
0689 struct device_node *np = dev->of_node;
0690 struct resource *res;
0691 struct regmap *rmap;
0692 u32 val;
0693
0694
0695 rmap = syscon_regmap_lookup_by_compatible("syscon");
0696 if (IS_ERR(rmap))
0697 return dev_err_probe(dev, PTR_ERR(rmap),
0698 "failed to look up syscon\n");
0699
0700 for (i = 0; i < NPE_COUNT; i++) {
0701 struct npe *npe = &npe_tab[i];
0702
0703 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
0704 if (!res)
0705 return -ENODEV;
0706
0707 val = cpu_ixp4xx_features(rmap);
0708
0709 if (!(val & (IXP4XX_FEATURE_RESET_NPEA << i))) {
0710 dev_info(dev, "NPE%d at %pR not available\n",
0711 i, res);
0712 continue;
0713 }
0714 npe->regs = devm_ioremap_resource(dev, res);
0715 if (IS_ERR(npe->regs))
0716 return PTR_ERR(npe->regs);
0717 npe->rmap = rmap;
0718
0719 if (npe_reset(npe)) {
0720 dev_info(dev, "NPE%d at %pR does not reset\n",
0721 i, res);
0722 continue;
0723 }
0724 npe->valid = 1;
0725 dev_info(dev, "NPE%d at %pR registered\n", i, res);
0726 found++;
0727 }
0728
0729 if (!found)
0730 return -ENODEV;
0731
0732
0733 if (IS_ENABLED(CONFIG_OF) && np)
0734 devm_of_platform_populate(dev);
0735
0736 return 0;
0737 }
0738
0739 static int ixp4xx_npe_remove(struct platform_device *pdev)
0740 {
0741 int i;
0742
0743 for (i = 0; i < NPE_COUNT; i++)
0744 if (npe_tab[i].regs) {
0745 npe_reset(&npe_tab[i]);
0746 }
0747
0748 return 0;
0749 }
0750
0751 static const struct of_device_id ixp4xx_npe_of_match[] = {
0752 {
0753 .compatible = "intel,ixp4xx-network-processing-engine",
0754 },
0755 {},
0756 };
0757
0758 static struct platform_driver ixp4xx_npe_driver = {
0759 .driver = {
0760 .name = "ixp4xx-npe",
0761 .of_match_table = ixp4xx_npe_of_match,
0762 },
0763 .probe = ixp4xx_npe_probe,
0764 .remove = ixp4xx_npe_remove,
0765 };
0766 module_platform_driver(ixp4xx_npe_driver);
0767
0768 MODULE_AUTHOR("Krzysztof Halasa");
0769 MODULE_LICENSE("GPL v2");
0770 MODULE_FIRMWARE(NPE_A_FIRMWARE);
0771 MODULE_FIRMWARE(NPE_B_FIRMWARE);
0772 MODULE_FIRMWARE(NPE_C_FIRMWARE);
0773
0774 EXPORT_SYMBOL(npe_names);
0775 EXPORT_SYMBOL(npe_running);
0776 EXPORT_SYMBOL(npe_request);
0777 EXPORT_SYMBOL(npe_release);
0778 EXPORT_SYMBOL(npe_load_firmware);
0779 EXPORT_SYMBOL(npe_send_message);
0780 EXPORT_SYMBOL(npe_recv_message);
0781 EXPORT_SYMBOL(npe_send_recv_message);