Commit 8cae207d03cac19c57b135871493a9278948cc18

Authored by Ye Li
1 parent 95a530df83

MLK-17357-2 lpi2c: Add bus busy error handling

When doing "i2c dev 4; i2c probe" with ENET daughter card connected on iMX8QXP MEK
board, we met a i2c bus busy issue, that the BBF of lpi2c always show busy, but the
master is idle, and stop is detected (SDF set).

This patch addes a handling to re-init the lpi2c master for this case. Then the issue
can be worked around.

Signed-off-by: Ye Li <ye.li@nxp.com>
Acked-by: Peng Fan <peng.fan@nxp.com>
(cherry picked from commit 6b4021d04c7f637fd60cf73f9cc46fdebc853790)

Showing 1 changed file with 30 additions and 21 deletions Side-by-side Diff

drivers/i2c/imx_lpi2c.c
... ... @@ -20,6 +20,8 @@
20 20 #define LPI2C_NACK_TOUT_MS 1
21 21 #define LPI2C_TIMEOUT_MS 100
22 22  
  23 +static int bus_i2c_init(struct udevice *bus, int speed);
  24 +
23 25 /* Weak linked function for overridden by some SoC power function */
24 26 int __weak init_i2c_power(unsigned i2c_num)
25 27 {
26 28  
... ... @@ -93,8 +95,9 @@
93 95 return result;
94 96 }
95 97  
96   -static int bus_i2c_send(struct imx_lpi2c_reg *regs, u8 *txbuf, int len)
  98 +static int bus_i2c_send(struct udevice *bus, u8 *txbuf, int len)
97 99 {
  100 + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
98 101 lpi2c_status_t result = LPI2C_SUCESS;
99 102  
100 103 /* empty tx */
101 104  
... ... @@ -113,8 +116,9 @@
113 116 return result;
114 117 }
115 118  
116   -static int bus_i2c_receive(struct imx_lpi2c_reg *regs, u8 *rxbuf, int len)
  119 +static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len)
117 120 {
  121 + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
118 122 lpi2c_status_t result = LPI2C_SUCESS;
119 123 u32 val;
120 124 ulong start_time = get_timer(0);
121 125  
122 126  
... ... @@ -155,15 +159,23 @@
155 159 return result;
156 160 }
157 161  
158   -static int bus_i2c_start(struct imx_lpi2c_reg *regs, u8 addr, u8 dir)
  162 +static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir)
159 163 {
  164 + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
160 165 lpi2c_status_t result = LPI2C_SUCESS;
161 166 u32 val;
162 167  
163 168 result = imx_lpci2c_check_busy_bus(regs);
164 169 if (result) {
165 170 debug("i2c: start check busy bus: 0x%x\n", result);
166   - return result;
  171 +
  172 + /* Try to init the lpi2c then check the bus busy again */
  173 + bus_i2c_init(bus, 100000);
  174 + result = imx_lpci2c_check_busy_bus(regs);
  175 + if (result) {
  176 + printf("i2c: Error check busy bus: 0x%x\n", result);
  177 + return result;
  178 + }
167 179 }
168 180 /* clear all status flags */
169 181 writel(0x7f00, &regs->msr);
170 182  
... ... @@ -183,8 +195,9 @@
183 195 return result;
184 196 }
185 197  
186   -static int bus_i2c_stop(struct imx_lpi2c_reg *regs)
  198 +static int bus_i2c_stop(struct udevice *bus)
187 199 {
  200 + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
188 201 lpi2c_status_t result = LPI2C_SUCESS;
189 202 u32 status;
190 203 ulong start_time;
191 204  
192 205  
193 206  
194 207  
195 208  
... ... @@ -219,28 +232,28 @@
219 232 return result;
220 233 }
221 234  
222   -static int bus_i2c_read(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len)
  235 +static int bus_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len)
223 236 {
224 237 lpi2c_status_t result = LPI2C_SUCESS;
225 238  
226   - result = bus_i2c_start(regs, chip, 1);
  239 + result = bus_i2c_start(bus, chip, 1);
227 240 if (result)
228 241 return result;
229   - result = bus_i2c_receive(regs, buf, len);
  242 + result = bus_i2c_receive(bus, buf, len);
230 243 if (result)
231 244 return result;
232 245  
233 246 return result;
234 247 }
235 248  
236   -static int bus_i2c_write(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len)
  249 +static int bus_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len)
237 250 {
238 251 lpi2c_status_t result = LPI2C_SUCESS;
239 252  
240   - result = bus_i2c_start(regs, chip, 0);
  253 + result = bus_i2c_start(bus, chip, 0);
241 254 if (result)
242 255 return result;
243   - result = bus_i2c_send(regs, buf, len);
  256 + result = bus_i2c_send(bus, buf, len);
244 257 if (result)
245 258 return result;
246 259  
247 260  
248 261  
249 262  
... ... @@ -355,18 +368,16 @@
355 368 static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip,
356 369 u32 chip_flags)
357 370 {
358   - struct imx_lpi2c_reg *regs;
359 371 lpi2c_status_t result = LPI2C_SUCESS;
360 372  
361   - regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
362   - result = bus_i2c_start(regs, chip, 0);
  373 + result = bus_i2c_start(bus, chip, 0);
363 374 if (result) {
364   - bus_i2c_stop(regs);
  375 + bus_i2c_stop(bus);
365 376 bus_i2c_init(bus, 100000);
366 377 return result;
367 378 }
368 379  
369   - result = bus_i2c_stop(regs);
  380 + result = bus_i2c_stop(bus);
370 381 if (result)
371 382 bus_i2c_init(bus, 100000);
372 383  
373 384  
374 385  
375 386  
... ... @@ -375,16 +386,14 @@
375 386  
376 387 static int imx_lpi2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
377 388 {
378   - struct imx_lpi2c_reg *regs;
379 389 int ret = 0, ret_stop;
380 390  
381   - regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
382 391 for (; nmsgs > 0; nmsgs--, msg++) {
383 392 debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
384 393 if (msg->flags & I2C_M_RD)
385   - ret = bus_i2c_read(regs, msg->addr, msg->buf, msg->len);
  394 + ret = bus_i2c_read(bus, msg->addr, msg->buf, msg->len);
386 395 else {
387   - ret = bus_i2c_write(regs, msg->addr, msg->buf,
  396 + ret = bus_i2c_write(bus, msg->addr, msg->buf,
388 397 msg->len);
389 398 if (ret)
390 399 break;
... ... @@ -394,7 +403,7 @@
394 403 if (ret)
395 404 debug("i2c_write: error sending\n");
396 405  
397   - ret_stop = bus_i2c_stop(regs);
  406 + ret_stop = bus_i2c_stop(bus);
398 407 if (ret_stop)
399 408 debug("i2c_xfer: stop bus error\n");
400 409