xref: /openbsd/sys/arch/armv7/omap/dmtimer.c (revision 0ed1bf01)
1 /*	$OpenBSD: dmtimer.c,v 1.22 2023/09/17 14:50:51 cheloha Exp $	*/
2 /*
3  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
4  * Copyright (c) 2013 Raphael Graf <r@undefined.ch>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  *	WARNING - this timer initialization has not been checked
21  *	to see if it will do _ANYTHING_ sane if the omap enters
22  *	low power mode.
23  */
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/kernel.h>
28 #include <sys/clockintr.h>
29 #include <sys/evcount.h>
30 #include <sys/device.h>
31 #include <sys/stdint.h>
32 #include <sys/timetc.h>
33 #include <machine/bus.h>
34 #include <armv7/armv7/armv7var.h>
35 #include <armv7/omap/prcmvar.h>
36 
37 #include <machine/intr.h>
38 
39 /* registers */
40 #define	DM_TIDR		0x000
41 #define		DM_TIDR_MAJOR		0x00000700
42 #define		DM_TIDR_MINOR		0x0000003f
43 #define	DM_TIOCP_CFG	0x010
44 #define 	DM_TIOCP_CFG_IDLEMODE	(3<<2)
45 #define 	DM_TIOCP_CFG_EMUFREE	(1<<1)
46 #define 	DM_TIOCP_CFG_SOFTRESET	(1<<0)
47 #define	DM_TISR		0x028
48 #define		DM_TISR_TCAR		(1<<2)
49 #define		DM_TISR_OVF		(1<<1)
50 #define		DM_TISR_MAT		(1<<0)
51 #define DM_TIER		0x2c
52 #define		DM_TIER_TCAR_EN		(1<<2)
53 #define		DM_TIER_OVF_EN		(1<<1)
54 #define		DM_TIER_MAT_EN		(1<<0)
55 #define DM_TIECR	0x30
56 #define		DM_TIECR_TCAR_EN	(1<<2)
57 #define		DM_TIECR_OVF_EN		(1<<1)
58 #define		DM_TIECR_MAT_EN		(1<<0)
59 #define	DM_TWER		0x034
60 #define		DM_TWER_TCAR_EN		(1<<2)
61 #define		DM_TWER_OVF_EN		(1<<1)
62 #define		DM_TWER_MAT_EN		(1<<0)
63 #define	DM_TCLR		0x038
64 #define		DM_TCLR_GPO		(1<<14)
65 #define		DM_TCLR_CAPT		(1<<13)
66 #define		DM_TCLR_PT		(1<<12)
67 #define		DM_TCLR_TRG		(3<<10)
68 #define		DM_TCLR_TRG_O		(1<<10)
69 #define		DM_TCLR_TRG_OM		(2<<10)
70 #define		DM_TCLR_TCM		(3<<8)
71 #define		DM_TCLR_TCM_RISE	(1<<8)
72 #define		DM_TCLR_TCM_FALL	(2<<8)
73 #define		DM_TCLR_TCM_BOTH	(3<<8)
74 #define		DM_TCLR_SCPWM		(1<<7)
75 #define		DM_TCLR_CE		(1<<6)
76 #define		DM_TCLR_PRE		(1<<5)
77 #define		DM_TCLR_PTV		(7<<2)
78 #define		DM_TCLR_AR		(1<<1)
79 #define		DM_TCLR_ST		(1<<0)
80 #define	DM_TCRR		0x03c
81 #define	DM_TLDR		0x040
82 #define	DM_TTGR		0x044
83 #define	DM_TWPS		0x048
84 #define		DM_TWPS_TMAR		(1<<4)
85 #define		DM_TWPS_TTGR		(1<<3)
86 #define		DM_TWPS_TLDR		(1<<2)
87 #define		DM_TWPS_TCLR		(1<<0)
88 #define		DM_TWPS_TCRR		(1<<1)
89 #define		DM_TWPS_ALL		0x1f
90 #define	DM_TMAR		0x04c
91 #define	DM_TCAR		0x050
92 #define	DM_TSICR	0x054
93 #define		DM_TSICR_POSTED		(1<<2)
94 #define		DM_TSICR_SFT		(1<<1)
95 #define	DM_TCAR2	0x058
96 
97 #define TIMER_FREQUENCY			32768	/* 32kHz is used, selectable */
98 #define MAX_TIMERS			2
99 
100 void dmtimer_attach(struct device *parent, struct device *self, void *args);
101 int dmtimer_intr(void *frame);
102 void dmtimer_reset_tisr(void);
103 void dmtimer_wait(int reg);
104 void dmtimer_cpu_initclocks(void);
105 void dmtimer_cpu_startclock(void);
106 void dmtimer_delay(u_int);
107 void dmtimer_setstatclockrate(int newhz);
108 
109 u_int dmtimer_get_timecount(struct timecounter *);
110 
111 static struct timecounter dmtimer_timecounter = {
112 	.tc_get_timecount = dmtimer_get_timecount,
113 	.tc_counter_mask = 0xffffffff,
114 	.tc_frequency = 0,
115 	.tc_name = "dmtimer",
116 	.tc_quality = 0,
117 	.tc_priv = NULL,
118 };
119 
120 void dmtimer_rearm(void *, uint64_t);
121 void dmtimer_trigger(void *);
122 
123 struct intrclock dmtimer_intrclock = {
124 	.ic_rearm = dmtimer_rearm,
125 	.ic_trigger = dmtimer_trigger
126 };
127 
128 bus_space_handle_t dmtimer_ioh0;
129 int dmtimer_irq = 0;
130 
131 struct dmtimer_softc {
132 	struct device		sc_dev;
133 	bus_space_tag_t		sc_iot;
134 	bus_space_handle_t	sc_ioh[MAX_TIMERS];
135 	u_int32_t		sc_irq;
136 	u_int32_t		sc_ticks_per_second;
137 	u_int64_t		sc_nsec_cycle_ratio;
138 	u_int64_t		sc_nsec_max;
139 };
140 
141 const struct cfattach	dmtimer_ca = {
142 	sizeof (struct dmtimer_softc), NULL, dmtimer_attach
143 };
144 
145 struct cfdriver dmtimer_cd = {
146 	NULL, "dmtimer", DV_DULL
147 };
148 
149 void
dmtimer_attach(struct device * parent,struct device * self,void * args)150 dmtimer_attach(struct device *parent, struct device *self, void *args)
151 {
152 	struct dmtimer_softc	*sc = (struct dmtimer_softc *)self;
153 	struct armv7_attach_args *aa = args;
154 	bus_space_handle_t	ioh;
155 	u_int32_t		rev, cfg;
156 
157 	sc->sc_iot = aa->aa_iot;
158 
159 	if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
160 	    aa->aa_dev->mem[0].size, 0, &ioh))
161 		panic("%s: bus_space_map failed!", __func__);
162 
163 
164 	prcm_setclock(1, PRCM_CLK_SPEED_32);
165 	prcm_setclock(2, PRCM_CLK_SPEED_32);
166 	prcm_enablemodule(PRCM_TIMER2);
167 	prcm_enablemodule(PRCM_TIMER3);
168 
169 	/* reset */
170 	bus_space_write_4(sc->sc_iot, ioh, DM_TIOCP_CFG,
171 	    DM_TIOCP_CFG_SOFTRESET);
172 	while (bus_space_read_4(sc->sc_iot, ioh, DM_TIOCP_CFG)
173 	    & DM_TIOCP_CFG_SOFTRESET)
174 		;
175 
176 	if (self->dv_unit == 0) {
177 		dmtimer_ioh0 = ioh;
178 		dmtimer_irq = aa->aa_dev->irq[0];
179 		/* enable write posted mode */
180 		bus_space_write_4(sc->sc_iot, ioh, DM_TSICR, DM_TSICR_POSTED);
181 		/* stop timer */
182 		bus_space_write_4(sc->sc_iot, ioh, DM_TCLR, 0);
183 	} else if (self->dv_unit == 1) {
184 		/* start timer because it is used in delay */
185 		/* interrupts and posted mode are disabled */
186 		sc->sc_irq = dmtimer_irq;
187 		sc->sc_ioh[0] = dmtimer_ioh0;
188 		sc->sc_ioh[1] = ioh;
189 
190 		bus_space_write_4(sc->sc_iot, ioh, DM_TCRR, 0);
191 		bus_space_write_4(sc->sc_iot, ioh, DM_TLDR, 0);
192 		bus_space_write_4(sc->sc_iot, ioh, DM_TCLR,
193 		    DM_TCLR_AR | DM_TCLR_ST);
194 
195 		dmtimer_timecounter.tc_frequency = TIMER_FREQUENCY;
196 		dmtimer_timecounter.tc_priv = sc;
197 		tc_init(&dmtimer_timecounter);
198 		arm_clock_register(dmtimer_cpu_initclocks, dmtimer_delay,
199 		    dmtimer_setstatclockrate, dmtimer_cpu_startclock);
200 	}
201 	else
202 		panic("attaching too many dmtimers at 0x%lx",
203 		    aa->aa_dev->mem[0].addr);
204 
205 	/* set IDLEMODE to smart-idle */
206 	cfg = bus_space_read_4(sc->sc_iot, ioh, DM_TIOCP_CFG);
207 	bus_space_write_4(sc->sc_iot, ioh, DM_TIOCP_CFG,
208 	    (cfg & ~DM_TIOCP_CFG_IDLEMODE) | 0x02);
209 
210 	rev = bus_space_read_4(sc->sc_iot, ioh, DM_TIDR);
211 	printf(" rev %d.%d\n", (rev & DM_TIDR_MAJOR) >> 8, rev & DM_TIDR_MINOR);
212 }
213 
214 int
dmtimer_intr(void * frame)215 dmtimer_intr(void *frame)
216 {
217 	dmtimer_reset_tisr();		/* clear pending interrupts */
218 	clockintr_dispatch(frame);
219 	return 1;
220 }
221 
222 /*
223  * would be interesting to play with trigger mode while having one timer
224  * in 32kHz mode, and the other timer running in sysclk mode and use
225  * the high resolution speeds (matters more for delay than tick timer
226  */
227 
228 void
dmtimer_cpu_initclocks(void)229 dmtimer_cpu_initclocks(void)
230 {
231 	struct dmtimer_softc	*sc = dmtimer_cd.cd_devs[1];
232 
233 	stathz = hz;
234 	profhz = stathz * 10;
235 	statclock_is_randomized = 1;
236 
237 	sc->sc_ticks_per_second = TIMER_FREQUENCY; /* 32768 */
238 	sc->sc_nsec_cycle_ratio =
239 	    sc->sc_ticks_per_second * (1ULL << 32) / 1000000000;
240 	sc->sc_nsec_max = UINT64_MAX / sc->sc_nsec_cycle_ratio;
241 	dmtimer_intrclock.ic_cookie = sc;
242 
243 	/* establish interrupts */
244 	arm_intr_establish(sc->sc_irq, IPL_CLOCK, dmtimer_intr,
245 	    NULL, "tick");
246 
247 	/* setup timer 0 */
248 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TLDR, 0);
249 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TIER, DM_TIER_OVF_EN);
250 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TWER, DM_TWER_OVF_EN);
251 }
252 
253 void
dmtimer_cpu_startclock(void)254 dmtimer_cpu_startclock(void)
255 {
256 	/* start the clock interrupt cycle */
257 	clockintr_cpu_init(&dmtimer_intrclock);
258 	clockintr_trigger();
259 }
260 
261 void
dmtimer_wait(int reg)262 dmtimer_wait(int reg)
263 {
264 	struct dmtimer_softc	*sc = dmtimer_cd.cd_devs[1];
265 	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TWPS) & reg)
266 		;
267 }
268 
269 /*
270  * Clear all interrupt status bits.
271  */
272 void
dmtimer_reset_tisr(void)273 dmtimer_reset_tisr(void)
274 {
275 	struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
276 	u_int32_t tisr;
277 
278 	tisr = bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR);
279 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR, tisr);
280 }
281 
282 void
dmtimer_delay(u_int usecs)283 dmtimer_delay(u_int usecs)
284 {
285 	struct dmtimer_softc	*sc = dmtimer_cd.cd_devs[1];
286 	u_int32_t		clock, oclock, delta, delaycnt;
287 	volatile int		j;
288 	int			csec, usec;
289 
290 	if (usecs > (0x80000000 / (TIMER_FREQUENCY))) {
291 		csec = usecs / 10000;
292 		usec = usecs % 10000;
293 
294 		delaycnt = (TIMER_FREQUENCY / 100) * csec +
295 		    (TIMER_FREQUENCY / 100) * usec / 10000;
296 	} else {
297 		delaycnt = TIMER_FREQUENCY * usecs / 1000000;
298 	}
299 	if (delaycnt <= 1)
300 		for (j = 100; j > 0; j--)
301 			;
302 
303 	if (sc->sc_ioh[1] == 0) {
304 		/* BAH */
305 		for (; usecs > 0; usecs--)
306 			for (j = 100; j > 0; j--)
307 				;
308 		return;
309 	}
310 	oclock = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
311 	while (1) {
312 		for (j = 100; j > 0; j--)
313 			;
314 		clock = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
315 		delta = clock - oclock;
316 		if (delta > delaycnt)
317 			break;
318 	}
319 
320 }
321 
322 void
dmtimer_setstatclockrate(int newhz)323 dmtimer_setstatclockrate(int newhz)
324 {
325 }
326 
327 
328 u_int
dmtimer_get_timecount(struct timecounter * tc)329 dmtimer_get_timecount(struct timecounter *tc)
330 {
331 	struct dmtimer_softc *sc = dmtimer_timecounter.tc_priv;
332 
333 	return bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
334 }
335 
336 void
dmtimer_rearm(void * cookie,uint64_t nsecs)337 dmtimer_rearm(void *cookie, uint64_t nsecs)
338 {
339 	struct dmtimer_softc *sc = cookie;
340 	uint32_t cycles;
341 
342 	if (nsecs > sc->sc_nsec_max)
343 		nsecs = sc->sc_nsec_max;
344 	cycles = (nsecs * sc->sc_nsec_cycle_ratio) >> 32;
345 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCRR,
346 	    UINT32_MAX - cycles);
347 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, DM_TCLR_ST);
348 	dmtimer_wait(DM_TWPS_ALL);
349 }
350 
351 void
dmtimer_trigger(void * cookie)352 dmtimer_trigger(void *cookie)
353 {
354 	struct dmtimer_softc *sc = cookie;
355 
356 	/* stop timer */
357 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, 0);
358 
359 	dmtimer_reset_tisr();	/* clear pending interrupts */
360 
361 	/* set shortest possible timeout */
362 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCRR, UINT32_MAX);
363 	dmtimer_wait(DM_TWPS_ALL);
364 
365 	/* start timer */
366 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, DM_TCLR_ST);
367 	dmtimer_wait(DM_TWPS_ALL);
368 }
369