patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / ppc64 / kernel / setup.c
1 /*
2  * 
3  * Common boot and setup code.
4  *
5  * Copyright (C) 2001 PPC64 Team, IBM Corp
6  *
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.
11  */
12
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>
30 #include <asm/io.h>
31 #include <asm/prom.h>
32 #include <asm/processor.h>
33 #include <asm/pgtable.h>
34 #include <asm/bootinfo.h>
35 #include <asm/smp.h>
36 #include <asm/elf.h>
37 #include <asm/machdep.h>
38 #include <asm/iSeries/LparData.h>
39 #include <asm/naca.h>
40 #include <asm/paca.h>
41 #include <asm/ppcdebug.h>
42 #include <asm/time.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>
48
49 extern unsigned long klimit;
50 /* extern void *stab; */
51 extern HTAB htab_data;
52 extern unsigned long loops_per_jiffy;
53
54 int have_of = 1;
55
56 extern void  chrp_init(unsigned long r3,
57                        unsigned long r4,
58                        unsigned long r5,
59                        unsigned long r6,
60                        unsigned long r7);
61
62 extern void  pmac_init(unsigned long r3,
63                        unsigned long r4,
64                        unsigned long r5,
65                        unsigned long r6,
66                        unsigned long r7);
67
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);
77
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;
82
83 int powersave_nap;
84
85 char saved_command_line[COMMAND_LINE_SIZE];
86 unsigned char aux_device_present;
87
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);
91
92 #ifdef CONFIG_MAGIC_SYSRQ
93 unsigned long SYSRQ_KEY;
94 #endif /* CONFIG_MAGIC_SYSRQ */
95
96 struct machdep_calls ppc_md;
97
98 static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
99
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 */
103 };
104
105 /*
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
109  * that is.  -- Cort
110  * Maybe tie it to serial consoles, since this is really what
111  * these processors use on existing boards.  -- Dan
112  */ 
113 struct screen_info screen_info = {
114         0, 25,                  /* orig-x, orig-y */
115         0,                      /* unused */
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 */
123 };
124
125 /*
126  * These are used in binfmt_elf.c to put aux entries on the stack
127  * for each elf executable being started.
128  */
129 int dcache_bsize;
130 int icache_bsize;
131 int ucache_bsize;
132
133 /*
134  * Initialize the PPCDBG state.  Called before relocation has been enabled.
135  */
136 void ppcdbg_initialize(void) {
137         unsigned long offset = reloc_offset();
138         struct naca_struct *_naca = RELOC(naca);
139
140         _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
141 }
142
143 static struct console udbg_console = {
144         .name   = "udbg",
145         .write  = udbg_console_write,
146         .flags  = CON_PRINTBUFFER,
147         .index  = -1,
148 };
149
150 static int early_console_initialized;
151
152 void __init disable_early_printk(void)
153 {
154         if (!early_console_initialized)
155                 return;
156         unregister_console(&udbg_console);
157         early_console_initialized = 0;
158 }
159
160 /*
161  * Do some initial setup of the system.  The parameters are those which 
162  * were passed in from the bootloader.
163  */
164 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
165                   unsigned long r6, unsigned long r7)
166 {
167 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
168         unsigned int ret, i;
169 #endif
170
171 #ifdef CONFIG_XMON_DEFAULT
172         xmon_init();
173 #endif
174
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;
179 #endif
180         
181         switch (systemcfg->platform) {
182 #ifdef CONFIG_PPC_ISERIES
183         case PLATFORM_ISERIES_LPAR:
184                 iSeries_init_early();
185                 break;
186 #endif
187
188 #ifdef CONFIG_PPC_PSERIES
189         case PLATFORM_PSERIES:
190                 pSeries_init_early();
191                 parse_bootinfo();
192                 break;
193
194         case PLATFORM_PSERIES_LPAR:
195                 pSeriesLP_init_early();
196                 parse_bootinfo();
197                 break;
198 #endif /* CONFIG_PPC_PSERIES */
199 #ifdef CONFIG_PPC_PMAC
200         case PLATFORM_POWERMAC:
201                 pmac_init_early();
202                 parse_bootinfo();
203 #endif /* CONFIG_PPC_PMAC */
204         }
205
206         /* If we were passed an initrd, set the ROOT_DEV properly if the values
207          * look sensible. If not, clear initrd reference.
208          */
209 #ifdef CONFIG_BLK_DEV_INITRD
210         if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
211             initrd_end > initrd_start)
212                 ROOT_DEV = Root_RAM0;
213         else
214                 initrd_start = initrd_end = 0;
215 #endif /* CONFIG_BLK_DEV_INITRD */
216
217 #ifdef CONFIG_BOOTX_TEXT
218         map_boot_text();
219         if (systemcfg->platform == PLATFORM_POWERMAC) {
220                 early_console_initialized = 1;
221                 register_console(&udbg_console);
222         }
223 #endif /* CONFIG_BOOTX_TEXT */
224
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);
232
233 #ifdef CONFIG_SMP
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, 
239                                           (void *)&ret,
240                                           get_hard_smp_processor_id(i), 
241                                           *((unsigned long *)pseries_secondary_smp_init),
242                                           i);
243                                 cpu_set(i, cpu_possible_map);
244                                 systemcfg->processorCount++;
245                         }
246                 }
247 #endif /* CONFIG_SMP */
248         }
249 #endif /* CONFIG_PPC_PSERIES */
250
251 #ifdef CONFIG_PPC_PMAC
252         if (systemcfg->platform == PLATFORM_POWERMAC) {
253                 finish_device_tree();
254                 pmac_init(r3, r4, r5, r6, r7);
255         }
256 #endif /* CONFIG_PPC_PMAC */
257
258         /* Finish initializing the hash table (do the dynamic
259          * patching for the fast-path hashtable.S code)
260          */
261         htab_finish_init();
262
263         printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
264
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");
278
279         mm_init_ppc64();
280
281 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
282         if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
283                 vpa_init(boot_cpuid);
284         }
285 #endif
286
287         /* Select the correct idle loop for the platform. */
288         idle_setup();
289
290         switch (systemcfg->platform) {
291 #ifdef CONFIG_PPC_ISERIES
292         case PLATFORM_ISERIES_LPAR:
293                 iSeries_init();
294                 break;
295 #endif
296         default:
297                 /* The following relies on the device tree being */
298                 /* fully configured.                             */
299                 parse_cmd_line(r3, r4, r5, r6, r7);
300         }
301 }
302
303 void machine_restart(char *cmd)
304 {
305         if (ppc_md.nvram_sync)
306                 ppc_md.nvram_sync();
307         ppc_md.restart(cmd);
308 }
309
310 EXPORT_SYMBOL(machine_restart);
311   
312 void machine_power_off(void)
313 {
314         if (ppc_md.nvram_sync)
315                 ppc_md.nvram_sync();
316         ppc_md.power_off();
317 }
318
319 EXPORT_SYMBOL(machine_power_off);
320   
321 void machine_halt(void)
322 {
323         if (ppc_md.nvram_sync)
324                 ppc_md.nvram_sync();
325         ppc_md.halt();
326 }
327
328 EXPORT_SYMBOL(machine_halt);
329
330 unsigned long ppc_proc_freq;
331 unsigned long ppc_tb_freq;
332
333 static int ppc64_panic_event(struct notifier_block *this,
334                              unsigned long event, void *ptr)
335 {
336         ppc_md.panic((char *)ptr);  /* May not return */
337         return NOTIFY_DONE;
338 }
339
340
341 #ifdef CONFIG_SMP
342 DEFINE_PER_CPU(unsigned int, pvr);
343 #endif
344
345 static int show_cpuinfo(struct seq_file *m, void *v)
346 {
347         unsigned long cpu_id = (unsigned long)v - 1;
348         unsigned int pvr;
349         unsigned short maj;
350         unsigned short min;
351
352         if (cpu_id == NR_CPUS) {
353                 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
354
355                 if (ppc_md.get_cpuinfo != NULL)
356                         ppc_md.get_cpuinfo(m);
357
358                 return 0;
359         }
360
361         /* We only show online cpus: disable preempt (overzealous, I
362          * knew) to prevent cpu going down. */
363         preempt_disable();
364         if (!cpu_online(cpu_id)) {
365                 preempt_enable();
366                 return 0;
367         }
368
369 #ifdef CONFIG_SMP
370         pvr = per_cpu(pvr, cpu_id);
371 #else
372         pvr = _get_PVR();
373 #endif
374         maj = (pvr >> 8) & 0xFF;
375         min = pvr & 0xFF;
376
377         seq_printf(m, "processor\t: %lu\n", cpu_id);
378         seq_printf(m, "cpu\t\t: ");
379
380         if (cur_cpu_spec->pvr_mask)
381                 seq_printf(m, "%s", cur_cpu_spec->cpu_name);
382         else
383                 seq_printf(m, "unknown (%08x)", pvr);
384
385 #ifdef CONFIG_ALTIVEC
386         if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
387                 seq_printf(m, ", altivec supported");
388 #endif /* CONFIG_ALTIVEC */
389
390         seq_printf(m, "\n");
391
392         /*
393          * Assume here that all clock rates are the same in a
394          * smp system.  -- Cort
395          */
396         seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
397                    ppc_proc_freq % 1000000);
398
399         seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
400
401         preempt_enable();
402         return 0;
403 }
404
405 static void *c_start(struct seq_file *m, loff_t *pos)
406 {
407         return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
408 }
409 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
410 {
411         ++*pos;
412         return c_start(m, pos);
413 }
414 static void c_stop(struct seq_file *m, void *v)
415 {
416 }
417 struct seq_operations cpuinfo_op = {
418         .start =c_start,
419         .next = c_next,
420         .stop = c_stop,
421         .show = show_cpuinfo,
422 };
423
424 /*
425  * Fetch the cmd_line from open firmware. 
426  */
427 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
428                   unsigned long r6, unsigned long r7)
429 {
430         cmd_line[0] = 0;
431
432 #ifdef CONFIG_CMDLINE
433         strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
434 #endif /* CONFIG_CMDLINE */
435
436 #ifdef CONFIG_PPC_PSERIES
437         {
438         struct device_node *chosen;
439
440         chosen = of_find_node_by_name(NULL, "chosen");
441         if (chosen != NULL) {
442                 char *p;
443                 p = get_property(chosen, "bootargs", NULL);
444                 if (p != NULL && p[0] != 0)
445                         strlcpy(cmd_line, p, sizeof(cmd_line));
446                 of_node_put(chosen);
447         }
448         }
449 #endif
450
451         /* Look for mem= option on command line */
452         if (strstr(cmd_line, "mem=")) {
453                 char *p, *q;
454                 unsigned long maxmem = 0;
455                 extern unsigned long __max_memory;
456
457                 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
458                         q = p + 4;
459                         if (p > cmd_line && p[-1] != ' ')
460                                 continue;
461                         maxmem = simple_strtoul(q, &q, 0);
462                         if (*q == 'k' || *q == 'K') {
463                                 maxmem <<= 10;
464                                 ++q;
465                         } else if (*q == 'm' || *q == 'M') {
466                                 maxmem <<= 20;
467                                 ++q;
468                         }
469                 }
470                 __max_memory = maxmem;
471         }
472 }
473
474 #ifdef CONFIG_PPC_PSERIES
475 static int __init set_preferred_console(void)
476 {
477         struct device_node *prom_stdout;
478         char *name;
479         int offset;
480
481         /* The user has requested a console so this is already set up. */
482         if (strstr(saved_command_line, "console="))
483                 return -EBUSY;
484
485         prom_stdout = find_path_device(of_stdout_device);
486         if (!prom_stdout)
487                 return -ENODEV;
488
489         name = (char *)get_property(prom_stdout, "name", NULL);
490         if (!name)
491                 return -ENODEV;
492
493         if (strcmp(name, "serial") == 0) {
494                 int i;
495                 u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
496                 if (i > 8) {
497                         switch (reg[1]) {
498                                 case 0x3f8:
499                                         offset = 0;
500                                         break;
501                                 case 0x2f8:
502                                         offset = 1;
503                                         break;
504                                 case 0x898:
505                                         offset = 2;
506                                         break;
507                                 case 0x890:
508                                         offset = 3;
509                                         break;
510                                 default:
511                                         /* We dont recognise the serial port */
512                                         return -ENODEV;
513                         }
514                 }
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)
519                 offset = 0;
520         else if (strcmp(name, "ch-b") == 0)
521                 offset = 1;
522         else
523                 return -ENODEV;
524
525         return add_preferred_console("ttyS", offset, NULL);
526
527 }
528 console_initcall(set_preferred_console);
529
530 int parse_bootinfo(void)
531 {
532         struct bi_record *rec;
533
534         rec = prom.bi_recs;
535
536         if ( rec == NULL || rec->tag != BI_FIRST )
537                 return -1;
538
539         for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
540                 switch (rec->tag) {
541                 case BI_CMD_LINE:
542                         strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
543                         break;
544                 }
545         }
546
547         return 0;
548 }
549 #endif
550
551 int __init ppc_init(void)
552 {
553         /* clear the progress line */
554         ppc_md.progress(" ", 0xffff);
555
556         if (ppc_md.init != NULL) {
557                 ppc_md.init();
558         }
559         return 0;
560 }
561
562 arch_initcall(ppc_init);
563
564 void __init ppc64_calibrate_delay(void)
565 {
566         loops_per_jiffy = tb_ticks_per_jiffy;
567
568         printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
569                                loops_per_jiffy/(500000/HZ),
570                                loops_per_jiffy/(5000/HZ) % 100);
571 }       
572
573 extern void (*calibrate_delay)(void);
574
575 #ifdef CONFIG_IRQSTACKS
576 static void __init irqstack_early_init(void)
577 {
578         int i;
579
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));
586         }
587 }
588 #else
589 #define irqstack_early_init()
590 #endif
591
592 /*
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.
596  */
597 void __init setup_arch(char **cmdline_p)
598 {
599         extern int panic_timeout;
600         extern void do_init_bootmem(void);
601
602         calibrate_delay = ppc64_calibrate_delay;
603
604         ppc64_boot_msg(0x12, "Setup Arch");
605
606 #ifdef CONFIG_XMON
607         if (strstr(cmd_line, "xmon")) {
608                 /* ensure xmon is enabled */
609                 xmon_init();
610                 debugger(0);
611         }
612 #endif /* CONFIG_XMON */
613
614         /*
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.
618          */
619         dcache_bsize = systemcfg->dCacheL1LineSize; 
620         icache_bsize = systemcfg->iCacheL1LineSize; 
621
622         /* reboot on panic */
623         panic_timeout = 180;
624
625         if (ppc_md.panic)
626                 notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
627
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;
632         
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;
636
637         irqstack_early_init();
638
639         /* set up the bootmem stuff with available memory */
640         do_init_bootmem();
641
642         ppc_md.setup_arch();
643
644         paging_init();
645         ppc64_boot_msg(0x15, "Setup Done");
646 }
647
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
654
655 static void ppc64_do_msg(unsigned int src, const char *msg)
656 {
657         if (ppc_md.progress) {
658                 char buf[32];
659
660                 sprintf(buf, "%08x        \n", src);
661                 ppc_md.progress(buf, 0);
662                 sprintf(buf, "%-16s", msg);
663                 ppc_md.progress(buf, 0);
664         }
665 }
666
667 /* Print a boot progress message. */
668 void ppc64_boot_msg(unsigned int src, const char *msg)
669 {
670         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
671         printk("[boot]%04x %s\n", src, msg);
672 }
673
674 /* Print a termination message (print only -- does not stop the kernel) */
675 void ppc64_terminate_msg(unsigned int src, const char *msg)
676 {
677         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
678         printk("[terminate]%04x %s\n", src, msg);
679 }
680
681 /* Print something that needs attention (device error, etc) */
682 void ppc64_attention_msg(unsigned int src, const char *msg)
683 {
684         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
685         printk("[attention]%04x %s\n", src, msg);
686 }
687
688 /* Print a dump progress message. */
689 void ppc64_dump_msg(unsigned int src, const char *msg)
690 {
691         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
692         printk("[dump]%04x %s\n", src, msg);
693 }
694
695 int set_spread_lpevents( char * str )
696 {
697         /* The parameter is the number of processors to share in processing lp events */
698         unsigned long i;
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);
704         }
705         else
706                 printk("invalid spreaqd_lpevents %ld\n", val);
707         return 1;
708 }       
709
710 /* This should only be called on processor 0 during calibrate decr */
711 void setup_default_decr(void)
712 {
713         struct paca_struct *lpaca = get_paca();
714
715         if ( decr_overclock_set && !decr_overclock_proc0_set )
716                 decr_overclock_proc0 = decr_overclock;
717
718         lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;        
719         lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
720 }
721
722 int set_decr_overclock_proc0( char * str )
723 {
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);
729         }
730         else
731                 printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
732         return 1;
733 }
734
735 int set_decr_overclock( char * str )
736 {
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);
742         }
743         else
744                 printk("invalid decrementer overclock factor of %ld\n", val);
745         return 1;
746
747 }
748
749 __setup("spread_lpevents=", set_spread_lpevents );
750 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
751 __setup("decr_overclock=", set_decr_overclock );