summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hendricks <dhendrix@chromium.org>2012-08-31 15:18:26 -0700
committerDavid Hendricks <dhendrix@chromium.org>2012-09-07 17:54:35 -0700
commitd7c14aaea26740e50fe3f67a307db9fa54cb0a99 (patch)
treefa57faec7ec38cb594a6ade0a3a1ea29e4b3224e
parent8bb9244797dccf92b4441016b55ce6a3f0d15d9a (diff)
downloadchrome-ec-d7c14aaea26740e50fe3f67a307db9fa54cb0a99.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: Ibd0dc50492683f26eec17f8c14da1d7367e3f869 Reviewed-on: https://gerrit.chromium.org/gerrit/32638 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 */