[PATCH v3 1/1] arm: ls1: add CPU hotplug platform support

2014-12-18 Thread Zhuoyu Zhang
From: Zhang Zhuoyu 

This implements CPU hotplug for ls1. When cpu is down, it will be put
in boot holdoff state. When cpu is up, it will always soft reset and
boots up the same path as a cold boot.

Signed-off-by: Zhang Zhuoyu 
---
 arch/arm/mach-imx/common.h  |  16 +
 arch/arm/mach-imx/hotplug.c |  29 +
 arch/arm/mach-imx/platsmp.c | 153 
 3 files changed, 186 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cfcdb62..c2acb81 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -13,6 +13,17 @@
 
 #include 
 
+#defineSCFG_CORE0_SFT_RST  0x130
+#defineSCFG_CORESRENCR 0x204
+#defineDCFG_CCSR_BRR   0x0E4
+#defineDCFG_CCSR_SCRATCHRW10x200
+#defineCCSR_TWAITSR0   0x04C
+
+#defineSTRIDE_4B   4
+
+#defineSCFG_CORE_SOFT_RST_EN   0x8000
+#defineSCFG_CORE_SOFT_RST  0x8000
+
 struct irq_data;
 struct platform_device;
 struct pt_regs;
@@ -92,6 +103,7 @@ void imx_print_silicon_rev(const char *cpu, int srev);
 void imx_enable_cpu(int cpu, bool enable);
 void imx_set_cpu_jump(int cpu, void *jump_addr);
 u32 imx_get_cpu_arg(int cpu);
+u32 ls1_get_cpu_arg(int cpu);
 void imx_set_cpu_arg(int cpu, u32 arg);
 #ifdef CONFIG_SMP
 void v7_secondary_startup(void);
@@ -134,6 +146,10 @@ void imx6sl_pm_init(void);
 void imx6sx_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
 
+extern int ls1021a_holdoff(unsigned int cpu);
+extern void ls1021a_cpu_die(unsigned int cpu);
+extern int ls1021a_cpu_kill(unsigned int cpu);
+
 #ifdef CONFIG_PM
 void imx51_pm_init(void);
 void imx53_pm_init(void);
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index b35e99c..8f5f082 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "common.h"
 
@@ -68,3 +69,31 @@ int imx_cpu_kill(unsigned int cpu)
imx_set_cpu_arg(cpu, 0);
return 1;
 }
+
+void __ref ls1021a_cpu_die(unsigned int cpu)
+{
+   v7_exit_coherency_flush(louis);
+
+   /* LS1021a platform can't really power down an offline CPU.
+* So we put offline core into WFI, then reset it and put it into
+* boot holdoff state as a workaround method. It is a little tricky,
+* but we have no better choice due to hardware limitation for now.
+*/
+   wfi();
+
+   /* We should never get here. */
+   BUG();
+
+}
+
+int ls1021a_cpu_kill(unsigned int cpu)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+   while (!ls1_get_cpu_arg(cpu))
+   if (time_after(jiffies, timeout))
+   return 0;
+
+   /* Reset offline core and put it into boot holdoff state */
+   return ls1021a_holdoff(cpu);
+}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7f27001..6bc1320 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -14,17 +14,23 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "common.h"
 #include "hardware.h"
 
 u32 g_diag_reg;
 static void __iomem *scu_base;
+static void __iomem *dcfg_base;
+static void __iomem *scfg_base;
+static void __iomem *rcpm_base;
+static u32 secondary_pre_boot_entry;
 
 static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
@@ -98,32 +104,155 @@ struct smp_operations  imx_smp_ops __initdata = {
 #endif
 };
 
