1 /* $OpenBSD: sxitimer.c,v 1.6 2016/07/18 19:22:45 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> 4 * Copyright (c) 2013 Raphael Graf <r@undefined.ch> 5 * Copyright (c) 2013 Artturi Alm 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/kernel.h> 24 #include <sys/time.h> 25 #include <sys/evcount.h> 26 #include <sys/device.h> 27 #include <sys/timetc.h> 28 #include <dev/clock_subr.h> 29 30 #include <arm/cpufunc.h> 31 32 #include <machine/bus.h> 33 #include <machine/intr.h> 34 35 #include <armv7/armv7/armv7var.h> 36 #include <armv7/sunxi/sunxireg.h> 37 /* #include <armv7/sunxi/sxipiovar.h> */ 38 39 #define TIMER_IER 0x00 40 #define TIMER_ISR 0x04 41 #define TIMER_IRQ(x) (1 << (x)) 42 43 #define TIMER_CTRL(x) (0x10 + (0x10 * (x))) 44 #define TIMER_INTV(x) (0x14 + (0x10 * (x))) 45 #define TIMER_CURR(x) (0x18 + (0x10 * (x))) 46 47 /* A1X counter */ 48 #define CNT64_CTRL 0xa0 49 #define CNT64_LOW 0xa4 50 #define CNT64_HIGH 0xa8 51 52 #define CNT64_CLR_EN (1 << 0) /* clear enable */ 53 #define CNT64_RL_EN (1 << 1) /* read latch enable */ 54 55 #define LOSC_CTRL 0x100 56 #define OSC32K_SRC_SEL (1 << 0) 57 58 #define TIMER_ENABLE (1 << 0) 59 #define TIMER_RELOAD (1 << 1) 60 #define TIMER_CLK_SRC_MASK (3 << 2) 61 #define TIMER_LSOSC (0 << 2) 62 #define TIMER_OSC24M (1 << 2) 63 #define TIMER_PLL6_6 (2 << 2) 64 #define TIMER_PRESC_1 (0 << 4) 65 #define TIMER_PRESC_2 (1 << 4) 66 #define TIMER_PRESC_4 (2 << 4) 67 #define TIMER_PRESC_8 (3 << 4) 68 #define TIMER_PRESC_16 (4 << 4) 69 #define TIMER_PRESC_32 (5 << 4) 70 #define TIMER_PRESC_64 (6 << 4) 71 #define TIMER_PRESC_128 (7 << 4) 72 #define TIMER_CONTINOUS (0 << 7) 73 #define TIMER_SINGLESHOT (1 << 7) 74 75 #define TICKTIMER 0 76 #define STATTIMER 1 77 #define CNTRTIMER 2 78 79 #define TIMER_SYNC 3 80 81 void sxitimer_attach(struct device *, struct device *, void *); 82 int sxitimer_tickintr(void *); 83 int sxitimer_statintr(void *); 84 void sxitimer_cpu_initclocks(void); 85 void sxitimer_setstatclockrate(int); 86 uint64_t sxitimer_readcnt64(void); 87 uint32_t sxitimer_readcnt32(void); 88 void sxitimer_sync(void); 89 void sxitimer_delay(u_int); 90 91 u_int sxitimer_get_timecount(struct timecounter *); 92 93 static struct timecounter sxitimer_timecounter = { 94 sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL 95 }; 96 97 bus_space_tag_t sxitimer_iot; 98 bus_space_handle_t sxitimer_ioh; 99 100 uint32_t sxitimer_freq[] = { 101 TIMER0_FREQUENCY, 102 TIMER1_FREQUENCY, 103 TIMER2_FREQUENCY, 104 0 105 }; 106 107 uint32_t sxitimer_irq[] = { 108 TIMER0_IRQ, 109 TIMER1_IRQ, 110 TIMER2_IRQ, 111 0 112 }; 113 114 uint32_t sxitimer_stat_tpi, sxitimer_tick_tpi; 115 uint32_t sxitimer_statvar, sxitimer_statmin; 116 uint32_t sxitimer_tick_nextevt, sxitimer_stat_nextevt; 117 uint32_t sxitimer_ticks_err_cnt, sxitimer_ticks_err_sum; 118 119 struct sxitimer_softc { 120 struct device sc_dev; 121 }; 122 123 struct cfattach sxitimer_ca = { 124 sizeof (struct sxitimer_softc), NULL, sxitimer_attach 125 }; 126 127 struct cfdriver sxitimer_cd = { 128 NULL, "sxitimer", DV_DULL 129 }; 130 131 void 132 sxitimer_attach(struct device *parent, struct device *self, void *args) 133 { 134 struct armv7_attach_args *aa = args; 135 uint32_t freq, ival, now, cr; 136 int unit = self->dv_unit; 137 138 if (unit != 0) 139 goto skip_init; 140 141 sxitimer_iot = aa->aa_iot; 142 143 if (bus_space_map(sxitimer_iot, aa->aa_dev->mem[0].addr, 144 aa->aa_dev->mem[0].size, 0, &sxitimer_ioh)) 145 panic("sxitimer_attach: bus_space_map failed!"); 146 147 /* clear counter, loop until ready */ 148 bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL, 149 CNT64_CLR_EN); /* XXX as a side-effect counter clk src=OSC24M */ 150 while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL) 151 & CNT64_CLR_EN) 152 continue; 153 154 /* setup timers */ 155 cr = bus_space_read_4(sxitimer_iot, sxitimer_ioh, LOSC_CTRL); 156 cr |= OSC32K_SRC_SEL; /* ext 32.768KHz OSC src */ 157 bus_space_write_4(sxitimer_iot, sxitimer_ioh, LOSC_CTRL, cr); 158 159 skip_init: 160 /* timers are down-counters, from interval to 0 */ 161 now = 0xffffffff; /* known big value */ 162 freq = sxitimer_freq[unit]; 163 164 /* stop timer, and set clk src */ 165 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 166 TIMER_CTRL(unit), 167 freq == 24000000 ? TIMER_OSC24M : TIMER_LSOSC); 168 169 switch (unit) { /* XXX more XXXXTIMER magic for less lines? */ 170 case TICKTIMER: 171 ival = sxitimer_tick_tpi = freq / hz; 172 sxitimer_tick_nextevt = now - ival; 173 174 sxitimer_ticks_err_cnt = freq % hz; 175 sxitimer_ticks_err_sum = 0; 176 177 printf(": ticktimer %dhz @ %dKHz", hz, freq / 1000); 178 break; 179 case STATTIMER: 180 /* 100/1000 or 128/1024 ? */ 181 stathz = 128; 182 profhz = 1024; 183 sxitimer_setstatclockrate(stathz); 184 185 ival = sxitimer_stat_tpi = freq / stathz; 186 sxitimer_stat_nextevt = now - ival; 187 188 printf(": stattimer %dhz @ %dKHz", stathz, freq / 1000); 189 break; 190 case CNTRTIMER: 191 ival = now; 192 193 sxitimer_timecounter.tc_frequency = freq; 194 tc_init(&sxitimer_timecounter); 195 arm_clock_register(sxitimer_cpu_initclocks, sxitimer_delay, 196 sxitimer_setstatclockrate, NULL); 197 198 printf(": cntrtimer @ %dKHz", freq / 1000); 199 break; 200 default: 201 panic("sxitimer_attach: unit = %d", unit); 202 break; 203 } 204 205 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 206 TIMER_INTV(unit), ival); 207 208 printf("\n"); 209 } 210 211 /* 212 * would be interesting to play with trigger mode while having one timer 213 * in 32KHz mode, and the other timer running in sysclk mode and use 214 * the high resolution speeds (matters more for delay than tick timer) 215 */ 216 217 void 218 sxitimer_cpu_initclocks(void) 219 { 220 uint32_t isr, ier; 221 222 /* establish interrupts */ 223 arm_intr_establish(sxitimer_irq[TICKTIMER], IPL_CLOCK, 224 sxitimer_tickintr, NULL, "tick"); 225 arm_intr_establish(sxitimer_irq[STATTIMER], IPL_STATCLOCK, 226 sxitimer_statintr, NULL, "stattick"); 227 228 /* clear timer interrupt pending bits */ 229 isr = bus_space_read_4(sxitimer_iot, sxitimer_ioh, TIMER_ISR); 230 isr |= TIMER_IRQ(STATTIMER) | TIMER_IRQ(TICKTIMER); 231 bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_ISR, isr); 232 233 /* enable timer IRQs */ 234 ier = bus_space_read_4(sxitimer_iot, sxitimer_ioh, TIMER_IER); 235 ier |= TIMER_IRQ(STATTIMER) | TIMER_IRQ(TICKTIMER); 236 bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_IER, ier); 237 238 /* enable timers */ 239 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 240 TIMER_CTRL(CNTRTIMER), 241 TIMER_ENABLE | TIMER_RELOAD | TIMER_CONTINOUS); 242 243 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 244 TIMER_CTRL(STATTIMER), 245 TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 246 247 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 248 TIMER_CTRL(TICKTIMER), 249 TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 250 } 251 252 /* 253 * See comment in arm/xscale/i80321_clock.c 254 * 255 * Counter is count up, but with autoreload timers it is not possible 256 * to detect how many interrupts passed while interrupts were blocked. 257 * Also it is not possible to atomically add to the register. 258 * 259 * To work around this two timers are used, one is used as a reference 260 * clock without reload, however we just disable the interrupt it 261 * could generate. 262 * 263 * Internally this keeps track of when the next timer should fire 264 * and based on that time and the current value of the reference 265 * clock a number is written into the timer count register to schedule 266 * the next event. 267 */ 268 /* XXX update above comment */ 269 int 270 sxitimer_tickintr(void *frame) 271 { 272 uint32_t now, nextevent; 273 uint32_t val; 274 int rc = 0; 275 276 splassert(IPL_CLOCK); 277 278 /* clear timer pending interrupt bit */ 279 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 280 TIMER_ISR, TIMER_IRQ(TICKTIMER)); 281 282 now = sxitimer_readcnt32(); 283 284 while ((int32_t)(now - sxitimer_tick_nextevt) < 0) { 285 sxitimer_tick_nextevt -= sxitimer_tick_tpi; 286 sxitimer_ticks_err_sum += sxitimer_ticks_err_cnt; 287 288 while (sxitimer_ticks_err_sum > hz) { 289 sxitimer_tick_nextevt += 1; 290 sxitimer_ticks_err_sum -= hz; 291 } 292 293 rc = 1; 294 hardclock(frame); 295 } 296 nextevent = now - sxitimer_tick_nextevt; 297 if (nextevent < 10 /* XXX */) 298 nextevent = 10; 299 300 if (nextevent > sxitimer_tick_tpi) { 301 /* 302 * If interrupts are blocked too long, like during 303 * the root prompt or ddb, the timer can roll over, 304 * this will allow the system to continue to run 305 * even if time is lost. 306 */ 307 nextevent = sxitimer_tick_tpi; 308 sxitimer_tick_nextevt = now; 309 } 310 311 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 312 TIMER_CTRL(TICKTIMER)); 313 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 314 TIMER_CTRL(TICKTIMER), val & ~TIMER_ENABLE); 315 316 sxitimer_sync(); 317 318 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 319 TIMER_INTV(TICKTIMER), nextevent); 320 321 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 322 TIMER_CTRL(TICKTIMER)); 323 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 324 TIMER_CTRL(TICKTIMER), 325 val | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 326 327 return rc; 328 } 329 330 int 331 sxitimer_statintr(void *frame) 332 { 333 uint32_t now, nextevent, r; 334 uint32_t val; 335 int rc = 0; 336 337 splassert(IPL_STATCLOCK); 338 339 /* clear timer pending interrupt bit */ 340 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 341 TIMER_ISR, TIMER_IRQ(STATTIMER)); 342 343 now = sxitimer_readcnt32(); 344 while ((int32_t)(now - sxitimer_stat_nextevt) < 0) { 345 do { 346 r = random() & (sxitimer_statvar -1); 347 } while (r == 0); /* random == 0 not allowed */ 348 sxitimer_stat_nextevt -= sxitimer_statmin + r; 349 rc = 1; 350 statclock(frame); 351 } 352 353 nextevent = now - sxitimer_stat_nextevt; 354 355 if (nextevent < 10 /* XXX */) 356 nextevent = 10; 357 358 if (nextevent > sxitimer_stat_tpi) { 359 /* 360 * If interrupts are blocked too long, like during 361 * the root prompt or ddb, the timer can roll over, 362 * this will allow the system to continue to run 363 * even if time is lost. 364 */ 365 nextevent = sxitimer_stat_tpi; 366 sxitimer_stat_nextevt = now; 367 } 368 369 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 370 TIMER_CTRL(STATTIMER)); 371 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 372 TIMER_CTRL(STATTIMER), val & ~TIMER_ENABLE); 373 374 sxitimer_sync(); 375 376 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 377 TIMER_INTV(STATTIMER), nextevent); 378 379 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 380 TIMER_CTRL(STATTIMER)); 381 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 382 TIMER_CTRL(STATTIMER), 383 val | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 384 385 return rc; 386 } 387 388 uint64_t 389 sxitimer_readcnt64(void) 390 { 391 uint32_t low, high; 392 393 /* latch counter, loop until ready */ 394 bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL, CNT64_RL_EN); 395 while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL) 396 & CNT64_RL_EN) 397 continue; 398 399 /* 400 * A10 usermanual doesn't mention anything about order, but fwiw 401 * iirc. A20 manual mentions that low should be read first. 402 */ 403 /* XXX check above */ 404 low = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_LOW); 405 high = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_HIGH); 406 return (uint64_t)high << 32 | low; 407 } 408 409 uint32_t 410 sxitimer_readcnt32(void) 411 { 412 return bus_space_read_4(sxitimer_iot, sxitimer_ioh, 413 TIMER_CURR(CNTRTIMER)); 414 } 415 416 void 417 sxitimer_sync(void) 418 { 419 uint32_t now = sxitimer_readcnt32(); 420 421 while ((now - sxitimer_readcnt32()) < TIMER_SYNC) 422 CPU_BUSY_CYCLE(); 423 } 424 425 void 426 sxitimer_delay(u_int usecs) 427 { 428 uint64_t oclock, timeout; 429 430 oclock = sxitimer_readcnt64(); 431 timeout = oclock + (COUNTER_FREQUENCY / 1000000) * usecs; 432 433 while (oclock < timeout) 434 oclock = sxitimer_readcnt64(); 435 } 436 437 void 438 sxitimer_setstatclockrate(int newhz) 439 { 440 int minint, statint, s; 441 442 s = splstatclock(); 443 444 statint = sxitimer_freq[STATTIMER] / newhz; 445 /* calculate largest 2^n which is smaller than just over half statint */ 446 sxitimer_statvar = 0x40000000; /* really big power of two */ 447 minint = statint / 2 + 100; 448 while (sxitimer_statvar > minint) 449 sxitimer_statvar >>= 1; 450 451 sxitimer_statmin = statint - (sxitimer_statvar >> 1); 452 453 splx(s); 454 455 /* 456 * XXX this allows the next stat timer to occur then it switches 457 * to the new frequency. Rather than switching instantly. 458 */ 459 } 460 461 u_int 462 sxitimer_get_timecount(struct timecounter *tc) 463 { 464 return (u_int)UINT_MAX - sxitimer_readcnt32(); 465 } 466