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-16 20:04:08 +0000
commit8abd61c61d15953409fe9f9f89cb6d761c9982df (patch)
tree2b63bd73c3efff763e5801f917dff82f0921d4ea
parent1f47c92c3aa108cc2b2d2a7d6ae20dc0f46dd3db (diff)
downloadchrome-ec-8abd61c61d15953409fe9f9f89cb6d761c9982df.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/+/3824925 Tested-by: Pablo Ceballos <pceballos@chromium.org> Auto-Submit: Pablo Ceballos <pceballos@chromium.org> Reviewed-by: Bruce Goodwin <bgoodwin@chromium.org> Commit-Queue: Bruce Goodwin <bgoodwin@chromium.org>
-rw-r--r--common/chipset.c16
-rw-r--r--common/power_button.c5
-rw-r--r--include/chipset.h13
3 files changed, 33 insertions, 1 deletions
diff --git a/common/chipset.c b/common/chipset.c
index 209334add5..01323d3a30 100644
--- a/common/chipset.c
+++ b/common/chipset.c
@@ -125,5 +125,19 @@ get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries,
return EC_SUCCESS;
}
-#endif /* !CONFIG_AP_RESET_LOG */
+enum chipset_shutdown_reason chipset_get_shutdown_reason(void)
+{
+ enum chipset_shutdown_reason reason = 0;
+
+ 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 2b4668b733..daf5ad7dd5 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"
@@ -127,6 +128,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 8664f6ecf3..2e1554293a 100644
--- a/include/chipset.h
+++ b/include/chipset.h
@@ -285,6 +285,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) { }
@@ -296,6 +304,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 0;
+}
+
#endif /* !CONFIG_CMD_AP_RESET_LOG */
#endif /* __CROS_EC_CHIPSET_H */