xref: /original-bsd/sys/sparc/sparc/cpu.c (revision cf2061f8)
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.3 (Berkeley) 09/30/93
17  *
18  * from: $Header: cpu.c,v 1.16.1.1 93/09/30 22:38:50 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 	printf("%s: %d byte write-through, %d bytes/line, %cw flush ",
148 	    dev->dv_xname, cacheinfo.c_totalsize, l,
149 	    cacheinfo.c_hwflush ? 'h' : 's');
150 	cache_enable();
151 }
152 
153 /*
154  * The following tables convert <IU impl, IU version, FPU version> triples
155  * into names for the CPU and FPU chip.  In most cases we do not need to
156  * inspect the FPU version to name the IU chip, but there is one exception
157  * (for Tsunami), and this makes the tables the same.
158  *
159  * The table contents (and much of the structure here) are from Guy Harris.
160  *
161  * NOTE: we have Sun-4m cpu types here, even though this only runs on the
162  * Sun-4c (yet)...
163  */
164 struct info {
165 	u_char	valid;
166 	u_char	iu_impl;
167 	u_char	iu_vers;
168 	u_char	fpu_vers;
169 	char	*name;
170 };
171 
172 #define	ANY	0xff	/* match any FPU version (or, later, IU version) */
173 
174 static struct info iu_types[] = {
175 	{ 1, 0x0, 0x0, ANY, "MB86900/1A or L64801" },
176 	{ 1, 0x1, 0x0, ANY, "RT601 or L64811 v1" },
177 	{ 1, 0x1, 0x1, ANY, "RT601 or L64811 v2" },
178 	{ 1, 0x1, 0x3, ANY, "RT611" },
179 	{ 1, 0x1, 0xf, ANY, "RT620" },
180 	{ 1, 0x2, 0x0, ANY, "B5010" },
181 	{ 1, 0x4, 0x0,   0, "TMS390Z50 v0" },
182 	{ 1, 0x4, 0x1,   0, "TMS390Z50 v1" },
183 	{ 1, 0x4, 0x1,   4, "TMS390S10" },
184 	{ 1, 0x5, 0x0, ANY, "MN10501" },
185 	{ 1, 0x9, 0x0, ANY, "W8601/8701 or MB86903" },
186 	{ 0 }
187 };
188 
189 static char *
190 psrtoname(impl, vers, fver, buf)
191 	register int impl, vers, fver;
192 	char *buf;
193 {
194 	register struct info *p;
195 
196 	for (p = iu_types; p->valid; p++)
197 		if (p->iu_impl == impl && p->iu_vers == vers &&
198 		    (p->fpu_vers == fver || p->fpu_vers == ANY))
199 			return (p->name);
200 
201 	/* Not found. */
202 	sprintf(buf, "IU impl 0x%x vers 0x%x", impl, vers);
203 	return (buf);
204 }
205 
206 /* NB: table order matters here; specific numbers must appear before ANY. */
207 static struct info fpu_types[] = {
208 	/*
209 	 * Vendor 0, IU Fujitsu0.
210 	 */
211 	{ 1, 0x0, ANY, 0, "MB86910 or WTL1164/5" },
212 	{ 1, 0x0, ANY, 1, "MB86911 or WTL1164/5" },
213 	{ 1, 0x0, ANY, 2, "L64802 or ACT8847" },
214 	{ 1, 0x0, ANY, 3, "WTL3170/2" },
215 	{ 1, 0x0, ANY, 4, "L64804" },
216 
217 	/*
218 	 * Vendor 1, IU ROSS0/1.
219 	 */
220 	{ 1, 0x1, ANY, 0, "L64812 or ACT8847" },
221 	{ 1, 0x1, ANY, 1, "L64814" },
222 	{ 1, 0x1, ANY, 2, "TMS390C602A" },
223 	{ 1, 0x1, ANY, 3, "RT602 or WTL3171" },
224 
225 	/*
226 	 * Vendor 2, IU BIT0.
227 	 */
228 	{ 1, 0x2, ANY, 0, "B5010 or B5110/20 or B5210" },
229 
230 	/*
231 	 * Vendor 4, Texas Instruments.
232 	 */
233 	{ 1, 0x4, ANY, 0, "on-chip" },		/* Viking */
234 	{ 1, 0x4, ANY, 4, "on-chip" },		/* Tsunami */
235 
236 	/*
237 	 * Vendor 5, IU Matsushita0.
238 	 */
239 	{ 1, 0x5, ANY, 0, "on-chip" },
240 
241 	/*
242 	 * Vendor 9, Weitek.
243 	 */
244 	{ 1, 0x9, ANY, 3, "on-chip" },
245 
246 	{ 0 }
247 };
248 
249 static char *
250 fsrtoname(impl, vers, fver, buf)
251 	register int impl, vers, fver;
252 	char *buf;
253 {
254 	register struct info *p;
255 
256 	for (p = fpu_types; p->valid; p++)
257 		if (p->iu_impl == impl &&
258 		    (p->iu_vers == vers || p->iu_vers == ANY) &
259 		    p->fpu_vers == fver)
260 			return (p->name);
261 	sprintf(buf, "version %x", fver);
262 	return (buf);
263 }
264