Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6/mini2440.git] / arch / arm / kernel / setup.c
blob7049815d66d566e7d89c08fd3c25e33b8c48c995
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/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>
39 #include <asm/mach/arch.h>
40 #include <asm/mach/irq.h>
41 #include <asm/mach/time.h>
42 #include <asm/traps.h>
44 #include "compat.h"
45 #include "atags.h"
47 #ifndef MEM_SIZE
48 #define MEM_SIZE (16*1024*1024)
49 #endif
51 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
52 char fpe_type[8];
54 static int __init fpe_setup(char *line)
56 memcpy(fpe_type, line, 8);
57 return 1;
60 __setup("fpe=", fpe_setup);
61 #endif
63 extern void paging_init(struct machine_desc *desc);
64 extern void reboot_setup(char *str);
66 unsigned int processor_id;
67 EXPORT_SYMBOL(processor_id);
68 unsigned int __machine_arch_type;
69 EXPORT_SYMBOL(__machine_arch_type);
70 unsigned int cacheid;
71 EXPORT_SYMBOL(cacheid);
73 unsigned int __atags_pointer __initdata;
75 unsigned int system_rev;
76 EXPORT_SYMBOL(system_rev);
78 unsigned int system_serial_low;
79 EXPORT_SYMBOL(system_serial_low);
81 unsigned int system_serial_high;
82 EXPORT_SYMBOL(system_serial_high);
84 unsigned int elf_hwcap;
85 EXPORT_SYMBOL(elf_hwcap);
88 #ifdef MULTI_CPU
89 struct processor processor;
90 #endif
91 #ifdef MULTI_TLB
92 struct cpu_tlb_fns cpu_tlb;
93 #endif
94 #ifdef MULTI_USER
95 struct cpu_user_fns cpu_user;
96 #endif
97 #ifdef MULTI_CACHE
98 struct cpu_cache_fns cpu_cache;
99 #endif
100 #ifdef CONFIG_OUTER_CACHE
101 struct outer_cache_fns outer_cache;
102 #endif
104 struct stack {
105 u32 irq[3];
106 u32 abt[3];
107 u32 und[3];
108 } ____cacheline_aligned;
110 static struct stack stacks[NR_CPUS];
112 char elf_platform[ELF_PLATFORM_SIZE];
113 EXPORT_SYMBOL(elf_platform);
115 static const char *cpu_name;
116 static const char *machine_name;
117 static char __initdata command_line[COMMAND_LINE_SIZE];
119 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
120 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
121 #define ENDIANNESS ((char)endian_test.l)
123 DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
126 * Standard memory resources
128 static struct resource mem_res[] = {
130 .name = "Video RAM",
131 .start = 0,
132 .end = 0,
133 .flags = IORESOURCE_MEM
136 .name = "Kernel text",
137 .start = 0,
138 .end = 0,
139 .flags = IORESOURCE_MEM
142 .name = "Kernel data",
143 .start = 0,
144 .end = 0,
145 .flags = IORESOURCE_MEM
149 #define video_ram mem_res[0]
150 #define kernel_code mem_res[1]
151 #define kernel_data mem_res[2]
153 static struct resource io_res[] = {
155 .name = "reserved",
156 .start = 0x3bc,
157 .end = 0x3be,
158 .flags = IORESOURCE_IO | IORESOURCE_BUSY
161 .name = "reserved",
162 .start = 0x378,
163 .end = 0x37f,
164 .flags = IORESOURCE_IO | IORESOURCE_BUSY
167 .name = "reserved",
168 .start = 0x278,
169 .end = 0x27f,
170 .flags = IORESOURCE_IO | IORESOURCE_BUSY
174 #define lp0 io_res[0]
175 #define lp1 io_res[1]
176 #define lp2 io_res[2]
178 static const char *proc_arch[] = {
179 "undefined/unknown",
180 "3",
181 "4",
182 "4T",
183 "5",
184 "5T",
185 "5TE",
186 "5TEJ",
187 "6TEJ",
188 "7",
189 "?(11)",
190 "?(12)",
191 "?(13)",
192 "?(14)",
193 "?(15)",
194 "?(16)",
195 "?(17)",
198 int cpu_architecture(void)
200 int cpu_arch;
202 if ((read_cpuid_id() & 0x0008f000) == 0) {
203 cpu_arch = CPU_ARCH_UNKNOWN;
204 } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
205 cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
206 } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
207 cpu_arch = (read_cpuid_id() >> 16) & 7;
208 if (cpu_arch)
209 cpu_arch += CPU_ARCH_ARMv3;
210 } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
211 unsigned int mmfr0;
213 /* Revised CPUID format. Read the Memory Model Feature
214 * Register 0 and check for VMSAv7 or PMSAv7 */
215 asm("mrc p15, 0, %0, c0, c1, 4"
216 : "=r" (mmfr0));
217 if ((mmfr0 & 0x0000000f) == 0x00000003 ||
218 (mmfr0 & 0x000000f0) == 0x00000030)
219 cpu_arch = CPU_ARCH_ARMv7;
220 else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
221 (mmfr0 & 0x000000f0) == 0x00000020)
222 cpu_arch = CPU_ARCH_ARMv6;
223 else
224 cpu_arch = CPU_ARCH_UNKNOWN;
225 } else
226 cpu_arch = CPU_ARCH_UNKNOWN;
228 return cpu_arch;
231 static void __init cacheid_init(void)
233 unsigned int cachetype = read_cpuid_cachetype();
234 unsigned int arch = cpu_architecture();
236 if (arch >= CPU_ARCH_ARMv7) {
237 cacheid = CACHEID_VIPT_NONALIASING;
238 if ((cachetype & (3 << 14)) == 1 << 14)
239 cacheid |= CACHEID_ASID_TAGGED;
240 } else if (arch >= CPU_ARCH_ARMv6) {
241 if (cachetype & (1 << 23))
242 cacheid = CACHEID_VIPT_ALIASING;
243 else
244 cacheid = CACHEID_VIPT_NONALIASING;
245 } else {
246 cacheid = CACHEID_VIVT;
249 printk("CPU: %s data cache, %s instruction cache\n",
250 cache_is_vivt() ? "VIVT" :
251 cache_is_vipt_aliasing() ? "VIPT aliasing" :
252 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
253 cache_is_vivt() ? "VIVT" :
254 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
255 cache_is_vipt_aliasing() ? "VIPT aliasing" :
256 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
260 * These functions re-use the assembly code in head.S, which
261 * already provide the required functionality.
263 extern struct proc_info_list *lookup_processor_type(unsigned int);
264 extern struct machine_desc *lookup_machine_type(unsigned int);
266 static void __init setup_processor(void)
268 struct proc_info_list *list;
271 * locate processor in the list of supported processor
272 * types. The linker builds this table for us from the
273 * entries in arch/arm/mm/proc-*.S
275 list = lookup_processor_type(read_cpuid_id());
276 if (!list) {
277 printk("CPU configuration botched (ID %08x), unable "
278 "to continue.\n", read_cpuid_id());
279 while (1);
282 cpu_name = list->cpu_name;
284 #ifdef MULTI_CPU
285 processor = *list->proc;
286 #endif
287 #ifdef MULTI_TLB
288 cpu_tlb = *list->tlb;
289 #endif
290 #ifdef MULTI_USER
291 cpu_user = *list->user;
292 #endif
293 #ifdef MULTI_CACHE
294 cpu_cache = *list->cache;
295 #endif
297 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
298 cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
299 proc_arch[cpu_architecture()], cr_alignment);
301 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
302 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
303 elf_hwcap = list->elf_hwcap;
304 #ifndef CONFIG_ARM_THUMB
305 elf_hwcap &= ~HWCAP_THUMB;
306 #endif
308 cacheid_init();
309 cpu_proc_init();
313 * cpu_init - initialise one CPU.
315 * cpu_init sets up the per-CPU stacks.
317 void cpu_init(void)
319 unsigned int cpu = smp_processor_id();
320 struct stack *stk = &stacks[cpu];
322 if (cpu >= NR_CPUS) {
323 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
324 BUG();
328 * setup stacks for re-entrant exception handlers
330 __asm__ (
331 "msr cpsr_c, %1\n\t"
332 "add sp, %0, %2\n\t"
333 "msr cpsr_c, %3\n\t"
334 "add sp, %0, %4\n\t"
335 "msr cpsr_c, %5\n\t"
336 "add sp, %0, %6\n\t"
337 "msr cpsr_c, %7"
339 : "r" (stk),
340 "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
341 "I" (offsetof(struct stack, irq[0])),
342 "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
343 "I" (offsetof(struct stack, abt[0])),
344 "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
345 "I" (offsetof(struct stack, und[0])),
346 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
347 : "r14");
350 static struct machine_desc * __init setup_machine(unsigned int nr)
352 struct machine_desc *list;
355 * locate machine in the list of supported machines.
357 list = lookup_machine_type(nr);
358 if (!list) {
359 printk("Machine configuration botched (nr %d), unable "
360 "to continue.\n", nr);
361 while (1);
364 printk("Machine: %s\n", list->name);
366 return list;
369 static int __init arm_add_memory(unsigned long start, unsigned long size)
371 struct membank *bank = &meminfo.bank[meminfo.nr_banks];
373 if (meminfo.nr_banks >= NR_BANKS) {
374 printk(KERN_CRIT "NR_BANKS too low, "
375 "ignoring memory at %#lx\n", start);
376 return -EINVAL;
380 * Ensure that start/size are aligned to a page boundary.
381 * Size is appropriately rounded down, start is rounded up.
383 size -= start & ~PAGE_MASK;
384 bank->start = PAGE_ALIGN(start);
385 bank->size = size & PAGE_MASK;
386 bank->node = PHYS_TO_NID(start);
389 * Check whether this memory region has non-zero size or
390 * invalid node number.
392 if (bank->size == 0 || bank->node >= MAX_NUMNODES)
393 return -EINVAL;
395 meminfo.nr_banks++;
396 return 0;
400 * Pick out the memory size. We look for mem=size@start,
401 * where start and size are "size[KkMm]"
403 static void __init early_mem(char **p)
405 static int usermem __initdata = 0;
406 unsigned long size, start;
409 * If the user specifies memory size, we
410 * blow away any automatically generated
411 * size.
413 if (usermem == 0) {
414 usermem = 1;
415 meminfo.nr_banks = 0;
418 start = PHYS_OFFSET;
419 size = memparse(*p, p);
420 if (**p == '@')
421 start = memparse(*p + 1, p);
423 arm_add_memory(start, size);
425 __early_param("mem=", early_mem);
428 * Initial parsing of the command line.
430 static void __init parse_cmdline(char **cmdline_p, char *from)
432 char c = ' ', *to = command_line;
433 int len = 0;
435 for (;;) {
436 if (c == ' ') {
437 extern struct early_params __early_begin, __early_end;
438 struct early_params *p;
440 for (p = &__early_begin; p < &__early_end; p++) {
441 int arglen = strlen(p->arg);
443 if (memcmp(from, p->arg, arglen) == 0) {
444 if (to != command_line)
445 to -= 1;
446 from += arglen;
447 p->fn(&from);
449 while (*from != ' ' && *from != '\0')
450 from++;
451 break;
455 c = *from++;
456 if (!c)
457 break;
458 if (COMMAND_LINE_SIZE <= ++len)
459 break;
460 *to++ = c;
462 *to = '\0';
463 *cmdline_p = command_line;
466 static void __init
467 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
469 #ifdef CONFIG_BLK_DEV_RAM
470 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
472 rd_image_start = image_start;
473 rd_prompt = prompt;
474 rd_doload = doload;
476 if (rd_sz)
477 rd_size = rd_sz;
478 #endif
481 static void __init
482 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
484 struct resource *res;
485 int i;
487 kernel_code.start = virt_to_phys(_text);
488 kernel_code.end = virt_to_phys(_etext - 1);
489 kernel_data.start = virt_to_phys(_data);
490 kernel_data.end = virt_to_phys(_end - 1);
492 for (i = 0; i < mi->nr_banks; i++) {
493 if (mi->bank[i].size == 0)
494 continue;
496 res = alloc_bootmem_low(sizeof(*res));
497 res->name = "System RAM";
498 res->start = mi->bank[i].start;
499 res->end = mi->bank[i].start + mi->bank[i].size - 1;
500 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
502 request_resource(&iomem_resource, res);
504 if (kernel_code.start >= res->start &&
505 kernel_code.end <= res->end)
506 request_resource(res, &kernel_code);
507 if (kernel_data.start >= res->start &&
508 kernel_data.end <= res->end)
509 request_resource(res, &kernel_data);
512 if (mdesc->video_start) {
513 video_ram.start = mdesc->video_start;
514 video_ram.end = mdesc->video_end;
515 request_resource(&iomem_resource, &video_ram);
519 * Some machines don't have the possibility of ever
520 * possessing lp0, lp1 or lp2
522 if (mdesc->reserve_lp0)
523 request_resource(&ioport_resource, &lp0);
524 if (mdesc->reserve_lp1)
525 request_resource(&ioport_resource, &lp1);
526 if (mdesc->reserve_lp2)
527 request_resource(&ioport_resource, &lp2);
531 * Tag parsing.
533 * This is the new way of passing data to the kernel at boot time. Rather
534 * than passing a fixed inflexible structure to the kernel, we pass a list
535 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
536 * tag for the list to be recognised (to distinguish the tagged list from
537 * a param_struct). The list is terminated with a zero-length tag (this tag
538 * is not parsed in any way).
540 static int __init parse_tag_core(const struct tag *tag)
542 if (tag->hdr.size > 2) {
543 if ((tag->u.core.flags & 1) == 0)
544 root_mountflags &= ~MS_RDONLY;
545 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
547 return 0;
550 __tagtable(ATAG_CORE, parse_tag_core);
552 static int __init parse_tag_mem32(const struct tag *tag)
554 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
557 __tagtable(ATAG_MEM, parse_tag_mem32);
559 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
560 struct screen_info screen_info = {
561 .orig_video_lines = 30,
562 .orig_video_cols = 80,
563 .orig_video_mode = 0,
564 .orig_video_ega_bx = 0,
565 .orig_video_isVGA = 1,
566 .orig_video_points = 8
569 static int __init parse_tag_videotext(const struct tag *tag)
571 screen_info.orig_x = tag->u.videotext.x;
572 screen_info.orig_y = tag->u.videotext.y;
573 screen_info.orig_video_page = tag->u.videotext.video_page;
574 screen_info.orig_video_mode = tag->u.videotext.video_mode;
575 screen_info.orig_video_cols = tag->u.videotext.video_cols;
576 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
577 screen_info.orig_video_lines = tag->u.videotext.video_lines;
578 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
579 screen_info.orig_video_points = tag->u.videotext.video_points;
580 return 0;
583 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
584 #endif
586 static int __init parse_tag_ramdisk(const struct tag *tag)
588 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
589 (tag->u.ramdisk.flags & 2) == 0,
590 tag->u.ramdisk.start, tag->u.ramdisk.size);
591 return 0;
594 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
596 static int __init parse_tag_serialnr(const struct tag *tag)
598 system_serial_low = tag->u.serialnr.low;
599 system_serial_high = tag->u.serialnr.high;
600 return 0;
603 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
605 static int __init parse_tag_revision(const struct tag *tag)
607 system_rev = tag->u.revision.rev;
608 return 0;
611 __tagtable(ATAG_REVISION, parse_tag_revision);
613 static int __init parse_tag_cmdline(const struct tag *tag)
615 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
616 return 0;
619 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
622 * Scan the tag table for this tag, and call its parse function.
623 * The tag table is built by the linker from all the __tagtable
624 * declarations.
626 static int __init parse_tag(const struct tag *tag)
628 extern struct tagtable __tagtable_begin, __tagtable_end;
629 struct tagtable *t;
631 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
632 if (tag->hdr.tag == t->tag) {
633 t->parse(tag);
634 break;
637 return t < &__tagtable_end;
641 * Parse all tags in the list, checking both the global and architecture
642 * specific tag tables.
644 static void __init parse_tags(const struct tag *t)
646 for (; t->hdr.size; t = tag_next(t))
647 if (!parse_tag(t))
648 printk(KERN_WARNING
649 "Ignoring unrecognised tag 0x%08x\n",
650 t->hdr.tag);
654 * This holds our defaults.
656 static struct init_tags {
657 struct tag_header hdr1;
658 struct tag_core core;
659 struct tag_header hdr2;
660 struct tag_mem32 mem;
661 struct tag_header hdr3;
662 } init_tags __initdata = {
663 { tag_size(tag_core), ATAG_CORE },
664 { 1, PAGE_SIZE, 0xff },
665 { tag_size(tag_mem32), ATAG_MEM },
666 { MEM_SIZE, PHYS_OFFSET },
667 { 0, ATAG_NONE }
670 static void (*init_machine)(void) __initdata;
672 static int __init customize_machine(void)
674 /* customizes platform devices, or adds new ones */
675 if (init_machine)
676 init_machine();
677 return 0;
679 arch_initcall(customize_machine);
681 void __init setup_arch(char **cmdline_p)
683 struct tag *tags = (struct tag *)&init_tags;
684 struct machine_desc *mdesc;
685 char *from = default_command_line;
687 setup_processor();
688 mdesc = setup_machine(machine_arch_type);
689 machine_name = mdesc->name;
691 if (mdesc->soft_reboot)
692 reboot_setup("s");
694 if (__atags_pointer)
695 tags = phys_to_virt(__atags_pointer);
696 else if (mdesc->boot_params)
697 tags = phys_to_virt(mdesc->boot_params);
700 * If we have the old style parameters, convert them to
701 * a tag list.
703 if (tags->hdr.tag != ATAG_CORE)
704 convert_to_tag_list(tags);
705 if (tags->hdr.tag != ATAG_CORE)
706 tags = (struct tag *)&init_tags;
708 if (mdesc->fixup)
709 mdesc->fixup(mdesc, tags, &from, &meminfo);
711 if (tags->hdr.tag == ATAG_CORE) {
712 if (meminfo.nr_banks != 0)
713 squash_mem_tags(tags);
714 save_atags(tags);
715 parse_tags(tags);
718 init_mm.start_code = (unsigned long) _text;
719 init_mm.end_code = (unsigned long) _etext;
720 init_mm.end_data = (unsigned long) _edata;
721 init_mm.brk = (unsigned long) _end;
723 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
724 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
725 parse_cmdline(cmdline_p, from);
726 paging_init(mdesc);
727 request_standard_resources(&meminfo, mdesc);
729 #ifdef CONFIG_SMP
730 smp_init_cpus();
731 #endif
733 cpu_init();
736 * Set up various architecture-specific pointers
738 init_arch_irq = mdesc->init_irq;
739 system_timer = mdesc->timer;
740 init_machine = mdesc->init_machine;
742 #ifdef CONFIG_VT
743 #if defined(CONFIG_VGA_CONSOLE)
744 conswitchp = &vga_con;
745 #elif defined(CONFIG_DUMMY_CONSOLE)
746 conswitchp = &dummy_con;
747 #endif
748 #endif
749 early_trap_init();
753 static int __init topology_init(void)
755 int cpu;
757 for_each_possible_cpu(cpu) {
758 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
759 cpuinfo->cpu.hotpluggable = 1;
760 register_cpu(&cpuinfo->cpu, cpu);
763 return 0;
766 subsys_initcall(topology_init);
768 static const char *hwcap_str[] = {
769 "swp",
770 "half",
771 "thumb",
772 "26bit",
773 "fastmult",
774 "fpa",
775 "vfp",
776 "edsp",
777 "java",
778 "iwmmxt",
779 "crunch",
780 "thumbee",
781 "neon",
782 NULL
785 static int c_show(struct seq_file *m, void *v)
787 int i;
789 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
790 cpu_name, read_cpuid_id() & 15, elf_platform);
792 #if defined(CONFIG_SMP)
793 for_each_online_cpu(i) {
795 * glibc reads /proc/cpuinfo to determine the number of
796 * online processors, looking for lines beginning with
797 * "processor". Give glibc what it expects.
799 seq_printf(m, "processor\t: %d\n", i);
800 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
801 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
802 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
804 #else /* CONFIG_SMP */
805 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
806 loops_per_jiffy / (500000/HZ),
807 (loops_per_jiffy / (5000/HZ)) % 100);
808 #endif
810 /* dump out the processor features */
811 seq_puts(m, "Features\t: ");
813 for (i = 0; hwcap_str[i]; i++)
814 if (elf_hwcap & (1 << i))
815 seq_printf(m, "%s ", hwcap_str[i]);
817 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
818 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
820 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
821 /* pre-ARM7 */
822 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
823 } else {
824 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
825 /* ARM7 */
826 seq_printf(m, "CPU variant\t: 0x%02x\n",
827 (read_cpuid_id() >> 16) & 127);
828 } else {
829 /* post-ARM7 */
830 seq_printf(m, "CPU variant\t: 0x%x\n",
831 (read_cpuid_id() >> 20) & 15);
833 seq_printf(m, "CPU part\t: 0x%03x\n",
834 (read_cpuid_id() >> 4) & 0xfff);
836 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
838 seq_puts(m, "\n");
840 seq_printf(m, "Hardware\t: %s\n", machine_name);
841 seq_printf(m, "Revision\t: %04x\n", system_rev);
842 seq_printf(m, "Serial\t\t: %08x%08x\n",
843 system_serial_high, system_serial_low);
845 return 0;
848 static void *c_start(struct seq_file *m, loff_t *pos)
850 return *pos < 1 ? (void *)1 : NULL;
853 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
855 ++*pos;
856 return NULL;
859 static void c_stop(struct seq_file *m, void *v)
863 const struct seq_operations cpuinfo_op = {
864 .start = c_start,
865 .next = c_next,
866 .stop = c_stop,
867 .show = c_show