1
2
3
4
5
6
7
8
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>
27
28#include <asm/cpu.h>
29#include <asm/elf.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>
35
36#include <asm/mach/arch.h>
37#include <asm/mach/irq.h>
38#include <asm/mach/time.h>
39
40#include "compat.h"
41
42#ifndef MEM_SIZE
43#define MEM_SIZE (16*1024*1024)
44#endif
45
46#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
47char fpe_type[8];
48
49static int __init fpe_setup(char *line)
50{
51 memcpy(fpe_type, line, 8);
52 return 1;
53}
54
55__setup("fpe=", fpe_setup);
56#endif
57
58extern void paging_init(struct meminfo *, struct machine_desc *desc);
59extern void reboot_setup(char *str);
60extern int root_mountflags;
61extern void _stext, _text, _etext, __data_start, _edata, _end;
62
63unsigned int processor_id;
64unsigned int __machine_arch_type;
65EXPORT_SYMBOL(__machine_arch_type);
66
67unsigned int __atags_pointer __initdata;
68
69unsigned int system_rev;
70EXPORT_SYMBOL(system_rev);
71
72unsigned int system_serial_low;
73EXPORT_SYMBOL(system_serial_low);
74
75unsigned int system_serial_high;
76EXPORT_SYMBOL(system_serial_high);
77
78unsigned int elf_hwcap;
79EXPORT_SYMBOL(elf_hwcap);
80
81
82#ifdef MULTI_CPU
83struct processor processor;
84#endif
85#ifdef MULTI_TLB
86struct cpu_tlb_fns cpu_tlb;
87#endif
88#ifdef MULTI_USER
89struct cpu_user_fns cpu_user;
90#endif
91#ifdef MULTI_CACHE
92struct cpu_cache_fns cpu_cache;
93#endif
94#ifdef CONFIG_OUTER_CACHE
95struct outer_cache_fns outer_cache;
96#endif
97
98struct stack {
99 u32 irq[3];
100 u32 abt[3];
101 u32 und[3];
102} ____cacheline_aligned;
103
104static struct stack stacks[NR_CPUS];
105
106char elf_platform[ELF_PLATFORM_SIZE];
107EXPORT_SYMBOL(elf_platform);
108
109unsigned long phys_initrd_start __initdata = 0;
110unsigned long phys_initrd_size __initdata = 0;
111
112static struct meminfo meminfo __initdata = { 0, };
113static const char *cpu_name;
114static const char *machine_name;
115static char __initdata command_line[COMMAND_LINE_SIZE];
116
117static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
118static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
119#define ENDIANNESS ((char)endian_test.l)
120
121DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
122
123
124
125
126static struct resource mem_res[] = {
127 {
128 .name = "Video RAM",
129 .start = 0,
130 .end = 0,
131 .flags = IORESOURCE_MEM
132 },
133 {
134 .name = "Kernel text",
135 .start = 0,
136 .end = 0,
137 .flags = IORESOURCE_MEM
138 },
139 {
140 .name = "Kernel data",
141 .start = 0,
142 .end = 0,
143 .flags = IORESOURCE_MEM
144 }
145};
146
147#define video_ram mem_res[0]
148#define kernel_code mem_res[1]
149#define kernel_data mem_res[2]
150
151static struct resource io_res[] = {
152 {
153 .name = "reserved",
154 .start = 0x3bc,
155 .end = 0x3be,
156 .flags = IORESOURCE_IO | IORESOURCE_BUSY
157 },
158 {
159 .name = "reserved",
160 .start = 0x378,
161 .end = 0x37f,
162 .flags = IORESOURCE_IO | IORESOURCE_BUSY
163 },
164 {
165 .name = "reserved",
166 .start = 0x278,
167 .end = 0x27f,
168 .flags = IORESOURCE_IO | IORESOURCE_BUSY
169 }
170};
171
172#define lp0 io_res[0]
173#define lp1 io_res[1]
174#define lp2 io_res[2]
175
176static const char *cache_types[16] = {
177 "write-through",
178 "write-back",
179 "write-back",
180 "undefined 3",
181 "undefined 4",
182 "undefined 5",
183 "write-back",
184 "write-back",
185 "undefined 8",
186 "undefined 9",
187 "undefined 10",
188 "undefined 11",
189 "undefined 12",
190 "undefined 13",
191 "write-back",
192 "undefined 15",
193};
194
195static const char *cache_clean[16] = {
196 "not required",
197 "read-block",
198 "cp15 c7 ops",
199 "undefined 3",
200 "undefined 4",
201 "undefined 5",
202 "cp15 c7 ops",
203 "cp15 c7 ops",
204 "undefined 8",
205 "undefined 9",
206 "undefined 10",
207 "undefined 11",
208 "undefined 12",
209 "undefined 13",
210 "cp15 c7 ops",
211 "undefined 15",
212};
213
214static const char *cache_lockdown[16] = {
215 "not supported",
216 "not supported",
217 "not supported",
218 "undefined 3",
219 "undefined 4",
220 "undefined 5",
221 "format A",
222 "format B",
223 "undefined 8",
224 "undefined 9",
225 "undefined 10",
226 "undefined 11",
227 "undefined 12",
228 "undefined 13",
229 "format C",
230 "undefined 15",
231};
232
233static const char *proc_arch[] = {
234 "undefined/unknown",
235 "3",
236 "4",
237 "4T",
238 "5",
239 "5T",
240 "5TE",
241 "5TEJ",
242 "6TEJ",
243 "7",
244 "?(11)",
245 "?(12)",
246 "?(13)",
247 "?(14)",
248 "?(15)",
249 "?(16)",
250 "?(17)",
251};
252
253#define CACHE_TYPE(x) (((x) >> 25) & 15)
254#define CACHE_S(x) ((x) & (1 << 24))
255#define CACHE_DSIZE(x) (((x) >> 12) & 4095)
256#define CACHE_ISIZE(x) ((x) & 4095)
257
258#define CACHE_SIZE(y) (((y) >> 6) & 7)
259#define CACHE_ASSOC(y) (((y) >> 3) & 7)
260#define CACHE_M(y) ((y) & (1 << 2))
261#define CACHE_LINE(y) ((y) & 3)
262
263static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
264{
265 unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
266
267 printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n",
268 cpu, prefix,
269 mult << (8 + CACHE_SIZE(cache)),
270 (mult << CACHE_ASSOC(cache)) >> 1,
271 8 << CACHE_LINE(cache),
272 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
273 CACHE_LINE(cache)));
274}
275
276static void __init dump_cpu_info(int cpu)
277{
278 unsigned int info = read_cpuid(CPUID_CACHETYPE);
279
280 if (info != processor_id) {
281 printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
282 cache_types[CACHE_TYPE(info)]);
283 if (CACHE_S(info)) {
284 dump_cache("I cache", cpu, CACHE_ISIZE(info));
285 dump_cache("D cache", cpu, CACHE_DSIZE(info));
286 } else {
287 dump_cache("cache", cpu, CACHE_ISIZE(info));
288 }
289 }
290
291 if (arch_is_coherent())
292 printk("Cache coherency enabled\n");
293}
294
295int cpu_architecture(void)
296{
297 int cpu_arch;
298
299 if ((processor_id & 0x0008f000) == 0) {
300 cpu_arch = CPU_ARCH_UNKNOWN;
301 } else if ((processor_id & 0x0008f000) == 0x00007000) {
302 cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
303 } else if ((processor_id & 0x00080000) == 0x00000000) {
304 cpu_arch = (processor_id >> 16) & 7;
305 if (cpu_arch)
306 cpu_arch += CPU_ARCH_ARMv3;
307 } else {
308
309 cpu_arch = ((processor_id >> 12) & 0xf) - 0xb + CPU_ARCH_ARMv6;
310 }
311
312 return cpu_arch;
313}
314
315
316
317
318
319extern struct proc_info_list *lookup_processor_type(unsigned int);
320extern struct machine_desc *lookup_machine_type(unsigned int);
321
322static void __init setup_processor(void)
323{
324 struct proc_info_list *list;
325
326
327
328
329
330
331 list = lookup_processor_type(processor_id);
332 if (!list) {
333 printk("CPU configuration botched (ID %08x), unable "
334 "to continue.\n", processor_id);
335 while (1);
336 }
337
338 cpu_name = list->cpu_name;
339
340#ifdef MULTI_CPU
341 processor = *list->proc;
342#endif
343#ifdef MULTI_TLB
344 cpu_tlb = *list->tlb;
345#endif
346#ifdef MULTI_USER
347 cpu_user = *list->user;
348#endif
349#ifdef MULTI_CACHE
350 cpu_cache = *list->cache;
351#endif
352
353 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
354 cpu_name, processor_id, (int)processor_id & 15,
355 proc_arch[cpu_architecture()], cr_alignment);
356
357 sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
358 sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
359 elf_hwcap = list->elf_hwcap;
360#ifndef CONFIG_ARM_THUMB
361 elf_hwcap &= ~HWCAP_THUMB;
362#endif
363
364 cpu_proc_init();
365}
366
367
368
369
370
371
372
373void cpu_init(void)
374{
375 unsigned int cpu = smp_processor_id();
376 struct stack *stk = &stacks[cpu];
377
378 if (cpu >= NR_CPUS) {
379 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
380 BUG();
381 }
382
383 if (system_state == SYSTEM_BOOTING)
384 dump_cpu_info(cpu);
385
386
387
388
389 __asm__ (
390 "msr cpsr_c, %1\n\t"
391 "add sp, %0, %2\n\t"
392 "msr cpsr_c, %3\n\t"
393 "add sp, %0, %4\n\t"
394 "msr cpsr_c, %5\n\t"
395 "add sp, %0, %6\n\t"
396 "msr cpsr_c, %7"
397 :
398 : "r" (stk),
399 "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
400 "I" (offsetof(struct stack, irq[0])),
401 "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
402 "I" (offsetof(struct stack, abt[0])),
403 "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
404 "I" (offsetof(struct stack, und[0])),
405 "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
406 : "r14");
407}
408
409static struct machine_desc * __init setup_machine(unsigned int nr)
410{
411 struct machine_desc *list;
412
413
414
415
416 list = lookup_machine_type(nr);
417 if (!list) {
418 printk("Machine configuration botched (nr %d), unable "
419 "to continue.\n", nr);
420 while (1);
421 }
422
423 printk("Machine: %s\n", list->name);
424
425 return list;
426}
427
428static void __init early_initrd(char **p)
429{
430 unsigned long start, size;
431
432 start = memparse(*p, p);
433 if (**p == ',') {
434 size = memparse((*p) + 1, p);
435
436 phys_initrd_start = start;
437 phys_initrd_size = size;
438 }
439}
440__early_param("initrd=", early_initrd);
441
442static void __init arm_add_memory(unsigned long start, unsigned long size)
443{
444 struct membank *bank;
445
446
447
448
449
450 size -= start & ~PAGE_MASK;
451
452 bank = &meminfo.bank[meminfo.nr_banks++];
453
454 bank->start = PAGE_ALIGN(start);
455 bank->size = size & PAGE_MASK;
456 bank->node = PHYS_TO_NID(start);
457}
458
459
460
461
462
463static void __init early_mem(char **p)
464{
465 static int usermem __initdata = 0;
466 unsigned long size, start;
467
468
469
470
471
472
473 if (usermem == 0) {
474 usermem = 1;
475 meminfo.nr_banks = 0;
476 }
477
478 start = PHYS_OFFSET;
479 size = memparse(*p, p);
480 if (**p == '@')
481 start = memparse(*p + 1, p);
482
483 arm_add_memory(start, size);
484}
485__early_param("mem=", early_mem);
486
487
488
489
490static void __init parse_cmdline(char **cmdline_p, char *from)
491{
492 char c = ' ', *to = command_line;
493 int len = 0;
494
495 for (;;) {
496 if (c == ' ') {
497 extern struct early_params __early_begin, __early_end;
498 struct early_params *p;
499
500 for (p = &__early_begin; p < &__early_end; p++) {
501 int len = strlen(p->arg);
502
503 if (memcmp(from, p->arg, len) == 0) {
504 if (to != command_line)
505 to -= 1;
506 from += len;
507 p->fn(&from);
508
509 while (*from != ' ' && *from != '\0')
510 from++;
511 break;
512 }
513 }
514 }
515 c = *from++;
516 if (!c)
517 break;
518 if (COMMAND_LINE_SIZE <= ++len)
519 break;
520 *to++ = c;
521 }
522 *to = '\0';
523 *cmdline_p = command_line;
524}
525
526static void __init
527setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
528{
529#ifdef CONFIG_BLK_DEV_RAM
530 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
531
532 rd_image_start = image_start;
533 rd_prompt = prompt;
534 rd_doload = doload;
535
536 if (rd_sz)
537 rd_size = rd_sz;
538#endif
539}
540
541static void __init
542request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
543{
544 struct resource *res;
545 int i;
546
547 kernel_code.start = virt_to_phys(&_text);
548 kernel_code.end = virt_to_phys(&_etext - 1);
549 kernel_data.start = virt_to_phys(&__data_start);
550 kernel_data.end = virt_to_phys(&_end - 1);
551
552 for (i = 0; i < mi->nr_banks; i++) {
553 unsigned long virt_start, virt_end;
554
555 if (mi->bank[i].size == 0)
556 continue;
557
558 virt_start = __phys_to_virt(mi->bank[i].start);
559 virt_end = virt_start + mi->bank[i].size - 1;
560
561 res = alloc_bootmem_low(sizeof(*res));
562 res->name = "System RAM";
563 res->start = __virt_to_phys(virt_start);
564 res->end = __virt_to_phys(virt_end);
565 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
566
567 request_resource(&iomem_resource, res);
568
569 if (kernel_code.start >= res->start &&
570 kernel_code.end <= res->end)
571 request_resource(res, &kernel_code);
572 if (kernel_data.start >= res->start &&
573 kernel_data.end <= res->end)
574 request_resource(res, &kernel_data);
575 }
576
577 if (mdesc->video_start) {
578 video_ram.start = mdesc->video_start;
579 video_ram.end = mdesc->video_end;
580 request_resource(&iomem_resource, &video_ram);
581 }
582
583
584
585
586
587 if (mdesc->reserve_lp0)
588 request_resource(&ioport_resource, &lp0);
589 if (mdesc->reserve_lp1)
590 request_resource(&ioport_resource, &lp1);
591 if (mdesc->reserve_lp2)
592 request_resource(&ioport_resource, &lp2);
593}
594
595
596
597
598
599
600
601
602
603
604
605static int __init parse_tag_core(const struct tag *tag)
606{
607 if (tag->hdr.size > 2) {
608 if ((tag->u.core.flags & 1) == 0)
609 root_mountflags &= ~MS_RDONLY;
610 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
611 }
612 return 0;
613}
614
615__tagtable(ATAG_CORE, parse_tag_core);
616
617static int __init parse_tag_mem32(const struct tag *tag)
618{
619 if (meminfo.nr_banks >= NR_BANKS) {
620 printk(KERN_WARNING
621 "Ignoring memory bank 0x%08x size %dKB\n",
622 tag->u.mem.start, tag->u.mem.size / 1024);
623 return -EINVAL;
624 }
625 arm_add_memory(tag->u.mem.start, tag->u.mem.size);
626 return 0;
627}
628
629__tagtable(ATAG_MEM, parse_tag_mem32);
630
631#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
632struct screen_info screen_info = {
633 .orig_video_lines = 30,
634 .orig_video_cols = 80,
635 .orig_video_mode = 0,
636 .orig_video_ega_bx = 0,
637 .orig_video_isVGA = 1,
638 .orig_video_points = 8
639};
640
641static int __init parse_tag_videotext(const struct tag *tag)
642{
643 screen_info.orig_x = tag->u.videotext.x;
644 screen_info.orig_y = tag->u.videotext.y;
645 screen_info.orig_video_page = tag->u.videotext.video_page;
646 screen_info.orig_video_mode = tag->u.videotext.video_mode;
647 screen_info.orig_video_cols = tag->u.videotext.video_cols;
648 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
649 screen_info.orig_video_lines = tag->u.videotext.video_lines;
650 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
651 screen_info.orig_video_points = tag->u.videotext.video_points;
652 return 0;
653}
654
655__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
656#endif
657
658static int __init parse_tag_ramdisk(const struct tag *tag)
659{
660 setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
661 (tag->u.ramdisk.flags & 2) == 0,
662 tag->u.ramdisk.start, tag->u.ramdisk.size);
663 return 0;
664}
665
666__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
667
668static int __init parse_tag_initrd(const struct tag *tag)
669{
670 printk(KERN_WARNING "ATAG_INITRD is deprecated; "
671 "please update your bootloader.\n");
672 phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
673 phys_initrd_size = tag->u.initrd.size;
674 return 0;
675}
676
677__tagtable(ATAG_INITRD, parse_tag_initrd);
678
679static int __init parse_tag_initrd2(const struct tag *tag)
680{
681 phys_initrd_start = tag->u.initrd.start;
682 phys_initrd_size = tag->u.initrd.size;
683 return 0;
684}
685
686__tagtable(ATAG_INITRD2, parse_tag_initrd2);
687
688static int __init parse_tag_serialnr(const struct tag *tag)
689{
690 system_serial_low = tag->u.serialnr.low;
691 system_serial_high = tag->u.serialnr.high;
692 return 0;
693}
694
695__tagtable(ATAG_SERIAL, parse_tag_serialnr);
696
697static int __init parse_tag_revision(const struct tag *tag)
698{
699 system_rev = tag->u.revision.rev;
700 return 0;
701}
702
703__tagtable(ATAG_REVISION, parse_tag_revision);
704
705static int __init parse_tag_cmdline(const struct tag *tag)
706{
707 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
708 return 0;
709}
710
711__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
712
713
714
715
716
717
718static int __init parse_tag(const struct tag *tag)
719{
720 extern struct tagtable __tagtable_begin, __tagtable_end;
721 struct tagtable *t;
722
723 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
724 if (tag->hdr.tag == t->tag) {
725 t->parse(tag);
726 break;
727 }
728
729 return t < &__tagtable_end;
730}
731
732
733
734
735
736static void __init parse_tags(const struct tag *t)
737{
738 for (; t->hdr.size; t = tag_next(t))
739 if (!parse_tag(t))
740 printk(KERN_WARNING
741 "Ignoring unrecognised tag 0x%08x\n",
742 t->hdr.tag);
743}
744
745
746
747
748static struct init_tags {
749 struct tag_header hdr1;
750 struct tag_core core;
751 struct tag_header hdr2;
752 struct tag_mem32 mem;
753 struct tag_header hdr3;
754} init_tags __initdata = {
755 { tag_size(tag_core), ATAG_CORE },
756 { 1, PAGE_SIZE, 0xff },
757 { tag_size(tag_mem32), ATAG_MEM },
758 { MEM_SIZE, PHYS_OFFSET },
759 { 0, ATAG_NONE }
760};
761
762static void (*init_machine)(void) __initdata;
763
764static int __init customize_machine(void)
765{
766
767 if (init_machine)
768 init_machine();
769 return 0;
770}
771arch_initcall(customize_machine);
772
773void __init setup_arch(char **cmdline_p)
774{
775 struct tag *tags = (struct tag *)&init_tags;
776 struct machine_desc *mdesc;
777 char *from = default_command_line;
778
779 setup_processor();
780 mdesc = setup_machine(machine_arch_type);
781 machine_name = mdesc->name;
782
783 if (mdesc->soft_reboot)
784 reboot_setup("s");
785
786 if (__atags_pointer)
787 tags = phys_to_virt(__atags_pointer);
788 else if (mdesc->boot_params)
789 tags = phys_to_virt(mdesc->boot_params);
790
791
792
793
794
795 if (tags->hdr.tag != ATAG_CORE)
796 convert_to_tag_list(tags);
797 if (tags->hdr.tag != ATAG_CORE)
798 tags = (struct tag *)&init_tags;
799
800 if (mdesc->fixup)
801 mdesc->fixup(mdesc, tags, &from, &meminfo);
802
803 if (tags->hdr.tag == ATAG_CORE) {
804 if (meminfo.nr_banks != 0)
805 squash_mem_tags(tags);
806 parse_tags(tags);
807 }
808
809 init_mm.start_code = (unsigned long) &_text;
810 init_mm.end_code = (unsigned long) &_etext;
811 init_mm.end_data = (unsigned long) &_edata;
812 init_mm.brk = (unsigned long) &_end;
813
814 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
815 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
816 parse_cmdline(cmdline_p, from);
817 paging_init(&meminfo, mdesc);
818 request_standard_resources(&meminfo, mdesc);
819
820#ifdef CONFIG_SMP
821 smp_init_cpus();
822#endif
823
824 cpu_init();
825
826
827
828
829 init_arch_irq = mdesc->init_irq;
830 system_timer = mdesc->timer;
831 init_machine = mdesc->init_machine;
832
833#ifdef CONFIG_VT
834#if defined(CONFIG_VGA_CONSOLE)
835 conswitchp = &vga_con;
836#elif defined(CONFIG_DUMMY_CONSOLE)
837 conswitchp = &dummy_con;
838#endif
839#endif
840}
841
842
843static int __init topology_init(void)
844{
845 int cpu;
846
847 for_each_possible_cpu(cpu) {
848 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
849 cpuinfo->cpu.hotpluggable = 1;
850 register_cpu(&cpuinfo->cpu, cpu);
851 }
852
853 return 0;
854}
855
856subsys_initcall(topology_init);
857
858static const char *hwcap_str[] = {
859 "swp",
860 "half",
861 "thumb",
862 "26bit",
863 "fastmult",
864 "fpa",
865 "vfp",
866 "edsp",
867 "java",
868 "iwmmxt",
869 "crunch",
870 NULL
871};
872
873static void
874c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
875{
876 unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
877
878 seq_printf(m, "%s size\t\t: %d\n"
879 "%s assoc\t\t: %d\n"
880 "%s line length\t: %d\n"
881 "%s sets\t\t: %d\n",
882 type, mult << (8 + CACHE_SIZE(cache)),
883 type, (mult << CACHE_ASSOC(cache)) >> 1,
884 type, 8 << CACHE_LINE(cache),
885 type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
886 CACHE_LINE(cache)));
887}
888
889static int c_show(struct seq_file *m, void *v)
890{
891 int i;
892
893 seq_printf(m, "Processor\t: %s rev %d (%s)\n",
894 cpu_name, (int)processor_id & 15, elf_platform);
895
896#if defined(CONFIG_SMP)
897 for_each_online_cpu(i) {
898
899
900
901
902
903 seq_printf(m, "processor\t: %d\n", i);
904 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
905 per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
906 (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
907 }
908#else
909 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
910 loops_per_jiffy / (500000/HZ),
911 (loops_per_jiffy / (5000/HZ)) % 100);
912#endif
913
914
915 seq_puts(m, "Features\t: ");
916
917 for (i = 0; hwcap_str[i]; i++)
918 if (elf_hwcap & (1 << i))
919 seq_printf(m, "%s ", hwcap_str[i]);
920
921 seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
922 seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
923
924 if ((processor_id & 0x0008f000) == 0x00000000) {
925
926 seq_printf(m, "CPU part\t: %07x\n", processor_id >> 4);
927 } else {
928 if ((processor_id & 0x0008f000) == 0x00007000) {
929
930 seq_printf(m, "CPU variant\t: 0x%02x\n",
931 (processor_id >> 16) & 127);
932 } else {
933
934 seq_printf(m, "CPU variant\t: 0x%x\n",
935 (processor_id >> 20) & 15);
936 }
937 seq_printf(m, "CPU part\t: 0x%03x\n",
938 (processor_id >> 4) & 0xfff);
939 }
940 seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
941
942 {
943 unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
944 if (cache_info != processor_id) {
945 seq_printf(m, "Cache type\t: %s\n"
946 "Cache clean\t: %s\n"
947 "Cache lockdown\t: %s\n"
948 "Cache format\t: %s\n",
949 cache_types[CACHE_TYPE(cache_info)],
950 cache_clean[CACHE_TYPE(cache_info)],
951 cache_lockdown[CACHE_TYPE(cache_info)],
952 CACHE_S(cache_info) ? "Harvard" : "Unified");
953
954 if (CACHE_S(cache_info)) {
955 c_show_cache(m, "I", CACHE_ISIZE(cache_info));
956 c_show_cache(m, "D", CACHE_DSIZE(cache_info));
957 } else {
958 c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
959 }
960 }
961 }
962
963 seq_puts(m, "\n");
964
965 seq_printf(m, "Hardware\t: %s\n", machine_name);
966 seq_printf(m, "Revision\t: %04x\n", system_rev);
967 seq_printf(m, "Serial\t\t: %08x%08x\n",
968 system_serial_high, system_serial_low);
969
970 return 0;
971}
972
973static void *c_start(struct seq_file *m, loff_t *pos)
974{
975 return *pos < 1 ? (void *)1 : NULL;
976}
977
978static void *c_next(struct seq_file *m, void *v, loff_t *pos)
979{
980 ++*pos;
981 return NULL;
982}
983
984static void c_stop(struct seq_file *m, void *v)
985{
986}
987
988struct seq_operations cpuinfo_op = {
989 .start = c_start,
990 .next = c_next,
991 .stop = c_stop,
992 .show = c_show
993};
994