This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.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 <asm/io.h>
35 #include <asm/delay.h>
36 #include <asm/uaccess.h>
37
38 #include <linux/acpi.h>
39 #include <acpi/processor.h>
40
41 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
42
43 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
44 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
45 MODULE_LICENSE("GPL");
46
47
48 struct cpufreq_acpi_io {
49         struct acpi_processor_performance       acpi_data;
50         struct cpufreq_frequency_table          *freq_table;
51 };
52
53 static struct cpufreq_acpi_io   *acpi_io_data[NR_CPUS];
54
55
56 static int
57 acpi_processor_write_port(
58         u16     port,
59         u8      bit_width,
60         u32     value)
61 {
62         if (bit_width <= 8) {
63                 outb(value, port);
64         } else if (bit_width <= 16) {
65                 outw(value, port);
66         } else if (bit_width <= 32) {
67                 outl(value, port);
68         } else {
69                 return -ENODEV;
70         }
71         return 0;
72 }
73
74 static int
75 acpi_processor_read_port(
76         u16     port,
77         u8      bit_width,
78         u32     *ret)
79 {
80         *ret = 0;
81         if (bit_width <= 8) {
82                 *ret = inb(port);
83         } else if (bit_width <= 16) {
84                 *ret = inw(port);
85         } else if (bit_width <= 32) {
86                 *ret = inl(port);
87         } else {
88                 return -ENODEV;
89         }
90         return 0;
91 }
92
93 static int
94 acpi_processor_set_performance (
95         struct cpufreq_acpi_io  *data,
96         unsigned int            cpu,
97         int                     state)
98 {
99         u16                     port = 0;
100         u8                      bit_width = 0;
101         int                     ret = 0;
102         u32                     value = 0;
103         int                     i = 0;
104         struct cpufreq_freqs    cpufreq_freqs;
105         cpumask_t               saved_mask;
106         int                     retval;
107
108         dprintk("acpi_processor_set_performance\n");
109
110         /*
111          * TBD: Use something other than set_cpus_allowed.
112          * As set_cpus_allowed is a bit racy, 
113          * with any other set_cpus_allowed for this process.
114          */
115         saved_mask = current->cpus_allowed;
116         set_cpus_allowed(current, cpumask_of_cpu(cpu));
117         if (smp_processor_id() != cpu) {
118                 return (-EAGAIN);
119         }
120         
121         if (state == data->acpi_data.state) {
122                 dprintk("Already at target state (P%d)\n", state);
123                 retval = 0;
124                 goto migrate_end;
125         }
126
127         dprintk("Transitioning from P%d to P%d\n",
128                 data->acpi_data.state, state);
129
130         /* cpufreq frequency struct */
131         cpufreq_freqs.cpu = cpu;
132         cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
133         cpufreq_freqs.new = data->freq_table[state].frequency;
134
135         /* notify cpufreq */
136         cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
137
138         /*
139          * First we write the target state's 'control' value to the
140          * control_register.
141          */
142
143         port = data->acpi_data.control_register.address;
144         bit_width = data->acpi_data.control_register.bit_width;
145         value = (u32) data->acpi_data.states[state].control;
146
147         dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
148
149         ret = acpi_processor_write_port(port, bit_width, value);
150         if (ret) {
151                 dprintk("Invalid port width 0x%04x\n", bit_width);
152                 retval = ret;
153                 goto migrate_end;
154         }
155
156         /*
157          * Then we read the 'status_register' and compare the value with the
158          * target state's 'status' to make sure the transition was successful.
159          * Note that we'll poll for up to 1ms (100 cycles of 10us) before
160          * giving up.
161          */
162
163         port = data->acpi_data.status_register.address;
164         bit_width = data->acpi_data.status_register.bit_width;
165
166         dprintk("Looking for 0x%08x from port 0x%04x\n",
167                 (u32) data->acpi_data.states[state].status, port);
168
169         for (i=0; i<100; i++) {
170                 ret = acpi_processor_read_port(port, bit_width, &value);
171                 if (ret) {      
172                         dprintk("Invalid port width 0x%04x\n", bit_width);
173                         retval = ret;
174                         goto migrate_end;
175                 }
176                 if (value == (u32) data->acpi_data.states[state].status)
177                         break;
178                 udelay(10);
179         }
180
181         /* notify cpufreq */
182         cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
183
184         if (value != (u32) data->acpi_data.states[state].status) {
185                 unsigned int tmp = cpufreq_freqs.new;
186                 cpufreq_freqs.new = cpufreq_freqs.old;
187                 cpufreq_freqs.old = tmp;
188                 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
189                 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
190                 printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
191                 retval = -ENODEV;
192                 goto migrate_end;
193         }
194
195         dprintk("Transition successful after %d microseconds\n", i * 10);
196
197         data->acpi_data.state = state;
198
199         retval = 0;
200 migrate_end:
201         set_cpus_allowed(current, saved_mask);
202         return (retval);
203 }
204
205
206 static int
207 acpi_cpufreq_target (
208         struct cpufreq_policy   *policy,
209         unsigned int target_freq,
210         unsigned int relation)
211 {
212         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
213         unsigned int next_state = 0;
214         unsigned int result = 0;
215
216         dprintk("acpi_cpufreq_setpolicy\n");
217
218         result = cpufreq_frequency_table_target(policy,
219                         data->freq_table,
220                         target_freq,
221                         relation,
222                         &next_state);
223         if (result)
224                 return (result);
225
226         result = acpi_processor_set_performance (data, policy->cpu, next_state);
227
228         return (result);
229 }
230
231
232 static int
233 acpi_cpufreq_verify (
234         struct cpufreq_policy   *policy)
235 {
236         unsigned int result = 0;
237         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
238
239         dprintk("acpi_cpufreq_verify\n");
240
241         result = cpufreq_frequency_table_verify(policy, 
242                         data->freq_table);
243
244         return (result);
245 }
246
247
248 static unsigned long
249 acpi_cpufreq_guess_freq (
250         struct cpufreq_acpi_io  *data,
251         unsigned int            cpu)
252 {
253         if (cpu_khz) {
254                 /* search the closest match to cpu_khz */
255                 unsigned int i;
256                 unsigned long freq;
257                 unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
258
259                 for (i=0; i < (data->acpi_data.state_count - 1); i++) {
260                         freq = freqn;
261                         freqn = data->acpi_data.states[i+1].core_frequency * 1000;
262                         if ((2 * cpu_khz) > (freqn + freq)) {
263                                 data->acpi_data.state = i;
264                                 return (freq);
265                         }
266                 }
267                 data->acpi_data.state = data->acpi_data.state_count - 1;
268                 return (freqn);
269         } else
270                 /* assume CPU is at P0... */
271                 data->acpi_data.state = 0;
272                 return data->acpi_data.states[0].core_frequency * 1000;
273         
274 }
275
276
277 /* 
278  * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
279  * of this driver
280  * @perf: processor-specific acpi_io_data struct
281  * @cpu: CPU being initialized
282  *
283  * To avoid issues with legacy OSes, some BIOSes require to be informed of
284  * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC 
285  * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
286  * driver/acpi/processor.c
287  */
288 static void 
289 acpi_processor_cpu_init_pdc_est(
290                 struct acpi_processor_performance *perf, 
291                 unsigned int cpu,
292                 struct acpi_object_list *obj_list
293                 )
294 {
295         union acpi_object *obj;
296         u32 *buf;
297         struct cpuinfo_x86 *c = cpu_data + cpu;
298         dprintk("acpi_processor_cpu_init_pdc_est\n");
299
300         if (!cpu_has(c, X86_FEATURE_EST))
301                 return;
302
303         /* Initialize pdc. It will be used later. */
304         if (!obj_list)
305                 return;
306                 
307         if (!(obj_list->count && obj_list->pointer))
308                 return;
309
310         obj = obj_list->pointer;
311         if ((obj->buffer.length == 12) && obj->buffer.pointer) {
312                 buf = (u32 *)obj->buffer.pointer;
313                 buf[0] = ACPI_PDC_REVISION_ID;
314                 buf[1] = 1;
315                 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
316                 perf->pdc = obj_list;
317         }
318         return;
319 }
320  
321
322 /* CPU specific PDC initialization */
323 static void 
324 acpi_processor_cpu_init_pdc(
325                 struct acpi_processor_performance *perf, 
326                 unsigned int cpu,
327                 struct acpi_object_list *obj_list
328                 )
329 {
330         struct cpuinfo_x86 *c = cpu_data + cpu;
331         dprintk("acpi_processor_cpu_init_pdc\n");
332         perf->pdc = NULL;
333         if (cpu_has(c, X86_FEATURE_EST))
334                 acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
335         return;
336 }
337
338
339 static int
340 acpi_cpufreq_cpu_init (
341         struct cpufreq_policy   *policy)
342 {
343         unsigned int            i;
344         unsigned int            cpu = policy->cpu;
345         struct cpufreq_acpi_io  *data;
346         unsigned int            result = 0;
347
348         union acpi_object               arg0 = {ACPI_TYPE_BUFFER};
349         u32                             arg0_buf[3];
350         struct acpi_object_list         arg_list = {1, &arg0};
351
352         dprintk("acpi_cpufreq_cpu_init\n");
353         /* setup arg_list for _PDC settings */
354         arg0.buffer.length = 12;
355         arg0.buffer.pointer = (u8 *) arg0_buf;
356
357         data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
358         if (!data)
359                 return (-ENOMEM);
360         memset(data, 0, sizeof(struct cpufreq_acpi_io));
361
362         acpi_io_data[cpu] = data;
363
364         acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
365         result = acpi_processor_register_performance(&data->acpi_data, cpu);
366         data->acpi_data.pdc = NULL;
367
368         if (result)
369                 goto err_free;
370
371         /* capability check */
372         if (data->acpi_data.state_count <= 1) {
373                 dprintk("No P-States\n");
374                 result = -ENODEV;
375                 goto err_unreg;
376         }
377         if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
378             (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
379                 dprintk("Unsupported address space [%d, %d]\n",
380                         (u32) (data->acpi_data.control_register.space_id),
381                         (u32) (data->acpi_data.status_register.space_id));
382                 result = -ENODEV;
383                 goto err_unreg;
384         }
385
386         /* alloc freq_table */
387         data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL);
388         if (!data->freq_table) {
389                 result = -ENOMEM;
390                 goto err_unreg;
391         }
392
393         /* detect transition latency */
394         policy->cpuinfo.transition_latency = 0;
395         for (i=0; i<data->acpi_data.state_count; i++) {
396                 if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
397                         policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
398         }
399         policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
400
401         /* The current speed is unknown and not detectable by ACPI...  */
402         policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
403
404         /* table init */
405         for (i=0; i<=data->acpi_data.state_count; i++)
406         {
407                 data->freq_table[i].index = i;
408                 if (i<data->acpi_data.state_count)
409                         data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
410                 else
411                         data->freq_table[i].frequency = CPUFREQ_TABLE_END;
412         }
413
414         result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
415         if (result) {
416                 goto err_freqfree;
417         }
418
419         /* notify BIOS that we exist */
420         acpi_processor_notify_smm(THIS_MODULE);
421
422         printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
423                cpu);
424         for (i = 0; i < data->acpi_data.state_count; i++)
425                 dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
426                         (i == data->acpi_data.state?'*':' '), i,
427                         (u32) data->acpi_data.states[i].core_frequency,
428                         (u32) data->acpi_data.states[i].power,
429                         (u32) data->acpi_data.states[i].transition_latency);
430
431         cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
432         return (result);
433
434  err_freqfree:
435         kfree(data->freq_table);
436  err_unreg:
437         acpi_processor_unregister_performance(&data->acpi_data, cpu);
438  err_free:
439         kfree(data);
440         acpi_io_data[cpu] = NULL;
441
442         return (result);
443 }
444
445
446 static int
447 acpi_cpufreq_cpu_exit (
448         struct cpufreq_policy   *policy)
449 {
450         struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
451
452
453         dprintk("acpi_cpufreq_cpu_exit\n");
454
455         if (data) {
456                 cpufreq_frequency_table_put_attr(policy->cpu);
457                 acpi_io_data[policy->cpu] = NULL;
458                 acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
459                 kfree(data);
460         }
461
462         return (0);
463 }
464
465
466 static struct freq_attr* acpi_cpufreq_attr[] = {
467         &cpufreq_freq_attr_scaling_available_freqs,
468         NULL,
469 };
470
471 static struct cpufreq_driver acpi_cpufreq_driver = {
472         .verify         = acpi_cpufreq_verify,
473         .target         = acpi_cpufreq_target,
474         .init           = acpi_cpufreq_cpu_init,
475         .exit           = acpi_cpufreq_cpu_exit,
476         .name           = "acpi-cpufreq",
477         .owner          = THIS_MODULE,
478         .attr           = acpi_cpufreq_attr,
479 };
480
481
482 static int __init
483 acpi_cpufreq_init (void)
484 {
485         int                     result = 0;
486
487         dprintk("acpi_cpufreq_init\n");
488
489         result = cpufreq_register_driver(&acpi_cpufreq_driver);
490         
491         return (result);
492 }
493
494
495 static void __exit
496 acpi_cpufreq_exit (void)
497 {
498         dprintk("acpi_cpufreq_exit\n");
499
500         cpufreq_unregister_driver(&acpi_cpufreq_driver);
501
502         return;
503 }
504
505
506 late_initcall(acpi_cpufreq_init);
507 module_exit(acpi_cpufreq_exit);
508
509 MODULE_ALIAS("acpi");