ixp425_npe.c revision 331722
1/*-
2 * Copyright (c) 2006-2008 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer,
10 *    without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 *    redistribution must be conditioned upon including a substantially
14 *    similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30/*-
31 * Copyright (c) 2001-2005, Intel Corporation.
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 *    notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 *    notice, this list of conditions and the following disclaimer in the
41 *    documentation and/or other materials provided with the distribution.
42 * 3. Neither the name of the Intel Corporation nor the names of its contributors
43 *    may be used to endorse or promote products derived from this software
44 *    without specific prior written permission.
45 *
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58*/
59#include <sys/cdefs.h>
60__FBSDID("$FreeBSD: stable/11/sys/arm/xscale/ixp425/ixp425_npe.c 331722 2018-03-29 02:50:57Z eadler $");
61
62/*
63 * Intel XScale Network Processing Engine (NPE) support.
64 *
65 * Each NPE has an ixpnpeX device associated with it that is
66 * attached at boot.  Depending on the microcode loaded into
67 * an NPE there may be an Ethernet interface (npeX) or some
68 * other network interface (e.g. for ATM).  This file has support
69 * for loading microcode images and the associated NPE CPU
70 * manipulations (start, stop, reset).
71 *
72 * The code here basically replaces the npeDl and npeMh classes
73 * in the Intel Access Library (IAL).
74 *
75 * NB: Microcode images are loaded with firmware(9).  To
76 *     include microcode in a static kernel include the
77 *     ixpnpe_fw device.  Otherwise the firmware will be
78 *     automatically loaded from the filesystem.
79 */
80#include <sys/param.h>
81#include <sys/systm.h>
82#include <sys/kernel.h>
83#include <sys/malloc.h>
84#include <sys/module.h>
85#include <sys/time.h>
86#include <sys/bus.h>
87#include <sys/resource.h>
88#include <sys/rman.h>
89#include <sys/sysctl.h>
90
91#include <sys/linker.h>
92#include <sys/firmware.h>
93
94#include <machine/bus.h>
95#include <machine/resource.h>
96#include <machine/intr.h>
97#include <arm/xscale/ixp425/ixp425reg.h>
98#include <arm/xscale/ixp425/ixp425var.h>
99
100#include <arm/xscale/ixp425/ixp425_npereg.h>
101#include <arm/xscale/ixp425/ixp425_npevar.h>
102
103struct ixpnpe_softc {
104	device_t	sc_dev;
105	bus_space_tag_t	sc_iot;
106	bus_space_handle_t sc_ioh;
107	bus_size_t	sc_size;	/* size of mapped register window */
108	struct resource	*sc_irq;	/* IRQ resource */
109	void		*sc_ih;		/* interrupt handler */
110	struct mtx	sc_mtx;		/* mailbox lock */
111	uint32_t	sc_msg[2];	/* reply msg collected in ixpnpe_intr */
112	int		sc_msgwaiting;	/* sc_msg holds valid data */
113	int		sc_npeid;
114	int		sc_nrefs;	/* # of references */
115
116	int		validImage;	/* valid ucode image loaded */
117	int		started;	/* NPE is started */
118	uint8_t		functionalityId;/* ucode functionality ID */
119	int		insMemSize;	/* size of instruction memory */
120	int		dataMemSize;	/* size of data memory */
121	uint32_t	savedExecCount;
122	uint32_t	savedEcsDbgCtxtReg2;
123};
124static struct ixpnpe_softc *npes[NPE_MAX];
125
126#define	IX_NPEDL_NPEIMAGE_FIELD_MASK	0xff
127
128/* used to read download map from version in microcode image */
129#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION	0x00000000
130#define IX_NPEDL_BLOCK_TYPE_DATA	0x00000001
131#define IX_NPEDL_BLOCK_TYPE_STATE	0x00000002
132#define IX_NPEDL_END_OF_DOWNLOAD_MAP	0x0000000F
133
134/*
135 * masks used to extract address info from State information context
136 * register addresses as read from microcode image
137 */
138#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG         0x0000000F
139#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM         0x000000F0
140
141/* LSB offset of Context Number field in State-Info Context Address */
142#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM       4
143
144/* size (in words) of single State Information entry (ctxt reg address|data) */
145#define IX_NPEDL_STATE_INFO_ENTRY_SIZE	2
146
147typedef struct {
148	uint32_t type;
149	uint32_t offset;
150} IxNpeDlNpeMgrDownloadMapBlockEntry;
151
152typedef union {
153	IxNpeDlNpeMgrDownloadMapBlockEntry block;
154	uint32_t eodmMarker;
155} IxNpeDlNpeMgrDownloadMapEntry;
156
157typedef struct {
158	/* 1st entry in the download map (there may be more than one) */
159	IxNpeDlNpeMgrDownloadMapEntry entry[1];
160} IxNpeDlNpeMgrDownloadMap;
161
162/* used to access an instruction or data block in a microcode image */
163typedef struct {
164	uint32_t npeMemAddress;
165	uint32_t size;
166	uint32_t data[1];
167} IxNpeDlNpeMgrCodeBlock;
168
169/* used to access each Context Reg entry state-information block */
170typedef struct {
171	uint32_t addressInfo;
172	uint32_t value;
173} IxNpeDlNpeMgrStateInfoCtxtRegEntry;
174
175/* used to access a state-information block in a microcode image */
176typedef struct {
177	uint32_t size;
178	IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
179} IxNpeDlNpeMgrStateInfoBlock;
180
181static int npe_debug = 0;
182SYSCTL_INT(_debug, OID_AUTO, ixp425npe, CTLFLAG_RWTUN, &npe_debug,
183	   0, "IXP4XX NPE debug msgs");
184#define	DPRINTF(dev, fmt, ...) do {					\
185	if (npe_debug) device_printf(dev, fmt, __VA_ARGS__);		\
186} while (0)
187#define	DPRINTFn(n, dev, fmt, ...) do {					\
188	if (npe_debug >= n) printf(fmt, __VA_ARGS__);			\
189} while (0)
190
191static int npe_checkbits(struct ixpnpe_softc *, uint32_t reg, uint32_t);
192static int npe_isstopped(struct ixpnpe_softc *);
193static int npe_load_ins(struct ixpnpe_softc *,
194		const IxNpeDlNpeMgrCodeBlock *bp, int verify);
195static int npe_load_data(struct ixpnpe_softc *,
196		const IxNpeDlNpeMgrCodeBlock *bp, int verify);
197static int npe_load_stateinfo(struct ixpnpe_softc *,
198		const IxNpeDlNpeMgrStateInfoBlock *bp, int verify);
199static int npe_load_image(struct ixpnpe_softc *,
200		const uint32_t *imageCodePtr, int verify);
201static int npe_cpu_reset(struct ixpnpe_softc *);
202static int npe_cpu_start(struct ixpnpe_softc *);
203static int npe_cpu_stop(struct ixpnpe_softc *);
204static void npe_cmd_issue_write(struct ixpnpe_softc *,
205		uint32_t cmd, uint32_t addr, uint32_t data);
206static uint32_t npe_cmd_issue_read(struct ixpnpe_softc *,
207		uint32_t cmd, uint32_t addr);
208static int npe_ins_write(struct ixpnpe_softc *,
209		uint32_t addr, uint32_t data, int verify);
210static int npe_data_write(struct ixpnpe_softc *,
211		uint32_t addr, uint32_t data, int verify);
212static void npe_ecs_reg_write(struct ixpnpe_softc *,
213		uint32_t reg, uint32_t data);
214static uint32_t npe_ecs_reg_read(struct ixpnpe_softc *, uint32_t reg);
215static void npe_issue_cmd(struct ixpnpe_softc *, uint32_t command);
216static void npe_cpu_step_save(struct ixpnpe_softc *);
217static int npe_cpu_step(struct ixpnpe_softc *, uint32_t npeInstruction,
218		uint32_t ctxtNum, uint32_t ldur);
219static void npe_cpu_step_restore(struct ixpnpe_softc *);
220static int npe_logical_reg_read(struct ixpnpe_softc *,
221		uint32_t regAddr, uint32_t regSize,
222		uint32_t ctxtNum, uint32_t *regVal);
223static int npe_logical_reg_write(struct ixpnpe_softc *,
224		uint32_t regAddr, uint32_t regVal,
225		uint32_t regSize, uint32_t ctxtNum, int verify);
226static int npe_physical_reg_write(struct ixpnpe_softc *,
227		uint32_t regAddr, uint32_t regValue, int verify);
228static int npe_ctx_reg_write(struct ixpnpe_softc *, uint32_t ctxtNum,
229		uint32_t ctxtReg, uint32_t ctxtRegVal, int verify);
230
231static void ixpnpe_intr(void *arg);
232
233static uint32_t
234npe_reg_read(struct ixpnpe_softc *sc, bus_size_t off)
235{
236	uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
237	DPRINTFn(9, sc->sc_dev, "%s(0x%lx) => 0x%x\n", __func__, off, v);
238	return v;
239}
240
241static void
242npe_reg_write(struct ixpnpe_softc *sc, bus_size_t off, uint32_t val)
243{
244	DPRINTFn(9, sc->sc_dev, "%s(0x%lx, 0x%x)\n", __func__, off, val);
245	bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
246}
247
248struct ixpnpe_softc *
249ixpnpe_attach(device_t dev, int npeid)
250{
251	struct npeconfig {
252		uint32_t	base;
253		uint32_t	size;
254		int		irq;
255		uint32_t	ins_memsize;
256		uint32_t	data_memsize;
257	};
258	static const struct npeconfig npeconfigs[NPE_MAX] = {
259		[NPE_A] = {
260		    .base = IXP425_NPE_A_HWBASE,
261		    .size = IXP425_NPE_A_SIZE,
262		    .irq = IXP425_INT_NPE_A,
263		    .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
264		    .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
265		},
266		[NPE_B] = {
267		    .base = IXP425_NPE_B_HWBASE,
268		    .size = IXP425_NPE_B_SIZE,
269		    .irq = IXP425_INT_NPE_B,
270		    .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
271		    .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
272		},
273		[NPE_C] = {
274		    .base = IXP425_NPE_C_HWBASE,
275		    .size = IXP425_NPE_C_SIZE,
276		    .irq = IXP425_INT_NPE_C,
277		    .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
278		    .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
279		},
280	};
281	struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
282	struct ixpnpe_softc *sc;
283	const struct npeconfig *config;
284	int rid;
285
286	if (npeid >= NPE_MAX) {
287		device_printf(dev, "%s: bad npeid %d\n", __func__, npeid);
288		return NULL;
289	}
290	sc = npes[npeid];
291	if (sc != NULL) {
292		sc->sc_nrefs++;
293		return sc;
294	}
295	config = &npeconfigs[npeid];
296
297	/* XXX M_BUS */
298	sc = malloc(sizeof(struct ixpnpe_softc), M_TEMP, M_WAITOK | M_ZERO);
299	sc->sc_dev = dev;
300	sc->sc_iot = sa->sc_iot;
301	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "npe driver", MTX_DEF);
302	sc->sc_npeid = npeid;
303	sc->sc_nrefs = 1;
304
305	sc->sc_size = config->size;
306	if (cpu_is_ixp42x()) {
307		/* NB: instruction/data memory sizes are NPE-dependent */
308		sc->insMemSize = config->ins_memsize;
309		sc->dataMemSize = config->data_memsize;
310	} else {
311		sc->insMemSize = IXP46X_NPEDL_INS_MEMSIZE_WORDS;
312		sc->dataMemSize = IXP46X_NPEDL_DATA_MEMSIZE_WORDS;
313	}
314
315	if (bus_space_map(sc->sc_iot, config->base, sc->sc_size, 0, &sc->sc_ioh))
316		panic("%s: Cannot map registers", device_get_name(dev));
317
318	/*
319	 * Setup IRQ and handler for NPE message support.
320	 */
321	rid = 0;
322	sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
323	    config->irq, config->irq, 1, RF_ACTIVE);
324	if (sc->sc_irq == NULL)
325		panic("%s: Unable to allocate irq %u", device_get_name(dev),
326		    config->irq);
327	/* XXX could be a source of entropy */
328	bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE,
329	    NULL, ixpnpe_intr, sc, &sc->sc_ih);
330	/*
331	 * Enable output fifo interrupts (NB: must also set OFIFO Write Enable)
332	 */
333	npe_reg_write(sc, IX_NPECTL,
334	    npe_reg_read(sc, IX_NPECTL) | (IX_NPECTL_OFE | IX_NPECTL_OFWE));
335
336	npes[npeid] = sc;
337
338	return sc;
339}
340
341void
342ixpnpe_detach(struct ixpnpe_softc *sc)
343{
344	if (--sc->sc_nrefs == 0) {
345		npes[sc->sc_npeid] = NULL;
346
347		/* disable output fifo interrupts */
348		npe_reg_write(sc, IX_NPECTL,
349		    npe_reg_read(sc, IX_NPECTL) &~ (IX_NPECTL_OFE | IX_NPECTL_OFWE));
350
351		bus_teardown_intr(sc->sc_dev, sc->sc_irq, sc->sc_ih);
352		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
353		mtx_destroy(&sc->sc_mtx);
354		free(sc, M_TEMP);
355	}
356}
357
358int
359ixpnpe_stopandreset(struct ixpnpe_softc *sc)
360{
361	int error;
362
363	mtx_lock(&sc->sc_mtx);
364	error = npe_cpu_stop(sc);		/* stop NPE */
365	if (error == 0)
366		error = npe_cpu_reset(sc);	/* reset it */
367	if (error == 0)
368		sc->started = 0;		/* mark stopped */
369	mtx_unlock(&sc->sc_mtx);
370
371	DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
372	return error;
373}
374
375static int
376ixpnpe_start_locked(struct ixpnpe_softc *sc)
377{
378	int error;
379
380	if (!sc->started) {
381		error = npe_cpu_start(sc);
382		if (error == 0)
383			sc->started = 1;
384	} else
385		error = 0;
386
387	DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
388	return error;
389}
390
391int
392ixpnpe_start(struct ixpnpe_softc *sc)
393{
394	int ret;
395
396	mtx_lock(&sc->sc_mtx);
397	ret = ixpnpe_start_locked(sc);
398	mtx_unlock(&sc->sc_mtx);
399	return (ret);
400}
401
402int
403ixpnpe_stop(struct ixpnpe_softc *sc)
404{
405	int error;
406
407	mtx_lock(&sc->sc_mtx);
408	error = npe_cpu_stop(sc);
409	if (error == 0)
410		sc->started = 0;
411	mtx_unlock(&sc->sc_mtx);
412
413	DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
414	return error;
415}
416
417/*
418 * Indicates the start of an NPE Image, in new NPE Image Library format.
419 * 2 consecutive occurrences indicates the end of the NPE Image Library
420 */
421#define NPE_IMAGE_MARKER 0xfeedf00d
422
423/*
424 * NPE Image Header definition, used in new NPE Image Library format
425 */
426typedef struct {
427	uint32_t marker;
428	uint32_t id;
429	uint32_t size;
430} IxNpeDlImageMgrImageHeader;
431
432static int
433npe_findimage(struct ixpnpe_softc *sc,
434    const uint32_t *imageLibrary, uint32_t imageId,
435    const uint32_t **imagePtr, uint32_t *imageSize)
436{
437	const IxNpeDlImageMgrImageHeader *image;
438	uint32_t offset = 0;
439
440	while (imageLibrary[offset] == NPE_IMAGE_MARKER) {
441		image = (const IxNpeDlImageMgrImageHeader *)
442		    &imageLibrary[offset];
443		offset += sizeof(IxNpeDlImageMgrImageHeader)/sizeof(uint32_t);
444
445		DPRINTF(sc->sc_dev, "%s: off %u mark 0x%x id 0x%x size %u\n",
446		    __func__, offset, image->marker, image->id, image->size);
447		if (image->id == imageId) {
448			*imagePtr = imageLibrary + offset;
449			*imageSize = image->size;
450			return 0;
451		}
452		/* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */
453		if (image->id == NPE_IMAGE_MARKER) {
454			DPRINTF(sc->sc_dev, "imageId 0x%08x not found in "
455			    "image library header\n", imageId);
456			/* reached end of library, image not found */
457			return ESRCH;
458		}
459		offset += image->size;
460	}
461	return ESRCH;
462}
463
464static int
465ixpnpe_load_firmware(struct ixpnpe_softc *sc, const char *imageName,
466    uint32_t imageId)
467{
468	static const char *devname[4] =
469	     { "IXP425", "IXP435/IXP465", "DeviceID#2", "DeviceID#3" };
470	uint32_t imageSize;
471	const uint32_t *imageCodePtr;
472	const struct firmware *fw;
473	int error;
474
475	DPRINTF(sc->sc_dev, "load %s, imageId 0x%08x\n", imageName, imageId);
476
477#if 0
478	IxFeatureCtrlDeviceId devid = IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId);
479	/*
480	 * Checking if image being loaded is meant for device that is running.
481	 * Image is forward compatible. i.e Image built for IXP42X should run
482	 * on IXP46X but not vice versa.
483	 */
484	if (devid > (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK))
485	    return EINVAL;
486#endif
487	error = ixpnpe_stopandreset(sc);		/* stop and reset the NPE */
488	if (error != 0)
489		return error;
490
491	fw = firmware_get(imageName);
492	if (fw == NULL)
493		return ENOENT;
494
495	/* Locate desired image in files w/ combined images */
496	error = npe_findimage(sc, fw->data, imageId, &imageCodePtr, &imageSize);
497	if (error != 0)
498		goto done;
499
500	device_printf(sc->sc_dev,
501	    "load fw image %s.NPE-%c Func 0x%x Rev %u.%u\n",
502	    devname[NPEIMAGE_DEVID(imageId)], 'A' + NPEIMAGE_NPEID(imageId),
503	    NPEIMAGE_FUNCID(imageId), NPEIMAGE_MAJOR(imageId),
504	    NPEIMAGE_MINOR(imageId));
505
506	/*
507	 * If download was successful, store image Id in list of
508	 * currently loaded images. If a critical error occurred
509	 * during download, record that the NPE has an invalid image
510	 */
511	mtx_lock(&sc->sc_mtx);
512	error = npe_load_image(sc, imageCodePtr, 1 /*VERIFY*/);
513	if (error == 0) {
514		sc->validImage = 1;
515		error = ixpnpe_start_locked(sc);
516	} else {
517		sc->validImage = 0;
518	}
519	sc->functionalityId = IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId);
520	mtx_unlock(&sc->sc_mtx);
521done:
522	firmware_put(fw, FIRMWARE_UNLOAD);
523	DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
524	return error;
525}
526
527static int
528override_imageid(device_t dev, const char *resname, uint32_t *val)
529{
530	int unit = device_get_unit(dev);
531	int resval;
532
533	if (resource_int_value("npe", unit, resname, &resval) != 0)
534		return 0;
535	/* XXX validate */
536	if (bootverbose)
537		device_printf(dev, "using npe.%d.%s=0x%x override\n",
538		    unit, resname, resval);
539	*val = resval;
540	return 1;
541}
542
543int
544ixpnpe_init(struct ixpnpe_softc *sc)
545{
546	static const uint32_t npeconfig[NPE_MAX] = {
547		[NPE_A] = IXP425_NPE_A_IMAGEID,
548		[NPE_B] = IXP425_NPE_B_IMAGEID,
549		[NPE_C] = IXP425_NPE_C_IMAGEID,
550	};
551	uint32_t imageid, msg[2];
552	int error;
553
554	if (sc->started)
555		return 0;
556	/*
557	 * Load NPE firmware and start it running.  We assume
558	 * that minor version bumps remain compatible so probe
559	 * the firmware image starting with the expected version
560	 * and then bump the minor version up to the max.
561	 */
562	if (!override_imageid(sc->sc_dev, "imageid", &imageid))
563		imageid = npeconfig[sc->sc_npeid];
564	for (;;) {
565		error = ixpnpe_load_firmware(sc, "npe_fw", imageid);
566		if (error == 0)
567			break;
568		/*
569		 * ESRCH is returned when the requested image
570		 * is not present
571		 */
572		if (error != ESRCH) {
573			device_printf(sc->sc_dev,
574			    "cannot init NPE (error %d)\n", error);
575			return error;
576		}
577		/* bump the minor version up to the max possible */
578		if (NPEIMAGE_MINOR(imageid) == 0xff) {
579			device_printf(sc->sc_dev, "cannot locate firmware "
580			    "(imageid 0x%08x)\n", imageid);
581			return error;
582		}
583		imageid++;
584	}
585	/* NB: firmware should respond with a status msg */
586	if (ixpnpe_recvmsg_sync(sc, msg) != 0) {
587		device_printf(sc->sc_dev,
588		    "firmware did not respond as expected\n");
589		return EIO;
590	}
591	return 0;
592}
593
594int
595ixpnpe_getfunctionality(struct ixpnpe_softc *sc)
596{
597	return (sc->validImage ? sc->functionalityId : 0);
598}
599
600static int
601npe_checkbits(struct ixpnpe_softc *sc, uint32_t reg, uint32_t expectedBitsSet)
602{
603	uint32_t val;
604
605	val = npe_reg_read(sc, reg);
606	DPRINTFn(5, sc->sc_dev, "%s(0x%x, 0x%x) => 0x%x (%u)\n",
607	    __func__, reg, expectedBitsSet, val,
608	    (val & expectedBitsSet) == expectedBitsSet);
609	return ((val & expectedBitsSet) == expectedBitsSet);
610}
611
612static int
613npe_isstopped(struct ixpnpe_softc *sc)
614{
615	return npe_checkbits(sc,
616	    IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP);
617}
618
619static int
620npe_load_ins(struct ixpnpe_softc *sc,
621    const IxNpeDlNpeMgrCodeBlock *bp, int verify)
622{
623	uint32_t npeMemAddress;
624	int i, blockSize;
625
626	npeMemAddress = bp->npeMemAddress;
627	blockSize = bp->size;		/* NB: instruction/data count */
628	if (npeMemAddress + blockSize > sc->insMemSize) {
629		device_printf(sc->sc_dev,
630		    "Block size %u too big for NPE memory\n", blockSize);
631		return EINVAL;	/* XXX */
632	}
633	for (i = 0; i < blockSize; i++, npeMemAddress++) {
634		if (npe_ins_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
635			device_printf(sc->sc_dev,
636			    "NPE instruction write failed");
637			return EIO;
638		}
639	}
640	return 0;
641}
642
643static int
644npe_load_data(struct ixpnpe_softc *sc,
645    const IxNpeDlNpeMgrCodeBlock *bp, int verify)
646{
647	uint32_t npeMemAddress;
648	int i, blockSize;
649
650	npeMemAddress = bp->npeMemAddress;
651	blockSize = bp->size;		/* NB: instruction/data count */
652	if (npeMemAddress + blockSize > sc->dataMemSize) {
653		device_printf(sc->sc_dev,
654		    "Block size %u too big for NPE memory\n", blockSize);
655		return EINVAL;
656	}
657	for (i = 0; i < blockSize; i++, npeMemAddress++) {
658		if (npe_data_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
659			device_printf(sc->sc_dev, "NPE data write failed\n");
660			return EIO;
661		}
662	}
663	return 0;
664}
665
666static int
667npe_load_stateinfo(struct ixpnpe_softc *sc,
668    const IxNpeDlNpeMgrStateInfoBlock *bp, int verify)
669{
670	int i, nentries, error;
671
672	npe_cpu_step_save(sc);
673
674	/* for each state-info context register entry in block */
675	nentries = bp->size / IX_NPEDL_STATE_INFO_ENTRY_SIZE;
676	error = 0;
677	for (i = 0; i < nentries; i++) {
678		/* each state-info entry is 2 words (address, value) */
679		uint32_t regVal = bp->ctxtRegEntry[i].value;
680		uint32_t addrInfo = bp->ctxtRegEntry[i].addressInfo;
681
682		uint32_t reg = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
683		uint32_t cNum = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
684		    IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
685
686		/* error-check Context Register No. and Context Number values */
687		if (!(0 <= reg && reg < IX_NPEDL_CTXT_REG_MAX)) {
688			device_printf(sc->sc_dev,
689			    "invalid Context Register %u\n", reg);
690			error = EINVAL;
691			break;
692		}
693		if (!(0 <= cNum && cNum < IX_NPEDL_CTXT_NUM_MAX)) {
694			device_printf(sc->sc_dev,
695			    "invalid Context Number %u\n", cNum);
696			error = EINVAL;
697			break;
698		}
699		/* NOTE that there is no STEVT register for Context 0 */
700		if (cNum == 0 && reg == IX_NPEDL_CTXT_REG_STEVT) {
701			device_printf(sc->sc_dev,
702			    "no STEVT for Context 0\n");
703			error = EINVAL;
704			break;
705		}
706
707		if (npe_ctx_reg_write(sc, cNum, reg, regVal, verify) != 0) {
708			device_printf(sc->sc_dev,
709			    "write of state-info to NPE failed\n");
710			error = EIO;
711			break;
712		}
713	}
714
715	npe_cpu_step_restore(sc);
716	return error;
717}
718
719static int
720npe_load_image(struct ixpnpe_softc *sc,
721    const uint32_t *imageCodePtr, int verify)
722{
723#define	EOM(marker)	((marker) == IX_NPEDL_END_OF_DOWNLOAD_MAP)
724	const IxNpeDlNpeMgrDownloadMap *downloadMap;
725	int i, error;
726
727	if (!npe_isstopped(sc)) {		/* verify NPE is stopped */
728		device_printf(sc->sc_dev,
729		    "cannot load image, NPE not stopped\n");
730		return EIO;
731	}
732
733	/*
734	 * Read Download Map, checking each block type and calling
735	 * appropriate function to perform download
736	 */
737	error = 0;
738	downloadMap = (const IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
739	for (i = 0; !EOM(downloadMap->entry[i].eodmMarker); i++) {
740		/* calculate pointer to block to be downloaded */
741		const uint32_t *bp = imageCodePtr +
742		    downloadMap->entry[i].block.offset;
743		switch (downloadMap->entry[i].block.type) {
744		case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
745			error = npe_load_ins(sc,
746			    (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
747			DPRINTF(sc->sc_dev, "%s: inst, error %d\n",
748			    __func__, error);
749			break;
750		case IX_NPEDL_BLOCK_TYPE_DATA:
751			error = npe_load_data(sc,
752			    (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
753			DPRINTF(sc->sc_dev, "%s: data, error %d\n",
754			    __func__, error);
755			break;
756		case IX_NPEDL_BLOCK_TYPE_STATE:
757		    error = npe_load_stateinfo(sc,
758			(const IxNpeDlNpeMgrStateInfoBlock *) bp, verify);
759			DPRINTF(sc->sc_dev, "%s: state, error %d\n",
760			    __func__, error);
761			break;
762		default:
763			device_printf(sc->sc_dev,
764			    "unknown block type 0x%x in download map\n",
765			    downloadMap->entry[i].block.type);
766			error = EIO;		/* XXX */
767			break;
768		}
769		if (error != 0)
770			break;
771	}
772	return error;
773#undef EOM
774}
775
776/* contains Reset values for Context Store Registers  */
777static const struct {
778	uint32_t regAddr;
779	uint32_t regResetVal;
780} ixNpeDlEcsRegResetValues[] = {
781	{ IX_NPEDL_ECS_BG_CTXT_REG_0,    IX_NPEDL_ECS_BG_CTXT_REG_0_RESET },
782	{ IX_NPEDL_ECS_BG_CTXT_REG_1,    IX_NPEDL_ECS_BG_CTXT_REG_1_RESET },
783	{ IX_NPEDL_ECS_BG_CTXT_REG_2,    IX_NPEDL_ECS_BG_CTXT_REG_2_RESET },
784	{ IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET },
785	{ IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET },
786	{ IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET },
787	{ IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET },
788	{ IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET },
789	{ IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET },
790	{ IX_NPEDL_ECS_DBG_CTXT_REG_0,   IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET },
791	{ IX_NPEDL_ECS_DBG_CTXT_REG_1,   IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET },
792	{ IX_NPEDL_ECS_DBG_CTXT_REG_2,   IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET },
793	{ IX_NPEDL_ECS_INSTRUCT_REG,     IX_NPEDL_ECS_INSTRUCT_REG_RESET }
794};
795
796/* contains Reset values for Context Store Registers  */
797static const uint32_t ixNpeDlCtxtRegResetValues[] = {
798	IX_NPEDL_CTXT_REG_RESET_STEVT,
799	IX_NPEDL_CTXT_REG_RESET_STARTPC,
800	IX_NPEDL_CTXT_REG_RESET_REGMAP,
801	IX_NPEDL_CTXT_REG_RESET_CINDEX,
802};
803
804#define	IX_NPEDL_PARITY_BIT_MASK	0x3F00FFFF
805#define	IX_NPEDL_CONFIG_CTRL_REG_MASK	0x3F3FFFFF
806
807#if 0
808/*
809 * Reset the NPE and its coprocessor using the
810 * fuse bits in the feature control register.
811 */
812static void
813npe_reset(int npeid)
814{
815	uint32_t mask = EXP_FCTRL_NPEA << npeid;
816	uint32_t v;
817
818	v = ixp4xx_read_feature_bits();
819	ixp4xx_write_feature_bits(v &~ mask);
820	/* un-fuse and un-reset the NPE & coprocessor */
821	ixp4xx_write_feature_bits(v | mask);
822}
823#endif
824
825static int
826npe_cpu_reset(struct ixpnpe_softc *sc)
827{
828#define	N(a)	(sizeof(a) / sizeof(a[0]))
829	uint32_t ctxtReg; /* identifies Context Store reg (0-3) */
830	uint32_t regAddr;
831	uint32_t regVal;
832	uint32_t ixNpeConfigCtrlRegVal;
833	int i, error = 0;
834
835	/* pre-store the NPE Config Control Register Value */
836	ixNpeConfigCtrlRegVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL);
837	ixNpeConfigCtrlRegVal |= 0x3F000000;
838
839	/* disable the parity interrupt */
840	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
841	    (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
842	DPRINTFn(2, sc->sc_dev, "%s: dis parity int, CTL => 0x%x\n",
843	    __func__, ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK);
844
845	npe_cpu_step_save(sc);
846
847	/*
848	 * Clear the FIFOs.
849	 */
850	while (npe_checkbits(sc,
851	      IX_NPEDL_REG_OFFSET_WFIFO, IX_NPEDL_MASK_WFIFO_VALID)) {
852		/* read from the Watch-point FIFO until empty */
853		(void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WFIFO);
854	}
855
856	while (npe_checkbits(sc,
857	      IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_OFNE)) {
858		/* read from the outFIFO until empty */
859		(void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_FIFO);
860	}
861
862	while (npe_checkbits(sc,
863	      IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) {
864		/*
865		 * Step execution of the NPE instruction to read inFIFO using
866		 * the Debug Executing Context stack.
867		 */
868		error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0);
869		if (error != 0) {
870			DPRINTF(sc->sc_dev, "%s: cannot step (1), error %u\n",
871			    __func__, error);
872			npe_cpu_step_restore(sc);
873			return error;
874		}
875	}
876
877	/*
878	 * Reset the mailbox reg
879	 */
880	/* ...from XScale side */
881	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_MBST, IX_NPEDL_REG_RESET_MBST);
882	/* ...from NPE side */
883	error = npe_cpu_step(sc, IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
884	if (error != 0) {
885		DPRINTF(sc->sc_dev, "%s: cannot step (2), error %u\n",
886		    __func__, error);
887		npe_cpu_step_restore(sc);
888		return error;
889	}
890
891	/*
892	 * Reset the physical registers in the NPE register file:
893	 * Note: no need to save/restore REGMAP for Context 0 here
894	 * since all Context Store regs are reset in subsequent code.
895	 */
896	for (regAddr = 0;
897	     regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG && error == 0;
898	     regAddr++) {
899		/* for each physical register in the NPE reg file, write 0 : */
900		error = npe_physical_reg_write(sc, regAddr, 0, TRUE);
901		if (error != 0) {
902			DPRINTF(sc->sc_dev, "%s: cannot write phy reg,"
903			    "error %u\n", __func__, error);
904			npe_cpu_step_restore(sc);
905			return error;		/* abort reset */
906		}
907	}
908
909	/*
910	 * Reset the context store:
911	 */
912	for (i = IX_NPEDL_CTXT_NUM_MIN; i <= IX_NPEDL_CTXT_NUM_MAX; i++) {
913		/* set each context's Context Store registers to reset values */
914		for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) {
915			/* NOTE that there is no STEVT register for Context 0 */
916			if (i == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STEVT)
917				continue;
918			regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
919			error = npe_ctx_reg_write(sc, i, ctxtReg,
920			    regVal, TRUE);
921			if (error != 0) {
922				DPRINTF(sc->sc_dev, "%s: cannot write ctx reg,"
923				    "error %u\n", __func__, error);
924				npe_cpu_step_restore(sc);
925				return error;	 /* abort reset */
926			}
927		}
928	}
929
930	npe_cpu_step_restore(sc);
931
932	/* write Reset values to Execution Context Stack registers */
933	for (i = 0; i < N(ixNpeDlEcsRegResetValues); i++)
934		npe_ecs_reg_write(sc,
935		    ixNpeDlEcsRegResetValues[i].regAddr,
936		    ixNpeDlEcsRegResetValues[i].regResetVal);
937
938	/* clear the profile counter */
939	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
940
941	/* clear registers EXCT, AP0, AP1, AP2 and AP3 */
942	for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
943	     regAddr <= IX_NPEDL_REG_OFFSET_AP3;
944	     regAddr += sizeof(uint32_t))
945		npe_reg_write(sc, regAddr, 0);
946
947	/* Reset the Watch-count register */
948	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_WC, 0);
949#if 0
950	/*
951	 * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
952	 * XXX Removed because it breaks IXP435 operation; e.g. on Gateworks
953	 * XXX 2358 boards reseting NPE-A after NPE-C is running causes both
954	 * XXX npe's to stop working
955	 */
956	npe_reset(sc->sc_npeid);
957#endif
958	/*
959	 * Call NpeMgr function to stop the NPE again after the Feature Control
960	 * has unfused and Un-Reset the NPE and its associated Coprocessors.
961	 */
962	error = npe_cpu_stop(sc);
963
964	/* restore NPE configuration bus Control Register - Parity Settings  */
965	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
966	    (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
967	DPRINTFn(2, sc->sc_dev, "%s: restore CTL => 0x%x\n",
968	    __func__, npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL));
969
970	return error;
971#undef N
972}
973
974static int
975npe_cpu_start(struct ixpnpe_softc *sc)
976{
977	uint32_t ecsRegVal;
978
979	/*
980	 * Ensure only Background Context Stack Level is Active by turning off
981	 * the Active bit in each of the other Executing Context Stack levels.
982	 */
983	ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
984	ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
985	npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, ecsRegVal);
986
987	ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
988	ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
989	npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, ecsRegVal);
990
991	ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0);
992	ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
993	npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsRegVal);
994
995	/* clear the pipeline */
996	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
997
998	/* start NPE execution by issuing cmd through EXCTL register on NPE */
999	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_START);
1000
1001	/*
1002	 * Check execution status of NPE to verify operation was successful.
1003	 */
1004	return npe_checkbits(sc,
1005	    IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_RUN) ? 0 : EIO;
1006}
1007
1008static int
1009npe_cpu_stop(struct ixpnpe_softc *sc)
1010{
1011	/* stop NPE execution by issuing cmd through EXCTL register on NPE */
1012	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STOP);
1013
1014	/* verify that NPE Stop was successful */
1015	return npe_checkbits(sc,
1016	    IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP) ? 0 : EIO;
1017}
1018
1019#define IX_NPEDL_REG_SIZE_BYTE            8
1020#define IX_NPEDL_REG_SIZE_SHORT           16
1021#define IX_NPEDL_REG_SIZE_WORD            32
1022
1023/*
1024 * Introduce extra read cycles after issuing read command to NPE
1025 * so that we read the register after the NPE has updated it
1026 * This is to overcome race condition between XScale and NPE
1027 */
1028#define IX_NPEDL_DELAY_READ_CYCLES        2
1029/*
1030 * To mask top three MSBs of 32bit word to download into NPE IMEM
1031 */
1032#define IX_NPEDL_MASK_UNUSED_IMEM_BITS    0x1FFFFFFF;
1033
1034static void
1035npe_cmd_issue_write(struct ixpnpe_softc *sc,
1036    uint32_t cmd, uint32_t addr, uint32_t data)
1037{
1038	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, data);
1039	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
1040	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
1041}
1042
1043static uint32_t
1044npe_cmd_issue_read(struct ixpnpe_softc *sc, uint32_t cmd, uint32_t addr)
1045{
1046	uint32_t data;
1047	int i;
1048
1049	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
1050	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
1051	for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++)
1052		data = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
1053	return data;
1054}
1055
1056static int
1057npe_ins_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
1058{
1059	DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
1060	npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_INS_MEM, addr, data);
1061	if (verify) {
1062		uint32_t rdata;
1063
1064		/*
1065		 * Write invalid data to this reg, so we can see if we're
1066		 * reading the EXDATA register too early.
1067		 */
1068		npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
1069
1070		/*
1071		 * Disabled since top 3 MSB are not used for Azusa
1072		 * hardware Refer WR:IXA00053900
1073		 */
1074		data &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
1075
1076		rdata = npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_INS_MEM,
1077		    addr);
1078		rdata &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
1079
1080		if (data != rdata)
1081			return EIO;
1082	}
1083	return 0;
1084}
1085
1086static int
1087npe_data_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
1088{
1089	DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
1090	npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM, addr, data);
1091	if (verify) {
1092		/*
1093		 * Write invalid data to this reg, so we can see if we're
1094		 * reading the EXDATA register too early.
1095		 */
1096		npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
1097		if (data != npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM, addr))
1098			return EIO;
1099	}
1100	return 0;
1101}
1102
1103static void
1104npe_ecs_reg_write(struct ixpnpe_softc *sc, uint32_t reg, uint32_t data)
1105{
1106	npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_ECS_REG, reg, data);
1107}
1108
1109static uint32_t
1110npe_ecs_reg_read(struct ixpnpe_softc *sc, uint32_t reg)
1111{
1112	return npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_ECS_REG, reg);
1113}
1114
1115static void
1116npe_issue_cmd(struct ixpnpe_softc *sc, uint32_t command)
1117{
1118	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, command);
1119}
1120
1121static void
1122npe_cpu_step_save(struct ixpnpe_softc *sc)
1123{
1124	/* turn off the halt bit by clearing Execution Count register. */
1125	/* save reg contents 1st and restore later */
1126	sc->savedExecCount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXCT);
1127	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, 0);
1128
1129	/* ensure that IF and IE are on (temporarily), so that we don't end up
1130	 * stepping forever */
1131	sc->savedEcsDbgCtxtReg2 = npe_ecs_reg_read(sc,
1132	    IX_NPEDL_ECS_DBG_CTXT_REG_2);
1133
1134	npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2,
1135	    (sc->savedEcsDbgCtxtReg2 | IX_NPEDL_MASK_ECS_DBG_REG_2_IF |
1136	     IX_NPEDL_MASK_ECS_DBG_REG_2_IE));
1137}
1138
1139static int
1140npe_cpu_step(struct ixpnpe_softc *sc, uint32_t npeInstruction,
1141    uint32_t ctxtNum, uint32_t ldur)
1142{
1143#define	IX_NPE_DL_MAX_NUM_OF_RETRIES	1000000
1144	uint32_t ecsDbgRegVal;
1145	uint32_t oldWatchcount, newWatchcount;
1146	int tries;
1147
1148	/* set the Active bit, and the LDUR, in the debug level */
1149	ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE |
1150	    (ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR);
1151
1152	npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsDbgRegVal);
1153
1154	/*
1155	 * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the
1156	 * instruction, and set SELCTXT at ECS DEBUG Level to specify which
1157	 * context store to access.
1158	 * Debug ECS Level Reg 1 has form  0x000n000n, where n = context number
1159	 */
1160	ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) |
1161	    (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT);
1162
1163	npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_1, ecsDbgRegVal);
1164
1165	/* clear the pipeline */
1166	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
1167
1168	/* load NPE instruction into the instruction register */
1169	npe_ecs_reg_write(sc, IX_NPEDL_ECS_INSTRUCT_REG, npeInstruction);
1170
1171	/* need this value later to wait for completion of NPE execution step */
1172	oldWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1173
1174	/* issue a Step One command via the Execution Control register */
1175	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STEP);
1176
1177	/*
1178	 * Force the XScale to wait until the NPE has finished execution step
1179	 * NOTE that this delay will be very small, just long enough to allow a
1180	 * single NPE instruction to complete execution; if instruction
1181	 * execution is not completed before timeout retries, exit the while
1182	 * loop.
1183	 */
1184	newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1185	for (tries = 0; tries < IX_NPE_DL_MAX_NUM_OF_RETRIES &&
1186	    newWatchcount == oldWatchcount; tries++) {
1187		/* Watch Count register incr's when NPE completes an inst */
1188		newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1189	}
1190	return (tries < IX_NPE_DL_MAX_NUM_OF_RETRIES) ? 0 : EIO;
1191#undef IX_NPE_DL_MAX_NUM_OF_RETRIES
1192}
1193
1194static void
1195npe_cpu_step_restore(struct ixpnpe_softc *sc)
1196{
1197	/* clear active bit in debug level */
1198	npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, 0);
1199
1200	/* clear the pipeline */
1201	npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
1202
1203	/* restore Execution Count register contents. */
1204	npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, sc->savedExecCount);
1205
1206	/* restore IF and IE bits to original values */
1207	npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, sc->savedEcsDbgCtxtReg2);
1208}
1209
1210static int
1211npe_logical_reg_read(struct ixpnpe_softc *sc,
1212    uint32_t regAddr, uint32_t regSize,
1213    uint32_t ctxtNum, uint32_t *regVal)
1214{
1215	uint32_t npeInstruction, mask;
1216	int error;
1217
1218	switch (regSize) {
1219	case IX_NPEDL_REG_SIZE_BYTE:
1220		npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE;
1221		mask = 0xff;
1222		break;
1223	case IX_NPEDL_REG_SIZE_SHORT:
1224		npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT;
1225		mask = 0xffff;
1226		break;
1227	case IX_NPEDL_REG_SIZE_WORD:
1228		npeInstruction = IX_NPEDL_INSTR_RD_REG_WORD;
1229		mask = 0xffffffff;
1230		break;
1231	default:
1232		return EINVAL;
1233	}
1234
1235	/* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */
1236	npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_SRC) |
1237	    (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
1238
1239	/* step execution of NPE inst using Debug Executing Context stack */
1240	error = npe_cpu_step(sc, npeInstruction, ctxtNum,
1241	    IX_NPEDL_RD_INSTR_LDUR);
1242	if (error != 0) {
1243		DPRINTF(sc->sc_dev, "%s(0x%x, %u, %u), cannot step, error %d\n",
1244		    __func__, regAddr, regSize, ctxtNum, error);
1245		return error;
1246	}
1247	/* read value of register from Execution Data register */
1248	*regVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
1249
1250	/* align value from left to right */
1251	*regVal = (*regVal >> (IX_NPEDL_REG_SIZE_WORD - regSize)) & mask;
1252
1253	return 0;
1254}
1255
1256static int
1257npe_logical_reg_write(struct ixpnpe_softc *sc, uint32_t regAddr, uint32_t regVal,
1258    uint32_t regSize, uint32_t ctxtNum, int verify)
1259{
1260	int error;
1261
1262	DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x, %u, %u)\n",
1263	    __func__, regAddr, regVal, regSize, ctxtNum);
1264	if (regSize == IX_NPEDL_REG_SIZE_WORD) {
1265		/*
1266		 * NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3|
1267		 * Write upper half-word (short) to |d0|d1|
1268		 */
1269		error = npe_logical_reg_write(sc, regAddr,
1270			     regVal >> IX_NPEDL_REG_SIZE_SHORT,
1271			     IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify);
1272		if (error != 0)
1273		    return error;
1274
1275		/* Write lower half-word (short) to |d2|d3| */
1276		error = npe_logical_reg_write(sc,
1277			     regAddr + sizeof(uint16_t),
1278			     regVal & 0xffff,
1279			     IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify);
1280	} else {
1281		uint32_t npeInstruction;
1282
1283		switch (regSize) {
1284		case IX_NPEDL_REG_SIZE_BYTE:
1285			npeInstruction = IX_NPEDL_INSTR_WR_REG_BYTE;
1286			regVal &= 0xff;
1287			break;
1288		case IX_NPEDL_REG_SIZE_SHORT:
1289			npeInstruction = IX_NPEDL_INSTR_WR_REG_SHORT;
1290			regVal &= 0xffff;
1291			break;
1292		default:
1293			return EINVAL;
1294		}
1295		/* fill dest operand field of inst with dest reg addr */
1296		npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
1297
1298		/* fill src operand field of inst with least-sig 5 bits of val*/
1299		npeInstruction |=
1300		    ((regVal & IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA) <<
1301		     IX_NPEDL_OFFSET_INSTR_SRC);
1302
1303		/* fill coprocessor field of inst with most-sig 11 bits of val*/
1304		npeInstruction |=
1305		    ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) <<
1306		     IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA);
1307
1308		/* step execution of NPE instruction using Debug ECS */
1309		error = npe_cpu_step(sc, npeInstruction,
1310		    ctxtNum, IX_NPEDL_WR_INSTR_LDUR);
1311	}
1312	if (error != 0) {
1313		DPRINTF(sc->sc_dev, "%s(0x%x, 0x%x, %u, %u), error %u "
1314		    "writing reg\n", __func__, regAddr, regVal, regSize,
1315		    ctxtNum, error);
1316		return error;
1317	}
1318	if (verify) {
1319		uint32_t retRegVal;
1320
1321		error = npe_logical_reg_read(sc, regAddr, regSize, ctxtNum,
1322		    &retRegVal);
1323		if (error == 0 && regVal != retRegVal)
1324			error = EIO;	/* XXX ambiguous */
1325	}
1326	return error;
1327}
1328
1329/*
1330 * There are 32 physical registers used in an NPE.  These are
1331 * treated as 16 pairs of 32-bit registers.  To write one of the pair,
1332 * write the pair number (0-16) to the REGMAP for Context 0.  Then write
1333 * the value to register  0 or 4 in the regfile, depending on which
1334 * register of the pair is to be written
1335 */
1336static int
1337npe_physical_reg_write(struct ixpnpe_softc *sc,
1338    uint32_t regAddr, uint32_t regValue, int verify)
1339{
1340	int error;
1341
1342	/*
1343	 * Set REGMAP for context 0 to (regAddr >> 1) to choose which pair
1344	 * (0-16) of physical registers to write .
1345	 */
1346	error = npe_logical_reg_write(sc, IX_NPEDL_CTXT_REG_ADDR_REGMAP,
1347		   (regAddr >> IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP),
1348		   IX_NPEDL_REG_SIZE_SHORT, 0, verify);
1349	if (error == 0) {
1350	    /* regAddr = 0 or 4  */
1351	    regAddr = (regAddr & IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR) *
1352		sizeof(uint32_t);
1353	    error = npe_logical_reg_write(sc, regAddr, regValue,
1354		IX_NPEDL_REG_SIZE_WORD, 0, verify);
1355	}
1356	return error;
1357}
1358
1359static int
1360npe_ctx_reg_write(struct ixpnpe_softc *sc, uint32_t ctxtNum,
1361    uint32_t ctxtReg, uint32_t ctxtRegVal, int verify)
1362{
1363	DPRINTFn(4, sc->sc_dev, "%s(%u, %u, %u)\n",
1364	    __func__, ctxtNum, ctxtReg, ctxtRegVal);
1365	/*
1366	 * Context 0 has no STARTPC. Instead, this value is used to set
1367	 * NextPC for Background ECS, to set where NPE starts executing code
1368	 */
1369	if (ctxtNum == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STARTPC) {
1370		/* read BG_CTXT_REG_0, update NEXTPC bits, & write back to reg*/
1371		uint32_t v = npe_ecs_reg_read(sc, IX_NPEDL_ECS_BG_CTXT_REG_0);
1372		v &= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
1373		v |= (ctxtRegVal << IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC) &
1374		    IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
1375
1376		npe_ecs_reg_write(sc, IX_NPEDL_ECS_BG_CTXT_REG_0, v);
1377		return 0;
1378	} else {
1379		static const struct {
1380			uint32_t regAddress;
1381			uint32_t regSize;
1382		} regAccInfo[IX_NPEDL_CTXT_REG_MAX] = {
1383			{ IX_NPEDL_CTXT_REG_ADDR_STEVT,
1384			  IX_NPEDL_REG_SIZE_BYTE },
1385			{ IX_NPEDL_CTXT_REG_ADDR_STARTPC,
1386			  IX_NPEDL_REG_SIZE_SHORT },
1387			{ IX_NPEDL_CTXT_REG_ADDR_REGMAP,
1388			  IX_NPEDL_REG_SIZE_SHORT },
1389			{ IX_NPEDL_CTXT_REG_ADDR_CINDEX,
1390			  IX_NPEDL_REG_SIZE_BYTE }
1391		};
1392		return npe_logical_reg_write(sc, regAccInfo[ctxtReg].regAddress,
1393			ctxtRegVal, regAccInfo[ctxtReg].regSize, ctxtNum, verify);
1394	}
1395}
1396
1397/*
1398 * NPE Mailbox support.
1399 */
1400#define	IX_NPEMH_MAXTRIES	100000
1401
1402static int
1403ofifo_wait(struct ixpnpe_softc *sc)
1404{
1405	int i;
1406
1407	for (i = 0; i < IX_NPEMH_MAXTRIES; i++) {
1408		if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_OFNE)
1409			return 1;
1410		DELAY(10);
1411	}
1412	device_printf(sc->sc_dev, "%s: timeout, last status 0x%x\n",
1413	    __func__, npe_reg_read(sc, IX_NPESTAT));
1414	return 0;
1415}
1416
1417static int
1418getmsg(struct ixpnpe_softc *sc, uint32_t msg[2])
1419{
1420	mtx_assert(&sc->sc_mtx, MA_OWNED);
1421
1422	if (!ofifo_wait(sc))
1423		return EAGAIN;
1424	msg[0] = npe_reg_read(sc, IX_NPEFIFO);
1425	DPRINTF(sc->sc_dev, "%s: msg0 0x%x\n", __func__, msg[0]);
1426	if (!ofifo_wait(sc))
1427		return EAGAIN;
1428	msg[1] = npe_reg_read(sc, IX_NPEFIFO);
1429	DPRINTF(sc->sc_dev, "%s: msg1 0x%x\n", __func__, msg[1]);
1430	return 0;
1431}
1432
1433static void
1434ixpnpe_intr(void *arg)
1435{
1436	struct ixpnpe_softc *sc = arg;
1437	uint32_t status;
1438
1439	mtx_lock(&sc->sc_mtx);
1440	status = npe_reg_read(sc, IX_NPESTAT);
1441	DPRINTF(sc->sc_dev, "%s: status 0x%x\n", __func__, status);
1442	if ((status & IX_NPESTAT_OFINT) == 0) {
1443		/* NB: should not happen */
1444		device_printf(sc->sc_dev, "%s: status 0x%x\n",
1445		    __func__, status);
1446		/* XXX must silence interrupt? */
1447		mtx_unlock(&sc->sc_mtx);
1448		return;
1449	}
1450	/*
1451	 * A message is waiting in the output FIFO, copy it so
1452	 * the interrupt will be silenced.
1453	 */
1454	if (getmsg(sc, sc->sc_msg) == 0)
1455		sc->sc_msgwaiting = 1;
1456	mtx_unlock(&sc->sc_mtx);
1457}
1458
1459static int
1460ififo_wait(struct ixpnpe_softc *sc)
1461{
1462	int i;
1463
1464	for (i = 0; i < IX_NPEMH_MAXTRIES; i++) {
1465		if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_IFNF)
1466			return 1;
1467		DELAY(10);
1468	}
1469	device_printf(sc->sc_dev, "%s: timeout, last status 0x%x\n",
1470	    __func__, npe_reg_read(sc, IX_NPESTAT));
1471	return 0;
1472}
1473
1474static int
1475putmsg(struct ixpnpe_softc *sc, const uint32_t msg[2])
1476{
1477	mtx_assert(&sc->sc_mtx, MA_OWNED);
1478
1479	DPRINTF(sc->sc_dev, "%s: msg 0x%x:0x%x\n", __func__, msg[0], msg[1]);
1480	if (!ififo_wait(sc))
1481		return EIO;
1482	npe_reg_write(sc, IX_NPEFIFO, msg[0]);
1483	if (!ififo_wait(sc))
1484		return EIO;
1485	npe_reg_write(sc, IX_NPEFIFO, msg[1]);
1486
1487	return 0;
1488}
1489
1490/*
1491 * Send a msg to the NPE and wait for a reply.  We spin as
1492 * we may be called early with interrupts not properly setup.
1493 */
1494int
1495ixpnpe_sendandrecvmsg_sync(struct ixpnpe_softc *sc,
1496	const uint32_t send[2], uint32_t recv[2])
1497{
1498	int error;
1499
1500	mtx_lock(&sc->sc_mtx);
1501	error = putmsg(sc, send);
1502	if (error == 0)
1503		error = getmsg(sc, recv);
1504	mtx_unlock(&sc->sc_mtx);
1505
1506	return error;
1507}
1508
1509/*
1510 * Send a msg to the NPE w/o waiting for a reply.
1511 */
1512int
1513ixpnpe_sendmsg_async(struct ixpnpe_softc *sc, const uint32_t msg[2])
1514{
1515	int error;
1516
1517	mtx_lock(&sc->sc_mtx);
1518	error = putmsg(sc, msg);
1519	mtx_unlock(&sc->sc_mtx);
1520
1521	return error;
1522}
1523
1524static int
1525recvmsg_locked(struct ixpnpe_softc *sc, uint32_t msg[2])
1526{
1527	mtx_assert(&sc->sc_mtx, MA_OWNED);
1528
1529	DPRINTF(sc->sc_dev, "%s: msgwaiting %d\n", __func__, sc->sc_msgwaiting);
1530	if (sc->sc_msgwaiting) {
1531		msg[0] = sc->sc_msg[0];
1532		msg[1] = sc->sc_msg[1];
1533		sc->sc_msgwaiting = 0;
1534		return 0;
1535	}
1536	return EAGAIN;
1537}
1538
1539/*
1540 * Receive any msg previously received from the NPE. If nothing
1541 * is available we return EAGAIN and the caller is required to
1542 * do a synchronous receive or try again later.
1543 */
1544int
1545ixpnpe_recvmsg_async(struct ixpnpe_softc *sc, uint32_t msg[2])
1546{
1547	int error;
1548
1549	mtx_lock(&sc->sc_mtx);
1550	error = recvmsg_locked(sc, msg);
1551	mtx_unlock(&sc->sc_mtx);
1552
1553	return error;
1554}
1555
1556/*
1557 * Receive a msg from the NPE.  If one was received asynchronously
1558 * then it's returned; otherwise we poll synchronously.
1559 */
1560int
1561ixpnpe_recvmsg_sync(struct ixpnpe_softc *sc, uint32_t msg[2])
1562{
1563	int error;
1564
1565	mtx_lock(&sc->sc_mtx);
1566	error = recvmsg_locked(sc, msg);
1567	if (error == EAGAIN)
1568		error = getmsg(sc, msg);
1569	mtx_unlock(&sc->sc_mtx);
1570
1571	return error;
1572}
1573