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>
This commit is contained in:
nagendra modadugu
2015-11-04 18:00:55 -08:00
committed by Nagendra Modadugu
parent e997753117
commit e97da2f17c
2 changed files with 52 additions and 8 deletions

View File

@@ -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);
}

View File

@@ -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;
} 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. */
/* Spin and wait for reboot; should never return */
while (1)
;
/* 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)