/** * Callback to setup calendar and miscellaneous settings before clock detection * * @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). * @num_ports: Number of ports to configure on SPI * * Returns Zero on success, non-zero error code on failure (will cause * SPI initialization to abort) */ int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode, int num_ports) { int port; int index; if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { union cvmx_srxx_com_ctl srxx_com_ctl; union cvmx_srxx_spi4_stat srxx_spi4_stat; /* SRX0 number of Ports */ srxx_com_ctl.u64 = 0; srxx_com_ctl.s.prts = num_ports - 1; srxx_com_ctl.s.st_en = 0; srxx_com_ctl.s.inf_en = 0; cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); /* SRX0 Calendar Table. This round robbins through all ports */ port = 0; index = 0; while (port < num_ports) { union cvmx_srxx_spi4_calx srxx_spi4_calx; srxx_spi4_calx.u64 = 0; srxx_spi4_calx.s.prt0 = port++; srxx_spi4_calx.s.prt1 = port++; srxx_spi4_calx.s.prt2 = port++; srxx_spi4_calx.s.prt3 = port++; srxx_spi4_calx.s.oddpar = ~(cvmx_dpop(srxx_spi4_calx.u64) & 1); cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), srxx_spi4_calx.u64); index++; } srxx_spi4_stat.u64 = 0; srxx_spi4_stat.s.len = num_ports; srxx_spi4_stat.s.m = 1; cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface), srxx_spi4_stat.u64); } if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { union cvmx_stxx_arb_ctl stxx_arb_ctl; union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max; union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh; union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl; union cvmx_stxx_spi4_stat stxx_spi4_stat; union cvmx_stxx_spi4_dat stxx_spi4_dat; /* STX0 Config */ stxx_arb_ctl.u64 = 0; stxx_arb_ctl.s.igntpa = 0; stxx_arb_ctl.s.mintrn = 0; cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64); gmxx_tx_spi_max.u64 = 0; gmxx_tx_spi_max.s.max1 = 8; gmxx_tx_spi_max.s.max2 = 4; gmxx_tx_spi_max.s.slice = 0; cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface), gmxx_tx_spi_max.u64); gmxx_tx_spi_thresh.u64 = 0; gmxx_tx_spi_thresh.s.thresh = 4; cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface), gmxx_tx_spi_thresh.u64); gmxx_tx_spi_ctl.u64 = 0; gmxx_tx_spi_ctl.s.tpa_clr = 0; gmxx_tx_spi_ctl.s.cont_pkt = 0; cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface), gmxx_tx_spi_ctl.u64); /* STX0 Training Control */ stxx_spi4_dat.u64 = 0; /*Minimum needed by dynamic alignment */ stxx_spi4_dat.s.alpha = 32; stxx_spi4_dat.s.max_t = 0xFFFF; /*Minimum interval is 0x20 */ cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface), stxx_spi4_dat.u64); /* STX0 Calendar Table. This round robbins through all ports */ port = 0; index = 0; while (port < num_ports) { union cvmx_stxx_spi4_calx stxx_spi4_calx; stxx_spi4_calx.u64 = 0; stxx_spi4_calx.s.prt0 = port++; stxx_spi4_calx.s.prt1 = port++; stxx_spi4_calx.s.prt2 = port++; stxx_spi4_calx.s.prt3 = port++; stxx_spi4_calx.s.oddpar = ~(cvmx_dpop(stxx_spi4_calx.u64) & 1); cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), stxx_spi4_calx.u64); index++; } stxx_spi4_stat.u64 = 0; stxx_spi4_stat.s.len = num_ports; stxx_spi4_stat.s.m = 1; cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface), stxx_spi4_stat.u64); } return 0; }
int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode, int num_ports) { int port; int index; if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { union cvmx_srxx_com_ctl srxx_com_ctl; union cvmx_srxx_spi4_stat srxx_spi4_stat; srxx_com_ctl.u64 = 0; srxx_com_ctl.s.prts = num_ports - 1; srxx_com_ctl.s.st_en = 0; srxx_com_ctl.s.inf_en = 0; cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); port = 0; index = 0; while (port < num_ports) { union cvmx_srxx_spi4_calx srxx_spi4_calx; srxx_spi4_calx.u64 = 0; srxx_spi4_calx.s.prt0 = port++; srxx_spi4_calx.s.prt1 = port++; srxx_spi4_calx.s.prt2 = port++; srxx_spi4_calx.s.prt3 = port++; srxx_spi4_calx.s.oddpar = ~(cvmx_dpop(srxx_spi4_calx.u64) & 1); cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), srxx_spi4_calx.u64); index++; } srxx_spi4_stat.u64 = 0; srxx_spi4_stat.s.len = num_ports; srxx_spi4_stat.s.m = 1; cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface), srxx_spi4_stat.u64); } if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { union cvmx_stxx_arb_ctl stxx_arb_ctl; union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max; union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh; union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl; union cvmx_stxx_spi4_stat stxx_spi4_stat; union cvmx_stxx_spi4_dat stxx_spi4_dat; stxx_arb_ctl.u64 = 0; stxx_arb_ctl.s.igntpa = 0; stxx_arb_ctl.s.mintrn = 0; cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64); gmxx_tx_spi_max.u64 = 0; gmxx_tx_spi_max.s.max1 = 8; gmxx_tx_spi_max.s.max2 = 4; gmxx_tx_spi_max.s.slice = 0; cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface), gmxx_tx_spi_max.u64); gmxx_tx_spi_thresh.u64 = 0; gmxx_tx_spi_thresh.s.thresh = 4; cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface), gmxx_tx_spi_thresh.u64); gmxx_tx_spi_ctl.u64 = 0; gmxx_tx_spi_ctl.s.tpa_clr = 0; gmxx_tx_spi_ctl.s.cont_pkt = 0; cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface), gmxx_tx_spi_ctl.u64); stxx_spi4_dat.u64 = 0; stxx_spi4_dat.s.alpha = 32; stxx_spi4_dat.s.max_t = 0xFFFF; cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface), stxx_spi4_dat.u64); port = 0; index = 0; while (port < num_ports) { union cvmx_stxx_spi4_calx stxx_spi4_calx; stxx_spi4_calx.u64 = 0; stxx_spi4_calx.s.prt0 = port++; stxx_spi4_calx.s.prt1 = port++; stxx_spi4_calx.s.prt2 = port++; stxx_spi4_calx.s.prt3 = port++; stxx_spi4_calx.s.oddpar = ~(cvmx_dpop(stxx_spi4_calx.u64) & 1); cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), stxx_spi4_calx.u64); index++; } stxx_spi4_stat.u64 = 0; stxx_spi4_stat.s.len = num_ports; stxx_spi4_stat.s.m = 1; cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface), stxx_spi4_stat.u64); } return 0; }