From: Tang Yuantian <yuantian.t...@freescale.com>

PowerPC E500MC serial SoCs, like T2080 T1040 and T4240, use RCPM
to manage power consumption. This patch adds hot plug feature to
RCPM driver.

Signed-off-by: Chenhui Zhao <chenhui.z...@freescale.com>
Signed-off-by: Tang Yuantian <yuantian.t...@freescale.com>
---
 arch/powerpc/include/asm/fsl_pm.h |  2 ++
 arch/powerpc/sysdev/fsl_rcpm.c    | 56 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/arch/powerpc/include/asm/fsl_pm.h 
b/arch/powerpc/include/asm/fsl_pm.h
index 4b09f09..0b03b03 100644
--- a/arch/powerpc/include/asm/fsl_pm.h
+++ b/arch/powerpc/include/asm/fsl_pm.h
@@ -33,6 +33,8 @@ struct fsl_pm_ops {
        void (*irq_unmask)(int cpu);
        void (*cpu_enter_state)(int cpu, int state);
        void (*cpu_exit_state)(int cpu, int state);
+       void (*cpu_up)(int cpu);
+       void (*cpu_die)(int cpu);
        int (*plat_enter_sleep)(void);
        void (*freeze_time_base)(bool freeze);
 
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
index 4bd2d64..acf3f94 100644
--- a/arch/powerpc/sysdev/fsl_rcpm.c
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -128,6 +128,46 @@ static void rcpm_v2_cpu_enter_state(int cpu, int state)
        }
 }
 
+static void rcpm_v1_cpu_die(int cpu)
+{
+       rcpm_v1_cpu_enter_state(cpu, E500_PM_PH15);
+}
+
+static void qoriq_disable_thread(void *info)
+{
+       int hw_cpu = get_hard_smp_processor_id(*(const int *)info);
+       int thread = cpu_thread_in_core(hw_cpu);
+
+       mtspr(SPRN_TENC, TEN_THREAD(thread));
+}
+
+static void rcpm_v2_cpu_die(int cpu)
+{
+       int primary;
+
+       if (threads_per_core == 1) {
+               rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
+               return;
+       }
+
+       primary = cpu_first_thread_sibling(cpu);
+       if (cpu_is_offline(primary) && cpu_is_offline(primary + 1)) {
+               /* when two threads are all offline, put core in PH20 */
+               rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
+       } else {
+               /*
+                * When one thread is offline, disable the thread
+                * by running qoriq_disable_thread() on the other thread.
+                */
+               if (cpu_online(primary))
+                       smp_call_function_single(primary,
+                                       qoriq_disable_thread, &cpu, 1);
+               else
+                       smp_call_function_single(primary + 1,
+                                       qoriq_disable_thread, &cpu, 1);
+       }
+}
+
 static void rcpm_v1_cpu_exit_state(int cpu, int state)
 {
        int hw_cpu = get_hard_smp_processor_id(cpu);
@@ -146,6 +186,12 @@ static void rcpm_v1_cpu_exit_state(int cpu, int state)
        }
 }
 
+static void rcpm_v1_cpu_up(int cpu)
+{
+       rcpm_v1_cpu_exit_state(cpu, E500_PM_PH15);
+       rcpm_v1_irq_unmask(cpu);
+}
+
 static void rcpm_v2_cpu_exit_state(int cpu, int state)
 {
        int hw_cpu = get_hard_smp_processor_id(cpu);
@@ -169,6 +215,12 @@ static void rcpm_v2_cpu_exit_state(int cpu, int state)
        }
 }
 
+static void rcpm_v2_cpu_up(int cpu)
+{
+       rcpm_v2_cpu_exit_state(cpu, E500_PM_PH20);
+       rcpm_v2_irq_unmask(cpu);
+}
+
 static int rcpm_v1_plat_enter_state(int state)
 {
        u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
@@ -275,6 +327,8 @@ static const struct fsl_pm_ops qoriq_rcpm_v1_ops = {
        .irq_unmask = rcpm_v1_irq_unmask,
        .cpu_enter_state = rcpm_v1_cpu_enter_state,
        .cpu_exit_state = rcpm_v1_cpu_exit_state,
+       .cpu_up = rcpm_v1_cpu_up,
+       .cpu_die = rcpm_v1_cpu_die,
        .plat_enter_sleep = rcpm_v1_plat_enter_sleep,
        .set_ip_power = rcpm_v1_set_ip_power,
        .freeze_time_base = rcpm_v1_freeze_time_base,
@@ -286,6 +340,8 @@ static const struct fsl_pm_ops qoriq_rcpm_v2_ops = {
        .irq_unmask = rcpm_v2_irq_unmask,
        .cpu_enter_state = rcpm_v2_cpu_enter_state,
        .cpu_exit_state = rcpm_v2_cpu_exit_state,
+       .cpu_up = rcpm_v2_cpu_up,
+       .cpu_die = rcpm_v2_cpu_die,
        .plat_enter_sleep = rcpm_v2_plat_enter_sleep,
        .set_ip_power = rcpm_v2_set_ip_power,
        .freeze_time_base = rcpm_v2_freeze_time_base,
-- 
2.1.0.27.g96db324

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to