cpu.c 3.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/* cpu.c: Dinky routines to look for the kind of Sparc cpu
 *        we are on.
 *
4
 * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <asm/asi.h>
#include <asm/system.h>
#include <asm/fpumacro.h>
#include <asm/cpudata.h>
15
#include <asm/spitfire.h>
16
#include <asm/oplib.h>
L
Linus Torvalds 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };

struct cpu_iu_info {
  short manuf;
  short impl;
  char* cpu_name;   /* should be enough I hope... */
};

struct cpu_fp_info {
  short manuf;
  short impl;
  char fpu_vers;
  char* fp_name;
};

struct cpu_fp_info linux_sparc_fpu[] = {
  { 0x17, 0x10, 0, "UltraSparc I integrated FPU"},
  { 0x22, 0x10, 0, "UltraSparc I integrated FPU"},
  { 0x17, 0x11, 0, "UltraSparc II integrated FPU"},
  { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"},
  { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"},
  { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"},
  { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"},
  { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"},
  { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"},
43 44
  { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"},
  { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"},
L
Linus Torvalds 已提交
45 46
};

T
Tobias Klauser 已提交
47
#define NSPARCFPU  ARRAY_SIZE(linux_sparc_fpu)
L
Linus Torvalds 已提交
48 49 50 51 52 53 54 55 56 57 58

struct cpu_iu_info linux_sparc_chips[] = {
  { 0x17, 0x10, "TI UltraSparc I   (SpitFire)"},
  { 0x22, 0x10, "TI UltraSparc I   (SpitFire)"},
  { 0x17, 0x11, "TI UltraSparc II  (BlackBird)"},
  { 0x17, 0x12, "TI UltraSparc IIi (Sabre)"},
  { 0x17, 0x13, "TI UltraSparc IIe (Hummingbird)"},
  { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"},
  { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"},
  { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"},
  { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"},
59 60
  { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"},
  { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"},
L
Linus Torvalds 已提交
61 62
};

T
Tobias Klauser 已提交
63
#define NSPARCCHIPS  ARRAY_SIZE(linux_sparc_chips)
L
Linus Torvalds 已提交
64

65 66
char *sparc_cpu_type;
char *sparc_fpu_type;
L
Linus Torvalds 已提交
67 68 69

unsigned int fsr_storage;

70 71
static void __init sun4v_cpu_probe(void)
{
72 73
	switch (sun4v_chip_type) {
	case SUN4V_CHIP_NIAGARA1:
74 75
		sparc_cpu_type = "UltraSparc T1 (Niagara)";
		sparc_fpu_type = "UltraSparc T1 integrated FPU";
76 77 78
		break;

	case SUN4V_CHIP_NIAGARA2:
79 80
		sparc_cpu_type = "UltraSparc T2 (Niagara2)";
		sparc_fpu_type = "UltraSparc T2 integrated FPU";
81 82 83 84 85 86 87 88 89
		break;

	default:
		printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
		       prom_cpu_compatible);
		sparc_cpu_type = "Unknown SUN4V CPU";
		sparc_fpu_type = "Unknown SUN4V FPU";
		break;
	}
90 91
}

L
Linus Torvalds 已提交
92 93 94 95 96
void __init cpu_probe(void)
{
	unsigned long ver, fpu_vers, manuf, impl, fprs;
	int i;
	
97 98
	if (tlb_type == hypervisor)
		return sun4v_cpu_probe();
99

L
Linus Torvalds 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
	fprs = fprs_read();
	fprs_write(FPRS_FEF);
	__asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]"
			      : "=&r" (ver)
			      : "r" (&fpu_vers));
	fprs_write(fprs);
	
	manuf = ((ver >> 48) & 0xffff);
	impl = ((ver >> 32) & 0xffff);

	fpu_vers = ((fpu_vers >> 17) & 0x7);

retry:
	for (i = 0; i < NSPARCCHIPS; i++) {
		if (linux_sparc_chips[i].manuf == manuf) {
			if (linux_sparc_chips[i].impl == impl) {
				sparc_cpu_type =
					linux_sparc_chips[i].cpu_name;
				break;
			}
		}
	}

	if (i == NSPARCCHIPS) {
 		/* Maybe it is a cheetah+ derivative, report it as cheetah+
 		 * in that case until we learn the real names.
 		 */
 		if (manuf == 0x3e &&
 		    impl > 0x15) {
 			impl = 0x15;
 			goto retry;
 		} else {
 			printk("DEBUG: manuf[%lx] impl[%lx]\n",
 			       manuf, impl);
 		}
		sparc_cpu_type = "Unknown CPU";
	}

	for (i = 0; i < NSPARCFPU; i++) {
		if (linux_sparc_fpu[i].manuf == manuf &&
		    linux_sparc_fpu[i].impl == impl) {
			if (linux_sparc_fpu[i].fpu_vers == fpu_vers) {
				sparc_fpu_type =
					linux_sparc_fpu[i].fp_name;
				break;
			}
		}
	}

	if (i == NSPARCFPU) {
 		printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n",
 		       manuf, impl, fpu_vers);
		sparc_fpu_type = "Unknown FPU";
	}
}