3 * System timers run at 1MHz (timers 1 and 2 are used by GPU)
4 * ARM timer usually runs at 250MHz (may be slower in low power modes)
5 * Cycle counter runs at 700MHz (unless overclocked)
6 * All are free-running up-counters
8 * Use system timer 3 (64 bits) for hzclock interrupts and fastticks
9 * Use ARM timer (32 bits) for perfticks
10 * Use ARM timer to force immediate interrupt
11 * Use cycle counter for cycles()
15 #include "../port/lib.h"
22 SYSTIMERS = VIRTIO+0x3000,
23 ARMTIMER = VIRTIO+0xB400,
26 MaxPeriod = SystimerFreq / HZ,
27 MinPeriod = SystimerFreq / (100*HZ),
30 typedef struct Systimers Systimers;
31 typedef struct Armtimer Armtimer;
56 CntPrescaleShift= 16, /* freq is sys_clk/(prescale+1) */
57 CntPrescaleMask = 0xFF,
62 TmrPrescale1 = 0x00<<2,
63 TmrPrescale16 = 0x01<<2,
64 TmrPrescale256 = 0x02<<2,
70 clockintr(Ureg *ureg, void *)
74 tn = (Systimers*)SYSTIMERS;
75 /* dismiss interrupt */
85 tm = (Armtimer*)ARMTIMER;
94 u32int t0, t1, tstart, tend;
96 tn = (Systimers*)SYSTIMERS;
97 tm = (Armtimer*)ARMTIMER;
99 tm->ctl = TmrPrescale1|CntEnable|CntWidth32;
105 }while(tn->clo == tstart);
106 tend = tstart + 10000;
109 }while(tn->clo != tend);
112 m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz;
113 m->cyclefreq = m->cpuhz;
115 tn->c3 = tn->clo - 1;
116 intrenable(IRQtimer3, clockintr, nil, 0, "clock");
120 timerset(uvlong next)
125 tn = (Systimers*)SYSTIMERS;
126 now = fastticks(nil);
127 period = next - fastticks(nil);
128 if(period < MinPeriod)
129 next = now + MinPeriod;
130 else if(period > MaxPeriod)
131 next = now + MaxPeriod;
132 tn->c3 = (ulong)next;
136 fastticks(uvlong *hz)
141 tn = (Systimers*)SYSTIMERS;
147 }while(tn->chi != hi);
148 m->fastclock = (uvlong)hi<<32 | lo;
157 tm = (Armtimer*)ARMTIMER;
166 tm = (Armtimer*)ARMTIMER;
168 tm->ctl |= TmrEnable|TmrIntEnable;
172 tm->ctl &= ~(TmrEnable|TmrIntEnable);
181 if(SystimerFreq != 1*Mhz)
182 return fastticks2us(fastticks(nil));
183 return fastticks(nil);
192 tn = (Systimers*)SYSTIMERS;
195 while(tn->clo - now < diff)