aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Porter <mporter@ti.com>2013-06-20 17:06:39 -0400
committerSekhar Nori <nsekhar@ti.com>2013-06-24 04:38:34 -0400
commit2646a0e52b65a5ea3d108794611f95df1a6cb409 (patch)
tree172e60e26d8698bccc28f0f73d03c4969c775e0e
parent6cba4355066bda19f14d4da66b8abbca0ffdfd59 (diff)
ARM: edma: Add EDMA crossbar event mux support
EDMA supports a cross bar which provides ability to mux additional events into physical channels present in the channel controller. This is required when the number of events present in the system are more than number of available physical channels. Changes by Joel: * Split EDMA xbar support out of original EDMA DT parsing patch to keep it easier for review. * Rewrite shift and offset calculation. Suggested-by: Sekhar Nori <nsekhar@ti.com> Suggested by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Joel A Fernandes <joelagnel@ti.com> Acked-by: Arnd Bergmann <arnd@arndb.de> [nsekhar@ti.com: fix checkpatch errors and a minor coding improvement] Signed-off-by: Sekhar Nori <nsekhar@ti.com>
-rw-r--r--arch/arm/common/edma.c78
-rw-r--r--include/linux/platform_data/edma.h1
2 files changed, 79 insertions, 0 deletions
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index 5183a310657c..a432e6c1dac1 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -1378,12 +1378,76 @@ EXPORT_SYMBOL(edma_clear_event);
1378 1378
1379#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) 1379#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)
1380 1380
1381static int edma_of_read_u32_to_s16_array(const struct device_node *np,
1382 const char *propname, s16 *out_values,
1383 size_t sz)
1384{
1385 int ret;
1386
1387 ret = of_property_read_u16_array(np, propname, out_values, sz);
1388 if (ret)
1389 return ret;
1390
1391 /* Terminate it */
1392 *out_values++ = -1;
1393 *out_values++ = -1;
1394
1395 return 0;
1396}
1397
1398static int edma_xbar_event_map(struct device *dev,
1399 struct device_node *node,
1400 struct edma_soc_info *pdata, int len)
1401{
1402 int ret, i;
1403 struct resource res;
1404 void __iomem *xbar;
1405 const s16 (*xbar_chans)[2];
1406 u32 shift, offset, mux;
1407
1408 xbar_chans = devm_kzalloc(dev,
1409 len/sizeof(s16) + 2*sizeof(s16),
1410 GFP_KERNEL);
1411 if (!xbar_chans)
1412 return -ENOMEM;
1413
1414 ret = of_address_to_resource(node, 1, &res);
1415 if (ret)
1416 return -EIO;
1417
1418 xbar = devm_ioremap(dev, res.start, resource_size(&res));
1419 if (!xbar)
1420 return -ENOMEM;
1421
1422 ret = edma_of_read_u32_to_s16_array(node,
1423 "ti,edma-xbar-event-map",
1424 (s16 *)xbar_chans,
1425 len/sizeof(u32));
1426 if (ret)
1427 return -EIO;
1428
1429 for (i = 0; xbar_chans[i][0] != -1; i++) {
1430 shift = (xbar_chans[i][1] & 0x03) << 3;
1431 offset = xbar_chans[i][1] & 0xfffffffc;
1432 mux = readl(xbar + offset);
1433 mux &= ~(0xff << shift);
1434 mux |= xbar_chans[i][0] << shift;
1435 writel(mux, (xbar + offset));
1436 }
1437
1438 pdata->xbar_chans = xbar_chans;
1439
1440 return 0;
1441}
1442
1381static int edma_of_parse_dt(struct device *dev, 1443static int edma_of_parse_dt(struct device *dev,
1382 struct device_node *node, 1444 struct device_node *node,
1383 struct edma_soc_info *pdata) 1445 struct edma_soc_info *pdata)
1384{ 1446{
1385 int ret = 0, i; 1447 int ret = 0, i;
1386 u32 value; 1448 u32 value;
1449 struct property *prop;
1450 size_t sz;
1387 struct edma_rsv_info *rsv_info; 1451 struct edma_rsv_info *rsv_info;
1388 s8 (*queue_tc_map)[2], (*queue_priority_map)[2]; 1452 s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
1389 1453
@@ -1439,6 +1503,10 @@ static int edma_of_parse_dt(struct device *dev,
1439 1503
1440 pdata->default_queue = 0; 1504 pdata->default_queue = 0;
1441 1505
1506 prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
1507 if (prop)
1508 ret = edma_xbar_event_map(dev, node, pdata, sz);
1509
1442 return ret; 1510 return ret;
1443} 1511}
1444 1512
@@ -1484,6 +1552,7 @@ static int edma_probe(struct platform_device *pdev)
1484 int status = -1; 1552 int status = -1;
1485 const s16 (*rsv_chans)[2]; 1553 const s16 (*rsv_chans)[2];
1486 const s16 (*rsv_slots)[2]; 1554 const s16 (*rsv_slots)[2];
1555 const s16 (*xbar_chans)[2];
1487 int irq[EDMA_MAX_CC] = {0, 0}; 1556 int irq[EDMA_MAX_CC] = {0, 0};
1488 int err_irq[EDMA_MAX_CC] = {0, 0}; 1557 int err_irq[EDMA_MAX_CC] = {0, 0};
1489 struct resource *r[EDMA_MAX_CC] = {NULL}; 1558 struct resource *r[EDMA_MAX_CC] = {NULL};
@@ -1599,6 +1668,15 @@ static int edma_probe(struct platform_device *pdev)
1599 } 1668 }
1600 } 1669 }
1601 1670
1671 /* Clear the xbar mapped channels in unused list */
1672 xbar_chans = info[j]->xbar_chans;
1673 if (xbar_chans) {
1674 for (i = 0; xbar_chans[i][1] != -1; i++) {
1675 off = xbar_chans[i][1];
1676 clear_bits(off, 1,
1677 edma_cc[j]->edma_unused);
1678 }
1679 }
1602 1680
1603 if (node) { 1681 if (node) {
1604 irq[j] = irq_of_parse_and_map(node, 0); 1682 irq[j] = irq_of_parse_and_map(node, 0);
diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
index 317f2beeaece..57300fd7cc03 100644
--- a/include/linux/platform_data/edma.h
+++ b/include/linux/platform_data/edma.h
@@ -177,6 +177,7 @@ struct edma_soc_info {
177 177
178 s8 (*queue_tc_mapping)[2]; 178 s8 (*queue_tc_mapping)[2];
179 s8 (*queue_priority_mapping)[2]; 179 s8 (*queue_priority_mapping)[2];
180 const s16 (*xbar_chans)[2];
180}; 181};
181 182
182#endif 183#endif