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