diff options
Diffstat (limited to 'arch/sh/kernel/setup.c')
-rw-r--r-- | arch/sh/kernel/setup.c | 267 |
1 files changed, 104 insertions, 163 deletions
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 98802ab28211..477d2a854fc4 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * This file handles the architecture-dependent parts of initialization | 4 | * This file handles the architecture-dependent parts of initialization |
5 | * | 5 | * |
6 | * Copyright (C) 1999 Niibe Yutaka | 6 | * Copyright (C) 1999 Niibe Yutaka |
7 | * Copyright (C) 2002 - 2006 Paul Mundt | 7 | * Copyright (C) 2002 - 2007 Paul Mundt |
8 | */ | 8 | */ |
9 | #include <linux/screen_info.h> | 9 | #include <linux/screen_info.h> |
10 | #include <linux/ioport.h> | 10 | #include <linux/ioport.h> |
@@ -15,21 +15,22 @@ | |||
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/root_dev.h> | 16 | #include <linux/root_dev.h> |
17 | #include <linux/utsname.h> | 17 | #include <linux/utsname.h> |
18 | #include <linux/nodemask.h> | ||
18 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
19 | #include <linux/pfn.h> | 20 | #include <linux/pfn.h> |
20 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/mm.h> | ||
23 | #include <linux/kexec.h> | ||
21 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
22 | #include <asm/io.h> | 25 | #include <asm/io.h> |
23 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
24 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
25 | #include <asm/setup.h> | 28 | #include <asm/setup.h> |
26 | #include <asm/clock.h> | 29 | #include <asm/clock.h> |
30 | #include <asm/mmu_context.h> | ||
27 | 31 | ||
28 | #ifdef CONFIG_SH_KGDB | ||
29 | #include <asm/kgdb.h> | ||
30 | static int kgdb_parse_options(char *options); | ||
31 | #endif | ||
32 | extern void * __rd_start, * __rd_end; | 32 | extern void * __rd_start, * __rd_end; |
33 | |||
33 | /* | 34 | /* |
34 | * Machine setup.. | 35 | * Machine setup.. |
35 | */ | 36 | */ |
@@ -205,53 +206,33 @@ static int __init sh_mv_setup(char **cmdline_p) | |||
205 | return 0; | 206 | return 0; |
206 | } | 207 | } |
207 | 208 | ||
208 | void __init setup_arch(char **cmdline_p) | 209 | /* |
210 | * Register fully available low RAM pages with the bootmem allocator. | ||
211 | */ | ||
212 | static void __init register_bootmem_low_pages(void) | ||
209 | { | 213 | { |
210 | unsigned long bootmap_size; | 214 | unsigned long curr_pfn, last_pfn, pages; |
211 | unsigned long start_pfn, max_pfn, max_low_pfn; | ||
212 | |||
213 | #ifdef CONFIG_CMDLINE_BOOL | ||
214 | strcpy(COMMAND_LINE, CONFIG_CMDLINE); | ||
215 | #endif | ||
216 | |||
217 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); | ||
218 | |||
219 | #ifdef CONFIG_BLK_DEV_RAM | ||
220 | rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; | ||
221 | rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); | ||
222 | rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); | ||
223 | #endif | ||
224 | |||
225 | if (!MOUNT_ROOT_RDONLY) | ||
226 | root_mountflags &= ~MS_RDONLY; | ||
227 | init_mm.start_code = (unsigned long) _text; | ||
228 | init_mm.end_code = (unsigned long) _etext; | ||
229 | init_mm.end_data = (unsigned long) _edata; | ||
230 | init_mm.brk = (unsigned long) _end; | ||
231 | |||
232 | code_resource.start = (unsigned long)virt_to_phys(_text); | ||
233 | code_resource.end = (unsigned long)virt_to_phys(_etext)-1; | ||
234 | data_resource.start = (unsigned long)virt_to_phys(_etext); | ||
235 | data_resource.end = (unsigned long)virt_to_phys(_edata)-1; | ||
236 | |||
237 | sh_mv_setup(cmdline_p); | ||
238 | |||
239 | 215 | ||
240 | /* | 216 | /* |
241 | * Find the highest page frame number we have available | 217 | * We are rounding up the start address of usable memory: |
242 | */ | 218 | */ |
243 | max_pfn = PFN_DOWN(__pa(memory_end)); | 219 | curr_pfn = PFN_UP(__MEMORY_START); |
244 | 220 | ||
245 | /* | 221 | /* |
246 | * Determine low and high memory ranges: | 222 | * ... and at the end of the usable range downwards: |
247 | */ | 223 | */ |
248 | max_low_pfn = max_pfn; | 224 | last_pfn = PFN_DOWN(__pa(memory_end)); |
249 | 225 | ||
250 | /* | 226 | if (last_pfn > max_low_pfn) |
251 | * Partially used pages are not usable - thus | 227 | last_pfn = max_low_pfn; |
252 | * we are rounding upwards: | 228 | |
253 | */ | 229 | pages = last_pfn - curr_pfn; |
254 | start_pfn = PFN_UP(__pa(_end)); | 230 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); |
231 | } | ||
232 | |||
233 | void __init setup_bootmem_allocator(unsigned long start_pfn) | ||
234 | { | ||
235 | unsigned long bootmap_size; | ||
255 | 236 | ||
256 | /* | 237 | /* |
257 | * Find a proper area for the bootmem bitmap. After this | 238 | * Find a proper area for the bootmem bitmap. After this |
@@ -259,31 +240,11 @@ void __init setup_arch(char **cmdline_p) | |||
259 | * is intact) must be done via bootmem_alloc(). | 240 | * is intact) must be done via bootmem_alloc(). |
260 | */ | 241 | */ |
261 | bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, | 242 | bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, |
262 | __MEMORY_START>>PAGE_SHIFT, | 243 | min_low_pfn, max_low_pfn); |
263 | max_low_pfn); | ||
264 | /* | ||
265 | * Register fully available low RAM pages with the bootmem allocator. | ||
266 | */ | ||
267 | { | ||
268 | unsigned long curr_pfn, last_pfn, pages; | ||
269 | |||
270 | /* | ||
271 | * We are rounding up the start address of usable memory: | ||
272 | */ | ||
273 | curr_pfn = PFN_UP(__MEMORY_START); | ||
274 | /* | ||
275 | * ... and at the end of the usable range downwards: | ||
276 | */ | ||
277 | last_pfn = PFN_DOWN(__pa(memory_end)); | ||
278 | 244 | ||
279 | if (last_pfn > max_low_pfn) | 245 | register_bootmem_low_pages(); |
280 | last_pfn = max_low_pfn; | ||
281 | |||
282 | pages = last_pfn - curr_pfn; | ||
283 | free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), | ||
284 | PFN_PHYS(pages)); | ||
285 | } | ||
286 | 246 | ||
247 | node_set_online(0); | ||
287 | 248 | ||
288 | /* | 249 | /* |
289 | * Reserve the kernel text and | 250 | * Reserve the kernel text and |
@@ -292,14 +253,14 @@ void __init setup_arch(char **cmdline_p) | |||
292 | * case of us accidentally initializing the bootmem allocator with | 253 | * case of us accidentally initializing the bootmem allocator with |
293 | * an invalid RAM area. | 254 | * an invalid RAM area. |
294 | */ | 255 | */ |
295 | reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE, | 256 | reserve_bootmem(__MEMORY_START+PAGE_SIZE, |
296 | (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); | 257 | (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); |
297 | 258 | ||
298 | /* | 259 | /* |
299 | * reserve physical page 0 - it's a special BIOS page on many boxes, | 260 | * reserve physical page 0 - it's a special BIOS page on many boxes, |
300 | * enabling clean reboots, SMP operation, laptop functions. | 261 | * enabling clean reboots, SMP operation, laptop functions. |
301 | */ | 262 | */ |
302 | reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); | 263 | reserve_bootmem(__MEMORY_START, PAGE_SIZE); |
303 | 264 | ||
304 | #ifdef CONFIG_BLK_DEV_INITRD | 265 | #ifdef CONFIG_BLK_DEV_INITRD |
305 | ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); | 266 | ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); |
@@ -313,8 +274,8 @@ void __init setup_arch(char **cmdline_p) | |||
313 | 274 | ||
314 | if (LOADER_TYPE && INITRD_START) { | 275 | if (LOADER_TYPE && INITRD_START) { |
315 | if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { | 276 | if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { |
316 | reserve_bootmem_node(NODE_DATA(0), INITRD_START + | 277 | reserve_bootmem(INITRD_START + __MEMORY_START, |
317 | __MEMORY_START, INITRD_SIZE); | 278 | INITRD_SIZE); |
318 | initrd_start = INITRD_START + PAGE_OFFSET + | 279 | initrd_start = INITRD_START + PAGE_OFFSET + |
319 | __MEMORY_START; | 280 | __MEMORY_START; |
320 | initrd_end = initrd_start + INITRD_SIZE; | 281 | initrd_end = initrd_start + INITRD_SIZE; |
@@ -327,6 +288,76 @@ void __init setup_arch(char **cmdline_p) | |||
327 | } | 288 | } |
328 | } | 289 | } |
329 | #endif | 290 | #endif |
291 | #ifdef CONFIG_KEXEC | ||
292 | if (crashk_res.start != crashk_res.end) | ||
293 | reserve_bootmem(crashk_res.start, | ||
294 | crashk_res.end - crashk_res.start + 1); | ||
295 | #endif | ||
296 | } | ||
297 | |||
298 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
299 | static void __init setup_memory(void) | ||
300 | { | ||
301 | unsigned long start_pfn; | ||
302 | |||
303 | /* | ||
304 | * Partially used pages are not usable - thus | ||
305 | * we are rounding upwards: | ||
306 | */ | ||
307 | start_pfn = PFN_UP(__pa(_end)); | ||
308 | setup_bootmem_allocator(start_pfn); | ||
309 | } | ||
310 | #else | ||
311 | extern void __init setup_memory(void); | ||
312 | #endif | ||
313 | |||
314 | void __init setup_arch(char **cmdline_p) | ||
315 | { | ||
316 | enable_mmu(); | ||
317 | |||
318 | #ifdef CONFIG_CMDLINE_BOOL | ||
319 | strcpy(COMMAND_LINE, CONFIG_CMDLINE); | ||
320 | #endif | ||
321 | |||
322 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); | ||
323 | |||
324 | #ifdef CONFIG_BLK_DEV_RAM | ||
325 | rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; | ||
326 | rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); | ||
327 | rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); | ||
328 | #endif | ||
329 | |||
330 | if (!MOUNT_ROOT_RDONLY) | ||
331 | root_mountflags &= ~MS_RDONLY; | ||
332 | init_mm.start_code = (unsigned long) _text; | ||
333 | init_mm.end_code = (unsigned long) _etext; | ||
334 | init_mm.end_data = (unsigned long) _edata; | ||
335 | init_mm.brk = (unsigned long) _end; | ||
336 | |||
337 | code_resource.start = virt_to_phys(_text); | ||
338 | code_resource.end = virt_to_phys(_etext)-1; | ||
339 | data_resource.start = virt_to_phys(_etext); | ||
340 | data_resource.end = virt_to_phys(_edata)-1; | ||
341 | |||
342 | parse_early_param(); | ||
343 | |||
344 | sh_mv_setup(cmdline_p); | ||
345 | |||
346 | /* | ||
347 | * Find the highest page frame number we have available | ||
348 | */ | ||
349 | max_pfn = PFN_DOWN(__pa(memory_end)); | ||
350 | |||
351 | /* | ||
352 | * Determine low and high memory ranges: | ||
353 | */ | ||
354 | max_low_pfn = max_pfn; | ||
355 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; | ||
356 | |||
357 | nodes_clear(node_online_map); | ||
358 | setup_memory(); | ||
359 | paging_init(); | ||
360 | sparse_init(); | ||
330 | 361 | ||
331 | #ifdef CONFIG_DUMMY_CONSOLE | 362 | #ifdef CONFIG_DUMMY_CONSOLE |
332 | conswitchp = &dummy_con; | 363 | conswitchp = &dummy_con; |
@@ -335,8 +366,6 @@ void __init setup_arch(char **cmdline_p) | |||
335 | /* Perform the machine specific initialisation */ | 366 | /* Perform the machine specific initialisation */ |
336 | if (likely(sh_mv.mv_setup)) | 367 | if (likely(sh_mv.mv_setup)) |
337 | sh_mv.mv_setup(cmdline_p); | 368 | sh_mv.mv_setup(cmdline_p); |
338 | |||
339 | paging_init(); | ||
340 | } | 369 | } |
341 | 370 | ||
342 | struct sh_machine_vector* __init get_mv_byname(const char* name) | 371 | struct sh_machine_vector* __init get_mv_byname(const char* name) |
@@ -380,6 +409,7 @@ static const char *cpu_name[] = { | |||
380 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", | 409 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", |
381 | [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", | 410 | [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", |
382 | [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710", | 411 | [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710", |
412 | [CPU_SH7712] = "SH7712", | ||
383 | [CPU_SH7729] = "SH7729", [CPU_SH7750] = "SH7750", | 413 | [CPU_SH7729] = "SH7729", [CPU_SH7750] = "SH7750", |
384 | [CPU_SH7750S] = "SH7750S", [CPU_SH7750R] = "SH7750R", | 414 | [CPU_SH7750S] = "SH7750S", [CPU_SH7750R] = "SH7750R", |
385 | [CPU_SH7751] = "SH7751", [CPU_SH7751R] = "SH7751R", | 415 | [CPU_SH7751] = "SH7751", [CPU_SH7751R] = "SH7751R", |
@@ -477,7 +507,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
477 | c->loops_per_jiffy/(500000/HZ), | 507 | c->loops_per_jiffy/(500000/HZ), |
478 | (c->loops_per_jiffy/(5000/HZ)) % 100); | 508 | (c->loops_per_jiffy/(5000/HZ)) % 100); |
479 | 509 | ||
480 | return show_clocks(m); | 510 | return 0; |
481 | } | 511 | } |
482 | 512 | ||
483 | static void *c_start(struct seq_file *m, loff_t *pos) | 513 | static void *c_start(struct seq_file *m, loff_t *pos) |
@@ -499,92 +529,3 @@ struct seq_operations cpuinfo_op = { | |||
499 | .show = show_cpuinfo, | 529 | .show = show_cpuinfo, |
500 | }; | 530 | }; |
501 | #endif /* CONFIG_PROC_FS */ | 531 | #endif /* CONFIG_PROC_FS */ |
502 | |||
503 | #ifdef CONFIG_SH_KGDB | ||
504 | /* | ||
505 | * Parse command-line kgdb options. By default KGDB is enabled, | ||
506 | * entered on error (or other action) using default serial info. | ||
507 | * The command-line option can include a serial port specification | ||
508 | * and an action to override default or configured behavior. | ||
509 | */ | ||
510 | struct kgdb_sermap kgdb_sci_sermap = | ||
511 | { "ttySC", 5, kgdb_sci_setup, NULL }; | ||
512 | |||
513 | struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap; | ||
514 | struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap; | ||
515 | |||
516 | void kgdb_register_sermap(struct kgdb_sermap *map) | ||
517 | { | ||
518 | struct kgdb_sermap *last; | ||
519 | |||
520 | for (last = kgdb_serlist; last->next; last = last->next) | ||
521 | ; | ||
522 | last->next = map; | ||
523 | if (!map->namelen) { | ||
524 | map->namelen = strlen(map->name); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | static int __init kgdb_parse_options(char *options) | ||
529 | { | ||
530 | char c; | ||
531 | int baud; | ||
532 | |||
533 | /* Check for port spec (or use default) */ | ||
534 | |||
535 | /* Determine port type and instance */ | ||
536 | if (!memcmp(options, "tty", 3)) { | ||
537 | struct kgdb_sermap *map = kgdb_serlist; | ||
538 | |||
539 | while (map && memcmp(options, map->name, map->namelen)) | ||
540 | map = map->next; | ||
541 | |||
542 | if (!map) { | ||
543 | KGDB_PRINTK("unknown port spec in %s\n", options); | ||
544 | return -1; | ||
545 | } | ||
546 | |||
547 | kgdb_porttype = map; | ||
548 | kgdb_serial_setup = map->setup_fn; | ||
549 | kgdb_portnum = options[map->namelen] - '0'; | ||
550 | options += map->namelen + 1; | ||
551 | |||
552 | options = (*options == ',') ? options+1 : options; | ||
553 | |||
554 | /* Read optional parameters (baud/parity/bits) */ | ||
555 | baud = simple_strtoul(options, &options, 10); | ||
556 | if (baud != 0) { | ||
557 | kgdb_baud = baud; | ||
558 | |||
559 | c = toupper(*options); | ||
560 | if (c == 'E' || c == 'O' || c == 'N') { | ||
561 | kgdb_parity = c; | ||
562 | options++; | ||
563 | } | ||
564 | |||
565 | c = *options; | ||
566 | if (c == '7' || c == '8') { | ||
567 | kgdb_bits = c; | ||
568 | options++; | ||
569 | } | ||
570 | options = (*options == ',') ? options+1 : options; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | /* Check for action specification */ | ||
575 | if (!memcmp(options, "halt", 4)) { | ||
576 | kgdb_halt = 1; | ||
577 | options += 4; | ||
578 | } else if (!memcmp(options, "disabled", 8)) { | ||
579 | kgdb_enabled = 0; | ||
580 | options += 8; | ||
581 | } | ||
582 | |||
583 | if (*options) { | ||
584 | KGDB_PRINTK("ignored unknown options: %s\n", options); | ||
585 | return 0; | ||
586 | } | ||
587 | return 1; | ||
588 | } | ||
589 | __setup("kgdb=", kgdb_parse_options); | ||
590 | #endif /* CONFIG_SH_KGDB */ | ||