]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/arm/mach-berlin/platsmp.c
Merge remote-tracking branch 'samsung/for-next'
[karo-tx-linux.git] / arch / arm / mach-berlin / platsmp.c
index 34a3753e73564ed99cf92bbaee7c94ed5a869acb..405cd37e4fba59d1010b14e1e1e11db069ef75b8 100644 (file)
 #include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 
-#define CPU_RESET              0x00
+/*
+ * There are two reset registers, one with self-clearing (SC)
+ * reset and one with non-self-clearing reset (NON_SC).
+ */
+#define CPU_RESET_SC           0x00
+#define CPU_RESET_NON_SC       0x20
 
 #define RESET_VECT             0x00
 #define SW_RESET_ADDR          0x94
@@ -30,9 +36,11 @@ static inline void berlin_perform_reset_cpu(unsigned int cpu)
 {
        u32 val;
 
-       val = readl(cpu_ctrl + CPU_RESET);
+       val = readl(cpu_ctrl + CPU_RESET_NON_SC);
+       val &= ~BIT(cpu_logical_map(cpu));
+       writel(val, cpu_ctrl + CPU_RESET_NON_SC);
        val |= BIT(cpu_logical_map(cpu));
-       writel(val, cpu_ctrl + CPU_RESET);
+       writel(val, cpu_ctrl + CPU_RESET_NON_SC);
 }
 
 static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -91,8 +99,32 @@ unmap_scu:
        iounmap(scu_base);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void berlin_cpu_die(unsigned int cpu)
+{
+       v7_exit_coherency_flush(louis);
+       while (1)
+               cpu_do_idle();
+}
+
+static int berlin_cpu_kill(unsigned int cpu)
+{
+       u32 val;
+
+       val = readl(cpu_ctrl + CPU_RESET_NON_SC);
+       val &= ~BIT(cpu_logical_map(cpu));
+       writel(val, cpu_ctrl + CPU_RESET_NON_SC);
+
+       return 1;
+}
+#endif
+
 static struct smp_operations berlin_smp_ops __initdata = {
        .smp_prepare_cpus       = berlin_smp_prepare_cpus,
        .smp_boot_secondary     = berlin_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die                = berlin_cpu_die,
+       .cpu_kill               = berlin_cpu_kill,
+#endif
 };
 CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);