]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blob - arch/arm/kernel/setup.c
648c3c1e16c40dcd4504e90e96759113d5d7ee16
[lisovros/linux_canprio.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/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 #include <linux/proc_fs.h>
28
29 #include <asm/unified.h>
30 #include <asm/cpu.h>
31 #include <asm/cputype.h>
32 #include <asm/elf.h>
33 #include <asm/procinfo.h>
34 #include <asm/sections.h>
35 #include <asm/setup.h>
36 #include <asm/mach-types.h>
37 #include <asm/cacheflush.h>
38 #include <asm/cachetype.h>
39 #include <asm/tlbflush.h>
40
41 #include <asm/mach/arch.h>
42 #include <asm/mach/irq.h>
43 #include <asm/mach/time.h>
44 #include <asm/traps.h>
45 #include <asm/unwind.h>
46
47 #include "compat.h"
48 #include "atags.h"
49 #include "tcm.h"
50
51 #ifndef MEM_SIZE
52 #define MEM_SIZE        (16*1024*1024)
53 #endif
54
55 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
56 char fpe_type[8];
57
58 static int __init fpe_setup(char *line)
59 {
60         memcpy(fpe_type, line, 8);
61         return 1;
62 }
63
64 __setup("fpe=", fpe_setup);
65 #endif
66
67 extern void paging_init(struct machine_desc *desc);
68 extern void reboot_setup(char *str);
69
70 unsigned int processor_id;
71 EXPORT_SYMBOL(processor_id);
72 unsigned int __machine_arch_type;
73 EXPORT_SYMBOL(__machine_arch_type);
74 unsigned int cacheid;
75 EXPORT_SYMBOL(cacheid);
76
77 unsigned int __atags_pointer __initdata;
78
79 unsigned int system_rev;
80 EXPORT_SYMBOL(system_rev);
81
82 unsigned int system_serial_low;
83 EXPORT_SYMBOL(system_serial_low);
84
85 unsigned int system_serial_high;
86 EXPORT_SYMBOL(system_serial_high);
87
88 unsigned int elf_hwcap;
89 EXPORT_SYMBOL(elf_hwcap);
90
91
92 #ifdef MULTI_CPU
93 struct processor processor;
94 #endif
95 #ifdef MULTI_TLB
96 struct cpu_tlb_fns cpu_tlb;
97 #endif
98 #ifdef MULTI_USER
99 struct cpu_user_fns cpu_user;
100 #endif
101 #ifdef MULTI_CACHE
102 struct cpu_cache_fns cpu_cache;
103 #endif
104 #ifdef CONFIG_OUTER_CACHE
105 struct outer_cache_fns outer_cache;
106 EXPORT_SYMBOL(outer_cache);
107 #endif
108
109 struct stack {
110         u32 irq[3];
111         u32 abt[3];
112         u32 und[3];
113 } ____cacheline_aligned;
114
115 static struct stack stacks[NR_CPUS];
116
117 char elf_platform[ELF_PLATFORM_SIZE];
118 EXPORT_SYMBOL(elf_platform);
119
120 static const char *cpu_name;
121 static const char *machine_name;
122 static char __initdata cmd_line[COMMAND_LINE_SIZE];
123
124 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
125 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
126 #define ENDIANNESS ((char)endian_test.l)
127
128 DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
129
130 /*
131  * Standard memory resources
132  */
133 static struct resource mem_res[] = {
134         {
135                 .name = "Video RAM",
136                 .start = 0,
137                 .end = 0,
138                 .flags = IORESOURCE_MEM
139         },
140         {
141                 .name = "Kernel text",
142                 .start = 0,
143                 .end = 0,
144                 .flags = IORESOURCE_MEM
145         },
146         {
147                 .name = "Kernel data",
148                 .start = 0,
149                 .end = 0,
150                 .flags = IORESOURCE_MEM
151         }
152 };
153
154 #define video_ram   mem_res[0]
155 #define kernel_code mem_res[1]
156 #define kernel_data mem_res[2]
157
158 static struct resource io_res[] = {
159         {
160                 .name = "reserved",
161                 .start = 0x3bc,
162                 .end = 0x3be,
163                 .flags = IORESOURCE_IO | IORESOURCE_BUSY
164         },
165         {
166                 .name = "reserved",
167                 .start = 0x378,
168                 .end = 0x37f,
169                 .flags = IORESOURCE_IO | IORESOURCE_BUSY
170         },
171         {
172                 .name = "reserved",
173                 .start = 0x278,
174                 .end = 0x27f,
175                 .flags = IORESOURCE_IO | IORESOURCE_BUSY
176         }
177 };
178
179 #define lp0 io_res[0]
180 #define lp1 io_res[1]
181 #define lp2 io_res[2]
182
183 static const char *proc_arch[] = {
184         "undefined/unknown",
185         "3",
186         "4",
187         "4T",
188         "5",
189         "5T",
190         "5TE",
191         "5TEJ",
192         "6TEJ",
193         "7",
194         "?(11)",
195         "?(12)",
196         "?(13)",
197         "?(14)",
198         "?(15)",
199         "?(16)",
200         "?(17)",
201 };
202
203 int cpu_architecture(void)
204 {
205         int cpu_arch;
206
207         if ((read_cpuid_id() & 0x0008f000) == 0) {
208                 cpu_arch = CPU_ARCH_UNKNOWN;
209         } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
210                 cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
211         } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
212                 cpu_arch = (read_cpuid_id() >> 16) & 7;
213                 if (cpu_arch)
214                         cpu_arch += CPU_ARCH_ARMv3;
215         } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
216                 unsigned int mmfr0;
217
218                 /* Revised CPUID format. Read the Memory Model Feature
219                  * Register 0 and check for VMSAv7 or PMSAv7 */
220                 asm("mrc        p15, 0, %0, c0, c1, 4"
221                     : "=r" (mmfr0));
222                 if ((mmfr0 & 0x0000000f) == 0x00000003 ||
223                     (mmfr0 & 0x000000f0) == 0x00000030)
224                         cpu_arch = CPU_ARCH_ARMv7;
225                 else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
226                          (mmfr0 & 0x000000f0) == 0x00000020)
227                         cpu_arch = CPU_ARCH_ARMv6;
228                 else
229                         cpu_arch = CPU_ARCH_UNKNOWN;
230         } else
231                 cpu_arch = CPU_ARCH_UNKNOWN;
232
233         return cpu_arch;
234 }
235
236 static void __init cacheid_init(void)
237 {
238         unsigned int cachetype = read_cpuid_cachetype();
239         unsigned int arch = cpu_architecture();
240
241         if (arch >= CPU_ARCH_ARMv6) {
242                 if ((cachetype & (7 << 29)) == 4 << 29) {
243                         /* ARMv7 register format */
244                         cacheid = CACHEID_VIPT_NONALIASING;
245                         if ((cachetype & (3 << 14)) == 1 << 14)
246                                 cacheid |= CACHEID_ASID_TAGGED;
247                 } else if (cachetype & (1 << 23))
248                         cacheid = CACHEID_VIPT_ALIASING;
249                 else
250                         cacheid = CACHEID_VIPT_NONALIASING;
251         } else {
252                 cacheid = CACHEID_VIVT;
253         }
254
255         printk("CPU: %s data cache, %s instruction cache\n",
256                 cache_is_vivt() ? "VIVT" :
257                 cache_is_vipt_aliasing() ? "VIPT aliasing" :
258                 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
259                 cache_is_vivt() ? "VIVT" :
260                 icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
261                 cache_is_vipt_aliasing() ? "VIPT aliasing" :
262                 cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
263 }
264
265 /*
266  * These functions re-use the assembly code in head.S, which
267  * already provide the required functionality.
268  */
269 extern struct proc_info_list *lookup_processor_type(unsigned int);
270 extern struct machine_desc *lookup_machine_type(unsigned int);
271
272 static void __init feat_v6_fixup(void)
273 {
274         int id = read_cpuid_id();
275
276         if ((id & 0xff0f0000) != 0x41070000)
277                 return;
278
279         /*
280          * HWCAP_TLS is available only on 1136 r1p0 and later,
281          * see also kuser_get_tls_init.
282          */
283         if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0))
284                 elf_hwcap &= ~HWCAP_TLS;
285 }
286
287 static void __init setup_processor(void)
288 {
289         struct proc_info_list *list;
290
291         /*
292          * locate processor in the list of supported processor
293          * types.  The linker builds this table for us from the
294          * entries in arch/arm/mm/proc-*.S
295          */
296         list = lookup_processor_type(read_cpuid_id());
297         if (!list) {
298                 printk("CPU configuration botched (ID %08x), unable "
299                        "to continue.\n", read_cpuid_id());
300                 while (1);
301         }
302
303         cpu_name = list->cpu_name;
304
305 #ifdef MULTI_CPU
306         processor = *list->proc;
307 #endif
308 #ifdef MULTI_TLB
309         cpu_tlb = *list->tlb;
310 #endif
311 #ifdef MULTI_USER
312         cpu_user = *list->user;
313 #endif
314 #ifdef MULTI_CACHE
315         cpu_cache = *list->cache;
316 #endif
317
318         printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
319                cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
320                proc_arch[cpu_architecture()], cr_alignment);
321
322         sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
323         sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
324         elf_hwcap = list->elf_hwcap;
325 #ifndef CONFIG_ARM_THUMB
326         elf_hwcap &= ~HWCAP_THUMB;
327 #endif
328
329         feat_v6_fixup();
330
331         cacheid_init();
332         cpu_proc_init();
333 }
334
335 /*
336  * cpu_init - initialise one CPU.
337  *
338  * cpu_init sets up the per-CPU stacks.
339  */
340 void cpu_init(void)
341 {
342         unsigned int cpu = smp_processor_id();
343         struct stack *stk = &stacks[cpu];
344
345         if (cpu >= NR_CPUS) {
346                 printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
347                 BUG();
348         }
349
350         /*
351          * Define the placement constraint for the inline asm directive below.
352          * In Thumb-2, msr with an immediate value is not allowed.
353          */
354 #ifdef CONFIG_THUMB2_KERNEL
355 #define PLC     "r"
356 #else
357 #define PLC     "I"
358 #endif
359
360         /*
361          * setup stacks for re-entrant exception handlers
362          */
363         __asm__ (
364         "msr    cpsr_c, %1\n\t"
365         "add    r14, %0, %2\n\t"
366         "mov    sp, r14\n\t"
367         "msr    cpsr_c, %3\n\t"
368         "add    r14, %0, %4\n\t"
369         "mov    sp, r14\n\t"
370         "msr    cpsr_c, %5\n\t"
371         "add    r14, %0, %6\n\t"
372         "mov    sp, r14\n\t"
373         "msr    cpsr_c, %7"
374             :
375             : "r" (stk),
376               PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
377               "I" (offsetof(struct stack, irq[0])),
378               PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
379               "I" (offsetof(struct stack, abt[0])),
380               PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
381               "I" (offsetof(struct stack, und[0])),
382               PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
383             : "r14");
384 }
385
386 static struct machine_desc * __init setup_machine(unsigned int nr)
387 {
388         struct machine_desc *list;
389
390         /*
391          * locate machine in the list of supported machines.
392          */
393         list = lookup_machine_type(nr);
394         if (!list) {
395                 printk("Machine configuration botched (nr %d), unable "
396                        "to continue.\n", nr);
397                 while (1);
398         }
399
400         printk("Machine: %s\n", list->name);
401
402         return list;
403 }
404
405 static int __init arm_add_memory(unsigned long start, unsigned long size)
406 {
407         struct membank *bank = &meminfo.bank[meminfo.nr_banks];
408
409         if (meminfo.nr_banks >= NR_BANKS) {
410                 printk(KERN_CRIT "NR_BANKS too low, "
411                         "ignoring memory at %#lx\n", start);
412                 return -EINVAL;
413         }
414
415         /*
416          * Ensure that start/size are aligned to a page boundary.
417          * Size is appropriately rounded down, start is rounded up.
418          */
419         size -= start & ~PAGE_MASK;
420         bank->start = PAGE_ALIGN(start);
421         bank->size  = size & PAGE_MASK;
422         bank->node  = PHYS_TO_NID(start);
423
424         /*
425          * Check whether this memory region has non-zero size or
426          * invalid node number.
427          */
428         if (bank->size == 0 || bank->node >= MAX_NUMNODES)
429                 return -EINVAL;
430
431         meminfo.nr_banks++;
432         return 0;
433 }
434
435 /*
436  * Pick out the memory size.  We look for mem=size@start,
437  * where start and size are "size[KkMm]"
438  */
439 static int __init early_mem(char *p)
440 {
441         static int usermem __initdata = 0;
442         unsigned long size, start;
443         char *endp;
444
445         /*
446          * If the user specifies memory size, we
447          * blow away any automatically generated
448          * size.
449          */
450         if (usermem == 0) {
451                 usermem = 1;
452                 meminfo.nr_banks = 0;
453         }
454
455         start = PHYS_OFFSET;
456         size  = memparse(p, &endp);
457         if (*endp == '@')
458                 start = memparse(endp + 1, NULL);
459
460         arm_add_memory(start, size);
461
462         return 0;
463 }
464 early_param("mem", early_mem);
465
466 static void __init
467 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
468 {
469 #ifdef CONFIG_BLK_DEV_RAM
470         extern int rd_size, rd_image_start, rd_prompt, rd_doload;
471
472         rd_image_start = image_start;
473         rd_prompt = prompt;
474         rd_doload = doload;
475
476         if (rd_sz)
477                 rd_size = rd_sz;
478 #endif
479 }
480
481 static void __init
482 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
483 {
484         struct resource *res;
485         int i;
486
487         kernel_code.start   = virt_to_phys(_text);
488         kernel_code.end     = virt_to_phys(_etext - 1);
489         kernel_data.start   = virt_to_phys(_data);
490         kernel_data.end     = virt_to_phys(_end - 1);
491
492         for (i = 0; i < mi->nr_banks; i++) {
493                 if (mi->bank[i].size == 0)
494                         continue;
495
496                 res = alloc_bootmem_low(sizeof(*res));
497                 res->name  = "System RAM";
498                 res->start = mi->bank[i].start;
499                 res->end   = mi->bank[i].start + mi->bank[i].size - 1;
500                 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
501
502                 request_resource(&iomem_resource, res);
503
504                 if (kernel_code.start >= res->start &&
505                     kernel_code.end <= res->end)
506                         request_resource(res, &kernel_code);
507                 if (kernel_data.start >= res->start &&
508                     kernel_data.end <= res->end)
509                         request_resource(res, &kernel_data);
510         }
511
512         if (mdesc->video_start) {
513                 video_ram.start = mdesc->video_start;
514                 video_ram.end   = mdesc->video_end;
515                 request_resource(&iomem_resource, &video_ram);
516         }
517
518         /*
519          * Some machines don't have the possibility of ever
520          * possessing lp0, lp1 or lp2
521          */
522         if (mdesc->reserve_lp0)
523                 request_resource(&ioport_resource, &lp0);
524         if (mdesc->reserve_lp1)
525                 request_resource(&ioport_resource, &lp1);
526         if (mdesc->reserve_lp2)
527                 request_resource(&ioport_resource, &lp2);
528 }
529
530 /*
531  *  Tag parsing.
532  *
533  * This is the new way of passing data to the kernel at boot time.  Rather
534  * than passing a fixed inflexible structure to the kernel, we pass a list
535  * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
536  * tag for the list to be recognised (to distinguish the tagged list from
537  * a param_struct).  The list is terminated with a zero-length tag (this tag
538  * is not parsed in any way).
539  */
540 static int __init parse_tag_core(const struct tag *tag)
541 {
542         if (tag->hdr.size > 2) {
543                 if ((tag->u.core.flags & 1) == 0)
544                         root_mountflags &= ~MS_RDONLY;
545                 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
546         }
547         return 0;
548 }
549
550 __tagtable(ATAG_CORE, parse_tag_core);
551
552 static int __init parse_tag_mem32(const struct tag *tag)
553 {
554         return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
555 }
556
557 __tagtable(ATAG_MEM, parse_tag_mem32);
558
559 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
560 struct screen_info screen_info = {
561  .orig_video_lines      = 30,
562  .orig_video_cols       = 80,
563  .orig_video_mode       = 0,
564  .orig_video_ega_bx     = 0,
565  .orig_video_isVGA      = 1,
566  .orig_video_points     = 8
567 };
568
569 static int __init parse_tag_videotext(const struct tag *tag)
570 {
571         screen_info.orig_x            = tag->u.videotext.x;
572         screen_info.orig_y            = tag->u.videotext.y;
573         screen_info.orig_video_page   = tag->u.videotext.video_page;
574         screen_info.orig_video_mode   = tag->u.videotext.video_mode;
575         screen_info.orig_video_cols   = tag->u.videotext.video_cols;
576         screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
577         screen_info.orig_video_lines  = tag->u.videotext.video_lines;
578         screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
579         screen_info.orig_video_points = tag->u.videotext.video_points;
580         return 0;
581 }
582
583 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
584 #endif
585
586 static int __init parse_tag_ramdisk(const struct tag *tag)
587 {
588         setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
589                       (tag->u.ramdisk.flags & 2) == 0,
590                       tag->u.ramdisk.start, tag->u.ramdisk.size);
591         return 0;
592 }
593
594 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
595
596 static int __init parse_tag_serialnr(const struct tag *tag)
597 {
598         system_serial_low = tag->u.serialnr.low;
599         system_serial_high = tag->u.serialnr.high;
600         return 0;
601 }
602
603 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
604
605 static int __init parse_tag_revision(const struct tag *tag)
606 {
607         system_rev = tag->u.revision.rev;
608         return 0;
609 }
610
611 __tagtable(ATAG_REVISION, parse_tag_revision);
612
613 #ifndef CONFIG_CMDLINE_FORCE
614 static int __init parse_tag_cmdline(const struct tag *tag)
615 {
616         strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
617         return 0;
618 }
619
620 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
621 #endif /* CONFIG_CMDLINE_FORCE */
622
623 /*
624  * Scan the tag table for this tag, and call its parse function.
625  * The tag table is built by the linker from all the __tagtable
626  * declarations.
627  */
628 static int __init parse_tag(const struct tag *tag)
629 {
630         extern struct tagtable __tagtable_begin, __tagtable_end;
631         struct tagtable *t;
632
633         for (t = &__tagtable_begin; t < &__tagtable_end; t++)
634                 if (tag->hdr.tag == t->tag) {
635                         t->parse(tag);
636                         break;
637                 }
638
639         return t < &__tagtable_end;
640 }
641
642 /*
643  * Parse all tags in the list, checking both the global and architecture
644  * specific tag tables.
645  */
646 static void __init parse_tags(const struct tag *t)
647 {
648         for (; t->hdr.size; t = tag_next(t))
649                 if (!parse_tag(t))
650                         printk(KERN_WARNING
651                                 "Ignoring unrecognised tag 0x%08x\n",
652                                 t->hdr.tag);
653 }
654
655 /*
656  * This holds our defaults.
657  */
658 static struct init_tags {
659         struct tag_header hdr1;
660         struct tag_core   core;
661         struct tag_header hdr2;
662         struct tag_mem32  mem;
663         struct tag_header hdr3;
664 } init_tags __initdata = {
665         { tag_size(tag_core), ATAG_CORE },
666         { 1, PAGE_SIZE, 0xff },
667         { tag_size(tag_mem32), ATAG_MEM },
668         { MEM_SIZE, PHYS_OFFSET },
669         { 0, ATAG_NONE }
670 };
671
672 static void (*init_machine)(void) __initdata;
673
674 static int __init customize_machine(void)
675 {
676         /* customizes platform devices, or adds new ones */
677         if (init_machine)
678                 init_machine();
679         return 0;
680 }
681 arch_initcall(customize_machine);
682
683 void __init setup_arch(char **cmdline_p)
684 {
685         struct tag *tags = (struct tag *)&init_tags;
686         struct machine_desc *mdesc;
687         char *from = default_command_line;
688
689         unwind_init();
690
691         setup_processor();
692         mdesc = setup_machine(machine_arch_type);
693         machine_name = mdesc->name;
694
695         if (mdesc->soft_reboot)
696                 reboot_setup("s");
697
698         if (__atags_pointer)
699                 tags = phys_to_virt(__atags_pointer);
700         else if (mdesc->boot_params)
701                 tags = phys_to_virt(mdesc->boot_params);
702
703         /*
704          * If we have the old style parameters, convert them to
705          * a tag list.
706          */
707         if (tags->hdr.tag != ATAG_CORE)
708                 convert_to_tag_list(tags);
709         if (tags->hdr.tag != ATAG_CORE)
710                 tags = (struct tag *)&init_tags;
711
712         if (mdesc->fixup)
713                 mdesc->fixup(mdesc, tags, &from, &meminfo);
714
715         if (tags->hdr.tag == ATAG_CORE) {
716                 if (meminfo.nr_banks != 0)
717                         squash_mem_tags(tags);
718                 save_atags(tags);
719                 parse_tags(tags);
720         }
721
722         init_mm.start_code = (unsigned long) _text;
723         init_mm.end_code   = (unsigned long) _etext;
724         init_mm.end_data   = (unsigned long) _edata;
725         init_mm.brk        = (unsigned long) _end;
726
727         /* parse_early_param needs a boot_command_line */
728         strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
729
730         /* populate cmd_line too for later use, preserving boot_command_line */
731         strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
732         *cmdline_p = cmd_line;
733
734         parse_early_param();
735
736         paging_init(mdesc);
737         request_standard_resources(&meminfo, mdesc);
738
739 #ifdef CONFIG_SMP
740         smp_init_cpus();
741 #endif
742
743         cpu_init();
744         tcm_init();
745
746         /*
747          * Set up various architecture-specific pointers
748          */
749         arch_nr_irqs = mdesc->nr_irqs;
750         init_arch_irq = mdesc->init_irq;
751         system_timer = mdesc->timer;
752         init_machine = mdesc->init_machine;
753
754 #ifdef CONFIG_VT
755 #if defined(CONFIG_VGA_CONSOLE)
756         conswitchp = &vga_con;
757 #elif defined(CONFIG_DUMMY_CONSOLE)
758         conswitchp = &dummy_con;
759 #endif
760 #endif
761         early_trap_init();
762 }
763
764
765 static int __init topology_init(void)
766 {
767         int cpu;
768
769         for_each_possible_cpu(cpu) {
770                 struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
771                 cpuinfo->cpu.hotpluggable = 1;
772                 register_cpu(&cpuinfo->cpu, cpu);
773         }
774
775         return 0;
776 }
777 subsys_initcall(topology_init);
778
779 #ifdef CONFIG_HAVE_PROC_CPU
780 static int __init proc_cpu_init(void)
781 {
782         struct proc_dir_entry *res;
783
784         res = proc_mkdir("cpu", NULL);
785         if (!res)
786                 return -ENOMEM;
787         return 0;
788 }
789 fs_initcall(proc_cpu_init);
790 #endif
791
792 static const char *hwcap_str[] = {
793         "swp",
794         "half",
795         "thumb",
796         "26bit",
797         "fastmult",
798         "fpa",
799         "vfp",
800         "edsp",
801         "java",
802         "iwmmxt",
803         "crunch",
804         "thumbee",
805         "neon",
806         "vfpv3",
807         "vfpv3d16",
808         NULL
809 };
810
811 static int c_show(struct seq_file *m, void *v)
812 {
813         int i;
814
815         seq_printf(m, "Processor\t: %s rev %d (%s)\n",
816                    cpu_name, read_cpuid_id() & 15, elf_platform);
817
818 #if defined(CONFIG_SMP)
819         for_each_online_cpu(i) {
820                 /*
821                  * glibc reads /proc/cpuinfo to determine the number of
822                  * online processors, looking for lines beginning with
823                  * "processor".  Give glibc what it expects.
824                  */
825                 seq_printf(m, "processor\t: %d\n", i);
826                 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
827                            per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
828                            (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
829         }
830 #else /* CONFIG_SMP */
831         seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
832                    loops_per_jiffy / (500000/HZ),
833                    (loops_per_jiffy / (5000/HZ)) % 100);
834 #endif
835
836         /* dump out the processor features */
837         seq_puts(m, "Features\t: ");
838
839         for (i = 0; hwcap_str[i]; i++)
840                 if (elf_hwcap & (1 << i))
841                         seq_printf(m, "%s ", hwcap_str[i]);
842
843         seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
844         seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
845
846         if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
847                 /* pre-ARM7 */
848                 seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
849         } else {
850                 if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
851                         /* ARM7 */
852                         seq_printf(m, "CPU variant\t: 0x%02x\n",
853                                    (read_cpuid_id() >> 16) & 127);
854                 } else {
855                         /* post-ARM7 */
856                         seq_printf(m, "CPU variant\t: 0x%x\n",
857                                    (read_cpuid_id() >> 20) & 15);
858                 }
859                 seq_printf(m, "CPU part\t: 0x%03x\n",
860                            (read_cpuid_id() >> 4) & 0xfff);
861         }
862         seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
863
864         seq_puts(m, "\n");
865
866         seq_printf(m, "Hardware\t: %s\n", machine_name);
867         seq_printf(m, "Revision\t: %04x\n", system_rev);
868         seq_printf(m, "Serial\t\t: %08x%08x\n",
869                    system_serial_high, system_serial_low);
870
871         return 0;
872 }
873
874 static void *c_start(struct seq_file *m, loff_t *pos)
875 {
876         return *pos < 1 ? (void *)1 : NULL;
877 }
878
879 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
880 {
881         ++*pos;
882         return NULL;
883 }
884
885 static void c_stop(struct seq_file *m, void *v)
886 {
887 }
888
889 const struct seq_operations cpuinfo_op = {
890         .start  = c_start,
891         .next   = c_next,
892         .stop   = c_stop,
893         .show   = c_show
894 };