summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorZhikui Ren <zhikui.ren@intel.com>2022-02-02 04:30:42 +0300
committerZhikui Ren <zhikui.ren@intel.com>2022-02-15 20:05:33 +0300
commite8b2774abc5edd91e85aedf45e8365b25f3a1adc (patch)
tree42131d67d7c55f8de7dd2855783998ef444f9e96 /drivers/i2c
parent96da09186ed329d58d7f230eeabbaea306b022ec (diff)
downloadlinux-e8b2774abc5edd91e85aedf45e8365b25f3a1adc.tar.xz
i2c:aspeed: fix I2C_M_RECV_LEN return msg length
When I2C_M_RECV_LEN flag is set, the first byte of return data is the received data length. Fix the handling of i2c_smbus_read_block_data in aspeed i2c driver to include the received data length. Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 0542be568588..d2cbfa7ce5c9 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -1009,16 +1009,24 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
if (msg->flags & I2C_M_RECV_LEN) {
- recv_byte = readl(bus->base +
- ASPEED_I2C_BYTE_BUF_REG) >> 8;
- if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) {
+ if (unlikely(bus->buf_index != 0)) {
+ dev_err(bus->dev, "I2C_M_RECV_LEN buf_index is not zero\n");
bus->cmd_err = -EPROTO;
aspeed_i2c_do_stop(bus);
goto out_no_complete;
}
+ recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
+ if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) {
+ dev_err(bus->dev,
+ "I2C_M_RECV_LEN too big %d, truncate to %d\n",
+ recv_byte, I2C_SMBUS_BLOCK_MAX);
+ recv_byte = I2C_SMBUS_BLOCK_MAX;
+ }
msg->len = recv_byte + ((msg->flags & I2C_CLIENT_PEC) ?
2 : 1);
msg->flags &= ~I2C_M_RECV_LEN;
+ msg->buf[0] = recv_byte;
+ bus->buf_index = 1;
} else if (msg->len) {
aspeed_i2c_master_handle_rx(bus, msg);
}