summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hendricks <dhendrix@chromium.org>2012-08-31 15:18:26 -0700
committerGerrit <chrome-bot@google.com>2012-09-07 19:00:11 -0700
commit42bc4b8b089bf7a4872ff0879747bc4953aa4bb3 (patch)
tree29c6a7ee9cbac6567d41ddfd7fda73023e2c50e5
parenta8a3c6d9be83e260279ad4da469fc60a5a05d0fd (diff)
downloadchrome-ec-42bc4b8b089bf7a4872ff0879747bc4953aa4bb3.tar.gz
snow: re-configure I2C arbitration pins at AP off/on to fix leakage
This (re-)configures the I2C arbitration lines as floating inputs when the AP powers off, and restores them strictly before the AP powers on. This is intended to prevent leakage when the AP is off and arbitration is not needed. This CL does not impact the AP on/suspend case. Signed-off-by: David Hendricks <dhendrix@chromium.org> BRANCH=snow BUG=chrome-os-partner:12573,chrome-os-partner:12381 TEST=manual (see notes below) - PA4: SPI1_NSS / AP_CLAIM, input w/ pull-up when AP on - PA6: SPI1_MISO / EC_CLAIM, output when AP is on - Both floating when AP off 8 = input with pull up/down, 4 = floating input, 1 = output AP off (before this CL): > rw 0x40010800 read 0x40010800 = 0x41484144 > gpioget SPI1_NSS 0* SPI1_NSS > gpioget SPI1_MISO 1 SPI1_MISO AP off (after this CL): > rw 0x40010800 read 0x40010800 = 0x44444144 > gpioget SPI1_NSS 0* SPI1_NSS > gpioget SPI1_MISO 0* SPI1_MISO AP on or suspended (before and after this CL): > rw 0x40010800 read 0x40010800 = 0x81484144 > gpioget SPI1_NSS 1* SPI1_NSS > gpioget SPI1_MISO 1* SPI1_MISO Additional testing: - "pmu 10000" and "cros_test i2c" in u-boot only showed the FET2 control changing (as expected). - "pmu 10000" and "while [ 1 ] ; do i2cdump -f -y -r 0-24 4 0x48 b ; done" and ran "suspend_stress_test" for a couple dozen iterations. The registers only changed as expected (FET1 and FET6 turned off when suspending). Change-Id: I72f5cb1883d01b1faad6c2db65dfa09d477e1885 Reviewed-on: https://gerrit.chromium.org/gerrit/32078 Commit-Ready: David Hendricks <dhendrix@chromium.org> Reviewed-by: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org>
-rw-r--r--board/snow/board.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/board/snow/board.c b/board/snow/board.c
index 14c7277a71..e973ab46e3 100644
--- a/board/snow/board.c
+++ b/board/snow/board.c
@@ -165,10 +165,6 @@ void configure_board_late(void)
#ifdef CONFIG_AC_POWER_STATUS
gpio_set_flags(GPIO_AC_STATUS, GPIO_OUT_HIGH);
#endif
-#ifdef CONFIG_ARBITRATE_I2C
- gpio_set_flags(GPIO_AP_CLAIM, GPIO_PULL_UP);
- gpio_set_flags(GPIO_EC_CLAIM, GPIO_OUT_HIGH);
-#endif
}
void board_interrupt_host(int active)
@@ -213,6 +209,35 @@ void board_power_led_config(enum powerled_config config)
}
}
+enum {
+ /* Time between requesting bus and deciding that we have it */
+ BUS_SLEW_DELAY_US = 10,
+
+ /* Time between retrying to see if the AP has released the bus */
+ BUS_WAIT_RETRY_US = 3000,
+
+ /* Time to wait until the bus becomes free */
+ BUS_WAIT_FREE_US = 100 * 1000,
+};
+
+/*
+ * This reflects the desired value of GPIO_EC_CLAIM to ensure that the
+ * GPIO is driven correctly when re-enabled before AP power on.
+ */
+static char i2c_claimed_by_ec;
+
+static int board_pre_init_hook(void)
+{
+#ifdef CONFIG_ARBITRATE_I2C
+ gpio_set_flags(GPIO_AP_CLAIM, GPIO_PULL_UP);
+ gpio_set_level(GPIO_EC_CLAIM, i2c_claimed_by_ec ? 0 : 1);
+ gpio_set_flags(GPIO_EC_CLAIM, GPIO_OUTPUT);
+ usleep(BUS_SLEW_DELAY_US);
+#endif
+ return 0;
+}
+DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, board_pre_init_hook, HOOK_PRIO_DEFAULT);
+
static int board_startup_hook(void)
{
gpio_set_flags(GPIO_SUSPEND_L, INT_BOTH_PULL_UP);
@@ -224,20 +249,15 @@ static int board_shutdown_hook(void)
{
/* Disable pull-up on SUSPEND_L during shutdown to prevent leakage */
gpio_set_flags(GPIO_SUSPEND_L, INT_BOTH_FLOATING);
+
+#ifdef CONFIG_ARBITRATE_I2C
+ gpio_set_flags(GPIO_AP_CLAIM, GPIO_INPUT);
+ gpio_set_flags(GPIO_EC_CLAIM, GPIO_INPUT);
+#endif
return 0;
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_shutdown_hook, HOOK_PRIO_DEFAULT);
-enum {
- /* Time between requesting bus and deciding that we have it */
- BUS_SLEW_DELAY_US = 10,
-
- /* Time between retrying to see if the AP has released the bus */
- BUS_WAIT_RETRY_US = 3000,
-
- /* Time to wait until the bus becomes free */
- BUS_WAIT_FREE_US = 100 * 1000,
-};
#ifdef CONFIG_ARBITRATE_I2C
@@ -250,7 +270,7 @@ int board_i2c_claim(int port)
/* If AP is off, we have the bus */
if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
- gpio_set_level(GPIO_EC_CLAIM, 0);
+ i2c_claimed_by_ec = 1;
return EC_SUCCESS;
}
@@ -269,6 +289,7 @@ int board_i2c_claim(int port)
while (time_since32(start_retry) < BUS_WAIT_RETRY_US) {
if (gpio_get_level(GPIO_AP_CLAIM)) {
/* We got it, so return */
+ i2c_claimed_by_ec = 1;
return EC_SUCCESS;
}
@@ -284,6 +305,7 @@ int board_i2c_claim(int port)
gpio_set_level(GPIO_EC_CLAIM, 1);
usleep(BUS_SLEW_DELAY_US);
+ i2c_claimed_by_ec = 0;
panic_puts("Unable to access I2C bus (arbitration timeout)\n");
return EC_ERROR_BUSY;
@@ -295,6 +317,7 @@ void board_i2c_release(int port)
/* Release our claim */
gpio_set_level(GPIO_EC_CLAIM, 1);
usleep(BUS_SLEW_DELAY_US);
+ i2c_claimed_by_ec = 0;
}
}
#endif /* CONFIG_ARBITRATE_I2C */