diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2014-11-21 11:00:10 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-11-30 11:40:16 -0500 |
commit | b9b1de0f4da37dac76d812a27d6065eba02dc05b (patch) | |
tree | d1103001d3ce2fcc150d6dfc40696445e820d90d /arch/arm/mach-mvebu | |
parent | 77ea46d1331e5b46ff4dd98e7296eb17355cff75 (diff) |
ARM: mvebu: synchronize secondary CPU clocks on resume
The Armada XP has multiple cores clocked by independent clocks. The
SMP startup code contains a function called set_secondary_cpus_clock()
called in armada_xp_smp_prepare_cpus() to ensure the clocks of the
secondary CPUs match the clock of the boot CPU.
With the introduction of suspend/resume, this operation is no longer
needed when booting the system, but also when existing the suspend to
RAM state. Therefore this commit reworks a bit the logic: instead of
configuring the clock of all secondary CPUs in
armada_xp_smp_prepare_cpus(), we do it on a per-secondary CPU basis in
armada_xp_boot_secondary(), as this function gets called when existing
suspend to RAM for each secondary CPU.
Since the function now only takes care of one CPU, we rename it from
set_secondary_cpus_clock() to set_secondary_cpu_clock(), and it looses
its __init marker, as it is now used beyond the system initialization.
Note that we can't use smp_processor_id() directly, because when
exiting from suspend to RAM, the code is apparently executed with
preemption enabled, so smp_processor_id() is not happy (prints a
warning). We therefore switch to using get_cpu()/put_cpu(), even
though we pretty much have the guarantee that the code starting the
secondary CPUs is going to run on the boot CPU and will not be
migrated.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-14-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'arch/arm/mach-mvebu')
-rw-r--r-- | arch/arm/mach-mvebu/platsmp.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 895dc373c8a1..e65e69a7e65d 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #define AXP_BOOTROM_BASE 0xfff00000 | 33 | #define AXP_BOOTROM_BASE 0xfff00000 |
34 | #define AXP_BOOTROM_SIZE 0x100000 | 34 | #define AXP_BOOTROM_SIZE 0x100000 |
35 | 35 | ||
36 | static struct clk *__init get_cpu_clk(int cpu) | 36 | static struct clk *get_cpu_clk(int cpu) |
37 | { | 37 | { |
38 | struct clk *cpu_clk; | 38 | struct clk *cpu_clk; |
39 | struct device_node *np = of_get_cpu_node(cpu, NULL); | 39 | struct device_node *np = of_get_cpu_node(cpu, NULL); |
@@ -46,29 +46,28 @@ static struct clk *__init get_cpu_clk(int cpu) | |||
46 | return cpu_clk; | 46 | return cpu_clk; |
47 | } | 47 | } |
48 | 48 | ||
49 | static void __init set_secondary_cpus_clock(void) | 49 | static void set_secondary_cpu_clock(unsigned int cpu) |
50 | { | 50 | { |
51 | int thiscpu, cpu; | 51 | int thiscpu; |
52 | unsigned long rate; | 52 | unsigned long rate; |
53 | struct clk *cpu_clk; | 53 | struct clk *cpu_clk; |
54 | 54 | ||
55 | thiscpu = smp_processor_id(); | 55 | thiscpu = get_cpu(); |
56 | |||
56 | cpu_clk = get_cpu_clk(thiscpu); | 57 | cpu_clk = get_cpu_clk(thiscpu); |
57 | if (!cpu_clk) | 58 | if (!cpu_clk) |
58 | return; | 59 | goto out; |
59 | clk_prepare_enable(cpu_clk); | 60 | clk_prepare_enable(cpu_clk); |
60 | rate = clk_get_rate(cpu_clk); | 61 | rate = clk_get_rate(cpu_clk); |
61 | 62 | ||
62 | /* set all the other CPU clk to the same rate than the boot CPU */ | 63 | cpu_clk = get_cpu_clk(cpu); |
63 | for_each_possible_cpu(cpu) { | 64 | if (!cpu_clk) |
64 | if (cpu == thiscpu) | 65 | goto out; |
65 | continue; | 66 | clk_set_rate(cpu_clk, rate); |
66 | cpu_clk = get_cpu_clk(cpu); | 67 | clk_prepare_enable(cpu_clk); |
67 | if (!cpu_clk) | 68 | |
68 | return; | 69 | out: |
69 | clk_set_rate(cpu_clk, rate); | 70 | put_cpu(); |
70 | clk_prepare_enable(cpu_clk); | ||
71 | } | ||
72 | } | 71 | } |
73 | 72 | ||
74 | static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) | 73 | static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) |
@@ -78,6 +77,7 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
78 | pr_info("Booting CPU %d\n", cpu); | 77 | pr_info("Booting CPU %d\n", cpu); |
79 | 78 | ||
80 | hw_cpu = cpu_logical_map(cpu); | 79 | hw_cpu = cpu_logical_map(cpu); |
80 | set_secondary_cpu_clock(hw_cpu); | ||
81 | mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); | 81 | mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); |
82 | 82 | ||
83 | /* | 83 | /* |
@@ -126,7 +126,6 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) | |||
126 | struct resource res; | 126 | struct resource res; |
127 | int err; | 127 | int err; |
128 | 128 | ||
129 | set_secondary_cpus_clock(); | ||
130 | flush_cache_all(); | 129 | flush_cache_all(); |
131 | set_cpu_coherent(); | 130 | set_cpu_coherent(); |
132 | 131 | ||