summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2017-07-31 16:24:08 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-08-01 13:01:41 -0700
commitc7b11ca7b855d35dce75502429ed56af990ea41a (patch)
treeb2eaef6673a012941835ad80b9b6a23178067af0
parent00ea73ab166ebc8a2c4b5693b7fa776c76c7fe45 (diff)
downloadchrome-ec-c7b11ca7b855d35dce75502429ed56af990ea41a.tar.gz
cr50: CCD V1 controls UART access
AP and EC UART now use the CCD V1 capabilities to determine when access is allowed. Transmit to AP and EC can be toggled independently from read access to output from those UARTs. Note that disabling read access disables both transmit and receive. That is, it's not possible to set a UART where transmit is allowed but receive isn't. Why would you want to do that, anyway? See go/cr50-ccd-wp for more information. BUG=b:62537474 BRANCH=cr50 TEST=manual with CR50_DEV=1 ccdoops ccdset cr50fullconsole always -> so we can use ccd command for testing ccd -> AP RX+TX, EC RX+TX ccdset uartecrx unlesslocked ccdset uartectx ifopened ccdset uartaprx always ccdset uartaptx unlesslocked ccdunlock ccd -> AP RX+TX, EC RX ccdlock ccd -> AP RX, EC disabled ccdoops ccdset cr50fullconsole always ccd -> AP RX+TX, EC RX+TX ccdset uartaprx ifopened ccdlock ccd -> AP disabled, EC RX Change-Id: I55db5897bb52cd60658ab221eadf5c59fc86744a Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/595196 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--board/cr50/board.c42
-rw-r--r--board/cr50/rdd.c64
-rw-r--r--chip/g/uartn.c5
-rw-r--r--chip/g/uartn.h11
-rw-r--r--include/case_closed_debug.h10
5 files changed, 103 insertions, 29 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 49543d4cf4..f56081b2d3 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -889,11 +889,19 @@ static int servo_state_unknown(void)
static void enable_uart(int uart)
{
- /*
- * For the EC UART, we can't connect the TX pin to the UART block when
- * it's in bit bang mode.
- */
- if ((uart == UART_EC) && uart_bitbang_is_enabled(uart))
+ if (uart == UART_EC) {
+ if (!ccd_is_cap_enabled(CCD_CAP_EC_TX_CR50_RX))
+ return;
+
+ /*
+ * For the EC UART, we can't connect the TX pin to the UART
+ * block when it's in bit bang mode.
+ */
+ if (uart_bitbang_is_enabled(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 */
@@ -913,6 +921,30 @@ static void disable_uart(int uart)
uartn_tx_disconnect(uart);
}
+static void board_ccd_change_hook(void)
+{
+ if (uartn_is_enabled(UART_AP) &&
+ !ccd_is_cap_enabled(CCD_CAP_AP_TX_CR50_RX)) {
+ /* Receiving from AP, but no longer allowed */
+ disable_uart(UART_AP);
+ } else if (!uartn_is_enabled(UART_AP) &&
+ ccd_is_cap_enabled(CCD_CAP_AP_TX_CR50_RX)) {
+ /* Not receiving from AP, but allowed now */
+ enable_uart(UART_AP);
+ }
+
+ if (uartn_is_enabled(UART_EC) &&
+ !ccd_is_cap_enabled(CCD_CAP_EC_TX_CR50_RX)) {
+ /* Receiving from EC, but no longer allowed */
+ disable_uart(UART_EC);
+ } else if (!uartn_is_enabled(UART_EC) &&
+ ccd_is_cap_enabled(CCD_CAP_EC_TX_CR50_RX)) {
+ /* Not receiving from EC, but allowed now */
+ enable_uart(UART_EC);
+ }
+}
+DECLARE_HOOK(HOOK_CCD_CHANGE, board_ccd_change_hook, HOOK_PRIO_DEFAULT);
+
static int device_powered_off(enum device_type device)
{
if (device_get_state(device) == DEVICE_STATE_ON)
diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c
index bf5a3ed8f0..52082d56f4 100644
--- a/board/cr50/rdd.c
+++ b/board/cr50/rdd.c
@@ -20,7 +20,7 @@
#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
static int keep_ccd_enabled;
-static int ec_uart_enabled, enable_usb_wakeup;
+static int enable_usb_wakeup;
static int usb_is_initialized;
struct uart_config {
@@ -79,7 +79,10 @@ static int servo_is_connected(void)
void uartn_tx_connect(int uart)
{
- if (uart == UART_EC && !ec_uart_enabled)
+ if (uart == UART_AP && !ccd_is_cap_enabled(CCD_CAP_AP_RX_CR50_TX))
+ return;
+
+ if (uart == UART_EC && !ccd_is_cap_enabled(CCD_CAP_EC_RX_CR50_TX))
return;
if (!ccd_is_enabled())
@@ -99,10 +102,6 @@ void uartn_tx_connect(int uart)
void uartn_tx_disconnect(int uart)
{
- /* If servo is connected disable UART */
- if (servo_is_connected())
- ec_uart_enabled = 0;
-
/* Disconnect the TX pin from UART peripheral */
uart_select_tx(uart, 0);
}
@@ -118,7 +117,9 @@ static void configure_ccd(int enable)
enable_usb_wakeup = 1;
+ /* Attempt to connect UART TX */
uartn_tx_connect(UART_AP);
+ uartn_tx_connect(UART_EC);
/* Turn on 3.3V rail used for INAs and initialize I2CM module */
usb_i2c_board_enable();
@@ -128,7 +129,6 @@ static void configure_ccd(int enable)
uartn_tx_disconnect(UART_AP);
enable_usb_wakeup = board_has_ap_usb();
- ec_uart_enabled = 0;
/* Disable CCD */
ccd_set_mode(CCD_MODE_DISABLED);
@@ -230,6 +230,32 @@ void enable_ap_usb(void)
}
DECLARE_HOOK(HOOK_CHIPSET_RESUME, enable_ap_usb, HOOK_PRIO_DEFAULT);
+static void rdd_ccd_change_hook(void)
+{
+ if (uart_tx_is_connected(UART_AP) &&
+ !ccd_is_cap_enabled(CCD_CAP_AP_RX_CR50_TX)) {
+ /* Transmitting to AP, but no longer allowed */
+ uartn_tx_disconnect(UART_AP);
+ } else if (!uart_tx_is_connected(UART_AP) &&
+ ccd_is_cap_enabled(CCD_CAP_AP_RX_CR50_TX)) {
+ /* Not transmitting to AP, but allowed now */
+ uartn_tx_connect(UART_AP);
+ }
+
+ if (uart_tx_is_connected(UART_EC) &&
+ !ccd_is_cap_enabled(CCD_CAP_EC_RX_CR50_TX)) {
+ /* Transmitting to EC, but no longer allowed */
+ uartn_tx_disconnect(UART_EC);
+ } else if (!uart_tx_is_connected(UART_EC) &&
+ ccd_is_cap_enabled(CCD_CAP_EC_RX_CR50_TX)) {
+ /* Not transmitting to EC, but allowed now */
+ uartn_tx_connect(UART_EC);
+ }
+
+
+}
+DECLARE_HOOK(HOOK_CCD_CHANGE, rdd_ccd_change_hook, HOOK_PRIO_DEFAULT);
+
static void clear_keepalive(void)
{
keep_ccd_enabled = 0;
@@ -245,13 +271,10 @@ static int command_ccd(int argc, char **argv)
return argc == 2 ? EC_ERROR_PARAM1 : EC_ERROR_PARAM2;
if (!strcasecmp("uart", argv[1])) {
- if (val) {
- ec_uart_enabled = 1;
+ if (val)
uartn_tx_connect(UART_EC);
- } else {
- ec_uart_enabled = 0;
+ else
uartn_tx_disconnect(UART_EC);
- }
} else if (!strcasecmp("i2c", argv[1])) {
if (val)
usb_i2c_board_enable();
@@ -283,14 +306,17 @@ static int command_ccd(int argc, char **argv)
return EC_ERROR_PARAM1;
}
- ccprintf("CCD:%14s\n",
+ ccprintf("CCD: %s\n",
keep_ccd_enabled ? "forced enable" :
- ccd_is_enabled() ? " enabled" : "disabled");
- ccprintf("AP UART: %s\nEC UART: %s\n",
- uart_tx_is_connected(UART_AP) ? " enabled" : "disabled",
- uart_tx_is_connected(UART_EC) ? " enabled" : "disabled");
- ccprintf("I2C: %s\n",
- usb_i2c_board_is_enabled() ? " enabled" : "disabled");
+ ccd_is_enabled() ? "enabled" : "disabled");
+ ccprintf("AP UART: %s\n",
+ uartn_is_enabled(UART_AP) ?
+ uart_tx_is_connected(UART_AP) ? "RX+TX" : "RX" : "disabled");
+ ccprintf("EC UART: %s\n",
+ uartn_is_enabled(UART_EC) ?
+ uart_tx_is_connected(UART_EC) ? "RX+TX" : "RX" : "disabled");
+ ccprintf("I2C: %s\n",
+ usb_i2c_board_is_enabled() ? "enabled" : "disabled");
return EC_SUCCESS;
}
diff --git a/chip/g/uartn.c b/chip/g/uartn.c
index 6140e8cff4..b9d08d4375 100644
--- a/chip/g/uartn.c
+++ b/chip/g/uartn.c
@@ -197,6 +197,11 @@ void uartn_disable(int uart)
GR_UART_CTRL(uart) = 0;
}
+int uartn_is_enabled(int uart)
+{
+ return !!(GR_UART_CTRL(uart) & 0x03);
+}
+
void uartn_init(int uart)
{
long long setting = (16 * (1 << UART_NCO_WIDTH) *
diff --git a/chip/g/uartn.h b/chip/g/uartn.h
index 967136de22..bfb7772518 100644
--- a/chip/g/uartn.h
+++ b/chip/g/uartn.h
@@ -89,6 +89,17 @@ void uartn_tx_connect(int uart);
void uartn_tx_disconnect(int uart);
/**
+ * Return non-zero if TX and RX are enabled for the UART.
+ *
+ * Note that TX won't be connected unless uart_tx_is_connected() is also
+ * non-zero.
+ *
+ * @param uart UART to check
+ * @return 1 if UART is enabled, 0 if disabled.
+ */
+int uartn_is_enabled(int uart);
+
+/**
* Enable TX and RX for the UART. Disable HW flow control and loopback.
*
* @param uart UART to enable
diff --git a/include/case_closed_debug.h b/include/case_closed_debug.h
index 2edbf1763d..456bafa58d 100644
--- a/include/case_closed_debug.h
+++ b/include/case_closed_debug.h
@@ -91,11 +91,11 @@ enum ccd_flag {
/* Capabilities */
enum ccd_capability {
- /* AP and EC UART output and input */
- CCD_CAP_AP_UART_OUTPUT = 0,
- CCD_CAP_AP_UART_INPUT = 1,
- CCD_CAP_EC_UART_OUTPUT = 2,
- CCD_CAP_EC_UART_INPUT = 3,
+ /* AP and EC UART output (from AP/EC) and input (to AP/EC) */
+ CCD_CAP_AP_TX_CR50_RX = 0,
+ CCD_CAP_AP_RX_CR50_TX = 1,
+ CCD_CAP_EC_TX_CR50_RX = 2,
+ CCD_CAP_EC_RX_CR50_TX = 3,
/* Access to AP SPI flash */
CCD_CAP_AP_FLASH = 4,