summaryrefslogtreecommitdiff
path: root/power
diff options
context:
space:
mode:
authorEric Yilun Lin <yllin@chromium.org>2023-03-15 10:56:43 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-15 10:38:26 +0000
commitf27b843a9b1f289b32277b8f04bf59dc8a130b73 (patch)
treecda09d73e0fd22a00555aaa75513bc4ff0600dd7 /power
parent1fb66a343d42b8829823d3d3ae6bc4ccd390ff41 (diff)
downloadchrome-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.c38
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,