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/initrd.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 <linux/notifier.h>
29 #include <linux/cpu.h>
32 #include <asm/processor.h>
33 #include <asm/pgtable.h>
34 #include <asm/bootinfo.h>
37 #include <asm/machdep.h>
38 #include <asm/iSeries/LparData.h>
41 #include <asm/ppcdebug.h>
43 #include <asm/cputable.h>
44 #include <asm/sections.h>
45 #include <asm/btext.h>
46 #include <asm/nvram.h>
47 #include <asm/setup.h>
48 #include <asm/system.h>
51 extern unsigned long klimit;
52 /* extern void *stab; */
53 extern HTAB htab_data;
54 extern unsigned long loops_per_jiffy;
58 extern void chrp_init(unsigned long r3,
64 extern void pmac_init(unsigned long r3,
70 extern void iSeries_init( void );
71 extern void iSeries_init_early( void );
72 extern void pSeries_init_early( void );
73 extern void pSeriesLP_init_early(void);
74 extern void pmac_init_early(void);
75 extern void mm_init_ppc64( void );
76 extern void pseries_secondary_smp_init(unsigned long);
77 extern int idle_setup(void);
78 extern void vpa_init(int cpu);
80 unsigned long decr_overclock = 1;
81 unsigned long decr_overclock_proc0 = 1;
82 unsigned long decr_overclock_set = 0;
83 unsigned long decr_overclock_proc0_set = 0;
87 unsigned char aux_device_present;
89 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
90 unsigned long r6, unsigned long r7);
91 int parse_bootinfo(void);
93 #ifdef CONFIG_MAGIC_SYSRQ
94 unsigned long SYSRQ_KEY;
95 #endif /* CONFIG_MAGIC_SYSRQ */
97 struct machdep_calls ppc_md;
99 static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
101 static struct notifier_block ppc64_panic_block = {
102 notifier_call: ppc64_panic_event,
103 priority: INT_MIN /* may not return; must be done last */
107 * Perhaps we can put the pmac screen_info[] here
108 * on pmac as well so we don't need the ifdef's.
109 * Until we get multiple-console support in here
111 * Maybe tie it to serial consoles, since this is really what
112 * these processors use on existing boards. -- Dan
114 struct screen_info screen_info = {
115 0, 25, /* orig-x, orig-y */
117 0, /* orig-video-page */
118 0, /* orig-video-mode */
119 80, /* orig-video-cols */
120 0,0,0, /* ega_ax, ega_bx, ega_cx */
121 25, /* orig-video-lines */
122 1, /* orig-video-isVGA */
123 16 /* orig-video-points */
127 * These are used in binfmt_elf.c to put aux entries on the stack
128 * for each elf executable being started.
135 * Initialize the PPCDBG state. Called before relocation has been enabled.
137 void ppcdbg_initialize(void) {
138 unsigned long offset = reloc_offset();
139 struct naca_struct *_naca = RELOC(naca);
141 _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
144 static struct console udbg_console = {
146 .write = udbg_console_write,
147 .flags = CON_PRINTBUFFER,
151 static int early_console_initialized;
153 void __init disable_early_printk(void)
155 if (!early_console_initialized)
157 unregister_console(&udbg_console);
158 early_console_initialized = 0;
162 * Do some initial setup of the system. The parameters are those which
163 * were passed in from the bootloader.
165 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
166 unsigned long r6, unsigned long r7)
168 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
172 #ifdef CONFIG_XMON_DEFAULT
176 #ifdef CONFIG_PPC_ISERIES
177 /* pSeries systems are identified in prom.c via OF. */
178 if ( itLpNaca.xLparInstalled == 1 )
179 systemcfg->platform = PLATFORM_ISERIES_LPAR;
182 switch (systemcfg->platform) {
183 #ifdef CONFIG_PPC_ISERIES
184 case PLATFORM_ISERIES_LPAR:
185 iSeries_init_early();
189 #ifdef CONFIG_PPC_PSERIES
190 case PLATFORM_PSERIES:
191 pSeries_init_early();
195 case PLATFORM_PSERIES_LPAR:
196 pSeriesLP_init_early();
199 #endif /* CONFIG_PPC_PSERIES */
200 #ifdef CONFIG_PPC_PMAC
201 case PLATFORM_POWERMAC:
204 #endif /* CONFIG_PPC_PMAC */
207 /* If we were passed an initrd, set the ROOT_DEV properly if the values
208 * look sensible. If not, clear initrd reference.
210 #ifdef CONFIG_BLK_DEV_INITRD
211 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
212 initrd_end > initrd_start)
213 ROOT_DEV = Root_RAM0;
215 initrd_start = initrd_end = 0;
216 #endif /* CONFIG_BLK_DEV_INITRD */
218 #ifdef CONFIG_BOOTX_TEXT
220 if (systemcfg->platform == PLATFORM_POWERMAC) {
221 early_console_initialized = 1;
222 register_console(&udbg_console);
224 #endif /* CONFIG_BOOTX_TEXT */
226 #ifdef CONFIG_PPC_PSERIES
227 if (systemcfg->platform & PLATFORM_PSERIES) {
228 early_console_initialized = 1;
229 register_console(&udbg_console);
230 __irq_offset_value = NUM_ISA_INTERRUPTS;
231 finish_device_tree();
232 chrp_init(r3, r4, r5, r6, r7);
235 /* Start secondary threads on SMT systems */
236 for (i = 0; i < NR_CPUS; i++) {
237 if (cpu_available(i) && !cpu_possible(i)) {
238 printk("%16.16x : starting thread\n", i);
239 rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
240 get_hard_smp_processor_id(i),
241 (u32)*((unsigned long *)pseries_secondary_smp_init),
243 cpu_set(i, cpu_possible_map);
244 systemcfg->processorCount++;
247 #endif /* CONFIG_SMP */
249 #endif /* CONFIG_PPC_PSERIES */
251 #ifdef CONFIG_PPC_PMAC
252 if (systemcfg->platform == PLATFORM_POWERMAC) {
253 finish_device_tree();
254 pmac_init(r3, r4, r5, r6, r7);
256 #endif /* CONFIG_PPC_PMAC */
258 #if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_PPC_PMAC)
259 rtas_stop_self_args.token = rtas_token("stop-self");
260 #endif /* CONFIG_HOTPLUG_CPU && !CONFIG_PPC_PMAC */
262 /* Finish initializing the hash table (do the dynamic
263 * patching for the fast-path hashtable.S code)
267 printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
269 printk("-----------------------------------------------------\n");
270 printk("naca = 0x%p\n", naca);
271 printk("naca->pftSize = 0x%lx\n", naca->pftSize);
272 printk("naca->debug_switch = 0x%lx\n", naca->debug_switch);
273 printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller);
274 printk("systemcfg = 0x%p\n", systemcfg);
275 printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
276 printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
277 printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize);
278 printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize);
279 printk("htab_data.htab = 0x%p\n", htab_data.htab);
280 printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
281 printk("-----------------------------------------------------\n");
285 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
286 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
287 vpa_init(boot_cpuid);
291 /* Select the correct idle loop for the platform. */
294 switch (systemcfg->platform) {
295 #ifdef CONFIG_PPC_ISERIES
296 case PLATFORM_ISERIES_LPAR:
301 /* The following relies on the device tree being */
302 /* fully configured. */
303 parse_cmd_line(r3, r4, r5, r6, r7);
307 void machine_restart(char *cmd)
309 if (ppc_md.nvram_sync)
314 EXPORT_SYMBOL(machine_restart);
316 void machine_power_off(void)
318 if (ppc_md.nvram_sync)
323 EXPORT_SYMBOL(machine_power_off);
325 void machine_halt(void)
327 if (ppc_md.nvram_sync)
332 EXPORT_SYMBOL(machine_halt);
334 unsigned long ppc_proc_freq;
335 unsigned long ppc_tb_freq;
337 static int ppc64_panic_event(struct notifier_block *this,
338 unsigned long event, void *ptr)
340 ppc_md.panic((char *)ptr); /* May not return */
346 DEFINE_PER_CPU(unsigned int, pvr);
349 static int show_cpuinfo(struct seq_file *m, void *v)
351 unsigned long cpu_id = (unsigned long)v - 1;
356 if (cpu_id == NR_CPUS) {
357 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
359 if (ppc_md.get_cpuinfo != NULL)
360 ppc_md.get_cpuinfo(m);
365 /* We only show online cpus: disable preempt (overzealous, I
366 * knew) to prevent cpu going down. */
368 if (!cpu_online(cpu_id)) {
374 pvr = per_cpu(pvr, cpu_id);
378 maj = (pvr >> 8) & 0xFF;
381 seq_printf(m, "processor\t: %lu\n", cpu_id);
382 seq_printf(m, "cpu\t\t: ");
384 if (cur_cpu_spec->pvr_mask)
385 seq_printf(m, "%s", cur_cpu_spec->cpu_name);
387 seq_printf(m, "unknown (%08x)", pvr);
389 #ifdef CONFIG_ALTIVEC
390 if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
391 seq_printf(m, ", altivec supported");
392 #endif /* CONFIG_ALTIVEC */
397 * Assume here that all clock rates are the same in a
398 * smp system. -- Cort
400 seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
401 ppc_proc_freq % 1000000);
403 seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
409 static void *c_start(struct seq_file *m, loff_t *pos)
411 return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
413 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
416 return c_start(m, pos);
418 static void c_stop(struct seq_file *m, void *v)
421 struct seq_operations cpuinfo_op = {
425 .show = show_cpuinfo,
429 * Fetch the cmd_line from open firmware.
431 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
432 unsigned long r6, unsigned long r7)
436 #ifdef CONFIG_CMDLINE
437 strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
438 #endif /* CONFIG_CMDLINE */
440 #ifdef CONFIG_PPC_PSERIES
442 struct device_node *chosen;
444 chosen = of_find_node_by_name(NULL, "chosen");
445 if (chosen != NULL) {
447 p = get_property(chosen, "bootargs", NULL);
448 if (p != NULL && p[0] != 0)
449 strlcpy(cmd_line, p, sizeof(cmd_line));
455 /* Look for mem= option on command line */
456 if (strstr(cmd_line, "mem=")) {
458 unsigned long maxmem = 0;
459 extern unsigned long __max_memory;
461 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
463 if (p > cmd_line && p[-1] != ' ')
465 maxmem = simple_strtoul(q, &q, 0);
466 if (*q == 'k' || *q == 'K') {
469 } else if (*q == 'm' || *q == 'M') {
474 __max_memory = maxmem;
478 #ifdef CONFIG_PPC_PSERIES
479 static int __init set_preferred_console(void)
481 struct device_node *prom_stdout;
485 /* The user has requested a console so this is already set up. */
486 if (strstr(saved_command_line, "console="))
489 prom_stdout = find_path_device(of_stdout_device);
493 name = (char *)get_property(prom_stdout, "name", NULL);
497 if (strcmp(name, "serial") == 0) {
499 u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
515 /* We dont recognise the serial port */
519 } else if (strcmp(name, "vty") == 0)
520 /* pSeries LPAR virtual console */
521 return add_preferred_console("hvc", 0, NULL);
522 else if (strcmp(name, "ch-a") == 0)
524 else if (strcmp(name, "ch-b") == 0)
529 return add_preferred_console("ttyS", offset, NULL);
532 console_initcall(set_preferred_console);
534 int parse_bootinfo(void)
536 struct bi_record *rec;
540 if ( rec == NULL || rec->tag != BI_FIRST )
543 for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
546 strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
555 int __init ppc_init(void)
557 /* clear the progress line */
558 ppc_md.progress(" ", 0xffff);
560 if (ppc_md.init != NULL) {
566 arch_initcall(ppc_init);
568 void __init ppc64_calibrate_delay(void)
570 loops_per_jiffy = tb_ticks_per_jiffy;
572 printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
573 loops_per_jiffy/(500000/HZ),
574 loops_per_jiffy/(5000/HZ) % 100);
577 extern void (*calibrate_delay)(void);
579 #ifdef CONFIG_IRQSTACKS
580 static void __init irqstack_early_init(void)
584 /* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */
585 for (i = 0; i < NR_CPUS; i++) {
586 softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
587 THREAD_SIZE, 0x10000000));
588 hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
589 THREAD_SIZE, 0x10000000));
593 #define irqstack_early_init()
597 * Called into from start_kernel, after lock_kernel has been called.
598 * Initializes bootmem, which is unsed to manage page allocation until
599 * mem_init is called.
601 void __init setup_arch(char **cmdline_p)
603 extern int panic_timeout;
604 extern void do_init_bootmem(void);
606 calibrate_delay = ppc64_calibrate_delay;
608 ppc64_boot_msg(0x12, "Setup Arch");
611 if (strstr(cmd_line, "xmon")) {
612 /* ensure xmon is enabled */
616 #endif /* CONFIG_XMON */
619 * Set cache line size based on type of cpu as a default.
620 * Systems with OF can look in the properties on the cpu node(s)
621 * for a possibly more accurate value.
623 dcache_bsize = systemcfg->dCacheL1LineSize;
624 icache_bsize = systemcfg->iCacheL1LineSize;
626 /* reboot on panic */
630 notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
632 init_mm.start_code = PAGE_OFFSET;
633 init_mm.end_code = (unsigned long) _etext;
634 init_mm.end_data = (unsigned long) _edata;
635 init_mm.brk = klimit;
637 /* Save unparsed command line copy for /proc/cmdline */
638 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
639 *cmdline_p = cmd_line;
641 irqstack_early_init();
643 /* set up the bootmem stuff with available memory */
649 ppc64_boot_msg(0x15, "Setup Done");
652 /* ToDo: do something useful if ppc_md is not yet setup. */
653 #define PPC64_LINUX_FUNCTION 0x0f000000
654 #define PPC64_IPL_MESSAGE 0xc0000000
655 #define PPC64_TERM_MESSAGE 0xb0000000
656 #define PPC64_ATTN_MESSAGE 0xa0000000
657 #define PPC64_DUMP_MESSAGE 0xd0000000
659 static void ppc64_do_msg(unsigned int src, const char *msg)
661 if (ppc_md.progress) {
664 sprintf(buf, "%08x \n", src);
665 ppc_md.progress(buf, 0);
666 sprintf(buf, "%-16s", msg);
667 ppc_md.progress(buf, 0);
671 /* Print a boot progress message. */
672 void ppc64_boot_msg(unsigned int src, const char *msg)
674 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
675 printk("[boot]%04x %s\n", src, msg);
678 /* Print a termination message (print only -- does not stop the kernel) */
679 void ppc64_terminate_msg(unsigned int src, const char *msg)
681 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
682 printk("[terminate]%04x %s\n", src, msg);
685 /* Print something that needs attention (device error, etc) */
686 void ppc64_attention_msg(unsigned int src, const char *msg)
688 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
689 printk("[attention]%04x %s\n", src, msg);
692 /* Print a dump progress message. */
693 void ppc64_dump_msg(unsigned int src, const char *msg)
695 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
696 printk("[dump]%04x %s\n", src, msg);
699 int set_spread_lpevents( char * str )
701 /* The parameter is the number of processors to share in processing lp events */
703 unsigned long val = simple_strtoul( str, NULL, 0 );
704 if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
705 for ( i=1; i<val; ++i )
706 paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
707 printk("lpevent processing spread over %ld processors\n", val);
710 printk("invalid spreaqd_lpevents %ld\n", val);
714 /* This should only be called on processor 0 during calibrate decr */
715 void setup_default_decr(void)
717 struct paca_struct *lpaca = get_paca();
719 if ( decr_overclock_set && !decr_overclock_proc0_set )
720 decr_overclock_proc0 = decr_overclock;
722 lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
723 lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
726 int set_decr_overclock_proc0( char * str )
728 unsigned long val = simple_strtoul( str, NULL, 0 );
729 if ( ( val >= 1 ) && ( val <= 48 ) ) {
730 decr_overclock_proc0_set = 1;
731 decr_overclock_proc0 = val;
732 printk("proc 0 decrementer overclock factor of %ld\n", val);
735 printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
739 int set_decr_overclock( char * str )
741 unsigned long val = simple_strtoul( str, NULL, 0 );
742 if ( ( val >= 1 ) && ( val <= 48 ) ) {
743 decr_overclock_set = 1;
744 decr_overclock = val;
745 printk("decrementer overclock factor of %ld\n", val);
748 printk("invalid decrementer overclock factor of %ld\n", val);
753 __setup("spread_lpevents=", set_spread_lpevents );
754 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
755 __setup("decr_overclock=", set_decr_overclock );