mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user