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/kernel.h>
12 #include <linux/stddef.h>
13 #include <linux/ioport.h>
14 #include <linux/delay.h>
15 #include <linux/utsname.h>
16 #include <linux/blkdev.h>
17 #include <linux/console.h>
18 #include <linux/bootmem.h>
19 #include <linux/seq_file.h>
20 #include <linux/screen_info.h>
21 #include <linux/init.h>
22 #include <linux/root_dev.h>
25 #include <asm/hardware.h>
27 #include <asm/procinfo.h>
28 #include <asm/setup.h>
29 #include <asm/mach-types.h>
30 #include <asm/tlbflush.h>
32 #include <asm/irqchip.h>
35 #define MEM_SIZE (16*1024*1024)
39 DEFINE_SPINLOCK(kernel_flag
);
42 #if defined(CONFIG_FPE_NWFPE)
45 static int __init
fpe_setup(char *line
)
47 memcpy(fpe_type
, line
, 8);
51 __setup("fpe=", fpe_setup
);
54 extern void paging_init(struct meminfo
*);
55 extern void convert_to_tag_list(struct tag
*tags
);
56 extern void squash_mem_tags(struct tag
*tag
);
57 extern void bootmem_init(struct meminfo
*);
58 extern int root_mountflags
;
59 extern int _stext
, _text
, _etext
, _edata
, _end
;
60 #ifdef CONFIG_XIP_KERNEL
61 extern int _endtext
, _sdata
;
65 unsigned int processor_id
;
66 unsigned int __machine_arch_type
;
67 unsigned int system_rev
;
68 unsigned int system_serial_low
;
69 unsigned int system_serial_high
;
70 unsigned int elf_hwcap
;
71 unsigned int memc_ctrl_reg
;
72 unsigned int number_mfm_drives
;
74 struct processor processor
;
76 char elf_platform
[ELF_PLATFORM_SIZE
];
78 unsigned long phys_initrd_start __initdata
= 0;
79 unsigned long phys_initrd_size __initdata
= 0;
80 static struct meminfo meminfo __initdata
= { 0, };
81 static struct proc_info_item proc_info
;
82 static const char *machine_name
;
83 static char __initdata command_line
[COMMAND_LINE_SIZE
];
85 static char default_command_line
[COMMAND_LINE_SIZE
] __initdata
= CONFIG_CMDLINE
;
88 * Standard memory resources
90 static struct resource mem_res
[] = {
91 { "Video RAM", 0, 0, IORESOURCE_MEM
},
92 { "Kernel code", 0, 0, IORESOURCE_MEM
},
93 { "Kernel data", 0, 0, IORESOURCE_MEM
}
96 #define video_ram mem_res[0]
97 #define kernel_code mem_res[1]
98 #define kernel_data mem_res[2]
100 static struct resource io_res
[] = {
101 { "reserved", 0x3bc, 0x3be, IORESOURCE_IO
| IORESOURCE_BUSY
},
102 { "reserved", 0x378, 0x37f, IORESOURCE_IO
| IORESOURCE_BUSY
},
103 { "reserved", 0x278, 0x27f, IORESOURCE_IO
| IORESOURCE_BUSY
}
106 #define lp0 io_res[0]
107 #define lp1 io_res[1]
108 #define lp2 io_res[2]
110 #define dump_cpu_info() do { } while (0)
112 static void __init
setup_processor(void)
114 extern struct proc_info_list __proc_info_begin
, __proc_info_end
;
115 struct proc_info_list
*list
;
118 * locate processor in the list of supported processor
119 * types. The linker builds this table for us from the
120 * entries in arch/arm26/mm/proc-*.S
122 for (list
= &__proc_info_begin
; list
< &__proc_info_end
; list
++)
123 if ((processor_id
& list
->cpu_mask
) == list
->cpu_val
)
127 * If processor type is unrecognised, then we
130 if (list
>= &__proc_info_end
) {
131 printk("CPU configuration botched (ID %08x), unable "
132 "to continue.\n", processor_id
);
136 proc_info
= *list
->info
;
137 processor
= *list
->proc
;
140 printk("CPU: %s %s revision %d\n",
141 proc_info
.manufacturer
, proc_info
.cpu_name
,
142 (int)processor_id
& 15);
146 sprintf(init_utsname()->machine
, "%s", list
->arch_name
);
147 sprintf(elf_platform
, "%s", list
->elf_name
);
148 elf_hwcap
= list
->elf_hwcap
;
154 * Initial parsing of the command line. We need to pick out the
155 * memory size. We look for mem=size@start, where start and size
159 parse_cmdline(struct meminfo
*mi
, char **cmdline_p
, char *from
)
161 char c
= ' ', *to
= command_line
;
162 int usermem
= 0, len
= 0;
165 if (c
== ' ' && !memcmp(from
, "mem=", 4)) {
166 unsigned long size
, start
;
168 if (to
!= command_line
)
172 * If the user specifies memory size, we
173 * blow away any automatically generated
182 size
= memparse(from
+ 4, &from
);
184 start
= memparse(from
+ 1, &from
);
186 mi
->bank
[mi
->nr_banks
].start
= start
;
187 mi
->bank
[mi
->nr_banks
].size
= size
;
188 mi
->bank
[mi
->nr_banks
].node
= PHYS_TO_NID(start
);
194 if (COMMAND_LINE_SIZE
<= ++len
)
199 *cmdline_p
= command_line
;
203 setup_ramdisk(int doload
, int prompt
, int image_start
, unsigned int rd_sz
)
205 #ifdef CONFIG_BLK_DEV_RAM
206 extern int rd_size
, rd_image_start
, rd_prompt
, rd_doload
;
208 rd_image_start
= image_start
;
218 request_standard_resources(struct meminfo
*mi
)
220 struct resource
*res
;
223 kernel_code
.start
= init_mm
.start_code
;
224 kernel_code
.end
= init_mm
.end_code
- 1;
225 #ifdef CONFIG_XIP_KERNEL
226 kernel_data
.start
= init_mm
.start_data
;
228 kernel_data
.start
= init_mm
.end_code
;
230 kernel_data
.end
= init_mm
.brk
- 1;
232 for (i
= 0; i
< mi
->nr_banks
; i
++) {
233 unsigned long virt_start
, virt_end
;
235 if (mi
->bank
[i
].size
== 0)
238 virt_start
= mi
->bank
[i
].start
;
239 virt_end
= virt_start
+ mi
->bank
[i
].size
- 1;
241 res
= alloc_bootmem_low(sizeof(*res
));
242 res
->name
= "System RAM";
243 res
->start
= virt_start
;
245 res
->flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
247 request_resource(&iomem_resource
, res
);
249 if (kernel_code
.start
>= res
->start
&&
250 kernel_code
.end
<= res
->end
)
251 request_resource(res
, &kernel_code
);
252 if (kernel_data
.start
>= res
->start
&&
253 kernel_data
.end
<= res
->end
)
254 request_resource(res
, &kernel_data
);
257 /* FIXME - needed? if (mdesc->video_start) {
258 video_ram.start = mdesc->video_start;
259 video_ram.end = mdesc->video_end;
260 request_resource(&iomem_resource, &video_ram);
264 * Some machines don't have the possibility of ever
265 * possessing lp1 or lp2
267 if (0) /* FIXME - need to do this for A5k at least */
268 request_resource(&ioport_resource
, &lp0
);
274 * This is the new way of passing data to the kernel at boot time. Rather
275 * than passing a fixed inflexible structure to the kernel, we pass a list
276 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
277 * tag for the list to be recognised (to distinguish the tagged list from
278 * a param_struct). The list is terminated with a zero-length tag (this tag
279 * is not parsed in any way).
281 static int __init
parse_tag_core(const struct tag
*tag
)
283 if (tag
->hdr
.size
> 2) {
284 if ((tag
->u
.core
.flags
& 1) == 0)
285 root_mountflags
&= ~MS_RDONLY
;
286 ROOT_DEV
= old_decode_dev(tag
->u
.core
.rootdev
);
291 __tagtable(ATAG_CORE
, parse_tag_core
);
293 static int __init
parse_tag_mem32(const struct tag
*tag
)
295 if (meminfo
.nr_banks
>= NR_BANKS
) {
297 "Ignoring memory bank 0x%08x size %dKB\n",
298 tag
->u
.mem
.start
, tag
->u
.mem
.size
/ 1024);
301 meminfo
.bank
[meminfo
.nr_banks
].start
= tag
->u
.mem
.start
;
302 meminfo
.bank
[meminfo
.nr_banks
].size
= tag
->u
.mem
.size
;
303 meminfo
.bank
[meminfo
.nr_banks
].node
= PHYS_TO_NID(tag
->u
.mem
.start
);
304 meminfo
.nr_banks
+= 1;
309 __tagtable(ATAG_MEM
, parse_tag_mem32
);
311 #if defined(CONFIG_DUMMY_CONSOLE)
312 struct screen_info screen_info
= {
313 .orig_video_lines
= 30,
314 .orig_video_cols
= 80,
315 .orig_video_mode
= 0,
316 .orig_video_ega_bx
= 0,
317 .orig_video_isVGA
= 1,
318 .orig_video_points
= 8
321 static int __init
parse_tag_videotext(const struct tag
*tag
)
323 screen_info
.orig_x
= tag
->u
.videotext
.x
;
324 screen_info
.orig_y
= tag
->u
.videotext
.y
;
325 screen_info
.orig_video_page
= tag
->u
.videotext
.video_page
;
326 screen_info
.orig_video_mode
= tag
->u
.videotext
.video_mode
;
327 screen_info
.orig_video_cols
= tag
->u
.videotext
.video_cols
;
328 screen_info
.orig_video_ega_bx
= tag
->u
.videotext
.video_ega_bx
;
329 screen_info
.orig_video_lines
= tag
->u
.videotext
.video_lines
;
330 screen_info
.orig_video_isVGA
= tag
->u
.videotext
.video_isvga
;
331 screen_info
.orig_video_points
= tag
->u
.videotext
.video_points
;
335 __tagtable(ATAG_VIDEOTEXT
, parse_tag_videotext
);
338 static int __init
parse_tag_acorn(const struct tag
*tag
)
340 memc_ctrl_reg
= tag
->u
.acorn
.memc_control_reg
;
341 number_mfm_drives
= tag
->u
.acorn
.adfsdrives
;
345 __tagtable(ATAG_ACORN
, parse_tag_acorn
);
347 static int __init
parse_tag_ramdisk(const struct tag
*tag
)
349 setup_ramdisk((tag
->u
.ramdisk
.flags
& 1) == 0,
350 (tag
->u
.ramdisk
.flags
& 2) == 0,
351 tag
->u
.ramdisk
.start
, tag
->u
.ramdisk
.size
);
355 __tagtable(ATAG_RAMDISK
, parse_tag_ramdisk
);
357 static int __init
parse_tag_initrd(const struct tag
*tag
)
359 printk(KERN_WARNING
"ATAG_INITRD is deprecated; please update your bootloader. \n");
360 phys_initrd_start
= (unsigned long)tag
->u
.initrd
.start
;
361 phys_initrd_size
= (unsigned long)tag
->u
.initrd
.size
;
365 __tagtable(ATAG_INITRD
, parse_tag_initrd
);
367 static int __init
parse_tag_initrd2(const struct tag
*tag
)
369 printk(KERN_WARNING
"ATAG_INITRD is deprecated; please update your bootloader. \n");
370 phys_initrd_start
= (unsigned long)tag
->u
.initrd
.start
;
371 phys_initrd_size
= (unsigned long)tag
->u
.initrd
.size
;
375 __tagtable(ATAG_INITRD2
, parse_tag_initrd2
);
377 static int __init
parse_tag_serialnr(const struct tag
*tag
)
379 system_serial_low
= tag
->u
.serialnr
.low
;
380 system_serial_high
= tag
->u
.serialnr
.high
;
384 __tagtable(ATAG_SERIAL
, parse_tag_serialnr
);
386 static int __init
parse_tag_revision(const struct tag
*tag
)
388 system_rev
= tag
->u
.revision
.rev
;
392 __tagtable(ATAG_REVISION
, parse_tag_revision
);
394 static int __init
parse_tag_cmdline(const struct tag
*tag
)
396 strncpy(default_command_line
, tag
->u
.cmdline
.cmdline
, COMMAND_LINE_SIZE
);
397 default_command_line
[COMMAND_LINE_SIZE
- 1] = '\0';
401 __tagtable(ATAG_CMDLINE
, parse_tag_cmdline
);
404 * Scan the tag table for this tag, and call its parse function.
405 * The tag table is built by the linker from all the __tagtable
408 static int __init
parse_tag(const struct tag
*tag
)
410 extern struct tagtable __tagtable_begin
, __tagtable_end
;
413 for (t
= &__tagtable_begin
; t
< &__tagtable_end
; t
++)
414 if (tag
->hdr
.tag
== t
->tag
) {
419 return t
< &__tagtable_end
;
423 * Parse all tags in the list, checking both the global and architecture
424 * specific tag tables.
426 static void __init
parse_tags(const struct tag
*t
)
428 for (; t
->hdr
.size
; t
= tag_next(t
))
431 "Ignoring unrecognised tag 0x%08x\n",
436 * This holds our defaults.
438 static struct init_tags
{
439 struct tag_header hdr1
;
440 struct tag_core core
;
441 struct tag_header hdr2
;
442 struct tag_mem32 mem
;
443 struct tag_header hdr3
;
444 } init_tags __initdata
= {
445 { tag_size(tag_core
), ATAG_CORE
},
446 { 1, PAGE_SIZE
, 0xff },
447 { tag_size(tag_mem32
), ATAG_MEM
},
448 { MEM_SIZE
, PHYS_OFFSET
},
452 void __init
setup_arch(char **cmdline_p
)
454 struct tag
*tags
= (struct tag
*)&init_tags
;
455 char *from
= default_command_line
;
458 if(machine_arch_type
== MACH_TYPE_A5K
)
459 machine_name
= "A5000";
460 else if(machine_arch_type
== MACH_TYPE_ARCHIMEDES
)
461 machine_name
= "Archimedes";
463 machine_name
= "UNKNOWN";
465 //FIXME - the tag struct is always copied here but this is a block
466 // of RAM that is accidentally reserved along with video RAM. perhaps
467 // it would be a good idea to explicitly reserve this?
469 tags
= (struct tag
*)0x0207c000;
472 * If we have the old style parameters, convert them to
475 if (tags
->hdr
.tag
!= ATAG_CORE
)
476 convert_to_tag_list(tags
);
477 if (tags
->hdr
.tag
!= ATAG_CORE
)
478 tags
= (struct tag
*)&init_tags
;
479 if (tags
->hdr
.tag
== ATAG_CORE
) {
480 if (meminfo
.nr_banks
!= 0)
481 squash_mem_tags(tags
);
485 init_mm
.start_code
= (unsigned long) &_text
;
486 #ifndef CONFIG_XIP_KERNEL
487 init_mm
.end_code
= (unsigned long) &_etext
;
489 init_mm
.end_code
= (unsigned long) &_endtext
;
490 init_mm
.start_data
= (unsigned long) &_sdata
;
492 init_mm
.end_data
= (unsigned long) &_edata
;
493 init_mm
.brk
= (unsigned long) &_end
;
495 memcpy(boot_command_line
, from
, COMMAND_LINE_SIZE
);
496 boot_command_line
[COMMAND_LINE_SIZE
-1] = '\0';
497 parse_cmdline(&meminfo
, cmdline_p
, from
);
498 bootmem_init(&meminfo
);
499 paging_init(&meminfo
);
500 request_standard_resources(&meminfo
);
503 #if defined(CONFIG_DUMMY_CONSOLE)
504 conswitchp
= &dummy_con
;
509 static const char *hwcap_str
[] = {
521 static int c_show(struct seq_file
*m
, void *v
)
525 seq_printf(m
, "Processor\t: %s %s rev %d (%s)\n",
526 proc_info
.manufacturer
, proc_info
.cpu_name
,
527 (int)processor_id
& 15, elf_platform
);
529 seq_printf(m
, "BogoMIPS\t: %lu.%02lu\n",
530 loops_per_jiffy
/ (500000/HZ
),
531 (loops_per_jiffy
/ (5000/HZ
)) % 100);
533 /* dump out the processor features */
534 seq_puts(m
, "Features\t: ");
536 for (i
= 0; hwcap_str
[i
]; i
++)
537 if (elf_hwcap
& (1 << i
))
538 seq_printf(m
, "%s ", hwcap_str
[i
]);
542 seq_printf(m
, "CPU part\t\t: %07x\n", processor_id
>> 4);
543 seq_printf(m
, "CPU revision\t: %d\n\n", processor_id
& 15);
544 seq_printf(m
, "Hardware\t: %s\n", machine_name
);
545 seq_printf(m
, "Revision\t: %04x\n", system_rev
);
546 seq_printf(m
, "Serial\t\t: %08x%08x\n",
547 system_serial_high
, system_serial_low
);
552 static void *c_start(struct seq_file
*m
, loff_t
*pos
)
554 return *pos
< 1 ? (void *)1 : NULL
;
557 static void *c_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
563 static void c_stop(struct seq_file
*m
, void *v
)
567 struct seq_operations cpuinfo_op
= {