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 <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/49898
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
Randall Spangler
2013-05-02 10:06:15 -07:00
committed by ChromeBot
parent 001fb660bd
commit 3e76215df4
2 changed files with 20 additions and 16 deletions

View File

@@ -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},

View File

@@ -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)