Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Aug 2015 19:48:49 +0000 (UTC)
From:      Dimitry Andric <dim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r286697 - in projects/clang-trunk: . sys/arm/ti/am335x
Message-ID:  <201508121948.t7CJmnbZ001755@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dim
Date: Wed Aug 12 19:48:49 2015
New Revision: 286697
URL: https://svnweb.freebsd.org/changeset/base/286697

Log:
  Merge ^/head r286694 through r286696.

Added:
  projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtreg.h
     - copied unchanged from r286696, head/sys/arm/ti/am335x/am335x_dmtreg.h
Modified:
  projects/clang-trunk/Makefile.inc1
  projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtimer.c
Directory Properties:
  projects/clang-trunk/   (props changed)
  projects/clang-trunk/sys/   (props changed)

Modified: projects/clang-trunk/Makefile.inc1
==============================================================================
--- projects/clang-trunk/Makefile.inc1	Wed Aug 12 19:40:32 2015	(r286696)
+++ projects/clang-trunk/Makefile.inc1	Wed Aug 12 19:48:49 2015	(r286697)
@@ -1439,7 +1439,7 @@ _gcc_tools= gnu/usr.bin/cc/cc_tools
 
 .if ${MK_RESCUE} != "no"
 # rescue includes programs that have build-tools targets
-_rescue=rescue
+_rescue=rescue/rescue
 .endif
 
 build-tools: .MAKE

Modified: projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtimer.c
==============================================================================
--- projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtimer.c	Wed Aug 12 19:40:32 2015	(r286696)
+++ projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtimer.c	Wed Aug 12 19:48:49 2015	(r286697)
@@ -30,79 +30,22 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
-#include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/malloc.h>
 #include <sys/rman.h>
-#include <sys/taskqueue.h>
 #include <sys/timeet.h>
-#include <sys/timepps.h>
 #include <sys/timetc.h>
-#include <sys/watchdog.h>
 #include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/intr.h>
 
-#include "opt_ntp.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 <arm/ti/ti_prcm.h>
 #include <arm/ti/ti_hwmods.h>
-#include <arm/ti/ti_pinmux.h>
 
