aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <Guangyu.Chen@freescale.com>2014-04-08 06:34:56 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:18 -0400
commit91b488d016766c6322ea09d1872cdeb0c8dfddaa (patch)
tree0afd607463141ba3ecec8307c899b4146199d0ad
parentcf0e709ba674b3f82b6b5ee5c3bd5b3534c8b6b6 (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.txt6
-rw-r--r--drivers/dma/imx-sdma.c86
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 {
322enum sdma_devtype { 325enum 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
327struct sdma_engine { 331struct 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);
358static const struct of_device_id sdma_dt_ids[] = { 365static 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};
363MODULE_DEVICE_TABLE(of, sdma_dt_ids); 371MODULE_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
1379static 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, &reg);
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
1443out:
1444 if (!IS_ERR(gpr_np))
1445 of_node_put(gpr_np);
1446
1447 return ret;
1448}
1449
1369static int __init sdma_get_firmware(struct sdma_engine *sdma, 1450static 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