socsvn commit: r237548 - soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x

aleek at FreeBSD.org aleek at FreeBSD.org
Tue Jun 12 13:59:24 UTC 2012


Author: aleek
Date: Tue Jun 12 13:59:21 2012
New Revision: 237548
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237548

Log:
  Extending GPTimer support

Added:
  soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h
Modified:
  soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c
  soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/files.am37x

Modified: soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c
==============================================================================
--- soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c	Tue Jun 12 13:46:54 2012	(r237547)
+++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c	Tue Jun 12 13:59:21 2012	(r237548)
@@ -29,86 +29,32 @@
 /*
  * Based on gptimer driver by Ben Gray
  */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#define OMAP3_NUM_TIMERS               12
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/timetc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/am37x/am37x_gptimer.h>
 
-/*
- * Ids of the timers used by the kernel
- */
-#define TICKTIMER_GPTIMER       10
-#define TIMECOUNT_GPTIMER       11
-
-/*
- * Standard registers for OMAP3 General Purpose Timers
- */
-#define OMAP3_GPT_TIDR           0x0000
-#define OMAP3_GPT_TIOCP_CFG      0x0010
-#define OMAP3_GPT_TISTAT         0x0014
-#define OMAP3_GPT_TISR           0x0018
-#define OMAP3_GPT_TIER           0x001C
-#define OMAP3_GPT_TWER           0x0020
-#define OMAP3_GPT_TCLR           0x0024
-#define OMAP3_GPT_TCRR           0x0028
-#define OMAP3_GPT_TLDR           0x002C
-#define OMAP3_GPT_TTGR           0x0030
-#define OMAP3_GPT_TWPS           0x0034
-#define OMAP3_GPT_TMAR           0x0038
-#define OMAP3_GPT_TCAR1          0x003C
-#define OMAP3_GPT_TSICR          0x0040
-#define OMAP3_GPT_TCAR2          0x0044
-#define OMAP3_GPT_TPIR           0x0048
-#define OMAP3_GPT_TNIR           0x004C
-#define OMAP3_GPT_TCVR           0x0050
-#define OMAP3_GPT_TOCR           0x0054
-#define OMAP3_GPT_TOWR           0x0058
-
-/**
- *	Data structure per Timer. 
- */
-struct omap3_gptimer {
-	
-	/* Flags indicating current and configured status */
-	unsigned int        flags;
-
-#define OMAP_GPTIMER_AVAILABLE_FLAG      0x01000000
-#define OMAP_GPTIMER_ACTIVATED_FLAG      0x02000000
-	
-    /* Lock taken when configuring the registers */
-	struct mtx          mtx;
-	    
-    /* The memory resource for the timer register set */
-	struct resource*    mem_res;
-	
-	/* The IRQ resource and handle (if installed) for the timer */
-	struct resource*    irq_res;
-	void*               irq_h;
-
-	/* Callback function used when an interrupt is tripped on the given channel */
-	void (*callback)(void *data);
-	
-	/* Callback data passed in the callback ... duh */
-	void*               callback_data;
-	
-	/* The profile of the timer, basically defines the register layout */
-	unsigned int        profile;
-
-	/* The source clock to use */
-	unsigned int        source;
-};
-
-
-/**
- *	Timer driver context, allocated and stored globally, this driver is not
- *	intended to ever be unloaded (see g_omap_gptimer_sc).
- *
- */
-struct omap3_gptimer_softc {
-	device_t              sc_dev;
-	unsigned int          sc_num_timers;
-	struct omap3_gptimer   sc_timers[MAX_NUM_TIMERS];
-	struct omap3_gptimer  *sc_tick_timer;
-	
-};
 
 static struct omap3_gptimer_softc *g_omap3_gptimer_sc = NULL;
 
