Merge branch 'core/debugobjects' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.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/sections.h>
33 #include <asm/setup.h>
34 #include <asm/mach-types.h>
35 #include <asm/cacheflush.h>
36 #include <asm/cachetype.h>
37 #include <asm/tlbflush.h>
38
39 #include <asm/mach/arch.h>
40 #include <asm/mach/irq.h>
41 #include <asm/mach/time.h>
42 #include <asm/traps.h>
43 #include <asm/unwind.h>
44
45 #include "compat.h"
46 #include "atags.h"
47
48 #ifndef MEM_SIZE
49 #define MEM_SIZE (16*1024*1024)
50 #endif
51
52 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
53 char fpe_type[8];
54
55 static int __init fpe_setup(char *line)
56 {
57 memcpy(fpe_type, line, 8);
58 return 1;
59 }
60
61 __setup("fpe=", fpe_setup);
62 #endif
63
64 extern void paging_init(struct machine_desc *desc);
65 extern void reboot_setup(char *str);
66
67 unsigned int processor_id;
68 EXPORT_SYMBOL(processor_id);
69 unsigned int __machine_arch_type;
70 EXPORT_SYMBOL(__machine_arch_type);
71 unsigned int cacheid;
72 EXPORT_SYMBOL(cacheid);
73
74 unsigned int __atags_pointer __initdata;
75
76 unsigned int system_rev;
77 EXPORT_SYMBOL(system_rev);
78
79 unsigned int system_serial_low;
80 EXPORT_SYMBOL(system_serial_low);
81
82 unsigned int system_serial_high;
83 EXPORT_SYMBOL(system_serial_high);
84
85 unsigned int elf_hwcap;
86 EXPORT_SYMBOL(elf_hwcap);
87
88
89 #ifdef MULTI_CPU
90 struct processor processor;
91 #endif
92 #ifdef MULTI_TLB
93 struct cpu_tlb_fns cpu_tlb;
94 #endif
95 #ifdef MULTI_USER
96 struct cpu_user_fns cpu_user;
97 #endif
98 #ifdef MULTI_CACHE
99 struct cpu_cache_fns cpu_cache;
100 #endif
101 #ifdef CONFIG_OUTER_CACHE
102 struct outer_cache_fns outer_cache;
103 #endif
104
105 struct stack {
106 u32 irq[3];
107 u32 abt[3];
108 u32 und[3];
109 } ____cacheline_aligned;
110
111 static struct stack stacks[NR_CPUS];
112
113 char elf_platform[ELF_PLATFORM_SIZE];
114 EXPORT_SYMBOL(elf_platform);
115
116 static const char *cpu_name;
117 static const char *machine_name;
118 static char __initdata command_line[COMMAND_LINE_SIZE];
119
120 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
121 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
122 #define ENDIANNESS ((char)endian_test.l)
123
124 DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
125
126 /*
127 * Standard memory resources
128 */
129 static struct resource mem_res[] = {
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 }
148 };
149
150 #define video_ram mem_res[0]
151 #define kernel_code mem_res[1]
152 #define kernel_data mem_res[2]
153
154 static struct resource io_res[] = {
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 }
173 };
174
175 #define lp0 io_res[0]
176 #define lp1 io_res[1]
177 #define lp2 io_res[2]
178
179 static const char *proc_arch[] = {
180 "undefined/unknown",
181 "3",
182 "4",
183 "4T",
184 "5",
185 "5T",
186 "5TE",
187 "5TEJ",
188 "6TEJ",
189 "7",
190 "?(11)",
191 "?(12)",
192 "?(13)",
193 "?(14)",
194 "?(15)",
195 "?(16)",
196 "?(17)",
197 };
198
199 int cpu_architecture(void)
200 {
201 int cpu_arch;
202
203 if ((read_cpuid_id() & 0x0008f000) == 0) {
204 cpu_arch = CPU_ARCH_UNKNOWN;
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;
209 if (cpu_arch)
210 cpu_arch += CPU_ARCH_ARMv3;
211 } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
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;
228
229 return cpu_arch;
230 }
231
232 static 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_ARMv6) {
238 if ((cachetype & (7 << 29)) == 4 << 29) {
239 /* ARMv7 register format */
240 cacheid = CACHEID_VIPT_NONALIASING;
241 if ((cachetype & (3 << 14)) == 1 << 14)
242 cacheid |= CACHEID_ASID_TAGGED;
243 } else if (cachetype & (1 << 23))
244 cacheid = CACHEID_VIPT_ALIASING;
245 else
246 cacheid = CACHEID_VIPT_NONALIASING;
247 } else {
248 cacheid = CACHEID_VIVT;
249 }
250
251 printk("CPU: %s data cache, %s instruction cache\n",
252 cache_is_vivt() ? "VIVT" :
253 cache_is_vipt_aliasing() ? "VIPT aliasing" :
254 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
255 cache_is_vivt() ? "VIVT" :
256 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
257 cache_is_vipt_aliasing() ? "VIPT aliasing" :
258 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
259 }
260
261 /*
262 * These functions re-use the assembly code in head.S, which
263 * already provide the required functionality.
264 */
265 extern struct proc_info_list *lookup_processor_type(unsigned int);
266 extern struct machine_desc *lookup_machine_type(unsigned int);
267
268 static void __init setup_processor(void)
269 {
270 struct proc_info_list *list;
271
272 /*
273 * locate processor in the list of supported processor
274 * types. The linker builds this table for us from the
275 * entries in arch/arm/mm/proc-*.S
276 */
277 list = lookup_processor_type(read_cpuid_id());
278 if (!list) {
279 printk("CPU configuration botched (ID %08x), unable "
280 "to continue.\n", read_cpuid_id());
281 while (1);
282 }
283
284 cpu_name = list->cpu_name;
285
286 #ifdef MULTI_CPU
287 processor = *list->proc;
288 #endif
289 #ifdef MULTI_TLB
290 cpu_tlb = *list->tlb;
291 #endif
292 #ifdef MULTI_USER
293 cpu_user = *list->user;
294 #endif
295 #ifdef MULTI_CACHE
296 cpu_cache = *list->cache;
297 #endif
298
299 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
300 cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
301 proc_arch[cpu_architecture()], cr_alignment);
302
303 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
304 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
305 elf_hwcap = list->elf_hwcap;
306 #ifndef CONFIG_ARM_THUMB
307 elf_hwcap &= ~HWCAP_THUMB;
308 #endif
309
310 cacheid_init();
311 cpu_proc_init();
312 }
313
314 /*
315 * cpu_init - initialise one CPU.
316 *
317 * cpu_init sets up the per-CPU stacks.
318 */
319 void cpu_init(void)
320 {
321 unsigned int cpu = smp_processor_id();
322 struct stack *stk = &stacks[cpu];
323
324 if (cpu >= NR_CPUS) {
325 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
326 BUG();
327 }
328
329 /*
330 * setup stacks for re-entrant exception handlers
331 */
332 __asm__ (
333 "msr cpsr_c, %1\n\t"
334 "add sp, %0, %2\n\t"
335 "msr cpsr_c, %3\n\t"
336 "add sp, %0, %4\n\t"
337 "msr cpsr_c, %5\n\t"
338 "add sp, %0, %6\n\t"
339 "msr cpsr_c, %7"
340 :
341 : "r" (stk),
342 "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
343 "I" (offsetof(struct stack, irq[0])),
344 "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
345 "I" (offsetof(struct stack, abt[0])),
346 "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
347 "I" (offsetof(struct stack, und[0])),
348 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
349 : "r14");
350 }
351
352 static struct machine_desc * __init setup_machine(unsigned int nr)
353 {
354 struct machine_desc *list;
355
356 /*
357 * locate machine in the list of supported machines.
358 */
359 list = lookup_machine_type(nr);
360 if (!list) {
361 printk("Machine configuration botched (nr %d), unable "
362 "to continue.\n", nr);
363 while (1);
364 }
365
366 printk("Machine: %s\n", list->name);
367
368 return list;
369 }
370
371 static int __init arm_add_memory(unsigned long start, unsigned long size)
372 {
373 struct membank *bank = &meminfo.bank[meminfo.nr_banks];
374
375 if (meminfo.nr_banks >= NR_BANKS) {
376 printk(KERN_CRIT "NR_BANKS too low, "
377 "ignoring memory at %#lx\n", start);
378 return -EINVAL;
379 }
380
381 /*
382 * Ensure that start/size are aligned to a page boundary.
383 * Size is appropriately rounded down, start is rounded up.
384 */
385 size -= start & ~PAGE_MASK;
386 bank->start = PAGE_ALIGN(start);
387 bank->size = size & PAGE_MASK;
388 bank->node = PHYS_TO_NID(start);
389
390 /*
391 * Check whether this memory region has non-zero size or
392 * invalid node number.
393 */
394 if (bank->size == 0 || bank->node >= MAX_NUMNODES)
395 return -EINVAL;
396
397 meminfo.nr_banks++;
398 return 0;
399 }
400
401 /*
402 * Pick out the memory size. We look for mem=size@start,
403 * where start and size are "size[KkMm]"
404 */
405 static void __init early_mem(char **p)
406 {
407 static int usermem __initdata = 0;
408 unsigned long size, start;
409
410 /*
411 * If the user specifies memory size, we
412 * blow away any automatically generated
413 * size.
414 */
415 if (usermem == 0) {
416 usermem = 1;
417 meminfo.nr_banks = 0;
418 }
419
420 start = PHYS_OFFSET;
421 size = memparse(*p, p);
422 if (**p == '@')
423 start = memparse(*p + 1, p);
424
425 arm_add_memory(start, size);
426 }
427 __early_param("mem=", early_mem);
428
429 /*
430 * Initial parsing of the command line.
431 */
432 static void __init parse_cmdline(char **cmdline_p, char *from)
433 {
434 char c = ' ', *to = command_line;
435 int len = 0;
436
437 for (;;) {
438 if (c == ' ') {
439 extern struct early_params __early_begin, __early_end;
440 struct early_params *p;
441
442 for (p = &__early_begin; p < &__early_end; p++) {
443 int arglen = strlen(p->arg);
444
445 if (memcmp(from, p->arg, arglen) == 0) {
446 if (to != command_line)
447 to -= 1;
448 from += arglen;
449 p->fn(&from);
450
451 while (*from != ' ' && *from != '\0')
452 from++;
453 break;
454 }
455 }
456 }
457 c = *from++;
458 if (!c)
459 break;
460 if (COMMAND_LINE_SIZE <= ++len)
461 break;
462 *to++ = c;
463 }
464 *to = '\0';
465 *cmdline_p = command_line;
466 }
467
468 static void __init
469 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
470 {
471 #ifdef CONFIG_BLK_DEV_RAM
472 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
473
474 rd_image_start = image_start;
475 rd_prompt = prompt;
476 rd_doload = doload;
477
478 if (rd_sz)
479 rd_size = rd_sz;
480 #endif
481 }
482
483 static void __init
484 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
485 {
486 struct resource *res;
487 int i;
488
489 kernel_code.start = virt_to_phys(_text);
490 kernel_code.end = virt_to_phys(_etext - 1);
491 kernel_data.start = virt_to_phys(_data);
492 kernel_data.end = virt_to_phys(_end - 1);
493
494 for (i = 0; i < mi->nr_banks; i++) {
495 if (mi->bank[i].size == 0)
496 continue;
497
498 res = alloc_bootmem_low(sizeof(*res));
499 res->name = "System RAM";
500 res->start = mi->bank[i].start;
501 res->end = mi->bank[i].start + mi->bank[i].size - 1;
502 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
503
504 request_resource(&iomem_resource, res);
505
506 if (kernel_code.start >= res->start &&
507 kernel_code.end <= res->end)
508 request_resource(res, &kernel_code);
509 if (kernel_data.start >= res->start &&
510 kernel_data.end <= res->end)
511 request_resource(res, &kernel_data);
512 }
513
514 if (mdesc->video_start) {
515 video_ram.start = mdesc->video_start;
516 video_ram.end = mdesc->video_end;
517 request_resource(&iomem_resource, &video_ram);
518 }
519
520 /*
521 * Some machines don't have the possibility of ever
522 * possessing lp0, lp1 or lp2
523 */
524 if (mdesc->reserve_lp0)
525 request_resource(&ioport_resource, &lp0);
526 if (mdesc->reserve_lp1)
527 request_resource(&ioport_resource, &lp1);
528 if (mdesc->reserve_lp2)
529 request_resource(&ioport_resource, &lp2);
530 }
531
532 /*
533 * Tag parsing.
534 *
535 * This is the new way of passing data to the kernel at boot time. Rather
536 * than passing a fixed inflexible structure to the kernel, we pass a list
537 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
538 * tag for the list to be recognised (to distinguish the tagged list from
539 * a param_struct). The list is terminated with a zero-length tag (this tag
540 * is not parsed in any way).
541 */
542 static int __init parse_tag_core(const struct tag *tag)
543 {
544 if (tag->hdr.size > 2) {
545 if ((tag->u.core.flags & 1) == 0)
546 root_mountflags &= ~MS_RDONLY;
547 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
548 }
549 return 0;
550 }
551
552 __tagtable(ATAG_CORE, parse_tag_core);
553
554 static int __init parse_tag_mem32(const struct tag *tag)
555 {
556 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
557 }
558
559 __tagtable(ATAG_MEM, parse_tag_mem32);
560
561 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
562 struct screen_info screen_info = {
563 .orig_video_lines = 30,
564 .orig_video_cols = 80,
565 .orig_video_mode = 0,
566 .orig_video_ega_bx = 0,
567 .orig_video_isVGA = 1,
568 .orig_video_points = 8
569 };
570
571 static int __init parse_tag_videotext(const struct tag *tag)
572 {
573 screen_info.orig_x = tag->u.videotext.x;
574 screen_info.orig_y = tag->u.videotext.y;
575 screen_info.orig_video_page = tag->u.videotext.video_page;
576 screen_info.orig_video_mode = tag->u.videotext.video_mode;
577 screen_info.orig_video_cols = tag->u.videotext.video_cols;
578 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
579 screen_info.orig_video_lines = tag->u.videotext.video_lines;
580 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
581 screen_info.orig_video_points = tag->u.videotext.video_points;
582 return 0;
583 }
584
585 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
586 #endif
587
588 static int __init parse_tag_ramdisk(const struct tag *tag)
589 {
590 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
591 (tag->u.ramdisk.flags & 2) == 0,
592 tag->u.ramdisk.start, tag->u.ramdisk.size);
593 return 0;
594 }
595
596 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
597
598 static int __init parse_tag_serialnr(const struct tag *tag)
599 {
600 system_serial_low = tag->u.serialnr.low;
601 system_serial_high = tag->u.serialnr.high;
602 return 0;
603 }
604
605 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
606
607 static int __init parse_tag_revision(const struct tag *tag)
608 {
609 system_rev = tag->u.revision.rev;
610 return 0;
611 }
612
613 __tagtable(ATAG_REVISION, parse_tag_revision);
614
615 static int __init parse_tag_cmdline(const struct tag *tag)
616 {
617 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
618 return 0;
619 }
620
621 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
622
623 /*
624 * Scan the tag table for this tag, and call its parse function.
625 * The tag table is built by the linker from all the __tagtable
626 * declarations.
627 */
628 static int __init parse_tag(const struct tag *tag)
629 {
630 extern struct tagtable __tagtable_begin, __tagtable_end;
631 struct tagtable *t;
632
633 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
634 if (tag->hdr.tag == t->tag) {
635 t->parse(tag);
636 break;
637 }
638
639 return t < &__tagtable_end;
640 }
641
642 /*
643 * Parse all tags in the list, checking both the global and architecture
644 * specific tag tables.
645 */
646 static void __init parse_tags(const struct tag *t)
647 {
648 for (; t->hdr.size; t = tag_next(t))
649 if (!parse_tag(t))
650 printk(KERN_WARNING
651 "Ignoring unrecognised tag 0x%08x\n",
652 t->hdr.tag);
653 }
654
655 /*
656 * This holds our defaults.
657 */
658 static struct init_tags {
659 struct tag_header hdr1;
660 struct tag_core core;
661 struct tag_header hdr2;
662 struct tag_mem32 mem;
663 struct tag_header hdr3;
664 } init_tags __initdata = {
665 { tag_size(tag_core), ATAG_CORE },
666 { 1, PAGE_SIZE, 0xff },
667 { tag_size(tag_mem32), ATAG_MEM },
668 { MEM_SIZE, PHYS_OFFSET },
669 { 0, ATAG_NONE }
670 };
671
672 static void (*init_machine)(void) __initdata;
673
674 static int __init customize_machine(void)
675 {
676 /* customizes platform devices, or adds new ones */
677 if (init_machine)
678 init_machine();
679 return 0;
680 }
681 arch_initcall(customize_machine);
682
683 void __init setup_arch(char **cmdline_p)
684 {
685 struct tag *tags = (struct tag *)&init_tags;
686 struct machine_desc *mdesc;
687 char *from = default_command_line;
688
689 unwind_init();
690
691 setup_processor();
692 mdesc = setup_machine(machine_arch_type);
693 machine_name = mdesc->name;
694
695 if (mdesc->soft_reboot)
696 reboot_setup("s");
697
698 if (__atags_pointer)
699 tags = phys_to_virt(__atags_pointer);
700 else if (mdesc->boot_params)
701 tags = phys_to_virt(mdesc->boot_params);
702
703 /*
704 * If we have the old style parameters, convert them to
705 * a tag list.
706 */
707 if (tags->hdr.tag != ATAG_CORE)
708 convert_to_tag_list(tags);
709 if (tags->hdr.tag != ATAG_CORE)
710 tags = (struct tag *)&init_tags;
711
712 if (mdesc->fixup)
713 mdesc->fixup(mdesc, tags, &from, &meminfo);
714
715 if (tags->hdr.tag == ATAG_CORE) {
716 if (meminfo.nr_banks != 0)
717 squash_mem_tags(tags);
718 save_atags(tags);
719 parse_tags(tags);
720 }
721
722 init_mm.start_code = (unsigned long) _text;
723 init_mm.end_code = (unsigned long) _etext;
724 init_mm.end_data = (unsigned long) _edata;
725 init_mm.brk = (unsigned long) _end;
726
727 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
728 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
729 parse_cmdline(cmdline_p, from);
730 paging_init(mdesc);
731 request_standard_resources(&meminfo, mdesc);
732
733 #ifdef CONFIG_SMP
734 smp_init_cpus();
735 #endif
736
737 cpu_init();
738
739 /*
740 * Set up various architecture-specific pointers
741 */
742 init_arch_irq = mdesc->init_irq;
743 system_timer = mdesc->timer;
744 init_machine = mdesc->init_machine;
745
746 #ifdef CONFIG_VT
747 #if defined(CONFIG_VGA_CONSOLE)
748 conswitchp = &vga_con;
749 #elif defined(CONFIG_DUMMY_CONSOLE)
750 conswitchp = &dummy_con;
751 #endif
752 #endif
753 early_trap_init();
754 }
755
756
757 static int __init topology_init(void)
758 {
759 int cpu;
760
761 for_each_possible_cpu(cpu) {
762 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
763 cpuinfo->cpu.hotpluggable = 1;
764 register_cpu(&cpuinfo->cpu, cpu);
765 }
766
767 return 0;
768 }
769
770 subsys_initcall(topology_init);
771
772 static const char *hwcap_str[] = {
773 "swp",
774 "half",
775 "thumb",
776 "26bit",
777 "fastmult",
778 "fpa",
779 "vfp",
780 "edsp",
781 "java",
782 "iwmmxt",
783 "crunch",
784 "thumbee",
785 "neon",
786 "vfpv3",
787 "vfpv3d16",
788 NULL
789 };
790
791 static int c_show(struct seq_file *m, void *v)
792 {
793 int i;
794
795 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
796 cpu_name, read_cpuid_id() & 15, elf_platform);
797
798 #if defined(CONFIG_SMP)
799 for_each_online_cpu(i) {
800 /*
801 * glibc reads /proc/cpuinfo to determine the number of
802 * online processors, looking for lines beginning with
803 * "processor". Give glibc what it expects.
804 */
805 seq_printf(m, "processor\t: %d\n", i);
806 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
807 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
808 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
809 }
810 #else /* CONFIG_SMP */
811 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
812 loops_per_jiffy / (500000/HZ),
813 (loops_per_jiffy / (5000/HZ)) % 100);
814 #endif
815
816 /* dump out the processor features */
817 seq_puts(m, "Features\t: ");
818
819 for (i = 0; hwcap_str[i]; i++)
820 if (elf_hwcap & (1 << i))
821 seq_printf(m, "%s ", hwcap_str[i]);
822
823 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
824 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
825
826 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
827 /* pre-ARM7 */
828 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
829 } else {
830 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
831 /* ARM7 */
832 seq_printf(m, "CPU variant\t: 0x%02x\n",
833 (read_cpuid_id() >> 16) & 127);
834 } else {
835 /* post-ARM7 */
836 seq_printf(m, "CPU variant\t: 0x%x\n",
837 (read_cpuid_id() >> 20) & 15);
838 }
839 seq_printf(m, "CPU part\t: 0x%03x\n",
840 (read_cpuid_id() >> 4) & 0xfff);
841 }
842 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
843
844 seq_puts(m, "\n");
845
846 seq_printf(m, "Hardware\t: %s\n", machine_name);
847 seq_printf(m, "Revision\t: %04x\n", system_rev);
848 seq_printf(m, "Serial\t\t: %08x%08x\n",
849 system_serial_high, system_serial_low);
850
851 return 0;
852 }
853
854 static void *c_start(struct seq_file *m, loff_t *pos)
855 {
856 return *pos < 1 ? (void *)1 : NULL;
857 }
858
859 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
860 {
861 ++*pos;
862 return NULL;
863 }
864
865 static void c_stop(struct seq_file *m, void *v)
866 {
867 }
868
869 const struct seq_operations cpuinfo_op = {
870 .start = c_start,
871 .next = c_next,
872 .stop = c_stop,
873 .show = c_show
874 };
This page took 0.047442 seconds and 6 git commands to generate.