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>
29 #include <asm/processor.h>
30 #include <asm/pgtable.h>
31 #include <asm/bootinfo.h>
34 #include <asm/machdep.h>
35 #include <asm/iSeries/LparData.h>
38 #include <asm/ppcdebug.h>
40 #include <asm/cputable.h>
42 extern unsigned long klimit;
43 /* extern void *stab; */
44 extern HTAB htab_data;
45 extern unsigned long loops_per_jiffy;
46 extern int blk_nohighio;
48 extern unsigned long embedded_sysmap_start;
49 extern unsigned long embedded_sysmap_end;
53 extern void chrp_init(unsigned long r3,
59 extern void chrp_init_map_io_space( void );
60 extern void iSeries_init( void );
61 extern void iSeries_init_early( void );
62 extern void pSeries_init_early( void );
63 extern void pSeriesLP_init_early(void);
64 extern void mm_init_ppc64( void );
65 extern void pseries_secondary_smp_init(unsigned long);
67 unsigned long decr_overclock = 1;
68 unsigned long decr_overclock_proc0 = 1;
69 unsigned long decr_overclock_set = 0;
70 unsigned long decr_overclock_proc0_set = 0;
73 extern void xmon_map_scc(void);
76 char saved_command_line[256];
77 unsigned char aux_device_present;
79 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
80 unsigned long r6, unsigned long r7);
81 int parse_bootinfo(void);
83 #ifdef CONFIG_MAGIC_SYSRQ
84 unsigned long SYSRQ_KEY;
85 #endif /* CONFIG_MAGIC_SYSRQ */
87 struct machdep_calls ppc_md;
90 * These are used in binfmt_elf.c to put aux entries on the stack
91 * for each elf executable being started.
97 struct console udbg_console = {
99 write: udbg_console_write,
100 flags: CON_PRINTBUFFER,
105 * Do some initial setup of the system. The parameters are those which
106 * were passed in from the bootloader.
108 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
109 unsigned long r6, unsigned long r7)
113 /* This should be fixed properly in kernel/resource.c */
114 iomem_resource.end = MEM_SPACE_LIMIT;
116 /* pSeries systems are identified in prom.c via OF. */
117 if ( itLpNaca.xLparInstalled == 1 )
118 systemcfg->platform = PLATFORM_ISERIES_LPAR;
120 switch (systemcfg->platform) {
121 case PLATFORM_ISERIES_LPAR:
122 iSeries_init_early();
125 #ifdef CONFIG_PPC_PSERIES
126 case PLATFORM_PSERIES:
127 pSeries_init_early();
128 #ifdef CONFIG_BLK_DEV_INITRD
129 initrd_start = initrd_end = 0;
134 case PLATFORM_PSERIES_LPAR:
135 pSeriesLP_init_early();
136 #ifdef CONFIG_BLK_DEV_INITRD
137 initrd_start = initrd_end = 0;
144 if (systemcfg->platform & PLATFORM_PSERIES) {
145 register_console(&udbg_console);
146 udbg_printf("---- start early boot console ----\n");
149 if (systemcfg->platform & PLATFORM_PSERIES) {
150 finish_device_tree();
151 chrp_init(r3, r4, r5, r6, r7);
153 /* Start secondary threads on SMT systems */
154 for (i = 0; i < NR_CPUS; i++) {
155 if(cpu_available(i) && !cpu_possible(i)) {
156 printk("%16.16lx : starting thread\n", i);
157 rtas_call(rtas_token("start-cpu"), 3, 1,
159 i, *((unsigned long *)pseries_secondary_smp_init), i);
161 systemcfg->processorCount++;
166 printk("-----------------------------------------------------\n");
167 printk("naca = 0x%p\n", naca);
168 printk("naca->pftSize = 0x%lx\n", naca->pftSize);
169 printk("naca->paca = 0x%p\n\n", naca->paca);
170 printk("systemcfg = 0x%p\n", systemcfg);
171 printk("systemcfg->platform = 0x%x\n", systemcfg->platform);
172 printk("systemcfg->processor = 0x%x\n", systemcfg->processor);
173 printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
174 printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
175 printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize);
176 printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize);
177 printk("htab_data.htab = 0x%p\n", htab_data.htab);
178 printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
179 printk("-----------------------------------------------------\n");
181 printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
185 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
191 switch (systemcfg->platform) {
192 case PLATFORM_ISERIES_LPAR:
196 /* The following relies on the device tree being */
197 /* fully configured. */
198 parse_cmd_line(r3, r4, r5, r6, r7);
200 ppc64_boot_msg(0x10, "Setup System");
203 /* This is called just before console_init().
204 * It will be obsolete when Linux gets real early console support (2.5?)
205 * We need to hack preferred_console to retain the correct behavior
207 void setup_before_console_init(void)
209 if (systemcfg->platform & PLATFORM_PSERIES) {
210 unregister_console(&udbg_console);
211 udbg_console.next = NULL;
212 udbg_printf("---- end early boot console ----\n");
216 void machine_restart(char *cmd)
221 void machine_power_off(void)
226 void machine_halt(void)
231 unsigned long ppc_proc_freq;
232 unsigned long ppc_tb_freq;
234 static int show_cpuinfo(struct seq_file *m, void *v)
236 unsigned long cpu_id = (unsigned long)v - 1;
242 if (cpu_id == NR_CPUS) {
244 if (ppc_md.get_cpuinfo != NULL)
245 ppc_md.get_cpuinfo(m);
250 if (!(cpu_online_map & (1<<cpu_id)))
254 pvr = paca[cpu_id].pvr;
255 maj = (pvr >> 8) & 0xFF;
258 seq_printf(m, "processor\t: %lu\n", cpu_id);
259 seq_printf(m, "cpu\t\t: ");
261 pvr = paca[cpu_id].pvr;
263 if (cur_cpu_spec->pvr_mask)
264 seq_printf(m, "%s", cur_cpu_spec->cpu_name);
266 seq_printf(m, "unknown (%08x)", pvr);
272 * Assume here that all clock rates are the same in a
273 * smp system. -- Cort
275 if (systemcfg->platform != PLATFORM_ISERIES_LPAR) {
276 struct device_node *cpu_node;
279 cpu_node = find_type_devices("cpu");
281 fp = (int *) get_property(cpu_node, "clock-frequency",
284 seq_printf(m, "clock\t\t: %dMHz\n",
289 if (ppc_md.setup_residual != NULL)
290 ppc_md.setup_residual(m, cpu_id);
292 seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
297 static void *c_start(struct seq_file *m, loff_t *pos)
299 return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
301 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
304 return c_start(m, pos);
306 static void c_stop(struct seq_file *m, void *v)
309 struct seq_operations cpuinfo_op = {
313 .show = show_cpuinfo,
317 * Fetch the cmd_line from open firmware.
319 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
320 unsigned long r6, unsigned long r7)
324 #ifdef CONFIG_BLK_DEV_INITRD
325 if ((initrd_start == 0) && r3 && r4 && r4 != 0xdeadbeef) {
326 initrd_start = (r3 >= KERNELBASE) ? r3 : (unsigned long)__va(r3);
327 initrd_end = initrd_start + r4;
328 ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
329 initrd_below_start_ok = 1;
330 lmb_reserve(__pa(initrd_start),r4);
334 /* Hack -- add console=ttySn,9600 if necessary */
335 if(strstr(cmd_line, "console=") == NULL) {
336 struct device_node *prom_stdout = find_path_device(of_stdout_device);
339 char *name, *val = NULL;
340 printk("of_stdout_device %s\n", of_stdout_device);
342 name = (char *)get_property(prom_stdout, "name", NULL);
344 if (strcmp(name, "serial") == 0) {
345 reg = (u32 *)get_property(prom_stdout, "reg", &i);
348 case 0x3f8: val = "ttyS0,9600"; break;
349 case 0x2f8: val = "ttyS1,9600"; break;
350 case 0x898: val = "ttyS2,9600"; break;
351 case 0x890: val = "ttyS3,9600"; break;
354 } else if (strcmp(name, "vty") == 0) {
355 /* pSeries LPAR virtual console */
359 char tmp_cmd_line[512];
360 snprintf(tmp_cmd_line, 512,
361 "AUTOCONSOLE console=%s %s",
363 memcpy(cmd_line, tmp_cmd_line, 512);
364 printk("console= not found, add console=%s\ncmd_line is now %s\n",
371 /* Look for mem= option on command line */
372 if (strstr(cmd_line, "mem=")) {
374 unsigned long maxmem = 0;
375 extern unsigned long __max_memory;
377 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
379 if (p > cmd_line && p[-1] != ' ')
381 maxmem = simple_strtoul(q, &q, 0);
382 if (*q == 'k' || *q == 'K') {
385 } else if (*q == 'm' || *q == 'M') {
390 __max_memory = maxmem;
395 char *bi_tag2str(unsigned long tag)
403 return "BI_CMD_LINE";
404 case BI_BOOTLOADER_ID:
405 return "BI_BOOTLOADER_ID";
411 return "BI_MACHTYPE";
418 int parse_bootinfo(void)
420 struct bi_record *rec;
422 extern unsigned long sysmap_size;
426 if ( rec == NULL || rec->tag != BI_FIRST )
429 for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
432 memcpy(cmd_line, (void *)rec->data, rec->size);
435 sysmap = (char *)((rec->data[0] >= (KERNELBASE))
436 ? rec->data[0] : (unsigned long)__va(rec->data[0]));
437 sysmap_size = rec->data[1];
439 #ifdef CONFIG_BLK_DEV_INITRD
441 initrd_start = (unsigned long)__va(rec->data[0]);
442 initrd_end = initrd_start + rec->data[1];
443 ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
444 initrd_below_start_ok = 1;
446 #endif /* CONFIG_BLK_DEV_INITRD */
453 void __init ppc_init(void)
455 /* clear the progress line */
456 ppc_md.progress(" ", 0xffff);
458 if (ppc_md.init != NULL) {
463 void __init ppc64_calibrate_delay(void)
465 loops_per_jiffy = tb_ticks_per_jiffy;
467 printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
468 loops_per_jiffy/(500000/HZ),
469 loops_per_jiffy/(5000/HZ) % 100);
472 extern void (*calibrate_delay)(void);
473 extern void sort_exception_table(void);
476 * Called into from start_kernel, after lock_kernel has been called.
477 * Initializes bootmem, which is unsed to manage page allocation until
478 * mem_init is called.
480 void __init setup_arch(char **cmdline_p)
482 extern int panic_timeout;
483 extern char _etext[], _edata[];
484 extern void do_init_bootmem(void);
488 calibrate_delay = ppc64_calibrate_delay;
490 ppc64_boot_msg(0x12, "Setup Arch");
493 if (strstr(cmd_line, "xmon"))
495 #endif /* CONFIG_XMON */
497 #if defined(CONFIG_KGDB)
503 * Set cache line size based on type of cpu as a default.
504 * Systems with OF can look in the properties on the cpu node(s)
505 * for a possibly more accurate value.
507 dcache_bsize = systemcfg->dCacheL1LineSize;
508 icache_bsize = systemcfg->iCacheL1LineSize;
510 /* reboot on panic */
513 init_mm.start_code = PAGE_OFFSET;
514 init_mm.end_code = (unsigned long) _etext;
515 init_mm.end_data = (unsigned long) _edata;
516 init_mm.brk = (unsigned long) klimit;
518 /* Save unparsed command line copy for /proc/cmdline */
519 strcpy(saved_command_line, cmd_line);
520 *cmdline_p = cmd_line;
522 /* set up the bootmem stuff with available memory */
528 sort_exception_table();
529 ppc64_boot_msg(0x15, "Setup Done");
533 /* ToDo: do something useful if ppc_md is not yet setup. */
534 #define PPC64_LINUX_FUNCTION 0x0f000000
535 #define PPC64_IPL_MESSAGE 0xc0000000
536 #define PPC64_TERM_MESSAGE 0xb0000000
537 #define PPC64_ATTN_MESSAGE 0xa0000000
538 #define PPC64_DUMP_MESSAGE 0xd0000000
540 static void ppc64_do_msg(unsigned int src, const char *msg)
542 if (ppc_md.progress) {
545 sprintf(buf, "%08x \n", src);
546 ppc_md.progress(buf, 0);
547 sprintf(buf, "%-16s", msg);
548 ppc_md.progress(buf, 0);
552 /* Print a boot progress message. */
553 void ppc64_boot_msg(unsigned int src, const char *msg)
555 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
556 udbg_printf("[boot]%04x %s\n", src, msg);
559 /* Print a termination message (print only -- does not stop the kernel) */
560 void ppc64_terminate_msg(unsigned int src, const char *msg)
562 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
563 udbg_printf("[terminate]%04x %s\n", src, msg);
566 /* Print something that needs attention (device error, etc) */
567 void ppc64_attention_msg(unsigned int src, const char *msg)
569 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
570 udbg_printf("[attention]%04x %s\n", src, msg);
573 /* Print a dump progress message. */
574 void ppc64_dump_msg(unsigned int src, const char *msg)
576 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
577 udbg_printf("[dump]%04x %s\n", src, msg);
581 void exception_trace(unsigned long trap)
583 unsigned long x, srr0, srr1, reg20, reg1, reg21;
585 asm("mflr %0" : "=r" (x) :);
586 asm("mfspr %0,0x1a" : "=r" (srr0) :);
587 asm("mfspr %0,0x1b" : "=r" (srr1) :);
588 asm("mr %0,1" : "=r" (reg1) :);
589 asm("mr %0,20" : "=r" (reg20) :);
590 asm("mr %0,21" : "=r" (reg21) :);
593 udbg_puts("Took an exception : "); udbg_puthex(x); udbg_puts("\n");
594 udbg_puts(" "); udbg_puthex(reg1); udbg_puts("\n");
595 udbg_puts(" "); udbg_puthex(reg20); udbg_puts("\n");
596 udbg_puts(" "); udbg_puthex(reg21); udbg_puts("\n");
597 udbg_puts(" "); udbg_puthex(srr0); udbg_puts("\n");
598 udbg_puts(" "); udbg_puthex(srr1); udbg_puts("\n");
601 void do_spread_lpevents(unsigned long n)
611 paca[i].lpQueuePtr = paca[0].lpQueuePtr;
613 printk("lpevent processing spread over %ld processors\n", n);
617 * The parameter is the number of processors to share in
618 * processing lp events
620 int set_spread_lpevents(char * str)
622 unsigned long val = simple_strtoul( str, NULL, 0 );
623 if ((val > 0) && (val <= MAX_PACAS)) {
624 do_spread_lpevents(val);
626 printk("invalid spreaqd_lpevents %ld\n", val);
631 /* This should only be called on processor 0 during calibrate decr */
632 void setup_default_decr(void)
634 struct paca_struct *lpaca = get_paca();
636 if ( decr_overclock_set && !decr_overclock_proc0_set )
637 decr_overclock_proc0 = decr_overclock;
639 lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
640 lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
643 int set_decr_overclock_proc0( char * str )
645 unsigned long val = simple_strtoul( str, NULL, 0 );
646 if ( ( val >= 1 ) && ( val <= 48 ) ) {
647 decr_overclock_proc0_set = 1;
648 decr_overclock_proc0 = val;
649 printk("proc 0 decrementer overclock factor of %ld\n", val);
652 printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
656 int set_decr_overclock( char * str )
658 unsigned long val = simple_strtoul( str, NULL, 0 );
659 if ( ( val >= 1 ) && ( val <= 48 ) ) {
660 decr_overclock_set = 1;
661 decr_overclock = val;
662 printk("decrementer overclock factor of %ld\n", val);
665 printk("invalid decrementer overclock factor of %ld\n", val);
670 __setup("spread_lpevents=", set_spread_lpevents );
671 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
672 __setup("decr_overclock=", set_decr_overclock );