mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user