ixp425_npe.c revision 1.3 1 /* $NetBSD: ixp425_npe.c,v 1.3 2008/01/08 02:07:53 matt Exp $ */
2
3 /*-
4 * Copyright (c) 2006 Sam Leffler, Errno Consulting
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
17 *
18 * NO WARRANTY
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.
30 */
31
32 /*-
33 * Copyright (c) 2001-2005, Intel Corporation.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
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.
47 *
48 *
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
59 * SUCH DAMAGE.
60 */
61 #include <sys/cdefs.h>
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 $");
64 #endif
65 __KERNEL_RCSID(0, "$NetBSD: ixp425_npe.c,v 1.3 2008/01/08 02:07:53 matt Exp $");
66
67 /*
68 * Intel XScale Network Processing Engine (NPE) support.
69 *
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).
76 *
77 * The code here basically replaces the npeDl and npeMh classes
78 * in the Intel Access Library (IAL).
79 *
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.
84 */
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>
90 #include <sys/time.h>
91 #include <sys/proc.h>
92
93 #include <dev/firmload.h>
94
95 #include <machine/bus.h>
96 #include <machine/cpu.h>
97 #include <machine/intr.h>
98
99 #include <arm/xscale/ixp425reg.h>
100 #include <arm/xscale/ixp425var.h>
101 #include <arm/xscale/ixp425_ixmevar.h>
102
103 #include <arm/xscale/ixp425_npereg.h>
104 #include <arm/xscale/ixp425_npevar.h>
105
106 #include "locators.h"
107
108 struct ixpnpe_softc {
109 struct device sc_dev;
110 bus_dma_tag_t sc_dt;
111 bus_space_tag_t sc_iot;
112 bus_space_handle_t sc_ioh;
113 bus_size_t sc_size; /* size of mapped register window */
114 int sc_unit;
115 void *sc_ih; /* interrupt handler */
116 struct simplelock sc_lock; /* mailbox lock */
117 uint32_t sc_msg[2]; /* reply msg collected in ixpnpe_intr */
118 int sc_msgwaiting; /* sc_msg holds valid data */
119
120 int validImage; /* valid ucode image loaded */
121 int started; /* NPE is started */
122 uint8_t functionalityId;/* ucode functionality ID */
123 int insMemSize; /* size of instruction memory */
124 int dataMemSize; /* size of data memory */
125 uint32_t savedExecCount;
126 uint32_t savedEcsDbgCtxtReg2;
127 };
128
129 /*
130 * IXP425_NPE_MICROCODE will be defined by ixp425-fw.mk IFF the
131 * microcode object file exists in sys/arch/arm/xscale.
132 *
133 * To permit building the NPE drivers without microcode (so they
134 * don't bitrot due to lack of use), we use "empty" microcode so
135 * that the NPE drivers will simply fail to start at runtime.
136 */
137 #ifdef IXP425_NPE_MICROCODE
138 extern char _binary_IxNpeMicrocode_dat_start[];
139 #else
140 static char _binary_IxNpeMicrocode_dat_start[] = {
141 0xfe, 0xed, 0xf0, 0x0d, 0xfe, 0xed, 0xf0, 0x0d
142 };
143 #endif
144
145 #define IX_NPEDL_NPEIMAGE_FIELD_MASK 0xff
146
147 /* used to read download map from version in microcode image */
148 #define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000
149 #define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001
150 #define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002
151 #define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F
152
153 /*
154 * masks used to extract address info from State information context
155 * register addresses as read from microcode image
156 */
157 #define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F
158 #define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0
159
160 /* LSB offset of Context Number field in State-Info Context Address */
161 #define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4
162
163 /* size (in words) of single State Information entry (ctxt reg address|data) */
164 #define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2
165
166 typedef struct {
167 uint32_t type;
168 uint32_t offset;
169 } IxNpeDlNpeMgrDownloadMapBlockEntry;
170
171 typedef union {
172 IxNpeDlNpeMgrDownloadMapBlockEntry block;
173 uint32_t eodmMarker;
174 } IxNpeDlNpeMgrDownloadMapEntry;
175
176 typedef struct {
177 /* 1st entry in the download map (there may be more than one) */
178 IxNpeDlNpeMgrDownloadMapEntry entry[1];
179 } IxNpeDlNpeMgrDownloadMap;
180
181 /* used to access an instruction or data block in a microcode image */
182 typedef struct {
183 uint32_t npeMemAddress;
184 uint32_t size;
185 uint32_t data[1];
186 } IxNpeDlNpeMgrCodeBlock;
187
188 /* used to access each Context Reg entry state-information block */
189 typedef struct {
190 uint32_t addressInfo;
191 uint32_t value;
192 } IxNpeDlNpeMgrStateInfoCtxtRegEntry;
193
194 /* used to access a state-information block in a microcode image */
195 typedef struct {
196 uint32_t size;
197 IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
198 } IxNpeDlNpeMgrStateInfoBlock;
199
200 static int npe_debug = 0;
201 #define DPRINTF(dev, fmt, ...) do { \
202 if (npe_debug) printf(fmt, __VA_ARGS__); \
203 } while (0)
204 #define DPRINTFn(n, dev, fmt, ...) do { \
205 if (npe_debug >= n) printf(fmt, __VA_ARGS__); \
206 } while (0)
207
208 static int npe_checkbits(struct ixpnpe_softc *, uint32_t reg, uint32_t);
209 static int npe_isstopped(struct ixpnpe_softc *);
210 static int npe_load_ins(struct ixpnpe_softc *,
211 const IxNpeDlNpeMgrCodeBlock *bp, int verify);
212 static int npe_load_data(struct ixpnpe_softc *,
213 const IxNpeDlNpeMgrCodeBlock *bp, int verify);
214 static int npe_load_stateinfo(struct ixpnpe_softc *,
215 const IxNpeDlNpeMgrStateInfoBlock *bp, int verify);
216 static int npe_load_image(struct ixpnpe_softc *,
217 const uint32_t *imageCodePtr, int verify);
218 static int npe_cpu_reset(struct ixpnpe_softc *);
219 static int npe_cpu_start(struct ixpnpe_softc *);
220 static int npe_cpu_stop(struct ixpnpe_softc *);
221 static void npe_cmd_issue_write(struct ixpnpe_softc *,
222 uint32_t cmd, uint32_t addr, uint32_t data);
223 static uint32_t npe_cmd_issue_read(struct ixpnpe_softc *,
224 uint32_t cmd, uint32_t addr);
225 static int npe_ins_write(struct ixpnpe_softc *,
226 uint32_t addr, uint32_t data, int verify);
227 static int npe_data_write(struct ixpnpe_softc *,
228 uint32_t addr, uint32_t data, int verify);
229 static void npe_ecs_reg_write(struct ixpnpe_softc *,
230 uint32_t reg, uint32_t data);
231 static uint32_t npe_ecs_reg_read(struct ixpnpe_softc *, uint32_t reg);
232 static void npe_issue_cmd(struct ixpnpe_softc *, uint32_t command);
233 static void npe_cpu_step_save(struct ixpnpe_softc *);
234 static int npe_cpu_step(struct ixpnpe_softc *, uint32_t npeInstruction,
235 uint32_t ctxtNum, uint32_t ldur);
236 static void npe_cpu_step_restore(struct ixpnpe_softc *);
237 static int npe_logical_reg_read(struct ixpnpe_softc *,
238 uint32_t regAddr, uint32_t regSize,
239 uint32_t ctxtNum, uint32_t *regVal);
240 static int npe_logical_reg_write(struct ixpnpe_softc *,
241 uint32_t regAddr, uint32_t regVal,
242 uint32_t regSize, uint32_t ctxtNum, int verify);
243 static int npe_physical_reg_write(struct ixpnpe_softc *,
244 uint32_t regAddr, uint32_t regValue, int verify);
245 static int npe_ctx_reg_write(struct ixpnpe_softc *, uint32_t ctxtNum,
246 uint32_t ctxtReg, uint32_t ctxtRegVal, int verify);
247
248 static int ixpnpe_intr(void *arg);
249
250 static uint32_t
251 npe_reg_read(struct ixpnpe_softc *sc, bus_size_t off)
252 {
253 uint32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, off);
254 DPRINTFn(9, sc->sc_dev, "%s(0x%lx) => 0x%x\n", __func__, off, v);
255 return v;
256 }
257
258 static void
259 npe_reg_write(struct ixpnpe_softc *sc, bus_size_t off, uint32_t val)
260 {
261 DPRINTFn(9, sc->sc_dev, "%s(0x%lx, 0x%x)\n", __func__, off, val);
262 bus_space_write_4(sc->sc_iot, sc->sc_ioh, off, val);
263 }
264
265 static int ixpnpe_match(struct device *, struct cfdata *, void *);
266 static void ixpnpe_attach(struct device *, struct device *, void *);
267 static int ixpnpe_print(void *, const char *);
268 static int ixpnpe_search(struct device *, struct cfdata *, const int *,
269 void *);
270
271 CFATTACH_DECL(ixpnpe, sizeof(struct ixpnpe_softc),
272 ixpnpe_match, ixpnpe_attach, NULL, NULL);
273
274 static int
275 ixpnpe_match(struct device *parent, struct cfdata *match, void *arg)
276 {
277 struct ixme_attach_args *ixa = arg;
278
279 return (ixa->ixa_npe == 1 || ixa->ixa_npe == 2);
280 }
281
282 static void
283 ixpnpe_attach(struct device *parent, struct device *self, void *arg)
284 {
285 struct ixpnpe_softc *sc = (void *)self;
286 struct ixme_attach_args *ixa = arg;
287 bus_addr_t base;
288 int irq;
289
290 aprint_naive("\n");
291 aprint_normal("\n");
292
293 sc->sc_iot = ixa->ixa_iot;
294 sc->sc_dt = ixa->ixa_dt;
295 sc->sc_unit = ixa->ixa_npe;
296
297 simple_lock_init(&sc->sc_lock);
298
299 /* XXX: Check features to ensure this NPE is enabled */
300
301 switch (ixa->ixa_npe) {
302 default:
303 panic("%s: Invalid NPE!", sc->sc_dev.dv_xname);
304
305 case 1:
306 base = IXP425_NPE_B_HWBASE;
307 sc->sc_size = IXP425_NPE_B_SIZE;
308 irq = IXP425_INT_NPE_B;
309
310 /* size of instruction memory */
311 sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB;
312 /* size of data memory */
313 sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB;
314 break;
315
316 case 2:
317 base = IXP425_NPE_C_HWBASE;
318 sc->sc_size = IXP425_NPE_C_SIZE;
319 irq = IXP425_INT_NPE_C;
320
321 /* size of instruction memory */
322 sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC;
323 /* size of data memory */
324 sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC;
325 break;
326 }
327 if (bus_space_map(sc->sc_iot, base, sc->sc_size, 0, &sc->sc_ioh))
328 panic("%s: Cannot map registers", sc->sc_dev.dv_xname);
329
330 /*
331 * Setup IRQ and handler for NPE message support.
332 */
333 sc->sc_ih = ixp425_intr_establish(irq, IPL_NET, ixpnpe_intr, sc);
334 if (sc->sc_ih == NULL)
335 panic("%s: Unable to establish irq %u", sc->sc_dev.dv_xname, irq);
336 /* enable output fifo interrupts (NB: must also set OFIFO Write Enable) */
337 npe_reg_write(sc, IX_NPECTL,
338 npe_reg_read(sc, IX_NPECTL) | (IX_NPECTL_OFE | IX_NPECTL_OFWE));
339
340 config_search_ia(ixpnpe_search, self, "ixpnpe", ixa);
341 }
342
343 static int
344 ixpnpe_print(void *arg, const char *name)
345 {
346
347 return (UNCONF);
348 }
349
350 static int
351 ixpnpe_search(struct device *parent, struct cfdata *cf, const int *ldesc,
352 void *arg)
353 {
354 struct ixpnpe_softc *sc = (void *)parent;
355 struct ixme_attach_args *ixa = arg;
356 struct ixpnpe_attach_args na;
357
358 na.na_unit = ixa->ixa_npe;
359 na.na_phy = cf->cf_loc[IXPNPECF_PHY];
360 na.na_npe = sc;
361 na.na_iot = ixa->ixa_iot;
362 na.na_dt = ixa->ixa_dt;
363
364 if (config_match(parent, cf, &na) > 0) {
365 config_attach(parent, cf, &na, ixpnpe_print);
366 return (1);
367 }
368
369 return (0);
370 }
371
372 int
373 ixpnpe_stopandreset(struct ixpnpe_softc *sc)
374 {
375 int error;
376
377 simple_lock(&sc->sc_lock);
378 error = npe_cpu_stop(sc); /* stop NPE */
379 if (error == 0)
380 error = npe_cpu_reset(sc); /* reset it */
381 if (error == 0)
382 sc->started = 0; /* mark stopped */
383 simple_unlock(&sc->sc_lock);
384
385 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
386 return error;
387 }
388
389 static int
390 ixpnpe_start_locked(struct ixpnpe_softc *sc)
391 {
392 int error;
393
394 if (!sc->started) {
395 error = npe_cpu_start(sc);
396 if (error == 0)
397 sc->started = 1;
398 } else
399 error = 0;
400
401 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
402 return error;
403 }
404
405 int
406 ixpnpe_start(struct ixpnpe_softc *sc)
407 {
408 int ret;
409
410 simple_lock(&sc->sc_lock);
411 ret = ixpnpe_start_locked(sc);
412 simple_unlock(&sc->sc_lock);
413 return (ret);
414 }
415
416 int
417 ixpnpe_stop(struct ixpnpe_softc *sc)
418 {
419 int error;
420
421 simple_lock(&sc->sc_lock);
422 error = npe_cpu_stop(sc);
423 if (error == 0)
424 sc->started = 0;
425 simple_unlock(&sc->sc_lock);
426
427 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
428 return error;
429 }
430
431 /*
432 * Indicates the start of an NPE Image, in new NPE Image Library format.
433 * 2 consecutive occurances indicates the end of the NPE Image Library
434 */
435 #define NPE_IMAGE_MARKER 0xfeedf00d
436
437 /*
438 * NPE Image Header definition, used in new NPE Image Library format
439 */
440 typedef struct {
441 uint32_t marker;
442 uint32_t id;
443 uint32_t size;
444 } IxNpeDlImageMgrImageHeader;
445
446 static int
447 npe_findimage(struct ixpnpe_softc *sc,
448 const uint32_t *imageLibrary, uint32_t imageId,
449 const uint32_t **imagePtr, uint32_t *imageSize)
450 {
451 const IxNpeDlImageMgrImageHeader *image;
452 uint32_t offset = 0;
453
454 while (imageLibrary[offset] == NPE_IMAGE_MARKER) {
455 image = (const IxNpeDlImageMgrImageHeader *)&imageLibrary[offset];
456 offset += sizeof(IxNpeDlImageMgrImageHeader)/sizeof(uint32_t);
457
458 DPRINTF(sc->sc_dev, "%s: off %u mark 0x%x id 0x%x size %u\n",
459 __func__, offset, image->marker, image->id, image->size);
460 if (image->id == imageId) {
461 *imagePtr = imageLibrary + offset;
462 *imageSize = image->size;
463 return 0;
464 }
465 /* 2 consecutive NPE_IMAGE_MARKER's indicates end of library */
466 if (image->id == NPE_IMAGE_MARKER) {
467 printf("%s: imageId 0x%08x not found in image library header\n",
468 sc->sc_dev.dv_xname, imageId);
469 /* reached end of library, image not found */
470 return EIO;
471 }
472 offset += image->size;
473 }
474 return EIO;
475 }
476
477 int
478 ixpnpe_init(struct ixpnpe_softc *sc, const char *imageName, uint32_t imageId)
479 {
480 uint32_t imageSize;
481 const uint32_t *imageCodePtr;
482 void *fw;
483 int error;
484
485 DPRINTF(sc->sc_dev, "load %s, imageId 0x%08x\n", imageName, imageId);
486
487 #if 0
488 IxFeatureCtrlDeviceId devid = IX_NPEDL_DEVICEID_FROM_IMAGEID_GET(imageId);
489 /*
490 * Checking if image being loaded is meant for device that is running.
491 * Image is forward compatible. i.e Image built for IXP42X should run
492 * on IXP46X but not vice versa.
493 */
494 if (devid > (ixFeatureCtrlDeviceRead() & IX_FEATURE_CTRL_DEVICE_TYPE_MASK))
495 return EINVAL;
496 #endif
497 error = ixpnpe_stopandreset(sc); /* stop and reset the NPE */
498 if (error != 0)
499 return error;
500
501 fw = (void *)_binary_IxNpeMicrocode_dat_start;
502
503 /* Locate desired image in files w/ combined images */
504 error = npe_findimage(sc, (void *)fw /*fw->data*/, imageId, &imageCodePtr, &imageSize);
505 if (error != 0)
506 goto done;
507
508 /*
509 * If download was successful, store image Id in list of
510 * currently loaded images. If a critical error occured
511 * during download, record that the NPE has an invalid image
512 */
513 simple_lock(&sc->sc_lock);
514 error = npe_load_image(sc, imageCodePtr, 1 /*VERIFY*/);
515 if (error == 0) {
516 sc->validImage = 1;
517 error = ixpnpe_start_locked(sc);
518 } else {
519 sc->validImage = 0;
520 }
521 sc->functionalityId = IX_NPEDL_FUNCTIONID_FROM_IMAGEID_GET(imageId);
522 simple_unlock(&sc->sc_lock);
523 done:
524 DPRINTF(sc->sc_dev, "%s: error %d\n", __func__, error);
525 return error;
526 }
527
528 int
529 ixpnpe_getfunctionality(struct ixpnpe_softc *sc)
530 {
531 return (sc->validImage ? sc->functionalityId : 0);
532 }
533
534 static int
535 npe_checkbits(struct ixpnpe_softc *sc, uint32_t reg, uint32_t expectedBitsSet)
536 {
537 uint32_t val;
538
539 val = npe_reg_read(sc, reg);
540 DPRINTFn(5, sc->sc_dev, "%s(0x%x, 0x%x) => 0x%x (%u)\n",
541 __func__, reg, expectedBitsSet, val,
542 (val & expectedBitsSet) == expectedBitsSet);
543 return ((val & expectedBitsSet) == expectedBitsSet);
544 }
545
546 static int
547 npe_isstopped(struct ixpnpe_softc *sc)
548 {
549 return npe_checkbits(sc,
550 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP);
551 }
552
553 static int
554 npe_load_ins(struct ixpnpe_softc *sc,
555 const IxNpeDlNpeMgrCodeBlock *bp, int verify)
556 {
557 uint32_t npeMemAddress;
558 int i, blockSize;
559
560 npeMemAddress = bp->npeMemAddress;
561 blockSize = bp->size; /* NB: instruction/data count */
562 if (npeMemAddress + blockSize > sc->insMemSize) {
563 printf("%s: Block size too big for NPE memory\n", sc->sc_dev.dv_xname);
564 return EINVAL; /* XXX */
565 }
566 for (i = 0; i < blockSize; i++, npeMemAddress++) {
567 if (npe_ins_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
568 printf("%s: NPE instruction write failed", sc->sc_dev.dv_xname);
569 return EIO;
570 }
571 }
572 return 0;
573 }
574
575 static int
576 npe_load_data(struct ixpnpe_softc *sc,
577 const IxNpeDlNpeMgrCodeBlock *bp, int verify)
578 {
579 uint32_t npeMemAddress;
580 int i, blockSize;
581
582 npeMemAddress = bp->npeMemAddress;
583 blockSize = bp->size; /* NB: instruction/data count */
584 if (npeMemAddress + blockSize > sc->dataMemSize) {
585 printf("%s: Block size too big for NPE memory\n", sc->sc_dev.dv_xname);
586 return EINVAL;
587 }
588 for (i = 0; i < blockSize; i++, npeMemAddress++) {
589 if (npe_data_write(sc, npeMemAddress, bp->data[i], verify) != 0) {
590 printf("%s: NPE data write failed\n", sc->sc_dev.dv_xname);
591 return EIO;
592 }
593 }
594 return 0;
595 }
596
597 static int
598 npe_load_stateinfo(struct ixpnpe_softc *sc,
599 const IxNpeDlNpeMgrStateInfoBlock *bp, int verify)
600 {
601 int i, nentries, error;
602
603 npe_cpu_step_save(sc);
604
605 /* for each state-info context register entry in block */
606 nentries = bp->size / IX_NPEDL_STATE_INFO_ENTRY_SIZE;
607 error = 0;
608 for (i = 0; i < nentries; i++) {
609 /* each state-info entry is 2 words (address, value) in length */
610 uint32_t regVal = bp->ctxtRegEntry[i].value;
611 uint32_t addrInfo = bp->ctxtRegEntry[i].addressInfo;
612
613 uint32_t reg = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
614 uint32_t cNum = (addrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
615 IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
616
617 /* error-check Context Register No. and Context Number values */
618 if (!(0 <= reg && reg < IX_NPEDL_CTXT_REG_MAX)) {
619 printf("%s: invalid Context Register %u\n", sc->sc_dev.dv_xname,
620 reg);
621 error = EINVAL;
622 break;
623 }
624 if (!(0 <= cNum && cNum < IX_NPEDL_CTXT_NUM_MAX)) {
625 printf("%s: invalid Context Number %u\n", sc->sc_dev.dv_xname,
626 cNum);
627 error = EINVAL;
628 break;
629 }
630 /* NOTE that there is no STEVT register for Context 0 */
631 if (cNum == 0 && reg == IX_NPEDL_CTXT_REG_STEVT) {
632 printf("%s: no STEVT for Context 0\n", sc->sc_dev.dv_xname);
633 error = EINVAL;
634 break;
635 }
636
637 if (npe_ctx_reg_write(sc, cNum, reg, regVal, verify) != 0) {
638 printf("%s: write of state-info to NPE failed\n",
639 sc->sc_dev.dv_xname);
640 error = EIO;
641 break;
642 }
643 }
644
645 npe_cpu_step_restore(sc);
646 return error;
647 }
648
649 static int
650 npe_load_image(struct ixpnpe_softc *sc,
651 const uint32_t *imageCodePtr, int verify)
652 {
653 #define EOM(marker) ((marker) == IX_NPEDL_END_OF_DOWNLOAD_MAP)
654 const IxNpeDlNpeMgrDownloadMap *downloadMap;
655 int i, error;
656
657 if (!npe_isstopped(sc)) { /* verify NPE is stopped */
658 printf("%s: cannot load image, NPE not stopped\n", sc->sc_dev.dv_xname);
659 return EIO;
660 }
661
662 /*
663 * Read Download Map, checking each block type and calling
664 * appropriate function to perform download
665 */
666 error = 0;
667 downloadMap = (const IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
668 for (i = 0; !EOM(downloadMap->entry[i].eodmMarker); i++) {
669 /* calculate pointer to block to be downloaded */
670 const uint32_t *bp = imageCodePtr + downloadMap->entry[i].block.offset;
671 switch (downloadMap->entry[i].block.type) {
672 case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
673 error = npe_load_ins(sc,
674 (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
675 DPRINTF(sc->sc_dev, "%s: inst, error %d\n", __func__, error);
676 break;
677 case IX_NPEDL_BLOCK_TYPE_DATA:
678 error = npe_load_data(sc,
679 (const IxNpeDlNpeMgrCodeBlock *) bp, verify);
680 DPRINTF(sc->sc_dev, "%s: data, error %d\n", __func__, error);
681 break;
682 case IX_NPEDL_BLOCK_TYPE_STATE:
683 error = npe_load_stateinfo(sc,
684 (const IxNpeDlNpeMgrStateInfoBlock *) bp, verify);
685 DPRINTF(sc->sc_dev, "%s: state, error %d\n", __func__, error);
686 break;
687 default:
688 printf("%s: unknown block type 0x%x in download map\n",
689 sc->sc_dev.dv_xname, downloadMap->entry[i].block.type);
690 error = EIO; /* XXX */
691 break;
692 }
693 if (error != 0)
694 break;
695 }
696 return error;
697 #undef EOM
698 }
699
700 /* contains Reset values for Context Store Registers */
701 static const struct {
702 uint32_t regAddr;
703 uint32_t regResetVal;
704 } ixNpeDlEcsRegResetValues[] = {
705 { IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET },
706 { IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET },
707 { IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET },
708 { IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET },
709 { IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET },
710 { IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET },
711 { IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET },
712 { IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET },
713 { IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET },
714 { IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET },
715 { IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET },
716 { IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET },
717 { IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET }
718 };
719
720 /* contains Reset values for Context Store Registers */
721 static const uint32_t ixNpeDlCtxtRegResetValues[] = {
722 IX_NPEDL_CTXT_REG_RESET_STEVT,
723 IX_NPEDL_CTXT_REG_RESET_STARTPC,
724 IX_NPEDL_CTXT_REG_RESET_REGMAP,
725 IX_NPEDL_CTXT_REG_RESET_CINDEX,
726 };
727
728 #define IX_NPEDL_RESET_NPE_PARITY 0x0800
729 #define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF
730 #define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF
731
732 static int
733 npe_cpu_reset(struct ixpnpe_softc *sc)
734 {
735 #define N(a) (sizeof(a) / sizeof(a[0]))
736 uint32_t ctxtReg; /* identifies Context Store reg (0-3) */
737 uint32_t regAddr;
738 uint32_t regVal;
739 uint32_t resetNpeParity;
740 uint32_t ixNpeConfigCtrlRegVal;
741 int i, error = 0;
742
743 /* pre-store the NPE Config Control Register Value */
744 ixNpeConfigCtrlRegVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL);
745 ixNpeConfigCtrlRegVal |= 0x3F000000;
746
747 /* disable the parity interrupt */
748 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
749 (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
750 DPRINTFn(2, sc->sc_dev, "%s: dis parity int, CTL => 0x%x\n",
751 __func__, ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK);
752
753 npe_cpu_step_save(sc);
754
755 /*
756 * Clear the FIFOs.
757 */
758 while (npe_checkbits(sc,
759 IX_NPEDL_REG_OFFSET_WFIFO, IX_NPEDL_MASK_WFIFO_VALID)) {
760 /* read from the Watch-point FIFO until empty */
761 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WFIFO);
762 }
763
764 while (npe_checkbits(sc,
765 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_OFNE)) {
766 /* read from the outFIFO until empty */
767 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_FIFO);
768 }
769
770 while (npe_checkbits(sc,
771 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) {
772 /*
773 * Step execution of the NPE intruction to read inFIFO using
774 * the Debug Executing Context stack.
775 */
776 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0);
777 if (error != 0) {
778 DPRINTF(sc->sc_dev, "%s: cannot step (1), error %u\n",
779 __func__, error);
780 npe_cpu_step_restore(sc);
781 return error;
782 }
783 }
784
785 /*
786 * Reset the mailbox reg
787 */
788 /* ...from XScale side */
789 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_MBST, IX_NPEDL_REG_RESET_MBST);
790 /* ...from NPE side */
791 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
792 if (error != 0) {
793 DPRINTF(sc->sc_dev, "%s: cannot step (2), error %u\n", __func__, error);
794 npe_cpu_step_restore(sc);
795 return error;
796 }
797
798 /*
799 * Reset the physical registers in the NPE register file:
800 * Note: no need to save/restore REGMAP for Context 0 here
801 * since all Context Store regs are reset in subsequent code.
802 */
803 for (regAddr = 0;
804 regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG && error == 0;
805 regAddr++) {
806 /* for each physical register in the NPE reg file, write 0 : */
807 error = npe_physical_reg_write(sc, regAddr, 0, true);
808 if (error != 0) {
809 DPRINTF(sc->sc_dev, "%s: cannot write phy reg, error %u\n",
810 __func__, error);
811 npe_cpu_step_restore(sc);
812 return error; /* abort reset */
813 }
814 }
815
816 /*
817 * Reset the context store:
818 */
819 for (i = IX_NPEDL_CTXT_NUM_MIN; i <= IX_NPEDL_CTXT_NUM_MAX; i++) {
820 /* set each context's Context Store registers to reset values: */
821 for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) {
822 /* NOTE that there is no STEVT register for Context 0 */
823 if (!(i == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STEVT)) {
824 regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
825 error = npe_ctx_reg_write(sc, i, ctxtReg, regVal, true);
826 if (error != 0) {
827 DPRINTF(sc->sc_dev, "%s: cannot write ctx reg, error %u\n",
828 __func__, error);
829 npe_cpu_step_restore(sc);
830 return error; /* abort reset */
831 }
832 }
833 }
834 }
835
836 npe_cpu_step_restore(sc);
837
838 /* write Reset values to Execution Context Stack registers */
839 for (i = 0; i < N(ixNpeDlEcsRegResetValues); i++)
840 npe_ecs_reg_write(sc,
841 ixNpeDlEcsRegResetValues[i].regAddr,
842 ixNpeDlEcsRegResetValues[i].regResetVal);
843
844 /* clear the profile counter */
845 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
846
847 /* clear registers EXCT, AP0, AP1, AP2 and AP3 */
848 for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
849 regAddr <= IX_NPEDL_REG_OFFSET_AP3;
850 regAddr += sizeof(uint32_t))
851 npe_reg_write(sc, regAddr, 0);
852
853 /* Reset the Watch-count register */
854 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_WC, 0);
855
856 /*
857 * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
858 */
859
860 /*
861 * Reset the NPE and its coprocessor - to reset internal
862 * states and remove parity error. Note this makes no
863 * sense based on the documentation. The feature control
864 * register always reads back as 0 on the ixp425 and further
865 * the bit definition of NPEA/NPEB is off by 1 according to
866 * the Intel documention--so we're blindly following the
867 * Intel code w/o any real understanding.
868 */
869 regVal = EXP_BUS_READ_4(ixp425_softc, EXP_FCTRL_OFFSET);
870 DPRINTFn(2, sc->sc_dev, "%s: FCTRL 0x%x\n", __func__, regVal);
871 resetNpeParity =
872 IX_NPEDL_RESET_NPE_PARITY << (1 + sc->sc_unit);
873 DPRINTFn(2, sc->sc_dev, "%s: FCTRL fuse parity, write 0x%x\n",
874 __func__, regVal | resetNpeParity);
875 EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal | resetNpeParity);
876
877 /* un-fuse and un-reset the NPE & coprocessor */
878 DPRINTFn(2, sc->sc_dev, "%s: FCTRL unfuse parity, write 0x%x\n",
879 __func__, regVal & resetNpeParity);
880 EXP_BUS_WRITE_4(ixp425_softc, EXP_FCTRL_OFFSET, regVal &~ resetNpeParity);
881
882 /*
883 * Call NpeMgr function to stop the NPE again after the Feature Control
884 * has unfused and Un-Reset the NPE and its associated Coprocessors.
885 */
886 error = npe_cpu_stop(sc);
887
888 /* restore NPE configuration bus Control Register - Parity Settings */
889 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL,
890 (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
891 DPRINTFn(2, sc->sc_dev, "%s: restore CTL => 0x%x\n",
892 __func__, npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL));
893
894 return error;
895 #undef N
896 }
897
898 static int
899 npe_cpu_start(struct ixpnpe_softc *sc)
900 {
901 uint32_t ecsRegVal;
902
903 /*
904 * Ensure only Background Context Stack Level is Active by turning off
905 * the Active bit in each of the other Executing Context Stack levels.
906 */
907 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
908 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
909 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, ecsRegVal);
910
911 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
912 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
913 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, ecsRegVal);
914
915 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0);
916 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
917 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsRegVal);
918
919 /* clear the pipeline */
920 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
921
922 /* start NPE execution by issuing command through EXCTL register on NPE */
923 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_START);
924
925 /*
926 * Check execution status of NPE to verify operation was successful.
927 */
928 return npe_checkbits(sc,
929 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_RUN) ? 0 : EIO;
930 }
931
932 static int
933 npe_cpu_stop(struct ixpnpe_softc *sc)
934 {
935 /* stop NPE execution by issuing command through EXCTL register on NPE */
936 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STOP);
937
938 /* verify that NPE Stop was successful */
939 return npe_checkbits(sc,
940 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP) ? 0 : EIO;
941 }
942
943 #define IX_NPEDL_REG_SIZE_BYTE 8
944 #define IX_NPEDL_REG_SIZE_SHORT 16
945 #define IX_NPEDL_REG_SIZE_WORD 32
946
947 /*
948 * Introduce extra read cycles after issuing read command to NPE
949 * so that we read the register after the NPE has updated it
950 * This is to overcome race condition between XScale and NPE
951 */
952 #define IX_NPEDL_DELAY_READ_CYCLES 2
953 /*
954 * To mask top three MSBs of 32bit word to download into NPE IMEM
955 */
956 #define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF;
957
958 static void
959 npe_cmd_issue_write(struct ixpnpe_softc *sc,
960 uint32_t cmd, uint32_t addr, uint32_t data)
961 {
962 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, data);
963 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
964 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
965 }
966
967 static uint32_t
968 npe_cmd_issue_read(struct ixpnpe_softc *sc, uint32_t cmd, uint32_t addr)
969 {
970 uint32_t data;
971 int i;
972
973 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr);
974 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
975 for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++)
976 data = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
977 return data;
978 }
979
980 static int
981 npe_ins_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
982 {
983 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
984 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_INS_MEM, addr, data);
985 if (verify) {
986 uint32_t rdata;
987
988 /*
989 * Write invalid data to this reg, so we can see if we're reading
990 * the EXDATA register too early.
991 */
992 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
993
994 /* Disabled since top 3 MSB are not used for Azusa hardware Refer WR:IXA00053900*/
995 data &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
996
997 rdata = npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_INS_MEM, addr);
998 rdata &= IX_NPEDL_MASK_UNUSED_IMEM_BITS;
999
1000 if (data != rdata)
1001 return EIO;
1002 }
1003 return 0;
1004 }
1005
1006 static int
1007 npe_data_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify)
1008 {
1009 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data);
1010 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM, addr, data);
1011 if (verify) {
1012 /*
1013 * Write invalid data to this reg, so we can see if we're reading
1014 * the EXDATA register too early.
1015 */
1016 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data);
1017 if (data != npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM, addr))
1018 return EIO;
1019 }
1020 return 0;
1021 }
1022
1023 static void
1024 npe_ecs_reg_write(struct ixpnpe_softc *sc, uint32_t reg, uint32_t data)
1025 {
1026 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_ECS_REG, reg, data);
1027 }
1028
1029 static uint32_t
1030 npe_ecs_reg_read(struct ixpnpe_softc *sc, uint32_t reg)
1031 {
1032 return npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_ECS_REG, reg);
1033 }
1034
1035 static void
1036 npe_issue_cmd(struct ixpnpe_softc *sc, uint32_t command)
1037 {
1038 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, command);
1039 }
1040
1041 static void
1042 npe_cpu_step_save(struct ixpnpe_softc *sc)
1043 {
1044 /* turn off the halt bit by clearing Execution Count register. */
1045 /* save reg contents 1st and restore later */
1046 sc->savedExecCount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXCT);
1047 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, 0);
1048
1049 /* ensure that IF and IE are on (temporarily), so that we don't end up
1050 * stepping forever */
1051 sc->savedEcsDbgCtxtReg2 = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2);
1052
1053 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2,
1054 (sc->savedEcsDbgCtxtReg2 | IX_NPEDL_MASK_ECS_DBG_REG_2_IF |
1055 IX_NPEDL_MASK_ECS_DBG_REG_2_IE));
1056 }
1057
1058 static int
1059 npe_cpu_step(struct ixpnpe_softc *sc, uint32_t npeInstruction,
1060 uint32_t ctxtNum, uint32_t ldur)
1061 {
1062 #define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000
1063 uint32_t ecsDbgRegVal;
1064 uint32_t oldWatchcount, newWatchcount;
1065 int tries;
1066
1067 /* set the Active bit, and the LDUR, in the debug level */
1068 ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE |
1069 (ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR);
1070
1071 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsDbgRegVal);
1072
1073 /*
1074 * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the
1075 * instruction, and set SELCTXT at ECS DEBUG Level to specify which context
1076 * store to access.
1077 * Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
1078 */
1079 ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) |
1080 (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT);
1081
1082 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_1, ecsDbgRegVal);
1083
1084 /* clear the pipeline */
1085 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
1086
1087 /* load NPE instruction into the instruction register */
1088 npe_ecs_reg_write(sc, IX_NPEDL_ECS_INSTRUCT_REG, npeInstruction);
1089
1090 /* we need this value later to wait for completion of NPE execution step */
1091 oldWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1092
1093 /* issue a Step One command via the Execution Control register */
1094 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STEP);
1095
1096 /*
1097 * Force the XScale to wait until the NPE has finished execution step
1098 * NOTE that this delay will be very small, just long enough to allow a
1099 * single NPE instruction to complete execution; if instruction execution
1100 * is not completed before timeout retries, exit the while loop.
1101 */
1102 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1103 for (tries = 0; tries < IX_NPE_DL_MAX_NUM_OF_RETRIES &&
1104 newWatchcount == oldWatchcount; tries++) {
1105 /* Watch Count register increments when NPE completes an instruction */
1106 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC);
1107 }
1108 return (tries < IX_NPE_DL_MAX_NUM_OF_RETRIES) ? 0 : EIO;
1109 #undef IX_NPE_DL_MAX_NUM_OF_RETRIES
1110 }
1111
1112 static void
1113 npe_cpu_step_restore(struct ixpnpe_softc *sc)
1114 {
1115 /* clear active bit in debug level */
1116 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, 0);
1117
1118 /* clear the pipeline */
1119 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
1120
1121 /* restore Execution Count register contents. */
1122 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, sc->savedExecCount);
1123
1124 /* restore IF and IE bits to original values */
1125 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, sc->savedEcsDbgCtxtReg2);
1126 }
1127
1128 static int
1129 npe_logical_reg_read(struct ixpnpe_softc *sc,
1130 uint32_t regAddr, uint32_t regSize,
1131 uint32_t ctxtNum, uint32_t *regVal)
1132 {
1133 uint32_t npeInstruction, mask;
1134 int error;
1135
1136 switch (regSize) {
1137 case IX_NPEDL_REG_SIZE_BYTE:
1138 npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE;
1139 mask = 0xff;
1140 break;
1141 case IX_NPEDL_REG_SIZE_SHORT:
1142 npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT;
1143 mask = 0xffff;
1144 break;
1145 case IX_NPEDL_REG_SIZE_WORD:
1146 npeInstruction = IX_NPEDL_INSTR_RD_REG_WORD;
1147 mask = 0xffffffff;
1148 break;
1149 default:
1150 return EINVAL;
1151 }
1152
1153 /* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */
1154 npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_SRC) |
1155 (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
1156
1157 /* step execution of NPE intruction using Debug Executing Context stack */
1158 error = npe_cpu_step(sc, npeInstruction, ctxtNum, IX_NPEDL_RD_INSTR_LDUR);
1159 if (error != 0) {
1160 DPRINTF(sc->sc_dev, "%s(0x%x, %u, %u), cannot step, error %d\n",
1161 __func__, regAddr, regSize, ctxtNum, error);
1162 return error;
1163 }
1164 /* read value of register from Execution Data register */
1165 *regVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA);
1166
1167 /* align value from left to right */
1168 *regVal = (*regVal >> (IX_NPEDL_REG_SIZE_WORD - regSize)) & mask;
1169
1170 return 0;
1171 }
1172
1173 static int
1174 npe_logical_reg_write(struct ixpnpe_softc *sc, uint32_t regAddr, uint32_t regVal,
1175 uint32_t regSize, uint32_t ctxtNum, int verify)
1176 {
1177 int error;
1178
1179 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x, %u, %u)\n",
1180 __func__, regAddr, regVal, regSize, ctxtNum);
1181 if (regSize == IX_NPEDL_REG_SIZE_WORD) {
1182 /* NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3| */
1183 /* Write upper half-word (short) to |d0|d1| */
1184 error = npe_logical_reg_write(sc, regAddr,
1185 regVal >> IX_NPEDL_REG_SIZE_SHORT,
1186 IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify);
1187 if (error != 0)
1188 return error;
1189
1190 /* Write lower half-word (short) to |d2|d3| */
1191 error = npe_logical_reg_write(sc,
1192 regAddr + sizeof(uint16_t),
1193 regVal & 0xffff,
1194 IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify);
1195 } else {
1196 uint32_t npeInstruction;
1197
1198 switch (regSize) {
1199 case IX_NPEDL_REG_SIZE_BYTE:
1200 npeInstruction = IX_NPEDL_INSTR_WR_REG_BYTE;
1201 regVal &= 0xff;
1202 break;
1203 case IX_NPEDL_REG_SIZE_SHORT:
1204 npeInstruction = IX_NPEDL_INSTR_WR_REG_SHORT;
1205 regVal &= 0xffff;
1206 break;
1207 default:
1208 return EINVAL;
1209 }
1210 /* fill dest operand field of instruction with destination reg addr */
1211 npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
1212
1213 /* fill src operand field of instruction with least-sig 5 bits of val*/
1214 npeInstruction |= ((regVal & IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA) <<
1215 IX_NPEDL_OFFSET_INSTR_SRC);
1216
1217 /* fill coprocessor field of instruction with most-sig 11 bits of val*/
1218 npeInstruction |= ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) <<
1219 IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA);
1220
1221 /* step execution of NPE intruction using Debug ECS */
1222 error = npe_cpu_step(sc, npeInstruction,
1223 ctxtNum, IX_NPEDL_WR_INSTR_LDUR);
1224 }
1225 if (error != 0) {
1226 DPRINTF(sc->sc_dev, "%s(0x%x, 0x%x, %u, %u), error %u writing reg\n",
1227 __func__, regAddr, regVal, regSize, ctxtNum, error);
1228 return error;
1229 }
1230 if (verify) {
1231 uint32_t retRegVal;
1232
1233 error = npe_logical_reg_read(sc, regAddr, regSize, ctxtNum, &retRegVal);
1234 if (error == 0 && regVal != retRegVal)
1235 error = EIO; /* XXX ambiguous */
1236 }
1237 return error;
1238 }
1239
1240 /*
1241 * There are 32 physical registers used in an NPE. These are
1242 * treated as 16 pairs of 32-bit registers. To write one of the pair,
1243 * write the pair number (0-16) to the REGMAP for Context 0. Then write
1244 * the value to register 0 or 4 in the regfile, depending on which
1245 * register of the pair is to be written
1246 */
1247 static int
1248 npe_physical_reg_write(struct ixpnpe_softc *sc,
1249 uint32_t regAddr, uint32_t regValue, int verify)
1250 {
1251 int error;
1252
1253 /*
1254 * Set REGMAP for context 0 to (regAddr >> 1) to choose which pair (0-16)
1255 * of physical registers to write .
1256 */
1257 error = npe_logical_reg_write(sc, IX_NPEDL_CTXT_REG_ADDR_REGMAP,
1258 (regAddr >> IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP),
1259 IX_NPEDL_REG_SIZE_SHORT, 0, verify);
1260 if (error == 0) {
1261 /* regAddr = 0 or 4 */
1262 regAddr = (regAddr & IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR) *
1263 sizeof(uint32_t);
1264 error = npe_logical_reg_write(sc, regAddr, regValue,
1265 IX_NPEDL_REG_SIZE_WORD, 0, verify);
1266 }
1267 return error;
1268 }
1269
1270 static int
1271 npe_ctx_reg_write(struct ixpnpe_softc *sc, uint32_t ctxtNum,
1272 uint32_t ctxtReg, uint32_t ctxtRegVal, int verify)
1273 {
1274 DPRINTFn(4, sc->sc_dev, "%s(%u, %u, %u)\n",
1275 __func__, ctxtNum, ctxtReg, ctxtRegVal);
1276 /*
1277 * Context 0 has no STARTPC. Instead, this value is used to set
1278 * NextPC for Background ECS, to set where NPE starts executing code
1279 */
1280 if (ctxtNum == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STARTPC) {
1281 /* read BG_CTXT_REG_0, update NEXTPC bits, and write back to reg */
1282 uint32_t v = npe_ecs_reg_read(sc, IX_NPEDL_ECS_BG_CTXT_REG_0);
1283 v &= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
1284 v |= (ctxtRegVal << IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC) &
1285 IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
1286
1287 npe_ecs_reg_write(sc, IX_NPEDL_ECS_BG_CTXT_REG_0, v);
1288 return 0;
1289 } else {
1290 static const struct {
1291 uint32_t regAddress;
1292 uint32_t regSize;
1293 } regAccInfo[IX_NPEDL_CTXT_REG_MAX] = {
1294 { IX_NPEDL_CTXT_REG_ADDR_STEVT, IX_NPEDL_REG_SIZE_BYTE },
1295 { IX_NPEDL_CTXT_REG_ADDR_STARTPC, IX_NPEDL_REG_SIZE_SHORT },
1296 { IX_NPEDL_CTXT_REG_ADDR_REGMAP, IX_NPEDL_REG_SIZE_SHORT },
1297 { IX_NPEDL_CTXT_REG_ADDR_CINDEX, IX_NPEDL_REG_SIZE_BYTE }
1298 };
1299 return npe_logical_reg_write(sc, regAccInfo[ctxtReg].regAddress,
1300 ctxtRegVal, regAccInfo[ctxtReg].regSize, ctxtNum, verify);
1301 }
1302 }
1303
1304 /*
1305 * NPE Mailbox support.
1306 */
1307 #define IX_NPEMH_MAXTRIES 100000
1308
1309 static int
1310 ixpnpe_ofifo_wait(struct ixpnpe_softc *sc)
1311 {
1312 int i;
1313
1314 for (i = 0; i < IX_NPEMH_MAXTRIES; i++) {
1315 if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_OFNE)
1316 return 1;
1317 DELAY(10);
1318 }
1319 printf("%s: %s: timeout, last status 0x%x\n", sc->sc_dev.dv_xname,
1320 __func__, npe_reg_read(sc, IX_NPESTAT));
1321 return 0;
1322 }
1323
1324 static int
1325 ixpnpe_intr(void *arg)
1326 {
1327 struct ixpnpe_softc *sc = arg;
1328 uint32_t status;
1329
1330 status = npe_reg_read(sc, IX_NPESTAT);
1331 if ((status & IX_NPESTAT_OFINT) == 0) {
1332 /* NB: should not happen */
1333 printf("%s: %s: status 0x%x\n", sc->sc_dev.dv_xname, __func__, status);
1334 /* XXX must silence interrupt? */
1335 return(1);
1336 }
1337 /*
1338 * A message is waiting in the output FIFO, copy it so
1339 * the interrupt will be silenced; then signal anyone
1340 * waiting to collect the result.
1341 */
1342 sc->sc_msgwaiting = -1; /* NB: error indicator */
1343 if (ixpnpe_ofifo_wait(sc)) {
1344 sc->sc_msg[0] = npe_reg_read(sc, IX_NPEFIFO);
1345 if (ixpnpe_ofifo_wait(sc)) {
1346 sc->sc_msg[1] = npe_reg_read(sc, IX_NPEFIFO);
1347 sc->sc_msgwaiting = 1; /* successful fetch */
1348 }
1349 }
1350 wakeup(sc);
1351
1352 return (1);
1353 }
1354
1355 static int
1356 ixpnpe_ififo_wait(struct ixpnpe_softc *sc)
1357 {
1358 int i;
1359
1360 for (i = 0; i < IX_NPEMH_MAXTRIES; i++) {
1361 if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_IFNF)
1362 return 1;
1363 DELAY(10);
1364 }
1365 return 0;
1366 }
1367
1368 static int
1369 ixpnpe_sendmsg_locked(struct ixpnpe_softc *sc, const uint32_t msg[2])
1370 {
1371 int error = 0;
1372
1373 sc->sc_msgwaiting = 0;
1374 if (ixpnpe_ififo_wait(sc)) {
1375 npe_reg_write(sc, IX_NPEFIFO, msg[0]);
1376 if (ixpnpe_ififo_wait(sc))
1377 npe_reg_write(sc, IX_NPEFIFO, msg[1]);
1378 else
1379 error = EIO;
1380 } else
1381 error = EIO;
1382
1383 if (error)
1384 printf("%s: input FIFO timeout, msg [0x%x,0x%x]\n",
1385 sc->sc_dev.dv_xname, msg[0], msg[1]);
1386 return error;
1387 }
1388
1389 static int
1390 ixpnpe_recvmsg_locked(struct ixpnpe_softc *sc, uint32_t msg[2])
1391 {
1392
1393 if (!sc->sc_msgwaiting)
1394 ltsleep(sc, 0, "npemh", 0, &sc->sc_lock);
1395 bcopy(sc->sc_msg, msg, sizeof(sc->sc_msg));
1396 /* NB: sc_msgwaiting != 1 means the ack fetch failed */
1397 return sc->sc_msgwaiting != 1 ? EIO : 0;
1398 }
1399
1400 /*
1401 * Send a msg to the NPE and wait for a reply. We use the
1402 * private mutex and sleep until an interrupt is received
1403 * signalling the availability of data in the output FIFO
1404 * so the caller cannot be holding a mutex. May be better
1405 * piggyback on the caller's mutex instead but that would
1406 * make other locking confusing.
1407 */
1408 int
1409 ixpnpe_sendandrecvmsg(struct ixpnpe_softc *sc,
1410 const uint32_t send[2], uint32_t recv[2])
1411 {
1412 int error;
1413
1414 simple_lock(&sc->sc_lock);
1415 error = ixpnpe_sendmsg_locked(sc, send);
1416 if (error == 0)
1417 error = ixpnpe_recvmsg_locked(sc, recv);
1418 simple_unlock(&sc->sc_lock);
1419
1420 return error;
1421 }
1422
1423 /* XXX temporary, not reliable */
1424
1425 int
1426 ixpnpe_sendmsg(struct ixpnpe_softc *sc, const uint32_t msg[2])
1427 {
1428 int error;
1429
1430 simple_lock(&sc->sc_lock);
1431 error = ixpnpe_sendmsg_locked(sc, msg);
1432 simple_unlock(&sc->sc_lock);
1433
1434 return error;
1435 }
1436
1437 int
1438 ixpnpe_recvmsg(struct ixpnpe_softc *sc, uint32_t msg[2])
1439 {
1440 int error;
1441
1442 simple_lock(&sc->sc_lock);
1443 if (sc->sc_msgwaiting)
1444 bcopy(sc->sc_msg, msg, sizeof(sc->sc_msg));
1445 /* NB: sc_msgwaiting != 1 means the ack fetch failed */
1446 error = sc->sc_msgwaiting != 1 ? EIO : 0;
1447 simple_unlock(&sc->sc_lock);
1448
1449 return error;
1450 }
1451