aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 19:41:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 19:41:07 -0400
commita6dc77254b3c3eb0307b372b77b861d5cd2ead08 (patch)
tree5770a808b0527eebeff43f16508ea8f03e459b58 /drivers/spi
parent02a6ec6a24077ffda33b99cb193e8a536b90711d (diff)
parent0e52d987c0b242fe3fe4c8e9732bd663cce0e50b (diff)
Merge branch 'dmaengine' of git://git.linaro.org/people/rmk/linux-arm
Pull ARM DMA engine updates from Russell King: "This looks scary at first glance, but what it is is: - a rework of the sa11x0 DMA engine driver merged during the previous cycle, to extract a common set of helper functions for DMA engine implementations. - conversion of amba-pl08x.c to use these helper functions. - addition of OMAP DMA engine driver (using these helper functions), and conversion of some of the OMAP DMA users to use DMA engine. Nothing in the helper functions is ARM specific, so I hope that other implementations can consolidate some of their code by making use of these helpers. This has been sitting in linux-next most of the merge cycle, and has been tested by several OMAP folk. I've tested it on sa11x0 platforms, and given it my best shot on my broken platforms which have the amba-pl08x controller. The last point is the addition to feature-removal-schedule.txt, which will have a merge conflict. Between myself and TI, we're planning to remove the old TI DMA implementation next year." Fix up trivial add/add conflicts in Documentation/feature-removal-schedule.txt and drivers/dma/{Kconfig,Makefile} * 'dmaengine' of git://git.linaro.org/people/rmk/linux-arm: (53 commits) ARM: 7481/1: OMAP2+: omap2plus_defconfig: enable OMAP DMA engine ARM: 7464/1: mmc: omap_hsmmc: ensure probe returns error if DMA channel request fails Add feature removal of old OMAP private DMA implementation mtd: omap2: remove private DMA API implementation mtd: omap2: add DMA engine support spi: omap2-mcspi: remove private DMA API implementation spi: omap2-mcspi: add DMA engine support ARM: omap: remove mmc platform data dma_mask and initialization mmc: omap: remove private DMA API implementation mmc: omap: add DMA engine support mmc: omap_hsmmc: remove private DMA API implementation mmc: omap_hsmmc: add DMA engine support dmaengine: omap: add support for cyclic DMA dmaengine: omap: add support for setting fi dmaengine: omap: add support for returning residue in tx_state method dmaengine: add OMAP DMA engine driver dmaengine: sa11x0-dma: add cyclic DMA support dmaengine: sa11x0-dma: fix DMA residue support dmaengine: PL08x: ensure all descriptors are freed when channel is released dmaengine: PL08x: get rid of write only pool_ctr and free_txd locking ...
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-omap2-mcspi.c229
1 files changed, 127 insertions, 102 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 7d46b15e1520..bc4778175e34 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -28,6 +28,8 @@
28#include <linux/device.h> 28#include <linux/device.h>
29#include <linux/delay.h> 29#include <linux/delay.h>
30#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
31#include <linux/dmaengine.h>
32#include <linux/omap-dma.h>
31#include <linux/platform_device.h> 33#include <linux/platform_device.h>
32#include <linux/err.h> 34#include <linux/err.h>
33#include <linux/clk.h> 35#include <linux/clk.h>
@@ -39,7 +41,6 @@
39 41
40#include <linux/spi/spi.h> 42#include <linux/spi/spi.h>
41 43
42#include <plat/dma.h>
43#include <plat/clock.h> 44#include <plat/clock.h>
44#include <plat/mcspi.h> 45#include <plat/mcspi.h>
45 46
@@ -93,8 +94,8 @@
93 94
94/* We have 2 DMA channels per CS, one for RX and one for TX */ 95/* We have 2 DMA channels per CS, one for RX and one for TX */
95struct omap2_mcspi_dma { 96struct omap2_mcspi_dma {
96 int dma_tx_channel; 97 struct dma_chan *dma_tx;
97 int dma_rx_channel; 98 struct dma_chan *dma_rx;
98 99
99 int dma_tx_sync_dev; 100 int dma_tx_sync_dev;
100 int dma_rx_sync_dev; 101 int dma_rx_sync_dev;
@@ -300,20 +301,46 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
300 return 0; 301 return 0;
301} 302}
302 303
304static void omap2_mcspi_rx_callback(void *data)
305{
306 struct spi_device *spi = data;
307 struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
308 struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select];
309
310 complete(&mcspi_dma->dma_rx_completion);
311
312 /* We must disable the DMA RX request */
313 omap2_mcspi_set_dma_req(spi, 1, 0);
314}
315
316static void omap2_mcspi_tx_callback(void *data)
317{
318 struct spi_device *spi = data;
319 struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
320 struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select];
321
322 complete(&mcspi_dma->dma_tx_completion);
323
324 /* We must disable the DMA TX request */
325 omap2_mcspi_set_dma_req(spi, 0, 0);
326}
327
303static unsigned 328static unsigned
304omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) 329omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
305{ 330{
306 struct omap2_mcspi *mcspi; 331 struct omap2_mcspi *mcspi;
307 struct omap2_mcspi_cs *cs = spi->controller_state; 332 struct omap2_mcspi_cs *cs = spi->controller_state;
308 struct omap2_mcspi_dma *mcspi_dma; 333 struct omap2_mcspi_dma *mcspi_dma;
309 unsigned int count, c; 334 unsigned int count;
310 unsigned long base, tx_reg, rx_reg; 335 int word_len, element_count;
311 int word_len, data_type, element_count;
312 int elements = 0; 336 int elements = 0;
313 u32 l; 337 u32 l;
314 u8 * rx; 338 u8 * rx;
315 const u8 * tx; 339 const u8 * tx;
316 void __iomem *chstat_reg; 340 void __iomem *chstat_reg;
341 struct dma_slave_config cfg;
342 enum dma_slave_buswidth width;
343 unsigned es;
317 344
318 mcspi = spi_master_get_devdata(spi->master); 345 mcspi = spi_master_get_devdata(spi->master);
319 mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 346 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -321,68 +348,92 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
321 348
322 chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; 349 chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
323 350
351 if (cs->word_len <= 8) {
352 width = DMA_SLAVE_BUSWIDTH_1_BYTE;
353 es = 1;
354 } else if (cs->word_len <= 16) {
355 width = DMA_SLAVE_BUSWIDTH_2_BYTES;
356 es = 2;
357 } else {
358 width = DMA_SLAVE_BUSWIDTH_4_BYTES;
359 es = 4;
360 }
361
362 memset(&cfg, 0, sizeof(cfg));
363 cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0;
364 cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
365 cfg.src_addr_width = width;
366 cfg.dst_addr_width = width;
367 cfg.src_maxburst = 1;
368 cfg.dst_maxburst = 1;
369
370 if (xfer->tx_buf && mcspi_dma->dma_tx) {
371 struct dma_async_tx_descriptor *tx;
372 struct scatterlist sg;
373
374 dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);
375
376 sg_init_table(&sg, 1);
377 sg_dma_address(&sg) = xfer->tx_dma;
378 sg_dma_len(&sg) = xfer->len;
379
380 tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1,
381 DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
382 if (tx) {
383 tx->callback = omap2_mcspi_tx_callback;
384 tx->callback_param = spi;
385 dmaengine_submit(tx);
386 } else {
387 /* FIXME: fall back to PIO? */
388 }
389 }
390
391 if (xfer->rx_buf && mcspi_dma->dma_rx) {
392 struct dma_async_tx_descriptor *tx;
393 struct scatterlist sg;
394 size_t len = xfer->len - es;
395
396 dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);
397
398 if (l & OMAP2_MCSPI_CHCONF_TURBO)
399 len -= es;
400
401 sg_init_table(&sg, 1);
402 sg_dma_address(&sg) = xfer->rx_dma;
403 sg_dma_len(&sg) = len;
404
405 tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
406 DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
407 if (tx) {
408 tx->callback = omap2_mcspi_rx_callback;
409 tx->callback_param = spi;
410 dmaengine_submit(tx);
411 } else {
412 /* FIXME: fall back to PIO? */
413 }
414 }
415
324 count = xfer->len; 416 count = xfer->len;
325 c = count;
326 word_len = cs->word_len; 417 word_len = cs->word_len;
327 418
328 base = cs->phys;
329 tx_reg = base + OMAP2_MCSPI_TX0;
330 rx_reg = base + OMAP2_MCSPI_RX0;
331 rx = xfer->rx_buf; 419 rx = xfer->rx_buf;
332 tx = xfer->tx_buf; 420 tx = xfer->tx_buf;
333 421
334 if (word_len <= 8) { 422 if (word_len <= 8) {
335 data_type = OMAP_DMA_DATA_TYPE_S8;
336 element_count = count; 423 element_count = count;
337 } else if (word_len <= 16) { 424 } else if (word_len <= 16) {
338 data_type = OMAP_DMA_DATA_TYPE_S16;
339 element_count = count >> 1; 425 element_count = count >> 1;
340 } else /* word_len <= 32 */ { 426 } else /* word_len <= 32 */ {
341 data_type = OMAP_DMA_DATA_TYPE_S32;
342 element_count = count >> 2; 427 element_count = count >> 2;
343 } 428 }
344 429
345 if (tx != NULL) { 430 if (tx != NULL) {
346 omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel, 431 dma_async_issue_pending(mcspi_dma->dma_tx);
347 data_type, element_count, 1,
348 OMAP_DMA_SYNC_ELEMENT,
349 mcspi_dma->dma_tx_sync_dev, 0);
350
351 omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
352 OMAP_DMA_AMODE_CONSTANT,
353 tx_reg, 0, 0);
354
355 omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
356 OMAP_DMA_AMODE_POST_INC,
357 xfer->tx_dma, 0, 0);
358 }
359
360 if (rx != NULL) {
361 elements = element_count - 1;
362 if (l & OMAP2_MCSPI_CHCONF_TURBO)
363 elements--;
364
365 omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
366 data_type, elements, 1,
367 OMAP_DMA_SYNC_ELEMENT,
368 mcspi_dma->dma_rx_sync_dev, 1);
369
370 omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
371 OMAP_DMA_AMODE_CONSTANT,
372 rx_reg, 0, 0);
373
374 omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
375 OMAP_DMA_AMODE_POST_INC,
376 xfer->rx_dma, 0, 0);
377 }
378
379 if (tx != NULL) {
380 omap_start_dma(mcspi_dma->dma_tx_channel);
381 omap2_mcspi_set_dma_req(spi, 0, 1); 432 omap2_mcspi_set_dma_req(spi, 0, 1);
382 } 433 }
383 434
384 if (rx != NULL) { 435 if (rx != NULL) {
385 omap_start_dma(mcspi_dma->dma_rx_channel); 436 dma_async_issue_pending(mcspi_dma->dma_rx);
386 omap2_mcspi_set_dma_req(spi, 1, 1); 437 omap2_mcspi_set_dma_req(spi, 1, 1);
387 } 438 }
388 439
@@ -408,7 +459,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
408 DMA_FROM_DEVICE); 459 DMA_FROM_DEVICE);
409 omap2_mcspi_set_enable(spi, 0); 460 omap2_mcspi_set_enable(spi, 0);
410 461
462 elements = element_count - 1;
463
411 if (l & OMAP2_MCSPI_CHCONF_TURBO) { 464 if (l & OMAP2_MCSPI_CHCONF_TURBO) {
465 elements--;
412 466
413 if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) 467 if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
414 & OMAP2_MCSPI_CHSTAT_RXS)) { 468 & OMAP2_MCSPI_CHSTAT_RXS)) {
@@ -725,64 +779,38 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
725 return 0; 779 return 0;
726} 780}
727 781
728static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
729{
730 struct spi_device *spi = data;
731 struct omap2_mcspi *mcspi;
732 struct omap2_mcspi_dma *mcspi_dma;
733
734 mcspi = spi_master_get_devdata(spi->master);
735 mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
736
737 complete(&mcspi_dma->dma_rx_completion);
738
739 /* We must disable the DMA RX request */
740 omap2_mcspi_set_dma_req(spi, 1, 0);
741}
742
743static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
744{
745 struct spi_device *spi = data;
746 struct omap2_mcspi *mcspi;
747 struct omap2_mcspi_dma *mcspi_dma;
748
749 mcspi = spi_master_get_devdata(spi->master);
750 mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
751
752 complete(&mcspi_dma->dma_tx_completion);
753
754 /* We must disable the DMA TX request */
755 omap2_mcspi_set_dma_req(spi, 0, 0);
756}
757
758static int omap2_mcspi_request_dma(struct spi_device *spi) 782static int omap2_mcspi_request_dma(struct spi_device *spi)
759{ 783{
760 struct spi_master *master = spi->master; 784 struct spi_master *master = spi->master;
761 struct omap2_mcspi *mcspi; 785 struct omap2_mcspi *mcspi;
762 struct omap2_mcspi_dma *mcspi_dma; 786 struct omap2_mcspi_dma *mcspi_dma;
787 dma_cap_mask_t mask;
788 unsigned sig;
763 789
764 mcspi = spi_master_get_devdata(master); 790 mcspi = spi_master_get_devdata(master);
765 mcspi_dma = mcspi->dma_channels + spi->chip_select; 791 mcspi_dma = mcspi->dma_channels + spi->chip_select;
766 792
767 if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX", 793 init_completion(&mcspi_dma->dma_rx_completion);
768 omap2_mcspi_dma_rx_callback, spi, 794 init_completion(&mcspi_dma->dma_tx_completion);
769 &mcspi_dma->dma_rx_channel)) { 795
770 dev_err(&spi->dev, "no RX DMA channel for McSPI\n"); 796 dma_cap_zero(mask);
797 dma_cap_set(DMA_SLAVE, mask);
798 sig = mcspi_dma->dma_rx_sync_dev;
799 mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
800 if (!mcspi_dma->dma_rx) {
801 dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n");
771 return -EAGAIN; 802 return -EAGAIN;
772 } 803 }
773 804
774 if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX", 805 sig = mcspi_dma->dma_tx_sync_dev;
775 omap2_mcspi_dma_tx_callback, spi, 806 mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
776 &mcspi_dma->dma_tx_channel)) { 807 if (!mcspi_dma->dma_tx) {
777 omap_free_dma(mcspi_dma->dma_rx_channel); 808 dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n");
778 mcspi_dma->dma_rx_channel = -1; 809 dma_release_channel(mcspi_dma->dma_rx);
779 dev_err(&spi->dev, "no TX DMA channel for McSPI\n"); 810 mcspi_dma->dma_rx = NULL;
780 return -EAGAIN; 811 return -EAGAIN;
781 } 812 }
782 813
783 init_completion(&mcspi_dma->dma_rx_completion);
784 init_completion(&mcspi_dma->dma_tx_completion);
785
786 return 0; 814 return 0;
787} 815}
788 816
@@ -814,8 +842,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
814 list_add_tail(&cs->node, &ctx->cs); 842 list_add_tail(&cs->node, &ctx->cs);
815 } 843 }
816 844
817 if (mcspi_dma->dma_rx_channel == -1 845 if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) {
818 || mcspi_dma->dma_tx_channel == -1) {
819 ret = omap2_mcspi_request_dma(spi); 846 ret = omap2_mcspi_request_dma(spi);
820 if (ret < 0) 847 if (ret < 0)
821 return ret; 848 return ret;
@@ -850,13 +877,13 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
850 if (spi->chip_select < spi->master->num_chipselect) { 877 if (spi->chip_select < spi->master->num_chipselect) {
851 mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 878 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
852 879
853 if (mcspi_dma->dma_rx_channel != -1) { 880 if (mcspi_dma->dma_rx) {
854 omap_free_dma(mcspi_dma->dma_rx_channel); 881 dma_release_channel(mcspi_dma->dma_rx);
855 mcspi_dma->dma_rx_channel = -1; 882 mcspi_dma->dma_rx = NULL;
856 } 883 }
857 if (mcspi_dma->dma_tx_channel != -1) { 884 if (mcspi_dma->dma_tx) {
858 omap_free_dma(mcspi_dma->dma_tx_channel); 885 dma_release_channel(mcspi_dma->dma_tx);
859 mcspi_dma->dma_tx_channel = -1; 886 mcspi_dma->dma_tx = NULL;
860 } 887 }
861 } 888 }
862} 889}
@@ -1176,7 +1203,6 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
1176 break; 1203 break;
1177 } 1204 }
1178 1205
1179 mcspi->dma_channels[i].dma_rx_channel = -1;
1180 mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start; 1206 mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
1181 sprintf(dma_ch_name, "tx%d", i); 1207 sprintf(dma_ch_name, "tx%d", i);
1182 dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, 1208 dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
@@ -1187,7 +1213,6 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
1187 break; 1213 break;
1188 } 1214 }
1189 1215
1190 mcspi->dma_channels[i].dma_tx_channel = -1;
1191 mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start; 1216 mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
1192 } 1217 }
1193 1218