aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Krafft <krafft@de.ibm.com>2007-07-20 15:39:22 -0400
committerArnd Bergmann <arnd@klappe.arndb.de>2007-07-20 15:41:38 -0400
commit74889e41d9a1f80928130a02af9b010673bc5ba7 (patch)
tree300feac7ceaad88b090ba385abd414281033425a
parent1e21fd5af3797a2c322e1723c69732e77aa74f48 (diff)
[CELL] cbe_cpufreq: reorganize code
This patch reorganizes the code of the driver into three files. Two cbe_cpufreq_pmi.c and cbe_cpufreq_pervasive.c care about hardware. cbe_cpufreq.c contains the logic. There is no changed behaviour, except that the PMI related function is now located in a seperate module cbe_cpufreq_pmi. This module will be required by cbe_cpufreq, if CONFIG_CBE_CPUFREQ_PMI has been set. Signed-off-by: Christian Krafft <krafft@de.ibm.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
-rw-r--r--arch/powerpc/platforms/cell/Kconfig10
-rw-r--r--arch/powerpc/platforms/cell/Makefile4
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c196
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.h24
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c115
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c148
6 files changed, 309 insertions, 188 deletions
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 9b2b386ccf48..ac8032034fb8 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -73,4 +73,14 @@ config CBE_CPUFREQ
73 For details, take a look at <file:Documentation/cpu-freq/>. 73 For details, take a look at <file:Documentation/cpu-freq/>.
74 If you don't have such processor, say N 74 If you don't have such processor, say N
75 75
76config CBE_CPUFREQ_PMI
77 tristate "CBE frequency scaling using PMI interface"
78 depends on CBE_CPUFREQ && PPC_PMI && EXPERIMENTAL
79 default n
80 help
81 Select this, if you want to use the PMI interface
82 to switch frequencies. Using PMI, the
83 processor will not only be able to run at lower speed,
84 but also at lower core voltage.
85
76endmenu 86endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 869af89df6ff..be059718becd 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -4,7 +4,9 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \
4obj-$(CONFIG_CBE_RAS) += ras.o 4obj-$(CONFIG_CBE_RAS) += ras.o
5 5
6obj-$(CONFIG_CBE_THERM) += cbe_thermal.o 6obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
7obj-$(CONFIG_CBE_CPUFREQ) += cbe_cpufreq.o 7obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o
8obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o
9cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o
8 10
9ifeq ($(CONFIG_SMP),y) 11ifeq ($(CONFIG_SMP),y)
10obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o 12obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index a62562ee1461..9a9932624c0c 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * cpufreq driver for the cell processor 2 * cpufreq driver for the cell processor
3 * 3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
5 * 5 *
6 * Author: Christian Krafft <krafft@de.ibm.com> 6 * Author: Christian Krafft <krafft@de.ibm.com>
7 * 7 *
@@ -21,18 +21,10 @@
21 */ 21 */
22 22
23#include <linux/cpufreq.h> 23#include <linux/cpufreq.h>
24#include <linux/timer.h>
25
26#include <asm/hw_irq.h>
27#include <asm/io.h>
28#include <asm/machdep.h> 24#include <asm/machdep.h>
29#include <asm/processor.h>
30#include <asm/prom.h>
31#include <asm/time.h>
32#include <asm/pmi.h>
33#include <asm/of_platform.h> 25#include <asm/of_platform.h>
34 26#include <asm/prom.h>
35#include "cbe_regs.h" 27#include "cbe_cpufreq.h"
36 28
37static DEFINE_MUTEX(cbe_switch_mutex); 29static DEFINE_MUTEX(cbe_switch_mutex);
38 30
@@ -50,183 +42,24 @@ static struct cpufreq_frequency_table cbe_freqs[] = {
50 {0, CPUFREQ_TABLE_END}, 42 {0, CPUFREQ_TABLE_END},
51}; 43};
52 44
53/* to write to MIC register */
54static u64 MIC_Slow_Fast_Timer_table[] = {
55 [0 ... 7] = 0x007fc00000000000ull,
56};
57
58/* more values for the MIC */
59static u64 MIC_Slow_Next_Timer_table[] = {
60 0x0000240000000000ull,
61 0x0000268000000000ull,
62 0x000029C000000000ull,
63 0x00002D0000000000ull,
64 0x0000300000000000ull,
65 0x0000334000000000ull,
66 0x000039C000000000ull,
67 0x00003FC000000000ull,
68};
69
70static u8 pmi_slow_mode_limit[MAX_BE];
71
72/* 45/*
73 * hardware specific functions 46 * hardware specific functions
74 */ 47 */
75 48
76static bool cbe_cpufreq_has_pmi; 49static int set_pmode(unsigned int cpu, unsigned int slow_mode)
77
78#ifdef CONFIG_PPC_PMI
79static int set_pmode_pmi(int cpu, unsigned int pmode)
80{
81 int ret;
82 pmi_message_t pmi_msg;
83#ifdef DEBUG
84 long time;
85#endif
86
87 pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
88 pmi_msg.data1 = cbe_cpu_to_node(cpu);
89 pmi_msg.data2 = pmode;
90
91#ifdef DEBUG
92 time = jiffies;
93#endif
94
95 pmi_send_message(pmi_msg);
96 ret = pmi_msg.data2;
97
98 pr_debug("PMI returned slow mode %d\n", ret);
99
100#ifdef DEBUG
101 time = jiffies - time; /* actual cycles (not cpu cycles!) */
102 time = jiffies_to_msecs(time);
103 pr_debug("had to wait %lu ms for a transition using PMI.\n", time);
104#endif
105 return ret;
106}
107#endif
108
109static int get_pmode(int cpu)
110{
111 int ret;
112 struct cbe_pmd_regs __iomem *pmd_regs;
113
114 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
115 ret = in_be64(&pmd_regs->pmsr) & 0x07;
116
117 return ret;
118}
119
120static int set_pmode_reg(int cpu, unsigned int pmode)
121{
122 struct cbe_pmd_regs __iomem *pmd_regs;
123 struct cbe_mic_tm_regs __iomem *mic_tm_regs;
124 u64 flags;
125 u64 value;
126#ifdef DEBUG
127 long time;
128#endif
129
130 local_irq_save(flags);
131
132 mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
133 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
134
135#ifdef DEBUG
136 time = jiffies;
137#endif
138 out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
139 out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
140
141 out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
142 out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
143
144 value = in_be64(&pmd_regs->pmcr);
145 /* set bits to zero */
146 value &= 0xFFFFFFFFFFFFFFF8ull;
147 /* set bits to next pmode */
148 value |= pmode;
149
150 out_be64(&pmd_regs->pmcr, value);
151
152#ifdef DEBUG
153 /* wait until new pmode appears in status register */
154 value = in_be64(&pmd_regs->pmsr) & 0x07;
155 while(value != pmode) {
156 cpu_relax();
157 value = in_be64(&pmd_regs->pmsr) & 0x07;
158 }
159
160 time = jiffies - time;
161 time = jiffies_to_msecs(time);
162 pr_debug("had to wait %lu ms for a transition using " \
163 "the pervasive unit.\n", time);
164#endif
165 local_irq_restore(flags);
166
167 return 0;
168}
169
170static int set_pmode(int cpu, unsigned int slow_mode)
171{ 50{
172 int rc; 51 int rc;
173#ifdef CONFIG_PPC_PMI 52
174 if (cbe_cpufreq_has_pmi) 53 if (cbe_cpufreq_has_pmi)
175 rc = set_pmode_pmi(cpu, slow_mode); 54 rc = cbe_cpufreq_set_pmode_pmi(cpu, slow_mode);
176 else 55 else
177#endif 56 rc = cbe_cpufreq_set_pmode(cpu, slow_mode);
178 rc = set_pmode_reg(cpu, slow_mode);
179 57
180 pr_debug("register contains slow mode %d\n", get_pmode(cpu)); 58 pr_debug("register contains slow mode %d\n", cbe_cpufreq_get_pmode(cpu));
181 59
182 return rc; 60 return rc;
183} 61}
184 62
185static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
186{
187 u8 node; slow_mode;
188
189 BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
190
191 node = pmi_msg.data1;
192 slow_mode = pmi_msg.data2;
193
194 pmi_slow_mode_limit[node] = slow_mode;
195
196 pr_debug("cbe_handle_pmi: node: %d, max slow_mode=%d\n", slow_mode);
197}
198
199static int pmi_notifier(struct notifier_block *nb,
200 unsigned long event, void *data)
201{
202 struct cpufreq_policy *policy = data;
203 u8 node;
204
205 node = cbe_cpu_to_node(policy->cpu);
206
207 pr_debug("got notified, event=%lu, node=%u\n", event, node);
208
209 if (pmi_slow_mode_limit[node] != 0) {
210 pr_debug("limiting node %d to slow mode %d\n",
211 node, pmi_slow_mode_limit[node]);
212
213 cpufreq_verify_within_limits(policy, 0,
214 cbe_freqs[pmi_slow_mode_limit[node]].frequency);
215 }
216
217 return 0;
218}
219
220static struct notifier_block pmi_notifier_block = {
221 .notifier_call = pmi_notifier,
222};
223
224static struct pmi_handler cbe_pmi_handler = {
225 .type = PMI_TYPE_FREQ_CHANGE,
226 .handle_pmi_message = cbe_cpufreq_handle_pmi,
227};
228
229
230/* 63/*
231 * cpufreq functions 64 * cpufreq functions
232 */ 65 */
@@ -270,7 +103,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
270 * of a transition */ 103 * of a transition */
271 policy->cpuinfo.transition_latency = 25000; 104 policy->cpuinfo.transition_latency = 25000;
272 105
273 cur_pmode = get_pmode(policy->cpu); 106 cur_pmode = cbe_cpufreq_get_pmode(policy->cpu);
274 pr_debug("current pmode is at %d\n",cur_pmode); 107 pr_debug("current pmode is at %d\n",cur_pmode);
275 108
276 policy->cur = cbe_freqs[cur_pmode].frequency; 109 policy->cur = cbe_freqs[cur_pmode].frequency;
@@ -297,7 +130,6 @@ static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
297 return cpufreq_frequency_table_verify(policy, cbe_freqs); 130 return cpufreq_frequency_table_verify(policy, cbe_freqs);
298} 131}
299 132
300
301static int cbe_cpufreq_target(struct cpufreq_policy *policy, 133static int cbe_cpufreq_target(struct cpufreq_policy *policy,
302 unsigned int target_freq, 134 unsigned int target_freq,
303 unsigned int relation) 135 unsigned int relation)
@@ -352,22 +184,12 @@ static int __init cbe_cpufreq_init(void)
352 if (!machine_is(cell)) 184 if (!machine_is(cell))
353 return -ENODEV; 185 return -ENODEV;
354 186
355 cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0;
356
357 if (cbe_cpufreq_has_pmi)
358 cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
359
360 return cpufreq_register_driver(&cbe_cpufreq_driver); 187 return cpufreq_register_driver(&cbe_cpufreq_driver);
361} 188}
362 189
363static void __exit cbe_cpufreq_exit(void) 190static void __exit cbe_cpufreq_exit(void)
364{ 191{
365 cpufreq_unregister_driver(&cbe_cpufreq_driver); 192 cpufreq_unregister_driver(&cbe_cpufreq_driver);
366
367 if (cbe_cpufreq_has_pmi) {
368 cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
369 pmi_unregister_handler(&cbe_pmi_handler);
370 }
371} 193}
372 194
373module_init(cbe_cpufreq_init); 195module_init(cbe_cpufreq_init);
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.h b/arch/powerpc/platforms/cell/cbe_cpufreq.h
new file mode 100644
index 000000000000..c1d86bfa92ff
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.h
@@ -0,0 +1,24 @@
1/*
2 * cbe_cpufreq.h
3 *
4 * This file contains the definitions used by the cbe_cpufreq driver.
5 *
6 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
7 *
8 * Author: Christian Krafft <krafft@de.ibm.com>
9 *
10 */
11
12#include <linux/cpufreq.h>
13#include <linux/types.h>
14
15int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode);
16int cbe_cpufreq_get_pmode(int cpu);
17
18int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode);
19
20#if defined(CONFIG_CBE_CPUFREQ_PMI) || defined(CONFIG_CBE_CPUFREQ_PMI_MODULE)
21extern bool cbe_cpufreq_has_pmi;
22#else
23#define cbe_cpufreq_has_pmi (0)
24#endif
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
new file mode 100644
index 000000000000..163263b3e1cd
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
@@ -0,0 +1,115 @@
1/*
2 * pervasive backend for the cbe_cpufreq driver
3 *
4 * This driver makes use of the pervasive unit to
5 * engage the desired frequency.
6 *
7 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
8 *
9 * Author: Christian Krafft <krafft@de.ibm.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/io.h>
27#include <linux/kernel.h>
28#include <linux/time.h>
29#include <asm/machdep.h>
30#include <asm/hw_irq.h>
31
32#include "cbe_regs.h"
33#include "cbe_cpufreq.h"
34
35/* to write to MIC register */
36static u64 MIC_Slow_Fast_Timer_table[] = {
37 [0 ... 7] = 0x007fc00000000000ull,
38};
39
40/* more values for the MIC */
41static u64 MIC_Slow_Next_Timer_table[] = {
42 0x0000240000000000ull,
43 0x0000268000000000ull,
44 0x000029C000000000ull,
45 0x00002D0000000000ull,
46 0x0000300000000000ull,
47 0x0000334000000000ull,
48 0x000039C000000000ull,
49 0x00003FC000000000ull,
50};
51
52
53int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)
54{
55 struct cbe_pmd_regs __iomem *pmd_regs;
56 struct cbe_mic_tm_regs __iomem *mic_tm_regs;
57 u64 flags;
58 u64 value;
59#ifdef DEBUG
60 long time;
61#endif
62
63 local_irq_save(flags);
64
65 mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
66 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
67
68#ifdef DEBUG
69 time = jiffies;
70#endif
71
72 out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
73 out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
74
75 out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
76 out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
77
78 value = in_be64(&pmd_regs->pmcr);
79 /* set bits to zero */
80 value &= 0xFFFFFFFFFFFFFFF8ull;
81 /* set bits to next pmode */
82 value |= pmode;
83
84 out_be64(&pmd_regs->pmcr, value);
85
86#ifdef DEBUG
87 /* wait until new pmode appears in status register */
88 value = in_be64(&pmd_regs->pmsr) & 0x07;
89 while (value != pmode) {
90 cpu_relax();
91 value = in_be64(&pmd_regs->pmsr) & 0x07;
92 }
93
94 time = jiffies - time;
95 time = jiffies_to_msecs(time);
96 pr_debug("had to wait %lu ms for a transition using " \
97 "pervasive unit\n", time);
98#endif
99 local_irq_restore(flags);
100
101 return 0;
102}
103
104
105int cbe_cpufreq_get_pmode(int cpu)
106{
107 int ret;
108 struct cbe_pmd_regs __iomem *pmd_regs;
109
110 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
111 ret = in_be64(&pmd_regs->pmsr) & 0x07;
112
113 return ret;
114}
115
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
new file mode 100644
index 000000000000..fc6f38982ff4
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
@@ -0,0 +1,148 @@
1/*
2 * pmi backend for the cbe_cpufreq driver
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
5 *
6 * Author: Christian Krafft <krafft@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/kernel.h>
24#include <linux/types.h>
25#include <linux/timer.h>
26#include <asm/of_platform.h>
27#include <asm/processor.h>
28#include <asm/prom.h>
29#include <asm/pmi.h>
30
31#ifdef DEBUG
32#include <asm/time.h>
33#endif
34
35#include "cbe_regs.h"
36#include "cbe_cpufreq.h"
37
38static u8 pmi_slow_mode_limit[MAX_CBE];
39
40bool cbe_cpufreq_has_pmi = false;
41EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi);
42
43/*
44 * hardware specific functions
45 */
46
47int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode)
48{
49 int ret;
50 pmi_message_t pmi_msg;
51#ifdef DEBUG
52 long time;
53#endif
54 pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
55 pmi_msg.data1 = cbe_cpu_to_node(cpu);
56 pmi_msg.data2 = pmode;
57
58#ifdef DEBUG
59 time = jiffies;
60#endif
61 pmi_send_message(pmi_msg);
62
63#ifdef DEBUG
64 time = jiffies - time;
65 time = jiffies_to_msecs(time);
66 pr_debug("had to wait %lu ms for a transition using " \
67 "PMI\n", time);
68#endif
69 ret = pmi_msg.data2;
70 pr_debug("PMI returned slow mode %d\n", ret);
71
72 return ret;
73}
74EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi);
75
76
77static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
78{
79 u8 node, slow_mode;
80
81 BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
82
83 node = pmi_msg.data1;
84 slow_mode = pmi_msg.data2;
85
86 pmi_slow_mode_limit[node] = slow_mode;
87
88 pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode);
89}
90
91static int pmi_notifier(struct notifier_block *nb,
92 unsigned long event, void *data)
93{
94 struct cpufreq_policy *policy = data;
95 struct cpufreq_frequency_table *cbe_freqs;
96 u8 node;
97
98 cbe_freqs = cpufreq_frequency_get_table(policy->cpu);
99 node = cbe_cpu_to_node(policy->cpu);
100
101 pr_debug("got notified, event=%lu, node=%u\n", event, node);
102
103 if (pmi_slow_mode_limit[node] != 0) {
104 pr_debug("limiting node %d to slow mode %d\n",
105 node, pmi_slow_mode_limit[node]);
106
107 cpufreq_verify_within_limits(policy, 0,
108
109 cbe_freqs[pmi_slow_mode_limit[node]].frequency);
110 }
111
112 return 0;
113}
114
115static struct notifier_block pmi_notifier_block = {
116 .notifier_call = pmi_notifier,
117};
118
119static struct pmi_handler cbe_pmi_handler = {
120 .type = PMI_TYPE_FREQ_CHANGE,
121 .handle_pmi_message = cbe_cpufreq_handle_pmi,
122};
123
124
125
126static int __init cbe_cpufreq_pmi_init(void)
127{
128 cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0;
129
130 if (!cbe_cpufreq_has_pmi)
131 return -ENODEV;
132
133 cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
134
135 return 0;
136}
137
138static void __exit cbe_cpufreq_pmi_exit(void)
139{
140 cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
141 pmi_unregister_handler(&cbe_pmi_handler);
142}
143
144module_init(cbe_cpufreq_pmi_init);
145module_exit(cbe_cpufreq_pmi_exit);
146
147MODULE_LICENSE("GPL");
148MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");