From 3e76215df46fbcfb8fa0920b448c2dab7c098914 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Thu, 2 May 2013 10:06:15 -0700 Subject: [PATCH] Fix I2C port configuration on pit 1) Port needs to be open-drain. Missed this when porting from STM32F because open-drain and alternate function are set in the same register on STM32F and are different regs on STM32L. 2) Queue a stop condition if a transaction failed, so the clock goes back high. BUG=chrome-os-partner:18969 BRANCH=none TEST=i2cscan finds both the PMU at 0x90 and the battery at 0x16 Change-Id: I708b925e4e30da9d5864b74641b1cbe90c9313fe Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/49898 Reviewed-by: Bill Richardson --- board/pit/board.c | 12 ++++-------- chip/stm32/i2c-stm32l15x.c | 24 ++++++++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/board/pit/board.c b/board/pit/board.c index c7c124df6d..a8bdf5e930 100644 --- a/board/pit/board.c +++ b/board/pit/board.c @@ -56,14 +56,10 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"EN_PP3300", GPIO_A, (1<<8), GPIO_OUT_LOW, NULL}, {"EN_PP5000", GPIO_A, (1<<11), GPIO_OUT_LOW, NULL}, {"ENTERING_RW", GPIO_H, (1<<0), GPIO_OUT_LOW, NULL}, - /* - * I2C pins should be configured as inputs until I2C module is - * initialized. This will avoid driving the lines unintentionally. - */ - {"I2C1_SCL", GPIO_B, (1<<6), GPIO_INPUT, NULL}, - {"I2C1_SDA", GPIO_B, (1<<7), GPIO_INPUT, NULL}, - {"I2C2_SCL", GPIO_B, (1<<10), GPIO_INPUT, NULL}, - {"I2C2_SDA", GPIO_B, (1<<11), GPIO_INPUT, NULL}, + {"I2C1_SCL", GPIO_B, (1<<6), GPIO_HI_Z, NULL}, + {"I2C1_SDA", GPIO_B, (1<<7), GPIO_HI_Z, NULL}, + {"I2C2_SCL", GPIO_B, (1<<10), GPIO_HI_Z, NULL}, + {"I2C2_SDA", GPIO_B, (1<<11), GPIO_HI_Z, NULL}, {"LED_POWER_L", GPIO_A, (1<<2), GPIO_OUT_HIGH, NULL}, {"PMIC_PWRON", GPIO_A, (1<<12), GPIO_OUT_LOW, NULL}, {"PMIC_RESET", GPIO_A, (1<<15), GPIO_OUT_LOW, NULL}, diff --git a/chip/stm32/i2c-stm32l15x.c b/chip/stm32/i2c-stm32l15x.c index c96b4e76e1..e3ff2cb0d1 100644 --- a/chip/stm32/i2c-stm32l15x.c +++ b/chip/stm32/i2c-stm32l15x.c @@ -77,8 +77,10 @@ static int wait_sr1(int port, int mask) /* Check for errors */ if (sr1 & (STM32_I2C_SR1_ARLO | STM32_I2C_SR1_BERR | - STM32_I2C_SR1_AF)) + STM32_I2C_SR1_AF)) { + dump_i2c_reg(port, "wait_sr1 failed"); return EC_ERROR_UNKNOWN; + } /* I2C is slow, so let other things run while we wait */ usleep(100); @@ -134,6 +136,8 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes, ASSERT(out || !out_bytes); ASSERT(in || !in_bytes); + dump_i2c_reg(port, "xfer start"); + /* Clear status */ /* * TODO: should check for any leftover error status, and reset the @@ -147,13 +151,11 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes, /* Clear start and stop bits */ STM32_I2C_CR1(port) &= ~(STM32_I2C_CR1_START | STM32_I2C_CR1_STOP); - dump_i2c_reg(port, "xfer start"); - if (out_bytes) { if (!started) { rv = send_start(port, slave_addr); if (rv) - return rv; + goto xfer_exit; } /* Write data, if any */ @@ -164,7 +166,7 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes, rv = wait_sr1(port, STM32_I2C_SR1_BTF); if (rv) - return rv; + goto xfer_exit; } /* Need repeated start condition before reading */ @@ -179,7 +181,7 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes, if (!started) { rv = send_start(port, slave_addr | 0x01); if (rv) - return rv; + goto xfer_exit; } /* Read data, if any */ @@ -200,8 +202,14 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes, } } - /* Success */ - return EC_SUCCESS; + xfer_exit: + /* On error, queue a stop condition */ + if (rv) { + STM32_I2C_CR1(port) |= STM32_I2C_CR1_STOP; + dump_i2c_reg(port, "stop after error"); + } + + return rv; } int i2c_get_line_levels(int port)