xref: /inferno-os/os/mpc/clock.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include	"u.h"
2*74a4d8c2SCharles.Forsyth #include	"../port/lib.h"
3*74a4d8c2SCharles.Forsyth #include	"mem.h"
4*74a4d8c2SCharles.Forsyth #include	"dat.h"
5*74a4d8c2SCharles.Forsyth #include	"fns.h"
6*74a4d8c2SCharles.Forsyth #include	"io.h"
7*74a4d8c2SCharles.Forsyth #include	"ureg.h"
8*74a4d8c2SCharles.Forsyth 
9*74a4d8c2SCharles.Forsyth #include	<isa.h>
10*74a4d8c2SCharles.Forsyth #include	<interp.h>
11*74a4d8c2SCharles.Forsyth 
12*74a4d8c2SCharles.Forsyth typedef struct Clock0link Clock0link;
13*74a4d8c2SCharles.Forsyth typedef struct Clock0link {
14*74a4d8c2SCharles.Forsyth 	void		(*clock)(void);
15*74a4d8c2SCharles.Forsyth 	Clock0link*	link;
16*74a4d8c2SCharles.Forsyth } Clock0link;
17*74a4d8c2SCharles.Forsyth 
18*74a4d8c2SCharles.Forsyth static Clock0link *clock0link;
19*74a4d8c2SCharles.Forsyth static Lock clock0lock;
20*74a4d8c2SCharles.Forsyth ulong	clkrelinq;
21*74a4d8c2SCharles.Forsyth void	(*kproftick)(ulong);	/* set by devkprof.c when active */
22*74a4d8c2SCharles.Forsyth void	(*archclocktick)(void);	/* set by arch*.c when desired */
23*74a4d8c2SCharles.Forsyth 
24*74a4d8c2SCharles.Forsyth Timer*
addclock0link(void (* clock)(void),int)25*74a4d8c2SCharles.Forsyth addclock0link(void (*clock)(void), int)
26*74a4d8c2SCharles.Forsyth {
27*74a4d8c2SCharles.Forsyth 	Clock0link *lp;
28*74a4d8c2SCharles.Forsyth 
29*74a4d8c2SCharles.Forsyth 	if((lp = malloc(sizeof(Clock0link))) == 0){
30*74a4d8c2SCharles.Forsyth 		print("addclock0link: too many links\n");
31*74a4d8c2SCharles.Forsyth 		return nil;
32*74a4d8c2SCharles.Forsyth 	}
33*74a4d8c2SCharles.Forsyth 	ilock(&clock0lock);
34*74a4d8c2SCharles.Forsyth 	lp->clock = clock;
35*74a4d8c2SCharles.Forsyth 	lp->link = clock0link;
36*74a4d8c2SCharles.Forsyth 	clock0link = lp;
37*74a4d8c2SCharles.Forsyth 	iunlock(&clock0lock);
38*74a4d8c2SCharles.Forsyth 	return nil;
39*74a4d8c2SCharles.Forsyth }
40*74a4d8c2SCharles.Forsyth 
41*74a4d8c2SCharles.Forsyth void
delay(int l)42*74a4d8c2SCharles.Forsyth delay(int l)
43*74a4d8c2SCharles.Forsyth {
44*74a4d8c2SCharles.Forsyth 	ulong i, j;
45*74a4d8c2SCharles.Forsyth 
46*74a4d8c2SCharles.Forsyth 	j = m->delayloop;
47*74a4d8c2SCharles.Forsyth 	while(l-- > 0)
48*74a4d8c2SCharles.Forsyth 		for(i=0; i < j; i++)
49*74a4d8c2SCharles.Forsyth 			;
50*74a4d8c2SCharles.Forsyth }
51*74a4d8c2SCharles.Forsyth 
52*74a4d8c2SCharles.Forsyth void
microdelay(int l)53*74a4d8c2SCharles.Forsyth microdelay(int l)
54*74a4d8c2SCharles.Forsyth {
55*74a4d8c2SCharles.Forsyth 	ulong i;
56*74a4d8c2SCharles.Forsyth 
57*74a4d8c2SCharles.Forsyth 	l *= m->delayloop;
58*74a4d8c2SCharles.Forsyth 	l /= 1000;
59*74a4d8c2SCharles.Forsyth 	if(l <= 0)
60*74a4d8c2SCharles.Forsyth 		l = 1;
61*74a4d8c2SCharles.Forsyth 	for(i = 0; i < l; i++)
62*74a4d8c2SCharles.Forsyth 		;
63*74a4d8c2SCharles.Forsyth }
64*74a4d8c2SCharles.Forsyth 
65*74a4d8c2SCharles.Forsyth enum {
66*74a4d8c2SCharles.Forsyth 	Timebase = 4,	/* system clock cycles per time base cycle */
67*74a4d8c2SCharles.Forsyth };
68*74a4d8c2SCharles.Forsyth 
69*74a4d8c2SCharles.Forsyth static	ulong	clkreload;
70*74a4d8c2SCharles.Forsyth 
71*74a4d8c2SCharles.Forsyth void
clockinit(void)72*74a4d8c2SCharles.Forsyth clockinit(void)
73*74a4d8c2SCharles.Forsyth {
74*74a4d8c2SCharles.Forsyth 	long x;
75*74a4d8c2SCharles.Forsyth 
76*74a4d8c2SCharles.Forsyth 	m->delayloop = m->cpuhz/1000;	/* initial estimate */
77*74a4d8c2SCharles.Forsyth 	do {
78*74a4d8c2SCharles.Forsyth 		x = gettbl();
79*74a4d8c2SCharles.Forsyth 		delay(10);
80*74a4d8c2SCharles.Forsyth 		x = gettbl() - x;
81*74a4d8c2SCharles.Forsyth 	} while(x < 0);
82*74a4d8c2SCharles.Forsyth 
83*74a4d8c2SCharles.Forsyth 	/*
84*74a4d8c2SCharles.Forsyth 	 *  fix count
85*74a4d8c2SCharles.Forsyth 	 */
86*74a4d8c2SCharles.Forsyth 	m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
87*74a4d8c2SCharles.Forsyth 	if(m->delayloop == 0)
88*74a4d8c2SCharles.Forsyth 		m->delayloop = 1;
89*74a4d8c2SCharles.Forsyth 
90*74a4d8c2SCharles.Forsyth 	clkreload = (m->clockgen/Timebase)/HZ-1;
91*74a4d8c2SCharles.Forsyth 	putdec(clkreload);
92*74a4d8c2SCharles.Forsyth }
93*74a4d8c2SCharles.Forsyth 
94*74a4d8c2SCharles.Forsyth void
clockintr(Ureg * ur)95*74a4d8c2SCharles.Forsyth clockintr(Ureg *ur)
96*74a4d8c2SCharles.Forsyth {
97*74a4d8c2SCharles.Forsyth 	Clock0link *lp;
98*74a4d8c2SCharles.Forsyth 	long v;
99*74a4d8c2SCharles.Forsyth 
100*74a4d8c2SCharles.Forsyth 	v = -getdec();
101*74a4d8c2SCharles.Forsyth 	if(v > clkreload/2){
102*74a4d8c2SCharles.Forsyth 		if(v > clkreload)
103*74a4d8c2SCharles.Forsyth 			m->ticks += v/clkreload;
104*74a4d8c2SCharles.Forsyth 		v = 0;
105*74a4d8c2SCharles.Forsyth 	}
106*74a4d8c2SCharles.Forsyth 	putdec(clkreload-v);
107*74a4d8c2SCharles.Forsyth 
108*74a4d8c2SCharles.Forsyth 	/* watchdog */
109*74a4d8c2SCharles.Forsyth 	if(m->iomem->sypcr & (1<<2)){
110*74a4d8c2SCharles.Forsyth 		m->iomem->swsr = 0x556c;
111*74a4d8c2SCharles.Forsyth 		m->iomem->swsr = 0xaa39;
112*74a4d8c2SCharles.Forsyth 	}
113*74a4d8c2SCharles.Forsyth 
114*74a4d8c2SCharles.Forsyth 	m->ticks++;
115*74a4d8c2SCharles.Forsyth 	if(archclocktick != nil)
116*74a4d8c2SCharles.Forsyth 		archclocktick();
117*74a4d8c2SCharles.Forsyth 
118*74a4d8c2SCharles.Forsyth 	if(up)
119*74a4d8c2SCharles.Forsyth 		up->pc = ur->pc;
120*74a4d8c2SCharles.Forsyth 
121*74a4d8c2SCharles.Forsyth 	checkalarms();
122*74a4d8c2SCharles.Forsyth 	if(m->machno == 0) {
123*74a4d8c2SCharles.Forsyth 		if(kproftick != nil)
124*74a4d8c2SCharles.Forsyth 			(*kproftick)(ur->pc);
125*74a4d8c2SCharles.Forsyth 		if(canlock(&clock0lock)){
126*74a4d8c2SCharles.Forsyth 			for(lp = clock0link; lp; lp = lp->link)
127*74a4d8c2SCharles.Forsyth 				lp->clock();
128*74a4d8c2SCharles.Forsyth 			unlock(&clock0lock);
129*74a4d8c2SCharles.Forsyth 		}
130*74a4d8c2SCharles.Forsyth 	}
131*74a4d8c2SCharles.Forsyth 
132*74a4d8c2SCharles.Forsyth 	if(up && up->state == Running){
133*74a4d8c2SCharles.Forsyth 		if(cflag && up->type == Interp && tready(nil))
134*74a4d8c2SCharles.Forsyth 			ur->cr |= 1;	/* set flag in condition register for ../../libinterp/comp-power.c:/^schedcheck */
135*74a4d8c2SCharles.Forsyth 	}
136*74a4d8c2SCharles.Forsyth 	/* other preemption checks are done by trap.c */
137*74a4d8c2SCharles.Forsyth }
138*74a4d8c2SCharles.Forsyth 
139*74a4d8c2SCharles.Forsyth uvlong
fastticks(uvlong * hz)140*74a4d8c2SCharles.Forsyth fastticks(uvlong *hz)
141*74a4d8c2SCharles.Forsyth {
142*74a4d8c2SCharles.Forsyth 	if(hz)
143*74a4d8c2SCharles.Forsyth 		*hz = HZ;
144*74a4d8c2SCharles.Forsyth 	return m->ticks;
145*74a4d8c2SCharles.Forsyth }
146