diff options
Diffstat (limited to 'board/cr50/rdd.c')
-rw-r--r-- | board/cr50/rdd.c | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index 26a3f2b507..2f12db089f 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -28,6 +28,26 @@ USB_SPI_CONFIG(ccd_usb_spi, USB_IFACE_SPI, USB_EP_SPI); static enum device_state state = DEVICE_STATE_INIT; +/* Flags for CCD blocking */ +enum ccd_block_flags { + /* + * UARTs. Disabling these can be helpful if the AP or EC is doing + * something which creates an interrupt storm on these ports. + */ + CCD_BLOCK_AP_UART = (1 << 0), + CCD_BLOCK_EC_UART = (1 << 1), + + /* + * Any ports shared with servo. Disabling these will stop CCD from + * interfering with servo, in the case where both CCD and servo is + * connected but servo isn't properly detected. + */ + CCD_BLOCK_SERVO_SHARED = (1 << 2) +}; + +/* Which UARTs are blocked by console command */ +static uint8_t ccd_block; + int ccd_ext_is_enabled(void) { return state == DEVICE_STATE_CONNECTED; @@ -217,7 +237,7 @@ static void ccd_state_change_hook(void) /* Then disable flags we can't have */ /* Servo takes over UART TX, I2C, and SPI */ - if (servo_is_connected()) + if (servo_is_connected() || (ccd_block & CCD_BLOCK_SERVO_SHARED)) flags_want &= ~(CCD_ENABLE_UART_AP_TX | CCD_ENABLE_UART_EC_TX | CCD_ENABLE_UART_EC_BITBANG | CCD_ENABLE_I2C | CCD_ENABLE_SPI); @@ -247,6 +267,12 @@ static void ccd_state_change_hook(void) if (flags_want & CCD_ENABLE_UART_EC_BITBANG) flags_want &= ~CCD_ENABLE_UART_EC_TX; + /* UARTs can be specifically blocked by console command */ + if (ccd_block & CCD_BLOCK_AP_UART) + flags_want &= ~CCD_ENABLE_UART_AP; + if (ccd_block & CCD_BLOCK_EC_UART) + flags_want &= ~CCD_ENABLE_UART_EC; + /* UARTs are either RX-only or RX+TX, so no RX implies no TX */ if (!(flags_want & CCD_ENABLE_UART_AP)) flags_want &= ~CCD_ENABLE_UART_AP_TX; @@ -353,6 +379,21 @@ static void ccd_ext_detect(void) } DECLARE_HOOK(HOOK_SECOND, ccd_ext_detect, HOOK_PRIO_DEFAULT); +static void print_ccd_ports_blocked(void) +{ + /* Regardless, print current state */ + ccputs("CCD ports blocked:"); + if (ccd_block & CCD_BLOCK_AP_UART) + ccputs(" AP"); + if (ccd_block & CCD_BLOCK_EC_UART) + ccputs(" EC"); + if (ccd_block & CCD_BLOCK_SERVO_SHARED) + ccputs(" SERVO"); + if (!ccd_block) + ccputs(" (none)"); + ccputs("\n"); +} + static int command_ccd_state(int argc, char **argv) { print_ap_state(); @@ -367,9 +408,45 @@ static int command_ccd_state(int argc, char **argv) print_state_flags(CC_COMMAND, get_state_flags()); ccprintf("\n"); + print_ccd_ports_blocked(); + return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(ccdstate, command_ccd_state, "", "Print the case closed debug device state"); +static int command_ccd_block(int argc, char **argv) +{ + uint8_t block_flag = 0; + int new_state; + + if (argc == 3) { + if (!strcasecmp(argv[1], "AP")) + block_flag = CCD_BLOCK_AP_UART; + else if (!strcasecmp(argv[1], "EC")) + block_flag = CCD_BLOCK_EC_UART; + else if (!strcasecmp(argv[1], "SERVO")) + block_flag = CCD_BLOCK_SERVO_SHARED; + else + return EC_ERROR_PARAM1; + + if (!parse_bool(argv[2], &new_state)) + return EC_ERROR_PARAM2; + + if (new_state) + ccd_block |= block_flag; + else + ccd_block &= ~block_flag; + + /* Update blocked state in deferred function */ + ccd_update_state(); + } + + print_ccd_ports_blocked(); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ccdblock, command_ccd_block, + "[<AP | EC | SERVO> [BOOLEAN]]", + "Force CCD ports disabled"); |