|
@@ -128,7 +128,6 @@ static void xilinx_spi_rx(struct xilinx_spi *xspi)
|
|
static void xspi_init_hw(struct xilinx_spi *xspi)
|
|
static void xspi_init_hw(struct xilinx_spi *xspi)
|
|
{
|
|
{
|
|
void __iomem *regs_base = xspi->regs;
|
|
void __iomem *regs_base = xspi->regs;
|
|
- u32 inhibit;
|
|
|
|
|
|
|
|
/* Reset the SPI device */
|
|
/* Reset the SPI device */
|
|
xspi->write_fn(XIPIF_V123B_RESET_MASK,
|
|
xspi->write_fn(XIPIF_V123B_RESET_MASK,
|
|
@@ -138,22 +137,15 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
|
|
*/
|
|
*/
|
|
xspi->write_fn(XSPI_INTR_TX_EMPTY,
|
|
xspi->write_fn(XSPI_INTR_TX_EMPTY,
|
|
regs_base + XIPIF_V123B_IIER_OFFSET);
|
|
regs_base + XIPIF_V123B_IIER_OFFSET);
|
|
- /* Enable the global IPIF interrupt */
|
|
|
|
- if (xspi->irq >= 0) {
|
|
|
|
- xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
|
|
|
|
- regs_base + XIPIF_V123B_DGIER_OFFSET);
|
|
|
|
- inhibit = XSPI_CR_TRANS_INHIBIT;
|
|
|
|
- } else {
|
|
|
|
- xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
|
|
|
|
- inhibit = 0;
|
|
|
|
- }
|
|
|
|
|
|
+ /* Disable the global IPIF interrupt */
|
|
|
|
+ xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
|
|
/* Deselect the slave on the SPI bus */
|
|
/* Deselect the slave on the SPI bus */
|
|
xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
|
|
xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
|
|
/* Disable the transmitter, enable Manual Slave Select Assertion,
|
|
/* Disable the transmitter, enable Manual Slave Select Assertion,
|
|
* put SPI controller into master mode, and enable it */
|
|
* put SPI controller into master mode, and enable it */
|
|
- xspi->write_fn(inhibit | XSPI_CR_MANUAL_SSELECT |
|
|
|
|
- XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
|
|
|
|
- XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
|
|
|
|
|
|
+ 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);
|
|
}
|
|
}
|
|
|
|
|
|
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
|
|
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
|
|
@@ -212,6 +204,8 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|
{
|
|
{
|
|
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
|
|
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
|
|
int remaining_words; /* the number of words left to transfer */
|
|
int remaining_words; /* the number of words left to transfer */
|
|
|
|
+ bool use_irq = false;
|
|
|
|
+ u16 cr = 0;
|
|
|
|
|
|
/* We get here with transmitter inhibited */
|
|
/* We get here with transmitter inhibited */
|
|
|
|
|
|
@@ -220,8 +214,20 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|
remaining_words = t->len / xspi->bytes_per_word;
|
|
remaining_words = t->len / xspi->bytes_per_word;
|
|
reinit_completion(&xspi->done);
|
|
reinit_completion(&xspi->done);
|
|
|
|
|
|
|
|
+ if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) {
|
|
|
|
+ use_irq = true;
|
|
|
|
+ xspi->write_fn(XSPI_INTR_TX_EMPTY,
|
|
|
|
+ xspi->regs + XIPIF_V123B_IISR_OFFSET);
|
|
|
|
+ /* Enable the global IPIF interrupt */
|
|
|
|
+ xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
|
|
|
|
+ xspi->regs + XIPIF_V123B_DGIER_OFFSET);
|
|
|
|
+ /* Inhibit irq to avoid spurious irqs on tx_empty*/
|
|
|
|
+ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
|
|
|
|
+ xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
|
|
|
|
+ xspi->regs + XSPI_CR_OFFSET);
|
|
|
|
+ }
|
|
|
|
+
|
|
while (remaining_words) {
|
|
while (remaining_words) {
|
|
- u16 cr = 0;
|
|
|
|
int n_words, tx_words, rx_words;
|
|
int n_words, tx_words, rx_words;
|
|
|
|
|
|
n_words = min(remaining_words, xspi->buffer_size);
|
|
n_words = min(remaining_words, xspi->buffer_size);
|
|
@@ -234,9 +240,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|
* longer
|
|
* longer
|
|
*/
|
|
*/
|
|
|
|
|
|
- if (xspi->irq >= 0) {
|
|
|
|
- cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
|
|
|
|
- ~XSPI_CR_TRANS_INHIBIT;
|
|
|
|
|
|
+ if (use_irq) {
|
|
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
|
|
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
|
|
wait_for_completion(&xspi->done);
|
|
wait_for_completion(&xspi->done);
|
|
} else
|
|
} else
|
|
@@ -249,7 +253,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|
* transmitter while the Isr refills the transmit register/FIFO,
|
|
* transmitter while the Isr refills the transmit register/FIFO,
|
|
* or make sure it is stopped if we're done.
|
|
* or make sure it is stopped if we're done.
|
|
*/
|
|
*/
|
|
- if (xspi->irq >= 0)
|
|
|
|
|
|
+ if (use_irq)
|
|
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
|
|
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
|
|
xspi->regs + XSPI_CR_OFFSET);
|
|
xspi->regs + XSPI_CR_OFFSET);
|
|
|
|
|
|
@@ -261,6 +265,9 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|
remaining_words -= n_words;
|
|
remaining_words -= n_words;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (use_irq)
|
|
|
|
+ xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
|
|
|
|
+
|
|
return t->len;
|
|
return t->len;
|
|
}
|
|
}
|
|
|
|
|