patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / arm / kernel / setup.c
1 /*
2  *  linux/arch/arm/kernel/setup.c
3  *
4  *  Copyright (C) 1995-2001 Russell King
5  *
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
26 #include <asm/elf.h>
27 #include <asm/hardware.h>
28 #include <asm/io.h>
29 #include <asm/procinfo.h>
30 #include <asm/setup.h>
31 #include <asm/mach-types.h>
32 #include <asm/cacheflush.h>
33 #include <asm/tlbflush.h>
34
35 #include <asm/mach/arch.h>
36 #include <asm/mach/irq.h>
37
38 #ifndef MEM_SIZE
39 #define MEM_SIZE        (16*1024*1024)
40 #endif
41
42 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
43 char fpe_type[8];
44
45 static int __init fpe_setup(char *line)
46 {
47         memcpy(fpe_type, line, 8);
48         return 1;
49 }
50
51 __setup("fpe=", fpe_setup);
52 #endif
53
54 extern unsigned int mem_fclk_21285;
55 extern void paging_init(struct meminfo *, struct machine_desc *desc);
56 extern void convert_to_tag_list(struct tag *tags);
57 extern void squash_mem_tags(struct tag *tag);
58 extern void bootmem_init(struct meminfo *);
59 extern void reboot_setup(char *str);
60 extern int root_mountflags;
61 extern int _stext, _text, _etext, _edata, _end;
62
63 unsigned int processor_id;
64 unsigned int __machine_arch_type;
65 EXPORT_SYMBOL(__machine_arch_type);
66
67 unsigned int system_rev;
68 EXPORT_SYMBOL(system_rev);
69
70 unsigned int system_serial_low;
71 EXPORT_SYMBOL(system_serial_low);
72
73 unsigned int system_serial_high;
74 EXPORT_SYMBOL(system_serial_high);
75
76 unsigned int elf_hwcap;
77 EXPORT_SYMBOL(elf_hwcap);
78
79
80 #ifdef MULTI_CPU
81 struct processor processor;
82 #endif
83 #ifdef MULTI_TLB
84 struct cpu_tlb_fns cpu_tlb;
85 #endif
86 #ifdef MULTI_USER
87 struct cpu_user_fns cpu_user;
88 #endif
89 #ifdef MULTI_CACHE
90 struct cpu_cache_fns cpu_cache;
91 #endif
92
93 unsigned char aux_device_present;
94
95 char elf_platform[ELF_PLATFORM_SIZE];
96 EXPORT_SYMBOL(elf_platform);
97
98 char saved_command_line[COMMAND_LINE_SIZE];
99 unsigned long phys_initrd_start __initdata = 0;
100 unsigned long phys_initrd_size __initdata = 0;
101
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];
106
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)
110
111 /*
112  * Standard memory resources
113  */
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                   }
118 };
119
120 #define video_ram   mem_res[0]
121 #define kernel_code mem_res[1]
122 #define kernel_data mem_res[2]
123
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 }
128 };
129
130 #define lp0 io_res[0]
131 #define lp1 io_res[1]
132 #define lp2 io_res[2]
133
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",
151 };
152
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",
170 };
171
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",
189 };
190
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)",
209 };
210
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)
215
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)
220
221 static inline void dump_cache(const char *prefix, unsigned int cache)
222 {
223         unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
224
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)));
232 }
233
234 static void __init dump_cpu_info(void)
235 {
236         unsigned int info = read_cpuid(CPUID_CACHETYPE);
237
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));
245                 }
246         }
247 }
248
249 int cpu_architecture(void)
250 {
251         int cpu_arch;
252
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;
261         }
262
263         return cpu_arch;
264 }
265
266 static void __init setup_processor(void)
267 {
268         extern struct proc_info_list __proc_info_begin, __proc_info_end;
269         struct proc_info_list *list;
270
271         /*
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
275          */
276         for (list = &__proc_info_begin; list < &__proc_info_end ; list++)
277                 if ((processor_id & list->cpu_mask) == list->cpu_val)
278                         break;
279
280         /*
281          * If processor type is unrecognised, then we
282          * can do nothing...
283          */
284         if (list >= &__proc_info_end) {
285                 printk("CPU configuration botched (ID %08x), unable "
286                        "to continue.\n", processor_id);
287                 while (1);
288         }
289
290         cpu_name = list->cpu_name;
291
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
304
305         printk("CPU: %s [%08x] revision %d (ARMv%s)\n",
306                cpu_name, processor_id, (int)processor_id & 15,
307                proc_arch[cpu_architecture()]);
308
309         dump_cpu_info();
310
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;
314
315         cpu_proc_init();
316 }
317
318 static struct machine_desc * __init setup_machine(unsigned int nr)
319 {
320         extern struct machine_desc __arch_info_begin, __arch_info_end;
321         struct machine_desc *list;
322
323         /*
324          * locate architecture in the list of supported architectures.
325          */
326         for (list = &__arch_info_begin; list < &__arch_info_end; list++)
327                 if (list->nr == nr)
328                         break;
329
330         /*
331          * If the architecture type is not recognised, then we
332          * can co nothing...
333          */
334         if (list >= &__arch_info_end) {
335                 printk("Architecture configuration botched (nr %d), unable "
336                        "to continue.\n", nr);
337                 while (1);
338         }
339
340         printk("Machine: %s\n", list->name);
341
342         return list;
343 }
344
345 static void __init early_initrd(char **p)
346 {
347         unsigned long start, size;
348
349         start = memparse(*p, p);
350         if (**p == ',') {
351                 size = memparse((*p) + 1, p);
352
353                 phys_initrd_start = start;
354                 phys_initrd_size = size;
355         }
356 }
357 __early_param("initrd=", early_initrd);
358
359 /*
360  * Pick out the memory size.  We look for mem=size@start,
361  * where start and size are "size[KkMm]"
362  */
363 static void __init early_mem(char **p)
364 {
365         static int usermem __initdata = 0;
366         unsigned long size, start;
367
368         /*
369          * If the user specifies memory size, we
370          * blow away any automatically generated
371          * size.
372          */
373         if (usermem == 0) {
374                 usermem = 1;
375                 meminfo.nr_banks = 0;
376         }
377
378         start = PHYS_OFFSET;
379         size  = memparse(*p, p);
380         if (**p == '@')
381                 start = memparse(*p + 1, p);
382
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;
387 }
388 __early_param("mem=", early_mem);
389
390 /*
391  * Initial parsing of the command line.
392  */
393 static void __init parse_cmdline(char **cmdline_p, char *from)
394 {
395         char c = ' ', *to = command_line;
396         int len = 0;
397
398         for (;;) {
399                 if (c == ' ') {
400                         extern struct early_params __early_begin, __early_end;
401                         struct early_params *p;
402
403                         for (p = &__early_begin; p < &__early_end; p++) {
404                                 int len = strlen(p->arg);
405
406                                 if (memcmp(from, p->arg, len) == 0) {
407                                         if (to != command_line)
408                                                 to -= 1;
409                                         from += len;
410                                         p->fn(&from);
411
412                                         while (*from != ' ' && *from != '\0')
413                                                 from++;
414                                         break;
415                                 }
416                         }
417                 }
418                 c = *from++;
419                 if (!c)
420                         break;
421                 if (COMMAND_LINE_SIZE <= ++len)
422                         break;
423                 *to++ = c;
424         }
425         *to = '\0';
426         *cmdline_p = command_line;
427 }
428
429 static void __init
430 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
431 {
432 #ifdef CONFIG_BLK_DEV_RAM
433         extern int rd_size, rd_image_start, rd_prompt, rd_doload;
434
435         rd_image_start = image_start;
436         rd_prompt = prompt;
437         rd_doload = doload;
438
439         if (rd_sz)
440                 rd_size = rd_sz;
441 #endif
442 }
443
444 static void __init
445 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
446 {
447         struct resource *res;
448         int i;
449
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);
454
455         for (i = 0; i < mi->nr_banks; i++) {
456                 unsigned long virt_start, virt_end;
457
458                 if (mi->bank[i].size == 0)
459                         continue;
460
461                 virt_start = __phys_to_virt(mi->bank[i].start);
462                 virt_end   = virt_start + mi->bank[i].size - 1;
463
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;
469
470                 request_resource(&iomem_resource, res);
471
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);
478         }
479
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);
484         }
485
486         /*
487          * Some machines don't have the possibility of ever
488          * possessing lp0, lp1 or lp2
489          */
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);
496 }
497
498 /*
499  *  Tag parsing.
500  *
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).
507  */
508 static int __init parse_tag_core(const struct tag *tag)
509 {
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);
514         }
515         return 0;
516 }
517
518 __tagtable(ATAG_CORE, parse_tag_core);
519
520 static int __init parse_tag_mem32(const struct tag *tag)
521 {
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;
527         }
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;
532
533         return 0;
534 }
535
536 __tagtable(ATAG_MEM, parse_tag_mem32);
537
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
546 };
547
548 static int __init parse_tag_videotext(const struct tag *tag)
549 {
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;
560 }
561
562 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
563 #endif
564
565 static int __init parse_tag_ramdisk(const struct tag *tag)
566 {
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;
571 }
572
573 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
574
575 static int __init parse_tag_initrd(const struct tag *tag)
576 {
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;
582 }
583
584 __tagtable(ATAG_INITRD, parse_tag_initrd);
585
586 static int __init parse_tag_initrd2(const struct tag *tag)
587 {
588         phys_initrd_start = tag->u.initrd.start;
589         phys_initrd_size = tag->u.initrd.size;
590         return 0;
591 }
592
593 __tagtable(ATAG_INITRD2, parse_tag_initrd2);
594
595 static int __init parse_tag_serialnr(const struct tag *tag)
596 {
597         system_serial_low = tag->u.serialnr.low;
598         system_serial_high = tag->u.serialnr.high;
599         return 0;
600 }
601
602 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
603
604 static int __init parse_tag_revision(const struct tag *tag)
605 {
606         system_rev = tag->u.revision.rev;
607         return 0;
608 }
609
610 __tagtable(ATAG_REVISION, parse_tag_revision);
611
612 static int __init parse_tag_cmdline(const struct tag *tag)
613 {
614         strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
615         return 0;
616 }
617
618 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
619
620 /*
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.
624  */
625 static int __init parse_tag(const struct tag *tag)
626 {
627         extern struct tagtable __tagtable_begin, __tagtable_end;
628         struct tagtable *t;
629
630         for (t = &__tagtable_begin; t < &__tagtable_end; t++)
631                 if (tag->hdr.tag == t->tag) {
632                         t->parse(tag);
633                         break;
634                 }
635
636         return t < &__tagtable_end;
637 }
638
639 /*
640  * Parse all tags in the list, checking both the global and architecture
641  * specific tag tables.
642  */
643 static void __init parse_tags(const struct tag *t)
644 {
645         for (; t->hdr.size; t = tag_next(t))
646                 if (!parse_tag(t))
647                         printk(KERN_WARNING
648                                 "Ignoring unrecognised tag 0x%08x\n",
649                                 t->hdr.tag);
650 }
651
652 /*
653  * This holds our defaults.
654  */
655 static struct init_tags {
656         struct tag_header hdr1;
657         struct tag_core   core;
658         struct tag_header hdr2;
659         struct tag_mem32  mem;
660         struct tag_header hdr3;
661 } init_tags __initdata = {
662         { tag_size(tag_core), ATAG_CORE },
663         { 1, PAGE_SIZE, 0xff },
664         { tag_size(tag_mem32), ATAG_MEM },
665         { MEM_SIZE, PHYS_OFFSET },
666         { 0, ATAG_NONE }
667 };
668
669 static void (*init_machine)(void) __initdata;
670
671 static int __init customize_machine(void)
672 {
673         /* customizes platform devices, or adds new ones */
674         if (init_machine)
675                 init_machine();
676         return 0;
677 }
678 arch_initcall(customize_machine);
679
680 void __init setup_arch(char **cmdline_p)
681 {
682         struct tag *tags = (struct tag *)&init_tags;
683         struct machine_desc *mdesc;
684         char *from = default_command_line;
685
686         setup_processor();
687         mdesc = setup_machine(machine_arch_type);
688         machine_name = mdesc->name;
689
690         if (mdesc->soft_reboot)
691                 reboot_setup("s");
692
693         if (mdesc->param_offset)
694                 tags = phys_to_virt(mdesc->param_offset);
695
696         /*
697          * If we have the old style parameters, convert them to
698          * a tag list.
699          */
700         if (tags->hdr.tag != ATAG_CORE)
701                 convert_to_tag_list(tags);
702         if (tags->hdr.tag != ATAG_CORE)
703                 tags = (struct tag *)&init_tags;
704
705         if (mdesc->fixup)
706                 mdesc->fixup(mdesc, tags, &from, &meminfo);
707
708         if (tags->hdr.tag == ATAG_CORE) {
709                 if (meminfo.nr_banks != 0)
710                         squash_mem_tags(tags);
711                 parse_tags(tags);
712         }
713
714         init_mm.start_code = (unsigned long) &_text;
715         init_mm.end_code   = (unsigned long) &_etext;
716         init_mm.end_data   = (unsigned long) &_edata;
717         init_mm.brk        = (unsigned long) &_end;
718
719         memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
720         saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
721         parse_cmdline(cmdline_p, from);
722         bootmem_init(&meminfo);
723         paging_init(&meminfo, mdesc);
724         request_standard_resources(&meminfo, mdesc);
725
726         /*
727          * Set up various architecture-specific pointers
728          */
729         init_arch_irq = mdesc->init_irq;
730         init_machine = mdesc->init_machine;
731
732 #ifdef CONFIG_VT
733 #if defined(CONFIG_VGA_CONSOLE)
734         conswitchp = &vga_con;
735 #elif defined(CONFIG_DUMMY_CONSOLE)
736         conswitchp = &dummy_con;
737 #endif
738 #endif
739 }
740
741 static struct cpu cpu[1];
742
743 static int __init topology_init(void)
744 {
745         return register_cpu(cpu, 0, NULL);
746 }
747
748 subsys_initcall(topology_init);
749
750 static const char *hwcap_str[] = {
751         "swp",
752         "half",
753         "thumb",
754         "26bit",
755         "fastmult",
756         "fpa",
757         "vfp",
758         "edsp",
759         NULL
760 };
761
762 static void
763 c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
764 {
765         unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
766
767         seq_printf(m, "%s size\t\t: %d\n"
768                       "%s assoc\t\t: %d\n"
769                       "%s line length\t: %d\n"
770                       "%s sets\t\t: %d\n",
771                 type, mult << (8 + CACHE_SIZE(cache)),
772                 type, (mult << CACHE_ASSOC(cache)) >> 1,
773                 type, 8 << CACHE_LINE(cache),
774                 type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
775                             CACHE_LINE(cache)));
776 }
777
778 static int c_show(struct seq_file *m, void *v)
779 {
780         int i;
781
782         seq_printf(m, "Processor\t: %s rev %d (%s)\n",
783                    cpu_name, (int)processor_id & 15, elf_platform);
784
785         seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
786                    loops_per_jiffy / (500000/HZ),
787                    (loops_per_jiffy / (5000/HZ)) % 100);
788
789         /* dump out the processor features */
790         seq_puts(m, "Features\t: ");
791
792         for (i = 0; hwcap_str[i]; i++)
793                 if (elf_hwcap & (1 << i))
794                         seq_printf(m, "%s ", hwcap_str[i]);
795
796         seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
797         seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
798
799         if ((processor_id & 0x0000f000) == 0x00000000) {
800                 /* pre-ARM7 */
801                 seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
802         } else {
803                 if ((processor_id & 0x0000f000) == 0x00007000) {
804                         /* ARM7 */
805                         seq_printf(m, "CPU variant\t: 0x%02x\n",
806                                    (processor_id >> 16) & 127);
807                 } else {
808                         /* post-ARM7 */
809                         seq_printf(m, "CPU variant\t: 0x%x\n",
810                                    (processor_id >> 20) & 15);
811                 }
812                 seq_printf(m, "CPU part\t: 0x%03x\n",
813                            (processor_id >> 4) & 0xfff);
814         }
815         seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
816
817         {
818                 unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
819                 if (cache_info != processor_id) {
820                         seq_printf(m, "Cache type\t: %s\n"
821                                       "Cache clean\t: %s\n"
822                                       "Cache lockdown\t: %s\n"
823                                       "Cache format\t: %s\n",
824                                    cache_types[CACHE_TYPE(cache_info)],
825                                    cache_clean[CACHE_TYPE(cache_info)],
826                                    cache_lockdown[CACHE_TYPE(cache_info)],
827                                    CACHE_S(cache_info) ? "Harvard" : "Unified");
828
829                         if (CACHE_S(cache_info)) {
830                                 c_show_cache(m, "I", CACHE_ISIZE(cache_info));
831                                 c_show_cache(m, "D", CACHE_DSIZE(cache_info));
832                         } else {
833                                 c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
834                         }
835                 }
836         }
837
838         seq_puts(m, "\n");
839
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);
844
845         return 0;
846 }
847
848 static void *c_start(struct seq_file *m, loff_t *pos)
849 {
850         return *pos < 1 ? (void *)1 : NULL;
851 }
852
853 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
854 {
855         ++*pos;
856         return NULL;
857 }
858
859 static void c_stop(struct seq_file *m, void *v)
860 {
861 }
862
863 struct seq_operations cpuinfo_op = {
864         .start  = c_start,
865         .next   = c_next,
866         .stop   = c_stop,
867         .show   = c_show
868 };