xref: /plan9/sys/src/9/ppc/saturntimer.c (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 #include "msaturn.h"
9 
10 enum {
11 	Timer_ctrl = Saturn + 0x0106,
12 	Timer0_load = Saturn + 0x0200,
13 	Timer0_cnt = Saturn + 0x0204,
14 	Timer1_load = Saturn + 0x0300,
15 	Timer1_cnt = Saturn + 0x0304,
16 
17 	T0_event = RBIT(13, ushort),
18 	T0_ie = RBIT(14, ushort),
19 	T0_cen = RBIT(15, ushort),
20 	T1_event = RBIT(5, ushort),
21 	T1_ie = RBIT(6, ushort),
22 	T1_cen = RBIT(7, ushort),
23 };
24 
25 static ulong ticks;
26 static Lock tlock;
27 static ushort timer_ctl;
28 
29 ulong multiplier;
30 
31 ulong
s(void)32 µs(void)
33 {
34 	uvlong x;
35 
36 	if(multiplier == 0){
37 		multiplier = (uvlong)(1000000LL << 16) / m->cyclefreq;
38 		print("µs: multiplier %ld, cyclefreq %lld, shifter %d\n", multiplier, m->cyclefreq, 16);
39 	}
40 	cycles(&x);
41 	return (x*multiplier) >> 16;
42 }
43 
44 void
saturntimerintr(Ureg * u,void *)45 saturntimerintr(Ureg *u, void*)
46 {
47 	ushort ctl = *(ushort*)Timer_ctrl, v = 0;
48 
49 	if(ctl&T1_event){
50 		v = T1_event;
51 		ticks++;
52 	}
53 
54 	*(ushort*)Timer_ctrl = timer_ctl|T0_event|v;
55 	intack();
56 	timerintr(u, 0);
57 }
58 
59 void
timerinit(void)60 timerinit(void)
61 {
62 	*(ushort*)Timer_ctrl = 0;
63 	*(ulong*)Timer0_load = m->bushz  / HZ;
64 	*(ulong*)Timer0_cnt = m->bushz / HZ;
65 	*(ulong*)Timer1_load = m->bushz;
66 	*(ulong*)Timer1_cnt = m->bushz;
67 
68 	intrenable(Vectimer0, saturntimerintr, nil, "timer");
69 
70 	timer_ctl = T0_cen|T0_ie|T1_cen;
71 	*(ushort*)Timer_ctrl = timer_ctl;
72 }
73 
74 uvlong
fastticks(uvlong * hz)75 fastticks(uvlong *hz)
76 {
77 	assert(*(ushort*)Timer_ctrl&T1_cen);
78 	if(*(ushort*)Timer_ctrl&T1_event){
79 		*(ushort*)Timer_ctrl = timer_ctl|T1_event;
80 		ticks++;
81 	}
82 
83 	if (hz)
84 		*hz = m->bushz;
85 
86 	return (uvlong)ticks*m->bushz+(uvlong)(m->bushz-*(ulong*)Timer1_cnt);
87 }
88 
89 void
timerset(Tval next)90 timerset(Tval next)
91 {
92 	ulong offset;
93 	uvlong now;
94 
95 	ilock(&tlock);
96 	*(ushort*)Timer_ctrl = T1_cen;
97 
98 	now = fastticks(nil);
99 	offset = next - now;
100 	if((long)offset < 10000)
101 		offset = 10000;
102 	else if(offset > m->bushz)
103 		offset = m->bushz;
104 
105 	*(ulong*)Timer0_cnt = offset;
106 	*(ushort*)Timer_ctrl = timer_ctl;
107 	assert(*(ushort*)Timer_ctrl & T1_cen);
108 	iunlock(&tlock);
109 }
110 
111