xref: /original-bsd/sys/sparc/sparc/cpu.c (revision 95ecee29)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratory.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)cpu.c	8.5 (Berkeley) 11/23/93
17  *
18  * from: $Header: cpu.c,v 1.18 93/10/31 05:28:13 torek Exp $ (LBL)
19  */
20 
21 #include <sys/param.h>
22 #include <sys/device.h>
23 
24 #include <machine/autoconf.h>
25 #include <machine/cpu.h>
26 #include <machine/reg.h>
27 #include <machine/trap.h>
28 
29 #include <sparc/sparc/cache.h>
30 
31 /* This is declared here so that you must include a CPU for the cache code. */
32 struct cacheinfo cacheinfo;
33 
34 /* The following are used externally (sysctl_hw). */
35 char	machine[] = "sparc";
36 char	cpu_model[100];
37 
38 /* The CPU configuration driver. */
39 static void cpu_attach __P((struct device *, struct device *, void *));
40 
41 struct cfdriver cpucd =
42     { NULL, "cpu", matchbyname, cpu_attach, DV_CPU, sizeof(struct device) };
43 
44 static char *psrtoname __P((int, int, int, char *));
45 static char *fsrtoname __P((int, int, int, char *));
46 
47 #define	IU_IMPL(psr)	((u_int)(psr) >> 28)
48 #define	IU_VERS(psr)	(((psr) >> 24) & 0xf)
49 
50 #ifdef notdef
51 /*
52  * IU implementations are parceled out to vendors (with some slight
53  * glitches).  Printing these is cute but takes too much space.
54  */
55 static char *iu_vendor[16] = {
56 	"Fujitsu",	/* and also LSI Logic */
57 	"ROSS",		/* ROSS (ex-Cypress) */
58 	"BIT",
59 	"LSIL",		/* LSI Logic finally got their own */
60 	"TI",		/* Texas Instruments */
61 	"Matsushita",
62 	"Philips",
63 	"Harvest",	/* Harvest VLSI Design Center */
64 	"SPEC",		/* Systems and Processes Engineering Corporation */
65 	"Weitek",
66 	"vendor#10",
67 	"vendor#11",
68 	"vendor#12",
69 	"vendor#13",
70 	"vendor#14",
71 	"vendor#15"
72 };
73 #endif
74 
75 /*
76  * Attach the CPU.
77  * Discover interesting goop about the virtual address cache
78  * (slightly funny place to do it, but this is where it is to be found).
79  */
80 static void
81 cpu_attach(parent, dev, aux)
82 	struct device *parent;
83 	struct device *dev;
84 	void *aux;
85 {
86 	register int node, clk, i, l;
87 	register int impl, vers, fver;
88 	register char *fpuname;
89 	struct fpstate fpstate;
90 	char iubuf[40], fpbuf[40];
91 
92 	/*
93 	 * Get the FSR and clear any exceptions.  If we do not unload
94 	 * the queue here and it is left over from a previous crash, we
95 	 * will panic in the first loadfpstate(), due to a sequence error,
96 	 * so we need to dump the whole state anyway.
97 	 *
98 	 * If there is no FPU, trap.c will advance over all the stores,
99 	 * so we initialize fs_fsr here.
100 	 */
101 	fpstate.fs_fsr = 7 << FSR_VER_SHIFT;	/* 7 is reserved for "none" */
102 	savefpstate(&fpstate);
103 	fver = (fpstate.fs_fsr >> FSR_VER_SHIFT) & (FSR_VER >> FSR_VER_SHIFT);
104 	i = getpsr();
105 	impl = IU_IMPL(i);
106 	vers = IU_VERS(i);
107 	if (fver != 7) {
108 		foundfpu = 1;
109 		fpuname = fsrtoname(impl, vers, fver, fpbuf);
110 	} else
111 		fpuname = "no";
112 
113 	/* tell them what we have */
114 	node = ((struct romaux *)aux)->ra_node;
115 	clk = getpropint(node, "clock-frequency", 0);
116 	sprintf(cpu_model, "%s (%s @ %s MHz, %s FPU)",
117 	    getpropstring(node, "name"),
118 	    psrtoname(impl, vers, fver, iubuf), clockfreq(clk), fpuname);
119 	printf(": %s\n", cpu_model);
120 
121 	/*
122 	 * Fill in the cache info.  Note, vac-hwflush is spelled
123 	 * with an underscore on 4/75s.
124 	 */
125 	cacheinfo.c_totalsize = getpropint(node, "vac-size", 65536);
126 	cacheinfo.c_hwflush = getpropint(node, "vac_hwflush", 0) |
127 	    getpropint(node, "vac-hwflush", 0);
128 	cacheinfo.c_linesize = l = getpropint(node, "vac-linesize", 16);
129 	for (i = 0; (1 << i) < l; i++)
130 		/* void */;
131 	if ((1 << i) != l)
132 		panic("bad cache line size %d", l);
133 	cacheinfo.c_l2linesize = i;
134 	vactype = VAC_WRITETHROUGH;
135 
136 	/*
137 	 * Machines with "buserr-type" 1 have a bug in the cache
138 	 * chip that affects traps.  (I wish I knew more about this
139 	 * mysterious buserr-type variable....)
140 	 */
141 	if (getpropint(node, "buserr-type", 0) == 1) {
142 		kvm_uncache((caddr_t)trapbase, 1);
143 		printf("%s: cache chip bug; trap page uncached\n",
144 		    dev->dv_xname);
145 	}
146 }
147 
148 /*
149  * The following tables convert <IU impl, IU version, FPU version> triples
150  * into names for the CPU and FPU chip.  In most cases we do not need to
151  * inspect the FPU version to name the IU chip, but there is one exception
152  * (for Tsunami), and this makes the tables the same.
153  *
154  * The table contents (and much of the structure here) are from Guy Harris.
155  *
156  * NOTE: we have Sun-4m cpu types here, even though this only runs on the
157  * Sun-4c (yet)...
158  */
159 struct info {
160 	u_char	valid;
161 	u_char	iu_impl;
162 	u_char	iu_vers;
163 	u_char	fpu_vers;
164 	char	*name;
165 };
166 
167 #define	ANY	0xff	/* match any FPU version (or, later, IU version) */
168 
169 static struct info iu_types[] = {
170 	{ 1, 0x0, 0x0, ANY, "MB86900/1A or L64801" },
171 	{ 1, 0x1, 0x0, ANY, "RT601 or L64811 v1" },
172 	{ 1, 0x1, 0x1, ANY, "RT601 or L64811 v2" },
173 	{ 1, 0x1, 0x3, ANY, "RT611" },
174 	{ 1, 0x1, 0xf, ANY, "RT620" },
175 	{ 1, 0x2, 0x0, ANY, "B5010" },
176 	{ 1, 0x4, 0x0,   0, "TMS390Z50 v0" },
177 	{ 1, 0x4, 0x1,   0, "TMS390Z50 v1" },
178 	{ 1, 0x4, 0x1,   4, "TMS390S10" },
179 	{ 1, 0x5, 0x0, ANY, "MN10501" },
180 	{ 1, 0x9, 0x0, ANY, "W8601/8701 or MB86903" },
181 	{ 0 }
182 };
183 
184 static char *
185 psrtoname(impl, vers, fver, buf)
186 	register int impl, vers, fver;
187 	char *buf;
188 {
189 	register struct info *p;
190 
191 	for (p = iu_types; p->valid; p++)
192 		if (p->iu_impl == impl && p->iu_vers == vers &&
193 		    (p->fpu_vers == fver || p->fpu_vers == ANY))
194 			return (p->name);
195 
196 	/* Not found. */
197 	sprintf(buf, "IU impl 0x%x vers 0x%x", impl, vers);
198 	return (buf);
199 }
200 
201 /* NB: table order matters here; specific numbers must appear before ANY. */
202 static struct info fpu_types[] = {
203 	/*
204 	 * Vendor 0, IU Fujitsu0.
205 	 */
206 	{ 1, 0x0, ANY, 0, "MB86910 or WTL1164/5" },
207 	{ 1, 0x0, ANY, 1, "MB86911 or WTL1164/5" },
208 	{ 1, 0x0, ANY, 2, "L64802 or ACT8847" },
209 	{ 1, 0x0, ANY, 3, "WTL3170/2" },
210 	{ 1, 0x0, ANY, 4, "L64804" },
211 
212 	/*
213 	 * Vendor 1, IU ROSS0/1 or Pinnacle.
214 	 */
215 	{ 1, 0x1, 0xf, 0, "on-chip" },		/* Pinnacle */
216 	{ 1, 0x1, ANY, 0, "L64812 or ACT8847" },
217 	{ 1, 0x1, ANY, 1, "L64814" },
218 	{ 1, 0x1, ANY, 2, "TMS390C602A" },
219 	{ 1, 0x1, ANY, 3, "RT602 or WTL3171" },
220 
221 	/*
222 	 * Vendor 2, IU BIT0.
223 	 */
224 	{ 1, 0x2, ANY, 0, "B5010 or B5110/20 or B5210" },
225 
226 	/*
227 	 * Vendor 4, Texas Instruments.
228 	 */
229 	{ 1, 0x4, ANY, 0, "on-chip" },		/* Viking */
230 	{ 1, 0x4, ANY, 4, "on-chip" },		/* Tsunami */
231 
232 	/*
233 	 * Vendor 5, IU Matsushita0.
234 	 */
235 	{ 1, 0x5, ANY, 0, "on-chip" },
236 
237 	/*
238 	 * Vendor 9, Weitek.
239 	 */
240 	{ 1, 0x9, ANY, 3, "on-chip" },
241 
242 	{ 0 }
243 };
244 
245 static char *
246 fsrtoname(impl, vers, fver, buf)
247 	register int impl, vers, fver;
248 	char *buf;
249 {
250 	register struct info *p;
251 
252 	for (p = fpu_types; p->valid; p++)
253 		if (p->iu_impl == impl &&
254 		    (p->iu_vers == vers || p->iu_vers == ANY) &
255 		    p->fpu_vers == fver)
256 			return (p->name);
257 	sprintf(buf, "version %x", fver);
258 	return (buf);
259 }
260