1294332Sdes/*- 276259Sgreen * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 365668Skris * All rights reserved. 465668Skris * 565668Skris * Redistribution and use in source and binary forms, with or without 665668Skris * modification, are permitted provided that the following conditions 765668Skris * are met: 865668Skris * 1. Redistributions of source code must retain the above copyright 965668Skris * notice, this list of conditions and the following disclaimer. 1065668Skris * 2. Redistributions in binary form must reproduce the above copyright 1165668Skris * notice, this list of conditions and the following disclaimer in the 1265668Skris * documentation and/or other materials provided with the distribution. 1365668Skris * 1465668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1565668Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1665668Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1765668Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1865668Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1965668Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2065668Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2165668Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2265668Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2365668Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2465668Skris * SUCH DAMAGE. 2565668Skris */ 26162852Sdes 27294332Sdes#include <sys/cdefs.h> 28294332Sdes__FBSDID("$FreeBSD$"); 29162852Sdes 30294332Sdes#include <sys/param.h> 31294332Sdes#include <sys/systm.h> 3260573Skris#include <sys/bus.h> 3360573Skris#include <sys/kernel.h> 3460573Skris#include <sys/module.h> 3560573Skris#include <sys/malloc.h> 3660573Skris#include <sys/rman.h> 37294332Sdes#include <sys/timeet.h> 3860573Skris#include <sys/timetc.h> 39294332Sdes#include <sys/watchdog.h> 40294332Sdes#include <machine/bus.h> 41294332Sdes#include <machine/cpu.h> 42294332Sdes#include <machine/frame.h> 43294332Sdes#include <machine/intr.h> 44294332Sdes 45294332Sdes#include <dev/fdt/fdt_common.h> 46294332Sdes#include <dev/ofw/openfirm.h> 47294332Sdes#include <dev/ofw/ofw_bus.h> 48294332Sdes#include <dev/ofw/ofw_bus_subr.h> 49294332Sdes 50294332Sdes#include <machine/bus.h> 51294332Sdes#include <machine/fdt.h> 52294332Sdes 53294332Sdes#include <arm/ti/ti_prcm.h> 54294332Sdes 55294332Sdes#define AM335X_NUM_TIMERS 8 56294332Sdes 57294332Sdes#define DMTIMER_TIDR 0x00 /* Identification Register */ 58294332Sdes#define DMTIMER_TIOCP_CFG 0x10 /* Timer OCP Configuration Reg */ 59#define DMTIMER_IQR_EOI 0x20 /* Timer IRQ End-Of-Interrupt Reg */ 60#define DMTIMER_IRQSTATUS_RAW 0x24 /* Timer IRQSTATUS Raw Reg */ 61#define DMTIMER_IRQSTATUS 0x28 /* Timer IRQSTATUS Reg */ 62#define DMTIMER_IRQENABLE_SET 0x2c /* Timer IRQSTATUS Set Reg */ 63#define DMTIMER_IRQENABLE_CLR 0x30 /* Timer IRQSTATUS Clear Reg */ 64#define DMTIMER_IRQWAKEEN 0x34 /* Timer IRQ Wakeup Enable Reg */ 65#define DMTIMER_TCLR 0x38 /* Timer Control Register */ 66#define DMTIMER_TCRR 0x3C /* Timer Counter Register */ 67#define DMTIMER_TLDR 0x40 /* Timer Load Reg */ 68#define DMTIMER_TTGR 0x44 /* Timer Trigger Reg */ 69#define DMTIMER_TWPS 0x48 /* Timer Write Posted Status Reg */ 70#define DMTIMER_TMAR 0x4C /* Timer Match Reg */ 71#define DMTIMER_TCAR1 0x50 /* Timer Capture Reg */ 72#define DMTIMER_TSICR 0x54 /* Timer Synchr. Interface Control Reg */ 73#define DMTIMER_TCAR2 0x48 /* Timer Capture Reg */ 74 75 76struct am335x_dmtimer_softc { 77 struct resource * tmr_mem_res[AM335X_NUM_TIMERS]; 78 struct resource * tmr_irq_res[AM335X_NUM_TIMERS]; 79 uint32_t sysclk_freq; 80 struct am335x_dmtimer { 81 bus_space_tag_t bst; 82 bus_space_handle_t bsh; 83 struct eventtimer et; 84 } t[AM335X_NUM_TIMERS]; 85}; 86 87static struct resource_spec am335x_dmtimer_mem_spec[] = { 88 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 89 { SYS_RES_MEMORY, 1, RF_ACTIVE }, 90 { SYS_RES_MEMORY, 2, RF_ACTIVE }, 91 { SYS_RES_MEMORY, 3, RF_ACTIVE }, 92 { SYS_RES_MEMORY, 4, RF_ACTIVE }, 93 { SYS_RES_MEMORY, 5, RF_ACTIVE }, 94 { SYS_RES_MEMORY, 6, RF_ACTIVE }, 95 { SYS_RES_MEMORY, 7, RF_ACTIVE }, 96 { -1, 0, 0 } 97}; 98static struct resource_spec am335x_dmtimer_irq_spec[] = { 99 { SYS_RES_IRQ, 0, RF_ACTIVE }, 100 { SYS_RES_IRQ, 1, RF_ACTIVE }, 101 { SYS_RES_IRQ, 2, RF_ACTIVE }, 102 { SYS_RES_IRQ, 3, RF_ACTIVE }, 103 { SYS_RES_IRQ, 4, RF_ACTIVE }, 104 { SYS_RES_IRQ, 5, RF_ACTIVE }, 105 { SYS_RES_IRQ, 6, RF_ACTIVE }, 106 { SYS_RES_IRQ, 7, RF_ACTIVE }, 107 { -1, 0, 0 } 108}; 109 110static struct am335x_dmtimer *am335x_dmtimer_tc_tmr = NULL; 111 112/* Read/Write macros for Timer used as timecounter */ 113#define am335x_dmtimer_tc_read_4(reg) \ 114 bus_space_read_4(am335x_dmtimer_tc_tmr->bst, \ 115 am335x_dmtimer_tc_tmr->bsh, reg) 116 117#define am335x_dmtimer_tc_write_4(reg, val) \ 118 bus_space_write_4(am335x_dmtimer_tc_tmr->bst, \ 119 am335x_dmtimer_tc_tmr->bsh, reg, val) 120 121/* Read/Write macros for Timer used as eventtimer */ 122#define am335x_dmtimer_et_read_4(reg) \ 123 bus_space_read_4(tmr->bst, tmr->bsh, reg) 124 125#define am335x_dmtimer_et_write_4(reg, val) \ 126 bus_space_write_4(tmr->bst, tmr->bsh, reg, val) 127 128static unsigned am335x_dmtimer_tc_get_timecount(struct timecounter *); 129 130static struct timecounter am335x_dmtimer_tc = { 131 .tc_name = "AM335x Timecounter", 132 .tc_get_timecount = am335x_dmtimer_tc_get_timecount, 133 .tc_poll_pps = NULL, 134 .tc_counter_mask = ~0u, 135 .tc_frequency = 0, 136 .tc_quality = 1000, 137}; 138 139static unsigned 140am335x_dmtimer_tc_get_timecount(struct timecounter *tc) 141{ 142 return am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 143} 144 145static int 146am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) 147{ 148 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv; 149 uint32_t load, count; 150 uint32_t tclr = 0; 151 152 if (period != 0) { 153 load = ((uint32_t)et->et_frequency * period) >> 32; 154 tclr |= 2; /* autoreload bit */ 155 panic("periodic timer not implemented\n"); 156 } else { 157 load = 0; 158 } 159 160 if (first != 0) 161 count = ((uint32_t)et->et_frequency * first) >> 32; 162 else 163 count = load; 164 165 /* Reset Timer */ 166 am335x_dmtimer_et_write_4(DMTIMER_TSICR, 2); 167 168 /* Wait for reset to complete */ 169 while (am335x_dmtimer_et_read_4(DMTIMER_TIOCP_CFG) & 1); 170 171 /* set load value */ 172 am335x_dmtimer_et_write_4(DMTIMER_TLDR, 0xFFFFFFFE - load); 173 174 /* set counter value */ 175 am335x_dmtimer_et_write_4(DMTIMER_TCRR, 0xFFFFFFFE - count); 176 177 /* enable overflow interrupt */ 178 am335x_dmtimer_et_write_4(DMTIMER_IRQENABLE_SET, 2); 179 180 /* start timer(ST) */ 181 tclr |= 1; 182 am335x_dmtimer_et_write_4(DMTIMER_TCLR, tclr); 183 184 return (0); 185} 186 187static int 188am335x_dmtimer_stop(struct eventtimer *et) 189{ 190 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv; 191 192 /* Disable all interrupts */ 193 am335x_dmtimer_et_write_4(DMTIMER_IRQENABLE_CLR, 7); 194 195 /* Stop Timer */ 196 am335x_dmtimer_et_write_4(DMTIMER_TCLR, 0); 197 198 return (0); 199} 200 201static int 202am335x_dmtimer_intr(void *arg) 203{ 204 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)arg; 205 206 /* Ack interrupt */ 207 am335x_dmtimer_et_write_4(DMTIMER_IRQSTATUS, 7); 208 if (tmr->et.et_active) 209 tmr->et.et_event_cb(&tmr->et, tmr->et.et_arg); 210 211 return (FILTER_HANDLED); 212} 213 214static int 215am335x_dmtimer_probe(device_t dev) 216{ 217 struct am335x_dmtimer_softc *sc; 218 sc = (struct am335x_dmtimer_softc *)device_get_softc(dev); 219 220 if (ofw_bus_is_compatible(dev, "ti,am335x-dmtimer")) { 221 device_set_desc(dev, "AM335x DMTimer"); 222 return(BUS_PROBE_DEFAULT); 223 } 224 225 return (ENXIO); 226} 227 228static int 229am335x_dmtimer_attach(device_t dev) 230{ 231 struct am335x_dmtimer_softc *sc = device_get_softc(dev); 232 void *ihl; 233 int err; 234 int i; 235 236 if (am335x_dmtimer_tc_tmr != NULL) 237 return (EINVAL); 238 239 /* Get the base clock frequency */ 240 err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq); 241 if (err) { 242 device_printf(dev, "Error: could not get sysclk frequency\n"); 243 return (ENXIO); 244 } 245 246 /* Request the memory resources */ 247 err = bus_alloc_resources(dev, am335x_dmtimer_mem_spec, 248 sc->tmr_mem_res); 249 if (err) { 250 device_printf(dev, "Error: could not allocate mem resources\n"); 251 return (ENXIO); 252 } 253 254 /* Request the IRQ resources */ 255 err = bus_alloc_resources(dev, am335x_dmtimer_irq_spec, 256 sc->tmr_irq_res); 257 if (err) { 258 device_printf(dev, "Error: could not allocate irq resources\n"); 259 return (ENXIO); 260 } 261 262 for(i=0;i<AM335X_NUM_TIMERS;i++) { 263 sc->t[i].bst = rman_get_bustag(sc->tmr_mem_res[i]); 264 sc->t[i].bsh = rman_get_bushandle(sc->tmr_mem_res[i]); 265 } 266 267 /* Configure DMTimer2 and DMTimer3 source and enable them */ 268 err = ti_prcm_clk_set_source(DMTIMER2_CLK, SYSCLK_CLK); 269 err |= ti_prcm_clk_enable(DMTIMER2_CLK); 270 err |= ti_prcm_clk_set_source(DMTIMER3_CLK, SYSCLK_CLK); 271 err |= ti_prcm_clk_enable(DMTIMER3_CLK); 272 if (err) { 273 device_printf(dev, "Error: could not setup timer clock\n"); 274 return (ENXIO); 275 } 276 277 /* Take DMTimer2 for TC */ 278 am335x_dmtimer_tc_tmr = &sc->t[2]; 279 280 /* Reset Timer */ 281 am335x_dmtimer_tc_write_4(DMTIMER_TSICR, 2); 282 283 /* Wait for reset to complete */ 284 while (am335x_dmtimer_tc_read_4(DMTIMER_TIOCP_CFG) & 1); 285 286 /* set load value */ 287 am335x_dmtimer_tc_write_4(DMTIMER_TLDR, 0); 288 289 /* set counter value */ 290 am335x_dmtimer_tc_write_4(DMTIMER_TCRR, 0); 291 292 /* Set Timer autoreload(AR) and start timer(ST) */ 293 am335x_dmtimer_tc_write_4(DMTIMER_TCLR, 3); 294 295 am335x_dmtimer_tc.tc_frequency = sc->sysclk_freq; 296 tc_init(&am335x_dmtimer_tc); 297 298 /* Register DMTimer3 as ET */ 299 300 /* Setup and enable the timer */ 301 if (bus_setup_intr(dev, sc->tmr_irq_res[3], INTR_TYPE_CLK, 302 am335x_dmtimer_intr, NULL, &sc->t[3], &ihl) != 0) { 303 bus_release_resources(dev, am335x_dmtimer_irq_spec, 304 sc->tmr_irq_res); 305 device_printf(dev, "Unable to setup the clock irq handler.\n"); 306 return (ENXIO); 307 } 308 309 sc->t[3].et.et_name = "AM335x Eventtimer0"; 310 sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; 311 sc->t[3].et.et_quality = 1000; 312 sc->t[3].et.et_frequency = sc->sysclk_freq; 313 sc->t[3].et.et_min_period = 314 (0x00000002LLU << 32) / sc->t[3].et.et_frequency; 315 sc->t[3].et.et_max_period = 316 (0xfffffffeLLU << 32) / sc->t[3].et.et_frequency; 317 sc->t[3].et.et_start = am335x_dmtimer_start; 318 sc->t[3].et.et_stop = am335x_dmtimer_stop; 319 sc->t[3].et.et_priv = &sc->t[3]; 320 et_register(&sc->t[3].et); 321 322 return (0); 323} 324 325static device_method_t am335x_dmtimer_methods[] = { 326 DEVMETHOD(device_probe, am335x_dmtimer_probe), 327 DEVMETHOD(device_attach, am335x_dmtimer_attach), 328 { 0, 0 } 329}; 330 331static driver_t am335x_dmtimer_driver = { 332 "am335x_dmtimer", 333 am335x_dmtimer_methods, 334 sizeof(struct am335x_dmtimer_softc), 335}; 336 337static devclass_t am335x_dmtimer_devclass; 338 339DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0); 340MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1); 341 342void 343cpu_initclocks(void) 344{ 345 cpu_initclocks_bsp(); 346} 347 348void 349DELAY(int usec) 350{ 351 int32_t counts; 352 uint32_t first, last; 353 354 if (am335x_dmtimer_tc_tmr == NULL) { 355 for (; usec > 0; usec--) 356 for (counts = 200; counts > 0; counts--) 357 /* Prevent gcc from optimizing out the loop */ 358 cpufunc_nullop(); 359 return; 360 } 361 362 /* Get the number of times to count */ 363 counts = usec * ((am335x_dmtimer_tc.tc_frequency / 1000000) + 1); 364 365 first = am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 366 367 while (counts > 0) { 368 last = am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 369 if (last>first) { 370 counts -= (int32_t)(last - first); 371 } else { 372 counts -= (int32_t)((0xFFFFFFFF - first) + last); 373 } 374 first = last; 375 } 376} 377 378