-#define DCFG_CCSR_SCRATCHRW1   0x200
+static int ls1021a_secondary_iomap(void)
+{
+   struct device_node *np;
+   int ret;
+
+   np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
+   if (!np) {
+   pr_err("%s: failed to find dcfg node.\n", __func__);
+   ret = -ENODEV;
+   goto dcfg_err;
+   }
+
+   dcfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!dcfg_base) {
+   pr_err("%s: failed to map dcfg.\n", __func__);
+   ret = -ENOMEM;
+   goto dcfg_err;
+   }
+
+   np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-scfg");
+   if (!np) {
+   pr_err("%s: failed to find scfg node.\n", __func__);
+   ret = -ENODEV;
+   goto scfg_err;
+   }
+
+   scfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!scfg_base) {
+   pr_err("%s: failed to map scfg.\n", __func__);
+   ret = -ENOMEM;
+   goto scfg_err;
+   }
+
+   np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.1");
+   if (!np) {
+   pr_err("%s(): failed to find rcpm node.\n", __func__);
+   return -ENODEV;
+   goto rcpm_err;
+   }
+
+   rcpm_base = of_iomap(np, 0);
+   

[PATCH v3 1/1] arm: ls1: add CPU hotplug platform support

2014-12-18 Thread Zhuoyu Zhang
From: Zhang Zhuoyu zhuoyu.zh...@freescale.com

This implements CPU hotplug for ls1. When cpu is down, it will be put
in boot holdoff state. When cpu is up, it will always soft reset and
boots up the same path as a cold boot.

Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com
---
 arch/arm/mach-imx/common.h  |  16 +
 arch/arm/mach-imx/hotplug.c |  29 +
 arch/arm/mach-imx/platsmp.c | 153 
 3 files changed, 186 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cfcdb62..c2acb81 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -13,6 +13,17 @@
 
 #include linux/reboot.h
 
+#defineSCFG_CORE0_SFT_RST  0x130
+#defineSCFG_CORESRENCR 0x204
+#defineDCFG_CCSR_BRR   0x0E4
+#defineDCFG_CCSR_SCRATCHRW10x200
+#defineCCSR_TWAITSR0   0x04C
+
+#defineSTRIDE_4B   4
+
+#defineSCFG_CORE_SOFT_RST_EN   0x8000
+#defineSCFG_CORE_SOFT_RST  0x8000
+
 struct irq_data;
 struct platform_device;
 struct pt_regs;
@@ -92,6 +103,7 @@ void imx_print_silicon_rev(const char *cpu, int srev);
 void imx_enable_cpu(int cpu, bool enable);
 void imx_set_cpu_jump(int cpu, void *jump_addr);
 u32 imx_get_cpu_arg(int cpu);
+u32 ls1_get_cpu_arg(int cpu);
 void imx_set_cpu_arg(int cpu, u32 arg);
 #ifdef CONFIG_SMP
 void v7_secondary_startup(void);
@@ -134,6 +146,10 @@ void imx6sl_pm_init(void);
 void imx6sx_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
 
+extern int ls1021a_holdoff(unsigned int cpu);
+extern void ls1021a_cpu_die(unsigned int cpu);
+extern int ls1021a_cpu_kill(unsigned int cpu);
+
 #ifdef CONFIG_PM
 void imx51_pm_init(void);
 void imx53_pm_init(void);
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index b35e99c..8f5f082 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -14,6 +14,7 @@
 #include linux/jiffies.h
 #include asm/cp15.h
 #include asm/proc-fns.h
+#include asm/cacheflush.h
 
 #include common.h
 
@@ -68,3 +69,31 @@ int imx_cpu_kill(unsigned int cpu)
imx_set_cpu_arg(cpu, 0);
return 1;
 }
+
+void __ref ls1021a_cpu_die(unsigned int cpu)
+{
+   v7_exit_coherency_flush(louis);
+
+   /* LS1021a platform can't really power down an offline CPU.
+* So we put offline core into WFI, then reset it and put it into
+* boot holdoff state as a workaround method. It is a little tricky,
+* but we have no better choice due to hardware limitation for now.
+*/
+   wfi();
+
+   /* We should never get here. */
+   BUG();
+
+}
+
+int ls1021a_cpu_kill(unsigned int cpu)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+   while (!ls1_get_cpu_arg(cpu))
+   if (time_after(jiffies, timeout))
+   return 0;
+
+   /* Reset offline core and put it into boot holdoff state */
+   return ls1021a_holdoff(cpu);
+}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7f27001..6bc1320 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -14,17 +14,23 @@
 #include linux/of_address.h
 #include linux/of.h
 #include linux/smp.h
