aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>2015-03-26 13:32:56 -0400
committerKukjin Kim <kgene@kernel.org>2015-03-26 13:32:56 -0400
commit497ab3b30c7687f52e6711e2ac72d1b696ec7685 (patch)
tree54220f51a7de1ee57e7787c3fa2d03fca9e99cff /arch/arm
parent4e330ae4ab2915444f1e6dca1358a910aa259362 (diff)
ARM: EXYNOS: fix CPU1 hotplug on Exynos3250
CPU1 hotplug may hang when AFTR is used. Fix it by: - setting AUTOWAKEUP_EN bit in ARM_COREx_CONFIGURATION register in exynos_cpu_power_up() - not clearing reserved bits of ARM_COREx_CONFIGURATION register in exynos_cpu_power_down() - waiting while an undocumented register 0x0908 becomes non-zero in exynos_core_restart() - using dsb_sev() instead of IPI in exynos_boot_secondary() on Exynos3250 This patch also fixes hotplug issues during resume from S2R: $ echo mem > /sys/power/state [ 156.517266] Disabling non-boot CPUs ... [ 156.517781] IRQ18 no longer affine to CPU1 [ 156.518043] CPU1: shutdown [ 156.544718] Enabling non-boot CPUs ... [ 156.554925] CPU1: Software reset [ 158.552631] CPU1: failed to come online [ 158.552753] Error taking CPU1 up: -5 Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Kukjin Kim <kgene@kernel.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-exynos/platsmp.c23
-rw-r--r--arch/arm/mach-exynos/regs-pmu.h2
2 files changed, 22 insertions, 3 deletions
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 3f32c47a6d74..511b81ac2a18 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -126,6 +126,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
126 */ 126 */
127void exynos_cpu_power_down(int cpu) 127void exynos_cpu_power_down(int cpu)
128{ 128{
129 u32 core_conf;
130
129 if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") || 131 if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") ||
130 of_machine_is_compatible("samsung,exynos5800"))) { 132 of_machine_is_compatible("samsung,exynos5800"))) {
131 /* 133 /*
@@ -138,7 +140,10 @@ void exynos_cpu_power_down(int cpu)
138 if (!(val & S5P_CORE_LOCAL_PWR_EN)) 140 if (!(val & S5P_CORE_LOCAL_PWR_EN))
139 return; 141 return;
140 } 142 }
141 pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu)); 143
144 core_conf = pmu_raw_readl(EXYNOS_ARM_CORE_CONFIGURATION(cpu));
145 core_conf &= ~S5P_CORE_LOCAL_PWR_EN;
146 pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
142} 147}
143 148
144/** 149/**
@@ -149,7 +154,12 @@ void exynos_cpu_power_down(int cpu)
149 */ 154 */
150void exynos_cpu_power_up(int cpu) 155void exynos_cpu_power_up(int cpu)
151{ 156{
152 pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN, 157 u32 core_conf = S5P_CORE_LOCAL_PWR_EN;
158
159 if (soc_is_exynos3250())
160 core_conf |= S5P_CORE_AUTOWAKEUP_EN;
161
162 pmu_raw_writel(core_conf,
153 EXYNOS_ARM_CORE_CONFIGURATION(cpu)); 163 EXYNOS_ARM_CORE_CONFIGURATION(cpu));
154} 164}
155 165
@@ -227,6 +237,10 @@ static void exynos_core_restart(u32 core_id)
227 if (!of_machine_is_compatible("samsung,exynos3250")) 237 if (!of_machine_is_compatible("samsung,exynos3250"))
228 return; 238 return;
229 239
240 while (!pmu_raw_readl(S5P_PMU_SPARE2))
241 udelay(10);
242 udelay(10);
243
230 val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id)); 244 val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
231 val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG; 245 val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
232 pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id)); 246 pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
@@ -347,7 +361,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
347 361
348 call_firmware_op(cpu_boot, core_id); 362 call_firmware_op(cpu_boot, core_id);
349 363
350 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 364 if (soc_is_exynos3250())
365 dsb_sev();
366 else
367 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
351 368
352 if (pen_release == -1) 369 if (pen_release == -1)
353 break; 370 break;
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index eb461e1c325a..84ddce142ab1 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -49,6 +49,7 @@
49#define S5P_INFORM5 0x0814 49#define S5P_INFORM5 0x0814
50#define S5P_INFORM6 0x0818 50#define S5P_INFORM6 0x0818
51#define S5P_INFORM7 0x081C 51#define S5P_INFORM7 0x081C
52#define S5P_PMU_SPARE2 0x0908
52#define S5P_PMU_SPARE3 0x090C 53#define S5P_PMU_SPARE3 0x090C
53 54
54#define EXYNOS_IROM_DATA2 0x0988 55#define EXYNOS_IROM_DATA2 0x0988
@@ -182,6 +183,7 @@
182 183
183#define S5P_CORE_LOCAL_PWR_EN 0x3 184#define S5P_CORE_LOCAL_PWR_EN 0x3
184#define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8) 185#define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8)
186#define S5P_CORE_AUTOWAKEUP_EN (1 << 31)
185 187
186/* Only for EXYNOS4210 */ 188/* Only for EXYNOS4210 */
187#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154 189#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154