Merge branch 'core/xen' into x86/xen
[safe/jmp/linux-2.6] / arch / sh / kernel / setup.c
index 4d6d891..de83205 100644 (file)
@@ -4,7 +4,7 @@
  * This file handles the architecture-dependent parts of initialization
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2002 - 2006 Paul Mundt
+ *  Copyright (C) 2002 - 2007 Paul Mundt
  */
 #include <linux/screen_info.h>
 #include <linux/ioport.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/utsname.h>
+#include <linux/nodemask.h>
 #include <linux/cpu.h>
 #include <linux/pfn.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/crash_dump.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/page.h>
+#include <asm/elf.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/clock.h>
-
-extern void * __rd_start, * __rd_end;
-
-/*
- * Machine setup..
- */
+#include <asm/mmu_context.h>
 
 /*
  * Initialize loops_per_jiffy as 10000000 (1000MIPS).
  * This value will be used at the very early stage of serial setup.
  * The bigger value means no problem.
  */
-struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+struct sh_cpuinfo cpu_data[NR_CPUS] __read_mostly = {
+       [0] = {
+               .type                   = CPU_SH_NONE,
+               .loops_per_jiffy        = 10000000,
+       },
+};
+EXPORT_SYMBOL(cpu_data);
+
+/*
+ * The machine vector. First entry in .machvec.init, or clobbered by
+ * sh_mv= on the command line, prior to .machvec.init teardown.
+ */
+struct sh_machine_vector sh_mv = { .mv_name = "generic", };
+EXPORT_SYMBOL(sh_mv);
+
 #ifdef CONFIG_VT
 struct screen_info screen_info;
 #endif
 
-#if defined(CONFIG_SH_UNKNOWN)
-struct sh_machine_vector sh_mv;
-#endif
-
 extern int root_mountflags;
 
-#define MV_NAME_SIZE 32
-
-static struct sh_machine_vector* __init get_mv_byname(const char* name);
-
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define PARAM  ((unsigned char *)empty_zero_page)
-
-#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
-#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
-#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008))
-#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
-#define INITRD_START (*(unsigned long *) (PARAM+0x010))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
-/* ... */
-#define COMMAND_LINE ((char *) (PARAM+0x100))
-
 #define RAMDISK_IMAGE_START_MASK       0x07FF
 #define RAMDISK_PROMPT_FLAG            0x8000
 #define RAMDISK_LOAD_FLAG              0x4000
 
 static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
 
