1*74a4d8c2SCharles.Forsyth /*
2*74a4d8c2SCharles.Forsyth * programmable interrupt timer
3*74a4d8c2SCharles.Forsyth */
4*74a4d8c2SCharles.Forsyth
5*74a4d8c2SCharles.Forsyth #include "u.h"
6*74a4d8c2SCharles.Forsyth #include "../port/lib.h"
7*74a4d8c2SCharles.Forsyth #include "mem.h"
8*74a4d8c2SCharles.Forsyth #include "dat.h"
9*74a4d8c2SCharles.Forsyth #include "fns.h"
10*74a4d8c2SCharles.Forsyth #include "io.h"
11*74a4d8c2SCharles.Forsyth #include "ureg.h"
12*74a4d8c2SCharles.Forsyth
13*74a4d8c2SCharles.Forsyth enum {
14*74a4d8c2SCharles.Forsyth /* piscr */
15*74a4d8c2SCharles.Forsyth PTE = 1<<0,
16*74a4d8c2SCharles.Forsyth PITF = 1<<1,
17*74a4d8c2SCharles.Forsyth PIE = 1<<2,
18*74a4d8c2SCharles.Forsyth PS = 1<<7,
19*74a4d8c2SCharles.Forsyth };
20*74a4d8c2SCharles.Forsyth
21*74a4d8c2SCharles.Forsyth static void
pitinterrupt(Ureg *,void *)22*74a4d8c2SCharles.Forsyth pitinterrupt(Ureg*, void*)
23*74a4d8c2SCharles.Forsyth {
24*74a4d8c2SCharles.Forsyth IMM *io;
25*74a4d8c2SCharles.Forsyth
26*74a4d8c2SCharles.Forsyth io = m->iomem;
27*74a4d8c2SCharles.Forsyth if(io->piscr & PS){
28*74a4d8c2SCharles.Forsyth io->piscr |= PS; /* clear by writing 1 */
29*74a4d8c2SCharles.Forsyth /* do whatever is required */
30*74a4d8c2SCharles.Forsyth }
31*74a4d8c2SCharles.Forsyth }
32*74a4d8c2SCharles.Forsyth
33*74a4d8c2SCharles.Forsyth static void
pitreset(void)34*74a4d8c2SCharles.Forsyth pitreset(void)
35*74a4d8c2SCharles.Forsyth {
36*74a4d8c2SCharles.Forsyth IMM *io;
37*74a4d8c2SCharles.Forsyth
38*74a4d8c2SCharles.Forsyth io = ioplock();
39*74a4d8c2SCharles.Forsyth io->piscrk = KEEP_ALIVE_KEY;
40*74a4d8c2SCharles.Forsyth io->piscr = (PITlevel<<8) | PS | PITF;
41*74a4d8c2SCharles.Forsyth if(0)
42*74a4d8c2SCharles.Forsyth io->piscrk = ~KEEP_ALIVE_KEY;
43*74a4d8c2SCharles.Forsyth /* piscrk is left unlocked for interrupt routine */
44*74a4d8c2SCharles.Forsyth iopunlock();
45*74a4d8c2SCharles.Forsyth intrenable(PITlevel, pitinterrupt, nil, BUSUNKNOWN, "pit");
46*74a4d8c2SCharles.Forsyth }
47*74a4d8c2SCharles.Forsyth
48*74a4d8c2SCharles.Forsyth static ulong
pitload(ulong usec)49*74a4d8c2SCharles.Forsyth pitload(ulong usec)
50*74a4d8c2SCharles.Forsyth {
51*74a4d8c2SCharles.Forsyth IMM *io;
52*74a4d8c2SCharles.Forsyth ulong v;
53*74a4d8c2SCharles.Forsyth
54*74a4d8c2SCharles.Forsyth v = ((usec*m->oscclk)/512);
55*74a4d8c2SCharles.Forsyth if(v == 0 || v >= (1<<16))
56*74a4d8c2SCharles.Forsyth return 0; /* can't do */
57*74a4d8c2SCharles.Forsyth io = ioplock();
58*74a4d8c2SCharles.Forsyth io->pitck = KEEP_ALIVE_KEY;
59*74a4d8c2SCharles.Forsyth io->pitc = (v-1)<<16;
60*74a4d8c2SCharles.Forsyth io->pitck = ~KEEP_ALIVE_KEY;
61*74a4d8c2SCharles.Forsyth io->piscrk = KEEP_ALIVE_KEY;
62*74a4d8c2SCharles.Forsyth io->piscr = (PITlevel<<8) | PS | PIE | PITF | PTE;
63*74a4d8c2SCharles.Forsyth if(0)
64*74a4d8c2SCharles.Forsyth io->piscrk = ~KEEP_ALIVE_KEY;
65*74a4d8c2SCharles.Forsyth /* piscrk is left unlocked for interrupt routine */
66*74a4d8c2SCharles.Forsyth iopunlock();
67*74a4d8c2SCharles.Forsyth return (v*512)/m->oscclk;
68*74a4d8c2SCharles.Forsyth }
69