1 /* $OpenBSD: sxitimer.c,v 1.17 2021/03/25 04:12:01 jsg 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/param.h> 21 #include <sys/systm.h> 22 #include <sys/kernel.h> 23 #include <sys/device.h> 24 #include <sys/timetc.h> 25 26 #include <machine/bus.h> 27 #include <machine/fdt.h> 28 #include <machine/intr.h> 29 30 #include <dev/fdt/sunxireg.h> 31 32 #include <dev/ofw/openfirm.h> 33 #include <dev/ofw/fdt.h> 34 35 #define TIMER_IER 0x00 36 #define TIMER_ISR 0x04 37 #define TIMER_IRQ(x) (1 << (x)) 38 39 #define TIMER_CTRL(x) (0x10 + (0x10 * (x))) 40 #define TIMER_INTV(x) (0x14 + (0x10 * (x))) 41 #define TIMER_CURR(x) (0x18 + (0x10 * (x))) 42 43 /* A1X counter */ 44 #define CNT64_CTRL 0xa0 45 #define CNT64_LOW 0xa4 46 #define CNT64_HIGH 0xa8 47 48 #define CNT64_CLR_EN (1 << 0) /* clear enable */ 49 #define CNT64_RL_EN (1 << 1) /* read latch enable */ 50 51 #define TIMER_ENABLE (1 << 0) 52 #define TIMER_RELOAD (1 << 1) 53 #define TIMER_CLK_SRC_MASK (3 << 2) 54 #define TIMER_OSC24M (1 << 2) 55 #define TIMER_PLL6_6 (2 << 2) 56 #define TIMER_PRESC_1 (0 << 4) 57 #define TIMER_PRESC_2 (1 << 4) 58 #define TIMER_PRESC_4 (2 << 4) 59 #define TIMER_PRESC_8 (3 << 4) 60 #define TIMER_PRESC_16 (4 << 4) 61 #define TIMER_PRESC_32 (5 << 4) 62 #define TIMER_PRESC_64 (6 << 4) 63 #define TIMER_PRESC_128 (7 << 4) 64 #define TIMER_CONTINOUS (0 << 7) 65 #define TIMER_SINGLESHOT (1 << 7) 66 67 #define TICKTIMER 0 68 #define STATTIMER 1 69 #define CNTRTIMER 2 70 71 #define TIMER_SYNC 3 72 73 int sxitimer_match(struct device *, void *, void *); 74 void sxitimer_attach(struct device *, struct device *, void *); 75 int sxitimer_tickintr(void *); 76 int sxitimer_statintr(void *); 77 void sxitimer_cpu_initclocks(void); 78 void sxitimer_setstatclockrate(int); 79 uint64_t sxitimer_readcnt64(void); 80 uint32_t sxitimer_readcnt32(void); 81 void sxitimer_sync(void); 82 void sxitimer_delay(u_int); 83 84 u_int sxitimer_get_timecount(struct timecounter *); 85 86 static struct timecounter sxitimer_timecounter = { 87 .tc_get_timecount = sxitimer_get_timecount, 88 .tc_poll_pps = NULL, 89 .tc_counter_mask = 0xffffffff, 90 .tc_frequency = 0, 91 .tc_name = "sxitimer", 92 .tc_quality = 0, 93 .tc_priv = NULL, 94 .tc_user = 0, 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), sxitimer_match, sxitimer_attach 125 }; 126 127 struct cfdriver sxitimer_cd = { 128 NULL, "sxitimer", DV_DULL 129 }; 130 131 int 132 sxitimer_match(struct device *parent, void *match, void *aux) 133 { 134 struct fdt_attach_args *faa = aux; 135 int node; 136 137 node = OF_finddevice("/"); 138 if (!OF_is_compatible(node, "allwinner,sun4i-a10") && 139 !OF_is_compatible(node, "allwinner,sun5i-a10s") && 140 !OF_is_compatible(node, "allwinner,sun5i-a13")) 141 return 0; 142 143 return OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-timer"); 144 } 145 146 void 147 sxitimer_attach(struct device *parent, struct device *self, void *aux) 148 { 149 struct fdt_attach_args *faa = aux; 150 uint32_t freq, ival, now; 151 152 KASSERT(faa->fa_nreg > 0); 153 154 sxitimer_iot = faa->fa_iot; 155 if (bus_space_map(sxitimer_iot, faa->fa_reg[0].addr, 156 faa->fa_reg[0].size, 0, &sxitimer_ioh)) 157 panic("%s: bus_space_map failed!", __func__); 158 159 /* clear counter, loop until ready */ 160 bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL, 161 CNT64_CLR_EN); /* XXX as a side-effect counter clk src=OSC24M */ 162 while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL) 163 & CNT64_CLR_EN) 164 continue; 165 166 /* timers are down-counters, from interval to 0 */ 167 now = 0xffffffff; /* known big value */ 168 freq = sxitimer_freq[TICKTIMER]; 169 170 /* stop timer, and set clk src */ 171 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 172 TIMER_CTRL(TICKTIMER), TIMER_OSC24M); 173 174 ival = sxitimer_tick_tpi = freq / hz; 175 sxitimer_tick_nextevt = now - ival; 176 177 sxitimer_ticks_err_cnt = freq % hz; 178 sxitimer_ticks_err_sum = 0; 179 180 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 181 TIMER_INTV(TICKTIMER), ival); 182 183 /* timers are down-counters, from interval to 0 */ 184 now = 0xffffffff; /* known big value */ 185 freq = sxitimer_freq[STATTIMER]; 186 187 /* stop timer, and set clk src */ 188 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 189 TIMER_CTRL(STATTIMER), TIMER_OSC24M); 190 191 /* 100/1000 or 128/1024 ? */ 192 stathz = 128; 193 profhz = 1024; 194 sxitimer_setstatclockrate(stathz); 195 196 ival = sxitimer_stat_tpi = freq / stathz; 197 sxitimer_stat_nextevt = now - ival; 198 199 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 200 TIMER_INTV(STATTIMER), ival); 201 202 /* timers are down-counters, from interval to 0 */ 203 now = 0xffffffff; /* known big value */ 204 freq = sxitimer_freq[CNTRTIMER]; 205 206 /* stop timer, and set clk src */ 207 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 208 TIMER_CTRL(CNTRTIMER), TIMER_OSC24M); 209 210 ival = now; 211 212 sxitimer_timecounter.tc_frequency = freq; 213 tc_init(&sxitimer_timecounter); 214 arm_clock_register(sxitimer_cpu_initclocks, sxitimer_delay, 215 sxitimer_setstatclockrate, NULL); 216 217 printf(": %d kHz", freq / 1000); 218 219 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 220 TIMER_INTV(CNTRTIMER), ival); 221 222 printf("\n"); 223 } 224 225 /* 226 * would be interesting to play with trigger mode while having one timer 227 * in 32kHz mode, and the other timer running in sysclk mode and use 228 * the high resolution speeds (matters more for delay than tick timer) 229 */ 230 231 void 232 sxitimer_cpu_initclocks(void) 233 { 234 uint32_t isr, ier, ctrl; 235 236 /* establish interrupts */ 237 arm_intr_establish(sxitimer_irq[TICKTIMER], IPL_CLOCK, 238 sxitimer_tickintr, NULL, "tick"); 239 arm_intr_establish(sxitimer_irq[STATTIMER], IPL_STATCLOCK, 240 sxitimer_statintr, NULL, "stattick"); 241 242 /* clear timer interrupt pending bits */ 243 isr = bus_space_read_4(sxitimer_iot, sxitimer_ioh, TIMER_ISR); 244 isr |= TIMER_IRQ(STATTIMER) | TIMER_IRQ(TICKTIMER); 245 bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_ISR, isr); 246 247 /* enable timer IRQs */ 248 ier = bus_space_read_4(sxitimer_iot, sxitimer_ioh, TIMER_IER); 249 ier |= TIMER_IRQ(STATTIMER) | TIMER_IRQ(TICKTIMER); 250 bus_space_write_4(sxitimer_iot, sxitimer_ioh, TIMER_IER, ier); 251 252 /* enable timers */ 253 ctrl = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 254 TIMER_CTRL(CNTRTIMER)); 255 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 256 TIMER_CTRL(CNTRTIMER), 257 ctrl | TIMER_ENABLE | TIMER_RELOAD | TIMER_CONTINOUS); 258 259 ctrl = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 260 TIMER_CTRL(STATTIMER)); 261 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 262 TIMER_CTRL(STATTIMER), 263 ctrl | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 264 265 ctrl = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 266 TIMER_CTRL(TICKTIMER)); 267 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 268 TIMER_CTRL(TICKTIMER), 269 ctrl | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 270 } 271 272 /* 273 * See comment in arm/xscale/i80321_clock.c 274 * 275 * Counter is count up, but with autoreload timers it is not possible 276 * to detect how many interrupts passed while interrupts were blocked. 277 * Also it is not possible to atomically add to the register. 278 * 279 * To work around this two timers are used, one is used as a reference 280 * clock without reload, however we just disable the interrupt it 281 * could generate. 282 * 283 * Internally this keeps track of when the next timer should fire 284 * and based on that time and the current value of the reference 285 * clock a number is written into the timer count register to schedule 286 * the next event. 287 */ 288 /* XXX update above comment */ 289 int 290 sxitimer_tickintr(void *frame) 291 { 292 uint32_t now, nextevent; 293 uint32_t val; 294 int rc = 0; 295 296 splassert(IPL_CLOCK); 297 298 /* clear timer pending interrupt bit */ 299 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 300 TIMER_ISR, TIMER_IRQ(TICKTIMER)); 301 302 now = sxitimer_readcnt32(); 303 304 while ((int32_t)(now - sxitimer_tick_nextevt) < 0) { 305 sxitimer_tick_nextevt -= sxitimer_tick_tpi; 306 sxitimer_ticks_err_sum += sxitimer_ticks_err_cnt; 307 308 while (sxitimer_ticks_err_sum > hz) { 309 sxitimer_tick_nextevt += 1; 310 sxitimer_ticks_err_sum -= hz; 311 } 312 313 rc = 1; 314 hardclock(frame); 315 } 316 nextevent = now - sxitimer_tick_nextevt; 317 if (nextevent < 10 /* XXX */) 318 nextevent = 10; 319 320 if (nextevent > sxitimer_tick_tpi) { 321 /* 322 * If interrupts are blocked too long, like during 323 * the root prompt or ddb, the timer can roll over, 324 * this will allow the system to continue to run 325 * even if time is lost. 326 */ 327 nextevent = sxitimer_tick_tpi; 328 sxitimer_tick_nextevt = now; 329 } 330 331 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 332 TIMER_CTRL(TICKTIMER)); 333 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 334 TIMER_CTRL(TICKTIMER), val & ~TIMER_ENABLE); 335 336 sxitimer_sync(); 337 338 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 339 TIMER_INTV(TICKTIMER), nextevent); 340 341 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 342 TIMER_CTRL(TICKTIMER)); 343 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 344 TIMER_CTRL(TICKTIMER), 345 val | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 346 347 return rc; 348 } 349 350 int 351 sxitimer_statintr(void *frame) 352 { 353 uint32_t now, nextevent, r; 354 uint32_t val; 355 int rc = 0; 356 357 splassert(IPL_STATCLOCK); 358 359 /* clear timer pending interrupt bit */ 360 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 361 TIMER_ISR, TIMER_IRQ(STATTIMER)); 362 363 now = sxitimer_readcnt32(); 364 while ((int32_t)(now - sxitimer_stat_nextevt) < 0) { 365 do { 366 r = random() & (sxitimer_statvar -1); 367 } while (r == 0); /* random == 0 not allowed */ 368 sxitimer_stat_nextevt -= sxitimer_statmin + r; 369 rc = 1; 370 statclock(frame); 371 } 372 373 nextevent = now - sxitimer_stat_nextevt; 374 375 if (nextevent < 10 /* XXX */) 376 nextevent = 10; 377 378 if (nextevent > sxitimer_stat_tpi) { 379 /* 380 * If interrupts are blocked too long, like during 381 * the root prompt or ddb, the timer can roll over, 382 * this will allow the system to continue to run 383 * even if time is lost. 384 */ 385 nextevent = sxitimer_stat_tpi; 386 sxitimer_stat_nextevt = now; 387 } 388 389 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 390 TIMER_CTRL(STATTIMER)); 391 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 392 TIMER_CTRL(STATTIMER), val & ~TIMER_ENABLE); 393 394 sxitimer_sync(); 395 396 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 397 TIMER_INTV(STATTIMER), nextevent); 398 399 val = bus_space_read_4(sxitimer_iot, sxitimer_ioh, 400 TIMER_CTRL(STATTIMER)); 401 bus_space_write_4(sxitimer_iot, sxitimer_ioh, 402 TIMER_CTRL(STATTIMER), 403 val | TIMER_ENABLE | TIMER_RELOAD | TIMER_SINGLESHOT); 404 405 return rc; 406 } 407 408 uint64_t 409 sxitimer_readcnt64(void) 410 { 411 uint32_t low, high; 412 413 /* latch counter, loop until ready */ 414 bus_space_write_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL, CNT64_RL_EN); 415 while (bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_CTRL) 416 & CNT64_RL_EN) 417 continue; 418 419 /* 420 * A10 usermanual doesn't mention anything about order, but fwiw 421 * iirc. A20 manual mentions that low should be read first. 422 */ 423 /* XXX check above */ 424 low = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_LOW); 425 high = bus_space_read_4(sxitimer_iot, sxitimer_ioh, CNT64_HIGH); 426 return (uint64_t)high << 32 | low; 427 } 428 429 uint32_t 430 sxitimer_readcnt32(void) 431 { 432 return bus_space_read_4(sxitimer_iot, sxitimer_ioh, 433 TIMER_CURR(CNTRTIMER)); 434 } 435 436 void 437 sxitimer_sync(void) 438 { 439 uint32_t now = sxitimer_readcnt32(); 440 441 while ((now - sxitimer_readcnt32()) < TIMER_SYNC) 442 CPU_BUSY_CYCLE(); 443 } 444 445 void 446 sxitimer_delay(u_int usecs) 447 { 448 uint64_t oclock, timeout; 449 450 oclock = sxitimer_readcnt64(); 451 timeout = oclock + (COUNTER_FREQUENCY / 1000000) * usecs; 452 453 while (oclock < timeout) 454 oclock = sxitimer_readcnt64(); 455 } 456 457 void 458 sxitimer_setstatclockrate(int newhz) 459 { 460 int minint, statint, s; 461 462 s = splstatclock(); 463 464 statint = sxitimer_freq[STATTIMER] / newhz; 465 /* calculate largest 2^n which is smaller than just over half statint */ 466 sxitimer_statvar = 0x40000000; /* really big power of two */ 467 minint = statint / 2 + 100; 468 while (sxitimer_statvar > minint) 469 sxitimer_statvar >>= 1; 470 471 sxitimer_statmin = statint - (sxitimer_statvar >> 1); 472 473 splx(s); 474 475 /* 476 * XXX this allows the next stat timer to occur then it switches 477 * to the new frequency. Rather than switching instantly. 478 */ 479 } 480 481 u_int 482 sxitimer_get_timecount(struct timecounter *tc) 483 { 484 return (u_int)UINT_MAX - sxitimer_readcnt32(); 485 } 486