/* * Lemma to deal with race condition of write..read to epb regs */ static int epb_trans(struct qib_devdata *dd, u16 reg, u64 i_val, u64 *o_vp) { int tries; u64 transval; qib_write_kreg(dd, reg, i_val); /* Throw away first read, as RDY bit may be stale */ transval = qib_read_kreg64(dd, reg); for (tries = EPB_TRANS_TRIES; tries; --tries) { transval = qib_read_kreg32(dd, reg); if (transval & EPB_TRANS_RDY) break; udelay(5); } if (transval & EPB_TRANS_ERR) return -1; if (tries > 0 && o_vp) *o_vp = transval; return tries; }
/* * Below is portion of IBA7220-specific bringup_serdes() that actually * deals with registers and memory within the SerDes itself. * Post IB uC code version 1.32.17, was_reset being 1 is not really * informative, so we double-check. */ int qib_sd7220_init(struct qib_devdata *dd) { const struct firmware *fw; int ret = 1; /* default to failure */ int first_reset, was_reset; /* SERDES MPU reset recorded in D0 */ was_reset = (qib_read_kreg64(dd, kr_ibserdesctrl) & 1); if (!was_reset) { /* entered with reset not asserted, we need to do it */ qib_ibsd_reset(dd, 1); qib_sd_trimdone_monitor(dd, "Driver-reload"); } ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev); if (ret) goto done; /* Substitute our deduced value for was_reset */ ret = qib_ibsd_ucode_loaded(dd->pport, fw); if (ret < 0) goto bail; first_reset = !ret; /* First reset if IBSD uCode not yet loaded */ /* * Alter some regs per vendor latest doc, reset-defaults * are not right for IB. */ ret = qib_sd_early(dd); if (ret < 0) { qib_dev_err(dd, "Failed to set IB SERDES early defaults\n"); goto bail; } /* * Set DAC manual trim IB. * We only do this once after chip has been reset (usually * same as once per system boot). */ if (first_reset) { ret = qib_sd_dactrim(dd); if (ret < 0) { qib_dev_err(dd, "Failed IB SERDES DAC trim\n"); goto bail; } } /* * Set various registers (DDS and RXEQ) that will be * controlled by IBC (in 1.2 mode) to reasonable preset values * Calling the "internal" version avoids the "check for needed" * and "trimdone monitor" that might be counter-productive. */ ret = qib_internal_presets(dd); if (ret < 0) { qib_dev_err(dd, "Failed to set IB SERDES presets\n"); goto bail; } ret = qib_sd_trimself(dd, 0x80); if (ret < 0) { qib_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n"); goto bail; } /* Load image, then try to verify */ ret = 0; /* Assume success */ if (first_reset) { int vfy; int trim_done; ret = qib_sd7220_ib_load(dd, fw); if (ret < 0) { qib_dev_err(dd, "Failed to load IB SERDES image\n"); goto bail; } else { /* Loaded image, try to verify */ vfy = qib_sd7220_ib_vfy(dd, fw); if (vfy != ret) { qib_dev_err(dd, "SERDES PRAM VFY failed\n"); goto bail; } /* end if verified */ } /* end if loaded */ /* * Loaded and verified. Almost good... * hold "success" in ret */ ret = 0; /* * Prev steps all worked, continue bringup * De-assert RESET to uC, only in first reset, to allow * trimming. * * Since our default setup sets START_EQ1 to * PRESET, we need to clear that for this very first run. */ ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38); if (ret < 0) { qib_dev_err(dd, "Failed clearing START_EQ1\n"); goto bail; } qib_ibsd_reset(dd, 0); /* * If this is not the first reset, trimdone should be set * already. We may need to check about this. */ trim_done = qib_sd_trimdone_poll(dd); /* * Whether or not trimdone succeeded, we need to put the * uC back into reset to avoid a possible fight with the * IBC state-machine. */ qib_ibsd_reset(dd, 1); if (!trim_done) { qib_dev_err(dd, "No TRIMDONE seen\n"); goto bail; } /* * DEBUG: check each time we reset if trimdone bits have * gotten cleared, and re-set them. */ qib_sd_trimdone_monitor(dd, "First-reset"); /* Remember so we do not re-do the load, dactrim, etc. */ dd->cspec->serdes_first_init_done = 1; } /* * setup for channel training and load values for * RxEq and DDS in tables used by IBC in IB1.2 mode */ ret = 0; if (qib_sd_setvals(dd) >= 0) goto done; bail: ret = 1; done: /* start relock timer regardless, but start at 1 second */ set_7220_relock_poll(dd, -1); release_firmware(fw); return ret; }
static void qib_sd_trimdone_monitor(struct qib_devdata *dd, const char *where) { int ret, chn, baduns; u64 val; if (!where) where = "?"; /* give time for reset to settle out in EPB */ udelay(2); ret = qib_resync_ibepb(dd); if (ret < 0) qib_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where); /* Do "sacrificial read" to get EPB in sane state after reset */ ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0); if (ret < 0) qib_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where); /* Check/show "summary" Trim-done bit in IBCStatus */ val = qib_read_kreg64(dd, kr_ibcstatus); if (!(val & (1ULL << 11))) qib_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where); /* * Do "dummy read/mod/wr" to get EPB in sane state after reset * The default value for MPREG6 is 0. */ udelay(2); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80); if (ret < 0) qib_dev_err(dd, "Failed Dummy RMW, (%s)\n", where); udelay(10); baduns = 0; for (chn = 3; chn >= 0; --chn) { /* Read CTRL reg for each channel to check TRIMDONE */ ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0, 0); if (ret < 0) qib_dev_err(dd, "Failed checking TRIMDONE, chn %d (%s)\n", chn, where); if (!(ret & 0x10)) { int probe; baduns |= (1 << chn); qib_dev_err(dd, "TRIMDONE cleared on chn %d (%02X). (%s)\n", chn, ret, where); probe = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_PGUDP(0), 0, 0); qib_dev_err(dd, "probe is %d (%02X)\n", probe, probe); probe = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0, 0); qib_dev_err(dd, "re-read: %d (%02X)\n", probe, probe); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); if (ret < 0) qib_dev_err(dd, "Err on TRIMDONE rewrite1\n"); } } for (chn = 3; chn >= 0; --chn) { /* Read CTRL reg for each channel to check TRIMDONE */ if (baduns & (1 << chn)) { qib_dev_err(dd, "Resetting TRIMDONE on chn %d (%s)\n", chn, where); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); if (ret < 0) qib_dev_err(dd, "Failed re-setting TRIMDONE, chn %d (%s)\n", chn, where); } } }
/* * Localize the stuff that should be done to change IB uC reset * returns <0 for errors. */ static int qib_ibsd_reset(struct qib_devdata *dd, int assert_rst) { u64 rst_val; int ret = 0; unsigned long flags; rst_val = qib_read_kreg64(dd, kr_ibserdesctrl); if (assert_rst) { /* * Vendor recommends "interrupting" uC before reset, to * minimize possible glitches. */ spin_lock_irqsave(&dd->cspec->sdepb_lock, flags); epb_access(dd, IB_7220_SERDES, 1); rst_val |= 1ULL; /* Squelch possible parity error from _asserting_ reset */ qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask & ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR); qib_write_kreg(dd, kr_ibserdesctrl, rst_val); /* flush write, delay to ensure it took effect */ qib_read_kreg32(dd, kr_scratch); udelay(2); /* once it's reset, can remove interrupt */ epb_access(dd, IB_7220_SERDES, -1); spin_unlock_irqrestore(&dd->cspec->sdepb_lock, flags); } else { /* * Before we de-assert reset, we need to deal with * possible glitch on the Parity-error line. * Suppress it around the reset, both in chip-level * hwerrmask and in IB uC control reg. uC will allow * it again during startup. */ u64 val; rst_val &= ~(1ULL); qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask & ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR); ret = qib_resync_ibepb(dd); if (ret < 0) qib_dev_err(dd, "unable to re-sync IB EPB\n"); /* set uC control regs to suppress parity errs */ ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1); if (ret < 0) goto bail; /* IB uC code past Version 1.32.17 allow suppression of wdog */ ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80); if (ret < 0) { qib_dev_err(dd, "Failed to set WDOG disable\n"); goto bail; } qib_write_kreg(dd, kr_ibserdesctrl, rst_val); /* flush write, delay for startup */ qib_read_kreg32(dd, kr_scratch); udelay(1); /* clear, then re-enable parity errs */ qib_sd7220_clr_ibpar(dd); val = qib_read_kreg64(dd, kr_hwerrstatus); if (val & QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR) { qib_dev_err(dd, "IBUC Parity still set after RST\n"); dd->cspec->hwerrmask &= ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR; } qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask); } bail: return ret; }
int qib_sd7220_init(struct qib_devdata *dd) { const struct firmware *fw; int ret = 1; int first_reset, was_reset; was_reset = (qib_read_kreg64(dd, kr_ibserdesctrl) & 1); if (!was_reset) { qib_ibsd_reset(dd, 1); qib_sd_trimdone_monitor(dd, "Driver-reload"); } ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev); if (ret) { qib_dev_err(dd, "Failed to load IB SERDES image\n"); goto done; } ret = qib_ibsd_ucode_loaded(dd->pport, fw); if (ret < 0) goto bail; first_reset = !ret; ret = qib_sd_early(dd); if (ret < 0) { qib_dev_err(dd, "Failed to set IB SERDES early defaults\n"); goto bail; } if (first_reset) { ret = qib_sd_dactrim(dd); if (ret < 0) { qib_dev_err(dd, "Failed IB SERDES DAC trim\n"); goto bail; } } ret = qib_internal_presets(dd); if (ret < 0) { qib_dev_err(dd, "Failed to set IB SERDES presets\n"); goto bail; } ret = qib_sd_trimself(dd, 0x80); if (ret < 0) { qib_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n"); goto bail; } ret = 0; if (first_reset) { int vfy; int trim_done; ret = qib_sd7220_ib_load(dd, fw); if (ret < 0) { qib_dev_err(dd, "Failed to load IB SERDES image\n"); goto bail; } else { vfy = qib_sd7220_ib_vfy(dd, fw); if (vfy != ret) { qib_dev_err(dd, "SERDES PRAM VFY failed\n"); goto bail; } } ret = 0; ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38); if (ret < 0) { qib_dev_err(dd, "Failed clearing START_EQ1\n"); goto bail; } qib_ibsd_reset(dd, 0); trim_done = qib_sd_trimdone_poll(dd); qib_ibsd_reset(dd, 1); if (!trim_done) { qib_dev_err(dd, "No TRIMDONE seen\n"); goto bail; } qib_sd_trimdone_monitor(dd, "First-reset"); dd->cspec->serdes_first_init_done = 1; } ret = 0; if (qib_sd_setvals(dd) >= 0) goto done; bail: ret = 1; done: set_7220_relock_poll(dd, -1); release_firmware(fw); return ret; }
static void qib_sd_trimdone_monitor(struct qib_devdata *dd, const char *where) { int ret, chn, baduns; u64 val; if (!where) where = "?"; udelay(2); ret = qib_resync_ibepb(dd); if (ret < 0) qib_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0); if (ret < 0) qib_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where); val = qib_read_kreg64(dd, kr_ibcstatus); if (!(val & (1ULL << 11))) qib_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where); udelay(2); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80); if (ret < 0) qib_dev_err(dd, "Failed Dummy RMW, (%s)\n", where); udelay(10); baduns = 0; for (chn = 3; chn >= 0; --chn) { ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0, 0); if (ret < 0) qib_dev_err(dd, "Failed checking TRIMDONE, chn %d" " (%s)\n", chn, where); if (!(ret & 0x10)) { int probe; baduns |= (1 << chn); qib_dev_err(dd, "TRIMDONE cleared on chn %d (%02X)." " (%s)\n", chn, ret, where); probe = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_PGUDP(0), 0, 0); qib_dev_err(dd, "probe is %d (%02X)\n", probe, probe); probe = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0, 0); qib_dev_err(dd, "re-read: %d (%02X)\n", probe, probe); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); if (ret < 0) qib_dev_err(dd, "Err on TRIMDONE rewrite1\n"); } } for (chn = 3; chn >= 0; --chn) { if (baduns & (1 << chn)) { qib_dev_err(dd, "Reseting TRIMDONE on chn %d (%s)\n", chn, where); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); if (ret < 0) qib_dev_err(dd, "Failed re-setting " "TRIMDONE, chn %d (%s)\n", chn, where); } } }
static int qib_ibsd_reset(struct qib_devdata *dd, int assert_rst) { u64 rst_val; int ret = 0; unsigned long flags; rst_val = qib_read_kreg64(dd, kr_ibserdesctrl); if (assert_rst) { spin_lock_irqsave(&dd->cspec->sdepb_lock, flags); epb_access(dd, IB_7220_SERDES, 1); rst_val |= 1ULL; qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask & ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR); qib_write_kreg(dd, kr_ibserdesctrl, rst_val); qib_read_kreg32(dd, kr_scratch); udelay(2); epb_access(dd, IB_7220_SERDES, -1); spin_unlock_irqrestore(&dd->cspec->sdepb_lock, flags); } else { u64 val; rst_val &= ~(1ULL); qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask & ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR); ret = qib_resync_ibepb(dd); if (ret < 0) qib_dev_err(dd, "unable to re-sync IB EPB\n"); ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1); if (ret < 0) goto bail; ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80); if (ret < 0) { qib_dev_err(dd, "Failed to set WDOG disable\n"); goto bail; } qib_write_kreg(dd, kr_ibserdesctrl, rst_val); qib_read_kreg32(dd, kr_scratch); udelay(1); qib_sd7220_clr_ibpar(dd); val = qib_read_kreg64(dd, kr_hwerrstatus); if (val & QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR) { qib_dev_err(dd, "IBUC Parity still set after RST\n"); dd->cspec->hwerrmask &= ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR; } qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask); } bail: return ret; }