View | Details | Raw Unified | Return to bug 150318
Collapse All | Expand All

(-)/data/l/linux/arch/i386/kernel/cpu/cpufreq/longhaul.c (-61 / +140 lines)
Lines 14-20 Link Here
14
 *   until we have code that gets it right.
14
 *   until we have code that gets it right.
15
 *  Version 3 of longhaul got renamed to Powersaver and redesigned
15
 *  Version 3 of longhaul got renamed to Powersaver and redesigned
16
 *   to use the POWERSAVER MSR at 0x110a.
16
 *   to use the POWERSAVER MSR at 0x110a.
17
 *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
17
 *   It is present in Ezra-T (C5N), Nehemiah (C5XLOE/C5XLOH/C5P) and above.
18
 *   It's pretty much the same feature wise to longhaul v2, though
18
 *   It's pretty much the same feature wise to longhaul v2, though
19
 *   there is provision for scaling FSB too, but this doesn't work
19
 *   there is provision for scaling FSB too, but this doesn't work
20
 *   too well in practice so we don't even try to use this.
20
 *   too well in practice so we don't even try to use this.
Lines 29-35 Link Here
29
#include <linux/cpufreq.h>
29
#include <linux/cpufreq.h>
30
#include <linux/slab.h>
30
#include <linux/slab.h>
31
#include <linux/string.h>
31
#include <linux/string.h>
32
#include <linux/pci.h>
32
33
#include <linux/ide.h>
34
#include <linux/delay.h>
33
35
34
#include <asm/msr.h>
36
#include <asm/msr.h>
35
#include <asm/timex.h>
37
#include <asm/timex.h>
Lines 59-67 Link Here
59
61
60
/* Module parameters */
62
/* Module parameters */
61
static int dont_scale_voltage;
63
static int dont_scale_voltage;
64
static int debug;
65
66
static void dprintk(const char *fmt, ...)
67
{
68
        char s[256];
69
        va_list args;
70
71
        if (debug == 0)
72
                return;
73
74
        va_start(args, fmt);
75
        vsprintf(s, fmt, args);
76
        printk(s);
77
        va_end(args);
78
}
62
79
63
80
64
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
81
#define __hlt()     __asm__ __volatile__("hlt": : :"memory")
65
82
66
83
67
/* Clock ratios multiplied by 10 */
84
/* Clock ratios multiplied by 10 */
Lines 72-93 Link Here
72
static int longhaul_version;
89
static int longhaul_version;
73
static struct cpufreq_frequency_table *longhaul_table;
90
static struct cpufreq_frequency_table *longhaul_table;
74
91
75
#ifdef CONFIG_CPU_FREQ_DEBUG
76
static char speedbuffer[8];
77
92
78
static char *print_speed(int speed)
93
void ide_idle(void) {
79
{
94
	int i;
80
	if (speed > 1000) {
95
	ide_hwif_t *hwif = ide_hwifs;
81
		if (speed%1000 == 0)
96
	ide_drive_t *drive;
82
			sprintf (speedbuffer, "%dGHz", speed/1000);
83
		else
84
			sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100);
85
	} else
86
		sprintf (speedbuffer, "%dMHz", speed);
87
97
88
	return speedbuffer;
98
	i = 0;
99
	do {
100
		drive = &hwif->drives[i];
101
		i++;
102
		if (strncmp(drive->name,"hd",2) == 0) {
103
			while (drive->waiting_for_dma) udelay(10) ;
104
		} else {
105
			i = 0;
106
		}
107
	} while (i != 0);
89
}
108
}
90
#endif
91
109
92
110
93
static unsigned int calc_speed(int mult)
111
static unsigned int calc_speed(int mult)
Lines 118-127 Link Here
118
static void do_powersaver(union msr_longhaul *longhaul,
136
static void do_powersaver(union msr_longhaul *longhaul,
119
			unsigned int clock_ratio_index)
137
			unsigned int clock_ratio_index)
120
{
138
{
121
	struct pci_dev *dev;
139
	int version;
122
	unsigned long flags;
140
	unsigned long flags;
123
	unsigned int tmp_mask;
141
	unsigned int tmp_mask;
124
	int version;
142
	struct pci_dev *dev;
125
	int i;
143
	int i;
126
	u16 pci_cmd;
144
	u16 pci_cmd;
127
	u16 cmd_state[64];
145
	u16 cmd_state[64];
Lines 138-155 Link Here
138
	}
156
	}
139
157
140
	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
158
	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
159
141
	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
160
	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
142
	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
161
	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
143
	longhaul->bits.EnableSoftBusRatio = 1;
162
	longhaul->bits.EnableSoftBusRatio = 1;
