ARM: hisi: enable hix5hd2 SoC
[cascardo/linux.git] / arch / arm / mach-hisi / hotplug.c
index abd441b..84e6919 100644 (file)
 #define CPU0_NEON_SRST_REQ_EN          (1 << 4)
 #define CPU0_SRST_REQ_EN               (1 << 0)
 
+#define HIX5HD2_PERI_CRG20             0x50
+#define CRG20_CPU1_RESET               (1 << 17)
+
+#define HIX5HD2_PERI_PMC0              0x1000
+#define PMC0_CPU1_WAIT_MTCOMS_ACK      (1 << 8)
+#define PMC0_CPU1_PMC_ENABLE           (1 << 7)
+#define PMC0_CPU1_POWERDOWN            (1 << 3)
+
 enum {
        HI3620_CTRL,
        ERROR_CTRL,
@@ -157,6 +165,50 @@ void hi3xxx_set_cpu(int cpu, bool enable)
                set_cpu_hi3620(cpu, enable);
 }
 
+static bool hix5hd2_hotplug_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
+       if (np) {
+               ctrl_base = of_iomap(np, 0);
+               return true;
+       }
+       return false;
+}
+
+void hix5hd2_set_cpu(int cpu, bool enable)
+{
+       u32 val = 0;
+
+       if (!ctrl_base)
+               if (!hix5hd2_hotplug_init())
+                       BUG();
+
+       if (enable) {
+               /* power on cpu1 */
+               val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
+               val &= ~(PMC0_CPU1_WAIT_MTCOMS_ACK | PMC0_CPU1_POWERDOWN);
+               val |= PMC0_CPU1_PMC_ENABLE;
+               writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
+               /* unreset */
+               val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
+               val &= ~CRG20_CPU1_RESET;
+               writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
+       } else {
+               /* power down cpu1 */
+               val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
+               val |= PMC0_CPU1_PMC_ENABLE | PMC0_CPU1_POWERDOWN;
+               val &= ~PMC0_CPU1_WAIT_MTCOMS_ACK;
+               writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
+
+               /* reset */
+               val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
+               val |= CRG20_CPU1_RESET;
+               writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
+       }
+}
+
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -199,4 +251,10 @@ int hi3xxx_cpu_kill(unsigned int cpu)
        hi3xxx_set_cpu(cpu, false);
        return 1;
 }
+
+void hix5hd2_cpu_die(unsigned int cpu)
+{
+       flush_cache_all();
+       hix5hd2_set_cpu(cpu, false);
+}
 #endif