summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2013-05-29 15:58:40 -0700
committerChromeBot <chrome-bot@google.com>2013-06-10 09:17:10 -0700
commit6ca6f2851b40330426f782a30164a92bb13c2898 (patch)
tree25e52c1f919f6ae236b92515dd45c1553ac56656
parente738d7422eef063399854e6581c48a0ad2dbac59 (diff)
downloadchrome-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.c16
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 */