Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[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>
29#include <asm/elf.h>
1da177e4
LT
30#include <asm/procinfo.h>
31#include <asm/setup.h>
32#include <asm/mach-types.h>
33#include <asm/cacheflush.h>
34#include <asm/tlbflush.h>
35
36#include <asm/mach/arch.h>
37#include <asm/mach/irq.h>
38#include <asm/mach/time.h>
5cbad0eb 39#include <asm/traps.h>
1da177e4 40
0fc1c832 41#include "compat.h"
4cd9d6f7 42#include "atags.h"
0fc1c832 43
1da177e4
LT
44#ifndef MEM_SIZE
45#define MEM_SIZE (16*1024*1024)
46#endif
47
48#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
49char fpe_type[8];
50
51static int __init fpe_setup(char *line)
52{
53 memcpy(fpe_type, line, 8);
54 return 1;
55}
56
57__setup("fpe=", fpe_setup);
58#endif
59
1da177e4 60extern void paging_init(struct meminfo *, struct machine_desc *desc);
1da177e4
LT
61extern void reboot_setup(char *str);
62extern int root_mountflags;
63extern void _stext, _text, _etext, __data_start, _edata, _end;
64
65unsigned int processor_id;
c18f6581 66EXPORT_SYMBOL(processor_id);
1da177e4
LT
67unsigned int __machine_arch_type;
68EXPORT_SYMBOL(__machine_arch_type);
69
9d20fdd5
BG
70unsigned int __atags_pointer __initdata;
71
1da177e4
LT
72unsigned int system_rev;
73EXPORT_SYMBOL(system_rev);
74
75unsigned int system_serial_low;
76EXPORT_SYMBOL(system_serial_low);
77
78unsigned int system_serial_high;
79EXPORT_SYMBOL(system_serial_high);
80
81unsigned int elf_hwcap;
82EXPORT_SYMBOL(elf_hwcap);
83
60296c71
LB
84unsigned long __initdata vmalloc_reserve = 128 << 20;
85
1da177e4
LT
86
87#ifdef MULTI_CPU
88struct processor processor;
89#endif
90#ifdef MULTI_TLB
91struct cpu_tlb_fns cpu_tlb;
92#endif
93#ifdef MULTI_USER
94struct cpu_user_fns cpu_user;
95#endif
96#ifdef MULTI_CACHE
97struct cpu_cache_fns cpu_cache;
98#endif
953233dc
CM
99#ifdef CONFIG_OUTER_CACHE
100struct outer_cache_fns outer_cache;
101#endif
1da177e4 102
ccea7a19
RK
103struct stack {
104 u32 irq[3];
105 u32 abt[3];
106 u32 und[3];
107} ____cacheline_aligned;
108
109static struct stack stacks[NR_CPUS];
110
1da177e4
LT
111char elf_platform[ELF_PLATFORM_SIZE];
112EXPORT_SYMBOL(elf_platform);
113
114unsigned long phys_initrd_start __initdata = 0;
115unsigned long phys_initrd_size __initdata = 0;
116
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
181static const char *cache_types[16] = {
182 "write-through",
183 "write-back",
184 "write-back",
185 "undefined 3",
186 "undefined 4",
187 "undefined 5",
188 "write-back",
189 "write-back",
190 "undefined 8",
191 "undefined 9",
192 "undefined 10",
193 "undefined 11",
194 "undefined 12",
195 "undefined 13",
196 "write-back",
197 "undefined 15",
198};
199
200static const char *cache_clean[16] = {
201 "not required",
202 "read-block",
203 "cp15 c7 ops",
204 "undefined 3",
205 "undefined 4",
206 "undefined 5",
207 "cp15 c7 ops",
208 "cp15 c7 ops",
209 "undefined 8",
210 "undefined 9",
211 "undefined 10",
212 "undefined 11",
213 "undefined 12",
214 "undefined 13",
215 "cp15 c7 ops",
216 "undefined 15",
217};
218
219static const char *cache_lockdown[16] = {
220 "not supported",
221 "not supported",
222 "not supported",
223 "undefined 3",
224 "undefined 4",
225 "undefined 5",
226 "format A",
227 "format B",
228 "undefined 8",
229 "undefined 9",
230 "undefined 10",
231 "undefined 11",
232 "undefined 12",
233 "undefined 13",
234 "format C",
235 "undefined 15",
236};
237
238static const char *proc_arch[] = {
239 "undefined/unknown",
240 "3",
241 "4",
242 "4T",
243 "5",
244 "5T",
245 "5TE",
246 "5TEJ",
247 "6TEJ",
6b090a25 248 "7",
1da177e4
LT
249 "?(11)",
250 "?(12)",
251 "?(13)",
252 "?(14)",
253 "?(15)",
254 "?(16)",
255 "?(17)",
256};
257
258#define CACHE_TYPE(x) (((x) >> 25) & 15)
259#define CACHE_S(x) ((x) & (1 << 24))
260#define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
261#define CACHE_ISIZE(x) ((x) & 4095)
262
263#define CACHE_SIZE(y) (((y) >> 6) & 7)
264#define CACHE_ASSOC(y) (((y) >> 3) & 7)
265#define CACHE_M(y) ((y) & (1 << 2))
266#define CACHE_LINE(y) ((y) & 3)
267
268static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
269{
270 unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
271
272 printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n",
273 cpu, prefix,
274 mult << (8 + CACHE_SIZE(cache)),
275 (mult << CACHE_ASSOC(cache)) >> 1,
276 8 << CACHE_LINE(cache),
277 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
278 CACHE_LINE(cache)));
279}
280
281static void __init dump_cpu_info(int cpu)
282{
283 unsigned int info = read_cpuid(CPUID_CACHETYPE);
284
285 if (info != processor_id) {
286 printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
287 cache_types[CACHE_TYPE(info)]);
288 if (CACHE_S(info)) {
289 dump_cache("I cache", cpu, CACHE_ISIZE(info));
290 dump_cache("D cache", cpu, CACHE_DSIZE(info));
291 } else {
292 dump_cache("cache", cpu, CACHE_ISIZE(info));
293 }
294 }
23759dc6
LB
295
296 if (arch_is_coherent())
297 printk("Cache coherency enabled\n");
1da177e4
LT
298}
299
300int cpu_architecture(void)
301{
302 int cpu_arch;
303
6b090a25 304 if ((processor_id & 0x0008f000) == 0) {
1da177e4 305 cpu_arch = CPU_ARCH_UNKNOWN;
6b090a25 306 } else if ((processor_id & 0x0008f000) == 0x00007000) {
1da177e4 307 cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
6b090a25 308 } else if ((processor_id & 0x00080000) == 0x00000000) {
1da177e4
LT
309 cpu_arch = (processor_id >> 16) & 7;
310 if (cpu_arch)
311 cpu_arch += CPU_ARCH_ARMv3;
180005c4
CM
312 } else if ((processor_id & 0x000f0000) == 0x000f0000) {
313 unsigned int mmfr0;
314
315 /* Revised CPUID format. Read the Memory Model Feature
316 * Register 0 and check for VMSAv7 or PMSAv7 */
317 asm("mrc p15, 0, %0, c0, c1, 4"
318 : "=r" (mmfr0));
319 if ((mmfr0 & 0x0000000f) == 0x00000003 ||
320 (mmfr0 & 0x000000f0) == 0x00000030)
321 cpu_arch = CPU_ARCH_ARMv7;
322 else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
323 (mmfr0 & 0x000000f0) == 0x00000020)
324 cpu_arch = CPU_ARCH_ARMv6;
325 else
326 cpu_arch = CPU_ARCH_UNKNOWN;
327 } else
328 cpu_arch = CPU_ARCH_UNKNOWN;
1da177e4
LT
329
330 return cpu_arch;
331}
332
333/*
334 * These functions re-use the assembly code in head.S, which
335 * already provide the required functionality.
336 */
0f44ba1d 337extern struct proc_info_list *lookup_processor_type(unsigned int);
1da177e4
LT
338extern struct machine_desc *lookup_machine_type(unsigned int);
339
340static void __init setup_processor(void)
341{
342 struct proc_info_list *list;
343
344 /*
345 * locate processor in the list of supported processor
346 * types. The linker builds this table for us from the
347 * entries in arch/arm/mm/proc-*.S
348 */
0f44ba1d 349 list = lookup_processor_type(processor_id);
1da177e4
LT
350 if (!list) {
351 printk("CPU configuration botched (ID %08x), unable "
352 "to continue.\n", processor_id);
353 while (1);
354 }
355
356 cpu_name = list->cpu_name;
357
358#ifdef MULTI_CPU
359 processor = *list->proc;
360#endif
361#ifdef MULTI_TLB
362 cpu_tlb = *list->tlb;
363#endif
364#ifdef MULTI_USER
365 cpu_user = *list->user;
366#endif
367#ifdef MULTI_CACHE
368 cpu_cache = *list->cache;
369#endif
370
4e19025b 371 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
1da177e4 372 cpu_name, processor_id, (int)processor_id & 15,
264edb35 373 proc_arch[cpu_architecture()], cr_alignment);
1da177e4 374
96b644bd 375 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
1da177e4
LT
376 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
377 elf_hwcap = list->elf_hwcap;
adeff422
CM
378#ifndef CONFIG_ARM_THUMB
379 elf_hwcap &= ~HWCAP_THUMB;
380#endif
1da177e4
LT
381
382 cpu_proc_init();
383}
384
ccea7a19
RK
385/*
386 * cpu_init - initialise one CPU.
387 *
388 * cpu_init dumps the cache information, initialises SMP specific
389 * information, and sets up the per-CPU stacks.
390 */
36c5ed23 391void cpu_init(void)
ccea7a19
RK
392{
393 unsigned int cpu = smp_processor_id();
394 struct stack *stk = &stacks[cpu];
395
396 if (cpu >= NR_CPUS) {
397 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
398 BUG();
399 }
400
32f8b97c
RK
401 if (system_state == SYSTEM_BOOTING)
402 dump_cpu_info(cpu);
ccea7a19
RK
403
404 /*
405 * setup stacks for re-entrant exception handlers
406 */
407 __asm__ (
408 "msr cpsr_c, %1\n\t"
409 "add sp, %0, %2\n\t"
410 "msr cpsr_c, %3\n\t"
411 "add sp, %0, %4\n\t"
412 "msr cpsr_c, %5\n\t"
413 "add sp, %0, %6\n\t"
414 "msr cpsr_c, %7"
415 :
416 : "r" (stk),
417 "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
418 "I" (offsetof(struct stack, irq[0])),
419 "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
420 "I" (offsetof(struct stack, abt[0])),
421 "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
422 "I" (offsetof(struct stack, und[0])),
aaaa3f9e
CM
423 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
424 : "r14");
ccea7a19
RK
425}
426
1da177e4
LT
427static struct machine_desc * __init setup_machine(unsigned int nr)
428{
429 struct machine_desc *list;
430
431 /*
432 * locate machine in the list of supported machines.
433 */
434 list = lookup_machine_type(nr);
435 if (!list) {
436 printk("Machine configuration botched (nr %d), unable "
437 "to continue.\n", nr);
438 while (1);
439 }
440
441 printk("Machine: %s\n", list->name);
442
443 return list;
444}
445
446static void __init early_initrd(char **p)
447{
448 unsigned long start, size;
449
450 start = memparse(*p, p);
451 if (**p == ',') {
452 size = memparse((*p) + 1, p);
453
454 phys_initrd_start = start;
455 phys_initrd_size = size;
456 }
457}
458__early_param("initrd=", early_initrd);
459
1c97b73e 460static void __init arm_add_memory(unsigned long start, unsigned long size)
3a669411 461{
05f96ef1
RK
462 struct membank *bank;
463
3a669411
RK
464 /*
465 * Ensure that start/size are aligned to a page boundary.
466 * Size is appropriately rounded down, start is rounded up.
467 */
468 size -= start & ~PAGE_MASK;
469
05f96ef1
RK
470 bank = &meminfo.bank[meminfo.nr_banks++];
471
472 bank->start = PAGE_ALIGN(start);
473 bank->size = size & PAGE_MASK;
474 bank->node = PHYS_TO_NID(start);
3a669411
RK
475}
476
1da177e4
LT
477/*
478 * Pick out the memory size. We look for mem=size@start,
479 * where start and size are "size[KkMm]"
480 */
481static void __init early_mem(char **p)
482{
483 static int usermem __initdata = 0;
484 unsigned long size, start;
485
486 /*
487 * If the user specifies memory size, we
488 * blow away any automatically generated
489 * size.
490 */
491 if (usermem == 0) {
492 usermem = 1;
493 meminfo.nr_banks = 0;
494 }
495
496 start = PHYS_OFFSET;
497 size = memparse(*p, p);
498 if (**p == '@')
499 start = memparse(*p + 1, p);
500
1c97b73e 501 arm_add_memory(start, size);
1da177e4
LT
502}
503__early_param("mem=", early_mem);
504
60296c71
LB
505/*
506 * vmalloc=size forces the vmalloc area to be exactly 'size'
507 * bytes. This can be used to increase (or decrease) the vmalloc
508 * area - the default is 128m.
509 */
510static void __init early_vmalloc(char **arg)
511{
512 vmalloc_reserve = memparse(*arg, arg);
513}
514__early_param("vmalloc=", early_vmalloc);
515
1da177e4
LT
516/*
517 * Initial parsing of the command line.
518 */
519static void __init parse_cmdline(char **cmdline_p, char *from)
520{
521 char c = ' ', *to = command_line;
522 int len = 0;
523
524 for (;;) {
525 if (c == ' ') {
526 extern struct early_params __early_begin, __early_end;
527 struct early_params *p;
528
529 for (p = &__early_begin; p < &__early_end; p++) {
530 int len = strlen(p->arg);
531
532 if (memcmp(from, p->arg, len) == 0) {
533 if (to != command_line)
534 to -= 1;
535 from += len;
536 p->fn(&from);
537
538 while (*from != ' ' && *from != '\0')
539 from++;
540 break;
541 }
542 }
543 }
544 c = *from++;
545 if (!c)
546 break;
547 if (COMMAND_LINE_SIZE <= ++len)
548 break;
549 *to++ = c;
550 }
551 *to = '\0';
552 *cmdline_p = command_line;
553}
554
555static void __init
556setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
557{
558#ifdef CONFIG_BLK_DEV_RAM
559 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
560
561 rd_image_start = image_start;
562 rd_prompt = prompt;
563 rd_doload = doload;
564
565 if (rd_sz)
566 rd_size = rd_sz;
567#endif
568}
569
570static void __init
571request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
572{
573 struct resource *res;
574 int i;
575
576 kernel_code.start = virt_to_phys(&_text);
577 kernel_code.end = virt_to_phys(&_etext - 1);
578 kernel_data.start = virt_to_phys(&__data_start);
579 kernel_data.end = virt_to_phys(&_end - 1);
580
581 for (i = 0; i < mi->nr_banks; i++) {
582 unsigned long virt_start, virt_end;
583
584 if (mi->bank[i].size == 0)
585 continue;
586
587 virt_start = __phys_to_virt(mi->bank[i].start);
588 virt_end = virt_start + mi->bank[i].size - 1;
589
590 res = alloc_bootmem_low(sizeof(*res));
591 res->name = "System RAM";
592 res->start = __virt_to_phys(virt_start);
593 res->end = __virt_to_phys(virt_end);
594 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
595
596 request_resource(&iomem_resource, res);
597
598 if (kernel_code.start >= res->start &&
599 kernel_code.end <= res->end)
600 request_resource(res, &kernel_code);
601 if (kernel_data.start >= res->start &&
602 kernel_data.end <= res->end)
603 request_resource(res, &kernel_data);
604 }
605
606 if (mdesc->video_start) {
607 video_ram.start = mdesc->video_start;
608 video_ram.end = mdesc->video_end;
609 request_resource(&iomem_resource, &video_ram);
610 }
611
612 /*
613 * Some machines don't have the possibility of ever
614 * possessing lp0, lp1 or lp2
615 */
616 if (mdesc->reserve_lp0)
617 request_resource(&ioport_resource, &lp0);
618 if (mdesc->reserve_lp1)
619 request_resource(&ioport_resource, &lp1);
620 if (mdesc->reserve_lp2)
621 request_resource(&ioport_resource, &lp2);
622}
623
624/*
625 * Tag parsing.
626 *
627 * This is the new way of passing data to the kernel at boot time. Rather
628 * than passing a fixed inflexible structure to the kernel, we pass a list
629 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
630 * tag for the list to be recognised (to distinguish the tagged list from
631 * a param_struct). The list is terminated with a zero-length tag (this tag
632 * is not parsed in any way).
633 */
634static int __init parse_tag_core(const struct tag *tag)
635{
636 if (tag->hdr.size > 2) {
637 if ((tag->u.core.flags & 1) == 0)
638 root_mountflags &= ~MS_RDONLY;
639 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
640 }
641 return 0;
642}
643
644__tagtable(ATAG_CORE, parse_tag_core);
645
646static int __init parse_tag_mem32(const struct tag *tag)
647{
648 if (meminfo.nr_banks >= NR_BANKS) {
649 printk(KERN_WARNING
650 "Ignoring memory bank 0x%08x size %dKB\n",
651 tag->u.mem.start, tag->u.mem.size / 1024);
652 return -EINVAL;
653 }
1c97b73e 654 arm_add_memory(tag->u.mem.start, tag->u.mem.size);
1da177e4
LT
655 return 0;
656}
657
658__tagtable(ATAG_MEM, parse_tag_mem32);
659
660#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
661struct screen_info screen_info = {
662 .orig_video_lines = 30,
663 .orig_video_cols = 80,
664 .orig_video_mode = 0,
665 .orig_video_ega_bx = 0,
666 .orig_video_isVGA = 1,
667 .orig_video_points = 8
668};
669
670static int __init parse_tag_videotext(const struct tag *tag)
671{
672 screen_info.orig_x = tag->u.videotext.x;
673 screen_info.orig_y = tag->u.videotext.y;
674 screen_info.orig_video_page = tag->u.videotext.video_page;
675 screen_info.orig_video_mode = tag->u.videotext.video_mode;
676 screen_info.orig_video_cols = tag->u.videotext.video_cols;
677 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
678 screen_info.orig_video_lines = tag->u.videotext.video_lines;
679 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
680 screen_info.orig_video_points = tag->u.videotext.video_points;
681 return 0;
682}
683
684__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
685#endif
686
687static int __init parse_tag_ramdisk(const struct tag *tag)
688{
689 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
690 (tag->u.ramdisk.flags & 2) == 0,
691 tag->u.ramdisk.start, tag->u.ramdisk.size);
692 return 0;
693}
694
695__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
696
697static int __init parse_tag_initrd(const struct tag *tag)
698{
699 printk(KERN_WARNING "ATAG_INITRD is deprecated; "
700 "please update your bootloader.\n");
701 phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
702 phys_initrd_size = tag->u.initrd.size;
703 return 0;
704}
705
706__tagtable(ATAG_INITRD, parse_tag_initrd);
707
708static int __init parse_tag_initrd2(const struct tag *tag)
709{
710 phys_initrd_start = tag->u.initrd.start;
711 phys_initrd_size = tag->u.initrd.size;
712 return 0;
713}
714
715__tagtable(ATAG_INITRD2, parse_tag_initrd2);
716
717static int __init parse_tag_serialnr(const struct tag *tag)
718{
719 system_serial_low = tag->u.serialnr.low;
720 system_serial_high = tag->u.serialnr.high;
721 return 0;
722}
723
724__tagtable(ATAG_SERIAL, parse_tag_serialnr);
725
726static int __init parse_tag_revision(const struct tag *tag)
727{
728 system_rev = tag->u.revision.rev;
729 return 0;
730}
731
732__tagtable(ATAG_REVISION, parse_tag_revision);
733
734static int __init parse_tag_cmdline(const struct tag *tag)
735{
736 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
737 return 0;
738}
739
740__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
741
742/*
743 * Scan the tag table for this tag, and call its parse function.
744 * The tag table is built by the linker from all the __tagtable
745 * declarations.
746 */
747static int __init parse_tag(const struct tag *tag)
748{
749 extern struct tagtable __tagtable_begin, __tagtable_end;
750 struct tagtable *t;
751
752 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
753 if (tag->hdr.tag == t->tag) {
754 t->parse(tag);
755 break;
756 }
757
758 return t < &__tagtable_end;
759}
760
761/*
762 * Parse all tags in the list, checking both the global and architecture
763 * specific tag tables.
764 */
765static void __init parse_tags(const struct tag *t)
766{
767 for (; t->hdr.size; t = tag_next(t))
768 if (!parse_tag(t))
769 printk(KERN_WARNING
770 "Ignoring unrecognised tag 0x%08x\n",
771 t->hdr.tag);
772}
773
774/*
775 * This holds our defaults.
776 */
777static struct init_tags {
778 struct tag_header hdr1;
779 struct tag_core core;
780 struct tag_header hdr2;
781 struct tag_mem32 mem;
782 struct tag_header hdr3;
783} init_tags __initdata = {
784 { tag_size(tag_core), ATAG_CORE },
785 { 1, PAGE_SIZE, 0xff },
786 { tag_size(tag_mem32), ATAG_MEM },
787 { MEM_SIZE, PHYS_OFFSET },
788 { 0, ATAG_NONE }
789};
790
791static void (*init_machine)(void) __initdata;
792
793static int __init customize_machine(void)
794{
795 /* customizes platform devices, or adds new ones */
796 if (init_machine)
797 init_machine();
798 return 0;
799}
800arch_initcall(customize_machine);
801
802void __init setup_arch(char **cmdline_p)
803{
804 struct tag *tags = (struct tag *)&init_tags;
805 struct machine_desc *mdesc;
806 char *from = default_command_line;
807
808 setup_processor();
809 mdesc = setup_machine(machine_arch_type);
810 machine_name = mdesc->name;
811
812 if (mdesc->soft_reboot)
813 reboot_setup("s");
814
9d20fdd5
BG
815 if (__atags_pointer)
816 tags = phys_to_virt(__atags_pointer);
817 else if (mdesc->boot_params)
f9bd6ea4 818 tags = phys_to_virt(mdesc->boot_params);
1da177e4
LT
819
820 /*
821 * If we have the old style parameters, convert them to
822 * a tag list.
823 */
824 if (tags->hdr.tag != ATAG_CORE)
825 convert_to_tag_list(tags);
826 if (tags->hdr.tag != ATAG_CORE)
827 tags = (struct tag *)&init_tags;
828
829 if (mdesc->fixup)
830 mdesc->fixup(mdesc, tags, &from, &meminfo);
831
832 if (tags->hdr.tag == ATAG_CORE) {
833 if (meminfo.nr_banks != 0)
834 squash_mem_tags(tags);
4cd9d6f7 835 save_atags(tags);
1da177e4
LT
836 parse_tags(tags);
837 }
838
839 init_mm.start_code = (unsigned long) &_text;
840 init_mm.end_code = (unsigned long) &_etext;
841 init_mm.end_data = (unsigned long) &_edata;
842 init_mm.brk = (unsigned long) &_end;
843
cd81899a
ABL
844 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
845 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
1da177e4
LT
846 parse_cmdline(cmdline_p, from);
847 paging_init(&meminfo, mdesc);
848 request_standard_resources(&meminfo, mdesc);
849
7bbb7940
RK
850#ifdef CONFIG_SMP
851 smp_init_cpus();
852#endif
853
ccea7a19
RK
854 cpu_init();
855
1da177e4
LT
856 /*
857 * Set up various architecture-specific pointers
858 */
859 init_arch_irq = mdesc->init_irq;
860 system_timer = mdesc->timer;
861 init_machine = mdesc->init_machine;
862
863#ifdef CONFIG_VT
864#if defined(CONFIG_VGA_CONSOLE)
865 conswitchp = &vga_con;
866#elif defined(CONFIG_DUMMY_CONSOLE)
867 conswitchp = &dummy_con;
868#endif
869#endif
5cbad0eb 870 early_trap_init();
1da177e4
LT
871}
872
873
874static int __init topology_init(void)
875{
876 int cpu;
877
66fb8bd2
RK
878 for_each_possible_cpu(cpu) {
879 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
880 cpuinfo->cpu.hotpluggable = 1;
881 register_cpu(&cpuinfo->cpu, cpu);
882 }
1da177e4
LT
883
884 return 0;
885}
886
887subsys_initcall(topology_init);
888
889static const char *hwcap_str[] = {
890 "swp",
891 "half",
892 "thumb",
893 "26bit",
894 "fastmult",
895 "fpa",
896 "vfp",
897 "edsp",
898 "java",
8f7f9435 899 "iwmmxt",
99e4a6dd 900 "crunch",
1da177e4
LT
901 NULL
902};
903
904static void
905c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
906{
907 unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
908
909 seq_printf(m, "%s size\t\t: %d\n"
910 "%s assoc\t\t: %d\n"
911 "%s line length\t: %d\n"
912 "%s sets\t\t: %d\n",
913 type, mult << (8 + CACHE_SIZE(cache)),
914 type, (mult << CACHE_ASSOC(cache)) >> 1,
915 type, 8 << CACHE_LINE(cache),
916 type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
917 CACHE_LINE(cache)));
918}
919
920static int c_show(struct seq_file *m, void *v)
921{
922 int i;
923
924 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
925 cpu_name, (int)processor_id & 15, elf_platform);
926
927#if defined(CONFIG_SMP)
928 for_each_online_cpu(i) {
15559722
RK
929 /*
930 * glibc reads /proc/cpuinfo to determine the number of
931 * online processors, looking for lines beginning with
932 * "processor". Give glibc what it expects.
933 */
934 seq_printf(m, "processor\t: %d\n", i);
1da177e4
LT
935 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
936 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
937 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
938 }
939#else /* CONFIG_SMP */
940 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
941 loops_per_jiffy / (500000/HZ),
942 (loops_per_jiffy / (5000/HZ)) % 100);
943#endif
944
945 /* dump out the processor features */
946 seq_puts(m, "Features\t: ");
947
948 for (i = 0; hwcap_str[i]; i++)
949 if (elf_hwcap & (1 << i))
950 seq_printf(m, "%s ", hwcap_str[i]);
951
952 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
953 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
954
6b090a25 955 if ((processor_id & 0x0008f000) == 0x00000000) {
1da177e4 956 /* pre-ARM7 */
1d28bff7 957 seq_printf(m, "CPU part\t: %07x\n", processor_id >> 4);
1da177e4 958 } else {
6b090a25 959 if ((processor_id & 0x0008f000) == 0x00007000) {
1da177e4
LT
960 /* ARM7 */
961 seq_printf(m, "CPU variant\t: 0x%02x\n",
962 (processor_id >> 16) & 127);
963 } else {
964 /* post-ARM7 */
965 seq_printf(m, "CPU variant\t: 0x%x\n",
966 (processor_id >> 20) & 15);
967 }
968 seq_printf(m, "CPU part\t: 0x%03x\n",
969 (processor_id >> 4) & 0xfff);
970 }
971 seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
972
973 {
974 unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
975 if (cache_info != processor_id) {
976 seq_printf(m, "Cache type\t: %s\n"
977 "Cache clean\t: %s\n"
978 "Cache lockdown\t: %s\n"
979 "Cache format\t: %s\n",
980 cache_types[CACHE_TYPE(cache_info)],
981 cache_clean[CACHE_TYPE(cache_info)],
982 cache_lockdown[CACHE_TYPE(cache_info)],
983 CACHE_S(cache_info) ? "Harvard" : "Unified");
984
985 if (CACHE_S(cache_info)) {
986 c_show_cache(m, "I", CACHE_ISIZE(cache_info));
987 c_show_cache(m, "D", CACHE_DSIZE(cache_info));
988 } else {
989 c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
990 }
991 }
992 }
993
994 seq_puts(m, "\n");
995
996 seq_printf(m, "Hardware\t: %s\n", machine_name);
997 seq_printf(m, "Revision\t: %04x\n", system_rev);
998 seq_printf(m, "Serial\t\t: %08x%08x\n",
999 system_serial_high, system_serial_low);
1000
1001 return 0;
1002}
1003
1004static void *c_start(struct seq_file *m, loff_t *pos)
1005{
1006 return *pos < 1 ? (void *)1 : NULL;
1007}
1008
1009static void *c_next(struct seq_file *m, void *v, loff_t *pos)
1010{
1011 ++*pos;
1012 return NULL;
1013}
1014
1015static void c_stop(struct seq_file *m, void *v)
1016{
1017}
1018
2ffd6e18 1019const struct seq_operations cpuinfo_op = {
1da177e4
LT
1020 .start = c_start,
1021 .next = c_next,
1022 .stop = c_stop,
1023 .show = c_show
1024};
This page took 0.38812 seconds and 5 git commands to generate.