am335x_dmtimer.c (286648) | am335x_dmtimer.c (286696) |
---|---|
1/*- 2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/arm/ti/am335x/am335x_dmtimer.c 286648 2015-08-11 19:25:26Z ian $"); | 28__FBSDID("$FreeBSD: head/sys/arm/ti/am335x/am335x_dmtimer.c 286696 2015-08-12 19:40:32Z ian $"); |
29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> | 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> |
33#include <sys/conf.h> | |
34#include <sys/kernel.h> 35#include <sys/module.h> 36#include <sys/malloc.h> 37#include <sys/rman.h> | 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/malloc.h> 36#include <sys/rman.h> |
38#include <sys/taskqueue.h> | |
39#include <sys/timeet.h> | 37#include <sys/timeet.h> |
40#include <sys/timepps.h> | |
41#include <sys/timetc.h> | 38#include <sys/timetc.h> |
42#include <sys/watchdog.h> | |
43#include <machine/bus.h> | 39#include <machine/bus.h> |
44#include <machine/cpu.h> 45#include <machine/intr.h> | |
46 | 40 |
47#include "opt_ntp.h" 48 49#include <dev/fdt/fdt_common.h> | |
50#include <dev/ofw/openfirm.h> 51#include <dev/ofw/ofw_bus.h> 52#include <dev/ofw/ofw_bus_subr.h> 53 | 41#include <dev/ofw/openfirm.h> 42#include <dev/ofw/ofw_bus.h> 43#include <dev/ofw/ofw_bus_subr.h> 44 |
54#include <machine/bus.h> 55 | |
56#include <arm/ti/ti_prcm.h> 57#include <arm/ti/ti_hwmods.h> | 45#include <arm/ti/ti_prcm.h> 46#include <arm/ti/ti_hwmods.h> |
58#include <arm/ti/ti_pinmux.h> | |
59 | 47 |
60#define AM335X_NUM_TIMERS 8 | 48#include "am335x_dmtreg.h" |
61 | 49 |
62#define DMT_TIDR 0x00 /* Identification Register */ 63#define DMT_TIOCP_CFG 0x10 /* OCP Configuration Reg */ 64#define DMT_TIOCP_RESET (1 << 0) /* TIOCP perform soft reset */ 65#define DMT_IQR_EOI 0x20 /* IRQ End-Of-Interrupt Reg */ 66#define DMT_IRQSTATUS_RAW 0x24 /* IRQSTATUS Raw Reg */ 67#define DMT_IRQSTATUS 0x28 /* IRQSTATUS Reg */ 68#define DMT_IRQENABLE_SET 0x2c /* IRQSTATUS Set Reg */ 69#define DMT_IRQENABLE_CLR 0x30 /* IRQSTATUS Clear Reg */ 70#define DMT_IRQWAKEEN 0x34 /* IRQ Wakeup Enable Reg */ 71#define DMT_IRQ_MAT (1 << 0) /* IRQ: Match */ 72#define DMT_IRQ_OVF (1 << 1) /* IRQ: Overflow */ 73#define DMT_IRQ_TCAR (1 << 2) /* IRQ: Capture */ 74#define DMT_IRQ_MASK (DMT_IRQ_TCAR | DMT_IRQ_OVF | DMT_IRQ_MAT) 75#define DMT_TCLR 0x38 /* Control Register */ 76#define DMT_TCLR_START (1 << 0) /* Start timer */ 77#define DMT_TCLR_AUTOLOAD (1 << 1) /* Auto-reload on overflow */ 78#define DMT_TCLR_PRES_MASK (7 << 2) /* Prescaler mask */ 79#define DMT_TCLR_PRES_ENABLE (1 << 5) /* Prescaler enable */ 80#define DMT_TCLR_COMP_ENABLE (1 << 6) /* Compare enable */ 81#define DMT_TCLR_PWM_HIGH (1 << 7) /* PWM default output high */ 82#define DMT_TCLR_CAPTRAN_MASK (3 << 8) /* Capture transition mask */ 83#define DMT_TCLR_CAPTRAN_NONE (0 << 8) /* Capture: none */ 84#define DMT_TCLR_CAPTRAN_LOHI (1 << 8) /* Capture lo->hi transition */ 85#define DMT_TCLR_CAPTRAN_HILO (2 << 8) /* Capture hi->lo transition */ 86#define DMT_TCLR_CAPTRAN_BOTH (3 << 8) /* Capture both transitions */ 87#define DMT_TCLR_TRGMODE_MASK (3 << 10) /* Trigger output mode mask */ 88#define DMT_TCLR_TRGMODE_NONE (0 << 10) /* Trigger off */ 89#define DMT_TCLR_TRGMODE_OVFL (1 << 10) /* Trigger on overflow */ 90#define DMT_TCLR_TRGMODE_BOTH (2 << 10) /* Trigger on match + ovflow */ 91#define DMT_TCLR_PWM_PTOGGLE (1 << 12) /* PWM toggles */ 92#define DMT_TCLR_CAP_MODE_2ND (1 << 13) /* Capture second event mode */ 93#define DMT_TCLR_GPO_CFG (1 << 14) /* (no descr in datasheet) */ 94#define DMT_TCRR 0x3C /* Counter Register */ 95#define DMT_TLDR 0x40 /* Load Reg */ 96#define DMT_TTGR 0x44 /* Trigger Reg */ 97#define DMT_TWPS 0x48 /* Write Posted Status Reg */ 98#define DMT_TMAR 0x4C /* Match Reg */ 99#define DMT_TCAR1 0x50 /* Capture Reg */ 100#define DMT_TSICR 0x54 /* Synchr. Interface Ctrl Reg */ 101#define DMT_TSICR_RESET (1 << 1) /* TSICR perform soft reset */ 102#define DMT_TCAR2 0x48 /* Capture Reg */ 103 104#define DMTIMER_READ4(sc, reg) (bus_read_4((sc)->tmr_mem_res, (reg))) 105#define DMTIMER_WRITE4(sc, reg, val) (bus_write_4((sc)->tmr_mem_res, (reg), (val))) 106 | |
107struct am335x_dmtimer_softc { 108 device_t dev; 109 int tmr_mem_rid; 110 struct resource * tmr_mem_res; 111 int tmr_irq_rid; 112 struct resource * tmr_irq_res; 113 void *tmr_irq_handler; 114 uint32_t sysclk_freq; 115 uint32_t tclr; /* Cached TCLR register. */ | 50struct am335x_dmtimer_softc { 51 device_t dev; 52 int tmr_mem_rid; 53 struct resource * tmr_mem_res; 54 int tmr_irq_rid; 55 struct resource * tmr_irq_res; 56 void *tmr_irq_handler; 57 uint32_t sysclk_freq; 58 uint32_t tclr; /* Cached TCLR register. */ |
116 int pps_curmode; /* Edge mode now set in hw. */ 117 struct task pps_task; /* For pps_event handling. */ 118 struct cdev * pps_cdev; 119 struct pps_state pps; 120 | |
121 union { 122 struct timecounter tc; 123 struct eventtimer et; 124 } func; | 59 union { 60 struct timecounter tc; 61 struct eventtimer et; 62 } func; |
63 int tmr_num; /* Hardware unit number. */ 64 char tmr_name[12]; /* "DMTimerN", N = tmr_num */ |
|
125}; 126 127static struct am335x_dmtimer_softc *am335x_dmtimer_et_sc = NULL; 128static struct am335x_dmtimer_softc *am335x_dmtimer_tc_sc = NULL; 129 | 65}; 66 67static struct am335x_dmtimer_softc *am335x_dmtimer_et_sc = NULL; 68static struct am335x_dmtimer_softc *am335x_dmtimer_tc_sc = NULL; 69 |
130 131#ifdef PPS_SYNC 132/* -1 - not detected, 0 - not found, > 0 - timerX module */ 133static int am335x_dmtimer_pps_module = -1; 134static const char *am335x_dmtimer_pps_hwmod = NULL; 135#endif 136 | |
137/* | 70/* |
138 * PPS driver routines, included when the kernel is built with option PPS_SYNC. 139 * 140 * Note that this PPS driver does not use an interrupt. Instead it uses the 141 * hardware's ability to latch the timer's count register in response to a 142 * signal on an IO pin. Each of timers 4-7 have an associated pin, and this 143 * code allows any one of those to be used. 144 * 145 * The timecounter routines in kern_tc.c call the pps poll routine periodically 146 * to see if a new counter value has been latched. When a new value has been 147 * latched, the only processing done in the poll routine is to capture the 148 * current set of timecounter timehands (done with pps_capture()) and the 149 * latched value from the timer. The remaining work (done by pps_event()) is 150 * scheduled to be done later in a non-interrupt context. | 71 * We use dmtimer2 for eventtimer and dmtimer3 for timecounter. |
151 */ | 72 */ |
152#ifdef PPS_SYNC | 73#define ET_TMR_NUM 2 74#define TC_TMR_NUM 3 |
153 | 75 |
154#define PPS_CDEV_NAME "dmtpps" 155 156static void 157am335x_dmtimer_set_capture_mode(struct am335x_dmtimer_softc *sc, bool force_off) 158{ 159 int newmode; 160 161 if (force_off) 162 newmode = 0; 163 else 164 newmode = sc->pps.ppsparam.mode & PPS_CAPTUREBOTH; 165 166 if (newmode == sc->pps_curmode) 167 return; 168 169 sc->pps_curmode = newmode; 170 sc->tclr &= ~DMT_TCLR_CAPTRAN_MASK; 171 switch (newmode) { 172 case PPS_CAPTUREASSERT: 173 sc->tclr |= DMT_TCLR_CAPTRAN_LOHI; 174 break; 175 case PPS_CAPTURECLEAR: 176 sc->tclr |= DMT_TCLR_CAPTRAN_HILO; 177 break; 178 default: 179 /* It can't be BOTH, so it's disabled. */ 180 break; 181 } 182 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 183} 184 185static void 186am335x_dmtimer_tc_poll_pps(struct timecounter *tc) 187{ 188 struct am335x_dmtimer_softc *sc; 189 190 sc = tc->tc_priv; 191 192 /* 193 * Note that we don't have the TCAR interrupt enabled, but the hardware 194 * still provides the status bits in the "RAW" status register even when 195 * they're masked from generating an irq. However, when clearing the 196 * TCAR status to re-arm the capture for the next second, we have to 197 * write to the IRQ status register, not the RAW register. Quirky. 198 */ 199 if (DMTIMER_READ4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) { 200 pps_capture(&sc->pps); 201 sc->pps.capcount = DMTIMER_READ4(sc, DMT_TCAR1); 202 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR); 203 taskqueue_enqueue_fast(taskqueue_fast, &sc->pps_task); 204 } 205} 206 207static void 208am335x_dmtimer_process_pps_event(void *arg, int pending) 209{ 210 struct am335x_dmtimer_softc *sc; 211 212 sc = arg; 213 214 /* This is the task function that gets enqueued by poll_pps. Once the 215 * time has been captured in the hw interrupt context, the remaining 216 * (more expensive) work to process the event is done later in a 217 * non-fast-interrupt context. 218 * 219 * We only support capture of the rising or falling edge, not both at 220 * once; tell the kernel to process whichever mode is currently active. 221 */ 222 pps_event(&sc->pps, sc->pps.ppsparam.mode & PPS_CAPTUREBOTH); 223} 224 225static int 226am335x_dmtimer_pps_open(struct cdev *dev, int flags, int fmt, 227 struct thread *td) 228{ 229 struct am335x_dmtimer_softc *sc; 230 231 sc = dev->si_drv1; 232 233 /* Enable capture on open. Harmless if already open. */ 234 am335x_dmtimer_set_capture_mode(sc, 0); 235 236 return 0; 237} 238 239static int 240am335x_dmtimer_pps_close(struct cdev *dev, int flags, int fmt, 241 struct thread *td) 242{ 243 struct am335x_dmtimer_softc *sc; 244 245 sc = dev->si_drv1; 246 247 /* 248 * Disable capture on last close. Use the force-off flag to override 249 * the configured mode and turn off the hardware capture. 250 */ 251 am335x_dmtimer_set_capture_mode(sc, 1); 252 253 return 0; 254} 255 256static int 257am335x_dmtimer_pps_ioctl(struct cdev *dev, u_long cmd, caddr_t data, 258 int flags, struct thread *td) 259{ 260 struct am335x_dmtimer_softc *sc; 261 int err; 262 263 sc = dev->si_drv1; 264 265 /* 266 * The hardware has a "capture both edges" mode, but we can't do 267 * anything useful with it in terms of PPS capture, so don't even try. 268 */ 269 if ((sc->pps.ppsparam.mode & PPS_CAPTUREBOTH) == PPS_CAPTUREBOTH) 270 return (EINVAL); 271 272 /* Let the kernel do the heavy lifting for ioctl. */ 273 err = pps_ioctl(cmd, data, &sc->pps); 274 if (err != 0) 275 return (err); 276 277 /* 278 * The capture mode could have changed, set the hardware to whatever 279 * mode is now current. Effectively a no-op if nothing changed. 280 */ 281 am335x_dmtimer_set_capture_mode(sc, 0); 282 283 return (err); 284} 285 286static struct cdevsw am335x_dmtimer_pps_cdevsw = { 287 .d_version = D_VERSION, 288 .d_open = am335x_dmtimer_pps_open, 289 .d_close = am335x_dmtimer_pps_close, 290 .d_ioctl = am335x_dmtimer_pps_ioctl, 291 .d_name = PPS_CDEV_NAME, | 76/* List of compatible strings for FDT tree */ 77static struct ofw_compat_data compat_data[] = { 78 {"ti,am335x-timer", 1}, 79 {"ti,am335x-timer-1ms", 1}, 80 {NULL, 0}, |
292}; 293 | 81}; 82 |
294static void 295am335x_dmtimer_pps_find() 296{ 297 int i; 298 unsigned int padstate; 299 const char * padmux; 300 struct padinfo { 301 char * ballname; 302 const char * muxname; 303 int timer_num; 304 } padinfo[] = { 305 {"GPMC_ADVn_ALE", "timer4", 4}, 306 {"GPMC_BEn0_CLE", "timer5", 5}, 307 {"GPMC_WEn", "timer6", 6}, 308 {"GPMC_OEn_REn", "timer7", 7}, 309 }; | 83#define DMTIMER_READ4(sc, reg) bus_read_4((sc)->tmr_mem_res, (reg)) 84#define DMTIMER_WRITE4(sc, reg, val) bus_write_4((sc)->tmr_mem_res, (reg), (val)) |
310 | 85 |
311 /* 312 * Figure out which pin the user has set up for pps. We'll use the 313 * first timer that has an external caputure pin configured as input. 314 * 315 * XXX The hieroglyphic "(padstate & (0x01 << 5)))" checks that the pin 316 * is configured for input. The right symbolic values aren't exported 317 * yet from ti_scm.h. 318 */ 319 am335x_dmtimer_pps_module = 0; 320 for (i = 0; i < nitems(padinfo) && am335x_dmtimer_pps_module == 0; ++i) { 321 if (ti_pinmux_padconf_get(padinfo[i].ballname, &padmux, 322 &padstate) == 0) { 323 if (strcasecmp(padinfo[i].muxname, padmux) == 0 && 324 (padstate & (0x01 << 5))) { 325 am335x_dmtimer_pps_module = padinfo[i].timer_num; 326 am335x_dmtimer_pps_hwmod = padinfo[i].muxname; 327 } 328 } 329 } 330 331 332 if (am335x_dmtimer_pps_module == 0) { 333 printf("am335x_dmtimer: No DMTimer found with capture pin " 334 "configured as input; PPS driver disabled.\n"); 335 } 336} 337 338/* 339 * Set up the PPS cdev and the the kernel timepps stuff. 340 * 341 * Note that this routine cannot touch the hardware, because bus space resources 342 * are not fully set up yet when this is called. 343 */ 344static void 345am335x_dmtimer_pps_init(device_t dev, struct am335x_dmtimer_softc *sc) 346{ 347 int unit; 348 349 if (am335x_dmtimer_pps_module == -1) 350 am335x_dmtimer_pps_find(); 351 352 /* No PPS input */ 353 if (am335x_dmtimer_pps_module == 0) 354 return; 355 356 /* Not PPS-enabled input */ 357 if ((am335x_dmtimer_pps_module > 0) && 358 (!ti_hwmods_contains(dev, am335x_dmtimer_pps_hwmod))) 359 return; 360 361 /* 362 * Indicate our capabilities (pretty much just capture of either edge). 363 * Have the kernel init its part of the pps_state struct and add its 364 * capabilities. 365 */ 366 sc->pps.ppscap = PPS_CAPTUREBOTH; 367 pps_init(&sc->pps); 368 369 /* 370 * Set up to capture the PPS via timecounter polling, and init the task 371 * that does deferred pps_event() processing after capture. 372 */ 373 sc->func.tc.tc_poll_pps = am335x_dmtimer_tc_poll_pps; 374 TASK_INIT(&sc->pps_task, 0, am335x_dmtimer_process_pps_event, sc); 375 376 /* Create the PPS cdev. */ 377 unit = device_get_unit(dev); 378 sc->pps_cdev = make_dev(&am335x_dmtimer_pps_cdevsw, unit, 379 UID_ROOT, GID_WHEEL, 0600, PPS_CDEV_NAME); 380 sc->pps_cdev->si_drv1 = sc; 381 382 device_printf(dev, "Using DMTimer%d for PPS device /dev/%s%d\n", 383 am335x_dmtimer_pps_module, PPS_CDEV_NAME, unit); 384} 385 386#endif 387 388/* 389 * End of PPS driver code. 390 */ 391 392static unsigned 393am335x_dmtimer_tc_get_timecount(struct timecounter *tc) 394{ 395 struct am335x_dmtimer_softc *sc; 396 397 sc = tc->tc_priv; 398 399 return (DMTIMER_READ4(sc, DMT_TCRR)); 400} 401 | |
402static int | 86static int |
403am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) | 87am335x_dmtimer_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period) |
404{ 405 struct am335x_dmtimer_softc *sc; 406 uint32_t initial_count, reload_count; 407 408 sc = et->et_priv; 409 410 /* 411 * Stop the timer before changing it. This routine will often be called --- 35 unchanged lines hidden (view full) --- 447 DMTIMER_WRITE4(sc, DMT_IRQENABLE_SET, DMT_IRQ_OVF); 448 sc->tclr |= DMT_TCLR_START; 449 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 450 451 return (0); 452} 453 454static int | 88{ 89 struct am335x_dmtimer_softc *sc; 90 uint32_t initial_count, reload_count; 91 92 sc = et->et_priv; 93 94 /* 95 * Stop the timer before changing it. This routine will often be called --- 35 unchanged lines hidden (view full) --- 131 DMTIMER_WRITE4(sc, DMT_IRQENABLE_SET, DMT_IRQ_OVF); 132 sc->tclr |= DMT_TCLR_START; 133 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 134 135 return (0); 136} 137 138static int |
455am335x_dmtimer_stop(struct eventtimer *et) | 139am335x_dmtimer_et_stop(struct eventtimer *et) |
456{ 457 struct am335x_dmtimer_softc *sc; 458 459 sc = et->et_priv; 460 461 /* Stop timer, disable and clear interrupt. */ 462 sc->tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD); 463 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 464 DMTIMER_WRITE4(sc, DMT_IRQENABLE_CLR, DMT_IRQ_OVF); 465 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF); 466 return (0); 467} 468 469static int | 140{ 141 struct am335x_dmtimer_softc *sc; 142 143 sc = et->et_priv; 144 145 /* Stop timer, disable and clear interrupt. */ 146 sc->tclr &= ~(DMT_TCLR_START | DMT_TCLR_AUTOLOAD); 147 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 148 DMTIMER_WRITE4(sc, DMT_IRQENABLE_CLR, DMT_IRQ_OVF); 149 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF); 150 return (0); 151} 152 153static int |
470am335x_dmtimer_intr(void *arg) | 154am335x_dmtimer_et_intr(void *arg) |
471{ 472 struct am335x_dmtimer_softc *sc; 473 474 sc = arg; 475 476 /* Ack the interrupt, and invoke the callback if it's still enabled. */ 477 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF); 478 if (sc->func.et.et_active) 479 sc->func.et.et_event_cb(&sc->func.et, sc->func.et.et_arg); 480 481 return (FILTER_HANDLED); 482} 483 | 155{ 156 struct am335x_dmtimer_softc *sc; 157 158 sc = arg; 159 160 /* Ack the interrupt, and invoke the callback if it's still enabled. */ 161 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF); 162 if (sc->func.et.et_active) 163 sc->func.et.et_event_cb(&sc->func.et, sc->func.et.et_arg); 164 165 return (FILTER_HANDLED); 166} 167 |
484/* 485 * Checks if timer is suitable to be system timer 486 */ | |
487static int | 168static int |
488am335x_dmtimer_system_compatible(device_t dev) | 169am335x_dmtimer_et_init(struct am335x_dmtimer_softc *sc) |
489{ | 170{ |
490 phandle_t node; | 171 KASSERT(am335x_dmtimer_et_sc == NULL, ("already have an eventtimer")); |
491 | 172 |
492 node = ofw_bus_get_node(dev); 493 if (OF_hasprop(node, "ti,timer-alwon")) 494 return (0); 495 496 return (1); 497} 498 499static int 500am335x_dmtimer_init_et(struct am335x_dmtimer_softc *sc) 501{ 502 if (am335x_dmtimer_et_sc != NULL) 503 return (EEXIST); 504 505#ifdef PPS_SYNC 506 if ((am335x_dmtimer_pps_module > 0) && 507 (!ti_hwmods_contains(sc->dev, am335x_dmtimer_pps_hwmod))) { 508 device_printf(sc->dev, "not PPS enabled\n"); 509 return (ENXIO); 510 } 511#endif 512 513 /* Setup eventtimer interrupt handler. */ | 173 /* 174 * Setup eventtimer interrupt handling. Panic if anything goes wrong, 175 * because the system just isn't going to run without an eventtimer. 176 */ 177 sc->tmr_irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, 178 &sc->tmr_irq_rid, RF_ACTIVE); 179 if (sc->tmr_irq_res == NULL) 180 panic("am335x_dmtimer: could not allocate irq resources"); |
514 if (bus_setup_intr(sc->dev, sc->tmr_irq_res, INTR_TYPE_CLK, | 181 if (bus_setup_intr(sc->dev, sc->tmr_irq_res, INTR_TYPE_CLK, |
515 am335x_dmtimer_intr, NULL, sc, &sc->tmr_irq_handler) != 0) { 516 device_printf(sc->dev, "Unable to setup the clock irq handler.\n"); 517 return (ENXIO); 518 } | 182 am335x_dmtimer_et_intr, NULL, sc, &sc->tmr_irq_handler) != 0) 183 panic("am335x_dmtimer: count not setup irq handler"); |
519 | 184 |
520 sc->func.et.et_name = "AM335x Eventtimer"; | 185 sc->func.et.et_name = sc->tmr_name; |
521 sc->func.et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; | 186 sc->func.et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; |
522 sc->func.et.et_quality = 1000; | 187 sc->func.et.et_quality = 500; |
523 sc->func.et.et_frequency = sc->sysclk_freq; 524 sc->func.et.et_min_period = 525 ((0x00000005LLU << 32) / sc->func.et.et_frequency); 526 sc->func.et.et_max_period = 527 (0xfffffffeLLU << 32) / sc->func.et.et_frequency; | 188 sc->func.et.et_frequency = sc->sysclk_freq; 189 sc->func.et.et_min_period = 190 ((0x00000005LLU << 32) / sc->func.et.et_frequency); 191 sc->func.et.et_max_period = 192 (0xfffffffeLLU << 32) / sc->func.et.et_frequency; |
528 sc->func.et.et_start = am335x_dmtimer_start; 529 sc->func.et.et_stop = am335x_dmtimer_stop; | 193 sc->func.et.et_start = am335x_dmtimer_et_start; 194 sc->func.et.et_stop = am335x_dmtimer_et_stop; |
530 sc->func.et.et_priv = sc; | 195 sc->func.et.et_priv = sc; |
531 et_register(&sc->func.et); | |
532 533 am335x_dmtimer_et_sc = sc; | 196 197 am335x_dmtimer_et_sc = sc; |
198 et_register(&sc->func.et); |
|
534 535 return (0); 536} 537 | 199 200 return (0); 201} 202 |
203static unsigned 204am335x_dmtimer_tc_get_timecount(struct timecounter *tc) 205{ 206 struct am335x_dmtimer_softc *sc; 207 208 sc = tc->tc_priv; 209 210 return (DMTIMER_READ4(sc, DMT_TCRR)); 211} 212 |
|
538static int | 213static int |
539am335x_dmtimer_init_tc(struct am335x_dmtimer_softc *sc) | 214am335x_dmtimer_tc_init(struct am335x_dmtimer_softc *sc) |
540{ | 215{ |
541 if (am335x_dmtimer_tc_sc != NULL) 542 return (EEXIST); | 216 KASSERT(am335x_dmtimer_tc_sc == NULL, ("already have a timecounter")); |
543 544 /* Set up timecounter, start it, register it. */ 545 DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET); 546 while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET) 547 continue; 548 549 sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD; 550 DMTIMER_WRITE4(sc, DMT_TLDR, 0); 551 DMTIMER_WRITE4(sc, DMT_TCRR, 0); 552 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 553 | 217 218 /* Set up timecounter, start it, register it. */ 219 DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET); 220 while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET) 221 continue; 222 223 sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD; 224 DMTIMER_WRITE4(sc, DMT_TLDR, 0); 225 DMTIMER_WRITE4(sc, DMT_TCRR, 0); 226 DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr); 227 |
554 sc->func.tc.tc_name = "AM335x Timecounter"; | 228 sc->func.tc.tc_name = sc->tmr_name; |
555 sc->func.tc.tc_get_timecount = am335x_dmtimer_tc_get_timecount; 556 sc->func.tc.tc_counter_mask = ~0u; 557 sc->func.tc.tc_frequency = sc->sysclk_freq; | 229 sc->func.tc.tc_get_timecount = am335x_dmtimer_tc_get_timecount; 230 sc->func.tc.tc_counter_mask = ~0u; 231 sc->func.tc.tc_frequency = sc->sysclk_freq; |
558 sc->func.tc.tc_quality = 1000; | 232 sc->func.tc.tc_quality = 500; |
559 sc->func.tc.tc_priv = sc; | 233 sc->func.tc.tc_priv = sc; |
560 tc_init(&sc->func.tc); | |
561 562 am335x_dmtimer_tc_sc = sc; | 234 235 am335x_dmtimer_tc_sc = sc; |
236 tc_init(&sc->func.tc); |
|
563 564 return (0); 565} 566 567static int 568am335x_dmtimer_probe(device_t dev) 569{ | 237 238 return (0); 239} 240 241static int 242am335x_dmtimer_probe(device_t dev) 243{ |
244 char strbuf[32]; 245 int tmr_num; |
|
570 571 if (!ofw_bus_status_okay(dev)) 572 return (ENXIO); 573 | 246 247 if (!ofw_bus_status_okay(dev)) 248 return (ENXIO); 249 |
574 if (ofw_bus_is_compatible(dev, "ti,am335x-timer-1ms") || 575 ofw_bus_is_compatible(dev, "ti,am335x-timer")) { 576 device_set_desc(dev, "AM335x DMTimer"); 577 return(BUS_PROBE_DEFAULT); 578 } | 250 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 251 return (ENXIO); |
579 | 252 |
580 return (ENXIO); | 253 /* 254 * Get the hardware unit number (the N from ti,hwmods="timerN"). 255 * If this isn't the hardware unit we're going to use for either the 256 * eventtimer or the timecounter, no point in instantiating the device. 257 */ 258 tmr_num = ti_hwmods_get_unit(dev, "timer"); 259 if (tmr_num != ET_TMR_NUM && tmr_num != TC_TMR_NUM) 260 return (ENXIO); 261 262 snprintf(strbuf, sizeof(strbuf), "AM335x DMTimer%d", tmr_num); 263 device_set_desc_copy(dev, strbuf); 264 265 return(BUS_PROBE_DEFAULT); |
581} 582 583static int 584am335x_dmtimer_attach(device_t dev) 585{ 586 struct am335x_dmtimer_softc *sc; | 266} 267 268static int 269am335x_dmtimer_attach(device_t dev) 270{ 271 struct am335x_dmtimer_softc *sc; |
587 int err; | |
588 clk_ident_t timer_id; | 272 clk_ident_t timer_id; |
589 int enable; | 273 int err; |
590 591 sc = device_get_softc(dev); 592 sc->dev = dev; 593 594 /* Get the base clock frequency. */ | 274 275 sc = device_get_softc(dev); 276 sc->dev = dev; 277 278 /* Get the base clock frequency. */ |
595 err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq); 596 if (err) { 597 device_printf(dev, "Error: could not get sysclk frequency\n"); | 279 if ((err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq)) != 0) 280 return (err); 281 282 /* Enable clocks and power on the device. */ 283 if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT) |
598 return (ENXIO); | 284 return (ENXIO); |
599 } | 285 if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0) 286 return (err); 287 if ((err = ti_prcm_clk_enable(timer_id)) != 0) 288 return (err); |
600 601 /* Request the memory resources. */ 602 sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 603 &sc->tmr_mem_rid, RF_ACTIVE); 604 if (sc->tmr_mem_res == NULL) { | 289 290 /* Request the memory resources. */ 291 sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 292 &sc->tmr_mem_rid, RF_ACTIVE); 293 if (sc->tmr_mem_res == NULL) { |
605 device_printf(dev, "Error: could not allocate mem resources\n"); | |
606 return (ENXIO); 607 } 608 | 294 return (ENXIO); 295 } 296 |
609 /* Request the IRQ resources. */ 610 sc->tmr_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 611 &sc->tmr_irq_rid, RF_ACTIVE); 612 if (err) { 613 bus_release_resource(dev, SYS_RES_MEMORY, sc->tmr_mem_rid, 614 sc->tmr_mem_res); 615 device_printf(dev, "Error: could not allocate irq resources\n"); 616 return (ENXIO); 617 } | 297 sc->tmr_num = ti_hwmods_get_unit(dev, "timer"); 298 snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num); |
618 | 299 |
619#ifdef PPS_SYNC 620 am335x_dmtimer_pps_init(dev, sc); 621#endif | 300 /* 301 * Go set up either a timecounter or eventtimer. We wouldn't have 302 * attached if we weren't one or the other. 303 */ 304 if (sc->tmr_num == ET_TMR_NUM) 305 am335x_dmtimer_et_init(sc); 306 else if (sc->tmr_num == TC_TMR_NUM) 307 am335x_dmtimer_tc_init(sc); 308 else 309 panic("am335x_dmtimer: bad timer number %d", sc->tmr_num); |
622 | 310 |
623 enable = 0; 624 /* Try to use as a timecounter or event timer */ 625 if (am335x_dmtimer_system_compatible(dev)) { 626 if (am335x_dmtimer_init_tc(sc) == 0) 627 enable = 1; 628 else if (am335x_dmtimer_init_et(sc) == 0) 629 enable = 1; 630 } 631 632 if (enable) { 633 /* Enable clocks and power on the chosen devices. */ 634 timer_id = ti_hwmods_get_clock(dev); 635 if (timer_id == INVALID_CLK_IDENT) { 636 bus_release_resource(dev, SYS_RES_MEMORY, sc->tmr_mem_rid, 637 sc->tmr_mem_res); 638 bus_release_resource(dev, SYS_RES_IRQ, sc->tmr_irq_rid, 639 sc->tmr_irq_res); 640 device_printf(dev, "failed to get device id using ti,hwmods\n"); 641 return (ENXIO); 642 } 643 644 err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK); 645 err |= ti_prcm_clk_enable(timer_id); 646 647 if (err) { 648 bus_release_resource(dev, SYS_RES_MEMORY, sc->tmr_mem_rid, 649 sc->tmr_mem_res); 650 bus_release_resource(dev, SYS_RES_IRQ, sc->tmr_irq_rid, 651 sc->tmr_irq_res); 652 device_printf(dev, "Error: could not enable timer clock\n"); 653 return (ENXIO); 654 } 655 } 656 | |
657 return (0); 658} 659 660static device_method_t am335x_dmtimer_methods[] = { 661 DEVMETHOD(device_probe, am335x_dmtimer_probe), 662 DEVMETHOD(device_attach, am335x_dmtimer_attach), 663 { 0, 0 } 664}; --- 45 unchanged lines hidden --- | 311 return (0); 312} 313 314static device_method_t am335x_dmtimer_methods[] = { 315 DEVMETHOD(device_probe, am335x_dmtimer_probe), 316 DEVMETHOD(device_attach, am335x_dmtimer_attach), 317 { 0, 0 } 318}; --- 45 unchanged lines hidden --- |