summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2019-02-17 18:26:03 -0800
committerYe Li <ye.li@nxp.com>2019-02-17 23:29:32 -0800
commite8f70409620da897917dfa29dbe65be82c9129fd (patch)
tree733864fbebf4221f94b1ea00c405d2e501882fc3 /drivers/i2c
parent545b972a59c86e2b45b40e53a8e6c13f79e3e265 (diff)
MLK-20939 imx_virt_i2c: Add a STOP flag for last message
Add a new private flag I2C_M_SRTM_STOP(0x0200) to indicate if STOP is needed for current message. When reading/writing registers for slave devices, generally we have two messages, the first message writes the register address, second message reads/writes the value. Only the last message needs STOP. But previously M4 sends STOP for each message, this causes some slave devices treat it as end of transfer. Then, second message won't have any effect. To solve the problem, we introduce this private STOP flag, so M4 can STOP according to the flag. Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/imx_virt_i2c.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/drivers/i2c/imx_virt_i2c.c b/drivers/i2c/imx_virt_i2c.c
index 68ad9f491e..46472547ad 100644
--- a/drivers/i2c/imx_virt_i2c.c
+++ b/drivers/i2c/imx_virt_i2c.c
@@ -24,6 +24,9 @@ DECLARE_GLOBAL_DATA_PTR;
#define SRTM_CMD_READ 0x0
#define SRTM_CMD_WRITE 0x1
+#define I2C_M_SELECT_MUX_BUS 0x010000
+#define I2C_M_SRTM_STOP 0x0200
+
struct imx_virt_i2c_bus {
int index;
ulong base;
@@ -59,7 +62,7 @@ static void imx_virt_i2c_msg_dump(struct imx_srtm_i2c_msg *msg)
}
}
-static int imx_virt_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len)
+static int imx_virt_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len, uint flag)
{
struct imx_srtm_i2c_msg *msg;
u32 size;
@@ -89,7 +92,7 @@ static int imx_virt_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len)
msg->i2c_bus = i2c_bus->index;
msg->return_val = 0;
msg->slave_addr = (u16)chip;
- msg->flag = I2C_M_RD;
+ msg->flag = (u16)flag;
msg->data_length = len;
imx_virt_i2c_msg_dump(msg);
@@ -116,7 +119,7 @@ static int imx_virt_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len)
return ret;
}
-static int imx_virt_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len)
+static int imx_virt_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len, uint flag)
{
struct imx_srtm_i2c_msg *msg;
u32 size;
@@ -146,7 +149,7 @@ static int imx_virt_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len)
msg->i2c_bus = i2c_bus->index;
msg->return_val = 0;
msg->slave_addr = (u16)chip;
- msg->flag = 0;
+ msg->flag = (u16)flag;
msg->data_length = len;
imx_virt_i2c_msg_dump(msg);
@@ -183,20 +186,26 @@ static int imx_virt_i2c_probe_chip(struct udevice *bus, u32 chip,
{
debug("imx_virt_i2c_probe_chip\n");
- return imx_virt_i2c_write(bus, chip, NULL, 0);
+ return imx_virt_i2c_write(bus, chip, NULL, 0, I2C_M_SRTM_STOP);
}
static int imx_virt_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
{
int ret = 0;
+ uint flag = 0;
for (; nmsgs > 0; nmsgs--, msg++) {
debug("virt_i2c_xfer: chip=0x%x, len=0x%x, buf=0x%08x\n", msg->addr, msg->len, *msg->buf);
- if (msg->flags & I2C_M_RD)
- ret = imx_virt_i2c_read(bus, msg->addr, msg->buf, msg->len);
+
+ flag = msg->flags;
+ if (nmsgs == 1)
+ flag |= I2C_M_SRTM_STOP;
+
+ if (flag & I2C_M_RD)
+ ret = imx_virt_i2c_read(bus, msg->addr, msg->buf, msg->len, flag);
else {
ret = imx_virt_i2c_write(bus, msg->addr, msg->buf,
- msg->len);
+ msg->len, flag);
if (ret)
break;
}
@@ -232,8 +241,6 @@ static int imx_virt_i2c_probe(struct udevice *bus)
return 0;
}
-#define I2C_M_SELECT_MUX_BUS 0x010000
-
static int imx_virt_i2c_set_flags(struct udevice *child_dev, uint flags)
{
#ifdef CONFIG_I2C_MUX_IMX_VIRT