/** * __cvmx_interrupt_stxx_int_msk_enable enables all interrupt bits in cvmx_stxx_int_msk_t */ void __cvmx_interrupt_stxx_int_msk_enable(int index) { union cvmx_stxx_int_msk stx_int_msk; cvmx_write_csr(CVMX_STXX_INT_REG(index), cvmx_read_csr(CVMX_STXX_INT_REG(index))); stx_int_msk.u64 = 0; if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { /* Skipping stx_int_msk.s.reserved_8_63 */ stx_int_msk.s.frmerr = 1; stx_int_msk.s.unxfrm = 1; stx_int_msk.s.nosync = 1; stx_int_msk.s.diperr = 1; stx_int_msk.s.datovr = 1; stx_int_msk.s.ovrbst = 1; stx_int_msk.s.calpar1 = 1; stx_int_msk.s.calpar0 = 1; } if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { /* Skipping stx_int_msk.s.reserved_8_63 */ stx_int_msk.s.frmerr = 1; stx_int_msk.s.unxfrm = 1; stx_int_msk.s.nosync = 1; stx_int_msk.s.diperr = 1; stx_int_msk.s.datovr = 1; stx_int_msk.s.ovrbst = 1; stx_int_msk.s.calpar1 = 1; stx_int_msk.s.calpar0 = 1; } cvmx_write_csr(CVMX_STXX_INT_MSK(index), stx_int_msk.u64); }
/** * Callback to perform SPI4 reset * * @interface: The identifier of the packet interface to configure and * use as a SPI interface. * @mode: The operating mode for the SPI interface. The interface * can operate as a full duplex (both Tx and Rx data paths * active) or as a halfplex (either the Tx data path is * active or the Rx data path is active, but not both). * * Returns Zero on success, non-zero error code on failure (will cause * SPI initialization to abort) */ int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode) { union cvmx_spxx_dbg_deskew_ctl spxx_dbg_deskew_ctl; union cvmx_spxx_clk_ctl spxx_clk_ctl; union cvmx_spxx_bist_stat spxx_bist_stat; union cvmx_spxx_int_msk spxx_int_msk; union cvmx_stxx_int_msk stxx_int_msk; union cvmx_spxx_trn4_ctl spxx_trn4_ctl; int index; uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; /* Disable SPI error events while we run BIST */ spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); /* Run BIST in the SPI interface */ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), 0); cvmx_write_csr(CVMX_STXX_COM_CTL(interface), 0); spxx_clk_ctl.u64 = 0; spxx_clk_ctl.s.runbist = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); cvmx_wait(10 * MS); spxx_bist_stat.u64 = cvmx_read_csr(CVMX_SPXX_BIST_STAT(interface)); if (spxx_bist_stat.s.stat0) cvmx_dprintf ("ERROR SPI%d: BIST failed on receive datapath FIFO\n", interface); if (spxx_bist_stat.s.stat1) cvmx_dprintf("ERROR SPI%d: BIST failed on RX calendar table\n", interface); if (spxx_bist_stat.s.stat2) cvmx_dprintf("ERROR SPI%d: BIST failed on TX calendar table\n", interface); /* Clear the calendar table after BIST to fix parity errors */ for (index = 0; index < 32; index++) { union cvmx_srxx_spi4_calx srxx_spi4_calx; union cvmx_stxx_spi4_calx stxx_spi4_calx; srxx_spi4_calx.u64 = 0; srxx_spi4_calx.s.oddpar = 1; cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), srxx_spi4_calx.u64); stxx_spi4_calx.u64 = 0; stxx_spi4_calx.s.oddpar = 1; cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), stxx_spi4_calx.u64); } /* Re enable reporting of error interrupts */ cvmx_write_csr(CVMX_SPXX_INT_REG(interface), cvmx_read_csr(CVMX_SPXX_INT_REG(interface))); cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); cvmx_write_csr(CVMX_STXX_INT_REG(interface), cvmx_read_csr(CVMX_STXX_INT_REG(interface))); cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); /* Setup the CLKDLY right in the middle */ spxx_clk_ctl.u64 = 0; spxx_clk_ctl.s.seetrn = 0; spxx_clk_ctl.s.clkdly = 0x10; spxx_clk_ctl.s.runbist = 0; spxx_clk_ctl.s.statdrv = 0; /* This should always be on the opposite edge as statdrv */ spxx_clk_ctl.s.statrcv = 1; spxx_clk_ctl.s.sndtrn = 0; spxx_clk_ctl.s.drptrn = 0; spxx_clk_ctl.s.rcvtrn = 0; spxx_clk_ctl.s.srxdlck = 0; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); cvmx_wait(100 * MS); /* Reset SRX0 DLL */ spxx_clk_ctl.s.srxdlck = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); /* Waiting for Inf0 Spi4 RX DLL to lock */ cvmx_wait(100 * MS); /* Enable dynamic alignment */ spxx_trn4_ctl.s.trntest = 0; spxx_trn4_ctl.s.jitter = 1; spxx_trn4_ctl.s.clr_boot = 1; spxx_trn4_ctl.s.set_boot = 0; if (OCTEON_IS_MODEL(OCTEON_CN58XX)) spxx_trn4_ctl.s.maxdist = 3; else spxx_trn4_ctl.s.maxdist = 8; spxx_trn4_ctl.s.macro_en = 1; spxx_trn4_ctl.s.mux_en = 1; cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64); spxx_dbg_deskew_ctl.u64 = 0; cvmx_write_csr(CVMX_SPXX_DBG_DESKEW_CTL(interface), spxx_dbg_deskew_ctl.u64); return 0; }
static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) { irqreturn_t return_status = IRQ_NONE; union cvmx_npi_rsl_int_blocks rsl_int_blocks; /* Check and see if this interrupt was caused by the GMX block */ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */ union cvmx_spxx_int_reg spx_int_reg; union cvmx_stxx_int_reg stx_int_reg; spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1)); cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64); if (!need_retrain[1]) { spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1)); if (spx_int_reg.s.spf) pr_err("SPI1: SRX Spi4 interface down\n"); if (spx_int_reg.s.calerr) pr_err("SPI1: SRX Spi4 Calendar table " "parity error\n"); if (spx_int_reg.s.syncerr) pr_err("SPI1: SRX Consecutive Spi4 DIP4 " "errors have exceeded " "SPX_ERR_CTL[ERRCNT]\n"); if (spx_int_reg.s.diperr) pr_err("SPI1: SRX Spi4 DIP4 error\n"); if (spx_int_reg.s.tpaovr) pr_err("SPI1: SRX Selected port has hit " "TPA overflow\n"); if (spx_int_reg.s.rsverr) pr_err("SPI1: SRX Spi4 reserved control " "word detected\n"); if (spx_int_reg.s.drwnng) pr_err("SPI1: SRX Spi4 receive FIFO " "drowning/overflow\n"); if (spx_int_reg.s.clserr) pr_err("SPI1: SRX Spi4 packet closed on " "non-16B alignment without EOP\n"); if (spx_int_reg.s.spiovr) pr_err("SPI1: SRX Spi4 async FIFO overflow\n"); if (spx_int_reg.s.abnorm) pr_err("SPI1: SRX Abnormal packet " "termination (ERR bit)\n"); if (spx_int_reg.s.prtnxa) pr_err("SPI1: SRX Port out of range\n"); } stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1)); cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64); if (!need_retrain[1]) { stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1)); if (stx_int_reg.s.syncerr) pr_err("SPI1: STX Interface encountered a " "fatal error\n"); if (stx_int_reg.s.frmerr) pr_err("SPI1: STX FRMCNT has exceeded " "STX_DIP_CNT[MAXFRM]\n"); if (stx_int_reg.s.unxfrm) pr_err("SPI1: STX Unexpected framing " "sequence\n"); if (stx_int_reg.s.nosync) pr_err("SPI1: STX ERRCNT has exceeded " "STX_DIP_CNT[MAXDIP]\n"); if (stx_int_reg.s.diperr) pr_err("SPI1: STX DIP2 error on the Spi4 " "Status channel\n"); if (stx_int_reg.s.datovr) pr_err("SPI1: STX Spi4 FIFO overflow error\n"); if (stx_int_reg.s.ovrbst) pr_err("SPI1: STX Transmit packet burst " "too big\n"); if (stx_int_reg.s.calpar1) pr_err("SPI1: STX Calendar Table Parity " "Error Bank1\n"); if (stx_int_reg.s.calpar0) pr_err("SPI1: STX Calendar Table Parity " "Error Bank0\n"); } cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0); cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0); need_retrain[1] = 1; return_status = IRQ_HANDLED; } if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */ union cvmx_spxx_int_reg spx_int_reg; union cvmx_stxx_int_reg stx_int_reg; spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0)); cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64); if (!need_retrain[0]) { spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0)); if (spx_int_reg.s.spf) pr_err("SPI0: SRX Spi4 interface down\n"); if (spx_int_reg.s.calerr) pr_err("SPI0: SRX Spi4 Calendar table " "parity error\n"); if (spx_int_reg.s.syncerr) pr_err("SPI0: SRX Consecutive Spi4 DIP4 " "errors have exceeded " "SPX_ERR_CTL[ERRCNT]\n"); if (spx_int_reg.s.diperr) pr_err("SPI0: SRX Spi4 DIP4 error\n"); if (spx_int_reg.s.tpaovr) pr_err("SPI0: SRX Selected port has hit " "TPA overflow\n"); if (spx_int_reg.s.rsverr) pr_err("SPI0: SRX Spi4 reserved control " "word detected\n"); if (spx_int_reg.s.drwnng) pr_err("SPI0: SRX Spi4 receive FIFO " "drowning/overflow\n"); if (spx_int_reg.s.clserr) pr_err("SPI0: SRX Spi4 packet closed on " "non-16B alignment without EOP\n"); if (spx_int_reg.s.spiovr) pr_err("SPI0: SRX Spi4 async FIFO overflow\n"); if (spx_int_reg.s.abnorm) pr_err("SPI0: SRX Abnormal packet " "termination (ERR bit)\n"); if (spx_int_reg.s.prtnxa) pr_err("SPI0: SRX Port out of range\n"); } stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0)); cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64); if (!need_retrain[0]) { stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0)); if (stx_int_reg.s.syncerr) pr_err("SPI0: STX Interface encountered a " "fatal error\n"); if (stx_int_reg.s.frmerr) pr_err("SPI0: STX FRMCNT has exceeded " "STX_DIP_CNT[MAXFRM]\n"); if (stx_int_reg.s.unxfrm) pr_err("SPI0: STX Unexpected framing " "sequence\n"); if (stx_int_reg.s.nosync) pr_err("SPI0: STX ERRCNT has exceeded " "STX_DIP_CNT[MAXDIP]\n"); if (stx_int_reg.s.diperr) pr_err("SPI0: STX DIP2 error on the Spi4 " "Status channel\n"); if (stx_int_reg.s.datovr) pr_err("SPI0: STX Spi4 FIFO overflow error\n"); if (stx_int_reg.s.ovrbst) pr_err("SPI0: STX Transmit packet burst " "too big\n"); if (stx_int_reg.s.calpar1) pr_err("SPI0: STX Calendar Table Parity " "Error Bank1\n"); if (stx_int_reg.s.calpar0) pr_err("SPI0: STX Calendar Table Parity " "Error Bank0\n"); } cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0); cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0); need_retrain[0] = 1; return_status = IRQ_HANDLED; } return return_status; }
int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode) { union cvmx_spxx_dbg_deskew_ctl spxx_dbg_deskew_ctl; union cvmx_spxx_clk_ctl spxx_clk_ctl; union cvmx_spxx_bist_stat spxx_bist_stat; union cvmx_spxx_int_msk spxx_int_msk; union cvmx_stxx_int_msk stxx_int_msk; union cvmx_spxx_trn4_ctl spxx_trn4_ctl; int index; uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), 0); cvmx_write_csr(CVMX_STXX_COM_CTL(interface), 0); spxx_clk_ctl.u64 = 0; spxx_clk_ctl.s.runbist = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); cvmx_wait(10 * MS); spxx_bist_stat.u64 = cvmx_read_csr(CVMX_SPXX_BIST_STAT(interface)); if (spxx_bist_stat.s.stat0) cvmx_dprintf ("ERROR SPI%d: BIST failed on receive datapath FIFO\n", interface); if (spxx_bist_stat.s.stat1) cvmx_dprintf("ERROR SPI%d: BIST failed on RX calendar table\n", interface); if (spxx_bist_stat.s.stat2) cvmx_dprintf("ERROR SPI%d: BIST failed on TX calendar table\n", interface); for (index = 0; index < 32; index++) { union cvmx_srxx_spi4_calx srxx_spi4_calx; union cvmx_stxx_spi4_calx stxx_spi4_calx; srxx_spi4_calx.u64 = 0; srxx_spi4_calx.s.oddpar = 1; cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), srxx_spi4_calx.u64); stxx_spi4_calx.u64 = 0; stxx_spi4_calx.s.oddpar = 1; cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), stxx_spi4_calx.u64); } cvmx_write_csr(CVMX_SPXX_INT_REG(interface), cvmx_read_csr(CVMX_SPXX_INT_REG(interface))); cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); cvmx_write_csr(CVMX_STXX_INT_REG(interface), cvmx_read_csr(CVMX_STXX_INT_REG(interface))); cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); spxx_clk_ctl.u64 = 0; spxx_clk_ctl.s.seetrn = 0; spxx_clk_ctl.s.clkdly = 0x10; spxx_clk_ctl.s.runbist = 0; spxx_clk_ctl.s.statdrv = 0; spxx_clk_ctl.s.statrcv = 1; spxx_clk_ctl.s.sndtrn = 0; spxx_clk_ctl.s.drptrn = 0; spxx_clk_ctl.s.rcvtrn = 0; spxx_clk_ctl.s.srxdlck = 0; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); cvmx_wait(100 * MS); spxx_clk_ctl.s.srxdlck = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); cvmx_wait(100 * MS); spxx_trn4_ctl.s.trntest = 0; spxx_trn4_ctl.s.jitter = 1; spxx_trn4_ctl.s.clr_boot = 1; spxx_trn4_ctl.s.set_boot = 0; if (OCTEON_IS_MODEL(OCTEON_CN58XX)) spxx_trn4_ctl.s.maxdist = 3; else spxx_trn4_ctl.s.maxdist = 8; spxx_trn4_ctl.s.macro_en = 1; spxx_trn4_ctl.s.mux_en = 1; cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64); spxx_dbg_deskew_ctl.u64 = 0; cvmx_write_csr(CVMX_SPXX_DBG_DESKEW_CTL(interface), spxx_dbg_deskew_ctl.u64); return 0; }