summaryrefslogtreecommitdiff
path: root/power/sdm845.c
diff options
context:
space:
mode:
Diffstat (limited to 'power/sdm845.c')
-rw-r--r--power/sdm845.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/power/sdm845.c b/power/sdm845.c
index 24429c1f37..f6a22c54ae 100644
--- a/power/sdm845.c
+++ b/power/sdm845.c
@@ -22,6 +22,7 @@
* - If POWER_GOOD is dropped by the AP, then we power the AP off
*/
+#include "charge_state.h"
#include "chipset.h"
#include "common.h"
#include "gpio.h"
@@ -60,6 +61,12 @@
/* Wait for polling the AP on signal */
#define PMIC_POWER_AP_WAIT (1 * MSEC)
+/* The timeout of the check if the system can boot AP */
+#define CAN_BOOT_AP_CHECK_TIMEOUT (500 * MSEC)
+
+/* Wait for polling if the system can boot AP */
+#define CAN_BOOT_AP_CHECK_WAIT (100 * MSEC)
+
/* Delay between power-on the system and power-on the PMIC */
#define SYSTEM_POWER_ON_DELAY (10 * MSEC)
@@ -389,22 +396,66 @@ static void power_off(void)
/* Wait longer to ensure the PMIC/AP totally off */
usleep(SYSTEM_POWER_OFF_DELAY);
+ /* Turn off the 5V rail. */
+#ifdef CONFIG_POWER_PP5000_CONTROL
+ power_5v_enable(task_get_current(), 0);
+#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */
+ gpio_set_level(GPIO_EN_PP5000, 0);
+#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */
+
lid_opened = 0;
enable_sleep(SLEEP_MASK_AP_RUN);
CPRINTS("power shutdown complete");
}
/**
+ * Check if the power is enough to boot the AP.
+ */
+static int power_is_enough(void)
+{
+ timestamp_t poll_deadline;
+
+ /* If powered by adapter only, wait a while for PD negoiation. */
+ poll_deadline = get_time();
+ poll_deadline.val += CAN_BOOT_AP_CHECK_TIMEOUT;
+
+ /*
+ * Wait for PD negotiation. If a system with drained battery, don't
+ * waste the time and exit the loop.
+ */
+ while (!system_can_boot_ap() && !charge_want_shutdown() &&
+ get_time().val < poll_deadline.val) {
+ usleep(CAN_BOOT_AP_CHECK_WAIT);
+ }
+
+ return system_can_boot_ap() && !charge_want_shutdown();
+}
+
+/**
* Power on the AP
*/
static void power_on(void)
{
/*
+ * If no enough power, return and the state machine will transition
+ * back to S5.
+ */
+ if (!power_is_enough())
+ return;
+
+ /*
* When power_on() is called, we are at S5S3. Initialize components
* to ready state before AP is up.
*/
hook_notify(HOOK_CHIPSET_PRE_INIT);
+ /* Enable the 5V rail. */
+#ifdef CONFIG_POWER_PP5000_CONTROL
+ power_5v_enable(task_get_current(), 1);
+#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */
+ gpio_set_level(GPIO_EN_PP5000, 1);
+#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */
+
set_system_power(1);
usleep(SYSTEM_POWER_ON_DELAY);
set_pmic_pwron(1);