diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 12:24:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 12:24:48 -0500 |
commit | 5115f3c19d17851aaff5a857f55b4a019c908775 (patch) | |
tree | 0d02cf01e12e86365f4f5e3b234f986daef181a7 /drivers/dma/pl330.c | |
parent | c41b3810c09e60664433548c5218cc6ece6a8903 (diff) | |
parent | 17166a3b6e88b93189e6be5f7e1335a3cc4fa965 (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.c | 101 |
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 | ||
610 | struct dma_pl330_filter_args { | ||
611 | struct dma_pl330_dmac *pdmac; | ||
612 | unsigned int chan_id; | ||
613 | }; | ||
614 | |||
609 | static inline void _callback(struct pl330_req *r, enum pl330_op_err err) | 615 | static 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 | ||
2361 | static 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 | |||
2355 | bool pl330_filter(struct dma_chan *chan, void *param) | 2371 | bool 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 | } |
2379 | EXPORT_SYMBOL(pl330_filter); | 2381 | EXPORT_SYMBOL(pl330_filter); |
2380 | 2382 | ||
2383 | static 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 | |||
2381 | static int pl330_alloc_chan_resources(struct dma_chan *chan) | 2407 | static 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 | ||
2978 | probe_err4: | ||
2979 | pl330_del(pi); | ||
2980 | probe_err3: | ||
2981 | free_irq(irq, pi); | ||
2982 | probe_err2: | 3008 | probe_err2: |
2983 | iounmap(pi->base); | 3009 | pl330_del(pi); |
2984 | probe_err1: | 3010 | probe_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 | ||