From cbbaf428a9ba7efcd467ab72aef1460066e934c4 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Tue, 26 Jun 2012 23:20:46 +0000 Subject: [PATCH] stm32: fix I2C waveforms and states - most events happen in the first 100us, we don't want to sleep to 2ms. This introduces big delays. Just poll the 150us, then fall back to sleep. - restore properly the port state after master transfers. Signed-off-by: Vincent Palatin BUG=None TEST=On Lucas DVT, probe I2C signals with logic analyzer and manually check them. Verify that the keyboard is still working with the charging code enabled. Change-Id: Ic0afde081d070ff6720d924469ecc7166bbc9e4c Reviewed-on: https://gerrit.chromium.org/gerrit/26161 Commit-Ready: Vincent Palatin Reviewed-by: Vincent Palatin Tested-by: Vincent Palatin --- chip/stm32/i2c.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index 1a4546800a..a51a249fe6 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -235,8 +235,8 @@ static int i2c_init1(void) /* set clock configuration : standard mode (100kHz) */ STM32_I2C_CCR(I2C1) = I2C_CCR; - /* configuration : I2C mode / Periphal enabled */ - STM32_I2C_CR1(I2C1) = (1 << 0); + /* configuration : I2C mode / Periphal enabled, ACK enabled */ + STM32_I2C_CR1(I2C1) = (1 << 10) | (1 << 0); /* error and event interrupts enabled / input clock is 16Mhz */ STM32_I2C_CR2(I2C1) = (1 << 9) | (1 << 8) | 0x10; @@ -332,8 +332,9 @@ static int wait_status(int port, uint32_t mask) CPRINTF(" - %016b\n", r); #endif /* CONFIG_DEBUG_I2C */ return EC_ERROR_TIMEOUT; + } else if (t2.val - t1.val > 150) { + usleep(2000); } - usleep(2000); r = STM32_I2C_SR1(port); } @@ -353,8 +354,8 @@ static int master_start(int port, int slave_addr) { int rv; - /* Change to master send mode, send start bit */ - STM32_I2C_CR1(port) |= (1 << 8); + /* Change to master send mode, reset stop bit, send start bit */ + STM32_I2C_CR1(port) = (STM32_I2C_CR1(port) & ~(1 << 9)) | (1 << 8); /* Wait for start bit sent event */ rv = wait_status(port, SR1_SB); if (rv) @@ -398,13 +399,19 @@ static void handle_i2c_error(int port, int rv) t2 = get_time(); if (t2.val - t1.val > 1000000) { dump_i2c_reg(port); - return; + goto cr_cleanup; } /* Send stop */ master_stop(port); usleep(10000); r = STM32_I2C_SR2(port); } +cr_cleanup: + /** + * reset control register to the default state : + * I2C mode / Periphal enabled, ACK enabled + */ + STM32_I2C_CR1(port) = (1 << 10) | (1 << 0); } static int i2c_master_transmit(int port, int slave_addr, uint8_t *data, @@ -428,7 +435,10 @@ static int i2c_master_transmit(int port, int slave_addr, uint8_t *data, return rv; STM32_I2C_DR(port) = data[i]; } - rv = wait_status(port, SR1_BTF | SR1_TxE); + rv = wait_status(port, SR1_TxE); + if (rv) + return rv; + rv = wait_status(port, SR1_BTF); if (rv) return rv;