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