aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2005-06-29 14:59:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-06-29 14:59:48 -0400
commitb3402cf50efead37dd9553b90fbf1486e09fb78e (patch)
tree75e2bf1533a10c7e4540cb7a925089a7fd3b6d91
parent20f720ccce8864583365d844d48d3fe8d0d171ad (diff)
[PATCH] ARM: 2771/1: Dynamic Tick support for OMAP, take 4
Patch from Tony Lindgren This patch adds support for Dynamic Tick Timer for OMAP. This patch is an updated version of ARM patch 2642/1 to make it work with the already integrated generic ARM dyntick support. Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-omap/pm.c16
-rw-r--r--arch/arm/mach-omap/time.c44
2 files changed, 52 insertions, 8 deletions
diff --git a/arch/arm/mach-omap/pm.c b/arch/arm/mach-omap/pm.c
index 00fac155df2a..6b03ccdc1e92 100644
--- a/arch/arm/mach-omap/pm.c
+++ b/arch/arm/mach-omap/pm.c
@@ -41,7 +41,9 @@
41#include <linux/pm.h> 41#include <linux/pm.h>
42 42
43#include <asm/io.h> 43#include <asm/io.h>
44#include <asm/mach/time.h>
44#include <asm/mach-types.h> 45#include <asm/mach-types.h>
46
45#include <asm/arch/omap16xx.h> 47#include <asm/arch/omap16xx.h>
46#include <asm/arch/pm.h> 48#include <asm/arch/pm.h>
47#include <asm/arch/mux.h> 49#include <asm/arch/mux.h>
@@ -80,13 +82,13 @@ void omap_pm_idle(void)
80 return; 82 return;
81 } 83 }
82 mask32 = omap_readl(ARM_SYSST); 84 mask32 = omap_readl(ARM_SYSST);
83 local_fiq_enable();
84 local_irq_enable();
85 85
86#if defined(CONFIG_OMAP_32K_TIMER) && defined(CONFIG_NO_IDLE_HZ) 86 /*
87 /* Override timer to use VST for the next cycle */ 87 * Since an interrupt may set up a timer, we don't want to
88 omap_32k_timer_next_vst_interrupt(); 88 * reprogram the hardware timer with interrupts enabled.
89#endif 89 * Re-enable interrupts only after returning from idle.
90 */
91 timer_dyn_reprogram();
90 92
91 if ((mask32 & DSP_IDLE) == 0) { 93 if ((mask32 & DSP_IDLE) == 0) {
92 __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); 94 __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
@@ -102,6 +104,8 @@ void omap_pm_idle(void)
102 104
103 func_ptr(); 105 func_ptr();
104 } 106 }
107 local_fiq_enable();
108 local_irq_enable();
105} 109}
106 110
107/* 111/*
diff --git a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
index 589e8b2740dd..dd34e9f4c413 100644
--- a/arch/arm/mach-omap/time.c
+++ b/arch/arm/mach-omap/time.c
@@ -4,7 +4,7 @@
4 * OMAP Timers 4 * OMAP Timers
5 * 5 *
6 * Copyright (C) 2004 Nokia Corporation 6 * Copyright (C) 2004 Nokia Corporation
7 * Partial timer rewrite and additional VST timer support by 7 * Partial timer rewrite and additional dynamic tick timer support by
8 * Tony Lindgen <tony@atomide.com> and 8 * Tony Lindgen <tony@atomide.com> and
9 * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> 9 * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
10 * 10 *
@@ -261,7 +261,6 @@ unsigned long long sched_clock(void)
261 * so with HZ = 100, TVR = 327.68. 261 * so with HZ = 100, TVR = 327.68.
262 */ 262 */
263#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1) 263#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
264#define MAX_SKIP_JIFFIES 25
265#define TIMER_32K_SYNCHRONIZED 0xfffbc410 264#define TIMER_32K_SYNCHRONIZED 0xfffbc410
266 265
267#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ 266#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
@@ -347,6 +346,42 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
347 return IRQ_HANDLED; 346 return IRQ_HANDLED;
348} 347}
349 348
349#ifdef CONFIG_NO_IDLE_HZ
350/*
351 * Programs the next timer interrupt needed. Called when dynamic tick is
352 * enabled, and to reprogram the ticks to skip from pm_idle. Note that
353 * we can keep the timer continuous, and don't need to set it to run in
354 * one-shot mode. This is because the timer will get reprogrammed again
355 * after next interrupt.
356 */
357void omap_32k_timer_reprogram(unsigned long next_tick)
358{
359 omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
360}
361
362static struct irqaction omap_32k_timer_irq;
363extern struct timer_update_handler timer_update;
364
365static int omap_32k_timer_enable_dyn_tick(void)
366{
367 /* No need to reprogram timer, just use the next interrupt */
368 return 0;
369}
370
371static int omap_32k_timer_disable_dyn_tick(void)
372{
373 omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
374 return 0;
375}
376
377static struct dyn_tick_timer omap_dyn_tick_timer = {
378 .enable = omap_32k_timer_enable_dyn_tick,
379 .disable = omap_32k_timer_disable_dyn_tick,
380 .reprogram = omap_32k_timer_reprogram,
381 .handler = omap_32k_timer_interrupt,
382};
383#endif /* CONFIG_NO_IDLE_HZ */
384
350static struct irqaction omap_32k_timer_irq = { 385static struct irqaction omap_32k_timer_irq = {
351 .name = "32KHz timer", 386 .name = "32KHz timer",
352 .flags = SA_INTERRUPT | SA_TIMER, 387 .flags = SA_INTERRUPT | SA_TIMER,
@@ -355,6 +390,11 @@ static struct irqaction omap_32k_timer_irq = {
355 390
356static __init void omap_init_32k_timer(void) 391static __init void omap_init_32k_timer(void)
357{ 392{
393
394#ifdef CONFIG_NO_IDLE_HZ
395 omap_timer.dyn_tick = &omap_dyn_tick_timer;
396#endif
397
358 setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); 398 setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
359 omap_timer.offset = omap_32k_timer_gettimeoffset; 399 omap_timer.offset = omap_32k_timer_gettimeoffset;
360 omap_32k_last_tick = omap_32k_sync_timer_read(); 400 omap_32k_last_tick = omap_32k_sync_timer_read();