These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / arm / mach-ux500 / platsmp.c
index 3af22a4..70766b9 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/device.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include "db8500-regs.h"
 #include "id.h"
 
-/* This is called from headsmp.S to wakeup the secondary core */
-extern void u8500_secondary_startup(void);
-
-/*
- * Write pen_release in a way that is guaranteed to be visible to all
- * observers, irrespective of whether they're taking part in coherency
- * or not.  This is necessary for the hotplug code to work reliably.
- */
-static void write_pen_release(int val)
-{
-       pen_release = val;
-       smp_wmb();
-       sync_cache_w(&pen_release);
-}
-
-static void __iomem *scu_base_addr(void)
-{
-       if (cpu_is_u8500_family() || cpu_is_ux540_family())
-               return __io_address(U8500_SCU_BASE);
-       else
-               ux500_unknown_soc();
-
-       return NULL;
-}
-
-static DEFINE_RAW_SPINLOCK(boot_lock);
-
-static void ux500_secondary_init(unsigned int cpu)
-{
-       /*
-        * let the primary processor know we're out of the
-        * pen, then head off into the C entry point
-        */
-       write_pen_release(-1);
-
-       /*
-        * Synchronise with the boot thread.
-        */
-       raw_spin_lock(&boot_lock);
-       raw_spin_unlock(&boot_lock);
-}
+/* Magic triggers in backup RAM */
+#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
+#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
 
-static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static void wakeup_secondary(void)
 {
-       unsigned long timeout;
-
-       /*
-        * set synchronisation state between this boot processor
-        * and the secondary one
-        */
-       raw_spin_lock(&boot_lock);
+       struct device_node *np;
+       static void __iomem *backupram;
 
-       /*
-        * The secondary processor is waiting to be released from
-        * the holding pen - release it, then wait for it to flag
-        * that it has been released by resetting pen_release.
-        */
-       write_pen_release(cpu_logical_map(cpu));
-
-       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
-
-       timeout = jiffies + (1 * HZ);
-       while (time_before(jiffies, timeout)) {
-               if (pen_release == -1)
-                       break;
+       np = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram");
+       if (!np) {
+               pr_err("No backupram base address\n");
+               return;
+       }
+       backupram = of_iomap(np, 0);
+       of_node_put(np);
+       if (!backupram) {
+               pr_err("No backupram remap\n");
+               return;
        }
-
-       /*
-        * now the secondary core is starting up let it run its
-        * calibrations, then wait for it to finish
-        */
-       raw_spin_unlock(&boot_lock);
-
-       return pen_release != -1 ? -ENOSYS : 0;
-}
-
-static void __init wakeup_secondary(void)
-{
-       void __iomem *backupram;
-
-       if (cpu_is_u8500_family() || cpu_is_ux540_family())
-               backupram = __io_address(U8500_BACKUPRAM0_BASE);
-       else
-               ux500_unknown_soc();
 
        /*
         * write the address of secondary startup into the backup ram register
         * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
         * backup ram register at offset 0x1FF0, which is what boot rom code
-        * is waiting for. This would wake up the secondary core from WFE
+        * is waiting for. This will wake up the secondary core from WFE.
         */
-#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
-       __raw_writel(virt_to_phys(u8500_secondary_startup),
-                    backupram + UX500_CPU1_JUMPADDR_OFFSET);
-
-#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
-       __raw_writel(0xA1FEED01,
-                    backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
+       writel(virt_to_phys(secondary_startup),
+              backupram + UX500_CPU1_JUMPADDR_OFFSET);
+       writel(0xA1FEED01,
+              backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
 
        /* make sure write buffer is drained */
        mb();
+       iounmap(backupram);
 }
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init ux500_smp_init_cpus(void)
+static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
 {
-       void __iomem *scu_base = scu_base_addr();
-       unsigned int i, ncores;
-
-       ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-
-       /* sanity check */
-       if (ncores > nr_cpu_ids) {
-               pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-                       ncores, nr_cpu_ids);
-               ncores = nr_cpu_ids;
+       struct device_node *np;
+       static void __iomem *scu_base;
+       unsigned int ncores;
+       int i;
+
+       np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+       if (!np) {
+               pr_err("No SCU base address\n");
+               return;
+       }
+       scu_base = of_iomap(np, 0);
+       of_node_put(np);
+       if (!scu_base) {
+               pr_err("No SCU remap\n");
+               return;
        }
 
+       scu_enable(scu_base);
+       ncores = scu_get_core_count(scu_base);
        for (i = 0; i < ncores; i++)
                set_cpu_possible(i, true);
+       iounmap(scu_base);
 }
 
-static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
+static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-
-       scu_enable(scu_base_addr());
        wakeup_secondary();
+       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+       return 0;
 }
 
 struct smp_operations ux500_smp_ops __initdata = {
-       .smp_init_cpus          = ux500_smp_init_cpus,
        .smp_prepare_cpus       = ux500_smp_prepare_cpus,
-       .smp_secondary_init     = ux500_secondary_init,
        .smp_boot_secondary     = ux500_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = ux500_cpu_die,
 #endif
 };
+CPU_METHOD_OF_DECLARE(ux500_smp, "ste,dbx500-smp", &ux500_smp_ops);