diff options
Diffstat (limited to 'chip')
-rw-r--r-- | chip/stm32/i2c.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index 160186a4a1..7a6d4fced3 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -801,12 +801,24 @@ static void handle_i2c_error(int port, int rv) /* Clear busy state */ t1 = get_time(); - /** - * If the BUSY bit is faulty, send a stop bit just to be sure. It - * seems that this can be happen very briefly while sending a 1. - * We've not actually seen this happen, but we just want to be safe. - */ - if (rv == EC_ERROR_TIMEOUT && !(r & 2)) { + if (rv == EC_ERROR_TIMEOUT && (STM32_I2C_CR1(port) & (1 << 8))) { + /* + * If it failed while just trying to send the start bit then + * something is wrong with the internal state of the i2c, + * (Probably a stray pulse on the line got it out of sync with + * 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(); + goto cr_cleanup; + } else if (rv == EC_ERROR_TIMEOUT && !(r & 2)) { + /* + * If the BUSY bit is faulty, send a stop bit just to be sure. + * It seems that this can be happen very briefly while sending + * a 1. We've not actually seen this, but just to be safe. + */ CPRINTF("Bad BUSY bit detected.\n"); master_stop(port); } |