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 */ 135e61cba0SAndrew Jones #include "libcflat.h" 145e61cba0SAndrew Jones #include "libfdt/libfdt.h" 155e61cba0SAndrew Jones #include "devicetree.h" 165e61cba0SAndrew Jones #include "alloc.h" 175e61cba0SAndrew Jones #include "asm/setup.h" 185e61cba0SAndrew Jones #include "asm/page.h" 19153d1936SAndrew Jones #include "asm/mmu.h" 205e61cba0SAndrew Jones 215e61cba0SAndrew Jones extern unsigned long stacktop; 225e61cba0SAndrew Jones extern void io_init(void); 235e61cba0SAndrew Jones extern void setup_args(const char *args); 245e61cba0SAndrew Jones 25*8d83d5e7SAndrew Jones u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) }; 265e61cba0SAndrew Jones int nr_cpus; 275e61cba0SAndrew Jones 285e61cba0SAndrew Jones phys_addr_t __phys_offset, __phys_end; 295e61cba0SAndrew Jones 305e61cba0SAndrew Jones static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused) 315e61cba0SAndrew Jones { 325e61cba0SAndrew Jones assert(nr_cpus < NR_CPUS); 335e61cba0SAndrew Jones cpus[nr_cpus++] = regval; 345e61cba0SAndrew Jones } 355e61cba0SAndrew Jones 365e61cba0SAndrew Jones static void cpu_init(void) 375e61cba0SAndrew Jones { 385e61cba0SAndrew Jones nr_cpus = 0; 395e61cba0SAndrew Jones assert(dt_for_each_cpu_node(cpu_set, NULL) == 0); 405e61cba0SAndrew Jones } 415e61cba0SAndrew Jones 425e61cba0SAndrew Jones static void mem_init(phys_addr_t freemem_start) 435e61cba0SAndrew Jones { 445e61cba0SAndrew Jones /* we only expect one membank to be defined in the DT */ 455e61cba0SAndrew Jones struct dt_pbus_reg regs[1]; 465e61cba0SAndrew Jones phys_addr_t mem_start, mem_end; 475e61cba0SAndrew Jones 485e61cba0SAndrew Jones assert(dt_get_memory_params(regs, 1)); 495e61cba0SAndrew Jones 505e61cba0SAndrew Jones mem_start = regs[0].addr; 515e61cba0SAndrew Jones mem_end = mem_start + regs[0].size; 525e61cba0SAndrew Jones 535e61cba0SAndrew Jones assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK)); 545e61cba0SAndrew Jones assert(freemem_start >= mem_start && freemem_start < mem_end); 555e61cba0SAndrew Jones 565e61cba0SAndrew Jones __phys_offset = mem_start; /* PHYS_OFFSET */ 575e61cba0SAndrew Jones __phys_end = mem_end; /* PHYS_END */ 585e61cba0SAndrew Jones 595e61cba0SAndrew Jones phys_alloc_init(freemem_start, mem_end - freemem_start); 605e61cba0SAndrew Jones phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES); 61153d1936SAndrew Jones 62153d1936SAndrew Jones mmu_enable_idmap(); 635e61cba0SAndrew Jones } 645e61cba0SAndrew Jones 655e61cba0SAndrew Jones void setup(unsigned long arg __unused, unsigned long id __unused, 665e61cba0SAndrew Jones 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 835e61cba0SAndrew Jones assert(dt_get_bootargs(&bootargs) == 0); 845e61cba0SAndrew Jones setup_args(bootargs); 855e61cba0SAndrew Jones } 86