i2c: brcmstb: Fix START and STOP conditions
The BSC data buffers to send and receive data are each of size 32 bytes
or 8 bytes 'xfersz' depending on SoC. The problem observed for all the
combined message transfer was if length of data transfer was a multiple
of 'xfersz' a repeated START was being transmitted by BSC driver. Fixed
this by appropriately setting START/STOP conditions for such transfers.
Fixes: dd1aa2524b
("i2c: brcmstb: Add Broadcom settop SoC i2c controller driver")
Signed-off-by: Jaedon Shin <jaedon.shin@gmail.com>
Acked-by: Kamal Dasu <kdasu.kdev@gmail.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
02dbfa5e55
commit
2de3ec4f1d
|
@ -465,6 +465,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
|
||||||
u8 *tmp_buf;
|
u8 *tmp_buf;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int xfersz = brcmstb_i2c_get_xfersz(dev);
|
int xfersz = brcmstb_i2c_get_xfersz(dev);
|
||||||
|
u32 cond, cond_per_msg;
|
||||||
|
|
||||||
if (dev->is_suspended)
|
if (dev->is_suspended)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -481,10 +482,11 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
|
||||||
pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
|
pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
|
||||||
|
|
||||||
if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART))
|
if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART))
|
||||||
brcmstb_set_i2c_start_stop(dev, ~(COND_START_STOP));
|
cond = ~COND_START_STOP;
|
||||||
else
|
else
|
||||||
brcmstb_set_i2c_start_stop(dev,
|
cond = COND_RESTART | COND_NOSTOP;
|
||||||
COND_RESTART | COND_NOSTOP);
|
|
||||||
|
brcmstb_set_i2c_start_stop(dev, cond);
|
||||||
|
|
||||||
/* Send slave address */
|
/* Send slave address */
|
||||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||||
|
@ -497,13 +499,24 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_per_msg = cond;
|
||||||
|
|
||||||
/* Perform data transfer */
|
/* Perform data transfer */
|
||||||
while (len) {
|
while (len) {
|
||||||
bytes_to_xfer = min(len, xfersz);
|
bytes_to_xfer = min(len, xfersz);
|
||||||
|
|
||||||
if (len <= xfersz && i == (num - 1))
|
if (len <= xfersz) {
|
||||||
brcmstb_set_i2c_start_stop(dev,
|
if (i == (num - 1))
|
||||||
~(COND_START_STOP));
|
cond_per_msg = cond_per_msg &
|
||||||
|
~(COND_RESTART | COND_NOSTOP);
|
||||||
|
else
|
||||||
|
cond_per_msg = cond;
|
||||||
|
} else {
|
||||||
|
cond_per_msg = (cond_per_msg & ~COND_RESTART) |
|
||||||
|
COND_NOSTOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
brcmstb_set_i2c_start_stop(dev, cond_per_msg);
|
||||||
|
|
||||||
rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf,
|
rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf,
|
||||||
bytes_to_xfer, pmsg);
|
bytes_to_xfer, pmsg);
|
||||||
|
@ -512,6 +525,8 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
|
||||||
|
|
||||||
len -= bytes_to_xfer;
|
len -= bytes_to_xfer;
|
||||||
tmp_buf += bytes_to_xfer;
|
tmp_buf += bytes_to_xfer;
|
||||||
|
|
||||||
|
cond_per_msg = COND_NOSTART | COND_NOSTOP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue