Import 2.3.18pre1
[davej-history.git] / arch / ppc / kernel / setup.c
blob8015b8d30636da139d27f528da0226854a38ee10
1 /*
2 * $Id: setup.c,v 1.148 1999/09/05 11:56:34 paulus Exp $
3 * Common prep/pmac/chrp boot and setup code.
4 */
6 #include <linux/config.h>
7 #include <linux/module.h>
8 #include <linux/string.h>
9 #include <linux/sched.h>
10 #include <linux/init.h>
11 #include <linux/reboot.h>
12 #include <linux/delay.h>
13 #include <linux/blk.h>
15 #include <asm/init.h>
16 #include <asm/adb.h>
17 #include <asm/cuda.h>
18 #include <asm/pmu.h>
19 #include <asm/residual.h>
20 #include <asm/io.h>
21 #include <linux/ide.h>
22 #include <asm/ide.h>
23 #include <asm/prom.h>
24 #include <asm/processor.h>
25 #include <asm/pgtable.h>
26 #include <asm/bootinfo.h>
27 #include <asm/setup.h>
28 #include <asm/amigappc.h>
29 #include <asm/smp.h>
30 #ifdef CONFIG_MBX
31 #include <asm/mbx.h>
32 #include <asm/8xx_immap.h>
33 #endif
34 #include <asm/bootx.h>
35 #include <asm/machdep.h>
37 extern void pmac_init(unsigned long r3,
38 unsigned long r4,
39 unsigned long r5,
40 unsigned long r6,
41 unsigned long r7);
43 extern void chrp_init(unsigned long r3,
44 unsigned long r4,
45 unsigned long r5,
46 unsigned long r6,
47 unsigned long r7);
49 extern void prep_init(unsigned long r3,
50 unsigned long r4,
51 unsigned long r5,
52 unsigned long r6,
53 unsigned long r7);
55 extern void mbx_init(unsigned long r3,
56 unsigned long r4,
57 unsigned long r5,
58 unsigned long r6,
59 unsigned long r7);
61 extern void apus_init(unsigned long r3,
62 unsigned long r4,
63 unsigned long r5,
64 unsigned long r6,
65 unsigned long r7);
67 extern void gemini_init(unsigned long r3,
68 unsigned long r4,
69 unsigned long r5,
70 unsigned long r6,
71 unsigned long r7);
73 extern boot_infos_t *boot_infos;
74 extern char cmd_line[512];
75 char saved_command_line[256];
76 unsigned char aux_device_present;
78 struct ide_machdep_calls ppc_ide_md;
80 unsigned long ISA_DMA_THRESHOLD;
81 unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
83 /* Temporary hacks until machdep.h is fully done. */
84 int _machine = 0;
85 /* do we have OF? */
86 int have_of = 0;
87 int is_prep = 0;
88 int is_chrp = 0;
89 #ifdef CONFIG_MAGIC_SYSRQ
90 unsigned long SYSRQ_KEY;
91 #endif /* CONFIG_MAGIC_SYSRQ */
92 /* For MTX/MVME boards.. with Raven/Falcon Chipset
93 Real close to CHRP, but boot like PReP (via PPCbug)
94 There's probably a nicer way to do this.. --Troy */
95 int is_powerplus = 0;
97 struct machdep_calls ppc_md;
100 /* copy of the residual data */
101 #ifndef CONFIG_MBX
102 unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
103 #else
104 unsigned char __res[sizeof(bd_t)] = {0,};
105 #endif
107 RESIDUAL *res = (RESIDUAL *)&__res;
110 * Perhaps we can put the pmac screen_info[] here
111 * on pmac as well so we don't need the ifdef's.
112 * Until we get multiple-console support in here
113 * that is. -- Cort
115 #ifndef CONFIG_MBX
116 struct screen_info screen_info = {
117 0, 25, /* orig-x, orig-y */
118 0, /* unused */
119 0, /* orig-video-page */
120 0, /* orig-video-mode */
121 80, /* orig-video-cols */
122 0,0,0, /* ega_ax, ega_bx, ega_cx */
123 25, /* orig-video-lines */
124 1, /* orig-video-isVGA */
125 16 /* orig-video-points */
129 * I really need to add multiple-console support... -- Cort
131 int __init pmac_display_supported(char *name)
133 return 0;
135 void __init pmac_find_display(void)
139 #else /* CONFIG_MBX */
141 /* We need this to satisfy some external references until we can
142 * strip the kernel down.
144 struct screen_info screen_info = {
145 0, 25, /* orig-x, orig-y */
146 0, /* unused */
147 0, /* orig-video-page */
148 0, /* orig-video-mode */
149 80, /* orig-video-cols */
150 0,0,0, /* ega_ax, ega_bx, ega_cx */
151 25, /* orig-video-lines */
152 0, /* orig-video-isVGA */
153 16 /* orig-video-points */
155 #endif /* CONFIG_MBX */
157 void machine_restart(char *cmd)
159 ppc_md.restart(cmd);
162 void machine_power_off(void)
164 ppc_md.power_off();
167 void machine_halt(void)
169 ppc_md.halt();
172 unsigned long cpu_temp(void)
174 unsigned char thres = 0;
176 #if 0
177 /* disable thrm2 */
178 _set_THRM2( 0 );
179 /* threshold 0 C, tid: exceeding threshold, tie: don't generate interrupt */
180 _set_THRM1( THRM1_V );
182 /* we need 20us to do the compare - assume 300MHz processor clock */
183 _set_THRM3(0);
184 _set_THRM3(THRM3_E | (300*30)<<18 );
186 udelay(100);
187 /* wait for the compare to complete */
188 /*while ( !(_get_THRM1() & THRM1_TIV) ) ;*/
189 if ( !(_get_THRM1() & THRM1_TIV) )
190 printk("no tiv\n");
191 if ( _get_THRM1() & THRM1_TIN )
192 printk("crossed\n");
193 /* turn everything off */
194 _set_THRM3(0);
195 _set_THRM1(0);
196 #endif
198 return thres;
201 int get_cpuinfo(char *buffer)
203 unsigned long len = 0;
204 unsigned long bogosum = 0;
205 unsigned long i;
207 #ifdef __SMP__
208 #define CPU_PRESENT(x) (cpu_callin_map[(x)])
209 #define GET_PVR ((long int)(cpu_data[i].pvr))
210 #define CD(x) (cpu_data[i].x)
211 #else
212 #define CPU_PRESENT(x) ((x)==0)
213 #define smp_num_cpus 1
214 #define GET_PVR ((long int)_get_PVR())
215 #define CD(x) (x)
216 #endif
218 for ( i = 0; i < smp_num_cpus ; i++ )
220 if ( !CPU_PRESENT(i) )
221 continue;
222 if ( i )
223 len += sprintf(len+buffer,"\n");
224 len += sprintf(len+buffer,"processor\t: %lu\n",i);
225 len += sprintf(len+buffer,"cpu\t\t: ");
227 switch (GET_PVR >> 16)
229 case 1:
230 len += sprintf(len+buffer, "601\n");
231 break;
232 case 3:
233 len += sprintf(len+buffer, "603\n");
234 break;
235 case 4:
236 len += sprintf(len+buffer, "604\n");
237 break;
238 case 6:
239 len += sprintf(len+buffer, "603e\n");
240 break;
241 case 7:
242 len += sprintf(len+buffer, "603ev\n");
243 break;
244 case 8:
245 len += sprintf(len+buffer, "750\n");
246 len += sprintf(len+buffer, "temperature \t: %lu C\n",
247 cpu_temp());
248 break;
249 case 9:
250 len += sprintf(len+buffer, "604e\n");
251 break;
252 case 10:
253 len += sprintf(len+buffer, "604ev5 (MachV)\n");
254 break;
255 case 50:
256 len += sprintf(len+buffer, "821\n");
257 case 80:
258 len += sprintf(len+buffer, "860\n");
259 break;
260 default:
261 len += sprintf(len+buffer, "unknown (%lu)\n",
262 GET_PVR>>16);
263 break;
267 * Assume here that all clock rates are the same in a
268 * smp system. -- Cort
270 if ( have_of )
272 struct device_node *cpu_node;
273 int *fp;
275 cpu_node = find_type_devices("cpu");
276 if ( !cpu_node ) break;
278 int s;
279 for ( s = 0; (s < i) && cpu_node->next ;
280 s++, cpu_node = cpu_node->next )
281 /* nothing */ ;
282 #if 0 /* SMP Pmacs don't have all cpu nodes -- Cort */
283 if ( s != i )
284 printk("get_cpuinfo(): ran out of "
285 "cpu nodes.\n");
286 #endif
288 fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
289 if ( !fp ) break;
290 len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
291 *fp / 1000000);
294 if (ppc_md.setup_residual != NULL)
296 len += ppc_md.setup_residual(buffer + len);
299 len += sprintf(len+buffer, "revision\t: %ld.%ld\n",
300 (GET_PVR & 0xff00) >> 8, GET_PVR & 0xff);
302 len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
303 (CD(loops_per_sec)+2500)/500000,
304 (CD(loops_per_sec)+2500)/5000 % 100);
305 bogosum += CD(loops_per_sec);
308 #ifdef __SMP__
309 if ( i )
310 len += sprintf(buffer+len, "\n");
311 len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
312 (bogosum+2500)/500000,
313 (bogosum+2500)/5000 % 100);
314 #endif /* __SMP__ */
317 * Ooh's and aah's info about zero'd pages in idle task
320 len += sprintf(buffer+len,"zero pages\t: total %lu (%luKb) "
321 "current: %lu (%luKb) hits: %lu/%lu (%lu%%)\n",
322 zero_cache_total,
323 (zero_cache_total*PAGE_SIZE)>>10,
324 zero_cache_sz,
325 (zero_cache_sz*PAGE_SIZE)>>10,
326 zero_cache_hits,zero_cache_calls,
327 /* : 1 below is so we don't div by zero */
328 (zero_cache_hits*100) /
329 ((zero_cache_calls)?zero_cache_calls:1));
332 if (ppc_md.get_cpuinfo != NULL)
334 len += ppc_md.get_cpuinfo(buffer+len);
337 return len;
341 * Find out what kind of machine we're on and save any data we need
342 * from the early boot process (devtree is copied on pmac by prom_init() )
344 unsigned long __init
345 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
346 unsigned long r6, unsigned long r7)
348 #ifdef __SMP__
349 if ( first_cpu_booted ) return 0;
350 #endif /* __SMP__ */
351 if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
353 #ifndef CONFIG_MACH_SPECIFIC
354 /* boot loader will tell us if we're APUS */
355 if ( r3 == 0x61707573 )
357 _machine = _MACH_apus;
358 r3 = 0;
360 /* prep boot loader tells us if we're prep or not */
361 else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) {
362 _machine = _MACH_prep;
363 is_prep = 1;
364 } else {
365 char *model;
367 have_of = 1;
369 /* prom_init has already been called from __start */
370 finish_device_tree();
371 /* ask the OF info if we're a chrp or pmac */
372 model = get_property(find_path_device("/"), "device_type", NULL);
373 if ( model && !strncmp("chrp",model,4) )
375 _machine = _MACH_chrp;
376 is_chrp = 1;
378 else
380 model = get_property(find_path_device("/"),
381 "model", NULL);
382 if ( model && !strncmp(model, "IBM", 3))
384 _machine = _MACH_chrp;
385 is_chrp = 1;
387 else
389 _machine = _MACH_Pmac;
394 #else /* CONFIG_MACH_SPECIFIC */
396 #ifdef CONFIG_PREP
397 _machine = _MACH_prep;
398 is_prep = 1;
399 #elif defined(CONFIG_CHRP)
400 _machine = _MACH_chrp;
401 is_chrp = 1;
402 have_of = 1;
403 #elif defined(CONFIG_PMAC)
404 _machine = _MACH_Pmac;
405 have_of = 1;
406 #elif defined(CONFIG_MBX)
407 _machine = _MACH_mbx;
408 #elif defined(CONFIG_FADS)
409 _machine = _MACH_fads;
410 #elif defined(CONFIG_APUS)
411 _machine = _MACH_apus;
412 #elif defined(CONFIG_GEMINI)
413 _machine = _MACH_gemini;
414 #else
415 #error "Machine not defined correctly"
416 #endif /* CONFIG_APUS */
417 #endif /* CONFIG_MACH_SPECIFIC */
419 if ( have_of )
421 #ifdef CONFIG_MACH_SPECIFIC
422 /* prom_init has already been called from __start */
423 finish_device_tree();
424 #endif /* CONFIG_MACH_SPECIFIC */
426 * If we were booted via quik, r3 points to the physical
427 * address of the command-line parameters.
428 * If we were booted from an xcoff image (i.e. netbooted or
429 * booted from floppy), we get the command line from the
430 * bootargs property of the /chosen node.
431 * If an initial ramdisk is present, r3 and r4
432 * are used for initrd_start and initrd_size,
433 * otherwise they contain 0xdeadbeef.
435 cmd_line[0] = 0;
436 if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
437 strncpy(cmd_line, (char *)r3 + KERNELBASE,
438 sizeof(cmd_line));
439 } else if (boot_infos != 0) {
440 /* booted by BootX - check for ramdisk */
441 if (boot_infos->kernelParamsOffset != 0)
442 strncpy(cmd_line, (char *) boot_infos
443 + boot_infos->kernelParamsOffset,
444 sizeof(cmd_line));
445 #ifdef CONFIG_BLK_DEV_INITRD
446 if (boot_infos->ramDisk) {
447 initrd_start = (unsigned long) boot_infos
448 + boot_infos->ramDisk;
449 initrd_end = initrd_start + boot_infos->ramDiskSize;
450 initrd_below_start_ok = 1;
452 #endif
453 } else {
454 struct device_node *chosen;
455 char *p;
457 #ifdef CONFIG_BLK_DEV_INITRD
458 if (r3 - KERNELBASE < 0x800000
459 && r4 != 0 && r4 != 0xdeadbeef) {
460 initrd_start = r3;
461 initrd_end = r3 + r4;
462 ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
464 #endif
465 cmd_line[0] = 0;
466 chosen = find_devices("chosen");
467 if (chosen != NULL) {
468 p = get_property(chosen, "bootargs", NULL);
469 if (p != NULL)
470 strncpy(cmd_line, p, sizeof(cmd_line));
473 cmd_line[sizeof(cmd_line) - 1] = 0;
476 switch (_machine)
478 case _MACH_Pmac:
479 pmac_init(r3, r4, r5, r6, r7);
480 break;
481 case _MACH_prep:
482 prep_init(r3, r4, r5, r6, r7);
483 break;
484 case _MACH_chrp:
485 chrp_init(r3, r4, r5, r6, r7);
486 break;
487 #ifdef CONFIG_APUS
488 case _MACH_apus:
489 apus_init(r3, r4, r5, r6, r7);
490 break;
491 #endif
492 #ifdef CONFIG_MBX
493 case _MACH_mbx:
494 mbx_init(r3, r4, r5, r6, r7);
495 break;
496 #endif
497 case _MACH_gemini:
498 gemini_init(r3, r4, r5, r6, r7);
499 break;
500 default:
501 printk("Unknown machine type in identify_machine!\n");
503 /* Check for nobats option (used in mapin_ram). */
504 if (strstr(cmd_line, "nobats")) {
505 extern int __map_without_bats;
506 __map_without_bats = 1;
509 if ( ppc_md.progress ) ppc_md.progress("id mach(): done", 0x200);
510 return 0;
513 /* Checks "l2cr=xxxx" command-line option */
514 void ppc_setup_l2cr(char *str, int *ints)
516 if ( (_get_PVR() >> 16) == 8)
518 unsigned long val = simple_strtoul(str, NULL, 0);
519 printk(KERN_INFO "l2cr set to %lx\n", val);
520 _set_L2CR(0);
521 _set_L2CR(val);
525 void __init ppc_init(void)
527 /* clear the progress line */
528 if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
530 if (ppc_md.init != NULL) {
531 ppc_md.init();
535 void __init setup_arch(char **cmdline_p,
536 unsigned long * memory_start_p, unsigned long * memory_end_p)
538 extern int panic_timeout;
539 extern char _etext[], _edata[];
540 extern char *klimit;
541 extern unsigned long find_available_memory(void);
542 extern unsigned long *end_of_DRAM;
544 #ifdef CONFIG_XMON
545 extern void xmon_map_scc(void);
546 xmon_map_scc();
547 if (strstr(cmd_line, "xmon"))
548 xmon(0);
549 #endif /* CONFIG_XMON */
551 /* reboot on panic */
552 panic_timeout = 180;
554 init_mm.start_code = PAGE_OFFSET;
555 init_mm.end_code = (unsigned long) _etext;
556 init_mm.end_data = (unsigned long) _edata;
557 init_mm.brk = (unsigned long) klimit;
559 /* Save unparsed command line copy for /proc/cmdline */
560 strcpy(saved_command_line, cmd_line);
561 *cmdline_p = cmd_line;
563 *memory_start_p = find_available_memory();
564 *memory_end_p = (unsigned long) end_of_DRAM;
566 ppc_md.setup_arch(memory_start_p, memory_end_p);
567 /* clear the progress line */
568 if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
571 void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
573 int i;
574 unsigned short *stringcast;
577 id->config = __le16_to_cpu(id->config);
578 id->cyls = __le16_to_cpu(id->cyls);
579 id->reserved2 = __le16_to_cpu(id->reserved2);
580 id->heads = __le16_to_cpu(id->heads);
581 id->track_bytes = __le16_to_cpu(id->track_bytes);
582 id->sector_bytes = __le16_to_cpu(id->sector_bytes);
583 id->sectors = __le16_to_cpu(id->sectors);
584 id->vendor0 = __le16_to_cpu(id->vendor0);
585 id->vendor1 = __le16_to_cpu(id->vendor1);
586 id->vendor2 = __le16_to_cpu(id->vendor2);
587 stringcast = (unsigned short *)&id->serial_no[0];
588 for (i=0; i<(20/2); i++)
589 stringcast[i] = __le16_to_cpu(stringcast[i]);
590 id->buf_type = __le16_to_cpu(id->buf_type);
591 id->buf_size = __le16_to_cpu(id->buf_size);
592 id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
593 stringcast = (unsigned short *)&id->fw_rev[0];
594 for (i=0; i<(8/2); i++)
595 stringcast[i] = __le16_to_cpu(stringcast[i]);
596 stringcast = (unsigned short *)&id->model[0];
597 for (i=0; i<(40/2); i++)
598 stringcast[i] = __le16_to_cpu(stringcast[i]);
599 id->dword_io = __le16_to_cpu(id->dword_io);
600 id->reserved50 = __le16_to_cpu(id->reserved50);
601 id->field_valid = __le16_to_cpu(id->field_valid);
602 id->cur_cyls = __le16_to_cpu(id->cur_cyls);
603 id->cur_heads = __le16_to_cpu(id->cur_heads);
604 id->cur_sectors = __le16_to_cpu(id->cur_sectors);
605 id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
606 id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
607 id->lba_capacity = __le32_to_cpu(id->lba_capacity);
608 id->dma_1word = __le16_to_cpu(id->dma_1word);
609 id->dma_mword = __le16_to_cpu(id->dma_mword);
610 id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
611 id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
612 id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
613 id->eide_pio = __le16_to_cpu(id->eide_pio);
614 id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
615 id->word69 = __le16_to_cpu(id->word69);
616 id->word70 = __le16_to_cpu(id->word70);
617 id->word71 = __le16_to_cpu(id->word71);
618 id->word72 = __le16_to_cpu(id->word72);
619 id->word73 = __le16_to_cpu(id->word73);
620 id->word74 = __le16_to_cpu(id->word74);
621 id->word75 = __le16_to_cpu(id->word75);
622 id->word76 = __le16_to_cpu(id->word76);
623 id->word77 = __le16_to_cpu(id->word77);
624 id->word78 = __le16_to_cpu(id->word78);
625 id->word79 = __le16_to_cpu(id->word79);
626 id->word80 = __le16_to_cpu(id->word80);
627 id->word81 = __le16_to_cpu(id->word81);
628 id->command_sets = __le16_to_cpu(id->command_sets);
629 id->word83 = __le16_to_cpu(id->word83);
630 id->word84 = __le16_to_cpu(id->word84);
631 id->word85 = __le16_to_cpu(id->word85);
632 id->word86 = __le16_to_cpu(id->word86);
633 id->word87 = __le16_to_cpu(id->word87);
634 id->dma_ultra = __le16_to_cpu(id->dma_ultra);
635 id->word89 = __le16_to_cpu(id->word89);
636 id->word90 = __le16_to_cpu(id->word90);
637 id->word91 = __le16_to_cpu(id->word91);
638 id->word92 = __le16_to_cpu(id->word92);
639 id->word93 = __le16_to_cpu(id->word93);
640 id->word94 = __le16_to_cpu(id->word94);
641 id->word95 = __le16_to_cpu(id->word95);
642 id->word96 = __le16_to_cpu(id->word96);
643 id->word97 = __le16_to_cpu(id->word97);
644 id->word98 = __le16_to_cpu(id->word98);
645 id->word99 = __le16_to_cpu(id->word99);
646 id->word100 = __le16_to_cpu(id->word100);
647 id->word101 = __le16_to_cpu(id->word101);
648 id->word102 = __le16_to_cpu(id->word102);
649 id->word103 = __le16_to_cpu(id->word103);
650 id->word104 = __le16_to_cpu(id->word104);
651 id->word105 = __le16_to_cpu(id->word105);
652 id->word106 = __le16_to_cpu(id->word106);
653 id->word107 = __le16_to_cpu(id->word107);
654 id->word108 = __le16_to_cpu(id->word108);
655 id->word109 = __le16_to_cpu(id->word109);
656 id->word110 = __le16_to_cpu(id->word110);
657 id->word111 = __le16_to_cpu(id->word111);
658 id->word112 = __le16_to_cpu(id->word112);
659 id->word113 = __le16_to_cpu(id->word113);
660 id->word114 = __le16_to_cpu(id->word114);
661 id->word115 = __le16_to_cpu(id->word115);
662 id->word116 = __le16_to_cpu(id->word116);
663 id->word117 = __le16_to_cpu(id->word117);
664 id->word118 = __le16_to_cpu(id->word118);
665 id->word119 = __le16_to_cpu(id->word119);
666 id->word120 = __le16_to_cpu(id->word120);
667 id->word121 = __le16_to_cpu(id->word121);
668 id->word122 = __le16_to_cpu(id->word122);
669 id->word123 = __le16_to_cpu(id->word123);
670 id->word124 = __le16_to_cpu(id->word124);
671 id->word125 = __le16_to_cpu(id->word125);
672 id->word126 = __le16_to_cpu(id->word126);
673 id->word127 = __le16_to_cpu(id->word127);
674 id->security = __le16_to_cpu(id->security);
675 for (i=0; i<127; i++)
676 id->reserved[i] = __le16_to_cpu(id->reserved[i]);