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>
This commit is contained in:
li feng
2015-06-02 18:23:20 -07:00
committed by ChromeOS Commit Bot
parent f64945d8d1
commit 5b2e673948
4 changed files with 33 additions and 9 deletions

View File

@@ -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,

View File

@@ -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)

View File

@@ -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)

View File

@@ -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