| 1 | |
| 2 | * Nios2-specific parts of system setup
|
| 3 | *
|
| 4 | * Copyright (C) 2010 Tobias Klauser <[email protected]>
|
| 5 | * Copyright (C) 2004 Microtronix Datacom Ltd.
|
| 6 | * Copyright (C) 2001 Vic Phillips <[email protected]>
|
| 7 | *
|
| 8 | * This file is subject to the terms and conditions of the GNU General Public
|
| 9 | * License. See the file "COPYING" in the main directory of this archive
|
| 10 | * for more details.
|
| 11 |
|
| 12 |
|
| 13 | #include <linux/export.h>
|
| 14 | #include <linux/kernel.h>
|
| 15 | #include <linux/mm.h>
|
| 16 | #include <linux/sched.h>
|
| 17 | #include <linux/sched/task.h>
|
| 18 | #include <linux/console.h>
|
| 19 | #include <linux/memblock.h>
|
| 20 | #include <linux/initrd.h>
|
| 21 | #include <linux/of_fdt.h>
|
| 22 |
|
| 23 | #include <asm/mmu_context.h>
|
| 24 | #include <asm/sections.h>
|
| 25 | #include <asm/setup.h>
|
| 26 | #include <asm/cpuinfo.h>
|
| 27 |
|
| 28 | unsigned long memory_start;
|
| 29 | EXPORT_SYMBOL(memory_start);
|
| 30 |
|
| 31 | unsigned long memory_end;
|
| 32 | EXPORT_SYMBOL(memory_end);
|
| 33 |
|
| 34 | static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
| 35 | 0, 0, 0, 0, 0, 0,
|
| 36 | 0};
|
| 37 |
|
| 38 |
|
| 39 | static inline void copy_exception_handler(unsigned int addr)
|
| 40 | {
|
| 41 | unsigned int start = (unsigned int) exception_handler_hook;
|
| 42 | volatile unsigned int tmp = 0;
|
| 43 |
|
| 44 | if (start == addr) {
|
| 45 |
|
| 46 | return;
|
| 47 | }
|
| 48 |
|
| 49 | __asm__ __volatile__ (
|
| 50 | "ldw %2,0(%0)\n"
|
| 51 | "stw %2,0(%1)\n"
|
| 52 | "ldw %2,4(%0)\n"
|
| 53 | "stw %2,4(%1)\n"
|
| 54 | "ldw %2,8(%0)\n"
|
| 55 | "stw %2,8(%1)\n"
|
| 56 | "flushd 0(%1)\n"
|
| 57 | "flushd 4(%1)\n"
|
| 58 | "flushd 8(%1)\n"
|
| 59 | "flushi %1\n"
|
| 60 | "addi %1,%1,4\n"
|
| 61 | "flushi %1\n"
|
| 62 | "addi %1,%1,4\n"
|
| 63 | "flushi %1\n"
|
| 64 | "flushp\n"
|
| 65 | :
|
| 66 | : "r" (start), "r" (addr), "r" (tmp)
|
| 67 | : "memory"
|
| 68 | );
|
| 69 | }
|
| 70 |
|
| 71 |
|
| 72 | static inline void copy_fast_tlb_miss_handler(unsigned int addr)
|
| 73 | {
|
| 74 | unsigned int start = (unsigned int) fast_handler;
|
| 75 | unsigned int end = (unsigned int) fast_handler_end;
|
| 76 | volatile unsigned int tmp = 0;
|
| 77 |
|
| 78 | __asm__ __volatile__ (
|
| 79 | "1:\n"
|
| 80 | " ldw %3,0(%0)\n"
|
| 81 | " stw %3,0(%1)\n"
|
| 82 | " flushd 0(%1)\n"
|
| 83 | " flushi %1\n"
|
| 84 | " flushp\n"
|
| 85 | " addi %0,%0,4\n"
|
| 86 | " addi %1,%1,4\n"
|
| 87 | " bne %0,%2,1b\n"
|
| 88 | :
|
| 89 | : "r" (start), "r" (addr), "r" (end), "r" (tmp)
|
| 90 | : "memory"
|
| 91 | );
|
| 92 | }
|
| 93 |
|
| 94 | |
| 95 | * save args passed from u-boot, called from head.S
|
| 96 | *
|
| 97 | * @r4: NIOS magic
|
| 98 | * @r5: initrd start
|
| 99 | * @r6: initrd end or fdt
|
| 100 | * @r7: kernel command line
|
| 101 |
|
| 102 | asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6,
|
| 103 | unsigned r7)
|
| 104 | {
|
| 105 | unsigned dtb_passed = 0;
|
| 106 | char cmdline_passed[COMMAND_LINE_SIZE] __maybe_unused = { 0, };
|
| 107 |
|
| 108 | #if defined(CONFIG_NIOS2_PASS_CMDLINE)
|
| 109 | if (r4 == 0x534f494e) {
|
| 110 | #if defined(CONFIG_BLK_DEV_INITRD)
|
| 111 | if (r5) {
|
| 112 | initrd_start = r5;
|
| 113 | initrd_end = r6;
|
| 114 | }
|
| 115 | #endif
|
| 116 | dtb_passed = r6;
|
| 117 |
|
| 118 | if (r7)
|
| 119 | strscpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE);
|
| 120 | }
|
| 121 | #endif
|
| 122 |
|
| 123 | early_init_devtree((void *)dtb_passed);
|
| 124 |
|
| 125 | #ifndef CONFIG_CMDLINE_FORCE
|
| 126 | if (cmdline_passed[0])
|
| 127 | strscpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE);
|
| 128 | #ifdef CONFIG_NIOS2_CMDLINE_IGNORE_DTB
|
| 129 | else
|
| 130 | strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
| 131 | #endif
|
| 132 | #endif
|
| 133 |
|
| 134 | parse_early_param();
|
| 135 | }
|
| 136 |
|
| 137 | static void __init find_limits(unsigned long *min, unsigned long *max_low,
|
| 138 | unsigned long *max_high)
|
| 139 | {
|
| 140 | *max_low = PFN_DOWN(memblock_get_current_limit());
|
| 141 | *min = PFN_UP(memblock_start_of_DRAM());
|
| 142 | *max_high = PFN_DOWN(memblock_end_of_DRAM());
|
| 143 | }
|
| 144 |
|
| 145 | static void __init adjust_lowmem_bounds(void)
|
| 146 | {
|
| 147 | phys_addr_t block_start, block_end;
|
| 148 | u64 i;
|
| 149 | phys_addr_t memblock_limit = 0;
|
| 150 |
|
| 151 | for_each_mem_range(i, &block_start, &block_end) {
|
| 152 | if (block_end > memblock_limit)
|
| 153 | memblock_limit = block_end;
|
| 154 | }
|
| 155 |
|
| 156 | memblock_set_current_limit(memblock_limit);
|
| 157 | }
|
| 158 |
|
| 159 | void __init setup_arch(char **cmdline_p)
|
| 160 | {
|
| 161 | console_verbose();
|
| 162 |
|
| 163 | memory_start = memblock_start_of_DRAM();
|
| 164 | memory_end = memblock_end_of_DRAM();
|
| 165 |
|
| 166 | pr_debug("%s: start=%lx, end=%lx\n", __func__, memory_start, memory_end);
|
| 167 |
|
| 168 | setup_initial_init_mm(_stext, _etext, _edata, _end);
|
| 169 | init_task.thread.kregs = &fake_regs;
|
| 170 |
|
| 171 |
|
| 172 | *cmdline_p = boot_command_line;
|
| 173 |
|
| 174 | adjust_lowmem_bounds();
|
| 175 | find_limits(&min_low_pfn, &max_low_pfn, &max_pfn);
|
| 176 |
|
| 177 | memblock_reserve(__pa_symbol(_stext), _end - _stext);
|
| 178 | #ifdef CONFIG_BLK_DEV_INITRD
|
| 179 | if (initrd_start) {
|
| 180 | memblock_reserve(virt_to_phys((void *)initrd_start),
|
| 181 | initrd_end - initrd_start);
|
| 182 | }
|
| 183 | #endif
|
| 184 |
|
| 185 | early_init_fdt_reserve_self();
|
| 186 | early_init_fdt_scan_reserved_mem();
|
| 187 |
|
| 188 | unflatten_and_copy_device_tree();
|
| 189 |
|
| 190 | setup_cpuinfo();
|
| 191 |
|
| 192 | copy_exception_handler(cpuinfo.exception_addr);
|
| 193 |
|
| 194 | mmu_init();
|
| 195 |
|
| 196 | copy_fast_tlb_miss_handler(cpuinfo.fast_tlb_miss_exc_addr);
|
| 197 |
|
| 198 | |
| 199 | * Initialize MMU context handling here because data from cpuinfo is
|
| 200 | * needed for this.
|
| 201 |
|
| 202 | mmu_context_init();
|
| 203 |
|
| 204 | |
| 205 | * get kmalloc into gear
|
| 206 |
|
| 207 | paging_init();
|
| 208 | }
|