xref: /openbmc/linux/arch/powerpc/kernel/setup_32.c (revision dd184343b45e94fd3b0d4d0865070924bc6195ab)
170d64ceaSPaul Mackerras /*
270d64ceaSPaul Mackerras  * Common prep/pmac/chrp boot and setup code.
370d64ceaSPaul Mackerras  */
470d64ceaSPaul Mackerras 
570d64ceaSPaul Mackerras #include <linux/config.h>
670d64ceaSPaul Mackerras #include <linux/module.h>
770d64ceaSPaul Mackerras #include <linux/string.h>
870d64ceaSPaul Mackerras #include <linux/sched.h>
970d64ceaSPaul Mackerras #include <linux/init.h>
1070d64ceaSPaul Mackerras #include <linux/kernel.h>
1170d64ceaSPaul Mackerras #include <linux/reboot.h>
1270d64ceaSPaul Mackerras #include <linux/delay.h>
1370d64ceaSPaul Mackerras #include <linux/initrd.h>
1470d64ceaSPaul Mackerras #include <linux/ide.h>
1570d64ceaSPaul Mackerras #include <linux/tty.h>
1670d64ceaSPaul Mackerras #include <linux/bootmem.h>
1770d64ceaSPaul Mackerras #include <linux/seq_file.h>
1870d64ceaSPaul Mackerras #include <linux/root_dev.h>
1970d64ceaSPaul Mackerras #include <linux/cpu.h>
2070d64ceaSPaul Mackerras #include <linux/console.h>
2170d64ceaSPaul Mackerras 
2270d64ceaSPaul Mackerras #include <asm/residual.h>
2370d64ceaSPaul Mackerras #include <asm/io.h>
2470d64ceaSPaul Mackerras #include <asm/prom.h>
2570d64ceaSPaul Mackerras #include <asm/processor.h>
2670d64ceaSPaul Mackerras #include <asm/pgtable.h>
2770d64ceaSPaul Mackerras #include <asm/bootinfo.h>
2870d64ceaSPaul Mackerras #include <asm/setup.h>
2970d64ceaSPaul Mackerras #include <asm/amigappc.h>
3070d64ceaSPaul Mackerras #include <asm/smp.h>
3170d64ceaSPaul Mackerras #include <asm/elf.h>
3270d64ceaSPaul Mackerras #include <asm/cputable.h>
3370d64ceaSPaul Mackerras #include <asm/bootx.h>
3470d64ceaSPaul Mackerras #include <asm/btext.h>
3570d64ceaSPaul Mackerras #include <asm/machdep.h>
3670d64ceaSPaul Mackerras #include <asm/uaccess.h>
3770d64ceaSPaul Mackerras #include <asm/system.h>
3870d64ceaSPaul Mackerras #include <asm/pmac_feature.h>
3970d64ceaSPaul Mackerras #include <asm/sections.h>
4070d64ceaSPaul Mackerras #include <asm/nvram.h>
4170d64ceaSPaul Mackerras #include <asm/xmon.h>
4270d64ceaSPaul Mackerras #include <asm/ocp.h>
4370d64ceaSPaul Mackerras 
4470d64ceaSPaul Mackerras #define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \
4570d64ceaSPaul Mackerras 		      defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \
4670d64ceaSPaul Mackerras 		      defined(CONFIG_PPC_MPC52xx))
4770d64ceaSPaul Mackerras 
4870d64ceaSPaul Mackerras #if USES_PPC_SYS
4970d64ceaSPaul Mackerras #include <asm/ppc_sys.h>
5070d64ceaSPaul Mackerras #endif
5170d64ceaSPaul Mackerras 
5270d64ceaSPaul Mackerras #if defined CONFIG_KGDB
5370d64ceaSPaul Mackerras #include <asm/kgdb.h>
5470d64ceaSPaul Mackerras #endif
5570d64ceaSPaul Mackerras 
5670d64ceaSPaul Mackerras extern void platform_init(void);
5770d64ceaSPaul Mackerras extern void bootx_init(unsigned long r4, unsigned long phys);
5870d64ceaSPaul Mackerras 
5970d64ceaSPaul Mackerras extern void ppc6xx_idle(void);
6070d64ceaSPaul Mackerras extern void power4_idle(void);
6170d64ceaSPaul Mackerras 
6270d64ceaSPaul Mackerras boot_infos_t *boot_infos;
6370d64ceaSPaul Mackerras struct ide_machdep_calls ppc_ide_md;
6470d64ceaSPaul Mackerras 
6570d64ceaSPaul Mackerras /* Used with the BI_MEMSIZE bootinfo parameter to store the memory
6670d64ceaSPaul Mackerras    size value reported by the boot loader. */
6770d64ceaSPaul Mackerras unsigned long boot_mem_size;
6870d64ceaSPaul Mackerras 
6970d64ceaSPaul Mackerras unsigned long ISA_DMA_THRESHOLD;
7070d64ceaSPaul Mackerras unsigned int DMA_MODE_READ;
7170d64ceaSPaul Mackerras unsigned int DMA_MODE_WRITE;
7270d64ceaSPaul Mackerras 
73e574d238SPaul Mackerras int have_of = 1;
74e574d238SPaul Mackerras 
7570d64ceaSPaul Mackerras #ifdef CONFIG_PPC_MULTIPLATFORM
7670d64ceaSPaul Mackerras int _machine = 0;
7770d64ceaSPaul Mackerras 
7870d64ceaSPaul Mackerras extern void prep_init(void);
7970d64ceaSPaul Mackerras extern void pmac_init(void);
8070d64ceaSPaul Mackerras extern void chrp_init(void);
8170d64ceaSPaul Mackerras 
8270d64ceaSPaul Mackerras dev_t boot_dev;
8370d64ceaSPaul Mackerras #endif /* CONFIG_PPC_MULTIPLATFORM */
8470d64ceaSPaul Mackerras 
8570d64ceaSPaul Mackerras #ifdef CONFIG_MAGIC_SYSRQ
8670d64ceaSPaul Mackerras unsigned long SYSRQ_KEY = 0x54;
8770d64ceaSPaul Mackerras #endif /* CONFIG_MAGIC_SYSRQ */
8870d64ceaSPaul Mackerras 
8970d64ceaSPaul Mackerras #ifdef CONFIG_VGA_CONSOLE
9070d64ceaSPaul Mackerras unsigned long vgacon_remap_base;
9170d64ceaSPaul Mackerras #endif
9270d64ceaSPaul Mackerras 
9370d64ceaSPaul Mackerras struct machdep_calls ppc_md;
94e574d238SPaul Mackerras EXPORT_SYMBOL(ppc_md);
9570d64ceaSPaul Mackerras 
9670d64ceaSPaul Mackerras /*
9770d64ceaSPaul Mackerras  * These are used in binfmt_elf.c to put aux entries on the stack
9870d64ceaSPaul Mackerras  * for each elf executable being started.
9970d64ceaSPaul Mackerras  */
10070d64ceaSPaul Mackerras int dcache_bsize;
10170d64ceaSPaul Mackerras int icache_bsize;
10270d64ceaSPaul Mackerras int ucache_bsize;
10370d64ceaSPaul Mackerras 
10470d64ceaSPaul Mackerras #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_FB_VGA16) || \
10570d64ceaSPaul Mackerras     defined(CONFIG_FB_VGA16_MODULE) || defined(CONFIG_FB_VESA)
10670d64ceaSPaul Mackerras struct screen_info screen_info = {
10770d64ceaSPaul Mackerras 	0, 25,			/* orig-x, orig-y */
10870d64ceaSPaul Mackerras 	0,			/* unused */
10970d64ceaSPaul Mackerras 	0,			/* orig-video-page */
11070d64ceaSPaul Mackerras 	0,			/* orig-video-mode */
11170d64ceaSPaul Mackerras 	80,			/* orig-video-cols */
11270d64ceaSPaul Mackerras 	0,0,0,			/* ega_ax, ega_bx, ega_cx */
11370d64ceaSPaul Mackerras 	25,			/* orig-video-lines */
11470d64ceaSPaul Mackerras 	1,			/* orig-video-isVGA */
11570d64ceaSPaul Mackerras 	16			/* orig-video-points */
11670d64ceaSPaul Mackerras };
11770d64ceaSPaul Mackerras #endif /* CONFIG_VGA_CONSOLE || CONFIG_FB_VGA16 || CONFIG_FB_VESA */
11870d64ceaSPaul Mackerras 
11970d64ceaSPaul Mackerras void machine_restart(char *cmd)
12070d64ceaSPaul Mackerras {
12170d64ceaSPaul Mackerras #ifdef CONFIG_NVRAM
12270d64ceaSPaul Mackerras 	nvram_sync();
12370d64ceaSPaul Mackerras #endif
12470d64ceaSPaul Mackerras 	ppc_md.restart(cmd);
12570d64ceaSPaul Mackerras }
12670d64ceaSPaul Mackerras 
12770d64ceaSPaul Mackerras void machine_power_off(void)
12870d64ceaSPaul Mackerras {
12970d64ceaSPaul Mackerras #ifdef CONFIG_NVRAM
13070d64ceaSPaul Mackerras 	nvram_sync();
13170d64ceaSPaul Mackerras #endif
13270d64ceaSPaul Mackerras 	ppc_md.power_off();
13370d64ceaSPaul Mackerras }
13470d64ceaSPaul Mackerras 
13570d64ceaSPaul Mackerras void machine_halt(void)
13670d64ceaSPaul Mackerras {
13770d64ceaSPaul Mackerras #ifdef CONFIG_NVRAM
13870d64ceaSPaul Mackerras 	nvram_sync();
13970d64ceaSPaul Mackerras #endif
14070d64ceaSPaul Mackerras 	ppc_md.halt();
14170d64ceaSPaul Mackerras }
14270d64ceaSPaul Mackerras 
14370d64ceaSPaul Mackerras void (*pm_power_off)(void) = machine_power_off;
14470d64ceaSPaul Mackerras 
14570d64ceaSPaul Mackerras #ifdef CONFIG_TAU
14670d64ceaSPaul Mackerras extern u32 cpu_temp(unsigned long cpu);
14770d64ceaSPaul Mackerras extern u32 cpu_temp_both(unsigned long cpu);
14870d64ceaSPaul Mackerras #endif /* CONFIG_TAU */
14970d64ceaSPaul Mackerras 
15070d64ceaSPaul Mackerras int show_cpuinfo(struct seq_file *m, void *v)
15170d64ceaSPaul Mackerras {
15270d64ceaSPaul Mackerras 	int i = (int) v - 1;
15370d64ceaSPaul Mackerras 	int err = 0;
15470d64ceaSPaul Mackerras 	unsigned int pvr;
15570d64ceaSPaul Mackerras 	unsigned short maj, min;
15670d64ceaSPaul Mackerras 	unsigned long lpj;
15770d64ceaSPaul Mackerras 
15870d64ceaSPaul Mackerras 	if (i >= NR_CPUS) {
15970d64ceaSPaul Mackerras 		/* Show summary information */
16070d64ceaSPaul Mackerras #ifdef CONFIG_SMP
16170d64ceaSPaul Mackerras 		unsigned long bogosum = 0;
16270d64ceaSPaul Mackerras 		for (i = 0; i < NR_CPUS; ++i)
16370d64ceaSPaul Mackerras 			if (cpu_online(i))
16470d64ceaSPaul Mackerras 				bogosum += cpu_data[i].loops_per_jiffy;
16570d64ceaSPaul Mackerras 		seq_printf(m, "total bogomips\t: %lu.%02lu\n",
16670d64ceaSPaul Mackerras 			   bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
16770d64ceaSPaul Mackerras #endif /* CONFIG_SMP */
16870d64ceaSPaul Mackerras 
16970d64ceaSPaul Mackerras 		if (ppc_md.show_cpuinfo != NULL)
17070d64ceaSPaul Mackerras 			err = ppc_md.show_cpuinfo(m);
17170d64ceaSPaul Mackerras 		return err;
17270d64ceaSPaul Mackerras 	}
17370d64ceaSPaul Mackerras 
17470d64ceaSPaul Mackerras #ifdef CONFIG_SMP
17570d64ceaSPaul Mackerras 	if (!cpu_online(i))
17670d64ceaSPaul Mackerras 		return 0;
17770d64ceaSPaul Mackerras 	pvr = cpu_data[i].pvr;
17870d64ceaSPaul Mackerras 	lpj = cpu_data[i].loops_per_jiffy;
17970d64ceaSPaul Mackerras #else
18070d64ceaSPaul Mackerras 	pvr = mfspr(SPRN_PVR);
18170d64ceaSPaul Mackerras 	lpj = loops_per_jiffy;
18270d64ceaSPaul Mackerras #endif
18370d64ceaSPaul Mackerras 
18470d64ceaSPaul Mackerras 	seq_printf(m, "processor\t: %d\n", i);
18570d64ceaSPaul Mackerras 	seq_printf(m, "cpu\t\t: ");
18670d64ceaSPaul Mackerras 
18770d64ceaSPaul Mackerras 	if (cur_cpu_spec->pvr_mask)
18870d64ceaSPaul Mackerras 		seq_printf(m, "%s", cur_cpu_spec->cpu_name);
18970d64ceaSPaul Mackerras 	else
19070d64ceaSPaul Mackerras 		seq_printf(m, "unknown (%08x)", pvr);
19170d64ceaSPaul Mackerras #ifdef CONFIG_ALTIVEC
19270d64ceaSPaul Mackerras 	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
19370d64ceaSPaul Mackerras 		seq_printf(m, ", altivec supported");
19470d64ceaSPaul Mackerras #endif
19570d64ceaSPaul Mackerras 	seq_printf(m, "\n");
19670d64ceaSPaul Mackerras 
19770d64ceaSPaul Mackerras #ifdef CONFIG_TAU
19870d64ceaSPaul Mackerras 	if (cur_cpu_spec->cpu_features & CPU_FTR_TAU) {
19970d64ceaSPaul Mackerras #ifdef CONFIG_TAU_AVERAGE
20070d64ceaSPaul Mackerras 		/* more straightforward, but potentially misleading */
20170d64ceaSPaul Mackerras 		seq_printf(m,  "temperature \t: %u C (uncalibrated)\n",
20270d64ceaSPaul Mackerras 			   cpu_temp(i));
20370d64ceaSPaul Mackerras #else
20470d64ceaSPaul Mackerras 		/* show the actual temp sensor range */
20570d64ceaSPaul Mackerras 		u32 temp;
20670d64ceaSPaul Mackerras 		temp = cpu_temp_both(i);
20770d64ceaSPaul Mackerras 		seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
20870d64ceaSPaul Mackerras 			   temp & 0xff, temp >> 16);
20970d64ceaSPaul Mackerras #endif
21070d64ceaSPaul Mackerras 	}
21170d64ceaSPaul Mackerras #endif /* CONFIG_TAU */
21270d64ceaSPaul Mackerras 
21370d64ceaSPaul Mackerras 	if (ppc_md.show_percpuinfo != NULL) {
21470d64ceaSPaul Mackerras 		err = ppc_md.show_percpuinfo(m, i);
21570d64ceaSPaul Mackerras 		if (err)
21670d64ceaSPaul Mackerras 			return err;
21770d64ceaSPaul Mackerras 	}
21870d64ceaSPaul Mackerras 
21970d64ceaSPaul Mackerras 	/* If we are a Freescale core do a simple check so
22070d64ceaSPaul Mackerras 	 * we dont have to keep adding cases in the future */
22170d64ceaSPaul Mackerras 	if ((PVR_VER(pvr) & 0x8000) == 0x8000) {
22270d64ceaSPaul Mackerras 		maj = PVR_MAJ(pvr);
22370d64ceaSPaul Mackerras 		min = PVR_MIN(pvr);
22470d64ceaSPaul Mackerras 	} else {
22570d64ceaSPaul Mackerras 		switch (PVR_VER(pvr)) {
22670d64ceaSPaul Mackerras 			case 0x0020:	/* 403 family */
22770d64ceaSPaul Mackerras 				maj = PVR_MAJ(pvr) + 1;
22870d64ceaSPaul Mackerras 				min = PVR_MIN(pvr);
22970d64ceaSPaul Mackerras 				break;
23070d64ceaSPaul Mackerras 			case 0x1008:	/* 740P/750P ?? */
23170d64ceaSPaul Mackerras 				maj = ((pvr >> 8) & 0xFF) - 1;
23270d64ceaSPaul Mackerras 				min = pvr & 0xFF;
23370d64ceaSPaul Mackerras 				break;
23470d64ceaSPaul Mackerras 			default:
23570d64ceaSPaul Mackerras 				maj = (pvr >> 8) & 0xFF;
23670d64ceaSPaul Mackerras 				min = pvr & 0xFF;
23770d64ceaSPaul Mackerras 				break;
23870d64ceaSPaul Mackerras 		}
23970d64ceaSPaul Mackerras 	}
24070d64ceaSPaul Mackerras 
24170d64ceaSPaul Mackerras 	seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
24270d64ceaSPaul Mackerras 		   maj, min, PVR_VER(pvr), PVR_REV(pvr));
24370d64ceaSPaul Mackerras 
24470d64ceaSPaul Mackerras 	seq_printf(m, "bogomips\t: %lu.%02lu\n",
24570d64ceaSPaul Mackerras 		   lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
24670d64ceaSPaul Mackerras 
24770d64ceaSPaul Mackerras #if USES_PPC_SYS
24870d64ceaSPaul Mackerras 	if (cur_ppc_sys_spec->ppc_sys_name)
24970d64ceaSPaul Mackerras 		seq_printf(m, "chipset\t\t: %s\n",
25070d64ceaSPaul Mackerras 			cur_ppc_sys_spec->ppc_sys_name);
25170d64ceaSPaul Mackerras #endif
25270d64ceaSPaul Mackerras 
25370d64ceaSPaul Mackerras #ifdef CONFIG_SMP
25470d64ceaSPaul Mackerras 	seq_printf(m, "\n");
25570d64ceaSPaul Mackerras #endif
25670d64ceaSPaul Mackerras 
25770d64ceaSPaul Mackerras 	return 0;
25870d64ceaSPaul Mackerras }
25970d64ceaSPaul Mackerras 
26070d64ceaSPaul Mackerras static void *c_start(struct seq_file *m, loff_t *pos)
26170d64ceaSPaul Mackerras {
26270d64ceaSPaul Mackerras 	int i = *pos;
26370d64ceaSPaul Mackerras 
26470d64ceaSPaul Mackerras 	return i <= NR_CPUS? (void *) (i + 1): NULL;
26570d64ceaSPaul Mackerras }
26670d64ceaSPaul Mackerras 
26770d64ceaSPaul Mackerras static void *c_next(struct seq_file *m, void *v, loff_t *pos)
26870d64ceaSPaul Mackerras {
26970d64ceaSPaul Mackerras 	++*pos;
27070d64ceaSPaul Mackerras 	return c_start(m, pos);
27170d64ceaSPaul Mackerras }
27270d64ceaSPaul Mackerras 
27370d64ceaSPaul Mackerras static void c_stop(struct seq_file *m, void *v)
27470d64ceaSPaul Mackerras {
27570d64ceaSPaul Mackerras }
27670d64ceaSPaul Mackerras 
27770d64ceaSPaul Mackerras struct seq_operations cpuinfo_op = {
27870d64ceaSPaul Mackerras 	.start =c_start,
27970d64ceaSPaul Mackerras 	.next =	c_next,
28070d64ceaSPaul Mackerras 	.stop =	c_stop,
28170d64ceaSPaul Mackerras 	.show =	show_cpuinfo,
28270d64ceaSPaul Mackerras };
28370d64ceaSPaul Mackerras 
28470d64ceaSPaul Mackerras /*
28570d64ceaSPaul Mackerras  * We're called here very early in the boot.  We determine the machine
28670d64ceaSPaul Mackerras  * type and call the appropriate low-level setup functions.
28770d64ceaSPaul Mackerras  *  -- Cort <cort@fsmlabs.com>
28870d64ceaSPaul Mackerras  *
28970d64ceaSPaul Mackerras  * Note that the kernel may be running at an address which is different
29070d64ceaSPaul Mackerras  * from the address that it was linked at, so we must use RELOC/PTRRELOC
29170d64ceaSPaul Mackerras  * to access static data (including strings).  -- paulus
29270d64ceaSPaul Mackerras  */
29370d64ceaSPaul Mackerras unsigned long __init early_init(unsigned long dt_ptr)
29470d64ceaSPaul Mackerras {
29570d64ceaSPaul Mackerras 	unsigned long offset = reloc_offset();
29670d64ceaSPaul Mackerras 
297*dd184343SPaul Mackerras 	/* First zero the BSS -- use memset_io, some platforms don't have
298*dd184343SPaul Mackerras 	 * caches on yet */
299*dd184343SPaul Mackerras 	memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
300*dd184343SPaul Mackerras 
30170d64ceaSPaul Mackerras 	/*
30270d64ceaSPaul Mackerras 	 * Identify the CPU type and fix up code sections
30370d64ceaSPaul Mackerras 	 * that depend on which cpu we have.
30470d64ceaSPaul Mackerras 	 */
30570d64ceaSPaul Mackerras 	identify_cpu(offset, 0);
30670d64ceaSPaul Mackerras 	do_cpu_ftr_fixups(offset);
30770d64ceaSPaul Mackerras 
30870d64ceaSPaul Mackerras 	return KERNELBASE + offset;
30970d64ceaSPaul Mackerras }
31070d64ceaSPaul Mackerras 
31170d64ceaSPaul Mackerras #ifdef CONFIG_PPC_OF
31270d64ceaSPaul Mackerras /*
31370d64ceaSPaul Mackerras  * Assume here that all clock rates are the same in a
31470d64ceaSPaul Mackerras  * smp system.  -- Cort
31570d64ceaSPaul Mackerras  */
31670d64ceaSPaul Mackerras int
31770d64ceaSPaul Mackerras of_show_percpuinfo(struct seq_file *m, int i)
31870d64ceaSPaul Mackerras {
31970d64ceaSPaul Mackerras 	struct device_node *cpu_node;
32070d64ceaSPaul Mackerras 	u32 *fp;
32170d64ceaSPaul Mackerras 	int s;
32270d64ceaSPaul Mackerras 
32370d64ceaSPaul Mackerras 	cpu_node = find_type_devices("cpu");
32470d64ceaSPaul Mackerras 	if (!cpu_node)
32570d64ceaSPaul Mackerras 		return 0;
32670d64ceaSPaul Mackerras 	for (s = 0; s < i && cpu_node->next; s++)
32770d64ceaSPaul Mackerras 		cpu_node = cpu_node->next;
32870d64ceaSPaul Mackerras 	fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
32970d64ceaSPaul Mackerras 	if (fp)
33070d64ceaSPaul Mackerras 		seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
33170d64ceaSPaul Mackerras 	return 0;
33270d64ceaSPaul Mackerras }
33370d64ceaSPaul Mackerras 
33470d64ceaSPaul Mackerras void __init
33570d64ceaSPaul Mackerras intuit_machine_type(void)
33670d64ceaSPaul Mackerras {
33770d64ceaSPaul Mackerras 	char *model;
33870d64ceaSPaul Mackerras 	struct device_node *root;
33970d64ceaSPaul Mackerras 
34070d64ceaSPaul Mackerras 	/* ask the OF info if we're a chrp or pmac */
34170d64ceaSPaul Mackerras 	root = find_path_device("/");
34270d64ceaSPaul Mackerras 	if (root != 0) {
34370d64ceaSPaul Mackerras 		/* assume pmac unless proven to be chrp -- Cort */
34470d64ceaSPaul Mackerras 		_machine = _MACH_Pmac;
34570d64ceaSPaul Mackerras 		model = get_property(root, "device_type", NULL);
34670d64ceaSPaul Mackerras 		if (model && !strncmp("chrp", model, 4))
34770d64ceaSPaul Mackerras 			_machine = _MACH_chrp;
34870d64ceaSPaul Mackerras 		else {
34970d64ceaSPaul Mackerras 			model = get_property(root, "model", NULL);
35070d64ceaSPaul Mackerras 			if (model && !strncmp(model, "IBM", 3))
35170d64ceaSPaul Mackerras 				_machine = _MACH_chrp;
35270d64ceaSPaul Mackerras 		}
35370d64ceaSPaul Mackerras 	}
35470d64ceaSPaul Mackerras }
35570d64ceaSPaul Mackerras #endif
35670d64ceaSPaul Mackerras 
35770d64ceaSPaul Mackerras #ifdef CONFIG_PPC_MULTIPLATFORM
35870d64ceaSPaul Mackerras /*
35970d64ceaSPaul Mackerras  * The PPC_MULTIPLATFORM version of platform_init...
36070d64ceaSPaul Mackerras  */
36170d64ceaSPaul Mackerras void __init platform_init(void)
36270d64ceaSPaul Mackerras {
36370d64ceaSPaul Mackerras 	/* if we didn't get any bootinfo telling us what we are... */
36470d64ceaSPaul Mackerras 	if (_machine == 0) {
36570d64ceaSPaul Mackerras 		/* prep boot loader tells us if we're prep or not */
36670d64ceaSPaul Mackerras 		if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
36770d64ceaSPaul Mackerras 			_machine = _MACH_prep;
36870d64ceaSPaul Mackerras 	}
36970d64ceaSPaul Mackerras 
37070d64ceaSPaul Mackerras #ifdef CONFIG_PPC_PREP
37170d64ceaSPaul Mackerras 	/* not much more to do here, if prep */
37270d64ceaSPaul Mackerras 	if (_machine == _MACH_prep) {
37370d64ceaSPaul Mackerras 		prep_init();
37470d64ceaSPaul Mackerras 		return;
37570d64ceaSPaul Mackerras 	}
37670d64ceaSPaul Mackerras #endif
37770d64ceaSPaul Mackerras 
37870d64ceaSPaul Mackerras #ifdef CONFIG_ADB
37970d64ceaSPaul Mackerras 	if (strstr(cmd_line, "adb_sync")) {
38070d64ceaSPaul Mackerras 		extern int __adb_probe_sync;
38170d64ceaSPaul Mackerras 		__adb_probe_sync = 1;
38270d64ceaSPaul Mackerras 	}
38370d64ceaSPaul Mackerras #endif /* CONFIG_ADB */
38470d64ceaSPaul Mackerras 
38570d64ceaSPaul Mackerras 	switch (_machine) {
38670d64ceaSPaul Mackerras #ifdef CONFIG_PPC_PMAC
38770d64ceaSPaul Mackerras 	case _MACH_Pmac:
38870d64ceaSPaul Mackerras 		pmac_init();
38970d64ceaSPaul Mackerras 		break;
39070d64ceaSPaul Mackerras #endif
39170d64ceaSPaul Mackerras #ifdef CONFIG_PPC_CHRP
39270d64ceaSPaul Mackerras 	case _MACH_chrp:
39370d64ceaSPaul Mackerras 		chrp_init();
39470d64ceaSPaul Mackerras 		break;
39570d64ceaSPaul Mackerras #endif
39670d64ceaSPaul Mackerras 	}
39770d64ceaSPaul Mackerras }
39870d64ceaSPaul Mackerras 
39970d64ceaSPaul Mackerras #ifdef CONFIG_SERIAL_CORE_CONSOLE
40070d64ceaSPaul Mackerras extern char *of_stdout_device;
40170d64ceaSPaul Mackerras 
40270d64ceaSPaul Mackerras static int __init set_preferred_console(void)
40370d64ceaSPaul Mackerras {
40470d64ceaSPaul Mackerras 	struct device_node *prom_stdout;
40570d64ceaSPaul Mackerras 	char *name;
40670d64ceaSPaul Mackerras 	int offset = 0;
40770d64ceaSPaul Mackerras 
40870d64ceaSPaul Mackerras 	if (of_stdout_device == NULL)
40970d64ceaSPaul Mackerras 		return -ENODEV;
41070d64ceaSPaul Mackerras 
41170d64ceaSPaul Mackerras 	/* The user has requested a console so this is already set up. */
41270d64ceaSPaul Mackerras 	if (strstr(saved_command_line, "console="))
41370d64ceaSPaul Mackerras 		return -EBUSY;
41470d64ceaSPaul Mackerras 
41570d64ceaSPaul Mackerras 	prom_stdout = find_path_device(of_stdout_device);
41670d64ceaSPaul Mackerras 	if (!prom_stdout)
41770d64ceaSPaul Mackerras 		return -ENODEV;
41870d64ceaSPaul Mackerras 
41970d64ceaSPaul Mackerras 	name = (char *)get_property(prom_stdout, "name", NULL);
42070d64ceaSPaul Mackerras 	if (!name)
42170d64ceaSPaul Mackerras 		return -ENODEV;
42270d64ceaSPaul Mackerras 
42370d64ceaSPaul Mackerras 	if (strcmp(name, "serial") == 0) {
42470d64ceaSPaul Mackerras 		int i;
42570d64ceaSPaul Mackerras 		u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
42670d64ceaSPaul Mackerras 		if (i > 8) {
42770d64ceaSPaul Mackerras 			switch (reg[1]) {
42870d64ceaSPaul Mackerras 				case 0x3f8:
42970d64ceaSPaul Mackerras 					offset = 0;
43070d64ceaSPaul Mackerras 					break;
43170d64ceaSPaul Mackerras 				case 0x2f8:
43270d64ceaSPaul Mackerras 					offset = 1;
43370d64ceaSPaul Mackerras 					break;
43470d64ceaSPaul Mackerras 				case 0x898:
43570d64ceaSPaul Mackerras 					offset = 2;
43670d64ceaSPaul Mackerras 					break;
43770d64ceaSPaul Mackerras 				case 0x890:
43870d64ceaSPaul Mackerras 					offset = 3;
43970d64ceaSPaul Mackerras 					break;
44070d64ceaSPaul Mackerras 				default:
44170d64ceaSPaul Mackerras 					/* We dont recognise the serial port */
44270d64ceaSPaul Mackerras 					return -ENODEV;
44370d64ceaSPaul Mackerras 			}
44470d64ceaSPaul Mackerras 		}
44570d64ceaSPaul Mackerras 	} else if (strcmp(name, "ch-a") == 0)
44670d64ceaSPaul Mackerras 		offset = 0;
44770d64ceaSPaul Mackerras 	else if (strcmp(name, "ch-b") == 0)
44870d64ceaSPaul Mackerras 		offset = 1;
44970d64ceaSPaul Mackerras 	else
45070d64ceaSPaul Mackerras 		return -ENODEV;
45170d64ceaSPaul Mackerras 	return add_preferred_console("ttyS", offset, NULL);
45270d64ceaSPaul Mackerras }
45370d64ceaSPaul Mackerras console_initcall(set_preferred_console);
45470d64ceaSPaul Mackerras #endif /* CONFIG_SERIAL_CORE_CONSOLE */
45570d64ceaSPaul Mackerras #endif /* CONFIG_PPC_MULTIPLATFORM */
45670d64ceaSPaul Mackerras 
45770d64ceaSPaul Mackerras /*
45870d64ceaSPaul Mackerras  * Find out what kind of machine we're on and save any data we need
45970d64ceaSPaul Mackerras  * from the early boot process (devtree is copied on pmac by prom_init()).
46070d64ceaSPaul Mackerras  * This is called very early on the boot process, after a minimal
46170d64ceaSPaul Mackerras  * MMU environment has been set up but before MMU_init is called.
46270d64ceaSPaul Mackerras  */
46370d64ceaSPaul Mackerras void __init machine_init(unsigned long dt_ptr, unsigned long phys)
46470d64ceaSPaul Mackerras {
46570d64ceaSPaul Mackerras 	early_init_devtree(__va(dt_ptr));
46670d64ceaSPaul Mackerras 
46770d64ceaSPaul Mackerras #ifdef CONFIG_CMDLINE
46870d64ceaSPaul Mackerras 	strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
46970d64ceaSPaul Mackerras #endif /* CONFIG_CMDLINE */
47070d64ceaSPaul Mackerras 
47170d64ceaSPaul Mackerras #ifdef CONFIG_6xx
47270d64ceaSPaul Mackerras 	ppc_md.power_save = ppc6xx_idle;
47370d64ceaSPaul Mackerras #endif
47470d64ceaSPaul Mackerras #ifdef CONFIG_POWER4
47570d64ceaSPaul Mackerras 	ppc_md.power_save = power4_idle;
47670d64ceaSPaul Mackerras #endif
47770d64ceaSPaul Mackerras 
47870d64ceaSPaul Mackerras 	platform_init();
47970d64ceaSPaul Mackerras 
48070d64ceaSPaul Mackerras 	if (ppc_md.progress)
48170d64ceaSPaul Mackerras 		ppc_md.progress("id mach(): done", 0x200);
48270d64ceaSPaul Mackerras }
48370d64ceaSPaul Mackerras 
48470d64ceaSPaul Mackerras #ifdef CONFIG_BOOKE_WDT
48570d64ceaSPaul Mackerras /* Checks wdt=x and wdt_period=xx command-line option */
48670d64ceaSPaul Mackerras int __init early_parse_wdt(char *p)
48770d64ceaSPaul Mackerras {
48870d64ceaSPaul Mackerras 	if (p && strncmp(p, "0", 1) != 0)
48970d64ceaSPaul Mackerras 	       booke_wdt_enabled = 1;
49070d64ceaSPaul Mackerras 
49170d64ceaSPaul Mackerras 	return 0;
49270d64ceaSPaul Mackerras }
49370d64ceaSPaul Mackerras early_param("wdt", early_parse_wdt);
49470d64ceaSPaul Mackerras 
49570d64ceaSPaul Mackerras int __init early_parse_wdt_period (char *p)
49670d64ceaSPaul Mackerras {
49770d64ceaSPaul Mackerras 	if (p)
49870d64ceaSPaul Mackerras 		booke_wdt_period = simple_strtoul(p, NULL, 0);
49970d64ceaSPaul Mackerras 
50070d64ceaSPaul Mackerras 	return 0;
50170d64ceaSPaul Mackerras }
50270d64ceaSPaul Mackerras early_param("wdt_period", early_parse_wdt_period);
50370d64ceaSPaul Mackerras #endif	/* CONFIG_BOOKE_WDT */
50470d64ceaSPaul Mackerras 
50570d64ceaSPaul Mackerras /* Checks "l2cr=xxxx" command-line option */
50670d64ceaSPaul Mackerras int __init ppc_setup_l2cr(char *str)
50770d64ceaSPaul Mackerras {
50870d64ceaSPaul Mackerras 	if (cpu_has_feature(CPU_FTR_L2CR)) {
50970d64ceaSPaul Mackerras 		unsigned long val = simple_strtoul(str, NULL, 0);
51070d64ceaSPaul Mackerras 		printk(KERN_INFO "l2cr set to %lx\n", val);
51170d64ceaSPaul Mackerras 		_set_L2CR(0);		/* force invalidate by disable cache */
51270d64ceaSPaul Mackerras 		_set_L2CR(val);		/* and enable it */
51370d64ceaSPaul Mackerras 	}
51470d64ceaSPaul Mackerras 	return 1;
51570d64ceaSPaul Mackerras }
51670d64ceaSPaul Mackerras __setup("l2cr=", ppc_setup_l2cr);
51770d64ceaSPaul Mackerras 
51870d64ceaSPaul Mackerras #ifdef CONFIG_GENERIC_NVRAM
51970d64ceaSPaul Mackerras 
52070d64ceaSPaul Mackerras /* Generic nvram hooks used by drivers/char/gen_nvram.c */
52170d64ceaSPaul Mackerras unsigned char nvram_read_byte(int addr)
52270d64ceaSPaul Mackerras {
52370d64ceaSPaul Mackerras 	if (ppc_md.nvram_read_val)
52470d64ceaSPaul Mackerras 		return ppc_md.nvram_read_val(addr);
52570d64ceaSPaul Mackerras 	return 0xff;
52670d64ceaSPaul Mackerras }
52770d64ceaSPaul Mackerras EXPORT_SYMBOL(nvram_read_byte);
52870d64ceaSPaul Mackerras 
52970d64ceaSPaul Mackerras void nvram_write_byte(unsigned char val, int addr)
53070d64ceaSPaul Mackerras {
53170d64ceaSPaul Mackerras 	if (ppc_md.nvram_write_val)
53270d64ceaSPaul Mackerras 		ppc_md.nvram_write_val(addr, val);
53370d64ceaSPaul Mackerras }
53470d64ceaSPaul Mackerras EXPORT_SYMBOL(nvram_write_byte);
53570d64ceaSPaul Mackerras 
53670d64ceaSPaul Mackerras void nvram_sync(void)
53770d64ceaSPaul Mackerras {
53870d64ceaSPaul Mackerras 	if (ppc_md.nvram_sync)
53970d64ceaSPaul Mackerras 		ppc_md.nvram_sync();
54070d64ceaSPaul Mackerras }
54170d64ceaSPaul Mackerras EXPORT_SYMBOL(nvram_sync);
54270d64ceaSPaul Mackerras 
54370d64ceaSPaul Mackerras #endif /* CONFIG_NVRAM */
54470d64ceaSPaul Mackerras 
54570d64ceaSPaul Mackerras static struct cpu cpu_devices[NR_CPUS];
54670d64ceaSPaul Mackerras 
54770d64ceaSPaul Mackerras int __init ppc_init(void)
54870d64ceaSPaul Mackerras {
54970d64ceaSPaul Mackerras 	int i;
55070d64ceaSPaul Mackerras 
55170d64ceaSPaul Mackerras 	/* clear the progress line */
55270d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("             ", 0xffff);
55370d64ceaSPaul Mackerras 
55470d64ceaSPaul Mackerras 	/* register CPU devices */
55570d64ceaSPaul Mackerras 	for (i = 0; i < NR_CPUS; i++)
55670d64ceaSPaul Mackerras 		if (cpu_possible(i))
55770d64ceaSPaul Mackerras 			register_cpu(&cpu_devices[i], i, NULL);
55870d64ceaSPaul Mackerras 
55970d64ceaSPaul Mackerras 	/* call platform init */
56070d64ceaSPaul Mackerras 	if (ppc_md.init != NULL) {
56170d64ceaSPaul Mackerras 		ppc_md.init();
56270d64ceaSPaul Mackerras 	}
56370d64ceaSPaul Mackerras 	return 0;
56470d64ceaSPaul Mackerras }
56570d64ceaSPaul Mackerras 
56670d64ceaSPaul Mackerras arch_initcall(ppc_init);
56770d64ceaSPaul Mackerras 
56870d64ceaSPaul Mackerras /* Warning, IO base is not yet inited */
56970d64ceaSPaul Mackerras void __init setup_arch(char **cmdline_p)
57070d64ceaSPaul Mackerras {
57170d64ceaSPaul Mackerras 	extern char *klimit;
57270d64ceaSPaul Mackerras 	extern void do_init_bootmem(void);
57370d64ceaSPaul Mackerras 
57470d64ceaSPaul Mackerras 	/* so udelay does something sensible, assume <= 1000 bogomips */
57570d64ceaSPaul Mackerras 	loops_per_jiffy = 500000000 / HZ;
57670d64ceaSPaul Mackerras 
57770d64ceaSPaul Mackerras 	unflatten_device_tree();
57870d64ceaSPaul Mackerras 	finish_device_tree();
57970d64ceaSPaul Mackerras 
58030cd4a4eSPaul Mackerras #ifdef CONFIG_BOOTX_TEXT
58130cd4a4eSPaul Mackerras 	init_boot_display();
58230cd4a4eSPaul Mackerras #endif
58330cd4a4eSPaul Mackerras 
58470d64ceaSPaul Mackerras #ifdef CONFIG_PPC_MULTIPLATFORM
58570d64ceaSPaul Mackerras 	/* This could be called "early setup arch", it must be done
58670d64ceaSPaul Mackerras 	 * now because xmon need it
58770d64ceaSPaul Mackerras 	 */
58870d64ceaSPaul Mackerras 	if (_machine == _MACH_Pmac)
58970d64ceaSPaul Mackerras 		pmac_feature_init();	/* New cool way */
59070d64ceaSPaul Mackerras #endif
59170d64ceaSPaul Mackerras 
59270d64ceaSPaul Mackerras #ifdef CONFIG_XMON
59370d64ceaSPaul Mackerras 	xmon_map_scc();
59470d64ceaSPaul Mackerras 	if (strstr(cmd_line, "xmon"))
59570d64ceaSPaul Mackerras 		xmon(NULL);
59670d64ceaSPaul Mackerras #endif /* CONFIG_XMON */
59770d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
59870d64ceaSPaul Mackerras 
59970d64ceaSPaul Mackerras #if defined(CONFIG_KGDB)
60070d64ceaSPaul Mackerras 	if (ppc_md.kgdb_map_scc)
60170d64ceaSPaul Mackerras 		ppc_md.kgdb_map_scc();
60270d64ceaSPaul Mackerras 	set_debug_traps();
60370d64ceaSPaul Mackerras 	if (strstr(cmd_line, "gdb")) {
60470d64ceaSPaul Mackerras 		if (ppc_md.progress)
60570d64ceaSPaul Mackerras 			ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
60670d64ceaSPaul Mackerras 		printk("kgdb breakpoint activated\n");
60770d64ceaSPaul Mackerras 		breakpoint();
60870d64ceaSPaul Mackerras 	}
60970d64ceaSPaul Mackerras #endif
61070d64ceaSPaul Mackerras 
61170d64ceaSPaul Mackerras 	/*
61270d64ceaSPaul Mackerras 	 * Set cache line size based on type of cpu as a default.
61370d64ceaSPaul Mackerras 	 * Systems with OF can look in the properties on the cpu node(s)
61470d64ceaSPaul Mackerras 	 * for a possibly more accurate value.
61570d64ceaSPaul Mackerras 	 */
61670d64ceaSPaul Mackerras 	if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
61770d64ceaSPaul Mackerras 		dcache_bsize = cur_cpu_spec->dcache_bsize;
61870d64ceaSPaul Mackerras 		icache_bsize = cur_cpu_spec->icache_bsize;
61970d64ceaSPaul Mackerras 		ucache_bsize = 0;
62070d64ceaSPaul Mackerras 	} else
62170d64ceaSPaul Mackerras 		ucache_bsize = dcache_bsize = icache_bsize
62270d64ceaSPaul Mackerras 			= cur_cpu_spec->dcache_bsize;
62370d64ceaSPaul Mackerras 
62470d64ceaSPaul Mackerras 	/* reboot on panic */
62570d64ceaSPaul Mackerras 	panic_timeout = 180;
62670d64ceaSPaul Mackerras 
62770d64ceaSPaul Mackerras 	init_mm.start_code = PAGE_OFFSET;
62870d64ceaSPaul Mackerras 	init_mm.end_code = (unsigned long) _etext;
62970d64ceaSPaul Mackerras 	init_mm.end_data = (unsigned long) _edata;
63070d64ceaSPaul Mackerras 	init_mm.brk = (unsigned long) klimit;
63170d64ceaSPaul Mackerras 
63270d64ceaSPaul Mackerras 	/* Save unparsed command line copy for /proc/cmdline */
63370d64ceaSPaul Mackerras 	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
63470d64ceaSPaul Mackerras 	*cmdline_p = cmd_line;
63570d64ceaSPaul Mackerras 
63670d64ceaSPaul Mackerras 	parse_early_param();
63770d64ceaSPaul Mackerras 
63870d64ceaSPaul Mackerras 	/* set up the bootmem stuff with available memory */
63970d64ceaSPaul Mackerras 	do_init_bootmem();
64070d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
64170d64ceaSPaul Mackerras 
64270d64ceaSPaul Mackerras #ifdef CONFIG_PPC_OCP
64370d64ceaSPaul Mackerras 	/* Initialize OCP device list */
64470d64ceaSPaul Mackerras 	ocp_early_init();
64570d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
64670d64ceaSPaul Mackerras #endif
64770d64ceaSPaul Mackerras 
64870d64ceaSPaul Mackerras #ifdef CONFIG_DUMMY_CONSOLE
64970d64ceaSPaul Mackerras 	conswitchp = &dummy_con;
65070d64ceaSPaul Mackerras #endif
65170d64ceaSPaul Mackerras 
65270d64ceaSPaul Mackerras 	ppc_md.setup_arch();
65370d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
65470d64ceaSPaul Mackerras 
65570d64ceaSPaul Mackerras 	paging_init();
65670d64ceaSPaul Mackerras 
65770d64ceaSPaul Mackerras 	/* this is for modules since _machine can be a define -- Cort */
65870d64ceaSPaul Mackerras 	ppc_md.ppc_machine = _machine;
65970d64ceaSPaul Mackerras }
660