OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | From 659aa30c59fb188b533a7edcb9bd38ac007a2739 Mon Sep 17 00:00:00 2001 |
2 | From: Yangbo Lu <yangbo.lu@nxp.com> |
||
3 | Date: Wed, 17 Jan 2018 15:35:11 +0800 |
||
4 | Subject: [PATCH 21/30] i2c: support layerscape |
||
5 | |||
6 | This is an integrated patch for layerscape i2c support. |
||
7 | |||
8 | Signed-off-by: Zhang Ying-22455 <ying.zhang22455@nxp.com> |
||
9 | Signed-off-by: Priyanka Jain <Priyanka.Jain@freescale.com> |
||
10 | Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> |
||
11 | --- |
||
12 | drivers/i2c/busses/i2c-imx.c | 195 +++++++++++++++++++++++++++++++++++- |
||
13 | drivers/i2c/muxes/i2c-mux-pca954x.c | 43 ++++++++ |
||
14 | 2 files changed, 237 insertions(+), 1 deletion(-) |
||
15 | |||
16 | --- a/drivers/i2c/busses/i2c-imx.c |
||
17 | +++ b/drivers/i2c/busses/i2c-imx.c |
||
18 | @@ -53,6 +53,11 @@ |
||
19 | #include <linux/pm_runtime.h> |
||
20 | #include <linux/sched.h> |
||
21 | #include <linux/slab.h> |
||
22 | +#include <linux/gpio.h> |
||
23 | +#include <linux/of_address.h> |
||
24 | +#include <linux/of.h> |
||
25 | +#include <linux/of_device.h> |
||
26 | +#include <linux/libata.h> |
||
27 | |||
28 | /* This will be the driver name the kernel reports */ |
||
29 | #define DRIVER_NAME "imx-i2c" |
||
30 | @@ -117,6 +122,54 @@ |
||
31 | |||
32 | #define I2C_PM_TIMEOUT 10 /* ms */ |
||
33 | |||
34 | +enum pinmux_endian_type { |
||
35 | + BIG_ENDIAN, |
||
36 | + LITTLE_ENDIAN, |
||
37 | +}; |
||
38 | + |
||
39 | +struct pinmux_cfg { |
||
40 | + enum pinmux_endian_type endian; /* endian of RCWPMUXCR0 */ |
||
41 | + u32 pmuxcr_offset; |
||
42 | + u32 pmuxcr_set_bit; /* pin mux of RCWPMUXCR0 */ |
||
43 | +}; |
||
44 | + |
||
45 | +static struct pinmux_cfg ls1012a_pinmux_cfg = { |
||
46 | + .endian = BIG_ENDIAN, |
||
47 | + .pmuxcr_offset = 0x430, |
||
48 | + .pmuxcr_set_bit = 0x10, |
||
49 | +}; |
||
50 | + |
||
51 | +static struct pinmux_cfg ls1043a_pinmux_cfg = { |
||
52 | + .endian = BIG_ENDIAN, |
||
53 | + .pmuxcr_offset = 0x40C, |
||
54 | + .pmuxcr_set_bit = 0x10, |
||
55 | +}; |
||
56 | + |
||
57 | +static struct pinmux_cfg ls1046a_pinmux_cfg = { |
||
58 | + .endian = BIG_ENDIAN, |
||
59 | + .pmuxcr_offset = 0x40C, |
||
60 | + .pmuxcr_set_bit = 0x80000000, |
||
61 | +}; |
||
62 | + |
||
63 | +static const struct of_device_id pinmux_of_match[] = { |
||
64 | + { .compatible = "fsl,ls1012a-vf610-i2c", .data = &ls1012a_pinmux_cfg}, |
||
65 | + { .compatible = "fsl,ls1043a-vf610-i2c", .data = &ls1043a_pinmux_cfg}, |
||
66 | + { .compatible = "fsl,ls1046a-vf610-i2c", .data = &ls1046a_pinmux_cfg}, |
||
67 | + {}, |
||
68 | +}; |
||
69 | +MODULE_DEVICE_TABLE(of, pinmux_of_match); |
||
70 | + |
||
71 | +/* The SCFG, Supplemental Configuration Unit, provides SoC specific |
||
72 | + * configuration and status registers for the device. There is a |
||
73 | + * SDHC IO VSEL control register on SCFG for some platforms. It's |
||
74 | + * used to support SDHC IO voltage switching. |
||
75 | + */ |
||
76 | +static const struct of_device_id scfg_device_ids[] = { |
||
77 | + { .compatible = "fsl,ls1012a-scfg", }, |
||
78 | + { .compatible = "fsl,ls1043a-scfg", }, |
||
79 | + { .compatible = "fsl,ls1046a-scfg", }, |
||
80 | + {} |
||
81 | +}; |
||
82 | /* |
||
83 | * sorted list of clock divider, register value pairs |
||
84 | * taken from table 26-5, p.26-9, Freescale i.MX |
||
85 | @@ -210,6 +263,12 @@ struct imx_i2c_struct { |
||
86 | struct pinctrl_state *pinctrl_pins_gpio; |
||
87 | |||
88 | struct imx_i2c_dma *dma; |
||
89 | + int layerscape_bus_recover; |
||
90 | + int gpio; |
||
91 | + int need_set_pmuxcr; |
||
92 | + int pmuxcr_set; |
||
93 | + int pmuxcr_endian; |
||
94 | + void __iomem *pmuxcr_addr; |
||
95 | }; |
||
96 | |||
97 | static const struct imx_i2c_hwdata imx1_i2c_hwdata = { |
||
98 | @@ -878,6 +937,78 @@ static int i2c_imx_read(struct imx_i2c_s |
||
99 | return 0; |
||
100 | } |
||
101 | |||
102 | +/* |
||
103 | + * Based on the I2C specification, if the data line (SDA) is |
||
104 | + * stuck low, the master should send nine * clock pulses. |
||
105 | + * The I2C slave device that held the bus low should release it |
||
106 | + * sometime within * those nine clocks. Due to this erratum, |
||
107 | + * the I2C controller cannot generate nine clock pulses. |
||
108 | + */ |
||
109 | +static int i2c_imx_recovery_for_layerscape(struct imx_i2c_struct *i2c_imx) |
||
110 | +{ |
||
111 | + u32 pmuxcr = 0; |
||
112 | + int ret; |
||
113 | + unsigned int i, temp; |
||
114 | + |
||
115 | + /* configure IICx_SCL/GPIO pin as a GPIO */ |
||
116 | + if (i2c_imx->need_set_pmuxcr == 1) { |
||
117 | + pmuxcr = ioread32be(i2c_imx->pmuxcr_addr); |
||
118 | + if (i2c_imx->pmuxcr_endian == BIG_ENDIAN) |
||
119 | + iowrite32be(i2c_imx->pmuxcr_set|pmuxcr, |
||
120 | + i2c_imx->pmuxcr_addr); |
||
121 | + else |
||
122 | + iowrite32(i2c_imx->pmuxcr_set|pmuxcr, |
||
123 | + i2c_imx->pmuxcr_addr); |
||
124 | + } |
||
125 | + |
||
126 | + ret = gpio_request(i2c_imx->gpio, i2c_imx->adapter.name); |
||
127 | + if (ret) { |
||
128 | + dev_err(&i2c_imx->adapter.dev, |
||
129 | + "can't get gpio: %d\n", ret); |
||
130 | + return ret; |
||
131 | + } |
||
132 | + |
||
133 | + /* Configure GPIO pin as an output and open drain. */ |
||
134 | + gpio_direction_output(i2c_imx->gpio, 1); |
||
135 | + udelay(10); |
||
136 | + |
||
137 | + /* Write data to generate 9 pulses */ |
||
138 | + for (i = 0; i < 9; i++) { |
||
139 | + gpio_set_value(i2c_imx->gpio, 1); |
||
140 | + udelay(10); |
||
141 | + gpio_set_value(i2c_imx->gpio, 0); |
||
142 | + udelay(10); |
||
143 | + } |
||
144 | + /* ensure that the last level sent is always high */ |
||
145 | + gpio_set_value(i2c_imx->gpio, 1); |
||
146 | + |
||
147 | + /* |
||
148 | + * Set I2Cx_IBCR = 0h00 to generate a STOP and then |
||
149 | + * set I2Cx_IBCR = 0h80 to reset |
||
150 | + */ |
||
151 | + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); |
||
152 | + temp &= ~(I2CR_MSTA | I2CR_MTX); |
||
153 | + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); |
||
154 | + |
||
155 | + /* Restore the saved value of the register SCFG_RCWPMUXCR0 */ |
||
156 | + if (i2c_imx->need_set_pmuxcr == 1) { |
||
157 | + if (i2c_imx->pmuxcr_endian == BIG_ENDIAN) |
||
158 | + iowrite32be(pmuxcr, i2c_imx->pmuxcr_addr); |
||
159 | + else |
||
160 | + iowrite32(pmuxcr, i2c_imx->pmuxcr_addr); |
||
161 | + } |
||
162 | + /* |
||
163 | + * Set I2C_IBSR[IBAL] to clear the IBAL bit if- |
||
164 | + * I2C_IBSR[IBAL] = 1 |
||
165 | + */ |
||
166 | + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); |
||
167 | + if (temp & I2SR_IAL) { |
||
168 | + temp &= ~I2SR_IAL; |
||
169 | + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); |
||
170 | + } |
||
171 | + return 0; |
||
172 | +} |
||
173 | + |
||
174 | static int i2c_imx_xfer(struct i2c_adapter *adapter, |
||
175 | struct i2c_msg *msgs, int num) |
||
176 | { |
||
177 | @@ -888,6 +1019,19 @@ static int i2c_imx_xfer(struct i2c_adapt |
||
178 | |||
179 | dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); |
||
180 | |||
181 | + /* |
||
182 | + * workround for ERR010027: ensure that the I2C BUS is idle |
||
183 | + * before switching to master mode and attempting a Start cycle |
||
184 | + */ |
||
185 | + result = i2c_imx_bus_busy(i2c_imx, 0); |
||
186 | + if (result) { |
||
187 | + /* timeout */ |
||
188 | + if ((result == -ETIMEDOUT) && (i2c_imx->layerscape_bus_recover == 1)) |
||
189 | + i2c_imx_recovery_for_layerscape(i2c_imx); |
||
190 | + else |
||
191 | + goto out; |
||
192 | + } |
||
193 | + |
||
194 | result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); |
||
195 | if (result < 0) |
||
196 | goto out; |
||
197 | @@ -1030,6 +1174,50 @@ static int i2c_imx_init_recovery_info(st |
||
198 | return 0; |
||
199 | } |
||
200 | |||
201 | +/* |
||
202 | + * switch SCL and SDA to their GPIO function and do some bitbanging |
||
203 | + * for bus recovery. |
||
204 | + * There are platforms such as Layerscape that don't support pinctrl, so add |
||
205 | + * workaround for layerscape, it has no effect for other platforms. |
||
206 | + */ |
||
207 | +static int i2c_imx_init_recovery_for_layerscape( |
||
208 | + struct imx_i2c_struct *i2c_imx, |
||
209 | + struct platform_device *pdev) |
||
210 | +{ |
||
211 | + const struct of_device_id *of_id; |
||
212 | + struct device_node *np = pdev->dev.of_node; |
||
213 | + struct pinmux_cfg *pinmux_cfg; |
||
214 | + struct device_node *scfg_node; |
||
215 | + void __iomem *scfg_base = NULL; |
||
216 | + |
||
217 | + i2c_imx->gpio = of_get_named_gpio(np, "fsl-scl-gpio", 0); |
||
218 | + if (!gpio_is_valid(i2c_imx->gpio)) { |
||
219 | + dev_info(&pdev->dev, "fsl-scl-gpio not found\n"); |
||
220 | + return 0; |
||
221 | + } |
||
222 | + pinmux_cfg = devm_kzalloc(&pdev->dev, sizeof(*pinmux_cfg), GFP_KERNEL); |
||
223 | + if (!pinmux_cfg) |
||
224 | + return -ENOMEM; |
||
225 | + |
||
226 | + i2c_imx->need_set_pmuxcr = 0; |
||
227 | + of_id = of_match_node(pinmux_of_match, np); |
||
228 | + if (of_id) { |
||
229 | + pinmux_cfg = (struct pinmux_cfg *)of_id->data; |
||
230 | + i2c_imx->pmuxcr_endian = pinmux_cfg->endian; |
||
231 | + i2c_imx->pmuxcr_set = pinmux_cfg->pmuxcr_set_bit; |
||
232 | + scfg_node = of_find_matching_node(NULL, scfg_device_ids); |
||
233 | + if (scfg_node) { |
||
234 | + scfg_base = of_iomap(scfg_node, 0); |
||
235 | + if (scfg_base) { |
||
236 | + i2c_imx->pmuxcr_addr = scfg_base + pinmux_cfg->pmuxcr_offset; |
||
237 | + i2c_imx->need_set_pmuxcr = 1; |
||
238 | + } |
||
239 | + } |
||
240 | + } |
||
241 | + i2c_imx->layerscape_bus_recover = 1; |
||
242 | + return 0; |
||
243 | +} |
||
244 | + |
||
245 | static u32 i2c_imx_func(struct i2c_adapter *adapter) |
||
246 | { |
||
247 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
||
248 | @@ -1085,6 +1273,11 @@ static int i2c_imx_probe(struct platform |
||
249 | i2c_imx->adapter.dev.of_node = pdev->dev.of_node; |
||
250 | i2c_imx->base = base; |
||
251 | |||
252 | + /* Init optional bus recovery for layerscape */ |
||
253 | + ret = i2c_imx_init_recovery_for_layerscape(i2c_imx, pdev); |
||
254 | + if (ret) |
||
255 | + return ret; |
||
256 | + |
||
257 | /* Get I2C clock */ |
||
258 | i2c_imx->clk = devm_clk_get(&pdev->dev, NULL); |
||
259 | if (IS_ERR(i2c_imx->clk)) { |
||
260 | @@ -1099,7 +1292,7 @@ static int i2c_imx_probe(struct platform |
||
261 | } |
||
262 | |||
263 | /* Request IRQ */ |
||
264 | - ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, |
||
265 | + ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED, |
||
266 | pdev->name, i2c_imx); |
||
267 | if (ret) { |
||
268 | dev_err(&pdev->dev, "can't claim irq %d\n", irq); |
||
269 | --- a/drivers/i2c/muxes/i2c-mux-pca954x.c |
||
270 | +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c |
||
271 | @@ -74,6 +74,7 @@ struct pca954x { |
||
272 | u8 last_chan; /* last register value */ |
||
273 | u8 deselect; |
||
274 | struct i2c_client *client; |
||
275 | + u8 disable_mux; /* do not disable mux if val not 0 */ |
||
276 | }; |
||
277 | |||
278 | /* Provide specs for the PCA954x types we know about */ |
||
279 | @@ -196,6 +197,13 @@ static int pca954x_deselect_mux(struct i |
||
280 | if (!(data->deselect & (1 << chan))) |
||
281 | return 0; |
||
282 | |||
283 | +#ifdef CONFIG_ARCH_LAYERSCAPE |
||
284 | + if (data->disable_mux != 0) |
||
285 | + data->last_chan = data->chip->nchans; |
||
286 | + else |
||
287 | + data->last_chan = 0; |
||
288 | + return pca954x_reg_write(muxc->parent, client, data->disable_mux); |
||
289 | +#endif |
||
290 | /* Deselect active channel */ |
||
291 | data->last_chan = 0; |
||
292 | return pca954x_reg_write(muxc->parent, client, data->last_chan); |
||
293 | @@ -228,6 +236,28 @@ static int pca954x_probe(struct i2c_clie |
||
294 | return -ENOMEM; |
||
295 | data = i2c_mux_priv(muxc); |
||
296 | |||
297 | +#ifdef CONFIG_ARCH_LAYERSCAPE |
||
298 | + /* The point here is that you must not disable a mux if there |
||
299 | + * are no pullups on the input or you mess up the I2C. This |
||
300 | + * needs to be put into the DTS really as the kernel cannot |
||
301 | + * know this otherwise. |
||
302 | + */ |
||
303 | + match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); |
||
304 | + if (match) |
||
305 | + data->chip = of_device_get_match_data(&client->dev); |
||
306 | + else |
||
307 | + data->chip = &chips[id->driver_data]; |
||
308 | + |
||
309 | + data->disable_mux = of_node && |
||
310 | + of_property_read_bool(of_node, "i2c-mux-never-disable") && |
||
311 | + data->chip->muxtype == pca954x_ismux ? |
||
312 | + data->chip->enable : 0; |
||
313 | + /* force the first selection */ |
||
314 | + if (data->disable_mux != 0) |
||
315 | + data->last_chan = data->chip->nchans; |
||
316 | + else |
||
317 | + data->last_chan = 0; |
||
318 | +#endif |
||
319 | i2c_set_clientdata(client, muxc); |
||
320 | data->client = client; |
||
321 | |||
322 | @@ -240,11 +270,16 @@ static int pca954x_probe(struct i2c_clie |
||
323 | * that the mux is in fact present. This also |
||
324 | * initializes the mux to disconnected state. |
||
325 | */ |
||
326 | +#ifdef CONFIG_ARCH_LAYERSCAPE |
||
327 | + if (i2c_smbus_write_byte(client, data->disable_mux) < 0) { |
||
328 | +#else |
||
329 | if (i2c_smbus_write_byte(client, 0) < 0) { |
||
330 | +#endif |
||
331 | dev_warn(&client->dev, "probe failed\n"); |
||
332 | return -ENODEV; |
||
333 | } |
||
334 | |||
335 | +#ifndef CONFIG_ARCH_LAYERSCAPE |
||
336 | match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); |
||
337 | if (match) |
||
338 | data->chip = of_device_get_match_data(&client->dev); |
||
339 | @@ -252,6 +287,7 @@ static int pca954x_probe(struct i2c_clie |
||
340 | data->chip = &chips[id->driver_data]; |
||
341 | |||
342 | data->last_chan = 0; /* force the first selection */ |
||
343 | +#endif |
||
344 | |||
345 | idle_disconnect_dt = of_node && |
||
346 | of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); |
||
347 | @@ -312,6 +348,13 @@ static int pca954x_resume(struct device |
||
348 | struct i2c_mux_core *muxc = i2c_get_clientdata(client); |
||
349 | struct pca954x *data = i2c_mux_priv(muxc); |
||
350 | |||
351 | +#ifdef CONFIG_ARCH_LAYERSCAPE |
||
352 | + if (data->disable_mux != 0) |
||
353 | + data->last_chan = data->chip->nchans; |
||
354 | + else |
||
355 | + data->last_chan = 0; |
||
356 | + return i2c_smbus_write_byte(client, data->disable_mux); |
||
357 | +#endif |
||
358 | data->last_chan = 0; |
||
359 | return i2c_smbus_write_byte(client, 0); |
||
360 | } |