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