Thread (4 messages) 4 messages, 3 authors, 2009-09-01

[RFC/RFT 2/3] iop: clockevent support

flat view
STALE6256d

From: Russell King - ARM Linux <hidden>
Date: 2009-09-01 12:25:11

On Sat, Aug 22, 2009 at 02:05:29PM +0200, Mikael Pettersson wrote:
quoted hunk ↗ jump to hunk
+/*
+ * IOP clockevents (interrupting timer 0).
+ */
+static int iop_set_next_event(unsigned long delta,
+			      struct clock_event_device *unused)
+{
+	u32 tmr = IOP_TMR_EN | IOP_TMR_PRIVILEGED
+		| IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1;
+
+	BUG_ON(delta == 0);
+	write_tmr0(tmr & ~(IOP_TMR_EN | IOP_TMR_RELOAD));
+	write_tcr0(delta);
+	write_tmr0((tmr & ~IOP_TMR_RELOAD) | IOP_TMR_EN);
Hmm, not sure you should be clearing TMR_RELOAD here.  I thought
periodic clock events were initialized by a call to set_mode followed
by a call to set_next_event.
quoted hunk ↗ jump to hunk
+static void iop_set_mode(enum clock_event_mode mode,
+			 struct clock_event_device *unused)
+{
+	u32 tmr = IOP_TMR_EN | IOP_TMR_PRIVILEGED
+		| IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		write_tmr0(tmr & ~IOP_TMR_EN);
+		write_tcr0(ticks_per_jiffy - 1);
+		tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* ->set_next_event sets period and enables timer */
+		tmr &= ~(IOP_TMR_RELOAD | IOP_TMR_EN);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		tmr |= IOP_TMR_EN;
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+	default:
+		tmr &= ~IOP_TMR_EN;
Doesn't this result in the clock mode being overwritten upon
resume/shutdown?  tmr, being a local variable, will always be
initialized with IOP_TMR_RELOAD etc.
quoted hunk ↗ jump to hunk
+		break;
+	}
+
+	write_tmr0(tmr);
+}
+
+static struct clock_event_device iop_clockevent = {
+	.name		= "iop_timer0",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating         = 300,
+	.shift		= 20,	/* ??? crude guesstimate */
+	.set_next_event	= iop_set_next_event,
+	.set_mode	= iop_set_mode,
+};
+
 static unsigned long ticks_per_usec;
 static unsigned long next_jiffy_time;
 
@@ -75,13 +132,12 @@ unsigned long iop_gettimeoffset(void)
 static irqreturn_t
 iop_timer_interrupt(int irq, void *dev_id)
 {
+	struct clock_event_device *evt;
+
 	write_tisr(1);
 
-	while ((signed long)(next_jiffy_time - read_tcr1())
-		>= ticks_per_jiffy) {
-		timer_tick();
-		next_jiffy_time -= ticks_per_jiffy;
-	}
+	evt = &iop_clockevent;
You can use 'dev_id' here, and when registering the interrupt, pass
iop_clockevent via the dev_id field in iop_timer_irq.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help