diff options
author | Zhikui Ren <zhikui.ren@intel.com> | 2022-02-02 04:30:42 +0300 |
---|---|---|
committer | Zhikui Ren <zhikui.ren@intel.com> | 2022-02-15 20:05:33 +0300 |
commit | e8b2774abc5edd91e85aedf45e8365b25f3a1adc (patch) | |
tree | 42131d67d7c55f8de7dd2855783998ef444f9e96 /drivers/i2c | |
parent | 96da09186ed329d58d7f230eeabbaea306b022ec (diff) | |
download | linux-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.c | 14 |
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); } |