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