Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[linux/fpc-iii.git] / arch / arm / kernel / setup.c
blob122d999bdc7ca0c8f690355a101f59f1ea8152f8
1 /*
2 * linux/arch/arm/kernel/setup.c
4 * Copyright (C) 1995-2001 Russell King
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>
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>
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>
47 #include "compat.h"
48 #include "atags.h"
49 #include "tcm.h"
51 #ifndef MEM_SIZE
52 #define MEM_SIZE (16*1024*1024)
53 #endif
55 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
56 char fpe_type[8];
58 static int __init fpe_setup(char *line)
60 memcpy(fpe_type, line, 8);
61 return 1;
64 __setup("fpe=", fpe_setup);
65 #endif
67 extern void paging_init(struct machine_desc *desc);
68 extern void reboot_setup(char *str);
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);
77 unsigned int __atags_pointer __initdata;
79 unsigned int system_rev;
80 EXPORT_SYMBOL(system_rev);
82 unsigned int system_serial_low;
83 EXPORT_SYMBOL(system_serial_low);
85 unsigned int system_serial_high;
86 EXPORT_SYMBOL(system_serial_high);
88 unsigned int elf_hwcap;
89 EXPORT_SYMBOL(elf_hwcap);
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
109 struct stack {
110 u32 irq[3];
111 u32 abt[3];
112 u32 und[3];
113 } ____cacheline_aligned;
115 static struct stack stacks[NR_CPUS];
117 char elf_platform[ELF_PLATFORM_SIZE];
118 EXPORT_SYMBOL(elf_platform);
120 static const char *cpu_name;
121 static const char *machine_name;
122 static char __initdata cmd_line[COMMAND_LINE_SIZE];
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)
128 DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
131 * Standard memory resources
133 static struct resource mem_res[] = {
135 .name = "Video RAM",
136 .start = 0,
137 .end = 0,
138 .flags = IORESOURCE_MEM
141 .name = "Kernel text",
142 .start = 0,
143 .end = 0,
144 .flags = IORESOURCE_MEM
147 .name = "Kernel data",
148 .start = 0,
149 .end = 0,
150 .flags = IORESOURCE_MEM
154 #define video_ram mem_res[0]
155 #define kernel_code mem_res[1]
156 #define kernel_data mem_res[2]
158 static struct resource io_res[] = {
160 .name = "reserved",
161 .start = 0x3bc,
162 .end = 0x3be,
163 .flags = IORESOURCE_IO | IORESOURCE_BUSY
166 .name = "reserved",
167 .start = 0x378,
168 .end = 0x37f,
169 .flags = IORESOURCE_IO | IORESOURCE_BUSY
172 .name = "reserved",
173 .start = 0x278,
174 .end = 0x27f,
175 .flags = IORESOURCE_IO | IORESOURCE_BUSY
179 #define lp0 io_res[0]
180 #define lp1 io_res[1]
181 #define lp2 io_res[2]
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)",
203 int cpu_architecture(void)
205 int cpu_arch;
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;
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;
233 return cpu_arch;
236 static void __init cacheid_init(void)
238 unsigned int cachetype = read_cpuid_cachetype();
239 unsigned int arch = cpu_architecture();
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;
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");
266 * These functions re-use the assembly code in head.S, which
267 * already provide the required functionality.
269 extern struct proc_info_list *lookup_processor_type(unsigned int);
270 extern struct machine_desc *lookup_machine_type(unsigned int);
272 static void __init setup_processor(void)
274 struct proc_info_list *list;
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
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);
288 cpu_name = list->cpu_name;
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
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);
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
314 cacheid_init();
315 cpu_proc_init();
319 * cpu_init - initialise one CPU.
321 * cpu_init sets up the per-CPU stacks.
323 void cpu_init(void)
325 unsigned int cpu = smp_processor_id();
326 struct stack *stk = &stacks[cpu];
328 if (cpu >= NR_CPUS) {
329 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
330 BUG();
334 * Define the placement constraint for the inline asm directive below.
335 * In Thumb-2, msr with an immediate value is not allowed.
337 #ifdef CONFIG_THUMB2_KERNEL
338 #define PLC "r"
339 #else
340 #define PLC "I"
341 #endif
344 * setup stacks for re-entrant exception handlers
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"
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");
369 static struct machine_desc * __init setup_machine(unsigned int nr)
371 struct machine_desc *list;
374 * locate machine in the list of supported machines.
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);
383 printk("Machine: %s\n", list->name);
385 return list;
388 static int __init arm_add_memory(unsigned long start, unsigned long size)
390 struct membank *bank = &meminfo.bank[meminfo.nr_banks];
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;
399 * Ensure that start/size are aligned to a page boundary.
400 * Size is appropriately rounded down, start is rounded up.
402 size -= start & ~PAGE_MASK;
403 bank->start = PAGE_ALIGN(start);
404 bank->size = size & PAGE_MASK;
405 bank->node = PHYS_TO_NID(start);
408 * Check whether this memory region has non-zero size or
409 * invalid node number.
411 if (bank->size == 0 || bank->node >= MAX_NUMNODES)
412 return -EINVAL;
414 meminfo.nr_banks++;
415 return 0;
419 * Pick out the memory size. We look for mem=size@start,
420 * where start and size are "size[KkMm]"
422 static int __init early_mem(char *p)
424 static int usermem __initdata = 0;
425 unsigned long size, start;
426 char *endp;
429 * If the user specifies memory size, we
430 * blow away any automatically generated
431 * size.
433 if (usermem == 0) {
434 usermem = 1;
435 meminfo.nr_banks = 0;
438 start = PHYS_OFFSET;
439 size = memparse(p, &endp);
440 if (*endp == '@')
441 start = memparse(endp + 1, NULL);
443 arm_add_memory(start, size);
445 return 0;
447 early_param("mem", early_mem);
449 static void __init
450 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
452 #ifdef CONFIG_BLK_DEV_RAM
453 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
455 rd_image_start = image_start;
456 rd_prompt = prompt;
457 rd_doload = doload;
459 if (rd_sz)
460 rd_size = rd_sz;
461 #endif
464 static void __init
465 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
467 struct resource *res;
468 int i;
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);
475 for (i = 0; i < mi->nr_banks; i++) {
476 if (mi->bank[i].size == 0)
477 continue;
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;
485 request_resource(&iomem_resource, res);
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);
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);
502 * Some machines don't have the possibility of ever
503 * possessing lp0, lp1 or lp2
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);
514 * Tag parsing.
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).
523 static int __init parse_tag_core(const struct tag *tag)
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);
530 return 0;
533 __tagtable(ATAG_CORE, parse_tag_core);
535 static int __init parse_tag_mem32(const struct tag *tag)
537 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
540 __tagtable(ATAG_MEM, parse_tag_mem32);
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
552 static int __init parse_tag_videotext(const struct tag *tag)
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;
566 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
567 #endif
569 static int __init parse_tag_ramdisk(const struct tag *tag)
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;
577 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
579 static int __init parse_tag_serialnr(const struct tag *tag)
581 system_serial_low = tag->u.serialnr.low;
582 system_serial_high = tag->u.serialnr.high;
583 return 0;
586 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
588 static int __init parse_tag_revision(const struct tag *tag)
590 system_rev = tag->u.revision.rev;
591 return 0;
594 __tagtable(ATAG_REVISION, parse_tag_revision);
596 #ifndef CONFIG_CMDLINE_FORCE
597 static int __init parse_tag_cmdline(const struct tag *tag)
599 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
600 return 0;
603 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
604 #endif /* CONFIG_CMDLINE_FORCE */
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.
611 static int __init parse_tag(const struct tag *tag)
613 extern struct tagtable __tagtable_begin, __tagtable_end;
614 struct tagtable *t;
616 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
617 if (tag->hdr.tag == t->tag) {
618 t->parse(tag);
619 break;
622 return t < &__tagtable_end;
626 * Parse all tags in the list, checking both the global and architecture
627 * specific tag tables.
629 static void __init parse_tags(const struct tag *t)
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);
639 * This holds our defaults.
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 }
655 static void (*init_machine)(void) __initdata;
657 static int __init customize_machine(void)
659 /* customizes platform devices, or adds new ones */
660 if (init_machine)
661 init_machine();
662 return 0;
664 arch_initcall(customize_machine);
666 void __init setup_arch(char **cmdline_p)
668 struct tag *tags = (struct tag *)&init_tags;
669 struct machine_desc *mdesc;
670 char *from = default_command_line;
672 unwind_init();
674 setup_processor();
675 mdesc = setup_machine(machine_arch_type);
676 machine_name = mdesc->name;
678 if (mdesc->soft_reboot)
679 reboot_setup("s");
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);
687 * If we have the old style parameters, convert them to
688 * a tag list.
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;
695 if (mdesc->fixup)
696 mdesc->fixup(mdesc, tags, &from, &meminfo);
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);
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;
710 /* parse_early_param needs a boot_command_line */
711 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
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;
717 parse_early_param();
719 paging_init(mdesc);
720 request_standard_resources(&meminfo, mdesc);
722 #ifdef CONFIG_SMP
723 smp_init_cpus();
724 #endif
726 cpu_init();
727 tcm_init();
730 * Set up various architecture-specific pointers
732 init_arch_irq = mdesc->init_irq;
733 system_timer = mdesc->timer;
734 init_machine = mdesc->init_machine;
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();
747 static int __init topology_init(void)
749 int cpu;
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);
757 return 0;
759 subsys_initcall(topology_init);
761 #ifdef CONFIG_HAVE_PROC_CPU
762 static int __init proc_cpu_init(void)
764 struct proc_dir_entry *res;
766 res = proc_mkdir("cpu", NULL);
767 if (!res)
768 return -ENOMEM;
769 return 0;
771 fs_initcall(proc_cpu_init);
772 #endif
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
793 static int c_show(struct seq_file *m, void *v)
795 int i;
797 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
798 cpu_name, read_cpuid_id() & 15, elf_platform);
800 #if defined(CONFIG_SMP)
801 for_each_online_cpu(i) {
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.
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);
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
818 /* dump out the processor features */
819 seq_puts(m, "Features\t: ");
821 for (i = 0; hwcap_str[i]; i++)
822 if (elf_hwcap & (1 << i))
823 seq_printf(m, "%s ", hwcap_str[i]);
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()]);
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);
841 seq_printf(m, "CPU part\t: 0x%03x\n",
842 (read_cpuid_id() >> 4) & 0xfff);
844 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
846 seq_puts(m, "\n");
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);
853 return 0;
856 static void *c_start(struct seq_file *m, loff_t *pos)
858 return *pos < 1 ? (void *)1 : NULL;
861 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
863 ++*pos;
864 return NULL;
867 static void c_stop(struct seq_file *m, void *v)
871 const struct seq_operations cpuinfo_op = {
872 .start = c_start,
873 .next = c_next,
874 .stop = c_stop,
875 .show = c_show