aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/tegra20-apb-dma.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-01-06 11:22:02 -0500
committerVinod Koul <vinod.koul@intel.com>2013-01-08 05:53:05 -0500
commit1b140908c4cda43c653bb080c244d112e619008f (patch)
tree4ee653ced926928937db65f029bf19c6d42b7048 /drivers/dma/tegra20-apb-dma.c
parente65f32ca21faed30ce37cd6480271697fe671f74 (diff)
dma: tegra: add support for channel wise pause
NVIDIA's some SoCs like Tegra114 support the channel wise pause control inplace of global pause which pauses all DMA channels. When SoCs support the channel wise pause control then it uses the global pause for clock gating for register access as well as all DMA channel pause. Hence DMA registers are not accessible if DMAs are globally paused on these new SoCs. Add support for channel wise pause feature if SoCs support it. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/tegra20-apb-dma.c')
-rw-r--r--drivers/dma/tegra20-apb-dma.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index efdfffa13349..2c46ac46e7ad 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -62,6 +62,9 @@
62#define TEGRA_APBDMA_STATUS_COUNT_SHIFT 2 62#define TEGRA_APBDMA_STATUS_COUNT_SHIFT 2
63#define TEGRA_APBDMA_STATUS_COUNT_MASK 0xFFFC 63#define TEGRA_APBDMA_STATUS_COUNT_MASK 0xFFFC
64 64
65#define TEGRA_APBDMA_CHAN_CSRE 0x00C
66#define TEGRA_APBDMA_CHAN_CSRE_PAUSE (1 << 31)
67
65/* AHB memory address */ 68/* AHB memory address */
66#define TEGRA_APBDMA_CHAN_AHBPTR 0x010 69#define TEGRA_APBDMA_CHAN_AHBPTR 0x010
67 70
@@ -112,10 +115,12 @@ struct tegra_dma;
112 * tegra_dma_chip_data Tegra chip specific DMA data 115 * tegra_dma_chip_data Tegra chip specific DMA data
113 * @nr_channels: Number of channels available in the controller. 116 * @nr_channels: Number of channels available in the controller.
114 * @max_dma_count: Maximum DMA transfer count supported by DMA controller. 117 * @max_dma_count: Maximum DMA transfer count supported by DMA controller.
118 * @support_channel_pause: Support channel wise pause of dma.
115 */ 119 */
116struct tegra_dma_chip_data { 120struct tegra_dma_chip_data {
117 int nr_channels; 121 int nr_channels;
118 int max_dma_count; 122 int max_dma_count;
123 bool support_channel_pause;
119}; 124};
120 125
121/* DMA channel registers */ 126/* DMA channel registers */
@@ -353,6 +358,32 @@ static void tegra_dma_global_resume(struct tegra_dma_channel *tdc)
353 spin_unlock(&tdma->global_lock); 358 spin_unlock(&tdma->global_lock);
354} 359}
355 360
361static void tegra_dma_pause(struct tegra_dma_channel *tdc,
362 bool wait_for_burst_complete)
363{
364 struct tegra_dma *tdma = tdc->tdma;
365
366 if (tdma->chip_data->support_channel_pause) {
367 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSRE,
368 TEGRA_APBDMA_CHAN_CSRE_PAUSE);
369 if (wait_for_burst_complete)
370 udelay(TEGRA_APBDMA_BURST_COMPLETE_TIME);
371 } else {
372 tegra_dma_global_pause(tdc, wait_for_burst_complete);
373 }
374}
375
376static void tegra_dma_resume(struct tegra_dma_channel *tdc)
377{
378 struct tegra_dma *tdma = tdc->tdma;
379
380 if (tdma->chip_data->support_channel_pause) {
381 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSRE, 0);
382 } else {
383 tegra_dma_global_resume(tdc);
384 }
385}
386
356static void tegra_dma_stop(struct tegra_dma_channel *tdc) 387static void tegra_dma_stop(struct tegra_dma_channel *tdc)
357{ 388{
358 u32 csr; 389 u32 csr;
@@ -408,7 +439,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
408 * If there is already IEC status then interrupt handler need to 439 * If there is already IEC status then interrupt handler need to
409 * load new configuration. 440 * load new configuration.
410 */ 441 */
411 tegra_dma_global_pause(tdc, false); 442 tegra_dma_pause(tdc, false);
412 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); 443 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS);
413 444
414 /* 445 /*
@@ -418,7 +449,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
418 if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { 449 if (status & TEGRA_APBDMA_STATUS_ISE_EOC) {
419 dev_err(tdc2dev(tdc), 450 dev_err(tdc2dev(tdc),
420 "Skipping new configuration as interrupt is pending\n"); 451 "Skipping new configuration as interrupt is pending\n");
421 tegra_dma_global_resume(tdc); 452 tegra_dma_resume(tdc);
422 return; 453 return;
423 } 454 }
424 455
@@ -429,7 +460,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
429 nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); 460 nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB);
430 nsg_req->configured = true; 461 nsg_req->configured = true;
431 462
432 tegra_dma_global_resume(tdc); 463 tegra_dma_resume(tdc);
433} 464}
434 465
435static void tdc_start_head_req(struct tegra_dma_channel *tdc) 466static void tdc_start_head_req(struct tegra_dma_channel *tdc)
@@ -690,7 +721,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
690 goto skip_dma_stop; 721 goto skip_dma_stop;
691 722
692 /* Pause DMA before checking the queue status */ 723 /* Pause DMA before checking the queue status */
693 tegra_dma_global_pause(tdc, true); 724 tegra_dma_pause(tdc, true);
694 725
695 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); 726 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS);
696 if (status & TEGRA_APBDMA_STATUS_ISE_EOC) { 727 if (status & TEGRA_APBDMA_STATUS_ISE_EOC) {
@@ -708,7 +739,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
708 sgreq->dma_desc->bytes_transferred += 739 sgreq->dma_desc->bytes_transferred +=
709 get_current_xferred_count(tdc, sgreq, status); 740 get_current_xferred_count(tdc, sgreq, status);
710 } 741 }
711 tegra_dma_global_resume(tdc); 742 tegra_dma_resume(tdc);
712 743
713skip_dma_stop: 744skip_dma_stop:
714 tegra_dma_abort_all(tdc); 745 tegra_dma_abort_all(tdc);
@@ -1175,6 +1206,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
1175static const struct tegra_dma_chip_data tegra20_dma_chip_data = { 1206static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
1176 .nr_channels = 16, 1207 .nr_channels = 16,
1177 .max_dma_count = 1024UL * 64, 1208 .max_dma_count = 1024UL * 64,
1209 .support_channel_pause = false,
1178}; 1210};
1179 1211
1180#if defined(CONFIG_OF) 1212#if defined(CONFIG_OF)
@@ -1182,6 +1214,7 @@ static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
1182static const struct tegra_dma_chip_data tegra30_dma_chip_data = { 1214static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
1183 .nr_channels = 32, 1215 .nr_channels = 32,
1184 .max_dma_count = 1024UL * 64, 1216 .max_dma_count = 1024UL * 64,
1217 .support_channel_pause = false,
1185}; 1218};
1186 1219
1187static const struct of_device_id tegra_dma_of_match[] __devinitconst = { 1220static const struct of_device_id tegra_dma_of_match[] __devinitconst = {