summaryrefslogtreecommitdiff
path: root/power
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2016-05-02 12:13:47 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-05-04 16:15:02 -0700
commit15ac27daa157ea0ec0ed717e373fb056c9479be6 (patch)
treecd8b35de705e100b57751875b8ab4557ea5d2b69 /power
parent25a4f355e8d4ec67faa11241750868c721b448b5 (diff)
downloadchrome-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>
Diffstat (limited to 'power')
-rw-r--r--power/rk3399.c58
1 files changed, 49 insertions, 9 deletions
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;