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