summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-06-11 14:12:58 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-06-12 01:37:57 +0000
commitdbb55cb1f4322cd78d180c25ceeda43439766e40 (patch)
treeb3119048d1ec30a50817e21ebc0283c855f9954b
parentb78f9594ae64b9937950e81bd408952d6894d46c (diff)
downloadchrome-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.h3
-rw-r--r--board/keyborg/runtime.c18
-rw-r--r--board/keyborg/spi_comm.c7
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))