diff options
author | nagendra modadugu <ngm@google.com> | 2015-11-04 18:00:55 -0800 |
---|---|---|
committer | Nagendra Modadugu <ngm@google.com> | 2015-11-06 20:23:10 +0000 |
commit | e97da2f17c8eb188c09177b821521bebf5d830ea (patch) | |
tree | e5d64ab0f338499c384aad38eb5573b0e87de9bc | |
parent | e99775311728eb01e47d5c5d29156f13842ca721 (diff) | |
download | chrome-ec-e97da2f17c8eb188c09177b821521bebf5d830ea.tar.gz |
Fix soft reboot to handle dropped permissions.
Permission registers only reset on power cycle,
so a soft reboot will fail unless a minimum power
cycle is performed.
BRANCH=none
BUG=chrome-os-partner:47289,chrome-os-partner:43025
TEST=hard / soft reboot from ec shell
Signed-off-by: nagendra modadugu <ngm@google.com>
Change-Id: I8f0f1bc80a2748b031a9b7a3715485577f2b5b3b
Reviewed-on: https://chromium-review.googlesource.com/310975
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Tested-by: Nagendra Modadugu <ngm@google.com>
Commit-Queue: Nagendra Modadugu <ngm@google.com>
Trybot-Ready: Nagendra Modadugu <ngm@google.com>
-rw-r--r-- | board/cr50/board.c | 24 | ||||
-rw-r--r-- | chip/g/system.c | 38 |
2 files changed, 53 insertions, 9 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index b90234d02d..972506e383 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -65,7 +65,25 @@ void button_event(enum gpio_signal signal) gpio_set_level(signal - GPIO_SW_N + GPIO_LED_4, v); } -static void init_interrutps(void) +static void init_pmu(void) +{ + /* This boot sequence may be a result of previous soft reset, + * in which case the PMU low power sequence register needs to + * be reset. */ + GREG32(PMU, LOW_POWER_DIS) = 0; +} + +static void init_timers(void) +{ + /* Cancel low speed timers that may have + * been initialized prior to soft reset. */ + GREG32(TIMELS, TIMER0_CONTROL) = 0; + GREG32(TIMELS, TIMER0_LOAD) = 0; + GREG32(TIMELS, TIMER1_CONTROL) = 0; + GREG32(TIMELS, TIMER1_LOAD) = 0; +} + +static void init_interrupts(void) { int i; static const enum gpio_signal gpio_signals[] = { @@ -113,7 +131,9 @@ static void init_runlevel(const enum permission_level desired_level) /* Initialize board. */ static void board_init(void) { - init_interrutps(); + init_pmu(); + init_timers(); + init_interrupts(); init_trng(); init_runlevel(PERMISSION_MEDIUM); } diff --git a/chip/g/system.c b/chip/g/system.c index 761849ad1c..0fc3334a4e 100644 --- a/chip/g/system.c +++ b/chip/g/system.c @@ -48,14 +48,38 @@ void system_reset(int flags) /* Disable interrupts to avoid task swaps during reboot */ interrupt_disable(); - if (flags & SYSTEM_RESET_HARD) /* Reset the full microcontroller */ + if (flags & SYSTEM_RESET_HARD) { + /* Reset the full microcontroller */ GR_PMU_GLOBAL_RESET = GC_PMU_GLOBAL_RESET_KEY; - else /* Reset only the CPU core */ - CPU_NVIC_APINT = 0x05fa0004; - - /* Spin and wait for reboot; should never return */ - while (1) - ; + } else { + /* Soft reset is also fairly hard, and requires + * permission registers to be reset to their initial + * state. To accomplish this, first register a wakeup + * timer and then enter lower power mode. */ + + /* Low speed timers continue to run in low power mode. */ + GREG32(TIMELS, TIMER1_CONTROL) = 0x1; + /* Wait for this long. */ + GREG32(TIMELS, TIMER1_LOAD) = 1; + /* Setup wake-up on Timer1 firing. */ + GREG32(PMU, EXITPD_MASK) = + GC_PMU_EXITPD_MASK_TIMELS0_PD_EXIT_TIMER1_MASK; + + /* All the components to power cycle. */ + GREG32(PMU, LOW_POWER_DIS) = + GC_PMU_LOW_POWER_DIS_VDDL_MASK | + GC_PMU_LOW_POWER_DIS_VDDIOF_MASK | + GC_PMU_LOW_POWER_DIS_VDDXO_MASK | + GC_PMU_LOW_POWER_DIS_JTR_RC_MASK; + /* Start low power sequence. */ + REG_WRITE_MLV(GREG32(PMU, LOW_POWER_DIS), + GC_PMU_LOW_POWER_DIS_START_MASK, + GC_PMU_LOW_POWER_DIS_START_LSB, + 1); + } + + /* Wait for reboot; should never return */ + asm("wfi"); } const char *system_get_chip_vendor(void) |