diff options
author | David Hendricks <dhendrix@chromium.org> | 2012-08-31 15:18:26 -0700 |
---|---|---|
committer | David Hendricks <dhendrix@chromium.org> | 2012-09-07 17:54:35 -0700 |
commit | d7c14aaea26740e50fe3f67a307db9fa54cb0a99 (patch) | |
tree | fa57faec7ec38cb594a6ade0a3a1ea29e4b3224e | |
parent | 8bb9244797dccf92b4441016b55ce6a3f0d15d9a (diff) | |
download | chrome-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.c | 53 |
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 */ |