summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Mooney <charliemooney@chromium.org>2012-09-06 09:03:36 -0700
committerCharlie Mooney <charliemooney@chromium.org>2012-09-06 18:02:06 -0700
commit8bb9244797dccf92b4441016b55ce6a3f0d15d9a (patch)
tree0adc78776050e0fd981cb4af1477e99e3a887f5f
parent2d85100a05b5b422a1949634e43e7720e6acfd10 (diff)
downloadchrome-ec-8bb9244797dccf92b4441016b55ce6a3f0d15d9a.tar.gz
Snow: Always reset i2c when it's initiallized
Previously, the i2c init code would only preform a software reset of the i2c peripheral it is initializing when it was already BUSY. It turns out it's always BUSY and the init functions are now used in two other places where they always want the software reset as well, so this pulls out the conditional, and makes it always do it. BUG=chrome-os-partner:13388 TEST=Standard i2c stress tests. Running a loop of i2cdumps from the AP while looping i2c transactions on the EC run without any errors. Even across multiple reboots, and jumping back and forth from RO to RW on the EC via sysjump while the AP is still stressing the bus. BRANCH=snow Original-Change-Id: I6b3aaae0042844033bb04cf5cb4171c8be041ad9 Signed-off-by: Charlie Mooney <charliemooney@chromium.org> (cherry picked from commit d9d31cbbdc7b110912f91fff959cde4dfad6ef9d) Change-Id: Ic3c51672819b96405a1190fbba35a78c7892c982 Signed-off-by: Charlie Mooney <charliemooney@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/32471 Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
-rw-r--r--chip/stm32/i2c.c88
1 files changed, 25 insertions, 63 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c
index 7a6d4fced3..c5b1dd9018 100644
--- a/chip/stm32/i2c.c
+++ b/chip/stm32/i2c.c
@@ -494,79 +494,46 @@ static void unwedge_i2c_bus(int port)
gpio_set_level(sda, 1);
}
-static int i2c_init2(void)
+static int i2c_init_port(unsigned int port)
{
- if (!(STM32_RCC_APB1ENR & (1 << 22))) {
+ const int i2c_clock_bit[] = {21, 22};
+
+ ASSERT(port == I2C1 || port == I2C2);
+ ASSERT(port < 2);
+
+ if (!(STM32_RCC_APB1ENR & (1 << i2c_clock_bit[port]))) {
/* Only unwedge the bus if the clock is off */
- if (board_i2c_claim(I2C2) == EC_SUCCESS) {
- unwedge_i2c_bus(I2C2);
- board_i2c_release(I2C2);
+ if (board_i2c_claim(port) == EC_SUCCESS) {
+ unwedge_i2c_bus(port);
+ board_i2c_release(port);
}
/* enable I2C2 clock */
- STM32_RCC_APB1ENR |= 1 << 22;
+ STM32_RCC_APB1ENR |= 1 << i2c_clock_bit[port];
}
- /* force reset if the bus is stuck in BUSY state */
- if (STM32_I2C_SR2(I2C2) & 0x2) {
- STM32_I2C_CR1(I2C2) = 0x8000;
- STM32_I2C_CR1(I2C2) = 0x0000;
- }
+ /* force reset of the i2c peripheral */
+ STM32_I2C_CR1(port) = 0x8000;
+ STM32_I2C_CR1(port) = 0x0000;
/* set clock configuration : standard mode (100kHz) */
- STM32_I2C_CCR(I2C2) = I2C_CCR;
+ STM32_I2C_CCR(port) = I2C_CCR;
/* set slave address */
- STM32_I2C_OAR1(I2C2) = I2C_ADDRESS;
-
- /* configuration : I2C mode / Periphal enabled, ACK enabled */
- STM32_I2C_CR1(I2C2) = (1 << 10) | (1 << 0);
- /* error and event interrupts enabled / input clock is 16Mhz */
- STM32_I2C_CR2(I2C2) = (1 << 9) | (1 << 8) | 0x10;
-
- /* clear status */
- STM32_I2C_SR1(I2C2) = 0;
-
- board_i2c_post_init(I2C2);
-
- CPUTS("done\n");
- return EC_SUCCESS;
-}
-
-static int i2c_init1(void)
-{
- if (!(STM32_RCC_APB1ENR & (1 << 21))) {
- /* Only unwedge the bus if the clock is off */
- if (board_i2c_claim(I2C1) == EC_SUCCESS) {
- unwedge_i2c_bus(I2C1);
- board_i2c_release(I2C1);
- }
-
- /* enable clock */
- STM32_RCC_APB1ENR |= 1 << 21;
- }
-
- /* force reset if the bus is stuck in BUSY state */
- if (STM32_I2C_SR2(I2C1) & 0x2) {
- STM32_I2C_CR1(I2C1) = 0x8000;
- STM32_I2C_CR1(I2C1) = 0x0000;
- }
-
- /* set clock configuration : standard mode (100kHz) */
- STM32_I2C_CCR(I2C1) = I2C_CCR;
+ if (port == I2C2)
+ STM32_I2C_OAR1(port) = I2C_ADDRESS;
/* configuration : I2C mode / Periphal enabled, ACK enabled */
- STM32_I2C_CR1(I2C1) = (1 << 10) | (1 << 0);
+ STM32_I2C_CR1(port) = (1 << 10) | (1 << 0);
/* error and event interrupts enabled / input clock is 16Mhz */
- STM32_I2C_CR2(I2C1) = (1 << 9) | (1 << 8) | 0x10;
+ STM32_I2C_CR2(port) = (1 << 9) | (1 << 8) | 0x10;
/* clear status */
- STM32_I2C_SR1(I2C1) = 0;
+ STM32_I2C_SR1(port) = 0;
- board_i2c_post_init(I2C1);
+ board_i2c_post_init(port);
return EC_SUCCESS;
-
}
static int i2c_init(void)
@@ -574,8 +541,8 @@ static int i2c_init(void)
int rc = 0;
/* FIXME: Add #defines to determine which channels to init */
- rc |= i2c_init2();
- rc |= i2c_init1();
+ rc |= i2c_init_port(I2C1);
+ rc |= i2c_init_port(I2C2);
/* enable event and error interrupts */
if (!rc) {
@@ -809,9 +776,7 @@ static void handle_i2c_error(int port, int rv)
* the actual bytes) so reset it.
*/
CPRINTF("Unable to send START, resetting i2c.\n");
- STM32_I2C_CR1(I2C2) = 0x8000;
- STM32_I2C_CR1(I2C2) = 0x0000;
- i2c_init2();
+ i2c_init_port(port);
goto cr_cleanup;
} else if (rv == EC_ERROR_TIMEOUT && !(r & 2)) {
/*
@@ -829,10 +794,7 @@ static void handle_i2c_error(int port, int rv)
if (t2.val - t1.val > I2C_TX_TIMEOUT_MASTER) {
dump_i2c_reg(port);
/* Reset the i2c periph to get it back to slave mode */
- if (port == I2C1)
- i2c_init1();
- else
- i2c_init2();
+ i2c_init_port(port);
goto cr_cleanup;
}
/* Send stop */