diff --git a/board/cr50/board.c b/board/cr50/board.c index ccdc4a626f..96182c7865 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -139,7 +139,6 @@ void pmu_wakeup_interrupt(void) /* Trigger timer1 interrupt */ if (wakeup_src & GC_PMU_EXITPD_SRC_TIMELS0_PD_EXIT_TIMER1_MASK) task_trigger_irq(GC_IRQNUM_TIMELS0_TIMINT1); - } DECLARE_IRQ(GC_IRQNUM_PMU_INTR_WAKEUP_INT, pmu_wakeup_interrupt, 1); @@ -402,15 +401,19 @@ void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, memcpy(p_sha, sha1_digest, sha_len); } -static void device_state_changed(enum device_type device, +static int device_state_changed(enum device_type device, enum device_state state) { + int state_changed = state != device_states[device].last_known_state; + device_set_state(device, state); /* * We've determined the device state, so cancel any deferred callbacks. */ hook_call_deferred(device_states[device].deferred, -1); + + return state_changed; } /* @@ -426,12 +429,13 @@ static int servo_state_unknown(void) return 0; } -static void device_powered_off(enum device_type device, int uart) +static int device_powered_off(enum device_type device, int uart) { if (device_get_state(device) == DEVICE_STATE_ON) - return; + return EC_ERROR_UNKNOWN; - device_state_changed(device, DEVICE_STATE_OFF); + if (!device_state_changed(device, DEVICE_STATE_OFF)) + return EC_ERROR_UNKNOWN; if (uart) { /* Disable RX and TX on the UART peripheral */ @@ -440,6 +444,7 @@ static void device_powered_off(enum device_type device, int uart) /* Disconnect the TX pin from the UART peripheral */ uartn_tx_disconnect(uart); } + return EC_SUCCESS; } static void servo_deferred(void) @@ -453,7 +458,8 @@ DECLARE_DEFERRED(servo_deferred); static void ap_deferred(void) { - device_powered_off(DEVICE_AP, UART_AP); + if (device_powered_off(DEVICE_AP, UART_AP) == EC_SUCCESS) + hook_notify(HOOK_CHIPSET_SHUTDOWN); } DECLARE_DEFERRED(ap_deferred); @@ -482,10 +488,12 @@ struct device_config device_states[] = { }; BUILD_ASSERT(ARRAY_SIZE(device_states) == DEVICE_COUNT); -static void device_powered_on(enum device_type device, int uart) +/* Returns EC_SUCCESS if the device state changed to on */ +static int device_powered_on(enum device_type device, int uart) { /* Update the device state */ - device_state_changed(device, DEVICE_STATE_ON); + if (!device_state_changed(device, DEVICE_STATE_ON)) + return EC_ERROR_UNKNOWN; /* Enable RX and TX on the UART peripheral */ uartn_enable(uart); @@ -494,6 +502,8 @@ static void device_powered_on(enum device_type device, int uart) if (device_get_state(DEVICE_SERVO) != DEVICE_STATE_ON && !uartn_enabled(uart)) uartn_tx_connect(uart); + + return EC_SUCCESS; } static void servo_attached(void) @@ -515,7 +525,8 @@ void device_state_on(enum gpio_signal signal) switch (signal) { case GPIO_DETECT_AP: - device_powered_on(DEVICE_AP, UART_AP); + if (device_powered_on(DEVICE_AP, UART_AP) == EC_SUCCESS) + hook_notify(HOOK_CHIPSET_RESUME); break; case GPIO_DETECT_EC: device_powered_on(DEVICE_EC, UART_EC); @@ -546,10 +557,13 @@ void board_update_device_state(enum device_type device) gpio_enable_interrupt(device_states[device].detect); /* - * Wait a bit. If cr50 detects this device is ever powered on - * during this time then the status wont be set to powered off. + * The signal is low now, but the detect signals are on UART RX + * which may be receiving something. Wait long enough for an + * entire data chunk to be sent to declare that the device is + * off. If the detect signal remains low for 100us then the + * signal is low because the device is off. */ - hook_call_deferred(device_states[device].deferred, 50); + hook_call_deferred(device_states[device].deferred, 100); } } diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index a01c35cea7..ac2557ef3e 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -102,17 +102,12 @@ void rdd_attached(void) ccd_set_mode(CCD_MODE_ENABLED); enable_usb_wakeup = 1; - uartn_tx_connect(UART_AP); - /* Enable device state monitoring */ - device_detect_state_enable(1); + uartn_tx_connect(UART_AP); } void rdd_detached(void) { - /* Disable device state monitoring */ - device_detect_state_enable(0); - /* Disconnect from AP and EC UART TX peripheral from gpios */ uartn_tx_disconnect(UART_EC); uartn_tx_disconnect(UART_AP); diff --git a/common/device_state.c b/common/device_state.c index 0c4024880a..17c32a7054 100644 --- a/common/device_state.c +++ b/common/device_state.c @@ -7,8 +7,6 @@ #include "device_state.h" #include "hooks.h" -static int enabled = 1; - int device_get_state(enum device_type device) { return device_states[device].state; @@ -19,6 +17,9 @@ void device_set_state(enum device_type device, enum device_state state) if (device_states[device].state == state) return; + if (state != DEVICE_STATE_UNKNOWN) + device_states[device].last_known_state = state; + device_states[device].state = state; } @@ -26,57 +27,11 @@ static void check_device_state(void) { int i; - if (!enabled) - return; - for (i = 0; i < DEVICE_COUNT; i++) board_update_device_state(i); } DECLARE_HOOK(HOOK_SECOND, check_device_state, HOOK_PRIO_DEFAULT); -static int device_has_interrupts(enum device_type device) -{ - return (device_states[device].deferred && - device_states[device].detect != GPIO_COUNT); -} - -static void disable_interrupts(enum device_type device) -{ - if (!device_has_interrupts(device)) - return; - - /* Cancel any deferred callbacks */ - hook_call_deferred(device_states[device].deferred, -1); - - /* Disable gpio interrupts */ - gpio_disable_interrupt(device_states[device].detect); -} - -static void enable_interrupts(enum device_type device) -{ - if (!device_has_interrupts(device)) - return; - - /* Enable gpio interrupts */ - gpio_enable_interrupt(device_states[device].detect); -} - -void device_detect_state_enable(int enable) -{ - int i; - - enabled = enable; - for (i = 0; i < DEVICE_COUNT; i++) { - if (enabled) { - enable_interrupts(i); - board_update_device_state(i); - } else { - disable_interrupts(i); - device_set_state(i, DEVICE_STATE_UNKNOWN); - } - } -} - static void print_state(const char *name, enum device_state state) { ccprintf("%-9s %s\n", name, state == DEVICE_STATE_ON ? "on" : @@ -87,12 +42,9 @@ static int command_devices(int argc, char **argv) { int i; - if (!enabled) - ccprintf("Device monitoring disabled\n"); - else - for (i = 0; i < DEVICE_COUNT; i++) - print_state(device_states[i].name, - device_states[i].state); + for (i = 0; i < DEVICE_COUNT; i++) + print_state(device_states[i].name, + device_states[i].state); return EC_SUCCESS; } diff --git a/include/device_state.h b/include/device_state.h index 1ad78f002c..379cdb2f47 100644 --- a/include/device_state.h +++ b/include/device_state.h @@ -19,6 +19,7 @@ enum device_state { struct device_config { const char *name; /* Device name */ enum device_state state; /* Device status */ + enum device_state last_known_state; /* Either off or on */ /* Deferred handler to detect power off */ const struct deferred_data *deferred; enum gpio_signal detect; /* GPIO detecting power on */ @@ -41,11 +42,4 @@ void device_set_state(enum device_type device, enum device_state state); /* Update the device state based on the device gpios */ void board_update_device_state(enum device_type device); - -/** - * Enables or disables all device gpio interrupts - * - * @param enable enable or disable detection - */ -void device_detect_state_enable(int enable); #endif /* __CROS_DEVICE_STATE_H */