]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blob - arch/x86/kernel/cpu/cyrix.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
[lisovros/linux_canprio.git] / arch / x86 / kernel / cpu / cyrix.c
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-cyrix.h>
8 #include <asm/processor-flags.h>
9 #include <asm/timer.h>
10 #include <asm/pci-direct.h>
11 #include <asm/tsc.h>
12
13 #include "cpu.h"
14
15 /*
16  * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
17  */
18 static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
19 {
20         unsigned char ccr2, ccr3;
21         unsigned long flags;
22         
23         /* we test for DEVID by checking whether CCR3 is writable */
24         local_irq_save(flags);
25         ccr3 = getCx86(CX86_CCR3);
26         setCx86(CX86_CCR3, ccr3 ^ 0x80);
27         getCx86(0xc0);   /* dummy to change bus */
28
29         if (getCx86(CX86_CCR3) == ccr3) {       /* no DEVID regs. */
30                 ccr2 = getCx86(CX86_CCR2);
31                 setCx86(CX86_CCR2, ccr2 ^ 0x04);
32                 getCx86(0xc0);  /* dummy */
33
34                 if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
35                         *dir0 = 0xfd;
36                 else {                          /* Cx486S A step */
37                         setCx86(CX86_CCR2, ccr2);
38                         *dir0 = 0xfe;
39                 }
40         }
41         else {
42                 setCx86(CX86_CCR3, ccr3);  /* restore CCR3 */
43
44                 /* read DIR0 and DIR1 CPU registers */
45                 *dir0 = getCx86(CX86_DIR0);
46                 *dir1 = getCx86(CX86_DIR1);
47         }
48         local_irq_restore(flags);
49 }
50
51 /*
52  * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
53  * order to identify the Cyrix CPU model after we're out of setup.c
54  *
55  * Actually since bugs.h doesn't even reference this perhaps someone should
56  * fix the documentation ???
57  */
58 static unsigned char Cx86_dir0_msb __cpuinitdata = 0;
59
60 static char Cx86_model[][9] __cpuinitdata = {
61         "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
62         "M II ", "Unknown"
63 };
64 static char Cx486_name[][5] __cpuinitdata = {
65         "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
66         "SRx2", "DRx2"
67 };
68 static char Cx486S_name[][4] __cpuinitdata = {
69         "S", "S2", "Se", "S2e"
70 };
71 static char Cx486D_name[][4] __cpuinitdata = {
72         "DX", "DX2", "?", "?", "?", "DX4"
73 };
74 static char Cx86_cb[] __cpuinitdata = "?.5x Core/Bus Clock";
75 static char cyrix_model_mult1[] __cpuinitdata = "12??43";
76 static char cyrix_model_mult2[] __cpuinitdata = "12233445";
77
78 /*
79  * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
80  * BIOSes for compatibility with DOS games.  This makes the udelay loop
81  * work correctly, and improves performance.
82  *
83  * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
84  */
85
86 extern void calibrate_delay(void) __init;
87
88 static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
89 {
90         unsigned long flags;
91         
92         if (Cx86_dir0_msb == 3) {
93                 unsigned char ccr3, ccr5;
94
95                 local_irq_save(flags);
96                 ccr3 = getCx86(CX86_CCR3);
97                 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
98                 ccr5 = getCx86(CX86_CCR5);
99                 if (ccr5 & 2)
100                         setCx86(CX86_CCR5, ccr5 & 0xfd);  /* reset SLOP */
101                 setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
102                 local_irq_restore(flags);
103
104                 if (ccr5 & 2) { /* possible wrong calibration done */
105                         printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");
106                         calibrate_delay();
107                         c->loops_per_jiffy = loops_per_jiffy;
108                 }
109         }
110 }
111
112
113 static void __cpuinit set_cx86_reorder(void)
114 {
115         u8 ccr3;
116
117         printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n");
118         ccr3 = getCx86(CX86_CCR3);
119         setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
120
121         /* Load/Store Serialize to mem access disable (=reorder it) */
122         setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80);
123         /* set load/store serialize from 1GB to 4GB */
124         ccr3 |= 0xe0;
125         setCx86(CX86_CCR3, ccr3);
126 }
127
128 static void __cpuinit set_cx86_memwb(void)
129 {
130         printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
131
132         /* CCR2 bit 2: unlock NW bit */
133         setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
134         /* set 'Not Write-through' */
135         write_cr0(read_cr0() | X86_CR0_NW);
136         /* CCR2 bit 2: lock NW bit and set WT1 */
137         setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
138 }
139
140 static void __cpuinit set_cx86_inc(void)
141 {
142         unsigned char ccr3;
143
144         printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
145
146         ccr3 = getCx86(CX86_CCR3);
147         setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
148         /* PCR1 -- Performance Control */
149         /* Incrementor on, whatever that is */
150         setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
151         /* PCR0 -- Performance Control */
152         /* Incrementor Margin 10 */
153         setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); 
154         setCx86(CX86_CCR3, ccr3);       /* disable MAPEN */
155 }
156
157 /*
158  *      Configure later MediaGX and/or Geode processor.
159  */
160
161 static void __cpuinit geode_configure(void)
162 {
163         unsigned long flags;
164         u8 ccr3;
165         local_irq_save(flags);
166
167         /* Suspend on halt power saving and enable #SUSP pin */
168         setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
169
170         ccr3 = getCx86(CX86_CCR3);
171         setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN */
172         
173
174         /* FPU fast, DTE cache, Mem bypass */
175         setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38);
176         setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
177         
178         set_cx86_memwb();
179         set_cx86_reorder();     
180         set_cx86_inc();
181         
182         local_irq_restore(flags);
183 }
184
185
186 static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
187 {
188         unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
189         char *buf = c->x86_model_id;
190         const char *p = NULL;
191
192         /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
193            3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
194         clear_bit(0*32+31, c->x86_capability);
195
196         /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
197         if ( test_bit(1*32+24, c->x86_capability) ) {
198                 clear_bit(1*32+24, c->x86_capability);
199                 set_bit(X86_FEATURE_CXMMX, c->x86_capability);
200         }
201
202         do_cyrix_devid(&dir0, &dir1);
203
204         check_cx686_slop(c);
205
206         Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family"   */
207         dir0_lsn = dir0 & 0xf;                /* model or clock multiplier */
208
209         /* common case step number/rev -- exceptions handled below */
210         c->x86_model = (dir1 >> 4) + 1;
211         c->x86_mask = dir1 & 0xf;
212
213         /* Now cook; the original recipe is by Channing Corn, from Cyrix.
214          * We do the same thing for each generation: we work out
215          * the model, multiplier and stepping.  Black magic included,
216          * to make the silicon step/rev numbers match the printed ones.
217          */
218          
219         switch (dir0_msn) {
220                 unsigned char tmp;
221
222         case 0: /* Cx486SLC/DLC/SRx/DRx */
223                 p = Cx486_name[dir0_lsn & 7];
224                 break;
225
226         case 1: /* Cx486S/DX/DX2/DX4 */
227                 p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5]
228                         : Cx486S_name[dir0_lsn & 3];
229                 break;
230
231         case 2: /* 5x86 */
232                 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
233                 p = Cx86_cb+2;
234                 break;
235
236         case 3: /* 6x86/6x86L */
237                 Cx86_cb[1] = ' ';
238                 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
239                 if (dir1 > 0x21) { /* 686L */
240                         Cx86_cb[0] = 'L';
241                         p = Cx86_cb;
242                         (c->x86_model)++;
243                 } else             /* 686 */
244                         p = Cx86_cb+1;
245                 /* Emulate MTRRs using Cyrix's ARRs. */
246                 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
247                 /* 6x86's contain this bug */
248                 c->coma_bug = 1;
249                 break;
250
251         case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
252 #ifdef CONFIG_PCI
253         {
254                 u32 vendor, device;
255                 /* It isn't really a PCI quirk directly, but the cure is the
256                    same. The MediaGX has deep magic SMM stuff that handles the
257                    SB emulation. It throws away the fifo on disable_dma() which
258                    is wrong and ruins the audio. 
259
260                    Bug2: VSA1 has a wrap bug so that using maximum sized DMA 
261                    causes bad things. According to NatSemi VSA2 has another
262                    bug to do with 'hlt'. I've not seen any boards using VSA2
263                    and X doesn't seem to support it either so who cares 8).
264                    VSA1 we work around however.
265                 */
266
267                 printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
268                 isa_dma_bridge_buggy = 2;
269
270                 /* We do this before the PCI layer is running. However we
271                    are safe here as we know the bridge must be a Cyrix
272                    companion and must be present */
273                 vendor = read_pci_config_16(0, 0, 0x12, PCI_VENDOR_ID);
274                 device = read_pci_config_16(0, 0, 0x12, PCI_DEVICE_ID);
275
276                 /*
277                  *  The 5510/5520 companion chips have a funky PIT.
278                  */  
279                 if (vendor == PCI_VENDOR_ID_CYRIX &&
280          (device == PCI_DEVICE_ID_CYRIX_5510 || device == PCI_DEVICE_ID_CYRIX_5520))
281                         mark_tsc_unstable("cyrix 5510/5520 detected");
282         }
283 #endif
284                 c->x86_cache_size=16;   /* Yep 16K integrated cache thats it */
285
286                 /* GXm supports extended cpuid levels 'ala' AMD */
287                 if (c->cpuid_level == 2) {
288                         /* Enable cxMMX extensions (GX1 Datasheet 54) */
289                         setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
290                         
291                         /*
292                          * GXm : 0x30 ... 0x5f GXm  datasheet 51
293                          * GXlv: 0x6x          GXlv datasheet 54
294                          *  ?  : 0x7x
295                          * GX1 : 0x8x          GX1  datasheet 56
296                          */
297                         if((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <=dir1 && dir1 <= 0x8f))
298                                 geode_configure();
299                         get_model_name(c);  /* get CPU marketing name */
300                         return;
301                 }
302                 else {  /* MediaGX */
303                         Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
304                         p = Cx86_cb+2;
305                         c->x86_model = (dir1 & 0x20) ? 1 : 2;
306                 }
307                 break;
308
309         case 5: /* 6x86MX/M II */
310                 if (dir1 > 7)
311                 {
312                         dir0_msn++;  /* M II */
313                         /* Enable MMX extensions (App note 108) */
314                         setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
315                 }
316                 else
317                 {
318                         c->coma_bug = 1;      /* 6x86MX, it has the bug. */
319                 }
320                 tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
321                 Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
322                 p = Cx86_cb+tmp;
323                 if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
324                         (c->x86_model)++;
325                 /* Emulate MTRRs using Cyrix's ARRs. */
326                 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
327                 break;
328
329         case 0xf:  /* Cyrix 486 without DEVID registers */
330                 switch (dir0_lsn) {
331                 case 0xd:  /* either a 486SLC or DLC w/o DEVID */
332                         dir0_msn = 0;
333                         p = Cx486_name[(c->hard_math) ? 1 : 0];
334                         break;
335
336                 case 0xe:  /* a 486S A step */
337                         dir0_msn = 0;
338                         p = Cx486S_name[0];
339                         break;
340                 }
341                 break;
342
343         default:  /* unknown (shouldn't happen, we know everyone ;-) */
344                 dir0_msn = 7;
345                 break;
346         }
347         strcpy(buf, Cx86_model[dir0_msn & 7]);
348         if (p) strcat(buf, p);
349         return;
350 }
351
352 /*
353  * Handle National Semiconductor branded processors
354  */
355 static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
356 {
357         /* There may be GX1 processors in the wild that are branded
358          * NSC and not Cyrix.
359          *
360          * This function only handles the GX processor, and kicks every
361          * thing else to the Cyrix init function above - that should
362          * cover any processors that might have been branded differently
363          * after NSC acquired Cyrix.
364          *
365          * If this breaks your GX1 horribly, please e-mail
366          * info-linux@ldcmail.amd.com to tell us.
367          */
368
369         /* Handle the GX (Formally known as the GX2) */
370
371         if (c->x86 == 5 && c->x86_model == 5)
372                 display_cacheinfo(c);
373         else
374                 init_cyrix(c);
375 }
376
377 /*
378  * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
379  * by the fact that they preserve the flags across the division of 5/2.
380  * PII and PPro exhibit this behavior too, but they have cpuid available.
381  */
382  
383 /*
384  * Perform the Cyrix 5/2 test. A Cyrix won't change
385  * the flags, while other 486 chips will.
386  */
387 static inline int test_cyrix_52div(void)
388 {
389         unsigned int test;
390
391         __asm__ __volatile__(
392              "sahf\n\t"         /* clear flags (%eax = 0x0005) */
393              "div %b2\n\t"      /* divide 5 by 2 */
394              "lahf"             /* store flags into %ah */
395              : "=a" (test)
396              : "0" (5), "q" (2)
397              : "cc");
398
399         /* AH is 0x02 on Cyrix after the divide.. */
400         return (unsigned char) (test >> 8) == 0x02;
401 }
402
403 static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
404 {
405         /* Detect Cyrix with disabled CPUID */
406         if ( c->x86 == 4 && test_cyrix_52div() ) {
407                 unsigned char dir0, dir1;
408                 
409                 strcpy(c->x86_vendor_id, "CyrixInstead");
410                 c->x86_vendor = X86_VENDOR_CYRIX;
411                 
412                 /* Actually enable cpuid on the older cyrix */
413             
414                 /* Retrieve CPU revisions */
415                 
416                 do_cyrix_devid(&dir0, &dir1);
417
418                 dir0>>=4;               
419                 
420                 /* Check it is an affected model */
421                 
422                 if (dir0 == 5 || dir0 == 3)
423                 {
424                         unsigned char ccr3;
425                         unsigned long flags;
426                         printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
427                         local_irq_save(flags);
428                         ccr3 = getCx86(CX86_CCR3);
429                         setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);       /* enable MAPEN  */
430                         setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80);  /* enable cpuid  */
431                         setCx86(CX86_CCR3, ccr3);                       /* disable MAPEN */
432                         local_irq_restore(flags);
433                 }
434         }
435 }
436
437 static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
438         .c_vendor       = "Cyrix",
439         .c_ident        = { "CyrixInstead" },
440         .c_init         = init_cyrix,
441         .c_identify     = cyrix_identify,
442 };
443
444 int __init cyrix_init_cpu(void)
445 {
446         cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
447         return 0;
448 }
449
450 static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
451         .c_vendor       = "NSC",
452         .c_ident        = { "Geode by NSC" },
453         .c_init         = init_nsc,
454 };
455
456 int __init nsc_init_cpu(void)
457 {
458         cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
459         return 0;
460 }
461