summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-11-30 12:21:21 (GMT)
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-12-29 12:36:07 (GMT)
commit4808972a1cac08f8e8d65419ab56d27a9da3a922 (patch)
tree3d026b41bf42408ebd8205b976dc19f582e07a1e
parent6cefe92f2991c2bcd8f3a16faa9f4e3c91be48f2 (diff)
downloadlinux-4808972a1cac08f8e8d65419ab56d27a9da3a922.tar.xz
ARM: footbridge: add one-shot mode for DC21285 timer
Add a one-shot mode for the DC21285 timer. This allows us to use the NO_HZ modes on this platform. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-footbridge/dc21285-timer.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index 785e419..2babdbc 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -47,6 +47,16 @@ static struct clocksource cksrc_dc21285 = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
+static int ckevt_dc21285_set_next_event(unsigned long delta,
+ struct clock_event_device *c)
+{
+ *CSR_TIMER1_CLR = 0;
+ *CSR_TIMER1_LOAD = delta;
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
+
+ return 0;
+}
+
static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
struct clock_event_device *c)
{
@@ -59,7 +69,9 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
TIMER_CNTL_DIV16;
break;
- default:
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
*CSR_TIMER1_CNTL = 0;
break;
}
@@ -67,9 +79,11 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
static struct clock_event_device ckevt_dc21285 = {
.name = "dc21285_timer1",
- .features = CLOCK_EVT_FEAT_PERIODIC,
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.irq = IRQ_TIMER1,
+ .set_next_event = ckevt_dc21285_set_next_event,
.set_mode = ckevt_dc21285_set_mode,
};
@@ -79,6 +93,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
*CSR_TIMER1_CLR = 0;
+ /* Stop the timer if in one-shot mode */
+ if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
+ *CSR_TIMER1_CNTL = 0;
+
ce->event_handler(ce);
return IRQ_HANDLED;