Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);