aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/tegra20-apb-dma.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-29 23:27:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-29 23:27:23 -0500
commitca2a650f3dfdc30d71d21bcbb04d2d057779f3f9 (patch)
tree12e5f7f4dea5ba17cc82f2c633bbe9dbf725fb11 /drivers/dma/tegra20-apb-dma.c
parente9e352e9100b98aed1a5fb9e33355c29fb07d5b1 (diff)
parent15cec530e4bc7bed3f51cde8404f96fd28a8c7c5 (diff)
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dma updates from Vinod Koul: - new driver for BCM2835 used in R-pi - new driver for MOXA ART - dma_get_any_slave_channel API for DT based systems - minor fixes and updates spread acrooss driver [ The fsl-ssi dual fifo mode support addition clashed badly with the other changes to fsl-ssi that came in through the sound merge. I did a very rough cut at fixing up the conflict, but Nicolin Chen (author of both sides) will need to verify and check things ] * 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (36 commits) dmaengine: mmp_pdma: fix mismerge dma: pl08x: Export pl08x_filter_id acpi-dma: align documentation with kernel-doc format dma: fix vchan_cookie_complete() debug print DMA: dmatest: extend the "device" module parameter to 32 characters drivers/dma: fix error return code dma: omap: Set debug level to debugging messages dmaengine: fix kernel-doc style typos for few comments dma: tegra: add support for Tegra148/124 dma: dw: use %pad instead of casting dma_addr_t dma: dw: join split up messages dma: dw: fix style of multiline comment dmaengine: k3dma: fix sparse warnings dma: pl330: Use dma_get_slave_channel() in the of xlate callback dma: pl330: Differentiate between submitted and issued descriptors dmaengine: sirf: Add device_slave_caps interface DMA: Freescale: change BWC from 256 bytes to 1024 bytes dmaengine: Add MOXA ART DMA engine driver dmaengine: Add DMA_PRIVATE to BCM2835 driver dma: imx-sdma: Assign a default script number for ROM firmware cases ...
Diffstat (limited to 'drivers/dma/tegra20-apb-dma.c')
-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 d11bb3620f27..03ad64ecaaf0 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -100,6 +100,11 @@
100#define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27) 100#define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27)
101#define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16) 101#define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16)
102 102
103/* Tegra148 specific registers */
104#define TEGRA_APBDMA_CHAN_WCOUNT 0x20
105
106#define TEGRA_APBDMA_CHAN_WORD_TRANSFER 0x24
107
103/* 108/*
104 * If any burst is in flight and DMA paused then this is the time to complete 109 * If any burst is in flight and DMA paused then this is the time to complete
105 * on-flight burst and update DMA status register. 110 * on-flight burst and update DMA status register.
@@ -109,21 +114,22 @@
109/* Channel base address offset from APBDMA base address */ 114/* Channel base address offset from APBDMA base address */
110#define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000 115#define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000
111 116
112/* DMA channel register space size */
113#define TEGRA_APBDMA_CHANNEL_REGISTER_SIZE 0x20
114
115struct tegra_dma; 117struct tegra_dma;
116 118
117/* 119/*
118 * tegra_dma_chip_data Tegra chip specific DMA data 120 * tegra_dma_chip_data Tegra chip specific DMA data
119 * @nr_channels: Number of channels available in the controller. 121 * @nr_channels: Number of channels available in the controller.
122 * @channel_reg_size: Channel register size/stride.
120 * @max_dma_count: Maximum DMA transfer count supported by DMA controller. 123 * @max_dma_count: Maximum DMA transfer count supported by DMA controller.
121 * @support_channel_pause: Support channel wise pause of dma. 124 * @support_channel_pause: Support channel wise pause of dma.
125 * @support_separate_wcount_reg: Support separate word count register.
122 */ 126 */
123struct tegra_dma_chip_data { 127struct tegra_dma_chip_data {
124 int nr_channels; 128 int nr_channels;
129 int channel_reg_size;
125 int max_dma_count; 130 int max_dma_count;
126 bool support_channel_pause; 131 bool support_channel_pause;
132 bool support_separate_wcount_reg;
127}; 133};
128 134
129/* DMA channel registers */ 135/* DMA channel registers */
@@ -133,6 +139,7 @@ struct tegra_dma_channel_regs {
133 unsigned long apb_ptr; 139 unsigned long apb_ptr;
134 unsigned long ahb_seq; 140 unsigned long ahb_seq;
135 unsigned long apb_seq; 141 unsigned long apb_seq;
142 unsigned long wcount;
136}; 143};
137 144
138/* 145/*
@@ -426,6 +433,8 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc,
426 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr); 433 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr);
427 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq); 434 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq);
428 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr); 435 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr);
436 if (tdc->tdma->chip_data->support_separate_wcount_reg)
437 tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT, ch_regs->wcount);
429 438
430 /* Start DMA */ 439 /* Start DMA */
431 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, 440 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
@@ -465,6 +474,9 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
465 /* Safe to program new configuration */ 474 /* Safe to program new configuration */
466 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr); 475 tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr);
467 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr); 476 tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr);
477 if (tdc->tdma->chip_data->support_separate_wcount_reg)
478 tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT,
479 nsg_req->ch_regs.wcount);
468 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, 480 tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
469 nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); 481 nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB);
470 nsg_req->configured = true; 482 nsg_req->configured = true;
@@ -718,6 +730,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
718 struct tegra_dma_desc *dma_desc; 730 struct tegra_dma_desc *dma_desc;
719 unsigned long flags; 731 unsigned long flags;
720 unsigned long status; 732 unsigned long status;
733 unsigned long wcount;
721 bool was_busy; 734 bool was_busy;
722 735
723 spin_lock_irqsave(&tdc->lock, flags); 736 spin_lock_irqsave(&tdc->lock, flags);
@@ -738,6 +751,10 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
738 tdc->isr_handler(tdc, true); 751 tdc->isr_handler(tdc, true);
739 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); 752 status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS);
740 } 753 }
754 if (tdc->tdma->chip_data->support_separate_wcount_reg)
755 wcount = tdc_read(tdc, TEGRA_APBDMA_CHAN_WORD_TRANSFER);
756 else
757 wcount = status;
741 758
742 was_busy = tdc->busy; 759 was_busy = tdc->busy;
743 tegra_dma_stop(tdc); 760 tegra_dma_stop(tdc);
@@ -746,7 +763,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
746 sgreq = list_first_entry(&tdc->pending_sg_req, 763 sgreq = list_first_entry(&tdc->pending_sg_req,
747 typeof(*sgreq), node); 764 typeof(*sgreq), node);
748 sgreq->dma_desc->bytes_transferred += 765 sgreq->dma_desc->bytes_transferred +=
749 get_current_xferred_count(tdc, sgreq, status); 766 get_current_xferred_count(tdc, sgreq, wcount);
750 } 767 }
751 tegra_dma_resume(tdc); 768 tegra_dma_resume(tdc);
752 769
@@ -908,6 +925,17 @@ static int get_transfer_param(struct tegra_dma_channel *tdc,
908 return -EINVAL; 925 return -EINVAL;
909} 926}
910 927
928static void tegra_dma_prep_wcount(struct tegra_dma_channel *tdc,
929 struct tegra_dma_channel_regs *ch_regs, u32 len)
930{
931 u32 len_field = (len - 4) & 0xFFFC;
932
933 if (tdc->tdma->chip_data->support_separate_wcount_reg)
934 ch_regs->wcount = len_field;
935 else
936 ch_regs->csr |= len_field;
937}
938
911static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( 939static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
912 struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len, 940 struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len,
913 enum dma_transfer_direction direction, unsigned long flags, 941 enum dma_transfer_direction direction, unsigned long flags,
@@ -991,7 +1019,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
991 1019
992 sg_req->ch_regs.apb_ptr = apb_ptr; 1020 sg_req->ch_regs.apb_ptr = apb_ptr;
993 sg_req->ch_regs.ahb_ptr = mem; 1021 sg_req->ch_regs.ahb_ptr = mem;
994 sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); 1022 sg_req->ch_regs.csr = csr;
1023 tegra_dma_prep_wcount(tdc, &sg_req->ch_regs, len);
995 sg_req->ch_regs.apb_seq = apb_seq; 1024 sg_req->ch_regs.apb_seq = apb_seq;
996 sg_req->ch_regs.ahb_seq = ahb_seq; 1025 sg_req->ch_regs.ahb_seq = ahb_seq;
997 sg_req->configured = false; 1026 sg_req->configured = false;
@@ -1120,7 +1149,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
1120 ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len); 1149 ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
1121 sg_req->ch_regs.apb_ptr = apb_ptr; 1150 sg_req->ch_regs.apb_ptr = apb_ptr;
1122 sg_req->ch_regs.ahb_ptr = mem; 1151 sg_req->ch_regs.ahb_ptr = mem;
1123 sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); 1152 sg_req->ch_regs.csr = csr;
1153 tegra_dma_prep_wcount(tdc, &sg_req->ch_regs, len);
1124 sg_req->ch_regs.apb_seq = apb_seq; 1154 sg_req->ch_regs.apb_seq = apb_seq;
1125 sg_req->ch_regs.ahb_seq = ahb_seq; 1155 sg_req->ch_regs.ahb_seq = ahb_seq;
1126 sg_req->configured = false; 1156 sg_req->configured = false;
@@ -1234,27 +1264,45 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
1234/* Tegra20 specific DMA controller information */ 1264/* Tegra20 specific DMA controller information */
1235static const struct tegra_dma_chip_data tegra20_dma_chip_data = { 1265static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
1236 .nr_channels = 16, 1266 .nr_channels = 16,
1267 .channel_reg_size = 0x20,
1237 .max_dma_count = 1024UL * 64, 1268 .max_dma_count = 1024UL * 64,
1238 .support_channel_pause = false, 1269 .support_channel_pause = false,
1270 .support_separate_wcount_reg = false,
1239}; 1271};
1240 1272
1241/* Tegra30 specific DMA controller information */ 1273/* Tegra30 specific DMA controller information */
1242static const struct tegra_dma_chip_data tegra30_dma_chip_data = { 1274static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
1243 .nr_channels = 32, 1275 .nr_channels = 32,
1276 .channel_reg_size = 0x20,
1244 .max_dma_count = 1024UL * 64, 1277 .max_dma_count = 1024UL * 64,
1245 .support_channel_pause = false, 1278 .support_channel_pause = false,
1279 .support_separate_wcount_reg = false,
1246}; 1280};
1247 1281
1248/* Tegra114 specific DMA controller information */ 1282/* Tegra114 specific DMA controller information */
1249static const struct tegra_dma_chip_data tegra114_dma_chip_data = { 1283static const struct tegra_dma_chip_data tegra114_dma_chip_data = {
1250 .nr_channels = 32, 1284 .nr_channels = 32,
1285 .channel_reg_size = 0x20,
1251 .max_dma_count = 1024UL * 64, 1286 .max_dma_count = 1024UL * 64,
1252 .support_channel_pause = true, 1287 .support_channel_pause = true,
1288 .support_separate_wcount_reg = false,
1289};
1290
1291/* Tegra148 specific DMA controller information */
1292static const struct tegra_dma_chip_data tegra148_dma_chip_data = {
1293 .nr_channels = 32,
1294 .channel_reg_size = 0x40,
1295 .max_dma_count = 1024UL * 64,
1296 .support_channel_pause = true,
1297 .support_separate_wcount_reg = true,
1253}; 1298};
1254 1299
1255 1300
1256static const struct of_device_id tegra_dma_of_match[] = { 1301static const struct of_device_id tegra_dma_of_match[] = {
1257 { 1302 {
1303 .compatible = "nvidia,tegra148-apbdma",
1304 .data = &tegra148_dma_chip_data,
1305 }, {
1258 .compatible = "nvidia,tegra114-apbdma", 1306 .compatible = "nvidia,tegra114-apbdma",
1259 .data = &tegra114_dma_chip_data, 1307 .data = &tegra114_dma_chip_data,
1260 }, { 1308 }, {
@@ -1348,7 +1396,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
1348 struct tegra_dma_channel *tdc = &tdma->channels[i]; 1396 struct tegra_dma_channel *tdc = &tdma->channels[i];
1349 1397
1350 tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET + 1398 tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET +
1351 i * TEGRA_APBDMA_CHANNEL_REGISTER_SIZE; 1399 i * cdata->channel_reg_size;
1352 1400
1353 res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 1401 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
1354 if (!res) { 1402 if (!res) {