/* *CallbacktoperformSPI4reset * *@interface:Theidentifierofthepacketinterfacetoconfigureand *useasaSPIinterface. *@mode:TheoperatingmodefortheSPIinterface.Theinterface *canoperateasafullduplex(bothTxandRxdatapaths *active)orasahalfplex(eithertheTxdatapathis *activeortheRxdatapathisactive,butnotboth). * *ReturnsZeroonsuccess,non-zeroerrorcodeonfailure(willcause *SPIinitializationtoabort)
*/ 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);
__delay(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;
/* 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;
cvmx_dprintf("SPI%d: Waiting to see RsClk...\n", interface);
timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; /* *Require100clocktransitionsinordertoavoidanynoiseinthe *beginning.
*/
clock_transitions = 100; do {
stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); if (stat.s.d4clk0 && stat.s.d4clk1 && clock_transitions) { /* *We'veseenaclocktransition,sodecrement *thenumberwestillneed
*/
clock_transitions--;
cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64);
stat.s.d4clk0 = 0;
stat.s.d4clk1 = 0;
} if (cvmx_get_cycle() > timeout_time) {
cvmx_dprintf("SPI%d: Timeout\n", interface); return -1;
}
} while (stat.s.d4clk0 == 0 || stat.s.d4clk1 == 0);
return0;
}
/* *Callbacktoperformlinktraining * *@interface:Theidentifierofthepacketinterfacetoconfigureand *useasaSPIinterface. *@mode:TheoperatingmodefortheSPIinterface.Theinterface *canoperateasafullduplex(bothTxandRxdatapaths *active)orasahalfplex(eithertheTxdatapathis *activeortheRxdatapathisactive,butnotboth). *@timeout:Timeouttowaitforlinktobetrained(inseconds) * *ReturnsZeroonsuccess,non-zeroerrorcodeonfailure(willcause *SPIinitializationtoabort)
*/ int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout)
{ union cvmx_spxx_trn4_ctl spxx_trn4_ctl; union cvmx_spxx_clk_stat stat;
uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000;
uint64_t timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; int rx_training_needed;
/* SRX0 & STX0 Inf0 Links are configured - begin training */ union cvmx_spxx_clk_ctl spxx_clk_ctl;
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 = 1;
spxx_clk_ctl.s.drptrn = 1;
spxx_clk_ctl.s.rcvtrn = 1;
spxx_clk_ctl.s.srxdlck = 1;
cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64);
__delay(1000 * MS);
/* SRX0 clear the boot bit */
spxx_trn4_ctl.u64 = cvmx_read_csr(CVMX_SPXX_TRN4_CTL(interface));
spxx_trn4_ctl.s.clr_boot = 1;
cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64);
/* Wait for the training sequence to complete */
cvmx_dprintf("SPI%d: Waiting for training\n", interface);
__delay(1000 * MS); /* Wait a really long time here */
timeout_time = cvmx_get_cycle() + 1000ull * MS * 600; /* *TheHRMsayswemustwaitfor34+16*MAXDISTtrainingsequences. *We'llbepessimisticandwaitforalotmore.
*/
rx_training_needed = 500; do {
stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); if (stat.s.srxtrn && rx_training_needed) {
rx_training_needed--;
cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64);
stat.s.srxtrn = 0;
} if (cvmx_get_cycle() > timeout_time) {
cvmx_dprintf("SPI%d: Timeout\n", interface); return -1;
}
} while (stat.s.srxtrn == 0);
return0;
}
/* *Callbacktoperformcalendardatasynchronization * *@interface:Theidentifierofthepacketinterfacetoconfigureand *useasaSPIinterface. *@mode:TheoperatingmodefortheSPIinterface.Theinterface *canoperateasafullduplex(bothTxandRxdatapaths *active)orasahalfplex(eithertheTxdatapathis *activeortheRxdatapathisactive,butnotboth). *@timeout:Timeouttowaitforcalendardatainseconds * *ReturnsZeroonsuccess,non-zeroerrorcodeonfailure(willcause *SPIinitializationtoabort)
*/ int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, int timeout)
{
uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { /* SRX0 interface should be good, send calendar data */ union cvmx_srxx_com_ctl srxx_com_ctl;
cvmx_dprintf
("SPI%d: Rx is synchronized, start sending calendar data\n",
interface);
srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface));
srxx_com_ctl.s.inf_en = 1;
srxx_com_ctl.s.st_en = 1;
cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);
}
if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { /* STX0 has achieved sync */ /* The corespondant board should be sending calendar data */ /* Enable the STX0 STAT receiver. */ union cvmx_spxx_clk_stat stat;
uint64_t timeout_time; union cvmx_stxx_com_ctl stxx_com_ctl;
stxx_com_ctl.u64 = 0;
stxx_com_ctl.s.st_en = 1;
cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64);
/* Waiting for calendar sync on STX0 STAT */
cvmx_dprintf("SPI%d: Waiting to sync on STX[%d] STAT\n",
interface, interface);
timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; /* SPX0_CLK_STAT - SPX0_CLK_STAT[STXCAL] should be 1 (bit10) */ do {
stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); if (cvmx_get_cycle() > timeout_time) {
cvmx_dprintf("SPI%d: Timeout\n", interface); return -1;
}
} while (stat.s.stxcal == 0);
}
return0;
}
/* *Callbacktohandleinterfaceup * *@interface:Theidentifierofthepacketinterfacetoconfigureand *useasaSPIinterface. *@mode:TheoperatingmodefortheSPIinterface.Theinterface *canoperateasafullduplex(bothTxandRxdatapaths *active)orasahalfplex(eithertheTxdatapathis *activeortheRxdatapathisactive,butnotboth). * *ReturnsZeroonsuccess,non-zeroerrorcodeonfailure(willcause *SPIinitializationtoabort)
*/ int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode)
{ union cvmx_gmxx_rxx_frm_min gmxx_rxx_frm_min; union cvmx_gmxx_rxx_frm_max gmxx_rxx_frm_max; union cvmx_gmxx_rxx_jabber gmxx_rxx_jabber;
if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { union cvmx_srxx_com_ctl srxx_com_ctl;
srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface));
srxx_com_ctl.s.inf_en = 1;
cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);
cvmx_dprintf("SPI%d: Rx is now up\n", interface);
}
if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { union cvmx_stxx_com_ctl stxx_com_ctl;
stxx_com_ctl.u64 = cvmx_read_csr(CVMX_STXX_COM_CTL(interface));
stxx_com_ctl.s.inf_en = 1;
cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64);
cvmx_dprintf("SPI%d: Tx is now up\n", interface);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.