summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagendra modadugu <ngm@google.com>2015-11-04 18:00:55 -0800
committerNagendra Modadugu <ngm@google.com>2015-11-06 20:23:10 +0000
commite97da2f17c8eb188c09177b821521bebf5d830ea (patch)
treee5d64ab0f338499c384aad38eb5573b0e87de9bc
parente99775311728eb01e47d5c5d29156f13842ca721 (diff)
downloadchrome-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.c24
-rw-r--r--chip/g/system.c38
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)