x86: Remove old bootmem code
[linux-2.6.git] / arch / blackfin / mach-bf561 / smp.c
index 9b27e69..3b9a4bf 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * File:         arch/blackfin/mach-bf561/smp.c
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * Copyright 2007-2009 Analog Devices Inc.
+ *               Philippe Gerum <rpm@xenomai.org>
  *
- *               Copyright 2007 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/init.h>
 #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
@@ -67,8 +51,6 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       local_irq_disable();
-
        /* Clone setup for peripheral interrupt sources from CoreA. */
        bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
        bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
@@ -83,18 +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();
 
-       local_irq_enable();
-
-       /* Calibrate loops per jiffy value. */
-       calibrate_delay();
-
        /* 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);
 }
@@ -103,29 +82,33 @@ 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();
        }
 
-       spin_unlock(&boot_lock);
-
-       return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS;
+       if (cpu_online(cpu)) {
+               /* release the lock and let coreb run */
+               spin_unlock(&boot_lock);
+               return 0;
+       } else
+               panic("CPU%u: processor failed to boot\n", cpu);
 }
 
 void __init platform_request_ipi(irq_handler_t handler)
@@ -133,9 +116,9 @@ void __init platform_request_ipi(irq_handler_t handler)
        int ret;
 
        ret = request_irq(IRQ_SUPPLE_0, handler, IRQF_DISABLED,
-                         "SMP interrupt", handler);
+                         "Supplemental Interrupt0", handler);
        if (ret)
-               panic("Cannot request supplemental interrupt 0 for IPI service\n");
+               panic("Cannot request supplemental interrupt 0 for IPI service");
 }
 
 void platform_send_ipi(cpumask_t callmap)
@@ -165,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
+
+}