aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2015-10-30 04:00:37 -0400
committerVinod Koul <vinod.koul@intel.com>2015-11-30 04:39:16 -0500
commit0f73f3e85757091f40019b71077b41a717182b29 (patch)
tree4f07b7ba263757b20c8daaa3862f7ca8b8eacf1b
parentec9bfa1e1a796ef7acc2e55917c9b8be5a79e70e (diff)
dmaengine: ti-dma-crossbar: dra7: Support for reserving DMA event ranges
In eDMA the events are directly mapped to a DMA channel (for example DMA event 14 can only be handled by DMA channel 14). If the memcpy is enabled on the eDMA, there is a possibility that the crossbar driver would assign DMA event number already allocated in eDMA for memcpy. Furthermore the eDMA can be shared with DSP in which case the crossbar driver should also avoid mapping xbar events to DSP used event numbers (or channels). Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt6
-rw-r--r--drivers/dma/ti-dma-crossbar.c47
2 files changed, 49 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt b/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt
index b152a75dceae..aead5869a28d 100644
--- a/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt
+++ b/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt
@@ -14,6 +14,10 @@ The DMA controller node need to have the following poroperties:
14 14
15Optional properties: 15Optional properties:
16- ti,dma-safe-map: Safe routing value for unused request lines 16- ti,dma-safe-map: Safe routing value for unused request lines
17- ti,reserved-dma-request-ranges: DMA request ranges which should not be used
18 when mapping xbar input to DMA request, they are either
19 allocated to be used by for example the DSP or they are used as
20 memcpy channels in eDMA.
17 21
18Notes: 22Notes:
19When requesting channel via ti,dra7-dma-crossbar, the DMA clinet must request 23When requesting channel via ti,dra7-dma-crossbar, the DMA clinet must request
@@ -46,6 +50,8 @@ sdma_xbar: dma-router@4a002b78 {
46 #dma-cells = <1>; 50 #dma-cells = <1>;
47 dma-requests = <205>; 51 dma-requests = <205>;
48 ti,dma-safe-map = <0>; 52 ti,dma-safe-map = <0>;
53 /* Protect the sDMA request ranges: 10-14 and 100-126 */
54 ti,reserved-dma-request-ranges = <10 5>, <100 27>;
49 dma-masters = <&sdma>; 55 dma-masters = <&sdma>;
50}; 56};
51 57
diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c
index 7b1e3ea874bf..e107779b1a2e 100644
--- a/drivers/dma/ti-dma-crossbar.c
+++ b/drivers/dma/ti-dma-crossbar.c
@@ -296,14 +296,22 @@ static const struct of_device_id ti_dra7_master_match[] = {
296 {}, 296 {},
297}; 297};
298 298
299static inline void ti_dra7_xbar_reserve(int offset, int len, unsigned long *p)
300{
301 for (; len > 0; len--)
302 clear_bit(offset + (len - 1), p);
303}
304
299static int ti_dra7_xbar_probe(struct platform_device *pdev) 305static int ti_dra7_xbar_probe(struct platform_device *pdev)
300{ 306{
301 struct device_node *node = pdev->dev.of_node; 307 struct device_node *node = pdev->dev.of_node;
302 const struct of_device_id *match; 308 const struct of_device_id *match;
303 struct device_node *dma_node; 309 struct device_node *dma_node;
304 struct ti_dra7_xbar_data *xbar; 310 struct ti_dra7_xbar_data *xbar;
311 struct property *prop;
305 struct resource *res; 312 struct resource *res;
306 u32 safe_val; 313 u32 safe_val;
314 size_t sz;
307 void __iomem *iomem; 315 void __iomem *iomem;
308 int i, ret; 316 int i, ret;
309 317
@@ -351,6 +359,33 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
351 if (!of_property_read_u32(node, "ti,dma-safe-map", &safe_val)) 359 if (!of_property_read_u32(node, "ti,dma-safe-map", &safe_val))
352 xbar->safe_val = (u16)safe_val; 360 xbar->safe_val = (u16)safe_val;
353 361
362
363 prop = of_find_property(node, "ti,reserved-dma-request-ranges", &sz);
364 if (prop) {
365 const char pname[] = "ti,reserved-dma-request-ranges";
366 u32 (*rsv_events)[2];
367 size_t nelm = sz / sizeof(*rsv_events);
368 int i;
369
370 if (!nelm)
371 return -EINVAL;
372
373 rsv_events = kcalloc(nelm, sizeof(*rsv_events), GFP_KERNEL);
374 if (!rsv_events)
375 return -ENOMEM;
376
377 ret = of_property_read_u32_array(node, pname, (u32 *)rsv_events,
378 nelm * 2);
379 if (ret)
380 return ret;
381
382 for (i = 0; i < nelm; i++) {
383 ti_dra7_xbar_reserve(rsv_events[i][0], rsv_events[i][1],
384 xbar->dma_inuse);
385 }
386 kfree(rsv_events);
387 }
388
354 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 389 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
355 iomem = devm_ioremap_resource(&pdev->dev, res); 390 iomem = devm_ioremap_resource(&pdev->dev, res);
356 if (IS_ERR(iomem)) 391 if (IS_ERR(iomem))
@@ -366,15 +401,19 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
366 platform_set_drvdata(pdev, xbar); 401 platform_set_drvdata(pdev, xbar);
367 402
368 /* Reset the crossbar */ 403 /* Reset the crossbar */
369 for (i = 0; i < xbar->dma_requests; i++) 404 for (i = 0; i < xbar->dma_requests; i++) {
370 ti_dra7_xbar_write(xbar->iomem, i, xbar->safe_val); 405 if (!test_bit(i, xbar->dma_inuse))
406 ti_dra7_xbar_write(xbar->iomem, i, xbar->safe_val);
407 }
371 408
372 ret = of_dma_router_register(node, ti_dra7_xbar_route_allocate, 409 ret = of_dma_router_register(node, ti_dra7_xbar_route_allocate,
373 &xbar->dmarouter); 410 &xbar->dmarouter);
374 if (ret) { 411 if (ret) {
375 /* Restore the defaults for the crossbar */ 412 /* Restore the defaults for the crossbar */
376 for (i = 0; i < xbar->dma_requests; i++) 413 for (i = 0; i < xbar->dma_requests; i++) {
377 ti_dra7_xbar_write(xbar->iomem, i, i); 414 if (!test_bit(i, xbar->dma_inuse))
415 ti_dra7_xbar_write(xbar->iomem, i, i);
416 }
378 } 417 }
379 418
380 return ret; 419 return ret;