#define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */ #define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while
* disabled */ #define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */ #define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */ #define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */ #define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */ #define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */
#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
struct xilinx_spi { /* bitbang has to be first */ struct spi_bitbang bitbang; struct completion done; void __iomem *regs; /* virt. address of the control registers */
int irq; bool force_irq; /* force irq to setup host inhibit */
u8 *rx_ptr; /* pointer in the Tx buffer */ const u8 *tx_ptr; /* pointer in the Rx buffer */
u8 bytes_per_word; int buffer_size; /* buffer size in words */
u32 cs_inactive; /* Level of the CS pins when inactive*/ unsignedint (*read_fn)(void __iomem *addr); void (*write_fn)(u32 val, void __iomem *addr);
};
staticvoid xilinx_spi_tx(struct xilinx_spi *xspi)
{
u32 data = 0;
if (!xspi->tx_ptr) {
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); return;
}
switch (xspi->bytes_per_word) { case 1:
data = *(u8 *)(xspi->tx_ptr); break; case 2:
data = *(u16 *)(xspi->tx_ptr); break; case 4:
data = *(u32 *)(xspi->tx_ptr); break;
}
/* Reset the SPI device */
xspi->write_fn(XIPIF_V123B_RESET_MASK,
regs_base + XIPIF_V123B_RESETR_OFFSET); /* Enable the transmit empty interrupt, which we use to determine * progress on the transmission.
*/
xspi->write_fn(XSPI_INTR_TX_EMPTY,
regs_base + XIPIF_V123B_IIER_OFFSET); /* Disable the global IPIF interrupt */
xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); /* Deselect the Target on the SPI bus */
xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET); /* Disable the transmitter, enable Manual Target Select Assertion,
* put SPI controller into host mode, and enable it */
xspi->write_fn(XSPI_CR_MANUAL_SSELECT | XSPI_CR_MASTER_MODE |
XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET | XSPI_CR_RXFIFO_RESET,
regs_base + XSPI_CR_OFFSET);
}
if (is_on == BITBANG_CS_INACTIVE) { /* Deselect the target on the SPI bus */
xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET); return;
}
/* Set the SPI clock phase and polarity */
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_MODE_MASK; if (spi->mode & SPI_CPHA)
cr |= XSPI_CR_CPHA; if (spi->mode & SPI_CPOL)
cr |= XSPI_CR_CPOL; if (spi->mode & SPI_LSB_FIRST)
cr |= XSPI_CR_LSB_FIRST; if (spi->mode & SPI_LOOP)
cr |= XSPI_CR_LOOP;
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
/* We do not check spi->max_speed_hz here as the SPI clock * frequency is not software programmable (the IP block design * parameter)
*/
/* spi_bitbang requires custom setup_transfer() to be defined if there is a * custom txrx_bufs().
*/ staticint xilinx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{ struct xilinx_spi *xspi = spi_controller_get_devdata(spi->controller);
staticint xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{ struct xilinx_spi *xspi = spi_controller_get_devdata(spi->controller); int remaining_words; /* the number of words left to transfer */ bool use_irq = false;
u16 cr = 0;
tx_words = n_words; while (tx_words--)
xilinx_spi_tx(xspi);
/* Start the transfer by not inhibiting the transmitter any * longer
*/
if (use_irq) {
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
wait_for_completion(&xspi->done); /* A transmit has just completed. Process received data * and check for more data to transmit. Always inhibit * the transmitter while the Isr refills the transmit * register/FIFO, or make sure it is stopped if we're * done.
*/
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);
sr = XSPI_SR_TX_EMPTY_MASK;
} else
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
/* Read out all the data from the Rx FIFO */
rx_words = n_words;
stalled = 10; while (rx_words) { if (rx_words == n_words && !(stalled--) &&
!(sr & XSPI_SR_TX_EMPTY_MASK) &&
(sr & XSPI_SR_RX_EMPTY_MASK)) {
dev_err(&spi->dev, "Detected stall. Check C_SPI_MODE and C_SPI_MEMORY\n");
xspi_init_hw(xspi); return -EIO;
}
/* This driver supports single host mode only. Hence Tx FIFO Empty * is the only interrupt we care about. * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Target Mode * Fault are not to happen.
*/ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
{ struct xilinx_spi *xspi = dev_id;
u32 ipif_isr;
/* Get the IPIF interrupts, and clear them immediately */
ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
/* * Before the buffer_size detection we reset the core * to make sure we start with a clean state.
*/
xspi->write_fn(XIPIF_V123B_RESET_MASK,
xspi->regs + XIPIF_V123B_RESETR_OFFSET);
/* Fill the Tx FIFO with as many words as possible */ do {
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
n_words++;
} while (!(sr & XSPI_SR_TX_FULL_MASK));
/* * Detect endianess on the IP via loop bit in CR. Detection * must be done before reset is sent because incorrect reset * value generates error interrupt. * Setup little endian helper functions first and try to use them * and check if bit was correctly setup or not.
*/
xspi->read_fn = xspi_read32;
xspi->write_fn = xspi_write32;
/* Disable all the interrupts just in case */
xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); /* Disable the global IPIF interrupt */
xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
spi_controller_put(xspi->bitbang.ctlr);
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:" XILINX_SPI_NAME);
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.