-#define	AM335X_NUM_TIMERS	8
-
-#define	DMT_TIDR		0x00		/* Identification Register */
-#define	DMT_TIOCP_CFG		0x10		/* OCP Configuration Reg */
-#define	  DMT_TIOCP_RESET	  (1 << 0)	/* TIOCP perform soft reset */
-#define	DMT_IQR_EOI		0x20		/* IRQ End-Of-Interrupt Reg */
-#define	DMT_IRQSTATUS_RAW	0x24		/* IRQSTATUS Raw Reg */
-#define	DMT_IRQSTATUS		0x28		/* IRQSTATUS Reg */
-#define	DMT_IRQENABLE_SET	0x2c		/* IRQSTATUS Set Reg */
-#define	DMT_IRQENABLE_CLR	0x30		/* IRQSTATUS Clear Reg */
-#define	DMT_IRQWAKEEN		0x34		/* IRQ Wakeup Enable Reg */
-#define	  DMT_IRQ_MAT		  (1 << 0)	/* IRQ: Match */
-#define	  DMT_IRQ_OVF		  (1 << 1)	/* IRQ: Overflow */
-#define	  DMT_IRQ_TCAR		  (1 << 2)	/* IRQ: Capture */
-#define	  DMT_IRQ_MASK		  (DMT_IRQ_TCAR | DMT_IRQ_OVF | DMT_IRQ_MAT)
-#define	DMT_TCLR		0x38		/* Control Register */
-#define	  DMT_TCLR_START	  (1 << 0)	/* Start timer */
-#define	  DMT_TCLR_AUTOLOAD	  (1 << 1)	/* Auto-reload on overflow */
-#define	  DMT_TCLR_PRES_MASK	  (7 << 2)	/* Prescaler mask */
-#define	  DMT_TCLR_PRES_ENABLE	  (1 << 5)	/* Prescaler enable */
-#define	  DMT_TCLR_COMP_ENABLE	  (1 << 6)	/* Compare enable */
-#define	  DMT_TCLR_PWM_HIGH	  (1 << 7)	/* PWM default output high */
-#define	  DMT_TCLR_CAPTRAN_MASK	  (3 << 8)	/* Capture transition mask */
-#define	  DMT_TCLR_CAPTRAN_NONE	  (0 << 8)	/* Capture: none */
-#define	  DMT_TCLR_CAPTRAN_LOHI	  (1 << 8)	/* Capture lo->hi transition */
-#define	  DMT_TCLR_CAPTRAN_HILO	  (2 << 8)	/* Capture hi->lo transition */
-#define	  DMT_TCLR_CAPTRAN_BOTH	  (3 << 8)	/* Capture both transitions */
-#define	  DMT_TCLR_TRGMODE_MASK	  (3 << 10)	/* Trigger output mode mask */
-#define	  DMT_TCLR_TRGMODE_NONE	  (0 << 10)	/* Trigger off */
-#define	  DMT_TCLR_TRGMODE_OVFL	  (1 << 10)	/* Trigger on overflow */
-#define	  DMT_TCLR_TRGMODE_BOTH	  (2 << 10)	/* Trigger on match + ovflow */
-#define	  DMT_TCLR_PWM_PTOGGLE	  (1 << 12)	/* PWM toggles */
-#define	  DMT_TCLR_CAP_MODE_2ND	  (1 << 13)	/* Capture second event mode */
-#define	  DMT_TCLR_GPO_CFG	  (1 << 14)	/* (no descr in datasheet) */
-#define	DMT_TCRR		0x3C		/* Counter Register */
-#define	DMT_TLDR		0x40		/* Load Reg */
-#define	DMT_TTGR		0x44		/* Trigger Reg */
-#define	DMT_TWPS		0x48		/* Write Posted Status Reg */
-#define	DMT_TMAR		0x4C		/* Match Reg */
-#define	DMT_TCAR1		0x50		/* Capture Reg */
-#define	DMT_TSICR		0x54		/* Synchr. Interface Ctrl Reg */
-#define	  DMT_TSICR_RESET	  (1 << 1)	/* TSICR perform soft reset */
-#define	DMT_TCAR2		0x48		/* Capture Reg */
-
-#define	DMTIMER_READ4(sc, reg)	(bus_read_4((sc)->tmr_mem_res, (reg)))
-#define	DMTIMER_WRITE4(sc, reg, val)	(bus_write_4((sc)->tmr_mem_res, (reg), (val)))
+#include "am335x_dmtreg.h"
 
 struct am335x_dmtimer_softc {
 	device_t		dev;
@@ -113,294 +56,35 @@ struct am335x_dmtimer_softc {
 	void			*tmr_irq_handler;
 	uint32_t		sysclk_freq;
 	uint32_t		tclr;		/* Cached TCLR register. */
-	int			pps_curmode;	/* Edge mode now set in hw. */
-	struct task 		pps_task;	/* For pps_event handling. */
-	struct cdev *		pps_cdev;
-	struct pps_state 	pps;
-
 	union {
 		struct timecounter tc;
 		struct eventtimer et;
 	} func;
+	int			tmr_num;	/* Hardware unit number. */
+	char			tmr_name[12];	/* "DMTimerN", N = tmr_num */
 };
 
 static struct am335x_dmtimer_softc *am335x_dmtimer_et_sc = NULL;
 static struct am335x_dmtimer_softc *am335x_dmtimer_tc_sc = NULL;
 
-
-#ifdef PPS_SYNC
-/* -1 - not detected, 0 - not found, > 0 - timerX module */
-static int am335x_dmtimer_pps_module = -1;
-static const char *am335x_dmtimer_pps_hwmod = NULL;
-#endif
-
 /*
- * PPS driver routines, included when the kernel is built with option PPS_SYNC.
- *
- * Note that this PPS driver does not use an interrupt.  Instead it uses the
- * hardware's ability to latch the timer's count register in response to a
- * signal on an IO pin.  Each of timers 4-7 have an associated pin, and this
- * code allows any one of those to be used.
- *
- * The timecounter routines in kern_tc.c call the pps poll routine periodically
- * to see if a new counter value has been latched.  When a new value has been
- * latched, the only processing done in the poll routine is to capture the
- * current set of timecounter timehands (done with pps_capture()) and the
- * latched value from the timer.  The remaining work (done by pps_event()) is
- * scheduled to be done later in a non-interrupt context.
+ * We use dmtimer2 for eventtimer and dmtimer3 for timecounter.
  */
-#ifdef PPS_SYNC
-
-#define	PPS_CDEV_NAME	"dmtpps"
-
-static void
-am335x_dmtimer_set_capture_mode(struct am335x_dmtimer_softc *sc, bool force_off)
-{
-	int newmode;
-
-	if (force_off)
-		newmode = 0;
-	else
-		newmode = sc->pps.ppsparam.mode & PPS_CAPTUREBOTH;
-
-	if (newmode == sc->pps_curmode)
-		return;
-
-	sc->pps_curmode = newmode;
-	sc->tclr &= ~DMT_TCLR_CAPTRAN_MASK;
-	switch (newmode) {
-	case PPS_CAPTUREASSERT:
-		sc->tclr |= DMT_TCLR_CAPTRAN_LOHI;
-		break;
-	case PPS_CAPTURECLEAR:
-		sc->tclr |= DMT_TCLR_CAPTRAN_HILO;
-		break;
-	default:
-		/* It can't be BOTH, so it's disabled. */
-		break;
-	}
-	DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
-}
-
-static void
-am335x_dmtimer_tc_poll_pps(struct timecounter *tc)
-{
-	struct am335x_dmtimer_softc *sc;
-
-	sc = tc->tc_priv;
-
-	/*
-	 * Note that we don't have the TCAR interrupt enabled, but the hardware
-	 * still provides the status bits in the "RAW" status register even when
-	 * they're masked from generating an irq.  However, when clearing the
-	 * TCAR status to re-arm the capture for the next second, we have to
-	 * write to the IRQ status register, not the RAW register.  Quirky.
-	 */
-	if (DMTIMER_READ4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) {
-		pps_capture(&sc->pps);
-		sc->pps.capcount = DMTIMER_READ4(sc, DMT_TCAR1);
-		DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR);
-		taskqueue_enqueue_fast(taskqueue_fast, &sc->pps_task);
-	}
-}
-
-static void
-am335x_dmtimer_process_pps_event(void *arg, int pending)
-{
-	struct am335x_dmtimer_softc *sc;
-
-	sc = arg;
-
-	/* This is the task function that gets enqueued by poll_pps.  Once the
-	 * time has been captured in the hw interrupt context, the remaining
-	 * (more expensive) work to process the event is done later in a
-	 * non-fast-interrupt context.
-	 *
-	 * We only support capture of the rising or falling edge, not both at
-	 * once; tell the kernel to process whichever mode is currently active.
-	 */
-	pps_event(&sc->pps, sc->pps.ppsparam.mode & PPS_CAPTUREBOTH);
-}
-
-static int
-am335x_dmtimer_pps_open(struct cdev *dev, int flags, int fmt, 
-    struct thread *td)
-{
-	struct am335x_dmtimer_softc *sc;
-
-	sc = dev->si_drv1;
+#define ET_TMR_NUM      2
+#define TC_TMR_NUM      3
 
-	/* Enable capture on open.  Harmless if already open. */
-	am335x_dmtimer_set_capture_mode(sc, 0);
-
-	return 0;
-}
-
-static	int
-am335x_dmtimer_pps_close(struct cdev *dev, int flags, int fmt, 
-    struct thread *td)
-{
-	struct am335x_dmtimer_softc *sc;
-
-	sc = dev->si_drv1;
-
-	/*
-	 * Disable capture on last close.  Use the force-off flag to override
-	 * the configured mode and turn off the hardware capture.
-	 */
-	am335x_dmtimer_set_capture_mode(sc, 1);
-
-	return 0;
-}
-
-static int
-am335x_dmtimer_pps_ioctl(struct cdev *dev, u_long cmd, caddr_t data, 
-    int flags, struct thread *td)
-{
-	struct am335x_dmtimer_softc *sc;
-	int err;
-
-	sc = dev->si_drv1;
-
-	/*
-	 * The hardware has a "capture both edges" mode, but we can't do
-	 * anything useful with it in terms of PPS capture, so don't even try.
-	 */
-	if ((sc->pps.ppsparam.mode & PPS_CAPTUREBOTH) == PPS_CAPTUREBOTH)
-		return (EINVAL);
-
-	/* Let the kernel do the heavy lifting for ioctl. */
-	err = pps_ioctl(cmd, data, &sc->pps);
-	if (err != 0)
-		return (err);
-
-	/*
-	 * The capture mode could have changed, set the hardware to whatever
-	 * mode is now current.  Effectively a no-op if nothing changed.
-	 */
-	am335x_dmtimer_set_capture_mode(sc, 0);
-
-	return (err);
-}
-
-static struct cdevsw am335x_dmtimer_pps_cdevsw = {
-	.d_version =    D_VERSION,
-	.d_open =       am335x_dmtimer_pps_open,
-	.d_close =      am335x_dmtimer_pps_close,
-	.d_ioctl =      am335x_dmtimer_pps_ioctl,
-	.d_name =       PPS_CDEV_NAME,
+/* List of compatible strings for FDT tree */
+static struct ofw_compat_data compat_data[] = {
+	{"ti,am335x-timer",     1},
+	{"ti,am335x-timer-1ms", 1},
+	{NULL,                  0},
 };
 
-static void
-am335x_dmtimer_pps_find()
-{
-	int i;
-	unsigned int padstate;
-	const char * padmux;
-	struct padinfo {
-		char * ballname;
-		const char * muxname;
-		int    timer_num;
-	} padinfo[] = {
-		{"GPMC_ADVn_ALE", "timer4", 4}, 
-		{"GPMC_BEn0_CLE", "timer5", 5},
-		{"GPMC_WEn",      "timer6", 6},
-		{"GPMC_OEn_REn",  "timer7", 7},
-	};
-
-	/*
-	 * Figure out which pin the user has set up for pps.  We'll use the
-	 * first timer that has an external caputure pin configured as input.
-	 *
-	 * XXX The hieroglyphic "(padstate & (0x01 << 5)))" checks that the pin
-	 * is configured for input.  The right symbolic values aren't exported
-	 * yet from ti_scm.h.
-	 */
-	am335x_dmtimer_pps_module = 0;
-	for (i = 0; i < nitems(padinfo) && am335x_dmtimer_pps_module == 0; ++i) {
-		if (ti_pinmux_padconf_get(padinfo[i].ballname, &padmux, 
-		    &padstate) == 0) {
-			if (strcasecmp(padinfo[i].muxname, padmux) == 0 &&
-			    (padstate & (0x01 << 5))) {
-				am335x_dmtimer_pps_module = padinfo[i].timer_num;
-				am335x_dmtimer_pps_hwmod = padinfo[i].muxname;
-			}
-		}
-	}
-
-
-	if (am335x_dmtimer_pps_module == 0) {
-		printf("am335x_dmtimer: No DMTimer found with capture pin "
-		    "configured as input; PPS driver disabled.\n");
-	}
-}
-
-/*
- * Set up the PPS cdev and the the kernel timepps stuff.
- *
- * Note that this routine cannot touch the hardware, because bus space resources
- * are not fully set up yet when this is called.
- */
-static void
-am335x_dmtimer_pps_init(device_t dev, struct am335x_dmtimer_softc *sc)
-{
-	int unit;
-
-	if (am335x_dmtimer_pps_module == -1)
-		am335x_dmtimer_pps_find();
-
-	/* No PPS input */
-	if (am335x_dmtimer_pps_module == 0)
-		return;
-
-	/* Not PPS-enabled input */
-	if ((am335x_dmtimer_pps_module > 0) &&
-	    (!ti_hwmods_contains(dev, am335x_dmtimer_pps_hwmod)))
-	 	return;
-
-	/*
-	 * Indicate our capabilities (pretty much just capture of either edge).
-	 * Have the kernel init its part of the pps_state struct and add its
-	 * capabilities.
-	 */
-	sc->pps.ppscap = PPS_CAPTUREBOTH;
-	pps_init(&sc->pps);
-
-	/*
-	 * Set up to capture the PPS via timecounter polling, and init the task
-	 * that does deferred pps_event() processing after capture.
-	 */
-	sc->func.tc.tc_poll_pps = am335x_dmtimer_tc_poll_pps;
-	TASK_INIT(&sc->pps_task, 0, am335x_dmtimer_process_pps_event, sc);
-
-	/* Create the PPS cdev.  */
-	unit = device_get_unit(dev);
-	sc->pps_cdev = make_dev(&am335x_dmtimer_pps_cdevsw, unit, 
-	    UID_ROOT, GID_WHEEL, 0600, PPS_CDEV_NAME);
-	sc->pps_cdev->si_drv1 = sc;
-
-	device_printf(dev, "Using DMTimer%d for PPS device /dev/%s%d\n", 
-	    am335x_dmtimer_pps_module, PPS_CDEV_NAME, unit);
-}
-
-#endif
-
-/*
- * End of PPS driver code.
- */
-
-static unsigned
-am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
-{
-	struct am335x_dmtimer_softc *sc;
-
-	sc = tc->tc_priv;
-
-	return (DMTIMER_READ4(sc, DMT_TCRR));
-}
+#define	DMTIMER_READ4(sc, reg)		bus_read_4((sc)->tmr_mem_res, (reg))
+#define	DMTIMER_WRITE4(sc, reg, val)	bus_write_4((sc)->tmr_mem_res, (reg), (val))
 
 static int
-am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+am335x_dmtimer_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
 {
 	struct am335x_dmtimer_softc *sc;
 	uint32_t initial_count, reload_count;
@@ -452,7 +136,7 @@ am335x_dmtimer_start(struct eventtimer *
 }
 
 static int
-am335x_dmtimer_stop(struct eventtimer *et)
+am335x_dmtimer_et_stop(struct eventtimer *et)
 {
 	struct am335x_dmtimer_softc *sc;
 
@@ -467,7 +151,7 @@ am335x_dmtimer_stop(struct eventtimer *e
 }
 
 static int
-am335x_dmtimer_intr(void *arg)
+am335x_dmtimer_et_intr(void *arg)
 {
 	struct am335x_dmtimer_softc *sc;
 
@@ -481,65 +165,55 @@ am335x_dmtimer_intr(void *arg)
 	return (FILTER_HANDLED);
 }
 
-/*
- * Checks if timer is suitable to be system timer
- */
 static int
-am335x_dmtimer_system_compatible(device_t dev)
+am335x_dmtimer_et_init(struct am335x_dmtimer_softc *sc)
 {
-	phandle_t node;
+	KASSERT(am335x_dmtimer_et_sc == NULL, ("already have an eventtimer"));
 
-	node = ofw_bus_get_node(dev);
-	if (OF_hasprop(node, "ti,timer-alwon"))
-		return (0);
-
-	return (1);
-}
-
-static int
-am335x_dmtimer_init_et(struct am335x_dmtimer_softc *sc)
-{
-	if (am335x_dmtimer_et_sc != NULL)
-		return (EEXIST);
-
-#ifdef PPS_SYNC
-	if ((am335x_dmtimer_pps_module > 0) &&
-	    (!ti_hwmods_contains(sc->dev, am335x_dmtimer_pps_hwmod))) {
-	    	device_printf(sc->dev, "not PPS enabled\n");
-	 	return (ENXIO);
-	}
-#endif
-
-	/* Setup eventtimer interrupt handler. */
+	/*
+	 * Setup eventtimer interrupt handling.  Panic if anything goes wrong,
+	 * because the system just isn't going to run without an eventtimer.
+	 */
+	sc->tmr_irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
+	    &sc->tmr_irq_rid, RF_ACTIVE);
+	if (sc->tmr_irq_res == NULL)
+		panic("am335x_dmtimer: could not allocate irq resources");
 	if (bus_setup_intr(sc->dev, sc->tmr_irq_res, INTR_TYPE_CLK,
-			am335x_dmtimer_intr, NULL, sc, &sc->tmr_irq_handler) != 0) {
-		device_printf(sc->dev, "Unable to setup the clock irq handler.\n");
-		return (ENXIO);
-	}
+	    am335x_dmtimer_et_intr, NULL, sc, &sc->tmr_irq_handler) != 0)
+		panic("am335x_dmtimer: count not setup irq handler");
 
-	sc->func.et.et_name = "AM335x Eventtimer";
+	sc->func.et.et_name = sc->tmr_name;
 	sc->func.et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
-	sc->func.et.et_quality = 1000;
+	sc->func.et.et_quality = 500;
 	sc->func.et.et_frequency = sc->sysclk_freq;
 	sc->func.et.et_min_period =
 	    ((0x00000005LLU << 32) / sc->func.et.et_frequency);
 	sc->func.et.et_max_period =
 	    (0xfffffffeLLU << 32) / sc->func.et.et_frequency;
-	sc->func.et.et_start = am335x_dmtimer_start;
-	sc->func.et.et_stop = am335x_dmtimer_stop;
+	sc->func.et.et_start = am335x_dmtimer_et_start;
+	sc->func.et.et_stop = am335x_dmtimer_et_stop;
 	sc->func.et.et_priv = sc;
-	et_register(&sc->func.et);
 
 	am335x_dmtimer_et_sc = sc;
+	et_register(&sc->func.et);
 
 	return (0);
 }
 
