aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/cpu_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/cpu_pm.c')
-rw-r--r--arch/arm/kernel/cpu_pm.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/arm/kernel/cpu_pm.c b/arch/arm/kernel/cpu_pm.c
new file mode 100644
index 00000000000..748af1f1f43
--- /dev/null
+++ b/arch/arm/kernel/cpu_pm.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) 2011 Google, Inc.
3 *
4 * Author:
5 * Colin Cross <ccross@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/notifier.h>
21#include <linux/spinlock.h>
22
23#include <asm/cpu_pm.h>
24
25static DEFINE_RWLOCK(cpu_pm_notifier_lock);
26static RAW_NOTIFIER_HEAD(cpu_pm_notifier_chain);
27
28int cpu_pm_register_notifier(struct notifier_block *nb)
29{
30 unsigned long flags;
31 int ret;
32
33 write_lock_irqsave(&cpu_pm_notifier_lock, flags);
34 ret = raw_notifier_chain_register(&cpu_pm_notifier_chain, nb);
35 write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
36
37 return ret;
38}
39EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
40
41int cpu_pm_unregister_notifier(struct notifier_block *nb)
42{
43 unsigned long flags;
44 int ret;
45
46 write_lock_irqsave(&cpu_pm_notifier_lock, flags);
47 ret = raw_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);
48 write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
49
50 return ret;
51}
52EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
53
54static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)
55{
56 int ret;
57
58 ret = __raw_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,
59 nr_to_call, nr_calls);
60
61 return notifier_to_errno(ret);
62}
63
64int cpu_pm_enter(void)
65{
66 int nr_calls;
67 int ret = 0;
68
69 read_lock(&cpu_pm_notifier_lock);
70 ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);
71 if (ret)
72 cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL);
73 read_unlock(&cpu_pm_notifier_lock);
74
75 return ret;
76}
77EXPORT_SYMBOL_GPL(cpu_pm_enter);
78
79int cpu_pm_exit(void)
80{
81 int ret;
82
83 read_lock(&cpu_pm_notifier_lock);
84 ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL);
85 read_unlock(&cpu_pm_notifier_lock);
86
87 return ret;
88}
89EXPORT_SYMBOL_GPL(cpu_pm_exit);
90
91int cpu_complex_pm_enter(void)
92{
93 int nr_calls;
94 int ret = 0;
95
96 read_lock(&cpu_pm_notifier_lock);
97 ret = cpu_pm_notify(CPU_COMPLEX_PM_ENTER, -1, &nr_calls);
98 if (ret)
99 cpu_pm_notify(CPU_COMPLEX_PM_ENTER_FAILED, nr_calls - 1, NULL);
100 read_unlock(&cpu_pm_notifier_lock);
101
102 return ret;
103}
104EXPORT_SYMBOL_GPL(cpu_complex_pm_enter);
105
106int cpu_complex_pm_exit(void)
107{
108 int ret;
109
110 read_lock(&cpu_pm_notifier_lock);
111 ret = cpu_pm_notify(CPU_COMPLEX_PM_EXIT, -1, NULL);
112 read_unlock(&cpu_pm_notifier_lock);
113
114 return ret;
115}
116EXPORT_SYMBOL_GPL(cpu_complex_pm_exit);