Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/cpufreq/speedstep-centrino.c
15111 views
1
/*
2
* cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium
3
* M (part of the Centrino chipset).
4
*
5
* Since the original Pentium M, most new Intel CPUs support Enhanced
6
* SpeedStep.
7
*
8
* Despite the "SpeedStep" in the name, this is almost entirely unlike
9
* traditional SpeedStep.
10
*
11
* Modelled on speedstep.c
12
*
13
* Copyright (C) 2003 Jeremy Fitzhardinge <[email protected]>
14
*/
15
16
#include <linux/kernel.h>
17
#include <linux/module.h>
18
#include <linux/init.h>
19
#include <linux/cpufreq.h>
20
#include <linux/sched.h> /* current */
21
#include <linux/delay.h>
22
#include <linux/compiler.h>
23
#include <linux/gfp.h>
24
25
#include <asm/msr.h>
26
#include <asm/processor.h>
27
#include <asm/cpufeature.h>
28
29
#define PFX "speedstep-centrino: "
30
#define MAINTAINER "[email protected]"
31
32
#define INTEL_MSR_RANGE (0xffff)
33
34
struct cpu_id
35
{
36
__u8 x86; /* CPU family */
37
__u8 x86_model; /* model */
38
__u8 x86_mask; /* stepping */
39
};
40
41
enum {
42
CPU_BANIAS,
43
CPU_DOTHAN_A1,
44
CPU_DOTHAN_A2,
45
CPU_DOTHAN_B0,
46
CPU_MP4HT_D0,
47
CPU_MP4HT_E0,
48
};
49
50
static const struct cpu_id cpu_ids[] = {
51
[CPU_BANIAS] = { 6, 9, 5 },
52
[CPU_DOTHAN_A1] = { 6, 13, 1 },
53
[CPU_DOTHAN_A2] = { 6, 13, 2 },
54
[CPU_DOTHAN_B0] = { 6, 13, 6 },
55
[CPU_MP4HT_D0] = {15, 3, 4 },
56
[CPU_MP4HT_E0] = {15, 4, 1 },
57
};
58
#define N_IDS ARRAY_SIZE(cpu_ids)
59
60
struct cpu_model
61
{
62
const struct cpu_id *cpu_id;
63
const char *model_name;
64
unsigned max_freq; /* max clock in kHz */
65
66
struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
67
};
68
static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
69
const struct cpu_id *x);
70
71
/* Operating points for current CPU */
72
static DEFINE_PER_CPU(struct cpu_model *, centrino_model);
73
static DEFINE_PER_CPU(const struct cpu_id *, centrino_cpu);
74
75
static struct cpufreq_driver centrino_driver;
76
77
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
78
79
/* Computes the correct form for IA32_PERF_CTL MSR for a particular
80
frequency/voltage operating point; frequency in MHz, volts in mV.
81
This is stored as "index" in the structure. */
82
#define OP(mhz, mv) \
83
{ \
84
.frequency = (mhz) * 1000, \
85
.index = (((mhz)/100) << 8) | ((mv - 700) / 16) \
86
}
87
88
/*
89
* These voltage tables were derived from the Intel Pentium M
90
* datasheet, document 25261202.pdf, Table 5. I have verified they
91
* are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium
92
* M.
93
*/
94
95
/* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */
96
static struct cpufreq_frequency_table banias_900[] =
97
{
98
OP(600, 844),
99
OP(800, 988),
100
OP(900, 1004),
101
{ .frequency = CPUFREQ_TABLE_END }
102
};
103
104
/* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */
105
static struct cpufreq_frequency_table banias_1000[] =
106
{
107
OP(600, 844),
108
OP(800, 972),
109
OP(900, 988),
110
OP(1000, 1004),
111
{ .frequency = CPUFREQ_TABLE_END }
112
};
113
114
/* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */
115
static struct cpufreq_frequency_table banias_1100[] =
116
{
117
OP( 600, 956),
118
OP( 800, 1020),
119
OP( 900, 1100),
120
OP(1000, 1164),
121
OP(1100, 1180),
122
{ .frequency = CPUFREQ_TABLE_END }
123
};
124
125
126
/* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */
127
static struct cpufreq_frequency_table banias_1200[] =
128
{
129
OP( 600, 956),
130
OP( 800, 1004),
131
OP( 900, 1020),
132
OP(1000, 1100),
133
OP(1100, 1164),
134
OP(1200, 1180),
135
{ .frequency = CPUFREQ_TABLE_END }
136
};
137
138
/* Intel Pentium M processor 1.30GHz (Banias) */
139
static struct cpufreq_frequency_table banias_1300[] =
140
{
141
OP( 600, 956),
142
OP( 800, 1260),
143
OP(1000, 1292),
144
OP(1200, 1356),
145
OP(1300, 1388),
146
{ .frequency = CPUFREQ_TABLE_END }
147
};
148
149
/* Intel Pentium M processor 1.40GHz (Banias) */
150
static struct cpufreq_frequency_table banias_1400[] =
151
{
152
OP( 600, 956),
153
OP( 800, 1180),
154
OP(1000, 1308),
155
OP(1200, 1436),
156
OP(1400, 1484),
157
{ .frequency = CPUFREQ_TABLE_END }
158
};
159
160
/* Intel Pentium M processor 1.50GHz (Banias) */
161
static struct cpufreq_frequency_table banias_1500[] =
162
{
163
OP( 600, 956),
164
OP( 800, 1116),
165
OP(1000, 1228),
166
OP(1200, 1356),
167
OP(1400, 1452),
168
OP(1500, 1484),
169
{ .frequency = CPUFREQ_TABLE_END }
170
};
171
172
/* Intel Pentium M processor 1.60GHz (Banias) */
173
static struct cpufreq_frequency_table banias_1600[] =
174
{
175
OP( 600, 956),
176
OP( 800, 1036),
177
OP(1000, 1164),
178
OP(1200, 1276),
179
OP(1400, 1420),
180
OP(1600, 1484),
181
{ .frequency = CPUFREQ_TABLE_END }
182
};
183
184
/* Intel Pentium M processor 1.70GHz (Banias) */
185
static struct cpufreq_frequency_table banias_1700[] =
186
{
187
OP( 600, 956),
188
OP( 800, 1004),
189
OP(1000, 1116),
190
OP(1200, 1228),
191
OP(1400, 1308),
192
OP(1700, 1484),
193
{ .frequency = CPUFREQ_TABLE_END }
194
};
195
#undef OP
196
197
#define _BANIAS(cpuid, max, name) \
198
{ .cpu_id = cpuid, \
199
.model_name = "Intel(R) Pentium(R) M processor " name "MHz", \
200
.max_freq = (max)*1000, \
201
.op_points = banias_##max, \
202
}
203
#define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max)
204
205
/* CPU models, their operating frequency range, and freq/voltage
206
operating points */
207
static struct cpu_model models[] =
208
{
209
_BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"),
210
BANIAS(1000),
211
BANIAS(1100),
212
BANIAS(1200),
213
BANIAS(1300),
214
BANIAS(1400),
215
BANIAS(1500),
216
BANIAS(1600),
217
BANIAS(1700),
218
219
/* NULL model_name is a wildcard */
220
{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
221
{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
222
{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
223
{ &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },
224
{ &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },
225
226
{ NULL, }
227
};
228
#undef _BANIAS
229
#undef BANIAS
230
231
static int centrino_cpu_init_table(struct cpufreq_policy *policy)
232
{
233
struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
234
struct cpu_model *model;
235
236
for(model = models; model->cpu_id != NULL; model++)
237
if (centrino_verify_cpu_id(cpu, model->cpu_id) &&
238
(model->model_name == NULL ||
239
strcmp(cpu->x86_model_id, model->model_name) == 0))
240
break;
241
242
if (model->cpu_id == NULL) {
243
/* No match at all */
244
pr_debug("no support for CPU model \"%s\": "
245
"send /proc/cpuinfo to " MAINTAINER "\n",
246
cpu->x86_model_id);
247
return -ENOENT;
248
}
249
250
if (model->op_points == NULL) {
251
/* Matched a non-match */
252
pr_debug("no table support for CPU model \"%s\"\n",
253
cpu->x86_model_id);
254
pr_debug("try using the acpi-cpufreq driver\n");
255
return -ENOENT;
256
}
257
258
per_cpu(centrino_model, policy->cpu) = model;
259
260
pr_debug("found \"%s\": max frequency: %dkHz\n",
261
model->model_name, model->max_freq);
262
263
return 0;
264
}
265
266
#else
267
static inline int centrino_cpu_init_table(struct cpufreq_policy *policy)
268
{
269
return -ENODEV;
270
}
271
#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
272
273
static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
274
const struct cpu_id *x)
275
{
276
if ((c->x86 == x->x86) &&
277
(c->x86_model == x->x86_model) &&
278
(c->x86_mask == x->x86_mask))
279
return 1;
280
return 0;
281
}
282
283
/* To be called only after centrino_model is initialized */
284
static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe)
285
{
286
int i;
287
288
/*
289
* Extract clock in kHz from PERF_CTL value
290
* for centrino, as some DSDTs are buggy.
291
* Ideally, this can be done using the acpi_data structure.
292
*/
293
if ((per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_BANIAS]) ||
294
(per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_A1]) ||
295
(per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_B0])) {
296
msr = (msr >> 8) & 0xff;
297
return msr * 100000;
298
}
299
300
if ((!per_cpu(centrino_model, cpu)) ||
301
(!per_cpu(centrino_model, cpu)->op_points))
302
return 0;
303
304
msr &= 0xffff;
305
for (i = 0;
306
per_cpu(centrino_model, cpu)->op_points[i].frequency
307
!= CPUFREQ_TABLE_END;
308
i++) {
309
if (msr == per_cpu(centrino_model, cpu)->op_points[i].index)
310
return per_cpu(centrino_model, cpu)->
311
op_points[i].frequency;
312
}
313
if (failsafe)
314
return per_cpu(centrino_model, cpu)->op_points[i-1].frequency;
315
else
316
return 0;
317
}
318
319
/* Return the current CPU frequency in kHz */
320
static unsigned int get_cur_freq(unsigned int cpu)
321
{
322
unsigned l, h;
323
unsigned clock_freq;
324
325
rdmsr_on_cpu(cpu, MSR_IA32_PERF_STATUS, &l, &h);
326
clock_freq = extract_clock(l, cpu, 0);
327
328
if (unlikely(clock_freq == 0)) {
329
/*
330
* On some CPUs, we can see transient MSR values (which are
331
* not present in _PSS), while CPU is doing some automatic
332
* P-state transition (like TM2). Get the last freq set
333
* in PERF_CTL.
334
*/
335
rdmsr_on_cpu(cpu, MSR_IA32_PERF_CTL, &l, &h);
336
clock_freq = extract_clock(l, cpu, 1);
337
}
338
return clock_freq;
339
}
340
341
342
static int centrino_cpu_init(struct cpufreq_policy *policy)
343
{
344
struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
345
unsigned freq;
346
unsigned l, h;
347
int ret;
348
int i;
349
350
/* Only Intel makes Enhanced Speedstep-capable CPUs */
351
if (cpu->x86_vendor != X86_VENDOR_INTEL ||
352
!cpu_has(cpu, X86_FEATURE_EST))
353
return -ENODEV;
354
355
if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
356
centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
357
358
if (policy->cpu != 0)
359
return -ENODEV;
360
361
for (i = 0; i < N_IDS; i++)
362
if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
363
break;
364
365
if (i != N_IDS)
366
per_cpu(centrino_cpu, policy->cpu) = &cpu_ids[i];
367
368
if (!per_cpu(centrino_cpu, policy->cpu)) {
369
pr_debug("found unsupported CPU with "
370
"Enhanced SpeedStep: send /proc/cpuinfo to "
371
MAINTAINER "\n");
372
return -ENODEV;
373
}
374
375
if (centrino_cpu_init_table(policy)) {
376
return -ENODEV;
377
}
378
379
/* Check to see if Enhanced SpeedStep is enabled, and try to
380
enable it if not. */
381
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
382
383
if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
384
l |= MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP;
385
pr_debug("trying to enable Enhanced SpeedStep (%x)\n", l);
386
wrmsr(MSR_IA32_MISC_ENABLE, l, h);
387
388
/* check to see if it stuck */
389
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
390
if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
391
printk(KERN_INFO PFX
392
"couldn't enable Enhanced SpeedStep\n");
393
return -ENODEV;
394
}
395
}
396
397
freq = get_cur_freq(policy->cpu);
398
policy->cpuinfo.transition_latency = 10000;
399
/* 10uS transition latency */
400
policy->cur = freq;
401
402
pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur);
403
404
ret = cpufreq_frequency_table_cpuinfo(policy,
405
per_cpu(centrino_model, policy->cpu)->op_points);
406
if (ret)
407
return (ret);
408
409
cpufreq_frequency_table_get_attr(
410
per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu);
411
412
return 0;
413
}
414
415
static int centrino_cpu_exit(struct cpufreq_policy *policy)
416
{
417
unsigned int cpu = policy->cpu;
418
419
if (!per_cpu(centrino_model, cpu))
420
return -ENODEV;
421
422
cpufreq_frequency_table_put_attr(cpu);
423
424
per_cpu(centrino_model, cpu) = NULL;
425
426
return 0;
427
}
428
429
/**
430
* centrino_verify - verifies a new CPUFreq policy
431
* @policy: new policy
432
*
433
* Limit must be within this model's frequency range at least one
434
* border included.
435
*/
436
static int centrino_verify (struct cpufreq_policy *policy)
437
{
438
return cpufreq_frequency_table_verify(policy,
439
per_cpu(centrino_model, policy->cpu)->op_points);
440
}
441
442
/**
443
* centrino_setpolicy - set a new CPUFreq policy
444
* @policy: new policy
445
* @target_freq: the target frequency
446
* @relation: how that frequency relates to achieved frequency
447
* (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
448
*
449
* Sets a new CPUFreq policy.
450
*/
451
static int centrino_target (struct cpufreq_policy *policy,
452
unsigned int target_freq,
453
unsigned int relation)
454
{
455
unsigned int newstate = 0;
456
unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu;
457
struct cpufreq_freqs freqs;
458
int retval = 0;
459
unsigned int j, k, first_cpu, tmp;
460
cpumask_var_t covered_cpus;
461
462
if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL)))
463
return -ENOMEM;
464
465
if (unlikely(per_cpu(centrino_model, cpu) == NULL)) {
466
retval = -ENODEV;
467
goto out;
468
}
469
470
if (unlikely(cpufreq_frequency_table_target(policy,
471
per_cpu(centrino_model, cpu)->op_points,
472
target_freq,
473
relation,
474
&newstate))) {
475
retval = -EINVAL;
476
goto out;
477
}
478
479
first_cpu = 1;
480
for_each_cpu(j, policy->cpus) {
481
int good_cpu;
482
483
/* cpufreq holds the hotplug lock, so we are safe here */
484
if (!cpu_online(j))
485
continue;
486
487
/*
488
* Support for SMP systems.
489
* Make sure we are running on CPU that wants to change freq
490
*/
491
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
492
good_cpu = cpumask_any_and(policy->cpus,
493
cpu_online_mask);
494
else
495
good_cpu = j;
496
497
if (good_cpu >= nr_cpu_ids) {
498
pr_debug("couldn't limit to CPUs in this domain\n");
499
retval = -EAGAIN;
500
if (first_cpu) {
501
/* We haven't started the transition yet. */
502
goto out;
503
}
504
break;
505
}
506
507
msr = per_cpu(centrino_model, cpu)->op_points[newstate].index;
508
509
if (first_cpu) {
510
rdmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, &oldmsr, &h);
511
if (msr == (oldmsr & 0xffff)) {
512
pr_debug("no change needed - msr was and needs "
513
"to be %x\n", oldmsr);
514
retval = 0;
515
goto out;
516
}
517
518
freqs.old = extract_clock(oldmsr, cpu, 0);
519
freqs.new = extract_clock(msr, cpu, 0);
520
521
pr_debug("target=%dkHz old=%d new=%d msr=%04x\n",
522
target_freq, freqs.old, freqs.new, msr);
523
524
for_each_cpu(k, policy->cpus) {
525
if (!cpu_online(k))
526
continue;
527
freqs.cpu = k;
528
cpufreq_notify_transition(&freqs,
529
CPUFREQ_PRECHANGE);
530
}
531
532
first_cpu = 0;
533
/* all but 16 LSB are reserved, treat them with care */
534
oldmsr &= ~0xffff;
535
msr &= 0xffff;
536
oldmsr |= msr;
537
}
538
539
wrmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, oldmsr, h);
540
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
541
break;
542
543
cpumask_set_cpu(j, covered_cpus);
544
}
545
546
for_each_cpu(k, policy->cpus) {
547
if (!cpu_online(k))
548
continue;
549
freqs.cpu = k;
550
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
551
}
552
553
if (unlikely(retval)) {
554
/*
555
* We have failed halfway through the frequency change.
556
* We have sent callbacks to policy->cpus and
557
* MSRs have already been written on coverd_cpus.
558
* Best effort undo..
559
*/
560
561
for_each_cpu(j, covered_cpus)
562
wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h);
563
564
tmp = freqs.new;
565
freqs.new = freqs.old;
566
freqs.old = tmp;
567
for_each_cpu(j, policy->cpus) {
568
if (!cpu_online(j))
569
continue;
570
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
571
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
572
}
573
}
574
retval = 0;
575
576
out:
577
free_cpumask_var(covered_cpus);
578
return retval;
579
}
580
581
static struct freq_attr* centrino_attr[] = {
582
&cpufreq_freq_attr_scaling_available_freqs,
583
NULL,
584
};
585
586
static struct cpufreq_driver centrino_driver = {
587
.name = "centrino", /* should be speedstep-centrino,
588
but there's a 16 char limit */
589
.init = centrino_cpu_init,
590
.exit = centrino_cpu_exit,
591
.verify = centrino_verify,
592
.target = centrino_target,
593
.get = get_cur_freq,
594
.attr = centrino_attr,
595
.owner = THIS_MODULE,
596
};
597
598
599
/**
600
* centrino_init - initializes the Enhanced SpeedStep CPUFreq driver
601
*
602
* Initializes the Enhanced SpeedStep support. Returns -ENODEV on
603
* unsupported devices, -ENOENT if there's no voltage table for this
604
* particular CPU model, -EINVAL on problems during initiatization,
605
* and zero on success.
606
*
607
* This is quite picky. Not only does the CPU have to advertise the
608
* "est" flag in the cpuid capability flags, we look for a specific
609
* CPU model and stepping, and we need to have the exact model name in
610
* our voltage tables. That is, be paranoid about not releasing
611
* someone's valuable magic smoke.
612
*/
613
static int __init centrino_init(void)
614
{
615
struct cpuinfo_x86 *cpu = &cpu_data(0);
616
617
if (!cpu_has(cpu, X86_FEATURE_EST))
618
return -ENODEV;
619
620
return cpufreq_register_driver(&centrino_driver);
621
}
622
623
static void __exit centrino_exit(void)
624
{
625
cpufreq_unregister_driver(&centrino_driver);
626
}
627
628
MODULE_AUTHOR ("Jeremy Fitzhardinge <[email protected]>");
629
MODULE_DESCRIPTION ("Enhanced SpeedStep driver for Intel Pentium M processors.");
630
MODULE_LICENSE ("GPL");
631
632
late_initcall(centrino_init);
633
module_exit(centrino_exit);
634
635