+static unsigned
+am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
+{
+	struct am335x_dmtimer_softc *sc;
+
+	sc = tc->tc_priv;
+
+	return (DMTIMER_READ4(sc, DMT_TCRR));
+}
+
 static int
-am335x_dmtimer_init_tc(struct am335x_dmtimer_softc *sc)
+am335x_dmtimer_tc_init(struct am335x_dmtimer_softc *sc)
 {
-	if (am335x_dmtimer_tc_sc != NULL)
-		return (EEXIST);
+	KASSERT(am335x_dmtimer_tc_sc == NULL, ("already have a timecounter"));
 
 	/* Set up timecounter, start it, register it. */
 	DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);
@@ -551,15 +225,15 @@ am335x_dmtimer_init_tc(struct am335x_dmt
 	DMTIMER_WRITE4(sc, DMT_TCRR, 0);
 	DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
 
-	sc->func.tc.tc_name           = "AM335x Timecounter";
+	sc->func.tc.tc_name           = sc->tmr_name;
 	sc->func.tc.tc_get_timecount  = am335x_dmtimer_tc_get_timecount;
 	sc->func.tc.tc_counter_mask   = ~0u;
 	sc->func.tc.tc_frequency      = sc->sysclk_freq;
-	sc->func.tc.tc_quality        = 1000;
+	sc->func.tc.tc_quality        = 500;
 	sc->func.tc.tc_priv           = sc;
-	tc_init(&sc->func.tc);
 
 	am335x_dmtimer_tc_sc = sc;
+	tc_init(&sc->func.tc);
 
 	return (0);
 }
