diff options
Diffstat (limited to 'arch/arm/mach-rockchip/platsmp.c')
-rw-r--r-- | arch/arm/mach-rockchip/platsmp.c | 56 |
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) | |||
72 | static int pmu_set_power_domain(int pd, bool on) | 72 | static 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 |
318 | static int rockchip_cpu_kill(unsigned int cpu) | 322 | static 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) | |||
324 | static void rockchip_cpu_die(unsigned int cpu) | 335 | static 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 | |||
340 | CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops); | 352 | CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops); |