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