Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 6 Jan 2006 20:29:08 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 89293 for review
Message-ID:  <200601062029.k06KT8sJ041817@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=89293

Change 89293 by imp@imp_Speedy on 2006/01/06 20:29:07

	Streamline the timer driver a little.  Move from using TIMER_
	defines to ST_ defines, to match the atmel datasheet.  Use macros
	rather than raw-bus_space calls to access these registers.  Fix
	DELAY by writing the RTMR in attach rather than at clock init time
	as well as making sure it will terminate.  Optimize DELAY as well to
	avoid complicated math.
	
	Moved cpu_reset to the at91rm92timer device file, since that's
	where the reset hardware lives.
	
	Remove redundant definitions of ST_ that I created before.
	
	# DELAY needs to migrate 

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91rm92.c#10 edit
.. //depot/projects/arm/src/sys/arm/at91/at91rm92reg.h#11 edit
.. //depot/projects/arm/src/sys/arm/at91/at91rm92timer.c#5 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91rm92.c#10 (text+ko) ====

@@ -291,22 +291,6 @@
 	return (0);
 }
 
-void
-cpu_reset(void)
-{
-	struct at91rm92_softc *sc = at91rm92_softc;
-
-	/*
-	 * Reset the CPU by programmig the watchdog timer to reset the
-	 * CPU after 128 'slow' clocks, or about ~4ms.  Loop until
-	 * the reset happens for safety.
-	 */
-	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, ST_WDMR, ST_RSTEN | 2);
-	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, ST_CR, ST_WDRST);
-	while (1)
-		continue;
-}
-
 static struct resource *
 at91rm92_alloc_resource(device_t dev, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)

==== //depot/projects/arm/src/sys/arm/at91/at91rm92reg.h#11 (text+ko) ====

@@ -203,19 +203,6 @@
 #define PIOD_OWDR		(0xa00 + 164) /* Output write disable register */
 #define PIOD_OWSR		(0xa00 + 168) /* Output write status register */
 
-#define ST_CR			(0xd00 + 0) /* Control register */
-#define   ST_WDRST 1
-#define ST_PIMR			(0xd00 + 4) /* Period Interval Mode register */
-#define ST_WDMR			(0xd00 + 8) /* Watchdog Mode register */
-#define   ST_RSTEN (1 << 16)
-#define ST_RTMR			(0xd00 + 12) /* Reat-time Mode register */
-#define ST_SR			(0xd00 + 16) /* Status register */
-#define ST_IER			(0xd00 + 20) /* Interrupt Enable register */
-#define ST_IDR			(0xd00 + 24) /* Interrupt Disable register */
-#define ST_IMR			(0xd00 + 28) /* Interrupt Mask register */
-#define ST_RTAR			(0xd00 + 32) /* Real-time Alarm register */
-#define ST_CRTR			(0xd00 + 36) /* Current Real-time register */
-
 /* IRQs : */
 /*
  * 0: AIC 
@@ -280,19 +267,27 @@
 
 /* Timer */
 
-#define AT91RM92_TIMER_BASE	0xffffd00
-#define AT91RM92_TIMER_SIZE	0x100
+#define AT91RM92_ST_BASE	0xffffd00
+#define AT91RM92_ST_SIZE	0x100
 
-#define TIMER_CR		0x00 /* Control register */
-#define TIMER_PIMR		0x04 /* Period interval mode register */
-#define TIMER_WMR		0x08 /* Watchdog mode register */
-#define TIMER_RTMR		0x0c /* Real-time mode register */
-#define TIMER_SR		0x10 /* Status register */
-#define TIMER_IER		0x14 /* Interrupt enable register */
-#define TIMER_IDR		0x18 /* Interrupt disable register */
-#define TIMER_IMR		0x1c /* Interrupt mask register */
-#define TIMER_RTAR		0x20 /* Real-time alarm register */
-#define	TIMER_CRTR		0x24 /* Current real-time register */
+#define ST_CR		0x00 /* Control register */
+#define ST_CR_WDRST	(1U << 0) /* WDRST: Watchdog Timer Restart */
+#define ST_PIMR		0x04 /* Period interval mode register */
+#define ST_WDMR		0x08 /* Watchdog mode register */
+#define ST_WDMR_EXTEN	(1U << 17) /* EXTEN: External Signal Assert Enable */
+#define ST_WDMR_RSTEN	(1U << 16) /* RSTEN: Reset Enable */
+#define ST_RTMR		0x0c /* Real-time mode register */
+#define ST_SR		0x10 /* Status register */
+#define ST_SR_PITS	(1U << 0) /* PITS: Period Interval Timer Status */
+#define ST_SR_WDOVF	(1U << 1) /* WDOVF: Watchdog Overflow */
+#define ST_SR_RTTINC	(1U << 2) /* RTTINC: Real-time Timer Increment */
+#define ST_SR_ALMS	(1U << 3) /* ALMS: Alarm Status */
+#define ST_IER		0x14 /* Interrupt enable register */
+#define ST_IDR		0x18 /* Interrupt disable register */
+#define ST_IMR		0x1c /* Interrupt mask register */
+#define ST_RTAR		0x20 /* Real-time alarm register */
+#define	ST_CRTR		0x24 /* Current real-time register */
+#define ST_CRTR_MASK	0xfffff /* 20-bit counter */
 
 #define AT91RM92_SPI_BASE	0xffe0000
 #define AT91RM92_SPI_SIZE	0x4000

