aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/imx-weim.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 3ef58c8dbf11..f8ee13c7bf7b 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -11,6 +11,9 @@
11#include <linux/clk.h> 11#include <linux/clk.h>
12#include <linux/io.h> 12#include <linux/io.h>
13#include <linux/of_device.h> 13#include <linux/of_device.h>
14#include <linux/mfd/syscon.h>
15#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
16#include <linux/regmap.h>
14 17
15struct imx_weim_devtype { 18struct imx_weim_devtype {
16 unsigned int cs_count; 19 unsigned int cs_count;
@@ -56,6 +59,55 @@ static const struct of_device_id weim_id_table[] = {
56}; 59};
57MODULE_DEVICE_TABLE(of, weim_id_table); 60MODULE_DEVICE_TABLE(of, weim_id_table);
58 61
62static int __init imx_weim_gpr_setup(struct platform_device *pdev)
63{
64 struct device_node *np = pdev->dev.of_node;
65 struct property *prop;
66 const __be32 *p;
67 struct regmap *gpr;
68 u32 gprvals[4] = {
69 05, /* CS0(128M) CS1(0M) CS2(0M) CS3(0M) */
70 033, /* CS0(64M) CS1(64M) CS2(0M) CS3(0M) */
71 0113, /* CS0(64M) CS1(32M) CS2(32M) CS3(0M) */
72 01111, /* CS0(32M) CS1(32M) CS2(32M) CS3(32M) */
73 };
74 u32 gprval = 0;
75 u32 val;
76 int cs = 0;
77 int i = 0;
78
79 gpr = syscon_regmap_lookup_by_phandle(np, "fsl,weim-cs-gpr");
80 if (IS_ERR(gpr)) {
81 dev_dbg(&pdev->dev, "failed to find weim-cs-gpr\n");
82 return 0;
83 }
84
85 of_property_for_each_u32(np, "ranges", prop, p, val) {
86 if (i % 4 == 0) {
87 cs = val;
88 } else if (i % 4 == 3 && val) {
89 val = (val / SZ_32M) | 1;
90 gprval |= val << cs * 3;
91 }
92 i++;
93 }
94
95 if (i == 0 || i % 4)
96 goto err;
97
98 for (i = 0; i < ARRAY_SIZE(gprvals); i++) {
99 if (gprval == gprvals[i]) {
100 /* Found it. Set up IOMUXC_GPR1[11:0] with it. */
101 regmap_update_bits(gpr, IOMUXC_GPR1, 0xfff, gprval);
102 return 0;
103 }
104 }
105
106err:
107 dev_err(&pdev->dev, "Invalid 'ranges' configuration\n");
108 return -EINVAL;
109}
110
59/* Parse and set the timing for this device. */ 111/* Parse and set the timing for this device. */
60static int __init weim_timing_setup(struct device_node *np, void __iomem *base, 112static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
61 const struct imx_weim_devtype *devtype) 113 const struct imx_weim_devtype *devtype)
@@ -92,6 +144,12 @@ static int __init weim_parse_dt(struct platform_device *pdev,
92 struct device_node *child; 144 struct device_node *child;
93 int ret; 145 int ret;
94 146
147 if (devtype == &imx50_weim_devtype) {
148 ret = imx_weim_gpr_setup(pdev);
149 if (ret)
150 return ret;
151 }
152
95 for_each_child_of_node(pdev->dev.of_node, child) { 153 for_each_child_of_node(pdev->dev.of_node, child) {
96 if (!child->name) 154 if (!child->name)
97 continue; 155 continue;