aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorMatt Porter <mporter@ti.com>2013-06-20 17:06:38 -0400
committerSekhar Nori <nsekhar@ti.com>2013-06-24 04:38:26 -0400
commit6cba4355066bda19f14d4da66b8abbca0ffdfd59 (patch)
tree0c9fea0669bf397c8b22dcbcff1b567817bf9050 /arch/arm/common
parentbf3156dde3b6718e843152e826a493f80b973655 (diff)
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>
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/edma.c186
1 files changed, 173 insertions, 13 deletions
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index 7658874cc3d5..5183a310657c 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -25,6 +25,13 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/slab.h> 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#include <linux/platform_data/edma.h> 36#include <linux/platform_data/edma.h>
30 37
@@ -1369,13 +1376,110 @@ void edma_clear_event(unsigned channel)
1369} 1376}
1370EXPORT_SYMBOL(edma_clear_event); 1377EXPORT_SYMBOL(edma_clear_event);
1371 1378
1372/*-----------------------------------------------------------------------*/ 1379#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)
1380
1381static int edma_of_parse_dt(struct device *dev,
1382 struct device_node *node,
1383 struct edma_soc_info *pdata)
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;
1373 1441
1374static int __init edma_probe(struct platform_device *pdev) 1442 return ret;
1443}
1444
1445static struct of_dma_filter_info edma_filter_info = {
1446 .filter_fn = edma_filter_fn,
1447};
1448
1449static 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
1470static 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
1477static int edma_probe(struct platform_device *pdev)
1375{ 1478{
1376 struct edma_soc_info **info = pdev->dev.platform_data; 1479 struct edma_soc_info **info = pdev->dev.platform_data;
1377 const s8 (*queue_priority_mapping)[2]; 1480 struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL};
1378 const s8 (*queue_tc_mapping)[2]; 1481 s8 (*queue_priority_mapping)[2];
1482 s8 (*queue_tc_mapping)[2];
1379 int i, j, off, ln, found = 0; 1483 int i, j, off, ln, found = 0;
1380 int status = -1; 1484 int status = -1;
1381 const s16 (*rsv_chans)[2]; 1485 const s16 (*rsv_chans)[2];
@@ -1383,17 +1487,56 @@ static int __init edma_probe(struct platform_device *pdev)
1383 int irq[EDMA_MAX_CC] = {0, 0}; 1487 int irq[EDMA_MAX_CC] = {0, 0};
1384 int err_irq[EDMA_MAX_CC] = {0, 0}; 1488 int err_irq[EDMA_MAX_CC] = {0, 0};
1385 struct resource *r[EDMA_MAX_CC] = {NULL}; 1489 struct resource *r[EDMA_MAX_CC] = {NULL};
1490 struct resource res[EDMA_MAX_CC];
1386 char res_name[10]; 1491 char res_name[10];
1387 char irq_name[10]; 1492 char irq_name[10];
1493 struct device_node *node = pdev->dev.of_node;
1494 struct device *dev = &pdev->dev;
1495 int ret;
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 }
1388 1512
1389 if (!info) 1513 if (!info)
1390 return -ENODEV; 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 for (j = 0; j < EDMA_MAX_CC; j++) { 1523 for (j = 0; j < EDMA_MAX_CC; j++) {
1393 sprintf(res_name, "edma_cc%d", j); 1524 if (!info[j]) {
1394 r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM, 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 res_name); 1537 res_name);
1396 if (!r[j] || !info[j]) { 1538 }
1539 if (!r[j]) {
1397 if (found) 1540 if (found)
1398 break; 1541 break;
1399 else 1542 else
@@ -1440,7 +1583,7 @@ static int __init edma_probe(struct platform_device *pdev)
1440 off = rsv_chans[i][0]; 1583 off = rsv_chans[i][0];
1441 ln = rsv_chans[i][1]; 1584 ln = rsv_chans[i][1];
1442 clear_bits(off, ln, 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 @@ static int __init edma_probe(struct platform_device *pdev)
1456 } 1599 }
1457 } 1600 }
1458 1601
1459 sprintf(irq_name, "edma%d", j); 1602
1460 irq[j] = platform_get_irq_byname(pdev, irq_name); 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 edma_cc[j]->irq_res_start = irq[j]; 1609 edma_cc[j]->irq_res_start = irq[j];
1462 status = devm_request_irq(&pdev->dev, irq[j], 1610 status = devm_request_irq(&pdev->dev, irq[j],
1463 dma_irq_handler, 0, "edma", 1611 dma_irq_handler, 0, "edma",
@@ -1469,8 +1617,12 @@ static int __init edma_probe(struct platform_device *pdev)
1469 return status; 1617 return status;
1470 } 1618 }
1471 1619
1472 sprintf(irq_name, "edma%d_err", j); 1620 if (node) {
1473 err_irq[j] = platform_get_irq_byname(pdev, irq_name); 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 edma_cc[j]->irq_res_end = err_irq[j]; 1626 edma_cc[j]->irq_res_end = err_irq[j];
1475 status = devm_request_irq(&pdev->dev, err_irq[j], 1627 status = devm_request_irq(&pdev->dev, err_irq[j],
1476 dma_ccerr_handler, 0, 1628 dma_ccerr_handler, 0,
@@ -1516,9 +1668,17 @@ static int __init edma_probe(struct platform_device *pdev)
1516 return 0; 1668 return 0;
1517} 1669}
1518 1670
1671static const struct of_device_id edma_of_ids[] = {
1672 { .compatible = "ti,edma3", },
1673 {}
1674};
1519 1675
1520static struct platform_driver edma_driver = { 1676static 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
1524static int __init edma_init(void) 1684static int __init edma_init(void)