
Hello Jim,
Am 27.12.2017 um 02:05 schrieb Jim Brennan:
From e643f91ccfa544b7e3153a7721fba66e0e494759 Mon Sep 17 00:00:00 2001 From: Jim Brennan jbrennan@impinj.com Date: Wed, 13 Dec 2017 13:44:02 -0800 Subject: [PATCH] i2c: imx: bus arbitration fix when reading block data
Fixes arbitration failure on imx platform due to incorrect chip address use when reading a block of data. Add support for both reading or writing a block of data or any combination.
Signed-off-by: Jim Brennan jbrennan@impinj.com
drivers/i2c/mxc_i2c.c | 65 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 24 deletions(-)
Your patch drops a lot of checkpatch warnings, see:
http://xeidos.ddns.net/tbot/id_590/tbot.txt
and search for "2018-01-16 02:41:58" to see the wget cmd, to get your patch from aptchwork and search for "2018-01-16 02:42:00" to see the checkpatch.pl command.
ERROR: Please use git commit description style 'commit <12+ chars of sha1> ("<title line>")' - ie: 'commit fatal: bad o ("721fba66e0e494759")' #15:
From e643f91ccfa544b7e3153a7721fba66e0e494759 Mon Sep 17 00:00:00 2001
ERROR: DOS line endings #42: FILE: drivers/i2c/mxc_i2c.c:28: +#include <stdbool.h>^M$ [...]
Please fix this, and resend your patch, thanks!
And some Tested-by would be helpful ...
@Stefano, @Fabio: Any chance to test this change? Thanks!
bye, Heiko
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 205274e947..bd2a39ebe6 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -25,6 +25,7 @@ #include <dm.h> #include <dm/pinctrl.h> #include <fdtdec.h> +#include <stdbool.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -275,7 +276,7 @@ static void i2c_imx_stop(struct mxc_i2c_bus *i2c_bus)
- write register address
*/ static int i2c_init_transfer_(struct mxc_i2c_bus *i2c_bus, u8 chip,
u32 addr, int alen)
{ unsigned int temp; int ret;u32 addr, int alen, bool read)
@@ -317,9 +318,17 @@ static int i2c_init_transfer_(struct mxc_i2c_bus *i2c_bus, u8 chip, temp |= I2CR_MTX | I2CR_TX_NO_AK; writeb(temp, base + (I2CR << reg_shift));
- if (alen >= 0) {
/* write slave address */
ret = tx_byte(i2c_bus, chip << 1);
- /* write slave address */
- u8 slave_address = (chip << 1);
- if (read)
slave_address |= 1;
- ret = tx_byte(i2c_bus, slave_address);
- if (ret < 0)
return ret;
- while (alen--) {
if (ret < 0) return ret;ret = tx_byte(i2c_bus, (addr >> (alen * 8)) & 0xff);
@@ -413,7 +422,7 @@ exit: #endif
static int i2c_init_transfer(struct mxc_i2c_bus *i2c_bus, u8 chip,
u32 addr, int alen)
{ int retry; int ret;u32 addr, int alen, bool read)
@@ -424,7 +433,7 @@ static int i2c_init_transfer(struct mxc_i2c_bus *i2c_bus, u8 chip, return -EINVAL;
for (retry = 0; retry < 3; retry++) {
ret = i2c_init_transfer_(i2c_bus, chip, addr, alen);
if (ret >= 0) return 0; i2c_imx_stop(i2c_bus);ret = i2c_init_transfer_(i2c_bus, chip, addr, alen, read);
@@ -536,7 +545,7 @@ static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr, VF610_I2C_REGSHIFT : IMX_I2C_REGSHIFT; ulong base = i2c_bus->base;
- ret = i2c_init_transfer(i2c_bus, chip, addr, alen);
- ret = i2c_init_transfer(i2c_bus, chip, addr, alen, false); if (ret < 0) return ret;
@@ -566,7 +575,7 @@ static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr, { int ret = 0;
- ret = i2c_init_transfer(i2c_bus, chip, addr, alen);
- ret = i2c_init_transfer(i2c_bus, chip, addr, alen, false); if (ret < 0) return ret;
@@ -817,7 +826,7 @@ static int mxc_i2c_probe_chip(struct udevice *bus, u32 chip_addr, int ret; struct mxc_i2c_bus *i2c_bus = dev_get_priv(bus);
- ret = i2c_init_transfer(i2c_bus, chip_addr, 0, 0);
- ret = i2c_init_transfer(i2c_bus, chip_addr, 0, 0, false); if (ret < 0) { debug("%s failed, ret = %d\n", __func__, ret); return ret;
@@ -841,35 +850,43 @@ static int mxc_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) * because here we only want to send out chip address. The register * address is wrapped in msg. */
- ret = i2c_init_transfer(i2c_bus, msg->addr, 0, 0);
bool read = (msg->flags & I2C_M_RD) ? true : false;
ret = i2c_init_transfer(i2c_bus, msg->addr, 0, 0, read); if (ret < 0) { debug("i2c_init_transfer error: %d\n", ret); return ret; }
for (; nmsgs > 0; nmsgs--, msg++) {
bool current_is_read = (msg->flags & I2C_M_RD) ? true : false;
bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD); debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
if (msg->flags & I2C_M_RD)
else { ret = i2c_write_data(i2c_bus, msg->addr, msg->buf, msg->len);if (current_is_read) ret = i2c_read_data(i2c_bus, msg->addr, msg->buf, msg->len);
if (ret)
}
if (ret)
break;
if (nmsgs > 1 && (current_is_read ^ next_is_read)) {
u8 addr = msg->addr << 1;
/* Reuse ret */
ret = readb(base + (I2CR << reg_shift));
ret |= I2CR_RSTA;
writeb(ret, base + (I2CR << reg_shift));
if (next_is_read)
addr |= 1;
ret = tx_byte(i2c_bus, addr);
if (ret < 0) break;
if (next_is_read) {
/* Reuse ret */
ret = readb(base + (I2CR << reg_shift));
ret |= I2CR_RSTA;
writeb(ret, base + (I2CR << reg_shift));
ret = tx_byte(i2c_bus, (msg->addr << 1) | 1);
if (ret < 0) {
i2c_imx_stop(i2c_bus);
break;
}
} }}