2022-05-08 16:50:29 +00:00
|
|
|
#include "u.h"
|
|
|
|
#include "../port/lib.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
#include "io.h"
|
|
|
|
#include "ureg.h"
|
|
|
|
#include "sysreg.h"
|
|
|
|
|
|
|
|
static uvlong freq;
|
|
|
|
|
|
|
|
enum {
|
|
|
|
Enable = 1<<0,
|
|
|
|
Imask = 1<<1,
|
|
|
|
Istatus = 1<<2,
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
clockshutdown(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
localclockintr(Ureg *ureg, void *)
|
|
|
|
{
|
|
|
|
timerintr(ureg, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
clockinit(void)
|
|
|
|
{
|
2022-07-09 16:06:42 +00:00
|
|
|
uvlong tstart, tend;
|
|
|
|
ulong t0, t1;
|
|
|
|
|
2022-05-08 16:50:29 +00:00
|
|
|
syswr(PMCR_EL0, 1<<6 | 7);
|
|
|
|
syswr(PMCNTENSET, 1<<31);
|
|
|
|
syswr(PMUSERENR_EL0, 1<<2);
|
|
|
|
syswr(CNTKCTL_EL1, 1<<1);
|
|
|
|
|
|
|
|
syswr(CNTP_TVAL_EL0, ~0UL);
|
|
|
|
syswr(CNTP_CTL_EL0, Enable);
|
|
|
|
|
|
|
|
if(m->machno == 0){
|
|
|
|
freq = sysrd(CNTFRQ_EL0);
|
|
|
|
print("timer frequency %lld Hz\n", freq);
|
2022-07-09 21:12:20 +00:00
|
|
|
|
|
|
|
/* TURBO! */
|
|
|
|
setclkrate("ccm_arm_a53_clk_root", "osc_25m_ref_clk", 25*Mhz);
|
|
|
|
setclkrate("ccm_arm_a53_clk_root", "arm_pll_clk", 1400*Mhz);
|
2022-05-08 16:50:29 +00:00
|
|
|
}
|
2022-07-09 16:06:42 +00:00
|
|
|
tstart = sysrd(CNTPCT_EL0);
|
|
|
|
do{
|
|
|
|
t0 = lcycles();
|
|
|
|
}while(sysrd(CNTPCT_EL0) == tstart);
|
|
|
|
tend = tstart + (freq/100);
|
|
|
|
do{
|
|
|
|
t1 = lcycles();
|
|
|
|
}while(sysrd(CNTPCT_EL0) < tend);
|
|
|
|
t1 -= t0;
|
|
|
|
m->cpuhz = 100 * t1;
|
|
|
|
m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we are using virtual counter register CNTVCT_EL0
|
|
|
|
* instead of the performance counter in userspace.
|
|
|
|
*/
|
2022-07-09 15:15:55 +00:00
|
|
|
m->cyclefreq = freq;
|
2022-05-08 16:50:29 +00:00
|
|
|
|
|
|
|
intrenable(IRQcntpns, localclockintr, nil, BUSUNKNOWN, "clock");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
timerset(uvlong next)
|
|
|
|
{
|
|
|
|
uvlong now;
|
|
|
|
long period;
|
|
|
|
|
|
|
|
now = fastticks(nil);
|
|
|
|
period = next - now;
|
|
|
|
syswr(CNTP_TVAL_EL0, period);
|
|
|
|
}
|
|
|
|
|
|
|
|
uvlong
|
|
|
|
fastticks(uvlong *hz)
|
|
|
|
{
|
|
|
|
if(hz)
|
|
|
|
*hz = freq;
|
|
|
|
return sysrd(CNTPCT_EL0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ulong
|
|
|
|
perfticks(void)
|
|
|
|
{
|
|
|
|
return fastticks(nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
ulong
|
|
|
|
µs(void)
|
|
|
|
{
|
|
|
|
uvlong hz;
|
|
|
|
uvlong t = fastticks(&hz);
|
|
|
|
return (t * 1000000ULL) / hz;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
microdelay(int n)
|
|
|
|
{
|
|
|
|
ulong now;
|
|
|
|
|
|
|
|
now = µs();
|
|
|
|
while(µs() - now < n);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
delay(int n)
|
|
|
|
{
|
|
|
|
while(--n >= 0)
|
|
|
|
microdelay(1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
synccycles(void)
|
|
|
|
{
|
|
|
|
static Ref r1, r2;
|
|
|
|
int s;
|
|
|
|
|
|
|
|
s = splhi();
|
|
|
|
r2.ref = 0;
|
|
|
|
incref(&r1);
|
|
|
|
while(r1.ref != conf.nmach)
|
|
|
|
;
|
|
|
|
// syswr(PMCR_EL0, 1<<6 | 7);
|
|
|
|
incref(&r2);
|
|
|
|
while(r2.ref != conf.nmach)
|
|
|
|
;
|
|
|
|
r1.ref = 0;
|
|
|
|
splx(s);
|
|
|
|
}
|