Add LM4 support for hard reset

(And add STM32 support for disabling interrupts before reset, which
got missed before.)

Signed-off-by: Randall Spangler <rspangler@chromium.org>

BUG=chrome-os-partner:7470
TEST=from console, "reboot", then "reboot hard"

Change-Id: Ib98792abc0c91a01e2230b419fc876052380655a
This commit is contained in:
Randall Spangler
2012-05-18 15:56:30 -07:00
parent 8407b93f6d
commit b1bb8314bd
5 changed files with 62 additions and 70 deletions

View File

@@ -26,7 +26,6 @@ static int wait_for_hibctl_wc(void)
static void check_reset_cause(void)
{
enum system_image_copy_t copy = system_get_image_copy();
uint32_t hib_status = LM4_HIBERNATE_HIBRIS;
enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN;
uint32_t raw_reset_cause;
@@ -36,25 +35,24 @@ static void check_reset_cause(void)
LM4_SYSTEM_RESC = 0;
if (hib_status & 0x0d) {
/* the hibernation module wakes up the system */
/* The hibernation module woke up the system */
if (hib_status & 0x8)
reset_cause = SYSTEM_RESET_WAKE_PIN;
else if (hib_status & 0x1)
/* Note that system_reset(1) also triggers this reset
* cause, because it uses hibernate with a RTC wake to
* trigger a power-on reset. */
reset_cause = SYSTEM_RESET_RTC_ALARM;
else if (hib_status & 0x4)
reset_cause = SYSTEM_RESET_LOW_BATTERY;
/* clear the pending interrupt */
/* Clear the pending interrupt */
wait_for_hibctl_wc();
LM4_HIBERNATE_HIBIC = hib_status;
} else if (copy == SYSTEM_IMAGE_RW_A || copy == SYSTEM_IMAGE_RW_B) {
/* If we're in image A or B, the only way we can get there is
* via a warm reset. */
reset_cause = SYSTEM_RESET_SOFT_WARM;
} else if (raw_reset_cause & 0x28) {
/* Watchdog timer 0 or 1 */
reset_cause = SYSTEM_RESET_WATCHDOG;
} else if (raw_reset_cause & 0x10) {
reset_cause = SYSTEM_RESET_SOFT_COLD;
reset_cause = SYSTEM_RESET_SOFT;
} else if (raw_reset_cause & 0x04) {
reset_cause = SYSTEM_RESET_BROWNOUT;
} else if (raw_reset_cause & 0x02) {
@@ -63,9 +61,6 @@ static void check_reset_cause(void)
reset_cause = SYSTEM_RESET_RESET_PIN;
} else if (raw_reset_cause) {
reset_cause = SYSTEM_RESET_OTHER;
} else {
/* Reset cause is still 0, so this is a warm reset. */
reset_cause = SYSTEM_RESET_SOFT_WARM;
}
system_set_reset_cause(reset_cause);
}
@@ -87,12 +82,19 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds)
LM4_HIBERNATE_HIBRTCLD = 0;
/* go to hibernation and wake on RTC match or WAKE pin */
wait_for_hibctl_wc();
#ifdef BOARD_link
/* Need VDD3ON because we can't drop VDD externally */
LM4_HIBERNATE_HIBCTL = 0x15B;
if (system_get_board_version() == BOARD_VERSION_PROTO1) {
/* Need VDD3ON because we can't drop VDD externally */
LM4_HIBERNATE_HIBCTL = 0x15B;
} else {
/* EVT+ can drop VDD */
LM4_HIBERNATE_HIBCTL = 0x5B;
}
#else
LM4_HIBERNATE_HIBCTL = 0x5B;
#endif
/* we are going to hibernate ... */
while (1) ;
}
@@ -146,19 +148,21 @@ int system_pre_init(void)
}
int system_reset(int is_cold)
void system_reset(int is_hard)
{
/* Disable interrupts to avoid task swaps during reboot */
interrupt_disable();
/* TODO: (crosbug.com/p/7470) support cold boot; this is a
warm boot. */
CPU_NVIC_APINT = 0x05fa0004;
if (is_hard) {
/* Bounce through hibernate to trigger a hard reboot */
system_hibernate(0, 50000);
} else {
/* Soft reboot */
CPU_NVIC_APINT = 0x05fa0004;
}
/* Spin and wait for reboot; should never return */
while (1) {}
return EC_ERROR_UNKNOWN;
}

View File

@@ -8,35 +8,29 @@
#include "cpu.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "version.h"
static void check_reset_cause(void)
{
enum system_image_copy_t copy = system_get_image_copy();
enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN;
uint32_t raw_cause = STM32_RCC_CSR;
/* Clear the hardware reset cause by setting the RMVF bit */
STM32_RCC_CSR |= 1 << 24;
if (copy == SYSTEM_IMAGE_RW_A || copy == SYSTEM_IMAGE_RW_B) {
/* If we're in image A or B, the only way we can get there is
* via a warm reset. */
reset_cause = SYSTEM_RESET_SOFT_WARM;
} else if (raw_cause & 0x60000000) {
if (raw_cause & 0x60000000) {
/* IWDG pr WWDG */
reset_cause = SYSTEM_RESET_WATCHDOG;
} else if (raw_cause & 0x10000000) {
reset_cause = SYSTEM_RESET_SOFT_COLD;
reset_cause = SYSTEM_RESET_SOFT;
} else if (raw_cause & 0x08000000) {
reset_cause = SYSTEM_RESET_POWER_ON;
} else if (raw_cause & 0x04000000) {
reset_cause = SYSTEM_RESET_RESET_PIN;
} else if (raw_cause & 0xFE000000) {
reset_cause = SYSTEM_RESET_OTHER;
} else {
reset_cause = SYSTEM_RESET_UNKNOWN;
}
system_set_reset_cause(reset_cause);
}
@@ -87,19 +81,18 @@ int system_pre_init(void)
}
int system_reset(int is_cold)
void system_reset(int is_hard)
{
/* TODO: (crosbug.com/p/7470) support cold boot; this is a
warm boot. */
/* Disable interrupts to avoid task swaps during reboot */
interrupt_disable();
/* TODO: (crosbug.com/p/7470) support hard boot; this is a
* soft boot. */
CPU_NVIC_APINT = 0x05fa0004;
/* Spin and wait for reboot; should never return */
/* TODO: (crosbug.com/p/7471) should disable task swaps while
waiting */
while (1)
;
return EC_ERROR_UNKNOWN;
}

