1e53470feSOleksandr Tymoshenko /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3af3dc4a7SPedro F. Giffuni *
4e53470feSOleksandr Tymoshenko * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
5e53470feSOleksandr Tymoshenko * All rights reserved.
6e53470feSOleksandr Tymoshenko *
7e53470feSOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without
8e53470feSOleksandr Tymoshenko * modification, are permitted provided that the following conditions
9e53470feSOleksandr Tymoshenko * are met:
10e53470feSOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright
11e53470feSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer.
12e53470feSOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright
13e53470feSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the
14e53470feSOleksandr Tymoshenko * documentation and/or other materials provided with the distribution.
15e53470feSOleksandr Tymoshenko *
16e53470feSOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17e53470feSOleksandr Tymoshenko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18e53470feSOleksandr Tymoshenko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19e53470feSOleksandr Tymoshenko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20e53470feSOleksandr Tymoshenko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21e53470feSOleksandr Tymoshenko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22e53470feSOleksandr Tymoshenko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23e53470feSOleksandr Tymoshenko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24e53470feSOleksandr Tymoshenko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25e53470feSOleksandr Tymoshenko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e53470feSOleksandr Tymoshenko * SUCH DAMAGE.
27e53470feSOleksandr Tymoshenko */
28e53470feSOleksandr Tymoshenko
29e53470feSOleksandr Tymoshenko #include <sys/param.h>
30e53470feSOleksandr Tymoshenko #include <sys/systm.h>
31e53470feSOleksandr Tymoshenko #include <sys/bus.h>
32e53470feSOleksandr Tymoshenko #include <sys/kernel.h>
33e53470feSOleksandr Tymoshenko #include <sys/module.h>
34e53470feSOleksandr Tymoshenko #include <sys/malloc.h>
35e53470feSOleksandr Tymoshenko #include <sys/rman.h>
36e53470feSOleksandr Tymoshenko #include <sys/timeet.h>
37e53470feSOleksandr Tymoshenko #include <sys/timetc.h>
38e53470feSOleksandr Tymoshenko #include <machine/bus.h>
39e53470feSOleksandr Tymoshenko
408fcbb323SAndrew Turner #include <machine/machdep.h> /* For arm_set_delay */
418fcbb323SAndrew Turner
42be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h>
430050ea24SMichal Meloun
44e53470feSOleksandr Tymoshenko #include <dev/ofw/openfirm.h>
45e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h>
46e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h>
47e53470feSOleksandr Tymoshenko
480050ea24SMichal Meloun #include <arm/ti/ti_sysc.h>
49e53470feSOleksandr Tymoshenko
50479e7c44SIan Lepore #include "am335x_dmtreg.h"
515b03aba6SOleksandr Tymoshenko
52e53470feSOleksandr Tymoshenko struct am335x_dmtimer_softc {
535b03aba6SOleksandr Tymoshenko device_t dev;
545b03aba6SOleksandr Tymoshenko int tmr_mem_rid;
555b03aba6SOleksandr Tymoshenko struct resource * tmr_mem_res;
565b03aba6SOleksandr Tymoshenko int tmr_irq_rid;
575b03aba6SOleksandr Tymoshenko struct resource * tmr_irq_res;
585b03aba6SOleksandr Tymoshenko void *tmr_irq_handler;
590050ea24SMichal Meloun clk_t clk_fck;
600050ea24SMichal Meloun uint64_t sysclk_freq;
615b03aba6SOleksandr Tymoshenko uint32_t tclr; /* Cached TCLR register. */
625b03aba6SOleksandr Tymoshenko union {
6397247a2aSIan Lepore struct timecounter tc;
64e53470feSOleksandr Tymoshenko struct eventtimer et;
655b03aba6SOleksandr Tymoshenko } func;
66479e7c44SIan Lepore int tmr_num; /* Hardware unit number. */
67479e7c44SIan Lepore char tmr_name[12]; /* "DMTimerN", N = tmr_num */
68e53470feSOleksandr Tymoshenko };
69e53470feSOleksandr Tymoshenko
705b03aba6SOleksandr Tymoshenko static struct am335x_dmtimer_softc *am335x_dmtimer_et_sc = NULL;
715b03aba6SOleksandr Tymoshenko static struct am335x_dmtimer_softc *am335x_dmtimer_tc_sc = NULL;
7297247a2aSIan Lepore
738fcbb323SAndrew Turner static void am335x_dmtimer_delay(int, void *);
748fcbb323SAndrew Turner
75fb962e6dSIan Lepore /*
76479e7c44SIan Lepore * We use dmtimer2 for eventtimer and dmtimer3 for timecounter.
77fb962e6dSIan Lepore */
78479e7c44SIan Lepore #define ET_TMR_NUM 2
79479e7c44SIan Lepore #define TC_TMR_NUM 3
80fb962e6dSIan Lepore
81479e7c44SIan Lepore /* List of compatible strings for FDT tree */
82479e7c44SIan Lepore static struct ofw_compat_data compat_data[] = {
83479e7c44SIan Lepore {"ti,am335x-timer", 1},
84479e7c44SIan Lepore {"ti,am335x-timer-1ms", 1},
85479e7c44SIan Lepore {NULL, 0},
86fb962e6dSIan Lepore };
87fb962e6dSIan Lepore
88479e7c44SIan Lepore #define DMTIMER_READ4(sc, reg) bus_read_4((sc)->tmr_mem_res, (reg))
89479e7c44SIan Lepore #define DMTIMER_WRITE4(sc, reg, val) bus_write_4((sc)->tmr_mem_res, (reg), (val))
90e53470feSOleksandr Tymoshenko
91e53470feSOleksandr Tymoshenko static int
am335x_dmtimer_et_start(struct eventtimer * et,sbintime_t first,sbintime_t period)92479e7c44SIan Lepore am335x_dmtimer_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
93e53470feSOleksandr Tymoshenko {
9497247a2aSIan Lepore struct am335x_dmtimer_softc *sc;
95fb962e6dSIan Lepore uint32_t initial_count, reload_count;
96e53470feSOleksandr Tymoshenko
9797247a2aSIan Lepore sc = et->et_priv;
9897247a2aSIan Lepore
99fb962e6dSIan Lepore /*
100fb962e6dSIan Lepore * Stop the timer before changing it. This routine will often be called
101fb962e6dSIan Lepore * while the timer is still running, to either lengthen or shorten the
102fb962e6dSIan Lepore * current event time. We need to ensure the timer doesn't expire while
103fb962e6dSIan Lepore * we're working with it.
104fb962e6dSIan Lepore *
105fb962e6dSIan Lepore * Also clear any pending interrupt status, because it's at least
106fb962e6dSIan Lepore * theoretically possible that we're running in a primary interrupt
107fb962e6dSIan Lepore * context now, and a timer interrupt could be pending even before we
108fb962e6dSIan Lepore * stopped the timer. The more likely case is that we're being called
109fb962e6dSIan Lepore * from the et_event_cb() routine dispatched from our own handler, but
110fb962e6dSIan Lepore * it's not clear to me that that's the only case possible.
111fb962e6dSIan Lepore */
1125b03aba6SOleksandr Tymoshenko sc->tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
1135b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
1145b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
115fb962e6dSIan Lepore
116fdc5dd2dSAlexander Motin if (period != 0) {
117fb962e6dSIan Lepore reload_count = ((uint32_t)et->et_frequency * period) >> 32;
1185b03aba6SOleksandr Tymoshenko sc->tclr |= DMT_TCLR_AUTOLOAD;
119e53470feSOleksandr Tymoshenko } else {
120fb962e6dSIan Lepore reload_count = 0;
121e53470feSOleksandr Tymoshenko }
122e53470feSOleksandr Tymoshenko
123fdc5dd2dSAlexander Motin if (first != 0)
124fb962e6dSIan Lepore initial_count = ((uint32_t)et->et_frequency * first) >> 32;
125fdc5dd2dSAlexander Motin else
126fb962e6dSIan Lepore initial_count = reload_count;
127e53470feSOleksandr Tymoshenko
128fb962e6dSIan Lepore /*
129fb962e6dSIan Lepore * Set auto-reload and current-count values. This timer hardware counts
130fb962e6dSIan Lepore * up from the initial/reload value and interrupts on the zero rollover.
131fb962e6dSIan Lepore */
1325b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TLDR, 0xFFFFFFFF - reload_count);
1335b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TCRR, 0xFFFFFFFF - initial_count);
134e53470feSOleksandr Tymoshenko
135fb962e6dSIan Lepore /* Enable overflow interrupt, and start the timer. */
1365b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_IRQENABLE_SET, DMT_IRQ_OVF);
1375b03aba6SOleksandr Tymoshenko sc->tclr |= DMT_TCLR_START;
1385b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
139e53470feSOleksandr Tymoshenko
140e53470feSOleksandr Tymoshenko return (0);
141e53470feSOleksandr Tymoshenko }
142e53470feSOleksandr Tymoshenko
143e53470feSOleksandr Tymoshenko static int
am335x_dmtimer_et_stop(struct eventtimer * et)144479e7c44SIan Lepore am335x_dmtimer_et_stop(struct eventtimer *et)
145e53470feSOleksandr Tymoshenko {
14697247a2aSIan Lepore struct am335x_dmtimer_softc *sc;
14797247a2aSIan Lepore
14897247a2aSIan Lepore sc = et->et_priv;
149e53470feSOleksandr Tymoshenko
150fb962e6dSIan Lepore /* Stop timer, disable and clear interrupt. */
1515b03aba6SOleksandr Tymoshenko sc->tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
1525b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
1535b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_IRQENABLE_CLR, DMT_IRQ_OVF);
1545b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
155e53470feSOleksandr Tymoshenko return (0);
156e53470feSOleksandr Tymoshenko }
157e53470feSOleksandr Tymoshenko
158e53470feSOleksandr Tymoshenko static int
am335x_dmtimer_et_intr(void * arg)159479e7c44SIan Lepore am335x_dmtimer_et_intr(void *arg)
160e53470feSOleksandr Tymoshenko {
16197247a2aSIan Lepore struct am335x_dmtimer_softc *sc;
162e53470feSOleksandr Tymoshenko
16397247a2aSIan Lepore sc = arg;
164fb962e6dSIan Lepore
165fb962e6dSIan Lepore /* Ack the interrupt, and invoke the callback if it's still enabled. */
1665b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
1675b03aba6SOleksandr Tymoshenko if (sc->func.et.et_active)
1685b03aba6SOleksandr Tymoshenko sc->func.et.et_event_cb(&sc->func.et, sc->func.et.et_arg);
169e53470feSOleksandr Tymoshenko
170e53470feSOleksandr Tymoshenko return (FILTER_HANDLED);
171e53470feSOleksandr Tymoshenko }
172e53470feSOleksandr Tymoshenko
173479e7c44SIan Lepore static int
am335x_dmtimer_et_init(struct am335x_dmtimer_softc * sc)174479e7c44SIan Lepore am335x_dmtimer_et_init(struct am335x_dmtimer_softc *sc)
175479e7c44SIan Lepore {
176479e7c44SIan Lepore KASSERT(am335x_dmtimer_et_sc == NULL, ("already have an eventtimer"));
177479e7c44SIan Lepore
1785b03aba6SOleksandr Tymoshenko /*
179479e7c44SIan Lepore * Setup eventtimer interrupt handling. Panic if anything goes wrong,
180479e7c44SIan Lepore * because the system just isn't going to run without an eventtimer.
1815b03aba6SOleksandr Tymoshenko */
182479e7c44SIan Lepore sc->tmr_irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
183479e7c44SIan Lepore &sc->tmr_irq_rid, RF_ACTIVE);
184479e7c44SIan Lepore if (sc->tmr_irq_res == NULL)
185479e7c44SIan Lepore panic("am335x_dmtimer: could not allocate irq resources");
1865b03aba6SOleksandr Tymoshenko if (bus_setup_intr(sc->dev, sc->tmr_irq_res, INTR_TYPE_CLK,
187479e7c44SIan Lepore am335x_dmtimer_et_intr, NULL, sc, &sc->tmr_irq_handler) != 0)
188479e7c44SIan Lepore panic("am335x_dmtimer: count not setup irq handler");
1895b03aba6SOleksandr Tymoshenko
190479e7c44SIan Lepore sc->func.et.et_name = sc->tmr_name;
1915b03aba6SOleksandr Tymoshenko sc->func.et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
192479e7c44SIan Lepore sc->func.et.et_quality = 500;
1935b03aba6SOleksandr Tymoshenko sc->func.et.et_frequency = sc->sysclk_freq;
1945b03aba6SOleksandr Tymoshenko sc->func.et.et_min_period =
1955b03aba6SOleksandr Tymoshenko ((0x00000005LLU << 32) / sc->func.et.et_frequency);
1965b03aba6SOleksandr Tymoshenko sc->func.et.et_max_period =
1975b03aba6SOleksandr Tymoshenko (0xfffffffeLLU << 32) / sc->func.et.et_frequency;
198479e7c44SIan Lepore sc->func.et.et_start = am335x_dmtimer_et_start;
199479e7c44SIan Lepore sc->func.et.et_stop = am335x_dmtimer_et_stop;
2005b03aba6SOleksandr Tymoshenko sc->func.et.et_priv = sc;
2015b03aba6SOleksandr Tymoshenko
2025b03aba6SOleksandr Tymoshenko am335x_dmtimer_et_sc = sc;
203479e7c44SIan Lepore et_register(&sc->func.et);
2045b03aba6SOleksandr Tymoshenko
2055b03aba6SOleksandr Tymoshenko return (0);
2065b03aba6SOleksandr Tymoshenko }
2075b03aba6SOleksandr Tymoshenko
208479e7c44SIan Lepore static unsigned
am335x_dmtimer_tc_get_timecount(struct timecounter * tc)209479e7c44SIan Lepore am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
2105b03aba6SOleksandr Tymoshenko {
211479e7c44SIan Lepore struct am335x_dmtimer_softc *sc;
212479e7c44SIan Lepore
213479e7c44SIan Lepore sc = tc->tc_priv;
214479e7c44SIan Lepore
215479e7c44SIan Lepore return (DMTIMER_READ4(sc, DMT_TCRR));
216479e7c44SIan Lepore }
217479e7c44SIan Lepore
218479e7c44SIan Lepore static int
am335x_dmtimer_tc_init(struct am335x_dmtimer_softc * sc)219479e7c44SIan Lepore am335x_dmtimer_tc_init(struct am335x_dmtimer_softc *sc)
220479e7c44SIan Lepore {
221479e7c44SIan Lepore KASSERT(am335x_dmtimer_tc_sc == NULL, ("already have a timecounter"));
2225b03aba6SOleksandr Tymoshenko
2235b03aba6SOleksandr Tymoshenko /* Set up timecounter, start it, register it. */
2245b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);
2255b03aba6SOleksandr Tymoshenko while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
2265b03aba6SOleksandr Tymoshenko continue;
2275b03aba6SOleksandr Tymoshenko
2285b03aba6SOleksandr Tymoshenko sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;
2295b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TLDR, 0);
2305b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TCRR, 0);
2315b03aba6SOleksandr Tymoshenko DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
2325b03aba6SOleksandr Tymoshenko
233479e7c44SIan Lepore sc->func.tc.tc_name = sc->tmr_name;
2345b03aba6SOleksandr Tymoshenko sc->func.tc.tc_get_timecount = am335x_dmtimer_tc_get_timecount;
2355b03aba6SOleksandr Tymoshenko sc->func.tc.tc_counter_mask = ~0u;
2365b03aba6SOleksandr Tymoshenko sc->func.tc.tc_frequency = sc->sysclk_freq;
237479e7c44SIan Lepore sc->func.tc.tc_quality = 500;
2385b03aba6SOleksandr Tymoshenko sc->func.tc.tc_priv = sc;
2395b03aba6SOleksandr Tymoshenko
2405b03aba6SOleksandr Tymoshenko am335x_dmtimer_tc_sc = sc;
241479e7c44SIan Lepore tc_init(&sc->func.tc);
2425b03aba6SOleksandr Tymoshenko
2438fcbb323SAndrew Turner arm_set_delay(am335x_dmtimer_delay, sc);
2448fcbb323SAndrew Turner
2455b03aba6SOleksandr Tymoshenko return (0);
2465b03aba6SOleksandr Tymoshenko }
2475b03aba6SOleksandr Tymoshenko
248e53470feSOleksandr Tymoshenko static int
am335x_dmtimer_probe(device_t dev)249e53470feSOleksandr Tymoshenko am335x_dmtimer_probe(device_t dev)
250e53470feSOleksandr Tymoshenko {
251479e7c44SIan Lepore int tmr_num;
2520050ea24SMichal Meloun uint64_t rev_address;
253e53470feSOleksandr Tymoshenko
254add35ed5SIan Lepore if (!ofw_bus_status_okay(dev))
255add35ed5SIan Lepore return (ENXIO);
256add35ed5SIan Lepore
257479e7c44SIan Lepore if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
258e53470feSOleksandr Tymoshenko return (ENXIO);
259479e7c44SIan Lepore
260479e7c44SIan Lepore /*
2610050ea24SMichal Meloun * Get the hardware unit number from address of rev register.
262479e7c44SIan Lepore * If this isn't the hardware unit we're going to use for either the
263479e7c44SIan Lepore * eventtimer or the timecounter, no point in instantiating the device.
264479e7c44SIan Lepore */
2650050ea24SMichal Meloun rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
2660050ea24SMichal Meloun switch (rev_address) {
2670050ea24SMichal Meloun case DMTIMER2_REV:
2680050ea24SMichal Meloun tmr_num = 2;
2690050ea24SMichal Meloun break;
2700050ea24SMichal Meloun case DMTIMER3_REV:
2710050ea24SMichal Meloun tmr_num = 3;
2720050ea24SMichal Meloun break;
2730050ea24SMichal Meloun default:
2740050ea24SMichal Meloun /* Not DMTIMER2 or DMTIMER3 */
275479e7c44SIan Lepore return (ENXIO);
2760050ea24SMichal Meloun }
277479e7c44SIan Lepore
278*332f00cdSOskar Holmlund device_set_descf(dev, "AM335x DMTimer%d", tmr_num);
279479e7c44SIan Lepore
280479e7c44SIan Lepore return(BUS_PROBE_DEFAULT);
281e53470feSOleksandr Tymoshenko }
282e53470feSOleksandr Tymoshenko
283e53470feSOleksandr Tymoshenko static int
am335x_dmtimer_attach(device_t dev)284e53470feSOleksandr Tymoshenko am335x_dmtimer_attach(device_t dev)
285e53470feSOleksandr Tymoshenko {
28697247a2aSIan Lepore struct am335x_dmtimer_softc *sc;
287479e7c44SIan Lepore int err;
2880050ea24SMichal Meloun uint64_t rev_address;
2890050ea24SMichal Meloun clk_t sys_clkin;
290e53470feSOleksandr Tymoshenko
29197247a2aSIan Lepore sc = device_get_softc(dev);
2925b03aba6SOleksandr Tymoshenko sc->dev = dev;
293e53470feSOleksandr Tymoshenko
2940050ea24SMichal Meloun /* expect one clock */
2950050ea24SMichal Meloun err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck);
2960050ea24SMichal Meloun if (err != 0) {
2970050ea24SMichal Meloun device_printf(dev, "Cant find clock index 0. err: %d\n", err);
2980050ea24SMichal Meloun return (ENXIO);
2990050ea24SMichal Meloun }
3000050ea24SMichal Meloun
3010050ea24SMichal Meloun err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin);
3020050ea24SMichal Meloun if (err != 0) {
3030050ea24SMichal Meloun device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err);
3040050ea24SMichal Meloun return (ENXIO);
3050050ea24SMichal Meloun }
3060050ea24SMichal Meloun
3070050ea24SMichal Meloun /* Select M_OSC as DPLL parent */
3080050ea24SMichal Meloun err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin);
3090050ea24SMichal Meloun if (err != 0) {
3100050ea24SMichal Meloun device_printf(dev, "Cant set mux to CLK_M_OSC\n");
3110050ea24SMichal Meloun return (ENXIO);
3120050ea24SMichal Meloun }
313479e7c44SIan Lepore
314479e7c44SIan Lepore /* Enable clocks and power on the device. */
3150050ea24SMichal Meloun err = ti_sysc_clock_enable(device_get_parent(dev));
3160050ea24SMichal Meloun if (err != 0) {
3170050ea24SMichal Meloun device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err);
318e53470feSOleksandr Tymoshenko return (ENXIO);
3190050ea24SMichal Meloun }
3200050ea24SMichal Meloun
3210050ea24SMichal Meloun /* Get the base clock frequency. */
3220050ea24SMichal Meloun err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq);
3230050ea24SMichal Meloun if (err != 0) {
3240050ea24SMichal Meloun device_printf(dev, "Cant get sysclk frequency, err %d\n", err);
3250050ea24SMichal Meloun return (ENXIO);
3260050ea24SMichal Meloun }
327e53470feSOleksandr Tymoshenko
32897247a2aSIan Lepore /* Request the memory resources. */
3295b03aba6SOleksandr Tymoshenko sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
3305b03aba6SOleksandr Tymoshenko &sc->tmr_mem_rid, RF_ACTIVE);
3315b03aba6SOleksandr Tymoshenko if (sc->tmr_mem_res == NULL) {
332e53470feSOleksandr Tymoshenko return (ENXIO);
333e53470feSOleksandr Tymoshenko }
334e53470feSOleksandr Tymoshenko
3350050ea24SMichal Meloun rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
3360050ea24SMichal Meloun switch (rev_address) {
3370050ea24SMichal Meloun case DMTIMER2_REV:
3380050ea24SMichal Meloun sc->tmr_num = 2;
3390050ea24SMichal Meloun break;
3400050ea24SMichal Meloun case DMTIMER3_REV:
3410050ea24SMichal Meloun sc->tmr_num = 3;
3420050ea24SMichal Meloun break;
3430050ea24SMichal Meloun default:
3440050ea24SMichal Meloun device_printf(dev, "Not timer 2 or 3! %#jx\n",
3450050ea24SMichal Meloun rev_address);
3460050ea24SMichal Meloun return (ENXIO);
3470050ea24SMichal Meloun }
3480050ea24SMichal Meloun
349479e7c44SIan Lepore snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
350e53470feSOleksandr Tymoshenko
351479e7c44SIan Lepore /*
352479e7c44SIan Lepore * Go set up either a timecounter or eventtimer. We wouldn't have
353479e7c44SIan Lepore * attached if we weren't one or the other.
354479e7c44SIan Lepore */
355479e7c44SIan Lepore if (sc->tmr_num == ET_TMR_NUM)
356479e7c44SIan Lepore am335x_dmtimer_et_init(sc);
357479e7c44SIan Lepore else if (sc->tmr_num == TC_TMR_NUM)
358479e7c44SIan Lepore am335x_dmtimer_tc_init(sc);
359479e7c44SIan Lepore else
360479e7c44SIan Lepore panic("am335x_dmtimer: bad timer number %d", sc->tmr_num);
361fb962e6dSIan Lepore
362e53470feSOleksandr Tymoshenko return (0);
363e53470feSOleksandr Tymoshenko }
364e53470feSOleksandr Tymoshenko
365e53470feSOleksandr Tymoshenko static device_method_t am335x_dmtimer_methods[] = {
366e53470feSOleksandr Tymoshenko DEVMETHOD(device_probe, am335x_dmtimer_probe),
367e53470feSOleksandr Tymoshenko DEVMETHOD(device_attach, am335x_dmtimer_attach),
368e53470feSOleksandr Tymoshenko { 0, 0 }
369e53470feSOleksandr Tymoshenko };
370e53470feSOleksandr Tymoshenko
371e53470feSOleksandr Tymoshenko static driver_t am335x_dmtimer_driver = {
372e53470feSOleksandr Tymoshenko "am335x_dmtimer",
373e53470feSOleksandr Tymoshenko am335x_dmtimer_methods,
374e53470feSOleksandr Tymoshenko sizeof(struct am335x_dmtimer_softc),
375e53470feSOleksandr Tymoshenko };
376e53470feSOleksandr Tymoshenko
3778537e671SJohn Baldwin DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, 0, 0);
3780050ea24SMichal Meloun MODULE_DEPEND(am335x_dmtimer, ti_sysc, 1, 1, 1);
379e53470feSOleksandr Tymoshenko
3808fcbb323SAndrew Turner static void
am335x_dmtimer_delay(int usec,void * arg)3818fcbb323SAndrew Turner am335x_dmtimer_delay(int usec, void *arg)
382e53470feSOleksandr Tymoshenko {
3838fcbb323SAndrew Turner struct am335x_dmtimer_softc *sc = arg;
384e53470feSOleksandr Tymoshenko int32_t counts;
385e53470feSOleksandr Tymoshenko uint32_t first, last;
386e53470feSOleksandr Tymoshenko
387e53470feSOleksandr Tymoshenko /* Get the number of times to count */
38897247a2aSIan Lepore counts = (usec + 1) * (sc->sysclk_freq / 1000000);
389e53470feSOleksandr Tymoshenko
3905b03aba6SOleksandr Tymoshenko first = DMTIMER_READ4(sc, DMT_TCRR);
391e53470feSOleksandr Tymoshenko
392e53470feSOleksandr Tymoshenko while (counts > 0) {
3935b03aba6SOleksandr Tymoshenko last = DMTIMER_READ4(sc, DMT_TCRR);
394e53470feSOleksandr Tymoshenko if (last > first) {
395e53470feSOleksandr Tymoshenko counts -= (int32_t)(last - first);
396e53470feSOleksandr Tymoshenko } else {
397e53470feSOleksandr Tymoshenko counts -= (int32_t)((0xFFFFFFFF - first) + last);
398e53470feSOleksandr Tymoshenko }
399e53470feSOleksandr Tymoshenko first = last;
400e53470feSOleksandr Tymoshenko }
401e53470feSOleksandr Tymoshenko }
402