1 /*-
2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/malloc.h>
36 #include <sys/rman.h>
37 #include <sys/timeet.h>
38 #include <sys/timetc.h>
39 #include <machine/bus.h>
40
41 #include <dev/ofw/openfirm.h>
42 #include <dev/ofw/ofw_bus.h>
43 #include <dev/ofw/ofw_bus_subr.h>
44
45 #include <arm/ti/ti_prcm.h>
46 #include <arm/ti/ti_hwmods.h>
47
48 #include "am335x_dmtreg.h"
49
50 struct am335x_dmtimer_softc {
51 device_t dev;
52 int tmr_mem_rid;
53 struct resource * tmr_mem_res;
54 int tmr_irq_rid;
55 struct resource * tmr_irq_res;
56 void *tmr_irq_handler;
57 uint32_t sysclk_freq;
58 uint32_t tclr; /* Cached TCLR register. */
59 union {
60 struct timecounter tc;
61 struct eventtimer et;
62 } func;
63 int tmr_num; /* Hardware unit number. */
64 char tmr_name[12]; /* "DMTimerN", N = tmr_num */
65 };
66
67 static struct am335x_dmtimer_softc *am335x_dmtimer_et_sc = NULL;
68 static struct am335x_dmtimer_softc *am335x_dmtimer_tc_sc = NULL;
69
70 /*
71 * We use dmtimer2 for eventtimer and dmtimer3 for timecounter.
72 */
73 #define ET_TMR_NUM 2
74 #define TC_TMR_NUM 3
75
76 /* List of compatible strings for FDT tree */
77 static struct ofw_compat_data compat_data[] = {
78 {"ti,am335x-timer", 1},
79 {"ti,am335x-timer-1ms", 1},
80 {NULL, 0},
81 };
82
83 #define DMTIMER_READ4(sc, reg) bus_read_4((sc)->tmr_mem_res, (reg))
84 #define DMTIMER_WRITE4(sc, reg, val) bus_write_4((sc)->tmr_mem_res, (reg), (val))
85
86 static int
am335x_dmtimer_et_start(struct eventtimer * et,sbintime_t first,sbintime_t period)87 am335x_dmtimer_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
88 {
89 struct am335x_dmtimer_softc *sc;
90 uint32_t initial_count, reload_count;
91
92 sc = et->et_priv;
93
94 /*
95 * Stop the timer before changing it. This routine will often be called
96 * while the timer is still running, to either lengthen or shorten the
97 * current event time. We need to ensure the timer doesn't expire while
98 * we're working with it.
99 *
100 * Also clear any pending interrupt status, because it's at least
101 * theoretically possible that we're running in a primary interrupt
102 * context now, and a timer interrupt could be pending even before we
103 * stopped the timer. The more likely case is that we're being called
104 * from the et_event_cb() routine dispatched from our own handler, but
105 * it's not clear to me that that's the only case possible.
106 */
107 sc->tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
108 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
109 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
110
111 if (period != 0) {
112 reload_count = ((uint32_t)et->et_frequency * period) >> 32;
113 sc->tclr |= DMT_TCLR_AUTOLOAD;
114 } else {
115 reload_count = 0;
116 }
117
118 if (first != 0)
119 initial_count = ((uint32_t)et->et_frequency * first) >> 32;
120 else
121 initial_count = reload_count;
122
123 /*
124 * Set auto-reload and current-count values. This timer hardware counts
125 * up from the initial/reload value and interrupts on the zero rollover.
126 */
127 DMTIMER_WRITE4(sc, DMT_TLDR, 0xFFFFFFFF - reload_count);
128 DMTIMER_WRITE4(sc, DMT_TCRR, 0xFFFFFFFF - initial_count);
129
130 /* Enable overflow interrupt, and start the timer. */
131 DMTIMER_WRITE4(sc, DMT_IRQENABLE_SET, DMT_IRQ_OVF);
132 sc->tclr |= DMT_TCLR_START;
133 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
134
135 return (0);
136 }
137
138 static int
am335x_dmtimer_et_stop(struct eventtimer * et)139 am335x_dmtimer_et_stop(struct eventtimer *et)
140 {
141 struct am335x_dmtimer_softc *sc;
142
143 sc = et->et_priv;
144
145 /* Stop timer, disable and clear interrupt. */
146 sc->tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
147 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
148 DMTIMER_WRITE4(sc, DMT_IRQENABLE_CLR, DMT_IRQ_OVF);
149 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
150 return (0);
151 }
152
153 static int
am335x_dmtimer_et_intr(void * arg)154 am335x_dmtimer_et_intr(void *arg)
155 {
156 struct am335x_dmtimer_softc *sc;
157
158 sc = arg;
159
160 /* Ack the interrupt, and invoke the callback if it's still enabled. */
161 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
162 if (sc->func.et.et_active)
163 sc->func.et.et_event_cb(&sc->func.et, sc->func.et.et_arg);
164
165 return (FILTER_HANDLED);
166 }
167
168 static int
am335x_dmtimer_et_init(struct am335x_dmtimer_softc * sc)169 am335x_dmtimer_et_init(struct am335x_dmtimer_softc *sc)
170 {
171 KASSERT(am335x_dmtimer_et_sc == NULL, ("already have an eventtimer"));
172
173 /*
174 * Setup eventtimer interrupt handling. Panic if anything goes wrong,
175 * because the system just isn't going to run without an eventtimer.
176 */
177 sc->tmr_irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
178 &sc->tmr_irq_rid, RF_ACTIVE);
179 if (sc->tmr_irq_res == NULL)
180 panic("am335x_dmtimer: could not allocate irq resources");
181 if (bus_setup_intr(sc->dev, sc->tmr_irq_res, INTR_TYPE_CLK,
182 am335x_dmtimer_et_intr, NULL, sc, &sc->tmr_irq_handler) != 0)
183 panic("am335x_dmtimer: count not setup irq handler");
184
185 sc->func.et.et_name = sc->tmr_name;
186 sc->func.et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
187 sc->func.et.et_quality = 500;
188 sc->func.et.et_frequency = sc->sysclk_freq;
189 sc->func.et.et_min_period =
190 ((0x00000005LLU << 32) / sc->func.et.et_frequency);
191 sc->func.et.et_max_period =
192 (0xfffffffeLLU << 32) / sc->func.et.et_frequency;
193 sc->func.et.et_start = am335x_dmtimer_et_start;
194 sc->func.et.et_stop = am335x_dmtimer_et_stop;
195 sc->func.et.et_priv = sc;
196
197 am335x_dmtimer_et_sc = sc;
198 et_register(&sc->func.et);
199
200 return (0);
201 }
202
203 static unsigned
am335x_dmtimer_tc_get_timecount(struct timecounter * tc)204 am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
205 {
206 struct am335x_dmtimer_softc *sc;
207
208 sc = tc->tc_priv;
209
210 return (DMTIMER_READ4(sc, DMT_TCRR));
211 }
212
213 static int
am335x_dmtimer_tc_init(struct am335x_dmtimer_softc * sc)214 am335x_dmtimer_tc_init(struct am335x_dmtimer_softc *sc)
215 {
216 KASSERT(am335x_dmtimer_tc_sc == NULL, ("already have a timecounter"));
217
218 /* Set up timecounter, start it, register it. */
219 DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);
220 while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
221 continue;
222
223 sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;
224 DMTIMER_WRITE4(sc, DMT_TLDR, 0);
225 DMTIMER_WRITE4(sc, DMT_TCRR, 0);
226 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
227
228 sc->func.tc.tc_name = sc->tmr_name;
229 sc->func.tc.tc_get_timecount = am335x_dmtimer_tc_get_timecount;
230 sc->func.tc.tc_counter_mask = ~0u;
231 sc->func.tc.tc_frequency = sc->sysclk_freq;
232 sc->func.tc.tc_quality = 500;
233 sc->func.tc.tc_priv = sc;
234
235 am335x_dmtimer_tc_sc = sc;
236 tc_init(&sc->func.tc);
237
238 return (0);
239 }
240
241 static int
am335x_dmtimer_probe(device_t dev)242 am335x_dmtimer_probe(device_t dev)
243 {
244 char strbuf[32];
245 int tmr_num;
246
247 if (!ofw_bus_status_okay(dev))
248 return (ENXIO);
249
250 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
251 return (ENXIO);
252
253 /*
254 * Get the hardware unit number (the N from ti,hwmods="timerN").
255 * If this isn't the hardware unit we're going to use for either the
256 * eventtimer or the timecounter, no point in instantiating the device.
257 */
258 tmr_num = ti_hwmods_get_unit(dev, "timer");
259 if (tmr_num != ET_TMR_NUM && tmr_num != TC_TMR_NUM)
260 return (ENXIO);
261
262 snprintf(strbuf, sizeof(strbuf), "AM335x DMTimer%d", tmr_num);
263 device_set_desc_copy(dev, strbuf);
264
265 return(BUS_PROBE_DEFAULT);
266 }
267
268 static int
am335x_dmtimer_attach(device_t dev)269 am335x_dmtimer_attach(device_t dev)
270 {
271 struct am335x_dmtimer_softc *sc;
272 clk_ident_t timer_id;
273 int err;
274
275 sc = device_get_softc(dev);
276 sc->dev = dev;
277
278 /* Get the base clock frequency. */
279 if ((err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq)) != 0)
280 return (err);
281
282 /* Enable clocks and power on the device. */
283 if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT)
284 return (ENXIO);
285 if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0)
286 return (err);
287 if ((err = ti_prcm_clk_enable(timer_id)) != 0)
288 return (err);
289
290 /* Request the memory resources. */
291 sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
292 &sc->tmr_mem_rid, RF_ACTIVE);
293 if (sc->tmr_mem_res == NULL) {
294 return (ENXIO);
295 }
296
297 sc->tmr_num = ti_hwmods_get_unit(dev, "timer");
298 snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
299
300 /*
301 * Go set up either a timecounter or eventtimer. We wouldn't have
302 * attached if we weren't one or the other.
303 */
304 if (sc->tmr_num == ET_TMR_NUM)
305 am335x_dmtimer_et_init(sc);
306 else if (sc->tmr_num == TC_TMR_NUM)
307 am335x_dmtimer_tc_init(sc);
308 else
309 panic("am335x_dmtimer: bad timer number %d", sc->tmr_num);
310
311 return (0);
312 }
313
314 static device_method_t am335x_dmtimer_methods[] = {
315 DEVMETHOD(device_probe, am335x_dmtimer_probe),
316 DEVMETHOD(device_attach, am335x_dmtimer_attach),
317 { 0, 0 }
318 };
319
320 static driver_t am335x_dmtimer_driver = {
321 "am335x_dmtimer",
322 am335x_dmtimer_methods,
323 sizeof(struct am335x_dmtimer_softc),
324 };
325
326 static devclass_t am335x_dmtimer_devclass;
327
328 DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0);
329 MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1);
330
331 void
DELAY(int usec)332 DELAY(int usec)
333 {
334 struct am335x_dmtimer_softc *sc;
335 int32_t counts;
336 uint32_t first, last;
337
338 sc = am335x_dmtimer_tc_sc;
339
340 if (sc == NULL) {
341 for (; usec > 0; usec--)
342 for (counts = 200; counts > 0; counts--)
343 /* Prevent gcc from optimizing out the loop */
344 cpufunc_nullop();
345 return;
346 }
347
348 /* Get the number of times to count */
349 counts = (usec + 1) * (sc->sysclk_freq / 1000000);
350
351 first = DMTIMER_READ4(sc, DMT_TCRR);
352
353 while (counts > 0) {
354 last = DMTIMER_READ4(sc, DMT_TCRR);
355 if (last > first) {
356 counts -= (int32_t)(last - first);
357 } else {
358 counts -= (int32_t)((0xFFFFFFFF - first) + last);
359 }
360 first = last;
361 }
362 }
363
364