diff options
Diffstat (limited to 'drivers/bus')
-rw-r--r-- | drivers/bus/imx-weim.c | 58 |
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 | ||
15 | struct imx_weim_devtype { | 18 | struct 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 | }; |
57 | MODULE_DEVICE_TABLE(of, weim_id_table); | 60 | MODULE_DEVICE_TABLE(of, weim_id_table); |
58 | 61 | ||
62 | static 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 | |||
106 | err: | ||
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. */ |
60 | static int __init weim_timing_setup(struct device_node *np, void __iomem *base, | 112 | static 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; |