revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-chrp / efika / timer / ticks.c
blob28fc1bd9723056e1c0470188c8c6b9c45aa84a42
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
7 #include <asm/mpc5200b.h>
8 #include <asm/io.h>
9 #include <aros/asmcall.h>
10 #include <exec/execbase.h>
12 #include <inttypes.h>
13 #include <proto/exec.h>
14 #include <proto/timer.h>
16 #include "lowlevel.h"
18 // tick2usec - 64424510 for 66.666666MHz
19 // tick2usec - 130150524 for 33.000000MHz
21 inline uint32_t __attribute__((const)) tick2usec(uint32_t tick)
23 uint32_t retval;
24 uint64_t tmp = ((uint64_t)tick) * 130150524;
26 retval = (tmp + 0x7fffffff) >> 32;
28 return retval;
31 inline uint32_t __attribute__((const)) usec2tick(uint32_t usec)
33 uint32_t retval;
34 // uint64_t tmp = ((uint64_t)usec) * 286331150203ULL;
36 // retval = (tmp + 0x7fffffff) >> 32;
38 retval = usec * 33;
40 return retval;
43 void EClockUpdate(struct TimerBase *TimerBase)
45 uint32_t time;
46 uint32_t diff;
47 int show = 0;
49 time = mftbl();
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++;
63 show = 1;
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);
75 // if (show)
76 // {
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);
79 // }
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 */
92 struct timeval time;
93 struct timerequest *tr;
94 uint32_t current_time;
96 tr = (struct timerequest *)GetHead(&TimerBase->tb_Lists[TL_WAITVBL]);
98 if (tr)
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)
107 delay = 0;
109 else if (time.tv_secs == 0)
111 // if (time.tv_micro < 20000)
112 // {
113 if (delay > usec2tick(time.tv_micro))
114 delay = usec2tick(time.tv_micro);
115 // }
119 tr = (struct timerequest *)GetHead(&TimerBase->tb_Lists[TL_VBLANK]);
121 if (tr)
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)
130 delay = 0;
132 else if (time.tv_secs == 0)
134 // if (time.tv_micro < 20000)
135 // {
136 if (delay > usec2tick(time.tv_micro))
137 delay = usec2tick(time.tv_micro);
138 // }
142 current_time = mftbl();
143 delay -= ((int32_t)(current_time - waste)) + corr;
145 if (delay < 256) delay = 256;
147 tbc_expected = current_time + delay;
149 /* Stop the timer */
150 outl(SLT_CF_INTRENA, &slice_timer->slt_cf);
151 /* Set the delay */
152 outl(delay, &slice_timer->slt_tc);
153 /* Let timer go */
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);