1239268Sgonzo/*- 2239268Sgonzo * Copyright (c) 2011 The FreeBSD Foundation 3239268Sgonzo * All rights reserved. 4239268Sgonzo * 5239268Sgonzo * Developed by Ben Gray <ben.r.gray@gmail.com> 6239268Sgonzo * 7239268Sgonzo * Redistribution and use in source and binary forms, with or without 8239268Sgonzo * modification, are permitted provided that the following conditions 9239268Sgonzo * are met: 10239268Sgonzo * 1. Redistributions of source code must retain the above copyright 11239268Sgonzo * notice, this list of conditions and the following disclaimer. 12239268Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 13239268Sgonzo * notice, this list of conditions and the following disclaimer in the 14239268Sgonzo * documentation and/or other materials provided with the distribution. 15239268Sgonzo * 3. The name of the company nor the name of the author may be used to 16239268Sgonzo * endorse or promote products derived from this software without specific 17239268Sgonzo * prior written permission. 18239268Sgonzo * 19239268Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20239268Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21239268Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22239268Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23239268Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24239268Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25239268Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26239268Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27239268Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28239268Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29239268Sgonzo * SUCH DAMAGE. 30239268Sgonzo */ 31239268Sgonzo 32239268Sgonzo/** 33264051Sian * The ARM Cortex-A9 core can support a global timer plus a private and 34264051Sian * watchdog timer per core. This driver reserves memory and interrupt 35264051Sian * resources for accessing both timer register sets, these resources are 36264051Sian * stored globally and used to setup the timecount and eventtimer. 37239268Sgonzo * 38264051Sian * The timecount timer uses the global 64-bit counter, whereas the 39264051Sian * per-CPU eventtimer uses the private 32-bit counters. 40239268Sgonzo * 41239268Sgonzo * 42264051Sian * REF: ARM Cortex-A9 MPCore, Technical Reference Manual (rev. r2p2) 43239268Sgonzo */ 44239268Sgonzo 45239268Sgonzo#include <sys/cdefs.h> 46239268Sgonzo__FBSDID("$FreeBSD: stable/11/sys/arm/arm/mpcore_timer.c 346551 2019-04-22 13:58:28Z ian $"); 47239268Sgonzo 48239268Sgonzo#include <sys/param.h> 49239268Sgonzo#include <sys/systm.h> 50239268Sgonzo#include <sys/bus.h> 51239268Sgonzo#include <sys/kernel.h> 52239268Sgonzo#include <sys/module.h> 53239268Sgonzo#include <sys/malloc.h> 54239268Sgonzo#include <sys/rman.h> 55239268Sgonzo#include <sys/timeet.h> 56239268Sgonzo#include <sys/timetc.h> 57239268Sgonzo#include <sys/watchdog.h> 58239268Sgonzo#include <machine/bus.h> 59239268Sgonzo#include <machine/cpu.h> 60239268Sgonzo#include <machine/intr.h> 61239268Sgonzo 62239268Sgonzo#include <dev/fdt/fdt_common.h> 63239268Sgonzo#include <dev/ofw/openfirm.h> 64239268Sgonzo#include <dev/ofw/ofw_bus.h> 65239268Sgonzo#include <dev/ofw/ofw_bus_subr.h> 66239268Sgonzo 67239268Sgonzo#include <machine/bus.h> 68239268Sgonzo 69264050Sian#include <arm/arm/mpcore_timervar.h> 70264050Sian 71239268Sgonzo/* Private (per-CPU) timer register map */ 72239268Sgonzo#define PRV_TIMER_LOAD 0x0000 73239268Sgonzo#define PRV_TIMER_COUNT 0x0004 74239268Sgonzo#define PRV_TIMER_CTRL 0x0008 75239268Sgonzo#define PRV_TIMER_INTR 0x000C 76239268Sgonzo 77239268Sgonzo#define PRV_TIMER_CTR_PRESCALER_SHIFT 8 78239268Sgonzo#define PRV_TIMER_CTRL_IRQ_ENABLE (1UL << 2) 79239268Sgonzo#define PRV_TIMER_CTRL_AUTO_RELOAD (1UL << 1) 80239268Sgonzo#define PRV_TIMER_CTRL_TIMER_ENABLE (1UL << 0) 81239268Sgonzo 82239268Sgonzo#define PRV_TIMER_INTR_EVENT (1UL << 0) 83239268Sgonzo 84239268Sgonzo/* Global timer register map */ 85239268Sgonzo#define GBL_TIMER_COUNT_LOW 0x0000 86239268Sgonzo#define GBL_TIMER_COUNT_HIGH 0x0004 87239268Sgonzo#define GBL_TIMER_CTRL 0x0008 88239268Sgonzo#define GBL_TIMER_INTR 0x000C 89239268Sgonzo 90239268Sgonzo#define GBL_TIMER_CTR_PRESCALER_SHIFT 8 91239268Sgonzo#define GBL_TIMER_CTRL_AUTO_INC (1UL << 3) 92239268Sgonzo#define GBL_TIMER_CTRL_IRQ_ENABLE (1UL << 2) 93239268Sgonzo#define GBL_TIMER_CTRL_COMP_ENABLE (1UL << 1) 94239268Sgonzo#define GBL_TIMER_CTRL_TIMER_ENABLE (1UL << 0) 95239268Sgonzo 96239268Sgonzo#define GBL_TIMER_INTR_EVENT (1UL << 0) 97239268Sgonzo 98239268Sgonzostruct arm_tmr_softc { 99271906Sian device_t dev; 100271906Sian int irqrid; 101271906Sian int memrid; 102271906Sian struct resource * gbl_mem; 103271906Sian struct resource * prv_mem; 104271906Sian struct resource * prv_irq; 105264050Sian uint64_t clkfreq; 106239268Sgonzo struct eventtimer et; 107239268Sgonzo}; 108239268Sgonzo 109271906Sianstatic struct eventtimer *arm_tmr_et; 110271906Sianstatic struct timecounter *arm_tmr_tc; 111271906Sianstatic uint64_t arm_tmr_freq; 112271906Sianstatic boolean_t arm_tmr_freq_varies; 113239268Sgonzo 114271906Sian#define tmr_prv_read_4(sc, reg) bus_read_4((sc)->prv_mem, reg) 115271906Sian#define tmr_prv_write_4(sc, reg, val) bus_write_4((sc)->prv_mem, reg, val) 116271906Sian#define tmr_gbl_read_4(sc, reg) bus_read_4((sc)->gbl_mem, reg) 117271906Sian#define tmr_gbl_write_4(sc, reg, val) bus_write_4((sc)->gbl_mem, reg, val) 118239268Sgonzo 119239268Sgonzostatic timecounter_get_t arm_tmr_get_timecount; 120239268Sgonzo 121239268Sgonzostatic struct timecounter arm_tmr_timecount = { 122262584Sian .tc_name = "MPCore", 123239268Sgonzo .tc_get_timecount = arm_tmr_get_timecount, 124239268Sgonzo .tc_poll_pps = NULL, 125239268Sgonzo .tc_counter_mask = ~0u, 126239268Sgonzo .tc_frequency = 0, 127262584Sian .tc_quality = 800, 128239268Sgonzo}; 129239268Sgonzo 130271906Sian#define TMR_GBL 0x01 131271906Sian#define TMR_PRV 0x02 132271906Sian#define TMR_BOTH (TMR_GBL | TMR_PRV) 133271906Sian#define TMR_NONE 0 134271906Sian 135271906Sianstatic struct ofw_compat_data compat_data[] = { 136271906Sian {"arm,mpcore-timers", TMR_BOTH}, /* Non-standard, FreeBSD. */ 137271906Sian {"arm,cortex-a9-global-timer", TMR_GBL}, 138271906Sian {"arm,cortex-a5-global-timer", TMR_GBL}, 139271906Sian {"arm,cortex-a9-twd-timer", TMR_PRV}, 140271906Sian {"arm,cortex-a5-twd-timer", TMR_PRV}, 141271906Sian {"arm,arm11mp-twd-timer", TMR_PRV}, 142271906Sian {NULL, TMR_NONE} 143271906Sian}; 144271906Sian 145239268Sgonzo/** 146239268Sgonzo * arm_tmr_get_timecount - reads the timecount (global) timer 147239268Sgonzo * @tc: pointer to arm_tmr_timecount struct 148239268Sgonzo * 149239268Sgonzo * We only read the lower 32-bits, the timecount stuff only uses 32-bits 150239268Sgonzo * so (for now?) ignore the upper 32-bits. 151239268Sgonzo * 152239268Sgonzo * RETURNS 153239268Sgonzo * The lower 32-bits of the counter. 154239268Sgonzo */ 155239268Sgonzostatic unsigned 156239268Sgonzoarm_tmr_get_timecount(struct timecounter *tc) 157239268Sgonzo{ 158271906Sian struct arm_tmr_softc *sc; 159271906Sian 160271906Sian sc = tc->tc_priv; 161271906Sian return (tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW)); 162239268Sgonzo} 163239268Sgonzo 164239268Sgonzo/** 165239268Sgonzo * arm_tmr_start - starts the eventtimer (private) timer 166239268Sgonzo * @et: pointer to eventtimer struct 167239268Sgonzo * @first: the number of seconds and fractional sections to trigger in 168239268Sgonzo * @period: the period (in seconds and fractional sections) to set 169239268Sgonzo * 170239268Sgonzo * If the eventtimer is required to be in oneshot mode, period will be 171239268Sgonzo * NULL and first will point to the time to trigger. If in periodic mode 172239268Sgonzo * period will contain the time period and first may optionally contain 173239268Sgonzo * the time for the first period. 174239268Sgonzo * 175239268Sgonzo * RETURNS 176239268Sgonzo * Always returns 0 177239268Sgonzo */ 178239268Sgonzostatic int 179247463Smavarm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period) 180239268Sgonzo{ 181271906Sian struct arm_tmr_softc *sc; 182239268Sgonzo uint32_t load, count; 183239268Sgonzo uint32_t ctrl; 184239268Sgonzo 185271906Sian sc = et->et_priv; 186271906Sian tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0); 187271906Sian tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT); 188264049Sian 189239268Sgonzo ctrl = PRV_TIMER_CTRL_IRQ_ENABLE | PRV_TIMER_CTRL_TIMER_ENABLE; 190239268Sgonzo 191247463Smav if (period != 0) { 192247463Smav load = ((uint32_t)et->et_frequency * period) >> 32; 193239268Sgonzo ctrl |= PRV_TIMER_CTRL_AUTO_RELOAD; 194247463Smav } else 195239268Sgonzo load = 0; 196239268Sgonzo 197247463Smav if (first != 0) 198264049Sian count = (uint32_t)((et->et_frequency * first) >> 32); 199247463Smav else 200239268Sgonzo count = load; 201239268Sgonzo 202271906Sian tmr_prv_write_4(sc, PRV_TIMER_LOAD, load); 203271906Sian tmr_prv_write_4(sc, PRV_TIMER_COUNT, count); 204271906Sian tmr_prv_write_4(sc, PRV_TIMER_CTRL, ctrl); 205239268Sgonzo 206239268Sgonzo return (0); 207239268Sgonzo} 208239268Sgonzo 209239268Sgonzo/** 210239268Sgonzo * arm_tmr_stop - stops the eventtimer (private) timer 211239268Sgonzo * @et: pointer to eventtimer struct 212239268Sgonzo * 213239268Sgonzo * Simply stops the private timer by clearing all bits in the ctrl register. 214239268Sgonzo * 215239268Sgonzo * RETURNS 216239268Sgonzo * Always returns 0 217239268Sgonzo */ 218239268Sgonzostatic int 219239268Sgonzoarm_tmr_stop(struct eventtimer *et) 220239268Sgonzo{ 221271906Sian struct arm_tmr_softc *sc; 222271906Sian 223271906Sian sc = et->et_priv; 224271906Sian tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0); 225271906Sian tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT); 226239268Sgonzo return (0); 227239268Sgonzo} 228239268Sgonzo 229239268Sgonzo/** 230239268Sgonzo * arm_tmr_intr - ISR for the eventtimer (private) timer 231239268Sgonzo * @arg: pointer to arm_tmr_softc struct 232239268Sgonzo * 233239268Sgonzo * Clears the event register and then calls the eventtimer callback. 234239268Sgonzo * 235239268Sgonzo * RETURNS 236239268Sgonzo * Always returns FILTER_HANDLED 237239268Sgonzo */ 238239268Sgonzostatic int 239239268Sgonzoarm_tmr_intr(void *arg) 240239268Sgonzo{ 241271906Sian struct arm_tmr_softc *sc; 242239268Sgonzo 243271906Sian sc = arg; 244271906Sian tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT); 245239268Sgonzo if (sc->et.et_active) 246239268Sgonzo sc->et.et_event_cb(&sc->et, sc->et.et_arg); 247239268Sgonzo return (FILTER_HANDLED); 248239268Sgonzo} 249239268Sgonzo 250239268Sgonzo 251239268Sgonzo 252239268Sgonzo 253239268Sgonzo/** 254239268Sgonzo * arm_tmr_probe - timer probe routine 255239268Sgonzo * @dev: new device 256239268Sgonzo * 257239268Sgonzo * The probe function returns success when probed with the fdt compatible 258239268Sgonzo * string set to "arm,mpcore-timers". 259239268Sgonzo * 260239268Sgonzo * RETURNS 261239268Sgonzo * BUS_PROBE_DEFAULT if the fdt device is compatible, otherwise ENXIO. 262239268Sgonzo */ 263239268Sgonzostatic int 264239268Sgonzoarm_tmr_probe(device_t dev) 265239268Sgonzo{ 266261410Sian 267261410Sian if (!ofw_bus_status_okay(dev)) 268261410Sian return (ENXIO); 269261410Sian 270271906Sian if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == TMR_NONE) 271239268Sgonzo return (ENXIO); 272239268Sgonzo 273262584Sian device_set_desc(dev, "ARM MPCore Timers"); 274239268Sgonzo return (BUS_PROBE_DEFAULT); 275239268Sgonzo} 276239268Sgonzo 277271906Sianstatic int 278271906Sianattach_tc(struct arm_tmr_softc *sc) 279271906Sian{ 280271906Sian int rid; 281271906Sian 282271906Sian if (arm_tmr_tc != NULL) 283271906Sian return (EBUSY); 284271906Sian 285271906Sian rid = sc->memrid; 286271906Sian sc->gbl_mem = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid, 287271906Sian RF_ACTIVE); 288271906Sian if (sc->gbl_mem == NULL) { 289271906Sian device_printf(sc->dev, "could not allocate gbl mem resources\n"); 290271906Sian return (ENXIO); 291271906Sian } 292271906Sian tmr_gbl_write_4(sc, GBL_TIMER_CTRL, 0x00000000); 293271906Sian 294271906Sian arm_tmr_timecount.tc_frequency = sc->clkfreq; 295271906Sian arm_tmr_timecount.tc_priv = sc; 296271906Sian tc_init(&arm_tmr_timecount); 297271906Sian arm_tmr_tc = &arm_tmr_timecount; 298271906Sian 299271906Sian tmr_gbl_write_4(sc, GBL_TIMER_CTRL, GBL_TIMER_CTRL_TIMER_ENABLE); 300271906Sian 301271906Sian return (0); 302271906Sian} 303271906Sian 304271906Sianstatic int 305271906Sianattach_et(struct arm_tmr_softc *sc) 306271906Sian{ 307271906Sian void *ihl; 308271906Sian int irid, mrid; 309271906Sian 310271906Sian if (arm_tmr_et != NULL) 311271906Sian return (EBUSY); 312271906Sian 313271906Sian mrid = sc->memrid; 314271906Sian sc->prv_mem = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &mrid, 315271906Sian RF_ACTIVE); 316271906Sian if (sc->prv_mem == NULL) { 317271906Sian device_printf(sc->dev, "could not allocate prv mem resources\n"); 318271906Sian return (ENXIO); 319271906Sian } 320271906Sian tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0x00000000); 321271906Sian 322271906Sian irid = sc->irqrid; 323271906Sian sc->prv_irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &irid, RF_ACTIVE); 324271906Sian if (sc->prv_irq == NULL) { 325271906Sian bus_release_resource(sc->dev, SYS_RES_MEMORY, mrid, sc->prv_mem); 326271906Sian device_printf(sc->dev, "could not allocate prv irq resources\n"); 327271906Sian return (ENXIO); 328271906Sian } 329271906Sian 330271906Sian if (bus_setup_intr(sc->dev, sc->prv_irq, INTR_TYPE_CLK, arm_tmr_intr, 331271906Sian NULL, sc, &ihl) != 0) { 332271906Sian bus_release_resource(sc->dev, SYS_RES_MEMORY, mrid, sc->prv_mem); 333271906Sian bus_release_resource(sc->dev, SYS_RES_IRQ, irid, sc->prv_irq); 334271906Sian device_printf(sc->dev, "unable to setup the et irq handler.\n"); 335271906Sian return (ENXIO); 336271906Sian } 337271906Sian 338271906Sian /* 339271906Sian * Setup and register the eventtimer. Most event timers set their min 340271906Sian * and max period values to some value calculated from the clock 341271906Sian * frequency. We might not know yet what our runtime clock frequency 342271906Sian * will be, so we just use some safe values. A max of 2 seconds ensures 343271906Sian * that even if our base clock frequency is 2GHz (meaning a 4GHz CPU), 344271906Sian * we won't overflow our 32-bit timer count register. A min of 20 345271906Sian * nanoseconds is pretty much completely arbitrary. 346271906Sian */ 347271906Sian sc->et.et_name = "MPCore"; 348271906Sian sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU; 349271906Sian sc->et.et_quality = 1000; 350271906Sian sc->et.et_frequency = sc->clkfreq; 351323424Sian sc->et.et_min_period = nstosbt(20); 352271906Sian sc->et.et_max_period = 2 * SBT_1S; 353271906Sian sc->et.et_start = arm_tmr_start; 354271906Sian sc->et.et_stop = arm_tmr_stop; 355271906Sian sc->et.et_priv = sc; 356271906Sian et_register(&sc->et); 357271906Sian arm_tmr_et = &sc->et; 358271906Sian 359271906Sian return (0); 360271906Sian} 361271906Sian 362239268Sgonzo/** 363239268Sgonzo * arm_tmr_attach - attaches the timer to the simplebus 364239268Sgonzo * @dev: new device 365239268Sgonzo * 366239268Sgonzo * Reserves memory and interrupt resources, stores the softc structure 367239268Sgonzo * globally and registers both the timecount and eventtimer objects. 368239268Sgonzo * 369239268Sgonzo * RETURNS 370299069Spfg * Zero on success or ENXIO if an error occuried. 371239268Sgonzo */ 372239268Sgonzostatic int 373239268Sgonzoarm_tmr_attach(device_t dev) 374239268Sgonzo{ 375271906Sian struct arm_tmr_softc *sc; 376239268Sgonzo phandle_t node; 377239268Sgonzo pcell_t clock; 378271906Sian int et_err, tc_err, tmrtype; 379239268Sgonzo 380271906Sian sc = device_get_softc(dev); 381271906Sian sc->dev = dev; 382239268Sgonzo 383271906Sian if (arm_tmr_freq_varies) { 384271906Sian sc->clkfreq = arm_tmr_freq; 385264050Sian } else { 386271906Sian if (arm_tmr_freq != 0) { 387271906Sian sc->clkfreq = arm_tmr_freq; 388264050Sian } else { 389264050Sian /* Get the base clock frequency */ 390264050Sian node = ofw_bus_get_node(dev); 391264050Sian if ((OF_getencprop(node, "clock-frequency", &clock, 392264050Sian sizeof(clock))) <= 0) { 393264050Sian device_printf(dev, "missing clock-frequency " 394264050Sian "attribute in FDT\n"); 395264050Sian return (ENXIO); 396264050Sian } 397264094Sian sc->clkfreq = clock; 398253971Scognet } 399239268Sgonzo } 400239268Sgonzo 401271906Sian tmrtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data; 402271906Sian tc_err = ENXIO; 403271906Sian et_err = ENXIO; 404239268Sgonzo 405264050Sian /* 406271906Sian * If we're handling the global timer and it is fixed-frequency, set it 407271906Sian * up to use as a timecounter. If it's variable frequency it won't work 408271906Sian * as a timecounter. We also can't use it for DELAY(), so hopefully the 409271906Sian * platform provides its own implementation. If it doesn't, ours will 410264050Sian * get used, but since the frequency isn't set, it will only use the 411264050Sian * bogus loop counter. 412264050Sian */ 413271906Sian if (tmrtype & TMR_GBL) { 414271906Sian if (!arm_tmr_freq_varies) 415271906Sian tc_err = attach_tc(sc); 416271906Sian else if (bootverbose) 417283366Sandrew device_printf(sc->dev, 418346551Sian "not using variable-frequency device as timecounter\n"); 419271906Sian sc->memrid++; 420271906Sian sc->irqrid++; 421264050Sian } 422264050Sian 423271906Sian /* If we are handling the private timer, set it up as an eventtimer. */ 424271906Sian if (tmrtype & TMR_PRV) { 425271906Sian et_err = attach_et(sc); 426271906Sian } 427271906Sian 428264050Sian /* 429271906Sian * If we didn't successfully set up a timecounter or eventtimer then we 430271906Sian * didn't actually attach at all, return error. 431264050Sian */ 432271906Sian if (tc_err != 0 && et_err != 0) { 433271906Sian return (ENXIO); 434271906Sian } 435239268Sgonzo return (0); 436239268Sgonzo} 437239268Sgonzo 438239268Sgonzostatic device_method_t arm_tmr_methods[] = { 439239268Sgonzo DEVMETHOD(device_probe, arm_tmr_probe), 440239268Sgonzo DEVMETHOD(device_attach, arm_tmr_attach), 441239268Sgonzo { 0, 0 } 442239268Sgonzo}; 443239268Sgonzo 444239268Sgonzostatic driver_t arm_tmr_driver = { 445239268Sgonzo "mp_tmr", 446239268Sgonzo arm_tmr_methods, 447239268Sgonzo sizeof(struct arm_tmr_softc), 448239268Sgonzo}; 449239268Sgonzo 450239268Sgonzostatic devclass_t arm_tmr_devclass; 451239268Sgonzo 452269605SianEARLY_DRIVER_MODULE(mp_tmr, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0, 453269605Sian BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); 454271906SianEARLY_DRIVER_MODULE(mp_tmr, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0, 455271906Sian BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); 456239268Sgonzo 457264050Sian/* 458264050Sian * Handle a change in clock frequency. The mpcore timer runs at half the CPU 459264050Sian * frequency. When the CPU frequency changes due to power-saving or thermal 460299069Spfg * management, the platform-specific code that causes the frequency change calls 461264050Sian * this routine to inform the clock driver, and we in turn inform the event 462264050Sian * timer system, which actually updates the value in et->frequency for us and 463264050Sian * reschedules the current event(s) in a way that's atomic with respect to 464264050Sian * start/stop/intr code that may be running on various CPUs at the time of the 465264050Sian * call. 466264050Sian * 467264050Sian * This routine can also be called by a platform's early init code. If the 468264050Sian * value passed is ARM_TMR_FREQUENCY_VARIES, that will cause the attach() code 469264050Sian * to register as an eventtimer, but not a timecounter. If the value passed in 470264050Sian * is any other non-zero value it is used as the fixed frequency for the timer. 471264050Sian */ 472264050Sianvoid 473264050Sianarm_tmr_change_frequency(uint64_t newfreq) 474264050Sian{ 475264050Sian 476271906Sian if (newfreq == ARM_TMR_FREQUENCY_VARIES) { 477271906Sian arm_tmr_freq_varies = true; 478271906Sian return; 479271906Sian } 480271906Sian 481271906Sian arm_tmr_freq = newfreq; 482271906Sian if (arm_tmr_et != NULL) 483271906Sian et_change_frequency(arm_tmr_et, newfreq); 484264050Sian} 485264050Sian 486239268Sgonzo/** 487239268Sgonzo * DELAY - Delay for at least usec microseconds. 488239268Sgonzo * @usec: number of microseconds to delay by 489239268Sgonzo * 490239268Sgonzo * This function is called all over the kernel and is suppose to provide a 491283366Sandrew * consistent delay. This function may also be called before the console 492239268Sgonzo * is setup so no printf's can be called here. 493239268Sgonzo * 494239268Sgonzo * RETURNS: 495239268Sgonzo * nothing 496239268Sgonzo */ 497262712Sianstatic void __used /* Must emit function code for the weak ref below. */ 498262584Sianarm_tmr_DELAY(int usec) 499239268Sgonzo{ 500271906Sian struct arm_tmr_softc *sc; 501239268Sgonzo int32_t counts_per_usec; 502239268Sgonzo int32_t counts; 503239268Sgonzo uint32_t first, last; 504239268Sgonzo 505239268Sgonzo /* Check the timers are setup, if not just use a for loop for the meantime */ 506271906Sian if (arm_tmr_tc == NULL || arm_tmr_timecount.tc_frequency == 0) { 507239268Sgonzo for (; usec > 0; usec--) 508239268Sgonzo for (counts = 200; counts > 0; counts--) 509239268Sgonzo cpufunc_nullop(); /* Prevent gcc from optimizing 510239268Sgonzo * out the loop 511239268Sgonzo */ 512239268Sgonzo return; 513239268Sgonzo } 514239268Sgonzo 515271906Sian sc = arm_tmr_tc->tc_priv; 516271906Sian 517239268Sgonzo /* Get the number of times to count */ 518239268Sgonzo counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1); 519239268Sgonzo 520239268Sgonzo /* 521239268Sgonzo * Clamp the timeout at a maximum value (about 32 seconds with 522239268Sgonzo * a 66MHz clock). *Nobody* should be delay()ing for anywhere 523239268Sgonzo * near that length of time and if they are, they should be hung 524239268Sgonzo * out to dry. 525239268Sgonzo */ 526239268Sgonzo if (usec >= (0x80000000U / counts_per_usec)) 527239268Sgonzo counts = (0x80000000U / counts_per_usec) - 1; 528239268Sgonzo else 529239268Sgonzo counts = usec * counts_per_usec; 530239268Sgonzo 531271906Sian first = tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW); 532239268Sgonzo 533239268Sgonzo while (counts > 0) { 534271906Sian last = tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW); 535239268Sgonzo counts -= (int32_t)(last - first); 536239268Sgonzo first = last; 537239268Sgonzo } 538239268Sgonzo} 539262584Sian 540262584Sian/* 541262584Sian * Supply a DELAY() implementation via weak linkage. A platform may want to use 542262584Sian * the mpcore per-cpu eventtimers but provide its own DELAY() routine, 543262584Sian * especially when the core frequency can change on the fly. 544262584Sian */ 545262584Sian__weak_reference(arm_tmr_DELAY, DELAY); 546262584Sian 547