@@ -146,9 +92,121 @@
 static unsigned
 omap3_gptimer_tc_get_timecount(struct timecounter *tc)
 {
-	return omap3_gptimer_tc_read_4(DMTIMER_TCRR);
+	uint32_t count;
+	omap3_gptimer_read_count(TIMECOUNT_GPTIMER, &count);
+	return(count);
+
+}
+
+/**
+ *	omap_gptimer_read_count - reads the current timer value
+ *	@n: the number of the timer (first timer is number 1)
+ *	@cnt:
+ *	
+ *
+ *	RETURNS:
+ *	Returns 0 on success, otherwise an error code
+ */
+int
+omap3_gptimer_read_count(unsigned int n, uint32_t *cnt)
+{
+	struct omap_gptimer_softc *sc = g_omap_gptimer_sc;
+	struct omap_gptimer *timer;
+	int ret;
+
+	/* Sanity checks */
+	if (sc == NULL)
+		return (ENOMEM);
+	if ((n == 0) || (n > sc->sc_num_timers))
+		return (EINVAL);
+		
+	/* Get a pointer to the individual timer struct */
+	timer = &sc->sc_timers[n-1];
+	
+	OMAP3_GPTIMER_LOCK(timer);
+	
+	if (!(timer->flags & OMAP_GPTIMER_ACTIVATED_FLAG)) {
+		ret = EINVAL;
+	} else {
+		*cnt = omap_gptimer_readl(timer, timer->tcrr);
+		ret = 0;
+	}
+
+	OMAP3_GPTIMER_UNLOCK(timer);
+	
+	return (ret);
+}
+
+
+/**
+ *	omap_gptimer_write_count - writes a value into the current count
+ *	@n: the number of the timer (first timer is number 1)
+ *	@cnt: the value to put in the count register
+ *
+ *	
+ *
+ *	RETURNS:
+ *	Returns 0 on success, otherwise an error code
+ */
+int
+omap3_gptimer_write_count(unsigned int n, uint32_t cnt)
+{
+	struct omap_gptimer_softc *sc = g_omap_gptimer_sc;
+	struct omap_gptimer *timer;
+
+	/* Sanity checks */
+	if (sc == NULL)
+		return (ENOMEM);
+	if ((n == 0) || (n > MAX_NUM_TIMERS))
+		return (EINVAL);
+
+	/* Get a pointer to the individual timer struct */
+	timer = &sc->sc_timers[n-1];
+	if (!(timer->flags & OMAP_GPTIMER_ACTIVATED_FLAG))
+		return (EINVAL);
+
+	OMAP3_GPTIMER_LOCK(timer);
+	
+	omap_gptimer_writel(timer, timer->tcrr, cnt);
+
+	OMAP3_GPTIMER_UNLOCK(timer);
+	
+	return (0);
 }
 
+
+/**
+ *	omap_gptimer_readl - reads a 32-bit value from one of the timer registers
+ *	@timer: Timer device context
+ *	@off: The offset of a register from the timer register address range
+ *
+ *
+ *	RETURNS:
+ *	32-bit value read from the register.
+ */
+static inline uint32_t
+omap3_gptimer_readl(struct omap3_gptimer *timer, bus_size_t off)
+{
+	return (bus_read_4(timer->mem_res, off));
+}
+
+/**
+ *	omap_gptimer_writel - writes a 32-bit value to one of the timer registers
+ *	@timer: Timer device context
+ *	@off: The offset of a register from the timer register address range
+ *	@val: The value to write into the register
+ *
+ *
+ *	RETURNS:
+ *	nothing
+ */
+static inline void
+omap3_gptimer_writel(struct omap3_gptimer *timer, bus_size_t off, uint32_t val)
+{
+	bus_write_4(timer->mem_res, off, val);
+}
+
+
 /**
  *	omap_gptimer_activate - configures the timer
  *	@n: the number of the timer (first timer is number 1)
@@ -201,15 +259,15 @@
 	}
 
 
-	OMAP_GPTIMER_LOCK(timer);
+	OMAP3_GPTIMER_LOCK(timer);
 
 	/* Enable the functional and interface clock */
-	if (flags & OMAP_GPTIMER_32KCLK_FLAG)
-		omap_prcm_clk_set_source(timer->source, F32KHZ_CLK);
+	if (flags & OMAP3_GPTIMER_32KCLK_FLAG)
+		ti_prcm_clk_set_source(timer->source, F32KHZ_CLK);
 	else
