summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/hooks.c45
-rw-r--r--include/hooks.h117
2 files changed, 131 insertions, 31 deletions
diff --git a/common/hooks.c b/common/hooks.c
index a17cf1ade1..4704992de0 100644
--- a/common/hooks.c
+++ b/common/hooks.c
@@ -1,10 +1,12 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* System hooks for Chrome EC */
+#include "atomic.h"
+#include "console.h"
#include "hooks.h"
#include "link_defs.h"
#include "timer.h"
@@ -34,7 +36,12 @@ static const struct hook_ptrs hook_list[] = {
{__hooks_second, __hooks_second_end},
};
-void hook_notify(enum hook_type type)
+static uint32_t pending_hooks;
+
+/**
+ * Actual notification function
+ */
+static void notify(enum hook_type type)
{
const struct hook_data *start, *end, *p;
int count, called = 0;
@@ -63,18 +70,46 @@ void hook_notify(enum hook_type type)
}
}
+void hook_notify(enum hook_type type)
+{
+ if (type == HOOK_AC_CHANGE) {
+ /* Store deferred hook and wake task */
+ atomic_or(&pending_hooks, 1 << type);
+ task_wake(TASK_ID_TICK);
+ } else {
+ /* Notify now */
+ notify(type);
+ }
+}
+
void hook_task(void)
{
- /* Per-second hook will be called first time through the loop */
+ /* Periodic hooks will be called first time through the loop */
static uint64_t last_second = -SECOND;
+ static uint64_t last_tick = -HOOK_TICK_INTERVAL;
while (1) {
uint64_t t = get_time().val;
+ uint32_t pending = atomic_read_clear(&pending_hooks);
+ int i;
+
+ /* Call pending hooks, if any */
+ for (i = 0; pending && i < 32; i++) {
+ const uint32_t mask = 1 << i;
+
+ if (pending & mask) {
+ notify(i);
+ pending ^= mask;
+ }
+ }
- hook_notify(HOOK_TICK);
+ if (t - last_tick >= HOOK_TICK_INTERVAL) {
+ notify(HOOK_TICK);
+ last_tick = t;
+ }
if (t - last_second >= SECOND) {
- hook_notify(HOOK_SECOND);
+ notify(HOOK_SECOND);
last_second = t;
}
diff --git a/include/hooks.h b/include/hooks.h
index 6e6c1c8e3c..c07877feca 100644
--- a/include/hooks.h
+++ b/include/hooks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -24,31 +24,96 @@ enum hook_priority {
};
enum hook_type {
- HOOK_INIT = 0, /* System init */
- HOOK_FREQ_CHANGE, /* System clock changed frequency */
- HOOK_SYSJUMP, /* About to jump to another image. Modules
- * which need to preserve data across such a
- * jump should save it here and restore it in
- * HOOK_INIT.
- *
- * NOTE: This hook is called with interrupts
- * disabled! */
- HOOK_CHIPSET_PRE_INIT, /* Initialization for components such as PMU to
- * be done before host chipset/AP starts up. */
- HOOK_CHIPSET_STARTUP, /* System is starting up. All suspend rails are
- * now on. */
- HOOK_CHIPSET_RESUME, /* System is resuming from suspend, or booting
- * and has reached the point where all voltage
- * rails are on */
- HOOK_CHIPSET_SUSPEND, /* System is suspending, or shutting down; all
- * voltage rails are still on */
- HOOK_CHIPSET_SHUTDOWN, /* System is shutting down. All suspend rails
- * are still on. */
- HOOK_AC_CHANGE, /* AC power plugged in or removed */
- HOOK_LID_CHANGE, /* Lid opened or closed. Based on debounced lid
- * state, not raw lid GPIO input. */
- HOOK_TICK, /* Periodic tick, every HOOK_TICK_INTERVAL */
- HOOK_SECOND, /* Periodic tick, every second */
+ /*
+ * System initialization.
+ *
+ * Hook routines are called from main(), after all hard-coded inits,
+ * before task scheduling is enabled.
+ */
+ HOOK_INIT = 0,
+
+ /*
+ * System clock changed frequency.
+ *
+ * Hook routines are called from the context which initiates the
+ * frequency change.
+ */
+ HOOK_FREQ_CHANGE,
+
+ /*
+ * About to jump to another image. Modules which need to preserve data
+ * across such a jump should save it here and restore it in HOOK_INIT.
+ *
+ * Hook routines are called from the context which initiates the jump,
+ * WITH INTERRUPTS DISABLED.
+ */
+ HOOK_SYSJUMP,
+
+ /*
+ * Initialization for components such as PMU to be done before host
+ * chipset/AP starts up.
+ *
+ * Hook routines are called from the chipset task.
+ */
+ HOOK_CHIPSET_PRE_INIT,
+
+ /* System is starting up. All suspend rails are now on.
+ *
+ * Hook routines are called from the chipset task.
+ */
+ HOOK_CHIPSET_STARTUP,
+
+ /*
+ * System is resuming from suspend, or booting and has reached the
+ * point where all voltage rails are on.
+ *
+ * Hook routines are called from the chipset task.
+ */
+ HOOK_CHIPSET_RESUME,
+
+ /*
+ * System is suspending, or shutting down; all voltage rails are still
+ * on.
+ *
+ * Hook routines are called from the chipset task.
+ */
+ HOOK_CHIPSET_SUSPEND,
+
+ /*
+ * System is shutting down. All suspend rails are still on.
+ *
+ * Hook routines are called from the chipset task.
+ */
+ HOOK_CHIPSET_SHUTDOWN,
+
+ /*
+ * AC power plugged in or removed.
+ *
+ * Hook routines are called from the TICK task.
+ */
+ HOOK_AC_CHANGE,
+
+ /*
+ * Lid opened or closed. Based on debounced lid state, not raw lid
+ * GPIO input.
+ *
+ * Hook routines are called from the chipset task.
+ */
+ HOOK_LID_CHANGE,
+
+ /*
+ * Periodic tick, every HOOK_TICK_INTERVAL.
+ *
+ * Hook routines will be called from the TICK task.
+ */
+ HOOK_TICK,
+
+ /*
+ * Periodic tick, every second.
+ *
+ * Hook routines will be called from the TICK task.
+ */
+ HOOK_SECOND,
};
struct hook_data {