diff options
Diffstat (limited to 'arch/mips/kernel/setup.c')
-rw-r--r-- | arch/mips/kernel/setup.c | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c new file mode 100644 index 000000000000..6018ca25aceb --- /dev/null +++ b/arch/mips/kernel/setup.c | |||
@@ -0,0 +1,571 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 1995 Linus Torvalds | ||
7 | * Copyright (C) 1995 Waldorf Electronics | ||
8 | * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle | ||
9 | * Copyright (C) 1996 Stoned Elipot | ||
10 | * Copyright (C) 1999 Silicon Graphics, Inc. | ||
11 | * Copyright (C) 2000 2001, 2002 Maciej W. Rozycki | ||
12 | */ | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/unistd.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/user.h> | ||
26 | #include <linux/utsname.h> | ||
27 | #include <linux/a.out.h> | ||
28 | #include <linux/tty.h> | ||
29 | #include <linux/bootmem.h> | ||
30 | #include <linux/initrd.h> | ||
31 | #include <linux/major.h> | ||
32 | #include <linux/kdev_t.h> | ||
33 | #include <linux/root_dev.h> | ||
34 | #include <linux/highmem.h> | ||
35 | #include <linux/console.h> | ||
36 | |||
37 | #include <asm/addrspace.h> | ||
38 | #include <asm/bootinfo.h> | ||
39 | #include <asm/cpu.h> | ||
40 | #include <asm/sections.h> | ||
41 | #include <asm/setup.h> | ||
42 | #include <asm/system.h> | ||
43 | |||
44 | struct cpuinfo_mips cpu_data[NR_CPUS]; | ||
45 | |||
46 | EXPORT_SYMBOL(cpu_data); | ||
47 | |||
48 | #ifdef CONFIG_VT | ||
49 | struct screen_info screen_info; | ||
50 | #endif | ||
51 | |||
52 | /* | ||
53 | * Despite it's name this variable is even if we don't have PCI | ||
54 | */ | ||
55 | unsigned int PCI_DMA_BUS_IS_PHYS; | ||
56 | |||
57 | EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); | ||
58 | |||
59 | /* | ||
60 | * Setup information | ||
61 | * | ||
62 | * These are initialized so they are in the .data section | ||
63 | */ | ||
64 | unsigned long mips_machtype = MACH_UNKNOWN; | ||
65 | unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; | ||
66 | |||
67 | EXPORT_SYMBOL(mips_machtype); | ||
68 | EXPORT_SYMBOL(mips_machgroup); | ||
69 | |||
70 | struct boot_mem_map boot_mem_map; | ||
71 | |||
72 | static char command_line[CL_SIZE]; | ||
73 | char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE; | ||
74 | |||
75 | /* | ||
76 | * mips_io_port_base is the begin of the address space to which x86 style | ||
77 | * I/O ports are mapped. | ||
78 | */ | ||
79 | const unsigned long mips_io_port_base = -1; | ||
80 | EXPORT_SYMBOL(mips_io_port_base); | ||
81 | |||
82 | /* | ||
83 | * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped | ||
84 | * for the processor. | ||
85 | */ | ||
86 | unsigned long isa_slot_offset; | ||
87 | EXPORT_SYMBOL(isa_slot_offset); | ||
88 | |||
89 | static struct resource code_resource = { .name = "Kernel code", }; | ||
90 | static struct resource data_resource = { .name = "Kernel data", }; | ||
91 | |||
92 | void __init add_memory_region(phys_t start, phys_t size, long type) | ||
93 | { | ||
94 | int x = boot_mem_map.nr_map; | ||
95 | struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; | ||
96 | |||
97 | /* | ||
98 | * Try to merge with previous entry if any. This is far less than | ||
99 | * perfect but is sufficient for most real world cases. | ||
100 | */ | ||
101 | if (x && prev->addr + prev->size == start && prev->type == type) { | ||
102 | prev->size += size; | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | if (x == BOOT_MEM_MAP_MAX) { | ||
107 | printk("Ooops! Too many entries in the memory map!\n"); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | boot_mem_map.map[x].addr = start; | ||
112 | boot_mem_map.map[x].size = size; | ||
113 | boot_mem_map.map[x].type = type; | ||
114 | boot_mem_map.nr_map++; | ||
115 | } | ||
116 | |||
117 | static void __init print_memory_map(void) | ||
118 | { | ||
119 | int i; | ||
120 | const int field = 2 * sizeof(unsigned long); | ||
121 | |||
122 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
123 | printk(" memory: %0*Lx @ %0*Lx ", | ||
124 | field, (unsigned long long) boot_mem_map.map[i].size, | ||
125 | field, (unsigned long long) boot_mem_map.map[i].addr); | ||
126 | |||
127 | switch (boot_mem_map.map[i].type) { | ||
128 | case BOOT_MEM_RAM: | ||
129 | printk("(usable)\n"); | ||
130 | break; | ||
131 | case BOOT_MEM_ROM_DATA: | ||
132 | printk("(ROM data)\n"); | ||
133 | break; | ||
134 | case BOOT_MEM_RESERVED: | ||
135 | printk("(reserved)\n"); | ||
136 | break; | ||
137 | default: | ||
138 | printk("type %lu\n", boot_mem_map.map[i].type); | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | static inline void parse_cmdline_early(void) | ||
145 | { | ||
146 | char c = ' ', *to = command_line, *from = saved_command_line; | ||
147 | unsigned long start_at, mem_size; | ||
148 | int len = 0; | ||
149 | int usermem = 0; | ||
150 | |||
151 | printk("Determined physical RAM map:\n"); | ||
152 | print_memory_map(); | ||
153 | |||
154 | for (;;) { | ||
155 | /* | ||
156 | * "mem=XXX[kKmM]" defines a memory region from | ||
157 | * 0 to <XXX>, overriding the determined size. | ||
158 | * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from | ||
159 | * <YYY> to <YYY>+<XXX>, overriding the determined size. | ||
160 | */ | ||
161 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
162 | if (to != command_line) | ||
163 | to--; | ||
164 | /* | ||
165 | * If a user specifies memory size, we | ||
166 | * blow away any automatically generated | ||
167 | * size. | ||
168 | */ | ||
169 | if (usermem == 0) { | ||
170 | boot_mem_map.nr_map = 0; | ||
171 | usermem = 1; | ||
172 | } | ||
173 | mem_size = memparse(from + 4, &from); | ||
174 | if (*from == '@') | ||
175 | start_at = memparse(from + 1, &from); | ||
176 | else | ||
177 | start_at = 0; | ||
178 | add_memory_region(start_at, mem_size, BOOT_MEM_RAM); | ||
179 | } | ||
180 | c = *(from++); | ||
181 | if (!c) | ||
182 | break; | ||
183 | if (CL_SIZE <= ++len) | ||
184 | break; | ||
185 | *(to++) = c; | ||
186 | } | ||
187 | *to = '\0'; | ||
188 | |||
189 | if (usermem) { | ||
190 | printk("User-defined physical RAM map:\n"); | ||
191 | print_memory_map(); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end) | ||
196 | { | ||
197 | /* | ||
198 | * "rd_start=0xNNNNNNNN" defines the memory address of an initrd | ||
199 | * "rd_size=0xNN" it's size | ||
200 | */ | ||
201 | unsigned long start = 0; | ||
202 | unsigned long size = 0; | ||
203 | unsigned long end; | ||
204 | char cmd_line[CL_SIZE]; | ||
205 | char *start_str; | ||
206 | char *size_str; | ||
207 | char *tmp; | ||
208 | |||
209 | strcpy(cmd_line, command_line); | ||
210 | *command_line = 0; | ||
211 | tmp = cmd_line; | ||
212 | /* Ignore "rd_start=" strings in other parameters. */ | ||
213 | start_str = strstr(cmd_line, "rd_start="); | ||
214 | if (start_str && start_str != cmd_line && *(start_str - 1) != ' ') | ||
215 | start_str = strstr(start_str, " rd_start="); | ||
216 | while (start_str) { | ||
217 | if (start_str != cmd_line) | ||
218 | strncat(command_line, tmp, start_str - tmp); | ||
219 | start = memparse(start_str + 9, &start_str); | ||
220 | tmp = start_str + 1; | ||
221 | start_str = strstr(start_str, " rd_start="); | ||
222 | } | ||
223 | if (*tmp) | ||
224 | strcat(command_line, tmp); | ||
225 | |||
226 | strcpy(cmd_line, command_line); | ||
227 | *command_line = 0; | ||
228 | tmp = cmd_line; | ||
229 | /* Ignore "rd_size" strings in other parameters. */ | ||
230 | size_str = strstr(cmd_line, "rd_size="); | ||
231 | if (size_str && size_str != cmd_line && *(size_str - 1) != ' ') | ||
232 | size_str = strstr(size_str, " rd_size="); | ||
233 | while (size_str) { | ||
234 | if (size_str != cmd_line) | ||
235 | strncat(command_line, tmp, size_str - tmp); | ||
236 | size = memparse(size_str + 8, &size_str); | ||
237 | tmp = size_str + 1; | ||
238 | size_str = strstr(size_str, " rd_size="); | ||
239 | } | ||
240 | if (*tmp) | ||
241 | strcat(command_line, tmp); | ||
242 | |||
243 | #ifdef CONFIG_MIPS64 | ||
244 | /* HACK: Guess if the sign extension was forgotten */ | ||
245 | if (start > 0x0000000080000000 && start < 0x00000000ffffffff) | ||
246 | start |= 0xffffffff00000000; | ||
247 | #endif | ||
248 | |||
249 | end = start + size; | ||
250 | if (start && end) { | ||
251 | *rd_start = start; | ||
252 | *rd_end = end; | ||
253 | return 1; | ||
254 | } | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) | ||
259 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
260 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
261 | |||
262 | #define MAXMEM HIGHMEM_START | ||
263 | #define MAXMEM_PFN PFN_DOWN(MAXMEM) | ||
264 | |||
265 | static inline void bootmem_init(void) | ||
266 | { | ||
267 | unsigned long start_pfn; | ||
268 | unsigned long reserved_end = (unsigned long)&_end; | ||
269 | #ifndef CONFIG_SGI_IP27 | ||
270 | unsigned long first_usable_pfn; | ||
271 | unsigned long bootmap_size; | ||
272 | int i; | ||
273 | #endif | ||
274 | #ifdef CONFIG_BLK_DEV_INITRD | ||
275 | int initrd_reserve_bootmem = 0; | ||
276 | |||
277 | /* Board specific code should have set up initrd_start and initrd_end */ | ||
278 | ROOT_DEV = Root_RAM0; | ||
279 | if (parse_rd_cmdline(&initrd_start, &initrd_end)) { | ||
280 | reserved_end = max(reserved_end, initrd_end); | ||
281 | initrd_reserve_bootmem = 1; | ||
282 | } else { | ||
283 | unsigned long tmp; | ||
284 | u32 *initrd_header; | ||
285 | |||
286 | tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2; | ||
287 | if (tmp < reserved_end) | ||
288 | tmp += PAGE_SIZE; | ||
289 | initrd_header = (u32 *)tmp; | ||
290 | if (initrd_header[0] == 0x494E5244) { | ||
291 | initrd_start = (unsigned long)&initrd_header[2]; | ||
292 | initrd_end = initrd_start + initrd_header[1]; | ||
293 | reserved_end = max(reserved_end, initrd_end); | ||
294 | initrd_reserve_bootmem = 1; | ||
295 | } | ||
296 | } | ||
297 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
298 | |||
299 | /* | ||
300 | * Partially used pages are not usable - thus | ||
301 | * we are rounding upwards. | ||
302 | */ | ||
303 | start_pfn = PFN_UP(CPHYSADDR(reserved_end)); | ||
304 | |||
305 | #ifndef CONFIG_SGI_IP27 | ||
306 | /* Find the highest page frame number we have available. */ | ||
307 | max_pfn = 0; | ||
308 | first_usable_pfn = -1UL; | ||
309 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
310 | unsigned long start, end; | ||
311 | |||
312 | if (boot_mem_map.map[i].type != BOOT_MEM_RAM) | ||
313 | continue; | ||
314 | |||
315 | start = PFN_UP(boot_mem_map.map[i].addr); | ||
316 | end = PFN_DOWN(boot_mem_map.map[i].addr | ||
317 | + boot_mem_map.map[i].size); | ||
318 | |||
319 | if (start >= end) | ||
320 | continue; | ||
321 | if (end > max_pfn) | ||
322 | max_pfn = end; | ||
323 | if (start < first_usable_pfn) { | ||
324 | if (start > start_pfn) { | ||
325 | first_usable_pfn = start; | ||
326 | } else if (end > start_pfn) { | ||
327 | first_usable_pfn = start_pfn; | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * Determine low and high memory ranges | ||
334 | */ | ||
335 | max_low_pfn = max_pfn; | ||
336 | if (max_low_pfn > MAXMEM_PFN) { | ||
337 | max_low_pfn = MAXMEM_PFN; | ||
338 | #ifndef CONFIG_HIGHMEM | ||
339 | /* Maximum memory usable is what is directly addressable */ | ||
340 | printk(KERN_WARNING "Warning only %ldMB will be used.\n", | ||
341 | MAXMEM >> 20); | ||
342 | printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); | ||
343 | #endif | ||
344 | } | ||
345 | |||
346 | #ifdef CONFIG_HIGHMEM | ||
347 | /* | ||
348 | * Crude, we really should make a better attempt at detecting | ||
349 | * highstart_pfn | ||
350 | */ | ||
351 | highstart_pfn = highend_pfn = max_pfn; | ||
352 | if (max_pfn > MAXMEM_PFN) { | ||
353 | highstart_pfn = MAXMEM_PFN; | ||
354 | printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", | ||
355 | (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT)); | ||
356 | } | ||
357 | #endif | ||
358 | |||
359 | /* Initialize the boot-time allocator with low memory only. */ | ||
360 | bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn); | ||
361 | |||
362 | /* | ||
363 | * Register fully available low RAM pages with the bootmem allocator. | ||
364 | */ | ||
365 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
366 | unsigned long curr_pfn, last_pfn, size; | ||
367 | |||
368 | /* | ||
369 | * Reserve usable memory. | ||
370 | */ | ||
371 | if (boot_mem_map.map[i].type != BOOT_MEM_RAM) | ||
372 | continue; | ||
373 | |||
374 | /* | ||
375 | * We are rounding up the start address of usable memory: | ||
376 | */ | ||
377 | curr_pfn = PFN_UP(boot_mem_map.map[i].addr); | ||
378 | if (curr_pfn >= max_low_pfn) | ||
379 | continue; | ||
380 | if (curr_pfn < start_pfn) | ||
381 | curr_pfn = start_pfn; | ||
382 | |||
383 | /* | ||
384 | * ... and at the end of the usable range downwards: | ||
385 | */ | ||
386 | last_pfn = PFN_DOWN(boot_mem_map.map[i].addr | ||
387 | + boot_mem_map.map[i].size); | ||
388 | |||
389 | if (last_pfn > max_low_pfn) | ||
390 | last_pfn = max_low_pfn; | ||
391 | |||
392 | /* | ||
393 | * Only register lowmem part of lowmem segment with bootmem. | ||
394 | */ | ||
395 | size = last_pfn - curr_pfn; | ||
396 | if (curr_pfn > PFN_DOWN(HIGHMEM_START)) | ||
397 | continue; | ||
398 | if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START)) | ||
399 | size = PFN_DOWN(HIGHMEM_START) - curr_pfn; | ||
400 | if (!size) | ||
401 | continue; | ||
402 | |||
403 | /* | ||
404 | * ... finally, did all the rounding and playing | ||
405 | * around just make the area go away? | ||
406 | */ | ||
407 | if (last_pfn <= curr_pfn) | ||
408 | continue; | ||
409 | |||
410 | /* Register lowmem ranges */ | ||
411 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); | ||
412 | } | ||
413 | |||
414 | /* Reserve the bootmap memory. */ | ||
415 | reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size); | ||
416 | #endif /* CONFIG_SGI_IP27 */ | ||
417 | |||
418 | #ifdef CONFIG_BLK_DEV_INITRD | ||
419 | initrd_below_start_ok = 1; | ||
420 | if (initrd_start) { | ||
421 | unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); | ||
422 | printk("Initial ramdisk at: 0x%p (%lu bytes)\n", | ||
423 | (void *)initrd_start, initrd_size); | ||
424 | |||
425 | if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { | ||
426 | printk("initrd extends beyond end of memory " | ||
427 | "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n", | ||
428 | sizeof(long) * 2, | ||
429 | (unsigned long long)CPHYSADDR(initrd_end), | ||
430 | sizeof(long) * 2, | ||
431 | (unsigned long long)PFN_PHYS(max_low_pfn)); | ||
432 | initrd_start = initrd_end = 0; | ||
433 | initrd_reserve_bootmem = 0; | ||
434 | } | ||
435 | |||
436 | if (initrd_reserve_bootmem) | ||
437 | reserve_bootmem(CPHYSADDR(initrd_start), initrd_size); | ||
438 | } | ||
439 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
440 | } | ||
441 | |||
442 | static inline void resource_init(void) | ||
443 | { | ||
444 | int i; | ||
445 | |||
446 | #if defined(CONFIG_MIPS64) && !defined(CONFIG_BUILD_ELF64) | ||
447 | /* | ||
448 | * The 64bit code in 32bit object format trick can't represent | ||
449 | * 64bit wide relocations for linker script symbols. | ||
450 | */ | ||
451 | code_resource.start = CPHYSADDR(&_text); | ||
452 | code_resource.end = CPHYSADDR(&_etext) - 1; | ||
453 | data_resource.start = CPHYSADDR(&_etext); | ||
454 | data_resource.end = CPHYSADDR(&_edata) - 1; | ||
455 | #else | ||
456 | code_resource.start = virt_to_phys(&_text); | ||
457 | code_resource.end = virt_to_phys(&_etext) - 1; | ||
458 | data_resource.start = virt_to_phys(&_etext); | ||
459 | data_resource.end = virt_to_phys(&_edata) - 1; | ||
460 | #endif | ||
461 | |||
462 | /* | ||
463 | * Request address space for all standard RAM. | ||
464 | */ | ||
465 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
466 | struct resource *res; | ||
467 | unsigned long start, end; | ||
468 | |||
469 | start = boot_mem_map.map[i].addr; | ||
470 | end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; | ||
471 | if (start >= MAXMEM) | ||
472 | continue; | ||
473 | if (end >= MAXMEM) | ||
474 | end = MAXMEM - 1; | ||
475 | |||
476 | res = alloc_bootmem(sizeof(struct resource)); | ||
477 | switch (boot_mem_map.map[i].type) { | ||
478 | case BOOT_MEM_RAM: | ||
479 | case BOOT_MEM_ROM_DATA: | ||
480 | res->name = "System RAM"; | ||
481 | break; | ||
482 | case BOOT_MEM_RESERVED: | ||
483 | default: | ||
484 | res->name = "reserved"; | ||
485 | } | ||
486 | |||
487 | res->start = start; | ||
488 | res->end = end; | ||
489 | |||
490 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
491 | request_resource(&iomem_resource, res); | ||
492 | |||
493 | /* | ||
494 | * We don't know which RAM region contains kernel data, | ||
495 | * so we try it repeatedly and let the resource manager | ||
496 | * test it. | ||
497 | */ | ||
498 | request_resource(res, &code_resource); | ||
499 | request_resource(res, &data_resource); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | #undef PFN_UP | ||
504 | #undef PFN_DOWN | ||
505 | #undef PFN_PHYS | ||
506 | |||
507 | #undef MAXMEM | ||
508 | #undef MAXMEM_PFN | ||
509 | |||
510 | static int __initdata earlyinit_debug; | ||
511 | |||
512 | static int __init earlyinit_debug_setup(char *str) | ||
513 | { | ||
514 | earlyinit_debug = 1; | ||
515 | return 1; | ||
516 | } | ||
517 | __setup("earlyinit_debug", earlyinit_debug_setup); | ||
518 | |||
519 | extern initcall_t __earlyinitcall_start, __earlyinitcall_end; | ||
520 | |||
521 | static void __init do_earlyinitcalls(void) | ||
522 | { | ||
523 | initcall_t *call, *start, *end; | ||
524 | |||
525 | start = &__earlyinitcall_start; | ||
526 | end = &__earlyinitcall_end; | ||
527 | |||
528 | for (call = start; call < end; call++) { | ||
529 | if (earlyinit_debug) | ||
530 | printk("calling earlyinitcall 0x%p\n", *call); | ||
531 | |||
532 | (*call)(); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | void __init setup_arch(char **cmdline_p) | ||
537 | { | ||
538 | cpu_probe(); | ||
539 | prom_init(); | ||
540 | cpu_report(); | ||
541 | |||
542 | #if defined(CONFIG_VT) | ||
543 | #if defined(CONFIG_VGA_CONSOLE) | ||
544 | conswitchp = &vga_con; | ||
545 | #elif defined(CONFIG_DUMMY_CONSOLE) | ||
546 | conswitchp = &dummy_con; | ||
547 | #endif | ||
548 | #endif | ||
549 | |||
550 | /* call board setup routine */ | ||
551 | do_earlyinitcalls(); | ||
552 | |||
553 | strlcpy(command_line, arcs_cmdline, sizeof(command_line)); | ||
554 | strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | ||
555 | |||
556 | *cmdline_p = command_line; | ||
557 | |||
558 | parse_cmdline_early(); | ||
559 | bootmem_init(); | ||
560 | paging_init(); | ||
561 | resource_init(); | ||
562 | } | ||
563 | |||
564 | int __init fpu_disable(char *s) | ||
565 | { | ||
566 | cpu_data[0].options &= ~MIPS_CPU_FPU; | ||
567 | |||
568 | return 1; | ||
569 | } | ||
570 | |||
571 | __setup("nofpu", fpu_disable); | ||