-static struct resource code_resource = { .name = "Kernel code", };
-static struct resource data_resource = { .name = "Kernel data", };
+static struct resource code_resource = {
+       .name = "Kernel code",
+       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
 
-unsigned long memory_start, memory_end;
+static struct resource data_resource = {
+       .name = "Kernel data",
+       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
 
-static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
-                                 struct sh_machine_vector** mvp,
-                                 unsigned long *mv_io_base)
-{
-       char c = ' ', *to = command_line, *from = COMMAND_LINE;
-       int len = 0;
+static struct resource bss_resource = {
+       .name   = "Kernel bss",
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
 
-       /* Save unparsed command line copy for /proc/cmdline */
-       memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-       boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
-       memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
-       memory_end = memory_start + __MEMORY_SIZE;
-
-       for (;;) {
-               /*
-                * "mem=XXX[kKmM]" defines a size of memory.
-                */
-               if (c == ' ' && !memcmp(from, "mem=", 4)) {
-                       if (to != command_line)
-                               to--;
-                       {
-                               unsigned long mem_size;
-
-                               mem_size = memparse(from+4, &from);
-                               memory_end = memory_start + mem_size;
-                       }
-               }
+unsigned long memory_start;
+EXPORT_SYMBOL(memory_start);
+unsigned long memory_end = 0;
+EXPORT_SYMBOL(memory_end);
 
-               if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
-                       char* mv_end;
-                       char* mv_comma;
-                       int mv_len;
-                       if (to != command_line)
-                               to--;
-                       from += 6;
-                       mv_end = strchr(from, ' ');
-                       if (mv_end == NULL)
-                               mv_end = from + strlen(from);
-
-                       mv_comma = strchr(from, ',');
-                       if ((mv_comma != NULL) && (mv_comma < mv_end)) {
-                               int ints[3];
-                               get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
-                               *mv_io_base = ints[1];
-                               mv_len = mv_comma - from;
-                       } else {
-                               mv_len = mv_end - from;
-                       }
-                       if (mv_len > (MV_NAME_SIZE-1))
-                               mv_len = MV_NAME_SIZE-1;
-                       memcpy(mv_name, from, mv_len);
-                       mv_name[mv_len] = '\0';
-                       from = mv_end;
-
-                       *mvp = get_mv_byname(mv_name);
-               }
+static struct resource mem_resources[MAX_NUMNODES];
 
-               c = *(from++);
-               if (!c)
-                       break;
-               if (COMMAND_LINE_SIZE <= ++len)
-                       break;
-               *(to++) = c;
-       }
-       *to = '\0';
-       *cmdline_p = command_line;
-}
+int l1i_cache_shape, l1d_cache_shape, l2_cache_shape;
 
-static int __init sh_mv_setup(char **cmdline_p)
+static int __init early_parse_mem(char *p)
 {
-#ifdef CONFIG_SH_UNKNOWN
-       extern struct sh_machine_vector mv_unknown;
-#endif
-       struct sh_machine_vector *mv = NULL;
-       char mv_name[MV_NAME_SIZE] = "";
-       unsigned long mv_io_base = 0;
-
-       parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
-
-#ifdef CONFIG_SH_UNKNOWN
-       if (mv == NULL) {
-               mv = &mv_unknown;
-               if (*mv_name != '\0') {
-                       printk("Warning: Unsupported machine %s, using unknown\n",
-                              mv_name);
-               }
+       unsigned long size;
+
+       memory_start = (unsigned long)__va(__MEMORY_START);
+       size = memparse(p, &p);
+
+       if (size > __MEMORY_SIZE) {
+               static char msg[] __initdata = KERN_ERR
+                       "Using mem= to increase the size of kernel memory "
+                       "is not allowed.\n"
+                       "  Recompile the kernel with the correct value for "
+                       "CONFIG_MEMORY_SIZE.\n";
+               printk(msg);
+               return 0;
        }
-       sh_mv = *mv;
-#endif
 
-       /*
-        * Manually walk the vec, fill in anything that the board hasn't yet
-        * by hand, wrapping to the generic implementation.
-        */
-#define mv_set(elem) do { \
-       if (!sh_mv.mv_##elem) \
-               sh_mv.mv_##elem = generic_##elem; \
-} while (0)
+       memory_end = memory_start + size;
 
-       mv_set(inb);    mv_set(inw);    mv_set(inl);
-       mv_set(outb);   mv_set(outw);   mv_set(outl);
-
-       mv_set(inb_p);  mv_set(inw_p);  mv_set(inl_p);
-       mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
-
-       mv_set(insb);   mv_set(insw);   mv_set(insl);
-       mv_set(outsb);  mv_set(outsw);  mv_set(outsl);
+       return 0;
+}
+early_param("mem", early_parse_mem);
 
-       mv_set(readb);  mv_set(readw);  mv_set(readl);
-       mv_set(writeb); mv_set(writew); mv_set(writel);
+/*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+static void __init register_bootmem_low_pages(void)
+{
+       unsigned long curr_pfn, last_pfn, pages;
 
-       mv_set(ioport_map);
-       mv_set(ioport_unmap);
-       mv_set(irq_demux);
+       /*
+        * We are rounding up the start address of usable memory:
+        */
+       curr_pfn = PFN_UP(__MEMORY_START);
 
-#ifdef CONFIG_SH_UNKNOWN
-       __set_io_port_base(mv_io_base);
-#endif
+       /*
+        * ... and at the end of the usable range downwards:
+        */
+       last_pfn = PFN_DOWN(__pa(memory_end));
 
-       if (!sh_mv.mv_nr_irqs)
-               sh_mv.mv_nr_irqs = NR_IRQS;
+       if (last_pfn > max_low_pfn)
+               last_pfn = max_low_pfn;
 
-       return 0;
+       pages = last_pfn - curr_pfn;
+       free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
 }
 
-void __init setup_arch(char **cmdline_p)
+#ifdef CONFIG_KEXEC
+static void __init reserve_crashkernel(void)
 {
-       unsigned long bootmap_size;
-       unsigned long start_pfn, max_pfn, max_low_pfn;
-
-#ifdef CONFIG_CMDLINE_BOOL
-        strcpy(COMMAND_LINE, CONFIG_CMDLINE);
-#endif
+       unsigned long long free_mem;
+       unsigned long long crash_size, crash_base;
+       int ret;
+
+       free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
+
+       ret = parse_crashkernel(boot_command_line, free_mem,
+                       &crash_size, &crash_base);
+       if (ret == 0 && crash_size) {
+               if (crash_base <= 0) {
+                       printk(KERN_INFO "crashkernel reservation failed - "
+                                       "you have to specify a base address\n");
+                       return;
+               }
 
-       ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+               if (reserve_bootmem(crash_base, crash_size,
+                                       BOOTMEM_EXCLUSIVE) < 0) {
+                       printk(KERN_INFO "crashkernel reservation failed - "
+                                       "memory is in use\n");
+                       return;
+               }
 
-#ifdef CONFIG_BLK_DEV_RAM
-       rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-       rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
-       rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+               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)(free_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 __init reserve_crashkernel(void)
+{}
 #endif
 
-       if (!MOUNT_ROOT_RDONLY)
-               root_mountflags &= ~MS_RDONLY;
-       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;
-
-       code_resource.start = (unsigned long)virt_to_phys(_text);
-       code_resource.end = (unsigned long)virt_to_phys(_etext)-1;
-       data_resource.start = (unsigned long)virt_to_phys(_etext);
-       data_resource.end = (unsigned long)virt_to_phys(_edata)-1;
+void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
+                                               unsigned long end_pfn)
+{
+       struct resource *res = &mem_resources[nid];
 
-       sh_mv_setup(cmdline_p);
+       WARN_ON(res->name); /* max one active range per node for now */
 
+       res->name = "System RAM";
+       res->start = start_pfn << PAGE_SHIFT;
+       res->end = (end_pfn << PAGE_SHIFT) - 1;
+       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       if (request_resource(&iomem_resource, res)) {
+               pr_err("unable to request memory_resource 0x%lx 0x%lx\n",
+                      start_pfn, end_pfn);
+               return;
+       }
 
        /*
-        * Find the highest page frame number we have available
+        *  We don't know which RAM region contains kernel data,
+        *  so we try it repeatedly and let the resource manager
+        *  test it.
         */
-       max_pfn = PFN_DOWN(__pa(memory_end));
+       request_resource(res, &code_resource);
+       request_resource(res, &data_resource);
+       request_resource(res, &bss_resource);
 
-       /*
-        * Determine low and high memory ranges:
-        */
-       max_low_pfn = max_pfn;
+       add_active_range(nid, start_pfn, end_pfn);
+}
 
-       /*
-        * Partially used pages are not usable - thus
-        * we are rounding upwards:
-        */
-       start_pfn = PFN_UP(__pa(_end));
+void __init setup_bootmem_allocator(unsigned long free_pfn)
+{
+       unsigned long bootmap_size;
 
        /*
         * Find a proper area for the bootmem bitmap. After this
         * bootstrap step all allocations (until the page allocator
         * is intact) must be done via bootmem_alloc().
         */
-       bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
-                                        __MEMORY_START>>PAGE_SHIFT,
-                                        max_low_pfn);
-       /*
-        * Register fully available low RAM pages with the bootmem allocator.
-        */
-       {
-               unsigned long curr_pfn, last_pfn, pages;
-
-               /*
-                * We are rounding up the start address of usable memory:
-                */
-               curr_pfn = PFN_UP(__MEMORY_START);
-               /*
-                * ... and at the end of the usable range downwards:
-                */
-               last_pfn = PFN_DOWN(__pa(memory_end));
-
-               if (last_pfn > max_low_pfn)
-                       last_pfn = max_low_pfn;
-
-               pages = last_pfn - curr_pfn;
-               free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
-                                 PFN_PHYS(pages));
-       }
+       bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
+                                        min_low_pfn, max_low_pfn);
+
+       __add_active_range(0, min_low_pfn, max_low_pfn);
+       register_bootmem_low_pages();
 
