diff options
-rw-r--r-- | Documentation/devicetree/bindings/dma/arm-pl330.txt | 30 | ||||
-rw-r--r-- | drivers/dma/pl330.c | 33 |
2 files changed, 59 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt b/Documentation/devicetree/bindings/dma/arm-pl330.txt new file mode 100644 index 000000000000..a4cd273b2a67 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | * ARM PrimeCell PL330 DMA Controller | ||
2 | |||
3 | The ARM PrimeCell PL330 DMA controller can move blocks of memory contents | ||
4 | between memory and peripherals or memory to memory. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: should include both "arm,pl330" and "arm,primecell". | ||
8 | - reg: physical base address of the controller and length of memory mapped | ||
9 | region. | ||
10 | - interrupts: interrupt number to the cpu. | ||
11 | |||
12 | Example: | ||
13 | |||
14 | pdma0: pdma@12680000 { | ||
15 | compatible = "arm,pl330", "arm,primecell"; | ||
16 | reg = <0x12680000 0x1000>; | ||
17 | interrupts = <99>; | ||
18 | }; | ||
19 | |||
20 | Client drivers (device nodes requiring dma transfers from dev-to-mem or | ||
21 | mem-to-dev) should specify the DMA channel numbers using a two-value pair | ||
22 | as shown below. | ||
23 | |||
24 | [property name] = <[phandle of the dma controller] [dma request id]>; | ||
25 | |||
26 | where 'dma request id' is the dma request number which is connected | ||
27 | to the client controller. The 'property name' is recommended to be | ||
28 | of the form <name>-dma-channel. | ||
29 | |||
30 | Example: tx-dma-channel = <&pdma0 12>; | ||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 317aaeaa6f66..a626e15799a5 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/amba/pl330.h> | 19 | #include <linux/amba/pl330.h> |
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
22 | #include <linux/of.h> | ||
22 | 23 | ||
23 | #define NR_DEFAULT_DESC 16 | 24 | #define NR_DEFAULT_DESC 16 |
24 | 25 | ||
@@ -277,6 +278,20 @@ bool pl330_filter(struct dma_chan *chan, void *param) | |||
277 | if (chan->device->dev->driver != &pl330_driver.drv) | 278 | if (chan->device->dev->driver != &pl330_driver.drv) |
278 | return false; | 279 | return false; |
279 | 280 | ||
281 | #ifdef CONFIG_OF | ||
282 | if (chan->device->dev->of_node) { | ||
283 | const __be32 *prop_value; | ||
284 | phandle phandle; | ||
285 | struct device_node *node; | ||
286 | |||
287 | prop_value = ((struct property *)param)->value; | ||
288 | phandle = be32_to_cpup(prop_value++); | ||
289 | node = of_find_node_by_phandle(phandle); | ||
290 | return ((chan->private == node) && | ||
291 | (chan->chan_id == be32_to_cpup(prop_value))); | ||
292 | } | ||
293 | #endif | ||
294 | |||
280 | peri_id = chan->private; | 295 | peri_id = chan->private; |
281 | return *peri_id == (unsigned)param; | 296 | return *peri_id == (unsigned)param; |
282 | } | 297 | } |
@@ -855,12 +870,17 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
855 | INIT_LIST_HEAD(&pd->channels); | 870 | INIT_LIST_HEAD(&pd->channels); |
856 | 871 | ||
857 | /* Initialize channel parameters */ | 872 | /* Initialize channel parameters */ |
858 | num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan); | 873 | num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri, |
874 | (u8)pi->pcfg.num_chan); | ||
859 | pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); | 875 | pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); |
860 | 876 | ||
861 | for (i = 0; i < num_chan; i++) { | 877 | for (i = 0; i < num_chan; i++) { |
862 | pch = &pdmac->peripherals[i]; | 878 | pch = &pdmac->peripherals[i]; |
863 | pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; | 879 | if (!adev->dev.of_node) |
880 | pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; | ||
881 | else | ||
882 | pch->chan.private = adev->dev.of_node; | ||
883 | |||
864 | INIT_LIST_HEAD(&pch->work_list); | 884 | INIT_LIST_HEAD(&pch->work_list); |
865 | spin_lock_init(&pch->lock); | 885 | spin_lock_init(&pch->lock); |
866 | pch->pl330_chid = NULL; | 886 | pch->pl330_chid = NULL; |
@@ -872,10 +892,15 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
872 | } | 892 | } |
873 | 893 | ||
874 | pd->dev = &adev->dev; | 894 | pd->dev = &adev->dev; |
875 | if (pdat) | 895 | if (pdat) { |
876 | pd->cap_mask = pdat->cap_mask; | 896 | pd->cap_mask = pdat->cap_mask; |
877 | else | 897 | } else { |
878 | dma_cap_set(DMA_MEMCPY, pd->cap_mask); | 898 | dma_cap_set(DMA_MEMCPY, pd->cap_mask); |
899 | if (pi->pcfg.num_peri) { | ||
900 | dma_cap_set(DMA_SLAVE, pd->cap_mask); | ||
901 | dma_cap_set(DMA_CYCLIC, pd->cap_mask); | ||
902 | } | ||
903 | } | ||
879 | 904 | ||
880 | pd->device_alloc_chan_resources = pl330_alloc_chan_resources; | 905 | pd->device_alloc_chan_resources = pl330_alloc_chan_resources; |
881 | pd->device_free_chan_resources = pl330_free_chan_resources; | 906 | pd->device_free_chan_resources = pl330_free_chan_resources; |