diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2012-06-22 23:39:59 +0000 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-06-26 20:52:35 -0700 |
commit | 240470a54b234704bd77f9485e06af5fc41d52d2 (patch) | |
tree | 07f0dad487f0d4ef0ba4578266203391f50a0982 /chip | |
parent | cbbaf428a9ba7efcd467ab72aef1460066e934c4 (diff) | |
download | chrome-ec-240470a54b234704bd77f9485e06af5fc41d52d2.tar.gz |
stm32: fix race condition in I2C response
When we are transmitting a response to the EC, we don't want to race
with the TX empty interrupt handler. So just disable I2C interrupt
during the transmission.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BUG=None
TEST=on Lucas DVT, use the keyboard and see we are no longer getting
"bad checksum" in the kernel log.
Change-Id: Ic59532d1ac0a3eabb67ba0d498940986282bd87f
Reviewed-on: https://gerrit.chromium.org/gerrit/26162
Commit-Ready: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/stm32/i2c.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index a51a249fe6..1573561139 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -50,6 +50,26 @@ static int rx_index; /* indicates if a wait loop should abort */ static volatile int abort_transaction; +static inline void disable_i2c_interrupt(int port) +{ + STM32_I2C_CR2(port) &= ~(3 << 8); +} + +static inline void enable_i2c_interrupt(int port) +{ + STM32_I2C_CR2(port) |= 3 << 8; +} + +static inline void enable_ack(int port) +{ + STM32_I2C_CR1(port) |= (1 << 10); +} + +static inline void disable_ack(int port) +{ + STM32_I2C_CR1(port) &= ~(1 << 10); +} + static int wait_tx(int port) { static timestamp_t deadline; @@ -67,6 +87,9 @@ static int i2c_write_raw(int port, void *buf, int len) int i; uint8_t *data = buf; + /* we don't want to race with TxE interrupt event */ + disable_i2c_interrupt(port); + abort_transaction = 0; for (i = 0; i < len; i++) { STM32_I2C_DR(port) = data[i]; @@ -76,6 +99,8 @@ static int i2c_write_raw(int port, void *buf, int len) } } + enable_i2c_interrupt(port); + return len; } @@ -281,26 +306,6 @@ DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_DEFAULT); #define SR1_PECERR (1 << 12) /* PEC err in reception */ #define SR1_TIMEOUT (1 << 14) /* Timeout : 25ms */ -static inline void disable_i2c_interrupt(int port) -{ - STM32_I2C_CR2(port) &= ~(3 << 8); -} - -static inline void enable_i2c_interrupt(int port) -{ - STM32_I2C_CR2(port) |= 3 << 8; -} - -static inline void enable_ack(int port) -{ - STM32_I2C_CR1(port) |= (1 << 10); -} - -static inline void disable_ack(int port) -{ - STM32_I2C_CR1(port) &= ~(1 << 10); -} - static inline void dump_i2c_reg(int port) { #ifdef CONFIG_DEBUG_I2C |