Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / arch / ppc64 / kernel / setup.c
blob38b1c3c64b3f1976bdce42d8917c012b193a6139
1 /*
2 *
3 * Common boot and setup code.
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/string.h>
16 #include <linux/sched.h>
17 #include <linux/init.h>
18 #include <linux/reboot.h>
19 #include <linux/delay.h>
20 #include <linux/blk.h>
21 #include <linux/ide.h>
22 #include <linux/seq_file.h>
23 #include <linux/ioport.h>
24 #include <linux/console.h>
25 #include <linux/version.h>
26 #include <linux/tty.h>
27 #include <linux/root_dev.h>
28 #include <asm/io.h>
29 #include <asm/prom.h>
30 #include <asm/processor.h>
31 #include <asm/pgtable.h>
32 #include <asm/bootinfo.h>
33 #include <asm/smp.h>
34 #include <asm/elf.h>
35 #include <asm/machdep.h>
36 #include <asm/iSeries/LparData.h>
37 #include <asm/naca.h>
38 #include <asm/paca.h>
39 #include <asm/ppcdebug.h>
40 #include <asm/time.h>
42 extern unsigned long klimit;
43 /* extern void *stab; */
44 extern HTAB htab_data;
45 extern unsigned long loops_per_jiffy;
47 int have_of = 1;
49 extern void chrp_init(unsigned long r3,
50 unsigned long r4,
51 unsigned long r5,
52 unsigned long r6,
53 unsigned long r7);
55 extern void iSeries_init( void );
56 extern void iSeries_init_early( void );
57 extern void pSeries_init_early( void );
58 extern void pSeriesLP_init_early(void);
59 extern void mm_init_ppc64( void );
61 unsigned long decr_overclock = 1;
62 unsigned long decr_overclock_proc0 = 1;
63 unsigned long decr_overclock_set = 0;
64 unsigned long decr_overclock_proc0_set = 0;
66 #ifdef CONFIG_XMON
67 extern void xmon_map_scc(void);
68 #endif
70 char saved_command_line[256];
71 unsigned char aux_device_present;
73 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
74 unsigned long r6, unsigned long r7);
75 int parse_bootinfo(void);
77 #ifdef CONFIG_MAGIC_SYSRQ
78 unsigned long SYSRQ_KEY;
79 #endif /* CONFIG_MAGIC_SYSRQ */
81 struct machdep_calls ppc_md;
84 * Perhaps we can put the pmac screen_info[] here
85 * on pmac as well so we don't need the ifdef's.
86 * Until we get multiple-console support in here
87 * that is. -- Cort
88 * Maybe tie it to serial consoles, since this is really what
89 * these processors use on existing boards. -- Dan
90 */
91 struct screen_info screen_info = {
92 0, 25, /* orig-x, orig-y */
93 0, /* unused */
94 0, /* orig-video-page */
95 0, /* orig-video-mode */
96 80, /* orig-video-cols */
97 0,0,0, /* ega_ax, ega_bx, ega_cx */
98 25, /* orig-video-lines */
99 1, /* orig-video-isVGA */
100 16 /* orig-video-points */
104 * These are used in binfmt_elf.c to put aux entries on the stack
105 * for each elf executable being started.
107 int dcache_bsize;
108 int icache_bsize;
109 int ucache_bsize;
112 * Initialize the PPCDBG state. Called before relocation has been enabled.
114 void ppcdbg_initialize(void) {
115 unsigned long offset = reloc_offset();
116 struct naca_struct *_naca = RELOC(naca);
118 _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
121 static struct console udbg_console = {
122 .name = "udbg",
123 .write = udbg_console_write,
124 .flags = CON_PRINTBUFFER,
125 .index = -1,
128 static int early_console_initialized;
130 void __init disable_early_printk(void)
132 if (!early_console_initialized)
133 return;
134 unregister_console(&udbg_console);
135 early_console_initialized = 0;
139 * Do some initial setup of the system. The paramters are those which
140 * were passed in from the bootloader.
142 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
143 unsigned long r6, unsigned long r7)
145 /* This should be fixed properly in kernel/resource.c */
146 iomem_resource.end = MEM_SPACE_LIMIT;
148 #ifdef CONFIG_XMON_DEFAULT
149 debugger = xmon;
150 debugger_bpt = xmon_bpt;
151 debugger_sstep = xmon_sstep;
152 debugger_iabr_match = xmon_iabr_match;
153 debugger_dabr_match = xmon_dabr_match;
154 #endif
156 /* pSeries systems are identified in prom.c via OF. */
157 if ( itLpNaca.xLparInstalled == 1 )
158 naca->platform = PLATFORM_ISERIES_LPAR;
160 switch (naca->platform) {
161 case PLATFORM_ISERIES_LPAR:
162 iSeries_init_early();
163 break;
165 #ifdef CONFIG_PPC_PSERIES
166 case PLATFORM_PSERIES:
167 pSeries_init_early();
168 #ifdef CONFIG_BLK_DEV_INITRD
169 initrd_start = initrd_end = 0;
170 #endif
171 parse_bootinfo();
172 break;
174 case PLATFORM_PSERIES_LPAR:
175 pSeriesLP_init_early();
176 #ifdef CONFIG_BLK_DEV_INITRD
177 initrd_start = initrd_end = 0;
178 #endif
179 parse_bootinfo();
180 break;
181 #endif
184 if (naca->platform & PLATFORM_PSERIES) {
185 early_console_initialized = 1;
186 register_console(&udbg_console);
189 printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
191 printk("-----------------------------------------------------\n");
192 printk("naca = 0x%p\n", naca);
193 #if 0
194 printk("naca->processorCount = 0x%x\n", naca->processorCount);
195 #endif
196 printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize);
197 printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize);
198 printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize);
199 printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage);
200 printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize);
201 printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize);
202 printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage);
203 printk("naca->pftSize = 0x%lx\n", naca->pftSize);
204 printk("naca->debug_switch = 0x%lx\n", naca->debug_switch);
205 printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller);
206 printk("htab_data.htab = 0x%p\n", htab_data.htab);
207 printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
208 printk("-----------------------------------------------------\n");
210 if (naca->platform & PLATFORM_PSERIES) {
211 finish_device_tree();
212 chrp_init(r3, r4, r5, r6, r7);
215 mm_init_ppc64();
217 switch (naca->platform) {
218 case PLATFORM_ISERIES_LPAR:
219 iSeries_init();
220 break;
221 default:
222 /* The following relies on the device tree being */
223 /* fully configured. */
224 parse_cmd_line(r3, r4, r5, r6, r7);
228 void machine_restart(char *cmd)
230 ppc_md.restart(cmd);
233 void machine_power_off(void)
235 ppc_md.power_off();
238 void machine_halt(void)
240 ppc_md.halt();
243 unsigned long ppc_proc_freq;
244 unsigned long ppc_tb_freq;
246 static int show_cpuinfo(struct seq_file *m, void *v)
248 unsigned long cpu_id = (unsigned long)v - 1;
249 unsigned int pvr;
250 unsigned short maj;
251 unsigned short min;
253 if (cpu_id == NR_CPUS) {
255 if (ppc_md.get_cpuinfo != NULL)
256 ppc_md.get_cpuinfo(m);
258 return 0;
261 if (!(cpu_online_map & (1<<cpu_id)))
262 return 0;
264 #ifdef CONFIG_SMP
265 pvr = paca[cpu_id].pvr;
266 #else
267 pvr = _get_PVR();
268 #endif
269 maj = (pvr >> 8) & 0xFF;
270 min = pvr & 0xFF;
272 seq_printf(m, "processor\t: %lu\n", cpu_id);
273 seq_printf(m, "cpu\t\t: ");
275 switch (PVR_VER(pvr)) {
276 case PV_NORTHSTAR:
277 seq_printf(m, "RS64-II (northstar)\n");
278 break;
279 case PV_PULSAR:
280 seq_printf(m, "RS64-III (pulsar)\n");
281 break;
282 case PV_POWER4:
283 seq_printf(m, "POWER4 (gp)\n");
284 break;
285 case PV_ICESTAR:
286 seq_printf(m, "RS64-III (icestar)\n");
287 break;
288 case PV_SSTAR:
289 seq_printf(m, "RS64-IV (sstar)\n");
290 break;
291 case PV_POWER4p:
292 seq_printf(m, "POWER4+ (gq)\n");
293 break;
294 case PV_630:
295 seq_printf(m, "POWER3 (630)\n");
296 break;
297 case PV_630p:
298 seq_printf(m, "POWER3 (630+)\n");
299 break;
300 default:
301 seq_printf(m, "Unknown (%08x)\n", pvr);
302 break;
306 * Assume here that all clock rates are the same in a
307 * smp system. -- Cort
309 if (naca->platform != PLATFORM_ISERIES_LPAR) {
310 struct device_node *cpu_node;
311 int *fp;
313 cpu_node = find_type_devices("cpu");
314 if (cpu_node) {
315 fp = (int *) get_property(cpu_node, "clock-frequency",
316 NULL);
317 if (fp)
318 seq_printf(m, "clock\t\t: %dMHz\n",
319 *fp / 1000000);
323 if (ppc_md.setup_residual != NULL)
324 ppc_md.setup_residual(m, cpu_id);
326 seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
328 return 0;
331 static void *c_start(struct seq_file *m, loff_t *pos)
333 return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
335 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
337 ++*pos;
338 return c_start(m, pos);
340 static void c_stop(struct seq_file *m, void *v)
343 struct seq_operations cpuinfo_op = {
344 .start =c_start,
345 .next = c_next,
346 .stop = c_stop,
347 .show = show_cpuinfo,
351 * Fetch the cmd_line from open firmware. */
352 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
353 unsigned long r6, unsigned long r7)
355 struct device_node *chosen;
356 char *p;
358 #ifdef CONFIG_BLK_DEV_INITRD
359 if ((initrd_start == 0) && r3 && r4 && r4 != 0xdeadbeef) {
360 initrd_start = (r3 >= KERNELBASE) ? r3 : (unsigned long)__va(r3);
361 initrd_end = initrd_start + r4;
362 ROOT_DEV = Root_RAM0;
363 initrd_below_start_ok = 1;
365 #endif
367 cmd_line[0] = 0;
369 #ifdef CONFIG_CMDLINE
370 strcpy(cmd_line, CONFIG_CMDLINE);
371 #endif /* CONFIG_CMDLINE */
373 chosen = find_devices("chosen");
374 if (chosen != NULL) {
375 p = get_property(chosen, "bootargs", NULL);
376 if (p != NULL && p[0] != 0)
377 strncpy(cmd_line, p, sizeof(cmd_line));
379 cmd_line[sizeof(cmd_line) - 1] = 0;
381 /* Look for mem= option on command line */
382 if (strstr(cmd_line, "mem=")) {
383 char *p, *q;
384 unsigned long maxmem = 0;
385 extern unsigned long __max_memory;
387 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
388 q = p + 4;
389 if (p > cmd_line && p[-1] != ' ')
390 continue;
391 maxmem = simple_strtoul(q, &q, 0);
392 if (*q == 'k' || *q == 'K') {
393 maxmem <<= 10;
394 ++q;
395 } else if (*q == 'm' || *q == 'M') {
396 maxmem <<= 20;
397 ++q;
400 __max_memory = maxmem;
405 char *bi_tag2str(unsigned long tag)
407 switch (tag) {
408 case BI_FIRST:
409 return "BI_FIRST";
410 case BI_LAST:
411 return "BI_LAST";
412 case BI_CMD_LINE:
413 return "BI_CMD_LINE";
414 case BI_BOOTLOADER_ID:
415 return "BI_BOOTLOADER_ID";
416 case BI_INITRD:
417 return "BI_INITRD";
418 case BI_SYSMAP:
419 return "BI_SYSMAP";
420 case BI_MACHTYPE:
421 return "BI_MACHTYPE";
422 default:
423 return "BI_UNKNOWN";
427 int parse_bootinfo(void)
429 struct bi_record *rec;
430 extern char *sysmap;
431 extern unsigned long sysmap_size;
433 rec = prom.bi_recs;
435 if ( rec == NULL || rec->tag != BI_FIRST )
436 return -1;
438 for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
439 switch (rec->tag) {
440 case BI_CMD_LINE:
441 memcpy(cmd_line, (void *)rec->data, rec->size);
442 break;
443 case BI_SYSMAP:
444 sysmap = (char *)((rec->data[0] >= (KERNELBASE))
445 ? rec->data[0] : (unsigned long)__va(rec->data[0]));
446 sysmap_size = rec->data[1];
447 break;
448 #ifdef CONFIG_BLK_DEV_INITRD
449 case BI_INITRD:
450 initrd_start = (unsigned long)__va(rec->data[0]);
451 initrd_end = initrd_start + rec->data[1];
452 ROOT_DEV = Root_RAM0;
453 initrd_below_start_ok = 1;
454 break;
455 #endif /* CONFIG_BLK_DEV_INITRD */
459 return 0;
462 int __init ppc_init(void)
464 /* clear the progress line */
465 ppc_md.progress(" ", 0xffff);
467 if (ppc_md.init != NULL) {
468 ppc_md.init();
470 return 0;
473 arch_initcall(ppc_init);
475 void __init ppc64_calibrate_delay(void)
477 loops_per_jiffy = tb_ticks_per_jiffy;
479 printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
480 loops_per_jiffy/(500000/HZ),
481 loops_per_jiffy/(5000/HZ) % 100);
484 extern void (*calibrate_delay)(void);
485 extern void sort_exception_table(void);
488 * Called into from start_kernel, after lock_kernel has been called.
489 * Initializes bootmem, which is unsed to manage page allocation until
490 * mem_init is called.
492 void __init setup_arch(char **cmdline_p)
494 extern int panic_timeout;
495 extern char _etext[], _edata[];
496 extern void do_init_bootmem(void);
498 calibrate_delay = ppc64_calibrate_delay;
500 ppc64_boot_msg(0x12, "Setup Arch");
501 #ifdef CONFIG_XMON
502 xmon_map_scc();
503 if (strstr(cmd_line, "xmon"))
504 xmon(0);
505 #endif /* CONFIG_XMON */
509 * Set cache line size based on type of cpu as a default.
510 * Systems with OF can look in the properties on the cpu node(s)
511 * for a possibly more accurate value.
513 dcache_bsize = naca->dCacheL1LineSize;
514 icache_bsize = naca->iCacheL1LineSize;
516 /* reboot on panic */
517 panic_timeout = 180;
519 init_mm.start_code = PAGE_OFFSET;
520 init_mm.end_code = (unsigned long) _etext;
521 init_mm.end_data = (unsigned long) _edata;
522 init_mm.brk = (unsigned long) klimit;
524 /* Save unparsed command line copy for /proc/cmdline */
525 strcpy(saved_command_line, cmd_line);
526 *cmdline_p = cmd_line;
528 /* set up the bootmem stuff with available memory */
529 do_init_bootmem();
531 ppc_md.setup_arch();
533 paging_init();
534 sort_exception_table();
535 ppc64_boot_msg(0x15, "Setup Done");
538 /* ToDo: do something useful if ppc_md is not yet setup. */
539 #define PPC64_LINUX_FUNCTION 0x0f000000
540 #define PPC64_IPL_MESSAGE 0xc0000000
541 #define PPC64_TERM_MESSAGE 0xb0000000
542 #define PPC64_ATTN_MESSAGE 0xa0000000
543 #define PPC64_DUMP_MESSAGE 0xd0000000
545 static void ppc64_do_msg(unsigned int src, const char *msg)
547 if (ppc_md.progress) {
548 char buf[32];
550 sprintf(buf, "%08x \n", src);
551 ppc_md.progress(buf, 0);
552 sprintf(buf, "%-16s", msg);
553 ppc_md.progress(buf, 0);
557 /* Print a boot progress message. */
558 void ppc64_boot_msg(unsigned int src, const char *msg)
560 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
561 printk("[boot]%04x %s\n", src, msg);
564 /* Print a termination message (print only -- does not stop the kernel) */
565 void ppc64_terminate_msg(unsigned int src, const char *msg)
567 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
568 printk("[terminate]%04x %s\n", src, msg);
571 /* Print something that needs attention (device error, etc) */
572 void ppc64_attention_msg(unsigned int src, const char *msg)
574 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
575 printk("[attention]%04x %s\n", src, msg);
578 /* Print a dump progress message. */
579 void ppc64_dump_msg(unsigned int src, const char *msg)
581 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
582 printk("[dump]%04x %s\n", src, msg);
585 int set_spread_lpevents( char * str )
587 /* The parameter is the number of processors to share in processing lp events */
588 unsigned long i;
589 unsigned long val = simple_strtoul( str, NULL, 0 );
590 if ( ( val > 0 ) && ( val <= MAX_PACAS ) ) {
591 for ( i=1; i<val; ++i )
592 paca[i].lpQueuePtr = paca[0].lpQueuePtr;
593 printk("lpevent processing spread over %ld processors\n", val);
595 else
596 printk("invalid spreaqd_lpevents %ld\n", val);
597 return 1;
600 /* This should only be called on processor 0 during calibrate decr */
601 void setup_default_decr(void)
603 struct paca_struct *lpaca = get_paca();
605 if ( decr_overclock_set && !decr_overclock_proc0_set )
606 decr_overclock_proc0 = decr_overclock;
608 lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
609 lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
612 int set_decr_overclock_proc0( char * str )
614 unsigned long val = simple_strtoul( str, NULL, 0 );
615 if ( ( val >= 1 ) && ( val <= 48 ) ) {
616 decr_overclock_proc0_set = 1;
617 decr_overclock_proc0 = val;
618 printk("proc 0 decrementer overclock factor of %ld\n", val);
620 else
621 printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
622 return 1;
625 int set_decr_overclock( char * str )
627 unsigned long val = simple_strtoul( str, NULL, 0 );
628 if ( ( val >= 1 ) && ( val <= 48 ) ) {
629 decr_overclock_set = 1;
630 decr_overclock = val;
631 printk("decrementer overclock factor of %ld\n", val);
633 else
634 printk("invalid decrementer overclock factor of %ld\n", val);
635 return 1;
639 __setup("spread_lpevents=", set_spread_lpevents );
640 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
641 __setup("decr_overclock=", set_decr_overclock );