diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-04-18 13:03:38 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-04-19 08:39:41 -0700 |
commit | 70f3fcaf8648230a5cd27a9da151494d6df3016f (patch) | |
tree | c67e9ff911914f7eaef7af6c9e95874cf8d0cce2 /common/hooks.c | |
parent | 6ecbb86b6392fa0b11514903a9fb3d3a3b704391 (diff) | |
download | chrome-ec-70f3fcaf8648230a5cd27a9da151494d6df3016f.tar.gz |
Add hooks module so modules can be notified of system-level events.
This will be used for sleep/wake/sysjump/etc. For now it's just wired
up to clock frequency changing.
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=none
TEST=manual: use nopll command, should still work
Change-Id: Iedcea5830bc18eacfd955c29b8f793aba8905dd8
Diffstat (limited to 'common/hooks.c')
-rw-r--r-- | common/hooks.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/common/hooks.c b/common/hooks.c new file mode 100644 index 0000000000..94bf2627fb --- /dev/null +++ b/common/hooks.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2012 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 "hooks.h" +#include "uart.h" +#include "util.h" + +/* Hooks are described in special sections */ +extern const struct hook_data __hooks_freq_change[]; +extern const struct hook_data __hooks_freq_change_end[]; + + +int hook_notify(enum hook_type type, int stop_on_error) +{ + const struct hook_data *start, *end, *p; + int count, called = 0; + int last_prio = HOOK_PRIO_FIRST - 1, prio; + int rv_error = EC_SUCCESS, rv; + + /* Get the start and end pointers for the hook type */ + switch (type) { + case HOOK_FREQ_CHANGE: + start = __hooks_freq_change; + end = __hooks_freq_change_end; + break; + default: + /* Unhandled hook type */ + return EC_ERROR_UNKNOWN; + } + + count = ((uint32_t)end - (uint32_t)start) / sizeof(struct hook_data); + + /* Call all the hooks in priority order */ + while (called < count) { + /* Find the lowest remaining priority */ + for (p = start, prio = HOOK_PRIO_LAST + 1; p < end; p++) { + if (p->priority < prio && p->priority > last_prio) + prio = p->priority; + } + last_prio = prio; + + /* Call all the hooks with that priority */ + for (p = start; p < end; p++) { + if (p->priority == prio) { + called++; + rv = p->routine(); + if (rv != EC_SUCCESS) { + if (stop_on_error) + return rv; + else if (rv_error == EC_SUCCESS) + rv_error = rv; + } + } + } + } + + /* Return the first error seen, if any */ + return rv_error; +} |