-		omap_prcm_clk_set_source(timer->source, SYSCLK_CLK);
+		ti_prcm_clk_set_source(timer->source, SYSCLK_CLK);
 	
-	omap_prcm_clk_enable(timer->source);
+	ti_prcm_clk_enable(timer->source);
 
 
 	/* Store the flags in the timer context */
@@ -219,38 +277,24 @@
 
 	/* Reset the timer and poll on the reset complete flag */
 	if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP3) {
-		omap_gptimer_writel(timer, OMAP_GPT_TIOCP_CFG, 0x2);
+		omap_gptimer_writel(timer, OMAP3_GPT_TIOCP_CFG, 0x2);
 		/* TODO: add a timeout */
-		while ((omap_gptimer_readl(timer, OMAP_GPT_TISTAT) & 0x01) == 0x00)
+		while ((omap_gptimer_readl(timer, OMAP3_GPT_TISTAT) & 0x01) == 0x00)
 			continue;
 
 		/* Clear the interrupt status */
-		omap_gptimer_writel(timer, OMAP_GPT_TISR, TCAR | OVF | MAT);
+		omap_gptimer_writel(timer, OMAP3_GPT_TISR, TCAR | OVF | MAT);
 	}
 
-	else if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP4) {
-		omap_gptimer_writel(timer, OMAP_GPT_TIOCP_CFG, 0x1);
-		/* TODO: add a timeout */
-		while ((omap_gptimer_readl(timer, OMAP_GPT_TIOCP_CFG) & 0x01) == 0x01)
-			continue;
-
-		/* Clear the interrupt status */
-		omap_gptimer_writel(timer, OMAP4_GPT_IRQSTATUS, TCAR | OVF | MAT);
-	}
-	
-
 	/* If the user supplied a zero value we set a free running timer */
 	if (time_us == 0) {
-	
 		/* Set the initial value and roll over value to 0 */
 		startcount = 0x00000000;
-	
 	} else {
-	
 		/* We need to calculate the number of timer ticks in either the reload
 		 * value (for periodic timers) or the overflow
 		 */
-		omap_prcm_clk_get_source_freq(timer->source, &freq);
+		ti_prcm_clk_get_source_freq(timer->source, &freq);
 		freq64 = freq;
 		
 		/* Calculate the period of the timer, 64 bit calculations used to
@@ -277,35 +321,35 @@
 			/* Adjust the count and apply the prescaler */
 			tickcount >>= (prescaler + 1);
 
-			val = omap_gptimer_readl(timer, timer->tclr);
+			val = omap3_gptimer_readl(timer, timer->tclr);
 			val &= ~TCLR_PTV_MASK;
 			val |= TCLR_PRE | (prescaler << 2);
-			omap_gptimer_writel(timer, timer->tclr, val);
+			omap3_gptimer_writel(timer, timer->tclr, val);
 		}
 	
 		/* Calculate the start value */
 		startcount = 0xFFFFFFFFUL - (uint32_t)(tickcount & 0xFFFFFFFFUL);
 
-printf("[BRG] %s, %d : freq64=%llu : tickcount=%llu : startcount=%u : time_us=%u\n",
+		printf("[BRG] %s, %d : freq64=%llu : tickcount=%llu : startcount=%u : time_us=%u\n",
        __func__, __LINE__, freq64, tickcount, startcount, time_us);
 	}
 	
 	/* Load the start value into the count register */
-	omap_gptimer_writel(timer, timer->tcrr, startcount);
+	omap3_gptimer_writel(timer, timer->tcrr, startcount);
 	
 	
 	
 	/* Enable autoload mode if configuring a periodic timer or system tick
 	 * timer. Also set the reload count to match the period tick count.
 	 */