@@ -567,92 +241,72 @@ am335x_dmtimer_init_tc(struct am335x_dmt
 static int
 am335x_dmtimer_probe(device_t dev)
 {
+	char strbuf[32];
+	int tmr_num;
 
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
-	if (ofw_bus_is_compatible(dev, "ti,am335x-timer-1ms") ||
-	    ofw_bus_is_compatible(dev, "ti,am335x-timer")) {
-		device_set_desc(dev, "AM335x DMTimer");
-		return(BUS_PROBE_DEFAULT);
-	}
+	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+		return (ENXIO);
+
+	/*
+	 * Get the hardware unit number (the N from ti,hwmods="timerN").
+	 * If this isn't the hardware unit we're going to use for either the
+	 * eventtimer or the timecounter, no point in instantiating the device.
+	 */
+	tmr_num = ti_hwmods_get_unit(dev, "timer");
+	if (tmr_num != ET_TMR_NUM && tmr_num != TC_TMR_NUM)
+		return (ENXIO);
 
-	return (ENXIO);
+	snprintf(strbuf, sizeof(strbuf), "AM335x DMTimer%d", tmr_num);
+	device_set_desc_copy(dev, strbuf);
+
+	return(BUS_PROBE_DEFAULT);
 }
 
 static int
 am335x_dmtimer_attach(device_t dev)
 {
 	struct am335x_dmtimer_softc *sc;
-	int err;
 	clk_ident_t timer_id;
-	int enable;
+	int err;
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
 
 	/* Get the base clock frequency. */
-	err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq);
-	if (err) {
-		device_printf(dev, "Error: could not get sysclk frequency\n");
+	if ((err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq)) != 0)
+		return (err);
+
+	/* Enable clocks and power on the device. */
+	if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT)
 		return (ENXIO);
