summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Anderson <dianders@chromium.org>2013-08-27 12:55:09 -0700
committerCaroline Tice <cmtice@chromium.org>2013-08-29 22:51:11 +0000
commit3f4899b6b0e97d6fca4cde0a9bb44c98c258a012 (patch)
tree658cfe3d4dfce7e12347fb18fd5910904f5e1da7
parentfcd388df8eef2f723cb4ff7277fa44d3754bb966 (diff)
downloadchrome-ec-3f4899b6b0e97d6fca4cde0a9bb44c98c258a012.tar.gz
stm32l: Add a "PRE_FREQ_CHANGE" hook to allow other code to prepare
Before this change drivers had no way of knowing that a frequency change was coming. This could cause problems for some drivers (like i2c) that need to make sure that a transaction isn't happening while a frequency change is happening. The PRE_FREQ_CHANGE archiecture is very simple here and we don't allow any way to cancel it. At the moment, we guarantee: - We won't call PRE_FREQ_CHANGE with interrupts disabled, so acquiring locks / sleeping is OK. - We'll call the actual HOOK_FREQ_CHANGE after the PRE_FREQ_CHANGE. PRE_FREQ_CHANGE and HOOK_FREQ_CHANGE should not use deferred function calls. BRANCH=pit BUG=chrome-os-partner:22093 TEST=With all patches together: - on AP: suspend_stress_test - on EC: battery 10000 50 Change-Id: I2731a3e85d41e749fa571fdb74b5c9b12043cda6 Signed-off-by: Doug Anderson <dianders@chromium.org> Previous-Reviewed-on: https://chromium-review.googlesource.com/167101 (cherry picked from commit d84c0dbbf7c5a72917a820e292ecfdfa698d0fb9) Reviewed-on: https://chromium-review.googlesource.com/167148 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/stm32/clock-stm32l.c3
-rw-r--r--common/hooks.c1
-rw-r--r--core/cortex-m/ec.lds.S4
-rw-r--r--core/host/host_exe.lds4
-rw-r--r--include/hooks.h9
-rw-r--r--include/link_defs.h2
6 files changed, 21 insertions, 2 deletions
diff --git a/chip/stm32/clock-stm32l.c b/chip/stm32/clock-stm32l.c
index 4d5b1babeb..e89c2e3ef5 100644
--- a/chip/stm32/clock-stm32l.c
+++ b/chip/stm32/clock-stm32l.c
@@ -59,6 +59,9 @@ static void clock_set_osc(enum clock_osc osc)
if (osc == current_osc)
return;
+ if (current_osc != OSC_INIT)
+ hook_notify(HOOK_PRE_FREQ_CHANGE);
+
switch (osc) {
case OSC_HSI:
/* Ensure that HSI is ON */
diff --git a/common/hooks.c b/common/hooks.c
index cd2941434c..59038008a8 100644
--- a/common/hooks.c
+++ b/common/hooks.c
@@ -33,6 +33,7 @@ struct hook_ptrs {
*/
static const struct hook_ptrs hook_list[] = {
{__hooks_init, __hooks_init_end},
+ {__hooks_pre_freq_change, __hooks_pre_freq_change_end},
{__hooks_freq_change, __hooks_freq_change_end},
{__hooks_sysjump, __hooks_sysjump_end},
{__hooks_chipset_pre_init, __hooks_chipset_pre_init_end},
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index c5d90265ce..115310bc28 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -60,6 +60,10 @@ SECTIONS
*(.rodata.HOOK_INIT)
__hooks_init_end = .;
+ __hooks_pre_freq_change = .;
+ *(.rodata.HOOK_PRE_FREQ_CHANGE)
+ __hooks_pre_freq_change_end = .;
+
__hooks_freq_change = .;
*(.rodata.HOOK_FREQ_CHANGE)
__hooks_freq_change_end = .;
diff --git a/core/host/host_exe.lds b/core/host/host_exe.lds
index 04e605287b..15925213a7 100644
--- a/core/host/host_exe.lds
+++ b/core/host/host_exe.lds
@@ -24,6 +24,10 @@ SECTIONS {
*(.rodata.HOOK_INIT)
__hooks_init_end = .;
+ __hooks_pre_freq_change = .;
+ *(.rodata.HOOK_PRE_FREQ_CHANGE)
+ __hooks_pre_freq_change_end = .;
+
__hooks_freq_change = .;
*(.rodata.HOOK_FREQ_CHANGE)
__hooks_freq_change_end = .;
diff --git a/include/hooks.h b/include/hooks.h
index 2ef5523d1d..6862005379 100644
--- a/include/hooks.h
+++ b/include/hooks.h
@@ -46,9 +46,14 @@ enum hook_type {
/*
* System clock changed frequency.
*
- * Hook routines are called from the context which initiates the
- * frequency change.
+ * The "pre" frequency hook is called before we change the frequency.
+ * There is no way to cancel. Hook routines are always called from
+ * a task, so it's OK to lock a mutex here. However, they may be called
+ * from a deferred task on some platforms so callbacks must make sure
+ * not to do anything that would require some other deferred task to
+ * run.
*/
+ HOOK_PRE_FREQ_CHANGE,
HOOK_FREQ_CHANGE,
/*
diff --git a/include/link_defs.h b/include/link_defs.h
index a9c9e97e41..d5e4ccd595 100644
--- a/include/link_defs.h
+++ b/include/link_defs.h
@@ -20,6 +20,8 @@ extern const struct console_command __cmds_end[];
/* Hooks */
extern const struct hook_data __hooks_init[];
extern const struct hook_data __hooks_init_end[];
+extern const struct hook_data __hooks_pre_freq_change[];
+extern const struct hook_data __hooks_pre_freq_change_end[];
extern const struct hook_data __hooks_freq_change[];
extern const struct hook_data __hooks_freq_change_end[];
extern const struct hook_data __hooks_sysjump[];