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