xref: /linux/arch/x86/kernel/cpu/cyrix.c (revision 643d1f7fe3aa12c8bdea6fa5b4ba874ff6dd601d)
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 
462