Commit 6cba4355066bda19f14d4da66b8abbca0ffdfd59

Authored by Matt Porter
Committed by Sekhar Nori
1 parent bf3156dde3

ARM: edma: Add DT and runtime PM support to the private EDMA API

Adds support for parsing the TI EDMA DT data into the required EDMA
private API platform data. Enables runtime PM support to initialize
the EDMA hwmod. Enables build on OMAP.

Changes by Joel:
* Setup default one-to-one mapping for queue_priority and queue_tc
mapping as discussed in [1].
* Split out xbar stuff to separate patch. [1]
* Dropped unused DT helper to convert to array
* Fixed dangling pointer issue with Sekhar's changes

[1] https://patchwork.kernel.org/patch/2226761/

Signed-off-by: Matt Porter <mporter@ti.com>
[nsekhar@ti.com: fix checkpatch errors, build breakages. Introduce
edma_setup_info_from_dt() as part of that effort]
Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>

Showing 8 changed files with 189 additions and 29 deletions Side-by-side Diff

arch/arm/common/edma.c
... ... @@ -25,6 +25,13 @@
25 25 #include <linux/platform_device.h>
26 26 #include <linux/io.h>
27 27 #include <linux/slab.h>
  28 +#include <linux/edma.h>
  29 +#include <linux/err.h>
  30 +#include <linux/of_address.h>
  31 +#include <linux/of_device.h>
  32 +#include <linux/of_dma.h>
  33 +#include <linux/of_irq.h>
  34 +#include <linux/pm_runtime.h>
28 35  
29 36 #include <linux/platform_data/edma.h>
30 37  
31 38  
32 39  
33 40  
... ... @@ -1369,13 +1376,110 @@
1369 1376 }
1370 1377 EXPORT_SYMBOL(edma_clear_event);
1371 1378  
1372   -/*-----------------------------------------------------------------------*/
  1379 +#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)
1373 1380  
1374   -static int __init edma_probe(struct platform_device *pdev)
  1381 +static int edma_of_parse_dt(struct device *dev,
  1382 + struct device_node *node,
  1383 + struct edma_soc_info *pdata)
1375 1384 {
  1385 + int ret = 0, i;
  1386 + u32 value;
  1387 + struct edma_rsv_info *rsv_info;
  1388 + s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
  1389 +
  1390 + memset(pdata, 0, sizeof(struct edma_soc_info));
  1391 +
  1392 + ret = of_property_read_u32(node, "dma-channels", &value);
  1393 + if (ret < 0)
  1394 + return ret;
  1395 + pdata->n_channel = value;
  1396 +
  1397 + ret = of_property_read_u32(node, "ti,edma-regions", &value);
  1398 + if (ret < 0)
  1399 + return ret;
  1400 + pdata->n_region = value;
  1401 +
  1402 + ret = of_property_read_u32(node, "ti,edma-slots", &value);
  1403 + if (ret < 0)
  1404 + return ret;
  1405 + pdata->n_slot = value;
  1406 +
  1407 + pdata->n_cc = 1;
  1408 +
  1409 + rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL);
  1410 + if (!rsv_info)
  1411 + return -ENOMEM;
  1412 + pdata->rsv = rsv_info;
  1413 +
  1414 + queue_tc_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL);
  1415 + if (!queue_tc_map)
  1416 + return -ENOMEM;
  1417 +
  1418 + for (i = 0; i < 3; i++) {
  1419 + queue_tc_map[i][0] = i;
  1420 + queue_tc_map[i][1] = i;
  1421 + }
  1422 + queue_tc_map[i][0] = -1;
  1423 + queue_tc_map[i][1] = -1;
  1424 +
  1425 + pdata->queue_tc_mapping = queue_tc_map;
  1426 +
  1427 + queue_priority_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL);
  1428 + if (!queue_priority_map)
  1429 + return -ENOMEM;
  1430 +
  1431 + for (i = 0; i < 3; i++) {
  1432 + queue_priority_map[i][0] = i;
  1433 + queue_priority_map[i][1] = i;
  1434 + }
  1435 + queue_priority_map[i][0] = -1;
  1436 + queue_priority_map[i][1] = -1;
  1437 +
  1438 + pdata->queue_priority_mapping = queue_priority_map;
  1439 +
  1440 + pdata->default_queue = 0;
  1441 +
  1442 + return ret;
  1443 +}
  1444 +
  1445 +static struct of_dma_filter_info edma_filter_info = {
  1446 + .filter_fn = edma_filter_fn,
  1447 +};
  1448 +
  1449 +static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
  1450 + struct device_node *node)
  1451 +{
  1452 + struct edma_soc_info *info;
  1453 + int ret;
  1454 +
  1455 + info = devm_kzalloc(dev, sizeof(struct edma_soc_info), GFP_KERNEL);
  1456 + if (!info)
  1457 + return ERR_PTR(-ENOMEM);
  1458 +
  1459 + ret = edma_of_parse_dt(dev, node, info);
  1460 + if (ret)
  1461 + return ERR_PTR(ret);
  1462 +
  1463 + dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
  1464 + of_dma_controller_register(dev->of_node, of_dma_simple_xlate,
  1465 + &edma_filter_info);
  1466 +
  1467 + return info;
  1468 +}
  1469 +#else
  1470 +static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
  1471 + struct device_node *node)
  1472 +{
  1473 + return ERR_PTR(-ENOSYS);
  1474 +}
  1475 +#endif
  1476 +
  1477 +static int edma_probe(struct platform_device *pdev)
  1478 +{
1376 1479 struct edma_soc_info **info = pdev->dev.platform_data;
1377   - const s8 (*queue_priority_mapping)[2];
1378   - const s8 (*queue_tc_mapping)[2];
  1480 + struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL};
  1481 + s8 (*queue_priority_mapping)[2];
  1482 + s8 (*queue_tc_mapping)[2];
