19703d9d7SCatalin Marinas /* 29703d9d7SCatalin Marinas * Based on arch/arm/kernel/setup.c 39703d9d7SCatalin Marinas * 49703d9d7SCatalin Marinas * Copyright (C) 1995-2001 Russell King 59703d9d7SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 69703d9d7SCatalin Marinas * 79703d9d7SCatalin Marinas * This program is free software; you can redistribute it and/or modify 89703d9d7SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 99703d9d7SCatalin Marinas * published by the Free Software Foundation. 109703d9d7SCatalin Marinas * 119703d9d7SCatalin Marinas * This program is distributed in the hope that it will be useful, 129703d9d7SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 139703d9d7SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 149703d9d7SCatalin Marinas * GNU General Public License for more details. 159703d9d7SCatalin Marinas * 169703d9d7SCatalin Marinas * You should have received a copy of the GNU General Public License 179703d9d7SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 189703d9d7SCatalin Marinas */ 199703d9d7SCatalin Marinas 209703d9d7SCatalin Marinas #include <linux/export.h> 219703d9d7SCatalin Marinas #include <linux/kernel.h> 229703d9d7SCatalin Marinas #include <linux/stddef.h> 239703d9d7SCatalin Marinas #include <linux/ioport.h> 249703d9d7SCatalin Marinas #include <linux/delay.h> 259703d9d7SCatalin Marinas #include <linux/utsname.h> 269703d9d7SCatalin Marinas #include <linux/initrd.h> 279703d9d7SCatalin Marinas #include <linux/console.h> 28a41dc0e8SCatalin Marinas #include <linux/cache.h> 299703d9d7SCatalin Marinas #include <linux/bootmem.h> 309703d9d7SCatalin Marinas #include <linux/seq_file.h> 319703d9d7SCatalin Marinas #include <linux/screen_info.h> 329703d9d7SCatalin Marinas #include <linux/init.h> 339703d9d7SCatalin Marinas #include <linux/kexec.h> 349703d9d7SCatalin Marinas #include <linux/crash_dump.h> 359703d9d7SCatalin Marinas #include <linux/root_dev.h> 36de79a64dSCatalin Marinas #include <linux/clk-provider.h> 379703d9d7SCatalin Marinas #include <linux/cpu.h> 389703d9d7SCatalin Marinas #include <linux/interrupt.h> 399703d9d7SCatalin Marinas #include <linux/smp.h> 409703d9d7SCatalin Marinas #include <linux/fs.h> 419703d9d7SCatalin Marinas #include <linux/proc_fs.h> 429703d9d7SCatalin Marinas #include <linux/memblock.h> 439703d9d7SCatalin Marinas #include <linux/of_fdt.h> 44d6bafb9bSCatalin Marinas #include <linux/of_platform.h> 45f84d0275SMark Salter #include <linux/efi.h> 469703d9d7SCatalin Marinas 47bf4b558eSMark Salter #include <asm/fixmap.h> 48df857416SMark Rutland #include <asm/cpu.h> 499703d9d7SCatalin Marinas #include <asm/cputype.h> 509703d9d7SCatalin Marinas #include <asm/elf.h> 519703d9d7SCatalin Marinas #include <asm/cputable.h> 52e8765b26SMark Rutland #include <asm/cpu_ops.h> 539703d9d7SCatalin Marinas #include <asm/sections.h> 549703d9d7SCatalin Marinas #include <asm/setup.h> 554c7aa002SJavi Merino #include <asm/smp_plat.h> 569703d9d7SCatalin Marinas #include <asm/cacheflush.h> 579703d9d7SCatalin Marinas #include <asm/tlbflush.h> 589703d9d7SCatalin Marinas #include <asm/traps.h> 599703d9d7SCatalin Marinas #include <asm/memblock.h> 60e790f1deSWill Deacon #include <asm/psci.h> 61f84d0275SMark Salter #include <asm/efi.h> 629703d9d7SCatalin Marinas 639703d9d7SCatalin Marinas unsigned int processor_id; 649703d9d7SCatalin Marinas EXPORT_SYMBOL(processor_id); 659703d9d7SCatalin Marinas 6625804e6aSSteve Capper unsigned long elf_hwcap __read_mostly; 679703d9d7SCatalin Marinas EXPORT_SYMBOL_GPL(elf_hwcap); 689703d9d7SCatalin Marinas 6946efe547SSudeep KarkadaNagesha #ifdef CONFIG_COMPAT 7046efe547SSudeep KarkadaNagesha #define COMPAT_ELF_HWCAP_DEFAULT \ 7146efe547SSudeep KarkadaNagesha (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ 7246efe547SSudeep KarkadaNagesha COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ 7346efe547SSudeep KarkadaNagesha COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ 7446efe547SSudeep KarkadaNagesha COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ 7546efe547SSudeep KarkadaNagesha COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) 7646efe547SSudeep KarkadaNagesha unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; 7728964d32SArd Biesheuvel unsigned int compat_elf_hwcap2 __read_mostly; 7846efe547SSudeep KarkadaNagesha #endif 7946efe547SSudeep KarkadaNagesha 809703d9d7SCatalin Marinas static const char *cpu_name; 815e39977eSWill Deacon static const char *machine_name; 829703d9d7SCatalin Marinas phys_addr_t __fdt_pointer __initdata; 839703d9d7SCatalin Marinas 849703d9d7SCatalin Marinas /* 859703d9d7SCatalin Marinas * Standard memory resources 869703d9d7SCatalin Marinas */ 879703d9d7SCatalin Marinas static struct resource mem_res[] = { 889703d9d7SCatalin Marinas { 899703d9d7SCatalin Marinas .name = "Kernel code", 909703d9d7SCatalin Marinas .start = 0, 919703d9d7SCatalin Marinas .end = 0, 929703d9d7SCatalin Marinas .flags = IORESOURCE_MEM 939703d9d7SCatalin Marinas }, 949703d9d7SCatalin Marinas { 959703d9d7SCatalin Marinas .name = "Kernel data", 969703d9d7SCatalin Marinas .start = 0, 979703d9d7SCatalin Marinas .end = 0, 989703d9d7SCatalin Marinas .flags = IORESOURCE_MEM 999703d9d7SCatalin Marinas } 1009703d9d7SCatalin Marinas }; 1019703d9d7SCatalin Marinas 1029703d9d7SCatalin Marinas #define kernel_code mem_res[0] 1039703d9d7SCatalin Marinas #define kernel_data mem_res[1] 1049703d9d7SCatalin Marinas 1059703d9d7SCatalin Marinas void __init early_print(const char *str, ...) 1069703d9d7SCatalin Marinas { 1079703d9d7SCatalin Marinas char buf[256]; 1089703d9d7SCatalin Marinas va_list ap; 1099703d9d7SCatalin Marinas 1109703d9d7SCatalin Marinas va_start(ap, str); 1119703d9d7SCatalin Marinas vsnprintf(buf, sizeof(buf), str, ap); 1129703d9d7SCatalin Marinas va_end(ap); 1139703d9d7SCatalin Marinas 1149703d9d7SCatalin Marinas printk("%s", buf); 1159703d9d7SCatalin Marinas } 1169703d9d7SCatalin Marinas 11771586276SWill Deacon void __init smp_setup_processor_id(void) 11871586276SWill Deacon { 11971586276SWill Deacon /* 12071586276SWill Deacon * clear __my_cpu_offset on boot CPU to avoid hang caused by 12171586276SWill Deacon * using percpu variable early, for example, lockdep will 12271586276SWill Deacon * access percpu variable inside lock_release 12371586276SWill Deacon */ 12471586276SWill Deacon set_my_cpu_offset(0); 12571586276SWill Deacon } 12671586276SWill Deacon 1276e15d0e0SSudeep KarkadaNagesha bool arch_match_cpu_phys_id(int cpu, u64 phys_id) 1286e15d0e0SSudeep KarkadaNagesha { 1296e15d0e0SSudeep KarkadaNagesha return phys_id == cpu_logical_map(cpu); 1306e15d0e0SSudeep KarkadaNagesha } 1316e15d0e0SSudeep KarkadaNagesha 132976d7d3fSLorenzo Pieralisi struct mpidr_hash mpidr_hash; 133976d7d3fSLorenzo Pieralisi #ifdef CONFIG_SMP 134976d7d3fSLorenzo Pieralisi /** 135976d7d3fSLorenzo Pieralisi * smp_build_mpidr_hash - Pre-compute shifts required at each affinity 136976d7d3fSLorenzo Pieralisi * level in order to build a linear index from an 137976d7d3fSLorenzo Pieralisi * MPIDR value. Resulting algorithm is a collision 138976d7d3fSLorenzo Pieralisi * free hash carried out through shifting and ORing 139976d7d3fSLorenzo Pieralisi */ 140976d7d3fSLorenzo Pieralisi static void __init smp_build_mpidr_hash(void) 141976d7d3fSLorenzo Pieralisi { 142976d7d3fSLorenzo Pieralisi u32 i, affinity, fs[4], bits[4], ls; 143976d7d3fSLorenzo Pieralisi u64 mask = 0; 144976d7d3fSLorenzo Pieralisi /* 145976d7d3fSLorenzo Pieralisi * Pre-scan the list of MPIDRS and filter out bits that do 146976d7d3fSLorenzo Pieralisi * not contribute to affinity levels, ie they never toggle. 147976d7d3fSLorenzo Pieralisi */ 148976d7d3fSLorenzo Pieralisi for_each_possible_cpu(i) 149976d7d3fSLorenzo Pieralisi mask |= (cpu_logical_map(i) ^ cpu_logical_map(0)); 150976d7d3fSLorenzo Pieralisi pr_debug("mask of set bits %#llx\n", mask); 151976d7d3fSLorenzo Pieralisi /* 152976d7d3fSLorenzo Pieralisi * Find and stash the last and first bit set at all affinity levels to 153976d7d3fSLorenzo Pieralisi * check how many bits are required to represent them. 154976d7d3fSLorenzo Pieralisi */ 155976d7d3fSLorenzo Pieralisi for (i = 0; i < 4; i++) { 156976d7d3fSLorenzo Pieralisi affinity = MPIDR_AFFINITY_LEVEL(mask, i); 157976d7d3fSLorenzo Pieralisi /* 158976d7d3fSLorenzo Pieralisi * Find the MSB bit and LSB bits position 159976d7d3fSLorenzo Pieralisi * to determine how many bits are required 160976d7d3fSLorenzo Pieralisi * to express the affinity level. 161976d7d3fSLorenzo Pieralisi */ 162976d7d3fSLorenzo Pieralisi ls = fls(affinity); 163976d7d3fSLorenzo Pieralisi fs[i] = affinity ? ffs(affinity) - 1 : 0; 164976d7d3fSLorenzo Pieralisi bits[i] = ls - fs[i]; 165976d7d3fSLorenzo Pieralisi } 166976d7d3fSLorenzo Pieralisi /* 167976d7d3fSLorenzo Pieralisi * An index can be created from the MPIDR_EL1 by isolating the 168976d7d3fSLorenzo Pieralisi * significant bits at each affinity level and by shifting 169976d7d3fSLorenzo Pieralisi * them in order to compress the 32 bits values space to a 170976d7d3fSLorenzo Pieralisi * compressed set of values. This is equivalent to hashing 171976d7d3fSLorenzo Pieralisi * the MPIDR_EL1 through shifting and ORing. It is a collision free 172976d7d3fSLorenzo Pieralisi * hash though not minimal since some levels might contain a number 173976d7d3fSLorenzo Pieralisi * of CPUs that is not an exact power of 2 and their bit 174976d7d3fSLorenzo Pieralisi * representation might contain holes, eg MPIDR_EL1[7:0] = {0x2, 0x80}. 175976d7d3fSLorenzo Pieralisi */ 176976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0] = MPIDR_LEVEL_SHIFT(0) + fs[0]; 177976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1] = MPIDR_LEVEL_SHIFT(1) + fs[1] - bits[0]; 178976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2] = MPIDR_LEVEL_SHIFT(2) + fs[2] - 179976d7d3fSLorenzo Pieralisi (bits[1] + bits[0]); 180976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3] = MPIDR_LEVEL_SHIFT(3) + 181976d7d3fSLorenzo Pieralisi fs[3] - (bits[2] + bits[1] + bits[0]); 182976d7d3fSLorenzo Pieralisi mpidr_hash.mask = mask; 183976d7d3fSLorenzo Pieralisi mpidr_hash.bits = bits[3] + bits[2] + bits[1] + bits[0]; 184976d7d3fSLorenzo Pieralisi pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] aff3[%u] mask[%#llx] bits[%u]\n", 185976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0], 186976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1], 187976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2], 188976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3], 189976d7d3fSLorenzo Pieralisi mpidr_hash.mask, 190976d7d3fSLorenzo Pieralisi mpidr_hash.bits); 191976d7d3fSLorenzo Pieralisi /* 192976d7d3fSLorenzo Pieralisi * 4x is an arbitrary value used to warn on a hash table much bigger 193976d7d3fSLorenzo Pieralisi * than expected on most systems. 194976d7d3fSLorenzo Pieralisi */ 195976d7d3fSLorenzo Pieralisi if (mpidr_hash_size() > 4 * num_possible_cpus()) 196976d7d3fSLorenzo Pieralisi pr_warn("Large number of MPIDR hash buckets detected\n"); 197976d7d3fSLorenzo Pieralisi __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash)); 198976d7d3fSLorenzo Pieralisi } 199976d7d3fSLorenzo Pieralisi #endif 200976d7d3fSLorenzo Pieralisi 2019703d9d7SCatalin Marinas static void __init setup_processor(void) 2029703d9d7SCatalin Marinas { 2039703d9d7SCatalin Marinas struct cpu_info *cpu_info; 2044bff28ccSSteve Capper u64 features, block; 205a41dc0e8SCatalin Marinas u32 cwg; 206a41dc0e8SCatalin Marinas int cls; 2079703d9d7SCatalin Marinas 2089703d9d7SCatalin Marinas cpu_info = lookup_processor_type(read_cpuid_id()); 2099703d9d7SCatalin Marinas if (!cpu_info) { 2109703d9d7SCatalin Marinas printk("CPU configuration botched (ID %08x), unable to continue.\n", 2119703d9d7SCatalin Marinas read_cpuid_id()); 2129703d9d7SCatalin Marinas while (1); 2139703d9d7SCatalin Marinas } 2149703d9d7SCatalin Marinas 2159703d9d7SCatalin Marinas cpu_name = cpu_info->cpu_name; 2169703d9d7SCatalin Marinas 2179703d9d7SCatalin Marinas printk("CPU: %s [%08x] revision %d\n", 2189703d9d7SCatalin Marinas cpu_name, read_cpuid_id(), read_cpuid_id() & 15); 2199703d9d7SCatalin Marinas 22094ed1f2cSWill Deacon sprintf(init_utsname()->machine, ELF_PLATFORM); 2219703d9d7SCatalin Marinas elf_hwcap = 0; 2224bff28ccSSteve Capper 223df857416SMark Rutland cpuinfo_store_boot_cpu(); 224df857416SMark Rutland 2254bff28ccSSteve Capper /* 226a41dc0e8SCatalin Marinas * Check for sane CTR_EL0.CWG value. 227a41dc0e8SCatalin Marinas */ 228a41dc0e8SCatalin Marinas cwg = cache_type_cwg(); 229a41dc0e8SCatalin Marinas cls = cache_line_size(); 230a41dc0e8SCatalin Marinas if (!cwg) 231a41dc0e8SCatalin Marinas pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n", 232a41dc0e8SCatalin Marinas cls); 233a41dc0e8SCatalin Marinas if (L1_CACHE_BYTES < cls) 234a41dc0e8SCatalin Marinas pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n", 235a41dc0e8SCatalin Marinas L1_CACHE_BYTES, cls); 236a41dc0e8SCatalin Marinas 237a41dc0e8SCatalin Marinas /* 2384bff28ccSSteve Capper * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. 2394bff28ccSSteve Capper * The blocks we test below represent incremental functionality 2404bff28ccSSteve Capper * for non-negative values. Negative values are reserved. 2414bff28ccSSteve Capper */ 2424bff28ccSSteve Capper features = read_cpuid(ID_AA64ISAR0_EL1); 2434bff28ccSSteve Capper block = (features >> 4) & 0xf; 2444bff28ccSSteve Capper if (!(block & 0x8)) { 2454bff28ccSSteve Capper switch (block) { 2464bff28ccSSteve Capper default: 2474bff28ccSSteve Capper case 2: 2484bff28ccSSteve Capper elf_hwcap |= HWCAP_PMULL; 2494bff28ccSSteve Capper case 1: 2504bff28ccSSteve Capper elf_hwcap |= HWCAP_AES; 2514bff28ccSSteve Capper case 0: 2524bff28ccSSteve Capper break; 2534bff28ccSSteve Capper } 2544bff28ccSSteve Capper } 2554bff28ccSSteve Capper 2564bff28ccSSteve Capper block = (features >> 8) & 0xf; 2574bff28ccSSteve Capper if (block && !(block & 0x8)) 2584bff28ccSSteve Capper elf_hwcap |= HWCAP_SHA1; 2594bff28ccSSteve Capper 2604bff28ccSSteve Capper block = (features >> 12) & 0xf; 2614bff28ccSSteve Capper if (block && !(block & 0x8)) 2624bff28ccSSteve Capper elf_hwcap |= HWCAP_SHA2; 2634bff28ccSSteve Capper 2644bff28ccSSteve Capper block = (features >> 16) & 0xf; 2654bff28ccSSteve Capper if (block && !(block & 0x8)) 2664bff28ccSSteve Capper elf_hwcap |= HWCAP_CRC32; 2674cf761cdSArd Biesheuvel 2684cf761cdSArd Biesheuvel #ifdef CONFIG_COMPAT 2694cf761cdSArd Biesheuvel /* 2704cf761cdSArd Biesheuvel * ID_ISAR5_EL1 carries similar information as above, but pertaining to 2714cf761cdSArd Biesheuvel * the Aarch32 32-bit execution state. 2724cf761cdSArd Biesheuvel */ 2734cf761cdSArd Biesheuvel features = read_cpuid(ID_ISAR5_EL1); 2744cf761cdSArd Biesheuvel block = (features >> 4) & 0xf; 2754cf761cdSArd Biesheuvel if (!(block & 0x8)) { 2764cf761cdSArd Biesheuvel switch (block) { 2774cf761cdSArd Biesheuvel default: 2784cf761cdSArd Biesheuvel case 2: 2794cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL; 2804cf761cdSArd Biesheuvel case 1: 2814cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_AES; 2824cf761cdSArd Biesheuvel case 0: 2834cf761cdSArd Biesheuvel break; 2844cf761cdSArd Biesheuvel } 2854cf761cdSArd Biesheuvel } 2864cf761cdSArd Biesheuvel 2874cf761cdSArd Biesheuvel block = (features >> 8) & 0xf; 2884cf761cdSArd Biesheuvel if (block && !(block & 0x8)) 2894cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1; 2904cf761cdSArd Biesheuvel 2914cf761cdSArd Biesheuvel block = (features >> 12) & 0xf; 2924cf761cdSArd Biesheuvel if (block && !(block & 0x8)) 2934cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2; 2944cf761cdSArd Biesheuvel 2954cf761cdSArd Biesheuvel block = (features >> 16) & 0xf; 2964cf761cdSArd Biesheuvel if (block && !(block & 0x8)) 2974cf761cdSArd Biesheuvel compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32; 2984cf761cdSArd Biesheuvel #endif 2999703d9d7SCatalin Marinas } 3009703d9d7SCatalin Marinas 3019703d9d7SCatalin Marinas static void __init setup_machine_fdt(phys_addr_t dt_phys) 3029703d9d7SCatalin Marinas { 303d5189cc5SRob Herring if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys))) { 3049703d9d7SCatalin Marinas early_print("\n" 3059703d9d7SCatalin Marinas "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n" 306d5189cc5SRob Herring "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n" 3079703d9d7SCatalin Marinas "\nPlease check your bootloader.\n", 308d5189cc5SRob Herring dt_phys, phys_to_virt(dt_phys)); 3099703d9d7SCatalin Marinas 3109703d9d7SCatalin Marinas while (true) 3119703d9d7SCatalin Marinas cpu_relax(); 3129703d9d7SCatalin Marinas } 3135e39977eSWill Deacon 3145e39977eSWill Deacon machine_name = of_flat_dt_get_machine_name(); 3159703d9d7SCatalin Marinas } 3169703d9d7SCatalin Marinas 3179703d9d7SCatalin Marinas /* 3189703d9d7SCatalin Marinas * Limit the memory size that was specified via FDT. 3199703d9d7SCatalin Marinas */ 3209703d9d7SCatalin Marinas static int __init early_mem(char *p) 3219703d9d7SCatalin Marinas { 3229703d9d7SCatalin Marinas phys_addr_t limit; 3239703d9d7SCatalin Marinas 3249703d9d7SCatalin Marinas if (!p) 3259703d9d7SCatalin Marinas return 1; 3269703d9d7SCatalin Marinas 3279703d9d7SCatalin Marinas limit = memparse(p, &p) & PAGE_MASK; 3289703d9d7SCatalin Marinas pr_notice("Memory limited to %lldMB\n", limit >> 20); 3299703d9d7SCatalin Marinas 3309703d9d7SCatalin Marinas memblock_enforce_memory_limit(limit); 3319703d9d7SCatalin Marinas 3329703d9d7SCatalin Marinas return 0; 3339703d9d7SCatalin Marinas } 3349703d9d7SCatalin Marinas early_param("mem", early_mem); 3359703d9d7SCatalin Marinas 3369703d9d7SCatalin Marinas static void __init request_standard_resources(void) 3379703d9d7SCatalin Marinas { 3389703d9d7SCatalin Marinas struct memblock_region *region; 3399703d9d7SCatalin Marinas struct resource *res; 3409703d9d7SCatalin Marinas 3419703d9d7SCatalin Marinas kernel_code.start = virt_to_phys(_text); 3429703d9d7SCatalin Marinas kernel_code.end = virt_to_phys(_etext - 1); 3439703d9d7SCatalin Marinas kernel_data.start = virt_to_phys(_sdata); 3449703d9d7SCatalin Marinas kernel_data.end = virt_to_phys(_end - 1); 3459703d9d7SCatalin Marinas 3469703d9d7SCatalin Marinas for_each_memblock(memory, region) { 3479703d9d7SCatalin Marinas res = alloc_bootmem_low(sizeof(*res)); 3489703d9d7SCatalin Marinas res->name = "System RAM"; 3499703d9d7SCatalin Marinas res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); 3509703d9d7SCatalin Marinas res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; 3519703d9d7SCatalin Marinas res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 3529703d9d7SCatalin Marinas 3539703d9d7SCatalin Marinas request_resource(&iomem_resource, res); 3549703d9d7SCatalin Marinas 3559703d9d7SCatalin Marinas if (kernel_code.start >= res->start && 3569703d9d7SCatalin Marinas kernel_code.end <= res->end) 3579703d9d7SCatalin Marinas request_resource(res, &kernel_code); 3589703d9d7SCatalin Marinas if (kernel_data.start >= res->start && 3599703d9d7SCatalin Marinas kernel_data.end <= res->end) 3609703d9d7SCatalin Marinas request_resource(res, &kernel_data); 3619703d9d7SCatalin Marinas } 3629703d9d7SCatalin Marinas } 3639703d9d7SCatalin Marinas 3644c7aa002SJavi Merino u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; 3654c7aa002SJavi Merino 3669703d9d7SCatalin Marinas void __init setup_arch(char **cmdline_p) 3679703d9d7SCatalin Marinas { 3689703d9d7SCatalin Marinas setup_processor(); 3699703d9d7SCatalin Marinas 3709703d9d7SCatalin Marinas setup_machine_fdt(__fdt_pointer); 3719703d9d7SCatalin Marinas 3729703d9d7SCatalin Marinas init_mm.start_code = (unsigned long) _text; 3739703d9d7SCatalin Marinas init_mm.end_code = (unsigned long) _etext; 3749703d9d7SCatalin Marinas init_mm.end_data = (unsigned long) _edata; 3759703d9d7SCatalin Marinas init_mm.brk = (unsigned long) _end; 3769703d9d7SCatalin Marinas 3779703d9d7SCatalin Marinas *cmdline_p = boot_command_line; 3789703d9d7SCatalin Marinas 379bf4b558eSMark Salter early_ioremap_init(); 3800bf757c7SMark Salter 3819703d9d7SCatalin Marinas parse_early_param(); 3829703d9d7SCatalin Marinas 3837a9c43beSJon Masters /* 3847a9c43beSJon Masters * Unmask asynchronous aborts after bringing up possible earlycon. 3857a9c43beSJon Masters * (Report possible System Errors once we can report this occurred) 3867a9c43beSJon Masters */ 3877a9c43beSJon Masters local_async_enable(); 3887a9c43beSJon Masters 389f84d0275SMark Salter efi_init(); 3909703d9d7SCatalin Marinas arm64_memblock_init(); 3919703d9d7SCatalin Marinas 3929703d9d7SCatalin Marinas paging_init(); 3939703d9d7SCatalin Marinas request_standard_resources(); 3949703d9d7SCatalin Marinas 395f84d0275SMark Salter efi_idmap_init(); 396f84d0275SMark Salter 3979703d9d7SCatalin Marinas unflatten_device_tree(); 3989703d9d7SCatalin Marinas 399e790f1deSWill Deacon psci_init(); 400e790f1deSWill Deacon 4014c7aa002SJavi Merino cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; 402e8765b26SMark Rutland cpu_read_bootcpu_ops(); 4039703d9d7SCatalin Marinas #ifdef CONFIG_SMP 4049703d9d7SCatalin Marinas smp_init_cpus(); 405976d7d3fSLorenzo Pieralisi smp_build_mpidr_hash(); 4069703d9d7SCatalin Marinas #endif 4079703d9d7SCatalin Marinas 4089703d9d7SCatalin Marinas #ifdef CONFIG_VT 4099703d9d7SCatalin Marinas #if defined(CONFIG_VGA_CONSOLE) 4109703d9d7SCatalin Marinas conswitchp = &vga_con; 4119703d9d7SCatalin Marinas #elif defined(CONFIG_DUMMY_CONSOLE) 4129703d9d7SCatalin Marinas conswitchp = &dummy_con; 4139703d9d7SCatalin Marinas #endif 4149703d9d7SCatalin Marinas #endif 4159703d9d7SCatalin Marinas } 4169703d9d7SCatalin Marinas 417c560ecfeSCatalin Marinas static int __init arm64_device_init(void) 418de79a64dSCatalin Marinas { 419c560ecfeSCatalin Marinas of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 420de79a64dSCatalin Marinas return 0; 421de79a64dSCatalin Marinas } 4226ecba8ebSCatalin Marinas arch_initcall_sync(arm64_device_init); 423de79a64dSCatalin Marinas 4249703d9d7SCatalin Marinas static int __init topology_init(void) 4259703d9d7SCatalin Marinas { 4269703d9d7SCatalin Marinas int i; 4279703d9d7SCatalin Marinas 4289703d9d7SCatalin Marinas for_each_possible_cpu(i) { 429df857416SMark Rutland struct cpu *cpu = &per_cpu(cpu_data.cpu, i); 4309703d9d7SCatalin Marinas cpu->hotpluggable = 1; 4319703d9d7SCatalin Marinas register_cpu(cpu, i); 4329703d9d7SCatalin Marinas } 4339703d9d7SCatalin Marinas 4349703d9d7SCatalin Marinas return 0; 4359703d9d7SCatalin Marinas } 4369703d9d7SCatalin Marinas subsys_initcall(topology_init); 4379703d9d7SCatalin Marinas 4389703d9d7SCatalin Marinas static const char *hwcap_str[] = { 4399703d9d7SCatalin Marinas "fp", 4409703d9d7SCatalin Marinas "asimd", 44146efe547SSudeep KarkadaNagesha "evtstrm", 4424bff28ccSSteve Capper "aes", 4434bff28ccSSteve Capper "pmull", 4444bff28ccSSteve Capper "sha1", 4454bff28ccSSteve Capper "sha2", 4464bff28ccSSteve Capper "crc32", 4479703d9d7SCatalin Marinas NULL 4489703d9d7SCatalin Marinas }; 4499703d9d7SCatalin Marinas 4509703d9d7SCatalin Marinas static int c_show(struct seq_file *m, void *v) 4519703d9d7SCatalin Marinas { 4529703d9d7SCatalin Marinas int i; 4539703d9d7SCatalin Marinas 4545e39977eSWill Deacon seq_printf(m, "Processor\t: %s rev %d (%s)\n", 4555e39977eSWill Deacon cpu_name, read_cpuid_id() & 15, ELF_PLATFORM); 4569703d9d7SCatalin Marinas 4579703d9d7SCatalin Marinas for_each_online_cpu(i) { 4589703d9d7SCatalin Marinas /* 4599703d9d7SCatalin Marinas * glibc reads /proc/cpuinfo to determine the number of 4609703d9d7SCatalin Marinas * online processors, looking for lines beginning with 4619703d9d7SCatalin Marinas * "processor". Give glibc what it expects. 4629703d9d7SCatalin Marinas */ 4639703d9d7SCatalin Marinas #ifdef CONFIG_SMP 4649703d9d7SCatalin Marinas seq_printf(m, "processor\t: %d\n", i); 4659703d9d7SCatalin Marinas #endif 4669703d9d7SCatalin Marinas } 4679703d9d7SCatalin Marinas 4685e39977eSWill Deacon /* dump out the processor features */ 4695e39977eSWill Deacon seq_puts(m, "Features\t: "); 4705e39977eSWill Deacon 4715e39977eSWill Deacon for (i = 0; hwcap_str[i]; i++) 4725e39977eSWill Deacon if (elf_hwcap & (1 << i)) 4735e39977eSWill Deacon seq_printf(m, "%s ", hwcap_str[i]); 4745e39977eSWill Deacon 4755e39977eSWill Deacon seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); 4765e39977eSWill Deacon seq_printf(m, "CPU architecture: AArch64\n"); 4775e39977eSWill Deacon seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); 4785e39977eSWill Deacon seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); 4795e39977eSWill Deacon seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); 4805e39977eSWill Deacon 4815e39977eSWill Deacon seq_puts(m, "\n"); 4825e39977eSWill Deacon 4835e39977eSWill Deacon seq_printf(m, "Hardware\t: %s\n", machine_name); 4845e39977eSWill Deacon 4859703d9d7SCatalin Marinas return 0; 4869703d9d7SCatalin Marinas } 4879703d9d7SCatalin Marinas 4889703d9d7SCatalin Marinas static void *c_start(struct seq_file *m, loff_t *pos) 4899703d9d7SCatalin Marinas { 4909703d9d7SCatalin Marinas return *pos < 1 ? (void *)1 : NULL; 4919703d9d7SCatalin Marinas } 4929703d9d7SCatalin Marinas 4939703d9d7SCatalin Marinas static void *c_next(struct seq_file *m, void *v, loff_t *pos) 4949703d9d7SCatalin Marinas { 4959703d9d7SCatalin Marinas ++*pos; 4969703d9d7SCatalin Marinas return NULL; 4979703d9d7SCatalin Marinas } 4989703d9d7SCatalin Marinas 4999703d9d7SCatalin Marinas static void c_stop(struct seq_file *m, void *v) 5009703d9d7SCatalin Marinas { 5019703d9d7SCatalin Marinas } 5029703d9d7SCatalin Marinas 5039703d9d7SCatalin Marinas const struct seq_operations cpuinfo_op = { 5049703d9d7SCatalin Marinas .start = c_start, 5059703d9d7SCatalin Marinas .next = c_next, 5069703d9d7SCatalin Marinas .stop = c_stop, 5079703d9d7SCatalin Marinas .show = c_show 5089703d9d7SCatalin Marinas }; 509