plan9fox/sys/src/9/imx8/clock.c

139 lines
1.9 KiB
C

#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)
{
uvlong tstart, tend;
ulong t0, t1;
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);
/* TURBO! */
setclkrate("ccm_arm_a53_clk_root", "osc_25m_ref_clk", 25*Mhz);
setclkrate("ccm_arm_a53_clk_root", "arm_pll_clk", 1400*Mhz);
}
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.
*/
m->cyclefreq = freq;
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);
}