From owner-svn-soc-all@FreeBSD.ORG Thu Aug 16 20:55:23 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 189451065675 for ; Thu, 16 Aug 2012 20:55:21 +0000 (UTC) (envelope-from aleek@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Thu, 16 Aug 2012 20:55:21 +0000 Date: Thu, 16 Aug 2012 20:55:21 +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: <20120816205521.189451065675@hub.freebsd.org> Cc: Subject: socsvn commit: r240447 - in soc2012/aleek/beaglexm-armv6/sys/arm: conf ti/am37x ti/omap3 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: Thu, 16 Aug 2012 20:55:23 -0000 Author: aleek Date: Thu Aug 16 20:55:18 2012 New Revision: 240447 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=240447 Log: I decided to get rid of the 'am37x' thing, since AM3730 is compatible with omap3 - linux kernel source is the same for both. So I moved all the code to omap3 folder and updated the files Added: soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.beagleboardxm soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_early_uart.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_early_uart.h soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_gptimer.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_gptimer.h soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_gptimer_generic.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_prcm.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_scm_padconf.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/std.beagleboardxm Deleted: soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_dmtimer.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_early_uart.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_early_uart.h 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/arm/ti/am37x/am37x_gptimer_tc.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_pmic.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_prcm.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_reg.h soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/am37x_scm_padconf.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/files.am37x soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/files.beagleboardxm soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/std.am37x soc2012/aleek/beaglexm-armv6/sys/arm/ti/am37x/std.beagleboardxm soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_intr.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_timer.c soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3var.h Modified: soc2012/aleek/beaglexm-armv6/sys/arm/conf/BEAGLEBOARD-XM soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.omap3 soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/std.omap3 Modified: soc2012/aleek/beaglexm-armv6/sys/arm/conf/BEAGLEBOARD-XM ============================================================================== --- soc2012/aleek/beaglexm-armv6/sys/arm/conf/BEAGLEBOARD-XM Thu Aug 16 20:18:10 2012 (r240446) +++ soc2012/aleek/beaglexm-armv6/sys/arm/conf/BEAGLEBOARD-XM Thu Aug 16 20:55:18 2012 (r240447) @@ -20,7 +20,7 @@ ident BEAGLEBOARD-XM -include "../ti/am37x/std.beagleboardxm" +include "../ti/omap3/std.beagleboardxm" makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" Added: soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.beagleboardxm ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.beagleboardxm Thu Aug 16 20:55:18 2012 (r240447) @@ -0,0 +1,5 @@ +#$FreeBSD$ + +arm/ti/twl/twl.c optional twl +arm/ti/twl/twl_vreg.c optional twl twl_vreg +arm/ti/twl/twl_clks.c optional twl twl_clks Modified: soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.omap3 ============================================================================== --- soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.omap3 Thu Aug 16 20:18:10 2012 (r240446) +++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/files.omap3 Thu Aug 16 20:55:18 2012 (r240447) @@ -1,5 +1,10 @@ #$FreeBSD$ -arm/ti/omap3/omap3_intr.c standard -arm/ti/omap3/omap35x.c standard -arm/ti/omap3/omap3_prcm_clks.c standard +arm/ti/aintc.c standard +arm/ti/omap3/omap3_prcm.c standard +arm/ti/omap3/omap3_gptimer.c standard +arm/ti/omap3/omap3_scm_padconf.c standard +arm/ti/ti_sdma.c standard +arm/ti/omap3/omap3_early_uart.c standard +arm/ti/ti_mmchs.c optional mmc +arm/ti/usb/omap_ehci.c optional usb Added: soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_early_uart.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_early_uart.c Thu Aug 16 20:55:18 2012 (r240447) @@ -0,0 +1,200 @@ +/*- + * Copyright (c) 2009 Guillaume Ballet + * Copyright (c) 2012 Aleksander Dutkowski + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Debugging functions for early uart for omap3530 and omap3 TI SoC's + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + + +void +arm_early_putc( char c ) +{ + volatile uint32_t *uart = (volatile uint32_t *)0xe9020000; + volatile uint32_t *uart_lsr = (volatile uint32_t *)0xe9020014; + + while ((*uart_lsr & 0x20) == 0); + *uart = c; + + if( c == '\n' ) + { + while ((*uart_lsr & 0x20) == 0); + *uart = '\r'; + } +} + +void +arm_early_puts(unsigned char *str) +{ + do { + arm_early_putc(*str); + } while (*++str != '\0'); +} + +void +eprintf(const char *fmt,...) +{ + va_list ap; + const char *hex = "0123456789abcdef"; + char buf[10]; + char *s; + unsigned u; + int c; + + va_start(ap, fmt); + while ((c = *fmt++)) { + if (c == '%') { + c = *fmt++; + switch (c) { + case 'c': + arm_early_putc(va_arg(ap, int)); + continue; + case 's': + for (s = va_arg(ap, char *); *s; s++) + arm_early_putc(*s); + continue; + case 'd': /* A lie, always prints unsigned */ + case 'u': + u = va_arg(ap, unsigned); + s = buf; + do + *s++ = '0' + u % 10U; + while (u /= 10U); + dumpbuf:; + while (--s >= buf) + arm_early_putc(*s); + continue; + case 'x': + u = va_arg(ap, unsigned); + s = buf; + do + *s++ = hex[u & 0xfu]; + while (u >>= 4); + goto dumpbuf; + } + } + arm_early_putc(c); + } + va_end(ap); + + return; +} + +void +dump_l2pagetable(uint32_t pta, uint32_t l1) +{ + int i; + volatile uint32_t *pt = (volatile uint32_t*)pta; + + for (i=0; i<256;i++) { + switch (pt[i] & 0x3) { + case 1: + eprintf("0x%x -> 0x%x 64K ",(i<<12) | l1, + pt[i]&0xFFFF0000); + eprintf("l2pt[0x%x]=0x%x ",i, pt[i]); + eprintf("s=%u ", (pt[i]>>10) &0x1); + eprintf("apx=%u ", (pt[i]>> 9) &0x1); + eprintf("tex=%u ", (pt[i]>>12) &0x7); + eprintf("ap=%u ", (pt[i]>> 4) &0x3); + eprintf("c=%u ", (pt[i]>> 3) &0x1); + eprintf("b=%u\n", (pt[i]>> 2) &0x1); + break; + case 2: + case 3: + eprintf("0x%x -> 0x%x 4K ",(i<<12) | l1, + pt[i]&0xFFFFF000); + eprintf("l2pt[0x%x]=0x%x ",i, pt[i]); + eprintf("s=%u ", (pt[i]>>10) &0x1); + eprintf("apx=%u ", (pt[i]>> 9) &0x1); + eprintf("tex=%u ", (pt[i]>> 6) &0x7); + eprintf("ap=%u ", (pt[i]>> 4) &0x3); + eprintf("c=%u ", (pt[i]>> 3) &0x1); + eprintf("b=%u\n", (pt[i]>> 2) &0x1); + break; + } + } +} + +void +dump_l1pagetable(uint32_t pta) +{ + int i; + eprintf("L1 pagetable starts at 0x%x\n",pta); + volatile uint32_t *pt = (volatile uint32_t*)pta; + for (i=0; i<4096;i++) { + switch (pt[i] & 0x3) { + case 1: + eprintf("0x%x -> L2 ",i<<20); + eprintf("l1pt[0x%x]=0x%x ",i, pt[i]); + eprintf("l2desc=0x%x ",pt[i] & 0xFFFFFC00); + eprintf("p=%u ",(pt[i]>>9) &0x1); + eprintf("domain=0x%x\n",(pt[i]>>5) &0xF); + dump_l2pagetable(pt[i] & 0xFFFFFC00, i<<20); + break; + case 2: + if (pt[i] &0x40000) { + eprintf("0x%x -> 0x%x 16M ",i<<20, pt[i] & 0xFF000000); + eprintf("l1pt[0x%x]=0x%x ",i, pt[i]); + eprintf("base=0x%x ", ((pt[i]>>24))); + } else { + eprintf("0x%x -> 0x%x 1M ",i<<20, pt[i] & 0xFFF00000); + eprintf("l1pt[0x%x]=0x%x ",i, pt[i]); + eprintf("base=0x%x ", (pt[i]>>20)); + } + eprintf("nG=%u ", (pt[i]>>17) &0x1); + eprintf("s=%u ", (pt[i]>>16) &0x1); + eprintf("apx=%u ", (pt[i]>>15) &0x1); + eprintf("tex=%u ", (pt[i]>>12) &0x7); + eprintf("ap=%u ", (pt[i]>>10) &0x3); + eprintf("p=%u ", (pt[i]>> 9) &0x1); + eprintf("domain=0x%x ", (pt[i]>> 5) &0xF); + eprintf("xn=%u ", (pt[i]>> 4) &0x1); + eprintf("c=%u ", (pt[i]>> 3) &0x1); + eprintf("b=%u\n", (pt[i]>> 2) &0x1); + break; + case 3: + eprintf("pt[0x%x] 0x%x RESV\n",i, pt[i]); + break; + } + } +} Added: soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_early_uart.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_early_uart.h Thu Aug 16 20:55:18 2012 (r240447) @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2009 Guillaume Ballet + * Copyright (c) 2012 Aleksander Dutkowski + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef AM37X_EARLY_UART_INC +#define AM37X_EARLY_UART_INC + +void +arm_early_putc( char c ); + +void +arm_early_puts(unsigned char *str); + +void +eprintf(const char *fmt,...); + +void +dump_l1pagetable(uint32_t pta); + +void +dump_l2pagetable(uint32_t pta, uint32_t l1); +#endif /* ----- #ifndef AM37X_EARLY_UART_INC ----- */ Added: soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_gptimer.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/aleek/beaglexm-armv6/sys/arm/ti/omap3/omap3_gptimer.c Thu Aug 16 20:55:18 2012 (r240447) @@ -0,0 +1,927 @@ + +/*- + * Copyright (c) 2012 Aleksander Dutkowski + * All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Based on gptimer driver by Ben Gray + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define gptimer_read_4(reg) bus_read_4( sc->mem_res, reg ) +#define gptimer_write_4(reg, val) bus_write_4( sc->mem_res, reg, val ) + +static struct omap3_gptimer_softc *g_omap3_gptimer_sc_tc = NULL; +static struct omap3_gptimer_softc *g_omap3_gptimer_sc_et = NULL; + +static unsigned int delay_loops_per_us = 100; + +/** + * Struct used by tc_init(), to init the timecounter + */ +static struct timecounter omap3_gptimer_tc = { + /* Name of the timecounter. */ + .tc_name = "OMAP3 Timecounter", + /* + * This function reads the counter. It is not required to + * mask any unimplemented bits out, as long as they are + * constant. + */ + .tc_get_timecount = omap3_gptimer_tc_get_timecount, + .tc_poll_pps = NULL, + /* This mask should mask off any unimplemented bits. */ + .tc_counter_mask = ~0u, + /* Frequency of the counter in Hz. */ + .tc_frequency = 0, + /* + * Used to determine if this timecounter is better than + * another timecounter higher means better. Negative + * means "only use at explicit request". + */ + .tc_quality = 1000, +}; + +static struct eventtimer omap3_gptimer_et; + +#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 omap3_gptimer_softc *sc, 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); + for (int usec=10240; usec > 0; usec--) + //for (int32_t counts = 200; counts > 0; counts--) + /* Prevent gcc from optimizing out the loop */ + cpufunc_nullop(); + + 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); + + device_printf( sc->sc_dev, "Delay loop calibrated to %u cycles\n", delay_loops_per_us); + + return (0); +} + + +static unsigned +omap3_gptimer_tc_get_timecount(struct timecounter *tc) +{ + uint32_t count; + omap3_gptimer_read_count(g_omap3_gptimer_sc_tc, &count); + return(count); + +} + +/** + * omap3_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(struct omap3_gptimer_softc *sc, uint32_t *cnt) +{ + int ret; + + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + + /* Get a pointer to the individual sc struct */ + + OMAP3_GPTIMER_LOCK(sc); + + if (!(sc->flags & OMAP3_GPTIMER_ACTIVATED_FLAG)) { + ret = EINVAL; + } else { + *cnt = gptimer_read_4(OMAP3_GPT_TCRR); + ret = 0; + } + + OMAP3_GPTIMER_UNLOCK(sc); + + return (ret); +} + + +/** + * 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 + * + * + * + * RETURNS: + * Returns 0 on success, otherwise an error code + */ +int +omap3_gptimer_write_count(struct omap3_gptimer_softc *sc, uint32_t cnt) +{ + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + + if (!(sc->flags & OMAP3_GPTIMER_ACTIVATED_FLAG)) + return (EINVAL); + + OMAP3_GPTIMER_LOCK(sc); + + gptimer_write_4(OMAP3_GPT_TCRR, cnt); + + OMAP3_GPTIMER_UNLOCK(sc); + + return (0); +} + + + +/** + * 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(struct omap3_gptimer_softc *sc, uint32_t *freq) +{ + 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 (freq == NULL) + return (EINVAL); + + /* Get a pointer to the individual timer struct */ + if (!(sc->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(sc->source, &src_freq)) != 0) + return (rc); + + + OMAP3_GPTIMER_LOCK(sc); + + /* Determine if the pre-scalar is enabled and if so the prescaler value */ + tclr = gptimer_read_4(OMAP3_GPT_TCLR); + if (tclr & TCLR_PRE) + prescaler = 1UL << (((tclr & TCLR_PTV_MASK) >> 2) + 1); + else + prescaler = 1; + + /* Get the reload count */ + tldr = gptimer_read_4(OMAP3_GPT_TLDR); + + OMAP3_GPTIMER_UNLOCK(sc); + + + /* 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); +} + + + +/** + * 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 + * @callback: if defined this function will be called when the timer overflows + * @data: data value to pass to the callback + * + * + * RETURNS: + * Returns 0 on success, otherwise an error code + */ +int +omap3_gptimer_activate(struct omap3_gptimer_softc *sc, unsigned int flags, unsigned int time_us, + void (*callback)(void *data), void *data) +{ + uint32_t val; + uint64_t tickcount; + unsigned int freq; + uint64_t freq64; + uint32_t prescaler; + uint32_t startcount; + + + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + + /* Sanity check the timer is availabe and not activated */ + if (!(sc->flags & OMAP3_GPTIMER_AVAILABLE_FLAG)) { + device_printf(sc->sc_dev, "Error: timer not available\n"); + return (EINVAL); + } + if (sc->flags & OMAP3_GPTIMER_ACTIVATED_FLAG) { + device_printf(sc->sc_dev, "Error: timer already activated\n"); + return (EINVAL); + } + + /* Set up system clock information */ + if (ti_prcm_clk_valid(sc->source) != 0) { + device_printf(sc->sc_dev, "Error: failed to find source clock\n"); + return (EINVAL); + } + + OMAP3_GPTIMER_LOCK(sc); + + /* Enable the functional and interface clock */ + if (flags & OMAP3_GPTIMER_32KCLK_FLAG) + ti_prcm_clk_set_source(sc->source, F32KHZ_CLK); + else + ti_prcm_clk_set_source(sc->source, SYSCLK_CLK); + + ti_prcm_clk_enable(sc->source); + + + /* Store the flags in the timer context */ + sc->flags &= 0xFF000000; + sc->flags |= (0x00FFFFFF & flags); + + + /* Reset the timer and poll on the reset complete flag */ + if (sc->profile == OMAP_GPTIMER_PROFILE_OMAP3) { + gptimer_write_4(OMAP3_GPT_TIOCP_CFG, 0x2); + /* TODO: add a timeout */ + while ((gptimer_read_4(OMAP3_GPT_TISTAT) & 0x01) == 0x00) + continue; + + /* Clear the interrupt status */ + gptimer_write_4(OMAP3_GPT_TISR, 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 + */ + ti_prcm_clk_get_source_freq(sc->source, &freq); + freq64 = freq; + + /* Calculate the period of the timer, 64 bit calculations used to + * prevent rollover. + */ + tickcount = (freq64 * (uint64_t)time_us) / 1000000; + + /* Must have a count of at least 1 */ + if (tickcount == 0) + tickcount = 1; + + /* If the number is too large then see if by enabling the prescaler it + * will fit, otherwise just set the max count we can do. + */ + if (tickcount > 0xFFFFFFFFULL) { + + /* Try and find a prescaler that will match */ + for (prescaler = 0; prescaler < 7; prescaler++) { + if (tickcount < (0x1ULL << (32 + prescaler))) { + break; + } + } + + /* Adjust the count and apply the prescaler */ + tickcount >>= (prescaler + 1); + + val = gptimer_read_4(OMAP3_GPT_TCLR); + val &= ~TCLR_PTV_MASK; + val |= TCLR_PRE | (prescaler << 2); + gptimer_write_4(OMAP3_GPT_TCLR, val); + } + + /* Calculate the start value */ + startcount = 0xFFFFFFFFUL - (uint32_t)(tickcount & 0xFFFFFFFFUL); + + device_printf( sc->sc_dev, "%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 */ + gptimer_write_4(OMAP3_GPT_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 & OMAP3_GPTIMER_PERIODIC_FLAG) { + /* Enable auto reload */ + val = gptimer_read_4(OMAP3_GPT_TCLR); + val |= TCLR_AR; + gptimer_write_4(OMAP3_GPT_TCLR, val); + + /* Set the reload value */ + gptimer_write_4(OMAP3_GPT_TLDR, startcount); + } + + /* If a callback function has been supplied setup a overflow interrupt */ + if (callback != NULL) { + + /* Save the callback function and the data for it */ + sc->callback = callback; + sc->callback_data = data; + + /* Activate the interrupt */ + if (bus_setup_intr(sc->sc_dev, sc->irq_res, + INTR_TYPE_MISC | INTR_MPSAFE, NULL, omap3_gptimer_intr, + (void*)sc, &sc->irq_h)) { + device_printf(sc->sc_dev, "Error: failed to activate interrupt\n"); + } + + /* Enable the overflow interrupts. */ + if (sc->profile == OMAP_GPTIMER_PROFILE_OMAP3) { + val = gptimer_read_4(OMAP3_GPT_TIER); + val |= OVF; + gptimer_write_4(OMAP3_GPT_TIER, val); + } + } + + /* Finally set the activated flag */ + sc->flags |= OMAP3_GPTIMER_ACTIVATED_FLAG; + + OMAP3_GPTIMER_UNLOCK(sc); + 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_et(struct eventtimer *et, struct bintime *first, struct bintime *period) +{ + struct omap3_gptimer_softc *sc = (struct omap3_gptimer_softc *)et->et_priv; + uint32_t val; + + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + if (!(sc->flags & OMAP3_GPTIMER_ACTIVATED_FLAG)) + return (EINVAL); + + OMAP3_GPTIMER_LOCK(sc); + + val = gptimer_read_4(OMAP3_GPT_TCLR); + val |= TCLR_ST; + gptimer_write_4(OMAP3_GPT_TCLR, val); + + OMAP3_GPTIMER_UNLOCK(sc); + + return 0; +} + +int +omap3_gptimer_start(struct omap3_gptimer_softc *sc) +{ + uint32_t val; + + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + if (!(sc->flags & OMAP3_GPTIMER_ACTIVATED_FLAG)) + return (EINVAL); + + OMAP3_GPTIMER_LOCK(sc); + + val = gptimer_read_4(OMAP3_GPT_TCLR); + val |= TCLR_ST; + gptimer_write_4(OMAP3_GPT_TCLR, val); + + OMAP3_GPTIMER_UNLOCK(sc); + + 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(struct eventtimer *et) +{ + struct omap3_gptimer_softc *sc = (struct omap3_gptimer_softc *)et->et_priv; + uint32_t val; + + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + if (!(sc->flags & OMAP3_GPTIMER_ACTIVATED_FLAG)) + return (EINVAL); + + OMAP3_GPTIMER_LOCK(sc); + + val = gptimer_read_4(OMAP3_GPT_TCLR); + val &= ~TCLR_ST; + gptimer_write_4(OMAP3_GPT_TCLR, val); + + OMAP3_GPTIMER_UNLOCK(sc); + + 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(struct omap3_gptimer_softc *sc, driver_filter_t filter) +{ + uint32_t val; + + /* Sanity checks */ + if (sc == NULL) + return (ENOMEM); + + OMAP3_GPTIMER_LOCK(sc); + + /* If a callback is already installed this won't work */ + if (sc->callback != NULL) { + OMAP3_GPTIMER_UNLOCK(sc); + return(EINVAL); + } + + /* Sanity check the timer is already activated and periodic type */ + if ((sc->flags & (OMAP3_GPTIMER_ACTIVATED_FLAG | OMAP3_GPTIMER_PERIODIC_FLAG)) + != (OMAP3_GPTIMER_ACTIVATED_FLAG | OMAP3_GPTIMER_PERIODIC_FLAG)) { + OMAP3_GPTIMER_UNLOCK(sc); + return(EINVAL); + } + + + /* Attempt to activate the interrupt for the tick */ + if (bus_setup_intr(sc->sc_dev, sc->irq_res, INTR_TYPE_CLK, + filter, NULL, NULL, &sc->irq_h)) { + device_printf(sc->sc_dev, "Error: failed to activate interrupt\n"); + OMAP3_GPTIMER_UNLOCK(sc); + return(EINVAL); + } + + + /* Enable the overflow interrupts */ + if (sc->profile == OMAP_GPTIMER_PROFILE_OMAP3) { + val = gptimer_read_4(OMAP3_GPT_TIER); + val |= OVF; + gptimer_write_4(OMAP3_GPT_TIER, val); + } + + OMAP3_GPTIMER_UNLOCK(sc); + + 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(struct omap3_gptimer_softc *sc) +{ + uint32_t stat; + + OMAP3_GPTIMER_LOCK(sc); + + /* Read the interrupt status flag and clear it */ + /* Read the status and it with the enable flag */ + stat = gptimer_read_4(OMAP3_GPT_TISR); + stat &= gptimer_read_4(OMAP3_GPT_TIER); + + /* Clear the status flag */ + gptimer_write_4(OMAP3_GPT_TISR, stat); + OMAP3_GPTIMER_UNLOCK(sc); +} + + + +/** + * cpu_initclocks - function called by the system in init the tick clock/timer + * + * This is where both the timercount and system ticks timer are started. + * + * RETURNS: + * nothing + */ +void +cpu_initclocks(void) +{ + cpu_initclocks_bsp(); +} + +/** + * DELAY - Delay for at least N microseconds. + * @n: number of microseconds to delay by + * + * This function is called all over the kernel and is suppose to provide a + * consistent delay. It is a busy loop and blocks polling a timer when called. + * + * RETURNS: + * nothing + */ +void +DELAY(int usec) +{ + int32_t counts; + //uint32_t first, last; + + //if (g_omap3_gptimer_sc_tc == NULL) { + for (; usec > 0; usec--) + for (counts = 200; counts > 0; counts--) + /* Prevent gcc from optimizing out the loop */ + cpufunc_nullop(); + return; + //} +} + +static void +omap3_gptimer_intr(void *arg) +{ + struct omap3_gptimer_softc *sc = (struct omap3_gptimer_softc *)arg; + void (*callback)(void *data); + void* callback_data; + uint32_t stat = 0x0000; + + OMAP3_GPTIMER_LOCK(sc); + + /* Read the interrupt status flag and clear it */ + if (sc->profile == OMAP_GPTIMER_PROFILE_OMAP3) { + + /* Read the status and it with the enable flag */ + stat = gptimer_read_4(OMAP3_GPT_TISR); + stat &= gptimer_read_4(OMAP3_GPT_TIER); + + /* Clear the status flag */ + gptimer_write_4(OMAP3_GPT_TISR, stat); + } + + /* Store the callback details before releasing the lock */ + callback = sc->callback; + callback_data = sc->callback_data; + + OMAP3_GPTIMER_UNLOCK(sc); + + /* Check if an actual overflow interrupt */ + if ((stat & OVF) && (callback != NULL)) + callback(sc->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) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***