]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - arch/arm/kernel/setup.c
Merge branch 'for_rmk' of git://git.mnementh.co.uk/linux-2.6-im into devel
[mirror_ubuntu-zesty-kernel.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 31#include <asm/procinfo.h>
37efe642 32#include <asm/sections.h>
1da177e4
LT
33#include <asm/setup.h>
34#include <asm/mach-types.h>
35#include <asm/cacheflush.h>
46097c7d 36#include <asm/cachetype.h>
1da177e4
LT
37#include <asm/tlbflush.h>
38
39#include <asm/mach/arch.h>
40#include <asm/mach/irq.h>
41#include <asm/mach/time.h>
5cbad0eb 42#include <asm/traps.h>
1da177e4 43
0fc1c832 44#include "compat.h"
4cd9d6f7 45#include "atags.h"
0fc1c832 46
1da177e4
LT
47#ifndef MEM_SIZE
48#define MEM_SIZE (16*1024*1024)
49#endif
50
51#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
52char fpe_type[8];
53
54static int __init fpe_setup(char *line)
55{
56 memcpy(fpe_type, line, 8);
57 return 1;
58}
59
60__setup("fpe=", fpe_setup);
61#endif
62
4b5f32ce 63extern void paging_init(struct machine_desc *desc);
1da177e4 64extern void reboot_setup(char *str);
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 const char *cpu_name;
116static const char *machine_name;
cd81899a 117static char __initdata command_line[COMMAND_LINE_SIZE];
1da177e4
LT
118
119static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
120static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
121#define ENDIANNESS ((char)endian_test.l)
122
123DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
124
125/*
126 * Standard memory resources
127 */
128static struct resource mem_res[] = {
740e518e
GKH
129 {
130 .name = "Video RAM",
131 .start = 0,
132 .end = 0,
133 .flags = IORESOURCE_MEM
134 },
135 {
136 .name = "Kernel text",
137 .start = 0,
138 .end = 0,
139 .flags = IORESOURCE_MEM
140 },
141 {
142 .name = "Kernel data",
143 .start = 0,
144 .end = 0,
145 .flags = IORESOURCE_MEM
146 }
1da177e4
LT
147};
148
149#define video_ram mem_res[0]
150#define kernel_code mem_res[1]
151#define kernel_data mem_res[2]
152
153static struct resource io_res[] = {
740e518e
GKH
154 {
155 .name = "reserved",
156 .start = 0x3bc,
157 .end = 0x3be,
158 .flags = IORESOURCE_IO | IORESOURCE_BUSY
159 },
160 {
161 .name = "reserved",
162 .start = 0x378,
163 .end = 0x37f,
164 .flags = IORESOURCE_IO | IORESOURCE_BUSY
165 },
166 {
167 .name = "reserved",
168 .start = 0x278,
169 .end = 0x27f,
170 .flags = IORESOURCE_IO | IORESOURCE_BUSY
171 }
1da177e4
LT
172};
173
174#define lp0 io_res[0]
175#define lp1 io_res[1]
176#define lp2 io_res[2]
177
1da177e4
LT
178static const char *proc_arch[] = {
179 "undefined/unknown",
180 "3",
181 "4",
182 "4T",
183 "5",
184 "5T",
185 "5TE",
186 "5TEJ",
187 "6TEJ",
6b090a25 188 "7",
1da177e4
LT
189 "?(11)",
190 "?(12)",
191 "?(13)",
192 "?(14)",
193 "?(15)",
194 "?(16)",
195 "?(17)",
196};
197
1da177e4
LT
198int cpu_architecture(void)
199{
200 int cpu_arch;
201
0ba8b9b2 202 if ((read_cpuid_id() & 0x0008f000) == 0) {
1da177e4 203 cpu_arch = CPU_ARCH_UNKNOWN;
0ba8b9b2
RK
204 } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
205 cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
206 } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
207 cpu_arch = (read_cpuid_id() >> 16) & 7;
1da177e4
LT
208 if (cpu_arch)
209 cpu_arch += CPU_ARCH_ARMv3;
0ba8b9b2 210 } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
180005c4
CM
211 unsigned int mmfr0;
212
213 /* Revised CPUID format. Read the Memory Model Feature
214 * Register 0 and check for VMSAv7 or PMSAv7 */
215 asm("mrc p15, 0, %0, c0, c1, 4"
216 : "=r" (mmfr0));
217 if ((mmfr0 & 0x0000000f) == 0x00000003 ||
218 (mmfr0 & 0x000000f0) == 0x00000030)
219 cpu_arch = CPU_ARCH_ARMv7;
220 else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
221 (mmfr0 & 0x000000f0) == 0x00000020)
222 cpu_arch = CPU_ARCH_ARMv6;
223 else
224 cpu_arch = CPU_ARCH_UNKNOWN;
225 } else
226 cpu_arch = CPU_ARCH_UNKNOWN;
1da177e4
LT
227
228 return cpu_arch;
229}
230
c0e95878
RK
231static void __init cacheid_init(void)
232{
233 unsigned int cachetype = read_cpuid_cachetype();
234 unsigned int arch = cpu_architecture();
235
236 if (arch >= CPU_ARCH_ARMv7) {
237 cacheid = CACHEID_VIPT_NONALIASING;
238 if ((cachetype & (3 << 14)) == 1 << 14)
239 cacheid |= CACHEID_ASID_TAGGED;
240 } else if (arch >= CPU_ARCH_ARMv6) {
241 if (cachetype & (1 << 23))
242 cacheid = CACHEID_VIPT_ALIASING;
243 else
244 cacheid = CACHEID_VIPT_NONALIASING;
245 } else {
246 cacheid = CACHEID_VIVT;
247 }
2b4ae1f1
RK
248
249 printk("CPU: %s data cache, %s instruction cache\n",
250 cache_is_vivt() ? "VIVT" :
251 cache_is_vipt_aliasing() ? "VIPT aliasing" :
252 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
253 cache_is_vivt() ? "VIVT" :
254 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
255 cache_is_vipt_aliasing() ? "VIPT aliasing" :
256 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
c0e95878
RK
257}
258
1da177e4
LT
259/*
260 * These functions re-use the assembly code in head.S, which
261 * already provide the required functionality.
262 */
0f44ba1d 263extern struct proc_info_list *lookup_processor_type(unsigned int);
1da177e4
LT
264extern struct machine_desc *lookup_machine_type(unsigned int);
265
266static void __init setup_processor(void)
267{
268 struct proc_info_list *list;
269
270 /*
271 * locate processor in the list of supported processor
272 * types. The linker builds this table for us from the
273 * entries in arch/arm/mm/proc-*.S
274 */
0ba8b9b2 275 list = lookup_processor_type(read_cpuid_id());
1da177e4
LT
276 if (!list) {
277 printk("CPU configuration botched (ID %08x), unable "
0ba8b9b2 278 "to continue.\n", read_cpuid_id());
1da177e4
LT
279 while (1);
280 }
281
282 cpu_name = list->cpu_name;
283
284#ifdef MULTI_CPU
285 processor = *list->proc;
286#endif
287#ifdef MULTI_TLB
288 cpu_tlb = *list->tlb;
289#endif
290#ifdef MULTI_USER
291 cpu_user = *list->user;
292#endif
293#ifdef MULTI_CACHE
294 cpu_cache = *list->cache;
295#endif
296
4e19025b 297 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
0ba8b9b2 298 cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
264edb35 299 proc_arch[cpu_architecture()], cr_alignment);
1da177e4 300
96b644bd 301 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
1da177e4
LT
302 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
303 elf_hwcap = list->elf_hwcap;
adeff422
CM
304#ifndef CONFIG_ARM_THUMB
305 elf_hwcap &= ~HWCAP_THUMB;
306#endif
1da177e4 307
c0e95878 308 cacheid_init();
1da177e4
LT
309 cpu_proc_init();
310}
311
ccea7a19
RK
312/*
313 * cpu_init - initialise one CPU.
314 *
90f1e084 315 * cpu_init sets up the per-CPU stacks.
ccea7a19 316 */
36c5ed23 317void cpu_init(void)
ccea7a19
RK
318{
319 unsigned int cpu = smp_processor_id();
320 struct stack *stk = &stacks[cpu];
321
322 if (cpu >= NR_CPUS) {
323 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
324 BUG();
325 }
326
ccea7a19
RK
327 /*
328 * setup stacks for re-entrant exception handlers
329 */
330 __asm__ (
331 "msr cpsr_c, %1\n\t"
332 "add sp, %0, %2\n\t"
333 "msr cpsr_c, %3\n\t"
334 "add sp, %0, %4\n\t"
335 "msr cpsr_c, %5\n\t"
336 "add sp, %0, %6\n\t"
337 "msr cpsr_c, %7"
338 :
339 : "r" (stk),
340 "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
341 "I" (offsetof(struct stack, irq[0])),
342 "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
343 "I" (offsetof(struct stack, abt[0])),
344 "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
345 "I" (offsetof(struct stack, und[0])),
aaaa3f9e
CM
346 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
347 : "r14");
ccea7a19
RK
348}
349
1da177e4
LT
350static struct machine_desc * __init setup_machine(unsigned int nr)
351{
352 struct machine_desc *list;
353
354 /*
355 * locate machine in the list of supported machines.
356 */
357 list = lookup_machine_type(nr);
358 if (!list) {
359 printk("Machine configuration botched (nr %d), unable "
360 "to continue.\n", nr);
361 while (1);
362 }
363
364 printk("Machine: %s\n", list->name);
365
366 return list;
367}
368
4b5f32ce 369static int __init arm_add_memory(unsigned long start, unsigned long size)
3a669411 370{
4b5f32ce
NP
371 struct membank *bank = &meminfo.bank[meminfo.nr_banks];
372
373 if (meminfo.nr_banks >= NR_BANKS) {
374 printk(KERN_CRIT "NR_BANKS too low, "
375 "ignoring memory at %#lx\n", start);
376 return -EINVAL;
377 }
05f96ef1 378
3a669411
RK
379 /*
380 * Ensure that start/size are aligned to a page boundary.
381 * Size is appropriately rounded down, start is rounded up.
382 */
383 size -= start & ~PAGE_MASK;
05f96ef1
RK
384 bank->start = PAGE_ALIGN(start);
385 bank->size = size & PAGE_MASK;
386 bank->node = PHYS_TO_NID(start);
4b5f32ce
NP
387
388 /*
389 * Check whether this memory region has non-zero size or
390 * invalid node number.
391 */
392 if (bank->size == 0 || bank->node >= MAX_NUMNODES)
393 return -EINVAL;
394
395 meminfo.nr_banks++;
396 return 0;
3a669411
RK
397}
398
1da177e4
LT
399/*
400 * Pick out the memory size. We look for mem=size@start,
401 * where start and size are "size[KkMm]"
402 */
403static void __init early_mem(char **p)
404{
405 static int usermem __initdata = 0;
406 unsigned long size, start;
407
408 /*
409 * If the user specifies memory size, we
410 * blow away any automatically generated
411 * size.
412 */
413 if (usermem == 0) {
414 usermem = 1;
415 meminfo.nr_banks = 0;
416 }
417
418 start = PHYS_OFFSET;
419 size = memparse(*p, p);
420 if (**p == '@')
421 start = memparse(*p + 1, p);
422
1c97b73e 423 arm_add_memory(start, size);
1da177e4
LT
424}
425__early_param("mem=", early_mem);
426
427/*
428 * Initial parsing of the command line.
429 */
430static void __init parse_cmdline(char **cmdline_p, char *from)
431{
432 char c = ' ', *to = command_line;
433 int len = 0;
434
435 for (;;) {
436 if (c == ' ') {
437 extern struct early_params __early_begin, __early_end;
438 struct early_params *p;
439
440 for (p = &__early_begin; p < &__early_end; p++) {
09d9bae0 441 int arglen = strlen(p->arg);
1da177e4 442
09d9bae0 443 if (memcmp(from, p->arg, arglen) == 0) {
1da177e4
LT
444 if (to != command_line)
445 to -= 1;
09d9bae0 446 from += arglen;
1da177e4
LT
447 p->fn(&from);
448
449 while (*from != ' ' && *from != '\0')
450 from++;
451 break;
452 }
453 }
454 }
455 c = *from++;
456 if (!c)
457 break;
458 if (COMMAND_LINE_SIZE <= ++len)
459 break;
460 *to++ = c;
461 }
462 *to = '\0';
463 *cmdline_p = command_line;
464}
465
466static void __init
467setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
468{
469#ifdef CONFIG_BLK_DEV_RAM
470 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
471
472 rd_image_start = image_start;
473 rd_prompt = prompt;
474 rd_doload = doload;
475
476 if (rd_sz)
477 rd_size = rd_sz;
478#endif
479}
480
481static void __init
482request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
483{
484 struct resource *res;
485 int i;
486
37efe642
RK
487 kernel_code.start = virt_to_phys(_text);
488 kernel_code.end = virt_to_phys(_etext - 1);
489 kernel_data.start = virt_to_phys(_data);
490 kernel_data.end = virt_to_phys(_end - 1);
1da177e4
LT
491
492 for (i = 0; i < mi->nr_banks; i++) {
1da177e4
LT
493 if (mi->bank[i].size == 0)
494 continue;
495
1da177e4
LT
496 res = alloc_bootmem_low(sizeof(*res));
497 res->name = "System RAM";
3319f5e5
NP
498 res->start = mi->bank[i].start;
499 res->end = mi->bank[i].start + mi->bank[i].size - 1;
1da177e4
LT
500 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
501
502 request_resource(&iomem_resource, res);
503
504 if (kernel_code.start >= res->start &&
505 kernel_code.end <= res->end)
506 request_resource(res, &kernel_code);
507 if (kernel_data.start >= res->start &&
508 kernel_data.end <= res->end)
509 request_resource(res, &kernel_data);
510 }
511
512 if (mdesc->video_start) {
513 video_ram.start = mdesc->video_start;
514 video_ram.end = mdesc->video_end;
515 request_resource(&iomem_resource, &video_ram);
516 }
517
518 /*
519 * Some machines don't have the possibility of ever
520 * possessing lp0, lp1 or lp2
521 */
522 if (mdesc->reserve_lp0)
523 request_resource(&ioport_resource, &lp0);
524 if (mdesc->reserve_lp1)
525 request_resource(&ioport_resource, &lp1);
526 if (mdesc->reserve_lp2)
527 request_resource(&ioport_resource, &lp2);
528}
529
530/*
531 * Tag parsing.
532 *
533 * This is the new way of passing data to the kernel at boot time. Rather
534 * than passing a fixed inflexible structure to the kernel, we pass a list
535 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
536 * tag for the list to be recognised (to distinguish the tagged list from
537 * a param_struct). The list is terminated with a zero-length tag (this tag
538 * is not parsed in any way).
539 */
540static int __init parse_tag_core(const struct tag *tag)
541{
542 if (tag->hdr.size > 2) {
543 if ((tag->u.core.flags & 1) == 0)
544 root_mountflags &= ~MS_RDONLY;
545 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
546 }
547 return 0;
548}
549
550__tagtable(ATAG_CORE, parse_tag_core);
551
552static int __init parse_tag_mem32(const struct tag *tag)
553{
4b5f32ce 554 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
1da177e4
LT
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
37efe642
RK
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;
1da177e4 722
cd81899a
ABL
723 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
724 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
1da177e4 725 parse_cmdline(cmdline_p, from);
4b5f32ce 726 paging_init(mdesc);
1da177e4
LT
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",
4369ae16 780 "thumbee",
2bedbdf4 781 "neon",
1da177e4
LT
782 NULL
783};
784
1da177e4
LT
785static int c_show(struct seq_file *m, void *v)
786{
787 int i;
788
789 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
0ba8b9b2 790 cpu_name, read_cpuid_id() & 15, elf_platform);
1da177e4
LT
791
792#if defined(CONFIG_SMP)
793 for_each_online_cpu(i) {
15559722
RK
794 /*
795 * glibc reads /proc/cpuinfo to determine the number of
796 * online processors, looking for lines beginning with
797 * "processor". Give glibc what it expects.
798 */
799 seq_printf(m, "processor\t: %d\n", i);
1da177e4
LT
800 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
801 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
802 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
803 }
804#else /* CONFIG_SMP */
805 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
806 loops_per_jiffy / (500000/HZ),
807 (loops_per_jiffy / (5000/HZ)) % 100);
808#endif
809
810 /* dump out the processor features */
811 seq_puts(m, "Features\t: ");
812
813 for (i = 0; hwcap_str[i]; i++)
814 if (elf_hwcap & (1 << i))
815 seq_printf(m, "%s ", hwcap_str[i]);
816
0ba8b9b2 817 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
1da177e4
LT
818 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
819
0ba8b9b2 820 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
1da177e4 821 /* pre-ARM7 */
0ba8b9b2 822 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
1da177e4 823 } else {
0ba8b9b2 824 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
1da177e4
LT
825 /* ARM7 */
826 seq_printf(m, "CPU variant\t: 0x%02x\n",
0ba8b9b2 827 (read_cpuid_id() >> 16) & 127);
1da177e4
LT
828 } else {
829 /* post-ARM7 */
830 seq_printf(m, "CPU variant\t: 0x%x\n",
0ba8b9b2 831 (read_cpuid_id() >> 20) & 15);
1da177e4
LT
832 }
833 seq_printf(m, "CPU part\t: 0x%03x\n",
0ba8b9b2 834 (read_cpuid_id() >> 4) & 0xfff);
1da177e4 835 }
0ba8b9b2 836 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
1da177e4 837
1da177e4
LT
838 seq_puts(m, "\n");
839
840 seq_printf(m, "Hardware\t: %s\n", machine_name);
841 seq_printf(m, "Revision\t: %04x\n", system_rev);
842 seq_printf(m, "Serial\t\t: %08x%08x\n",
843 system_serial_high, system_serial_low);
844
845 return 0;
846}
847
848static void *c_start(struct seq_file *m, loff_t *pos)
849{
850 return *pos < 1 ? (void *)1 : NULL;
851}
852
853static void *c_next(struct seq_file *m, void *v, loff_t *pos)
854{
855 ++*pos;
856 return NULL;
857}
858
859static void c_stop(struct seq_file *m, void *v)
860{
861}
862
2ffd6e18 863const struct seq_operations cpuinfo_op = {
1da177e4
LT
864 .start = c_start,
865 .next = c_next,
866 .stop = c_stop,
867 .show = c_show
868};