Merge branches 'at91', 'ep93xx', 'kexec', 'iop', 'lmb', 'nomadik', 'nuc', 'pl', ...
[linux-2.6.git] / arch / arm / kernel / setup.c
index 2ca7038..776ea1a 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/screen_info.h>
 #include <linux/init.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/memblock.h>
 
+#include <asm/unified.h>
 #include <asm/cpu.h>
+#include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/procinfo.h>
+#include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/cacheflush.h>
+#include <asm/cachetype.h>
 #include <asm/tlbflush.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/traps.h>
+#include <asm/unwind.h>
 
 #include "compat.h"
 #include "atags.h"
+#include "tcm.h"
 
 #ifndef MEM_SIZE
 #define MEM_SIZE       (16*1024*1024)
@@ -57,15 +67,15 @@ static int __init fpe_setup(char *line)
 __setup("fpe=", fpe_setup);
 #endif
 
-extern void paging_init(struct meminfo *, struct machine_desc *desc);
+extern void paging_init(struct machine_desc *desc);
 extern void reboot_setup(char *str);
-extern int root_mountflags;
-extern void _stext, _text, _etext, __data_start, _edata, _end;
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
 unsigned int __machine_arch_type;
 EXPORT_SYMBOL(__machine_arch_type);
+unsigned int cacheid;
+EXPORT_SYMBOL(cacheid);
 
 unsigned int __atags_pointer __initdata;
 
@@ -81,8 +91,6 @@ EXPORT_SYMBOL(system_serial_high);
 unsigned int elf_hwcap;
 EXPORT_SYMBOL(elf_hwcap);
 
-unsigned long __initdata vmalloc_reserve = 128 << 20;
-
 
 #ifdef MULTI_CPU
 struct processor processor;
@@ -98,6 +106,7 @@ struct cpu_cache_fns cpu_cache;
 #endif
 #ifdef CONFIG_OUTER_CACHE
 struct outer_cache_fns outer_cache;
