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>
This commit is contained in:
Vic Yang
2014-06-11 14:12:58 -07:00
committed by chrome-internal-fetch
parent b78f9594ae
commit dbb55cb1f4
3 changed files with 27 additions and 1 deletions

View File

@@ -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 */

View File

@@ -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 */ }

View File

@@ -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))