diff options
-rw-r--r-- | common/hooks.c | 45 | ||||
-rw-r--r-- | include/hooks.h | 117 |
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 { |