if (c->mode == CLOCK_EVT_MODE_ONESHOT) {
/* Disarm the compare/match, signal the event. */
OIER &= ~OIER_E0;
+ OSSR = OSSR_M0;
c->event_handler(c);
} else if (c->mode == CLOCK_EVT_MODE_PERIODIC) {
/* Call the event handler as many times as necessary
* anything that might put us "very close".
*/
#define MIN_OSCR_DELTA 16
- do {
+ do {
OSSR = OSSR_M0;
- next_match = (OSMR0 += LATCH);
+ next_match = (OSMR0 += LATCH);
c->event_handler(c);
} while (((signed long)(next_match - OSCR) <= MIN_OSCR_DELTA)
&& (c->mode == CLOCK_EVT_MODE_PERIODIC));
static int
pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
{
- unsigned long irqflags;
+ unsigned long flags, next, oscr;
- raw_local_irq_save(irqflags);
- OSMR0 = OSCR + delta;
- OSSR = OSSR_M0;
+ raw_local_irq_save(flags);
OIER |= OIER_E0;
- raw_local_irq_restore(irqflags);
- return 0;
+ next = OSCR + delta;
+ OSMR0 = next;
+ oscr = OSCR;
+ raw_local_irq_restore(flags);
+
+ return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
}
static void
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
raw_local_irq_save(irqflags);
- OSMR0 = OSCR + LATCH;
OSSR = OSSR_M0;
OIER |= OIER_E0;
+ OSMR0 = OSCR + LATCH;
raw_local_irq_restore(irqflags);
break;
case CLOCK_EVT_MODE_ONESHOT:
raw_local_irq_save(irqflags);
OIER &= ~OIER_E0;
+ OSSR = OSSR_M0;
raw_local_irq_restore(irqflags);
break;
/* initializing, released, or preparing for suspend */
raw_local_irq_save(irqflags);
OIER &= ~OIER_E0;
+ OSSR = OSSR_M0;
raw_local_irq_restore(irqflags);
break;