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