summaryrefslogtreecommitdiff
path: root/power
diff options
context:
space:
mode:
authorWai-Hong Tam <waihong@google.com>2018-07-26 17:04:05 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-08-31 05:22:50 -0700
commit224667711a684241ef24cc3338b112097b10eba4 (patch)
tree069b19a42898754b77e24bfc852d856c7e7e96d6 /power
parent1d4471de578c799d9428f78fe3ce3fee6246daef (diff)
downloadchrome-ec-224667711a684241ef24cc3338b112097b10eba4.tar.gz
cheza: Use POWER_GOOD signal instead of AP_RST_L
The AP_RST_L is not a good signal to indicate power good. For an AP initiated warm reset (the Qualcomm way), AP pulls down PS_HOLD for a short pulse, and then PMIC pulls down AP_RST_L for another short pulse. This short pulse confuses EC from a power-lost. We use a confirmation logic to differentiate this case as a workaround. This CL uses another signal POWER_GOOD, which is SRC_PP1800_S4A from PMIC, as an indicator. CQ-DEPEND=CL:1169952 BRANCH=none BUG=b:78455067 TEST=Checked "power on", "power off", "apshutdown", and "apreset". Verifed the power-off sequence: * if the PMIC registers not programmed, it forces off switchcap. * if the PMIC registers programmed, it does graceful PMIC shutdown. Change-Id: I847eef5d4202485b70354b3f65ce24cd1ccb7ece Signed-off-by: Wai-Hong Tam <waihong@google.com> Reviewed-on: https://chromium-review.googlesource.com/1169953 Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Diffstat (limited to 'power')
-rw-r--r--power/sdm845.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/power/sdm845.c b/power/sdm845.c
index 73b18dbe34..81c18fb804 100644
--- a/power/sdm845.c
+++ b/power/sdm845.c
@@ -37,7 +37,7 @@
#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args)
/* Masks for power signals */
-#define IN_POWER_GOOD POWER_SIGNAL_MASK(SDM845_AP_RST_L)
+#define IN_POWER_GOOD POWER_SIGNAL_MASK(SDM845_POWER_GOOD)
/* Long power key press to force shutdown */
#define DELAY_FORCE_SHUTDOWN (8 * SECOND)
@@ -53,11 +53,17 @@
#define DELAY_SHUTDOWN_ON_POWER_HOLD (8 * SECOND)
/*
- * After trigger PMIC power-on, how long it triggers AP to turn on.
- * Obversed that the worst case is ~150ms. Pick a safe vale.
+ * After trigger PMIC power sequence, how long it triggers AP to turn on
+ * or off. Observed that the worst case is ~150ms. Pick a safe vale.
*/
#define PMIC_POWER_AP_RESPONSE_TIMEOUT (350 * MSEC)
+/*
+ * After force off the switch cap, how long the PMIC/AP totally off.
+ * Observed that the worst case is 2s. Pick a safe vale.
+ */
+#define FORCE_OFF_RESPONSE_TIMEOUT (4 * SECOND)
+
/* Wait for polling the AP on signal */
#define PMIC_POWER_AP_WAIT (1 * MSEC)
@@ -76,9 +82,6 @@
/* Delay between power-on the system and power-on the PMIC */
#define SYSTEM_POWER_ON_DELAY (10 * MSEC)
-/* Delay between power-off the system and all things (PMIC/AP) expected off */
-#define SYSTEM_POWER_OFF_DELAY (350 * MSEC)
-
/* TODO(crosbug.com/p/25047): move to HOOK_POWER_BUTTON_CHANGE */
/* 1 if the power button was pressed last time we checked */
static char power_button_was_pressed;
@@ -240,8 +243,8 @@ static int is_system_powered(void)
*/
static int is_pmic_pwron(void)
{
- /* Use PS_HOLD to indicate PMIC/AP is on/off */
- return gpio_get_level(GPIO_PS_HOLD);
+ /* Use POWER_GOOD to indicate PMIC/AP is on/off */
+ return gpio_get_level(GPIO_POWER_GOOD);
}
/**
@@ -249,8 +252,9 @@ static int is_pmic_pwron(void)
*
* @param enable 1 to wait the PMIC/AP on.
0 to wait the PMIC/AP off.
+ * @param timeout Number of microsecond of timeout.
*/
-static void wait_pmic_pwron(int enable)
+static void wait_pmic_pwron(int enable, unsigned int timeout)
{
timestamp_t poll_deadline;
@@ -259,7 +263,7 @@ static void wait_pmic_pwron(int enable)
return;
poll_deadline = get_time();
- poll_deadline.val += PMIC_POWER_AP_RESPONSE_TIMEOUT;
+ poll_deadline.val += timeout;
while (enable != is_pmic_pwron() &&
get_time().val < poll_deadline.val) {
usleep(PMIC_POWER_AP_WAIT);
@@ -293,22 +297,18 @@ static void set_pmic_pwron(int enable)
/*
* Power-on sequence:
* 1. Hold down PMIC_KPD_PWR_ODL, which is a power-on trigger
- * 2. PM845 pulls up AP_RST_L signal to power-on SDM845
- * 3. SDM845 pulls up PS_HOLD signal
- * 4. Wait for PS_HOLD up
- * 5. Release PMIC_KPD_PWR_ODL
+ * 2. PM845 supplies power to POWER_GOOD
+ * 3. Release PMIC_KPD_PWR_ODL
*
* Power-off sequence:
* 1. Hold down PMIC_KPD_PWR_ODL and PM845_RESIN_L, which is a power-off
* trigger (requiring reprogramming PMIC registers to make
* PMIC_KPD_PWR_ODL + PM845_RESIN_L as a shutdown trigger)
- * 2. PM845 pulls down AP_RST_L signal to power-off SDM845 (requreing
+ * 2. PM845 stops supplying power to POWER_GOOD (requiring
* reprogramming PMIC to set the stage-1 and stage-2 reset timers to
* 0 such that the pull down happens just after the deboucing time
* of the trigger, like 2ms)
- * 3. SDM845 pulls down PS_HOLD signal
- * 4. Wait for PS_HOLD down
- * 5. Release PMIC_KPD_PWR_ODL and PM845_RESIN_L
+ * 3. Release PMIC_KPD_PWR_ODL and PM845_RESIN_L
*
* If the above PMIC registers not programmed or programmed wrong, it
* falls back to the next functions, which cuts off the system power.
@@ -317,7 +317,7 @@ static void set_pmic_pwron(int enable)
gpio_set_level(GPIO_PMIC_KPD_PWR_ODL, 0);
if (!enable)
gpio_set_level(GPIO_PM845_RESIN_L, 0);
- wait_pmic_pwron(enable);
+ wait_pmic_pwron(enable, PMIC_POWER_AP_RESPONSE_TIMEOUT);
gpio_set_level(GPIO_PMIC_KPD_PWR_ODL, 1);
if (!enable)
gpio_set_level(GPIO_PM845_RESIN_L, 1);
@@ -387,8 +387,8 @@ static void power_off(void)
/* Force to switch off all rails */
set_system_power(0);
- /* Wait longer to ensure the PMIC/AP totally off */
- usleep(SYSTEM_POWER_OFF_DELAY);
+ /* If it is forced down, wait to ensure POWER_GOOD down */
+ wait_pmic_pwron(0, FORCE_OFF_RESPONSE_TIMEOUT);
/* Turn off the 5V rail. */
#ifdef CONFIG_POWER_PP5000_CONTROL