aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-rockchip/platsmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-rockchip/platsmp.c')
-rw-r--r--arch/arm/mach-rockchip/platsmp.c56
1 files changed, 34 insertions, 22 deletions
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 8fcec1cc101e..3e7a4b761a95 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -72,29 +72,22 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
72static int pmu_set_power_domain(int pd, bool on) 72static int pmu_set_power_domain(int pd, bool on)
73{ 73{
74 u32 val = (on) ? 0 : BIT(pd); 74 u32 val = (on) ? 0 : BIT(pd);
75 struct reset_control *rstc = rockchip_get_core_reset(pd);
75 int ret; 76 int ret;
76 77
78 if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
79 pr_err("%s: could not get reset control for core %d\n",
80 __func__, pd);
81 return PTR_ERR(rstc);
82 }
83
77 /* 84 /*
78 * We need to soft reset the cpu when we turn off the cpu power domain, 85 * We need to soft reset the cpu when we turn off the cpu power domain,
79 * or else the active processors might be stalled when the individual 86 * or else the active processors might be stalled when the individual
80 * processor is powered down. 87 * processor is powered down.
81 */ 88 */
82 if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { 89 if (!IS_ERR(rstc) && !on)
83 struct reset_control *rstc = rockchip_get_core_reset(pd); 90 reset_control_assert(rstc);
84
85 if (IS_ERR(rstc)) {
86 pr_err("%s: could not get reset control for core %d\n",
87 __func__, pd);
88 return PTR_ERR(rstc);
89 }
90
91 if (on)
92 reset_control_deassert(rstc);
93 else
94 reset_control_assert(rstc);
95
96 reset_control_put(rstc);
97 }
98 91
99 ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val); 92 ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
100 if (ret < 0) { 93 if (ret < 0) {
@@ -107,11 +100,17 @@ static int pmu_set_power_domain(int pd, bool on)
107 ret = pmu_power_domain_is_on(pd); 100 ret = pmu_power_domain_is_on(pd);
108 if (ret < 0) { 101 if (ret < 0) {
109 pr_err("%s: could not read power domain state\n", 102 pr_err("%s: could not read power domain state\n",
110 __func__); 103 __func__);
111 return ret; 104 return ret;
112 } 105 }
113 } 106 }
114 107
108 if (!IS_ERR(rstc)) {
109 if (on)
110 reset_control_deassert(rstc);
111 reset_control_put(rstc);
112 }
113
115 return 0; 114 return 0;
116} 115}
117 116
@@ -130,7 +129,7 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle)
130 129
131 if (cpu >= ncores) { 130 if (cpu >= ncores) {
132 pr_err("%s: cpu %d outside maximum number of cpus %d\n", 131 pr_err("%s: cpu %d outside maximum number of cpus %d\n",
133 __func__, cpu, ncores); 132 __func__, cpu, ncores);
134 return -ENXIO; 133 return -ENXIO;
135 } 134 }
136 135
@@ -140,14 +139,19 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle)
140 return ret; 139 return ret;
141 140
142 if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { 141 if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
143 /* We communicate with the bootrom to active the cpus other 142 /*
143 * We communicate with the bootrom to active the cpus other
144 * than cpu0, after a blob of initialize code, they will 144 * than cpu0, after a blob of initialize code, they will
145 * stay at wfe state, once they are actived, they will check 145 * stay at wfe state, once they are actived, they will check
146 * the mailbox: 146 * the mailbox:
147 * sram_base_addr + 4: 0xdeadbeaf 147 * sram_base_addr + 4: 0xdeadbeaf
148 * sram_base_addr + 8: start address for pc 148 * sram_base_addr + 8: start address for pc
149 * */ 149 * The cpu0 need to wait the other cpus other than cpu0 entering
150 udelay(10); 150 * the wfe state.The wait time is affected by many aspects.
151 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
152 */
153 mdelay(1); /* ensure the cpus other than cpu0 to startup */
154
151 writel(virt_to_phys(secondary_startup), sram_base_addr + 8); 155 writel(virt_to_phys(secondary_startup), sram_base_addr + 8);
152 writel(0xDEADBEAF, sram_base_addr + 4); 156 writel(0xDEADBEAF, sram_base_addr + 4);
153 dsb_sev(); 157 dsb_sev();
@@ -317,6 +321,13 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
317#ifdef CONFIG_HOTPLUG_CPU 321#ifdef CONFIG_HOTPLUG_CPU
318static int rockchip_cpu_kill(unsigned int cpu) 322static int rockchip_cpu_kill(unsigned int cpu)
319{ 323{
324 /*
325 * We need a delay here to ensure that the dying CPU can finish
326 * executing v7_coherency_exit() and reach the WFI/WFE state
327 * prior to having the power domain disabled.
328 */
329 mdelay(1);
330
320 pmu_set_power_domain(0 + cpu, false); 331 pmu_set_power_domain(0 + cpu, false);
321 return 1; 332 return 1;
322} 333}
@@ -324,7 +335,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
324static void rockchip_cpu_die(unsigned int cpu) 335static void rockchip_cpu_die(unsigned int cpu)
325{ 336{
326 v7_exit_coherency_flush(louis); 337 v7_exit_coherency_flush(louis);
327 while(1) 338 while (1)
328 cpu_do_idle(); 339 cpu_do_idle();
329} 340}
330#endif 341#endif
@@ -337,4 +348,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
337 .cpu_die = rockchip_cpu_die, 348 .cpu_die = rockchip_cpu_die,
338#endif 349#endif
339}; 350};
351
340CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops); 352CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);