Sat Jun 17 11:57:49 2023 UTC ()
Rework microcode for IXP425 npe(4).

Instead of using objcopy(1), which cannot handle EABI version
embedded in e_flags of ELF header, add a dedicated asm file.

If proprietary microcode binary is present, it is incbin'ed
from that asm file.


(rin)
diff -r1.12 -r1.13 src/sys/arch/arm/xscale/files.ixp425
diff -r1.2 -r1.3 src/sys/arch/arm/xscale/ixp425-fw.mk
diff -r1.16 -r1.17 src/sys/arch/arm/xscale/ixp425_npe.c
diff -r0 -r1.1 src/sys/arch/arm/xscale/ixp425_npe_fw.S

cvs diff -r1.12 -r1.13 src/sys/arch/arm/xscale/files.ixp425 (switch to unified diff)

--- src/sys/arch/arm/xscale/files.ixp425 2018/07/12 10:46:42 1.12
+++ src/sys/arch/arm/xscale/files.ixp425 2023/06/17 11:57:49 1.13
@@ -1,57 +1,58 @@ @@ -1,57 +1,58 @@
1# $NetBSD: files.ixp425,v 1.12 2018/07/12 10:46:42 maxv Exp $ 1# $NetBSD: files.ixp425,v 1.13 2023/06/17 11:57:49 rin Exp $
2# 2#
3# Configuration info for Intel IXP4xx CPU support 3# Configuration info for Intel IXP4xx CPU support
4# 4#
5 5
6defparam opt_ixp425.h IXP425_CLOCK_FREQ 6defparam opt_ixp425.h IXP425_CLOCK_FREQ
7 7
8file arch/arm/xscale/ixp425_intr.c 8file arch/arm/xscale/ixp425_intr.c
9file arch/arm/xscale/ixp425_mem.c 9file arch/arm/xscale/ixp425_mem.c
10file arch/arm/arm32/irq_dispatch.S 10file arch/arm/arm32/irq_dispatch.S
11 11
12# IXP425 Slow peripheral devices 12# IXP425 Slow peripheral devices
13device ixpsip { [addr=-1], [size=0], [index=-1], [intr=-1] }: bus_space_generic 13device ixpsip { [addr=-1], [size=0], [index=-1], [intr=-1] }: bus_space_generic
14file arch/arm/xscale/ixp425_sip.c ixpsip 14file arch/arm/xscale/ixp425_sip.c ixpsip
15 15
16# IXP425 Processor CPU support 16# IXP425 Processor CPU support
17# IXP425 PCI bus 17# IXP425 PCI bus
18device ixpio: pcibus, bus_space_generic 18device ixpio: pcibus, bus_space_generic
19file arch/arm/xscale/ixp425.c ixpio 19file arch/arm/xscale/ixp425.c ixpio
20file arch/arm/xscale/ixp425_space.c ixpio 20file arch/arm/xscale/ixp425_space.c ixpio
21file arch/arm/xscale/ixp425_pci.c ixpio 21file arch/arm/xscale/ixp425_pci.c ixpio
22file arch/arm/xscale/ixp425_pci_space.c ixpio 22file arch/arm/xscale/ixp425_pci_space.c ixpio
23file arch/arm/xscale/ixp425_pci_dma.c ixpio 23file arch/arm/xscale/ixp425_pci_dma.c ixpio
24file arch/arm/xscale/ixp425_pci_asm.S ixpio 24file arch/arm/xscale/ixp425_pci_asm.S ixpio
25 25
26# clock device 26# clock device
27device ixpclk 27device ixpclk
28attach ixpclk at ixpsip 28attach ixpclk at ixpsip
29file arch/arm/xscale/ixp425_timer.c ixpclk needs-flag 29file arch/arm/xscale/ixp425_timer.c ixpclk needs-flag
30 30
31# watchdog device 31# watchdog device
32device ixpdog: sysmon_wdog 32device ixpdog: sysmon_wdog
33attach ixpdog at ixpsip 33attach ixpdog at ixpsip
34file arch/arm/xscale/ixp425_wdog.c ixpdog 34file arch/arm/xscale/ixp425_wdog.c ixpdog
35 35
36# Serial port 36# Serial port
37# Note: Can't call this 'ixpcom' as that clashes with another arm device. 37# Note: Can't call this 'ixpcom' as that clashes with another arm device.
38attach com at ixpsip with ixsipcom 38attach com at ixpsip with ixsipcom
39file arch/arm/xscale/ixp425_com.c ixsipcom 39file arch/arm/xscale/ixp425_com.c ixsipcom
40file arch/arm/xscale/ixp425_a4x_space.c ixsipcom 40file arch/arm/xscale/ixp425_a4x_space.c ixsipcom
41file arch/arm/xscale/ixp425_a4x_io.S ixsipcom 41file arch/arm/xscale/ixp425_a4x_io.S ixsipcom
42 42
43# Micro-engine support 43# Micro-engine support
44device ixme { npe }: bus_space_generic 44device ixme { npe }: bus_space_generic
45attach ixme at mainbus 45attach ixme at mainbus
46file arch/arm/xscale/ixp425_ixme.c ixme 46file arch/arm/xscale/ixp425_ixme.c ixme
47file arch/arm/xscale/ixp425_qmgr.c ixme 47file arch/arm/xscale/ixp425_qmgr.c ixme
48 48
49# NPE support 49# NPE support
50device ixpnpe { [phy=-1] } 50device ixpnpe { [phy=-1] }
51attach ixpnpe at ixme 51attach ixpnpe at ixme
52file arch/arm/xscale/ixp425_npe.c ixpnpe 52file arch/arm/xscale/ixp425_npe.c ixpnpe
 53file arch/arm/xscale/ixp425_npe_fw.S ixpnpe
53 54
54# NPE Ethernet 55# NPE Ethernet
55device npe: ether, ifnet, arp, mii 56device npe: ether, ifnet, arp, mii
56attach npe at ixpnpe 57attach npe at ixpnpe
57file arch/arm/xscale/ixp425_if_npe.c npe 58file arch/arm/xscale/ixp425_if_npe.c npe

cvs diff -r1.2 -r1.3 src/sys/arch/arm/xscale/ixp425-fw.mk (switch to unified diff)

--- src/sys/arch/arm/xscale/ixp425-fw.mk 2010/03/26 15:55:33 1.2
+++ src/sys/arch/arm/xscale/ixp425-fw.mk 2023/06/17 11:57:49 1.3
@@ -1,21 +1,16 @@ @@ -1,21 +1,16 @@
1# $NetBSD: ixp425-fw.mk,v 1.2 2010/03/26 15:55:33 jakllsch Exp $ 1# $NetBSD: ixp425-fw.mk,v 1.3 2023/06/17 11:57:49 rin Exp $
2 2
3# 3#
4# For IXP425 NE support, this file must be included by the board-specific 4# For IXP425 NE support, this file must be included by the board-specific
5# Makefile stub. 5# Makefile stub.
6# 6#
7 7
8# 8#
9# See ixp425-fw.README for instructions on how to download and generate 9# See ixp425-fw.README for instructions on how to download and generate
10# a suitable microcode image for IXP425 Ethernet support. 10# a suitable microcode image for IXP425 Ethernet support.
11# 11#
12 12
13.if exists($S/arch/arm/xscale/IxNpeMicrocode.dat) 13NPE_MICROCODE= $S/arch/arm/xscale/IxNpeMicrocode.dat
14MD_OBJS+= ixp425_fw.o 14.if exists(${MICROCODE})
15CPPFLAGS+= -DIXP425_NPE_MICROCODE 15CPPFLAGS+= -DIXP425_NPE_MICROCODE=\"${NPE_MICROCODE}\"
16 
17ixp425_fw.o: $S/arch/arm/xscale/IxNpeMicrocode.dat 
18 -rm -f ${.OBJDIR}/IxNpeMicrocode.dat 
19 -ln -s $S/arch/arm/xscale/IxNpeMicrocode.dat ${.OBJDIR} 
20 ${OBJCOPY} -I binary -O default -B arm IxNpeMicrocode.dat ${.TARGET} 
21.endif 16.endif

cvs diff -r1.16 -r1.17 src/sys/arch/arm/xscale/ixp425_npe.c (switch to unified diff)