+       node_set_online(0);
 
        /*
         * Reserve the kernel text and
@@ -289,29 +232,25 @@ void __init setup_arch(char **cmdline_p)
         * case of us accidentally initializing the bootmem allocator with
         * an invalid RAM area.
         */
-       reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE,
-               (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
+       reserve_bootmem(__MEMORY_START+PAGE_SIZE,
+               (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START,
+               BOOTMEM_DEFAULT);
 
        /*
         * reserve physical page 0 - it's a special BIOS page on many boxes,
         * enabling clean reboots, SMP operation, laptop functions.
         */
-       reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
+       reserve_bootmem(__MEMORY_START, PAGE_SIZE, BOOTMEM_DEFAULT);
+
+       sparse_memory_present_with_active_regions(0);
 
 #ifdef CONFIG_BLK_DEV_INITRD
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-       if (&__rd_start != &__rd_end) {
-               LOADER_TYPE = 1;
-               INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
-                                       __MEMORY_START;
-               INITRD_SIZE = (unsigned long)&__rd_end -
-                             (unsigned long)&__rd_start;
-       }
+       ROOT_DEV = Root_RAM0;
 
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-                       reserve_bootmem_node(NODE_DATA(0), INITRD_START +
-                                               __MEMORY_START, INITRD_SIZE);
+                       reserve_bootmem(INITRD_START + __MEMORY_START,
+                                       INITRD_SIZE, BOOTMEM_DEFAULT);
                        initrd_start = INITRD_START + PAGE_OFFSET +
                                        __MEMORY_START;
                        initrd_end = initrd_start + INITRD_SIZE;
@@ -325,81 +264,163 @@ void __init setup_arch(char **cmdline_p)
        }
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-       conswitchp = &dummy_con;
-#endif
+       reserve_crashkernel();
+}
 
