[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.