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