Linux 3.12.39
[linux/fpc-iii.git] / arch / arm64 / kernel / setup.c
blob24bf1563c3bdfe75ac36506e4dedc94fa77867d7
1 /*
2 * Based on arch/arm/kernel/setup.c
4 * Copyright (C) 1995-2001 Russell King
5 * Copyright (C) 2012 ARM Ltd.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/export.h>
21 #include <linux/kernel.h>
22 #include <linux/stddef.h>
23 #include <linux/ioport.h>
24 #include <linux/delay.h>
25 #include <linux/utsname.h>
26 #include <linux/initrd.h>
27 #include <linux/console.h>
28 #include <linux/bootmem.h>
29 #include <linux/seq_file.h>
30 #include <linux/screen_info.h>
31 #include <linux/init.h>
32 #include <linux/kexec.h>
33 #include <linux/crash_dump.h>
34 #include <linux/root_dev.h>
35 #include <linux/clk-provider.h>
36 #include <linux/cpu.h>
37 #include <linux/interrupt.h>
38 #include <linux/smp.h>
39 #include <linux/fs.h>
40 #include <linux/proc_fs.h>
41 #include <linux/memblock.h>
42 #include <linux/of_fdt.h>
43 #include <linux/of_platform.h>
44 #include <linux/personality.h>
46 #include <asm/cputype.h>
47 #include <asm/elf.h>
48 #include <asm/cputable.h>
49 #include <asm/sections.h>
50 #include <asm/setup.h>
51 #include <asm/smp_plat.h>
52 #include <asm/cacheflush.h>
53 #include <asm/tlbflush.h>
54 #include <asm/traps.h>
55 #include <asm/memblock.h>
56 #include <asm/psci.h>
58 unsigned int processor_id;
59 EXPORT_SYMBOL(processor_id);
61 unsigned long elf_hwcap __read_mostly;
62 EXPORT_SYMBOL_GPL(elf_hwcap);
64 static const char *cpu_name;
65 static const char *machine_name;
66 phys_addr_t __fdt_pointer __initdata;
69 * Standard memory resources
71 static struct resource mem_res[] = {
73 .name = "Kernel code",
74 .start = 0,
75 .end = 0,
76 .flags = IORESOURCE_MEM
79 .name = "Kernel data",
80 .start = 0,
81 .end = 0,
82 .flags = IORESOURCE_MEM
86 #define kernel_code mem_res[0]
87 #define kernel_data mem_res[1]
89 void __init early_print(const char *str, ...)
91 char buf[256];
92 va_list ap;
94 va_start(ap, str);
95 vsnprintf(buf, sizeof(buf), str, ap);
96 va_end(ap);
98 printk("%s", buf);
101 struct cpuinfo_arm64 {
102 struct cpu cpu;
103 u32 reg_midr;
106 static DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
108 void cpuinfo_store_cpu(void)
110 struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
111 info->reg_midr = read_cpuid_id();
114 static void __init setup_processor(void)
116 struct cpu_info *cpu_info;
119 * locate processor in the list of supported processor
120 * types. The linker builds this table for us from the
121 * entries in arch/arm/mm/proc.S
123 cpu_info = lookup_processor_type(read_cpuid_id());
124 if (!cpu_info) {
125 printk("CPU configuration botched (ID %08x), unable to continue.\n",
126 read_cpuid_id());
127 while (1);
130 cpu_name = cpu_info->cpu_name;
132 printk("CPU: %s [%08x] revision %d\n",
133 cpu_name, read_cpuid_id(), read_cpuid_id() & 15);
135 sprintf(init_utsname()->machine, "aarch64");
136 elf_hwcap = 0;
139 static void __init setup_machine_fdt(phys_addr_t dt_phys)
141 struct boot_param_header *devtree;
142 unsigned long dt_root;
144 cpuinfo_store_cpu();
146 /* Check we have a non-NULL DT pointer */
147 if (!dt_phys) {
148 early_print("\n"
149 "Error: NULL or invalid device tree blob\n"
150 "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
151 "\nPlease check your bootloader.\n");
153 while (true)
154 cpu_relax();
158 devtree = phys_to_virt(dt_phys);
160 /* Check device tree validity */
161 if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {
162 early_print("\n"
163 "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"
164 "Expected 0x%x, found 0x%x\n"
165 "\nPlease check your bootloader.\n",
166 dt_phys, devtree, OF_DT_HEADER,
167 be32_to_cpu(devtree->magic));
169 while (true)
170 cpu_relax();
173 initial_boot_params = devtree;
174 dt_root = of_get_flat_dt_root();
176 machine_name = of_get_flat_dt_prop(dt_root, "model", NULL);
177 if (!machine_name)
178 machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
179 if (!machine_name)
180 machine_name = "<unknown>";
181 pr_info("Machine: %s\n", machine_name);
183 /* Retrieve various information from the /chosen node */
184 of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
185 /* Initialize {size,address}-cells info */
186 of_scan_flat_dt(early_init_dt_scan_root, NULL);
187 /* Setup memory, calling early_init_dt_add_memory_arch */
188 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
191 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
193 base &= PAGE_MASK;
194 size &= PAGE_MASK;
195 if (base + size < PHYS_OFFSET) {
196 pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
197 base, base + size);
198 return;
200 if (base < PHYS_OFFSET) {
201 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
202 base, PHYS_OFFSET);
203 size -= PHYS_OFFSET - base;
204 base = PHYS_OFFSET;
206 memblock_add(base, size);
210 * Limit the memory size that was specified via FDT.
212 static int __init early_mem(char *p)
214 phys_addr_t limit;
216 if (!p)
217 return 1;
219 limit = memparse(p, &p) & PAGE_MASK;
220 pr_notice("Memory limited to %lldMB\n", limit >> 20);
222 memblock_enforce_memory_limit(limit);
224 return 0;
226 early_param("mem", early_mem);
228 static void __init request_standard_resources(void)
230 struct memblock_region *region;
231 struct resource *res;
233 kernel_code.start = virt_to_phys(_text);
234 kernel_code.end = virt_to_phys(_etext - 1);
235 kernel_data.start = virt_to_phys(_sdata);
236 kernel_data.end = virt_to_phys(_end - 1);
238 for_each_memblock(memory, region) {
239 res = alloc_bootmem_low(sizeof(*res));
240 res->name = "System RAM";
241 res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
242 res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
243 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
245 request_resource(&iomem_resource, res);
247 if (kernel_code.start >= res->start &&
248 kernel_code.end <= res->end)
249 request_resource(res, &kernel_code);
250 if (kernel_data.start >= res->start &&
251 kernel_data.end <= res->end)
252 request_resource(res, &kernel_data);
256 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
258 void __init setup_arch(char **cmdline_p)
260 setup_processor();
262 setup_machine_fdt(__fdt_pointer);
264 init_mm.start_code = (unsigned long) _text;
265 init_mm.end_code = (unsigned long) _etext;
266 init_mm.end_data = (unsigned long) _edata;
267 init_mm.brk = (unsigned long) _end;
269 *cmdline_p = boot_command_line;
271 parse_early_param();
273 arm64_memblock_init();
275 paging_init();
276 request_standard_resources();
278 unflatten_device_tree();
280 psci_init();
282 cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
283 #ifdef CONFIG_SMP
284 smp_init_cpus();
285 #endif
287 #ifdef CONFIG_VT
288 #if defined(CONFIG_VGA_CONSOLE)
289 conswitchp = &vga_con;
290 #elif defined(CONFIG_DUMMY_CONSOLE)
291 conswitchp = &dummy_con;
292 #endif
293 #endif
296 static int __init arm64_device_init(void)
298 of_clk_init(NULL);
299 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
300 return 0;
302 arch_initcall(arm64_device_init);
304 static int __init topology_init(void)
306 int i;
308 for_each_possible_cpu(i) {
309 struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
310 cpu->hotpluggable = 1;
311 register_cpu(cpu, i);
314 return 0;
316 subsys_initcall(topology_init);
318 static const char *hwcap_str[] = {
319 "fp",
320 "asimd",
321 NULL
324 #ifdef CONFIG_COMPAT
325 static const char *compat_hwcap_str[] = {
326 "swp",
327 "half",
328 "thumb",
329 "26bit",
330 "fastmult",
331 "fpa",
332 "vfp",
333 "edsp",
334 "java",
335 "iwmmxt",
336 "crunch",
337 "thumbee",
338 "neon",
339 "vfpv3",
340 "vfpv3d16",
341 "tls",
342 "vfpv4",
343 "idiva",
344 "idivt",
345 "vfpd32",
346 "lpae",
347 "evtstrm"
349 #endif /* CONFIG_COMPAT */
351 static int c_show(struct seq_file *m, void *v)
353 int i, j;
355 for_each_online_cpu(i) {
356 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
357 u32 midr = cpuinfo->reg_midr;
360 * glibc reads /proc/cpuinfo to determine the number of
361 * online processors, looking for lines beginning with
362 * "processor". Give glibc what it expects.
364 #ifdef CONFIG_SMP
365 seq_printf(m, "processor\t: %d\n", i);
366 #endif
369 * Dump out the common processor features in a single line.
370 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
371 * rather than attempting to parse this, but there's a body of
372 * software which does already (at least for 32-bit).
374 seq_puts(m, "Features\t:");
375 if (personality(current->personality) == PER_LINUX32) {
376 #ifdef CONFIG_COMPAT
377 for (j = 0; compat_hwcap_str[j]; j++)
378 if (COMPAT_ELF_HWCAP & (1 << j))
379 seq_printf(m, " %s", compat_hwcap_str[j]);
380 #endif /* CONFIG_COMPAT */
381 } else {
382 for (j = 0; hwcap_str[j]; j++)
383 if (elf_hwcap & (1 << j))
384 seq_printf(m, " %s", hwcap_str[j]);
386 seq_puts(m, "\n");
388 seq_printf(m, "CPU implementer\t: 0x%02x\n", (midr >> 24));
389 seq_printf(m, "CPU architecture: 8\n");
390 seq_printf(m, "CPU variant\t: 0x%x\n", ((midr >> 20) & 0xf));
391 seq_printf(m, "CPU part\t: 0x%03x\n", ((midr >> 4) & 0xfff));
392 seq_printf(m, "CPU revision\t: %d\n\n", (midr & 0xf));
395 return 0;
398 static void *c_start(struct seq_file *m, loff_t *pos)
400 return *pos < 1 ? (void *)1 : NULL;
403 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
405 ++*pos;
406 return NULL;
409 static void c_stop(struct seq_file *m, void *v)
413 const struct seq_operations cpuinfo_op = {
414 .start = c_start,
415 .next = c_next,
416 .stop = c_stop,
417 .show = c_show