ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / i386 / kernel / cpu / centaur.c
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
11 static 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  
24 static 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
42 static 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
93 static 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
168 static 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
191 static 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
229 static 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
241 static 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
259 static 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         switch (c->x86_model) {
290                 case 6 ... 8:           /* Cyrix III family */
291                         rdmsr (MSR_VIA_FCR, lo, hi);
292                         lo |= (1<<1 | 1<<7);    /* Report CX8 & enable PGE */
293                         wrmsr (MSR_VIA_FCR, lo, hi);
294
295                         set_bit(X86_FEATURE_CX8, c->x86_capability);
296                         set_bit(X86_FEATURE_3DNOW, c->x86_capability);
297
298                         /* fall through */
299
300                 case 9: /* Nehemiah */
301                 default:
302                         get_model_name(c);
303                         display_cacheinfo(c);
304                         break;
305         }
306 }
307
308 static void __init init_centaur(struct cpuinfo_x86 *c)
309 {
310         enum {
311                 ECX8=1<<1,
312                 EIERRINT=1<<2,
313                 DPM=1<<3,
314                 DMCE=1<<4,
315                 DSTPCLK=1<<5,
316                 ELINEAR=1<<6,
317                 DSMC=1<<7,
318                 DTLOCK=1<<8,
319                 EDCTLB=1<<8,
320                 EMMX=1<<9,
321                 DPDC=1<<11,
322                 EBRPRED=1<<12,
323                 DIC=1<<13,
324                 DDC=1<<14,
325                 DNA=1<<15,
326                 ERETSTK=1<<16,
327                 E2MMX=1<<19,
328                 EAMD3D=1<<20,
329         };
330
331         char *name;
332         u32  fcr_set=0;
333         u32  fcr_clr=0;
334         u32  lo,hi,newlo;
335         u32  aa,bb,cc,dd;
336
337         /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
338            3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
339         clear_bit(0*32+31, c->x86_capability);
340
341         switch (c->x86) {
342
343                 case 5:
344                         switch(c->x86_model) {
345                         case 4:
346                                 name="C6";
347                                 fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
348                                 fcr_clr=DPDC;
349                                 printk(KERN_NOTICE "Disabling bugged TSC.\n");
350                                 clear_bit(X86_FEATURE_TSC, c->x86_capability);
351 #ifdef CONFIG_X86_OOSTORE
352                                 centaur_create_optimal_mcr();
353                                 /* Enable
354                                         write combining on non-stack, non-string
355                                         write combining on string, all types
356                                         weak write ordering 
357                                         
358                                    The C6 original lacks weak read order 
359                                    
360                                    Note 0x120 is write only on Winchip 1 */
361                                    
362                                 wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
363 #endif                          
364                                 break;
365                         case 8:
366                                 switch(c->x86_mask) {
367                                 default:
368                                         name="2";
369                                         break;
370                                 case 7 ... 9:
371                                         name="2A";
372                                         break;
373                                 case 10 ... 15:
374                                         name="2B";
375                                         break;
376                                 }
377                                 fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
378                                 fcr_clr=DPDC;
379 #ifdef CONFIG_X86_OOSTORE
380                                 winchip2_unprotect_mcr();
381                                 winchip2_create_optimal_mcr();
382                                 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
383                                 /* Enable
384                                         write combining on non-stack, non-string
385                                         write combining on string, all types
386                                         weak write ordering 
387                                 */
388                                 lo|=31;                         
389                                 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
390                                 winchip2_protect_mcr();
391 #endif
392                                 break;
393                         case 9:
394                                 name="3";
395                                 fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
396                                 fcr_clr=DPDC;
397 #ifdef CONFIG_X86_OOSTORE
398                                 winchip2_unprotect_mcr();
399                                 winchip2_create_optimal_mcr();
400                                 rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
401                                 /* Enable
402                                         write combining on non-stack, non-string
403                                         write combining on string, all types
404                                         weak write ordering 
405                                 */
406                                 lo|=31;                         
407                                 wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
408                                 winchip2_protect_mcr();
409 #endif
410                                 break;
411                         case 10:
412                                 name="4";
413                                 /* no info on the WC4 yet */
414                                 break;
415                         default:
416                                 name="??";
417                         }
418
419                         rdmsr(MSR_IDT_FCR1, lo, hi);
420                         newlo=(lo|fcr_set) & (~fcr_clr);
421
422                         if (newlo!=lo) {
423                                 printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
424                                 wrmsr(MSR_IDT_FCR1, newlo, hi );
425                         } else {
426                                 printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
427                         }
428                         /* Emulate MTRRs using Centaur's MCR. */
429                         set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability);
430                         /* Report CX8 */
431                         set_bit(X86_FEATURE_CX8, c->x86_capability);
432                         /* Set 3DNow! on Winchip 2 and above. */
433                         if (c->x86_model >=8)
434                                 set_bit(X86_FEATURE_3DNOW, c->x86_capability);
435                         /* See if we can find out some more. */
436                         if ( cpuid_eax(0x80000000) >= 0x80000005 ) {
437                                 /* Yes, we can. */
438                                 cpuid(0x80000005,&aa,&bb,&cc,&dd);
439                                 /* Add L1 data and code cache sizes. */
440                                 c->x86_cache_size = (cc>>24)+(dd>>24);
441                         }
442                         sprintf( c->x86_model_id, "WinChip %s", name );
443                         break;
444
445                 case 6:
446                         init_c3(c);
447                         break;
448         }
449 }
450
451 static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
452 {
453         /* VIA C3 CPUs (670-68F) need further shifting. */
454         if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
455                 size >>= 8;
456
457         /* VIA also screwed up Nehemiah stepping 1, and made
458            it return '65KB' instead of '64KB'
459            - Note, it seems this may only be in engineering samples. */
460         if ((c->x86==6) && (c->x86_model==9) && (c->x86_mask==1) && (size==65))
461                 size -=1;
462
463         return size;
464 }
465
466 static struct cpu_dev centaur_cpu_dev __initdata = {
467         .c_vendor       = "Centaur",
468         .c_ident        = { "CentaurHauls" },
469         .c_init         = init_centaur,
470         .c_size_cache   = centaur_size_cache,
471 };
472
473 int __init centaur_init_cpu(void)
474 {
475         cpu_devs[X86_VENDOR_CENTAUR] = &centaur_cpu_dev;
476         return 0;
477 }
478
479 //early_arch_initcall(centaur_init_cpu);