1 /* $NetBSD: ifpga_clock.c,v 1.15 2013/02/19 10:57:10 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 2001 ARM Ltd 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the company may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * The IFPGA has three timers. Timer 0 is clocked by the system bus clock, 34 * while timers 1 and 2 are clocked at 24MHz (1Mhz for Integrator CP). To 35 * keep things simple here, we use timers 1 and 2 only. All three timers 36 * are 16-bit counters that are programmable in either periodic mode or in 37 * one-shot mode. 38 */ 39 40 /* Include header files */ 41 42 #include <sys/cdefs.h> 43 __KERNEL_RCSID(0, "$NetBSD: ifpga_clock.c,v 1.15 2013/02/19 10:57:10 skrll Exp $"); 44 45 #include <sys/types.h> 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/atomic.h> 50 #include <sys/time.h> 51 #include <sys/timetc.h> 52 #include <sys/device.h> 53 54 #include <arm/cpufunc.h> 55 #include <machine/intr.h> 56 57 #include <evbarm/ifpga/ifpgavar.h> 58 #include <evbarm/ifpga/ifpgamem.h> 59 #include <evbarm/ifpga/ifpgareg.h> 60 61 /* 62 * Statistics clock interval and variance, in usec. Variance must be a 63 * power of two. Since this gives us an even number, not an odd number, 64 * we discard one case and compensate. That is, a variance of 1024 would 65 * give us offsets in [0..1023]. Instead, we take offsets in [1..1023]. 66 * This is symmetric about the point 512, or statvar/2, and thus averages 67 * to that value (assuming uniform random numbers). 68 */ 69 static int statvar = 1024 / 4; /* {stat,prof}clock variance */ 70 static int statmin; /* statclock interval - variance/2 */ 71 static int profmin; /* profclock interval - variance/2 */ 72 static int timer2min; /* current, from above choices */ 73 static int statprev; /* previous value in stat timer */ 74 75 #define TIMER_1_CLEAR (IFPGA_TIMER1_BASE + TIMERx_CLR) 76 #define TIMER_1_LOAD (IFPGA_TIMER1_BASE + TIMERx_LOAD) 77 #define TIMER_1_VALUE (IFPGA_TIMER1_BASE + TIMERx_VALUE) 78 #define TIMER_1_CTRL (IFPGA_TIMER1_BASE + TIMERx_CTRL) 79 80 #define TIMER_2_CLEAR (IFPGA_TIMER2_BASE + TIMERx_CLR) 81 #define TIMER_2_LOAD (IFPGA_TIMER2_BASE + TIMERx_LOAD) 82 #define TIMER_2_VALUE (IFPGA_TIMER2_BASE + TIMERx_VALUE) 83 #define TIMER_2_CTRL (IFPGA_TIMER2_BASE + TIMERx_CTRL) 84 85 #define COUNTS_PER_SEC (IFPGA_TIMER1_FREQ / 16) 86 87 static u_int ifpga_get_timecount(struct timecounter *); 88 89 static struct timecounter ifpga_timecounter = { 90 ifpga_get_timecount, /* get_timecount */ 91 0, /* no poll_pps */ 92 0xffffffff, /* counter_mask */ 93 COUNTS_PER_SEC, /* frequency */ 94 "ifpga", /* name */ 95 100, /* quality */ 96 NULL, /* prev */ 97 NULL, /* next */ 98 }; 99 100 static volatile uint32_t ifpga_base; 101 102 extern struct ifpga_softc *ifpga_sc; 103 extern device_t ifpga_dev; 104 105 static int clock_started = 0; 106 107 static int load_timer(int, int); 108 109 static inline u_int 110 getclock(void) 111 { 112 return bus_space_read_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh, 113 TIMER_1_VALUE); 114 } 115 116 static inline u_int 117 getstatclock(void) 118 { 119 return bus_space_read_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh, 120 TIMER_2_VALUE); 121 } 122 123 /* 124 * int clockhandler(struct clockframe *frame) 125 * 126 * Function called by timer 1 interrupts. 127 * This just clears the interrupt condition and calls hardclock(). 128 */ 129 130 static int 131 clockhandler(void *fr) 132 { 133 struct clockframe *frame = (struct clockframe *)fr; 134 135 bus_space_write_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh, 136 TIMER_1_CLEAR, 0); 137 138 atomic_add_32(&ifpga_base, ifpga_sc->sc_clock_count); 139 140 hardclock(frame); 141 return 0; /* Pass the interrupt on down the chain */ 142 } 143 144 145 /* 146 * int statclockhandler(struct clockframe *frame) 147 * 148 * Function called by timer 2 interrupts. 149 * Add some random jitter to the clock, and then call statclock(). 150 */ 151 152 static int 153 statclockhandler(void *fr) 154 { 155 struct clockframe *frame = (struct clockframe *) fr; 156 int newint, r, var; 157 158 var = statvar; 159 do { 160 r = random() & (var - 1); 161 } while (r == 0); 162 newint = timer2min + r; 163 164 if (newint & ~0x0000ffff) 165 panic("statclockhandler: statclock variance too large"); 166 167 /* 168 * The timer was automatically reloaded with the previous latch 169 * value at the time of the interrupts. Compensate now for the 170 * amount of time that has run off since then, plus one tick 171 * roundoff. This should keep us closer to the mean. 172 */ 173 174 r = (statprev - getstatclock() + 1); 175 if (r < newint) { 176 newint -= r; 177 r = 0; 178 } 179 else 180 printf("statclockhandler: Statclock overrun\n"); 181 182 statprev = load_timer(IFPGA_TIMER2_BASE, newint); 183 statclock(frame); 184 if (r) 185 /* 186 * We've completely overrun the previous interval, 187 * make sure we report the correct number of ticks. 188 */ 189 statclock(frame); 190 191 return 0; /* Pass the interrupt on down the chain */ 192 } 193 194 static int 195 load_timer(int base, int intvl) 196 { 197 int control; 198 199 if (intvl & ~0x0000ffff) 200 panic("clock: Invalid interval"); 201 202 #if defined(INTEGRATOR_CP) 203 control = (TIMERx_CTRL_ENABLE | TIMERx_CTRL_MODE_PERIODIC | 204 TIMERx_CTRL_PRESCALE_DIV16 | TIMERx_CTRL_RAISE_IRQ); 205 #else 206 control = (TIMERx_CTRL_ENABLE | TIMERx_CTRL_MODE_PERIODIC | 207 TIMERx_CTRL_PRESCALE_DIV16); 208 #endif 209 210 bus_space_write_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh, 211 base + TIMERx_LOAD, intvl); 212 bus_space_write_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh, 213 base + TIMERx_CTRL, control); 214 bus_space_write_4(ifpga_sc->sc_iot, ifpga_sc->sc_tmr_ioh, 215 base + TIMERx_CLR, 0); 216 return intvl; 217 } 218 219 /* 220 * void setstatclockrate(int hz) 221 * 222 * We assume that hz is either stathz or profhz, and that neither will 223 * change after being set by cpu_initclocks(). We could recalculate the 224 * intervals here, but that would be a pain. 225 */ 226 227 void 228 setstatclockrate(int new_hz) 229 { 230 if (new_hz == stathz) 231 timer2min = statmin; 232 else 233 timer2min = profmin; 234 } 235 236 /* 237 * void cpu_initclocks(void) 238 * 239 * Initialise the clocks. 240 */ 241 242 void 243 cpu_initclocks(void) 244 { 245 int intvl; 246 int statint; 247 int profint; 248 int minint; 249 250 if (hz < 50 || COUNTS_PER_SEC % hz) { 251 printf("cannot get %d Hz clock; using 100 Hz\n", hz); 252 hz = 100; 253 tick = 1000000 / hz; 254 } 255 256 if (stathz == 0) 257 stathz = hz; 258 else if (stathz < 50 || COUNTS_PER_SEC % stathz) { 259 printf("cannot get %d Hz statclock; using 100 Hz\n", stathz); 260 stathz = 100; 261 } 262 263 if (profhz == 0) 264 profhz = stathz * 5; 265 else if (profhz < stathz || COUNTS_PER_SEC % profhz) { 266 printf("cannot get %d Hz profclock; using %d Hz\n", profhz, 267 stathz); 268 profhz = stathz; 269 } 270 271 intvl = COUNTS_PER_SEC / hz; 272 statint = COUNTS_PER_SEC / stathz; 273 profint = COUNTS_PER_SEC / profhz; 274 minint = statint / 2 + 100; 275 while (statvar > minint) 276 statvar >>= 1; 277 278 /* Adjust interval counts, per note above. */ 279 intvl--; 280 statint--; 281 profint--; 282 283 /* Calculate the base reload values. */ 284 statmin = statint - (statvar >> 1); 285 profmin = profint - (statvar >> 1); 286 timer2min = statmin; 287 statprev = statint; 288 289 /* Report the clock frequencies */ 290 printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz); 291 292 /* Setup timer 1 and claim interrupt */ 293 ifpga_sc->sc_clockintr = ifpga_intr_establish(IFPGA_TIMER1_IRQ, 294 IPL_CLOCK, clockhandler, 0); 295 if (ifpga_sc->sc_clockintr == NULL) 296 panic("%s: Cannot install timer 1 interrupt handler", 297 device_xname(ifpga_dev)); 298 299 ifpga_sc->sc_clock_count 300 = load_timer(IFPGA_TIMER1_BASE, intvl); 301 302 /* 303 * Use ticks per 256us for accuracy since ticks per us is often 304 * fractional e.g. @ 66MHz 305 */ 306 ifpga_sc->sc_clock_ticks_per_256us = 307 ((((ifpga_sc->sc_clock_count * hz) / 1000) * 256) / 1000); 308 309 clock_started = 1; 310 311 /* Set up timer 2 as statclk/profclk. */ 312 ifpga_sc->sc_statclockintr = ifpga_intr_establish(IFPGA_TIMER2_IRQ, 313 IPL_HIGH, statclockhandler, 0); 314 if (ifpga_sc->sc_statclockintr == NULL) 315 panic("%s: Cannot install timer 2 interrupt handler", 316 device_xname(ifpga_dev)); 317 load_timer(IFPGA_TIMER2_BASE, statint); 318 319 tc_init(&ifpga_timecounter); 320 } 321 322 static u_int 323 ifpga_get_timecount(struct timecounter *tc) 324 { 325 u_int base, counter; 326 327 do { 328 base = ifpga_base; 329 counter = getclock(); 330 } while (base != ifpga_base); 331 332 return base - counter; 333 } 334 335 /* 336 * Estimated loop for n microseconds 337 */ 338 339 /* Need to re-write this to use the timers */ 340 341 /* One day soon I will actually do this */ 342 343 int delaycount = 50; 344 345 void 346 delay(u_int n) 347 { 348 if (clock_started) { 349 u_int starttime; 350 u_int curtime; 351 u_int delta = 0; 352 u_int count_max = ifpga_sc->sc_clock_count; 353 354 starttime = getclock(); 355 356 n *= IFPGA_TIMER1_FREQ / 1000000; 357 358 do { 359 n -= delta; 360 curtime = getclock(); 361 delta = curtime - starttime; 362 if (curtime < starttime) 363 delta += count_max; 364 starttime = curtime; 365 } while (n > delta); 366 } else { 367 volatile u_int i; 368 369 if (n == 0) return; 370 while (n-- > 0) { 371 /* XXX - Seriously gross hack */ 372 if (cputype == CPU_ID_SA110) 373 for (i = delaycount; --i;) 374 ; 375 else 376 for (i = 8; --i;) 377 ; 378 } 379 } 380 } 381