diff options
author | Vic Yang <victoryang@chromium.org> | 2014-06-11 14:12:58 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-06-12 01:37:57 +0000 |
commit | dbb55cb1f4322cd78d180c25ceeda43439766e40 (patch) | |
tree | b3119048d1ec30a50817e21ebc0283c855f9954b | |
parent | b78f9594ae64b9937950e81bd408952d6894d46c (diff) | |
download | chrome-ec-dbb55cb1f4322cd78d180c25ceeda43439766e40.tar.gz |
Keyborg: implement system reboot
In case the slave got into a bad state, we may need a way to reboot the
slave from the master. The protocol must not involve SPI communication;
otherwise this will fail if the slave SPI module is in a bad state.
This CL implements this using SPI_NSS. In normal SPI communication, the
master pulls SPI_NSS low and immediately sync with the slave. To reboot
the slave, the master pulls SPI_NSS low without the following sync.
BUG=None
TEST=Reboots the slave from the master.
BRANCH=None
Change-Id: I947523e1d86fb2332b87fbfa3dab73cba958fb72
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/203485
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/keyborg/board.h | 3 | ||||
-rw-r--r-- | board/keyborg/runtime.c | 18 | ||||
-rw-r--r-- | board/keyborg/spi_comm.c | 7 |
3 files changed, 27 insertions, 1 deletions
diff --git a/board/keyborg/board.h b/board/keyborg/board.h index b1750575a6..5d63551d33 100644 --- a/board/keyborg/board.h +++ b/board/keyborg/board.h @@ -40,6 +40,9 @@ enum gpio_signal; /* Initialize all useful registers */ void hardware_init(void); +/* On the master, reboot both chips. On the slave, reboot itself. */ +void system_reboot(void); + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/keyborg/runtime.c b/board/keyborg/runtime.c index c7c619c46c..e335442398 100644 --- a/board/keyborg/runtime.c +++ b/board/keyborg/runtime.c @@ -8,6 +8,7 @@ #include "cpu.h" #include "debug.h" #include "irq_handler.h" +#include "master_slave.h" #include "registers.h" #include "timer.h" #include "util.h" @@ -109,6 +110,23 @@ uint32_t task_wait_event(int timeout_us) return evt; } +void system_reboot(void) +{ + if (master_slave_is_master()) { + /* Ask the slave to reboot as well */ + STM32_GPIO_BSRR(GPIO_A) = 1 << (6 + 16); + udelay(10 * MSEC); /* The slave reboots in 5 ms */ + } + + /* Ask the watchdog to trigger a hard reboot */ + STM32_IWDG_KR = 0x5555; + STM32_IWDG_RLR = 0x1; + STM32_IWDG_KR = 0xcccc; + /* wait for the watchdog */ + while (1) + ; +} + /* --- stubs --- */ void __hw_timer_enable_clock(int n, int enable) { /* Done in hardware init */ } diff --git a/board/keyborg/spi_comm.c b/board/keyborg/spi_comm.c index 380ab6906b..4c5c729e7b 100644 --- a/board/keyborg/spi_comm.c +++ b/board/keyborg/spi_comm.c @@ -408,7 +408,12 @@ static void spi_nss_interrupt(void) if (spi->sr & STM32_SPI_SR_RXNE) in_msg[0] = spi->dr; - master_slave_sync(5); + /* + * SPI_NSS is also used for the master to reboot the slave. + * If SPI_NSS goes low without a sync in time, reboots. + */ + if (master_slave_sync(5)) + system_reboot(); /* Read in the packet size */ while (!(spi->sr & STM32_SPI_SR_RXNE)) |