summary refs log tree commit diff
path: root/arch/arm/mach-footbridge
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-11-30 12:21:21 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-12-29 12:36:07 +0000
commit4808972a1cac08f8e8d65419ab56d27a9da3a922 (patch)
tree3d026b41bf42408ebd8205b976dc19f582e07a1e /arch/arm/mach-footbridge
parent6cefe92f2991c2bcd8f3a16faa9f4e3c91be48f2 (diff)
downloadlinux-4808972a1cac08f8e8d65419ab56d27a9da3a922.tar.gz
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>
Diffstat (limited to 'arch/arm/mach-footbridge')
-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 785e4199f9cd..2babdbcaa691 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;