diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2013-05-29 15:58:40 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-06-10 09:17:10 -0700 |
commit | 6ca6f2851b40330426f782a30164a92bb13c2898 (patch) | |
tree | 25e52c1f919f6ae236b92515dd45c1553ac56656 | |
parent | e738d7422eef063399854e6581c48a0ad2dbac59 (diff) | |
download | chrome-ec-6ca6f2851b40330426f782a30164a92bb13c2898.tar.gz |
stm32: avoid getting stuck on interrupted AP I2C transfer
When the main CPU is shutdown, if an AP/EC I2C transfer is still
on-going, the slave I2C controller on the EC will stay stuck with the
"busy" bit set and will refuse further I2C communications when the AP is
restarted.
To solve that issue, we check the busy bit everytime we shut down the
CPU and fully reset the I2C controller if it is set.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=spring
BUG=chromium:241094
TEST=run bootperf on a Spring board for a lot of cycles :
~/trunk/src/platform/crostestutils/bootperf-bin/bootperf 172.22.x.x 40
and see that we are not failing on a ssh connection timeout.
Change-Id: Ia691ae5bfba85ceacd58968487a89913934a3665
Reviewed-on: https://gerrit.chromium.org/gerrit/57047
Reviewed-by: Vic Yang <victoryang@chromium.org>
Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | chip/stm32/i2c.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index 44d662fa9b..822ace188d 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -495,6 +495,22 @@ static void i2c_init_port(unsigned int port) board_i2c_post_init(port); } +static void i2c_cleanup(void) +{ + /* + * if the platform has a dedicated I2C port for AP/EC communication + * and a transfer is still on-going (busy bit set) while we are + * shutting down the AP, the slave I2C will get stuck in that + * situation : It's time to reset it to a sane state. + */ + if ((I2C_PORT_HOST != I2C_PORT_SLAVE) && + (STM32_I2C_SR2(I2C_PORT_SLAVE) & 2)) { + CPRINTF("host i2c xfer interrupted. resetting i2c.\n"); + i2c_init_port(I2C_PORT_SLAVE); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, i2c_cleanup, HOOK_PRIO_DEFAULT); + static void i2c_init(void) { /* TODO: Add #defines to determine which channels to init */ |