ref: a7b1ab8236b7ccd41e96e9e4008cbc3213294724
dir: /timer.c/
#include <u.h>
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
enum
{
TIOCP_CFG = 0x10/4,
SOFTRESET = 1<<0,
IRQSTATUS_RAW = 0x24/4,
IRQSTATUS = 0x28/4,
MAT_IT_FLAG = 1<<0,
OVF_IT_FLAG = 1<<1,
TCAR_IT_FLAG = 1<<2,
IRQENABLE_SET = 0x2c/4,
IRQENABLE_CLR = 0x30/4,
MAT_EN_FLAG = 1<<0,
OVF_EN_FLAG = 1<<1,
TCAR_EN_FLAG = 1<<2,
TCLR = 0x38/4,
ST = 1<<0,
AR = 1<<1,
PTV_SHIFT = 2,
PTV_MASK = 0x07<<PTV_SHIFT,
PRE = 1<<5,
CE = 1<<6,
TCRR = 0x3c/4,
TLDR = 0x40/4,
TWPS = 0x48/4,
W_PEND_TCLR = 1<<0,
W_PEND_TCRR = 1<<1,
W_PEND_TLDR = 1<<2,
W_PEND_TMAR = 1<<4,
TMAR = 0x4c/4,
};
enum
{
CM_PER = 0,
CM_PER_L4LS_CLKSTCTRL = 0,
CLKACTIVITY_TIMER2_GCLK = 1<<14,
CLKACTIVITY_TIMER3_GCLK = 1<<15,
CM_PER_TIMER2_CLKCTRL = 0x80/4,
CM_PER_TIMER3_CLKCTRL = 0x84/4,
CM_DPLL = 0x500/4,
CLKSEL_TIMER2_CLK = 0x8/4,
CLKSEL_TIMER3_CLK = 0xc/4,
CLK_M_OSC = 0x1,
};
uvlong timerhz;
ulong
µs(void)
{
return fastticks2us(fastticks(nil));
}
void
microdelay(int n)
{
ulong now;
now = µs();
while(µs() - now < n);
}
void
delay(int n)
{
while(--n >= 0)
microdelay(1000);
}
ulong currhi;
uvlong
fastticks(uvlong *hz)
{
int x;
uvlong r;
if(hz)
*hz = timerhz;
x = splhi();
r = (uvlong)currhi<<32 | timer3[TCRR];
splx(x);
return r;
}
void
timerset(Tval next)
{
int x;
vlong period;
uvlong ft;
if(next == 0)
return;
x = splhi();
ft = fastticks(nil);
period = next - ft;
if(period > 0xffffffffLL)
period = 0xffffffffLL;
else if(period < 1)
period = 1;
timer2[TCRR] = -period;
timer2[TCLR] |= ST;
splx(x);
}
void
timer2irq(Ureg *u, void*)
{
timer2[IRQSTATUS] = OVF_IT_FLAG;
while((timer2[IRQSTATUS] & OVF_IT_FLAG) != 0);
timerintr(u, 0);
}
void
timer3irq(Ureg*, void*)
{
currhi++;
timer3[IRQSTATUS] = OVF_IT_FLAG;
while((timer3[IRQSTATUS] & OVF_IT_FLAG) != 0);
}
void
timerinit(void)
{
ulong *dpll, *per;
m->cpumhz = 1000;
m->cpuhz = m->cpumhz * 1000000;
timerhz = 24000000;
dpll = &cprm[CM_DPLL];
dpll[CLKSEL_TIMER2_CLK] |= CLK_M_OSC;
dpll[CLKSEL_TIMER3_CLK] |= CLK_M_OSC;
per = &cprm[CM_PER];
per[CM_PER_TIMER2_CLKCTRL] |= 2;
per[CM_PER_TIMER3_CLKCTRL] |= 2;
per[CM_PER_L4LS_CLKSTCTRL] |= CLKACTIVITY_TIMER2_GCLK | CLKACTIVITY_TIMER3_GCLK;
timer2[TIOCP_CFG] = SOFTRESET;
while((timer2[TIOCP_CFG] & SOFTRESET) != 0);
timer2[IRQENABLE_SET] = OVF_EN_FLAG;
timer3[TIOCP_CFG] = SOFTRESET;
while((timer3[TIOCP_CFG] & SOFTRESET) != 0);
timer3[IRQENABLE_SET] = OVF_EN_FLAG;
timer3[TCLR] |= AR | ST;
intrenable(TIMER2IRQ, timer2irq, nil, "clock");
intrenable(TIMER3IRQ, timer3irq, nil, "clock");
}