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