From 148c28c9f61a1d9633ef3570670c64f1acc76d64 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Tue, 28 Aug 2018 17:32:43 +0800 Subject: power/mt8183: Fix power sequencing Fix power sequencing: 1. Replace power_has_signals(...) with power_get_signals() & ... to reduce unwanted noise during boot 2. PMIC_FORCE_RESET only takes about 5ms to work. 3. In G3, switch back to S5->G3 if the PMIC happens to be on again. 4. On boot, start from S5 instead of G3 if the PMIC is on. 5. In S5->S3, retry to turn on PMIC if the first attempt fails (this is necessary after a force reset) BRANCH=none BUG=b:109850749 TEST=Cycles of apshutdown, powerbtn; EC reboot TEST=apshutdown, sysjump rw, powerbtn works properly Change-Id: I2e52e267eab9d45d30036f75cfd6b821d3b13638 Signed-off-by: Nicolas Boichat Reviewed-on: https://chromium-review.googlesource.com/1194546 Reviewed-by: Yilun Lin --- power/mt8183.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/power/mt8183.c b/power/mt8183.c index 221e315892..4522efcd02 100644 --- a/power/mt8183.c +++ b/power/mt8183.c @@ -43,6 +43,9 @@ #define PMIC_EN_PULSE_MS 50 +/* Maximum time it should for PMIC to turn on after toggling PMIC_EN_ODL. */ +#define PMIC_EN_TIMEOUT (300 * MSEC) + /* Data structure for a GPIO operation for power sequencing */ struct power_seq_op { /* enum gpio_signal in 8 bits */ @@ -135,6 +138,10 @@ enum power_state power_chipset_init(void) chipset_exit_hard_off(); } + /* Start from S5 if the PMIC is already up. */ + if (power_get_signals() & IN_PGOOD_PMIC) + return POWER_S5; + return POWER_G3; } @@ -160,14 +167,21 @@ static void power_seq_run(const struct power_seq_op *power_seq_ops, enum power_state power_handle_state(enum power_state state) { + /* Retry S5->S3 transition, if not zero. */ + static int s5s3_retry; + switch (state) { case POWER_G3: + /* Go back to S5->G3 if the PMIC unexpectedly starts again. */ + if (power_get_signals() & IN_PGOOD_PMIC) + return POWER_S5G3; break; case POWER_S5: if (forcing_shutdown) { return POWER_S5G3; } else { + s5s3_retry = 1; return POWER_S5S3; } break; @@ -197,7 +211,7 @@ enum power_state power_handle_state(enum power_state state) case POWER_S5S3: /* If PMIC is off, switch it on by pulsing PMIC enable. */ - if (!power_has_signals(IN_PGOOD_PMIC)) { + if (!(power_get_signals() & IN_PGOOD_PMIC)) { gpio_set_level(GPIO_PMIC_EN_ODL, 0); msleep(PMIC_EN_PULSE_MS); gpio_set_level(GPIO_PMIC_EN_ODL, 1); @@ -215,9 +229,20 @@ enum power_state power_handle_state(enum power_state state) chipset_reset(CHIPSET_RESET_INIT); } - /* Wait for PMIC to bring up rails. */ - if (power_wait_signals(IN_PGOOD_PMIC)) - return POWER_G3; + /* + * Wait for PMIC to bring up rails. Retry if it fails + * (it may take 2 attempts on restart after we use + * force reset). + */ + if (power_wait_signals_timeout(IN_PGOOD_PMIC, + PMIC_EN_TIMEOUT)) { + if (s5s3_retry) { + s5s3_retry = 0; + return POWER_S5S3; + } + /* Give up, go back to G3. */ + return POWER_S5G3; + } /* Enable S3 power supplies, release AP reset. */ power_seq_run(s5s3_power_seq, ARRAY_SIZE(s5s3_power_seq)); @@ -292,13 +317,14 @@ enum power_state power_handle_state(enum power_state state) * This should not happen if PMIC is configured properly, and * shuts down upon receiving WATCHDOG. */ - if (power_has_signals(IN_PGOOD_PMIC)) { + if (power_get_signals() & IN_PGOOD_PMIC) { #if defined(BOARD_KUKUI) && BOARD_REV == 0 CPRINTS("Cannot force PMIC off (rev0)"); #else CPRINTS("Forcing PMIC off"); gpio_set_level(GPIO_PMIC_FORCE_RESET_ODL, 0); - msleep(50); + msleep(5); + return POWER_S5G3; #endif } -- cgit v1.2.1