Add "thumbee" to the hwcap_str array
[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",
4369ae16 775 "thumbee",
1da177e4
LT
776 NULL
777};
778
1da177e4
LT
779static int c_show(struct seq_file *m, void *v)
780{
781 int i;
782
783 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
0ba8b9b2 784 cpu_name, read_cpuid_id() & 15, elf_platform);
1da177e4
LT
785
786#if defined(CONFIG_SMP)
787 for_each_online_cpu(i) {
15559722
RK
788 /*
789 * glibc reads /proc/cpuinfo to determine the number of
790 * online processors, looking for lines beginning with
791 * "processor". Give glibc what it expects.
792 */
793 seq_printf(m, "processor\t: %d\n", i);
1da177e4
LT
794 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
795 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
796 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
797 }
798#else /* CONFIG_SMP */
799 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
800 loops_per_jiffy / (500000/HZ),
801 (loops_per_jiffy / (5000/HZ)) % 100);
802#endif
803
804 /* dump out the processor features */
805 seq_puts(m, "Features\t: ");
806
807 for (i = 0; hwcap_str[i]; i++)
808 if (elf_hwcap & (1 << i))
809 seq_printf(m, "%s ", hwcap_str[i]);
810
0ba8b9b2 811 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
1da177e4
LT
812 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
813
0ba8b9b2 814 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
1da177e4 815 /* pre-ARM7 */
0ba8b9b2 816 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
1da177e4 817 } else {
0ba8b9b2 818 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
1da177e4
LT
819 /* ARM7 */
820 seq_printf(m, "CPU variant\t: 0x%02x\n",
0ba8b9b2 821 (read_cpuid_id() >> 16) & 127);
1da177e4
LT
822 } else {
823 /* post-ARM7 */
824 seq_printf(m, "CPU variant\t: 0x%x\n",
0ba8b9b2 825 (read_cpuid_id() >> 20) & 15);
1da177e4
LT
826 }
827 seq_printf(m, "CPU part\t: 0x%03x\n",
0ba8b9b2 828 (read_cpuid_id() >> 4) & 0xfff);
1da177e4 829 }
0ba8b9b2 830 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
1da177e4 831
1da177e4
LT
832 seq_puts(m, "\n");
833
834 seq_printf(m, "Hardware\t: %s\n", machine_name);
835 seq_printf(m, "Revision\t: %04x\n", system_rev);
836 seq_printf(m, "Serial\t\t: %08x%08x\n",
837 system_serial_high, system_serial_low);
838
839 return 0;
840}
841
842static void *c_start(struct seq_file *m, loff_t *pos)
843{
844 return *pos < 1 ? (void *)1 : NULL;
845}
846
847static void *c_next(struct seq_file *m, void *v, loff_t *pos)
848{
849 ++*pos;
850 return NULL;
851}
852
853static void c_stop(struct seq_file *m, void *v)
854{
855}
856
2ffd6e18 857const struct seq_operations cpuinfo_op = {
1da177e4
LT
858 .start = c_start,
859 .next = c_next,
860 .stop = c_stop,
861 .show = c_show
862};
This page took 0.389756 seconds and 5 git commands to generate.