diff options
Diffstat (limited to 'drivers/spi/dw_spi.c')
-rw-r--r-- | drivers/spi/dw_spi.c | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 0838c79861e4..22af77f98816 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c | |||
@@ -164,20 +164,23 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) | |||
164 | 164 | ||
165 | static void wait_till_not_busy(struct dw_spi *dws) | 165 | static void wait_till_not_busy(struct dw_spi *dws) |
166 | { | 166 | { |
167 | unsigned long end = jiffies + 1 + usecs_to_jiffies(1000); | 167 | unsigned long end = jiffies + 1 + usecs_to_jiffies(5000); |
168 | 168 | ||
169 | while (time_before(jiffies, end)) { | 169 | while (time_before(jiffies, end)) { |
170 | if (!(dw_readw(dws, sr) & SR_BUSY)) | 170 | if (!(dw_readw(dws, sr) & SR_BUSY)) |
171 | return; | 171 | return; |
172 | cpu_relax(); | ||
172 | } | 173 | } |
173 | dev_err(&dws->master->dev, | 174 | dev_err(&dws->master->dev, |
174 | "DW SPI: Status keeps busy for 1000us after a read/write!\n"); | 175 | "DW SPI: Status keeps busy for 5000us after a read/write!\n"); |
175 | } | 176 | } |
176 | 177 | ||
177 | static void flush(struct dw_spi *dws) | 178 | static void flush(struct dw_spi *dws) |
178 | { | 179 | { |
179 | while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 180 | while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) { |
180 | dw_readw(dws, dr); | 181 | dw_readw(dws, dr); |
182 | cpu_relax(); | ||
183 | } | ||
181 | 184 | ||
182 | wait_till_not_busy(dws); | 185 | wait_till_not_busy(dws); |
183 | } | 186 | } |
@@ -285,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws) | |||
285 | */ | 288 | */ |
286 | static int map_dma_buffers(struct dw_spi *dws) | 289 | static int map_dma_buffers(struct dw_spi *dws) |
287 | { | 290 | { |
288 | if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited | 291 | if (!dws->cur_msg->is_dma_mapped |
289 | || !dws->cur_chip->enable_dma) | 292 | || !dws->dma_inited |
293 | || !dws->cur_chip->enable_dma | ||
294 | || !dws->dma_ops) | ||
290 | return 0; | 295 | return 0; |
291 | 296 | ||
292 | if (dws->cur_transfer->tx_dma) | 297 | if (dws->cur_transfer->tx_dma) |
@@ -338,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char *msg) | |||
338 | tasklet_schedule(&dws->pump_transfers); | 343 | tasklet_schedule(&dws->pump_transfers); |
339 | } | 344 | } |
340 | 345 | ||
341 | static void transfer_complete(struct dw_spi *dws) | 346 | void dw_spi_xfer_done(struct dw_spi *dws) |
342 | { | 347 | { |
343 | /* Update total byte transfered return count actual bytes read */ | 348 | /* Update total byte transfered return count actual bytes read */ |
344 | dws->cur_msg->actual_length += dws->len; | 349 | dws->cur_msg->actual_length += dws->len; |
@@ -353,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws) | |||
353 | } else | 358 | } else |
354 | tasklet_schedule(&dws->pump_transfers); | 359 | tasklet_schedule(&dws->pump_transfers); |
355 | } | 360 | } |
361 | EXPORT_SYMBOL_GPL(dw_spi_xfer_done); | ||
356 | 362 | ||
357 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) | 363 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) |
358 | { | 364 | { |
@@ -384,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) | |||
384 | if (dws->tx_end > dws->tx) | 390 | if (dws->tx_end > dws->tx) |
385 | spi_umask_intr(dws, SPI_INT_TXEI); | 391 | spi_umask_intr(dws, SPI_INT_TXEI); |
386 | else | 392 | else |
387 | transfer_complete(dws); | 393 | dw_spi_xfer_done(dws); |
388 | } | 394 | } |
389 | 395 | ||
390 | return IRQ_HANDLED; | 396 | return IRQ_HANDLED; |
@@ -419,11 +425,7 @@ static void poll_transfer(struct dw_spi *dws) | |||
419 | */ | 425 | */ |
420 | dws->read(dws); | 426 | dws->read(dws); |
421 | 427 | ||
422 | transfer_complete(dws); | 428 | dw_spi_xfer_done(dws); |
423 | } | ||
424 | |||
425 | static void dma_transfer(struct dw_spi *dws, int cs_change) | ||
426 | { | ||
427 | } | 429 | } |
428 | 430 | ||
429 | static void pump_transfers(unsigned long data) | 431 | static void pump_transfers(unsigned long data) |
@@ -592,7 +594,7 @@ static void pump_transfers(unsigned long data) | |||
592 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); | 594 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); |
593 | spi_chip_sel(dws, spi->chip_select); | 595 | spi_chip_sel(dws, spi->chip_select); |
594 | 596 | ||
595 | /* Set the interrupt mask, for poll mode just diable all int */ | 597 | /* Set the interrupt mask, for poll mode just disable all int */ |
596 | spi_mask_intr(dws, 0xff); | 598 | spi_mask_intr(dws, 0xff); |
597 | if (imask) | 599 | if (imask) |
598 | spi_umask_intr(dws, imask); | 600 | spi_umask_intr(dws, imask); |
@@ -605,7 +607,7 @@ static void pump_transfers(unsigned long data) | |||
605 | } | 607 | } |
606 | 608 | ||
607 | if (dws->dma_mapped) | 609 | if (dws->dma_mapped) |
608 | dma_transfer(dws, cs_change); | 610 | dws->dma_ops->dma_transfer(dws, cs_change); |
609 | 611 | ||
610 | if (chip->poll_mode) | 612 | if (chip->poll_mode) |
611 | poll_transfer(dws); | 613 | poll_transfer(dws); |
@@ -901,11 +903,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) | |||
901 | master->setup = dw_spi_setup; | 903 | master->setup = dw_spi_setup; |
902 | master->transfer = dw_spi_transfer; | 904 | master->transfer = dw_spi_transfer; |
903 | 905 | ||
904 | dws->dma_inited = 0; | ||
905 | |||
906 | /* Basic HW init */ | 906 | /* Basic HW init */ |
907 | spi_hw_init(dws); | 907 | spi_hw_init(dws); |
908 | 908 | ||
909 | if (dws->dma_ops && dws->dma_ops->dma_init) { | ||
910 | ret = dws->dma_ops->dma_init(dws); | ||
911 | if (ret) { | ||
912 | dev_warn(&master->dev, "DMA init failed\n"); | ||
913 | dws->dma_inited = 0; | ||
914 | } | ||
915 | } | ||
916 | |||
909 | /* Initial and start queue */ | 917 | /* Initial and start queue */ |
910 | ret = init_queue(dws); | 918 | ret = init_queue(dws); |
911 | if (ret) { | 919 | if (ret) { |
@@ -930,6 +938,8 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) | |||
930 | 938 | ||
931 | err_queue_alloc: | 939 | err_queue_alloc: |
932 | destroy_queue(dws); | 940 | destroy_queue(dws); |
941 | if (dws->dma_ops && dws->dma_ops->dma_exit) | ||
942 | dws->dma_ops->dma_exit(dws); | ||
933 | err_diable_hw: | 943 | err_diable_hw: |
934 | spi_enable_chip(dws, 0); | 944 | spi_enable_chip(dws, 0); |
935 | free_irq(dws->irq, dws); | 945 | free_irq(dws->irq, dws); |
@@ -938,7 +948,7 @@ err_free_master: | |||
938 | exit: | 948 | exit: |
939 | return ret; | 949 | return ret; |
940 | } | 950 | } |
941 | EXPORT_SYMBOL(dw_spi_add_host); | 951 | EXPORT_SYMBOL_GPL(dw_spi_add_host); |
942 | 952 | ||
943 | void __devexit dw_spi_remove_host(struct dw_spi *dws) | 953 | void __devexit dw_spi_remove_host(struct dw_spi *dws) |
944 | { | 954 | { |
@@ -954,6 +964,8 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws) | |||
954 | dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " | 964 | dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not " |
955 | "complete, message memory not freed\n"); | 965 | "complete, message memory not freed\n"); |
956 | 966 | ||
967 | if (dws->dma_ops && dws->dma_ops->dma_exit) | ||
968 | dws->dma_ops->dma_exit(dws); | ||
957 | spi_enable_chip(dws, 0); | 969 | spi_enable_chip(dws, 0); |
958 | /* Disable clk */ | 970 | /* Disable clk */ |
959 | spi_set_clk(dws, 0); | 971 | spi_set_clk(dws, 0); |
@@ -962,7 +974,7 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws) | |||
962 | /* Disconnect from the SPI framework */ | 974 | /* Disconnect from the SPI framework */ |
963 | spi_unregister_master(dws->master); | 975 | spi_unregister_master(dws->master); |
964 | } | 976 | } |
965 | EXPORT_SYMBOL(dw_spi_remove_host); | 977 | EXPORT_SYMBOL_GPL(dw_spi_remove_host); |
966 | 978 | ||
967 | int dw_spi_suspend_host(struct dw_spi *dws) | 979 | int dw_spi_suspend_host(struct dw_spi *dws) |
968 | { | 980 | { |
@@ -975,7 +987,7 @@ int dw_spi_suspend_host(struct dw_spi *dws) | |||
975 | spi_set_clk(dws, 0); | 987 | spi_set_clk(dws, 0); |
976 | return ret; | 988 | return ret; |
977 | } | 989 | } |
978 | EXPORT_SYMBOL(dw_spi_suspend_host); | 990 | EXPORT_SYMBOL_GPL(dw_spi_suspend_host); |
979 | 991 | ||
980 | int dw_spi_resume_host(struct dw_spi *dws) | 992 | int dw_spi_resume_host(struct dw_spi *dws) |
981 | { | 993 | { |
@@ -987,7 +999,7 @@ int dw_spi_resume_host(struct dw_spi *dws) | |||
987 | dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); | 999 | dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); |
988 | return ret; | 1000 | return ret; |
989 | } | 1001 | } |
990 | EXPORT_SYMBOL(dw_spi_resume_host); | 1002 | EXPORT_SYMBOL_GPL(dw_spi_resume_host); |
991 | 1003 | ||
992 | MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>"); | 1004 | MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>"); |
993 | MODULE_DESCRIPTION("Driver for DesignWare SPI controller core"); | 1005 | MODULE_DESCRIPTION("Driver for DesignWare SPI controller core"); |