diff options
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/export/timer.h | 6 | ||||
-rw-r--r-- | firmware/target/coldfire/timer-coldfire.c | 119 | ||||
-rw-r--r-- | firmware/target/coldfire/timer-target.h | 40 | ||||
-rw-r--r-- | firmware/timer.c | 83 |
5 files changed, 164 insertions, 85 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 8e3f1ea549..b2fbfa13f2 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -332,6 +332,7 @@ target/coldfire/memset16-coldfire.S | |||
332 | #endif | 332 | #endif |
333 | target/coldfire/kernel-coldfire.c | 333 | target/coldfire/kernel-coldfire.c |
334 | target/coldfire/system-coldfire.c | 334 | target/coldfire/system-coldfire.c |
335 | target/coldfire/timer-coldfire.c | ||
335 | #ifndef BOOTLOADER | 336 | #ifndef BOOTLOADER |
336 | target/coldfire/pcm-coldfire.c | 337 | target/coldfire/pcm-coldfire.c |
337 | #endif /* BOOTLOADER */ | 338 | #endif /* BOOTLOADER */ |
diff --git a/firmware/export/timer.h b/firmware/export/timer.h index e36baa1e1f..b758f57ae5 100644 --- a/firmware/export/timer.h +++ b/firmware/export/timer.h | |||
@@ -28,12 +28,10 @@ | |||
28 | #if defined(CPU_PP) | 28 | #if defined(CPU_PP) |
29 | /* Portalplayer chips use a microsecond timer. */ | 29 | /* Portalplayer chips use a microsecond timer. */ |
30 | #define TIMER_FREQ 1000000 | 30 | #define TIMER_FREQ 1000000 |
31 | #elif defined(CPU_COLDFIRE) | ||
32 | /* timer is based on busclk == cpuclk/2 */ | ||
33 | #define TIMER_FREQ (CPU_FREQ/2) | ||
34 | #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \ | 31 | #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \ |
35 | || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 || CONFIG_CPU == IMX31L \ | 32 | || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 || CONFIG_CPU == IMX31L \ |
36 | || CONFIG_CPU == JZ4732 || CONFIG_CPU == PNX0101 | 33 | || CONFIG_CPU == JZ4732 || CONFIG_CPU == PNX0101 \ |
34 | || defined(CPU_COLDFIRE) | ||
37 | #include "timer-target.h" | 35 | #include "timer-target.h" |
38 | #elif defined(SIMULATOR) | 36 | #elif defined(SIMULATOR) |
39 | #define TIMER_FREQ 1000000 | 37 | #define TIMER_FREQ 1000000 |
diff --git a/firmware/target/coldfire/timer-coldfire.c b/firmware/target/coldfire/timer-coldfire.c new file mode 100644 index 0000000000..ef9fd9ea7a --- /dev/null +++ b/firmware/target/coldfire/timer-coldfire.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Jens Arnold | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | |||
24 | #include "config.h" | ||
25 | #include "system.h" | ||
26 | #include "cpu.h" | ||
27 | #include "timer.h" | ||
28 | #include "timer-target.h" | ||
29 | |||
30 | static int base_prescale; | ||
31 | |||
32 | void TIMER1(void) __attribute__ ((interrupt_handler)); | ||
33 | void TIMER1(void) | ||
34 | { | ||
35 | if (pfn_timer != NULL) | ||
36 | pfn_timer(); | ||
37 | TER1 = 0xff; /* clear all events */ | ||
38 | } | ||
39 | |||
40 | bool __timer_set(long cycles, bool start) | ||
41 | { | ||
42 | int phi = 0; /* bits for the prescaler */ | ||
43 | int prescale = 1; | ||
44 | |||
45 | while (cycles > 0x10000) | ||
46 | { | ||
47 | prescale <<= 1; | ||
48 | cycles >>= 1; | ||
49 | } | ||
50 | |||
51 | if (prescale > 4096/CPUFREQ_MAX_MULT) | ||
52 | return false; | ||
53 | |||
54 | if (prescale > 256/CPUFREQ_MAX_MULT) | ||
55 | { | ||
56 | phi = 0x05; /* prescale sysclk/16, timer enabled */ | ||
57 | prescale >>= 4; | ||
58 | } | ||
59 | else | ||
60 | phi = 0x03; /* prescale sysclk, timer enabled */ | ||
61 | |||
62 | base_prescale = prescale; | ||
63 | prescale *= (cpu_frequency / CPU_FREQ); | ||
64 | |||
65 | if (start) | ||
66 | { | ||
67 | if (pfn_unregister != NULL) | ||
68 | { | ||
69 | pfn_unregister(); | ||
70 | pfn_unregister = NULL; | ||
71 | } | ||
72 | phi &= ~1; /* timer disabled at start */ | ||
73 | |||
74 | /* If it is already enabled, writing a 0 to the RST bit will clear | ||
75 | the register, so we clear RST explicitly before writing the real | ||
76 | data. */ | ||
77 | TMR1 = 0; | ||
78 | } | ||
79 | |||
80 | /* We are using timer 1 */ | ||
81 | TMR1 = 0x0018 | (unsigned short)phi | ((unsigned short)(prescale - 1) << 8); | ||
82 | TRR1 = (unsigned short)(cycles - 1); | ||
83 | if (start || (TCN1 >= TRR1)) | ||
84 | TCN1 = 0; /* reset the timer */ | ||
85 | TER1 = 0xff; /* clear all events */ | ||
86 | |||
87 | return true; | ||
88 | } | ||
89 | |||
90 | bool __timer_start(void) | ||
91 | { | ||
92 | ICR2 = 0x90; /* interrupt on level 4.0 */ | ||
93 | and_l(~(1<<10), &IMR); | ||
94 | TMR1 |= 1; /* start timer */ | ||
95 | return true; | ||
96 | } | ||
97 | |||
98 | void __timer_stop(void) | ||
99 | { | ||
100 | TMR1 = 0; /* disable timer 1 */ | ||
101 | or_l((1<<10), &IMR); /* disable interrupt */ | ||
102 | } | ||
103 | |||
104 | void timers_adjust_prescale(int multiplier, bool enable_irq) | ||
105 | { | ||
106 | /* tick timer */ | ||
107 | TMR0 = (TMR0 & 0x00ef) | ||
108 | | ((unsigned short)(multiplier - 1) << 8) | ||
109 | | (enable_irq ? 0x10 : 0); | ||
110 | |||
111 | if (pfn_timer) | ||
112 | { | ||
113 | /* user timer */ | ||
114 | int prescale = base_prescale * multiplier; | ||
115 | TMR1 = (TMR1 & 0x00ef) | ||
116 | | ((unsigned short)(prescale - 1) << 8) | ||
117 | | (enable_irq ? 0x10 : 0); | ||
118 | } | ||
119 | } | ||
diff --git a/firmware/target/coldfire/timer-target.h b/firmware/target/coldfire/timer-target.h new file mode 100644 index 0000000000..29488887e8 --- /dev/null +++ b/firmware/target/coldfire/timer-target.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Jens Arnold | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef TIMER_TARGET_H | ||
22 | #define TIMER_TARGET_H | ||
23 | |||
24 | bool __timer_set(long cycles, bool start); | ||
25 | bool __timer_start(void); | ||
26 | void __timer_stop(void); | ||
27 | |||
28 | /* timer is based on busclk == cpuclk/2 */ | ||
29 | #define TIMER_FREQ (CPU_FREQ/2) | ||
30 | |||
31 | #define __TIMER_SET(cycles, set) \ | ||
32 | __timer_set(cycles, set) | ||
33 | |||
34 | #define __TIMER_START() \ | ||
35 | __timer_start() | ||
36 | |||
37 | #define __TIMER_STOP(...) \ | ||
38 | __timer_stop() | ||
39 | |||
40 | #endif /* TIMER_TARGET_H */ | ||
diff --git a/firmware/timer.c b/firmware/timer.c index 089deffbd4..34b410c017 100644 --- a/firmware/timer.c +++ b/firmware/timer.c | |||
@@ -29,9 +29,7 @@ | |||
29 | static int timer_prio = -1; | 29 | static int timer_prio = -1; |
30 | void SHAREDBSS_ATTR (*pfn_timer)(void) = NULL; /* timer callback */ | 30 | void SHAREDBSS_ATTR (*pfn_timer)(void) = NULL; /* timer callback */ |
31 | void SHAREDBSS_ATTR (*pfn_unregister)(void) = NULL; /* unregister callback */ | 31 | void SHAREDBSS_ATTR (*pfn_unregister)(void) = NULL; /* unregister callback */ |
32 | #ifdef CPU_COLDFIRE | 32 | #if defined CPU_PP |
33 | static int base_prescale; | ||
34 | #elif defined CPU_PP | ||
35 | static long SHAREDBSS_ATTR cycles_new = 0; | 33 | static long SHAREDBSS_ATTR cycles_new = 0; |
36 | #endif | 34 | #endif |
37 | 35 | ||
@@ -52,14 +50,6 @@ void IMIA4(void) | |||
52 | pfn_timer(); | 50 | pfn_timer(); |
53 | and_b(~0x01, &TSR4); /* clear the interrupt */ | 51 | and_b(~0x01, &TSR4); /* clear the interrupt */ |
54 | } | 52 | } |
55 | #elif defined CPU_COLDFIRE | ||
56 | void TIMER1(void) __attribute__ ((interrupt_handler)); | ||
57 | void TIMER1(void) | ||
58 | { | ||
59 | if (pfn_timer != NULL) | ||
60 | pfn_timer(); | ||
61 | TER1 = 0xff; /* clear all events */ | ||
62 | } | ||
63 | #elif defined(CPU_PP) | 53 | #elif defined(CPU_PP) |
64 | void TIMER2(void) | 54 | void TIMER2(void) |
65 | { | 55 | { |
@@ -82,21 +72,17 @@ void TIMER2(void) | |||
82 | 72 | ||
83 | static bool timer_set(long cycles, bool start) | 73 | static bool timer_set(long cycles, bool start) |
84 | { | 74 | { |
85 | #if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) | 75 | #if CONFIG_CPU == SH7034 |
86 | int phi = 0; /* bits for the prescaler */ | 76 | int phi = 0; /* bits for the prescaler */ |
87 | int prescale = 1; | 77 | int prescale = 1; |
88 | 78 | ||
89 | while (cycles > 0x10000) | 79 | while (cycles > 0x10000) |
90 | { /* work out the smallest prescaler that makes it fit */ | 80 | { /* work out the smallest prescaler that makes it fit */ |
91 | #if CONFIG_CPU == SH7034 | ||
92 | phi++; | 81 | phi++; |
93 | #endif | ||
94 | prescale <<= 1; | 82 | prescale <<= 1; |
95 | cycles >>= 1; | 83 | cycles >>= 1; |
96 | } | 84 | } |
97 | #endif | ||
98 | 85 | ||
99 | #if CONFIG_CPU == SH7034 | ||
100 | if (prescale > 8) | 86 | if (prescale > 8) |
101 | return false; | 87 | return false; |
102 | 88 | ||
@@ -122,44 +108,6 @@ static bool timer_set(long cycles, bool start) | |||
122 | and_b(~0x01, &TSR4); /* clear an eventual interrupt */ | 108 | and_b(~0x01, &TSR4); /* clear an eventual interrupt */ |
123 | 109 | ||
124 | return true; | 110 | return true; |
125 | #elif defined CPU_COLDFIRE | ||
126 | if (prescale > 4096/CPUFREQ_MAX_MULT) | ||
127 | return false; | ||
128 | |||
129 | if (prescale > 256/CPUFREQ_MAX_MULT) | ||
130 | { | ||
131 | phi = 0x05; /* prescale sysclk/16, timer enabled */ | ||
132 | prescale >>= 4; | ||
133 | } | ||
134 | else | ||
135 | phi = 0x03; /* prescale sysclk, timer enabled */ | ||
136 | |||
137 | base_prescale = prescale; | ||
138 | prescale *= (cpu_frequency / CPU_FREQ); | ||
139 | |||
140 | if (start) | ||
141 | { | ||
142 | if (pfn_unregister != NULL) | ||
143 | { | ||
144 | pfn_unregister(); | ||
145 | pfn_unregister = NULL; | ||
146 | } | ||
147 | phi &= ~1; /* timer disabled at start */ | ||
148 | |||
149 | /* If it is already enabled, writing a 0 to the RST bit will clear | ||
150 | the register, so we clear RST explicitly before writing the real | ||
151 | data. */ | ||
152 | TMR1 = 0; | ||
153 | } | ||
154 | |||
155 | /* We are using timer 1 */ | ||
156 | TMR1 = 0x0018 | (unsigned short)phi | ((unsigned short)(prescale - 1) << 8); | ||
157 | TRR1 = (unsigned short)(cycles - 1); | ||
158 | if (start || (TCN1 >= TRR1)) | ||
159 | TCN1 = 0; /* reset the timer */ | ||
160 | TER1 = 0xff; /* clear all events */ | ||
161 | |||
162 | return true; | ||
163 | #elif defined(CPU_PP) | 111 | #elif defined(CPU_PP) |
164 | if (cycles > 0x20000000 || cycles < 2) | 112 | if (cycles > 0x20000000 || cycles < 2) |
165 | return false; | 113 | return false; |
@@ -185,25 +133,6 @@ static bool timer_set(long cycles, bool start) | |||
185 | #endif /* CONFIG_CPU */ | 133 | #endif /* CONFIG_CPU */ |
186 | } | 134 | } |
187 | 135 | ||
188 | #ifdef CPU_COLDFIRE | ||
189 | void timers_adjust_prescale(int multiplier, bool enable_irq) | ||
190 | { | ||
191 | /* tick timer */ | ||
192 | TMR0 = (TMR0 & 0x00ef) | ||
193 | | ((unsigned short)(multiplier - 1) << 8) | ||
194 | | (enable_irq ? 0x10 : 0); | ||
195 | |||
196 | if (pfn_timer) | ||
197 | { | ||
198 | /* user timer */ | ||
199 | int prescale = base_prescale * multiplier; | ||
200 | TMR1 = (TMR1 & 0x00ef) | ||
201 | | ((unsigned short)(prescale - 1) << 8) | ||
202 | | (enable_irq ? 0x10 : 0); | ||
203 | } | ||
204 | } | ||
205 | #endif | ||
206 | |||
207 | /* Register a user timer, called every <cycles> TIMER_FREQ cycles */ | 136 | /* Register a user timer, called every <cycles> TIMER_FREQ cycles */ |
208 | bool timer_register(int reg_prio, void (*unregister_callback)(void), | 137 | bool timer_register(int reg_prio, void (*unregister_callback)(void), |
209 | long cycles, int int_prio, void (*timer_callback)(void) | 138 | long cycles, int int_prio, void (*timer_callback)(void) |
@@ -228,11 +157,6 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), | |||
228 | IPRD = (IPRD & 0xFF0F) | int_prio << 4; /* interrupt priority */ | 157 | IPRD = (IPRD & 0xFF0F) | int_prio << 4; /* interrupt priority */ |
229 | or_b(0x10, &TSTR); /* start timer 4 */ | 158 | or_b(0x10, &TSTR); /* start timer 4 */ |
230 | return true; | 159 | return true; |
231 | #elif defined CPU_COLDFIRE | ||
232 | ICR2 = 0x90; /* interrupt on level 4.0 */ | ||
233 | and_l(~(1<<10), &IMR); | ||
234 | TMR1 |= 1; /* start timer */ | ||
235 | return true; | ||
236 | #elif defined(CPU_PP) | 160 | #elif defined(CPU_PP) |
237 | /* unmask interrupt source */ | 161 | /* unmask interrupt source */ |
238 | #if NUM_CORES > 1 | 162 | #if NUM_CORES > 1 |
@@ -264,9 +188,6 @@ void timer_unregister(void) | |||
264 | #if CONFIG_CPU == SH7034 | 188 | #if CONFIG_CPU == SH7034 |
265 | and_b(~0x10, &TSTR); /* stop the timer 4 */ | 189 | and_b(~0x10, &TSTR); /* stop the timer 4 */ |
266 | IPRD = (IPRD & 0xFF0F); /* disable interrupt */ | 190 | IPRD = (IPRD & 0xFF0F); /* disable interrupt */ |
267 | #elif defined CPU_COLDFIRE | ||
268 | TMR1 = 0; /* disable timer 1 */ | ||
269 | or_l((1<<10), &IMR); /* disable interrupt */ | ||
270 | #elif defined(CPU_PP) | 191 | #elif defined(CPU_PP) |
271 | TIMER2_CFG = 0; /* stop timer 2 */ | 192 | TIMER2_CFG = 0; /* stop timer 2 */ |
272 | CPU_INT_DIS = TIMER2_MASK; | 193 | CPU_INT_DIS = TIMER2_MASK; |