summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@libc.org>2016-04-07 14:55:17 +0000
committerRich Felker <dalias@libc.org>2016-04-07 14:57:38 +0000
commit105a6eb0d78596f9f572b04b3d3175ef122a3e2a (patch)
tree7a848f61a0cb544ac7a93b1c28201505368a5507
parent405da69a20e53c8febf8e11ffa500a6ccc6353cc (diff)
downloadlinux-sh-105a6eb0d78596f9f572b04b3d3175ef122a3e2a.tar.gz
spi: optimize J-Core bitbang driver
-rw-r--r--drivers/spi/spi-jcore-bitbang.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/spi/spi-jcore-bitbang.c b/drivers/spi/spi-jcore-bitbang.c
index 9f86d6acb3c6..03ecdbbe1289 100644
--- a/drivers/spi/spi-jcore-bitbang.c
+++ b/drivers/spi/spi-jcore-bitbang.c
@@ -50,15 +50,9 @@ struct sei_spi {
struct spi_bitbang bitbang;
void __iomem *base;
- int len;
- int count;
volatile unsigned int ctrlReg;
unsigned int csReg;
unsigned int speedReg;
-
- /* data buffers */
- const unsigned char *tx;
- unsigned char *rx;
};
static void sei_spi_wait_till_ready(struct sei_spi *hw, int timeout)
@@ -120,25 +114,42 @@ static int sei_spi_setup(struct spi_device *spi)
static int sei_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
struct sei_spi *hw = spi_master_get_devdata(spi->master);
- unsigned char rxByte, txByte;
+
+ void *ctrl = hw->base + CTRL_REG;
+ void *stat = hw->base + STAT_REG;
+ void *data = hw->base + DATA_REG;
+ int timeout;
+ int xmit = hw->csReg | hw->speedReg | SEI_SPI_CTRL_XMIT;
+ int status;
+
+ /* data buffers */
+ const unsigned char *tx;
+ unsigned char *rx;
+ int len;
+ int count;
// pr_info("%s: TXRX cpu=%d\n", __func__, smp_processor_id());
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->len = t->len;
-
- for (hw->count = 0; hw->count < hw->len; hw->count++) {
- if (hw->tx)
- txByte = hw->tx[hw->count];
- else
- txByte = 0;
- hw_txbyte(hw, txByte);
- rxByte = hw_rxbyte(hw);
- if (hw->rx)
- hw->rx[hw->count] = rxByte;
+ tx = t->tx_buf;
+ rx = t->rx_buf;
+ len = t->len;
+// pr_info("txrx %d\n", len);
+
+ for (count = 0; count < len; count++) {
+ timeout = SEI_SPI_WAIT_RDY_MAX_LOOP;
+ do status = readl(stat);
+ while ((status & SEI_SPI_STAT_BUSY) && timeout--);
+
+ writel(tx ? *tx++ : 0, data);
+ writel(xmit, ctrl);
+
+ timeout = SEI_SPI_WAIT_RDY_MAX_LOOP;
+ do status = readl(stat);
+ while ((status & SEI_SPI_STAT_BUSY) && timeout--);
+
+ if (rx) *rx++ = readl(data);
}
- return hw->count;
+ return count;
}
static int sei_spi_probe(struct platform_device *pdev)