15e61cba0SAndrew Jones /* 25e61cba0SAndrew Jones * Initialize machine setup information and I/O. 35e61cba0SAndrew Jones * 45e61cba0SAndrew Jones * After running setup() unit tests may query how many cpus they have 55e61cba0SAndrew Jones * (nr_cpus), how much memory they have (PHYS_END - PHYS_OFFSET), may 65e61cba0SAndrew Jones * use dynamic memory allocation (malloc, etc.), printf, and exit. 75e61cba0SAndrew Jones * Finally, argc and argv are also ready to be passed to main(). 85e61cba0SAndrew Jones * 95e61cba0SAndrew Jones * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 105e61cba0SAndrew Jones * 115e61cba0SAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 125e61cba0SAndrew Jones */ 138cca5668SAndrew Jones #include <libcflat.h> 148cca5668SAndrew Jones #include <libfdt/libfdt.h> 158cca5668SAndrew Jones #include <devicetree.h> 168cca5668SAndrew Jones #include <alloc.h> 17*f6d10793SAndrew Jones #include <asm/thread_info.h> 188cca5668SAndrew Jones #include <asm/setup.h> 198cca5668SAndrew Jones #include <asm/page.h> 208cca5668SAndrew Jones #include <asm/mmu.h> 215e61cba0SAndrew Jones 225e61cba0SAndrew Jones extern unsigned long stacktop; 235e61cba0SAndrew Jones extern void io_init(void); 245e61cba0SAndrew Jones extern void setup_args(const char *args); 255e61cba0SAndrew Jones 268d83d5e7SAndrew Jones u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) }; 275e61cba0SAndrew Jones int nr_cpus; 285e61cba0SAndrew Jones 295e61cba0SAndrew Jones phys_addr_t __phys_offset, __phys_end; 305e61cba0SAndrew Jones 315e61cba0SAndrew Jones static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused) 325e61cba0SAndrew Jones { 335e61cba0SAndrew Jones assert(nr_cpus < NR_CPUS); 345e61cba0SAndrew Jones cpus[nr_cpus++] = regval; 355e61cba0SAndrew Jones } 365e61cba0SAndrew Jones 375e61cba0SAndrew Jones static void cpu_init(void) 385e61cba0SAndrew Jones { 395e61cba0SAndrew Jones nr_cpus = 0; 405e61cba0SAndrew Jones assert(dt_for_each_cpu_node(cpu_set, NULL) == 0); 415e61cba0SAndrew Jones } 425e61cba0SAndrew Jones 435e61cba0SAndrew Jones static void mem_init(phys_addr_t freemem_start) 445e61cba0SAndrew Jones { 455e61cba0SAndrew Jones /* we only expect one membank to be defined in the DT */ 465e61cba0SAndrew Jones struct dt_pbus_reg regs[1]; 475e61cba0SAndrew Jones phys_addr_t mem_start, mem_end; 485e61cba0SAndrew Jones 495e61cba0SAndrew Jones assert(dt_get_memory_params(regs, 1)); 505e61cba0SAndrew Jones 515e61cba0SAndrew Jones mem_start = regs[0].addr; 525e61cba0SAndrew Jones mem_end = mem_start + regs[0].size; 535e61cba0SAndrew Jones 545e61cba0SAndrew Jones assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK)); 555e61cba0SAndrew Jones assert(freemem_start >= mem_start && freemem_start < mem_end); 565e61cba0SAndrew Jones 575e61cba0SAndrew Jones __phys_offset = mem_start; /* PHYS_OFFSET */ 585e61cba0SAndrew Jones __phys_end = mem_end; /* PHYS_END */ 595e61cba0SAndrew Jones 605e61cba0SAndrew Jones phys_alloc_init(freemem_start, mem_end - freemem_start); 615e61cba0SAndrew Jones phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES); 62153d1936SAndrew Jones 63153d1936SAndrew Jones mmu_enable_idmap(); 645e61cba0SAndrew Jones } 655e61cba0SAndrew Jones 66dd4af6b1SAndrew Jones void setup(const void *fdt) 675e61cba0SAndrew Jones { 685e61cba0SAndrew Jones const char *bootargs; 695e61cba0SAndrew Jones u32 fdt_size; 705e61cba0SAndrew Jones 715e61cba0SAndrew Jones /* 725e61cba0SAndrew Jones * Move the fdt to just above the stack. The free memory 735e61cba0SAndrew Jones * then starts just after the fdt. 745e61cba0SAndrew Jones */ 755e61cba0SAndrew Jones fdt_size = fdt_totalsize(fdt); 765e61cba0SAndrew Jones assert(fdt_move(fdt, &stacktop, fdt_size) == 0); 775e61cba0SAndrew Jones assert(dt_init(&stacktop) == 0); 785e61cba0SAndrew Jones 795e61cba0SAndrew Jones mem_init(PAGE_ALIGN((unsigned long)&stacktop + fdt_size)); 805e61cba0SAndrew Jones io_init(); 815e61cba0SAndrew Jones cpu_init(); 825e61cba0SAndrew Jones 83*f6d10793SAndrew Jones thread_info_init(current_thread_info(), 0); 84*f6d10793SAndrew Jones 855e61cba0SAndrew Jones assert(dt_get_bootargs(&bootargs) == 0); 865e61cba0SAndrew Jones setup_args(bootargs); 875e61cba0SAndrew Jones } 88