144
	longhaul->bits.RevisionKey = 0;
163
	longhaul->bits.RevisionKey = 0;
145
164
165
	/* Begin critical section */
146
	preempt_disable();
166
	preempt_disable();
167
	ide_idle();	/* avoid ide timeouts when bus master off */
147
	local_irq_save(flags);
168
	local_irq_save(flags);
148
169
149
	/*
170
	/* get current pci bus master state for all devices */
150
	 * get current pci bus master state for all devices
171
	/* and clear bus master bit */
151
	 * and clear bus master bit
172
152
	 */
153
	dev = NULL;
173
	dev = NULL;
154
	i = 0;
174
	i = 0;
155
	do {
175
	do {
Lines 162-180 Link Here
162
		}
182
		}
163
	} while (dev != NULL);
183
	} while (dev != NULL);
164
184
185
	/* disabling INT2 takes care of ints 8-15 (cascaded) */
186
165
	tmp_mask=inb(0x21);	/* works on C3. save mask. */
187
	tmp_mask=inb(0x21);	/* works on C3. save mask. */
166
	outb(0xFE,0x21);	/* TMR0 only */
188
	outb(0xFE,0x21);        /* TMR0 only */
167
	outb(0xFF,0x80);	/* delay */
189
	outb(0xFF,0x80);        /* delay */
190
191
	local_irq_enable();     /* sti */
192
193
	__hlt();		/* make sure we've got a full tick */
168
194
169
	safe_halt();
170
	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
195
	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
171
	halt();
172
196
173
	local_irq_disable();
197
	__hlt();
198
199
	local_irq_disable();	/* cli */
174
200
175
	outb(tmp_mask,0x21);	/* restore mask */
201
	outb(tmp_mask,0x21);  /* restore mask */
176
202
177
	/* restore pci bus master state for all devices */
203
	/* restore pci bus master state for all devices */
204
178
	dev = NULL;
205
	dev = NULL;
179
	i = 0;
206
	i = 0;
180
	do {
207
	do {
Lines 184-197 Link Here
184
			pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
211
			pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
185
		}
212
		}
186
	} while (dev != NULL);
213
	} while (dev != NULL);
214
187
	local_irq_restore(flags);
215
	local_irq_restore(flags);
216
188
	preempt_enable();
217
	preempt_enable();
189
218
219
	/* END CRITICAL SECTION */
220
190
	/* disable bus ratio bit */
221
	/* disable bus ratio bit */
222
191
	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
223
	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
224
192
	longhaul->bits.EnableSoftBusRatio = 0;
225
	longhaul->bits.EnableSoftBusRatio = 0;
193
	longhaul->bits.RevisionKey = version;
226
	longhaul->bits.RevisionKey = version;
227
194
	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
228
	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
229
195
}
230
}
196
231
197
/**
232
/**
Lines 227-234 Link Here
227
262
228
	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
263
	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
229
264
230
	dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
265
	dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%d)\n",
231
			fsb, mult/10, mult%10, print_speed(speed/1000));
266
			fsb, mult/10, mult%10, speed/1000);
232
267
233
	switch (longhaul_version) {
268
	switch (longhaul_version) {
234
269
Lines 247-253 Link Here
247
		bcr2.bits.CLOCKMUL = clock_ratio_index;
282
		bcr2.bits.CLOCKMUL = clock_ratio_index;
248
		local_irq_disable();
283
		local_irq_disable();
249
		wrmsrl (MSR_VIA_BCR2, bcr2.val);
284
		wrmsrl (MSR_VIA_BCR2, bcr2.val);
250
		safe_halt();
285
		local_irq_enable();
286
287
		__hlt();
251
288
252
		/* Disable software clock multiplier */
289
		/* Disable software clock multiplier */
253
		rdmsrl (MSR_VIA_BCR2, bcr2.val);
290
		rdmsrl (MSR_VIA_BCR2, bcr2.val);
Lines 258-264 Link Here
258
		break;
295
		break;
