static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); u32 ipif_ier; u32 cr; int len = 0; cr = spi_regr(xspi, XSPI_CR_OFFSET); if (cr & XSPI_CR_MASTER_MODE) { /* We're a SPI master */ /* We get here with transmitter inhibited */ xspi->tx_ptr = t->tx_buf; xspi->remaining_bytes = t->len; xspi->rx_ptr = t->rx_buf; INIT_COMPLETION(xspi->done); xilinx_spi_fill_tx_fifo(xspi); /* Enable the transmit empty interrupt, which we use to determine * progress on the transmission. */ ipif_ier = spi_regr(xspi, XIPIF_V123B_IIER_OFFSET); spi_regw(xspi, XIPIF_V123B_IIER_OFFSET, ipif_ier | XSPI_INTR_TX_EMPTY); /* Start the transfer by not inhibiting the transmitter any longer */ spi_regw(xspi, XSPI_CR_OFFSET, cr & ~XSPI_CR_TRANS_INHIBIT); wait_for_completion(&xspi->done); /* Disable the interrupt */ spi_regw(xspi, XIPIF_V123B_IIER_OFFSET, ipif_ier); len = t->len - xspi->remaining_bytes; } else { /* We're a SPI slave */ if (t->tx_buf != NULL) { /* Make a local copy of the data to transmit, since we can't be sure the * caller's buffer will still be around when the transfer occurs. */ len = min((size_t)t->len, sizeof(xspi->slave_tx_buf)); memcpy(xspi->slave_tx_buf, t->tx_buf, len); xspi->tx_ptr = xspi->slave_tx_buf; xspi->remaining_bytes = len; xspi->tx_len = len; /* Clear out old transmit contents */ spi_regw(xspi, XSPI_CR_OFFSET, cr | XSPI_CR_TXFIFO_RESET); xilinx_spi_fill_tx_fifo(xspi); } if (t->rx_buf != NULL) { len = min((int)t->len, (int)(xspi->rx_ptr - xspi->slave_rx_buf)); /* Clear out old receive contents */ spi_regw(xspi, XSPI_CR_OFFSET, cr | XSPI_CR_RXFIFO_RESET); memcpy(t->rx_buf, xspi->slave_rx_buf, len); if (len < xspi->rx_ptr - xspi->slave_rx_buf) { memcpy(xspi->slave_rx_buf, xspi->slave_rx_buf + len, (xspi->rx_ptr - xspi->slave_rx_buf) - len); } xspi->rx_ptr -= len; } } return len; }
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); u32 ipif_ier; u16 cr; /* We get here with transmitter inhibited */ xspi->tx_ptr = t->tx_buf; xspi->rx_ptr = t->rx_buf; xspi->remaining_bytes = t->len; INIT_COMPLETION(xspi->done); xilinx_spi_fill_tx_fifo(xspi); /* Enable the transmit empty interrupt, which we use to determine * progress on the transmission. */ ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET); xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY, xspi->regs + XIPIF_V123B_IIER_OFFSET); /* Start the transfer by not inhibiting the transmitter any longer */ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT; xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); wait_for_completion(&xspi->done); /* Disable the transmit empty interrupt */ xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET); return t->len - xspi->remaining_bytes; }
static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) { struct xilinx_spi *xspi = dev_id; u32 ipif_isr; ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); if (ipif_isr & XSPI_INTR_TX_EMPTY) { u16 cr; u8 sr; cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, xspi->regs + XSPI_CR_OFFSET); sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { xspi->rx_fn(xspi); sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); } if (xspi->remaining_bytes > 0) { xilinx_spi_fill_tx_fifo(xspi); xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); } else { complete(&xspi->done); } } return IRQ_HANDLED; }
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); u32 ipif_ier; u16 cr; xspi->tx_ptr = t->tx_buf; xspi->rx_ptr = t->rx_buf; xspi->remaining_bytes = t->len; INIT_COMPLETION(xspi->done); xilinx_spi_fill_tx_fifo(xspi); ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET); xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY, xspi->regs + XIPIF_V123B_IIER_OFFSET); cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT; xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); wait_for_completion(&xspi->done); xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET); return t->len - xspi->remaining_bytes; }
static void xspi_reset_transmit_buffer(struct xilinx_spi *xspi) { xspi->tx_ptr = xspi->slave_tx_buf; xspi->remaining_bytes = xspi->tx_len; /* Clear out old transmit contents */ spi_regw(xspi, XSPI_CR_OFFSET, spi_regr(xspi, XSPI_CR_OFFSET) | XSPI_CR_TXFIFO_RESET); xilinx_spi_fill_tx_fifo(xspi); }
/* This driver supports single master mode only. Hence Tx FIFO Empty * is the only interrupt we care about. * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave 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 = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET); out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr); if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ u16 cr; u8 sr; /* 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. */ cr = in_be16(xspi->regs + XSPI_CR_OFFSET); out_be16(xspi->regs + XSPI_CR_OFFSET, cr | XSPI_CR_TRANS_INHIBIT); /* Read out all the data from the Rx FIFO */ sr = in_8(xspi->regs + XSPI_SR_OFFSET); while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { u8 data; data = in_8(xspi->regs + XSPI_RXD_OFFSET); if (xspi->rx_ptr) { *xspi->rx_ptr++ = data; } sr = in_8(xspi->regs + XSPI_SR_OFFSET); } /* See if there is more data to send */ if (xspi->remaining_bytes > 0) { xilinx_spi_fill_tx_fifo(xspi); /* Start the transfer by not inhibiting the * transmitter any longer */ out_be16(xspi->regs + XSPI_CR_OFFSET, cr); } else { /* No more data to send. * Indicate the transfer is completed. */ complete(&xspi->done); } } return IRQ_HANDLED; }
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); u32 ipif_ier; /* We get here with transmitter inhibited */ xspi->tx_ptr = t->tx_buf; xspi->rx_ptr = t->rx_buf; xspi->remaining_bytes = t->len; reinit_completion(&xspi->done); /* Enable the transmit empty interrupt, which we use to determine * progress on the transmission. */ ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET); xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY, xspi->regs + XIPIF_V123B_IIER_OFFSET); for (;;) { u16 cr; u8 sr; xilinx_spi_fill_tx_fifo(xspi); /* Start the transfer by not inhibiting the transmitter any * longer */ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT; 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. */ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, xspi->regs + XSPI_CR_OFFSET); /* Read out all the data from the Rx FIFO */ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { xspi->rx_fn(xspi); sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); } /* See if there is more data to send */ if (xspi->remaining_bytes <= 0) break; } /* Disable the transmit empty interrupt */ xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET); return t->len - xspi->remaining_bytes; }
/* In single master mode, Tx FIFO Empty is the only interrupt we care about. * As a slave, Receive FIFO Not Empty and (possibly) Slave Sel Asserted interrupts used. * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave 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; u32 cr; u32 sr; /* Get the IPIF interrupts, and clear them immediately */ ipif_isr = spi_regr(xspi, XIPIF_V123B_IISR_OFFSET); spi_regw(xspi, XIPIF_V123B_IISR_OFFSET, ipif_isr); cr = spi_regr(xspi, XSPI_CR_OFFSET); if (cr & XSPI_CR_MASTER_MODE) { /* We're a SPI master */ if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ /* 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. */ spi_regw(xspi, XSPI_CR_OFFSET, cr | XSPI_CR_TRANS_INHIBIT); /* Read out all the data from the Rx FIFO */ sr = spi_regr(xspi, XSPI_SR_OFFSET); while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { u32 data; data = spi_regr(xspi, XSPI_RXD_OFFSET); #ifdef XSPI_DEBUG_FIFOIO printk("<%02x>", data & 0xff); #endif if (xspi->rx_ptr) { *xspi->rx_ptr++ = (u8)(data & 0xFF); } sr = spi_regr(xspi, XSPI_SR_OFFSET); } /* See if there is more data to send */ if (xspi->remaining_bytes > 0) { xilinx_spi_fill_tx_fifo(xspi); /* Start the transfer by not inhibiting the * transmitter any longer */ spi_regw(xspi, XSPI_CR_OFFSET, cr); } else { /* No more data to send. * Indicate the transfer is completed. */ complete(&xspi->done); } } } else { /* We're a SPI slave */ if (ipif_isr & XSPI_INTR_SLAVE_SEL_ASSERT) { xspi_reset_transmit_buffer(xspi); } if (ipif_isr & XSPI_INTR_RX_NOT_EMPTY) { /* Byte received */ /* Read out all the data from the Rx FIFO */ sr = spi_regr(xspi, XSPI_SR_OFFSET); while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { u32 data; data = spi_regr(xspi, XSPI_RXD_OFFSET); #ifdef XSPI_DEBUG_FIFOIO printk("{%02x}", data & 0xff); #endif if (xspi->rx_ptr - xspi->slave_rx_buf < sizeof(xspi->slave_rx_buf)) { *xspi->rx_ptr++ = (u8)(data & 0xFF); } /* Check if the transfer is completed. */ sr = spi_regr(xspi, XSPI_SR_OFFSET); } if (xspi->remaining_bytes > 0) { xilinx_spi_fill_tx_fifo(xspi); } } } return IRQ_HANDLED; }