aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKukjin Kim <kgene.kim@samsung.com>2014-11-21 07:40:23 -0500
committerKukjin Kim <kgene.kim@samsung.com>2014-11-21 07:40:23 -0500
commit68847edc835e582dacbc90ded0c51d27b2ee2bf7 (patch)
tree82cc53aca70ce426098564b463f9644f152876b7
parent03c1b7609fbb367c7a9ae49bd41e72cad38fe305 (diff)
parent13cfa6c4f7facfc690ba9e99ec382c151fddaced (diff)
Merge branch 'v3.19-next/cleanup-samsung' into v3.19-next/mach-exynos
-rw-r--r--arch/arm/mach-exynos/Makefile3
-rw-r--r--arch/arm/mach-exynos/common.h2
-rw-r--r--arch/arm/mach-exynos/hotplug.c91
-rw-r--r--arch/arm/mach-exynos/platsmp.c113
-rw-r--r--arch/arm/mach-exynos/regs-pmu.h3
5 files changed, 116 insertions, 96 deletions
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 775ee35cb277..bcefb5473ee4 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -17,9 +17,6 @@ obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
17 17
18obj-$(CONFIG_SMP) += platsmp.o headsmp.o 18obj-$(CONFIG_SMP) += platsmp.o headsmp.o
19 19
20obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
21CFLAGS_hotplug.o += -march=armv7-a
22
23plus_sec := $(call as-instr,.arch_extension sec,+sec) 20plus_sec := $(call as-instr,.arch_extension sec,+sec)
24AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec) 21AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
25AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec) 22AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index ef95cb1cc00a..d4d09bc1e48c 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -139,8 +139,6 @@ extern void exynos_cpu_resume_ns(void);
139 139
140extern struct smp_operations exynos_smp_ops; 140extern struct smp_operations exynos_smp_ops;
141 141
142extern void exynos_cpu_die(unsigned int cpu);
143
144/* PMU(Power Management Unit) support */ 142/* PMU(Power Management Unit) support */
145 143
146#define PMU_TABLE_END (-1U) 144#define PMU_TABLE_END (-1U)
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
deleted file mode 100644
index 4d86961a7957..000000000000
--- a/arch/arm/mach-exynos/hotplug.c
+++ /dev/null
@@ -1,91 +0,0 @@
1/*
2 * Cloned from linux/arch/arm/mach-realview/hotplug.c
3 *
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/smp.h>
15#include <linux/io.h>
16
17#include <asm/cacheflush.h>
18#include <asm/cp15.h>
19#include <asm/smp_plat.h>
20
21#include "common.h"
22#include "regs-pmu.h"
23
24static inline void cpu_leave_lowpower(void)
25{
26 unsigned int v;
27
28 asm volatile(
29 "mrc p15, 0, %0, c1, c0, 0\n"
30 " orr %0, %0, %1\n"
31 " mcr p15, 0, %0, c1, c0, 0\n"
32 " mrc p15, 0, %0, c1, c0, 1\n"
33 " orr %0, %0, %2\n"
34 " mcr p15, 0, %0, c1, c0, 1\n"
35 : "=&r" (v)
36 : "Ir" (CR_C), "Ir" (0x40)
37 : "cc");
38}
39
40static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
41{
42 u32 mpidr = cpu_logical_map(cpu);
43 u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
44
45 for (;;) {
46
47 /* Turn the CPU off on next WFI instruction. */
48 exynos_cpu_power_down(core_id);
49
50 wfi();
51
52 if (pen_release == core_id) {
53 /*
54 * OK, proper wakeup, we're done
55 */
56 break;
57 }
58
59 /*
60 * Getting here, means that we have come out of WFI without
61 * having been woken up - this shouldn't happen
62 *
63 * Just note it happening - when we're woken, we can report
64 * its occurrence.
65 */
66 (*spurious)++;
67 }
68}
69
70/*
71 * platform-specific code to shutdown a CPU
72 *
73 * Called with IRQs disabled
74 */
75void __ref exynos_cpu_die(unsigned int cpu)
76{
77 int spurious = 0;
78
79 v7_exit_coherency_flush(louis);
80
81 platform_do_lowpower(cpu, &spurious);
82
83 /*
84 * bring this CPU back into the world of cache
85 * coherency, and then restore interrupts
86 */
87 cpu_leave_lowpower();
88
89 if (spurious)
90 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
91}
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 8543064dc445..adb36a8e8785 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -22,6 +22,7 @@
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23 23
24#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
25#include <asm/cp15.h>
25#include <asm/smp_plat.h> 26#include <asm/smp_plat.h>
26#include <asm/smp_scu.h> 27#include <asm/smp_scu.h>
27#include <asm/firmware.h> 28#include <asm/firmware.h>
@@ -33,6 +34,88 @@
33 34
34extern void exynos4_secondary_startup(void); 35extern void exynos4_secondary_startup(void);
35 36
37/*
38 * Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs
39 * during hot-(un)plugging CPUx.
40 *
41 * The feature can be cleared safely during first boot of secondary CPU.
42 *
43 * Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering
44 * down a CPU so the CPU idle clock down feature could properly detect global
45 * idle state when CPUx is off.
46 */
47static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable)
48{
49 if (soc_is_exynos4()) {
50 unsigned int tmp;
51
52 tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
53 if (enable)
54 tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
55 else
56 tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
57 pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
58 }
59}
60
61#ifdef CONFIG_HOTPLUG_CPU
62static inline void cpu_leave_lowpower(u32 core_id)
63{
64 unsigned int v;
65
66 asm volatile(
67 "mrc p15, 0, %0, c1, c0, 0\n"
68 " orr %0, %0, %1\n"
69 " mcr p15, 0, %0, c1, c0, 0\n"
70 " mrc p15, 0, %0, c1, c0, 1\n"
71 " orr %0, %0, %2\n"
72 " mcr p15, 0, %0, c1, c0, 1\n"
73 : "=&r" (v)
74 : "Ir" (CR_C), "Ir" (0x40)
75 : "cc");
76
77 exynos_set_delayed_reset_assertion(core_id, false);
78}
79
80static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
81{
82 u32 mpidr = cpu_logical_map(cpu);
83 u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
84
85 for (;;) {
86
87 /* Turn the CPU off on next WFI instruction. */
88 exynos_cpu_power_down(core_id);
89
90 /*
91 * Exynos4 SoCs require setting
92 * USE_DELAYED_RESET_ASSERTION so the CPU idle
93 * clock down feature could properly detect
94 * global idle state when CPUx is off.
95 */
96 exynos_set_delayed_reset_assertion(core_id, true);
97
98 wfi();
99
100 if (pen_release == core_id) {
101 /*
102 * OK, proper wakeup, we're done
103 */
104 break;
105 }
106
107 /*
108 * Getting here, means that we have come out of WFI without
109 * having been woken up - this shouldn't happen
110 *
111 * Just note it happening - when we're woken, we can report
112 * its occurrence.
113 */
114 (*spurious)++;
115 }
116}
117#endif /* CONFIG_HOTPLUG_CPU */
118
36/** 119/**
37 * exynos_core_power_down : power down the specified cpu 120 * exynos_core_power_down : power down the specified cpu
38 * @cpu : the cpu to power down 121 * @cpu : the cpu to power down
@@ -260,6 +343,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
260 udelay(10); 343 udelay(10);
261 } 344 }
262 345
346 /* No harm if this is called during first boot of secondary CPU */
347 exynos_set_delayed_reset_assertion(core_id, false);
348
263 /* 349 /*
264 * now the secondary core is starting up let it run its 350 * now the secondary core is starting up let it run its
265 * calibrations, then wait for it to finish 351 * calibrations, then wait for it to finish
@@ -341,6 +427,33 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
341 } 427 }
342} 428}
343 429
430#ifdef CONFIG_HOTPLUG_CPU
431/*
432 * platform-specific code to shutdown a CPU
433 *
434 * Called with IRQs disabled
435 */
436static void exynos_cpu_die(unsigned int cpu)
437{
438 int spurious = 0;
439 u32 mpidr = cpu_logical_map(cpu);
440 u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
441
442 v7_exit_coherency_flush(louis);
443
444 platform_do_lowpower(cpu, &spurious);
445
446 /*
447 * bring this CPU back into the world of cache
448 * coherency, and then restore interrupts
449 */
450 cpu_leave_lowpower(core_id);
451
452 if (spurious)
453 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
454}
455#endif /* CONFIG_HOTPLUG_CPU */
456
344struct smp_operations exynos_smp_ops __initdata = { 457struct smp_operations exynos_smp_ops __initdata = {
345 .smp_init_cpus = exynos_smp_init_cpus, 458 .smp_init_cpus = exynos_smp_init_cpus,
346 .smp_prepare_cpus = exynos_smp_prepare_cpus, 459 .smp_prepare_cpus = exynos_smp_prepare_cpus,
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 4ea5e320c6d1..322f13277c3b 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -20,6 +20,7 @@
20 20
21#define S5P_USE_STANDBY_WFI0 (1 << 16) 21#define S5P_USE_STANDBY_WFI0 (1 << 16)
22#define S5P_USE_STANDBY_WFE0 (1 << 24) 22#define S5P_USE_STANDBY_WFE0 (1 << 24)
23#define S5P_USE_DELAYED_RESET_ASSERTION BIT(12)
23 24
24#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n) 25#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n)
25#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28) 26#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28)
@@ -108,6 +109,8 @@
108 (EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr))) 109 (EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
109#define EXYNOS_ARM_CORE_STATUS(_nr) \ 110#define EXYNOS_ARM_CORE_STATUS(_nr) \
110 (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4) 111 (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
112#define EXYNOS_ARM_CORE_OPTION(_nr) \
113 (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x8)
111 114
112#define EXYNOS_ARM_COMMON_CONFIGURATION 0x2500 115#define EXYNOS_ARM_COMMON_CONFIGURATION 0x2500
113#define EXYNOS_COMMON_CONFIGURATION(_nr) \ 116#define EXYNOS_COMMON_CONFIGURATION(_nr) \