From owner-svn-soc-all@FreeBSD.ORG Wed Jun 13 14:38:57 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id 08C0F106564A for ; Wed, 13 Jun 2012 14:38:55 +0000 (UTC) (envelope-from aleek@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Wed, 13 Jun 2012 14:38:55 +0000 Date: Wed, 13 Jun 2012 14:38:55 +0000 From: aleek@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120613143855.08C0F106564A@hub.freebsd.org> Cc: Subject: socsvn commit: r237610 - in soc2012/aleek/beaglexm-armv6/sys: arm/ti/am37x boot/fdt/dts X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Jun 2012 14:38:57 -0000 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 #include #include +#include "sys/gpio.h"" #include #include @@ -56,8 +57,11 @@ #include + 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@44E05000 { compatible = "ti,am37x-dmtimer"; #address-cells = <1>;