]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/arm/kernel/setup.c
ARM: 5880/1: arm: use generic infrastructure for early params
[net-next-2.6.git] / arch / arm / kernel / setup.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/arm/kernel/setup.c
3 *
4 * Copyright (C) 1995-2001 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
1da177e4
LT
10#include <linux/module.h>
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/initrd.h>
17#include <linux/console.h>
18#include <linux/bootmem.h>
19#include <linux/seq_file.h>
894673ee 20#include <linux/screen_info.h>
1da177e4
LT
21#include <linux/init.h>
22#include <linux/root_dev.h>
23#include <linux/cpu.h>
24#include <linux/interrupt.h>
7bbb7940 25#include <linux/smp.h>
4e950f6f 26#include <linux/fs.h>
e119bfff 27#include <linux/proc_fs.h>
1da177e4 28
b86040a5 29#include <asm/unified.h>
1da177e4 30#include <asm/cpu.h>
0ba8b9b2 31#include <asm/cputype.h>
1da177e4 32#include <asm/elf.h>
1da177e4 33#include <asm/procinfo.h>
37efe642 34#include <asm/sections.h>
1da177e4
LT
35#include <asm/setup.h>
36#include <asm/mach-types.h>
37#include <asm/cacheflush.h>
46097c7d 38#include <asm/cachetype.h>
1da177e4
LT
39#include <asm/tlbflush.h>
40
41#include <asm/mach/arch.h>
42#include <asm/mach/irq.h>
43#include <asm/mach/time.h>
5cbad0eb 44#include <asm/traps.h>
bff595c1 45#include <asm/unwind.h>
1da177e4 46
0fc1c832 47#include "compat.h"
4cd9d6f7 48#include "atags.h"
bc581770 49#include "tcm.h"
0fc1c832 50
1da177e4
LT
51#ifndef MEM_SIZE
52#define MEM_SIZE (16*1024*1024)
53#endif
54
55#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
56char fpe_type[8];
57
58static int __init fpe_setup(char *line)
59{
60 memcpy(fpe_type, line, 8);
61 return 1;
62}
63
64__setup("fpe=", fpe_setup);
65#endif
66
4b5f32ce 67extern void paging_init(struct machine_desc *desc);
1da177e4 68extern void reboot_setup(char *str);
1da177e4
LT
69
70unsigned int processor_id;
c18f6581 71EXPORT_SYMBOL(processor_id);
1da177e4
LT
72unsigned int __machine_arch_type;
73EXPORT_SYMBOL(__machine_arch_type);
c0e95878
RK
74unsigned int cacheid;
75EXPORT_SYMBOL(cacheid);
1da177e4 76
9d20fdd5
BG
77unsigned int __atags_pointer __initdata;
78
1da177e4
LT
79unsigned int system_rev;
80EXPORT_SYMBOL(system_rev);
81
82unsigned int system_serial_low;
83EXPORT_SYMBOL(system_serial_low);
84
85unsigned int system_serial_high;
86EXPORT_SYMBOL(system_serial_high);
87
88unsigned int elf_hwcap;
89EXPORT_SYMBOL(elf_hwcap);
90
91
92#ifdef MULTI_CPU
93struct processor processor;
94#endif
95#ifdef MULTI_TLB
96struct cpu_tlb_fns cpu_tlb;
97#endif
98#ifdef MULTI_USER
99struct cpu_user_fns cpu_user;
100#endif
101#ifdef MULTI_CACHE
102struct cpu_cache_fns cpu_cache;
103#endif
953233dc
CM
104#ifdef CONFIG_OUTER_CACHE
105struct outer_cache_fns outer_cache;
106#endif
1da177e4 107
ccea7a19
RK
108struct stack {
109 u32 irq[3];
110 u32 abt[3];
111 u32 und[3];
112} ____cacheline_aligned;
113
114static struct stack stacks[NR_CPUS];
115
1da177e4
LT
116char elf_platform[ELF_PLATFORM_SIZE];
117EXPORT_SYMBOL(elf_platform);
118
1da177e4
LT
119static const char *cpu_name;
120static const char *machine_name;
cd81899a 121static char __initdata command_line[COMMAND_LINE_SIZE];
1da177e4
LT
122
123static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
124static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
125#define ENDIANNESS ((char)endian_test.l)
126
127DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
128
129/*
130 * Standard memory resources
131 */
132static struct resource mem_res[] = {
740e518e
GKH
133 {
134 .name = "Video RAM",
135 .start = 0,
136 .end = 0,
137 .flags = IORESOURCE_MEM
138 },
139 {
140 .name = "Kernel text",
141 .start = 0,
142 .end = 0,
143 .flags = IORESOURCE_MEM
144 },
145 {
146 .name = "Kernel data",
147 .start = 0,
148 .end = 0,
149 .flags = IORESOURCE_MEM
150 }
1da177e4
LT
151};
152
153#define video_ram mem_res[0]
154#define kernel_code mem_res[1]
155#define kernel_data mem_res[2]
156
157static struct resource io_res[] = {
740e518e
GKH
158 {
159 .name = "reserved",
160 .start = 0x3bc,
161 .end = 0x3be,
162 .flags = IORESOURCE_IO | IORESOURCE_BUSY
163 },
164 {
165 .name = "reserved",
166 .start = 0x378,
167 .end = 0x37f,
168 .flags = IORESOURCE_IO | IORESOURCE_BUSY
169 },
170 {
171 .name = "reserved",
172 .start = 0x278,
173 .end = 0x27f,
174 .flags = IORESOURCE_IO | IORESOURCE_BUSY
175 }
1da177e4
LT
176};
177
178#define lp0 io_res[0]
179#define lp1 io_res[1]
180#define lp2 io_res[2]
181
1da177e4
LT
182static const char *proc_arch[] = {
183 "undefined/unknown",
184 "3",
185 "4",
186 "4T",
187 "5",
188 "5T",
189 "5TE",
190 "5TEJ",
191 "6TEJ",
6b090a25 192 "7",
1da177e4
LT
193 "?(11)",
194 "?(12)",
195 "?(13)",
196 "?(14)",
197 "?(15)",
198 "?(16)",
199 "?(17)",
200};
201
1da177e4
LT
202int cpu_architecture(void)
203{
204 int cpu_arch;
205
0ba8b9b2 206 if ((read_cpuid_id() & 0x0008f000) == 0) {
1da177e4 207 cpu_arch = CPU_ARCH_UNKNOWN;
0ba8b9b2
RK
208 } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
209 cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
210 } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
211 cpu_arch = (read_cpuid_id() >> 16) & 7;
1da177e4
LT
212 if (cpu_arch)
213 cpu_arch += CPU_ARCH_ARMv3;
0ba8b9b2 214 } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
180005c4
CM
215 unsigned int mmfr0;
216
217 /* Revised CPUID format. Read the Memory Model Feature
218 * Register 0 and check for VMSAv7 or PMSAv7 */
219 asm("mrc p15, 0, %0, c0, c1, 4"
220 : "=r" (mmfr0));
221 if ((mmfr0 & 0x0000000f) == 0x00000003 ||
222 (mmfr0 & 0x000000f0) == 0x00000030)
223 cpu_arch = CPU_ARCH_ARMv7;
224 else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
225 (mmfr0 & 0x000000f0) == 0x00000020)
226 cpu_arch = CPU_ARCH_ARMv6;
227 else
228 cpu_arch = CPU_ARCH_UNKNOWN;
229 } else
230 cpu_arch = CPU_ARCH_UNKNOWN;
1da177e4
LT
231
232 return cpu_arch;
233}
234
c0e95878
RK
235static void __init cacheid_init(void)
236{
237 unsigned int cachetype = read_cpuid_cachetype();
238 unsigned int arch = cpu_architecture();
239
b57ee99f
CM
240 if (arch >= CPU_ARCH_ARMv6) {
241 if ((cachetype & (7 << 29)) == 4 << 29) {
242 /* ARMv7 register format */
243 cacheid = CACHEID_VIPT_NONALIASING;
244 if ((cachetype & (3 << 14)) == 1 << 14)
245 cacheid |= CACHEID_ASID_TAGGED;
246 } else if (cachetype & (1 << 23))
c0e95878
RK
247 cacheid = CACHEID_VIPT_ALIASING;
248 else
249 cacheid = CACHEID_VIPT_NONALIASING;
250 } else {
251 cacheid = CACHEID_VIVT;
252 }
2b4ae1f1
RK
253
254 printk("CPU: %s data cache, %s instruction cache\n",
255 cache_is_vivt() ? "VIVT" :
256 cache_is_vipt_aliasing() ? "VIPT aliasing" :
257 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
258 cache_is_vivt() ? "VIVT" :
259 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
260 cache_is_vipt_aliasing() ? "VIPT aliasing" :
261 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
c0e95878
RK
262}
263
1da177e4
LT
264/*
265 * These functions re-use the assembly code in head.S, which
266 * already provide the required functionality.
267 */
0f44ba1d 268extern struct proc_info_list *lookup_processor_type(unsigned int);
1da177e4
LT
269extern struct machine_desc *lookup_machine_type(unsigned int);
270
271static void __init setup_processor(void)
272{
273 struct proc_info_list *list;
274
275 /*
276 * locate processor in the list of supported processor
277 * types. The linker builds this table for us from the
278 * entries in arch/arm/mm/proc-*.S
279 */
0ba8b9b2 280 list = lookup_processor_type(read_cpuid_id());
1da177e4
LT
281 if (!list) {
282 printk("CPU configuration botched (ID %08x), unable "
0ba8b9b2 283 "to continue.\n", read_cpuid_id());
1da177e4
LT
284 while (1);
285 }
286
287 cpu_name = list->cpu_name;
288
289#ifdef MULTI_CPU
290 processor = *list->proc;
291#endif
292#ifdef MULTI_TLB
293 cpu_tlb = *list->tlb;
294#endif
295#ifdef MULTI_USER
296 cpu_user = *list->user;
297#endif
298#ifdef MULTI_CACHE
299 cpu_cache = *list->cache;
300#endif
301
4e19025b 302 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
0ba8b9b2 303 cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
264edb35 304 proc_arch[cpu_architecture()], cr_alignment);
1da177e4 305
96b644bd 306 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
1da177e4
LT
307 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
308 elf_hwcap = list->elf_hwcap;
adeff422
CM
309#ifndef CONFIG_ARM_THUMB
310 elf_hwcap &= ~HWCAP_THUMB;
311#endif
1da177e4 312
c0e95878 313 cacheid_init();
1da177e4
LT
314 cpu_proc_init();
315}
316
ccea7a19
RK
317/*
318 * cpu_init - initialise one CPU.
319 *
90f1e084 320 * cpu_init sets up the per-CPU stacks.
ccea7a19 321 */
36c5ed23 322void cpu_init(void)
ccea7a19
RK
323{
324 unsigned int cpu = smp_processor_id();
325 struct stack *stk = &stacks[cpu];
326
327 if (cpu >= NR_CPUS) {
328 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
329 BUG();
330 }
331
b86040a5
CM
332 /*
333 * Define the placement constraint for the inline asm directive below.
334 * In Thumb-2, msr with an immediate value is not allowed.
335 */
336#ifdef CONFIG_THUMB2_KERNEL
337#define PLC "r"
338#else
339#define PLC "I"
340#endif
341
ccea7a19
RK
342 /*
343 * setup stacks for re-entrant exception handlers
344 */
345 __asm__ (
346 "msr cpsr_c, %1\n\t"
b86040a5
CM
347 "add r14, %0, %2\n\t"
348 "mov sp, r14\n\t"
ccea7a19 349 "msr cpsr_c, %3\n\t"
b86040a5
CM
350 "add r14, %0, %4\n\t"
351 "mov sp, r14\n\t"
ccea7a19 352 "msr cpsr_c, %5\n\t"
b86040a5
CM
353 "add r14, %0, %6\n\t"
354 "mov sp, r14\n\t"
ccea7a19
RK
355 "msr cpsr_c, %7"
356 :
357 : "r" (stk),
b86040a5 358 PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
ccea7a19 359 "I" (offsetof(struct stack, irq[0])),
b86040a5 360 PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
ccea7a19 361 "I" (offsetof(struct stack, abt[0])),
b86040a5 362 PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
ccea7a19 363 "I" (offsetof(struct stack, und[0])),
b86040a5 364 PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
aaaa3f9e 365 : "r14");
ccea7a19
RK
366}
367
1da177e4
LT
368static struct machine_desc * __init setup_machine(unsigned int nr)
369{
370 struct machine_desc *list;
371
372 /*
373 * locate machine in the list of supported machines.
374 */
375 list = lookup_machine_type(nr);
376 if (!list) {
377 printk("Machine configuration botched (nr %d), unable "
378 "to continue.\n", nr);
379 while (1);
380 }
381
382 printk("Machine: %s\n", list->name);
383
384 return list;
385}
386
4b5f32ce 387static int __init arm_add_memory(unsigned long start, unsigned long size)
3a669411 388{
4b5f32ce
NP
389 struct membank *bank = &meminfo.bank[meminfo.nr_banks];
390
391 if (meminfo.nr_banks >= NR_BANKS) {
392 printk(KERN_CRIT "NR_BANKS too low, "
393 "ignoring memory at %#lx\n", start);
394 return -EINVAL;
395 }
05f96ef1 396
3a669411
RK
397 /*
398 * Ensure that start/size are aligned to a page boundary.
399 * Size is appropriately rounded down, start is rounded up.
400 */
401 size -= start & ~PAGE_MASK;
05f96ef1
RK
402 bank->start = PAGE_ALIGN(start);
403 bank->size = size & PAGE_MASK;
404 bank->node = PHYS_TO_NID(start);
4b5f32ce
NP
405
406 /*
407 * Check whether this memory region has non-zero size or
408 * invalid node number.
409 */
410 if (bank->size == 0 || bank->node >= MAX_NUMNODES)
411 return -EINVAL;
412
413 meminfo.nr_banks++;
414 return 0;
3a669411
RK
415}
416
1da177e4
LT
417/*
418 * Pick out the memory size. We look for mem=size@start,
419 * where start and size are "size[KkMm]"
420 */
2b0d8c25 421static int __init early_mem(char *p)
1da177e4
LT
422{
423 static int usermem __initdata = 0;
424 unsigned long size, start;
2b0d8c25 425 char *endp;
1da177e4
LT
426
427 /*
428 * If the user specifies memory size, we
429 * blow away any automatically generated
430 * size.
431 */
432 if (usermem == 0) {
433 usermem = 1;
434 meminfo.nr_banks = 0;
435 }
436
437 start = PHYS_OFFSET;
2b0d8c25
JK
438 size = memparse(p, &endp);
439 if (*endp == '@')
440 start = memparse(endp + 1, NULL);
1da177e4 441
1c97b73e 442 arm_add_memory(start, size);
1da177e4 443
2b0d8c25 444 return 0;
1da177e4 445}
2b0d8c25 446early_param("mem", early_mem);
1da177e4
LT
447
448static void __init
449setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
450{
451#ifdef CONFIG_BLK_DEV_RAM
452 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
453
454 rd_image_start = image_start;
455 rd_prompt = prompt;
456 rd_doload = doload;
457
458 if (rd_sz)
459 rd_size = rd_sz;
460#endif
461}
462
463static void __init
464request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
465{
466 struct resource *res;
467 int i;
468
37efe642
RK
469 kernel_code.start = virt_to_phys(_text);
470 kernel_code.end = virt_to_phys(_etext - 1);
471 kernel_data.start = virt_to_phys(_data);
472 kernel_data.end = virt_to_phys(_end - 1);
1da177e4
LT
473
474 for (i = 0; i < mi->nr_banks; i++) {
1da177e4
LT
475 if (mi->bank[i].size == 0)
476 continue;
477
1da177e4
LT
478 res = alloc_bootmem_low(sizeof(*res));
479 res->name = "System RAM";
3319f5e5
NP
480 res->start = mi->bank[i].start;
481 res->end = mi->bank[i].start + mi->bank[i].size - 1;
1da177e4
LT
482 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
483
484 request_resource(&iomem_resource, res);
485
486 if (kernel_code.start >= res->start &&
487 kernel_code.end <= res->end)
488 request_resource(res, &kernel_code);
489 if (kernel_data.start >= res->start &&
490 kernel_data.end <= res->end)
491 request_resource(res, &kernel_data);
492 }
493
494 if (mdesc->video_start) {
495 video_ram.start = mdesc->video_start;
496 video_ram.end = mdesc->video_end;
497 request_resource(&iomem_resource, &video_ram);
498 }
499
500 /*
501 * Some machines don't have the possibility of ever
502 * possessing lp0, lp1 or lp2
503 */
504 if (mdesc->reserve_lp0)
505 request_resource(&ioport_resource, &lp0);
506 if (mdesc->reserve_lp1)
507 request_resource(&ioport_resource, &lp1);
508 if (mdesc->reserve_lp2)
509 request_resource(&ioport_resource, &lp2);
510}
511
512/*
513 * Tag parsing.
514 *
515 * This is the new way of passing data to the kernel at boot time. Rather
516 * than passing a fixed inflexible structure to the kernel, we pass a list
517 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
518 * tag for the list to be recognised (to distinguish the tagged list from
519 * a param_struct). The list is terminated with a zero-length tag (this tag
520 * is not parsed in any way).
521 */
522static int __init parse_tag_core(const struct tag *tag)
523{
524 if (tag->hdr.size > 2) {
525 if ((tag->u.core.flags & 1) == 0)
526 root_mountflags &= ~MS_RDONLY;
527 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
528 }
529 return 0;
530}
531
532__tagtable(ATAG_CORE, parse_tag_core);
533
534static int __init parse_tag_mem32(const struct tag *tag)
535{
4b5f32ce 536 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
1da177e4
LT
537}
538
539__tagtable(ATAG_MEM, parse_tag_mem32);
540
541#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
542struct screen_info screen_info = {
543 .orig_video_lines = 30,
544 .orig_video_cols = 80,
545 .orig_video_mode = 0,
546 .orig_video_ega_bx = 0,
547 .orig_video_isVGA = 1,
548 .orig_video_points = 8
549};
550
551static int __init parse_tag_videotext(const struct tag *tag)
552{
553 screen_info.orig_x = tag->u.videotext.x;
554 screen_info.orig_y = tag->u.videotext.y;
555 screen_info.orig_video_page = tag->u.videotext.video_page;
556 screen_info.orig_video_mode = tag->u.videotext.video_mode;
557 screen_info.orig_video_cols = tag->u.videotext.video_cols;
558 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
559 screen_info.orig_video_lines = tag->u.videotext.video_lines;
560 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
561 screen_info.orig_video_points = tag->u.videotext.video_points;
562 return 0;
563}
564
565__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
566#endif
567
568static int __init parse_tag_ramdisk(const struct tag *tag)
569{
570 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
571 (tag->u.ramdisk.flags & 2) == 0,
572 tag->u.ramdisk.start, tag->u.ramdisk.size);
573 return 0;
574}
575
576__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
577
1da177e4
LT
578static int __init parse_tag_serialnr(const struct tag *tag)
579{
580 system_serial_low = tag->u.serialnr.low;
581 system_serial_high = tag->u.serialnr.high;
582 return 0;
583}
584
585__tagtable(ATAG_SERIAL, parse_tag_serialnr);
586
587static int __init parse_tag_revision(const struct tag *tag)
588{
589 system_rev = tag->u.revision.rev;
590 return 0;
591}
592
593__tagtable(ATAG_REVISION, parse_tag_revision);
594
595static int __init parse_tag_cmdline(const struct tag *tag)
596{
597 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
598 return 0;
599}
600
601__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
602
603/*
604 * Scan the tag table for this tag, and call its parse function.
605 * The tag table is built by the linker from all the __tagtable
606 * declarations.
607 */
608static int __init parse_tag(const struct tag *tag)
609{
610 extern struct tagtable __tagtable_begin, __tagtable_end;
611 struct tagtable *t;
612
613 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
614 if (tag->hdr.tag == t->tag) {
615 t->parse(tag);
616 break;
617 }
618
619 return t < &__tagtable_end;
620}
621
622/*
623 * Parse all tags in the list, checking both the global and architecture
624 * specific tag tables.
625 */
626static void __init parse_tags(const struct tag *t)
627{
628 for (; t->hdr.size; t = tag_next(t))
629 if (!parse_tag(t))
630 printk(KERN_WARNING
631 "Ignoring unrecognised tag 0x%08x\n",
632 t->hdr.tag);
633}
634
635/*
636 * This holds our defaults.
637 */
638static struct init_tags {
639 struct tag_header hdr1;
640 struct tag_core core;
641 struct tag_header hdr2;
642 struct tag_mem32 mem;
643 struct tag_header hdr3;
644} init_tags __initdata = {
645 { tag_size(tag_core), ATAG_CORE },
646 { 1, PAGE_SIZE, 0xff },
647 { tag_size(tag_mem32), ATAG_MEM },
648 { MEM_SIZE, PHYS_OFFSET },
649 { 0, ATAG_NONE }
650};
651
652static void (*init_machine)(void) __initdata;
653
654static int __init customize_machine(void)
655{
656 /* customizes platform devices, or adds new ones */
657 if (init_machine)
658 init_machine();
659 return 0;
660}
661arch_initcall(customize_machine);
662
663void __init setup_arch(char **cmdline_p)
664{
665 struct tag *tags = (struct tag *)&init_tags;
666 struct machine_desc *mdesc;
667 char *from = default_command_line;
668
bff595c1
CM
669 unwind_init();
670
1da177e4
LT
671 setup_processor();
672 mdesc = setup_machine(machine_arch_type);
673 machine_name = mdesc->name;
674
675 if (mdesc->soft_reboot)
676 reboot_setup("s");
677
9d20fdd5
BG
678 if (__atags_pointer)
679 tags = phys_to_virt(__atags_pointer);
680 else if (mdesc->boot_params)
f9bd6ea4 681 tags = phys_to_virt(mdesc->boot_params);
1da177e4
LT
682
683 /*
684 * If we have the old style parameters, convert them to
685 * a tag list.
686 */
687 if (tags->hdr.tag != ATAG_CORE)
688 convert_to_tag_list(tags);
689 if (tags->hdr.tag != ATAG_CORE)
690 tags = (struct tag *)&init_tags;
691
692 if (mdesc->fixup)
693 mdesc->fixup(mdesc, tags, &from, &meminfo);
694
695 if (tags->hdr.tag == ATAG_CORE) {
696 if (meminfo.nr_banks != 0)
697 squash_mem_tags(tags);
4cd9d6f7 698 save_atags(tags);
1da177e4
LT
699 parse_tags(tags);
700 }
701
37efe642
RK
702 init_mm.start_code = (unsigned long) _text;
703 init_mm.end_code = (unsigned long) _etext;
704 init_mm.end_data = (unsigned long) _edata;
705 init_mm.brk = (unsigned long) _end;
1da177e4 706
2b0d8c25
JK
707 /* parse_early_param needs a boot_command_line */
708 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
709
710 /* populate command_line too for later use, preserving boot_command_line */
711 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
712 *cmdline_p = command_line;
713
714 parse_early_param();
715
4b5f32ce 716 paging_init(mdesc);
1da177e4
LT
717 request_standard_resources(&meminfo, mdesc);
718
7bbb7940
RK
719#ifdef CONFIG_SMP
720 smp_init_cpus();
721#endif
722
ccea7a19 723 cpu_init();
bc581770 724 tcm_init();
ccea7a19 725
1da177e4
LT
726 /*
727 * Set up various architecture-specific pointers
728 */
729 init_arch_irq = mdesc->init_irq;
730 system_timer = mdesc->timer;
731 init_machine = mdesc->init_machine;
732
733#ifdef CONFIG_VT
734#if defined(CONFIG_VGA_CONSOLE)
735 conswitchp = &vga_con;
736#elif defined(CONFIG_DUMMY_CONSOLE)
737 conswitchp = &dummy_con;
738#endif
739#endif
5cbad0eb 740 early_trap_init();
1da177e4
LT
741}
742
743
744static int __init topology_init(void)
745{
746 int cpu;
747
66fb8bd2
RK
748 for_each_possible_cpu(cpu) {
749 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
750 cpuinfo->cpu.hotpluggable = 1;
751 register_cpu(&cpuinfo->cpu, cpu);
752 }
1da177e4
LT
753
754 return 0;
755}
1da177e4
LT
756subsys_initcall(topology_init);
757
e119bfff
RK
758#ifdef CONFIG_HAVE_PROC_CPU
759static int __init proc_cpu_init(void)
760{
761 struct proc_dir_entry *res;
762
763 res = proc_mkdir("cpu", NULL);
764 if (!res)
765 return -ENOMEM;
766 return 0;
767}
768fs_initcall(proc_cpu_init);
769#endif
770
1da177e4
LT
771static const char *hwcap_str[] = {
772 "swp",
773 "half",
774 "thumb",
775 "26bit",
776 "fastmult",
777 "fpa",
778 "vfp",
779 "edsp",
780 "java",
8f7f9435 781 "iwmmxt",
99e4a6dd 782 "crunch",
4369ae16 783 "thumbee",
2bedbdf4 784 "neon",
7279dc3e
CM
785 "vfpv3",
786 "vfpv3d16",
1da177e4
LT
787 NULL
788};
789
1da177e4
LT
790static int c_show(struct seq_file *m, void *v)
791{
792 int i;
793
794 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
0ba8b9b2 795 cpu_name, read_cpuid_id() & 15, elf_platform);
1da177e4
LT
796
797#if defined(CONFIG_SMP)
798 for_each_online_cpu(i) {
15559722
RK
799 /*
800 * glibc reads /proc/cpuinfo to determine the number of
801 * online processors, looking for lines beginning with
802 * "processor". Give glibc what it expects.
803 */
804 seq_printf(m, "processor\t: %d\n", i);
1da177e4
LT
805 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
806 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
807 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
808 }
809#else /* CONFIG_SMP */
810 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
811 loops_per_jiffy / (500000/HZ),
812 (loops_per_jiffy / (5000/HZ)) % 100);
813#endif
814
815 /* dump out the processor features */
816 seq_puts(m, "Features\t: ");
817
818 for (i = 0; hwcap_str[i]; i++)
819 if (elf_hwcap & (1 << i))
820 seq_printf(m, "%s ", hwcap_str[i]);
821
0ba8b9b2 822 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
1da177e4
LT
823 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
824
0ba8b9b2 825 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
1da177e4 826 /* pre-ARM7 */
0ba8b9b2 827 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
1da177e4 828 } else {
0ba8b9b2 829 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
1da177e4
LT
830 /* ARM7 */
831 seq_printf(m, "CPU variant\t: 0x%02x\n",
0ba8b9b2 832 (read_cpuid_id() >> 16) & 127);
1da177e4
LT
833 } else {
834 /* post-ARM7 */
835 seq_printf(m, "CPU variant\t: 0x%x\n",
0ba8b9b2 836 (read_cpuid_id() >> 20) & 15);
1da177e4
LT
837 }
838 seq_printf(m, "CPU part\t: 0x%03x\n",
0ba8b9b2 839 (read_cpuid_id() >> 4) & 0xfff);
1da177e4 840 }
0ba8b9b2 841 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
1da177e4 842
1da177e4
LT
843 seq_puts(m, "\n");
844
845 seq_printf(m, "Hardware\t: %s\n", machine_name);
846 seq_printf(m, "Revision\t: %04x\n", system_rev);
847 seq_printf(m, "Serial\t\t: %08x%08x\n",
848 system_serial_high, system_serial_low);
849
850 return 0;
851}
852
853static void *c_start(struct seq_file *m, loff_t *pos)
854{
855 return *pos < 1 ? (void *)1 : NULL;
856}
857
858static void *c_next(struct seq_file *m, void *v, loff_t *pos)
859{
860 ++*pos;
861 return NULL;
862}
863
864static void c_stop(struct seq_file *m, void *v)
865{
866}
867
2ffd6e18 868const struct seq_operations cpuinfo_op = {
1da177e4
LT
869 .start = c_start,
870 .next = c_next,
871 .stop = c_stop,
872 .show = c_show
873};