#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" /* * jz4780 timer/counter unit */ #define TER 0x10 #define TESR 0x14 #define TECR 0x18 #define TFR 0x20 #define TFCR 0x28 #define TMCR 0x38 #define TCSR0 0x4C #define TDFR5 0x90 #define TDHR5 0x94 #define TCNT5 0x98 #define TCSR5 0x9C /* operating system timer */ #define OSTDR 0xE0 #define OSTCNTL 0xE4 #define OSTCNTH 0xE8 #define OSTCSR 0xEC #define OSTBUF 0xFC enum { /* hz */ RTCCLK = 32768, }; /* initialize system clocks */ void clockinit(void) { m->maxperiod = 1024; m->minperiod = 2; /* reset counter */ *IO(u32int, TCUBASE+OSTCNTL) = 0; *IO(u32int, TCUBASE+OSTCNTH) = 0; /* no clear on overflow, CLK/16, RTCCLK */ *IO(u16int, TCUBASE+OSTCSR) = (1<<15) | (1<<4) | (1<<1); /* ~500 ms */ *IO(u32int, TCUBASE+OSTDR) = m->maxperiod; /* enable os timer */ *IO(u16int, TCUBASE+TESR) = (1<<15); /* clear os timer mask */ *IO(u32int, TCUBASE+TMCR) = (1<<15); intrenable(IRQTCU0, clock, nil); } void clock(Ureg *ur, void*) { *IO(u32int, TCUBASE+OSTDR) = *IO(u32int, TCUBASE+OSTCNTL) + m->maxperiod; /* clear comparison flag */ *IO(u32int, TCUBASE+TFCR) = (1<<15); timerintr(ur, 0); } void microdelay(int n) { ulong now; now = µs(); while(µs() - now < n); } void delay(int ms) { while(--ms >= 0) microdelay(1000); } ulong µs(void) { return fastticks2us(fastticks(nil)); } uvlong fastticks(uvlong *hz) { int x; ulong delta, count; if(hz) *hz = RTCCLK/16; /* avoid reentry on interrupt or trap, to prevent recursion */ x = splhi(); count = *IO(u32int, TCUBASE+OSTCNTL); if(*IO(u32int, TCUBASE+OSTDR) - count > m->maxperiod) *IO(u32int, TCUBASE+OSTDR) = count + m->maxperiod; if (count < m->lastcount) /* wrapped around? */ delta = count + ((1ull<<32) - m->lastcount); else delta = count - m->lastcount; m->lastcount = count; m->fastticks += delta; splx(x); return m->fastticks; } ulong perfticks(void) { return *IO(ulong, TCUBASE+OSTCNTL); } void timerset(Tval next) { int x; long period; if(next == 0) return; /* don't let us get scheduled */ x = splhi(); period = next - fastticks(nil); if(period > m->maxperiod - m->minperiod) period = m->maxperiod; else if(period < m->minperiod) period = m->minperiod; *IO(u32int, TCUBASE+OSTDR) = period; splx(x); }