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 * For smp on bcm2836, use local generic timer for interrupts on cpu1-3
10 * Use ARM timer (32 bits) for perfticks
11 * Use ARM timer to force immediate interrupt
12 * Use cycle counter for cycles()
16 #include "../port/lib.h"
25 SYSTIMERS = VIRTIO+0x3000,
26 ARMTIMER = VIRTIO+0xB400,
33 MaxPeriod = SystimerFreq / HZ,
37 typedef struct Systimers Systimers;
38 typedef struct Armtimer Armtimer;
63 CntPrescaleShift= 16, /* freq is sys_clk/(prescale+1) */
64 CntPrescaleMask = 0xFF,
69 TmrPrescale1 = 0x00<<2,
70 TmrPrescale16 = 0x01<<2,
71 TmrPrescale256 = 0x02<<2,
75 /* generic timer (cortex-a7) */
82 clockintr(Ureg *ureg, void *)
87 panic("cpu%d: unexpected system timer interrupt", m->machno);
88 tn = (Systimers*)SYSTIMERS;
89 /* dismiss interrupt */
95 localclockintr(Ureg *ureg, void *)
98 panic("cpu0: Unexpected local generic timer interrupt");
107 tm = (Armtimer*)ARMTIMER;
116 ulong t0, t1, tstart, tend;
118 syswr(PMCR_EL0, 1<<6 | 7);
119 syswr(PMCNTENSET, 1<<31);
120 syswr(PMUSERENR_EL0, 1<<2);
122 syswr(CNTP_TVAL_EL0, ~0UL);
124 syswr(CNTP_CTL_EL0, Imask);
126 *(u32int*)(ARMLOCAL + GPUirqroute) = 0;
128 /* input clock is 19.2Mhz crystal */
129 *(u32int*)(ARMLOCAL + Localctl) = 0;
130 /* divide by (2^31/Prescaler) */
131 *(u32int*)(ARMLOCAL + Prescaler) = (((uvlong)SystimerFreq<<31)/19200000)&~1UL;
133 syswr(CNTP_CTL_EL0, Enable);
134 intrenable(IRQcntpns, localclockintr, nil, 0, "clock");
137 tn = (Systimers*)SYSTIMERS;
141 }while(tn->clo == tstart);
142 tend = tstart + (SystimerFreq/100);
145 }while(tn->clo < tend);
148 m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz;
149 m->cyclefreq = m->cpuhz;
153 tn->c3 = tn->clo - 1;
154 intrenable(IRQtimer3, clockintr, nil, 0, "clock");
156 tm = (Armtimer*)ARMTIMER;
158 tm->ctl = TmrPrescale1|CntEnable|CntWidth32;
163 timerset(uvlong next)
169 now = fastticks(nil);
171 if(period < MinPeriod)
173 else if(period > MaxPeriod)
176 syswr(CNTP_TVAL_EL0, period);
178 tn = (Systimers*)SYSTIMERS;
179 tn->c3 = tn->clo + period;
184 fastticks(uvlong *hz)
192 tn = (Systimers*)SYSTIMERS;
196 }while(tn->chi != hi);
197 now = (uvlong)hi<<32 | lo;
206 tm = (Armtimer*)ARMTIMER;
215 tm = (Armtimer*)ARMTIMER;
217 tm->ctl |= TmrEnable|TmrIntEnable;
221 tm->ctl &= ~(TmrEnable|TmrIntEnable);
229 if(SystimerFreq != 1*Mhz)
230 return fastticks2us(fastticks(nil));
231 return ((Systimers*)SYSTIMERS)->clo;
240 while(µs() - now < n);
259 while(r1.ref != conf.nmach)
261 // syswr(PMCR_EL0, 1<<6 | 7);
263 while(r2.ref != conf.nmach)