예제 #1
0
/**
 * __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);
}
예제 #2
0
/**
 * 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;
}