Lines Matching +full:cpu +full:- +full:power +full:- +full:controller
1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright: (C) 2012-2013 Linaro Limited
17 #include <linux/irqchip/arm-gic.h>
20 #include <asm/proc-fns.h>
25 #include <linux/arm-cci.h>
31 #define RESET_A15_NCORERESET(cpu) (1 << (2 + (cpu))) argument
32 #define RESET_A7_NCORERESET(cpu) (1 << (16 + (cpu))) argument
46 static int tc2_pm_cpu_powerup(unsigned int cpu, unsigned int cluster) in tc2_pm_cpu_powerup() argument
48 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); in tc2_pm_cpu_powerup()
49 if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) in tc2_pm_cpu_powerup()
50 return -EINVAL; in tc2_pm_cpu_powerup()
51 ve_spc_set_resume_addr(cluster, cpu, in tc2_pm_cpu_powerup()
53 ve_spc_cpu_wakeup_irq(cluster, cpu, true); in tc2_pm_cpu_powerup()
61 return -EINVAL; in tc2_pm_cluster_powerup()
66 static void tc2_pm_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster) in tc2_pm_cpu_powerdown_prepare() argument
68 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); in tc2_pm_cpu_powerdown_prepare()
69 BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER); in tc2_pm_cpu_powerdown_prepare()
70 ve_spc_cpu_wakeup_irq(cluster, cpu, true); in tc2_pm_cpu_powerdown_prepare()
72 * If the CPU is committed to power down, make sure in tc2_pm_cpu_powerdown_prepare()
73 * the power controller will be in charge of waking it in tc2_pm_cpu_powerdown_prepare()
74 * up upon IRQ, ie IRQ lines are cut from GIC CPU IF in tc2_pm_cpu_powerdown_prepare()
75 * to the CPU by disabling the GIC CPU IF to prevent wfi in tc2_pm_cpu_powerdown_prepare()
76 * from completing execution behind power controller back in tc2_pm_cpu_powerdown_prepare()
98 * On the Cortex-A15 we need to disable in tc2_pm_cluster_cache_disable()
112 static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster) in tc2_core_in_reset() argument
115 RESET_A7_NCORERESET(cpu) in tc2_core_in_reset()
116 : RESET_A15_NCORERESET(cpu); in tc2_core_in_reset()
124 static int tc2_pm_wait_for_powerdown(unsigned int cpu, unsigned int cluster) in tc2_pm_wait_for_powerdown() argument
128 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); in tc2_pm_wait_for_powerdown()
129 BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER); in tc2_pm_wait_for_powerdown()
132 pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n", in tc2_pm_wait_for_powerdown()
133 __func__, cpu, cluster, in tc2_pm_wait_for_powerdown()
137 * We need the CPU to reach WFI, but the power in tc2_pm_wait_for_powerdown()
138 * controller may put the cluster in reset and in tc2_pm_wait_for_powerdown()
139 * power it off as soon as that happens, before in tc2_pm_wait_for_powerdown()
144 if (tc2_core_in_reset(cpu, cluster) || in tc2_pm_wait_for_powerdown()
145 ve_spc_cpu_in_wfi(cpu, cluster)) in tc2_pm_wait_for_powerdown()
146 return 0; /* success: the CPU is halted */ in tc2_pm_wait_for_powerdown()
152 return -ETIMEDOUT; /* timeout */ in tc2_pm_wait_for_powerdown()
155 static void tc2_pm_cpu_suspend_prepare(unsigned int cpu, unsigned int cluster) in tc2_pm_cpu_suspend_prepare() argument
157 ve_spc_set_resume_addr(cluster, cpu, __pa_symbol(mcpm_entry_point)); in tc2_pm_cpu_suspend_prepare()
160 static void tc2_pm_cpu_is_up(unsigned int cpu, unsigned int cluster) in tc2_pm_cpu_is_up() argument
162 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); in tc2_pm_cpu_is_up()
163 BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER); in tc2_pm_cpu_is_up()
164 ve_spc_cpu_wakeup_irq(cluster, cpu, false); in tc2_pm_cpu_is_up()
165 ve_spc_set_resume_addr(cluster, cpu, 0); in tc2_pm_cpu_is_up()
190 * Enable cluster-level coherency, in preparation for turning on the MMU.
202 unsigned int mpidr, cpu, cluster; in tc2_pm_init() local
208 * The power management-related features are hidden behind in tc2_pm_init()
213 "arm,vexpress-scc,v2p-ca15_a7"); in tc2_pm_init()
216 return -ENODEV; in tc2_pm_init()
221 return -EINVAL; in tc2_pm_init()
231 * with the SPC (power controller). We need to be able to in tc2_pm_init()
232 * drive it very early in the boot process to power up in tc2_pm_init()
240 return -ENODEV; in tc2_pm_init()
243 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); in tc2_pm_init()
245 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); in tc2_pm_init()
246 if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) { in tc2_pm_init()
247 pr_err("%s: boot CPU is out of bound!\n", __func__); in tc2_pm_init()
248 return -EINVAL; in tc2_pm_init()
256 pr_info("TC2 power management initialized\n"); in tc2_pm_init()