+#include linux/delay.h
 
 #include asm/cacheflush.h
 #include asm/page.h
 #include asm/smp_scu.h
 #include asm/mach/map.h
+#include asm/smp_plat.h
 
 #include common.h
 #include hardware.h
 
 u32 g_diag_reg;
 static void __iomem *scu_base;
+static void __iomem *dcfg_base;
+static void __iomem *scfg_base;
+static void __iomem *rcpm_base;
+static u32 secondary_pre_boot_entry;
 
 static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
@@ -98,32 +104,155 @@ struct smp_operations  imx_smp_ops __initdata = {
 #endif
 };
 
-#define DCFG_CCSR_SCRATCHRW1   0x200
+static int ls1021a_secondary_iomap(void)
+{
+   struct device_node *np;
+   int ret;
+
+   np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-dcfg);
+   if (!np) {
+   pr_err(%s: failed to find dcfg node.\n, __func__);
+   ret = -ENODEV;
+   goto dcfg_err;
+   }
+
+   dcfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!dcfg_base) {
+   pr_err(%s: failed to map dcfg.\n, __func__);
+   ret = -ENOMEM;
+   goto dcfg_err;
+   }
+
+   np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-scfg);
+   if (!np) {
+   pr_err(%s: failed to find scfg node.\n, __func__);
+   ret = -ENODEV;
+   goto scfg_err;
+   }
+
+   scfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!scfg_base) {
+   pr_err(%s: failed to map scfg.\n, __func__);
+   ret = -ENOMEM;
+   goto scfg_err;
+   }
+
+   np = of_find_compatible_node(NULL, NULL, 

[PATCH v2 1/2] arm: ls1: add CPU hotplug platform support

2014-11-23 Thread Zhuoyu Zhang
From: Zhang Zhuoyu 

This implements CPU hotplug for ls1. When cpu is down, it will be put
in WFI state. When cpu is up, it will always soft reset and boots up
the same path as a cold boot.

Signed-off-by: Zhang Zhuoyu 
---
 arch/arm/mach-imx/common.h  |   4 ++
 arch/arm/mach-imx/hotplug.c |  25 +
 arch/arm/mach-imx/platsmp.c | 132 +++-
 arch/arm/mach-imx/src.c |  21 +++
 4 files changed, 169 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 59ce8f3..f7d2be5 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -92,6 +92,7 @@ void imx_print_silicon_rev(const char *cpu, int srev);
 void imx_enable_cpu(int cpu, bool enable);
 void imx_set_cpu_jump(int cpu, void *jump_addr);
 u32 imx_get_cpu_arg(int cpu);
+u32 ls1_get_cpu_arg(int cpu);
 void imx_set_cpu_arg(int cpu, u32 arg);
 #ifdef CONFIG_SMP
 void v7_secondary_startup(void);
@@ -134,6 +135,9 @@ void imx6sl_pm_init(void);
 void imx6sx_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
 
+extern void ls1021a_cpu_die(unsigned int cpu);
+extern int ls1021a_cpu_kill(unsigned int cpu);
+
 #ifdef CONFIG_PM
 void imx51_pm_init(void);
 void imx53_pm_init(void);
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index b35e99c..2ee5e46 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "common.h"
 
@@ -68,3 +69,27 @@ int imx_cpu_kill(unsigned int cpu)
imx_set_cpu_arg(cpu, 0);
return 1;
 }
+
+/*
+ * For LS102x platforms, shutdowning a CPU is not supported by hardware.
+ * So we just put the offline CPU into lower-power state here.
+ */
+void __ref ls1021a_cpu_die(unsigned int cpu)
+{
+   v7_exit_coherency_flush(louis);
+
+   /* LS1021a platform can't really power down a CPU, so we
+* just put it into WFI state here.
+*/
+   wfi();
+}
+
+int ls1021a_cpu_kill(unsigned int cpu)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+   while (!ls1_get_cpu_arg(cpu))
+   if (time_after(jiffies, timeout))
+   return 0;
+   return 1;
+}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7f27001..7735ebb 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -23,8 +24,24 @@
 #include "common.h"
 #include "hardware.h"
 
