diff options
author | Jonathan Brandmeyer <jbrandmeyer@chromium.org> | 2018-09-25 10:13:34 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-25 15:48:08 -0700 |
commit | 8649d800a9dd9c23de199029b2db25827f687925 (patch) | |
tree | c4176eeaebb6b0d761895858e8d6b03b21a4526b /common/i2c_master.c | |
parent | de0629592aef6e9d77821bb89b62d2a733675e2b (diff) | |
download | chrome-ec-8649d800a9dd9c23de199029b2db25827f687925.tar.gz |
i2c: Do not attempt bus clear on split xfer failurestabilize-11101.B
If a split transaction fails after its first half, the chip driver has a
few options for dealing with the bus state. It can either release the
bus by sending a stop bit, or it can leave the bus busy and use a
repeated start for the next transaction. ChromeEC does not support
multimaster I2C, so either condition is acceptable.
TEST=boot a bip with a battery disconnected. Observe that the bus reset
error path is not taken when attempting to read the battery
identification registers.
BRANCH=none
BUG=b:116603165, b:112862656
Change-Id: Ieb29233b0701edc2135707247b15a637e9d4d25b
Signed-off-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1243707
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Scott Collyer <scollyer@chromium.org>
Diffstat (limited to 'common/i2c_master.c')
-rw-r--r-- | common/i2c_master.c | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/common/i2c_master.c b/common/i2c_master.c index fb967afd0f..b4b403f877 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -319,12 +319,8 @@ int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, */ rv = i2c_xfer_unlocked(port, slave_addr, ®, 1, &block_length, 1, I2C_XFER_START); - if (rv) { - /* Dummy read for the stop bit */ - i2c_xfer_unlocked(port, slave_addr, 0, 0, ®, 1, - I2C_XFER_STOP); + if (rv) goto exit; - } if (len && block_length > (len - 1)) block_length = len - 1; @@ -351,7 +347,7 @@ int i2c_read_block(int port, int slave_addr, int offset, uint8_t *data, int i2c_write_block(int port, int slave_addr, int offset, const uint8_t *data, int len) { - int rv0, rv1; + int rv; uint8_t reg_address = offset; /* @@ -361,14 +357,15 @@ int i2c_write_block(int port, int slave_addr, int offset, const uint8_t *data, * order to have a better chance at sending out the stop bit. */ i2c_lock(port, 1); - rv0 = i2c_xfer_unlocked(port, slave_addr, ®_address, 1, NULL, 0, - I2C_XFER_START); - rv1 = i2c_xfer_unlocked(port, slave_addr, data, len, NULL, 0, - I2C_XFER_STOP); + rv = i2c_xfer_unlocked(port, slave_addr, ®_address, 1, NULL, 0, + I2C_XFER_START); + if (!rv) { + rv = i2c_xfer_unlocked(port, slave_addr, data, len, NULL, 0, + I2C_XFER_STOP); + } i2c_lock(port, 0); - /* Guess that the first error seen is more helpful. */ - return (rv0 != EC_SUCCESS) ? rv0 : rv1; + return rv; } int get_sda_from_i2c_port(int port, enum gpio_signal *sda) |