summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-06-22 23:39:59 +0000
committerGerrit <chrome-bot@google.com>2012-06-26 20:52:35 -0700
commit240470a54b234704bd77f9485e06af5fc41d52d2 (patch)
tree07f0dad487f0d4ef0ba4578266203391f50a0982 /chip
parentcbbaf428a9ba7efcd467ab72aef1460066e934c4 (diff)
downloadchrome-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.c45
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