generic_timer.c revision 295470
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
4 * All rights reserved.
5 *
6 * Based on mpcore_timer.c developed by Ben Gray <ben.r.gray@gmail.com>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name of the company nor the name of the author may be used to
17 *    endorse or promote products derived from this software without specific
18 *    prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/**
34 *      Cortex-A7, Cortex-A15, ARMv8 and later Generic Timer
35 */
36
37#include "opt_acpi.h"
38#include "opt_platform.h"
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: head/sys/arm/arm/generic_timer.c 295470 2016-02-10 15:56:52Z andrew $");
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/bus.h>
46#include <sys/kernel.h>
47#include <sys/module.h>
48#include <sys/malloc.h>
49#include <sys/rman.h>
50#include <sys/timeet.h>
51#include <sys/timetc.h>
52#include <sys/smp.h>
53#include <sys/vdso.h>
54#include <sys/watchdog.h>
55#include <machine/bus.h>
56#include <machine/cpu.h>
57#include <machine/intr.h>
58#include <machine/md_var.h>
59
60#ifdef FDT
61#include <dev/fdt/fdt_common.h>
62#include <dev/ofw/openfirm.h>
63#include <dev/ofw/ofw_bus.h>
64#include <dev/ofw/ofw_bus_subr.h>
65#endif
66
67#ifdef DEV_ACPI
68#include <contrib/dev/acpica/include/acpi.h>
69#include <dev/acpica/acpivar.h>
70#endif
71
72#define	GT_CTRL_ENABLE		(1 << 0)
73#define	GT_CTRL_INT_MASK	(1 << 1)
74#define	GT_CTRL_INT_STAT	(1 << 2)
75#define	GT_REG_CTRL		0
76#define	GT_REG_TVAL		1
77
78#define	GT_CNTKCTL_PL0PTEN	(1 << 9) /* PL0 Physical timer reg access */
79#define	GT_CNTKCTL_PL0VTEN	(1 << 8) /* PL0 Virtual timer reg access */
80#define	GT_CNTKCTL_EVNTI	(0xf << 4) /* Virtual counter event bits */
81#define	GT_CNTKCTL_EVNTDIR	(1 << 3) /* Virtual counter event transition */
82#define	GT_CNTKCTL_EVNTEN	(1 << 2) /* Enables virtual counter events */
83#define	GT_CNTKCTL_PL0VCTEN	(1 << 1) /* PL0 CNTVCT and CNTFRQ access */
84#define	GT_CNTKCTL_PL0PCTEN	(1 << 0) /* PL0 CNTPCT and CNTFRQ access */
85
86struct arm_tmr_softc {
87	struct resource		*res[4];
88	void			*ihl[4];
89	uint32_t		clkfreq;
90	struct eventtimer	et;
91	bool			physical;
92};
93
94static struct arm_tmr_softc *arm_tmr_sc = NULL;
95
96static struct resource_spec timer_spec[] = {
97	{ SYS_RES_IRQ,		0,	RF_ACTIVE },	/* Secure */
98	{ SYS_RES_IRQ,		1,	RF_ACTIVE },	/* Non-secure */
99	{ SYS_RES_IRQ,		2,	RF_ACTIVE },	/* Virt */
100	{ SYS_RES_IRQ,		3,	RF_ACTIVE | RF_OPTIONAL	}, /* Hyp */
101	{ -1, 0 }
102};
103
104static timecounter_get_t arm_tmr_get_timecount;
105
106static struct timecounter arm_tmr_timecount = {
107	.tc_name           = "ARM MPCore Timecounter",
108	.tc_get_timecount  = arm_tmr_get_timecount,
109	.tc_poll_pps       = NULL,
110	.tc_counter_mask   = ~0u,
111	.tc_frequency      = 0,
112	.tc_quality        = 1000,
113};
114
115#ifdef __arm__
116#define	get_el0(x)	cp15_## x ##_get()
117#define	get_el1(x)	cp15_## x ##_get()
118#define	set_el0(x, val)	cp15_## x ##_set(val)
119#define	set_el1(x, val)	cp15_## x ##_set(val)
120#else /* __aarch64__ */
121#define	get_el0(x)	READ_SPECIALREG(x ##_el0)
122#define	get_el1(x)	READ_SPECIALREG(x ##_el1)
123#define	set_el0(x, val)	WRITE_SPECIALREG(x ##_el0, val)
124#define	set_el1(x, val)	WRITE_SPECIALREG(x ##_el1, val)
125#endif
126
127static uint32_t arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th,
128    struct timecounter *tc);
129
130static int
131get_freq(void)
132{
133	return (get_el0(cntfrq));
134}
135
136static long
137get_cntxct(bool physical)
138{
139	uint64_t val;
140
141	isb();
142	if (physical)
143		val = get_el0(cntpct);
144	else
145		val = get_el0(cntvct);
146
147	return (val);
148}
149
150static int
151set_ctrl(uint32_t val, bool physical)
152{
153
154	if (physical)
155		set_el0(cntp_ctl, val);
156	else
157		set_el0(cntv_ctl, val);
158	isb();
159
160	return (0);
161}
162
163static int
164set_tval(uint32_t val, bool physical)
165{
166
167	if (physical)
168		set_el0(cntp_tval, val);
169	else
170		set_el0(cntv_tval, val);
171	isb();
172
173	return (0);
174}
175
176static int
177get_ctrl(bool physical)
178{
179	uint32_t val;
180
181	if (physical)
182		val = get_el0(cntp_ctl);
183	else
184		val = get_el0(cntv_ctl);
185
186	return (val);
187}
188
189static void
190setup_user_access(void *arg __unused)
191{
192	uint32_t cntkctl;
193
194	cntkctl = get_el1(cntkctl);
195	cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN |
196	    GT_CNTKCTL_EVNTEN);
197	if (arm_tmr_sc->physical) {
198		cntkctl |= GT_CNTKCTL_PL0PCTEN;
199		cntkctl &= ~GT_CNTKCTL_PL0VCTEN;
200	} else {
201		cntkctl |= GT_CNTKCTL_PL0VCTEN;
202		cntkctl &= ~GT_CNTKCTL_PL0PCTEN;
203	}
204	set_el1(cntkctl, cntkctl);
205	isb();
206}
207
208static void
209tmr_setup_user_access(void *arg __unused)
210{
211
212	smp_rendezvous(NULL, setup_user_access, NULL, NULL);
213}
214SYSINIT(tmr_ua, SI_SUB_SMP, SI_ORDER_SECOND, tmr_setup_user_access, NULL);
215
216static unsigned
217arm_tmr_get_timecount(struct timecounter *tc)
218{
219
220	return (get_cntxct(arm_tmr_sc->physical));
221}
222
223static int
224arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
225{
226	struct arm_tmr_softc *sc;
227	int counts, ctrl;
228
229	sc = (struct arm_tmr_softc *)et->et_priv;
230
231	if (first != 0) {
232		counts = ((uint32_t)et->et_frequency * first) >> 32;
233		ctrl = get_ctrl(sc->physical);
234		ctrl &= ~GT_CTRL_INT_MASK;
235		ctrl |= GT_CTRL_ENABLE;
236		set_tval(counts, sc->physical);
237		set_ctrl(ctrl, sc->physical);
238		return (0);
239	}
240
241	return (EINVAL);
242
243}
244
245static int
246arm_tmr_stop(struct eventtimer *et)
247{
248	struct arm_tmr_softc *sc;
249	int ctrl;
250
251	sc = (struct arm_tmr_softc *)et->et_priv;
252
253	ctrl = get_ctrl(sc->physical);
254	ctrl &= GT_CTRL_ENABLE;
255	set_ctrl(ctrl, sc->physical);
256
257	return (0);
258}
259
260static int
261arm_tmr_intr(void *arg)
262{
263	struct arm_tmr_softc *sc;
264	int ctrl;
265
266	sc = (struct arm_tmr_softc *)arg;
267	ctrl = get_ctrl(sc->physical);
268	if (ctrl & GT_CTRL_INT_STAT) {
269		ctrl |= GT_CTRL_INT_MASK;
270		set_ctrl(ctrl, sc->physical);
271	}
272
273	if (sc->et.et_active)
274		sc->et.et_event_cb(&sc->et, sc->et.et_arg);
275
276	return (FILTER_HANDLED);
277}
278
279#ifdef FDT
280static int
281arm_tmr_fdt_probe(device_t dev)
282{
283
284	if (!ofw_bus_status_okay(dev))
285		return (ENXIO);
286
287	if (ofw_bus_is_compatible(dev, "arm,armv7-timer")) {
288		device_set_desc(dev, "ARMv7 Generic Timer");
289		return (BUS_PROBE_DEFAULT);
290	} else if (ofw_bus_is_compatible(dev, "arm,armv8-timer")) {
291		device_set_desc(dev, "ARMv8 Generic Timer");
292		return (BUS_PROBE_DEFAULT);
293	}
294
295	return (ENXIO);
296}
297#endif
298
299#ifdef DEV_ACPI
300static void
301arm_tmr_acpi_identify(driver_t *driver, device_t parent)
302{
303	ACPI_TABLE_GTDT *gtdt;
304	vm_paddr_t physaddr;
305	device_t dev;
306
307	physaddr = acpi_find_table(ACPI_SIG_GTDT);
308	if (physaddr == 0)
309		return;
310
311	gtdt = acpi_map_table(physaddr, ACPI_SIG_GTDT);
312	if (gtdt == NULL) {
313		device_printf(parent, "gic: Unable to map the GTDT\n");
314		return;
315	}
316
317	dev = BUS_ADD_CHILD(parent, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE,
318	    "generic_timer", -1);
319	if (dev == NULL) {
320		device_printf(parent, "add gic child failed\n");
321		goto out;
322	}
323
324	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0,
325	    gtdt->SecureEl1Interrupt, 1);
326	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1,
327	    gtdt->NonSecureEl1Interrupt, 1);
328	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2,
329	    gtdt->VirtualTimerInterrupt, 1);
330
331out:
332	acpi_unmap_table(gtdt);
333}
334
335static int
336arm_tmr_acpi_probe(device_t dev)
337{
338
339	device_set_desc(dev, "ARM Generic Timer");
340	return (BUS_PROBE_NOWILDCARD);
341}
342#endif
343
344
345static int
346arm_tmr_attach(device_t dev)
347{
348	struct arm_tmr_softc *sc;
349#ifdef FDT
350	phandle_t node;
351	pcell_t clock;
352#endif
353	int error;
354	int i;
355
356	sc = device_get_softc(dev);
357	if (arm_tmr_sc)
358		return (ENXIO);
359
360#ifdef FDT
361	/* Get the base clock frequency */
362	node = ofw_bus_get_node(dev);
363	if (node > 0) {
364		error = OF_getencprop(node, "clock-frequency", &clock,
365		    sizeof(clock));
366	}
367#endif
368
369	if (sc->clkfreq == 0) {
370		/* Try to get clock frequency from timer */
371		sc->clkfreq = get_freq();
372	}
373
374	if (sc->clkfreq == 0) {
375		device_printf(dev, "No clock frequency specified\n");
376		return (ENXIO);
377	}
378
379	if (bus_alloc_resources(dev, timer_spec, sc->res)) {
380		device_printf(dev, "could not allocate resources\n");
381		return (ENXIO);
382	}
383
384#ifdef __arm__
385	sc->physical = true;
386#else /* __aarch64__ */
387	sc->physical = false;
388#endif
389
390	arm_tmr_sc = sc;
391
392	/* Setup secure, non-secure and virtual IRQs handler */
393	for (i = 0; i < 3; i++) {
394		error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK,
395		    arm_tmr_intr, NULL, sc, &sc->ihl[i]);
396		if (error) {
397			device_printf(dev, "Unable to alloc int resource.\n");
398			return (ENXIO);
399		}
400	}
401
402	arm_cpu_fill_vdso_timehands = arm_tmr_fill_vdso_timehands;
403
404	arm_tmr_timecount.tc_frequency = sc->clkfreq;
405	tc_init(&arm_tmr_timecount);
406
407	sc->et.et_name = "ARM MPCore Eventtimer";
408	sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
409	sc->et.et_quality = 1000;
410
411	sc->et.et_frequency = sc->clkfreq;
412	sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
413	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
414	sc->et.et_start = arm_tmr_start;
415	sc->et.et_stop = arm_tmr_stop;
416	sc->et.et_priv = sc;
417	et_register(&sc->et);
418
419	return (0);
420}
421
422#ifdef FDT
423static device_method_t arm_tmr_fdt_methods[] = {
424	DEVMETHOD(device_probe,		arm_tmr_fdt_probe),
425	DEVMETHOD(device_attach,	arm_tmr_attach),
426	{ 0, 0 }
427};
428
429static driver_t arm_tmr_fdt_driver = {
430	"generic_timer",
431	arm_tmr_fdt_methods,
432	sizeof(struct arm_tmr_softc),
433};
434
435static devclass_t arm_tmr_fdt_devclass;
436
437EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass,
438    0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
439EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass,
440    0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
441#endif
442
443#ifdef DEV_ACPI
444static device_method_t arm_tmr_acpi_methods[] = {
445	DEVMETHOD(device_identify,	arm_tmr_acpi_identify),
446	DEVMETHOD(device_probe,		arm_tmr_acpi_probe),
447	DEVMETHOD(device_attach,	arm_tmr_attach),
448	{ 0, 0 }
449};
450
451static driver_t arm_tmr_acpi_driver = {
452	"generic_timer",
453	arm_tmr_acpi_methods,
454	sizeof(struct arm_tmr_softc),
455};
456
457static devclass_t arm_tmr_acpi_devclass;
458
459EARLY_DRIVER_MODULE(timer, acpi, arm_tmr_acpi_driver, arm_tmr_acpi_devclass,
460    0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
461#endif
462
463void
464DELAY(int usec)
465{
466	int32_t counts, counts_per_usec;
467	uint32_t first, last;
468
469	/*
470	 * Check the timers are setup, if not just
471	 * use a for loop for the meantime
472	 */
473	if (arm_tmr_sc == NULL) {
474		for (; usec > 0; usec--)
475			for (counts = 200; counts > 0; counts--)
476				/*
477				 * Prevent the compiler from optimizing
478				 * out the loop
479				 */
480				cpufunc_nullop();
481		return;
482	}
483
484	/* Get the number of times to count */
485	counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1);
486
487	/*
488	 * Clamp the timeout at a maximum value (about 32 seconds with
489	 * a 66MHz clock). *Nobody* should be delay()ing for anywhere
490	 * near that length of time and if they are, they should be hung
491	 * out to dry.
492	 */
493	if (usec >= (0x80000000U / counts_per_usec))
494		counts = (0x80000000U / counts_per_usec) - 1;
495	else
496		counts = usec * counts_per_usec;
497
498	first = get_cntxct(arm_tmr_sc->physical);
499
500	while (counts > 0) {
501		last = get_cntxct(arm_tmr_sc->physical);
502		counts -= (int32_t)(last - first);
503		first = last;
504	}
505}
506
507static uint32_t
508arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th,
509    struct timecounter *tc)
510{
511
512	vdso_th->th_physical = arm_tmr_sc->physical;
513	bzero(vdso_th->th_res, sizeof(vdso_th->th_res));
514	return (tc == &arm_tmr_timecount);
515}
516