aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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 /drivers
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/at_hdmac.c93
-rw-r--r--drivers/dma/at_hdmac_regs.h4
2 files changed, 91 insertions, 6 deletions
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;