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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 #include <sys/module.h> 35 #include <sys/malloc.h> 36 #include <sys/rman.h> 37 #include <sys/timeet.h> 38 #include <sys/timetc.h> 39 #include <sys/watchdog.h> 40 #include <machine/bus.h> 41 #include <machine/cpu.h> 42 #include <machine/frame.h> 43 #include <machine/intr.h> 44 45 #include <dev/fdt/fdt_common.h> 46 #include <dev/ofw/openfirm.h> 47 #include <dev/ofw/ofw_bus.h> 48 #include <dev/ofw/ofw_bus_subr.h> 49 50 #include <machine/bus.h> 51 #include <machine/fdt.h> 52 53 #include <arm/ti/ti_prcm.h> 54 55 #define AM335X_NUM_TIMERS 8 56 57 #define DMTIMER_TIDR 0x00 /* Identification Register */ 58 #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 76 struct 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 87 static 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 }; 98 static 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 110 static 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 128 static unsigned am335x_dmtimer_tc_get_timecount(struct timecounter *); 129 130 static 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 139 static unsigned 140 am335x_dmtimer_tc_get_timecount(struct timecounter *tc) 141 { 142 return am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 143 } 144 145 static int 146 am335x_dmtimer_start(struct eventtimer *et, struct bintime *first, 147 struct bintime *period) 148 { 149 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv; 150 uint32_t load, count; 151 uint32_t tclr = 0; 152 153 if (period != NULL) { 154 load = (et->et_frequency * (period->frac >> 32)) >> 32; 155 if (period->sec > 0) 156 load += et->et_frequency * period->sec; 157 tclr |= 2; /* autoreload bit */ 158 panic("periodic timer not implemented\n"); 159 } else { 160 load = 0; 161 } 162 163 if (first != NULL) { 164 count = (tmr->et.et_frequency * (first->frac >> 32)) >> 32; 165 if (first->sec != 0) 166 count += tmr->et.et_frequency * first->sec; 167 } else { 168 count = load; 169 } 170 171 /* Reset Timer */ 172 am335x_dmtimer_et_write_4(DMTIMER_TSICR, 2); 173 174 /* Wait for reset to complete */ 175 while (am335x_dmtimer_et_read_4(DMTIMER_TIOCP_CFG) & 1); 176 177 /* set load value */ 178 am335x_dmtimer_et_write_4(DMTIMER_TLDR, 0xFFFFFFFE - load); 179 180 /* set counter value */ 181 am335x_dmtimer_et_write_4(DMTIMER_TCRR, 0xFFFFFFFE - count); 182 183 /* enable overflow interrupt */ 184 am335x_dmtimer_et_write_4(DMTIMER_IRQENABLE_SET, 2); 185 186 /* start timer(ST) */ 187 tclr |= 1; 188 am335x_dmtimer_et_write_4(DMTIMER_TCLR, tclr); 189 190 return (0); 191 } 192 193 static int 194 am335x_dmtimer_stop(struct eventtimer *et) 195 { 196 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv; 197 198 /* Disable all interrupts */ 199 am335x_dmtimer_et_write_4(DMTIMER_IRQENABLE_CLR, 7); 200 201 /* Stop Timer */ 202 am335x_dmtimer_et_write_4(DMTIMER_TCLR, 0); 203 204 return (0); 205 } 206 207 static int 208 am335x_dmtimer_intr(void *arg) 209 { 210 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)arg; 211 212 /* Ack interrupt */ 213 am335x_dmtimer_et_write_4(DMTIMER_IRQSTATUS, 7); 214 if (tmr->et.et_active) 215 tmr->et.et_event_cb(&tmr->et, tmr->et.et_arg); 216 217 return (FILTER_HANDLED); 218 } 219 220 static int 221 am335x_dmtimer_probe(device_t dev) 222 { 223 struct am335x_dmtimer_softc *sc; 224 sc = (struct am335x_dmtimer_softc *)device_get_softc(dev); 225 226 if (ofw_bus_is_compatible(dev, "ti,am335x-dmtimer")) { 227 device_set_desc(dev, "AM335x DMTimer"); 228 return(BUS_PROBE_DEFAULT); 229 } 230 231 return (ENXIO); 232 } 233 234 static int 235 am335x_dmtimer_attach(device_t dev) 236 { 237 struct am335x_dmtimer_softc *sc = device_get_softc(dev); 238 void *ihl; 239 int err; 240 int i; 241 242 if (am335x_dmtimer_tc_tmr != NULL) 243 return (EINVAL); 244 245 /* Get the base clock frequency */ 246 err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq); 247 if (err) { 248 device_printf(dev, "Error: could not get sysclk frequency\n"); 249 return (ENXIO); 250 } 251 252 /* Request the memory resources */ 253 err = bus_alloc_resources(dev, am335x_dmtimer_mem_spec, 254 sc->tmr_mem_res); 255 if (err) { 256 device_printf(dev, "Error: could not allocate mem resources\n"); 257 return (ENXIO); 258 } 259 260 /* Request the IRQ resources */ 261 err = bus_alloc_resources(dev, am335x_dmtimer_irq_spec, 262 sc->tmr_irq_res); 263 if (err) { 264 device_printf(dev, "Error: could not allocate irq resources\n"); 265 return (ENXIO); 266 } 267 268 for(i=0;i<AM335X_NUM_TIMERS;i++) { 269 sc->t[i].bst = rman_get_bustag(sc->tmr_mem_res[i]); 270 sc->t[i].bsh = rman_get_bushandle(sc->tmr_mem_res[i]); 271 } 272 273 /* Configure DMTimer2 and DMTimer3 source and enable them */ 274 err = ti_prcm_clk_set_source(DMTIMER2_CLK, SYSCLK_CLK); 275 err |= ti_prcm_clk_enable(DMTIMER2_CLK); 276 err |= ti_prcm_clk_set_source(DMTIMER3_CLK, SYSCLK_CLK); 277 err |= ti_prcm_clk_enable(DMTIMER3_CLK); 278 if (err) { 279 device_printf(dev, "Error: could not setup timer clock\n"); 280 return (ENXIO); 281 } 282 283 /* Take DMTimer2 for TC */ 284 am335x_dmtimer_tc_tmr = &sc->t[2]; 285 286 /* Reset Timer */ 287 am335x_dmtimer_tc_write_4(DMTIMER_TSICR, 2); 288 289 /* Wait for reset to complete */ 290 while (am335x_dmtimer_tc_read_4(DMTIMER_TIOCP_CFG) & 1); 291 292 /* set load value */ 293 am335x_dmtimer_tc_write_4(DMTIMER_TLDR, 0); 294 295 /* set counter value */ 296 am335x_dmtimer_tc_write_4(DMTIMER_TCRR, 0); 297 298 /* Set Timer autoreload(AR) and start timer(ST) */ 299 am335x_dmtimer_tc_write_4(DMTIMER_TCLR, 3); 300 301 am335x_dmtimer_tc.tc_frequency = sc->sysclk_freq; 302 tc_init(&am335x_dmtimer_tc); 303 304 /* Register DMTimer3 as ET */ 305 306 /* Setup and enable the timer */ 307 if (bus_setup_intr(dev, sc->tmr_irq_res[3], INTR_TYPE_CLK, 308 am335x_dmtimer_intr, NULL, &sc->t[3], &ihl) != 0) { 309 bus_release_resources(dev, am335x_dmtimer_irq_spec, 310 sc->tmr_irq_res); 311 device_printf(dev, "Unable to setup the clock irq handler.\n"); 312 return (ENXIO); 313 } 314 315 sc->t[3].et.et_name = "AM335x Eventtimer0"; 316 sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; 317 sc->t[3].et.et_quality = 1000; 318 sc->t[3].et.et_frequency = sc->sysclk_freq; 319 sc->t[3].et.et_min_period.sec = 0; 320 sc->t[3].et.et_min_period.frac = 321 ((0x00000002LLU << 32) / sc->t[3].et.et_frequency) << 32; 322 sc->t[3].et.et_max_period.sec = 0xfffffff0U / sc->t[3].et.et_frequency; 323 sc->t[3].et.et_max_period.frac = 324 ((0xfffffffeLLU << 32) / sc->t[3].et.et_frequency) << 32; 325 sc->t[3].et.et_start = am335x_dmtimer_start; 326 sc->t[3].et.et_stop = am335x_dmtimer_stop; 327 sc->t[3].et.et_priv = &sc->t[3]; 328 et_register(&sc->t[3].et); 329 330 return (0); 331 } 332 333 static device_method_t am335x_dmtimer_methods[] = { 334 DEVMETHOD(device_probe, am335x_dmtimer_probe), 335 DEVMETHOD(device_attach, am335x_dmtimer_attach), 336 { 0, 0 } 337 }; 338 339 static driver_t am335x_dmtimer_driver = { 340 "am335x_dmtimer", 341 am335x_dmtimer_methods, 342 sizeof(struct am335x_dmtimer_softc), 343 }; 344 345 static devclass_t am335x_dmtimer_devclass; 346 347 DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0); 348 MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1); 349 350 void 351 cpu_initclocks(void) 352 { 353 cpu_initclocks_bsp(); 354 } 355 356 void 357 DELAY(int usec) 358 { 359 int32_t counts; 360 uint32_t first, last; 361 362 if (am335x_dmtimer_tc_tmr == NULL) { 363 for (; usec > 0; usec--) 364 for (counts = 200; counts > 0; counts--) 365 /* Prevent gcc from optimizing out the loop */ 366 cpufunc_nullop(); 367 return; 368 } 369 370 /* Get the number of times to count */ 371 counts = usec * ((am335x_dmtimer_tc.tc_frequency / 1000000) + 1); 372 373 first = am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 374 375 while (counts > 0) { 376 last = am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 377 if (last>first) { 378 counts -= (int32_t)(last - first); 379 } else { 380 counts -= (int32_t)((0xFFFFFFFF - first) + last); 381 } 382 first = last; 383 } 384 } 385 386