Subversion Repositories shark

Rev

Rev 582 | Details | Compare with Previous | Last modification | View Log | RSS feed

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