Merge master.kernel.org:/home/rmk/linux-2.6-serial
[sfrench/cifs-2.6.git] / arch / powerpc / kernel / setup_64.c
index 6791668213e75997ba229544d7b421a5cfe1bc6f..98e9f0595dd8096a1935867203ee87487379eaf1 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <asm/io.h>
+#include <asm/kdump.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
@@ -57,9 +58,9 @@
 #include <asm/lmb.h>
 #include <asm/iseries/it_lp_naca.h>
 #include <asm/firmware.h>
-#include <asm/systemcfg.h>
 #include <asm/xmon.h>
 #include <asm/udbg.h>
+#include <asm/kexec.h>
 
 #include "setup.h"
 
@@ -102,7 +103,15 @@ int boot_cpuid_phys = 0;
 dev_t boot_dev;
 u64 ppc64_pft_size;
 
-struct ppc64_caches ppc64_caches;
+/* Pick defaults since we might want to patch instructions
+ * before we've read this from the device tree.
+ */
+struct ppc64_caches ppc64_caches = {
+       .dline_size = 0x80,
+       .log_dline_size = 7,
+       .iline_size = 0x80,
+       .log_iline_size = 7
+};
 EXPORT_SYMBOL_GPL(ppc64_caches);
 
 /*
@@ -260,6 +269,10 @@ void __init early_setup(unsigned long dt_ptr)
        }
        ppc_md = **mach;
 
+#ifdef CONFIG_CRASH_DUMP
+       kdump_setup();
+#endif
+
        DBG("Found, Initializing memory management...\n");
 
        /*
@@ -309,6 +322,7 @@ void early_setup_secondary(void)
 void smp_release_cpus(void)
 {
        extern unsigned long __secondary_hold_spinloop;
+       unsigned long *ptr;
 
        DBG(" -> smp_release_cpus()\n");
 
@@ -319,7 +333,9 @@ void smp_release_cpus(void)
         * This is useless but harmless on iSeries, secondaries are already
         * waiting on their paca spinloops. */
 
-       __secondary_hold_spinloop = 1;
+       ptr  = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
+                       - PHYSICAL_START);
+       *ptr = 1;
        mb();
 
        DBG(" <- smp_release_cpus()\n");
@@ -375,9 +391,8 @@ static void __init initialize_cache_info(void)
                                DBG("Argh, can't find dcache properties ! "
                                    "sizep: %p, lsizep: %p\n", sizep, lsizep);
 
-                       _systemcfg->dcache_size = ppc64_caches.dsize = size;
-                       _systemcfg->dcache_line_size =
-                               ppc64_caches.dline_size = lsize;
+                       ppc64_caches.dsize = size;
+                       ppc64_caches.dline_size = lsize;
                        ppc64_caches.log_dline_size = __ilog2(lsize);
                        ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
 
@@ -393,22 +408,13 @@ static void __init initialize_cache_info(void)
                                DBG("Argh, can't find icache properties ! "
                                    "sizep: %p, lsizep: %p\n", sizep, lsizep);
 
-                       _systemcfg->icache_size = ppc64_caches.isize = size;
-                       _systemcfg->icache_line_size =
-                               ppc64_caches.iline_size = lsize;
+                       ppc64_caches.isize = size;
+                       ppc64_caches.iline_size = lsize;
                        ppc64_caches.log_iline_size = __ilog2(lsize);
                        ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
                }
        }
 
-       /* Add an eye catcher and the systemcfg layout version number */
-       strcpy(_systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
-       _systemcfg->version.major = SYSTEMCFG_MAJOR;
-       _systemcfg->version.minor = SYSTEMCFG_MINOR;
-       _systemcfg->processor = mfspr(SPRN_PVR);
-       _systemcfg->platform = _machine;
-       _systemcfg->physicalMemorySize = lmb_phys_mem_size();
-
        DBG(" <- initialize_cache_info()\n");
 }
 
@@ -426,6 +432,10 @@ void __init setup_system(void)
         */
        unflatten_device_tree();
 
+#ifdef CONFIG_KEXEC
+       kexec_setup();  /* requires unflattened device tree. */
+#endif
+
        /*
         * Fill the ppc64_caches & systemcfg structures with informations
         * retreived from the device-tree. Need to be called before
@@ -457,16 +467,21 @@ void __init setup_system(void)
         */
        ppc_md.init_early();
 
+       /*
+        * We can discover serial ports now since the above did setup the
+        * hash table management for us, thus ioremap works. We do that early
+        * so that further code can be debugged
+        */
+#ifdef CONFIG_SERIAL_8250
+       find_legacy_serial_ports();
+#endif
+
        /*
         * "Finish" the device-tree, that is do the actual parsing of
         * some of the properties like the interrupt map
         */
        finish_device_tree();
 
