diff options
-rw-r--r-- | chip/it83xx/registers.h | 1 | ||||
-rw-r--r-- | chip/it83xx/system.c | 70 |
2 files changed, 70 insertions, 1 deletions
diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h index e27840796d..bacdc18d33 100644 --- a/chip/it83xx/registers.h +++ b/chip/it83xx/registers.h @@ -529,6 +529,7 @@ enum clock_gate_offsets { #define IT83XX_GCTRL_BASE 0x00F02000 #define IT83XX_GCTRL_WNCKR REG8(IT83XX_GCTRL_BASE+0x0B) +#define IT83XX_GCTRL_RSTS REG8(IT83XX_GCTRL_BASE+0x06) /* --- MISC (not implemented yet) --- */ diff --git a/chip/it83xx/system.c b/chip/it83xx/system.c index 731b5d64f9..e5110c83e1 100644 --- a/chip/it83xx/system.c +++ b/chip/it83xx/system.c @@ -15,19 +15,87 @@ #include "version.h" #include "watchdog.h" +/* Battery backed RAM indices. */ +enum system_bram_indices { + BRAM_INDEX_SAVED_RESET_FLAGS = 0, /* uses 4 bytes */ +}; + + + void system_hibernate(uint32_t seconds, uint32_t microseconds) { /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ } +static void check_reset_cause(void) +{ + uint32_t flags = 0; + uint8_t raw_reset_cause = IT83XX_GCTRL_RSTS & 0x03; + + /* Clear reset cause. */ + IT83XX_GCTRL_RSTS |= 0x01; + + /* Determine if watchdog reset or power on reset. */ + if (raw_reset_cause & 0x02) + flags |= RESET_FLAG_WATCHDOG; + else + flags |= RESET_FLAG_POWER_ON; + + /* Restore then clear saved reset flags. */ + flags |= REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS) << 24; + flags |= REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+1) << 16; + flags |= REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+2) << 8; + flags |= REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+3); + + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS) = 0; + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+1) = 0; + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+2) = 0; + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+3) = 0; + + system_set_reset_flags(flags); +} + void system_pre_init(void) { /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + + check_reset_cause(); } void system_reset(int flags) { - /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + uint32_t save_flags = 0; + + /* Disable interrupts to avoid task swaps during reboot. */ + interrupt_disable(); + + /* Save current reset reasons if necessary */ + if (flags & SYSTEM_RESET_PRESERVE_FLAGS) + save_flags = system_get_reset_flags() | RESET_FLAG_PRESERVED; + + /* Add in AP off flag into saved flags. */ + if (flags & SYSTEM_RESET_LEAVE_AP_OFF) + save_flags |= RESET_FLAG_AP_OFF; + + /* Store flags to battery backed RAM. */ + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS) = save_flags >> 24; + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+1) = + (save_flags >> 16) & 0xff; + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+2) = + (save_flags >> 8) & 0xff; + REG8(IT83XX_BRAM_BASE+BRAM_INDEX_SAVED_RESET_FLAGS+3) = + save_flags & 0xff; + + /* + * Writing invalid key to watchdog module triggers a soft reset. For + * now this is the only option, no hard reset. + */ + IT83XX_ETWD_ETWCFG |= 0x20; + IT83XX_ETWD_EWDKEYR = 0x00; + + /* Spin and wait for reboot; should never return */ + while (1) + ; } int system_set_scratchpad(uint32_t value) |