diff options
-rw-r--r-- | Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt | 6 | ||||
-rw-r--r-- | drivers/dma/ti-dma-crossbar.c | 47 |
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 | ||
15 | Optional properties: | 15 | Optional 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 | ||
18 | Notes: | 22 | Notes: |
19 | When requesting channel via ti,dra7-dma-crossbar, the DMA clinet must request | 23 | When 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 | ||
299 | static 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 | |||
299 | static int ti_dra7_xbar_probe(struct platform_device *pdev) | 305 | static 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; |