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/intr.h> 43 44 #include <dev/fdt/fdt_common.h> 45 #include <dev/ofw/openfirm.h> 46 #include <dev/ofw/ofw_bus.h> 47 #include <dev/ofw/ofw_bus_subr.h> 48 49 #include <machine/bus.h> 50 #include <machine/fdt.h> 51 52 #include <arm/ti/ti_prcm.h> 53 54 #define AM335X_NUM_TIMERS 8 55 56 #define DMTIMER_TIDR 0x00 /* Identification Register */ 57 #define DMTIMER_TIOCP_CFG 0x10 /* Timer OCP Configuration Reg */ 58 #define DMTIMER_IQR_EOI 0x20 /* Timer IRQ End-Of-Interrupt Reg */ 59 #define DMTIMER_IRQSTATUS_RAW 0x24 /* Timer IRQSTATUS Raw Reg */ 60 #define DMTIMER_IRQSTATUS 0x28 /* Timer IRQSTATUS Reg */ 61 #define DMTIMER_IRQENABLE_SET 0x2c /* Timer IRQSTATUS Set Reg */ 62 #define DMTIMER_IRQENABLE_CLR 0x30 /* Timer IRQSTATUS Clear Reg */ 63 #define DMTIMER_IRQWAKEEN 0x34 /* Timer IRQ Wakeup Enable Reg */ 64 #define DMTIMER_TCLR 0x38 /* Timer Control Register */ 65 #define DMTIMER_TCRR 0x3C /* Timer Counter Register */ 66 #define DMTIMER_TLDR 0x40 /* Timer Load Reg */ 67 #define DMTIMER_TTGR 0x44 /* Timer Trigger Reg */ 68 #define DMTIMER_TWPS 0x48 /* Timer Write Posted Status Reg */ 69 #define DMTIMER_TMAR 0x4C /* Timer Match Reg */ 70 #define DMTIMER_TCAR1 0x50 /* Timer Capture Reg */ 71 #define DMTIMER_TSICR 0x54 /* Timer Synchr. Interface Control Reg */ 72 #define DMTIMER_TCAR2 0x48 /* Timer Capture Reg */ 73 74 75 struct am335x_dmtimer_softc { 76 struct resource * tmr_mem_res[AM335X_NUM_TIMERS]; 77 struct resource * tmr_irq_res[AM335X_NUM_TIMERS]; 78 uint32_t sysclk_freq; 79 struct am335x_dmtimer { 80 bus_space_tag_t bst; 81 bus_space_handle_t bsh; 82 struct eventtimer et; 83 } t[AM335X_NUM_TIMERS]; 84 }; 85 86 static struct resource_spec am335x_dmtimer_mem_spec[] = { 87 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 88 { SYS_RES_MEMORY, 1, RF_ACTIVE }, 89 { SYS_RES_MEMORY, 2, RF_ACTIVE }, 90 { SYS_RES_MEMORY, 3, RF_ACTIVE }, 91 { SYS_RES_MEMORY, 4, RF_ACTIVE }, 92 { SYS_RES_MEMORY, 5, RF_ACTIVE }, 93 { SYS_RES_MEMORY, 6, RF_ACTIVE }, 94 { SYS_RES_MEMORY, 7, RF_ACTIVE }, 95 { -1, 0, 0 } 96 }; 97 static struct resource_spec am335x_dmtimer_irq_spec[] = { 98 { SYS_RES_IRQ, 0, RF_ACTIVE }, 99 { SYS_RES_IRQ, 1, RF_ACTIVE }, 100 { SYS_RES_IRQ, 2, RF_ACTIVE }, 101 { SYS_RES_IRQ, 3, RF_ACTIVE }, 102 { SYS_RES_IRQ, 4, RF_ACTIVE }, 103 { SYS_RES_IRQ, 5, RF_ACTIVE }, 104 { SYS_RES_IRQ, 6, RF_ACTIVE }, 105 { SYS_RES_IRQ, 7, RF_ACTIVE }, 106 { -1, 0, 0 } 107 }; 108 109 static struct am335x_dmtimer *am335x_dmtimer_tc_tmr = NULL; 110 111 /* Read/Write macros for Timer used as timecounter */ 112 #define am335x_dmtimer_tc_read_4(reg) \ 113 bus_space_read_4(am335x_dmtimer_tc_tmr->bst, \ 114 am335x_dmtimer_tc_tmr->bsh, reg) 115 116 #define am335x_dmtimer_tc_write_4(reg, val) \ 117 bus_space_write_4(am335x_dmtimer_tc_tmr->bst, \ 118 am335x_dmtimer_tc_tmr->bsh, reg, val) 119 120 /* Read/Write macros for Timer used as eventtimer */ 121 #define am335x_dmtimer_et_read_4(reg) \ 122 bus_space_read_4(tmr->bst, tmr->bsh, reg) 123 124 #define am335x_dmtimer_et_write_4(reg, val) \ 125 bus_space_write_4(tmr->bst, tmr->bsh, reg, val) 126 127 static unsigned am335x_dmtimer_tc_get_timecount(struct timecounter *); 128 129 static struct timecounter am335x_dmtimer_tc = { 130 .tc_name = "AM335x Timecounter", 131 .tc_get_timecount = am335x_dmtimer_tc_get_timecount, 132 .tc_poll_pps = NULL, 133 .tc_counter_mask = ~0u, 134 .tc_frequency = 0, 135 .tc_quality = 1000, 136 }; 137 138 static unsigned 139 am335x_dmtimer_tc_get_timecount(struct timecounter *tc) 140 { 141 return am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 142 } 143 144 static int 145 am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) 146 { 147 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv; 148 uint32_t load, count; 149 uint32_t tclr = 0; 150 151 if (period != 0) { 152 load = ((uint32_t)et->et_frequency * period) >> 32; 153 tclr |= 2; /* autoreload bit */ 154 panic("periodic timer not implemented\n"); 155 } else { 156 load = 0; 157 } 158 159 if (first != 0) 160 count = ((uint32_t)et->et_frequency * first) >> 32; 161 else 162 count = load; 163 164 /* Reset Timer */ 165 am335x_dmtimer_et_write_4(DMTIMER_TSICR, 2); 166 167 /* Wait for reset to complete */ 168 while (am335x_dmtimer_et_read_4(DMTIMER_TIOCP_CFG) & 1); 169 170 /* set load value */ 171 am335x_dmtimer_et_write_4(DMTIMER_TLDR, 0xFFFFFFFE - load); 172 173 /* set counter value */ 174 am335x_dmtimer_et_write_4(DMTIMER_TCRR, 0xFFFFFFFE - count); 175 176 /* enable overflow interrupt */ 177 am335x_dmtimer_et_write_4(DMTIMER_IRQENABLE_SET, 2); 178 179 /* start timer(ST) */ 180 tclr |= 1; 181 am335x_dmtimer_et_write_4(DMTIMER_TCLR, tclr); 182 183 return (0); 184 } 185 186 static int 187 am335x_dmtimer_stop(struct eventtimer *et) 188 { 189 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv; 190 191 /* Disable all interrupts */ 192 am335x_dmtimer_et_write_4(DMTIMER_IRQENABLE_CLR, 7); 193 194 /* Stop Timer */ 195 am335x_dmtimer_et_write_4(DMTIMER_TCLR, 0); 196 197 return (0); 198 } 199 200 static int 201 am335x_dmtimer_intr(void *arg) 202 { 203 struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)arg; 204 205 /* Ack interrupt */ 206 am335x_dmtimer_et_write_4(DMTIMER_IRQSTATUS, 7); 207 if (tmr->et.et_active) 208 tmr->et.et_event_cb(&tmr->et, tmr->et.et_arg); 209 210 return (FILTER_HANDLED); 211 } 212 213 static int 214 am335x_dmtimer_probe(device_t dev) 215 { 216 struct am335x_dmtimer_softc *sc; 217 sc = (struct am335x_dmtimer_softc *)device_get_softc(dev); 218 219 if (ofw_bus_is_compatible(dev, "ti,am335x-dmtimer")) { 220 device_set_desc(dev, "AM335x DMTimer"); 221 return(BUS_PROBE_DEFAULT); 222 } 223 224 return (ENXIO); 225 } 226 227 static int 228 am335x_dmtimer_attach(device_t dev) 229 { 230 struct am335x_dmtimer_softc *sc = device_get_softc(dev); 231 void *ihl; 232 int err; 233 int i; 234 235 if (am335x_dmtimer_tc_tmr != NULL) 236 return (EINVAL); 237 238 /* Get the base clock frequency */ 239 err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq); 240 if (err) { 241 device_printf(dev, "Error: could not get sysclk frequency\n"); 242 return (ENXIO); 243 } 244 245 /* Request the memory resources */ 246 err = bus_alloc_resources(dev, am335x_dmtimer_mem_spec, 247 sc->tmr_mem_res); 248 if (err) { 249 device_printf(dev, "Error: could not allocate mem resources\n"); 250 return (ENXIO); 251 } 252 253 /* Request the IRQ resources */ 254 err = bus_alloc_resources(dev, am335x_dmtimer_irq_spec, 255 sc->tmr_irq_res); 256 if (err) { 257 device_printf(dev, "Error: could not allocate irq resources\n"); 258 return (ENXIO); 259 } 260 261 for(i=0;i<AM335X_NUM_TIMERS;i++) { 262 sc->t[i].bst = rman_get_bustag(sc->tmr_mem_res[i]); 263 sc->t[i].bsh = rman_get_bushandle(sc->tmr_mem_res[i]); 264 } 265 266 /* Configure DMTimer2 and DMTimer3 source and enable them */ 267 err = ti_prcm_clk_set_source(DMTIMER2_CLK, SYSCLK_CLK); 268 err |= ti_prcm_clk_enable(DMTIMER2_CLK); 269 err |= ti_prcm_clk_set_source(DMTIMER3_CLK, SYSCLK_CLK); 270 err |= ti_prcm_clk_enable(DMTIMER3_CLK); 271 if (err) { 272 device_printf(dev, "Error: could not setup timer clock\n"); 273 return (ENXIO); 274 } 275 276 /* Take DMTimer2 for TC */ 277 am335x_dmtimer_tc_tmr = &sc->t[2]; 278 279 /* Reset Timer */ 280 am335x_dmtimer_tc_write_4(DMTIMER_TSICR, 2); 281 282 /* Wait for reset to complete */ 283 while (am335x_dmtimer_tc_read_4(DMTIMER_TIOCP_CFG) & 1); 284 285 /* set load value */ 286 am335x_dmtimer_tc_write_4(DMTIMER_TLDR, 0); 287 288 /* set counter value */ 289 am335x_dmtimer_tc_write_4(DMTIMER_TCRR, 0); 290 291 /* Set Timer autoreload(AR) and start timer(ST) */ 292 am335x_dmtimer_tc_write_4(DMTIMER_TCLR, 3); 293 294 am335x_dmtimer_tc.tc_frequency = sc->sysclk_freq; 295 tc_init(&am335x_dmtimer_tc); 296 297 /* Register DMTimer3 as ET */ 298 299 /* Setup and enable the timer */ 300 if (bus_setup_intr(dev, sc->tmr_irq_res[3], INTR_TYPE_CLK, 301 am335x_dmtimer_intr, NULL, &sc->t[3], &ihl) != 0) { 302 bus_release_resources(dev, am335x_dmtimer_irq_spec, 303 sc->tmr_irq_res); 304 device_printf(dev, "Unable to setup the clock irq handler.\n"); 305 return (ENXIO); 306 } 307 308 sc->t[3].et.et_name = "AM335x Eventtimer0"; 309 sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; 310 sc->t[3].et.et_quality = 1000; 311 sc->t[3].et.et_frequency = sc->sysclk_freq; 312 sc->t[3].et.et_min_period = 313 (0x00000002LLU << 32) / sc->t[3].et.et_frequency; 314 sc->t[3].et.et_max_period = 315 (0xfffffffeLLU << 32) / sc->t[3].et.et_frequency; 316 sc->t[3].et.et_start = am335x_dmtimer_start; 317 sc->t[3].et.et_stop = am335x_dmtimer_stop; 318 sc->t[3].et.et_priv = &sc->t[3]; 319 et_register(&sc->t[3].et); 320 321 return (0); 322 } 323 324 static device_method_t am335x_dmtimer_methods[] = { 325 DEVMETHOD(device_probe, am335x_dmtimer_probe), 326 DEVMETHOD(device_attach, am335x_dmtimer_attach), 327 { 0, 0 } 328 }; 329 330 static driver_t am335x_dmtimer_driver = { 331 "am335x_dmtimer", 332 am335x_dmtimer_methods, 333 sizeof(struct am335x_dmtimer_softc), 334 }; 335 336 static devclass_t am335x_dmtimer_devclass; 337 338 DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0); 339 MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1); 340 341 void 342 cpu_initclocks(void) 343 { 344 cpu_initclocks_bsp(); 345 } 346 347 void 348 DELAY(int usec) 349 { 350 int32_t counts; 351 uint32_t first, last; 352 353 if (am335x_dmtimer_tc_tmr == NULL) { 354 for (; usec > 0; usec--) 355 for (counts = 200; counts > 0; counts--) 356 /* Prevent gcc from optimizing out the loop */ 357 cpufunc_nullop(); 358 return; 359 } 360 361 /* Get the number of times to count */ 362 counts = usec * ((am335x_dmtimer_tc.tc_frequency / 1000000) + 1); 363 364 first = am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 365 366 while (counts > 0) { 367 last = am335x_dmtimer_tc_read_4(DMTIMER_TCRR); 368 if (last>first) { 369 counts -= (int32_t)(last - first); 370 } else { 371 counts -= (int32_t)((0xFFFFFFFF - first) + last); 372 } 373 first = last; 374 } 375 } 376 377