259
296
260
	/*
297
	/*
261
	 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
298
	 * Longhaul v3 (aka Powersaver). (Ezra-T [C5N] & Nehemiah 
299
         * [C5XLOE/C5XLOH/C5P])
262
	 * We can scale voltage with this too, but that's currently
300
	 * We can scale voltage with this too, but that's currently
263
	 * disabled until we come up with a decent 'match freq to voltage'
301
	 * disabled until we come up with a decent 'match freq to voltage'
264
	 * algorithm.
302
	 * algorithm.
Lines 328-334 Link Here
328
	unsigned long lo, hi;
366
	unsigned long lo, hi;
329
	unsigned int eblcr_fsb_table_v1[] = { 66, 133, 100, -1 };
367
	unsigned int eblcr_fsb_table_v1[] = { 66, 133, 100, -1 };
330
	unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
368
	unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
331
369
        unsigned long deviceid=0,cpufreqdiv=0; // FSB 200 MHz
332
	switch (longhaul_version) {
370
	switch (longhaul_version) {
333
	case TYPE_LONGHAUL_V1:
371
	case TYPE_LONGHAUL_V1:
334
	case TYPE_LONGHAUL_V2:
372
	case TYPE_LONGHAUL_V2:
Lines 363-371 Link Here
363
		}
401
		}
364
402
365
		/* Nehemiah */
403
		/* Nehemiah */
366
		if (cpu_model==CPU_NEHEMIAH) {
404
	        if (cpu_model==CPU_NEHEMIAH) 
367
			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
405
                {
368
369
			/*
406
			/*
370
			 * TODO: This code works, but raises a lot of questions.
407
			 * TODO: This code works, but raises a lot of questions.
371
			 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
408
			 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
Lines 377-414 Link Here
377
			 *   We're possibly using something undocumented and unsupported,
414
			 *   We're possibly using something undocumented and unsupported,
378
			 *   But it works, so we don't grumble.
415
			 *   But it works, so we don't grumble.
379
			 */
416
			 */
380
			minmult=40;
381
			maxmult=longhaul_get_cpu_mult();
382
417
383
			/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
418
384
			if ((cpu_khz/1000) > 1200)
419
/* VIA improved the 200MHz FSB by Eddy Fu (2005-05-18) */
385
				fsb = 200;
420
                       // started
386
			else
421
                       __asm__ (
387
				fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
422
                		"movl    $0x80000200, %%eax\n\r"
388
			break;
423
                                "movl    $0x0cf8, %%edx\n\r"
389
		}
424
                                "outl    %%eax, %%dx\n\r"
425
                   
426
                                "movl    $0x0cfc, %%edx\n\r"
427
                                "inl     %%dx, %%eax\n\r"
428
                                "movl    %%eax, %0\n\r"
429
	                        :"=m" (deviceid)
430
                               );
431
                               // printk("deviceid=%lx\n",deviceid);
432
                      if (deviceid == 0x22591106) {    
433
                      // Read System Frequency Divider Rx54[7:5]
434
435
                              __asm__ (
436
                     	               "movl    $0x80000254, %%eax\n\r"
437
                                       "movl    $0x0cf8, %%edx\n\r"
438
                          	       "outl    %%eax, %%dx\n\r"
439
                       
440
                                       "movl    $0x0cfc, %%edx\n\r"
441
                                       "inl     %%dx, %%eax\n\r"
442
                    		       "andl    $0x000000e0, %%eax\n\r"
443
                       	               "movl    %%eax, %0\n\r"
444
                                       :"=m" (cpufreqdiv)
445
	                              );
446
		              // dprintk("cpufreqdiv = %lx\n", cpufreqdiv);
447
	    	              if (cpufreqdiv == 0x00) 
448
	                           fsb = 100;
449
	                      if (cpufreqdiv == 0x20) 
450
	                           fsb = 133;
451
	    	              if (cpufreqdiv == 0x40) 
452
                	           fsb = 200;
453
		              // dprintk ("VIA Nehemiah CPU's FSB=%d.\n", fsb);
454
                      }
455
	              else
456
	  	      { 
457
                              rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
458
	                      fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
459
                      }
460
      	        minmult=40;
461
		maxmult=longhaul_get_cpu_mult();
462
		// dprintk ("VIA Nehemiah CPU's maxmult = %d .\n", maxmult);
463
		// dprintk ("VIA Nehemiah CPU's FSB = %d .\n", fsb);
464
                // finished
465
		break;
466
	    }
390
	}
467
	}
391
468
392
	dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
469
	printk (KERN_INFO PFX "MinMult: %d.%d x MaxMult: %d.%d x\n",
393
		 minmult/10, minmult%10, maxmult/10, maxmult%10);
470
		 minmult/10, minmult%10, maxmult/10, maxmult%10);
394
471
395
	if (fsb == -1) {
472
	if (fsb == -1) {
396
		printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
473
		dprintk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
397
		return -EINVAL;
474
		return -EINVAL;
398
	}
475
	}
399
400
	highest_speed = calc_speed(maxmult);
476
	highest_speed = calc_speed(maxmult);
401
	lowest_speed = calc_speed(minmult);
477
	lowest_speed = calc_speed(minmult);
