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>