diff mbox series

[U-Boot,25/41] lpi2c: Fix bus stop problem in xfer

Message ID 20180528122526.20597-26-peng.fan@nxp.com
State Superseded
Delegated to: Stefano Babic
Headers show
Series imx: add i.MX8QXP support | expand

Commit Message

Peng Fan May 28, 2018, 12:25 p.m. UTC
From: Ye Li <ye.li@nxp.com>

In xfer function, both bus_i2c_read and bus_i2c_write will
send a STOP command.  This causes a problem when reading register
data from i2c device.

Generally two operations comprise the register data reading:
   1. Write the register address to i2c device.
      START | chip_addr | W | ACK | register_addr | ACK |

   2. Read the Data from i2c device.
      START | chip_addr | R | ACK | DATA          | NACK | STOP

The STOP command should happen at the end of the transfer, otherwise
we will always get data from register address 0

Signed-off-by: Ye Li <ye.li@nxp.com>
Acked-by: Peng Fan <peng.fan@nxp.com>
Cc: Heiko Schocher <hs@denx.de>
---
 drivers/i2c/imx_lpi2c.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

Comments

Heiko Schocher May 29, 2018, 3:55 a.m. UTC | #1
Hello Peng,

Am 28.05.2018 um 14:25 schrieb Peng Fan:
> From: Ye Li <ye.li@nxp.com>
> 
> In xfer function, both bus_i2c_read and bus_i2c_write will
> send a STOP command.  This causes a problem when reading register
> data from i2c device.
> 
> Generally two operations comprise the register data reading:
>     1. Write the register address to i2c device.
>        START | chip_addr | W | ACK | register_addr | ACK |
> 
>     2. Read the Data from i2c device.
>        START | chip_addr | R | ACK | DATA          | NACK | STOP
> 
> The STOP command should happen at the end of the transfer, otherwise
> we will always get data from register address 0
> 
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Acked-by: Peng Fan <peng.fan@nxp.com>
> Cc: Heiko Schocher <hs@denx.de>
> ---
>   drivers/i2c/imx_lpi2c.c | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)

Good catch.

Reviewed-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
diff mbox series

Patch

diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c
index d2e11b411b..585787a35c 100644
--- a/drivers/i2c/imx_lpi2c.c
+++ b/drivers/i2c/imx_lpi2c.c
@@ -225,9 +225,6 @@  static int bus_i2c_read(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len)
 	if (result)
 		return result;
 	result = bus_i2c_receive(regs, buf, len);
-	if (result)
-		return result;
-	result = bus_i2c_stop(regs);
 	if (result)
 		return result;
 
@@ -242,9 +239,6 @@  static int bus_i2c_write(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len)
 	if (result)
 		return result;
 	result = bus_i2c_send(regs, buf, len);
-	if (result)
-		return result;
-	result = bus_i2c_stop(regs);
 	if (result)
 		return result;
 
@@ -380,7 +374,7 @@  static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip,
 static int imx_lpi2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
 {
 	struct imx_lpi2c_reg *regs;
-	int ret = 0;
+	int ret = 0, ret_stop;
 
 	regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
 	for (; nmsgs > 0; nmsgs--, msg++) {
@@ -398,6 +392,12 @@  static int imx_lpi2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
 	if (ret)
 		debug("i2c_write: error sending\n");
 
+	ret_stop = bus_i2c_stop(regs);
+	if (ret_stop)
+		debug("i2c_xfer: stop bus error\n");
+
+	ret |= ret_stop;
+
 	return ret;
 }