1 /* $NetBSD: ixp425_npe.c,v 1.5 2009/03/18 17:06:42 cegger Exp $ */
4 * Copyright (c) 2006 Sam Leffler, Errno Consulting
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
15 * redistribution must be conditioned upon including a substantially
16 * similar Disclaimer requirement for further binary redistribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
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
29 * THE POSSIBILITY OF SUCH DAMAGES.
33 * Copyright (c) 2001-2005, Intel Corporation.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
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
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
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
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
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
61 #include <sys/cdefs.h>
63 __FBSDID("$FreeBSD: src/sys/arm/xscale/ixp425/ixp425_npe.c,v 1.1 2006/11/19 23:55:23 sam Exp $");
65 __KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.5 2009/03/18 17:06:42 cegger Exp $");
68 * Intel XScale Network Processing Engine (NPE) support.
70 * Each NPE has an ixpnpeX device associated with it that is
71 * attached at boot. Depending on the microcode loaded into
72 * an NPE there may be an Ethernet interface (npeX) or some
73 * other network interface (e.g. for ATM). This file has support
74 * for loading microcode images and the associated NPE CPU
75 * manipulations (start, stop, reset).
77 * The code here basically replaces the npeDl and npeMh classes
78 * in the Intel Access Library (IAL).
80 * NB: Microcode images are loaded with firmware(9). To
81 * include microcode in a static kernel include the
82 * ixpnpe_fw device. Otherwise the firmware will be
83 * automatically loaded from the filesystem.
85 #include <sys/param.h>
86 #include <sys/systm.h>
87 #include <sys/kernel.h>
88 #include <sys/malloc.h>
89 #include <sys/simplelock.h>
93 #include <dev/firmload.h>
95 #include <machine/bus.h>
96 #include <machine/cpu.h>
97 #include <machine/intr.h>
99 #include <arm/xscale/ixp425reg.h>
100 #include <arm/xscale/ixp425var.h>
101 #include <arm/xscale/ixp425_ixmevar.h>
103 #include <arm/xscale/ixp425_npereg.h>
104 #include <arm/xscale/ixp425_npevar.h>
105 #include <arm/xscale/ixp425_if_npereg.h>
107 #include "locators.h"
110 * IXP425_NPE_MICROCODE will be defined by ixp425-fw.mk IFF the
111 * microcode object file exists in sys/arch/arm/xscale.
113 * To permit building the NPE drivers without microcode (so they
114 * don't bitrot due to lack of use), we use "empty" microcode so
115 * that the NPE drivers will simply fail to start at runtime.
117 #ifdef IXP425_NPE_MICROCODE
118 extern char _binary_IxNpeMicrocode_dat_start
[];
120 static char _binary_IxNpeMicrocode_dat_start
[] = {
121 0xfe, 0xed, 0xf0, 0x0d, 0xfe, 0xed, 0xf0, 0x0d
125 #define IX_NPEDL_NPEIMAGE_FIELD_MASK 0xff
127 /* used to read download map from version in microcode image */
128 #define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000
129 #define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001
130 #define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002
131 #define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F
134 * masks used to extract address info from State information context
135 * register addresses as read from microcode image
137 #define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F
138 #define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0
140 /* LSB offset of Context Number field in State-Info Context Address */
141 #define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4
143 /* size (in words) of single State Information entry (ctxt reg address|data) */
144 #define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2
149 } IxNpeDlNpeMgrDownloadMapBlockEntry
;
152 IxNpeDlNpeMgrDownloadMapBlockEntry block
;
154 } IxNpeDlNpeMgrDownloadMapEntry
;
157 /* 1st entry in the download map (there may be more than one) */
158 IxNpeDlNpeMgrDownloadMapEntry entry
[1];
159 } IxNpeDlNpeMgrDownloadMap
;
161 /* used to access an instruction or data block in a microcode image */
163 uint32_t npeMemAddress
;
166 } IxNpeDlNpeMgrCodeBlock
;
168 /* used to access each Context Reg entry state-information block */
170 uint32_t addressInfo
;
172 } IxNpeDlNpeMgrStateInfoCtxtRegEntry
;
174 /* used to access a state-information block in a microcode image */
177 IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry
[1];
178 } IxNpeDlNpeMgrStateInfoBlock
;
180 static int npe_debug
= 0;
181 #define DPRINTF(dev, fmt, ...) do { \
182 if (npe_debug) printf(fmt, __VA_ARGS__); \
184 #define DPRINTFn(n, dev, fmt, ...) do { \
185 if (npe_debug >= n) printf(fmt, __VA_ARGS__); \
188 static int npe_checkbits(struct ixpnpe_softc
*, uint32_t reg
, uint32_t);
189 static int npe_isstopped(struct ixpnpe_softc
*);
190 static int npe_load_ins(struct ixpnpe_softc
*,
191 const IxNpeDlNpeMgrCodeBlock
*bp
, int verify
);
192 static int npe_load_data(struct ixpnpe_softc
*,
193 const IxNpeDlNpeMgrCodeBlock
*bp
, int verify
);
194 static int npe_load_stateinfo(struct ixpnpe_softc
*,
195 const IxNpeDlNpeMgrStateInfoBlock
*bp
, int verify
);
196 static int npe_load_image(struct ixpnpe_softc
*,
197 const uint32_t *imageCodePtr
, int verify
);
198 static int npe_cpu_reset(struct ixpnpe_softc
*);
199 static int npe_cpu_start(struct ixpnpe_softc
*);
200 static int npe_cpu_stop(struct ixpnpe_softc
*);
201 static void npe_cmd_issue_write(struct ixpnpe_softc
*,
202 uint32_t cmd
, uint32_t addr
, uint32_t data
);
203 static uint32_t npe_cmd_issue_read(struct ixpnpe_softc
*,
204 uint32_t cmd
, uint32_t addr
);
205 static int npe_ins_write(struct ixpnpe_softc
*,
206 uint32_t addr
, uint32_t data
, int verify
);
207 static int npe_data_write(struct ixpnpe_softc
*,
208 uint32_t addr
, uint32_t data
, int verify
);
209 static void npe_ecs_reg_write(struct ixpnpe_softc
*,
210 uint32_t reg
, uint32_t data
);
211 static uint32_t npe_ecs_reg_read(struct ixpnpe_softc
*, uint32_t reg
);
212 static void npe_issue_cmd(struct ixpnpe_softc
*, uint32_t command
);
213 static void npe_cpu_step_save(struct ixpnpe_softc
*);
214 static int npe_cpu_step(struct ixpnpe_softc
*, uint32_t npeInstruction
,
215 uint32_t ctxtNum
, uint32_t ldur
);
216 static void npe_cpu_step_restore(struct ixpnpe_softc
*);
217 static int npe_logical_reg_read(struct ixpnpe_softc
*,
218 uint32_t regAddr
, uint32_t regSize
,
219 uint32_t ctxtNum
, uint32_t *regVal
);
220 static int npe_logical_reg_write(struct ixpnpe_softc
*,
221 uint32_t regAddr
, uint32_t regVal
,
222 uint32_t regSize
, uint32_t ctxtNum
, int verify
);
223 static int npe_physical_reg_write(struct ixpnpe_softc
*,
224 uint32_t regAddr
, uint32_t regValue
, int verify
);
225 static int npe_ctx_reg_write(struct ixpnpe_softc
*, uint32_t ctxtNum
,
226 uint32_t ctxtReg
, uint32_t ctxtRegVal
, int verify
);
228 static int ixpnpe_intr(void *arg
);
231 npe_reg_read(struct ixpnpe_softc
*sc
, bus_size_t off
)
233 uint32_t v
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, off
);
234 DPRINTFn(9, sc
->sc_dev
, "%s(0x%lx) => 0x%x\n", __func__
, off
, v
);
239 npe_reg_write(struct ixpnpe_softc
*sc
, bus_size_t off
, uint32_t val
)
241 DPRINTFn(9, sc
->sc_dev
, "%s(0x%lx, 0x%x)\n", __func__
, off
, val
);
242 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, off
, val
);
245 static int ixpnpe_match(struct device
*, struct cfdata
*, void *);
246 static void ixpnpe_attach(struct device
*, struct device
*, void *);
247 static int ixpnpe_print(void *, const char *);
248 static int ixpnpe_search(struct device
*, struct cfdata
*, const int *,
251 CFATTACH_DECL(ixpnpe
, sizeof(struct ixpnpe_softc
),
252 ixpnpe_match
, ixpnpe_attach
, NULL
, NULL
);
255 ixpnpe_match(struct device
*parent
, struct cfdata
*match
, void *arg
)
257 struct ixme_attach_args
*ixa
= arg
;
259 return (ixa
->ixa_npe
== 1 || ixa
->ixa_npe
== 2);
263 ixpnpe_attach(struct device
*parent
, struct device
*self
, void *arg
)
265 struct ixpnpe_softc
*sc
= (void *)self
;
266 struct ixme_attach_args
*ixa
= arg
;
273 sc
->sc_iot
= ixa
->ixa_iot
;
274 sc
->sc_dt
= ixa
->ixa_dt
;
275 sc
->sc_unit
= ixa
->ixa_npe
;
277 simple_lock_init(&sc
->sc_lock
);
279 /* XXX: Check features to ensure this NPE is enabled */
281 switch (ixa
->ixa_npe
) {
283 panic("%s: Invalid NPE!", sc
->sc_dev
.dv_xname
);
286 base
= IXP425_NPE_B_HWBASE
;
287 sc
->sc_size
= IXP425_NPE_B_SIZE
;
288 irq
= IXP425_INT_NPE_B
;
290 /* size of instruction memory */
291 sc
->insMemSize
= IX_NPEDL_INS_MEMSIZE_WORDS_NPEB
;
292 /* size of data memory */
293 sc
->dataMemSize
= IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
;
297 base
= IXP425_NPE_C_HWBASE
;
298 sc
->sc_size
= IXP425_NPE_C_SIZE
;
299 irq
= IXP425_INT_NPE_C
;
301 /* size of instruction memory */
302 sc
->insMemSize
= IX_NPEDL_INS_MEMSIZE_WORDS_NPEC
;
303 /* size of data memory */
304 sc
->dataMemSize
= IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
;
307 if (bus_space_map(sc
->sc_iot
, base
, sc
->sc_size
, 0, &sc
->sc_ioh
))
308 panic("%s: Cannot map registers", sc
->sc_dev
.dv_xname
);
311 * Setup IRQ and handler for NPE message support.
313 sc
->sc_ih
= ixp425_intr_establish(irq
, IPL_NET
, ixpnpe_intr
, sc
);
314 if (sc
->sc_ih
== NULL
)
315 panic("%s: Unable to establish irq %u", sc
->sc_dev
.dv_xname
, irq
);
316 /* enable output fifo interrupts (NB: must also set OFIFO Write Enable) */
317 npe_reg_write(sc
, IX_NPECTL
,
318 npe_reg_read(sc
, IX_NPECTL
) | (IX_NPECTL_OFE
| IX_NPECTL_OFWE
));
320 config_search_ia(ixpnpe_search
, self
, "ixpnpe", ixa
);
324 ixpnpe_print(void *arg
, const char *name
)
331 ixpnpe_search(struct device
*parent
, struct cfdata
*cf
, const int *ldesc
,
334 struct ixpnpe_softc
*sc
= (void *)parent
;
335 struct ixme_attach_args
*ixa
= arg
;
336 struct ixpnpe_attach_args na
;
338 na
.na_unit
= ixa
->ixa_npe
;
339 na
.na_phy
= cf
->cf_loc
[IXPNPECF_PHY
];
341 na
.na_iot
= ixa
->ixa_iot
;
342 na
.na_dt
= ixa
->ixa_dt
;
344 if (config_match(parent
, cf
, &na
) > 0) {
345 config_attach(parent
, cf
, &na
, ixpnpe_print
);
353 ixpnpe_stopandreset(struct ixpnpe_softc
*sc
)
357 simple_lock(&sc
->sc_lock
);
358 error
= npe_cpu_stop(sc
); /* stop NPE */
360 error
= npe_cpu_reset(sc
); /* reset it */
362 sc
->started
= 0; /* mark stopped */
363 simple_unlock(&sc
->sc_lock
);
365 DPRINTF(sc
->sc_dev
, "%s: error %d\n", __func__
, error
);
370 ixpnpe_start_locked(struct ixpnpe_softc
*sc
)
375 error
= npe_cpu_start(sc
);
381 DPRINTF(sc
->sc_dev
, "%s: error %d\n", __func__
, error
);
386 ixpnpe_start(struct ixpnpe_softc
*sc
)
390 simple_lock(&sc
->sc_lock
);
391 ret
= ixpnpe_start_locked(sc
);
392 simple_unlock(&sc
->sc_lock
);
397 ixpnpe_stop(struct ixpnpe_softc
*sc
)
401 simple_lock(&sc
->sc_lock
);
402 error
= npe_cpu_stop(sc
);
405 simple_unlock(&sc
->sc_lock
);
407 DPRINTF(sc
->sc_dev
, "%s: error %d\n", __func__
, error
);
412 * Indicates the start of an NPE Image, in new NPE Image Library format.
413 * 2 consecutive occurances indicates the end of the NPE Image Library
415 #define NPE_IMAGE_MARKER 0xfeedf00d
418 * NPE Image Header definition, used in new NPE Image Library format
424 } IxNpeDlImageMgrImageHeader
;
427 npe_findimage(struct ixpnpe_softc
*sc
,
428 const uint32_t *imageLibrary
, uint32_t imageId
,
429 const uint32_t **imagePtr
, uint32_t *imageSize
)
431 const IxNpeDlImageMgrImageHeader
*image
;
434 while (imageLibrary
[offset
] == NPE_IMAGE_MARKER
) {
435 image
= (const IxNpeDlImageMgrImageHeader
*)&imageLibrary
[offset
];
436 offset
+= sizeof(IxNpeDlImageMgrImageHeader
)/sizeof(uint32_t);
438 DPRINTF(sc
->sc_dev
, "%s: off %u mark 0x%x id 0x%x size %u\n",
439 __func__
, offset
, image
->marker
, image
->id
, image
->size
);
440 if (image
->id
== imageId
) {
441 *imagePtr
= imageLibrary
+ offset
;
442 *imageSize
= image
->size
;
445 /* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */
446 if (image
->id
== NPE_IMAGE_MARKER
) {
447 printf("%s: imageId 0x%08x not found in image library header\n",
448 sc
->sc_dev
.dv_xname
, imageId
);
449 /* reached end of library, image not found */
452 offset
+= image
->size
;
458 ixpnpe_init(struct ixpnpe_softc
*sc
, const char *imageName
, uint32_t imageId
)
461 const uint32_t *imageCodePtr
;
465 DPRINTF(sc
->sc_dev
, "load %s, imageId 0x%08x\n", imageName
, imageId
);
468 IxFeatureCtrlDeviceId devid
= IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId
);
470 * Checking if image being loaded is meant for device that is running.
471 * Image is forward compatible. i.e Image built for IXP42X should run
472 * on IXP46X but not vice versa.
474 if (devid
> (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK
))
477 error
= ixpnpe_stopandreset(sc
); /* stop and reset the NPE */
481 fw
= (void *)_binary_IxNpeMicrocode_dat_start
;
483 /* Locate desired image in files w/ combined images */
484 error
= npe_findimage(sc
, (void *)fw
/*fw->data*/, imageId
, &imageCodePtr
, &imageSize
);
489 * If download was successful, store image Id in list of
490 * currently loaded images. If a critical error occured
491 * during download, record that the NPE has an invalid image
493 simple_lock(&sc
->sc_lock
);
494 error
= npe_load_image(sc
, imageCodePtr
, 1 /*VERIFY*/);
497 error
= ixpnpe_start_locked(sc
);
501 sc
->functionalityId
= IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId
);
502 simple_unlock(&sc
->sc_lock
);
504 DPRINTF(sc
->sc_dev
, "%s: error %d\n", __func__
, error
);
509 ixpnpe_getfunctionality(struct ixpnpe_softc
*sc
)
511 return (sc
->validImage
? sc
->functionalityId
: 0);
515 npe_checkbits(struct ixpnpe_softc
*sc
, uint32_t reg
, uint32_t expectedBitsSet
)
519 val
= npe_reg_read(sc
, reg
);
520 DPRINTFn(5, sc
->sc_dev
, "%s(0x%x, 0x%x) => 0x%x (%u)\n",
521 __func__
, reg
, expectedBitsSet
, val
,
522 (val
& expectedBitsSet
) == expectedBitsSet
);
523 return ((val
& expectedBitsSet
) == expectedBitsSet
);
527 npe_isstopped(struct ixpnpe_softc
*sc
)
529 return npe_checkbits(sc
,
530 IX_NPEDL_REG_OFFSET_EXCTL
, IX_NPEDL_EXCTL_STATUS_STOP
);
534 npe_load_ins(struct ixpnpe_softc
*sc
,
535 const IxNpeDlNpeMgrCodeBlock
*bp
, int verify
)
537 uint32_t npeMemAddress
;
540 npeMemAddress
= bp
->npeMemAddress
;
541 blockSize
= bp
->size
; /* NB: instruction/data count */
542 if (npeMemAddress
+ blockSize
> sc
->insMemSize
) {
543 printf("%s: Block size too big for NPE memory\n", sc
->sc_dev
.dv_xname
);
544 return EINVAL
; /* XXX */
546 for (i
= 0; i
< blockSize
; i
++, npeMemAddress
++) {
547 if (npe_ins_write(sc
, npeMemAddress
, bp
->data
[i
], verify
) != 0) {
548 printf("%s: NPE instruction write failed", sc
->sc_dev
.dv_xname
);
556 npe_load_data(struct ixpnpe_softc
*sc
,
557 const IxNpeDlNpeMgrCodeBlock
*bp
, int verify
)
559 uint32_t npeMemAddress
;
562 npeMemAddress
= bp
->npeMemAddress
;
563 blockSize
= bp
->size
; /* NB: instruction/data count */
564 if (npeMemAddress
+ blockSize
> sc
->dataMemSize
) {
565 printf("%s: Block size too big for NPE memory\n", sc
->sc_dev
.dv_xname
);
568 for (i
= 0; i
< blockSize
; i
++, npeMemAddress
++) {
569 if (npe_data_write(sc
, npeMemAddress
, bp
->data
[i
], verify
) != 0) {
570 printf("%s: NPE data write failed\n", sc
->sc_dev
.dv_xname
);
578 npe_load_stateinfo(struct ixpnpe_softc
*sc
,
579 const IxNpeDlNpeMgrStateInfoBlock
*bp
, int verify
)
581 int i
, nentries
, error
;
583 npe_cpu_step_save(sc
);
585 /* for each state-info context register entry in block */
586 nentries
= bp
->size
/ IX_NPEDL_STATE_INFO_ENTRY_SIZE
;
588 for (i
= 0; i
< nentries
; i
++) {
589 /* each state-info entry is 2 words (address, value) in length */
590 uint32_t regVal
= bp
->ctxtRegEntry
[i
].value
;
591 uint32_t addrInfo
= bp
->ctxtRegEntry
[i
].addressInfo
;
593 uint32_t reg
= (addrInfo
& IX_NPEDL_MASK_STATE_ADDR_CTXT_REG
);
594 uint32_t cNum
= (addrInfo
& IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM
) >>
595 IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM
;
597 /* error-check Context Register No. and Context Number values */
598 if (!(0 <= reg
&& reg
< IX_NPEDL_CTXT_REG_MAX
)) {
599 printf("%s: invalid Context Register %u\n", sc
->sc_dev
.dv_xname
,
604 if (!(0 <= cNum
&& cNum
< IX_NPEDL_CTXT_NUM_MAX
)) {
605 printf("%s: invalid Context Number %u\n", sc
->sc_dev
.dv_xname
,
610 /* NOTE that there is no STEVT register for Context 0 */
611 if (cNum
== 0 && reg
== IX_NPEDL_CTXT_REG_STEVT
) {
612 printf("%s: no STEVT for Context 0\n", sc
->sc_dev
.dv_xname
);
617 if (npe_ctx_reg_write(sc
, cNum
, reg
, regVal
, verify
) != 0) {
618 printf("%s: write of state-info to NPE failed\n",
619 sc
->sc_dev
.dv_xname
);
625 npe_cpu_step_restore(sc
);
630 npe_load_image(struct ixpnpe_softc
*sc
,
631 const uint32_t *imageCodePtr
, int verify
)
633 #define EOM(marker) ((marker) == IX_NPEDL_END_OF_DOWNLOAD_MAP)
634 const IxNpeDlNpeMgrDownloadMap
*downloadMap
;
637 if (!npe_isstopped(sc
)) { /* verify NPE is stopped */
638 printf("%s: cannot load image, NPE not stopped\n", sc
->sc_dev
.dv_xname
);
643 * Read Download Map, checking each block type and calling
644 * appropriate function to perform download
647 downloadMap
= (const IxNpeDlNpeMgrDownloadMap
*) imageCodePtr
;
648 for (i
= 0; !EOM(downloadMap
->entry
[i
].eodmMarker
); i
++) {
649 /* calculate pointer to block to be downloaded */
650 const uint32_t *bp
= imageCodePtr
+ downloadMap
->entry
[i
].block
.offset
;
651 switch (downloadMap
->entry
[i
].block
.type
) {
652 case IX_NPEDL_BLOCK_TYPE_INSTRUCTION
:
653 error
= npe_load_ins(sc
,
654 (const IxNpeDlNpeMgrCodeBlock
*) bp
, verify
);
655 DPRINTF(sc
->sc_dev
, "%s: inst, error %d\n", __func__
, error
);
657 case IX_NPEDL_BLOCK_TYPE_DATA
:
658 error
= npe_load_data(sc
,
659 (const IxNpeDlNpeMgrCodeBlock
*) bp
, verify
);
660 DPRINTF(sc
->sc_dev
, "%s: data, error %d\n", __func__
, error
);
662 case IX_NPEDL_BLOCK_TYPE_STATE
:
663 error
= npe_load_stateinfo(sc
,
664 (const IxNpeDlNpeMgrStateInfoBlock
*) bp
, verify
);
665 DPRINTF(sc
->sc_dev
, "%s: state, error %d\n", __func__
, error
);
668 printf("%s: unknown block type 0x%x in download map\n",
669 sc
->sc_dev
.dv_xname
, downloadMap
->entry
[i
].block
.type
);
670 error
= EIO
; /* XXX */
680 /* contains Reset values for Context Store Registers */
681 static const struct {
683 uint32_t regResetVal
;
684 } ixNpeDlEcsRegResetValues
[] = {
685 { IX_NPEDL_ECS_BG_CTXT_REG_0
, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET
},
686 { IX_NPEDL_ECS_BG_CTXT_REG_1
, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET
},
687 { IX_NPEDL_ECS_BG_CTXT_REG_2
, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET
},
688 { IX_NPEDL_ECS_PRI_1_CTXT_REG_0
, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET
},
689 { IX_NPEDL_ECS_PRI_1_CTXT_REG_1
, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET
},
690 { IX_NPEDL_ECS_PRI_1_CTXT_REG_2
, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET
},
691 { IX_NPEDL_ECS_PRI_2_CTXT_REG_0
, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET
},
692 { IX_NPEDL_ECS_PRI_2_CTXT_REG_1
, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET
},
693 { IX_NPEDL_ECS_PRI_2_CTXT_REG_2
, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET
},
694 { IX_NPEDL_ECS_DBG_CTXT_REG_0
, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET
},
695 { IX_NPEDL_ECS_DBG_CTXT_REG_1
, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET
},
696 { IX_NPEDL_ECS_DBG_CTXT_REG_2
, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET
},
697 { IX_NPEDL_ECS_INSTRUCT_REG
, IX_NPEDL_ECS_INSTRUCT_REG_RESET
}
700 /* contains Reset values for Context Store Registers */
701 static const uint32_t ixNpeDlCtxtRegResetValues
[] = {
702 IX_NPEDL_CTXT_REG_RESET_STEVT
,
703 IX_NPEDL_CTXT_REG_RESET_STARTPC
,
704 IX_NPEDL_CTXT_REG_RESET_REGMAP
,
705 IX_NPEDL_CTXT_REG_RESET_CINDEX
,
708 #define IX_NPEDL_RESET_NPE_PARITY 0x0800
709 #define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF
710 #define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF
713 npe_cpu_reset(struct ixpnpe_softc
*sc
)
715 #define N(a) (sizeof(a) / sizeof(a[0]))
716 uint32_t ctxtReg
; /* identifies Context Store reg (0-3) */
719 uint32_t resetNpeParity
;
720 uint32_t ixNpeConfigCtrlRegVal
;
723 /* pre-store the NPE Config Control Register Value */
724 ixNpeConfigCtrlRegVal
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_CTL
);
725 ixNpeConfigCtrlRegVal
|= 0x3F000000;
727 /* disable the parity interrupt */
728 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_CTL
,
729 (ixNpeConfigCtrlRegVal
& IX_NPEDL_PARITY_BIT_MASK
));
730 DPRINTFn(2, sc
->sc_dev
, "%s: dis parity int, CTL => 0x%x\n",
731 __func__
, ixNpeConfigCtrlRegVal
& IX_NPEDL_PARITY_BIT_MASK
);
733 npe_cpu_step_save(sc
);
738 while (npe_checkbits(sc
,
739 IX_NPEDL_REG_OFFSET_WFIFO
, IX_NPEDL_MASK_WFIFO_VALID
)) {
740 /* read from the Watch-point FIFO until empty */
741 (void) npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_WFIFO
);
744 while (npe_checkbits(sc
,
745 IX_NPEDL_REG_OFFSET_STAT
, IX_NPEDL_MASK_STAT_OFNE
)) {
746 /* read from the outFIFO until empty */
747 (void) npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_FIFO
);
750 while (npe_checkbits(sc
,
751 IX_NPEDL_REG_OFFSET_STAT
, IX_NPEDL_MASK_STAT_IFNE
)) {
753 * Step execution of the NPE intruction to read inFIFO using
754 * the Debug Executing Context stack.
756 error
= npe_cpu_step(sc
, IX_NPEDL_INSTR_RD_FIFO
, 0, 0);
758 DPRINTF(sc
->sc_dev
, "%s: cannot step (1), error %u\n",
760 npe_cpu_step_restore(sc
);
766 * Reset the mailbox reg
768 /* ...from XScale side */
769 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_MBST
, IX_NPEDL_REG_RESET_MBST
);
770 /* ...from NPE side */
771 error
= npe_cpu_step(sc
, IX_NPEDL_INSTR_RESET_MBOX
, 0, 0);
773 DPRINTF(sc
->sc_dev
, "%s: cannot step (2), error %u\n", __func__
, error
);
774 npe_cpu_step_restore(sc
);
779 * Reset the physical registers in the NPE register file:
780 * Note: no need to save/restore REGMAP for Context 0 here
781 * since all Context Store regs are reset in subsequent code.
784 regAddr
< IX_NPEDL_TOTAL_NUM_PHYS_REG
&& error
== 0;
786 /* for each physical register in the NPE reg file, write 0 : */
787 error
= npe_physical_reg_write(sc
, regAddr
, 0, true);
789 DPRINTF(sc
->sc_dev
, "%s: cannot write phy reg, error %u\n",
791 npe_cpu_step_restore(sc
);
792 return error
; /* abort reset */
797 * Reset the context store:
799 for (i
= IX_NPEDL_CTXT_NUM_MIN
; i
<= IX_NPEDL_CTXT_NUM_MAX
; i
++) {
800 /* set each context's Context Store registers to reset values: */
801 for (ctxtReg
= 0; ctxtReg
< IX_NPEDL_CTXT_REG_MAX
; ctxtReg
++) {
802 /* NOTE that there is no STEVT register for Context 0 */
803 if (!(i
== 0 && ctxtReg
== IX_NPEDL_CTXT_REG_STEVT
)) {
804 regVal
= ixNpeDlCtxtRegResetValues
[ctxtReg
];
805 error
= npe_ctx_reg_write(sc
, i
, ctxtReg
, regVal
, true);
807 DPRINTF(sc
->sc_dev
, "%s: cannot write ctx reg, error %u\n",
809 npe_cpu_step_restore(sc
);
810 return error
; /* abort reset */
816 npe_cpu_step_restore(sc
);
818 /* write Reset values to Execution Context Stack registers */
819 for (i
= 0; i
< N(ixNpeDlEcsRegResetValues
); i
++)
820 npe_ecs_reg_write(sc
,
821 ixNpeDlEcsRegResetValues
[i
].regAddr
,
822 ixNpeDlEcsRegResetValues
[i
].regResetVal
);
824 /* clear the profile counter */
825 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT
);
827 /* clear registers EXCT, AP0, AP1, AP2 and AP3 */
828 for (regAddr
= IX_NPEDL_REG_OFFSET_EXCT
;
829 regAddr
<= IX_NPEDL_REG_OFFSET_AP3
;
830 regAddr
+= sizeof(uint32_t))
831 npe_reg_write(sc
, regAddr
, 0);
833 /* Reset the Watch-count register */
834 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_WC
, 0);
837 * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
841 * Reset the NPE and its coprocessor - to reset internal
842 * states and remove parity error. Note this makes no
843 * sense based on the documentation. The feature control
844 * register always reads back as 0 on the ixp425 and further
845 * the bit definition of NPEA/NPEB is off by 1 according to
846 * the Intel documention--so we're blindly following the
847 * Intel code w/o any real understanding.
849 regVal
= EXP_BUS_READ_4(ixp425_softc
, EXP_FCTRL_OFFSET
);
850 DPRINTFn(2, sc
->sc_dev
, "%s: FCTRL 0x%x\n", __func__
, regVal
);
852 IX_NPEDL_RESET_NPE_PARITY
<< (1 + sc
->sc_unit
);
853 DPRINTFn(2, sc
->sc_dev
, "%s: FCTRL fuse parity, write 0x%x\n",
854 __func__
, regVal
| resetNpeParity
);
855 EXP_BUS_WRITE_4(ixp425_softc
, EXP_FCTRL_OFFSET
, regVal
| resetNpeParity
);
857 /* un-fuse and un-reset the NPE & coprocessor */
858 DPRINTFn(2, sc
->sc_dev
, "%s: FCTRL unfuse parity, write 0x%x\n",
859 __func__
, regVal
& ~resetNpeParity
);
860 EXP_BUS_WRITE_4(ixp425_softc
, EXP_FCTRL_OFFSET
, regVal
&~ resetNpeParity
);
863 * Call NpeMgr function to stop the NPE again after the Feature Control
864 * has unfused and Un-Reset the NPE and its associated Coprocessors.
866 error
= npe_cpu_stop(sc
);
868 /* restore NPE configuration bus Control Register - Parity Settings */
869 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_CTL
,
870 (ixNpeConfigCtrlRegVal
& IX_NPEDL_CONFIG_CTRL_REG_MASK
));
871 DPRINTFn(2, sc
->sc_dev
, "%s: restore CTL => 0x%x\n",
872 __func__
, npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_CTL
));
879 npe_cpu_start(struct ixpnpe_softc
*sc
)
884 * Ensure only Background Context Stack Level is Active by turning off
885 * the Active bit in each of the other Executing Context Stack levels.
887 ecsRegVal
= npe_ecs_reg_read(sc
, IX_NPEDL_ECS_PRI_1_CTXT_REG_0
);
888 ecsRegVal
&= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE
;
889 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_PRI_1_CTXT_REG_0
, ecsRegVal
);
891 ecsRegVal
= npe_ecs_reg_read(sc
, IX_NPEDL_ECS_PRI_2_CTXT_REG_0
);
892 ecsRegVal
&= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE
;
893 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_PRI_2_CTXT_REG_0
, ecsRegVal
);
895 ecsRegVal
= npe_ecs_reg_read(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_0
);
896 ecsRegVal
&= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE
;
897 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_0
, ecsRegVal
);
899 /* clear the pipeline */
900 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE
);
902 /* start NPE execution by issuing command through EXCTL register on NPE */
903 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_NPE_START
);
906 * Check execution status of NPE to verify operation was successful.
908 return npe_checkbits(sc
,
909 IX_NPEDL_REG_OFFSET_EXCTL
, IX_NPEDL_EXCTL_STATUS_RUN
) ? 0 : EIO
;
913 npe_cpu_stop(struct ixpnpe_softc
*sc
)
915 /* stop NPE execution by issuing command through EXCTL register on NPE */
916 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_NPE_STOP
);
918 /* verify that NPE Stop was successful */
919 return npe_checkbits(sc
,
920 IX_NPEDL_REG_OFFSET_EXCTL
, IX_NPEDL_EXCTL_STATUS_STOP
) ? 0 : EIO
;
923 #define IX_NPEDL_REG_SIZE_BYTE 8
924 #define IX_NPEDL_REG_SIZE_SHORT 16
925 #define IX_NPEDL_REG_SIZE_WORD 32
928 * Introduce extra read cycles after issuing read command to NPE
929 * so that we read the register after the NPE has updated it
930 * This is to overcome race condition between XScale and NPE
932 #define IX_NPEDL_DELAY_READ_CYCLES 2
934 * To mask top three MSBs of 32bit word to download into NPE IMEM
936 #define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF;
939 npe_cmd_issue_write(struct ixpnpe_softc
*sc
,
940 uint32_t cmd
, uint32_t addr
, uint32_t data
)
942 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXDATA
, data
);
943 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXAD
, addr
);
944 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXCTL
, cmd
);
948 npe_cmd_issue_read(struct ixpnpe_softc
*sc
, uint32_t cmd
, uint32_t addr
)
953 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXAD
, addr
);
954 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXCTL
, cmd
);
955 for (i
= 0; i
<= IX_NPEDL_DELAY_READ_CYCLES
; i
++)
956 data
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_EXDATA
);
961 npe_ins_write(struct ixpnpe_softc
*sc
, uint32_t addr
, uint32_t data
, int verify
)
963 DPRINTFn(4, sc
->sc_dev
, "%s(0x%x, 0x%x)\n", __func__
, addr
, data
);
964 npe_cmd_issue_write(sc
, IX_NPEDL_EXCTL_CMD_WR_INS_MEM
, addr
, data
);
969 * Write invalid data to this reg, so we can see if we're reading
970 * the EXDATA register too early.
972 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXDATA
, ~data
);
974 /* Disabled since top 3 MSB are not used for Azusa hardware Refer WR:IXA00053900*/
975 data
&= IX_NPEDL_MASK_UNUSED_IMEM_BITS
;
977 rdata
= npe_cmd_issue_read(sc
, IX_NPEDL_EXCTL_CMD_RD_INS_MEM
, addr
);
978 rdata
&= IX_NPEDL_MASK_UNUSED_IMEM_BITS
;
987 npe_data_write(struct ixpnpe_softc
*sc
, uint32_t addr
, uint32_t data
, int verify
)
989 DPRINTFn(4, sc
->sc_dev
, "%s(0x%x, 0x%x)\n", __func__
, addr
, data
);
990 npe_cmd_issue_write(sc
, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM
, addr
, data
);
993 * Write invalid data to this reg, so we can see if we're reading
994 * the EXDATA register too early.
996 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXDATA
, ~data
);
997 if (data
!= npe_cmd_issue_read(sc
, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM
, addr
))
1004 npe_ecs_reg_write(struct ixpnpe_softc
*sc
, uint32_t reg
, uint32_t data
)
1006 npe_cmd_issue_write(sc
, IX_NPEDL_EXCTL_CMD_WR_ECS_REG
, reg
, data
);
1010 npe_ecs_reg_read(struct ixpnpe_softc
*sc
, uint32_t reg
)
1012 return npe_cmd_issue_read(sc
, IX_NPEDL_EXCTL_CMD_RD_ECS_REG
, reg
);
1016 npe_issue_cmd(struct ixpnpe_softc
*sc
, uint32_t command
)
1018 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXCTL
, command
);
1022 npe_cpu_step_save(struct ixpnpe_softc
*sc
)
1024 /* turn off the halt bit by clearing Execution Count register. */
1025 /* save reg contents 1st and restore later */
1026 sc
->savedExecCount
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_EXCT
);
1027 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXCT
, 0);
1029 /* ensure that IF and IE are on (temporarily), so that we don't end up
1030 * stepping forever */
1031 sc
->savedEcsDbgCtxtReg2
= npe_ecs_reg_read(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_2
);
1033 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_2
,
1034 (sc
->savedEcsDbgCtxtReg2
| IX_NPEDL_MASK_ECS_DBG_REG_2_IF
|
1035 IX_NPEDL_MASK_ECS_DBG_REG_2_IE
));
1039 npe_cpu_step(struct ixpnpe_softc
*sc
, uint32_t npeInstruction
,
1040 uint32_t ctxtNum
, uint32_t ldur
)
1042 #define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000
1043 uint32_t ecsDbgRegVal
;
1044 uint32_t oldWatchcount
, newWatchcount
;
1047 /* set the Active bit, and the LDUR, in the debug level */
1048 ecsDbgRegVal
= IX_NPEDL_MASK_ECS_REG_0_ACTIVE
|
1049 (ldur
<< IX_NPEDL_OFFSET_ECS_REG_0_LDUR
);
1051 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_0
, ecsDbgRegVal
);
1054 * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the
1055 * instruction, and set SELCTXT at ECS DEBUG Level to specify which context
1057 * Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
1059 ecsDbgRegVal
= (ctxtNum
<< IX_NPEDL_OFFSET_ECS_REG_1_CCTXT
) |
1060 (ctxtNum
<< IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT
);
1062 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_1
, ecsDbgRegVal
);
1064 /* clear the pipeline */
1065 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE
);
1067 /* load NPE instruction into the instruction register */
1068 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_INSTRUCT_REG
, npeInstruction
);
1070 /* we need this value later to wait for completion of NPE execution step */
1071 oldWatchcount
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_WC
);
1073 /* issue a Step One command via the Execution Control register */
1074 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_NPE_STEP
);
1077 * Force the XScale to wait until the NPE has finished execution step
1078 * NOTE that this delay will be very small, just long enough to allow a
1079 * single NPE instruction to complete execution; if instruction execution
1080 * is not completed before timeout retries, exit the while loop.
1082 newWatchcount
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_WC
);
1083 for (tries
= 0; tries
< IX_NPE_DL_MAX_NUM_OF_RETRIES
&&
1084 newWatchcount
== oldWatchcount
; tries
++) {
1085 /* Watch Count register increments when NPE completes an instruction */
1086 newWatchcount
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_WC
);
1088 return (tries
< IX_NPE_DL_MAX_NUM_OF_RETRIES
) ? 0 : EIO
;
1089 #undef IX_NPE_DL_MAX_NUM_OF_RETRIES
1093 npe_cpu_step_restore(struct ixpnpe_softc
*sc
)
1095 /* clear active bit in debug level */
1096 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_0
, 0);
1098 /* clear the pipeline */
1099 npe_issue_cmd(sc
, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE
);
1101 /* restore Execution Count register contents. */
1102 npe_reg_write(sc
, IX_NPEDL_REG_OFFSET_EXCT
, sc
->savedExecCount
);
1104 /* restore IF and IE bits to original values */
1105 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_DBG_CTXT_REG_2
, sc
->savedEcsDbgCtxtReg2
);
1109 npe_logical_reg_read(struct ixpnpe_softc
*sc
,
1110 uint32_t regAddr
, uint32_t regSize
,
1111 uint32_t ctxtNum
, uint32_t *regVal
)
1113 uint32_t npeInstruction
, mask
;
1117 case IX_NPEDL_REG_SIZE_BYTE
:
1118 npeInstruction
= IX_NPEDL_INSTR_RD_REG_BYTE
;
1121 case IX_NPEDL_REG_SIZE_SHORT
:
1122 npeInstruction
= IX_NPEDL_INSTR_RD_REG_SHORT
;
1125 case IX_NPEDL_REG_SIZE_WORD
:
1126 npeInstruction
= IX_NPEDL_INSTR_RD_REG_WORD
;
1133 /* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */
1134 npeInstruction
|= (regAddr
<< IX_NPEDL_OFFSET_INSTR_SRC
) |
1135 (regAddr
<< IX_NPEDL_OFFSET_INSTR_DEST
);
1137 /* step execution of NPE intruction using Debug Executing Context stack */
1138 error
= npe_cpu_step(sc
, npeInstruction
, ctxtNum
, IX_NPEDL_RD_INSTR_LDUR
);
1140 DPRINTF(sc
->sc_dev
, "%s(0x%x, %u, %u), cannot step, error %d\n",
1141 __func__
, regAddr
, regSize
, ctxtNum
, error
);
1144 /* read value of register from Execution Data register */
1145 *regVal
= npe_reg_read(sc
, IX_NPEDL_REG_OFFSET_EXDATA
);
1147 /* align value from left to right */
1148 *regVal
= (*regVal
>> (IX_NPEDL_REG_SIZE_WORD
- regSize
)) & mask
;
1154 npe_logical_reg_write(struct ixpnpe_softc
*sc
, uint32_t regAddr
, uint32_t regVal
,
1155 uint32_t regSize
, uint32_t ctxtNum
, int verify
)
1159 DPRINTFn(4, sc
->sc_dev
, "%s(0x%x, 0x%x, %u, %u)\n",
1160 __func__
, regAddr
, regVal
, regSize
, ctxtNum
);
1161 if (regSize
== IX_NPEDL_REG_SIZE_WORD
) {
1162 /* NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3| */
1163 /* Write upper half-word (short) to |d0|d1| */
1164 error
= npe_logical_reg_write(sc
, regAddr
,
1165 regVal
>> IX_NPEDL_REG_SIZE_SHORT
,
1166 IX_NPEDL_REG_SIZE_SHORT
, ctxtNum
, verify
);
1170 /* Write lower half-word (short) to |d2|d3| */
1171 error
= npe_logical_reg_write(sc
,
1172 regAddr
+ sizeof(uint16_t),
1174 IX_NPEDL_REG_SIZE_SHORT
, ctxtNum
, verify
);
1176 uint32_t npeInstruction
;
1179 case IX_NPEDL_REG_SIZE_BYTE
:
1180 npeInstruction
= IX_NPEDL_INSTR_WR_REG_BYTE
;
1183 case IX_NPEDL_REG_SIZE_SHORT
:
1184 npeInstruction
= IX_NPEDL_INSTR_WR_REG_SHORT
;
1190 /* fill dest operand field of instruction with destination reg addr */
1191 npeInstruction
|= (regAddr
<< IX_NPEDL_OFFSET_INSTR_DEST
);
1193 /* fill src operand field of instruction with least-sig 5 bits of val*/
1194 npeInstruction
|= ((regVal
& IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA
) <<
1195 IX_NPEDL_OFFSET_INSTR_SRC
);
1197 /* fill coprocessor field of instruction with most-sig 11 bits of val*/
1198 npeInstruction
|= ((regVal
& IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA
) <<
1199 IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA
);
1201 /* step execution of NPE intruction using Debug ECS */
1202 error
= npe_cpu_step(sc
, npeInstruction
,
1203 ctxtNum
, IX_NPEDL_WR_INSTR_LDUR
);
1206 DPRINTF(sc
->sc_dev
, "%s(0x%x, 0x%x, %u, %u), error %u writing reg\n",
1207 __func__
, regAddr
, regVal
, regSize
, ctxtNum
, error
);
1213 error
= npe_logical_reg_read(sc
, regAddr
, regSize
, ctxtNum
, &retRegVal
);
1214 if (error
== 0 && regVal
!= retRegVal
)
1215 error
= EIO
; /* XXX ambiguous */
1221 * There are 32 physical registers used in an NPE. These are
1222 * treated as 16 pairs of 32-bit registers. To write one of the pair,
1223 * write the pair number (0-16) to the REGMAP for Context 0. Then write
1224 * the value to register 0 or 4 in the regfile, depending on which
1225 * register of the pair is to be written
1228 npe_physical_reg_write(struct ixpnpe_softc
*sc
,
1229 uint32_t regAddr
, uint32_t regValue
, int verify
)
1234 * Set REGMAP for context 0 to (regAddr >> 1) to choose which pair (0-16)
1235 * of physical registers to write .
1237 error
= npe_logical_reg_write(sc
, IX_NPEDL_CTXT_REG_ADDR_REGMAP
,
1238 (regAddr
>> IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP
),
1239 IX_NPEDL_REG_SIZE_SHORT
, 0, verify
);
1241 /* regAddr = 0 or 4 */
1242 regAddr
= (regAddr
& IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR
) *
1244 error
= npe_logical_reg_write(sc
, regAddr
, regValue
,
1245 IX_NPEDL_REG_SIZE_WORD
, 0, verify
);
1251 npe_ctx_reg_write(struct ixpnpe_softc
*sc
, uint32_t ctxtNum
,
1252 uint32_t ctxtReg
, uint32_t ctxtRegVal
, int verify
)
1254 DPRINTFn(4, sc
->sc_dev
, "%s(%u, %u, %u)\n",
1255 __func__
, ctxtNum
, ctxtReg
, ctxtRegVal
);
1257 * Context 0 has no STARTPC. Instead, this value is used to set
1258 * NextPC for Background ECS, to set where NPE starts executing code
1260 if (ctxtNum
== 0 && ctxtReg
== IX_NPEDL_CTXT_REG_STARTPC
) {
1261 /* read BG_CTXT_REG_0, update NEXTPC bits, and write back to reg */
1262 uint32_t v
= npe_ecs_reg_read(sc
, IX_NPEDL_ECS_BG_CTXT_REG_0
);
1263 v
&= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC
;
1264 v
|= (ctxtRegVal
<< IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC
) &
1265 IX_NPEDL_MASK_ECS_REG_0_NEXTPC
;
1267 npe_ecs_reg_write(sc
, IX_NPEDL_ECS_BG_CTXT_REG_0
, v
);
1270 static const struct {
1271 uint32_t regAddress
;
1273 } regAccInfo
[IX_NPEDL_CTXT_REG_MAX
] = {
1274 { IX_NPEDL_CTXT_REG_ADDR_STEVT
, IX_NPEDL_REG_SIZE_BYTE
},
1275 { IX_NPEDL_CTXT_REG_ADDR_STARTPC
, IX_NPEDL_REG_SIZE_SHORT
},
1276 { IX_NPEDL_CTXT_REG_ADDR_REGMAP
, IX_NPEDL_REG_SIZE_SHORT
},
1277 { IX_NPEDL_CTXT_REG_ADDR_CINDEX
, IX_NPEDL_REG_SIZE_BYTE
}
1279 return npe_logical_reg_write(sc
, regAccInfo
[ctxtReg
].regAddress
,
1280 ctxtRegVal
, regAccInfo
[ctxtReg
].regSize
, ctxtNum
, verify
);
1285 * NPE Mailbox support.
1287 #define IX_NPEMH_MAXTRIES 100000
1290 ixpnpe_ofifo_wait(struct ixpnpe_softc
*sc
)
1294 for (i
= 0; i
< IX_NPEMH_MAXTRIES
; i
++) {
1295 if (npe_reg_read(sc
, IX_NPESTAT
) & IX_NPESTAT_OFNE
)
1299 printf("%s: %s: timeout, last status 0x%x\n", sc
->sc_dev
.dv_xname
,
1300 __func__
, npe_reg_read(sc
, IX_NPESTAT
));
1305 ixpnpe_intr(void *arg
)
1307 struct ixpnpe_softc
*sc
= arg
;
1310 status
= npe_reg_read(sc
, IX_NPESTAT
);
1311 if ((status
& IX_NPESTAT_OFINT
) == 0) {
1312 /* NB: should not happen */
1313 printf("%s: %s: status 0x%x\n", sc
->sc_dev
.dv_xname
, __func__
, status
);
1314 /* XXX must silence interrupt? */
1318 * A message is waiting in the output FIFO, copy it so
1319 * the interrupt will be silenced; then signal anyone
1320 * waiting to collect the result.
1322 sc
->sc_msgwaiting
= -1; /* NB: error indicator */
1323 if (ixpnpe_ofifo_wait(sc
)) {
1324 sc
->sc_msg
[0] = npe_reg_read(sc
, IX_NPEFIFO
);
1325 if (ixpnpe_ofifo_wait(sc
)) {
1326 sc
->sc_msg
[1] = npe_reg_read(sc
, IX_NPEFIFO
);
1327 sc
->sc_msgwaiting
= 1; /* successful fetch */
1330 if (sc
->sc_msg
[0] == (NPE_MACRECOVERYSTART
<< NPE_MAC_MSGID_SHL
)) {
1334 delay(100); /* delay 100usec */
1335 if (sc
->macresetcbfunc
!= NULL
)
1336 sc
->macresetcbfunc(sc
->macresetcbarg
);
1341 /* XXX Too dangerous! see ixpnpe_recvmsg_locked() */
1349 ixpnpe_ififo_wait(struct ixpnpe_softc
*sc
)
1353 for (i
= 0; i
< IX_NPEMH_MAXTRIES
; i
++) {
1354 if (npe_reg_read(sc
, IX_NPESTAT
) & IX_NPESTAT_IFNF
)
1362 ixpnpe_sendmsg_locked(struct ixpnpe_softc
*sc
, const uint32_t msg
[2])
1366 sc
->sc_msgwaiting
= 0;
1367 if (ixpnpe_ififo_wait(sc
)) {
1368 npe_reg_write(sc
, IX_NPEFIFO
, msg
[0]);
1369 if (ixpnpe_ififo_wait(sc
))
1370 npe_reg_write(sc
, IX_NPEFIFO
, msg
[1]);
1377 printf("%s: input FIFO timeout, msg [0x%x,0x%x]\n",
1378 sc
->sc_dev
.dv_xname
, msg
[0], msg
[1]);
1383 ixpnpe_recvmsg_locked(struct ixpnpe_softc
*sc
, uint32_t msg
[2])
1386 if (!sc
->sc_msgwaiting
) {
1389 * This ltsleep() is dangerous because this function may be
1390 * called under interrupt context.
1392 ltsleep(sc
, 0, "npemh", 0, &sc
->sc_lock
);
1394 delay(1000); /* wait 1ms (is it ok?)*/
1397 memcpy(msg
, sc
->sc_msg
, sizeof(sc
->sc_msg
));
1398 /* NB: sc_msgwaiting != 1 means the ack fetch failed */
1399 return sc
->sc_msgwaiting
!= 1 ? EIO
: 0;
1403 * Send a msg to the NPE and wait for a reply. We use the
1404 * private mutex and sleep until an interrupt is received
1405 * signalling the availability of data in the output FIFO
1406 * so the caller cannot be holding a mutex. May be better
1407 * piggyback on the caller's mutex instead but that would
1408 * make other locking confusing.
1411 ixpnpe_sendandrecvmsg(struct ixpnpe_softc
*sc
,
1412 const uint32_t send
[2], uint32_t recv
[2])
1416 simple_lock(&sc
->sc_lock
);
1417 error
= ixpnpe_sendmsg_locked(sc
, send
);
1419 error
= ixpnpe_recvmsg_locked(sc
, recv
);
1420 simple_unlock(&sc
->sc_lock
);
1425 /* XXX temporary, not reliable */
1428 ixpnpe_sendmsg(struct ixpnpe_softc
*sc
, const uint32_t msg
[2])
1432 simple_lock(&sc
->sc_lock
);
1433 error
= ixpnpe_sendmsg_locked(sc
, msg
);
1434 simple_unlock(&sc
->sc_lock
);
1440 ixpnpe_recvmsg(struct ixpnpe_softc
*sc
, uint32_t msg
[2])
1444 simple_lock(&sc
->sc_lock
);
1445 if (sc
->sc_msgwaiting
)
1446 memcpy(msg
, sc
->sc_msg
, sizeof(sc
->sc_msg
));
1447 /* NB: sc_msgwaiting != 1 means the ack fetch failed */
1448 error
= sc
->sc_msgwaiting
!= 1 ? EIO
: 0;
1449 simple_unlock(&sc
->sc_lock
);