diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-29 23:27:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-29 23:27:23 -0500 |
commit | ca2a650f3dfdc30d71d21bcbb04d2d057779f3f9 (patch) | |
tree | 12e5f7f4dea5ba17cc82f2c633bbe9dbf725fb11 /drivers/dma/tegra20-apb-dma.c | |
parent | e9e352e9100b98aed1a5fb9e33355c29fb07d5b1 (diff) | |
parent | 15cec530e4bc7bed3f51cde8404f96fd28a8c7c5 (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.c | 62 |
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 | |||
115 | struct tegra_dma; | 117 | struct 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 | */ |
123 | struct tegra_dma_chip_data { | 127 | struct 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 | ||
928 | static 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 | |||
911 | static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( | 939 | static 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 */ |
1235 | static const struct tegra_dma_chip_data tegra20_dma_chip_data = { | 1265 | static 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 */ |
1242 | static const struct tegra_dma_chip_data tegra30_dma_chip_data = { | 1274 | static 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 */ |
1249 | static const struct tegra_dma_chip_data tegra114_dma_chip_data = { | 1283 | static 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 */ | ||
1292 | static 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 | ||
1256 | static const struct of_device_id tegra_dma_of_match[] = { | 1301 | static 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) { |