-	if (flags & OMAP_GPTIMER_PERIODIC_FLAG) {
+	if (flags & OMAP3_GPTIMER_PERIODIC_FLAG) {
 		/* Enable auto reload */
-		val = omap_gptimer_readl(timer, timer->tclr);
+		val = omap3_gptimer_readl(timer, timer->tclr);
 		val |= TCLR_AR;
-		omap_gptimer_writel(timer, timer->tclr, val);
+		omap3_gptimer_writel(timer, timer->tclr, val);
 		
 		/* Set the reload value */
-		omap_gptimer_writel(timer, timer->tldr, startcount);
+		omap3_gptimer_writel(timer, timer->tldr, startcount);
 	}
 
 
@@ -318,19 +362,16 @@
 		
 		/* Activate the interrupt */
 		if (bus_setup_intr(sc->sc_dev, timer->irq_res, 
-		                   INTR_TYPE_MISC | INTR_MPSAFE, NULL, omap_gptimer_intr,
+		                   INTR_TYPE_MISC | INTR_MPSAFE, NULL, omap3_gptimer_intr,
 						   (void*)timer, &timer->irq_h)) {
 			device_printf(sc->sc_dev, "Error: failed to activate interrupt\n");
 		}
 
 		/* Enable the overflow interrupts. */
 		if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP3) {
-			val = omap_gptimer_readl(timer, OMAP_GPT_TIER);
+			val = omap3_gptimer_readl(timer, OMAP3_GPT_TIER);
 			val |= OVF;
-			omap_gptimer_writel(timer, OMAP_GPT_TIER, val);
-		}
-		else if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP4) {
-			omap_gptimer_writel(timer, OMAP4_GPT_IRQENABLE_SET, OVF);
+			omap3_gptimer_writel(timer, OMAP3_GPT_TIER, val);
 		}
 	}
 
@@ -338,9 +379,9 @@
 	/* Finally set the activated flag */
 	timer->flags |= OMAP_GPTIMER_ACTIVATED_FLAG;
 
-	OMAP_GPTIMER_UNLOCK(timer);
+	OMAP3_GPTIMER_UNLOCK(timer);
 	
-printf("[BRG] %s, %d\n", __func__, __LINE__);
+	printf("[BRG] %s, %d\n", __func__, __LINE__);
 
 	return (0);
 }

