diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2014-05-16 08:17:15 -0400 |
---|---|---|
committer | Sekhar Nori <nsekhar@ti.com> | 2014-05-22 05:25:07 -0400 |
commit | 6d10c3950bf4d42a5bd28bfd7572834225acb031 (patch) | |
tree | c73ebf53b4cde0a1bb37160298b68413831db18f /arch/arm/common | |
parent | 643efcff5208b5521060779f769593ca3837887d (diff) |
ARM: edma: Get IP configuration from HW (number of channels, tc, etc)
From CCCFG register of eDMA3 we can get all the needed information for the
driver about the IP:
Number of channels: NUM_DMACH
Number of regions: NUM_REGN
Number of slots (PaRAM sets): NUM_PAENTRY
Number of TC/EQ: NUM_EVQUE
In case when booted with DT or the queue_priority_mapping is not provided
set up a default priority map.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: Joel Fernandes <joelf@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/edma.c | 115 |
1 files changed, 73 insertions, 42 deletions
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 79097d880d50..eeea011480eb 100644 --- a/arch/arm/common/edma.c +++ b/arch/arm/common/edma.c | |||
@@ -102,7 +102,13 @@ | |||
102 | #define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5)) | 102 | #define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5)) |
103 | 103 | ||
104 | #define EDMA_DCHMAP 0x0100 /* 64 registers */ | 104 | #define EDMA_DCHMAP 0x0100 /* 64 registers */ |
105 | #define CHMAP_EXIST BIT(24) | 105 | |
106 | /* CCCFG register */ | ||
107 | #define GET_NUM_DMACH(x) (x & 0x7) /* bits 0-2 */ | ||
108 | #define GET_NUM_PAENTRY(x) ((x & 0x7000) >> 12) /* bits 12-14 */ | ||
109 | #define GET_NUM_EVQUE(x) ((x & 0x70000) >> 16) /* bits 16-18 */ | ||
110 | #define GET_NUM_REGN(x) ((x & 0x300000) >> 20) /* bits 20-21 */ | ||
111 | #define CHMAP_EXIST BIT(24) | ||
106 | 112 | ||
107 | #define EDMA_MAX_DMACH 64 | 113 | #define EDMA_MAX_DMACH 64 |
108 | #define EDMA_MAX_PARAMENTRY 512 | 114 | #define EDMA_MAX_PARAMENTRY 512 |
@@ -1408,6 +1414,67 @@ void edma_clear_event(unsigned channel) | |||
1408 | } | 1414 | } |
1409 | EXPORT_SYMBOL(edma_clear_event); | 1415 | EXPORT_SYMBOL(edma_clear_event); |
1410 | 1416 | ||
1417 | static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata, | ||
1418 | struct edma *edma_cc) | ||
1419 | { | ||
1420 | int i; | ||
1421 | u32 value, cccfg; | ||
1422 | s8 (*queue_priority_map)[2]; | ||
1423 | |||
1424 | /* Decode the eDMA3 configuration from CCCFG register */ | ||
1425 | cccfg = edma_read(0, EDMA_CCCFG); | ||
1426 | |||
1427 | value = GET_NUM_REGN(cccfg); | ||
1428 | edma_cc->num_region = BIT(value); | ||
1429 | |||
1430 | value = GET_NUM_DMACH(cccfg); | ||
1431 | edma_cc->num_channels = BIT(value + 1); | ||
1432 | |||
1433 | value = GET_NUM_PAENTRY(cccfg); | ||
1434 | edma_cc->num_slots = BIT(value + 4); | ||
1435 | |||
1436 | value = GET_NUM_EVQUE(cccfg); | ||
1437 | edma_cc->num_tc = value + 1; | ||
1438 | |||
1439 | dev_dbg(dev, "eDMA3 HW configuration (cccfg: 0x%08x):\n", cccfg); | ||
1440 | dev_dbg(dev, "num_region: %u\n", edma_cc->num_region); | ||
1441 | dev_dbg(dev, "num_channel: %u\n", edma_cc->num_channels); | ||
1442 | dev_dbg(dev, "num_slot: %u\n", edma_cc->num_slots); | ||
1443 | dev_dbg(dev, "num_tc: %u\n", edma_cc->num_tc); | ||
1444 | |||
1445 | /* Nothing need to be done if queue priority is provided */ | ||
1446 | if (pdata->queue_priority_mapping) | ||
1447 | return 0; | ||
1448 | |||
1449 | /* | ||
1450 | * Configure TC/queue priority as follows: | ||
1451 | * Q0 - priority 0 | ||
1452 | * Q1 - priority 1 | ||
1453 | * Q2 - priority 2 | ||
1454 | * ... | ||
1455 | * The meaning of priority numbers: 0 highest priority, 7 lowest | ||
1456 | * priority. So Q0 is the highest priority queue and the last queue has | ||
1457 | * the lowest priority. | ||
1458 | */ | ||
1459 | queue_priority_map = devm_kzalloc(dev, | ||
1460 | (edma_cc->num_tc + 1) * sizeof(s8), | ||
1461 | GFP_KERNEL); | ||
1462 | if (!queue_priority_map) | ||
1463 | return -ENOMEM; | ||
1464 | |||
1465 | for (i = 0; i < edma_cc->num_tc; i++) { | ||
1466 | queue_priority_map[i][0] = i; | ||
1467 | queue_priority_map[i][1] = i; | ||
1468 | } | ||
1469 | queue_priority_map[i][0] = -1; | ||
1470 | queue_priority_map[i][1] = -1; | ||
1471 | |||
1472 | pdata->queue_priority_mapping = queue_priority_map; | ||
1473 | pdata->default_queue = 0; | ||
1474 | |||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1411 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) | 1478 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) |
1412 | 1479 | ||
1413 | static int edma_of_read_u32_to_s16_array(const struct device_node *np, | 1480 | static int edma_of_read_u32_to_s16_array(const struct device_node *np, |
@@ -1476,50 +1543,16 @@ static int edma_of_parse_dt(struct device *dev, | |||
1476 | struct device_node *node, | 1543 | struct device_node *node, |
1477 | struct edma_soc_info *pdata) | 1544 | struct edma_soc_info *pdata) |
1478 | { | 1545 | { |
1479 | int ret = 0, i; | 1546 | int ret = 0; |
1480 | u32 value; | ||
1481 | struct property *prop; | 1547 | struct property *prop; |
1482 | size_t sz; | 1548 | size_t sz; |
1483 | struct edma_rsv_info *rsv_info; | 1549 | struct edma_rsv_info *rsv_info; |
1484 | s8 (*queue_priority_map)[2]; | ||
1485 | |||
1486 | ret = of_property_read_u32(node, "dma-channels", &value); | ||
1487 | if (ret < 0) | ||
1488 | return ret; | ||
1489 | pdata->n_channel = value; | ||
1490 | |||
1491 | ret = of_property_read_u32(node, "ti,edma-regions", &value); | ||
1492 | if (ret < 0) | ||
1493 | return ret; | ||
1494 | pdata->n_region = value; | ||
1495 | |||
1496 | ret = of_property_read_u32(node, "ti,edma-slots", &value); | ||
1497 | if (ret < 0) | ||
1498 | return ret; | ||
1499 | pdata->n_slot = value; | ||
1500 | |||
1501 | pdata->n_tc = 3; | ||
1502 | 1550 | ||
1503 | rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL); | 1551 | rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL); |
1504 | if (!rsv_info) | 1552 | if (!rsv_info) |
1505 | return -ENOMEM; | 1553 | return -ENOMEM; |
1506 | pdata->rsv = rsv_info; | 1554 | pdata->rsv = rsv_info; |
1507 | 1555 | ||
1508 | queue_priority_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL); | ||
1509 | if (!queue_priority_map) | ||
1510 | return -ENOMEM; | ||
1511 | |||
1512 | for (i = 0; i < 3; i++) { | ||
1513 | queue_priority_map[i][0] = i; | ||
1514 | queue_priority_map[i][1] = i; | ||
1515 | } | ||
1516 | queue_priority_map[i][0] = -1; | ||
1517 | queue_priority_map[i][1] = -1; | ||
1518 | |||
1519 | pdata->queue_priority_mapping = queue_priority_map; | ||
1520 | |||
1521 | pdata->default_queue = 0; | ||
1522 | |||
1523 | prop = of_find_property(node, "ti,edma-xbar-event-map", &sz); | 1556 | prop = of_find_property(node, "ti,edma-xbar-event-map", &sz); |
1524 | if (prop) | 1557 | if (prop) |
1525 | ret = edma_xbar_event_map(dev, node, pdata, sz); | 1558 | ret = edma_xbar_event_map(dev, node, pdata, sz); |
@@ -1639,14 +1672,12 @@ static int edma_probe(struct platform_device *pdev) | |||
1639 | if (!edma_cc[j]) | 1672 | if (!edma_cc[j]) |
1640 | return -ENOMEM; | 1673 | return -ENOMEM; |
1641 | 1674 | ||
1642 | edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel, | 1675 | /* Get eDMA3 configuration from IP */ |
1643 | EDMA_MAX_DMACH); | 1676 | ret = edma_setup_from_hw(dev, info[j], edma_cc[j]); |
1644 | edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot, | 1677 | if (ret) |
1645 | EDMA_MAX_PARAMENTRY); | 1678 | return ret; |
1646 | edma_cc[j]->num_tc = info[j]->n_tc; | ||
1647 | 1679 | ||
1648 | edma_cc[j]->default_queue = info[j]->default_queue; | 1680 | edma_cc[j]->default_queue = info[j]->default_queue; |
1649 | edma_cc[j]->num_region = info[j]->n_region; | ||
1650 | 1681 | ||
1651 | dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", | 1682 | dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", |
1652 | edmacc_regs_base[j]); | 1683 | edmacc_regs_base[j]); |