aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeshwari Shinde2013-10-08 16:20:05 +0530
committerJagannadha Sutradharudu Teki2013-10-08 18:18:11 +0530
commit120af1572a3647bb87eff2f62dd8f8a919ee71f0 (patch)
tree60e8c86eabec0f346baa1c8b9a9d95e37546f4ce
parent8d203afdd3bf54ad5b2523cdacaff4ac35da6b08 (diff)
spi: exynos: Minimise access to SPI FIFO level
Accessing SPI registers is slow, but access to the FIFO level register in particular seems to be extraordinarily expensive (I measure up to 600ns). Perhaps it is required to synchronise with the SPI byte output logic which might run at 1/8th of the 40MHz SPI speed (just a guess). Reduce access to this register by filling up and emptying FIFOs more completely, rather than just one word each time around the inner loop. Since the rxfifo value will now likely be much greater that what we read before we fill the txfifo, we only fill the txfifo halfway. This is because if the txfifo is empty, but the rxfifo has data in it, then writing too much data to the txfifo may overflow the rxfifo as data arrives. This speeds up SPI flash reading from about 1MB/s to about 2MB/s on snow. Signed-off-by: Simon Glass <sjg@chromium.org> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> Reviewed-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
-rw-r--r--drivers/spi/exynos_spi.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index d7fdaacebdc..7407d6cc128 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -247,24 +247,27 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
/* Keep the fifos full/empty. */
spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl);
- if (tx_lvl < spi_slave->fifo_size && out_bytes) {
+ while (tx_lvl < spi_slave->fifo_size/2 && out_bytes) {
temp = txp ? *txp++ : 0xff;
writel(temp, &regs->tx_data);
out_bytes--;
+ tx_lvl++;
}
if (rx_lvl > 0) {
- temp = readl(&regs->rx_data);
- if (spi_slave->skip_preamble) {
- if (temp == SPI_PREAMBLE_END_BYTE) {
- spi_slave->skip_preamble = 0;
- stopping = 0;
+ while (rx_lvl > 0) {
+ temp = readl(&regs->rx_data);
+ if (spi_slave->skip_preamble) {
+ if (temp == SPI_PREAMBLE_END_BYTE) {
+ spi_slave->skip_preamble = 0;
+ stopping = 0;
+ }
+ } else {
+ if (rxp || stopping)
+ *rxp++ = temp;
+ in_bytes--;
}
- } else {
- if (rxp || stopping)
- *rxp++ = temp;
- in_bytes--;
- }
- toread--;
+ toread--;
+ rx_lvl--;
} else if (!toread) {
/*
* We have run out of input data, but haven't read