aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/i386/kernel/cpu
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/i386/kernel/cpu')
-rw-r--r--arch/i386/kernel/cpu/Makefile19
-rw-r--r--arch/i386/kernel/cpu/amd.c249
-rw-r--r--arch/i386/kernel/cpu/centaur.c476
-rw-r--r--arch/i386/kernel/cpu/changelog63
-rw-r--r--arch/i386/kernel/cpu/common.c634
-rw-r--r--arch/i386/kernel/cpu/cpu.h30
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig231
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Makefile14
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c537
-rw-r--r--arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c457
-rw-r--r--arch/i386/kernel/cpu/cpufreq/elanfreq.c312
-rw-r--r--arch/i386/kernel/cpu/cpufreq/gx-suspmod.c502
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c658
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.h466
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longrun.c326
-rw-r--r--arch/i386/kernel/cpu/cpufreq/p4-clockmod.c337
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k6.c256
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c690
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.h44
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c1135
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h176
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c715
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h25
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-ich.c424
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c385
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.h47
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c424
-rw-r--r--arch/i386/kernel/cpu/cyrix.c439
-rw-r--r--arch/i386/kernel/cpu/intel.c248
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c598
-rw-r--r--arch/i386/kernel/cpu/mcheck/Makefile2
-rw-r--r--arch/i386/kernel/cpu/mcheck/k7.c97
-rw-r--r--arch/i386/kernel/cpu/mcheck/mce.c77
-rw-r--r--arch/i386/kernel/cpu/mcheck/mce.h14
-rw-r--r--arch/i386/kernel/cpu/mcheck/non-fatal.c93
-rw-r--r--arch/i386/kernel/cpu/mcheck/p4.c271
-rw-r--r--arch/i386/kernel/cpu/mcheck/p5.c54
-rw-r--r--arch/i386/kernel/cpu/mcheck/p6.c115
-rw-r--r--arch/i386/kernel/cpu/mcheck/winchip.c37
-rw-r--r--arch/i386/kernel/cpu/mtrr/Makefile5
-rw-r--r--arch/i386/kernel/cpu/mtrr/amd.c121
-rw-r--r--arch/i386/kernel/cpu/mtrr/centaur.c223
-rw-r--r--arch/i386/kernel/cpu/mtrr/changelog229
-rw-r--r--arch/i386/kernel/cpu/mtrr/cyrix.c364
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c417
-rw-r--r--arch/i386/kernel/cpu/mtrr/if.c374
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c693
-rw-r--r--arch/i386/kernel/cpu/mtrr/mtrr.h98
-rw-r--r--arch/i386/kernel/cpu/mtrr/state.c78
-rw-r--r--arch/i386/kernel/cpu/nexgen.c63
-rw-r--r--arch/i386/kernel/cpu/proc.c149
-rw-r--r--arch/i386/kernel/cpu/rise.c53
-rw-r--r--arch/i386/kernel/cpu/transmeta.c107
-rw-r--r--arch/i386/kernel/cpu/umc.c33
54 files changed, 14684 insertions, 0 deletions
diff --git a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile
new file mode 100644
index 000000000000..010aecfffbc1
--- /dev/null
+++ b/arch/i386/kernel/cpu/Makefile
@@ -0,0 +1,19 @@
1#
2# Makefile for x86-compatible CPU details and quirks
3#
4
5obj-y := common.o proc.o
6
7obj-y += amd.o
8obj-y += cyrix.o
9obj-y += centaur.o
10obj-y += transmeta.o
11obj-y += intel.o intel_cacheinfo.o
12obj-y += rise.o
13obj-y += nexgen.o
14obj-y += umc.o
15
16obj-$(CONFIG_X86_MCE) += mcheck/
17
18obj-$(CONFIG_MTRR) += mtrr/
19obj-$(CONFIG_CPU_FREQ) += cpufreq/
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
new file mode 100644
index 000000000000..ae94585d0445
--- /dev/null
+++ b/arch/i386/kernel/cpu/amd.c
@@ -0,0 +1,249 @@
1#include <linux/init.h>
2#include <linux/bitops.h>
3#include <linux/mm.h>
4#include <asm/io.h>
5#include <asm/processor.h>
6
7#include "cpu.h"
8
9/*
10 * B step AMD K6 before B 9730xxxx have hardware bugs that can cause
11 * misexecution of code under Linux. Owners of such processors should
12 * contact AMD for precise details and a CPU swap.
13 *
14 * See http://www.multimania.com/poulot/k6bug.html
15 * http://www.amd.com/K6/k6docs/revgd.html
16 *
17 * The following test is erm.. interesting. AMD neglected to up
18 * the chip setting when fixing the bug but they also tweaked some
19 * performance at the same time..
20 */
21
22extern void vide(void);
23__asm__(".align 4\nvide: ret");
24
25static void __init init_amd(struct cpuinfo_x86 *c)
26{
27 u32 l, h;
28 int mbytes = num_physpages >> (20-PAGE_SHIFT);
29 int r;
30
31 /*
32 * FIXME: We should handle the K5 here. Set up the write
33 * range and also turn on MSR 83 bits 4 and 31 (write alloc,
34 * no bus pipeline)
35 */
36
37 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
38 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
39 clear_bit(0*32+31, c->x86_capability);
40
41 r = get_model_name(c);
42
43 switch(c->x86)
44 {
45 case 4:
46 /*
47 * General Systems BIOSen alias the cpu frequency registers
48 * of the Elan at 0x000df000. Unfortuantly, one of the Linux
49 * drivers subsequently pokes it, and changes the CPU speed.
50 * Workaround : Remove the unneeded alias.
51 */
52#define CBAR (0xfffc) /* Configuration Base Address (32-bit) */
53#define CBAR_ENB (0x80000000)
54#define CBAR_KEY (0X000000CB)
55 if (c->x86_model==9 || c->x86_model == 10) {
56 if (inl (CBAR) & CBAR_ENB)
57 outl (0 | CBAR_KEY, CBAR);
58 }
59 break;
60 case 5:
61 if( c->x86_model < 6 )
62 {
63 /* Based on AMD doc 20734R - June 2000 */
64 if ( c->x86_model == 0 ) {
65 clear_bit(X86_FEATURE_APIC, c->x86_capability);
66 set_bit(X86_FEATURE_PGE, c->x86_capability);
67 }
68 break;
69 }
70
71 if ( c->x86_model == 6 && c->x86_mask == 1 ) {
72 const int K6_BUG_LOOP = 1000000;
73 int n;
74 void (*f_vide)(void);
75 unsigned long d, d2;
76
77 printk(KERN_INFO "AMD K6 stepping B detected - ");
78
79 /*
80 * It looks like AMD fixed the 2.6.2 bug and improved indirect
81 * calls at the same time.
82 */
83
84 n = K6_BUG_LOOP;
85 f_vide = vide;
86 rdtscl(d);
87 while (n--)
88 f_vide();
89 rdtscl(d2);
90 d = d2-d;
91
92 /* Knock these two lines out if it debugs out ok */
93 printk(KERN_INFO "AMD K6 stepping B detected - ");
94 /* -- cut here -- */
95 if (d > 20*K6_BUG_LOOP)
96 printk("system stability may be impaired when more than 32 MB are used.\n");
97 else
98 printk("probably OK (after B9730xxxx).\n");
99 printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n");
100 }
101
102 /* K6 with old style WHCR */
103 if (c->x86_model < 8 ||
104 (c->x86_model== 8 && c->x86_mask < 8)) {
105 /* We can only write allocate on the low 508Mb */
106 if(mbytes>508)
107 mbytes=508;
108
109 rdmsr(MSR_K6_WHCR, l, h);
110 if ((l&0x0000FFFF)==0) {
111 unsigned long flags;
112 l=(1<<0)|((mbytes/4)<<1);
113 local_irq_save(flags);
114 wbinvd();
115 wrmsr(MSR_K6_WHCR, l, h);
116 local_irq_restore(flags);
117 printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
118 mbytes);
119 }
120 break;
121 }
122
123 if ((c->x86_model == 8 && c->x86_mask >7) ||
124 c->x86_model == 9 || c->x86_model == 13) {
125 /* The more serious chips .. */
126
127 if(mbytes>4092)
128 mbytes=4092;
129
130 rdmsr(MSR_K6_WHCR, l, h);
131 if ((l&0xFFFF0000)==0) {
132 unsigned long flags;
133 l=((mbytes>>2)<<22)|(1<<16);
134 local_irq_save(flags);
135 wbinvd();
136 wrmsr(MSR_K6_WHCR, l, h);
137 local_irq_restore(flags);
138 printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
139 mbytes);
140 }
141
142 /* Set MTRR capability flag if appropriate */
143 if (c->x86_model == 13 || c->x86_model == 9 ||
144 (c->x86_model == 8 && c->x86_mask >= 8))
145 set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
146 break;
147 }
148 break;
149
150 case 6: /* An Athlon/Duron */
151
152 /* Bit 15 of Athlon specific MSR 15, needs to be 0
153 * to enable SSE on Palomino/Morgan/Barton CPU's.
154 * If the BIOS didn't enable it already, enable it here.
155 */
156 if (c->x86_model >= 6 && c->x86_model <= 10) {
157 if (!cpu_has(c, X86_FEATURE_XMM)) {
158 printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
159 rdmsr(MSR_K7_HWCR, l, h);
160 l &= ~0x00008000;
161 wrmsr(MSR_K7_HWCR, l, h);
162 set_bit(X86_FEATURE_XMM, c->x86_capability);
163 }
164 }
165
166 /* It's been determined by AMD that Athlons since model 8 stepping 1
167 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
168 * As per AMD technical note 27212 0.2
169 */
170 if ((c->x86_model == 8 && c->x86_mask>=1) || (c->x86_model > 8)) {
171 rdmsr(MSR_K7_CLK_CTL, l, h);
172 if ((l & 0xfff00000) != 0x20000000) {
173 printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l,
174 ((l & 0x000fffff)|0x20000000));
175 wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
176 }
177 }
178 break;
179 }
180
181 switch (c->x86) {
182 case 15:
183 set_bit(X86_FEATURE_K8, c->x86_capability);
184 break;
185 case 6:
186 set_bit(X86_FEATURE_K7, c->x86_capability);
187 break;
188 }
189
190 display_cacheinfo(c);
191 detect_ht(c);
192
193#ifdef CONFIG_X86_HT
194 /* AMD dual core looks like HT but isn't really. Hide it from the
195 scheduler. This works around problems with the domain scheduler.
196 Also probably gives slightly better scheduling and disables
197 SMT nice which is harmful on dual core.
198 TBD tune the domain scheduler for dual core. */
199 if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
200 smp_num_siblings = 1;
201#endif
202
203 if (cpuid_eax(0x80000000) >= 0x80000008) {
204 c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
205 if (c->x86_num_cores & (c->x86_num_cores - 1))
206 c->x86_num_cores = 1;
207 }
208}
209
210static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
211{
212 /* AMD errata T13 (order #21922) */
213 if ((c->x86 == 6)) {
214 if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */
215 size = 64;
216 if (c->x86_model == 4 &&
217 (c->x86_mask==0 || c->x86_mask==1)) /* Tbird rev A1/A2 */
218 size = 256;
219 }
220 return size;
221}
222
223static struct cpu_dev amd_cpu_dev __initdata = {
224 .c_vendor = "AMD",
225 .c_ident = { "AuthenticAMD" },
226 .c_models = {
227 { .vendor = X86_VENDOR_AMD, .family = 4, .model_names =
228 {
229 [3] = "486 DX/2",
230 [7] = "486 DX/2-WB",
231 [8] = "486 DX/4",
232 [9] = "486 DX/4-WB",
233 [14] = "Am5x86-WT",
234 [15] = "Am5x86-WB"
235 }
236 },
237 },
238 .c_init = init_amd,
239 .c_identify = generic_identify,
240 .c_size_cache = amd_size_cache,
241};
242
243int __init amd_init_cpu(void)
244{
245 cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
246 return 0;
247}
248
249//early_arch_initcall(amd_init_cpu);
diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
new file mode 100644
index 000000000000..394814e57672
--- /dev/null
+++ b/arch/i386/kernel/cpu/centaur.c
@@ -0,0 +1,476 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/bitops.h>
4#include <asm/processor.h>
5#include <asm/msr.h>
6#include <asm/e820.h>
7#include "cpu.h"
8
9#ifdef CONFIG_X86_OOSTORE
10
11static u32 __init power2(u32 x)
12{
13 u32 s=1;
14 while(s<=x)
15 s<<=1;
16 return s>>=1;
17}
18
19
20/*
21 * Set up an actual MCR
22 */
23
24static void __init centaur_mcr_insert(int reg, u32 base, u32 size, int key)
25{
26 u32 lo, hi;
27
28 hi = base & ~0xFFF;
29 lo = ~(size-1); /* Size is a power of 2 so this makes a mask */
30 lo &= ~0xFFF; /* Remove the ctrl value bits */
31 lo |= key; /* Attribute we wish to set */
32 wrmsr(reg+MSR_IDT_MCR0, lo, hi);
33 mtrr_centaur_report_mcr(reg, lo, hi); /* Tell the mtrr driver */
34}
35
36/*
37 * Figure what we can cover with MCR's
38 *
39 * Shortcut: We know you can't put 4Gig of RAM on a winchip
40 */
41
42static u32 __init ramtop(void) /* 16388 */
43{
44 int i;
45 u32 top = 0;
46 u32 clip = 0xFFFFFFFFUL;
47
48 for (i = 0; i < e820.nr_map; i++) {
49 unsigned long start, end;
50
51 if (e820.map[i].addr > 0xFFFFFFFFUL)
52 continue;
53 /*
54 * Don't MCR over reserved space. Ignore the ISA hole
55 * we frob around that catastrophy already
56 */
57
58 if (e820.map[i].type == E820_RESERVED)
59 {
60 if(e820.map[i].addr >= 0x100000UL && e820.map[i].addr < clip)
61 clip = e820.map[i].addr;
62 continue;
63 }
64 start = e820.map[i].addr;
65 end = e820.map[i].addr + e820.map[i].size;
66 if (start >= end)
67 continue;
68 if (end > top)
69 top = end;
70 }
71 /* Everything below 'top' should be RAM except for the ISA hole.
72 Because of the limited MCR's we want to map NV/ACPI into our
73 MCR range for gunk in RAM
74
75 Clip might cause us to MCR insufficient RAM but that is an
76 acceptable failure mode and should only bite obscure boxes with
77 a VESA hole at 15Mb
78
79 The second case Clip sometimes kicks in is when the EBDA is marked
80 as reserved. Again we fail safe with reasonable results
81 */
82
83 if(top>clip)
84 top=clip;
85
86 return top;
87}
88
89/*
90 * Compute a set of MCR's to give maximum coverage
91 */
92
93static int __init centaur_mcr_compute(int nr, int key)
94{
95 u32 mem = ramtop();
96 u32 root = power2(mem);
97 u32 base = root;
98 u32 top = root;
99 u32 floor = 0;
100 int ct = 0;
101
102 while(ct<nr)
103 {
104 u32 fspace = 0;
105
106 /*
107 * Find the largest block we will fill going upwards
108 */
109
110 u32 high = power2(mem-top);
111
112 /*
113 * Find the largest block we will fill going downwards
114 */
115
116 u32 low = base/2;
117
118 /*
119 * Don't fill below 1Mb going downwards as there
120 * is an ISA hole in the way.
121 */
122
123 if(base <= 1024*1024)
124 low = 0;
125
126 /*
127 * See how much space we could cover by filling below
128 * the ISA hole
129 */
130
131 if(floor == 0)
132 fspace = 512*1024;
133 else if(floor ==512*1024)
134 fspace = 128*1024;
135
136 /* And forget ROM space */
137
138 /*
139 * Now install the largest coverage we get
140 */
141
142 if(fspace > high && fspace > low)
143 {
144 centaur_mcr_insert(ct, floor, fspace, key);
145 floor += fspace;
146 }
147 else if(high > low)
148 {
149 centaur_mcr_insert(ct, top, high, key);
150 top += high;
151 }
152 else if(low > 0)
153 {
154 base -= low;
155 centaur_mcr_insert(ct, base, low, key);
156 }
157 else break;
158 ct++;
159 }
160 /*
161 * We loaded ct values. We now need to set the mask. The caller
162 * must do this bit.
163 */
164
165 return ct;
166}
167
168static void __init centaur_create_optimal_mcr(void)
169{
170 int i;
171 /*
172 * Allocate up to 6 mcrs to mark as much of ram as possible
173 * as write combining and weak write ordered.
174 *
175 * To experiment with: Linux never uses stack operations for
176 * mmio spaces so we could globally enable stack operation wc
177 *
178 * Load the registers with type 31 - full write combining, all
179 * writes weakly ordered.
180 */
181 int used = centaur_mcr_compute(6, 31);
182
183 /*
184 * Wipe unused MCRs
185 */
186
187 for(i=used;i<8;i++)
188 wrmsr(MSR_IDT_MCR0+i, 0, 0);
189}
190
191static void __init winchip2_create_optimal_mcr(void)
192{
193 u32 lo, hi;
194 int i;
195
196 /*
197 * Allocate up to 6 mcrs to mark as much of ram as possible
198 * as write combining, weak store ordered.
199 *
200 * Load the registers with type 25
201 * 8 - weak write ordering
202 * 16 - weak read ordering
203 * 1 - write combining
204 */
205
206 int used = centaur_mcr_compute(6, 25);
207
208 /*
209 * Mark the registers we are using.
210 */
211
212 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
213 for(i=0;i<used;i++)
214 lo|=1<<(9+i);
215 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
216
217 /*
218 * Wipe unused MCRs
219 */
220
221 for(i=used;i<8;i++)
222 wrmsr(MSR_IDT_MCR0+i, 0, 0);
223}
224
225/*
226 * Handle the MCR key on the Winchip 2.
227 */
228
229static void __init winchip2_unprotect_mcr(void)
230{
231 u32 lo, hi;
232 u32 key;
233
234 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
235 lo&=~0x1C0; /* blank bits 8-6 */
236 key = (lo>>17) & 7;
237 lo |= key<<6; /* replace with unlock key */
238 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
239}
240
241static void __init winchip2_protect_mcr(void)
242{
243 u32 lo, hi;
244
245 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
246 lo&=~0x1C0; /* blank bits 8-6 */
247 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
248}
249#endif /* CONFIG_X86_OOSTORE */
250
251#define ACE_PRESENT (1 << 6)
252#define ACE_ENABLED (1 << 7)
253#define ACE_FCR (1 << 28) /* MSR_VIA_FCR */
254
255#define RNG_PRESENT (1 << 2)
256#define RNG_ENABLED (1 << 3)
257#define RNG_ENABLE (1 << 6) /* MSR_VIA_RNG */
258
259static void __init init_c3(struct cpuinfo_x86 *c)
260{
261 u32 lo, hi;
262
263 /* Test for Centaur Extended Feature Flags presence */
264 if (cpuid_eax(0xC0000000) >= 0xC0000001) {
265 u32 tmp = cpuid_edx(0xC0000001);
266
267 /* enable ACE unit, if present and disabled */
268 if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
269 rdmsr (MSR_VIA_FCR, lo, hi);
270 lo |= ACE_FCR; /* enable ACE unit */
271 wrmsr (MSR_VIA_FCR, lo, hi);
272 printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n");
273 }
274
275 /* enable RNG unit, if present and disabled */
276 if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
277 rdmsr (MSR_VIA_RNG, lo, hi);
278 lo |= RNG_ENABLE; /* enable RNG unit */
279 wrmsr (MSR_VIA_RNG, lo, hi);
280 printk(KERN_INFO "CPU: Enabled h/w RNG\n");
281 }
282
283 /* store Centaur Extended Feature Flags as
284 * word 5 of the CPU capability bit array
285 */
286 c->x86_capability[5] = cpuid_edx(0xC0000001);
287 }
288
289 /* Cyrix III family needs CX8 & PGE explicity enabled. */
290 if (c->x86_model >=6 && c->x86_model <= 9) {
291 rdmsr (MSR_VIA_FCR, lo, hi);
292 lo |= (1<<1 | 1<<7);
293 wrmsr (MSR_VIA_FCR, lo, hi);
294 set_bit(X86_FEATURE_CX8, c->x86_capability);
295 }
296
297 /* Before Nehemiah, the C3's had 3dNOW! */
298 if (c->x86_model >=6 && c->x86_model <9)
299 set_bit(X86_FEATURE_3DNOW, c->x86_capability);
300
301 get_model_name(c);
302 display_cacheinfo(c);
303}
304
305static void __init init_centaur(struct cpuinfo_x86 *c)
306{
307 enum {
308 ECX8=1<<1,
309 EIERRINT=1<<2,
310 DPM=1<<3,
311 DMCE=1<<4,
312 DSTPCLK=1<<5,
313 ELINEAR=1<<6,
314 DSMC=1<<7,
315 DTLOCK=1<<8,
316 EDCTLB=1<<8,
317 EMMX=1<<9,
318 DPDC=1<<11,
319 EBRPRED=1<<12,
320 DIC=1<<13,
321 DDC=1<<14,
322 DNA=1<<15,
323 ERETSTK=1<<16,
324 E2MMX=1<<19,
325 EAMD3D=1<<20,
326 };
327
328 char *name;
329 u32 fcr_set=0;
330 u32 fcr_clr=0;
331 u32 lo,hi,newlo;
332 u32 aa,bb,cc,dd;
333
334 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
335 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
336 clear_bit(0*32+31, c->x86_capability);
337
338 switch (c->x86) {
339
340 case 5:
341 switch(c->x86_model) {
342 case 4:
343 name="C6";
344 fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
345 fcr_clr=DPDC;
346 printk(KERN_NOTICE "Disabling bugged TSC.\n");
347 clear_bit(X86_FEATURE_TSC, c->x86_capability);
348#ifdef CONFIG_X86_OOSTORE
349 centaur_create_optimal_mcr();
350 /* Enable
351 write combining on non-stack, non-string
352 write combining on string, all types
353 weak write ordering
354
355 The C6 original lacks weak read order
356
357 Note 0x120 is write only on Winchip 1 */
358
359 wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
360#endif
361 break;
362 case 8:
363 switch(c->x86_mask) {
364 default:
365 name="2";
366 break;
367 case 7 ... 9:
368 name="2A";
369 break;
370 case 10 ... 15:
371 name="2B";
372 break;
373 }
374 fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
375 fcr_clr=DPDC;
376#ifdef CONFIG_X86_OOSTORE
377 winchip2_unprotect_mcr();
378 winchip2_create_optimal_mcr();
379 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
380 /* Enable
381 write combining on non-stack, non-string
382 write combining on string, all types
383 weak write ordering
384 */
385 lo|=31;
386 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
387 winchip2_protect_mcr();
388#endif
389 break;
390 case 9:
391 name="3";
392 fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
393 fcr_clr=DPDC;
394#ifdef CONFIG_X86_OOSTORE
395 winchip2_unprotect_mcr();
396 winchip2_create_optimal_mcr();
397 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
398 /* Enable
399 write combining on non-stack, non-string
400 write combining on string, all types
401 weak write ordering
402 */
403 lo|=31;
404 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
405 winchip2_protect_mcr();
406#endif
407 break;
408 case 10:
409 name="4";
410 /* no info on the WC4 yet */
411 break;
412 default:
413 name="??";
414 }
415
416 rdmsr(MSR_IDT_FCR1, lo, hi);
417 newlo=(lo|fcr_set) & (~fcr_clr);
418
419 if (newlo!=lo) {
420 printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
421 wrmsr(MSR_IDT_FCR1, newlo, hi );
422 } else {
423 printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
424 }
425 /* Emulate MTRRs using Centaur's MCR. */
426 set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability);
427 /* Report CX8 */
428 set_bit(X86_FEATURE_CX8, c->x86_capability);
429 /* Set 3DNow! on Winchip 2 and above. */
430 if (c->x86_model >=8)
431 set_bit(X86_FEATURE_3DNOW, c->x86_capability);
432 /* See if we can find out some more. */
433 if ( cpuid_eax(0x80000000) >= 0x80000005 ) {
434 /* Yes, we can. */
435 cpuid(0x80000005,&aa,&bb,&cc,&dd);
436 /* Add L1 data and code cache sizes. */
437 c->x86_cache_size = (cc>>24)+(dd>>24);
438 }
439 sprintf( c->x86_model_id, "WinChip %s", name );
440 break;
441
442 case 6:
443 init_c3(c);
444 break;
445 }
446}
447
448static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
449{
450 /* VIA C3 CPUs (670-68F) need further shifting. */
451 if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
452 size >>= 8;
453
454 /* VIA also screwed up Nehemiah stepping 1, and made
455 it return '65KB' instead of '64KB'
456 - Note, it seems this may only be in engineering samples. */
457 if ((c->x86==6) && (c->x86_model==9) && (c->x86_mask==1) && (size==65))
458 size -=1;
459
460 return size;
461}
462
463static struct cpu_dev centaur_cpu_dev __initdata = {
464 .c_vendor = "Centaur",
465 .c_ident = { "CentaurHauls" },
466 .c_init = init_centaur,
467 .c_size_cache = centaur_size_cache,
468};
469
470int __init centaur_init_cpu(void)
471{
472 cpu_devs[X86_VENDOR_CENTAUR] = &centaur_cpu_dev;
473 return 0;
474}
475
476//early_arch_initcall(centaur_init_cpu);
diff --git a/arch/i386/kernel/cpu/changelog b/arch/i386/kernel/cpu/changelog
new file mode 100644
index 000000000000..cef76b80a710
--- /dev/null
+++ b/arch/i386/kernel/cpu/changelog
@@ -0,0 +1,63 @@
1/*
2 * Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean
3 * and Martin Mares, November 1997.
4 *
5 * Force Cyrix 6x86(MX) and M II processors to report MTRR capability
6 * and Cyrix "coma bug" recognition by
7 * Zoltán Böszörményi <zboszor@mail.externet.hu> February 1999.
8 *
9 * Force Centaur C6 processors to report MTRR capability.
10 * Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
11 *
12 * Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
13 *
14 * IDT Winchip tweaks, misc clean ups.
15 * Dave Jones <davej@suse.de>, August 1999
16 *
17 * Better detection of Centaur/IDT WinChip models.
18 * Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999.
19 *
20 * Cleaned up cache-detection code
21 * Dave Jones <davej@suse.de>, October 1999
22 *
23 * Added proper L2 cache detection for Coppermine
24 * Dragan Stancevic <visitor@valinux.com>, October 1999
25 *
26 * Added the original array for capability flags but forgot to credit
27 * myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff
28 * Jauder Ho <jauderho@carumba.com>, January 2000
29 *
30 * Detection for Celeron coppermine, identify_cpu() overhauled,
31 * and a few other clean ups.
32 * Dave Jones <davej@suse.de>, April 2000
33 *
34 * Pentium III FXSR, SSE support
35 * General FPU state handling cleanups
36 * Gareth Hughes <gareth@valinux.com>, May 2000
37 *
38 * Added proper Cascades CPU and L2 cache detection for Cascades
39 * and 8-way type cache happy bunch from Intel:^)
40 * Dragan Stancevic <visitor@valinux.com>, May 2000
41 *
42 * Forward port AMD Duron errata T13 from 2.2.17pre
43 * Dave Jones <davej@suse.de>, August 2000
44 *
45 * Forward port lots of fixes/improvements from 2.2.18pre
46 * Cyrix III, Pentium IV support.
47 * Dave Jones <davej@suse.de>, October 2000
48 *
49 * Massive cleanup of CPU detection and bug handling;
50 * Transmeta CPU detection,
51 * H. Peter Anvin <hpa@zytor.com>, November 2000
52 *
53 * VIA C3 Support.
54 * Dave Jones <davej@suse.de>, March 2001
55 *
56 * AMD Athlon/Duron/Thunderbird bluesmoke support.
57 * Dave Jones <davej@suse.de>, April 2001.
58 *
59 * CacheSize bug workaround updates for AMD, Intel & VIA Cyrix.
60 * Dave Jones <davej@suse.de>, September, October 2001.
61 *
62 */
63
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
new file mode 100644
index 000000000000..ebd5d8247faa
--- /dev/null
+++ b/arch/i386/kernel/cpu/common.c
@@ -0,0 +1,634 @@
1#include <linux/init.h>
2#include <linux/string.h>
3#include <linux/delay.h>
4#include <linux/smp.h>
5#include <linux/module.h>
6#include <linux/percpu.h>
7#include <asm/semaphore.h>
8#include <asm/processor.h>
9#include <asm/i387.h>
10#include <asm/msr.h>
11#include <asm/io.h>
12#include <asm/mmu_context.h>
13#ifdef CONFIG_X86_LOCAL_APIC
14#include <asm/mpspec.h>
15#include <asm/apic.h>
16#include <mach_apic.h>
17#endif
18
19#include "cpu.h"
20
21DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
22EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
23
24DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
25EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
26
27static int cachesize_override __initdata = -1;
28static int disable_x86_fxsr __initdata = 0;
29static int disable_x86_serial_nr __initdata = 1;
30
31struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
32
33extern void mcheck_init(struct cpuinfo_x86 *c);
34
35extern int disable_pse;
36
37static void default_init(struct cpuinfo_x86 * c)
38{
39 /* Not much we can do here... */
40 /* Check if at least it has cpuid */
41 if (c->cpuid_level == -1) {
42 /* No cpuid. It must be an ancient CPU */
43 if (c->x86 == 4)
44 strcpy(c->x86_model_id, "486");
45 else if (c->x86 == 3)
46 strcpy(c->x86_model_id, "386");
47 }
48}
49
50static struct cpu_dev default_cpu = {
51 .c_init = default_init,
52};
53static struct cpu_dev * this_cpu = &default_cpu;
54
55static int __init cachesize_setup(char *str)
56{
57 get_option (&str, &cachesize_override);
58 return 1;
59}
60__setup("cachesize=", cachesize_setup);
61
62int __init get_model_name(struct cpuinfo_x86 *c)
63{
64 unsigned int *v;
65 char *p, *q;
66
67 if (cpuid_eax(0x80000000) < 0x80000004)
68 return 0;
69
70 v = (unsigned int *) c->x86_model_id;
71 cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
72 cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
73 cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
74 c->x86_model_id[48] = 0;
75
76 /* Intel chips right-justify this string for some dumb reason;
77 undo that brain damage */
78 p = q = &c->x86_model_id[0];
79 while ( *p == ' ' )
80 p++;
81 if ( p != q ) {
82 while ( *p )
83 *q++ = *p++;
84 while ( q <= &c->x86_model_id[48] )
85 *q++ = '\0'; /* Zero-pad the rest */
86 }
87
88 return 1;
89}
90
91
92void __init display_cacheinfo(struct cpuinfo_x86 *c)
93{
94 unsigned int n, dummy, ecx, edx, l2size;
95
96 n = cpuid_eax(0x80000000);
97
98 if (n >= 0x80000005) {
99 cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
100 printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
101 edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
102 c->x86_cache_size=(ecx>>24)+(edx>>24);
103 }
104
105 if (n < 0x80000006) /* Some chips just has a large L1. */
106 return;
107
108 ecx = cpuid_ecx(0x80000006);
109 l2size = ecx >> 16;
110
111 /* do processor-specific cache resizing */
112 if (this_cpu->c_size_cache)
113 l2size = this_cpu->c_size_cache(c,l2size);
114
115 /* Allow user to override all this if necessary. */
116 if (cachesize_override != -1)
117 l2size = cachesize_override;
118
119 if ( l2size == 0 )
120 return; /* Again, no L2 cache is possible */
121
122 c->x86_cache_size = l2size;
123
124 printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
125 l2size, ecx & 0xFF);
126}
127
128/* Naming convention should be: <Name> [(<Codename>)] */
129/* This table only is used unless init_<vendor>() below doesn't set it; */
130/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
131
132/* Look up CPU names by table lookup. */
133static char __init *table_lookup_model(struct cpuinfo_x86 *c)
134{
135 struct cpu_model_info *info;
136
137 if ( c->x86_model >= 16 )
138 return NULL; /* Range check */
139
140 if (!this_cpu)
141 return NULL;
142
143 info = this_cpu->c_models;
144
145 while (info && info->family) {
146 if (info->family == c->x86)
147 return info->model_names[c->x86_model];
148 info++;
149 }
150 return NULL; /* Not found */
151}
152
153
154void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early)
155{
156 char *v = c->x86_vendor_id;
157 int i;
158
159 for (i = 0; i < X86_VENDOR_NUM; i++) {
160 if (cpu_devs[i]) {
161 if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
162 (cpu_devs[i]->c_ident[1] &&
163 !strcmp(v,cpu_devs[i]->c_ident[1]))) {
164 c->x86_vendor = i;
165 if (!early)
166 this_cpu = cpu_devs[i];
167 break;
168 }
169 }
170 }
171}
172
173
174static int __init x86_fxsr_setup(char * s)
175{
176 disable_x86_fxsr = 1;
177 return 1;
178}
179__setup("nofxsr", x86_fxsr_setup);
180
181
182/* Standard macro to see if a specific flag is changeable */
183static inline int flag_is_changeable_p(u32 flag)
184{
185 u32 f1, f2;
186
187 asm("pushfl\n\t"
188 "pushfl\n\t"
189 "popl %0\n\t"
190 "movl %0,%1\n\t"
191 "xorl %2,%0\n\t"
192 "pushl %0\n\t"
193 "popfl\n\t"
194 "pushfl\n\t"
195 "popl %0\n\t"
196 "popfl\n\t"
197 : "=&r" (f1), "=&r" (f2)
198 : "ir" (flag));
199
200 return ((f1^f2) & flag) != 0;
201}
202
203
204/* Probe for the CPUID instruction */
205static int __init have_cpuid_p(void)
206{
207 return flag_is_changeable_p(X86_EFLAGS_ID);
208}
209
210/* Do minimum CPU detection early.
211 Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
212 The others are not touched to avoid unwanted side effects. */
213static void __init early_cpu_detect(void)
214{
215 struct cpuinfo_x86 *c = &boot_cpu_data;
216
217 c->x86_cache_alignment = 32;
218
219 if (!have_cpuid_p())
220 return;
221
222 /* Get vendor name */
223 cpuid(0x00000000, &c->cpuid_level,
224 (int *)&c->x86_vendor_id[0],
225 (int *)&c->x86_vendor_id[8],
226 (int *)&c->x86_vendor_id[4]);
227
228 get_cpu_vendor(c, 1);
229
230 c->x86 = 4;
231 if (c->cpuid_level >= 0x00000001) {
232 u32 junk, tfms, cap0, misc;
233 cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
234 c->x86 = (tfms >> 8) & 15;
235 c->x86_model = (tfms >> 4) & 15;
236 if (c->x86 == 0xf) {
237 c->x86 += (tfms >> 20) & 0xff;
238 c->x86_model += ((tfms >> 16) & 0xF) << 4;
239 }
240 c->x86_mask = tfms & 15;
241 if (cap0 & (1<<19))
242 c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
243 }
244
245 early_intel_workaround(c);
246}
247
248void __init generic_identify(struct cpuinfo_x86 * c)
249{
250 u32 tfms, xlvl;
251 int junk;
252
253 if (have_cpuid_p()) {
254 /* Get vendor name */
255 cpuid(0x00000000, &c->cpuid_level,
256 (int *)&c->x86_vendor_id[0],
257 (int *)&c->x86_vendor_id[8],
258 (int *)&c->x86_vendor_id[4]);
259
260 get_cpu_vendor(c, 0);
261 /* Initialize the standard set of capabilities */
262 /* Note that the vendor-specific code below might override */
263
264 /* Intel-defined flags: level 0x00000001 */
265 if ( c->cpuid_level >= 0x00000001 ) {
266 u32 capability, excap;
267 cpuid(0x00000001, &tfms, &junk, &excap, &capability);
268 c->x86_capability[0] = capability;
269 c->x86_capability[4] = excap;
270 c->x86 = (tfms >> 8) & 15;
271 c->x86_model = (tfms >> 4) & 15;
272 if (c->x86 == 0xf) {
273 c->x86 += (tfms >> 20) & 0xff;
274 c->x86_model += ((tfms >> 16) & 0xF) << 4;
275 }
276 c->x86_mask = tfms & 15;
277 } else {
278 /* Have CPUID level 0 only - unheard of */
279 c->x86 = 4;
280 }
281
282 /* AMD-defined flags: level 0x80000001 */
283 xlvl = cpuid_eax(0x80000000);
284 if ( (xlvl & 0xffff0000) == 0x80000000 ) {
285 if ( xlvl >= 0x80000001 ) {
286 c->x86_capability[1] = cpuid_edx(0x80000001);
287 c->x86_capability[6] = cpuid_ecx(0x80000001);
288 }
289 if ( xlvl >= 0x80000004 )
290 get_model_name(c); /* Default name */
291 }
292 }
293}
294
295static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
296{
297 if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
298 /* Disable processor serial number */
299 unsigned long lo,hi;
300 rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
301 lo |= 0x200000;
302 wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
303 printk(KERN_NOTICE "CPU serial number disabled.\n");
304 clear_bit(X86_FEATURE_PN, c->x86_capability);
305
306 /* Disabling the serial number may affect the cpuid level */
307 c->cpuid_level = cpuid_eax(0);
308 }
309}
310
311static int __init x86_serial_nr_setup(char *s)
312{
313 disable_x86_serial_nr = 0;
314 return 1;
315}
316__setup("serialnumber", x86_serial_nr_setup);
317
318
319
320/*
321 * This does the hard work of actually picking apart the CPU stuff...
322 */
323void __init identify_cpu(struct cpuinfo_x86 *c)
324{
325 int i;
326
327 c->loops_per_jiffy = loops_per_jiffy;
328 c->x86_cache_size = -1;
329 c->x86_vendor = X86_VENDOR_UNKNOWN;
330 c->cpuid_level = -1; /* CPUID not detected */
331 c->x86_model = c->x86_mask = 0; /* So far unknown... */
332 c->x86_vendor_id[0] = '\0'; /* Unset */
333 c->x86_model_id[0] = '\0'; /* Unset */
334 c->x86_num_cores = 1;
335 memset(&c->x86_capability, 0, sizeof c->x86_capability);
336
337 if (!have_cpuid_p()) {
338 /* First of all, decide if this is a 486 or higher */
339 /* It's a 486 if we can modify the AC flag */
340 if ( flag_is_changeable_p(X86_EFLAGS_AC) )
341 c->x86 = 4;
342 else
343 c->x86 = 3;
344 }
345
346 generic_identify(c);
347
348 printk(KERN_DEBUG "CPU: After generic identify, caps:");
349 for (i = 0; i < NCAPINTS; i++)
350 printk(" %08lx", c->x86_capability[i]);
351 printk("\n");
352
353 if (this_cpu->c_identify) {
354 this_cpu->c_identify(c);
355
356 printk(KERN_DEBUG "CPU: After vendor identify, caps:");
357 for (i = 0; i < NCAPINTS; i++)
358 printk(" %08lx", c->x86_capability[i]);
359 printk("\n");
360 }
361
362 /*
363 * Vendor-specific initialization. In this section we
364 * canonicalize the feature flags, meaning if there are
365 * features a certain CPU supports which CPUID doesn't
366 * tell us, CPUID claiming incorrect flags, or other bugs,
367 * we handle them here.
368 *
369 * At the end of this section, c->x86_capability better
370 * indicate the features this CPU genuinely supports!
371 */
372 if (this_cpu->c_init)
373 this_cpu->c_init(c);
374
375 /* Disable the PN if appropriate */
376 squash_the_stupid_serial_number(c);
377
378 /*
379 * The vendor-specific functions might have changed features. Now
380 * we do "generic changes."
381 */
382
383 /* TSC disabled? */
384 if ( tsc_disable )
385 clear_bit(X86_FEATURE_TSC, c->x86_capability);
386
387 /* FXSR disabled? */
388 if (disable_x86_fxsr) {
389 clear_bit(X86_FEATURE_FXSR, c->x86_capability);
390 clear_bit(X86_FEATURE_XMM, c->x86_capability);
391 }
392
393 if (disable_pse)
394 clear_bit(X86_FEATURE_PSE, c->x86_capability);
395
396 /* If the model name is still unset, do table lookup. */
397 if ( !c->x86_model_id[0] ) {
398 char *p;
399 p = table_lookup_model(c);
400 if ( p )
401 strcpy(c->x86_model_id, p);
402 else
403 /* Last resort... */
404 sprintf(c->x86_model_id, "%02x/%02x",
405 c->x86_vendor, c->x86_model);
406 }
407
408 /* Now the feature flags better reflect actual CPU features! */
409
410 printk(KERN_DEBUG "CPU: After all inits, caps:");
411 for (i = 0; i < NCAPINTS; i++)
412 printk(" %08lx", c->x86_capability[i]);
413 printk("\n");
414
415 /*
416 * On SMP, boot_cpu_data holds the common feature set between
417 * all CPUs; so make sure that we indicate which features are
418 * common between the CPUs. The first time this routine gets
419 * executed, c == &boot_cpu_data.
420 */
421 if ( c != &boot_cpu_data ) {
422 /* AND the already accumulated flags with these */
423 for ( i = 0 ; i < NCAPINTS ; i++ )
424 boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
425 }
426
427 /* Init Machine Check Exception if available. */
428#ifdef CONFIG_X86_MCE
429 mcheck_init(c);
430#endif
431}
432
433#ifdef CONFIG_X86_HT
434void __init detect_ht(struct cpuinfo_x86 *c)
435{
436 u32 eax, ebx, ecx, edx;
437 int index_lsb, index_msb, tmp;
438 int cpu = smp_processor_id();
439
440 if (!cpu_has(c, X86_FEATURE_HT))
441 return;
442
443 cpuid(1, &eax, &ebx, &ecx, &edx);
444 smp_num_siblings = (ebx & 0xff0000) >> 16;
445
446 if (smp_num_siblings == 1) {
447 printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
448 } else if (smp_num_siblings > 1 ) {
449 index_lsb = 0;
450 index_msb = 31;
451
452 if (smp_num_siblings > NR_CPUS) {
453 printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
454 smp_num_siblings = 1;
455 return;
456 }
457 tmp = smp_num_siblings;
458 while ((tmp & 1) == 0) {
459 tmp >>=1 ;
460 index_lsb++;
461 }
462 tmp = smp_num_siblings;
463 while ((tmp & 0x80000000 ) == 0) {
464 tmp <<=1 ;
465 index_msb--;
466 }
467 if (index_lsb != index_msb )
468 index_msb++;
469 phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
470
471 printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
472 phys_proc_id[cpu]);
473 }
474}
475#endif
476
477void __init print_cpu_info(struct cpuinfo_x86 *c)
478{
479 char *vendor = NULL;
480
481 if (c->x86_vendor < X86_VENDOR_NUM)
482 vendor = this_cpu->c_vendor;
483 else if (c->cpuid_level >= 0)
484 vendor = c->x86_vendor_id;
485
486 if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
487 printk("%s ", vendor);
488
489 if (!c->x86_model_id[0])
490 printk("%d86", c->x86);
491 else
492 printk("%s", c->x86_model_id);
493
494 if (c->x86_mask || c->cpuid_level >= 0)
495 printk(" stepping %02x\n", c->x86_mask);
496 else
497 printk("\n");
498}
499
500cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
501
502/* This is hacky. :)
503 * We're emulating future behavior.
504 * In the future, the cpu-specific init functions will be called implicitly
505 * via the magic of initcalls.
506 * They will insert themselves into the cpu_devs structure.
507 * Then, when cpu_init() is called, we can just iterate over that array.
508 */
509
510extern int intel_cpu_init(void);
511extern int cyrix_init_cpu(void);
512extern int nsc_init_cpu(void);
513extern int amd_init_cpu(void);
514extern int centaur_init_cpu(void);
515extern int transmeta_init_cpu(void);
516extern int rise_init_cpu(void);
517extern int nexgen_init_cpu(void);
518extern int umc_init_cpu(void);
519
520void __init early_cpu_init(void)
521{
522 intel_cpu_init();
523 cyrix_init_cpu();
524 nsc_init_cpu();
525 amd_init_cpu();
526 centaur_init_cpu();
527 transmeta_init_cpu();
528 rise_init_cpu();
529 nexgen_init_cpu();
530 umc_init_cpu();
531 early_cpu_detect();
532
533#ifdef CONFIG_DEBUG_PAGEALLOC
534 /* pse is not compatible with on-the-fly unmapping,
535 * disable it even if the cpus claim to support it.
536 */
537 clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
538 disable_pse = 1;
539#endif
540}
541/*
542 * cpu_init() initializes state that is per-CPU. Some data is already
543 * initialized (naturally) in the bootstrap process, such as the GDT
544 * and IDT. We reload them nevertheless, this function acts as a
545 * 'CPU state barrier', nothing should get across.
546 */
547void __init cpu_init (void)
548{
549 int cpu = smp_processor_id();
550 struct tss_struct * t = &per_cpu(init_tss, cpu);
551 struct thread_struct *thread = &current->thread;
552 __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
553
554 if (cpu_test_and_set(cpu, cpu_initialized)) {
555 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
556 for (;;) local_irq_enable();
557 }
558 printk(KERN_INFO "Initializing CPU#%d\n", cpu);
559
560 if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
561 clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
562 if (tsc_disable && cpu_has_tsc) {
563 printk(KERN_NOTICE "Disabling TSC...\n");
564 /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
565 clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
566 set_in_cr4(X86_CR4_TSD);
567 }
568
569 /*
570 * Initialize the per-CPU GDT with the boot GDT,
571 * and set up the GDT descriptor:
572 */
573 memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
574 GDT_SIZE);
575
576 /* Set up GDT entry for 16bit stack */
577 *(__u64 *)&(per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_ESPFIX_SS]) |=
578 ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
579 ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
580 (CPU_16BIT_STACK_SIZE - 1);
581
582 cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
583 cpu_gdt_descr[cpu].address =
584 (unsigned long)&per_cpu(cpu_gdt_table, cpu);
585
586 /*
587 * Set up the per-thread TLS descriptor cache:
588 */
589 memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
590 GDT_ENTRY_TLS_ENTRIES * 8);
591
592 __asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
593 __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
594
595 /*
596 * Delete NT
597 */
598 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
599
600 /*
601 * Set up and load the per-CPU TSS and LDT
602 */
603 atomic_inc(&init_mm.mm_count);
604 current->active_mm = &init_mm;
605 if (current->mm)
606 BUG();
607 enter_lazy_tlb(&init_mm, current);
608
609 load_esp0(t, thread);
610 set_tss_desc(cpu,t);
611 load_TR_desc();
612 load_LDT(&init_mm.context);
613
614 /* Set up doublefault TSS pointer in the GDT */
615 __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
616
617 /* Clear %fs and %gs. */
618 asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
619
620 /* Clear all 6 debug registers: */
621
622#define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
623
624 CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
625
626#undef CD
627
628 /*
629 * Force FPU initialization:
630 */
631 current_thread_info()->status = 0;
632 clear_used_math();
633 mxcsr_feature_mask_init();
634}
diff --git a/arch/i386/kernel/cpu/cpu.h b/arch/i386/kernel/cpu/cpu.h
new file mode 100644
index 000000000000..5a1d4f163e84
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpu.h
@@ -0,0 +1,30 @@
1
2struct cpu_model_info {
3 int vendor;
4 int family;
5 char *model_names[16];
6};
7
8/* attempt to consolidate cpu attributes */
9struct cpu_dev {
10 char * c_vendor;
11
12 /* some have two possibilities for cpuid string */
13 char * c_ident[2];
14
15 struct cpu_model_info c_models[4];
16
17 void (*c_init)(struct cpuinfo_x86 * c);
18 void (*c_identify)(struct cpuinfo_x86 * c);
19 unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size);
20};
21
22extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
23
24extern int get_model_name(struct cpuinfo_x86 *c);
25extern void display_cacheinfo(struct cpuinfo_x86 *c);
26
27extern void generic_identify(struct cpuinfo_x86 * c);
28
29extern void early_intel_workaround(struct cpuinfo_x86 *c);
30
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
new file mode 100644
index 000000000000..f25ffd74235c
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -0,0 +1,231 @@
1#
2# CPU Frequency scaling
3#
4
5menu "CPU Frequency scaling"
6
7source "drivers/cpufreq/Kconfig"
8
9if CPU_FREQ
10
11comment "CPUFreq processor drivers"
12
13config X86_ACPI_CPUFREQ
14 tristate "ACPI Processor P-States driver"
15 select CPU_FREQ_TABLE
16 depends on ACPI_PROCESSOR
17 help
18 This driver adds a CPUFreq driver which utilizes the ACPI
19 Processor Performance States.
20
21 For details, take a look at <file:Documentation/cpu-freq/>.
22
23 If in doubt, say N.
24
25config ELAN_CPUFREQ
26 tristate "AMD Elan"
27 select CPU_FREQ_TABLE
28 depends on X86_ELAN
29 ---help---
30 This adds the CPUFreq driver for AMD Elan SC400 and SC410
31 processors.
32
33 You need to specify the processor maximum speed as boot
34 parameter: elanfreq=maxspeed (in kHz) or as module
35 parameter "max_freq".
36
37 For details, take a look at <file:Documentation/cpu-freq/>.
38
39 If in doubt, say N.
40
41config X86_POWERNOW_K6
42 tristate "AMD Mobile K6-2/K6-3 PowerNow!"
43 select CPU_FREQ_TABLE
44 help
45 This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
46 AMD K6-3+ processors.
47
48 For details, take a look at <file:Documentation/cpu-freq/>.
49
50 If in doubt, say N.
51
52config X86_POWERNOW_K7
53 tristate "AMD Mobile Athlon/Duron PowerNow!"
54 select CPU_FREQ_TABLE
55 help
56 This adds the CPUFreq driver for mobile AMD K7 mobile processors.
57
58 For details, take a look at <file:Documentation/cpu-freq/>.
59
60 If in doubt, say N.
61
62config X86_POWERNOW_K7_ACPI
63 bool
64 depends on X86_POWERNOW_K7 && ACPI_PROCESSOR
65 depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)
66 default y
67
68config X86_POWERNOW_K8
69 tristate "AMD Opteron/Athlon64 PowerNow!"
70 select CPU_FREQ_TABLE
71 depends on EXPERIMENTAL
72 help
73 This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
74
75 For details, take a look at <file:Documentation/cpu-freq/>.
76
77 If in doubt, say N.
78
79config X86_POWERNOW_K8_ACPI
80 bool
81 depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
82 depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
83 default y
84
85config X86_GX_SUSPMOD
86 tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
87 help
88 This add the CPUFreq driver for NatSemi Geode processors which
89 support suspend modulation.
90
91 For details, take a look at <file:Documentation/cpu-freq/>.
92
93 If in doubt, say N.
94
95config X86_SPEEDSTEP_CENTRINO
96 tristate "Intel Enhanced SpeedStep"
97 select CPU_FREQ_TABLE
98 select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
99 help
100 This adds the CPUFreq driver for Enhanced SpeedStep enabled
101 mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
102 you also need to say Y to "Use ACPI tables to decode..." below
103 [which might imply enabling ACPI] if you want to use this driver
104 on non-Banias CPUs.
105
106 For details, take a look at <file:Documentation/cpu-freq/>.
107
108 If in doubt, say N.
109
110config X86_SPEEDSTEP_CENTRINO_ACPI
111 bool "Use ACPI tables to decode valid frequency/voltage pairs"
112 depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
113 depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
114 default y
115 help
116 Use primarily the information provided in the BIOS ACPI tables
117 to determine valid CPU frequency and voltage pairings. It is
118 required for the driver to work on non-Banias CPUs.
119
120 If in doubt, say Y.
121
122config X86_SPEEDSTEP_CENTRINO_TABLE
123 bool "Built-in tables for Banias CPUs"
124 depends on X86_SPEEDSTEP_CENTRINO
125 default y
126 help
127 Use built-in tables for Banias CPUs if ACPI encoding
128 is not available.
129
130 If in doubt, say N.
131
132config X86_SPEEDSTEP_ICH
133 tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
134 select CPU_FREQ_TABLE
135 help
136 This adds the CPUFreq driver for certain mobile Intel Pentium III
137 (Coppermine), all mobile Intel Pentium III-M (Tualatin) and all
138 mobile Intel Pentium 4 P4-M on systems which have an Intel ICH2,
139 ICH3 or ICH4 southbridge.
140
141 For details, take a look at <file:Documentation/cpu-freq/>.
142
143 If in doubt, say N.
144
145config X86_SPEEDSTEP_SMI
146 tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
147 select CPU_FREQ_TABLE
148 depends on EXPERIMENTAL
149 help
150 This adds the CPUFreq driver for certain mobile Intel Pentium III
151 (Coppermine), all mobile Intel Pentium III-M (Tualatin)
152 on systems which have an Intel 440BX/ZX/MX southbridge.
153
154 For details, take a look at <file:Documentation/cpu-freq/>.
155
156 If in doubt, say N.
157
158config X86_P4_CLOCKMOD
159 tristate "Intel Pentium 4 clock modulation"
160 select CPU_FREQ_TABLE
161 help
162 This adds the CPUFreq driver for Intel Pentium 4 / XEON
163 processors.
164
165 For details, take a look at <file:Documentation/cpu-freq/>.
166
167 If in doubt, say N.
168
169config X86_CPUFREQ_NFORCE2
170 tristate "nVidia nForce2 FSB changing"
171 depends on EXPERIMENTAL
172 help
173 This adds the CPUFreq driver for FSB changing on nVidia nForce2
174 platforms.
175
176 For details, take a look at <file:Documentation/cpu-freq/>.
177
178 If in doubt, say N.
179
180config X86_LONGRUN
181 tristate "Transmeta LongRun"
182 help
183 This adds the CPUFreq driver for Transmeta Crusoe and Efficeon processors
184 which support LongRun.
185
186 For details, take a look at <file:Documentation/cpu-freq/>.
187
188 If in doubt, say N.
189
190config X86_LONGHAUL
191 tristate "VIA Cyrix III Longhaul"
192 select CPU_FREQ_TABLE
193 help
194 This adds the CPUFreq driver for VIA Samuel/CyrixIII,
195 VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
196 processors.
197
198 For details, take a look at <file:Documentation/cpu-freq/>.
199
200 If in doubt, say N.
201
202comment "shared options"
203
204config X86_ACPI_CPUFREQ_PROC_INTF
205 bool "/proc/acpi/processor/../performance interface (deprecated)"
206 depends on PROC_FS
207 depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
208 help
209 This enables the deprecated /proc/acpi/processor/../performance
210 interface. While it is helpful for debugging, the generic,
211 cross-architecture cpufreq interfaces should be used.
212
213 If in doubt, say N.
214
215config X86_SPEEDSTEP_LIB
216 tristate
217 default X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD
218
219config X86_SPEEDSTEP_RELAXED_CAP_CHECK
220 bool "Relaxed speedstep capability checks"
221 depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
222 help
223 Don't perform all checks for a speedstep capable system which would
224 normally be done. Some ancient or strange systems, though speedstep
225 capable, don't always indicate that they are speedstep capable. This
226 option lets the probing code bypass some of those checks if the
227 parameter "relaxed_check=1" is passed to the module.
228
229endif # CPU_FREQ
230
231endmenu
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
new file mode 100644
index 000000000000..a922e97aeedd
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -0,0 +1,14 @@
1obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
2obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
3obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
4obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
5obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
6obj-$(CONFIG_X86_LONGRUN) += longrun.o
7obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
8obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
9obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
10obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o
11obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o
12obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
13obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
14obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
new file mode 100644
index 000000000000..963e17aa205d
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -0,0 +1,537 @@
1/*
2 * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
26
27#include <linux/config.h>
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/cpufreq.h>
32#include <linux/proc_fs.h>
33#include <linux/seq_file.h>
34#include <asm/io.h>
35#include <asm/delay.h>
36#include <asm/uaccess.h>
37
38#include <linux/acpi.h>
39#include <acpi/processor.h>
40
41#include "speedstep-est-common.h"
42
43#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
44
45MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
46MODULE_DESCRIPTION("ACPI Processor P-States Driver");
47MODULE_LICENSE("GPL");
48
49
50struct cpufreq_acpi_io {
51 struct acpi_processor_performance acpi_data;
52 struct cpufreq_frequency_table *freq_table;
53 unsigned int resume;
54};
55
56static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
57
58static struct cpufreq_driver acpi_cpufreq_driver;
59
60static int
61acpi_processor_write_port(
62 u16 port,
63 u8 bit_width,
64 u32 value)
65{
66 if (bit_width <= 8) {
67 outb(value, port);
68 } else if (bit_width <= 16) {
69 outw(value, port);
70 } else if (bit_width <= 32) {
71 outl(value, port);
72 } else {
73 return -ENODEV;
74 }
75 return 0;
76}
77
78static int
79acpi_processor_read_port(
80 u16 port,
81 u8 bit_width,
82 u32 *ret)
83{
84 *ret = 0;
85 if (bit_width <= 8) {
86 *ret = inb(port);
87 } else if (bit_width <= 16) {
88 *ret = inw(port);
89 } else if (bit_width <= 32) {
90 *ret = inl(port);
91 } else {
92 return -ENODEV;
93 }
94 return 0;
95}
96
97static int
98acpi_processor_set_performance (
99 struct cpufreq_acpi_io *data,
100 unsigned int cpu,
101 int state)
102{
103 u16 port = 0;
104 u8 bit_width = 0;
105 int ret = 0;
106 u32 value = 0;
107 int i = 0;
108 struct cpufreq_freqs cpufreq_freqs;
109 cpumask_t saved_mask;
110 int retval;
111
112 dprintk("acpi_processor_set_performance\n");
113
114 /*
115 * TBD: Use something other than set_cpus_allowed.
116 * As set_cpus_allowed is a bit racy,
117 * with any other set_cpus_allowed for this process.
118 */
119 saved_mask = current->cpus_allowed;
120 set_cpus_allowed(current, cpumask_of_cpu(cpu));
121 if (smp_processor_id() != cpu) {
122 return (-EAGAIN);
123 }
124
125 if (state == data->acpi_data.state) {
126 if (unlikely(data->resume)) {
127 dprintk("Called after resume, resetting to P%d\n", state);
128 data->resume = 0;
129 } else {
130 dprintk("Already at target state (P%d)\n", state);
131 retval = 0;
132 goto migrate_end;
133 }
134 }
135
136 dprintk("Transitioning from P%d to P%d\n",
137 data->acpi_data.state, state);
138
139 /* cpufreq frequency struct */
140 cpufreq_freqs.cpu = cpu;
141 cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
142 cpufreq_freqs.new = data->freq_table[state].frequency;
143
144 /* notify cpufreq */
145 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
146
147 /*
148 * First we write the target state's 'control' value to the
149 * control_register.
150 */
151
152 port = data->acpi_data.control_register.address;
153 bit_width = data->acpi_data.control_register.bit_width;
154 value = (u32) data->acpi_data.states[state].control;
155
156 dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
157
158 ret = acpi_processor_write_port(port, bit_width, value);
159 if (ret) {
160 dprintk("Invalid port width 0x%04x\n", bit_width);
161 retval = ret;
162 goto migrate_end;
163 }
164
165 /*
166 * Then we read the 'status_register' and compare the value with the
167 * target state's 'status' to make sure the transition was successful.
168 * Note that we'll poll for up to 1ms (100 cycles of 10us) before
169 * giving up.
170 */
171
172 port = data->acpi_data.status_register.address;
173 bit_width = data->acpi_data.status_register.bit_width;
174
175 dprintk("Looking for 0x%08x from port 0x%04x\n",
176 (u32) data->acpi_data.states[state].status, port);
177
178 for (i=0; i<100; i++) {
179 ret = acpi_processor_read_port(port, bit_width, &value);
180 if (ret) {
181 dprintk("Invalid port width 0x%04x\n", bit_width);
182 retval = ret;
183 goto migrate_end;
184 }
185 if (value == (u32) data->acpi_data.states[state].status)
186 break;
187 udelay(10);
188 }
189
190 /* notify cpufreq */
191 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
192
193 if (value != (u32) data->acpi_data.states[state].status) {
194 unsigned int tmp = cpufreq_freqs.new;
195 cpufreq_freqs.new = cpufreq_freqs.old;
196 cpufreq_freqs.old = tmp;
197 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
198 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
199 printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
200 retval = -ENODEV;
201 goto migrate_end;
202 }
203
204 dprintk("Transition successful after %d microseconds\n", i * 10);
205
206 data->acpi_data.state = state;
207
208 retval = 0;
209migrate_end:
210 set_cpus_allowed(current, saved_mask);
211 return (retval);
212}
213
214
215static int
216acpi_cpufreq_target (
217 struct cpufreq_policy *policy,
218 unsigned int target_freq,
219 unsigned int relation)
220{
221 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
222 unsigned int next_state = 0;
223 unsigned int result = 0;
224
225 dprintk("acpi_cpufreq_setpolicy\n");
226
227 result = cpufreq_frequency_table_target(policy,
228 data->freq_table,
229 target_freq,
230 relation,
231 &next_state);
232 if (result)
233 return (result);
234
235 result = acpi_processor_set_performance (data, policy->cpu, next_state);
236
237 return (result);
238}
239
240
241static int
242acpi_cpufreq_verify (
243 struct cpufreq_policy *policy)
244{
245 unsigned int result = 0;
246 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
247
248 dprintk("acpi_cpufreq_verify\n");
249
250 result = cpufreq_frequency_table_verify(policy,
251 data->freq_table);
252
253 return (result);
254}
255
256
257static unsigned long
258acpi_cpufreq_guess_freq (
259 struct cpufreq_acpi_io *data,
260 unsigned int cpu)
261{
262 if (cpu_khz) {
263 /* search the closest match to cpu_khz */
264 unsigned int i;
265 unsigned long freq;
266 unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
267
268 for (i=0; i < (data->acpi_data.state_count - 1); i++) {
269 freq = freqn;
270 freqn = data->acpi_data.states[i+1].core_frequency * 1000;
271 if ((2 * cpu_khz) > (freqn + freq)) {
272 data->acpi_data.state = i;
273 return (freq);
274 }
275 }
276 data->acpi_data.state = data->acpi_data.state_count - 1;
277 return (freqn);
278 } else
279 /* assume CPU is at P0... */
280 data->acpi_data.state = 0;
281 return data->acpi_data.states[0].core_frequency * 1000;
282
283}
284
285
286/*
287 * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
288 * of this driver
289 * @perf: processor-specific acpi_io_data struct
290 * @cpu: CPU being initialized
291 *
292 * To avoid issues with legacy OSes, some BIOSes require to be informed of
293 * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
294 * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
295 * driver/acpi/processor.c
296 */
297static void
298acpi_processor_cpu_init_pdc_est(
299 struct acpi_processor_performance *perf,
300 unsigned int cpu,
301 struct acpi_object_list *obj_list
302 )
303{
304 union acpi_object *obj;
305 u32 *buf;
306 struct cpuinfo_x86 *c = cpu_data + cpu;
307 dprintk("acpi_processor_cpu_init_pdc_est\n");
308
309 if (!cpu_has(c, X86_FEATURE_EST))
310 return;
311
312 /* Initialize pdc. It will be used later. */
313 if (!obj_list)
314 return;
315
316 if (!(obj_list->count && obj_list->pointer))
317 return;
318
319 obj = obj_list->pointer;
320 if ((obj->buffer.length == 12) && obj->buffer.pointer) {
321 buf = (u32 *)obj->buffer.pointer;
322 buf[0] = ACPI_PDC_REVISION_ID;
323 buf[1] = 1;
324 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
325 perf->pdc = obj_list;
326 }
327 return;
328}
329
330
331/* CPU specific PDC initialization */
332static void
333acpi_processor_cpu_init_pdc(
334 struct acpi_processor_performance *perf,
335 unsigned int cpu,
336 struct acpi_object_list *obj_list
337 )
338{
339 struct cpuinfo_x86 *c = cpu_data + cpu;
340 dprintk("acpi_processor_cpu_init_pdc\n");
341 perf->pdc = NULL;
342 if (cpu_has(c, X86_FEATURE_EST))
343 acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
344 return;
345}
346
347
348static int
349acpi_cpufreq_cpu_init (
350 struct cpufreq_policy *policy)
351{
352 unsigned int i;
353 unsigned int cpu = policy->cpu;
354 struct cpufreq_acpi_io *data;
355 unsigned int result = 0;
356
357 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
358 u32 arg0_buf[3];
359 struct acpi_object_list arg_list = {1, &arg0};
360
361 dprintk("acpi_cpufreq_cpu_init\n");
362 /* setup arg_list for _PDC settings */
363 arg0.buffer.length = 12;
364 arg0.buffer.pointer = (u8 *) arg0_buf;
365
366 data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
367 if (!data)
368 return (-ENOMEM);
369 memset(data, 0, sizeof(struct cpufreq_acpi_io));
370
371 acpi_io_data[cpu] = data;
372
373 acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
374 result = acpi_processor_register_performance(&data->acpi_data, cpu);
375 data->acpi_data.pdc = NULL;
376
377 if (result)
378 goto err_free;
379
380 if (is_const_loops_cpu(cpu)) {
381 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
382 }
383
384 /* capability check */
385 if (data->acpi_data.state_count <= 1) {
386 dprintk("No P-States\n");
387 result = -ENODEV;
388 goto err_unreg;
389 }
390 if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
391 (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
392 dprintk("Unsupported address space [%d, %d]\n",
393 (u32) (data->acpi_data.control_register.space_id),
394 (u32) (data->acpi_data.status_register.space_id));
395 result = -ENODEV;
396 goto err_unreg;
397 }
398
399 /* alloc freq_table */
400 data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL);
401 if (!data->freq_table) {
402 result = -ENOMEM;
403 goto err_unreg;
404 }
405
406 /* detect transition latency */
407 policy->cpuinfo.transition_latency = 0;
408 for (i=0; i<data->acpi_data.state_count; i++) {
409 if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
410 policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
411 }
412 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
413
414 /* The current speed is unknown and not detectable by ACPI... */
415 policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
416
417 /* table init */
418 for (i=0; i<=data->acpi_data.state_count; i++)
419 {
420 data->freq_table[i].index = i;
421 if (i<data->acpi_data.state_count)
422 data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
423 else
424 data->freq_table[i].frequency = CPUFREQ_TABLE_END;
425 }
426
427 result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
428 if (result) {
429 goto err_freqfree;
430 }
431
432 /* notify BIOS that we exist */
433 acpi_processor_notify_smm(THIS_MODULE);
434
435 printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
436 cpu);
437 for (i = 0; i < data->acpi_data.state_count; i++)
438 dprintk(" %cP%d: %d MHz, %d mW, %d uS\n",
439 (i == data->acpi_data.state?'*':' '), i,
440 (u32) data->acpi_data.states[i].core_frequency,
441 (u32) data->acpi_data.states[i].power,
442 (u32) data->acpi_data.states[i].transition_latency);
443
444 cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
445 return (result);
446
447 err_freqfree:
448 kfree(data->freq_table);
449 err_unreg:
450 acpi_processor_unregister_performance(&data->acpi_data, cpu);
451 err_free:
452 kfree(data);
453 acpi_io_data[cpu] = NULL;
454
455 return (result);
456}
457
458
459static int
460acpi_cpufreq_cpu_exit (
461 struct cpufreq_policy *policy)
462{
463 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
464
465
466 dprintk("acpi_cpufreq_cpu_exit\n");
467
468 if (data) {
469 cpufreq_frequency_table_put_attr(policy->cpu);
470 acpi_io_data[policy->cpu] = NULL;
471 acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
472 kfree(data);
473 }
474
475 return (0);
476}
477
478static int
479acpi_cpufreq_resume (
480 struct cpufreq_policy *policy)
481{
482 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
483
484
485 dprintk("acpi_cpufreq_resume\n");
486
487 data->resume = 1;
488
489 return (0);
490}
491
492
493static struct freq_attr* acpi_cpufreq_attr[] = {
494 &cpufreq_freq_attr_scaling_available_freqs,
495 NULL,
496};
497
498static struct cpufreq_driver acpi_cpufreq_driver = {
499 .verify = acpi_cpufreq_verify,
500 .target = acpi_cpufreq_target,
501 .init = acpi_cpufreq_cpu_init,
502 .exit = acpi_cpufreq_cpu_exit,
503 .resume = acpi_cpufreq_resume,
504 .name = "acpi-cpufreq",
505 .owner = THIS_MODULE,
506 .attr = acpi_cpufreq_attr,
507};
508
509
510static int __init
511acpi_cpufreq_init (void)
512{
513 int result = 0;
514
515 dprintk("acpi_cpufreq_init\n");
516
517 result = cpufreq_register_driver(&acpi_cpufreq_driver);
518
519 return (result);
520}
521
522
523static void __exit
524acpi_cpufreq_exit (void)
525{
526 dprintk("acpi_cpufreq_exit\n");
527
528 cpufreq_unregister_driver(&acpi_cpufreq_driver);
529
530 return;
531}
532
533
534late_initcall(acpi_cpufreq_init);
535module_exit(acpi_cpufreq_exit);
536
537MODULE_ALIAS("acpi");
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
new file mode 100644
index 000000000000..04a405345203
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -0,0 +1,457 @@
1/*
2 * (C) 2004 Sebastian Witt <se.witt@gmx.net>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 * Based upon reverse engineered information
6 *
7 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/init.h>
14#include <linux/cpufreq.h>
15#include <linux/pci.h>
16#include <linux/delay.h>
17
18#define NFORCE2_XTAL 25
19#define NFORCE2_BOOTFSB 0x48
20#define NFORCE2_PLLENABLE 0xa8
21#define NFORCE2_PLLREG 0xa4
22#define NFORCE2_PLLADR 0xa0
23#define NFORCE2_PLL(mul, div) (0x100000 | (mul << 8) | div)
24
25#define NFORCE2_MIN_FSB 50
26#define NFORCE2_SAFE_DISTANCE 50
27
28/* Delay in ms between FSB changes */
29//#define NFORCE2_DELAY 10
30
31/* nforce2_chipset:
32 * FSB is changed using the chipset
33 */
34static struct pci_dev *nforce2_chipset_dev;
35
36/* fid:
37 * multiplier * 10
38 */
39static int fid = 0;
40
41/* min_fsb, max_fsb:
42 * minimum and maximum FSB (= FSB at boot time)
43 */
44static int min_fsb = 0;
45static int max_fsb = 0;
46
47MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
48MODULE_DESCRIPTION("nForce2 FSB changing cpufreq driver");
49MODULE_LICENSE("GPL");
50
51module_param(fid, int, 0444);
52module_param(min_fsb, int, 0444);
53
54MODULE_PARM_DESC(fid, "CPU multiplier to use (11.5 = 115)");
55MODULE_PARM_DESC(min_fsb,
56 "Minimum FSB to use, if not defined: current FSB - 50");
57
58#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "cpufreq-nforce2", msg)
59
60/*
61 * nforce2_calc_fsb - calculate FSB
62 * @pll: PLL value
63 *
64 * Calculates FSB from PLL value
65 */
66static int nforce2_calc_fsb(int pll)
67{
68 unsigned char mul, div;
69
70 mul = (pll >> 8) & 0xff;
71 div = pll & 0xff;
72
73 if (div > 0)
74 return NFORCE2_XTAL * mul / div;
75
76 return 0;
77}
78
79/*
80 * nforce2_calc_pll - calculate PLL value
81 * @fsb: FSB
82 *
83 * Calculate PLL value for given FSB
84 */
85static int nforce2_calc_pll(unsigned int fsb)
86{
87 unsigned char xmul, xdiv;
88 unsigned char mul = 0, div = 0;
89 int tried = 0;
90
91 /* Try to calculate multiplier and divider up to 4 times */
92 while (((mul == 0) || (div == 0)) && (tried <= 3)) {
93 for (xdiv = 1; xdiv <= 0x80; xdiv++)
94 for (xmul = 1; xmul <= 0xfe; xmul++)
95 if (nforce2_calc_fsb(NFORCE2_PLL(xmul, xdiv)) ==
96 fsb + tried) {
97 mul = xmul;
98 div = xdiv;
99 }
100 tried++;
101 }
102
103 if ((mul == 0) || (div == 0))
104 return -1;
105
106 return NFORCE2_PLL(mul, div);
107}
108
109/*
110 * nforce2_write_pll - write PLL value to chipset
111 * @pll: PLL value
112 *
113 * Writes new FSB PLL value to chipset
114 */
115static void nforce2_write_pll(int pll)
116{
117 int temp;
118
119 /* Set the pll addr. to 0x00 */
120 temp = 0x00;
121 pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, temp);
122
123 /* Now write the value in all 64 registers */
124 for (temp = 0; temp <= 0x3f; temp++) {
125 pci_write_config_dword(nforce2_chipset_dev,
126 NFORCE2_PLLREG, pll);
127 }
128
129 return;
130}
131
132/*
133 * nforce2_fsb_read - Read FSB
134 *
135 * Read FSB from chipset
136 * If bootfsb != 0, return FSB at boot-time
137 */
138static unsigned int nforce2_fsb_read(int bootfsb)
139{
140 struct pci_dev *nforce2_sub5;
141 u32 fsb, temp = 0;
142
143
144 /* Get chipset boot FSB from subdevice 5 (FSB at boot-time) */
145 nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
146 0x01EF,
147 PCI_ANY_ID,
148 PCI_ANY_ID,
149 NULL);
150
151 if (!nforce2_sub5)
152 return 0;
153
154 pci_read_config_dword(nforce2_sub5, NFORCE2_BOOTFSB, &fsb);
155 fsb /= 1000000;
156
157 /* Check if PLL register is already set */
158 pci_read_config_byte(nforce2_chipset_dev,
159 NFORCE2_PLLENABLE, (u8 *)&temp);
160
161 if(bootfsb || !temp)
162 return fsb;
163
164 /* Use PLL register FSB value */
165 pci_read_config_dword(nforce2_chipset_dev,
166 NFORCE2_PLLREG, &temp);
167 fsb = nforce2_calc_fsb(temp);
168
169 return fsb;
170}
171
172/*
173 * nforce2_set_fsb - set new FSB
174 * @fsb: New FSB
175 *
176 * Sets new FSB
177 */
178static int nforce2_set_fsb(unsigned int fsb)
179{
180 u32 pll, temp = 0;
181 unsigned int tfsb;
182 int diff;
183
184 if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
185 printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
186 return -EINVAL;
187 }
188
189 tfsb = nforce2_fsb_read(0);
190 if (!tfsb) {
191 printk(KERN_ERR "cpufreq: Error while reading the FSB\n");
192 return -EINVAL;
193 }
194
195 /* First write? Then set actual value */
196 pci_read_config_byte(nforce2_chipset_dev,
197 NFORCE2_PLLENABLE, (u8 *)&temp);
198 if (!temp) {
199 pll = nforce2_calc_pll(tfsb);
200
201 if (pll < 0)
202 return -EINVAL;
203
204 nforce2_write_pll(pll);
205 }
206
207 /* Enable write access */
208 temp = 0x01;
209 pci_write_config_byte(nforce2_chipset_dev, NFORCE2_PLLENABLE, (u8)temp);
210
211 diff = tfsb - fsb;
212
213 if (!diff)
214 return 0;
215
216 while ((tfsb != fsb) && (tfsb <= max_fsb) && (tfsb >= min_fsb)) {
217 if (diff < 0)
218 tfsb++;
219 else
220 tfsb--;
221
222 /* Calculate the PLL reg. value */
223 if ((pll = nforce2_calc_pll(tfsb)) == -1)
224 return -EINVAL;
225
226 nforce2_write_pll(pll);
227#ifdef NFORCE2_DELAY
228 mdelay(NFORCE2_DELAY);
229#endif
230 }
231
232 temp = 0x40;
233 pci_write_config_byte(nforce2_chipset_dev, NFORCE2_PLLADR, (u8)temp);
234
235 return 0;
236}
237
238/**
239 * nforce2_get - get the CPU frequency
240 * @cpu: CPU number
241 *
242 * Returns the CPU frequency
243 */
244static unsigned int nforce2_get(unsigned int cpu)
245{
246 if (cpu)
247 return 0;
248 return nforce2_fsb_read(0) * fid * 100;
249}
250
251/**
252 * nforce2_target - set a new CPUFreq policy
253 * @policy: new policy
254 * @target_freq: the target frequency
255 * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
256 *
257 * Sets a new CPUFreq policy.
258 */
259static int nforce2_target(struct cpufreq_policy *policy,
260 unsigned int target_freq, unsigned int relation)
261{
262// unsigned long flags;
263 struct cpufreq_freqs freqs;
264 unsigned int target_fsb;
265
266 if ((target_freq > policy->max) || (target_freq < policy->min))
267 return -EINVAL;
268
269 target_fsb = target_freq / (fid * 100);
270
271 freqs.old = nforce2_get(policy->cpu);
272 freqs.new = target_fsb * fid * 100;
273 freqs.cpu = 0; /* Only one CPU on nForce2 plattforms */
274
275 if (freqs.old == freqs.new)
276 return 0;
277
278 dprintk(KERN_INFO "cpufreq: Old CPU frequency %d kHz, new %d kHz\n",
279 freqs.old, freqs.new);
280
281 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
282
283 /* Disable IRQs */
284 //local_irq_save(flags);
285
286 if (nforce2_set_fsb(target_fsb) < 0)
287 printk(KERN_ERR "cpufreq: Changing FSB to %d failed\n",
288 target_fsb);
289 else
290 dprintk(KERN_INFO "cpufreq: Changed FSB successfully to %d\n",
291 target_fsb);
292
293 /* Enable IRQs */
294 //local_irq_restore(flags);
295
296 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
297
298 return 0;
299}
300
301/**
302 * nforce2_verify - verifies a new CPUFreq policy
303 * @policy: new policy
304 */
305static int nforce2_verify(struct cpufreq_policy *policy)
306{
307 unsigned int fsb_pol_max;
308
309 fsb_pol_max = policy->max / (fid * 100);
310
311 if (policy->min < (fsb_pol_max * fid * 100))
312 policy->max = (fsb_pol_max + 1) * fid * 100;
313
314 cpufreq_verify_within_limits(policy,
315 policy->cpuinfo.min_freq,
316 policy->cpuinfo.max_freq);
317 return 0;
318}
319
320static int nforce2_cpu_init(struct cpufreq_policy *policy)
321{
322 unsigned int fsb;
323 unsigned int rfid;
324
325 /* capability check */
326 if (policy->cpu != 0)
327 return -ENODEV;
328
329 /* Get current FSB */
330 fsb = nforce2_fsb_read(0);
331
332 if (!fsb)
333 return -EIO;
334
335 /* FIX: Get FID from CPU */
336 if (!fid) {
337 if (!cpu_khz) {
338 printk(KERN_WARNING
339 "cpufreq: cpu_khz not set, can't calculate multiplier!\n");
340 return -ENODEV;
341 }
342
343 fid = cpu_khz / (fsb * 100);
344 rfid = fid % 5;
345
346 if (rfid) {
347 if (rfid > 2)
348 fid += 5 - rfid;
349 else
350 fid -= rfid;
351 }
352 }
353
354 printk(KERN_INFO "cpufreq: FSB currently at %i MHz, FID %d.%d\n", fsb,
355 fid / 10, fid % 10);
356
357 /* Set maximum FSB to FSB at boot time */
358 max_fsb = nforce2_fsb_read(1);
359
360 if(!max_fsb)
361 return -EIO;
362
363 if (!min_fsb)
364 min_fsb = max_fsb - NFORCE2_SAFE_DISTANCE;
365
366 if (min_fsb < NFORCE2_MIN_FSB)
367 min_fsb = NFORCE2_MIN_FSB;
368
369 /* cpuinfo and default policy values */
370 policy->cpuinfo.min_freq = min_fsb * fid * 100;
371 policy->cpuinfo.max_freq = max_fsb * fid * 100;
372 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
373 policy->cur = nforce2_get(policy->cpu);
374 policy->min = policy->cpuinfo.min_freq;
375 policy->max = policy->cpuinfo.max_freq;
376 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
377
378 return 0;
379}
380
381static int nforce2_cpu_exit(struct cpufreq_policy *policy)
382{
383 return 0;
384}
385
386static struct cpufreq_driver nforce2_driver = {
387 .name = "nforce2",
388 .verify = nforce2_verify,
389 .target = nforce2_target,
390 .get = nforce2_get,
391 .init = nforce2_cpu_init,
392 .exit = nforce2_cpu_exit,
393 .owner = THIS_MODULE,
394};
395
396/**
397 * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic
398 *
399 * Detects nForce2 A2 and C1 stepping
400 *
401 */
402static unsigned int nforce2_detect_chipset(void)
403{
404 u8 revision;
405
406 nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
407 PCI_DEVICE_ID_NVIDIA_NFORCE2,
408 PCI_ANY_ID,
409 PCI_ANY_ID,
410 NULL);
411
412 if (nforce2_chipset_dev == NULL)
413 return -ENODEV;
414
415 pci_read_config_byte(nforce2_chipset_dev, PCI_REVISION_ID, &revision);
416
417 printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n",
418 revision);
419 printk(KERN_INFO
420 "cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n");
421
422 return 0;
423}
424
425/**
426 * nforce2_init - initializes the nForce2 CPUFreq driver
427 *
428 * Initializes the nForce2 FSB support. Returns -ENODEV on unsupported
429 * devices, -EINVAL on problems during initiatization, and zero on
430 * success.
431 */
432static int __init nforce2_init(void)
433{
434 /* TODO: do we need to detect the processor? */
435
436 /* detect chipset */
437 if (nforce2_detect_chipset()) {
438 printk(KERN_ERR "cpufreq: No nForce2 chipset.\n");
439 return -ENODEV;
440 }
441
442 return cpufreq_register_driver(&nforce2_driver);
443}
444
445/**
446 * nforce2_exit - unregisters cpufreq module
447 *
448 * Unregisters nForce2 FSB change support.
449 */
450static void __exit nforce2_exit(void)
451{
452 cpufreq_unregister_driver(&nforce2_driver);
453}
454
455module_init(nforce2_init);
456module_exit(nforce2_exit);
457
diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
new file mode 100644
index 000000000000..3f7caa4ae6d6
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
@@ -0,0 +1,312 @@
1/*
2 * elanfreq: cpufreq driver for the AMD ELAN family
3 *
4 * (c) Copyright 2002 Robert Schwebel <r.schwebel@pengutronix.de>
5 *
6 * Parts of this code are (c) Sven Geggus <sven@geggus.net>
7 *
8 * All Rights Reserved.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 *
15 * 2002-02-13: - initial revision for 2.4.18-pre9 by Robert Schwebel
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/init.h>
22
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <linux/cpufreq.h>
26
27#include <asm/msr.h>
28#include <asm/timex.h>
29#include <asm/io.h>
30
31#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
32#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */
33
34/* Module parameter */
35static int max_freq;
36
37struct s_elan_multiplier {
38 int clock; /* frequency in kHz */
39 int val40h; /* PMU Force Mode register */
40 int val80h; /* CPU Clock Speed Register */
41};
42
43/*
44 * It is important that the frequencies
45 * are listed in ascending order here!
46 */
47struct s_elan_multiplier elan_multiplier[] = {
48 {1000, 0x02, 0x18},
49 {2000, 0x02, 0x10},
50 {4000, 0x02, 0x08},
51 {8000, 0x00, 0x00},
52 {16000, 0x00, 0x02},
53 {33000, 0x00, 0x04},
54 {66000, 0x01, 0x04},
55 {99000, 0x01, 0x05}
56};
57
58static struct cpufreq_frequency_table elanfreq_table[] = {
59 {0, 1000},
60 {1, 2000},
61 {2, 4000},
62 {3, 8000},
63 {4, 16000},
64 {5, 33000},
65 {6, 66000},
66 {7, 99000},
67 {0, CPUFREQ_TABLE_END},
68};
69
70
71/**
72 * elanfreq_get_cpu_frequency: determine current cpu speed
73 *
74 * Finds out at which frequency the CPU of the Elan SOC runs
75 * at the moment. Frequencies from 1 to 33 MHz are generated
76 * the normal way, 66 and 99 MHz are called "Hyperspeed Mode"
77 * and have the rest of the chip running with 33 MHz.
78 */
79
80static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
81{
82 u8 clockspeed_reg; /* Clock Speed Register */
83
84 local_irq_disable();
85 outb_p(0x80,REG_CSCIR);
86 clockspeed_reg = inb_p(REG_CSCDR);
87 local_irq_enable();
88
89 if ((clockspeed_reg & 0xE0) == 0xE0) { return 0; }
90
91 /* Are we in CPU clock multiplied mode (66/99 MHz)? */
92 if ((clockspeed_reg & 0xE0) == 0xC0) {
93 if ((clockspeed_reg & 0x01) == 0) {
94 return 66000;
95 } else {
96 return 99000;
97 }
98 }
99
100 /* 33 MHz is not 32 MHz... */
101 if ((clockspeed_reg & 0xE0)==0xA0)
102 return 33000;
103
104 return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000);
105}
106
107
108/**
109 * elanfreq_set_cpu_frequency: Change the CPU core frequency
110 * @cpu: cpu number
111 * @freq: frequency in kHz
112 *
113 * This function takes a frequency value and changes the CPU frequency
114 * according to this. Note that the frequency has to be checked by
115 * elanfreq_validatespeed() for correctness!
116 *
117 * There is no return value.
118 */
119
120static void elanfreq_set_cpu_state (unsigned int state) {
121
122 struct cpufreq_freqs freqs;
123
124 freqs.old = elanfreq_get_cpu_frequency(0);
125 freqs.new = elan_multiplier[state].clock;
126 freqs.cpu = 0; /* elanfreq.c is UP only driver */
127
128 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
129
130 printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",elan_multiplier[state].clock);
131
132
133 /*
134 * Access to the Elan's internal registers is indexed via
135 * 0x22: Chip Setup & Control Register Index Register (CSCI)
136 * 0x23: Chip Setup & Control Register Data Register (CSCD)
137 *
138 */
139
140 /*
141 * 0x40 is the Power Management Unit's Force Mode Register.
142 * Bit 6 enables Hyperspeed Mode (66/100 MHz core frequency)
143 */
144
145 local_irq_disable();
146 outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */
147 outb_p(0x00,REG_CSCDR);
148 local_irq_enable(); /* wait till internal pipelines and */
149 udelay(1000); /* buffers have cleaned up */
150
151 local_irq_disable();
152
153 /* now, set the CPU clock speed register (0x80) */
154 outb_p(0x80,REG_CSCIR);
155 outb_p(elan_multiplier[state].val80h,REG_CSCDR);
156
157 /* now, the hyperspeed bit in PMU Force Mode Register (0x40) */
158 outb_p(0x40,REG_CSCIR);
159 outb_p(elan_multiplier[state].val40h,REG_CSCDR);
160 udelay(10000);
161 local_irq_enable();
162
163 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
164};
165
166
167/**
168 * elanfreq_validatespeed: test if frequency range is valid
169 * @policy: the policy to validate
170 *
171 * This function checks if a given frequency range in kHz is valid
172 * for the hardware supported by the driver.
173 */
174
175static int elanfreq_verify (struct cpufreq_policy *policy)
176{
177 return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
178}
179
180static int elanfreq_target (struct cpufreq_policy *policy,
181 unsigned int target_freq,
182 unsigned int relation)
183{
184 unsigned int newstate = 0;
185
186 if (cpufreq_frequency_table_target(policy, &elanfreq_table[0], target_freq, relation, &newstate))
187 return -EINVAL;
188
189 elanfreq_set_cpu_state(newstate);
190
191 return 0;
192}
193
194
195/*
196 * Module init and exit code
197 */
198
199static int elanfreq_cpu_init(struct cpufreq_policy *policy)
200{
201 struct cpuinfo_x86 *c = cpu_data;
202 unsigned int i;
203 int result;
204
205 /* capability check */
206 if ((c->x86_vendor != X86_VENDOR_AMD) ||
207 (c->x86 != 4) || (c->x86_model!=10))
208 return -ENODEV;
209
210 /* max freq */
211 if (!max_freq)
212 max_freq = elanfreq_get_cpu_frequency(0);
213
214 /* table init */
215 for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
216 if (elanfreq_table[i].frequency > max_freq)
217 elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
218 }
219
220 /* cpuinfo and default policy values */
221 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
222 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
223 policy->cur = elanfreq_get_cpu_frequency(0);
224
225 result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
226 if (result)
227 return (result);
228
229 cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
230
231 return 0;
232}
233
234
235static int elanfreq_cpu_exit(struct cpufreq_policy *policy)
236{
237 cpufreq_frequency_table_put_attr(policy->cpu);
238 return 0;
239}
240
241
242#ifndef MODULE
243/**
244 * elanfreq_setup - elanfreq command line parameter parsing
245 *
246 * elanfreq command line parameter. Use:
247 * elanfreq=66000
248 * to set the maximum CPU frequency to 66 MHz. Note that in
249 * case you do not give this boot parameter, the maximum
250 * frequency will fall back to _current_ CPU frequency which
251 * might be lower. If you build this as a module, use the
252 * max_freq module parameter instead.
253 */
254static int __init elanfreq_setup(char *str)
255{
256 max_freq = simple_strtoul(str, &str, 0);
257 printk(KERN_WARNING "You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n");
258 return 1;
259}
260__setup("elanfreq=", elanfreq_setup);
261#endif
262
263
264static struct freq_attr* elanfreq_attr[] = {
265 &cpufreq_freq_attr_scaling_available_freqs,
266 NULL,
267};
268
269
270static struct cpufreq_driver elanfreq_driver = {
271 .get = elanfreq_get_cpu_frequency,
272 .verify = elanfreq_verify,
273 .target = elanfreq_target,
274 .init = elanfreq_cpu_init,
275 .exit = elanfreq_cpu_exit,
276 .name = "elanfreq",
277 .owner = THIS_MODULE,
278 .attr = elanfreq_attr,
279};
280
281
282static int __init elanfreq_init(void)
283{
284 struct cpuinfo_x86 *c = cpu_data;
285
286 /* Test if we have the right hardware */
287 if ((c->x86_vendor != X86_VENDOR_AMD) ||
288 (c->x86 != 4) || (c->x86_model!=10))
289 {
290 printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
291 return -ENODEV;
292 }
293
294 return cpufreq_register_driver(&elanfreq_driver);
295}
296
297
298static void __exit elanfreq_exit(void)
299{
300 cpufreq_unregister_driver(&elanfreq_driver);
301}
302
303
304module_param (max_freq, int, 0444);
305
306MODULE_LICENSE("GPL");
307MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
308MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs");
309
310module_init(elanfreq_init);
311module_exit(elanfreq_exit);
312
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
new file mode 100644
index 000000000000..1a49adb1f4a6
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -0,0 +1,502 @@
1/*
2 * Cyrix MediaGX and NatSemi Geode Suspend Modulation
3 * (C) 2002 Zwane Mwaikambo <zwane@commfireservices.com>
4 * (C) 2002 Hiroshi Miura <miura@da-cha.org>
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation
10 *
11 * The author(s) of this software shall not be held liable for damages
12 * of any nature resulting due to the use of this software. This
13 * software is provided AS-IS with no warranties.
14 *
15 * Theoritical note:
16 *
17 * (see Geode(tm) CS5530 manual (rev.4.1) page.56)
18 *
19 * CPU frequency control on NatSemi Geode GX1/GXLV processor and CS55x0
20 * are based on Suspend Moduration.
21 *
22 * Suspend Modulation works by asserting and de-asserting the SUSP# pin
23 * to CPU(GX1/GXLV) for configurable durations. When asserting SUSP#
24 * the CPU enters an idle state. GX1 stops its core clock when SUSP# is
25 * asserted then power consumption is reduced.
26 *
27 * Suspend Modulation's OFF/ON duration are configurable
28 * with 'Suspend Modulation OFF Count Register'
29 * and 'Suspend Modulation ON Count Register'.
30 * These registers are 8bit counters that represent the number of
31 * 32us intervals which the SUSP# pin is asserted(ON)/de-asserted(OFF)
32 * to the processor.
33 *
34 * These counters define a ratio which is the effective frequency
35 * of operation of the system.
36 *
37 * OFF Count
38 * F_eff = Fgx * ----------------------
39 * OFF Count + ON Count
40 *
41 * 0 <= On Count, Off Count <= 255
42 *
43 * From these limits, we can get register values
44 *
45 * off_duration + on_duration <= MAX_DURATION
46 * on_duration = off_duration * (stock_freq - freq) / freq
47 *
48 * off_duration = (freq * DURATION) / stock_freq
49 * on_duration = DURATION - off_duration
50 *
51 *
52 *---------------------------------------------------------------------------
53 *
54 * ChangeLog:
55 * Dec. 12, 2003 Hiroshi Miura <miura@da-cha.org>
56 * - fix on/off register mistake
57 * - fix cpu_khz calc when it stops cpu modulation.
58 *
59 * Dec. 11, 2002 Hiroshi Miura <miura@da-cha.org>
60 * - rewrite for Cyrix MediaGX Cx5510/5520 and
61 * NatSemi Geode Cs5530(A).
62 *
63 * Jul. ??, 2002 Zwane Mwaikambo <zwane@commfireservices.com>
64 * - cs5530_mod patch for 2.4.19-rc1.
65 *
66 *---------------------------------------------------------------------------
67 *
68 * Todo
69 * Test on machines with 5510, 5530, 5530A
70 */
71
72/************************************************************************
73 * Suspend Modulation - Definitions *
74 ************************************************************************/
75
76#include <linux/kernel.h>
77#include <linux/module.h>
78#include <linux/init.h>
79#include <linux/smp.h>
80#include <linux/cpufreq.h>
81#include <linux/pci.h>
82#include <asm/processor.h>
83#include <asm/errno.h>
84
85/* PCI config registers, all at F0 */
86#define PCI_PMER1 0x80 /* power management enable register 1 */
87#define PCI_PMER2 0x81 /* power management enable register 2 */
88#define PCI_PMER3 0x82 /* power management enable register 3 */
89#define PCI_IRQTC 0x8c /* irq speedup timer counter register:typical 2 to 4ms */
90#define PCI_VIDTC 0x8d /* video speedup timer counter register: typical 50 to 100ms */
91#define PCI_MODOFF 0x94 /* suspend modulation OFF counter register, 1 = 32us */
92#define PCI_MODON 0x95 /* suspend modulation ON counter register */
93#define PCI_SUSCFG 0x96 /* suspend configuration register */
94
95/* PMER1 bits */
96#define GPM (1<<0) /* global power management */
97#define GIT (1<<1) /* globally enable PM device idle timers */
98#define GTR (1<<2) /* globally enable IO traps */
99#define IRQ_SPDUP (1<<3) /* disable clock throttle during interrupt handling */
100#define VID_SPDUP (1<<4) /* disable clock throttle during vga video handling */
101
102/* SUSCFG bits */
103#define SUSMOD (1<<0) /* enable/disable suspend modulation */
104/* the belows support only with cs5530 (after rev.1.2)/cs5530A */
105#define SMISPDUP (1<<1) /* select how SMI re-enable suspend modulation: */
106 /* IRQTC timer or read SMI speedup disable reg.(F1BAR[08-09h]) */
107#define SUSCFG (1<<2) /* enable powering down a GXLV processor. "Special 3Volt Suspend" mode */
108/* the belows support only with cs5530A */
109#define PWRSVE_ISA (1<<3) /* stop ISA clock */
110#define PWRSVE (1<<4) /* active idle */
111
112struct gxfreq_params {
113 u8 on_duration;
114 u8 off_duration;
115 u8 pci_suscfg;
116 u8 pci_pmer1;
117 u8 pci_pmer2;
118 u8 pci_rev;
119 struct pci_dev *cs55x0;
120};
121
122static struct gxfreq_params *gx_params;
123static int stock_freq;
124
125/* PCI bus clock - defaults to 30.000 if cpu_khz is not available */
126static int pci_busclk = 0;
127module_param (pci_busclk, int, 0444);
128
129/* maximum duration for which the cpu may be suspended
130 * (32us * MAX_DURATION). If no parameter is given, this defaults
131 * to 255.
132 * Note that this leads to a maximum of 8 ms(!) where the CPU clock
133 * is suspended -- processing power is just 0.39% of what it used to be,
134 * though. 781.25 kHz(!) for a 200 MHz processor -- wow. */
135static int max_duration = 255;
136module_param (max_duration, int, 0444);
137
138/* For the default policy, we want at least some processing power
139 * - let's say 5%. (min = maxfreq / POLICY_MIN_DIV)
140 */
141#define POLICY_MIN_DIV 20
142
143
144#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "gx-suspmod", msg)
145
146/**
147 * we can detect a core multipiler from dir0_lsb
148 * from GX1 datasheet p.56,
149 * MULT[3:0]:
150 * 0000 = SYSCLK multiplied by 4 (test only)
151 * 0001 = SYSCLK multiplied by 10
152 * 0010 = SYSCLK multiplied by 4
153 * 0011 = SYSCLK multiplied by 6
154 * 0100 = SYSCLK multiplied by 9
155 * 0101 = SYSCLK multiplied by 5
156 * 0110 = SYSCLK multiplied by 7
157 * 0111 = SYSCLK multiplied by 8
158 * of 33.3MHz
159 **/
160static int gx_freq_mult[16] = {
161 4, 10, 4, 6, 9, 5, 7, 8,
162 0, 0, 0, 0, 0, 0, 0, 0
163};
164
165
166/****************************************************************
167 * Low Level chipset interface *
168 ****************************************************************/
169static struct pci_device_id gx_chipset_tbl[] __initdata = {
170 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, PCI_ANY_ID, PCI_ANY_ID },
171 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID },
172 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID },
173 { 0, },
174};
175
176/**
177 * gx_detect_chipset:
178 *
179 **/
180static __init struct pci_dev *gx_detect_chipset(void)
181{
182 struct pci_dev *gx_pci = NULL;
183
184 /* check if CPU is a MediaGX or a Geode. */
185 if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
186 (current_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
187 dprintk("error: no MediaGX/Geode processor found!\n");
188 return NULL;
189 }
190
191 /* detect which companion chip is used */
192 while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) {
193 if ((pci_match_device (gx_chipset_tbl, gx_pci)) != NULL) {
194 return gx_pci;
195 }
196 }
197
198 dprintk("error: no supported chipset found!\n");
199 return NULL;
200}
201
202/**
203 * gx_get_cpuspeed:
204 *
205 * Finds out at which efficient frequency the Cyrix MediaGX/NatSemi Geode CPU runs.
206 */
207static unsigned int gx_get_cpuspeed(unsigned int cpu)
208{
209 if ((gx_params->pci_suscfg & SUSMOD) == 0)
210 return stock_freq;
211
212 return (stock_freq * gx_params->off_duration)
213 / (gx_params->on_duration + gx_params->off_duration);
214}
215
216/**
217 * gx_validate_speed:
218 * determine current cpu speed
219 *
220**/
221
222static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off_duration)
223{
224 unsigned int i;
225 u8 tmp_on, tmp_off;
226 int old_tmp_freq = stock_freq;
227 int tmp_freq;
228
229 *off_duration=1;
230 *on_duration=0;
231
232 for (i=max_duration; i>0; i--) {
233 tmp_off = ((khz * i) / stock_freq) & 0xff;
234 tmp_on = i - tmp_off;
235 tmp_freq = (stock_freq * tmp_off) / i;
236 /* if this relation is closer to khz, use this. If it's equal,
237 * prefer it, too - lower latency */
238 if (abs(tmp_freq - khz) <= abs(old_tmp_freq - khz)) {
239 *on_duration = tmp_on;
240 *off_duration = tmp_off;
241 old_tmp_freq = tmp_freq;
242 }
243 }
244
245 return old_tmp_freq;
246}
247
248
249/**
250 * gx_set_cpuspeed:
251 * set cpu speed in khz.
252 **/
253
254static void gx_set_cpuspeed(unsigned int khz)
255{
256 u8 suscfg, pmer1;
257 unsigned int new_khz;
258 unsigned long flags;
259 struct cpufreq_freqs freqs;
260
261
262 freqs.cpu = 0;
263 freqs.old = gx_get_cpuspeed(0);
264
265 new_khz = gx_validate_speed(khz, &gx_params->on_duration, &gx_params->off_duration);
266
267 freqs.new = new_khz;
268
269 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
270 local_irq_save(flags);
271
272 if (new_khz != stock_freq) { /* if new khz == 100% of CPU speed, it is special case */
273 switch (gx_params->cs55x0->device) {
274 case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
275 pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP;
276 /* FIXME: need to test other values -- Zwane,Miura */
277 pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */
278 pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
279 pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
280
281 if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */
282 suscfg = gx_params->pci_suscfg | SUSMOD;
283 } else { /* CS5530A,B.. */
284 suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
285 }
286 break;
287 case PCI_DEVICE_ID_CYRIX_5520:
288 case PCI_DEVICE_ID_CYRIX_5510:
289 suscfg = gx_params->pci_suscfg | SUSMOD;
290 break;
291 default:
292 local_irq_restore(flags);
293 dprintk("fatal: try to set unknown chipset.\n");
294 return;
295 }
296 } else {
297 suscfg = gx_params->pci_suscfg & ~(SUSMOD);
298 gx_params->off_duration = 0;
299 gx_params->on_duration = 0;
300 dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n");
301 }
302
303 pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration);
304 pci_write_config_byte(gx_params->cs55x0, PCI_MODON, gx_params->on_duration);
305
306 pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, suscfg);
307 pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &suscfg);
308
309 local_irq_restore(flags);
310
311 gx_params->pci_suscfg = suscfg;
312
313 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
314
315 dprintk("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
316 gx_params->on_duration * 32, gx_params->off_duration * 32);
317 dprintk("suspend modulation w/ clock speed: %d kHz.\n", freqs.new);
318}
319
320/****************************************************************
321 * High level functions *
322 ****************************************************************/
323
324/*
325 * cpufreq_gx_verify: test if frequency range is valid
326 *
327 * This function checks if a given frequency range in kHz is valid
328 * for the hardware supported by the driver.
329 */
330
331static int cpufreq_gx_verify(struct cpufreq_policy *policy)
332{
333 unsigned int tmp_freq = 0;
334 u8 tmp1, tmp2;
335
336 if (!stock_freq || !policy)
337 return -EINVAL;
338
339 policy->cpu = 0;
340 cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq);
341
342 /* it needs to be assured that at least one supported frequency is
343 * within policy->min and policy->max. If it is not, policy->max
344 * needs to be increased until one freuqency is supported.
345 * policy->min may not be decreased, though. This way we guarantee a
346 * specific processing capacity.
347 */
348 tmp_freq = gx_validate_speed(policy->min, &tmp1, &tmp2);
349 if (tmp_freq < policy->min)
350 tmp_freq += stock_freq / max_duration;
351 policy->min = tmp_freq;
352 if (policy->min > policy->max)
353 policy->max = tmp_freq;
354 tmp_freq = gx_validate_speed(policy->max, &tmp1, &tmp2);
355 if (tmp_freq > policy->max)
356 tmp_freq -= stock_freq / max_duration;
357 policy->max = tmp_freq;
358 if (policy->max < policy->min)
359 policy->max = policy->min;
360 cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq);
361
362 return 0;
363}
364
365/*
366 * cpufreq_gx_target:
367 *
368 */
369static int cpufreq_gx_target(struct cpufreq_policy *policy,
370 unsigned int target_freq,
371 unsigned int relation)
372{
373 u8 tmp1, tmp2;
374 unsigned int tmp_freq;
375
376 if (!stock_freq || !policy)
377 return -EINVAL;
378
379 policy->cpu = 0;
380
381 tmp_freq = gx_validate_speed(target_freq, &tmp1, &tmp2);
382 while (tmp_freq < policy->min) {
383 tmp_freq += stock_freq / max_duration;
384 tmp_freq = gx_validate_speed(tmp_freq, &tmp1, &tmp2);
385 }
386 while (tmp_freq > policy->max) {
387 tmp_freq -= stock_freq / max_duration;
388 tmp_freq = gx_validate_speed(tmp_freq, &tmp1, &tmp2);
389 }
390
391 gx_set_cpuspeed(tmp_freq);
392
393 return 0;
394}
395
396static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
397{
398 unsigned int maxfreq, curfreq;
399
400 if (!policy || policy->cpu != 0)
401 return -ENODEV;
402
403 /* determine maximum frequency */
404 if (pci_busclk) {
405 maxfreq = pci_busclk * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
406 } else if (cpu_khz) {
407 maxfreq = cpu_khz;
408 } else {
409 maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
410 }
411 stock_freq = maxfreq;
412 curfreq = gx_get_cpuspeed(0);
413
414 dprintk("cpu max frequency is %d.\n", maxfreq);
415 dprintk("cpu current frequency is %dkHz.\n",curfreq);
416
417 /* setup basic struct for cpufreq API */
418 policy->cpu = 0;
419
420 if (max_duration < POLICY_MIN_DIV)
421 policy->min = maxfreq / max_duration;
422 else
423 policy->min = maxfreq / POLICY_MIN_DIV;
424 policy->max = maxfreq;
425 policy->cur = curfreq;
426 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
427 policy->cpuinfo.min_freq = maxfreq / max_duration;
428 policy->cpuinfo.max_freq = maxfreq;
429 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
430
431 return 0;
432}
433
434/*
435 * cpufreq_gx_init:
436 * MediaGX/Geode GX initialize cpufreq driver
437 */
438static struct cpufreq_driver gx_suspmod_driver = {
439 .get = gx_get_cpuspeed,
440 .verify = cpufreq_gx_verify,
441 .target = cpufreq_gx_target,
442 .init = cpufreq_gx_cpu_init,
443 .name = "gx-suspmod",
444 .owner = THIS_MODULE,
445};
446
447static int __init cpufreq_gx_init(void)
448{
449 int ret;
450 struct gxfreq_params *params;
451 struct pci_dev *gx_pci;
452 u32 class_rev;
453
454 /* Test if we have the right hardware */
455 if ((gx_pci = gx_detect_chipset()) == NULL)
456 return -ENODEV;
457
458 /* check whether module parameters are sane */
459 if (max_duration > 0xff)
460 max_duration = 0xff;
461
462 dprintk("geode suspend modulation available.\n");
463
464 params = kmalloc(sizeof(struct gxfreq_params), GFP_KERNEL);
465 if (params == NULL)
466 return -ENOMEM;
467 memset(params, 0, sizeof(struct gxfreq_params));
468
469 params->cs55x0 = gx_pci;
470 gx_params = params;
471
472 /* keep cs55x0 configurations */
473 pci_read_config_byte(params->cs55x0, PCI_SUSCFG, &(params->pci_suscfg));
474 pci_read_config_byte(params->cs55x0, PCI_PMER1, &(params->pci_pmer1));
475 pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
476 pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
477 pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
478 pci_read_config_dword(params->cs55x0, PCI_CLASS_REVISION, &class_rev);
479 params->pci_rev = class_rev && 0xff;
480
481 if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
482 kfree(params);
483 return ret; /* register error! */
484 }
485
486 return 0;
487}
488
489static void __exit cpufreq_gx_exit(void)
490{
491 cpufreq_unregister_driver(&gx_suspmod_driver);
492 pci_dev_put(gx_params->cs55x0);
493 kfree(gx_params);
494}
495
496MODULE_AUTHOR ("Hiroshi Miura <miura@da-cha.org>");
497MODULE_DESCRIPTION ("Cpufreq driver for Cyrix MediaGX and NatSemi Geode");
498MODULE_LICENSE ("GPL");
499
500module_init(cpufreq_gx_init);
501module_exit(cpufreq_gx_exit);
502
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
new file mode 100644
index 000000000000..ab0f9f5aac11
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -0,0 +1,658 @@
1/*
2 * (C) 2001-2004 Dave Jones. <davej@codemonkey.org.uk>
3 * (C) 2002 Padraig Brady. <padraig@antefacto.com>
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
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 the same as v1, but adds voltage scaling.
12 * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
13 * voltage scaling support has currently been disabled in this driver
14 * until we have code that gets it right.
15 * Version 3 of longhaul got renamed to Powersaver and redesigned
16 * to use the POWERSAVER MSR at 0x110a.
17 * It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
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
20 * too well in practice so we don't even try to use this.
21 *
22 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
23 */
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/init.h>
29#include <linux/cpufreq.h>
30#include <linux/slab.h>
31#include <linux/string.h>
32
33#include <asm/msr.h>
34#include <asm/timex.h>
35#include <asm/io.h>
36
37#include "longhaul.h"
38
39#define PFX "longhaul: "
40
41#define TYPE_LONGHAUL_V1 1
42#define TYPE_LONGHAUL_V2 2
43#define TYPE_POWERSAVER 3
44
45#define CPU_SAMUEL 1
46#define CPU_SAMUEL2 2
47#define CPU_EZRA 3
48#define CPU_EZRA_T 4
49#define CPU_NEHEMIAH 5
50
51static int cpu_model;
52static unsigned int numscales=16, numvscales;
53static unsigned int fsb;
54static int minvid, maxvid;
55static unsigned int minmult, maxmult;
56static int can_scale_voltage;
57static int vrmrev;
58
59/* Module parameters */
60static int dont_scale_voltage;
61
62
63#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
64
65
66#define __hlt() __asm__ __volatile__("hlt": : :"memory")
67
68/* Clock ratios multiplied by 10 */
69static int clock_ratio[32];
70static int eblcr_table[32];
71static int voltage_table[32];
72static unsigned int highest_speed, lowest_speed; /* kHz */
73static int longhaul_version;
74static struct cpufreq_frequency_table *longhaul_table;
75
76#ifdef CONFIG_CPU_FREQ_DEBUG
77static char speedbuffer[8];
78
79static char *print_speed(int speed)
80{
81 if (speed > 1000) {
82 if (speed%1000 == 0)
83 sprintf (speedbuffer, "%dGHz", speed/1000);
84 else
85 sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100);
86 } else
87 sprintf (speedbuffer, "%dMHz", speed);
88
89 return speedbuffer;
90}
91#endif
92
93
94static unsigned int calc_speed(int mult)
95{
96 int khz;
97 khz = (mult/10)*fsb;
98 if (mult%10)
99 khz += fsb/2;
100 khz *= 1000;
101 return khz;
102}
103
104
105static int longhaul_get_cpu_mult(void)
106{
107 unsigned long invalue=0,lo, hi;
108
109 rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
110 invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22;
111 if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) {
112 if (lo & (1<<27))
113 invalue+=16;
114 }
115 return eblcr_table[invalue];
116}
117
118
119static void do_powersaver(union msr_longhaul *longhaul,
120 unsigned int clock_ratio_index)
121{
122 int version;
123
124 switch (cpu_model) {
125 case CPU_EZRA_T:
126 version = 3;
127 break;
128 case CPU_NEHEMIAH:
129 version = 0xf;
130 break;
131 default:
132 return;
133 }
134
135 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
136 longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
137 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
138 longhaul->bits.EnableSoftBusRatio = 1;
139 longhaul->bits.RevisionKey = 0;
140 local_irq_disable();
141 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
142 local_irq_enable();
143 __hlt();
144
145 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
146 longhaul->bits.EnableSoftBusRatio = 0;
147 longhaul->bits.RevisionKey = version;
148 local_irq_disable();
149 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
150 local_irq_enable();
151}
152
153/**
154 * longhaul_set_cpu_frequency()
155 * @clock_ratio_index : bitpattern of the new multiplier.
156 *
157 * Sets a new clock ratio.
158 */
159
160static void longhaul_setstate(unsigned int clock_ratio_index)
161{
162 int speed, mult;
163 struct cpufreq_freqs freqs;
164 union msr_longhaul longhaul;
165 union msr_bcr2 bcr2;
166 static unsigned int old_ratio=-1;
167
168 if (old_ratio == clock_ratio_index)
169 return;
170 old_ratio = clock_ratio_index;
171
172 mult = clock_ratio[clock_ratio_index];
173 if (mult == -1)
174 return;
175
176 speed = calc_speed(mult);
177 if ((speed > highest_speed) || (speed < lowest_speed))
178 return;
179
180 freqs.old = calc_speed(longhaul_get_cpu_mult());
181 freqs.new = speed;
182 freqs.cpu = 0; /* longhaul.c is UP only driver */
183
184 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
185
186 dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
187 fsb, mult/10, mult%10, print_speed(speed/1000));
188
189 switch (longhaul_version) {
190
191 /*
192 * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
193 * Software controlled multipliers only.
194 *
195 * *NB* Until we get voltage scaling working v1 & v2 are the same code.
196 * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
197 */
198 case TYPE_LONGHAUL_V1:
199 case TYPE_LONGHAUL_V2:
200 rdmsrl (MSR_VIA_BCR2, bcr2.val);
201 /* Enable software clock multiplier */
202 bcr2.bits.ESOFTBF = 1;
203 bcr2.bits.CLOCKMUL = clock_ratio_index;
204 local_irq_disable();
205 wrmsrl (MSR_VIA_BCR2, bcr2.val);
206 local_irq_enable();
207
208 __hlt();
209
210 /* Disable software clock multiplier */
211 rdmsrl (MSR_VIA_BCR2, bcr2.val);
212 bcr2.bits.ESOFTBF = 0;
213 local_irq_disable();
214 wrmsrl (MSR_VIA_BCR2, bcr2.val);
215 local_irq_enable();
216 break;
217
218 /*
219 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
220 * We can scale voltage with this too, but that's currently
221 * disabled until we come up with a decent 'match freq to voltage'
222 * algorithm.
223 * When we add voltage scaling, we will also need to do the
224 * voltage/freq setting in order depending on the direction
225 * of scaling (like we do in powernow-k7.c)
226 * Nehemiah can do FSB scaling too, but this has never been proven
227 * to work in practice.
228 */
229 case TYPE_POWERSAVER:
230 do_powersaver(&longhaul, clock_ratio_index);
231 break;
232 }
233
234 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
235}
236
237/*
238 * Centaur decided to make life a little more tricky.
239 * Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
240 * Samuel2 and above have to try and guess what the FSB is.
241 * We do this by assuming we booted at maximum multiplier, and interpolate
242 * between that value multiplied by possible FSBs and cpu_mhz which
243 * was calculated at boot time. Really ugly, but no other way to do this.
244 */
245
246#define ROUNDING 0xf
247
248static int _guess(int guess)
249{
250 int target;
251
252 target = ((maxmult/10)*guess);
253 if (maxmult%10 != 0)
254 target += (guess/2);
255 target += ROUNDING/2;
256 target &= ~ROUNDING;
257 return target;
258}
259
260
261static int guess_fsb(void)
262{
263 int speed = (cpu_khz/1000);
264 int i;
265 int speeds[3] = { 66, 100, 133 };
266
267 speed += ROUNDING/2;
268 speed &= ~ROUNDING;
269
270 for (i=0; i<3; i++) {
271 if (_guess(speeds[i]) == speed)
272 return speeds[i];
273 }
274 return 0;
275}
276
277
278static int __init longhaul_get_ranges(void)
279{
280 unsigned long invalue;
281 unsigned int multipliers[32]= {
282 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
283 -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
284 unsigned int j, k = 0;
285 union msr_longhaul longhaul;
286 unsigned long lo, hi;
287 unsigned int eblcr_fsb_table_v1[] = { 66, 133, 100, -1 };
288 unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
289
290 switch (longhaul_version) {
291 case TYPE_LONGHAUL_V1:
292 case TYPE_LONGHAUL_V2:
293 /* Ugh, Longhaul v1 didn't have the min/max MSRs.
294 Assume min=3.0x & max = whatever we booted at. */
295 minmult = 30;
296 maxmult = longhaul_get_cpu_mult();
297 rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
298 invalue = (lo & (1<<18|1<<19)) >>18;
299 if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2)
300 fsb = eblcr_fsb_table_v1[invalue];
301 else
302 fsb = guess_fsb();
303 break;
304
305 case TYPE_POWERSAVER:
306 /* Ezra-T */
307 if (cpu_model==CPU_EZRA_T) {
308 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
309 invalue = longhaul.bits.MaxMHzBR;
310 if (longhaul.bits.MaxMHzBR4)
311 invalue += 16;
312 maxmult=multipliers[invalue];
313
314 invalue = longhaul.bits.MinMHzBR;
315 if (longhaul.bits.MinMHzBR4 == 1)
316 minmult = 30;
317 else
318 minmult = multipliers[invalue];
319 fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
320 break;
321 }
322
323 /* Nehemiah */
324 if (cpu_model==CPU_NEHEMIAH) {
325 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
326
327 /*
328 * TODO: This code works, but raises a lot of questions.
329 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
330 * We get around this by using a hardcoded multiplier of 4.0x
331 * for the minimimum speed, and the speed we booted up at for the max.
332 * This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
333 * - According to some VIA documentation EBLCR is only
334 * in pre-Nehemiah C3s. How this still works is a mystery.
335 * We're possibly using something undocumented and unsupported,
336 * But it works, so we don't grumble.
337 */
338 minmult=40;
339 maxmult=longhaul_get_cpu_mult();
340
341 /* Starting with the 1.2GHz parts, theres a 200MHz bus. */
342 if ((cpu_khz/1000) > 1200)
343 fsb = 200;
344 else
345 fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
346 break;
347 }
348 }
349
350 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
351 minmult/10, minmult%10, maxmult/10, maxmult%10);
352
353 if (fsb == -1) {
354 printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
355 return -EINVAL;
356 }
357
358 highest_speed = calc_speed(maxmult);
359 lowest_speed = calc_speed(minmult);
360 dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
361 print_speed(lowest_speed/1000),
362 print_speed(highest_speed/1000));
363
364 if (lowest_speed == highest_speed) {
365 printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
366 return -EINVAL;
367 }
368 if (lowest_speed > highest_speed) {
369 printk (KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
370 lowest_speed, highest_speed);
371 return -EINVAL;
372 }
373
374 longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
375 if(!longhaul_table)
376 return -ENOMEM;
377
378 for (j=0; j < numscales; j++) {
379 unsigned int ratio;
380 ratio = clock_ratio[j];
381 if (ratio == -1)
382 continue;
383 if (ratio > maxmult || ratio < minmult)
384 continue;
385 longhaul_table[k].frequency = calc_speed(ratio);
386 longhaul_table[k].index = j;
387 k++;
388 }
389
390 longhaul_table[k].frequency = CPUFREQ_TABLE_END;
391 if (!k) {
392 kfree (longhaul_table);
393 return -EINVAL;
394 }
395
396 return 0;
397}
398
399
400static void __init longhaul_setup_voltagescaling(void)
401{
402 union msr_longhaul longhaul;
403
404 rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
405
406 if (!(longhaul.bits.RevisionID & 1))
407 return;
408
409 minvid = longhaul.bits.MinimumVID;
410 maxvid = longhaul.bits.MaximumVID;
411 vrmrev = longhaul.bits.VRMRev;
412
413 if (minvid == 0 || maxvid == 0) {
414 printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
415 "Voltage scaling disabled.\n",
416 minvid/1000, minvid%1000, maxvid/1000, maxvid%1000);
417 return;
418 }
419
420 if (minvid == maxvid) {
421 printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
422 "both %d.%03d. Voltage scaling disabled\n",
423 maxvid/1000, maxvid%1000);
424 return;
425 }
426
427 if (vrmrev==0) {
428 dprintk ("VRM 8.5 \n");
429 memcpy (voltage_table, vrm85scales, sizeof(voltage_table));
430 numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25;
431 } else {
432 dprintk ("Mobile VRM \n");
433 memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table));
434 numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5;
435 }
436
437 /* Current voltage isn't readable at first, so we need to
438 set it to a known value. The spec says to use maxvid */
439 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; /* FIXME: This is bad. */
440 longhaul.bits.EnableSoftVID = 1;
441 longhaul.bits.SoftVID = maxvid;
442 wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
443
444 minvid = voltage_table[minvid];
445 maxvid = voltage_table[maxvid];
446
447 dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n",
448 maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales);
449
450 can_scale_voltage = 1;
451}
452
453
454static int longhaul_verify(struct cpufreq_policy *policy)
455{
456 return cpufreq_frequency_table_verify(policy, longhaul_table);
457}
458
459
460static int longhaul_target(struct cpufreq_policy *policy,
461 unsigned int target_freq, unsigned int relation)
462{
463 unsigned int table_index = 0;
464 unsigned int new_clock_ratio = 0;
465
466 if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
467 return -EINVAL;
468
469 new_clock_ratio = longhaul_table[table_index].index & 0xFF;
470
471 longhaul_setstate(new_clock_ratio);
472
473 return 0;
474}
475
476
477static unsigned int longhaul_get(unsigned int cpu)
478{
479 if (cpu)
480 return 0;
481 return calc_speed(longhaul_get_cpu_mult());
482}
483
484
485static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
486{
487 struct cpuinfo_x86 *c = cpu_data;
488 char *cpuname=NULL;
489 int ret;
490
491 switch (c->x86_model) {
492 case 6:
493 cpu_model = CPU_SAMUEL;
494 cpuname = "C3 'Samuel' [C5A]";
495 longhaul_version = TYPE_LONGHAUL_V1;
496 memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
497 memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr));
498 break;
499
500 case 7:
501 longhaul_version = TYPE_LONGHAUL_V1;
502 switch (c->x86_mask) {
503 case 0:
504 cpu_model = CPU_SAMUEL2;
505 cpuname = "C3 'Samuel 2' [C5B]";
506 /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */
507 memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
508 memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr));
509 break;
510 case 1 ... 15:
511 if (c->x86_mask < 8) {
512 cpu_model = CPU_SAMUEL2;
513 cpuname = "C3 'Samuel 2' [C5B]";
514 } else {
515 cpu_model = CPU_EZRA;
516 cpuname = "C3 'Ezra' [C5C]";
517 }
518 memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio));
519 memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr));
520 break;
521 }
522 break;
523
524 case 8:
525 cpu_model = CPU_EZRA_T;
526 cpuname = "C3 'Ezra-T' [C5M]";
527 longhaul_version = TYPE_POWERSAVER;
528 numscales=32;
529 memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
530 memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr));
531 break;
532
533 case 9:
534 cpu_model = CPU_NEHEMIAH;
535 longhaul_version = TYPE_POWERSAVER;
536 numscales=32;
537 switch (c->x86_mask) {
538 case 0 ... 1:
539 cpuname = "C3 'Nehemiah A' [C5N]";
540 memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
541 memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
542 break;
543 case 2 ... 4:
544 cpuname = "C3 'Nehemiah B' [C5N]";
545 memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
546 memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
547 break;
548 case 5 ... 15:
549 cpuname = "C3 'Nehemiah C' [C5N]";
550 memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
551 memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
552 break;
553 }
554 break;
555
556 default:
557 cpuname = "Unknown";
558 break;
559 }
560
561 printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname);
562 switch (longhaul_version) {
563 case TYPE_LONGHAUL_V1:
564 case TYPE_LONGHAUL_V2:
565 printk ("Longhaul v%d supported.\n", longhaul_version);
566 break;
567 case TYPE_POWERSAVER:
568 printk ("Powersaver supported.\n");
569 break;
570 };
571
572 ret = longhaul_get_ranges();
573 if (ret != 0)
574 return ret;
575
576 if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
577 (dont_scale_voltage==0))
578 longhaul_setup_voltagescaling();
579
580 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
581 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
582 policy->cur = calc_speed(longhaul_get_cpu_mult());
583
584 ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
585 if (ret)
586 return ret;
587
588 cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
589
590 return 0;
591}
592
593static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
594{
595 cpufreq_frequency_table_put_attr(policy->cpu);
596 return 0;
597}
598
599static struct freq_attr* longhaul_attr[] = {
600 &cpufreq_freq_attr_scaling_available_freqs,
601 NULL,
602};
603
604static struct cpufreq_driver longhaul_driver = {
605 .verify = longhaul_verify,
606 .target = longhaul_target,
607 .get = longhaul_get,
608 .init = longhaul_cpu_init,
609 .exit = __devexit_p(longhaul_cpu_exit),
610 .name = "longhaul",
611 .owner = THIS_MODULE,
612 .attr = longhaul_attr,
613};
614
615
616static int __init longhaul_init(void)
617{
618 struct cpuinfo_x86 *c = cpu_data;
619
620 if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
621 return -ENODEV;
622
623 switch (c->x86_model) {
624 case 6 ... 9:
625 return cpufreq_register_driver(&longhaul_driver);
626 default:
627 printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n");
628 }
629
630 return -ENODEV;
631}
632
633
634static void __exit longhaul_exit(void)
635{
636 int i=0;
637
638 for (i=0; i < numscales; i++) {
639 if (clock_ratio[i] == maxmult) {
640 longhaul_setstate(i);
641 break;
642 }
643 }
644
645 cpufreq_unregister_driver(&longhaul_driver);
646 kfree(longhaul_table);
647}
648
649module_param (dont_scale_voltage, int, 0644);
650MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor");
651
652MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
653MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
654MODULE_LICENSE ("GPL");
655
656module_init(longhaul_init);
657module_exit(longhaul_exit);
658
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
new file mode 100644
index 000000000000..2a495c162ec7
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -0,0 +1,466 @@
1/*
2 * longhaul.h
3 * (C) 2003 Dave Jones.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 *
7 * VIA-specific information
8 */
9
10union msr_bcr2 {
11 struct {
12 unsigned Reseved:19, // 18:0
13 ESOFTBF:1, // 19
14 Reserved2:3, // 22:20
15 CLOCKMUL:4, // 26:23
16 Reserved3:5; // 31:27
17 } bits;
18 unsigned long val;
19};
20
21union msr_longhaul {
22 struct {
23 unsigned RevisionID:4, // 3:0
24 RevisionKey:4, // 7:4
25 EnableSoftBusRatio:1, // 8
26 EnableSoftVID:1, // 9
27 EnableSoftBSEL:1, // 10
28 Reserved:3, // 11:13
29 SoftBusRatio4:1, // 14
30 VRMRev:1, // 15
31 SoftBusRatio:4, // 19:16
32 SoftVID:5, // 24:20
33 Reserved2:3, // 27:25
34 SoftBSEL:2, // 29:28
35 Reserved3:2, // 31:30
36 MaxMHzBR:4, // 35:32
37 MaximumVID:5, // 40:36
38 MaxMHzFSB:2, // 42:41
39 MaxMHzBR4:1, // 43
40 Reserved4:4, // 47:44
41 MinMHzBR:4, // 51:48
42 MinimumVID:5, // 56:52
43 MinMHzFSB:2, // 58:57
44 MinMHzBR4:1, // 59
45 Reserved5:4; // 63:60
46 } bits;
47 unsigned long long val;
48};
49
50/*
51 * Clock ratio tables. Div/Mod by 10 to get ratio.
52 * The eblcr ones specify the ratio read from the CPU.
53 * The clock_ratio ones specify what to write to the CPU.
54 */
55
56/*
57 * VIA C3 Samuel 1 & Samuel 2 (stepping 0)
58 */
59static int __initdata samuel1_clock_ratio[16] = {
60 -1, /* 0000 -> RESERVED */
61 30, /* 0001 -> 3.0x */
62 40, /* 0010 -> 4.0x */
63 -1, /* 0011 -> RESERVED */
64 -1, /* 0100 -> RESERVED */
65 35, /* 0101 -> 3.5x */
66 45, /* 0110 -> 4.5x */
67 55, /* 0111 -> 5.5x */
68 60, /* 1000 -> 6.0x */
69 70, /* 1001 -> 7.0x */
70 80, /* 1010 -> 8.0x */
71 50, /* 1011 -> 5.0x */
72 65, /* 1100 -> 6.5x */
73 75, /* 1101 -> 7.5x */
74 -1, /* 1110 -> RESERVED */
75 -1, /* 1111 -> RESERVED */
76};
77
78static int __initdata samuel1_eblcr[16] = {
79 50, /* 0000 -> RESERVED */
80 30, /* 0001 -> 3.0x */
81 40, /* 0010 -> 4.0x */
82 -1, /* 0011 -> RESERVED */
83 55, /* 0100 -> 5.5x */
84 35, /* 0101 -> 3.5x */
85 45, /* 0110 -> 4.5x */
86 -1, /* 0111 -> RESERVED */
87 -1, /* 1000 -> RESERVED */
88 70, /* 1001 -> 7.0x */
89 80, /* 1010 -> 8.0x */
90 60, /* 1011 -> 6.0x */
91 -1, /* 1100 -> RESERVED */
92 75, /* 1101 -> 7.5x */
93 -1, /* 1110 -> RESERVED */
94 65, /* 1111 -> 6.5x */
95};
96
97/*
98 * VIA C3 Samuel2 Stepping 1->15
99 */
100static int __initdata samuel2_eblcr[16] = {
101 50, /* 0000 -> 5.0x */
102 30, /* 0001 -> 3.0x */
103 40, /* 0010 -> 4.0x */
104 100, /* 0011 -> 10.0x */
105 55, /* 0100 -> 5.5x */
106 35, /* 0101 -> 3.5x */
107 45, /* 0110 -> 4.5x */
108 110, /* 0111 -> 11.0x */
109 90, /* 1000 -> 9.0x */
110 70, /* 1001 -> 7.0x */
111 80, /* 1010 -> 8.0x */
112 60, /* 1011 -> 6.0x */
113 120, /* 1100 -> 12.0x */
114 75, /* 1101 -> 7.5x */
115 130, /* 1110 -> 13.0x */
116 65, /* 1111 -> 6.5x */
117};
118
119/*
120 * VIA C3 Ezra
121 */
122static int __initdata ezra_clock_ratio[16] = {
123 100, /* 0000 -> 10.0x */
124 30, /* 0001 -> 3.0x */
125 40, /* 0010 -> 4.0x */
126 90, /* 0011 -> 9.0x */
127 95, /* 0100 -> 9.5x */
128 35, /* 0101 -> 3.5x */
129 45, /* 0110 -> 4.5x */
130 55, /* 0111 -> 5.5x */
131 60, /* 1000 -> 6.0x */
132 70, /* 1001 -> 7.0x */
133 80, /* 1010 -> 8.0x */
134 50, /* 1011 -> 5.0x */
135 65, /* 1100 -> 6.5x */
136 75, /* 1101 -> 7.5x */
137 85, /* 1110 -> 8.5x */
138 120, /* 1111 -> 12.0x */
139};
140
141static int __initdata ezra_eblcr[16] = {
142 50, /* 0000 -> 5.0x */
143 30, /* 0001 -> 3.0x */
144 40, /* 0010 -> 4.0x */
145 100, /* 0011 -> 10.0x */
146 55, /* 0100 -> 5.5x */
147 35, /* 0101 -> 3.5x */
148 45, /* 0110 -> 4.5x */
149 95, /* 0111 -> 9.5x */
150 90, /* 1000 -> 9.0x */
151 70, /* 1001 -> 7.0x */
152 80, /* 1010 -> 8.0x */
153 60, /* 1011 -> 6.0x */
154 120, /* 1100 -> 12.0x */
155 75, /* 1101 -> 7.5x */
156 85, /* 1110 -> 8.5x */
157 65, /* 1111 -> 6.5x */
158};
159
160/*
161 * VIA C3 (Ezra-T) [C5M].
162 */
163static int __initdata ezrat_clock_ratio[32] = {
164 100, /* 0000 -> 10.0x */
165 30, /* 0001 -> 3.0x */
166 40, /* 0010 -> 4.0x */
167 90, /* 0011 -> 9.0x */
168 95, /* 0100 -> 9.5x */
169 35, /* 0101 -> 3.5x */
170 45, /* 0110 -> 4.5x */
171 55, /* 0111 -> 5.5x */
172 60, /* 1000 -> 6.0x */
173 70, /* 1001 -> 7.0x */
174 80, /* 1010 -> 8.0x */
175 50, /* 1011 -> 5.0x */
176 65, /* 1100 -> 6.5x */
177 75, /* 1101 -> 7.5x */
178 85, /* 1110 -> 8.5x */
179 120, /* 1111 -> 12.0x */
180
181 -1, /* 0000 -> RESERVED (10.0x) */
182 110, /* 0001 -> 11.0x */
183 120, /* 0010 -> 12.0x */
184 -1, /* 0011 -> RESERVED (9.0x)*/
185 105, /* 0100 -> 10.5x */
186 115, /* 0101 -> 11.5x */
187 125, /* 0110 -> 12.5x */
188 135, /* 0111 -> 13.5x */
189 140, /* 1000 -> 14.0x */
190 150, /* 1001 -> 15.0x */
191 160, /* 1010 -> 16.0x */
192 130, /* 1011 -> 13.0x */
193 145, /* 1100 -> 14.5x */
194 155, /* 1101 -> 15.5x */
195 -1, /* 1110 -> RESERVED (13.0x) */
196 -1, /* 1111 -> RESERVED (12.0x) */
197};
198
199static int __initdata ezrat_eblcr[32] = {
200 50, /* 0000 -> 5.0x */
201 30, /* 0001 -> 3.0x */
202 40, /* 0010 -> 4.0x */
203 100, /* 0011 -> 10.0x */
204 55, /* 0100 -> 5.5x */
205 35, /* 0101 -> 3.5x */
206 45, /* 0110 -> 4.5x */
207 95, /* 0111 -> 9.5x */
208 90, /* 1000 -> 9.0x */
209 70, /* 1001 -> 7.0x */
210 80, /* 1010 -> 8.0x */
211 60, /* 1011 -> 6.0x */
212 120, /* 1100 -> 12.0x */
213 75, /* 1101 -> 7.5x */
214 85, /* 1110 -> 8.5x */
215 65, /* 1111 -> 6.5x */
216
217 -1, /* 0000 -> RESERVED (9.0x) */
218 110, /* 0001 -> 11.0x */
219 120, /* 0010 -> 12.0x */
220 -1, /* 0011 -> RESERVED (10.0x)*/
221 135, /* 0100 -> 13.5x */
222 115, /* 0101 -> 11.5x */
223 125, /* 0110 -> 12.5x */
224 105, /* 0111 -> 10.5x */
225 130, /* 1000 -> 13.0x */
226 150, /* 1001 -> 15.0x */
227 160, /* 1010 -> 16.0x */
228 140, /* 1011 -> 14.0x */
229 -1, /* 1100 -> RESERVED (12.0x) */
230 155, /* 1101 -> 15.5x */
231 -1, /* 1110 -> RESERVED (13.0x) */
232 145, /* 1111 -> 14.5x */
233};
234
235/*
236 * VIA C3 Nehemiah */
237
238static int __initdata nehemiah_a_clock_ratio[32] = {
239 100, /* 0000 -> 10.0x */
240 160, /* 0001 -> 16.0x */
241 -1, /* 0010 -> RESERVED */
242 90, /* 0011 -> 9.0x */
243 95, /* 0100 -> 9.5x */
244 -1, /* 0101 -> RESERVED */
245 -1, /* 0110 -> RESERVED */
246 55, /* 0111 -> 5.5x */
247 60, /* 1000 -> 6.0x */
248 70, /* 1001 -> 7.0x */
249 80, /* 1010 -> 8.0x */
250 50, /* 1011 -> 5.0x */
251 65, /* 1100 -> 6.5x */
252 75, /* 1101 -> 7.5x */
253 85, /* 1110 -> 8.5x */
254 120, /* 1111 -> 12.0x */
255 100, /* 0000 -> 10.0x */
256 -1, /* 0001 -> RESERVED */
257 120, /* 0010 -> 12.0x */
258 90, /* 0011 -> 9.0x */
259 105, /* 0100 -> 10.5x */
260 115, /* 0101 -> 11.5x */
261 125, /* 0110 -> 12.5x */
262 135, /* 0111 -> 13.5x */
263 140, /* 1000 -> 14.0x */
264 150, /* 1001 -> 15.0x */
265 160, /* 1010 -> 16.0x */
266 130, /* 1011 -> 13.0x */
267 145, /* 1100 -> 14.5x */
268 155, /* 1101 -> 15.5x */
269 -1, /* 1110 -> RESERVED (13.0x) */
270 120, /* 1111 -> 12.0x */
271};
272
273static int __initdata nehemiah_b_clock_ratio[32] = {
274 100, /* 0000 -> 10.0x */
275 160, /* 0001 -> 16.0x */
276 -1, /* 0010 -> RESERVED */
277 90, /* 0011 -> 9.0x */
278 95, /* 0100 -> 9.5x */
279 -1, /* 0101 -> RESERVED */
280 -1, /* 0110 -> RESERVED */
281 55, /* 0111 -> 5.5x */
282 60, /* 1000 -> 6.0x */
283 70, /* 1001 -> 7.0x */
284 80, /* 1010 -> 8.0x */
285 50, /* 1011 -> 5.0x */
286 65, /* 1100 -> 6.5x */
287 75, /* 1101 -> 7.5x */
288 85, /* 1110 -> 8.5x */
289 120, /* 1111 -> 12.0x */
290 100, /* 0000 -> 10.0x */
291 110, /* 0001 -> 11.0x */
292 120, /* 0010 -> 12.0x */
293 90, /* 0011 -> 9.0x */
294 105, /* 0100 -> 10.5x */
295 115, /* 0101 -> 11.5x */
296 125, /* 0110 -> 12.5x */
297 135, /* 0111 -> 13.5x */
298 140, /* 1000 -> 14.0x */
299 150, /* 1001 -> 15.0x */
300 160, /* 1010 -> 16.0x */
301 130, /* 1011 -> 13.0x */
302 145, /* 1100 -> 14.5x */
303 155, /* 1101 -> 15.5x */
304 -1, /* 1110 -> RESERVED (13.0x) */
305 120, /* 1111 -> 12.0x */
306};
307
308static int __initdata nehemiah_c_clock_ratio[32] = {
309 100, /* 0000 -> 10.0x */
310 160, /* 0001 -> 16.0x */
311 40, /* 0010 -> RESERVED */
312 90, /* 0011 -> 9.0x */
313 95, /* 0100 -> 9.5x */
314 -1, /* 0101 -> RESERVED */
315 45, /* 0110 -> RESERVED */
316 55, /* 0111 -> 5.5x */
317 60, /* 1000 -> 6.0x */
318 70, /* 1001 -> 7.0x */
319 80, /* 1010 -> 8.0x */
320 50, /* 1011 -> 5.0x */
321 65, /* 1100 -> 6.5x */
322 75, /* 1101 -> 7.5x */
323 85, /* 1110 -> 8.5x */
324 120, /* 1111 -> 12.0x */
325 100, /* 0000 -> 10.0x */
326 110, /* 0001 -> 11.0x */
327 120, /* 0010 -> 12.0x */
328 90, /* 0011 -> 9.0x */
329 105, /* 0100 -> 10.5x */
330 115, /* 0101 -> 11.5x */
331 125, /* 0110 -> 12.5x */
332 135, /* 0111 -> 13.5x */
333 140, /* 1000 -> 14.0x */
334 150, /* 1001 -> 15.0x */
335 160, /* 1010 -> 16.0x */
336 130, /* 1011 -> 13.0x */
337 145, /* 1100 -> 14.5x */
338 155, /* 1101 -> 15.5x */
339 -1, /* 1110 -> RESERVED (13.0x) */
340 120, /* 1111 -> 12.0x */
341};
342
343static int __initdata nehemiah_a_eblcr[32] = {
344 50, /* 0000 -> 5.0x */
345 160, /* 0001 -> 16.0x */
346 -1, /* 0010 -> RESERVED */
347 100, /* 0011 -> 10.0x */
348 55, /* 0100 -> 5.5x */
349 -1, /* 0101 -> RESERVED */
350 -1, /* 0110 -> RESERVED */
351 95, /* 0111 -> 9.5x */
352 90, /* 1000 -> 9.0x */
353 70, /* 1001 -> 7.0x */
354 80, /* 1010 -> 8.0x */
355 60, /* 1011 -> 6.0x */
356 120, /* 1100 -> 12.0x */
357 75, /* 1101 -> 7.5x */
358 85, /* 1110 -> 8.5x */
359 65, /* 1111 -> 6.5x */
360 90, /* 0000 -> 9.0x */
361 -1, /* 0001 -> RESERVED */
362 120, /* 0010 -> 12.0x */
363 100, /* 0011 -> 10.0x */
364 135, /* 0100 -> 13.5x */
365 115, /* 0101 -> 11.5x */
366 125, /* 0110 -> 12.5x */
367 105, /* 0111 -> 10.5x */
368 130, /* 1000 -> 13.0x */
369 150, /* 1001 -> 15.0x */
370 160, /* 1010 -> 16.0x */
371 140, /* 1011 -> 14.0x */
372 120, /* 1100 -> 12.0x */
373 155, /* 1101 -> 15.5x */
374 -1, /* 1110 -> RESERVED (13.0x) */
375 145 /* 1111 -> 14.5x */
376 /* end of table */
377};
378static int __initdata nehemiah_b_eblcr[32] = {
379 50, /* 0000 -> 5.0x */
380 160, /* 0001 -> 16.0x */
381 -1, /* 0010 -> RESERVED */
382 100, /* 0011 -> 10.0x */
383 55, /* 0100 -> 5.5x */
384 -1, /* 0101 -> RESERVED */
385 -1, /* 0110 -> RESERVED */
386 95, /* 0111 -> 9.5x */
387 90, /* 1000 -> 9.0x */
388 70, /* 1001 -> 7.0x */
389 80, /* 1010 -> 8.0x */
390 60, /* 1011 -> 6.0x */
391 120, /* 1100 -> 12.0x */
392 75, /* 1101 -> 7.5x */
393 85, /* 1110 -> 8.5x */
394 65, /* 1111 -> 6.5x */
395 90, /* 0000 -> 9.0x */
396 110, /* 0001 -> 11.0x */
397 120, /* 0010 -> 12.0x */
398 100, /* 0011 -> 10.0x */
399 135, /* 0100 -> 13.5x */
400 115, /* 0101 -> 11.5x */
401 125, /* 0110 -> 12.5x */
402 105, /* 0111 -> 10.5x */
403 130, /* 1000 -> 13.0x */
404 150, /* 1001 -> 15.0x */
405 160, /* 1010 -> 16.0x */
406 140, /* 1011 -> 14.0x */
407 120, /* 1100 -> 12.0x */
408 155, /* 1101 -> 15.5x */
409 -1, /* 1110 -> RESERVED (13.0x) */
410 145 /* 1111 -> 14.5x */
411 /* end of table */
412};
413static int __initdata nehemiah_c_eblcr[32] = {
414 50, /* 0000 -> 5.0x */
415 160, /* 0001 -> 16.0x */
416 40, /* 0010 -> RESERVED */
417 100, /* 0011 -> 10.0x */
418 55, /* 0100 -> 5.5x */
419 -1, /* 0101 -> RESERVED */
420 45, /* 0110 -> RESERVED */
421 95, /* 0111 -> 9.5x */
422 90, /* 1000 -> 9.0x */
423 70, /* 1001 -> 7.0x */
424 80, /* 1010 -> 8.0x */
425 60, /* 1011 -> 6.0x */
426 120, /* 1100 -> 12.0x */
427 75, /* 1101 -> 7.5x */
428 85, /* 1110 -> 8.5x */
429 65, /* 1111 -> 6.5x */
430 90, /* 0000 -> 9.0x */
431 110, /* 0001 -> 11.0x */
432 120, /* 0010 -> 12.0x */
433 100, /* 0011 -> 10.0x */
434 135, /* 0100 -> 13.5x */
435 115, /* 0101 -> 11.5x */
436 125, /* 0110 -> 12.5x */
437 105, /* 0111 -> 10.5x */
438 130, /* 1000 -> 13.0x */
439 150, /* 1001 -> 15.0x */
440 160, /* 1010 -> 16.0x */
441 140, /* 1011 -> 14.0x */
442 120, /* 1100 -> 12.0x */
443 155, /* 1101 -> 15.5x */
444 -1, /* 1110 -> RESERVED (13.0x) */
445 145 /* 1111 -> 14.5x */
446 /* end of table */
447};
448
449/*
450 * Voltage scales. Div/Mod by 1000 to get actual voltage.
451 * Which scale to use depends on the VRM type in use.
452 */
453static int __initdata vrm85scales[32] = {
454 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700,
455 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300,
456 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725,
457 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325,
458};
459
460static int __initdata mobilevrmscales[32] = {
461 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
462 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1,
463 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
464 1075, 1050, 1025, 1000, 975, 950, 925, -1,
465};
466
diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
new file mode 100644
index 000000000000..e3868de4dc2e
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c
@@ -0,0 +1,326 @@
1/*
2 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/slab.h>
13#include <linux/cpufreq.h>
14
15#include <asm/msr.h>
16#include <asm/processor.h>
17#include <asm/timex.h>
18
19#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longrun", msg)
20
21static struct cpufreq_driver longrun_driver;
22
23/**
24 * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz
25 * values into per cent values. In TMTA microcode, the following is valid:
26 * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
27 */
28static unsigned int longrun_low_freq, longrun_high_freq;
29
30
31/**
32 * longrun_get_policy - get the current LongRun policy
33 * @policy: struct cpufreq_policy where current policy is written into
34 *
35 * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS
36 * and MSR_TMTA_LONGRUN_CTRL
37 */
38static void __init longrun_get_policy(struct cpufreq_policy *policy)
39{
40 u32 msr_lo, msr_hi;
41
42 rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi);
43 dprintk("longrun flags are %x - %x\n", msr_lo, msr_hi);
44 if (msr_lo & 0x01)
45 policy->policy = CPUFREQ_POLICY_PERFORMANCE;
46 else
47 policy->policy = CPUFREQ_POLICY_POWERSAVE;
48
49 rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
50 dprintk("longrun ctrl is %x - %x\n", msr_lo, msr_hi);
51 msr_lo &= 0x0000007F;
52 msr_hi &= 0x0000007F;
53
54 if ( longrun_high_freq <= longrun_low_freq ) {
55 /* Assume degenerate Longrun table */
56 policy->min = policy->max = longrun_high_freq;
57 } else {
58 policy->min = longrun_low_freq + msr_lo *
59 ((longrun_high_freq - longrun_low_freq) / 100);
60 policy->max = longrun_low_freq + msr_hi *
61 ((longrun_high_freq - longrun_low_freq) / 100);
62 }
63 policy->cpu = 0;
64}
65
66
67/**
68 * longrun_set_policy - sets a new CPUFreq policy
69 * @policy: new policy
70 *
71 * Sets a new CPUFreq policy on LongRun-capable processors. This function
72 * has to be called with cpufreq_driver locked.
73 */
74static int longrun_set_policy(struct cpufreq_policy *policy)
75{
76 u32 msr_lo, msr_hi;
77 u32 pctg_lo, pctg_hi;
78
79 if (!policy)
80 return -EINVAL;
81
82 if ( longrun_high_freq <= longrun_low_freq ) {
83 /* Assume degenerate Longrun table */
84 pctg_lo = pctg_hi = 100;
85 } else {
86 pctg_lo = (policy->min - longrun_low_freq) /
87 ((longrun_high_freq - longrun_low_freq) / 100);
88 pctg_hi = (policy->max - longrun_low_freq) /
89 ((longrun_high_freq - longrun_low_freq) / 100);
90 }
91
92 if (pctg_hi > 100)
93 pctg_hi = 100;
94 if (pctg_lo > pctg_hi)
95 pctg_lo = pctg_hi;
96
97 /* performance or economy mode */
98 rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi);
99 msr_lo &= 0xFFFFFFFE;
100 switch (policy->policy) {
101 case CPUFREQ_POLICY_PERFORMANCE:
102 msr_lo |= 0x00000001;
103 break;
104 case CPUFREQ_POLICY_POWERSAVE:
105 break;
106 }
107 wrmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi);
108
109 /* lower and upper boundary */
110 rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
111 msr_lo &= 0xFFFFFF80;
112 msr_hi &= 0xFFFFFF80;
113 msr_lo |= pctg_lo;
114 msr_hi |= pctg_hi;
115 wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
116
117 return 0;
118}
119
120
121/**
122 * longrun_verify_poliy - verifies a new CPUFreq policy
123 * @policy: the policy to verify
124 *
125 * Validates a new CPUFreq policy. This function has to be called with
126 * cpufreq_driver locked.
127 */
128static int longrun_verify_policy(struct cpufreq_policy *policy)
129{
130 if (!policy)
131 return -EINVAL;
132
133 policy->cpu = 0;
134 cpufreq_verify_within_limits(policy,
135 policy->cpuinfo.min_freq,
136 policy->cpuinfo.max_freq);
137
138 if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
139 (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
140 return -EINVAL;
141
142 return 0;
143}
144
145static unsigned int longrun_get(unsigned int cpu)
146{
147 u32 eax, ebx, ecx, edx;
148
149 if (cpu)
150 return 0;
151
152 cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
153 dprintk("cpuid eax is %u\n", eax);
154
155 return (eax * 1000);
156}
157
158/**
159 * longrun_determine_freqs - determines the lowest and highest possible core frequency
160 * @low_freq: an int to put the lowest frequency into
161 * @high_freq: an int to put the highest frequency into
162 *
163 * Determines the lowest and highest possible core frequencies on this CPU.
164 * This is necessary to calculate the performance percentage according to
165 * TMTA rules:
166 * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
167 */
168static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
169 unsigned int *high_freq)
170{
171 u32 msr_lo, msr_hi;
172 u32 save_lo, save_hi;
173 u32 eax, ebx, ecx, edx;
174 u32 try_hi;
175 struct cpuinfo_x86 *c = cpu_data;
176
177 if (!low_freq || !high_freq)
178 return -EINVAL;
179
180 if (cpu_has(c, X86_FEATURE_LRTI)) {
181 /* if the LongRun Table Interface is present, the
182 * detection is a bit easier:
183 * For minimum frequency, read out the maximum
184 * level (msr_hi), write that into "currently
185 * selected level", and read out the frequency.
186 * For maximum frequency, read out level zero.
187 */
188 /* minimum */
189 rdmsr(MSR_TMTA_LRTI_READOUT, msr_lo, msr_hi);
190 wrmsr(MSR_TMTA_LRTI_READOUT, msr_hi, msr_hi);
191 rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi);
192 *low_freq = msr_lo * 1000; /* to kHz */
193
194 /* maximum */
195 wrmsr(MSR_TMTA_LRTI_READOUT, 0, msr_hi);
196 rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi);
197 *high_freq = msr_lo * 1000; /* to kHz */
198
199 dprintk("longrun table interface told %u - %u kHz\n", *low_freq, *high_freq);
200
201 if (*low_freq > *high_freq)
202 *low_freq = *high_freq;
203 return 0;
204 }
205
206 /* set the upper border to the value determined during TSC init */
207 *high_freq = (cpu_khz / 1000);
208 *high_freq = *high_freq * 1000;
209 dprintk("high frequency is %u kHz\n", *high_freq);
210
211 /* get current borders */
212 rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
213 save_lo = msr_lo & 0x0000007F;
214 save_hi = msr_hi & 0x0000007F;
215
216 /* if current perf_pctg is larger than 90%, we need to decrease the
217 * upper limit to make the calculation more accurate.
218 */
219 cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
220 /* try decreasing in 10% steps, some processors react only
221 * on some barrier values */
222 for (try_hi = 80; try_hi > 0 && ecx > 90; try_hi -=10) {
223 /* set to 0 to try_hi perf_pctg */
224 msr_lo &= 0xFFFFFF80;
225 msr_hi &= 0xFFFFFF80;
226 msr_lo |= 0;
227 msr_hi |= try_hi;
228 wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
229
230 /* read out current core MHz and current perf_pctg */
231 cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
232
233 /* restore values */
234 wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);
235 }
236 dprintk("percentage is %u %%, freq is %u MHz\n", ecx, eax);
237
238 /* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
239 * eqals
240 * low_freq * ( 1 - perf_pctg) = (cur_freq - high_freq * perf_pctg)
241 *
242 * high_freq * perf_pctg is stored tempoarily into "ebx".
243 */
244 ebx = (((cpu_khz / 1000) * ecx) / 100); /* to MHz */
245
246 if ((ecx > 95) || (ecx == 0) || (eax < ebx))
247 return -EIO;
248
249 edx = (eax - ebx) / (100 - ecx);
250 *low_freq = edx * 1000; /* back to kHz */
251
252 dprintk("low frequency is %u kHz\n", *low_freq);
253
254 if (*low_freq > *high_freq)
255 *low_freq = *high_freq;
256
257 return 0;
258}
259
260
261static int __init longrun_cpu_init(struct cpufreq_policy *policy)
262{
263 int result = 0;
264
265 /* capability check */
266 if (policy->cpu != 0)
267 return -ENODEV;
268
269 /* detect low and high frequency */
270 result = longrun_determine_freqs(&longrun_low_freq, &longrun_high_freq);
271 if (result)
272 return result;
273
274 /* cpuinfo and default policy values */
275 policy->cpuinfo.min_freq = longrun_low_freq;
276 policy->cpuinfo.max_freq = longrun_high_freq;
277 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
278 longrun_get_policy(policy);
279
280 return 0;
281}
282
283
284static struct cpufreq_driver longrun_driver = {
285 .flags = CPUFREQ_CONST_LOOPS,
286 .verify = longrun_verify_policy,
287 .setpolicy = longrun_set_policy,
288 .get = longrun_get,
289 .init = longrun_cpu_init,
290 .name = "longrun",
291 .owner = THIS_MODULE,
292};
293
294
295/**
296 * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
297 *
298 * Initializes the LongRun support.
299 */
300static int __init longrun_init(void)
301{
302 struct cpuinfo_x86 *c = cpu_data;
303
304 if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
305 !cpu_has(c, X86_FEATURE_LONGRUN))
306 return -ENODEV;
307
308 return cpufreq_register_driver(&longrun_driver);
309}
310
311
312/**
313 * longrun_exit - unregisters LongRun support
314 */
315static void __exit longrun_exit(void)
316{
317 cpufreq_unregister_driver(&longrun_driver);
318}
319
320
321MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
322MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe and Efficeon processors.");
323MODULE_LICENSE ("GPL");
324
325module_init(longrun_init);
326module_exit(longrun_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
new file mode 100644
index 000000000000..aa622d52c6e5
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -0,0 +1,337 @@
1/*
2 * Pentium 4/Xeon CPU on demand clock modulation/speed scaling
3 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
4 * (C) 2002 Zwane Mwaikambo <zwane@commfireservices.com>
5 * (C) 2002 Arjan van de Ven <arjanv@redhat.com>
6 * (C) 2002 Tora T. Engstad
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 *
14 * The author(s) of this software shall not be held liable for damages
15 * of any nature resulting due to the use of this software. This
16 * software is provided AS-IS with no warranties.
17 *
18 * Date Errata Description
19 * 20020525 N44, O17 12.5% or 25% DC causes lockup
20 *
21 */
22
23#include <linux/config.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/smp.h>
28#include <linux/cpufreq.h>
29#include <linux/slab.h>
30#include <linux/cpumask.h>
31
32#include <asm/processor.h>
33#include <asm/msr.h>
34#include <asm/timex.h>
35
36#include "speedstep-lib.h"
37
38#define PFX "p4-clockmod: "
39#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "p4-clockmod", msg)
40
41/*
42 * Duty Cycle (3bits), note DC_DISABLE is not specified in
43 * intel docs i just use it to mean disable
44 */
45enum {
46 DC_RESV, DC_DFLT, DC_25PT, DC_38PT, DC_50PT,
47 DC_64PT, DC_75PT, DC_88PT, DC_DISABLE
48};
49
50#define DC_ENTRIES 8
51
52
53static int has_N44_O17_errata[NR_CPUS];
54static unsigned int stock_freq;
55static struct cpufreq_driver p4clockmod_driver;
56static unsigned int cpufreq_p4_get(unsigned int cpu);
57
58static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
59{
60 u32 l, h;
61
62 if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV))
63 return -EINVAL;
64
65 rdmsr(MSR_IA32_THERM_STATUS, l, h);
66
67 if (l & 0x01)
68 dprintk("CPU#%d currently thermal throttled\n", cpu);
69
70 if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT))
71 newstate = DC_38PT;
72
73 rdmsr(MSR_IA32_THERM_CONTROL, l, h);
74 if (newstate == DC_DISABLE) {
75 dprintk("CPU#%d disabling modulation\n", cpu);
76 wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
77 } else {
78 dprintk("CPU#%d setting duty cycle to %d%%\n",
79 cpu, ((125 * newstate) / 10));
80 /* bits 63 - 5 : reserved
81 * bit 4 : enable/disable
82 * bits 3-1 : duty cycle
83 * bit 0 : reserved
84 */
85 l = (l & ~14);
86 l = l | (1<<4) | ((newstate & 0x7)<<1);
87 wrmsr(MSR_IA32_THERM_CONTROL, l, h);
88 }
89
90 return 0;
91}
92
93
94static struct cpufreq_frequency_table p4clockmod_table[] = {
95 {DC_RESV, CPUFREQ_ENTRY_INVALID},
96 {DC_DFLT, 0},
97 {DC_25PT, 0},
98 {DC_38PT, 0},
99 {DC_50PT, 0},
100 {DC_64PT, 0},
101 {DC_75PT, 0},
102 {DC_88PT, 0},
103 {DC_DISABLE, 0},
104 {DC_RESV, CPUFREQ_TABLE_END},
105};
106
107
108static int cpufreq_p4_target(struct cpufreq_policy *policy,
109 unsigned int target_freq,
110 unsigned int relation)
111{
112 unsigned int newstate = DC_RESV;
113 struct cpufreq_freqs freqs;
114 cpumask_t cpus_allowed;
115 int i;
116
117 if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
118 return -EINVAL;
119
120 freqs.old = cpufreq_p4_get(policy->cpu);
121 freqs.new = stock_freq * p4clockmod_table[newstate].index / 8;
122
123 if (freqs.new == freqs.old)
124 return 0;
125
126 /* notifiers */
127 for_each_cpu_mask(i, policy->cpus) {
128 freqs.cpu = i;
129 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
130 }
131
132 /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
133 * Developer's Manual, Volume 3
134 */
135 cpus_allowed = current->cpus_allowed;
136
137 for_each_cpu_mask(i, policy->cpus) {
138 cpumask_t this_cpu = cpumask_of_cpu(i);
139
140 set_cpus_allowed(current, this_cpu);
141 BUG_ON(smp_processor_id() != i);
142
143 cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
144 }
145 set_cpus_allowed(current, cpus_allowed);
146
147 /* notifiers */
148 for_each_cpu_mask(i, policy->cpus) {
149 freqs.cpu = i;
150 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
151 }
152
153 return 0;
154}
155
156
157static int cpufreq_p4_verify(struct cpufreq_policy *policy)
158{
159 return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);
160}
161
162
163static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
164{
165 if ((c->x86 == 0x06) && (c->x86_model == 0x09)) {
166 /* Pentium M (Banias) */
167 printk(KERN_WARNING PFX "Warning: Pentium M detected. "
168 "The speedstep_centrino module offers voltage scaling"
169 " in addition of frequency scaling. You should use "
170 "that instead of p4-clockmod, if possible.\n");
171 return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
172 }
173
174 if ((c->x86 == 0x06) && (c->x86_model == 0x0D)) {
175 /* Pentium M (Dothan) */
176 printk(KERN_WARNING PFX "Warning: Pentium M detected. "
177 "The speedstep_centrino module offers voltage scaling"
178 " in addition of frequency scaling. You should use "
179 "that instead of p4-clockmod, if possible.\n");
180 /* on P-4s, the TSC runs with constant frequency independent whether
181 * throttling is active or not. */
182 p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
183 return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
184 }
185
186 if (c->x86 != 0xF) {
187 printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <linux@brodo.de>\n");
188 return 0;
189 }
190
191 /* on P-4s, the TSC runs with constant frequency independent whether
192 * throttling is active or not. */
193 p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
194
195 if (speedstep_detect_processor() == SPEEDSTEP_PROCESSOR_P4M) {
196 printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. "
197 "The speedstep-ich or acpi cpufreq modules offer "
198 "voltage scaling in addition of frequency scaling. "
199 "You should use either one instead of p4-clockmod, "
200 "if possible.\n");
201 return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4M);
202 }
203
204 return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4D);
205}
206
207
208
209static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
210{
211 struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
212 int cpuid = 0;
213 unsigned int i;
214
215#ifdef CONFIG_SMP
216 policy->cpus = cpu_sibling_map[policy->cpu];
217#endif
218
219 /* Errata workaround */
220 cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;
221 switch (cpuid) {
222 case 0x0f07:
223 case 0x0f0a:
224 case 0x0f11:
225 case 0x0f12:
226 has_N44_O17_errata[policy->cpu] = 1;
227 dprintk("has errata -- disabling low frequencies\n");
228 }
229
230 /* get max frequency */
231 stock_freq = cpufreq_p4_get_frequency(c);
232 if (!stock_freq)
233 return -EINVAL;
234
235 /* table init */
236 for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
237 if ((i<2) && (has_N44_O17_errata[policy->cpu]))
238 p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
239 else
240 p4clockmod_table[i].frequency = (stock_freq * i)/8;
241 }
242 cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
243
244 /* cpuinfo and default policy values */
245 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
246 policy->cpuinfo.transition_latency = 1000000; /* assumed */
247 policy->cur = stock_freq;
248
249 return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
250}
251
252
253static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
254{
255 cpufreq_frequency_table_put_attr(policy->cpu);
256 return 0;
257}
258
259static unsigned int cpufreq_p4_get(unsigned int cpu)
260{
261 cpumask_t cpus_allowed;
262 u32 l, h;
263
264 cpus_allowed = current->cpus_allowed;
265
266 set_cpus_allowed(current, cpumask_of_cpu(cpu));
267 BUG_ON(smp_processor_id() != cpu);
268
269 rdmsr(MSR_IA32_THERM_CONTROL, l, h);
270
271 set_cpus_allowed(current, cpus_allowed);
272
273 if (l & 0x10) {
274 l = l >> 1;
275 l &= 0x7;
276 } else
277 l = DC_DISABLE;
278
279 if (l != DC_DISABLE)
280 return (stock_freq * l / 8);
281
282 return stock_freq;
283}
284
285static struct freq_attr* p4clockmod_attr[] = {
286 &cpufreq_freq_attr_scaling_available_freqs,
287 NULL,
288};
289
290static struct cpufreq_driver p4clockmod_driver = {
291 .verify = cpufreq_p4_verify,
292 .target = cpufreq_p4_target,
293 .init = cpufreq_p4_cpu_init,
294 .exit = cpufreq_p4_cpu_exit,
295 .get = cpufreq_p4_get,
296 .name = "p4-clockmod",
297 .owner = THIS_MODULE,
298 .attr = p4clockmod_attr,
299};
300
301
302static int __init cpufreq_p4_init(void)
303{
304 struct cpuinfo_x86 *c = cpu_data;
305 int ret;
306
307 /*
308 * THERM_CONTROL is architectural for IA32 now, so
309 * we can rely on the capability checks
310 */
311 if (c->x86_vendor != X86_VENDOR_INTEL)
312 return -ENODEV;
313
314 if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
315 !test_bit(X86_FEATURE_ACC, c->x86_capability))
316 return -ENODEV;
317
318 ret = cpufreq_register_driver(&p4clockmod_driver);
319 if (!ret)
320 printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
321
322 return (ret);
323}
324
325
326static void __exit cpufreq_p4_exit(void)
327{
328 cpufreq_unregister_driver(&p4clockmod_driver);
329}
330
331
332MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");
333MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
334MODULE_LICENSE ("GPL");
335
336late_initcall(cpufreq_p4_init);
337module_exit(cpufreq_p4_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
new file mode 100644
index 000000000000..222f8cfe3c57
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
@@ -0,0 +1,256 @@
1/*
2 * This file was based upon code in Powertweak Linux (http://powertweak.sf.net)
3 * (C) 2000-2003 Dave Jones, Arjan van de Ven, Janne Pänkälä, Dominik Brodowski.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 *
7 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/cpufreq.h>
14#include <linux/ioport.h>
15#include <linux/slab.h>
16
17#include <asm/msr.h>
18#include <asm/timex.h>
19#include <asm/io.h>
20
21
22#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long
23 as it is unused */
24
25static unsigned int busfreq; /* FSB, in 10 kHz */
26static unsigned int max_multiplier;
27
28
29/* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
30static struct cpufreq_frequency_table clock_ratio[] = {
31 {45, /* 000 -> 4.5x */ 0},
32 {50, /* 001 -> 5.0x */ 0},
33 {40, /* 010 -> 4.0x */ 0},
34 {55, /* 011 -> 5.5x */ 0},
35 {20, /* 100 -> 2.0x */ 0},
36 {30, /* 101 -> 3.0x */ 0},
37 {60, /* 110 -> 6.0x */ 0},
38 {35, /* 111 -> 3.5x */ 0},
39 {0, CPUFREQ_TABLE_END}
40};
41
42
43/**
44 * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier
45 *
46 * Returns the current setting of the frequency multiplier. Core clock
47 * speed is frequency of the Front-Side Bus multiplied with this value.
48 */
49static int powernow_k6_get_cpu_multiplier(void)
50{
51 u64 invalue = 0;
52 u32 msrval;
53
54 msrval = POWERNOW_IOPORT + 0x1;
55 wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
56 invalue=inl(POWERNOW_IOPORT + 0x8);
57 msrval = POWERNOW_IOPORT + 0x0;
58 wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
59
60 return clock_ratio[(invalue >> 5)&7].index;
61}
62
63
64/**
65 * powernow_k6_set_state - set the PowerNow! multiplier
66 * @best_i: clock_ratio[best_i] is the target multiplier
67 *
68 * Tries to change the PowerNow! multiplier
69 */
70static void powernow_k6_set_state (unsigned int best_i)
71{
72 unsigned long outvalue=0, invalue=0;
73 unsigned long msrval;
74 struct cpufreq_freqs freqs;
75
76 if (clock_ratio[best_i].index > max_multiplier) {
77 printk(KERN_ERR "cpufreq: invalid target frequency\n");
78 return;
79 }
80
81 freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
82 freqs.new = busfreq * clock_ratio[best_i].index;
83 freqs.cpu = 0; /* powernow-k6.c is UP only driver */
84
85 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
86
87 /* we now need to transform best_i to the BVC format, see AMD#23446 */
88
89 outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5);
90
91 msrval = POWERNOW_IOPORT + 0x1;
92 wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
93 invalue=inl(POWERNOW_IOPORT + 0x8);
94 invalue = invalue & 0xf;
95 outvalue = outvalue | invalue;
96 outl(outvalue ,(POWERNOW_IOPORT + 0x8));
97 msrval = POWERNOW_IOPORT + 0x0;
98 wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
99
100 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
101
102 return;
103}
104
105
106/**
107 * powernow_k6_verify - verifies a new CPUfreq policy
108 * @policy: new policy
109 *
110 * Policy must be within lowest and highest possible CPU Frequency,
111 * and at least one possible state must be within min and max.
112 */
113static int powernow_k6_verify(struct cpufreq_policy *policy)
114{
115 return cpufreq_frequency_table_verify(policy, &clock_ratio[0]);
116}
117
118
119/**
120 * powernow_k6_setpolicy - sets a new CPUFreq policy
121 * @policy: new policy
122 * @target_freq: the target frequency
123 * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
124 *
125 * sets a new CPUFreq policy
126 */
127static int powernow_k6_target (struct cpufreq_policy *policy,
128 unsigned int target_freq,
129 unsigned int relation)
130{
131 unsigned int newstate = 0;
132
133 if (cpufreq_frequency_table_target(policy, &clock_ratio[0], target_freq, relation, &newstate))
134 return -EINVAL;
135
136 powernow_k6_set_state(newstate);
137
138 return 0;
139}
140
141
142static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
143{
144 unsigned int i;
145 int result;
146
147 if (policy->cpu != 0)
148 return -ENODEV;
149
150 /* get frequencies */
151 max_multiplier = powernow_k6_get_cpu_multiplier();
152 busfreq = cpu_khz / max_multiplier;
153
154 /* table init */
155 for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
156 if (clock_ratio[i].index > max_multiplier)
157 clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
158 else
159 clock_ratio[i].frequency = busfreq * clock_ratio[i].index;
160 }
161
162 /* cpuinfo and default policy values */
163 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
164 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
165 policy->cur = busfreq * max_multiplier;
166
167 result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
168 if (result)
169 return (result);
170
171 cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu);
172
173 return 0;
174}
175
176
177static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
178{
179 unsigned int i;
180 for (i=0; i<8; i++) {
181 if (i==max_multiplier)
182 powernow_k6_set_state(i);
183 }
184 cpufreq_frequency_table_put_attr(policy->cpu);
185 return 0;
186}
187
188static unsigned int powernow_k6_get(unsigned int cpu)
189{
190 return busfreq * powernow_k6_get_cpu_multiplier();
191}
192
193static struct freq_attr* powernow_k6_attr[] = {
194 &cpufreq_freq_attr_scaling_available_freqs,
195 NULL,
196};
197
198static struct cpufreq_driver powernow_k6_driver = {
199 .verify = powernow_k6_verify,
200 .target = powernow_k6_target,
201 .init = powernow_k6_cpu_init,
202 .exit = powernow_k6_cpu_exit,
203 .get = powernow_k6_get,
204 .name = "powernow-k6",
205 .owner = THIS_MODULE,
206 .attr = powernow_k6_attr,
207};
208
209
210/**
211 * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver
212 *
213 * Initializes the K6 PowerNow! support. Returns -ENODEV on unsupported
214 * devices, -EINVAL or -ENOMEM on problems during initiatization, and zero
215 * on success.
216 */
217static int __init powernow_k6_init(void)
218{
219 struct cpuinfo_x86 *c = cpu_data;
220
221 if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
222 ((c->x86_model != 12) && (c->x86_model != 13)))
223 return -ENODEV;
224
225 if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
226 printk("cpufreq: PowerNow IOPORT region already used.\n");
227 return -EIO;
228 }
229
230 if (cpufreq_register_driver(&powernow_k6_driver)) {
231 release_region (POWERNOW_IOPORT, 16);
232 return -EINVAL;
233 }
234
235 return 0;
236}
237
238
239/**
240 * powernow_k6_exit - unregisters AMD K6-2+/3+ PowerNow! support
241 *
242 * Unregisters AMD K6-2+ / K6-3+ PowerNow! support.
243 */
244static void __exit powernow_k6_exit(void)
245{
246 cpufreq_unregister_driver(&powernow_k6_driver);
247 release_region (POWERNOW_IOPORT, 16);
248}
249
250
251MODULE_AUTHOR ("Arjan van de Ven <arjanv@redhat.com>, Dave Jones <davej@codemonkey.org.uk>, Dominik Brodowski <linux@brodo.de>");
252MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
253MODULE_LICENSE ("GPL");
254
255module_init(powernow_k6_init);
256module_exit(powernow_k6_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
new file mode 100644
index 000000000000..913f652623d9
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -0,0 +1,690 @@
1/*
2 * AMD K7 Powernow driver.
3 * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs.
4 * (C) 2003-2004 Dave Jones <davej@redhat.com>
5 *
6 * Licensed under the terms of the GNU GPL License version 2.
7 * Based upon datasheets & sample CPUs kindly provided by AMD.
8 *
9 * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
10 * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
11 * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
12 * - We disable half multipliers if ACPI is used on A0 stepping CPUs.
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/init.h>
20#include <linux/cpufreq.h>
21#include <linux/slab.h>
22#include <linux/string.h>
23#include <linux/dmi.h>
24
25#include <asm/msr.h>
26#include <asm/timex.h>
27#include <asm/io.h>
28#include <asm/system.h>
29
30#ifdef CONFIG_X86_POWERNOW_K7_ACPI
31#include <linux/acpi.h>
32#include <acpi/processor.h>
33#endif
34
35#include "powernow-k7.h"
36
37#define PFX "powernow: "
38
39
40struct psb_s {
41 u8 signature[10];
42 u8 tableversion;
43 u8 flags;
44 u16 settlingtime;
45 u8 reserved1;
46 u8 numpst;
47};
48
49struct pst_s {
50 u32 cpuid;
51 u8 fsbspeed;
52 u8 maxfid;
53 u8 startvid;
54 u8 numpstates;
55};
56
57#ifdef CONFIG_X86_POWERNOW_K7_ACPI
58union powernow_acpi_control_t {
59 struct {
60 unsigned long fid:5,
61 vid:5,
62 sgtc:20,
63 res1:2;
64 } bits;
65 unsigned long val;
66};
67#endif
68
69#ifdef CONFIG_CPU_FREQ_DEBUG
70/* divide by 1000 to get VCore voltage in V. */
71static int mobile_vid_table[32] = {
72 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
73 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
74 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
75 1075, 1050, 1025, 1000, 975, 950, 925, 0,
76};
77#endif
78
79/* divide by 10 to get FID. */
80static int fid_codes[32] = {
81 110, 115, 120, 125, 50, 55, 60, 65,
82 70, 75, 80, 85, 90, 95, 100, 105,
83 30, 190, 40, 200, 130, 135, 140, 210,
84 150, 225, 160, 165, 170, 180, -1, -1,
85};
86
87/* This parameter is used in order to force ACPI instead of legacy method for
88 * configuration purpose.
89 */
90
91static int acpi_force;
92
93static struct cpufreq_frequency_table *powernow_table;
94
95static unsigned int can_scale_bus;
96static unsigned int can_scale_vid;
97static unsigned int minimum_speed=-1;
98static unsigned int maximum_speed;
99static unsigned int number_scales;
100static unsigned int fsb;
101static unsigned int latency;
102static char have_a0;
103
104#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k7", msg)
105
106static int check_fsb(unsigned int fsbspeed)
107{
108 int delta;
109 unsigned int f = fsb / 1000;
110
111 delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
112 return (delta < 5);
113}
114
115static int check_powernow(void)
116{
117 struct cpuinfo_x86 *c = cpu_data;
118 unsigned int maxei, eax, ebx, ecx, edx;
119
120 if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) {
121#ifdef MODULE
122 printk (KERN_INFO PFX "This module only works with AMD K7 CPUs\n");
123#endif
124 return 0;
125 }
126
127 /* Get maximum capabilities */
128 maxei = cpuid_eax (0x80000000);
129 if (maxei < 0x80000007) { /* Any powernow info ? */
130#ifdef MODULE
131 printk (KERN_INFO PFX "No powernow capabilities detected\n");
132#endif
133 return 0;
134 }
135
136 if ((c->x86_model == 6) && (c->x86_mask == 0)) {
137 printk (KERN_INFO PFX "K7 660[A0] core detected, enabling errata workarounds\n");
138 have_a0 = 1;
139 }
140
141 cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
142
143 /* Check we can actually do something before we say anything.*/
144 if (!(edx & (1 << 1 | 1 << 2)))
145 return 0;
146
147 printk (KERN_INFO PFX "PowerNOW! Technology present. Can scale: ");
148
149 if (edx & 1 << 1) {
150 printk ("frequency");
151 can_scale_bus=1;
152 }
153
154 if ((edx & (1 << 1 | 1 << 2)) == 0x6)
155 printk (" and ");
156
157 if (edx & 1 << 2) {
158 printk ("voltage");
159 can_scale_vid=1;
160 }
161
162 printk (".\n");
163 return 1;
164}
165
166
167static int get_ranges (unsigned char *pst)
168{
169 unsigned int j;
170 unsigned int speed;
171 u8 fid, vid;
172
173 powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
174 if (!powernow_table)
175 return -ENOMEM;
176 memset(powernow_table, 0, (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));
177
178 for (j=0 ; j < number_scales; j++) {
179 fid = *pst++;
180
181 powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
182 powernow_table[j].index = fid; /* lower 8 bits */
183
184 speed = powernow_table[j].frequency;
185
186 if ((fid_codes[fid] % 10)==5) {
187#ifdef CONFIG_X86_POWERNOW_K7_ACPI
188 if (have_a0 == 1)
189 powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
190#endif
191 }
192
193 if (speed < minimum_speed)
194 minimum_speed = speed;
195 if (speed > maximum_speed)
196 maximum_speed = speed;
197
198 vid = *pst++;
199 powernow_table[j].index |= (vid << 8); /* upper 8 bits */
200
201 dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
202 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
203 fid_codes[fid] % 10, speed/1000, vid,
204 mobile_vid_table[vid]/1000,
205 mobile_vid_table[vid]%1000);
206 }
207 powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
208 powernow_table[number_scales].index = 0;
209
210 return 0;
211}
212
213
214static void change_FID(int fid)
215{
216 union msr_fidvidctl fidvidctl;
217
218 rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
219 if (fidvidctl.bits.FID != fid) {
220 fidvidctl.bits.SGTC = latency;
221 fidvidctl.bits.FID = fid;
222 fidvidctl.bits.VIDC = 0;
223 fidvidctl.bits.FIDC = 1;
224 wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
225 }
226}
227
228
229static void change_VID(int vid)
230{
231 union msr_fidvidctl fidvidctl;
232
233 rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
234 if (fidvidctl.bits.VID != vid) {
235 fidvidctl.bits.SGTC = latency;
236 fidvidctl.bits.VID = vid;
237 fidvidctl.bits.FIDC = 0;
238 fidvidctl.bits.VIDC = 1;
239 wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
240 }
241}
242
243
244static void change_speed (unsigned int index)
245{
246 u8 fid, vid;
247 struct cpufreq_freqs freqs;
248 union msr_fidvidstatus fidvidstatus;
249 int cfid;
250
251 /* fid are the lower 8 bits of the index we stored into
252 * the cpufreq frequency table in powernow_decode_bios,
253 * vid are the upper 8 bits.
254 */
255
256 fid = powernow_table[index].index & 0xFF;
257 vid = (powernow_table[index].index & 0xFF00) >> 8;
258
259 freqs.cpu = 0;
260
261 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
262 cfid = fidvidstatus.bits.CFID;
263 freqs.old = fsb * fid_codes[cfid] / 10;
264
265 freqs.new = powernow_table[index].frequency;
266
267 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
268
269 /* Now do the magic poking into the MSRs. */
270
271 if (have_a0 == 1) /* A0 errata 5 */
272 local_irq_disable();
273
274 if (freqs.old > freqs.new) {
275 /* Going down, so change FID first */
276 change_FID(fid);
277 change_VID(vid);
278 } else {
279 /* Going up, so change VID first */
280 change_VID(vid);
281 change_FID(fid);
282 }
283
284
285 if (have_a0 == 1)
286 local_irq_enable();
287
288 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
289}
290
291
292#ifdef CONFIG_X86_POWERNOW_K7_ACPI
293
294static struct acpi_processor_performance *acpi_processor_perf;
295
296static int powernow_acpi_init(void)
297{
298 int i;
299 int retval = 0;
300 union powernow_acpi_control_t pc;
301
302 if (acpi_processor_perf != NULL && powernow_table != NULL) {
303 retval = -EINVAL;
304 goto err0;
305 }
306
307 acpi_processor_perf = kmalloc(sizeof(struct acpi_processor_performance),
308 GFP_KERNEL);
309
310 if (!acpi_processor_perf) {
311 retval = -ENOMEM;
312 goto err0;
313 }
314
315 memset(acpi_processor_perf, 0, sizeof(struct acpi_processor_performance));
316
317 if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
318 retval = -EIO;
319 goto err1;
320 }
321
322 if (acpi_processor_perf->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
323 retval = -ENODEV;
324 goto err2;
325 }
326
327 if (acpi_processor_perf->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
328 retval = -ENODEV;
329 goto err2;
330 }
331
332 number_scales = acpi_processor_perf->state_count;
333
334 if (number_scales < 2) {
335 retval = -ENODEV;
336 goto err2;
337 }
338
339 powernow_table = kmalloc((number_scales + 1) * (sizeof(struct cpufreq_frequency_table)), GFP_KERNEL);
340 if (!powernow_table) {
341 retval = -ENOMEM;
342 goto err2;
343 }
344
345 memset(powernow_table, 0, ((number_scales + 1) * sizeof(struct cpufreq_frequency_table)));
346
347 pc.val = (unsigned long) acpi_processor_perf->states[0].control;
348 for (i = 0; i < number_scales; i++) {
349 u8 fid, vid;
350 unsigned int speed;
351
352 pc.val = (unsigned long) acpi_processor_perf->states[i].control;
353 dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
354 i,
355 (u32) acpi_processor_perf->states[i].core_frequency,
356 (u32) acpi_processor_perf->states[i].power,
357 (u32) acpi_processor_perf->states[i].transition_latency,
358 (u32) acpi_processor_perf->states[i].control,
359 pc.bits.sgtc);
360
361 vid = pc.bits.vid;
362 fid = pc.bits.fid;
363
364 powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
365 powernow_table[i].index = fid; /* lower 8 bits */
366 powernow_table[i].index |= (vid << 8); /* upper 8 bits */
367
368 speed = powernow_table[i].frequency;
369
370 if ((fid_codes[fid] % 10)==5) {
371 if (have_a0 == 1)
372 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
373 }
374
375 dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
376 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
377 fid_codes[fid] % 10, speed/1000, vid,
378 mobile_vid_table[vid]/1000,
379 mobile_vid_table[vid]%1000);
380
381 if (latency < pc.bits.sgtc)
382 latency = pc.bits.sgtc;
383
384 if (speed < minimum_speed)
385 minimum_speed = speed;
386 if (speed > maximum_speed)
387 maximum_speed = speed;
388 }
389
390 powernow_table[i].frequency = CPUFREQ_TABLE_END;
391 powernow_table[i].index = 0;
392
393 /* notify BIOS that we exist */
394 acpi_processor_notify_smm(THIS_MODULE);
395
396 return 0;
397
398err2:
399 acpi_processor_unregister_performance(acpi_processor_perf, 0);
400err1:
401 kfree(acpi_processor_perf);
402err0:
403 printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
404 acpi_processor_perf = NULL;
405 return retval;
406}
407#else
408static int powernow_acpi_init(void)
409{
410 printk(KERN_INFO PFX "no support for ACPI processor found."
411 " Please recompile your kernel with ACPI processor\n");
412 return -EINVAL;
413}
414#endif
415
416static int powernow_decode_bios (int maxfid, int startvid)
417{
418 struct psb_s *psb;
419 struct pst_s *pst;
420 unsigned int i, j;
421 unsigned char *p;
422 unsigned int etuple;
423 unsigned int ret;
424
425 etuple = cpuid_eax(0x80000001);
426
427 for (i=0xC0000; i < 0xffff0 ; i+=16) {
428
429 p = phys_to_virt(i);
430
431 if (memcmp(p, "AMDK7PNOW!", 10) == 0){
432 dprintk ("Found PSB header at %p\n", p);
433 psb = (struct psb_s *) p;
434 dprintk ("Table version: 0x%x\n", psb->tableversion);
435 if (psb->tableversion != 0x12) {
436 printk (KERN_INFO PFX "Sorry, only v1.2 tables supported right now\n");
437 return -ENODEV;
438 }
439
440 dprintk ("Flags: 0x%x\n", psb->flags);
441 if ((psb->flags & 1)==0) {
442 dprintk ("Mobile voltage regulator\n");
443 } else {
444 dprintk ("Desktop voltage regulator\n");
445 }
446
447 latency = psb->settlingtime;
448 if (latency < 100) {
449 printk (KERN_INFO PFX "BIOS set settling time to %d microseconds."
450 "Should be at least 100. Correcting.\n", latency);
451 latency = 100;
452 }
453 dprintk ("Settling Time: %d microseconds.\n", psb->settlingtime);
454 dprintk ("Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst);
455
456 p += sizeof (struct psb_s);
457
458 pst = (struct pst_s *) p;
459
460 for (i = 0 ; i <psb->numpst; i++) {
461 pst = (struct pst_s *) p;
462 number_scales = pst->numpstates;
463
464 if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
465 (maxfid==pst->maxfid) && (startvid==pst->startvid))
466 {
467 dprintk ("PST:%d (@%p)\n", i, pst);
468 dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
469 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
470
471 ret = get_ranges ((char *) pst + sizeof (struct pst_s));
472 return ret;
473
474 } else {
475 p = (char *) pst + sizeof (struct pst_s);
476 for (j=0 ; j < number_scales; j++)
477 p+=2;
478 }
479 }
480 printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);
481 printk (KERN_INFO PFX "This is indicative of a broken BIOS.\n");
482
483 return -EINVAL;
484 }
485 p++;
486 }
487
488 return -ENODEV;
489}
490
491
492static int powernow_target (struct cpufreq_policy *policy,
493 unsigned int target_freq,
494 unsigned int relation)
495{
496 unsigned int newstate;
497
498 if (cpufreq_frequency_table_target(policy, powernow_table, target_freq, relation, &newstate))
499 return -EINVAL;
500
501 change_speed(newstate);
502
503 return 0;
504}
505
506
507static int powernow_verify (struct cpufreq_policy *policy)
508{
509 return cpufreq_frequency_table_verify(policy, powernow_table);
510}
511
512/*
513 * We use the fact that the bus frequency is somehow
514 * a multiple of 100000/3 khz, then we compute sgtc according
515 * to this multiple.
516 * That way, we match more how AMD thinks all of that work.
517 * We will then get the same kind of behaviour already tested under
518 * the "well-known" other OS.
519 */
520static int __init fixup_sgtc(void)
521{
522 unsigned int sgtc;
523 unsigned int m;
524
525 m = fsb / 3333;
526 if ((m % 10) >= 5)
527 m += 5;
528
529 m /= 10;
530
531 sgtc = 100 * m * latency;
532 sgtc = sgtc / 3;
533 if (sgtc > 0xfffff) {
534 printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
535 sgtc = 0xfffff;
536 }
537 return sgtc;
538}
539
540static unsigned int powernow_get(unsigned int cpu)
541{
542 union msr_fidvidstatus fidvidstatus;
543 unsigned int cfid;
544
545 if (cpu)
546 return 0;
547 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
548 cfid = fidvidstatus.bits.CFID;
549
550 return (fsb * fid_codes[cfid] / 10);
551}
552
553
554static int __init acer_cpufreq_pst(struct dmi_system_id *d)
555{
556 printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident);
557 printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
558 printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n");
559 return 0;
560}
561
562/*
563 * Some Athlon laptops have really fucked PST tables.
564 * A BIOS update is all that can save them.
565 * Mention this, and disable cpufreq.
566 */
567static struct dmi_system_id __initdata powernow_dmi_table[] = {
568 {
569 .callback = acer_cpufreq_pst,
570 .ident = "Acer Aspire",
571 .matches = {
572 DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
573 DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
574 },
575 },
576 { }
577};
578
579static int __init powernow_cpu_init (struct cpufreq_policy *policy)
580{
581 union msr_fidvidstatus fidvidstatus;
582 int result;
583
584 if (policy->cpu != 0)
585 return -ENODEV;
586
587 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
588
589 /* A K7 with powernow technology is set to max frequency by BIOS */
590 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
591 if (!fsb) {
592 printk(KERN_WARNING PFX "can not determine bus frequency\n");
593 return -EINVAL;
594 }
595 dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
596
597 if (dmi_check_system(powernow_dmi_table) || acpi_force) {
598 printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
599 result = powernow_acpi_init();
600 } else {
601 result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);
602 if (result) {
603 printk (KERN_INFO PFX "Trying ACPI perflib\n");
604 maximum_speed = 0;
605 minimum_speed = -1;
606 latency = 0;
607 result = powernow_acpi_init();
608 if (result) {
609 printk (KERN_INFO PFX "ACPI and legacy methods failed\n");
610 printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n");
611 }
612 } else {
613 /* SGTC use the bus clock as timer */
614 latency = fixup_sgtc();
615 printk(KERN_INFO PFX "SGTC: %d\n", latency);
616 }
617 }
618
619 if (result)
620 return result;
621
622 printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
623 minimum_speed/1000, maximum_speed/1000);
624
625 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
626
627 policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency);
628
629 policy->cur = powernow_get(0);
630
631 cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);
632
633 return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
634}
635
636static int powernow_cpu_exit (struct cpufreq_policy *policy) {
637 cpufreq_frequency_table_put_attr(policy->cpu);
638
639#ifdef CONFIG_X86_POWERNOW_K7_ACPI
640 if (acpi_processor_perf) {
641 acpi_processor_unregister_performance(acpi_processor_perf, 0);
642 kfree(acpi_processor_perf);
643 }
644#endif
645
646 if (powernow_table)
647 kfree(powernow_table);
648
649 return 0;
650}
651
652static struct freq_attr* powernow_table_attr[] = {
653 &cpufreq_freq_attr_scaling_available_freqs,
654 NULL,
655};
656
657static struct cpufreq_driver powernow_driver = {
658 .verify = powernow_verify,
659 .target = powernow_target,
660 .get = powernow_get,
661 .init = powernow_cpu_init,
662 .exit = powernow_cpu_exit,
663 .name = "powernow-k7",
664 .owner = THIS_MODULE,
665 .attr = powernow_table_attr,
666};
667
668static int __init powernow_init (void)
669{
670 if (check_powernow()==0)
671 return -ENODEV;
672 return cpufreq_register_driver(&powernow_driver);
673}
674
675
676static void __exit powernow_exit (void)
677{
678 cpufreq_unregister_driver(&powernow_driver);
679}
680
681module_param(acpi_force, int, 0444);
682MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
683
684MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
685MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
686MODULE_LICENSE ("GPL");
687
688late_initcall(powernow_init);
689module_exit(powernow_exit);
690
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.h b/arch/i386/kernel/cpu/cpufreq/powernow-k7.h
new file mode 100644
index 000000000000..f8a63b3664e3
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.h
@@ -0,0 +1,44 @@
1/*
2 * $Id: powernow-k7.h,v 1.2 2003/02/10 18:26:01 davej Exp $
3 * (C) 2003 Dave Jones.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 *
7 * AMD-specific information
8 *
9 */
10
11union msr_fidvidctl {
12 struct {
13 unsigned FID:5, // 4:0
14 reserved1:3, // 7:5
15 VID:5, // 12:8
16 reserved2:3, // 15:13
17 FIDC:1, // 16
18 VIDC:1, // 17
19 reserved3:2, // 19:18
20 FIDCHGRATIO:1, // 20
21 reserved4:11, // 31-21
22 SGTC:20, // 32:51
23 reserved5:12; // 63:52
24 } bits;
25 unsigned long long val;
26};
27
28union msr_fidvidstatus {
29 struct {
30 unsigned CFID:5, // 4:0
31 reserved1:3, // 7:5
32 SFID:5, // 12:8
33 reserved2:3, // 15:13
34 MFID:5, // 20:16
35 reserved3:11, // 31:21
36 CVID:5, // 36:32
37 reserved4:3, // 39:37
38 SVID:5, // 44:40
39 reserved5:3, // 47:45
40 MVID:5, // 52:48
41 reserved6:11; // 63:53
42 } bits;
43 unsigned long long val;
44};
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
new file mode 100644
index 000000000000..a65ff7e32e5d
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -0,0 +1,1135 @@
1/*
2 * (c) 2003, 2004 Advanced Micro Devices, Inc.
3 * Your use of this code is subject to the terms and conditions of the
4 * GNU general public license version 2. See "COPYING" or
5 * http://www.gnu.org/licenses/gpl.html
6 *
7 * Support : paul.devriendt@amd.com
8 *
9 * Based on the powernow-k7.c module written by Dave Jones.
10 * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
11 * (C) 2004 Dominik Brodowski <linux@brodo.de>
12 * (C) 2004 Pavel Machek <pavel@suse.cz>
13 * Licensed under the terms of the GNU GPL License version 2.
14 * Based upon datasheets & sample CPUs kindly provided by AMD.
15 *
16 * Valuable input gratefully received from Dave Jones, Pavel Machek,
17 * Dominik Brodowski, and others.
18 * Processor information obtained from Chapter 9 (Power and Thermal Management)
19 * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
20 * Opteron Processors" available for download from www.amd.com
21 *
22 * Tables for specific CPUs can be infrerred from
23 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
24 */
25
26#include <linux/kernel.h>
27#include <linux/smp.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/cpufreq.h>
31#include <linux/slab.h>
32#include <linux/string.h>
33
34#include <asm/msr.h>
35#include <asm/io.h>
36#include <asm/delay.h>
37
38#ifdef CONFIG_X86_POWERNOW_K8_ACPI
39#include <linux/acpi.h>
40#include <acpi/processor.h>
41#endif
42
43#define PFX "powernow-k8: "
44#define BFX PFX "BIOS error: "
45#define VERSION "version 1.00.09e"
46#include "powernow-k8.h"
47
48/* serialize freq changes */
49static DECLARE_MUTEX(fidvid_sem);
50
51static struct powernow_k8_data *powernow_data[NR_CPUS];
52
53/* Return a frequency in MHz, given an input fid */
54static u32 find_freq_from_fid(u32 fid)
55{
56 return 800 + (fid * 100);
57}
58
59/* Return a frequency in KHz, given an input fid */
60static u32 find_khz_freq_from_fid(u32 fid)
61{
62 return 1000 * find_freq_from_fid(fid);
63}
64
65/* Return a voltage in miliVolts, given an input vid */
66static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
67{
68 return 1550-vid*25;
69}
70
71/* Return the vco fid for an input fid
72 *
73 * Each "low" fid has corresponding "high" fid, and you can get to "low" fids
74 * only from corresponding high fids. This returns "high" fid corresponding to
75 * "low" one.
76 */
77static u32 convert_fid_to_vco_fid(u32 fid)
78{
79 if (fid < HI_FID_TABLE_BOTTOM) {
80 return 8 + (2 * fid);
81 } else {
82 return fid;
83 }
84}
85
86/*
87 * Return 1 if the pending bit is set. Unless we just instructed the processor
88 * to transition to a new state, seeing this bit set is really bad news.
89 */
90static int pending_bit_stuck(void)
91{
92 u32 lo, hi;
93
94 rdmsr(MSR_FIDVID_STATUS, lo, hi);
95 return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
96}
97
98/*
99 * Update the global current fid / vid values from the status msr.
100 * Returns 1 on error.
101 */
102static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
103{
104 u32 lo, hi;
105 u32 i = 0;
106
107 lo = MSR_S_LO_CHANGE_PENDING;
108 while (lo & MSR_S_LO_CHANGE_PENDING) {
109 if (i++ > 0x1000000) {
110 printk(KERN_ERR PFX "detected change pending stuck\n");
111 return 1;
112 }
113 rdmsr(MSR_FIDVID_STATUS, lo, hi);
114 }
115
116 data->currvid = hi & MSR_S_HI_CURRENT_VID;
117 data->currfid = lo & MSR_S_LO_CURRENT_FID;
118
119 return 0;
120}
121
122/* the isochronous relief time */
123static void count_off_irt(struct powernow_k8_data *data)
124{
125 udelay((1 << data->irt) * 10);
126 return;
127}
128
129/* the voltage stabalization time */
130static void count_off_vst(struct powernow_k8_data *data)
131{
132 udelay(data->vstable * VST_UNITS_20US);
133 return;
134}
135
136/* need to init the control msr to a safe value (for each cpu) */
137static void fidvid_msr_init(void)
138{
139 u32 lo, hi;
140 u8 fid, vid;
141
142 rdmsr(MSR_FIDVID_STATUS, lo, hi);
143 vid = hi & MSR_S_HI_CURRENT_VID;
144 fid = lo & MSR_S_LO_CURRENT_FID;
145 lo = fid | (vid << MSR_C_LO_VID_SHIFT);
146 hi = MSR_C_HI_STP_GNT_BENIGN;
147 dprintk("cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi);
148 wrmsr(MSR_FIDVID_CTL, lo, hi);
149}
150
151
152/* write the new fid value along with the other control fields to the msr */
153static int write_new_fid(struct powernow_k8_data *data, u32 fid)
154{
155 u32 lo;
156 u32 savevid = data->currvid;
157
158 if ((fid & INVALID_FID_MASK) || (data->currvid & INVALID_VID_MASK)) {
159 printk(KERN_ERR PFX "internal error - overflow on fid write\n");
160 return 1;
161 }
162
163 lo = fid | (data->currvid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
164
165 dprintk("writing fid 0x%x, lo 0x%x, hi 0x%x\n",
166 fid, lo, data->plllock * PLL_LOCK_CONVERSION);
167
168 wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION);
169
170 if (query_current_values_with_pending_wait(data))
171 return 1;
172
173 count_off_irt(data);
174
175 if (savevid != data->currvid) {
176 printk(KERN_ERR PFX "vid change on fid trans, old 0x%x, new 0x%x\n",
177 savevid, data->currvid);
178 return 1;
179 }
180
181 if (fid != data->currfid) {
182 printk(KERN_ERR PFX "fid trans failed, fid 0x%x, curr 0x%x\n", fid,
183 data->currfid);
184 return 1;
185 }
186
187 return 0;
188}
189
190/* Write a new vid to the hardware */
191static int write_new_vid(struct powernow_k8_data *data, u32 vid)
192{
193 u32 lo;
194 u32 savefid = data->currfid;
195
196 if ((data->currfid & INVALID_FID_MASK) || (vid & INVALID_VID_MASK)) {
197 printk(KERN_ERR PFX "internal error - overflow on vid write\n");
198 return 1;
199 }
200
201 lo = data->currfid | (vid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
202
203 dprintk("writing vid 0x%x, lo 0x%x, hi 0x%x\n",
204 vid, lo, STOP_GRANT_5NS);
205
206 wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
207
208 if (query_current_values_with_pending_wait(data))
209 return 1;
210
211 if (savefid != data->currfid) {
212 printk(KERN_ERR PFX "fid changed on vid trans, old 0x%x new 0x%x\n",
213 savefid, data->currfid);
214 return 1;
215 }
216
217 if (vid != data->currvid) {
218 printk(KERN_ERR PFX "vid trans failed, vid 0x%x, curr 0x%x\n", vid,
219 data->currvid);
220 return 1;
221 }
222
223 return 0;
224}
225
226/*
227 * Reduce the vid by the max of step or reqvid.
228 * Decreasing vid codes represent increasing voltages:
229 * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off.
230 */
231static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid, u32 step)
232{
233 if ((data->currvid - reqvid) > step)
234 reqvid = data->currvid - step;
235
236 if (write_new_vid(data, reqvid))
237 return 1;
238
239 count_off_vst(data);
240
241 return 0;
242}
243
244/* Change the fid and vid, by the 3 phases. */
245static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid)
246{
247 if (core_voltage_pre_transition(data, reqvid))
248 return 1;
249
250 if (core_frequency_transition(data, reqfid))
251 return 1;
252
253 if (core_voltage_post_transition(data, reqvid))
254 return 1;
255
256 if (query_current_values_with_pending_wait(data))
257 return 1;
258
259 if ((reqfid != data->currfid) || (reqvid != data->currvid)) {
260 printk(KERN_ERR PFX "failed (cpu%d): req 0x%x 0x%x, curr 0x%x 0x%x\n",
261 smp_processor_id(),
262 reqfid, reqvid, data->currfid, data->currvid);
263 return 1;
264 }
265
266 dprintk("transitioned (cpu%d): new fid 0x%x, vid 0x%x\n",
267 smp_processor_id(), data->currfid, data->currvid);
268
269 return 0;
270}
271
272/* Phase 1 - core voltage transition ... setup voltage */
273static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid)
274{
275 u32 rvosteps = data->rvo;
276 u32 savefid = data->currfid;
277
278 dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
279 smp_processor_id(),
280 data->currfid, data->currvid, reqvid, data->rvo);
281
282 while (data->currvid > reqvid) {
283 dprintk("ph1: curr 0x%x, req vid 0x%x\n",
284 data->currvid, reqvid);
285 if (decrease_vid_code_by_step(data, reqvid, data->vidmvs))
286 return 1;
287 }
288
289 while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
290 if (data->currvid == 0) {
291 rvosteps = 0;
292 } else {
293 dprintk("ph1: changing vid for rvo, req 0x%x\n",
294 data->currvid - 1);
295 if (decrease_vid_code_by_step(data, data->currvid - 1, 1))
296 return 1;
297 rvosteps--;
298 }
299 }
300
301 if (query_current_values_with_pending_wait(data))
302 return 1;
303
304 if (savefid != data->currfid) {
305 printk(KERN_ERR PFX "ph1 err, currfid changed 0x%x\n", data->currfid);
306 return 1;
307 }
308
309 dprintk("ph1 complete, currfid 0x%x, currvid 0x%x\n",
310 data->currfid, data->currvid);
311
312 return 0;
313}
314
315/* Phase 2 - core frequency transition */
316static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
317{
318 u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid;
319
320 if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
321 printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n",
322 reqfid, data->currfid);
323 return 1;
324 }
325
326 if (data->currfid == reqfid) {
327 printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n", data->currfid);
328 return 0;
329 }
330
331 dprintk("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n",
332 smp_processor_id(),
333 data->currfid, data->currvid, reqfid);
334
335 vcoreqfid = convert_fid_to_vco_fid(reqfid);
336 vcocurrfid = convert_fid_to_vco_fid(data->currfid);
337 vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
338 : vcoreqfid - vcocurrfid;
339
340 while (vcofiddiff > 2) {
341 if (reqfid > data->currfid) {
342 if (data->currfid > LO_FID_TABLE_TOP) {
343 if (write_new_fid(data, data->currfid + 2)) {
344 return 1;
345 }
346 } else {
347 if (write_new_fid
348 (data, 2 + convert_fid_to_vco_fid(data->currfid))) {
349 return 1;
350 }
351 }
352 } else {
353 if (write_new_fid(data, data->currfid - 2))
354 return 1;
355 }
356
357 vcocurrfid = convert_fid_to_vco_fid(data->currfid);
358 vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
359 : vcoreqfid - vcocurrfid;
360 }
361
362 if (write_new_fid(data, reqfid))
363 return 1;
364
365 if (query_current_values_with_pending_wait(data))
366 return 1;
367
368 if (data->currfid != reqfid) {
369 printk(KERN_ERR PFX
370 "ph2: mismatch, failed fid transition, curr 0x%x, req 0x%x\n",
371 data->currfid, reqfid);
372 return 1;
373 }
374
375 if (savevid != data->currvid) {
376 printk(KERN_ERR PFX "ph2: vid changed, save 0x%x, curr 0x%x\n",
377 savevid, data->currvid);
378 return 1;
379 }
380
381 dprintk("ph2 complete, currfid 0x%x, currvid 0x%x\n",
382 data->currfid, data->currvid);
383
384 return 0;
385}
386
387/* Phase 3 - core voltage transition flow ... jump to the final vid. */
388static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid)
389{
390 u32 savefid = data->currfid;
391 u32 savereqvid = reqvid;
392
393 dprintk("ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n",
394 smp_processor_id(),
395 data->currfid, data->currvid);
396
397 if (reqvid != data->currvid) {
398 if (write_new_vid(data, reqvid))
399 return 1;
400
401 if (savefid != data->currfid) {
402 printk(KERN_ERR PFX
403 "ph3: bad fid change, save 0x%x, curr 0x%x\n",
404 savefid, data->currfid);
405 return 1;
406 }
407
408 if (data->currvid != reqvid) {
409 printk(KERN_ERR PFX
410 "ph3: failed vid transition\n, req 0x%x, curr 0x%x",
411 reqvid, data->currvid);
412 return 1;
413 }
414 }
415
416 if (query_current_values_with_pending_wait(data))
417 return 1;
418
419 if (savereqvid != data->currvid) {
420 dprintk("ph3 failed, currvid 0x%x\n", data->currvid);
421 return 1;
422 }
423
424 if (savefid != data->currfid) {
425 dprintk("ph3 failed, currfid changed 0x%x\n",
426 data->currfid);
427 return 1;
428 }
429
430 dprintk("ph3 complete, currfid 0x%x, currvid 0x%x\n",
431 data->currfid, data->currvid);
432
433 return 0;
434}
435
436static int check_supported_cpu(unsigned int cpu)
437{
438 cpumask_t oldmask = CPU_MASK_ALL;
439 u32 eax, ebx, ecx, edx;
440 unsigned int rc = 0;
441
442 oldmask = current->cpus_allowed;
443 set_cpus_allowed(current, cpumask_of_cpu(cpu));
444 schedule();
445
446 if (smp_processor_id() != cpu) {
447 printk(KERN_ERR "limiting to cpu %u failed\n", cpu);
448 goto out;
449 }
450
451 if (current_cpu_data.x86_vendor != X86_VENDOR_AMD)
452 goto out;
453
454 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
455 if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
456 ((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
457 ((eax & CPUID_XMOD) > CPUID_XMOD_REV_E)) {
458 printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
459 goto out;
460 }
461
462 eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
463 if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
464 printk(KERN_INFO PFX
465 "No frequency change capabilities detected\n");
466 goto out;
467 }
468
469 cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
470 if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
471 printk(KERN_INFO PFX "Power state transitions not supported\n");
472 goto out;
473 }
474
475 rc = 1;
476
477out:
478 set_cpus_allowed(current, oldmask);
479 schedule();
480 return rc;
481
482}
483
484static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid)
485{
486 unsigned int j;
487 u8 lastfid = 0xff;
488
489 for (j = 0; j < data->numps; j++) {
490 if (pst[j].vid > LEAST_VID) {
491 printk(KERN_ERR PFX "vid %d invalid : 0x%x\n", j, pst[j].vid);
492 return -EINVAL;
493 }
494 if (pst[j].vid < data->rvo) { /* vid + rvo >= 0 */
495 printk(KERN_ERR BFX "0 vid exceeded with pstate %d\n", j);
496 return -ENODEV;
497 }
498 if (pst[j].vid < maxvid + data->rvo) { /* vid + rvo >= maxvid */
499 printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j);
500 return -ENODEV;
501 }
502 if ((pst[j].fid > MAX_FID)
503 || (pst[j].fid & 1)
504 || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
505 /* Only first fid is allowed to be in "low" range */
506 printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
507 return -EINVAL;
508 }
509 if (pst[j].fid < lastfid)
510 lastfid = pst[j].fid;
511 }
512 if (lastfid & 1) {
513 printk(KERN_ERR PFX "lastfid invalid\n");
514 return -EINVAL;
515 }
516 if (lastfid > LO_FID_TABLE_TOP)
517 printk(KERN_INFO PFX "first fid not from lo freq table\n");
518
519 return 0;
520}
521
522static void print_basics(struct powernow_k8_data *data)
523{
524 int j;
525 for (j = 0; j < data->numps; j++) {
526 if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID)
527 printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j,
528 data->powernow_table[j].index & 0xff,
529 data->powernow_table[j].frequency/1000,
530 data->powernow_table[j].index >> 8,
531 find_millivolts_from_vid(data, data->powernow_table[j].index >> 8));
532 }
533 if (data->batps)
534 printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
535}
536
537static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid)
538{
539 struct cpufreq_frequency_table *powernow_table;
540 unsigned int j;
541
542 if (data->batps) { /* use ACPI support to get full speed on mains power */
543 printk(KERN_WARNING PFX "Only %d pstates usable (use ACPI driver for full range\n", data->batps);
544 data->numps = data->batps;
545 }
546
547 for ( j=1; j<data->numps; j++ ) {
548 if (pst[j-1].fid >= pst[j].fid) {
549 printk(KERN_ERR PFX "PST out of sequence\n");
550 return -EINVAL;
551 }
552 }
553
554 if (data->numps < 2) {
555 printk(KERN_ERR PFX "no p states to transition\n");
556 return -ENODEV;
557 }
558
559 if (check_pst_table(data, pst, maxvid))
560 return -EINVAL;
561
562 powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table)
563 * (data->numps + 1)), GFP_KERNEL);
564 if (!powernow_table) {
565 printk(KERN_ERR PFX "powernow_table memory alloc failure\n");
566 return -ENOMEM;
567 }
568
569 for (j = 0; j < data->numps; j++) {
570 powernow_table[j].index = pst[j].fid; /* lower 8 bits */
571 powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */
572 powernow_table[j].frequency = find_khz_freq_from_fid(pst[j].fid);
573 }
574 powernow_table[data->numps].frequency = CPUFREQ_TABLE_END;
575 powernow_table[data->numps].index = 0;
576
577 if (query_current_values_with_pending_wait(data)) {
578 kfree(powernow_table);
579 return -EIO;
580 }
581
582 dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
583 data->powernow_table = powernow_table;
584 print_basics(data);
585
586 for (j = 0; j < data->numps; j++)
587 if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid))
588 return 0;
589
590 dprintk("currfid/vid do not match PST, ignoring\n");
591 return 0;
592}
593
594/* Find and validate the PSB/PST table in BIOS. */
595static int find_psb_table(struct powernow_k8_data *data)
596{
597 struct psb_s *psb;
598 unsigned int i;
599 u32 mvs;
600 u8 maxvid;
601 u32 cpst = 0;
602 u32 thiscpuid;
603
604 for (i = 0xc0000; i < 0xffff0; i += 0x10) {
605 /* Scan BIOS looking for the signature. */
606 /* It can not be at ffff0 - it is too big. */
607
608 psb = phys_to_virt(i);
609 if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0)
610 continue;
611
612 dprintk("found PSB header at 0x%p\n", psb);
613
614 dprintk("table vers: 0x%x\n", psb->tableversion);
615 if (psb->tableversion != PSB_VERSION_1_4) {
616 printk(KERN_INFO BFX "PSB table is not v1.4\n");
617 return -ENODEV;
618 }
619
620 dprintk("flags: 0x%x\n", psb->flags1);
621 if (psb->flags1) {
622 printk(KERN_ERR BFX "unknown flags\n");
623 return -ENODEV;
624 }
625
626 data->vstable = psb->vstable;
627 dprintk("voltage stabilization time: %d(*20us)\n", data->vstable);
628
629 dprintk("flags2: 0x%x\n", psb->flags2);
630 data->rvo = psb->flags2 & 3;
631 data->irt = ((psb->flags2) >> 2) & 3;
632 mvs = ((psb->flags2) >> 4) & 3;
633 data->vidmvs = 1 << mvs;
634 data->batps = ((psb->flags2) >> 6) & 3;
635
636 dprintk("ramp voltage offset: %d\n", data->rvo);
637 dprintk("isochronous relief time: %d\n", data->irt);
638 dprintk("maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs);
639
640 dprintk("numpst: 0x%x\n", psb->num_tables);
641 cpst = psb->num_tables;
642 if ((psb->cpuid == 0x00000fc0) || (psb->cpuid == 0x00000fe0) ){
643 thiscpuid = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
644 if ((thiscpuid == 0x00000fc0) || (thiscpuid == 0x00000fe0) ) {
645 cpst = 1;
646 }
647 }
648 if (cpst != 1) {
649 printk(KERN_ERR BFX "numpst must be 1\n");
650 return -ENODEV;
651 }
652
653 data->plllock = psb->plllocktime;
654 dprintk("plllocktime: 0x%x (units 1us)\n", psb->plllocktime);
655 dprintk("maxfid: 0x%x\n", psb->maxfid);
656 dprintk("maxvid: 0x%x\n", psb->maxvid);
657 maxvid = psb->maxvid;
658
659 data->numps = psb->numps;
660 dprintk("numpstates: 0x%x\n", data->numps);
661 return fill_powernow_table(data, (struct pst_s *)(psb+1), maxvid);
662 }
663 /*
664 * If you see this message, complain to BIOS manufacturer. If
665 * he tells you "we do not support Linux" or some similar
666 * nonsense, remember that Windows 2000 uses the same legacy
667 * mechanism that the old Linux PSB driver uses. Tell them it
668 * is broken with Windows 2000.
669 *
670 * The reference to the AMD documentation is chapter 9 in the
671 * BIOS and Kernel Developer's Guide, which is available on
672 * www.amd.com
673 */
674 printk(KERN_ERR PFX "BIOS error - no PSB\n");
675 return -ENODEV;
676}
677
678#ifdef CONFIG_X86_POWERNOW_K8_ACPI
679static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
680{
681 if (!data->acpi_data.state_count)
682 return;
683
684 data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK;
685 data->rvo = (data->acpi_data.states[index].control >> RVO_SHIFT) & RVO_MASK;
686 data->plllock = (data->acpi_data.states[index].control >> PLL_L_SHIFT) & PLL_L_MASK;
687 data->vidmvs = 1 << ((data->acpi_data.states[index].control >> MVS_SHIFT) & MVS_MASK);
688 data->vstable = (data->acpi_data.states[index].control >> VST_SHIFT) & VST_MASK;
689}
690
691static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
692{
693 int i;
694 int cntlofreq = 0;
695 struct cpufreq_frequency_table *powernow_table;
696
697 if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
698 dprintk("register performance failed\n");
699 return -EIO;
700 }
701
702 /* verify the data contained in the ACPI structures */
703 if (data->acpi_data.state_count <= 1) {
704 dprintk("No ACPI P-States\n");
705 goto err_out;
706 }
707
708 if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
709 (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
710 dprintk("Invalid control/status registers (%x - %x)\n",
711 data->acpi_data.control_register.space_id,
712 data->acpi_data.status_register.space_id);
713 goto err_out;
714 }
715
716 /* fill in data->powernow_table */
717 powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table)
718 * (data->acpi_data.state_count + 1)), GFP_KERNEL);
719 if (!powernow_table) {
720 dprintk("powernow_table memory alloc failure\n");
721 goto err_out;
722 }
723
724 for (i = 0; i < data->acpi_data.state_count; i++) {
725 u32 fid = data->acpi_data.states[i].control & FID_MASK;
726 u32 vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK;
727
728 dprintk(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid);
729
730 powernow_table[i].index = fid; /* lower 8 bits */
731 powernow_table[i].index |= (vid << 8); /* upper 8 bits */
732 powernow_table[i].frequency = find_khz_freq_from_fid(fid);
733
734 /* verify frequency is OK */
735 if ((powernow_table[i].frequency > (MAX_FREQ * 1000)) ||
736 (powernow_table[i].frequency < (MIN_FREQ * 1000))) {
737 dprintk("invalid freq %u kHz, ignoring\n", powernow_table[i].frequency);
738 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
739 continue;
740 }
741
742 /* verify voltage is OK - BIOSs are using "off" to indicate invalid */
743 if (vid == 0x1f) {
744 dprintk("invalid vid %u, ignoring\n", vid);
745 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
746 continue;
747 }
748
749 if (fid < HI_FID_TABLE_BOTTOM) {
750 if (cntlofreq) {
751 /* if both entries are the same, ignore this
752 * one...
753 */
754 if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
755 (powernow_table[i].index != powernow_table[cntlofreq].index)) {
756 printk(KERN_ERR PFX "Too many lo freq table entries\n");
757 goto err_out_mem;
758 }
759
760 dprintk("double low frequency table entry, ignoring it.\n");
761 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
762 continue;
763 } else
764 cntlofreq = i;
765 }
766
767 if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
768 printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n",
769 powernow_table[i].frequency,
770 (unsigned int) (data->acpi_data.states[i].core_frequency * 1000));
771 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
772 continue;
773 }
774 }
775
776 powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
777 powernow_table[data->acpi_data.state_count].index = 0;
778 data->powernow_table = powernow_table;
779
780 /* fill in data */
781 data->numps = data->acpi_data.state_count;
782 print_basics(data);
783 powernow_k8_acpi_pst_values(data, 0);
784
785 /* notify BIOS that we exist */
786 acpi_processor_notify_smm(THIS_MODULE);
787
788 return 0;
789
790err_out_mem:
791 kfree(powernow_table);
792
793err_out:
794 acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
795
796 /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
797 data->acpi_data.state_count = 0;
798
799 return -ENODEV;
800}
801
802static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
803{
804 if (data->acpi_data.state_count)
805 acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
806}
807
808#else
809static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { return -ENODEV; }
810static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { return; }
811static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { return; }
812#endif /* CONFIG_X86_POWERNOW_K8_ACPI */
813
814/* Take a frequency, and issue the fid/vid transition command */
815static int transition_frequency(struct powernow_k8_data *data, unsigned int index)
816{
817 u32 fid;
818 u32 vid;
819 int res;
820 struct cpufreq_freqs freqs;
821
822 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
823
824 /* fid are the lower 8 bits of the index we stored into
825 * the cpufreq frequency table in find_psb_table, vid are
826 * the upper 8 bits.
827 */
828
829 fid = data->powernow_table[index].index & 0xFF;
830 vid = (data->powernow_table[index].index & 0xFF00) >> 8;
831
832 dprintk("table matched fid 0x%x, giving vid 0x%x\n", fid, vid);
833
834 if (query_current_values_with_pending_wait(data))
835 return 1;
836
837 if ((data->currvid == vid) && (data->currfid == fid)) {
838 dprintk("target matches current values (fid 0x%x, vid 0x%x)\n",
839 fid, vid);
840 return 0;
841 }
842
843 if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
844 printk("ignoring illegal change in lo freq table-%x to 0x%x\n",
845 data->currfid, fid);
846 return 1;
847 }
848
849 dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
850 smp_processor_id(), fid, vid);
851
852 freqs.cpu = data->cpu;
853
854 freqs.old = find_khz_freq_from_fid(data->currfid);
855 freqs.new = find_khz_freq_from_fid(fid);
856 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
857
858 down(&fidvid_sem);
859 res = transition_fid_vid(data, fid, vid);
860 up(&fidvid_sem);
861
862 freqs.new = find_khz_freq_from_fid(data->currfid);
863 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
864
865 return res;
866}
867
868/* Driver entry point to switch to the target frequency */
869static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
870{
871 cpumask_t oldmask = CPU_MASK_ALL;
872 struct powernow_k8_data *data = powernow_data[pol->cpu];
873 u32 checkfid = data->currfid;
874 u32 checkvid = data->currvid;
875 unsigned int newstate;
876 int ret = -EIO;
877
878 /* only run on specific CPU from here on */
879 oldmask = current->cpus_allowed;
880 set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
881 schedule();
882
883 if (smp_processor_id() != pol->cpu) {
884 printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
885 goto err_out;
886 }
887
888 if (pending_bit_stuck()) {
889 printk(KERN_ERR PFX "failing targ, change pending bit set\n");
890 goto err_out;
891 }
892
893 dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
894 pol->cpu, targfreq, pol->min, pol->max, relation);
895
896 if (query_current_values_with_pending_wait(data)) {
897 ret = -EIO;
898 goto err_out;
899 }
900
901 dprintk("targ: curr fid 0x%x, vid 0x%x\n",
902 data->currfid, data->currvid);
903
904 if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
905 printk(KERN_ERR PFX
906 "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
907 checkfid, data->currfid, checkvid, data->currvid);
908 }
909
910 if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
911 goto err_out;
912
913 powernow_k8_acpi_pst_values(data, newstate);
914
915 if (transition_frequency(data, newstate)) {
916 printk(KERN_ERR PFX "transition frequency failed\n");
917 ret = 1;
918 goto err_out;
919 }
920
921 pol->cur = find_khz_freq_from_fid(data->currfid);
922 ret = 0;
923
924err_out:
925 set_cpus_allowed(current, oldmask);
926 schedule();
927
928 return ret;
929}
930
931/* Driver entry point to verify the policy and range of frequencies */
932static int powernowk8_verify(struct cpufreq_policy *pol)
933{
934 struct powernow_k8_data *data = powernow_data[pol->cpu];
935
936 return cpufreq_frequency_table_verify(pol, data->powernow_table);
937}
938
939/* per CPU init entry point to the driver */
940static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
941{
942 struct powernow_k8_data *data;
943 cpumask_t oldmask = CPU_MASK_ALL;
944 int rc;
945
946 if (!check_supported_cpu(pol->cpu))
947 return -ENODEV;
948
949 data = kmalloc(sizeof(struct powernow_k8_data), GFP_KERNEL);
950 if (!data) {
951 printk(KERN_ERR PFX "unable to alloc powernow_k8_data");
952 return -ENOMEM;
953 }
954 memset(data,0,sizeof(struct powernow_k8_data));
955
956 data->cpu = pol->cpu;
957
958 if (powernow_k8_cpu_init_acpi(data)) {
959 /*
960 * Use the PSB BIOS structure. This is only availabe on
961 * an UP version, and is deprecated by AMD.
962 */
963
964 if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
965 printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
966 kfree(data);
967 return -ENODEV;
968 }
969 if (pol->cpu != 0) {
970 printk(KERN_ERR PFX "init not cpu 0\n");
971 kfree(data);
972 return -ENODEV;
973 }
974 rc = find_psb_table(data);
975 if (rc) {
976 kfree(data);
977 return -ENODEV;
978 }
979 }
980
981 /* only run on specific CPU from here on */
982 oldmask = current->cpus_allowed;
983 set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
984 schedule();
985
986 if (smp_processor_id() != pol->cpu) {
987 printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
988 goto err_out;
989 }
990
991 if (pending_bit_stuck()) {
992 printk(KERN_ERR PFX "failing init, change pending bit set\n");
993 goto err_out;
994 }
995
996 if (query_current_values_with_pending_wait(data))
997 goto err_out;
998
999 fidvid_msr_init();
1000
1001 /* run on any CPU again */
1002 set_cpus_allowed(current, oldmask);
1003 schedule();
1004
1005 pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
1006
1007 /* Take a crude guess here.
1008 * That guess was in microseconds, so multiply with 1000 */
1009 pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
1010 + (3 * (1 << data->irt) * 10)) * 1000;
1011
1012 pol->cur = find_khz_freq_from_fid(data->currfid);
1013 dprintk("policy current frequency %d kHz\n", pol->cur);
1014
1015 /* min/max the cpu is capable of */
1016 if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) {
1017 printk(KERN_ERR PFX "invalid powernow_table\n");
1018 powernow_k8_cpu_exit_acpi(data);
1019 kfree(data->powernow_table);
1020 kfree(data);
1021 return -EINVAL;
1022 }
1023
1024 cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
1025
1026 printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
1027 data->currfid, data->currvid);
1028
1029 powernow_data[pol->cpu] = data;
1030
1031 return 0;
1032
1033err_out:
1034 set_cpus_allowed(current, oldmask);
1035 schedule();
1036 powernow_k8_cpu_exit_acpi(data);
1037
1038 kfree(data);
1039 return -ENODEV;
1040}
1041
1042static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
1043{
1044 struct powernow_k8_data *data = powernow_data[pol->cpu];
1045
1046 if (!data)
1047 return -EINVAL;
1048
1049 powernow_k8_cpu_exit_acpi(data);
1050
1051 cpufreq_frequency_table_put_attr(pol->cpu);
1052
1053 kfree(data->powernow_table);
1054 kfree(data);
1055
1056 return 0;
1057}
1058
1059static unsigned int powernowk8_get (unsigned int cpu)
1060{
1061 struct powernow_k8_data *data = powernow_data[cpu];
1062 cpumask_t oldmask = current->cpus_allowed;
1063 unsigned int khz = 0;
1064
1065 set_cpus_allowed(current, cpumask_of_cpu(cpu));
1066 if (smp_processor_id() != cpu) {
1067 printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
1068 set_cpus_allowed(current, oldmask);
1069 return 0;
1070 }
1071 preempt_disable();
1072
1073 if (query_current_values_with_pending_wait(data))
1074 goto out;
1075
1076 khz = find_khz_freq_from_fid(data->currfid);
1077
1078 out:
1079 preempt_enable_no_resched();
1080 set_cpus_allowed(current, oldmask);
1081
1082 return khz;
1083}
1084
1085static struct freq_attr* powernow_k8_attr[] = {
1086 &cpufreq_freq_attr_scaling_available_freqs,
1087 NULL,
1088};
1089
1090static struct cpufreq_driver cpufreq_amd64_driver = {
1091 .verify = powernowk8_verify,
1092 .target = powernowk8_target,
1093 .init = powernowk8_cpu_init,
1094 .exit = __devexit_p(powernowk8_cpu_exit),
1095 .get = powernowk8_get,
1096 .name = "powernow-k8",
1097 .owner = THIS_MODULE,
1098 .attr = powernow_k8_attr,
1099};
1100
1101/* driver entry point for init */
1102static int __init powernowk8_init(void)
1103{
1104 unsigned int i, supported_cpus = 0;
1105
1106 for (i=0; i<NR_CPUS; i++) {
1107 if (!cpu_online(i))
1108 continue;
1109 if (check_supported_cpu(i))
1110 supported_cpus++;
1111 }
1112
1113 if (supported_cpus == num_online_cpus()) {
1114 printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron processors (" VERSION ")\n",
1115 supported_cpus);
1116 return cpufreq_register_driver(&cpufreq_amd64_driver);
1117 }
1118
1119 return -ENODEV;
1120}
1121
1122/* driver entry point for term */
1123static void __exit powernowk8_exit(void)
1124{
1125 dprintk("exit\n");
1126
1127 cpufreq_unregister_driver(&cpufreq_amd64_driver);
1128}
1129
1130MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
1131MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
1132MODULE_LICENSE("GPL");
1133
1134late_initcall(powernowk8_init);
1135module_exit(powernowk8_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
new file mode 100644
index 000000000000..63ebc8470f52
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -0,0 +1,176 @@
1/*
2 * (c) 2003, 2004 Advanced Micro Devices, Inc.
3 * Your use of this code is subject to the terms and conditions of the
4 * GNU general public license version 2. See "COPYING" or
5 * http://www.gnu.org/licenses/gpl.html
6 */
7
8struct powernow_k8_data {
9 unsigned int cpu;
10
11 u32 numps; /* number of p-states */
12 u32 batps; /* number of p-states supported on battery */
13
14 /* these values are constant when the PSB is used to determine
15 * vid/fid pairings, but are modified during the ->target() call
16 * when ACPI is used */
17 u32 rvo; /* ramp voltage offset */
18 u32 irt; /* isochronous relief time */
19 u32 vidmvs; /* usable value calculated from mvs */
20 u32 vstable; /* voltage stabilization time, units 20 us */
21 u32 plllock; /* pll lock time, units 1 us */
22
23 /* keep track of the current fid / vid */
24 u32 currvid, currfid;
25
26 /* the powernow_table includes all frequency and vid/fid pairings:
27 * fid are the lower 8 bits of the index, vid are the upper 8 bits.
28 * frequency is in kHz */
29 struct cpufreq_frequency_table *powernow_table;
30
31#ifdef CONFIG_X86_POWERNOW_K8_ACPI
32 /* the acpi table needs to be kept. it's only available if ACPI was
33 * used to determine valid frequency/vid/fid states */
34 struct acpi_processor_performance acpi_data;
35#endif
36};
37
38
39/* processor's cpuid instruction support */
40#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */
41#define CPUID_XFAM 0x0ff00000 /* extended family */
42#define CPUID_XFAM_K8 0
43#define CPUID_XMOD 0x000f0000 /* extended model */
44#define CPUID_XMOD_REV_E 0x00020000
45#define CPUID_USE_XFAM_XMOD 0x00000f00
46#define CPUID_GET_MAX_CAPABILITIES 0x80000000
47#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
48#define P_STATE_TRANSITION_CAPABLE 6
49
50/* Model Specific Registers for p-state transitions. MSRs are 64-bit. For */
51/* writes (wrmsr - opcode 0f 30), the register number is placed in ecx, and */
52/* the value to write is placed in edx:eax. For reads (rdmsr - opcode 0f 32), */
53/* the register number is placed in ecx, and the data is returned in edx:eax. */
54
55#define MSR_FIDVID_CTL 0xc0010041
56#define MSR_FIDVID_STATUS 0xc0010042
57
58/* Field definitions within the FID VID Low Control MSR : */
59#define MSR_C_LO_INIT_FID_VID 0x00010000
60#define MSR_C_LO_NEW_VID 0x00001f00
61#define MSR_C_LO_NEW_FID 0x0000002f
62#define MSR_C_LO_VID_SHIFT 8
63
64/* Field definitions within the FID VID High Control MSR : */
65#define MSR_C_HI_STP_GNT_TO 0x000fffff
66
67/* Field definitions within the FID VID Low Status MSR : */
68#define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */
69#define MSR_S_LO_MAX_RAMP_VID 0x1f000000
70#define MSR_S_LO_MAX_FID 0x003f0000
71#define MSR_S_LO_START_FID 0x00003f00
72#define MSR_S_LO_CURRENT_FID 0x0000003f
73
74/* Field definitions within the FID VID High Status MSR : */
75#define MSR_S_HI_MAX_WORKING_VID 0x001f0000
76#define MSR_S_HI_START_VID 0x00001f00
77#define MSR_S_HI_CURRENT_VID 0x0000001f
78#define MSR_C_HI_STP_GNT_BENIGN 0x00000001
79
80/*
81 * There are restrictions frequencies have to follow:
82 * - only 1 entry in the low fid table ( <=1.4GHz )
83 * - lowest entry in the high fid table must be >= 2 * the entry in the
84 * low fid table
85 * - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry
86 * in the low fid table
87 * - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid
88 * - lowest frequency must be >= interprocessor hypertransport link speed
89 * (only applies to MP systems obviously)
90 */
91
92/* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
93#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */
94#define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */
95
96#define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */
97#define HI_VCOFREQ_TABLE_BOTTOM 1600
98
99#define MIN_FREQ_RESOLUTION 200 /* fids jump by 2 matching freq jumps by 200 */
100
101#define MAX_FID 0x2a /* Spec only gives FID values as far as 5 GHz */
102#define LEAST_VID 0x1e /* Lowest (numerically highest) useful vid value */
103
104#define MIN_FREQ 800 /* Min and max freqs, per spec */
105#define MAX_FREQ 5000
106
107#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */
108#define INVALID_VID_MASK 0xffffffe0 /* not a valid vid if these bits are set */
109
110#define STOP_GRANT_5NS 1 /* min poss memory access latency for voltage change */
111
112#define PLL_LOCK_CONVERSION (1000/5) /* ms to ns, then divide by clock period */
113
114#define MAXIMUM_VID_STEPS 1 /* Current cpus only allow a single step of 25mV */
115#define VST_UNITS_20US 20 /* Voltage Stabalization Time is in units of 20us */
116
117/*
118 * Most values of interest are enocoded in a single field of the _PSS
119 * entries: the "control" value.
120 */
121
122#define IRT_SHIFT 30
123#define RVO_SHIFT 28
124#define PLL_L_SHIFT 20
125#define MVS_SHIFT 18
126#define VST_SHIFT 11
127#define VID_SHIFT 6
128#define IRT_MASK 3
129#define RVO_MASK 3
130#define PLL_L_MASK 0x7f
131#define MVS_MASK 3
132#define VST_MASK 0x7f
133#define VID_MASK 0x1f
134#define FID_MASK 0x3f
135
136
137/*
138 * Version 1.4 of the PSB table. This table is constructed by BIOS and is
139 * to tell the OS's power management driver which VIDs and FIDs are
140 * supported by this particular processor.
141 * If the data in the PSB / PST is wrong, then this driver will program the
142 * wrong values into hardware, which is very likely to lead to a crash.
143 */
144
145#define PSB_ID_STRING "AMDK7PNOW!"
146#define PSB_ID_STRING_LEN 10
147
148#define PSB_VERSION_1_4 0x14
149
150struct psb_s {
151 u8 signature[10];
152 u8 tableversion;
153 u8 flags1;
154 u16 vstable;
155 u8 flags2;
156 u8 num_tables;
157 u32 cpuid;
158 u8 plllocktime;
159 u8 maxfid;
160 u8 maxvid;
161 u8 numps;
162};
163
164/* Pairs of fid/vid values are appended to the version 1.4 PSB table. */
165struct pst_s {
166 u8 fid;
167 u8 vid;
168};
169
170#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg)
171
172static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid);
173static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid);
174static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
175
176static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
new file mode 100644
index 000000000000..07d5612dc00f
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -0,0 +1,715 @@
1/*
2 * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium
3 * M (part of the Centrino chipset).
4 *
5 * Despite the "SpeedStep" in the name, this is almost entirely unlike
6 * traditional SpeedStep.
7 *
8 * Modelled on speedstep.c
9 *
10 * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
11 *
12 * WARNING WARNING WARNING
13 *
14 * This driver manipulates the PERF_CTL MSR, which is only somewhat
15 * documented. While it seems to work on my laptop, it has not been
16 * tested anywhere else, and it may not work for you, do strange
17 * things or simply crash.
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/cpufreq.h>
24#include <linux/config.h>
25#include <linux/delay.h>
26#include <linux/compiler.h>
27
28#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
29#include <linux/acpi.h>
30#include <acpi/processor.h>
31#endif
32
33#include <asm/msr.h>
34#include <asm/processor.h>
35#include <asm/cpufeature.h>
36
37#include "speedstep-est-common.h"
38
39#define PFX "speedstep-centrino: "
40#define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>"
41
42#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
43
44
45struct cpu_id
46{
47 __u8 x86; /* CPU family */
48 __u8 x86_model; /* model */
49 __u8 x86_mask; /* stepping */
50};
51
52enum {
53 CPU_BANIAS,
54 CPU_DOTHAN_A1,
55 CPU_DOTHAN_A2,
56 CPU_DOTHAN_B0,
57};
58
59static const struct cpu_id cpu_ids[] = {
60 [CPU_BANIAS] = { 6, 9, 5 },
61 [CPU_DOTHAN_A1] = { 6, 13, 1 },
62 [CPU_DOTHAN_A2] = { 6, 13, 2 },
63 [CPU_DOTHAN_B0] = { 6, 13, 6 },
64};
65#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
66
67struct cpu_model
68{
69 const struct cpu_id *cpu_id;
70 const char *model_name;
71 unsigned max_freq; /* max clock in kHz */
72
73 struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
74};
75static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);
76
77/* Operating points for current CPU */
78static struct cpu_model *centrino_model[NR_CPUS];
79static const struct cpu_id *centrino_cpu[NR_CPUS];
80
81static struct cpufreq_driver centrino_driver;
82
83#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
84
85/* Computes the correct form for IA32_PERF_CTL MSR for a particular
86 frequency/voltage operating point; frequency in MHz, volts in mV.
87 This is stored as "index" in the structure. */
88#define OP(mhz, mv) \
89 { \
90 .frequency = (mhz) * 1000, \
91 .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \
92 }
93
94/*
95 * These voltage tables were derived from the Intel Pentium M
96 * datasheet, document 25261202.pdf, Table 5. I have verified they
97 * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium
98 * M.
99 */
100
101/* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */
102static struct cpufreq_frequency_table banias_900[] =
103{
104 OP(600, 844),
105 OP(800, 988),
106 OP(900, 1004),
107 { .frequency = CPUFREQ_TABLE_END }
108};
109
110/* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */
111static struct cpufreq_frequency_table banias_1000[] =
112{
113 OP(600, 844),
114 OP(800, 972),
115 OP(900, 988),
116 OP(1000, 1004),
117 { .frequency = CPUFREQ_TABLE_END }
118};
119
120/* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */
121static struct cpufreq_frequency_table banias_1100[] =
122{
123 OP( 600, 956),
124 OP( 800, 1020),
125 OP( 900, 1100),
126 OP(1000, 1164),
127 OP(1100, 1180),
128 { .frequency = CPUFREQ_TABLE_END }
129};
130
131
132/* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */
133static struct cpufreq_frequency_table banias_1200[] =
134{
135 OP( 600, 956),
136 OP( 800, 1004),
137 OP( 900, 1020),
138 OP(1000, 1100),
139 OP(1100, 1164),
140 OP(1200, 1180),
141 { .frequency = CPUFREQ_TABLE_END }
142};
143
144/* Intel Pentium M processor 1.30GHz (Banias) */
145static struct cpufreq_frequency_table banias_1300[] =
146{
147 OP( 600, 956),
148 OP( 800, 1260),
149 OP(1000, 1292),
150 OP(1200, 1356),
151 OP(1300, 1388),
152 { .frequency = CPUFREQ_TABLE_END }
153};
154
155/* Intel Pentium M processor 1.40GHz (Banias) */
156static struct cpufreq_frequency_table banias_1400[] =
157{
158 OP( 600, 956),
159 OP( 800, 1180),
160 OP(1000, 1308),
161 OP(1200, 1436),
162 OP(1400, 1484),
163 { .frequency = CPUFREQ_TABLE_END }
164};
165
166/* Intel Pentium M processor 1.50GHz (Banias) */
167static struct cpufreq_frequency_table banias_1500[] =
168{
169 OP( 600, 956),
170 OP( 800, 1116),
171 OP(1000, 1228),
172 OP(1200, 1356),
173 OP(1400, 1452),
174 OP(1500, 1484),
175 { .frequency = CPUFREQ_TABLE_END }
176};
177
178/* Intel Pentium M processor 1.60GHz (Banias) */
179static struct cpufreq_frequency_table banias_1600[] =
180{
181 OP( 600, 956),
182 OP( 800, 1036),
183 OP(1000, 1164),
184 OP(1200, 1276),
185 OP(1400, 1420),
186 OP(1600, 1484),
187 { .frequency = CPUFREQ_TABLE_END }
188};
189
190/* Intel Pentium M processor 1.70GHz (Banias) */
191static struct cpufreq_frequency_table banias_1700[] =
192{
193 OP( 600, 956),
194 OP( 800, 1004),
195 OP(1000, 1116),
196 OP(1200, 1228),
197 OP(1400, 1308),
198 OP(1700, 1484),
199 { .frequency = CPUFREQ_TABLE_END }
200};
201#undef OP
202
203#define _BANIAS(cpuid, max, name) \
204{ .cpu_id = cpuid, \
205 .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \
206 .max_freq = (max)*1000, \
207 .op_points = banias_##max, \
208}
209#define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max)
210
211/* CPU models, their operating frequency range, and freq/voltage
212 operating points */
213static struct cpu_model models[] =
214{
215 _BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"),
216 BANIAS(1000),
217 BANIAS(1100),
218 BANIAS(1200),
219 BANIAS(1300),
220 BANIAS(1400),
221 BANIAS(1500),
222 BANIAS(1600),
223 BANIAS(1700),
224
225 /* NULL model_name is a wildcard */
226 { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
227 { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
228 { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
229
230 { NULL, }
231};
232#undef _BANIAS
233#undef BANIAS
234
235static int centrino_cpu_init_table(struct cpufreq_policy *policy)
236{
237 struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
238 struct cpu_model *model;
239
240 for(model = models; model->cpu_id != NULL; model++)
241 if (centrino_verify_cpu_id(cpu, model->cpu_id) &&
242 (model->model_name == NULL ||
243 strcmp(cpu->x86_model_id, model->model_name) == 0))
244 break;
245
246 if (model->cpu_id == NULL) {
247 /* No match at all */
248 dprintk(KERN_INFO PFX "no support for CPU model \"%s\": "
249 "send /proc/cpuinfo to " MAINTAINER "\n",
250 cpu->x86_model_id);
251 return -ENOENT;
252 }
253
254 if (model->op_points == NULL) {
255 /* Matched a non-match */
256 dprintk(KERN_INFO PFX "no table support for CPU model \"%s\": \n",
257 cpu->x86_model_id);
258#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
259 dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
260#endif
261 return -ENOENT;
262 }
263
264 centrino_model[policy->cpu] = model;
265
266 dprintk("found \"%s\": max frequency: %dkHz\n",
267 model->model_name, model->max_freq);
268
269 return 0;
270}
271
272#else
273static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
274#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
275
276static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x)
277{
278 if ((c->x86 == x->x86) &&
279 (c->x86_model == x->x86_model) &&
280 (c->x86_mask == x->x86_mask))
281 return 1;
282 return 0;
283}
284
285/* To be called only after centrino_model is initialized */
286static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe)
287{
288 int i;
289
290 /*
291 * Extract clock in kHz from PERF_CTL value
292 * for centrino, as some DSDTs are buggy.
293 * Ideally, this can be done using the acpi_data structure.
294 */
295 if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) ||
296 (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) ||
297 (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) {
298 msr = (msr >> 8) & 0xff;
299 return msr * 100000;
300 }
301
302 if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points))
303 return 0;
304
305 msr &= 0xffff;
306 for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {
307 if (msr == centrino_model[cpu]->op_points[i].index)
308 return centrino_model[cpu]->op_points[i].frequency;
309 }
310 if (failsafe)
311 return centrino_model[cpu]->op_points[i-1].frequency;
312 else
313 return 0;
314}
315
316/* Return the current CPU frequency in kHz */
317static unsigned int get_cur_freq(unsigned int cpu)
318{
319 unsigned l, h;
320 unsigned clock_freq;
321 cpumask_t saved_mask;
322
323 saved_mask = current->cpus_allowed;
324 set_cpus_allowed(current, cpumask_of_cpu(cpu));
325 if (smp_processor_id() != cpu)
326 return 0;
327
328 rdmsr(MSR_IA32_PERF_STATUS, l, h);
329 clock_freq = extract_clock(l, cpu, 0);
330
331 if (unlikely(clock_freq == 0)) {
332 /*
333 * On some CPUs, we can see transient MSR values (which are
334 * not present in _PSS), while CPU is doing some automatic
335 * P-state transition (like TM2). Get the last freq set
336 * in PERF_CTL.
337 */
338 rdmsr(MSR_IA32_PERF_CTL, l, h);
339 clock_freq = extract_clock(l, cpu, 1);
340 }
341
342 set_cpus_allowed(current, saved_mask);
343 return clock_freq;
344}
345
346
347#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
348
349static struct acpi_processor_performance p;
350
351/*
352 * centrino_cpu_init_acpi - register with ACPI P-States library
353 *
354 * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
355 * in order to determine correct frequency and voltage pairings by reading
356 * the _PSS of the ACPI DSDT or SSDT tables.
357 */
358static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
359{
360 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
361 u32 arg0_buf[3];
362 struct acpi_object_list arg_list = {1, &arg0};
363 unsigned long cur_freq;
364 int result = 0, i;
365 unsigned int cpu = policy->cpu;
366
367 /* _PDC settings */
368 arg0.buffer.length = 12;
369 arg0.buffer.pointer = (u8 *) arg0_buf;
370 arg0_buf[0] = ACPI_PDC_REVISION_ID;
371 arg0_buf[1] = 1;
372 arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_MSR;
373
374 p.pdc = &arg_list;
375
376 /* register with ACPI core */
377 if (acpi_processor_register_performance(&p, cpu)) {
378 dprintk(KERN_INFO PFX "obtaining ACPI data failed\n");
379 return -EIO;
380 }
381
382 /* verify the acpi_data */
383 if (p.state_count <= 1) {
384 dprintk("No P-States\n");
385 result = -ENODEV;
386 goto err_unreg;
387 }
388
389 if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
390 (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
391 dprintk("Invalid control/status registers (%x - %x)\n",
392 p.control_register.space_id, p.status_register.space_id);
393 result = -EIO;
394 goto err_unreg;
395 }
396
397 for (i=0; i<p.state_count; i++) {
398 if (p.states[i].control != p.states[i].status) {
399 dprintk("Different control (%x) and status values (%x)\n",
400 p.states[i].control, p.states[i].status);
401 result = -EINVAL;
402 goto err_unreg;
403 }
404
405 if (!p.states[i].core_frequency) {
406 dprintk("Zero core frequency for state %u\n", i);
407 result = -EINVAL;
408 goto err_unreg;
409 }
410
411 if (p.states[i].core_frequency > p.states[0].core_frequency) {
412 dprintk("P%u has larger frequency (%u) than P0 (%u), skipping\n", i,
413 p.states[i].core_frequency, p.states[0].core_frequency);
414 p.states[i].core_frequency = 0;
415 continue;
416 }
417 }
418
419 centrino_model[cpu] = kmalloc(sizeof(struct cpu_model), GFP_KERNEL);
420 if (!centrino_model[cpu]) {
421 result = -ENOMEM;
422 goto err_unreg;
423 }
424 memset(centrino_model[cpu], 0, sizeof(struct cpu_model));
425
426 centrino_model[cpu]->model_name=NULL;
427 centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000;
428 centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) *
429 (p.state_count + 1), GFP_KERNEL);
430 if (!centrino_model[cpu]->op_points) {
431 result = -ENOMEM;
432 goto err_kfree;
433 }
434
435 for (i=0; i<p.state_count; i++) {
436 centrino_model[cpu]->op_points[i].index = p.states[i].control;
437 centrino_model[cpu]->op_points[i].frequency = p.states[i].core_frequency * 1000;
438 dprintk("adding state %i with frequency %u and control value %04x\n",
439 i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
440 }
441 centrino_model[cpu]->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
442
443 cur_freq = get_cur_freq(cpu);
444
445 for (i=0; i<p.state_count; i++) {
446 if (!p.states[i].core_frequency) {
447 dprintk("skipping state %u\n", i);
448 centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
449 continue;
450 }
451
452 if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) !=
453 (centrino_model[cpu]->op_points[i].frequency)) {
454 dprintk("Invalid encoded frequency (%u vs. %u)\n",
455 extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0),
456 centrino_model[cpu]->op_points[i].frequency);
457 result = -EINVAL;
458 goto err_kfree_all;
459 }
460
461 if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
462 p.state = i;
463 }
464
465 /* notify BIOS that we exist */
466 acpi_processor_notify_smm(THIS_MODULE);
467
468 return 0;
469
470 err_kfree_all:
471 kfree(centrino_model[cpu]->op_points);
472 err_kfree:
473 kfree(centrino_model[cpu]);
474 err_unreg:
475 acpi_processor_unregister_performance(&p, cpu);
476 dprintk(KERN_INFO PFX "invalid ACPI data\n");
477 return (result);
478}
479#else
480static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
481#endif
482
483static int centrino_cpu_init(struct cpufreq_policy *policy)
484{
485 struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
486 unsigned freq;
487 unsigned l, h;
488 int ret;
489 int i;
490
491 /* Only Intel makes Enhanced Speedstep-capable CPUs */
492 if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
493 return -ENODEV;
494
495 for (i = 0; i < N_IDS; i++)
496 if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
497 break;
498
499 if (i != N_IDS)
500 centrino_cpu[policy->cpu] = &cpu_ids[i];
501
502 if (is_const_loops_cpu(policy->cpu)) {
503 centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
504 }
505
506 if (centrino_cpu_init_acpi(policy)) {
507 if (policy->cpu != 0)
508 return -ENODEV;
509
510 if (!centrino_cpu[policy->cpu]) {
511 dprintk(KERN_INFO PFX "found unsupported CPU with "
512 "Enhanced SpeedStep: send /proc/cpuinfo to "
513 MAINTAINER "\n");
514 return -ENODEV;
515 }
516
517 if (centrino_cpu_init_table(policy)) {
518 return -ENODEV;
519 }
520 }
521
522 /* Check to see if Enhanced SpeedStep is enabled, and try to
523 enable it if not. */
524 rdmsr(MSR_IA32_MISC_ENABLE, l, h);
525
526 if (!(l & (1<<16))) {
527 l |= (1<<16);
528 dprintk("trying to enable Enhanced SpeedStep (%x)\n", l);
529 wrmsr(MSR_IA32_MISC_ENABLE, l, h);
530
531 /* check to see if it stuck */
532 rdmsr(MSR_IA32_MISC_ENABLE, l, h);
533 if (!(l & (1<<16))) {
534 printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n");
535 return -ENODEV;
536 }
537 }
538
539 freq = get_cur_freq(policy->cpu);
540
541 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
542 policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
543 policy->cur = freq;
544
545 dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur);
546
547 ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model[policy->cpu]->op_points);
548 if (ret)
549 return (ret);
550
551 cpufreq_frequency_table_get_attr(centrino_model[policy->cpu]->op_points, policy->cpu);
552
553 return 0;
554}
555
556static int centrino_cpu_exit(struct cpufreq_policy *policy)
557{
558 unsigned int cpu = policy->cpu;
559
560 if (!centrino_model[cpu])
561 return -ENODEV;
562
563 cpufreq_frequency_table_put_attr(cpu);
564
565#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
566 if (!centrino_model[cpu]->model_name) {
567 dprintk("unregistering and freeing ACPI data\n");
568 acpi_processor_unregister_performance(&p, cpu);
569 kfree(centrino_model[cpu]->op_points);
570 kfree(centrino_model[cpu]);
571 }
572#endif
573
574 centrino_model[cpu] = NULL;
575
576 return 0;
577}
578
579/**
580 * centrino_verify - verifies a new CPUFreq policy
581 * @policy: new policy
582 *
583 * Limit must be within this model's frequency range at least one
584 * border included.
585 */
586static int centrino_verify (struct cpufreq_policy *policy)
587{
588 return cpufreq_frequency_table_verify(policy, centrino_model[policy->cpu]->op_points);
589}
590
591/**
592 * centrino_setpolicy - set a new CPUFreq policy
593 * @policy: new policy
594 * @target_freq: the target frequency
595 * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
596 *
597 * Sets a new CPUFreq policy.
598 */
599static int centrino_target (struct cpufreq_policy *policy,
600 unsigned int target_freq,
601 unsigned int relation)
602{
603 unsigned int newstate = 0;
604 unsigned int msr, oldmsr, h, cpu = policy->cpu;
605 struct cpufreq_freqs freqs;
606 cpumask_t saved_mask;
607 int retval;
608
609 if (centrino_model[cpu] == NULL)
610 return -ENODEV;
611
612 /*
613 * Support for SMP systems.
614 * Make sure we are running on the CPU that wants to change frequency
615 */
616 saved_mask = current->cpus_allowed;
617 set_cpus_allowed(current, policy->cpus);
618 if (!cpu_isset(smp_processor_id(), policy->cpus)) {
619 dprintk("couldn't limit to CPUs in this domain\n");
620 return(-EAGAIN);
621 }
622
623 if (cpufreq_frequency_table_target(policy, centrino_model[cpu]->op_points, target_freq,
624 relation, &newstate)) {
625 retval = -EINVAL;
626 goto migrate_end;
627 }
628
629 msr = centrino_model[cpu]->op_points[newstate].index;
630 rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
631
632 if (msr == (oldmsr & 0xffff)) {
633 retval = 0;
634 dprintk("no change needed - msr was and needs to be %x\n", oldmsr);
635 goto migrate_end;
636 }
637
638 freqs.cpu = cpu;
639 freqs.old = extract_clock(oldmsr, cpu, 0);
640 freqs.new = extract_clock(msr, cpu, 0);
641
642 dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
643 target_freq, freqs.old, freqs.new, msr);
644
645 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
646
647 /* all but 16 LSB are "reserved", so treat them with
648 care */
649 oldmsr &= ~0xffff;
650 msr &= 0xffff;
651 oldmsr |= msr;
652
653 wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
654
655 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
656
657 retval = 0;
658migrate_end:
659 set_cpus_allowed(current, saved_mask);
660 return (retval);
661}
662
663static struct freq_attr* centrino_attr[] = {
664 &cpufreq_freq_attr_scaling_available_freqs,
665 NULL,
666};
667
668static struct cpufreq_driver centrino_driver = {
669 .name = "centrino", /* should be speedstep-centrino,
670 but there's a 16 char limit */
671 .init = centrino_cpu_init,
672 .exit = centrino_cpu_exit,
673 .verify = centrino_verify,
674 .target = centrino_target,
675 .get = get_cur_freq,
676 .attr = centrino_attr,
677 .owner = THIS_MODULE,
678};
679
680
681/**
682 * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver
683 *
684 * Initializes the Enhanced SpeedStep support. Returns -ENODEV on
685 * unsupported devices, -ENOENT if there's no voltage table for this
686 * particular CPU model, -EINVAL on problems during initiatization,
687 * and zero on success.
688 *
689 * This is quite picky. Not only does the CPU have to advertise the
690 * "est" flag in the cpuid capability flags, we look for a specific
691 * CPU model and stepping, and we need to have the exact model name in
692 * our voltage tables. That is, be paranoid about not releasing
693 * someone's valuable magic smoke.
694 */
695static int __init centrino_init(void)
696{
697 struct cpuinfo_x86 *cpu = cpu_data;
698
699 if (!cpu_has(cpu, X86_FEATURE_EST))
700 return -ENODEV;
701
702 return cpufreq_register_driver(&centrino_driver);
703}
704
705static void __exit centrino_exit(void)
706{
707 cpufreq_unregister_driver(&centrino_driver);
708}
709
710MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
711MODULE_DESCRIPTION ("Enhanced SpeedStep driver for Intel Pentium M processors.");
712MODULE_LICENSE ("GPL");
713
714late_initcall(centrino_init);
715module_exit(centrino_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h b/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
new file mode 100644
index 000000000000..5ce995c9d866
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
@@ -0,0 +1,25 @@
1/*
2 * Routines common for drivers handling Enhanced Speedstep Technology
3 * Copyright (C) 2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
4 *
5 * Licensed under the terms of the GNU GPL License version 2 -- see
6 * COPYING for details.
7 */
8
9static inline int is_const_loops_cpu(unsigned int cpu)
10{
11 struct cpuinfo_x86 *c = cpu_data + cpu;
12
13 if (c->x86_vendor != X86_VENDOR_INTEL || !cpu_has(c, X86_FEATURE_EST))
14 return 0;
15
16 /*
17 * on P-4s, the TSC runs with constant frequency independent of cpu freq
18 * when we use EST
19 */
20 if (c->x86 == 0xf)
21 return 1;
22
23 return 0;
24}
25
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
new file mode 100644
index 000000000000..5b7d18a06afa
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
@@ -0,0 +1,424 @@
1/*
2 * (C) 2001 Dave Jones, Arjan van de ven.
3 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 * Based upon reverse engineered information, and on Intel documentation
7 * for chipsets ICH2-M and ICH3-M.
8 *
9 * Many thanks to Ducrot Bruno for finding and fixing the last
10 * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler
11 * for extensive testing.
12 *
13 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
14 */
15
16
17/*********************************************************************
18 * SPEEDSTEP - DEFINITIONS *
19 *********************************************************************/
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/cpufreq.h>
25#include <linux/pci.h>
26#include <linux/slab.h>
27
28#include "speedstep-lib.h"
29
30
31/* speedstep_chipset:
32 * It is necessary to know which chipset is used. As accesses to
33 * this device occur at various places in this module, we need a
34 * static struct pci_dev * pointing to that device.
35 */
36static struct pci_dev *speedstep_chipset_dev;
37
38
39/* speedstep_processor
40 */
41static unsigned int speedstep_processor = 0;
42
43
44/*
45 * There are only two frequency states for each processor. Values
46 * are in kHz for the time being.
47 */
48static struct cpufreq_frequency_table speedstep_freqs[] = {
49 {SPEEDSTEP_HIGH, 0},
50 {SPEEDSTEP_LOW, 0},
51 {0, CPUFREQ_TABLE_END},
52};
53
54
55#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-ich", msg)
56
57
58/**
59 * speedstep_set_state - set the SpeedStep state
60 * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
61 *
62 * Tries to change the SpeedStep state.
63 */
64static void speedstep_set_state (unsigned int state)
65{
66 u32 pmbase;
67 u8 pm2_blk;
68 u8 value;
69 unsigned long flags;
70
71 if (!speedstep_chipset_dev || (state > 0x1))
72 return;
73
74 /* get PMBASE */
75 pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
76 if (!(pmbase & 0x01)) {
77 printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
78 return;
79 }
80
81 pmbase &= 0xFFFFFFFE;
82 if (!pmbase) {
83 printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
84 return;
85 }
86
87 /* Disable IRQs */
88 local_irq_save(flags);
89
90 /* read state */
91 value = inb(pmbase + 0x50);
92
93 dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
94
95 /* write new state */
96 value &= 0xFE;
97 value |= state;
98
99 dprintk("writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase);
100
101 /* Disable bus master arbitration */
102 pm2_blk = inb(pmbase + 0x20);
103 pm2_blk |= 0x01;
104 outb(pm2_blk, (pmbase + 0x20));
105
106 /* Actual transition */
107 outb(value, (pmbase + 0x50));
108
109 /* Restore bus master arbitration */
110 pm2_blk &= 0xfe;
111 outb(pm2_blk, (pmbase + 0x20));
112
113 /* check if transition was successful */
114 value = inb(pmbase + 0x50);
115
116 /* Enable IRQs */
117 local_irq_restore(flags);
118
119 dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value);
120
121 if (state == (value & 0x1)) {
122 dprintk("change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000));
123 } else {
124 printk (KERN_ERR "cpufreq: change failed - I/O error\n");
125 }
126
127 return;
128}
129
130
131/**
132 * speedstep_activate - activate SpeedStep control in the chipset
133 *
134 * Tries to activate the SpeedStep status and control registers.
135 * Returns -EINVAL on an unsupported chipset, and zero on success.
136 */
137static int speedstep_activate (void)
138{
139 u16 value = 0;
140
141 if (!speedstep_chipset_dev)
142 return -EINVAL;
143
144 pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value);
145 if (!(value & 0x08)) {
146 value |= 0x08;
147 dprintk("activating SpeedStep (TM) registers\n");
148 pci_write_config_word(speedstep_chipset_dev, 0x00A0, value);
149 }
150
151 return 0;
152}
153
154
155/**
156 * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic
157 *
158 * Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to
159 * the LPC bridge / PM module which contains all power-management
160 * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected
161 * chipset, or zero on failure.
162 */
163static unsigned int speedstep_detect_chipset (void)
164{
165 speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
166 PCI_DEVICE_ID_INTEL_82801DB_12,
167 PCI_ANY_ID,
168 PCI_ANY_ID,
169 NULL);
170 if (speedstep_chipset_dev)
171 return 4; /* 4-M */
172
173 speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
174 PCI_DEVICE_ID_INTEL_82801CA_12,
175 PCI_ANY_ID,
176 PCI_ANY_ID,
177 NULL);
178 if (speedstep_chipset_dev)
179 return 3; /* 3-M */
180
181
182 speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
183 PCI_DEVICE_ID_INTEL_82801BA_10,
184 PCI_ANY_ID,
185 PCI_ANY_ID,
186 NULL);
187 if (speedstep_chipset_dev) {
188 /* speedstep.c causes lockups on Dell Inspirons 8000 and
189 * 8100 which use a pretty old revision of the 82815
190 * host brige. Abort on these systems.
191 */
192 static struct pci_dev *hostbridge;
193 u8 rev = 0;
194
195 hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL,
196 PCI_DEVICE_ID_INTEL_82815_MC,
197 PCI_ANY_ID,
198 PCI_ANY_ID,
199 NULL);
200
201 if (!hostbridge)
202 return 2; /* 2-M */
203
204 pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
205 if (rev < 5) {
206 dprintk("hostbridge does not support speedstep\n");
207 speedstep_chipset_dev = NULL;
208 pci_dev_put(hostbridge);
209 return 0;
210 }
211
212 pci_dev_put(hostbridge);
213 return 2; /* 2-M */
214 }
215
216 return 0;
217}
218
219static unsigned int _speedstep_get(cpumask_t cpus)
220{
221 unsigned int speed;
222 cpumask_t cpus_allowed;
223
224 cpus_allowed = current->cpus_allowed;
225 set_cpus_allowed(current, cpus);
226 speed = speedstep_get_processor_frequency(speedstep_processor);
227 set_cpus_allowed(current, cpus_allowed);
228 dprintk("detected %u kHz as current frequency\n", speed);
229 return speed;
230}
231
232static unsigned int speedstep_get(unsigned int cpu)
233{
234 return _speedstep_get(cpumask_of_cpu(cpu));
235}
236
237/**
238 * speedstep_target - set a new CPUFreq policy
239 * @policy: new policy
240 * @target_freq: the target frequency
241 * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
242 *
243 * Sets a new CPUFreq policy.
244 */
245static int speedstep_target (struct cpufreq_policy *policy,
246 unsigned int target_freq,
247 unsigned int relation)
248{
249 unsigned int newstate = 0;
250 struct cpufreq_freqs freqs;
251 cpumask_t cpus_allowed;
252 int i;
253
254 if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
255 return -EINVAL;
256
257 freqs.old = _speedstep_get(policy->cpus);
258 freqs.new = speedstep_freqs[newstate].frequency;
259 freqs.cpu = policy->cpu;
260
261 dprintk("transiting from %u to %u kHz\n", freqs.old, freqs.new);
262
263 /* no transition necessary */
264 if (freqs.old == freqs.new)
265 return 0;
266
267 cpus_allowed = current->cpus_allowed;
268
269 for_each_cpu_mask(i, policy->cpus) {
270 freqs.cpu = i;
271 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
272 }
273
274 /* switch to physical CPU where state is to be changed */
275 set_cpus_allowed(current, policy->cpus);
276
277 speedstep_set_state(newstate);
278
279 /* allow to be run on all CPUs */
280 set_cpus_allowed(current, cpus_allowed);
281
282 for_each_cpu_mask(i, policy->cpus) {
283 freqs.cpu = i;
284 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
285 }
286
287 return 0;
288}
289
290
291/**
292 * speedstep_verify - verifies a new CPUFreq policy
293 * @policy: new policy
294 *
295 * Limit must be within speedstep_low_freq and speedstep_high_freq, with
296 * at least one border included.
297 */
298static int speedstep_verify (struct cpufreq_policy *policy)
299{
300 return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
301}
302
303
304static int speedstep_cpu_init(struct cpufreq_policy *policy)
305{
306 int result = 0;
307 unsigned int speed;
308 cpumask_t cpus_allowed;
309
310 /* only run on CPU to be set, or on its sibling */
311#ifdef CONFIG_SMP
312 policy->cpus = cpu_sibling_map[policy->cpu];
313#endif
314
315 cpus_allowed = current->cpus_allowed;
316 set_cpus_allowed(current, policy->cpus);
317
318 /* detect low and high frequency */
319 result = speedstep_get_freqs(speedstep_processor,
320 &speedstep_freqs[SPEEDSTEP_LOW].frequency,
321 &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
322 &speedstep_set_state);
323 set_cpus_allowed(current, cpus_allowed);
324 if (result)
325 return result;
326
327 /* get current speed setting */
328 speed = _speedstep_get(policy->cpus);
329 if (!speed)
330 return -EIO;
331
332 dprintk("currently at %s speed setting - %i MHz\n",
333 (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
334 (speed / 1000));
335
336 /* cpuinfo and default policy values */
337 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
338 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
339 policy->cur = speed;
340
341 result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
342 if (result)
343 return (result);
344
345 cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
346
347 return 0;
348}
349
350
351static int speedstep_cpu_exit(struct cpufreq_policy *policy)
352{
353 cpufreq_frequency_table_put_attr(policy->cpu);
354 return 0;
355}
356
357static struct freq_attr* speedstep_attr[] = {
358 &cpufreq_freq_attr_scaling_available_freqs,
359 NULL,
360};
361
362
363static struct cpufreq_driver speedstep_driver = {
364 .name = "speedstep-ich",
365 .verify = speedstep_verify,
366 .target = speedstep_target,
367 .init = speedstep_cpu_init,
368 .exit = speedstep_cpu_exit,
369 .get = speedstep_get,
370 .owner = THIS_MODULE,
371 .attr = speedstep_attr,
372};
373
374
375/**
376 * speedstep_init - initializes the SpeedStep CPUFreq driver
377 *
378 * Initializes the SpeedStep support. Returns -ENODEV on unsupported
379 * devices, -EINVAL on problems during initiatization, and zero on
380 * success.
381 */
382static int __init speedstep_init(void)
383{
384 /* detect processor */
385 speedstep_processor = speedstep_detect_processor();
386 if (!speedstep_processor) {
387 dprintk("Intel(R) SpeedStep(TM) capable processor not found\n");
388 return -ENODEV;
389 }
390
391 /* detect chipset */
392 if (!speedstep_detect_chipset()) {
393 dprintk("Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n");
394 return -ENODEV;
395 }
396
397 /* activate speedstep support */
398 if (speedstep_activate()) {
399 pci_dev_put(speedstep_chipset_dev);
400 return -EINVAL;
401 }
402
403 return cpufreq_register_driver(&speedstep_driver);
404}
405
406
407/**
408 * speedstep_exit - unregisters SpeedStep support
409 *
410 * Unregisters SpeedStep support.
411 */
412static void __exit speedstep_exit(void)
413{
414 pci_dev_put(speedstep_chipset_dev);
415 cpufreq_unregister_driver(&speedstep_driver);
416}
417
418
419MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>, Dominik Brodowski <linux@brodo.de>");
420MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors on chipsets with ICH-M southbridges.");
421MODULE_LICENSE ("GPL");
422
423module_init(speedstep_init);
424module_exit(speedstep_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
new file mode 100644
index 000000000000..8ba430a9c3a2
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -0,0 +1,385 @@
1/*
2 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Library for common functions for Intel SpeedStep v.1 and v.2 support
7 *
8 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/init.h>
15#include <linux/cpufreq.h>
16#include <linux/pci.h>
17#include <linux/slab.h>
18
19#include <asm/msr.h>
20#include "speedstep-lib.h"
21
22#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-lib", msg)
23
24#ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK
25static int relaxed_check = 0;
26#else
27#define relaxed_check 0
28#endif
29
30/*********************************************************************
31 * GET PROCESSOR CORE SPEED IN KHZ *
32 *********************************************************************/
33
34static unsigned int pentium3_get_frequency (unsigned int processor)
35{
36 /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
37 struct {
38 unsigned int ratio; /* Frequency Multiplier (x10) */
39 u8 bitmap; /* power on configuration bits
40 [27, 25:22] (in MSR 0x2a) */
41 } msr_decode_mult [] = {
42 { 30, 0x01 },
43 { 35, 0x05 },
44 { 40, 0x02 },
45 { 45, 0x06 },
46 { 50, 0x00 },
47 { 55, 0x04 },
48 { 60, 0x0b },
49 { 65, 0x0f },
50 { 70, 0x09 },
51 { 75, 0x0d },
52 { 80, 0x0a },
53 { 85, 0x26 },
54 { 90, 0x20 },
55 { 100, 0x2b },
56 { 0, 0xff } /* error or unknown value */
57 };
58
59 /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
60 struct {
61 unsigned int value; /* Front Side Bus speed in MHz */
62 u8 bitmap; /* power on configuration bits [18: 19]
63 (in MSR 0x2a) */
64 } msr_decode_fsb [] = {
65 { 66, 0x0 },
66 { 100, 0x2 },
67 { 133, 0x1 },
68 { 0, 0xff}
69 };
70
71 u32 msr_lo, msr_tmp;
72 int i = 0, j = 0;
73
74 /* read MSR 0x2a - we only need the low 32 bits */
75 rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
76 dprintk("P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
77 msr_tmp = msr_lo;
78
79 /* decode the FSB */
80 msr_tmp &= 0x00c0000;
81 msr_tmp >>= 18;
82 while (msr_tmp != msr_decode_fsb[i].bitmap) {
83 if (msr_decode_fsb[i].bitmap == 0xff)
84 return 0;
85 i++;
86 }
87
88 /* decode the multiplier */
89 if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY) {
90 dprintk("workaround for early PIIIs\n");
91 msr_lo &= 0x03c00000;
92 } else
93 msr_lo &= 0x0bc00000;
94 msr_lo >>= 22;
95 while (msr_lo != msr_decode_mult[j].bitmap) {
96 if (msr_decode_mult[j].bitmap == 0xff)
97 return 0;
98 j++;
99 }
100
101 dprintk("speed is %u\n", (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100));
102
103 return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100);
104}
105
106
107static unsigned int pentiumM_get_frequency(void)
108{
109 u32 msr_lo, msr_tmp;
110
111 rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
112 dprintk("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
113
114 /* see table B-2 of 24547212.pdf */
115 if (msr_lo & 0x00040000) {
116 printk(KERN_DEBUG "speedstep-lib: PM - invalid FSB: 0x%x 0x%x\n", msr_lo, msr_tmp);
117 return 0;
118 }
119
120 msr_tmp = (msr_lo >> 22) & 0x1f;
121 dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * 100 * 1000));
122
123 return (msr_tmp * 100 * 1000);
124}
125
126
127static unsigned int pentium4_get_frequency(void)
128{
129 struct cpuinfo_x86 *c = &boot_cpu_data;
130 u32 msr_lo, msr_hi, mult;
131 unsigned int fsb = 0;
132
133 rdmsr(0x2c, msr_lo, msr_hi);
134
135 dprintk("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
136
137 /* decode the FSB: see IA-32 Intel (C) Architecture Software
138 * Developer's Manual, Volume 3: System Prgramming Guide,
139 * revision #12 in Table B-1: MSRs in the Pentium 4 and
140 * Intel Xeon Processors, on page B-4 and B-5.
141 */
142 if (c->x86_model < 2)
143 fsb = 100 * 1000;
144 else {
145 u8 fsb_code = (msr_lo >> 16) & 0x7;
146 switch (fsb_code) {
147 case 0:
148 fsb = 100 * 1000;
149 break;
150 case 1:
151 fsb = 13333 * 10;
152 break;
153 case 2:
154 fsb = 200 * 1000;
155 break;
156 }
157 }
158
159 if (!fsb)
160 printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to <linux@brodo.de>\n");
161
162 /* Multiplier. */
163 if (c->x86_model < 2)
164 mult = msr_lo >> 27;
165 else
166 mult = msr_lo >> 24;
167
168 dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult));
169
170 return (fsb * mult);
171}
172
173
174unsigned int speedstep_get_processor_frequency(unsigned int processor)
175{
176 switch (processor) {
177 case SPEEDSTEP_PROCESSOR_PM:
178 return pentiumM_get_frequency();
179 case SPEEDSTEP_PROCESSOR_P4D:
180 case SPEEDSTEP_PROCESSOR_P4M:
181 return pentium4_get_frequency();
182 case SPEEDSTEP_PROCESSOR_PIII_T:
183 case SPEEDSTEP_PROCESSOR_PIII_C:
184 case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
185 return pentium3_get_frequency(processor);
186 default:
187 return 0;
188 };
189 return 0;
190}
191EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency);
192
193
194/*********************************************************************
195 * DETECT SPEEDSTEP-CAPABLE PROCESSOR *
196 *********************************************************************/
197
198unsigned int speedstep_detect_processor (void)
199{
200 struct cpuinfo_x86 *c = cpu_data;
201 u32 ebx, msr_lo, msr_hi;
202
203 dprintk("x86: %x, model: %x\n", c->x86, c->x86_model);
204
205 if ((c->x86_vendor != X86_VENDOR_INTEL) ||
206 ((c->x86 != 6) && (c->x86 != 0xF)))
207 return 0;
208
209 if (c->x86 == 0xF) {
210 /* Intel Mobile Pentium 4-M
211 * or Intel Mobile Pentium 4 with 533 MHz FSB */
212 if (c->x86_model != 2)
213 return 0;
214
215 ebx = cpuid_ebx(0x00000001);
216 ebx &= 0x000000FF;
217
218 dprintk("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask);
219
220 switch (c->x86_mask) {
221 case 4:
222 /*
223 * B-stepping [M-P4-M]
224 * sample has ebx = 0x0f, production has 0x0e.
225 */
226 if ((ebx == 0x0e) || (ebx == 0x0f))
227 return SPEEDSTEP_PROCESSOR_P4M;
228 break;
229 case 7:
230 /*
231 * C-stepping [M-P4-M]
232 * needs to have ebx=0x0e, else it's a celeron:
233 * cf. 25130917.pdf / page 7, footnote 5 even
234 * though 25072120.pdf / page 7 doesn't say
235 * samples are only of B-stepping...
236 */
237 if (ebx == 0x0e)
238 return SPEEDSTEP_PROCESSOR_P4M;
239 break;
240 case 9:
241 /*
242 * D-stepping [M-P4-M or M-P4/533]
243 *
244 * this is totally strange: CPUID 0x0F29 is
245 * used by M-P4-M, M-P4/533 and(!) Celeron CPUs.
246 * The latter need to be sorted out as they don't
247 * support speedstep.
248 * Celerons with CPUID 0x0F29 may have either
249 * ebx=0x8 or 0xf -- 25130917.pdf doesn't say anything
250 * specific.
251 * M-P4-Ms may have either ebx=0xe or 0xf [see above]
252 * M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf]
253 * also, M-P4M HTs have ebx=0x8, too
254 * For now, they are distinguished by the model_id string
255 */
256 if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL))
257 return SPEEDSTEP_PROCESSOR_P4M;
258 break;
259 default:
260 break;
261 }
262 return 0;
263 }
264
265 switch (c->x86_model) {
266 case 0x0B: /* Intel PIII [Tualatin] */
267 /* cpuid_ebx(1) is 0x04 for desktop PIII,
268 0x06 for mobile PIII-M */
269 ebx = cpuid_ebx(0x00000001);
270 dprintk("ebx is %x\n", ebx);
271
272 ebx &= 0x000000FF;
273
274 if (ebx != 0x06)
275 return 0;
276
277 /* So far all PIII-M processors support SpeedStep. See
278 * Intel's 24540640.pdf of June 2003
279 */
280
281 return SPEEDSTEP_PROCESSOR_PIII_T;
282
283 case 0x08: /* Intel PIII [Coppermine] */
284
285 /* all mobile PIII Coppermines have FSB 100 MHz
286 * ==> sort out a few desktop PIIIs. */
287 rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi);
288 dprintk("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi);
289 msr_lo &= 0x00c0000;
290 if (msr_lo != 0x0080000)
291 return 0;
292
293 /*
294 * If the processor is a mobile version,
295 * platform ID has bit 50 set
296 * it has SpeedStep technology if either
297 * bit 56 or 57 is set
298 */
299 rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi);
300 dprintk("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi);
301 if ((msr_hi & (1<<18)) && (relaxed_check ? 1 : (msr_hi & (3<<24)))) {
302 if (c->x86_mask == 0x01) {
303 dprintk("early PIII version\n");
304 return SPEEDSTEP_PROCESSOR_PIII_C_EARLY;
305 } else
306 return SPEEDSTEP_PROCESSOR_PIII_C;
307 }
308
309 default:
310 return 0;
311 }
312}
313EXPORT_SYMBOL_GPL(speedstep_detect_processor);
314
315
316/*********************************************************************
317 * DETECT SPEEDSTEP SPEEDS *
318 *********************************************************************/
319
320unsigned int speedstep_get_freqs(unsigned int processor,
321 unsigned int *low_speed,
322 unsigned int *high_speed,
323 void (*set_state) (unsigned int state))
324{
325 unsigned int prev_speed;
326 unsigned int ret = 0;
327 unsigned long flags;
328
329 if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
330 return -EINVAL;
331
332 dprintk("trying to determine both speeds\n");
333
334 /* get current speed */
335 prev_speed = speedstep_get_processor_frequency(processor);
336 if (!prev_speed)
337 return -EIO;
338
339 dprintk("previous seped is %u\n", prev_speed);
340
341 local_irq_save(flags);
342
343 /* switch to low state */
344 set_state(SPEEDSTEP_LOW);
345 *low_speed = speedstep_get_processor_frequency(processor);
346 if (!*low_speed) {
347 ret = -EIO;
348 goto out;
349 }
350
351 dprintk("low seped is %u\n", *low_speed);
352
353 /* switch to high state */
354 set_state(SPEEDSTEP_HIGH);
355 *high_speed = speedstep_get_processor_frequency(processor);
356 if (!*high_speed) {
357 ret = -EIO;
358 goto out;
359 }
360
361 dprintk("high seped is %u\n", *high_speed);
362
363 if (*low_speed == *high_speed) {
364 ret = -ENODEV;
365 goto out;
366 }
367
368 /* switch to previous state, if necessary */
369 if (*high_speed != prev_speed)
370 set_state(SPEEDSTEP_LOW);
371
372 out:
373 local_irq_restore(flags);
374 return (ret);
375}
376EXPORT_SYMBOL_GPL(speedstep_get_freqs);
377
378#ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK
379module_param(relaxed_check, int, 0444);
380MODULE_PARM_DESC(relaxed_check, "Don't do all checks for speedstep capability.");
381#endif
382
383MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
384MODULE_DESCRIPTION ("Library for Intel SpeedStep 1 or 2 cpufreq drivers.");
385MODULE_LICENSE ("GPL");
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
new file mode 100644
index 000000000000..261a2c9b7f6b
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
@@ -0,0 +1,47 @@
1/*
2 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Library for common functions for Intel SpeedStep v.1 and v.2 support
7 *
8 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
9 */
10
11
12
13/* processors */
14
15#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */
16#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */
17#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */
18#define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M */
19
20/* the following processors are not speedstep-capable and are not auto-detected
21 * in speedstep_detect_processor(). However, their speed can be detected using
22 * the speedstep_get_processor_frequency() call. */
23#define SPEEDSTEP_PROCESSOR_PM 0xFFFFFF03 /* Pentium M */
24#define SPEEDSTEP_PROCESSOR_P4D 0xFFFFFF04 /* desktop P4 */
25
26/* speedstep states -- only two of them */
27
28#define SPEEDSTEP_HIGH 0x00000000
29#define SPEEDSTEP_LOW 0x00000001
30
31
32/* detect a speedstep-capable processor */
33extern unsigned int speedstep_detect_processor (void);
34
35/* detect the current speed (in khz) of the processor */
36extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
37
38
39/* detect the low and high speeds of the processor. The callback
40 * set_state"'s first argument is either SPEEDSTEP_HIGH or
41 * SPEEDSTEP_LOW; the second argument is zero so that no
42 * cpufreq_notify_transition calls are initiated.
43 */
44extern unsigned int speedstep_get_freqs(unsigned int processor,
45 unsigned int *low_speed,
46 unsigned int *high_speed,
47 void (*set_state) (unsigned int state));
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
new file mode 100644
index 000000000000..79440b3f087e
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -0,0 +1,424 @@
1/*
2 * Intel SpeedStep SMI driver.
3 *
4 * (C) 2003 Hiroshi Miura <miura@da-cha.org>
5 *
6 * Licensed under the terms of the GNU GPL License version 2.
7 *
8 */
9
10
11/*********************************************************************
12 * SPEEDSTEP - DEFINITIONS *
13 *********************************************************************/
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/init.h>
19#include <linux/cpufreq.h>
20#include <linux/pci.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <asm/ist.h>
24
25#include "speedstep-lib.h"
26
27/* speedstep system management interface port/command.
28 *
29 * These parameters are got from IST-SMI BIOS call.
30 * If user gives it, these are used.
31 *
32 */
33static int smi_port = 0;
34static int smi_cmd = 0;
35static unsigned int smi_sig = 0;
36
37/* info about the processor */
38static unsigned int speedstep_processor = 0;
39
40/*
41 * There are only two frequency states for each processor. Values
42 * are in kHz for the time being.
43 */
44static struct cpufreq_frequency_table speedstep_freqs[] = {
45 {SPEEDSTEP_HIGH, 0},
46 {SPEEDSTEP_LOW, 0},
47 {0, CPUFREQ_TABLE_END},
48};
49
50#define GET_SPEEDSTEP_OWNER 0
51#define GET_SPEEDSTEP_STATE 1
52#define SET_SPEEDSTEP_STATE 2
53#define GET_SPEEDSTEP_FREQS 4
54
55/* how often shall the SMI call be tried if it failed, e.g. because
56 * of DMA activity going on? */
57#define SMI_TRIES 5
58
59#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-smi", msg)
60
61/**
62 * speedstep_smi_ownership
63 */
64static int speedstep_smi_ownership (void)
65{
66 u32 command, result, magic;
67 u32 function = GET_SPEEDSTEP_OWNER;
68 unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation";
69
70 command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
71 magic = virt_to_phys(magic_data);
72
73 dprintk("trying to obtain ownership with command %x at port %x\n", command, smi_port);
74
75 __asm__ __volatile__(
76 "out %%al, (%%dx)\n"
77 : "=D" (result)
78 : "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic)
79 );
80
81 dprintk("result is %x\n", result);
82
83 return result;
84}
85
86/**
87 * speedstep_smi_get_freqs - get SpeedStep preferred & current freq.
88 * @low: the low frequency value is placed here
89 * @high: the high frequency value is placed here
90 *
91 * Only available on later SpeedStep-enabled systems, returns false results or
92 * even hangs [cf. bugme.osdl.org # 1422] on earlier systems. Empirical testing
93 * shows that the latter occurs if !(ist_info.event & 0xFFFF).
94 */
95static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
96{
97 u32 command, result = 0, edi, high_mhz, low_mhz;
98 u32 state=0;
99 u32 function = GET_SPEEDSTEP_FREQS;
100
101 if (!(ist_info.event & 0xFFFF)) {
102 dprintk("bug #1422 -- can't read freqs from BIOS\n", result);
103 return -ENODEV;
104 }
105
106 command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
107
108 dprintk("trying to determine frequencies with command %x at port %x\n", command, smi_port);
109
110 __asm__ __volatile__("movl $0, %%edi\n"
111 "out %%al, (%%dx)\n"
112 : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi)
113 : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
114 );
115
116 dprintk("result %x, low_freq %u, high_freq %u\n", result, low_mhz, high_mhz);
117
118 /* abort if results are obviously incorrect... */
119 if ((high_mhz + low_mhz) < 600)
120 return -EINVAL;
121
122 *high = high_mhz * 1000;
123 *low = low_mhz * 1000;
124
125 return result;
126}
127
128/**
129 * speedstep_get_state - set the SpeedStep state
130 * @state: processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
131 *
132 */
133static int speedstep_get_state (void)
134{
135 u32 function=GET_SPEEDSTEP_STATE;
136 u32 result, state, edi, command;
137
138 command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
139
140 dprintk("trying to determine current setting with command %x at port %x\n", command, smi_port);
141
142 __asm__ __volatile__("movl $0, %%edi\n"
143 "out %%al, (%%dx)\n"
144 : "=a" (result), "=b" (state), "=D" (edi)
145 : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0)
146 );
147
148 dprintk("state is %x, result is %x\n", state, result);
149
150 return (state & 1);
151}
152
153
154/**
155 * speedstep_set_state - set the SpeedStep state
156 * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
157 *
158 */
159static void speedstep_set_state (unsigned int state)
160{
161 unsigned int result = 0, command, new_state;
162 unsigned long flags;
163 unsigned int function=SET_SPEEDSTEP_STATE;
164 unsigned int retry = 0;
165
166 if (state > 0x1)
167 return;
168
169 /* Disable IRQs */
170 local_irq_save(flags);
171
172 command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
173
174 dprintk("trying to set frequency to state %u with command %x at port %x\n", state, command, smi_port);
175
176 do {
177 if (retry) {
178 dprintk("retry %u, previous result %u, waiting...\n", retry, result);
179 mdelay(retry * 50);
180 }
181 retry++;
182 __asm__ __volatile__(
183 "movl $0, %%edi\n"
184 "out %%al, (%%dx)\n"
185 : "=b" (new_state), "=D" (result)
186 : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
187 );
188 } while ((new_state != state) && (retry <= SMI_TRIES));
189
190 /* enable IRQs */
191 local_irq_restore(flags);
192
193 if (new_state == state) {
194 dprintk("change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result);
195 } else {
196 printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result);
197 }
198
199 return;
200}
201
202
203/**
204 * speedstep_target - set a new CPUFreq policy
205 * @policy: new policy
206 * @target_freq: new freq
207 * @relation:
208 *
209 * Sets a new CPUFreq policy/freq.
210 */
211static int speedstep_target (struct cpufreq_policy *policy,
212 unsigned int target_freq, unsigned int relation)
213{
214 unsigned int newstate = 0;
215 struct cpufreq_freqs freqs;
216
217 if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
218 return -EINVAL;
219
220 freqs.old = speedstep_freqs[speedstep_get_state()].frequency;
221 freqs.new = speedstep_freqs[newstate].frequency;
222 freqs.cpu = 0; /* speedstep.c is UP only driver */
223
224 if (freqs.old == freqs.new)
225 return 0;
226
227 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
228 speedstep_set_state(newstate);
229 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
230
231 return 0;
232}
233
234
235/**
236 * speedstep_verify - verifies a new CPUFreq policy
237 * @policy: new policy
238 *
239 * Limit must be within speedstep_low_freq and speedstep_high_freq, with
240 * at least one border included.
241 */
242static int speedstep_verify (struct cpufreq_policy *policy)
243{
244 return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
245}
246
247
248static int speedstep_cpu_init(struct cpufreq_policy *policy)
249{
250 int result;
251 unsigned int speed,state;
252
253 /* capability check */
254 if (policy->cpu != 0)
255 return -ENODEV;
256
257 result = speedstep_smi_ownership();
258 if (result) {
259 dprintk("fails in aquiring ownership of a SMI interface.\n");
260 return -EINVAL;
261 }
262
263 /* detect low and high frequency */
264 result = speedstep_smi_get_freqs(&speedstep_freqs[SPEEDSTEP_LOW].frequency,
265 &speedstep_freqs[SPEEDSTEP_HIGH].frequency);
266 if (result) {
267 /* fall back to speedstep_lib.c dection mechanism: try both states out */
268 dprintk("could not detect low and high frequencies by SMI call.\n");
269 result = speedstep_get_freqs(speedstep_processor,
270 &speedstep_freqs[SPEEDSTEP_LOW].frequency,
271 &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
272 &speedstep_set_state);
273
274 if (result) {
275 dprintk("could not detect two different speeds -- aborting.\n");
276 return result;
277 } else
278 dprintk("workaround worked.\n");
279 }
280
281 /* get current speed setting */
282 state = speedstep_get_state();
283 speed = speedstep_freqs[state].frequency;
284
285 dprintk("currently at %s speed setting - %i MHz\n",
286 (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
287 (speed / 1000));
288
289 /* cpuinfo and default policy values */
290 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
291 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
292 policy->cur = speed;
293
294 result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
295 if (result)
296 return (result);
297
298 cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
299
300 return 0;
301}
302
303static int speedstep_cpu_exit(struct cpufreq_policy *policy)
304{
305 cpufreq_frequency_table_put_attr(policy->cpu);
306 return 0;
307}
308
309static unsigned int speedstep_get(unsigned int cpu)
310{
311 if (cpu)
312 return -ENODEV;
313 return speedstep_get_processor_frequency(speedstep_processor);
314}
315
316
317static int speedstep_resume(struct cpufreq_policy *policy)
318{
319 int result = speedstep_smi_ownership();
320
321 if (result)
322 dprintk("fails in re-aquiring ownership of a SMI interface.\n");
323
324 return result;
325}
326
327static struct freq_attr* speedstep_attr[] = {
328 &cpufreq_freq_attr_scaling_available_freqs,
329 NULL,
330};
331
332static struct cpufreq_driver speedstep_driver = {
333 .name = "speedstep-smi",
334 .verify = speedstep_verify,
335 .target = speedstep_target,
336 .init = speedstep_cpu_init,
337 .exit = speedstep_cpu_exit,
338 .get = speedstep_get,
339 .resume = speedstep_resume,
340 .owner = THIS_MODULE,
341 .attr = speedstep_attr,
342};
343
344/**
345 * speedstep_init - initializes the SpeedStep CPUFreq driver
346 *
347 * Initializes the SpeedStep support. Returns -ENODEV on unsupported
348 * BIOS, -EINVAL on problems during initiatization, and zero on
349 * success.
350 */
351static int __init speedstep_init(void)
352{
353 speedstep_processor = speedstep_detect_processor();
354
355 switch (speedstep_processor) {
356 case SPEEDSTEP_PROCESSOR_PIII_T:
357 case SPEEDSTEP_PROCESSOR_PIII_C:
358 case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
359 break;
360 default:
361 speedstep_processor = 0;
362 }
363
364 if (!speedstep_processor) {
365 dprintk ("No supported Intel CPU detected.\n");
366 return -ENODEV;
367 }
368
369 dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n",
370 ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level);
371
372
373 /* Error if no IST-SMI BIOS or no PARM
374 sig= 'ISGE' aka 'Intel Speedstep Gate E' */
375 if ((ist_info.signature != 0x47534943) && (
376 (smi_port == 0) || (smi_cmd == 0)))
377 return -ENODEV;
378
379 if (smi_sig == 1)
380 smi_sig = 0x47534943;
381 else
382 smi_sig = ist_info.signature;
383
384 /* setup smi_port from MODLULE_PARM or BIOS */
385 if ((smi_port > 0xff) || (smi_port < 0)) {
386 return -EINVAL;
387 } else if (smi_port == 0) {
388 smi_port = ist_info.command & 0xff;
389 }
390
391 if ((smi_cmd > 0xff) || (smi_cmd < 0)) {
392 return -EINVAL;
393 } else if (smi_cmd == 0) {
394 smi_cmd = (ist_info.command >> 16) & 0xff;
395 }
396
397 return cpufreq_register_driver(&speedstep_driver);
398}
399
400
401/**
402 * speedstep_exit - unregisters SpeedStep support
403 *
404 * Unregisters SpeedStep support.
405 */
406static void __exit speedstep_exit(void)
407{
408 cpufreq_unregister_driver(&speedstep_driver);
409}
410
411module_param(smi_port, int, 0444);
412module_param(smi_cmd, int, 0444);
413module_param(smi_sig, uint, 0444);
414
415MODULE_PARM_DESC(smi_port, "Override the BIOS-given IST port with this value -- Intel's default setting is 0xb2");
416MODULE_PARM_DESC(smi_cmd, "Override the BIOS-given IST command with this value -- Intel's default setting is 0x82");
417MODULE_PARM_DESC(smi_sig, "Set to 1 to fake the IST signature when using the SMI interface.");
418
419MODULE_AUTHOR ("Hiroshi Miura");
420MODULE_DESCRIPTION ("Speedstep driver for IST applet SMI interface.");
421MODULE_LICENSE ("GPL");
422
423module_init(speedstep_init);
424module_exit(speedstep_exit);
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
new file mode 100644
index 000000000000..ba4b01138c8f
--- /dev/null
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -0,0 +1,439 @@
1#include <linux/init.h>
2#include <linux/bitops.h>
3#include <linux/delay.h>
4#include <linux/pci.h>
5#include <asm/dma.h>
6#include <asm/io.h>
7#include <asm/processor.h>
8#include <asm/timer.h>
9
10#include "cpu.h"
11
12/*
13 * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
14 */
15static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
16{
17 unsigned char ccr2, ccr3;
18 unsigned long flags;
19
20 /* we test for DEVID by checking whether CCR3 is writable */
21 local_irq_save(flags);
22 ccr3 = getCx86(CX86_CCR3);
23 setCx86(CX86_CCR3, ccr3 ^ 0x80);
24 getCx86(0xc0); /* dummy to change bus */
25
26 if (getCx86(CX86_CCR3) == ccr3) { /* no DEVID regs. */
27 ccr2 = getCx86(CX86_CCR2);
28 setCx86(CX86_CCR2, ccr2 ^ 0x04);
29 getCx86(0xc0); /* dummy */
30
31 if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
32 *dir0 = 0xfd;
33 else { /* Cx486S A step */
34 setCx86(CX86_CCR2, ccr2);
35 *dir0 = 0xfe;
36 }
37 }
38 else {
39 setCx86(CX86_CCR3, ccr3); /* restore CCR3 */
40
41 /* read DIR0 and DIR1 CPU registers */
42 *dir0 = getCx86(CX86_DIR0);
43 *dir1 = getCx86(CX86_DIR1);
44 }
45 local_irq_restore(flags);
46}
47
48/*
49 * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
50 * order to identify the Cyrix CPU model after we're out of setup.c
51 *
52 * Actually since bugs.h doesn't even reference this perhaps someone should
53 * fix the documentation ???
54 */
55static unsigned char Cx86_dir0_msb __initdata = 0;
56
57static char Cx86_model[][9] __initdata = {
58 "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
59 "M II ", "Unknown"
60};
61static char Cx486_name[][5] __initdata = {
62 "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
63 "SRx2", "DRx2"
64};
65static char Cx486S_name[][4] __initdata = {
66 "S", "S2", "Se", "S2e"
67};
68static char Cx486D_name[][4] __initdata = {
69 "DX", "DX2", "?", "?", "?", "DX4"
70};
71static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
72static char cyrix_model_mult1[] __initdata = "12??43";
73static char cyrix_model_mult2[] __initdata = "12233445";
74
75/*
76 * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
77 * BIOSes for compatibility with DOS games. This makes the udelay loop
78 * work correctly, and improves performance.
79 *
80 * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
81 */
82
83extern void calibrate_delay(void) __init;
84
85static void __init check_cx686_slop(struct cpuinfo_x86 *c)
86{
87 unsigned long flags;
88
89 if (Cx86_dir0_msb == 3) {
90 unsigned char ccr3, ccr5;
91
92 local_irq_save(flags);
93 ccr3 = getCx86(CX86_CCR3);
94 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
95 ccr5 = getCx86(CX86_CCR5);
96 if (ccr5 & 2)
97 setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */
98 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
99 local_irq_restore(flags);
100
101 if (ccr5 & 2) { /* possible wrong calibration done */
102 printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");
103 calibrate_delay();
104 c->loops_per_jiffy = loops_per_jiffy;
105 }
106 }
107}
108
109
110static void __init set_cx86_reorder(void)
111{
112 u8 ccr3;
113
114 printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n");
115 ccr3 = getCx86(CX86_CCR3);
116 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
117
118 /* Load/Store Serialize to mem access disable (=reorder it)  */
119 setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80);
120 /* set load/store serialize from 1GB to 4GB */
121 ccr3 |= 0xe0;
122 setCx86(CX86_CCR3, ccr3);
123}
124
125static void __init set_cx86_memwb(void)
126{
127 u32 cr0;
128
129 printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
130
131 /* CCR2 bit 2: unlock NW bit */
132 setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
133 /* set 'Not Write-through' */
134 cr0 = 0x20000000;
135 __asm__("movl %%cr0,%%eax\n\t"
136 "orl %0,%%eax\n\t"
137 "movl %%eax,%%cr0\n"
138 : : "r" (cr0)
139 :"ax");
140 /* CCR2 bit 2: lock NW bit and set WT1 */
141 setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
142}
143
144static void __init set_cx86_inc(void)
145{
146 unsigned char ccr3;
147
148 printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
149
150 ccr3 = getCx86(CX86_CCR3);
151 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
152 /* PCR1 -- Performance Control */
153 /* Incrementor on, whatever that is */
154 setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
155 /* PCR0 -- Performance Control */
156 /* Incrementor Margin 10 */
157 setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
158 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
159}
160
161/*
162 * Configure later MediaGX and/or Geode processor.
163 */
164
165static void __init geode_configure(void)
166{
167 unsigned long flags;
168 u8 ccr3, ccr4;
169 local_irq_save(flags);
170
171 /* Suspend on halt power saving and enable #SUSP pin */
172 setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
173
174 ccr3 = getCx86(CX86_CCR3);
175 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* Enable */
176
177 ccr4 = getCx86(CX86_CCR4);
178 ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */
179
180 setCx86(CX86_CCR3, ccr3);
181
182 set_cx86_memwb();
183 set_cx86_reorder();
184 set_cx86_inc();
185
186 local_irq_restore(flags);
187}
188
189
190#ifdef CONFIG_PCI
191static struct pci_device_id cyrix_55x0[] = {
192 { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) },
193 { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) },
194 { },
195};
196#endif
197
198static void __init init_cyrix(struct cpuinfo_x86 *c)
199{
200 unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
201 char *buf = c->x86_model_id;
202 const char *p = NULL;
203
204 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
205 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
206 clear_bit(0*32+31, c->x86_capability);
207
208 /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
209 if ( test_bit(1*32+24, c->x86_capability) ) {
210 clear_bit(1*32+24, c->x86_capability);
211 set_bit(X86_FEATURE_CXMMX, c->x86_capability);
212 }
213
214 do_cyrix_devid(&dir0, &dir1);
215
216 check_cx686_slop(c);
217
218 Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */
219 dir0_lsn = dir0 & 0xf; /* model or clock multiplier */
220
221 /* common case step number/rev -- exceptions handled below */
222 c->x86_model = (dir1 >> 4) + 1;
223 c->x86_mask = dir1 & 0xf;
224
225 /* Now cook; the original recipe is by Channing Corn, from Cyrix.
226 * We do the same thing for each generation: we work out
227 * the model, multiplier and stepping. Black magic included,
228 * to make the silicon step/rev numbers match the printed ones.
229 */
230
231 switch (dir0_msn) {
232 unsigned char tmp;
233
234 case 0: /* Cx486SLC/DLC/SRx/DRx */
235 p = Cx486_name[dir0_lsn & 7];
236 break;
237
238 case 1: /* Cx486S/DX/DX2/DX4 */
239 p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5]
240 : Cx486S_name[dir0_lsn & 3];
241 break;
242
243 case 2: /* 5x86 */
244 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
245 p = Cx86_cb+2;
246 break;
247
248 case 3: /* 6x86/6x86L */
249 Cx86_cb[1] = ' ';
250 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
251 if (dir1 > 0x21) { /* 686L */
252 Cx86_cb[0] = 'L';
253 p = Cx86_cb;
254 (c->x86_model)++;
255 } else /* 686 */
256 p = Cx86_cb+1;
257 /* Emulate MTRRs using Cyrix's ARRs. */
258 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
259 /* 6x86's contain this bug */
260 c->coma_bug = 1;
261 break;
262
263 case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
264#ifdef CONFIG_PCI
265 /* It isn't really a PCI quirk directly, but the cure is the
266 same. The MediaGX has deep magic SMM stuff that handles the
267 SB emulation. It thows away the fifo on disable_dma() which
268 is wrong and ruins the audio.
269
270 Bug2: VSA1 has a wrap bug so that using maximum sized DMA
271 causes bad things. According to NatSemi VSA2 has another
272 bug to do with 'hlt'. I've not seen any boards using VSA2
273 and X doesn't seem to support it either so who cares 8).
274 VSA1 we work around however.
275 */
276
277 printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
278 isa_dma_bridge_buggy = 2;
279#endif
280 c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
281
282 /*
283 * The 5510/5520 companion chips have a funky PIT.
284 */
285 if (pci_dev_present(cyrix_55x0))
286 pit_latch_buggy = 1;
287
288 /* GXm supports extended cpuid levels 'ala' AMD */
289 if (c->cpuid_level == 2) {
290 /* Enable cxMMX extensions (GX1 Datasheet 54) */
291 setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
292
293 /* GXlv/GXm/GX1 */
294 if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63)
295 geode_configure();
296 get_model_name(c); /* get CPU marketing name */
297 return;
298 }
299 else { /* MediaGX */
300 Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
301 p = Cx86_cb+2;
302 c->x86_model = (dir1 & 0x20) ? 1 : 2;
303 }
304 break;
305
306 case 5: /* 6x86MX/M II */
307 if (dir1 > 7)
308 {
309 dir0_msn++; /* M II */
310 /* Enable MMX extensions (App note 108) */
311 setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
312 }
313 else
314 {
315 c->coma_bug = 1; /* 6x86MX, it has the bug. */
316 }
317 tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
318 Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
319 p = Cx86_cb+tmp;
320 if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
321 (c->x86_model)++;
322 /* Emulate MTRRs using Cyrix's ARRs. */
323 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
324 break;
325
326 case 0xf: /* Cyrix 486 without DEVID registers */
327 switch (dir0_lsn) {
328 case 0xd: /* either a 486SLC or DLC w/o DEVID */
329 dir0_msn = 0;
330 p = Cx486_name[(c->hard_math) ? 1 : 0];
331 break;
332
333 case 0xe: /* a 486S A step */
334 dir0_msn = 0;
335 p = Cx486S_name[0];
336 break;
337 }
338 break;
339
340 default: /* unknown (shouldn't happen, we know everyone ;-) */
341 dir0_msn = 7;
342 break;
343 }
344 strcpy(buf, Cx86_model[dir0_msn & 7]);
345 if (p) strcat(buf, p);
346 return;
347}
348
349/*
350 * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
351 * by the fact that they preserve the flags across the division of 5/2.
352 * PII and PPro exhibit this behavior too, but they have cpuid available.
353 */
354
355/*
356 * Perform the Cyrix 5/2 test. A Cyrix won't change
357 * the flags, while other 486 chips will.
358 */
359static inline int test_cyrix_52div(void)
360{
361 unsigned int test;
362
363 __asm__ __volatile__(
364 "sahf\n\t" /* clear flags (%eax = 0x0005) */
365 "div %b2\n\t" /* divide 5 by 2 */
366 "lahf" /* store flags into %ah */
367 : "=a" (test)
368 : "0" (5), "q" (2)
369 : "cc");
370
371 /* AH is 0x02 on Cyrix after the divide.. */
372 return (unsigned char) (test >> 8) == 0x02;
373}
374
375static void cyrix_identify(struct cpuinfo_x86 * c)
376{
377 /* Detect Cyrix with disabled CPUID */
378 if ( c->x86 == 4 && test_cyrix_52div() ) {
379 unsigned char dir0, dir1;
380
381 strcpy(c->x86_vendor_id, "CyrixInstead");
382 c->x86_vendor = X86_VENDOR_CYRIX;
383
384 /* Actually enable cpuid on the older cyrix */
385
386 /* Retrieve CPU revisions */
387
388 do_cyrix_devid(&dir0, &dir1);
389
390 dir0>>=4;
391
392 /* Check it is an affected model */
393
394 if (dir0 == 5 || dir0 == 3)
395 {
396 unsigned char ccr3, ccr4;
397 unsigned long flags;
398 printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
399 local_irq_save(flags);
400 ccr3 = getCx86(CX86_CCR3);
401 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
402 ccr4 = getCx86(CX86_CCR4);
403 setCx86(CX86_CCR4, ccr4 | 0x80); /* enable cpuid */
404 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
405 local_irq_restore(flags);
406 }
407 }
408 generic_identify(c);
409}
410
411static struct cpu_dev cyrix_cpu_dev __initdata = {
412 .c_vendor = "Cyrix",
413 .c_ident = { "CyrixInstead" },
414 .c_init = init_cyrix,
415 .c_identify = cyrix_identify,
416};
417
418int __init cyrix_init_cpu(void)
419{
420 cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
421 return 0;
422}
423
424//early_arch_initcall(cyrix_init_cpu);
425
426static struct cpu_dev nsc_cpu_dev __initdata = {
427 .c_vendor = "NSC",
428 .c_ident = { "Geode by NSC" },
429 .c_init = init_cyrix,
430 .c_identify = generic_identify,
431};
432
433int __init nsc_init_cpu(void)
434{
435 cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
436 return 0;
437}
438
439//early_arch_initcall(nsc_init_cpu);
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
new file mode 100644
index 000000000000..b8d847b850dc
--- /dev/null
+++ b/arch/i386/kernel/cpu/intel.c
@@ -0,0 +1,248 @@
1#include <linux/config.h>
2#include <linux/init.h>
3#include <linux/kernel.h>
4
5#include <linux/string.h>
6#include <linux/bitops.h>
7#include <linux/smp.h>
8#include <linux/thread_info.h>
9
10#include <asm/processor.h>
11#include <asm/msr.h>
12#include <asm/uaccess.h>
13
14#include "cpu.h"
15
16#ifdef CONFIG_X86_LOCAL_APIC
17#include <asm/mpspec.h>
18#include <asm/apic.h>
19#include <mach_apic.h>
20#endif
21
22extern int trap_init_f00f_bug(void);
23
24#ifdef CONFIG_X86_INTEL_USERCOPY
25/*
26 * Alignment at which movsl is preferred for bulk memory copies.
27 */
28struct movsl_mask movsl_mask;
29#endif
30
31void __init early_intel_workaround(struct cpuinfo_x86 *c)
32{
33 if (c->x86_vendor != X86_VENDOR_INTEL)
34 return;
35 /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */
36 if (c->x86 == 15 && c->x86_cache_alignment == 64)
37 c->x86_cache_alignment = 128;
38}
39
40/*
41 * Early probe support logic for ppro memory erratum #50
42 *
43 * This is called before we do cpu ident work
44 */
45
46int __init ppro_with_ram_bug(void)
47{
48 /* Uses data from early_cpu_detect now */
49 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
50 boot_cpu_data.x86 == 6 &&
51 boot_cpu_data.x86_model == 1 &&
52 boot_cpu_data.x86_mask < 8) {
53 printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n");
54 return 1;
55 }
56 return 0;
57}
58
59
60/*
61 * P4 Xeon errata 037 workaround.
62 * Hardware prefetcher may cause stale data to be loaded into the cache.
63 */
64static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
65{
66 unsigned long lo, hi;
67
68 if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
69 rdmsr (MSR_IA32_MISC_ENABLE, lo, hi);
70 if ((lo & (1<<9)) == 0) {
71 printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n");
72 printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n");
73 lo |= (1<<9); /* Disable hw prefetching */
74 wrmsr (MSR_IA32_MISC_ENABLE, lo, hi);
75 }
76 }
77}
78
79
80static void __init init_intel(struct cpuinfo_x86 *c)
81{
82 unsigned int l2 = 0;
83 char *p = NULL;
84
85#ifdef CONFIG_X86_F00F_BUG
86 /*
87 * All current models of Pentium and Pentium with MMX technology CPUs
88 * have the F0 0F bug, which lets nonprivileged users lock up the system.
89 * Note that the workaround only should be initialized once...
90 */
91 c->f00f_bug = 0;
92 if ( c->x86 == 5 ) {
93 static int f00f_workaround_enabled = 0;
94
95 c->f00f_bug = 1;
96 if ( !f00f_workaround_enabled ) {
97 trap_init_f00f_bug();
98 printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
99 f00f_workaround_enabled = 1;
100 }
101 }
102#endif
103
104 select_idle_routine(c);
105 l2 = init_intel_cacheinfo(c);
106
107 /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
108 if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
109 clear_bit(X86_FEATURE_SEP, c->x86_capability);
110
111 /* Names for the Pentium II/Celeron processors
112 detectable only by also checking the cache size.
113 Dixon is NOT a Celeron. */
114 if (c->x86 == 6) {
115 switch (c->x86_model) {
116 case 5:
117 if (c->x86_mask == 0) {
118 if (l2 == 0)
119 p = "Celeron (Covington)";
120 else if (l2 == 256)
121 p = "Mobile Pentium II (Dixon)";
122 }
123 break;
124
125 case 6:
126 if (l2 == 128)
127 p = "Celeron (Mendocino)";
128 else if (c->x86_mask == 0 || c->x86_mask == 5)
129 p = "Celeron-A";
130 break;
131
132 case 8:
133 if (l2 == 128)
134 p = "Celeron (Coppermine)";
135 break;
136 }
137 }
138
139 if ( p )
140 strcpy(c->x86_model_id, p);
141
142 detect_ht(c);
143
144 /* Work around errata */
145 Intel_errata_workarounds(c);
146
147#ifdef CONFIG_X86_INTEL_USERCOPY
148 /*
149 * Set up the preferred alignment for movsl bulk memory moves
150 */
151 switch (c->x86) {
152 case 4: /* 486: untested */
153 break;
154 case 5: /* Old Pentia: untested */
155 break;
156 case 6: /* PII/PIII only like movsl with 8-byte alignment */
157 movsl_mask.mask = 7;
158 break;
159 case 15: /* P4 is OK down to 8-byte alignment */
160 movsl_mask.mask = 7;
161 break;
162 }
163#endif
164
165 if (c->x86 == 15)
166 set_bit(X86_FEATURE_P4, c->x86_capability);
167 if (c->x86 == 6)
168 set_bit(X86_FEATURE_P3, c->x86_capability);
169}
170
171
172static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
173{
174 /* Intel PIII Tualatin. This comes in two flavours.
175 * One has 256kb of cache, the other 512. We have no way
176 * to determine which, so we use a boottime override
177 * for the 512kb model, and assume 256 otherwise.
178 */
179 if ((c->x86 == 6) && (c->x86_model == 11) && (size == 0))
180 size = 256;
181 return size;
182}
183
184static struct cpu_dev intel_cpu_dev __initdata = {
185 .c_vendor = "Intel",
186 .c_ident = { "GenuineIntel" },
187 .c_models = {
188 { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names =
189 {
190 [0] = "486 DX-25/33",
191 [1] = "486 DX-50",
192 [2] = "486 SX",
193 [3] = "486 DX/2",
194 [4] = "486 SL",
195 [5] = "486 SX/2",
196 [7] = "486 DX/2-WB",
197 [8] = "486 DX/4",
198 [9] = "486 DX/4-WB"
199 }
200 },
201 { .vendor = X86_VENDOR_INTEL, .family = 5, .model_names =
202 {
203 [0] = "Pentium 60/66 A-step",
204 [1] = "Pentium 60/66",
205 [2] = "Pentium 75 - 200",
206 [3] = "OverDrive PODP5V83",
207 [4] = "Pentium MMX",
208 [7] = "Mobile Pentium 75 - 200",
209 [8] = "Mobile Pentium MMX"
210 }
211 },
212 { .vendor = X86_VENDOR_INTEL, .family = 6, .model_names =
213 {
214 [0] = "Pentium Pro A-step",
215 [1] = "Pentium Pro",
216 [3] = "Pentium II (Klamath)",
217 [4] = "Pentium II (Deschutes)",
218 [5] = "Pentium II (Deschutes)",
219 [6] = "Mobile Pentium II",
220 [7] = "Pentium III (Katmai)",
221 [8] = "Pentium III (Coppermine)",
222 [10] = "Pentium III (Cascades)",
223 [11] = "Pentium III (Tualatin)",
224 }
225 },
226 { .vendor = X86_VENDOR_INTEL, .family = 15, .model_names =
227 {
228 [0] = "Pentium 4 (Unknown)",
229 [1] = "Pentium 4 (Willamette)",
230 [2] = "Pentium 4 (Northwood)",
231 [4] = "Pentium 4 (Foster)",
232 [5] = "Pentium 4 (Foster)",
233 }
234 },
235 },
236 .c_init = init_intel,
237 .c_identify = generic_identify,
238 .c_size_cache = intel_size_cache,
239};
240
241__init int intel_cpu_init(void)
242{
243 cpu_devs[X86_VENDOR_INTEL] = &intel_cpu_dev;
244 return 0;
245}
246
247// arch_initcall(intel_cpu_init);
248
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
new file mode 100644
index 000000000000..aeb5b4ef8c8b
--- /dev/null
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -0,0 +1,598 @@
1/*
2 * Routines to indentify caches on Intel CPU.
3 *
4 * Changes:
5 * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
6 */
7
8#include <linux/init.h>
9#include <linux/slab.h>
10#include <linux/device.h>
11#include <linux/compiler.h>
12#include <linux/cpu.h>
13
14#include <asm/processor.h>
15#include <asm/smp.h>
16
17#define LVL_1_INST 1
18#define LVL_1_DATA 2
19#define LVL_2 3
20#define LVL_3 4
21#define LVL_TRACE 5
22
23struct _cache_table
24{
25 unsigned char descriptor;
26 char cache_type;
27 short size;
28};
29
30/* all the cache descriptor types we care about (no TLB or trace cache entries) */
31static struct _cache_table cache_table[] __initdata =
32{
33 { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
34 { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
35 { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
36 { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
37 { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
38 { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
39 { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */
40 { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */
41 { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */
42 { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */
43 { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */
44 { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */
45 { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */
46 { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */
47 { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */
48 { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */
49 { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */
50 { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */
51 { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */
52 { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */
53 { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */
54 { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */
55 { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */
56 { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */
57 { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */
58 { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */
59 { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */
60 { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */
61 { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */
62 { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
63 { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */
64 { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */
65 { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */
66 { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */
67 { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */
68 { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */
69 { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
70 { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */
71 { 0x00, 0, 0}
72};
73
74
75enum _cache_type
76{
77 CACHE_TYPE_NULL = 0,
78 CACHE_TYPE_DATA = 1,
79 CACHE_TYPE_INST = 2,
80 CACHE_TYPE_UNIFIED = 3
81};
82
83union _cpuid4_leaf_eax {
84 struct {
85 enum _cache_type type:5;
86 unsigned int level:3;
87 unsigned int is_self_initializing:1;
88 unsigned int is_fully_associative:1;
89 unsigned int reserved:4;
90 unsigned int num_threads_sharing:12;
91 unsigned int num_cores_on_die:6;
92 } split;
93 u32 full;
94};
95
96union _cpuid4_leaf_ebx {
97 struct {
98 unsigned int coherency_line_size:12;
99 unsigned int physical_line_partition:10;
100 unsigned int ways_of_associativity:10;
101 } split;
102 u32 full;
103};
104
105union _cpuid4_leaf_ecx {
106 struct {
107 unsigned int number_of_sets:32;
108 } split;
109 u32 full;
110};
111
112struct _cpuid4_info {
113 union _cpuid4_leaf_eax eax;
114 union _cpuid4_leaf_ebx ebx;
115 union _cpuid4_leaf_ecx ecx;
116 unsigned long size;
117 cpumask_t shared_cpu_map;
118};
119
120#define MAX_CACHE_LEAVES 4
121static unsigned short __devinitdata num_cache_leaves;
122
123static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
124{
125 unsigned int eax, ebx, ecx, edx;
126 union _cpuid4_leaf_eax cache_eax;
127
128 cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
129 cache_eax.full = eax;
130 if (cache_eax.split.type == CACHE_TYPE_NULL)
131 return -1;
132
133 this_leaf->eax.full = eax;
134 this_leaf->ebx.full = ebx;
135 this_leaf->ecx.full = ecx;
136 this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
137 (this_leaf->ebx.split.coherency_line_size + 1) *
138 (this_leaf->ebx.split.physical_line_partition + 1) *
139 (this_leaf->ebx.split.ways_of_associativity + 1);
140 return 0;
141}
142
143static int __init find_num_cache_leaves(void)
144{
145 unsigned int eax, ebx, ecx, edx;
146 union _cpuid4_leaf_eax cache_eax;
147 int i;
148 int retval;
149
150 retval = MAX_CACHE_LEAVES;
151 /* Do cpuid(4) loop to find out num_cache_leaves */
152 for (i = 0; i < MAX_CACHE_LEAVES; i++) {
153 cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
154 cache_eax.full = eax;
155 if (cache_eax.split.type == CACHE_TYPE_NULL) {
156 retval = i;
157 break;
158 }
159 }
160 return retval;
161}
162
163unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
164{
165 unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
166 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
167 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
168
169 if (c->cpuid_level > 4) {
170 static int is_initialized;
171
172 if (is_initialized == 0) {
173 /* Init num_cache_leaves from boot CPU */
174 num_cache_leaves = find_num_cache_leaves();
175 is_initialized++;
176 }
177
178 /*
179 * Whenever possible use cpuid(4), deterministic cache
180 * parameters cpuid leaf to find the cache details
181 */
182 for (i = 0; i < num_cache_leaves; i++) {
183 struct _cpuid4_info this_leaf;
184
185 int retval;
186
187 retval = cpuid4_cache_lookup(i, &this_leaf);
188 if (retval >= 0) {
189 switch(this_leaf.eax.split.level) {
190 case 1:
191 if (this_leaf.eax.split.type ==
192 CACHE_TYPE_DATA)
193 new_l1d = this_leaf.size/1024;
194 else if (this_leaf.eax.split.type ==
195 CACHE_TYPE_INST)
196 new_l1i = this_leaf.size/1024;
197 break;
198 case 2:
199 new_l2 = this_leaf.size/1024;
200 break;
201 case 3:
202 new_l3 = this_leaf.size/1024;
203 break;
204 default:
205 break;
206 }
207 }
208 }
209 }
210 if (c->cpuid_level > 1) {
211 /* supports eax=2 call */
212 int i, j, n;
213 int regs[4];
214 unsigned char *dp = (unsigned char *)regs;
215
216 /* Number of times to iterate */
217 n = cpuid_eax(2) & 0xFF;
218
219 for ( i = 0 ; i < n ; i++ ) {
220 cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
221
222 /* If bit 31 is set, this is an unknown format */
223 for ( j = 0 ; j < 3 ; j++ ) {
224 if ( regs[j] < 0 ) regs[j] = 0;
225 }
226
227 /* Byte 0 is level count, not a descriptor */
228 for ( j = 1 ; j < 16 ; j++ ) {
229 unsigned char des = dp[j];
230 unsigned char k = 0;
231
232 /* look up this descriptor in the table */
233 while (cache_table[k].descriptor != 0)
234 {
235 if (cache_table[k].descriptor == des) {
236 switch (cache_table[k].cache_type) {
237 case LVL_1_INST:
238 l1i += cache_table[k].size;
239 break;
240 case LVL_1_DATA:
241 l1d += cache_table[k].size;
242 break;
243 case LVL_2:
244 l2 += cache_table[k].size;
245 break;
246 case LVL_3:
247 l3 += cache_table[k].size;
248 break;
249 case LVL_TRACE:
250 trace += cache_table[k].size;
251 break;
252 }
253
254 break;
255 }
256
257 k++;
258 }
259 }
260 }
261
262 if (new_l1d)
263 l1d = new_l1d;
264
265 if (new_l1i)
266 l1i = new_l1i;
267
268 if (new_l2)
269 l2 = new_l2;
270
271 if (new_l3)
272 l3 = new_l3;
273
274 if ( trace )
275 printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
276 else if ( l1i )
277 printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
278 if ( l1d )
279 printk(", L1 D cache: %dK\n", l1d);
280 else
281 printk("\n");
282 if ( l2 )
283 printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
284 if ( l3 )
285 printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
286
287 /*
288 * This assumes the L3 cache is shared; it typically lives in
289 * the northbridge. The L1 caches are included by the L2
290 * cache, and so should not be included for the purpose of
291 * SMP switching weights.
292 */
293 c->x86_cache_size = l2 ? l2 : (l1i+l1d);
294 }
295
296 return l2;
297}
298
299/* pointer to _cpuid4_info array (for each cache leaf) */
300static struct _cpuid4_info *cpuid4_info[NR_CPUS];
301#define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y]))
302
303#ifdef CONFIG_SMP
304static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
305{
306 struct _cpuid4_info *this_leaf;
307 unsigned long num_threads_sharing;
308
309 this_leaf = CPUID4_INFO_IDX(cpu, index);
310 num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
311
312 if (num_threads_sharing == 1)
313 cpu_set(cpu, this_leaf->shared_cpu_map);
314#ifdef CONFIG_X86_HT
315 else if (num_threads_sharing == smp_num_siblings)
316 this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
317#endif
318 else
319 printk(KERN_INFO "Number of CPUs sharing cache didn't match "
320 "any known set of CPUs\n");
321}
322#else
323static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
324#endif
325
326static void free_cache_attributes(unsigned int cpu)
327{
328 kfree(cpuid4_info[cpu]);
329 cpuid4_info[cpu] = NULL;
330}
331
332static int __devinit detect_cache_attributes(unsigned int cpu)
333{
334 struct _cpuid4_info *this_leaf;
335 unsigned long j;
336 int retval;
337
338 if (num_cache_leaves == 0)
339 return -ENOENT;
340
341 cpuid4_info[cpu] = kmalloc(
342 sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
343 if (unlikely(cpuid4_info[cpu] == NULL))
344 return -ENOMEM;
345 memset(cpuid4_info[cpu], 0,
346 sizeof(struct _cpuid4_info) * num_cache_leaves);
347
348 /* Do cpuid and store the results */
349 for (j = 0; j < num_cache_leaves; j++) {
350 this_leaf = CPUID4_INFO_IDX(cpu, j);
351 retval = cpuid4_cache_lookup(j, this_leaf);
352 if (unlikely(retval < 0))
353 goto err_out;
354 cache_shared_cpu_map_setup(cpu, j);
355 }
356 return 0;
357
358err_out:
359 free_cache_attributes(cpu);
360 return -ENOMEM;
361}
362
363#ifdef CONFIG_SYSFS
364
365#include <linux/kobject.h>
366#include <linux/sysfs.h>
367
368extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
369
370/* pointer to kobject for cpuX/cache */
371static struct kobject * cache_kobject[NR_CPUS];
372
373struct _index_kobject {
374 struct kobject kobj;
375 unsigned int cpu;
376 unsigned short index;
377};
378
379/* pointer to array of kobjects for cpuX/cache/indexY */
380static struct _index_kobject *index_kobject[NR_CPUS];
381#define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y]))
382
383#define show_one_plus(file_name, object, val) \
384static ssize_t show_##file_name \
385 (struct _cpuid4_info *this_leaf, char *buf) \
386{ \
387 return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \
388}
389
390show_one_plus(level, eax.split.level, 0);
391show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
392show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
393show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
394show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
395
396static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
397{
398 return sprintf (buf, "%luK\n", this_leaf->size / 1024);
399}
400
401static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
402{
403 char mask_str[NR_CPUS];
404 cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
405 return sprintf(buf, "%s\n", mask_str);
406}
407
408static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
409 switch(this_leaf->eax.split.type) {
410 case CACHE_TYPE_DATA:
411 return sprintf(buf, "Data\n");
412 break;
413 case CACHE_TYPE_INST:
414 return sprintf(buf, "Instruction\n");
415 break;
416 case CACHE_TYPE_UNIFIED:
417 return sprintf(buf, "Unified\n");
418 break;
419 default:
420 return sprintf(buf, "Unknown\n");
421 break;
422 }
423}
424
425struct _cache_attr {
426 struct attribute attr;
427 ssize_t (*show)(struct _cpuid4_info *, char *);
428 ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
429};
430
431#define define_one_ro(_name) \
432static struct _cache_attr _name = \
433 __ATTR(_name, 0444, show_##_name, NULL)
434
435define_one_ro(level);
436define_one_ro(type);
437define_one_ro(coherency_line_size);
438define_one_ro(physical_line_partition);
439define_one_ro(ways_of_associativity);
440define_one_ro(number_of_sets);
441define_one_ro(size);
442define_one_ro(shared_cpu_map);
443
444static struct attribute * default_attrs[] = {
445 &type.attr,
446 &level.attr,
447 &coherency_line_size.attr,
448 &physical_line_partition.attr,
449 &ways_of_associativity.attr,
450 &number_of_sets.attr,
451 &size.attr,
452 &shared_cpu_map.attr,
453 NULL
454};
455
456#define to_object(k) container_of(k, struct _index_kobject, kobj)
457#define to_attr(a) container_of(a, struct _cache_attr, attr)
458
459static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
460{
461 struct _cache_attr *fattr = to_attr(attr);
462 struct _index_kobject *this_leaf = to_object(kobj);
463 ssize_t ret;
464
465 ret = fattr->show ?
466 fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
467 buf) :
468 0;
469 return ret;
470}
471
472static ssize_t store(struct kobject * kobj, struct attribute * attr,
473 const char * buf, size_t count)
474{
475 return 0;
476}
477
478static struct sysfs_ops sysfs_ops = {
479 .show = show,
480 .store = store,
481};
482
483static struct kobj_type ktype_cache = {
484 .sysfs_ops = &sysfs_ops,
485 .default_attrs = default_attrs,
486};
487
488static struct kobj_type ktype_percpu_entry = {
489 .sysfs_ops = &sysfs_ops,
490};
491
492static void cpuid4_cache_sysfs_exit(unsigned int cpu)
493{
494 kfree(cache_kobject[cpu]);
495 kfree(index_kobject[cpu]);
496 cache_kobject[cpu] = NULL;
497 index_kobject[cpu] = NULL;
498 free_cache_attributes(cpu);
499}
500
501static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu)
502{
503
504 if (num_cache_leaves == 0)
505 return -ENOENT;
506
507 detect_cache_attributes(cpu);
508 if (cpuid4_info[cpu] == NULL)
509 return -ENOENT;
510
511 /* Allocate all required memory */
512 cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL);
513 if (unlikely(cache_kobject[cpu] == NULL))
514 goto err_out;
515 memset(cache_kobject[cpu], 0, sizeof(struct kobject));
516
517 index_kobject[cpu] = kmalloc(
518 sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
519 if (unlikely(index_kobject[cpu] == NULL))
520 goto err_out;
521 memset(index_kobject[cpu], 0,
522 sizeof(struct _index_kobject) * num_cache_leaves);
523
524 return 0;
525
526err_out:
527 cpuid4_cache_sysfs_exit(cpu);
528 return -ENOMEM;
529}
530
531/* Add/Remove cache interface for CPU device */
532static int __devinit cache_add_dev(struct sys_device * sys_dev)
533{
534 unsigned int cpu = sys_dev->id;
535 unsigned long i, j;
536 struct _index_kobject *this_object;
537 int retval = 0;
538
539 retval = cpuid4_cache_sysfs_init(cpu);
540 if (unlikely(retval < 0))
541 return retval;
542
543 cache_kobject[cpu]->parent = &sys_dev->kobj;
544 kobject_set_name(cache_kobject[cpu], "%s", "cache");
545 cache_kobject[cpu]->ktype = &ktype_percpu_entry;
546 retval = kobject_register(cache_kobject[cpu]);
547
548 for (i = 0; i < num_cache_leaves; i++) {
549 this_object = INDEX_KOBJECT_PTR(cpu,i);
550 this_object->cpu = cpu;
551 this_object->index = i;
552 this_object->kobj.parent = cache_kobject[cpu];
553 kobject_set_name(&(this_object->kobj), "index%1lu", i);
554 this_object->kobj.ktype = &ktype_cache;
555 retval = kobject_register(&(this_object->kobj));
556 if (unlikely(retval)) {
557 for (j = 0; j < i; j++) {
558 kobject_unregister(
559 &(INDEX_KOBJECT_PTR(cpu,j)->kobj));
560 }
561 kobject_unregister(cache_kobject[cpu]);
562 cpuid4_cache_sysfs_exit(cpu);
563 break;
564 }
565 }
566 return retval;
567}
568
569static int __devexit cache_remove_dev(struct sys_device * sys_dev)
570{
571 unsigned int cpu = sys_dev->id;
572 unsigned long i;
573
574 for (i = 0; i < num_cache_leaves; i++)
575 kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
576 kobject_unregister(cache_kobject[cpu]);
577 cpuid4_cache_sysfs_exit(cpu);
578 return 0;
579}
580
581static struct sysdev_driver cache_sysdev_driver = {
582 .add = cache_add_dev,
583 .remove = __devexit_p(cache_remove_dev),
584};
585
586/* Register/Unregister the cpu_cache driver */
587static int __devinit cache_register_driver(void)
588{
589 if (num_cache_leaves == 0)
590 return 0;
591
592 return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver);
593}
594
595device_initcall(cache_register_driver);
596
597#endif
598
diff --git a/arch/i386/kernel/cpu/mcheck/Makefile b/arch/i386/kernel/cpu/mcheck/Makefile
new file mode 100644
index 000000000000..30808f3d6715
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/Makefile
@@ -0,0 +1,2 @@
1obj-y = mce.o k7.o p4.o p5.o p6.o winchip.o
2obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
new file mode 100644
index 000000000000..8df52e86c4d2
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -0,0 +1,97 @@
1/*
2 * Athlon/Hammer specific Machine Check Exception Reporting
3 * (C) Copyright 2002 Dave Jones <davej@codemonkey.org.uk>
4 */
5
6#include <linux/init.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/config.h>
10#include <linux/irq.h>
11#include <linux/interrupt.h>
12#include <linux/smp.h>
13
14#include <asm/processor.h>
15#include <asm/system.h>
16#include <asm/msr.h>
17
18#include "mce.h"
19
20/* Machine Check Handler For AMD Athlon/Duron */
21static fastcall void k7_machine_check(struct pt_regs * regs, long error_code)
22{
23 int recover=1;
24 u32 alow, ahigh, high, low;
25 u32 mcgstl, mcgsth;
26 int i;
27
28 rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
29 if (mcgstl & (1<<0)) /* Recoverable ? */
30 recover=0;
31
32 printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
33 smp_processor_id(), mcgsth, mcgstl);
34
35 for (i=1; i<nr_mce_banks; i++) {
36 rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
37 if (high&(1<<31)) {
38 if (high & (1<<29))
39 recover |= 1;
40 if (high & (1<<25))
41 recover |= 2;
42 printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low);
43 high &= ~(1<<31);
44 if (high & (1<<27)) {
45 rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh);
46 printk ("[%08x%08x]", ahigh, alow);
47 }
48 if (high & (1<<26)) {
49 rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
50 printk (" at %08x%08x", ahigh, alow);
51 }
52 printk ("\n");
53 /* Clear it */
54 wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
55 /* Serialize */
56 wmb();
57 add_taint(TAINT_MACHINE_CHECK);
58 }
59 }
60
61 if (recover&2)
62 panic ("CPU context corrupt");
63 if (recover&1)
64 panic ("Unable to continue");
65 printk (KERN_EMERG "Attempting to continue.\n");
66 mcgstl &= ~(1<<2);
67 wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
68}
69
70
71/* AMD K7 machine check is Intel like */
72void __init amd_mcheck_init(struct cpuinfo_x86 *c)
73{
74 u32 l, h;
75 int i;
76
77 machine_check_vector = k7_machine_check;
78 wmb();
79
80 printk (KERN_INFO "Intel machine check architecture supported.\n");
81 rdmsr (MSR_IA32_MCG_CAP, l, h);
82 if (l & (1<<8)) /* Control register present ? */
83 wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
84 nr_mce_banks = l & 0xff;
85
86 /* Clear status for MC index 0 separately, we don't touch CTL,
87 * as some Athlons cause spurious MCEs when its enabled. */
88 wrmsr (MSR_IA32_MC0_STATUS, 0x0, 0x0);
89 for (i=1; i<nr_mce_banks; i++) {
90 wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
91 wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
92 }
93
94 set_in_cr4 (X86_CR4_MCE);
95 printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
96 smp_processor_id());
97}
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
new file mode 100644
index 000000000000..bf6d1aefafc0
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -0,0 +1,77 @@
1/*
2 * mce.c - x86 Machine Check Exception Reporting
3 * (c) 2002 Alan Cox <alan@redhat.com>, Dave Jones <davej@codemonkey.org.uk>
4 */
5
6#include <linux/init.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/config.h>
10#include <linux/module.h>
11#include <linux/smp.h>
12#include <linux/thread_info.h>
13
14#include <asm/processor.h>
15#include <asm/system.h>
16
17#include "mce.h"
18
19int mce_disabled __initdata = 0;
20int nr_mce_banks;
21
22EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
23
24/* Handle unconfigured int18 (should never happen) */
25static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_code)
26{
27 printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
28}
29
30/* Call the installed machine check handler for this CPU setup. */
31void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
32
33/* This has to be run for each processor */
34void __init mcheck_init(struct cpuinfo_x86 *c)
35{
36 if (mce_disabled==1)
37 return;
38
39 switch (c->x86_vendor) {
40 case X86_VENDOR_AMD:
41 if (c->x86==6 || c->x86==15)
42 amd_mcheck_init(c);
43 break;
44
45 case X86_VENDOR_INTEL:
46 if (c->x86==5)
47 intel_p5_mcheck_init(c);
48 if (c->x86==6)
49 intel_p6_mcheck_init(c);
50 if (c->x86==15)
51 intel_p4_mcheck_init(c);
52 break;
53
54 case X86_VENDOR_CENTAUR:
55 if (c->x86==5)
56 winchip_mcheck_init(c);
57 break;
58
59 default:
60 break;
61 }
62}
63
64static int __init mcheck_disable(char *str)
65{
66 mce_disabled = 1;
67 return 0;
68}
69
70static int __init mcheck_enable(char *str)
71{
72 mce_disabled = -1;
73 return 0;
74}
75
76__setup("nomce", mcheck_disable);
77__setup("mce", mcheck_enable);
diff --git a/arch/i386/kernel/cpu/mcheck/mce.h b/arch/i386/kernel/cpu/mcheck/mce.h
new file mode 100644
index 000000000000..dc2416dfef15
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/mce.h
@@ -0,0 +1,14 @@
1#include <linux/init.h>
2
3void amd_mcheck_init(struct cpuinfo_x86 *c);
4void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
5void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
6void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
7void winchip_mcheck_init(struct cpuinfo_x86 *c);
8
9/* Call the installed machine check handler for this CPU setup. */
10extern fastcall void (*machine_check_vector)(struct pt_regs *, long error_code);
11
12extern int mce_disabled __initdata;
13extern int nr_mce_banks;
14
diff --git a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c
new file mode 100644
index 000000000000..7864ddfccf07
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c
@@ -0,0 +1,93 @@
1/*
2 * Non Fatal Machine Check Exception Reporting
3 *
4 * (C) Copyright 2002 Dave Jones. <davej@codemonkey.org.uk>
5 *
6 * This file contains routines to check for non-fatal MCEs every 15s
7 *
8 */
9
10#include <linux/init.h>
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/jiffies.h>
14#include <linux/config.h>
15#include <linux/irq.h>
16#include <linux/workqueue.h>
17#include <linux/interrupt.h>
18#include <linux/smp.h>
19#include <linux/module.h>
20
21#include <asm/processor.h>
22#include <asm/system.h>
23#include <asm/msr.h>
24
25#include "mce.h"
26
27static int firstbank;
28
29#define MCE_RATE 15*HZ /* timer rate is 15s */
30
31static void mce_checkregs (void *info)
32{
33 u32 low, high;
34 int i;
35
36 for (i=firstbank; i<nr_mce_banks; i++) {
37 rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
38
39 if (high & (1<<31)) {
40 printk(KERN_INFO "MCE: The hardware reports a non "
41 "fatal, correctable incident occurred on "
42 "CPU %d.\n",
43 smp_processor_id());
44 printk (KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
45
46 /* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
47 wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
48
49 /* Serialize */
50 wmb();
51 add_taint(TAINT_MACHINE_CHECK);
52 }
53 }
54}
55
56static void mce_work_fn(void *data);
57static DECLARE_WORK(mce_work, mce_work_fn, NULL);
58
59static void mce_work_fn(void *data)
60{
61 on_each_cpu(mce_checkregs, NULL, 1, 1);
62 schedule_delayed_work(&mce_work, MCE_RATE);
63}
64
65static int __init init_nonfatal_mce_checker(void)
66{
67 struct cpuinfo_x86 *c = &boot_cpu_data;
68
69 /* Check for MCE support */
70 if (!cpu_has(c, X86_FEATURE_MCE))
71 return -ENODEV;
72
73 /* Check for PPro style MCA */
74 if (!cpu_has(c, X86_FEATURE_MCA))
75 return -ENODEV;
76
77 /* Some Athlons misbehave when we frob bank 0 */
78 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
79 boot_cpu_data.x86 == 6)
80 firstbank = 1;
81 else
82 firstbank = 0;
83
84 /*
85 * Check for non-fatal errors every MCE_RATE s
86 */
87 schedule_delayed_work(&mce_work, MCE_RATE);
88 printk(KERN_INFO "Machine check exception polling timer started.\n");
89 return 0;
90}
91module_init(init_nonfatal_mce_checker);
92
93MODULE_LICENSE("GPL");
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c
new file mode 100644
index 000000000000..8b16ceb929b4
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/p4.c
@@ -0,0 +1,271 @@
1/*
2 * P4 specific Machine Check Exception Reporting
3 */
4
5#include <linux/init.h>
6#include <linux/types.h>
7#include <linux/kernel.h>
8#include <linux/config.h>
9#include <linux/irq.h>
10#include <linux/interrupt.h>
11#include <linux/smp.h>
12
13#include <asm/processor.h>
14#include <asm/system.h>
15#include <asm/msr.h>
16#include <asm/apic.h>
17
18#include "mce.h"
19
20/* as supported by the P4/Xeon family */
21struct intel_mce_extended_msrs {
22 u32 eax;
23 u32 ebx;
24 u32 ecx;
25 u32 edx;
26 u32 esi;
27 u32 edi;
28 u32 ebp;
29 u32 esp;
30 u32 eflags;
31 u32 eip;
32 /* u32 *reserved[]; */
33};
34
35static int mce_num_extended_msrs = 0;
36
37
38#ifdef CONFIG_X86_MCE_P4THERMAL
39static void unexpected_thermal_interrupt(struct pt_regs *regs)
40{
41 printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
42 smp_processor_id());
43 add_taint(TAINT_MACHINE_CHECK);
44}
45
46/* P4/Xeon Thermal transition interrupt handler */
47static void intel_thermal_interrupt(struct pt_regs *regs)
48{
49 u32 l, h;
50 unsigned int cpu = smp_processor_id();
51 static unsigned long next[NR_CPUS];
52
53 ack_APIC_irq();
54
55 if (time_after(next[cpu], jiffies))
56 return;
57
58 next[cpu] = jiffies + HZ*5;
59 rdmsr(MSR_IA32_THERM_STATUS, l, h);
60 if (l & 0x1) {
61 printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu);
62 printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n",
63 cpu);
64 add_taint(TAINT_MACHINE_CHECK);
65 } else {
66 printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
67 }
68}
69
70/* Thermal interrupt handler for this CPU setup */
71static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
72
73fastcall void smp_thermal_interrupt(struct pt_regs *regs)
74{
75 irq_enter();
76 vendor_thermal_interrupt(regs);
77 irq_exit();
78}
79
80/* P4/Xeon Thermal regulation detect and init */
81static void __init intel_init_thermal(struct cpuinfo_x86 *c)
82{
83 u32 l, h;
84 unsigned int cpu = smp_processor_id();
85
86 /* Thermal monitoring */
87 if (!cpu_has(c, X86_FEATURE_ACPI))
88 return; /* -ENODEV */
89
90 /* Clock modulation */
91 if (!cpu_has(c, X86_FEATURE_ACC))
92 return; /* -ENODEV */
93
94 /* first check if its enabled already, in which case there might
95 * be some SMM goo which handles it, so we can't even put a handler
96 * since it might be delivered via SMI already -zwanem.
97 */
98 rdmsr (MSR_IA32_MISC_ENABLE, l, h);
99 h = apic_read(APIC_LVTTHMR);
100 if ((l & (1<<3)) && (h & APIC_DM_SMI)) {
101 printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n",
102 cpu);
103 return; /* -EBUSY */
104 }
105
106 /* check whether a vector already exists, temporarily masked? */
107 if (h & APIC_VECTOR_MASK) {
108 printk(KERN_DEBUG "CPU%d: Thermal LVT vector (%#x) already "
109 "installed\n",
110 cpu, (h & APIC_VECTOR_MASK));
111 return; /* -EBUSY */
112 }
113
114 /* The temperature transition interrupt handler setup */
115 h = THERMAL_APIC_VECTOR; /* our delivery vector */
116 h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */
117 apic_write_around(APIC_LVTTHMR, h);
118
119 rdmsr (MSR_IA32_THERM_INTERRUPT, l, h);
120 wrmsr (MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
121
122 /* ok we're good to go... */
123 vendor_thermal_interrupt = intel_thermal_interrupt;
124
125 rdmsr (MSR_IA32_MISC_ENABLE, l, h);
126 wrmsr (MSR_IA32_MISC_ENABLE, l | (1<<3), h);
127
128 l = apic_read (APIC_LVTTHMR);
129 apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
130 printk (KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu);
131 return;
132}
133#endif /* CONFIG_X86_MCE_P4THERMAL */
134
135
136/* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */
137static inline int intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
138{
139 u32 h;
140
141 if (mce_num_extended_msrs == 0)
142 goto done;
143
144 rdmsr (MSR_IA32_MCG_EAX, r->eax, h);
145 rdmsr (MSR_IA32_MCG_EBX, r->ebx, h);
146 rdmsr (MSR_IA32_MCG_ECX, r->ecx, h);
147 rdmsr (MSR_IA32_MCG_EDX, r->edx, h);
148 rdmsr (MSR_IA32_MCG_ESI, r->esi, h);
149 rdmsr (MSR_IA32_MCG_EDI, r->edi, h);
150 rdmsr (MSR_IA32_MCG_EBP, r->ebp, h);
151 rdmsr (MSR_IA32_MCG_ESP, r->esp, h);
152 rdmsr (MSR_IA32_MCG_EFLAGS, r->eflags, h);
153 rdmsr (MSR_IA32_MCG_EIP, r->eip, h);
154
155 /* can we rely on kmalloc to do a dynamic
156 * allocation for the reserved registers?
157 */
158done:
159 return mce_num_extended_msrs;
160}
161
162static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
163{
164 int recover=1;
165 u32 alow, ahigh, high, low;
166 u32 mcgstl, mcgsth;
167 int i;
168 struct intel_mce_extended_msrs dbg;
169
170 rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
171 if (mcgstl & (1<<0)) /* Recoverable ? */
172 recover=0;
173
174 printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
175 smp_processor_id(), mcgsth, mcgstl);
176
177 if (intel_get_extended_msrs(&dbg)) {
178 printk (KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n",
179 smp_processor_id(), dbg.eip, dbg.eflags);
180 printk (KERN_DEBUG "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n",
181 dbg.eax, dbg.ebx, dbg.ecx, dbg.edx);
182 printk (KERN_DEBUG "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n",
183 dbg.esi, dbg.edi, dbg.ebp, dbg.esp);
184 }
185
186 for (i=0; i<nr_mce_banks; i++) {
187 rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
188 if (high & (1<<31)) {
189 if (high & (1<<29))
190 recover |= 1;
191 if (high & (1<<25))
192 recover |= 2;
193 printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low);
194 high &= ~(1<<31);
195 if (high & (1<<27)) {
196 rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh);
197 printk ("[%08x%08x]", ahigh, alow);
198 }
199 if (high & (1<<26)) {
200 rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
201 printk (" at %08x%08x", ahigh, alow);
202 }
203 printk ("\n");
204 }
205 }
206
207 if (recover & 2)
208 panic ("CPU context corrupt");
209 if (recover & 1)
210 panic ("Unable to continue");
211
212 printk(KERN_EMERG "Attempting to continue.\n");
213 /*
214 * Do not clear the MSR_IA32_MCi_STATUS if the error is not
215 * recoverable/continuable.This will allow BIOS to look at the MSRs
216 * for errors if the OS could not log the error.
217 */
218 for (i=0; i<nr_mce_banks; i++) {
219 u32 msr;
220 msr = MSR_IA32_MC0_STATUS+i*4;
221 rdmsr (msr, low, high);
222 if (high&(1<<31)) {
223 /* Clear it */
224 wrmsr(msr, 0UL, 0UL);
225 /* Serialize */
226 wmb();
227 add_taint(TAINT_MACHINE_CHECK);
228 }
229 }
230 mcgstl &= ~(1<<2);
231 wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
232}
233
234
235void __init intel_p4_mcheck_init(struct cpuinfo_x86 *c)
236{
237 u32 l, h;
238 int i;
239
240 machine_check_vector = intel_machine_check;
241 wmb();
242
243 printk (KERN_INFO "Intel machine check architecture supported.\n");
244 rdmsr (MSR_IA32_MCG_CAP, l, h);
245 if (l & (1<<8)) /* Control register present ? */
246 wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
247 nr_mce_banks = l & 0xff;
248
249 for (i=0; i<nr_mce_banks; i++) {
250 wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
251 wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
252 }
253
254 set_in_cr4 (X86_CR4_MCE);
255 printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
256 smp_processor_id());
257
258 /* Check for P4/Xeon extended MCE MSRs */
259 rdmsr (MSR_IA32_MCG_CAP, l, h);
260 if (l & (1<<9)) {/* MCG_EXT_P */
261 mce_num_extended_msrs = (l >> 16) & 0xff;
262 printk (KERN_INFO "CPU%d: Intel P4/Xeon Extended MCE MSRs (%d)"
263 " available\n",
264 smp_processor_id(), mce_num_extended_msrs);
265
266#ifdef CONFIG_X86_MCE_P4THERMAL
267 /* Check for P4/Xeon Thermal monitor */
268 intel_init_thermal(c);
269#endif
270 }
271}
diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c
new file mode 100644
index 000000000000..c45a1b485c80
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/p5.c
@@ -0,0 +1,54 @@
1/*
2 * P5 specific Machine Check Exception Reporting
3 * (C) Copyright 2002 Alan Cox <alan@redhat.com>
4 */
5
6#include <linux/init.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/irq.h>
10#include <linux/interrupt.h>
11#include <linux/smp.h>
12
13#include <asm/processor.h>
14#include <asm/system.h>
15#include <asm/msr.h>
16
17#include "mce.h"
18
19/* Machine check handler for Pentium class Intel */
20static fastcall void pentium_machine_check(struct pt_regs * regs, long error_code)
21{
22 u32 loaddr, hi, lotype;
23 rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
24 rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
25 printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
26 if(lotype&(1<<5))
27 printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
28 add_taint(TAINT_MACHINE_CHECK);
29}
30
31/* Set up machine check reporting for processors with Intel style MCE */
32void __init intel_p5_mcheck_init(struct cpuinfo_x86 *c)
33{
34 u32 l, h;
35
36 /*Check for MCE support */
37 if( !cpu_has(c, X86_FEATURE_MCE) )
38 return;
39
40 /* Default P5 to off as its often misconnected */
41 if(mce_disabled != -1)
42 return;
43 machine_check_vector = pentium_machine_check;
44 wmb();
45
46 /* Read registers before enabling */
47 rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
48 rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
49 printk(KERN_INFO "Intel old style machine check architecture supported.\n");
50
51 /* Enable MCE */
52 set_in_cr4(X86_CR4_MCE);
53 printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
54}
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c
new file mode 100644
index 000000000000..46640f8c2494
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/p6.c
@@ -0,0 +1,115 @@
1/*
2 * P6 specific Machine Check Exception Reporting
3 * (C) Copyright 2002 Alan Cox <alan@redhat.com>
4 */
5
6#include <linux/init.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/irq.h>
10#include <linux/interrupt.h>
11#include <linux/smp.h>
12
13#include <asm/processor.h>
14#include <asm/system.h>
15#include <asm/msr.h>
16
17#include "mce.h"
18
19/* Machine Check Handler For PII/PIII */
20static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
21{
22 int recover=1;
23 u32 alow, ahigh, high, low;
24 u32 mcgstl, mcgsth;
25 int i;
26
27 rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
28 if (mcgstl & (1<<0)) /* Recoverable ? */
29 recover=0;
30
31 printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
32 smp_processor_id(), mcgsth, mcgstl);
33
34 for (i=0; i<nr_mce_banks; i++) {
35 rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
36 if (high & (1<<31)) {
37 if (high & (1<<29))
38 recover |= 1;
39 if (high & (1<<25))
40 recover |= 2;
41 printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low);
42 high &= ~(1<<31);
43 if (high & (1<<27)) {
44 rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh);
45 printk ("[%08x%08x]", ahigh, alow);
46 }
47 if (high & (1<<26)) {
48 rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
49 printk (" at %08x%08x", ahigh, alow);
50 }
51 printk ("\n");
52 }
53 }
54
55 if (recover & 2)
56 panic ("CPU context corrupt");
57 if (recover & 1)
58 panic ("Unable to continue");
59
60 printk (KERN_EMERG "Attempting to continue.\n");
61 /*
62 * Do not clear the MSR_IA32_MCi_STATUS if the error is not
63 * recoverable/continuable.This will allow BIOS to look at the MSRs
64 * for errors if the OS could not log the error.
65 */
66 for (i=0; i<nr_mce_banks; i++) {
67 unsigned int msr;
68 msr = MSR_IA32_MC0_STATUS+i*4;
69 rdmsr (msr,low, high);
70 if (high & (1<<31)) {
71 /* Clear it */
72 wrmsr (msr, 0UL, 0UL);
73 /* Serialize */
74 wmb();
75 add_taint(TAINT_MACHINE_CHECK);
76 }
77 }
78 mcgstl &= ~(1<<2);
79 wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
80}
81
82/* Set up machine check reporting for processors with Intel style MCE */
83void __init intel_p6_mcheck_init(struct cpuinfo_x86 *c)
84{
85 u32 l, h;
86 int i;
87
88 /* Check for MCE support */
89 if (!cpu_has(c, X86_FEATURE_MCE))
90 return;
91
92 /* Check for PPro style MCA */
93 if (!cpu_has(c, X86_FEATURE_MCA))
94 return;
95
96 /* Ok machine check is available */
97 machine_check_vector = intel_machine_check;
98 wmb();
99
100 printk (KERN_INFO "Intel machine check architecture supported.\n");
101 rdmsr (MSR_IA32_MCG_CAP, l, h);
102 if (l & (1<<8)) /* Control register present ? */
103 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
104 nr_mce_banks = l & 0xff;
105
106 /* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
107 for (i=1; i<nr_mce_banks; i++) {
108 wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
109 wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
110 }
111
112 set_in_cr4 (X86_CR4_MCE);
113 printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
114 smp_processor_id());
115}
diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c
new file mode 100644
index 000000000000..753fa7acb984
--- /dev/null
+++ b/arch/i386/kernel/cpu/mcheck/winchip.c
@@ -0,0 +1,37 @@
1/*
2 * IDT Winchip specific Machine Check Exception Reporting
3 * (C) Copyright 2002 Alan Cox <alan@redhat.com>
4 */
5
6#include <linux/init.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/irq.h>
10#include <linux/interrupt.h>
11
12#include <asm/processor.h>
13#include <asm/system.h>
14#include <asm/msr.h>
15
16#include "mce.h"
17
18/* Machine check handler for WinChip C6 */
19static fastcall void winchip_machine_check(struct pt_regs * regs, long error_code)
20{
21 printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
22 add_taint(TAINT_MACHINE_CHECK);
23}
24
25/* Set up machine check reporting on the Winchip C6 series */
26void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
27{
28 u32 lo, hi;
29 machine_check_vector = winchip_machine_check;
30 wmb();
31 rdmsr(MSR_IDT_FCR1, lo, hi);
32 lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
33 lo&= ~(1<<4); /* Enable MCE */
34 wrmsr(MSR_IDT_FCR1, lo, hi);
35 set_in_cr4(X86_CR4_MCE);
36 printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n");
37}
diff --git a/arch/i386/kernel/cpu/mtrr/Makefile b/arch/i386/kernel/cpu/mtrr/Makefile
new file mode 100644
index 000000000000..a25b701ab84e
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/Makefile
@@ -0,0 +1,5 @@
1obj-y := main.o if.o generic.o state.o
2obj-y += amd.o
3obj-y += cyrix.o
4obj-y += centaur.o
5
diff --git a/arch/i386/kernel/cpu/mtrr/amd.c b/arch/i386/kernel/cpu/mtrr/amd.c
new file mode 100644
index 000000000000..1a1e04b6fd00
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/amd.c
@@ -0,0 +1,121 @@
1#include <linux/init.h>
2#include <linux/mm.h>
3#include <asm/mtrr.h>
4#include <asm/msr.h>
5
6#include "mtrr.h"
7
8static void
9amd_get_mtrr(unsigned int reg, unsigned long *base,
10 unsigned int *size, mtrr_type * type)
11{
12 unsigned long low, high;
13
14 rdmsr(MSR_K6_UWCCR, low, high);
15 /* Upper dword is region 1, lower is region 0 */
16 if (reg == 1)
17 low = high;
18 /* The base masks off on the right alignment */
19 *base = (low & 0xFFFE0000) >> PAGE_SHIFT;
20 *type = 0;
21 if (low & 1)
22 *type = MTRR_TYPE_UNCACHABLE;
23 if (low & 2)
24 *type = MTRR_TYPE_WRCOMB;
25 if (!(low & 3)) {
26 *size = 0;
27 return;
28 }
29 /*
30 * This needs a little explaining. The size is stored as an
31 * inverted mask of bits of 128K granularity 15 bits long offset
32 * 2 bits
33 *
34 * So to get a size we do invert the mask and add 1 to the lowest
35 * mask bit (4 as its 2 bits in). This gives us a size we then shift
36 * to turn into 128K blocks
37 *
38 * eg 111 1111 1111 1100 is 512K
39 *
40 * invert 000 0000 0000 0011
41 * +1 000 0000 0000 0100
42 * *128K ...
43 */
44 low = (~low) & 0x1FFFC;
45 *size = (low + 4) << (15 - PAGE_SHIFT);
46 return;
47}
48
49static void amd_set_mtrr(unsigned int reg, unsigned long base,
50 unsigned long size, mtrr_type type)
51/* [SUMMARY] Set variable MTRR register on the local CPU.
52 <reg> The register to set.
53 <base> The base address of the region.
54 <size> The size of the region. If this is 0 the region is disabled.
55 <type> The type of the region.
56 <do_safe> If TRUE, do the change safely. If FALSE, safety measures should
57 be done externally.
58 [RETURNS] Nothing.
59*/
60{
61 u32 regs[2];
62
63 /*
64 * Low is MTRR0 , High MTRR 1
65 */
66 rdmsr(MSR_K6_UWCCR, regs[0], regs[1]);
67 /*
68 * Blank to disable
69 */
70 if (size == 0)
71 regs[reg] = 0;
72 else
73 /* Set the register to the base, the type (off by one) and an
74 inverted bitmask of the size The size is the only odd
75 bit. We are fed say 512K We invert this and we get 111 1111
76 1111 1011 but if you subtract one and invert you get the
77 desired 111 1111 1111 1100 mask
78
79 But ~(x - 1) == ~x + 1 == -x. Two's complement rocks! */
80 regs[reg] = (-size >> (15 - PAGE_SHIFT) & 0x0001FFFC)
81 | (base << PAGE_SHIFT) | (type + 1);
82
83 /*
84 * The writeback rule is quite specific. See the manual. Its
85 * disable local interrupts, write back the cache, set the mtrr
86 */
87 wbinvd();
88 wrmsr(MSR_K6_UWCCR, regs[0], regs[1]);
89}
90
91static int amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
92{
93 /* Apply the K6 block alignment and size rules
94 In order
95 o Uncached or gathering only
96 o 128K or bigger block
97 o Power of 2 block
98 o base suitably aligned to the power
99 */
100 if (type > MTRR_TYPE_WRCOMB || size < (1 << (17 - PAGE_SHIFT))
101 || (size & ~(size - 1)) - size || (base & (size - 1)))
102 return -EINVAL;
103 return 0;
104}
105
106static struct mtrr_ops amd_mtrr_ops = {
107 .vendor = X86_VENDOR_AMD,
108 .set = amd_set_mtrr,
109 .get = amd_get_mtrr,
110 .get_free_region = generic_get_free_region,
111 .validate_add_page = amd_validate_add_page,
112 .have_wrcomb = positive_have_wrcomb,
113};
114
115int __init amd_init_mtrr(void)
116{
117 set_mtrr_ops(&amd_mtrr_ops);
118 return 0;
119}
120
121//arch_initcall(amd_mtrr_init);
diff --git a/arch/i386/kernel/cpu/mtrr/centaur.c b/arch/i386/kernel/cpu/mtrr/centaur.c
new file mode 100644
index 000000000000..33f00ac314ef
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/centaur.c
@@ -0,0 +1,223 @@
1#include <linux/init.h>
2#include <linux/mm.h>
3#include <asm/mtrr.h>
4#include <asm/msr.h>
5#include "mtrr.h"
6
7static struct {
8 unsigned long high;
9 unsigned long low;
10} centaur_mcr[8];
11
12static u8 centaur_mcr_reserved;
13static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */
14
15/*
16 * Report boot time MCR setups
17 */
18
19static int
20centaur_get_free_region(unsigned long base, unsigned long size)
21/* [SUMMARY] Get a free MTRR.
22 <base> The starting (base) address of the region.
23 <size> The size (in bytes) of the region.
24 [RETURNS] The index of the region on success, else -1 on error.
25*/
26{
27 int i, max;
28 mtrr_type ltype;
29 unsigned long lbase;
30 unsigned int lsize;
31
32 max = num_var_ranges;
33 for (i = 0; i < max; ++i) {
34 if (centaur_mcr_reserved & (1 << i))
35 continue;
36 mtrr_if->get(i, &lbase, &lsize, &ltype);
37 if (lsize == 0)
38 return i;
39 }
40 return -ENOSPC;
41}
42
43void
44mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
45{
46 centaur_mcr[mcr].low = lo;
47 centaur_mcr[mcr].high = hi;
48}
49
50static void
51centaur_get_mcr(unsigned int reg, unsigned long *base,
52 unsigned int *size, mtrr_type * type)
53{
54 *base = centaur_mcr[reg].high >> PAGE_SHIFT;
55 *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
56 *type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */
57 if (centaur_mcr_type == 1 && ((centaur_mcr[reg].low & 31) & 2))
58 *type = MTRR_TYPE_UNCACHABLE;
59 if (centaur_mcr_type == 1 && (centaur_mcr[reg].low & 31) == 25)
60 *type = MTRR_TYPE_WRBACK;
61 if (centaur_mcr_type == 0 && (centaur_mcr[reg].low & 31) == 31)
62 *type = MTRR_TYPE_WRBACK;
63
64}
65
66static void centaur_set_mcr(unsigned int reg, unsigned long base,
67 unsigned long size, mtrr_type type)
68{
69 unsigned long low, high;
70
71 if (size == 0) {
72 /* Disable */
73 high = low = 0;
74 } else {
75 high = base << PAGE_SHIFT;
76 if (centaur_mcr_type == 0)
77 low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
78 else {
79 if (type == MTRR_TYPE_UNCACHABLE)
80 low = -size << PAGE_SHIFT | 0x02; /* NC */
81 else
82 low = -size << PAGE_SHIFT | 0x09; /* WWO,WC */
83 }
84 }
85 centaur_mcr[reg].high = high;
86 centaur_mcr[reg].low = low;
87 wrmsr(MSR_IDT_MCR0 + reg, low, high);
88}
89
90#if 0
91/*
92 * Initialise the later (saner) Winchip MCR variant. In this version
93 * the BIOS can pass us the registers it has used (but not their values)
94 * and the control register is read/write
95 */
96
97static void __init
98centaur_mcr1_init(void)
99{
100 unsigned i;
101 u32 lo, hi;
102
103 /* Unfortunately, MCR's are read-only, so there is no way to
104 * find out what the bios might have done.
105 */
106
107 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
108 if (((lo >> 17) & 7) == 1) { /* Type 1 Winchip2 MCR */
109 lo &= ~0x1C0; /* clear key */
110 lo |= 0x040; /* set key to 1 */
111 wrmsr(MSR_IDT_MCR_CTRL, lo, hi); /* unlock MCR */
112 }
113
114 centaur_mcr_type = 1;
115
116 /*
117 * Clear any unconfigured MCR's.
118 */
119
120 for (i = 0; i < 8; ++i) {
121 if (centaur_mcr[i].high == 0 && centaur_mcr[i].low == 0) {
122 if (!(lo & (1 << (9 + i))))
123 wrmsr(MSR_IDT_MCR0 + i, 0, 0);
124 else
125 /*
126 * If the BIOS set up an MCR we cannot see it
127 * but we don't wish to obliterate it
128 */
129 centaur_mcr_reserved |= (1 << i);
130 }
131 }
132 /*
133 * Throw the main write-combining switch...
134 * However if OOSTORE is enabled then people have already done far
135 * cleverer things and we should behave.
136 */
137
138 lo |= 15; /* Write combine enables */
139 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
140}
141
142/*
143 * Initialise the original winchip with read only MCR registers
144 * no used bitmask for the BIOS to pass on and write only control
145 */
146
147static void __init
148centaur_mcr0_init(void)
149{
150 unsigned i;
151
152 /* Unfortunately, MCR's are read-only, so there is no way to
153 * find out what the bios might have done.
154 */
155
156 /* Clear any unconfigured MCR's.
157 * This way we are sure that the centaur_mcr array contains the actual
158 * values. The disadvantage is that any BIOS tweaks are thus undone.
159 *
160 */
161 for (i = 0; i < 8; ++i) {
162 if (centaur_mcr[i].high == 0 && centaur_mcr[i].low == 0)
163 wrmsr(MSR_IDT_MCR0 + i, 0, 0);
164 }
165
166 wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); /* Write only */
167}
168
169/*
170 * Initialise Winchip series MCR registers
171 */
172
173static void __init
174centaur_mcr_init(void)
175{
176 struct set_mtrr_context ctxt;
177
178 set_mtrr_prepare_save(&ctxt);
179 set_mtrr_cache_disable(&ctxt);
180
181 if (boot_cpu_data.x86_model == 4)
182 centaur_mcr0_init();
183 else if (boot_cpu_data.x86_model == 8 || boot_cpu_data.x86_model == 9)
184 centaur_mcr1_init();
185
186 set_mtrr_done(&ctxt);
187}
188#endif
189
190static int centaur_validate_add_page(unsigned long base,
191 unsigned long size, unsigned int type)
192{
193 /*
194 * FIXME: Winchip2 supports uncached
195 */
196 if (type != MTRR_TYPE_WRCOMB &&
197 (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE)) {
198 printk(KERN_WARNING
199 "mtrr: only write-combining%s supported\n",
200 centaur_mcr_type ? " and uncacheable are"
201 : " is");
202 return -EINVAL;
203 }
204 return 0;
205}
206
207static struct mtrr_ops centaur_mtrr_ops = {
208 .vendor = X86_VENDOR_CENTAUR,
209// .init = centaur_mcr_init,
210 .set = centaur_set_mcr,
211 .get = centaur_get_mcr,
212 .get_free_region = centaur_get_free_region,
213 .validate_add_page = centaur_validate_add_page,
214 .have_wrcomb = positive_have_wrcomb,
215};
216
217int __init centaur_init_mtrr(void)
218{
219 set_mtrr_ops(&centaur_mtrr_ops);
220 return 0;
221}
222
223//arch_initcall(centaur_init_mtrr);
diff --git a/arch/i386/kernel/cpu/mtrr/changelog b/arch/i386/kernel/cpu/mtrr/changelog
new file mode 100644
index 000000000000..af1368535955
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/changelog
@@ -0,0 +1,229 @@
1 ChangeLog
2
3 Prehistory Martin Tischhäuser <martin@ikcbarka.fzk.de>
4 Initial register-setting code (from proform-1.0).
5 19971216 Richard Gooch <rgooch@atnf.csiro.au>
6 Original version for /proc/mtrr interface, SMP-safe.
7 v1.0
8 19971217 Richard Gooch <rgooch@atnf.csiro.au>
9 Bug fix for ioctls()'s.
10 Added sample code in Documentation/mtrr.txt
11 v1.1
12 19971218 Richard Gooch <rgooch@atnf.csiro.au>
13 Disallow overlapping regions.
14 19971219 Jens Maurer <jmaurer@menuett.rhein-main.de>
15 Register-setting fixups.
16 v1.2
17 19971222 Richard Gooch <rgooch@atnf.csiro.au>
18 Fixups for kernel 2.1.75.
19 v1.3
20 19971229 David Wragg <dpw@doc.ic.ac.uk>
21 Register-setting fixups and conformity with Intel conventions.
22 19971229 Richard Gooch <rgooch@atnf.csiro.au>
23 Cosmetic changes and wrote this ChangeLog ;-)
24 19980106 Richard Gooch <rgooch@atnf.csiro.au>
25 Fixups for kernel 2.1.78.
26 v1.4
27 19980119 David Wragg <dpw@doc.ic.ac.uk>
28 Included passive-release enable code (elsewhere in PCI setup).
29 v1.5
30 19980131 Richard Gooch <rgooch@atnf.csiro.au>
31 Replaced global kernel lock with private spinlock.
32 v1.6
33 19980201 Richard Gooch <rgooch@atnf.csiro.au>
34 Added wait for other CPUs to complete changes.
35 v1.7
36 19980202 Richard Gooch <rgooch@atnf.csiro.au>
37 Bug fix in definition of <set_mtrr> for UP.
38 v1.8
39 19980319 Richard Gooch <rgooch@atnf.csiro.au>
40 Fixups for kernel 2.1.90.
41 19980323 Richard Gooch <rgooch@atnf.csiro.au>
42 Move SMP BIOS fixup before secondary CPUs call <calibrate_delay>
43 v1.9
44 19980325 Richard Gooch <rgooch@atnf.csiro.au>
45 Fixed test for overlapping regions: confused by adjacent regions
46 19980326 Richard Gooch <rgooch@atnf.csiro.au>
47 Added wbinvd in <set_mtrr_prepare>.
48 19980401 Richard Gooch <rgooch@atnf.csiro.au>
49 Bug fix for non-SMP compilation.
50 19980418 David Wragg <dpw@doc.ic.ac.uk>
51 Fixed-MTRR synchronisation for SMP and use atomic operations
52 instead of spinlocks.
53 19980418 Richard Gooch <rgooch@atnf.csiro.au>
54 Differentiate different MTRR register classes for BIOS fixup.
55 v1.10
56 19980419 David Wragg <dpw@doc.ic.ac.uk>
57 Bug fix in variable MTRR synchronisation.
58 v1.11
59 19980419 Richard Gooch <rgooch@atnf.csiro.au>
60 Fixups for kernel 2.1.97.
61 v1.12
62 19980421 Richard Gooch <rgooch@atnf.csiro.au>
63 Safer synchronisation across CPUs when changing MTRRs.
64 v1.13
65 19980423 Richard Gooch <rgooch@atnf.csiro.au>
66 Bugfix for SMP systems without MTRR support.
67 v1.14
68 19980427 Richard Gooch <rgooch@atnf.csiro.au>
69 Trap calls to <mtrr_add> and <mtrr_del> on non-MTRR machines.
70 v1.15
71 19980427 Richard Gooch <rgooch@atnf.csiro.au>
72 Use atomic bitops for setting SMP change mask.
73 v1.16
74 19980428 Richard Gooch <rgooch@atnf.csiro.au>
75 Removed spurious diagnostic message.
76 v1.17
77 19980429 Richard Gooch <rgooch@atnf.csiro.au>
78 Moved register-setting macros into this file.
79 Moved setup code from init/main.c to i386-specific areas.
80 v1.18
81 19980502 Richard Gooch <rgooch@atnf.csiro.au>
82 Moved MTRR detection outside conditionals in <mtrr_init>.
83 v1.19
84 19980502 Richard Gooch <rgooch@atnf.csiro.au>
85 Documentation improvement: mention Pentium II and AGP.
86 v1.20
87 19980521 Richard Gooch <rgooch@atnf.csiro.au>
88 Only manipulate interrupt enable flag on local CPU.
89 Allow enclosed uncachable regions.
90 v1.21
91 19980611 Richard Gooch <rgooch@atnf.csiro.au>
92 Always define <main_lock>.
93 v1.22
94 19980901 Richard Gooch <rgooch@atnf.csiro.au>
95 Removed module support in order to tidy up code.
96 Added sanity check for <mtrr_add>/<mtrr_del> before <mtrr_init>.
97 Created addition queue for prior to SMP commence.
98 v1.23
99 19980902 Richard Gooch <rgooch@atnf.csiro.au>
100 Ported patch to kernel 2.1.120-pre3.
101 v1.24
102 19980910 Richard Gooch <rgooch@atnf.csiro.au>
103 Removed sanity checks and addition queue: Linus prefers an OOPS.
104 v1.25
105 19981001 Richard Gooch <rgooch@atnf.csiro.au>
106 Fixed harmless compiler warning in include/asm-i386/mtrr.h
107 Fixed version numbering and history for v1.23 -> v1.24.
108 v1.26
109 19990118 Richard Gooch <rgooch@atnf.csiro.au>
110 Added devfs support.
111 v1.27
112 19990123 Richard Gooch <rgooch@atnf.csiro.au>
113 Changed locking to spin with reschedule.
114 Made use of new <smp_call_function>.
115 v1.28
116 19990201 Zoltán Böszörményi <zboszor@mail.externet.hu>
117 Extended the driver to be able to use Cyrix style ARRs.
118 19990204 Richard Gooch <rgooch@atnf.csiro.au>
119 Restructured Cyrix support.
120 v1.29
121 19990204 Zoltán Böszörményi <zboszor@mail.externet.hu>
122 Refined ARR support: enable MAPEN in set_mtrr_prepare()
123 and disable MAPEN in set_mtrr_done().
124 19990205 Richard Gooch <rgooch@atnf.csiro.au>
125 Minor cleanups.
126 v1.30
127 19990208 Zoltán Böszörményi <zboszor@mail.externet.hu>
128 Protect plain 6x86s (and other processors without the
129 Page Global Enable feature) against accessing CR4 in
130 set_mtrr_prepare() and set_mtrr_done().
131 19990210 Richard Gooch <rgooch@atnf.csiro.au>
132 Turned <set_mtrr_up> and <get_mtrr> into function pointers.
133 v1.31
134 19990212 Zoltán Böszörményi <zboszor@mail.externet.hu>
135 Major rewrite of cyrix_arr_init(): do not touch ARRs,
136 leave them as the BIOS have set them up.
137 Enable usage of all 8 ARRs.
138 Avoid multiplications by 3 everywhere and other
139 code clean ups/speed ups.
140 19990213 Zoltán Böszörményi <zboszor@mail.externet.hu>
141 Set up other Cyrix processors identical to the boot cpu.
142 Since Cyrix don't support Intel APIC, this is l'art pour l'art.
143 Weigh ARRs by size:
144 If size <= 32M is given, set up ARR# we were given.
145 If size > 32M is given, set up ARR7 only if it is free,
146 fail otherwise.
147 19990214 Zoltán Böszörményi <zboszor@mail.externet.hu>
148 Also check for size >= 256K if we are to set up ARR7,
149 mtrr_add() returns the value it gets from set_mtrr()
150 19990218 Zoltán Böszörményi <zboszor@mail.externet.hu>
151 Remove Cyrix "coma bug" workaround from here.
152 Moved to linux/arch/i386/kernel/setup.c and
153 linux/include/asm-i386/bugs.h
154 19990228 Richard Gooch <rgooch@atnf.csiro.au>
155 Added MTRRIOC_KILL_ENTRY ioctl(2)
156 Trap for counter underflow in <mtrr_file_del>.
157 Trap for 4 MiB aligned regions for PPro, stepping <= 7.
158 19990301 Richard Gooch <rgooch@atnf.csiro.au>
159 Created <get_free_region> hook.
160 19990305 Richard Gooch <rgooch@atnf.csiro.au>
161 Temporarily disable AMD support now MTRR capability flag is set.
162 v1.32
163 19990308 Zoltán Böszörményi <zboszor@mail.externet.hu>
164 Adjust my changes (19990212-19990218) to Richard Gooch's
165 latest changes. (19990228-19990305)
166 v1.33
167 19990309 Richard Gooch <rgooch@atnf.csiro.au>
168 Fixed typo in <printk> message.
169 19990310 Richard Gooch <rgooch@atnf.csiro.au>
170 Support K6-II/III based on Alan Cox's <alan@redhat.com> patches.
171 v1.34
172 19990511 Bart Hartgers <bart@etpmod.phys.tue.nl>
173 Support Centaur C6 MCR's.
174 19990512 Richard Gooch <rgooch@atnf.csiro.au>
175 Minor cleanups.
176 v1.35
177 19990707 Zoltán Böszörményi <zboszor@mail.externet.hu>
178 Check whether ARR3 is protected in cyrix_get_free_region()
179 and mtrr_del(). The code won't attempt to delete or change it
180 from now on if the BIOS protected ARR3. It silently skips ARR3
181 in cyrix_get_free_region() or returns with an error code from
182 mtrr_del().
183 19990711 Zoltán Böszörményi <zboszor@mail.externet.hu>
184 Reset some bits in the CCRs in cyrix_arr_init() to disable SMM
185 if ARR3 isn't protected. This is needed because if SMM is active
186 and ARR3 isn't protected then deleting and setting ARR3 again
187 may lock up the processor. With SMM entirely disabled, it does
188 not happen.
189 19990812 Zoltán Böszörményi <zboszor@mail.externet.hu>
190 Rearrange switch() statements so the driver accomodates to
191 the fact that the AMD Athlon handles its MTRRs the same way
192 as Intel does.
193 19990814 Zoltán Böszörményi <zboszor@mail.externet.hu>
194 Double check for Intel in mtrr_add()'s big switch() because
195 that revision check is only valid for Intel CPUs.
196 19990819 Alan Cox <alan@redhat.com>
197 Tested Zoltan's changes on a pre production Athlon - 100%
198 success.
199 19991008 Manfred Spraul <manfreds@colorfullife.com>
200 replaced spin_lock_reschedule() with a normal semaphore.
201 v1.36
202 20000221 Richard Gooch <rgooch@atnf.csiro.au>
203 Compile fix if procfs and devfs not enabled.
204 Formatting changes.
205 v1.37
206 20001109 H. Peter Anvin <hpa@zytor.com>
207 Use the new centralized CPU feature detects.
208
209 v1.38
210 20010309 Dave Jones <davej@suse.de>
211 Add support for Cyrix III.
212
213 v1.39
214 20010312 Dave Jones <davej@suse.de>
215 Ugh, I broke AMD support.
216 Reworked fix by Troels Walsted Hansen <troels@thule.no>
217
218 v1.40
219 20010327 Dave Jones <davej@suse.de>
220 Adapted Cyrix III support to include VIA C3.
221
222 v2.0
223 20020306 Patrick Mochel <mochel@osdl.org>
224 Split mtrr.c -> mtrr/*.c
225 Converted to Linux Kernel Coding Style
226 Fixed several minor nits in form
227 Moved some SMP-only functions out, so they can be used
228 for power management in the future.
229 TODO: Fix user interface cruft.
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
new file mode 100644
index 000000000000..933b0dd62f48
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c
@@ -0,0 +1,364 @@
1#include <linux/init.h>
2#include <linux/mm.h>
3#include <asm/mtrr.h>
4#include <asm/msr.h>
5#include <asm/io.h>
6#include "mtrr.h"
7
8int arr3_protected;
9
10static void
11cyrix_get_arr(unsigned int reg, unsigned long *base,
12 unsigned int *size, mtrr_type * type)
13{
14 unsigned long flags;
15 unsigned char arr, ccr3, rcr, shift;
16
17 arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
18
19 /* Save flags and disable interrupts */
20 local_irq_save(flags);
21
22 ccr3 = getCx86(CX86_CCR3);
23 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
24 ((unsigned char *) base)[3] = getCx86(arr);
25 ((unsigned char *) base)[2] = getCx86(arr + 1);
26 ((unsigned char *) base)[1] = getCx86(arr + 2);
27 rcr = getCx86(CX86_RCR_BASE + reg);
28 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
29
30 /* Enable interrupts if it was enabled previously */
31 local_irq_restore(flags);
32 shift = ((unsigned char *) base)[1] & 0x0f;
33 *base >>= PAGE_SHIFT;
34
35 /* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7
36 * Note: shift==0xf means 4G, this is unsupported.
37 */
38 if (shift)
39 *size = (reg < 7 ? 0x1UL : 0x40UL) << (shift - 1);
40 else
41 *size = 0;
42
43 /* Bit 0 is Cache Enable on ARR7, Cache Disable on ARR0-ARR6 */
44 if (reg < 7) {
45 switch (rcr) {
46 case 1:
47 *type = MTRR_TYPE_UNCACHABLE;
48 break;
49 case 8:
50 *type = MTRR_TYPE_WRBACK;
51 break;
52 case 9:
53 *type = MTRR_TYPE_WRCOMB;
54 break;
55 case 24:
56 default:
57 *type = MTRR_TYPE_WRTHROUGH;
58 break;
59 }
60 } else {
61 switch (rcr) {
62 case 0:
63 *type = MTRR_TYPE_UNCACHABLE;
64 break;
65 case 8:
66 *type = MTRR_TYPE_WRCOMB;
67 break;
68 case 9:
69 *type = MTRR_TYPE_WRBACK;
70 break;
71 case 25:
72 default:
73 *type = MTRR_TYPE_WRTHROUGH;
74 break;
75 }
76 }
77}
78
79static int
80cyrix_get_free_region(unsigned long base, unsigned long size)
81/* [SUMMARY] Get a free ARR.
82 <base> The starting (base) address of the region.
83 <size> The size (in bytes) of the region.
84 [RETURNS] The index of the region on success, else -1 on error.
85*/
86{
87 int i;
88 mtrr_type ltype;
89 unsigned long lbase;
90 unsigned int lsize;
91
92 /* If we are to set up a region >32M then look at ARR7 immediately */
93 if (size > 0x2000) {
94 cyrix_get_arr(7, &lbase, &lsize, &ltype);
95 if (lsize == 0)
96 return 7;
97 /* Else try ARR0-ARR6 first */
98 } else {
99 for (i = 0; i < 7; i++) {
100 cyrix_get_arr(i, &lbase, &lsize, &ltype);
101 if ((i == 3) && arr3_protected)
102 continue;
103 if (lsize == 0)
104 return i;
105 }
106 /* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
107 cyrix_get_arr(i, &lbase, &lsize, &ltype);
108 if ((lsize == 0) && (size >= 0x40))
109 return i;
110 }
111 return -ENOSPC;
112}
113
114static u32 cr4 = 0;
115static u32 ccr3;
116
117static void prepare_set(void)
118{
119 u32 cr0;
120
121 /* Save value of CR4 and clear Page Global Enable (bit 7) */
122 if ( cpu_has_pge ) {
123 cr4 = read_cr4();
124 write_cr4(cr4 & (unsigned char) ~(1 << 7));
125 }
126
127 /* Disable and flush caches. Note that wbinvd flushes the TLBs as
128 a side-effect */
129 cr0 = read_cr0() | 0x40000000;
130 wbinvd();
131 write_cr0(cr0);
132 wbinvd();
133
134 /* Cyrix ARRs - everything else were excluded at the top */
135 ccr3 = getCx86(CX86_CCR3);
136
137 /* Cyrix ARRs - everything else were excluded at the top */
138 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);
139
140}
141
142static void post_set(void)
143{
144 /* Flush caches and TLBs */
145 wbinvd();
146
147 /* Cyrix ARRs - everything else was excluded at the top */
148 setCx86(CX86_CCR3, ccr3);
149
150 /* Enable caches */
151 write_cr0(read_cr0() & 0xbfffffff);
152
153 /* Restore value of CR4 */
154 if ( cpu_has_pge )
155 write_cr4(cr4);
156}
157
158static void cyrix_set_arr(unsigned int reg, unsigned long base,
159 unsigned long size, mtrr_type type)
160{
161 unsigned char arr, arr_type, arr_size;
162
163 arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
164
165 /* count down from 32M (ARR0-ARR6) or from 2G (ARR7) */
166 if (reg >= 7)
167 size >>= 6;
168
169 size &= 0x7fff; /* make sure arr_size <= 14 */
170 for (arr_size = 0; size; arr_size++, size >>= 1) ;
171
172 if (reg < 7) {
173 switch (type) {
174 case MTRR_TYPE_UNCACHABLE:
175 arr_type = 1;
176 break;
177 case MTRR_TYPE_WRCOMB:
178 arr_type = 9;
179 break;
180 case MTRR_TYPE_WRTHROUGH:
181 arr_type = 24;
182 break;
183 default:
184 arr_type = 8;
185 break;
186 }
187 } else {
188 switch (type) {
189 case MTRR_TYPE_UNCACHABLE:
190 arr_type = 0;
191 break;
192 case MTRR_TYPE_WRCOMB:
193 arr_type = 8;
194 break;
195 case MTRR_TYPE_WRTHROUGH:
196 arr_type = 25;
197 break;
198 default:
199 arr_type = 9;
200 break;
201 }
202 }
203
204 prepare_set();
205
206 base <<= PAGE_SHIFT;
207 setCx86(arr, ((unsigned char *) &base)[3]);
208 setCx86(arr + 1, ((unsigned char *) &base)[2]);
209 setCx86(arr + 2, (((unsigned char *) &base)[1]) | arr_size);
210 setCx86(CX86_RCR_BASE + reg, arr_type);
211
212 post_set();
213}
214
215typedef struct {
216 unsigned long base;
217 unsigned int size;
218 mtrr_type type;
219} arr_state_t;
220
221static arr_state_t arr_state[8] __initdata = {
222 {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
223 {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
224};
225
226static unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
227
228static void cyrix_set_all(void)
229{
230 int i;
231
232 prepare_set();
233
234 /* the CCRs are not contiguous */
235 for (i = 0; i < 4; i++)
236 setCx86(CX86_CCR0 + i, ccr_state[i]);
237 for (; i < 7; i++)
238 setCx86(CX86_CCR4 + i, ccr_state[i]);
239 for (i = 0; i < 8; i++)
240 cyrix_set_arr(i, arr_state[i].base,
241 arr_state[i].size, arr_state[i].type);
242
243 post_set();
244}
245
246#if 0
247/*
248 * On Cyrix 6x86(MX) and M II the ARR3 is special: it has connection
249 * with the SMM (System Management Mode) mode. So we need the following:
250 * Check whether SMI_LOCK (CCR3 bit 0) is set
251 * if it is set, write a warning message: ARR3 cannot be changed!
252 * (it cannot be changed until the next processor reset)
253 * if it is reset, then we can change it, set all the needed bits:
254 * - disable access to SMM memory through ARR3 range (CCR1 bit 7 reset)
255 * - disable access to SMM memory (CCR1 bit 2 reset)
256 * - disable SMM mode (CCR1 bit 1 reset)
257 * - disable write protection of ARR3 (CCR6 bit 1 reset)
258 * - (maybe) disable ARR3
259 * Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set)
260 */
261static void __init
262cyrix_arr_init(void)
263{
264 struct set_mtrr_context ctxt;
265 unsigned char ccr[7];
266 int ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 };
267#ifdef CONFIG_SMP
268 int i;
269#endif
270
271 /* flush cache and enable MAPEN */
272 set_mtrr_prepare_save(&ctxt);
273 set_mtrr_cache_disable(&ctxt);
274
275 /* Save all CCRs locally */
276 ccr[0] = getCx86(CX86_CCR0);
277 ccr[1] = getCx86(CX86_CCR1);
278 ccr[2] = getCx86(CX86_CCR2);
279 ccr[3] = ctxt.ccr3;
280 ccr[4] = getCx86(CX86_CCR4);
281 ccr[5] = getCx86(CX86_CCR5);
282 ccr[6] = getCx86(CX86_CCR6);
283
284 if (ccr[3] & 1) {
285 ccrc[3] = 1;
286 arr3_protected = 1;
287 } else {
288 /* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
289 * access to SMM memory through ARR3 (bit 7).
290 */
291 if (ccr[1] & 0x80) {
292 ccr[1] &= 0x7f;
293 ccrc[1] |= 0x80;
294 }
295 if (ccr[1] & 0x04) {
296 ccr[1] &= 0xfb;
297 ccrc[1] |= 0x04;
298 }
299 if (ccr[1] & 0x02) {
300 ccr[1] &= 0xfd;
301 ccrc[1] |= 0x02;
302 }
303 arr3_protected = 0;
304 if (ccr[6] & 0x02) {
305 ccr[6] &= 0xfd;
306 ccrc[6] = 1; /* Disable write protection of ARR3 */
307 setCx86(CX86_CCR6, ccr[6]);
308 }
309 /* Disable ARR3. This is safe now that we disabled SMM. */
310 /* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
311 }
312 /* If we changed CCR1 in memory, change it in the processor, too. */
313 if (ccrc[1])
314 setCx86(CX86_CCR1, ccr[1]);
315
316 /* Enable ARR usage by the processor */
317 if (!(ccr[5] & 0x20)) {
318 ccr[5] |= 0x20;
319 ccrc[5] = 1;
320 setCx86(CX86_CCR5, ccr[5]);
321 }
322#ifdef CONFIG_SMP
323 for (i = 0; i < 7; i++)
324 ccr_state[i] = ccr[i];
325 for (i = 0; i < 8; i++)
326 cyrix_get_arr(i,
327 &arr_state[i].base, &arr_state[i].size,
328 &arr_state[i].type);
329#endif
330
331 set_mtrr_done(&ctxt); /* flush cache and disable MAPEN */
332
333 if (ccrc[5])
334 printk(KERN_INFO "mtrr: ARR usage was not enabled, enabled manually\n");
335 if (ccrc[3])
336 printk(KERN_INFO "mtrr: ARR3 cannot be changed\n");
337/*
338 if ( ccrc[1] & 0x80) printk ("mtrr: SMM memory access through ARR3 disabled\n");
339 if ( ccrc[1] & 0x04) printk ("mtrr: SMM memory access disabled\n");
340 if ( ccrc[1] & 0x02) printk ("mtrr: SMM mode disabled\n");
341*/
342 if (ccrc[6])
343 printk(KERN_INFO "mtrr: ARR3 was write protected, unprotected\n");
344}
345#endif
346
347static struct mtrr_ops cyrix_mtrr_ops = {
348 .vendor = X86_VENDOR_CYRIX,
349// .init = cyrix_arr_init,
350 .set_all = cyrix_set_all,
351 .set = cyrix_set_arr,
352 .get = cyrix_get_arr,
353 .get_free_region = cyrix_get_free_region,
354 .validate_add_page = generic_validate_add_page,
355 .have_wrcomb = positive_have_wrcomb,
356};
357
358int __init cyrix_init_mtrr(void)
359{
360 set_mtrr_ops(&cyrix_mtrr_ops);
361 return 0;
362}
363
364//arch_initcall(cyrix_init_mtrr);
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
new file mode 100644
index 000000000000..a4cce454d09b
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -0,0 +1,417 @@
1/* This only handles 32bit MTRR on 32bit hosts. This is strictly wrong
2 because MTRRs can span upto 40 bits (36bits on most modern x86) */
3#include <linux/init.h>
4#include <linux/slab.h>
5#include <linux/mm.h>
6#include <asm/io.h>
7#include <asm/mtrr.h>
8#include <asm/msr.h>
9#include <asm/system.h>
10#include <asm/cpufeature.h>
11#include <asm/tlbflush.h>
12#include "mtrr.h"
13
14struct mtrr_state {
15 struct mtrr_var_range *var_ranges;
16 mtrr_type fixed_ranges[NUM_FIXED_RANGES];
17 unsigned char enabled;
18 mtrr_type def_type;
19};
20
21static unsigned long smp_changes_mask;
22static struct mtrr_state mtrr_state = {};
23
24/* Get the MSR pair relating to a var range */
25static void __init
26get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
27{
28 rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
29 rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
30}
31
32static void __init
33get_fixed_ranges(mtrr_type * frs)
34{
35 unsigned int *p = (unsigned int *) frs;
36 int i;
37
38 rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
39
40 for (i = 0; i < 2; i++)
41 rdmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2], p[3 + i * 2]);
42 for (i = 0; i < 8; i++)
43 rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]);
44}
45
46/* Grab all of the MTRR state for this CPU into *state */
47void __init get_mtrr_state(void)
48{
49 unsigned int i;
50 struct mtrr_var_range *vrs;
51 unsigned lo, dummy;
52
53 if (!mtrr_state.var_ranges) {
54 mtrr_state.var_ranges = kmalloc(num_var_ranges * sizeof (struct mtrr_var_range),
55 GFP_KERNEL);
56 if (!mtrr_state.var_ranges)
57 return;
58 }
59 vrs = mtrr_state.var_ranges;
60
61 for (i = 0; i < num_var_ranges; i++)
62 get_mtrr_var_range(i, &vrs[i]);
63 get_fixed_ranges(mtrr_state.fixed_ranges);
64
65 rdmsr(MTRRdefType_MSR, lo, dummy);
66 mtrr_state.def_type = (lo & 0xff);
67 mtrr_state.enabled = (lo & 0xc00) >> 10;
68}
69
70/* Free resources associated with a struct mtrr_state */
71void __init finalize_mtrr_state(void)
72{
73 if (mtrr_state.var_ranges)
74 kfree(mtrr_state.var_ranges);
75 mtrr_state.var_ranges = NULL;
76}
77
78/* Some BIOS's are fucked and don't set all MTRRs the same! */
79void __init mtrr_state_warn(void)
80{
81 unsigned long mask = smp_changes_mask;
82
83 if (!mask)
84 return;
85 if (mask & MTRR_CHANGE_MASK_FIXED)
86 printk(KERN_WARNING "mtrr: your CPUs had inconsistent fixed MTRR settings\n");
87 if (mask & MTRR_CHANGE_MASK_VARIABLE)
88 printk(KERN_WARNING "mtrr: your CPUs had inconsistent variable MTRR settings\n");
89 if (mask & MTRR_CHANGE_MASK_DEFTYPE)
90 printk(KERN_WARNING "mtrr: your CPUs had inconsistent MTRRdefType settings\n");
91 printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n");
92 printk(KERN_INFO "mtrr: corrected configuration.\n");
93}
94
95/* Doesn't attempt to pass an error out to MTRR users
96 because it's quite complicated in some cases and probably not
97 worth it because the best error handling is to ignore it. */
98void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
99{
100 if (wrmsr_safe(msr, a, b) < 0)
101 printk(KERN_ERR
102 "MTRR: CPU %u: Writing MSR %x to %x:%x failed\n",
103 smp_processor_id(), msr, a, b);
104}
105
106int generic_get_free_region(unsigned long base, unsigned long size)
107/* [SUMMARY] Get a free MTRR.
108 <base> The starting (base) address of the region.
109 <size> The size (in bytes) of the region.
110 [RETURNS] The index of the region on success, else -1 on error.
111*/
112{
113 int i, max;
114 mtrr_type ltype;
115 unsigned long lbase;
116 unsigned lsize;
117
118 max = num_var_ranges;
119 for (i = 0; i < max; ++i) {
120 mtrr_if->get(i, &lbase, &lsize, &ltype);
121 if (lsize == 0)
122 return i;
123 }
124 return -ENOSPC;
125}
126
127void generic_get_mtrr(unsigned int reg, unsigned long *base,
128 unsigned int *size, mtrr_type * type)
129{
130 unsigned int mask_lo, mask_hi, base_lo, base_hi;
131
132 rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
133 if ((mask_lo & 0x800) == 0) {
134 /* Invalid (i.e. free) range */
135 *base = 0;
136 *size = 0;
137 *type = 0;
138 return;
139 }
140
141 rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
142
143 /* Work out the shifted address mask. */
144 mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT)
145 | mask_lo >> PAGE_SHIFT;
146
147 /* This works correctly if size is a power of two, i.e. a
148 contiguous range. */
149 *size = -mask_lo;
150 *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
151 *type = base_lo & 0xff;
152}
153
154static int set_fixed_ranges(mtrr_type * frs)
155{
156 unsigned int *p = (unsigned int *) frs;
157 int changed = FALSE;
158 int i;
159 unsigned int lo, hi;
160
161 rdmsr(MTRRfix64K_00000_MSR, lo, hi);
162 if (p[0] != lo || p[1] != hi) {
163 mtrr_wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
164 changed = TRUE;
165 }
166
167 for (i = 0; i < 2; i++) {
168 rdmsr(MTRRfix16K_80000_MSR + i, lo, hi);
169 if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) {
170 mtrr_wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2],
171 p[3 + i * 2]);
172 changed = TRUE;
173 }
174 }
175
176 for (i = 0; i < 8; i++) {
177 rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi);
178 if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) {
179 mtrr_wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2],
180 p[7 + i * 2]);
181 changed = TRUE;
182 }
183 }
184 return changed;
185}
186
187/* Set the MSR pair relating to a var range. Returns TRUE if
188 changes are made */
189static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
190{
191 unsigned int lo, hi;
192 int changed = FALSE;
193
194 rdmsr(MTRRphysBase_MSR(index), lo, hi);
195 if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
196 || (vr->base_hi & 0xfUL) != (hi & 0xfUL)) {
197 mtrr_wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
198 changed = TRUE;
199 }
200
201 rdmsr(MTRRphysMask_MSR(index), lo, hi);
202
203 if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
204 || (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) {
205 mtrr_wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
206 changed = TRUE;
207 }
208 return changed;
209}
210
211static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi)
212/* [SUMMARY] Set the MTRR state for this CPU.
213 <state> The MTRR state information to read.
214 <ctxt> Some relevant CPU context.
215 [NOTE] The CPU must already be in a safe state for MTRR changes.
216 [RETURNS] 0 if no changes made, else a mask indication what was changed.
217*/
218{
219 unsigned int i;
220 unsigned long change_mask = 0;
221
222 for (i = 0; i < num_var_ranges; i++)
223 if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i]))
224 change_mask |= MTRR_CHANGE_MASK_VARIABLE;
225
226 if (set_fixed_ranges(mtrr_state.fixed_ranges))
227 change_mask |= MTRR_CHANGE_MASK_FIXED;
228
229 /* Set_mtrr_restore restores the old value of MTRRdefType,
230 so to set it we fiddle with the saved value */
231 if ((deftype_lo & 0xff) != mtrr_state.def_type
232 || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) {
233 deftype_lo |= (mtrr_state.def_type | mtrr_state.enabled << 10);
234 change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
235 }
236
237 return change_mask;
238}
239
240
241static unsigned long cr4 = 0;
242static u32 deftype_lo, deftype_hi;
243static DEFINE_SPINLOCK(set_atomicity_lock);
244
245/*
246 * Since we are disabling the cache don't allow any interrupts - they
247 * would run extremely slow and would only increase the pain. The caller must
248 * ensure that local interrupts are disabled and are reenabled after post_set()
249 * has been called.
250 */
251
252static void prepare_set(void)
253{
254 unsigned long cr0;
255
256 /* Note that this is not ideal, since the cache is only flushed/disabled
257 for this CPU while the MTRRs are changed, but changing this requires
258 more invasive changes to the way the kernel boots */
259
260 spin_lock(&set_atomicity_lock);
261
262 /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
263 cr0 = read_cr0() | 0x40000000; /* set CD flag */
264 write_cr0(cr0);
265 wbinvd();
266
267 /* Save value of CR4 and clear Page Global Enable (bit 7) */
268 if ( cpu_has_pge ) {
269 cr4 = read_cr4();
270 write_cr4(cr4 & ~X86_CR4_PGE);
271 }
272
273 /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
274 __flush_tlb();
275
276 /* Save MTRR state */
277 rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
278
279 /* Disable MTRRs, and set the default type to uncached */
280 mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
281}
282
283static void post_set(void)
284{
285 /* Flush TLBs (no need to flush caches - they are disabled) */
286 __flush_tlb();
287
288 /* Intel (P6) standard MTRRs */
289 mtrr_wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
290
291 /* Enable caches */
292 write_cr0(read_cr0() & 0xbfffffff);
293
294 /* Restore value of CR4 */
295 if ( cpu_has_pge )
296 write_cr4(cr4);
297 spin_unlock(&set_atomicity_lock);
298}
299
300static void generic_set_all(void)
301{
302 unsigned long mask, count;
303 unsigned long flags;
304
305 local_irq_save(flags);
306 prepare_set();
307
308 /* Actually set the state */
309 mask = set_mtrr_state(deftype_lo,deftype_hi);
310
311 post_set();
312 local_irq_restore(flags);
313
314 /* Use the atomic bitops to update the global mask */
315 for (count = 0; count < sizeof mask * 8; ++count) {
316 if (mask & 0x01)
317 set_bit(count, &smp_changes_mask);
318 mask >>= 1;
319 }
320
321}
322
323static void generic_set_mtrr(unsigned int reg, unsigned long base,
324 unsigned long size, mtrr_type type)
325/* [SUMMARY] Set variable MTRR register on the local CPU.
326 <reg> The register to set.
327 <base> The base address of the region.
328 <size> The size of the region. If this is 0 the region is disabled.
329 <type> The type of the region.
330 <do_safe> If TRUE, do the change safely. If FALSE, safety measures should
331 be done externally.
332 [RETURNS] Nothing.
333*/
334{
335 unsigned long flags;
336
337 local_irq_save(flags);
338 prepare_set();
339
340 if (size == 0) {
341 /* The invalid bit is kept in the mask, so we simply clear the
342 relevant mask register to disable a range. */
343 mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0);
344 } else {
345 mtrr_wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type,
346 (base & size_and_mask) >> (32 - PAGE_SHIFT));
347 mtrr_wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800,
348 (-size & size_and_mask) >> (32 - PAGE_SHIFT));
349 }
350
351 post_set();
352 local_irq_restore(flags);
353}
354
355int generic_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
356{
357 unsigned long lbase, last;
358
359 /* For Intel PPro stepping <= 7, must be 4 MiB aligned
360 and not touch 0x70000000->0x7003FFFF */
361 if (is_cpu(INTEL) && boot_cpu_data.x86 == 6 &&
362 boot_cpu_data.x86_model == 1 &&
363 boot_cpu_data.x86_mask <= 7) {
364 if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
365 printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
366 return -EINVAL;
367 }
368 if (!(base + size < 0x70000000 || base > 0x7003FFFF) &&
369 (type == MTRR_TYPE_WRCOMB
370 || type == MTRR_TYPE_WRBACK)) {
371 printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
372 return -EINVAL;
373 }
374 }
375
376 if (base + size < 0x100) {
377 printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
378 base, size);
379 return -EINVAL;
380 }
381 /* Check upper bits of base and last are equal and lower bits are 0
382 for base and 1 for last */
383 last = base + size - 1;
384 for (lbase = base; !(lbase & 1) && (last & 1);
385 lbase = lbase >> 1, last = last >> 1) ;
386 if (lbase != last) {
387 printk(KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
388 base, size);
389 return -EINVAL;
390 }
391 return 0;
392}
393
394
395static int generic_have_wrcomb(void)
396{
397 unsigned long config, dummy;
398 rdmsr(MTRRcap_MSR, config, dummy);
399 return (config & (1 << 10));
400}
401
402int positive_have_wrcomb(void)
403{
404 return 1;
405}
406
407/* generic structure...
408 */
409struct mtrr_ops generic_mtrr_ops = {
410 .use_intel_if = 1,
411 .set_all = generic_set_all,
412 .get = generic_get_mtrr,
413 .get_free_region = generic_get_free_region,
414 .set = generic_set_mtrr,
415 .validate_add_page = generic_validate_add_page,
416 .have_wrcomb = generic_have_wrcomb,
417};
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c
new file mode 100644
index 000000000000..1923e0aed26a
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/if.c
@@ -0,0 +1,374 @@
1#include <linux/init.h>
2#include <linux/proc_fs.h>
3#include <linux/ctype.h>
4#include <linux/module.h>
5#include <linux/seq_file.h>
6#include <asm/uaccess.h>
7
8#define LINE_SIZE 80
9
10#include <asm/mtrr.h>
11#include "mtrr.h"
12
13/* RED-PEN: this is accessed without any locking */
14extern unsigned int *usage_table;
15
16
17#define FILE_FCOUNT(f) (((struct seq_file *)((f)->private_data))->private)
18
19static char *mtrr_strings[MTRR_NUM_TYPES] =
20{
21 "uncachable", /* 0 */
22 "write-combining", /* 1 */
23 "?", /* 2 */
24 "?", /* 3 */
25 "write-through", /* 4 */
26 "write-protect", /* 5 */
27 "write-back", /* 6 */
28};
29
30char *mtrr_attrib_to_str(int x)
31{
32 return (x <= 6) ? mtrr_strings[x] : "?";
33}
34
35#ifdef CONFIG_PROC_FS
36
37static int
38mtrr_file_add(unsigned long base, unsigned long size,
39 unsigned int type, char increment, struct file *file, int page)
40{
41 int reg, max;
42 unsigned int *fcount = FILE_FCOUNT(file);
43
44 max = num_var_ranges;
45 if (fcount == NULL) {
46 fcount = kmalloc(max * sizeof *fcount, GFP_KERNEL);
47 if (!fcount)
48 return -ENOMEM;
49 memset(fcount, 0, max * sizeof *fcount);
50 FILE_FCOUNT(file) = fcount;
51 }
52 if (!page) {
53 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)))
54 return -EINVAL;
55 base >>= PAGE_SHIFT;
56 size >>= PAGE_SHIFT;
57 }
58 reg = mtrr_add_page(base, size, type, 1);
59 if (reg >= 0)
60 ++fcount[reg];
61 return reg;
62}
63
64static int
65mtrr_file_del(unsigned long base, unsigned long size,
66 struct file *file, int page)
67{
68 int reg;
69 unsigned int *fcount = FILE_FCOUNT(file);
70
71 if (!page) {
72 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)))
73 return -EINVAL;
74 base >>= PAGE_SHIFT;
75 size >>= PAGE_SHIFT;
76 }
77 reg = mtrr_del_page(-1, base, size);
78 if (reg < 0)
79 return reg;
80 if (fcount == NULL)
81 return reg;
82 if (fcount[reg] < 1)
83 return -EINVAL;
84 --fcount[reg];
85 return reg;
86}
87
88/* RED-PEN: seq_file can seek now. this is ignored. */
89static ssize_t
90mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos)
91/* Format of control line:
92 "base=%Lx size=%Lx type=%s" OR:
93 "disable=%d"
94*/
95{
96 int i, err;
97 unsigned long reg;
98 unsigned long long base, size;
99 char *ptr;
100 char line[LINE_SIZE];
101 size_t linelen;
102
103 if (!capable(CAP_SYS_ADMIN))
104 return -EPERM;
105 if (!len)
106 return -EINVAL;
107 memset(line, 0, LINE_SIZE);
108 if (len > LINE_SIZE)
109 len = LINE_SIZE;
110 if (copy_from_user(line, buf, len - 1))
111 return -EFAULT;
112 linelen = strlen(line);
113 ptr = line + linelen - 1;
114 if (linelen && *ptr == '\n')
115 *ptr = '\0';
116 if (!strncmp(line, "disable=", 8)) {
117 reg = simple_strtoul(line + 8, &ptr, 0);
118 err = mtrr_del_page(reg, 0, 0);
119 if (err < 0)
120 return err;
121 return len;
122 }
123 if (strncmp(line, "base=", 5))
124 return -EINVAL;
125 base = simple_strtoull(line + 5, &ptr, 0);
126 for (; isspace(*ptr); ++ptr) ;
127 if (strncmp(ptr, "size=", 5))
128 return -EINVAL;
129 size = simple_strtoull(ptr + 5, &ptr, 0);
130 if ((base & 0xfff) || (size & 0xfff))
131 return -EINVAL;
132 for (; isspace(*ptr); ++ptr) ;
133 if (strncmp(ptr, "type=", 5))
134 return -EINVAL;
135 ptr += 5;
136 for (; isspace(*ptr); ++ptr) ;
137 for (i = 0; i < MTRR_NUM_TYPES; ++i) {
138 if (strcmp(ptr, mtrr_strings[i]))
139 continue;
140 base >>= PAGE_SHIFT;
141 size >>= PAGE_SHIFT;
142 err =
143 mtrr_add_page((unsigned long) base, (unsigned long) size, i,
144 1);
145 if (err < 0)
146 return err;
147 return len;
148 }
149 return -EINVAL;
150}
151
152static int
153mtrr_ioctl(struct inode *inode, struct file *file,
154 unsigned int cmd, unsigned long __arg)
155{
156 int err;
157 mtrr_type type;
158 struct mtrr_sentry sentry;
159 struct mtrr_gentry gentry;
160 void __user *arg = (void __user *) __arg;
161
162 switch (cmd) {
163 default:
164 return -ENOTTY;
165 case MTRRIOC_ADD_ENTRY:
166 if (!capable(CAP_SYS_ADMIN))
167 return -EPERM;
168 if (copy_from_user(&sentry, arg, sizeof sentry))
169 return -EFAULT;
170 err =
171 mtrr_file_add(sentry.base, sentry.size, sentry.type, 1,
172 file, 0);
173 if (err < 0)
174 return err;
175 break;
176 case MTRRIOC_SET_ENTRY:
177 if (!capable(CAP_SYS_ADMIN))
178 return -EPERM;
179 if (copy_from_user(&sentry, arg, sizeof sentry))
180 return -EFAULT;
181 err = mtrr_add(sentry.base, sentry.size, sentry.type, 0);
182 if (err < 0)
183 return err;
184 break;
185 case MTRRIOC_DEL_ENTRY:
186 if (!capable(CAP_SYS_ADMIN))
187 return -EPERM;
188 if (copy_from_user(&sentry, arg, sizeof sentry))
189 return -EFAULT;
190 err = mtrr_file_del(sentry.base, sentry.size, file, 0);
191 if (err < 0)
192 return err;
193 break;
194 case MTRRIOC_KILL_ENTRY:
195 if (!capable(CAP_SYS_ADMIN))
196 return -EPERM;
197 if (copy_from_user(&sentry, arg, sizeof sentry))
198 return -EFAULT;
199 err = mtrr_del(-1, sentry.base, sentry.size);
200 if (err < 0)
201 return err;
202 break;
203 case MTRRIOC_GET_ENTRY:
204 if (copy_from_user(&gentry, arg, sizeof gentry))
205 return -EFAULT;
206 if (gentry.regnum >= num_var_ranges)
207 return -EINVAL;
208 mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type);
209
210 /* Hide entries that go above 4GB */
211 if (gentry.base + gentry.size > 0x100000
212 || gentry.size == 0x100000)
213 gentry.base = gentry.size = gentry.type = 0;
214 else {
215 gentry.base <<= PAGE_SHIFT;
216 gentry.size <<= PAGE_SHIFT;
217 gentry.type = type;
218 }
219
220 if (copy_to_user(arg, &gentry, sizeof gentry))
221 return -EFAULT;
222 break;
223 case MTRRIOC_ADD_PAGE_ENTRY:
224 if (!capable(CAP_SYS_ADMIN))
225 return -EPERM;
226 if (copy_from_user(&sentry, arg, sizeof sentry))
227 return -EFAULT;
228 err =
229 mtrr_file_add(sentry.base, sentry.size, sentry.type, 1,
230 file, 1);
231 if (err < 0)
232 return err;
233 break;
234 case MTRRIOC_SET_PAGE_ENTRY:
235 if (!capable(CAP_SYS_ADMIN))
236 return -EPERM;
237 if (copy_from_user(&sentry, arg, sizeof sentry))
238 return -EFAULT;
239 err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0);
240 if (err < 0)
241 return err;
242 break;
243 case MTRRIOC_DEL_PAGE_ENTRY:
244 if (!capable(CAP_SYS_ADMIN))
245 return -EPERM;
246 if (copy_from_user(&sentry, arg, sizeof sentry))
247 return -EFAULT;
248 err = mtrr_file_del(sentry.base, sentry.size, file, 1);
249 if (err < 0)
250 return err;
251 break;
252 case MTRRIOC_KILL_PAGE_ENTRY:
253 if (!capable(CAP_SYS_ADMIN))
254 return -EPERM;
255 if (copy_from_user(&sentry, arg, sizeof sentry))
256 return -EFAULT;
257 err = mtrr_del_page(-1, sentry.base, sentry.size);
258 if (err < 0)
259 return err;
260 break;
261 case MTRRIOC_GET_PAGE_ENTRY:
262 if (copy_from_user(&gentry, arg, sizeof gentry))
263 return -EFAULT;
264 if (gentry.regnum >= num_var_ranges)
265 return -EINVAL;
266 mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type);
267 gentry.type = type;
268
269 if (copy_to_user(arg, &gentry, sizeof gentry))
270 return -EFAULT;
271 break;
272 }
273 return 0;
274}
275
276static int
277mtrr_close(struct inode *ino, struct file *file)
278{
279 int i, max;
280 unsigned int *fcount = FILE_FCOUNT(file);
281
282 if (fcount != NULL) {
283 max = num_var_ranges;
284 for (i = 0; i < max; ++i) {
285 while (fcount[i] > 0) {
286 mtrr_del(i, 0, 0);
287 --fcount[i];
288 }
289 }
290 kfree(fcount);
291 FILE_FCOUNT(file) = NULL;
292 }
293 return single_release(ino, file);
294}
295
296static int mtrr_seq_show(struct seq_file *seq, void *offset);
297
298static int mtrr_open(struct inode *inode, struct file *file)
299{
300 if (!mtrr_if)
301 return -EIO;
302 if (!mtrr_if->get)
303 return -ENXIO;
304 return single_open(file, mtrr_seq_show, NULL);
305}
306
307static struct file_operations mtrr_fops = {
308 .owner = THIS_MODULE,
309 .open = mtrr_open,
310 .read = seq_read,
311 .llseek = seq_lseek,
312 .write = mtrr_write,
313 .ioctl = mtrr_ioctl,
314 .release = mtrr_close,
315};
316
317
318static struct proc_dir_entry *proc_root_mtrr;
319
320
321static int mtrr_seq_show(struct seq_file *seq, void *offset)
322{
323 char factor;
324 int i, max, len;
325 mtrr_type type;
326 unsigned long base;
327 unsigned int size;
328
329 len = 0;
330 max = num_var_ranges;
331 for (i = 0; i < max; i++) {
332 mtrr_if->get(i, &base, &size, &type);
333 if (size == 0)
334 usage_table[i] = 0;
335 else {
336 if (size < (0x100000 >> PAGE_SHIFT)) {
337 /* less than 1MB */
338 factor = 'K';
339 size <<= PAGE_SHIFT - 10;
340 } else {
341 factor = 'M';
342 size >>= 20 - PAGE_SHIFT;
343 }
344 /* RED-PEN: base can be > 32bit */
345 len += seq_printf(seq,
346 "reg%02i: base=0x%05lx000 (%4liMB), size=%4i%cB: %s, count=%d\n",
347 i, base, base >> (20 - PAGE_SHIFT), size, factor,
348 mtrr_attrib_to_str(type), usage_table[i]);
349 }
350 }
351 return 0;
352}
353
354static int __init mtrr_if_init(void)
355{
356 struct cpuinfo_x86 *c = &boot_cpu_data;
357
358 if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
359 (!cpu_has(c, X86_FEATURE_K6_MTRR)) &&
360 (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) &&
361 (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
362 return -ENODEV;
363
364 proc_root_mtrr =
365 create_proc_entry("mtrr", S_IWUSR | S_IRUGO, &proc_root);
366 if (proc_root_mtrr) {
367 proc_root_mtrr->owner = THIS_MODULE;
368 proc_root_mtrr->proc_fops = &mtrr_fops;
369 }
370 return 0;
371}
372
373arch_initcall(mtrr_if_init);
374#endif /* CONFIG_PROC_FS */
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
new file mode 100644
index 000000000000..8f67b490a7fd
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -0,0 +1,693 @@
1/* Generic MTRR (Memory Type Range Register) driver.
2
3 Copyright (C) 1997-2000 Richard Gooch
4 Copyright (c) 2002 Patrick Mochel
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the Free
18 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 Richard Gooch may be reached by email at rgooch@atnf.csiro.au
21 The postal address is:
22 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
23
24 Source: "Pentium Pro Family Developer's Manual, Volume 3:
25 Operating System Writer's Guide" (Intel document number 242692),
26 section 11.11.7
27
28 This was cleaned and made readable by Patrick Mochel <mochel@osdl.org>
29 on 6-7 March 2002.
30 Source: Intel Architecture Software Developers Manual, Volume 3:
31 System Programming Guide; Section 9.11. (1997 edition - PPro).
32*/
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/pci.h>
37#include <linux/smp.h>
38#include <linux/cpu.h>
39
40#include <asm/mtrr.h>
41
42#include <asm/uaccess.h>
43#include <asm/processor.h>
44#include <asm/msr.h>
45#include "mtrr.h"
46
47#define MTRR_VERSION "2.0 (20020519)"
48
49u32 num_var_ranges = 0;
50
51unsigned int *usage_table;
52static DECLARE_MUTEX(main_lock);
53
54u32 size_or_mask, size_and_mask;
55
56static struct mtrr_ops * mtrr_ops[X86_VENDOR_NUM] = {};
57
58struct mtrr_ops * mtrr_if = NULL;
59
60static void set_mtrr(unsigned int reg, unsigned long base,
61 unsigned long size, mtrr_type type);
62
63extern int arr3_protected;
64
65void set_mtrr_ops(struct mtrr_ops * ops)
66{
67 if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
68 mtrr_ops[ops->vendor] = ops;
69}
70
71/* Returns non-zero if we have the write-combining memory type */
72static int have_wrcomb(void)
73{
74 struct pci_dev *dev;
75
76 if ((dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) {
77 /* ServerWorks LE chipsets have problems with write-combining
78 Don't allow it and leave room for other chipsets to be tagged */
79 if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
80 dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) {
81 printk(KERN_INFO "mtrr: Serverworks LE detected. Write-combining disabled.\n");
82 pci_dev_put(dev);
83 return 0;
84 }
85 /* Intel 450NX errata # 23. Non ascending cachline evictions to
86 write combining memory may resulting in data corruption */
87 if (dev->vendor == PCI_VENDOR_ID_INTEL &&
88 dev->device == PCI_DEVICE_ID_INTEL_82451NX) {
89 printk(KERN_INFO "mtrr: Intel 450NX MMC detected. Write-combining disabled.\n");
90 pci_dev_put(dev);
91 return 0;
92 }
93 pci_dev_put(dev);
94 }
95 return (mtrr_if->have_wrcomb ? mtrr_if->have_wrcomb() : 0);
96}
97
98/* This function returns the number of variable MTRRs */
99static void __init set_num_var_ranges(void)
100{
101 unsigned long config = 0, dummy;
102
103 if (use_intel()) {
104 rdmsr(MTRRcap_MSR, config, dummy);
105 } else if (is_cpu(AMD))
106 config = 2;
107 else if (is_cpu(CYRIX) || is_cpu(CENTAUR))
108 config = 8;
109 num_var_ranges = config & 0xff;
110}
111
112static void __init init_table(void)
113{
114 int i, max;
115
116 max = num_var_ranges;
117 if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
118 == NULL) {
119 printk(KERN_ERR "mtrr: could not allocate\n");
120 return;
121 }
122 for (i = 0; i < max; i++)
123 usage_table[i] = 1;
124}
125
126struct set_mtrr_data {
127 atomic_t count;
128 atomic_t gate;
129 unsigned long smp_base;
130 unsigned long smp_size;
131 unsigned int smp_reg;
132 mtrr_type smp_type;
133};
134
135#ifdef CONFIG_SMP
136
137static void ipi_handler(void *info)
138/* [SUMMARY] Synchronisation handler. Executed by "other" CPUs.
139 [RETURNS] Nothing.
140*/
141{
142 struct set_mtrr_data *data = info;
143 unsigned long flags;
144
145 local_irq_save(flags);
146
147 atomic_dec(&data->count);
148 while(!atomic_read(&data->gate))
149 cpu_relax();
150
151 /* The master has cleared me to execute */
152 if (data->smp_reg != ~0U)
153 mtrr_if->set(data->smp_reg, data->smp_base,
154 data->smp_size, data->smp_type);
155 else
156 mtrr_if->set_all();
157
158 atomic_dec(&data->count);
159 while(atomic_read(&data->gate))
160 cpu_relax();
161
162 atomic_dec(&data->count);
163 local_irq_restore(flags);
164}
165
166#endif
167
168/**
169 * set_mtrr - update mtrrs on all processors
170 * @reg: mtrr in question
171 * @base: mtrr base
172 * @size: mtrr size
173 * @type: mtrr type
174 *
175 * This is kinda tricky, but fortunately, Intel spelled it out for us cleanly:
176 *
177 * 1. Send IPI to do the following:
178 * 2. Disable Interrupts
179 * 3. Wait for all procs to do so
180 * 4. Enter no-fill cache mode
181 * 5. Flush caches
182 * 6. Clear PGE bit
183 * 7. Flush all TLBs
184 * 8. Disable all range registers
185 * 9. Update the MTRRs
186 * 10. Enable all range registers
187 * 11. Flush all TLBs and caches again
188 * 12. Enter normal cache mode and reenable caching
189 * 13. Set PGE
190 * 14. Wait for buddies to catch up
191 * 15. Enable interrupts.
192 *
193 * What does that mean for us? Well, first we set data.count to the number
194 * of CPUs. As each CPU disables interrupts, it'll decrement it once. We wait
195 * until it hits 0 and proceed. We set the data.gate flag and reset data.count.
196 * Meanwhile, they are waiting for that flag to be set. Once it's set, each
197 * CPU goes through the transition of updating MTRRs. The CPU vendors may each do it
198 * differently, so we call mtrr_if->set() callback and let them take care of it.
199 * When they're done, they again decrement data->count and wait for data.gate to
200 * be reset.
201 * When we finish, we wait for data.count to hit 0 and toggle the data.gate flag.
202 * Everyone then enables interrupts and we all continue on.
203 *
204 * Note that the mechanism is the same for UP systems, too; all the SMP stuff
205 * becomes nops.
206 */
207static void set_mtrr(unsigned int reg, unsigned long base,
208 unsigned long size, mtrr_type type)
209{
210 struct set_mtrr_data data;
211 unsigned long flags;
212
213 data.smp_reg = reg;
214 data.smp_base = base;
215 data.smp_size = size;
216 data.smp_type = type;
217 atomic_set(&data.count, num_booting_cpus() - 1);
218 atomic_set(&data.gate,0);
219
220 /* Start the ball rolling on other CPUs */
221 if (smp_call_function(ipi_handler, &data, 1, 0) != 0)
222 panic("mtrr: timed out waiting for other CPUs\n");
223
224 local_irq_save(flags);
225
226 while(atomic_read(&data.count))
227 cpu_relax();
228
229 /* ok, reset count and toggle gate */
230 atomic_set(&data.count, num_booting_cpus() - 1);
231 atomic_set(&data.gate,1);
232
233 /* do our MTRR business */
234
235 /* HACK!
236 * We use this same function to initialize the mtrrs on boot.
237 * The state of the boot cpu's mtrrs has been saved, and we want
238 * to replicate across all the APs.
239 * If we're doing that @reg is set to something special...
240 */
241 if (reg != ~0U)
242 mtrr_if->set(reg,base,size,type);
243
244 /* wait for the others */
245 while(atomic_read(&data.count))
246 cpu_relax();
247
248 atomic_set(&data.count, num_booting_cpus() - 1);
249 atomic_set(&data.gate,0);
250
251 /*
252 * Wait here for everyone to have seen the gate change
253 * So we're the last ones to touch 'data'
254 */
255 while(atomic_read(&data.count))
256 cpu_relax();
257
258 local_irq_restore(flags);
259}
260
261/**
262 * mtrr_add_page - Add a memory type region
263 * @base: Physical base address of region in pages (4 KB)
264 * @size: Physical size of region in pages (4 KB)
265 * @type: Type of MTRR desired
266 * @increment: If this is true do usage counting on the region
267 *
268 * Memory type region registers control the caching on newer Intel and
269 * non Intel processors. This function allows drivers to request an
270 * MTRR is added. The details and hardware specifics of each processor's
271 * implementation are hidden from the caller, but nevertheless the
272 * caller should expect to need to provide a power of two size on an
273 * equivalent power of two boundary.
274 *
275 * If the region cannot be added either because all regions are in use
276 * or the CPU cannot support it a negative value is returned. On success
277 * the register number for this entry is returned, but should be treated
278 * as a cookie only.
279 *
280 * On a multiprocessor machine the changes are made to all processors.
281 * This is required on x86 by the Intel processors.
282 *
283 * The available types are
284 *
285 * %MTRR_TYPE_UNCACHABLE - No caching
286 *
287 * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
288 *
289 * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
290 *
291 * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
292 *
293 * BUGS: Needs a quiet flag for the cases where drivers do not mind
294 * failures and do not wish system log messages to be sent.
295 */
296
297int mtrr_add_page(unsigned long base, unsigned long size,
298 unsigned int type, char increment)
299{
300 int i;
301 mtrr_type ltype;
302 unsigned long lbase;
303 unsigned int lsize;
304 int error;
305
306 if (!mtrr_if)
307 return -ENXIO;
308
309 if ((error = mtrr_if->validate_add_page(base,size,type)))
310 return error;
311
312 if (type >= MTRR_NUM_TYPES) {
313 printk(KERN_WARNING "mtrr: type: %u invalid\n", type);
314 return -EINVAL;
315 }
316
317 /* If the type is WC, check that this processor supports it */
318 if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
319 printk(KERN_WARNING
320 "mtrr: your processor doesn't support write-combining\n");
321 return -ENOSYS;
322 }
323
324 if (base & size_or_mask || size & size_or_mask) {
325 printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n");
326 return -EINVAL;
327 }
328
329 error = -EINVAL;
330
331 /* Search for existing MTRR */
332 down(&main_lock);
333 for (i = 0; i < num_var_ranges; ++i) {
334 mtrr_if->get(i, &lbase, &lsize, &ltype);
335 if (base >= lbase + lsize)
336 continue;
337 if ((base < lbase) && (base + size <= lbase))
338 continue;
339 /* At this point we know there is some kind of overlap/enclosure */
340 if ((base < lbase) || (base + size > lbase + lsize)) {
341 printk(KERN_WARNING
342 "mtrr: 0x%lx000,0x%lx000 overlaps existing"
343 " 0x%lx000,0x%x000\n", base, size, lbase,
344 lsize);
345 goto out;
346 }
347 /* New region is enclosed by an existing region */
348 if (ltype != type) {
349 if (type == MTRR_TYPE_UNCACHABLE)
350 continue;
351 printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
352 base, size, mtrr_attrib_to_str(ltype),
353 mtrr_attrib_to_str(type));
354 goto out;
355 }
356 if (increment)
357 ++usage_table[i];
358 error = i;
359 goto out;
360 }
361 /* Search for an empty MTRR */
362 i = mtrr_if->get_free_region(base, size);
363 if (i >= 0) {
364 set_mtrr(i, base, size, type);
365 usage_table[i] = 1;
366 } else
367 printk(KERN_INFO "mtrr: no more MTRRs available\n");
368 error = i;
369 out:
370 up(&main_lock);
371 return error;
372}
373
374/**
375 * mtrr_add - Add a memory type region
376 * @base: Physical base address of region
377 * @size: Physical size of region
378 * @type: Type of MTRR desired
379 * @increment: If this is true do usage counting on the region
380 *
381 * Memory type region registers control the caching on newer Intel and
382 * non Intel processors. This function allows drivers to request an
383 * MTRR is added. The details and hardware specifics of each processor's
384 * implementation are hidden from the caller, but nevertheless the
385 * caller should expect to need to provide a power of two size on an
386 * equivalent power of two boundary.
387 *
388 * If the region cannot be added either because all regions are in use
389 * or the CPU cannot support it a negative value is returned. On success
390 * the register number for this entry is returned, but should be treated
391 * as a cookie only.
392 *
393 * On a multiprocessor machine the changes are made to all processors.
394 * This is required on x86 by the Intel processors.
395 *
396 * The available types are
397 *
398 * %MTRR_TYPE_UNCACHABLE - No caching
399 *
400 * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
401 *
402 * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
403 *
404 * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
405 *
406 * BUGS: Needs a quiet flag for the cases where drivers do not mind
407 * failures and do not wish system log messages to be sent.
408 */
409
410int
411mtrr_add(unsigned long base, unsigned long size, unsigned int type,
412 char increment)
413{
414 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
415 printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n");
416 printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
417 return -EINVAL;
418 }
419 return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
420 increment);
421}
422
423/**
424 * mtrr_del_page - delete a memory type region
425 * @reg: Register returned by mtrr_add
426 * @base: Physical base address
427 * @size: Size of region
428 *
429 * If register is supplied then base and size are ignored. This is
430 * how drivers should call it.
431 *
432 * Releases an MTRR region. If the usage count drops to zero the
433 * register is freed and the region returns to default state.
434 * On success the register is returned, on failure a negative error
435 * code.
436 */
437
438int mtrr_del_page(int reg, unsigned long base, unsigned long size)
439{
440 int i, max;
441 mtrr_type ltype;
442 unsigned long lbase;
443 unsigned int lsize;
444 int error = -EINVAL;
445
446 if (!mtrr_if)
447 return -ENXIO;
448
449 max = num_var_ranges;
450 down(&main_lock);
451 if (reg < 0) {
452 /* Search for existing MTRR */
453 for (i = 0; i < max; ++i) {
454 mtrr_if->get(i, &lbase, &lsize, &ltype);
455 if (lbase == base && lsize == size) {
456 reg = i;
457 break;
458 }
459 }
460 if (reg < 0) {
461 printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
462 size);
463 goto out;
464 }
465 }
466 if (reg >= max) {
467 printk(KERN_WARNING "mtrr: register: %d too big\n", reg);
468 goto out;
469 }
470 if (is_cpu(CYRIX) && !use_intel()) {
471 if ((reg == 3) && arr3_protected) {
472 printk(KERN_WARNING "mtrr: ARR3 cannot be changed\n");
473 goto out;
474 }
475 }
476 mtrr_if->get(reg, &lbase, &lsize, &ltype);
477 if (lsize < 1) {
478 printk(KERN_WARNING "mtrr: MTRR %d not used\n", reg);
479 goto out;
480 }
481 if (usage_table[reg] < 1) {
482 printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
483 goto out;
484 }
485 if (--usage_table[reg] < 1)
486 set_mtrr(reg, 0, 0, 0);
487 error = reg;
488 out:
489 up(&main_lock);
490 return error;
491}
492/**
493 * mtrr_del - delete a memory type region
494 * @reg: Register returned by mtrr_add
495 * @base: Physical base address
496 * @size: Size of region
497 *
498 * If register is supplied then base and size are ignored. This is
499 * how drivers should call it.
500 *
501 * Releases an MTRR region. If the usage count drops to zero the
502 * register is freed and the region returns to default state.
503 * On success the register is returned, on failure a negative error
504 * code.
505 */
506
507int
508mtrr_del(int reg, unsigned long base, unsigned long size)
509{
510 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
511 printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n");
512 printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
513 return -EINVAL;
514 }
515 return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
516}
517
518EXPORT_SYMBOL(mtrr_add);
519EXPORT_SYMBOL(mtrr_del);
520
521/* HACK ALERT!
522 * These should be called implicitly, but we can't yet until all the initcall
523 * stuff is done...
524 */
525extern void amd_init_mtrr(void);
526extern void cyrix_init_mtrr(void);
527extern void centaur_init_mtrr(void);
528
529static void __init init_ifs(void)
530{
531 amd_init_mtrr();
532 cyrix_init_mtrr();
533 centaur_init_mtrr();
534}
535
536static void __init init_other_cpus(void)
537{
538 if (use_intel())
539 get_mtrr_state();
540
541 /* bring up the other processors */
542 set_mtrr(~0U,0,0,0);
543
544 if (use_intel()) {
545 finalize_mtrr_state();
546 mtrr_state_warn();
547 }
548}
549
550
551struct mtrr_value {
552 mtrr_type ltype;
553 unsigned long lbase;
554 unsigned int lsize;
555};
556
557static struct mtrr_value * mtrr_state;
558
559static int mtrr_save(struct sys_device * sysdev, u32 state)
560{
561 int i;
562 int size = num_var_ranges * sizeof(struct mtrr_value);
563
564 mtrr_state = kmalloc(size,GFP_ATOMIC);
565 if (mtrr_state)
566 memset(mtrr_state,0,size);
567 else
568 return -ENOMEM;
569
570 for (i = 0; i < num_var_ranges; i++) {
571 mtrr_if->get(i,
572 &mtrr_state[i].lbase,
573 &mtrr_state[i].lsize,
574 &mtrr_state[i].ltype);
575 }
576 return 0;
577}
578
579static int mtrr_restore(struct sys_device * sysdev)
580{
581 int i;
582
583 for (i = 0; i < num_var_ranges; i++) {
584 if (mtrr_state[i].lsize)
585 set_mtrr(i,
586 mtrr_state[i].lbase,
587 mtrr_state[i].lsize,
588 mtrr_state[i].ltype);
589 }
590 kfree(mtrr_state);
591 return 0;
592}
593
594
595
596static struct sysdev_driver mtrr_sysdev_driver = {
597 .suspend = mtrr_save,
598 .resume = mtrr_restore,
599};
600
601
602/**
603 * mtrr_init - initialize mtrrs on the boot CPU
604 *
605 * This needs to be called early; before any of the other CPUs are
606 * initialized (i.e. before smp_init()).
607 *
608 */
609static int __init mtrr_init(void)
610{
611 init_ifs();
612
613 if (cpu_has_mtrr) {
614 mtrr_if = &generic_mtrr_ops;
615 size_or_mask = 0xff000000; /* 36 bits */
616 size_and_mask = 0x00f00000;
617
618 switch (boot_cpu_data.x86_vendor) {
619 case X86_VENDOR_AMD:
620 /* The original Athlon docs said that
621 total addressable memory is 44 bits wide.
622 It was not really clear whether its MTRRs
623 follow this or not. (Read: 44 or 36 bits).
624 However, "x86-64_overview.pdf" explicitly
625 states that "previous implementations support
626 36 bit MTRRs" and also provides a way to
627 query the width (in bits) of the physical
628 addressable memory on the Hammer family.
629 */
630 if (boot_cpu_data.x86 == 15
631 && (cpuid_eax(0x80000000) >= 0x80000008)) {
632 u32 phys_addr;
633 phys_addr = cpuid_eax(0x80000008) & 0xff;
634 size_or_mask =
635 ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
636 size_and_mask = ~size_or_mask & 0xfff00000;
637 }
638 /* Athlon MTRRs use an Intel-compatible interface for
639 * getting and setting */
640 break;
641 case X86_VENDOR_CENTAUR:
642 if (boot_cpu_data.x86 == 6) {
643 /* VIA Cyrix family have Intel style MTRRs, but don't support PAE */
644 size_or_mask = 0xfff00000; /* 32 bits */
645 size_and_mask = 0;
646 }
647 break;
648
649 default:
650 break;
651 }
652 } else {
653 switch (boot_cpu_data.x86_vendor) {
654 case X86_VENDOR_AMD:
655 if (cpu_has_k6_mtrr) {
656 /* Pre-Athlon (K6) AMD CPU MTRRs */
657 mtrr_if = mtrr_ops[X86_VENDOR_AMD];
658 size_or_mask = 0xfff00000; /* 32 bits */
659 size_and_mask = 0;
660 }
661 break;
662 case X86_VENDOR_CENTAUR:
663 if (cpu_has_centaur_mcr) {
664 mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR];
665 size_or_mask = 0xfff00000; /* 32 bits */
666 size_and_mask = 0;
667 }
668 break;
669 case X86_VENDOR_CYRIX:
670 if (cpu_has_cyrix_arr) {
671 mtrr_if = mtrr_ops[X86_VENDOR_CYRIX];
672 size_or_mask = 0xfff00000; /* 32 bits */
673 size_and_mask = 0;
674 }
675 break;
676 default:
677 break;
678 }
679 }
680 printk(KERN_INFO "mtrr: v%s\n",MTRR_VERSION);
681
682 if (mtrr_if) {
683 set_num_var_ranges();
684 init_table();
685 init_other_cpus();
686
687 return sysdev_driver_register(&cpu_sysdev_class,
688 &mtrr_sysdev_driver);
689 }
690 return -ENXIO;
691}
692
693subsys_initcall(mtrr_init);
diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h
new file mode 100644
index 000000000000..de1351245599
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/mtrr.h
@@ -0,0 +1,98 @@
1/*
2 * local mtrr defines.
3 */
4
5#ifndef TRUE
6#define TRUE 1
7#define FALSE 0
8#endif
9
10#define MTRRcap_MSR 0x0fe
11#define MTRRdefType_MSR 0x2ff
12
13#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
14#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
15
16#define NUM_FIXED_RANGES 88
17#define MTRRfix64K_00000_MSR 0x250
18#define MTRRfix16K_80000_MSR 0x258
19#define MTRRfix16K_A0000_MSR 0x259
20#define MTRRfix4K_C0000_MSR 0x268
21#define MTRRfix4K_C8000_MSR 0x269
22#define MTRRfix4K_D0000_MSR 0x26a
23#define MTRRfix4K_D8000_MSR 0x26b
24#define MTRRfix4K_E0000_MSR 0x26c
25#define MTRRfix4K_E8000_MSR 0x26d
26#define MTRRfix4K_F0000_MSR 0x26e
27#define MTRRfix4K_F8000_MSR 0x26f
28
29#define MTRR_CHANGE_MASK_FIXED 0x01
30#define MTRR_CHANGE_MASK_VARIABLE 0x02
31#define MTRR_CHANGE_MASK_DEFTYPE 0x04
32
33/* In the Intel processor's MTRR interface, the MTRR type is always held in
34 an 8 bit field: */
35typedef u8 mtrr_type;
36
37struct mtrr_ops {
38 u32 vendor;
39 u32 use_intel_if;
40// void (*init)(void);
41 void (*set)(unsigned int reg, unsigned long base,
42 unsigned long size, mtrr_type type);
43 void (*set_all)(void);
44
45 void (*get)(unsigned int reg, unsigned long *base,
46 unsigned int *size, mtrr_type * type);
47 int (*get_free_region) (unsigned long base, unsigned long size);
48
49 int (*validate_add_page)(unsigned long base, unsigned long size,
50 unsigned int type);
51 int (*have_wrcomb)(void);
52};
53
54extern int generic_get_free_region(unsigned long base, unsigned long size);
55extern int generic_validate_add_page(unsigned long base, unsigned long size,
56 unsigned int type);
57
58extern struct mtrr_ops generic_mtrr_ops;
59
60extern int positive_have_wrcomb(void);
61
62/* library functions for processor-specific routines */
63struct set_mtrr_context {
64 unsigned long flags;
65 unsigned long deftype_lo;
66 unsigned long deftype_hi;
67 unsigned long cr4val;
68 unsigned long ccr3;
69};
70
71struct mtrr_var_range {
72 unsigned long base_lo;
73 unsigned long base_hi;
74 unsigned long mask_lo;
75 unsigned long mask_hi;
76};
77
78void set_mtrr_done(struct set_mtrr_context *ctxt);
79void set_mtrr_cache_disable(struct set_mtrr_context *ctxt);
80void set_mtrr_prepare_save(struct set_mtrr_context *ctxt);
81
82void get_mtrr_state(void);
83
84extern void set_mtrr_ops(struct mtrr_ops * ops);
85
86extern u32 size_or_mask, size_and_mask;
87extern struct mtrr_ops * mtrr_if;
88
89#define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd)
90#define use_intel() (mtrr_if && mtrr_if->use_intel_if == 1)
91
92extern unsigned int num_var_ranges;
93
94void finalize_mtrr_state(void);
95void mtrr_state_warn(void);
96char *mtrr_attrib_to_str(int x);
97void mtrr_wrmsr(unsigned, unsigned, unsigned);
98
diff --git a/arch/i386/kernel/cpu/mtrr/state.c b/arch/i386/kernel/cpu/mtrr/state.c
new file mode 100644
index 000000000000..f62ecd15811a
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/state.c
@@ -0,0 +1,78 @@
1#include <linux/mm.h>
2#include <linux/init.h>
3#include <asm/io.h>
4#include <asm/mtrr.h>
5#include <asm/msr.h>
6#include "mtrr.h"
7
8
9/* Put the processor into a state where MTRRs can be safely set */
10void set_mtrr_prepare_save(struct set_mtrr_context *ctxt)
11{
12 unsigned int cr0;
13
14 /* Disable interrupts locally */
15 local_irq_save(ctxt->flags);
16
17 if (use_intel() || is_cpu(CYRIX)) {
18
19 /* Save value of CR4 and clear Page Global Enable (bit 7) */
20 if ( cpu_has_pge ) {
21 ctxt->cr4val = read_cr4();
22 write_cr4(ctxt->cr4val & (unsigned char) ~(1 << 7));
23 }
24
25 /* Disable and flush caches. Note that wbinvd flushes the TLBs as
26 a side-effect */
27 cr0 = read_cr0() | 0x40000000;
28 wbinvd();
29 write_cr0(cr0);
30 wbinvd();
31
32 if (use_intel())
33 /* Save MTRR state */
34 rdmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
35 else
36 /* Cyrix ARRs - everything else were excluded at the top */
37 ctxt->ccr3 = getCx86(CX86_CCR3);
38 }
39}
40
41void set_mtrr_cache_disable(struct set_mtrr_context *ctxt)
42{
43 if (use_intel())
44 /* Disable MTRRs, and set the default type to uncached */
45 mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL,
46 ctxt->deftype_hi);
47 else if (is_cpu(CYRIX))
48 /* Cyrix ARRs - everything else were excluded at the top */
49 setCx86(CX86_CCR3, (ctxt->ccr3 & 0x0f) | 0x10);
50}
51
52/* Restore the processor after a set_mtrr_prepare */
53void set_mtrr_done(struct set_mtrr_context *ctxt)
54{
55 if (use_intel() || is_cpu(CYRIX)) {
56
57 /* Flush caches and TLBs */
58 wbinvd();
59
60 /* Restore MTRRdefType */
61 if (use_intel())
62 /* Intel (P6) standard MTRRs */
63 mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
64 else
65 /* Cyrix ARRs - everything else was excluded at the top */
66 setCx86(CX86_CCR3, ctxt->ccr3);
67
68 /* Enable caches */
69 write_cr0(read_cr0() & 0xbfffffff);
70
71 /* Restore value of CR4 */
72 if ( cpu_has_pge )
73 write_cr4(ctxt->cr4val);
74 }
75 /* Re-enable interrupts locally (if enabled previously) */
76 local_irq_restore(ctxt->flags);
77}
78
diff --git a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c
new file mode 100644
index 000000000000..30898a260a5c
--- /dev/null
+++ b/arch/i386/kernel/cpu/nexgen.c
@@ -0,0 +1,63 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/string.h>
4#include <asm/processor.h>
5
6#include "cpu.h"
7
8/*
9 * Detect a NexGen CPU running without BIOS hypercode new enough
10 * to have CPUID. (Thanks to Herbert Oppmann)
11 */
12
13static int __init deep_magic_nexgen_probe(void)
14{
15 int ret;
16
17 __asm__ __volatile__ (
18 " movw $0x5555, %%ax\n"
19 " xorw %%dx,%%dx\n"
20 " movw $2, %%cx\n"
21 " divw %%cx\n"
22 " movl $0, %%eax\n"
23 " jnz 1f\n"
24 " movl $1, %%eax\n"
25 "1:\n"
26 : "=a" (ret) : : "cx", "dx" );
27 return ret;
28}
29
30static void __init init_nexgen(struct cpuinfo_x86 * c)
31{
32 c->x86_cache_size = 256; /* A few had 1 MB... */
33}
34
35static void __init nexgen_identify(struct cpuinfo_x86 * c)
36{
37 /* Detect NexGen with old hypercode */
38 if ( deep_magic_nexgen_probe() ) {
39 strcpy(c->x86_vendor_id, "NexGenDriven");
40 }
41 generic_identify(c);
42}
43
44static struct cpu_dev nexgen_cpu_dev __initdata = {
45 .c_vendor = "Nexgen",
46 .c_ident = { "NexGenDriven" },
47 .c_models = {
48 { .vendor = X86_VENDOR_NEXGEN,
49 .family = 5,
50 .model_names = { [1] = "Nx586" }
51 },
52 },
53 .c_init = init_nexgen,
54 .c_identify = nexgen_identify,
55};
56
57int __init nexgen_init_cpu(void)
58{
59 cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
60 return 0;
61}
62
63//early_arch_initcall(nexgen_init_cpu);
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
new file mode 100644
index 000000000000..c8d83fdc237a
--- /dev/null
+++ b/arch/i386/kernel/cpu/proc.c
@@ -0,0 +1,149 @@
1#include <linux/smp.h>
2#include <linux/timex.h>
3#include <linux/string.h>
4#include <asm/semaphore.h>
5#include <linux/seq_file.h>
6
7/*
8 * Get CPU information for use by the procfs.
9 */
10static int show_cpuinfo(struct seq_file *m, void *v)
11{
12 /*
13 * These flag bits must match the definitions in <asm/cpufeature.h>.
14 * NULL means this bit is undefined or reserved; either way it doesn't
15 * have meaning as far as Linux is concerned. Note that it's important
16 * to realize there is a difference between this table and CPUID -- if
17 * applications want to get the raw CPUID data, they should access
18 * /dev/cpu/<cpu_nr>/cpuid instead.
19 */
20 static char *x86_cap_flags[] = {
21 /* Intel-defined */
22 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
23 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
24 "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
25 "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
26
27 /* AMD-defined */
28 "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
29 NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
30 NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
31 NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
32
33 /* Transmeta-defined */
34 "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
35 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
36 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
37 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
38
39 /* Other (Linux-defined) */
40 "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
41 NULL, NULL, NULL, NULL,
42 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
43 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
44 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
45
46 /* Intel-defined (#2) */
47 "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
48 "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
49 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
50 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
51
52 /* VIA/Cyrix/Centaur-defined */
53 NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
54 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
55 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
56 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
57
58 /* AMD-defined (#2) */
59 "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
60 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
61 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
62 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
63 };
64 struct cpuinfo_x86 *c = v;
65 int i, n = c - cpu_data;
66 int fpu_exception;
67
68#ifdef CONFIG_SMP
69 if (!cpu_online(n))
70 return 0;
71#endif
72 seq_printf(m, "processor\t: %d\n"
73 "vendor_id\t: %s\n"
74 "cpu family\t: %d\n"
75 "model\t\t: %d\n"
76 "model name\t: %s\n",
77 n,
78 c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
79 c->x86,
80 c->x86_model,
81 c->x86_model_id[0] ? c->x86_model_id : "unknown");
82
83 if (c->x86_mask || c->cpuid_level >= 0)
84 seq_printf(m, "stepping\t: %d\n", c->x86_mask);
85 else
86 seq_printf(m, "stepping\t: unknown\n");
87
88 if ( cpu_has(c, X86_FEATURE_TSC) ) {
89 seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
90 cpu_khz / 1000, (cpu_khz % 1000));
91 }
92
93 /* Cache size */
94 if (c->x86_cache_size >= 0)
95 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
96#ifdef CONFIG_X86_HT
97 seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
98 seq_printf(m, "siblings\t: %d\n", c->x86_num_cores * smp_num_siblings);
99#endif
100
101 /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
102 fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu);
103 seq_printf(m, "fdiv_bug\t: %s\n"
104 "hlt_bug\t\t: %s\n"
105 "f00f_bug\t: %s\n"
106 "coma_bug\t: %s\n"
107 "fpu\t\t: %s\n"
108 "fpu_exception\t: %s\n"
109 "cpuid level\t: %d\n"
110 "wp\t\t: %s\n"
111 "flags\t\t:",
112 c->fdiv_bug ? "yes" : "no",
113 c->hlt_works_ok ? "no" : "yes",
114 c->f00f_bug ? "yes" : "no",
115 c->coma_bug ? "yes" : "no",
116 c->hard_math ? "yes" : "no",
117 fpu_exception ? "yes" : "no",
118 c->cpuid_level,
119 c->wp_works_ok ? "yes" : "no");
120
121 for ( i = 0 ; i < 32*NCAPINTS ; i++ )
122 if ( test_bit(i, c->x86_capability) &&
123 x86_cap_flags[i] != NULL )
124 seq_printf(m, " %s", x86_cap_flags[i]);
125
126 seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
127 c->loops_per_jiffy/(500000/HZ),
128 (c->loops_per_jiffy/(5000/HZ)) % 100);
129 return 0;
130}
131
132static void *c_start(struct seq_file *m, loff_t *pos)
133{
134 return *pos < NR_CPUS ? cpu_data + *pos : NULL;
135}
136static void *c_next(struct seq_file *m, void *v, loff_t *pos)
137{
138 ++*pos;
139 return c_start(m, pos);
140}
141static void c_stop(struct seq_file *m, void *v)
142{
143}
144struct seq_operations cpuinfo_op = {
145 .start = c_start,
146 .next = c_next,
147 .stop = c_stop,
148 .show = show_cpuinfo,
149};
diff --git a/arch/i386/kernel/cpu/rise.c b/arch/i386/kernel/cpu/rise.c
new file mode 100644
index 000000000000..8602425628ca
--- /dev/null
+++ b/arch/i386/kernel/cpu/rise.c
@@ -0,0 +1,53 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/bitops.h>
4#include <asm/processor.h>
5
6#include "cpu.h"
7
8static void __init init_rise(struct cpuinfo_x86 *c)
9{
10 printk("CPU: Rise iDragon");
11 if (c->x86_model > 2)
12 printk(" II");
13 printk("\n");
14
15 /* Unhide possibly hidden capability flags
16 The mp6 iDragon family don't have MSRs.
17 We switch on extra features with this cpuid weirdness: */
18 __asm__ (
19 "movl $0x6363452a, %%eax\n\t"
20 "movl $0x3231206c, %%ecx\n\t"
21 "movl $0x2a32313a, %%edx\n\t"
22 "cpuid\n\t"
23 "movl $0x63634523, %%eax\n\t"
24 "movl $0x32315f6c, %%ecx\n\t"
25 "movl $0x2333313a, %%edx\n\t"
26 "cpuid\n\t" : : : "eax", "ebx", "ecx", "edx"
27 );
28 set_bit(X86_FEATURE_CX8, c->x86_capability);
29}
30
31static struct cpu_dev rise_cpu_dev __initdata = {
32 .c_vendor = "Rise",
33 .c_ident = { "RiseRiseRise" },
34 .c_models = {
35 { .vendor = X86_VENDOR_RISE, .family = 5, .model_names =
36 {
37 [0] = "iDragon",
38 [2] = "iDragon",
39 [8] = "iDragon II",
40 [9] = "iDragon II"
41 }
42 },
43 },
44 .c_init = init_rise,
45};
46
47int __init rise_init_cpu(void)
48{
49 cpu_devs[X86_VENDOR_RISE] = &rise_cpu_dev;
50 return 0;
51}
52
53//early_arch_initcall(rise_init_cpu);
diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c
new file mode 100644
index 000000000000..f57e5ee94943
--- /dev/null
+++ b/arch/i386/kernel/cpu/transmeta.c
@@ -0,0 +1,107 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <asm/processor.h>
4#include <asm/msr.h>
5#include "cpu.h"
6
7static void __init init_transmeta(struct cpuinfo_x86 *c)
8{
9 unsigned int cap_mask, uk, max, dummy;
10 unsigned int cms_rev1, cms_rev2;
11 unsigned int cpu_rev, cpu_freq, cpu_flags, new_cpu_rev;
12 char cpu_info[65];
13
14 get_model_name(c); /* Same as AMD/Cyrix */
15 display_cacheinfo(c);
16
17 /* Print CMS and CPU revision */
18 max = cpuid_eax(0x80860000);
19 cpu_rev = 0;
20 if ( max >= 0x80860001 ) {
21 cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags);
22 if (cpu_rev != 0x02000000) {
23 printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
24 (cpu_rev >> 24) & 0xff,
25 (cpu_rev >> 16) & 0xff,
26 (cpu_rev >> 8) & 0xff,
27 cpu_rev & 0xff,
28 cpu_freq);
29 }
30 }
31 if ( max >= 0x80860002 ) {
32 cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy);
33 if (cpu_rev == 0x02000000) {
34 printk(KERN_INFO "CPU: Processor revision %08X, %u MHz\n",
35 new_cpu_rev, cpu_freq);
36 }
37 printk(KERN_INFO "CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n",
38 (cms_rev1 >> 24) & 0xff,
39 (cms_rev1 >> 16) & 0xff,
40 (cms_rev1 >> 8) & 0xff,
41 cms_rev1 & 0xff,
42 cms_rev2);
43 }
44 if ( max >= 0x80860006 ) {
45 cpuid(0x80860003,
46 (void *)&cpu_info[0],
47 (void *)&cpu_info[4],
48 (void *)&cpu_info[8],
49 (void *)&cpu_info[12]);
50 cpuid(0x80860004,
51 (void *)&cpu_info[16],
52 (void *)&cpu_info[20],
53 (void *)&cpu_info[24],
54 (void *)&cpu_info[28]);
55 cpuid(0x80860005,
56 (void *)&cpu_info[32],
57 (void *)&cpu_info[36],
58 (void *)&cpu_info[40],
59 (void *)&cpu_info[44]);
60 cpuid(0x80860006,
61 (void *)&cpu_info[48],
62 (void *)&cpu_info[52],
63 (void *)&cpu_info[56],
64 (void *)&cpu_info[60]);
65 cpu_info[64] = '\0';
66 printk(KERN_INFO "CPU: %s\n", cpu_info);
67 }
68
69 /* Unhide possibly hidden capability flags */
70 rdmsr(0x80860004, cap_mask, uk);
71 wrmsr(0x80860004, ~0, uk);
72 c->x86_capability[0] = cpuid_edx(0x00000001);
73 wrmsr(0x80860004, cap_mask, uk);
74
75 /* If we can run i686 user-space code, call us an i686 */
76#define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV)
77 if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 )
78 c->x86 = 6;
79}
80
81static void transmeta_identify(struct cpuinfo_x86 * c)
82{
83 u32 xlvl;
84 generic_identify(c);
85
86 /* Transmeta-defined flags: level 0x80860001 */
87 xlvl = cpuid_eax(0x80860000);
88 if ( (xlvl & 0xffff0000) == 0x80860000 ) {
89 if ( xlvl >= 0x80860001 )
90 c->x86_capability[2] = cpuid_edx(0x80860001);
91 }
92}
93
94static struct cpu_dev transmeta_cpu_dev __initdata = {
95 .c_vendor = "Transmeta",
96 .c_ident = { "GenuineTMx86", "TransmetaCPU" },
97 .c_init = init_transmeta,
98 .c_identify = transmeta_identify,
99};
100
101int __init transmeta_init_cpu(void)
102{
103 cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev;
104 return 0;
105}
106
107//early_arch_initcall(transmeta_init_cpu);
diff --git a/arch/i386/kernel/cpu/umc.c b/arch/i386/kernel/cpu/umc.c
new file mode 100644
index 000000000000..264fcad559d5
--- /dev/null
+++ b/arch/i386/kernel/cpu/umc.c
@@ -0,0 +1,33 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <asm/processor.h>
4#include "cpu.h"
5
6/* UMC chips appear to be only either 386 or 486, so no special init takes place.
7 */
8static void __init init_umc(struct cpuinfo_x86 * c)
9{
10
11}
12
13static struct cpu_dev umc_cpu_dev __initdata = {
14 .c_vendor = "UMC",
15 .c_ident = { "UMC UMC UMC" },
16 .c_models = {
17 { .vendor = X86_VENDOR_UMC, .family = 4, .model_names =
18 {
19 [1] = "U5D",
20 [2] = "U5S",
21 }
22 },
23 },
24 .c_init = init_umc,
25};
26
27int __init umc_init_cpu(void)
28{
29 cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev;
30 return 0;
31}
32
33//early_arch_initcall(umc_init_cpu);