socsvn commit: r237610 - in soc2012/aleek/beaglexm-armv6/sys:
arm/ti/am37x boot/fdt/dts
aleek at FreeBSD.org
aleek at FreeBSD.org
Wed Jun 13 14:38:57 UTC 2012
Author: aleek
Date: Wed Jun 13 14:38:54 2012
New Revision: 237610
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237610
Log:
Almost all OMAP3 GPTIMER support is written
Modified:
soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c
soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h
soc2012/aleek/beaglexm-armv6/sys/boot/fdt/dts/beagleboardxm.dts
Modified: soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c
==============================================================================
--- soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c Wed Jun 13 14:20:15 2012 (r237609)
+++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.c Wed Jun 13 14:38:54 2012 (r237610)
@@ -42,6 +42,7 @@
#include <sys/rman.h>
#include <sys/timetc.h>
#include <sys/lock.h>
+#include "sys/gpio.h""
#include <sys/mutex.h>
#include <machine/bus.h>
@@ -56,8 +57,11 @@
#include <arm/ti/am37x/am37x_gptimer.h>
+
static struct omap3_gptimer_softc *g_omap3_gptimer_sc = NULL;
+static unsigned int delay_loops_per_us = 100;
+
/**
* Timer for tick counting. This is used to measure time by CPU
@@ -89,6 +93,48 @@
.tc_quality = 1000,
};
+#define __omap3_delay(i) \
+ do { \
+ unsigned int cnt = (i); \
+ __asm __volatile("1: subs %0, %0, 1\n" \
+ " bne 1b\n" \
+ : "+r" (cnt) : : "cc"); \
+ } while(0)
+
+/**
+ * omap3_calibrate_delay_loop - uses the setup timecounter to configure delay
+ *
+ * This is not very scientfic, basically just use the timecount to measure the
+ * time to do 1000 delay loops (for loop with 1024 loops).
+ *
+ *
+ */
+static int
+omap3_calibrate_delay_loop(struct timecounter *tc)
+{
+ u_int oldirqstate;
+ unsigned int start, end;
+ uint64_t nanosecs;
+
+ /* Disable interrupts to ensure they don't mess up the calculation */
+ oldirqstate = disable_interrupts(I32_bit);
+
+ start = omap3_gptimer_tc_get_timecount(tc);
+ __omap3_delay(10240);
+ end = omap3_gptimer_tc_get_timecount(tc);
+
+ restore_interrupts(oldirqstate);
+
+ /* Calculate the number of loops in 1us */
+ nanosecs = ((uint64_t)(end - start) * 1000000000ULL) / tc->tc_frequency;
+ delay_loops_per_us = (unsigned int)((uint64_t)(10240 * 1000) / nanosecs);
+
+ printf("OMAP3: delay loop calibrated to %u cycles\n", delay_loops_per_us);
+
+ return (0);
+}
+
+
static unsigned
omap3_gptimer_tc_get_timecount(struct timecounter *tc)
{
@@ -99,7 +145,7 @@
}
/**
- * omap_gptimer_read_count - reads the current timer value
+ * omap3_gptimer_read_count - reads the current timer value
* @n: the number of the timer (first timer is number 1)
* @cnt:
*
@@ -110,8 +156,8 @@
int
omap3_gptimer_read_count(unsigned int n, uint32_t *cnt)
{
- struct omap_gptimer_softc *sc = g_omap_gptimer_sc;
- struct omap_gptimer *timer;
+ struct omap3_gptimer_softc *sc = g_omap3_gptimer_sc;
+ struct omap3_gptimer *timer;
int ret;
/* Sanity checks */
@@ -125,10 +171,10 @@
OMAP3_GPTIMER_LOCK(timer);
- if (!(timer->flags & OMAP_GPTIMER_ACTIVATED_FLAG)) {
+ if (!(timer->flags & OMAP3_GPTIMER_ACTIVATED_FLAG)) {
ret = EINVAL;
} else {
- *cnt = omap_gptimer_readl(timer, timer->tcrr);
+ *cnt = omap3_gptimer_readl(timer, OMAP3_GPT_TCRR);
ret = 0;
}
@@ -139,7 +185,7 @@
/**
- * omap_gptimer_write_count - writes a value into the current count
+ * omap3_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
*
@@ -151,23 +197,23 @@
int
omap3_gptimer_write_count(unsigned int n, uint32_t cnt)
{
- struct omap_gptimer_softc *sc = g_omap_gptimer_sc;
- struct omap_gptimer *timer;
+ struct omap3_gptimer_softc *sc = g_omap3_gptimer_sc;
+ struct omap3_gptimer *timer;
/* Sanity checks */
if (sc == NULL)
return (ENOMEM);
- if ((n == 0) || (n > MAX_NUM_TIMERS))
+ if ((n == 0) || (n > OMAP3_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))
+ if (!(timer->flags & OMAP3_GPTIMER_ACTIVATED_FLAG))
return (EINVAL);
OMAP3_GPTIMER_LOCK(timer);
- omap_gptimer_writel(timer, timer->tcrr, cnt);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TCRR, cnt);
OMAP3_GPTIMER_UNLOCK(timer);
@@ -176,7 +222,7 @@
/**
- * omap_gptimer_readl - reads a 32-bit value from one of the timer registers
+ * omap3_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
*
@@ -191,7 +237,7 @@
}
/**
- * omap_gptimer_writel - writes a 32-bit value to one of the timer registers
+ * omap3_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
@@ -206,9 +252,81 @@
bus_write_4(timer->mem_res, off, val);
}
+/**
+ * omap_gptimer_get_freq - gets the frequency of an activated timer
+ * @n: the number of the timer (first timer is number 1)
+ * @freq: unpon return will contain the current freq
+ *
+ * The timer must be activated, if not this function will return EINVAL.
+ *
+ * RETURNS:
+ * Returns 0 on success, otherwise an error code
+ */
+int
+omap3_gptimer_get_freq(unsigned int n, uint32_t *freq)
+{
+ struct omap3_gptimer_softc *sc = g_omap3_gptimer_sc;
+ struct omap3_gptimer *timer;
+ unsigned int src_freq;
+ unsigned int tmr_freq;
+ unsigned int prescaler;
+ uint32_t tclr, tldr;
+ int rc;
+
+ /* Sanity checks */
+ if (sc == NULL)
+ return (ENOMEM);
+ if ((n == 0) || (n > OMAP3_NUM_TIMERS))
+ return (EINVAL);
+ if (freq == NULL)
+ return (EINVAL);
+
+ /* Get a pointer to the individual timer struct */
+ timer = &sc->sc_timers[n-1];
+ if (!(timer->flags & OMAP3_GPTIMER_ACTIVATED_FLAG))
+ return (EINVAL);
+
+ /* We get the frequency by first reading the source frequency */
+ if ((rc = ti_prcm_clk_get_source_freq(timer->source, &src_freq)) != 0)
+ return (rc);
+
+
+ OMAP3_GPTIMER_LOCK(timer);
+
+ /* Determine if the pre-scalar is enabled and if so the prescaler value */
+ tclr = omap3_gptimer_readl(timer, OMAP3_GPT_TCLR);
+ if (tclr & TCLR_PRE)
+ prescaler = 1UL << (((tclr & TCLR_PTV_MASK) >> 2) + 1);
+ else
+ prescaler = 1;
+
+ /* Get the reload count */
+ tldr = omap3_gptimer_readl(timer, OMAP3_GPT_TLDR);
+
+ OMAP3_GPTIMER_UNLOCK(timer);
+
+
+ /* Calculate the tick freq */
+ tmr_freq = (src_freq / prescaler);
+
+ /* If auto-reload mode is set and the reload count is not zero then the
+ * frequency is the period between overflows.
+ */
+ if ((tclr & TCLR_AR) && (tldr != 0x00000000)) {
+ tmr_freq /= ((0xffffffff - tldr) + 1);
+ }
+
+
+ if (freq != NULL)
+ *freq = tmr_freq;
+
+ return (0);
+}
+
+
/**
- * omap_gptimer_activate - configures the timer
+ * omap3_gptimer_activate - configures the timer
* @n: the number of the timer (first timer is number 1)
* @flags: defines the type of timer to turn on
* @time_ns: the period of the timer in nanoseconds
@@ -220,11 +338,11 @@
* Returns 0 on success, otherwise an error code
*/
int
-omap_gptimer_activate(unsigned int n, unsigned int flags, unsigned int time_us,
+omap3_gptimer_activate(unsigned int n, unsigned int flags, unsigned int time_us,
void (*callback)(void *data), void *data)
{
- struct omap_gptimer_softc *sc = g_omap3_gptimer_sc;
- struct omap_gptimer *timer;
+ struct omap3_gptimer_softc *sc = g_omap3_gptimer_sc;
+ struct omap3_gptimer *timer;
uint32_t val;
uint64_t tickcount;
unsigned int freq;
@@ -243,11 +361,11 @@
timer = &sc->sc_timers[n-1];
/* Sanity check the timer is availabe and not activated */
- if (!(timer->flags & OMAP_GPTIMER_AVAILABLE_FLAG)) {
+ if (!(timer->flags & OMAP3_GPTIMER_AVAILABLE_FLAG)) {
device_printf(sc->sc_dev, "Error: timer %d not available\n", n);
return (EINVAL);
}
- if (timer->flags & OMAP_GPTIMER_ACTIVATED_FLAG) {
+ if (timer->flags & OMAP3_GPTIMER_ACTIVATED_FLAG) {
device_printf(sc->sc_dev, "Error: timer %d already activated\n", n);
return (EINVAL);
}
@@ -277,13 +395,13 @@
/* Reset the timer and poll on the reset complete flag */
if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP3) {
- omap_gptimer_writel(timer, OMAP3_GPT_TIOCP_CFG, 0x2);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TIOCP_CFG, 0x2);
/* TODO: add a timeout */
- while ((omap_gptimer_readl(timer, OMAP3_GPT_TISTAT) & 0x01) == 0x00)
+ while ((omap3_gptimer_readl(timer, OMAP3_GPT_TISTAT) & 0x01) == 0x00)
continue;
/* Clear the interrupt status */
- omap_gptimer_writel(timer, OMAP3_GPT_TISR, TCAR | OVF | MAT);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TISR, TCAR | OVF | MAT);
}
/* If the user supplied a zero value we set a free running timer */
@@ -321,10 +439,10 @@
/* Adjust the count and apply the prescaler */
tickcount >>= (prescaler + 1);
- val = omap3_gptimer_readl(timer, timer->tclr);
+ val = omap3_gptimer_readl(timer, OMAP3_GPT_TCLR);
val &= ~TCLR_PTV_MASK;
val |= TCLR_PRE | (prescaler << 2);
- omap3_gptimer_writel(timer, timer->tclr, val);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TCLR, val);
}
/* Calculate the start value */
@@ -335,7 +453,7 @@
}
/* Load the start value into the count register */
- omap3_gptimer_writel(timer, timer->tcrr, startcount);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TCRR, startcount);
@@ -344,12 +462,12 @@
*/
if (flags & OMAP3_GPTIMER_PERIODIC_FLAG) {
/* Enable auto reload */
- val = omap3_gptimer_readl(timer, timer->tclr);
+ val = omap3_gptimer_readl(timer, OMAP3_GPT_TCLR);
val |= TCLR_AR;
- omap3_gptimer_writel(timer, timer->tclr, val);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TCLR, val);
/* Set the reload value */
- omap3_gptimer_writel(timer, timer->tldr, startcount);
+ omap3_gptimer_writel(timer, OMAP3_GPT_TLDR, startcount);
}
@@ -377,7 +495,7 @@
/* Finally set the activated flag */
- timer->flags |= OMAP_GPTIMER_ACTIVATED_FLAG;
+ timer->flags |= OMAP3_GPTIMER_ACTIVATED_FLAG;
OMAP3_GPTIMER_UNLOCK(timer);
@@ -386,6 +504,127 @@
return (0);
}
+/**
+ * omap3_gptimer_start - starts a one-shot or periodic timer
+ * @n: the number of the timer (first timer is number 1)
+ *
+ *
+ * RETURNS:
+ * Returns 0 on success, otherwise an error code
+ */
+int
+omap3_gptimer_start(unsigned int n)
+{
+ return 0;
+}
+
+/**
+ * omap3_gptimer_stop - stops a one-shot or periodic timer
+ * @n: the number of the timer (first timer is number 1)
+ *
+ *
+ * RETURNS:
+ * Returns 0 on success, otherwise an error code
+ */
+int
+omap3_gptimer_stop(unsigned int n)
+{
+ return 0;
+}
+
+/**
+ * omap3_gptimer_set_intr_filter - sets a filter
+ * @n: the number of the timer (first timer is number 1)
+ *
+ *
+ * RETURNS:
+ * Returns 0 on success, otherwise an error code
+ */
+int
+omap3_gptimer_set_intr_filter(unsigned int n, driver_filter_t filter)
+{
+ struct omap3_gptimer_softc *sc = g_omap3_gptimer_sc;
+ struct omap3_gptimer *timer;
+ uint32_t val;
+
+ /* 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 a callback is already installed this won't work */
+ if (timer->callback != NULL) {
+ OMAP3_GPTIMER_UNLOCK(timer);
+ return(EINVAL);
+ }
+
+ /* Sanity check the timer is already activated and periodic type */
+ if ((timer->flags & (OMAP3_GPTIMER_ACTIVATED_FLAG | OMAP3_GPTIMER_PERIODIC_FLAG))
+ != (OMAP3_GPTIMER_ACTIVATED_FLAG | OMAP3_GPTIMER_PERIODIC_FLAG)) {
+ OMAP3_GPTIMER_UNLOCK(timer);
+ return(EINVAL);
+ }
+
+
+ /* Attempt to activate the interrupt for the tick */
+ if (bus_setup_intr(sc->sc_dev, timer->irq_res, INTR_TYPE_CLK,
+ filter, NULL, NULL, &timer->irq_h)) {
+ device_printf(sc->sc_dev, "Error: failed to activate interrupt\n");
+ OMAP3_GPTIMER_UNLOCK(timer);
+ return(EINVAL);
+ }
+
+
+ /* Enable the overflow interrupts */
+ if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP3) {
+ val = omap3_gptimer_readl(timer, OMAP3_GPT_TIER);
+ val |= OVF;
+ omap3_gptimer_writel(timer, OMAP3_GPT_TIER, val);
+ }
+
+ OMAP3_GPTIMER_UNLOCK(timer);
+
+ return(0);
+}
+
+/**
+ * omap3_gptimer_intr_filter_ack - acknowledges a timer interrupt
+ * @n: the number of the timer (first timer is number 1)
+ *
+ * This function should only be called from filter interrupt handler installed
+ * by calling the omap_gptimer_set_intr_filter() function.
+ *
+ * RETURNS:
+ * Nothing
+ */
+void
+omap3_gptimer_intr_filter_ack(unsigned int n)
+{
+ struct omap3_gptimer_softc *sc = g_omap3_gptimer_sc;
+ struct omap3_gptimer *timer;
+ uint32_t stat;
+
+ /* Get a pointer to the individual timer struct */
+ timer = &sc->sc_timers[n-1];
+
+ OMAP3_GPTIMER_LOCK(timer);
+
+ /* Read the interrupt status flag and clear it */
+ /* Read the status and it with the enable flag */
+ stat = omap3_gptimer_readl(timer, OMAP3_GPT_TISR);
+ stat &= omap3_gptimer_readl(timer, OMAP3_GPT_TIER);
+
+ /* Clear the status flag */
+ omap3_gptimer_writel(timer, OMAP3_GPT_TISR, stat);
+ OMAP3_GPTIMER_UNLOCK(timer);
+}
+
/**
@@ -416,7 +655,7 @@
DELAY(int usec)
{
int32_t counts;
- uint32_t first, last;
+ //uint32_t first, last;
if (omap3_gptimer_tc_tmr == NULL) {
for (; usec > 0; usec--)
@@ -430,9 +669,75 @@
static void
omap3_gptimer_intr(void *arg)
{
+ struct omap3_gptimer *timer = (struct omap3_gptimer *) arg;
+ void (*callback)(void *data);
+ void* callback_data;
+ uint32_t stat = 0x0000;
+
+ OMAP3_GPTIMER_LOCK(timer);
+
+ /* Read the interrupt status flag and clear it */
+ if (timer->profile == OMAP_GPTIMER_PROFILE_OMAP3) {
+
+ /* Read the status and it with the enable flag */
+ stat = omap3_gptimer_readl(timer, OMAP3_GPT_TISR);
+ stat &= omap3_gptimer_readl(timer, OMAP3_GPT_TIER);
+
+ /* Clear the status flag */
+ omap3_gptimer_writel(timer, OMAP3_GPT_TISR, stat);
+ }
+
+ /* Store the callback details before releasing the lock */
+ callback = timer->callback;
+ callback_data = timer->callback_data;
+
+ OMAP3_GPTIMER_UNLOCK(timer);
+
+ /* Check if an actual overflow interrupt */
+ if ((stat & OVF) && (callback != NULL))
+ callback(timer->callback_data);
+}
+
+/**
+ * omap3_clk_intr - interrupt handler for the tick timer (GPTIMER10)
+ * @arg: the trapframe, needed for the hardclock system function.
+ *
+ * This interrupt is triggered every hz times a second. It's role is basically
+ * to just clear the interrupt status and set it up for triggering again, plus
+ * tell the system a tick timer has gone off by calling the hardclock()
+ * function from the kernel API.
+ *
+ * RETURNS:
+ * Always returns FILTER_HANDLED.
+ */
+static int
+omap3_timer_tick_intr(void *arg)
+{
+ struct trapframe *frame = arg;
+#if defined(OMAP3_HEARTBEAT_GPIO)
+ static int heartbeat_cnt = 0;
+#endif
+
+ /* Acknowledge the interrupt */
+ omap3_gptimer_intr_filter_ack(TICKTIMER_GPTIMER);
+
+ /* Heartbeat */
+#if defined(OMAP3_HEARTBEAT_GPIO)
+ if (heartbeat_cnt++ >= (hz/2)) {
+ //printf("[BRG] ** tick **\n");
+ gpio_pin_toggle(OMAP3_HEARTBEAT_GPIO);
+ heartbeat_cnt = 0;
+ }
+#endif
+ /* Do what we came here for */
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+
+ /* Indicate we've handed the interrupt */
+ return (FILTER_HANDLED);
}
+
static int
omap3_gptimer_probe(device_t dev)
{
@@ -477,7 +782,7 @@
RF_ACTIVE | RF_SHAREABLE);
// I decided to delete support for OMAP4 timers from the original code - aleek
- rev = omap_gptimer_readl(timer, OMAP_GPT_TIDR);
+ rev = omap3_gptimer_readl(timer, OMAP3_GPT_TIDR);
switch (rev) {
case 0x00000013: /* OMAP3 without 1ms generation */
case 0x00000015:
@@ -502,14 +807,14 @@
timer->source = (GPTIMER1_CLK + n);
/* Finally mark the timer as available */
- timer->flags = OMAP_GPTIMER_AVAILABLE_FLAG;
+ timer->flags = OMAP3_GPTIMER_AVAILABLE_FLAG;
}
/* Store the number of timers installed */
sc->sc_num_timers = n;
/* Store the timer structure globally - this driver should never be unloaded */
- g_omap_gptimer_sc = sc;
+ g_omap3_gptimer_sc = sc;
/* setup GPTIMER10 for system ticks, and GPTIMER11 for general purpose counter */
@@ -519,17 +824,17 @@
tick = 1000000 / hz;
/* Next setup one of the timers to be the system tick timer */
- if (omap3_gptimer_activate(TICKTIMER_GPTIMER, OMAP_GPTIMER_PERIODIC_FLAG,
+ if (omap3_gptimer_activate(TICKTIMER_GPTIMER, OMAP3_GPTIMER_PERIODIC_FLAG,
tick, NULL, NULL)) {
panic("Error: failed to activate system tick timer\n");
}
/* Setup an interrupt filter for the timer */
- if (omap_gptimer_set_intr_filter(TICKTIMER_GPTIMER, omap3_timer_tick_intr))
+ if (omap3_gptimer_set_intr_filter(TICKTIMER_GPTIMER, omap3_timer_tick_intr))
panic("Error: failed to start system tick timer\n");
/* Lastly start the tick timer */
- if (omap_gptimer_start(TICKTIMER_GPTIMER))
+ if (omap3_gptimer_start(TICKTIMER_GPTIMER))
panic("Error: failed to start system tick timer\n");
omap3_gptimer_get_freq(TICKTIMER_GPTIMER, &timer_freq);
@@ -538,42 +843,41 @@
/* Setup another timer to be the timecounter */
- if (omap3_gptimer_activate(TIMECOUNT_GPTIMER, OMAP_GPTIMER_PERIODIC_FLAG, 0,
+ if (omap3_gptimer_activate(TIMECOUNT_GPTIMER, OMAP3_GPTIMER_PERIODIC_FLAG, 0,
NULL, NULL)) {
printf("Error: failed to activate system tick timer\n");
- } else if (omap_gptimer_start(TIMECOUNT_GPTIMER)) {
+ } else if (omap3_gptimer_start(TIMECOUNT_GPTIMER)) {
printf("Error: failed to start system tick timer\n");
}
/* Save the system clock speed */
omap3_gptimer_get_freq(TIMECOUNT_GPTIMER, &timer_freq);
- g_omap3_timecounter.tc_frequency = timer_freq;
+ omap3_gptimer_tc.tc_frequency = timer_freq;
/* Setup the time counter */
- tc_init(&g_omap3_timecounter);
+ tc_init(&omap3_gptimer_tc);
/* Calibrate the delay loop */
- omap3_calibrate_delay_loop(&g_omap3_timecounter);
+ omap3_calibrate_delay_loop(&omap3_gptimer_tc);
/* Restore interrupt state */
restore_interrupts(oldirqstate);
}
-static device_method_t g_omap_gptimer_methods[] = {
- DEVMETHOD(device_probe, omap_gptimer_probe),
- DEVMETHOD(device_attach, omap_gptimer_attach),
+static device_method_t g_omap3_gptimer_methods[] = {
+ DEVMETHOD(device_probe, omap3_gptimer_probe),
+ DEVMETHOD(device_attach, omap3_gptimer_attach),
{0, 0},
};
-static driver_t g_omap_gptimer_driver = {
- "omap_gptimer",
- g_omap_gptimer_methods,
- sizeof(struct omap_gptimer_softc),
+static driver_t g_omap3_gptimer_driver = {
+ "omap3_gptimer",
+ g_omap3_gptimer_methods,
+ sizeof(struct omap3_gptimer_softc),
};
-static devclass_t g_omap_gptimer_devclass;
+static devclass_t g_omap3_gptimer_devclass;
-DRIVER_MODULE(omap_gptimer, omap, g_omap_gptimer_driver, g_omap_gptimer_devclass, 0, 0);
-MODULE_DEPEND(omap_gptimer, ti_prcm, 1, 1, 1);
+DRIVER_MODULE(omap3_gptimer, omap, g_omap3_gptimer_driver, g_omap3_gptimer_devclass, 0, 0);
+MODULE_DEPEND(omap3_gptimer, ti_prcm, 1, 1, 1);
-}
Modified: soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h
==============================================================================
--- soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h Wed Jun 13 14:20:15 2012 (r237609)
+++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_gptimer.h Wed Jun 13 14:38:54 2012 (r237610)
@@ -12,23 +12,23 @@
#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
+#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)
@@ -43,14 +43,30 @@
#define TCLR_AR (0x1 << 1)
#define TCLR_ST (0x1 << 0)
+/* The interrupt/status bits used in the timer registers. */
+#define TCAR (0x1 << 2)
+#define OVF (0x1 << 1)
+#define MAT (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
+#define OMAP3_GPTIMER_32KCLK_FLAG 0x00000100
+/* Indicates if the timer should be periodic, if not specified the timer is
+ * one-shot and you have to call omap_timer_start() to restart the timer.
+ */
+#define OMAP3_GPTIMER_PERIODIC_FLAG 0x00000001
-/**
+#define OMAP_GPTIMER_PROFILE_UNKNOWN -1
+#define OMAP_GPTIMER_PROFILE_OMAP3 3
+
+// XXX @todo fix it, move somewhere
+#define OMAP3_HEARTBEAT_GPIO 150
+
+
+/*
* Macros for driver mutex locking
*/
#define OMAP3_GPTIMER_LOCK(_tmr) mtx_lock(&(_tmr)->mtx)
@@ -58,7 +74,7 @@
#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 {
@@ -66,8 +82,8 @@
/* Flags indicating current and configured status */
unsigned int flags;
-#define OMAP_GPTIMER_AVAILABLE_FLAG 0x01000000
-#define OMAP_GPTIMER_ACTIVATED_FLAG 0x02000000
+#define OMAP3_GPTIMER_AVAILABLE_FLAG 0x01000000
+#define OMAP3_GPTIMER_ACTIVATED_FLAG 0x02000000
/* Lock taken when configuring the registers */
struct mtx mtx;
@@ -95,7 +111,7 @@
/**
* Timer driver context, allocated and stored globally, this driver is not
- * intended to ever be unloaded (see g_omap_gptimer_sc).
+ * intended to ever be unloaded (see g_omap3_gptimer_sc).
*
*/
struct omap3_gptimer_softc {
@@ -106,6 +122,8 @@
};
+void
+omap3_gptimer_intr_filter_ack(unsigned int n);
static unsigned
omap3_gptimer_tc_get_timecount(struct timecounter *tc);
@@ -118,17 +136,33 @@
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,
+omap3_gptimer_activate(unsigned int n, unsigned int flags, unsigned int time_us,
void (*callback)(void *data), void *data);
+int
+omap3_gptimer_start(unsigned int n);
+
+int
+omap3_gptimer_stop(unsigned int n);
+
+int
+omap3_gptimer_get_freq(unsigned int n, uint32_t *freq);
+
+static int
+omap3_calibrate_delay_loop(struct timecounter *tc);
+
+int
+omap3_gptimer_set_intr_filter(unsigned int n, driver_filter_t filter);
+
static void
omap3_gptimer_intr(void *arg);
+static int
+omap3_timer_tick_intr(void *arg);
static int
omap3_gptimer_probe(device_t dev);
-
static int
omap3_gptimer_attach(device_t dev);
Modified: soc2012/aleek/beaglexm-armv6/sys/boot/fdt/dts/beagleboardxm.dts
==============================================================================
--- soc2012/aleek/beaglexm-armv6/sys/boot/fdt/dts/beagleboardxm.dts Wed Jun 13 14:20:15 2012 (r237609)
+++ soc2012/aleek/beaglexm-armv6/sys/boot/fdt/dts/beagleboardxm.dts Wed Jun 13 14:38:54 2012 (r237610)
@@ -59,6 +59,20 @@
reg = < 0x48200000 0x1000 >;
};
+ GPIO: gpio {
+ #gpio-cells = <3>;
+ compatible = "ti,gpio";
+ gpio-controller;
+ reg =< 0x48310000 0x1000
+ 0x49050000 0x1000
+ 0x49052000 0x1000
+ 0x49054000 0x1000
+ 0x49056000 0x1000
+ 0x49058000 0x1000 >;
+ interrupts = < 29 30 31 32 33 34 >;
+ interrupt-parent = <&AINTC>;
+ };
+
dmtimers at 44E05000 {
compatible = "ti,am37x-dmtimer";
#address-cells = <1>;
More information about the svn-soc-all
mailing list