Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / arch / blackfin / mach-bf561 / smp.c
index 0192532..3b9a4bf 100644 (file)
 #include <linux/delay.h>
 #include <asm/smp.h>
 #include <asm/dma.h>
+#include <asm/time.h>
 
 static DEFINE_SPINLOCK(boot_lock);
 
-static cpumask_t cpu_callin_map;
-
 /*
  * platform_init_cpus() - Tell the world about how many cores we
  * have. This is called while setting up the architecture support
@@ -66,13 +65,15 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
        bfin_write_SICB_IAR5(bfin_read_SICA_IAR5());
        bfin_write_SICB_IAR6(bfin_read_SICA_IAR6());
        bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
+       bfin_write_SICB_IWR0(IWR_DISABLE_ALL);
+       bfin_write_SICB_IWR1(IWR_DISABLE_ALL);
        SSYNC();
 
        /* Store CPU-private information to the cpu_data array. */
        bfin_setup_cpudata(cpu);
 
        /* We are done with local CPU inits, unblock the boot CPU. */
-       cpu_set(cpu, cpu_callin_map);
+       set_cpu_online(cpu, true);
        spin_lock(&boot_lock);
        spin_unlock(&boot_lock);
 }
@@ -81,28 +82,28 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle
 {
        unsigned long timeout;
 
-       /* CoreB already running?! */
-       BUG_ON((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0);
-
        printk(KERN_INFO "Booting Core B.\n");
 
        spin_lock(&boot_lock);
 
-       /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
-       SSYNC();
-       bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
-       SSYNC();
+       if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0) {
+               /* CoreB already running, sending ipi to wakeup it */
+               platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+       } else {
+               /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
+               bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
+               SSYNC();
+       }
 
        timeout = jiffies + 1 * HZ;
        while (time_before(jiffies, timeout)) {
-               if (cpu_isset(cpu, cpu_callin_map))
+               if (cpu_online(cpu))
                        break;
                udelay(100);
                barrier();
        }
 
-       if (cpu_isset(cpu, cpu_callin_map)) {
-               cpu_set(cpu, cpu_online_map);
+       if (cpu_online(cpu)) {
                /* release the lock and let coreb run */
                spin_unlock(&boot_lock);
                return 0;
@@ -147,3 +148,20 @@ void platform_clear_ipi(unsigned int cpu)
        bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + cpu)));
        SSYNC();
 }
+
+/*
+ * Setup core B's local core timer.
+ * In SMP, core timer is used for clock event device.
+ */
+void __cpuinit bfin_local_timer_setup(void)
+{
+#if defined(CONFIG_TICKSOURCE_CORETMR)
+       bfin_coretmr_init();
+       bfin_coretmr_clockevent_init();
+       get_irq_chip(IRQ_CORETMR)->unmask(IRQ_CORETMR);
+#else
+       /* Power down the core timer, just to play safe. */
+       bfin_write_TCNTL(0);
+#endif
+
+}