-	}
+	if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0)
+		return (err);
+	if ((err = ti_prcm_clk_enable(timer_id)) != 0)
+		return (err);
 
 	/* Request the memory resources. */
 	sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 	    &sc->tmr_mem_rid, RF_ACTIVE);
 	if (sc->tmr_mem_res == NULL) {
-		device_printf(dev, "Error: could not allocate mem resources\n");
 		return (ENXIO);
 	}
 
-	/* Request the IRQ resources. */
-	sc->tmr_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-	    &sc->tmr_irq_rid, RF_ACTIVE);
-	if (err) {
-		bus_release_resource(dev, SYS_RES_MEMORY, sc->tmr_mem_rid,
-		    sc->tmr_mem_res);
-		device_printf(dev, "Error: could not allocate irq resources\n");
-		return (ENXIO);
-	}
+	sc->tmr_num = ti_hwmods_get_unit(dev, "timer");
+	snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
 
-#ifdef PPS_SYNC
-	am335x_dmtimer_pps_init(dev, sc);
-#endif
-
-	enable = 0;
-	/* Try to use as a timecounter or event timer */
-	if (am335x_dmtimer_system_compatible(dev)) {
-		if (am335x_dmtimer_init_tc(sc) == 0)
-			enable = 1;
-		else if (am335x_dmtimer_init_et(sc) == 0)
-			enable = 1;
-	}
-
-	if (enable) {
-		/* Enable clocks and power on the chosen devices. */
-		timer_id = ti_hwmods_get_clock(dev);
-		if (timer_id == INVALID_CLK_IDENT) {
-			bus_release_resource(dev, SYS_RES_MEMORY, sc->tmr_mem_rid,
-			    sc->tmr_mem_res);
-			bus_release_resource(dev, SYS_RES_IRQ, sc->tmr_irq_rid,
-			    sc->tmr_irq_res);
-			device_printf(dev, "failed to get device id using ti,hwmods\n");
-			return (ENXIO);
-		}
-
-		err  = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK);
-		err |= ti_prcm_clk_enable(timer_id);
-
-		if (err) {
-			bus_release_resource(dev, SYS_RES_MEMORY, sc->tmr_mem_rid,
-			    sc->tmr_mem_res);
-			bus_release_resource(dev, SYS_RES_IRQ, sc->tmr_irq_rid,
-			    sc->tmr_irq_res);
-			device_printf(dev, "Error: could not enable timer clock\n");
-			return (ENXIO);
-		}
-	}
+	/*
+	 * Go set up either a timecounter or eventtimer.  We wouldn't have
+	 * attached if we weren't one or the other.
+	 */
+	if (sc->tmr_num == ET_TMR_NUM)
+		am335x_dmtimer_et_init(sc);
+	else if (sc->tmr_num == TC_TMR_NUM)
+		am335x_dmtimer_tc_init(sc);
+	else
+		panic("am335x_dmtimer: bad timer number %d", sc->tmr_num);
 
 	return (0);
 }