View File

@@ -155,8 +155,7 @@ const char *system_get_reset_cause_string(void)
{
static const char * const cause_descs[] = {
"unknown", "other", "brownout", "power-on", "reset pin",
"soft cold", "soft warm", "watchdog", "rtc alarm", "wake pin",
"low battery"};
"soft", "watchdog", "rtc alarm", "wake pin", "low battery"};
return reset_cause < ARRAY_SIZE(cause_descs) ?
cause_descs[reset_cause] : "?";
@@ -356,10 +355,12 @@ const char *system_get_build_info(void)
int system_common_pre_init(void)
{
/* Check jump data if this is a jump between images */
/* Check jump data if this is a jump between images. Jumps all show up
* as an unknown reset reason, because we jumped directly from one
* image to another without actually triggering a chip reset. */
if (jdata->magic == JUMP_DATA_MAGIC &&
jdata->version >= 1 &&
reset_cause == SYSTEM_RESET_SOFT_WARM) {
reset_cause == SYSTEM_RESET_UNKNOWN) {
int delta; /* Change in jump data struct size between the
* previous image and this one. */
@@ -533,9 +534,16 @@ DECLARE_CONSOLE_COMMAND(sysjump, command_sysjump);
static int command_reboot(int argc, char **argv)
{
int is_hard = 0;
if (argc == 2 && !strcasecmp(argv[1], "hard")) {
ccputs("Hard-");
is_hard = 1;
}
ccputs("Rebooting!\n\n\n");
cflush();
system_reset(1);
system_reset(is_hard);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(reboot, command_reboot);

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
@@ -60,6 +60,7 @@ panic:
panic_print:
ldr r0, =msg_excep @ pointer to the text buffer
bl emergency_puts @ print the banner
mov r0, #0 @ Soft boot
b system_reset @ Reboot the system
/* Helpers for exception trace */

View File

@@ -12,29 +12,17 @@
/* Reset causes */
enum system_reset_cause_t {
/* Unknown reset cause */
SYSTEM_RESET_UNKNOWN = 0,
/* System reset cause is known, but not one of the causes
* listed below */
SYSTEM_RESET_OTHER,
/* Brownout */
SYSTEM_RESET_BROWNOUT,
/* Power-on reset */
SYSTEM_RESET_POWER_ON,
/* Reset caused by asserting reset (RST#) pin */
SYSTEM_RESET_RESET_PIN,
/* Software requested cold reset */
SYSTEM_RESET_SOFT_COLD,
/* Software requested warm reset */
SYSTEM_RESET_SOFT_WARM,
/* Watchdog timer reset */
SYSTEM_RESET_WATCHDOG,
/* the RTC alarm triggered power on */
SYSTEM_RESET_RTC_ALARM,
/* the Wake pin triggered power on */
SYSTEM_RESET_WAKE_PIN,
/* the low battery detection triggered power on */
SYSTEM_RESET_LOW_BATTERY,
SYSTEM_RESET_UNKNOWN = 0, /* Unknown reset cause */
SYSTEM_RESET_OTHER, /* System reset cause is known, but not one
* of the causes listed below */
SYSTEM_RESET_BROWNOUT, /* Brownout */
SYSTEM_RESET_POWER_ON, /* Power-on reset */
SYSTEM_RESET_RESET_PIN, /* Reset pin asserted */
SYSTEM_RESET_SOFT, /* Soft reset trigger by core */
SYSTEM_RESET_WATCHDOG, /* Watchdog timer reset */
SYSTEM_RESET_RTC_ALARM, /* RTC alarm wake */
SYSTEM_RESET_WAKE_PIN, /* Wake pin triggered wake */
SYSTEM_RESET_LOW_BATTERY, /* Low battery triggered wake */
};
/* System images */
@@ -114,12 +102,10 @@ int system_get_board_version(void);
*/
const char *system_get_build_info(void);
/* Resets the system. If is_cold!=0, performs a cold reset (which
* resets on-chip peripherals); else performs a warm reset (which does
* not reset on-chip peripherals). If successful, does not return.
* Returns error if the reboot type cannot be requested (e.g. brownout
* or reset pin). */
int system_reset(int is_cold);
/* Resets the system. If is_hard, performs a hard reset, which cuts power to
* the entire system; else performs a soft reset (which resets the core and
* on-chip peripherals, without actually cutting power to the chip). */
void system_reset(int is_hard);
/* Sets a scratchpad register to the specified value. The scratchpad
* register must maintain its contents across a software-requested