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