1 /* $OpenBSD: gptimer.c,v 1.10 2021/01/19 12:29:07 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * WARNING - this timer initializion has not been checked 20 * to see if it will do _ANYTHING_ sane if the omap enters 21 * low power mode. 22 */ 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 #include <sys/kernel.h> 27 #include <sys/time.h> 28 #include <sys/evcount.h> 29 #include <sys/device.h> 30 #include <sys/timetc.h> 31 #include <dev/clock_subr.h> 32 #include <machine/bus.h> 33 #include <armv7/armv7/armv7var.h> 34 #include <armv7/omap/prcmvar.h> 35 36 #include <machine/intr.h> 37 #include <arm/cpufunc.h> 38 39 /* registers */ 40 #define GP_TIDR 0x000 41 #define GP_TIDR_REV 0xff 42 #define GP_TIOCP_CFG 0x010 43 #define GP_TIOCP_CFG_CLKA 0x000000300 44 #define GP_TIOCP_CFG_EMUFREE 0x000000020 45 #define GP_TIOCP_CFG_IDLEMODE 0x000000018 46 #define GP_TIOCP_CFG_ENAPWAKEUP 0x000000004 47 #define GP_TIOCP_CFG_SOFTRESET 0x000000002 48 #define GP_TIOCP_CFG_AUTOIDLE 0x000000001 49 #define GP_TISTAT 0x014 50 #define GP_TISTAT_RESETDONE 0x000000001 51 #define GP_TISR 0x018 52 #define GP_TISTAT_TCAR 0x00000004 53 #define GP_TISTAT_OVF 0x00000002 54 #define GP_TISTAT_MATCH 0x00000001 55 #define GP_TIER 0x1c 56 #define GP_TIER_TCAR_EN 0x4 57 #define GP_TIER_OVF_EN 0x2 58 #define GP_TIER_MAT_EN 0x1 59 #define GP_TWER 0x020 60 #define GP_TWER_TCAR_EN 0x00000004 61 #define GP_TWER_OVF_EN 0x00000002 62 #define GP_TWER_MAT_EN 0x00000001 63 #define GP_TCLR 0x024 64 #define GP_TCLR_GPO (1<<14) 65 #define GP_TCLR_CAPT (1<<13) 66 #define GP_TCLR_PT (1<<12) 67 #define GP_TCLR_TRG (3<<10) 68 #define GP_TCLR_TRG_O (1<<10) 69 #define GP_TCLR_TRG_OM (2<<10) 70 #define GP_TCLR_TCM (3<<8) 71 #define GP_TCLR_TCM_RISE (1<<8) 72 #define GP_TCLR_TCM_FALL (2<<8) 73 #define GP_TCLR_TCM_BOTH (3<<8) 74 #define GP_TCLR_SCPWM (1<<7) 75 #define GP_TCLR_CE (1<<6) 76 #define GP_TCLR_PRE (1<<5) 77 #define GP_TCLR_PTV (7<<2) 78 #define GP_TCLR_AR (1<<1) 79 #define GP_TCLR_ST (1<<0) 80 #define GP_TCRR 0x028 /* counter */ 81 #define GP_TLDR 0x02c /* reload */ 82 #define GP_TTGR 0x030 83 #define GP_TWPS 0x034 84 #define GP_TWPS_TCLR 0x01 85 #define GP_TWPS_TCRR 0x02 86 #define GP_TWPS_TLDR 0x04 87 #define GP_TWPS_TTGR 0x08 88 #define GP_TWPS_TMAR 0x10 89 #define GP_TWPS_ALL 0x1f 90 #define GP_TMAR 0x038 91 #define GP_TCAR 0x03C 92 #define GP_TSICR 0x040 93 #define GP_TSICR_POSTED 0x00000002 94 #define GP_TSICR_SFT 0x00000001 95 #define GP_TCAR2 0x044 96 97 #define TIMER_FREQUENCY 32768 /* 32kHz is used, selectable */ 98 99 static struct evcount clk_count; 100 static struct evcount stat_count; 101 102 void gptimer_attach(struct device *parent, struct device *self, void *args); 103 int gptimer_intr(void *frame); 104 void gptimer_wait(int reg); 105 void gptimer_cpu_initclocks(void); 106 void gptimer_delay(u_int); 107 void gptimer_setstatclockrate(int newhz); 108 109 bus_space_tag_t gptimer_iot; 110 bus_space_handle_t gptimer_ioh0, gptimer_ioh1; 111 int gptimer_irq = 0; 112 113 u_int gptimer_get_timecount(struct timecounter *); 114 115 static struct timecounter gptimer_timecounter = { 116 gptimer_get_timecount, NULL, 0xffffffff, 0, "gptimer", 0, NULL, 0 117 }; 118 119 volatile u_int32_t nexttickevent; 120 volatile u_int32_t nextstatevent; 121 u_int32_t ticks_per_second; 122 u_int32_t ticks_per_intr; 123 u_int32_t ticks_err_cnt; 124 u_int32_t ticks_err_sum; 125 u_int32_t statvar, statmin; 126 127 struct cfattach gptimer_ca = { 128 sizeof (struct device), NULL, gptimer_attach 129 }; 130 131 struct cfdriver gptimer_cd = { 132 NULL, "gptimer", DV_DULL 133 }; 134 135 void 136 gptimer_attach(struct device *parent, struct device *self, void *args) 137 { 138 struct armv7_attach_args *aa = args; 139 bus_space_handle_t ioh; 140 u_int32_t rev; 141 142 gptimer_iot = aa->aa_iot; 143 if (bus_space_map(gptimer_iot, aa->aa_dev->mem[0].addr, 144 aa->aa_dev->mem[0].size, 0, &ioh)) 145 panic("gptimer_attach: bus_space_map failed!"); 146 147 rev = bus_space_read_4(gptimer_iot, ioh, GP_TIDR); 148 149 printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf); 150 if (self->dv_unit == 0) { 151 gptimer_ioh0 = ioh; 152 gptimer_irq = aa->aa_dev->irq[0]; 153 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, 0); 154 } else if (self->dv_unit == 1) { 155 /* start timer because it is used in delay */ 156 gptimer_ioh1 = ioh; 157 bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCRR, 0); 158 gptimer_wait(GP_TWPS_ALL); 159 bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TLDR, 0); 160 gptimer_wait(GP_TWPS_ALL); 161 bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCLR, 162 GP_TCLR_AR | GP_TCLR_ST); 163 gptimer_wait(GP_TWPS_ALL); 164 165 gptimer_timecounter.tc_frequency = TIMER_FREQUENCY; 166 tc_init(&gptimer_timecounter); 167 } 168 else 169 panic("attaching too many gptimers at 0x%lx", 170 aa->aa_dev->mem[0].addr); 171 172 arm_clock_register(gptimer_cpu_initclocks, gptimer_delay, 173 gptimer_setstatclockrate, NULL); 174 } 175 176 /* 177 * See comment in arm/xscale/i80321_clock.c 178 * 179 * counter is count up, but with autoreload timers it is not possible 180 * to detect how many interrupts passed while interrupts were blocked. 181 * also it is not possible to atomically add to the register 182 * get get it to precisely fire at a non-fixed interval. 183 * 184 * To work around this two timers are used, GPT1 is used as a reference 185 * clock without reload , however we just ignore the interrupt it 186 * would (may?) generate. 187 * 188 * Internally this keeps track of when the next timer should fire 189 * and based on that time and the current value of the reference 190 * clock a number is written into the timer count register to schedule 191 * the next event. 192 */ 193 194 int 195 gptimer_intr(void *frame) 196 { 197 u_int32_t now, r; 198 u_int32_t nextevent, duration; 199 200 /* clear interrupt */ 201 now = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); 202 203 while ((int32_t) (nexttickevent - now) < 0) { 204 nexttickevent += ticks_per_intr; 205 ticks_err_sum += ticks_err_cnt; 206 #if 0 207 if (ticks_err_sum > hz) { 208 u_int32_t match_error; 209 match_error = ticks_err_sum / hz 210 ticks_err_sum -= (match_error * hz); 211 } 212 #else 213 /* looping a few times is faster than divide */ 214 while (ticks_err_sum > hz) { 215 nexttickevent += 1; 216 ticks_err_sum -= hz; 217 } 218 #endif 219 clk_count.ec_count++; 220 hardclock(frame); 221 } 222 while ((int32_t) (nextstatevent - now) < 0) { 223 do { 224 r = random() & (statvar -1); 225 } while (r == 0); /* random == 0 not allowed */ 226 nextstatevent += statmin + r; 227 /* XXX - correct nextstatevent? */ 228 stat_count.ec_count++; 229 statclock(frame); 230 } 231 if ((nexttickevent - now) < (nextstatevent - now)) 232 nextevent = nexttickevent; 233 else 234 nextevent = nextstatevent; 235 236 /* XXX */ 237 duration = nextevent - 238 bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); 239 #if 0 240 printf("duration 0x%x %x %x\n", nextevent - 241 bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR), 242 bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TCRR), 243 bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR)); 244 #endif 245 246 247 if (duration <= 0) 248 duration = 1; /* trigger immediately. */ 249 250 if (duration > ticks_per_intr) { 251 /* 252 * If interrupts are blocked too long, like during 253 * the root prompt or ddb, the timer can roll over, 254 * this will allow the system to continue to run 255 * even if time is lost. 256 */ 257 duration = ticks_per_intr; 258 nexttickevent = now; 259 nextstatevent = now; 260 } 261 262 gptimer_wait(GP_TWPS_ALL); 263 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR, 264 bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR)); 265 gptimer_wait(GP_TWPS_ALL); 266 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -duration); 267 268 return 1; 269 } 270 271 /* 272 * would be interesting to play with trigger mode while having one timer 273 * in 32KHz mode, and the other timer running in sysclk mode and use 274 * the high resolution speeds (matters more for delay than tick timer 275 */ 276 277 void 278 gptimer_cpu_initclocks() 279 { 280 stathz = 128; 281 profhz = 1024; 282 283 ticks_per_second = TIMER_FREQUENCY; 284 285 setstatclockrate(stathz); 286 287 ticks_per_intr = ticks_per_second / hz; 288 ticks_err_cnt = ticks_per_second % hz; 289 ticks_err_sum = 0; 290 291 prcm_setclock(1, PRCM_CLK_SPEED_32); 292 prcm_setclock(2, PRCM_CLK_SPEED_32); 293 /* establish interrupts */ 294 arm_intr_establish(gptimer_irq, IPL_CLOCK, gptimer_intr, 295 NULL, "tick"); 296 297 /* setup timer 0 (hardware timer 2) */ 298 /* reset? - XXX */ 299 300 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TLDR, 0); 301 302 nexttickevent = nextstatevent = bus_space_read_4(gptimer_iot, 303 gptimer_ioh1, GP_TCRR) + ticks_per_intr; 304 305 gptimer_wait(GP_TWPS_ALL); 306 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TIER, GP_TIER_OVF_EN); 307 gptimer_wait(GP_TWPS_ALL); 308 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TWER, GP_TWER_OVF_EN); 309 gptimer_wait(GP_TWPS_ALL); 310 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, 311 GP_TCLR_AR | GP_TCLR_ST); 312 gptimer_wait(GP_TWPS_ALL); 313 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR, 314 bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR)); 315 gptimer_wait(GP_TWPS_ALL); 316 bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -ticks_per_intr); 317 gptimer_wait(GP_TWPS_ALL); 318 } 319 320 void 321 gptimer_wait(int reg) 322 { 323 while (bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TWPS) & reg) 324 ; 325 } 326 327 #if 0 328 void 329 microtime(struct timeval *tvp) 330 { 331 int s; 332 int deltacnt; 333 u_int32_t counter, expected; 334 s = splhigh(); 335 336 if (1) { /* not inited */ 337 tvp->tv_sec = 0; 338 tvp->tv_usec = 0; 339 return; 340 } 341 s = splhigh(); 342 counter = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); 343 expected = nexttickevent; 344 345 *tvp = time; 346 splx(s); 347 348 deltacnt = counter - expected + ticks_per_intr; 349 350 #if 1 351 /* low frequency timer algorithm */ 352 tvp->tv_usec += deltacnt * 1000000ULL / TIMER_FREQUENCY; 353 #else 354 /* high frequency timer algorithm - XXX */ 355 tvp->tv_usec += deltacnt / (TIMER_FREQUENCY / 1000000ULL); 356 #endif 357 358 while (tvp->tv_usec >= 1000000) { 359 tvp->tv_sec++; 360 tvp->tv_usec -= 1000000; 361 } 362 363 } 364 #endif 365 366 void 367 gptimer_delay(u_int usecs) 368 { 369 u_int32_t clock, oclock, delta, delaycnt; 370 volatile int j; 371 int csec, usec; 372 373 if (usecs > (0x80000000 / (TIMER_FREQUENCY))) { 374 csec = usecs / 10000; 375 usec = usecs % 10000; 376 377 delaycnt = (TIMER_FREQUENCY / 100) * csec + 378 (TIMER_FREQUENCY / 100) * usec / 10000; 379 } else { 380 delaycnt = TIMER_FREQUENCY * usecs / 1000000; 381 } 382 if (delaycnt <= 1) 383 for (j = 100; j > 0; j--) 384 ; 385 386 if (gptimer_ioh1 == 0) { 387 /* BAH */ 388 for (; usecs > 0; usecs--) 389 for (j = 100; j > 0; j--) 390 ; 391 return; 392 } 393 oclock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); 394 while (1) { 395 for (j = 100; j > 0; j--) 396 ; 397 clock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); 398 delta = clock - oclock; 399 if (delta > delaycnt) 400 break; 401 } 402 403 } 404 405 void 406 gptimer_setstatclockrate(int newhz) 407 { 408 int minint, statint; 409 int s; 410 411 s = splclock(); 412 413 statint = ticks_per_second / newhz; 414 /* calculate largest 2^n which is smaller that just over half statint */ 415 statvar = 0x40000000; /* really big power of two */ 416 minint = statint / 2 + 100; 417 while (statvar > minint) 418 statvar >>= 1; 419 420 statmin = statint - (statvar >> 1); 421 422 splx(s); 423 424 /* 425 * XXX this allows the next stat timer to occur then it switches 426 * to the new frequency. Rather than switching instantly. 427 */ 428 } 429 430 431 u_int 432 gptimer_get_timecount(struct timecounter *tc) 433 { 434 return bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); 435 } 436