aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-sirf.c
diff options
context:
space:
mode:
authorQipan Li <Qipan.Li@csr.com>2013-05-18 07:46:06 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-20 12:10:49 -0400
commit237ce4665c12376391ddb148509204652f6ab758 (patch)
treeef66edad9f6fecec1082b75d62ea1c150ea84ff0 /drivers/spi/spi-sirf.c
parentde1f9f270ea7fb7af37e1b62580e27b15273d63d (diff)
spi: sirf: fix the issue while transferring more than 256 words
currently, spi irq handler only does rx processing and fetching data from rx fifo when "FRM_END" irq happens. FRM_END indicates one transfer completes. if rx size is less than 256, it works well. but the problem is that spi rx fifo size is only 256 bytes, then if data size of one frame is more than 256, before FRM_END comes, rx fifo will be filled with RXFIFO_OFLOW overflow interrupt, it will make us lose some data due to fifo overflow. Explicitly we need do fetch work from device rx fifo in irq handler not only in "FRM_END" irq but also in "THD_REACH" irq. THD_REACH means rx fifo has come to its threshold and will come to overflow if we don't take data from it in time. In this patch, we fix this issue. we take data from rx fifo when either FRM_END or RX_THD_REACH irq comes, we put data into tx fifo when either TX_FIFO_EMPTY or TX_THD_REACH irq comes. Signed-off-by: Qipan Li <Qipan.Li@csr.com> Signed-off-by: Zhiwu Song <Zhiwu.Song@csr.com> Signed-off-by: Barry Song <Baohua.Song@csr.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/spi/spi-sirf.c')
-rw-r--r--drivers/spi/spi-sirf.c43
1 files changed, 13 insertions, 30 deletions
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index ac2ea8a1bd65..e00b437fa2a2 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -140,9 +140,6 @@ struct sirfsoc_spi {
140 unsigned int left_tx_cnt; 140 unsigned int left_tx_cnt;
141 unsigned int left_rx_cnt; 141 unsigned int left_rx_cnt;
142 142
143 /* tasklet to push tx msg into FIFO */
144 struct tasklet_struct tasklet_tx;
145
146 int chipselect[0]; 143 int chipselect[0];
147}; 144};
148 145
@@ -234,17 +231,6 @@ static void spi_sirfsoc_tx_word_u32(struct sirfsoc_spi *sspi)
234 sspi->left_tx_cnt--; 231 sspi->left_tx_cnt--;
235} 232}
236 233
237static void spi_sirfsoc_tasklet_tx(unsigned long arg)
238{
239 struct sirfsoc_spi *sspi = (struct sirfsoc_spi *)arg;
240
241 /* Fill Tx FIFO while there are left words to be transmitted */
242 while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) &
243 SIRFSOC_SPI_FIFO_FULL)) &&
244 sspi->left_tx_cnt)
245 sspi->tx_word(sspi);
246}
247
248static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) 234static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
249{ 235{
250 struct sirfsoc_spi *sspi = dev_id; 236 struct sirfsoc_spi *sspi = dev_id;
@@ -259,25 +245,25 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
259 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); 245 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
260 } 246 }
261 247
262 if (spi_stat & SIRFSOC_SPI_FRM_END) { 248 if (spi_stat & (SIRFSOC_SPI_FRM_END
249 | SIRFSOC_SPI_RXFIFO_THD_REACH))
263 while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) 250 while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS)
264 & SIRFSOC_SPI_FIFO_EMPTY)) && 251 & SIRFSOC_SPI_FIFO_EMPTY)) &&
265 sspi->left_rx_cnt) 252 sspi->left_rx_cnt)
266 sspi->rx_word(sspi); 253 sspi->rx_word(sspi);
267 254
268 /* Received all words */ 255 if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY
269 if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) { 256 | SIRFSOC_SPI_TXFIFO_THD_REACH))
270 complete(&sspi->done); 257 while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
271 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); 258 & SIRFSOC_SPI_FIFO_FULL)) &&
272 } 259 sspi->left_tx_cnt)
273 } 260 sspi->tx_word(sspi);
274
275 if (spi_stat & SIRFSOC_SPI_RXFIFO_THD_REACH ||
276 spi_stat & SIRFSOC_SPI_TXFIFO_THD_REACH ||
277 spi_stat & SIRFSOC_SPI_RX_FIFO_FULL ||
278 spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY)
279 tasklet_schedule(&sspi->tasklet_tx);
280 261
262 /* Received all words */
263 if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) {
264 complete(&sspi->done);
265 writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
266 }
281 return IRQ_HANDLED; 267 return IRQ_HANDLED;
282} 268}
283 269
@@ -566,9 +552,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
566 552
567 init_completion(&sspi->done); 553 init_completion(&sspi->done);
568 554
569 tasklet_init(&sspi->tasklet_tx, spi_sirfsoc_tasklet_tx,
570 (unsigned long)sspi);
571
572 writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); 555 writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
573 writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); 556 writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
574 writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); 557 writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);