123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /*
- * kirkwood clocks
- *
- * timers count down to zero.
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "ureg.h"
- enum {
- Tcycles = CLOCKFREQ / HZ, /* cycles per clock tick */
- Dogperiod = 15 * CLOCKFREQ, /* at most 21 s.; must fit in ulong */
- MaxPeriod = Tcycles,
- MinPeriod = MaxPeriod / 100,
- /* timer ctl bits */
- Tmr0enable = 1<<0,
- Tmr0reload = 1<<1, /* at 0 count, load timer0 from reload0 */
- Tmr1enable = 1<<2,
- Tmr1reload = 1<<3, /* at 0 count, load timer1 from reload1 */
- TmrWDenable = 1<<4,
- TmrWDreload = 1<<5,
- };
- typedef struct TimerReg TimerReg;
- struct TimerReg
- {
- ulong ctl;
- ulong pad[3];
- ulong reload0;
- ulong timer0; /* cycles until zero */
- ulong reload1;
- ulong timer1; /* cycles until zero */
- ulong reloadwd;
- ulong timerwd;
- };
- static int ticks; /* for sanity checking; m->ticks doesn't always get updated */
- static void
- clockintr(Ureg *ureg, void *arg)
- {
- TimerReg *tmr = arg;
- static int nesting;
- tmr->timerwd = Dogperiod; /* reassure the watchdog */
- ticks++;
- coherence();
- if (nesting == 0) { /* if the clock interrupted itself, bail out */
- ++nesting;
- timerintr(ureg, 0);
- --nesting;
- }
- intrclear(Irqbridge, IRQcputimer0);
- }
- /* stop clock interrupts and disable the watchdog timer */
- void
- clockshutdown(void)
- {
- TimerReg *tmr = (TimerReg *)soc.clock;
- tmr->ctl = 0;
- coherence();
- }
- void
- clockinit(void)
- {
- int i, s;
- CpucsReg *cpu = (CpucsReg *)soc.cpu;
- TimerReg *tmr = (TimerReg *)soc.clock;
- clockshutdown();
- /*
- * verify sanity of timer0
- */
- intrenable(Irqbridge, IRQcputimer0, clockintr, tmr, "clock0");
- s = spllo(); /* risky */
- /* take any deferred clock (& other) interrupts here */
- splx(s);
- /* adjust m->bootdelay, used by delay()? */
- m->ticks = ticks = 0;
- m->fastclock = 0;
- tmr->timer0 = 1;
- tmr->ctl = Tmr0enable; /* just once */
- coherence();
- s = spllo(); /* risky */
- for (i = 0; i < 10 && ticks == 0; i++) {
- delay(1);
- coherence();
- }
- splx(s);
- if (ticks == 0) {
- serialputc('?');
- if (tmr->timer0 == 0)
- panic("clock not interrupting");
- else if (tmr->timer0 == tmr->reload0)
- panic("clock not ticking");
- else
- panic("clock running very slowly");
- }
- /*
- * configure all timers
- */
- clockshutdown();
- tmr->reload0 = tmr->timer0 = Tcycles; /* tick clock */
- tmr->reload1 = tmr->timer1 = ~0; /* cycle clock */
- tmr->timerwd = Dogperiod; /* watch dog timer */
- coherence();
- tmr->ctl = Tmr0enable | Tmr0reload | Tmr1enable | Tmr1reload |
- TmrWDenable;
- cpu->rstout |= RstoutWatchdog;
- coherence();
- }
- void
- timerset(Tval next)
- {
- int offset;
- TimerReg *tmr = (TimerReg *)soc.clock;
- offset = next - fastticks(nil);
- if(offset < MinPeriod)
- offset = MinPeriod;
- else if(offset > MaxPeriod)
- offset = MaxPeriod;
- tmr->timer0 = offset;
- coherence();
- }
- uvlong
- fastticks(uvlong *hz)
- {
- uvlong now;
- int s;
- if(hz)
- *hz = CLOCKFREQ;
- s = splhi();
- /* zero low ulong of fastclock */
- now = (m->fastclock & ~(uvlong)~0ul) | perfticks();
- if(now < m->fastclock) /* low bits must have wrapped */
- now += 1ll << 32;
- m->fastclock = now;
- splx(s);
- return now;
- }
- ulong
- perfticks(void)
- {
- TimerReg *tmr = (TimerReg *)soc.clock;
- return ~tmr->timer1;
- }
- long
- lcycles(void)
- {
- return perfticks();
- }
- ulong
- µs(void)
- {
- return fastticks2us(fastticks(nil));
- }
- void
- microdelay(int l)
- {
- int i;
- l *= m->delayloop;
- l /= 1000;
- if(l <= 0)
- l = 1;
- for(i = 0; i < l; i++)
- ;
- }
- void
- delay(int l)
- {
- ulong i, j;
- j = m->delayloop;
- while(l-- > 0)
- for(i=0; i < j; i++)
- ;
- }
|