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