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