summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-10-03 09:24:36 +0000
committerJens Arnold <amiconn@rockbox.org>2005-10-03 09:24:36 +0000
commitcfb073c452c0218a82e23fb5f5f89043719f2c07 (patch)
tree5aff8555b218e10037c086aaad3aaec1b4d677c8 /firmware
parent7190cf2ed9cfa854d81e7bf9c0e8a1ef71935c1f (diff)
downloadrockbox-cfb073c452c0218a82e23fb5f5f89043719f2c07.tar.gz
rockbox-cfb073c452c0218a82e23fb5f5f89043719f2c07.zip
Coldfire: New timer handling on CPU frequency change, adjusting the prescaler on the fly, for both tick and user timer. Precondition is that the higher frequencies are integer multiples of the base: now NORMAL is 45 MHz and MAX is 124 MHz. Removes the need for applications with longer timer periods (>= 10 ms) to boost the CPU all the time, e.g. the grayscale lib. Timer counts are now always based on the base frequency (CPU_FREQ). * Adjusted the RAM refresh timers to the new frequencies (all frequencies for H100) * All: Fixed the tick timer count being off by one.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7576 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/backlight.c2
-rw-r--r--firmware/export/system.h15
-rw-r--r--firmware/export/timer.h3
-rw-r--r--firmware/kernel.c26
-rw-r--r--firmware/system.c37
-rw-r--r--firmware/timer.c32
6 files changed, 78 insertions, 37 deletions
diff --git a/firmware/backlight.c b/firmware/backlight.c
index 675237157b..ecd4403d88 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -81,7 +81,7 @@ static void backlight_isr(void)
81 int timer_period; 81 int timer_period;
82 bool idle = false; 82 bool idle = false;
83 83
84 timer_period = FREQ / 1000 * BL_PWM_INTERVAL / 1000; 84 timer_period = CPU_FREQ / 1000 * BL_PWM_INTERVAL / 1000;
85 switch (bl_dim_state) 85 switch (bl_dim_state)
86 { 86 {
87 /* New cycle */ 87 /* New cycle */
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 58e6570d3a..c2246e1e70 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -257,14 +257,17 @@ static inline unsigned long SWAB32(unsigned long value)
257static inline void invalidate_icache(void) 257static inline void invalidate_icache(void)
258{ 258{
259 asm volatile ("move.l #0x01000000,%d0\n" 259 asm volatile ("move.l #0x01000000,%d0\n"
260 "movec.l %d0,%cacr\n" 260 "movec.l %d0,%cacr\n"
261 "move.l #0x80000000,%d0\n" 261 "move.l #0x80000000,%d0\n"
262 "movec.l %d0,%cacr"); 262 "movec.l %d0,%cacr");
263} 263}
264 264
265#define CPUFREQ_DEFAULT CPU_FREQ 265#define CPUFREQ_DEFAULT_MULT 1
266#define CPUFREQ_NORMAL 47980800 266#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ)
267#define CPUFREQ_MAX 119952000 267#define CPUFREQ_NORMAL_MULT 4
268#define CPUFREQ_NORMAL (CPUFREQ_NORMAL_MULT * CPU_FREQ)
269#define CPUFREQ_MAX_MULT 11
270#define CPUFREQ_MAX (CPUFREQ_MAX_MULT * CPU_FREQ)
268 271
269#elif CONFIG_CPU == TCC730 272#elif CONFIG_CPU == TCC730
270 273
diff --git a/firmware/export/timer.h b/firmware/export/timer.h
index 73936ca28c..afd60ac66c 100644
--- a/firmware/export/timer.h
+++ b/firmware/export/timer.h
@@ -28,6 +28,9 @@
28bool timer_register(int reg_prio, void (*unregister_callback)(void), 28bool timer_register(int reg_prio, void (*unregister_callback)(void),
29 long cycles, int int_prio, void (*timer_callback)(void)); 29 long cycles, int int_prio, void (*timer_callback)(void));
30bool timer_set_period(long cycles); 30bool timer_set_period(long cycles);
31#ifdef CPU_COLDFIRE
32void timers_adjust_prescale(int multiplier, bool enable_irq);
33#endif
31void timer_unregister(void); 34void timer_unregister(void);
32 35
33#endif /* !SIMULATOR */ 36#endif /* !SIMULATOR */
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 44927cd1c3..ee4e37e50d 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -156,11 +156,11 @@ int queue_broadcast(long id, void *data)
156#if CONFIG_CPU == SH7034 156#if CONFIG_CPU == SH7034
157void tick_start(unsigned int interval_in_ms) 157void tick_start(unsigned int interval_in_ms)
158{ 158{
159 unsigned int count; 159 unsigned long count;
160 160
161 count = FREQ * interval_in_ms / 1000 / 8; 161 count = CPU_FREQ * interval_in_ms / 1000 / 8;
162 162
163 if(count > 0xffff) 163 if(count > 0x10000)
164 { 164 {
165 panicf("Error! The tick interval is too long (%d ms)\n", 165 panicf("Error! The tick interval is too long (%d ms)\n",
166 interval_in_ms); 166 interval_in_ms);
@@ -174,7 +174,7 @@ void tick_start(unsigned int interval_in_ms)
174 TMDR &= ~0x01; /* Operate normally */ 174 TMDR &= ~0x01; /* Operate normally */
175 175
176 TCNT0 = 0; /* Start counting at 0 */ 176 TCNT0 = 0; /* Start counting at 0 */
177 GRA0 = count; 177 GRA0 = (unsigned short)(count - 1);
178 TCR0 = 0x23; /* Clear at GRA match, sysclock/8 */ 178 TCR0 = 0x23; /* Clear at GRA match, sysclock/8 */
179 179
180 /* Enable interrupt on level 1 */ 180 /* Enable interrupt on level 1 */
@@ -186,7 +186,7 @@ void tick_start(unsigned int interval_in_ms)
186 TSTR |= 0x01; /* Start timer 1 */ 186 TSTR |= 0x01; /* Start timer 1 */
187} 187}
188 188
189#pragma interrupt 189void IMIA0(void) __attribute__ ((interrupt_handler));
190void IMIA0(void) 190void IMIA0(void)
191{ 191{
192 int i; 192 int i;
@@ -208,22 +208,28 @@ void IMIA0(void)
208#elif defined(CPU_COLDFIRE) 208#elif defined(CPU_COLDFIRE)
209void tick_start(unsigned int interval_in_ms) 209void tick_start(unsigned int interval_in_ms)
210{ 210{
211 unsigned int count; 211 unsigned long count;
212 int prescale;
212 213
213 count = FREQ/2 * interval_in_ms / 1000 / 16; 214 count = CPU_FREQ/2 * interval_in_ms / 1000 / 16;
214 215
215 if(count > 0xffff) 216 if(count > 0x10000)
216 { 217 {
217 panicf("Error! The tick interval is too long (%d ms)\n", 218 panicf("Error! The tick interval is too long (%d ms)\n",
218 interval_in_ms); 219 interval_in_ms);
219 return; 220 return;
220 } 221 }
222
223 prescale = cpu_frequency / CPU_FREQ;
224 /* Note: The prescaler is later adjusted on-the-fly on CPU frequency
225 changes within timer.c */
221 226
222 /* We are using timer 0 */ 227 /* We are using timer 0 */
223 228
224 TRR0 = count; /* The reference count */ 229 TRR0 = (unsigned short)(count - 1); /* The reference count */
225 TCN0 = 0; /* reset the timer */ 230 TCN0 = 0; /* reset the timer */
226 TMR0 = 0x001d; /* no prescaler, restart, CLK/16, enabled */ 231 TMR0 = 0x001d | ((unsigned short)(prescale - 1) << 8);
232 /* restart, CLK/16, enabled, prescaler */
227 233
228 TER0 = 0xff; /* Clear all events */ 234 TER0 = 0xff; /* Clear all events */
229 235
diff --git a/firmware/system.c b/firmware/system.c
index 20dc7c5241..e2b4efca21 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -23,6 +23,7 @@
23#include "font.h" 23#include "font.h"
24#include "system.h" 24#include "system.h"
25#include "kernel.h" 25#include "kernel.h"
26#include "timer.h"
26 27
27#ifndef SIMULATOR 28#ifndef SIMULATOR
28long cpu_frequency = CPU_FREQ; 29long cpu_frequency = CPU_FREQ;
@@ -503,11 +504,13 @@ void system_init(void)
503} 504}
504 505
505#ifdef IRIVER_H100 506#ifdef IRIVER_H100
506#define MAX_REFRESH_TIMER 56 507#define MAX_REFRESH_TIMER 59
507#define NORMAL_REFRESH_TIMER 20 508#define NORMAL_REFRESH_TIMER 21
509#define DEFAULT_REFRESH_TIMER 4
508#else 510#else
509#define MAX_REFRESH_TIMER 28 511#define MAX_REFRESH_TIMER 29
510#define NORMAL_REFRESH_TIMER 10 512#define NORMAL_REFRESH_TIMER 10
513#define DEFAULT_REFRESH_TIMER 1
511#endif 514#endif
512 515
513void set_cpu_frequency (long) __attribute__ ((section (".icode"))); 516void set_cpu_frequency (long) __attribute__ ((section (".icode")));
@@ -516,44 +519,46 @@ void set_cpu_frequency(long frequency)
516 switch(frequency) 519 switch(frequency)
517 { 520 {
518 case CPUFREQ_MAX: 521 case CPUFREQ_MAX:
519 DCR = (DCR & ~0x01ff) | 1; /* Refresh timer for bypass 522 DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
520 frequency */ 523 /* Refresh timer for bypass frequency */
521 PLLCR &= ~1; /* Bypass mode */ 524 PLLCR &= ~1; /* Bypass mode */
522 PLLCR = 0x11853005; 525 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
526 PLLCR = 0x11856005;
523 CSCR0 = 0x00000980; /* Flash: 2 wait state */ 527 CSCR0 = 0x00000980; /* Flash: 2 wait state */
524 CSCR1 = 0x00000980; /* LCD: 2 wait states */ 528 CSCR1 = 0x00000980; /* LCD: 2 wait states */
525 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. 529 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
526 This may take up to 10ms! */ 530 This may take up to 10ms! */
531 timers_adjust_prescale(CPUFREQ_MAX_MULT, true);
527 DCR = (DCR & ~0x01ff) | MAX_REFRESH_TIMER; /* Refresh timer */ 532 DCR = (DCR & ~0x01ff) | MAX_REFRESH_TIMER; /* Refresh timer */
528 cpu_frequency = CPUFREQ_MAX; 533 cpu_frequency = CPUFREQ_MAX;
529 tick_start(1000/HZ);
530 IDECONFIG1 = 0x106000 | (5 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */ 534 IDECONFIG1 = 0x106000 | (5 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */
531 IDECONFIG2 = 0x40000 | (1 << 8); /* TA enable + CS2wait */ 535 IDECONFIG2 = 0x40000 | (1 << 8); /* TA enable + CS2wait */
532 break; 536 break;
533 537
534 case CPUFREQ_NORMAL: 538 case CPUFREQ_NORMAL:
535 DCR = (DCR & ~0x01ff) | 1; /* Refresh timer for bypass 539 DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
536 frequency */ 540 /* Refresh timer for bypass frequency */
537 PLLCR &= ~1; /* Bypass mode */ 541 PLLCR &= ~1; /* Bypass mode */
538 PLLCR = 0x10886001; 542 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
543 PLLCR = 0x1385e005;
539 CSCR0 = 0x00000180; /* Flash: 0 wait states */ 544 CSCR0 = 0x00000180; /* Flash: 0 wait states */
540 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 545 CSCR1 = 0x00000180; /* LCD: 0 wait states */
541 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. 546 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
542 This may take up to 10ms! */ 547 This may take up to 10ms! */
548 timers_adjust_prescale(CPUFREQ_NORMAL_MULT, true);
543 DCR = (DCR & ~0x01ff) | NORMAL_REFRESH_TIMER; /* Refresh timer */ 549 DCR = (DCR & ~0x01ff) | NORMAL_REFRESH_TIMER; /* Refresh timer */
544 cpu_frequency = CPUFREQ_NORMAL; 550 cpu_frequency = CPUFREQ_NORMAL;
545 tick_start(1000/HZ);
546 IDECONFIG1 = 0x106000 | (5 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */ 551 IDECONFIG1 = 0x106000 | (5 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */
547 IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */ 552 IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */
548 break; 553 break;
549 default: 554 default:
550 DCR = (DCR & ~0x01ff) | 1; /* Refresh timer for bypass 555 DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
551 frequency */ 556 /* Refresh timer for bypass frequency */
552 PLLCR = 0x00000000; /* Bypass mode */ 557 PLLCR = 0x00000000; /* Bypass mode */
558 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
553 CSCR0 = 0x00000180; /* Flash: 0 wait states */ 559 CSCR0 = 0x00000180; /* Flash: 0 wait states */
554 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 560 CSCR1 = 0x00000180; /* LCD: 0 wait states */
555 cpu_frequency = CPU_FREQ; 561 cpu_frequency = CPUFREQ_DEFAULT;
556 tick_start(1000/HZ);
557 IDECONFIG1 = 0x106000 | (1 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */ 562 IDECONFIG1 = 0x106000 | (1 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */
558 IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */ 563 IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */
559 break; 564 break;
diff --git a/firmware/timer.c b/firmware/timer.c
index 3e524ace35..8aff4eb6ee 100644
--- a/firmware/timer.c
+++ b/firmware/timer.c
@@ -28,7 +28,9 @@
28static int timer_prio = -1; 28static int timer_prio = -1;
29static void (*pfn_timer)(void) = NULL; /* timer callback */ 29static void (*pfn_timer)(void) = NULL; /* timer callback */
30static void (*pfn_unregister)(void) = NULL; /* unregister callback */ 30static void (*pfn_unregister)(void) = NULL; /* unregister callback */
31 31#ifdef CPU_COLDFIRE
32static int base_prescale;
33#endif
32 34
33/* interrupt handler */ 35/* interrupt handler */
34#if CONFIG_CPU == SH7034 36#if CONFIG_CPU == SH7034
@@ -93,16 +95,19 @@ static bool timer_set(long cycles, bool start)
93 and_b(~0x01, &TSR4); /* clear an eventual interrupt */ 95 and_b(~0x01, &TSR4); /* clear an eventual interrupt */
94 96
95#elif defined CPU_COLDFIRE 97#elif defined CPU_COLDFIRE
96 if (prescale > 4096) 98 if (prescale > 4096/CPUFREQ_MAX_MULT)
97 return false; 99 return false;
98 100
99 if (prescale > 256) 101 if (prescale > 256/CPUFREQ_MAX_MULT)
100 { 102 {
101 phi = 0x05; /* prescale sysclk/16, timer enabled */ 103 phi = 0x05; /* prescale sysclk/16, timer enabled */
102 prescale >>= 4; 104 prescale >>= 4;
103 } 105 }
104 else 106 else
105 phi = 0x03; /* prescale sysclk, timer enabled */ 107 phi = 0x03; /* prescale sysclk, timer enabled */
108
109 base_prescale = prescale;
110 prescale *= (cpu_frequency / CPU_FREQ);
106 111
107 if (start) 112 if (start)
108 { 113 {
@@ -125,7 +130,26 @@ static bool timer_set(long cycles, bool start)
125 return true; 130 return true;
126} 131}
127 132
128/* Register a user timer, called every <count> CPU cycles */ 133#ifdef CPU_COLDFIRE
134void timers_adjust_prescale(int multiplier, bool enable_irq)
135{
136 /* tick timer */
137 TMR0 = (TMR0 & 0x00ef)
138 | ((unsigned short)(multiplier - 1) << 8)
139 | (enable_irq ? 0x10 : 0);
140
141 if (pfn_timer)
142 {
143 /* user timer */
144 int prescale = base_prescale * multiplier;
145 TMR1 = (TMR1 & 0x00ef)
146 | ((unsigned short)(prescale - 1) << 8)
147 | (enable_irq ? 0x10 : 0);
148 }
149}
150#endif
151
152/* Register a user timer, called every <cycles> CPU_FREQ cycles */
129bool timer_register(int reg_prio, void (*unregister_callback)(void), 153bool timer_register(int reg_prio, void (*unregister_callback)(void),
130 long cycles, int int_prio, void (*timer_callback)(void)) 154 long cycles, int int_prio, void (*timer_callback)(void))
131{ 155{