diff --git a/board/cr50/board.c b/board/cr50/board.c index 0ba8712bf2..f2c1b99569 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -322,24 +322,32 @@ struct device_config device_states[] = { [DEVICE_SERVO_AP] = { .deferred = &servo_ap_deferred_data, .detect_on = GPIO_SERVO_UART1_ON, - .detect_off = GPIO_SERVO_UART1_OFF + .detect_off = GPIO_SERVO_UART1_OFF, + .name = "Servo AP" }, [DEVICE_SERVO_EC] = { .deferred = &servo_ec_deferred_data, .detect_on = GPIO_SERVO_UART2_ON, - .detect_off = GPIO_SERVO_UART2_OFF + .detect_off = GPIO_SERVO_UART2_OFF, + .name = "Servo EC" }, [DEVICE_AP] = { .deferred = &ap_deferred_data, .detect_on = GPIO_AP_ON, - .detect_off = GPIO_AP_OFF + .detect_off = GPIO_AP_OFF, + .name = "AP" }, [DEVICE_EC] = { .deferred = &ec_deferred_data, .detect_on = GPIO_EC_ON, - .detect_off = GPIO_EC_OFF + .detect_off = GPIO_EC_OFF, + .name = "EC" + }, + [DEVICE_SERVO] = { + .detect_on = GPIO_COUNT, + .detect_off = GPIO_COUNT, + .name = "Servo" }, - [DEVICE_SERVO] = {}, }; BUILD_ASSERT(ARRAY_SIZE(device_states) == DEVICE_COUNT); @@ -448,23 +456,3 @@ void board_update_device_state(enum device_type device) hook_call_deferred(device_states[device].deferred, 50); } } - -static void print_state(const char *name, enum device_state state) -{ - ccprintf("%s %s\n", name, state == DEVICE_STATE_ON ? "on" : - state == DEVICE_STATE_OFF ? "off" : "unknown"); -} -static int command_devices(int argc, char **argv) -{ - - print_state("AP", device_get_state(DEVICE_AP)); - print_state("EC", device_get_state(DEVICE_EC)); - print_state("Servo", device_get_state(DEVICE_SERVO)); - print_state(" AP", device_get_state(DEVICE_SERVO_AP)); - print_state(" EC", device_get_state(DEVICE_SERVO_EC)); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(devices, command_devices, - "", - "Get the AP, EC, and servo device states", - NULL); diff --git a/board/cr50/board.h b/board/cr50/board.h index 6c1ba85795..0bfc3eaa53 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -109,11 +109,11 @@ enum usb_strings { /* Device indexes */ enum device_type { - DEVICE_SERVO_AP = 0, - DEVICE_SERVO_EC, - DEVICE_AP, + DEVICE_AP = 0, DEVICE_EC, DEVICE_SERVO, + DEVICE_SERVO_AP, + DEVICE_SERVO_EC, DEVICE_COUNT }; diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index beefc761dd..2aab5be6a3 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -27,6 +27,11 @@ static struct uart_config uarts[] = { [UART_EC] = {"EC", DEVICE_EC, GC_PINMUX_UART2_TX_SEL}, }; +static int ccd_is_enabled(void) +{ + return !gpio_get_level(GPIO_CCD_MODE_L); +} + /* If the UART TX is enabled the pinmux select will have a non-zero value */ int uartn_enabled(int uart) { @@ -51,7 +56,7 @@ static int servo_is_connected(void) void uartn_tx_connect(int uart) { - if (!uart_enabled) + if (!uart_enabled || !ccd_is_enabled()) return; if (servo_is_connected()) { @@ -81,18 +86,30 @@ void rdd_attached(void) /* Indicate case-closed debug mode (active low) */ gpio_set_level(GPIO_CCD_MODE_L, 0); + /* Enable CCD */ ccd_set_mode(CCD_MODE_ENABLED); + + /* Enable device state monitoring */ + device_detect_state_enable(1); } void rdd_detached(void) { - /* Disconnect from AP and EC UART TX */ + /* 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); + /* Disable the AP and EC UART peripheral */ + uartn_disable(UART_AP); + uartn_disable(UART_EC); + /* Done with case-closed debug mode */ gpio_set_level(GPIO_CCD_MODE_L, 1); + /* Disable CCD */ ccd_set_mode(CCD_MODE_DISABLED); } @@ -118,9 +135,8 @@ static int command_ccd(int argc, char **argv) return EC_ERROR_PARAM1; } - ccprintf("CCD: %s\n", !gpio_get_level(GPIO_CCD_MODE_L) ? - " enabled" : "disabled"); - ccprintf("AP UART: %s\nEC UART: %s\n", + ccprintf("CCD: %s\nAP UART: %s\nEC UART: %s\n", + ccd_is_enabled() ? " enabled" : "disabled", uartn_enabled(UART_AP) ? " enabled" : "disabled", uartn_enabled(UART_EC) ? " enabled" : "disabled"); return EC_SUCCESS; diff --git a/common/device_state.c b/common/device_state.c index 2b3f969d4c..650e2671ef 100644 --- a/common/device_state.c +++ b/common/device_state.c @@ -3,9 +3,12 @@ * found in the LICENSE file. */ +#include "console.h" #include "device_state.h" #include "hooks.h" +static int enabled = 1; + int device_get_state(enum device_type device) { return device_states[device].state; @@ -23,7 +26,80 @@ 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_on != GPIO_COUNT && + device_states[device].detect_off != 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_on); + gpio_disable_interrupt(device_states[device].detect_off); +} + +static void enable_interrupts(enum device_type device) +{ + if (!device_has_interrupts(device)) + return; + + /* Enable gpio interrupts */ + gpio_enable_interrupt(device_states[device].detect_on); + gpio_enable_interrupt(device_states[device].detect_off); +} + +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" : + state == DEVICE_STATE_OFF ? "off" : "unknown"); +} + +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); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(devices, command_devices, + "", + "Get the device states", + NULL); diff --git a/include/device_state.h b/include/device_state.h index 1af3972bfb..d7ff0661dc 100644 --- a/include/device_state.h +++ b/include/device_state.h @@ -17,20 +17,36 @@ enum device_state { }; struct device_config { - enum device_state state; - int state_change; + const char *name; /* Device name */ + enum device_state state; /* Device status */ + /* Deferred handler to detect power off */ const struct deferred_data *deferred; - enum gpio_signal detect_on; - enum gpio_signal detect_off; + enum gpio_signal detect_on; /* GPIO detecting power on */ + enum gpio_signal detect_off; /* GPIO detecting power off */ }; enum device_type; extern struct device_config device_states[]; +/* Return the device state */ int device_get_state(enum device_type device); +/** + * Sets the device state + * + * @param device the device to update + * @param state the new device state + */ 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 */