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