summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@chromium.org>2019-12-27 10:32:23 -0800
committerCommit Bot <commit-bot@chromium.org>2020-02-08 04:08:18 +0000
commit1411a256089ad45a99a2e327972bc6f732f5a6e9 (patch)
tree4049582527aade9d95ac4012b2d06a6a5d5f2f7f
parent341cc2da402e23dc9ff09072058f79d5ec0c40c6 (diff)
downloadchrome-ec-1411a256089ad45a99a2e327972bc6f732f5a6e9.tar.gz
make DIOB3 interruptible and wakable for EC-EFS2
If the board supports EC-CR50 communication, Cr50 enables both rising/falling-edge triggered interrupt on DIOB3 pin and makes it wakable as well.Cr50 connects GPIO_AP_FLASH_SELECT to DIOB4. If the board does not support EC-CR50 communication, Cr50 connects GPIO_AP_FLASH_SELECT to DIOB3. If EC puts high on DIOB3 to activate EC-CR50 communication, CR50 enables UART_EC RX and TX. BUG=chromium:1035706 BRANCH=cr50 TEST=none Change-Id: I1221a1a19219274622ab710568ce7c66ab2f1da7 Signed-off-by: Namyoon Woo <namyoon@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1989581 Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r--board/cr50/board.c36
-rw-r--r--board/cr50/board.h13
-rw-r--r--board/cr50/build.mk1
-rw-r--r--board/cr50/ec_comm.c68
-rw-r--r--board/cr50/gpio.inc11
-rw-r--r--chip/g/usart.c16
-rw-r--r--include/system.h1
7 files changed, 138 insertions, 8 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index e61f9be991..4927194b74 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -453,12 +453,18 @@ static void init_ac_detect(void)
/*****************************************************************************/
/*
- * There's no way to trigger on both rising and falling edges, so force a
- * compiler error if we try. The workaround is to use the pinmux to connect
- * two GPIOs to the same input and configure each one for a separate edge.
+ * There's no way to have more than one trigger condition on a GPIO,
+ * so force a compiler error if we try. The workaround is to use the pinmux to
+ * connect as many GPIOs as the number of required trigger conditions to the
+ * same input and configure each one for a separate condition.
+ */
+#define GPIO_INT_COND(x) ((x) & GPIO_INT_ANY & ~GPIO_INPUT)
+/*
+ * Checks flags has only one bit set among GPIO_INT_F_RISING,
+ * GPIO_INT_F_FALLING, GPIO_INT_F_LOW, GPIO_INT_F_HIGH.
*/
#define GPIO_INT(name, pin, flags, signal) \
- BUILD_ASSERT(((flags) & GPIO_INT_BOTH) != GPIO_INT_BOTH);
+ BUILD_ASSERT((GPIO_INT_COND(flags) & (GPIO_INT_COND(flags) - 1)) == 0);
#include "gpio.wrap"
/**
@@ -600,6 +606,15 @@ void board_configure_deep_sleep_wakepins(void)
/* enable powerdown exit */
GWRITE_FIELD(PINMUX, EXITEN0, DIOM0, 1);
}
+
+ if (board_has_ec_cr50_comm_support()) {
+ /* disable powerdown exit */
+ GWRITE_FIELD(PINMUX, EXITEN0, DIOB3, 0);
+ GWRITE_FIELD(PINMUX, EXITEDGE0, DIOB3, 0); /* level sensitive */
+ GWRITE_FIELD(PINMUX, EXITINV0, DIOB3, 0); /* wake on high */
+ /* enable powerdown exit */
+ GWRITE_FIELD(PINMUX, EXITEN0, DIOB3, 1);
+ }
}
static void deferred_tpm_rst_isr(void);
@@ -697,16 +712,21 @@ static void configure_board_specific_gpios(void)
GWRITE(PINMUX, DIOB4_SEL, GC_PINMUX_GPIO0_GPIO2_SEL);
GWRITE(PINMUX, GPIO0_GPIO2_SEL, GC_PINMUX_DIOB4_SEL);
- /* Enable the input */
+ /* Enable the input for DIOB4 */
GWRITE_FIELD(PINMUX, DIOB4_CTL, IE, 1);
+
+ /* Connect GPIO_EC_PACKET_MODE_EN to DIOB3 as input. */
+ GWRITE(PINMUX, GPIO1_GPIO7_SEL, GC_PINMUX_DIOB3_SEL);
+ /* Connect GPIO_EC_PACKET_MODE_DIS to DIOB3 as input. */
+ GWRITE(PINMUX, GPIO1_GPIO8_SEL, GC_PINMUX_DIOB3_SEL);
} else {
/* Connect GPIO_AP_FLASH_SELECT to DIOB3. */
GWRITE(PINMUX, DIOB3_SEL, GC_PINMUX_GPIO0_GPIO2_SEL);
GWRITE(PINMUX, GPIO0_GPIO2_SEL, GC_PINMUX_DIOB3_SEL);
-
- /* Enable the input */
- GWRITE_FIELD(PINMUX, DIOB3_CTL, IE, 1);
}
+ /* Enable the input for DIOB3 */
+ GWRITE_FIELD(PINMUX, DIOB3_CTL, IE, 1);
+
}
static uint8_t mismatched_board_id;
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 43bc6abd78..4c35fb9e07 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -380,6 +380,18 @@ void board_unwedge_i2cs(void);
int board_in_prod_mode(void);
+/* GPIO Interrupt handler for GPIO_EC_PACKET_MODE_EN rising edge */
+void ec_comm_packet_mode_en(enum gpio_signal unsed);
+
+/* GPIO Interrupt handler for GPIO_EC_PACKET_MODE_DIS falling edge */
+void ec_comm_packet_mode_dis(enum gpio_signal unsed);
+
+/*
+ * Return True if the given UART is in packet mode, in which EC-CR50
+ * communication is on-going.
+ */
+int ec_comm_is_uart_in_packet_mode(int uart);
+
#endif /* !__ASSEMBLER__ */
/* USB interface indexes (use define rather than enum to expand them) */
@@ -405,6 +417,7 @@ int board_in_prod_mode(void);
#define UART_CR50 0
#define UART_AP 1
#define UART_EC 2
+#define UART_NULL 0xff
#define UARTN UART_CR50
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index 5b0d788401..dfef2b1847 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -42,6 +42,7 @@ dirs-y += $(BDIR)/tpm2
board-y = board.o
board-y += ap_state.o
board-y += closed_source_set1.o
+board-y += ec_comm.o
board-y += ec_state.o
board-y += power_button.o
board-y += servo_state.o
diff --git a/board/cr50/ec_comm.c b/board/cr50/ec_comm.c
new file mode 100644
index 0000000000..3e9a343f2c
--- /dev/null
+++ b/board/cr50/ec_comm.c
@@ -0,0 +1,68 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * EC-CR50 communication
+ */
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "system.h"
+#include "task.h"
+#include "uartn.h"
+
+#define CPRINTS(format, args...) cprints(CC_TASK, "EC-COMM: " format, ## args)
+
+/*
+ * Context of EC-CR50 communication
+ */
+static struct ec_comm_context_ {
+ uint8_t uart; /* Current UART ID in packet mode. */
+ /* UART_NULL if no UART is in packet mode */
+} ec_comm_ctx;
+
+
+/*
+ * Initialize EC-CR50 communication context.
+ */
+static void ec_comm_init_(void)
+{
+ ec_comm_ctx.uart = UART_NULL;
+
+ if (!board_has_ec_cr50_comm_support())
+ return;
+
+ CPRINTS("Initializtion");
+
+ gpio_enable_interrupt(GPIO_EC_PACKET_MODE_EN);
+ gpio_enable_interrupt(GPIO_EC_PACKET_MODE_DIS);
+
+ /* If DIOB3 is already high, then enable the packet mode. */
+ if (gpio_get_level(GPIO_EC_PACKET_MODE_EN))
+ ec_comm_packet_mode_en(GPIO_EC_PACKET_MODE_EN);
+}
+DECLARE_HOOK(HOOK_INIT, ec_comm_init_, HOOK_PRIO_DEFAULT + 1);
+
+void ec_comm_packet_mode_en(enum gpio_signal unsed)
+{
+ disable_sleep(SLEEP_MASK_EC_CR50_COMM);
+
+ /* TODO: Initialize packet context */
+
+ ec_comm_ctx.uart = UART_EC; /* Enable Packet Mode */
+ ccd_update_state();
+}
+
+void ec_comm_packet_mode_dis(enum gpio_signal unsed)
+{
+ ec_comm_ctx.uart = UART_NULL; /* Disable Packet Mode. */
+ ccd_update_state();
+
+ enable_sleep(SLEEP_MASK_EC_CR50_COMM);
+}
+
+int ec_comm_is_uart_in_packet_mode(int uart)
+{
+ return uart == ec_comm_ctx.uart;
+}
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index 2f2402aea3..9457adba99 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -69,6 +69,8 @@
* GPIO1.4 detect_tpm_rst_asserted
* GPIO1.5 unwedge_i2cs_scl
* GPIO1.6 monitor_i2cs_sda
+ * GPIO1.7 ec_packet_mode_en
+ * GPIO1.8 ec_packet_mode_dis
* GPIO1.10 rec_lid_switch
* GPIO1.11 ec_tx_cr50_rx_in
* GPIO1.12 strap_a0
@@ -106,6 +108,15 @@ GPIO_INT(DETECT_SERVO, PIN(1, 3), GPIO_INT_HIGH | GPIO_PULL_DOWN,
GPIO_INT(DETECT_TPM_RST_L_ASSERTED, PIN(1, 4), GPIO_INT_FALLING,
tpm_rst_asserted)
+/*
+ * These GPIOs are to enable or disable EC-CR50 communication.
+ * NOTE: If these are changed, you must update the information in board.c
+ * and ec_comm.c
+ */
+GPIO_INT(EC_PACKET_MODE_EN, PIN(1, 7), GPIO_INT_RISING, ec_comm_packet_mode_en)
+GPIO_INT(EC_PACKET_MODE_DIS, PIN(1, 8), GPIO_INT_FALLING,
+ ec_comm_packet_mode_dis)
+
/*****************************************************************************/
/* NON STANDARD INTERRUPT GPIOs - handlers defined and configured in board.c */
/*
diff --git a/chip/g/usart.c b/chip/g/usart.c
index 0a08d261b8..d7ca39ea14 100644
--- a/chip/g/usart.c
+++ b/chip/g/usart.c
@@ -134,6 +134,15 @@ 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
+
/* Copy output from buffer until TX fifo full or output buffer empty */
while (queue_count(uart_out) && QUEUE_REMOVE_UNITS(uart_out, &c, 1))
uartn_write_char(config->uart, c);
@@ -161,6 +170,13 @@ void send_data_to_usb(struct usart_config const *config)
tail = uart_in->state->tail & mask;
count = 0;
+ /*
+ * TODO(b/119329144): Process packet data separately,
+ * and filter console data based on ccd capability.
+ * if (ec_comm_is_uart_in_packet_mode(uart))
+ * ...
+ */
+
while ((count != q_room) && uartn_rx_available(uart)) {
uart_in->buffer[tail] = uartn_read_char(uart);
tail = (tail + 1) & mask;
diff --git a/include/system.h b/include/system.h
index 0d785c6899..1df48cf28e 100644
--- a/include/system.h
+++ b/include/system.h
@@ -441,6 +441,7 @@ enum {
*/
SLEEP_MASK_JTAG = BIT(16), /* JTAG is in use. */
SLEEP_MASK_CONSOLE = BIT(17), /* Console is in use. */
+ SLEEP_MASK_EC_CR50_COMM = BIT(18), /* EC-CR50 commncation is active. */
SLEEP_MASK_FORCE_NO_LOW_SPEED = BIT(31) /* Force disable. */
};