MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / arm / kernel / setup.c
blobae0267fd7abd95ef706a46cdf1c7e52cbf6eed9a
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/config.h>
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/stddef.h>
14 #include <linux/ioport.h>
15 #include <linux/delay.h>
16 #include <linux/utsname.h>
17 #include <linux/initrd.h>
18 #include <linux/console.h>
19 #include <linux/bootmem.h>
20 #include <linux/seq_file.h>
21 #include <linux/tty.h>
22 #include <linux/init.h>
23 #include <linux/root_dev.h>
24 #include <linux/cpu.h>
25 #include <linux/interrupt.h>
27 #include <asm/elf.h>
28 #include <asm/hardware.h>
29 #include <asm/io.h>
30 #include <asm/procinfo.h>
31 #include <asm/setup.h>
32 #include <asm/mach-types.h>
33 #include <asm/cacheflush.h>
34 #include <asm/tlbflush.h>
36 #include <asm/mach/arch.h>
37 #include <asm/mach/irq.h>
38 #include <asm/mach/time.h>
40 #ifndef MEM_SIZE
41 #define MEM_SIZE (16*1024*1024)
42 #endif
44 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
45 char fpe_type[8];
47 static int __init fpe_setup(char *line)
49 memcpy(fpe_type, line, 8);
50 return 1;
53 __setup("fpe=", fpe_setup);
54 #endif
56 extern unsigned int mem_fclk_21285;
57 extern void paging_init(struct meminfo *, struct machine_desc *desc);
58 extern void convert_to_tag_list(struct tag *tags);
59 extern void squash_mem_tags(struct tag *tag);
60 extern void reboot_setup(char *str);
61 extern int root_mountflags;
62 extern int _stext, _text, _etext, _edata, _end;
64 unsigned int processor_id;
65 unsigned int __machine_arch_type;
66 EXPORT_SYMBOL(__machine_arch_type);
68 unsigned int system_rev;
69 EXPORT_SYMBOL(system_rev);
71 unsigned int system_serial_low;
72 EXPORT_SYMBOL(system_serial_low);
74 unsigned int system_serial_high;
75 EXPORT_SYMBOL(system_serial_high);
77 unsigned int elf_hwcap;
78 EXPORT_SYMBOL(elf_hwcap);
81 #ifdef MULTI_CPU
82 struct processor processor;
83 #endif
84 #ifdef MULTI_TLB
85 struct cpu_tlb_fns cpu_tlb;
86 #endif
87 #ifdef MULTI_USER
88 struct cpu_user_fns cpu_user;
89 #endif
90 #ifdef MULTI_CACHE
91 struct cpu_cache_fns cpu_cache;
92 #endif
94 unsigned char aux_device_present;
96 char elf_platform[ELF_PLATFORM_SIZE];
97 EXPORT_SYMBOL(elf_platform);
99 unsigned long phys_initrd_start __initdata = 0;
100 unsigned long phys_initrd_size __initdata = 0;
102 static struct meminfo meminfo __initdata = { 0, };
103 static const char *cpu_name;
104 static const char *machine_name;
105 static char command_line[COMMAND_LINE_SIZE];
107 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
108 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
109 #define ENDIANNESS ((char)endian_test.l)
112 * Standard memory resources
114 static struct resource mem_res[] = {
115 { "Video RAM", 0, 0, IORESOURCE_MEM },
116 { "Kernel code", 0, 0, IORESOURCE_MEM },
117 { "Kernel data", 0, 0, IORESOURCE_MEM }
120 #define video_ram mem_res[0]
121 #define kernel_code mem_res[1]
122 #define kernel_data mem_res[2]
124 static struct resource io_res[] = {
125 { "reserved", 0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY },
126 { "reserved", 0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY },
127 { "reserved", 0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }
130 #define lp0 io_res[0]
131 #define lp1 io_res[1]
132 #define lp2 io_res[2]
134 static const char *cache_types[16] = {
135 "VIVT write-through",
136 "VIVT write-back",
137 "VIVT write-back",
138 "undefined 3",
139 "undefined 4",
140 "undefined 5",
141 "VIVT write-back",
142 "VIVT write-back",
143 "undefined 8",
144 "undefined 9",
145 "undefined 10",
146 "undefined 11",
147 "undefined 12",
148 "undefined 13",
149 "VIPT write-back",
150 "undefined 15",
153 static const char *cache_clean[16] = {
154 "not required",
155 "read-block",
156 "cp15 c7 ops",
157 "undefined 3",
158 "undefined 4",
159 "undefined 5",
160 "cp15 c7 ops",
161 "cp15 c7 ops",
162 "undefined 8",
163 "undefined 9",
164 "undefined 10",
165 "undefined 11",
166 "undefined 12",
167 "undefined 13",
168 "cp15 c7 ops",
169 "undefined 15",
172 static const char *cache_lockdown[16] = {
173 "not supported",
174 "not supported",
175 "not supported",
176 "undefined 3",
177 "undefined 4",
178 "undefined 5",
179 "format A",
180 "format B",
181 "undefined 8",
182 "undefined 9",
183 "undefined 10",
184 "undefined 11",
185 "undefined 12",
186 "undefined 13",
187 "format C",
188 "undefined 15",
191 static const char *proc_arch[] = {
192 "undefined/unknown",
193 "3",
194 "4",
195 "4T",
196 "5",
197 "5T",
198 "5TE",
199 "5TEJ",
200 "6TEJ",
201 "?(10)",
202 "?(11)",
203 "?(12)",
204 "?(13)",
205 "?(14)",
206 "?(15)",
207 "?(16)",
208 "?(17)",
211 #define CACHE_TYPE(x) (((x) >> 25) & 15)
212 #define CACHE_S(x) ((x) & (1 << 24))
213 #define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
214 #define CACHE_ISIZE(x) ((x) & 4095)
216 #define CACHE_SIZE(y) (((y) >> 6) & 7)
217 #define CACHE_ASSOC(y) (((y) >> 3) & 7)
218 #define CACHE_M(y) ((y) & (1 << 2))
219 #define CACHE_LINE(y) ((y) & 3)
221 static inline void dump_cache(const char *prefix, unsigned int cache)
223 unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
225 printk("%s: %d bytes, associativity %d, %d byte lines, %d sets\n",
226 prefix,
227 mult << (8 + CACHE_SIZE(cache)),
228 (mult << CACHE_ASSOC(cache)) >> 1,
229 8 << CACHE_LINE(cache),
230 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
231 CACHE_LINE(cache)));
234 static void __init dump_cpu_info(void)
236 unsigned int info = read_cpuid(CPUID_CACHETYPE);
238 if (info != processor_id) {
239 printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(info)]);
240 if (CACHE_S(info)) {
241 dump_cache("CPU: I cache", CACHE_ISIZE(info));
242 dump_cache("CPU: D cache", CACHE_DSIZE(info));
243 } else {
244 dump_cache("CPU: cache", CACHE_ISIZE(info));
249 int cpu_architecture(void)
251 int cpu_arch;
253 if ((processor_id & 0x0000f000) == 0) {
254 cpu_arch = CPU_ARCH_UNKNOWN;
255 } else if ((processor_id & 0x0000f000) == 0x00007000) {
256 cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
257 } else {
258 cpu_arch = (processor_id >> 16) & 15;
259 if (cpu_arch)
260 cpu_arch += CPU_ARCH_ARMv3;
263 return cpu_arch;
266 static void __init setup_processor(void)
268 extern struct proc_info_list __proc_info_begin, __proc_info_end;
269 struct proc_info_list *list;
272 * locate processor in the list of supported processor
273 * types. The linker builds this table for us from the
274 * entries in arch/arm/mm/proc-*.S
276 for (list = &__proc_info_begin; list < &__proc_info_end ; list++)
277 if ((processor_id & list->cpu_mask) == list->cpu_val)
278 break;
281 * If processor type is unrecognised, then we
282 * can do nothing...
284 if (list >= &__proc_info_end) {
285 printk("CPU configuration botched (ID %08x), unable "
286 "to continue.\n", processor_id);
287 while (1);
290 cpu_name = list->cpu_name;
292 #ifdef MULTI_CPU
293 processor = *list->proc;
294 #endif
295 #ifdef MULTI_TLB
296 cpu_tlb = *list->tlb;
297 #endif
298 #ifdef MULTI_USER
299 cpu_user = *list->user;
300 #endif
301 #ifdef MULTI_CACHE
302 cpu_cache = *list->cache;
303 #endif
305 printk("CPU: %s [%08x] revision %d (ARMv%s)\n",
306 cpu_name, processor_id, (int)processor_id & 15,
307 proc_arch[cpu_architecture()]);
309 dump_cpu_info();
311 sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
312 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
313 elf_hwcap = list->elf_hwcap;
315 cpu_proc_init();
318 static struct machine_desc * __init setup_machine(unsigned int nr)
320 extern struct machine_desc __arch_info_begin, __arch_info_end;
321 struct machine_desc *list;
324 * locate architecture in the list of supported architectures.
326 for (list = &__arch_info_begin; list < &__arch_info_end; list++)
327 if (list->nr == nr)
328 break;
331 * If the architecture type is not recognised, then we
332 * can co nothing...
334 if (list >= &__arch_info_end) {
335 printk("Architecture configuration botched (nr %d), unable "
336 "to continue.\n", nr);
337 while (1);
340 printk("Machine: %s\n", list->name);
342 return list;
345 static void __init early_initrd(char **p)
347 unsigned long start, size;
349 start = memparse(*p, p);
350 if (**p == ',') {
351 size = memparse((*p) + 1, p);
353 phys_initrd_start = start;
354 phys_initrd_size = size;
357 __early_param("initrd=", early_initrd);
360 * Pick out the memory size. We look for mem=size@start,
361 * where start and size are "size[KkMm]"
363 static void __init early_mem(char **p)
365 static int usermem __initdata = 0;
366 unsigned long size, start;
369 * If the user specifies memory size, we
370 * blow away any automatically generated
371 * size.
373 if (usermem == 0) {
374 usermem = 1;
375 meminfo.nr_banks = 0;
378 start = PHYS_OFFSET;
379 size = memparse(*p, p);
380 if (**p == '@')
381 start = memparse(*p + 1, p);
383 meminfo.bank[meminfo.nr_banks].start = start;
384 meminfo.bank[meminfo.nr_banks].size = size;
385 meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start);
386 meminfo.nr_banks += 1;
388 __early_param("mem=", early_mem);
391 * Initial parsing of the command line.
393 static void __init parse_cmdline(char **cmdline_p, char *from)
395 char c = ' ', *to = command_line;
396 int len = 0;
398 for (;;) {
399 if (c == ' ') {
400 extern struct early_params __early_begin, __early_end;
401 struct early_params *p;
403 for (p = &__early_begin; p < &__early_end; p++) {
404 int len = strlen(p->arg);
406 if (memcmp(from, p->arg, len) == 0) {
407 if (to != command_line)
408 to -= 1;
409 from += len;
410 p->fn(&from);
412 while (*from != ' ' && *from != '\0')
413 from++;
414 break;
418 c = *from++;
419 if (!c)
420 break;
421 if (COMMAND_LINE_SIZE <= ++len)
422 break;
423 *to++ = c;
425 *to = '\0';
426 *cmdline_p = command_line;
429 static void __init
430 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
432 #ifdef CONFIG_BLK_DEV_RAM
433 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
435 rd_image_start = image_start;
436 rd_prompt = prompt;
437 rd_doload = doload;
439 if (rd_sz)
440 rd_size = rd_sz;
441 #endif
444 static void __init
445 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
447 struct resource *res;
448 int i;
450 kernel_code.start = __virt_to_phys(init_mm.start_code);
451 kernel_code.end = __virt_to_phys(init_mm.end_code - 1);
452 kernel_data.start = __virt_to_phys(init_mm.end_code);
453 kernel_data.end = __virt_to_phys(init_mm.brk - 1);
455 for (i = 0; i < mi->nr_banks; i++) {
456 unsigned long virt_start, virt_end;
458 if (mi->bank[i].size == 0)
459 continue;
461 virt_start = __phys_to_virt(mi->bank[i].start);
462 virt_end = virt_start + mi->bank[i].size - 1;
464 res = alloc_bootmem_low(sizeof(*res));
465 res->name = "System RAM";
466 res->start = __virt_to_phys(virt_start);
467 res->end = __virt_to_phys(virt_end);
468 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
470 request_resource(&iomem_resource, res);
472 if (kernel_code.start >= res->start &&
473 kernel_code.end <= res->end)
474 request_resource(res, &kernel_code);
475 if (kernel_data.start >= res->start &&
476 kernel_data.end <= res->end)
477 request_resource(res, &kernel_data);
480 if (mdesc->video_start) {
481 video_ram.start = mdesc->video_start;
482 video_ram.end = mdesc->video_end;
483 request_resource(&iomem_resource, &video_ram);
487 * Some machines don't have the possibility of ever
488 * possessing lp0, lp1 or lp2
490 if (mdesc->reserve_lp0)
491 request_resource(&ioport_resource, &lp0);
492 if (mdesc->reserve_lp1)
493 request_resource(&ioport_resource, &lp1);
494 if (mdesc->reserve_lp2)
495 request_resource(&ioport_resource, &lp2);
499 * Tag parsing.
501 * This is the new way of passing data to the kernel at boot time. Rather
502 * than passing a fixed inflexible structure to the kernel, we pass a list
503 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
504 * tag for the list to be recognised (to distinguish the tagged list from
505 * a param_struct). The list is terminated with a zero-length tag (this tag
506 * is not parsed in any way).
508 static int __init parse_tag_core(const struct tag *tag)
510 if (tag->hdr.size > 2) {
511 if ((tag->u.core.flags & 1) == 0)
512 root_mountflags &= ~MS_RDONLY;
513 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
515 return 0;
518 __tagtable(ATAG_CORE, parse_tag_core);
520 static int __init parse_tag_mem32(const struct tag *tag)
522 if (meminfo.nr_banks >= NR_BANKS) {
523 printk(KERN_WARNING
524 "Ignoring memory bank 0x%08x size %dKB\n",
525 tag->u.mem.start, tag->u.mem.size / 1024);
526 return -EINVAL;
528 meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
529 meminfo.bank[meminfo.nr_banks].size = tag->u.mem.size;
530 meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(tag->u.mem.start);
531 meminfo.nr_banks += 1;
533 return 0;
536 __tagtable(ATAG_MEM, parse_tag_mem32);
538 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
539 struct screen_info screen_info = {
540 .orig_video_lines = 30,
541 .orig_video_cols = 80,
542 .orig_video_mode = 0,
543 .orig_video_ega_bx = 0,
544 .orig_video_isVGA = 1,
545 .orig_video_points = 8
548 static int __init parse_tag_videotext(const struct tag *tag)
550 screen_info.orig_x = tag->u.videotext.x;
551 screen_info.orig_y = tag->u.videotext.y;
552 screen_info.orig_video_page = tag->u.videotext.video_page;
553 screen_info.orig_video_mode = tag->u.videotext.video_mode;
554 screen_info.orig_video_cols = tag->u.videotext.video_cols;
555 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
556 screen_info.orig_video_lines = tag->u.videotext.video_lines;
557 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
558 screen_info.orig_video_points = tag->u.videotext.video_points;
559 return 0;
562 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
563 #endif
565 static int __init parse_tag_ramdisk(const struct tag *tag)
567 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
568 (tag->u.ramdisk.flags & 2) == 0,
569 tag->u.ramdisk.start, tag->u.ramdisk.size);
570 return 0;
573 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
575 static int __init parse_tag_initrd(const struct tag *tag)
577 printk(KERN_WARNING "ATAG_INITRD is deprecated; "
578 "please update your bootloader.\n");
579 phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
580 phys_initrd_size = tag->u.initrd.size;
581 return 0;
584 __tagtable(ATAG_INITRD, parse_tag_initrd);
586 static int __init parse_tag_initrd2(const struct tag *tag)
588 phys_initrd_start = tag->u.initrd.start;
589 phys_initrd_size = tag->u.initrd.size;
590 return 0;
593 __tagtable(ATAG_INITRD2, parse_tag_initrd2);
595 static int __init parse_tag_serialnr(const struct tag *tag)
597 system_serial_low = tag->u.serialnr.low;
598 system_serial_high = tag->u.serialnr.high;
599 return 0;
602 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
604 static int __init parse_tag_revision(const struct tag *tag)
606 system_rev = tag->u.revision.rev;
607 return 0;
610 __tagtable(ATAG_REVISION, parse_tag_revision);
612 static int __init parse_tag_cmdline(const struct tag *tag)
614 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
615 return 0;
618 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
621 * Scan the tag table for this tag, and call its parse function.
622 * The tag table is built by the linker from all the __tagtable
623 * declarations.
625 static int __init parse_tag(const struct tag *tag)
627 extern struct tagtable __tagtable_begin, __tagtable_end;
628 struct tagtable *t;
630 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
631 if (tag->hdr.tag == t->tag) {
632 t->parse(tag);
633 break;
636 return t < &__tagtable_end;
640 * Parse all tags in the list, checking both the global and architecture
641 * specific tag tables.
643 static void __init parse_tags(const struct tag *t)
645 for (; t->hdr.size; t = tag_next(t)) {
646 if (!parse_tag(t)) {
647 #if 0 // mask by Victor Yu. 12-15-2005
648 printk(KERN_WARNING
649 "Ignoring unrecognised tag 0x%08x\n",
650 t->hdr.tag);
651 #endif
657 * This holds our defaults.
659 static struct init_tags {
660 struct tag_header hdr1;
661 struct tag_core core;
662 struct tag_header hdr2;
663 struct tag_mem32 mem;
664 struct tag_header hdr3;
665 } init_tags __initdata = {
666 { tag_size(tag_core), ATAG_CORE },
667 { 1, PAGE_SIZE, 0xff },
668 { tag_size(tag_mem32), ATAG_MEM },
669 { MEM_SIZE, PHYS_OFFSET },
670 { 0, ATAG_NONE }
673 static void (*init_machine)(void) __initdata;
675 static int __init customize_machine(void)
677 /* customizes platform devices, or adds new ones */
678 if (init_machine)
679 init_machine();
680 return 0;
682 arch_initcall(customize_machine);
684 void __init setup_arch(char **cmdline_p)
686 struct tag *tags = (struct tag *)&init_tags;
687 struct machine_desc *mdesc;
688 char *from = default_command_line;
690 setup_processor();
691 mdesc = setup_machine(machine_arch_type);
692 machine_name = mdesc->name;
694 if (mdesc->soft_reboot)
695 reboot_setup("s");
697 if (mdesc->param_offset)
698 tags = phys_to_virt(mdesc->param_offset);
701 * If we have the old style parameters, convert them to
702 * a tag list.
704 if (tags->hdr.tag != ATAG_CORE)
705 convert_to_tag_list(tags);
706 if (tags->hdr.tag != ATAG_CORE)
707 tags = (struct tag *)&init_tags;
709 if (mdesc->fixup)
710 mdesc->fixup(mdesc, tags, &from, &meminfo);
712 if (tags->hdr.tag == ATAG_CORE) {
713 if (meminfo.nr_banks != 0)
714 squash_mem_tags(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(saved_command_line, from, COMMAND_LINE_SIZE);
724 saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
725 parse_cmdline(cmdline_p, from);
726 paging_init(&meminfo, mdesc);
727 request_standard_resources(&meminfo, mdesc);
730 * Set up various architecture-specific pointers
732 init_arch_irq = mdesc->init_irq;
733 init_arch_time = mdesc->init_time;
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
745 static struct cpu cpu[1];
747 static int __init topology_init(void)
749 return register_cpu(cpu, 0, NULL);
752 subsys_initcall(topology_init);
754 static const char *hwcap_str[] = {
755 "swp",
756 "half",
757 "thumb",
758 "26bit",
759 "fastmult",
760 "fpa",
761 "vfp",
762 "edsp",
763 "java",
764 NULL
767 static void
768 c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
770 unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
772 seq_printf(m, "%s size\t\t: %d\n"
773 "%s assoc\t\t: %d\n"
774 "%s line length\t: %d\n"
775 "%s sets\t\t: %d\n",
776 type, mult << (8 + CACHE_SIZE(cache)),
777 type, (mult << CACHE_ASSOC(cache)) >> 1,
778 type, 8 << CACHE_LINE(cache),
779 type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
780 CACHE_LINE(cache)));
783 static int c_show(struct seq_file *m, void *v)
785 int i;
787 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
788 cpu_name, (int)processor_id & 15, elf_platform);
790 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
791 loops_per_jiffy / (500000/HZ),
792 (loops_per_jiffy / (5000/HZ)) % 100);
794 /* dump out the processor features */
795 seq_puts(m, "Features\t: ");
797 for (i = 0; hwcap_str[i]; i++)
798 if (elf_hwcap & (1 << i))
799 seq_printf(m, "%s ", hwcap_str[i]);
801 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
802 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
804 if ((processor_id & 0x0000f000) == 0x00000000) {
805 /* pre-ARM7 */
806 seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
807 } else {
808 if ((processor_id & 0x0000f000) == 0x00007000) {
809 /* ARM7 */
810 seq_printf(m, "CPU variant\t: 0x%02x\n",
811 (processor_id >> 16) & 127);
812 } else {
813 /* post-ARM7 */
814 seq_printf(m, "CPU variant\t: 0x%x\n",
815 (processor_id >> 20) & 15);
817 seq_printf(m, "CPU part\t: 0x%03x\n",
818 (processor_id >> 4) & 0xfff);
820 seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
823 unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
824 if (cache_info != processor_id) {
825 seq_printf(m, "Cache type\t: %s\n"
826 "Cache clean\t: %s\n"
827 "Cache lockdown\t: %s\n"
828 "Cache format\t: %s\n",
829 cache_types[CACHE_TYPE(cache_info)],
830 cache_clean[CACHE_TYPE(cache_info)],
831 cache_lockdown[CACHE_TYPE(cache_info)],
832 CACHE_S(cache_info) ? "Harvard" : "Unified");
834 if (CACHE_S(cache_info)) {
835 c_show_cache(m, "I", CACHE_ISIZE(cache_info));
836 c_show_cache(m, "D", CACHE_DSIZE(cache_info));
837 } else {
838 c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
843 seq_puts(m, "\n");
845 seq_printf(m, "Hardware\t: %s\n", machine_name);
846 seq_printf(m, "Revision\t: %04x\n", system_rev);
847 seq_printf(m, "Serial\t\t: %08x%08x\n",
848 system_serial_high, system_serial_low);
850 return 0;
853 static void *c_start(struct seq_file *m, loff_t *pos)
855 return *pos < 1 ? (void *)1 : NULL;
858 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
860 ++*pos;
861 return NULL;
864 static void c_stop(struct seq_file *m, void *v)
868 struct seq_operations cpuinfo_op = {
869 .start = c_start,
870 .next = c_next,
871 .stop = c_stop,
872 .show = c_show