-#ifdef CONFIG_BOOTX_TEXT
-       init_boot_display();
-#endif
-
        /*
         * Initialize xmon
         */
@@ -495,17 +510,19 @@ void __init setup_system(void)
 
        printk("-----------------------------------------------------\n");
        printk("ppc64_pft_size                = 0x%lx\n", ppc64_pft_size);
-       printk("ppc64_interrupt_controller    = 0x%ld\n", ppc64_interrupt_controller);
-       printk("systemcfg                     = 0x%p\n", _systemcfg);
-       printk("systemcfg->platform           = 0x%x\n", _systemcfg->platform);
-       printk("systemcfg->processorCount     = 0x%lx\n", _systemcfg->processorCount);
-       printk("systemcfg->physicalMemorySize = 0x%lx\n", _systemcfg->physicalMemorySize);
+       printk("ppc64_interrupt_controller    = 0x%ld\n",
+              ppc64_interrupt_controller);
+       printk("platform                      = 0x%x\n", _machine);
+       printk("physicalMemorySize            = 0x%lx\n", lmb_phys_mem_size());
        printk("ppc64_caches.dcache_line_size = 0x%x\n",
-                       ppc64_caches.dline_size);
+              ppc64_caches.dline_size);
        printk("ppc64_caches.icache_line_size = 0x%x\n",
-                       ppc64_caches.iline_size);
+              ppc64_caches.iline_size);
        printk("htab_address                  = 0x%p\n", htab_address);
        printk("htab_hash_mask                = 0x%lx\n", htab_hash_mask);
+#if PHYSICAL_START > 0
+       printk("physical_start                = 0x%x\n", PHYSICAL_START);
+#endif
        printk("-----------------------------------------------------\n");
 
        mm_init_ppc64();
@@ -567,33 +584,6 @@ static void __init emergency_stack_init(void)
                __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
 }
 
-/*
- * Called from setup_arch to initialize the bitmap of available
- * syscalls in the systemcfg page
- */
-void __init setup_syscall_map(void)
-{
-       unsigned int i, count64 = 0, count32 = 0;
-       extern unsigned long *sys_call_table;
-       extern unsigned long sys_ni_syscall;
-
-
-       for (i = 0; i < __NR_syscalls; i++) {
-               if (sys_call_table[i*2] != sys_ni_syscall) {
-                       count64++;
-                       _systemcfg->syscall_map_64[i >> 5] |=
-                               0x80000000UL >> (i & 0x1f);
-               }
-               if (sys_call_table[i*2+1] != sys_ni_syscall) {
-                       count32++;
-                       _systemcfg->syscall_map_32[i >> 5] |=
-                               0x80000000UL >> (i & 0x1f);
-               }
-       }
-       printk(KERN_INFO "Syscall map setup, %d 32-bit and %d 64-bit syscalls\n",
-              count32, count64);
-}
-
 /*
  * Called into from start_kernel, after lock_kernel has been called.
  * Initializes bootmem, which is unsed to manage page allocation until
@@ -635,9 +625,6 @@ void __init setup_arch(char **cmdline_p)
        do_init_bootmem();
        sparse_init();
 
-       /* initialize the syscall map in systemcfg */
-       setup_syscall_map();
-
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
 #endif
@@ -686,187 +673,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
        printk("[terminate]%04x %s\n", src, msg);
 }
 
