summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-05-18 15:56:30 -0700
committerRandall Spangler <rspangler@chromium.org>2012-05-21 09:17:43 -0700
commitb1bb8314bd852dea40bc7514486ce4e781e14f88 (patch)
treeb313282cf66c622fb7d008f51c9a7e27c721bb82
parent8407b93f6ddbd1533adc87a650913c4581a15f41 (diff)
downloadchrome-ec-b1bb8314bd852dea40bc7514486ce4e781e14f88.tar.gz
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
-rw-r--r--chip/lm4/system.c42
-rw-r--r--chip/stm32/system.c25
-rw-r--r--common/system_common.c18
-rw-r--r--core/cortex-m/panic.S3
-rw-r--r--include/system.h44
5 files changed, 62 insertions, 70 deletions
diff --git a/chip/lm4/system.c b/chip/lm4/system.c
index e2aedd3691..f4ac7bbb15 100644
--- a/chip/lm4/system.c
+++ b/chip/lm4/system.c
@@ -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;
}
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 8515a4bff3..1f7a66b5a7 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -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;
}
diff --git a/common/system_common.c b/common/system_common.c
index f1f530a273..018181870e 100644
--- a/common/system_common.c
+++ b/common/system_common.c
@@ -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);
diff --git a/core/cortex-m/panic.S b/core/cortex-m/panic.S
index 766af75143..f9ea888713 100644
--- a/core/cortex-m/panic.S
+++ b/core/cortex-m/panic.S
@@ -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 */
diff --git a/include/system.h b/include/system.h
index 4aeac7b2c6..33297dbc3f 100644
--- a/include/system.h
+++ b/include/system.h
@@ -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