]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
[ACPI] fix acpi_cpufreq.c build warrning
[linux-2.6-omap-h63xx.git] / arch / i386 / kernel / cpu / cpufreq / acpi-cpufreq.c
1 /*
2  * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *  Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
7  *
8  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or (at
13  *  your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with this program; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23  *
24  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25  */
26
27 #include <linux/config.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/cpufreq.h>
32 #include <linux/proc_fs.h>
33 #include <linux/seq_file.h>
34 #include <linux/compiler.h>
35 #include <linux/sched.h>        /* current */
36 #include <asm/io.h>
37 #include <asm/delay.h>
38 #include <asm/uaccess.h>
39
40 #include <linux/acpi.h>
41 #include <acpi/processor.h>
42
43 #include "speedstep-est-common.h"
44
45 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
46
47 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
48 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
49 MODULE_LICENSE("GPL");
50
51
52 struct cpufreq_acpi_io {
53         struct acpi_processor_performance       acpi_data;
54         struct cpufreq_frequency_table          *freq_table;
55         unsigned int                            resume;
56 };
57
58 static struct cpufreq_acpi_io   *acpi_io_data[NR_CPUS];
59
60 static struct cpufreq_driver acpi_cpufreq_driver;
61
62 static unsigned int acpi_pstate_strict;
63
64 static int
65 acpi_processor_write_port(
66         u16     port,
67         u8      bit_width,
68         u32     value)
69 {
70         if (bit_width <= 8) {
71                 outb(value, port);
72         } else if (bit_width <= 16) {
73                 outw(value, port);
74         } else if (bit_width <= 32) {
75                 outl(value, port);
76         } else {
77                 return -ENODEV;
78         }
79         return 0;
80 }
81
82 static int
83 acpi_processor_read_port(
84         u16     port,
85         u8      bit_width,
86         u32     *ret)
87 {
88         *ret = 0;
89         if (bit_width <= 8) {
90                 *ret = inb(port);
91         } else if (bit_width <= 16) {
92                 *ret = inw(port);
93         } else if (bit_width <= 32) {
94                 *ret = inl(port);
95         } else {
96                 return -ENODEV;
97         }
98         return 0;
99 }
100
101 static int
102 acpi_processor_set_performance (
103         struct cpufreq_acpi_io  *data,
104         unsigned int            cpu,
105         int                     state)
106 {
107         u16                     port = 0;
108         u8                      bit_width = 0;
109         int                     ret = 0;
110         u32                     value = 0;
111         int                     i = 0;
112         struct cpufreq_freqs    cpufreq_freqs;
113         cpumask_t               saved_mask;
114         int                     retval;
115
116         dprintk("acpi_processor_set_performance\n");
117
118         /*
119          * TBD: Use something other than set_cpus_allowed.
120          * As set_cpus_allowed is a bit racy, 
121          * with any other set_cpus_allowed for this process.
122          */
123         saved_mask = current->cpus_allowed;
124         set_cpus_allowed(current, cpumask_of_cpu(cpu));
125         if (smp_processor_id() != cpu) {
126                 return (-EAGAIN);
127         }
128         
129         if (state == data->acpi_data.state) {
130                 if (unlikely(data->resume)) {
131                         dprintk("Called after resume, resetting to P%d\n", state);
132                         data->resume = 0;
133                 } else {
134                         dprintk("Already at target state (P%d)\n", state);
135                         retval = 0;
136                         goto migrate_end;
137                 }
138         }
139
140         dprintk("Transitioning from P%d to P%d\n",
141                 data->acpi_data.state, state);
142
143         /* cpufreq frequency struct */
144         cpufreq_freqs.cpu = cpu;
145         cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
146         cpufreq_freqs.new = data->freq_table[state].frequency;
147
148         /* notify cpufreq */
149         cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
150
151         /*
152          * First we write the target state's 'control' value to the
153          * control_register.
154          */
155
156         port = data->acpi_data.control_register.address;
157         bit_width = data->acpi_data.control_register.bit_width;
158         value = (u32) data->acpi_data.states[state].control;
159
160         dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
161
162         ret = acpi_processor_write_port(port, bit_width, value);
163         if (ret) {
164                 dprintk("Invalid port width 0x%04x\n", bit_width);
165                 retval = ret;
166                 goto migrate_end;
167         }
168
169         /*
170          * Assume the write went through when acpi_pstate_strict is not used.
171          * As read status_register is an expensive operation and there 
172          * are no specific error cases where an IO port write will fail.
173          */
174         if (acpi_pstate_strict) {
175                 /* Then we read the 'status_register' and compare the value 
176                  * with the target state's 'status' to make sure the 
177                  * transition was successful.
178                  * Note that we'll poll for up to 1ms (100 cycles of 10us) 
179                  * before giving up.
180                  */
181
182                 port = data->acpi_data.status_register.address;
183                 bit_width = data->acpi_data.status_register.bit_width;
184
185                 dprintk("Looking for 0x%08x from port 0x%04x\n",
186                         (u32) data->acpi_data.states[state].status, port);
187
188                 for (i=0; i<100; i++) {
189                         ret = acpi_processor_read_port(port, bit_width, &value);
190                         if (ret) {      
191                                 dprintk("Invalid port width 0x%04x\n", bit_width);
192                                 retval = ret;
193                                 goto migrate_end;
194                         }
195                         if (value == (u32) data->acpi_data.states[state].status)
196                                 break;
197                         udelay(10);
198                 }
199         } else {
200                 i = 0;
201                 value = (u32) data->acpi_data.states[state].status;
202         }
203
204         /* notify cpufreq */
205         cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
206
207         if (unlikely(value != (u32) data->acpi_data.states[state].status)) {
208                 unsigned int tmp = cpufreq_freqs.new;
209                 cpufreq_freqs.new = cpufreq_freqs.old;
210                 cpufreq_freqs.old = tmp;
211                 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
212                 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
213                 printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
214                 retval = -ENODEV;
215                 goto migrate_end;
216         }
217
218         dprintk("Transition successful after %d microseconds\n", i * 10);
219
220         data->acpi_data.state = state;
221
222         retval = 0;
223 migrate_end:
224         set_cpus_allowed(current, saved_mask);
225         return (retval);
226 }
227
228
229 static int
230 acpi_cpufreq_target (
231         struct cpufreq_policy   *policy,
232         unsigned int target_freq,
233         unsigned int relation)
234 {
235         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
236         unsigned int next_state = 0;
237         unsigned int result = 0;
238
239         dprintk("acpi_cpufreq_setpolicy\n");
240
241         result = cpufreq_frequency_table_target(policy,
242                         data->freq_table,
243                         target_freq,
244                         relation,
245                         &next_state);
246         if (result)
247                 return (result);
248
249         result = acpi_processor_set_performance (data, policy->cpu, next_state);
250
251         return (result);
252 }
253
254
255 static int
256 acpi_cpufreq_verify (
257         struct cpufreq_policy   *policy)
258 {
259         unsigned int result = 0;
260         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
261
262         dprintk("acpi_cpufreq_verify\n");
263
264         result = cpufreq_frequency_table_verify(policy, 
265                         data->freq_table);
266
267         return (result);
268 }
269
270
271 static unsigned long
272 acpi_cpufreq_guess_freq (
273         struct cpufreq_acpi_io  *data,
274         unsigned int            cpu)
275 {
276         if (cpu_khz) {
277                 /* search the closest match to cpu_khz */
278                 unsigned int i;
279                 unsigned long freq;
280                 unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
281
282                 for (i=0; i < (data->acpi_data.state_count - 1); i++) {
283                         freq = freqn;
284                         freqn = data->acpi_data.states[i+1].core_frequency * 1000;
285                         if ((2 * cpu_khz) > (freqn + freq)) {
286                                 data->acpi_data.state = i;
287                                 return (freq);
288                         }
289                 }
290                 data->acpi_data.state = data->acpi_data.state_count - 1;
291                 return (freqn);
292         } else
293                 /* assume CPU is at P0... */
294                 data->acpi_data.state = 0;
295                 return data->acpi_data.states[0].core_frequency * 1000;
296         
297 }
298
299
300 static int
301 acpi_cpufreq_cpu_init (
302         struct cpufreq_policy   *policy)
303 {
304         unsigned int            i;
305         unsigned int            cpu = policy->cpu;
306         struct cpufreq_acpi_io  *data;
307         unsigned int            result = 0;
308
309         dprintk("acpi_cpufreq_cpu_init\n");
310
311         data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
312         if (!data)
313                 return (-ENOMEM);
314
315         acpi_io_data[cpu] = data;
316
317         result = acpi_processor_register_performance(&data->acpi_data, cpu);
318
319         if (result)
320                 goto err_free;
321
322         if (is_const_loops_cpu(cpu)) {
323                 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
324         }
325
326         /* capability check */
327         if (data->acpi_data.state_count <= 1) {
328                 dprintk("No P-States\n");
329                 result = -ENODEV;
330                 goto err_unreg;
331         }
332         if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
333             (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
334                 dprintk("Unsupported address space [%d, %d]\n",
335                         (u32) (data->acpi_data.control_register.space_id),
336                         (u32) (data->acpi_data.status_register.space_id));
337                 result = -ENODEV;
338                 goto err_unreg;
339         }
340
341         /* alloc freq_table */
342         data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL);
343         if (!data->freq_table) {
344                 result = -ENOMEM;
345                 goto err_unreg;
346         }
347
348         /* detect transition latency */
349         policy->cpuinfo.transition_latency = 0;
350         for (i=0; i<data->acpi_data.state_count; i++) {
351                 if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
352                         policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
353         }
354         policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
355
356         /* The current speed is unknown and not detectable by ACPI...  */
357         policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
358
359         /* table init */
360         for (i=0; i<=data->acpi_data.state_count; i++)
361         {
362                 data->freq_table[i].index = i;
363                 if (i<data->acpi_data.state_count)
364                         data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
365                 else
366                         data->freq_table[i].frequency = CPUFREQ_TABLE_END;
367         }
368
369         result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
370         if (result) {
371                 goto err_freqfree;
372         }
373
374         /* notify BIOS that we exist */
375         acpi_processor_notify_smm(THIS_MODULE);
376
377         printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
378                cpu);
379         for (i = 0; i < data->acpi_data.state_count; i++)
380                 dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
381                         (i == data->acpi_data.state?'*':' '), i,
382                         (u32) data->acpi_data.states[i].core_frequency,
383                         (u32) data->acpi_data.states[i].power,
384                         (u32) data->acpi_data.states[i].transition_latency);
385
386         cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
387         
388         /*
389          * the first call to ->target() should result in us actually
390          * writing something to the appropriate registers.
391          */
392         data->resume = 1;
393         
394         return (result);
395
396  err_freqfree:
397         kfree(data->freq_table);
398  err_unreg:
399         acpi_processor_unregister_performance(&data->acpi_data, cpu);
400  err_free:
401         kfree(data);
402         acpi_io_data[cpu] = NULL;
403
404         return (result);
405 }
406
407
408 static int
409 acpi_cpufreq_cpu_exit (
410         struct cpufreq_policy   *policy)
411 {
412         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
413
414
415         dprintk("acpi_cpufreq_cpu_exit\n");
416
417         if (data) {
418                 cpufreq_frequency_table_put_attr(policy->cpu);
419                 acpi_io_data[policy->cpu] = NULL;
420                 acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
421                 kfree(data);
422         }
423
424         return (0);
425 }
426
427 static int
428 acpi_cpufreq_resume (
429         struct cpufreq_policy   *policy)
430 {
431         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
432
433
434         dprintk("acpi_cpufreq_resume\n");
435
436         data->resume = 1;
437
438         return (0);
439 }
440
441
442 static struct freq_attr* acpi_cpufreq_attr[] = {
443         &cpufreq_freq_attr_scaling_available_freqs,
444         NULL,
445 };
446
447 static struct cpufreq_driver acpi_cpufreq_driver = {
448         .verify         = acpi_cpufreq_verify,
449         .target         = acpi_cpufreq_target,
450         .init           = acpi_cpufreq_cpu_init,
451         .exit           = acpi_cpufreq_cpu_exit,
452         .resume         = acpi_cpufreq_resume,
453         .name           = "acpi-cpufreq",
454         .owner          = THIS_MODULE,
455         .attr           = acpi_cpufreq_attr,
456 };
457
458
459 static int __init
460 acpi_cpufreq_init (void)
461 {
462         int                     result = 0;
463
464         dprintk("acpi_cpufreq_init\n");
465
466         result = cpufreq_register_driver(&acpi_cpufreq_driver);
467         
468         return (result);
469 }
470
471
472 static void __exit
473 acpi_cpufreq_exit (void)
474 {
475         dprintk("acpi_cpufreq_exit\n");
476
477         cpufreq_unregister_driver(&acpi_cpufreq_driver);
478
479         return;
480 }
481
482 module_param(acpi_pstate_strict, uint, 0644);
483 MODULE_PARM_DESC(acpi_pstate_strict, "value 0 or non-zero. non-zero -> strict ACPI checks are performed during frequency changes.");
484
485 late_initcall(acpi_cpufreq_init);
486 module_exit(acpi_cpufreq_exit);
487
488 MODULE_ALIAS("acpi");