socsvn commit: r240447 - in soc2012/aleek/beaglexm-armv6/sys/arm:
conf ti/am37x ti/omap3
aleek at FreeBSD.org
aleek at FreeBSD.org
Thu Aug 16 20:55:23 UTC 2012
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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/pcb.h>
+#include <machine/machdep.h>
+#include <machine/undefined.h>
+#include <machine/pte.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <sys/kdb.h>
+#include <arm/include/stdarg.h>
+
+#include <arm/ti/omap3/omap3_early_uart.h>
+
+
+
+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 <aleek at FreeBSD.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#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/gpio.h>
+#include <sys/mutex.h>
+#include <sys/timeet.h>
+#include <sys/timetc.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 <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/omap3/omap3_gptimer.h>
+
+#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 ***
More information about the svn-soc-all
mailing list