diff options
author | Namyoon Woo <namyoon@chromium.org> | 2019-12-27 10:32:23 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-02-08 04:08:18 +0000 |
commit | 1411a256089ad45a99a2e327972bc6f732f5a6e9 (patch) | |
tree | 4049582527aade9d95ac4012b2d06a6a5d5f2f7f | |
parent | 341cc2da402e23dc9ff09072058f79d5ec0c40c6 (diff) | |
download | chrome-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.c | 36 | ||||
-rw-r--r-- | board/cr50/board.h | 13 | ||||
-rw-r--r-- | board/cr50/build.mk | 1 | ||||
-rw-r--r-- | board/cr50/ec_comm.c | 68 | ||||
-rw-r--r-- | board/cr50/gpio.inc | 11 | ||||
-rw-r--r-- | chip/g/usart.c | 16 | ||||
-rw-r--r-- | include/system.h | 1 |
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. */ }; |