1 /* 2 * Initialize machine setup information and I/O. 3 * 4 * After running setup() unit tests may query how many cpus they have 5 * (nr_cpus), how much memory they have (PHYS_END - PHYS_OFFSET), may 6 * use dynamic memory allocation (malloc, etc.), printf, and exit. 7 * Finally, argc and argv are also ready to be passed to main(). 8 * 9 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 10 * 11 * This work is licensed under the terms of the GNU LGPL, version 2. 12 */ 13 #include "libcflat.h" 14 #include "libfdt/libfdt.h" 15 #include "devicetree.h" 16 #include "alloc.h" 17 #include "asm/setup.h" 18 #include "asm/page.h" 19 20 extern unsigned long stacktop; 21 extern void io_init(void); 22 extern void setup_args(const char *args); 23 24 u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0UL) }; 25 int nr_cpus; 26 27 phys_addr_t __phys_offset, __phys_end; 28 29 static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused) 30 { 31 assert(nr_cpus < NR_CPUS); 32 cpus[nr_cpus++] = regval; 33 } 34 35 static void cpu_init(void) 36 { 37 nr_cpus = 0; 38 assert(dt_for_each_cpu_node(cpu_set, NULL) == 0); 39 } 40 41 static void mem_init(phys_addr_t freemem_start) 42 { 43 /* we only expect one membank to be defined in the DT */ 44 struct dt_pbus_reg regs[1]; 45 phys_addr_t mem_start, mem_end; 46 47 assert(dt_get_memory_params(regs, 1)); 48 49 mem_start = regs[0].addr; 50 mem_end = mem_start + regs[0].size; 51 52 assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK)); 53 assert(freemem_start >= mem_start && freemem_start < mem_end); 54 55 __phys_offset = mem_start; /* PHYS_OFFSET */ 56 __phys_end = mem_end; /* PHYS_END */ 57 58 phys_alloc_init(freemem_start, mem_end - freemem_start); 59 phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES); 60 } 61 62 void setup(unsigned long arg __unused, unsigned long id __unused, 63 const void *fdt) 64 { 65 const char *bootargs; 66 u32 fdt_size; 67 68 /* 69 * Move the fdt to just above the stack. The free memory 70 * then starts just after the fdt. 71 */ 72 fdt_size = fdt_totalsize(fdt); 73 assert(fdt_move(fdt, &stacktop, fdt_size) == 0); 74 assert(dt_init(&stacktop) == 0); 75 76 mem_init(PAGE_ALIGN((unsigned long)&stacktop + fdt_size)); 77 io_init(); 78 cpu_init(); 79 80 assert(dt_get_bootargs(&bootargs) == 0); 81 setup_args(bootargs); 82 } 83