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
cpu_attach(parent,dev,aux)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 *
psrtoname(impl,vers,fver,buf)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 *
fsrtoname(impl,vers,fver,buf)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