Module Name:    src
Committed By:   riastradh
Date:           Tue Dec 11 19:01:18 UTC 2012

Added Files:
        src/sys/arch/arm/omap: omap_dmtimer.c omap_dmtimerreg.h
            omap_dmtimervar.h

Log Message:
New driver for OMAP-style dual-mode timers, for both v1 and v2 cores.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/omap/omap_dmtimer.c \
    src/sys/arch/arm/omap/omap_dmtimerreg.h \
    src/sys/arch/arm/omap/omap_dmtimervar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/sys/arch/arm/omap/omap_dmtimer.c
diff -u /dev/null src/sys/arch/arm/omap/omap_dmtimer.c:1.1
--- /dev/null	Tue Dec 11 19:01:18 2012
+++ src/sys/arch/arm/omap/omap_dmtimer.c	Tue Dec 11 19:01:18 2012
@@ -0,0 +1,407 @@
+/*	$NetBSD: omap_dmtimer.c,v 1.1 2012/12/11 19:01:18 riastradh Exp $	*/
+
+/*
+ * TI OMAP Dual-mode timers
+ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_dmtimer.c,v 1.1 2012/12/11 19:01:18 riastradh Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/atomic.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/timetc.h>
+
+#include <machine/intr.h>
+
+#include <arm/omap/omap2_prcm.h>
+#include <arm/omap/omap_dmtimerreg.h>
+#include <arm/omap/omap_dmtimervar.h>
+
+typedef uint8_t dmt_reg_t;
+typedef uint16_t dmt_timer_reg_t;
+
+static unsigned int
+		dmt_tc_get_timecount(struct timecounter *);
+static int	dmt_hardintr(void *);
+static int	dmt_statintr(void *);
+static void	dmt_start_periodic_intr(struct omap_dmtimer_softc *, int,
+		    unsigned int, int (*)(void *));
+static void	dmt_set_periodic_intr_frequency(struct omap_dmtimer_softc *,
+		    unsigned int);
+static void	dmt_start_timecounter(struct omap_dmtimer_softc *);
+static unsigned int
+		dmt_get_timecount(struct omap_dmtimer_softc *);
+static void	dmt_start(struct omap_dmtimer_softc *, unsigned int);
+static void	dmt_reset(struct omap_dmtimer_softc *);
+static void	dmt_enable(struct omap_dmtimer_softc *);
+static void	dmt_intr_enable(struct omap_dmtimer_softc *, uint32_t);
+static void	dmt_intr_ack(struct omap_dmtimer_softc *, uint32_t);
+static uint32_t	dmt_timer_read_4(struct omap_dmtimer_softc *, dmt_timer_reg_t);
+static void	dmt_timer_write_4(struct omap_dmtimer_softc *, dmt_timer_reg_t,
+		    uint32_t);
+static void	dmt_timer_write_post_wait(struct omap_dmtimer_softc *,
+		    dmt_timer_reg_t);
+static uint32_t	dmt_read_4(struct omap_dmtimer_softc *, dmt_reg_t);
+static void	dmt_write_4(struct omap_dmtimer_softc *, dmt_reg_t, uint32_t);
+
+static struct omap_dmtimer_softc *hardclock_sc;
+static struct omap_dmtimer_softc *statclock_sc;
+static struct timecounter dmt_timecounter;
+
+void
+omap_dmtimer_attach_timecounter(struct omap_dmtimer_softc *sc)
+{
+
+	if (dmt_timecounter.tc_priv != NULL)
+		panic("omap dmtimer timecounter already initialized");
+
+	dmt_timecounter.tc_priv = sc;
+}
+
+static struct timecounter dmt_timecounter = {
+	.tc_get_timecount	= dmt_tc_get_timecount,
+	.tc_counter_mask	= 0xffffffff, /* XXXMAGIC Make sense?  */
+	.tc_frequency		= OMAP_SYSTEM_CLOCK_FREQ, /* XXXPOWER */
+	.tc_name		= "dmtimer", /* XXX Which one?  */
+	.tc_quality		= 100, /* XXXMAGIC?  */
+	.tc_priv		= NULL,
+};
+
+static unsigned int
+dmt_tc_get_timecount(struct timecounter *tc)
+{
+	struct omap_dmtimer_softc *sc = tc->tc_priv;
+
+	if (sc == NULL)
+		panic("uninitialized omap dmtimer timecounter");
+
+	return dmt_get_timecount(sc);
+}
+
+void
+omap_dmtimer_attach_hardclock(struct omap_dmtimer_softc *sc)
+{
+
+	if (hardclock_sc != NULL)
+		panic("%s: replacing hardclock %s", device_xname(sc->sc_dev),
+		    device_xname(hardclock_sc->sc_dev));
+	hardclock_sc = sc;
+}
+
+void
+omap_dmtimer_attach_statclock(struct omap_dmtimer_softc *sc)
+{
+
+	KASSERT(stathz != 0);
+	if (statclock_sc != NULL)
+		panic("%s: replacing statclock %s", device_xname(sc->sc_dev),
+		    device_xname(statclock_sc->sc_dev));
+	statclock_sc = sc;
+}
+
+void
+cpu_initclocks(void)
+{
+	struct omap_dmtimer_softc *timecounter_sc = dmt_timecounter.tc_priv;
+
+	if (hardclock_sc == NULL)
+		panic("omap dmtimer hardclock not initialized");
+	dmt_enable(hardclock_sc);
+	dmt_start_periodic_intr(hardclock_sc, IPL_CLOCK, hz, &dmt_hardintr);
+
+	if (timecounter_sc == NULL)
+		panic("omap dmtimer timecounter not initialized");
+	dmt_enable(statclock_sc);
+	dmt_start_periodic_intr(statclock_sc, IPL_HIGH, stathz, &dmt_statintr);
+
+	if (statclock_sc == NULL)
+		panic("omap dmtimer statclock not initialized");
+	dmt_enable(timecounter_sc);
+	dmt_start_timecounter(timecounter_sc);
+	tc_init(&dmt_timecounter);
+}
+
+void
+setstatclockrate(int rate)
+{
+	struct omap_dmtimer_softc *sc = statclock_sc;
+
+	if (rate < 0)
+		panic("I can't run the statistics clock backward!");
+
+	if (sc == NULL)
+		panic("There is no statclock timer!\n");
+
+	dmt_set_periodic_intr_frequency(sc, rate);
+}
+
+static int
+dmt_hardintr(void *frame)
+{
+	struct omap_dmtimer_softc *sc = hardclock_sc;
+
+	KASSERT(sc != NULL);
+	dmt_intr_ack(sc, OMAP_DMTIMER_INTR_ALL);
+	hardclock(frame);
+
+	return 1;
+}
+
+static int
+dmt_statintr(void *frame)
+{
+	struct omap_dmtimer_softc *sc = statclock_sc;
+
+	KASSERT(sc != NULL);
+	dmt_intr_ack(sc, OMAP_DMTIMER_INTR_ALL);
+	statclock(frame);
+
+	return 1;
+}
+
+static void
+dmt_start_periodic_intr(struct omap_dmtimer_softc *sc, int ipl,
+    unsigned int frequency, int (*func)(void *))
+{
+
+	dmt_reset(sc);
+	dmt_start(sc, frequency);
+	/*
+	 * Null argument means func gets the interrupt frame.  For
+	 * whatever reason it's not an option to pass an argument (such
+	 * as sc) and the interrupt frame both, which is why we have
+	 * the global hardclock_sc and statclock_sc.
+	 */
+	intr_establish(sc->sc_intr, ipl, IST_LEVEL, func, 0);
+	dmt_intr_enable(sc, OMAP_DMTIMER_INTR_OVERFLOW);
+}
+
+static void
+dmt_set_periodic_intr_frequency(struct omap_dmtimer_softc *sc,
+    unsigned int frequency)
+{
+
+	dmt_reset(sc);
+	dmt_start(sc, frequency);
+	dmt_intr_enable(sc, OMAP_DMTIMER_INTR_OVERFLOW);
+}
+
+static void
+dmt_start_timecounter(struct omap_dmtimer_softc *sc)
+{
+
+	/*
+	 * XXXPOWER On reset, the timer uses the system clock.  For
+	 * low-power operation, we can configure timers to use less
+	 * frequent clocks, but there's currently no abstraction for
+	 * doing this.
+	 */
+	dmt_reset(sc);
+	dmt_timer_write_4(sc, OMAP_DMTIMER_TIMER_LOAD, 0);
+	dmt_timer_write_4(sc, OMAP_DMTIMER_TIMER_COUNTER, 0);
+	dmt_timer_write_4(sc, OMAP_DMTIMER_TIMER_CTRL,
+	    (OMAP_DMTIMER_TIMER_CTRL_START |
+		OMAP_DMTIMER_TIMER_CTRL_AUTORELOAD));
+}
+
+static unsigned int
+dmt_get_timecount(struct omap_dmtimer_softc *sc)
+{
+
+	return dmt_timer_read_4(sc, OMAP_DMTIMER_TIMER_COUNTER);
+}
+
+static void
+dmt_start(struct omap_dmtimer_softc *sc, unsigned int frequency)
+{
+	uint32_t value;
+
+	/*
+	 * XXXPOWER Should do something clever with prescaling and
+	 * clock selection to save power.
+	 */
+
+	/*
+	 * XXX The dmtimer doesn't even necessarily run at the system
+	 * clock frequency by default.  On the AM335x, the system clock
+	 * frequency is 24 MHz, but dmtimer0 runs at 32 kHz.
+	 */
+	value = (0xffffffff - ((OMAP_SYSTEM_CLOCK_FREQ / frequency) - 1));
+
+	dmt_timer_write_4(sc, OMAP_DMTIMER_TIMER_LOAD, value);
+	dmt_timer_write_4(sc, OMAP_DMTIMER_TIMER_COUNTER, value);
+
+	dmt_timer_write_4(sc, OMAP_DMTIMER_TIMER_CTRL,
+	    (OMAP_DMTIMER_TIMER_CTRL_START |
+		OMAP_DMTIMER_TIMER_CTRL_AUTORELOAD));
+}
+
+static void
+dmt_reset(struct omap_dmtimer_softc *sc)
+{
+	uint32_t reset_mask;
+	unsigned int tries = 1000; /* XXXMAGIC */
+
+	if (sc->sc_version == 1)
+		reset_mask = OMAP_DMTIMER_V1_OCP_CFG_SOFTRESET_MASK;
+	else
+		reset_mask = OMAP_DMTIMER_V2_OCP_CFG_SOFTRESET_MASK;
+
+	dmt_write_4(sc, OMAP_DMTIMER_OCP_CFG, reset_mask);
+	while (dmt_read_4(sc, OMAP_DMTIMER_OCP_CFG) & reset_mask) {
+		if (--tries == 0)
+			panic("unable to reset dmtimer %p", sc);
+		DELAY(10);	/* XXXMAGIC */
+	}
+
+	/*
+	 * Posted mode is enabled on reset on the OMAP35x but disabled
+	 * on reset on the AM335x, so handle both cases.
+	 *
+	 * XXXPOWER Does enabling this reduce power consumption?
+	 */
+	sc->sc_posted =
+	    (0 != (dmt_read_4(sc, OMAP_DMTIMER_TIMER_SYNC_INT_CTRL)
+		& OMAP_DMTIMER_TIMER_SYNC_INT_CTRL_POSTED));
+}
+
+static void
+dmt_enable(struct omap_dmtimer_softc *sc)
+{
+
+	if (!sc->sc_enabled) {
+		prcm_module_enable(sc->sc_module);
+		sc->sc_enabled = 1;
+	}
+}
+
+static void
+dmt_intr_enable(struct omap_dmtimer_softc *sc, uint32_t intr)
+{
+
+	if (sc->sc_version == 1) {
+		dmt_write_4(sc, OMAP_DMTIMER_V1_INTR_ENABLE, intr);
+	} else {
+		dmt_write_4(sc, OMAP_DMTIMER_V2_INTR_ENABLE_CLEAR,
+		    (OMAP_DMTIMER_INTR_ALL &~ intr));
+		dmt_write_4(sc, OMAP_DMTIMER_V2_INTR_ENABLE_SET, intr);
+	}
+}
+
+static void
+dmt_intr_ack(struct omap_dmtimer_softc *sc, uint32_t intr)
+{
+
+	if (sc->sc_version == 1)
+		dmt_write_4(sc, OMAP_DMTIMER_V1_INTR_STATUS, intr);
+	else
+		dmt_write_4(sc, OMAP_DMTIMER_V2_INTR_STATUS, intr);
+}
+
+static uint32_t
+dmt_timer_read_4(struct omap_dmtimer_softc *sc, dmt_timer_reg_t reg)
+{
+	dmt_reg_t timer_base;
+
+	if (sc->sc_version == 1)
+		timer_base = OMAP_DMTIMER_V1_TIMER_REGS;
+	else
+		timer_base = OMAP_DMTIMER_V2_TIMER_REGS;
+
+	dmt_timer_write_post_wait(sc, reg);
+	return dmt_read_4(sc, (timer_base + reg));
+}
+
+static void
+dmt_timer_write_4(struct omap_dmtimer_softc *sc, dmt_timer_reg_t reg,
+    uint32_t value)
+{
+	dmt_reg_t timer_base;
+
+	if (sc->sc_version == 1)
+		timer_base = OMAP_DMTIMER_V1_TIMER_REGS;
+	else
+		timer_base = OMAP_DMTIMER_V2_TIMER_REGS;
+
+	dmt_timer_write_post_wait(sc, reg);
+	dmt_write_4(sc, (timer_base + reg), value);
+}
+
+static void
+dmt_timer_write_post_wait(struct omap_dmtimer_softc *sc, dmt_timer_reg_t reg)
+{
+	dmt_reg_t timer_base;
+
+	if (sc->sc_version == 1)
+		timer_base = OMAP_DMTIMER_V1_TIMER_REGS;
+	else
+		timer_base = OMAP_DMTIMER_V2_TIMER_REGS;
+
+	/*
+	 * Make sure we can read the TWPS (OMAP_DMTIMER_TIMER_WRITE_POST)
+	 * register with vanilla dmt_read_4.
+	 */
+	CTASSERT(OMAP_DMTIMER_TIMER_WRITE_POST ==
+	    OMAP_DMTIMER_REG_POSTED_INDEX(OMAP_DMTIMER_TIMER_WRITE_POST));
+
+	if (sc->sc_posted && OMAP_DMTIMER_REG_POSTED_P(reg)) {
+		unsigned int tries = 1000; /* XXXMAGIC */
+		const dmt_reg_t write_post_reg = (timer_base +
+		    OMAP_DMTIMER_TIMER_WRITE_POST);
+
+		while (dmt_read_4(sc, write_post_reg) &
+		    OMAP_DMTIMER_REG_POSTED_MASK(reg)) {
+			if (--tries == 0)
+				panic("dmtimer %p failed to complete write",
+				    sc);
+			DELAY(10);
+		}
+	}
+}
+
+static uint32_t
+dmt_read_4(struct omap_dmtimer_softc *sc, dmt_reg_t reg)
+{
+
+	return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
+}
+
+static void
+dmt_write_4(struct omap_dmtimer_softc *sc, dmt_reg_t reg, uint32_t value)
+{
+
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, value);
+}
Index: src/sys/arch/arm/omap/omap_dmtimerreg.h
diff -u /dev/null src/sys/arch/arm/omap/omap_dmtimerreg.h:1.1
--- /dev/null	Tue Dec 11 19:01:18 2012
+++ src/sys/arch/arm/omap/omap_dmtimerreg.h	Tue Dec 11 19:01:18 2012
@@ -0,0 +1,167 @@
+/*	$NetBSD: omap_dmtimerreg.h,v 1.1 2012/12/11 19:01:18 riastradh Exp $	*/
+
+/*
+ * TI OMAP Dual-mode timers: Registers
+ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * References: TI AM335x TRM, TI OMAP35x TRM.
+ */
+
+#ifndef _ARM_OMAP_OMAP_DMTIMERREG_H_
+#define _ARM_OMAP_OMAP_DMTIMERREG_H_
+
+#include <sys/cdefs.h>
+
+#define OMAP_DMTIMER_ID					0x00 /* TIDR */
+#define OMAP_DMTIMER_OCP_CFG				0x10 /* TOCP_CFG */
+
+#define   OMAP_DMTIMER_OCP_CFG_IDLEMODE_FORCE_IDLE	0
+#define   OMAP_DMTIMER_OCP_CFG_IDLEMODE_NO_IDLE		1
+#define   OMAP_DMTIMER_OCP_CFG_IDLEMODE_SMART_IDLE	2
+#define   OMAP_DMTIMER_OCP_CFG_IDLEMODE_RESERVED	3
+
+/*
+ * DM timer version 1
+ */
+
+#define   OMAP_DMTIMER_V1_ID_REVISION_MASK		__BITS(0, 7)
+#define   OMAP_DMTIMER_V1_ID_RESERVED_MASK		__BITS(8, 31)
+
+#define   OMAP_DMTIMER_V1_OCP_CFG_AUTOIDLE_MASK		__BITS(0, 0)
+#define   OMAP_DMTIMER_V1_OCP_CFG_SOFTRESET_MASK	__BITS(1, 1)
+#define   OMAP_DMTIMER_V1_OCP_CFG_WAKEUP_MASK		__BITS(2, 2)
+#define   OMAP_DMTIMER_V1_OCP_CFG_IDLEMODE_MASK		__BITS(3, 4)
+#define   OMAP_DMTIMER_V1_OCP_CFG_EMUFREE_MASK		__BITS(5, 5)
+#define   OMAP_DMTIMER_V1_OCP_CFG_RESERVED0_MASK	__BITS(6, 8)
+#define   OMAP_DMTIMER_V1_OCP_CFG_CLOCKACT_MASK		__BITS(9, 8)
+#define     OMAP_DMTIMER_V1_OCP_CFG_CLOCKACT_OFF	0
+#define     OMAP_DMTIMER_V1_OCP_CFG_CLOCKACT_FUN	1
+#define     OMAP_DMTIMER_V1_OCP_CFG_CLOCKACT_L4		2
+#define     OMAP_DMTIMER_V1_OCP_CFG_CLOCKACT_L4_FUN	3
+
+#define   OMAP_DMTIMER_INTR_MATCH			__BIT(0)
+#define   OMAP_DMTIMER_INTR_OVERFLOW			__BIT(1)
+#define   OMAP_DMTIMER_INTR_CAPTURE			__BIT(2)
+#define   OMAP_DMTIMER_INTR_ALL				0x7
+
+#define OMAP_DMTIMER_V1_STATUS				0x14 /* TISTAT */
+#define   OMAP_DMTIMER_V1_STATUS_RESETDONE		__BIT(0)
+#define OMAP_DMTIMER_V1_INTR_STATUS			0x18 /* TISR */
+#define OMAP_DMTIMER_V1_INTR_ENABLE			0x1c /* TIER */
+#define OMAP_DMTIMER_V1_TIMER_REGS			0x20
+
+/*
+ * DM timer version 2
+ */
+
+#define   OMAP_DMTIMER_V2_ID_Y_MINOR_MASK		__BITS(0, 5)
+#define   OMAP_DMTIMER_V2_ID_CUSTOM_MASK		__BITS(6, 7)
+#define   OMAP_DMTIMER_V2_ID_X_MAJOR_MASK		__BITS(8, 10)
+#define   OMAP_DMTIMER_V2_ID_R_RTL_MASK			__BITS(11, 15)
+#define   OMAP_DMTIMER_V2_ID_FUNC_MASK			__BITS(16, 27)
+#define   OMAP_DMTIMER_V2_ID_RESERVED_MASK		__BITS(28, 29)
+#define   OMAP_DMTIMER_V2_ID_SCHEME_MASK		__BITS(30, 31)
+
+#define   OMAP_DMTIMER_V2_OCP_CFG_SOFTRESET_MASK	__BITS(0, 0)
+#define   OMAP_DMTIMER_V2_OCP_CFG_EMUFREE_MASK		__BITS(1, 1)
+#define   OMAP_DMTIMER_V2_OCP_CFG_IDLEMODE_MASK		__BITS(2, 3)
+
+#define OMAP_DMTIMER_V2_INTR_STATUS_RAW			0x24
+#define OMAP_DMTIMER_V2_INTR_STATUS			0x28
+#define OMAP_DMTIMER_V2_INTR_ENABLE_SET			0x2c
+#define OMAP_DMTIMER_V2_INTR_ENABLE_CLEAR		0x30
+#define OMAP_DMTIMER_V2_TIMER_REGS			0x34
+
+#define OMAP_DMTIMER_REG_INDEX_MASK			0x00ff
+#define OMAP_DMTIMER_REG_POSTED_BIT_MASK		0x0f00
+#define OMAP_DMTIMER_REG_POSTED_INDEX(reg)		\
+	__SHIFTOUT((reg), OMAP_DMTIMER_REG_INDEX_MASK)
+#define OMAP_DMTIMER_REG_POSTED_BIT(reg)		\
+	__SHIFTOUT((reg), OMAP_DMTIMER_REG_POSTED_BIT_MASK)
+#define OMAP_DMTIMER_REG_POSTED_MASK(reg)		\
+	__BIT(OMAP_DMTIMER_REG_POSTED_BIT(reg))
+#define OMAP_DMTIMER_REG_POSTED_P(reg)			\
+	(((reg) & 0x1000) == 0x1000)
+
+#define OMAP_DMTIMER_TIMER_INTR_WAKEUP			0x0000 /* TWER */
+#define OMAP_DMTIMER_TIMER_CTRL				0x1004 /* TCLR */
+#define   OMAP_DMTIMER_TIMER_CTRL_START			__BIT(0)
+#define   OMAP_DMTIMER_TIMER_CTRL_AUTORELOAD		__BIT(1)
+#define   OMAP_DMTIMER_TIMER_CTRL_PRESCALE_MASK		__BITS(2, 4)
+#define   OMAP_DMTIMER_TIMER_CTRL_PRESCALE_ENABLE	__BIT(5)
+#define   OMAP_DMTIMER_TIMER_CTRL_COMPARE_ENABLE	__BIT(6)
+#define   OMAP_DMTIMER_TIMER_CTRL_PWM_SIGN		__BIT(7)
+#define   OMAP_DMTIMER_TIMER_CTRL_TCM_MASK		__BITS(8, 9)
+#define     OMAP_DMTIMER_TIMER_CTRL_TCM_NONE		0
+#define     OMAP_DMTIMER_TIMER_CTRL_TCM_LOW_HIGH	1
+#define     OMAP_DMTIMER_TIMER_CTRL_TCM_HIGH_LOW	2
+#define     OMAP_DMTIMER_TIMER_CTRL_TCM_BOTH		3
+#define   OMAP_DMTIMER_TIMER_CTRL_TRG_MASK		__BITS(10, 11)
+#define     OMAP_DMTIMER_TIMER_CTRL_TRG_NONE		0
+#define     OMAP_DMTIMER_TIMER_CTRL_TRG_OVERFLOW	1
+#define     OMAP_DMTIMER_TIMER_CTRL_TRG_OVERFLOW_MATCH	2
+#define     OMAP_DMTIMER_TIMER_CTRL_TRG_RESERVED	3
+#define   OMAP_DMTIMER_TIMER_CTRL_PWM_PT		__BIT(12)
+#define     OMAP_DMTIMER_TIMER_CTRL_PWM_PULSE		0
+#define     OMAP_DMTIMER_TIMER_CTRL_PWM_TOGGLE		1
+#define   OMAP_DMTIMER_TIMER_CTRL_CAPTURE_MODE		__BIT(13)
+#define     OMAP_DMTIMER_TIMER_CTRL_CAPTURE_MODE_FIRST	0
+#define     OMAP_DMTIMER_TIMER_CTRL_CAPTURE_MODE_SECOND	1
+#define   OMAP_DMTIMER_TIMER_CTRL_GPO_CFG		__BIT(14)
+#define OMAP_DMTIMER_TIMER_COUNTER			0x1108 /* TCRR */
+#define OMAP_DMTIMER_TIMER_LOAD				0x120c /* TLDR */
+#define OMAP_DMTIMER_TIMER_TRIGGER			0x1310 /* TTGR */
+#define OMAP_DMTIMER_TIMER_WRITE_POST			0x0014 /* TWPS */
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_CTRL		__BIT(0)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_COUNTER		__BIT(1)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_LOAD		__BIT(2)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_TRIGGER		__BIT(3)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_MATCH		__BIT(4)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_POS_INCR	__BIT(5)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_NEG_INCR	__BIT(6)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_COUNTER_VALUE	__BIT(7)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_INTR_MASK_SET	__BIT(8)
+#define   OMAP_DMTIMER_TIMER_WRITE_POST_INTR_MASK_COUNT	__BIT(9)
+#define OMAP_DMTIMER_TIMER_MATCH			0x1418 /* TMAR */
+#define OMAP_DMTIMER_TIMER_CAPTURE1			0x001c /* TCAR1 */
+#define OMAP_DMTIMER_TIMER_SYNC_INT_CTRL		0x0020 /* TSICR */
+#define   OMAP_DMTIMER_TIMER_SYNC_INT_CTRL_SOFTRESET	__BIT(1)
+#define   OMAP_DMTIMER_TIMER_SYNC_INT_CTRL_POSTED	__BIT(2)
+#define OMAP_DMTIMER_TIMER_CAPTURE2			0x0024 /* TCAR2 */
+#define OMAP_DMTIMER_TICK_POS_INCR			0x1528 /* TPIR */
+#define OMAP_DMTIMER_TICK_NEG_INCR			0x162c /* TNIR */
+#define OMAP_DMTIMER_TICK_COUNTER_VALUE			0x1730 /* TCVR */
+#define OMAP_DMTIMER_TICK_INTR_MASK_SET			0x1834 /* TOCR */
+#define OMAP_DMTIMER_TICK_INTR_MASK_COUNT		0x1938 /* TOWR */
+
+#endif	/* _ARM_OMAP_OMAP_DMTIMERREG_H_ */
Index: src/sys/arch/arm/omap/omap_dmtimervar.h
diff -u /dev/null src/sys/arch/arm/omap/omap_dmtimervar.h:1.1
--- /dev/null	Tue Dec 11 19:01:18 2012
+++ src/sys/arch/arm/omap/omap_dmtimervar.h	Tue Dec 11 19:01:18 2012
@@ -0,0 +1,62 @@
+/*	$NetBSD: omap_dmtimervar.h,v 1.1 2012/12/11 19:01:18 riastradh Exp $	*/
+
+/*
+ * TI OMAP Dual-mode timers: Driver state
+ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _ARM_OMAP_OMAP_DMTIMERVAR_H_
+#define _ARM_OMAP_OMAP_DMTIMERVAR_H_
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device_if.h>
+
+struct omap_module;
+
+struct omap_dmtimer_softc {
+	device_t			sc_dev;
+	const struct omap_module	*sc_module;
+	unsigned int			sc_version;
+	int				sc_intr;
+	bus_space_tag_t			sc_iot;
+	bus_space_handle_t		sc_ioh;
+
+	bool				sc_posted;
+	bool				sc_enabled;
+};
+
+void	omap_dmtimer_attach_timecounter(struct omap_dmtimer_softc *);
+void	omap_dmtimer_attach_hardclock(struct omap_dmtimer_softc *);
+void	omap_dmtimer_attach_statclock(struct omap_dmtimer_softc *);
+
+#endif  /* _ARM_OMAP_OMAP_DMTIMERVAR_H_ */

Reply via email to