xref: /openbmc/linux/arch/powerpc/kernel/setup_32.c (revision 35499c0195e46f479cf6ac16ad8d3f394b5fcc10)
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 	unsigned int pvr;
15470d64ceaSPaul Mackerras 	unsigned short maj, min;
15570d64ceaSPaul Mackerras 	unsigned long lpj;
15670d64ceaSPaul Mackerras 
15770d64ceaSPaul Mackerras 	if (i >= NR_CPUS) {
15870d64ceaSPaul Mackerras 		/* Show summary information */
15970d64ceaSPaul Mackerras #ifdef CONFIG_SMP
16070d64ceaSPaul Mackerras 		unsigned long bogosum = 0;
16170d64ceaSPaul Mackerras 		for (i = 0; i < NR_CPUS; ++i)
16270d64ceaSPaul Mackerras 			if (cpu_online(i))
16370d64ceaSPaul Mackerras 				bogosum += cpu_data[i].loops_per_jiffy;
16470d64ceaSPaul Mackerras 		seq_printf(m, "total bogomips\t: %lu.%02lu\n",
16570d64ceaSPaul Mackerras 			   bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
16670d64ceaSPaul Mackerras #endif /* CONFIG_SMP */
16770d64ceaSPaul Mackerras 
16870d64ceaSPaul Mackerras 		if (ppc_md.show_cpuinfo != NULL)
1690dd194d0SPaul Mackerras 			ppc_md.show_cpuinfo(m);
1700dd194d0SPaul Mackerras 		return 0;
17170d64ceaSPaul Mackerras 	}
17270d64ceaSPaul Mackerras 
17370d64ceaSPaul Mackerras #ifdef CONFIG_SMP
17470d64ceaSPaul Mackerras 	if (!cpu_online(i))
17570d64ceaSPaul Mackerras 		return 0;
17670d64ceaSPaul Mackerras 	pvr = cpu_data[i].pvr;
17770d64ceaSPaul Mackerras 	lpj = cpu_data[i].loops_per_jiffy;
17870d64ceaSPaul Mackerras #else
17970d64ceaSPaul Mackerras 	pvr = mfspr(SPRN_PVR);
18070d64ceaSPaul Mackerras 	lpj = loops_per_jiffy;
18170d64ceaSPaul Mackerras #endif
18270d64ceaSPaul Mackerras 
18370d64ceaSPaul Mackerras 	seq_printf(m, "processor\t: %d\n", i);
18470d64ceaSPaul Mackerras 	seq_printf(m, "cpu\t\t: ");
18570d64ceaSPaul Mackerras 
18670d64ceaSPaul Mackerras 	if (cur_cpu_spec->pvr_mask)
18770d64ceaSPaul Mackerras 		seq_printf(m, "%s", cur_cpu_spec->cpu_name);
18870d64ceaSPaul Mackerras 	else
18970d64ceaSPaul Mackerras 		seq_printf(m, "unknown (%08x)", pvr);
19070d64ceaSPaul Mackerras #ifdef CONFIG_ALTIVEC
19170d64ceaSPaul Mackerras 	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
19270d64ceaSPaul Mackerras 		seq_printf(m, ", altivec supported");
19370d64ceaSPaul Mackerras #endif
19470d64ceaSPaul Mackerras 	seq_printf(m, "\n");
19570d64ceaSPaul Mackerras 
19670d64ceaSPaul Mackerras #ifdef CONFIG_TAU
19770d64ceaSPaul Mackerras 	if (cur_cpu_spec->cpu_features & CPU_FTR_TAU) {
19870d64ceaSPaul Mackerras #ifdef CONFIG_TAU_AVERAGE
19970d64ceaSPaul Mackerras 		/* more straightforward, but potentially misleading */
20070d64ceaSPaul Mackerras 		seq_printf(m,  "temperature \t: %u C (uncalibrated)\n",
20170d64ceaSPaul Mackerras 			   cpu_temp(i));
20270d64ceaSPaul Mackerras #else
20370d64ceaSPaul Mackerras 		/* show the actual temp sensor range */
20470d64ceaSPaul Mackerras 		u32 temp;
20570d64ceaSPaul Mackerras 		temp = cpu_temp_both(i);
20670d64ceaSPaul Mackerras 		seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
20770d64ceaSPaul Mackerras 			   temp & 0xff, temp >> 16);
20870d64ceaSPaul Mackerras #endif
20970d64ceaSPaul Mackerras 	}
21070d64ceaSPaul Mackerras #endif /* CONFIG_TAU */
21170d64ceaSPaul Mackerras 
2120dd194d0SPaul Mackerras 	if (ppc_md.show_percpuinfo != NULL)
2130dd194d0SPaul Mackerras 		ppc_md.show_percpuinfo(m, i);
21470d64ceaSPaul Mackerras 
21570d64ceaSPaul Mackerras 	/* If we are a Freescale core do a simple check so
21670d64ceaSPaul Mackerras 	 * we dont have to keep adding cases in the future */
2170dd194d0SPaul Mackerras 	if (PVR_VER(pvr) & 0x8000) {
21870d64ceaSPaul Mackerras 		maj = PVR_MAJ(pvr);
21970d64ceaSPaul Mackerras 		min = PVR_MIN(pvr);
22070d64ceaSPaul Mackerras 	} else {
22170d64ceaSPaul Mackerras 		switch (PVR_VER(pvr)) {
22270d64ceaSPaul Mackerras 			case 0x0020:	/* 403 family */
22370d64ceaSPaul Mackerras 				maj = PVR_MAJ(pvr) + 1;
22470d64ceaSPaul Mackerras 				min = PVR_MIN(pvr);
22570d64ceaSPaul Mackerras 				break;
22670d64ceaSPaul Mackerras 			case 0x1008:	/* 740P/750P ?? */
22770d64ceaSPaul Mackerras 				maj = ((pvr >> 8) & 0xFF) - 1;
22870d64ceaSPaul Mackerras 				min = pvr & 0xFF;
22970d64ceaSPaul Mackerras 				break;
23070d64ceaSPaul Mackerras 			default:
23170d64ceaSPaul Mackerras 				maj = (pvr >> 8) & 0xFF;
23270d64ceaSPaul Mackerras 				min = pvr & 0xFF;
23370d64ceaSPaul Mackerras 				break;
23470d64ceaSPaul Mackerras 		}
23570d64ceaSPaul Mackerras 	}
23670d64ceaSPaul Mackerras 
23770d64ceaSPaul Mackerras 	seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
23870d64ceaSPaul Mackerras 		   maj, min, PVR_VER(pvr), PVR_REV(pvr));
23970d64ceaSPaul Mackerras 
24070d64ceaSPaul Mackerras 	seq_printf(m, "bogomips\t: %lu.%02lu\n",
24170d64ceaSPaul Mackerras 		   lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
24270d64ceaSPaul Mackerras 
24370d64ceaSPaul Mackerras #if USES_PPC_SYS
24470d64ceaSPaul Mackerras 	if (cur_ppc_sys_spec->ppc_sys_name)
24570d64ceaSPaul Mackerras 		seq_printf(m, "chipset\t\t: %s\n",
24670d64ceaSPaul Mackerras 			cur_ppc_sys_spec->ppc_sys_name);
24770d64ceaSPaul Mackerras #endif
24870d64ceaSPaul Mackerras 
24970d64ceaSPaul Mackerras #ifdef CONFIG_SMP
25070d64ceaSPaul Mackerras 	seq_printf(m, "\n");
25170d64ceaSPaul Mackerras #endif
25270d64ceaSPaul Mackerras 
25370d64ceaSPaul Mackerras 	return 0;
25470d64ceaSPaul Mackerras }
25570d64ceaSPaul Mackerras 
25670d64ceaSPaul Mackerras static void *c_start(struct seq_file *m, loff_t *pos)
25770d64ceaSPaul Mackerras {
25870d64ceaSPaul Mackerras 	int i = *pos;
25970d64ceaSPaul Mackerras 
26070d64ceaSPaul Mackerras 	return i <= NR_CPUS? (void *) (i + 1): NULL;
26170d64ceaSPaul Mackerras }
26270d64ceaSPaul Mackerras 
26370d64ceaSPaul Mackerras static void *c_next(struct seq_file *m, void *v, loff_t *pos)
26470d64ceaSPaul Mackerras {
26570d64ceaSPaul Mackerras 	++*pos;
26670d64ceaSPaul Mackerras 	return c_start(m, pos);
26770d64ceaSPaul Mackerras }
26870d64ceaSPaul Mackerras 
26970d64ceaSPaul Mackerras static void c_stop(struct seq_file *m, void *v)
27070d64ceaSPaul Mackerras {
27170d64ceaSPaul Mackerras }
27270d64ceaSPaul Mackerras 
27370d64ceaSPaul Mackerras struct seq_operations cpuinfo_op = {
27470d64ceaSPaul Mackerras 	.start =c_start,
27570d64ceaSPaul Mackerras 	.next =	c_next,
27670d64ceaSPaul Mackerras 	.stop =	c_stop,
27770d64ceaSPaul Mackerras 	.show =	show_cpuinfo,
27870d64ceaSPaul Mackerras };
27970d64ceaSPaul Mackerras 
28070d64ceaSPaul Mackerras /*
28170d64ceaSPaul Mackerras  * We're called here very early in the boot.  We determine the machine
28270d64ceaSPaul Mackerras  * type and call the appropriate low-level setup functions.
28370d64ceaSPaul Mackerras  *  -- Cort <cort@fsmlabs.com>
28470d64ceaSPaul Mackerras  *
28570d64ceaSPaul Mackerras  * Note that the kernel may be running at an address which is different
28670d64ceaSPaul Mackerras  * from the address that it was linked at, so we must use RELOC/PTRRELOC
28770d64ceaSPaul Mackerras  * to access static data (including strings).  -- paulus
28870d64ceaSPaul Mackerras  */
28970d64ceaSPaul Mackerras unsigned long __init early_init(unsigned long dt_ptr)
29070d64ceaSPaul Mackerras {
29170d64ceaSPaul Mackerras 	unsigned long offset = reloc_offset();
29270d64ceaSPaul Mackerras 
293dd184343SPaul Mackerras 	/* First zero the BSS -- use memset_io, some platforms don't have
294dd184343SPaul Mackerras 	 * caches on yet */
295dd184343SPaul Mackerras 	memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
296dd184343SPaul Mackerras 
29770d64ceaSPaul Mackerras 	/*
29870d64ceaSPaul Mackerras 	 * Identify the CPU type and fix up code sections
29970d64ceaSPaul Mackerras 	 * that depend on which cpu we have.
30070d64ceaSPaul Mackerras 	 */
30170d64ceaSPaul Mackerras 	identify_cpu(offset, 0);
30270d64ceaSPaul Mackerras 	do_cpu_ftr_fixups(offset);
30370d64ceaSPaul Mackerras 
30470d64ceaSPaul Mackerras 	return KERNELBASE + offset;
30570d64ceaSPaul Mackerras }
30670d64ceaSPaul Mackerras 
30770d64ceaSPaul Mackerras #ifdef CONFIG_PPC_OF
30870d64ceaSPaul Mackerras /*
30970d64ceaSPaul Mackerras  * Assume here that all clock rates are the same in a
31070d64ceaSPaul Mackerras  * smp system.  -- Cort
31170d64ceaSPaul Mackerras  */
31270d64ceaSPaul Mackerras int
31370d64ceaSPaul Mackerras of_show_percpuinfo(struct seq_file *m, int i)
31470d64ceaSPaul Mackerras {
31570d64ceaSPaul Mackerras 	struct device_node *cpu_node;
31670d64ceaSPaul Mackerras 	u32 *fp;
31770d64ceaSPaul Mackerras 	int s;
31870d64ceaSPaul Mackerras 
31970d64ceaSPaul Mackerras 	cpu_node = find_type_devices("cpu");
32070d64ceaSPaul Mackerras 	if (!cpu_node)
32170d64ceaSPaul Mackerras 		return 0;
32270d64ceaSPaul Mackerras 	for (s = 0; s < i && cpu_node->next; s++)
32370d64ceaSPaul Mackerras 		cpu_node = cpu_node->next;
32470d64ceaSPaul Mackerras 	fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
32570d64ceaSPaul Mackerras 	if (fp)
32670d64ceaSPaul Mackerras 		seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
32770d64ceaSPaul Mackerras 	return 0;
32870d64ceaSPaul Mackerras }
32970d64ceaSPaul Mackerras 
33070d64ceaSPaul Mackerras void __init
33170d64ceaSPaul Mackerras intuit_machine_type(void)
33270d64ceaSPaul Mackerras {
33370d64ceaSPaul Mackerras 	char *model;
33470d64ceaSPaul Mackerras 	struct device_node *root;
33570d64ceaSPaul Mackerras 
33670d64ceaSPaul Mackerras 	/* ask the OF info if we're a chrp or pmac */
33770d64ceaSPaul Mackerras 	root = find_path_device("/");
33870d64ceaSPaul Mackerras 	if (root != 0) {
33970d64ceaSPaul Mackerras 		/* assume pmac unless proven to be chrp -- Cort */
34070d64ceaSPaul Mackerras 		_machine = _MACH_Pmac;
34170d64ceaSPaul Mackerras 		model = get_property(root, "device_type", NULL);
34270d64ceaSPaul Mackerras 		if (model && !strncmp("chrp", model, 4))
34370d64ceaSPaul Mackerras 			_machine = _MACH_chrp;
34470d64ceaSPaul Mackerras 		else {
34570d64ceaSPaul Mackerras 			model = get_property(root, "model", NULL);
34670d64ceaSPaul Mackerras 			if (model && !strncmp(model, "IBM", 3))
34770d64ceaSPaul Mackerras 				_machine = _MACH_chrp;
34870d64ceaSPaul Mackerras 		}
34970d64ceaSPaul Mackerras 	}
35070d64ceaSPaul Mackerras }
35170d64ceaSPaul Mackerras #endif
35270d64ceaSPaul Mackerras 
35370d64ceaSPaul Mackerras #ifdef CONFIG_PPC_MULTIPLATFORM
35470d64ceaSPaul Mackerras /*
35570d64ceaSPaul Mackerras  * The PPC_MULTIPLATFORM version of platform_init...
35670d64ceaSPaul Mackerras  */
35770d64ceaSPaul Mackerras void __init platform_init(void)
35870d64ceaSPaul Mackerras {
35970d64ceaSPaul Mackerras 	/* if we didn't get any bootinfo telling us what we are... */
36070d64ceaSPaul Mackerras 	if (_machine == 0) {
36170d64ceaSPaul Mackerras 		/* prep boot loader tells us if we're prep or not */
36270d64ceaSPaul Mackerras 		if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
36370d64ceaSPaul Mackerras 			_machine = _MACH_prep;
36470d64ceaSPaul Mackerras 	}
36570d64ceaSPaul Mackerras 
36670d64ceaSPaul Mackerras #ifdef CONFIG_PPC_PREP
36770d64ceaSPaul Mackerras 	/* not much more to do here, if prep */
36870d64ceaSPaul Mackerras 	if (_machine == _MACH_prep) {
36970d64ceaSPaul Mackerras 		prep_init();
37070d64ceaSPaul Mackerras 		return;
37170d64ceaSPaul Mackerras 	}
37270d64ceaSPaul Mackerras #endif
37370d64ceaSPaul Mackerras 
37470d64ceaSPaul Mackerras #ifdef CONFIG_ADB
37570d64ceaSPaul Mackerras 	if (strstr(cmd_line, "adb_sync")) {
37670d64ceaSPaul Mackerras 		extern int __adb_probe_sync;
37770d64ceaSPaul Mackerras 		__adb_probe_sync = 1;
37870d64ceaSPaul Mackerras 	}
37970d64ceaSPaul Mackerras #endif /* CONFIG_ADB */
38070d64ceaSPaul Mackerras 
38170d64ceaSPaul Mackerras 	switch (_machine) {
38270d64ceaSPaul Mackerras #ifdef CONFIG_PPC_PMAC
38370d64ceaSPaul Mackerras 	case _MACH_Pmac:
38470d64ceaSPaul Mackerras 		pmac_init();
38570d64ceaSPaul Mackerras 		break;
38670d64ceaSPaul Mackerras #endif
38770d64ceaSPaul Mackerras #ifdef CONFIG_PPC_CHRP
38870d64ceaSPaul Mackerras 	case _MACH_chrp:
38970d64ceaSPaul Mackerras 		chrp_init();
39070d64ceaSPaul Mackerras 		break;
39170d64ceaSPaul Mackerras #endif
39270d64ceaSPaul Mackerras 	}
39370d64ceaSPaul Mackerras }
39470d64ceaSPaul Mackerras 
39570d64ceaSPaul Mackerras #ifdef CONFIG_SERIAL_CORE_CONSOLE
39670d64ceaSPaul Mackerras extern char *of_stdout_device;
39770d64ceaSPaul Mackerras 
39870d64ceaSPaul Mackerras static int __init set_preferred_console(void)
39970d64ceaSPaul Mackerras {
40070d64ceaSPaul Mackerras 	struct device_node *prom_stdout;
40170d64ceaSPaul Mackerras 	char *name;
40270d64ceaSPaul Mackerras 	int offset = 0;
40370d64ceaSPaul Mackerras 
40470d64ceaSPaul Mackerras 	if (of_stdout_device == NULL)
40570d64ceaSPaul Mackerras 		return -ENODEV;
40670d64ceaSPaul Mackerras 
40770d64ceaSPaul Mackerras 	/* The user has requested a console so this is already set up. */
40870d64ceaSPaul Mackerras 	if (strstr(saved_command_line, "console="))
40970d64ceaSPaul Mackerras 		return -EBUSY;
41070d64ceaSPaul Mackerras 
41170d64ceaSPaul Mackerras 	prom_stdout = find_path_device(of_stdout_device);
41270d64ceaSPaul Mackerras 	if (!prom_stdout)
41370d64ceaSPaul Mackerras 		return -ENODEV;
41470d64ceaSPaul Mackerras 
41570d64ceaSPaul Mackerras 	name = (char *)get_property(prom_stdout, "name", NULL);
41670d64ceaSPaul Mackerras 	if (!name)
41770d64ceaSPaul Mackerras 		return -ENODEV;
41870d64ceaSPaul Mackerras 
41970d64ceaSPaul Mackerras 	if (strcmp(name, "serial") == 0) {
42070d64ceaSPaul Mackerras 		int i;
42170d64ceaSPaul Mackerras 		u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
42270d64ceaSPaul Mackerras 		if (i > 8) {
42370d64ceaSPaul Mackerras 			switch (reg[1]) {
42470d64ceaSPaul Mackerras 				case 0x3f8:
42570d64ceaSPaul Mackerras 					offset = 0;
42670d64ceaSPaul Mackerras 					break;
42770d64ceaSPaul Mackerras 				case 0x2f8:
42870d64ceaSPaul Mackerras 					offset = 1;
42970d64ceaSPaul Mackerras 					break;
43070d64ceaSPaul Mackerras 				case 0x898:
43170d64ceaSPaul Mackerras 					offset = 2;
43270d64ceaSPaul Mackerras 					break;
43370d64ceaSPaul Mackerras 				case 0x890:
43470d64ceaSPaul Mackerras 					offset = 3;
43570d64ceaSPaul Mackerras 					break;
43670d64ceaSPaul Mackerras 				default:
43770d64ceaSPaul Mackerras 					/* We dont recognise the serial port */
43870d64ceaSPaul Mackerras 					return -ENODEV;
43970d64ceaSPaul Mackerras 			}
44070d64ceaSPaul Mackerras 		}
44170d64ceaSPaul Mackerras 	} else if (strcmp(name, "ch-a") == 0)
44270d64ceaSPaul Mackerras 		offset = 0;
44370d64ceaSPaul Mackerras 	else if (strcmp(name, "ch-b") == 0)
44470d64ceaSPaul Mackerras 		offset = 1;
44570d64ceaSPaul Mackerras 	else
44670d64ceaSPaul Mackerras 		return -ENODEV;
44770d64ceaSPaul Mackerras 	return add_preferred_console("ttyS", offset, NULL);
44870d64ceaSPaul Mackerras }
44970d64ceaSPaul Mackerras console_initcall(set_preferred_console);
45070d64ceaSPaul Mackerras #endif /* CONFIG_SERIAL_CORE_CONSOLE */
45170d64ceaSPaul Mackerras #endif /* CONFIG_PPC_MULTIPLATFORM */
45270d64ceaSPaul Mackerras 
45370d64ceaSPaul Mackerras /*
45470d64ceaSPaul Mackerras  * Find out what kind of machine we're on and save any data we need
45570d64ceaSPaul Mackerras  * from the early boot process (devtree is copied on pmac by prom_init()).
45670d64ceaSPaul Mackerras  * This is called very early on the boot process, after a minimal
45770d64ceaSPaul Mackerras  * MMU environment has been set up but before MMU_init is called.
45870d64ceaSPaul Mackerras  */
45970d64ceaSPaul Mackerras void __init machine_init(unsigned long dt_ptr, unsigned long phys)
46070d64ceaSPaul Mackerras {
46170d64ceaSPaul Mackerras 	early_init_devtree(__va(dt_ptr));
46270d64ceaSPaul Mackerras 
46370d64ceaSPaul Mackerras #ifdef CONFIG_CMDLINE
46470d64ceaSPaul Mackerras 	strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
46570d64ceaSPaul Mackerras #endif /* CONFIG_CMDLINE */
46670d64ceaSPaul Mackerras 
467*35499c01SPaul Mackerras 	platform_init();
468*35499c01SPaul Mackerras 
46970d64ceaSPaul Mackerras #ifdef CONFIG_6xx
47070d64ceaSPaul Mackerras 	ppc_md.power_save = ppc6xx_idle;
47170d64ceaSPaul Mackerras #endif
47270d64ceaSPaul Mackerras 
47370d64ceaSPaul Mackerras 	if (ppc_md.progress)
47470d64ceaSPaul Mackerras 		ppc_md.progress("id mach(): done", 0x200);
47570d64ceaSPaul Mackerras }
47670d64ceaSPaul Mackerras 
47770d64ceaSPaul Mackerras #ifdef CONFIG_BOOKE_WDT
47870d64ceaSPaul Mackerras /* Checks wdt=x and wdt_period=xx command-line option */
47970d64ceaSPaul Mackerras int __init early_parse_wdt(char *p)
48070d64ceaSPaul Mackerras {
48170d64ceaSPaul Mackerras 	if (p && strncmp(p, "0", 1) != 0)
48270d64ceaSPaul Mackerras 	       booke_wdt_enabled = 1;
48370d64ceaSPaul Mackerras 
48470d64ceaSPaul Mackerras 	return 0;
48570d64ceaSPaul Mackerras }
48670d64ceaSPaul Mackerras early_param("wdt", early_parse_wdt);
48770d64ceaSPaul Mackerras 
48870d64ceaSPaul Mackerras int __init early_parse_wdt_period (char *p)
48970d64ceaSPaul Mackerras {
49070d64ceaSPaul Mackerras 	if (p)
49170d64ceaSPaul Mackerras 		booke_wdt_period = simple_strtoul(p, NULL, 0);
49270d64ceaSPaul Mackerras 
49370d64ceaSPaul Mackerras 	return 0;
49470d64ceaSPaul Mackerras }
49570d64ceaSPaul Mackerras early_param("wdt_period", early_parse_wdt_period);
49670d64ceaSPaul Mackerras #endif	/* CONFIG_BOOKE_WDT */
49770d64ceaSPaul Mackerras 
49870d64ceaSPaul Mackerras /* Checks "l2cr=xxxx" command-line option */
49970d64ceaSPaul Mackerras int __init ppc_setup_l2cr(char *str)
50070d64ceaSPaul Mackerras {
50170d64ceaSPaul Mackerras 	if (cpu_has_feature(CPU_FTR_L2CR)) {
50270d64ceaSPaul Mackerras 		unsigned long val = simple_strtoul(str, NULL, 0);
50370d64ceaSPaul Mackerras 		printk(KERN_INFO "l2cr set to %lx\n", val);
50470d64ceaSPaul Mackerras 		_set_L2CR(0);		/* force invalidate by disable cache */
50570d64ceaSPaul Mackerras 		_set_L2CR(val);		/* and enable it */
50670d64ceaSPaul Mackerras 	}
50770d64ceaSPaul Mackerras 	return 1;
50870d64ceaSPaul Mackerras }
50970d64ceaSPaul Mackerras __setup("l2cr=", ppc_setup_l2cr);
51070d64ceaSPaul Mackerras 
51170d64ceaSPaul Mackerras #ifdef CONFIG_GENERIC_NVRAM
51270d64ceaSPaul Mackerras 
51370d64ceaSPaul Mackerras /* Generic nvram hooks used by drivers/char/gen_nvram.c */
51470d64ceaSPaul Mackerras unsigned char nvram_read_byte(int addr)
51570d64ceaSPaul Mackerras {
51670d64ceaSPaul Mackerras 	if (ppc_md.nvram_read_val)
51770d64ceaSPaul Mackerras 		return ppc_md.nvram_read_val(addr);
51870d64ceaSPaul Mackerras 	return 0xff;
51970d64ceaSPaul Mackerras }
52070d64ceaSPaul Mackerras EXPORT_SYMBOL(nvram_read_byte);
52170d64ceaSPaul Mackerras 
52270d64ceaSPaul Mackerras void nvram_write_byte(unsigned char val, int addr)
52370d64ceaSPaul Mackerras {
52470d64ceaSPaul Mackerras 	if (ppc_md.nvram_write_val)
52570d64ceaSPaul Mackerras 		ppc_md.nvram_write_val(addr, val);
52670d64ceaSPaul Mackerras }
52770d64ceaSPaul Mackerras EXPORT_SYMBOL(nvram_write_byte);
52870d64ceaSPaul Mackerras 
52970d64ceaSPaul Mackerras void nvram_sync(void)
53070d64ceaSPaul Mackerras {
53170d64ceaSPaul Mackerras 	if (ppc_md.nvram_sync)
53270d64ceaSPaul Mackerras 		ppc_md.nvram_sync();
53370d64ceaSPaul Mackerras }
53470d64ceaSPaul Mackerras EXPORT_SYMBOL(nvram_sync);
53570d64ceaSPaul Mackerras 
53670d64ceaSPaul Mackerras #endif /* CONFIG_NVRAM */
53770d64ceaSPaul Mackerras 
53870d64ceaSPaul Mackerras static struct cpu cpu_devices[NR_CPUS];
53970d64ceaSPaul Mackerras 
54070d64ceaSPaul Mackerras int __init ppc_init(void)
54170d64ceaSPaul Mackerras {
54270d64ceaSPaul Mackerras 	int i;
54370d64ceaSPaul Mackerras 
54470d64ceaSPaul Mackerras 	/* clear the progress line */
54570d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("             ", 0xffff);
54670d64ceaSPaul Mackerras 
54770d64ceaSPaul Mackerras 	/* register CPU devices */
54870d64ceaSPaul Mackerras 	for (i = 0; i < NR_CPUS; i++)
54970d64ceaSPaul Mackerras 		if (cpu_possible(i))
55070d64ceaSPaul Mackerras 			register_cpu(&cpu_devices[i], i, NULL);
55170d64ceaSPaul Mackerras 
55270d64ceaSPaul Mackerras 	/* call platform init */
55370d64ceaSPaul Mackerras 	if (ppc_md.init != NULL) {
55470d64ceaSPaul Mackerras 		ppc_md.init();
55570d64ceaSPaul Mackerras 	}
55670d64ceaSPaul Mackerras 	return 0;
55770d64ceaSPaul Mackerras }
55870d64ceaSPaul Mackerras 
55970d64ceaSPaul Mackerras arch_initcall(ppc_init);
56070d64ceaSPaul Mackerras 
56170d64ceaSPaul Mackerras /* Warning, IO base is not yet inited */
56270d64ceaSPaul Mackerras void __init setup_arch(char **cmdline_p)
56370d64ceaSPaul Mackerras {
56470d64ceaSPaul Mackerras 	extern char *klimit;
56570d64ceaSPaul Mackerras 	extern void do_init_bootmem(void);
56670d64ceaSPaul Mackerras 
56770d64ceaSPaul Mackerras 	/* so udelay does something sensible, assume <= 1000 bogomips */
56870d64ceaSPaul Mackerras 	loops_per_jiffy = 500000000 / HZ;
56970d64ceaSPaul Mackerras 
57070d64ceaSPaul Mackerras 	unflatten_device_tree();
57170d64ceaSPaul Mackerras 	finish_device_tree();
57270d64ceaSPaul Mackerras 
57330cd4a4eSPaul Mackerras #ifdef CONFIG_BOOTX_TEXT
57430cd4a4eSPaul Mackerras 	init_boot_display();
57530cd4a4eSPaul Mackerras #endif
57630cd4a4eSPaul Mackerras 
57770d64ceaSPaul Mackerras #ifdef CONFIG_PPC_MULTIPLATFORM
57870d64ceaSPaul Mackerras 	/* This could be called "early setup arch", it must be done
57970d64ceaSPaul Mackerras 	 * now because xmon need it
58070d64ceaSPaul Mackerras 	 */
58170d64ceaSPaul Mackerras 	if (_machine == _MACH_Pmac)
58270d64ceaSPaul Mackerras 		pmac_feature_init();	/* New cool way */
58370d64ceaSPaul Mackerras #endif
58470d64ceaSPaul Mackerras 
58570d64ceaSPaul Mackerras #ifdef CONFIG_XMON
58670d64ceaSPaul Mackerras 	xmon_map_scc();
58770d64ceaSPaul Mackerras 	if (strstr(cmd_line, "xmon"))
58870d64ceaSPaul Mackerras 		xmon(NULL);
58970d64ceaSPaul Mackerras #endif /* CONFIG_XMON */
59070d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
59170d64ceaSPaul Mackerras 
59270d64ceaSPaul Mackerras #if defined(CONFIG_KGDB)
59370d64ceaSPaul Mackerras 	if (ppc_md.kgdb_map_scc)
59470d64ceaSPaul Mackerras 		ppc_md.kgdb_map_scc();
59570d64ceaSPaul Mackerras 	set_debug_traps();
59670d64ceaSPaul Mackerras 	if (strstr(cmd_line, "gdb")) {
59770d64ceaSPaul Mackerras 		if (ppc_md.progress)
59870d64ceaSPaul Mackerras 			ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
59970d64ceaSPaul Mackerras 		printk("kgdb breakpoint activated\n");
60070d64ceaSPaul Mackerras 		breakpoint();
60170d64ceaSPaul Mackerras 	}
60270d64ceaSPaul Mackerras #endif
60370d64ceaSPaul Mackerras 
60470d64ceaSPaul Mackerras 	/*
60570d64ceaSPaul Mackerras 	 * Set cache line size based on type of cpu as a default.
60670d64ceaSPaul Mackerras 	 * Systems with OF can look in the properties on the cpu node(s)
60770d64ceaSPaul Mackerras 	 * for a possibly more accurate value.
60870d64ceaSPaul Mackerras 	 */
60970d64ceaSPaul Mackerras 	if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
61070d64ceaSPaul Mackerras 		dcache_bsize = cur_cpu_spec->dcache_bsize;
61170d64ceaSPaul Mackerras 		icache_bsize = cur_cpu_spec->icache_bsize;
61270d64ceaSPaul Mackerras 		ucache_bsize = 0;
61370d64ceaSPaul Mackerras 	} else
61470d64ceaSPaul Mackerras 		ucache_bsize = dcache_bsize = icache_bsize
61570d64ceaSPaul Mackerras 			= cur_cpu_spec->dcache_bsize;
61670d64ceaSPaul Mackerras 
61770d64ceaSPaul Mackerras 	/* reboot on panic */
61870d64ceaSPaul Mackerras 	panic_timeout = 180;
61970d64ceaSPaul Mackerras 
62070d64ceaSPaul Mackerras 	init_mm.start_code = PAGE_OFFSET;
62170d64ceaSPaul Mackerras 	init_mm.end_code = (unsigned long) _etext;
62270d64ceaSPaul Mackerras 	init_mm.end_data = (unsigned long) _edata;
62370d64ceaSPaul Mackerras 	init_mm.brk = (unsigned long) klimit;
62470d64ceaSPaul Mackerras 
62570d64ceaSPaul Mackerras 	/* Save unparsed command line copy for /proc/cmdline */
62670d64ceaSPaul Mackerras 	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
62770d64ceaSPaul Mackerras 	*cmdline_p = cmd_line;
62870d64ceaSPaul Mackerras 
62970d64ceaSPaul Mackerras 	parse_early_param();
63070d64ceaSPaul Mackerras 
63170d64ceaSPaul Mackerras 	/* set up the bootmem stuff with available memory */
63270d64ceaSPaul Mackerras 	do_init_bootmem();
63370d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
63470d64ceaSPaul Mackerras 
63570d64ceaSPaul Mackerras #ifdef CONFIG_PPC_OCP
63670d64ceaSPaul Mackerras 	/* Initialize OCP device list */
63770d64ceaSPaul Mackerras 	ocp_early_init();
63870d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
63970d64ceaSPaul Mackerras #endif
64070d64ceaSPaul Mackerras 
64170d64ceaSPaul Mackerras #ifdef CONFIG_DUMMY_CONSOLE
64270d64ceaSPaul Mackerras 	conswitchp = &dummy_con;
64370d64ceaSPaul Mackerras #endif
64470d64ceaSPaul Mackerras 
64570d64ceaSPaul Mackerras 	ppc_md.setup_arch();
64670d64ceaSPaul Mackerras 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
64770d64ceaSPaul Mackerras 
64870d64ceaSPaul Mackerras 	paging_init();
64970d64ceaSPaul Mackerras 
65070d64ceaSPaul Mackerras 	/* this is for modules since _machine can be a define -- Cort */
65170d64ceaSPaul Mackerras 	ppc_md.ppc_machine = _machine;
65270d64ceaSPaul Mackerras }
653