ia64/xen-unstable

view xen/arch/x86/cpu/cyrix.c @ 19835:edfdeb150f27

Fix buildsystem to detect udev > version 124

udev removed the udevinfo symlink from versions higher than 123 and
xen's build-system could not detect if udev is in place and has the
required version.

Signed-off-by: Marc-A. Dahlhaus <mad@wol.de>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 25 13:02:37 2009 +0100 (2009-06-25)
parents 9488d3166553
children
line source
1 #include <xen/config.h>
2 #include <xen/init.h>
3 #include <xen/irq.h>
4 #include <xen/bitops.h>
5 #include <xen/delay.h>
6 #include <asm/io.h>
7 #include <asm/processor.h>
9 #include "cpu.h"
11 /*
12 * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
13 */
14 void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
15 {
16 unsigned char ccr2, ccr3;
17 unsigned long flags;
19 /* we test for DEVID by checking whether CCR3 is writable */
20 local_irq_save(flags);
21 ccr3 = getCx86(CX86_CCR3);
22 setCx86(CX86_CCR3, ccr3 ^ 0x80);
23 getCx86(0xc0); /* dummy to change bus */
25 if (getCx86(CX86_CCR3) == ccr3) { /* no DEVID regs. */
26 ccr2 = getCx86(CX86_CCR2);
27 setCx86(CX86_CCR2, ccr2 ^ 0x04);
28 getCx86(0xc0); /* dummy */
30 if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
31 *dir0 = 0xfd;
32 else { /* Cx486S A step */
33 setCx86(CX86_CCR2, ccr2);
34 *dir0 = 0xfe;
35 }
36 }
37 else {
38 setCx86(CX86_CCR3, ccr3); /* restore CCR3 */
40 /* read DIR0 and DIR1 CPU registers */
41 *dir0 = getCx86(CX86_DIR0);
42 *dir1 = getCx86(CX86_DIR1);
43 }
44 local_irq_restore(flags);
45 }
47 /*
48 * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
49 * order to identify the Cyrix CPU model after we're out of setup.c
50 *
51 * Actually since bugs.h doesn't even reference this perhaps someone should
52 * fix the documentation ???
53 */
54 static unsigned char Cx86_dir0_msb __initdata = 0;
56 static char Cx86_model[][9] __initdata = {
57 "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
58 "M II ", "Unknown"
59 };
60 static char Cx486_name[][5] __initdata = {
61 "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
62 "SRx2", "DRx2"
63 };
64 static char Cx486S_name[][4] __initdata = {
65 "S", "S2", "Se", "S2e"
66 };
67 static char Cx486D_name[][4] __initdata = {
68 "DX", "DX2", "?", "?", "?", "DX4"
69 };
70 static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
71 static char cyrix_model_mult1[] __initdata = "12??43";
72 static char cyrix_model_mult2[] __initdata = "12233445";
74 /*
75 * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
76 * BIOSes for compatibility with DOS games. This makes the udelay loop
77 * work correctly, and improves performance.
78 *
79 * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
80 */
82 static void __init check_cx686_slop(struct cpuinfo_x86 *c)
83 {
84 unsigned long flags;
86 if (Cx86_dir0_msb == 3) {
87 unsigned char ccr3, ccr5;
89 local_irq_save(flags);
90 ccr3 = getCx86(CX86_CCR3);
91 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
92 ccr5 = getCx86(CX86_CCR5);
93 if (ccr5 & 2)
94 setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */
95 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
96 local_irq_restore(flags);
97 }
98 }
101 static void __init set_cx86_reorder(void)
102 {
103 u8 ccr3;
105 printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n");
106 ccr3 = getCx86(CX86_CCR3);
107 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
109 /* Load/Store Serialize to mem access disable (=reorder it)  */
110 setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80);
111 /* set load/store serialize from 1GB to 4GB */
112 ccr3 |= 0xe0;
113 setCx86(CX86_CCR3, ccr3);
114 }
116 static void __init set_cx86_memwb(void)
117 {
118 u32 cr0;
120 printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
122 /* CCR2 bit 2: unlock NW bit */
123 setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
124 /* set 'Not Write-through' */
125 cr0 = 0x20000000;
126 __asm__("movl %%cr0,%%eax\n\t"
127 "orl %0,%%eax\n\t"
128 "movl %%eax,%%cr0\n"
129 : : "r" (cr0)
130 :"ax");
131 /* CCR2 bit 2: lock NW bit and set WT1 */
132 setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
133 }
135 static void __init set_cx86_inc(void)
136 {
137 unsigned char ccr3;
139 printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
141 ccr3 = getCx86(CX86_CCR3);
142 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
143 /* PCR1 -- Performance Control */
144 /* Incrementor on, whatever that is */
145 setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
146 /* PCR0 -- Performance Control */
147 /* Incrementor Margin 10 */
148 setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
149 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
150 }
152 /*
153 * Configure later MediaGX and/or Geode processor.
154 */
156 static void __init geode_configure(void)
157 {
158 unsigned long flags;
159 u8 ccr3, ccr4;
160 local_irq_save(flags);
162 /* Suspend on halt power saving and enable #SUSP pin */
163 setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
165 ccr3 = getCx86(CX86_CCR3);
166 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* Enable */
168 ccr4 = getCx86(CX86_CCR4);
169 ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */
171 setCx86(CX86_CCR3, ccr3);
173 set_cx86_memwb();
174 set_cx86_reorder();
175 set_cx86_inc();
177 local_irq_restore(flags);
178 }
181 static void __init init_cyrix(struct cpuinfo_x86 *c)
182 {
183 unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
184 const char *p = NULL;
186 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
187 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
188 clear_bit(0*32+31, c->x86_capability);
190 /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
191 if ( test_bit(1*32+24, c->x86_capability) ) {
192 clear_bit(1*32+24, c->x86_capability);
193 set_bit(X86_FEATURE_CXMMX, c->x86_capability);
194 }
196 do_cyrix_devid(&dir0, &dir1);
198 check_cx686_slop(c);
200 Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */
201 dir0_lsn = dir0 & 0xf; /* model or clock multiplier */
203 /* common case step number/rev -- exceptions handled below */
204 c->x86_model = (dir1 >> 4) + 1;
205 c->x86_mask = dir1 & 0xf;
207 /* Now cook; the original recipe is by Channing Corn, from Cyrix.
208 * We do the same thing for each generation: we work out
209 * the model, multiplier and stepping. Black magic included,
210 * to make the silicon step/rev numbers match the printed ones.
211 */
213 switch (dir0_msn) {
214 unsigned char tmp;
216 case 0: /* Cx486SLC/DLC/SRx/DRx */
217 p = Cx486_name[dir0_lsn & 7];
218 break;
220 case 1: /* Cx486S/DX/DX2/DX4 */
221 p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5]
222 : Cx486S_name[dir0_lsn & 3];
223 break;
225 case 2: /* 5x86 */
226 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
227 p = Cx86_cb+2;
228 break;
230 case 3: /* 6x86/6x86L */
231 Cx86_cb[1] = ' ';
232 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
233 if (dir1 > 0x21) { /* 686L */
234 Cx86_cb[0] = 'L';
235 p = Cx86_cb;
236 (c->x86_model)++;
237 } else /* 686 */
238 p = Cx86_cb+1;
239 /* Emulate MTRRs using Cyrix's ARRs. */
240 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
241 /* 6x86's contain this bug */
242 /*c->coma_bug = 1;*/
243 break;
245 case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
246 c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
248 /* GXm supports extended cpuid levels 'ala' AMD */
249 if (c->cpuid_level == 2) {
250 /* Enable cxMMX extensions (GX1 Datasheet 54) */
251 setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
253 /* GXlv/GXm/GX1 */
254 if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63)
255 geode_configure();
256 get_model_name(c); /* get CPU marketing name */
257 return;
258 }
259 else { /* MediaGX */
260 Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
261 p = Cx86_cb+2;
262 c->x86_model = (dir1 & 0x20) ? 1 : 2;
263 }
264 break;
266 case 5: /* 6x86MX/M II */
267 if (dir1 > 7)
268 {
269 dir0_msn++; /* M II */
270 /* Enable MMX extensions (App note 108) */
271 setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
272 }
273 else
274 {
275 /*c->coma_bug = 1;*/ /* 6x86MX, it has the bug. */
276 }
277 tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
278 Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
279 p = Cx86_cb+tmp;
280 if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
281 (c->x86_model)++;
282 /* Emulate MTRRs using Cyrix's ARRs. */
283 set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
284 break;
286 case 0xf: /* Cyrix 486 without DEVID registers */
287 switch (dir0_lsn) {
288 case 0xd: /* either a 486SLC or DLC w/o DEVID */
289 dir0_msn = 0;
290 p = Cx486_name[/*(c->hard_math) ? 1 : 0*/1];
291 break;
293 case 0xe: /* a 486S A step */
294 dir0_msn = 0;
295 p = Cx486S_name[0];
296 break;
297 }
298 break;
300 default: /* unknown (shouldn't happen, we know everyone ;-) */
301 dir0_msn = 7;
302 break;
303 }
304 safe_strcpy(c->x86_model_id, Cx86_model[dir0_msn & 7]);
305 if (p) safe_strcat(c->x86_model_id, p);
306 return;
307 }
309 /*
310 * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
311 * by the fact that they preserve the flags across the division of 5/2.
312 * PII and PPro exhibit this behavior too, but they have cpuid available.
313 */
315 /*
316 * Perform the Cyrix 5/2 test. A Cyrix won't change
317 * the flags, while other 486 chips will.
318 */
319 static inline int test_cyrix_52div(void)
320 {
321 unsigned int test;
323 __asm__ __volatile__(
324 "sahf\n\t" /* clear flags (%eax = 0x0005) */
325 "div %b2\n\t" /* divide 5 by 2 */
326 "lahf" /* store flags into %ah */
327 : "=a" (test)
328 : "0" (5), "q" (2)
329 : "cc");
331 /* AH is 0x02 on Cyrix after the divide.. */
332 return (unsigned char) (test >> 8) == 0x02;
333 }
335 static void cyrix_identify(struct cpuinfo_x86 * c)
336 {
337 /* Detect Cyrix with disabled CPUID */
338 if ( c->x86 == 4 && test_cyrix_52div() ) {
339 unsigned char dir0, dir1;
341 safe_strcpy(c->x86_vendor_id, "CyrixInstead");
342 c->x86_vendor = X86_VENDOR_CYRIX;
344 /* Actually enable cpuid on the older cyrix */
346 /* Retrieve CPU revisions */
348 do_cyrix_devid(&dir0, &dir1);
350 dir0>>=4;
352 /* Check it is an affected model */
354 if (dir0 == 5 || dir0 == 3)
355 {
356 unsigned char ccr3, ccr4;
357 unsigned long flags;
358 printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
359 local_irq_save(flags);
360 ccr3 = getCx86(CX86_CCR3);
361 setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
362 ccr4 = getCx86(CX86_CCR4);
363 setCx86(CX86_CCR4, ccr4 | 0x80); /* enable cpuid */
364 setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
365 local_irq_restore(flags);
366 }
367 }
368 generic_identify(c);
369 }
371 static struct cpu_dev cyrix_cpu_dev __initdata = {
372 .c_vendor = "Cyrix",
373 .c_ident = { "CyrixInstead" },
374 .c_init = init_cyrix,
375 .c_identify = cyrix_identify,
376 };
378 int __init cyrix_init_cpu(void)
379 {
380 cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
381 return 0;
382 }
384 //early_arch_initcall(cyrix_init_cpu);
386 static struct cpu_dev nsc_cpu_dev __initdata = {
387 .c_vendor = "NSC",
388 .c_ident = { "Geode by NSC" },
389 .c_init = init_cyrix,
390 .c_identify = generic_identify,
391 };
393 int __init nsc_init_cpu(void)
394 {
395 cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
396 return 0;
397 }
399 //early_arch_initcall(nsc_init_cpu);