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