diff options
Diffstat (limited to 'arch/arm/common/edma.c')
-rw-r--r-- | arch/arm/common/edma.c | 197 |
1 files changed, 96 insertions, 101 deletions
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 5339009b3c0c..485be42519b9 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 |
@@ -233,7 +239,6 @@ struct edma { | |||
233 | unsigned num_region; | 239 | unsigned num_region; |
234 | unsigned num_slots; | 240 | unsigned num_slots; |
235 | unsigned num_tc; | 241 | unsigned num_tc; |
236 | unsigned num_cc; | ||
237 | enum dma_event_q default_queue; | 242 | enum dma_event_q default_queue; |
238 | 243 | ||
239 | /* list of channels with no even trigger; terminated by "-1" */ | 244 | /* list of channels with no even trigger; terminated by "-1" */ |
@@ -290,12 +295,6 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no, | |||
290 | ~(0x7 << bit), queue_no << bit); | 295 | ~(0x7 << bit), queue_no << bit); |
291 | } | 296 | } |
292 | 297 | ||
293 | static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no) | ||
294 | { | ||
295 | int bit = queue_no * 4; | ||
296 | edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit)); | ||
297 | } | ||
298 | |||
299 | static void __init assign_priority_to_queue(unsigned ctlr, int queue_no, | 298 | static void __init assign_priority_to_queue(unsigned ctlr, int queue_no, |
300 | int priority) | 299 | int priority) |
301 | { | 300 | { |
@@ -994,29 +993,23 @@ void edma_set_dest(unsigned slot, dma_addr_t dest_port, | |||
994 | EXPORT_SYMBOL(edma_set_dest); | 993 | EXPORT_SYMBOL(edma_set_dest); |
995 | 994 | ||
996 | /** | 995 | /** |
997 | * edma_get_position - returns the current transfer points | 996 | * edma_get_position - returns the current transfer point |
998 | * @slot: parameter RAM slot being examined | 997 | * @slot: parameter RAM slot being examined |
999 | * @src: pointer to source port position | 998 | * @dst: true selects the dest position, false the source |
1000 | * @dst: pointer to destination port position | ||
1001 | * | 999 | * |
1002 | * Returns current source and destination addresses for a particular | 1000 | * Returns the position of the current active slot |
1003 | * parameter RAM slot. Its channel should not be active when this is called. | ||
1004 | */ | 1001 | */ |
1005 | void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst) | 1002 | dma_addr_t edma_get_position(unsigned slot, bool dst) |
1006 | { | 1003 | { |
1007 | struct edmacc_param temp; | 1004 | u32 offs, ctlr = EDMA_CTLR(slot); |
1008 | unsigned ctlr; | ||
1009 | 1005 | ||
1010 | ctlr = EDMA_CTLR(slot); | ||
1011 | slot = EDMA_CHAN_SLOT(slot); | 1006 | slot = EDMA_CHAN_SLOT(slot); |
1012 | 1007 | ||
1013 | edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp); | 1008 | offs = PARM_OFFSET(slot); |
1014 | if (src != NULL) | 1009 | offs += dst ? PARM_DST : PARM_SRC; |
1015 | *src = temp.src; | 1010 | |
1016 | if (dst != NULL) | 1011 | return edma_read(ctlr, offs); |
1017 | *dst = temp.dst; | ||
1018 | } | 1012 | } |
1019 | EXPORT_SYMBOL(edma_get_position); | ||
1020 | 1013 | ||
1021 | /** | 1014 | /** |
1022 | * edma_set_src_index - configure DMA source address indexing | 1015 | * edma_set_src_index - configure DMA source address indexing |
@@ -1421,6 +1414,67 @@ void edma_clear_event(unsigned channel) | |||
1421 | } | 1414 | } |
1422 | EXPORT_SYMBOL(edma_clear_event); | 1415 | EXPORT_SYMBOL(edma_clear_event); |
1423 | 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 | |||
1424 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) | 1478 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) |
1425 | 1479 | ||
1426 | static int edma_xbar_event_map(struct device *dev, struct device_node *node, | 1480 | static int edma_xbar_event_map(struct device *dev, struct device_node *node, |
@@ -1471,65 +1525,16 @@ static int edma_of_parse_dt(struct device *dev, | |||
1471 | struct device_node *node, | 1525 | struct device_node *node, |
1472 | struct edma_soc_info *pdata) | 1526 | struct edma_soc_info *pdata) |
1473 | { | 1527 | { |
1474 | int ret = 0, i; | 1528 | int ret = 0; |
1475 | u32 value; | ||
1476 | struct property *prop; | 1529 | struct property *prop; |
1477 | size_t sz; | 1530 | size_t sz; |
1478 | struct edma_rsv_info *rsv_info; | 1531 | struct edma_rsv_info *rsv_info; |
1479 | s8 (*queue_tc_map)[2], (*queue_priority_map)[2]; | ||
1480 | |||
1481 | memset(pdata, 0, sizeof(struct edma_soc_info)); | ||
1482 | |||
1483 | ret = of_property_read_u32(node, "dma-channels", &value); | ||
1484 | if (ret < 0) | ||
1485 | return ret; | ||
1486 | pdata->n_channel = value; | ||
1487 | |||
1488 | ret = of_property_read_u32(node, "ti,edma-regions", &value); | ||
1489 | if (ret < 0) | ||
1490 | return ret; | ||
1491 | pdata->n_region = value; | ||
1492 | |||
1493 | ret = of_property_read_u32(node, "ti,edma-slots", &value); | ||
1494 | if (ret < 0) | ||
1495 | return ret; | ||
1496 | pdata->n_slot = value; | ||
1497 | |||
1498 | pdata->n_cc = 1; | ||
1499 | 1532 | ||
1500 | rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL); | 1533 | rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL); |
1501 | if (!rsv_info) | 1534 | if (!rsv_info) |
1502 | return -ENOMEM; | 1535 | return -ENOMEM; |
1503 | pdata->rsv = rsv_info; | 1536 | pdata->rsv = rsv_info; |
1504 | 1537 | ||
1505 | queue_tc_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL); | ||
1506 | if (!queue_tc_map) | ||
1507 | return -ENOMEM; | ||
1508 | |||
1509 | for (i = 0; i < 3; i++) { | ||
1510 | queue_tc_map[i][0] = i; | ||
1511 | queue_tc_map[i][1] = i; | ||
1512 | } | ||
1513 | queue_tc_map[i][0] = -1; | ||
1514 | queue_tc_map[i][1] = -1; | ||
1515 | |||
1516 | pdata->queue_tc_mapping = queue_tc_map; | ||
1517 | |||
1518 | queue_priority_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL); | ||
1519 | if (!queue_priority_map) | ||
1520 | return -ENOMEM; | ||
1521 | |||
1522 | for (i = 0; i < 3; i++) { | ||
1523 | queue_priority_map[i][0] = i; | ||
1524 | queue_priority_map[i][1] = i; | ||
1525 | } | ||
1526 | queue_priority_map[i][0] = -1; | ||
1527 | queue_priority_map[i][1] = -1; | ||
1528 | |||
1529 | pdata->queue_priority_mapping = queue_priority_map; | ||
1530 | |||
1531 | pdata->default_queue = 0; | ||
1532 | |||
1533 | prop = of_find_property(node, "ti,edma-xbar-event-map", &sz); | 1538 | prop = of_find_property(node, "ti,edma-xbar-event-map", &sz); |
1534 | if (prop) | 1539 | if (prop) |
1535 | ret = edma_xbar_event_map(dev, node, pdata, sz); | 1540 | ret = edma_xbar_event_map(dev, node, pdata, sz); |
@@ -1556,6 +1561,7 @@ static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev, | |||
1556 | return ERR_PTR(ret); | 1561 | return ERR_PTR(ret); |
1557 | 1562 | ||
1558 | dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap); | 1563 | dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap); |
1564 | dma_cap_set(DMA_CYCLIC, edma_filter_info.dma_cap); | ||
1559 | of_dma_controller_register(dev->of_node, of_dma_simple_xlate, | 1565 | of_dma_controller_register(dev->of_node, of_dma_simple_xlate, |
1560 | &edma_filter_info); | 1566 | &edma_filter_info); |
1561 | 1567 | ||
@@ -1574,7 +1580,6 @@ static int edma_probe(struct platform_device *pdev) | |||
1574 | struct edma_soc_info **info = pdev->dev.platform_data; | 1580 | struct edma_soc_info **info = pdev->dev.platform_data; |
1575 | struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL}; | 1581 | struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL}; |
1576 | s8 (*queue_priority_mapping)[2]; | 1582 | s8 (*queue_priority_mapping)[2]; |
1577 | s8 (*queue_tc_mapping)[2]; | ||
1578 | int i, j, off, ln, found = 0; | 1583 | int i, j, off, ln, found = 0; |
1579 | int status = -1; | 1584 | int status = -1; |
1580 | const s16 (*rsv_chans)[2]; | 1585 | const s16 (*rsv_chans)[2]; |
@@ -1585,7 +1590,6 @@ static int edma_probe(struct platform_device *pdev) | |||
1585 | struct resource *r[EDMA_MAX_CC] = {NULL}; | 1590 | struct resource *r[EDMA_MAX_CC] = {NULL}; |
1586 | struct resource res[EDMA_MAX_CC]; | 1591 | struct resource res[EDMA_MAX_CC]; |
1587 | char res_name[10]; | 1592 | char res_name[10]; |
1588 | char irq_name[10]; | ||
1589 | struct device_node *node = pdev->dev.of_node; | 1593 | struct device_node *node = pdev->dev.of_node; |
1590 | struct device *dev = &pdev->dev; | 1594 | struct device *dev = &pdev->dev; |
1591 | int ret; | 1595 | int ret; |
@@ -1650,12 +1654,10 @@ static int edma_probe(struct platform_device *pdev) | |||
1650 | if (!edma_cc[j]) | 1654 | if (!edma_cc[j]) |
1651 | return -ENOMEM; | 1655 | return -ENOMEM; |
1652 | 1656 | ||
1653 | edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel, | 1657 | /* Get eDMA3 configuration from IP */ |
1654 | EDMA_MAX_DMACH); | 1658 | ret = edma_setup_from_hw(dev, info[j], edma_cc[j]); |
1655 | edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot, | 1659 | if (ret) |
1656 | EDMA_MAX_PARAMENTRY); | 1660 | return ret; |
1657 | edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc, | ||
1658 | EDMA_MAX_CC); | ||
1659 | 1661 | ||
1660 | edma_cc[j]->default_queue = info[j]->default_queue; | 1662 | edma_cc[j]->default_queue = info[j]->default_queue; |
1661 | 1663 | ||
@@ -1707,14 +1709,21 @@ static int edma_probe(struct platform_device *pdev) | |||
1707 | 1709 | ||
1708 | if (node) { | 1710 | if (node) { |
1709 | irq[j] = irq_of_parse_and_map(node, 0); | 1711 | irq[j] = irq_of_parse_and_map(node, 0); |
1712 | err_irq[j] = irq_of_parse_and_map(node, 2); | ||
1710 | } else { | 1713 | } else { |
1714 | char irq_name[10]; | ||
1715 | |||
1711 | sprintf(irq_name, "edma%d", j); | 1716 | sprintf(irq_name, "edma%d", j); |
1712 | irq[j] = platform_get_irq_byname(pdev, irq_name); | 1717 | irq[j] = platform_get_irq_byname(pdev, irq_name); |
1718 | |||
1719 | sprintf(irq_name, "edma%d_err", j); | ||
1720 | err_irq[j] = platform_get_irq_byname(pdev, irq_name); | ||
1713 | } | 1721 | } |
1714 | edma_cc[j]->irq_res_start = irq[j]; | 1722 | edma_cc[j]->irq_res_start = irq[j]; |
1715 | status = devm_request_irq(&pdev->dev, irq[j], | 1723 | edma_cc[j]->irq_res_end = err_irq[j]; |
1716 | dma_irq_handler, 0, "edma", | 1724 | |
1717 | &pdev->dev); | 1725 | status = devm_request_irq(dev, irq[j], dma_irq_handler, 0, |
1726 | "edma", dev); | ||
1718 | if (status < 0) { | 1727 | if (status < 0) { |
1719 | dev_dbg(&pdev->dev, | 1728 | dev_dbg(&pdev->dev, |
1720 | "devm_request_irq %d failed --> %d\n", | 1729 | "devm_request_irq %d failed --> %d\n", |
@@ -1722,16 +1731,8 @@ static int edma_probe(struct platform_device *pdev) | |||
1722 | return status; | 1731 | return status; |
1723 | } | 1732 | } |
1724 | 1733 | ||
1725 | if (node) { | 1734 | status = devm_request_irq(dev, err_irq[j], dma_ccerr_handler, 0, |
1726 | err_irq[j] = irq_of_parse_and_map(node, 2); | 1735 | "edma_error", dev); |
1727 | } else { | ||
1728 | sprintf(irq_name, "edma%d_err", j); | ||
1729 | err_irq[j] = platform_get_irq_byname(pdev, irq_name); | ||
1730 | } | ||
1731 | edma_cc[j]->irq_res_end = err_irq[j]; | ||
1732 | status = devm_request_irq(&pdev->dev, err_irq[j], | ||
1733 | dma_ccerr_handler, 0, | ||
1734 | "edma_error", &pdev->dev); | ||
1735 | if (status < 0) { | 1736 | if (status < 0) { |
1736 | dev_dbg(&pdev->dev, | 1737 | dev_dbg(&pdev->dev, |
1737 | "devm_request_irq %d failed --> %d\n", | 1738 | "devm_request_irq %d failed --> %d\n", |
@@ -1742,14 +1743,8 @@ static int edma_probe(struct platform_device *pdev) | |||
1742 | for (i = 0; i < edma_cc[j]->num_channels; i++) | 1743 | for (i = 0; i < edma_cc[j]->num_channels; i++) |
1743 | map_dmach_queue(j, i, info[j]->default_queue); | 1744 | map_dmach_queue(j, i, info[j]->default_queue); |
1744 | 1745 | ||
1745 | queue_tc_mapping = info[j]->queue_tc_mapping; | ||
1746 | queue_priority_mapping = info[j]->queue_priority_mapping; | 1746 | queue_priority_mapping = info[j]->queue_priority_mapping; |
1747 | 1747 | ||
1748 | /* Event queue to TC mapping */ | ||
1749 | for (i = 0; queue_tc_mapping[i][0] != -1; i++) | ||
1750 | map_queue_tc(j, queue_tc_mapping[i][0], | ||
1751 | queue_tc_mapping[i][1]); | ||
1752 | |||
1753 | /* Event queue priority mapping */ | 1748 | /* Event queue priority mapping */ |
1754 | for (i = 0; queue_priority_mapping[i][0] != -1; i++) | 1749 | for (i = 0; queue_priority_mapping[i][0] != -1; i++) |
1755 | assign_priority_to_queue(j, | 1750 | assign_priority_to_queue(j, |
@@ -1762,7 +1757,7 @@ static int edma_probe(struct platform_device *pdev) | |||
1762 | if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST) | 1757 | if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST) |
1763 | map_dmach_param(j); | 1758 | map_dmach_param(j); |
1764 | 1759 | ||
1765 | for (i = 0; i < info[j]->n_region; i++) { | 1760 | for (i = 0; i < edma_cc[j]->num_region; i++) { |
1766 | edma_write_array2(j, EDMA_DRAE, i, 0, 0x0); | 1761 | edma_write_array2(j, EDMA_DRAE, i, 0, 0x0); |
1767 | edma_write_array2(j, EDMA_DRAE, i, 1, 0x0); | 1762 | edma_write_array2(j, EDMA_DRAE, i, 1, 0x0); |
1768 | edma_write_array(j, EDMA_QRAE, i, 0x0); | 1763 | edma_write_array(j, EDMA_QRAE, i, 0x0); |