diff options
author | Charlie Mooney <charliemooney@chromium.org> | 2012-09-06 09:03:36 -0700 |
---|---|---|
committer | Charlie Mooney <charliemooney@chromium.org> | 2012-09-06 18:02:06 -0700 |
commit | 8bb9244797dccf92b4441016b55ce6a3f0d15d9a (patch) | |
tree | 0adc78776050e0fd981cb4af1477e99e3a887f5f | |
parent | 2d85100a05b5b422a1949634e43e7720e6acfd10 (diff) | |
download | chrome-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.c | 88 |
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 */ |