diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2016-05-02 12:13:47 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-05-04 16:15:02 -0700 |
commit | 15ac27daa157ea0ec0ed717e373fb056c9479be6 (patch) | |
tree | cd8b35de705e100b57751875b8ab4557ea5d2b69 | |
parent | 25a4f355e8d4ec67faa11241750868c721b448b5 (diff) | |
download | chrome-ec-15ac27daa157ea0ec0ed717e373fb056c9479be6.tar.gz |
rk3399: Set power state based on input signals
Use input signals to verify power state and determine power state after
sysjump.
BUG=chrome-os-partner:52878
BRANCH=None
TEST=Manual on kevin.
- Verify AP powers up on 'powerbtn'.
- AP shuts down on 'apshutdown'.
- AP re-powers / resets on 'powerbtn' + 'apreset'.
- AP doesn't shutdown on 'sysjump rw' while in S0.
Change-Id: Id24feb0f8490aa7cb73c46178085ff2e46f8d0a6
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/341704
Commit-Ready: Shawn N <shawnn@chromium.org>
Tested-by: Shawn N <shawnn@chromium.org>
Reviewed-by: David Schneider <dnschneid@chromium.org>
Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r-- | board/kevin/board.c | 9 | ||||
-rw-r--r-- | board/kevin/board.h | 7 | ||||
-rw-r--r-- | board/kevin/gpio.inc | 18 | ||||
-rw-r--r-- | power/rk3399.c | 58 |
4 files changed, 73 insertions, 19 deletions
diff --git a/board/kevin/board.c b/board/kevin/board.c index bd48fec0d6..538c91651f 100644 --- a/board/kevin/board.c +++ b/board/kevin/board.c @@ -86,6 +86,15 @@ const struct i2c_port_t i2c_ports[] = { }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + {GPIO_PP5000_PG, 1, "PP5000_PWR_GOOD"}, + {GPIO_TPS65261_PG, 1, "SYS_PWR_GOOD"}, + {GPIO_AP_CORE_PG, 1, "AP_PWR_GOOD"}, + {GPIO_AP_EC_S3_S0_L, 0, "SUSPEND_DEASSERTED"}, +}; +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + /******************************************************************************/ /* Wake-up pins for hibernate */ const enum gpio_signal hibernate_wake_pins[] = { diff --git a/board/kevin/board.h b/board/kevin/board.h index a450316f30..c9827a9285 100644 --- a/board/kevin/board.h +++ b/board/kevin/board.h @@ -122,8 +122,13 @@ enum pwm_channel { /* power signal definitions */ enum power_signal { + PP5000_PWR_GOOD = 0, + SYS_PWR_GOOD, + AP_PWR_GOOD, + SUSPEND_DEASSERTED, + /* Number of signals */ - POWER_SIGNAL_COUNT = 0 + POWER_SIGNAL_COUNT, }; #include "gpio_signal.h" diff --git a/board/kevin/gpio.inc b/board/kevin/gpio.inc index d93b4d92d6..b31cc35f87 100644 --- a/board/kevin/gpio.inc +++ b/board/kevin/gpio.inc @@ -12,7 +12,6 @@ GPIO_INT(WP_L, PIN(9, 3), GPIO_INT_BOTH, switch_interrupt) -/* TODO: May be floating when SOC unpowered */ GPIO_INT(SHI_CS_L, PIN(5, 3), GPIO_INT_FALLING, shi_cs_event) GPIO_INT(USB_C0_PD_INT_L, PIN(6, 0), GPIO_INT_FALLING | GPIO_PULL_UP, tcpc_alert_event) @@ -27,7 +26,15 @@ GPIO_INT(POWER_BUTTON_L, PIN(0, 4), GPIO_INT_BOTH | GPIO_INPUT | GPIO_PULL_UP, GPIO_INT(LID_OPEN, PIN(9, 7), GPIO_INT_BOTH | GPIO_INPUT | GPIO_SEL_1P8V, lid_interrupt) -/* TODO: Add power sequencing interrupt pins */ +GPIO_INT(PP5000_PG, PIN(7, 1), + GPIO_INT_BOTH | GPIO_INPUT | GPIO_PULL_UP, power_signal_interrupt) +GPIO_INT(TPS65261_PG, PIN(7, 5), + GPIO_INT_BOTH | GPIO_INPUT | GPIO_PULL_UP, power_signal_interrupt) +/* TODO: Remove PD in S3 for power savings */ +GPIO_INT(AP_EC_S3_S0_L, PIN(5, 4), + GPIO_INT_BOTH | GPIO_INPUT | GPIO_PULL_DOWN, power_signal_interrupt) +GPIO_INT(AP_CORE_PG, PIN(6, 7), + GPIO_INT_BOTH | GPIO_INPUT | GPIO_PULL_UP, power_signal_interrupt) /* VR EN */ GPIO(AP_CORE_EN, PIN(7, 2), GPIO_OUT_LOW) @@ -58,12 +65,6 @@ GPIO(PP3300_USB_EN_L, PIN(3, 7), GPIO_OUT_HIGH) GPIO(PP5000_EN, PIN(C, 6), GPIO_OUT_LOW) -GPIO(PP5000_PG, PIN(7, 1), GPIO_INPUT | GPIO_PULL_UP) -GPIO(TPS65261_PG, PIN(7, 5), GPIO_INPUT | GPIO_PULL_UP) -/* TODO: May be floating when SOC unpowered */ -GPIO(AP_EC_S3_S0_L, PIN(5, 4), GPIO_INPUT) -GPIO(AP_CORE_PG, PIN(6, 7), GPIO_INPUT | GPIO_PULL_UP) - /* * I2C pins should be configured as inputs until I2C module is * initialized. This will avoid driving the lines unintentionally. @@ -110,7 +111,6 @@ GPIO(AP_OVERTEMP, PIN(7, 4), GPIO_INPUT) GPIO(USB_A_CHARGE_EN, PIN(8, 4), GPIO_OUT_LOW) GPIO(SPI_SENSOR_CS_L, PIN(9, 4), GPIO_OUT_HIGH) - GPIO(USB_C0_DISCHARGE, PIN(0, 3), GPIO_OUT_LOW) GPIO(USB_C1_DISCHARGE, PIN(B, 1), GPIO_OUT_LOW) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */ diff --git a/power/rk3399.c b/power/rk3399.c index 81fff5c3a2..c374b78193 100644 --- a/power/rk3399.c +++ b/power/rk3399.c @@ -26,7 +26,19 @@ #define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) /* Input state flags */ -/* TODO: Monitor input signals to determine AP power state */ +#define IN_PGOOD_PP5000 POWER_SIGNAL_MASK(PP5000_PWR_GOOD) +#define IN_PGOOD_SYS POWER_SIGNAL_MASK(SYS_PWR_GOOD) +#define IN_PGOOD_AP POWER_SIGNAL_MASK(AP_PWR_GOOD) +#define IN_SUSPEND_DEASSERTED POWER_SIGNAL_MASK(SUSPEND_DEASSERTED) + +/* All always-on supplies */ +#define IN_PGOOD_ALWAYS_ON (IN_PGOOD_SYS) +/* Rails requires for S3 */ +#define IN_PGOOD_S3 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_PP5000) +/* Rails required for S0 */ +#define IN_PGOOD_S0 (IN_PGOOD_S3 | IN_PGOOD_AP) +/* All inputs in the right state for S0 */ +#define IN_ALL_S0 (IN_PGOOD_S0 | IN_SUSPEND_DEASSERTED) static const struct power_signal_info power_control_outputs[] = { { GPIO_AP_CORE_EN, 1 }, @@ -83,20 +95,33 @@ void chipset_reset(int cold_reset) gpio_set_level(GPIO_SYS_RST_L, 1); } -enum power_state power_chipset_init(void) +static void chipset_force_g3(void) { int i; const struct power_signal_info *output_signal; - /* TODO: decode state after sysjump */ /* Force all signals to their G3 states */ CPRINTS("forcing G3"); for (i = 0; i < ARRAY_SIZE(power_control_outputs); ++i) { output_signal = &power_control_outputs[i]; - gpio_set_level(output_signal->gpio, !output_signal->level); + gpio_set_level(output_signal->gpio, + !output_signal->level); + } +} + +enum power_state power_chipset_init(void) +{ + if (system_jumped_to_this_image()) { + if ((power_get_signals() & IN_ALL_S0) == IN_ALL_S0) { + disable_sleep(SLEEP_MASK_AP_RUN); + CPRINTS("already in S0"); + return POWER_S0; + } + + chipset_force_g3(); + wireless_set_state(WIRELESS_OFF); } - wireless_set_state(WIRELESS_OFF); return POWER_G3; } @@ -113,13 +138,13 @@ enum power_state power_handle_state(enum power_state state) return POWER_S5S3; case POWER_S3: - if (forcing_shutdown) + if (!power_has_signals(IN_PGOOD_S3) || forcing_shutdown) return POWER_S3S5; - else + else if (power_has_signals(IN_SUSPEND_DEASSERTED)) return POWER_S3S0; case POWER_S0: - if (forcing_shutdown) + if (!power_has_signals(IN_PGOOD_S0) || forcing_shutdown) return POWER_S0S3; break; @@ -153,6 +178,15 @@ enum power_state power_handle_state(enum power_state state) msleep(2); gpio_set_level(GPIO_PP3300_TRACKPAD_EN_L, 0); + /* + * TODO: Consider ADC_PP900_AP / ADC_PP1200_LPDDR analog + * voltage levels for state transition. + */ + if (power_wait_signals(IN_PGOOD_S3)) { + chipset_force_shutdown(); + return POWER_S5; + } + /* Call hooks now that rails are up */ hook_notify(HOOK_CHIPSET_STARTUP); /* Power up to next state */ @@ -176,6 +210,11 @@ enum power_state power_handle_state(enum power_state state) gpio_set_level(GPIO_PP1800_LID_EN_L, 0); gpio_set_level(GPIO_PP1800_SENSOR_EN_L, 0); + if (power_wait_signals(IN_PGOOD_S0)) { + chipset_force_shutdown(); + return POWER_S3; + } + /* Enable wireless */ wireless_set_state(WIRELESS_ON); @@ -218,7 +257,8 @@ enum power_state power_handle_state(enum power_state state) case POWER_S5G3: /* Initialize power signal outputs to default. */ - return power_chipset_init(); + chipset_force_g3(); + return POWER_G3; } return state; |