-#ifndef CONFIG_PPC_ISERIES
-/*
- * This function can be used by platforms to "find" legacy serial ports.
- * It works for "serial" nodes under an "isa" node, and will try to
- * respect the "ibm,aix-loc" property if any. It works with up to 8
- * ports.
- */
-
-#define MAX_LEGACY_SERIAL_PORTS        8
-static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
-static unsigned int old_serial_count;
-
-void __init generic_find_legacy_serial_ports(u64 *physport,
-               unsigned int *default_speed)
-{
-       struct device_node *np;
-       u32 *sizeprop;
-
-       struct isa_reg_property {
-               u32 space;
-               u32 address;
-               u32 size;
-       };
-       struct pci_reg_property {
-               struct pci_address addr;
-               u32 size_hi;
-               u32 size_lo;
-       };                                                                        
-
-       DBG(" -> generic_find_legacy_serial_port()\n");
-
-       *physport = 0;
-       if (default_speed)
-               *default_speed = 0;
-
-       np = of_find_node_by_path("/");
-       if (!np)
-               return;
-
-       /* First fill our array */
-       for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
-               struct device_node *isa, *pci;
-               struct isa_reg_property *reg;
-               unsigned long phys_size, addr_size, io_base;
-               u32 *rangesp;
-               u32 *interrupts, *clk, *spd;
-               char *typep;
-               int index, rlen, rentsize;
-
-               /* Ok, first check if it's under an "isa" parent */
-               isa = of_get_parent(np);
-               if (!isa || strcmp(isa->name, "isa")) {
-                       DBG("%s: no isa parent found\n", np->full_name);
-                       continue;
-               }
-               
-               /* Now look for an "ibm,aix-loc" property that gives us ordering
-                * if any...
-                */
-               typep = (char *)get_property(np, "ibm,aix-loc", NULL);
-
-               /* Get the ISA port number */
-               reg = (struct isa_reg_property *)get_property(np, "reg", NULL); 
-               if (reg == NULL)
-                       goto next_port;
-               /* We assume the interrupt number isn't translated ... */
-               interrupts = (u32 *)get_property(np, "interrupts", NULL);
-               /* get clock freq. if present */
-               clk = (u32 *)get_property(np, "clock-frequency", NULL);
-               /* get default speed if present */
-               spd = (u32 *)get_property(np, "current-speed", NULL);
-               /* Default to locate at end of array */
-               index = old_serial_count; /* end of the array by default */
-
-               /* If we have a location index, then use it */
-               if (typep && *typep == 'S') {
-                       index = simple_strtol(typep+1, NULL, 0) - 1;
-                       /* if index is out of range, use end of array instead */
-                       if (index >= MAX_LEGACY_SERIAL_PORTS)
-                               index = old_serial_count;
-                       /* if our index is still out of range, that mean that
-                        * array is full, we could scan for a free slot but that
-                        * make little sense to bother, just skip the port
-                        */
-                       if (index >= MAX_LEGACY_SERIAL_PORTS)
-                               goto next_port;
-                       if (index >= old_serial_count)
-                               old_serial_count = index + 1;
-                       /* Check if there is a port who already claimed our slot */
-                       if (serial_ports[index].iobase != 0) {
-                               /* if we still have some room, move it, else override */
-                               if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
-                                       DBG("Moved legacy port %d -> %d\n", index,
-                                           old_serial_count);
-                                       serial_ports[old_serial_count++] =
-                                               serial_ports[index];
-                               } else {
-                                       DBG("Replacing legacy port %d\n", index);
-                               }
-                       }
-               }
-               if (index >= MAX_LEGACY_SERIAL_PORTS)
-                       goto next_port;
-               if (index >= old_serial_count)
-                       old_serial_count = index + 1;
-
-               /* Now fill the entry */
-               memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port));
-               serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16;
-               serial_ports[index].iobase = reg->address;
-               serial_ports[index].irq = interrupts ? interrupts[0] : 0;
-               serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
-
-               DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
-                   index,
-                   serial_ports[index].iobase,
-                   serial_ports[index].irq,
-                   serial_ports[index].uartclk);
-
-               /* Get phys address of IO reg for port 1 */
-               if (index != 0)
-                       goto next_port;
-
-               pci = of_get_parent(isa);
-               if (!pci) {
-                       DBG("%s: no pci parent found\n", np->full_name);
-                       goto next_port;
-               }
-
-               rangesp = (u32 *)get_property(pci, "ranges", &rlen);
-               if (rangesp == NULL) {
-                       of_node_put(pci);
-                       goto next_port;
-               }
-               rlen /= 4;
-
-               /* we need the #size-cells of the PCI bridge node itself */
-               phys_size = 1;
-               sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
-               if (sizeprop != NULL)
-                       phys_size = *sizeprop;
-               /* we need the parent #addr-cells */
-               addr_size = prom_n_addr_cells(pci);
-               rentsize = 3 + addr_size + phys_size;
-               io_base = 0;
-               for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
-                       if (((rangesp[0] >> 24) & 0x3) != 1)
-                               continue; /* not IO space */
-                       io_base = rangesp[3];
-                       if (addr_size == 2)
-                               io_base = (io_base << 32) | rangesp[4];
-               }
-               if (io_base != 0) {
-                       *physport = io_base + reg->address;
-                       if (default_speed && spd)
-                               *default_speed = *spd;
-               }
-               of_node_put(pci);
-       next_port:
-               of_node_put(isa);
-       }
-
-       DBG(" <- generic_find_legacy_serial_port()\n");
-}
-
-static struct platform_device serial_device = {
-       .name   = "serial8250",
-       .id     = PLAT8250_DEV_PLATFORM,
-       .dev    = {
-               .platform_data = serial_ports,
-       },
-};
-
-static int __init serial_dev_init(void)
-{
-       return platform_device_register(&serial_device);
-}
-arch_initcall(serial_dev_init);
-
-#endif /* CONFIG_PPC_ISERIES */
-
 int check_legacy_ioport(unsigned long base_port)
 {
        if (ppc_md.check_legacy_ioport == NULL)