From 4ef1969a5026b457ff9f9194042e065f4dd129e5 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Fri, 5 Dec 2014 11:08:11 -0800 Subject: g: update reset code - record and display reset cause - add the hard reset option - add the scratchpad to store values across reboots. Signed-off-by: Vincent Palatin BRANCH=none BUG=chrome-os-partner:33818 TEST=On the console command line, chech the "[Reset cause: xxx]" string - for the initial reset cause - use "waitms 4000" to trigger a watchdog reset - use "reboot soft" - use "reboot hard" The "utils" test is now building and passing. Change-Id: I68c7096e5b7bfd102be89fd8eef6fe20da37a6f8 Reviewed-on: https://chromium-review.googlesource.com/233581 Reviewed-by: Bill Richardson Commit-Queue: Vincent Palatin Trybot-Ready: Vincent Palatin Tested-by: Vincent Palatin --- chip/g/registers.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++------- chip/g/system.c | 65 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 121 insertions(+), 16 deletions(-) diff --git a/chip/g/registers.h b/chip/g/registers.h index b257ec1cd4..1a4c9ab456 100644 --- a/chip/g/registers.h +++ b/chip/g/registers.h @@ -23,15 +23,69 @@ #define GR_PINMUX_UART0_RX_SEL REG32(GC_PINMUX_BASE_ADDR + GC_PINMUX_UART0_RX_SEL_OFFSET) #define GR_PINMUX_UART0_TX_SEL REG32(GC_PINMUX_BASE_ADDR + GC_PINMUX_UART0_TX_SEL_OFFSET) -#define GR_PMU_CLRDIS REG32(GC_PMU_BASE_ADDR + GC_PMU_CLRDIS_OFFSET) -#define GR_PMU_OSC_HOLD_SET REG32(GC_PMU_BASE_ADDR + GC_PMU_OSC_HOLD_SET_OFFSET) -#define GR_PMU_OSC_HOLD_CLR REG32(GC_PMU_BASE_ADDR + GC_PMU_OSC_HOLD_CLR_OFFSET) -#define GR_PMU_OSC_SELECT REG32(GC_PMU_BASE_ADDR + GC_PMU_OSC_SELECT_OFFSET) -#define GR_PMU_OSC_SELECT_STAT REG32(GC_PMU_BASE_ADDR + GC_PMU_OSC_SELECT_STAT_OFFSET) -#define GR_PMU_OSC_CTRL REG32(GC_PMU_BASE_ADDR + GC_PMU_OSC_CTRL_OFFSET) -#define GR_PMU_PERICLKSET0 REG32(GC_PMU_BASE_ADDR + GC_PMU_PERICLKSET0_OFFSET) -#define GR_PMU_FUSE_RD_RC_OSC_26MHZ REG32(GC_PMU_BASE_ADDR + GC_PMU_FUSE_RD_RC_OSC_26MHZ_OFFSET) -#define GR_PMU_FUSE_RD_XTL_OSC_26MHZ REG32(GC_PMU_BASE_ADDR + GC_PMU_FUSE_RD_XTL_OSC_26MHZ_OFFSET) +/* Power Management Unit */ +#define GR_PMU_REG(off) REG32(GC_PMU_BASE_ADDR + (off)) + +#define GR_PMU_RESET GR_PMU_REG(GC_PMU_RESET_OFFSET) +#define GR_PMU_SETRST GR_PMU_REG(GC_PMU_SETRST_OFFSET) +#define GR_PMU_CLRRST GR_PMU_REG(GC_PMU_CLRRST_OFFSET) +#define GR_PMU_RSTSRC GR_PMU_REG(GC_PMU_RSTSRC_OFFSET) +#define GR_PMU_GLOBAL_RESET GR_PMU_REG(GC_PMU_GLOBAL_RESET_OFFSET) +#define GR_PMU_SETDIS GR_PMU_REG(GC_PMU_SETDIS_OFFSET) +#define GR_PMU_CLRDIS GR_PMU_REG(GC_PMU_CLRDIS_OFFSET) +#define GR_PMU_STATDIS GR_PMU_REG(GC_PMU_STATDIS_OFFSET) +#define GR_PMU_SETWIC GR_PMU_REG(GC_PMU_SETWIC_OFFSET) +#define GR_PMU_CLRWIC GR_PMU_REG(GC_PMU_CLRWIC_OFFSET) +#define GR_PMU_SYSVTOR GR_PMU_REG(GC_PMU_SYSVTOR_OFFSET) +#define GR_PMU_EXCLUSIVE GR_PMU_REG(GC_PMU_EXCLUSIVE_OFFSET) +#define GR_PMU_DAP_ID0 GR_PMU_REG(GC_PMU_DAP_ID0_OFFSET) +#define GR_PMU_DAP_EN GR_PMU_REG(GC_PMU_DAP_EN_OFFSET) +#define GR_PMU_DAP_LOCK GR_PMU_REG(GC_PMU_DAP_LOCK_OFFSET) +#define GR_PMU_DAP_UNLOCK GR_PMU_REG(GC_PMU_DAP_UNLOCK_OFFSET) +#define GR_PMU_NAP_EN GR_PMU_REG(GC_PMU_NAP_EN_OFFSET) +#define GR_PMU_VREF GR_PMU_REG(GC_PMU_VREF_OFFSET) +#define GR_PMU_VREFCMP GR_PMU_REG(GC_PMU_VREFCMP_OFFSET) +#define GR_PMU_RBIAS GR_PMU_REG(GC_PMU_RBIAS_OFFSET) +#define GR_PMU_RBIASLO GR_PMU_REG(GC_PMU_RBIASLO_OFFSET) +#define GR_PMU_RBIASHI GR_PMU_REG(GC_PMU_RBIASHI_OFFSET) +#define GR_PMU_SETHOLDVREF GR_PMU_REG(GC_PMU_SETHOLDVREF_OFFSET) +#define GR_PMU_CLRHOLDVREF GR_PMU_REG(GC_PMU_CLRHOLDVREF_OFFSET) +#define GR_PMU_BAT_LVL_OK GR_PMU_REG(GC_PMU_BAT_LVL_OK_OFFSET) +#define GR_PMU_B_REG_DIG_CTRL GR_PMU_REG(GC_PMU_B_REG_DIG_CTRL_OFFSET) +#define GR_PMU_B_REG_DIG_LATCH_CTRL GR_PMU_REG(GC_PMU_B_REG_DIG_LATCH_CTRL_OFFSET) +#define GR_PMU_EXITPD_HOLD_SET GR_PMU_REG(GC_PMU_EXITPD_HOLD_SET_OFFSET) +#define GR_PMU_EXITPD_HOLD_CLR GR_PMU_REG(GC_PMU_EXITPD_HOLD_CLR_OFFSET) +#define GR_PMU_EXITPD_MASK GR_PMU_REG(GC_PMU_EXITPD_MASK_OFFSET) +#define GR_PMU_EXITPD_SRC GR_PMU_REG(GC_PMU_EXITPD_SRC_OFFSET) +#define GR_PMU_EXITPD_MON GR_PMU_REG(GC_PMU_EXITPD_MON_OFFSET) +#define GR_PMU_OSC_HOLD_SET GR_PMU_REG(GC_PMU_OSC_HOLD_SET_OFFSET) +#define GR_PMU_OSC_HOLD_CLR GR_PMU_REG(GC_PMU_OSC_HOLD_CLR_OFFSET) +#define GR_PMU_OSC_SELECT GR_PMU_REG(GC_PMU_OSC_SELECT_OFFSET) +#define GR_PMU_OSC_SELECT_STAT GR_PMU_REG(GC_PMU_OSC_SELECT_STAT_OFFSET) +#define GR_PMU_OSC_CTRL GR_PMU_REG(GC_PMU_OSC_CTRL_OFFSET) +#define GR_PMU_MEMCLKSET GR_PMU_REG(GC_PMU_MEMCLKSET_OFFSET) +#define GR_PMU_MEMCLKCLR GR_PMU_REG(GC_PMU_MEMCLKCLR_OFFSET) +#define GR_PMU_PERICLKSET0 GR_PMU_REG(GC_PMU_PERICLKSET0_OFFSET) +#define GR_PMU_PERICLKCLR0 GR_PMU_REG(GC_PMU_PERICLKCLR0_OFFSET) +#define GR_PMU_PERICLKSET1 GR_PMU_REG(GC_PMU_PERICLKSET1_OFFSET) +#define GR_PMU_PERICLKCLR1 GR_PMU_REG(GC_PMU_PERICLKCLR1_OFFSET) +#define GR_PMU_PERIGATEONSLEEPSET0 GR_PMU_REG(GC_PMU_PERIGATEONSLEEPSET0_OFFSET) +#define GR_PMU_PERIGATEONSLEEPCLR0 GR_PMU_REG(GC_PMU_PERIGATEONSLEEPCLR0_OFFSET) +#define GR_PMU_PERIGATEONSLEEPSET1 GR_PMU_REG(GC_PMU_PERIGATEONSLEEPSET1_OFFSET) +#define GR_PMU_PERIGATEONSLEEPCLR1 GR_PMU_REG(GC_PMU_PERIGATEONSLEEPCLR1_OFFSET) +#define GR_PMU_CLK0 GR_PMU_REG(GC_PMU_CLK0_OFFSET) +#define GR_PMU_CLK1 GR_PMU_REG(GC_PMU_CLK1_OFFSET) +#define GR_PMU_RST0 GR_PMU_REG(GC_PMU_RST0_OFFSET) +#define GR_PMU_RST1 GR_PMU_REG(GC_PMU_RST1_OFFSET) +#define GR_PMU_PWRDN_SCRATCH_HOLD_SET GR_PMU_REG(GC_PMU_PWRDN_SCRATCH_HOLD_SET_OFFSET) +#define GR_PMU_PWRDN_SCRATCH_HOLD_CLR GR_PMU_REG(GC_PMU_PWRDN_SCRATCH_HOLD_CLR_OFFSET) +#define GR_PMU_PWRDN_SCRATCH0 GR_PMU_REG(GC_PMU_PWRDN_SCRATCH0_OFFSET) +#define GR_PMU_PWRDN_SCRATCH1 GR_PMU_REG(GC_PMU_PWRDN_SCRATCH1_OFFSET) +#define GR_PMU_PWRDN_SCRATCH2 GR_PMU_REG(GC_PMU_PWRDN_SCRATCH2_OFFSET) +#define GR_PMU_PWRDN_SCRATCH3 GR_PMU_REG(GC_PMU_PWRDN_SCRATCH3_OFFSET) + +#define GR_PMU_FUSE_RD_RC_OSC_26MHZ GR_PMU_REG(GC_PMU_FUSE_RD_RC_OSC_26MHZ_OFFSET) +#define GR_PMU_FUSE_RD_XTL_OSC_26MHZ GR_PMU_REG(GC_PMU_FUSE_RD_XTL_OSC_26MHZ_OFFSET) /* More than one UART */ BUILD_ASSERT(GC_UART1_BASE_ADDR - GC_UART0_BASE_ADDR == GC_UART2_BASE_ADDR - GC_UART1_BASE_ADDR); diff --git a/chip/g/system.c b/chip/g/system.c index 342998b6ce..f22f2b819d 100644 --- a/chip/g/system.c +++ b/chip/g/system.c @@ -4,20 +4,58 @@ */ #include "cpu.h" -#include "system.h" #include "registers.h" +#include "system.h" +#include "task.h" -void system_pre_init(void) +static void check_reset_cause(void) { + uint32_t reset_source = GR_PMU_RSTSRC; + uint32_t flags = 0; + + /* Clear the reset source now we have recorded it */ + GR_PMU_CLRRST = 1; + + if (reset_source & (1 << GC_PMU_RSTSRC_POR_LSB)) + flags |= RESET_FLAG_POWER_ON; + else if (reset_source & (1 << GC_PMU_RSTSRC_RESETB_LSB)) + flags |= RESET_FLAG_RESET_PIN; + else if (reset_source & (1 << GC_PMU_RSTSRC_EXIT_LSB)) + flags |= RESET_FLAG_WAKE_PIN; + + if (reset_source & (1 << GC_PMU_RSTSRC_WDOG_LSB)) + flags |= RESET_FLAG_WATCHDOG; + if (reset_source & (1 << GC_PMU_RSTSRC_SOFTWARE_LSB)) + flags |= RESET_FLAG_HARD; + if (reset_source & (1 << GC_PMU_RSTSRC_SYSRESET_LSB)) + flags |= RESET_FLAG_SOFT; + + if (reset_source & (1 << GC_PMU_RSTSRC_FST_BRNOUT_LSB)) + flags |= RESET_FLAG_BROWNOUT; + + if (reset_source && !flags) + flags |= RESET_FLAG_OTHER; + + system_set_reset_flags(flags); +} + +void system_pre_init(void) +{ + check_reset_cause(); } -/* TODO(crosbug.com/p/33818): How do we force a reset? */ void system_reset(int flags) { - /* Until we have a full microcontroller, at least reset the CPU core */ - CPU_NVIC_APINT = 0x05fa0004; - /* should be gone here */ + /* Disable interrupts to avoid task swaps during reboot */ + interrupt_disable(); + + 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) ; } @@ -37,8 +75,21 @@ const char *system_get_chip_revision(void) return GC_REVISION_STR; } -/* TODO(crosbug.com/p/33822): Where can we store stuff persistently? */ +int system_set_scratchpad(uint32_t value) +{ + GR_PMU_PWRDN_SCRATCH_HOLD_CLR = 1; + GR_PMU_PWRDN_SCRATCH0 = value; + GR_PMU_PWRDN_SCRATCH_HOLD_SET = 1; + return EC_SUCCESS; +} + +uint32_t system_get_scratchpad(void) +{ + return GR_PMU_PWRDN_SCRATCH0; +} + +/* TODO(crosbug.com/p/33822): Where can we store stuff persistently? */ int system_get_vbnvcontext(uint8_t *block) { return 0; -- cgit v1.2.1