diff options
Diffstat (limited to 'drivers/spi/spi-tegra.c')
-rw-r--r-- | drivers/spi/spi-tegra.c | 89 |
1 files changed, 84 insertions, 5 deletions
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) | ||
181 | static void tegra_spi_rx_dma_complete(void *args); | ||
182 | #endif | ||
171 | 183 | ||
172 | static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi, | 184 | static 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 | ||
321 | static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) | 347 | static 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) | ||
409 | static 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 | ||
415 | static 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 | ||
384 | static int spi_tegra_setup(struct spi_device *spi) | 422 | static 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); |
561 | err4: | 632 | err4: |
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 | ||
563 | err3: | 638 | err3: |
564 | clk_put(tspi->clk); | 639 | clk_put(tspi->clk); |
565 | err2: | 640 | err2: |
@@ -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); |