From 4c9e99b5e9a13ceca37b51c671323e94f0bd8fc6 Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Tue, 23 May 2017 18:56:34 +0800 Subject: stm32f4: i2c: process stop condition after slave receiver executed We need to process the stop condition after slaver receiver is executed, or else we will lost the last byte of the transmission. BRANCH=none BUG=b:38510075 TEST=`make BOARD=rose -j`, AP suspend/resume should complete within 3 secs Change-Id: I6390a908b6c05b875b8bb2c0a124292785110b20 Signed-off-by: Wei-Ning Huang Reviewed-on: https://chromium-review.googlesource.com/512463 Commit-Ready: Wei-Ning Huang Tested-by: Wei-Ning Huang Reviewed-by: Rong Chang --- chip/stm32/i2c-stm32f4.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/chip/stm32/i2c-stm32f4.c b/chip/stm32/i2c-stm32f4.c index a542088567..7c9414e444 100644 --- a/chip/stm32/i2c-stm32f4.c +++ b/chip/stm32/i2c-stm32f4.c @@ -910,28 +910,6 @@ static void i2c_event_handler(int port) disable_sleep(SLEEP_MASK_I2C_SLAVE); } - /* STOPF or AF */ - if (i2c_sr1 & (STM32_I2C_SR1_STOPF | STM32_I2C_SR1_AF)) { - /* Disable buffer interrupt */ - STM32_I2C_CR2(port) &= ~STM32_I2C_CR2_ITBUFEN; - -#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR - if (rx_pending && addr == CONFIG_BOARD_I2C_SLAVE_ADDR) - i2c_process_board_command(0, addr, buf_idx); -#endif - rx_pending = 0; - tx_pending = 0; - - /* Clear AF */ - STM32_I2C_SR1(port) &= ~STM32_I2C_SR1_AF; - /* Clear STOPF: read SR1 and write CR1 */ - dummy = STM32_I2C_SR1(port); - STM32_I2C_CR1(port) = i2c_cr1 | STM32_I2C_CR1_PE; - - /* No longer inhibit deep sleep after stop condition */ - enable_sleep(SLEEP_MASK_I2C_SLAVE); - } - /* I2C in slave transmitter */ if (i2c_sr2 & STM32_I2C_SR2_TRA) { if (i2c_sr1 & (STM32_I2C_SR1_BTF | STM32_I2C_SR1_TXE)) { @@ -968,6 +946,28 @@ static void i2c_event_handler(int port) host_buffer[buf_idx++] = STM32_I2C_DR(port); } + /* STOPF or AF */ + if (i2c_sr1 & (STM32_I2C_SR1_STOPF | STM32_I2C_SR1_AF)) { + /* Disable buffer interrupt */ + STM32_I2C_CR2(port) &= ~STM32_I2C_CR2_ITBUFEN; + +#ifdef CONFIG_BOARD_I2C_SLAVE_ADDR + if (rx_pending && addr == CONFIG_BOARD_I2C_SLAVE_ADDR) + i2c_process_board_command(0, addr, buf_idx); +#endif + rx_pending = 0; + tx_pending = 0; + + /* Clear AF */ + STM32_I2C_SR1(port) &= ~STM32_I2C_SR1_AF; + /* Clear STOPF: read SR1 and write CR1 */ + dummy = STM32_I2C_SR1(port); + STM32_I2C_CR1(port) = i2c_cr1 | STM32_I2C_CR1_PE; + + /* No longer inhibit deep sleep after stop condition */ + enable_sleep(SLEEP_MASK_I2C_SLAVE); + } + /* Enable again */ if (!(i2c_cr1 & STM32_I2C_CR1_PE)) STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE; -- cgit v1.2.1