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;
37 #ifdef CPU_BOOST_TRACKING
38 #define CPU_BOOST_TRACKER_MAX 15
39 static char cpu_boost_tracker
[CPU_BOOST_TRACKER_MAX
+1] = "";
42 int get_cpu_boost_counter(void)
47 #ifdef CPU_BOOST_TRACKING
48 const char *get_cpu_boost_tracker()
50 return cpu_boost_tracker
;
53 void cpu_boost_id(bool on_off
, char id
)
57 /* Boost the frequency if not already boosted */
58 if(boost_counter
++ == 0)
59 set_cpu_frequency(CPUFREQ_MAX
);
61 /* Add to the boost tracker for debugging */
62 int l
= strlen(cpu_boost_tracker
);
63 if (l
< CPU_BOOST_TRACKER_MAX
)
65 cpu_boost_tracker
[l
] = id
;
66 cpu_boost_tracker
[l
+1] = '\0';
71 /* Lower the frequency if the counter reaches 0 */
72 if(--boost_counter
== 0)
75 set_cpu_frequency(CPUFREQ_DEFAULT
);
77 set_cpu_frequency(CPUFREQ_NORMAL
);
84 /* Remove an entry from the boost tracker */
85 int l
= strlen(cpu_boost_tracker
);
86 while (l
>= 0 && cpu_boost_tracker
[l
] != id
)
88 if (cpu_boost_tracker
[l
] != id
) /* No match found? */
89 l
= strlen(cpu_boost_tracker
)-1; /* Just remove last one */
90 while (l
< CPU_BOOST_TRACKER_MAX
)
92 cpu_boost_tracker
[l
] = cpu_boost_tracker
[l
+1];
99 void cpu_boost(bool on_off
)
101 cpu_boost_id(on_off
, '?');
104 void cpu_idle_mode(bool on_off
)
108 /* We need to adjust the frequency immediately if the CPU
110 if(boost_counter
== 0)
113 set_cpu_frequency(CPUFREQ_DEFAULT
);
115 set_cpu_frequency(CPUFREQ_NORMAL
);
120 #if CONFIG_CPU == S3C2440
122 void system_reboot(void) {
125 void system_init(void) {
129 #if defined(IRIVER_H100_SERIES) && !defined(SIMULATOR)
130 bool detect_flashed_rockbox(void)
132 struct flash_header hdr
;
133 uint8_t *src
= (uint8_t *)FLASH_ENTRYPOINT
;
137 oldmode
= system_memory_guard(MEMGUARD_NONE
);
140 memcpy(&hdr
, src
, sizeof(struct flash_header
));
143 system_memory_guard(oldmode
);
146 if (hdr
.magic
!= FLASH_MAGIC
)
152 bool detect_flashed_rockbox(void)
158 #if CONFIG_CPU == TCC730
160 void* volatile interrupt_vector
[16] __attribute__ ((section(".idata")));
162 static void ddma_wait_idle(void) __attribute__ ((section (".icode")));
163 static void ddma_wait_idle(void)
165 /* TODO: power saving trick: set the CPU freq to 22MHz
166 while doing the busy wait after a disk dma access.
169 } while ((DDMACOM
& 3) != 0);
172 void ddma_transfer(int dir
, int mem
, void* intAddr
, long extAddr
, int num
)
173 __attribute__ ((section (".icode")));
174 void ddma_transfer(int dir
, int mem
, void* intAddr
, long extAddr
, int num
) {
175 int irq
= set_irq_level(1);
177 long externalAddress
= (long) extAddr
;
178 long internalAddress
= ((long) intAddr
) & 0xFFFF;
179 /* HW wants those two in word units. */
181 externalAddress
/= 2;
183 DDMACFG
= (dir
<< 1) | (mem
<< 2);
184 DDMAIADR
= internalAddress
;
185 DDMAEADR
= externalAddress
;
187 DDMACOM
|= 0x4; /* start */
189 ddma_wait_idle(); /* wait for completion */
193 static void ddma_wait_idle_noicode(void)
196 } while ((DDMACOM
& 3) != 0);
199 static void ddma_transfer_noicode(int dir
, int mem
, long intAddr
, long extAddr
, int num
) {
200 int irq
= set_irq_level(1);
201 ddma_wait_idle_noicode();
202 long externalAddress
= (long) extAddr
;
203 long internalAddress
= (long) intAddr
;
204 /* HW wants those two in word units. */
206 externalAddress
/= 2;
208 DDMACFG
= (dir
<< 1) | (mem
<< 2);
209 DDMAIADR
= internalAddress
;
210 DDMAEADR
= externalAddress
;
212 DDMACOM
|= 0x4; /* start */
214 ddma_wait_idle_noicode(); /* wait for completion */
218 /* Some linker-defined symbols */
219 extern int icodecopy
;
220 extern int icodesize
;
221 extern int icodestart
;
223 /* change the a PLL frequency */
224 void set_pll_freq(int pll_index
, long freq_out
) {
225 volatile unsigned int* plldata
;
226 volatile unsigned char* pllcon
;
227 if (pll_index
== 0) {
234 /* VC0 is 32768 Hz */
235 #define VC0FREQ (32768L)
236 unsigned m
= (freq_out
/ VC0FREQ
) - 2;
237 /* TODO: if m is too small here, use the divider bits [0,1] */
239 *pllcon
|= 0x1; /* activate */
241 } while ((*pllcon
& 0x2) == 0); /* wait for stabilization */
244 int smsc_version(void) {
246 int* smsc_ver_addr
= (int*)0x4C20;
247 __asm__ ("ldc %0, @%1" : "=r"(v
) : "a"(smsc_ver_addr
));
249 if (v
< 4 || v
== 0xFF) {
259 /* FIXME: tune the delay.
260 Delay doesn't depend on CPU speed in Archos' firmware.
262 for (i
= 0; i
< 100; i
++) {
267 static void extra_init(void) {
273 * lines 0, 1 & 4 are digital, other analog. :
280 nothing to do: all are inputs
281 (reset value of the register is good)
284 /* SMSC chip config (?) */
289 if (smsc_version() < 4) {
295 void set_cpu_frequency(long frequency
) {
296 /* Enable SDRAM refresh, at least 15MHz */
297 if (frequency
< cpu_frequency
)
298 MIUDCNT
= 0x800 | (frequency
* 15/1000000L - 1);
300 set_pll_freq(0, frequency
);
301 PLL0CON
|= 0x4; /* use as CPU clock */
303 cpu_frequency
= frequency
;
304 /* wait states and such not changed by Archos. (!?) */
306 /* Enable SDRAM refresh, 15MHz. */
307 MIUDCNT
= 0x800 | (frequency
* 15/1000000L - 1);
310 /* TODO: when uart is done; sync uart freq */
314 void system_init(void)
316 /* Disable watchdog */
323 /* keep alive (?) -- clear the bit to prevent crash at start (??) */
327 /* smsc chip init (?) */
339 /* PLL0 (cpu osc. frequency) */
340 /* set_cpu_frequency(CPU_FREQ); */
347 /************************
348 * Copy .icode section to icram
350 ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy
, (int)&icodesize
);
353 /***************************
374 /* IRQ10 UART_Rx/UART_Err/ UART_tx INT */
384 void system_reboot (void)
388 int system_memory_guard(int newmode
)
393 #elif defined(CPU_COLDFIRE)
394 /* system code is in target tree for all coldfire targets */
395 #elif CONFIG_CPU == SH7034
400 static const char* const irqname
[] = {
401 "", "", "", "", "IllInstr", "", "IllSltIn","","",
402 "CPUAdrEr", "DMAAdrEr", "NMI", "UserBrk",
403 "","","","","","","","","","","","","","","","","","","",
404 "Trap32","Trap33","Trap34","Trap35","Trap36","Trap37","Trap38","Trap39",
405 "Trap40","Trap41","Trap42","Trap43","Trap44","Trap45","Trap46","Trap47",
406 "Trap48","Trap49","Trap50","Trap51","Trap52","Trap53","Trap54","Trap55",
407 "Trap56","Trap57","Trap58","Trap59","Trap60","Trap61","Trap62","Trap63",
408 "Irq0","Irq1","Irq2","Irq3","Irq4","Irq5","Irq6","Irq7",
409 "Dma0","","Dma1","","Dma2","","Dma3","",
410 "IMIA0","IMIB0","OVI0","", "IMIA1","IMIB1","OVI1","",
411 "IMIA2","IMIB2","OVI2","", "IMIA3","IMIB3","OVI3","",
412 "IMIA4","IMIB4","OVI4","",
413 "Ser0Err","Ser0Rx","Ser0Tx","Ser0TE",
414 "Ser1Err","Ser1Rx","Ser1Tx","Ser1TE",
415 "ParityEr","A/D conv","","","Watchdog","DRAMRefr"
418 #define RESERVE_INTERRUPT(number) "\t.long\t_UIE" #number "\n"
419 #define DEFAULT_INTERRUPT(name, number) "\t.weak\t_" #name \
420 "\n\t.set\t_" #name ",_UIE" #number \
421 "\n\t.long\t_" #name "\n"
426 * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols
427 * defined in an asm block -- silly.
428 * Reset vectors (0..3) are handled in crt0.S */
430 ".section\t.vectors,\"aw\",@progbits\n"
431 DEFAULT_INTERRUPT (GII
, 4)
432 RESERVE_INTERRUPT ( 5)
433 DEFAULT_INTERRUPT (ISI
, 6)
434 RESERVE_INTERRUPT ( 7)
435 RESERVE_INTERRUPT ( 8)
436 DEFAULT_INTERRUPT (CPUAE
, 9)
437 DEFAULT_INTERRUPT (DMAAE
, 10)
438 DEFAULT_INTERRUPT (NMI
, 11)
439 DEFAULT_INTERRUPT (UB
, 12)
440 RESERVE_INTERRUPT ( 13)
441 RESERVE_INTERRUPT ( 14)
442 RESERVE_INTERRUPT ( 15)
443 RESERVE_INTERRUPT ( 16) /* TCB #0 */
444 RESERVE_INTERRUPT ( 17) /* TCB #1 */
445 RESERVE_INTERRUPT ( 18) /* TCB #2 */
446 RESERVE_INTERRUPT ( 19) /* TCB #3 */
447 RESERVE_INTERRUPT ( 20) /* TCB #4 */
448 RESERVE_INTERRUPT ( 21) /* TCB #5 */
449 RESERVE_INTERRUPT ( 22) /* TCB #6 */
450 RESERVE_INTERRUPT ( 23) /* TCB #7 */
451 RESERVE_INTERRUPT ( 24) /* TCB #8 */
452 RESERVE_INTERRUPT ( 25) /* TCB #9 */
453 RESERVE_INTERRUPT ( 26) /* TCB #10 */
454 RESERVE_INTERRUPT ( 27) /* TCB #11 */
455 RESERVE_INTERRUPT ( 28) /* TCB #12 */
456 RESERVE_INTERRUPT ( 29) /* TCB #13 */
457 RESERVE_INTERRUPT ( 30) /* TCB #14 */
458 RESERVE_INTERRUPT ( 31) /* TCB #15 */
459 DEFAULT_INTERRUPT (TRAPA32
, 32)
460 DEFAULT_INTERRUPT (TRAPA33
, 33)
461 DEFAULT_INTERRUPT (TRAPA34
, 34)
462 DEFAULT_INTERRUPT (TRAPA35
, 35)
463 DEFAULT_INTERRUPT (TRAPA36
, 36)
464 DEFAULT_INTERRUPT (TRAPA37
, 37)
465 DEFAULT_INTERRUPT (TRAPA38
, 38)
466 DEFAULT_INTERRUPT (TRAPA39
, 39)
467 DEFAULT_INTERRUPT (TRAPA40
, 40)
468 DEFAULT_INTERRUPT (TRAPA41
, 41)
469 DEFAULT_INTERRUPT (TRAPA42
, 42)
470 DEFAULT_INTERRUPT (TRAPA43
, 43)
471 DEFAULT_INTERRUPT (TRAPA44
, 44)
472 DEFAULT_INTERRUPT (TRAPA45
, 45)
473 DEFAULT_INTERRUPT (TRAPA46
, 46)
474 DEFAULT_INTERRUPT (TRAPA47
, 47)
475 DEFAULT_INTERRUPT (TRAPA48
, 48)
476 DEFAULT_INTERRUPT (TRAPA49
, 49)
477 DEFAULT_INTERRUPT (TRAPA50
, 50)
478 DEFAULT_INTERRUPT (TRAPA51
, 51)
479 DEFAULT_INTERRUPT (TRAPA52
, 52)
480 DEFAULT_INTERRUPT (TRAPA53
, 53)
481 DEFAULT_INTERRUPT (TRAPA54
, 54)
482 DEFAULT_INTERRUPT (TRAPA55
, 55)
483 DEFAULT_INTERRUPT (TRAPA56
, 56)
484 DEFAULT_INTERRUPT (TRAPA57
, 57)
485 DEFAULT_INTERRUPT (TRAPA58
, 58)
486 DEFAULT_INTERRUPT (TRAPA59
, 59)
487 DEFAULT_INTERRUPT (TRAPA60
, 60)
488 DEFAULT_INTERRUPT (TRAPA61
, 61)
489 DEFAULT_INTERRUPT (TRAPA62
, 62)
490 DEFAULT_INTERRUPT (TRAPA63
, 63)
491 DEFAULT_INTERRUPT (IRQ0
, 64)
492 DEFAULT_INTERRUPT (IRQ1
, 65)
493 DEFAULT_INTERRUPT (IRQ2
, 66)
494 DEFAULT_INTERRUPT (IRQ3
, 67)
495 DEFAULT_INTERRUPT (IRQ4
, 68)
496 DEFAULT_INTERRUPT (IRQ5
, 69)
497 DEFAULT_INTERRUPT (IRQ6
, 70)
498 DEFAULT_INTERRUPT (IRQ7
, 71)
499 DEFAULT_INTERRUPT (DEI0
, 72)
500 RESERVE_INTERRUPT ( 73)
501 DEFAULT_INTERRUPT (DEI1
, 74)
502 RESERVE_INTERRUPT ( 75)
503 DEFAULT_INTERRUPT (DEI2
, 76)
504 RESERVE_INTERRUPT ( 77)
505 DEFAULT_INTERRUPT (DEI3
, 78)
506 RESERVE_INTERRUPT ( 79)
507 DEFAULT_INTERRUPT (IMIA0
, 80)
508 DEFAULT_INTERRUPT (IMIB0
, 81)
509 DEFAULT_INTERRUPT (OVI0
, 82)
510 RESERVE_INTERRUPT ( 83)
511 DEFAULT_INTERRUPT (IMIA1
, 84)
512 DEFAULT_INTERRUPT (IMIB1
, 85)
513 DEFAULT_INTERRUPT (OVI1
, 86)
514 RESERVE_INTERRUPT ( 87)
515 DEFAULT_INTERRUPT (IMIA2
, 88)
516 DEFAULT_INTERRUPT (IMIB2
, 89)
517 DEFAULT_INTERRUPT (OVI2
, 90)
518 RESERVE_INTERRUPT ( 91)
519 DEFAULT_INTERRUPT (IMIA3
, 92)
520 DEFAULT_INTERRUPT (IMIB3
, 93)
521 DEFAULT_INTERRUPT (OVI3
, 94)
522 RESERVE_INTERRUPT ( 95)
523 DEFAULT_INTERRUPT (IMIA4
, 96)
524 DEFAULT_INTERRUPT (IMIB4
, 97)
525 DEFAULT_INTERRUPT (OVI4
, 98)
526 RESERVE_INTERRUPT ( 99)
527 DEFAULT_INTERRUPT (REI0
, 100)
528 DEFAULT_INTERRUPT (RXI0
, 101)
529 DEFAULT_INTERRUPT (TXI0
, 102)
530 DEFAULT_INTERRUPT (TEI0
, 103)
531 DEFAULT_INTERRUPT (REI1
, 104)
532 DEFAULT_INTERRUPT (RXI1
, 105)
533 DEFAULT_INTERRUPT (TXI1
, 106)
534 DEFAULT_INTERRUPT (TEI1
, 107)
535 RESERVE_INTERRUPT ( 108)
536 DEFAULT_INTERRUPT (ADITI
, 109)
539 * Must go into the same section as the UIE() handler */
542 "_UIE4:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
543 "_UIE5:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
544 "_UIE6:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
545 "_UIE7:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
546 "_UIE8:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
547 "_UIE9:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
548 "_UIE10:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
549 "_UIE11:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
550 "_UIE12:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
551 "_UIE13:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
552 "_UIE14:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
553 "_UIE15:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
554 "_UIE16:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
555 "_UIE17:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
556 "_UIE18:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
557 "_UIE19:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
558 "_UIE20:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
559 "_UIE21:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
560 "_UIE22:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
561 "_UIE23:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
562 "_UIE24:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
563 "_UIE25:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
564 "_UIE26:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
565 "_UIE27:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
566 "_UIE28:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
567 "_UIE29:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
568 "_UIE30:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
569 "_UIE31:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
570 "_UIE32:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
571 "_UIE33:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
572 "_UIE34:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
573 "_UIE35:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
574 "_UIE36:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
575 "_UIE37:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
576 "_UIE38:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
577 "_UIE39:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
578 "_UIE40:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
579 "_UIE41:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
580 "_UIE42:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
581 "_UIE43:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
582 "_UIE44:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
583 "_UIE45:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
584 "_UIE46:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
585 "_UIE47:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
586 "_UIE48:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
587 "_UIE49:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
588 "_UIE50:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
589 "_UIE51:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
590 "_UIE52:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
591 "_UIE53:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
592 "_UIE54:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
593 "_UIE55:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
594 "_UIE56:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
595 "_UIE57:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
596 "_UIE58:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
597 "_UIE59:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
598 "_UIE60:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
599 "_UIE61:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
600 "_UIE62:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
601 "_UIE63:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
602 "_UIE64:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
603 "_UIE65:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
604 "_UIE66:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
605 "_UIE67:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
606 "_UIE68:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
607 "_UIE69:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
608 "_UIE70:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
609 "_UIE71:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
610 "_UIE72:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
611 "_UIE73:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
612 "_UIE74:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
613 "_UIE75:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
614 "_UIE76:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
615 "_UIE77:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
616 "_UIE78:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
617 "_UIE79:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
618 "_UIE80:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
619 "_UIE81:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
620 "_UIE82:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
621 "_UIE83:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
622 "_UIE84:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
623 "_UIE85:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
624 "_UIE86:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
625 "_UIE87:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
626 "_UIE88:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
627 "_UIE89:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
628 "_UIE90:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
629 "_UIE91:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
630 "_UIE92:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
631 "_UIE93:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
632 "_UIE94:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
633 "_UIE95:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
634 "_UIE96:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
635 "_UIE97:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
636 "_UIE98:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
637 "_UIE99:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
638 "_UIE100:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
639 "_UIE101:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
640 "_UIE102:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
641 "_UIE103:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
642 "_UIE104:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
643 "_UIE105:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
644 "_UIE106:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
645 "_UIE107:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
646 "_UIE108:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
647 "_UIE109:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
651 extern void UIE4(void); /* needed for calculating the UIE number */
653 void UIE (unsigned int pc
) __attribute__((section(".text")));
654 void UIE (unsigned int pc
) /* Unexpected Interrupt or Exception */
656 #if CONFIG_LED == LED_REAL
663 asm volatile ("sts\tpr,%0" : "=r"(n
));
666 lcd_clear_display ();
667 #ifdef HAVE_LCD_BITMAP
668 lcd_setfont(FONT_SYSFIXED
);
670 /* output exception */
671 n
= (n
- (unsigned)UIE4
+ 12)>>2; /* get exception or interrupt number */
672 snprintf(str
,sizeof(str
),"I%02x:%s",n
,irqname
[n
]);
674 snprintf(str
,sizeof(str
),"at %08x",pc
);
677 #ifdef HAVE_LCD_BITMAP
683 #if CONFIG_LED == LED_REAL
692 /* try to restart firmware if ON is pressed */
693 #if CONFIG_KEYPAD == PLAYER_PAD
695 #elif CONFIG_KEYPAD == RECORDER_PAD
697 if (!(PCDR
& 0x0008))
701 #elif CONFIG_KEYPAD == ONDIO_PAD
702 if (!(PCDR
& 0x0008))
705 /* enable the watchguard timer, but don't service it */
706 RSTCSR_W
= 0x5a40; /* Reset enabled, power-on reset */
707 TCSR_W
= 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */
712 void system_init(void)
714 /* Disable all interrupts */
721 /* NMI level low, falling edge on all interrupts */
724 /* Enable burst and RAS down mode on DRAM */
727 /* Activate Warp mode (simultaneous internal and external mem access) */
730 /* Bus state controller initializations. These are only necessary when
731 running from flash. */
732 WCR1
= 0x40FD; /* Long wait states for CS6 (ATA), short for the rest. */
733 WCR3
= 0x8000; /* WAIT is pulled up, 1 state inserted for CS6 */
736 void system_reboot (void)
738 set_irq_level(HIGHEST_IRQ_LEVEL
);
740 asm volatile ("ldc\t%0,vbr" : : "r"(0));
742 PACR2
|= 0x4000; /* for coldstart detection */
750 asm volatile ("jmp @%0; mov.l @%1,r15" : :
751 "r"(*(int*)0),"r"(4));
754 /* Utilise the user break controller to catch invalid memory accesses. */
755 int system_memory_guard(int newmode
)
757 static const struct {
761 } modes
[MAXMEMGUARD
] = {
763 { 0x00000000, 0x00000000, 0x0000 },
764 /* catch writes to area 02 (flash ROM) */
765 { 0x02000000, 0x00FFFFFF, 0x00F8 },
766 /* catch all accesses to areas 00 (internal ROM) and 01 (free) */
767 { 0x00000000, 0x01FFFFFF, 0x00FC }
770 int oldmode
= MEMGUARD_NONE
;
773 /* figure out the old mode from what is in the UBC regs. If the register
774 values don't match any mode, assume MEMGUARD_NONE */
775 for (i
= MEMGUARD_NONE
; i
< MAXMEMGUARD
; i
++)
777 if (BAR
== modes
[i
].addr
&& BAMR
== modes
[i
].mask
&&
785 if (newmode
== MEMGUARD_KEEP
)
788 BBR
= 0; /* switch off everything first */
790 /* always set the UBC according to the mode, in case the old settings
791 didn't match any valid mode */
792 BAR
= modes
[newmode
].addr
;
793 BAMR
= modes
[newmode
].mask
;
794 BBR
= modes
[newmode
].bbr
;
798 #elif defined(CPU_ARM)
800 static const char* const uiename
[] = {
801 "Undefined instruction", "Prefetch abort", "Data abort"
804 /* Unexpected Interrupt or Exception handler. Currently only deals with
805 exceptions, but will deal with interrupts later.
807 void UIE(unsigned int pc
, unsigned int num
)
812 #ifdef HAVE_LCD_BITMAP
813 lcd_setfont(FONT_SYSFIXED
);
815 lcd_puts(0, 0, uiename
[num
]);
816 snprintf(str
, sizeof(str
), "at %08x", pc
);
822 /* TODO: perhaps add button handling in here when we get a polling
828 #if CONFIG_CPU==PP5020
830 unsigned int ipod_hw_rev
;
833 extern void TIMER1(void);
834 extern void TIMER2(void);
836 #if defined(IPOD_MINI) /* mini 1 only, mini 2G uses iPod 4G code */
837 extern void ipod_mini_button_int(void);
841 if (CPU_INT_STAT
& TIMER1_MASK
)
843 else if (CPU_INT_STAT
& TIMER2_MASK
)
845 else if (CPU_HI_INT_STAT
& GPIO_MASK
)
846 ipod_mini_button_int();
848 #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) || defined(ELIO_TPJ1022)
849 /* TODO: this should really be in the target tree, but moving it there caused
850 crt0.S not to find it while linking */
853 if (CPU_INT_STAT
& TIMER1_MASK
)
855 else if (CPU_INT_STAT
& TIMER2_MASK
)
859 extern void ipod_4g_button_int(void);
863 if (CPU_INT_STAT
& TIMER1_MASK
)
865 else if (CPU_INT_STAT
& TIMER2_MASK
)
867 else if (CPU_HI_INT_STAT
& I2C_MASK
)
868 ipod_4g_button_int();
871 #endif /* BOOTLOADER */
873 unsigned int current_core(void)
875 if(((*(volatile unsigned long *)(0x60000000)) & 0xff) == 0x55)
883 /* TODO: The following two function have been lifted straight from IPL, and
884 hence have a lot of numeric addresses used straight. I'd like to use
885 #defines for these, but don't know what most of them are for or even what
886 they should be named. Because of this I also have no way of knowing how
887 to extend the funtions to do alternate cache configurations and/or
888 some other CPU frequency scaling. */
891 static void ipod_init_cache(void)
893 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
896 /* cache init mode? */
897 outl(0x4, 0x6000C000);
899 /* PP5002 has 8KB cache */
900 for (i
= 0xf0004000; i
< 0xf0006000; i
+= 16) {
904 outl(0x0, 0xf000f040);
905 outl(0x3fc0, 0xf000f044);
908 outl(0x1, 0x6000C000);
910 for (i
= 0x10000000; i
< 0x10002000; i
+= 16)
915 /* Not all iPod targets support CPU freq. boosting yet */
916 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
917 void set_cpu_frequency(long frequency
)
919 unsigned long postmult
;
921 if (frequency
== CPUFREQ_NORMAL
)
922 postmult
= CPUFREQ_NORMAL_MULT
;
923 else if (frequency
== CPUFREQ_MAX
)
924 postmult
= CPUFREQ_MAX_MULT
;
926 postmult
= CPUFREQ_DEFAULT_MULT
;
927 cpu_frequency
= frequency
;
930 outl(inl(0x70000020) | (1<<30), 0x70000020);
932 /* Select 24MHz crystal as clock source? */
933 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
935 /* Clock frequency = (24/8)*postmult */
936 outl(0xaa020000 | 8 | (postmult
<< 8), 0x60006034);
938 /* Wait for PLL relock? */
941 /* Select PLL as clock source? */
942 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
944 #if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
945 /* We don't know why the timer interrupt gets disabled on the PP5020
946 based ipods, but without the following line, the 4Gs will freeze
947 when CPU frequency changing is enabled.
949 Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used
950 elsewhere to enable interrupts) doesn't work, we need "|=".
952 It's not needed on the PP5021 and PP5022 ipods.
955 /* unmask interrupt source */
956 CPU_INT_EN
|= TIMER1_MASK
;
959 #elif !defined(BOOTLOADER)
960 void ipod_set_cpu_frequency(void)
963 outl(inl(0x70000020) | (1<<30), 0x70000020);
965 /* Select 24MHz crystal as clock source? */
966 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020);
968 /* Clock frequency = (24/8)*25 = 75MHz */
969 outl(0xaa020000 | 8 | (25 << 8), 0x60006034);
970 /* Wait for PLL relock? */
973 /* Select PLL as clock source? */
974 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
978 void system_init(void)
981 /* The hw revision is written to the last 4 bytes of SDRAM by the
982 bootloader - we save it before Rockbox overwrites it. */
983 ipod_hw_rev
= (*((volatile unsigned long*)(0x01fffffc)));
985 /* disable all irqs */
986 outl(-1, 0x60001138);
987 outl(-1, 0x60001128);
988 outl(-1, 0x6000111c);
990 outl(-1, 0x60001038);
991 outl(-1, 0x60001028);
992 outl(-1, 0x6000101c);
993 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
994 ipod_set_cpu_frequency();
1000 void system_reboot(void)
1003 DEV_RS
|= DEV_SYSTEM
;
1006 int system_memory_guard(int newmode
)
1011 #elif CONFIG_CPU==PP5002
1012 unsigned int ipod_hw_rev
;
1014 extern void TIMER1(void);
1015 extern void TIMER2(void);
1019 if (CPU_INT_STAT
& TIMER1_MASK
)
1021 else if (CPU_INT_STAT
& TIMER2_MASK
)
1027 unsigned int current_core(void)
1029 if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55)
1037 /* TODO: The following two function have been lifted straight from IPL, and
1038 hence have a lot of numeric addresses used straight. I'd like to use
1039 #defines for these, but don't know what most of them are for or even what
1040 they should be named. Because of this I also have no way of knowing how
1041 to extend the funtions to do alternate cache configurations and/or
1042 some other CPU frequency scaling. */
1045 static void ipod_init_cache(void)
1048 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
1049 outl(inl(0xcf004050) & ~0x700, 0xcf004050);
1050 outl(0x4000, 0xcf004020);
1052 outl(0x2, 0xcf004024);
1054 /* PP5002 has 8KB cache */
1055 for (i
= 0xf0004000; i
< (int)(0xf0006000); i
+= 16) {
1059 outl(0x0, 0xf000f020);
1060 outl(0x3fc0, 0xf000f024);
1062 outl(0x3, 0xcf004024);
1066 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1067 void set_cpu_frequency(long frequency
)
1069 unsigned long postmult
;
1071 if (frequency
== CPUFREQ_NORMAL
)
1072 postmult
= CPUFREQ_NORMAL_MULT
;
1073 else if (frequency
== CPUFREQ_MAX
)
1074 postmult
= CPUFREQ_MAX_MULT
;
1076 postmult
= CPUFREQ_DEFAULT_MULT
;
1077 cpu_frequency
= frequency
;
1079 outl(0x02, 0xcf005008);
1080 outl(0x55, 0xcf00500c);
1081 outl(0x6000, 0xcf005010);
1083 /* Clock frequency = (24/8)*postmult */
1084 outl(8, 0xcf005018);
1085 outl(postmult
, 0xcf00501c);
1087 outl(0xe000, 0xcf005010);
1089 /* Wait for PLL relock? */
1092 /* Select PLL as clock source? */
1093 outl(0xa8, 0xcf00500c);
1095 #elif !defined(BOOTLOADER)
1096 static void ipod_set_cpu_speed(void)
1098 outl(0x02, 0xcf005008);
1099 outl(0x55, 0xcf00500c);
1100 outl(0x6000, 0xcf005010);
1102 // 75 MHz (24/24 * 75) (default)
1103 outl(24, 0xcf005018);
1104 outl(75, 0xcf00501c);
1108 // 66 MHz (24/3 * 8)
1109 outl(3, 0xcf005018);
1110 outl(8, 0xcf00501c);
1113 outl(0xe000, 0xcf005010);
1117 outl(0xa8, 0xcf00500c);
1121 void system_init(void)
1124 ipod_hw_rev
= (*((volatile unsigned long*)(0x01fffffc)));
1125 outl(-1, 0xcf00101c);
1126 outl(-1, 0xcf001028);
1127 outl(-1, 0xcf001038);
1128 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
1129 ipod_set_cpu_speed();
1135 void system_reboot(void)
1137 outl(inl(0xcf005030) | 0x4, 0xcf005030);
1140 int system_memory_guard(int newmode
)
1146 #elif CONFIG_CPU==PNX0101
1148 interrupt_handler_t interrupt_vector
[0x1d] __attribute__ ((section(".idata")));
1150 #define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg)))
1152 static inline unsigned long irq_read(int reg
)
1154 unsigned long v
, v2
;
1163 #define IRQ_WRITE_WAIT(reg, val, cond) \
1164 do { unsigned long v, v2; \
1166 IRQ_REG(reg) = (val); \
1168 v2 = IRQ_REG(reg); \
1169 } while ((v != v2) || !(cond)); \
1172 static void undefined_int(void)
1178 int n
= irq_read(0x100) >> 3;
1179 (*(interrupt_vector
[n
]))();
1186 void irq_enable_int(int n
)
1188 IRQ_WRITE_WAIT(0x404 + n
* 4, 0x4010000, v
& 0x10000);
1191 void irq_set_int_handler(int n
, interrupt_handler_t handler
)
1193 interrupt_vector
[n
+ 1] = handler
;
1196 void system_init(void)
1200 /* turn off watchdog */
1201 (*(volatile unsigned long *)0x80002804) = 0;
1204 IRQ_WRITE_WAIT(0x100, 0, v == 0);
1205 IRQ_WRITE_WAIT(0x104, 0, v == 0);
1206 IRQ_WRITE_WAIT(0, 0, v == 0);
1207 IRQ_WRITE_WAIT(4, 0, v == 0);
1210 for (i
= 0; i
< 0x1c; i
++)
1212 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x1e000001, (v
& 0x3010f) == 1);
1213 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x4000000, (v
& 0x10000) == 0);
1214 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x10000001, (v
& 0xf) == 1);
1215 interrupt_vector
[i
+ 1] = undefined_int
;
1217 interrupt_vector
[0] = undefined_int
;
1221 void system_reboot(void)
1223 (*(volatile unsigned long *)0x80002804) = 1;
1227 int system_memory_guard(int newmode
)
1233 #endif /* CPU_ARM */
1234 #endif /* CONFIG_CPU */