diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index a2d45d742ce444872a6761a90500b6651c9e448f..fbfa1920353d8c9c12ef5535342d8bb2b4b5f5fd 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -68,6 +68,7 @@ pxa_ost0_interrupt(int irq, void *dev_id)
 	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
@@ -100,9 +101,9 @@ pxa_ost0_interrupt(int irq, void *dev_id)
 		 * 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));
@@ -114,14 +115,16 @@ pxa_ost0_interrupt(int irq, void *dev_id)
 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
@@ -132,15 +135,16 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 	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;
 
@@ -149,6 +153,7 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 		/* initializing, released, or preparing for suspend */
 		raw_local_irq_save(irqflags);
 		OIER &= ~OIER_E0;
+		OSSR = OSSR_M0;
 		raw_local_irq_restore(irqflags);
 		break;