diff options
author | Doug Anderson <dianders@chromium.org> | 2013-08-27 13:04:37 -0700 |
---|---|---|
committer | Caroline Tice <cmtice@chromium.org> | 2013-08-29 22:55:07 +0000 |
commit | 58d8a739b2f55be8c0c9a5cf38265733048e0742 (patch) | |
tree | 425694ba1dcab2e4caba07c1e23df6848c844fd5 /chip | |
parent | 6ecda4b0f1ea6c9aa6c1c249d1dcd4ace87cbda0 (diff) | |
download | chrome-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.c | 24 |
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) { |