-       /* Perform the machine specific initialisation */
-       if (likely(sh_mv.mv_setup))
-               sh_mv.mv_setup(cmdline_p);
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+static void __init setup_memory(void)
+{
+       unsigned long start_pfn;
 
-       paging_init();
+       /*
+        * Partially used pages are not usable - thus
+        * we are rounding upwards:
+        */
+       start_pfn = PFN_UP(__pa(_end));
+       setup_bootmem_allocator(start_pfn);
 }
+#else
+extern void __init setup_memory(void);
+#endif
 
-struct sh_machine_vector* __init get_mv_byname(const char* name)
+/*
+ * 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.
+ */
+static int __init parse_elfcorehdr(char *arg)
 {
-       extern long __machvec_start, __machvec_end;
-       struct sh_machine_vector *all_vecs =
-               (struct sh_machine_vector *)&__machvec_start;
-
-       int i, n = ((unsigned long)&__machvec_end
-                   - (unsigned long)&__machvec_start)/
-               sizeof(struct sh_machine_vector);
-
-       for (i = 0; i < n; ++i) {
-               struct sh_machine_vector *mv = &all_vecs[i];
-               if (mv == NULL)
-                       continue;
-               if (strcasecmp(name, get_system_type()) == 0) {
-                       return mv;
-               }
-       }
-       return NULL;
+       if (!arg)
+               return -EINVAL;
+       elfcorehdr_addr = memparse(arg, &arg);
+       return 0;
 }
