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