+EXPORT_SYMBOL(outer_cache);
 #endif
 
 struct stack {
@@ -111,13 +120,9 @@ static struct stack stacks[NR_CPUS];
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
 
-unsigned long phys_initrd_start __initdata = 0;
-unsigned long phys_initrd_size __initdata = 0;
-
-static struct meminfo meminfo __initdata = { 0, };
 static const char *cpu_name;
 static const char *machine_name;
-static char __initdata command_line[COMMAND_LINE_SIZE];
+static char __initdata cmd_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -178,63 +183,6 @@ static struct resource io_res[] = {
 #define lp1 io_res[1]
 #define lp2 io_res[2]
 
-static const char *cache_types[16] = {
-       "write-through",
-       "write-back",
-       "write-back",
-       "undefined 3",
-       "undefined 4",
-       "undefined 5",
-       "write-back",
-       "write-back",
-       "undefined 8",
-       "undefined 9",
-       "undefined 10",
-       "undefined 11",
-       "undefined 12",
-       "undefined 13",
-       "write-back",
-       "undefined 15",
-};
-
-static const char *cache_clean[16] = {
-       "not required",
-       "read-block",
-       "cp15 c7 ops",
-       "undefined 3",
-       "undefined 4",
-       "undefined 5",
-       "cp15 c7 ops",
-       "cp15 c7 ops",
-       "undefined 8",
-       "undefined 9",
-       "undefined 10",
-       "undefined 11",
-       "undefined 12",
-       "undefined 13",
-       "cp15 c7 ops",
-       "undefined 15",
-};
-
-static const char *cache_lockdown[16] = {
-       "not supported",
-       "not supported",
-       "not supported",
-       "undefined 3",
-       "undefined 4",
-       "undefined 5",
-       "format A",
-       "format B",
-       "undefined 8",
-       "undefined 9",
-       "undefined 10",
-       "undefined 11",
-       "undefined 12",
-       "undefined 13",
-       "format C",
-       "undefined 15",
-};
-
 static const char *proc_arch[] = {
        "undefined/unknown",
        "3",
@@ -255,61 +203,19 @@ static const char *proc_arch[] = {
        "?(17)",
 };
 
-#define CACHE_TYPE(x)  (((x) >> 25) & 15)
-#define CACHE_S(x)     ((x) & (1 << 24))
-#define CACHE_DSIZE(x) (((x) >> 12) & 4095)    /* only if S=1 */
-#define CACHE_ISIZE(x) ((x) & 4095)
-
-#define CACHE_SIZE(y)  (((y) >> 6) & 7)
-#define CACHE_ASSOC(y) (((y) >> 3) & 7)
-#define CACHE_M(y)     ((y) & (1 << 2))
-#define CACHE_LINE(y)  ((y) & 3)
-
-static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
-{
-       unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-
-       printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n",
-               cpu, prefix,
-               mult << (8 + CACHE_SIZE(cache)),
-               (mult << CACHE_ASSOC(cache)) >> 1,
-               8 << CACHE_LINE(cache),
-               1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-                       CACHE_LINE(cache)));
-}
-
-static void __init dump_cpu_info(int cpu)
-{
-       unsigned int info = read_cpuid(CPUID_CACHETYPE);
-
-       if (info != processor_id) {
-               printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
-                      cache_types[CACHE_TYPE(info)]);
-               if (CACHE_S(info)) {
-                       dump_cache("I cache", cpu, CACHE_ISIZE(info));
-                       dump_cache("D cache", cpu, CACHE_DSIZE(info));
-               } else {
-                       dump_cache("cache", cpu, CACHE_ISIZE(info));
-               }
-       }
-
-       if (arch_is_coherent())
-               printk("Cache coherency enabled\n");
-}
-
 int cpu_architecture(void)
 {
        int cpu_arch;
 
-       if ((processor_id & 0x0008f000) == 0) {
+       if ((read_cpuid_id() & 0x0008f000) == 0) {
                cpu_arch = CPU_ARCH_UNKNOWN;
-       } else if ((processor_id & 0x0008f000) == 0x00007000) {
-               cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
-       } else if ((processor_id & 0x00080000) == 0x00000000) {
-               cpu_arch = (processor_id >> 16) & 7;
+       } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
+               cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
+       } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
+               cpu_arch = (read_cpuid_id() >> 16) & 7;
                if (cpu_arch)
                        cpu_arch += CPU_ARCH_ARMv3;
-       } else if ((processor_id & 0x000f0000) == 0x000f0000) {
+       } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
                unsigned int mmfr0;
 
                /* Revised CPUID format. Read the Memory Model Feature
@@ -330,6 +236,35 @@ int cpu_architecture(void)
        return cpu_arch;
 }
 
+static void __init cacheid_init(void)
+{
+       unsigned int cachetype = read_cpuid_cachetype();
+       unsigned int arch = cpu_architecture();
+
+       if (arch >= CPU_ARCH_ARMv6) {
+               if ((cachetype & (7 << 29)) == 4 << 29) {
+                       /* ARMv7 register format */
+                       cacheid = CACHEID_VIPT_NONALIASING;
+                       if ((cachetype & (3 << 14)) == 1 << 14)
+                               cacheid |= CACHEID_ASID_TAGGED;
+               } else if (cachetype & (1 << 23))
+                       cacheid = CACHEID_VIPT_ALIASING;
+               else
+                       cacheid = CACHEID_VIPT_NONALIASING;
+       } else {
+               cacheid = CACHEID_VIVT;
+       }
+
+       printk("CPU: %s data cache, %s instruction cache\n",
+               cache_is_vivt() ? "VIVT" :
+               cache_is_vipt_aliasing() ? "VIPT aliasing" :
+               cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+               cache_is_vivt() ? "VIVT" :
+               icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
+               cache_is_vipt_aliasing() ? "VIPT aliasing" :
+               cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
+}
+
 /*
  * These functions re-use the assembly code in head.S, which
  * already provide the required functionality.
@@ -337,6 +272,21 @@ int cpu_architecture(void)
 extern struct proc_info_list *lookup_processor_type(unsigned int);
 extern struct machine_desc *lookup_machine_type(unsigned int);
 
+static void __init feat_v6_fixup(void)
+{
+       int id = read_cpuid_id();
+
+       if ((id & 0xff0f0000) != 0x41070000)
+               return;
+
+       /*
+        * HWCAP_TLS is available only on 1136 r1p0 and later,
+        * see also kuser_get_tls_init.
+        */
+       if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0))
+               elf_hwcap &= ~HWCAP_TLS;
+}
+
 static void __init setup_processor(void)
 {
        struct proc_info_list *list;
@@ -346,10 +296,10 @@ static void __init setup_processor(void)
         * types.  The linker builds this table for us from the
         * entries in arch/arm/mm/proc-*.S
         */
-       list = lookup_processor_type(processor_id);
+       list = lookup_processor_type(read_cpuid_id());
        if (!list) {
                printk("CPU configuration botched (ID %08x), unable "
-                      "to continue.\n", processor_id);
+                      "to continue.\n", read_cpuid_id());
                while (1);
        }
 
