Pop a stub in there for the e200 until playback is ready. Move it to the proper place...
[Rockbox.git] / firmware / system.c
bloba9c9d9e3505d7afa8bff2017e150d50b1a70f1ea
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Alan Korr
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdio.h>
20 #include "config.h"
21 #include <stdbool.h>
22 #include "lcd.h"
23 #include "font.h"
24 #include "system.h"
25 #include "kernel.h"
26 #include "timer.h"
27 #include "inttypes.h"
28 #include "string.h"
30 #ifndef SIMULATOR
31 long cpu_frequency = CPU_FREQ;
32 #endif
34 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
35 static int boost_counter = 0;
36 static bool cpu_idle = false;
38 int get_cpu_boost_counter(void)
40 return boost_counter;
42 #ifdef CPU_BOOST_LOGGING
43 #define MAX_BOOST_LOG 64
44 static char cpu_boost_calls[MAX_BOOST_LOG][MAX_PATH];
45 static int cpu_boost_first = 0;
46 static int cpu_boost_calls_count = 0;
47 static int cpu_boost_track_message = 0;
48 int cpu_boost_log_getcount(void)
50 return cpu_boost_calls_count;
52 char * cpu_boost_log_getlog_first(void)
54 if (cpu_boost_calls_count)
56 cpu_boost_track_message = 1;
57 return cpu_boost_calls[cpu_boost_first];
59 else return NULL;
61 char * cpu_boost_log_getlog_next(void)
63 int message = (cpu_boost_track_message+cpu_boost_first)%MAX_BOOST_LOG;
64 if (cpu_boost_track_message < cpu_boost_calls_count)
66 cpu_boost_track_message++;
67 return cpu_boost_calls[message];
69 else return NULL;
71 void cpu_boost_(bool on_off, char* location, int line)
73 if (cpu_boost_calls_count == MAX_BOOST_LOG)
75 cpu_boost_first = (cpu_boost_first+1)%MAX_BOOST_LOG;
76 cpu_boost_calls_count--;
77 if (cpu_boost_calls_count < 0)
78 cpu_boost_calls_count = 0;
80 if (cpu_boost_calls_count < MAX_BOOST_LOG)
82 int message = (cpu_boost_first+cpu_boost_calls_count)%MAX_BOOST_LOG;
83 snprintf(cpu_boost_calls[message], MAX_PATH,
84 "%c %s:%d",on_off==true?'B':'U',location,line);
85 cpu_boost_calls_count++;
87 #else
88 void cpu_boost(bool on_off)
90 #endif
91 if(on_off)
93 /* Boost the frequency if not already boosted */
94 if(boost_counter++ == 0)
95 set_cpu_frequency(CPUFREQ_MAX);
97 else
99 /* Lower the frequency if the counter reaches 0 */
100 if(--boost_counter == 0)
102 if(cpu_idle)
103 set_cpu_frequency(CPUFREQ_DEFAULT);
104 else
105 set_cpu_frequency(CPUFREQ_NORMAL);
108 /* Safety measure */
109 if(boost_counter < 0)
110 boost_counter = 0;
114 void cpu_idle_mode(bool on_off)
116 cpu_idle = on_off;
118 /* We need to adjust the frequency immediately if the CPU
119 isn't boosted */
120 if(boost_counter == 0)
122 if(cpu_idle)
123 set_cpu_frequency(CPUFREQ_DEFAULT);
124 else
125 set_cpu_frequency(CPUFREQ_NORMAL);
128 #endif /* HAVE_ADJUSTABLE_CPU_FREQ */
131 #ifdef HAVE_FLASHED_ROCKBOX
132 static bool detect_flash_header(uint8_t *addr)
134 #ifndef BOOTLOADER
135 int oldmode = system_memory_guard(MEMGUARD_NONE);
136 #endif
137 struct flash_header hdr;
138 memcpy(&hdr, addr, sizeof(struct flash_header));
139 #ifndef BOOTLOADER
140 system_memory_guard(oldmode);
141 #endif
142 return hdr.magic == FLASH_MAGIC;
144 #endif
146 bool detect_flashed_romimage(void)
148 #ifdef HAVE_FLASHED_ROCKBOX
149 return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY);
150 #else
151 return false;
152 #endif /* HAVE_FLASHED_ROCKBOX */
155 bool detect_flashed_ramimage(void)
157 #ifdef HAVE_FLASHED_ROCKBOX
158 return detect_flash_header((uint8_t *)FLASH_RAMIMAGE_ENTRY);
159 #else
160 return false;
161 #endif /* HAVE_FLASHED_ROCKBOX */
164 bool detect_original_firmware(void)
166 return !(detect_flashed_ramimage() || detect_flashed_romimage());
169 #if CONFIG_CPU == SH7034
170 #include "led.h"
171 #include "system.h"
172 #include "rolo.h"
174 static const char* const irqname[] = {
175 "", "", "", "", "IllInstr", "", "IllSltIn","","",
176 "CPUAdrEr", "DMAAdrEr", "NMI", "UserBrk",
177 "","","","","","","","","","","","","","","","","","","",
178 "Trap32","Trap33","Trap34","Trap35","Trap36","Trap37","Trap38","Trap39",
179 "Trap40","Trap41","Trap42","Trap43","Trap44","Trap45","Trap46","Trap47",
180 "Trap48","Trap49","Trap50","Trap51","Trap52","Trap53","Trap54","Trap55",
181 "Trap56","Trap57","Trap58","Trap59","Trap60","Trap61","Trap62","Trap63",
182 "Irq0","Irq1","Irq2","Irq3","Irq4","Irq5","Irq6","Irq7",
183 "Dma0","","Dma1","","Dma2","","Dma3","",
184 "IMIA0","IMIB0","OVI0","", "IMIA1","IMIB1","OVI1","",
185 "IMIA2","IMIB2","OVI2","", "IMIA3","IMIB3","OVI3","",
186 "IMIA4","IMIB4","OVI4","",
187 "Ser0Err","Ser0Rx","Ser0Tx","Ser0TE",
188 "Ser1Err","Ser1Rx","Ser1Tx","Ser1TE",
189 "ParityEr","A/D conv","","","Watchdog","DRAMRefr"
192 #define RESERVE_INTERRUPT(number) "\t.long\t_UIE" #number "\n"
193 #define DEFAULT_INTERRUPT(name, number) "\t.weak\t_" #name \
194 "\n\t.set\t_" #name ",_UIE" #number \
195 "\n\t.long\t_" #name "\n"
197 asm (
199 /* Vector table.
200 * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols
201 * defined in an asm block -- silly.
202 * Reset vectors (0..3) are handled in crt0.S */
204 ".section\t.vectors,\"aw\",@progbits\n"
205 DEFAULT_INTERRUPT (GII, 4)
206 RESERVE_INTERRUPT ( 5)
207 DEFAULT_INTERRUPT (ISI, 6)
208 RESERVE_INTERRUPT ( 7)
209 RESERVE_INTERRUPT ( 8)
210 DEFAULT_INTERRUPT (CPUAE, 9)
211 DEFAULT_INTERRUPT (DMAAE, 10)
212 DEFAULT_INTERRUPT (NMI, 11)
213 DEFAULT_INTERRUPT (UB, 12)
214 RESERVE_INTERRUPT ( 13)
215 RESERVE_INTERRUPT ( 14)
216 RESERVE_INTERRUPT ( 15)
217 RESERVE_INTERRUPT ( 16) /* TCB #0 */
218 RESERVE_INTERRUPT ( 17) /* TCB #1 */
219 RESERVE_INTERRUPT ( 18) /* TCB #2 */
220 RESERVE_INTERRUPT ( 19) /* TCB #3 */
221 RESERVE_INTERRUPT ( 20) /* TCB #4 */
222 RESERVE_INTERRUPT ( 21) /* TCB #5 */
223 RESERVE_INTERRUPT ( 22) /* TCB #6 */
224 RESERVE_INTERRUPT ( 23) /* TCB #7 */
225 RESERVE_INTERRUPT ( 24) /* TCB #8 */
226 RESERVE_INTERRUPT ( 25) /* TCB #9 */
227 RESERVE_INTERRUPT ( 26) /* TCB #10 */
228 RESERVE_INTERRUPT ( 27) /* TCB #11 */
229 RESERVE_INTERRUPT ( 28) /* TCB #12 */
230 RESERVE_INTERRUPT ( 29) /* TCB #13 */
231 RESERVE_INTERRUPT ( 30) /* TCB #14 */
232 RESERVE_INTERRUPT ( 31) /* TCB #15 */
233 DEFAULT_INTERRUPT (TRAPA32, 32)
234 DEFAULT_INTERRUPT (TRAPA33, 33)
235 DEFAULT_INTERRUPT (TRAPA34, 34)
236 DEFAULT_INTERRUPT (TRAPA35, 35)
237 DEFAULT_INTERRUPT (TRAPA36, 36)
238 DEFAULT_INTERRUPT (TRAPA37, 37)
239 DEFAULT_INTERRUPT (TRAPA38, 38)
240 DEFAULT_INTERRUPT (TRAPA39, 39)
241 DEFAULT_INTERRUPT (TRAPA40, 40)
242 DEFAULT_INTERRUPT (TRAPA41, 41)
243 DEFAULT_INTERRUPT (TRAPA42, 42)
244 DEFAULT_INTERRUPT (TRAPA43, 43)
245 DEFAULT_INTERRUPT (TRAPA44, 44)
246 DEFAULT_INTERRUPT (TRAPA45, 45)
247 DEFAULT_INTERRUPT (TRAPA46, 46)
248 DEFAULT_INTERRUPT (TRAPA47, 47)
249 DEFAULT_INTERRUPT (TRAPA48, 48)
250 DEFAULT_INTERRUPT (TRAPA49, 49)
251 DEFAULT_INTERRUPT (TRAPA50, 50)
252 DEFAULT_INTERRUPT (TRAPA51, 51)
253 DEFAULT_INTERRUPT (TRAPA52, 52)
254 DEFAULT_INTERRUPT (TRAPA53, 53)
255 DEFAULT_INTERRUPT (TRAPA54, 54)
256 DEFAULT_INTERRUPT (TRAPA55, 55)
257 DEFAULT_INTERRUPT (TRAPA56, 56)
258 DEFAULT_INTERRUPT (TRAPA57, 57)
259 DEFAULT_INTERRUPT (TRAPA58, 58)
260 DEFAULT_INTERRUPT (TRAPA59, 59)
261 DEFAULT_INTERRUPT (TRAPA60, 60)
262 DEFAULT_INTERRUPT (TRAPA61, 61)
263 DEFAULT_INTERRUPT (TRAPA62, 62)
264 DEFAULT_INTERRUPT (TRAPA63, 63)
265 DEFAULT_INTERRUPT (IRQ0, 64)
266 DEFAULT_INTERRUPT (IRQ1, 65)
267 DEFAULT_INTERRUPT (IRQ2, 66)
268 DEFAULT_INTERRUPT (IRQ3, 67)
269 DEFAULT_INTERRUPT (IRQ4, 68)
270 DEFAULT_INTERRUPT (IRQ5, 69)
271 DEFAULT_INTERRUPT (IRQ6, 70)
272 DEFAULT_INTERRUPT (IRQ7, 71)
273 DEFAULT_INTERRUPT (DEI0, 72)
274 RESERVE_INTERRUPT ( 73)
275 DEFAULT_INTERRUPT (DEI1, 74)
276 RESERVE_INTERRUPT ( 75)
277 DEFAULT_INTERRUPT (DEI2, 76)
278 RESERVE_INTERRUPT ( 77)
279 DEFAULT_INTERRUPT (DEI3, 78)
280 RESERVE_INTERRUPT ( 79)
281 DEFAULT_INTERRUPT (IMIA0, 80)
282 DEFAULT_INTERRUPT (IMIB0, 81)
283 DEFAULT_INTERRUPT (OVI0, 82)
284 RESERVE_INTERRUPT ( 83)
285 DEFAULT_INTERRUPT (IMIA1, 84)
286 DEFAULT_INTERRUPT (IMIB1, 85)
287 DEFAULT_INTERRUPT (OVI1, 86)
288 RESERVE_INTERRUPT ( 87)
289 DEFAULT_INTERRUPT (IMIA2, 88)
290 DEFAULT_INTERRUPT (IMIB2, 89)
291 DEFAULT_INTERRUPT (OVI2, 90)
292 RESERVE_INTERRUPT ( 91)
293 DEFAULT_INTERRUPT (IMIA3, 92)
294 DEFAULT_INTERRUPT (IMIB3, 93)
295 DEFAULT_INTERRUPT (OVI3, 94)
296 RESERVE_INTERRUPT ( 95)
297 DEFAULT_INTERRUPT (IMIA4, 96)
298 DEFAULT_INTERRUPT (IMIB4, 97)
299 DEFAULT_INTERRUPT (OVI4, 98)
300 RESERVE_INTERRUPT ( 99)
301 DEFAULT_INTERRUPT (REI0, 100)
302 DEFAULT_INTERRUPT (RXI0, 101)
303 DEFAULT_INTERRUPT (TXI0, 102)
304 DEFAULT_INTERRUPT (TEI0, 103)
305 DEFAULT_INTERRUPT (REI1, 104)
306 DEFAULT_INTERRUPT (RXI1, 105)
307 DEFAULT_INTERRUPT (TXI1, 106)
308 DEFAULT_INTERRUPT (TEI1, 107)
309 RESERVE_INTERRUPT ( 108)
310 DEFAULT_INTERRUPT (ADITI, 109)
312 /* UIE# block.
313 * Must go into the same section as the UIE() handler */
315 "\t.text\n"
316 "_UIE4:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
317 "_UIE5:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
318 "_UIE6:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
319 "_UIE7:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
320 "_UIE8:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
321 "_UIE9:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
322 "_UIE10:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
323 "_UIE11:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
324 "_UIE12:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
325 "_UIE13:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
326 "_UIE14:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
327 "_UIE15:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
328 "_UIE16:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
329 "_UIE17:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
330 "_UIE18:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
331 "_UIE19:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
332 "_UIE20:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
333 "_UIE21:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
334 "_UIE22:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
335 "_UIE23:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
336 "_UIE24:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
337 "_UIE25:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
338 "_UIE26:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
339 "_UIE27:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
340 "_UIE28:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
341 "_UIE29:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
342 "_UIE30:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
343 "_UIE31:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
344 "_UIE32:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
345 "_UIE33:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
346 "_UIE34:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
347 "_UIE35:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
348 "_UIE36:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
349 "_UIE37:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
350 "_UIE38:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
351 "_UIE39:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
352 "_UIE40:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
353 "_UIE41:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
354 "_UIE42:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
355 "_UIE43:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
356 "_UIE44:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
357 "_UIE45:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
358 "_UIE46:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
359 "_UIE47:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
360 "_UIE48:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
361 "_UIE49:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
362 "_UIE50:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
363 "_UIE51:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
364 "_UIE52:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
365 "_UIE53:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
366 "_UIE54:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
367 "_UIE55:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
368 "_UIE56:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
369 "_UIE57:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
370 "_UIE58:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
371 "_UIE59:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
372 "_UIE60:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
373 "_UIE61:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
374 "_UIE62:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
375 "_UIE63:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
376 "_UIE64:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
377 "_UIE65:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
378 "_UIE66:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
379 "_UIE67:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
380 "_UIE68:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
381 "_UIE69:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
382 "_UIE70:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
383 "_UIE71:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
384 "_UIE72:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
385 "_UIE73:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
386 "_UIE74:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
387 "_UIE75:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
388 "_UIE76:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
389 "_UIE77:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
390 "_UIE78:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
391 "_UIE79:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
392 "_UIE80:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
393 "_UIE81:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
394 "_UIE82:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
395 "_UIE83:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
396 "_UIE84:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
397 "_UIE85:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
398 "_UIE86:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
399 "_UIE87:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
400 "_UIE88:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
401 "_UIE89:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
402 "_UIE90:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
403 "_UIE91:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
404 "_UIE92:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
405 "_UIE93:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
406 "_UIE94:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
407 "_UIE95:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
408 "_UIE96:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
409 "_UIE97:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
410 "_UIE98:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
411 "_UIE99:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
412 "_UIE100:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
413 "_UIE101:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
414 "_UIE102:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
415 "_UIE103:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
416 "_UIE104:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
417 "_UIE105:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
418 "_UIE106:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
419 "_UIE107:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
420 "_UIE108:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
421 "_UIE109:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
425 extern void UIE4(void); /* needed for calculating the UIE number */
427 void UIE (unsigned int pc) __attribute__((section(".text")));
428 void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
430 #if CONFIG_LED == LED_REAL
431 bool state = false;
432 int i = 0;
433 #endif
434 unsigned int n;
435 char str[32];
437 asm volatile ("sts\tpr,%0" : "=r"(n));
439 /* clear screen */
440 lcd_clear_display ();
441 #ifdef HAVE_LCD_BITMAP
442 lcd_setfont(FONT_SYSFIXED);
443 #endif
444 /* output exception */
445 n = (n - (unsigned)UIE4 + 12)>>2; /* get exception or interrupt number */
446 snprintf(str,sizeof(str),"I%02x:%s",n,irqname[n]);
447 lcd_puts(0,0,str);
448 snprintf(str,sizeof(str),"at %08x",pc);
449 lcd_puts(0,1,str);
451 #ifdef HAVE_LCD_BITMAP
452 lcd_update ();
453 #endif
455 while (1)
457 #if CONFIG_LED == LED_REAL
458 if (--i <= 0)
460 state = !state;
461 led(state);
462 i = 240000;
464 #endif
466 /* try to restart firmware if ON is pressed */
467 #if CONFIG_KEYPAD == PLAYER_PAD
468 if (!(PADRL & 0x20))
469 #elif CONFIG_KEYPAD == RECORDER_PAD
470 #ifdef HAVE_FMADC
471 if (!(PCDR & 0x0008))
472 #else
473 if (!(PBDRH & 0x01))
474 #endif
475 #elif CONFIG_KEYPAD == ONDIO_PAD
476 if (!(PCDR & 0x0008))
477 #endif
479 /* enable the watchguard timer, but don't service it */
480 RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */
481 TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */
486 void system_init(void)
488 /* Disable all interrupts */
489 IPRA = 0;
490 IPRB = 0;
491 IPRC = 0;
492 IPRD = 0;
493 IPRE = 0;
495 /* NMI level low, falling edge on all interrupts */
496 ICR = 0;
498 /* Enable burst and RAS down mode on DRAM */
499 DCR |= 0x5000;
501 /* Activate Warp mode (simultaneous internal and external mem access) */
502 BCR |= 0x2000;
504 /* Bus state controller initializations. These are only necessary when
505 running from flash. */
506 WCR1 = 0x40FD; /* Long wait states for CS6 (ATA), short for the rest. */
507 WCR3 = 0x8000; /* WAIT is pulled up, 1 state inserted for CS6 */
510 void system_reboot (void)
512 set_irq_level(HIGHEST_IRQ_LEVEL);
514 asm volatile ("ldc\t%0,vbr" : : "r"(0));
516 PACR2 |= 0x4000; /* for coldstart detection */
517 IPRA = 0;
518 IPRB = 0;
519 IPRC = 0;
520 IPRD = 0;
521 IPRE = 0;
522 ICR = 0;
524 asm volatile ("jmp @%0; mov.l @%1,r15" : :
525 "r"(*(int*)0),"r"(4));
528 /* Utilise the user break controller to catch invalid memory accesses. */
529 int system_memory_guard(int newmode)
531 static const struct {
532 unsigned long addr;
533 unsigned long mask;
534 unsigned short bbr;
535 } modes[MAXMEMGUARD] = {
536 /* catch nothing */
537 { 0x00000000, 0x00000000, 0x0000 },
538 /* catch writes to area 02 (flash ROM) */
539 { 0x02000000, 0x00FFFFFF, 0x00F8 },
540 /* catch all accesses to areas 00 (internal ROM) and 01 (free) */
541 { 0x00000000, 0x01FFFFFF, 0x00FC }
544 int oldmode = MEMGUARD_NONE;
545 int i;
547 /* figure out the old mode from what is in the UBC regs. If the register
548 values don't match any mode, assume MEMGUARD_NONE */
549 for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++)
551 if (BAR == modes[i].addr && BAMR == modes[i].mask &&
552 BBR == modes[i].bbr)
554 oldmode = i;
555 break;
559 if (newmode == MEMGUARD_KEEP)
560 newmode = oldmode;
562 BBR = 0; /* switch off everything first */
564 /* always set the UBC according to the mode, in case the old settings
565 didn't match any valid mode */
566 BAR = modes[newmode].addr;
567 BAMR = modes[newmode].mask;
568 BBR = modes[newmode].bbr;
570 return oldmode;
572 #elif defined(CPU_ARM)
574 static const char* const uiename[] = {
575 "Undefined instruction", "Prefetch abort", "Data abort"
578 /* Unexpected Interrupt or Exception handler. Currently only deals with
579 exceptions, but will deal with interrupts later.
581 void UIE(unsigned int pc, unsigned int num)
583 char str[32];
585 lcd_clear_display();
586 #ifdef HAVE_LCD_BITMAP
587 lcd_setfont(FONT_SYSFIXED);
588 #endif
589 lcd_puts(0, 0, uiename[num]);
590 snprintf(str, sizeof(str), "at %08x", pc);
591 lcd_puts(0, 1, str);
592 lcd_update();
594 while (1)
596 /* TODO: perhaps add button handling in here when we get a polling
597 driver some day.
602 #if CONFIG_CPU==PP5020 || CONFIG_CPU==PP5024
604 unsigned int ipod_hw_rev;
606 #ifndef BOOTLOADER
607 extern void TIMER1(void);
608 extern void TIMER2(void);
610 #if defined(IPOD_MINI) /* mini 1 only, mini 2G uses iPod 4G code */
611 extern void ipod_mini_button_int(void);
613 void irq(void)
615 if(CURRENT_CORE == CPU)
617 if (CPU_INT_STAT & TIMER1_MASK)
618 TIMER1();
619 else if (CPU_INT_STAT & TIMER2_MASK)
620 TIMER2();
621 else if (CPU_HI_INT_STAT & GPIO_MASK)
622 ipod_mini_button_int();
623 } else {
624 if (COP_INT_STAT & TIMER1_MASK)
625 TIMER1();
626 else if (COP_INT_STAT & TIMER2_MASK)
627 TIMER2();
628 else if (COP_HI_INT_STAT & GPIO_MASK)
629 ipod_mini_button_int();
632 #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) || defined(ELIO_TPJ1022) \
633 || (defined SANSA_E200)
634 /* TODO: this should really be in the target tree, but moving it there caused
635 crt0.S not to find it while linking */
636 /* TODO: Even if it isn't in the target tree, this should be the default case */
637 void irq(void)
639 if(CURRENT_CORE == CPU)
641 if (CPU_INT_STAT & TIMER1_MASK)
642 TIMER1();
643 else if (CPU_INT_STAT & TIMER2_MASK)
644 TIMER2();
645 } else {
646 if (COP_INT_STAT & TIMER1_MASK)
647 TIMER1();
648 else if (COP_INT_STAT & TIMER2_MASK)
649 TIMER2();
652 #else
653 extern void ipod_4g_button_int(void);
655 void irq(void)
657 if(CURRENT_CORE == CPU)
659 if (CPU_INT_STAT & TIMER1_MASK)
660 TIMER1();
661 else if (CPU_INT_STAT & TIMER2_MASK)
662 TIMER2();
663 else if (CPU_HI_INT_STAT & I2C_MASK)
664 ipod_4g_button_int();
665 } else {
666 if (COP_INT_STAT & TIMER1_MASK)
667 TIMER1();
668 else if (COP_INT_STAT & TIMER2_MASK)
669 TIMER2();
670 else if (COP_HI_INT_STAT & I2C_MASK)
671 ipod_4g_button_int();
674 #endif
675 #endif /* BOOTLOADER */
677 unsigned int current_core(void)
679 if((PROCESSOR_ID & 0xff) == PROC_ID_CPU)
681 return CPU;
683 return COP;
687 /* TODO: The following two function have been lifted straight from IPL, and
688 hence have a lot of numeric addresses used straight. I'd like to use
689 #defines for these, but don't know what most of them are for or even what
690 they should be named. Because of this I also have no way of knowing how
691 to extend the funtions to do alternate cache configurations and/or
692 some other CPU frequency scaling. */
694 #ifndef BOOTLOADER
695 static void ipod_init_cache(void)
697 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
698 unsigned i;
700 /* cache init mode? */
701 CACHE_CTL = CACHE_INIT;
703 /* PP5002 has 8KB cache */
704 for (i = 0xf0004000; i < 0xf0006000; i += 16) {
705 outl(0x0, i);
708 outl(0x0, 0xf000f040);
709 outl(0x3fc0, 0xf000f044);
711 /* enable cache */
712 CACHE_CTL = CACHE_ENABLE;
714 for (i = 0x10000000; i < 0x10002000; i += 16)
715 inb(i);
717 #endif
719 /* Not all iPod targets support CPU freq. boosting yet */
720 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
721 void set_cpu_frequency(long frequency)
723 unsigned long postmult;
725 if (CURRENT_CORE == CPU)
727 if (frequency == CPUFREQ_NORMAL)
728 postmult = CPUFREQ_NORMAL_MULT;
729 else if (frequency == CPUFREQ_MAX)
730 postmult = CPUFREQ_MAX_MULT;
731 else
732 postmult = CPUFREQ_DEFAULT_MULT;
733 cpu_frequency = frequency;
735 /* Enable PLL? */
736 outl(inl(0x70000020) | (1<<30), 0x70000020);
738 /* Select 24MHz crystal as clock source? */
739 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
741 /* Clock frequency = (24/8)*postmult */
742 outl(0xaa020000 | 8 | (postmult << 8), 0x60006034);
744 /* Wait for PLL relock? */
745 udelay(2000);
747 /* Select PLL as clock source? */
748 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
750 #if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
751 /* We don't know why the timer interrupt gets disabled on the PP5020
752 based ipods, but without the following line, the 4Gs will freeze
753 when CPU frequency changing is enabled.
755 Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used
756 elsewhere to enable interrupts) doesn't work, we need "|=".
758 It's not needed on the PP5021 and PP5022 ipods.
761 /* unmask interrupt source */
762 CPU_INT_EN |= TIMER1_MASK;
763 COP_INT_EN |= TIMER1_MASK;
764 #endif
767 #elif !defined(BOOTLOADER)
768 void ipod_set_cpu_frequency(void)
770 /* Enable PLL? */
771 outl(inl(0x70000020) | (1<<30), 0x70000020);
773 /* Select 24MHz crystal as clock source? */
774 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
776 /* Clock frequency = (24/8)*25 = 75MHz */
777 outl(0xaa020000 | 8 | (25 << 8), 0x60006034);
778 /* Wait for PLL relock? */
779 udelay(2000);
781 /* Select PLL as clock source? */
782 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
784 #endif
786 void system_init(void)
788 #ifndef BOOTLOADER
789 if (CURRENT_CORE == CPU)
791 /* Remap the flash ROM from 0x00000000 to 0x20000000. */
792 MMAP3_LOGICAL = 0x20000000 | 0x3a00;
793 MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
795 /* The hw revision is written to the last 4 bytes of SDRAM by the
796 bootloader - we save it before Rockbox overwrites it. */
797 ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
799 /* disable all irqs */
800 outl(-1, 0x60001138);
801 outl(-1, 0x60001128);
802 outl(-1, 0x6000111c);
804 outl(-1, 0x60001038);
805 outl(-1, 0x60001028);
806 outl(-1, 0x6000101c);
807 #if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES == 1)
808 ipod_set_cpu_frequency();
809 #endif
811 #if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
812 else
814 ipod_set_cpu_frequency();
816 #endif
817 ipod_init_cache();
818 #endif
821 void system_reboot(void)
823 /* Reboot */
824 DEV_RS |= DEV_SYSTEM;
827 int system_memory_guard(int newmode)
829 (void)newmode;
830 return 0;
832 #elif CONFIG_CPU==PP5002
833 unsigned int ipod_hw_rev;
834 #ifndef BOOTLOADER
835 extern void TIMER1(void);
836 extern void TIMER2(void);
838 void irq(void)
840 if(CURRENT_CORE == CPU)
842 if (CPU_INT_STAT & TIMER1_MASK)
843 TIMER1();
844 else if (CPU_INT_STAT & TIMER2_MASK)
845 TIMER2();
846 } else {
847 if (COP_INT_STAT & TIMER1_MASK)
848 TIMER1();
849 else if (COP_INT_STAT & TIMER2_MASK)
850 TIMER2();
854 #endif
856 unsigned int current_core(void)
858 if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55)
860 return CPU;
862 return COP;
866 /* TODO: The following two function have been lifted straight from IPL, and
867 hence have a lot of numeric addresses used straight. I'd like to use
868 #defines for these, but don't know what most of them are for or even what
869 they should be named. Because of this I also have no way of knowing how
870 to extend the funtions to do alternate cache configurations and/or
871 some other CPU frequency scaling. */
873 #ifndef BOOTLOADER
874 static void ipod_init_cache(void)
876 int i =0;
877 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
878 outl(inl(0xcf004050) & ~0x700, 0xcf004050);
879 outl(0x4000, 0xcf004020);
881 outl(0x2, 0xcf004024);
883 /* PP5002 has 8KB cache */
884 for (i = 0xf0004000; i < (int)(0xf0006000); i += 16) {
885 outl(0x0, i);
888 outl(0x0, 0xf000f020);
889 outl(0x3fc0, 0xf000f024);
891 outl(0x3, 0xcf004024);
893 #endif
895 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
896 void set_cpu_frequency(long frequency)
898 unsigned long postmult;
900 if (CURRENT_CORE == CPU)
902 if (frequency == CPUFREQ_NORMAL)
903 postmult = CPUFREQ_NORMAL_MULT;
904 else if (frequency == CPUFREQ_MAX)
905 postmult = CPUFREQ_MAX_MULT;
906 else
907 postmult = CPUFREQ_DEFAULT_MULT;
908 cpu_frequency = frequency;
910 outl(0x02, 0xcf005008);
911 outl(0x55, 0xcf00500c);
912 outl(0x6000, 0xcf005010);
914 /* Clock frequency = (24/8)*postmult */
915 outl(8, 0xcf005018);
916 outl(postmult, 0xcf00501c);
918 outl(0xe000, 0xcf005010);
920 /* Wait for PLL relock? */
921 udelay(2000);
923 /* Select PLL as clock source? */
924 outl(0xa8, 0xcf00500c);
927 #elif !defined(BOOTLOADER)
928 static void ipod_set_cpu_speed(void)
930 outl(0x02, 0xcf005008);
931 outl(0x55, 0xcf00500c);
932 outl(0x6000, 0xcf005010);
933 #if 1
934 // 75 MHz (24/24 * 75) (default)
935 outl(24, 0xcf005018);
936 outl(75, 0xcf00501c);
937 #endif
939 #if 0
940 // 66 MHz (24/3 * 8)
941 outl(3, 0xcf005018);
942 outl(8, 0xcf00501c);
943 #endif
945 outl(0xe000, 0xcf005010);
947 udelay(2000);
949 outl(0xa8, 0xcf00500c);
951 #endif
953 void system_init(void)
955 #ifndef BOOTLOADER
956 if (CURRENT_CORE == CPU)
958 /* Remap the flash ROM from 0x00000000 to 0x20000000. */
959 MMAP3_LOGICAL = 0x20000000 | 0x3a00;
960 MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
962 ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
963 outl(-1, 0xcf00101c);
964 outl(-1, 0xcf001028);
965 outl(-1, 0xcf001038);
966 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
967 ipod_set_cpu_speed();
968 #endif
970 ipod_init_cache();
971 #endif
974 void system_reboot(void)
976 outl(inl(0xcf005030) | 0x4, 0xcf005030);
979 int system_memory_guard(int newmode)
981 (void)newmode;
982 return 0;
985 #elif CONFIG_CPU==PNX0101
987 interrupt_handler_t interrupt_vector[0x1d] __attribute__ ((section(".idata")));
989 #define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg)))
991 static inline unsigned long irq_read(int reg)
993 unsigned long v, v2;
996 v = IRQ_REG(reg);
997 v2 = IRQ_REG(reg);
998 } while (v != v2);
999 return v;
1002 #define IRQ_WRITE_WAIT(reg, val, cond) \
1003 do { unsigned long v, v2; \
1004 do { \
1005 IRQ_REG(reg) = (val); \
1006 v = IRQ_REG(reg); \
1007 v2 = IRQ_REG(reg); \
1008 } while ((v != v2) || !(cond)); \
1009 } while (0);
1011 static void undefined_int(void)
1015 void irq(void)
1017 int n = irq_read(0x100) >> 3;
1018 (*(interrupt_vector[n]))();
1021 void fiq(void)
1025 void irq_enable_int(int n)
1027 IRQ_WRITE_WAIT(0x404 + n * 4, 0x4010000, v & 0x10000);
1030 void irq_set_int_handler(int n, interrupt_handler_t handler)
1032 interrupt_vector[n + 1] = handler;
1035 void system_init(void)
1037 int i;
1039 /* turn off watchdog */
1040 (*(volatile unsigned long *)0x80002804) = 0;
1043 IRQ_WRITE_WAIT(0x100, 0, v == 0);
1044 IRQ_WRITE_WAIT(0x104, 0, v == 0);
1045 IRQ_WRITE_WAIT(0, 0, v == 0);
1046 IRQ_WRITE_WAIT(4, 0, v == 0);
1049 for (i = 0; i < 0x1c; i++)
1051 IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1);
1052 IRQ_WRITE_WAIT(0x404 + i * 4, 0x4000000, (v & 0x10000) == 0);
1053 IRQ_WRITE_WAIT(0x404 + i * 4, 0x10000001, (v & 0xf) == 1);
1054 interrupt_vector[i + 1] = undefined_int;
1056 interrupt_vector[0] = undefined_int;
1060 void system_reboot(void)
1062 (*(volatile unsigned long *)0x80002804) = 1;
1063 while (1);
1066 int system_memory_guard(int newmode)
1068 (void)newmode;
1069 return 0;
1072 #endif /* CPU_ARM */
1073 #endif /* CONFIG_CPU */