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_ */