diff options
-rw-r--r-- | board/cr50/ap_state.c | 96 | ||||
-rw-r--r-- | board/cr50/board.c | 19 | ||||
-rw-r--r-- | board/cr50/board.h | 1 | ||||
-rw-r--r-- | board/cr50/gpio.inc | 6 |
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 */ |