[ARM] Remove cache type printks
[linux-2.6/kvm.git] / arch / arm / kernel / setup.c
blob1939c904dae34deddc46dbdd1b15af2a7e659169
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/setup.h>
33 #include <asm/mach-types.h>
34 #include <asm/cacheflush.h>
35 #include <asm/cachetype.h>
36 #include <asm/tlbflush.h>
38 #include <asm/mach/arch.h>
39 #include <asm/mach/irq.h>
40 #include <asm/mach/time.h>
41 #include <asm/traps.h>
43 #include "compat.h"
44 #include "atags.h"
46 #ifndef MEM_SIZE
47 #define MEM_SIZE (16*1024*1024)
48 #endif
50 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
51 char fpe_type[8];
53 static int __init fpe_setup(char *line)
55 memcpy(fpe_type, line, 8);
56 return 1;
59 __setup("fpe=", fpe_setup);
60 #endif
62 extern void paging_init(struct meminfo *, struct machine_desc *desc);
63 extern void reboot_setup(char *str);
64 extern void _text, _etext, __data_start, _edata, _end;
66 unsigned int processor_id;
67 EXPORT_SYMBOL(processor_id);
68 unsigned int __machine_arch_type;
69 EXPORT_SYMBOL(__machine_arch_type);
71 unsigned int __atags_pointer __initdata;
73 unsigned int system_rev;
74 EXPORT_SYMBOL(system_rev);
76 unsigned int system_serial_low;
77 EXPORT_SYMBOL(system_serial_low);
79 unsigned int system_serial_high;
80 EXPORT_SYMBOL(system_serial_high);
82 unsigned int elf_hwcap;
83 EXPORT_SYMBOL(elf_hwcap);
85 unsigned long __initdata vmalloc_reserve = 128 << 20;
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 struct meminfo meminfo __initdata = { 0, };
116 static const char *cpu_name;
117 static const char *machine_name;
118 static char __initdata command_line[COMMAND_LINE_SIZE];
120 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
121 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
122 #define ENDIANNESS ((char)endian_test.l)
124 DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
127 * Standard memory resources
129 static struct resource mem_res[] = {
131 .name = "Video RAM",
132 .start = 0,
133 .end = 0,
134 .flags = IORESOURCE_MEM
137 .name = "Kernel text",
138 .start = 0,
139 .end = 0,
140 .flags = IORESOURCE_MEM
143 .name = "Kernel data",
144 .start = 0,
145 .end = 0,
146 .flags = IORESOURCE_MEM
150 #define video_ram mem_res[0]
151 #define kernel_code mem_res[1]
152 #define kernel_data mem_res[2]
154 static struct resource io_res[] = {
156 .name = "reserved",
157 .start = 0x3bc,
158 .end = 0x3be,
159 .flags = IORESOURCE_IO | IORESOURCE_BUSY
162 .name = "reserved",
163 .start = 0x378,
164 .end = 0x37f,
165 .flags = IORESOURCE_IO | IORESOURCE_BUSY
168 .name = "reserved",
169 .start = 0x278,
170 .end = 0x27f,
171 .flags = IORESOURCE_IO | IORESOURCE_BUSY
175 #define lp0 io_res[0]
176 #define lp1 io_res[1]
177 #define lp2 io_res[2]
179 static const char *proc_arch[] = {
180 "undefined/unknown",
181 "3",
182 "4",
183 "4T",
184 "5",
185 "5T",
186 "5TE",
187 "5TEJ",
188 "6TEJ",
189 "7",
190 "?(11)",
191 "?(12)",
192 "?(13)",
193 "?(14)",
194 "?(15)",
195 "?(16)",
196 "?(17)",
199 int cpu_architecture(void)
201 int cpu_arch;
203 if ((read_cpuid_id() & 0x0008f000) == 0) {
204 cpu_arch = CPU_ARCH_UNKNOWN;
205 } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
206 cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
207 } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
208 cpu_arch = (read_cpuid_id() >> 16) & 7;
209 if (cpu_arch)
210 cpu_arch += CPU_ARCH_ARMv3;
211 } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
212 unsigned int mmfr0;
214 /* Revised CPUID format. Read the Memory Model Feature
215 * Register 0 and check for VMSAv7 or PMSAv7 */
216 asm("mrc p15, 0, %0, c0, c1, 4"
217 : "=r" (mmfr0));
218 if ((mmfr0 & 0x0000000f) == 0x00000003 ||
219 (mmfr0 & 0x000000f0) == 0x00000030)
220 cpu_arch = CPU_ARCH_ARMv7;
221 else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
222 (mmfr0 & 0x000000f0) == 0x00000020)
223 cpu_arch = CPU_ARCH_ARMv6;
224 else
225 cpu_arch = CPU_ARCH_UNKNOWN;
226 } else
227 cpu_arch = CPU_ARCH_UNKNOWN;
229 return cpu_arch;
233 * These functions re-use the assembly code in head.S, which
234 * already provide the required functionality.
236 extern struct proc_info_list *lookup_processor_type(unsigned int);
237 extern struct machine_desc *lookup_machine_type(unsigned int);
239 static void __init setup_processor(void)
241 struct proc_info_list *list;
244 * locate processor in the list of supported processor
245 * types. The linker builds this table for us from the
246 * entries in arch/arm/mm/proc-*.S
248 list = lookup_processor_type(read_cpuid_id());
249 if (!list) {
250 printk("CPU configuration botched (ID %08x), unable "
251 "to continue.\n", read_cpuid_id());
252 while (1);
255 cpu_name = list->cpu_name;
257 #ifdef MULTI_CPU
258 processor = *list->proc;
259 #endif
260 #ifdef MULTI_TLB
261 cpu_tlb = *list->tlb;
262 #endif
263 #ifdef MULTI_USER
264 cpu_user = *list->user;
265 #endif
266 #ifdef MULTI_CACHE
267 cpu_cache = *list->cache;
268 #endif
270 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
271 cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
272 proc_arch[cpu_architecture()], cr_alignment);
274 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
275 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
276 elf_hwcap = list->elf_hwcap;
277 #ifndef CONFIG_ARM_THUMB
278 elf_hwcap &= ~HWCAP_THUMB;
279 #endif
281 cpu_proc_init();
285 * cpu_init - initialise one CPU.
287 * cpu_init sets up the per-CPU stacks.
289 void cpu_init(void)
291 unsigned int cpu = smp_processor_id();
292 struct stack *stk = &stacks[cpu];
294 if (cpu >= NR_CPUS) {
295 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
296 BUG();
300 * setup stacks for re-entrant exception handlers
302 __asm__ (
303 "msr cpsr_c, %1\n\t"
304 "add sp, %0, %2\n\t"
305 "msr cpsr_c, %3\n\t"
306 "add sp, %0, %4\n\t"
307 "msr cpsr_c, %5\n\t"
308 "add sp, %0, %6\n\t"
309 "msr cpsr_c, %7"
311 : "r" (stk),
312 "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
313 "I" (offsetof(struct stack, irq[0])),
314 "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
315 "I" (offsetof(struct stack, abt[0])),
316 "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
317 "I" (offsetof(struct stack, und[0])),
318 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
319 : "r14");
322 static struct machine_desc * __init setup_machine(unsigned int nr)
324 struct machine_desc *list;
327 * locate machine in the list of supported machines.
329 list = lookup_machine_type(nr);
330 if (!list) {
331 printk("Machine configuration botched (nr %d), unable "
332 "to continue.\n", nr);
333 while (1);
336 printk("Machine: %s\n", list->name);
338 return list;
341 static void __init arm_add_memory(unsigned long start, unsigned long size)
343 struct membank *bank;
346 * Ensure that start/size are aligned to a page boundary.
347 * Size is appropriately rounded down, start is rounded up.
349 size -= start & ~PAGE_MASK;
351 bank = &meminfo.bank[meminfo.nr_banks++];
353 bank->start = PAGE_ALIGN(start);
354 bank->size = size & PAGE_MASK;
355 bank->node = PHYS_TO_NID(start);
359 * Pick out the memory size. We look for mem=size@start,
360 * where start and size are "size[KkMm]"
362 static void __init early_mem(char **p)
364 static int usermem __initdata = 0;
365 unsigned long size, start;
368 * If the user specifies memory size, we
369 * blow away any automatically generated
370 * size.
372 if (usermem == 0) {
373 usermem = 1;
374 meminfo.nr_banks = 0;
377 start = PHYS_OFFSET;
378 size = memparse(*p, p);
379 if (**p == '@')
380 start = memparse(*p + 1, p);
382 arm_add_memory(start, size);
384 __early_param("mem=", early_mem);
387 * vmalloc=size forces the vmalloc area to be exactly 'size'
388 * bytes. This can be used to increase (or decrease) the vmalloc
389 * area - the default is 128m.
391 static void __init early_vmalloc(char **arg)
393 vmalloc_reserve = memparse(*arg, arg);
395 __early_param("vmalloc=", early_vmalloc);
398 * Initial parsing of the command line.
400 static void __init parse_cmdline(char **cmdline_p, char *from)
402 char c = ' ', *to = command_line;
403 int len = 0;
405 for (;;) {
406 if (c == ' ') {
407 extern struct early_params __early_begin, __early_end;
408 struct early_params *p;
410 for (p = &__early_begin; p < &__early_end; p++) {
411 int arglen = strlen(p->arg);
413 if (memcmp(from, p->arg, arglen) == 0) {
414 if (to != command_line)
415 to -= 1;
416 from += arglen;
417 p->fn(&from);
419 while (*from != ' ' && *from != '\0')
420 from++;
421 break;
425 c = *from++;
426 if (!c)
427 break;
428 if (COMMAND_LINE_SIZE <= ++len)
429 break;
430 *to++ = c;
432 *to = '\0';
433 *cmdline_p = command_line;
436 static void __init
437 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
439 #ifdef CONFIG_BLK_DEV_RAM
440 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
442 rd_image_start = image_start;
443 rd_prompt = prompt;
444 rd_doload = doload;
446 if (rd_sz)
447 rd_size = rd_sz;
448 #endif
451 static void __init
452 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
454 struct resource *res;
455 int i;
457 kernel_code.start = virt_to_phys(&_text);
458 kernel_code.end = virt_to_phys(&_etext - 1);
459 kernel_data.start = virt_to_phys(&__data_start);
460 kernel_data.end = virt_to_phys(&_end - 1);
462 for (i = 0; i < mi->nr_banks; i++) {
463 unsigned long virt_start, virt_end;
465 if (mi->bank[i].size == 0)
466 continue;
468 virt_start = __phys_to_virt(mi->bank[i].start);
469 virt_end = virt_start + mi->bank[i].size - 1;
471 res = alloc_bootmem_low(sizeof(*res));
472 res->name = "System RAM";
473 res->start = __virt_to_phys(virt_start);
474 res->end = __virt_to_phys(virt_end);
475 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
477 request_resource(&iomem_resource, res);
479 if (kernel_code.start >= res->start &&
480 kernel_code.end <= res->end)
481 request_resource(res, &kernel_code);
482 if (kernel_data.start >= res->start &&
483 kernel_data.end <= res->end)
484 request_resource(res, &kernel_data);
487 if (mdesc->video_start) {
488 video_ram.start = mdesc->video_start;
489 video_ram.end = mdesc->video_end;
490 request_resource(&iomem_resource, &video_ram);
494 * Some machines don't have the possibility of ever
495 * possessing lp0, lp1 or lp2
497 if (mdesc->reserve_lp0)
498 request_resource(&ioport_resource, &lp0);
499 if (mdesc->reserve_lp1)
500 request_resource(&ioport_resource, &lp1);
501 if (mdesc->reserve_lp2)
502 request_resource(&ioport_resource, &lp2);
506 * Tag parsing.
508 * This is the new way of passing data to the kernel at boot time. Rather
509 * than passing a fixed inflexible structure to the kernel, we pass a list
510 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
511 * tag for the list to be recognised (to distinguish the tagged list from
512 * a param_struct). The list is terminated with a zero-length tag (this tag
513 * is not parsed in any way).
515 static int __init parse_tag_core(const struct tag *tag)
517 if (tag->hdr.size > 2) {
518 if ((tag->u.core.flags & 1) == 0)
519 root_mountflags &= ~MS_RDONLY;
520 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
522 return 0;
525 __tagtable(ATAG_CORE, parse_tag_core);
527 static int __init parse_tag_mem32(const struct tag *tag)
529 if (meminfo.nr_banks >= NR_BANKS) {
530 printk(KERN_WARNING
531 "Ignoring memory bank 0x%08x size %dKB\n",
532 tag->u.mem.start, tag->u.mem.size / 1024);
533 return -EINVAL;
535 arm_add_memory(tag->u.mem.start, tag->u.mem.size);
536 return 0;
539 __tagtable(ATAG_MEM, parse_tag_mem32);
541 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
542 struct screen_info screen_info = {
543 .orig_video_lines = 30,
544 .orig_video_cols = 80,
545 .orig_video_mode = 0,
546 .orig_video_ega_bx = 0,
547 .orig_video_isVGA = 1,
548 .orig_video_points = 8
551 static int __init parse_tag_videotext(const struct tag *tag)
553 screen_info.orig_x = tag->u.videotext.x;
554 screen_info.orig_y = tag->u.videotext.y;
555 screen_info.orig_video_page = tag->u.videotext.video_page;
556 screen_info.orig_video_mode = tag->u.videotext.video_mode;
557 screen_info.orig_video_cols = tag->u.videotext.video_cols;
558 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
559 screen_info.orig_video_lines = tag->u.videotext.video_lines;
560 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
561 screen_info.orig_video_points = tag->u.videotext.video_points;
562 return 0;
565 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
566 #endif
568 static int __init parse_tag_ramdisk(const struct tag *tag)
570 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
571 (tag->u.ramdisk.flags & 2) == 0,
572 tag->u.ramdisk.start, tag->u.ramdisk.size);
573 return 0;
576 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
578 static int __init parse_tag_serialnr(const struct tag *tag)
580 system_serial_low = tag->u.serialnr.low;
581 system_serial_high = tag->u.serialnr.high;
582 return 0;
585 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
587 static int __init parse_tag_revision(const struct tag *tag)
589 system_rev = tag->u.revision.rev;
590 return 0;
593 __tagtable(ATAG_REVISION, parse_tag_revision);
595 static int __init parse_tag_cmdline(const struct tag *tag)
597 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
598 return 0;
601 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
604 * Scan the tag table for this tag, and call its parse function.
605 * The tag table is built by the linker from all the __tagtable
606 * declarations.
608 static int __init parse_tag(const struct tag *tag)
610 extern struct tagtable __tagtable_begin, __tagtable_end;
611 struct tagtable *t;
613 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
614 if (tag->hdr.tag == t->tag) {
615 t->parse(tag);
616 break;
619 return t < &__tagtable_end;
623 * Parse all tags in the list, checking both the global and architecture
624 * specific tag tables.
626 static void __init parse_tags(const struct tag *t)
628 for (; t->hdr.size; t = tag_next(t))
629 if (!parse_tag(t))
630 printk(KERN_WARNING
631 "Ignoring unrecognised tag 0x%08x\n",
632 t->hdr.tag);
636 * This holds our defaults.
638 static struct init_tags {
639 struct tag_header hdr1;
640 struct tag_core core;
641 struct tag_header hdr2;
642 struct tag_mem32 mem;
643 struct tag_header hdr3;
644 } init_tags __initdata = {
645 { tag_size(tag_core), ATAG_CORE },
646 { 1, PAGE_SIZE, 0xff },
647 { tag_size(tag_mem32), ATAG_MEM },
648 { MEM_SIZE, PHYS_OFFSET },
649 { 0, ATAG_NONE }
652 static void (*init_machine)(void) __initdata;
654 static int __init customize_machine(void)
656 /* customizes platform devices, or adds new ones */
657 if (init_machine)
658 init_machine();
659 return 0;
661 arch_initcall(customize_machine);
663 void __init setup_arch(char **cmdline_p)
665 struct tag *tags = (struct tag *)&init_tags;
666 struct machine_desc *mdesc;
667 char *from = default_command_line;
669 setup_processor();
670 mdesc = setup_machine(machine_arch_type);
671 machine_name = mdesc->name;
673 if (mdesc->soft_reboot)
674 reboot_setup("s");
676 if (__atags_pointer)
677 tags = phys_to_virt(__atags_pointer);
678 else if (mdesc->boot_params)
679 tags = phys_to_virt(mdesc->boot_params);
682 * If we have the old style parameters, convert them to
683 * a tag list.
685 if (tags->hdr.tag != ATAG_CORE)
686 convert_to_tag_list(tags);
687 if (tags->hdr.tag != ATAG_CORE)
688 tags = (struct tag *)&init_tags;
690 if (mdesc->fixup)
691 mdesc->fixup(mdesc, tags, &from, &meminfo);
693 if (tags->hdr.tag == ATAG_CORE) {
694 if (meminfo.nr_banks != 0)
695 squash_mem_tags(tags);
696 save_atags(tags);
697 parse_tags(tags);
700 init_mm.start_code = (unsigned long) &_text;
701 init_mm.end_code = (unsigned long) &_etext;
702 init_mm.end_data = (unsigned long) &_edata;
703 init_mm.brk = (unsigned long) &_end;
705 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
706 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
707 parse_cmdline(cmdline_p, from);
708 paging_init(&meminfo, mdesc);
709 request_standard_resources(&meminfo, mdesc);
711 #ifdef CONFIG_SMP
712 smp_init_cpus();
713 #endif
715 cpu_init();
718 * Set up various architecture-specific pointers
720 init_arch_irq = mdesc->init_irq;
721 system_timer = mdesc->timer;
722 init_machine = mdesc->init_machine;
724 #ifdef CONFIG_VT
725 #if defined(CONFIG_VGA_CONSOLE)
726 conswitchp = &vga_con;
727 #elif defined(CONFIG_DUMMY_CONSOLE)
728 conswitchp = &dummy_con;
729 #endif
730 #endif
731 early_trap_init();
735 static int __init topology_init(void)
737 int cpu;
739 for_each_possible_cpu(cpu) {
740 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
741 cpuinfo->cpu.hotpluggable = 1;
742 register_cpu(&cpuinfo->cpu, cpu);
745 return 0;
748 subsys_initcall(topology_init);
750 static const char *hwcap_str[] = {
751 "swp",
752 "half",
753 "thumb",
754 "26bit",
755 "fastmult",
756 "fpa",
757 "vfp",
758 "edsp",
759 "java",
760 "iwmmxt",
761 "crunch",
762 NULL
765 static int c_show(struct seq_file *m, void *v)
767 int i;
769 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
770 cpu_name, read_cpuid_id() & 15, elf_platform);
772 #if defined(CONFIG_SMP)
773 for_each_online_cpu(i) {
775 * glibc reads /proc/cpuinfo to determine the number of
776 * online processors, looking for lines beginning with
777 * "processor". Give glibc what it expects.
779 seq_printf(m, "processor\t: %d\n", i);
780 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
781 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
782 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
784 #else /* CONFIG_SMP */
785 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
786 loops_per_jiffy / (500000/HZ),
787 (loops_per_jiffy / (5000/HZ)) % 100);
788 #endif
790 /* dump out the processor features */
791 seq_puts(m, "Features\t: ");
793 for (i = 0; hwcap_str[i]; i++)
794 if (elf_hwcap & (1 << i))
795 seq_printf(m, "%s ", hwcap_str[i]);
797 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
798 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
800 if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
801 /* pre-ARM7 */
802 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
803 } else {
804 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
805 /* ARM7 */
806 seq_printf(m, "CPU variant\t: 0x%02x\n",
807 (read_cpuid_id() >> 16) & 127);
808 } else {
809 /* post-ARM7 */
810 seq_printf(m, "CPU variant\t: 0x%x\n",
811 (read_cpuid_id() >> 20) & 15);
813 seq_printf(m, "CPU part\t: 0x%03x\n",
814 (read_cpuid_id() >> 4) & 0xfff);
816 seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
818 seq_puts(m, "\n");
820 seq_printf(m, "Hardware\t: %s\n", machine_name);
821 seq_printf(m, "Revision\t: %04x\n", system_rev);
822 seq_printf(m, "Serial\t\t: %08x%08x\n",
823 system_serial_high, system_serial_low);
825 return 0;
828 static void *c_start(struct seq_file *m, loff_t *pos)
830 return *pos < 1 ? (void *)1 : NULL;
833 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
835 ++*pos;
836 return NULL;
839 static void c_stop(struct seq_file *m, void *v)
843 const struct seq_operations cpuinfo_op = {
844 .start = c_start,
845 .next = c_next,
846 .stop = c_stop,
847 .show = c_show