xtensa: convert to asm-generic/hardirq.h
[safe/jmp/linux-2.6] / arch / arm / mach-realview / platsmp.c
index 709a9b1..0092658 100644 (file)
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/jiffies.h>
 #include <linux/smp.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/arm_scu.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/localtimer.h>
+#include <asm/unified.h>
+
+#include <mach/board-eb.h>
+#include <mach/board-pb11mp.h>
+#include <mach/board-pbx.h>
+#include <asm/smp_scu.h>
+
+#include "core.h"
 
 extern void realview_secondary_startup(void);
 
@@ -27,38 +37,46 @@ extern void realview_secondary_startup(void);
  */
 volatile int __cpuinitdata pen_release = -1;
 
-static unsigned int __init get_core_count(void)
+static void __iomem *scu_base_addr(void)
 {
-       unsigned int ncores;
-
-       ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG);
+       if (machine_is_realview_eb_mp())
+               return __io_address(REALVIEW_EB11MP_SCU_BASE);
+       else if (machine_is_realview_pb11mp())
+               return __io_address(REALVIEW_TC11MP_SCU_BASE);
+       else if (machine_is_realview_pbx() &&
+                (core_tile_pbx11mp() || core_tile_pbxa9mp()))
+               return __io_address(REALVIEW_PBX_TILE_SCU_BASE);
+       else
+               return (void __iomem *)0;
+}
 
-       return (ncores & 0x03) + 1;
+static inline unsigned int get_core_count(void)
+{
+       void __iomem *scu_base = scu_base_addr();
+       if (scu_base)
+               return scu_get_core_count(scu_base);
+       return 1;
 }
 
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       /*
-        * the primary core may have used a "cross call" soft interrupt
-        * to get this processor out of WFI in the BootMonitor - make
-        * sure that we are no longer being sent this soft interrupt
-        */
-       smp_cross_call_done(cpumask_of_cpu(cpu));
+       trace_hardirqs_off();
 
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
+       gic_cpu_init(0, gic_cpu_base_addr);
 
        /*
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
        pen_release = -1;
+       smp_wmb();
 
        /*
         * Synchronise with the boot thread.
@@ -98,10 +116,11 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * Use smp_cross_call() for this, since there's little
         * point duplicating the code here
         */
-       smp_cross_call(cpumask_of_cpu(cpu));
+       smp_cross_call(cpumask_of(cpu));
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
+               smp_rmb();
                if (pen_release == -1)
                        break;
 
@@ -119,26 +138,16 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init poke_milo(void)
 {
-       extern void secondary_startup(void);
-
        /* nobody is to be released from the pen yet */
        pen_release = -1;
 
        /*
-        * write the address of secondary startup into the system-wide
-        * flags register, then clear the bottom two bits, which is what
-        * BootMonitor is waiting for
+        * Write the address of secondary startup into the system-wide flags
+        * register. The BootMonitor waits for this register to become
+        * non-zero.
         */
-#if 1
-#define REALVIEW_SYS_FLAGSS_OFFSET 0x30
-       __raw_writel(virt_to_phys(realview_secondary_startup),
-                    __io_address(REALVIEW_SYS_BASE) +
-                    REALVIEW_SYS_FLAGSS_OFFSET);
-#define REALVIEW_SYS_FLAGSC_OFFSET 0x34
-       __raw_writel(3,
-                    __io_address(REALVIEW_SYS_BASE) +
-                    REALVIEW_SYS_FLAGSC_OFFSET);
-#endif
+       __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
+                    __io_address(REALVIEW_SYS_FLAGSSET));
 
        mb();
 }
@@ -152,7 +161,7 @@ void __init smp_init_cpus(void)
        unsigned int i, ncores = get_core_count();
 
        for (i = 0; i < ncores; i++)
-               cpu_set(i, cpu_possible_map);
+               set_cpu_possible(i, true);
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -186,23 +195,27 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                max_cpus = ncores;
 
        /*
-        * Enable the local timer for primary CPU
-        */
-       local_timer_setup(cpu);
-
-       /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
         */
        for (i = 0; i < max_cpus; i++)
-               cpu_set(i, cpu_present_map);
+               set_cpu_present(i, true);
 
        /*
-        * Do we need any more CPUs? If so, then let them know where
-        * to start. Note that, on modern versions of MILO, the "poke"
-        * doesn't actually do anything until each individual core is
-        * sent a soft interrupt to get it out of WFI
+        * Initialise the SCU if there are more than one CPU and let
+        * them know where to start. Note that, on modern versions of
+        * MILO, the "poke" doesn't actually do anything until each
+        * individual core is sent a soft interrupt to get it out of
+        * WFI
         */
-       if (max_cpus > 1)
+       if (max_cpus > 1) {
+               /*
+                * Enable the local timer or broadcast device for the
+                * boot CPU, but only if we have more than one CPU.
+                */
+               percpu_timer_setup();
+
+               scu_enable(scu_base_addr());
                poke_milo();
+       }
 }