[ARM] mm: allow LH7A40x to use sparsemem
[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++) {
481 unsigned long virt_start, virt_end;
482
483 if (mi->bank[i].size == 0)
484 continue;
485
486 virt_start = __phys_to_virt(mi->bank[i].start);
487 virt_end = virt_start + mi->bank[i].size - 1;
488
489 res = alloc_bootmem_low(sizeof(*res));
490 res->name = "System RAM";
491 res->start = __virt_to_phys(virt_start);
492 res->end = __virt_to_phys(virt_end);
493 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
494
495 request_resource(&iomem_resource, res);
496
497 if (kernel_code.start >= res->start &&
498 kernel_code.end <= res->end)
499 request_resource(res, &kernel_code);
500 if (kernel_data.start >= res->start &&
501 kernel_data.end <= res->end)
502 request_resource(res, &kernel_data);
503 }
504
505 if (mdesc->video_start) {
506 video_ram.start = mdesc->video_start;
507 video_ram.end = mdesc->video_end;
508 request_resource(&iomem_resource, &video_ram);
509 }
510
511 /*
512 * Some machines don't have the possibility of ever
513 * possessing lp0, lp1 or lp2
514 */
515 if (mdesc->reserve_lp0)
516 request_resource(&ioport_resource, &lp0);
517 if (mdesc->reserve_lp1)
518 request_resource(&ioport_resource, &lp1);
519 if (mdesc->reserve_lp2)
520 request_resource(&ioport_resource, &lp2);
521}
522
523/*
524 * Tag parsing.
525 *
526 * This is the new way of passing data to the kernel at boot time. Rather
527 * than passing a fixed inflexible structure to the kernel, we pass a list
528 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
529 * tag for the list to be recognised (to distinguish the tagged list from
530 * a param_struct). The list is terminated with a zero-length tag (this tag
531 * is not parsed in any way).
532 */
533static int __init parse_tag_core(const struct tag *tag)
534{
535 if (tag->hdr.size > 2) {
536 if ((tag->u.core.flags & 1) == 0)
537 root_mountflags &= ~MS_RDONLY;
538 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
539 }
540 return 0;
541}
542
543__tagtable(ATAG_CORE, parse_tag_core);
544
545static int __init parse_tag_mem32(const struct tag *tag)
546{
547 if (meminfo.nr_banks >= NR_BANKS) {
548 printk(KERN_WARNING
549 "Ignoring memory bank 0x%08x size %dKB\n",
550 tag->u.mem.start, tag->u.mem.size / 1024);
551 return -EINVAL;
552 }
1c97b73e 553 arm_add_memory(tag->u.mem.start, tag->u.mem.size);
1da177e4
LT
554 return 0;
555}
556
557__tagtable(ATAG_MEM, parse_tag_mem32);
558
559#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
560struct screen_info screen_info = {
561 .orig_video_lines = 30,
562 .orig_video_cols = 80,
563 .orig_video_mode = 0,
564 .orig_video_ega_bx = 0,
565 .orig_video_isVGA = 1,
566 .orig_video_points = 8
567};
568
569static int __init parse_tag_videotext(const struct tag *tag)
570{
571 screen_info.orig_x = tag->u.videotext.x;
572 screen_info.orig_y = tag->u.videotext.y;
573 screen_info.orig_video_page = tag->u.videotext.video_page;
574 screen_info.orig_video_mode = tag->u.videotext.video_mode;
575 screen_info.orig_video_cols = tag->u.videotext.video_cols;
576 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
577 screen_info.orig_video_lines = tag->u.videotext.video_lines;
578 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
579 screen_info.orig_video_points = tag->u.videotext.video_points;
580 return 0;
581}
582
583__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
584#endif
585
586static int __init parse_tag_ramdisk(const struct tag *tag)
587{
588 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
589 (tag->u.ramdisk.flags & 2) == 0,
590 tag->u.ramdisk.start, tag->u.ramdisk.size);
591 return 0;
592}
593
594__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
595
1da177e4
LT
596static int __init parse_tag_serialnr(const struct tag *tag)
597{
598 system_serial_low = tag->u.serialnr.low;
599 system_serial_high = tag->u.serialnr.high;
600 return 0;
601}
602
603__tagtable(ATAG_SERIAL, parse_tag_serialnr);
604
605static int __init parse_tag_revision(const struct tag *tag)
606{
607 system_rev = tag->u.revision.rev;
608 return 0;
609}
610
611__tagtable(ATAG_REVISION, parse_tag_revision);
612
613static int __init parse_tag_cmdline(const struct tag *tag)
614{
615 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
616 return 0;
617}
618
619__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
620
621/*
622 * Scan the tag table for this tag, and call its parse function.
623 * The tag table is built by the linker from all the __tagtable
624 * declarations.
625 */
626static int __init parse_tag(const struct tag *tag)
627{
628 extern struct tagtable __tagtable_begin, __tagtable_end;
629 struct tagtable *t;
630
631 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
632 if (tag->hdr.tag == t->tag) {
633 t->parse(tag);
634 break;
635 }
636
637 return t < &__tagtable_end;
638}
639
640/*
641 * Parse all tags in the list, checking both the global and architecture
642 * specific tag tables.
643 */
644static void __init parse_tags(const struct tag *t)
645{
646 for (; t->hdr.size; t = tag_next(t))
647 if (!parse_tag(t))
648 printk(KERN_WARNING
649 "Ignoring unrecognised tag 0x%08x\n",
650 t->hdr.tag);
651}
652
653/*
654 * This holds our defaults.
655 */
656static struct init_tags {
657 struct tag_header hdr1;
658 struct tag_core core;
659 struct tag_header hdr2;
660 struct tag_mem32 mem;
661 struct tag_header hdr3;
662} init_tags __initdata = {
663 { tag_size(tag_core), ATAG_CORE },
664 { 1, PAGE_SIZE, 0xff },
665 { tag_size(tag_mem32), ATAG_MEM },
666 { MEM_SIZE, PHYS_OFFSET },
667 { 0, ATAG_NONE }
668};
669
670static void (*init_machine)(void) __initdata;
671
672static int __init customize_machine(void)
673{
674 /* customizes platform devices, or adds new ones */
675 if (init_machine)
676 init_machine();
677 return 0;
678}
679arch_initcall(customize_machine);
680
681void __init setup_arch(char **cmdline_p)
682{
683 struct tag *tags = (struct tag *)&init_tags;
684 struct machine_desc *mdesc;
685 char *from = default_command_line;
686
687 setup_processor();
688 mdesc = setup_machine(machine_arch_type);
689 machine_name = mdesc->name;
690
691 if (mdesc->soft_reboot)
692 reboot_setup("s");
693
9d20fdd5
BG
694 if (__atags_pointer)
695 tags = phys_to_virt(__atags_pointer);
696 else if (mdesc->boot_params)
f9bd6ea4 697 tags = phys_to_virt(mdesc->boot_params);
1da177e4
LT
698
699 /*
700 * If we have the old style parameters, convert them to
701 * a tag list.
702 */
703 if (tags->hdr.tag != ATAG_CORE)
704 convert_to_tag_list(tags);
705 if (tags->hdr.tag != ATAG_CORE)
706 tags = (struct tag *)&init_tags;
707
708 if (mdesc->fixup)
709 mdesc->fixup(mdesc, tags, &from, &meminfo);
710
711 if (tags->hdr.tag == ATAG_CORE) {
712 if (meminfo.nr_banks != 0)
713 squash_mem_tags(tags);
4cd9d6f7 714 save_atags(tags);
1da177e4
LT
715 parse_tags(tags);
716 }
717
718 init_mm.start_code = (unsigned long) &_text;
719 init_mm.end_code = (unsigned long) &_etext;
720 init_mm.end_data = (unsigned long) &_edata;
721 init_mm.brk = (unsigned long) &_end;
722
cd81899a
ABL
723 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
724 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
1da177e4
LT
725 parse_cmdline(cmdline_p, from);
726 paging_init(&meminfo, mdesc);
727 request_standard_resources(&meminfo, mdesc);
728
7bbb7940
RK
729#ifdef CONFIG_SMP
730 smp_init_cpus();
731#endif
732
ccea7a19
RK
733 cpu_init();
734
1da177e4
LT
735 /*
736 * Set up various architecture-specific pointers
737 */
738 init_arch_irq = mdesc->init_irq;
739 system_timer = mdesc->timer;
740 init_machine = mdesc->init_machine;
741
742#ifdef CONFIG_VT
743#if defined(CONFIG_VGA_CONSOLE)
744 conswitchp = &vga_con;
745#elif defined(CONFIG_DUMMY_CONSOLE)
746 conswitchp = &dummy_con;
747#endif
748#endif
5cbad0eb 749 early_trap_init();
1da177e4
LT
750}
751
752
753static int __init topology_init(void)
754{
755 int cpu;
756
66fb8bd2
RK
757 for_each_possible_cpu(cpu) {
758 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
759 cpuinfo->cpu.hotpluggable = 1;
760 register_cpu(&cpuinfo->cpu, cpu);
761 }
1da177e4
LT
762
763 return 0;
764}
765
766subsys_initcall(topology_init);
767
768static const char *hwcap_str[] = {
769 "swp",
770 "half",
771 "thumb",
772 "26bit",
773 "fastmult",
774 "fpa",
775 "vfp",
776 "edsp",
777 "java",
8f7f9435 778 "iwmmxt",
99e4a6dd 779 "crunch",
1da177e4
LT
780 NULL
781};
782
1da177e4
LT
783static int c_show(struct seq_file *m, void *v)
784{
785 int i;
786
787 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
0ba8b9b2 788 cpu_name, read_cpuid_id() & 15, elf_platform);
1da177e4
LT
789
790#if defined(CONFIG_SMP)
791 for_each_online_cpu(i) {
15559722
RK
792 /*
793 * glibc reads /proc/cpuinfo to determine the number of
794 * online processors, looking for lines beginning with
795 * "processor". Give glibc what it expects.
796 */
797 seq_printf(m, "processor\t: %d\n", i);
1da177e4
LT
798 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
799 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
800 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
801 }
802#else /* CONFIG_SMP */
803 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
804 loops_per_jiffy / (500000/HZ),
805 (loops_per_jiffy / (5000/HZ)) % 100);
806#endif
807
808 /* dump out the processor features */
809 seq_puts(m, "Features\t: ");
810
811 for (i = 0; hwcap_str[i]; i++)
812 if (elf_hwcap & (1 << i))
813 seq_printf(m, "%s ", hwcap_str[i]);
814
0ba8b9b2 815 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
1da177e4
LT
816 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
817
0ba8b9b2 818 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
1da177e4 819 /* pre-ARM7 */
0ba8b9b2 820 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
1da177e4 821 } else {
0ba8b9b2 822 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
1da177e4
LT
823 /* ARM7 */
824 seq_printf(m, "CPU variant\t: 0x%02x\n",
0ba8b9b2 825 (read_cpuid_id() >> 16) & 127);
1da177e4
LT
826 } else {
827 /* post-ARM7 */
828 seq_printf(m, "CPU variant\t: 0x%x\n",
0ba8b9b2 829 (read_cpuid_id() >> 20) & 15);
1da177e4
LT
830 }
831 seq_printf(m, "CPU part\t: 0x%03x\n",
0ba8b9b2 832 (read_cpuid_id() >> 4) & 0xfff);
1da177e4 833 }
0ba8b9b2 834 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
1da177e4 835
1da177e4
LT
836 seq_puts(m, "\n");
837
838 seq_printf(m, "Hardware\t: %s\n", machine_name);
839 seq_printf(m, "Revision\t: %04x\n", system_rev);
840 seq_printf(m, "Serial\t\t: %08x%08x\n",
841 system_serial_high, system_serial_low);
842
843 return 0;
844}
845
846static void *c_start(struct seq_file *m, loff_t *pos)
847{
848 return *pos < 1 ? (void *)1 : NULL;
849}
850
851static void *c_next(struct seq_file *m, void *v, loff_t *pos)
852{
853 ++*pos;
854 return NULL;
855}
856
857static void c_stop(struct seq_file *m, void *v)
858{
859}
860
2ffd6e18 861const struct seq_operations cpuinfo_op = {
1da177e4
LT
862 .start = c_start,
863 .next = c_next,
864 .stop = c_stop,
865 .show = c_show
866};
This page took 0.390598 seconds and 5 git commands to generate.