summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2016-09-08 19:05:46 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-13 22:22:11 -0700
commit91bd09c856cda8393c45c25e3f8b04082b6f3b74 (patch)
tree7fed3e9a6644cc1a5a73dd4578a226bb2090d5c2 /board
parent8229bdf775cd8d85af88c6e221930c83c10f37f3 (diff)
downloadchrome-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>
Diffstat (limited to 'board')
-rw-r--r--board/cr50/board.c66
-rw-r--r--board/cr50/board.h8
-rw-r--r--board/cr50/usb_spi.c36
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 */