chrp-ppc: Use AROS_UFIx() macros
[AROS.git] / arch / ppc-chrp / efika / timer / ticks.c
blob88f1bad5e253e9896c9404deac28debcc8009103
1 #include <aros/debug.h>
2 #include <asm/mpc5200b.h>
3 #include <asm/io.h>
4 #include <aros/asmcall.h>
5 #include <exec/execbase.h>
7 #include <inttypes.h>
8 #include <proto/exec.h>
9 #include <proto/timer.h>
11 #include "lowlevel.h"
13 // tick2usec - 64424510 for 66.666666MHz
14 // tick2usec - 130150524 for 33.000000MHz
16 inline uint32_t __attribute__((const)) tick2usec(uint32_t tick)
18 uint32_t retval;
19 uint64_t tmp = ((uint64_t)tick) * 130150524;
21 retval = (tmp + 0x7fffffff) >> 32;
23 return retval;
26 inline uint32_t __attribute__((const)) usec2tick(uint32_t usec)
28 uint32_t retval;
29 // uint64_t tmp = ((uint64_t)usec) * 286331150203ULL;
31 // retval = (tmp + 0x7fffffff) >> 32;
33 retval = usec * 33;
35 return retval;
38 void EClockUpdate(struct TimerBase *TimerBase)
40 uint32_t time;
41 uint32_t diff;
42 int show = 0;
44 time = mftbl();
45 diff = (time - TimerBase->tb_prev_tick);
46 TimerBase->tb_prev_tick = time;
48 TimerBase->tb_ticks_total += diff;
50 TimerBase->tb_ticks_sec += diff;
51 TimerBase->tb_ticks_elapsed += diff;
53 if (TimerBase->tb_ticks_sec >= 33000000)
55 TimerBase->tb_ticks_sec -= 33000000;
56 TimerBase->tb_CurrentTime.tv_secs++;
58 show = 1;
61 if (TimerBase->tb_ticks_elapsed >= 33000000)
63 TimerBase->tb_ticks_elapsed -= 33000000;
64 TimerBase->tb_Elapsed.tv_secs++;
67 TimerBase->tb_Elapsed.tv_micro = tick2usec(TimerBase->tb_ticks_elapsed);
68 TimerBase->tb_CurrentTime.tv_micro = tick2usec(TimerBase->tb_ticks_sec);
70 // if (show)
71 // {
72 // bug("[timer] CurrentTime: %d:%06d\n", TimerBase->tb_CurrentTime.tv_secs, TimerBase->tb_CurrentTime.tv_micro);
73 // bug("[timer] %08x %08x %d %d \n", tbc_expected, tbc_achieved, tbc_achieved-tbc_expected, corr);
74 // }
77 void EClockSet(struct TimerBase *TimerBase)
79 TimerBase->tb_ticks_sec = usec2tick(TimerBase->tb_CurrentTime.tv_micro);
82 extern volatile slt_t *slice_timer;
84 void TimerSetup(struct TimerBase *TimerBase, uint32_t waste)
86 int32_t delay = 660000; /* 50Hz in worst case */
87 struct timeval time;
88 struct timerequest *tr;
89 uint32_t current_time;
91 tr = (struct timerequest *)GetHead(&TimerBase->tb_Lists[TL_WAITVBL]);
93 if (tr)
95 time.tv_micro = tr->tr_time.tv_micro;
96 time.tv_secs = tr->tr_time.tv_secs;
98 SubTime(&time, &TimerBase->tb_CurrentTime);
100 if ((LONG)time.tv_secs < 0)
102 delay = 0;
104 else if (time.tv_secs == 0)
106 // if (time.tv_micro < 20000)
107 // {
108 if (delay > usec2tick(time.tv_micro))
109 delay = usec2tick(time.tv_micro);
110 // }
114 tr = (struct timerequest *)GetHead(&TimerBase->tb_Lists[TL_VBLANK]);
116 if (tr)
118 time.tv_micro = tr->tr_time.tv_micro;
119 time.tv_secs = tr->tr_time.tv_secs;
121 SubTime(&time, &TimerBase->tb_Elapsed);
123 if ((LONG)time.tv_secs < 0)
125 delay = 0;
127 else if (time.tv_secs == 0)
129 // if (time.tv_micro < 20000)
130 // {
131 if (delay > usec2tick(time.tv_micro))
132 delay = usec2tick(time.tv_micro);
133 // }
137 current_time = mftbl();
138 delay -= ((int32_t)(current_time - waste)) + corr;
140 if (delay < 256) delay = 256;
142 tbc_expected = current_time + delay;
144 /* Stop the timer */
145 outl(SLT_CF_INTRENA, &slice_timer->slt_cf);
146 /* Set the delay */
147 outl(delay, &slice_timer->slt_tc);
148 /* Let timer go */
149 outl(SLT_CF_INTRENA | SLT_CF_ENABLE, &slice_timer->slt_cf);
150 /* Clear interrupt request. */
151 outl(SLT_TS_ST, &slice_timer->slt_ts);