@@ -369,7 +319,7 @@ static void __init setup_processor(void)
 #endif
 
        printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-              cpu_name, processor_id, (int)processor_id & 15,
+              cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
               proc_arch[cpu_architecture()], cr_alignment);
 
        sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
@@ -379,14 +329,16 @@ static void __init setup_processor(void)
        elf_hwcap &= ~HWCAP_THUMB;
 #endif
 
+       feat_v6_fixup();
+
+       cacheid_init();
        cpu_proc_init();
 }
 
 /*
  * cpu_init - initialise one CPU.
  *
- * cpu_init dumps the cache information, initialises SMP specific
- * information, and sets up the per-CPU stacks.
+ * cpu_init sets up the per-CPU stacks.
  */
 void cpu_init(void)
 {
@@ -398,29 +350,39 @@ void cpu_init(void)
                BUG();
        }
 
-       if (system_state == SYSTEM_BOOTING)
-               dump_cpu_info(cpu);
+       /*
+        * Define the placement constraint for the inline asm directive below.
+        * In Thumb-2, msr with an immediate value is not allowed.
+        */
+#ifdef CONFIG_THUMB2_KERNEL
+#define PLC    "r"
+#else
+#define PLC    "I"
+#endif
 
        /*
         * setup stacks for re-entrant exception handlers
         */
        __asm__ (
        "msr    cpsr_c, %1\n\t"
-       "add    sp, %0, %2\n\t"
+       "add    r14, %0, %2\n\t"
+       "mov    sp, r14\n\t"
        "msr    cpsr_c, %3\n\t"
-       "add    sp, %0, %4\n\t"
+       "add    r14, %0, %4\n\t"
+       "mov    sp, r14\n\t"
        "msr    cpsr_c, %5\n\t"
-       "add    sp, %0, %6\n\t"
+       "add    r14, %0, %6\n\t"
+       "mov    sp, r14\n\t"
        "msr    cpsr_c, %7"
            :
            : "r" (stk),
-             "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+             PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
              "I" (offsetof(struct stack, irq[0])),
-             "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+             PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
              "I" (offsetof(struct stack, abt[0])),
-             "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+             PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
              "I" (offsetof(struct stack, und[0])),
-             "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+             PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
            : "r14");
 }
 
@@ -443,45 +405,44 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
        return list;
 }
 
