aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2011-09-06 04:16:37 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-10-04 12:10:50 -0400
commit25e803f9c339a070cd7361e853aebde11b1f9217 (patch)
treedb699d232879b967830c47f91cced54786a3605b
parent373b0eb64b9c97a14720896dcfdebfa3268b1991 (diff)
spi-topcliff-pch: Add recovery processing in case FIFO overrun error occurs
Add recovery processing in case FIFO overrun error occurs with DMA transfer mode. Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r--drivers/spi/spi-topcliff-pch.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 6cb2fdbe5dba..c8efa757fdaa 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -352,16 +352,26 @@ static irqreturn_t pch_spi_handler(int irq, void *dev_id)
352 "%s returning due to suspend\n", __func__); 352 "%s returning due to suspend\n", __func__);
353 return IRQ_NONE; 353 return IRQ_NONE;
354 } 354 }
355 if (data->use_dma)
356 return IRQ_NONE;
357 355
358 io_remap_addr = data->io_remap_addr; 356 io_remap_addr = data->io_remap_addr;
359 spsr = io_remap_addr + PCH_SPSR; 357 spsr = io_remap_addr + PCH_SPSR;
360 358
361 reg_spsr_val = ioread32(spsr); 359 reg_spsr_val = ioread32(spsr);
362 360
363 if (reg_spsr_val & SPSR_ORF_BIT) 361 if (reg_spsr_val & SPSR_ORF_BIT) {
364 dev_err(&board_dat->pdev->dev, "%s Over run error", __func__); 362 dev_err(&board_dat->pdev->dev, "%s Over run error\n", __func__);
363 if (data->current_msg->complete != 0) {
364 data->transfer_complete = true;
365 data->current_msg->status = -EIO;
366 data->current_msg->complete(data->current_msg->context);
367 data->bcurrent_msg_processing = false;
368 data->current_msg = NULL;
369 data->cur_trans = NULL;
370 }
371 }
372
373 if (data->use_dma)
374 return IRQ_NONE;
365 375
366 /* Check if the interrupt is for SPI device */ 376 /* Check if the interrupt is for SPI device */
367 if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) { 377 if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
@@ -815,10 +825,11 @@ static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw)
815 } 825 }
816} 826}
817 827
818static void pch_spi_start_transfer(struct pch_spi_data *data) 828static int pch_spi_start_transfer(struct pch_spi_data *data)
819{ 829{
820 struct pch_spi_dma_ctrl *dma; 830 struct pch_spi_dma_ctrl *dma;
821 unsigned long flags; 831 unsigned long flags;
832 int rtn;
822 833
823 dma = &data->dma; 834 dma = &data->dma;
824 835
@@ -833,7 +844,9 @@ static void pch_spi_start_transfer(struct pch_spi_data *data)
833 initiating the transfer. */ 844 initiating the transfer. */
834 dev_dbg(&data->master->dev, 845 dev_dbg(&data->master->dev,
835 "%s:waiting for transfer to get over\n", __func__); 846 "%s:waiting for transfer to get over\n", __func__);
836 wait_event_interruptible(data->wait, data->transfer_complete); 847 rtn = wait_event_interruptible_timeout(data->wait,
848 data->transfer_complete,
849 msecs_to_jiffies(2 * HZ));
837 850
838 dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent, 851 dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent,
839 DMA_FROM_DEVICE); 852 DMA_FROM_DEVICE);
@@ -860,6 +873,8 @@ static void pch_spi_start_transfer(struct pch_spi_data *data)
860 pch_spi_clear_fifo(data->master); 873 pch_spi_clear_fifo(data->master);
861 874
862 spin_unlock_irqrestore(&data->lock, flags); 875 spin_unlock_irqrestore(&data->lock, flags);
876
877 return rtn;
863} 878}
864 879
865static void pch_dma_rx_complete(void *arg) 880static void pch_dma_rx_complete(void *arg)
@@ -1187,7 +1202,8 @@ static void pch_spi_process_messages(struct work_struct *pwork)
1187 1202
1188 if (data->use_dma) { 1203 if (data->use_dma) {
1189 pch_spi_handle_dma(data, &bpw); 1204 pch_spi_handle_dma(data, &bpw);
1190 pch_spi_start_transfer(data); 1205 if (!pch_spi_start_transfer(data))
1206 goto out;
1191 pch_spi_copy_rx_data_for_dma(data, bpw); 1207 pch_spi_copy_rx_data_for_dma(data, bpw);
1192 } else { 1208 } else {
1193 pch_spi_set_tx(data, &bpw); 1209 pch_spi_set_tx(data, &bpw);
@@ -1225,6 +1241,7 @@ static void pch_spi_process_messages(struct work_struct *pwork)
1225 1241
1226 } while (data->cur_trans != NULL); 1242 } while (data->cur_trans != NULL);
1227 1243
1244out:
1228 pch_spi_writereg(data->master, PCH_SSNXCR, SSN_HIGH); 1245 pch_spi_writereg(data->master, PCH_SSNXCR, SSN_HIGH);
1229 if (data->use_dma) 1246 if (data->use_dma)
1230 pch_spi_release_dma(data); 1247 pch_spi_release_dma(data);