xref: /openbmc/linux/arch/arm/kernel/setup.c (revision 84f452b1)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/arch/arm/kernel/setup.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 1995-2001 Russell King
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
71da177e4SLinus Torvalds  * it under the terms of the GNU General Public License version 2 as
81da177e4SLinus Torvalds  * published by the Free Software Foundation.
91da177e4SLinus Torvalds  */
10ecea4ab6SPaul Gortmaker #include <linux/export.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/stddef.h>
131da177e4SLinus Torvalds #include <linux/ioport.h>
141da177e4SLinus Torvalds #include <linux/delay.h>
151da177e4SLinus Torvalds #include <linux/utsname.h>
161da177e4SLinus Torvalds #include <linux/initrd.h>
171da177e4SLinus Torvalds #include <linux/console.h>
181da177e4SLinus Torvalds #include <linux/bootmem.h>
191da177e4SLinus Torvalds #include <linux/seq_file.h>
20894673eeSJon Smirl #include <linux/screen_info.h>
21883a106bSArnd Bergmann #include <linux/of_platform.h>
221da177e4SLinus Torvalds #include <linux/init.h>
233c57fb43SMika Westerberg #include <linux/kexec.h>
2493c02ab4SGrant Likely #include <linux/of_fdt.h>
251da177e4SLinus Torvalds #include <linux/cpu.h>
261da177e4SLinus Torvalds #include <linux/interrupt.h>
277bbb7940SRussell King #include <linux/smp.h>
28e119bfffSRussell King #include <linux/proc_fs.h>
292778f620SRussell King #include <linux/memblock.h>
302ecccf90SDave Martin #include <linux/bug.h>
312ecccf90SDave Martin #include <linux/compiler.h>
3227a3f0e9SNicolas Pitre #include <linux/sort.h>
331da177e4SLinus Torvalds 
34b86040a5SCatalin Marinas #include <asm/unified.h>
3515d07dc9SRussell King #include <asm/cp15.h>
361da177e4SLinus Torvalds #include <asm/cpu.h>
370ba8b9b2SRussell King #include <asm/cputype.h>
381da177e4SLinus Torvalds #include <asm/elf.h>
391da177e4SLinus Torvalds #include <asm/procinfo.h>
4005774088SStefano Stabellini #include <asm/psci.h>
4137efe642SRussell King #include <asm/sections.h>
421da177e4SLinus Torvalds #include <asm/setup.h>
43f00ec48fSRussell King #include <asm/smp_plat.h>
441da177e4SLinus Torvalds #include <asm/mach-types.h>
451da177e4SLinus Torvalds #include <asm/cacheflush.h>
4646097c7dSRussell King #include <asm/cachetype.h>
471da177e4SLinus Torvalds #include <asm/tlbflush.h>
481da177e4SLinus Torvalds 
4993c02ab4SGrant Likely #include <asm/prom.h>
501da177e4SLinus Torvalds #include <asm/mach/arch.h>
511da177e4SLinus Torvalds #include <asm/mach/irq.h>
521da177e4SLinus Torvalds #include <asm/mach/time.h>
539f97da78SDavid Howells #include <asm/system_info.h>
549f97da78SDavid Howells #include <asm/system_misc.h>
555cbad0ebSJason Wessel #include <asm/traps.h>
56bff595c1SCatalin Marinas #include <asm/unwind.h>
571c16d242STejun Heo #include <asm/memblock.h>
584588c34dSDave Martin #include <asm/virt.h>
591da177e4SLinus Torvalds 
604cd9d6f7SRichard Purdie #include "atags.h"
610fc1c832SBen Dooks 
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
641da177e4SLinus Torvalds char fpe_type[8];
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds static int __init fpe_setup(char *line)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds 	memcpy(fpe_type, line, 8);
691da177e4SLinus Torvalds 	return 1;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds __setup("fpe=", fpe_setup);
731da177e4SLinus Torvalds #endif
741da177e4SLinus Torvalds 
75ff69a4c8SRussell King extern void paging_init(const struct machine_desc *desc);
76a77e0c7bSSantosh Shilimkar extern void early_paging_init(const struct machine_desc *,
77a77e0c7bSSantosh Shilimkar 			      struct proc_info_list *);
780371d3f7SRussell King extern void sanity_check_meminfo(void);
7916d6d5b0SRobin Holt extern enum reboot_mode reboot_mode;
80ff69a4c8SRussell King extern void setup_dma_zone(const struct machine_desc *desc);
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds unsigned int processor_id;
83c18f6581SKrzysztof Halasa EXPORT_SYMBOL(processor_id);
840385ebc0SRussell King unsigned int __machine_arch_type __read_mostly;
851da177e4SLinus Torvalds EXPORT_SYMBOL(__machine_arch_type);
860385ebc0SRussell King unsigned int cacheid __read_mostly;
87c0e95878SRussell King EXPORT_SYMBOL(cacheid);
881da177e4SLinus Torvalds 
899d20fdd5SBill Gatliff unsigned int __atags_pointer __initdata;
909d20fdd5SBill Gatliff 
911da177e4SLinus Torvalds unsigned int system_rev;
921da177e4SLinus Torvalds EXPORT_SYMBOL(system_rev);
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds unsigned int system_serial_low;
951da177e4SLinus Torvalds EXPORT_SYMBOL(system_serial_low);
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds unsigned int system_serial_high;
981da177e4SLinus Torvalds EXPORT_SYMBOL(system_serial_high);
991da177e4SLinus Torvalds 
1000385ebc0SRussell King unsigned int elf_hwcap __read_mostly;
1011da177e4SLinus Torvalds EXPORT_SYMBOL(elf_hwcap);
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds #ifdef MULTI_CPU
1050385ebc0SRussell King struct processor processor __read_mostly;
1061da177e4SLinus Torvalds #endif
1071da177e4SLinus Torvalds #ifdef MULTI_TLB
1080385ebc0SRussell King struct cpu_tlb_fns cpu_tlb __read_mostly;
1091da177e4SLinus Torvalds #endif
1101da177e4SLinus Torvalds #ifdef MULTI_USER
1110385ebc0SRussell King struct cpu_user_fns cpu_user __read_mostly;
1121da177e4SLinus Torvalds #endif
1131da177e4SLinus Torvalds #ifdef MULTI_CACHE
1140385ebc0SRussell King struct cpu_cache_fns cpu_cache __read_mostly;
1151da177e4SLinus Torvalds #endif
116953233dcSCatalin Marinas #ifdef CONFIG_OUTER_CACHE
1170385ebc0SRussell King struct outer_cache_fns outer_cache __read_mostly;
1186c09f09dSSantosh Shilimkar EXPORT_SYMBOL(outer_cache);
119953233dcSCatalin Marinas #endif
1201da177e4SLinus Torvalds 
1212ecccf90SDave Martin /*
1222ecccf90SDave Martin  * Cached cpu_architecture() result for use by assembler code.
1232ecccf90SDave Martin  * C code should use the cpu_architecture() function instead of accessing this
1242ecccf90SDave Martin  * variable directly.
1252ecccf90SDave Martin  */
1262ecccf90SDave Martin int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN;
1272ecccf90SDave Martin 
128ccea7a19SRussell King struct stack {
129ccea7a19SRussell King 	u32 irq[3];
130ccea7a19SRussell King 	u32 abt[3];
131ccea7a19SRussell King 	u32 und[3];
132ccea7a19SRussell King } ____cacheline_aligned;
133ccea7a19SRussell King 
13455bdd694SCatalin Marinas #ifndef CONFIG_CPU_V7M
135ccea7a19SRussell King static struct stack stacks[NR_CPUS];
13655bdd694SCatalin Marinas #endif
137ccea7a19SRussell King 
1381da177e4SLinus Torvalds char elf_platform[ELF_PLATFORM_SIZE];
1391da177e4SLinus Torvalds EXPORT_SYMBOL(elf_platform);
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds static const char *cpu_name;
1421da177e4SLinus Torvalds static const char *machine_name;
14348ab7e09SJeremy Kerr static char __initdata cmd_line[COMMAND_LINE_SIZE];
144ff69a4c8SRussell King const struct machine_desc *machine_desc __initdata;
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
1471da177e4SLinus Torvalds #define ENDIANNESS ((char)endian_test.l)
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds /*
1521da177e4SLinus Torvalds  * Standard memory resources
1531da177e4SLinus Torvalds  */
1541da177e4SLinus Torvalds static struct resource mem_res[] = {
155740e518eSGreg Kroah-Hartman 	{
156740e518eSGreg Kroah-Hartman 		.name = "Video RAM",
157740e518eSGreg Kroah-Hartman 		.start = 0,
158740e518eSGreg Kroah-Hartman 		.end = 0,
159740e518eSGreg Kroah-Hartman 		.flags = IORESOURCE_MEM
160740e518eSGreg Kroah-Hartman 	},
161740e518eSGreg Kroah-Hartman 	{
162a36d8e5bSKees Cook 		.name = "Kernel code",
163740e518eSGreg Kroah-Hartman 		.start = 0,
164740e518eSGreg Kroah-Hartman 		.end = 0,
165740e518eSGreg Kroah-Hartman 		.flags = IORESOURCE_MEM
166740e518eSGreg Kroah-Hartman 	},
167740e518eSGreg Kroah-Hartman 	{
168740e518eSGreg Kroah-Hartman 		.name = "Kernel data",
169740e518eSGreg Kroah-Hartman 		.start = 0,
170740e518eSGreg Kroah-Hartman 		.end = 0,
171740e518eSGreg Kroah-Hartman 		.flags = IORESOURCE_MEM
172740e518eSGreg Kroah-Hartman 	}
1731da177e4SLinus Torvalds };
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds #define video_ram   mem_res[0]
1761da177e4SLinus Torvalds #define kernel_code mem_res[1]
1771da177e4SLinus Torvalds #define kernel_data mem_res[2]
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds static struct resource io_res[] = {
180740e518eSGreg Kroah-Hartman 	{
181740e518eSGreg Kroah-Hartman 		.name = "reserved",
182740e518eSGreg Kroah-Hartman 		.start = 0x3bc,
183740e518eSGreg Kroah-Hartman 		.end = 0x3be,
184740e518eSGreg Kroah-Hartman 		.flags = IORESOURCE_IO | IORESOURCE_BUSY
185740e518eSGreg Kroah-Hartman 	},
186740e518eSGreg Kroah-Hartman 	{
187740e518eSGreg Kroah-Hartman 		.name = "reserved",
188740e518eSGreg Kroah-Hartman 		.start = 0x378,
189740e518eSGreg Kroah-Hartman 		.end = 0x37f,
190740e518eSGreg Kroah-Hartman 		.flags = IORESOURCE_IO | IORESOURCE_BUSY
191740e518eSGreg Kroah-Hartman 	},
192740e518eSGreg Kroah-Hartman 	{
193740e518eSGreg Kroah-Hartman 		.name = "reserved",
194740e518eSGreg Kroah-Hartman 		.start = 0x278,
195740e518eSGreg Kroah-Hartman 		.end = 0x27f,
196740e518eSGreg Kroah-Hartman 		.flags = IORESOURCE_IO | IORESOURCE_BUSY
197740e518eSGreg Kroah-Hartman 	}
1981da177e4SLinus Torvalds };
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds #define lp0 io_res[0]
2011da177e4SLinus Torvalds #define lp1 io_res[1]
2021da177e4SLinus Torvalds #define lp2 io_res[2]
2031da177e4SLinus Torvalds 
2041da177e4SLinus Torvalds static const char *proc_arch[] = {
2051da177e4SLinus Torvalds 	"undefined/unknown",
2061da177e4SLinus Torvalds 	"3",
2071da177e4SLinus Torvalds 	"4",
2081da177e4SLinus Torvalds 	"4T",
2091da177e4SLinus Torvalds 	"5",
2101da177e4SLinus Torvalds 	"5T",
2111da177e4SLinus Torvalds 	"5TE",
2121da177e4SLinus Torvalds 	"5TEJ",
2131da177e4SLinus Torvalds 	"6TEJ",
2146b090a25SCatalin Marinas 	"7",
21555bdd694SCatalin Marinas 	"7M",
2161da177e4SLinus Torvalds 	"?(12)",
2171da177e4SLinus Torvalds 	"?(13)",
2181da177e4SLinus Torvalds 	"?(14)",
2191da177e4SLinus Torvalds 	"?(15)",
2201da177e4SLinus Torvalds 	"?(16)",
2211da177e4SLinus Torvalds 	"?(17)",
2221da177e4SLinus Torvalds };
2231da177e4SLinus Torvalds 
22455bdd694SCatalin Marinas #ifdef CONFIG_CPU_V7M
22555bdd694SCatalin Marinas static int __get_cpu_architecture(void)
22655bdd694SCatalin Marinas {
22755bdd694SCatalin Marinas 	return CPU_ARCH_ARMv7M;
22855bdd694SCatalin Marinas }
22955bdd694SCatalin Marinas #else
2302ecccf90SDave Martin static int __get_cpu_architecture(void)
2311da177e4SLinus Torvalds {
2321da177e4SLinus Torvalds 	int cpu_arch;
2331da177e4SLinus Torvalds 
2340ba8b9b2SRussell King 	if ((read_cpuid_id() & 0x0008f000) == 0) {
2351da177e4SLinus Torvalds 		cpu_arch = CPU_ARCH_UNKNOWN;
2360ba8b9b2SRussell King 	} else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
2370ba8b9b2SRussell King 		cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
2380ba8b9b2SRussell King 	} else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
2390ba8b9b2SRussell King 		cpu_arch = (read_cpuid_id() >> 16) & 7;
2401da177e4SLinus Torvalds 		if (cpu_arch)
2411da177e4SLinus Torvalds 			cpu_arch += CPU_ARCH_ARMv3;
2420ba8b9b2SRussell King 	} else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
243180005c4SCatalin Marinas 		unsigned int mmfr0;
244180005c4SCatalin Marinas 
245180005c4SCatalin Marinas 		/* Revised CPUID format. Read the Memory Model Feature
246180005c4SCatalin Marinas 		 * Register 0 and check for VMSAv7 or PMSAv7 */
247180005c4SCatalin Marinas 		asm("mrc	p15, 0, %0, c0, c1, 4"
248180005c4SCatalin Marinas 		    : "=r" (mmfr0));
249315cfe78SCatalin Marinas 		if ((mmfr0 & 0x0000000f) >= 0x00000003 ||
250315cfe78SCatalin Marinas 		    (mmfr0 & 0x000000f0) >= 0x00000030)
251180005c4SCatalin Marinas 			cpu_arch = CPU_ARCH_ARMv7;
252180005c4SCatalin Marinas 		else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
253180005c4SCatalin Marinas 			 (mmfr0 & 0x000000f0) == 0x00000020)
254180005c4SCatalin Marinas 			cpu_arch = CPU_ARCH_ARMv6;
255180005c4SCatalin Marinas 		else
256180005c4SCatalin Marinas 			cpu_arch = CPU_ARCH_UNKNOWN;
257180005c4SCatalin Marinas 	} else
258180005c4SCatalin Marinas 		cpu_arch = CPU_ARCH_UNKNOWN;
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds 	return cpu_arch;
2611da177e4SLinus Torvalds }
26255bdd694SCatalin Marinas #endif
2631da177e4SLinus Torvalds 
2642ecccf90SDave Martin int __pure cpu_architecture(void)
2652ecccf90SDave Martin {
2662ecccf90SDave Martin 	BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN);
2672ecccf90SDave Martin 
2682ecccf90SDave Martin 	return __cpu_architecture;
2692ecccf90SDave Martin }
2702ecccf90SDave Martin 
2718925ec4cSWill Deacon static int cpu_has_aliasing_icache(unsigned int arch)
2728925ec4cSWill Deacon {
2738925ec4cSWill Deacon 	int aliasing_icache;
2748925ec4cSWill Deacon 	unsigned int id_reg, num_sets, line_size;
2758925ec4cSWill Deacon 
2767f94e9ccSWill Deacon 	/* PIPT caches never alias. */
2777f94e9ccSWill Deacon 	if (icache_is_pipt())
2787f94e9ccSWill Deacon 		return 0;
2797f94e9ccSWill Deacon 
2808925ec4cSWill Deacon 	/* arch specifies the register format */
2818925ec4cSWill Deacon 	switch (arch) {
2828925ec4cSWill Deacon 	case CPU_ARCH_ARMv7:
2835fb31a96SLinus Walleij 		asm("mcr	p15, 2, %0, c0, c0, 0 @ set CSSELR"
2845fb31a96SLinus Walleij 		    : /* No output operands */
2858925ec4cSWill Deacon 		    : "r" (1));
2865fb31a96SLinus Walleij 		isb();
2875fb31a96SLinus Walleij 		asm("mrc	p15, 1, %0, c0, c0, 0 @ read CCSIDR"
2885fb31a96SLinus Walleij 		    : "=r" (id_reg));
2898925ec4cSWill Deacon 		line_size = 4 << ((id_reg & 0x7) + 2);
2908925ec4cSWill Deacon 		num_sets = ((id_reg >> 13) & 0x7fff) + 1;
2918925ec4cSWill Deacon 		aliasing_icache = (line_size * num_sets) > PAGE_SIZE;
2928925ec4cSWill Deacon 		break;
2938925ec4cSWill Deacon 	case CPU_ARCH_ARMv6:
2948925ec4cSWill Deacon 		aliasing_icache = read_cpuid_cachetype() & (1 << 11);
2958925ec4cSWill Deacon 		break;
2968925ec4cSWill Deacon 	default:
2978925ec4cSWill Deacon 		/* I-cache aliases will be handled by D-cache aliasing code */
2988925ec4cSWill Deacon 		aliasing_icache = 0;
2998925ec4cSWill Deacon 	}
3008925ec4cSWill Deacon 
3018925ec4cSWill Deacon 	return aliasing_icache;
3028925ec4cSWill Deacon }
3038925ec4cSWill Deacon 
304c0e95878SRussell King static void __init cacheid_init(void)
305c0e95878SRussell King {
306c0e95878SRussell King 	unsigned int arch = cpu_architecture();
307c0e95878SRussell King 
30855bdd694SCatalin Marinas 	if (arch == CPU_ARCH_ARMv7M) {
30955bdd694SCatalin Marinas 		cacheid = 0;
31055bdd694SCatalin Marinas 	} else if (arch >= CPU_ARCH_ARMv6) {
311ac52e83fSUwe Kleine-König 		unsigned int cachetype = read_cpuid_cachetype();
312b57ee99fSCatalin Marinas 		if ((cachetype & (7 << 29)) == 4 << 29) {
313b57ee99fSCatalin Marinas 			/* ARMv7 register format */
31472dc53acSWill Deacon 			arch = CPU_ARCH_ARMv7;
315c0e95878SRussell King 			cacheid = CACHEID_VIPT_NONALIASING;
3167f94e9ccSWill Deacon 			switch (cachetype & (3 << 14)) {
3177f94e9ccSWill Deacon 			case (1 << 14):
318c0e95878SRussell King 				cacheid |= CACHEID_ASID_TAGGED;
3197f94e9ccSWill Deacon 				break;
3207f94e9ccSWill Deacon 			case (3 << 14):
3217f94e9ccSWill Deacon 				cacheid |= CACHEID_PIPT;
3227f94e9ccSWill Deacon 				break;
3237f94e9ccSWill Deacon 			}
3248925ec4cSWill Deacon 		} else {
32572dc53acSWill Deacon 			arch = CPU_ARCH_ARMv6;
32672dc53acSWill Deacon 			if (cachetype & (1 << 23))
32772dc53acSWill Deacon 				cacheid = CACHEID_VIPT_ALIASING;
32872dc53acSWill Deacon 			else
329c0e95878SRussell King 				cacheid = CACHEID_VIPT_NONALIASING;
3308925ec4cSWill Deacon 		}
33172dc53acSWill Deacon 		if (cpu_has_aliasing_icache(arch))
33272dc53acSWill Deacon 			cacheid |= CACHEID_VIPT_I_ALIASING;
333c0e95878SRussell King 	} else {
334c0e95878SRussell King 		cacheid = CACHEID_VIVT;
335c0e95878SRussell King 	}
3362b4ae1f1SRussell King 
3372b4ae1f1SRussell King 	printk("CPU: %s data cache, %s instruction cache\n",
3382b4ae1f1SRussell King 		cache_is_vivt() ? "VIVT" :
3392b4ae1f1SRussell King 		cache_is_vipt_aliasing() ? "VIPT aliasing" :
3407f94e9ccSWill Deacon 		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
3412b4ae1f1SRussell King 		cache_is_vivt() ? "VIVT" :
3422b4ae1f1SRussell King 		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
3438925ec4cSWill Deacon 		icache_is_vipt_aliasing() ? "VIPT aliasing" :
3447f94e9ccSWill Deacon 		icache_is_pipt() ? "PIPT" :
3452b4ae1f1SRussell King 		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
346c0e95878SRussell King }
347c0e95878SRussell King 
3481da177e4SLinus Torvalds /*
3491da177e4SLinus Torvalds  * These functions re-use the assembly code in head.S, which
3501da177e4SLinus Torvalds  * already provide the required functionality.
3511da177e4SLinus Torvalds  */
3520f44ba1dSRussell King extern struct proc_info_list *lookup_processor_type(unsigned int);
3536fc31d54SRussell King 
35493c02ab4SGrant Likely void __init early_print(const char *str, ...)
3556fc31d54SRussell King {
3566fc31d54SRussell King 	extern void printascii(const char *);
3576fc31d54SRussell King 	char buf[256];
3586fc31d54SRussell King 	va_list ap;
3596fc31d54SRussell King 
3606fc31d54SRussell King 	va_start(ap, str);
3616fc31d54SRussell King 	vsnprintf(buf, sizeof(buf), str, ap);
3626fc31d54SRussell King 	va_end(ap);
3636fc31d54SRussell King 
3646fc31d54SRussell King #ifdef CONFIG_DEBUG_LL
3656fc31d54SRussell King 	printascii(buf);
3666fc31d54SRussell King #endif
3676fc31d54SRussell King 	printk("%s", buf);
3686fc31d54SRussell King }
3696fc31d54SRussell King 
3708164f7afSStephen Boyd static void __init cpuid_init_hwcaps(void)
3718164f7afSStephen Boyd {
372a469abd0SWill Deacon 	unsigned int divide_instrs, vmsa;
3738164f7afSStephen Boyd 
3748164f7afSStephen Boyd 	if (cpu_architecture() < CPU_ARCH_ARMv7)
3758164f7afSStephen Boyd 		return;
3768164f7afSStephen Boyd 
3778164f7afSStephen Boyd 	divide_instrs = (read_cpuid_ext(CPUID_EXT_ISAR0) & 0x0f000000) >> 24;
3788164f7afSStephen Boyd 
3798164f7afSStephen Boyd 	switch (divide_instrs) {
3808164f7afSStephen Boyd 	case 2:
3818164f7afSStephen Boyd 		elf_hwcap |= HWCAP_IDIVA;
3828164f7afSStephen Boyd 	case 1:
3838164f7afSStephen Boyd 		elf_hwcap |= HWCAP_IDIVT;
3848164f7afSStephen Boyd 	}
385a469abd0SWill Deacon 
386a469abd0SWill Deacon 	/* LPAE implies atomic ldrd/strd instructions */
387a469abd0SWill Deacon 	vmsa = (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xf) >> 0;
388a469abd0SWill Deacon 	if (vmsa >= 5)
389a469abd0SWill Deacon 		elf_hwcap |= HWCAP_LPAE;
3908164f7afSStephen Boyd }
3918164f7afSStephen Boyd 
392f159f4edSTony Lindgren static void __init feat_v6_fixup(void)
393f159f4edSTony Lindgren {
394f159f4edSTony Lindgren 	int id = read_cpuid_id();
395f159f4edSTony Lindgren 
396f159f4edSTony Lindgren 	if ((id & 0xff0f0000) != 0x41070000)
397f159f4edSTony Lindgren 		return;
398f159f4edSTony Lindgren 
399f159f4edSTony Lindgren 	/*
400f159f4edSTony Lindgren 	 * HWCAP_TLS is available only on 1136 r1p0 and later,
401f159f4edSTony Lindgren 	 * see also kuser_get_tls_init.
402f159f4edSTony Lindgren 	 */
403f159f4edSTony Lindgren 	if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0))
404f159f4edSTony Lindgren 		elf_hwcap &= ~HWCAP_TLS;
405f159f4edSTony Lindgren }
406f159f4edSTony Lindgren 
407b69874e4SRussell King /*
408b69874e4SRussell King  * cpu_init - initialise one CPU.
409b69874e4SRussell King  *
410b69874e4SRussell King  * cpu_init sets up the per-CPU stacks.
411b69874e4SRussell King  */
4121783d457SJon Medhurst void notrace cpu_init(void)
413b69874e4SRussell King {
41455bdd694SCatalin Marinas #ifndef CONFIG_CPU_V7M
415b69874e4SRussell King 	unsigned int cpu = smp_processor_id();
416b69874e4SRussell King 	struct stack *stk = &stacks[cpu];
417b69874e4SRussell King 
418b69874e4SRussell King 	if (cpu >= NR_CPUS) {
419b69874e4SRussell King 		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
420b69874e4SRussell King 		BUG();
421b69874e4SRussell King 	}
422b69874e4SRussell King 
42314318efbSRob Herring 	/*
42414318efbSRob Herring 	 * This only works on resume and secondary cores. For booting on the
42514318efbSRob Herring 	 * boot cpu, smp_prepare_boot_cpu is called after percpu area setup.
42614318efbSRob Herring 	 */
42714318efbSRob Herring 	set_my_cpu_offset(per_cpu_offset(cpu));
42814318efbSRob Herring 
429b69874e4SRussell King 	cpu_proc_init();
430b69874e4SRussell King 
431b69874e4SRussell King 	/*
432b69874e4SRussell King 	 * Define the placement constraint for the inline asm directive below.
433b69874e4SRussell King 	 * In Thumb-2, msr with an immediate value is not allowed.
434b69874e4SRussell King 	 */
435b69874e4SRussell King #ifdef CONFIG_THUMB2_KERNEL
436b69874e4SRussell King #define PLC	"r"
437b69874e4SRussell King #else
438b69874e4SRussell King #define PLC	"I"
439b69874e4SRussell King #endif
440b69874e4SRussell King 
441b69874e4SRussell King 	/*
442b69874e4SRussell King 	 * setup stacks for re-entrant exception handlers
443b69874e4SRussell King 	 */
444b69874e4SRussell King 	__asm__ (
445b69874e4SRussell King 	"msr	cpsr_c, %1\n\t"
446b69874e4SRussell King 	"add	r14, %0, %2\n\t"
447b69874e4SRussell King 	"mov	sp, r14\n\t"
448b69874e4SRussell King 	"msr	cpsr_c, %3\n\t"
449b69874e4SRussell King 	"add	r14, %0, %4\n\t"
450b69874e4SRussell King 	"mov	sp, r14\n\t"
451b69874e4SRussell King 	"msr	cpsr_c, %5\n\t"
452b69874e4SRussell King 	"add	r14, %0, %6\n\t"
453b69874e4SRussell King 	"mov	sp, r14\n\t"
454b69874e4SRussell King 	"msr	cpsr_c, %7"
455b69874e4SRussell King 	    :
456b69874e4SRussell King 	    : "r" (stk),
457b69874e4SRussell King 	      PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
458b69874e4SRussell King 	      "I" (offsetof(struct stack, irq[0])),
459b69874e4SRussell King 	      PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
460b69874e4SRussell King 	      "I" (offsetof(struct stack, abt[0])),
461b69874e4SRussell King 	      PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
462b69874e4SRussell King 	      "I" (offsetof(struct stack, und[0])),
463b69874e4SRussell King 	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
464b69874e4SRussell King 	    : "r14");
46555bdd694SCatalin Marinas #endif
466b69874e4SRussell King }
467b69874e4SRussell King 
46818d7f152SLorenzo Pieralisi u32 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID };
469eb50439bSWill Deacon 
470eb50439bSWill Deacon void __init smp_setup_processor_id(void)
471eb50439bSWill Deacon {
472eb50439bSWill Deacon 	int i;
473cb8cf4f8SLorenzo Pieralisi 	u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
474cb8cf4f8SLorenzo Pieralisi 	u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
475eb50439bSWill Deacon 
476eb50439bSWill Deacon 	cpu_logical_map(0) = cpu;
477cb8cf4f8SLorenzo Pieralisi 	for (i = 1; i < nr_cpu_ids; ++i)
478eb50439bSWill Deacon 		cpu_logical_map(i) = i == cpu ? 0 : i;
479eb50439bSWill Deacon 
4809394c1c6SMing Lei 	/*
4819394c1c6SMing Lei 	 * clear __my_cpu_offset on boot CPU to avoid hang caused by
4829394c1c6SMing Lei 	 * using percpu variable early, for example, lockdep will
4839394c1c6SMing Lei 	 * access percpu variable inside lock_release
4849394c1c6SMing Lei 	 */
4859394c1c6SMing Lei 	set_my_cpu_offset(0);
4869394c1c6SMing Lei 
487cb8cf4f8SLorenzo Pieralisi 	printk(KERN_INFO "Booting Linux on physical CPU 0x%x\n", mpidr);
488eb50439bSWill Deacon }
489eb50439bSWill Deacon 
4908cf72172SLorenzo Pieralisi struct mpidr_hash mpidr_hash;
4918cf72172SLorenzo Pieralisi #ifdef CONFIG_SMP
4928cf72172SLorenzo Pieralisi /**
4938cf72172SLorenzo Pieralisi  * smp_build_mpidr_hash - Pre-compute shifts required at each affinity
4948cf72172SLorenzo Pieralisi  *			  level in order to build a linear index from an
4958cf72172SLorenzo Pieralisi  *			  MPIDR value. Resulting algorithm is a collision
4968cf72172SLorenzo Pieralisi  *			  free hash carried out through shifting and ORing
4978cf72172SLorenzo Pieralisi  */
4988cf72172SLorenzo Pieralisi static void __init smp_build_mpidr_hash(void)
4998cf72172SLorenzo Pieralisi {
5008cf72172SLorenzo Pieralisi 	u32 i, affinity;
5018cf72172SLorenzo Pieralisi 	u32 fs[3], bits[3], ls, mask = 0;
5028cf72172SLorenzo Pieralisi 	/*
5038cf72172SLorenzo Pieralisi 	 * Pre-scan the list of MPIDRS and filter out bits that do
5048cf72172SLorenzo Pieralisi 	 * not contribute to affinity levels, ie they never toggle.
5058cf72172SLorenzo Pieralisi 	 */
5068cf72172SLorenzo Pieralisi 	for_each_possible_cpu(i)
5078cf72172SLorenzo Pieralisi 		mask |= (cpu_logical_map(i) ^ cpu_logical_map(0));
5088cf72172SLorenzo Pieralisi 	pr_debug("mask of set bits 0x%x\n", mask);
5098cf72172SLorenzo Pieralisi 	/*
5108cf72172SLorenzo Pieralisi 	 * Find and stash the last and first bit set at all affinity levels to
5118cf72172SLorenzo Pieralisi 	 * check how many bits are required to represent them.
5128cf72172SLorenzo Pieralisi 	 */
5138cf72172SLorenzo Pieralisi 	for (i = 0; i < 3; i++) {
5148cf72172SLorenzo Pieralisi 		affinity = MPIDR_AFFINITY_LEVEL(mask, i);
5158cf72172SLorenzo Pieralisi 		/*
5168cf72172SLorenzo Pieralisi 		 * Find the MSB bit and LSB bits position
5178cf72172SLorenzo Pieralisi 		 * to determine how many bits are required
5188cf72172SLorenzo Pieralisi 		 * to express the affinity level.
5198cf72172SLorenzo Pieralisi 		 */
5208cf72172SLorenzo Pieralisi 		ls = fls(affinity);
5218cf72172SLorenzo Pieralisi 		fs[i] = affinity ? ffs(affinity) - 1 : 0;
5228cf72172SLorenzo Pieralisi 		bits[i] = ls - fs[i];
5238cf72172SLorenzo Pieralisi 	}
5248cf72172SLorenzo Pieralisi 	/*
5258cf72172SLorenzo Pieralisi 	 * An index can be created from the MPIDR by isolating the
5268cf72172SLorenzo Pieralisi 	 * significant bits at each affinity level and by shifting
5278cf72172SLorenzo Pieralisi 	 * them in order to compress the 24 bits values space to a
5288cf72172SLorenzo Pieralisi 	 * compressed set of values. This is equivalent to hashing
5298cf72172SLorenzo Pieralisi 	 * the MPIDR through shifting and ORing. It is a collision free
5308cf72172SLorenzo Pieralisi 	 * hash though not minimal since some levels might contain a number
5318cf72172SLorenzo Pieralisi 	 * of CPUs that is not an exact power of 2 and their bit
5328cf72172SLorenzo Pieralisi 	 * representation might contain holes, eg MPIDR[7:0] = {0x2, 0x80}.
5338cf72172SLorenzo Pieralisi 	 */
5348cf72172SLorenzo Pieralisi 	mpidr_hash.shift_aff[0] = fs[0];
5358cf72172SLorenzo Pieralisi 	mpidr_hash.shift_aff[1] = MPIDR_LEVEL_BITS + fs[1] - bits[0];
5368cf72172SLorenzo Pieralisi 	mpidr_hash.shift_aff[2] = 2*MPIDR_LEVEL_BITS + fs[2] -
5378cf72172SLorenzo Pieralisi 						(bits[1] + bits[0]);
5388cf72172SLorenzo Pieralisi 	mpidr_hash.mask = mask;
5398cf72172SLorenzo Pieralisi 	mpidr_hash.bits = bits[2] + bits[1] + bits[0];
5408cf72172SLorenzo Pieralisi 	pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] mask[0x%x] bits[%u]\n",
5418cf72172SLorenzo Pieralisi 				mpidr_hash.shift_aff[0],
5428cf72172SLorenzo Pieralisi 				mpidr_hash.shift_aff[1],
5438cf72172SLorenzo Pieralisi 				mpidr_hash.shift_aff[2],
5448cf72172SLorenzo Pieralisi 				mpidr_hash.mask,
5458cf72172SLorenzo Pieralisi 				mpidr_hash.bits);
5468cf72172SLorenzo Pieralisi 	/*
5478cf72172SLorenzo Pieralisi 	 * 4x is an arbitrary value used to warn on a hash table much bigger
5488cf72172SLorenzo Pieralisi 	 * than expected on most systems.
5498cf72172SLorenzo Pieralisi 	 */
5508cf72172SLorenzo Pieralisi 	if (mpidr_hash_size() > 4 * num_possible_cpus())
5518cf72172SLorenzo Pieralisi 		pr_warn("Large number of MPIDR hash buckets detected\n");
5528cf72172SLorenzo Pieralisi 	sync_cache_w(&mpidr_hash);
5538cf72172SLorenzo Pieralisi }
5548cf72172SLorenzo Pieralisi #endif
5558cf72172SLorenzo Pieralisi 
5561da177e4SLinus Torvalds static void __init setup_processor(void)
5571da177e4SLinus Torvalds {
5581da177e4SLinus Torvalds 	struct proc_info_list *list;
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds 	/*
5611da177e4SLinus Torvalds 	 * locate processor in the list of supported processor
5621da177e4SLinus Torvalds 	 * types.  The linker builds this table for us from the
5631da177e4SLinus Torvalds 	 * entries in arch/arm/mm/proc-*.S
5641da177e4SLinus Torvalds 	 */
5650ba8b9b2SRussell King 	list = lookup_processor_type(read_cpuid_id());
5661da177e4SLinus Torvalds 	if (!list) {
5671da177e4SLinus Torvalds 		printk("CPU configuration botched (ID %08x), unable "
5680ba8b9b2SRussell King 		       "to continue.\n", read_cpuid_id());
5691da177e4SLinus Torvalds 		while (1);
5701da177e4SLinus Torvalds 	}
5711da177e4SLinus Torvalds 
5721da177e4SLinus Torvalds 	cpu_name = list->cpu_name;
5732ecccf90SDave Martin 	__cpu_architecture = __get_cpu_architecture();
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds #ifdef MULTI_CPU
5761da177e4SLinus Torvalds 	processor = *list->proc;
5771da177e4SLinus Torvalds #endif
5781da177e4SLinus Torvalds #ifdef MULTI_TLB
5791da177e4SLinus Torvalds 	cpu_tlb = *list->tlb;
5801da177e4SLinus Torvalds #endif
5811da177e4SLinus Torvalds #ifdef MULTI_USER
5821da177e4SLinus Torvalds 	cpu_user = *list->user;
5831da177e4SLinus Torvalds #endif
5841da177e4SLinus Torvalds #ifdef MULTI_CACHE
5851da177e4SLinus Torvalds 	cpu_cache = *list->cache;
5861da177e4SLinus Torvalds #endif
5871da177e4SLinus Torvalds 
5884e19025bSRussell King 	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
5890ba8b9b2SRussell King 	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
590264edb35SRussell King 	       proc_arch[cpu_architecture()], cr_alignment);
5911da177e4SLinus Torvalds 
592a34dbfb0SWill Deacon 	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
593a34dbfb0SWill Deacon 		 list->arch_name, ENDIANNESS);
594a34dbfb0SWill Deacon 	snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
595a34dbfb0SWill Deacon 		 list->elf_name, ENDIANNESS);
5961da177e4SLinus Torvalds 	elf_hwcap = list->elf_hwcap;
5978164f7afSStephen Boyd 
5988164f7afSStephen Boyd 	cpuid_init_hwcaps();
5998164f7afSStephen Boyd 
600adeff422SCatalin Marinas #ifndef CONFIG_ARM_THUMB
601c40e3641SStephen Boyd 	elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
602adeff422SCatalin Marinas #endif
6031da177e4SLinus Torvalds 
60492871b94SRob Herring 	erratum_a15_798181_init();
60592871b94SRob Herring 
606f159f4edSTony Lindgren 	feat_v6_fixup();
607f159f4edSTony Lindgren 
608c0e95878SRussell King 	cacheid_init();
609b69874e4SRussell King 	cpu_init();
610ccea7a19SRussell King }
611ccea7a19SRussell King 
61293c02ab4SGrant Likely void __init dump_machine_table(void)
6131da177e4SLinus Torvalds {
614ff69a4c8SRussell King 	const struct machine_desc *p;
6151da177e4SLinus Torvalds 
6166291319dSGrant Likely 	early_print("Available machine support:\n\nID (hex)\tNAME\n");
6176291319dSGrant Likely 	for_each_machine_desc(p)
618dce72dd0SNicolas Pitre 		early_print("%08x\t%s\n", p->nr, p->name);
619dce72dd0SNicolas Pitre 
620dce72dd0SNicolas Pitre 	early_print("\nPlease check your kernel config and/or bootloader.\n");
621dce72dd0SNicolas Pitre 
622dce72dd0SNicolas Pitre 	while (true)
623dce72dd0SNicolas Pitre 		/* can't use cpu_relax() here as it may require MMU setup */;
6241da177e4SLinus Torvalds }
6251da177e4SLinus Torvalds 
6266a5014aaSMagnus Damm int __init arm_add_memory(u64 start, u64 size)
6273a669411SRussell King {
6284b5f32ceSNicolas Pitre 	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
6296d7d5da7SMagnus Damm 	u64 aligned_start;
6304b5f32ceSNicolas Pitre 
6314b5f32ceSNicolas Pitre 	if (meminfo.nr_banks >= NR_BANKS) {
6324b5f32ceSNicolas Pitre 		printk(KERN_CRIT "NR_BANKS too low, "
63329a38193SWill Deacon 			"ignoring memory at 0x%08llx\n", (long long)start);
6344b5f32ceSNicolas Pitre 		return -EINVAL;
6354b5f32ceSNicolas Pitre 	}
63605f96ef1SRussell King 
6373a669411SRussell King 	/*
6383a669411SRussell King 	 * Ensure that start/size are aligned to a page boundary.
6393a669411SRussell King 	 * Size is appropriately rounded down, start is rounded up.
6403a669411SRussell King 	 */
6413a669411SRussell King 	size -= start & ~PAGE_MASK;
6426d7d5da7SMagnus Damm 	aligned_start = PAGE_ALIGN(start);
643e5ab8580SWill Deacon 
6446d7d5da7SMagnus Damm #ifndef CONFIG_ARCH_PHYS_ADDR_T_64BIT
6456d7d5da7SMagnus Damm 	if (aligned_start > ULONG_MAX) {
6466d7d5da7SMagnus Damm 		printk(KERN_CRIT "Ignoring memory at 0x%08llx outside "
6476d7d5da7SMagnus Damm 		       "32-bit physical address space\n", (long long)start);
6486d7d5da7SMagnus Damm 		return -EINVAL;
6496d7d5da7SMagnus Damm 	}
6506d7d5da7SMagnus Damm 
6516d7d5da7SMagnus Damm 	if (aligned_start + size > ULONG_MAX) {
652e5ab8580SWill Deacon 		printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
653e5ab8580SWill Deacon 			"32-bit physical address space\n", (long long)start);
654e5ab8580SWill Deacon 		/*
655e5ab8580SWill Deacon 		 * To ensure bank->start + bank->size is representable in
656e5ab8580SWill Deacon 		 * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB.
657e5ab8580SWill Deacon 		 * This means we lose a page after masking.
658e5ab8580SWill Deacon 		 */
6596d7d5da7SMagnus Damm 		size = ULONG_MAX - aligned_start;
660e5ab8580SWill Deacon 	}
661e5ab8580SWill Deacon #endif
662e5ab8580SWill Deacon 
6636d7d5da7SMagnus Damm 	bank->start = aligned_start;
664a5d5f7daSPeter Maydell 	bank->size = size & ~(phys_addr_t)(PAGE_SIZE - 1);
6654b5f32ceSNicolas Pitre 
6664b5f32ceSNicolas Pitre 	/*
6674b5f32ceSNicolas Pitre 	 * Check whether this memory region has non-zero size or
6684b5f32ceSNicolas Pitre 	 * invalid node number.
6694b5f32ceSNicolas Pitre 	 */
670be370302SRussell King 	if (bank->size == 0)
6714b5f32ceSNicolas Pitre 		return -EINVAL;
6724b5f32ceSNicolas Pitre 
6734b5f32ceSNicolas Pitre 	meminfo.nr_banks++;
6744b5f32ceSNicolas Pitre 	return 0;
6753a669411SRussell King }
6763a669411SRussell King 
6771da177e4SLinus Torvalds /*
6781da177e4SLinus Torvalds  * Pick out the memory size.  We look for mem=size@start,
6791da177e4SLinus Torvalds  * where start and size are "size[KkMm]"
6801da177e4SLinus Torvalds  */
6812b0d8c25SJeremy Kerr static int __init early_mem(char *p)
6821da177e4SLinus Torvalds {
6831da177e4SLinus Torvalds 	static int usermem __initdata = 0;
6846a5014aaSMagnus Damm 	u64 size;
6856a5014aaSMagnus Damm 	u64 start;
6862b0d8c25SJeremy Kerr 	char *endp;
6871da177e4SLinus Torvalds 
6881da177e4SLinus Torvalds 	/*
6891da177e4SLinus Torvalds 	 * If the user specifies memory size, we
6901da177e4SLinus Torvalds 	 * blow away any automatically generated
6911da177e4SLinus Torvalds 	 * size.
6921da177e4SLinus Torvalds 	 */
6931da177e4SLinus Torvalds 	if (usermem == 0) {
6941da177e4SLinus Torvalds 		usermem = 1;
6951da177e4SLinus Torvalds 		meminfo.nr_banks = 0;
6961da177e4SLinus Torvalds 	}
6971da177e4SLinus Torvalds 
6981da177e4SLinus Torvalds 	start = PHYS_OFFSET;
6992b0d8c25SJeremy Kerr 	size  = memparse(p, &endp);
7002b0d8c25SJeremy Kerr 	if (*endp == '@')
7012b0d8c25SJeremy Kerr 		start = memparse(endp + 1, NULL);
7021da177e4SLinus Torvalds 
7031c97b73eSAndrew Morton 	arm_add_memory(start, size);
7041da177e4SLinus Torvalds 
7052b0d8c25SJeremy Kerr 	return 0;
7061da177e4SLinus Torvalds }
7072b0d8c25SJeremy Kerr early_param("mem", early_mem);
7081da177e4SLinus Torvalds 
709ff69a4c8SRussell King static void __init request_standard_resources(const struct machine_desc *mdesc)
7101da177e4SLinus Torvalds {
71111b9369cSDima Zavin 	struct memblock_region *region;
7121da177e4SLinus Torvalds 	struct resource *res;
7131da177e4SLinus Torvalds 
71437efe642SRussell King 	kernel_code.start   = virt_to_phys(_text);
71537efe642SRussell King 	kernel_code.end     = virt_to_phys(_etext - 1);
716842eab40SRussell King 	kernel_data.start   = virt_to_phys(_sdata);
71737efe642SRussell King 	kernel_data.end     = virt_to_phys(_end - 1);
7181da177e4SLinus Torvalds 
71911b9369cSDima Zavin 	for_each_memblock(memory, region) {
7201da177e4SLinus Torvalds 		res = alloc_bootmem_low(sizeof(*res));
7211da177e4SLinus Torvalds 		res->name  = "System RAM";
72211b9369cSDima Zavin 		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
72311b9369cSDima Zavin 		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
7241da177e4SLinus Torvalds 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds 		request_resource(&iomem_resource, res);
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds 		if (kernel_code.start >= res->start &&
7291da177e4SLinus Torvalds 		    kernel_code.end <= res->end)
7301da177e4SLinus Torvalds 			request_resource(res, &kernel_code);
7311da177e4SLinus Torvalds 		if (kernel_data.start >= res->start &&
7321da177e4SLinus Torvalds 		    kernel_data.end <= res->end)
7331da177e4SLinus Torvalds 			request_resource(res, &kernel_data);
7341da177e4SLinus Torvalds 	}
7351da177e4SLinus Torvalds 
7361da177e4SLinus Torvalds 	if (mdesc->video_start) {
7371da177e4SLinus Torvalds 		video_ram.start = mdesc->video_start;
7381da177e4SLinus Torvalds 		video_ram.end   = mdesc->video_end;
7391da177e4SLinus Torvalds 		request_resource(&iomem_resource, &video_ram);
7401da177e4SLinus Torvalds 	}
7411da177e4SLinus Torvalds 
7421da177e4SLinus Torvalds 	/*
7431da177e4SLinus Torvalds 	 * Some machines don't have the possibility of ever
7441da177e4SLinus Torvalds 	 * possessing lp0, lp1 or lp2
7451da177e4SLinus Torvalds 	 */
7461da177e4SLinus Torvalds 	if (mdesc->reserve_lp0)
7471da177e4SLinus Torvalds 		request_resource(&ioport_resource, &lp0);
7481da177e4SLinus Torvalds 	if (mdesc->reserve_lp1)
7491da177e4SLinus Torvalds 		request_resource(&ioport_resource, &lp1);
7501da177e4SLinus Torvalds 	if (mdesc->reserve_lp2)
7511da177e4SLinus Torvalds 		request_resource(&ioport_resource, &lp2);
7521da177e4SLinus Torvalds }
7531da177e4SLinus Torvalds 
7541da177e4SLinus Torvalds #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
7551da177e4SLinus Torvalds struct screen_info screen_info = {
7561da177e4SLinus Torvalds  .orig_video_lines	= 30,
7571da177e4SLinus Torvalds  .orig_video_cols	= 80,
7581da177e4SLinus Torvalds  .orig_video_mode	= 0,
7591da177e4SLinus Torvalds  .orig_video_ega_bx	= 0,
7601da177e4SLinus Torvalds  .orig_video_isVGA	= 1,
7611da177e4SLinus Torvalds  .orig_video_points	= 8
7621da177e4SLinus Torvalds };
7631da177e4SLinus Torvalds #endif
7641da177e4SLinus Torvalds 
7651da177e4SLinus Torvalds static int __init customize_machine(void)
7661da177e4SLinus Torvalds {
767883a106bSArnd Bergmann 	/*
768883a106bSArnd Bergmann 	 * customizes platform devices, or adds new ones
769883a106bSArnd Bergmann 	 * On DT based machines, we fall back to populating the
770883a106bSArnd Bergmann 	 * machine from the device tree, if no callback is provided,
771883a106bSArnd Bergmann 	 * otherwise we would always need an init_machine callback.
772883a106bSArnd Bergmann 	 */
7738ff1443cSRussell King 	if (machine_desc->init_machine)
7748ff1443cSRussell King 		machine_desc->init_machine();
775883a106bSArnd Bergmann #ifdef CONFIG_OF
776883a106bSArnd Bergmann 	else
777883a106bSArnd Bergmann 		of_platform_populate(NULL, of_default_bus_match_table,
778883a106bSArnd Bergmann 					NULL, NULL);
779883a106bSArnd Bergmann #endif
7801da177e4SLinus Torvalds 	return 0;
7811da177e4SLinus Torvalds }
7821da177e4SLinus Torvalds arch_initcall(customize_machine);
7831da177e4SLinus Torvalds 
78490de4137SShawn Guo static int __init init_machine_late(void)
78590de4137SShawn Guo {
78690de4137SShawn Guo 	if (machine_desc->init_late)
78790de4137SShawn Guo 		machine_desc->init_late();
78890de4137SShawn Guo 	return 0;
78990de4137SShawn Guo }
79090de4137SShawn Guo late_initcall(init_machine_late);
79190de4137SShawn Guo 
7923c57fb43SMika Westerberg #ifdef CONFIG_KEXEC
7933c57fb43SMika Westerberg static inline unsigned long long get_total_mem(void)
7943c57fb43SMika Westerberg {
7953c57fb43SMika Westerberg 	unsigned long total;
7963c57fb43SMika Westerberg 
7973c57fb43SMika Westerberg 	total = max_low_pfn - min_low_pfn;
7983c57fb43SMika Westerberg 	return total << PAGE_SHIFT;
7993c57fb43SMika Westerberg }
8003c57fb43SMika Westerberg 
8013c57fb43SMika Westerberg /**
8023c57fb43SMika Westerberg  * reserve_crashkernel() - reserves memory are for crash kernel
8033c57fb43SMika Westerberg  *
8043c57fb43SMika Westerberg  * This function reserves memory area given in "crashkernel=" kernel command
8053c57fb43SMika Westerberg  * line parameter. The memory reserved is used by a dump capture kernel when
8063c57fb43SMika Westerberg  * primary kernel is crashing.
8073c57fb43SMika Westerberg  */
8083c57fb43SMika Westerberg static void __init reserve_crashkernel(void)
8093c57fb43SMika Westerberg {
8103c57fb43SMika Westerberg 	unsigned long long crash_size, crash_base;
8113c57fb43SMika Westerberg 	unsigned long long total_mem;
8123c57fb43SMika Westerberg 	int ret;
8133c57fb43SMika Westerberg 
8143c57fb43SMika Westerberg 	total_mem = get_total_mem();
8153c57fb43SMika Westerberg 	ret = parse_crashkernel(boot_command_line, total_mem,
8163c57fb43SMika Westerberg 				&crash_size, &crash_base);
8173c57fb43SMika Westerberg 	if (ret)
8183c57fb43SMika Westerberg 		return;
8193c57fb43SMika Westerberg 
82084f452b1SSantosh Shilimkar 	ret = memblock_reserve(crash_base, crash_size);
8213c57fb43SMika Westerberg 	if (ret < 0) {
8223c57fb43SMika Westerberg 		printk(KERN_WARNING "crashkernel reservation failed - "
8233c57fb43SMika Westerberg 		       "memory is in use (0x%lx)\n", (unsigned long)crash_base);
8243c57fb43SMika Westerberg 		return;
8253c57fb43SMika Westerberg 	}
8263c57fb43SMika Westerberg 
8273c57fb43SMika Westerberg 	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
8283c57fb43SMika Westerberg 	       "for crashkernel (System RAM: %ldMB)\n",
8293c57fb43SMika Westerberg 	       (unsigned long)(crash_size >> 20),
8303c57fb43SMika Westerberg 	       (unsigned long)(crash_base >> 20),
8313c57fb43SMika Westerberg 	       (unsigned long)(total_mem >> 20));
8323c57fb43SMika Westerberg 
8333c57fb43SMika Westerberg 	crashk_res.start = crash_base;
8343c57fb43SMika Westerberg 	crashk_res.end = crash_base + crash_size - 1;
8353c57fb43SMika Westerberg 	insert_resource(&iomem_resource, &crashk_res);
8363c57fb43SMika Westerberg }
8373c57fb43SMika Westerberg #else
8383c57fb43SMika Westerberg static inline void reserve_crashkernel(void) {}
8393c57fb43SMika Westerberg #endif /* CONFIG_KEXEC */
8403c57fb43SMika Westerberg 
84127a3f0e9SNicolas Pitre static int __init meminfo_cmp(const void *_a, const void *_b)
84227a3f0e9SNicolas Pitre {
84327a3f0e9SNicolas Pitre 	const struct membank *a = _a, *b = _b;
84427a3f0e9SNicolas Pitre 	long cmp = bank_pfn_start(a) - bank_pfn_start(b);
84527a3f0e9SNicolas Pitre 	return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
84627a3f0e9SNicolas Pitre }
8476291319dSGrant Likely 
8484588c34dSDave Martin void __init hyp_mode_check(void)
8494588c34dSDave Martin {
8504588c34dSDave Martin #ifdef CONFIG_ARM_VIRT_EXT
8518fbac214SMark Rutland 	sync_boot_mode();
8528fbac214SMark Rutland 
8534588c34dSDave Martin 	if (is_hyp_mode_available()) {
8544588c34dSDave Martin 		pr_info("CPU: All CPU(s) started in HYP mode.\n");
8554588c34dSDave Martin 		pr_info("CPU: Virtualization extensions available.\n");
8564588c34dSDave Martin 	} else if (is_hyp_mode_mismatched()) {
8574588c34dSDave Martin 		pr_warn("CPU: WARNING: CPU(s) started in wrong/inconsistent modes (primary CPU mode 0x%x)\n",
8584588c34dSDave Martin 			__boot_cpu_mode & MODE_MASK);
8594588c34dSDave Martin 		pr_warn("CPU: This may indicate a broken bootloader or firmware.\n");
8604588c34dSDave Martin 	} else
8614588c34dSDave Martin 		pr_info("CPU: All CPU(s) started in SVC mode.\n");
8624588c34dSDave Martin #endif
8634588c34dSDave Martin }
8644588c34dSDave Martin 
8656291319dSGrant Likely void __init setup_arch(char **cmdline_p)
8666291319dSGrant Likely {
867ff69a4c8SRussell King 	const struct machine_desc *mdesc;
8686291319dSGrant Likely 
8696291319dSGrant Likely 	setup_processor();
87093c02ab4SGrant Likely 	mdesc = setup_machine_fdt(__atags_pointer);
87193c02ab4SGrant Likely 	if (!mdesc)
872b8b499c8SAlexander Shiyan 		mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
8736291319dSGrant Likely 	machine_desc = mdesc;
8746291319dSGrant Likely 	machine_name = mdesc->name;
8756291319dSGrant Likely 
876c7909509SMarek Szyprowski 	setup_dma_zone(mdesc);
877c7909509SMarek Szyprowski 
87816d6d5b0SRobin Holt 	if (mdesc->reboot_mode != REBOOT_HARD)
87916d6d5b0SRobin Holt 		reboot_mode = mdesc->reboot_mode;
8806291319dSGrant Likely 
88137efe642SRussell King 	init_mm.start_code = (unsigned long) _text;
88237efe642SRussell King 	init_mm.end_code   = (unsigned long) _etext;
88337efe642SRussell King 	init_mm.end_data   = (unsigned long) _edata;
88437efe642SRussell King 	init_mm.brk	   = (unsigned long) _end;
8851da177e4SLinus Torvalds 
88648ab7e09SJeremy Kerr 	/* populate cmd_line too for later use, preserving boot_command_line */
88748ab7e09SJeremy Kerr 	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
88848ab7e09SJeremy Kerr 	*cmdline_p = cmd_line;
8892b0d8c25SJeremy Kerr 
8902b0d8c25SJeremy Kerr 	parse_early_param();
8912b0d8c25SJeremy Kerr 
89227a3f0e9SNicolas Pitre 	sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
893a77e0c7bSSantosh Shilimkar 
894a77e0c7bSSantosh Shilimkar 	early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
8950371d3f7SRussell King 	sanity_check_meminfo();
8968d717a52SRussell King 	arm_memblock_init(&meminfo, mdesc);
8972778f620SRussell King 
8984b5f32ceSNicolas Pitre 	paging_init(mdesc);
89911b9369cSDima Zavin 	request_standard_resources(mdesc);
9001da177e4SLinus Torvalds 
901a528721dSRussell King 	if (mdesc->restart)
902a528721dSRussell King 		arm_pm_restart = mdesc->restart;
903a528721dSRussell King 
90493c02ab4SGrant Likely 	unflatten_device_tree();
90593c02ab4SGrant Likely 
9065587164eSLorenzo Pieralisi 	arm_dt_init_cpu_maps();
90705774088SStefano Stabellini 	psci_init();
9087bbb7940SRussell King #ifdef CONFIG_SMP
909abcee5fbSMarc Zyngier 	if (is_smp()) {
910b382b940SJon Medhurst 		if (!mdesc->smp_init || !mdesc->smp_init()) {
91105774088SStefano Stabellini 			if (psci_smp_available())
91205774088SStefano Stabellini 				smp_set_ops(&psci_smp_ops);
91305774088SStefano Stabellini 			else if (mdesc->smp)
914abcee5fbSMarc Zyngier 				smp_set_ops(mdesc->smp);
915b382b940SJon Medhurst 		}
9167bbb7940SRussell King 		smp_init_cpus();
9178cf72172SLorenzo Pieralisi 		smp_build_mpidr_hash();
918abcee5fbSMarc Zyngier 	}
9197bbb7940SRussell King #endif
9204588c34dSDave Martin 
9214588c34dSDave Martin 	if (!is_smp())
9224588c34dSDave Martin 		hyp_mode_check();
9234588c34dSDave Martin 
9243c57fb43SMika Westerberg 	reserve_crashkernel();
9257bbb7940SRussell King 
92652108641Seric miao #ifdef CONFIG_MULTI_IRQ_HANDLER
92752108641Seric miao 	handle_arch_irq = mdesc->handle_irq;
92852108641Seric miao #endif
9291da177e4SLinus Torvalds 
9301da177e4SLinus Torvalds #ifdef CONFIG_VT
9311da177e4SLinus Torvalds #if defined(CONFIG_VGA_CONSOLE)
9321da177e4SLinus Torvalds 	conswitchp = &vga_con;
9331da177e4SLinus Torvalds #elif defined(CONFIG_DUMMY_CONSOLE)
9341da177e4SLinus Torvalds 	conswitchp = &dummy_con;
9351da177e4SLinus Torvalds #endif
9361da177e4SLinus Torvalds #endif
937dec12e62SRussell King 
938dec12e62SRussell King 	if (mdesc->init_early)
939dec12e62SRussell King 		mdesc->init_early();
9401da177e4SLinus Torvalds }
9411da177e4SLinus Torvalds 
9421da177e4SLinus Torvalds 
9431da177e4SLinus Torvalds static int __init topology_init(void)
9441da177e4SLinus Torvalds {
9451da177e4SLinus Torvalds 	int cpu;
9461da177e4SLinus Torvalds 
94766fb8bd2SRussell King 	for_each_possible_cpu(cpu) {
94866fb8bd2SRussell King 		struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
94966fb8bd2SRussell King 		cpuinfo->cpu.hotpluggable = 1;
95066fb8bd2SRussell King 		register_cpu(&cpuinfo->cpu, cpu);
95166fb8bd2SRussell King 	}
9521da177e4SLinus Torvalds 
9531da177e4SLinus Torvalds 	return 0;
9541da177e4SLinus Torvalds }
9551da177e4SLinus Torvalds subsys_initcall(topology_init);
9561da177e4SLinus Torvalds 
957e119bfffSRussell King #ifdef CONFIG_HAVE_PROC_CPU
958e119bfffSRussell King static int __init proc_cpu_init(void)
959e119bfffSRussell King {
960e119bfffSRussell King 	struct proc_dir_entry *res;
961e119bfffSRussell King 
962e119bfffSRussell King 	res = proc_mkdir("cpu", NULL);
963e119bfffSRussell King 	if (!res)
964e119bfffSRussell King 		return -ENOMEM;
965e119bfffSRussell King 	return 0;
966e119bfffSRussell King }
967e119bfffSRussell King fs_initcall(proc_cpu_init);
968e119bfffSRussell King #endif
969e119bfffSRussell King 
9701da177e4SLinus Torvalds static const char *hwcap_str[] = {
9711da177e4SLinus Torvalds 	"swp",
9721da177e4SLinus Torvalds 	"half",
9731da177e4SLinus Torvalds 	"thumb",
9741da177e4SLinus Torvalds 	"26bit",
9751da177e4SLinus Torvalds 	"fastmult",
9761da177e4SLinus Torvalds 	"fpa",
9771da177e4SLinus Torvalds 	"vfp",
9781da177e4SLinus Torvalds 	"edsp",
9791da177e4SLinus Torvalds 	"java",
9808f7f9435SPaul Gortmaker 	"iwmmxt",
98199e4a6ddSLennert Buytenhek 	"crunch",
9824369ae16SCatalin Marinas 	"thumbee",
9832bedbdf4SCatalin Marinas 	"neon",
9847279dc3eSCatalin Marinas 	"vfpv3",
9857279dc3eSCatalin Marinas 	"vfpv3d16",
986254cdf8eSWill Deacon 	"tls",
987254cdf8eSWill Deacon 	"vfpv4",
988254cdf8eSWill Deacon 	"idiva",
989254cdf8eSWill Deacon 	"idivt",
990ab8d46c0STetsuyuki Kobayashi 	"vfpd32",
991a469abd0SWill Deacon 	"lpae",
992e9faebc6SSudeep KarkadaNagesha 	"evtstrm",
9931da177e4SLinus Torvalds 	NULL
9941da177e4SLinus Torvalds };
9951da177e4SLinus Torvalds 
9961da177e4SLinus Torvalds static int c_show(struct seq_file *m, void *v)
9971da177e4SLinus Torvalds {
998b4b8f770SLorenzo Pieralisi 	int i, j;
999b4b8f770SLorenzo Pieralisi 	u32 cpuid;
10001da177e4SLinus Torvalds 
10011da177e4SLinus Torvalds 	for_each_online_cpu(i) {
100215559722SRussell King 		/*
100315559722SRussell King 		 * glibc reads /proc/cpuinfo to determine the number of
100415559722SRussell King 		 * online processors, looking for lines beginning with
100515559722SRussell King 		 * "processor".  Give glibc what it expects.
100615559722SRussell King 		 */
100715559722SRussell King 		seq_printf(m, "processor\t: %d\n", i);
1008b4b8f770SLorenzo Pieralisi 		cpuid = is_smp() ? per_cpu(cpu_data, i).cpuid : read_cpuid_id();
1009b4b8f770SLorenzo Pieralisi 		seq_printf(m, "model name\t: %s rev %d (%s)\n",
1010b4b8f770SLorenzo Pieralisi 			   cpu_name, cpuid & 15, elf_platform);
1011b4b8f770SLorenzo Pieralisi 
10121da177e4SLinus Torvalds 		/* dump out the processor features */
10131da177e4SLinus Torvalds 		seq_puts(m, "Features\t: ");
10141da177e4SLinus Torvalds 
1015b4b8f770SLorenzo Pieralisi 		for (j = 0; hwcap_str[j]; j++)
1016b4b8f770SLorenzo Pieralisi 			if (elf_hwcap & (1 << j))
1017b4b8f770SLorenzo Pieralisi 				seq_printf(m, "%s ", hwcap_str[j]);
10181da177e4SLinus Torvalds 
1019b4b8f770SLorenzo Pieralisi 		seq_printf(m, "\nCPU implementer\t: 0x%02x\n", cpuid >> 24);
1020b4b8f770SLorenzo Pieralisi 		seq_printf(m, "CPU architecture: %s\n",
1021b4b8f770SLorenzo Pieralisi 			   proc_arch[cpu_architecture()]);
10221da177e4SLinus Torvalds 
1023b4b8f770SLorenzo Pieralisi 		if ((cpuid & 0x0008f000) == 0x00000000) {
10241da177e4SLinus Torvalds 			/* pre-ARM7 */
1025b4b8f770SLorenzo Pieralisi 			seq_printf(m, "CPU part\t: %07x\n", cpuid >> 4);
10261da177e4SLinus Torvalds 		} else {
1027b4b8f770SLorenzo Pieralisi 			if ((cpuid & 0x0008f000) == 0x00007000) {
10281da177e4SLinus Torvalds 				/* ARM7 */
10291da177e4SLinus Torvalds 				seq_printf(m, "CPU variant\t: 0x%02x\n",
1030b4b8f770SLorenzo Pieralisi 					   (cpuid >> 16) & 127);
10311da177e4SLinus Torvalds 			} else {
10321da177e4SLinus Torvalds 				/* post-ARM7 */
10331da177e4SLinus Torvalds 				seq_printf(m, "CPU variant\t: 0x%x\n",
1034b4b8f770SLorenzo Pieralisi 					   (cpuid >> 20) & 15);
10351da177e4SLinus Torvalds 			}
10361da177e4SLinus Torvalds 			seq_printf(m, "CPU part\t: 0x%03x\n",
1037b4b8f770SLorenzo Pieralisi 				   (cpuid >> 4) & 0xfff);
10381da177e4SLinus Torvalds 		}
1039b4b8f770SLorenzo Pieralisi 		seq_printf(m, "CPU revision\t: %d\n\n", cpuid & 15);
1040b4b8f770SLorenzo Pieralisi 	}
10411da177e4SLinus Torvalds 
10421da177e4SLinus Torvalds 	seq_printf(m, "Hardware\t: %s\n", machine_name);
10431da177e4SLinus Torvalds 	seq_printf(m, "Revision\t: %04x\n", system_rev);
10441da177e4SLinus Torvalds 	seq_printf(m, "Serial\t\t: %08x%08x\n",
10451da177e4SLinus Torvalds 		   system_serial_high, system_serial_low);
10461da177e4SLinus Torvalds 
10471da177e4SLinus Torvalds 	return 0;
10481da177e4SLinus Torvalds }
10491da177e4SLinus Torvalds 
10501da177e4SLinus Torvalds static void *c_start(struct seq_file *m, loff_t *pos)
10511da177e4SLinus Torvalds {
10521da177e4SLinus Torvalds 	return *pos < 1 ? (void *)1 : NULL;
10531da177e4SLinus Torvalds }
10541da177e4SLinus Torvalds 
10551da177e4SLinus Torvalds static void *c_next(struct seq_file *m, void *v, loff_t *pos)
10561da177e4SLinus Torvalds {
10571da177e4SLinus Torvalds 	++*pos;
10581da177e4SLinus Torvalds 	return NULL;
10591da177e4SLinus Torvalds }
10601da177e4SLinus Torvalds 
10611da177e4SLinus Torvalds static void c_stop(struct seq_file *m, void *v)
10621da177e4SLinus Torvalds {
10631da177e4SLinus Torvalds }
10641da177e4SLinus Torvalds 
10652ffd6e18SJan Engelhardt const struct seq_operations cpuinfo_op = {
10661da177e4SLinus Torvalds 	.start	= c_start,
10671da177e4SLinus Torvalds 	.next	= c_next,
10681da177e4SLinus Torvalds 	.stop	= c_stop,
10691da177e4SLinus Torvalds 	.show	= c_show
10701da177e4SLinus Torvalds };
1071