1*27d22413SLey Foon Tan /* 2*27d22413SLey Foon Tan * Nios2-specific parts of system setup 3*27d22413SLey Foon Tan * 4*27d22413SLey Foon Tan * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> 5*27d22413SLey Foon Tan * Copyright (C) 2004 Microtronix Datacom Ltd. 6*27d22413SLey Foon Tan * Copyright (C) 2001 Vic Phillips <vic@microtronix.com> 7*27d22413SLey Foon Tan * 8*27d22413SLey Foon Tan * This file is subject to the terms and conditions of the GNU General Public 9*27d22413SLey Foon Tan * License. See the file "COPYING" in the main directory of this archive 10*27d22413SLey Foon Tan * for more details. 11*27d22413SLey Foon Tan */ 12*27d22413SLey Foon Tan 13*27d22413SLey Foon Tan #include <linux/export.h> 14*27d22413SLey Foon Tan #include <linux/kernel.h> 15*27d22413SLey Foon Tan #include <linux/mm.h> 16*27d22413SLey Foon Tan #include <linux/sched.h> 17*27d22413SLey Foon Tan #include <linux/console.h> 18*27d22413SLey Foon Tan #include <linux/bootmem.h> 19*27d22413SLey Foon Tan #include <linux/initrd.h> 20*27d22413SLey Foon Tan #include <linux/of_fdt.h> 21*27d22413SLey Foon Tan 22*27d22413SLey Foon Tan #include <asm/mmu_context.h> 23*27d22413SLey Foon Tan #include <asm/sections.h> 24*27d22413SLey Foon Tan #include <asm/setup.h> 25*27d22413SLey Foon Tan #include <asm/cpuinfo.h> 26*27d22413SLey Foon Tan 27*27d22413SLey Foon Tan unsigned long memory_start; 28*27d22413SLey Foon Tan EXPORT_SYMBOL(memory_start); 29*27d22413SLey Foon Tan 30*27d22413SLey Foon Tan unsigned long memory_end; 31*27d22413SLey Foon Tan EXPORT_SYMBOL(memory_end); 32*27d22413SLey Foon Tan 33*27d22413SLey Foon Tan unsigned long memory_size; 34*27d22413SLey Foon Tan 35*27d22413SLey Foon Tan static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36*27d22413SLey Foon Tan 0, 0, 0, 0, 0, 0, 37*27d22413SLey Foon Tan 0}; 38*27d22413SLey Foon Tan 39*27d22413SLey Foon Tan /* Copy a short hook instruction sequence to the exception address */ 40*27d22413SLey Foon Tan static inline void copy_exception_handler(unsigned int addr) 41*27d22413SLey Foon Tan { 42*27d22413SLey Foon Tan unsigned int start = (unsigned int) exception_handler_hook; 43*27d22413SLey Foon Tan volatile unsigned int tmp = 0; 44*27d22413SLey Foon Tan 45*27d22413SLey Foon Tan if (start == addr) { 46*27d22413SLey Foon Tan /* The CPU exception address already points to the handler. */ 47*27d22413SLey Foon Tan return; 48*27d22413SLey Foon Tan } 49*27d22413SLey Foon Tan 50*27d22413SLey Foon Tan __asm__ __volatile__ ( 51*27d22413SLey Foon Tan "ldw %2,0(%0)\n" 52*27d22413SLey Foon Tan "stw %2,0(%1)\n" 53*27d22413SLey Foon Tan "ldw %2,4(%0)\n" 54*27d22413SLey Foon Tan "stw %2,4(%1)\n" 55*27d22413SLey Foon Tan "ldw %2,8(%0)\n" 56*27d22413SLey Foon Tan "stw %2,8(%1)\n" 57*27d22413SLey Foon Tan "flushd 0(%1)\n" 58*27d22413SLey Foon Tan "flushd 4(%1)\n" 59*27d22413SLey Foon Tan "flushd 8(%1)\n" 60*27d22413SLey Foon Tan "flushi %1\n" 61*27d22413SLey Foon Tan "addi %1,%1,4\n" 62*27d22413SLey Foon Tan "flushi %1\n" 63*27d22413SLey Foon Tan "addi %1,%1,4\n" 64*27d22413SLey Foon Tan "flushi %1\n" 65*27d22413SLey Foon Tan "flushp\n" 66*27d22413SLey Foon Tan : /* no output registers */ 67*27d22413SLey Foon Tan : "r" (start), "r" (addr), "r" (tmp) 68*27d22413SLey Foon Tan : "memory" 69*27d22413SLey Foon Tan ); 70*27d22413SLey Foon Tan } 71*27d22413SLey Foon Tan 72*27d22413SLey Foon Tan /* Copy the fast TLB miss handler */ 73*27d22413SLey Foon Tan static inline void copy_fast_tlb_miss_handler(unsigned int addr) 74*27d22413SLey Foon Tan { 75*27d22413SLey Foon Tan unsigned int start = (unsigned int) fast_handler; 76*27d22413SLey Foon Tan unsigned int end = (unsigned int) fast_handler_end; 77*27d22413SLey Foon Tan volatile unsigned int tmp = 0; 78*27d22413SLey Foon Tan 79*27d22413SLey Foon Tan __asm__ __volatile__ ( 80*27d22413SLey Foon Tan "1:\n" 81*27d22413SLey Foon Tan " ldw %3,0(%0)\n" 82*27d22413SLey Foon Tan " stw %3,0(%1)\n" 83*27d22413SLey Foon Tan " flushd 0(%1)\n" 84*27d22413SLey Foon Tan " flushi %1\n" 85*27d22413SLey Foon Tan " flushp\n" 86*27d22413SLey Foon Tan " addi %0,%0,4\n" 87*27d22413SLey Foon Tan " addi %1,%1,4\n" 88*27d22413SLey Foon Tan " bne %0,%2,1b\n" 89*27d22413SLey Foon Tan : /* no output registers */ 90*27d22413SLey Foon Tan : "r" (start), "r" (addr), "r" (end), "r" (tmp) 91*27d22413SLey Foon Tan : "memory" 92*27d22413SLey Foon Tan ); 93*27d22413SLey Foon Tan } 94*27d22413SLey Foon Tan 95*27d22413SLey Foon Tan /* 96*27d22413SLey Foon Tan * save args passed from u-boot, called from head.S 97*27d22413SLey Foon Tan * 98*27d22413SLey Foon Tan * @r4: NIOS magic 99*27d22413SLey Foon Tan * @r5: initrd start 100*27d22413SLey Foon Tan * @r6: initrd end or fdt 101*27d22413SLey Foon Tan * @r7: kernel command line 102*27d22413SLey Foon Tan */ 103*27d22413SLey Foon Tan asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6, 104*27d22413SLey Foon Tan unsigned r7) 105*27d22413SLey Foon Tan { 106*27d22413SLey Foon Tan unsigned dtb_passed = 0; 107*27d22413SLey Foon Tan char cmdline_passed[COMMAND_LINE_SIZE] = { 0, }; 108*27d22413SLey Foon Tan 109*27d22413SLey Foon Tan #if defined(CONFIG_NIOS2_PASS_CMDLINE) 110*27d22413SLey Foon Tan if (r4 == 0x534f494e) { /* r4 is magic NIOS */ 111*27d22413SLey Foon Tan #if defined(CONFIG_BLK_DEV_INITRD) 112*27d22413SLey Foon Tan if (r5) { /* initramfs */ 113*27d22413SLey Foon Tan initrd_start = r5; 114*27d22413SLey Foon Tan initrd_end = r6; 115*27d22413SLey Foon Tan } 116*27d22413SLey Foon Tan #endif /* CONFIG_BLK_DEV_INITRD */ 117*27d22413SLey Foon Tan dtb_passed = r6; 118*27d22413SLey Foon Tan 119*27d22413SLey Foon Tan if (r7) 120*27d22413SLey Foon Tan strncpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE); 121*27d22413SLey Foon Tan } 122*27d22413SLey Foon Tan #endif 123*27d22413SLey Foon Tan 124*27d22413SLey Foon Tan early_init_devtree((void *)dtb_passed); 125*27d22413SLey Foon Tan 126*27d22413SLey Foon Tan #ifndef CONFIG_CMDLINE_FORCE 127*27d22413SLey Foon Tan if (cmdline_passed[0]) 128*27d22413SLey Foon Tan strncpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE); 129*27d22413SLey Foon Tan #ifdef CONFIG_NIOS2_CMDLINE_IGNORE_DTB 130*27d22413SLey Foon Tan else 131*27d22413SLey Foon Tan strncpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 132*27d22413SLey Foon Tan #endif 133*27d22413SLey Foon Tan #endif 134*27d22413SLey Foon Tan } 135*27d22413SLey Foon Tan 136*27d22413SLey Foon Tan void __init setup_arch(char **cmdline_p) 137*27d22413SLey Foon Tan { 138*27d22413SLey Foon Tan int bootmap_size; 139*27d22413SLey Foon Tan 140*27d22413SLey Foon Tan console_verbose(); 141*27d22413SLey Foon Tan 142*27d22413SLey Foon Tan memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); 143*27d22413SLey Foon Tan memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; 144*27d22413SLey Foon Tan 145*27d22413SLey Foon Tan init_mm.start_code = (unsigned long) _stext; 146*27d22413SLey Foon Tan init_mm.end_code = (unsigned long) _etext; 147*27d22413SLey Foon Tan init_mm.end_data = (unsigned long) _edata; 148*27d22413SLey Foon Tan init_mm.brk = (unsigned long) _end; 149*27d22413SLey Foon Tan init_task.thread.kregs = &fake_regs; 150*27d22413SLey Foon Tan 151*27d22413SLey Foon Tan /* Keep a copy of command line */ 152*27d22413SLey Foon Tan *cmdline_p = boot_command_line; 153*27d22413SLey Foon Tan 154*27d22413SLey Foon Tan min_low_pfn = PFN_UP(memory_start); 155*27d22413SLey Foon Tan max_low_pfn = PFN_DOWN(memory_end); 156*27d22413SLey Foon Tan max_mapnr = max_low_pfn; 157*27d22413SLey Foon Tan 158*27d22413SLey Foon Tan /* 159*27d22413SLey Foon Tan * give all the memory to the bootmap allocator, tell it to put the 160*27d22413SLey Foon Tan * boot mem_map at the start of memory 161*27d22413SLey Foon Tan */ 162*27d22413SLey Foon Tan pr_debug("init_bootmem_node(?,%#lx, %#x, %#lx)\n", 163*27d22413SLey Foon Tan min_low_pfn, PFN_DOWN(PHYS_OFFSET), max_low_pfn); 164*27d22413SLey Foon Tan bootmap_size = init_bootmem_node(NODE_DATA(0), 165*27d22413SLey Foon Tan min_low_pfn, PFN_DOWN(PHYS_OFFSET), 166*27d22413SLey Foon Tan max_low_pfn); 167*27d22413SLey Foon Tan 168*27d22413SLey Foon Tan /* 169*27d22413SLey Foon Tan * free the usable memory, we have to make sure we do not free 170*27d22413SLey Foon Tan * the bootmem bitmap so we then reserve it after freeing it :-) 171*27d22413SLey Foon Tan */ 172*27d22413SLey Foon Tan pr_debug("free_bootmem(%#lx, %#lx)\n", 173*27d22413SLey Foon Tan memory_start, memory_end - memory_start); 174*27d22413SLey Foon Tan free_bootmem(memory_start, memory_end - memory_start); 175*27d22413SLey Foon Tan 176*27d22413SLey Foon Tan /* 177*27d22413SLey Foon Tan * Reserve the bootmem bitmap itself as well. We do this in two 178*27d22413SLey Foon Tan * steps (first step was init_bootmem()) because this catches 179*27d22413SLey Foon Tan * the (very unlikely) case of us accidentally initializing the 180*27d22413SLey Foon Tan * bootmem allocator with an invalid RAM area. 181*27d22413SLey Foon Tan * 182*27d22413SLey Foon Tan * Arguments are start, size 183*27d22413SLey Foon Tan */ 184*27d22413SLey Foon Tan pr_debug("reserve_bootmem(%#lx, %#x)\n", memory_start, bootmap_size); 185*27d22413SLey Foon Tan reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT); 186*27d22413SLey Foon Tan 187*27d22413SLey Foon Tan #ifdef CONFIG_BLK_DEV_INITRD 188*27d22413SLey Foon Tan if (initrd_start) { 189*27d22413SLey Foon Tan reserve_bootmem(virt_to_phys((void *)initrd_start), 190*27d22413SLey Foon Tan initrd_end - initrd_start, BOOTMEM_DEFAULT); 191*27d22413SLey Foon Tan } 192*27d22413SLey Foon Tan #endif /* CONFIG_BLK_DEV_INITRD */ 193*27d22413SLey Foon Tan 194*27d22413SLey Foon Tan unflatten_and_copy_device_tree(); 195*27d22413SLey Foon Tan 196*27d22413SLey Foon Tan setup_cpuinfo(); 197*27d22413SLey Foon Tan 198*27d22413SLey Foon Tan copy_exception_handler(cpuinfo.exception_addr); 199*27d22413SLey Foon Tan 200*27d22413SLey Foon Tan mmu_init(); 201*27d22413SLey Foon Tan 202*27d22413SLey Foon Tan copy_fast_tlb_miss_handler(cpuinfo.fast_tlb_miss_exc_addr); 203*27d22413SLey Foon Tan 204*27d22413SLey Foon Tan /* 205*27d22413SLey Foon Tan * Initialize MMU context handling here because data from cpuinfo is 206*27d22413SLey Foon Tan * needed for this. 207*27d22413SLey Foon Tan */ 208*27d22413SLey Foon Tan mmu_context_init(); 209*27d22413SLey Foon Tan 210*27d22413SLey Foon Tan /* 211*27d22413SLey Foon Tan * get kmalloc into gear 212*27d22413SLey Foon Tan */ 213*27d22413SLey Foon Tan paging_init(); 214*27d22413SLey Foon Tan 215*27d22413SLey Foon Tan #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) 216*27d22413SLey Foon Tan conswitchp = &dummy_con; 217*27d22413SLey Foon Tan #endif 218*27d22413SLey Foon Tan } 219