diff options
author | Nicolin Chen <Guangyu.Chen@freescale.com> | 2014-04-08 06:34:56 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:58:18 -0400 |
commit | 91b488d016766c6322ea09d1872cdeb0c8dfddaa (patch) | |
tree | 0afd607463141ba3ecec8307c899b4146199d0ad | |
parent | cf0e709ba674b3f82b6b5ee5c3bd5b3534c8b6b6 (diff) |
ENGR00307635-2 dmaengine: imx-sdma: Add imx6sx platform support
The new Solo X has more requirements for SDMA events. So it creates a event mux
to remap most of event numbers in GPR (General Purpose Register). If we want to
use SDMA support for those module who do not get the even number as default, we
need to configure GPR first.
Thus this patch adds this support of GPR event remapping configuration to the
SDMA driver.
Acked-by: Robin Gong <b38343@freescale.com>
Acked-by: Huang Shijie <b32955@freescale.com>
Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
-rw-r--r-- | Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt | 6 | ||||
-rw-r--r-- | drivers/dma/imx-sdma.c | 86 |
2 files changed, 92 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index c07f61f370d3..62e720065418 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt | |||
@@ -7,6 +7,12 @@ Required properties: | |||
7 | - #dma-cells : Must be <3>. | 7 | - #dma-cells : Must be <3>. |
8 | The first cell specifies the DMA request/event ID. See details below | 8 | The first cell specifies the DMA request/event ID. See details below |
9 | about the second and third cell. | 9 | about the second and third cell. |
10 | - gpr : The phandle to general purpose register node. | ||
11 | - fsl,sdma-event-remap : Register bits of sdma event remap, the format is | ||
12 | <reg shift val>. | ||
13 | reg is the gpr register offset. | ||
14 | shift is the bit offset of event remap. | ||
15 | val is the value of the bit to be set. | ||
10 | - fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM | 16 | - fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM |
11 | scripts firmware | 17 | scripts firmware |
12 | 18 | ||
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 136440db5f8e..973d3048c4cf 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/regmap.h> | ||
28 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
29 | #include <linux/semaphore.h> | 30 | #include <linux/semaphore.h> |
30 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
@@ -40,6 +41,8 @@ | |||
40 | #include <linux/of_dma.h> | 41 | #include <linux/of_dma.h> |
41 | 42 | ||
42 | #include <asm/irq.h> | 43 | #include <asm/irq.h> |
44 | #include <linux/mfd/syscon.h> | ||
45 | #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> | ||
43 | #include <linux/platform_data/dma-imx-sdma.h> | 46 | #include <linux/platform_data/dma-imx-sdma.h> |
44 | #include <linux/platform_data/dma-imx.h> | 47 | #include <linux/platform_data/dma-imx.h> |
45 | 48 | ||
@@ -322,6 +325,7 @@ struct sdma_firmware_header { | |||
322 | enum sdma_devtype { | 325 | enum sdma_devtype { |
323 | IMX31_SDMA, /* runs on i.mx31 */ | 326 | IMX31_SDMA, /* runs on i.mx31 */ |
324 | IMX35_SDMA, /* runs on i.mx35 and later */ | 327 | IMX35_SDMA, /* runs on i.mx35 and later */ |
328 | IMX6SX_SDMA, /* runs on i.mx6sx */ | ||
325 | }; | 329 | }; |
326 | 330 | ||
327 | struct sdma_engine { | 331 | struct sdma_engine { |
@@ -350,6 +354,9 @@ static struct platform_device_id sdma_devtypes[] = { | |||
350 | .name = "imx35-sdma", | 354 | .name = "imx35-sdma", |
351 | .driver_data = IMX35_SDMA, | 355 | .driver_data = IMX35_SDMA, |
352 | }, { | 356 | }, { |
357 | .name = "imx6sx-sdma", | ||
358 | .driver_data = IMX6SX_SDMA, | ||
359 | }, { | ||
353 | /* sentinel */ | 360 | /* sentinel */ |
354 | } | 361 | } |
355 | }; | 362 | }; |
@@ -358,6 +365,7 @@ MODULE_DEVICE_TABLE(platform, sdma_devtypes); | |||
358 | static const struct of_device_id sdma_dt_ids[] = { | 365 | static const struct of_device_id sdma_dt_ids[] = { |
359 | { .compatible = "fsl,imx31-sdma", .data = &sdma_devtypes[IMX31_SDMA], }, | 366 | { .compatible = "fsl,imx31-sdma", .data = &sdma_devtypes[IMX31_SDMA], }, |
360 | { .compatible = "fsl,imx35-sdma", .data = &sdma_devtypes[IMX35_SDMA], }, | 367 | { .compatible = "fsl,imx35-sdma", .data = &sdma_devtypes[IMX35_SDMA], }, |
368 | { .compatible = "fsl,imx6sx-sdma", .data = &sdma_devtypes[IMX6SX_SDMA], }, | ||
361 | { /* sentinel */ } | 369 | { /* sentinel */ } |
362 | }; | 370 | }; |
363 | MODULE_DEVICE_TABLE(of, sdma_dt_ids); | 371 | MODULE_DEVICE_TABLE(of, sdma_dt_ids); |
@@ -1366,6 +1374,79 @@ err_firmware: | |||
1366 | release_firmware(fw); | 1374 | release_firmware(fw); |
1367 | } | 1375 | } |
1368 | 1376 | ||
1377 | #define EVENT_REMAP_CELLS 3 | ||
1378 | |||
1379 | static int __init sdma_event_remap(struct sdma_engine *sdma) | ||
1380 | { | ||
1381 | struct device_node *np = sdma->dev->of_node; | ||
1382 | struct device_node *gpr_np = of_parse_phandle(np, "gpr", 0); | ||
1383 | struct property *event_remap; | ||
1384 | struct regmap *gpr; | ||
1385 | char propname[] = "fsl,sdma-event-remap"; | ||
1386 | u32 reg, val, shift, num_map, i; | ||
1387 | int ret = 0; | ||
1388 | |||
1389 | /* Only apply to imx6sx platform */ | ||
1390 | if (sdma->devtype != IMX6SX_SDMA || IS_ERR(np)) | ||
1391 | goto out; | ||
1392 | |||
1393 | if (IS_ERR(gpr_np)) { | ||
1394 | dev_err(sdma->dev, "failed to get gpr node by phandle\n"); | ||
1395 | ret = PTR_ERR(gpr_np); | ||
1396 | goto out; | ||
1397 | } | ||
1398 | |||
1399 | event_remap = of_find_property(np, propname, NULL); | ||
1400 | num_map = event_remap ? (event_remap->length / sizeof(u32)) : 0; | ||
1401 | if (!num_map) { | ||
1402 | dev_warn(sdma->dev, "no event needs to be remapped\n"); | ||
1403 | goto out; | ||
1404 | } else if (num_map % EVENT_REMAP_CELLS) { | ||
1405 | dev_err(sdma->dev, "the property %s must modulo %d\n", | ||
1406 | propname, EVENT_REMAP_CELLS); | ||
1407 | ret = -EINVAL; | ||
1408 | goto out; | ||
1409 | } | ||
1410 | |||
1411 | gpr = syscon_node_to_regmap(gpr_np); | ||
1412 | if (IS_ERR(gpr)) { | ||
1413 | dev_err(sdma->dev, "failed to get gpr regmap\n"); | ||
1414 | ret = PTR_ERR(gpr); | ||
1415 | goto out; | ||
1416 | } | ||
1417 | |||
1418 | for (i = 0; i < num_map; i += EVENT_REMAP_CELLS) { | ||
1419 | ret = of_property_read_u32_index(np, propname, i, ®); | ||
1420 | if (ret) { | ||
1421 | dev_err(sdma->dev, "failed to read property %s index %d\n", | ||
1422 | propname, i); | ||
1423 | goto out; | ||
1424 | } | ||
1425 | |||
1426 | ret = of_property_read_u32_index(np, propname, i + 1, &shift); | ||
1427 | if (ret) { | ||
1428 | dev_err(sdma->dev, "failed to read property %s index %d\n", | ||
1429 | propname, i + 1); | ||
1430 | goto out; | ||
1431 | } | ||
1432 | |||
1433 | ret = of_property_read_u32_index(np, propname, i + 2, &val); | ||
1434 | if (ret) { | ||
1435 | dev_err(sdma->dev, "failed to read property %s index %d\n", | ||
1436 | propname, i + 2); | ||
1437 | goto out; | ||
1438 | } | ||
1439 | |||
1440 | regmap_update_bits(gpr, reg, BIT(shift), val << shift); | ||
1441 | } | ||
1442 | |||
1443 | out: | ||
1444 | if (!IS_ERR(gpr_np)) | ||
1445 | of_node_put(gpr_np); | ||
1446 | |||
1447 | return ret; | ||
1448 | } | ||
1449 | |||
1369 | static int __init sdma_get_firmware(struct sdma_engine *sdma, | 1450 | static int __init sdma_get_firmware(struct sdma_engine *sdma, |
1370 | const char *fw_name) | 1451 | const char *fw_name) |
1371 | { | 1452 | { |
@@ -1388,6 +1469,7 @@ static int __init sdma_init(struct sdma_engine *sdma) | |||
1388 | sdma->num_events = 32; | 1469 | sdma->num_events = 32; |
1389 | break; | 1470 | break; |
1390 | case IMX35_SDMA: | 1471 | case IMX35_SDMA: |
1472 | case IMX6SX_SDMA: | ||
1391 | sdma->num_events = 48; | 1473 | sdma->num_events = 48; |
1392 | break; | 1474 | break; |
1393 | default: | 1475 | default: |
@@ -1605,6 +1687,10 @@ static int __init sdma_probe(struct platform_device *pdev) | |||
1605 | if (ret) | 1687 | if (ret) |
1606 | goto err_init; | 1688 | goto err_init; |
1607 | 1689 | ||
1690 | ret = sdma_event_remap(sdma); | ||
1691 | if (ret) | ||
1692 | goto err_init; | ||
1693 | |||
1608 | if (pdata && pdata->script_addrs) | 1694 | if (pdata && pdata->script_addrs) |
1609 | sdma_add_scripts(sdma, pdata->script_addrs); | 1695 | sdma_add_scripts(sdma, pdata->script_addrs); |
1610 | 1696 | ||