16 #include <linux/kernel.h>
17 #include <linux/module.h>
20 #include <linux/sched.h>
22 #include <linux/compiler.h>
26 #include <asm/processor.h>
27 #include <asm/cpufeature.h>
30 #define PFX "speedstep-centrino: "
33 #define INTEL_MSR_RANGE (0xffff)
51 static const struct cpu_id cpu_ids[] = {
59 #define N_IDS ARRAY_SIZE(cpu_ids)
69 static int centrino_verify_cpu_id(
const struct cpuinfo_x86 *
c,
78 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
85 .frequency = (mhz) * 1000, \
86 .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \
198 #define _BANIAS(cpuid, max, name) \
200 .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \
201 .max_freq = (max)*1000, \
202 .op_points = banias_##max, \
204 #define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max)
237 for(model = models; model->
cpu_id !=
NULL; model++)
238 if (centrino_verify_cpu_id(cpu, model->
cpu_id) &&
245 pr_debug(
"no support for CPU model \"%s\": "
253 pr_debug(
"no table support for CPU model \"%s\"\n",
255 pr_debug(
"try using the acpi-cpufreq driver\n");
261 pr_debug(
"found \"%s\": max frequency: %dkHz\n",
268 static inline int centrino_cpu_init_table(
struct cpufreq_policy *policy)
274 static int centrino_verify_cpu_id(
const struct cpuinfo_x86 *
c,
285 static unsigned extract_clock(
unsigned msr,
unsigned int cpu,
int failsafe)
297 msr = (msr >> 8) & 0xff;
301 if ((!
per_cpu(centrino_model, cpu)) ||
302 (!
per_cpu(centrino_model, cpu)->op_points))
307 per_cpu(centrino_model, cpu)->op_points[
i].frequency
310 if (msr ==
per_cpu(centrino_model, cpu)->op_points[
i].index)
311 return per_cpu(centrino_model, cpu)->
315 return per_cpu(centrino_model, cpu)->op_points[i-1].frequency;
321 static unsigned int get_cur_freq(
unsigned int cpu)
327 clock_freq = extract_clock(l, cpu, 0);
337 clock_freq = extract_clock(l, cpu, 1);
359 if (policy->
cpu != 0)
362 for (i = 0; i <
N_IDS; i++)
363 if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
370 pr_debug(
"found unsupported CPU with "
371 "Enhanced SpeedStep: send /proc/cpuinfo to "
376 if (centrino_cpu_init_table(policy)) {
386 pr_debug(
"trying to enable Enhanced SpeedStep (%x)\n", l);
391 if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
393 "couldn't enable Enhanced SpeedStep\n");
398 freq = get_cur_freq(policy->
cpu);
399 policy->
cpuinfo.transition_latency = 10000;
403 pr_debug(
"centrino_cpu_init: cur=%dkHz\n", policy->
cur);
406 per_cpu(centrino_model, policy->
cpu)->op_points);
411 per_cpu(centrino_model, policy->
cpu)->op_points, policy->
cpu);
418 unsigned int cpu = policy->
cpu;
420 if (!
per_cpu(centrino_model, cpu))
440 per_cpu(centrino_model, policy->
cpu)->op_points);
453 unsigned int target_freq,
454 unsigned int relation)
456 unsigned int newstate = 0;
457 unsigned int msr, oldmsr = 0, h = 0, cpu = policy->
cpu;
472 per_cpu(centrino_model, cpu)->op_points,
498 if (good_cpu >= nr_cpu_ids) {
499 pr_debug(
"couldn't limit to CPUs in this domain\n");
508 msr =
per_cpu(centrino_model, cpu)->op_points[newstate].index;
512 if (msr == (oldmsr & 0xffff)) {
513 pr_debug(
"no change needed - msr was and needs "
514 "to be %x\n", oldmsr);
519 freqs.old = extract_clock(oldmsr, cpu, 0);
520 freqs.new = extract_clock(msr, cpu, 0);
522 pr_debug(
"target=%dkHz old=%d new=%d msr=%04x\n",
523 target_freq, freqs.old, freqs.new, msr);
544 cpumask_set_cpu(j, covered_cpus);
566 freqs.new = freqs.
old;
578 free_cpumask_var(covered_cpus);
582 static struct freq_attr* centrino_attr[] = {
590 .init = centrino_cpu_init,
591 .exit = centrino_cpu_exit,
592 .verify = centrino_verify,
593 .target = centrino_target,
595 .attr = centrino_attr,
604 static const struct x86_cpu_id centrino_ids[] = {
632 static int __init centrino_init(
void)
639 static void __exit centrino_exit(
void)