Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/cpufreq/longhaul.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* (C) 2001-2004 Dave Jones.
4
* (C) 2002 Padraig Brady. <[email protected]>
5
*
6
* Based upon datasheets & sample CPUs kindly provided by VIA.
7
*
8
* VIA have currently 3 different versions of Longhaul.
9
* Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
10
* It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
11
* Version 2 of longhaul is backward compatible with v1, but adds
12
* LONGHAUL MSR for purpose of both frequency and voltage scaling.
13
* Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C).
14
* Version 3 of longhaul got renamed to Powersaver and redesigned
15
* to use only the POWERSAVER MSR at 0x110a.
16
* It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
17
* It's pretty much the same feature wise to longhaul v2, though
18
* there is provision for scaling FSB too, but this doesn't work
19
* too well in practice so we don't even try to use this.
20
*
21
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
22
*/
23
24
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
26
#include <linux/kernel.h>
27
#include <linux/module.h>
28
#include <linux/moduleparam.h>
29
#include <linux/init.h>
30
#include <linux/cpufreq.h>
31
#include <linux/pci.h>
32
#include <linux/slab.h>
33
#include <linux/string.h>
34
#include <linux/delay.h>
35
#include <linux/timex.h>
36
#include <linux/io.h>
37
#include <linux/acpi.h>
38
39
#include <asm/msr.h>
40
#include <asm/cpu_device_id.h>
41
#include <acpi/processor.h>
42
43
#include "longhaul.h"
44
45
#define TYPE_LONGHAUL_V1 1
46
#define TYPE_LONGHAUL_V2 2
47
#define TYPE_POWERSAVER 3
48
49
#define CPU_SAMUEL 1
50
#define CPU_SAMUEL2 2
51
#define CPU_EZRA 3
52
#define CPU_EZRA_T 4
53
#define CPU_NEHEMIAH 5
54
#define CPU_NEHEMIAH_C 6
55
56
/* Flags */
57
#define USE_ACPI_C3 (1 << 1)
58
#define USE_NORTHBRIDGE (1 << 2)
59
60
static int cpu_model;
61
static unsigned int numscales = 16;
62
static unsigned int fsb;
63
64
static const struct mV_pos *vrm_mV_table;
65
static const unsigned char *mV_vrm_table;
66
67
static unsigned int highest_speed, lowest_speed; /* kHz */
68
static unsigned int minmult, maxmult;
69
static int can_scale_voltage;
70
static struct acpi_processor *pr;
71
static struct acpi_processor_cx *cx;
72
static u32 acpi_regs_addr;
73
static u8 longhaul_flags;
74
static unsigned int longhaul_index;
75
76
/* Module parameters */
77
static int scale_voltage;
78
static int disable_acpi_c3;
79
static int revid_errata;
80
static int enable;
81
82
/* Clock ratios multiplied by 10 */
83
static int mults[32];
84
static int eblcr[32];
85
static int longhaul_version;
86
static struct cpufreq_frequency_table *longhaul_table;
87
88
static char speedbuffer[8];
89
90
static char *print_speed(int speed)
91
{
92
if (speed < 1000) {
93
snprintf(speedbuffer, sizeof(speedbuffer), "%dMHz", speed);
94
return speedbuffer;
95
}
96
97
if (speed%1000 == 0)
98
snprintf(speedbuffer, sizeof(speedbuffer),
99
"%dGHz", speed/1000);
100
else
101
snprintf(speedbuffer, sizeof(speedbuffer),
102
"%d.%dGHz", speed/1000, (speed%1000)/100);
103
104
return speedbuffer;
105
}
106
107
108
static unsigned int calc_speed(int mult)
109
{
110
int khz;
111
khz = (mult/10)*fsb;
112
if (mult%10)
113
khz += fsb/2;
114
khz *= 1000;
115
return khz;
116
}
117
118
119
static int longhaul_get_cpu_mult(void)
120
{
121
unsigned long invalue = 0, lo, hi;
122
123
rdmsr(MSR_IA32_EBL_CR_POWERON, lo, hi);
124
invalue = (lo & (1<<22|1<<23|1<<24|1<<25))>>22;
125
if (longhaul_version == TYPE_LONGHAUL_V2 ||
126
longhaul_version == TYPE_POWERSAVER) {
127
if (lo & (1<<27))
128
invalue += 16;
129
}
130
return eblcr[invalue];
131
}
132
133
/* For processor with BCR2 MSR */
134
135
static void do_longhaul1(unsigned int mults_index)
136
{
137
union msr_bcr2 bcr2;
138
139
rdmsrq(MSR_VIA_BCR2, bcr2.val);
140
/* Enable software clock multiplier */
141
bcr2.bits.ESOFTBF = 1;
142
bcr2.bits.CLOCKMUL = mults_index & 0xff;
143
144
/* Sync to timer tick */
145
safe_halt();
146
/* Change frequency on next halt or sleep */
147
wrmsrq(MSR_VIA_BCR2, bcr2.val);
148
/* Invoke transition */
149
ACPI_FLUSH_CPU_CACHE();
150
halt();
151
152
/* Disable software clock multiplier */
153
local_irq_disable();
154
rdmsrq(MSR_VIA_BCR2, bcr2.val);
155
bcr2.bits.ESOFTBF = 0;
156
wrmsrq(MSR_VIA_BCR2, bcr2.val);
157
}
158
159
/* For processor with Longhaul MSR */
160
161
static void do_powersaver(int cx_address, unsigned int mults_index,
162
unsigned int dir)
163
{
164
union msr_longhaul longhaul;
165
u32 t;
166
167
rdmsrq(MSR_VIA_LONGHAUL, longhaul.val);
168
/* Setup new frequency */
169
if (!revid_errata)
170
longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
171
else
172
longhaul.bits.RevisionKey = 0;
173
longhaul.bits.SoftBusRatio = mults_index & 0xf;
174
longhaul.bits.SoftBusRatio4 = (mults_index & 0x10) >> 4;
175
/* Setup new voltage */
176
if (can_scale_voltage)
177
longhaul.bits.SoftVID = (mults_index >> 8) & 0x1f;
178
/* Sync to timer tick */
179
safe_halt();
180
/* Raise voltage if necessary */
181
if (can_scale_voltage && dir) {
182
longhaul.bits.EnableSoftVID = 1;
183
wrmsrq(MSR_VIA_LONGHAUL, longhaul.val);
184
/* Change voltage */
185
if (!cx_address) {
186
ACPI_FLUSH_CPU_CACHE();
187
halt();
188
} else {
189
ACPI_FLUSH_CPU_CACHE();
190
/* Invoke C3 */
191
inb(cx_address);
192
/* Dummy op - must do something useless after P_LVL3
193
* read */
194
t = inl(acpi_gbl_FADT.xpm_timer_block.address);
195
}
196
longhaul.bits.EnableSoftVID = 0;
197
wrmsrq(MSR_VIA_LONGHAUL, longhaul.val);
198
}
199
200
/* Change frequency on next halt or sleep */
201
longhaul.bits.EnableSoftBusRatio = 1;
202
wrmsrq(MSR_VIA_LONGHAUL, longhaul.val);
203
if (!cx_address) {
204
ACPI_FLUSH_CPU_CACHE();
205
halt();
206
} else {
207
ACPI_FLUSH_CPU_CACHE();
208
/* Invoke C3 */
209
inb(cx_address);
210
/* Dummy op - must do something useless after P_LVL3 read */
211
t = inl(acpi_gbl_FADT.xpm_timer_block.address);
212
}
213
/* Disable bus ratio bit */
214
longhaul.bits.EnableSoftBusRatio = 0;
215
wrmsrq(MSR_VIA_LONGHAUL, longhaul.val);
216
217
/* Reduce voltage if necessary */
218
if (can_scale_voltage && !dir) {
219
longhaul.bits.EnableSoftVID = 1;
220
wrmsrq(MSR_VIA_LONGHAUL, longhaul.val);
221
/* Change voltage */
222
if (!cx_address) {
223
ACPI_FLUSH_CPU_CACHE();
224
halt();
225
} else {
226
ACPI_FLUSH_CPU_CACHE();
227
/* Invoke C3 */
228
inb(cx_address);
229
/* Dummy op - must do something useless after P_LVL3
230
* read */
231
t = inl(acpi_gbl_FADT.xpm_timer_block.address);
232
}
233
longhaul.bits.EnableSoftVID = 0;
234
wrmsrq(MSR_VIA_LONGHAUL, longhaul.val);
235
}
236
}
237
238
/**
239
* longhaul_setstate()
240
* @policy: cpufreq_policy structure containing the current policy.
241
* @table_index: index of the frequency within the cpufreq_frequency_table.
242
*
243
* Sets a new clock ratio.
244
*/
245
246
static int longhaul_setstate(struct cpufreq_policy *policy,
247
unsigned int table_index)
248
{
249
unsigned int mults_index;
250
int speed, mult;
251
struct cpufreq_freqs freqs;
252
unsigned long flags;
253
unsigned int pic1_mask, pic2_mask;
254
u16 bm_status = 0;
255
u32 bm_timeout = 1000;
256
unsigned int dir = 0;
257
258
mults_index = longhaul_table[table_index].driver_data;
259
/* Safety precautions */
260
mult = mults[mults_index & 0x1f];
261
if (mult == -1)
262
return -EINVAL;
263
264
speed = calc_speed(mult);
265
if ((speed > highest_speed) || (speed < lowest_speed))
266
return -EINVAL;
267
268
/* Voltage transition before frequency transition? */
269
if (can_scale_voltage && longhaul_index < table_index)
270
dir = 1;
271
272
freqs.old = calc_speed(longhaul_get_cpu_mult());
273
freqs.new = speed;
274
275
pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
276
fsb, mult/10, mult%10, print_speed(speed/1000));
277
retry_loop:
278
preempt_disable();
279
local_irq_save(flags);
280
281
pic2_mask = inb(0xA1);
282
pic1_mask = inb(0x21); /* works on C3. save mask. */
283
outb(0xFF, 0xA1); /* Overkill */
284
outb(0xFE, 0x21); /* TMR0 only */
285
286
/* Wait while PCI bus is busy. */
287
if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
288
|| ((pr != NULL) && pr->flags.bm_control))) {
289
bm_status = inw(acpi_regs_addr);
290
bm_status &= 1 << 4;
291
while (bm_status && bm_timeout) {
292
outw(1 << 4, acpi_regs_addr);
293
bm_timeout--;
294
bm_status = inw(acpi_regs_addr);
295
bm_status &= 1 << 4;
296
}
297
}
298
299
if (longhaul_flags & USE_NORTHBRIDGE) {
300
/* Disable AGP and PCI arbiters */
301
outb(3, 0x22);
302
} else if ((pr != NULL) && pr->flags.bm_control) {
303
/* Disable bus master arbitration */
304
acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
305
}
306
switch (longhaul_version) {
307
308
/*
309
* Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
310
* Software controlled multipliers only.
311
*/
312
case TYPE_LONGHAUL_V1:
313
do_longhaul1(mults_index);
314
break;
315
316
/*
317
* Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
318
*
319
* Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
320
* Nehemiah can do FSB scaling too, but this has never been proven
321
* to work in practice.
322
*/
323
case TYPE_LONGHAUL_V2:
324
case TYPE_POWERSAVER:
325
if (longhaul_flags & USE_ACPI_C3) {
326
/* Don't allow wakeup */
327
acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
328
do_powersaver(cx->address, mults_index, dir);
329
} else {
330
do_powersaver(0, mults_index, dir);
331
}
332
break;
333
}
334
335
if (longhaul_flags & USE_NORTHBRIDGE) {
336
/* Enable arbiters */
337
outb(0, 0x22);
338
} else if ((pr != NULL) && pr->flags.bm_control) {
339
/* Enable bus master arbitration */
340
acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
341
}
342
outb(pic2_mask, 0xA1); /* restore mask */
343
outb(pic1_mask, 0x21);
344
345
local_irq_restore(flags);
346
preempt_enable();
347
348
freqs.new = calc_speed(longhaul_get_cpu_mult());
349
/* Check if requested frequency is set. */
350
if (unlikely(freqs.new != speed)) {
351
pr_info("Failed to set requested frequency!\n");
352
/* Revision ID = 1 but processor is expecting revision key
353
* equal to 0. Jumpers at the bottom of processor will change
354
* multiplier and FSB, but will not change bits in Longhaul
355
* MSR nor enable voltage scaling. */
356
if (!revid_errata) {
357
pr_info("Enabling \"Ignore Revision ID\" option\n");
358
revid_errata = 1;
359
msleep(200);
360
goto retry_loop;
361
}
362
/* Why ACPI C3 sometimes doesn't work is a mystery for me.
363
* But it does happen. Processor is entering ACPI C3 state,
364
* but it doesn't change frequency. I tried poking various
365
* bits in northbridge registers, but without success. */
366
if (longhaul_flags & USE_ACPI_C3) {
367
pr_info("Disabling ACPI C3 support\n");
368
longhaul_flags &= ~USE_ACPI_C3;
369
if (revid_errata) {
370
pr_info("Disabling \"Ignore Revision ID\" option\n");
371
revid_errata = 0;
372
}
373
msleep(200);
374
goto retry_loop;
375
}
376
/* This shouldn't happen. Longhaul ver. 2 was reported not
377
* working on processors without voltage scaling, but with
378
* RevID = 1. RevID errata will make things right. Just
379
* to be 100% sure. */
380
if (longhaul_version == TYPE_LONGHAUL_V2) {
381
pr_info("Switching to Longhaul ver. 1\n");
382
longhaul_version = TYPE_LONGHAUL_V1;
383
msleep(200);
384
goto retry_loop;
385
}
386
}
387
388
if (!bm_timeout) {
389
pr_info("Warning: Timeout while waiting for idle PCI bus\n");
390
return -EBUSY;
391
}
392
393
return 0;
394
}
395
396
/*
397
* Centaur decided to make life a little more tricky.
398
* Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
399
* Samuel2 and above have to try and guess what the FSB is.
400
* We do this by assuming we booted at maximum multiplier, and interpolate
401
* between that value multiplied by possible FSBs and cpu_mhz which
402
* was calculated at boot time. Really ugly, but no other way to do this.
403
*/
404
405
#define ROUNDING 0xf
406
407
static int guess_fsb(int mult)
408
{
409
int speed = cpu_khz / 1000;
410
int i;
411
static const int speeds[] = { 666, 1000, 1333, 2000 };
412
int f_max, f_min;
413
414
for (i = 0; i < ARRAY_SIZE(speeds); i++) {
415
f_max = ((speeds[i] * mult) + 50) / 100;
416
f_max += (ROUNDING / 2);
417
f_min = f_max - ROUNDING;
418
if ((speed <= f_max) && (speed >= f_min))
419
return speeds[i] / 10;
420
}
421
return 0;
422
}
423
424
425
static int longhaul_get_ranges(void)
426
{
427
unsigned int i, j, k = 0;
428
unsigned int ratio;
429
int mult;
430
431
/* Get current frequency */
432
mult = longhaul_get_cpu_mult();
433
if (mult == -1) {
434
pr_info("Invalid (reserved) multiplier!\n");
435
return -EINVAL;
436
}
437
fsb = guess_fsb(mult);
438
if (fsb == 0) {
439
pr_info("Invalid (reserved) FSB!\n");
440
return -EINVAL;
441
}
442
/* Get max multiplier - as we always did.
443
* Longhaul MSR is useful only when voltage scaling is enabled.
444
* C3 is booting at max anyway. */
445
maxmult = mult;
446
/* Get min multiplier */
447
switch (cpu_model) {
448
case CPU_NEHEMIAH:
449
minmult = 50;
450
break;
451
case CPU_NEHEMIAH_C:
452
minmult = 40;
453
break;
454
default:
455
minmult = 30;
456
break;
457
}
458
459
pr_debug("MinMult:%d.%dx MaxMult:%d.%dx\n",
460
minmult/10, minmult%10, maxmult/10, maxmult%10);
461
462
highest_speed = calc_speed(maxmult);
463
lowest_speed = calc_speed(minmult);
464
pr_debug("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
465
print_speed(lowest_speed/1000),
466
print_speed(highest_speed/1000));
467
468
if (lowest_speed == highest_speed) {
469
pr_info("highestspeed == lowest, aborting\n");
470
return -EINVAL;
471
}
472
if (lowest_speed > highest_speed) {
473
pr_info("nonsense! lowest (%d > %d) !\n",
474
lowest_speed, highest_speed);
475
return -EINVAL;
476
}
477
478
longhaul_table = kcalloc(numscales + 1, sizeof(*longhaul_table),
479
GFP_KERNEL);
480
if (!longhaul_table)
481
return -ENOMEM;
482
483
for (j = 0; j < numscales; j++) {
484
ratio = mults[j];
485
if (ratio == -1)
486
continue;
487
if (ratio > maxmult || ratio < minmult)
488
continue;
489
longhaul_table[k].frequency = calc_speed(ratio);
490
longhaul_table[k].driver_data = j;
491
k++;
492
}
493
if (k <= 1) {
494
kfree(longhaul_table);
495
return -ENODEV;
496
}
497
/* Sort */
498
for (j = 0; j < k - 1; j++) {
499
unsigned int min_f, min_i;
500
min_f = longhaul_table[j].frequency;
501
min_i = j;
502
for (i = j + 1; i < k; i++) {
503
if (longhaul_table[i].frequency < min_f) {
504
min_f = longhaul_table[i].frequency;
505
min_i = i;
506
}
507
}
508
if (min_i != j) {
509
swap(longhaul_table[j].frequency,
510
longhaul_table[min_i].frequency);
511
swap(longhaul_table[j].driver_data,
512
longhaul_table[min_i].driver_data);
513
}
514
}
515
516
longhaul_table[k].frequency = CPUFREQ_TABLE_END;
517
518
/* Find index we are running on */
519
for (j = 0; j < k; j++) {
520
if (mults[longhaul_table[j].driver_data & 0x1f] == mult) {
521
longhaul_index = j;
522
break;
523
}
524
}
525
return 0;
526
}
527
528
529
static void longhaul_setup_voltagescaling(void)
530
{
531
struct cpufreq_frequency_table *freq_pos;
532
union msr_longhaul longhaul;
533
struct mV_pos minvid, maxvid, vid;
534
unsigned int j, speed, pos, kHz_step, numvscales;
535
int min_vid_speed;
536
537
rdmsrq(MSR_VIA_LONGHAUL, longhaul.val);
538
if (!(longhaul.bits.RevisionID & 1)) {
539
pr_info("Voltage scaling not supported by CPU\n");
540
return;
541
}
542
543
if (!longhaul.bits.VRMRev) {
544
pr_info("VRM 8.5\n");
545
vrm_mV_table = &vrm85_mV[0];
546
mV_vrm_table = &mV_vrm85[0];
547
} else {
548
pr_info("Mobile VRM\n");
549
if (cpu_model < CPU_NEHEMIAH)
550
return;
551
vrm_mV_table = &mobilevrm_mV[0];
552
mV_vrm_table = &mV_mobilevrm[0];
553
}
554
555
minvid = vrm_mV_table[longhaul.bits.MinimumVID];
556
maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
557
558
if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
559
pr_info("Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n",
560
minvid.mV/1000, minvid.mV%1000,
561
maxvid.mV/1000, maxvid.mV%1000);
562
return;
563
}
564
565
if (minvid.mV == maxvid.mV) {
566
pr_info("Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n",
567
maxvid.mV/1000, maxvid.mV%1000);
568
return;
569
}
570
571
/* How many voltage steps*/
572
numvscales = maxvid.pos - minvid.pos + 1;
573
pr_info("Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n",
574
maxvid.mV/1000, maxvid.mV%1000,
575
minvid.mV/1000, minvid.mV%1000,
576
numvscales);
577
578
/* Calculate max frequency at min voltage */
579
j = longhaul.bits.MinMHzBR;
580
if (longhaul.bits.MinMHzBR4)
581
j += 16;
582
min_vid_speed = eblcr[j];
583
if (min_vid_speed == -1)
584
return;
585
switch (longhaul.bits.MinMHzFSB) {
586
case 0:
587
min_vid_speed *= 13333;
588
break;
589
case 1:
590
min_vid_speed *= 10000;
591
break;
592
case 3:
593
min_vid_speed *= 6666;
594
break;
595
default:
596
return;
597
}
598
if (min_vid_speed >= highest_speed)
599
return;
600
/* Calculate kHz for one voltage step */
601
kHz_step = (highest_speed - min_vid_speed) / numvscales;
602
603
cpufreq_for_each_entry_idx(freq_pos, longhaul_table, j) {
604
speed = freq_pos->frequency;
605
if (speed > min_vid_speed)
606
pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
607
else
608
pos = minvid.pos;
609
freq_pos->driver_data |= mV_vrm_table[pos] << 8;
610
vid = vrm_mV_table[mV_vrm_table[pos]];
611
pr_info("f: %d kHz, index: %d, vid: %d mV\n",
612
speed, j, vid.mV);
613
}
614
615
can_scale_voltage = 1;
616
pr_info("Voltage scaling enabled\n");
617
}
618
619
620
static int longhaul_target(struct cpufreq_policy *policy,
621
unsigned int table_index)
622
{
623
unsigned int i;
624
unsigned int dir = 0;
625
u8 vid, current_vid;
626
int retval = 0;
627
628
if (!can_scale_voltage)
629
retval = longhaul_setstate(policy, table_index);
630
else {
631
/* On test system voltage transitions exceeding single
632
* step up or down were turning motherboard off. Both
633
* "ondemand" and "userspace" are unsafe. C7 is doing
634
* this in hardware, C3 is old and we need to do this
635
* in software. */
636
i = longhaul_index;
637
current_vid = (longhaul_table[longhaul_index].driver_data >> 8);
638
current_vid &= 0x1f;
639
if (table_index > longhaul_index)
640
dir = 1;
641
while (i != table_index) {
642
vid = (longhaul_table[i].driver_data >> 8) & 0x1f;
643
if (vid != current_vid) {
644
retval = longhaul_setstate(policy, i);
645
current_vid = vid;
646
msleep(200);
647
}
648
if (dir)
649
i++;
650
else
651
i--;
652
}
653
retval = longhaul_setstate(policy, table_index);
654
}
655
656
longhaul_index = table_index;
657
return retval;
658
}
659
660
661
static unsigned int longhaul_get(unsigned int cpu)
662
{
663
if (cpu)
664
return 0;
665
return calc_speed(longhaul_get_cpu_mult());
666
}
667
668
static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
669
u32 nesting_level,
670
void *context, void **return_value)
671
{
672
struct acpi_device *d = acpi_fetch_acpi_dev(obj_handle);
673
674
if (!d)
675
return 0;
676
677
*return_value = acpi_driver_data(d);
678
return 1;
679
}
680
681
/* VIA don't support PM2 reg, but have something similar */
682
static int enable_arbiter_disable(void)
683
{
684
struct pci_dev *dev;
685
int status = 1;
686
int reg;
687
u8 pci_cmd;
688
689
/* Find PLE133 host bridge */
690
reg = 0x78;
691
dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
692
NULL);
693
/* Find PM133/VT8605 host bridge */
694
if (dev == NULL)
695
dev = pci_get_device(PCI_VENDOR_ID_VIA,
696
PCI_DEVICE_ID_VIA_8605_0, NULL);
697
/* Find CLE266 host bridge */
698
if (dev == NULL) {
699
reg = 0x76;
700
dev = pci_get_device(PCI_VENDOR_ID_VIA,
701
PCI_DEVICE_ID_VIA_862X_0, NULL);
702
/* Find CN400 V-Link host bridge */
703
if (dev == NULL)
704
dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
705
}
706
if (dev != NULL) {
707
/* Enable access to port 0x22 */
708
pci_read_config_byte(dev, reg, &pci_cmd);
709
if (!(pci_cmd & 1<<7)) {
710
pci_cmd |= 1<<7;
711
pci_write_config_byte(dev, reg, pci_cmd);
712
pci_read_config_byte(dev, reg, &pci_cmd);
713
if (!(pci_cmd & 1<<7)) {
714
pr_err("Can't enable access to port 0x22\n");
715
status = 0;
716
}
717
}
718
pci_dev_put(dev);
719
return status;
720
}
721
return 0;
722
}
723
724
static int longhaul_setup_southbridge(void)
725
{
726
struct pci_dev *dev;
727
u8 pci_cmd;
728
729
/* Find VT8235 southbridge */
730
dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
731
if (dev == NULL)
732
/* Find VT8237 southbridge */
733
dev = pci_get_device(PCI_VENDOR_ID_VIA,
734
PCI_DEVICE_ID_VIA_8237, NULL);
735
if (dev != NULL) {
736
/* Set transition time to max */
737
pci_read_config_byte(dev, 0xec, &pci_cmd);
738
pci_cmd &= ~(1 << 2);
739
pci_write_config_byte(dev, 0xec, pci_cmd);
740
pci_read_config_byte(dev, 0xe4, &pci_cmd);
741
pci_cmd &= ~(1 << 7);
742
pci_write_config_byte(dev, 0xe4, pci_cmd);
743
pci_read_config_byte(dev, 0xe5, &pci_cmd);
744
pci_cmd |= 1 << 7;
745
pci_write_config_byte(dev, 0xe5, pci_cmd);
746
/* Get address of ACPI registers block*/
747
pci_read_config_byte(dev, 0x81, &pci_cmd);
748
if (pci_cmd & 1 << 7) {
749
pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
750
acpi_regs_addr &= 0xff00;
751
pr_info("ACPI I/O at 0x%x\n", acpi_regs_addr);
752
}
753
754
pci_dev_put(dev);
755
return 1;
756
}
757
return 0;
758
}
759
760
static int longhaul_cpu_init(struct cpufreq_policy *policy)
761
{
762
struct cpuinfo_x86 *c = &cpu_data(0);
763
char *cpuname = NULL;
764
int ret;
765
u32 lo, hi;
766
767
/* Check what we have on this motherboard */
768
switch (c->x86_model) {
769
case 6:
770
cpu_model = CPU_SAMUEL;
771
cpuname = "C3 'Samuel' [C5A]";
772
longhaul_version = TYPE_LONGHAUL_V1;
773
memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
774
memcpy(eblcr, samuel1_eblcr, sizeof(samuel1_eblcr));
775
break;
776
777
case 7:
778
switch (c->x86_stepping) {
779
case 0:
780
longhaul_version = TYPE_LONGHAUL_V1;
781
cpu_model = CPU_SAMUEL2;
782
cpuname = "C3 'Samuel 2' [C5B]";
783
/* Note, this is not a typo, early Samuel2's had
784
* Samuel1 ratios. */
785
memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
786
memcpy(eblcr, samuel2_eblcr, sizeof(samuel2_eblcr));
787
break;
788
case 1 ... 15:
789
longhaul_version = TYPE_LONGHAUL_V2;
790
if (c->x86_stepping < 8) {
791
cpu_model = CPU_SAMUEL2;
792
cpuname = "C3 'Samuel 2' [C5B]";
793
} else {
794
cpu_model = CPU_EZRA;
795
cpuname = "C3 'Ezra' [C5C]";
796
}
797
memcpy(mults, ezra_mults, sizeof(ezra_mults));
798
memcpy(eblcr, ezra_eblcr, sizeof(ezra_eblcr));
799
break;
800
}
801
break;
802
803
case 8:
804
cpu_model = CPU_EZRA_T;
805
cpuname = "C3 'Ezra-T' [C5M]";
806
longhaul_version = TYPE_POWERSAVER;
807
numscales = 32;
808
memcpy(mults, ezrat_mults, sizeof(ezrat_mults));
809
memcpy(eblcr, ezrat_eblcr, sizeof(ezrat_eblcr));
810
break;
811
812
case 9:
813
longhaul_version = TYPE_POWERSAVER;
814
numscales = 32;
815
memcpy(mults, nehemiah_mults, sizeof(nehemiah_mults));
816
memcpy(eblcr, nehemiah_eblcr, sizeof(nehemiah_eblcr));
817
switch (c->x86_stepping) {
818
case 0 ... 1:
819
cpu_model = CPU_NEHEMIAH;
820
cpuname = "C3 'Nehemiah A' [C5XLOE]";
821
break;
822
case 2 ... 4:
823
cpu_model = CPU_NEHEMIAH;
824
cpuname = "C3 'Nehemiah B' [C5XLOH]";
825
break;
826
case 5 ... 15:
827
cpu_model = CPU_NEHEMIAH_C;
828
cpuname = "C3 'Nehemiah C' [C5P]";
829
break;
830
}
831
break;
832
833
default:
834
cpuname = "Unknown";
835
break;
836
}
837
/* Check Longhaul ver. 2 */
838
if (longhaul_version == TYPE_LONGHAUL_V2) {
839
rdmsr(MSR_VIA_LONGHAUL, lo, hi);
840
if (lo == 0 && hi == 0)
841
/* Looks like MSR isn't present */
842
longhaul_version = TYPE_LONGHAUL_V1;
843
}
844
845
pr_info("VIA %s CPU detected. ", cpuname);
846
switch (longhaul_version) {
847
case TYPE_LONGHAUL_V1:
848
case TYPE_LONGHAUL_V2:
849
pr_cont("Longhaul v%d supported\n", longhaul_version);
850
break;
851
case TYPE_POWERSAVER:
852
pr_cont("Powersaver supported\n");
853
break;
854
}
855
856
/* Doesn't hurt */
857
longhaul_setup_southbridge();
858
859
/* Find ACPI data for processor */
860
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
861
ACPI_UINT32_MAX, &longhaul_walk_callback, NULL,
862
NULL, (void *)&pr);
863
864
/* Check ACPI support for C3 state */
865
if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
866
cx = &pr->power.states[ACPI_STATE_C3];
867
if (cx->address > 0 && cx->latency <= 1000)
868
longhaul_flags |= USE_ACPI_C3;
869
}
870
/* Disable if it isn't working */
871
if (disable_acpi_c3)
872
longhaul_flags &= ~USE_ACPI_C3;
873
/* Check if northbridge is friendly */
874
if (enable_arbiter_disable())
875
longhaul_flags |= USE_NORTHBRIDGE;
876
877
/* Check ACPI support for bus master arbiter disable */
878
if (!(longhaul_flags & USE_ACPI_C3
879
|| longhaul_flags & USE_NORTHBRIDGE)
880
&& ((pr == NULL) || !(pr->flags.bm_control))) {
881
pr_err("No ACPI support: Unsupported northbridge\n");
882
return -ENODEV;
883
}
884
885
if (longhaul_flags & USE_NORTHBRIDGE)
886
pr_info("Using northbridge support\n");
887
if (longhaul_flags & USE_ACPI_C3)
888
pr_info("Using ACPI support\n");
889
890
ret = longhaul_get_ranges();
891
if (ret != 0)
892
return ret;
893
894
if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
895
longhaul_setup_voltagescaling();
896
897
policy->transition_delay_us = 200000; /* usec */
898
policy->freq_table = longhaul_table;
899
900
return 0;
901
}
902
903
static struct cpufreq_driver longhaul_driver = {
904
.verify = cpufreq_generic_frequency_table_verify,
905
.target_index = longhaul_target,
906
.get = longhaul_get,
907
.init = longhaul_cpu_init,
908
.name = "longhaul",
909
};
910
911
static const struct x86_cpu_id longhaul_id[] = {
912
X86_MATCH_VENDOR_FAM(CENTAUR, 6, NULL),
913
{}
914
};
915
MODULE_DEVICE_TABLE(x86cpu, longhaul_id);
916
917
static int __init longhaul_init(void)
918
{
919
struct cpuinfo_x86 *c = &cpu_data(0);
920
921
if (!x86_match_cpu(longhaul_id))
922
return -ENODEV;
923
924
if (!enable) {
925
pr_err("Option \"enable\" not set - Aborting\n");
926
return -ENODEV;
927
}
928
#ifdef CONFIG_SMP
929
if (num_online_cpus() > 1) {
930
pr_err("More than 1 CPU detected, longhaul disabled\n");
931
return -ENODEV;
932
}
933
#endif
934
#ifdef CONFIG_X86_IO_APIC
935
if (boot_cpu_has(X86_FEATURE_APIC)) {
936
pr_err("APIC detected. Longhaul is currently broken in this configuration.\n");
937
return -ENODEV;
938
}
939
#endif
940
switch (c->x86_model) {
941
case 6 ... 9:
942
return cpufreq_register_driver(&longhaul_driver);
943
case 10:
944
pr_err("Use acpi-cpufreq driver for VIA C7\n");
945
}
946
947
return -ENODEV;
948
}
949
950
951
static void __exit longhaul_exit(void)
952
{
953
struct cpufreq_policy *policy = cpufreq_cpu_get(0);
954
int i;
955
956
for (i = 0; i < numscales; i++) {
957
if (mults[i] == maxmult) {
958
struct cpufreq_freqs freqs;
959
960
freqs.old = policy->cur;
961
freqs.new = longhaul_table[i].frequency;
962
freqs.flags = 0;
963
964
cpufreq_freq_transition_begin(policy, &freqs);
965
longhaul_setstate(policy, i);
966
cpufreq_freq_transition_end(policy, &freqs, 0);
967
break;
968
}
969
}
970
971
cpufreq_cpu_put(policy);
972
cpufreq_unregister_driver(&longhaul_driver);
973
kfree(longhaul_table);
974
}
975
976
/* Even if BIOS is exporting ACPI C3 state, and it is used
977
* with success when CPU is idle, this state doesn't
978
* trigger frequency transition in some cases. */
979
module_param(disable_acpi_c3, int, 0644);
980
MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
981
/* Change CPU voltage with frequency. Very useful to save
982
* power, but most VIA C3 processors aren't supporting it. */
983
module_param(scale_voltage, int, 0644);
984
MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
985
/* Force revision key to 0 for processors which doesn't
986
* support voltage scaling, but are introducing itself as
987
* such. */
988
module_param(revid_errata, int, 0644);
989
MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
990
/* By default driver is disabled to prevent incompatible
991
* system freeze. */
992
module_param(enable, int, 0644);
993
MODULE_PARM_DESC(enable, "Enable driver");
994
995
MODULE_AUTHOR("Dave Jones");
996
MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors.");
997
MODULE_LICENSE("GPL");
998
999
late_initcall(longhaul_init);
1000
module_exit(longhaul_exit);
1001
1002