Added: soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h	Tue Jun 12 13:59:21 2012	(r237548)
@@ -0,0 +1,139 @@
+#define OMAP3_NUM_TIMERS		12
+
+/*
+ * Ids of the timers used by the kernel
+ */
+#define TICKTIMER_GPTIMER		10
+#define TIMECOUNT_GPTIMER		11
+
+/*
+ * Standard registers for OMAP3 General Purpose Timers
+ */
+#define OMAP3_GPT_TIDR			0x0000
+#define OMAP3_GPT_TIOCP_CFG		0x0010
+#define OMAP3_GPT_TISTAT		0x0014
+#define OMAP3_GPT_TISR           0x0018
+#define OMAP3_GPT_TIER           0x001C
+#define OMAP3_GPT_TWER           0x0020
+#define OMAP3_GPT_TCLR           0x0024
+#define OMAP3_GPT_TCRR           0x0028
+#define OMAP3_GPT_TLDR           0x002C
+#define OMAP3_GPT_TTGR           0x0030
+#define OMAP3_GPT_TWPS           0x0034
+#define OMAP3_GPT_TMAR           0x0038
+#define OMAP3_GPT_TCAR1          0x003C
+#define OMAP3_GPT_TSICR          0x0040
+#define OMAP3_GPT_TCAR2          0x0044
+#define OMAP3_GPT_TPIR           0x0048
+#define OMAP3_GPT_TNIR           0x004C
+#define OMAP3_GPT_TCVR           0x0050
+#define OMAP3_GPT_TOCR           0x0054
+#define OMAP3_GPT_TOWR           0x0058
+
+/* GPT_TCLR Register bit fields */
+#define TCLR_GPO_CFG            (0x1 << 14)
+#define TCLR_CAPT_MODE          (0x1 << 13)
+#define TCLR_PT                 (0x1 << 12)
+#define TCLR_TRG_MASK           (0x3 << 10)
+#define TCLR_TCM_MASK           (0x3 << 8)
+#define TCLR_SCPWM              (0x1 << 7)
+#define TCLR_CE                 (0x1 << 6)
+#define TCLR_PRE                (0x1 << 5)
+#define TCLR_PTV_MASK           (0x7 << 2)
+#define TCLR_AR                 (0x1 << 1)
+#define TCLR_ST                 (0x1 << 0)
+
+/*
+ * The following flags define the clocking source, if specified the timer will
+ * be clocked from the 32Khz source, otherwise it clocked from the sysclk.
+ */
+#define OMAP_GPTIMER_32KCLK_FLAG      0x00000100
+
+
+/**
+ *	Macros for driver mutex locking
+ */
+#define OMAP3_GPTIMER_LOCK(_tmr)            mtx_lock(&(_tmr)->mtx)
+#define	OMAP3_GPTIMER_UNLOCK(_tmr)          mtx_unlock(&(_tmr)->mtx)
+#define OMAP3_GPTIMER_ASSERT_LOCKED(_tmr)   mtx_assert(&(_tmr)->mtx, MA_OWNED);
+#define OMAP3_GPTIMER_ASSERT_UNLOCKED(_tmr) mtx_assert(&(_tmr)->mtx, MA_NOTOWNED);
+
+/**
+ *	Data structure per Timer. 
+ */
+struct omap3_gptimer {
+	
+	/* Flags indicating current and configured status */
+	unsigned int        flags;
+
+#define OMAP_GPTIMER_AVAILABLE_FLAG      0x01000000
+#define OMAP_GPTIMER_ACTIVATED_FLAG      0x02000000
+	
+    /* Lock taken when configuring the registers */
+	struct mtx          mtx;
+	    
+    /* The memory resource for the timer register set */
+	struct resource*    mem_res;
+	
+	/* The IRQ resource and handle (if installed) for the timer */
+	struct resource*    irq_res;
+	void*               irq_h;
+
+	/* Callback function used when an interrupt is tripped on the given channel */
+	void (*callback)(void *data);
+	
+	/* Callback data passed in the callback ... duh */
+	void*               callback_data;
+	
+	/* The profile of the timer, basically defines the register layout */
+	unsigned int        profile;
+
+	/* The source clock to use */
+	unsigned int        source;
+};
+
+
+/**
+ *	Timer driver context, allocated and stored globally, this driver is not
+ *	intended to ever be unloaded (see g_omap_gptimer_sc).
+ *
+ */
+struct omap3_gptimer_softc {
+	device_t              sc_dev;
+	unsigned int          sc_num_timers;
+	struct omap3_gptimer   sc_timers[OMAP3_NUM_TIMERS];
+	struct omap3_gptimer  *sc_tick_timer;
+	
+};
+
+
+static unsigned
+omap3_gptimer_tc_get_timecount(struct timecounter *tc);
+
+static inline uint32_t
+omap3_gptimer_readl(struct omap3_gptimer *timer, bus_size_t off);
+
+
+static inline void
+omap3_gptimer_writel(struct omap3_gptimer *timer, bus_size_t off, uint32_t val);
+
+int
+omap_gptimer_activate(unsigned int n, unsigned int flags, unsigned int time_us,
+                    void (*callback)(void *data), void *data);
+
+static void
+omap3_gptimer_intr(void *arg);
+
+
+static int
+omap3_gptimer_probe(device_t dev);
+
+
+static int
+omap3_gptimer_attach(device_t dev);
+
+int
+omap3_gptimer_write_count(unsigned int n, uint32_t cnt);
+
+int
+omap3_gptimer_read_count(unsigned int n, uint32_t *cnt);

Modified: soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/files.am37x
==============================================================================
--- soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/files.am37x	Tue Jun 12 13:46:54 2012	(r237547)
+++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/files.am37x	Tue Jun 12 13:59:21 2012	(r237548)
@@ -2,7 +2,7 @@
 
 arm/ti/aintc.c						standard
 arm/ti/am37x/am37x_prcm.c			standard
-arm/ti/am37x/am37x_dmtimer.c		standard
+arm/ti/am37x/am37x_gptimer.c		standard
 arm/ti/am37x/am37x_scm_padconf.c	standard
 arm/ti/ti_edma3.c					standard
 arm/ti/ti_mmchs.c					optional	mmc


More information about the svn-soc-all mailing list