1379 1483 int i, j, off, ln, found = 0;
1380 1484 int status = -1;
1381 1485 const s16 (*rsv_chans)[2];
1382 1486  
1383 1487  
1384 1488  
1385 1489  
1386 1490  
... ... @@ -1383,17 +1487,56 @@
1383 1487 int irq[EDMA_MAX_CC] = {0, 0};
1384 1488 int err_irq[EDMA_MAX_CC] = {0, 0};
1385 1489 struct resource *r[EDMA_MAX_CC] = {NULL};
  1490 + struct resource res[EDMA_MAX_CC];
1386 1491 char res_name[10];
1387 1492 char irq_name[10];
  1493 + struct device_node *node = pdev->dev.of_node;
  1494 + struct device *dev = &pdev->dev;
  1495 + int ret;
1388 1496  
  1497 + if (node) {
  1498 + /* Check if this is a second instance registered */
  1499 + if (arch_num_cc) {
  1500 + dev_err(dev, "only one EDMA instance is supported via DT\n");
  1501 + return -ENODEV;
  1502 + }
  1503 +
  1504 + ninfo[0] = edma_setup_info_from_dt(dev, node);
  1505 + if (IS_ERR(ninfo[0])) {
  1506 + dev_err(dev, "failed to get DT data\n");
  1507 + return PTR_ERR(ninfo[0]);
  1508 + }
  1509 +
  1510 + info = ninfo;
  1511 + }
  1512 +
1389 1513 if (!info)
1390 1514 return -ENODEV;
1391 1515  
  1516 + pm_runtime_enable(dev);
  1517 + ret = pm_runtime_get_sync(dev);
  1518 + if (ret < 0) {
  1519 + dev_err(dev, "pm_runtime_get_sync() failed\n");
  1520 + return ret;
  1521 + }
  1522 +
