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