summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/ap_state.c96
-rw-r--r--board/cr50/board.c19
-rw-r--r--board/cr50/board.h1
-rw-r--r--board/cr50/gpio.inc6
4 files changed, 55 insertions, 67 deletions
diff --git a/board/cr50/ap_state.c b/board/cr50/ap_state.c
index d4f549940a..32064ae07c 100644
--- a/board/cr50/ap_state.c
+++ b/board/cr50/ap_state.c
@@ -22,8 +22,7 @@ void print_ap_state(void)
int ap_is_on(void)
{
- /* Debouncing and on are both still on */
- return (state == DEVICE_STATE_DEBOUNCING || state == DEVICE_STATE_ON);
+ return state == DEVICE_STATE_ON;
}
/**
@@ -47,9 +46,10 @@ static void set_state(enum device_state new_state)
}
/**
- * Set AP to the off state
+ * Set AP to the off state. Disable functionality that should only be available
+ * when the AP is on.
*/
-static void set_ap_off(void)
+static void deferred_set_ap_off(void)
{
CPRINTS("AP off");
set_state(DEVICE_STATE_OFF);
@@ -77,12 +77,14 @@ static void set_ap_off(void)
if (board_deep_sleep_allowed())
enable_deep_sleep();
}
+DECLARE_DEFERRED(deferred_set_ap_off);
/**
* Move the AP to the ON state
*/
void set_ap_on(void)
{
+ hook_call_deferred(&deferred_set_ap_off_data, -1);
CPRINTS("AP on");
set_state(DEVICE_STATE_ON);
@@ -99,62 +101,48 @@ void set_ap_on(void)
disable_deep_sleep();
}
-/**
- * Detect state machine
+/*
+ * If TPM_RST_L is asserted, the AP is in reset. Disable all AP functionality
+ * in 1 second if it remains asserted.
*/
-static void ap_detect(void)
+void tpm_rst_asserted(enum gpio_signal unused)
{
- /* Handle detecting device */
- if (gpio_get_level(GPIO_TPM_RST_L)) {
- /*
- * It is important to check if the AP is already 'on' here, so
- * we don't call tpm_rst_deasserted() when the AP is already on.
- *
- * If we were debouncing ON->OFF, cancel debouncing and go back
- * to the ON state.
- */
- if (state == DEVICE_STATE_DEBOUNCING)
- set_state(DEVICE_STATE_ON);
- /* If AP is already on, nothing needs to be done */
- if (state == DEVICE_STATE_ON)
- return;
-
- /*
- * The platform reset handler has not run yet; otherwise, it
- * would have already turned the AP on and we wouldn't get here.
- *
- * This can happen if the hook task calls ap_detect() before
- * deferred_tpm_rst_isr(). In this case, the deferred handler is
- * already pending so calling the ISR has no effect.
- *
- * But we may actually have missed the edge. In that case,
- * calling the ISR makes sure we don't miss the reset. It will
- * call set_ap_on() to move the AP to the ON state.
- */
- CPRINTS("AP detect calling tpm_rst_deasserted()");
- tpm_rst_deasserted(GPIO_TPM_RST_L);
- return;
- }
+ CPRINTS("%s", __func__);
- /* TPM_RST_L is asserted. If we're already off, done. */
- if (state == DEVICE_STATE_OFF)
- return;
+ /*
+ * It's possible the signal is being pulsed. Wait 1 second to disable
+ * functionality, so it's more likely the AP is fully off and not being
+ * reset.
+ */
+ hook_call_deferred(&deferred_set_ap_off_data, SECOND);
- /* If we were debouncing, we're now sure we're off */
- if (state == DEVICE_STATE_DEBOUNCING ||
- state == DEVICE_STATE_INIT_DEBOUNCING) {
- set_ap_off();
- return;
- }
+ set_state(DEVICE_STATE_DEBOUNCING);
+}
+/**
+ * Check the initial AP state.
+ */
+static void init_ap_detect(void)
+{
+ /* Enable interrupts for AP state detection */
+ gpio_enable_interrupt(GPIO_TPM_RST_L);
+ gpio_enable_interrupt(GPIO_DETECT_TPM_RST_L_ASSERTED);
/*
- * Otherwise, we were on before and haven't detected the AP off. We
- * don't know if thats because the AP is actually off, or because the
- * TPM_RST_L signal is being pulsed for a short reset. Start debouncing.
+ * Enable TPM reset GPIO interrupt.
+ *
+ * If the TPM_RST_L signal is already high when cr50 wakes up or
+ * transitions to high before we are able to configure the gpio then we
+ * will have missed the edge and the tpm reset isr will not get
+ * called. Check that we haven't already missed the rising edge. If we
+ * have alert tpm_rst_isr.
*/
- if (state == DEVICE_STATE_INIT)
- set_state(DEVICE_STATE_INIT_DEBOUNCING);
+ if (gpio_get_level(GPIO_TPM_RST_L))
+ tpm_rst_deasserted(GPIO_TPM_RST_L);
else
- set_state(DEVICE_STATE_DEBOUNCING);
+ tpm_rst_asserted(GPIO_TPM_RST_L);
}
-DECLARE_HOOK(HOOK_SECOND, ap_detect, HOOK_PRIO_DEFAULT);
+/*
+ * TPM_RST_L isn't setup until board_init. Make sure init_ap_detect happens
+ * after that.
+ */
+DECLARE_HOOK(HOOK_INIT, init_ap_detect, HOOK_PRIO_DEFAULT + 1);
diff --git a/board/cr50/board.c b/board/cr50/board.c
index e7e19a4577..3aa3693f16 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -582,7 +582,10 @@ static void configure_board_specific_gpios(void)
*/
if (board_use_plt_rst()) {
/* Use plt_rst_l as the tpm reset signal. */
+ /* Select for TPM_RST_L */
GWRITE(PINMUX, GPIO1_GPIO0_SEL, GC_PINMUX_DIOM3_SEL);
+ /* Select for DETECT_TPM_RST_L_ASSERTED */
+ GWRITE(PINMUX, GPIO1_GPIO4_SEL, GC_PINMUX_DIOM3_SEL);
/* Enable the input */
GWRITE_FIELD(PINMUX, DIOM3_CTL, IE, 1);
@@ -604,7 +607,10 @@ static void configure_board_specific_gpios(void)
GWRITE_FIELD(PINMUX, EXITEN0, DIOM3, 1);
} else {
/* Use sys_rst_l as the tpm reset signal. */
+ /* Select for TPM_RST_L */
GWRITE(PINMUX, GPIO1_GPIO0_SEL, GC_PINMUX_DIOM0_SEL);
+ /* Select for DETECT_TPM_RST_L_ASSERTED */
+ GWRITE(PINMUX, GPIO1_GPIO4_SEL, GC_PINMUX_DIOM0_SEL);
/* Enable the input */
GWRITE_FIELD(PINMUX, DIOM0_CTL, IE, 1);
@@ -738,19 +744,6 @@ static void board_init(void)
check_board_id_mismatch();
/*
- * Enable TPM reset GPIO interrupt.
- *
- * If the TPM_RST_L signal is already high when cr50 wakes up or
- * transitions to high before we are able to configure the gpio then we
- * will have missed the edge and the tpm reset isr will not get
- * called. Check that we haven't already missed the rising edge. If we
- * have alert tpm_rst_isr.
- */
- gpio_enable_interrupt(GPIO_TPM_RST_L);
- if (gpio_get_level(GPIO_TPM_RST_L))
- hook_call_deferred(&deferred_tpm_rst_isr_data, 0);
-
- /*
* Start monitoring AC detect to wake Cr50 from deep sleep. This is
* needed to detect RDD cable changes in deep sleep. AC detect is also
* used for battery cutoff software support on detachable devices.
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 527dcd3e01..352afdc04f 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -244,6 +244,7 @@ void ec_detect_asserted(enum gpio_signal signal);
void ec_tx_cr50_rx(enum gpio_signal signal);
void servo_detect_asserted(enum gpio_signal signal);
void tpm_rst_deasserted(enum gpio_signal signal);
+void tpm_rst_asserted(enum gpio_signal signal);
void post_reboot_request(void);
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index b686fe008a..cd9348fd2c 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -67,6 +67,12 @@ GPIO_INT(DETECT_EC_UART, PIN(1, 2), GPIO_INT_HIGH, ec_detect_asserted)
*/
GPIO_INT(DETECT_SERVO, PIN(1, 3), GPIO_INT_HIGH | GPIO_PULL_DOWN,
servo_detect_asserted)
+/*
+ * Whan TPM_RST_L is asserted, the AP is in reset. Use this for detecting when
+ * the AP is off.
+ */
+GPIO_INT(DETECT_TPM_RST_L_ASSERTED, PIN(1, 4), GPIO_INT_FALLING,
+ tpm_rst_asserted)
/*****************************************************************************/
/* NON STANDARD INTERRUPT GPIOs - handlers defined and configured in board.c */