+#defineSCFG_CORE0_SFT_RST  0x130
+#defineSCFG_REVCR  0x200
+#defineSCFG_CORESRENCR 0x204
+#defineSCFG_SPARECR4   0x50C
+
+#defineDCFG_CCSR_BRR   0x0E4
+#defineDCFG_CCSR_SCRATCHRW10x200
+
+#defineDCSR_RCPM2_DEBUG1   0x400
+#defineDCSR_RCPM2_DEBUG2   0x414
+
+#defineSTRIDE_4B   4
+
 u32 g_diag_reg;
 static void __iomem *scu_base;
+static void __iomem *dcfg_base;
+static void __iomem *scfg_base;
+static u32 secondary_pre_boot_entry;
 
 static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
@@ -98,32 +115,121 @@ struct smp_operations  imx_smp_ops __initdata = {
 #endif
 };
 
-#define DCFG_CCSR_SCRATCHRW1   0x200
-
-static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int ls1021a_secondary_iomap(void)
 {
-   arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+   struct device_node *np;
+   int ret;
+
+   np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
+   if (!np) {
+   pr_err("%s: failed to find dcfg node.\n", __func__);
+   ret = -EINVAL;
+   goto dcfg_err;
+   }
+
+   dcfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!dcfg_base) {
+   pr_err("%s: failed to map dcfg.\n", __func__);
+   ret = -ENOMEM;
+   goto dcfg_err;
+   }
+
+   np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-scfg");
+   if (!np) {
+   pr_err("%s: failed to find scfg node.\n", __func__);
+   ret = -EINVAL;
+   goto scfg_err;
+   }
+
+   scfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!scfg_base) {
+   pr_err("%s: failed to map scfg.\n", __func__);
+   ret = -ENOMEM;
+   goto scfg_err;
+   }
 
return 0;
+
+scfg_err:
+   iounmap(dcfg_base);
+dcfg_err:
+   return ret;
 }
 
-static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
+void ls1021a_set_secondary_entry(void)
 {
-   struct device_node *np;
-   void __iomem *dcfg_base;
unsigned long paddr;
 
-   np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
-   dcfg_base = of_iomap(np, 0);
-   BUG_ON(!dcfg_base);
+   

[PATCH v2 2/2] arm: ls1: provide a workaround for core soft reset

2014-11-23 Thread Zhuoyu Zhang
From: Zhang Zhuoyu 

Due to a hardware erratum, after core soft reset, core state machine
registers need to force release manually.

Signed-off-by: Zhang Zhuoyu 
---
 arch/arm/mach-imx/platsmp.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7735ebb..73c2289 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -41,6 +41,7 @@ u32 g_diag_reg;
 static void __iomem *scu_base;
 static void __iomem *dcfg_base;
 static void __iomem *scfg_base;
+static void __iomem *dcsr_rcpm2_base;
 static u32 secondary_pre_boot_entry;
 
 static struct map_desc scu_io_desc __initdata = {
@@ -150,8 +151,25 @@ static int ls1021a_secondary_iomap(void)
goto scfg_err;
}
 
+   np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcsr-rcpm");
+   if (!np) {
+   pr_err("%s: failed to find dcsr node.\n", __func__);
+   ret = -EINVAL;
+   goto dcsr_err;
+   }
+
+   dcsr_rcpm2_base = of_iomap(np, 1);
+   of_node_put(np);
+   if (!dcsr_rcpm2_base) {
+   pr_err("%s: failed to map dcsr.\n", __func__);
+   ret = -ENOMEM;
+   goto dcsr_err;
+   }
+
return 0;
 
+dcsr_err:
+   iounmap(scfg_base);
 scfg_err:
iounmap(dcfg_base);
 dcfg_err:
@@ -176,7 +194,7 @@ static int ls1021a_reset_secondary(unsigned int cpu)
 {
u32 tmp;
 
-   if (!scfg_base || !dcfg_base)
+   if (!scfg_base || !dcfg_base || !dcsr_rcpm2_base)
return -ENOMEM;
 
writel_relaxed(secondary_pre_boot_entry,
@@ -190,6 +208,15 @@ static int ls1021a_reset_secondary(unsigned int cpu)
iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR);
iowrite32be(0x8000, scfg_base +
SCFG_CORE0_SFT_RST + STRIDE_4B * cpu);
+   mdelay(10);
+
+   /* LS1021a errata. after reset, core state machine registers
+* need to force release manually.
+*/
+   iowrite32be(0x0080, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG1);
+   iowrite32be(0x0080, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG2);
+   iowrite32be(0, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG1);
+   iowrite32be(0, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG2);
 
/* Release secondary core */
iowrite32be(1 << cpu, dcfg_base + DCFG_CCSR_BRR);
-- 
2.1.0.27.g96db324

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/2] arm: ls1: provide a workaround for core soft reset

2014-11-23 Thread Zhuoyu Zhang
From: Zhang Zhuoyu zhuoyu.zh...@freescale.com

Due to a hardware erratum, after core soft reset, core state machine
registers need to force release manually.

Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com
---
 arch/arm/mach-imx/platsmp.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7735ebb..73c2289 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -41,6 +41,7 @@ u32 g_diag_reg;
 static void __iomem *scu_base;
 static void __iomem *dcfg_base;
 static void __iomem *scfg_base;
+static void __iomem *dcsr_rcpm2_base;
 static u32 secondary_pre_boot_entry;
 
 static struct map_desc scu_io_desc __initdata = {
@@ -150,8 +151,25 @@ static int ls1021a_secondary_iomap(void)
goto scfg_err;
}
 
+   np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-dcsr-rcpm);
+   if (!np) {
+   pr_err(%s: failed to find dcsr node.\n, __func__);
+   ret = -EINVAL;
+   goto dcsr_err;
+   }
+
+   dcsr_rcpm2_base = of_iomap(np, 1);
+   of_node_put(np);
+   if (!dcsr_rcpm2_base) {
+   pr_err(%s: failed to map dcsr.\n, __func__);
+   ret = -ENOMEM;
+   goto dcsr_err;
+   }
+
return 0;
 
