diff options
author | li feng <li1.feng@intel.com> | 2015-06-02 18:23:20 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-06-04 20:51:07 +0000 |
commit | 5b2e673948086bd9a63ffabc96beb98e6409d549 (patch) | |
tree | 7ff4250a44004e14a250d7ed66c29d48597e944f | |
parent | f64945d8d12a061bc8ce2ba31077c9fc3cac8947 (diff) | |
download | chrome-ec-5b2e673948086bd9a63ffabc96beb98e6409d549.tar.gz |
i2c: Retry i2c operation if fails on nack'd(EC_ERROR_BUSY).
Retry count is defined by CONFIG_I2C_NACK_RETRY_COUNT.
BUG=chrome-os-partner:37494
TEST=Tested on Cyan, observed retry happens on nack'd i2c.
BRANCH=None
Signed-off-by: li feng <li1.feng@intel.com>
Change-Id: I73ed15a52335de6c5a5b647660bfe431a8238716
Reviewed-on: https://chromium-review.googlesource.com/274689
Reviewed-by: Shawn N <shawnn@chromium.org>
Commit-Queue: Divya Jyothi <divya.jyothi@intel.com>
Tested-by: Divya Jyothi <divya.jyothi@intel.com>
-rw-r--r-- | board/cyan/board.h | 3 | ||||
-rw-r--r-- | chip/mec1322/i2c.c | 23 | ||||
-rw-r--r-- | common/i2c.c | 12 | ||||
-rw-r--r-- | include/config.h | 4 |
4 files changed, 33 insertions, 9 deletions
diff --git a/board/cyan/board.h b/board/cyan/board.h index 30805dea96..ddbd24ba9f 100644 --- a/board/cyan/board.h +++ b/board/cyan/board.h @@ -79,6 +79,9 @@ #define I2C_PORT_ACCEL MEC1322_I2C1 #define I2C_PORT_THERMAL MEC1322_I2C3 +#undef CONFIG_I2C_NACK_RETRY_COUNT +#define CONFIG_I2C_NACK_RETRY_COUNT 2 + /* power signal definitions */ enum power_signal { X86_ALL_SYS_PWRGD = 0, diff --git a/chip/mec1322/i2c.c b/chip/mec1322/i2c.c index df08479ab0..846bcb969e 100644 --- a/chip/mec1322/i2c.c +++ b/chip/mec1322/i2c.c @@ -229,6 +229,7 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, int skip = 0; int bytes_to_read; uint8_t reg; + int ret_done; if (out_size == 0 && in_size == 0) return EC_SUCCESS; @@ -272,11 +273,13 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, } for (i = 0; i < out_size; ++i) { - if (wait_byte_done(controller)) + ret_done = wait_byte_done(controller); + if (ret_done) goto err_chip_i2c_xfer; MEC1322_I2C_DATA(controller) = out[i]; } - if (wait_byte_done(controller)) + ret_done = wait_byte_done(controller); + if (ret_done) goto err_chip_i2c_xfer; /* @@ -320,12 +323,14 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, bytes_to_read = send_stop ? in_size - 2 : in_size; for (i = 0; i < bytes_to_read; ++i) { - if (wait_byte_done(controller)) + ret_done = wait_byte_done(controller); + if (ret_done) goto err_chip_i2c_xfer; push_in_buf(&in, MEC1322_I2C_DATA(controller), skip); skip = 0; } - if (wait_byte_done(controller)) + ret_done = wait_byte_done(controller); + if (ret_done) goto err_chip_i2c_xfer; if (send_stop) { @@ -335,7 +340,8 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, */ MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_ENI; push_in_buf(&in, MEC1322_I2C_DATA(controller), skip); - if (wait_byte_done(controller)) + ret_done = wait_byte_done(controller); + if (ret_done) goto err_chip_i2c_xfer; /* Send STOP */ @@ -362,7 +368,12 @@ err_chip_i2c_xfer: /* Send STOP and return error */ MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK; - return EC_ERROR_UNKNOWN; + if (ret_done == STS_LRB) + return EC_ERROR_BUSY; + else if (ret_done == EC_ERROR_TIMEOUT) + return EC_ERROR_TIMEOUT; + else + return EC_ERROR_UNKNOWN; } int i2c_raw_get_scl(int port) diff --git a/common/i2c.c b/common/i2c.c index 189420c102..3975bf1927 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -36,8 +36,16 @@ static struct mutex port_mutex[I2C_CONTROLLER_COUNT]; int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { - return chip_i2c_xfer(port, slave_addr, out, out_size, in, - in_size, flags); + int i; + int ret = EC_SUCCESS; + + for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { + ret = chip_i2c_xfer(port, slave_addr, out, out_size, in, + in_size, flags); + if (ret != EC_ERROR_BUSY) + break; + } + return ret; } void i2c_lock(int port, int lock) diff --git a/include/config.h b/include/config.h index b670d748ad..b867a440ab 100644 --- a/include/config.h +++ b/include/config.h @@ -805,6 +805,8 @@ #undef CONFIG_I2C_PASSTHROUGH #undef CONFIG_I2C_PASSTHRU_RESTRICTED +/* Defines I2C operation retry count when slave nack'd(EC_ERROR_BUSY) */ +#define CONFIG_I2C_NACK_RETRY_COUNT 0 /* * I2C SCL gating. * @@ -1381,7 +1383,7 @@ /* Compile chip support for the USB device controller */ #undef CONFIG_USB -/* USB device buffers and descriptors in dedicated RAM */ +/* USB device buffers and descriptors */ #undef CONFIG_USB_RAM_ACCESS_SIZE #undef CONFIG_USB_RAM_ACCESS_TYPE #undef CONFIG_USB_RAM_BASE |