402
	dprintk ("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
478
	printk (KERN_INFO PFX "FSB: %d MHz  Lowest speed: %d   Highest speed: %d\n", fsb,
403
		 print_speed(lowest_speed/1000), 
479
		 lowest_speed/1000, 
404
		 print_speed(highest_speed/1000));
480
		 highest_speed/1000);
405
481
406
	if (lowest_speed == highest_speed) {
482
	if (lowest_speed == highest_speed) {
407
		printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
483
		dprintk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
408
		return -EINVAL;
484
		return -EINVAL;
409
	}
485
	}
410
	if (lowest_speed > highest_speed) {
486
	if (lowest_speed > highest_speed) {
411
		printk (KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
487
		dprintk (KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
412
			lowest_speed, highest_speed);
488
			lowest_speed, highest_speed);
413
		return -EINVAL;
489
		return -EINVAL;
414
	}
490
	}
Lines 453-477 Link Here
453
	vrmrev = longhaul.bits.VRMRev;
529
	vrmrev = longhaul.bits.VRMRev;
454
530
455
	if (minvid == 0 || maxvid == 0) {
531
	if (minvid == 0 || maxvid == 0) {
456
		printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
532
		dprintk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
457
					"Voltage scaling disabled.\n",
533
					"Voltage scaling disabled.\n",
458
					minvid/1000, minvid%1000, maxvid/1000, maxvid%1000);
534
					minvid/1000, minvid%1000, maxvid/1000, maxvid%1000);
459
		return;
535
		return;
460
	}
536
	}
461
537
462
	if (minvid == maxvid) {
538
	if (minvid == maxvid) {
463
		printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
539
		dprintk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
464
				"both %d.%03d. Voltage scaling disabled\n",
540
				"both %d.%03d. Voltage scaling disabled\n",
465
				maxvid/1000, maxvid%1000);
541
				maxvid/1000, maxvid%1000);
466
		return;
542
		return;
467
	}
543
	}
468
544
469
	if (vrmrev==0) {
545
	if (vrmrev==0) {
470
		dprintk ("VRM 8.5\n");
546
		dprintk ("VRM 8.5 \n");
471
		memcpy (voltage_table, vrm85scales, sizeof(voltage_table));
547
		memcpy (voltage_table, vrm85scales, sizeof(voltage_table));
472
		numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25;
548
		numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25;
473
	} else {
549
	} else {
474
		dprintk ("Mobile VRM\n");
550
		dprintk ("Mobile VRM \n");
475
		memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table));
551
		memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table));
476
		numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5;
552
		numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5;
477
	}
553
	}
Lines 565-571 Link Here
565
641
566
	case 8:
642
	case 8:
567
		cpu_model = CPU_EZRA_T;
643
		cpu_model = CPU_EZRA_T;
568
		cpuname = "C3 'Ezra-T' [C5M]";
644
		cpuname = "C3 'Ezra-T' [C5N]";
569
		longhaul_version = TYPE_POWERSAVER;
645
		longhaul_version = TYPE_POWERSAVER;
570
		numscales=32;
646
		numscales=32;
571
		memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
647
		memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
Lines 578-594 Link Here
578
		numscales=32;
654
		numscales=32;
579
		switch (c->x86_mask) {
655
		switch (c->x86_mask) {
580
		case 0 ... 1:
656
		case 0 ... 1:
581
			cpuname = "C3 'Nehemiah A' [C5N]";
657
			cpuname = "C3 'Nehemiah A' [C5XLOE]";
582
			memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
658
			memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
583
			memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
659
			memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
584
			break;
660
			break;
585
		case 2 ... 4:
661
		case 2 ... 4:
586
			cpuname = "C3 'Nehemiah B' [C5N]";
662
			cpuname = "C3 'Nehemiah B' [C5XLOH]";
587
			memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
663
			memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
588
			memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
664
			memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
589
			break;
665
			break;
590
		case 5 ... 15:
666
		case 5 ... 15:
591
			cpuname = "C3 'Nehemiah C' [C5N]";
667
			cpuname = "C3 'Nehemiah C' [C5P]";
592
			memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
668
			memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
593
			memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
669
			memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
594
			break;
670
			break;
Lines 691-696 Link Here
691
module_param (dont_scale_voltage, int, 0644);
767
module_param (dont_scale_voltage, int, 0644);
692
MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor");
768
MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor");
693
769
770
module_param (debug, int, 0644);
771
MODULE_PARM_DESC(debug, "Dump debugging information.");
772
694
MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
773
MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
695
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
774
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
696
MODULE_LICENSE ("GPL");
775
MODULE_LICENSE ("GPL");

Return to bug 150318