summaryrefslogtreecommitdiff
path: root/board/cr50/ap_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/cr50/ap_state.c')
-rw-r--r--board/cr50/ap_state.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/board/cr50/ap_state.c b/board/cr50/ap_state.c
index 1dfd73af32..115f067c50 100644
--- a/board/cr50/ap_state.c
+++ b/board/cr50/ap_state.c
@@ -117,6 +117,17 @@ static void set_state(enum device_state new_state)
*/
static void deferred_set_ap_off(void)
{
+ /*
+ * It's important cr50 keeps INT_AP_L enabled whenever the AP is on.
+ * Check if TPM_RST_L is still asserted before touching the AP state or
+ * the INT_AP_L signal. It shouldn't be possible for TPM_RST_L to be
+ * deasserted in set_ap_off. Check the level just to be safe.
+ * Block the AP state change if it's deasserted.
+ */
+ if (gpio_get_level(GPIO_TPM_RST_L)) {
+ CPRINTS("AP: ovrd");
+ return;
+ }
CPRINTS("AP off");
set_state(DEVICE_STATE_OFF);
@@ -254,6 +265,31 @@ void board_closed_loop_reset(void)
tpm_rst_asserted(GPIO_TPM_RST_L);
}
+static void poll_ap_state(void)
+{
+ /*
+ * High means the AP is on. If cr50 thinks the AP is off, it missed an
+ * interrupt. Trigger the deasserted interrupt.
+ */
+ if (gpio_get_level(GPIO_TPM_RST_L)) {
+ /*
+ * If cr50 thinks the AP is off while TPM_RST_L is high, it
+ * missed a falling edge interrupt. Trigger it.
+ */
+ if (!ap_is_on()) {
+ CPRINTS("appoll: R-");
+ tpm_rst_deasserted(GPIO_TPM_RST_L);
+ }
+ } else if (ap_is_on()) {
+ /*
+ * If cr50 thinks the AP is on while TPM_RST_L is low, it missed
+ * a falling edge interrupt. Trigger it.
+ */
+ CPRINTS("appoll: -F");
+ tpm_rst_asserted(GPIO_TPM_RST_L);
+ }
+}
+DECLARE_HOOK(HOOK_SECOND, poll_ap_state, HOOK_PRIO_DEFAULT);
/**
* Check the initial AP state.
*/