linux/drivers/soc/ixp4xx/ixp4xx-npe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Intel IXP4xx Network Processor Engine driver for Linux
   4 *
   5 * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
   6 *
   7 * The code is based on publicly available information:
   8 * - Intel IXP4xx Developer's Manual and other e-papers
   9 * - Intel IXP400 Access Library Software (BSD license)
  10 * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
  11 *   Thanks, Christian.
  12 */
  13
  14#include <linux/delay.h>
  15#include <linux/dma-mapping.h>
  16#include <linux/firmware.h>
  17#include <linux/io.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/of.h>
  21#include <linux/platform_device.h>
  22#include <linux/soc/ixp4xx/npe.h>
  23
  24#define DEBUG_MSG                       0
  25#define DEBUG_FW                        0
  26
  27#define NPE_COUNT                       3
  28#define MAX_RETRIES                     1000    /* microseconds */
  29#define NPE_42X_DATA_SIZE               0x800   /* in dwords */
  30#define NPE_46X_DATA_SIZE               0x1000
  31#define NPE_A_42X_INSTR_SIZE            0x1000
  32#define NPE_B_AND_C_42X_INSTR_SIZE      0x800
  33#define NPE_46X_INSTR_SIZE              0x1000
  34#define REGS_SIZE                       0x1000
  35
  36#define NPE_PHYS_REG                    32
  37
  38#define FW_MAGIC                        0xFEEDF00D
  39#define FW_BLOCK_TYPE_INSTR             0x0
  40#define FW_BLOCK_TYPE_DATA              0x1
  41#define FW_BLOCK_TYPE_EOF               0xF
  42
  43/* NPE exec status (read) and command (write) */
  44#define CMD_NPE_STEP                    0x01
  45#define CMD_NPE_START                   0x02
  46#define CMD_NPE_STOP                    0x03
  47#define CMD_NPE_CLR_PIPE                0x04
  48#define CMD_CLR_PROFILE_CNT             0x0C
  49#define CMD_RD_INS_MEM                  0x10 /* instruction memory */
  50#define CMD_WR_INS_MEM                  0x11
  51#define CMD_RD_DATA_MEM                 0x12 /* data memory */
  52#define CMD_WR_DATA_MEM                 0x13
  53#define CMD_RD_ECS_REG                  0x14 /* exec access register */
  54#define CMD_WR_ECS_REG                  0x15
  55
  56#define STAT_RUN                        0x80000000
  57#define STAT_STOP                       0x40000000
  58#define STAT_CLEAR                      0x20000000
  59#define STAT_ECS_K                      0x00800000 /* pipeline clean */
  60
  61#define NPE_STEVT                       0x1B
  62#define NPE_STARTPC                     0x1C
  63#define NPE_REGMAP                      0x1E
  64#define NPE_CINDEX                      0x1F
  65
  66#define INSTR_WR_REG_SHORT              0x0000C000
  67#define INSTR_WR_REG_BYTE               0x00004000
  68#define INSTR_RD_FIFO                   0x0F888220
  69#define INSTR_RESET_MBOX                0x0FAC8210
  70
  71#define ECS_BG_CTXT_REG_0               0x00 /* Background Executing Context */
  72#define ECS_BG_CTXT_REG_1               0x01 /*         Stack level */
  73#define ECS_BG_CTXT_REG_2               0x02
  74#define ECS_PRI_1_CTXT_REG_0            0x04 /* Priority 1 Executing Context */
  75#define ECS_PRI_1_CTXT_REG_1            0x05 /*         Stack level */
  76#define ECS_PRI_1_CTXT_REG_2            0x06
  77#define ECS_PRI_2_CTXT_REG_0            0x08 /* Priority 2 Executing Context */
  78#define ECS_PRI_2_CTXT_REG_1            0x09 /*         Stack level */
  79#define ECS_PRI_2_CTXT_REG_2            0x0A
  80#define ECS_DBG_CTXT_REG_0              0x0C /* Debug Executing Context */
  81#define ECS_DBG_CTXT_REG_1              0x0D /*         Stack level */
  82#define ECS_DBG_CTXT_REG_2              0x0E
  83#define ECS_INSTRUCT_REG                0x11 /* NPE Instruction Register */
  84
  85#define ECS_REG_0_ACTIVE                0x80000000 /* all levels */
  86#define ECS_REG_0_NEXTPC_MASK           0x1FFF0000 /* BG/PRI1/PRI2 levels */
  87#define ECS_REG_0_LDUR_BITS             8
  88#define ECS_REG_0_LDUR_MASK             0x00000700 /* all levels */
  89#define ECS_REG_1_CCTXT_BITS            16
  90#define ECS_REG_1_CCTXT_MASK            0x000F0000 /* all levels */
  91#define ECS_REG_1_SELCTXT_BITS          0
  92#define ECS_REG_1_SELCTXT_MASK          0x0000000F /* all levels */
  93#define ECS_DBG_REG_2_IF                0x00100000 /* debug level */
  94#define ECS_DBG_REG_2_IE                0x00080000 /* debug level */
  95
  96/* NPE watchpoint_fifo register bit */
  97#define WFIFO_VALID                     0x80000000
  98
  99/* NPE messaging_status register bit definitions */
 100#define MSGSTAT_OFNE    0x00010000 /* OutFifoNotEmpty */
 101#define MSGSTAT_IFNF    0x00020000 /* InFifoNotFull */
 102#define MSGSTAT_OFNF    0x00040000 /* OutFifoNotFull */
 103#define MSGSTAT_IFNE    0x00080000 /* InFifoNotEmpty */
 104#define MSGSTAT_MBINT   0x00100000 /* Mailbox interrupt */
 105#define MSGSTAT_IFINT   0x00200000 /* InFifo interrupt */
 106#define MSGSTAT_OFINT   0x00400000 /* OutFifo interrupt */
 107#define MSGSTAT_WFINT   0x00800000 /* WatchFifo interrupt */
 108
 109/* NPE messaging_control register bit definitions */
 110#define MSGCTL_OUT_FIFO                 0x00010000 /* enable output FIFO */
 111#define MSGCTL_IN_FIFO                  0x00020000 /* enable input FIFO */
 112#define MSGCTL_OUT_FIFO_WRITE           0x01000000 /* enable FIFO + WRITE */
 113#define MSGCTL_IN_FIFO_WRITE            0x02000000
 114
 115/* NPE mailbox_status value for reset */
 116#define RESET_MBOX_STAT                 0x0000F0F0
 117
 118#define NPE_A_FIRMWARE "NPE-A"
 119#define NPE_B_FIRMWARE "NPE-B"
 120#define NPE_C_FIRMWARE "NPE-C"
 121
 122const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
 123
 124#define print_npe(pri, npe, fmt, ...)                                   \
 125        printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
 126
 127#if DEBUG_MSG
 128#define debug_msg(npe, fmt, ...)                                        \
 129        print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
 130#else
 131#define debug_msg(npe, fmt, ...)
 132#endif
 133
 134static struct {
 135        u32 reg, val;
 136} ecs_reset[] = {
 137        { ECS_BG_CTXT_REG_0,    0xA0000000 },
 138        { ECS_BG_CTXT_REG_1,    0x01000000 },
 139        { ECS_BG_CTXT_REG_2,    0x00008000 },
 140        { ECS_PRI_1_CTXT_REG_0, 0x20000080 },
 141        { ECS_PRI_1_CTXT_REG_1, 0x01000000 },
 142        { ECS_PRI_1_CTXT_REG_2, 0x00008000 },
 143        { ECS_PRI_2_CTXT_REG_0, 0x20000080 },
 144        { ECS_PRI_2_CTXT_REG_1, 0x01000000 },
 145        { ECS_PRI_2_CTXT_REG_2, 0x00008000 },
 146        { ECS_DBG_CTXT_REG_0,   0x20000000 },
 147        { ECS_DBG_CTXT_REG_1,   0x00000000 },
 148        { ECS_DBG_CTXT_REG_2,   0x001E0000 },
 149        { ECS_INSTRUCT_REG,     0x1003C00F },
 150};
 151
 152static struct npe npe_tab[NPE_COUNT] = {
 153        {
 154                .id     = 0,
 155        }, {
 156                .id     = 1,
 157        }, {
 158                .id     = 2,
 159        }
 160};
 161
 162int npe_running(struct npe *npe)
 163{
 164        return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
 165}
 166
 167static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
 168{
 169        __raw_writel(data, &npe->regs->exec_data);
 170        __raw_writel(addr, &npe->regs->exec_addr);
 171        __raw_writel(cmd, &npe->regs->exec_status_cmd);
 172}
 173
 174static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
 175{
 176        __raw_writel(addr, &npe->regs->exec_addr);
 177        __raw_writel(cmd, &npe->regs->exec_status_cmd);
 178        /* Iintroduce extra read cycles after issuing read command to NPE
 179           so that we read the register after the NPE has updated it.
 180           This is to overcome race condition between XScale and NPE */
 181        __raw_readl(&npe->regs->exec_data);
 182        __raw_readl(&npe->regs->exec_data);
 183        return __raw_readl(&npe->regs->exec_data);
 184}
 185
 186static void npe_clear_active(struct npe *npe, u32 reg)
 187{
 188        u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
 189        npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
 190}
 191
 192static void npe_start(struct npe *npe)
 193{
 194        /* ensure only Background Context Stack Level is active */
 195        npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
 196        npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
 197        npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
 198
 199        __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
 200        __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
 201}
 202
 203static void npe_stop(struct npe *npe)
 204{
 205        __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
 206        __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
 207}
 208
 209static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
 210                                        u32 ldur)
 211{
 212        u32 wc;
 213        int i;
 214
 215        /* set the Active bit, and the LDUR, in the debug level */
 216        npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
 217                      ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
 218
 219        /* set CCTXT at ECS DEBUG L3 to specify in which context to execute
 220           the instruction, and set SELCTXT at ECS DEBUG Level to specify
 221           which context store to access.
 222           Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
 223        */
 224        npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
 225                      (ctx << ECS_REG_1_CCTXT_BITS) |
 226                      (ctx << ECS_REG_1_SELCTXT_BITS));
 227
 228        /* clear the pipeline */
 229        __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
 230
 231        /* load NPE instruction into the instruction register */
 232        npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
 233
 234        /* we need this value later to wait for completion of NPE execution
 235           step */
 236        wc = __raw_readl(&npe->regs->watch_count);
 237
 238        /* issue a Step One command via the Execution Control register */
 239        __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
 240
 241        /* Watch Count register increments when NPE completes an instruction */
 242        for (i = 0; i < MAX_RETRIES; i++) {
 243                if (wc != __raw_readl(&npe->regs->watch_count))
 244                        return 0;
 245                udelay(1);
 246        }
 247
 248        print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
 249        return -ETIMEDOUT;
 250}
 251
 252static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
 253                                               u8 val, u32 ctx)
 254{
 255        /* here we build the NPE assembler instruction: mov8 d0, #0 */
 256        u32 instr = INSTR_WR_REG_BYTE | /* OpCode */
 257                addr << 9 |             /* base Operand */
 258                (val & 0x1F) << 4 |     /* lower 5 bits to immediate data */
 259                (val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
 260        return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
 261}
 262
 263static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
 264                                                u16 val, u32 ctx)
 265{
 266        /* here we build the NPE assembler instruction: mov16 d0, #0 */
 267        u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
 268                addr << 9 |             /* base Operand */
 269                (val & 0x1F) << 4 |     /* lower 5 bits to immediate data */
 270                (val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
 271        return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
 272}
 273
 274static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
 275                                                u32 val, u32 ctx)
 276{
 277        /* write in 16 bit steps first the high and then the low value */
 278        if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
 279                return -ETIMEDOUT;
 280        return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
 281}
 282
 283static int npe_reset(struct npe *npe)
 284{
 285        u32 val, ctl, exec_count, ctx_reg2;
 286        int i;
 287
 288        ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
 289                0x3F3FFFFF;
 290
 291        /* disable parity interrupt */
 292        __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
 293
 294        /* pre exec - debug instruction */
 295        /* turn off the halt bit by clearing Execution Count register. */
 296        exec_count = __raw_readl(&npe->regs->exec_count);
 297        __raw_writel(0, &npe->regs->exec_count);
 298        /* ensure that IF and IE are on (temporarily), so that we don't end up
 299           stepping forever */
 300        ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
 301        npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
 302                      ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
 303
 304        /* clear the FIFOs */
 305        while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
 306                ;
 307        while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
 308                /* read from the outFIFO until empty */
 309                print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
 310                          __raw_readl(&npe->regs->in_out_fifo));
 311
 312        while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
 313                /* step execution of the NPE intruction to read inFIFO using
 314                   the Debug Executing Context stack */
 315                if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
 316                        return -ETIMEDOUT;
 317
 318        /* reset the mailbox reg from the XScale side */
 319        __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
 320        /* from NPE side */
 321        if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
 322                return -ETIMEDOUT;
 323
 324        /* Reset the physical registers in the NPE register file */
 325        for (val = 0; val < NPE_PHYS_REG; val++) {
 326                if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
 327                        return -ETIMEDOUT;
 328                /* address is either 0 or 4 */
 329                if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
 330                        return -ETIMEDOUT;
 331        }
 332
 333        /* Reset the context store = each context's Context Store registers */
 334
 335        /* Context 0 has no STARTPC. Instead, this value is used to set NextPC
 336           for Background ECS, to set where NPE starts executing code */
 337        val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
 338        val &= ~ECS_REG_0_NEXTPC_MASK;
 339        val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
 340        npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
 341
 342        for (i = 0; i < 16; i++) {
 343                if (i) {        /* Context 0 has no STEVT nor STARTPC */
 344                        /* STEVT = off, 0x80 */
 345                        if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
 346                                return -ETIMEDOUT;
 347                        if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
 348                                return -ETIMEDOUT;
 349                }
 350                /* REGMAP = d0->p0, d8->p2, d16->p4 */
 351                if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
 352                        return -ETIMEDOUT;
 353                if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
 354                        return -ETIMEDOUT;
 355        }
 356
 357        /* post exec */
 358        /* clear active bit in debug level */
 359        npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
 360        /* clear the pipeline */
 361        __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
 362        /* restore previous values */
 363        __raw_writel(exec_count, &npe->regs->exec_count);
 364        npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
 365
 366        /* write reset values to Execution Context Stack registers */
 367        for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
 368                npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
 369                              ecs_reset[val].val);
 370
 371        /* clear the profile counter */
 372        __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
 373
 374        __raw_writel(0, &npe->regs->exec_count);
 375        __raw_writel(0, &npe->regs->action_points[0]);
 376        __raw_writel(0, &npe->regs->action_points[1]);
 377        __raw_writel(0, &npe->regs->action_points[2]);
 378        __raw_writel(0, &npe->regs->action_points[3]);
 379        __raw_writel(0, &npe->regs->watch_count);
 380
 381        val = ixp4xx_read_feature_bits();
 382        /* reset the NPE */
 383        ixp4xx_write_feature_bits(val &
 384                                  ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
 385        /* deassert reset */
 386        ixp4xx_write_feature_bits(val |
 387                                  (IXP4XX_FEATURE_RESET_NPEA << npe->id));
 388        for (i = 0; i < MAX_RETRIES; i++) {
 389                if (ixp4xx_read_feature_bits() &
 390                    (IXP4XX_FEATURE_RESET_NPEA << npe->id))
 391                        break;  /* NPE is back alive */
 392                udelay(1);
 393        }
 394        if (i == MAX_RETRIES)
 395                return -ETIMEDOUT;
 396
 397        npe_stop(npe);
 398
 399        /* restore NPE configuration bus Control Register - parity settings */
 400        __raw_writel(ctl, &npe->regs->messaging_control);
 401        return 0;
 402}
 403
 404
 405int npe_send_message(struct npe *npe, const void *msg, const char *what)
 406{
 407        const u32 *send = msg;
 408        int cycles = 0;
 409
 410        debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
 411                  what, send[0], send[1]);
 412
 413        if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
 414                debug_msg(npe, "NPE input FIFO not empty\n");
 415                return -EIO;
 416        }
 417
 418        __raw_writel(send[0], &npe->regs->in_out_fifo);
 419
 420        if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
 421                debug_msg(npe, "NPE input FIFO full\n");
 422                return -EIO;
 423        }
 424
 425        __raw_writel(send[1], &npe->regs->in_out_fifo);
 426
 427        while ((cycles < MAX_RETRIES) &&
 428               (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
 429                udelay(1);
 430                cycles++;
 431        }
 432
 433        if (cycles == MAX_RETRIES) {
 434                debug_msg(npe, "Timeout sending message\n");
 435                return -ETIMEDOUT;
 436        }
 437
 438#if DEBUG_MSG > 1
 439        debug_msg(npe, "Sending a message took %i cycles\n", cycles);
 440#endif
 441        return 0;
 442}
 443
 444int npe_recv_message(struct npe *npe, void *msg, const char *what)
 445{
 446        u32 *recv = msg;
 447        int cycles = 0, cnt = 0;
 448
 449        debug_msg(npe, "Trying to receive message %s\n", what);
 450
 451        while (cycles < MAX_RETRIES) {
 452                if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
 453                        recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
 454                        if (cnt == 2)
 455                                break;
 456                } else {
 457                        udelay(1);
 458                        cycles++;
 459                }
 460        }
 461
 462        switch(cnt) {
 463        case 1:
 464                debug_msg(npe, "Received [%08X]\n", recv[0]);
 465                break;
 466        case 2:
 467                debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
 468                break;
 469        }
 470
 471        if (cycles == MAX_RETRIES) {
 472                debug_msg(npe, "Timeout waiting for message\n");
 473                return -ETIMEDOUT;
 474        }
 475
 476#if DEBUG_MSG > 1
 477        debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
 478#endif
 479        return 0;
 480}
 481
 482int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
 483{
 484        int result;
 485        u32 *send = msg, recv[2];
 486
 487        if ((result = npe_send_message(npe, msg, what)) != 0)
 488                return result;
 489        if ((result = npe_recv_message(npe, recv, what)) != 0)
 490                return result;
 491
 492        if ((recv[0] != send[0]) || (recv[1] != send[1])) {
 493                debug_msg(npe, "Message %s: unexpected message received\n",
 494                          what);
 495                return -EIO;
 496        }
 497        return 0;
 498}
 499
 500
 501int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
 502{
 503        const struct firmware *fw_entry;
 504
 505        struct dl_block {
 506                u32 type;
 507                u32 offset;
 508        } *blk;
 509
 510        struct dl_image {
 511                u32 magic;
 512                u32 id;
 513                u32 size;
 514                union {
 515                        u32 data[0];
 516                        struct dl_block blocks[0];
 517                };
 518        } *image;
 519
 520        struct dl_codeblock {
 521                u32 npe_addr;
 522                u32 size;
 523                u32 data[0];
 524        } *cb;
 525
 526        int i, j, err, data_size, instr_size, blocks, table_end;
 527        u32 cmd;
 528
 529        if ((err = request_firmware(&fw_entry, name, dev)) != 0)
 530                return err;
 531
 532        err = -EINVAL;
 533        if (fw_entry->size < sizeof(struct dl_image)) {
 534                print_npe(KERN_ERR, npe, "incomplete firmware file\n");
 535                goto err;
 536        }
 537        image = (struct dl_image*)fw_entry->data;
 538
 539#if DEBUG_FW
 540        print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
 541                  image->magic, image->id, image->size, image->size * 4);
 542#endif
 543
 544        if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
 545                image->id = swab32(image->id);
 546                image->size = swab32(image->size);
 547        } else if (image->magic != FW_MAGIC) {
 548                print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
 549                          image->magic);
 550                goto err;
 551        }
 552        if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
 553                print_npe(KERN_ERR, npe,
 554                          "inconsistent size of firmware file\n");
 555                goto err;
 556        }
 557        if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
 558                print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
 559                goto err;
 560        }
 561        if (image->magic == swab32(FW_MAGIC))
 562                for (i = 0; i < image->size; i++)
 563                        image->data[i] = swab32(image->data[i]);
 564
 565        if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) {
 566                print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
 567                          "IXP42x\n");
 568                goto err;
 569        }
 570
 571        if (npe_running(npe)) {
 572                print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
 573                          "already running\n");
 574                err = -EBUSY;
 575                goto err;
 576        }
 577#if 0
 578        npe_stop(npe);
 579        npe_reset(npe);
 580#endif
 581
 582        print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
 583                  "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
 584                  (image->id >> 8) & 0xFF, image->id & 0xFF);
 585
 586        if (cpu_is_ixp42x()) {
 587                if (!npe->id)
 588                        instr_size = NPE_A_42X_INSTR_SIZE;
 589                else
 590                        instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
 591                data_size = NPE_42X_DATA_SIZE;
 592        } else {
 593                instr_size = NPE_46X_INSTR_SIZE;
 594                data_size = NPE_46X_DATA_SIZE;
 595        }
 596
 597        for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
 598             blocks++)
 599                if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
 600                        break;
 601        if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
 602                print_npe(KERN_INFO, npe, "firmware EOF block marker not "
 603                          "found\n");
 604                goto err;
 605        }
 606
 607#if DEBUG_FW
 608        print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
 609#endif
 610
 611        table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
 612        for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
 613                if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
 614                    || blk->offset < table_end) {
 615                        print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
 616                                  "firmware block #%i\n", blk->offset, i);
 617                        goto err;
 618                }
 619
 620                cb = (struct dl_codeblock*)&image->data[blk->offset];
 621                if (blk->type == FW_BLOCK_TYPE_INSTR) {
 622                        if (cb->npe_addr + cb->size > instr_size)
 623                                goto too_big;
 624                        cmd = CMD_WR_INS_MEM;
 625                } else if (blk->type == FW_BLOCK_TYPE_DATA) {
 626                        if (cb->npe_addr + cb->size > data_size)
 627                                goto too_big;
 628                        cmd = CMD_WR_DATA_MEM;
 629                } else {
 630                        print_npe(KERN_INFO, npe, "invalid firmware block #%i "
 631                                  "type 0x%X\n", i, blk->type);
 632                        goto err;
 633                }
 634                if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
 635                        print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
 636                                  "fit in firmware image: type %c, start 0x%X,"
 637                                  " length 0x%X\n", i,
 638                                  blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
 639                                  cb->npe_addr, cb->size);
 640                        goto err;
 641                }
 642
 643                for (j = 0; j < cb->size; j++)
 644                        npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
 645        }
 646
 647        npe_start(npe);
 648        if (!npe_running(npe))
 649                print_npe(KERN_ERR, npe, "unable to start\n");
 650        release_firmware(fw_entry);
 651        return 0;
 652
 653too_big:
 654        print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
 655                  "memory: type %c, start 0x%X, length 0x%X\n", i,
 656                  blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
 657                  cb->npe_addr, cb->size);
 658err:
 659        release_firmware(fw_entry);
 660        return err;
 661}
 662
 663
 664struct npe *npe_request(unsigned id)
 665{
 666        if (id < NPE_COUNT)
 667                if (npe_tab[id].valid)
 668                        if (try_module_get(THIS_MODULE))
 669                                return &npe_tab[id];
 670        return NULL;
 671}
 672
 673void npe_release(struct npe *npe)
 674{
 675        module_put(THIS_MODULE);
 676}
 677
 678static int ixp4xx_npe_probe(struct platform_device *pdev)
 679{
 680        int i, found = 0;
 681        struct device *dev = &pdev->dev;
 682        struct resource *res;
 683
 684        for (i = 0; i < NPE_COUNT; i++) {
 685                struct npe *npe = &npe_tab[i];
 686
 687                res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 688                if (!res)
 689                        return -ENODEV;
 690
 691                if (!(ixp4xx_read_feature_bits() &
 692                      (IXP4XX_FEATURE_RESET_NPEA << i))) {
 693                        dev_info(dev, "NPE%d at 0x%08x-0x%08x not available\n",
 694                                 i, res->start, res->end);
 695                        continue; /* NPE already disabled or not present */
 696                }
 697                npe->regs = devm_ioremap_resource(dev, res);
 698                if (IS_ERR(npe->regs))
 699                        return PTR_ERR(npe->regs);
 700
 701                if (npe_reset(npe)) {
 702                        dev_info(dev, "NPE%d at 0x%08x-0x%08x does not reset\n",
 703                                 i, res->start, res->end);
 704                        continue;
 705                }
 706                npe->valid = 1;
 707                dev_info(dev, "NPE%d at 0x%08x-0x%08x registered\n",
 708                         i, res->start, res->end);
 709                found++;
 710        }
 711
 712        if (!found)
 713                return -ENODEV;
 714        return 0;
 715}
 716
 717static int ixp4xx_npe_remove(struct platform_device *pdev)
 718{
 719        int i;
 720
 721        for (i = 0; i < NPE_COUNT; i++)
 722                if (npe_tab[i].regs) {
 723                        npe_reset(&npe_tab[i]);
 724                }
 725
 726        return 0;
 727}
 728
 729static const struct of_device_id ixp4xx_npe_of_match[] = {
 730        {
 731                .compatible = "intel,ixp4xx-network-processing-engine",
 732        },
 733        {},
 734};
 735
 736static struct platform_driver ixp4xx_npe_driver = {
 737        .driver = {
 738                .name           = "ixp4xx-npe",
 739                .of_match_table = of_match_ptr(ixp4xx_npe_of_match),
 740        },
 741        .probe = ixp4xx_npe_probe,
 742        .remove = ixp4xx_npe_remove,
 743};
 744module_platform_driver(ixp4xx_npe_driver);
 745
 746MODULE_AUTHOR("Krzysztof Halasa");
 747MODULE_LICENSE("GPL v2");
 748MODULE_FIRMWARE(NPE_A_FIRMWARE);
 749MODULE_FIRMWARE(NPE_B_FIRMWARE);
 750MODULE_FIRMWARE(NPE_C_FIRMWARE);
 751
 752EXPORT_SYMBOL(npe_names);
 753EXPORT_SYMBOL(npe_running);
 754EXPORT_SYMBOL(npe_request);
 755EXPORT_SYMBOL(npe_release);
 756EXPORT_SYMBOL(npe_load_firmware);
 757EXPORT_SYMBOL(npe_send_message);
 758EXPORT_SYMBOL(npe_recv_message);
 759EXPORT_SYMBOL(npe_send_recv_message);
 760