1392 1523 for (j = 0; j < EDMA_MAX_CC; j++) {
1393   - sprintf(res_name, "edma_cc%d", j);
1394   - r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  1524 + if (!info[j]) {
  1525 + if (!found)
  1526 + return -ENODEV;
  1527 + break;
  1528 + }
  1529 + if (node) {
  1530 + ret = of_address_to_resource(node, j, &res[j]);
  1531 + if (!ret)
  1532 + r[j] = &res[j];
  1533 + } else {
  1534 + sprintf(res_name, "edma_cc%d", j);
  1535 + r[j] = platform_get_resource_byname(pdev,
  1536 + IORESOURCE_MEM,
1395 1537 res_name);
1396   - if (!r[j] || !info[j]) {
  1538 + }
  1539 + if (!r[j]) {
1397 1540 if (found)
1398 1541 break;
1399 1542 else
... ... @@ -1440,7 +1583,7 @@
1440 1583 off = rsv_chans[i][0];
1441 1584 ln = rsv_chans[i][1];
1442 1585 clear_bits(off, ln,
1443   - edma_cc[j]->edma_unused);
  1586 + edma_cc[j]->edma_unused);
1444 1587 }
1445 1588 }
1446 1589  
... ... @@ -1456,8 +1599,13 @@
1456 1599 }
1457 1600 }
1458 1601  
1459   - sprintf(irq_name, "edma%d", j);
1460   - irq[j] = platform_get_irq_byname(pdev, irq_name);
  1602 +
  1603 + if (node) {
  1604 + irq[j] = irq_of_parse_and_map(node, 0);
  1605 + } else {
  1606 + sprintf(irq_name, "edma%d", j);
  1607 + irq[j] = platform_get_irq_byname(pdev, irq_name);
  1608 + }
1461 1609 edma_cc[j]->irq_res_start = irq[j];
1462 1610 status = devm_request_irq(&pdev->dev, irq[j],
1463 1611 dma_irq_handler, 0, "edma",
... ... @@ -1469,8 +1617,12 @@
1469 1617 return status;
1470 1618 }
1471 1619  
1472   - sprintf(irq_name, "edma%d_err", j);
1473   - err_irq[j] = platform_get_irq_byname(pdev, irq_name);
  1620 + if (node) {
  1621 + err_irq[j] = irq_of_parse_and_map(node, 2);
  1622 + } else {
  1623 + sprintf(irq_name, "edma%d_err", j);
  1624 + err_irq[j] = platform_get_irq_byname(pdev, irq_name);
  1625 + }
1474 1626 edma_cc[j]->irq_res_end = err_irq[j];
1475 1627 status = devm_request_irq(&pdev->dev, err_irq[j],
1476 1628 dma_ccerr_handler, 0,
1477 1629  
... ... @@ -1516,9 +1668,17 @@
1516 1668 return 0;
1517 1669 }
1518 1670  
  1671 +static const struct of_device_id edma_of_ids[] = {
  1672 + { .compatible = "ti,edma3", },
  1673 + {}
  1674 +};
