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