+early_param("elfcorehdr", parse_elfcorehdr);
+#endif
 
-static struct cpu cpu[NR_CPUS];
-
-static int __init topology_init(void)
+void __init setup_arch(char **cmdline_p)
 {
-       int cpu_id;
+       enable_mmu();
 
-       for_each_possible_cpu(cpu_id)
-               register_cpu(&cpu[cpu_id], cpu_id);
+       ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
 
-       return 0;
-}
+       printk(KERN_NOTICE "Boot params:\n"
+                          "... MOUNT_ROOT_RDONLY - %08lx\n"
+                          "... RAMDISK_FLAGS     - %08lx\n"
+                          "... ORIG_ROOT_DEV     - %08lx\n"
+                          "... LOADER_TYPE       - %08lx\n"
+                          "... INITRD_START      - %08lx\n"
+                          "... INITRD_SIZE       - %08lx\n",
+                          MOUNT_ROOT_RDONLY, RAMDISK_FLAGS,
+                          ORIG_ROOT_DEV, LOADER_TYPE,
+                          INITRD_START, INITRD_SIZE);
+
+#ifdef CONFIG_BLK_DEV_RAM
+       rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+       rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+       rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+       if (!MOUNT_ROOT_RDONLY)
+               root_mountflags &= ~MS_RDONLY;
+       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;
+
+       code_resource.start = virt_to_phys(_text);
+       code_resource.end = virt_to_phys(_etext)-1;
+       data_resource.start = virt_to_phys(_etext);
+       data_resource.end = virt_to_phys(_edata)-1;
+       bss_resource.start = virt_to_phys(__bss_start);
+       bss_resource.end = virt_to_phys(_ebss)-1;
+
+       memory_start = (unsigned long)__va(__MEMORY_START);
+       if (!memory_end)
+               memory_end = memory_start + __MEMORY_SIZE;
+
+#ifdef CONFIG_CMDLINE_BOOL
+       strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
+#else
+       strlcpy(command_line, COMMAND_LINE, sizeof(command_line));
+#endif
+
+       /* Save unparsed command line copy for /proc/cmdline */
+       memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+       *cmdline_p = command_line;
+
+       parse_early_param();
+
+       sh_mv_setup();
+
+       /*
+        * Find the highest page frame number we have available
+        */
+       max_pfn = PFN_DOWN(__pa(memory_end));
+
+       /*
+        * Determine low and high memory ranges:
+        */
+       max_low_pfn = max_pfn;
+       min_low_pfn = __MEMORY_START >> PAGE_SHIFT;
 
