4f6ae06d085564c58a262396669c28509f3e8e49
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / kernel / setup.c
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 */
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>
20 #include <linux/screen_info.h>
21 #include <linux/init.h>
22 #include <linux/root_dev.h>
23 #include <linux/cpu.h>
24 #include <linux/interrupt.h>
25 #include <linux/smp.h>
26 #include <linux/fs.h>
27
28 #include <asm/cpu.h>
29 #include <asm/cputype.h>
30 #include <asm/elf.h>
31 #include <asm/procinfo.h>
32 #include <asm/setup.h>
33 #include <asm/mach-types.h>
34 #include <asm/cacheflush.h>
35 #include <asm/cachetype.h>
36 #include <asm/tlbflush.h>
37
38 #include <asm/mach/arch.h>
39 #include <asm/mach/irq.h>
40 #include <asm/mach/time.h>
41 #include <asm/traps.h>
42
43 #include "compat.h"
44 #include "atags.h"
45
46 #ifndef MEM_SIZE
47 #define MEM_SIZE (16*1024*1024)
48 #endif
49
50 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
51 char fpe_type[8];
52
53 static 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
62 extern void paging_init(struct machine_desc *desc);
63 extern void reboot_setup(char *str);
64 extern void _text, _etext, __data_start, _edata, _end;
65
66 unsigned int processor_id;
67 EXPORT_SYMBOL(processor_id);
68 unsigned int __machine_arch_type;
69 EXPORT_SYMBOL(__machine_arch_type);
70 unsigned int cacheid;
71 EXPORT_SYMBOL(cacheid);
72
73 unsigned int __atags_pointer __initdata;
74
75 unsigned int system_rev;
76 EXPORT_SYMBOL(system_rev);
77
78 unsigned int system_serial_low;
79 EXPORT_SYMBOL(system_serial_low);
80
81 unsigned int system_serial_high;
82 EXPORT_SYMBOL(system_serial_high);
83
84 unsigned int elf_hwcap;
85 EXPORT_SYMBOL(elf_hwcap);
86
87
88 #ifdef MULTI_CPU
89 struct processor processor;
90 #endif
91 #ifdef MULTI_TLB
92 struct cpu_tlb_fns cpu_tlb;
93 #endif
94 #ifdef MULTI_USER
95 struct cpu_user_fns cpu_user;
96 #endif
97 #ifdef MULTI_CACHE
98 struct cpu_cache_fns cpu_cache;
99 #endif
100 #ifdef CONFIG_OUTER_CACHE
101 struct outer_cache_fns outer_cache;
102 #endif
103
104 struct stack {
105 u32 irq[3];
106 u32 abt[3];
107 u32 und[3];
108 } ____cacheline_aligned;
109
110 static struct stack stacks[NR_CPUS];
111
112 char elf_platform[ELF_PLATFORM_SIZE];
113 EXPORT_SYMBOL(elf_platform);
114
115 static const char *cpu_name;
116 static const char *machine_name;
117 static char __initdata command_line[COMMAND_LINE_SIZE];
118
119 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
120 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
121 #define ENDIANNESS ((char)endian_test.l)
122
123 DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
124
125 /*
126 * Standard memory resources
127 */
128 static struct resource mem_res[] = {
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 }
147 };
148
149 #define video_ram mem_res[0]
150 #define kernel_code mem_res[1]
151 #define kernel_data mem_res[2]
152
153 static struct resource io_res[] = {
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 }
172 };
173
174 #define lp0 io_res[0]
175 #define lp1 io_res[1]
176 #define lp2 io_res[2]
177
178 static const char *proc_arch[] = {
179 "undefined/unknown",
180 "3",
181 "4",
182 "4T",
183 "5",
184 "5T",
185 "5TE",
186 "5TEJ",
187 "6TEJ",
188 "7",
189 "?(11)",
190 "?(12)",
191 "?(13)",
192 "?(14)",
193 "?(15)",
194 "?(16)",
195 "?(17)",
196 };
197
198 int cpu_architecture(void)
199 {
200 int cpu_arch;
201
202 if ((read_cpuid_id() & 0x0008f000) == 0) {
203 cpu_arch = CPU_ARCH_UNKNOWN;
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;
208 if (cpu_arch)
209 cpu_arch += CPU_ARCH_ARMv3;
210 } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
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;
227
228 return cpu_arch;
229 }
230
231 static 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 }
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");
257 }
258
259 /*
260 * These functions re-use the assembly code in head.S, which
261 * already provide the required functionality.
262 */
263 extern struct proc_info_list *lookup_processor_type(unsigned int);
264 extern struct machine_desc *lookup_machine_type(unsigned int);
265
266 static 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 */
275 list = lookup_processor_type(read_cpuid_id());
276 if (!list) {
277 printk("CPU configuration botched (ID %08x), unable "
278 "to continue.\n", read_cpuid_id());
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
297 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
298 cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
299 proc_arch[cpu_architecture()], cr_alignment);
300
301 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
302 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
303 elf_hwcap = list->elf_hwcap;
304 #ifndef CONFIG_ARM_THUMB
305 elf_hwcap &= ~HWCAP_THUMB;
306 #endif
307
308 cacheid_init();
309 cpu_proc_init();
310 }
311
312 /*
313 * cpu_init - initialise one CPU.
314 *
315 * cpu_init sets up the per-CPU stacks.
316 */
317 void cpu_init(void)
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
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])),
346 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
347 : "r14");
348 }
349
350 static 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
369 static int __init arm_add_memory(unsigned long start, unsigned long size)
370 {
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 }
378
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;
384 bank->start = PAGE_ALIGN(start);
385 bank->size = size & PAGE_MASK;
386 bank->node = PHYS_TO_NID(start);
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;
397 }
398
399 /*
400 * Pick out the memory size. We look for mem=size@start,
401 * where start and size are "size[KkMm]"
402 */
403 static 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
423 arm_add_memory(start, size);
424 }
425 __early_param("mem=", early_mem);
426
427 /*
428 * Initial parsing of the command line.
429 */
430 static 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++) {
441 int arglen = strlen(p->arg);
442
443 if (memcmp(from, p->arg, arglen) == 0) {
444 if (to != command_line)
445 to -= 1;
446 from += arglen;
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
466 static void __init
467 setup_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
481 static void __init
482 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
483 {
484 struct resource *res;
485 int i;
486
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_start);
490 kernel_data.end = virt_to_phys(&_end - 1);
491
492 for (i = 0; i < mi->nr_banks; i++) {
493 if (mi->bank[i].size == 0)
494 continue;
495
496 res = alloc_bootmem_low(sizeof(*res));
497 res->name = "System RAM";
498 res->start = mi->bank[i].start;
499 res->end = mi->bank[i].start + mi->bank[i].size - 1;
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 */
540 static 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
552 static int __init parse_tag_mem32(const struct tag *tag)
553 {
554 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
555 }
556
557 __tagtable(ATAG_MEM, parse_tag_mem32);
558
559 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
560 struct 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
569 static 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
586 static 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
596 static 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
605 static 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
613 static 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 */
626 static 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 */
644 static 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 */
656 static 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
670 static void (*init_machine)(void) __initdata;
671
672 static 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 }
679 arch_initcall(customize_machine);
680
681 void __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
694 if (__atags_pointer)
695 tags = phys_to_virt(__atags_pointer);
696 else if (mdesc->boot_params)
697 tags = phys_to_virt(mdesc->boot_params);
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);
714 save_atags(tags);
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
723 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
724 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
725 parse_cmdline(cmdline_p, from);
726 paging_init(mdesc);
727 request_standard_resources(&meminfo, mdesc);
728
729 #ifdef CONFIG_SMP
730 smp_init_cpus();
731 #endif
732
733 cpu_init();
734
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
749 early_trap_init();
750 }
751
752
753 static int __init topology_init(void)
754 {
755 int cpu;
756
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 }
762
763 return 0;
764 }
765
766 subsys_initcall(topology_init);
767
768 static const char *hwcap_str[] = {
769 "swp",
770 "half",
771 "thumb",
772 "26bit",
773 "fastmult",
774 "fpa",
775 "vfp",
776 "edsp",
777 "java",
778 "iwmmxt",
779 "crunch",
780 "thumbee",
781 "neon",
782 NULL
783 };
784
785 static 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",
790 cpu_name, read_cpuid_id() & 15, elf_platform);
791
792 #if defined(CONFIG_SMP)
793 for_each_online_cpu(i) {
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);
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
817 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
818 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
819
820 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
821 /* pre-ARM7 */
822 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
823 } else {
824 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
825 /* ARM7 */
826 seq_printf(m, "CPU variant\t: 0x%02x\n",
827 (read_cpuid_id() >> 16) & 127);
828 } else {
829 /* post-ARM7 */
830 seq_printf(m, "CPU variant\t: 0x%x\n",
831 (read_cpuid_id() >> 20) & 15);
832 }
833 seq_printf(m, "CPU part\t: 0x%03x\n",
834 (read_cpuid_id() >> 4) & 0xfff);
835 }
836 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
837
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
848 static void *c_start(struct seq_file *m, loff_t *pos)
849 {
850 return *pos < 1 ? (void *)1 : NULL;
851 }
852
853 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
854 {
855 ++*pos;
856 return NULL;
857 }
858
859 static void c_stop(struct seq_file *m, void *v)
860 {
861 }
862
863 const struct seq_operations cpuinfo_op = {
864 .start = c_start,
865 .next = c_next,
866 .stop = c_stop,
867 .show = c_show
868 };