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

Ian Lepore ian at FreeBSD.org
Sun Mar 19 21:28:39 UTC 2017


Author: ian
Date: Sun Mar 19 21:28:37 2017
New Revision: 315589
URL: https://svnweb.freebsd.org/changeset/base/315589

Log:
  Eliminate unnecessary read/modify/write sequences during eventtimer setup.
  
  It turns out to be surprisingly expensive to access the gpt hardware (on the
  order of 150ns per read/write).  To cut down on the overhead of setting up
  each eventtimer event, eliminate read-modify-write sequences to manage the
  compare interrupt enable, by keeping a shadow copy of the hardware register
  and only writing to the hardware when the enable bits really change.

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	Sun Mar 19 21:25:27 2017	(r315588)
+++ head/sys/arm/freescale/imx/imx_gpt.c	Sun Mar 19 21:28:37 2017	(r315589)
@@ -83,6 +83,7 @@ struct imx_gpt_softc {
 	uint32_t 		sc_period;
 	uint32_t 		sc_clksrc;
 	uint32_t 		clkfreq;
+	uint32_t		ir_reg;
 	struct eventtimer 	et;
 };
 
@@ -284,16 +285,20 @@ imx_gpt_timer_start(struct eventtimer *e
 		/* Set expected value */
 		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);
+		sc->ir_reg |= GPT_IR_OF2;
+		WRITE4(sc, IMX_GPT_IR, sc->ir_reg);
 		return (0);
 	} else if (first != 0) {
+		/* Enable compare register 3 interrupt if not already on. */
+		if ((sc->ir_reg & GPT_IR_OF3) == 0) {
+			sc->ir_reg |= GPT_IR_OF3;
+			WRITE4(sc, IMX_GPT_IR, sc->ir_reg);
+		}
 		ticks = ((uint32_t)et->et_frequency * first) >> 32;
 		/* Do not disturb, otherwise event will be lost */
 		spinlock_enter();
 		/* Set expected value */
 		WRITE4(sc, IMX_GPT_OCR3, READ4(sc, IMX_GPT_CNT) + ticks);
-		/* Enable compare register 1 Interrupt */
-		SET4(sc, IMX_GPT_IR, GPT_IR_OF3);
 		/* Now everybody can relax */
 		spinlock_exit();
 		return (0);
@@ -309,9 +314,10 @@ imx_gpt_timer_stop(struct eventtimer *et
 
 	sc = (struct imx_gpt_softc *)et->et_priv;
 
-	/* Disable OF2 Interrupt */
-	CLEAR4(sc, IMX_GPT_IR, GPT_IR_OF2);
-	WRITE4(sc, IMX_GPT_SR, GPT_IR_OF2);
+	/* Disable interrupts and clear any pending status. */
+	sc->ir_reg &= ~(GPT_IR_OF2 | GPT_IR_OF3);
+	WRITE4(sc, IMX_GPT_IR, sc->ir_reg);
+	WRITE4(sc, IMX_GPT_SR, GPT_IR_OF2 | GPT_IR_OF3);
 	sc->sc_period = 0;
 
 	return (0);


More information about the svn-src-head mailing list