Copied: projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtreg.h (from r286696, head/sys/arm/ti/am335x/am335x_dmtreg.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/clang-trunk/sys/arm/ti/am335x/am335x_dmtreg.h	Wed Aug 12 19:48:49 2015	(r286697, copy of r286696, head/sys/arm/ti/am335x/am335x_dmtreg.h)
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion@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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef AM335X_DMTREG_H
+#define AM335X_DMTREG_H
+
+#define	AM335X_NUM_TIMERS	8
+
+#define	DMT_TIDR		0x00		/* Identification Register */
+#define	DMT_TIOCP_CFG		0x10		/* OCP Configuration Reg */
+#define	  DMT_TIOCP_RESET	  (1 << 0)	/* TIOCP perform soft reset */
+#define	DMT_IQR_EOI		0x20		/* IRQ End-Of-Interrupt Reg */
+#define	DMT_IRQSTATUS_RAW	0x24		/* IRQSTATUS Raw Reg */
+#define	DMT_IRQSTATUS		0x28		/* IRQSTATUS Reg */
+#define	DMT_IRQENABLE_SET	0x2c		/* IRQSTATUS Set Reg */
+#define	DMT_IRQENABLE_CLR	0x30		/* IRQSTATUS Clear Reg */
+#define	DMT_IRQWAKEEN		0x34		/* IRQ Wakeup Enable Reg */
+#define	  DMT_IRQ_MAT		  (1 << 0)	/* IRQ: Match */
+#define	  DMT_IRQ_OVF		  (1 << 1)	/* IRQ: Overflow */
+#define	  DMT_IRQ_TCAR		  (1 << 2)	/* IRQ: Capture */
+#define	  DMT_IRQ_MASK		  (DMT_IRQ_TCAR | DMT_IRQ_OVF | DMT_IRQ_MAT)
+#define	DMT_TCLR		0x38		/* Control Register */
+#define	  DMT_TCLR_START	  (1 << 0)	/* Start timer */
+#define	  DMT_TCLR_AUTOLOAD	  (1 << 1)	/* Auto-reload on overflow */
+#define	  DMT_TCLR_PRES_MASK	  (7 << 2)	/* Prescaler mask */
+#define	  DMT_TCLR_PRES_ENABLE	  (1 << 5)	/* Prescaler enable */
+#define	  DMT_TCLR_COMP_ENABLE	  (1 << 6)	/* Compare enable */
+#define	  DMT_TCLR_PWM_HIGH	  (1 << 7)	/* PWM default output high */
+#define	  DMT_TCLR_CAPTRAN_MASK	  (3 << 8)	/* Capture transition mask */
+#define	  DMT_TCLR_CAPTRAN_NONE	  (0 << 8)	/* Capture: none */
+#define	  DMT_TCLR_CAPTRAN_LOHI	  (1 << 8)	/* Capture lo->hi transition */
+#define	  DMT_TCLR_CAPTRAN_HILO	  (2 << 8)	/* Capture hi->lo transition */
+#define	  DMT_TCLR_CAPTRAN_BOTH	  (3 << 8)	/* Capture both transitions */
+#define	  DMT_TCLR_TRGMODE_MASK	  (3 << 10)	/* Trigger output mode mask */
+#define	  DMT_TCLR_TRGMODE_NONE	  (0 << 10)	/* Trigger off */
+#define	  DMT_TCLR_TRGMODE_OVFL	  (1 << 10)	/* Trigger on overflow */
+#define	  DMT_TCLR_TRGMODE_BOTH	  (2 << 10)	/* Trigger on match + ovflow */
+#define	  DMT_TCLR_PWM_PTOGGLE	  (1 << 12)	/* PWM toggles */
+#define	  DMT_TCLR_CAP_MODE_2ND	  (1 << 13)	/* Capture second event mode */
+#define	  DMT_TCLR_GPO_CFG	  (1 << 14)	/* (no descr in datasheet) */
+#define	DMT_TCRR		0x3C		/* Counter Register */
+#define	DMT_TLDR		0x40		/* Load Reg */
+#define	DMT_TTGR		0x44		/* Trigger Reg */
+#define	DMT_TWPS		0x48		/* Write Posted Status Reg */
+#define	DMT_TMAR		0x4C		/* Match Reg */
+#define	DMT_TCAR1		0x50		/* Capture Reg */
+#define	DMT_TSICR		0x54		/* Synchr. Interface Ctrl Reg */
+#define	  DMT_TSICR_RESET	  (1 << 1)	/* TSICR perform soft reset */
+#define	DMT_TCAR2		0x48		/* Capture Reg */
+
+#endif /* AM335X_DMTREG_H */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508121948.t7CJmnbZ001755>