plan9fox/sys/src/9/omap4/clock.c
2011-11-05 09:46:34 +01:00

124 lines
1.5 KiB
C

#include "u.h"
#include "ureg.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
extern uchar *periph;
ulong *global, *local;
enum {
PERIPHCLK = 506965000,
MaxPeriod = PERIPHCLK / (256 * 100),
MinPeriod = MaxPeriod / 100,
} ;
void
globalclockinit(void)
{
global = (ulong*) (periph + 0x200);
local = (ulong*) (periph + 0x600);
global[2] &= 0xFFFF00F0;
global[0] = 0;
global[1] = 0;
global[2] |= 1;
}
void
cycles(uvlong *x)
{
ulong hi, newhi, lo, *y;
newhi = global[1];
do{
hi = newhi;
lo = global[0];
}while((newhi = global[1]) != hi);
y = (ulong *) x;
y[0] = lo;
y[1] = hi;
}
uvlong
fastticks(uvlong *hz)
{
uvlong ret;
if(hz != nil)
*hz = PERIPHCLK;
cycles(&ret);
return ret;
}
ulong
µs(void)
{
return fastticks2us(fastticks(nil));
}
ulong
perfticks(void)
{
return global[0];
}
void
clocktick(Ureg* ureg, void *)
{
timerintr(ureg, 0);
}
void
localclockinit(void)
{
local[2] = 0xFF06;
intenable(29, clocktick, nil);
timerset(0);
}
void
timerset(uvlong val)
{
uvlong now, ticks;
if(val == 0)
ticks = MaxPeriod;
else{
cycles(&now);
ticks = (val - now) / 256;
if(ticks < MinPeriod)
ticks = MinPeriod;
if(ticks > MaxPeriod)
ticks = MaxPeriod;
}
local[2] &= ~1;
local[0] = local[1] = ticks;
local[2] |= 1;
}
static void
waituntil(uvlong n)
{
uvlong now, then;
cycles(&now);
then = now + n;
while(now < then)
cycles(&now);
}
void
microdelay(int n)
{
waituntil(((uvlong)n) * PERIPHCLK / 1000000);
}
void
delay(int n)
{
waituntil(((uvlong)n) * PERIPHCLK / 1000);
}