1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Jens Arnold
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
29 static int timer_prio
= -1;
30 void SHAREDBSS_ATTR (*pfn_timer
)(void) = NULL
; /* timer callback */
31 void SHAREDBSS_ATTR (*pfn_unregister
)(void) = NULL
; /* unregister callback */
33 static int base_prescale
;
34 #elif defined CPU_PP || CONFIG_CPU == PNX0101
35 static long SHAREDBSS_ATTR cycles_new
= 0;
38 /* interrupt handler */
39 #if CONFIG_CPU == SH7034
40 void IMIA4(void) __attribute__((interrupt_handler
));
43 if (pfn_timer
!= NULL
)
45 and_b(~0x01, &TSR4
); /* clear the interrupt */
47 #elif defined CPU_COLDFIRE
48 void TIMER1(void) __attribute__ ((interrupt_handler
));
51 if (pfn_timer
!= NULL
)
53 TER1
= 0xff; /* clear all events */
55 #elif CONFIG_CPU == AS3525
58 if (pfn_timer
!= NULL
)
61 TIMER1_INTCLR
= 0; /* clear interrupt */
66 TIMER2_VAL
; /* ACK interrupt */
69 TIMER2_CFG
= 0xc0000000 | (cycles_new
- 1);
72 if (pfn_timer
!= NULL
)
75 /* "lock" the variable, in case timer_set_period()
76 * is called within pfn_timer() */
81 #elif CONFIG_CPU == PNX0101
86 TIMER1
.load
= cycles_new
- 1;
89 if (pfn_timer
!= NULL
)
92 /* "lock" the variable, in case timer_set_period()
93 * is called within pfn_timer() */
97 TIMER1
.clr
= 1; /* clear the interrupt */
99 #endif /* CONFIG_CPU */
101 static bool timer_set(long cycles
, bool start
)
103 #if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) || CONFIG_CPU == AS3525
104 int phi
= 0; /* bits for the prescaler */
107 #if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE)
108 #define PRESCALE_STEP 1
109 #else /* CONFIG_CPU == AS3525 */
110 #define PRESCALE_STEP 4
113 while (cycles
> 0x10000)
114 { /* work out the smallest prescaler that makes it fit */
115 #if CONFIG_CPU == SH7034 || CONFIG_CPU == AS3525
118 prescale
<<= PRESCALE_STEP
;
119 cycles
>>= PRESCALE_STEP
;
123 #if CONFIG_CPU == PNX0101
126 if (pfn_unregister
!= NULL
)
129 pfn_unregister
= NULL
;
131 TIMER1
.ctrl
&= ~0x80; /* disable the counter */
132 TIMER1
.ctrl
|= 0x40; /* reload after counting down to zero */
133 TIMER1
.ctrl
&= ~0xc; /* no prescaler */
134 TIMER1
.clr
= 1; /* clear an interrupt event */
136 if (start
|| (cycles_new
== -1)) /* within isr, cycles_new is "locked" */
138 TIMER1
.load
= cycles
- 1;
139 TIMER1
.ctrl
|= 0x80; /* enable the counter */
145 #elif CONFIG_CPU == SH7034
151 if (pfn_unregister
!= NULL
)
154 pfn_unregister
= NULL
;
157 and_b(~0x10, &TSTR
); /* Stop the timer 4 */
158 and_b(~0x10, &TSNC
); /* No synchronization */
159 and_b(~0x10, &TMDR
); /* Operate normally */
161 TIER4
= 0xF9; /* Enable GRA match interrupt */
164 TCR4
= 0x20 | phi
; /* clear at GRA match, set prescaler */
165 GRA4
= (unsigned short)(cycles
- 1);
166 if (start
|| (TCNT4
>= GRA4
))
168 and_b(~0x01, &TSR4
); /* clear an eventual interrupt */
171 #elif CONFIG_CPU == AS3525
172 /* XXX: 32 bits cycles could be used */
173 if (prescale
> 256 || cycles
> 0x10000)
178 if (pfn_unregister
!= NULL
)
181 pfn_unregister
= NULL
;
185 TIMER1_LOAD
= TIMER1_BGLOAD
= cycles
;
186 /* /!\ bit 4 (reserved) must not be modified
187 * periodic mode, interrupt enabled, 16 bits counter */
188 TIMER1_CONTROL
= (TIMER1_CONTROL
& (1<<4)) | 0xe0 | (phi
<<2);
190 #elif defined CPU_COLDFIRE
191 if (prescale
> 4096/CPUFREQ_MAX_MULT
)
194 if (prescale
> 256/CPUFREQ_MAX_MULT
)
196 phi
= 0x05; /* prescale sysclk/16, timer enabled */
200 phi
= 0x03; /* prescale sysclk, timer enabled */
202 base_prescale
= prescale
;
203 prescale
*= (cpu_frequency
/ CPU_FREQ
);
207 if (pfn_unregister
!= NULL
)
210 pfn_unregister
= NULL
;
212 phi
&= ~1; /* timer disabled at start */
214 /* If it is already enabled, writing a 0 to the RST bit will clear
215 the register, so we clear RST explicitly before writing the real
220 /* We are using timer 1 */
221 TMR1
= 0x0018 | (unsigned short)phi
| ((unsigned short)(prescale
- 1) << 8);
222 TRR1
= (unsigned short)(cycles
- 1);
223 if (start
|| (TCN1
>= TRR1
))
224 TCN1
= 0; /* reset the timer */
225 TER1
= 0xff; /* clear all events */
228 #elif defined(CPU_PP)
229 if (cycles
> 0x20000000 || cycles
< 2)
234 if (pfn_unregister
!= NULL
)
237 pfn_unregister
= NULL
;
239 CPU_INT_DIS
= TIMER2_MASK
;
240 COP_INT_DIS
= TIMER2_MASK
;
242 if (start
|| (cycles_new
== -1)) /* within isr, cycles_new is "locked" */
243 TIMER2_CFG
= 0xc0000000 | (cycles
- 1); /* enable timer */
248 #elif (CONFIG_CPU == IMX31L)
250 (void)cycles
; (void)start
;
253 return __TIMER_SET(cycles
, start
);
254 #endif /* CONFIG_CPU */
258 void timers_adjust_prescale(int multiplier
, bool enable_irq
)
261 TMR0
= (TMR0
& 0x00ef)
262 | ((unsigned short)(multiplier
- 1) << 8)
263 | (enable_irq
? 0x10 : 0);
268 int prescale
= base_prescale
* multiplier
;
269 TMR1
= (TMR1
& 0x00ef)
270 | ((unsigned short)(prescale
- 1) << 8)
271 | (enable_irq
? 0x10 : 0);
276 /* Register a user timer, called every <cycles> TIMER_FREQ cycles */
277 bool timer_register(int reg_prio
, void (*unregister_callback
)(void),
278 long cycles
, int int_prio
, void (*timer_callback
)(void)
281 if (reg_prio
<= timer_prio
|| cycles
== 0)
284 #if CONFIG_CPU == SH7034
285 if (int_prio
< 1 || int_prio
> 15)
289 if (!timer_set(cycles
, true))
292 pfn_timer
= timer_callback
;
293 pfn_unregister
= unregister_callback
;
294 timer_prio
= reg_prio
;
296 #if CONFIG_CPU == SH7034
297 IPRD
= (IPRD
& 0xFF0F) | int_prio
<< 4; /* interrupt priority */
298 or_b(0x10, &TSTR
); /* start timer 4 */
300 #elif defined CPU_COLDFIRE
301 ICR2
= 0x90; /* interrupt on level 4.0 */
302 and_l(~(1<<10), &IMR
);
303 TMR1
|= 1; /* start timer */
305 #elif defined(CPU_PP)
306 /* unmask interrupt source */
309 COP_INT_EN
= TIMER2_MASK
;
312 CPU_INT_EN
= TIMER2_MASK
;
314 #elif CONFIG_CPU == PNX0101
315 irq_set_int_handler(IRQ_TIMER1
, TIMER1_ISR
);
316 irq_enable_int(IRQ_TIMER1
);
318 #elif CONFIG_CPU == AS3525
319 CGU_PERI
|= CGU_TIMER1_CLOCK_ENABLE
; /* enable peripheral */
320 VIC_INT_ENABLE
|= INTERRUPT_TIMER1
;
322 #elif CONFIG_CPU == IMX31L
326 return __TIMER_REGISTER(reg_prio
, unregister_callback
, cycles
,
327 int_prio
, timer_callback
);
329 /* Cover for targets that don't use all these */
331 (void)unregister_callback
;
333 /* TODO: Implement for PortalPlayer and iFP (if possible) */
335 (void)timer_callback
;
338 bool timer_set_period(long cycles
)
340 return timer_set(cycles
, false);
343 void timer_unregister(void)
345 #if CONFIG_CPU == SH7034
346 and_b(~0x10, &TSTR
); /* stop the timer 4 */
347 IPRD
= (IPRD
& 0xFF0F); /* disable interrupt */
348 #elif defined CPU_COLDFIRE
349 TMR1
= 0; /* disable timer 1 */
350 or_l((1<<10), &IMR
); /* disable interrupt */
351 #elif defined(CPU_PP)
352 TIMER2_CFG
= 0; /* stop timer 2 */
353 CPU_INT_DIS
= TIMER2_MASK
;
354 COP_INT_DIS
= TIMER2_MASK
;
355 #elif CONFIG_CPU == PNX0101
356 TIMER1
.ctrl
&= ~0x80; /* disable timer 1 */
357 irq_disable_int(IRQ_TIMER1
);
358 #elif CONFIG_CPU == AS3525
359 TIMER1_CONTROL
&= 0x10; /* disable timer 1 (don't modify bit 4) */
360 VIC_INT_EN_CLEAR
= INTERRUPT_TIMER1
; /* disable interrupt */
361 CGU_PERI
&= ~CGU_TIMER1_CLOCK_ENABLE
; /* disable peripheral */
362 #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320
363 __TIMER_UNREGISTER();
366 pfn_unregister
= NULL
;