diff options
author | Bill Richardson <wfrichar@chromium.org> | 2016-09-08 19:05:46 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-09-13 22:22:11 -0700 |
commit | 91bd09c856cda8393c45c25e3f8b04082b6f3b74 (patch) | |
tree | 7fed3e9a6644cc1a5a73dd4578a226bb2090d5c2 | |
parent | 8229bdf775cd8d85af88c6e221930c83c10f37f3 (diff) | |
download | chrome-ec-91bd09c856cda8393c45c25e3f8b04082b6f3b74.tar.gz |
Cr50: Add clean functions to hold EC/AP in reset
This moves the various GPIO/PINMUX reconfigurations needed to
occasionally drive a common-pulldown signal into a set of clean
functions. There's no new functionality, it's just abstracting
the control of SYS_RST_L and EC_RST_L into specific functions.
BUG=none
CQ-DEPEND=CL:380484
BRANCH=none
TEST=make buildall; test on relevant hardware
I tested this on Gru, Kevin, and Reef, and it works correctly in
all cases. I used flashrom over CCD to update both AP and EC
firmware on each of those systems.
If you just want a quick check, you can run this instead:
sudo flashrom -p raiden_debug_spi:target=AP --flash-name
sudo flashrom -p raiden_debug_spi:target=EC --flash-name
Change-Id: I15fa3b2089d10649bfd17f442e3b261f3b62b92e
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/382665
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r-- | board/cr50/board.c | 66 | ||||
-rw-r--r-- | board/cr50/board.h | 8 | ||||
-rw-r--r-- | board/cr50/usb_spi.c | 36 |
3 files changed, 82 insertions, 28 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index ce7dae31a4..575d3511dd 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -14,17 +14,18 @@ #include "hooks.h" #include "i2cs.h" #include "init_chip.h" -#include "registers.h" #include "nvmem.h" +#include "registers.h" +#include "spi.h" #include "system.h" #include "task.h" +#include "tpm_registers.h" #include "trng.h" #include "uartn.h" #include "usb_descriptor.h" #include "usb_hid.h" -#include "util.h" -#include "spi.h" #include "usb_spi.h" +#include "util.h" /* Define interrupt and gpio structs */ #include "gpio_list.h" @@ -288,20 +289,73 @@ int flash_regions_to_enable(struct g_flash_region *regions, #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) +/* This is the interrupt handler to react to SYS_RST_L_IN */ void sys_rst_asserted(enum gpio_signal signal) { /* * Cr50 drives SYS_RST_L in certain scenarios, in those cases - * asserting this signal should not cause a system reset. + * this signal's assertion should be ignored here. */ - CPRINTS("%s resceived signal %d)", __func__, signal); - if (usb_spi_update_in_progress()) + CPRINTS("%s", __func__); + if (usb_spi_update_in_progress() || is_sys_rst_asserted()) return; cflush(); system_reset(0); } +void assert_sys_rst(void) +{ + /* + * We don't have a good (any?) way to easily look up the pinmux/gpio + * assignments in gpio.inc, so they're hard-coded in this routine. This + * assertion is just to ensure it hasn't changed. + */ + ASSERT(GREAD(PINMUX, GPIO0_GPIO4_SEL) == GC_PINMUX_DIOM0_SEL); + + /* Set SYS_RST_L_OUT as an output, connected to the pad */ + GWRITE(PINMUX, DIOM0_SEL, GC_PINMUX_GPIO0_GPIO4_SEL); + gpio_set_flags(GPIO_SYS_RST_L_OUT, GPIO_OUT_HIGH); + + /* Assert it */ + gpio_set_level(GPIO_SYS_RST_L_OUT, 0); +} + +void deassert_sys_rst(void) +{ + ASSERT(GREAD(PINMUX, GPIO0_GPIO4_SEL) == GC_PINMUX_DIOM0_SEL); + + /* Deassert SYS_RST_L */ + gpio_set_level(GPIO_SYS_RST_L_OUT, 1); + + /* Set SYS_RST_L_OUT as an input, disconnected from the pad */ + gpio_set_flags(GPIO_SYS_RST_L_OUT, GPIO_INPUT); + GWRITE(PINMUX, DIOM0_SEL, 0); +} + +int is_sys_rst_asserted(void) +{ + return (GREAD(PINMUX, DIOM0_SEL) == GC_PINMUX_GPIO0_GPIO4_SEL) +#ifdef CONFIG_CMD_GPIO_EXTENDED + && (gpio_get_flags(GPIO_SYS_RST_L_OUT) & GPIO_OUTPUT) +#endif + && (gpio_get_level(GPIO_SYS_RST_L_OUT) == 0); +} + +void assert_ec_rst(void) +{ + GWRITE(RBOX, ASSERT_EC_RST, 1); +} +void deassert_ec_rst(void) +{ + GWRITE(RBOX, ASSERT_EC_RST, 0); +} + +int is_ec_rst_asserted(void) +{ + return GREAD(RBOX, ASSERT_EC_RST); +} + void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha, int sha_len) { diff --git a/board/cr50/board.h b/board/cr50/board.h index ca3ea5d1e7..de0ced7d36 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -128,6 +128,14 @@ void sys_rst_asserted(enum gpio_signal signal); void device_state_on(enum gpio_signal signal); void device_state_off(enum gpio_signal signal); +/* Special controls over EC and AP */ +void assert_sys_rst(void); +void deassert_sys_rst(void); +int is_sys_rst_asserted(void); +void assert_ec_rst(void); +void deassert_ec_rst(void); +int is_ec_rst_asserted(void); + #endif /* !__ASSEMBLER__ */ /* USB interface indexes (use define rather than enum to expand them) */ diff --git a/board/cr50/usb_spi.c b/board/cr50/usb_spi.c index 02d6525cdd..9ec9c0e7ad 100644 --- a/board/cr50/usb_spi.c +++ b/board/cr50/usb_spi.c @@ -16,46 +16,38 @@ static uint8_t update_in_progress; -void disable_spi(void) +static void disable_ec_ap_spi(void) { /* Configure SPI GPIOs */ gpio_set_level(GPIO_AP_FLASH_SELECT, 0); gpio_set_level(GPIO_EC_FLASH_SELECT, 0); /* Release AP and EC */ - GWRITE(RBOX, ASSERT_EC_RST, 0); - gpio_set_level(GPIO_SYS_RST_L_OUT, 1); - - /* Set SYS_RST_L as an input otherwise cr50 will hold the AP in reset */ - gpio_set_flags(GPIO_SYS_RST_L_OUT, GPIO_INPUT); + deassert_ec_rst(); + deassert_sys_rst(); } -void enable_ec_spi(void) +static void enable_ec_spi(void) { /* Select EC flash */ gpio_set_level(GPIO_AP_FLASH_SELECT, 0); gpio_set_level(GPIO_EC_FLASH_SELECT, 1); - /* hold EC in reset */ - GWRITE(RBOX, ASSERT_EC_RST, 1); + /* Hold EC in reset. This will also hold the AP in reset. */ + assert_ec_rst(); } -void enable_ap_spi(void) +static void enable_ap_spi(void) { /* Select AP flash */ gpio_set_level(GPIO_AP_FLASH_SELECT, 1); gpio_set_level(GPIO_EC_FLASH_SELECT, 0); - /* hold the EC in reset */ - GWRITE(RBOX, ASSERT_EC_RST, 1); - - /* Set SYS_RST_L as an output */ - ASSERT(GREAD(PINMUX, GPIO0_GPIO4_SEL) == GC_PINMUX_DIOM0_SEL); - GWRITE(PINMUX, DIOM0_SEL, GC_PINMUX_GPIO0_GPIO4_SEL); - gpio_set_flags(GPIO_SYS_RST_L_OUT, GPIO_OUT_HIGH); - - /* hold AP in reset */ - gpio_set_level(GPIO_SYS_RST_L_OUT, 0); + /* + * On some systems SYS_RST_L is not level sensitive, so the only way to + * be sure we're holding the AP in reset is to hold the EC in reset. + */ + assert_ec_rst(); } int usb_spi_update_in_progress(void) @@ -80,7 +72,7 @@ void usb_spi_board_enable(struct usb_spi_config const *config) hook_call_deferred(&update_finished_data, -1); update_in_progress = 1; - disable_spi(); + disable_ec_ap_spi(); if (config->state->enabled_host == USB_SPI_EC) enable_ec_spi(); @@ -108,7 +100,7 @@ void usb_spi_board_disable(struct usb_spi_config const *config) { CPRINTS("usb_spi disable"); spi_enable(CONFIG_SPI_FLASH_PORT, 0); - disable_spi(); + disable_ec_ap_spi(); /* Disconnect SPI peripheral to tri-state pads */ /* Disable internal pull up */ |