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