+dcsr_err:
+   iounmap(scfg_base);
 scfg_err:
iounmap(dcfg_base);
 dcfg_err:
@@ -176,7 +194,7 @@ static int ls1021a_reset_secondary(unsigned int cpu)
 {
u32 tmp;
 
-   if (!scfg_base || !dcfg_base)
+   if (!scfg_base || !dcfg_base || !dcsr_rcpm2_base)
return -ENOMEM;
 
writel_relaxed(secondary_pre_boot_entry,
@@ -190,6 +208,15 @@ static int ls1021a_reset_secondary(unsigned int cpu)
iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR);
iowrite32be(0x8000, scfg_base +
SCFG_CORE0_SFT_RST + STRIDE_4B * cpu);
+   mdelay(10);
+
+   /* LS1021a errata. after reset, core state machine registers
+* need to force release manually.
+*/
+   iowrite32be(0x0080, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG1);
+   iowrite32be(0x0080, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG2);
+   iowrite32be(0, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG1);
+   iowrite32be(0, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG2);
 
/* Release secondary core */
iowrite32be(1  cpu, dcfg_base + DCFG_CCSR_BRR);
-- 
2.1.0.27.g96db324

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/2] arm: ls1: add CPU hotplug platform support

2014-11-23 Thread Zhuoyu Zhang
From: Zhang Zhuoyu zhuoyu.zh...@freescale.com

This implements CPU hotplug for ls1. When cpu is down, it will be put
in WFI state. When cpu is up, it will always soft reset and boots up
the same path as a cold boot.

Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com
---
 arch/arm/mach-imx/common.h  |   4 ++
 arch/arm/mach-imx/hotplug.c |  25 +
 arch/arm/mach-imx/platsmp.c | 132 +++-
 arch/arm/mach-imx/src.c |  21 +++
 4 files changed, 169 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 59ce8f3..f7d2be5 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -92,6 +92,7 @@ void imx_print_silicon_rev(const char *cpu, int srev);
 void imx_enable_cpu(int cpu, bool enable);
 void imx_set_cpu_jump(int cpu, void *jump_addr);
 u32 imx_get_cpu_arg(int cpu);
