xref: /openbsd/sys/arch/armv7/omap/gptimer.c (revision 3cab2bb3)
1 /* $OpenBSD: gptimer.c,v 1.9 2020/07/12 20:36:37 naddy Exp $ */
2 /*
3  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /*
19  *	WARNING - this timer initializion has not been checked
20  *	to see if it will do _ANYTHING_ sane if the omap enters
21  *	low power mode.
22  */
23 
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/kernel.h>
27 #include <sys/time.h>
28 #include <sys/evcount.h>
29 #include <sys/device.h>
30 #include <sys/timetc.h>
31 #include <dev/clock_subr.h>
32 #include <machine/bus.h>
33 #include <armv7/armv7/armv7var.h>
34 #include <armv7/omap/prcmvar.h>
35 
36 #include <machine/intr.h>
37 #include <arm/cpufunc.h>
38 
39 /* registers */
40 #define	GP_TIDR		0x000
41 #define		GP_TIDR_REV	0xff
42 #define GP_TIOCP_CFG	0x010
43 #define 	GP_TIOCP_CFG_CLKA	0x000000300
44 #define 	GP_TIOCP_CFG_EMUFREE	0x000000020
45 #define 	GP_TIOCP_CFG_IDLEMODE	0x000000018
46 #define 	GP_TIOCP_CFG_ENAPWAKEUP	0x000000004
47 #define 	GP_TIOCP_CFG_SOFTRESET	0x000000002
48 #define 	GP_TIOCP_CFG_AUTOIDLE	0x000000001
49 #define	GP_TISTAT	0x014
50 #define 	GP_TISTAT_RESETDONE	0x000000001
51 #define	GP_TISR		0x018
52 #define		GP_TISTAT_TCAR		0x00000004
53 #define		GP_TISTAT_OVF		0x00000002
54 #define		GP_TISTAT_MATCH		0x00000001
55 #define GP_TIER		0x1c
56 #define		GP_TIER_TCAR_EN		0x4
57 #define		GP_TIER_OVF_EN		0x2
58 #define		GP_TIER_MAT_EN		0x1
59 #define	GP_TWER		0x020
60 #define		GP_TWER_TCAR_EN		0x00000004
61 #define		GP_TWER_OVF_EN		0x00000002
62 #define		GP_TWER_MAT_EN		0x00000001
63 #define	GP_TCLR		0x024
64 #define		GP_TCLR_GPO		(1<<14)
65 #define		GP_TCLR_CAPT		(1<<13)
66 #define		GP_TCLR_PT		(1<<12)
67 #define		GP_TCLR_TRG		(3<<10)
68 #define		GP_TCLR_TRG_O		(1<<10)
69 #define		GP_TCLR_TRG_OM		(2<<10)
70 #define		GP_TCLR_TCM		(3<<8)
71 #define		GP_TCLR_TCM_RISE	(1<<8)
72 #define		GP_TCLR_TCM_FALL	(2<<8)
73 #define		GP_TCLR_TCM_BOTH	(3<<8)
74 #define		GP_TCLR_SCPWM		(1<<7)
75 #define		GP_TCLR_CE		(1<<6)
76 #define		GP_TCLR_PRE		(1<<5)
77 #define		GP_TCLR_PTV		(7<<2)
78 #define		GP_TCLR_AR		(1<<1)
79 #define		GP_TCLR_ST		(1<<0)
80 #define	GP_TCRR		0x028				/* counter */
81 #define	GP_TLDR		0x02c				/* reload */
82 #define	GP_TTGR		0x030
83 #define	GP_TWPS		0x034
84 #define		GP_TWPS_TCLR	0x01
85 #define		GP_TWPS_TCRR	0x02
86 #define		GP_TWPS_TLDR	0x04
87 #define		GP_TWPS_TTGR	0x08
88 #define		GP_TWPS_TMAR	0x10
89 #define		GP_TWPS_ALL	0x1f
90 #define	GP_TMAR		0x038
91 #define	GP_TCAR		0x03C
92 #define	GP_TSICR	0x040
93 #define		GP_TSICR_POSTED		0x00000002
94 #define		GP_TSICR_SFT		0x00000001
95 #define	GP_TCAR2	0x044
96 
97 #define TIMER_FREQUENCY			32768	/* 32kHz is used, selectable */
98 
99 static struct evcount clk_count;
100 static struct evcount stat_count;
101 #define GPT1_IRQ  38
102 #define GPTIMER0_IRQ	38
103 
104 //static int clk_irq = GPT1_IRQ; /* XXX 37 */
105 
106 void gptimer_attach(struct device *parent, struct device *self, void *args);
107 int gptimer_intr(void *frame);
108 void gptimer_wait(int reg);
109 void gptimer_cpu_initclocks(void);
110 void gptimer_delay(u_int);
111 void gptimer_setstatclockrate(int newhz);
112 
113 bus_space_tag_t gptimer_iot;
114 bus_space_handle_t gptimer_ioh0, gptimer_ioh1;
115 int gptimer_irq = 0;
116 
117 u_int gptimer_get_timecount(struct timecounter *);
118 
119 static struct timecounter gptimer_timecounter = {
120 	gptimer_get_timecount, NULL, 0xffffffff, 0, "gptimer", 0, NULL, 0
121 };
122 
123 volatile u_int32_t nexttickevent;
124 volatile u_int32_t nextstatevent;
125 u_int32_t	ticks_per_second;
126 u_int32_t	ticks_per_intr;
127 u_int32_t	ticks_err_cnt;
128 u_int32_t	ticks_err_sum;
129 u_int32_t	statvar, statmin;
130 
131 struct cfattach	gptimer_ca = {
132 	sizeof (struct device), NULL, gptimer_attach
133 };
134 
135 struct cfdriver gptimer_cd = {
136 	NULL, "gptimer", DV_DULL
137 };
138 
139 void
140 gptimer_attach(struct device *parent, struct device *self, void *args)
141 {
142 	struct armv7_attach_args *aa = args;
143 	bus_space_handle_t ioh;
144 	u_int32_t rev;
145 
146 	gptimer_iot = aa->aa_iot;
147 	if (bus_space_map(gptimer_iot, aa->aa_dev->mem[0].addr,
148 	    aa->aa_dev->mem[0].size, 0, &ioh))
149 		panic("gptimer_attach: bus_space_map failed!");
150 
151 	rev = bus_space_read_4(gptimer_iot, ioh, GP_TIDR);
152 
153 	printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
154 	if (self->dv_unit == 0) {
155 		gptimer_ioh0 = ioh;
156 		gptimer_irq = aa->aa_dev->irq[0];
157 		bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, 0);
158 	} else if (self->dv_unit == 1) {
159 		/* start timer because it is used in delay */
160 		gptimer_ioh1 = ioh;
161 		bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCRR, 0);
162 		gptimer_wait(GP_TWPS_ALL);
163 		bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TLDR, 0);
164 		gptimer_wait(GP_TWPS_ALL);
165 		bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCLR,
166 		    GP_TCLR_AR | GP_TCLR_ST);
167 		gptimer_wait(GP_TWPS_ALL);
168 
169 		gptimer_timecounter.tc_frequency = TIMER_FREQUENCY;
170 		tc_init(&gptimer_timecounter);
171 	}
172 	else
173 		panic("attaching too many gptimers at 0x%lx",
174 		    aa->aa_dev->mem[0].addr);
175 
176 	arm_clock_register(gptimer_cpu_initclocks, gptimer_delay,
177 	    gptimer_setstatclockrate, NULL);
178 }
179 
180 /*
181  * See comment in arm/xscale/i80321_clock.c
182  *
183  * counter is count up, but with autoreload timers it is not possible
184  * to detect how many  interrupts passed while interrupts were blocked.
185  * also it is not possible to atomically add to the register
186  * get get it to precisely fire at a non-fixed interval.
187  *
188  * To work around this two timers are used, GPT1 is used as a reference
189  * clock without reload , however we just ignore the interrupt it
190  * would (may?) generate.
191  *
192  * Internally this keeps track of when the next timer should fire
193  * and based on that time and the current value of the reference
194  * clock a number is written into the timer count register to schedule
195  * the next event.
196  */
197 
198 int
199 gptimer_intr(void *frame)
200 {
201 	u_int32_t now, r;
202 	u_int32_t nextevent, duration;
203 
204 	/* clear interrupt */
205 	now = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
206 
207 	while ((int32_t) (nexttickevent - now) < 0) {
208 		nexttickevent += ticks_per_intr;
209 		ticks_err_sum += ticks_err_cnt;
210 #if 0
211 		if (ticks_err_sum  > hz) {
212 			u_int32_t match_error;
213 			match_error = ticks_err_sum / hz
214 			ticks_err_sum -= (match_error * hz);
215 		}
216 #else
217 		/* looping a few times is faster than divide */
218 		while (ticks_err_sum  > hz) {
219 			nexttickevent += 1;
220 			ticks_err_sum -= hz;
221 		}
222 #endif
223 		clk_count.ec_count++;
224 		hardclock(frame);
225 	}
226 	while ((int32_t) (nextstatevent - now) < 0) {
227 		do {
228 			r = random() & (statvar -1);
229 		} while (r == 0); /* random == 0 not allowed */
230 		nextstatevent += statmin + r;
231 		/* XXX - correct nextstatevent? */
232 		stat_count.ec_count++;
233 		statclock(frame);
234 	}
235 	if ((nexttickevent - now) < (nextstatevent - now))
236                 nextevent = nexttickevent;
237         else
238                 nextevent = nextstatevent;
239 
240 /* XXX */
241 	duration = nextevent -
242 	    bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
243 #if 0
244 	printf("duration 0x%x %x %x\n", nextevent -
245 	    bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR),
246 	    bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TCRR),
247 	    bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR));
248 #endif
249 
250 
251         if (duration <= 0)
252                 duration = 1; /* trigger immediately. */
253 
254         if (duration > ticks_per_intr) {
255                 /*
256                  * If interrupts are blocked too long, like during
257                  * the root prompt or ddb, the timer can roll over,
258                  * this will allow the system to continue to run
259                  * even if time is lost.
260                  */
261                 duration = ticks_per_intr;
262                 nexttickevent = now;
263                 nextstatevent = now;
264         }
265 
266 	gptimer_wait(GP_TWPS_ALL);
267 	bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR,
268 		bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR));
269 	gptimer_wait(GP_TWPS_ALL);
270         bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -duration);
271 
272 	return 1;
273 }
274 
275 /*
276  * would be interesting to play with trigger mode while having one timer
277  * in 32KHz mode, and the other timer running in sysclk mode and use
278  * the high resolution speeds (matters more for delay than tick timer
279  */
280 
281 void
282 gptimer_cpu_initclocks()
283 {
284 //	u_int32_t now;
285 	stathz = 128;
286 	profhz = 1024;
287 
288 	ticks_per_second = TIMER_FREQUENCY;
289 
290 	setstatclockrate(stathz);
291 
292 	ticks_per_intr = ticks_per_second / hz;
293 	ticks_err_cnt = ticks_per_second % hz;
294 	ticks_err_sum = 0;
295 
296 	prcm_setclock(1, PRCM_CLK_SPEED_32);
297 	prcm_setclock(2, PRCM_CLK_SPEED_32);
298 	/* establish interrupts */
299 	arm_intr_establish(gptimer_irq, IPL_CLOCK, gptimer_intr,
300 	    NULL, "tick");
301 
302 	/* setup timer 0 (hardware timer 2) */
303 	/* reset? - XXX */
304 
305         bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TLDR, 0);
306 
307 	nexttickevent = nextstatevent = bus_space_read_4(gptimer_iot,
308 	    gptimer_ioh1, GP_TCRR) + ticks_per_intr;
309 
310 	gptimer_wait(GP_TWPS_ALL);
311 	bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TIER, GP_TIER_OVF_EN);
312 	gptimer_wait(GP_TWPS_ALL);
313 	bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TWER, GP_TWER_OVF_EN);
314 	gptimer_wait(GP_TWPS_ALL);
315 	bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR,
316 	    GP_TCLR_AR | GP_TCLR_ST);
317 	gptimer_wait(GP_TWPS_ALL);
318 	bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR,
319 		bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR));
320 	gptimer_wait(GP_TWPS_ALL);
321 	bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -ticks_per_intr);
322 	gptimer_wait(GP_TWPS_ALL);
323 }
324 
325 void
326 gptimer_wait(int reg)
327 {
328 	while (bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TWPS) & reg)
329 		;
330 }
331 
332 #if 0
333 void
334 microtime(struct timeval *tvp)
335 {
336 	int s;
337 	int deltacnt;
338 	u_int32_t counter, expected;
339 	s = splhigh();
340 
341 	if (1) {	/* not inited */
342 		tvp->tv_sec = 0;
343 		tvp->tv_usec = 0;
344 		return;
345 	}
346 	s = splhigh();
347 	counter = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
348 	expected = nexttickevent;
349 
350 	*tvp = time;
351 	splx(s);
352 
353 	deltacnt = counter - expected + ticks_per_intr;
354 
355 #if 1
356 	/* low frequency timer algorithm */
357 	tvp->tv_usec += deltacnt * 1000000ULL / TIMER_FREQUENCY;
358 #else
359 	/* high frequency timer algorithm - XXX */
360 	tvp->tv_usec += deltacnt / (TIMER_FREQUENCY / 1000000ULL);
361 #endif
362 
363 	while (tvp->tv_usec >= 1000000) {
364 		tvp->tv_sec++;
365 		tvp->tv_usec -= 1000000;
366 	}
367 
368 }
369 #endif
370 
371 void
372 gptimer_delay(u_int usecs)
373 {
374 	u_int32_t clock, oclock, delta, delaycnt;
375 	volatile int j;
376 	int csec, usec;
377 
378 	if (usecs > (0x80000000 / (TIMER_FREQUENCY))) {
379 		csec = usecs / 10000;
380 		usec = usecs % 10000;
381 
382 		delaycnt = (TIMER_FREQUENCY / 100) * csec +
383 		    (TIMER_FREQUENCY / 100) * usec / 10000;
384 	} else {
385 		delaycnt = TIMER_FREQUENCY * usecs / 1000000;
386 	}
387 	if (delaycnt <= 1)
388 		for (j = 100; j > 0; j--)
389 			;
390 
391 	if (gptimer_ioh1 == 0) {
392 		/* BAH */
393 		for (; usecs > 0; usecs--)
394 			for (j = 100; j > 0; j--)
395 				;
396 		return;
397 	}
398 	oclock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
399 	while (1) {
400 		for (j = 100; j > 0; j--)
401 			;
402 		clock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
403 		delta = clock - oclock;
404 		if (delta > delaycnt)
405 			break;
406 	}
407 
408 }
409 
410 void
411 gptimer_setstatclockrate(int newhz)
412 {
413 	int minint, statint;
414 	int s;
415 
416 	s = splclock();
417 
418 	statint = ticks_per_second / newhz;
419 	/* calculate largest 2^n which is smaller that just over half statint */
420 	statvar = 0x40000000; /* really big power of two */
421 	minint = statint / 2 + 100;
422 	while (statvar > minint)
423 		statvar >>= 1;
424 
425 	statmin = statint - (statvar >> 1);
426 
427 	splx(s);
428 
429 	/*
430 	 * XXX this allows the next stat timer to occur then it switches
431 	 * to the new frequency. Rather than switching instantly.
432 	 */
433 }
434 
435 
436 u_int
437 gptimer_get_timecount(struct timecounter *tc)
438 {
439 	return bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
440 }
441