ixp425_npe.c revision 236987
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 236987 2012-06-13 04:38:09Z imp $"); 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_PARITY_BIT_MASK 0x3F00FFFF 808#define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF 809 810#if 0 811/* 812 * Reset the NPE and its coprocessor using the 813 * fuse bits in the feature control register. 814 */ 815static void 816npe_reset(int npeid) 817{ 818 uint32_t mask = EXP_FCTRL_NPEA << npeid; 819 uint32_t v; 820 821 v = ixp4xx_read_feature_bits(); 822 ixp4xx_write_feature_bits(v &~ mask); 823 /* un-fuse and un-reset the NPE & coprocessor */ 824 ixp4xx_write_feature_bits(v | mask); 825} 826#endif 827 828static int 829npe_cpu_reset(struct ixpnpe_softc *sc) 830{ 831#define N(a) (sizeof(a) / sizeof(a[0])) 832 uint32_t ctxtReg; /* identifies Context Store reg (0-3) */ 833 uint32_t regAddr; 834 uint32_t regVal; 835 uint32_t ixNpeConfigCtrlRegVal; 836 int i, error = 0; 837 838 /* pre-store the NPE Config Control Register Value */ 839 ixNpeConfigCtrlRegVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL); 840 ixNpeConfigCtrlRegVal |= 0x3F000000; 841 842 /* disable the parity interrupt */ 843 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL, 844 (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK)); 845 DPRINTFn(2, sc->sc_dev, "%s: dis parity int, CTL => 0x%x\n", 846 __func__, ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK); 847 848 npe_cpu_step_save(sc); 849 850 /* 851 * Clear the FIFOs. 852 */ 853 while (npe_checkbits(sc, 854 IX_NPEDL_REG_OFFSET_WFIFO, IX_NPEDL_MASK_WFIFO_VALID)) { 855 /* read from the Watch-point FIFO until empty */ 856 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WFIFO); 857 } 858 859 while (npe_checkbits(sc, 860 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_OFNE)) { 861 /* read from the outFIFO until empty */ 862 (void) npe_reg_read(sc, IX_NPEDL_REG_OFFSET_FIFO); 863 } 864 865 while (npe_checkbits(sc, 866 IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) { 867 /* 868 * Step execution of the NPE intruction to read inFIFO using 869 * the Debug Executing Context stack. 870 */ 871 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0); 872 if (error != 0) { 873 DPRINTF(sc->sc_dev, "%s: cannot step (1), error %u\n", 874 __func__, error); 875 npe_cpu_step_restore(sc); 876 return error; 877 } 878 } 879 880 /* 881 * Reset the mailbox reg 882 */ 883 /* ...from XScale side */ 884 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_MBST, IX_NPEDL_REG_RESET_MBST); 885 /* ...from NPE side */ 886 error = npe_cpu_step(sc, IX_NPEDL_INSTR_RESET_MBOX, 0, 0); 887 if (error != 0) { 888 DPRINTF(sc->sc_dev, "%s: cannot step (2), error %u\n", 889 __func__, error); 890 npe_cpu_step_restore(sc); 891 return error; 892 } 893 894 /* 895 * Reset the physical registers in the NPE register file: 896 * Note: no need to save/restore REGMAP for Context 0 here 897 * since all Context Store regs are reset in subsequent code. 898 */ 899 for (regAddr = 0; 900 regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG && error == 0; 901 regAddr++) { 902 /* for each physical register in the NPE reg file, write 0 : */ 903 error = npe_physical_reg_write(sc, regAddr, 0, TRUE); 904 if (error != 0) { 905 DPRINTF(sc->sc_dev, "%s: cannot write phy reg," 906 "error %u\n", __func__, error); 907 npe_cpu_step_restore(sc); 908 return error; /* abort reset */ 909 } 910 } 911 912 /* 913 * Reset the context store: 914 */ 915 for (i = IX_NPEDL_CTXT_NUM_MIN; i <= IX_NPEDL_CTXT_NUM_MAX; i++) { 916 /* set each context's Context Store registers to reset values */ 917 for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++) { 918 /* NOTE that there is no STEVT register for Context 0 */ 919 if (i == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STEVT) 920 continue; 921 regVal = ixNpeDlCtxtRegResetValues[ctxtReg]; 922 error = npe_ctx_reg_write(sc, i, ctxtReg, 923 regVal, TRUE); 924 if (error != 0) { 925 DPRINTF(sc->sc_dev, "%s: cannot write ctx reg," 926 "error %u\n", __func__, error); 927 npe_cpu_step_restore(sc); 928 return error; /* abort reset */ 929 } 930 } 931 } 932 933 npe_cpu_step_restore(sc); 934 935 /* write Reset values to Execution Context Stack registers */ 936 for (i = 0; i < N(ixNpeDlEcsRegResetValues); i++) 937 npe_ecs_reg_write(sc, 938 ixNpeDlEcsRegResetValues[i].regAddr, 939 ixNpeDlEcsRegResetValues[i].regResetVal); 940 941 /* clear the profile counter */ 942 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT); 943 944 /* clear registers EXCT, AP0, AP1, AP2 and AP3 */ 945 for (regAddr = IX_NPEDL_REG_OFFSET_EXCT; 946 regAddr <= IX_NPEDL_REG_OFFSET_AP3; 947 regAddr += sizeof(uint32_t)) 948 npe_reg_write(sc, regAddr, 0); 949 950 /* Reset the Watch-count register */ 951 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_WC, 0); 952#if 0 953 /* 954 * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation 955 * XXX Removed because it breaks IXP435 operation; e.g. on Gateworks 956 * XXX 2358 boards reseting NPE-A after NPE-C is running causes both 957 * XXX npe's to stop working 958 */ 959 npe_reset(sc->sc_npeid); 960#endif 961 /* 962 * Call NpeMgr function to stop the NPE again after the Feature Control 963 * has unfused and Un-Reset the NPE and its associated Coprocessors. 964 */ 965 error = npe_cpu_stop(sc); 966 967 /* restore NPE configuration bus Control Register - Parity Settings */ 968 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_CTL, 969 (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK)); 970 DPRINTFn(2, sc->sc_dev, "%s: restore CTL => 0x%x\n", 971 __func__, npe_reg_read(sc, IX_NPEDL_REG_OFFSET_CTL)); 972 973 return error; 974#undef N 975} 976 977static int 978npe_cpu_start(struct ixpnpe_softc *sc) 979{ 980 uint32_t ecsRegVal; 981 982 /* 983 * Ensure only Background Context Stack Level is Active by turning off 984 * the Active bit in each of the other Executing Context Stack levels. 985 */ 986 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0); 987 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; 988 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_1_CTXT_REG_0, ecsRegVal); 989 990 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0); 991 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; 992 npe_ecs_reg_write(sc, IX_NPEDL_ECS_PRI_2_CTXT_REG_0, ecsRegVal); 993 994 ecsRegVal = npe_ecs_reg_read(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0); 995 ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE; 996 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsRegVal); 997 998 /* clear the pipeline */ 999 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); 1000 1001 /* start NPE execution by issuing cmd through EXCTL register on NPE */ 1002 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_START); 1003 1004 /* 1005 * Check execution status of NPE to verify operation was successful. 1006 */ 1007 return npe_checkbits(sc, 1008 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_RUN) ? 0 : EIO; 1009} 1010 1011static int 1012npe_cpu_stop(struct ixpnpe_softc *sc) 1013{ 1014 /* stop NPE execution by issuing cmd through EXCTL register on NPE */ 1015 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STOP); 1016 1017 /* verify that NPE Stop was successful */ 1018 return npe_checkbits(sc, 1019 IX_NPEDL_REG_OFFSET_EXCTL, IX_NPEDL_EXCTL_STATUS_STOP) ? 0 : EIO; 1020} 1021 1022#define IX_NPEDL_REG_SIZE_BYTE 8 1023#define IX_NPEDL_REG_SIZE_SHORT 16 1024#define IX_NPEDL_REG_SIZE_WORD 32 1025 1026/* 1027 * Introduce extra read cycles after issuing read command to NPE 1028 * so that we read the register after the NPE has updated it 1029 * This is to overcome race condition between XScale and NPE 1030 */ 1031#define IX_NPEDL_DELAY_READ_CYCLES 2 1032/* 1033 * To mask top three MSBs of 32bit word to download into NPE IMEM 1034 */ 1035#define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF; 1036 1037static void 1038npe_cmd_issue_write(struct ixpnpe_softc *sc, 1039 uint32_t cmd, uint32_t addr, uint32_t data) 1040{ 1041 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, data); 1042 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr); 1043 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd); 1044} 1045 1046static uint32_t 1047npe_cmd_issue_read(struct ixpnpe_softc *sc, uint32_t cmd, uint32_t addr) 1048{ 1049 uint32_t data; 1050 int i; 1051 1052 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXAD, addr); 1053 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, cmd); 1054 for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++) 1055 data = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA); 1056 return data; 1057} 1058 1059static int 1060npe_ins_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify) 1061{ 1062 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data); 1063 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_INS_MEM, addr, data); 1064 if (verify) { 1065 uint32_t rdata; 1066 1067 /* 1068 * Write invalid data to this reg, so we can see if we're 1069 * reading the EXDATA register too early. 1070 */ 1071 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data); 1072 1073 /* 1074 * Disabled since top 3 MSB are not used for Azusa 1075 * hardware Refer WR:IXA00053900 1076 */ 1077 data &= IX_NPEDL_MASK_UNUSED_IMEM_BITS; 1078 1079 rdata = npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_INS_MEM, 1080 addr); 1081 rdata &= IX_NPEDL_MASK_UNUSED_IMEM_BITS; 1082 1083 if (data != rdata) 1084 return EIO; 1085 } 1086 return 0; 1087} 1088 1089static int 1090npe_data_write(struct ixpnpe_softc *sc, uint32_t addr, uint32_t data, int verify) 1091{ 1092 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x)\n", __func__, addr, data); 1093 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_DATA_MEM, addr, data); 1094 if (verify) { 1095 /* 1096 * Write invalid data to this reg, so we can see if we're 1097 * reading the EXDATA register too early. 1098 */ 1099 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXDATA, ~data); 1100 if (data != npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_DATA_MEM, addr)) 1101 return EIO; 1102 } 1103 return 0; 1104} 1105 1106static void 1107npe_ecs_reg_write(struct ixpnpe_softc *sc, uint32_t reg, uint32_t data) 1108{ 1109 npe_cmd_issue_write(sc, IX_NPEDL_EXCTL_CMD_WR_ECS_REG, reg, data); 1110} 1111 1112static uint32_t 1113npe_ecs_reg_read(struct ixpnpe_softc *sc, uint32_t reg) 1114{ 1115 return npe_cmd_issue_read(sc, IX_NPEDL_EXCTL_CMD_RD_ECS_REG, reg); 1116} 1117 1118static void 1119npe_issue_cmd(struct ixpnpe_softc *sc, uint32_t command) 1120{ 1121 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCTL, command); 1122} 1123 1124static void 1125npe_cpu_step_save(struct ixpnpe_softc *sc) 1126{ 1127 /* turn off the halt bit by clearing Execution Count register. */ 1128 /* save reg contents 1st and restore later */ 1129 sc->savedExecCount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXCT); 1130 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, 0); 1131 1132 /* ensure that IF and IE are on (temporarily), so that we don't end up 1133 * stepping forever */ 1134 sc->savedEcsDbgCtxtReg2 = npe_ecs_reg_read(sc, 1135 IX_NPEDL_ECS_DBG_CTXT_REG_2); 1136 1137 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, 1138 (sc->savedEcsDbgCtxtReg2 | IX_NPEDL_MASK_ECS_DBG_REG_2_IF | 1139 IX_NPEDL_MASK_ECS_DBG_REG_2_IE)); 1140} 1141 1142static int 1143npe_cpu_step(struct ixpnpe_softc *sc, uint32_t npeInstruction, 1144 uint32_t ctxtNum, uint32_t ldur) 1145{ 1146#define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000 1147 uint32_t ecsDbgRegVal; 1148 uint32_t oldWatchcount, newWatchcount; 1149 int tries; 1150 1151 /* set the Active bit, and the LDUR, in the debug level */ 1152 ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE | 1153 (ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR); 1154 1155 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, ecsDbgRegVal); 1156 1157 /* 1158 * Set CCTXT at ECS DEBUG L3 to specify in which context to execute the 1159 * instruction, and set SELCTXT at ECS DEBUG Level to specify which 1160 * context store to access. 1161 * Debug ECS Level Reg 1 has form 0x000n000n, where n = context number 1162 */ 1163 ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) | 1164 (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT); 1165 1166 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_1, ecsDbgRegVal); 1167 1168 /* clear the pipeline */ 1169 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); 1170 1171 /* load NPE instruction into the instruction register */ 1172 npe_ecs_reg_write(sc, IX_NPEDL_ECS_INSTRUCT_REG, npeInstruction); 1173 1174 /* need this value later to wait for completion of NPE execution step */ 1175 oldWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC); 1176 1177 /* issue a Step One command via the Execution Control register */ 1178 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_STEP); 1179 1180 /* 1181 * Force the XScale to wait until the NPE has finished execution step 1182 * NOTE that this delay will be very small, just long enough to allow a 1183 * single NPE instruction to complete execution; if instruction 1184 * execution is not completed before timeout retries, exit the while 1185 * loop. 1186 */ 1187 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC); 1188 for (tries = 0; tries < IX_NPE_DL_MAX_NUM_OF_RETRIES && 1189 newWatchcount == oldWatchcount; tries++) { 1190 /* Watch Count register incr's when NPE completes an inst */ 1191 newWatchcount = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_WC); 1192 } 1193 return (tries < IX_NPE_DL_MAX_NUM_OF_RETRIES) ? 0 : EIO; 1194#undef IX_NPE_DL_MAX_NUM_OF_RETRIES 1195} 1196 1197static void 1198npe_cpu_step_restore(struct ixpnpe_softc *sc) 1199{ 1200 /* clear active bit in debug level */ 1201 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_0, 0); 1202 1203 /* clear the pipeline */ 1204 npe_issue_cmd(sc, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE); 1205 1206 /* restore Execution Count register contents. */ 1207 npe_reg_write(sc, IX_NPEDL_REG_OFFSET_EXCT, sc->savedExecCount); 1208 1209 /* restore IF and IE bits to original values */ 1210 npe_ecs_reg_write(sc, IX_NPEDL_ECS_DBG_CTXT_REG_2, sc->savedEcsDbgCtxtReg2); 1211} 1212 1213static int 1214npe_logical_reg_read(struct ixpnpe_softc *sc, 1215 uint32_t regAddr, uint32_t regSize, 1216 uint32_t ctxtNum, uint32_t *regVal) 1217{ 1218 uint32_t npeInstruction, mask; 1219 int error; 1220 1221 switch (regSize) { 1222 case IX_NPEDL_REG_SIZE_BYTE: 1223 npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE; 1224 mask = 0xff; 1225 break; 1226 case IX_NPEDL_REG_SIZE_SHORT: 1227 npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT; 1228 mask = 0xffff; 1229 break; 1230 case IX_NPEDL_REG_SIZE_WORD: 1231 npeInstruction = IX_NPEDL_INSTR_RD_REG_WORD; 1232 mask = 0xffffffff; 1233 break; 1234 default: 1235 return EINVAL; 1236 } 1237 1238 /* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */ 1239 npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_SRC) | 1240 (regAddr << IX_NPEDL_OFFSET_INSTR_DEST); 1241 1242 /* step execution of NPE inst using Debug Executing Context stack */ 1243 error = npe_cpu_step(sc, npeInstruction, ctxtNum, 1244 IX_NPEDL_RD_INSTR_LDUR); 1245 if (error != 0) { 1246 DPRINTF(sc->sc_dev, "%s(0x%x, %u, %u), cannot step, error %d\n", 1247 __func__, regAddr, regSize, ctxtNum, error); 1248 return error; 1249 } 1250 /* read value of register from Execution Data register */ 1251 *regVal = npe_reg_read(sc, IX_NPEDL_REG_OFFSET_EXDATA); 1252 1253 /* align value from left to right */ 1254 *regVal = (*regVal >> (IX_NPEDL_REG_SIZE_WORD - regSize)) & mask; 1255 1256 return 0; 1257} 1258 1259static int 1260npe_logical_reg_write(struct ixpnpe_softc *sc, uint32_t regAddr, uint32_t regVal, 1261 uint32_t regSize, uint32_t ctxtNum, int verify) 1262{ 1263 int error; 1264 1265 DPRINTFn(4, sc->sc_dev, "%s(0x%x, 0x%x, %u, %u)\n", 1266 __func__, regAddr, regVal, regSize, ctxtNum); 1267 if (regSize == IX_NPEDL_REG_SIZE_WORD) { 1268 /* 1269 * NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3| 1270 * Write upper half-word (short) to |d0|d1| 1271 */ 1272 error = npe_logical_reg_write(sc, regAddr, 1273 regVal >> IX_NPEDL_REG_SIZE_SHORT, 1274 IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify); 1275 if (error != 0) 1276 return error; 1277 1278 /* Write lower half-word (short) to |d2|d3| */ 1279 error = npe_logical_reg_write(sc, 1280 regAddr + sizeof(uint16_t), 1281 regVal & 0xffff, 1282 IX_NPEDL_REG_SIZE_SHORT, ctxtNum, verify); 1283 } else { 1284 uint32_t npeInstruction; 1285 1286 switch (regSize) { 1287 case IX_NPEDL_REG_SIZE_BYTE: 1288 npeInstruction = IX_NPEDL_INSTR_WR_REG_BYTE; 1289 regVal &= 0xff; 1290 break; 1291 case IX_NPEDL_REG_SIZE_SHORT: 1292 npeInstruction = IX_NPEDL_INSTR_WR_REG_SHORT; 1293 regVal &= 0xffff; 1294 break; 1295 default: 1296 return EINVAL; 1297 } 1298 /* fill dest operand field of inst with dest reg addr */ 1299 npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_DEST); 1300 1301 /* fill src operand field of inst with least-sig 5 bits of val*/ 1302 npeInstruction |= 1303 ((regVal & IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA) << 1304 IX_NPEDL_OFFSET_INSTR_SRC); 1305 1306 /* fill coprocessor field of inst with most-sig 11 bits of val*/ 1307 npeInstruction |= 1308 ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) << 1309 IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA); 1310 1311 /* step execution of NPE intruction using Debug ECS */ 1312 error = npe_cpu_step(sc, npeInstruction, 1313 ctxtNum, IX_NPEDL_WR_INSTR_LDUR); 1314 } 1315 if (error != 0) { 1316 DPRINTF(sc->sc_dev, "%s(0x%x, 0x%x, %u, %u), error %u " 1317 "writing reg\n", __func__, regAddr, regVal, regSize, 1318 ctxtNum, error); 1319 return error; 1320 } 1321 if (verify) { 1322 uint32_t retRegVal; 1323 1324 error = npe_logical_reg_read(sc, regAddr, regSize, ctxtNum, 1325 &retRegVal); 1326 if (error == 0 && regVal != retRegVal) 1327 error = EIO; /* XXX ambiguous */ 1328 } 1329 return error; 1330} 1331 1332/* 1333 * There are 32 physical registers used in an NPE. These are 1334 * treated as 16 pairs of 32-bit registers. To write one of the pair, 1335 * write the pair number (0-16) to the REGMAP for Context 0. Then write 1336 * the value to register 0 or 4 in the regfile, depending on which 1337 * register of the pair is to be written 1338 */ 1339static int 1340npe_physical_reg_write(struct ixpnpe_softc *sc, 1341 uint32_t regAddr, uint32_t regValue, int verify) 1342{ 1343 int error; 1344 1345 /* 1346 * Set REGMAP for context 0 to (regAddr >> 1) to choose which pair 1347 * (0-16) of physical registers to write . 1348 */ 1349 error = npe_logical_reg_write(sc, IX_NPEDL_CTXT_REG_ADDR_REGMAP, 1350 (regAddr >> IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP), 1351 IX_NPEDL_REG_SIZE_SHORT, 0, verify); 1352 if (error == 0) { 1353 /* regAddr = 0 or 4 */ 1354 regAddr = (regAddr & IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR) * 1355 sizeof(uint32_t); 1356 error = npe_logical_reg_write(sc, regAddr, regValue, 1357 IX_NPEDL_REG_SIZE_WORD, 0, verify); 1358 } 1359 return error; 1360} 1361 1362static int 1363npe_ctx_reg_write(struct ixpnpe_softc *sc, uint32_t ctxtNum, 1364 uint32_t ctxtReg, uint32_t ctxtRegVal, int verify) 1365{ 1366 DPRINTFn(4, sc->sc_dev, "%s(%u, %u, %u)\n", 1367 __func__, ctxtNum, ctxtReg, ctxtRegVal); 1368 /* 1369 * Context 0 has no STARTPC. Instead, this value is used to set 1370 * NextPC for Background ECS, to set where NPE starts executing code 1371 */ 1372 if (ctxtNum == 0 && ctxtReg == IX_NPEDL_CTXT_REG_STARTPC) { 1373 /* read BG_CTXT_REG_0, update NEXTPC bits, & write back to reg*/ 1374 uint32_t v = npe_ecs_reg_read(sc, IX_NPEDL_ECS_BG_CTXT_REG_0); 1375 v &= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC; 1376 v |= (ctxtRegVal << IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC) & 1377 IX_NPEDL_MASK_ECS_REG_0_NEXTPC; 1378 1379 npe_ecs_reg_write(sc, IX_NPEDL_ECS_BG_CTXT_REG_0, v); 1380 return 0; 1381 } else { 1382 static const struct { 1383 uint32_t regAddress; 1384 uint32_t regSize; 1385 } regAccInfo[IX_NPEDL_CTXT_REG_MAX] = { 1386 { IX_NPEDL_CTXT_REG_ADDR_STEVT, 1387 IX_NPEDL_REG_SIZE_BYTE }, 1388 { IX_NPEDL_CTXT_REG_ADDR_STARTPC, 1389 IX_NPEDL_REG_SIZE_SHORT }, 1390 { IX_NPEDL_CTXT_REG_ADDR_REGMAP, 1391 IX_NPEDL_REG_SIZE_SHORT }, 1392 { IX_NPEDL_CTXT_REG_ADDR_CINDEX, 1393 IX_NPEDL_REG_SIZE_BYTE } 1394 }; 1395 return npe_logical_reg_write(sc, regAccInfo[ctxtReg].regAddress, 1396 ctxtRegVal, regAccInfo[ctxtReg].regSize, ctxtNum, verify); 1397 } 1398} 1399 1400/* 1401 * NPE Mailbox support. 1402 */ 1403#define IX_NPEMH_MAXTRIES 100000 1404 1405static int 1406ofifo_wait(struct ixpnpe_softc *sc) 1407{ 1408 int i; 1409 1410 for (i = 0; i < IX_NPEMH_MAXTRIES; i++) { 1411 if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_OFNE) 1412 return 1; 1413 DELAY(10); 1414 } 1415 device_printf(sc->sc_dev, "%s: timeout, last status 0x%x\n", 1416 __func__, npe_reg_read(sc, IX_NPESTAT)); 1417 return 0; 1418} 1419 1420static int 1421getmsg(struct ixpnpe_softc *sc, uint32_t msg[2]) 1422{ 1423 mtx_assert(&sc->sc_mtx, MA_OWNED); 1424 1425 if (!ofifo_wait(sc)) 1426 return EAGAIN; 1427 msg[0] = npe_reg_read(sc, IX_NPEFIFO); 1428 DPRINTF(sc->sc_dev, "%s: msg0 0x%x\n", __func__, msg[0]); 1429 if (!ofifo_wait(sc)) 1430 return EAGAIN; 1431 msg[1] = npe_reg_read(sc, IX_NPEFIFO); 1432 DPRINTF(sc->sc_dev, "%s: msg1 0x%x\n", __func__, msg[1]); 1433 return 0; 1434} 1435 1436static void 1437ixpnpe_intr(void *arg) 1438{ 1439 struct ixpnpe_softc *sc = arg; 1440 uint32_t status; 1441 1442 mtx_lock(&sc->sc_mtx); 1443 status = npe_reg_read(sc, IX_NPESTAT); 1444 DPRINTF(sc->sc_dev, "%s: status 0x%x\n", __func__, status); 1445 if ((status & IX_NPESTAT_OFINT) == 0) { 1446 /* NB: should not happen */ 1447 device_printf(sc->sc_dev, "%s: status 0x%x\n", 1448 __func__, status); 1449 /* XXX must silence interrupt? */ 1450 mtx_unlock(&sc->sc_mtx); 1451 return; 1452 } 1453 /* 1454 * A message is waiting in the output FIFO, copy it so 1455 * the interrupt will be silenced. 1456 */ 1457 if (getmsg(sc, sc->sc_msg) == 0) 1458 sc->sc_msgwaiting = 1; 1459 mtx_unlock(&sc->sc_mtx); 1460} 1461 1462static int 1463ififo_wait(struct ixpnpe_softc *sc) 1464{ 1465 int i; 1466 1467 for (i = 0; i < IX_NPEMH_MAXTRIES; i++) { 1468 if (npe_reg_read(sc, IX_NPESTAT) & IX_NPESTAT_IFNF) 1469 return 1; 1470 DELAY(10); 1471 } 1472 device_printf(sc->sc_dev, "%s: timeout, last status 0x%x\n", 1473 __func__, npe_reg_read(sc, IX_NPESTAT)); 1474 return 0; 1475} 1476 1477static int 1478putmsg(struct ixpnpe_softc *sc, const uint32_t msg[2]) 1479{ 1480 mtx_assert(&sc->sc_mtx, MA_OWNED); 1481 1482 DPRINTF(sc->sc_dev, "%s: msg 0x%x:0x%x\n", __func__, msg[0], msg[1]); 1483 if (!ififo_wait(sc)) 1484 return EIO; 1485 npe_reg_write(sc, IX_NPEFIFO, msg[0]); 1486 if (!ififo_wait(sc)) 1487 return EIO; 1488 npe_reg_write(sc, IX_NPEFIFO, msg[1]); 1489 1490 return 0; 1491} 1492 1493/* 1494 * Send a msg to the NPE and wait for a reply. We spin as 1495 * we may be called early with interrupts not properly setup. 1496 */ 1497int 1498ixpnpe_sendandrecvmsg_sync(struct ixpnpe_softc *sc, 1499 const uint32_t send[2], uint32_t recv[2]) 1500{ 1501 int error; 1502 1503 mtx_lock(&sc->sc_mtx); 1504 error = putmsg(sc, send); 1505 if (error == 0) 1506 error = getmsg(sc, recv); 1507 mtx_unlock(&sc->sc_mtx); 1508 1509 return error; 1510} 1511 1512/* 1513 * Send a msg to the NPE w/o waiting for a reply. 1514 */ 1515int 1516ixpnpe_sendmsg_async(struct ixpnpe_softc *sc, const uint32_t msg[2]) 1517{ 1518 int error; 1519 1520 mtx_lock(&sc->sc_mtx); 1521 error = putmsg(sc, msg); 1522 mtx_unlock(&sc->sc_mtx); 1523 1524 return error; 1525} 1526 1527static int 1528recvmsg_locked(struct ixpnpe_softc *sc, uint32_t msg[2]) 1529{ 1530 mtx_assert(&sc->sc_mtx, MA_OWNED); 1531 1532 DPRINTF(sc->sc_dev, "%s: msgwaiting %d\n", __func__, sc->sc_msgwaiting); 1533 if (sc->sc_msgwaiting) { 1534 msg[0] = sc->sc_msg[0]; 1535 msg[1] = sc->sc_msg[1]; 1536 sc->sc_msgwaiting = 0; 1537 return 0; 1538 } 1539 return EAGAIN; 1540} 1541 1542/* 1543 * Receive any msg previously received from the NPE. If nothing 1544 * is available we return EAGAIN and the caller is required to 1545 * do a synchronous receive or try again later. 1546 */ 1547int 1548ixpnpe_recvmsg_async(struct ixpnpe_softc *sc, uint32_t msg[2]) 1549{ 1550 int error; 1551 1552 mtx_lock(&sc->sc_mtx); 1553 error = recvmsg_locked(sc, msg); 1554 mtx_unlock(&sc->sc_mtx); 1555 1556 return error; 1557} 1558 1559/* 1560 * Receive a msg from the NPE. If one was received asynchronously 1561 * then it's returned; otherwise we poll synchronously. 1562 */ 1563int 1564ixpnpe_recvmsg_sync(struct ixpnpe_softc *sc, uint32_t msg[2]) 1565{ 1566 int error; 1567 1568 mtx_lock(&sc->sc_mtx); 1569 error = recvmsg_locked(sc, msg); 1570 if (error == EAGAIN) 1571 error = getmsg(sc, msg); 1572 mtx_unlock(&sc->sc_mtx); 1573 1574 return error; 1575} 1576