2 * linux/arch/arm26/kernel/setup.c
4 * Copyright (C) 1995-2001 Russell King
5 * Copyright (C) 2003 Ian Molton
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/stddef.h>
14 #include <linux/ioport.h>
15 #include <linux/delay.h>
16 #include <linux/utsname.h>
17 #include <linux/blkdev.h>
18 #include <linux/console.h>
19 #include <linux/bootmem.h>
20 #include <linux/seq_file.h>
21 #include <linux/tty.h>
22 #include <linux/init.h>
23 #include <linux/root_dev.h>
26 #include <asm/hardware.h>
28 #include <asm/procinfo.h>
29 #include <asm/setup.h>
30 #include <asm/mach-types.h>
31 #include <asm/tlbflush.h>
33 #include <asm/irqchip.h>
36 #define MEM_SIZE (16*1024*1024)
40 DEFINE_SPINLOCK(kernel_flag
);
43 #if defined(CONFIG_FPE_NWFPE)
46 static int __init
fpe_setup(char *line
)
48 memcpy(fpe_type
, line
, 8);
52 __setup("fpe=", fpe_setup
);
55 extern void paging_init(struct meminfo
*);
56 extern void convert_to_tag_list(struct tag
*tags
);
57 extern void squash_mem_tags(struct tag
*tag
);
58 extern void bootmem_init(struct meminfo
*);
59 extern int root_mountflags
;
60 extern int _stext
, _text
, _etext
, _edata
, _end
;
61 #ifdef CONFIG_XIP_KERNEL
62 extern int _endtext
, _sdata
;
66 unsigned int processor_id
;
67 unsigned int __machine_arch_type
;
68 unsigned int system_rev
;
69 unsigned int system_serial_low
;
70 unsigned int system_serial_high
;
71 unsigned int elf_hwcap
;
72 unsigned int memc_ctrl_reg
;
73 unsigned int number_mfm_drives
;
75 struct processor processor
;
77 char elf_platform
[ELF_PLATFORM_SIZE
];
79 unsigned long phys_initrd_start __initdata
= 0;
80 unsigned long phys_initrd_size __initdata
= 0;
81 static struct meminfo meminfo __initdata
= { 0, };
82 static struct proc_info_item proc_info
;
83 static const char *machine_name
;
84 static char command_line
[COMMAND_LINE_SIZE
];
86 static char default_command_line
[COMMAND_LINE_SIZE
] __initdata
= CONFIG_CMDLINE
;
89 * Standard memory resources
91 static struct resource mem_res
[] = {
92 { "Video RAM", 0, 0, IORESOURCE_MEM
},
93 { "Kernel code", 0, 0, IORESOURCE_MEM
},
94 { "Kernel data", 0, 0, IORESOURCE_MEM
}
97 #define video_ram mem_res[0]
98 #define kernel_code mem_res[1]
99 #define kernel_data mem_res[2]
101 static struct resource io_res
[] = {
102 { "reserved", 0x3bc, 0x3be, IORESOURCE_IO
| IORESOURCE_BUSY
},
103 { "reserved", 0x378, 0x37f, IORESOURCE_IO
| IORESOURCE_BUSY
},
104 { "reserved", 0x278, 0x27f, IORESOURCE_IO
| IORESOURCE_BUSY
}
107 #define lp0 io_res[0]
108 #define lp1 io_res[1]
109 #define lp2 io_res[2]
111 #define dump_cpu_info() do { } while (0)
113 static void __init
setup_processor(void)
115 extern struct proc_info_list __proc_info_begin
, __proc_info_end
;
116 struct proc_info_list
*list
;
119 * locate processor in the list of supported processor
120 * types. The linker builds this table for us from the
121 * entries in arch/arm26/mm/proc-*.S
123 for (list
= &__proc_info_begin
; list
< &__proc_info_end
; list
++)
124 if ((processor_id
& list
->cpu_mask
) == list
->cpu_val
)
128 * If processor type is unrecognised, then we
131 if (list
>= &__proc_info_end
) {
132 printk("CPU configuration botched (ID %08x), unable "
133 "to continue.\n", processor_id
);
137 proc_info
= *list
->info
;
138 processor
= *list
->proc
;
141 printk("CPU: %s %s revision %d\n",
142 proc_info
.manufacturer
, proc_info
.cpu_name
,
143 (int)processor_id
& 15);
147 sprintf(system_utsname
.machine
, "%s", list
->arch_name
);
148 sprintf(elf_platform
, "%s", list
->elf_name
);
149 elf_hwcap
= list
->elf_hwcap
;
155 * Initial parsing of the command line. We need to pick out the
156 * memory size. We look for mem=size@start, where start and size
160 parse_cmdline(struct meminfo
*mi
, char **cmdline_p
, char *from
)
162 char c
= ' ', *to
= command_line
;
163 int usermem
= 0, len
= 0;
166 if (c
== ' ' && !memcmp(from
, "mem=", 4)) {
167 unsigned long size
, start
;
169 if (to
!= command_line
)
173 * If the user specifies memory size, we
174 * blow away any automatically generated
183 size
= memparse(from
+ 4, &from
);
185 start
= memparse(from
+ 1, &from
);
187 mi
->bank
[mi
->nr_banks
].start
= start
;
188 mi
->bank
[mi
->nr_banks
].size
= size
;
189 mi
->bank
[mi
->nr_banks
].node
= PHYS_TO_NID(start
);
195 if (COMMAND_LINE_SIZE
<= ++len
)
200 *cmdline_p
= command_line
;
204 setup_ramdisk(int doload
, int prompt
, int image_start
, unsigned int rd_sz
)
206 #ifdef CONFIG_BLK_DEV_RAM
207 extern int rd_size
, rd_image_start
, rd_prompt
, rd_doload
;
209 rd_image_start
= image_start
;
219 request_standard_resources(struct meminfo
*mi
)
221 struct resource
*res
;
224 kernel_code
.start
= init_mm
.start_code
;
225 kernel_code
.end
= init_mm
.end_code
- 1;
226 #ifdef CONFIG_XIP_KERNEL
227 kernel_data
.start
= init_mm
.start_data
;
229 kernel_data
.start
= init_mm
.end_code
;
231 kernel_data
.end
= init_mm
.brk
- 1;
233 for (i
= 0; i
< mi
->nr_banks
; i
++) {
234 unsigned long virt_start
, virt_end
;
236 if (mi
->bank
[i
].size
== 0)
239 virt_start
= mi
->bank
[i
].start
;
240 virt_end
= virt_start
+ mi
->bank
[i
].size
- 1;
242 res
= alloc_bootmem_low(sizeof(*res
));
243 res
->name
= "System RAM";
244 res
->start
= virt_start
;
246 res
->flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
248 request_resource(&iomem_resource
, res
);
250 if (kernel_code
.start
>= res
->start
&&
251 kernel_code
.end
<= res
->end
)
252 request_resource(res
, &kernel_code
);
253 if (kernel_data
.start
>= res
->start
&&
254 kernel_data
.end
<= res
->end
)
255 request_resource(res
, &kernel_data
);
258 /* FIXME - needed? if (mdesc->video_start) {
259 video_ram.start = mdesc->video_start;
260 video_ram.end = mdesc->video_end;
261 request_resource(&iomem_resource, &video_ram);
265 * Some machines don't have the possibility of ever
266 * possessing lp1 or lp2
268 if (0) /* FIXME - need to do this for A5k at least */
269 request_resource(&ioport_resource
, &lp0
);
275 * This is the new way of passing data to the kernel at boot time. Rather
276 * than passing a fixed inflexible structure to the kernel, we pass a list
277 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
278 * tag for the list to be recognised (to distinguish the tagged list from
279 * a param_struct). The list is terminated with a zero-length tag (this tag
280 * is not parsed in any way).
282 static int __init
parse_tag_core(const struct tag
*tag
)
284 if (tag
->hdr
.size
> 2) {
285 if ((tag
->u
.core
.flags
& 1) == 0)
286 root_mountflags
&= ~MS_RDONLY
;
287 ROOT_DEV
= old_decode_dev(tag
->u
.core
.rootdev
);
292 __tagtable(ATAG_CORE
, parse_tag_core
);
294 static int __init
parse_tag_mem32(const struct tag
*tag
)
296 if (meminfo
.nr_banks
>= NR_BANKS
) {
298 "Ignoring memory bank 0x%08x size %dKB\n",
299 tag
->u
.mem
.start
, tag
->u
.mem
.size
/ 1024);
302 meminfo
.bank
[meminfo
.nr_banks
].start
= tag
->u
.mem
.start
;
303 meminfo
.bank
[meminfo
.nr_banks
].size
= tag
->u
.mem
.size
;
304 meminfo
.bank
[meminfo
.nr_banks
].node
= PHYS_TO_NID(tag
->u
.mem
.start
);
305 meminfo
.nr_banks
+= 1;
310 __tagtable(ATAG_MEM
, parse_tag_mem32
);
312 #if defined(CONFIG_DUMMY_CONSOLE)
313 struct screen_info screen_info
= {
314 .orig_video_lines
= 30,
315 .orig_video_cols
= 80,
316 .orig_video_mode
= 0,
317 .orig_video_ega_bx
= 0,
318 .orig_video_isVGA
= 1,
319 .orig_video_points
= 8
322 static int __init
parse_tag_videotext(const struct tag
*tag
)
324 screen_info
.orig_x
= tag
->u
.videotext
.x
;
325 screen_info
.orig_y
= tag
->u
.videotext
.y
;
326 screen_info
.orig_video_page
= tag
->u
.videotext
.video_page
;
327 screen_info
.orig_video_mode
= tag
->u
.videotext
.video_mode
;
328 screen_info
.orig_video_cols
= tag
->u
.videotext
.video_cols
;
329 screen_info
.orig_video_ega_bx
= tag
->u
.videotext
.video_ega_bx
;
330 screen_info
.orig_video_lines
= tag
->u
.videotext
.video_lines
;
331 screen_info
.orig_video_isVGA
= tag
->u
.videotext
.video_isvga
;
332 screen_info
.orig_video_points
= tag
->u
.videotext
.video_points
;
336 __tagtable(ATAG_VIDEOTEXT
, parse_tag_videotext
);
339 static int __init
parse_tag_acorn(const struct tag
*tag
)
341 memc_ctrl_reg
= tag
->u
.acorn
.memc_control_reg
;
342 number_mfm_drives
= tag
->u
.acorn
.adfsdrives
;
346 __tagtable(ATAG_ACORN
, parse_tag_acorn
);
348 static int __init
parse_tag_ramdisk(const struct tag
*tag
)
350 setup_ramdisk((tag
->u
.ramdisk
.flags
& 1) == 0,
351 (tag
->u
.ramdisk
.flags
& 2) == 0,
352 tag
->u
.ramdisk
.start
, tag
->u
.ramdisk
.size
);
356 __tagtable(ATAG_RAMDISK
, parse_tag_ramdisk
);
358 static int __init
parse_tag_initrd(const struct tag
*tag
)
360 printk(KERN_WARNING
"ATAG_INITRD is deprecated; please update your bootloader. \n");
361 phys_initrd_start
= (unsigned long)tag
->u
.initrd
.start
;
362 phys_initrd_size
= (unsigned long)tag
->u
.initrd
.size
;
366 __tagtable(ATAG_INITRD
, parse_tag_initrd
);
368 static int __init
parse_tag_initrd2(const struct tag
*tag
)
370 printk(KERN_WARNING
"ATAG_INITRD is deprecated; please update your bootloader. \n");
371 phys_initrd_start
= (unsigned long)tag
->u
.initrd
.start
;
372 phys_initrd_size
= (unsigned long)tag
->u
.initrd
.size
;
376 __tagtable(ATAG_INITRD2
, parse_tag_initrd2
);
378 static int __init
parse_tag_serialnr(const struct tag
*tag
)
380 system_serial_low
= tag
->u
.serialnr
.low
;
381 system_serial_high
= tag
->u
.serialnr
.high
;
385 __tagtable(ATAG_SERIAL
, parse_tag_serialnr
);
387 static int __init
parse_tag_revision(const struct tag
*tag
)
389 system_rev
= tag
->u
.revision
.rev
;
393 __tagtable(ATAG_REVISION
, parse_tag_revision
);
395 static int __init
parse_tag_cmdline(const struct tag
*tag
)
397 strncpy(default_command_line
, tag
->u
.cmdline
.cmdline
, COMMAND_LINE_SIZE
);
398 default_command_line
[COMMAND_LINE_SIZE
- 1] = '\0';
402 __tagtable(ATAG_CMDLINE
, parse_tag_cmdline
);
405 * Scan the tag table for this tag, and call its parse function.
406 * The tag table is built by the linker from all the __tagtable
409 static int __init
parse_tag(const struct tag
*tag
)
411 extern struct tagtable __tagtable_begin
, __tagtable_end
;
414 for (t
= &__tagtable_begin
; t
< &__tagtable_end
; t
++)
415 if (tag
->hdr
.tag
== t
->tag
) {
420 return t
< &__tagtable_end
;
424 * Parse all tags in the list, checking both the global and architecture
425 * specific tag tables.
427 static void __init
parse_tags(const struct tag
*t
)
429 for (; t
->hdr
.size
; t
= tag_next(t
))
432 "Ignoring unrecognised tag 0x%08x\n",
437 * This holds our defaults.
439 static struct init_tags
{
440 struct tag_header hdr1
;
441 struct tag_core core
;
442 struct tag_header hdr2
;
443 struct tag_mem32 mem
;
444 struct tag_header hdr3
;
445 } init_tags __initdata
= {
446 { tag_size(tag_core
), ATAG_CORE
},
447 { 1, PAGE_SIZE
, 0xff },
448 { tag_size(tag_mem32
), ATAG_MEM
},
449 { MEM_SIZE
, PHYS_OFFSET
},
453 void __init
setup_arch(char **cmdline_p
)
455 struct tag
*tags
= (struct tag
*)&init_tags
;
456 char *from
= default_command_line
;
459 if(machine_arch_type
== MACH_TYPE_A5K
)
460 machine_name
= "A5000";
461 else if(machine_arch_type
== MACH_TYPE_ARCHIMEDES
)
462 machine_name
= "Archimedes";
464 machine_name
= "UNKNOWN";
466 //FIXME - the tag struct is always copied here but this is a block
467 // of RAM that is accidentally reserved along with video RAM. perhaps
468 // it would be a good idea to explicitly reserve this?
470 tags
= (struct tag
*)0x0207c000;
473 * If we have the old style parameters, convert them to
476 if (tags
->hdr
.tag
!= ATAG_CORE
)
477 convert_to_tag_list(tags
);
478 if (tags
->hdr
.tag
!= ATAG_CORE
)
479 tags
= (struct tag
*)&init_tags
;
480 if (tags
->hdr
.tag
== ATAG_CORE
) {
481 if (meminfo
.nr_banks
!= 0)
482 squash_mem_tags(tags
);
486 init_mm
.start_code
= (unsigned long) &_text
;
487 #ifndef CONFIG_XIP_KERNEL
488 init_mm
.end_code
= (unsigned long) &_etext
;
490 init_mm
.end_code
= (unsigned long) &_endtext
;
491 init_mm
.start_data
= (unsigned long) &_sdata
;
493 init_mm
.end_data
= (unsigned long) &_edata
;
494 init_mm
.brk
= (unsigned long) &_end
;
496 memcpy(saved_command_line
, from
, COMMAND_LINE_SIZE
);
497 saved_command_line
[COMMAND_LINE_SIZE
-1] = '\0';
498 parse_cmdline(&meminfo
, cmdline_p
, from
);
499 bootmem_init(&meminfo
);
500 paging_init(&meminfo
);
501 request_standard_resources(&meminfo
);
504 #if defined(CONFIG_DUMMY_CONSOLE)
505 conswitchp
= &dummy_con
;
510 static const char *hwcap_str
[] = {
522 static int c_show(struct seq_file
*m
, void *v
)
526 seq_printf(m
, "Processor\t: %s %s rev %d (%s)\n",
527 proc_info
.manufacturer
, proc_info
.cpu_name
,
528 (int)processor_id
& 15, elf_platform
);
530 seq_printf(m
, "BogoMIPS\t: %lu.%02lu\n",
531 loops_per_jiffy
/ (500000/HZ
),
532 (loops_per_jiffy
/ (5000/HZ
)) % 100);
534 /* dump out the processor features */
535 seq_puts(m
, "Features\t: ");
537 for (i
= 0; hwcap_str
[i
]; i
++)
538 if (elf_hwcap
& (1 << i
))
539 seq_printf(m
, "%s ", hwcap_str
[i
]);
543 seq_printf(m
, "CPU part\t\t: %07x\n", processor_id
>> 4);
544 seq_printf(m
, "CPU revision\t: %d\n\n", processor_id
& 15);
545 seq_printf(m
, "Hardware\t: %s\n", machine_name
);
546 seq_printf(m
, "Revision\t: %04x\n", system_rev
);
547 seq_printf(m
, "Serial\t\t: %08x%08x\n",
548 system_serial_high
, system_serial_low
);
553 static void *c_start(struct seq_file
*m
, loff_t
*pos
)
555 return *pos
< 1 ? (void *)1 : NULL
;
558 static void *c_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
564 static void c_stop(struct seq_file
*m
, void *v
)
568 struct seq_operations cpuinfo_op
= {