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