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