summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2017-08-29 14:31:03 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-08-30 16:13:16 -0700
commit8202ddaa95b853ae7a4b6893e06c85df7b2c947f (patch)
treed2b82826ad255b08a7da489834ecb614cab778d1
parentb52f9b8ea614804e5e198f00cc24a5084e14470e (diff)
downloadchrome-ec-8202ddaa95b853ae7a4b6893e06c85df7b2c947f.tar.gz
cr50: Only enable UART RX when EC/AP is on
Previously, some code paths such as CCD permissions change could result in enabling EC or AP UART RX when the EC or AP is off. This could result in interrupt storms. BUG=none BRANCH=cr50 TEST=manual // Initial conditions Assert CCD_MODE_L Deassert DETECT_SERVO // Both RX and TX disabled when processor turns off // and re-enabled when it turns back on Deassert DETECT_EC ccd -> EC UART disabled Assert DETECT_EC ccd --> EC UART RX+TX Deassert DETECT_AP ccd -> AP UART disabled Assert DETECT_AP ccd --> AP UART RX+TX // TX disabled when CCD disabled Deassert CCD_MODE_L ccd --> EC UART RX, AP UART RX Assert DETECT_SERVO ccd --> EC UART RX, AP UART RX // Don't enable TX when detecting EC, if servo is connected Deassert DETECT_EC ccd -> EC UART disabled Assert DETECT_EC ccd --> EC UART RX // Don't enable TX when detecting CCD, if servo is connected Assert CCD_MODE_L ccd --> EC UART RX, AP UART RX // When servo disconnects, enable TX if CCD is connected Deassert DETECT_SERVO ccd --> EC UART RX+TX, AP UART RX+TX Change-Id: Icb144c23e949afb0384c242965aa729b078b03eb Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/642349 Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r--board/cr50/board.c22
-rw-r--r--board/cr50/rdd.c44
2 files changed, 37 insertions, 29 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 2453265fb2..e72a88a8c1 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -976,10 +976,25 @@ static int servo_state_unknowable(void)
void enable_ccd_uart(int uart)
{
- if (uart == UART_EC) {
+ /*
+ * Only enable the UART if we have receive permission, and if the
+ * processor we're talking to is on. When the processor is off, its
+ * transmit line (our receive line) may float, leading to interrupt
+ * storms.
+ */
+ if (uart == UART_AP) {
+ if (!ccd_is_cap_enabled(CCD_CAP_AP_TX_CR50_RX))
+ return;
+
+ if (!ap_is_on())
+ return;
+ } else {
if (!ccd_is_cap_enabled(CCD_CAP_EC_TX_CR50_RX))
return;
+ if (!ec_is_on())
+ return;
+
/*
* For the EC UART, we can't connect the TX pin to the UART
* block when it's in bit bang mode.
@@ -988,13 +1003,10 @@ void enable_ccd_uart(int uart)
return;
}
- if (uart == UART_AP && !ccd_is_cap_enabled(CCD_CAP_AP_TX_CR50_RX))
- return;
-
/* Enable RX and TX on the UART peripheral */
uartn_enable(uart);
- /* Connect the TX pin to the UART TX Signal */
+ /* Connect the TX pin to the UART TX signal */
if (!uart_tx_is_connected(uart))
uartn_tx_connect(uart);
}
diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c
index ca2da0fd75..a0ad76cb22 100644
--- a/board/cr50/rdd.c
+++ b/board/cr50/rdd.c
@@ -19,16 +19,6 @@
#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-struct uart_config {
- const char *name;
- int tx_signal;
-};
-
-static struct uart_config uarts[] = {
- [UART_AP] = {"AP", GC_PINMUX_UART1_TX_SEL},
- [UART_EC] = {"EC", GC_PINMUX_UART2_TX_SEL},
-};
-
int rdd_is_connected(void)
{
return ccd_get_mode() == CCD_MODE_ENABLED;
@@ -68,25 +58,31 @@ int servo_is_connected(void)
void uartn_tx_connect(int uart)
{
- if (uart == UART_AP && !ccd_is_cap_enabled(CCD_CAP_AP_RX_CR50_TX))
+ /*
+ * Don't drive TX unless the debug cable is connected (we have
+ * something to transmit) and servo is disconnected (we won't be
+ * drive-fighting with servo).
+ */
+ if (servo_is_connected() || !rdd_is_connected())
return;
- if (uart == UART_EC && !ccd_is_cap_enabled(CCD_CAP_EC_RX_CR50_TX))
- return;
+ if (uart == UART_AP) {
+ if (!ccd_is_cap_enabled(CCD_CAP_AP_RX_CR50_TX))
+ return;
- if (!rdd_is_connected())
- return;
+ if (!ap_is_on())
+ return;
- if (servo_is_connected()) {
- CPRINTS("Servo is attached cannot enable %s UART",
- uarts[uart].name);
- return;
- }
+ uart_select_tx(UART_AP, GC_PINMUX_UART1_TX_SEL);
+ } else {
+ if (!ccd_is_cap_enabled(CCD_CAP_EC_RX_CR50_TX))
+ return;
- if (uart == UART_AP ? ap_is_on() : ec_is_on())
- uart_select_tx(uart, uarts[uart].tx_signal);
- else if (!uart_tx_is_connected(uart))
- CPRINTS("%s is powered off", uarts[uart].name);
+ if (!ec_is_on())
+ return;
+
+ uart_select_tx(UART_EC, GC_PINMUX_UART2_TX_SEL);
+ }
}
void uartn_tx_disconnect(int uart)