aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2013-04-19 05:11:18 -0400
committerVinod Koul <vinod.koul@intel.com>2013-04-30 04:47:41 -0400
commitbbe89c8e3d598129b728d1388c3ad9abe4e8e261 (patch)
treeb4654e214de37c86501ad83005c29a8419a97a3d
parente6a30fec08b421a59064437a7d990c70a80a7e7f (diff)
at_hdmac: move to generic DMA binding
Update at_hdmac driver to support generic DMA device tree binding. Devices can still request channel with dma_request_channel() then it doesn't break DMA for non DT boards. Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--Documentation/devicetree/bindings/dma/atmel-dma.txt35
-rw-r--r--drivers/dma/at_hdmac.c93
-rw-r--r--drivers/dma/at_hdmac_regs.h4
3 files changed, 121 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/dma/atmel-dma.txt b/Documentation/devicetree/bindings/dma/atmel-dma.txt
index 3c046ee6e8b5..c80e8a3402f0 100644
--- a/Documentation/devicetree/bindings/dma/atmel-dma.txt
+++ b/Documentation/devicetree/bindings/dma/atmel-dma.txt
@@ -1,14 +1,39 @@
1* Atmel Direct Memory Access Controller (DMA) 1* Atmel Direct Memory Access Controller (DMA)
2 2
3Required properties: 3Required properties:
4- compatible: Should be "atmel,<chip>-dma" 4- compatible: Should be "atmel,<chip>-dma".
5- reg: Should contain DMA registers location and length 5- reg: Should contain DMA registers location and length.
6- interrupts: Should contain DMA interrupt 6- interrupts: Should contain DMA interrupt.
7- #dma-cells: Must be <2>, used to represent the number of integer cells in
8the dmas property of client devices.
7 9
8Examples: 10Example:
9 11
10dma@ffffec00 { 12dma0: dma@ffffec00 {
11 compatible = "atmel,at91sam9g45-dma"; 13 compatible = "atmel,at91sam9g45-dma";
12 reg = <0xffffec00 0x200>; 14 reg = <0xffffec00 0x200>;
13 interrupts = <21>; 15 interrupts = <21>;
16 #dma-cells = <2>;
17};
18
19DMA clients connected to the Atmel DMA controller must use the format
20described in the dma.txt file, using a three-cell specifier for each channel:
21a phandle plus two interger cells.
22The three cells in order are:
23
241. A phandle pointing to the DMA controller.
252. The memory interface (16 most significant bits), the peripheral interface
26(16 less significant bits).
273. The peripheral identifier for the hardware handshaking interface. The
28identifier can be different for tx and rx.
29
30Example:
31
32i2c0@i2c@f8010000 {
33 compatible = "atmel,at91sam9x5-i2c";
34 reg = <0xf8010000 0x100>;
35 interrupts = <9 4 6>;
36 dmas = <&dma0 1 7>,
37 <&dma0 1 8>;
38 dma-names = "tx", "rx";
14}; 39};
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 841546776159..3502c412caf9 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/of_dma.h>
27 28
28#include "at_hdmac_regs.h" 29#include "at_hdmac_regs.h"
29#include "dmaengine.h" 30#include "dmaengine.h"
@@ -676,7 +677,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
676 ctrlb |= ATC_DST_ADDR_MODE_FIXED 677 ctrlb |= ATC_DST_ADDR_MODE_FIXED
677 | ATC_SRC_ADDR_MODE_INCR 678 | ATC_SRC_ADDR_MODE_INCR
678 | ATC_FC_MEM2PER 679 | ATC_FC_MEM2PER
679 | ATC_SIF(AT_DMA_MEM_IF) | ATC_DIF(AT_DMA_PER_IF); 680 | ATC_SIF(atchan->mem_if) | ATC_DIF(atchan->per_if);
680 reg = sconfig->dst_addr; 681 reg = sconfig->dst_addr;
681 for_each_sg(sgl, sg, sg_len, i) { 682 for_each_sg(sgl, sg, sg_len, i) {
682 struct at_desc *desc; 683 struct at_desc *desc;
@@ -715,7 +716,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
715 ctrlb |= ATC_DST_ADDR_MODE_INCR 716 ctrlb |= ATC_DST_ADDR_MODE_INCR
716 | ATC_SRC_ADDR_MODE_FIXED 717 | ATC_SRC_ADDR_MODE_FIXED
717 | ATC_FC_PER2MEM 718 | ATC_FC_PER2MEM
718 | ATC_SIF(AT_DMA_PER_IF) | ATC_DIF(AT_DMA_MEM_IF); 719 | ATC_SIF(atchan->per_if) | ATC_DIF(atchan->mem_if);
719 720
720 reg = sconfig->src_addr; 721 reg = sconfig->src_addr;
721 for_each_sg(sgl, sg, sg_len, i) { 722 for_each_sg(sgl, sg, sg_len, i) {
@@ -821,8 +822,8 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
821 desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED 822 desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED
822 | ATC_SRC_ADDR_MODE_INCR 823 | ATC_SRC_ADDR_MODE_INCR
823 | ATC_FC_MEM2PER 824 | ATC_FC_MEM2PER
824 | ATC_SIF(AT_DMA_MEM_IF) 825 | ATC_SIF(atchan->mem_if)
825 | ATC_DIF(AT_DMA_PER_IF); 826 | ATC_DIF(atchan->per_if);
826 break; 827 break;
827 828
828 case DMA_DEV_TO_MEM: 829 case DMA_DEV_TO_MEM:
@@ -832,8 +833,8 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
832 desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR 833 desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR
833 | ATC_SRC_ADDR_MODE_FIXED 834 | ATC_SRC_ADDR_MODE_FIXED
834 | ATC_FC_PER2MEM 835 | ATC_FC_PER2MEM
835 | ATC_SIF(AT_DMA_PER_IF) 836 | ATC_SIF(atchan->per_if)
836 | ATC_DIF(AT_DMA_MEM_IF); 837 | ATC_DIF(atchan->mem_if);
837 break; 838 break;
838 839
839 default: 840 default:
@@ -1189,6 +1190,67 @@ static void atc_free_chan_resources(struct dma_chan *chan)
1189 dev_vdbg(chan2dev(chan), "free_chan_resources: done\n"); 1190 dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
1190} 1191}
1191 1192
1193#ifdef CONFIG_OF
1194static bool at_dma_filter(struct dma_chan *chan, void *slave)
1195{
1196 struct at_dma_slave *atslave = slave;
1197
1198 if (atslave->dma_dev == chan->device->dev) {
1199 chan->private = atslave;
1200 return true;
1201 } else {
1202 return false;
1203 }
1204}
1205
1206static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
1207 struct of_dma *of_dma)
1208{
1209 struct dma_chan *chan;
1210 struct at_dma_chan *atchan;
1211 struct at_dma_slave *atslave;
1212 dma_cap_mask_t mask;
1213 unsigned int per_id;
1214 struct platform_device *dmac_pdev;
1215
1216 if (dma_spec->args_count != 2)
1217 return NULL;
1218
1219 dmac_pdev = of_find_device_by_node(dma_spec->np);
1220
1221 dma_cap_zero(mask);
1222 dma_cap_set(DMA_SLAVE, mask);
1223
1224 atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL);
1225 if (!atslave)
1226 return NULL;
1227 /*
1228 * We can fill both SRC_PER and DST_PER, one of these fields will be
1229 * ignored depending on DMA transfer direction.
1230 */
1231 per_id = dma_spec->args[1];
1232 atslave->cfg = ATC_FIFOCFG_HALFFIFO | ATC_DST_H2SEL_HW
1233 | ATC_SRC_H2SEL_HW | ATC_DST_PER(per_id)
1234 | ATC_SRC_PER(per_id);
1235 atslave->dma_dev = &dmac_pdev->dev;
1236
1237 chan = dma_request_channel(mask, at_dma_filter, atslave);
1238 if (!chan)
1239 return NULL;
1240
1241 atchan = to_at_dma_chan(chan);
1242 atchan->per_if = dma_spec->args[0] & 0xff;
1243 atchan->mem_if = (dma_spec->args[0] >> 16) & 0xff;
1244
1245 return chan;
1246}
1247#else
1248static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
1249 struct of_dma *of_dma)
1250{
1251 return NULL;
1252}
1253#endif
1192 1254
1193/*-- Module Management -----------------------------------------------*/ 1255/*-- Module Management -----------------------------------------------*/
1194 1256
@@ -1343,6 +1405,8 @@ static int __init at_dma_probe(struct platform_device *pdev)
1343 for (i = 0; i < plat_dat->nr_channels; i++) { 1405 for (i = 0; i < plat_dat->nr_channels; i++) {
1344 struct at_dma_chan *atchan = &atdma->chan[i]; 1406 struct at_dma_chan *atchan = &atdma->chan[i];
1345 1407
1408 atchan->mem_if = AT_DMA_MEM_IF;
1409 atchan->per_if = AT_DMA_PER_IF;
1346 atchan->chan_common.device = &atdma->dma_common; 1410 atchan->chan_common.device = &atdma->dma_common;
1347 dma_cookie_init(&atchan->chan_common); 1411 dma_cookie_init(&atchan->chan_common);
1348 list_add_tail(&atchan->chan_common.device_node, 1412 list_add_tail(&atchan->chan_common.device_node,
@@ -1389,8 +1453,25 @@ static int __init at_dma_probe(struct platform_device *pdev)
1389 1453
1390 dma_async_device_register(&atdma->dma_common); 1454 dma_async_device_register(&atdma->dma_common);
1391 1455
1456 /*
1457 * Do not return an error if the dmac node is not present in order to
1458 * not break the existing way of requesting channel with
1459 * dma_request_channel().
1460 */
1461 if (pdev->dev.of_node) {
1462 err = of_dma_controller_register(pdev->dev.of_node,
1463 at_dma_xlate, atdma);
1464 if (err) {
1465 dev_err(&pdev->dev, "could not register of_dma_controller\n");
1466 goto err_of_dma_controller_register;
1467 }
1468 }
1469
1392 return 0; 1470 return 0;
1393 1471
1472err_of_dma_controller_register:
1473 dma_async_device_unregister(&atdma->dma_common);
1474 dma_pool_destroy(atdma->dma_desc_pool);
1394err_pool_create: 1475err_pool_create:
1395 platform_set_drvdata(pdev, NULL); 1476 platform_set_drvdata(pdev, NULL);
1396 free_irq(platform_get_irq(pdev, 0), atdma); 1477 free_irq(platform_get_irq(pdev, 0), atdma);
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 0eb3c1388667..c604d26fd4d3 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -220,6 +220,8 @@ enum atc_status {
220 * @device: parent device 220 * @device: parent device
221 * @ch_regs: memory mapped register base 221 * @ch_regs: memory mapped register base
222 * @mask: channel index in a mask 222 * @mask: channel index in a mask
223 * @per_if: peripheral interface
224 * @mem_if: memory interface
223 * @status: transmit status information from irq/prep* functions 225 * @status: transmit status information from irq/prep* functions
224 * to tasklet (use atomic operations) 226 * to tasklet (use atomic operations)
225 * @tasklet: bottom half to finish transaction work 227 * @tasklet: bottom half to finish transaction work
@@ -238,6 +240,8 @@ struct at_dma_chan {
238 struct at_dma *device; 240 struct at_dma *device;
239 void __iomem *ch_regs; 241 void __iomem *ch_regs;
240 u8 mask; 242 u8 mask;
243 u8 per_if;
244 u8 mem_if;
241 unsigned long status; 245 unsigned long status;
242 struct tasklet_struct tasklet; 246 struct tasklet_struct tasklet;
243 u32 save_cfg; 247 u32 save_cfg;