diff options
author | Eric Yilun Lin <yllin@chromium.org> | 2023-03-15 10:56:43 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-15 10:38:26 +0000 |
commit | f27b843a9b1f289b32277b8f04bf59dc8a130b73 (patch) | |
tree | cda09d73e0fd22a00555aaa75513bc4ff0600dd7 /power | |
parent | 1fb66a343d42b8829823d3d3ae6bc4ccd390ff41 (diff) | |
download | chrome-ec-f27b843a9b1f289b32277b8f04bf59dc8a130b73.tar.gz |
mt8186,mt8188: fix warm reset issued by servo and gsc
Fix the EC holding SYS_RST_ODL (AP reset) in S3S5. Only asserting the
SYS_RST_ODL with forcing shutdown. This will allow the AP to boot when
the servo or gsc releases SYS_RST_ODL.
When the AP is in reset, the power_state will be set to S5 first,
and the target should be G3 if the power state has been put to G3 by
S5 inactive timer. This is to prevent EN_PP4200_S5 and PMIC from being
turned off, which would prevent the AP from booting when SYS_RST_ODL
released if the AP reset was held by gsc or servo.
To make it clearer, only three cases that we need to consider:
1. SYS_RST_ODL is held by GSC or Servo
2. SYS_RST_ODL is asserted by AP itself, a gracefully shutdown
3. SYS_RST_ODL is asserted by EC.
For case 1, and 2, we don't need to assert SYS_RST_ODL, since the
EC is not the initiator.
BUG=b:267268982 b:273657518
TEST=On Steelix, and Geralt:
* Cold reset:
$ dut-control cold_reset:on sleep:0.2 cold_reset:off
Result: G3 -> S0
* Long power press to shutdown:
$ dut-control dut-control power_key:8.2
Result: S0 -> S5 -> G3
* Long power press to power-on but then shutdown:
$ dut-control dut-control power_key:9.2
Result: G3 -> S0 -> S5 -> G3
* Short power press to power-on:
$ dut-control dut-control power_key:tab
Result: G3 -> S0
* Console command: apreset
Result: S0 -> S0, AP reboots
* Console command: apshutdown
Result: S0 -> S5 -> G3
* Lid open to power-on:
$ dut-control lid_open:no sleep:0.2 lid_open:yes
Result: G3 -> S0
* AP console: reboot
Reulst: S0 -> S0
* AP console: poweroff
Reulst: S0 -> G3
* Short power press to power-on:
$ dut-control dut-control power_key:tab
Result: G3 -> S0
* Servo issue warm reset:
$ dut-control power_state:warm_reset
Result: S0 -> S5 -> S0
* Servo hold warm_reset and release:
$ dut-control warm_reset:on sleep:2 warm_reset:off
Result: S0 -> S5 -> S0
BRANCH=none
Change-Id: I81fc25a5088722487fbbf74d641a5edf4ad450e5
Signed-off-by: Eric Yilun Lin <yllin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4338758
Tested-by: Eric Yilun Lin <yllin@google.com>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Reviewed-by: Ting Shen <phoenixshen@chromium.org>
Auto-Submit: Eric Yilun Lin <yllin@google.com>
Diffstat (limited to 'power')
-rw-r--r-- | power/mt8186.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/power/mt8186.c b/power/mt8186.c index d5d5056ffc..0653c70ba0 100644 --- a/power/mt8186.c +++ b/power/mt8186.c @@ -82,6 +82,8 @@ static bool is_resetting; /* indicate MT8186 is processing a AP forcing shutdown. */ static bool is_shutdown; +/* indicate MT8186 has been dropped to S5G3 from the last IN_AP_RST state . */ +static bool is_s5g3_passed; /* * indicate exiting off state, and don't respect the power signals until chipset * on. @@ -213,15 +215,18 @@ static void power_reset_host_sleep_state(void) /* * Power state is determined from the following table: * - * | IN_AP_RST | IN_SUSPEND_ASSERTED | - * ---------------------------------------------- - * S0 | 0 | 0 | - * S3 | 0 | 1 | - * G3 | 1 | x | + * | IN_AP_RST | IN_SUSPEND_ASSERTED | is_s5g3_passed | + * -------------------------------------------------------- + * S0 | 0 | 0 | x| + * S3 | 0 | 1 | x| + * S5 | 1 | x | 0| + * G3 | 1 | x | 1| * - * S5 is only used when exit from G3 in power_common_state(). + * S5 is a temp stage, which will be put into G3 after s5_inactivity_timeout. * is_resetting flag indicate it's resetting chipset, and it's always S0. * is_shutdown flag indicates it's shutting down the AP, it goes for S5. + * is_s5g3_passed flag indicates it has shutdown from S5 to G3 since last + * shutdown. */ static enum power_state power_get_signal_state(void) { @@ -235,8 +240,12 @@ static enum power_state power_get_signal_state(void) return POWER_S0; if (is_shutdown) return POWER_S5; - if (power_get_signals() & IN_AP_RST) - return POWER_G3; + if (power_get_signals() & IN_AP_RST) { + /* If it has been put to G3 from S5 idle, then stay at G3.*/ + if (is_s5g3_passed) + return POWER_G3; + return POWER_S5; + } if (power_get_signals() & IN_SUSPEND_ASSERTED) return POWER_S3; return POWER_S0; @@ -311,6 +320,8 @@ enum power_state power_handle_state(enum power_state state) return POWER_S5S3; else if (next_state == POWER_G3) return POWER_S5G3; + else if (next_state == POWER_S5) + return POWER_S5; else return POWER_S5S3; @@ -342,6 +353,7 @@ enum power_state power_handle_state(enum power_state state) case POWER_S5S3: /* Off state exited. */ is_exiting_off = false; + is_s5g3_passed = false; hook_notify(HOOK_CHIPSET_PRE_INIT); power_signal_enable_interrupt(GPIO_AP_IN_SLEEP_L); @@ -415,7 +427,14 @@ enum power_state power_handle_state(enum power_state state) power_signal_disable_interrupt(GPIO_AP_IN_SLEEP_L); power_signal_disable_interrupt(GPIO_AP_EC_WDTRST_L); power_signal_disable_interrupt(GPIO_AP_EC_WARM_RST_REQ); - GPIO_SET_LEVEL(GPIO_SYS_RST_ODL, 0); + + /* Only actively reset AP with hard shutdown. + * For AP initiated shutdown, the AP has been reset by PMIC. + * For servo, gsc initiaed warm reset, EC doesn't need to hold + * it. + */ + if (is_shutdown) + GPIO_SET_LEVEL(GPIO_SYS_RST_ODL, 0); /* Call hooks before we remove power rails */ hook_notify(HOOK_CHIPSET_SHUTDOWN); @@ -432,6 +451,7 @@ enum power_state power_handle_state(enum power_state state) return POWER_S5; case POWER_S5G3: + is_s5g3_passed = true; #if DT_NODE_EXISTS(DT_NODELABEL(en_pp4200_s5)) if (power_wait_mask_signals_timeout(IN_PMIC_AP_RST, IN_PMIC_AP_RST, |