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