1519 1675  
1520 1676 static struct platform_driver edma_driver = {
1521   - .driver.name = "edma",
  1677 + .driver = {
  1678 + .name = "edma",
  1679 + .of_match_table = edma_of_ids,
  1680 + },
  1681 + .probe = edma_probe,
1522 1682 };
1523 1683  
1524 1684 static int __init edma_init(void)
arch/arm/mach-davinci/devices-da8xx.c
... ... @@ -105,27 +105,27 @@
105 105 },
106 106 };
107 107  
108   -static const s8 da8xx_queue_tc_mapping[][2] = {
  108 +static s8 da8xx_queue_tc_mapping[][2] = {
109 109 /* {event queue no, TC no} */
110 110 {0, 0},
111 111 {1, 1},
112 112 {-1, -1}
113 113 };
114 114  
115   -static const s8 da8xx_queue_priority_mapping[][2] = {
  115 +static s8 da8xx_queue_priority_mapping[][2] = {
116 116 /* {event queue no, Priority} */
117 117 {0, 3},
118 118 {1, 7},
119 119 {-1, -1}
120 120 };
121 121  
122   -static const s8 da850_queue_tc_mapping[][2] = {
  122 +static s8 da850_queue_tc_mapping[][2] = {
123 123 /* {event queue no, TC no} */
124 124 {0, 0},
125 125 {-1, -1}
126 126 };
127 127  
128   -static const s8 da850_queue_priority_mapping[][2] = {
  128 +static s8 da850_queue_priority_mapping[][2] = {
129 129 /* {event queue no, Priority} */
130 130 {0, 3},
131 131 {-1, -1}
arch/arm/mach-davinci/devices-tnetv107x.c
... ... @@ -58,14 +58,14 @@
58 58 #define TNETV107X_DMACH_SDIO1_RX 28
59 59 #define TNETV107X_DMACH_SDIO1_TX 29
60 60  
61   -static const s8 edma_tc_mapping[][2] = {
  61 +static s8 edma_tc_mapping[][2] = {
62 62 /* event queue no TC no */
63 63 { 0, 0 },
64 64 { 1, 1 },
65 65 { -1, -1 }
66 66 };
67 67  
68   -static const s8 edma_priority_mapping[][2] = {
  68 +static s8 edma_priority_mapping[][2] = {
69 69 /* event queue no Prio */
70 70 { 0, 3 },
71 71 { 1, 7 },
arch/arm/mach-davinci/dm355.c
... ... @@ -569,7 +569,7 @@
569 569  
570 570 /*----------------------------------------------------------------------*/
571 571  
572   -static const s8
  572 +static s8
573 573 queue_tc_mapping[][2] = {
574 574 /* {event queue no, TC no} */
575 575 {0, 0},
... ... @@ -577,7 +577,7 @@
577 577 {-1, -1},
578 578 };
579 579  
580   -static const s8
  580 +static s8
581 581 queue_priority_mapping[][2] = {
582 582 /* {event queue no, Priority} */
583 583 {0, 3},
arch/arm/mach-davinci/dm365.c
... ... @@ -826,7 +826,7 @@
826 826 };
827 827  
828 828 /* Four Transfer Controllers on DM365 */
829   -static const s8
  829 +static s8
830 830 dm365_queue_tc_mapping[][2] = {
831 831 /* {event queue no, TC no} */
832 832 {0, 0},
... ... @@ -836,7 +836,7 @@
836 836 {-1, -1},
837 837 };
838 838  
839   -static const s8
  839 +static s8
840 840 dm365_queue_priority_mapping[][2] = {
841 841 /* {event queue no, Priority} */
842 842 {0, 7},
arch/arm/mach-davinci/dm644x.c
... ... @@ -497,7 +497,7 @@
497 497  
498 498 /*----------------------------------------------------------------------*/
499 499  
500   -static const s8
  500 +static s8
501 501 queue_tc_mapping[][2] = {
502 502 /* {event queue no, TC no} */
503 503 {0, 0},
... ... @@ -505,7 +505,7 @@
505 505 {-1, -1},
506 506 };
507 507  
508   -static const s8
  508 +static s8
509 509 queue_priority_mapping[][2] = {
510 510 /* {event queue no, Priority} */
511 511 {0, 3},
arch/arm/mach-davinci/dm646x.c
... ... @@ -531,7 +531,7 @@
531 531 /*----------------------------------------------------------------------*/
532 532  
533 533 /* Four Transfer Controllers on DM646x */
534   -static const s8
  534 +static s8
535 535 dm646x_queue_tc_mapping[][2] = {
536 536 /* {event queue no, TC no} */
537 537 {0, 0},
... ... @@ -541,7 +541,7 @@
541 541 {-1, -1},
542 542 };
543 543  
544   -static const s8
  544 +static s8
545 545 dm646x_queue_priority_mapping[][2] = {
546 546 /* {event queue no, Priority} */
547 547 {0, 4},
include/linux/platform_data/edma.h
... ... @@ -175,8 +175,8 @@
175 175 /* Resource reservation for other cores */
176 176 struct edma_rsv_info *rsv;
177 177  
178   - const s8 (*queue_tc_mapping)[2];
179   - const s8 (*queue_priority_mapping)[2];
  178 + s8 (*queue_tc_mapping)[2];
  179 + s8 (*queue_priority_mapping)[2];
180 180 };
181 181  
182 182 #endif