diff options
| -rw-r--r-- | arch/arm/common/edma.c | 186 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/devices-da8xx.c | 8 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/devices-tnetv107x.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/dm355.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/dm365.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/dm644x.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/dm646x.c | 4 | ||||
| -rw-r--r-- | include/linux/platform_data/edma.h | 4 |
8 files changed, 189 insertions, 29 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 | } |
| 1370 | EXPORT_SYMBOL(edma_clear_event); | 1377 | EXPORT_SYMBOL(edma_clear_event); |
| 1371 | 1378 | ||
| 1372 | /*-----------------------------------------------------------------------*/ | 1379 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) |
| 1380 | |||
| 1381 | static 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 | ||
| 1374 | static int __init edma_probe(struct platform_device *pdev) | 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) | ||
| 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); | ||
