hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/bus/imx-weim.c
....@@ -19,6 +19,8 @@
1919 unsigned int cs_count;
2020 unsigned int cs_regs_count;
2121 unsigned int cs_stride;
22
+ unsigned int wcr_offset;
23
+ unsigned int wcr_bcm;
2224 };
2325
2426 static const struct imx_weim_devtype imx1_weim_devtype = {
....@@ -37,6 +39,8 @@
3739 .cs_count = 4,
3840 .cs_regs_count = 6,
3941 .cs_stride = 0x18,
42
+ .wcr_offset = 0x90,
43
+ .wcr_bcm = BIT(0),
4044 };
4145
4246 static const struct imx_weim_devtype imx51_weim_devtype = {
....@@ -46,6 +50,17 @@
4650 };
4751
4852 #define MAX_CS_REGS_COUNT 6
53
+#define MAX_CS_COUNT 6
54
+#define OF_REG_SIZE 3
55
+
56
+struct cs_timing {
57
+ bool is_applied;
58
+ u32 regs[MAX_CS_REGS_COUNT];
59
+};
60
+
61
+struct cs_timing_state {
62
+ struct cs_timing cs[MAX_CS_COUNT];
63
+};
4964
5065 static const struct of_device_id weim_id_table[] = {
5166 /* i.MX1/21 */
....@@ -61,7 +76,7 @@
6176 };
6277 MODULE_DEVICE_TABLE(of, weim_id_table);
6378
64
-static int __init imx_weim_gpr_setup(struct platform_device *pdev)
79
+static int imx_weim_gpr_setup(struct platform_device *pdev)
6580 {
6681 struct device_node *np = pdev->dev.of_node;
6782 struct property *prop;
....@@ -111,21 +126,19 @@
111126 }
112127
113128 /* Parse and set the timing for this device. */
114
-static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
115
- const struct imx_weim_devtype *devtype)
129
+static int weim_timing_setup(struct device *dev,
130
+ struct device_node *np, void __iomem *base,
131
+ const struct imx_weim_devtype *devtype,
132
+ struct cs_timing_state *ts)
116133 {
117134 u32 cs_idx, value[MAX_CS_REGS_COUNT];
118135 int i, ret;
136
+ int reg_idx, num_regs;
137
+ struct cs_timing *cst;
119138
120139 if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
121140 return -EINVAL;
122
-
123
- /* get the CS index from this child node's "reg" property. */
124
- ret = of_property_read_u32(np, "reg", &cs_idx);
125
- if (ret)
126
- return ret;
127
-
128
- if (cs_idx >= devtype->cs_count)
141
+ if (WARN_ON(devtype->cs_count > MAX_CS_COUNT))
129142 return -EINVAL;
130143
131144 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
....@@ -133,21 +146,56 @@
133146 if (ret)
134147 return ret;
135148
136
- /* set the timing for WEIM */
137
- for (i = 0; i < devtype->cs_regs_count; i++)
138
- writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
149
+ /*
150
+ * the child node's "reg" property may contain multiple address ranges,
151
+ * extract the chip select for each.
152
+ */
153
+ num_regs = of_property_count_elems_of_size(np, "reg", OF_REG_SIZE);
154
+ if (num_regs < 0)
155
+ return num_regs;
156
+ if (!num_regs)
157
+ return -EINVAL;
158
+ for (reg_idx = 0; reg_idx < num_regs; reg_idx++) {
159
+ /* get the CS index from this child node's "reg" property. */
160
+ ret = of_property_read_u32_index(np, "reg",
161
+ reg_idx * OF_REG_SIZE, &cs_idx);
162
+ if (ret)
163
+ break;
164
+
165
+ if (cs_idx >= devtype->cs_count)
166
+ return -EINVAL;
167
+
168
+ /* prevent re-configuring a CS that's already been configured */
169
+ cst = &ts->cs[cs_idx];
170
+ if (cst->is_applied && memcmp(value, cst->regs,
171
+ devtype->cs_regs_count * sizeof(u32))) {
172
+ dev_err(dev, "fsl,weim-cs-timing conflict on %pOF", np);
173
+ return -EINVAL;
174
+ }
175
+
176
+ /* set the timing for WEIM */
177
+ for (i = 0; i < devtype->cs_regs_count; i++)
178
+ writel(value[i],
179
+ base + cs_idx * devtype->cs_stride + i * 4);
180
+ if (!cst->is_applied) {
181
+ cst->is_applied = true;
182
+ memcpy(cst->regs, value,
183
+ devtype->cs_regs_count * sizeof(u32));
184
+ }
185
+ }
139186
140187 return 0;
141188 }
142189
143
-static int __init weim_parse_dt(struct platform_device *pdev,
144
- void __iomem *base)
190
+static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
145191 {
146192 const struct of_device_id *of_id = of_match_device(weim_id_table,
147193 &pdev->dev);
148194 const struct imx_weim_devtype *devtype = of_id->data;
195
+ int ret = 0, have_child = 0;
149196 struct device_node *child;
150
- int ret, have_child = 0;
197
+ struct cs_timing_state ts = {};
198
+ u32 reg;
151199
152200 if (devtype == &imx50_weim_devtype) {
153201 ret = imx_weim_gpr_setup(pdev);
....@@ -155,11 +203,19 @@
155203 return ret;
156204 }
157205
158
- for_each_available_child_of_node(pdev->dev.of_node, child) {
159
- if (!child->name)
160
- continue;
206
+ if (of_property_read_bool(pdev->dev.of_node, "fsl,burst-clk-enable")) {
207
+ if (devtype->wcr_bcm) {
208
+ reg = readl(base + devtype->wcr_offset);
209
+ writel(reg | devtype->wcr_bcm,
210
+ base + devtype->wcr_offset);
211
+ } else {
212
+ dev_err(&pdev->dev, "burst clk mode not supported.\n");
213
+ return -EINVAL;
214
+ }
215
+ }
161216
162
- ret = weim_timing_setup(child, base, devtype);
217
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
218
+ ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
163219 if (ret)
164220 dev_warn(&pdev->dev, "%pOF set timing failed.\n",
165221 child);
....@@ -176,7 +232,7 @@
176232 return ret;
177233 }
178234
179
-static int __init weim_probe(struct platform_device *pdev)
235
+static int weim_probe(struct platform_device *pdev)
180236 {
181237 struct resource *res;
182238 struct clk *clk;
....@@ -213,8 +269,9 @@
213269 .name = "imx-weim",
214270 .of_match_table = weim_id_table,
215271 },
272
+ .probe = weim_probe,
216273 };
217
-module_platform_driver_probe(weim_driver, weim_probe);
274
+module_platform_driver(weim_driver);
218275
219276 MODULE_AUTHOR("Freescale Semiconductor Inc.");
220277 MODULE_DESCRIPTION("i.MX EIM Controller Driver");