svn commit: r257413 - head/sys/arm/freescale/imx

Ian Lepore ian at FreeBSD.org
Thu Oct 31 02:11:36 UTC 2013


Author: ian
Date: Thu Oct 31 02:11:35 2013
New Revision: 257413
URL: http://svnweb.freebsd.org/changeset/base/257413

Log:
  Reset the timer interrupt status register at the top rather than bottom of
  the interrupt handler.  If the event callback starts a new short timeout,
  the timer can fire before returning from the event callback, and clearing
  the interrupt status after that loses the interrupt and hangs until the
  counter wraps.  Fixing all of this removes the need for the do-nothing
  loop at the top of the handler which really just waited for the counter to
  roll over and reach the one-shot count again.
  
  Also add a missing return(0) in the periodic timer start case.

Modified:
  head/sys/arm/freescale/imx/imx_gpt.c

Modified: head/sys/arm/freescale/imx/imx_gpt.c
==============================================================================
--- head/sys/arm/freescale/imx/imx_gpt.c	Thu Oct 31 02:04:53 2013	(r257412)
+++ head/sys/arm/freescale/imx/imx_gpt.c	Thu Oct 31 02:11:35 2013	(r257413)
@@ -277,14 +277,9 @@ imx_gpt_timer_start(struct eventtimer *e
 		WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + sc->sc_period);
 		/* Enable compare register 2 Interrupt */
 		SET4(sc, IMX_GPT_IR, GPT_IR_OF2);
+		return (0);
 	} else if (first != 0) {
 		ticks = ((uint32_t)et->et_frequency * first) >> 32;
-
-		/*
-		 * TODO: setupt second compare reg with time which will save
-		 * us in case correct one lost, f.e. if period to short and
-		 * setup done later than counter reach target value.
-		 */
 		/* Do not disturb, otherwise event will be lost */
 		spinlock_enter();
 		/* Set expected value */
@@ -293,7 +288,6 @@ imx_gpt_timer_start(struct eventtimer *e
 		SET4(sc, IMX_GPT_IR, GPT_IR_OF1);
 		/* Now everybody can relax */
 		spinlock_exit();
-
 		return (0);
 	}
 
@@ -341,27 +335,32 @@ imx_gpt_intr(void *arg)
 
 	sc = (struct imx_gpt_softc *)arg;
 
-	/* Sometime we not get staus bit when interrupt arrive.  Cache? */
-	while (!(status = READ4(sc, IMX_GPT_SR)))
-		;
+	status = READ4(sc, IMX_GPT_SR);
+
+	/*
+	* Clear interrupt status before invoking event callbacks.  The callback
+	* often sets up a new one-shot timer event and if the interval is short
+	* enough it can fire before we get out of this function.  If we cleared
+	* at the bottom we'd miss the interrupt and hang until the clock wraps.
+	*/
+	WRITE4(sc, IMX_GPT_SR, status);
 
+	/* Handle one-shot timer events. */
 	if (status & GPT_IR_OF1) {
 		if (sc->et.et_active) {
 			sc->et.et_event_cb(&sc->et, sc->et.et_arg);
 		}
 	}
+
+	/* Handle periodic timer events. */
 	if (status & GPT_IR_OF2) {
-		if (sc->et.et_active) {
+		if (sc->et.et_active)
 			sc->et.et_event_cb(&sc->et, sc->et.et_arg);
-			/* Set expected value */
+		if (sc->sc_period != 0)
 			WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) +
 			    sc->sc_period);
-		}
 	}
 
-	/* ACK */
-	WRITE4(sc, IMX_GPT_SR, status);
-
 	return (FILTER_HANDLED);
 }
 


More information about the svn-src-all mailing list