diff options
Diffstat (limited to 'arch/ppc/platforms/prep_setup.c')
-rw-r--r-- | arch/ppc/platforms/prep_setup.c | 1043 |
1 files changed, 0 insertions, 1043 deletions
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c deleted file mode 100644 index 465b658c927d..000000000000 --- a/arch/ppc/platforms/prep_setup.c +++ /dev/null | |||
@@ -1,1043 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1995 Linus Torvalds | ||
3 | * Adapted from 'alpha' version by Gary Thomas | ||
4 | * Modified by Cort Dougan (cort@cs.nmt.edu) | ||
5 | * | ||
6 | * Support for PReP (Motorola MTX/MVME) | ||
7 | * by Troy Benjegerdes (hozer@drgw.net) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * bootup setup stuff.. | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/stddef.h> | ||
21 | #include <linux/unistd.h> | ||
22 | #include <linux/ptrace.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/user.h> | ||
25 | #include <linux/a.out.h> | ||
26 | #include <linux/screen_info.h> | ||
27 | #include <linux/major.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/reboot.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/initrd.h> | ||
32 | #include <linux/ioport.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/timex.h> | ||
35 | #include <linux/pci.h> | ||
36 | #include <linux/seq_file.h> | ||
37 | #include <linux/root_dev.h> | ||
38 | |||
39 | #include <asm/sections.h> | ||
40 | #include <asm/mmu.h> | ||
41 | #include <asm/processor.h> | ||
42 | #include <asm/residual.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/pgtable.h> | ||
45 | #include <asm/cache.h> | ||
46 | #include <asm/dma.h> | ||
47 | #include <asm/machdep.h> | ||
48 | #include <asm/mc146818rtc.h> | ||
49 | #include <asm/mk48t59.h> | ||
50 | #include <asm/prep_nvram.h> | ||
51 | #include <asm/raven.h> | ||
52 | #include <asm/vga.h> | ||
53 | #include <asm/time.h> | ||
54 | #include <asm/mpc10x.h> | ||
55 | #include <asm/i8259.h> | ||
56 | #include <asm/open_pic.h> | ||
57 | #include <asm/pci-bridge.h> | ||
58 | #include <asm/todc.h> | ||
59 | |||
60 | /* prep registers for L2 */ | ||
61 | #define CACHECRBA 0x80000823 /* Cache configuration register address */ | ||
62 | #define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */ | ||
63 | #define L2CACHE_512KB 0x00 /* 512KB */ | ||
64 | #define L2CACHE_256KB 0x01 /* 256KB */ | ||
65 | #define L2CACHE_1MB 0x02 /* 1MB */ | ||
66 | #define L2CACHE_NONE 0x03 /* NONE */ | ||
67 | #define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */ | ||
68 | |||
69 | TODC_ALLOC(); | ||
70 | |||
71 | extern unsigned char prep_nvram_read_val(int addr); | ||
72 | extern void prep_nvram_write_val(int addr, | ||
73 | unsigned char val); | ||
74 | extern unsigned char rs_nvram_read_val(int addr); | ||
75 | extern void rs_nvram_write_val(int addr, | ||
76 | unsigned char val); | ||
77 | extern void ibm_prep_init(void); | ||
78 | |||
79 | extern void prep_find_bridges(void); | ||
80 | |||
81 | int _prep_type; | ||
82 | |||
83 | extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
84 | extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
85 | extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
86 | extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
87 | extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
88 | |||
89 | |||
90 | #define cached_21 (((char *)(ppc_cached_irq_mask))[3]) | ||
91 | #define cached_A1 (((char *)(ppc_cached_irq_mask))[2]) | ||
92 | |||
93 | extern PTE *Hash, *Hash_end; | ||
94 | extern unsigned long Hash_size, Hash_mask; | ||
95 | extern int probingmem; | ||
96 | extern unsigned long loops_per_jiffy; | ||
97 | |||
98 | /* useful ISA ports */ | ||
99 | #define PREP_SYSCTL 0x81c | ||
100 | /* present in the IBM reference design; possibly identical in Mot boxes: */ | ||
101 | #define PREP_IBM_SIMM_ID 0x803 /* SIMM size: 32 or 8 MiB */ | ||
102 | #define PREP_IBM_SIMM_PRESENCE 0x804 | ||
103 | #define PREP_IBM_EQUIPMENT 0x80c | ||
104 | #define PREP_IBM_L2INFO 0x80d | ||
105 | #define PREP_IBM_PM1 0x82a /* power management register 1 */ | ||
106 | #define PREP_IBM_PLANAR 0x852 /* planar ID - identifies the motherboard */ | ||
107 | #define PREP_IBM_DISP 0x8c0 /* 4-digit LED display */ | ||
108 | |||
109 | /* Equipment Present Register masks: */ | ||
110 | #define PREP_IBM_EQUIPMENT_RESERVED 0x80 | ||
111 | #define PREP_IBM_EQUIPMENT_SCSIFUSE 0x40 | ||
112 | #define PREP_IBM_EQUIPMENT_L2_COPYBACK 0x08 | ||
113 | #define PREP_IBM_EQUIPMENT_L2_256 0x04 | ||
114 | #define PREP_IBM_EQUIPMENT_CPU 0x02 | ||
115 | #define PREP_IBM_EQUIPMENT_L2 0x01 | ||
116 | |||
117 | /* planar ID values: */ | ||
118 | /* Sandalfoot/Sandalbow (6015/7020) */ | ||
119 | #define PREP_IBM_SANDALFOOT 0xfc | ||
120 | /* Woodfield, Thinkpad 850/860 (6042/7249) */ | ||
121 | #define PREP_IBM_THINKPAD 0xff /* planar ID unimplemented */ | ||
122 | /* PowerSeries 830/850 (6050/6070) */ | ||
123 | #define PREP_IBM_CAROLINA_IDE_0 0xf0 | ||
124 | #define PREP_IBM_CAROLINA_IDE_1 0xf1 | ||
125 | #define PREP_IBM_CAROLINA_IDE_2 0xf2 | ||
126 | #define PREP_IBM_CAROLINA_IDE_3 0xf3 | ||
127 | /* 7248-43P */ | ||
128 | #define PREP_IBM_CAROLINA_SCSI_0 0xf4 | ||
129 | #define PREP_IBM_CAROLINA_SCSI_1 0xf5 | ||
130 | #define PREP_IBM_CAROLINA_SCSI_2 0xf6 | ||
131 | #define PREP_IBM_CAROLINA_SCSI_3 0xf7 /* missing from Carolina Tech Spec */ | ||
132 | /* Tiger1 (7043-140) */ | ||
133 | #define PREP_IBM_TIGER1_133 0xd1 | ||
134 | #define PREP_IBM_TIGER1_166 0xd2 | ||
135 | #define PREP_IBM_TIGER1_180 0xd3 | ||
136 | #define PREP_IBM_TIGER1_xxx 0xd4 /* unknown, but probably exists */ | ||
137 | #define PREP_IBM_TIGER1_333 0xd5 /* missing from Tiger Tech Spec */ | ||
138 | |||
139 | /* setup_ibm_pci: | ||
140 | * set Motherboard_map_name, Motherboard_map, Motherboard_routes. | ||
141 | * return 8259 edge/level masks. | ||
142 | */ | ||
143 | void (*setup_ibm_pci)(char *irq_lo, char *irq_hi); | ||
144 | |||
145 | extern char *Motherboard_map_name; /* for use in *_cpuinfo */ | ||
146 | |||
147 | /* | ||
148 | * As found in the PReP reference implementation. | ||
149 | * Used by Thinkpad, Sandalfoot (6015/7020), and all Motorola PReP. | ||
150 | */ | ||
151 | static void __init | ||
152 | prep_gen_enable_l2(void) | ||
153 | { | ||
154 | outb(inb(PREP_SYSCTL) | 0x3, PREP_SYSCTL); | ||
155 | } | ||
156 | |||
157 | /* Used by Carolina and Tiger1 */ | ||
158 | static void __init | ||
159 | prep_carolina_enable_l2(void) | ||
160 | { | ||
161 | outb(inb(PREP_SYSCTL) | 0xc0, PREP_SYSCTL); | ||
162 | } | ||
163 | |||
164 | /* cpuinfo code common to all IBM PReP */ | ||
165 | static void | ||
166 | prep_ibm_cpuinfo(struct seq_file *m) | ||
167 | { | ||
168 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
169 | |||
170 | seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name); | ||
171 | |||
172 | seq_printf(m, "upgrade cpu\t: "); | ||
173 | if (equip_reg & PREP_IBM_EQUIPMENT_CPU) { | ||
174 | seq_printf(m, "not "); | ||
175 | } | ||
176 | seq_printf(m, "present\n"); | ||
177 | |||
178 | /* print info about the SCSI fuse */ | ||
179 | seq_printf(m, "scsi fuse\t: "); | ||
180 | if (equip_reg & PREP_IBM_EQUIPMENT_SCSIFUSE) | ||
181 | seq_printf(m, "ok"); | ||
182 | else | ||
183 | seq_printf(m, "bad"); | ||
184 | seq_printf(m, "\n"); | ||
185 | |||
186 | /* print info about SIMMs */ | ||
187 | if (have_residual_data) { | ||
188 | int i; | ||
189 | seq_printf(m, "simms\t\t: "); | ||
190 | for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { | ||
191 | if (res->Memories[i].SIMMSize != 0) | ||
192 | seq_printf(m, "%d:%ldMiB ", i, | ||
193 | (res->Memories[i].SIMMSize > 1024) ? | ||
194 | res->Memories[i].SIMMSize>>20 : | ||
195 | res->Memories[i].SIMMSize); | ||
196 | } | ||
197 | seq_printf(m, "\n"); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static int | ||
202 | prep_gen_cpuinfo(struct seq_file *m) | ||
203 | { | ||
204 | prep_ibm_cpuinfo(m); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int | ||
209 | prep_sandalfoot_cpuinfo(struct seq_file *m) | ||
210 | { | ||
211 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
212 | |||
213 | prep_ibm_cpuinfo(m); | ||
214 | |||
215 | /* report amount and type of L2 cache present */ | ||
216 | seq_printf(m, "L2 cache\t: "); | ||
217 | if (equip_reg & PREP_IBM_EQUIPMENT_L2) { | ||
218 | seq_printf(m, "not present"); | ||
219 | } else { | ||
220 | if (equip_reg & PREP_IBM_EQUIPMENT_L2_256) | ||
221 | seq_printf(m, "256KiB"); | ||
222 | else | ||
223 | seq_printf(m, "unknown size"); | ||
224 | |||
225 | if (equip_reg & PREP_IBM_EQUIPMENT_L2_COPYBACK) | ||
226 | seq_printf(m, ", copy-back"); | ||
227 | else | ||
228 | seq_printf(m, ", write-through"); | ||
229 | } | ||
230 | seq_printf(m, "\n"); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int | ||
236 | prep_thinkpad_cpuinfo(struct seq_file *m) | ||
237 | { | ||
238 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
239 | char *cpubus_speed, *pci_speed; | ||
240 | |||
241 | prep_ibm_cpuinfo(m); | ||
242 | |||
243 | /* report amount and type of L2 cache present */ | ||
244 | seq_printf(m, "l2 cache\t: "); | ||
245 | if ((equip_reg & 0x1) == 0) { | ||
246 | switch ((equip_reg & 0xc) >> 2) { | ||
247 | case 0x0: | ||
248 | seq_printf(m, "128KiB look-aside 2-way write-through\n"); | ||
249 | break; | ||
250 | case 0x1: | ||
251 | seq_printf(m, "512KiB look-aside direct-mapped write-back\n"); | ||
252 | break; | ||
253 | case 0x2: | ||
254 | seq_printf(m, "256KiB look-aside 2-way write-through\n"); | ||
255 | break; | ||
256 | case 0x3: | ||
257 | seq_printf(m, "256KiB look-aside direct-mapped write-back\n"); | ||
258 | break; | ||
259 | } | ||
260 | } else { | ||
261 | seq_printf(m, "not present\n"); | ||
262 | } | ||
263 | |||
264 | /* report bus speeds because we can */ | ||
265 | if ((equip_reg & 0x80) == 0) { | ||
266 | switch ((equip_reg & 0x30) >> 4) { | ||
267 | case 0x1: | ||
268 | cpubus_speed = "50"; | ||
269 | pci_speed = "25"; | ||
270 | break; | ||
271 | case 0x3: | ||
272 | cpubus_speed = "66"; | ||
273 | pci_speed = "33"; | ||
274 | break; | ||
275 | default: | ||
276 | cpubus_speed = "unknown"; | ||
277 | pci_speed = "unknown"; | ||
278 | break; | ||
279 | } | ||
280 | } else { | ||
281 | switch ((equip_reg & 0x30) >> 4) { | ||
282 | case 0x1: | ||
283 | cpubus_speed = "25"; | ||
284 | pci_speed = "25"; | ||
285 | break; | ||
286 | case 0x2: | ||
287 | cpubus_speed = "60"; | ||
288 | pci_speed = "30"; | ||
289 | break; | ||
290 | case 0x3: | ||
291 | cpubus_speed = "33"; | ||
292 | pci_speed = "33"; | ||
293 | break; | ||
294 | default: | ||
295 | cpubus_speed = "unknown"; | ||
296 | pci_speed = "unknown"; | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | seq_printf(m, "60x bus\t\t: %sMHz\n", cpubus_speed); | ||
301 | seq_printf(m, "pci bus\t\t: %sMHz\n", pci_speed); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int | ||
307 | prep_carolina_cpuinfo(struct seq_file *m) | ||
308 | { | ||
309 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
310 | |||
311 | prep_ibm_cpuinfo(m); | ||
312 | |||
313 | /* report amount and type of L2 cache present */ | ||
314 | seq_printf(m, "l2 cache\t: "); | ||
315 | if ((equip_reg & 0x1) == 0) { | ||
316 | unsigned int l2_reg = inb(PREP_IBM_L2INFO); | ||
317 | |||
318 | /* L2 size */ | ||
319 | if ((l2_reg & 0x60) == 0) | ||
320 | seq_printf(m, "256KiB"); | ||
321 | else if ((l2_reg & 0x60) == 0x20) | ||
322 | seq_printf(m, "512KiB"); | ||
323 | else | ||
324 | seq_printf(m, "unknown size"); | ||
325 | |||
326 | /* L2 type */ | ||
327 | if ((l2_reg & 0x3) == 0) | ||
328 | seq_printf(m, ", async"); | ||
329 | else if ((l2_reg & 0x3) == 1) | ||
330 | seq_printf(m, ", sync"); | ||
331 | else | ||
332 | seq_printf(m, ", unknown type"); | ||
333 | |||
334 | seq_printf(m, "\n"); | ||
335 | } else { | ||
336 | seq_printf(m, "not present\n"); | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int | ||
343 | prep_tiger1_cpuinfo(struct seq_file *m) | ||
344 | { | ||
345 | unsigned int l2_reg = inb(PREP_IBM_L2INFO); | ||
346 | |||
347 | prep_ibm_cpuinfo(m); | ||
348 | |||
349 | /* report amount and type of L2 cache present */ | ||
350 | seq_printf(m, "l2 cache\t: "); | ||
351 | if ((l2_reg & 0xf) == 0xf) { | ||
352 | seq_printf(m, "not present\n"); | ||
353 | } else { | ||
354 | if (l2_reg & 0x8) | ||
355 | seq_printf(m, "async, "); | ||
356 | else | ||
357 | seq_printf(m, "sync burst, "); | ||
358 | |||
359 | if (l2_reg & 0x4) | ||
360 | seq_printf(m, "parity, "); | ||
361 | else | ||
362 | seq_printf(m, "no parity, "); | ||
363 | |||
364 | switch (l2_reg & 0x3) { | ||
365 | case 0x0: | ||
366 | seq_printf(m, "256KiB\n"); | ||
367 | break; | ||
368 | case 0x1: | ||
369 | seq_printf(m, "512KiB\n"); | ||
370 | break; | ||
371 | case 0x2: | ||
372 | seq_printf(m, "1MiB\n"); | ||
373 | break; | ||
374 | default: | ||
375 | seq_printf(m, "unknown size\n"); | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | |||
384 | /* Used by all Motorola PReP */ | ||
385 | static int | ||
386 | prep_mot_cpuinfo(struct seq_file *m) | ||
387 | { | ||
388 | unsigned int cachew = *((unsigned char *)CACHECRBA); | ||
389 | |||
390 | seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name); | ||
391 | |||
392 | /* report amount and type of L2 cache present */ | ||
393 | seq_printf(m, "l2 cache\t: "); | ||
394 | switch (cachew & L2CACHE_MASK) { | ||
395 | case L2CACHE_512KB: | ||
396 | seq_printf(m, "512KiB"); | ||
397 | break; | ||
398 | case L2CACHE_256KB: | ||
399 | seq_printf(m, "256KiB"); | ||
400 | break; | ||
401 | case L2CACHE_1MB: | ||
402 | seq_printf(m, "1MiB"); | ||
403 | break; | ||
404 | case L2CACHE_NONE: | ||
405 | seq_printf(m, "none\n"); | ||
406 | goto no_l2; | ||
407 | break; | ||
408 | default: | ||
409 | seq_printf(m, "%x\n", cachew); | ||
410 | } | ||
411 | |||
412 | seq_printf(m, ", parity %s", | ||
413 | (cachew & L2CACHE_PARITY)? "enabled" : "disabled"); | ||
414 | |||
415 | seq_printf(m, " SRAM:"); | ||
416 | |||
417 | switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) { | ||
418 | case 1: seq_printf(m, "synchronous, parity, flow-through\n"); | ||
419 | break; | ||
420 | case 2: seq_printf(m, "asynchronous, no parity\n"); | ||
421 | break; | ||
422 | case 3: seq_printf(m, "asynchronous, parity\n"); | ||
423 | break; | ||
424 | default:seq_printf(m, "synchronous, pipelined, no parity\n"); | ||
425 | break; | ||
426 | } | ||
427 | |||
428 | no_l2: | ||
429 | /* print info about SIMMs */ | ||
430 | if (have_residual_data) { | ||
431 | int i; | ||
432 | seq_printf(m, "simms\t\t: "); | ||
433 | for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { | ||
434 | if (res->Memories[i].SIMMSize != 0) | ||
435 | seq_printf(m, "%d:%ldM ", i, | ||
436 | (res->Memories[i].SIMMSize > 1024) ? | ||
437 | res->Memories[i].SIMMSize>>20 : | ||
438 | res->Memories[i].SIMMSize); | ||
439 | } | ||
440 | seq_printf(m, "\n"); | ||
441 | } | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static void | ||
447 | prep_restart(char *cmd) | ||
448 | { | ||
449 | #define PREP_SP92 0x92 /* Special Port 92 */ | ||
450 | local_irq_disable(); /* no interrupts */ | ||
451 | |||
452 | /* set exception prefix high - to the prom */ | ||
453 | _nmask_and_or_msr(0, MSR_IP); | ||
454 | |||
455 | /* make sure bit 0 (reset) is a 0 */ | ||
456 | outb( inb(PREP_SP92) & ~1L , PREP_SP92); | ||
457 | /* signal a reset to system control port A - soft reset */ | ||
458 | outb( inb(PREP_SP92) | 1 , PREP_SP92); | ||
459 | |||
460 | while ( 1 ) ; | ||
461 | /* not reached */ | ||
462 | #undef PREP_SP92 | ||
463 | } | ||
464 | |||
465 | static void | ||
466 | prep_halt(void) | ||
467 | { | ||
468 | local_irq_disable(); /* no interrupts */ | ||
469 | |||
470 | /* set exception prefix high - to the prom */ | ||
471 | _nmask_and_or_msr(0, MSR_IP); | ||
472 | |||
473 | while ( 1 ) ; | ||
474 | /* not reached */ | ||
475 | } | ||
476 | |||
477 | /* Carrera is the power manager in the Thinkpads. Unfortunately not much is | ||
478 | * known about it, so we can't power down. | ||
479 | */ | ||
480 | static void | ||
481 | prep_carrera_poweroff(void) | ||
482 | { | ||
483 | prep_halt(); | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * On most IBM PReP's, power management is handled by a Signetics 87c750 | ||
488 | * behind the Utah component on the ISA bus. To access the 750 you must write | ||
489 | * a series of nibbles to port 0x82a (decoded by the Utah). This is described | ||
490 | * somewhat in the IBM Carolina Technical Specification. | ||
491 | * -Hollis | ||
492 | */ | ||
493 | static void | ||
494 | utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value) | ||
495 | { | ||
496 | /* | ||
497 | * byte1: 0 0 0 1 0 d a5 a4 | ||
498 | * byte2: 0 0 0 1 a3 a2 a1 a0 | ||
499 | * | ||
500 | * d = the bit's value, enabled or disabled | ||
501 | * (a5 a4 a3) = the byte number, minus 20 | ||
502 | * (a2 a1 a0) = the bit number | ||
503 | * | ||
504 | * example: set the 5th bit of byte 21 (21.5) | ||
505 | * a5 a4 a3 = 001 (byte 1) | ||
506 | * a2 a1 a0 = 101 (bit 5) | ||
507 | * | ||
508 | * byte1 = 0001 0100 (0x14) | ||
509 | * byte2 = 0001 1101 (0x1d) | ||
510 | */ | ||
511 | unsigned char byte1=0x10, byte2=0x10; | ||
512 | |||
513 | /* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */ | ||
514 | bytenum -= 20; | ||
515 | |||
516 | byte1 |= (!!value) << 2; /* set d */ | ||
517 | byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */ | ||
518 | |||
519 | byte2 |= (bytenum & 0x1) << 3; /* set a3 */ | ||
520 | byte2 |= bitnum & 0x7; /* set a2, a1, a0 */ | ||
521 | |||
522 | outb(byte1, PREP_IBM_PM1); /* first nibble */ | ||
523 | mb(); | ||
524 | udelay(100); /* important: let controller recover */ | ||
525 | |||
526 | outb(byte2, PREP_IBM_PM1); /* second nibble */ | ||
527 | mb(); | ||
528 | udelay(100); /* important: let controller recover */ | ||
529 | } | ||
530 | |||
531 | static void | ||
532 | prep_sig750_poweroff(void) | ||
533 | { | ||
534 | /* tweak the power manager found in most IBM PRePs (except Thinkpads) */ | ||
535 | |||
536 | local_irq_disable(); | ||
537 | /* set exception prefix high - to the prom */ | ||
538 | _nmask_and_or_msr(0, MSR_IP); | ||
539 | |||
540 | utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */ | ||
541 | |||
542 | while (1) ; | ||
543 | /* not reached */ | ||
544 | } | ||
545 | |||
546 | static int | ||
547 | prep_show_percpuinfo(struct seq_file *m, int i) | ||
548 | { | ||
549 | /* PREP's without residual data will give incorrect values here */ | ||
550 | seq_printf(m, "clock\t\t: "); | ||
551 | if (have_residual_data) | ||
552 | seq_printf(m, "%ldMHz\n", | ||
553 | (res->VitalProductData.ProcessorHz > 1024) ? | ||
554 | res->VitalProductData.ProcessorHz / 1000000 : | ||
555 | res->VitalProductData.ProcessorHz); | ||
556 | else | ||
557 | seq_printf(m, "???\n"); | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * Fill out screen_info according to the residual data. This allows us to use | ||
564 | * at least vesafb. | ||
565 | */ | ||
566 | static void __init | ||
567 | prep_init_vesa(void) | ||
568 | { | ||
569 | #if (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA16_MODULE) || \ | ||
570 | defined(CONFIG_FB_VESA)) | ||
571 | PPC_DEVICE *vgadev = NULL; | ||
572 | |||
573 | if (have_residual_data) | ||
574 | vgadev = residual_find_device(~0, NULL, DisplayController, | ||
575 | SVGAController, -1, 0); | ||
576 | |||
577 | if (vgadev != NULL) { | ||
578 | PnP_TAG_PACKET *pkt; | ||
579 | |||
580 | pkt = PnP_find_large_vendor_packet( | ||
581 | (unsigned char *)&res->DevicePnPHeap[vgadev->AllocatedOffset], | ||
582 | 0x04, 0); /* 0x04 = Display Tag */ | ||
583 | if (pkt != NULL) { | ||
584 | unsigned char *ptr = (unsigned char *)pkt; | ||
585 | |||
586 | if (ptr[4]) { | ||
587 | /* graphics mode */ | ||
588 | screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB; | ||
589 | |||
590 | screen_info.lfb_depth = ptr[4] * 8; | ||
591 | |||
592 | screen_info.lfb_width = swab16(*(short *)(ptr+6)); | ||
593 | screen_info.lfb_height = swab16(*(short *)(ptr+8)); | ||
594 | screen_info.lfb_linelength = swab16(*(short *)(ptr+10)); | ||
595 | |||
596 | screen_info.lfb_base = swab32(*(long *)(ptr+12)); | ||
597 | screen_info.lfb_size = swab32(*(long *)(ptr+20)) / 65536; | ||
598 | } | ||
599 | } | ||
600 | } | ||
601 | #endif | ||
602 | } | ||
603 | |||
604 | /* | ||
605 | * Set DBAT 2 to access 0x80000000 so early progress messages will work | ||
606 | */ | ||
607 | static __inline__ void | ||
608 | prep_set_bat(void) | ||
609 | { | ||
610 | /* wait for all outstanding memory access to complete */ | ||
611 | mb(); | ||
612 | |||
613 | /* setup DBATs */ | ||
614 | mtspr(SPRN_DBAT2U, 0x80001ffe); | ||
615 | mtspr(SPRN_DBAT2L, 0x8000002a); | ||
616 | |||
617 | /* wait for updates */ | ||
618 | mb(); | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | * IBM 3-digit status LED | ||
623 | */ | ||
624 | static unsigned int ibm_statusled_base; | ||
625 | |||
626 | static void | ||
627 | ibm_statusled_progress(char *s, unsigned short hex); | ||
628 | |||
629 | static int | ||
630 | ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2, | ||
631 | void * dummy3) | ||
632 | { | ||
633 | ibm_statusled_progress(NULL, 0x505); /* SOS */ | ||
634 | return NOTIFY_DONE; | ||
635 | } | ||
636 | |||
637 | static struct notifier_block ibm_statusled_block = { | ||
638 | ibm_statusled_panic, | ||
639 | NULL, | ||
640 | INT_MAX /* try to do it first */ | ||
641 | }; | ||
642 | |||
643 | static void | ||
644 | ibm_statusled_progress(char *s, unsigned short hex) | ||
645 | { | ||
646 | static int notifier_installed; | ||
647 | /* | ||
648 | * Progress uses 4 digits and we have only 3. So, we map 0xffff to | ||
649 | * 0xfff for display switch off. Out of range values are mapped to | ||
650 | * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes. | ||
651 | * Install the panic notifier when the display is first switched off. | ||
652 | */ | ||
653 | if (hex == 0xffff) { | ||
654 | hex = 0xfff; | ||
655 | if (!notifier_installed) { | ||
656 | ++notifier_installed; | ||
657 | atomic_notifier_chain_register(&panic_notifier_list, | ||
658 | &ibm_statusled_block); | ||
659 | } | ||
660 | } | ||
661 | else | ||
662 | if (hex > 0xfff) | ||
663 | hex = 0xeff; | ||
664 | |||
665 | mb(); | ||
666 | outw(hex, ibm_statusled_base); | ||
667 | } | ||
668 | |||
669 | static void __init | ||
670 | ibm_statusled_init(void) | ||
671 | { | ||
672 | /* | ||
673 | * The IBM 3-digit LED display is specified in the residual data | ||
674 | * as an operator panel device, type "System Status LED". Find | ||
675 | * that device and determine its address. We validate all the | ||
676 | * other parameters on the off-chance another, similar device | ||
677 | * exists. | ||
678 | */ | ||
679 | if (have_residual_data) { | ||
680 | PPC_DEVICE *led; | ||
681 | PnP_TAG_PACKET *pkt; | ||
682 | |||
683 | led = residual_find_device(~0, NULL, SystemPeripheral, | ||
684 | OperatorPanel, SystemStatusLED, 0); | ||
685 | if (!led) | ||
686 | return; | ||
687 | |||
688 | pkt = PnP_find_packet((unsigned char *) | ||
689 | &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0); | ||
690 | if (!pkt) | ||
691 | return; | ||
692 | |||
693 | if (pkt->S8_Pack.IOInfo != ISAAddr16bit) | ||
694 | return; | ||
695 | if (*(unsigned short *)pkt->S8_Pack.RangeMin != | ||
696 | *(unsigned short *)pkt->S8_Pack.RangeMax) | ||
697 | return; | ||
698 | if (pkt->S8_Pack.IOAlign != 2) | ||
699 | return; | ||
700 | if (pkt->S8_Pack.IONum != 2) | ||
701 | return; | ||
702 | |||
703 | ibm_statusled_base = ld_le16((unsigned short *) | ||
704 | (pkt->S8_Pack.RangeMin)); | ||
705 | ppc_md.progress = ibm_statusled_progress; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | static void __init | ||
710 | prep_setup_arch(void) | ||
711 | { | ||
712 | unsigned char reg; | ||
713 | int is_ide=0; | ||
714 | |||
715 | /* init to some ~sane value until calibrate_delay() runs */ | ||
716 | loops_per_jiffy = 50000000; | ||
717 | |||
718 | /* Lookup PCI host bridges */ | ||
719 | prep_find_bridges(); | ||
720 | |||
721 | /* Set up floppy in PS/2 mode */ | ||
722 | outb(0x09, SIO_CONFIG_RA); | ||
723 | reg = inb(SIO_CONFIG_RD); | ||
724 | reg = (reg & 0x3F) | 0x40; | ||
725 | outb(reg, SIO_CONFIG_RD); | ||
726 | outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ | ||
727 | |||
728 | switch ( _prep_type ) | ||
729 | { | ||
730 | case _PREP_IBM: | ||
731 | reg = inb(PREP_IBM_PLANAR); | ||
732 | printk(KERN_INFO "IBM planar ID: %02x", reg); | ||
733 | switch (reg) { | ||
734 | case PREP_IBM_SANDALFOOT: | ||
735 | prep_gen_enable_l2(); | ||
736 | setup_ibm_pci = prep_sandalfoot_setup_pci; | ||
737 | ppc_md.power_off = prep_sig750_poweroff; | ||
738 | ppc_md.show_cpuinfo = prep_sandalfoot_cpuinfo; | ||
739 | break; | ||
740 | case PREP_IBM_THINKPAD: | ||
741 | prep_gen_enable_l2(); | ||
742 | setup_ibm_pci = prep_thinkpad_setup_pci; | ||
743 | ppc_md.power_off = prep_carrera_poweroff; | ||
744 | ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo; | ||
745 | break; | ||
746 | default: | ||
747 | if (have_residual_data) { | ||
748 | prep_gen_enable_l2(); | ||
749 | setup_ibm_pci = prep_residual_setup_pci; | ||
750 | ppc_md.power_off = prep_halt; | ||
751 | ppc_md.show_cpuinfo = prep_gen_cpuinfo; | ||
752 | break; | ||
753 | } | ||
754 | else | ||
755 | printk(" - unknown! Assuming Carolina"); | ||
756 | /* fall through */ | ||
757 | case PREP_IBM_CAROLINA_IDE_0: | ||
758 | case PREP_IBM_CAROLINA_IDE_1: | ||
759 | case PREP_IBM_CAROLINA_IDE_2: | ||
760 | case PREP_IBM_CAROLINA_IDE_3: | ||
761 | is_ide = 1; | ||
762 | case PREP_IBM_CAROLINA_SCSI_0: | ||
763 | case PREP_IBM_CAROLINA_SCSI_1: | ||
764 | case PREP_IBM_CAROLINA_SCSI_2: | ||
765 | case PREP_IBM_CAROLINA_SCSI_3: | ||
766 | prep_carolina_enable_l2(); | ||
767 | setup_ibm_pci = prep_carolina_setup_pci; | ||
768 | ppc_md.power_off = prep_sig750_poweroff; | ||
769 | ppc_md.show_cpuinfo = prep_carolina_cpuinfo; | ||
770 | break; | ||
771 | case PREP_IBM_TIGER1_133: | ||
772 | case PREP_IBM_TIGER1_166: | ||
773 | case PREP_IBM_TIGER1_180: | ||
774 | case PREP_IBM_TIGER1_xxx: | ||
775 | case PREP_IBM_TIGER1_333: | ||
776 | prep_carolina_enable_l2(); | ||
777 | setup_ibm_pci = prep_tiger1_setup_pci; | ||
778 | ppc_md.power_off = prep_sig750_poweroff; | ||
779 | ppc_md.show_cpuinfo = prep_tiger1_cpuinfo; | ||
780 | break; | ||
781 | } | ||
782 | printk("\n"); | ||
783 | |||
784 | /* default root device */ | ||
785 | if (is_ide) | ||
786 | ROOT_DEV = MKDEV(IDE0_MAJOR, 3); | ||
787 | else | ||
788 | ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 3); | ||
789 | |||
790 | break; | ||
791 | case _PREP_Motorola: | ||
792 | prep_gen_enable_l2(); | ||
793 | ppc_md.power_off = prep_halt; | ||
794 | ppc_md.show_cpuinfo = prep_mot_cpuinfo; | ||
795 | |||
796 | #ifdef CONFIG_BLK_DEV_INITRD | ||
797 | if (initrd_start) | ||
798 | ROOT_DEV = Root_RAM0; | ||
799 | else | ||
800 | #endif | ||
801 | #ifdef CONFIG_ROOT_NFS | ||
802 | ROOT_DEV = Root_NFS; | ||
803 | #else | ||
804 | ROOT_DEV = Root_SDA2; | ||
805 | #endif | ||
806 | break; | ||
807 | } | ||
808 | |||
809 | /* Read in NVRAM data */ | ||
810 | init_prep_nvram(); | ||
811 | |||
812 | /* if no bootargs, look in NVRAM */ | ||
813 | if ( cmd_line[0] == '\0' ) { | ||
814 | char *bootargs; | ||
815 | bootargs = prep_nvram_get_var("bootargs"); | ||
816 | if (bootargs != NULL) { | ||
817 | strcpy(cmd_line, bootargs); | ||
818 | /* again.. */ | ||
819 | strcpy(boot_command_line, cmd_line); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | prep_init_vesa(); | ||
824 | |||
825 | switch (_prep_type) { | ||
826 | case _PREP_Motorola: | ||
827 | raven_init(); | ||
828 | break; | ||
829 | case _PREP_IBM: | ||
830 | ibm_prep_init(); | ||
831 | break; | ||
832 | } | ||
833 | |||
834 | #ifdef CONFIG_VGA_CONSOLE | ||
835 | /* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */ | ||
836 | vgacon_remap_base = 0xf0000000; | ||
837 | conswitchp = &vga_con; | ||
838 | #endif | ||
839 | } | ||
840 | |||
841 | /* | ||
842 | * First, see if we can get this information from the residual data. | ||
843 | * This is important on some IBM PReP systems. If we cannot, we let the | ||
844 | * TODC code handle doing this. | ||
845 | */ | ||
846 | static void __init | ||
847 | prep_calibrate_decr(void) | ||
848 | { | ||
849 | if (have_residual_data) { | ||
850 | unsigned long freq, divisor = 4; | ||
851 | |||
852 | if ( res->VitalProductData.ProcessorBusHz ) { | ||
853 | freq = res->VitalProductData.ProcessorBusHz; | ||
854 | printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
855 | (freq/divisor)/1000000, | ||
856 | (freq/divisor)%1000000); | ||
857 | tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); | ||
858 | tb_ticks_per_jiffy = freq / HZ / divisor; | ||
859 | } | ||
860 | } | ||
861 | else | ||
862 | todc_calibrate_decr(); | ||
863 | } | ||
864 | |||
865 | static void __init | ||
866 | prep_init_IRQ(void) | ||
867 | { | ||
868 | unsigned int pci_viddid, pci_did; | ||
869 | |||
870 | if (OpenPIC_Addr != NULL) { | ||
871 | openpic_init(NUM_8259_INTERRUPTS); | ||
872 | /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ | ||
873 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
874 | i8259_irq); | ||
875 | } | ||
876 | |||
877 | if (have_residual_data) { | ||
878 | i8259_init(residual_isapic_addr(), 0); | ||
879 | return; | ||
880 | } | ||
881 | |||
882 | /* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory | ||
883 | * controller, we poll (as they have a different int-ack address). */ | ||
884 | early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid); | ||
885 | pci_did = (pci_viddid & 0xffff0000) >> 16; | ||
886 | if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA) | ||
887 | && ((pci_did == PCI_DEVICE_ID_MOTOROLA_RAVEN) | ||
888 | || (pci_did == PCI_DEVICE_ID_MOTOROLA_HAWK))) | ||
889 | i8259_init(0, 0); | ||
890 | else | ||
891 | /* PCI interrupt ack address given in section 6.1.8 of the | ||
892 | * PReP specification. */ | ||
893 | i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR, 0); | ||
894 | } | ||
895 | |||
896 | #ifdef CONFIG_SMP | ||
897 | /* PReP (MTX) support */ | ||
898 | static int __init | ||
899 | smp_prep_probe(void) | ||
900 | { | ||
901 | extern int mot_multi; | ||
902 | |||
903 | if (mot_multi) { | ||
904 | openpic_request_IPIs(); | ||
905 | smp_hw_index[1] = 1; | ||
906 | return 2; | ||
907 | } | ||
908 | |||
909 | return 1; | ||
910 | } | ||
911 | |||
912 | static void __init | ||
913 | smp_prep_kick_cpu(int nr) | ||
914 | { | ||
915 | *(unsigned long *)KERNELBASE = nr; | ||
916 | asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); | ||
917 | printk("CPU1 released, waiting\n"); | ||
918 | } | ||
919 | |||
920 | static void __init | ||
921 | smp_prep_setup_cpu(int cpu_nr) | ||
922 | { | ||
923 | if (OpenPIC_Addr) | ||
924 | do_openpic_setup_cpu(); | ||
925 | } | ||
926 | |||
927 | static struct smp_ops_t prep_smp_ops = { | ||
928 | smp_openpic_message_pass, | ||
929 | smp_prep_probe, | ||
930 | smp_prep_kick_cpu, | ||
931 | smp_prep_setup_cpu, | ||
932 | .give_timebase = smp_generic_give_timebase, | ||
933 | .take_timebase = smp_generic_take_timebase, | ||
934 | }; | ||
935 | #endif /* CONFIG_SMP */ | ||
936 | |||
937 | /* | ||
938 | * Setup the bat mappings we're going to load that cover | ||
939 | * the io areas. RAM was mapped by mapin_ram(). | ||
940 | * -- Cort | ||
941 | */ | ||
942 | static void __init | ||
943 | prep_map_io(void) | ||
944 | { | ||
945 | io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO); | ||
946 | io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO); | ||
947 | } | ||
948 | |||
949 | static int __init | ||
950 | prep_request_io(void) | ||
951 | { | ||
952 | #ifdef CONFIG_NVRAM | ||
953 | request_region(PREP_NVRAM_AS0, 0x8, "nvram"); | ||
954 | #endif | ||
955 | request_region(0x00,0x20,"dma1"); | ||
956 | request_region(0x40,0x20,"timer"); | ||
957 | request_region(0x80,0x10,"dma page reg"); | ||
958 | request_region(0xc0,0x20,"dma2"); | ||
959 | |||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | device_initcall(prep_request_io); | ||
964 | |||
965 | void __init | ||
966 | prep_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
967 | unsigned long r6, unsigned long r7) | ||
968 | { | ||
969 | #ifdef CONFIG_PREP_RESIDUAL | ||
970 | /* make a copy of residual data */ | ||
971 | if ( r3 ) { | ||
972 | memcpy((void *)res,(void *)(r3+KERNELBASE), | ||
973 | sizeof(RESIDUAL)); | ||
974 | } | ||
975 | #endif | ||
976 | |||
977 | isa_io_base = PREP_ISA_IO_BASE; | ||
978 | isa_mem_base = PREP_ISA_MEM_BASE; | ||
979 | pci_dram_offset = PREP_PCI_DRAM_OFFSET; | ||
980 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
981 | DMA_MODE_READ = 0x44; | ||
982 | DMA_MODE_WRITE = 0x48; | ||
983 | ppc_do_canonicalize_irqs = 1; | ||
984 | |||
985 | /* figure out what kind of prep workstation we are */ | ||
986 | if (have_residual_data) { | ||
987 | if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) | ||
988 | _prep_type = _PREP_IBM; | ||
989 | else | ||
990 | _prep_type = _PREP_Motorola; | ||
991 | } | ||
992 | else { | ||
993 | /* assume motorola if no residual (netboot?) */ | ||
994 | _prep_type = _PREP_Motorola; | ||
995 | } | ||
996 | |||
997 | #ifdef CONFIG_PREP_RESIDUAL | ||
998 | /* Switch off all residual data processing if the user requests it */ | ||
999 | if (strstr(cmd_line, "noresidual") != NULL) | ||
1000 | res = NULL; | ||
1001 | #endif | ||
1002 | |||
1003 | /* Initialise progress early to get maximum benefit */ | ||
1004 | prep_set_bat(); | ||
1005 | ibm_statusled_init(); | ||
1006 | |||
1007 | ppc_md.setup_arch = prep_setup_arch; | ||
1008 | ppc_md.show_percpuinfo = prep_show_percpuinfo; | ||
1009 | ppc_md.show_cpuinfo = NULL; /* set in prep_setup_arch() */ | ||
1010 | ppc_md.init_IRQ = prep_init_IRQ; | ||
1011 | /* this gets changed later on if we have an OpenPIC -- Cort */ | ||
1012 | ppc_md.get_irq = i8259_irq; | ||
1013 | |||
1014 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; | ||
1015 | |||
1016 | ppc_md.restart = prep_restart; | ||
1017 | ppc_md.power_off = NULL; /* set in prep_setup_arch() */ | ||
1018 | ppc_md.halt = prep_halt; | ||
1019 | |||
1020 | ppc_md.nvram_read_val = prep_nvram_read_val; | ||
1021 | ppc_md.nvram_write_val = prep_nvram_write_val; | ||
1022 | |||
1023 | ppc_md.time_init = todc_time_init; | ||
1024 | if (_prep_type == _PREP_IBM) { | ||
1025 | ppc_md.rtc_read_val = todc_mc146818_read_val; | ||
1026 | ppc_md.rtc_write_val = todc_mc146818_write_val; | ||
1027 | TODC_INIT(TODC_TYPE_MC146818, RTC_PORT(0), NULL, RTC_PORT(1), | ||
1028 | 8); | ||
1029 | } else { | ||
1030 | TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1, | ||
1031 | PREP_NVRAM_DATA, 8); | ||
1032 | } | ||
1033 | |||
1034 | ppc_md.calibrate_decr = prep_calibrate_decr; | ||
1035 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
1036 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
1037 | |||
1038 | ppc_md.setup_io_mappings = prep_map_io; | ||
1039 | |||
1040 | #ifdef CONFIG_SMP | ||
1041 | smp_ops = &prep_smp_ops; | ||
1042 | #endif /* CONFIG_SMP */ | ||
1043 | } | ||