aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2012-05-16 10:55:54 -0400
committerNicolas Pitre <nicolas.pitre@linaro.org>2013-07-30 09:02:14 -0400
commit3f09d4799ecc076cccc11ab2333a36ec849d24f5 (patch)
tree07fb251ee08d956b5284264ea1c8d9516838132e
parent1c33be57496d927ce05b2513ff0c108f69db4345 (diff)
ARM: bL_switcher: add clockevent save/restore support
Per-CPU timers that are shutdown when a CPU is switched over must be disabled upon switching and reprogrammed on the inbound CPU by relying on the clock events management API. save/restore sequence is executed with irqs disabled as mandated by the clock events API. The next_event is an absolute time, hence, when the inbound CPU resumes, if the timer has expired the min delta is forced into the tick device to fire after few cycles. This patch adds switching support for clock events that are per-CPU and have to be migrated when a switch takes place; the cpumask of the clock event device is checked against the cpumask of the current cpu, and if they match, the clockevent device mode is saved and it is put in shutdown mode. Resume code reprogrammes the tick device accordingly. Tested on A15/A7 fast models and architected timers. Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Nicolas Pitre <nico@linaro.org>
-rw-r--r--arch/arm/common/bL_switcher.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
index f8f2e96b1466..ca04b5384bb0 100644
--- a/arch/arm/common/bL_switcher.c
+++ b/arch/arm/common/bL_switcher.c
@@ -15,7 +15,11 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/cpu_pm.h> 17#include <linux/cpu_pm.h>
18#include <linux/cpumask.h>
18#include <linux/workqueue.h> 19#include <linux/workqueue.h>
20#include <linux/clockchips.h>
21#include <linux/hrtimer.h>
22#include <linux/tick.h>
19#include <linux/mm.h> 23#include <linux/mm.h>
20#include <linux/string.h> 24#include <linux/string.h>
21#include <linux/irqchip/arm-gic.h> 25#include <linux/irqchip/arm-gic.h>
@@ -121,6 +125,8 @@ static int bL_switchpoint(unsigned long _arg)
121static int bL_switch_to(unsigned int new_cluster_id) 125static int bL_switch_to(unsigned int new_cluster_id)
122{ 126{
123 unsigned int mpidr, cpuid, clusterid, ob_cluster, ib_cluster, this_cpu; 127 unsigned int mpidr, cpuid, clusterid, ob_cluster, ib_cluster, this_cpu;
128 struct tick_device *tdev;
129 enum clock_event_mode tdev_mode;
124 int ret; 130 int ret;
125 131
126 mpidr = read_mpidr(); 132 mpidr = read_mpidr();
@@ -166,6 +172,14 @@ static int bL_switch_to(unsigned int new_cluster_id)
166 */ 172 */
167 arch_send_wakeup_ipi_mask(cpumask_of(this_cpu)); 173 arch_send_wakeup_ipi_mask(cpumask_of(this_cpu));
168 174
175 tdev = tick_get_device(this_cpu);
176 if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
177 tdev = NULL;
178 if (tdev) {
179 tdev_mode = tdev->evtdev->mode;
180 clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
181 }
182
169 ret = cpu_pm_enter(); 183 ret = cpu_pm_enter();
170 184
171 /* we can not tolerate errors at this point */ 185 /* we can not tolerate errors at this point */
@@ -191,6 +205,12 @@ static int bL_switch_to(unsigned int new_cluster_id)
191 205
192 ret = cpu_pm_exit(); 206 ret = cpu_pm_exit();
193 207
208 if (tdev) {
209 clockevents_set_mode(tdev->evtdev, tdev_mode);
210 clockevents_program_event(tdev->evtdev,
211 tdev->evtdev->next_event, 1);
212 }
213
194 local_fiq_enable(); 214 local_fiq_enable();
195 local_irq_enable(); 215 local_irq_enable();
196 216