linux-old/arch/mips64/kernel/cpu-probe.c
<<
>>
Prefs
   1/*
   2 *      arch/mips64/kernel/cpu-probe.c
   3 *
   4 *      Processor capabilities determination functions.
   5 *
   6 *      Copyright (C) xxxx  the Anonymous
   7 *      Copyright (C) 2003  Maciej W. Rozycki
   8 *
   9 *      This program is free software; you can redistribute it and/or
  10 *      modify it under the terms of the GNU General Public License
  11 *      as published by the Free Software Foundation; either version
  12 *      2 of the License, or (at your option) any later version.
  13 */
  14
  15#include <linux/init.h>
  16#include <linux/kernel.h>
  17#include <linux/ptrace.h>
  18#include <linux/stddef.h>
  19
  20#include <asm/bugs.h>
  21#include <asm/cpu.h>
  22#include <asm/fpu.h>
  23#include <asm/mipsregs.h>
  24#include <asm/system.h>
  25
  26/*
  27 * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
  28 * the implementation of the "wait" feature differs between CPU families. This
  29 * points to the function that implements CPU specific wait.
  30 * The wait instruction stops the pipeline and reduces the power consumption of
  31 * the CPU very much.
  32 */
  33void (*cpu_wait)(void) = NULL;
  34
  35static void r3081_wait(void)
  36{
  37        unsigned long cfg = read_c0_conf();
  38        write_c0_conf(cfg | R30XX_CONF_HALT);
  39}
  40
  41static void r39xx_wait(void)
  42{
  43        unsigned long cfg = read_c0_conf();
  44        write_c0_conf(cfg | TX39_CONF_HALT);
  45}
  46
  47static void r4k_wait(void)
  48{
  49        __asm__(".set\tmips3\n\t"
  50                "wait\n\t"
  51                ".set\tmips0");
  52}
  53
  54void au1k_wait(void)
  55{
  56#ifdef CONFIG_PM
  57        /* using the wait instruction makes CP0 counter unusable */
  58        __asm__(".set\tmips3\n\t"
  59                "wait\n\t"
  60                "nop\n\t"
  61                "nop\n\t"
  62                "nop\n\t"
  63                "nop\n\t"
  64                ".set\tmips0");
  65#else
  66        __asm__("nop\n\t"
  67                "nop");
  68#endif
  69}
  70
  71static inline void check_wait(void)
  72{
  73        struct cpuinfo_mips *c = &current_cpu_data;
  74
  75        printk("Checking for 'wait' instruction... ");
  76        switch (c->cputype) {
  77        case CPU_R3081:
  78        case CPU_R3081E:
  79                cpu_wait = r3081_wait;
  80                printk(" available.\n");
  81                break;
  82        case CPU_TX3927:
  83                cpu_wait = r39xx_wait;
  84                printk(" available.\n");
  85                break;
  86        case CPU_R4200:
  87/*      case CPU_R4300: */
  88        case CPU_R4600:
  89        case CPU_R4640:
  90        case CPU_R4650:
  91        case CPU_R4700:
  92        case CPU_R5000:
  93        case CPU_NEVADA:
  94        case CPU_RM7000:
  95        case CPU_TX49XX:
  96        case CPU_4KC:
  97        case CPU_4KEC:
  98        case CPU_4KSC:
  99        case CPU_5KC:
 100/*      case CPU_20KC:*/
 101        case CPU_24K:
 102        case CPU_25KF:
 103                cpu_wait = r4k_wait;
 104                printk(" available.\n");
 105                break;
 106        case CPU_AU1000:
 107        case CPU_AU1100:
 108        case CPU_AU1500:
 109                cpu_wait = au1k_wait;
 110                printk(" available.\n");
 111                break;
 112        default:
 113                printk(" unavailable.\n");
 114                break;
 115        }
 116}
 117
 118static inline void align_mod(const int align, const int mod)
 119{
 120        asm volatile(
 121                ".set   push\n\t"
 122                ".set   noreorder\n\t"
 123                ".balign %0\n\t"
 124                ".rept  %1\n\t"
 125                "nop\n\t"
 126                ".endr\n\t"
 127                ".set   pop"
 128                :
 129                : "n" (align), "n" (mod));
 130}
 131
 132static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
 133                                     const int align, const int mod)
 134{
 135        unsigned long flags;
 136        int m1, m2;
 137        long p, s, lv1, lv2, lw;
 138
 139        /*
 140         * We want the multiply and the shift to be isolated from the
 141         * rest of the code to disable gcc optimizations.  Hence the
 142         * asm statements that execute nothing, but make gcc not know
 143         * what the values of m1, m2 and s are and what lv2 and p are
 144         * used for.
 145         */
 146
 147        local_irq_save(flags);
 148        /*
 149         * The following code leads to a wrong result of the first
 150         * dsll32 when executed on R4000 rev. 2.2 or 3.0 (PRId
 151         * 00000422 or 00000430, respectively).
 152         *
 153         * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and
 154         * 3.0" by MIPS Technologies, Inc., errata #16 and #28 for
 155         * details.  I got no permission to duplicate them here,
 156         * sigh... --macro
 157         */
 158        asm volatile(
 159                ""
 160                : "=r" (m1), "=r" (m2), "=r" (s)
 161                : "0" (5), "1" (8), "2" (5));
 162        align_mod(align, mod);
 163        /*
 164         * The trailing nop is needed to fullfill the two-instruction
 165         * requirement between reading hi/lo and staring a mult/div.
 166         * Leaving it out may cause gas insert a nop itself breaking
 167         * the desired alignment of the next chunk.
 168         */
 169        asm volatile(
 170                ".set   push\n\t"
 171                ".set   noat\n\t"
 172                ".set   noreorder\n\t"
 173                ".set   nomacro\n\t"
 174                "mult   %2, %3\n\t"
 175                "dsll32 %0, %4, %5\n\t"
 176                "mflo   $0\n\t"
 177                "dsll32 %1, %4, %5\n\t"
 178                "nop\n\t"
 179                ".set   pop"
 180                : "=&r" (lv1), "=r" (lw)
 181                : "r" (m1), "r" (m2), "r" (s), "I" (0)
 182                : "hi", "lo", "accum");
 183        /* We have to use single integers for m1 and m2 and a double
 184         * one for p to be sure the mulsidi3 gcc's RTL multiplication
 185         * instruction has the workaround applied.  Older versions of
 186         * gcc have correct umulsi3 and mulsi3, but other
 187         * multiplication variants lack the workaround.
 188         */
 189        asm volatile(
 190                ""
 191                : "=r" (m1), "=r" (m2), "=r" (s)
 192                : "0" (m1), "1" (m2), "2" (s));
 193        align_mod(align, mod);
 194        p = m1 * m2;
 195        lv2 = s << 32;
 196        asm volatile(
 197                ""
 198                : "=r" (lv2)
 199                : "0" (lv2), "r" (p));
 200        local_irq_restore(flags);
 201
 202        *v1 = lv1;
 203        *v2 = lv2;
 204        *w = lw;
 205}
 206
 207static inline void check_mult_sh(void)
 208{
 209        long v1[8], v2[8], w[8];
 210        int bug, fix, i;
 211
 212        printk("Checking for the multiply/shift bug... ");
 213
 214        /*
 215         * Testing discovered false negatives for certain code offsets
 216         * into cache lines.  Hence we test all possible offsets for
 217         * the worst assumption of an R4000 I-cache line width of 32
 218         * bytes.
 219         *
 220         * We can't use a loop as alignment directives need to be
 221         * immediates.
 222         */
 223        mult_sh_align_mod(&v1[0], &v2[0], &w[0], 32, 0);
 224        mult_sh_align_mod(&v1[1], &v2[1], &w[1], 32, 1);
 225        mult_sh_align_mod(&v1[2], &v2[2], &w[2], 32, 2);
 226        mult_sh_align_mod(&v1[3], &v2[3], &w[3], 32, 3);
 227        mult_sh_align_mod(&v1[4], &v2[4], &w[4], 32, 4);
 228        mult_sh_align_mod(&v1[5], &v2[5], &w[5], 32, 5);
 229        mult_sh_align_mod(&v1[6], &v2[6], &w[6], 32, 6);
 230        mult_sh_align_mod(&v1[7], &v2[7], &w[7], 32, 7);
 231
 232        bug = 0;
 233        for (i = 0; i < 8; i++)
 234                if (v1[i] != w[i])
 235                        bug = 1;
 236                
 237        if (bug == 0) {
 238                printk("no.\n");
 239                return;
 240        }
 241
 242        printk("yes, workaround... ");
 243
 244        fix = 1;
 245        for (i = 0; i < 8; i++)
 246                if (v2[i] != w[i])
 247                        fix = 0;
 248                
 249        if (fix == 1) {
 250                printk("yes.\n");
 251                return;
 252        }
 253
 254        printk("no.\n");
 255        panic("Reliable operation impossible!\n"
 256#ifndef CONFIG_CPU_R4000
 257              "Configure for R4000 to enable the workaround."
 258#else
 259              "Please report to <linux-mips@linux-mips.org>."
 260#endif
 261              );
 262}
 263
 264static volatile int daddi_ov __initdata = 0;
 265
 266asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
 267{
 268        daddi_ov = 1;
 269        regs->cp0_epc += 4;
 270}
 271
 272static inline void check_daddi(void)
 273{
 274        extern asmlinkage void handle_daddi_ov(void);
 275        unsigned long flags;
 276        void *handler;
 277        long v;
 278
 279        printk("Checking for the daddi bug... ");
 280
 281        local_irq_save(flags);
 282        handler = set_except_vector(12, handle_daddi_ov);
 283        /*
 284         * The following code fails to trigger an overflow exception
 285         * when executed on R4000 rev. 2.2 or 3.0 (PRId 00000422 or
 286         * 00000430, respectively).
 287         *
 288         * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and
 289         * 3.0" by MIPS Technologies, Inc., erratum #23 for details.
 290         * I got no permission to duplicate it here, sigh... --macro
 291         */
 292        asm volatile(
 293                ".set   push\n\t"
 294                ".set   noat\n\t"
 295                ".set   noreorder\n\t"
 296                ".set   nomacro\n\t"
 297#ifdef HAVE_AS_SET_DADDI
 298                ".set   daddi\n\t"
 299#endif
 300                "daddi  %0, %1, %2\n\t"
 301                ".set   pop"
 302                : "=r" (v)
 303                : "r" (0x7fffffffffffedcd), "I" (0x1234));
 304        set_except_vector(12, handler);
 305        local_irq_restore(flags);
 306
 307        if (daddi_ov) {
 308                printk("no.\n");
 309                return;
 310        }
 311
 312        printk("yes, workaround... ");
 313
 314        local_irq_save(flags);
 315        handler = set_except_vector(12, handle_daddi_ov);
 316        asm volatile(
 317                "daddi  %0, %1, %2"
 318                : "=r" (v)
 319                : "r" (0x7fffffffffffedcd), "I" (0x1234));
 320        set_except_vector(12, handler);
 321        local_irq_restore(flags);
 322
 323        if (daddi_ov) {
 324                printk("yes.\n");
 325                return;
 326        }
 327
 328        printk("no.\n");
 329        panic("Reliable operation impossible!\n"
 330#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
 331              "Configure for R4000 or R4400 to enable the workaround."
 332#else
 333              "Please report to <linux-mips@linux-mips.org>."
 334#endif
 335              );
 336}
 337
 338static inline void check_daddiu(void)
 339{
 340        long v, w;
 341
 342        printk("Checking for the daddiu bug... ");
 343
 344        /*
 345         * The following code leads to a wrong result of daddiu when
 346         * executed on R4400 rev. 1.0 (PRId 00000440).
 347         *
 348         * See "MIPS R4400PC/SC Errata, Processor Revision 1.0" by
 349         * MIPS Technologies, Inc., erratum #7 for details.
 350         *
 351         * According to "MIPS R4000PC/SC Errata, Processor Revision
 352         * 2.2 and 3.0" by MIPS Technologies, Inc., erratum #41 this
 353         * problem affects R4000 rev. 2.2 and 3.0 (PRId 00000422 and
 354         * 00000430, respectively), too.  Testing failed to trigger it
 355         * so far.
 356         *
 357         * I got no permission to duplicate the errata here, sigh...
 358         * --macro
 359         */
 360        asm volatile(
 361                ".set   push\n\t"
 362                ".set   noat\n\t"
 363                ".set   noreorder\n\t"
 364                ".set   nomacro\n\t"
 365#ifdef HAVE_AS_SET_DADDI
 366                ".set   daddi\n\t"
 367#endif
 368                "daddiu %0, %2, %3\n\t"
 369                "addiu  %1, $0, %3\n\t"
 370                "daddu  %1, %2\n\t"
 371                ".set   pop"
 372                : "=&r" (v), "=&r" (w)
 373                : "r" (0x7fffffffffffedcd), "I" (0x1234));
 374
 375        if (v == w) {
 376                printk("no.\n");
 377                return;
 378        }
 379
 380        printk("yes, workaround... ");
 381
 382        asm volatile(
 383                "daddiu %0, %2, %3\n\t"
 384                "addiu  %1, $0, %3\n\t"
 385                "daddu  %1, %2"
 386                : "=&r" (v), "=&r" (w)
 387                : "r" (0x7fffffffffffedcd), "I" (0x1234));
 388
 389        if (v == w) {
 390                printk("yes.\n");
 391                return;
 392        }
 393
 394        printk("no.\n");
 395        panic("Reliable operation impossible!\n"
 396#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
 397              "Configure for R4000 or R4400 to enable the workaround."
 398#else
 399              "Please report to <linux-mips@linux-mips.org>."
 400#endif
 401              );
 402}
 403
 404void __init check_bugs(void)
 405{
 406        check_wait();
 407        check_mult_sh();
 408        check_daddi();
 409        check_daddiu();
 410}
 411
 412/*
 413 * Probe whether cpu has config register by trying to play with
 414 * alternate cache bit and see whether it matters.
 415 * It's used by cpu_probe to distinguish between R3000A and R3081.
 416 */
 417static inline int cpu_has_confreg(void)
 418{
 419#ifdef CONFIG_CPU_R3000
 420        extern unsigned long r3k_cache_size(unsigned long);
 421        unsigned long size1, size2;
 422        unsigned long cfg = read_c0_conf();
 423
 424        size1 = r3k_cache_size(ST0_ISC);
 425        write_c0_conf(cfg ^ R30XX_CONF_AC);
 426        size2 = r3k_cache_size(ST0_ISC);
 427        write_c0_conf(cfg);
 428        return size1 != size2;
 429#else
 430        return 0;
 431#endif
 432}
 433
 434/*
 435 * Get the FPU Implementation/Revision.
 436 */
 437static inline unsigned long cpu_get_fpu_id(void)
 438{
 439        unsigned long tmp, fpu_id;
 440
 441        tmp = read_c0_status();
 442        __enable_fpu();
 443        fpu_id = read_32bit_cp1_register(CP1_REVISION);
 444        write_c0_status(tmp);
 445        return fpu_id;
 446}
 447
 448/*
 449 * Check the CPU has an FPU the official way.
 450 */
 451static inline int __cpu_has_fpu(void)
 452{
 453        return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
 454}
 455
 456#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
 457                | MIPS_CPU_COUNTER)
 458
 459static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
 460{
 461        switch (c->processor_id & 0xff00) {
 462        case PRID_IMP_R2000:
 463                c->cputype = CPU_R2000;
 464                c->isa_level = MIPS_CPU_ISA_I;
 465                c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
 466                             MIPS_CPU_LLSC;
 467                if (__cpu_has_fpu())
 468                        c->options |= MIPS_CPU_FPU;
 469                c->tlbsize = 64;
 470                break;
 471        case PRID_IMP_R3000:
 472                if ((c->processor_id & 0xff) == PRID_REV_R3000A)
 473                        if (cpu_has_confreg())
 474                                c->cputype = CPU_R3081E;
 475                        else
 476                                c->cputype = CPU_R3000A;
 477                else
 478                        c->cputype = CPU_R3000;
 479                c->isa_level = MIPS_CPU_ISA_I;
 480                c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
 481                             MIPS_CPU_LLSC;
 482                if (__cpu_has_fpu())
 483                        c->options |= MIPS_CPU_FPU;
 484                c->tlbsize = 64;
 485                break;
 486        case PRID_IMP_R4000:
 487                if ((c->processor_id & 0xff) >= PRID_REV_R4400)
 488                        c->cputype = CPU_R4400SC;
 489                else
 490                        c->cputype = CPU_R4000SC;
 491                c->isa_level = MIPS_CPU_ISA_III;
 492                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 493                             MIPS_CPU_WATCH | MIPS_CPU_VCE |
 494                             MIPS_CPU_LLSC;
 495                c->tlbsize = 48;
 496                break;
 497        case PRID_IMP_VR41XX:
 498                switch (c->processor_id & 0xf0) {
 499#ifndef CONFIG_VR4181
 500                case PRID_REV_VR4111:
 501                        c->cputype = CPU_VR4111;
 502                        break;
 503#else
 504                case PRID_REV_VR4181:
 505                        c->cputype = CPU_VR4181;
 506                        break;
 507#endif
 508                case PRID_REV_VR4121:
 509                        c->cputype = CPU_VR4121;
 510                        break;
 511                case PRID_REV_VR4122:
 512                        if ((c->processor_id & 0xf) < 0x3)
 513                                c->cputype = CPU_VR4122;
 514                        else
 515                                c->cputype = CPU_VR4181A;
 516                        break;
 517                case PRID_REV_VR4130:
 518                        if ((c->processor_id & 0xf) < 0x4)
 519                                c->cputype = CPU_VR4131;
 520                        else
 521                                c->cputype = CPU_VR4133;
 522                        break;
 523                default:
 524                        printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
 525                        c->cputype = CPU_VR41XX;
 526                        break;
 527                }
 528                c->isa_level = MIPS_CPU_ISA_III;
 529                c->options = R4K_OPTS;
 530                c->tlbsize = 32;
 531                break;
 532        case PRID_IMP_R4300:
 533                c->cputype = CPU_R4300;
 534                c->isa_level = MIPS_CPU_ISA_III;
 535                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 536                             MIPS_CPU_LLSC;
 537                c->tlbsize = 32;
 538                break;
 539        case PRID_IMP_R4600:
 540                c->cputype = CPU_R4600;
 541                c->isa_level = MIPS_CPU_ISA_III;
 542                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
 543                c->tlbsize = 48;
 544                break;
 545        #if 0
 546        case PRID_IMP_R4650:
 547                /*
 548                 * This processor doesn't have an MMU, so it's not
 549                 * "real easy" to run Linux on it. It is left purely
 550                 * for documentation.  Commented out because it shares
 551                 * it's c0_prid id number with the TX3900.
 552                 */
 553                c->cputype = CPU_R4650;
 554                c->isa_level = MIPS_CPU_ISA_III;
 555                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
 556                c->tlbsize = 48;
 557                break;
 558        #endif
 559        case PRID_IMP_TX39:
 560                c->isa_level = MIPS_CPU_ISA_I;
 561                c->options = MIPS_CPU_TLB;
 562
 563                if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
 564                        c->cputype = CPU_TX3927;
 565                        c->tlbsize = 64;
 566                } else {
 567                        switch (c->processor_id & 0xff) {
 568                        case PRID_REV_TX3912:
 569                                c->cputype = CPU_TX3912;
 570                                c->tlbsize = 32;
 571                                break;
 572                        case PRID_REV_TX3922:
 573                                c->cputype = CPU_TX3922;
 574                                c->tlbsize = 64;
 575                                break;
 576                        default:
 577                                c->cputype = CPU_UNKNOWN;
 578                                break;
 579                        }
 580                }
 581                break;
 582        case PRID_IMP_R4700:
 583                c->cputype = CPU_R4700;
 584                c->isa_level = MIPS_CPU_ISA_III;
 585                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 586                             MIPS_CPU_LLSC;
 587                c->tlbsize = 48;
 588                break;
 589        case PRID_IMP_TX49:
 590                c->cputype = CPU_TX49XX;
 591                c->isa_level = MIPS_CPU_ISA_III;
 592                c->options = R4K_OPTS | MIPS_CPU_LLSC;
 593                if (!(c->processor_id & 0x08))
 594                        c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
 595                c->tlbsize = 48;
 596                break;
 597        case PRID_IMP_R5000:
 598                c->cputype = CPU_R5000;
 599                c->isa_level = MIPS_CPU_ISA_IV;
 600                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 601                             MIPS_CPU_LLSC;
 602                c->tlbsize = 48;
 603                break;
 604        case PRID_IMP_R5432:
 605                c->cputype = CPU_R5432;
 606                c->isa_level = MIPS_CPU_ISA_IV;
 607                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 608                             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
 609                c->tlbsize = 48;
 610                break;
 611        case PRID_IMP_R5500:
 612                c->cputype = CPU_R5500;
 613                c->isa_level = MIPS_CPU_ISA_IV;
 614                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 615                             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
 616                c->tlbsize = 48;
 617                break;
 618        case PRID_IMP_NEVADA:
 619                c->cputype = CPU_NEVADA;
 620                c->isa_level = MIPS_CPU_ISA_IV;
 621                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 622                             MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
 623                c->tlbsize = 48;
 624                break;
 625        case PRID_IMP_R6000:
 626                c->cputype = CPU_R6000;
 627                c->isa_level = MIPS_CPU_ISA_II;
 628                c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
 629                             MIPS_CPU_LLSC;
 630                c->tlbsize = 32;
 631                break;
 632        case PRID_IMP_R6000A:
 633                c->cputype = CPU_R6000A;
 634                c->isa_level = MIPS_CPU_ISA_II;
 635                c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
 636                             MIPS_CPU_LLSC;
 637                c->tlbsize = 32;
 638                break;
 639        case PRID_IMP_RM7000:
 640                c->cputype = CPU_RM7000;
 641                c->isa_level = MIPS_CPU_ISA_IV;
 642                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 643                             MIPS_CPU_LLSC;
 644                /*
 645                 * Undocumented RM7000:  Bit 29 in the info register of
 646                 * the RM7000 v2.0 indicates if the TLB has 48 or 64
 647                 * entries.
 648                 *
 649                 * 29      1 =>    64 entry JTLB
 650                 *         0 =>    48 entry JTLB
 651                 */
 652                c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
 653                break;
 654        case PRID_IMP_RM9000:
 655                c->cputype = CPU_RM9000;
 656                c->isa_level = MIPS_CPU_ISA_IV;
 657                c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 658                             MIPS_CPU_LLSC;
 659                /*
 660                 * Bit 29 in the info register of the RM9000
 661                 * indicates if the TLB has 48 or 64 entries.
 662                 *
 663                 * 29      1 =>    64 entry JTLB
 664                 *         0 =>    48 entry JTLB
 665                 */
 666                c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
 667                break;
 668        case PRID_IMP_R8000:
 669                c->cputype = CPU_R8000;
 670                c->isa_level = MIPS_CPU_ISA_IV;
 671                c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
 672                             MIPS_CPU_FPU | MIPS_CPU_32FPR |
 673                             MIPS_CPU_LLSC;
 674                c->tlbsize = 384;      /* has weird TLB: 3-way x 128 */
 675                break;
 676        case PRID_IMP_R10000:
 677                c->cputype = CPU_R10000;
 678                c->isa_level = MIPS_CPU_ISA_IV;
 679                c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
 680                             MIPS_CPU_FPU | MIPS_CPU_32FPR |
 681                             MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
 682                             MIPS_CPU_LLSC;
 683                c->tlbsize = 64;
 684                break;
 685        case PRID_IMP_R12000:
 686                c->cputype = CPU_R12000;
 687                c->isa_level = MIPS_CPU_ISA_IV;
 688                c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
 689                             MIPS_CPU_FPU | MIPS_CPU_32FPR |
 690                             MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
 691                             MIPS_CPU_LLSC;
 692                c->tlbsize = 64;
 693                break;
 694        default:
 695                c->cputype = CPU_UNKNOWN;
 696                break;
 697        }
 698}
 699
 700static inline void decode_config1(struct cpuinfo_mips *c)
 701{
 702        unsigned long config0 = read_c0_config();
 703        unsigned long config1;
 704
 705        if ((config0 & (1 << 31)) == 0)
 706                return;                 /* actually wort a panic() */
 707
 708        /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */
 709        c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
 710                MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
 711                MIPS_CPU_LLSC;
 712        config1 = read_c0_config1();
 713        if (config1 & (1 << 3))
 714                c->options |= MIPS_CPU_WATCH;
 715        if (config1 & (1 << 2))
 716                c->options |= MIPS_CPU_MIPS16;
 717        if (config1 & (1 << 1))
 718                c->options |= MIPS_CPU_EJTAG;
 719        if (config1 & 1) {
 720                c->options |= MIPS_CPU_FPU;
 721                c->options |= MIPS_CPU_32FPR;
 722        }
 723        c->scache.flags = MIPS_CACHE_NOT_PRESENT;
 724
 725        c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
 726}
 727
 728static inline void cpu_probe_mips(struct cpuinfo_mips *c)
 729{
 730        decode_config1(c);
 731        switch (c->processor_id & 0xff00) {
 732        case PRID_IMP_4KC:
 733                c->cputype = CPU_4KC;
 734                c->isa_level = MIPS_CPU_ISA_M32;
 735                break;
 736        case PRID_IMP_4KEC:
 737                c->cputype = CPU_4KEC;
 738                c->isa_level = MIPS_CPU_ISA_M32;
 739                break;
 740        case PRID_IMP_4KSC:
 741                c->cputype = CPU_4KSC;
 742                c->isa_level = MIPS_CPU_ISA_M32;
 743                break;
 744        case PRID_IMP_5KC:
 745                c->cputype = CPU_5KC;
 746                c->isa_level = MIPS_CPU_ISA_M64;
 747                break;
 748        case PRID_IMP_20KC:
 749                c->cputype = CPU_20KC;
 750                c->isa_level = MIPS_CPU_ISA_M64;
 751                break;
 752        case PRID_IMP_24K:
 753                c->cputype = CPU_24K;
 754                c->isa_level = MIPS_CPU_ISA_M32;
 755                break;
 756        case PRID_IMP_25KF:
 757                c->cputype = CPU_25KF;
 758                c->isa_level = MIPS_CPU_ISA_M64;
 759                /* Probe for L2 cache */
 760                c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
 761                break;
 762        default:
 763                c->cputype = CPU_UNKNOWN;
 764                break;
 765        }
 766}
 767
 768static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
 769{
 770        decode_config1(c);
 771        switch (c->processor_id & 0xff00) {
 772        case PRID_IMP_AU1_REV1:
 773        case PRID_IMP_AU1_REV2:
 774                switch ((c->processor_id >> 24) & 0xff) {
 775                case 0:
 776                        c->cputype = CPU_AU1000;
 777                        break;
 778                case 1:
 779                        c->cputype = CPU_AU1500;
 780                        break;
 781                case 2:
 782                        c->cputype = CPU_AU1100;
 783                        break;
 784                default:
 785                        panic("Unknown Au Core!");
 786                        break;
 787                }
 788                c->isa_level = MIPS_CPU_ISA_M32;
 789                break;
 790        }
 791}
 792
 793static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
 794{
 795        decode_config1(c);
 796        switch (c->processor_id & 0xff00) {
 797        case PRID_IMP_SB1:
 798                c->cputype = CPU_SB1;
 799                c->isa_level = MIPS_CPU_ISA_M64;
 800                c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
 801                             MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
 802                             MIPS_CPU_MCHECK | MIPS_CPU_EJTAG |
 803                             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
 804#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
 805                /* FPU in pass1 is known to have issues. */
 806                c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
 807#endif
 808                break;
 809        default:
 810                c->cputype = CPU_UNKNOWN;
 811                break;
 812        }
 813}
 814
 815static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
 816{
 817        decode_config1(c);
 818        switch (c->processor_id & 0xff00) {
 819        case PRID_IMP_SR71000:
 820                c->cputype = CPU_SR71000;
 821                c->isa_level = MIPS_CPU_ISA_M64;
 822                c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
 823                             MIPS_CPU_4KTLB | MIPS_CPU_FPU |
 824                             MIPS_CPU_COUNTER | MIPS_CPU_MCHECK;
 825                c->scache.ways = 8;
 826                c->tlbsize = 64;
 827                break;
 828        default:
 829                c->cputype = CPU_UNKNOWN;
 830                break;
 831        }
 832}
 833
 834__init void cpu_probe(void)
 835{
 836        struct cpuinfo_mips *c = &current_cpu_data;
 837
 838        c->processor_id = PRID_IMP_UNKNOWN;
 839        c->fpu_id       = FPIR_IMP_NONE;
 840        c->cputype      = CPU_UNKNOWN;
 841
 842        c->processor_id = read_c0_prid();
 843        switch (c->processor_id & 0xff0000) {
 844        case PRID_COMP_LEGACY:
 845                cpu_probe_legacy(c);
 846                break;
 847        case PRID_COMP_MIPS:
 848                cpu_probe_mips(c);
 849                break;
 850        case PRID_COMP_ALCHEMY:
 851                cpu_probe_alchemy(c);
 852                break;
 853        case PRID_COMP_SIBYTE:
 854                cpu_probe_sibyte(c);
 855                break;
 856
 857        case PRID_COMP_SANDCRAFT:
 858                cpu_probe_sandcraft(c);
 859                break;
 860        default:
 861                c->cputype = CPU_UNKNOWN;
 862        }
 863        if (c->options & MIPS_CPU_FPU)
 864                c->fpu_id = cpu_get_fpu_id();
 865}
 866
 867__init void cpu_report(void)
 868{
 869        struct cpuinfo_mips *c = &current_cpu_data;
 870
 871        printk("CPU revision is: %08x\n", c->processor_id);
 872        if (c->options & MIPS_CPU_FPU)
 873                printk("FPU revision is: %08x\n", c->fpu_id);
 874}
 875
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.