6 #include "irx_imports.h"
10 IRX_ID(
"Timer_Manager", 2, 2);
13 #ifdef BUILDING_TIMRMANP
20 TMR0_COUNT = 0xBF801100,
21 TMR1_COUNT = 0xBF801110,
22 TMR2_COUNT = 0xBF801120,
24 TMR3_COUNT = 0xBF801480,
25 TMR4_COUNT = 0xBF801490,
26 TMR5_COUNT = 0xBF8014A0,
32 TMR_IN_PS1_MODE = 0xBF801450,
34 TMR_HOLD_REG = 0xBF8014B0,
35 TMR_HOLD_MODE = 0xBF8014C0,
38 TMR_CTRL_ZERO_RETURN = 1 << 3,
41 TMR_CTRL_CMP_IRQ_ENABLE = 1 << 4,
42 TMR_CTRL_OVFL_IRQ_ENABLE = 1 << 5,
43 TMR_CTRL_IRQ_ENABLE = 1 << 11,
44 TMR_CTRL_IRQ_REPEAT = 1 << 6,
46 TMR_CTRL_EXT_SIGNAL = 1 << 8,
49 TMR_CTRL_CMP_IRQ = 1 << 11,
50 TMR_CTRL_OVFL_IRQ = 1 << 12,
67 unsigned int (*timeup_handler)(
void *userdata);
69 unsigned int (*overflow_handler)(
void *userdata);
70 void *overflow_common;
73 static struct Timer sTimerTable[NUM_TIMERS] = {
120 static int sIndexMap[NUM_TIMERS] = {
131 u32 timer0() {
return _lh(TMR0_COUNT); }
132 u32 timer1() {
return _lh(TMR1_COUNT); }
133 u32 timer2() {
return _lh(TMR2_COUNT); }
135 u32 timer3() {
return _lw(TMR3_COUNT); }
136 u32 timer4() {
return _lw(TMR4_COUNT); }
137 u32 timer5() {
return _lw(TMR5_COUNT); }
140 static u32 (*sTimerCountFun[NUM_TIMERS])() = {
151 int _start(
int argc,
char **argv)
156 #ifdef BUILDING_TIMRMANP
158 if ((_lw(TMR_IN_PS1_MODE) & 8) == 0) {
159 return MODULE_NO_RESIDENT_END;
164 return MODULE_NO_RESIDENT_END;
167 if ((_lw(TMR_IN_PS1_MODE) & 8) != 0) {
168 return MODULE_NO_RESIDENT_END;
172 for (
int i = 0; i < NUM_TIMERS; i++) {
173 sTimerTable[i].users = 0;
176 ret = RegisterLibraryEntries(&_exp_timrman);
178 return MODULE_NO_RESIDENT_END;
181 return MODULE_RESIDENT_END;
184 void *GetTimersTable()
189 int AllocHardTimer(
int source,
int size,
int prescale)
195 return KE_ILLEGAL_CONTEXT;
200 for (
int i = 0; i < NUM_TIMERS; i++) {
201 timer = &sTimerTable[sIndexMap[i]];
202 if (timer->users != 0) {
206 if ((timer->sources & source) == 0) {
210 if (timer->size != size || timer->max_prescale < prescale) {
214 timid = ((sIndexMap[i] + 1) << 28) | (timer->addr >> 4);
215 SetTimerMode(timid, 0);
219 timer->ctrl_config = 0;
220 timer->timeup_flags = 0;
221 timer->overflow_flags = 0;
222 timer->timeup_handler = 0;
223 timer->overflow_handler = 0;
233 int ReferHardTimer(
int source,
int size,
int mode,
int modemask)
239 return KE_ILLEGAL_CONTEXT;
245 for (
int i = 0; i < NUM_TIMERS; i++) {
246 timer = &sTimerTable[i];
247 if (timer->users == 0) {
251 if (timer->mode == 0) {
255 if ((timer->sources & source) == 0) {
259 if (timer->size != size || (timer->mode & modemask) != mode) {
267 return ((i << 28) + 1) | (timer->addr >> 4);
274 int FreeHardTimer(
int timid)
277 u32 timer_idx = (timid >> 28) - 1;
281 return KE_ILLEGAL_CONTEXT;
284 timer = &sTimerTable[timer_idx];
289 return KE_ILLEGAL_TIMERID;
294 if ((timer->users << 24) != 0) {
295 SetTimerMode(timid, 0);
297 timer->ctrl_config = 0;
298 timer->timeup_flags = 0;
299 timer->overflow_flags = 0;
300 timer->timeup_handler = 0;
301 timer->overflow_handler = 0;
303 if (timer->has_irq_handler) {
307 timer->has_irq_handler = 0;
314 void SetTimerMode(
int timid,
int mode)
316 u32 timer = (timid >> 28) - 1;
317 if (timer >= NUM_TIMERS) {
321 sTimerTable[timer].mode = mode;
322 _sh(mode, (timid << 4) + 4);
325 u32 GetTimerMode(
int timid)
327 u32 timer = (timid >> 28) - 1;
328 if (timer >= NUM_TIMERS) {
329 return KE_ILLEGAL_TIMERID;
332 return sTimerTable[timer].mode;
335 u32 GetTimerStatus(
int timid)
337 return _lh((timid << 4) + 4);
340 void SetTimerCounter(
int timid, u32
count)
342 u32 addr = timid << 4;
351 u32 GetTimerCounter(
int timid)
353 u32 addr = timid << 4;
362 void SetTimerCompare(
int timid, u32 compare)
364 u32 addr = timid << 4;
367 _sw(compare, addr + 8);
369 _sh(compare, addr + 8);
373 u32 GetTimerCompare(
int timid)
375 u32 addr = timid << 4;
378 return _lw(addr + 8);
380 return _lh(addr + 8);
384 void SetHoldMode(
int holdnum,
int mode)
386 #ifndef BUILDING_TIMRMANP
387 u32 hold = _lw(TMR_HOLD_MODE);
388 hold &= ~(0xF << (4 * holdnum));
389 hold |= (mode & 0xF) << (4 * holdnum);
390 _sw(TMR_HOLD_MODE, hold);
394 u32 GetHoldMode(
int holdnum)
396 #ifdef BUILDING_TIMRMANP
399 return _lw(TMR_HOLD_MODE >> (holdnum * 4)) & 0xF;
403 u32 GetHoldReg(
int holdnum)
405 #ifdef BUILDING_TIMRMANP
408 return _lw(TMR_HOLD_REG + (holdnum * 4));
412 int GetHardTimerIntrCode(
int timid)
414 u32 timer = (timid >> 28) - 1;
415 if (timer >= NUM_TIMERS) {
416 return KE_ILLEGAL_TIMERID;
419 return sTimerTable[timer].irq;
423 u32 (*GetTimerReadFunc(
int timid))()
425 u32 timer = (timid >> 28) - 1;
426 if (timer >= NUM_TIMERS) {
427 return (
void *)KE_ILLEGAL_TIMERID;
430 return sTimerCountFun[timer];
434 int SetTimerHandler(
int timid,
unsigned long comparevalue,
unsigned int (*timeuphandler)(
void *userdata),
void *common)
438 u32 timer_idx = (timid >> 28) - 1;
439 if (timer_idx >= NUM_TIMERS) {
440 return KE_ILLEGAL_TIMERID;
444 timer = &sTimerTable[timer_idx];
446 if (timer->mode != 0) {
451 timer->compare_value = comparevalue;
452 timer->timeup_handler = timeuphandler;
453 timer->timeup_common = common;
455 timer->timeup_flags = TMR_CTRL_ZERO_RETURN | TMR_CTRL_CMP_IRQ_ENABLE | TMR_CTRL_IRQ_REPEAT;
457 timer->timeup_flags = 0;
464 int SetOverflowHandler(
int timid,
unsigned int (*handler)(
void *userdata),
void *common)
469 u32 timer_idx = (timid >> 28) - 1;
470 if (timer_idx >= NUM_TIMERS) {
471 return KE_ILLEGAL_TIMERID;
475 timer = &sTimerTable[timer_idx];
477 if (timer->mode != 0) {
482 timer->overflow_handler = handler;
483 timer->overflow_common = common;
484 if (handler != NULL) {
485 timer->overflow_flags = TMR_CTRL_OVFL_IRQ_ENABLE | TMR_CTRL_IRQ_REPEAT;
487 timer->overflow_flags = 0;
493 static int irqHandler(
void *arg)
495 struct Timer *timer = arg;
499 u32 ctrl = _lh(timer->addr + TMR_CTRL_OFFSET);
500 if (ctrl & TMR_CTRL_OVFL_IRQ) {
501 cb_ret = timer->overflow_handler(timer->overflow_common);
507 if (ctrl & TMR_CTRL_CMP_IRQ) {
508 cb_ret = timer->timeup_handler(timer->timeup_common);
512 if (timer->size == 16) {
513 _sh(cb_ret, timer->addr + TMR_CMP_OFFSET);
515 _sw(cb_ret, timer->addr + TMR_CMP_OFFSET);
520 if (stop || timer->mode == 0) {
522 _sh(0, timer->addr + TMR_CTRL_OFFSET);
529 int SetupHardTimer(
int timid,
int source,
int mode,
int prescale)
531 u32 timer_idx = (timid >> 28) - 1;
537 return KE_ILLEGAL_CONTEXT;
540 if (timer_idx >= NUM_TIMERS) {
541 return KE_ILLEGAL_TIMERID;
545 timer = &sTimerTable[timer_idx];
547 if (timer->mode != 0) {
552 timer->ctrl_config = 0;
553 if (!timer->has_irq_handler) {
562 timer->has_irq_handler = 1;
574 return KE_ILLEGAL_MODE;
577 new_mode = mode | 0x80000000;
584 new_mode |= TMR_CTRL_EXT_SIGNAL;
615 timer->ctrl_config = new_mode;
620 int StartHardTimer(
int timid)
624 u32 timer_idx = (timid >> 28) - 1;
625 if (timer_idx >= NUM_TIMERS) {
626 return KE_ILLEGAL_TIMERID;
630 timer = &sTimerTable[timer_idx];
631 if (timer->mode != 0) {
636 if (timer->ctrl_config != 0) {
641 _sh(0, timer->addr + TMR_CTRL_OFFSET);
643 if (timer->timeup_flags) {
647 _sw(timer->compare_value, timer->addr + TMR_CMP_OFFSET);
652 _sh(timer->compare_value, timer->addr + TMR_CMP_OFFSET);
656 timer->mode = timer->ctrl_config | timer->timeup_flags | timer->overflow_flags;
658 _sh(timer->mode, timer->addr + TMR_CTRL_OFFSET);
660 if (timer->mode & 0x30) {
667 int StopHardTimer(
int timid)
671 u32 timer_idx = (timid >> 28) - 1;
672 if (timer_idx >= NUM_TIMERS) {
673 return KE_ILLEGAL_TIMERID;
677 timer = &sTimerTable[timer_idx];
678 if (timer->mode == 0) {
683 if (timer->mode & 0x30) {
688 _sh(0, timer->addr + 4);