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