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