aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2014-01-06 13:16:45 -0500
committerVinod Koul <vinod.koul@intel.com>2014-01-20 04:05:52 -0500
commit911daccc8b9672ec2206d3741127089dc2c695d4 (patch)
treec9ecf09f7c6700310e7ec5f0286a709095cd710e
parent5a87f0e618c709b982c1fa568a30346c38ea28de (diff)
dma: tegra: add support for Tegra148/124
Tegra148 introduces a few changes to the APB DMA HW registers. Update the driver to cope with them. Tegra124 inherits these changes. * The register address stride between DMA channels increases. * A new per-channel WCOUNT register is introduced. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Kunal Agrawal <kunala@nvidia.com> [swarren, remove .dts file change, rewrote commit description, removed some duplicate/unused code and register IO] Signed-off-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Thierry Reding <treding@nvidia.com> Tested-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/tegra20-apb-dma.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 73654e33f13b..25873bc10350 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -99,6 +99,11 @@
99#define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27) 99#define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27)
100#define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16) 100#define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16)
101 101
102/* Tegra148 specific registers */
103#define TEGRA_APBDMA_CHAN_WCOUNT 0x20
104
105#define TEGRA_APBDMA_CHAN_WORD_TRANSFER 0x24
106
102/* 107/*
103 * If any burst is in flight and DMA paused then this is the time to complete 108 * If any burst is in flight and DMA paused then this is the time to complete
104 * on-flight burst and update DMA status register. 109 * on-flight burst and update DMA status register.
@@ -108,21 +113,22 @@
108/* Channel base address offset from APBDMA base address */ 113/* Channel base address offset from APBDMA base address */
109#define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000 114#define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000
110 115
111/* DMA channel register space size */
112#define TEGRA_APBDMA_CHANNEL_REGISTER_SIZE 0x20
113
114struct tegra_dma; 116struct tegra_dma;
115 117
116/* 118/*
117 * tegra_dma_chip_data Tegra chip specific DMA data 119 * tegra_dma_chip_data Tegra chip specific DMA data
118 * @nr_channels: Number of channels available in the controller. 120 * @nr_channels: Number of channels available in the controller.
121 * @channel_reg_size: Channel register size/stride.
119 * @max_dma_count: Maximum DMA transfer count supported by DMA controller. 122 * @max_dma_count: Maximum DMA transfer count supported by DMA controller.
120 * @support_channel_pause: Support channel wise pause of dma. 123 * @support_channel_pause: Support channel wise pause of dma.
124 * @support_separate_wcount_reg: Support separate word count register.
121 */ 125 */
122struct tegra_dma_chip_data { 126struct tegra_dma_chip_data {
123 int nr_channels; 127 int nr_channels;
128 int channel_reg_size;
124 int max_dma_count; 129 int max_dma_count;
125 bool support_channel_pause; 130 bool support_channel_pause;
131 bool support_separate_wcount_reg;
126}; 132};
127 133
128/* DMA channel registers */ 134/* DMA channel registers */
@@ -132,6 +138,7 @@ struct tegra_dma_channel_regs {
132 unsigned long apb_ptr; 138 unsigned long apb_ptr;
133 unsigned long ahb_seq; 139 unsigned long ahb_seq;
134 unsigned long apb_seq; 140 unsigned long apb_seq;
141 unsigned long wcount;
135}; 142};
136 143
137/* 144/*
@@ -421,6 +428,8 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc,
421 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr); 428 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr);
422 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq); 429 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq);
423 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr); 430 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr);
431 if (tdc->tdma->chip_data->support_separate_wcount_reg)
432 tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT, ch_regs->wcount);
424 433
425 /* Start DMA */ 434 /* Start DMA */
426 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, 435 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
@@ -460,6 +469,9 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
460 /* Safe to program new configuration */ 469 /* Safe to program new configuration */
461 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr); 470 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr);
462 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr); 471 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr);
472 if (tdc->tdma->chip_data->support_separate_wcount_reg)
473 tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT,
474 nsg_req->ch_regs.wcount);
463 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, 475 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
464 nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); 476 nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB);
465 nsg_req->configured = true; 477 nsg_req->configured = true;
@@ -713,6 +725,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
713 struct tegra_dma_desc *dma_desc; 725 struct tegra_dma_desc *dma_desc;
714 unsigned long flags; 726 unsigned long flags;
715 unsigned long status; 727 unsigned long status;
728 unsigned long wcount;
716 bool was_busy; 729 bool was_busy;
717 730
718 spin_lock_irqsave(&tdc->lock, flags); 731 spin_lock_irqsave(&tdc->lock, flags);
@@ -733,6 +746,10 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
733 tdc->isr_handler(tdc, true); 746 tdc->isr_handler(tdc, true);
734 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); 747 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS);
735 } 748 }
749 if (tdc->tdma->chip_data->support_separate_wcount_reg)
750 wcount = tdc_read(tdc, TEGRA_APBDMA_CHAN_WORD_TRANSFER);
751 else
752 wcount = status;
736 753
737 was_busy = tdc->busy; 754 was_busy = tdc->busy;
738 tegra_dma_stop(tdc); 755 tegra_dma_stop(tdc);
@@ -741,7 +758,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
741 sgreq = list_first_entry(&tdc->pending_sg_req, 758 sgreq = list_first_entry(&tdc->pending_sg_req,
742 typeof(*sgreq), node); 759 typeof(*sgreq), node);
743 sgreq->dma_desc->bytes_transferred += 760 sgreq->dma_desc->bytes_transferred +=
744 get_current_xferred_count(tdc, sgreq, status); 761 get_current_xferred_count(tdc, sgreq, wcount);
745 } 762 }
746 tegra_dma_resume(tdc); 763 tegra_dma_resume(tdc);
747 764
@@ -903,6 +920,17 @@ static int get_transfer_param(struct tegra_dma_channel *tdc,
903 return -EINVAL; 920 return -EINVAL;
904} 921}
905 922
923static void tegra_dma_prep_wcount(struct tegra_dma_channel *tdc,
924 struct tegra_dma_channel_regs *ch_regs, u32 len)
925{
926 u32 len_field = (len - 4) & 0xFFFC;
927
928 if (tdc->tdma->chip_data->support_separate_wcount_reg)
929 ch_regs->wcount = len_field;
930 else
931 ch_regs->csr |= len_field;
932}
933
906static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( 934static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
907 struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len, 935 struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len,
908 enum dma_transfer_direction direction, unsigned long flags, 936 enum dma_transfer_direction direction, unsigned long flags,
@@ -986,7 +1014,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
986 1014
987 sg_req->ch_regs.apb_ptr = apb_ptr; 1015 sg_req->ch_regs.apb_ptr = apb_ptr;
988 sg_req->ch_regs.ahb_ptr = mem; 1016 sg_req->ch_regs.ahb_ptr = mem;
989 sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); 1017 sg_req->ch_regs.csr = csr;
1018 tegra_dma_prep_wcount(tdc, &sg_req->ch_regs, len);
990 sg_req->ch_regs.apb_seq = apb_seq; 1019 sg_req->ch_regs.apb_seq = apb_seq;
991 sg_req->ch_regs.ahb_seq = ahb_seq; 1020 sg_req->ch_regs.ahb_seq = ahb_seq;
992 sg_req->configured = false; 1021 sg_req->configured = false;
@@ -1115,7 +1144,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
1115 ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len); 1144 ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
1116 sg_req->ch_regs.apb_ptr = apb_ptr; 1145 sg_req->ch_regs.apb_ptr = apb_ptr;
1117 sg_req->ch_regs.ahb_ptr = mem; 1146 sg_req->ch_regs.ahb_ptr = mem;
1118 sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); 1147 sg_req->ch_regs.csr = csr;
1148 tegra_dma_prep_wcount(tdc, &sg_req->ch_regs, len);
1119 sg_req->ch_regs.apb_seq = apb_seq; 1149 sg_req->ch_regs.apb_seq = apb_seq;
1120 sg_req->ch_regs.ahb_seq = ahb_seq; 1150 sg_req->ch_regs.ahb_seq = ahb_seq;
1121 sg_req->configured = false; 1151 sg_req->configured = false;
@@ -1210,27 +1240,45 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
1210/* Tegra20 specific DMA controller information */ 1240/* Tegra20 specific DMA controller information */
1211static const struct tegra_dma_chip_data tegra20_dma_chip_data = { 1241static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
1212 .nr_channels = 16, 1242 .nr_channels = 16,
1243 .channel_reg_size = 0x20,
1213 .max_dma_count = 1024UL * 64, 1244 .max_dma_count = 1024UL * 64,
1214 .support_channel_pause = false, 1245 .support_channel_pause = false,
1246 .support_separate_wcount_reg = false,
1215}; 1247};
1216 1248
1217/* Tegra30 specific DMA controller information */ 1249/* Tegra30 specific DMA controller information */
1218static const struct tegra_dma_chip_data tegra30_dma_chip_data = { 1250static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
1219 .nr_channels = 32, 1251 .nr_channels = 32,
1252 .channel_reg_size = 0x20,
1220 .max_dma_count = 1024UL * 64, 1253 .max_dma_count = 1024UL * 64,
1221 .support_channel_pause = false, 1254 .support_channel_pause = false,
1255 .support_separate_wcount_reg = false,
1222}; 1256};
1223 1257
1224/* Tegra114 specific DMA controller information */ 1258/* Tegra114 specific DMA controller information */
1225static const struct tegra_dma_chip_data tegra114_dma_chip_data = { 1259static const struct tegra_dma_chip_data tegra114_dma_chip_data = {
1226 .nr_channels = 32, 1260 .nr_channels = 32,
1261 .channel_reg_size = 0x20,
1227 .max_dma_count = 1024UL * 64, 1262 .max_dma_count = 1024UL * 64,
1228 .support_channel_pause = true, 1263 .support_channel_pause = true,
1264 .support_separate_wcount_reg = false,
1265};
1266
1267/* Tegra148 specific DMA controller information */
1268static const struct tegra_dma_chip_data tegra148_dma_chip_data = {
1269 .nr_channels = 32,
1270 .channel_reg_size = 0x40,
1271 .max_dma_count = 1024UL * 64,
1272 .support_channel_pause = true,
1273 .support_separate_wcount_reg = true,
1229}; 1274};
1230 1275
1231 1276
1232static const struct of_device_id tegra_dma_of_match[] = { 1277static const struct of_device_id tegra_dma_of_match[] = {
1233 { 1278 {
1279 .compatible = "nvidia,tegra148-apbdma",
1280 .data = &tegra148_dma_chip_data,
1281 }, {
1234 .compatible = "nvidia,tegra114-apbdma", 1282 .compatible = "nvidia,tegra114-apbdma",
1235 .data = &tegra114_dma_chip_data, 1283 .data = &tegra114_dma_chip_data,
1236 }, { 1284 }, {
@@ -1318,7 +1366,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
1318 struct tegra_dma_channel *tdc = &tdma->channels[i]; 1366 struct tegra_dma_channel *tdc = &tdma->channels[i];
1319 1367
1320 tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET + 1368 tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET +
1321 i * TEGRA_APBDMA_CHANNEL_REGISTER_SIZE; 1369 i * cdata->channel_reg_size;
1322 1370
1323 res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 1371 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
1324 if (!res) { 1372 if (!res) {