diff options
author | Ting Shen <phoenixshen@google.com> | 2020-11-13 12:56:34 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-11-17 18:00:39 +0000 |
commit | 8f8d017fb3e5f8d73bb415295495023353049f79 (patch) | |
tree | 30468b9673dbf3f9b042a2d120feab14a1dd1688 /common/i2c_master.c | |
parent | 8ba81426bbc4030e1fa93e13f294fb3526a0d4de (diff) | |
download | chrome-ec-8f8d017fb3e5f8d73bb415295495023353049f79.tar.gz |
i2c_master: extend i2c_xfer_no_retry to also support large writestabilize-13605.B-master
This CL extends CONFIG_I2C_XFER_LARGE_READ to also support large
(greater than 255 bytes) write.
Related config name is also updated to reflect the behavior change,
BUG=b:169651794
TEST=flash fw successfully on Zed.
BRANCH=none
Signed-off-by: Ting Shen <phoenixshen@google.com>
Change-Id: Icb889013da01f48708cd0227207561b8186bac63
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2537412
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Diffstat (limited to 'common/i2c_master.c')
-rw-r--r-- | common/i2c_master.c | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/common/i2c_master.c b/common/i2c_master.c index 7702beebb3..ee54468dea 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -142,37 +142,48 @@ __maybe_unused static int chip_i2c_xfer_with_notify( return ret; } -#ifdef CONFIG_I2C_XFER_LARGE_READ +#ifdef CONFIG_I2C_XFER_LARGE_TRANSFER /* - * Internal function that splits reading into multiple chip_i2c_xfer() calls - * if in_size exceeds CONFIG_I2C_CHIP_MAX_READ_SIZE. + * Internal function that splits transfer into multiple chip_i2c_xfer() calls + * if in_size or out_size exceeds CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE. */ static int i2c_xfer_no_retry(const int port, const uint16_t slave_addr_flags, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { - int ret; - int out_flags = flags & I2C_XFER_START; - int in_chunk_size = MIN(in_size, CONFIG_I2C_CHIP_MAX_READ_SIZE); - - in_size -= in_chunk_size; - out_flags |= !in_size ? (flags & I2C_XFER_STOP) : 0; - ret = chip_i2c_xfer_with_notify(port, slave_addr_flags, - out, out_size, in, - in_chunk_size, out_flags); - in += in_chunk_size; - while (in_size && ret == EC_SUCCESS) { - in_chunk_size = MIN(in_size, CONFIG_I2C_CHIP_MAX_READ_SIZE); - in_size -= in_chunk_size; - ret = chip_i2c_xfer_with_notify(port, slave_addr_flags, - NULL, 0, in, - in_chunk_size, !in_size ? (flags & I2C_XFER_STOP) : 0); - in += in_chunk_size; + for (int offset = 0; offset < out_size; ) { + int chunk_size = MIN(out_size - offset, + CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE); + int out_flags = 0; + + if (offset == 0) + out_flags |= flags & I2C_XFER_START; + if (in_size == 0 && offset + chunk_size == out_size) + out_flags |= flags & I2C_XFER_STOP; + + RETURN_ERROR(chip_i2c_xfer_with_notify(port, slave_addr_flags, + out + offset, chunk_size, NULL, 0, + out_flags)); + offset += chunk_size; } - return ret; + for (int offset = 0; offset < in_size; ) { + int chunk_size = MIN(in_size - offset, + CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE); + int in_flags = 0; + + if (offset == 0) + in_flags |= flags & I2C_XFER_START; + if (offset + chunk_size == in_size) + in_flags |= flags & I2C_XFER_STOP; + + RETURN_ERROR(chip_i2c_xfer_with_notify(port, slave_addr_flags, + NULL, 0, in + offset, chunk_size, in_flags)); + offset += chunk_size; + } + return EC_SUCCESS; } -#endif /* CONFIG_I2C_XFER_LARGE_READ */ +#endif /* CONFIG_I2C_XFER_LARGE_TRANSFER */ int i2c_xfer_unlocked(const int port, const uint16_t slave_addr_flags, @@ -192,7 +203,7 @@ int i2c_xfer_unlocked(const int port, #ifdef CONFIG_ZEPHYR ret = i2c_write_read(i2c_get_device_for_port(port), addr_flags, out, out_size, in, in_size); -#elif defined(CONFIG_I2C_XFER_LARGE_READ) +#elif defined(CONFIG_I2C_XFER_LARGE_TRANSFER) ret = i2c_xfer_no_retry(port, addr_flags, out, out_size, in, in_size, flags); @@ -200,7 +211,7 @@ int i2c_xfer_unlocked(const int port, ret = chip_i2c_xfer_with_notify(port, addr_flags, out, out_size, in, in_size, flags); -#endif /* CONFIG_I2C_XFER_LARGE_READ */ +#endif /* CONFIG_I2C_XFER_LARGE_TRANSFER */ if (ret != EC_ERROR_BUSY) break; } |