linux/arch/sparc/kernel/cpu.c
<<
>>
Prefs
   1/* cpu.c: Dinky routines to look for the kind of Sparc cpu
   2 *        we are on.
   3 *
   4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
   5 */
   6
   7#include <linux/seq_file.h>
   8#include <linux/kernel.h>
   9#include <linux/export.h>
  10#include <linux/init.h>
  11#include <linux/smp.h>
  12#include <linux/threads.h>
  13
  14#include <asm/spitfire.h>
  15#include <asm/pgtable.h>
  16#include <asm/oplib.h>
  17#include <asm/setup.h>
  18#include <asm/page.h>
  19#include <asm/head.h>
  20#include <asm/psr.h>
  21#include <asm/mbus.h>
  22#include <asm/cpudata.h>
  23
  24#include "kernel.h"
  25#include "entry.h"
  26
  27DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
  28EXPORT_PER_CPU_SYMBOL(__cpu_data);
  29
  30int ncpus_probed;
  31unsigned int fsr_storage;
  32
  33struct cpu_info {
  34        int psr_vers;
  35        const char *name;
  36        const char *pmu_name;
  37};
  38
  39struct fpu_info {
  40        int fp_vers;
  41        const char *name;
  42};
  43
  44#define NOCPU 8
  45#define NOFPU 8
  46
  47struct manufacturer_info {
  48        int psr_impl;
  49        struct cpu_info cpu_info[NOCPU];
  50        struct fpu_info fpu_info[NOFPU];
  51};
  52
  53#define CPU(ver, _name) \
  54{ .psr_vers = ver, .name = _name }
  55
  56#define CPU_PMU(ver, _name, _pmu_name)  \
  57{ .psr_vers = ver, .name = _name, .pmu_name = _pmu_name }
  58
  59#define FPU(ver, _name) \
  60{ .fp_vers = ver, .name = _name }
  61
  62static const struct manufacturer_info __initconst manufacturer_info[] = {
  63{
  64        0,
  65        /* Sun4/100, 4/200, SLC */
  66        .cpu_info = {
  67                CPU(0, "Fujitsu  MB86900/1A or LSI L64831 SparcKIT-40"),
  68                /* borned STP1012PGA */
  69                CPU(4,  "Fujitsu  MB86904"),
  70                CPU(5, "Fujitsu TurboSparc MB86907"),
  71                CPU(-1, NULL)
  72        },
  73        .fpu_info = {
  74                FPU(0, "Fujitsu MB86910 or Weitek WTL1164/5"),
  75                FPU(1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"),
  76                FPU(2, "LSI Logic L64802 or Texas Instruments ACT8847"),
  77                /* SparcStation SLC, SparcStation1 */
  78                FPU(3, "Weitek WTL3170/2"),
  79                /* SPARCstation-5 */
  80                FPU(4, "Lsi Logic/Meiko L64804 or compatible"),
  81                FPU(-1, NULL)
  82        }
  83},{
  84        1,
  85        .cpu_info = {
  86                /* SparcStation2, SparcServer 490 & 690 */
  87                CPU(0, "LSI Logic Corporation - L64811"),
  88                /* SparcStation2 */
  89                CPU(1, "Cypress/ROSS CY7C601"),
  90                /* Embedded controller */
  91                CPU(3, "Cypress/ROSS CY7C611"),
  92                /* Ross Technologies HyperSparc */
  93                CPU(0xf, "ROSS HyperSparc RT620"),
  94                CPU(0xe, "ROSS HyperSparc RT625 or RT626"),
  95                CPU(-1, NULL)
  96        },
  97        .fpu_info = {
  98                FPU(0, "ROSS HyperSparc combined IU/FPU"),
  99                FPU(1, "Lsi Logic L64814"),
 100                FPU(2, "Texas Instruments TMS390-C602A"),
 101                FPU(3, "Cypress CY7C602 FPU"),
 102                FPU(-1, NULL)
 103        }
 104},{
 105        2,
 106        .cpu_info = {
 107                /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */
 108                /* Someone please write the code to support this beast! ;) */
 109                CPU(0, "Bipolar Integrated Technology - B5010"),
 110                CPU(-1, NULL)
 111        },
 112        .fpu_info = {
 113                FPU(-1, NULL)
 114        }
 115},{
 116        3,
 117        .cpu_info = {
 118                CPU(0, "LSI Logic Corporation - unknown-type"),
 119                CPU(-1, NULL)
 120        },
 121        .fpu_info = {
 122                FPU(-1, NULL)
 123        }
 124},{
 125        PSR_IMPL_TI,
 126        .cpu_info = {
 127                CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"),
 128                /* SparcClassic  --  borned STP1010TAB-50*/
 129                CPU(1, "Texas Instruments, Inc. - MicroSparc"),
 130                CPU(2, "Texas Instruments, Inc. - MicroSparc II"),
 131                CPU(3, "Texas Instruments, Inc. - SuperSparc 51"),
 132                CPU(4, "Texas Instruments, Inc. - SuperSparc 61"),
 133                CPU(5, "Texas Instruments, Inc. - unknown"),
 134                CPU(-1, NULL)
 135        },
 136        .fpu_info = {
 137                /* SuperSparc 50 module */
 138                FPU(0, "SuperSparc on-chip FPU"),
 139                /* SparcClassic */
 140                FPU(4, "TI MicroSparc on chip FPU"),
 141                FPU(-1, NULL)
 142        }
 143},{
 144        5,
 145        .cpu_info = {
 146                CPU(0, "Matsushita - MN10501"),
 147                CPU(-1, NULL)
 148        },
 149        .fpu_info = {
 150                FPU(0, "Matsushita MN10501"),
 151                FPU(-1, NULL)
 152        }
 153},{
 154        6,
 155        .cpu_info = {
 156                CPU(0, "Philips Corporation - unknown"),
 157                CPU(-1, NULL)
 158        },
 159        .fpu_info = {
 160                FPU(-1, NULL)
 161        }
 162},{
 163        7,
 164        .cpu_info = {
 165                CPU(0, "Harvest VLSI Design Center, Inc. - unknown"),
 166                CPU(-1, NULL)
 167        },
 168        .fpu_info = {
 169                FPU(-1, NULL)
 170        }
 171},{
 172        8,
 173        .cpu_info = {
 174                CPU(0, "Systems and Processes Engineering Corporation (SPEC)"),
 175                CPU(-1, NULL)
 176        },
 177        .fpu_info = {
 178                FPU(-1, NULL)
 179        }
 180},{
 181        9,
 182        .cpu_info = {
 183                /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */
 184                CPU(0, "Fujitsu or Weitek Power-UP"),
 185                CPU(1, "Fujitsu or Weitek Power-UP"),
 186                CPU(2, "Fujitsu or Weitek Power-UP"),
 187                CPU(3, "Fujitsu or Weitek Power-UP"),
 188                CPU(-1, NULL)
 189        },
 190        .fpu_info = {
 191                FPU(3, "Fujitsu or Weitek on-chip FPU"),
 192                FPU(-1, NULL)
 193        }
 194},{
 195        PSR_IMPL_LEON,          /* Aeroflex Gaisler */
 196        .cpu_info = {
 197                CPU(3, "LEON"),
 198                CPU(-1, NULL)
 199        },
 200        .fpu_info = {
 201                FPU(2, "GRFPU"),
 202                FPU(3, "GRFPU-Lite"),
 203                FPU(-1, NULL)
 204        }
 205},{
 206        0x17,
 207        .cpu_info = {
 208                CPU_PMU(0x10, "TI UltraSparc I   (SpitFire)", "ultra12"),
 209                CPU_PMU(0x11, "TI UltraSparc II  (BlackBird)", "ultra12"),
 210                CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"),
 211                CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"),
 212                CPU(-1, NULL)
 213        },
 214        .fpu_info = {
 215                FPU(0x10, "UltraSparc I integrated FPU"),
 216                FPU(0x11, "UltraSparc II integrated FPU"),
 217                FPU(0x12, "UltraSparc IIi integrated FPU"),
 218                FPU(0x13, "UltraSparc IIe integrated FPU"),
 219                FPU(-1, NULL)
 220        }
 221},{
 222        0x22,
 223        .cpu_info = {
 224                CPU_PMU(0x10, "TI UltraSparc I   (SpitFire)", "ultra12"),
 225                CPU(-1, NULL)
 226        },
 227        .fpu_info = {
 228                FPU(0x10, "UltraSparc I integrated FPU"),
 229                FPU(-1, NULL)
 230        }
 231},{
 232        0x3e,
 233        .cpu_info = {
 234                CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"),
 235                CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"),
 236                CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"),
 237                CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"),
 238                CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"),
 239                CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"),
 240                CPU(-1, NULL)
 241        },
 242        .fpu_info = {
 243                FPU(0x14, "UltraSparc III integrated FPU"),
 244                FPU(0x15, "UltraSparc III+ integrated FPU"),
 245                FPU(0x16, "UltraSparc IIIi integrated FPU"),
 246                FPU(0x18, "UltraSparc IV integrated FPU"),
 247                FPU(0x19, "UltraSparc IV+ integrated FPU"),
 248                FPU(0x22, "UltraSparc IIIi+ integrated FPU"),
 249                FPU(-1, NULL)
 250        }
 251}};
 252
 253/* In order to get the fpu type correct, you need to take the IDPROM's
 254 * machine type value into consideration too.  I will fix this.
 255 */
 256
 257static const char *sparc_cpu_type;
 258static const char *sparc_fpu_type;
 259const char *sparc_pmu_type;
 260
 261
 262static void __init set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
 263{
 264        const struct manufacturer_info *manuf;
 265        int i;
 266
 267        sparc_cpu_type = NULL;
 268        sparc_fpu_type = NULL;
 269        sparc_pmu_type = NULL;
 270        manuf = NULL;
 271
 272        for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++)
 273        {
 274                if (psr_impl == manufacturer_info[i].psr_impl) {
 275                        manuf = &manufacturer_info[i];
 276                        break;
 277                }
 278        }
 279        if (manuf != NULL)
 280        {
 281                const struct cpu_info *cpu;
 282                const struct fpu_info *fpu;
 283
 284                cpu = &manuf->cpu_info[0];
 285                while (cpu->psr_vers != -1)
 286                {
 287                        if (cpu->psr_vers == psr_vers) {
 288                                sparc_cpu_type = cpu->name;
 289                                sparc_pmu_type = cpu->pmu_name;
 290                                sparc_fpu_type = "No FPU";
 291                                break;
 292                        }
 293                        cpu++;
 294                }
 295                fpu =  &manuf->fpu_info[0];
 296                while (fpu->fp_vers != -1)
 297                {
 298                        if (fpu->fp_vers == fpu_vers) {
 299                                sparc_fpu_type = fpu->name;
 300                                break;
 301                        }
 302                        fpu++;
 303                }
 304        }
 305        if (sparc_cpu_type == NULL)
 306        {
 307                printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n",
 308                       psr_impl, psr_vers);
 309                sparc_cpu_type = "Unknown CPU";
 310        }
 311        if (sparc_fpu_type == NULL)
 312        {
 313                printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n",
 314                       psr_impl, fpu_vers);
 315                sparc_fpu_type = "Unknown FPU";
 316        }
 317        if (sparc_pmu_type == NULL)
 318                sparc_pmu_type = "Unknown PMU";
 319}
 320
 321#ifdef CONFIG_SPARC32
 322static int show_cpuinfo(struct seq_file *m, void *__unused)
 323{
 324        seq_printf(m,
 325                   "cpu\t\t: %s\n"
 326                   "fpu\t\t: %s\n"
 327                   "promlib\t\t: Version %d Revision %d\n"
 328                   "prom\t\t: %d.%d\n"
 329                   "type\t\t: %s\n"
 330                   "ncpus probed\t: %d\n"
 331                   "ncpus active\t: %d\n"
 332#ifndef CONFIG_SMP
 333                   "CPU0Bogo\t: %lu.%02lu\n"
 334                   "CPU0ClkTck\t: %ld\n"
 335#endif
 336                   ,
 337                   sparc_cpu_type,
 338                   sparc_fpu_type ,
 339                   romvec->pv_romvers,
 340                   prom_rev,
 341                   romvec->pv_printrev >> 16,
 342                   romvec->pv_printrev & 0xffff,
 343                   &cputypval[0],
 344                   ncpus_probed,
 345                   num_online_cpus()
 346#ifndef CONFIG_SMP
 347                   , cpu_data(0).udelay_val/(500000/HZ),
 348                   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
 349                   cpu_data(0).clock_tick
 350#endif
 351                );
 352
 353#ifdef CONFIG_SMP
 354        smp_bogo(m);
 355#endif
 356        mmu_info(m);
 357#ifdef CONFIG_SMP
 358        smp_info(m);
 359#endif
 360        return 0;
 361}
 362#endif /* CONFIG_SPARC32 */
 363
 364#ifdef CONFIG_SPARC64
 365unsigned int dcache_parity_tl1_occurred;
 366unsigned int icache_parity_tl1_occurred;
 367
 368
 369static int show_cpuinfo(struct seq_file *m, void *__unused)
 370{
 371        seq_printf(m,
 372                   "cpu\t\t: %s\n"
 373                   "fpu\t\t: %s\n"
 374                   "pmu\t\t: %s\n"
 375                   "prom\t\t: %s\n"
 376                   "type\t\t: %s\n"
 377                   "ncpus probed\t: %d\n"
 378                   "ncpus active\t: %d\n"
 379                   "D$ parity tl1\t: %u\n"
 380                   "I$ parity tl1\t: %u\n"
 381#ifndef CONFIG_SMP
 382                   "Cpu0ClkTck\t: %016lx\n"
 383#endif
 384                   ,
 385                   sparc_cpu_type,
 386                   sparc_fpu_type,
 387                   sparc_pmu_type,
 388                   prom_version,
 389                   ((tlb_type == hypervisor) ?
 390                    "sun4v" :
 391                    "sun4u"),
 392                   ncpus_probed,
 393                   num_online_cpus(),
 394                   dcache_parity_tl1_occurred,
 395                   icache_parity_tl1_occurred
 396#ifndef CONFIG_SMP
 397                   , cpu_data(0).clock_tick
 398#endif
 399                );
 400        cpucap_info(m);
 401#ifdef CONFIG_SMP
 402        smp_bogo(m);
 403#endif
 404        mmu_info(m);
 405#ifdef CONFIG_SMP
 406        smp_info(m);
 407#endif
 408        return 0;
 409}
 410#endif /* CONFIG_SPARC64 */
 411
 412static void *c_start(struct seq_file *m, loff_t *pos)
 413{
 414        /* The pointer we are returning is arbitrary,
 415         * it just has to be non-NULL and not IS_ERR
 416         * in the success case.
 417         */
 418        return *pos == 0 ? &c_start : NULL;
 419}
 420
 421static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 422{
 423        ++*pos;
 424        return c_start(m, pos);
 425}
 426
 427static void c_stop(struct seq_file *m, void *v)
 428{
 429}
 430
 431const struct seq_operations cpuinfo_op = {
 432        .start =c_start,
 433        .next = c_next,
 434        .stop = c_stop,
 435        .show = show_cpuinfo,
 436};
 437
 438#ifdef CONFIG_SPARC32
 439static int __init cpu_type_probe(void)
 440{
 441        int psr_impl, psr_vers, fpu_vers;
 442        int psr;
 443
 444        psr_impl = ((get_psr() >> PSR_IMPL_SHIFT) & PSR_IMPL_SHIFTED_MASK);
 445        psr_vers = ((get_psr() >> PSR_VERS_SHIFT) & PSR_VERS_SHIFTED_MASK);
 446
 447        psr = get_psr();
 448        put_psr(psr | PSR_EF);
 449
 450        if (psr_impl == PSR_IMPL_LEON)
 451                fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7;
 452        else
 453                fpu_vers = ((get_fsr() >> 17) & 0x7);
 454
 455        put_psr(psr);
 456
 457        set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers);
 458
 459        return 0;
 460}
 461#endif /* CONFIG_SPARC32 */
 462
 463#ifdef CONFIG_SPARC64
 464static void __init sun4v_cpu_probe(void)
 465{
 466        switch (sun4v_chip_type) {
 467        case SUN4V_CHIP_NIAGARA1:
 468                sparc_cpu_type = "UltraSparc T1 (Niagara)";
 469                sparc_fpu_type = "UltraSparc T1 integrated FPU";
 470                sparc_pmu_type = "niagara";
 471                break;
 472
 473        case SUN4V_CHIP_NIAGARA2:
 474                sparc_cpu_type = "UltraSparc T2 (Niagara2)";
 475                sparc_fpu_type = "UltraSparc T2 integrated FPU";
 476                sparc_pmu_type = "niagara2";
 477                break;
 478
 479        case SUN4V_CHIP_NIAGARA3:
 480                sparc_cpu_type = "UltraSparc T3 (Niagara3)";
 481                sparc_fpu_type = "UltraSparc T3 integrated FPU";
 482                sparc_pmu_type = "niagara3";
 483                break;
 484
 485        case SUN4V_CHIP_NIAGARA4:
 486                sparc_cpu_type = "UltraSparc T4 (Niagara4)";
 487                sparc_fpu_type = "UltraSparc T4 integrated FPU";
 488                sparc_pmu_type = "niagara4";
 489                break;
 490
 491        case SUN4V_CHIP_NIAGARA5:
 492                sparc_cpu_type = "UltraSparc T5 (Niagara5)";
 493                sparc_fpu_type = "UltraSparc T5 integrated FPU";
 494                sparc_pmu_type = "niagara5";
 495                break;
 496
 497        case SUN4V_CHIP_SPARC_M6:
 498                sparc_cpu_type = "SPARC-M6";
 499                sparc_fpu_type = "SPARC-M6 integrated FPU";
 500                sparc_pmu_type = "sparc-m6";
 501                break;
 502
 503        case SUN4V_CHIP_SPARC_M7:
 504                sparc_cpu_type = "SPARC-M7";
 505                sparc_fpu_type = "SPARC-M7 integrated FPU";
 506                sparc_pmu_type = "sparc-m7";
 507                break;
 508
 509        case SUN4V_CHIP_SPARC_SN:
 510                sparc_cpu_type = "SPARC-SN";
 511                sparc_fpu_type = "SPARC-SN integrated FPU";
 512                sparc_pmu_type = "sparc-sn";
 513                break;
 514
 515        case SUN4V_CHIP_SPARC64X:
 516                sparc_cpu_type = "SPARC64-X";
 517                sparc_fpu_type = "SPARC64-X integrated FPU";
 518                sparc_pmu_type = "sparc64-x";
 519                break;
 520
 521        default:
 522                printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
 523                       prom_cpu_compatible);
 524                sparc_cpu_type = "Unknown SUN4V CPU";
 525                sparc_fpu_type = "Unknown SUN4V FPU";
 526                sparc_pmu_type = "Unknown SUN4V PMU";
 527                break;
 528        }
 529}
 530
 531static int __init cpu_type_probe(void)
 532{
 533        if (tlb_type == hypervisor) {
 534                sun4v_cpu_probe();
 535        } else {
 536                unsigned long ver;
 537                int manuf, impl;
 538
 539                __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
 540
 541                manuf = ((ver >> 48) & 0xffff);
 542                impl = ((ver >> 32) & 0xffff);
 543                set_cpu_and_fpu(manuf, impl, impl);
 544        }
 545        return 0;
 546}
 547#endif /* CONFIG_SPARC64 */
 548
 549early_initcall(cpu_type_probe);
 550