2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
6 #include <aros/debug.h>
7 #include <asm/mpc5200b.h>
9 #include <aros/asmcall.h>
10 #include <exec/execbase.h>
13 #include <proto/exec.h>
14 #include <proto/timer.h>
18 // tick2usec - 64424510 for 66.666666MHz
19 // tick2usec - 130150524 for 33.000000MHz
21 inline uint32_t __attribute__((const)) tick2usec(uint32_t tick
)
24 uint64_t tmp
= ((uint64_t)tick
) * 130150524;
26 retval
= (tmp
+ 0x7fffffff) >> 32;
31 inline uint32_t __attribute__((const)) usec2tick(uint32_t usec
)
34 // uint64_t tmp = ((uint64_t)usec) * 286331150203ULL;
36 // retval = (tmp + 0x7fffffff) >> 32;
43 void EClockUpdate(struct TimerBase
*TimerBase
)
50 diff
= (time
- TimerBase
->tb_prev_tick
);
51 TimerBase
->tb_prev_tick
= time
;
53 TimerBase
->tb_ticks_total
+= diff
;
55 TimerBase
->tb_ticks_sec
+= diff
;
56 TimerBase
->tb_ticks_elapsed
+= diff
;
58 if (TimerBase
->tb_ticks_sec
>= 33000000)
60 TimerBase
->tb_ticks_sec
-= 33000000;
61 TimerBase
->tb_CurrentTime
.tv_secs
++;
66 if (TimerBase
->tb_ticks_elapsed
>= 33000000)
68 TimerBase
->tb_ticks_elapsed
-= 33000000;
69 TimerBase
->tb_Elapsed
.tv_secs
++;
72 TimerBase
->tb_Elapsed
.tv_micro
= tick2usec(TimerBase
->tb_ticks_elapsed
);
73 TimerBase
->tb_CurrentTime
.tv_micro
= tick2usec(TimerBase
->tb_ticks_sec
);
77 // bug("[timer] CurrentTime: %d:%06d\n", TimerBase->tb_CurrentTime.tv_secs, TimerBase->tb_CurrentTime.tv_micro);
78 // bug("[timer] %08x %08x %d %d \n", tbc_expected, tbc_achieved, tbc_achieved-tbc_expected, corr);
82 void EClockSet(struct TimerBase
*TimerBase
)
84 TimerBase
->tb_ticks_sec
= usec2tick(TimerBase
->tb_CurrentTime
.tv_micro
);
87 extern volatile slt_t
*slice_timer
;
89 void TimerSetup(struct TimerBase
*TimerBase
, uint32_t waste
)
91 int32_t delay
= 660000; /* 50Hz in worst case */
93 struct timerequest
*tr
;
94 uint32_t current_time
;
96 tr
= (struct timerequest
*)GetHead(&TimerBase
->tb_Lists
[TL_WAITVBL
]);
100 time
.tv_micro
= tr
->tr_time
.tv_micro
;
101 time
.tv_secs
= tr
->tr_time
.tv_secs
;
103 SubTime(&time
, &TimerBase
->tb_CurrentTime
);
105 if ((LONG
)time
.tv_secs
< 0)
109 else if (time
.tv_secs
== 0)
111 // if (time.tv_micro < 20000)
113 if (delay
> usec2tick(time
.tv_micro
))
114 delay
= usec2tick(time
.tv_micro
);
119 tr
= (struct timerequest
*)GetHead(&TimerBase
->tb_Lists
[TL_VBLANK
]);
123 time
.tv_micro
= tr
->tr_time
.tv_micro
;
124 time
.tv_secs
= tr
->tr_time
.tv_secs
;
126 SubTime(&time
, &TimerBase
->tb_Elapsed
);
128 if ((LONG
)time
.tv_secs
< 0)
132 else if (time
.tv_secs
== 0)
134 // if (time.tv_micro < 20000)
136 if (delay
> usec2tick(time
.tv_micro
))
137 delay
= usec2tick(time
.tv_micro
);
142 current_time
= mftbl();
143 delay
-= ((int32_t)(current_time
- waste
)) + corr
;
145 if (delay
< 256) delay
= 256;
147 tbc_expected
= current_time
+ delay
;
150 outl(SLT_CF_INTRENA
, &slice_timer
->slt_cf
);
152 outl(delay
, &slice_timer
->slt_tc
);
154 outl(SLT_CF_INTRENA
| SLT_CF_ENABLE
, &slice_timer
->slt_cf
);
155 /* Clear interrupt request. */
156 outl(SLT_TS_ST
, &slice_timer
->slt_ts
);