1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
31 long cpu_frequency
= CPU_FREQ
;
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)
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
];
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
];
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
++;
88 void cpu_boost(bool on_off
)
93 /* Boost the frequency if not already boosted */
94 if(boost_counter
++ == 0)
95 set_cpu_frequency(CPUFREQ_MAX
);
99 /* Lower the frequency if the counter reaches 0 */
100 if(--boost_counter
== 0)
103 set_cpu_frequency(CPUFREQ_DEFAULT
);
105 set_cpu_frequency(CPUFREQ_NORMAL
);
109 if(boost_counter
< 0)
114 void cpu_idle_mode(bool on_off
)
118 /* We need to adjust the frequency immediately if the CPU
120 if(boost_counter
== 0)
123 set_cpu_frequency(CPUFREQ_DEFAULT
);
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
)
135 int oldmode
= system_memory_guard(MEMGUARD_NONE
);
137 struct flash_header hdr
;
138 memcpy(&hdr
, addr
, sizeof(struct flash_header
));
140 system_memory_guard(oldmode
);
142 return hdr
.magic
== FLASH_MAGIC
;
146 bool detect_flashed_romimage(void)
148 #ifdef HAVE_FLASHED_ROCKBOX
149 return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY
);
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
);
161 #endif /* HAVE_FLASHED_ROCKBOX */
164 bool detect_original_firmware(void)
166 return !(detect_flashed_ramimage() || detect_flashed_romimage());
169 #if CONFIG_CPU == SH7034
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"
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)
313 * Must go into the same section as the UIE() handler */
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
437 asm volatile ("sts\tpr,%0" : "=r"(n
));
440 lcd_clear_display ();
441 #ifdef HAVE_LCD_BITMAP
442 lcd_setfont(FONT_SYSFIXED
);
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
]);
448 snprintf(str
,sizeof(str
),"at %08x",pc
);
451 #ifdef HAVE_LCD_BITMAP
457 #if CONFIG_LED == LED_REAL
466 /* try to restart firmware if ON is pressed */
467 #if CONFIG_KEYPAD == PLAYER_PAD
469 #elif CONFIG_KEYPAD == RECORDER_PAD
471 if (!(PCDR
& 0x0008))
475 #elif CONFIG_KEYPAD == ONDIO_PAD
476 if (!(PCDR
& 0x0008))
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 */
495 /* NMI level low, falling edge on all interrupts */
498 /* Enable burst and RAS down mode on DRAM */
501 /* Activate Warp mode (simultaneous internal and external mem access) */
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 */
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 {
535 } modes
[MAXMEMGUARD
] = {
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
;
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
&&
559 if (newmode
== MEMGUARD_KEEP
)
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
;
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
)
586 #ifdef HAVE_LCD_BITMAP
587 lcd_setfont(FONT_SYSFIXED
);
589 lcd_puts(0, 0, uiename
[num
]);
590 snprintf(str
, sizeof(str
), "at %08x", pc
);
596 /* TODO: perhaps add button handling in here when we get a polling
602 #if CONFIG_CPU==PP5020 || CONFIG_CPU==PP5024
604 unsigned int ipod_hw_rev
;
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);
615 if(CURRENT_CORE
== CPU
)
617 if (CPU_INT_STAT
& TIMER1_MASK
)
619 else if (CPU_INT_STAT
& TIMER2_MASK
)
621 else if (CPU_HI_INT_STAT
& GPIO_MASK
)
622 ipod_mini_button_int();
624 if (COP_INT_STAT
& TIMER1_MASK
)
626 else if (COP_INT_STAT
& TIMER2_MASK
)
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 */
639 if(CURRENT_CORE
== CPU
)
641 if (CPU_INT_STAT
& TIMER1_MASK
)
643 else if (CPU_INT_STAT
& TIMER2_MASK
)
646 if (COP_INT_STAT
& TIMER1_MASK
)
648 else if (COP_INT_STAT
& TIMER2_MASK
)
653 extern void ipod_4g_button_int(void);
657 if(CURRENT_CORE
== CPU
)
659 if (CPU_INT_STAT
& TIMER1_MASK
)
661 else if (CPU_INT_STAT
& TIMER2_MASK
)
663 else if (CPU_HI_INT_STAT
& I2C_MASK
)
664 ipod_4g_button_int();
666 if (COP_INT_STAT
& TIMER1_MASK
)
668 else if (COP_INT_STAT
& TIMER2_MASK
)
670 else if (COP_HI_INT_STAT
& I2C_MASK
)
671 ipod_4g_button_int();
675 #endif /* BOOTLOADER */
677 unsigned int current_core(void)
679 if((PROCESSOR_ID
& 0xff) == PROC_ID_CPU
)
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. */
695 static void ipod_init_cache(void)
697 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
700 /* cache init mode? */
701 CACHE_CTL
= CACHE_INIT
;
703 /* PP5002 has 8KB cache */
704 for (i
= 0xf0004000; i
< 0xf0006000; i
+= 16) {
708 outl(0x0, 0xf000f040);
709 outl(0x3fc0, 0xf000f044);
712 CACHE_CTL
= CACHE_ENABLE
;
714 for (i
= 0x10000000; i
< 0x10002000; i
+= 16)
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
;
732 postmult
= CPUFREQ_DEFAULT_MULT
;
733 cpu_frequency
= frequency
;
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? */
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
;
767 #elif !defined(BOOTLOADER)
768 void ipod_set_cpu_frequency(void)
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? */
781 /* Select PLL as clock source? */
782 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
786 void system_init(void)
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();
811 #if (!defined HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
814 ipod_set_cpu_frequency();
821 void system_reboot(void)
824 DEV_RS
|= DEV_SYSTEM
;
827 int system_memory_guard(int newmode
)
832 #elif CONFIG_CPU==PP5002
833 unsigned int ipod_hw_rev
;
835 extern void TIMER1(void);
836 extern void TIMER2(void);
840 if(CURRENT_CORE
== CPU
)
842 if (CPU_INT_STAT
& TIMER1_MASK
)
844 else if (CPU_INT_STAT
& TIMER2_MASK
)
847 if (COP_INT_STAT
& TIMER1_MASK
)
849 else if (COP_INT_STAT
& TIMER2_MASK
)
856 unsigned int current_core(void)
858 if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55)
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. */
874 static void ipod_init_cache(void)
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) {
888 outl(0x0, 0xf000f020);
889 outl(0x3fc0, 0xf000f024);
891 outl(0x3, 0xcf004024);
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
;
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 */
916 outl(postmult
, 0xcf00501c);
918 outl(0xe000, 0xcf005010);
920 /* Wait for PLL relock? */
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);
934 // 75 MHz (24/24 * 75) (default)
935 outl(24, 0xcf005018);
936 outl(75, 0xcf00501c);
945 outl(0xe000, 0xcf005010);
949 outl(0xa8, 0xcf00500c);
953 void system_init(void)
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();
974 void system_reboot(void)
976 outl(inl(0xcf005030) | 0x4, 0xcf005030);
979 int system_memory_guard(int newmode
)
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
)
1002 #define IRQ_WRITE_WAIT(reg, val, cond) \
1003 do { unsigned long v, v2; \
1005 IRQ_REG(reg) = (val); \
1007 v2 = IRQ_REG(reg); \
1008 } while ((v != v2) || !(cond)); \
1011 static void undefined_int(void)
1017 int n
= irq_read(0x100) >> 3;
1018 (*(interrupt_vector
[n
]))();
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)
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;
1066 int system_memory_guard(int newmode
)
1072 #endif /* CPU_ARM */
1073 #endif /* CONFIG_CPU */