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