aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/pl330.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:24:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:24:48 -0500
commit5115f3c19d17851aaff5a857f55b4a019c908775 (patch)
tree0d02cf01e12e86365f4f5e3b234f986daef181a7 /drivers/dma/pl330.c
parentc41b3810c09e60664433548c5218cc6ece6a8903 (diff)
parent17166a3b6e88b93189e6be5f7e1335a3cc4fa965 (diff)
Merge branch 'next' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dmaengine updates from Vinod Koul: "This is fairly big pull by my standards as I had missed last merge window. So we have the support for device tree for slave-dmaengine, large updates to dw_dmac driver from Andy for reusing on different architectures. Along with this we have fixes on bunch of the drivers" Fix up trivial conflicts, usually due to #include line movement next to each other. * 'next' of git://git.infradead.org/users/vkoul/slave-dma: (111 commits) Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT" ARM: dts: pl330: Add #dma-cells for generic dma binding support DMA: PL330: Register the DMA controller with the generic DMA helpers DMA: PL330: Add xlate function DMA: PL330: Add new pl330 filter for DT case. dma: tegra20-apb-dma: remove unnecessary assignment edma: do not waste memory for dma_mask dma: coh901318: set residue only if dma is in progress dma: coh901318: avoid unbalanced locking dmaengine.h: remove redundant else keyword dma: of-dma: protect list write operation by spin_lock dmaengine: ste_dma40: do not remove descriptors for cyclic transfers dma: of-dma.c: fix memory leakage dw_dmac: apply default dma_mask if needed dmaengine: ioat - fix spare sparse complain dmaengine: move drivers/of/dma.c -> drivers/dma/of-dma.c ioatdma: fix race between updating ioat->head and IOAT_COMPLETION_PENDING dw_dmac: add support for Lynxpoint DMA controllers dw_dmac: return proper residue value dw_dmac: fill individual length of descriptor ...
Diffstat (limited to 'drivers/dma/pl330.c')
-rw-r--r--drivers/dma/pl330.c101
1 files changed, 60 insertions, 41 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 80680eee0171..718153122759 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -25,6 +25,7 @@
25#include <linux/amba/pl330.h> 25#include <linux/amba/pl330.h>
26#include <linux/scatterlist.h> 26#include <linux/scatterlist.h>
27#include <linux/of.h> 27#include <linux/of.h>
28#include <linux/of_dma.h>
28 29
29#include "dmaengine.h" 30#include "dmaengine.h"
30#define PL330_MAX_CHAN 8 31#define PL330_MAX_CHAN 8
@@ -606,6 +607,11 @@ struct dma_pl330_desc {
606 struct dma_pl330_chan *pchan; 607 struct dma_pl330_chan *pchan;
607}; 608};
608 609
610struct dma_pl330_filter_args {
611 struct dma_pl330_dmac *pdmac;
612 unsigned int chan_id;
613};
614
609static inline void _callback(struct pl330_req *r, enum pl330_op_err err) 615static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
610{ 616{
611 if (r && r->xfer_cb) 617 if (r && r->xfer_cb)
@@ -2352,6 +2358,16 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
2352 tasklet_schedule(&pch->task); 2358 tasklet_schedule(&pch->task);
2353} 2359}
2354 2360
2361static bool pl330_dt_filter(struct dma_chan *chan, void *param)
2362{
2363 struct dma_pl330_filter_args *fargs = param;
2364
2365 if (chan->device != &fargs->pdmac->ddma)
2366 return false;
2367
2368 return (chan->chan_id == fargs->chan_id);
2369}
2370
2355bool pl330_filter(struct dma_chan *chan, void *param) 2371bool pl330_filter(struct dma_chan *chan, void *param)
2356{ 2372{
2357 u8 *peri_id; 2373 u8 *peri_id;
@@ -2359,25 +2375,35 @@ bool pl330_filter(struct dma_chan *chan, void *param)
2359 if (chan->device->dev->driver != &pl330_driver.drv) 2375 if (chan->device->dev->driver != &pl330_driver.drv)
2360 return false; 2376 return false;
2361 2377
2362#ifdef CONFIG_OF
2363 if (chan->device->dev->of_node) {
2364 const __be32 *prop_value;
2365 phandle phandle;
2366 struct device_node *node;
2367
2368 prop_value = ((struct property *)param)->value;
2369 phandle = be32_to_cpup(prop_value++);
2370 node = of_find_node_by_phandle(phandle);
2371 return ((chan->private == node) &&
2372 (chan->chan_id == be32_to_cpup(prop_value)));
2373 }
2374#endif
2375
2376 peri_id = chan->private; 2378 peri_id = chan->private;
2377 return *peri_id == (unsigned)param; 2379 return *peri_id == (unsigned)param;
2378} 2380}
2379EXPORT_SYMBOL(pl330_filter); 2381EXPORT_SYMBOL(pl330_filter);
2380 2382
2383static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
2384 struct of_dma *ofdma)
2385{
2386 int count = dma_spec->args_count;
2387 struct dma_pl330_dmac *pdmac = ofdma->of_dma_data;
2388 struct dma_pl330_filter_args fargs;
2389 dma_cap_mask_t cap;
2390
2391 if (!pdmac)
2392 return NULL;
2393
2394 if (count != 1)
2395 return NULL;
2396
2397 fargs.pdmac = pdmac;
2398 fargs.chan_id = dma_spec->args[0];
2399
2400 dma_cap_zero(cap);
2401 dma_cap_set(DMA_SLAVE, cap);
2402 dma_cap_set(DMA_CYCLIC, cap);
2403
2404 return dma_request_channel(cap, pl330_dt_filter, &fargs);
2405}
2406
2381static int pl330_alloc_chan_resources(struct dma_chan *chan) 2407static int pl330_alloc_chan_resources(struct dma_chan *chan)
2382{ 2408{
2383 struct dma_pl330_chan *pch = to_pchan(chan); 2409 struct dma_pl330_chan *pch = to_pchan(chan);
@@ -2866,7 +2892,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2866 pdat = adev->dev.platform_data; 2892 pdat = adev->dev.platform_data;
2867 2893
2868 /* Allocate a new DMAC and its Channels */ 2894 /* Allocate a new DMAC and its Channels */
2869 pdmac = kzalloc(sizeof(*pdmac), GFP_KERNEL); 2895 pdmac = devm_kzalloc(&adev->dev, sizeof(*pdmac), GFP_KERNEL);
2870 if (!pdmac) { 2896 if (!pdmac) {
2871 dev_err(&adev->dev, "unable to allocate mem\n"); 2897 dev_err(&adev->dev, "unable to allocate mem\n");
2872 return -ENOMEM; 2898 return -ENOMEM;
@@ -2878,13 +2904,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2878 pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0; 2904 pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
2879 2905
2880 res = &adev->res; 2906 res = &adev->res;
2881 request_mem_region(res->start, resource_size(res), "dma-pl330"); 2907 pi->base = devm_request_and_ioremap(&adev->dev, res);
2882 2908 if (!pi->base)
2883 pi->base = ioremap(res->start, resource_size(res)); 2909 return -ENXIO;
2884 if (!pi->base) {
2885 ret = -ENXIO;
2886 goto probe_err1;
2887 }
2888 2910
2889 amba_set_drvdata(adev, pdmac); 2911 amba_set_drvdata(adev, pdmac);
2890 2912
@@ -2892,11 +2914,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2892 ret = request_irq(irq, pl330_irq_handler, 0, 2914 ret = request_irq(irq, pl330_irq_handler, 0,
2893 dev_name(&adev->dev), pi); 2915 dev_name(&adev->dev), pi);
2894 if (ret) 2916 if (ret)
2895 goto probe_err2; 2917 return ret;
2896 2918
2897 ret = pl330_add(pi); 2919 ret = pl330_add(pi);
2898 if (ret) 2920 if (ret)
2899 goto probe_err3; 2921 goto probe_err1;
2900 2922
2901 INIT_LIST_HEAD(&pdmac->desc_pool); 2923 INIT_LIST_HEAD(&pdmac->desc_pool);
2902 spin_lock_init(&pdmac->pool_lock); 2924 spin_lock_init(&pdmac->pool_lock);
@@ -2918,7 +2940,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2918 if (!pdmac->peripherals) { 2940 if (!pdmac->peripherals) {
2919 ret = -ENOMEM; 2941 ret = -ENOMEM;
2920 dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); 2942 dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
2921 goto probe_err4; 2943 goto probe_err2;
2922 } 2944 }
2923 2945
2924 for (i = 0; i < num_chan; i++) { 2946 for (i = 0; i < num_chan; i++) {
@@ -2962,7 +2984,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2962 ret = dma_async_device_register(pd); 2984 ret = dma_async_device_register(pd);
2963 if (ret) { 2985 if (ret) {
2964 dev_err(&adev->dev, "unable to register DMAC\n"); 2986 dev_err(&adev->dev, "unable to register DMAC\n");
2965 goto probe_err4; 2987 goto probe_err2;
2966 } 2988 }
2967 2989
2968 dev_info(&adev->dev, 2990 dev_info(&adev->dev,
@@ -2973,17 +2995,20 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2973 pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan, 2995 pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
2974 pi->pcfg.num_peri, pi->pcfg.num_events); 2996 pi->pcfg.num_peri, pi->pcfg.num_events);
2975 2997
2998 ret = of_dma_controller_register(adev->dev.of_node,
2999 of_dma_pl330_xlate, pdmac);
3000 if (ret) {
3001 dev_err(&adev->dev,
3002 "unable to register DMA to the generic DT DMA helpers\n");
3003 goto probe_err2;
3004 }
3005
2976 return 0; 3006 return 0;
2977 3007
2978probe_err4:
2979 pl330_del(pi);
2980probe_err3:
2981 free_irq(irq, pi);
2982probe_err2: 3008probe_err2:
2983 iounmap(pi->base); 3009 pl330_del(pi);
2984probe_err1: 3010probe_err1:
2985 release_mem_region(res->start, resource_size(res)); 3011 free_irq(irq, pi);
2986 kfree(pdmac);
2987 3012
2988 return ret; 3013 return ret;
2989} 3014}
@@ -2993,12 +3018,13 @@ static int pl330_remove(struct amba_device *adev)
2993 struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev); 3018 struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
2994 struct dma_pl330_chan *pch, *_p; 3019 struct dma_pl330_chan *pch, *_p;
2995 struct pl330_info *pi; 3020 struct pl330_info *pi;
2996 struct resource *res;
2997 int irq; 3021 int irq;
2998 3022
2999 if (!pdmac) 3023 if (!pdmac)
3000 return 0; 3024 return 0;
3001 3025
3026 of_dma_controller_free(adev->dev.of_node);
3027
3002 amba_set_drvdata(adev, NULL); 3028 amba_set_drvdata(adev, NULL);
3003 3029
3004 /* Idle the DMAC */ 3030 /* Idle the DMAC */
@@ -3020,13 +3046,6 @@ static int pl330_remove(struct amba_device *adev)
3020 irq = adev->irq[0]; 3046 irq = adev->irq[0];
3021 free_irq(irq, pi); 3047 free_irq(irq, pi);
3022 3048
3023 iounmap(pi->base);
3024
3025 res = &adev->res;
3026 release_mem_region(res->start, resource_size(res));
3027
3028 kfree(pdmac);
3029
3030 return 0; 3049 return 0;
3031} 3050}
3032 3051