-static void __init early_initrd(char **p)
+static int __init arm_add_memory(unsigned long start, unsigned long size)
 {
-       unsigned long start, size;
+       struct membank *bank = &meminfo.bank[meminfo.nr_banks];
 
-       start = memparse(*p, p);
-       if (**p == ',') {
-               size = memparse((*p) + 1, p);
-
-               phys_initrd_start = start;
-               phys_initrd_size = size;
+       if (meminfo.nr_banks >= NR_BANKS) {
+               printk(KERN_CRIT "NR_BANKS too low, "
+                       "ignoring memory at %#lx\n", start);
+               return -EINVAL;
        }
-}
-__early_param("initrd=", early_initrd);
-
-static void __init arm_add_memory(unsigned long start, unsigned long size)
-{
-       struct membank *bank;
 
        /*
         * Ensure that start/size are aligned to a page boundary.
         * Size is appropriately rounded down, start is rounded up.
         */
        size -= start & ~PAGE_MASK;
-
-       bank = &meminfo.bank[meminfo.nr_banks++];
-
        bank->start = PAGE_ALIGN(start);
        bank->size  = size & PAGE_MASK;
-       bank->node  = PHYS_TO_NID(start);
+
+       /*
+        * Check whether this memory region has non-zero size or
+        * invalid node number.
+        */
+       if (bank->size == 0)
+               return -EINVAL;
+
+       meminfo.nr_banks++;
+       return 0;
 }
 
 /*
  * Pick out the memory size.  We look for mem=size@start,
  * where start and size are "size[KkMm]"
  */
-static void __init early_mem(char **p)
+static int __init early_mem(char *p)
 {
        static int usermem __initdata = 0;
        unsigned long size, start;
+       char *endp;
 
        /*
         * If the user specifies memory size, we
@@ -494,63 +455,15 @@ static void __init early_mem(char **p)
        }
 
        start = PHYS_OFFSET;
-       size  = memparse(*p, p);
-       if (**p == '@')
-               start = memparse(*p + 1, p);
+       size  = memparse(p, &endp);
+       if (*endp == '@')
+               start = memparse(endp + 1, NULL);
 
        arm_add_memory(start, size);
-}
-__early_param("mem=", early_mem);
 
-/*
- * vmalloc=size forces the vmalloc area to be exactly 'size'
- * bytes. This can be used to increase (or decrease) the vmalloc
- * area - the default is 128m.
- */
-static void __init early_vmalloc(char **arg)
-{
-       vmalloc_reserve = memparse(*arg, arg);
-}
-__early_param("vmalloc=", early_vmalloc);
-
-/*
- * Initial parsing of the command line.
- */
-static void __init parse_cmdline(char **cmdline_p, char *from)
-{
-       char c = ' ', *to = command_line;
-       int len = 0;
-
-       for (;;) {
-               if (c == ' ') {
-                       extern struct early_params __early_begin, __early_end;
-                       struct early_params *p;
-
-                       for (p = &__early_begin; p < &__early_end; p++) {
-                               int len = strlen(p->arg);
-
-                               if (memcmp(from, p->arg, len) == 0) {
-                                       if (to != command_line)
-                                               to -= 1;
-                                       from += len;
-                                       p->fn(&from);
-
-                                       while (*from != ' ' && *from != '\0')
-                                               from++;
-                                       break;
-                               }
-                       }
-               }
-               c = *from++;
-               if (!c)
-                       break;
-               if (COMMAND_LINE_SIZE <= ++len)
-                       break;
-               *to++ = c;
-       }
-       *to = '\0';
-       *cmdline_p = command_line;
+       return 0;
 }
+early_param("mem", early_mem);
 
 static void __init
 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
@@ -573,24 +486,19 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
        struct resource *res;
        int i;
 
-       kernel_code.start   = virt_to_phys(&_text);
-       kernel_code.end     = virt_to_phys(&_etext - 1);
-       kernel_data.start   = virt_to_phys(&__data_start);
-       kernel_data.end     = virt_to_phys(&_end - 1);
+       kernel_code.start   = virt_to_phys(_text);
+       kernel_code.end     = virt_to_phys(_etext - 1);
+       kernel_data.start   = virt_to_phys(_data);
+       kernel_data.end     = virt_to_phys(_end - 1);
 
        for (i = 0; i < mi->nr_banks; i++) {
-               unsigned long virt_start, virt_end;
-
                if (mi->bank[i].size == 0)
                        continue;
 
-               virt_start = __phys_to_virt(mi->bank[i].start);
-               virt_end   = virt_start + mi->bank[i].size - 1;
-
                res = alloc_bootmem_low(sizeof(*res));
                res->name  = "System RAM";
-               res->start = __virt_to_phys(virt_start);
-               res->end   = __virt_to_phys(virt_end);
+               res->start = mi->bank[i].start;
+               res->end   = mi->bank[i].start + mi->bank[i].size - 1;
                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 
                request_resource(&iomem_resource, res);
@@ -645,14 +553,7 @@ __tagtable(ATAG_CORE, parse_tag_core);
 
 static int __init parse_tag_mem32(const struct tag *tag)
 {
-       if (meminfo.nr_banks >= NR_BANKS) {
-               printk(KERN_WARNING
-                      "Ignoring memory bank 0x%08x size %dKB\n",
-                       tag->u.mem.start, tag->u.mem.size / 1024);
-               return -EINVAL;
-       }
-       arm_add_memory(tag->u.mem.start, tag->u.mem.size);
-       return 0;
+       return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
 }
 
 __tagtable(ATAG_MEM, parse_tag_mem32);
@@ -694,26 +595,6 @@ static int __init parse_tag_ramdisk(const struct tag *tag)
 
 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
 
-static int __init parse_tag_initrd(const struct tag *tag)
-{
-       printk(KERN_WARNING "ATAG_INITRD is deprecated; "
-               "please update your bootloader.\n");
-       phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
-       phys_initrd_size = tag->u.initrd.size;
-       return 0;
-}
-
-__tagtable(ATAG_INITRD, parse_tag_initrd);
-
-static int __init parse_tag_initrd2(const struct tag *tag)
-{
-       phys_initrd_start = tag->u.initrd.start;
-       phys_initrd_size = tag->u.initrd.size;
-       return 0;
-}
-
-__tagtable(ATAG_INITRD2, parse_tag_initrd2);
-
 static int __init parse_tag_serialnr(const struct tag *tag)
 {
        system_serial_low = tag->u.serialnr.low;
@@ -731,6 +612,7 @@ static int __init parse_tag_revision(const struct tag *tag)
 
 __tagtable(ATAG_REVISION, parse_tag_revision);
 
+#ifndef CONFIG_CMDLINE_FORCE
 static int __init parse_tag_cmdline(const struct tag *tag)
 {
        strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
@@ -738,6 +620,7 @@ static int __init parse_tag_cmdline(const struct tag *tag)
 }
 
 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
+#endif /* CONFIG_CMDLINE_FORCE */
 
 /*
  * Scan the tag table for this tag, and call its parse function.
@@ -799,12 +682,87 @@ static int __init customize_machine(void)
 }
 arch_initcall(customize_machine);
 
+#ifdef CONFIG_KEXEC
+static inline unsigned long long get_total_mem(void)
+{
+       unsigned long total;
+
+       total = max_low_pfn - min_low_pfn;
+       return total << PAGE_SHIFT;
+}
+
+/**
+ * reserve_crashkernel() - reserves memory are for crash kernel
+ *
+ * This function reserves memory area given in "crashkernel=" kernel command
+ * line parameter. The memory reserved is used by a dump capture kernel when
+ * primary kernel is crashing.
+ */
+static void __init reserve_crashkernel(void)
+{
+       unsigned long long crash_size, crash_base;
+       unsigned long long total_mem;
+       int ret;
+
+       total_mem = get_total_mem();
+       ret = parse_crashkernel(boot_command_line, total_mem,
+                               &crash_size, &crash_base);
+       if (ret)
+               return;
+
+       ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE);
+       if (ret < 0) {
+               printk(KERN_WARNING "crashkernel reservation failed - "
+                      "memory is in use (0x%lx)\n", (unsigned long)crash_base);
+               return;
+       }
+
+       printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+              "for crashkernel (System RAM: %ldMB)\n",
+              (unsigned long)(crash_size >> 20),
+              (unsigned long)(crash_base >> 20),
+              (unsigned long)(total_mem >> 20));
+
+       crashk_res.start = crash_base;
+       crashk_res.end = crash_base + crash_size - 1;
+       insert_resource(&iomem_resource, &crashk_res);
+}
+#else
+static inline void reserve_crashkernel(void) {}
+#endif /* CONFIG_KEXEC */
+
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
+
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * elfcorehdr= specifies the location of elf core header stored by the crashed
+ * kernel. This option will be passed by kexec loader to the capture kernel.
+ */
+static int __init setup_elfcorehdr(char *arg)
+{
+       char *end;
+
+       if (!arg)
+               return -EINVAL;
+
+       elfcorehdr_addr = memparse(arg, &end);
+       return end > arg ? 0 : -EINVAL;
+}
+early_param("elfcorehdr", setup_elfcorehdr);
+#endif /* CONFIG_CRASH_DUMP */
+
 void __init setup_arch(char **cmdline_p)
 {
        struct tag *tags = (struct tag *)&init_tags;
        struct machine_desc *mdesc;
        char *from = default_command_line;
 
+       unwind_init();
+
        setup_processor();
        mdesc = setup_machine(machine_arch_type);
        machine_name = mdesc->name;
@@ -836,26 +794,37 @@ void __init setup_arch(char **cmdline_p)
                parse_tags(tags);
        }
 
-       init_mm.start_code = (unsigned long) &_text;
-       init_mm.end_code   = (unsigned long) &_etext;
-       init_mm.end_data   = (unsigned long) &_edata;
-       init_mm.brk        = (unsigned long) &_end;
+       init_mm.start_code = (unsigned long) _text;
+       init_mm.end_code   = (unsigned long) _etext;
+       init_mm.end_data   = (unsigned long) _edata;
+       init_mm.brk        = (unsigned long) _end;
+
+       /* parse_early_param needs a boot_command_line */
+       strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+
+       /* populate cmd_line too for later use, preserving boot_command_line */
+       strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+       *cmdline_p = cmd_line;
+
+       parse_early_param();
 
-       memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
-       boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
-       parse_cmdline(cmdline_p, from);
-       paging_init(&meminfo, mdesc);
+       arm_memblock_init(&meminfo, mdesc);
+
+       paging_init(mdesc);
        request_standard_resources(&meminfo, mdesc);
 
 #ifdef CONFIG_SMP
        smp_init_cpus();
 #endif
+       reserve_crashkernel();
 
        cpu_init();
+       tcm_init();
 
        /*
         * Set up various architecture-specific pointers
         */
+       arch_nr_irqs = mdesc->nr_irqs;
        init_arch_irq = mdesc->init_irq;
        system_timer = mdesc->timer;
        init_machine = mdesc->init_machine;
@@ -883,9 +852,21 @@ static int __init topology_init(void)
 
        return 0;
 }
-
 subsys_initcall(topology_init);
 
+#ifdef CONFIG_HAVE_PROC_CPU
+static int __init proc_cpu_init(void)
+{
+       struct proc_dir_entry *res;
+
+       res = proc_mkdir("cpu", NULL);
+       if (!res)
+               return -ENOMEM;
+       return 0;
+}
+fs_initcall(proc_cpu_init);
+#endif
+
 static const char *hwcap_str[] = {
        "swp",
        "half",
@@ -898,31 +879,19 @@ static const char *hwcap_str[] = {
        "java",
        "iwmmxt",
        "crunch",
+       "thumbee",
+       "neon",
+       "vfpv3",
+       "vfpv3d16",
        NULL
 };
 
-static void
-c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
-{
-       unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-
-       seq_printf(m, "%s size\t\t: %d\n"
-                     "%s assoc\t\t: %d\n"
-                     "%s line length\t: %d\n"
-                     "%s sets\t\t: %d\n",
-               type, mult << (8 + CACHE_SIZE(cache)),
-               type, (mult << CACHE_ASSOC(cache)) >> 1,
-               type, 8 << CACHE_LINE(cache),
-               type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-                           CACHE_LINE(cache)));
-}
-
 static int c_show(struct seq_file *m, void *v)
 {
        int i;
 
        seq_printf(m, "Processor\t: %s rev %d (%s)\n",
-                  cpu_name, (int)processor_id & 15, elf_platform);
+                  cpu_name, read_cpuid_id() & 15, elf_platform);
 
 #if defined(CONFIG_SMP)
        for_each_online_cpu(i) {
@@ -949,47 +918,26 @@ static int c_show(struct seq_file *m, void *v)
                if (elf_hwcap & (1 << i))
                        seq_printf(m, "%s ", hwcap_str[i]);
 
-       seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
+       seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
        seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
 
-       if ((processor_id & 0x0008f000) == 0x00000000) {
+       if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
                /* pre-ARM7 */
-               seq_printf(m, "CPU part\t: %07x\n", processor_id >> 4);
+               seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
        } else {
-               if ((processor_id & 0x0008f000) == 0x00007000) {
+               if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
                        /* ARM7 */
                        seq_printf(m, "CPU variant\t: 0x%02x\n",
-                                  (processor_id >> 16) & 127);
+                                  (read_cpuid_id() >> 16) & 127);
                } else {
                        /* post-ARM7 */
                        seq_printf(m, "CPU variant\t: 0x%x\n",
-                                  (processor_id >> 20) & 15);
+                                  (read_cpuid_id() >> 20) & 15);
                }
                seq_printf(m, "CPU part\t: 0x%03x\n",
-                          (processor_id >> 4) & 0xfff);
-       }
-       seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
-
-       {
-               unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
-               if (cache_info != processor_id) {
-                       seq_printf(m, "Cache type\t: %s\n"
-                                     "Cache clean\t: %s\n"
-                                     "Cache lockdown\t: %s\n"
-                                     "Cache format\t: %s\n",
-                                  cache_types[CACHE_TYPE(cache_info)],
-                                  cache_clean[CACHE_TYPE(cache_info)],
-                                  cache_lockdown[CACHE_TYPE(cache_info)],
-                                  CACHE_S(cache_info) ? "Harvard" : "Unified");
-
-                       if (CACHE_S(cache_info)) {
-                               c_show_cache(m, "I", CACHE_ISIZE(cache_info));
-                               c_show_cache(m, "D", CACHE_DSIZE(cache_info));
-                       } else {
-                               c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
-                       }
-               }
+                          (read_cpuid_id() >> 4) & 0xfff);
        }
+       seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
 
        seq_puts(m, "\n");