summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
Diffstat (limited to 'chip')
-rw-r--r--chip/it83xx/registers.h1
-rw-r--r--chip/it83xx/system.c70
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)