+u32 ls1_get_cpu_arg(int cpu);
 void imx_set_cpu_arg(int cpu, u32 arg);
 #ifdef CONFIG_SMP
 void v7_secondary_startup(void);
@@ -134,6 +135,9 @@ void imx6sl_pm_init(void);
 void imx6sx_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
 
+extern void ls1021a_cpu_die(unsigned int cpu);
+extern int ls1021a_cpu_kill(unsigned int cpu);
+
 #ifdef CONFIG_PM
 void imx51_pm_init(void);
 void imx53_pm_init(void);
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index b35e99c..2ee5e46 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -14,6 +14,7 @@
 #include linux/jiffies.h
 #include asm/cp15.h
 #include asm/proc-fns.h
+#include asm/cacheflush.h
 
 #include common.h
 
@@ -68,3 +69,27 @@ int imx_cpu_kill(unsigned int cpu)
imx_set_cpu_arg(cpu, 0);
return 1;
 }
+
+/*
+ * For LS102x platforms, shutdowning a CPU is not supported by hardware.
+ * So we just put the offline CPU into lower-power state here.
+ */
+void __ref ls1021a_cpu_die(unsigned int cpu)
+{
+   v7_exit_coherency_flush(louis);
+
+   /* LS1021a platform can't really power down a CPU, so we
+* just put it into WFI state here.
+*/
+   wfi();
+}
+
+int ls1021a_cpu_kill(unsigned int cpu)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+   while (!ls1_get_cpu_arg(cpu))
+   if (time_after(jiffies, timeout))
+   return 0;
+   return 1;
+}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7f27001..7735ebb 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -14,6 +14,7 @@
 #include linux/of_address.h
 #include linux/of.h
 #include linux/smp.h
+#include linux/delay.h
 
 #include asm/cacheflush.h
 #include asm/page.h
@@ -23,8 +24,24 @@
 #include common.h
 #include hardware.h
 
+#defineSCFG_CORE0_SFT_RST  0x130
+#defineSCFG_REVCR  0x200
+#defineSCFG_CORESRENCR 0x204
+#defineSCFG_SPARECR4   0x50C
+
+#defineDCFG_CCSR_BRR   0x0E4
+#defineDCFG_CCSR_SCRATCHRW10x200
+
+#defineDCSR_RCPM2_DEBUG1   0x400
+#defineDCSR_RCPM2_DEBUG2   0x414
+
+#defineSTRIDE_4B   4
+
 u32 g_diag_reg;
 static void __iomem *scu_base;
+static void __iomem *dcfg_base;
+static void __iomem *scfg_base;
+static u32 secondary_pre_boot_entry;
 
 static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
@@ -98,32 +115,121 @@ struct smp_operations  imx_smp_ops __initdata = {
 #endif
 };
 
-#define DCFG_CCSR_SCRATCHRW1   0x200
-
-static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int ls1021a_secondary_iomap(void)
 {
-   arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+   struct device_node *np;
+   int ret;
+
+   np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-dcfg);
+   if (!np) {
+   pr_err(%s: failed to find dcfg node.\n, __func__);
+   ret = -EINVAL;
+   goto dcfg_err;
+   }
+
+   dcfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!dcfg_base) {
+   pr_err(%s: failed to map dcfg.\n, __func__);
+   ret = -ENOMEM;
+   goto dcfg_err;
+   }
+
+   np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-scfg);
+   if (!np) {
+   pr_err(%s: failed to find scfg node.\n, __func__);
+   ret = -EINVAL;
+   goto scfg_err;
+   }
+
+   scfg_base = of_iomap(np, 0);
+   of_node_put(np);
+   if (!scfg_base) {
+   pr_err(%s: failed to map scfg.\n, __func__);
+   ret = -ENOMEM;
+   goto scfg_err;
+   }
 
return 0;
+
+scfg_err:
+   iounmap(dcfg_base);
+dcfg_err:
+   return ret;
 }
 
-static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
+void ls1021a_set_secondary_entry(void)
 {
-   struct device_node *np;
-   void __iomem *dcfg_base;
unsigned long paddr;