aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorQipan Li <Qipan.Li@csr.com>2014-05-04 02:32:36 -0400
committerMark Brown <broonie@linaro.org>2014-05-20 18:24:20 -0400
commit41148c3a728222a885bc2f3ba3ce66831de0b244 (patch)
treee98c1efb42481caa47f2c256b73aef131812e079 /drivers/spi
parentc908ef345d2c314ec25cfac113a8f9bb2b6b3a25 (diff)
spi: sirf: decrease the interrupt count and latency of PIO mode
current PIO tranfer method be described as follows: 1. fill as much as bytes but no more than 256 bytes(fifo size) 2. enable oflow/uflow/txfifo_empty interrupt 3. isr process 3 interrupt signal, do complete works. 4. after isr done, if there are left bytes go into 1 else go into 5 5. transfer end by current PIO transfer method: 1. reduce interrupt counts in spi interrupt line. 2. reduce interrupt latency because no do data fill/fetch in isr. Signed-off-by: Qipan Li <Qipan.Li@csr.com> Signed-off-by: Barry Song <Baohua.Song@csr.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-sirf.c101
1 files changed, 54 insertions, 47 deletions
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index 2d238990115c..95ac276eaafe 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -86,6 +86,7 @@
86#define SIRFSOC_SPI_TX_DONE BIT(1) 86#define SIRFSOC_SPI_TX_DONE BIT(1)
87#define SIRFSOC_SPI_RX_OFLOW BIT(2) 87#define SIRFSOC_SPI_RX_OFLOW BIT(2)
88#define SIRFSOC_SPI_TX_UFLOW BIT(3) 88#define SIRFSOC_SPI_TX_UFLOW BIT(3)
89#define SIRFSOC_SPI_RX_IO_DMA BIT(4)
89#define SIRFSOC_SPI_RX_FIFO_FULL BIT(6) 90#define SIRFSOC_SPI_RX_FIFO_FULL BIT(6)
90#define SIRFSOC_SPI_TXFIFO_EMPTY BIT(7) 91#define SIRFSOC_SPI_TXFIFO_EMPTY BIT(7)
91#define SIRFSOC_SPI_RXFIFO_THD_REACH BIT(8) 92#define SIRFSOC_SPI_RXFIFO_THD_REACH BIT(8)
@@ -265,41 +266,34 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
265{ 266{
266 struct sirfsoc_spi *sspi = dev_id; 267 struct sirfsoc_spi *sspi = dev_id;
267 u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS); 268 u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS);
268
269 writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS);
270
271 if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) { 269 if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) {
272 complete(&sspi->tx_done); 270 complete(&sspi->tx_done);
273 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); 271 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
272 writel(SIRFSOC_SPI_INT_MASK_ALL,
273 sspi->base + SIRFSOC_SPI_INT_STATUS);
274 return IRQ_HANDLED; 274 return IRQ_HANDLED;
275 } 275 }
276 276
277 /* Error Conditions */ 277 /* Error Conditions */
278 if (spi_stat & SIRFSOC_SPI_RX_OFLOW || 278 if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
279 spi_stat & SIRFSOC_SPI_TX_UFLOW) { 279 spi_stat & SIRFSOC_SPI_TX_UFLOW) {
280 complete(&sspi->tx_done);
280 complete(&sspi->rx_done); 281 complete(&sspi->rx_done);
281 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); 282 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
283 writel(SIRFSOC_SPI_INT_MASK_ALL,
284 sspi->base + SIRFSOC_SPI_INT_STATUS);
285 return IRQ_HANDLED;
282 } 286 }
287 if (spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY)
288 complete(&sspi->tx_done);
289 while (!(readl(sspi->base + SIRFSOC_SPI_INT_STATUS) &
290 SIRFSOC_SPI_RX_IO_DMA))
291 cpu_relax();
292 complete(&sspi->rx_done);
293 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
294 writel(SIRFSOC_SPI_INT_MASK_ALL,
295 sspi->base + SIRFSOC_SPI_INT_STATUS);
283 296
284 if (spi_stat & (SIRFSOC_SPI_FRM_END
285 | SIRFSOC_SPI_RXFIFO_THD_REACH))
286 while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS)
287 & SIRFSOC_SPI_FIFO_EMPTY)) &&
288 sspi->left_rx_word)
289 sspi->rx_word(sspi);
290
291 if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY |
292 SIRFSOC_SPI_TXFIFO_THD_REACH))
293 while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
294 & SIRFSOC_SPI_FIFO_FULL)) &&
295 sspi->left_tx_word)
296 sspi->tx_word(sspi);
297
298 /* Received all words */
299 if ((sspi->left_rx_word == 0) && (sspi->left_tx_word == 0)) {
300 complete(&sspi->rx_done);
301 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
302 }
303 return IRQ_HANDLED; 297 return IRQ_HANDLED;
304} 298}
305 299
@@ -420,32 +414,45 @@ static void spi_sirfsoc_pio_transfer(struct spi_device *spi,
420 int timeout = t->len * 10; 414 int timeout = t->len * 10;
421 415
422 sspi = spi_master_get_devdata(spi->master); 416 sspi = spi_master_get_devdata(spi->master);
423 writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); 417 do {
424 writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); 418 writel(SIRFSOC_SPI_FIFO_RESET,
425 writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); 419 sspi->base + SIRFSOC_SPI_RXFIFO_OP);
426 writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); 420 writel(SIRFSOC_SPI_FIFO_RESET,
427 writel(0, sspi->base + SIRFSOC_SPI_INT_EN); 421 sspi->base + SIRFSOC_SPI_TXFIFO_OP);
428 writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); 422 writel(SIRFSOC_SPI_FIFO_START,
429 writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | SIRFSOC_SPI_MUL_DAT_MODE | 423 sspi->base + SIRFSOC_SPI_RXFIFO_OP);
430 SIRFSOC_SPI_ENA_AUTO_CLR, sspi->base + SIRFSOC_SPI_CTRL); 424 writel(SIRFSOC_SPI_FIFO_START,
431 writel(sspi->left_tx_word - 1, 425 sspi->base + SIRFSOC_SPI_TXFIFO_OP);
432 sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); 426 writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
433 writel(sspi->left_rx_word - 1, 427 writel(SIRFSOC_SPI_INT_MASK_ALL,
434 sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); 428 sspi->base + SIRFSOC_SPI_INT_STATUS);
435 sspi->tx_word(sspi); 429 writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
436 writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN | 430 SIRFSOC_SPI_MUL_DAT_MODE | SIRFSOC_SPI_ENA_AUTO_CLR,
437 SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_RXFIFO_THD_INT_EN | 431 sspi->base + SIRFSOC_SPI_CTRL);
438 SIRFSOC_SPI_TXFIFO_THD_INT_EN | SIRFSOC_SPI_FRM_END_INT_EN| 432 writel(min(sspi->left_tx_word, (u32)(256 / sspi->word_width))
439 SIRFSOC_SPI_RXFIFO_FULL_INT_EN, 433 - 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
440 sspi->base + SIRFSOC_SPI_INT_EN); 434 writel(min(sspi->left_rx_word, (u32)(256 / sspi->word_width))
441 writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, 435 - 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
436 while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
437 & SIRFSOC_SPI_FIFO_FULL)) && sspi->left_tx_word)
438 sspi->tx_word(sspi);
439 writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN |
440 SIRFSOC_SPI_TX_UFLOW_INT_EN |
441 SIRFSOC_SPI_RX_OFLOW_INT_EN,
442 sspi->base + SIRFSOC_SPI_INT_EN);
443 writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
442 sspi->base + SIRFSOC_SPI_TX_RX_EN); 444 sspi->base + SIRFSOC_SPI_TX_RX_EN);
443 if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) 445 if (!wait_for_completion_timeout(&sspi->tx_done, timeout) ||
444 dev_err(&spi->dev, "transfer timeout\n"); 446 !wait_for_completion_timeout(&sspi->rx_done, timeout)) {
445 writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); 447 dev_err(&spi->dev, "transfer timeout\n");
446 writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP); 448 break;
447 writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); 449 }
448 writel(0, sspi->base + SIRFSOC_SPI_INT_EN); 450 while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS)
451 & SIRFSOC_SPI_FIFO_EMPTY)) && sspi->left_rx_word)
452 sspi->rx_word(sspi);
453 writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
454 writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
455 } while (sspi->left_tx_word != 0 || sspi->left_rx_word != 0);
449} 456}
450 457
451static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) 458static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)