summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Ceballos <pceballos@google.com>2022-08-12 00:03:53 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-08-15 18:19:05 +0000
commit6d446440a610eaae41de38bb54f7bdc5860cffc9 (patch)
treefd14256f69722d4248272f2c2c8a6bedec026e87
parent003f969d94550ee09c3de16de6430fd7c98f4a10 (diff)
downloadchrome-ec-6d446440a610eaae41de38bb54f7bdc5860cffc9.tar.gz
power: Don't set the AP_IDLE flag if a power failure occurred
The AP_IDLE flag prevents the AP from automatically starting up. This is normally applied when the device has shut down cleanly. If the device has experienced power loss and has not shut down cleanly, the AP power state should be restored when power is restored. With some power supplies, the voltage drops slowly when the AC power is disconnected. This can cause the EC to detect that there is a power failure on some higher voltage rails while it continues to be powered for a short while from a lower voltage rail. In such a scenario, the EC can actually have enough time to complete all of the S0->S3->S5 power state transitions and trigger the chipset_shutdown hook that sets the AP_IDLE flag. BUG=b:239979405 TEST=Manually tested AC hotplug behavior on moonbuggy board BRANCH=none Change-Id: I82ec3c481fc62c79b5798b4d52f025a2825546f4 Signed-off-by: Pablo Ceballos <pceballos@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3824922 Reviewed-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: Pablo Ceballos <pceballos@chromium.org> Commit-Queue: Pablo Ceballos <pceballos@chromium.org>
-rw-r--r--common/chipset.c15
-rw-r--r--common/power_button.c5
-rw-r--r--include/chipset.h13
3 files changed, 33 insertions, 0 deletions
diff --git a/common/chipset.c b/common/chipset.c
index 4a3582d5ae..a640afcdd7 100644
--- a/common/chipset.c
+++ b/common/chipset.c
@@ -118,4 +118,19 @@ get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries,
return EC_SUCCESS;
}
+enum chipset_shutdown_reason chipset_get_shutdown_reason(void)
+{
+ enum chipset_shutdown_reason reason = CHIPSET_RESET_UNKNOWN;
+
+ mutex_lock(&reset_log_mutex);
+ if (ap_resets_since_ec_boot != 0) {
+ int i = (next_reset_log == 0) ? ARRAY_SIZE(reset_logs) - 1 :
+ next_reset_log - 1;
+ reason = reset_logs[i].reset_cause;
+ }
+ mutex_unlock(&reset_log_mutex);
+
+ return reason;
+}
+
#endif /* !CONFIG_AP_RESET_LOG */
diff --git a/common/power_button.c b/common/power_button.c
index 0f84fbb3f1..9fd4cbdb36 100644
--- a/common/power_button.c
+++ b/common/power_button.c
@@ -6,6 +6,7 @@
/* Power button module for Chrome EC */
#include "button.h"
+#include "chipset.h"
#include "common.h"
#include "console.h"
#include "gpio.h"
@@ -135,6 +136,10 @@ DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pb_chipset_startup, HOOK_PRIO_DEFAULT);
static void pb_chipset_shutdown(void)
{
+ /* Don't set AP_IDLE if shutting down due to power failure. */
+ if (chipset_get_shutdown_reason() == CHIPSET_SHUTDOWN_POWERFAIL)
+ return;
+
chip_save_reset_flags(chip_read_reset_flags() | EC_RESET_FLAG_AP_IDLE);
system_set_reset_flags(EC_RESET_FLAG_AP_IDLE);
CPRINTS("Saved AP_IDLE flag");
diff --git a/include/chipset.h b/include/chipset.h
index c049452bb8..874bf59548 100644
--- a/include/chipset.h
+++ b/include/chipset.h
@@ -263,6 +263,14 @@ get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries,
size_t num_reset_log_entries,
uint32_t *resets_since_ec_boot);
+/**
+ * Check the reason given in the last call to report_ap_reset() .
+ *
+ * @return Reason argument that was passed to the last call to
+ * report_ap_reset(). Zero if report_ap_reset() has not been called.
+ */
+enum chipset_shutdown_reason chipset_get_shutdown_reason(void);
+
#else
static inline void report_ap_reset(enum chipset_shutdown_reason reason)
@@ -276,6 +284,11 @@ get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries,
return EC_SUCCESS;
}
+static inline enum chipset_shutdown_reason chipset_get_shutdown_reason(void)
+{
+ return CHIPSET_RESET_UNKNOWN;
+}
+
#endif /* !CONFIG_CMD_AP_RESET_LOG */
#endif /* __CROS_EC_CHIPSET_H */