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