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