make the runtime view nicer.
[Rockbox.git] / firmware / system.c
blob02d14e3ee66a7c3d35de6b1734e584b764dadb0f
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 "thread.h"
27 #include "timer.h"
28 #include "inttypes.h"
29 #include "string.h"
31 #ifndef SIMULATOR
32 long cpu_frequency NOCACHEBSS_ATTR = CPU_FREQ;
33 #endif
35 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
36 static int boost_counter NOCACHEBSS_ATTR = 0;
37 static bool cpu_idle NOCACHEBSS_ATTR = false;
39 #if NUM_CORES > 1
40 struct mutex boostctrl_mtx NOCACHEBSS_ATTR;
41 #endif
43 int get_cpu_boost_counter(void)
45 return boost_counter;
47 #ifdef CPU_BOOST_LOGGING
48 #define MAX_BOOST_LOG 64
49 static char cpu_boost_calls[MAX_BOOST_LOG][MAX_PATH];
50 static int cpu_boost_first = 0;
51 static int cpu_boost_calls_count = 0;
52 static int cpu_boost_track_message = 0;
53 int cpu_boost_log_getcount(void)
55 return cpu_boost_calls_count;
57 char * cpu_boost_log_getlog_first(void)
59 if (cpu_boost_calls_count)
61 cpu_boost_track_message = 1;
62 return cpu_boost_calls[cpu_boost_first];
64 else return NULL;
66 char * cpu_boost_log_getlog_next(void)
68 int message = (cpu_boost_track_message+cpu_boost_first)%MAX_BOOST_LOG;
69 if (cpu_boost_track_message < cpu_boost_calls_count)
71 cpu_boost_track_message++;
72 return cpu_boost_calls[message];
74 else return NULL;
76 void cpu_boost_(bool on_off, char* location, int line)
78 if (cpu_boost_calls_count == MAX_BOOST_LOG)
80 cpu_boost_first = (cpu_boost_first+1)%MAX_BOOST_LOG;
81 cpu_boost_calls_count--;
82 if (cpu_boost_calls_count < 0)
83 cpu_boost_calls_count = 0;
85 if (cpu_boost_calls_count < MAX_BOOST_LOG)
87 int message = (cpu_boost_first+cpu_boost_calls_count)%MAX_BOOST_LOG;
88 snprintf(cpu_boost_calls[message], MAX_PATH,
89 "%c %s:%d",on_off==true?'B':'U',location,line);
90 cpu_boost_calls_count++;
92 #else
93 void cpu_boost(bool on_off)
95 #endif
96 if(on_off)
98 /* Boost the frequency if not already boosted */
99 if(boost_counter++ == 0)
100 set_cpu_frequency(CPUFREQ_MAX);
102 else
104 /* Lower the frequency if the counter reaches 0 */
105 if(--boost_counter == 0)
107 if(cpu_idle)
108 set_cpu_frequency(CPUFREQ_DEFAULT);
109 else
110 set_cpu_frequency(CPUFREQ_NORMAL);
113 /* Safety measure */
114 if(boost_counter < 0)
115 boost_counter = 0;
119 void cpu_idle_mode(bool on_off)
121 cpu_idle = on_off;
123 /* We need to adjust the frequency immediately if the CPU
124 isn't boosted */
125 if(boost_counter == 0)
127 if(cpu_idle)
128 set_cpu_frequency(CPUFREQ_DEFAULT);
129 else
130 set_cpu_frequency(CPUFREQ_NORMAL);
133 #endif /* HAVE_ADJUSTABLE_CPU_FREQ */
136 #ifdef HAVE_FLASHED_ROCKBOX
137 static bool detect_flash_header(uint8_t *addr)
139 #ifndef BOOTLOADER
140 int oldmode = system_memory_guard(MEMGUARD_NONE);
141 #endif
142 struct flash_header hdr;
143 memcpy(&hdr, addr, sizeof(struct flash_header));
144 #ifndef BOOTLOADER
145 system_memory_guard(oldmode);
146 #endif
147 return hdr.magic == FLASH_MAGIC;
149 #endif
151 bool detect_flashed_romimage(void)
153 #ifdef HAVE_FLASHED_ROCKBOX
154 return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY);
155 #else
156 return false;
157 #endif /* HAVE_FLASHED_ROCKBOX */
160 bool detect_flashed_ramimage(void)
162 #ifdef HAVE_FLASHED_ROCKBOX
163 return detect_flash_header((uint8_t *)FLASH_RAMIMAGE_ENTRY);
164 #else
165 return false;
166 #endif /* HAVE_FLASHED_ROCKBOX */
169 bool detect_original_firmware(void)
171 return !(detect_flashed_ramimage() || detect_flashed_romimage());
174 #if CONFIG_CPU == SH7034
175 #include "led.h"
176 #include "system.h"
177 #include "rolo.h"
179 static const char* const irqname[] = {
180 "", "", "", "", "IllInstr", "", "IllSltIn","","",
181 "CPUAdrEr", "DMAAdrEr", "NMI", "UserBrk",
182 "","","","","","","","","","","","","","","","","","","",
183 "Trap32","Trap33","Trap34","Trap35","Trap36","Trap37","Trap38","Trap39",
184 "Trap40","Trap41","Trap42","Trap43","Trap44","Trap45","Trap46","Trap47",
185 "Trap48","Trap49","Trap50","Trap51","Trap52","Trap53","Trap54","Trap55",
186 "Trap56","Trap57","Trap58","Trap59","Trap60","Trap61","Trap62","Trap63",
187 "Irq0","Irq1","Irq2","Irq3","Irq4","Irq5","Irq6","Irq7",
188 "Dma0","","Dma1","","Dma2","","Dma3","",
189 "IMIA0","IMIB0","OVI0","", "IMIA1","IMIB1","OVI1","",
190 "IMIA2","IMIB2","OVI2","", "IMIA3","IMIB3","OVI3","",
191 "IMIA4","IMIB4","OVI4","",
192 "Ser0Err","Ser0Rx","Ser0Tx","Ser0TE",
193 "Ser1Err","Ser1Rx","Ser1Tx","Ser1TE",
194 "ParityEr","A/D conv","","","Watchdog","DRAMRefr"
197 #define RESERVE_INTERRUPT(number) "\t.long\t_UIE" #number "\n"
198 #define DEFAULT_INTERRUPT(name, number) "\t.weak\t_" #name \
199 "\n\t.set\t_" #name ",_UIE" #number \
200 "\n\t.long\t_" #name "\n"
202 asm (
204 /* Vector table.
205 * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols
206 * defined in an asm block -- silly.
207 * Reset vectors (0..3) are handled in crt0.S */
209 ".section\t.vectors,\"aw\",@progbits\n"
210 DEFAULT_INTERRUPT (GII, 4)
211 RESERVE_INTERRUPT ( 5)
212 DEFAULT_INTERRUPT (ISI, 6)
213 RESERVE_INTERRUPT ( 7)
214 RESERVE_INTERRUPT ( 8)
215 DEFAULT_INTERRUPT (CPUAE, 9)
216 DEFAULT_INTERRUPT (DMAAE, 10)
217 DEFAULT_INTERRUPT (NMI, 11)
218 DEFAULT_INTERRUPT (UB, 12)
219 RESERVE_INTERRUPT ( 13)
220 RESERVE_INTERRUPT ( 14)
221 RESERVE_INTERRUPT ( 15)
222 RESERVE_INTERRUPT ( 16) /* TCB #0 */
223 RESERVE_INTERRUPT ( 17) /* TCB #1 */
224 RESERVE_INTERRUPT ( 18) /* TCB #2 */
225 RESERVE_INTERRUPT ( 19) /* TCB #3 */
226 RESERVE_INTERRUPT ( 20) /* TCB #4 */
227 RESERVE_INTERRUPT ( 21) /* TCB #5 */
228 RESERVE_INTERRUPT ( 22) /* TCB #6 */
229 RESERVE_INTERRUPT ( 23) /* TCB #7 */
230 RESERVE_INTERRUPT ( 24) /* TCB #8 */
231 RESERVE_INTERRUPT ( 25) /* TCB #9 */
232 RESERVE_INTERRUPT ( 26) /* TCB #10 */
233 RESERVE_INTERRUPT ( 27) /* TCB #11 */
234 RESERVE_INTERRUPT ( 28) /* TCB #12 */
235 RESERVE_INTERRUPT ( 29) /* TCB #13 */
236 RESERVE_INTERRUPT ( 30) /* TCB #14 */
237 RESERVE_INTERRUPT ( 31) /* TCB #15 */
238 DEFAULT_INTERRUPT (TRAPA32, 32)
239 DEFAULT_INTERRUPT (TRAPA33, 33)
240 DEFAULT_INTERRUPT (TRAPA34, 34)
241 DEFAULT_INTERRUPT (TRAPA35, 35)
242 DEFAULT_INTERRUPT (TRAPA36, 36)
243 DEFAULT_INTERRUPT (TRAPA37, 37)
244 DEFAULT_INTERRUPT (TRAPA38, 38)
245 DEFAULT_INTERRUPT (TRAPA39, 39)
246 DEFAULT_INTERRUPT (TRAPA40, 40)
247 DEFAULT_INTERRUPT (TRAPA41, 41)
248 DEFAULT_INTERRUPT (TRAPA42, 42)
249 DEFAULT_INTERRUPT (TRAPA43, 43)
250 DEFAULT_INTERRUPT (TRAPA44, 44)
251 DEFAULT_INTERRUPT (TRAPA45, 45)
252 DEFAULT_INTERRUPT (TRAPA46, 46)
253 DEFAULT_INTERRUPT (TRAPA47, 47)
254 DEFAULT_INTERRUPT (TRAPA48, 48)
255 DEFAULT_INTERRUPT (TRAPA49, 49)
256 DEFAULT_INTERRUPT (TRAPA50, 50)
257 DEFAULT_INTERRUPT (TRAPA51, 51)
258 DEFAULT_INTERRUPT (TRAPA52, 52)
259 DEFAULT_INTERRUPT (TRAPA53, 53)
260 DEFAULT_INTERRUPT (TRAPA54, 54)
261 DEFAULT_INTERRUPT (TRAPA55, 55)
262 DEFAULT_INTERRUPT (TRAPA56, 56)
263 DEFAULT_INTERRUPT (TRAPA57, 57)
264 DEFAULT_INTERRUPT (TRAPA58, 58)
265 DEFAULT_INTERRUPT (TRAPA59, 59)
266 DEFAULT_INTERRUPT (TRAPA60, 60)
267 DEFAULT_INTERRUPT (TRAPA61, 61)
268 DEFAULT_INTERRUPT (TRAPA62, 62)
269 DEFAULT_INTERRUPT (TRAPA63, 63)
270 DEFAULT_INTERRUPT (IRQ0, 64)
271 DEFAULT_INTERRUPT (IRQ1, 65)
272 DEFAULT_INTERRUPT (IRQ2, 66)
273 DEFAULT_INTERRUPT (IRQ3, 67)
274 DEFAULT_INTERRUPT (IRQ4, 68)
275 DEFAULT_INTERRUPT (IRQ5, 69)
276 DEFAULT_INTERRUPT (IRQ6, 70)
277 DEFAULT_INTERRUPT (IRQ7, 71)
278 DEFAULT_INTERRUPT (DEI0, 72)
279 RESERVE_INTERRUPT ( 73)
280 DEFAULT_INTERRUPT (DEI1, 74)
281 RESERVE_INTERRUPT ( 75)
282 DEFAULT_INTERRUPT (DEI2, 76)
283 RESERVE_INTERRUPT ( 77)
284 DEFAULT_INTERRUPT (DEI3, 78)
285 RESERVE_INTERRUPT ( 79)
286 DEFAULT_INTERRUPT (IMIA0, 80)
287 DEFAULT_INTERRUPT (IMIB0, 81)
288 DEFAULT_INTERRUPT (OVI0, 82)
289 RESERVE_INTERRUPT ( 83)
290 DEFAULT_INTERRUPT (IMIA1, 84)
291 DEFAULT_INTERRUPT (IMIB1, 85)
292 DEFAULT_INTERRUPT (OVI1, 86)
293 RESERVE_INTERRUPT ( 87)
294 DEFAULT_INTERRUPT (IMIA2, 88)
295 DEFAULT_INTERRUPT (IMIB2, 89)
296 DEFAULT_INTERRUPT (OVI2, 90)
297 RESERVE_INTERRUPT ( 91)
298 DEFAULT_INTERRUPT (IMIA3, 92)
299 DEFAULT_INTERRUPT (IMIB3, 93)
300 DEFAULT_INTERRUPT (OVI3, 94)
301 RESERVE_INTERRUPT ( 95)
302 DEFAULT_INTERRUPT (IMIA4, 96)
303 DEFAULT_INTERRUPT (IMIB4, 97)
304 DEFAULT_INTERRUPT (OVI4, 98)
305 RESERVE_INTERRUPT ( 99)
306 DEFAULT_INTERRUPT (REI0, 100)
307 DEFAULT_INTERRUPT (RXI0, 101)
308 DEFAULT_INTERRUPT (TXI0, 102)
309 DEFAULT_INTERRUPT (TEI0, 103)
310 DEFAULT_INTERRUPT (REI1, 104)
311 DEFAULT_INTERRUPT (RXI1, 105)
312 DEFAULT_INTERRUPT (TXI1, 106)
313 DEFAULT_INTERRUPT (TEI1, 107)
314 RESERVE_INTERRUPT ( 108)
315 DEFAULT_INTERRUPT (ADITI, 109)
317 /* UIE# block.
318 * Must go into the same section as the UIE() handler */
320 "\t.text\n"
321 "_UIE4:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
322 "_UIE5:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
323 "_UIE6:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
324 "_UIE7:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
325 "_UIE8:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
326 "_UIE9:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
327 "_UIE10:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
328 "_UIE11:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
329 "_UIE12:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
330 "_UIE13:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
331 "_UIE14:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
332 "_UIE15:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
333 "_UIE16:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
334 "_UIE17:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
335 "_UIE18:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
336 "_UIE19:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
337 "_UIE20:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
338 "_UIE21:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
339 "_UIE22:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
340 "_UIE23:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
341 "_UIE24:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
342 "_UIE25:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
343 "_UIE26:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
344 "_UIE27:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
345 "_UIE28:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
346 "_UIE29:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
347 "_UIE30:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
348 "_UIE31:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
349 "_UIE32:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
350 "_UIE33:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
351 "_UIE34:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
352 "_UIE35:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
353 "_UIE36:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
354 "_UIE37:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
355 "_UIE38:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
356 "_UIE39:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
357 "_UIE40:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
358 "_UIE41:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
359 "_UIE42:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
360 "_UIE43:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
361 "_UIE44:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
362 "_UIE45:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
363 "_UIE46:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
364 "_UIE47:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
365 "_UIE48:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
366 "_UIE49:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
367 "_UIE50:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
368 "_UIE51:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
369 "_UIE52:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
370 "_UIE53:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
371 "_UIE54:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
372 "_UIE55:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
373 "_UIE56:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
374 "_UIE57:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
375 "_UIE58:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
376 "_UIE59:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
377 "_UIE60:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
378 "_UIE61:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
379 "_UIE62:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
380 "_UIE63:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
381 "_UIE64:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
382 "_UIE65:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
383 "_UIE66:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
384 "_UIE67:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
385 "_UIE68:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
386 "_UIE69:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
387 "_UIE70:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
388 "_UIE71:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
389 "_UIE72:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
390 "_UIE73:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
391 "_UIE74:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
392 "_UIE75:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
393 "_UIE76:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
394 "_UIE77:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
395 "_UIE78:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
396 "_UIE79:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
397 "_UIE80:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
398 "_UIE81:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
399 "_UIE82:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
400 "_UIE83:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
401 "_UIE84:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
402 "_UIE85:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
403 "_UIE86:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
404 "_UIE87:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
405 "_UIE88:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
406 "_UIE89:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
407 "_UIE90:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
408 "_UIE91:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
409 "_UIE92:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
410 "_UIE93:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
411 "_UIE94:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
412 "_UIE95:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
413 "_UIE96:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
414 "_UIE97:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
415 "_UIE98:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
416 "_UIE99:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
417 "_UIE100:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
418 "_UIE101:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
419 "_UIE102:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
420 "_UIE103:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
421 "_UIE104:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
422 "_UIE105:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
423 "_UIE106:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
424 "_UIE107:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
425 "_UIE108:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
426 "_UIE109:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
430 extern void UIE4(void); /* needed for calculating the UIE number */
432 void UIE (unsigned int pc) __attribute__((section(".text")));
433 void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
435 #if CONFIG_LED == LED_REAL
436 bool state = false;
437 int i = 0;
438 #endif
439 unsigned int n;
440 char str[32];
442 asm volatile ("sts\tpr,%0" : "=r"(n));
444 /* clear screen */
445 lcd_clear_display ();
446 #ifdef HAVE_LCD_BITMAP
447 lcd_setfont(FONT_SYSFIXED);
448 #endif
449 /* output exception */
450 n = (n - (unsigned)UIE4 + 12)>>2; /* get exception or interrupt number */
451 snprintf(str,sizeof(str),"I%02x:%s",n,irqname[n]);
452 lcd_puts(0,0,str);
453 snprintf(str,sizeof(str),"at %08x",pc);
454 lcd_puts(0,1,str);
455 lcd_update ();
457 while (1)
459 #if CONFIG_LED == LED_REAL
460 if (--i <= 0)
462 state = !state;
463 led(state);
464 i = 240000;
466 #endif
468 /* try to restart firmware if ON is pressed */
469 #if CONFIG_KEYPAD == PLAYER_PAD
470 if (!(PADRL & 0x20))
471 #elif CONFIG_KEYPAD == RECORDER_PAD
472 #ifdef HAVE_FMADC
473 if (!(PCDR & 0x0008))
474 #else
475 if (!(PBDRH & 0x01))
476 #endif
477 #elif CONFIG_KEYPAD == ONDIO_PAD
478 if (!(PCDR & 0x0008))
479 #endif
481 /* enable the watchguard timer, but don't service it */
482 RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */
483 TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */
488 void system_init(void)
490 /* Disable all interrupts */
491 IPRA = 0;
492 IPRB = 0;
493 IPRC = 0;
494 IPRD = 0;
495 IPRE = 0;
497 /* NMI level low, falling edge on all interrupts */
498 ICR = 0;
500 /* Enable burst and RAS down mode on DRAM */
501 DCR |= 0x5000;
503 /* Activate Warp mode (simultaneous internal and external mem access) */
504 BCR |= 0x2000;
506 /* Bus state controller initializations. These are only necessary when
507 running from flash. */
508 WCR1 = 0x40FD; /* Long wait states for CS6 (ATA), short for the rest. */
509 WCR3 = 0x8000; /* WAIT is pulled up, 1 state inserted for CS6 */
512 void system_reboot (void)
514 set_irq_level(HIGHEST_IRQ_LEVEL);
516 asm volatile ("ldc\t%0,vbr" : : "r"(0));
518 PACR2 |= 0x4000; /* for coldstart detection */
519 IPRA = 0;
520 IPRB = 0;
521 IPRC = 0;
522 IPRD = 0;
523 IPRE = 0;
524 ICR = 0;
526 asm volatile ("jmp @%0; mov.l @%1,r15" : :
527 "r"(*(int*)0),"r"(4));
530 /* Utilise the user break controller to catch invalid memory accesses. */
531 int system_memory_guard(int newmode)
533 static const struct {
534 unsigned long addr;
535 unsigned long mask;
536 unsigned short bbr;
537 } modes[MAXMEMGUARD] = {
538 /* catch nothing */
539 { 0x00000000, 0x00000000, 0x0000 },
540 /* catch writes to area 02 (flash ROM) */
541 { 0x02000000, 0x00FFFFFF, 0x00F8 },
542 /* catch all accesses to areas 00 (internal ROM) and 01 (free) */
543 { 0x00000000, 0x01FFFFFF, 0x00FC }
546 int oldmode = MEMGUARD_NONE;
547 int i;
549 /* figure out the old mode from what is in the UBC regs. If the register
550 values don't match any mode, assume MEMGUARD_NONE */
551 for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++)
553 if (BAR == modes[i].addr && BAMR == modes[i].mask &&
554 BBR == modes[i].bbr)
556 oldmode = i;
557 break;
561 if (newmode == MEMGUARD_KEEP)
562 newmode = oldmode;
564 BBR = 0; /* switch off everything first */
566 /* always set the UBC according to the mode, in case the old settings
567 didn't match any valid mode */
568 BAR = modes[newmode].addr;
569 BAMR = modes[newmode].mask;
570 BBR = modes[newmode].bbr;
572 return oldmode;
574 #elif defined(CPU_ARM)
576 static const char* const uiename[] = {
577 "Undefined instruction", "Prefetch abort", "Data abort"
580 /* Unexpected Interrupt or Exception handler. Currently only deals with
581 exceptions, but will deal with interrupts later.
583 void UIE(unsigned int pc, unsigned int num)
585 char str[32];
587 lcd_clear_display();
588 #ifdef HAVE_LCD_BITMAP
589 lcd_setfont(FONT_SYSFIXED);
590 #endif
591 lcd_puts(0, 0, uiename[num]);
592 snprintf(str, sizeof(str), "at %08x", pc);
593 lcd_puts(0, 1, str);
594 lcd_update();
596 while (1)
598 /* TODO: perhaps add button handling in here when we get a polling
599 driver some day.
604 #if CONFIG_CPU==PP5020 || CONFIG_CPU==PP5024
606 unsigned int ipod_hw_rev;
608 #ifndef BOOTLOADER
609 extern void TIMER1(void);
610 extern void TIMER2(void);
612 #if defined(IPOD_MINI) /* mini 1 only, mini 2G uses iPod 4G code */
613 extern void ipod_mini_button_int(void);
615 void irq(void)
617 if(CURRENT_CORE == CPU)
619 if (CPU_INT_STAT & TIMER1_MASK)
620 TIMER1();
621 else if (CPU_INT_STAT & TIMER2_MASK)
622 TIMER2();
623 else if (CPU_HI_INT_STAT & GPIO_MASK)
624 ipod_mini_button_int();
625 } else {
626 if (COP_INT_STAT & TIMER1_MASK)
627 TIMER1();
628 else if (COP_INT_STAT & TIMER2_MASK)
629 TIMER2();
630 else if (COP_HI_INT_STAT & GPIO_MASK)
631 ipod_mini_button_int();
634 #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) || defined(ELIO_TPJ1022) \
635 || (defined SANSA_E200)
636 /* TODO: this should really be in the target tree, but moving it there caused
637 crt0.S not to find it while linking */
638 /* TODO: Even if it isn't in the target tree, this should be the default case */
639 void irq(void)
641 if(CURRENT_CORE == CPU)
643 if (CPU_INT_STAT & TIMER1_MASK)
644 TIMER1();
645 else if (CPU_INT_STAT & TIMER2_MASK)
646 TIMER2();
647 } else {
648 if (COP_INT_STAT & TIMER1_MASK)
649 TIMER1();
650 else if (COP_INT_STAT & TIMER2_MASK)
651 TIMER2();
654 #else
655 extern void ipod_4g_button_int(void);
657 void irq(void)
659 if(CURRENT_CORE == CPU)
661 if (CPU_INT_STAT & TIMER1_MASK)
662 TIMER1();
663 else if (CPU_INT_STAT & TIMER2_MASK)
664 TIMER2();
665 else if (CPU_HI_INT_STAT & I2C_MASK)
666 ipod_4g_button_int();
667 } else {
668 if (COP_INT_STAT & TIMER1_MASK)
669 TIMER1();
670 else if (COP_INT_STAT & TIMER2_MASK)
671 TIMER2();
672 else if (COP_HI_INT_STAT & I2C_MASK)
673 ipod_4g_button_int();
676 #endif
677 #endif /* BOOTLOADER */
679 unsigned int current_core(void)
681 if((PROCESSOR_ID & 0xff) == PROC_ID_CPU)
683 return CPU;
685 return COP;
689 /* TODO: The following two function have been lifted straight from IPL, and
690 hence have a lot of numeric addresses used straight. I'd like to use
691 #defines for these, but don't know what most of them are for or even what
692 they should be named. Because of this I also have no way of knowing how
693 to extend the funtions to do alternate cache configurations and/or
694 some other CPU frequency scaling. */
696 #ifndef BOOTLOADER
697 static void ipod_init_cache(void)
699 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
700 unsigned i;
702 /* cache init mode? */
703 CACHE_CTL = CACHE_INIT;
705 /* PP5002 has 8KB cache */
706 for (i = 0xf0004000; i < 0xf0006000; i += 16) {
707 outl(0x0, i);
710 outl(0x0, 0xf000f040);
711 outl(0x3fc0, 0xf000f044);
713 /* enable cache */
714 CACHE_CTL = CACHE_ENABLE;
716 for (i = 0x10000000; i < 0x10002000; i += 16)
717 inb(i);
719 #endif
721 /* Not all iPod targets support CPU freq. boosting yet */
722 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
723 void set_cpu_frequency(long frequency)
725 unsigned long postmult;
727 # if NUM_CORES > 1
728 /* Using mutex or spinlock isn't safe here. */
729 while (test_and_set(&boostctrl_mtx.locked, 1)) ;
730 # endif
732 if (frequency == CPUFREQ_NORMAL)
733 postmult = CPUFREQ_NORMAL_MULT;
734 else if (frequency == CPUFREQ_MAX)
735 postmult = CPUFREQ_MAX_MULT;
736 else
737 postmult = CPUFREQ_DEFAULT_MULT;
738 cpu_frequency = frequency;
740 /* Enable PLL? */
741 outl(inl(0x70000020) | (1<<30), 0x70000020);
743 /* Select 24MHz crystal as clock source? */
744 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
746 /* Clock frequency = (24/8)*postmult */
747 outl(0xaa020000 | 8 | (postmult << 8), 0x60006034);
749 /* Wait for PLL relock? */
750 udelay(2000);
752 /* Select PLL as clock source? */
753 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
755 # if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
756 /* We don't know why the timer interrupt gets disabled on the PP5020
757 based ipods, but without the following line, the 4Gs will freeze
758 when CPU frequency changing is enabled.
760 Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used
761 elsewhere to enable interrupts) doesn't work, we need "|=".
763 It's not needed on the PP5021 and PP5022 ipods.
766 /* unmask interrupt source */
767 CPU_INT_EN |= TIMER1_MASK;
768 COP_INT_EN |= TIMER1_MASK;
769 # endif
771 # if NUM_CORES > 1
772 boostctrl_mtx.locked = 0;
773 # endif
775 #elif !defined(BOOTLOADER)
776 void ipod_set_cpu_frequency(void)
778 /* Enable PLL? */
779 outl(inl(0x70000020) | (1<<30), 0x70000020);
781 /* Select 24MHz crystal as clock source? */
782 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
784 /* Clock frequency = (24/8)*25 = 75MHz */
785 outl(0xaa020000 | 8 | (25 << 8), 0x60006034);
786 /* Wait for PLL relock? */
787 udelay(2000);
789 /* Select PLL as clock source? */
790 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
792 #endif
794 void system_init(void)
796 #ifndef BOOTLOADER
797 if (CURRENT_CORE == CPU)
799 /* Remap the flash ROM from 0x00000000 to 0x20000000. */
800 MMAP3_LOGICAL = 0x20000000 | 0x3a00;
801 MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
803 /* The hw revision is written to the last 4 bytes of SDRAM by the
804 bootloader - we save it before Rockbox overwrites it. */
805 ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
807 /* disable all irqs */
808 outl(-1, 0x60001138);
809 outl(-1, 0x60001128);
810 outl(-1, 0x6000111c);
812 outl(-1, 0x60001038);
813 outl(-1, 0x60001028);
814 outl(-1, 0x6000101c);
816 # if NUM_CORES > 1 && defined(HAVE_ADJUSTABLE_CPU_FREQ)
817 spinlock_init(&boostctrl_mtx);
818 # endif
820 #if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES == 1)
821 ipod_set_cpu_frequency();
822 #endif
824 #if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
825 else
827 ipod_set_cpu_frequency();
829 #endif
830 ipod_init_cache();
831 #endif
834 void system_reboot(void)
836 /* Reboot */
837 DEV_RS |= DEV_SYSTEM;
840 int system_memory_guard(int newmode)
842 (void)newmode;
843 return 0;
845 #elif CONFIG_CPU==PP5002
846 unsigned int ipod_hw_rev;
847 #ifndef BOOTLOADER
848 extern void TIMER1(void);
849 extern void TIMER2(void);
851 void irq(void)
853 if(CURRENT_CORE == CPU)
855 if (CPU_INT_STAT & TIMER1_MASK)
856 TIMER1();
857 else if (CPU_INT_STAT & TIMER2_MASK)
858 TIMER2();
859 } else {
860 if (COP_INT_STAT & TIMER1_MASK)
861 TIMER1();
862 else if (COP_INT_STAT & TIMER2_MASK)
863 TIMER2();
867 #endif
869 unsigned int current_core(void)
871 if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55)
873 return CPU;
875 return COP;
879 /* TODO: The following two function have been lifted straight from IPL, and
880 hence have a lot of numeric addresses used straight. I'd like to use
881 #defines for these, but don't know what most of them are for or even what
882 they should be named. Because of this I also have no way of knowing how
883 to extend the funtions to do alternate cache configurations and/or
884 some other CPU frequency scaling. */
886 #ifndef BOOTLOADER
887 static void ipod_init_cache(void)
889 int i =0;
890 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
891 outl(inl(0xcf004050) & ~0x700, 0xcf004050);
892 outl(0x4000, 0xcf004020);
894 outl(0x2, 0xcf004024);
896 /* PP5002 has 8KB cache */
897 for (i = 0xf0004000; i < (int)(0xf0006000); i += 16) {
898 outl(0x0, i);
901 outl(0x0, 0xf000f020);
902 outl(0x3fc0, 0xf000f024);
904 outl(0x3, 0xcf004024);
907 #endif
909 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
910 void set_cpu_frequency(long frequency)
912 unsigned long postmult;
914 if (CURRENT_CORE == CPU)
916 if (frequency == CPUFREQ_NORMAL)
917 postmult = CPUFREQ_NORMAL_MULT;
918 else if (frequency == CPUFREQ_MAX)
919 postmult = CPUFREQ_MAX_MULT;
920 else
921 postmult = CPUFREQ_DEFAULT_MULT;
922 cpu_frequency = frequency;
924 outl(0x02, 0xcf005008);
925 outl(0x55, 0xcf00500c);
926 outl(0x6000, 0xcf005010);
928 /* Clock frequency = (24/8)*postmult */
929 outl(8, 0xcf005018);
930 outl(postmult, 0xcf00501c);
932 outl(0xe000, 0xcf005010);
934 /* Wait for PLL relock? */
935 udelay(2000);
937 /* Select PLL as clock source? */
938 outl(0xa8, 0xcf00500c);
941 #elif !defined(BOOTLOADER)
942 static void ipod_set_cpu_speed(void)
944 outl(0x02, 0xcf005008);
945 outl(0x55, 0xcf00500c);
946 outl(0x6000, 0xcf005010);
947 #if 1
948 // 75 MHz (24/24 * 75) (default)
949 outl(24, 0xcf005018);
950 outl(75, 0xcf00501c);
951 #endif
953 #if 0
954 // 66 MHz (24/3 * 8)
955 outl(3, 0xcf005018);
956 outl(8, 0xcf00501c);
957 #endif
959 outl(0xe000, 0xcf005010);
961 udelay(2000);
963 outl(0xa8, 0xcf00500c);
965 #endif
967 void system_init(void)
969 #ifndef BOOTLOADER
970 if (CURRENT_CORE == CPU)
972 /* Remap the flash ROM from 0x00000000 to 0x20000000. */
973 MMAP3_LOGICAL = 0x20000000 | 0x3a00;
974 MMAP3_PHYSICAL = 0x00000000 | 0x3f84;
976 ipod_hw_rev = (*((volatile unsigned long*)(0x01fffffc)));
977 outl(-1, 0xcf00101c);
978 outl(-1, 0xcf001028);
979 outl(-1, 0xcf001038);
980 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
981 ipod_set_cpu_speed();
982 #endif
984 ipod_init_cache();
985 #endif
988 void system_reboot(void)
990 outl(inl(0xcf005030) | 0x4, 0xcf005030);
993 int system_memory_guard(int newmode)
995 (void)newmode;
996 return 0;
999 #endif /* CPU_ARM */
1000 #endif /* CONFIG_CPU */