This source file includes following definitions.
- find_mmu_num_contexts
- probe_cpu
- probe_vac
- probe_mmu
- probe_clock
- probe_auxio
- probe_devices
1
2
3
4
5
6
7 #include <linux/kernel.h>
8 #include <linux/mm.h>
9 #include <linux/sched.h>
10 #include <linux/string.h>
11
12 #include <asm/oplib.h>
13 #include <asm/vac-ops.h>
14 #include <asm/idprom.h>
15 #include <asm/machines.h>
16 #include <asm/io.h>
17 #include <asm/vaddrs.h>
18 #include <asm/param.h>
19 #include <asm/timer.h>
20 #include <asm/mostek.h>
21 #include <asm/auxio.h>
22 #include <asm/system.h>
23 #include <asm/mp.h>
24 #include <asm/mbus.h>
25
26
27
28
29
30
31
32 enum sparc_clock_type sp_clock_typ;
33 struct mostek48t02 *mstk48t02_regs = 0;
34 struct mostek48t08 *mstk48t08_regs = 0;
35 volatile unsigned int *master_l10_limit = 0;
36 volatile unsigned int *master_l10_counter = 0;
37 struct sun4m_timer_regs *sun4m_timers;
38
39 static char node_str[128];
40
41
42
43 struct cpu_iu_info {
44 int psr_impl;
45 int psr_vers;
46 char* cpu_name;
47 };
48
49 struct cpu_fp_info {
50 int psr_impl;
51 int fp_vers;
52 char* fp_name;
53 };
54
55
56
57
58 struct cpu_fp_info linux_sparc_fpu[] = {
59 { 0, 0, "Fujitsu MB86910 or Weitek WTL1164/5"},
60 { 0, 1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"},
61 { 0, 2, "LSI Logic L64802 or Texas Instruments ACT8847"},
62
63 { 0, 3, "Weitek WTL3170/2"},
64
65 { 0, 4, "Lsi Logic/Meiko L64804 or compatible"},
66 { 0, 5, "reserved"},
67 { 0, 6, "reserved"},
68 { 0, 7, "No FPU"},
69 { 1, 0, "ROSS HyperSparc combined IU/FPU"},
70 { 1, 1, "Lsi Logic L64814"},
71 { 1, 2, "Texas Instruments TMS390-C602A"},
72 { 1, 3, "Cypress CY7C602 FPU"},
73 { 1, 4, "reserved"},
74 { 1, 5, "reserved"},
75 { 1, 6, "reserved"},
76 { 1, 7, "No FPU"},
77 { 2, 0, "BIT B5010 or B5110/20 or B5210"},
78 { 2, 1, "reserved"},
79 { 2, 2, "reserved"},
80 { 2, 3, "reserved"},
81 { 2, 4, "reserved"},
82 { 2, 5, "reserved"},
83 { 2, 6, "reserved"},
84 { 2, 7, "No FPU"},
85
86 { 4, 0, "SuperSparc on-chip FPU"},
87
88 { 4, 4, "TI MicroSparc on chip FPU"},
89 { 5, 0, "Matsushita MN10501"},
90 { 5, 1, "reserved"},
91 { 5, 2, "reserved"},
92 { 5, 3, "reserved"},
93 { 5, 4, "reserved"},
94 { 5, 5, "reserved"},
95 { 5, 6, "reserved"},
96 { 5, 7, "No FPU"},
97 };
98
99 #define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info))
100
101 struct cpu_iu_info linux_sparc_chips[] = {
102
103 { 0, 0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"},
104
105 { 0, 4, "Fujitsu MB86904"},
106
107 { 1, 0, "LSI Logic Corporation - L64811"},
108
109 { 1, 1, "Cypress/ROSS CY7C601"},
110
111 { 1, 3, "Cypress/ROSS CY7C611"},
112
113 { 1, 0xf, "ROSS HyperSparc RT620"},
114 { 1, 0xe, "ROSS HyperSparc RT625"},
115
116
117 { 2, 0, "Bipolar Integrated Technology - B5010"},
118 { 3, 0, "LSI Logic Corporation - unknown-type"},
119 { 4, 0, "Texas Instruments, Inc. - SuperSparc 50"},
120
121 { 4, 1, "Texas Instruments, Inc. - MicroSparc"},
122 { 4, 2, "Texas Instruments, Inc. - MicroSparc II"},
123 { 4, 3, "Texas Instruments, Inc. - SuperSparc 51"},
124 { 4, 4, "Texas Instruments, Inc. - SuperSparc 61"},
125 { 4, 5, "Texas Instruments, Inc. - unknown"},
126 { 5, 0, "Matsushita - MN10501"},
127 { 6, 0, "Philips Corporation - unknown"},
128 { 7, 0, "Harvest VLSI Design Center, Inc. - unknown"},
129
130 { 8, 0, "Systems and Processes Engineering Corporation (SPEC)"},
131 { 9, 0, "Fujitsu #3"},
132 { 0xa, 0, "UNKNOWN CPU-VENDOR/TYPE"},
133 { 0xb, 0, "UNKNOWN CPU-VENDOR/TYPE"},
134 { 0xc, 0, "UNKNOWN CPU-VENDOR/TYPE"},
135 { 0xd, 0, "UNKNOWN CPU-VENDOR/TYPE"},
136 { 0xe, 0, "UNKNOWN CPU-VENDOR/TYPE"},
137 { 0xf, 0, "UNKNOWN CPU-VENDOR/TYPE"},
138 };
139
140 #define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
141
142 char *sparc_cpu_type[NCPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" };
143 char *sparc_fpu_type[NCPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" };
144
145 static inline int find_mmu_num_contexts(int cpu)
146 {
147 return prom_getintdefault(cpu, "mmu-nctx", 0x8);
148 }
149
150 unsigned int fsr_storage;
151
152 void
153 probe_cpu(void)
154 {
155 int psr_impl, psr_vers, fpu_vers;
156 int i, cpuid;
157
158 cpuid = get_cpuid();
159
160 psr_impl = ((get_psr()>>28)&0xf);
161 psr_vers = ((get_psr()>>24)&0xf);
162
163 fpu_vers = ((get_fsr()>>17)&0x7);
164
165 for(i = 0; i<NSPARCCHIPS; i++) {
166 if(linux_sparc_chips[i].psr_impl == psr_impl)
167 if(linux_sparc_chips[i].psr_vers == psr_vers) {
168 sparc_cpu_type[cpuid] = linux_sparc_chips[i].cpu_name;
169 break;
170 }
171 }
172
173 if(i==NSPARCCHIPS)
174 printk("DEBUG: psr.impl = 0x%x psr.vers = 0x%x\n", psr_impl,
175 psr_vers);
176
177 for(i = 0; i<NSPARCFPU; i++) {
178 if(linux_sparc_fpu[i].psr_impl == psr_impl)
179 if(linux_sparc_fpu[i].fp_vers == fpu_vers) {
180 sparc_fpu_type[cpuid] = linux_sparc_fpu[i].fp_name;
181 break;
182 }
183 }
184
185 if(i == NSPARCFPU) {
186 printk("DEBUG: psr.impl = 0x%x fsr.vers = 0x%x\n", psr_impl,
187 fpu_vers);
188 sparc_fpu_type[cpuid] = linux_sparc_fpu[31].fp_name;
189 }
190 }
191
192 void
193 probe_vac(void)
194 {
195 int propval;
196
197 sun4c_disable_vac();
198 sun4c_vacinfo.num_bytes = prom_getintdefault(prom_root_node,
199 "vac-size", 65536);
200 sun4c_vacinfo.linesize = prom_getintdefault(prom_root_node,
201 "vac-linesize", 16);
202 sun4c_vacinfo.num_lines =
203 (sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize);
204 switch(sun4c_vacinfo.linesize) {
205 case 16:
206 sun4c_vacinfo.log2lsize = 4;
207 break;
208 case 32:
209 sun4c_vacinfo.log2lsize = 5;
210 break;
211 default:
212 prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n",
213 sun4c_vacinfo.linesize);
214 prom_halt();
215 };
216
217 propval = prom_getintdefault(prom_root_node, "vac_hwflush", -1);
218 sun4c_vacinfo.do_hwflushes = (propval == -1 ?
219 prom_getintdefault(prom_root_node,
220 "vac-hwflush", 0) :
221 propval);
222
223 if(sun4c_vacinfo.num_bytes != 65536) {
224 prom_printf("WEIRD Sun4C VAC cache size, tell davem");
225 prom_halt();
226 }
227
228 sun4c_flush_all();
229 sun4c_enable_vac();
230 }
231
232 extern int num_segmaps, num_contexts;
233
234
235 void
236 probe_mmu(void)
237 {
238 int cpuid;
239
240
241 cpuid = get_cpuid();
242 switch(sparc_cpu_model) {
243 case sun4:
244 case sun4c:
245 case sun4e:
246
247 num_segmaps = prom_getintdefault(prom_root_node, "mmu-npmg", 128);
248 num_contexts = find_mmu_num_contexts(prom_root_node);
249 break;
250 default:
251 printk("cpu%d probe_mmu: sparc_cpu_model botch\n", cpuid);
252 break;
253 };
254 }
255
256
257 volatile unsigned int foo_limit;
258
259 void
260 probe_clock(int fchild)
261 {
262 register int node, type;
263 struct linux_prom_registers clk_reg[2];
264
265
266
267
268
269 node = 0;
270 if(sparc_cpu_model == sun4) {
271 printk("probe_clock: No SUN4 Clock/Timer support yet...\n");
272 return;
273 }
274 if(sparc_cpu_model == sun4c) node=prom_getchild(prom_root_node);
275 else
276 if(sparc_cpu_model == sun4m)
277 node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
278 type = 0;
279 sp_clock_typ = MSTK_INVALID;
280 for(;;) {
281 prom_getstring(node, "model", node_str, sizeof(node_str));
282 if(strcmp(node_str, "mk48t02") == 0) {
283 sp_clock_typ = MSTK48T02;
284 if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
285 printk("probe_clock: FAILED!\n");
286 halt();
287 }
288 prom_apply_obio_ranges(clk_reg, 1);
289
290 mstk48t02_regs = (struct mostek48t02 *)
291 sparc_alloc_io((void *) clk_reg[0].phys_addr,
292 (void *) 0, sizeof(*mstk48t02_regs),
293 "clock", 0x0, 0x0);
294 mstk48t08_regs = 0;
295 break;
296 }
297
298 if(strcmp(node_str, "mk48t08") == 0) {
299 sp_clock_typ = MSTK48T08;
300 if(prom_getproperty(node, "reg", (char *) clk_reg,
301 sizeof(clk_reg)) == -1) {
302 printk("probe_clock: FAILED!\n");
303 halt();
304 }
305 prom_apply_obio_ranges(clk_reg, 1);
306
307 mstk48t08_regs = (struct mostek48t08 *)
308 sparc_alloc_io((void *) clk_reg[0].phys_addr,
309 (void *) 0, sizeof(*mstk48t08_regs),
310 "clock", 0x0, 0x0);
311
312 mstk48t02_regs = &mstk48t08_regs->regs;
313 break;
314 }
315
316 node = prom_getsibling(node);
317 if(node == 0) {
318 printk("Aieee, could not find timer chip type\n");
319 return;
320 }
321 }
322
323 if(sparc_cpu_model == sun4c) {
324
325
326
327 sparc_alloc_io ((void *) SUN4C_TIMER_PHYSADDR, (void *) TIMER_VADDR,
328 sizeof (*SUN4C_TIMER_STRUCT), "timer", 0x0, 0x0);
329
330
331
332
333
334 SUN4C_TIMER_STRUCT->timer_limit10 = (((1000000/HZ) + 1) << 10);
335 master_l10_limit = &(SUN4C_TIMER_STRUCT->timer_limit10);
336 master_l10_counter = &(SUN4C_TIMER_STRUCT->cur_count10);
337 } else {
338 int reg_count;
339 struct linux_prom_registers cnt_regs[PROMREG_MAX];
340 int obio_node, cnt_node;
341
342 cnt_node = 0;
343 if((obio_node =
344 prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 ||
345 (obio_node = prom_getchild (obio_node)) == 0 ||
346 (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) {
347 printk ("Cannot find /obio/counter node\n");
348 prom_halt ();
349 }
350 reg_count = prom_getproperty(cnt_node, "reg",
351 (void *) cnt_regs, sizeof(cnt_regs));
352 reg_count = (reg_count/sizeof(struct linux_prom_registers));
353
354
355 prom_apply_obio_ranges(cnt_regs, reg_count);
356
357
358 sparc_alloc_io(cnt_regs[0].phys_addr, (void *) TIMER_VADDR,
359 PAGE_SIZE*NCPUS, "counters_percpu",
360 cnt_regs[0].which_io, 0x0);
361
362
363 sparc_alloc_io(cnt_regs[reg_count-1].phys_addr,
364 (void *) TIMER_VADDR+(NCPUS*PAGE_SIZE),
365 cnt_regs[reg_count-1].reg_size,
366 "counters_system", cnt_regs[reg_count-1].which_io, 0x0);
367 sun4m_timers = (struct sun4m_timer_regs *) TIMER_VADDR;
368
369
370 foo_limit = (volatile) sun4m_timers->l10_timer_limit;
371
372
373 master_l10_limit =
374 &(((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit);
375 master_l10_counter =
376 &(((struct sun4m_timer_regs *)TIMER_VADDR)->l10_cur_count);
377
378 ((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit =
379 (((1000000/HZ) + 1) << 10);
380 }
381 }
382
383
384 void
385 probe_auxio(void)
386 {
387 int node, auxio_nd;
388 struct linux_prom_registers auxregs[1];
389
390 node = prom_getchild(prom_root_node);
391 auxio_nd = prom_searchsiblings(node, "auxiliary-io");
392 if(!auxio_nd) {
393 node = prom_searchsiblings(node, "obio");
394 node = prom_getchild(node);
395 auxio_nd = prom_searchsiblings(node, "auxio");
396 if(!auxio_nd) {
397 printk("Cannot find auxio node, cannot continue...\n");
398 prom_halt();
399 }
400 }
401 prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs));
402 prom_apply_obio_ranges(auxregs, 0x1);
403
404 sparc_alloc_io(auxregs[0].phys_addr, (void *) AUXIO_VADDR,
405 auxregs[0].reg_size, "auxilliaryIO", auxregs[0].which_io, 0x0);
406 }
407
408 extern unsigned long probe_memory(void);
409 extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
410 unsigned int phys_bytes_of_ram, end_of_phys_memory;
411 extern void probe_mbus(void);
412
413
414 struct prom_cpuinfo linux_cpus[NCPUS];
415 int linux_num_cpus;
416
417 unsigned long
418 probe_devices(unsigned long mem_start)
419 {
420 int nd, i, prom_node_cpu, thismid;
421 int cpu_nds[NCPUS];
422 int cpu_ctr = 0;
423
424 prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str));
425 if(strcmp(node_str, "cpu") == 0) {
426 cpu_nds[0] = prom_root_node;
427 cpu_ctr++;
428 } else {
429 int scan;
430 scan = prom_getchild(prom_root_node);
431 nd = 0;
432 while((scan = prom_getsibling(scan)) != 0) {
433 prom_getstring(scan, "device_type", node_str, sizeof(node_str));
434 if(strcmp(node_str, "cpu") == 0) {
435 cpu_nds[cpu_ctr] = scan;
436 linux_cpus[cpu_ctr].prom_node = scan;
437 prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid));
438 linux_cpus[cpu_ctr].mid = thismid;
439 cpu_ctr++;
440 }
441 };
442 if(cpu_ctr == 0) {
443 printk("No CPU nodes found, cannot continue.\n");
444
445 halt();
446 }
447 printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
448 };
449 prom_node_cpu = cpu_nds[0];
450
451 linux_num_cpus = cpu_ctr;
452 for(i=0; i<cpu_ctr; i++) {
453 prom_getstring(cpu_nds[i], "name", node_str, sizeof(node_str));
454 #if 0
455 printk("cpu%d: %s \n", i, node_str);
456 #endif
457 }
458
459 probe_cpu();
460 probe_auxio();
461 if(sparc_cpu_model != sun4c) probe_mbus();
462
463 return mem_start;
464 }