Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Intel IXP4xx Network Processor Engine driver for Linux
0004  *
0005  * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
0006  *
0007  * The code is based on publicly available information:
0008  * - Intel IXP4xx Developer's Manual and other e-papers
0009  * - Intel IXP400 Access Library Software (BSD license)
0010  * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
0011  *   Thanks, Christian.
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    /* microseconds */
0032 #define NPE_42X_DATA_SIZE       0x800   /* in dwords */
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 /* NPE exec status (read) and command (write) */
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 /* instruction memory */
0053 #define CMD_WR_INS_MEM          0x11
0054 #define CMD_RD_DATA_MEM         0x12 /* data memory */
0055 #define CMD_WR_DATA_MEM         0x13
0056 #define CMD_RD_ECS_REG          0x14 /* exec access register */
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 /* pipeline clean */
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 /* Background Executing Context */
0075 #define ECS_BG_CTXT_REG_1       0x01 /*     Stack level */
0076 #define ECS_BG_CTXT_REG_2       0x02
0077 #define ECS_PRI_1_CTXT_REG_0        0x04 /* Priority 1 Executing Context */
0078 #define ECS_PRI_1_CTXT_REG_1        0x05 /*     Stack level */
0079 #define ECS_PRI_1_CTXT_REG_2        0x06
0080 #define ECS_PRI_2_CTXT_REG_0        0x08 /* Priority 2 Executing Context */
0081 #define ECS_PRI_2_CTXT_REG_1        0x09 /*     Stack level */
0082 #define ECS_PRI_2_CTXT_REG_2        0x0A
0083 #define ECS_DBG_CTXT_REG_0      0x0C /* Debug Executing Context */
0084 #define ECS_DBG_CTXT_REG_1      0x0D /*     Stack level */
0085 #define ECS_DBG_CTXT_REG_2      0x0E
0086 #define ECS_INSTRUCT_REG        0x11 /* NPE Instruction Register */
0087 
0088 #define ECS_REG_0_ACTIVE        0x80000000 /* all levels */
0089 #define ECS_REG_0_NEXTPC_MASK       0x1FFF0000 /* BG/PRI1/PRI2 levels */
0090 #define ECS_REG_0_LDUR_BITS     8
0091 #define ECS_REG_0_LDUR_MASK     0x00000700 /* all levels */
0092 #define ECS_REG_1_CCTXT_BITS        16
0093 #define ECS_REG_1_CCTXT_MASK        0x000F0000 /* all levels */
0094 #define ECS_REG_1_SELCTXT_BITS      0
0095 #define ECS_REG_1_SELCTXT_MASK      0x0000000F /* all levels */
0096 #define ECS_DBG_REG_2_IF        0x00100000 /* debug level */
0097 #define ECS_DBG_REG_2_IE        0x00080000 /* debug level */
0098 
0099 /* NPE watchpoint_fifo register bit */
0100 #define WFIFO_VALID         0x80000000
0101 
0102 /* NPE messaging_status register bit definitions */
0103 #define MSGSTAT_OFNE    0x00010000 /* OutFifoNotEmpty */
0104 #define MSGSTAT_IFNF    0x00020000 /* InFifoNotFull */
0105 #define MSGSTAT_OFNF    0x00040000 /* OutFifoNotFull */
0106 #define MSGSTAT_IFNE    0x00080000 /* InFifoNotEmpty */
0107 #define MSGSTAT_MBINT   0x00100000 /* Mailbox interrupt */
0108 #define MSGSTAT_IFINT   0x00200000 /* InFifo interrupt */
0109 #define MSGSTAT_OFINT   0x00400000 /* OutFifo interrupt */
0110 #define MSGSTAT_WFINT   0x00800000 /* WatchFifo interrupt */
0111 
0112 /* NPE messaging_control register bit definitions */
0113 #define MSGCTL_OUT_FIFO         0x00010000 /* enable output FIFO */
0114 #define MSGCTL_IN_FIFO          0x00020000 /* enable input FIFO */
0115 #define MSGCTL_OUT_FIFO_WRITE       0x01000000 /* enable FIFO + WRITE */
0116 #define MSGCTL_IN_FIFO_WRITE        0x02000000
0117 
0118 /* NPE mailbox_status value for reset */
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     /* Iintroduce extra read cycles after issuing read command to NPE
0182        so that we read the register after the NPE has updated it.
0183        This is to overcome race condition between XScale and NPE */
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     /* ensure only Background Context Stack Level is active */
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); /*FIXME?*/
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     /* set the Active bit, and the LDUR, in the debug level */
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     /* set CCTXT at ECS DEBUG L3 to specify in which context to execute
0223        the instruction, and set SELCTXT at ECS DEBUG Level to specify
0224        which context store to access.
0225        Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
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     /* clear the pipeline */
0232     __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
0233 
0234     /* load NPE instruction into the instruction register */
0235     npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
0236 
0237     /* we need this value later to wait for completion of NPE execution
0238        step */
0239     wc = __raw_readl(&npe->regs->watch_count);
0240 
0241     /* issue a Step One command via the Execution Control register */
0242     __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
0243 
0244     /* Watch Count register increments when NPE completes an instruction */
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     /* here we build the NPE assembler instruction: mov8 d0, #0 */
0259     u32 instr = INSTR_WR_REG_BYTE | /* OpCode */
0260         addr << 9 |     /* base Operand */
0261         (val & 0x1F) << 4 | /* lower 5 bits to immediate data */
0262         (val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
0263     return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
0264 }
0265 
0266 static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
0267                         u16 val, u32 ctx)
0268 {
0269     /* here we build the NPE assembler instruction: mov16 d0, #0 */
0270     u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
0271         addr << 9 |     /* base Operand */
0272         (val & 0x1F) << 4 | /* lower 5 bits to immediate data */
0273         (val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
0274     return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
0275 }
0276 
0277 static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
0278                         u32 val, u32 ctx)
0279 {
0280     /* write in 16 bit steps first the high and then the low value */
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     /* disable parity interrupt */
0296     __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
0297 
0298     /* pre exec - debug instruction */
0299     /* turn off the halt bit by clearing Execution Count register. */
0300     exec_count = __raw_readl(&npe->regs->exec_count);
0301     __raw_writel(0, &npe->regs->exec_count);
0302     /* ensure that IF and IE are on (temporarily), so that we don't end up
0303        stepping forever */
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     /* clear the FIFOs */
0309     while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
0310         ;
0311     while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
0312         /* read from the outFIFO until empty */
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         /* step execution of the NPE intruction to read inFIFO using
0318            the Debug Executing Context stack */
0319         if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
0320             return -ETIMEDOUT;
0321 
0322     /* reset the mailbox reg from the XScale side */
0323     __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
0324     /* from NPE side */
0325     if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
0326         return -ETIMEDOUT;
0327 
0328     /* Reset the physical registers in the NPE register file */
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         /* address is either 0 or 4 */
0333         if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
0334             return -ETIMEDOUT;
0335     }
0336 
0337     /* Reset the context store = each context's Context Store registers */
0338 
0339     /* Context 0 has no STARTPC. Instead, this value is used to set NextPC
0340        for Background ECS, to set where NPE starts executing code */
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 /* NextPC */ << 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) {    /* Context 0 has no STEVT nor STARTPC */
0348             /* STEVT = off, 0x80 */
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         /* REGMAP = d0->p0, d8->p2, d16->p4 */
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     /* post exec */
0362     /* clear active bit in debug level */
0363     npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
0364     /* clear the pipeline */
0365     __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
0366     /* restore previous values */
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     /* write reset values to Execution Context Stack registers */
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     /* clear the profile counter */
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      * We need to work on cached values here because the register
0387      * will read inverted but needs to be written non-inverted.
0388      */
0389     val = cpu_ixp4xx_features(npe->rmap);
0390     /* reset the NPE */
0391     regmap_write(npe->rmap, IXP4XX_EXP_CNFG2, val & ~reset_bit);
0392     /* deassert reset */
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;  /* NPE is back alive */
0399         udelay(1);
0400     }
0401     if (i == MAX_RETRIES)
0402         return -ETIMEDOUT;
0403 
0404     npe_stop(npe);
0405 
0406     /* restore NPE configuration bus Control Register - parity settings */
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)) { /* swapped file */
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 */) != 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 /* device ID */)) {
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 /* EOF marker */;
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     /* This system has only one syscon, so fetch it */
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; /* NPE already disabled or not present */
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     /* Spawn crypto subdevice if using device tree */
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);