-subsys_initcall(topology_init);
+       nodes_clear(node_online_map);
+
+       /* Setup bootmem with available RAM */
+       setup_memory();
+       sparse_init();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+       conswitchp = &dummy_con;
+#endif
+
+       /* Perform the machine specific initialisation */
+       if (likely(sh_mv.mv_setup))
+               sh_mv.mv_setup(cmdline_p);
+
+       paging_init();
+
+#ifdef CONFIG_SMP
+       plat_smp_setup();
+#endif
+}
 
 static const char *cpu_name[] = {
+       [CPU_SH7203]    = "SH7203",     [CPU_SH7263]    = "SH7263",
        [CPU_SH7206]    = "SH7206",     [CPU_SH7619]    = "SH7619",
-       [CPU_SH7604]    = "SH7604",     [CPU_SH7300]    = "SH7300",
        [CPU_SH7705]    = "SH7705",     [CPU_SH7706]    = "SH7706",
        [CPU_SH7707]    = "SH7707",     [CPU_SH7708]    = "SH7708",
        [CPU_SH7709]    = "SH7709",     [CPU_SH7710]    = "SH7710",
-       [CPU_SH7712]    = "SH7712",
-       [CPU_SH7729]    = "SH7729",     [CPU_SH7750]    = "SH7750",
-       [CPU_SH7750S]   = "SH7750S",    [CPU_SH7750R]   = "SH7750R",
-       [CPU_SH7751]    = "SH7751",     [CPU_SH7751R]   = "SH7751R",
-       [CPU_SH7760]    = "SH7760",     [CPU_SH73180]   = "SH73180",
-       [CPU_ST40RA]    = "ST40RA",     [CPU_ST40GX1]   = "ST40GX1",
+       [CPU_SH7712]    = "SH7712",     [CPU_SH7720]    = "SH7720",
+       [CPU_SH7721]    = "SH7721",     [CPU_SH7729]    = "SH7729",
+       [CPU_SH7750]    = "SH7750",     [CPU_SH7750S]   = "SH7750S",
+       [CPU_SH7750R]   = "SH7750R",    [CPU_SH7751]    = "SH7751",
+       [CPU_SH7751R]   = "SH7751R",    [CPU_SH7760]    = "SH7760",
        [CPU_SH4_202]   = "SH4-202",    [CPU_SH4_501]   = "SH4-501",
-       [CPU_SH7770]    = "SH7770",     [CPU_SH7780]    = "SH7780",
-       [CPU_SH7781]    = "SH7781",     [CPU_SH7343]    = "SH7343",
-       [CPU_SH7785]    = "SH7785",     [CPU_SH7722]    = "SH7722",
-       [CPU_SH_NONE]   = "Unknown"
+       [CPU_SH7763]    = "SH7763",     [CPU_SH7770]    = "SH7770",
+       [CPU_SH7780]    = "SH7780",     [CPU_SH7781]    = "SH7781",
+       [CPU_SH7343]    = "SH7343",     [CPU_SH7785]    = "SH7785",
+       [CPU_SH7722]    = "SH7722",     [CPU_SHX3]      = "SH-X3",
+       [CPU_SH5_101]   = "SH5-101",    [CPU_SH5_103]   = "SH5-103",
+       [CPU_MXG]       = "MX-G",       [CPU_SH7723]    = "SH7723",
+       [CPU_SH7366]    = "SH7366",     [CPU_SH_NONE]   = "Unknown"
 };
 
 const char *get_cpu_subtype(struct sh_cpuinfo *c)
 {
        return cpu_name[c->type];
 }
+EXPORT_SYMBOL(get_cpu_subtype);
 
 #ifdef CONFIG_PROC_FS
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
        "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-       "ptea", "llsc", "l2", NULL
+       "ptea", "llsc", "l2", "op32", NULL
 };
 
 static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
@@ -448,6 +469,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "processor\t: %d\n", cpu);
        seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
        seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
+       if (c->cut_major == -1)
+               seq_printf(m, "cut\t\t: unknown\n");
+       else if (c->cut_minor == -1)
+               seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
+       else
+               seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
 
        show_cpuflags(m, c);
 
@@ -475,7 +502,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                     c->loops_per_jiffy/(500000/HZ),
                     (c->loops_per_jiffy/(5000/HZ)) % 100);
 
-       return show_clocks(m);
+       return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
@@ -490,10 +517,22 @@ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 static void c_stop(struct seq_file *m, void *v)
 {
 }
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
        .start  = c_start,
        .next   = c_next,
        .stop   = c_stop,
        .show   = show_cpuinfo,
 };
 #endif /* CONFIG_PROC_FS */
+
+struct dentry *sh_debugfs_root;
+
+static int __init sh_debugfs_init(void)
+{
+       sh_debugfs_root = debugfs_create_dir("sh", NULL);
+       if (IS_ERR(sh_debugfs_root))
+               return PTR_ERR(sh_debugfs_root);
+
+       return 0;
+}
+arch_initcall(sh_debugfs_init);