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