From 88025bd9551eb73e21221279df415a39444d076c Mon Sep 17 00:00:00 2001 From: Namyoon Woo Date: Thu, 23 Jan 2020 18:47:51 -0800 Subject: control EC USB-UART bridge This CL separates the control on USB-UART bridge of EC device from EC UART control. USB-UART bridge shall be enabled if CCD connection is detected and the CCD capability is enabled. Otherwise, EC USB-UART shall be disabled. By doing so, CCD capability can be observed even when EC-CR50 communication enables EC UART. This patch increases the flash usage by 204 bytes BUG=b:148247228 BRANCH=cr50, cr50_mp TEST=ran firmware_Cr50CCDServoCap on Helios. > ccd State: Locked Password: none Flags: 0x000001 Capabilities: 0000000000000000 ... > ccdstate AP: on AP UART: on EC: on Rdd: connected Servo: connected CCD EXT: enabled State flags: UARTAP UARTEC I2C USBEC > ccdstate AP: on AP UART: on EC: on Rdd: connected Servo: disconnected CCD EXT: enabled State flags: UARTAP+TX UARTEC USBEC CCD ports blocked: (none) > ccd State: Opened Password: none Flags: 0x800001 Capabilities: 5555454115000000 ... > ccdstate AP: on AP UART: on EC: on Rdd: connected Servo: connected CCD EXT: enabled State flags: UARTAP UARTEC I2C USBEC+TX CCD ports blocked: (none) > ccdstate AP: on AP UART: on EC: on Rdd: connected Servo: undetectable CCD EXT: enabled State flags: UARTAP+TX UARTEC+TX I2C SPI USBEC+TX CCD ports blocked: (none) Change-Id: I6bb560a05831105ff68a9e13e4b28b002ed98096 Signed-off-by: Namyoon Woo Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2018061 Reviewed-by: Vadim Bendebury Reviewed-by: Mary Ruthven --- board/cr50/rdd.c | 28 +++++++++++++++++++++++++- chip/g/usart.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++------- chip/g/usart.h | 9 +++++++++ 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index 21d1357df8..9cc217129c 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -15,6 +15,7 @@ #include "system.h" #include "uart_bitbang.h" #include "uartn.h" +#include "usart.h" #include "usb_api.h" #include "usb_console.h" #include "usb_i2c.h" @@ -134,6 +135,12 @@ enum ccd_state_flag { /* SPI port is enabled for AP and/or EC flash */ CCD_ENABLE_SPI = BIT(6), + + /* EC data bridging from UART to USB is enabled. */ + CCD_ENABLE_USB_FROM_UART_EC = BIT(7), + + /* EC data bridging from USB to UART is enabled. */ + CCD_ENABLE_USB_TO_UART_EC = BIT(8), }; int console_is_restricted(void) @@ -168,6 +175,11 @@ static uint32_t get_state_flags(void) if (ccd_usb_spi.state->enabled_device) flags_now |= CCD_ENABLE_SPI; + if (uart_ec_bridge_is_enabled()) + flags_now |= CCD_ENABLE_USB_FROM_UART_EC; + if (uart_ec_bridge_tx_is_enabled()) + flags_now |= CCD_ENABLE_USB_TO_UART_EC; + return flags_now; } @@ -193,6 +205,10 @@ static void print_state_flags(enum console_channel channel, uint32_t flags) cprintf(channel, " I2C"); if (flags & CCD_ENABLE_SPI) cprintf(channel, " SPI"); + if (flags & CCD_ENABLE_USB_FROM_UART_EC) + cprintf(channel, " USBEC"); + if (flags & CCD_ENABLE_USB_TO_UART_EC) + cprintf(channel, "+TX"); } static void ccd_state_change_hook(void) @@ -223,6 +239,8 @@ static void ccd_state_change_hook(void) */ if (ccd_ext_is_enabled()) flags_want |= (CCD_ENABLE_UART_AP_TX | CCD_ENABLE_UART_EC_TX | + CCD_ENABLE_USB_FROM_UART_EC | + CCD_ENABLE_USB_TO_UART_EC | CCD_ENABLE_I2C | CCD_ENABLE_SPI); else flags_want = 0; @@ -241,9 +259,14 @@ static void ccd_state_change_hook(void) if (!ccd_is_cap_enabled(CCD_CAP_GSC_TX_AP_RX)) flags_want &= ~CCD_ENABLE_UART_AP_TX; if (!ccd_is_cap_enabled(CCD_CAP_GSC_RX_EC_TX)) - flags_want &= ~CCD_ENABLE_UART_EC; + flags_want &= ~CCD_ENABLE_USB_FROM_UART_EC; + /* + * UART_EC TX needs to be disconnected as well as USB RX, otherwise + * Servo is not detectable. + */ if (!ccd_is_cap_enabled(CCD_CAP_GSC_TX_EC_RX)) flags_want &= ~(CCD_ENABLE_UART_EC_TX | + CCD_ENABLE_USB_TO_UART_EC | CCD_ENABLE_UART_EC_BITBANG); if (!ccd_is_cap_enabled(CCD_CAP_I2C)) flags_want &= ~CCD_ENABLE_I2C; @@ -272,6 +295,9 @@ static void ccd_state_change_hook(void) if (!(flags_want & CCD_ENABLE_UART_EC)) flags_want &= ~CCD_ENABLE_UART_EC_TX; + uart_ec_bridge_enable(flags_want & CCD_ENABLE_USB_FROM_UART_EC, + flags_want & CCD_ENABLE_USB_TO_UART_EC); + /* If no change, we're done */ if (flags_now == flags_want) return; diff --git a/chip/g/usart.c b/chip/g/usart.c index d7ca39ea14..68ab726814 100644 --- a/chip/g/usart.c +++ b/chip/g/usart.c @@ -129,19 +129,57 @@ USB_STREAM_CONFIG(ec_usb, ec_uart_to_usb) #endif +#ifdef BOARD_CR50 +static uint8_t ec_bridge_enabled_; +static uint8_t ec_bridge_tx_enabled_; + +void uart_ec_bridge_enable(int enable, int write) +{ + write = enable && write; + + if (write && !ec_bridge_tx_enabled_) + task_trigger_irq(GC_IRQNUM_UART2_TXINT); + + ec_bridge_enabled_ = enable; + ec_bridge_tx_enabled_ = write; +} + +int uart_ec_bridge_is_enabled(void) +{ + return !!ec_bridge_enabled_; +} + +int uart_ec_bridge_tx_is_enabled(void) +{ + return !!ec_bridge_tx_enabled_; +} + +#endif /* BOARD_CR50 */ + void get_data_from_usb(struct usart_config const *config) { struct queue const *uart_out = config->consumer.queue; int c; #ifdef BOARD_CR50 - /* - * If EC-CR50 communication is on-going, then let's not forward - * console input to EC for now. - */ - if (ec_comm_is_uart_in_packet_mode(config->uart)) - return; -#endif + if (config->uart == UART_EC) { + /* + * If USB-to-UART bridging is disabled, drop all input data. + * Otherwise, data could be pushed into UART TX FIFO, and + * transferred to EC eventually once EC-CR50 communication + * enables EC UART. + */ + if (!ec_bridge_tx_enabled_) + return; + + /* + * If EC-CR50 communication is on-going, then let's not forward + * console input to EC for now. + */ + if (ec_comm_is_uart_in_packet_mode(UART_EC)) + return; + } +#endif /* BOARD_CR50 */ /* Copy output from buffer until TX fifo full or output buffer empty */ while (queue_count(uart_out) && QUEUE_REMOVE_UNITS(uart_out, &c, 1)) @@ -170,6 +208,14 @@ void send_data_to_usb(struct usart_config const *config) tail = uart_in->state->tail & mask; count = 0; +#ifdef BOARD_CR50 + /* + * If UART-to-USB bridging is not allowed, do not put any output + * data to uart_in queue. + */ + if ((uart == UART_EC) && !ec_bridge_enabled_) + return; +#endif /* BOARD_CR50 */ /* * TODO(b/119329144): Process packet data separately, * and filter console data based on ccd capability. diff --git a/chip/g/usart.h b/chip/g/usart.h index cd3a9cfe40..2d9f04974f 100644 --- a/chip/g/usart.h +++ b/chip/g/usart.h @@ -74,4 +74,13 @@ void get_data_from_usb(struct usart_config const *config); /* Helper for UART bitbang mode. */ extern struct usart_config const ec_uart; +/* Change EC UART-USB Bridge status */ +void uart_ec_bridge_enable(int enabled, int write); + +/* Return non-zero if EC UART-USB Bridge is enabled, or 0 otherwise */ +int uart_ec_bridge_is_enabled(void); + +/* Return non-zero if EC UART-USB Bridge is readwritable, or 0 otherwise */ +int uart_ec_bridge_tx_is_enabled(void); + #endif /* __CROS_FORWARD_UART_H */ -- cgit v1.2.1