summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorDoug Anderson <dianders@chromium.org>2013-08-27 13:04:37 -0700
committerCaroline Tice <cmtice@chromium.org>2013-08-29 22:55:07 +0000
commit58d8a739b2f55be8c0c9a5cf38265733048e0742 (patch)
tree425694ba1dcab2e4caba07c1e23df6848c844fd5 /chip
parent6ecda4b0f1ea6c9aa6c1c249d1dcd4ace87cbda0 (diff)
downloadchrome-ec-58d8a739b2f55be8c0c9a5cf38265733048e0742.tar.gz
i2c: stm32l: Don't do i2c transactions during freq changes
Previously we could get into some pretty bad situtation around frequency changes. Specifically: * If the freq change code exectued during a transaction then it would get all messed up. * If the freq change notifier executed during a transaction then we'd reset the bus midway through transaction. Badness. BRANCH=pit BUG=chrome-os-partner:22093 TEST=With all patches together: - on AP: suspend_stress_test - on EC: battery 10000 50 Change-Id: I24be29d459fe229a6278829a7c03c1e102358e8c Signed-off-by: Doug Anderson <dianders@chromium.org> Previous-Reviewed-on: https://chromium-review.googlesource.com/167102 (cherry picked from commit deab2433c13bc3b3bb75cd33c12dad633ba6a42a) Reviewed-on: https://chromium-review.googlesource.com/167149 Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/stm32/i2c-stm32l.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/chip/stm32/i2c-stm32l.c b/chip/stm32/i2c-stm32l.c
index cd5ebf8000..d51ab20955 100644
--- a/chip/stm32/i2c-stm32l.c
+++ b/chip/stm32/i2c-stm32l.c
@@ -352,7 +352,29 @@ static void i2c_freq_change(void)
STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE;
}
}
-DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_change, HOOK_PRIO_DEFAULT);
+
+static void i2c_pre_freq_change_hook(void)
+{
+ const struct i2c_port_t *p = i2c_ports;
+ int i;
+
+ /* Lock I2C ports so freq change can't interrupt an I2C transaction */
+ for (i = 0; i < I2C_PORTS_USED; i++, p++)
+ i2c_lock(p->port, 1);
+}
+DECLARE_HOOK(HOOK_PRE_FREQ_CHANGE, i2c_pre_freq_change_hook, HOOK_PRIO_DEFAULT);
+static void i2c_freq_change_hook(void)
+{
+ const struct i2c_port_t *p = i2c_ports;
+ int i;
+
+ i2c_freq_change();
+
+ /* Unlock I2C ports we locked in pre-freq change hook */
+ for (i = 0; i < I2C_PORTS_USED; i++, p++)
+ i2c_lock(p->port, 0);
+}
+DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_change_hook, HOOK_PRIO_DEFAULT);
static void i2c_init(void)
{