--- src/sys/arch/arm/xscale/ixp425_npe.c 2022/09/27 06:36:43 1.16
+++ src/sys/arch/arm/xscale/ixp425_npe.c 2023/06/17 11:57:49 1.17
@@ -1,1121 +1,1107 @@ @@ -1,1121 +1,1107 @@
1/* $NetBSD: ixp425_npe.c,v 1.16 2022/09/27 06:36:43 skrll Exp $ */ 1/* $NetBSD: ixp425_npe.c,v 1.17 2023/06/17 11:57:49 rin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006 Sam Leffler, Errno Consulting 4 * Copyright (c) 2006 Sam Leffler, Errno Consulting
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer, 11 * notice, this list of conditions and the following disclaimer,
12 * without modification. 12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
15 * redistribution must be conditioned upon including a substantially 15 * redistribution must be conditioned upon including a substantially
16 * similar Disclaimer requirement for further binary redistribution. 16 * similar Disclaimer requirement for further binary redistribution.
17 * 17 *
18 * NO WARRANTY 18 * NO WARRANTY
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 21 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 23 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 * THE POSSIBILITY OF SUCH DAMAGES. 29 * THE POSSIBILITY OF SUCH DAMAGES.
30 */ 30 */
31 31
32/*- 32/*-
33 * Copyright (c) 2001-2005, Intel Corporation. 33 * Copyright (c) 2001-2005, Intel Corporation.
34 * All rights reserved. 34 * All rights reserved.
35 *  35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the Intel Corporation nor the names of its contributors 44 * 3. Neither the name of the Intel Corporation nor the names of its contributors
45 * may be used to endorse or promote products derived from this software 45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission. 46 * without specific prior written permission.
47 *  47 *
48 *  48 *
49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
50 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE. 59 * SUCH DAMAGE.
60*/ 60*/
61#include <sys/cdefs.h> 61#include <sys/cdefs.h>
62#if 0 62#if 0
63__FBSDID("$FreeBSD: src/sys/arm/xscale/ixp425/ixp425_npe.c,v 1.1 2006/11/19 23:55:23 sam Exp $"); 63__FBSDID("$FreeBSD: src/sys/arm/xscale/ixp425/ixp425_npe.c,v 1.1 2006/11/19 23:55:23 sam Exp $");
64#endif 64#endif
65__KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.16 2022/09/27 06:36:43 skrll Exp $"); 65__KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.17 2023/06/17 11:57:49 rin Exp $");
66 66
67/* 67/*
68 * Intel XScale Network Processing Engine (NPE) support. 68 * Intel XScale Network Processing Engine (NPE) support.
69 * 69 *
70 * Each NPE has an ixpnpeX device associated with it that is 70 * Each NPE has an ixpnpeX device associated with it that is
71 * attached at boot. Depending on the microcode loaded into 71 * attached at boot. Depending on the microcode loaded into
72 * an NPE there may be an Ethernet interface (npeX) or some 72 * an NPE there may be an Ethernet interface (npeX) or some
73 * other network interface (e.g. for ATM). This file has support 73 * other network interface (e.g. for ATM). This file has support
74 * for loading microcode images and the associated NPE CPU 74 * for loading microcode images and the associated NPE CPU
75 * manipulations (start, stop, reset). 75 * manipulations (start, stop, reset).
76 * 76 *
77 * The code here basically replaces the npeDl and npeMh classes 77 * The code here basically replaces the npeDl and npeMh classes
78 * in the Intel Access Library (IAL). 78 * in the Intel Access Library (IAL).
79 * 79 *
80 * NB: Microcode images are loaded with firmware(9). To 80 * NB: Microcode images are loaded with firmware(9). To
81 * include microcode in a static kernel include the 81 * include microcode in a static kernel include the
82 * ixpnpe_fw device. Otherwise the firmware will be 82 * ixpnpe_fw device. Otherwise the firmware will be
83 * automatically loaded from the filesystem. 83 * automatically loaded from the filesystem.
84 */ 84 */
85#include <sys/param.h> 85#include <sys/param.h>
86#include <sys/systm.h> 86#include <sys/systm.h>
87#include <sys/kernel.h> 87#include <sys/kernel.h>
88#include <sys/mutex.h> 88#include <sys/mutex.h>
89#include <sys/time.h> 89#include <sys/time.h>
90#include <sys/proc.h> 90#include <sys/proc.h>
91 91
92#include <dev/firmload.h> 92#include <dev/firmload.h>
93 93
94#include <sys/bus.h> 94#include <sys/bus.h>
95#include <machine/cpu.h> 95#include <machine/cpu.h>
96#include <machine/intr.h> 96#include <machine/intr.h>
97 97
98#include <arm/xscale/ixp425reg.h> 98#include <arm/xscale/ixp425reg.h>
99#include <arm/xscale/ixp425var.h> 99#include <arm/xscale/ixp425var.h>
100#include <arm/xscale/ixp425_ixmevar.h> 100#include <arm/xscale/ixp425_ixmevar.h>
101 101
102#include <arm/xscale/ixp425_npereg.h> 102#include <arm/xscale/ixp425_npereg.h>
103#include <arm/xscale/ixp425_npevar.h> 103#include <arm/xscale/ixp425_npevar.h>
104#include <arm/xscale/ixp425_if_npereg.h> 104#include <arm/xscale/ixp425_if_npereg.h>
105 105
106#include "locators.h" 106#include "locators.h"
107 107
108/* 108extern char _binary_IxNpeMicrocode_dat_start[];
109 * IXP425_NPE_MICROCODE will be defined by ixp425-fw.mk IFF the 
110 * microcode object file exists in sys/arch/arm/xscale. 
111 * 
112 * To permit building the NPE drivers without microcode (so they 
113 * don't bitrot due to lack of use), we use "empty" microcode so 
114 * that the NPE drivers will simply fail to start at runtime. 
115 */ 
116#ifdef IXP425_NPE_MICROCODE 
117extern char _binary_IxNpeMicrocode_dat_start[]; 
118#else 
119static char _binary_IxNpeMicrocode_dat_start[] = { 
120 0xfe, 0xed, 0xf0, 0x0d, 0xfe, 0xed, 0xf0, 0x0d 
121}; 
122#endif 
123 109
124#define IX_NPEDL_NPEIMAGE_FIELD_MASK 0xff 110#define IX_NPEDL_NPEIMAGE_FIELD_MASK 0xff
125 111
126/* used to read download map from version in microcode image */ 112/* used to read download map from version in microcode image */
127#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000 113#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000
128#define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001 114#define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001
129#define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002 115#define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002
130#define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F 116#define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F
131 117
132/* 118/*
133 * masks used to extract address info from State information context 119 * masks used to extract address info from State information context
134 * register addresses as read from microcode image  120 * register addresses as read from microcode image
135 */ 121 */
136#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F 122#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F
137#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0 123#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0
138 124
139/* LSB offset of Context Number field in State-Info Context Address */ 125/* LSB offset of Context Number field in State-Info Context Address */
140#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4 126#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4
141 127
142/* size (in words) of single State Information entry (ctxt reg address|data) */ 128/* size (in words) of single State Information entry (ctxt reg address|data) */
143#define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2 129#define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2
144 130
145typedef struct { 131typedef struct {
146 uint32_t type; 132 uint32_t type;
147 uint32_t offset; 133 uint32_t offset;
148} IxNpeDlNpeMgrDownloadMapBlockEntry; 134} IxNpeDlNpeMgrDownloadMapBlockEntry;
149 135
150typedef union { 136typedef union {
151 IxNpeDlNpeMgrDownloadMapBlockEntry block; 137 IxNpeDlNpeMgrDownloadMapBlockEntry block;
152 uint32_t eodmMarker; 138 uint32_t eodmMarker;
153} IxNpeDlNpeMgrDownloadMapEntry; 139} IxNpeDlNpeMgrDownloadMapEntry;
154 140
155typedef struct { 141typedef struct {
156 /* 1st entry in the download map (there may be more than one) */ 142 /* 1st entry in the download map (there may be more than one) */
157 IxNpeDlNpeMgrDownloadMapEntry entry[1]; 143 IxNpeDlNpeMgrDownloadMapEntry entry[1];
158} IxNpeDlNpeMgrDownloadMap; 144} IxNpeDlNpeMgrDownloadMap;
159 145
160/* used to access an instruction or data block in a microcode image */ 146/* used to access an instruction or data block in a microcode image */
161typedef struct { 147typedef struct {
162 uint32_t npeMemAddress; 148 uint32_t npeMemAddress;
163 uint32_t size; 149 uint32_t size;
164 uint32_t data[1]; 150 uint32_t data[1];
165} IxNpeDlNpeMgrCodeBlock; 151} IxNpeDlNpeMgrCodeBlock;
166 152
167/* used to access each Context Reg entry state-information block */ 153/* used to access each Context Reg entry state-information block */
168typedef struct { 154typedef struct {
169 uint32_t addressInfo; 155 uint32_t addressInfo;
170 uint32_t value; 156 uint32_t value;
171} IxNpeDlNpeMgrStateInfoCtxtRegEntry; 157} IxNpeDlNpeMgrStateInfoCtxtRegEntry;
172 158
173/* used to access a state-information block in a microcode image */ 159/* used to access a state-information block in a microcode image */
174typedef struct { 160typedef struct {
175 uint32_t size; 161 uint32_t size;
176 IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1]; 162 IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
177} IxNpeDlNpeMgrStateInfoBlock; 163} IxNpeDlNpeMgrStateInfoBlock;
178 164
179static int npe_debug = 0; 165static int npe_debug = 0;
180#define DPRINTF(dev, fmt, ...) do { \ 166#define DPRINTF(dev, fmt, ...) do { \
181 if (npe_debug) printf(fmt, __VA_ARGS__); \ 167 if (npe_debug) printf(fmt, __VA_ARGS__); \
182} while (0) 168} while (0)
183#define DPRINTFn(n, dev, fmt, ...) do { \ 169#define DPRINTFn(n, dev, fmt, ...) do { \
184 if (npe_debug >= n) printf(fmt, __VA_ARGS__); \ 170 if (npe_debug >= n) printf(fmt, __VA_ARGS__); \
185} while (0) 171} while (0)
186 172
187static int npe_checkbits(struct ixpnpe_softc *, uint32_t reg, uint32_t); 173static int npe_checkbits(struct ixpnpe_softc *, uint32_t reg, uint32_t);
188static int npe_isstopped(struct ixpnpe_softc *); 174static int npe_isstopped(struct ixpnpe_softc *);
189static int npe_load_ins(struct ixpnpe_softc *, 175static int npe_load_ins(struct ixpnpe_softc *,
190 const IxNpeDlNpeMgrCodeBlock *bp, int verify); 176 const IxNpeDlNpeMgrCodeBlock *bp, int verify);
191static int npe_load_data(struct ixpnpe_softc *, 177static int npe_load_data(struct ixpnpe_softc *,
192 const IxNpeDlNpeMgrCodeBlock *bp, int verify); 178 const IxNpeDlNpeMgrCodeBlock *bp, int verify);
193static int npe_load_stateinfo(struct ixpnpe_softc *, 179static int npe_load_stateinfo(struct ixpnpe_softc *,
194 const IxNpeDlNpeMgrStateInfoBlock *bp, int verify); 180 const IxNpeDlNpeMgrStateInfoBlock *bp, int verify);
195static int npe_load_image(struct ixpnpe_softc *, 181static int npe_load_image(struct ixpnpe_softc *,
196 const uint32_t *imageCodePtr, int verify); 182 const uint32_t *imageCodePtr, int verify);
197static int npe_cpu_reset(struct ixpnpe_softc *); 183static int npe_cpu_reset(struct ixpnpe_softc *);
198static int npe_cpu_start(struct ixpnpe_softc *); 184static int npe_cpu_start(struct ixpnpe_softc *);
199static int npe_cpu_stop(struct ixpnpe_softc *); 185static int npe_cpu_stop(struct ixpnpe_softc *);
200static void npe_cmd_issue_write(struct ixpnpe_softc *, 186static void npe_cmd_issue_write(struct ixpnpe_softc *,
201 uint32_t cmd, uint32_t addr, uint32_t data); 187 uint32_t cmd, uint32_t addr, uint32_t data);
202static uint32_t npe_cmd_issue_read(struct ixpnpe_softc *, 188static uint32_t npe_cmd_issue_read(struct ixpnpe_softc *,
203 uint32_t cmd, uint32_t addr); 189 uint32_t cmd, uint32_t addr);
204static int npe_ins_write(struct ixpnpe_softc *, 190static int npe_ins_write(struct ixpnpe_softc *,
205 uint32_t addr, uint32_t data, int verify); 191 uint32_t addr, uint32_t data, int verify);
206static int npe_data_write(struct ixpnpe_softc *, 192static int npe_data_write(struct ixpnpe_softc *,
207 uint32_t addr, uint32_t data, int verify); 193 uint32_t addr, uint32_t data, int verify);
208static void npe_ecs_reg_write(struct ixpnpe_softc *, 194static void npe_ecs_reg_write(struct ixpnpe_softc *,
209 uint32_t reg, uint32_t data); 195 uint32_t reg, uint32_t data);
210static uint32_t npe_ecs_reg_read(struct ixpnpe_softc *, uint32_t reg); 196static uint32_t npe_ecs_reg_read(struct ixpnpe_softc *, uint32_t reg);
211static void npe_issue_cmd(struct ixpnpe_softc *, uint32_t command); 197static void npe_issue_cmd(struct ixpnpe_softc *, uint32_t command);
212static void npe_cpu_step_save(struct ixpnpe_softc *); 198static void npe_cpu_step_save(struct ixpnpe_softc *);
213static int npe_cpu_step(struct ixpnpe_softc *, uint32_t npeInstruction, 199static int npe_cpu_step(struct ixpnpe_softc *, uint32_t npeInstruction,
214 uint32_t ctxtNum, uint32_t ldur); 200 uint32_t ctxtNum, uint32_t ldur);
215static void npe_cpu_step_restore(struct ixpnpe_softc *); 201static void npe_cpu_step_restore(struct ixpnpe_softc *);
216static int npe_logical_reg_read(struct ixpnpe_softc *, 202static int npe_logical_reg_read(struct ixpnpe_softc *,
217 uint32_t regAddr, uint32_t regSize, 203 uint32_t regAddr, uint32_t regSize,
218 uint32_t ctxtNum, uint32_t *regVal); 204 uint32_t ctxtNum, uint32_t *regVal);
219static int npe_logical_reg_write(struct ixpnpe_softc *, 205static int npe_logical_reg_write(struct ixpnpe_softc *,
220 uint32_t regAddr, uint32_t regVal, 206 uint32_t regAddr, uint32_t regVal,
221 uint32_t regSize, uint32_t ctxtNum, int verify); 207 uint32_t regSize, uint32_t ctxtNum, int verify);
222static int npe_physical_reg_write(struct ixpnpe_softc *, 208static int npe_physical_reg_write(struct ixpnpe_softc *,
223 uint32_t regAddr, uint32_t regValue, int verify); 209 uint32_t regAddr, uint32_t regValue, int verify);
224static int npe_ctx_reg_write(struct ixpnpe_softc *, uint32_t ctxtNum, 210static int npe_ctx_reg_write(struct ixpnpe_softc *, uint32_t ctxtNum,
225 uint32_t ctxtReg, uint32_t ctxtRegVal, int verify); 211 uint32_t ctxtReg, uint32_t ctxtRegVal, int verify);
226 212
227static int ixpnpe_intr(void *arg); 213static int ixpnpe_intr(void *arg);
228 214
229static uint32_t 215static uint32_t
230npe_reg_read(struct ixpnpe_softc *sc, bus_size_t off) 216npe_reg_read(struct ixpnpe_softc *sc, bus_size_t off)
231{ 217{
232 uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off); 218 uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
233 DPRINTFn(9, sc->sc_dev, "%s(0x%lx) => 0x%x\n", __func__, off, v); 219 DPRINTFn(9, sc->sc_dev, "%s(0x%lx) => 0x%x\n", __func__, off, v);
234 return v; 220 return v;
235} 221}
236 222
237static void 223static void
238npe_reg_write(struct ixpnpe_softc *sc, bus_size_t off, uint32_t val) 224npe_reg_write(struct ixpnpe_softc *sc, bus_size_t off, uint32_t val)
239{ 225{
240 DPRINTFn(9, sc->sc_dev, "%s(0x%lx, 0x%x)\n", __func__, off, val); 226 DPRINTFn(9, sc->sc_dev, "%s(0x%lx, 0x%x)\n", __func__, off, val);
241 bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val); 227 bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
242} 228}
243 229
244static int ixpnpe_match(device_t, cfdata_t, void *); 230static int ixpnpe_match(device_t, cfdata_t, void *);
245static void ixpnpe_attach(device_t, device_t, void *); 231static void ixpnpe_attach(device_t, device_t, void *);
246static int ixpnpe_print(void *, const char *); 232static int ixpnpe_print(void *, const char *);
247static int ixpnpe_search(device_t, cfdata_t, const int *, void *); 233static int ixpnpe_search(device_t, cfdata_t, const int *, void *);
248 234
249CFATTACH_DECL_NEW(ixpnpe, sizeof(struct ixpnpe_softc), 235CFATTACH_DECL_NEW(ixpnpe, sizeof(struct ixpnpe_softc),
250 ixpnpe_match, ixpnpe_attach, NULL, NULL); 236 ixpnpe_match, ixpnpe_attach, NULL, NULL);
251 237
252static int 238static int
253ixpnpe_match(device_t parent, cfdata_t match, void *arg) 239ixpnpe_match(device_t parent, cfdata_t match, void *arg)
254{ 240{
255 struct ixme_attach_args *ixa = arg; 241 struct ixme_attach_args *ixa = arg;
256 242
257 return (ixa->ixa_npe == 1 || ixa->ixa_npe == 2); 243 return (ixa->ixa_npe == 1 || ixa->ixa_npe == 2);
258} 244}
259 245
260static void 246static void
261ixpnpe_attach(device_t parent, device_t self, void *arg) 247ixpnpe_attach(device_t parent, device_t self, void *arg)
262{ 248{
263 struct ixpnpe_softc *sc = device_private(self); 249 struct ixpnpe_softc *sc = device_private(self);
264 struct ixme_attach_args *ixa = arg; 250 struct ixme_attach_args *ixa = arg;
265 bus_addr_t base; 251 bus_addr_t base;
266 int irq; 252 int irq;
267 253
268 aprint_naive("\n"); 254 aprint_naive("\n");
269 aprint_normal("\n"); 255 aprint_normal("\n");
270 256
271 sc->sc_dev = self; 257 sc->sc_dev = self;
272 sc->sc_iot = ixa->ixa_iot; 258 sc->sc_iot = ixa->ixa_iot;
273 sc->sc_dt = ixa->ixa_dt; 259 sc->sc_dt = ixa->ixa_dt;
274 sc->sc_unit = ixa->ixa_npe; 260 sc->sc_unit = ixa->ixa_npe;
275 261
276 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); 262 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
277 263
278 /* XXX: Check features to ensure this NPE is enabled */ 264 /* XXX: Check features to ensure this NPE is enabled */
279 265
280 switch (ixa->ixa_npe) { 266 switch (ixa->ixa_npe) {
281 default: 267 default:
282 panic("%s: Invalid NPE!", device_xname(self)); 268 panic("%s: Invalid NPE!", device_xname(self));
283 269
284 case 1: 270 case 1:
285 base = IXP425_NPE_B_HWBASE; 271 base = IXP425_NPE_B_HWBASE;
286 sc->sc_size = IXP425_NPE_B_SIZE; 272 sc->sc_size = IXP425_NPE_B_SIZE;
287 irq = IXP425_INT_NPE_B; 273 irq = IXP425_INT_NPE_B;
288 274
289 /* size of instruction memory */ 275 /* size of instruction memory */
290 sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB; 276 sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB;
291 /* size of data memory */ 277 /* size of data memory */
292 sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB; 278 sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB;
293 break; 279 break;
294 280
295 case 2: 281 case 2:
296 base = IXP425_NPE_C_HWBASE; 282 base = IXP425_NPE_C_HWBASE;
297 sc->sc_size = IXP425_NPE_C_SIZE; 283 sc->sc_size = IXP425_NPE_C_SIZE;
298 irq = IXP425_INT_NPE_C; 284 irq = IXP425_INT_NPE_C;
299 285
300 /* size of instruction memory */ 286 /* size of instruction memory */
301 sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC; 287 sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC;
302 /* size of data memory */ 288 /* size of data memory */
303 sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC; 289 sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC;
304 break; 290 break;
305 } 291 }
306 if (bus_space_map(sc->sc_iot, base, sc->sc_size, 0, &sc->sc_ioh)) 292 if (bus_space_map(sc->sc_iot, base, sc->sc_size, 0, &sc->sc_ioh))
307 panic("%s: Cannot map registers", device_xname(self)); 293 panic("%s: Cannot map registers", device_xname(self));
308 294
309 /* 295 /*
310 * Setup IRQ and handler for NPE message support. 296 * Setup IRQ and handler for NPE message support.
311 */ 297 */
312 sc->sc_ih = ixp425_intr_establish(irq, IPL_NET, ixpnpe_intr, sc); 298 sc->sc_ih = ixp425_intr_establish(irq, IPL_NET, ixpnpe_intr, sc);
313 if (sc->sc_ih == NULL) 299 if (sc->sc_ih == NULL)
314 panic("%s: Unable to establish irq %u", device_xname(self), irq); 300 panic("%s: Unable to establish irq %u", device_xname(self), irq);
315 /* enable output fifo interrupts (NB: must also set OFIFO Write Enable) */  301 /* enable output fifo interrupts (NB: must also set OFIFO Write Enable) */
316 npe_reg_write(sc, IX_NPECTL, 302 npe_reg_write(sc, IX_NPECTL,
317 npe_reg_read(sc, IX_NPECTL) | (IX_NPECTL_OFE | IX_NPECTL_OFWE)); 303 npe_reg_read(sc, IX_NPECTL) | (IX_NPECTL_OFE | IX_NPECTL_OFWE));
318 304
319 config_search(self, ixa, 305 config_search(self, ixa,
320 CFARGS(.search = ixpnpe_search)); 306 CFARGS(.search = ixpnpe_search));
321} 307}
322 308
323static int 309static int
324ixpnpe_print(void *arg, const char *name) 310ixpnpe_print(void *arg, const char *name)
325{ 311{
326 312
327 return (UNCONF); 313 return (UNCONF);
328} 314}
329 315
330static int 316static int
331ixpnpe_search(device_t parent, cfdata_t cf, const int *ldesc, void *arg) 317ixpnpe_search(device_t parent, cfdata_t cf, const int *ldesc, void *arg)
332{ 318{
333 struct ixpnpe_softc *sc = device_private(parent); 319 struct ixpnpe_softc *sc = device_private(parent);
334 struct ixme_attach_args *ixa = arg; 320 struct ixme_attach_args *ixa = arg;
335 struct ixpnpe_attach_args na; 321 struct ixpnpe_attach_args na;
336 322
337 na.na_unit = ixa->ixa_npe; 323 na.na_unit = ixa->ixa_npe;
338 na.na_phy = cf->cf_loc[IXPNPECF_PHY]; 324 na.na_phy = cf->cf_loc[IXPNPECF_PHY];
339 na.na_npe = sc; 325 na.na_npe = sc;
340 na.na_iot = ixa->ixa_iot; 326 na.na_iot = ixa->ixa_iot;
341 na.na_dt = ixa->ixa_dt; 327 na.na_dt = ixa->ixa_dt;
342 328
343 if (config_probe(parent, cf, &na)) { 329 if (config_probe(parent, cf, &na)) {
344 config_attach(parent, cf, &na, ixpnpe_print, CFARGS_NONE); 330 config_attach(parent, cf, &na, ixpnpe_print, CFARGS_NONE);
345 return (1); 331 return (1);
346 } 332 }
347 333
348 return (0); 334 return (0);
349} 335}
350 336
351int 337int
352ixpnpe_stopandreset(struct ixpnpe_softc *sc) 338ixpnpe_stopandreset(struct ixpnpe_softc *sc)
353{ 339{
354 int error; 340 int error;
355 341
356 mutex_enter(&sc->sc_lock); 342 mutex_enter(&sc->sc_lock);
357 error = npe_cpu_stop(sc); /* stop NPE */ 343 error = npe_cpu_stop(sc); /* stop NPE */
358 if (error == 0) 344 if (error == 0)
359 error = npe_cpu_reset(sc); /* reset it */ 345 error = npe_cpu_reset(sc); /* reset it */
360 if (error == 0) 346 if (error == 0)
361 sc->started = 0; /* mark stopped */ 347 sc->started = 0; /* mark stopped */
362 mutex_exit(&sc->sc_lock); 348 mutex_exit(&sc->sc_lock);
363 349
364 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error); 350 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
365 return error; 351 return error;
366} 352}
367 353
368static int 354static int
369ixpnpe_start_locked(struct ixpnpe_softc *sc) 355ixpnpe_start_locked(struct ixpnpe_softc *sc)
370{ 356{
371 int error; 357 int error;
372 358
373 if (!sc->started) { 359 if (!sc->started) {
374 error = npe_cpu_start(sc); 360 error = npe_cpu_start(sc);
375 if (error == 0) 361 if (error == 0)
376 sc->started = 1; 362 sc->started = 1;
377 } else 363 } else
378 error = 0; 364 error = 0;
379 365
380 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error); 366 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
381 return error; 367 return error;
382} 368}
383 369
384int 370int
385ixpnpe_start(struct ixpnpe_softc *sc) 371ixpnpe_start(struct ixpnpe_softc *sc)
386{ 372{
387 int ret; 373 int ret;
388 374
389 mutex_enter(&sc->sc_lock); 375 mutex_enter(&sc->sc_lock);
390 ret = ixpnpe_start_locked(sc); 376 ret = ixpnpe_start_locked(sc);
391 mutex_exit(&sc->sc_lock); 377 mutex_exit(&sc->sc_lock);
392 return (ret); 378 return (ret);
393} 379}
394 380
395int 381int
396ixpnpe_stop(struct ixpnpe_softc *sc) 382ixpnpe_stop(struct ixpnpe_softc *sc)
397{ 383{
398 int error; 384 int error;
399 385
400 mutex_enter(&sc->sc_lock); 386 mutex_enter(&sc->sc_lock);
401 error = npe_cpu_stop(sc); 387 error = npe_cpu_stop(sc);
402 if (error == 0) 388 if (error == 0)
403 sc->started = 0; 389 sc->started = 0;
404 mutex_exit(&sc->sc_lock); 390 mutex_exit(&sc->sc_lock);
405 391
406 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error); 392 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
407 return error; 393 return error;
408} 394}
409 395
410/* 396/*
411 * Indicates the start of an NPE Image, in new NPE Image Library format. 397 * Indicates the start of an NPE Image, in new NPE Image Library format.
412 * 2 consecutive occurrences indicates the end of the NPE Image Library 398 * 2 consecutive occurrences indicates the end of the NPE Image Library
413 */ 399 */
414#define NPE_IMAGE_MARKER 0xfeedf00d 400#define NPE_IMAGE_MARKER 0xfeedf00d
415 401
416/* 402/*
417 * NPE Image Header definition, used in new NPE Image Library format 403 * NPE Image Header definition, used in new NPE Image Library format
418 */ 404 */
419typedef struct { 405typedef struct {
420 uint32_t marker; 406 uint32_t marker;
421 uint32_t id; 407 uint32_t id;
422 uint32_t size; 408 uint32_t size;
423} IxNpeDlImageMgrImageHeader; 409} IxNpeDlImageMgrImageHeader;
424 410
425static int 411static int
426npe_findimage(struct ixpnpe_softc *sc, 412npe_findimage(struct ixpnpe_softc *sc,
427 const uint32_t *imageLibrary, uint32_t imageId, 413 const uint32_t *imageLibrary, uint32_t imageId,
428 const uint32_t **imagePtr, uint32_t *imageSize) 414 const uint32_t **imagePtr, uint32_t *imageSize)
429{ 415{
430 const IxNpeDlImageMgrImageHeader *image; 416 const IxNpeDlImageMgrImageHeader *image;
431 uint32_t offset = 0; 417 uint32_t offset = 0;
432 418
433 while (imageLibrary[offset] == NPE_IMAGE_MARKER) { 419 while (imageLibrary[offset] == NPE_IMAGE_MARKER) {
434 image = (const IxNpeDlImageMgrImageHeader *)&imageLibrary[offset]; 420 image = (const IxNpeDlImageMgrImageHeader *)&imageLibrary[offset];
435 offset += sizeof(IxNpeDlImageMgrImageHeader)/sizeof(uint32_t); 421 offset += sizeof(IxNpeDlImageMgrImageHeader)/sizeof(uint32_t);
436  422
437 DPRINTF(sc->sc_dev, "%s: off %u mark 0x%x id 0x%x size %u\n", 423 DPRINTF(sc->sc_dev, "%s: off %u mark 0x%x id 0x%x size %u\n",
438 __func__, offset, image->marker, image->id, image->size); 424 __func__, offset, image->marker, image->id, image->size);
439 if (image->id == imageId) { 425 if (image->id == imageId) {
440 *imagePtr = imageLibrary + offset; 426 *imagePtr = imageLibrary + offset;
441 *imageSize = image->size; 427 *imageSize = image->size;
442 return 0; 428 return 0;
443 } 429 }
444 /* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */ 430 /* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */
445 if (image->id == NPE_IMAGE_MARKER) { 431 if (image->id == NPE_IMAGE_MARKER) {
446 printf("%s: imageId 0x%08x not found in image library header\n", 432 printf("%s: imageId 0x%08x not found in image library header\n",
447 device_xname(sc->sc_dev), imageId); 433 device_xname(sc->sc_dev), imageId);
448 /* reached end of library, image not found */ 434 /* reached end of library, image not found */
449 return EIO; 435 return EIO;
450 } 436 }
451 offset += image->size; 437 offset += image->size;
452 } 438 }
453 return EIO; 439 return EIO;
454} 440}
455 441
456int 442int
457ixpnpe_init(struct ixpnpe_softc *sc, const char *imageName, uint32_t imageId) 443ixpnpe_init(struct ixpnpe_softc *sc, const char *imageName, uint32_t imageId)
458{ 444{
459 uint32_t imageSize; 445 uint32_t imageSize;
460 const uint32_t *imageCodePtr; 446 const uint32_t *imageCodePtr;
461 void *fw; 447 void *fw;
462 int error; 448 int error;
463 449
464 DPRINTF(sc->sc_dev, "load %s, imageId 0x%08x\n", imageName, imageId); 450 DPRINTF(sc->sc_dev, "load %s, imageId 0x%08x\n", imageName, imageId);
465 451
466#if 0 452#if 0
467 IxFeatureCtrlDeviceId devid = IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId); 453 IxFeatureCtrlDeviceId devid = IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId);
468 /* 454 /*
469 * Checking if image being loaded is meant for device that is running. 455 * Checking if image being loaded is meant for device that is running.
470 * Image is forward compatible. i.e Image built for IXP42X should run 456 * Image is forward compatible. i.e Image built for IXP42X should run
471 * on IXP46X but not vice versa. 457 * on IXP46X but not vice versa.
472 */ 458 */
473 if (devid > (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK)) 459 if (devid > (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK))
474 return EINVAL; 460 return EINVAL;
475#endif 461#endif
476 error = ixpnpe_stopandreset(sc); /* stop and reset the NPE */ 462 error = ixpnpe_stopandreset(sc); /* stop and reset the NPE */
477 if (error != 0) 463 if (error != 0)
478 return error; 464 return error;
479 465
480 fw = (void *)_binary_IxNpeMicrocode_dat_start; 466 fw = (void *)_binary_IxNpeMicrocode_dat_start;
481 467
482 /* Locate desired image in files w/ combined images */ 468 /* Locate desired image in files w/ combined images */
483 error = npe_findimage(sc, (void *)fw /*fw->data*/, imageId, &imageCodePtr, &imageSize); 469 error = npe_findimage(sc, (void *)fw /*fw->data*/, imageId, &imageCodePtr, &imageSize);
484 if (error != 0) 470 if (error != 0)
485 goto done; 471 goto done;
486 472
487 /* 473 /*
488 * If download was successful, store image Id in list of 474 * If download was successful, store image Id in list of
489 * currently loaded images. If a critical error occurred 475 * currently loaded images. If a critical error occurred
490 * during download, record that the NPE has an invalid image 476 * during download, record that the NPE has an invalid image
491 */ 477 */
492 mutex_enter(&sc->sc_lock); 478 mutex_enter(&sc->sc_lock);
493 error = npe_load_image(sc, imageCodePtr, 1 /*VERIFY*/); 479 error = npe_load_image(sc, imageCodePtr, 1 /*VERIFY*/);
494 if (error == 0) { 480 if (error == 0) {
495 sc->validImage = 1; 481 sc->validImage = 1;
496 error = ixpnpe_start_locked(sc); 482 error = ixpnpe_start_locked(sc);
497 } else { 483 } else {
498 sc->validImage = 0; 484 sc->validImage = 0;
499 } 485 }
500 sc->functionalityId = IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId); 486 sc->functionalityId = IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId);
501 mutex_exit(&sc->sc_lock); 487 mutex_exit(&sc->sc_lock);
502done: 488done:
503 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error); 489 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
504 return error; 490 return error;
505} 491}
506 492
507int 493int
508ixpnpe_getfunctionality(struct ixpnpe_softc *sc) 494ixpnpe_getfunctionality(struct ixpnpe_softc *sc)
509{ 495{
510 return (sc->validImage ? sc->functionalityId : 0); 496 return (sc->validImage ? sc->functionalityId : 0);
511} 497}
512 498
513static int 499static int
514npe_checkbits(struct ixpnpe_softc *sc, uint32_t reg, uint32_t expectedBitsSet) 500npe_checkbits(struct ixpnpe_softc *sc, uint32_t reg, uint32_t expectedBitsSet)
515{ 501{
516 uint32_t val; 502 uint32_t val;
517 503
518 val = npe_reg_read(sc, reg); 504 val = npe_reg_read(sc, reg);
519 DPRINTFn(5, sc->sc_dev, "%s(0x%x, 0x%x) => 0x%x (%u)\n", 505 DPRINTFn(5, sc->sc_dev, "%s(0x%x, 0x%x) => 0x%x (%u)\n",
520 __func__, reg, expectedBitsSet, val, 506 __func__, reg, expectedBitsSet, val,
521 (val & expectedBitsSet) == expectedBitsSet); 507 (val & expectedBitsSet) == expectedBitsSet);
522 return ((val & expectedBitsSet) == expectedBitsSet); 508 return ((val & expectedBitsSet) == expectedBitsSet);
523} 509}
524 510
525static int 511static int
526npe_isstopped(struct ixpnpe_softc *sc) 512npe_isstopped(struct ixpnpe_softc *sc)
527{ 513{
528 return npe_checkbits(sc, 514 return npe_checkbits(sc,
529 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP); 515 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP);
530} 516}
531 517
532static int 518static int
533npe_load_ins(struct ixpnpe_softc *sc, 519npe_load_ins(struct ixpnpe_softc *sc,
534 const IxNpeDlNpeMgrCodeBlock *bp, int verify) 520 const IxNpeDlNpeMgrCodeBlock *bp, int verify)
535{ 521{
536 uint32_t npeMemAddress; 522 uint32_t npeMemAddress;
537 int i, blockSize; 523 int i, blockSize;
538 524
539 npeMemAddress = bp->npeMemAddress; 525 npeMemAddress = bp->npeMemAddress;
540 blockSize = bp->size; /* NB: instruction/data count */ 526 blockSize = bp->size; /* NB: instruction/data count */
541 if (npeMemAddress + blockSize > sc->insMemSize) { 527 if (npeMemAddress + blockSize > sc->insMemSize) {
542 printf("%s: Block size too big for NPE memory\n", device_xname(sc->sc_dev)); 528 printf("%s: Block size too big for NPE memory\n", device_xname(sc->sc_dev));
543 return EINVAL; /* XXX */ 529 return EINVAL; /* XXX */
544 } 530 }
545 for (i = 0; i < blockSize; i++, npeMemAddress++) { 531 for (i = 0; i < blockSize; i++, npeMemAddress++) {
546 if (npe_ins_write(sc, npeMemAddress, bp->data[i], verify) != 0) { 532 if (npe_ins_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
547 printf("%s: NPE instruction write failed", device_xname(sc->sc_dev)); 533 printf("%s: NPE instruction write failed", device_xname(sc->sc_dev));
548 return EIO; 534 return EIO;
549 } 535 }
550 } 536 }
551 return 0; 537 return 0;
552} 538}
553 539
554static int 540static int
555npe_load_data(struct ixpnpe_softc *sc, 541npe_load_data(struct ixpnpe_softc *sc,
556 const IxNpeDlNpeMgrCodeBlock *bp, int verify) 542 const IxNpeDlNpeMgrCodeBlock *bp, int verify)
557{ 543{
558 uint32_t npeMemAddress; 544 uint32_t npeMemAddress;
559 int i, blockSize; 545 int i, blockSize;
560 546
561 npeMemAddress = bp->npeMemAddress; 547 npeMemAddress = bp->npeMemAddress;
562 blockSize = bp->size; /* NB: instruction/data count */ 548 blockSize = bp->size; /* NB: instruction/data count */
563 if (npeMemAddress + blockSize > sc->dataMemSize) { 549 if (npeMemAddress + blockSize > sc->dataMemSize) {
564 printf("%s: Block size too big for NPE memory\n", device_xname(sc->sc_dev)); 550 printf("%s: Block size too big for NPE memory\n", device_xname(sc->sc_dev));
565 return EINVAL; 551 return EINVAL;
566 } 552 }
567 for (i = 0; i < blockSize; i++, npeMemAddress++) { 553 for (i = 0; i < blockSize; i++, npeMemAddress++) {
568 if (npe_data_write(sc, npeMemAddress, bp->data[i], verify) != 0) { 554 if (npe_data_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
569 printf("%s: NPE data write failed\n", device_xname(sc->sc_dev)); 555 printf("%s: NPE data write failed\n", device_xname(sc->sc_dev));
570 return EIO; 556 return EIO;
571 } 557 }
572 } 558 }
573 return 0; 559 return 0;
574} 560}
575 561
576static int 562static int
577npe_load_stateinfo(struct ixpnpe_softc *sc, 563npe_load_stateinfo(struct ixpnpe_softc *sc,
578 const IxNpeDlNpeMgrStateInfoBlock *bp, int verify) 564 const IxNpeDlNpeMgrStateInfoBlock *bp, int verify)
579{ 565{
580 int i, nentries, error; 566 int i, nentries, error;
581  567
582 npe_cpu_step_save(sc); 568 npe_cpu_step_save(sc);
583 569
584 /* for each state-info context register entry in block */ 570 /* for each state-info context register entry in block */
585 nentries = bp->size / IX_NPEDL_STATE_INFO_ENTRY_SIZE; 571 nentries = bp->size / IX_NPEDL_STATE_INFO_ENTRY_SIZE;
586 error = 0; 572 error = 0;
587 for (i = 0; i < nentries; i++) { 573 for (i = 0; i < nentries; i++) {
588 /* each state-info entry is 2 words (address, value) in length */ 574 /* each state-info entry is 2 words (address, value) in length */
589 uint32_t regVal = bp->ctxtRegEntry[i].value; 575 uint32_t regVal = bp->ctxtRegEntry[i].value;
590 uint32_t addrInfo = bp->ctxtRegEntry[i].addressInfo; 576 uint32_t addrInfo = bp->ctxtRegEntry[i].addressInfo;
591 577
592 uint32_t reg = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG); 578 uint32_t reg = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
593 uint32_t cNum = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>  579 uint32_t cNum = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
594 IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM; 580 IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
595  581
596 /* error-check Context Register No. and Context Number values */ 582 /* error-check Context Register No. and Context Number values */
597 if (reg >= IX_NPEDL_CTXT_REG_MAX) { 583 if (reg >= IX_NPEDL_CTXT_REG_MAX) {
598 printf("%s: invalid Context Register %u\n", device_xname(sc->sc_dev), 584 printf("%s: invalid Context Register %u\n", device_xname(sc->sc_dev),
599 reg); 585 reg);
600 error = EINVAL; 586 error = EINVAL;
601 break; 587 break;
602 }  588 }
603 if (cNum >= IX_NPEDL_CTXT_NUM_MAX) { 589 if (cNum >= IX_NPEDL_CTXT_NUM_MAX) {
604 printf("%s: invalid Context Number %u\n", device_xname(sc->sc_dev), 590 printf("%s: invalid Context Number %u\n", device_xname(sc->sc_dev),
605 cNum); 591 cNum);
606 error = EINVAL; 592 error = EINVAL;
607 break; 593 break;
608 }  594 }
609 /* NOTE that there is no STEVT register for Context 0 */ 595 /* NOTE that there is no STEVT register for Context 0 */
610 if (cNum == 0 && reg == IX_NPEDL_CTXT_REG_STEVT) { 596 if (cNum == 0 && reg == IX_NPEDL_CTXT_REG_STEVT) {
611 printf("%s: no STEVT for Context 0\n", device_xname(sc->sc_dev)); 597 printf("%s: no STEVT for Context 0\n", device_xname(sc->sc_dev));
612 error = EINVAL; 598 error = EINVAL;
613 break; 599 break;
614 } 600 }
615 601
616 if (npe_ctx_reg_write(sc, cNum, reg, regVal, verify) != 0) { 602 if (npe_ctx_reg_write(sc, cNum, reg, regVal, verify) != 0) {
617 printf("%s: write of state-info to NPE failed\n", 603 printf("%s: write of state-info to NPE failed\n",
618 device_xname(sc->sc_dev)); 604 device_xname(sc->sc_dev));
619 error = EIO; 605 error = EIO;
620 break; 606 break;
621 } 607 }
622 } 608 }
623 609
624 npe_cpu_step_restore(sc); 610 npe_cpu_step_restore(sc);
625 return error; 611 return error;
626} 612}
627 613
628static int 614static int
629npe_load_image(struct ixpnpe_softc *sc, 615npe_load_image(struct ixpnpe_softc *sc,
630 const uint32_t *imageCodePtr, int verify) 616 const uint32_t *imageCodePtr, int verify)
631{ 617{
632#define EOM(marker) ((marker) == IX_NPEDL_END_OF_DOWNLOAD_MAP) 618#define EOM(marker) ((marker) == IX_NPEDL_END_OF_DOWNLOAD_MAP)
633 const IxNpeDlNpeMgrDownloadMap *downloadMap; 619 const IxNpeDlNpeMgrDownloadMap *downloadMap;
634 int i, error; 620 int i, error;
635 621
636 if (!npe_isstopped(sc)) { /* verify NPE is stopped */ 622 if (!npe_isstopped(sc)) { /* verify NPE is stopped */
637 printf("%s: cannot load image, NPE not stopped\n", device_xname(sc->sc_dev)); 623 printf("%s: cannot load image, NPE not stopped\n", device_xname(sc->sc_dev));
638 return EIO; 624 return EIO;
639 } 625 }
640 626
641 /* 627 /*
642 * Read Download Map, checking each block type and calling 628 * Read Download Map, checking each block type and calling
643 * appropriate function to perform download  629 * appropriate function to perform download
644 */ 630 */
645 error = 0; 631 error = 0;
646 downloadMap = (const IxNpeDlNpeMgrDownloadMap *) imageCodePtr; 632 downloadMap = (const IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
647 for (i = 0; !EOM(downloadMap->entry[i].eodmMarker); i++) { 633 for (i = 0; !EOM(downloadMap->entry[i].eodmMarker); i++) {
648 /* calculate pointer to block to be downloaded */ 634 /* calculate pointer to block to be downloaded */
649 const uint32_t *bp = imageCodePtr + downloadMap->entry[i].block.offset; 635 const uint32_t *bp = imageCodePtr + downloadMap->entry[i].block.offset;
650 switch (downloadMap->entry[i].block.type) { 636 switch (downloadMap->entry[i].block.type) {
651 case IX_NPEDL_BLOCK_TYPE_INSTRUCTION: 637 case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
652 error = npe_load_ins(sc, 638 error = npe_load_ins(sc,
653 (const IxNpeDlNpeMgrCodeBlock *) bp, verify); 639 (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
654 DPRINTF(sc->sc_dev, "%s: inst, error %d\n", __func__, error); 640 DPRINTF(sc->sc_dev, "%s: inst, error %d\n", __func__, error);
655 break; 641 break;
656 case IX_NPEDL_BLOCK_TYPE_DATA: 642 case IX_NPEDL_BLOCK_TYPE_DATA:
657 error = npe_load_data(sc, 643 error = npe_load_data(sc,
658 (const IxNpeDlNpeMgrCodeBlock *) bp, verify); 644 (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
659 DPRINTF(sc->sc_dev, "%s: data, error %d\n", __func__, error); 645 DPRINTF(sc->sc_dev, "%s: data, error %d\n", __func__, error);
660 break; 646 break;
661 case IX_NPEDL_BLOCK_TYPE_STATE: 647 case IX_NPEDL_BLOCK_TYPE_STATE:
662 error = npe_load_stateinfo(sc, 648 error = npe_load_stateinfo(sc,
663 (const IxNpeDlNpeMgrStateInfoBlock *) bp, verify); 649 (const IxNpeDlNpeMgrStateInfoBlock *) bp, verify);
664 DPRINTF(sc->sc_dev, "%s: state, error %d\n", __func__, error); 650 DPRINTF(sc->sc_dev, "%s: state, error %d\n", __func__, error);
665 break; 651 break;
666 default: 652 default:
667 printf("%s: unknown block type 0x%x in download map\n", 653 printf("%s: unknown block type 0x%x in download map\n",
668 device_xname(sc->sc_dev), downloadMap->entry[i].block.type); 654 device_xname(sc->sc_dev), downloadMap->entry[i].block.type);
669 error = EIO; /* XXX */ 655 error = EIO; /* XXX */
670 break; 656 break;
671 } 657 }
672 if (error != 0) 658 if (error != 0)
673 break; 659 break;
674 } 660 }
675 return error; 661 return error;
676#undef EOM 662#undef EOM
677} 663}
678 664
679/* contains Reset values for Context Store Registers */ 665/* contains Reset values for Context Store Registers */
680static const struct { 666static const struct {
681 uint32_t regAddr; 667 uint32_t regAddr;
682 uint32_t regResetVal; 668 uint32_t regResetVal;
683} ixNpeDlEcsRegResetValues[] = { 669} ixNpeDlEcsRegResetValues[] = {
684 { IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET }, 670 { IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET },
685 { IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET }, 671 { IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET },
686 { IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET }, 672 { IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET },
687 { IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET }, 673 { IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET },
688 { IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET }, 674 { IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET },
689 { IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET }, 675 { IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET },
690 { IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET }, 676 { IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET },
691 { IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET }, 677 { IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET },
692 { IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET }, 678 { IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET },
693 { IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET }, 679 { IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET },
694 { IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET }, 680 { IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET },
695 { IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET }, 681 { IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET },
696 { IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET } 682 { IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET }
697}; 683};
698 684
699/* contains Reset values for Context Store Registers */ 685/* contains Reset values for Context Store Registers */
700static const uint32_t ixNpeDlCtxtRegResetValues[] = { 686static const uint32_t ixNpeDlCtxtRegResetValues[] = {
701 IX_NPEDL_CTXT_REG_RESET_STEVT, 687 IX_NPEDL_CTXT_REG_RESET_STEVT,
702 IX_NPEDL_CTXT_REG_RESET_STARTPC, 688 IX_NPEDL_CTXT_REG_RESET_STARTPC,
703 IX_NPEDL_CTXT_REG_RESET_REGMAP, 689 IX_NPEDL_CTXT_REG_RESET_REGMAP,
704 IX_NPEDL_CTXT_REG_RESET_CINDEX, 690 IX_NPEDL_CTXT_REG_RESET_CINDEX,
705}; 691};
706 692
707#define IX_NPEDL_RESET_NPE_PARITY 0x0800 693#define IX_NPEDL_RESET_NPE_PARITY 0x0800
708#define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF 694#define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF
709#define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF 695#define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF
710 696
711static int 697static int
712npe_cpu_reset(struct ixpnpe_softc *sc) 698npe_cpu_reset(struct ixpnpe_softc *sc)
713{ 699{
714#define N(a) (sizeof(a) / sizeof(a[0])) 700#define N(a) (sizeof(a) / sizeof(a[0]))
715 uint32_t ctxtReg; /* identifies Context Store reg (0-3) */ 701 uint32_t ctxtReg; /* identifies Context Store reg (0-3) */
716 uint32_t regAddr; 702 uint32_t regAddr;
717 uint32_t regVal; 703 uint32_t regVal;
718 uint32_t resetNpeParity; 704 uint32_t resetNpeParity;
719 uint32_t ixNpeConfigCtrlRegVal; 705 uint32_t ixNpeConfigCtrlRegVal;
720 int i, error = 0; 706 int i, error = 0;
721  707
722 /* pre-store the NPE Config Control Register Value */ 708 /* pre-store the NPE Config Control Register Value */
723 ixNpeConfigCtrlRegVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL); 709 ixNpeConfigCtrlRegVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL);
724 ixNpeConfigCtrlRegVal |= 0x3F000000; 710 ixNpeConfigCtrlRegVal |= 0x3F000000;
725 711
726 /* disable the parity interrupt */ 712 /* disable the parity interrupt */
727 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL, 713 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
728 (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK)); 714 (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
729 DPRINTFn(2, sc->sc_dev, "%s: dis parity int, CTL => 0x%x\n", 715 DPRINTFn(2, sc->sc_dev, "%s: dis parity int, CTL => 0x%x\n",
730 __func__, ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK); 716 __func__, ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK);
731  717
732 npe_cpu_step_save(sc); 718 npe_cpu_step_save(sc);
733 719
734 /* 720 /*
735 * Clear the FIFOs. 721 * Clear the FIFOs.
736 */ 722 */
737 while (npe_checkbits(sc, 723 while (npe_checkbits(sc,
738 IX_NPEDL_REG_OFFSET_WFIFO, IX_NPEDL_MASK_WFIFO_VALID)) { 724 IX_NPEDL_REG_OFFSET_WFIFO, IX_NPEDL_MASK_WFIFO_VALID)) {
739 /* read from the Watch-point FIFO until empty */ 725 /* read from the Watch-point FIFO until empty */
740 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WFIFO); 726 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WFIFO);
741 } 727 }
742 728
743 while (npe_checkbits(sc, 729 while (npe_checkbits(sc,
744 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_OFNE)) { 730 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_OFNE)) {
745 /* read from the outFIFO until empty */ 731 /* read from the outFIFO until empty */
746 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_FIFO); 732 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_FIFO);
747 } 733 }
748  734
749 while (npe_checkbits(sc, 735 while (npe_checkbits(sc,
750 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) { 736 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) {
751 /* 737 /*
752 * Step execution of the NPE instruction to read inFIFO using 738 * Step execution of the NPE instruction to read inFIFO using
753 * the Debug Executing Context stack. 739 * the Debug Executing Context stack.
754 */ 740 */
755 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0); 741 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0);
756 if (error != 0) { 742 if (error != 0) {
757 DPRINTF(sc->sc_dev, "%s: cannot step (1), error %u\n", 743 DPRINTF(sc->sc_dev, "%s: cannot step (1), error %u\n",
758 __func__, error); 744 __func__, error);
759 npe_cpu_step_restore(sc); 745 npe_cpu_step_restore(sc);
760 return error;  746 return error;
761 } 747 }
762 } 748 }
763  749
764 /* 750 /*
765 * Reset the mailbox reg 751 * Reset the mailbox reg
766 */ 752 */
767 /* ...from XScale side */ 753 /* ...from XScale side */
768 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_MBST, IX_NPEDL_REG_RESET_MBST); 754 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_MBST, IX_NPEDL_REG_RESET_MBST);
769 /* ...from NPE side */ 755 /* ...from NPE side */
770 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RESET_MBOX, 0, 0); 756 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
771 if (error != 0) { 757 if (error != 0) {
772 DPRINTF(sc->sc_dev, "%s: cannot step (2), error %u\n", __func__, error); 758 DPRINTF(sc->sc_dev, "%s: cannot step (2), error %u\n", __func__, error);
773 npe_cpu_step_restore(sc); 759 npe_cpu_step_restore(sc);
774 return error;  760 return error;
775 } 761 }
776 762
777 /*  763 /*
778 * Reset the physical registers in the NPE register file: 764 * Reset the physical registers in the NPE register file:
779 * Note: no need to save/restore REGMAP for Context 0 here 765 * Note: no need to save/restore REGMAP for Context 0 here
780 * since all Context Store regs are reset in subsequent code. 766 * since all Context Store regs are reset in subsequent code.
781 */ 767 */
782 for (regAddr = 0; 768 for (regAddr = 0;
783 regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG && error == 0; 769 regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG && error == 0;
784 regAddr++) { 770 regAddr++) {
785 /* for each physical register in the NPE reg file, write 0 : */ 771 /* for each physical register in the NPE reg file, write 0 : */
786 error = npe_physical_reg_write(sc, regAddr, 0, true); 772 error = npe_physical_reg_write(sc, regAddr, 0, true);
787 if (error != 0) { 773 if (error != 0) {
788 DPRINTF(sc->sc_dev, "%s: cannot write phy reg, error %u\n", 774 DPRINTF(sc->sc_dev, "%s: cannot write phy reg, error %u\n",
789 __func__, error); 775 __func__, error);
790 npe_cpu_step_restore(sc); 776 npe_cpu_step_restore(sc);
791 return error; /* abort reset */ 777 return error; /* abort reset */
792 } 778 }
793 } 779 }
794 780
795 /* 781 /*
796 * Reset the context store: 782 * Reset the context store:
797 */ 783 */
798 for (i = IX_NPEDL_CTXT_NUM_MIN; i <= IX_NPEDL_CTXT_NUM_MAX; i++) {  784 for (i = IX_NPEDL_CTXT_NUM_MIN; i <= IX_NPEDL_CTXT_NUM_MAX; i++) {
799 /* set each context's Context Store registers to reset values: */ 785 /* set each context's Context Store registers to reset values: */
800 for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) { 786 for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) {
801 /* NOTE that there is no STEVT register for Context 0 */ 787 /* NOTE that there is no STEVT register for Context 0 */
802 if (!(i == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STEVT)) {  788 if (!(i == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STEVT)) {
803 regVal = ixNpeDlCtxtRegResetValues[ctxtReg]; 789 regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
804 error = npe_ctx_reg_write(sc, i, ctxtReg, regVal, true); 790 error = npe_ctx_reg_write(sc, i, ctxtReg, regVal, true);
805 if (error != 0) { 791 if (error != 0) {
806 DPRINTF(sc->sc_dev, "%s: cannot write ctx reg, error %u\n", 792 DPRINTF(sc->sc_dev, "%s: cannot write ctx reg, error %u\n",
807 __func__, error); 793 __func__, error);
808 npe_cpu_step_restore(sc); 794 npe_cpu_step_restore(sc);
809 return error; /* abort reset */ 795 return error; /* abort reset */
810 } 796 }
811 } 797 }
812 } 798 }
813 } 799 }
814 800
815 npe_cpu_step_restore(sc); 801 npe_cpu_step_restore(sc);
816 802
817 /* write Reset values to Execution Context Stack registers */ 803 /* write Reset values to Execution Context Stack registers */
818 for (i = 0; i < N(ixNpeDlEcsRegResetValues); i++) 804 for (i = 0; i < N(ixNpeDlEcsRegResetValues); i++)
819 npe_ecs_reg_write(sc, 805 npe_ecs_reg_write(sc,
820 ixNpeDlEcsRegResetValues[i].regAddr, 806 ixNpeDlEcsRegResetValues[i].regAddr,
821 ixNpeDlEcsRegResetValues[i].regResetVal); 807 ixNpeDlEcsRegResetValues[i].regResetVal);
822 808
823 /* clear the profile counter */ 809 /* clear the profile counter */
824 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT); 810 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
825  811
826 /* clear registers EXCT, AP0, AP1, AP2 and AP3 */ 812 /* clear registers EXCT, AP0, AP1, AP2 and AP3 */
827 for (regAddr = IX_NPEDL_REG_OFFSET_EXCT; 813 for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
828 regAddr <= IX_NPEDL_REG_OFFSET_AP3; 814 regAddr <= IX_NPEDL_REG_OFFSET_AP3;
829 regAddr += sizeof(uint32_t)) 815 regAddr += sizeof(uint32_t))
830 npe_reg_write(sc, regAddr, 0); 816 npe_reg_write(sc, regAddr, 0);
831 817
832 /* Reset the Watch-count register */ 818 /* Reset the Watch-count register */
833 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_WC, 0); 819 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_WC, 0);
834  820
835 /* 821 /*
836 * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation 822 * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
837 */ 823 */
838 824
839 /* 825 /*
840 * Reset the NPE and its coprocessor - to reset internal 826 * Reset the NPE and its coprocessor - to reset internal
841 * states and remove parity error. Note this makes no 827 * states and remove parity error. Note this makes no
842 * sense based on the documentation. The feature control 828 * sense based on the documentation. The feature control
843 * register always reads back as 0 on the ixp425 and further 829 * register always reads back as 0 on the ixp425 and further
844 * the bit definition of NPEA/NPEB is off by 1 according to 830 * the bit definition of NPEA/NPEB is off by 1 according to
845 * the Intel documentation--so we're blindly following the 831 * the Intel documentation--so we're blindly following the
846 * Intel code w/o any real understanding. 832 * Intel code w/o any real understanding.
847 */ 833 */
848 regVal = EXP_BUS_READ_4(ixp425_softc, EXP_FCTRL_OFFSET); 834 regVal = EXP_BUS_READ_4(ixp425_softc, EXP_FCTRL_OFFSET);
849 DPRINTFn(2, sc->sc_dev, "%s: FCTRL 0x%x\n", __func__, regVal); 835 DPRINTFn(2, sc->sc_dev, "%s: FCTRL 0x%x\n", __func__, regVal);
850 resetNpeParity = 836 resetNpeParity =
851 IX_NPEDL_RESET_NPE_PARITY << (1 + sc->sc_unit); 837 IX_NPEDL_RESET_NPE_PARITY << (1 + sc->sc_unit);
852 DPRINTFn(2, sc->sc_dev, "%s: FCTRL fuse parity, write 0x%x\n", 838 DPRINTFn(2, sc->sc_dev, "%s: FCTRL fuse parity, write 0x%x\n",
853 __func__, regVal | resetNpeParity); 839 __func__, regVal | resetNpeParity);
854 EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal | resetNpeParity); 840 EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal | resetNpeParity);
855 841
856 /* un-fuse and un-reset the NPE & coprocessor */ 842 /* un-fuse and un-reset the NPE & coprocessor */
857 DPRINTFn(2, sc->sc_dev, "%s: FCTRL unfuse parity, write 0x%x\n", 843 DPRINTFn(2, sc->sc_dev, "%s: FCTRL unfuse parity, write 0x%x\n",
858 __func__, regVal & ~resetNpeParity); 844 __func__, regVal & ~resetNpeParity);
859 EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal &~ resetNpeParity); 845 EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal &~ resetNpeParity);
860 846
861 /* 847 /*
862 * Call NpeMgr function to stop the NPE again after the Feature Control 848 * Call NpeMgr function to stop the NPE again after the Feature Control
863 * has unfused and Un-Reset the NPE and its associated Coprocessors. 849 * has unfused and Un-Reset the NPE and its associated Coprocessors.
864 */ 850 */
865 error = npe_cpu_stop(sc); 851 error = npe_cpu_stop(sc);
866 852
867 /* restore NPE configuration bus Control Register - Parity Settings */ 853 /* restore NPE configuration bus Control Register - Parity Settings */
868 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,  854 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
869 (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK)); 855 (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
870 DPRINTFn(2, sc->sc_dev, "%s: restore CTL => 0x%x\n", 856 DPRINTFn(2, sc->sc_dev, "%s: restore CTL => 0x%x\n",
871 __func__, npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL)); 857 __func__, npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL));
872 858
873 return error; 859 return error;
874#undef N 860#undef N
875} 861}
876 862
877static int 863static int
878npe_cpu_start(struct ixpnpe_softc *sc) 864npe_cpu_start(struct ixpnpe_softc *sc)
879{ 865{
880 uint32_t ecsRegVal; 866 uint32_t ecsRegVal;
881 867
882 /* 868 /*
883 * Ensure only Background Context Stack Level is Active by turning off 869 * Ensure only Background Context Stack Level is Active by turning off
884 * the Active bit in each of the other Executing Context Stack levels. 870 * the Active bit in each of the other Executing Context Stack levels.
885 */ 871 */
886 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0); 872 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
887 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; 873 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
888 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, ecsRegVal); 874 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, ecsRegVal);
889 875
890 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0); 876 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
891 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; 877 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
892 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, ecsRegVal); 878 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, ecsRegVal);
893 879
894 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0); 880 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0);
895 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; 881 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
896 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsRegVal); 882 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsRegVal);
897  883
898 /* clear the pipeline */ 884 /* clear the pipeline */
899 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); 885 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
900  886
901 /* start NPE execution by issuing command through EXCTL register on NPE */ 887 /* start NPE execution by issuing command through EXCTL register on NPE */
902 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_START); 888 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_START);
903 889
904 /* 890 /*
905 * Check execution status of NPE to verify operation was successful. 891 * Check execution status of NPE to verify operation was successful.
906 */ 892 */
907 return npe_checkbits(sc, 893 return npe_checkbits(sc,
908 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_RUN) ? 0 : EIO; 894 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_RUN) ? 0 : EIO;
909} 895}
910 896
911static int 897static int
912npe_cpu_stop(struct ixpnpe_softc *sc) 898npe_cpu_stop(struct ixpnpe_softc *sc)
913{ 899{
914 /* stop NPE execution by issuing command through EXCTL register on NPE */ 900 /* stop NPE execution by issuing command through EXCTL register on NPE */
915 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STOP); 901 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STOP);
916 902
917 /* verify that NPE Stop was successful */ 903 /* verify that NPE Stop was successful */
918 return npe_checkbits(sc, 904 return npe_checkbits(sc,
919 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP) ? 0 : EIO; 905 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP) ? 0 : EIO;
920} 906}
921 907
922#define IX_NPEDL_REG_SIZE_BYTE 8 908#define IX_NPEDL_REG_SIZE_BYTE 8
923#define IX_NPEDL_REG_SIZE_SHORT 16 909#define IX_NPEDL_REG_SIZE_SHORT 16
924#define IX_NPEDL_REG_SIZE_WORD 32 910#define IX_NPEDL_REG_SIZE_WORD 32
925 911
926/* 912/*
927 * Introduce extra read cycles after issuing read command to NPE 913 * Introduce extra read cycles after issuing read command to NPE
928 * so that we read the register after the NPE has updated it 914 * so that we read the register after the NPE has updated it
929 * This is to overcome race condition between XScale and NPE 915 * This is to overcome race condition between XScale and NPE
930 */ 916 */
931#define IX_NPEDL_DELAY_READ_CYCLES 2 917#define IX_NPEDL_DELAY_READ_CYCLES 2
932/* 918/*
933 * To mask top three MSBs of 32bit word to download into NPE IMEM 919 * To mask top three MSBs of 32bit word to download into NPE IMEM
934 */ 920 */
935#define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF; 921#define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF;
936 922
937static void 923static void
938npe_cmd_issue_write(struct ixpnpe_softc *sc, 924npe_cmd_issue_write(struct ixpnpe_softc *sc,
939 uint32_t cmd, uint32_t addr, uint32_t data) 925 uint32_t cmd, uint32_t addr, uint32_t data)
940{ 926{
941 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, data); 927 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, data);
942 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr); 928 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
943 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd); 929 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
944} 930}
945 931
946static uint32_t 932static uint32_t
947npe_cmd_issue_read(struct ixpnpe_softc *sc, uint32_t cmd, uint32_t addr) 933npe_cmd_issue_read(struct ixpnpe_softc *sc, uint32_t cmd, uint32_t addr)
948{ 934{
949 uint32_t data; 935 uint32_t data;
950 int i; 936 int i;
951 937
952 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr); 938 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
953 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd); 939 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
954 for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++) 940 for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++)
955 data = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA); 941 data = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
956 return data; 942 return data;
957} 943}
958 944
959static int 945static int
960npe_ins_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify) 946npe_ins_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
961{ 947{
962 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data); 948 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
963 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_INS_MEM, addr, data); 949 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_INS_MEM, addr, data);
964 if (verify) { 950 if (verify) {
965 uint32_t rdata; 951 uint32_t rdata;
966 952
967 /* 953 /*
968 * Write invalid data to this reg, so we can see if we're reading  954 * Write invalid data to this reg, so we can see if we're reading
969 * the EXDATA register too early. 955 * the EXDATA register too early.
970 */ 956 */
971 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data); 957 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
972 958
973 /* Disabled since top 3 MSB are not used for Azusa hardware Refer WR:IXA00053900*/ 959 /* Disabled since top 3 MSB are not used for Azusa hardware Refer WR:IXA00053900*/
974 data &= IX_NPEDL_MASK_UNUSED_IMEM_BITS; 960 data &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
975 961
976 rdata = npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_INS_MEM, addr); 962 rdata = npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_INS_MEM, addr);
977 rdata &= IX_NPEDL_MASK_UNUSED_IMEM_BITS; 963 rdata &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
978 964
979 if (data != rdata) 965 if (data != rdata)
980 return EIO; 966 return EIO;
981 } 967 }
982 return 0; 968 return 0;
983} 969}
984 970
985static int 971static int
986npe_data_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify) 972npe_data_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
987{ 973{
988 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data); 974 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
989 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM, addr, data); 975 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM, addr, data);
990 if (verify) { 976 if (verify) {
991 /* 977 /*
992 * Write invalid data to this reg, so we can see if we're reading  978 * Write invalid data to this reg, so we can see if we're reading
993 * the EXDATA register too early. 979 * the EXDATA register too early.
994 */ 980 */
995 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data); 981 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
996 if (data != npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM, addr)) 982 if (data != npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM, addr))
997 return EIO; 983 return EIO;
998 } 984 }
999 return 0; 985 return 0;
1000} 986}
1001 987
1002static void 988static void
1003npe_ecs_reg_write(struct ixpnpe_softc *sc, uint32_t reg, uint32_t data) 989npe_ecs_reg_write(struct ixpnpe_softc *sc, uint32_t reg, uint32_t data)
1004{ 990{
1005 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_ECS_REG, reg, data); 991 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_ECS_REG, reg, data);
1006} 992}
1007 993
1008static uint32_t 994static uint32_t
1009npe_ecs_reg_read(struct ixpnpe_softc *sc, uint32_t reg) 995npe_ecs_reg_read(struct ixpnpe_softc *sc, uint32_t reg)
1010{ 996{
1011 return npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_ECS_REG, reg); 997 return npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_ECS_REG, reg);
1012} 998}
1013 999
1014static void 1000static void
1015npe_issue_cmd(struct ixpnpe_softc *sc, uint32_t command) 1001npe_issue_cmd(struct ixpnpe_softc *sc, uint32_t command)
1016{ 1002{
1017 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, command); 1003 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, command);
1018} 1004}
1019 1005
1020static void 1006static void
1021npe_cpu_step_save(struct ixpnpe_softc *sc) 1007npe_cpu_step_save(struct ixpnpe_softc *sc)
1022{ 1008{
1023 /* turn off the halt bit by clearing Execution Count register. */ 1009 /* turn off the halt bit by clearing Execution Count register. */
1024 /* save reg contents 1st and restore later */ 1010 /* save reg contents 1st and restore later */
1025 sc->savedExecCount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXCT); 1011 sc->savedExecCount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXCT);
1026 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, 0); 1012 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, 0);
1027 1013
1028 /* ensure that IF and IE are on (temporarily), so that we don't end up 1014 /* ensure that IF and IE are on (temporarily), so that we don't end up
1029 * stepping forever */ 1015 * stepping forever */
1030 sc->savedEcsDbgCtxtReg2 = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2); 1016 sc->savedEcsDbgCtxtReg2 = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2);
1031 1017
1032 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, 1018 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2,
1033 (sc->savedEcsDbgCtxtReg2 | IX_NPEDL_MASK_ECS_DBG_REG_2_IF | 1019 (sc->savedEcsDbgCtxtReg2 | IX_NPEDL_MASK_ECS_DBG_REG_2_IF |
1034 IX_NPEDL_MASK_ECS_DBG_REG_2_IE)); 1020 IX_NPEDL_MASK_ECS_DBG_REG_2_IE));
1035} 1021}
1036 1022
1037static int 1023static int
1038npe_cpu_step(struct ixpnpe_softc *sc, uint32_t npeInstruction, 1024npe_cpu_step(struct ixpnpe_softc *sc, uint32_t npeInstruction,
1039 uint32_t ctxtNum, uint32_t ldur) 1025 uint32_t ctxtNum, uint32_t ldur)
1040{ 1026{
1041#define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000 1027#define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000
1042 uint32_t ecsDbgRegVal; 1028 uint32_t ecsDbgRegVal;
1043 uint32_t oldWatchcount, newWatchcount; 1029 uint32_t oldWatchcount, newWatchcount;
1044 int tries; 1030 int tries;
1045 1031
1046 /* set the Active bit, and the LDUR, in the debug level */ 1032 /* set the Active bit, and the LDUR, in the debug level */
1047 ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE | 1033 ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE |
1048 (ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR); 1034 (ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR);
1049 1035
1050 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsDbgRegVal); 1036 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsDbgRegVal);
1051 1037
1052 /* 1038 /*
1053 * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the 1039 * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the
1054 * instruction, and set SELCTXT at ECS DEBUG Level to specify which context 1040 * instruction, and set SELCTXT at ECS DEBUG Level to specify which context
1055 * store to access. 1041 * store to access.
1056 * Debug ECS Level Reg 1 has form 0x000n000n, where n = context number 1042 * Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
1057 */ 1043 */
1058 ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) | 1044 ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) |
1059 (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT); 1045 (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT);
1060 1046
1061 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_1, ecsDbgRegVal); 1047 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_1, ecsDbgRegVal);
1062 1048
1063 /* clear the pipeline */ 1049 /* clear the pipeline */
1064 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); 1050 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
1065 1051
1066 /* load NPE instruction into the instruction register */ 1052 /* load NPE instruction into the instruction register */
1067 npe_ecs_reg_write(sc, IX_NPEDL_ECS_INSTRUCT_REG, npeInstruction); 1053 npe_ecs_reg_write(sc, IX_NPEDL_ECS_INSTRUCT_REG, npeInstruction);
1068 1054
1069 /* we need this value later to wait for completion of NPE execution step */ 1055 /* we need this value later to wait for completion of NPE execution step */
1070 oldWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC); 1056 oldWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1071 1057
1072 /* issue a Step One command via the Execution Control register */ 1058 /* issue a Step One command via the Execution Control register */
1073 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STEP); 1059 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STEP);
1074 1060
1075 /* 1061 /*
1076 * Force the XScale to wait until the NPE has finished execution step 1062 * Force the XScale to wait until the NPE has finished execution step
1077 * NOTE that this delay will be very small, just long enough to allow a 1063 * NOTE that this delay will be very small, just long enough to allow a
1078 * single NPE instruction to complete execution; if instruction execution 1064 * single NPE instruction to complete execution; if instruction execution
1079 * is not completed before timeout retries, exit the while loop. 1065 * is not completed before timeout retries, exit the while loop.
1080 */ 1066 */
1081 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC); 1067 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1082 for (tries = 0; tries < IX_NPE_DL_MAX_NUM_OF_RETRIES && 1068 for (tries = 0; tries < IX_NPE_DL_MAX_NUM_OF_RETRIES &&
1083 newWatchcount == oldWatchcount; tries++) { 1069 newWatchcount == oldWatchcount; tries++) {
1084 /* Watch Count register increments when NPE completes an instruction */ 1070 /* Watch Count register increments when NPE completes an instruction */
1085 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC); 1071 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1086 }  1072 }
1087 return (tries < IX_NPE_DL_MAX_NUM_OF_RETRIES) ? 0 : EIO; 1073 return (tries < IX_NPE_DL_MAX_NUM_OF_RETRIES) ? 0 : EIO;
1088#undef IX_NPE_DL_MAX_NUM_OF_RETRIES 1074#undef IX_NPE_DL_MAX_NUM_OF_RETRIES
1089}  1075}
1090 1076
1091static void 1077static void
1092npe_cpu_step_restore(struct ixpnpe_softc *sc) 1078npe_cpu_step_restore(struct ixpnpe_softc *sc)
1093{ 1079{
1094 /* clear active bit in debug level */ 1080 /* clear active bit in debug level */
1095 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, 0); 1081 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, 0);
1096 1082
1097 /* clear the pipeline */ 1083 /* clear the pipeline */
1098 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); 1084 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
1099 1085
1100 /* restore Execution Count register contents. */ 1086 /* restore Execution Count register contents. */
1101 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, sc->savedExecCount); 1087 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, sc->savedExecCount);
1102 1088
1103 /* restore IF and IE bits to original values */ 1089 /* restore IF and IE bits to original values */
1104 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, sc->savedEcsDbgCtxtReg2); 1090 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, sc->savedEcsDbgCtxtReg2);
1105} 1091}
1106 1092
1107static int 1093static int
1108npe_logical_reg_read(struct ixpnpe_softc *sc, 1094npe_logical_reg_read(struct ixpnpe_softc *sc,
1109 uint32_t regAddr, uint32_t regSize, 1095 uint32_t regAddr, uint32_t regSize,
1110 uint32_t ctxtNum, uint32_t *regVal) 1096 uint32_t ctxtNum, uint32_t *regVal)
1111{ 1097{
1112 uint32_t npeInstruction, mask; 1098 uint32_t npeInstruction, mask;
1113 int error; 1099 int error;
1114 1100
1115 switch (regSize) { 1101 switch (regSize) {
1116 case IX_NPEDL_REG_SIZE_BYTE: 1102 case IX_NPEDL_REG_SIZE_BYTE:
1117 npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE; 1103 npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE;
1118 mask = 0xff; 1104 mask = 0xff;
1119 break; 1105 break;
1120 case IX_NPEDL_REG_SIZE_SHORT: 1106 case IX_NPEDL_REG_SIZE_SHORT:
1121 npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT; 1107 npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT;

File Added: src/sys/arch/arm/xscale/ixp425_npe_fw.S
/*	$NetBSD: ixp425_npe_fw.S,v 1.1 2023/06/17 11:57:49 rin Exp $	*/

/*-
 * Copyright (c) 2006 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
 *    redistribution must be conditioned upon including a substantially
 *    similar Disclaimer requirement for further binary redistribution.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGES.
 */

/*-
 * Copyright (c) 2001-2005, Intel Corporation.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Intel Corporation nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
*/

#include <arm/asm.h>

/*
 * IXP425_NPE_MICROCODE will be defined by ixp425-fw.mk IFF the
 * microcode object file exists in sys/arch/arm/xscale.
 *
 * To permit building the NPE drivers without microcode (so they
 * don't bitrot due to lack of use), we use "empty" microcode so
 * that the NPE drivers will simply fail to start at runtime.
 */

	.align		2
	.section	.data
	.global		_C_LABEL(_binary_IxNpeMicrocode_dat_start)
_C_LABEL(_binary_IxNpeMicrocode_dat_start):
#ifdef IXP425_NPE_MICROCODE
	.incbin		IXP425_NPE_MICROCODE
#else
	.word		0xfeedf00d
	.word		0xfeedf00d
#endif