1 #include <linux/init.h>
2 #include <linux/bitops.h>
3 #include <linux/delay.h>
7 #include <asm/processor.h>
13 * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
15 void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
17 unsigned char ccr2, ccr3;
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 */
26 if (getCx86(CX86_CCR3) == ccr3) { /* no DEVID regs. */
27 ccr2 = getCx86(CX86_CCR2);
28 setCx86(CX86_CCR2, ccr2 ^ 0x04);
29 getCx86(0xc0); /* dummy */
31 if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
33 else { /* Cx486S A step */
34 setCx86(CX86_CCR2, ccr2);
39 setCx86(CX86_CCR3, ccr3); /* restore CCR3 */
41 /* read DIR0 and DIR1 CPU registers */
42 *dir0 = getCx86(CX86_DIR0);
43 *dir1 = getCx86(CX86_DIR1);
45 local_irq_restore(flags);
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
52 * Actually since bugs.h doesn't even reference this perhaps someone should
53 * fix the documentation ???
55 static unsigned char Cx86_dir0_msb __initdata = 0;
57 static char Cx86_model[][9] __initdata = {
58 "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
61 static char Cx486_name[][5] __initdata = {
62 "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
65 static char Cx486S_name[][4] __initdata = {
66 "S", "S2", "Se", "S2e"
68 static char Cx486D_name[][4] __initdata = {
69 "DX", "DX2", "?", "?", "?", "DX4"
71 static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
72 static char cyrix_model_mult1[] __initdata = "12??43";
73 static char cyrix_model_mult2[] __initdata = "12233445";
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.
80 * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
83 extern void calibrate_delay(void) __init;
85 static void __init check_cx686_slop(struct cpuinfo_x86 *c)
89 if (Cx86_dir0_msb == 3) {
90 unsigned char ccr3, ccr5;
92 local_irq_save(flags);
93 ccr3 = getCx86(CX86_CCR3);
94 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
95 ccr5 = getCx86(CX86_CCR5);
97 setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */
98 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
99 local_irq_restore(flags);
101 if (ccr5 & 2) { /* possible wrong calibration done */
102 printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");
104 c->loops_per_jiffy = loops_per_jiffy;
110 static void __init set_cx86_reorder(void)
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 */
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 */
122 setCx86(CX86_CCR3, ccr3);
125 static void __init set_cx86_memwb(void)
129 printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
131 /* CCR2 bit 2: unlock NW bit */
132 setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
133 /* set 'Not Write-through' */
135 __asm__("movl %%cr0,%%eax\n\t"
140 /* CCR2 bit 2: lock NW bit and set WT1 */
141 setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
144 static void __init set_cx86_inc(void)
148 printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
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 */
162 * Configure later MediaGX and/or Geode processor.
165 static void __init geode_configure(void)
169 local_irq_save(flags);
171 /* Suspend on halt power saving and enable #SUSP pin */
172 setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
174 ccr3 = getCx86(CX86_CCR3);
175 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* Enable */
177 ccr4 = getCx86(CX86_CCR4);
178 ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */
180 setCx86(CX86_CCR3, ccr3);
186 local_irq_restore(flags);
190 static void __init init_cyrix(struct cpuinfo_x86 *c)
192 unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
193 char *buf = c->x86_model_id;
194 const char *p = NULL;
196 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
197 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
198 clear_bit(0*32+31, c->x86_capability);
200 /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
201 if ( test_bit(1*32+24, c->x86_capability) ) {
202 clear_bit(1*32+24, c->x86_capability);
203 set_bit(X86_FEATURE_CXMMX, c->x86_capability);
206 do_cyrix_devid(&dir0, &dir1);
210 Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */
211 dir0_lsn = dir0 & 0xf; /* model or clock multiplier */
213 /* common case step number/rev -- exceptions handled below */
214 c->x86_model = (dir1 >> 4) + 1;
215 c->x86_mask = dir1 & 0xf;
217 /* Now cook; the original recipe is by Channing Corn, from Cyrix.
218 * We do the same thing for each generation: we work out
219 * the model, multiplier and stepping. Black magic included,
220 * to make the silicon step/rev numbers match the printed ones.
226 case 0: /* Cx486SLC/DLC/SRx/DRx */
227 p = Cx486_name[dir0_lsn & 7];
230 case 1: /* Cx486S/DX/DX2/DX4 */
231 p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5]
232 : Cx486S_name[dir0_lsn & 3];
236 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
240 case 3: /* 6x86/6x86L */
242 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
243 if (dir1 > 0x21) { /* 686L */
249 /* Emulate MTRRs using Cyrix's ARRs. */
250 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
251 /* 6x86's contain this bug */
255 case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
257 /* It isn't really a PCI quirk directly, but the cure is the
258 same. The MediaGX has deep magic SMM stuff that handles the
259 SB emulation. It thows away the fifo on disable_dma() which
260 is wrong and ruins the audio.
262 Bug2: VSA1 has a wrap bug so that using maximum sized DMA
263 causes bad things. According to NatSemi VSA2 has another
264 bug to do with 'hlt'. I've not seen any boards using VSA2
265 and X doesn't seem to support it either so who cares 8).
266 VSA1 we work around however.
269 printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
270 isa_dma_bridge_buggy = 2;
272 c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
275 * The 5510/5520 companion chips have a funky PIT.
277 if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
278 pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
281 /* GXm supports extended cpuid levels 'ala' AMD */
282 if (c->cpuid_level == 2) {
283 /* Enable cxMMX extensions (GX1 Datasheet 54) */
284 setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
287 if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63)
289 get_model_name(c); /* get CPU marketing name */
293 Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
295 c->x86_model = (dir1 & 0x20) ? 1 : 2;
299 case 5: /* 6x86MX/M II */
302 dir0_msn++; /* M II */
303 /* Enable MMX extensions (App note 108) */
304 setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
308 c->coma_bug = 1; /* 6x86MX, it has the bug. */
310 tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
311 Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
313 if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
315 /* Emulate MTRRs using Cyrix's ARRs. */
316 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
319 case 0xf: /* Cyrix 486 without DEVID registers */
321 case 0xd: /* either a 486SLC or DLC w/o DEVID */
323 p = Cx486_name[(c->hard_math) ? 1 : 0];
326 case 0xe: /* a 486S A step */
333 default: /* unknown (shouldn't happen, we know everyone ;-) */
337 strcpy(buf, Cx86_model[dir0_msn & 7]);
338 if (p) strcat(buf, p);
343 * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
344 * by the fact that they preserve the flags across the division of 5/2.
345 * PII and PPro exhibit this behavior too, but they have cpuid available.
349 * Perform the Cyrix 5/2 test. A Cyrix won't change
350 * the flags, while other 486 chips will.
352 static inline int test_cyrix_52div(void)
356 __asm__ __volatile__(
357 "sahf\n\t" /* clear flags (%eax = 0x0005) */
358 "div %b2\n\t" /* divide 5 by 2 */
359 "lahf" /* store flags into %ah */
364 /* AH is 0x02 on Cyrix after the divide.. */
365 return (unsigned char) (test >> 8) == 0x02;
368 static void cyrix_identify(struct cpuinfo_x86 * c)
370 /* Detect Cyrix with disabled CPUID */
371 if ( c->x86 == 4 && test_cyrix_52div() ) {
372 unsigned char dir0, dir1;
374 strcpy(c->x86_vendor_id, "CyrixInstead");
375 c->x86_vendor = X86_VENDOR_CYRIX;
377 /* Actually enable cpuid on the older cyrix */
379 /* Retrieve CPU revisions */
381 do_cyrix_devid(&dir0, &dir1);
385 /* Check it is an affected model */
387 if (dir0 == 5 || dir0 == 3)
389 unsigned char ccr3, ccr4;
391 printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
392 local_irq_save(flags);
393 ccr3 = getCx86(CX86_CCR3);
394 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
395 ccr4 = getCx86(CX86_CCR4);
396 setCx86(CX86_CCR4, ccr4 | 0x80); /* enable cpuid */
397 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
398 local_irq_restore(flags);
404 static struct cpu_dev cyrix_cpu_dev __initdata = {
406 .c_ident = { "CyrixInstead" },
407 .c_init = init_cyrix,
408 .c_identify = cyrix_identify,
411 int __init cyrix_init_cpu(void)
413 cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
417 //early_arch_initcall(cyrix_init_cpu);
419 static struct cpu_dev nsc_cpu_dev __initdata = {
421 .c_ident = { "Geode by NSC" },
422 .c_init = init_cyrix,
423 .c_identify = generic_identify,
426 int __init nsc_init_cpu(void)
428 cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
432 //early_arch_initcall(nsc_init_cpu);