generic_timer.c revision 299071
1252372Sray/*- 2252372Sray * Copyright (c) 2011 The FreeBSD Foundation 3252372Sray * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com> 4252372Sray * All rights reserved. 5252372Sray * 6252372Sray * Based on mpcore_timer.c developed by Ben Gray <ben.r.gray@gmail.com> 7252372Sray * 8252372Sray * Redistribution and use in source and binary forms, with or without 9252372Sray * modification, are permitted provided that the following conditions 10252372Sray * are met: 11252372Sray * 1. Redistributions of source code must retain the above copyright 12252372Sray * notice, this list of conditions and the following disclaimer. 13252372Sray * 2. Redistributions in binary form must reproduce the above copyright 14252372Sray * notice, this list of conditions and the following disclaimer in the 15252372Sray * documentation and/or other materials provided with the distribution. 16252372Sray * 3. The name of the company nor the name of the author may be used to 17252372Sray * endorse or promote products derived from this software without specific 18252372Sray * prior written permission. 19252372Sray * 20252372Sray * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21252372Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22252372Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23252372Sray * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24252372Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25252372Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26252372Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27252372Sray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28252372Sray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29252372Sray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30252372Sray * SUCH DAMAGE. 31252372Sray */ 32252372Sray 33252372Sray/** 34282483Sandrew * Cortex-A7, Cortex-A15, ARMv8 and later Generic Timer 35252372Sray */ 36252372Sray 37284273Sandrew#include "opt_acpi.h" 38284273Sandrew#include "opt_platform.h" 39284273Sandrew 40252372Sray#include <sys/cdefs.h> 41252372Sray__FBSDID("$FreeBSD: head/sys/arm/arm/generic_timer.c 299071 2016-05-04 16:09:51Z bz $"); 42252372Sray 43252372Sray#include <sys/param.h> 44252372Sray#include <sys/systm.h> 45252372Sray#include <sys/bus.h> 46252372Sray#include <sys/kernel.h> 47252372Sray#include <sys/module.h> 48252372Sray#include <sys/malloc.h> 49252372Sray#include <sys/rman.h> 50252372Sray#include <sys/timeet.h> 51252372Sray#include <sys/timetc.h> 52291937Skib#include <sys/smp.h> 53291937Skib#include <sys/vdso.h> 54252372Sray#include <sys/watchdog.h> 55252372Sray#include <machine/bus.h> 56252372Sray#include <machine/cpu.h> 57252372Sray#include <machine/intr.h> 58291937Skib#include <machine/md_var.h> 59252372Sray 60298854Sandrew#ifdef MULTIDELAY 61298854Sandrew#include <machine/machdep.h> /* For arm_set_delay */ 62298854Sandrew#endif 63298854Sandrew 64284273Sandrew#ifdef FDT 65252372Sray#include <dev/fdt/fdt_common.h> 66252372Sray#include <dev/ofw/openfirm.h> 67252372Sray#include <dev/ofw/ofw_bus.h> 68252372Sray#include <dev/ofw/ofw_bus_subr.h> 69284273Sandrew#endif 70252372Sray 71284273Sandrew#ifdef DEV_ACPI 72284273Sandrew#include <contrib/dev/acpica/include/acpi.h> 73284273Sandrew#include <dev/acpica/acpivar.h> 74284273Sandrew#endif 75252372Sray 76252780Sray#define GT_CTRL_ENABLE (1 << 0) 77252780Sray#define GT_CTRL_INT_MASK (1 << 1) 78252780Sray#define GT_CTRL_INT_STAT (1 << 2) 79252780Sray#define GT_REG_CTRL 0 80252780Sray#define GT_REG_TVAL 1 81252372Sray 82252780Sray#define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */ 83252780Sray#define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */ 84271189Sandrew#define GT_CNTKCTL_EVNTI (0xf << 4) /* Virtual counter event bits */ 85252780Sray#define GT_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter event transition */ 86252780Sray#define GT_CNTKCTL_EVNTEN (1 << 2) /* Enables virtual counter events */ 87252780Sray#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */ 88252780Sray#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */ 89252372Sray 90252372Sraystruct arm_tmr_softc { 91264065Sbr struct resource *res[4]; 92264065Sbr void *ihl[4]; 93252372Sray uint32_t clkfreq; 94252372Sray struct eventtimer et; 95271189Sandrew bool physical; 96252372Sray}; 97252372Sray 98252372Sraystatic struct arm_tmr_softc *arm_tmr_sc = NULL; 99252372Sray 100264065Sbrstatic struct resource_spec timer_spec[] = { 101264065Sbr { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Secure */ 102264065Sbr { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Non-secure */ 103264065Sbr { SYS_RES_IRQ, 2, RF_ACTIVE }, /* Virt */ 104275207Sandrew { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, /* Hyp */ 105264065Sbr { -1, 0 } 106264065Sbr}; 107264065Sbr 108252372Sraystatic timecounter_get_t arm_tmr_get_timecount; 109252372Sray 110252372Sraystatic struct timecounter arm_tmr_timecount = { 111252372Sray .tc_name = "ARM MPCore Timecounter", 112252372Sray .tc_get_timecount = arm_tmr_get_timecount, 113252372Sray .tc_poll_pps = NULL, 114252372Sray .tc_counter_mask = ~0u, 115252372Sray .tc_frequency = 0, 116252372Sray .tc_quality = 1000, 117252372Sray}; 118252372Sray 119281072Sandrew#ifdef __arm__ 120281072Sandrew#define get_el0(x) cp15_## x ##_get() 121281072Sandrew#define get_el1(x) cp15_## x ##_get() 122281072Sandrew#define set_el0(x, val) cp15_## x ##_set(val) 123281072Sandrew#define set_el1(x, val) cp15_## x ##_set(val) 124281072Sandrew#else /* __aarch64__ */ 125281072Sandrew#define get_el0(x) READ_SPECIALREG(x ##_el0) 126281072Sandrew#define get_el1(x) READ_SPECIALREG(x ##_el1) 127281072Sandrew#define set_el0(x, val) WRITE_SPECIALREG(x ##_el0, val) 128281072Sandrew#define set_el1(x, val) WRITE_SPECIALREG(x ##_el1, val) 129281072Sandrew#endif 130281072Sandrew 131291937Skibstatic uint32_t arm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, 132291937Skib struct timecounter *tc); 133298854Sandrewstatic void arm_tmr_do_delay(int usec, void *); 134291937Skib 135271189Sandrewstatic int 136252372Srayget_freq(void) 137252372Sray{ 138281072Sandrew return (get_el0(cntfrq)); 139252372Sray} 140252372Sray 141271189Sandrewstatic long 142271189Sandrewget_cntxct(bool physical) 143252372Sray{ 144271189Sandrew uint64_t val; 145252372Sray 146252372Sray isb(); 147271189Sandrew if (physical) 148281072Sandrew val = get_el0(cntpct); 149271189Sandrew else 150281072Sandrew val = get_el0(cntvct); 151252372Sray 152252372Sray return (val); 153252372Sray} 154252372Sray 155271189Sandrewstatic int 156271189Sandrewset_ctrl(uint32_t val, bool physical) 157252372Sray{ 158252372Sray 159271189Sandrew if (physical) 160281072Sandrew set_el0(cntp_ctl, val); 161271189Sandrew else 162281072Sandrew set_el0(cntv_ctl, val); 163252372Sray isb(); 164252372Sray 165252372Sray return (0); 166252372Sray} 167252372Sray 168271189Sandrewstatic int 169271189Sandrewset_tval(uint32_t val, bool physical) 170252372Sray{ 171252372Sray 172271189Sandrew if (physical) 173281072Sandrew set_el0(cntp_tval, val); 174271189Sandrew else 175281072Sandrew set_el0(cntv_tval, val); 176252372Sray isb(); 177252372Sray 178252372Sray return (0); 179252372Sray} 180252372Sray 181271189Sandrewstatic int 182271189Sandrewget_ctrl(bool physical) 183252372Sray{ 184252372Sray uint32_t val; 185252372Sray 186271189Sandrew if (physical) 187281072Sandrew val = get_el0(cntp_ctl); 188271189Sandrew else 189281072Sandrew val = get_el0(cntv_ctl); 190252372Sray 191252372Sray return (val); 192252372Sray} 193252372Sray 194271189Sandrewstatic void 195291937Skibsetup_user_access(void *arg __unused) 196252372Sray{ 197252372Sray uint32_t cntkctl; 198252372Sray 199281072Sandrew cntkctl = get_el1(cntkctl); 200252780Sray cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN | 201291937Skib GT_CNTKCTL_EVNTEN); 202291937Skib if (arm_tmr_sc->physical) { 203291937Skib cntkctl |= GT_CNTKCTL_PL0PCTEN; 204291937Skib cntkctl &= ~GT_CNTKCTL_PL0VCTEN; 205291937Skib } else { 206291937Skib cntkctl |= GT_CNTKCTL_PL0VCTEN; 207291937Skib cntkctl &= ~GT_CNTKCTL_PL0PCTEN; 208291937Skib } 209281072Sandrew set_el1(cntkctl, cntkctl); 210252372Sray isb(); 211252372Sray} 212252372Sray 213291937Skibstatic void 214291937Skibtmr_setup_user_access(void *arg __unused) 215291937Skib{ 216291937Skib 217291937Skib smp_rendezvous(NULL, setup_user_access, NULL, NULL); 218291937Skib} 219291937SkibSYSINIT(tmr_ua, SI_SUB_SMP, SI_ORDER_SECOND, tmr_setup_user_access, NULL); 220291937Skib 221252372Sraystatic unsigned 222252372Srayarm_tmr_get_timecount(struct timecounter *tc) 223252372Sray{ 224252372Sray 225271189Sandrew return (get_cntxct(arm_tmr_sc->physical)); 226252372Sray} 227252372Sray 228252372Sraystatic int 229298648Sbzarm_tmr_start(struct eventtimer *et, sbintime_t first, 230298648Sbz sbintime_t period __unused) 231252372Sray{ 232252372Sray struct arm_tmr_softc *sc; 233252372Sray int counts, ctrl; 234252372Sray 235252372Sray sc = (struct arm_tmr_softc *)et->et_priv; 236252372Sray 237252372Sray if (first != 0) { 238252372Sray counts = ((uint32_t)et->et_frequency * first) >> 32; 239271189Sandrew ctrl = get_ctrl(sc->physical); 240252780Sray ctrl &= ~GT_CTRL_INT_MASK; 241252780Sray ctrl |= GT_CTRL_ENABLE; 242271189Sandrew set_tval(counts, sc->physical); 243271189Sandrew set_ctrl(ctrl, sc->physical); 244252372Sray return (0); 245252372Sray } 246252372Sray 247252372Sray return (EINVAL); 248252372Sray 249252372Sray} 250252372Sray 251252372Sraystatic int 252252372Srayarm_tmr_stop(struct eventtimer *et) 253252372Sray{ 254271189Sandrew struct arm_tmr_softc *sc; 255252372Sray int ctrl; 256252372Sray 257271189Sandrew sc = (struct arm_tmr_softc *)et->et_priv; 258271189Sandrew 259271189Sandrew ctrl = get_ctrl(sc->physical); 260252780Sray ctrl &= GT_CTRL_ENABLE; 261271189Sandrew set_ctrl(ctrl, sc->physical); 262252372Sray 263252372Sray return (0); 264252372Sray} 265252372Sray 266252372Sraystatic int 267252372Srayarm_tmr_intr(void *arg) 268252372Sray{ 269252372Sray struct arm_tmr_softc *sc; 270252372Sray int ctrl; 271252372Sray 272252372Sray sc = (struct arm_tmr_softc *)arg; 273271189Sandrew ctrl = get_ctrl(sc->physical); 274252780Sray if (ctrl & GT_CTRL_INT_STAT) { 275252780Sray ctrl |= GT_CTRL_INT_MASK; 276271189Sandrew set_ctrl(ctrl, sc->physical); 277252372Sray } 278252372Sray 279252372Sray if (sc->et.et_active) 280252372Sray sc->et.et_event_cb(&sc->et, sc->et.et_arg); 281252372Sray 282252372Sray return (FILTER_HANDLED); 283252372Sray} 284252372Sray 285284273Sandrew#ifdef FDT 286252372Sraystatic int 287284273Sandrewarm_tmr_fdt_probe(device_t dev) 288252372Sray{ 289252372Sray 290261410Sian if (!ofw_bus_status_okay(dev)) 291261410Sian return (ENXIO); 292261410Sian 293281072Sandrew if (ofw_bus_is_compatible(dev, "arm,armv7-timer")) { 294281072Sandrew device_set_desc(dev, "ARMv7 Generic Timer"); 295281072Sandrew return (BUS_PROBE_DEFAULT); 296281072Sandrew } else if (ofw_bus_is_compatible(dev, "arm,armv8-timer")) { 297281072Sandrew device_set_desc(dev, "ARMv8 Generic Timer"); 298281072Sandrew return (BUS_PROBE_DEFAULT); 299281072Sandrew } 300252372Sray 301281072Sandrew return (ENXIO); 302252372Sray} 303284273Sandrew#endif 304252372Sray 305284273Sandrew#ifdef DEV_ACPI 306284273Sandrewstatic void 307284273Sandrewarm_tmr_acpi_identify(driver_t *driver, device_t parent) 308284273Sandrew{ 309284273Sandrew ACPI_TABLE_GTDT *gtdt; 310284273Sandrew vm_paddr_t physaddr; 311284273Sandrew device_t dev; 312252372Sray 313284273Sandrew physaddr = acpi_find_table(ACPI_SIG_GTDT); 314284273Sandrew if (physaddr == 0) 315284273Sandrew return; 316284273Sandrew 317284273Sandrew gtdt = acpi_map_table(physaddr, ACPI_SIG_GTDT); 318284273Sandrew if (gtdt == NULL) { 319284273Sandrew device_printf(parent, "gic: Unable to map the GTDT\n"); 320284273Sandrew return; 321284273Sandrew } 322284273Sandrew 323284273Sandrew dev = BUS_ADD_CHILD(parent, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE, 324284273Sandrew "generic_timer", -1); 325284273Sandrew if (dev == NULL) { 326284273Sandrew device_printf(parent, "add gic child failed\n"); 327284273Sandrew goto out; 328284273Sandrew } 329284273Sandrew 330284273Sandrew BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0, 331284273Sandrew gtdt->SecureEl1Interrupt, 1); 332284273Sandrew BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1, 333284273Sandrew gtdt->NonSecureEl1Interrupt, 1); 334284273Sandrew BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2, 335284273Sandrew gtdt->VirtualTimerInterrupt, 1); 336284273Sandrew 337284273Sandrewout: 338284273Sandrew acpi_unmap_table(gtdt); 339284273Sandrew} 340284273Sandrew 341252372Sraystatic int 342284273Sandrewarm_tmr_acpi_probe(device_t dev) 343284273Sandrew{ 344284273Sandrew 345284273Sandrew device_set_desc(dev, "ARM Generic Timer"); 346284273Sandrew return (BUS_PROBE_NOWILDCARD); 347284273Sandrew} 348284273Sandrew#endif 349284273Sandrew 350284273Sandrew 351284273Sandrewstatic int 352252372Srayarm_tmr_attach(device_t dev) 353252372Sray{ 354252372Sray struct arm_tmr_softc *sc; 355284273Sandrew#ifdef FDT 356252372Sray phandle_t node; 357252372Sray pcell_t clock; 358284273Sandrew#endif 359252372Sray int error; 360264065Sbr int i; 361252372Sray 362252372Sray sc = device_get_softc(dev); 363252372Sray if (arm_tmr_sc) 364252372Sray return (ENXIO); 365252372Sray 366284273Sandrew#ifdef FDT 367252372Sray /* Get the base clock frequency */ 368252372Sray node = ofw_bus_get_node(dev); 369284273Sandrew if (node > 0) { 370295470Sandrew error = OF_getencprop(node, "clock-frequency", &clock, 371284273Sandrew sizeof(clock)); 372295633Sandrew if (error > 0) 373295633Sandrew sc->clkfreq = clock; 374264065Sbr } 375284273Sandrew#endif 376264065Sbr 377264065Sbr if (sc->clkfreq == 0) { 378264065Sbr /* Try to get clock frequency from timer */ 379264065Sbr sc->clkfreq = get_freq(); 380264065Sbr } 381264065Sbr 382264065Sbr if (sc->clkfreq == 0) { 383264065Sbr device_printf(dev, "No clock frequency specified\n"); 384252372Sray return (ENXIO); 385252372Sray } 386252372Sray 387264065Sbr if (bus_alloc_resources(dev, timer_spec, sc->res)) { 388264065Sbr device_printf(dev, "could not allocate resources\n"); 389264065Sbr return (ENXIO); 390271189Sandrew } 391252372Sray 392281072Sandrew#ifdef __arm__ 393271189Sandrew sc->physical = true; 394281072Sandrew#else /* __aarch64__ */ 395281072Sandrew sc->physical = false; 396281072Sandrew#endif 397271189Sandrew 398252372Sray arm_tmr_sc = sc; 399252372Sray 400271189Sandrew /* Setup secure, non-secure and virtual IRQs handler */ 401271189Sandrew for (i = 0; i < 3; i++) { 402264065Sbr error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK, 403264065Sbr arm_tmr_intr, NULL, sc, &sc->ihl[i]); 404264065Sbr if (error) { 405264065Sbr device_printf(dev, "Unable to alloc int resource.\n"); 406264065Sbr return (ENXIO); 407264065Sbr } 408252372Sray } 409252372Sray 410291937Skib arm_cpu_fill_vdso_timehands = arm_tmr_fill_vdso_timehands; 411252372Sray 412252427Sray arm_tmr_timecount.tc_frequency = sc->clkfreq; 413252372Sray tc_init(&arm_tmr_timecount); 414252372Sray 415252372Sray sc->et.et_name = "ARM MPCore Eventtimer"; 416252372Sray sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU; 417252372Sray sc->et.et_quality = 1000; 418252372Sray 419252372Sray sc->et.et_frequency = sc->clkfreq; 420299071Sbz sc->et.et_min_period = (0x00000010LLU << 32) / sc->et.et_frequency; 421252372Sray sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; 422252372Sray sc->et.et_start = arm_tmr_start; 423252372Sray sc->et.et_stop = arm_tmr_stop; 424252372Sray sc->et.et_priv = sc; 425252372Sray et_register(&sc->et); 426252372Sray 427298854Sandrew#ifdef MULTIDELAY 428298854Sandrew arm_set_delay(arm_tmr_do_delay, sc); 429298854Sandrew#endif 430298854Sandrew 431252372Sray return (0); 432252372Sray} 433252372Sray 434284273Sandrew#ifdef FDT 435284273Sandrewstatic device_method_t arm_tmr_fdt_methods[] = { 436284273Sandrew DEVMETHOD(device_probe, arm_tmr_fdt_probe), 437252372Sray DEVMETHOD(device_attach, arm_tmr_attach), 438252372Sray { 0, 0 } 439252372Sray}; 440252372Sray 441284273Sandrewstatic driver_t arm_tmr_fdt_driver = { 442252372Sray "generic_timer", 443284273Sandrew arm_tmr_fdt_methods, 444252372Sray sizeof(struct arm_tmr_softc), 445252372Sray}; 446252372Sray 447284273Sandrewstatic devclass_t arm_tmr_fdt_devclass; 448252372Sray 449284273SandrewEARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass, 450284273Sandrew 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); 451284273SandrewEARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_fdt_driver, arm_tmr_fdt_devclass, 452284273Sandrew 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); 453284273Sandrew#endif 454252372Sray 455284273Sandrew#ifdef DEV_ACPI 456284273Sandrewstatic device_method_t arm_tmr_acpi_methods[] = { 457284273Sandrew DEVMETHOD(device_identify, arm_tmr_acpi_identify), 458284273Sandrew DEVMETHOD(device_probe, arm_tmr_acpi_probe), 459284273Sandrew DEVMETHOD(device_attach, arm_tmr_attach), 460284273Sandrew { 0, 0 } 461284273Sandrew}; 462284273Sandrew 463284273Sandrewstatic driver_t arm_tmr_acpi_driver = { 464284273Sandrew "generic_timer", 465284273Sandrew arm_tmr_acpi_methods, 466284273Sandrew sizeof(struct arm_tmr_softc), 467284273Sandrew}; 468284273Sandrew 469284273Sandrewstatic devclass_t arm_tmr_acpi_devclass; 470284273Sandrew 471284273SandrewEARLY_DRIVER_MODULE(timer, acpi, arm_tmr_acpi_driver, arm_tmr_acpi_devclass, 472284273Sandrew 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); 473284273Sandrew#endif 474284273Sandrew 475298854Sandrewstatic void 476298854Sandrewarm_tmr_do_delay(int usec, void *arg) 477252372Sray{ 478298854Sandrew struct arm_tmr_softc *sc = arg; 479252372Sray int32_t counts, counts_per_usec; 480252372Sray uint32_t first, last; 481252372Sray 482252372Sray /* Get the number of times to count */ 483252427Sray counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1); 484252372Sray 485252372Sray /* 486252372Sray * Clamp the timeout at a maximum value (about 32 seconds with 487252372Sray * a 66MHz clock). *Nobody* should be delay()ing for anywhere 488252372Sray * near that length of time and if they are, they should be hung 489252372Sray * out to dry. 490252372Sray */ 491252372Sray if (usec >= (0x80000000U / counts_per_usec)) 492252372Sray counts = (0x80000000U / counts_per_usec) - 1; 493252372Sray else 494252372Sray counts = usec * counts_per_usec; 495252372Sray 496298854Sandrew first = get_cntxct(sc->physical); 497252372Sray 498252372Sray while (counts > 0) { 499298854Sandrew last = get_cntxct(sc->physical); 500252372Sray counts -= (int32_t)(last - first); 501252372Sray first = last; 502252372Sray } 503252372Sray} 504291937Skib 505298854Sandrew#ifndef MULTIDELAY 506298854Sandrewvoid 507298854SandrewDELAY(int usec) 508298854Sandrew{ 509298854Sandrew int32_t counts; 510298854Sandrew 511298854Sandrew /* 512298854Sandrew * Check the timers are setup, if not just 513298854Sandrew * use a for loop for the meantime 514298854Sandrew */ 515298854Sandrew if (arm_tmr_sc == NULL) { 516298854Sandrew for (; usec > 0; usec--) 517298854Sandrew for (counts = 200; counts > 0; counts--) 518298854Sandrew /* 519298854Sandrew * Prevent the compiler from optimizing 520298854Sandrew * out the loop 521298854Sandrew */ 522298854Sandrew cpufunc_nullop(); 523298854Sandrew } else 524298854Sandrew arm_tmr_do_delay(usec, arm_tmr_sc); 525298854Sandrew} 526298854Sandrew#endif 527298854Sandrew 528291937Skibstatic uint32_t 529291937Skibarm_tmr_fill_vdso_timehands(struct vdso_timehands *vdso_th, 530291937Skib struct timecounter *tc) 531291937Skib{ 532291937Skib 533291937Skib vdso_th->th_physical = arm_tmr_sc->physical; 534291937Skib bzero(vdso_th->th_res, sizeof(vdso_th->th_res)); 535291937Skib return (tc == &arm_tmr_timecount); 536291937Skib} 537