aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-07-10 09:38:37 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-07-10 10:28:56 -0400
commit619ac8d3e582ccd806f24dcfc369c4c250ca9814 (patch)
tree536d9a9f9d4cb4440f7180f7b08112671a4e300d /drivers/spi
parentd8e328b3bd65fdefc9c49a27ee80c28e0a44b653 (diff)
spi: tegra: use dmaengine based dma driver
Use the dmaengine based Tegra APB DMA driver for data transfer between SPI FIFO and memory in place of legacy Tegra APB DMA. The new driver is selected if legacy driver is not selected and new DMA driver is enabled through config file. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Acked-by: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-tegra.c89
2 files changed, 85 insertions, 6 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 00c024039c97..6eeb8a286a20 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -357,7 +357,7 @@ config SPI_STMP3XXX
357 357
358config SPI_TEGRA 358config SPI_TEGRA
359 tristate "Nvidia Tegra SPI controller" 359 tristate "Nvidia Tegra SPI controller"
360 depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA 360 depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA)
361 help 361 help
362 SPI driver for NVidia Tegra SoCs 362 SPI driver for NVidia Tegra SoCs
363 363
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
index ae6d78a3e912..956ff4a0827b 100644
--- a/drivers/spi/spi-tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -30,6 +30,7 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31 31
32#include <linux/spi/spi.h> 32#include <linux/spi/spi.h>
33#include <linux/dmaengine.h>
33 34
34#include <mach/dma.h> 35#include <mach/dma.h>
35 36
@@ -162,12 +163,23 @@ struct spi_tegra_data {
162 * require transfers to be 4 byte aligned we need a bounce buffer 163 * require transfers to be 4 byte aligned we need a bounce buffer
163 * for the generic case. 164 * for the generic case.
164 */ 165 */
166 int dma_req_len;
167#if defined(CONFIG_TEGRA_SYSTEM_DMA)
165 struct tegra_dma_req rx_dma_req; 168 struct tegra_dma_req rx_dma_req;
166 struct tegra_dma_channel *rx_dma; 169 struct tegra_dma_channel *rx_dma;
170#else
171 struct dma_chan *rx_dma;
172 struct dma_slave_config sconfig;
173 struct dma_async_tx_descriptor *rx_dma_desc;
174 dma_cookie_t rx_cookie;
175#endif
167 u32 *rx_bb; 176 u32 *rx_bb;
168 dma_addr_t rx_bb_phys; 177 dma_addr_t rx_bb_phys;
169}; 178};
170 179
180#if !defined(CONFIG_TEGRA_SYSTEM_DMA)
181static void tegra_spi_rx_dma_complete(void *args);
182#endif
171 183
172static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi, 184static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
173 unsigned long reg) 185 unsigned long reg)
@@ -190,10 +202,24 @@ static void spi_tegra_go(struct spi_tegra_data *tspi)
190 202
191 val = spi_tegra_readl(tspi, SLINK_DMA_CTL); 203 val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
192 val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN; 204 val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
193 val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1); 205 val |= SLINK_DMA_BLOCK_SIZE(tspi->dma_req_len / 4 - 1);
194 spi_tegra_writel(tspi, val, SLINK_DMA_CTL); 206 spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
195 207#if defined(CONFIG_TEGRA_SYSTEM_DMA)
208 tspi->rx_dma_req.size = tspi->dma_req_len;
196 tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req); 209 tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
210#else
211 tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma,
212 tspi->rx_bb_phys, tspi->dma_req_len,
213 DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
214 if (!tspi->rx_dma_desc) {
215 dev_err(&tspi->pdev->dev, "dmaengine slave prep failed\n");
216 return;
217 }
218 tspi->rx_dma_desc->callback = tegra_spi_rx_dma_complete;
219 tspi->rx_dma_desc->callback_param = tspi;
220 tspi->rx_cookie = dmaengine_submit(tspi->rx_dma_desc);
221 dma_async_issue_pending(tspi->rx_dma);
222#endif
197 223
198 val |= SLINK_DMA_EN; 224 val |= SLINK_DMA_EN;
199 spi_tegra_writel(tspi, val, SLINK_DMA_CTL); 225 spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
@@ -221,7 +247,7 @@ static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
221 spi_tegra_writel(tspi, val, SLINK_TX_FIFO); 247 spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
222 } 248 }
223 249
224 tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4; 250 tspi->dma_req_len = len / tspi->cur_bytes_per_word * 4;
225 251
226 return len; 252 return len;
227} 253}
@@ -318,9 +344,8 @@ static void spi_tegra_start_message(struct spi_device *spi,
318 spi_tegra_start_transfer(spi, t); 344 spi_tegra_start_transfer(spi, t);
319} 345}
320 346
321static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) 347static void handle_spi_rx_dma_complete(struct spi_tegra_data *tspi)
322{ 348{
323 struct spi_tegra_data *tspi = req->dev;
324 unsigned long flags; 349 unsigned long flags;
325 struct spi_message *m; 350 struct spi_message *m;
326 struct spi_device *spi; 351 struct spi_device *spi;
@@ -380,6 +405,19 @@ static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
380 405
381 spin_unlock_irqrestore(&tspi->lock, flags); 406 spin_unlock_irqrestore(&tspi->lock, flags);
382} 407}
408#if defined(CONFIG_TEGRA_SYSTEM_DMA)
409static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
410{
411 struct spi_tegra_data *tspi = req->dev;
412 handle_spi_rx_dma_complete(tspi);
413}
414#else
415static void tegra_spi_rx_dma_complete(void *args)
416{
417 struct spi_tegra_data *tspi = args;
418 handle_spi_rx_dma_complete(tspi);
419}
420#endif
383 421
384static int spi_tegra_setup(struct spi_device *spi) 422static int spi_tegra_setup(struct spi_device *spi)
385{ 423{
@@ -471,6 +509,9 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
471 struct spi_tegra_data *tspi; 509 struct spi_tegra_data *tspi;
472 struct resource *r; 510 struct resource *r;
473 int ret; 511 int ret;
512#if !defined(CONFIG_TEGRA_SYSTEM_DMA)
513 dma_cap_mask_t mask;
514#endif
474 515
475 master = spi_alloc_master(&pdev->dev, sizeof *tspi); 516 master = spi_alloc_master(&pdev->dev, sizeof *tspi);
476 if (master == NULL) { 517 if (master == NULL) {
@@ -522,12 +563,24 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
522 563
523 INIT_LIST_HEAD(&tspi->queue); 564 INIT_LIST_HEAD(&tspi->queue);
524 565
566#if defined(CONFIG_TEGRA_SYSTEM_DMA)
525 tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); 567 tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
526 if (!tspi->rx_dma) { 568 if (!tspi->rx_dma) {
527 dev_err(&pdev->dev, "can not allocate rx dma channel\n"); 569 dev_err(&pdev->dev, "can not allocate rx dma channel\n");
528 ret = -ENODEV; 570 ret = -ENODEV;
529 goto err3; 571 goto err3;
530 } 572 }
573#else
574 dma_cap_zero(mask);
575 dma_cap_set(DMA_SLAVE, mask);
576 tspi->rx_dma = dma_request_channel(mask, NULL, NULL);
577 if (!tspi->rx_dma) {
578 dev_err(&pdev->dev, "can not allocate rx dma channel\n");
579 ret = -ENODEV;
580 goto err3;
581 }
582
583#endif
531 584
532 tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN, 585 tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
533 &tspi->rx_bb_phys, GFP_KERNEL); 586 &tspi->rx_bb_phys, GFP_KERNEL);
@@ -537,6 +590,7 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
537 goto err4; 590 goto err4;
538 } 591 }
539 592
593#if defined(CONFIG_TEGRA_SYSTEM_DMA)
540 tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete; 594 tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
541 tspi->rx_dma_req.to_memory = 1; 595 tspi->rx_dma_req.to_memory = 1;
542 tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys; 596 tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
@@ -546,6 +600,23 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
546 tspi->rx_dma_req.source_wrap = 4; 600 tspi->rx_dma_req.source_wrap = 4;
547 tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id]; 601 tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
548 tspi->rx_dma_req.dev = tspi; 602 tspi->rx_dma_req.dev = tspi;
603#else
604 /* Dmaengine Dma slave config */
605 tspi->sconfig.src_addr = tspi->phys + SLINK_RX_FIFO;
606 tspi->sconfig.dst_addr = tspi->phys + SLINK_RX_FIFO;
607 tspi->sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
608 tspi->sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
609 tspi->sconfig.slave_id = spi_tegra_req_sels[pdev->id];
610 tspi->sconfig.src_maxburst = 1;
611 tspi->sconfig.dst_maxburst = 1;
612 ret = dmaengine_device_control(tspi->rx_dma,
613 DMA_SLAVE_CONFIG, (unsigned long) &tspi->sconfig);
614 if (ret < 0) {
615 dev_err(&pdev->dev, "can not do slave configure for dma %d\n",
616 ret);
617 goto err4;
618 }
619#endif
549 620
550 master->dev.of_node = pdev->dev.of_node; 621 master->dev.of_node = pdev->dev.of_node;
551 ret = spi_register_master(master); 622 ret = spi_register_master(master);
@@ -559,7 +630,11 @@ err5:
559 dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, 630 dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
560 tspi->rx_bb, tspi->rx_bb_phys); 631 tspi->rx_bb, tspi->rx_bb_phys);
561err4: 632err4:
633#if defined(CONFIG_TEGRA_SYSTEM_DMA)
562 tegra_dma_free_channel(tspi->rx_dma); 634 tegra_dma_free_channel(tspi->rx_dma);
635#else
636 dma_release_channel(tspi->rx_dma);
637#endif
563err3: 638err3:
564 clk_put(tspi->clk); 639 clk_put(tspi->clk);
565err2: 640err2:
@@ -581,7 +656,11 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
581 tspi = spi_master_get_devdata(master); 656 tspi = spi_master_get_devdata(master);
582 657
583 spi_unregister_master(master); 658 spi_unregister_master(master);
659#if defined(CONFIG_TEGRA_SYSTEM_DMA)
584 tegra_dma_free_channel(tspi->rx_dma); 660 tegra_dma_free_channel(tspi->rx_dma);
661#else
662 dma_release_channel(tspi->rx_dma);
663#endif
585 664
586 dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, 665 dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
587 tspi->rx_bb, tspi->rx_bb_phys); 666 tspi->rx_bb, tspi->rx_bb_phys);