@@ -200,6 +200,7 @@ struct rspi_data {
unsigned dma_width_16bit:1;
unsigned dma_callbacked:1;
+ unsigned txmode:1;
};
static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
@@ -259,6 +260,20 @@ struct spi_ops {
/*
* functions for RSPI
*/
+static void rspi_set_txmode(const struct rspi_data *rspi)
+{
+ if (rspi->txmode)
+ rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
+ RSPI_SPCR);
+}
+
+static void rspi_clear_txmode(const struct rspi_data *rspi)
+{
+ if (rspi->txmode)
+ rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
+ RSPI_SPCR);
+}
+
static int rspi_parse_platform_data(struct rspi_data *rspi,
const struct rspi_plat_data *rspi_pd)
{
@@ -283,6 +298,11 @@ static int rspi_parse_platform_data(struct rspi_data *rspi,
rspi->spdcr = 0;
}
+ if (rspi_pd)
+ rspi->txmode = rspi_pd->txmode;
+ else
+ rspi->txmode = 1; /* legacy RSPI defaults to true */
+
return 0;
}
@@ -329,6 +349,9 @@ static int qspi_parse_platform_data(struct rspi_data *rspi,
rspi->data_width = 8;
rspi->spdcr = 0;
+ /* No TX only mode */
+ rspi->txmode = 0;
+
return 0;
}
@@ -422,8 +445,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
int remain = t->len;
const u8 *data = t->tx_buf;
while (remain > 0) {
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
- RSPI_SPCR);
+ rspi_set_txmode(rspi);
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev,
@@ -431,6 +453,15 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
return -ETIMEDOUT;
}
+ if (!rspi->txmode && remain != t->len) {
+ if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+ SPCR_SPRIE) < 0) {
+ dev_err(&rspi->master->dev,
+ "%s: receive timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ rspi_read_data(rspi); /* dummy read */
+ }
rspi_write_data(rspi, *data);
data++;
remain--;
@@ -439,6 +470,14 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
/* Waiting for the last transmition */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+ if (!rspi->txmode) {
+ if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
+ dev_err(&rspi->master->dev,
+ "%s: receive timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ rspi_read_data(rspi); /* dummy read */
+ }
return 0;
}
@@ -570,7 +609,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
for (i = 0; i < rspi->num_irqs; i++)
disable_irq(rspi->irqs[i]);
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
+ rspi_set_txmode(rspi);
rspi_enable_irq(rspi, SPCR_SPTIE);
rspi->dma_callbacked = 0;
@@ -621,8 +660,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
data = t->rx_buf;
while (remain > 0) {
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
- RSPI_SPCR);
+ rspi_clear_txmode(rspi);
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
dev_err(&rspi->master->dev,
@@ -756,7 +794,7 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
for (i = 0; i < rspi->num_irqs; i++)
disable_irq(rspi->irqs[i]);
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
+ rspi_clear_txmode(rspi);
rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
rspi->dma_callbacked = 0;
@@ -28,6 +28,7 @@ struct rspi_plat_data {
unsigned int dma_rx_id;
unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */
+ unsigned txmode:1; /* TX only mode */
u16 num_chipselect;
};