diff options
author | Randall Spangler <rspangler@chromium.org> | 2017-09-29 13:08:59 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-09-29 20:16:20 -0700 |
commit | 7d816dbff5ef3ad22d16e1f8b39c2afcfa418275 (patch) | |
tree | 8d79664ef1772c0e5bfe425bcaa9b661028229a2 /board/cr50/rdd.c | |
parent | 90d8e5460f0f42d52a48b78843130c00b9cb6766 (diff) | |
download | chrome-ec-7d816dbff5ef3ad22d16e1f8b39c2afcfa418275.tar.gz |
cr50: Add ccdblock command to block ports
Currently, when CCD is opened, there is no way to disable the EC
and/or AP UARTs. But if there is some problem with the EC and/or AP,
and their UARTs are spamming interrupts, it can make debugging more
difficult.
If servo detection malfunctions, then CCD may drive the ports and
interfere with servo.
Add a new ccdblock command to disable the AP UART, EC UART, or any
ports shared with servo, until the next cr50 reboot.
BUG=b:65639347
BRANCH=cr50
TEST=manual with CR50_DEV=1 image, AP/EC powered on, suzyq connected
ccdblock --> (none)
ccdstate --> UARTAP+TX UARTEC+TX I2C SPI
ccdblock AP on
ccdstate --> UARTEC+TX I2C SPI
ccdblock EC on
ccdstate --> I2C SPI
ccdblock -> AP EC
ccdblock AP off
ccdstate --> UARTAP+TX I2C SPI
ccdblock EC off --> (none)
ccdstate --> UARTAP+TX UARTEC+TX I2C SPI
ccdblock SERVO on
ccdstate --> UARTAP UARTEC
ccd lock
ccdblock AP on --> access denied
Change-Id: I3dcc8314fc98a17af57f2fe0d150ecd1a19ccf52
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/693041
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
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"); |