xref: /freebsd/sys/arm/freescale/imx/imx_epit.c (revision fc0dd0d307816b52bfb4fa8ea24d63ec0752a30b)
1*fc0dd0d3SIan Lepore /*-
2*fc0dd0d3SIan Lepore  * Copyright (c) 2017 Ian Lepore <ian@freebsd.org>
3*fc0dd0d3SIan Lepore  * All rights reserved.
4*fc0dd0d3SIan Lepore  *
5*fc0dd0d3SIan Lepore  * Redistribution and use in source and binary forms, with or without
6*fc0dd0d3SIan Lepore  * modification, are permitted provided that the following conditions
7*fc0dd0d3SIan Lepore  * are met:
8*fc0dd0d3SIan Lepore  * 1. Redistributions of source code must retain the above copyright
9*fc0dd0d3SIan Lepore  *    notice, this list of conditions and the following disclaimer.
10*fc0dd0d3SIan Lepore  * 2. Redistributions in binary form must reproduce the above copyright
11*fc0dd0d3SIan Lepore  *    notice, this list of conditions and the following disclaimer in the
12*fc0dd0d3SIan Lepore  *    documentation and/or other materials provided with the distribution.
13*fc0dd0d3SIan Lepore  *
14*fc0dd0d3SIan Lepore  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*fc0dd0d3SIan Lepore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*fc0dd0d3SIan Lepore  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*fc0dd0d3SIan Lepore  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*fc0dd0d3SIan Lepore  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*fc0dd0d3SIan Lepore  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*fc0dd0d3SIan Lepore  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*fc0dd0d3SIan Lepore  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*fc0dd0d3SIan Lepore  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*fc0dd0d3SIan Lepore  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*fc0dd0d3SIan Lepore  * SUCH DAMAGE.
25*fc0dd0d3SIan Lepore  */
26*fc0dd0d3SIan Lepore 
27*fc0dd0d3SIan Lepore #include <sys/cdefs.h>
28*fc0dd0d3SIan Lepore __FBSDID("$FreeBSD$");
29*fc0dd0d3SIan Lepore 
30*fc0dd0d3SIan Lepore /*
31*fc0dd0d3SIan Lepore  * Driver for imx Enhanced Programmable Interval Timer, a simple free-running
32*fc0dd0d3SIan Lepore  * counter device that can be used as the system timecounter.  On imx5 a second
33*fc0dd0d3SIan Lepore  * instance of the device is used as the system eventtimer.
34*fc0dd0d3SIan Lepore  */
35*fc0dd0d3SIan Lepore 
36*fc0dd0d3SIan Lepore #include <sys/param.h>
37*fc0dd0d3SIan Lepore #include <sys/systm.h>
38*fc0dd0d3SIan Lepore #include <sys/bus.h>
39*fc0dd0d3SIan Lepore #include <sys/kernel.h>
40*fc0dd0d3SIan Lepore #include <sys/module.h>
41*fc0dd0d3SIan Lepore #include <sys/malloc.h>
42*fc0dd0d3SIan Lepore #include <sys/rman.h>
43*fc0dd0d3SIan Lepore #include <sys/timeet.h>
44*fc0dd0d3SIan Lepore #include <sys/timetc.h>
45*fc0dd0d3SIan Lepore #include <sys/watchdog.h>
46*fc0dd0d3SIan Lepore #include <machine/bus.h>
47*fc0dd0d3SIan Lepore #include <machine/cpu.h>
48*fc0dd0d3SIan Lepore #include <machine/intr.h>
49*fc0dd0d3SIan Lepore #include <machine/machdep.h>
50*fc0dd0d3SIan Lepore 
51*fc0dd0d3SIan Lepore #include <dev/fdt/fdt_common.h>
52*fc0dd0d3SIan Lepore #include <dev/ofw/openfirm.h>
53*fc0dd0d3SIan Lepore #include <dev/ofw/ofw_bus.h>
54*fc0dd0d3SIan Lepore #include <dev/ofw/ofw_bus_subr.h>
55*fc0dd0d3SIan Lepore 
56*fc0dd0d3SIan Lepore #include <arm/freescale/imx/imx_ccmvar.h>
57*fc0dd0d3SIan Lepore #include <arm/freescale/imx/imx_machdep.h>
58*fc0dd0d3SIan Lepore 
59*fc0dd0d3SIan Lepore #define	EPIT_CR				0x00		/* Control register */
60*fc0dd0d3SIan Lepore #define	  EPIT_CR_CLKSRC_SHIFT		  24
61*fc0dd0d3SIan Lepore #define	  EPIT_CR_CLKSRC_OFF		   0
62*fc0dd0d3SIan Lepore #define	  EPIT_CR_CLKSRC_IPG		   1
63*fc0dd0d3SIan Lepore #define	  EPIT_CR_CLKSRC_HFCLK		   2
64*fc0dd0d3SIan Lepore #define	  EPIT_CR_CLKSRC_LFCLK		   3
65*fc0dd0d3SIan Lepore #define	  EPIT_CR_STOPEN		  (1u << 21)
66*fc0dd0d3SIan Lepore #define	  EPIT_CR_WAITEN		  (1u << 19)
67*fc0dd0d3SIan Lepore #define	  EPIT_CR_DBGEN			  (1u << 18)
68*fc0dd0d3SIan Lepore #define	  EPIT_CR_IOVW			  (1u << 17)
69*fc0dd0d3SIan Lepore #define	  EPIT_CR_SWR			  (1u << 16)
70*fc0dd0d3SIan Lepore #define	  EPIT_CR_RLD			  (1u <<  3)
71*fc0dd0d3SIan Lepore #define	  EPIT_CR_OCIEN			  (1u <<  2)
72*fc0dd0d3SIan Lepore #define	  EPIT_CR_ENMOD			  (1u <<  1)
73*fc0dd0d3SIan Lepore #define	  EPIT_CR_EN			  (1u <<  0)
74*fc0dd0d3SIan Lepore 
75*fc0dd0d3SIan Lepore #define	EPIT_SR				0x04		/* Status register */
76*fc0dd0d3SIan Lepore #define	  EPIT_SR_OCIF			  (1u << 0)
77*fc0dd0d3SIan Lepore 
78*fc0dd0d3SIan Lepore #define	EPIT_LR				0x08		/* Load register */
79*fc0dd0d3SIan Lepore #define	EPIT_CMPR			0x0c		/* Compare register */
80*fc0dd0d3SIan Lepore #define	EPIT_CNR			0x10		/* Counter register */
81*fc0dd0d3SIan Lepore 
82*fc0dd0d3SIan Lepore /*
83*fc0dd0d3SIan Lepore  * Define event timer limits.
84*fc0dd0d3SIan Lepore  *
85*fc0dd0d3SIan Lepore  * In theory our minimum period is 1 tick, because to setup a oneshot we don't
86*fc0dd0d3SIan Lepore  * need a read-modify-write sequence to calculate and set a compare register
87*fc0dd0d3SIan Lepore  * value while the counter is running.  In practice the waveform diagrams in the
88*fc0dd0d3SIan Lepore  * manual make it appear that a setting of 1 might cause it to miss the event,
89*fc0dd0d3SIan Lepore  * so I'm setting the lower limit to 2 ticks.
90*fc0dd0d3SIan Lepore  */
91*fc0dd0d3SIan Lepore #define	ET_MIN_TICKS	2
92*fc0dd0d3SIan Lepore #define	ET_MAX_TICKS	0xfffffffe
93*fc0dd0d3SIan Lepore 
94*fc0dd0d3SIan Lepore static u_int epit_tc_get_timecount(struct timecounter *tc);
95*fc0dd0d3SIan Lepore 
96*fc0dd0d3SIan Lepore struct epit_softc {
97*fc0dd0d3SIan Lepore 	device_t 		dev;
98*fc0dd0d3SIan Lepore 	struct resource *	memres;
99*fc0dd0d3SIan Lepore 	struct resource *	intres;
100*fc0dd0d3SIan Lepore 	void *			inthandle;
101*fc0dd0d3SIan Lepore 	uint32_t 		clkfreq;
102*fc0dd0d3SIan Lepore 	uint32_t 		ctlreg;
103*fc0dd0d3SIan Lepore 	uint32_t		period;
104*fc0dd0d3SIan Lepore 	struct timecounter	tc;
105*fc0dd0d3SIan Lepore 	struct eventtimer	et;
106*fc0dd0d3SIan Lepore 	bool			oneshot;
107*fc0dd0d3SIan Lepore };
108*fc0dd0d3SIan Lepore 
109*fc0dd0d3SIan Lepore #ifndef MULTIDELAY
110*fc0dd0d3SIan Lepore /* Global softc pointer for use in DELAY(). */
111*fc0dd0d3SIan Lepore static struct epit_softc *epit_sc;
112*fc0dd0d3SIan Lepore #endif
113*fc0dd0d3SIan Lepore 
114*fc0dd0d3SIan Lepore /*
115*fc0dd0d3SIan Lepore  * Probe data.  For some reason, the standard linux dts files don't have
116*fc0dd0d3SIan Lepore  * compatible properties on the epit devices (other properties are missing too,
117*fc0dd0d3SIan Lepore  * like clocks, but we don't care as much about that).  So our probe routine
118*fc0dd0d3SIan Lepore  * uses the name of the node (must contain "epit") and the address of the
119*fc0dd0d3SIan Lepore  * registers as identifying marks.
120*fc0dd0d3SIan Lepore  */
121*fc0dd0d3SIan Lepore static const uint32_t imx51_epit_ioaddr[2] = {0x73fac000, 0x73fb0000};
122*fc0dd0d3SIan Lepore static const uint32_t imx53_epit_ioaddr[2] = {0x53fac000, 0x53fb0000};
123*fc0dd0d3SIan Lepore static const uint32_t imx6_epit_ioaddr[2]  = {0x020d0000, 0x020d4000};
124*fc0dd0d3SIan Lepore 
125*fc0dd0d3SIan Lepore /* ocd_data is number of units to instantiate on the platform */
126*fc0dd0d3SIan Lepore static struct ofw_compat_data compat_data[] = {
127*fc0dd0d3SIan Lepore 	{"fsl,imx6ul-epit", 1},
128*fc0dd0d3SIan Lepore 	{"fsl,imx6sx-epit", 1},
129*fc0dd0d3SIan Lepore 	{"fsl,imx6q-epit",  1},
130*fc0dd0d3SIan Lepore 	{"fsl,imx6dl-epit", 1},
131*fc0dd0d3SIan Lepore 	{"fsl,imx53-epit",  2},
132*fc0dd0d3SIan Lepore 	{"fsl,imx51-epit",  2},
133*fc0dd0d3SIan Lepore 	{"fsl,imx31-epit",  2},
134*fc0dd0d3SIan Lepore 	{"fsl,imx27-epit",  2},
135*fc0dd0d3SIan Lepore 	{"fsl,imx25-epit",  2},
136*fc0dd0d3SIan Lepore 	{NULL,              0}
137*fc0dd0d3SIan Lepore };
138*fc0dd0d3SIan Lepore 
139*fc0dd0d3SIan Lepore static inline uint32_t
140*fc0dd0d3SIan Lepore RD4(struct epit_softc *sc, bus_size_t offset)
141*fc0dd0d3SIan Lepore {
142*fc0dd0d3SIan Lepore 
143*fc0dd0d3SIan Lepore 	return (bus_read_4(sc->memres, offset));
144*fc0dd0d3SIan Lepore }
145*fc0dd0d3SIan Lepore 
146*fc0dd0d3SIan Lepore static inline void
147*fc0dd0d3SIan Lepore WR4(struct epit_softc *sc, bus_size_t offset, uint32_t value)
148*fc0dd0d3SIan Lepore {
149*fc0dd0d3SIan Lepore 
150*fc0dd0d3SIan Lepore 	bus_write_4(sc->memres, offset, value);
151*fc0dd0d3SIan Lepore }
152*fc0dd0d3SIan Lepore 
153*fc0dd0d3SIan Lepore static inline void
154*fc0dd0d3SIan Lepore WR4B(struct epit_softc *sc, bus_size_t offset, uint32_t value)
155*fc0dd0d3SIan Lepore {
156*fc0dd0d3SIan Lepore 
157*fc0dd0d3SIan Lepore 	bus_write_4(sc->memres, offset, value);
158*fc0dd0d3SIan Lepore 	bus_barrier(sc->memres, offset, 4, BUS_SPACE_BARRIER_WRITE);
159*fc0dd0d3SIan Lepore }
160*fc0dd0d3SIan Lepore 
161*fc0dd0d3SIan Lepore static u_int
162*fc0dd0d3SIan Lepore epit_read_counter(struct epit_softc *sc)
163*fc0dd0d3SIan Lepore {
164*fc0dd0d3SIan Lepore 
165*fc0dd0d3SIan Lepore 	/*
166*fc0dd0d3SIan Lepore 	 * Hardware is a downcounter, adjust to look like it counts up for use
167*fc0dd0d3SIan Lepore 	 * with timecounter and DELAY.
168*fc0dd0d3SIan Lepore 	 */
169*fc0dd0d3SIan Lepore 	return (0xffffffff - RD4(sc, EPIT_CNR));
170*fc0dd0d3SIan Lepore }
171*fc0dd0d3SIan Lepore 
172*fc0dd0d3SIan Lepore static void
173*fc0dd0d3SIan Lepore epit_do_delay(int usec, void *arg)
174*fc0dd0d3SIan Lepore {
175*fc0dd0d3SIan Lepore 	struct epit_softc *sc = arg;
176*fc0dd0d3SIan Lepore 	uint64_t curcnt, endcnt, startcnt, ticks;
177*fc0dd0d3SIan Lepore 
178*fc0dd0d3SIan Lepore 	/*
179*fc0dd0d3SIan Lepore 	 * Calculate the tick count with 64-bit values so that it works for any
180*fc0dd0d3SIan Lepore 	 * clock frequency.  Loop until the hardware count reaches start+ticks.
181*fc0dd0d3SIan Lepore 	 * If the 32-bit hardware count rolls over while we're looping, just
182*fc0dd0d3SIan Lepore 	 * manually do a carry into the high bits after each read; don't worry
183*fc0dd0d3SIan Lepore 	 * that doing this on each loop iteration is inefficient -- we're trying
184*fc0dd0d3SIan Lepore 	 * to waste time here.
185*fc0dd0d3SIan Lepore 	 */
186*fc0dd0d3SIan Lepore 	ticks = 1 + ((uint64_t)usec * sc->clkfreq) / 1000000;
187*fc0dd0d3SIan Lepore 	curcnt = startcnt = epit_read_counter(sc);
188*fc0dd0d3SIan Lepore 	endcnt = startcnt + ticks;
189*fc0dd0d3SIan Lepore 	while (curcnt < endcnt) {
190*fc0dd0d3SIan Lepore 		curcnt = epit_read_counter(sc);
191*fc0dd0d3SIan Lepore 		if (curcnt < startcnt)
192*fc0dd0d3SIan Lepore 			curcnt += 1ULL << 32;
193*fc0dd0d3SIan Lepore 	}
194*fc0dd0d3SIan Lepore }
195*fc0dd0d3SIan Lepore 
196*fc0dd0d3SIan Lepore static u_int
197*fc0dd0d3SIan Lepore epit_tc_get_timecount(struct timecounter *tc)
198*fc0dd0d3SIan Lepore {
199*fc0dd0d3SIan Lepore 
200*fc0dd0d3SIan Lepore 	return (epit_read_counter(tc->tc_priv));
201*fc0dd0d3SIan Lepore }
202*fc0dd0d3SIan Lepore 
203*fc0dd0d3SIan Lepore static int
204*fc0dd0d3SIan Lepore epit_tc_attach(struct epit_softc *sc)
205*fc0dd0d3SIan Lepore {
206*fc0dd0d3SIan Lepore 
207*fc0dd0d3SIan Lepore 	/* When the counter hits zero, reload with 0xffffffff.  Start it. */
208*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_LR, 0xffffffff);
209*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_CR, sc->ctlreg | EPIT_CR_EN);
210*fc0dd0d3SIan Lepore 
211*fc0dd0d3SIan Lepore 	/* Register as a timecounter. */
212*fc0dd0d3SIan Lepore 	sc->tc.tc_name          = "EPIT";
213*fc0dd0d3SIan Lepore 	sc->tc.tc_quality       = 1000;
214*fc0dd0d3SIan Lepore 	sc->tc.tc_frequency     = sc->clkfreq;
215*fc0dd0d3SIan Lepore 	sc->tc.tc_counter_mask  = 0xffffffff;
216*fc0dd0d3SIan Lepore 	sc->tc.tc_get_timecount = epit_tc_get_timecount;
217*fc0dd0d3SIan Lepore 	sc->tc.tc_priv          = sc;
218*fc0dd0d3SIan Lepore 	tc_init(&sc->tc);
219*fc0dd0d3SIan Lepore 
220*fc0dd0d3SIan Lepore 	/* We are the DELAY() implementation. */
221*fc0dd0d3SIan Lepore #ifdef MULTIDELAY
222*fc0dd0d3SIan Lepore 	arm_set_delay(epit_do_delay, sc);
223*fc0dd0d3SIan Lepore #else
224*fc0dd0d3SIan Lepore 	epit_sc = sc;
225*fc0dd0d3SIan Lepore #endif
226*fc0dd0d3SIan Lepore 	return (0);
227*fc0dd0d3SIan Lepore }
228*fc0dd0d3SIan Lepore 
229*fc0dd0d3SIan Lepore static int
230*fc0dd0d3SIan Lepore epit_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
231*fc0dd0d3SIan Lepore {
232*fc0dd0d3SIan Lepore 	struct epit_softc *sc;
233*fc0dd0d3SIan Lepore 	uint32_t ticks;
234*fc0dd0d3SIan Lepore 
235*fc0dd0d3SIan Lepore 	sc = (struct epit_softc *)et->et_priv;
236*fc0dd0d3SIan Lepore 
237*fc0dd0d3SIan Lepore 	/*
238*fc0dd0d3SIan Lepore 	 * Disable the timer and clear any pending status.  The timer may be
239*fc0dd0d3SIan Lepore 	 * running or may have just expired if we're called to reschedule the
240*fc0dd0d3SIan Lepore 	 * next event before the previous event time arrives.
241*fc0dd0d3SIan Lepore 	 */
242*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_CR, sc->ctlreg);
243*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_SR, EPIT_SR_OCIF);
244*fc0dd0d3SIan Lepore 	if (period != 0) {
245*fc0dd0d3SIan Lepore 		sc->oneshot = false;
246*fc0dd0d3SIan Lepore 		ticks = ((uint32_t)et->et_frequency * period) >> 32;
247*fc0dd0d3SIan Lepore 	} else if (first != 0) {
248*fc0dd0d3SIan Lepore 		sc->oneshot = true;
249*fc0dd0d3SIan Lepore 		ticks = ((uint32_t)et->et_frequency * first) >> 32;
250*fc0dd0d3SIan Lepore 	} else {
251*fc0dd0d3SIan Lepore 		return (EINVAL);
252*fc0dd0d3SIan Lepore 	}
253*fc0dd0d3SIan Lepore 
254*fc0dd0d3SIan Lepore 	/* Set the countdown load register and start the timer. */
255*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_LR, ticks);
256*fc0dd0d3SIan Lepore 	WR4B(sc, EPIT_CR, sc->ctlreg | EPIT_CR_EN);
257*fc0dd0d3SIan Lepore 
258*fc0dd0d3SIan Lepore 	return (0);
259*fc0dd0d3SIan Lepore }
260*fc0dd0d3SIan Lepore 
261*fc0dd0d3SIan Lepore static int
262*fc0dd0d3SIan Lepore epit_et_stop(struct eventtimer *et)
263*fc0dd0d3SIan Lepore {
264*fc0dd0d3SIan Lepore 	struct epit_softc *sc;
265*fc0dd0d3SIan Lepore 
266*fc0dd0d3SIan Lepore 	sc = (struct epit_softc *)et->et_priv;
267*fc0dd0d3SIan Lepore 
268*fc0dd0d3SIan Lepore 	/* Disable the timer and clear any pending status. */
269*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_CR, sc->ctlreg);
270*fc0dd0d3SIan Lepore 	WR4B(sc, EPIT_SR, EPIT_SR_OCIF);
271*fc0dd0d3SIan Lepore 
272*fc0dd0d3SIan Lepore 	return (0);
273*fc0dd0d3SIan Lepore }
274*fc0dd0d3SIan Lepore 
275*fc0dd0d3SIan Lepore static int
276*fc0dd0d3SIan Lepore epit_intr(void *arg)
277*fc0dd0d3SIan Lepore {
278*fc0dd0d3SIan Lepore 	struct epit_softc *sc;
279*fc0dd0d3SIan Lepore 	uint32_t status;
280*fc0dd0d3SIan Lepore 
281*fc0dd0d3SIan Lepore 	sc = arg;
282*fc0dd0d3SIan Lepore 
283*fc0dd0d3SIan Lepore 	/*
284*fc0dd0d3SIan Lepore 	 * Disable a one-shot timer until a new event is scheduled so that the
285*fc0dd0d3SIan Lepore 	 * counter doesn't wrap and fire again.  Do this before clearing the
286*fc0dd0d3SIan Lepore 	 * status since a short period would make it fire again really soon.
287*fc0dd0d3SIan Lepore 	 *
288*fc0dd0d3SIan Lepore 	 * Clear interrupt status before invoking event callbacks.  The callback
289*fc0dd0d3SIan Lepore 	 * often sets up a new one-shot timer event and if the interval is short
290*fc0dd0d3SIan Lepore 	 * enough it can fire before we get out of this function.  If we cleared
291*fc0dd0d3SIan Lepore 	 * at the bottom we'd miss the interrupt and hang until the clock wraps.
292*fc0dd0d3SIan Lepore 	 */
293*fc0dd0d3SIan Lepore 	if (sc->oneshot)
294*fc0dd0d3SIan Lepore 		WR4(sc, EPIT_CR, sc->ctlreg);
295*fc0dd0d3SIan Lepore 
296*fc0dd0d3SIan Lepore 	status = RD4(sc, EPIT_SR);
297*fc0dd0d3SIan Lepore 	WR4B(sc, EPIT_SR, status);
298*fc0dd0d3SIan Lepore 
299*fc0dd0d3SIan Lepore 	if ((status & EPIT_SR_OCIF) == 0)
300*fc0dd0d3SIan Lepore 		return (FILTER_STRAY);
301*fc0dd0d3SIan Lepore 
302*fc0dd0d3SIan Lepore 	if (sc->et.et_active)
303*fc0dd0d3SIan Lepore 		sc->et.et_event_cb(&sc->et, sc->et.et_arg);
304*fc0dd0d3SIan Lepore 
305*fc0dd0d3SIan Lepore 	return (FILTER_HANDLED);
306*fc0dd0d3SIan Lepore }
307*fc0dd0d3SIan Lepore 
308*fc0dd0d3SIan Lepore static int
309*fc0dd0d3SIan Lepore epit_et_attach(struct epit_softc *sc)
310*fc0dd0d3SIan Lepore {
311*fc0dd0d3SIan Lepore 	int err, rid;
312*fc0dd0d3SIan Lepore 
313*fc0dd0d3SIan Lepore 	rid = 0;
314*fc0dd0d3SIan Lepore 	sc->intres = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &rid,
315*fc0dd0d3SIan Lepore 	    RF_ACTIVE);
316*fc0dd0d3SIan Lepore 	if (sc->intres == NULL) {
317*fc0dd0d3SIan Lepore 		device_printf(sc->dev, "could not allocate interrupt\n");
318*fc0dd0d3SIan Lepore 		return (ENXIO);
319*fc0dd0d3SIan Lepore 	}
320*fc0dd0d3SIan Lepore 
321*fc0dd0d3SIan Lepore 	err = bus_setup_intr(sc->dev, sc->intres, INTR_TYPE_CLK | INTR_MPSAFE,
322*fc0dd0d3SIan Lepore 	    epit_intr, NULL, sc, &sc->inthandle);
323*fc0dd0d3SIan Lepore 	if (err != 0) {
324*fc0dd0d3SIan Lepore 		device_printf(sc->dev, "unable to setup the irq handler\n");
325*fc0dd0d3SIan Lepore 		return (err);
326*fc0dd0d3SIan Lepore 	}
327*fc0dd0d3SIan Lepore 
328*fc0dd0d3SIan Lepore 	/* To be an eventtimer, we need interrupts enabled. */
329*fc0dd0d3SIan Lepore 	sc->ctlreg |= EPIT_CR_OCIEN;
330*fc0dd0d3SIan Lepore 
331*fc0dd0d3SIan Lepore 	/* Register as an eventtimer. */
332*fc0dd0d3SIan Lepore 	sc->et.et_name = "EPIT";
333*fc0dd0d3SIan Lepore 	sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
334*fc0dd0d3SIan Lepore 	sc->et.et_quality = 1000;
335*fc0dd0d3SIan Lepore 	sc->et.et_frequency = sc->clkfreq;
336*fc0dd0d3SIan Lepore 	sc->et.et_min_period = ((uint64_t)ET_MIN_TICKS  << 32) / sc->clkfreq;
337*fc0dd0d3SIan Lepore 	sc->et.et_max_period = ((uint64_t)ET_MAX_TICKS  << 32) / sc->clkfreq;
338*fc0dd0d3SIan Lepore 	sc->et.et_start = epit_et_start;
339*fc0dd0d3SIan Lepore 	sc->et.et_stop = epit_et_stop;
340*fc0dd0d3SIan Lepore 	sc->et.et_priv = sc;
341*fc0dd0d3SIan Lepore 	et_register(&sc->et);
342*fc0dd0d3SIan Lepore 
343*fc0dd0d3SIan Lepore 	return (0);
344*fc0dd0d3SIan Lepore }
345*fc0dd0d3SIan Lepore 
346*fc0dd0d3SIan Lepore static int
347*fc0dd0d3SIan Lepore epit_probe(device_t dev)
348*fc0dd0d3SIan Lepore {
349*fc0dd0d3SIan Lepore 	struct resource *memres;
350*fc0dd0d3SIan Lepore 	rman_res_t ioaddr;
351*fc0dd0d3SIan Lepore 	int num_units, rid, unit;
352*fc0dd0d3SIan Lepore 
353*fc0dd0d3SIan Lepore 	if (!ofw_bus_status_okay(dev))
354*fc0dd0d3SIan Lepore 		return (ENXIO);
355*fc0dd0d3SIan Lepore 
356*fc0dd0d3SIan Lepore 	/*
357*fc0dd0d3SIan Lepore 	 * The FDT data for imx5 and imx6 EPIT hardware is missing or broken,
358*fc0dd0d3SIan Lepore 	 * but it may get fixed some day, so first just do a normal check.  We
359*fc0dd0d3SIan Lepore 	 * return success if the compatible string matches and we haven't
360*fc0dd0d3SIan Lepore 	 * already instantiated the number of units needed on this platform.
361*fc0dd0d3SIan Lepore 	 */
362*fc0dd0d3SIan Lepore 	unit = device_get_unit(dev);
363*fc0dd0d3SIan Lepore 	num_units = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
364*fc0dd0d3SIan Lepore 	if (unit < num_units) {
365*fc0dd0d3SIan Lepore 		device_set_desc(dev, "i.MX EPIT timer");
366*fc0dd0d3SIan Lepore 		return (BUS_PROBE_DEFAULT);
367*fc0dd0d3SIan Lepore 	}
368*fc0dd0d3SIan Lepore 
369*fc0dd0d3SIan Lepore 	/*
370*fc0dd0d3SIan Lepore 	 * No compat string match, but for imx6 all the data we need is in the
371*fc0dd0d3SIan Lepore 	 * node except the compat string, so do our own compatibility check
372*fc0dd0d3SIan Lepore 	 * using the device name of the node and the register block address.
373*fc0dd0d3SIan Lepore 	 */
374*fc0dd0d3SIan Lepore 	if (strstr(ofw_bus_get_name(dev), "epit") == NULL)
375*fc0dd0d3SIan Lepore 		return (ENXIO);
376*fc0dd0d3SIan Lepore 
377*fc0dd0d3SIan Lepore 	rid = 0;
378*fc0dd0d3SIan Lepore 	memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_UNMAPPED);
379*fc0dd0d3SIan Lepore 	if (memres == NULL)
380*fc0dd0d3SIan Lepore 		return (ENXIO);
381*fc0dd0d3SIan Lepore 	ioaddr = rman_get_start(memres);
382*fc0dd0d3SIan Lepore 	bus_free_resource(dev, SYS_RES_MEMORY, memres);
383*fc0dd0d3SIan Lepore 
384*fc0dd0d3SIan Lepore 	if (imx_soc_family() == 6) {
385*fc0dd0d3SIan Lepore 		if (unit > 0)
386*fc0dd0d3SIan Lepore 			return (ENXIO);
387*fc0dd0d3SIan Lepore 		if (ioaddr != imx6_epit_ioaddr[unit])
388*fc0dd0d3SIan Lepore 			return (ENXIO);
389*fc0dd0d3SIan Lepore 	} else {
390*fc0dd0d3SIan Lepore 		if (unit > 1)
391*fc0dd0d3SIan Lepore 			return (ENXIO);
392*fc0dd0d3SIan Lepore 		switch (imx_soc_type()) {
393*fc0dd0d3SIan Lepore 		case IMXSOC_51:
394*fc0dd0d3SIan Lepore 			if (ioaddr != imx51_epit_ioaddr[unit])
395*fc0dd0d3SIan Lepore 				return (ENXIO);
396*fc0dd0d3SIan Lepore 			break;
397*fc0dd0d3SIan Lepore 		case IMXSOC_53:
398*fc0dd0d3SIan Lepore 			if (ioaddr != imx53_epit_ioaddr[unit])
399*fc0dd0d3SIan Lepore 				return (ENXIO);
400*fc0dd0d3SIan Lepore 			break;
401*fc0dd0d3SIan Lepore 		default:
402*fc0dd0d3SIan Lepore 			return (ENXIO);
403*fc0dd0d3SIan Lepore 		}
404*fc0dd0d3SIan Lepore 		/*
405*fc0dd0d3SIan Lepore 		 * XXX Right now we have no way to handle the fact that the
406*fc0dd0d3SIan Lepore 		 * entire EPIT node is missing, which means no interrupt data.
407*fc0dd0d3SIan Lepore 		 */
408*fc0dd0d3SIan Lepore 		return (ENXIO);
409*fc0dd0d3SIan Lepore 	}
410*fc0dd0d3SIan Lepore 
411*fc0dd0d3SIan Lepore 	device_set_desc(dev, "i.MX EPIT timer");
412*fc0dd0d3SIan Lepore 	return (BUS_PROBE_DEFAULT);
413*fc0dd0d3SIan Lepore }
414*fc0dd0d3SIan Lepore 
415*fc0dd0d3SIan Lepore static int
416*fc0dd0d3SIan Lepore epit_attach(device_t dev)
417*fc0dd0d3SIan Lepore {
418*fc0dd0d3SIan Lepore 	struct epit_softc *sc;
419*fc0dd0d3SIan Lepore 	int err, rid;
420*fc0dd0d3SIan Lepore 	uint32_t clksrc;
421*fc0dd0d3SIan Lepore 
422*fc0dd0d3SIan Lepore 	sc = device_get_softc(dev);
423*fc0dd0d3SIan Lepore 	sc->dev = dev;
424*fc0dd0d3SIan Lepore 
425*fc0dd0d3SIan Lepore 	rid = 0;
426*fc0dd0d3SIan Lepore 	sc->memres = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid,
427*fc0dd0d3SIan Lepore 	    RF_ACTIVE);
428*fc0dd0d3SIan Lepore 	if (sc->memres == NULL) {
429*fc0dd0d3SIan Lepore 		device_printf(sc->dev, "could not allocate registers\n");
430*fc0dd0d3SIan Lepore 		return (ENXIO);
431*fc0dd0d3SIan Lepore 	}
432*fc0dd0d3SIan Lepore 
433*fc0dd0d3SIan Lepore 	/*
434*fc0dd0d3SIan Lepore 	 * For now, use ipg (66 MHz).  Some day we should get this from fdt.
435*fc0dd0d3SIan Lepore 	 */
436*fc0dd0d3SIan Lepore 	clksrc = EPIT_CR_CLKSRC_IPG;
437*fc0dd0d3SIan Lepore 
438*fc0dd0d3SIan Lepore 	switch (clksrc) {
439*fc0dd0d3SIan Lepore 	default:
440*fc0dd0d3SIan Lepore 		device_printf(dev,
441*fc0dd0d3SIan Lepore 		    "Unsupported clock source '%d', using IPG\n", clksrc);
442*fc0dd0d3SIan Lepore                 /* FALLTHROUGH */
443*fc0dd0d3SIan Lepore 	case EPIT_CR_CLKSRC_IPG:
444*fc0dd0d3SIan Lepore 		sc->clkfreq = imx_ccm_ipg_hz();
445*fc0dd0d3SIan Lepore 		break;
446*fc0dd0d3SIan Lepore 	case EPIT_CR_CLKSRC_HFCLK:
447*fc0dd0d3SIan Lepore 		sc->clkfreq = imx_ccm_perclk_hz();
448*fc0dd0d3SIan Lepore 		break;
449*fc0dd0d3SIan Lepore 	case EPIT_CR_CLKSRC_LFCLK:
450*fc0dd0d3SIan Lepore 		sc->clkfreq = 32768;
451*fc0dd0d3SIan Lepore 		break;
452*fc0dd0d3SIan Lepore 	}
453*fc0dd0d3SIan Lepore 
454*fc0dd0d3SIan Lepore 	/*
455*fc0dd0d3SIan Lepore 	 * Init: stop operations and clear all options, then set up options and
456*fc0dd0d3SIan Lepore 	 * clock source, then do a soft-reset and wait for it to complete.
457*fc0dd0d3SIan Lepore 	 */
458*fc0dd0d3SIan Lepore 	WR4(sc, EPIT_CR, 0);
459*fc0dd0d3SIan Lepore 
460*fc0dd0d3SIan Lepore 	sc->ctlreg =
461*fc0dd0d3SIan Lepore 	    (clksrc << EPIT_CR_CLKSRC_SHIFT) |  /* Use selected clock */
462*fc0dd0d3SIan Lepore 	    EPIT_CR_ENMOD  |                    /* Reload counter on enable */
463*fc0dd0d3SIan Lepore 	    EPIT_CR_RLD    |                    /* Reload counter from LR */
464*fc0dd0d3SIan Lepore 	    EPIT_CR_STOPEN |                    /* Run in STOP mode */
465*fc0dd0d3SIan Lepore 	    EPIT_CR_WAITEN |                    /* Run in WAIT mode */
466*fc0dd0d3SIan Lepore 	    EPIT_CR_DBGEN;                      /* Run in DEBUG mode */
467*fc0dd0d3SIan Lepore 
468*fc0dd0d3SIan Lepore 	WR4B(sc, EPIT_CR, sc->ctlreg | EPIT_CR_SWR);
469*fc0dd0d3SIan Lepore 	while (RD4(sc, EPIT_CR) & EPIT_CR_SWR)
470*fc0dd0d3SIan Lepore 		continue;
471*fc0dd0d3SIan Lepore 
472*fc0dd0d3SIan Lepore 	/*
473*fc0dd0d3SIan Lepore 	 * Unit 0 is the timecounter, 1 (if instantiated) is the eventtimer.
474*fc0dd0d3SIan Lepore 	 */
475*fc0dd0d3SIan Lepore 	if (device_get_unit(sc->dev) == 0)
476*fc0dd0d3SIan Lepore 		err = epit_tc_attach(sc);
477*fc0dd0d3SIan Lepore 	else
478*fc0dd0d3SIan Lepore 		err = epit_et_attach(sc);
479*fc0dd0d3SIan Lepore 
480*fc0dd0d3SIan Lepore 	return (err);
481*fc0dd0d3SIan Lepore }
482*fc0dd0d3SIan Lepore 
483*fc0dd0d3SIan Lepore static device_method_t epit_methods[] = {
484*fc0dd0d3SIan Lepore 	DEVMETHOD(device_probe,		epit_probe),
485*fc0dd0d3SIan Lepore 	DEVMETHOD(device_attach,	epit_attach),
486*fc0dd0d3SIan Lepore 
487*fc0dd0d3SIan Lepore 	DEVMETHOD_END
488*fc0dd0d3SIan Lepore };
489*fc0dd0d3SIan Lepore 
490*fc0dd0d3SIan Lepore static driver_t epit_driver = {
491*fc0dd0d3SIan Lepore 	"imx_epit",
492*fc0dd0d3SIan Lepore 	epit_methods,
493*fc0dd0d3SIan Lepore 	sizeof(struct epit_softc),
494*fc0dd0d3SIan Lepore };
495*fc0dd0d3SIan Lepore 
496*fc0dd0d3SIan Lepore static devclass_t epit_devclass;
497*fc0dd0d3SIan Lepore 
498*fc0dd0d3SIan Lepore EARLY_DRIVER_MODULE(imx_epit, simplebus, epit_driver, epit_devclass, 0,
499*fc0dd0d3SIan Lepore     0, BUS_PASS_TIMER);
500*fc0dd0d3SIan Lepore 
501*fc0dd0d3SIan Lepore #ifndef MULTIDELAY
502*fc0dd0d3SIan Lepore 
503*fc0dd0d3SIan Lepore /*
504*fc0dd0d3SIan Lepore  * Hand-calibrated delay-loop counter.  This was calibrated on an i.MX6 running
505*fc0dd0d3SIan Lepore  * at 792mhz.  It will delay a bit too long on slower processors -- that's
506*fc0dd0d3SIan Lepore  * better than not delaying long enough.  In practice this is unlikely to get
507*fc0dd0d3SIan Lepore  * used much since the clock driver is one of the first to start up, and once
508*fc0dd0d3SIan Lepore  * we're attached the delay loop switches to using the timer hardware.
509*fc0dd0d3SIan Lepore  */
510*fc0dd0d3SIan Lepore static const int epit_delay_count = 78;
511*fc0dd0d3SIan Lepore 
512*fc0dd0d3SIan Lepore void
513*fc0dd0d3SIan Lepore DELAY(int usec)
514*fc0dd0d3SIan Lepore {
515*fc0dd0d3SIan Lepore 	uint64_t ticks;
516*fc0dd0d3SIan Lepore 
517*fc0dd0d3SIan Lepore 	/* If the timer hardware is not accessible, just use a loop. */
518*fc0dd0d3SIan Lepore 	if (epit_sc == NULL) {
519*fc0dd0d3SIan Lepore 		while (usec-- > 0)
520*fc0dd0d3SIan Lepore 			for (ticks = 0; ticks < epit_delay_count; ++ticks)
521*fc0dd0d3SIan Lepore 				cpufunc_nullop();
522*fc0dd0d3SIan Lepore 		return;
523*fc0dd0d3SIan Lepore 	} else {
524*fc0dd0d3SIan Lepore 		epit_do_delay(usec, epit_sc);
525*fc0dd0d3SIan Lepore 	}
526*fc0dd0d3SIan Lepore }
527*fc0dd0d3SIan Lepore 
528*fc0dd0d3SIan Lepore #endif
529