mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 18:35:28 +00:00
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:
committed by
ChromeBot
parent
001fb660bd
commit
3e76215df4
@@ -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},
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user