summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/stm32/clock-stm32f0.c8
-rw-r--r--common/system.c5
-rw-r--r--include/config.h3
-rw-r--r--include/system.h24
4 files changed, 40 insertions, 0 deletions
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c
index 2db0244cf9..d324e8bab5 100644
--- a/chip/stm32/clock-stm32f0.c
+++ b/chip/stm32/clock-stm32f0.c
@@ -322,6 +322,11 @@ void __idle(void)
t0 = get_time();
next_delay = __hw_clock_event_get() - t0.le.lo;
+#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
+ if (idle_is_disabled())
+ goto en_int;
+#endif
+
if (DEEP_SLEEP_ALLOWED &&
#ifdef CONFIG_HOSTCMD_RTC
/*
@@ -381,6 +386,9 @@ void __idle(void)
/* normal idle : only CPU clock stopped */
asm("wfi");
}
+#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
+en_int:
+#endif
asm volatile("cpsie i");
}
}
diff --git a/common/system.c b/common/system.c
index 64bfabbbc2..aa3e48db34 100644
--- a/common/system.c
+++ b/common/system.c
@@ -102,6 +102,11 @@ static enum ec_reboot_cmd reboot_at_shutdown;
/* On-going actions preventing going into deep-sleep mode */
uint32_t sleep_mask;
+#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
+/* Set it to prevent going into idle mode */
+uint32_t idle_disabled;
+#endif
+
#ifdef CONFIG_HOSTCMD_AP_SET_SKUID
static uint32_t ap_sku_id;
diff --git a/include/config.h b/include/config.h
index 64d56395d6..d19b91cc58 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2061,6 +2061,9 @@
#undef CONFIG_LOW_POWER_IDLE
#undef CONFIG_LOW_POWER_USE_LFIOSC
+/* Allows us to enable/disable low power idle mode in runtime. */
+#undef CONFIG_LOW_POWER_IDLE_LIMITED
+
/*
* Enable deep sleep during S0 (ignores SLEEP_MASK_AP_RUN).
*/
diff --git a/include/system.h b/include/system.h
index acc3f71471..9b58203c5c 100644
--- a/include/system.h
+++ b/include/system.h
@@ -479,6 +479,30 @@ static inline void disable_sleep(uint32_t mask)
atomic_or(&sleep_mask, mask);
}
+#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
+/*
+ * If this variable is nonzero, all levels of idle modes are disabled.
+ * Do NOT access it directly. Use idle_is_disabled() to read it and
+ * enable_idle()/disable_idle() to write it.
+ */
+extern uint32_t idle_disabled;
+
+static inline uint32_t idle_is_disabled(void)
+{
+ return idle_disabled;
+}
+
+static inline void disable_idle(void)
+{
+ atomic_or(&idle_disabled, 1);
+}
+
+static inline void enable_idle(void)
+{
+ atomic_clear(&idle_disabled, 1);
+}
+#endif
+
/* The following three functions are not available on all chips. */
/**
* Postpone sleeping for at least this long, regardless of sleep_mask.