7 #include "lwp_threadq.h"
17 static u32 exi_wait_inited
= 0;
18 static lwpq_t time_exi_wait
;
20 extern u32
__SYS_GetRTC(u32
*gctime
);
21 extern syssram
* __SYS_LockSram();
22 extern u32
__SYS_UnlockSram(u32 write
);
26 u32
_DEFUN(gettick
,(),
31 __asm__
__volatile__ (
39 u64
_DEFUN(gettime
,(),
54 : "=r" (v
.ul
[0]), "=r" (v
.ul
[1]), "=&r" (tmp
)
59 void _DEFUN(settime
,(t
),
69 __asm__
__volatile__ (
75 : "r" (v
.ul
[0]), "r" (v
.ul
[1])
79 u32
diff_sec(u64 start
,u64 end
)
83 diff
= diff_ticks(start
,end
);
84 return ticks_to_secs(diff
);
87 u32
diff_msec(u64 start
,u64 end
)
91 diff
= diff_ticks(start
,end
);
92 return ticks_to_millisecs(diff
);
95 u32
diff_usec(u64 start
,u64 end
)
99 diff
= diff_ticks(start
,end
);
100 return ticks_to_microsecs(diff
);
103 u32
diff_nsec(u64 start
,u64 end
)
107 diff
= diff_ticks(start
,end
);
108 return ticks_to_nanosecs(diff
);
111 void __timesystem_init()
113 if(!exi_wait_inited
) {
115 LWP_InitQueue(&time_exi_wait
);
119 void timespec_subtract(const struct timespec
*tp_start
,const struct timespec
*tp_end
,struct timespec
*result
)
121 struct timespec start_st
= *tp_start
;
122 struct timespec
*start
= &start_st
;
123 u32 nsecpersec
= TB_NSPERSEC
;
125 if(tp_end
->tv_nsec
<start
->tv_nsec
) {
126 int secs
= (start
->tv_nsec
- tp_end
->tv_nsec
)/nsecpersec
+1;
127 start
->tv_nsec
-= nsecpersec
* secs
;
128 start
->tv_sec
+= secs
;
130 if((tp_end
->tv_nsec
- start
->tv_nsec
)>nsecpersec
) {
131 int secs
= (start
->tv_nsec
- tp_end
->tv_nsec
)/nsecpersec
;
132 start
->tv_nsec
+= nsecpersec
* secs
;
133 start
->tv_sec
-= secs
;
136 result
->tv_sec
= (tp_end
->tv_sec
- start
->tv_sec
);
137 result
->tv_nsec
= (tp_end
->tv_nsec
- start
->tv_nsec
);
140 unsigned long long timespec_to_ticks(const struct timespec
*tp
)
142 return __lwp_wd_calc_ticks(tp
);
145 int clock_gettime(struct timespec
*tp
)
154 if(!__SYS_GetRTC(&gctime
)) return -1;
157 syssram
* sram
= __SYS_LockSram();
158 gctime
+= sram
->counter_bias
;
161 if(CONF_GetCounterBias(&wii_bias
)>=0) gctime
+= wii_bias
;
166 tp
->tv_nsec
= ticks_to_nanosecs(gettick());
171 // this function spins till timeout is reached
172 void _DEFUN(udelay
,(us
),
175 unsigned long long start
, end
;
180 if (diff_usec(start
,end
) >= us
)
185 unsigned int _DEFUN(nanosleep
,(tb
),
190 __lwp_thread_dispatchdisable();
192 timeout
= __lwp_wd_calc_ticks(tb
);
193 __lwp_thread_setstate(_thr_executing
,LWP_STATES_DELAYING
|LWP_STATES_INTERRUPTIBLE_BY_SIGNAL
);
194 __lwp_wd_initialize(&_thr_executing
->timer
,__lwp_thread_delayended
,_thr_executing
->object
.id
,_thr_executing
);
195 __lwp_wd_insert_ticks(&_thr_executing
->timer
,timeout
);
197 __lwp_thread_dispatchenable();
198 return TB_SUCCESSFUL
;
201 static u32
__getrtc(u32
*gctime
)
207 if(EXI_Select(EXI_CHANNEL_0
,EXI_DEVICE_1
,EXI_SPEED8MHZ
)==0) {
214 if(EXI_Imm(EXI_CHANNEL_0
,&cmd
,4,EXI_WRITE
,NULL
)==0) ret
|= 0x01;
215 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x02;
216 if(EXI_Imm(EXI_CHANNEL_0
,&time
,4,EXI_READ
,NULL
)==0) ret
|= 0x04;
217 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x08;
218 if(EXI_Deselect(EXI_CHANNEL_0
)==0) ret
|= 0x10;
226 static s32
__time_exi_unlock(s32 chn
,s32 dev
)
228 LWP_ThreadBroadcast(time_exi_wait
);
232 static void __time_exi_wait()
237 if((ret
=EXI_Lock(EXI_CHANNEL_0
,EXI_DEVICE_1
,__time_exi_unlock
))==1) break;
238 LWP_ThreadSleep(time_exi_wait
);
242 static u32
__getRTC(u32
*gctime
)
252 if(__getrtc(&time1
)==0
253 || __getrtc(&time2
)==0) {
254 EXI_Unlock(EXI_CHANNEL_0
);
259 EXI_Unlock(EXI_CHANNEL_0
);
267 time_t _DEFUN(time
,(timer
),
275 if(__getRTC((u32
*)&gctime
)==0) return (time_t)0;
278 syssram
* sram
= __SYS_LockSram();
279 gctime
+= sram
->counter_bias
;
282 if(CONF_GetCounterBias(&wii_bias
)>=0) gctime
+= wii_bias
;
287 if(timer
) *timer
= gctime
;
291 unsigned int _DEFUN(sleep
,(s
),
298 return nanosleep(&tb
);
301 unsigned int _DEFUN(usleep
,(us
),
307 sec
= us
/TB_USPERSEC
;
308 rem
= us
- (sec
*TB_USPERSEC
);
311 tb
.tv_nsec
= rem
*TB_NSPERUS
;
312 return nanosleep(&tb
);
315 clock_t clock(void) {
319 int __libogc_gettod_r(struct _reent
*ptr
, struct timeval
*tp
, struct timezone
*tz
) {
322 tp
->tv_sec
= time(NULL
);
323 tp
->tv_usec
= tick_microsecs(gettick());
326 tz
->tz_minuteswest
= 0;