1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: 17: 18: 19: 20:
21:
22: #include <basic.h>
23: #include <tk/tkernel.h>
24: #include <tk/ptimer.h>
25:
26: 27: 28:
29: LOCAL struct timerlist {
30: INT base;
31: INTVEC irq;
32: UINT mode;
33: FP hdr;
34: void* exinf;
35: } TimerList[] = {
36: { 0xc0000100, IV_IRQ(55) },
37: { 0xc0000200, IV_IRQ(56) },
38: { 0xc0000300, IV_IRQ(57) },
39: { 0xc0002000, IV_IRQ(34) },
40: { 0xc0002100, IV_IRQ(35) },
41: { 0xc0002200, IV_IRQ(36) },
42: { 0xc0002300, IV_IRQ(44) },
43: { 0xc0002400, IV_IRQ(45) },
44: { 0xc0002500, IV_IRQ(46) },
45: { 0xc0001000, IV_IRQ(58) },
46: { 0xc0001100, IV_IRQ(59) },
47: { 0xc0001200, IV_IRQ(60) },
48: { 0xc0001300, IV_IRQ(61) }
49: };
50:
51: #define N_TIMER ( sizeof(TimerList) / sizeof(TimerList[0]) )
52:
53: 54: 55: 56:
57: #define TI(pn, ofs) ( TimerList[pn].base + (ofs) )
58:
59: #define TI_OP(pn) TI(pn, 0x00)
60: #define TI_CLR(pn) TI(pn, 0x04)
61: #define TI_SET(pn) TI(pn, 0x08)
62: #define TI_RCR(pn) TI(pn, 0x0c)
63: #define TI_SCLR(pn) TI(pn, 0x14)
64:
65: #define TO_EN 0x0004
66: #define TSTART 0x0002
67: #define TM_EN 0x0001
68:
69: #define TCR_CLR 0x0002
70:
71: #define TM_SCLR 0x0001
72:
73: 74: 75: 76:
77: #define ASMU(n) ( 0xc0110000 + (n) )
78:
79: #define TI0TIN_SEL ASMU(0x0138)
80: #define TI1TIN_SEL ASMU(0x013c)
81: #define TI2TIN_SEL ASMU(0x0140)
82: #define TI3TIN_SEL ASMU(0x0144)
83: #define TGnTIN_SEL ASMU(0x0148)
84:
85: #define DIVTIMTIN ASMU(0x014c)
86: #define GCLKCTRL3 ASMU(0x01cc)
87: #define GCLKCTRL3ENA ASMU(0x01d0)
88:
89: #define TITIN_PLL3 0
90: #define TITIN_32768 1
91: #define TITIN_32K 2
92:
93: #define TIN_GCK(pn) ( 2 << (pn) )
94:
95: 96: 97: 98:
99: #define PLL3_CLK 229376000
100:
101: #define D0(d) ( (d) & 0x7 )
102: #define D1(d) ( ((d) >> 4) & 0xf )
103:
104: #define TIN_CLK(d) ( PLL3_CLK / ((1 << D0(d)) * (D1(d) + 1)) )
105:
106:
107:
108: 109: 110:
111: LOCAL void initialize_timer( void )
112: {
113: UW m;
114:
115:
116: out_w(TI0TIN_SEL, in_w(TI0TIN_SEL) & ~0x00030000);
117: out_w(TI1TIN_SEL, 0);
118: out_w(TI2TIN_SEL, 0);
119: out_w(TI3TIN_SEL, 0);
120: out_w(TGnTIN_SEL, 0);
121:
122:
123: m = 0x00003ffe;
124: out_w(GCLKCTRL3ENA, in_w(GCLKCTRL3ENA) | m);
125: out_w(GCLKCTRL3, in_w(GCLKCTRL3) & ~m);
126: }
127:
128: 129: 130:
131: LOCAL INT CHK_PTMRNO( UINT ptmrno )
132: {
133: static BOOL init = FALSE;
134: UINT imask;
135:
136: if ( (ptmrno < 1) || (ptmrno > N_TIMER) ) return E_PAR;
137:
138: if ( !init ) {
139: DI(imask);
140:
141:
142: if ( !init ) initialize_timer();
143: init = TRUE;
144:
145: EI(imask);
146: }
147:
148: return ptmrno - 1;
149: }
150:
151:
152:
153: 154: 155:
156: LOCAL void timer_inthdr( UINT dintno, void *sp )
157: {
158: struct timerlist *tp;
159: INT pn;
160:
161: for ( pn = 0; pn < N_TIMER; ++pn ) {
162: tp = &TimerList[pn];
163: if ( DINTNO(tp->irq) == dintno ) break;
164: }
165: if ( pn >= N_TIMER ) return;
166:
167: ClearInt(tp->irq);
168:
169: if ( tp->mode == TA_ALM_PTMR ) {
170:
171: out_w(TI_OP(pn), 0);
172:
173:
174: out_w(GCLKCTRL3, in_w(GCLKCTRL3) & ~TIN_GCK(pn));
175: }
176:
177: if ( tp->hdr != NULL ) {
178:
179: (*tp->hdr)(tp->exinf);
180: }
181: }
182:
183: 184: 185:
186: EXPORT ER StartPhysicalTimer( UINT ptmrno, UW limit, UINT mode )
187: {
188: INT pn;
189: UINT imask;
190: T_DINT dint;
191: ER err;
192:
193: if ( (mode != TA_ALM_PTMR) && (mode != TA_CYC_PTMR) ) return E_PAR;
194:
195:
196: if ( limit <= 2 ) return E_PAR;
197:
198: pn = CHK_PTMRNO(ptmrno);
199: if ( pn < E_OK ) return pn;
200:
201:
202: out_w(TI_OP(pn), 0);
203:
204: TimerList[pn].mode = mode;
205:
206:
207: dint.intatr = TA_HLNG;
208: dint.inthdr = timer_inthdr;
209: err = tk_def_int(DINTNO(TimerList[pn].irq), &dint);
210: if ( err < E_OK ) return err;
211:
212: SetIntMode(TimerList[pn].irq, IM_ENA);
213: ClearInt(TimerList[pn].irq);
214:
215: DI(imask);
216:
217:
218: out_w(GCLKCTRL3, in_w(GCLKCTRL3) | TIN_GCK(pn));
219:
220:
221: out_w(TI_OP(pn), TM_EN);
222: while ( (in_w(TI_SCLR(pn)) & TM_SCLR) != 0 );
223: WaitUsec(1);
224:
225:
226: out_w(TI_SET(pn), limit);
227:
228:
229: out_w(TI_OP(pn), TO_EN|TSTART|TM_EN);
230:
231: EI(imask);
232:
233:
234: EnableInt(TimerList[pn].irq);
235:
236: return E_OK;
237: }
238:
239: 240: 241:
242: EXPORT ER StopPhysicalTimer( UINT ptmrno )
243: {
244: INT pn;
245: UINT imask;
246:
247: pn = CHK_PTMRNO(ptmrno);
248: if ( pn < E_OK ) return pn;
249:
250:
251: DisableInt(TimerList[pn].irq);
252:
253: DI(imask);
254:
255:
256: out_w(TI_OP(pn), in_w(TI_OP(pn)) & TM_EN);
257:
258:
259: out_w(GCLKCTRL3, in_w(GCLKCTRL3) & ~TIN_GCK(pn));
260:
261: EI(imask);
262:
263: return E_OK;
264: }
265:
266: 267: 268:
269: EXPORT ER GetPhysicalTimerCount( UINT ptmrno, UW *p_count )
270: {
271: INT pn;
272:
273: pn = CHK_PTMRNO(ptmrno);
274: if ( pn < E_OK ) return pn;
275:
276: if ( (in_w(TI_OP(pn)) & TM_EN) == 0 ) {
277: *p_count = 0;
278: } else {
279: *p_count = in_w(TI_RCR(pn));
280: }
281:
282: return E_OK;
283: }
284:
285: 286: 287:
288: EXPORT ER DefinePhysicalTimerHandler( UINT ptmrno, CONST T_DPTMR *pk_dptmr )
289: {
290: INT pn;
291: UINT imask;
292:
293: pn = CHK_PTMRNO(ptmrno);
294: if ( pn < E_OK ) return pn;
295:
296: if ( pk_dptmr != NULL ) {
297: if ( (pk_dptmr->ptmratr & ~(TA_ASM|TA_HLNG)) != 0 )
298: return E_PAR;
299:
300: DI(imask);
301: TimerList[pn].exinf = pk_dptmr->exinf;
302: TimerList[pn].hdr = pk_dptmr->ptmrhdr;
303: EI(imask);
304: } else {
305: TimerList[pn].hdr = NULL;
306: }
307:
308: return E_OK;
309: }
310:
311: 312: 313:
314: EXPORT ER GetPhysicalTimerConfig( UINT ptmrno, T_RPTMR *pk_rptmr )
315: {
316: INT pn;
317: UW d;
318:
319: pn = CHK_PTMRNO(ptmrno);
320: if ( pn < E_OK ) return pn;
321:
322: d = in_w(DIVTIMTIN);
323:
324: pk_rptmr->ptmrclk = TIN_CLK(d);
325: pk_rptmr->maxcount = 0xffffffff;
326: pk_rptmr->defhdr = TRUE;
327:
328: return E_OK;
329: }