diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-05-18 15:56:30 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-05-21 09:17:43 -0700 |
commit | b1bb8314bd852dea40bc7514486ce4e781e14f88 (patch) | |
tree | b313282cf66c622fb7d008f51c9a7e27c721bb82 | |
parent | 8407b93f6ddbd1533adc87a650913c4581a15f41 (diff) | |
download | chrome-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.c | 42 | ||||
-rw-r--r-- | chip/stm32/system.c | 25 | ||||
-rw-r--r-- | common/system_common.c | 18 | ||||
-rw-r--r-- | core/cortex-m/panic.S | 3 | ||||
-rw-r--r-- | include/system.h | 44 |
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 |