aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorVenkatesh Pallipadi <venkatesh.pallipadi@intel.com>2006-10-03 15:33:14 -0400
committerDave Jones <davej@redhat.com>2006-10-15 19:57:10 -0400
commitdde9f7ba60adac0cade262ab9b17654e93c626e2 (patch)
tree9e9c221b601979981ebabf5c2a2023f302b6a94c /arch
parentfe27cb358835cfa525b5831ec8ddb9b9bfda3c73 (diff)
[CPUFREQ][3/8] acpi-cpufreq: Pull in MSR based transition support
Add in the support for Intel Enhanced Speedstep - MSR based transitions. With this change, the ACPI based support in speedstep-centrino can be deprecated and duplicate code in that driver can be marked for removal. Much easier to maintain and support this way. This also reduces the user misconfigurations and questions on which driver is to be used under which CPUs to support Enhanced Speedstep. Signed-off-by: Denis Sadykov <denis.m.sadykov@intel.com> Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c155
1 files changed, 139 insertions, 16 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index ebc9fe285748..07fd97ba4c7a 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -39,6 +39,7 @@
39#include <acpi/processor.h> 39#include <acpi/processor.h>
40 40
41#include <asm/io.h> 41#include <asm/io.h>
42#include <asm/msr.h>
42#include <asm/processor.h> 43#include <asm/processor.h>
43#include <asm/cpufeature.h> 44#include <asm/cpufeature.h>
44#include <asm/delay.h> 45#include <asm/delay.h>
@@ -51,10 +52,19 @@ MODULE_DESCRIPTION("ACPI Processor P-States Driver");
51MODULE_LICENSE("GPL"); 52MODULE_LICENSE("GPL");
52 53
53 54
55enum {
56 UNDEFINED_CAPABLE = 0,
57 SYSTEM_INTEL_MSR_CAPABLE,
58 SYSTEM_IO_CAPABLE,
59};
60
61#define INTEL_MSR_RANGE (0xffff)
62
54struct acpi_cpufreq_data { 63struct acpi_cpufreq_data {
55 struct acpi_processor_performance *acpi_data; 64 struct acpi_processor_performance *acpi_data;
56 struct cpufreq_frequency_table *freq_table; 65 struct cpufreq_frequency_table *freq_table;
57 unsigned int resume; 66 unsigned int resume;
67 unsigned int cpu_feature;
58}; 68};
59 69
60static struct acpi_cpufreq_data *drv_data[NR_CPUS]; 70static struct acpi_cpufreq_data *drv_data[NR_CPUS];
@@ -64,7 +74,20 @@ static struct cpufreq_driver acpi_cpufreq_driver;
64 74
65static unsigned int acpi_pstate_strict; 75static unsigned int acpi_pstate_strict;
66 76
67static unsigned extract_freq(u32 value, struct acpi_cpufreq_data *data) 77
78static int check_est_cpu(unsigned int cpuid)
79{
80 struct cpuinfo_x86 *cpu = &cpu_data[cpuid];
81
82 if (cpu->x86_vendor != X86_VENDOR_INTEL ||
83 !cpu_has(cpu, X86_FEATURE_EST))
84 return 0;
85
86 return 1;
87}
88
89
90static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
68{ 91{
69 struct acpi_processor_performance *perf; 92 struct acpi_processor_performance *perf;
70 int i; 93 int i;
@@ -79,6 +102,31 @@ static unsigned extract_freq(u32 value, struct acpi_cpufreq_data *data)
79} 102}
80 103
81 104
105static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
106{
107 int i;
108
109 msr &= INTEL_MSR_RANGE;
110 for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
111 if (msr == data->freq_table[i].index)
112 return data->freq_table[i].frequency;
113 }
114 return data->freq_table[0].frequency;
115}
116
117
118static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
119{
120 switch (data->cpu_feature) {
121 case SYSTEM_INTEL_MSR_CAPABLE:
122 return extract_msr(val, data);
123 case SYSTEM_IO_CAPABLE:
124 return extract_io(val, data);
125 default:
126 return 0;
127 }
128}
129
82static void wrport(u16 port, u8 bit_width, u32 value) 130static void wrport(u16 port, u8 bit_width, u32 value)
83{ 131{
84 if (bit_width <= 8) { 132 if (bit_width <= 8) {
@@ -102,27 +150,57 @@ static void rdport(u16 port, u8 bit_width, u32 *ret)
102 } 150 }
103} 151}
104 152
153struct msr_addr {
154 u32 reg;
155};
156
105struct io_addr { 157struct io_addr {
106 u16 port; 158 u16 port;
107 u8 bit_width; 159 u8 bit_width;
108}; 160};
109 161
162typedef union {
163 struct msr_addr msr;
164 struct io_addr io;
165} drv_addr_union;
166
110struct drv_cmd { 167struct drv_cmd {
168 unsigned int type;
111 cpumask_t mask; 169 cpumask_t mask;
112 struct io_addr addr; 170 drv_addr_union addr;
113 u32 val; 171 u32 val;
114}; 172};
115 173
116static void do_drv_read(struct drv_cmd *cmd) 174static void do_drv_read(struct drv_cmd *cmd)
117{ 175{
118 rdport(cmd->addr.port, cmd->addr.bit_width, &cmd->val); 176 u32 h;
119 return; 177
178 switch (cmd->type) {
179 case SYSTEM_INTEL_MSR_CAPABLE:
180 rdmsr(cmd->addr.msr.reg, cmd->val, h);
181 break;
182 case SYSTEM_IO_CAPABLE:
183 rdport(cmd->addr.io.port, cmd->addr.io.bit_width, &cmd->val);
184 break;
185 default:
186 break;
187 }
120} 188}
121 189
122static void do_drv_write(struct drv_cmd *cmd) 190static void do_drv_write(struct drv_cmd *cmd)
123{ 191{
124 wrport(cmd->addr.port, cmd->addr.bit_width, cmd->val); 192 u32 h = 0;
125 return; 193
194 switch (cmd->type) {
195 case SYSTEM_INTEL_MSR_CAPABLE:
196 wrmsr(cmd->addr.msr.reg, cmd->val, h);
197 break;
198 case SYSTEM_IO_CAPABLE:
199 wrport(cmd->addr.io.port, cmd->addr.io.bit_width, cmd->val);
200 break;
201 default:
202 break;
203 }
126} 204}
127 205
128static inline void drv_read(struct drv_cmd *cmd) 206static inline void drv_read(struct drv_cmd *cmd)
@@ -158,9 +236,21 @@ static u32 get_cur_val(cpumask_t mask)
158 if (unlikely(cpus_empty(mask))) 236 if (unlikely(cpus_empty(mask)))
159 return 0; 237 return 0;
160 238
161 perf = drv_data[first_cpu(mask)]->acpi_data; 239 switch (drv_data[first_cpu(mask)]->cpu_feature) {
162 cmd.addr.port = perf->control_register.address; 240 case SYSTEM_INTEL_MSR_CAPABLE:
163 cmd.addr.bit_width = perf->control_register.bit_width; 241 cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
242 cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
243 break;
244 case SYSTEM_IO_CAPABLE:
245 cmd.type = SYSTEM_IO_CAPABLE;
246 perf = drv_data[first_cpu(mask)]->acpi_data;
247 cmd.addr.io.port = perf->control_register.address;
248 cmd.addr.io.bit_width = perf->control_register.bit_width;
249 break;
250 default:
251 return 0;
252 }
253
164 cmd.mask = mask; 254 cmd.mask = mask;
165 255
166 drv_read(&cmd); 256 drv_read(&cmd);
@@ -213,6 +303,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
213 struct cpufreq_freqs freqs; 303 struct cpufreq_freqs freqs;
214 cpumask_t online_policy_cpus; 304 cpumask_t online_policy_cpus;
215 struct drv_cmd cmd; 305 struct drv_cmd cmd;
306 unsigned int msr;
216 unsigned int next_state = 0; 307 unsigned int next_state = 0;
217 unsigned int next_perf_state = 0; 308 unsigned int next_perf_state = 0;
218 unsigned int i; 309 unsigned int i;
@@ -256,9 +347,22 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
256 } 347 }
257 } 348 }
258 349
259 cmd.addr.port = perf->control_register.address; 350 switch (data->cpu_feature) {
260 cmd.addr.bit_width = perf->control_register.bit_width; 351 case SYSTEM_INTEL_MSR_CAPABLE:
261 cmd.val = (u32) perf->states[next_perf_state].control; 352 cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
353 cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
354 msr = (u32) perf->states[next_perf_state].control & INTEL_MSR_RANGE;
355 cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr;
356 break;
357 case SYSTEM_IO_CAPABLE:
358 cmd.type = SYSTEM_IO_CAPABLE;
359 cmd.addr.io.port = perf->control_register.address;
360 cmd.addr.io.bit_width = perf->control_register.bit_width;
361 cmd.val = (u32) perf->states[next_perf_state].control;
362 break;
363 default:
364 return -ENODEV;
365 }
262 366
263 cpus_clear(cmd.mask); 367 cpus_clear(cmd.mask);
264 368
@@ -405,6 +509,7 @@ acpi_cpufreq_cpu_init (
405 unsigned int valid_states = 0; 509 unsigned int valid_states = 0;
406 unsigned int cpu = policy->cpu; 510 unsigned int cpu = policy->cpu;
407 struct acpi_cpufreq_data *data; 511 struct acpi_cpufreq_data *data;
512 unsigned int l, h;
408 unsigned int result = 0; 513 unsigned int result = 0;
409 struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; 514 struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
410 struct acpi_processor_performance *perf; 515 struct acpi_processor_performance *perf;
@@ -463,6 +568,15 @@ acpi_cpufreq_cpu_init (
463 switch (perf->control_register.space_id) { 568 switch (perf->control_register.space_id) {
464 case ACPI_ADR_SPACE_SYSTEM_IO: 569 case ACPI_ADR_SPACE_SYSTEM_IO:
465 dprintk("SYSTEM IO addr space\n"); 570 dprintk("SYSTEM IO addr space\n");
571 data->cpu_feature = SYSTEM_IO_CAPABLE;
572 break;
573 case ACPI_ADR_SPACE_FIXED_HARDWARE:
574 dprintk("HARDWARE addr space\n");
575 if (!check_est_cpu(cpu)) {
576 result = -ENODEV;
577 goto err_unreg;
578 }
579 data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
466 break; 580 break;
467 default: 581 default:
468 dprintk("Unknown addr space %d\n", 582 dprintk("Unknown addr space %d\n",
@@ -485,9 +599,6 @@ acpi_cpufreq_cpu_init (
485 } 599 }
486 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 600 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
487 601
488 /* The current speed is unknown and not detectable by ACPI... */
489 policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
490
491 /* table init */ 602 /* table init */
492 for (i=0; i<perf->state_count; i++) 603 for (i=0; i<perf->state_count; i++)
493 { 604 {
@@ -507,6 +618,18 @@ acpi_cpufreq_cpu_init (
507 goto err_freqfree; 618 goto err_freqfree;
508 } 619 }
509 620
621 switch (data->cpu_feature) {
622 case ACPI_ADR_SPACE_SYSTEM_IO:
623 /* Current speed is unknown and not detectable by IO port */
624 policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
625 break;
626 case ACPI_ADR_SPACE_FIXED_HARDWARE:
627 get_cur_freq_on_cpu(cpu);
628 break;
629 default:
630 break;
631 }
632
510 /* notify BIOS that we exist */ 633 /* notify BIOS that we exist */
511 acpi_processor_notify_smm(THIS_MODULE); 634 acpi_processor_notify_smm(THIS_MODULE);
512 635
@@ -599,7 +722,7 @@ acpi_cpufreq_init (void)
599 722
600 acpi_cpufreq_early_init(); 723 acpi_cpufreq_early_init();
601 724
602 return cpufreq_register_driver(&acpi_cpufreq_driver); 725 return cpufreq_register_driver(&acpi_cpufreq_driver);
603} 726}
604 727
605 728