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