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/system.h>
49 extern unsigned long klimit;
50 /* extern void *stab; */
51 extern HTAB htab_data;
52 extern unsigned long loops_per_jiffy;
56 extern void chrp_init(unsigned long r3,
62 extern void pmac_init(unsigned long r3,
68 extern void iSeries_init( void );
69 extern void iSeries_init_early( void );
70 extern void pSeries_init_early( void );
71 extern void pSeriesLP_init_early(void);
72 extern void pmac_init_early(void);
73 extern void mm_init_ppc64( void );
74 extern void pseries_secondary_smp_init(unsigned long);
75 extern int idle_setup(void);
76 extern void vpa_init(int cpu);
78 unsigned long decr_overclock = 1;
79 unsigned long decr_overclock_proc0 = 1;
80 unsigned long decr_overclock_set = 0;
81 unsigned long decr_overclock_proc0_set = 0;
85 char saved_command_line[COMMAND_LINE_SIZE];
86 unsigned char aux_device_present;
88 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
89 unsigned long r6, unsigned long r7);
90 int parse_bootinfo(void);
92 #ifdef CONFIG_MAGIC_SYSRQ
93 unsigned long SYSRQ_KEY;
94 #endif /* CONFIG_MAGIC_SYSRQ */
96 struct machdep_calls ppc_md;
98 static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
100 static struct notifier_block ppc64_panic_block = {
101 notifier_call: ppc64_panic_event,
102 priority: INT_MIN /* may not return; must be done last */
106 * Perhaps we can put the pmac screen_info[] here
107 * on pmac as well so we don't need the ifdef's.
108 * Until we get multiple-console support in here
110 * Maybe tie it to serial consoles, since this is really what
111 * these processors use on existing boards. -- Dan
113 struct screen_info screen_info = {
114 0, 25, /* orig-x, orig-y */
116 0, /* orig-video-page */
117 0, /* orig-video-mode */
118 80, /* orig-video-cols */
119 0,0,0, /* ega_ax, ega_bx, ega_cx */
120 25, /* orig-video-lines */
121 1, /* orig-video-isVGA */
122 16 /* orig-video-points */
126 * These are used in binfmt_elf.c to put aux entries on the stack
127 * for each elf executable being started.
134 * Initialize the PPCDBG state. Called before relocation has been enabled.
136 void ppcdbg_initialize(void) {
137 unsigned long offset = reloc_offset();
138 struct naca_struct *_naca = RELOC(naca);
140 _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
143 static struct console udbg_console = {
145 .write = udbg_console_write,
146 .flags = CON_PRINTBUFFER,
150 static int early_console_initialized;
152 void __init disable_early_printk(void)
154 if (!early_console_initialized)
156 unregister_console(&udbg_console);
157 early_console_initialized = 0;
161 * Do some initial setup of the system. The parameters are those which
162 * were passed in from the bootloader.
164 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
165 unsigned long r6, unsigned long r7)
167 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
171 #ifdef CONFIG_XMON_DEFAULT
175 #ifdef CONFIG_PPC_ISERIES
176 /* pSeries systems are identified in prom.c via OF. */
177 if ( itLpNaca.xLparInstalled == 1 )
178 systemcfg->platform = PLATFORM_ISERIES_LPAR;
181 switch (systemcfg->platform) {
182 #ifdef CONFIG_PPC_ISERIES
183 case PLATFORM_ISERIES_LPAR:
184 iSeries_init_early();
188 #ifdef CONFIG_PPC_PSERIES
189 case PLATFORM_PSERIES:
190 pSeries_init_early();
194 case PLATFORM_PSERIES_LPAR:
195 pSeriesLP_init_early();
198 #endif /* CONFIG_PPC_PSERIES */
199 #ifdef CONFIG_PPC_PMAC
200 case PLATFORM_POWERMAC:
203 #endif /* CONFIG_PPC_PMAC */
206 /* If we were passed an initrd, set the ROOT_DEV properly if the values
207 * look sensible. If not, clear initrd reference.
209 #ifdef CONFIG_BLK_DEV_INITRD
210 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
211 initrd_end > initrd_start)
212 ROOT_DEV = Root_RAM0;
214 initrd_start = initrd_end = 0;
215 #endif /* CONFIG_BLK_DEV_INITRD */
217 #ifdef CONFIG_BOOTX_TEXT
219 if (systemcfg->platform == PLATFORM_POWERMAC) {
220 early_console_initialized = 1;
221 register_console(&udbg_console);
223 #endif /* CONFIG_BOOTX_TEXT */
225 #ifdef CONFIG_PPC_PSERIES
226 if (systemcfg->platform & PLATFORM_PSERIES) {
227 early_console_initialized = 1;
228 register_console(&udbg_console);
229 __irq_offset_value = NUM_ISA_INTERRUPTS;
230 finish_device_tree();
231 chrp_init(r3, r4, r5, r6, r7);
234 /* Start secondary threads on SMT systems */
235 for (i = 0; i < NR_CPUS; i++) {
236 if(cpu_available(i) && !cpu_possible(i)) {
237 printk("%16.16x : starting thread\n", i);
238 rtas_call(rtas_token("start-cpu"), 3, 1,
240 get_hard_smp_processor_id(i),
241 *((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 /* Finish initializing the hash table (do the dynamic
259 * patching for the fast-path hashtable.S code)
263 printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
265 printk("-----------------------------------------------------\n");
266 printk("naca = 0x%p\n", naca);
267 printk("naca->pftSize = 0x%lx\n", naca->pftSize);
268 printk("naca->debug_switch = 0x%lx\n", naca->debug_switch);
269 printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller);
270 printk("systemcfg = 0x%p\n", systemcfg);
271 printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
272 printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
273 printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize);
274 printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize);
275 printk("htab_data.htab = 0x%p\n", htab_data.htab);
276 printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
277 printk("-----------------------------------------------------\n");
281 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
282 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
283 vpa_init(boot_cpuid);
287 /* Select the correct idle loop for the platform. */
290 switch (systemcfg->platform) {
291 #ifdef CONFIG_PPC_ISERIES
292 case PLATFORM_ISERIES_LPAR:
297 /* The following relies on the device tree being */
298 /* fully configured. */
299 parse_cmd_line(r3, r4, r5, r6, r7);
303 void machine_restart(char *cmd)
305 if (ppc_md.nvram_sync)
310 EXPORT_SYMBOL(machine_restart);
312 void machine_power_off(void)
314 if (ppc_md.nvram_sync)
319 EXPORT_SYMBOL(machine_power_off);
321 void machine_halt(void)
323 if (ppc_md.nvram_sync)
328 EXPORT_SYMBOL(machine_halt);
330 unsigned long ppc_proc_freq;
331 unsigned long ppc_tb_freq;
333 static int ppc64_panic_event(struct notifier_block *this,
334 unsigned long event, void *ptr)
336 ppc_md.panic((char *)ptr); /* May not return */
342 DEFINE_PER_CPU(unsigned int, pvr);
345 static int show_cpuinfo(struct seq_file *m, void *v)
347 unsigned long cpu_id = (unsigned long)v - 1;
352 if (cpu_id == NR_CPUS) {
353 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
355 if (ppc_md.get_cpuinfo != NULL)
356 ppc_md.get_cpuinfo(m);
361 /* We only show online cpus: disable preempt (overzealous, I
362 * knew) to prevent cpu going down. */
364 if (!cpu_online(cpu_id)) {
370 pvr = per_cpu(pvr, cpu_id);
374 maj = (pvr >> 8) & 0xFF;
377 seq_printf(m, "processor\t: %lu\n", cpu_id);
378 seq_printf(m, "cpu\t\t: ");
380 if (cur_cpu_spec->pvr_mask)
381 seq_printf(m, "%s", cur_cpu_spec->cpu_name);
383 seq_printf(m, "unknown (%08x)", pvr);
385 #ifdef CONFIG_ALTIVEC
386 if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
387 seq_printf(m, ", altivec supported");
388 #endif /* CONFIG_ALTIVEC */
393 * Assume here that all clock rates are the same in a
394 * smp system. -- Cort
396 seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
397 ppc_proc_freq % 1000000);
399 seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
405 static void *c_start(struct seq_file *m, loff_t *pos)
407 return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
409 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
412 return c_start(m, pos);
414 static void c_stop(struct seq_file *m, void *v)
417 struct seq_operations cpuinfo_op = {
421 .show = show_cpuinfo,
425 * Fetch the cmd_line from open firmware.
427 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
428 unsigned long r6, unsigned long r7)
432 #ifdef CONFIG_CMDLINE
433 strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
434 #endif /* CONFIG_CMDLINE */
436 #ifdef CONFIG_PPC_PSERIES
438 struct device_node *chosen;
440 chosen = of_find_node_by_name(NULL, "chosen");
441 if (chosen != NULL) {
443 p = get_property(chosen, "bootargs", NULL);
444 if (p != NULL && p[0] != 0)
445 strlcpy(cmd_line, p, sizeof(cmd_line));
451 /* Look for mem= option on command line */
452 if (strstr(cmd_line, "mem=")) {
454 unsigned long maxmem = 0;
455 extern unsigned long __max_memory;
457 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
459 if (p > cmd_line && p[-1] != ' ')
461 maxmem = simple_strtoul(q, &q, 0);
462 if (*q == 'k' || *q == 'K') {
465 } else if (*q == 'm' || *q == 'M') {
470 __max_memory = maxmem;
474 #ifdef CONFIG_PPC_PSERIES
475 static int __init set_preferred_console(void)
477 struct device_node *prom_stdout;
481 /* The user has requested a console so this is already set up. */
482 if (strstr(saved_command_line, "console="))
485 prom_stdout = find_path_device(of_stdout_device);
489 name = (char *)get_property(prom_stdout, "name", NULL);
493 if (strcmp(name, "serial") == 0) {
495 u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
511 /* We dont recognise the serial port */
515 } else if (strcmp(name, "vty") == 0)
516 /* pSeries LPAR virtual console */
517 return add_preferred_console("hvc", 0, NULL);
518 else if (strcmp(name, "ch-a") == 0)
520 else if (strcmp(name, "ch-b") == 0)
525 return add_preferred_console("ttyS", offset, NULL);
528 console_initcall(set_preferred_console);
530 int parse_bootinfo(void)
532 struct bi_record *rec;
536 if ( rec == NULL || rec->tag != BI_FIRST )
539 for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
542 strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
551 int __init ppc_init(void)
553 /* clear the progress line */
554 ppc_md.progress(" ", 0xffff);
556 if (ppc_md.init != NULL) {
562 arch_initcall(ppc_init);
564 void __init ppc64_calibrate_delay(void)
566 loops_per_jiffy = tb_ticks_per_jiffy;
568 printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
569 loops_per_jiffy/(500000/HZ),
570 loops_per_jiffy/(5000/HZ) % 100);
573 extern void (*calibrate_delay)(void);
575 #ifdef CONFIG_IRQSTACKS
576 static void __init irqstack_early_init(void)
580 /* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */
581 for (i = 0; i < NR_CPUS; i++) {
582 softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
583 THREAD_SIZE, 0x10000000));
584 hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
585 THREAD_SIZE, 0x10000000));
589 #define irqstack_early_init()
593 * Called into from start_kernel, after lock_kernel has been called.
594 * Initializes bootmem, which is unsed to manage page allocation until
595 * mem_init is called.
597 void __init setup_arch(char **cmdline_p)
599 extern int panic_timeout;
600 extern void do_init_bootmem(void);
602 calibrate_delay = ppc64_calibrate_delay;
604 ppc64_boot_msg(0x12, "Setup Arch");
607 if (strstr(cmd_line, "xmon")) {
608 /* ensure xmon is enabled */
612 #endif /* CONFIG_XMON */
615 * Set cache line size based on type of cpu as a default.
616 * Systems with OF can look in the properties on the cpu node(s)
617 * for a possibly more accurate value.
619 dcache_bsize = systemcfg->dCacheL1LineSize;
620 icache_bsize = systemcfg->iCacheL1LineSize;
622 /* reboot on panic */
626 notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
628 init_mm.start_code = PAGE_OFFSET;
629 init_mm.end_code = (unsigned long) _etext;
630 init_mm.end_data = (unsigned long) _edata;
631 init_mm.brk = klimit;
633 /* Save unparsed command line copy for /proc/cmdline */
634 strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line));
635 *cmdline_p = cmd_line;
637 irqstack_early_init();
639 /* set up the bootmem stuff with available memory */
645 ppc64_boot_msg(0x15, "Setup Done");
648 /* ToDo: do something useful if ppc_md is not yet setup. */
649 #define PPC64_LINUX_FUNCTION 0x0f000000
650 #define PPC64_IPL_MESSAGE 0xc0000000
651 #define PPC64_TERM_MESSAGE 0xb0000000
652 #define PPC64_ATTN_MESSAGE 0xa0000000
653 #define PPC64_DUMP_MESSAGE 0xd0000000
655 static void ppc64_do_msg(unsigned int src, const char *msg)
657 if (ppc_md.progress) {
660 sprintf(buf, "%08x \n", src);
661 ppc_md.progress(buf, 0);
662 sprintf(buf, "%-16s", msg);
663 ppc_md.progress(buf, 0);
667 /* Print a boot progress message. */
668 void ppc64_boot_msg(unsigned int src, const char *msg)
670 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
671 printk("[boot]%04x %s\n", src, msg);
674 /* Print a termination message (print only -- does not stop the kernel) */
675 void ppc64_terminate_msg(unsigned int src, const char *msg)
677 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
678 printk("[terminate]%04x %s\n", src, msg);
681 /* Print something that needs attention (device error, etc) */
682 void ppc64_attention_msg(unsigned int src, const char *msg)
684 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
685 printk("[attention]%04x %s\n", src, msg);
688 /* Print a dump progress message. */
689 void ppc64_dump_msg(unsigned int src, const char *msg)
691 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
692 printk("[dump]%04x %s\n", src, msg);
695 int set_spread_lpevents( char * str )
697 /* The parameter is the number of processors to share in processing lp events */
699 unsigned long val = simple_strtoul( str, NULL, 0 );
700 if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
701 for ( i=1; i<val; ++i )
702 paca[i].lpQueuePtr = paca[0].lpQueuePtr;
703 printk("lpevent processing spread over %ld processors\n", val);
706 printk("invalid spreaqd_lpevents %ld\n", val);
710 /* This should only be called on processor 0 during calibrate decr */
711 void setup_default_decr(void)
713 struct paca_struct *lpaca = get_paca();
715 if ( decr_overclock_set && !decr_overclock_proc0_set )
716 decr_overclock_proc0 = decr_overclock;
718 lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
719 lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
722 int set_decr_overclock_proc0( char * str )
724 unsigned long val = simple_strtoul( str, NULL, 0 );
725 if ( ( val >= 1 ) && ( val <= 48 ) ) {
726 decr_overclock_proc0_set = 1;
727 decr_overclock_proc0 = val;
728 printk("proc 0 decrementer overclock factor of %ld\n", val);
731 printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
735 int set_decr_overclock( char * str )
737 unsigned long val = simple_strtoul( str, NULL, 0 );
738 if ( ( val >= 1 ) && ( val <= 48 ) ) {
739 decr_overclock_set = 1;
740 decr_overclock = val;
741 printk("decrementer overclock factor of %ld\n", val);
744 printk("invalid decrementer overclock factor of %ld\n", val);
749 __setup("spread_lpevents=", set_spread_lpevents );
750 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
751 __setup("decr_overclock=", set_decr_overclock );