These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / arm / mach-socfpga / platsmp.c
index 79c5336..15c8ce8 100644 (file)
@@ -54,32 +54,43 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
        return 0;
 }
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init socfpga_smp_init_cpus(void)
+static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-       unsigned int i, ncores;
+       int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
 
-       ncores = scu_get_core_count(socfpga_scu_base_addr);
+       if (socfpga_cpu1start_addr) {
+               writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr +
+                      SOCFPGA_A10_RSTMGR_MODMPURST);
+               memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+
+               writel(virt_to_phys(secondary_startup),
+                      sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff));
 
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
+               flush_cache_all();
+               smp_wmb();
+               outer_clean_range(0, trampoline_size);
 
-       /* sanity check */
-       if (ncores > num_possible_cpus()) {
-               pr_warn("socfpga: no. of cores (%d) greater than configured"
-                       "maximum of %d - clipping\n", ncores, num_possible_cpus());
-               ncores = num_possible_cpus();
+               /* This will release CPU #1 out of reset. */
+               writel(0, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_MODMPURST);
        }
 
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
+       return 0;
 }
 
 static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
 {
+       struct device_node *np;
+       void __iomem *socfpga_scu_base_addr;
+
+       np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+       if (!np) {
+               pr_err("%s: missing scu\n", __func__);
+               return;
+       }
+
+       socfpga_scu_base_addr = of_iomap(np, 0);
+       if (!socfpga_scu_base_addr)
+               return;
        scu_enable(socfpga_scu_base_addr);
 }
 
@@ -95,11 +106,34 @@ static void socfpga_cpu_die(unsigned int cpu)
                cpu_do_idle();
 }
 
-struct smp_operations socfpga_smp_ops __initdata = {
-       .smp_init_cpus          = socfpga_smp_init_cpus,
+/*
+ * We need a dummy function so that platform_can_cpu_hotplug() knows
+ * we support CPU hotplug. However, the function does not need to do
+ * anything, because CPUs going offline just do WFI. We could reset
+ * the CPUs but it would increase power consumption.
+ */
+static int socfpga_cpu_kill(unsigned int cpu)
+{
+       return 1;
+}
+
+static struct smp_operations socfpga_smp_ops __initdata = {
        .smp_prepare_cpus       = socfpga_smp_prepare_cpus,
        .smp_boot_secondary     = socfpga_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = socfpga_cpu_die,
+       .cpu_kill               = socfpga_cpu_kill,
 #endif
 };
+
+static struct smp_operations socfpga_a10_smp_ops __initdata = {
+       .smp_prepare_cpus       = socfpga_smp_prepare_cpus,
+       .smp_boot_secondary     = socfpga_a10_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die                = socfpga_cpu_die,
+       .cpu_kill               = socfpga_cpu_kill,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(socfpga_smp, "altr,socfpga-smp", &socfpga_smp_ops);
+CPU_METHOD_OF_DECLARE(socfpga_a10_smp, "altr,socfpga-a10-smp", &socfpga_a10_smp_ops);