==== //depot/projects/arm/src/sys/arm/at91/at91rm92timer.c#5 (text+ko) ====

@@ -50,6 +50,22 @@
 	device_t		dev;
 } *timer_softc;
 
+#define RD4(off) \
+	bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh, (off))
+#define WR4(off, val) \
+	bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh, (off), (val))
+
+static inline int
+st_crtr(void)
+{
+	int cur1, cur2;
+	do {
+		cur1 = RD4(ST_CRTR);
+		cur2 = RD4(ST_CRTR);
+	} while (cur1 != cur2);
+	return (cur1);
+}
+
 static unsigned at91rm92timer_get_timecount(struct timecounter *tc);
 
 static struct timecounter at91rm92timer_timecounter = {
@@ -75,9 +91,15 @@
 	timer_softc = device_get_softc(dev);
 	timer_softc->sc_st = sc->sc_st;
 	timer_softc->dev = dev;
-	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_TIMER_BASE,
-	    AT91RM92_TIMER_SIZE, &timer_softc->sc_sh) != 0)
+	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_ST_BASE,
+	    AT91RM92_ST_SIZE, &timer_softc->sc_sh) != 0)
 		panic("couldn't subregion timer registers");
+	/*
+	 * Real time counter increments every clock cycle, need to set before
+	 * initializing clocks so that DELAY works.
+	 */
+	WR4(ST_RTMR, 1);
+
 	return (0);
 }
 
@@ -100,14 +122,7 @@
 static unsigned
 at91rm92timer_get_timecount(struct timecounter *tc)
 {
-	int cur1, cur2;
-	do {
-		cur1 = bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh,
-		    TIMER_CRTR);
-		cur2 = bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh,
-		    TIMER_CRTR);
-	} while (cur1 != cur2);
-	return (cur1);
+	return (st_crtr());
 }
 
 static void
@@ -116,10 +131,8 @@
 	struct trapframe *fp = arg;
 
 	/* The interrupt is shared, so we have to make sure it's for us. */
-	if (bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh,
-	    TIMER_SR) & 1) {
+	if (RD4(ST_SR) & ST_SR_PITS)
 		hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
-	}
 }
 
 void
@@ -137,8 +150,7 @@
 	}
 	rel_value = 32768 / hz;
 	/* Disable all interrupts. */
-	bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh,
-	    TIMER_IDR, 0xffffffff);
+	WR4(ST_IDR, 0xffffffff);
 	/* The system timer shares the system irq (1) */
 	irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1,
 	  RF_ACTIVE | RF_SHAREABLE);
@@ -148,42 +160,45 @@
 		bus_setup_intr(dev, irq, INTR_TYPE_CLK | INTR_FAST,
 		    clock_intr, NULL, &ih);
 
-	bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh,
-	    TIMER_PIMR, rel_value);
-	/* Real time counter increments every clock cycle. */
-	bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh, 
-	    TIMER_RTMR, 1);
+	WR4(ST_PIMR, rel_value);
 
 	/* Enable PITS interrupts. */
-	bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh, 
-	    TIMER_IER, 1);
+	WR4(ST_IER, ST_SR_PITS);
 	tc_init(&at91rm92timer_timecounter);
 }
 
 void
 DELAY(int n)
 {
-	uint32_t usec = 0;
-	uint32_t cur1, cur2, old, delta = 0;
+	uint32_t start, end, cur;
 
-	old = bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh,
-	    TIMER_CRTR);
-	while (usec < n) {
-		do {
-			cur1 = bus_space_read_4(timer_softc->sc_st, 
-			    timer_softc->sc_sh, TIMER_CRTR);
-			cur2 = bus_space_read_4(timer_softc->sc_st, 
-			    timer_softc->sc_sh, TIMER_CRTR);
-		} while (cur1 != cur2);
-		if (old > cur1)
-			delta += (old + (0xfffff + 1 - cur1));
-		else
-			delta += (cur1 - old);
-		usec += delta / 32768 * 1000000;
-		delta = 0;
-			
+	start = st_crtr();
+	n = (n * 1000000) / 32768;
+	if (n <= 0)
+		n = 1;
+	end = (start + n) & ST_CRTR_MASK;
+	cur = start;
+	if (start > end) {
+		while (cur >= start || cur < end)
+			cur = st_crtr();
+	} else {
+		while (cur < end)
+			cur = st_crtr();
+	}
+}
 
-	}
+void
+cpu_reset(void)
+{
+	/*
+	 * Reset the CPU by programmig the watchdog timer to reset the
+	 * CPU after 128 'slow' clocks, or about ~4ms.  Loop until
+	 * the reset happens for safety.
+	 */
+	WR4(ST_WDMR, ST_WDMR_RSTEN | 2);
+	WR4(ST_CR, ST_CR_WDRST);
+	while (1)
+		continue;
 }
 
 void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200601062029.k06KT8sJ041817>