Fix remote screen check in graphic equalizer, so that it can be used on logf-enabled...
[Rockbox.git] / firmware / system.c
blob242d84d16c34a4753e2c2ea39df3cdacc49f3ae1
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;
37 #ifdef CPU_BOOST_TRACKING
38 #define CPU_BOOST_TRACKER_MAX 15
39 static char cpu_boost_tracker[CPU_BOOST_TRACKER_MAX+1] = "";
40 #endif
42 int get_cpu_boost_counter(void)
44 return boost_counter;
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)
55 if(on_off)
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';
69 else
71 /* Lower the frequency if the counter reaches 0 */
72 if(--boost_counter == 0)
74 if(cpu_idle)
75 set_cpu_frequency(CPUFREQ_DEFAULT);
76 else
77 set_cpu_frequency(CPUFREQ_NORMAL);
80 /* Safety measure */
81 if(boost_counter < 0)
82 boost_counter = 0;
84 /* Remove an entry from the boost tracker */
85 int l = strlen(cpu_boost_tracker);
86 while (l >= 0 && cpu_boost_tracker[l] != id)
87 l--;
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];
93 l++;
97 #endif
99 void cpu_boost(bool on_off)
101 cpu_boost_id(on_off, '?');
104 void cpu_idle_mode(bool on_off)
106 cpu_idle = on_off;
108 /* We need to adjust the frequency immediately if the CPU
109 isn't boosted */
110 if(boost_counter == 0)
112 if(cpu_idle)
113 set_cpu_frequency(CPUFREQ_DEFAULT);
114 else
115 set_cpu_frequency(CPUFREQ_NORMAL);
119 #endif
120 #if CONFIG_CPU == S3C2440
122 void system_reboot(void) {
125 void system_init(void) {
128 #endif
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;
135 # ifndef BOOTLOADER
136 int oldmode;
137 oldmode = system_memory_guard(MEMGUARD_NONE);
138 # endif
140 memcpy(&hdr, src, sizeof(struct flash_header));
142 # ifndef BOOTLOADER
143 system_memory_guard(oldmode);
144 # endif
146 if (hdr.magic != FLASH_MAGIC)
147 return false;
149 return true;
151 #else
152 bool detect_flashed_rockbox(void)
154 return false;
156 #endif
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.
167 (Used by Archos) */
168 do {
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);
176 ddma_wait_idle();
177 long externalAddress = (long) extAddr;
178 long internalAddress = ((long) intAddr) & 0xFFFF;
179 /* HW wants those two in word units. */
180 num /= 2;
181 externalAddress /= 2;
183 DDMACFG = (dir << 1) | (mem << 2);
184 DDMAIADR = internalAddress;
185 DDMAEADR = externalAddress;
186 DDMANUM = num;
187 DDMACOM |= 0x4; /* start */
189 ddma_wait_idle(); /* wait for completion */
190 set_irq_level(irq);
193 static void ddma_wait_idle_noicode(void)
195 do {
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. */
205 num /= 2;
206 externalAddress /= 2;
208 DDMACFG = (dir << 1) | (mem << 2);
209 DDMAIADR = internalAddress;
210 DDMAEADR = externalAddress;
211 DDMANUM = num;
212 DDMACOM |= 0x4; /* start */
214 ddma_wait_idle_noicode(); /* wait for completion */
215 set_irq_level(irq);
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) {
228 plldata = &PLL0DATA;
229 pllcon = &PLL0CON;
230 } else {
231 plldata = &PLL1DATA;
232 pllcon = &PLL1CON;
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] */
238 *plldata = m << 2;
239 *pllcon |= 0x1; /* activate */
240 do {
241 } while ((*pllcon & 0x2) == 0); /* wait for stabilization */
244 int smsc_version(void) {
245 int v;
246 int* smsc_ver_addr = (int*)0x4C20;
247 __asm__ ("ldc %0, @%1" : "=r"(v) : "a"(smsc_ver_addr));
248 v &= 0xFF;
249 if (v < 4 || v == 0xFF) {
250 return 3;
252 return v;
257 void smsc_delay() {
258 int i;
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) {
268 /* Power on stuff */
269 P1 |= 0x07;
270 P1CON |= 0x1f;
272 /* P5 conf
273 * lines 0, 1 & 4 are digital, other analog. :
275 P5CON = 0xec;
277 P6CON = 0x19;
279 /* P7 conf
280 nothing to do: all are inputs
281 (reset value of the register is good)
284 /* SMSC chip config (?) */
285 P10CON |= 0x20;
286 P6 &= 0xF7;
287 P10 &= 0x20;
288 smsc_delay();
289 if (smsc_version() < 4) {
290 P6 |= 0x08;
291 P10 |= 0x20;
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);
309 tick_start(1000/HZ);
310 /* TODO: when uart is done; sync uart freq */
313 /* called by crt0 */
314 void system_init(void)
316 /* Disable watchdog */
317 WDTEN = 0xA5;
319 /****************
320 * GPIO ports
323 /* keep alive (?) -- clear the bit to prevent crash at start (??) */
324 P8 = 0x00;
325 P8CON = 0x01;
327 /* smsc chip init (?) */
328 P10 = 0x20;
329 P6 = 0x08;
331 P10CON = 0x20;
332 P6CON = 0x08;
334 /********
335 * CPU
339 /* PLL0 (cpu osc. frequency) */
340 /* set_cpu_frequency(CPU_FREQ); */
343 /*******************
344 * configure S(D)RAM
347 /************************
348 * Copy .icode section to icram
350 ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize);
353 /***************************
354 * Interrupts
357 /* priorities ? */
359 /* mask */
360 IMR0 = 0;
361 IMR1 = 0;
364 /* IRQ0 BT INT */
365 /* IRQ1 RTC INT */
366 /* IRQ2 TA INT */
367 /* IRQ3 TAOV INT */
368 /* IRQ4 TB INT */
369 /* IRQ5 TBOV INT */
370 /* IRQ6 TC INT */
371 /* IRQ7 TCOV INT */
372 /* IRQ8 USB INT */
373 /* IRQ9 PPIC INT */
374 /* IRQ10 UART_Rx/UART_Err/ UART_tx INT */
375 /* IRQ11 IIC INT */
376 /* IRQ12 SIO INT */
377 /* IRQ13 IIS0 INT */
378 /* IRQ14 IIS1 INT */
379 /* IRQ15 */
381 extra_init();
384 void system_reboot (void)
388 int system_memory_guard(int newmode)
390 (void)newmode;
391 return 0;
393 #elif defined(CPU_COLDFIRE)
394 /* system code is in target tree for all coldfire targets */
395 #elif CONFIG_CPU == SH7034
396 #include "led.h"
397 #include "system.h"
398 #include "rolo.h"
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"
423 asm (
425 /* Vector table.
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)
538 /* UIE# block.
539 * Must go into the same section as the UIE() handler */
541 "\t.text\n"
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
657 bool state = false;
658 int i = 0;
659 #endif
660 unsigned int n;
661 char str[32];
663 asm volatile ("sts\tpr,%0" : "=r"(n));
665 /* clear screen */
666 lcd_clear_display ();
667 #ifdef HAVE_LCD_BITMAP
668 lcd_setfont(FONT_SYSFIXED);
669 #endif
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]);
673 lcd_puts(0,0,str);
674 snprintf(str,sizeof(str),"at %08x",pc);
675 lcd_puts(0,1,str);
677 #ifdef HAVE_LCD_BITMAP
678 lcd_update ();
679 #endif
681 while (1)
683 #if CONFIG_LED == LED_REAL
684 if (--i <= 0)
686 state = !state;
687 led(state);
688 i = 240000;
690 #endif
692 /* try to restart firmware if ON is pressed */
693 #if CONFIG_KEYPAD == PLAYER_PAD
694 if (!(PADRL & 0x20))
695 #elif CONFIG_KEYPAD == RECORDER_PAD
696 #ifdef HAVE_FMADC
697 if (!(PCDR & 0x0008))
698 #else
699 if (!(PBDRH & 0x01))
700 #endif
701 #elif CONFIG_KEYPAD == ONDIO_PAD
702 if (!(PCDR & 0x0008))
703 #endif
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 */
715 IPRA = 0;
716 IPRB = 0;
717 IPRC = 0;
718 IPRD = 0;
719 IPRE = 0;
721 /* NMI level low, falling edge on all interrupts */
722 ICR = 0;
724 /* Enable burst and RAS down mode on DRAM */
725 DCR |= 0x5000;
727 /* Activate Warp mode (simultaneous internal and external mem access) */
728 BCR |= 0x2000;
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 */
743 IPRA = 0;
744 IPRB = 0;
745 IPRC = 0;
746 IPRD = 0;
747 IPRE = 0;
748 ICR = 0;
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 {
758 unsigned long addr;
759 unsigned long mask;
760 unsigned short bbr;
761 } modes[MAXMEMGUARD] = {
762 /* catch nothing */
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;
771 int i;
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 &&
778 BBR == modes[i].bbr)
780 oldmode = i;
781 break;
785 if (newmode == MEMGUARD_KEEP)
786 newmode = oldmode;
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;
796 return oldmode;
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)
809 char str[32];
811 lcd_clear_display();
812 #ifdef HAVE_LCD_BITMAP
813 lcd_setfont(FONT_SYSFIXED);
814 #endif
815 lcd_puts(0, 0, uiename[num]);
816 snprintf(str, sizeof(str), "at %08x", pc);
817 lcd_puts(0, 1, str);
818 lcd_update();
820 while (1)
822 /* TODO: perhaps add button handling in here when we get a polling
823 driver some day.
828 #if CONFIG_CPU==PP5020
830 unsigned int ipod_hw_rev;
832 #ifndef BOOTLOADER
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);
839 void irq(void)
841 if (CPU_INT_STAT & TIMER1_MASK)
842 TIMER1();
843 else if (CPU_INT_STAT & TIMER2_MASK)
844 TIMER2();
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 */
851 void irq(void)
853 if (CPU_INT_STAT & TIMER1_MASK)
854 TIMER1();
855 else if (CPU_INT_STAT & TIMER2_MASK)
856 TIMER2();
858 #else
859 extern void ipod_4g_button_int(void);
861 void irq(void)
863 if (CPU_INT_STAT & TIMER1_MASK)
864 TIMER1();
865 else if (CPU_INT_STAT & TIMER2_MASK)
866 TIMER2();
867 else if (CPU_HI_INT_STAT & I2C_MASK)
868 ipod_4g_button_int();
870 #endif
871 #endif /* BOOTLOADER */
873 unsigned int current_core(void)
875 if(((*(volatile unsigned long *)(0x60000000)) & 0xff) == 0x55)
877 return CPU;
879 return COP;
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. */
890 #ifndef BOOTLOADER
891 static void ipod_init_cache(void)
893 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
894 unsigned i;
896 /* cache init mode? */
897 outl(0x4, 0x6000C000);
899 /* PP5002 has 8KB cache */
900 for (i = 0xf0004000; i < 0xf0006000; i += 16) {
901 outl(0x0, i);
904 outl(0x0, 0xf000f040);
905 outl(0x3fc0, 0xf000f044);
907 /* enable cache */
908 outl(0x1, 0x6000C000);
910 for (i = 0x10000000; i < 0x10002000; i += 16)
911 inb(i);
913 #endif
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;
925 else
926 postmult = CPUFREQ_DEFAULT_MULT;
927 cpu_frequency = frequency;
929 /* Enable PLL? */
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? */
939 udelay(2000);
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;
957 #endif
959 #elif !defined(BOOTLOADER)
960 void ipod_set_cpu_frequency(void)
962 /* Enable PLL? */
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? */
971 udelay(2000);
973 /* Select PLL as clock source? */
974 outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020);
976 #endif
978 void system_init(void)
980 #ifndef BOOTLOADER
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();
995 #endif
996 ipod_init_cache();
997 #endif
1000 void system_reboot(void)
1002 /* Reboot */
1003 DEV_RS |= DEV_SYSTEM;
1006 int system_memory_guard(int newmode)
1008 (void)newmode;
1009 return 0;
1011 #elif CONFIG_CPU==PP5002
1012 unsigned int ipod_hw_rev;
1013 #ifndef BOOTLOADER
1014 extern void TIMER1(void);
1015 extern void TIMER2(void);
1017 void irq(void)
1019 if (CPU_INT_STAT & TIMER1_MASK)
1020 TIMER1();
1021 else if (CPU_INT_STAT & TIMER2_MASK)
1022 TIMER2();
1025 #endif
1027 unsigned int current_core(void)
1029 if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55)
1031 return CPU;
1033 return COP;
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. */
1044 #ifndef BOOTLOADER
1045 static void ipod_init_cache(void)
1047 int i =0;
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) {
1056 outl(0x0, i);
1059 outl(0x0, 0xf000f020);
1060 outl(0x3fc0, 0xf000f024);
1062 outl(0x3, 0xcf004024);
1064 #endif
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;
1075 else
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? */
1090 udelay(2000);
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);
1101 #if 1
1102 // 75 MHz (24/24 * 75) (default)
1103 outl(24, 0xcf005018);
1104 outl(75, 0xcf00501c);
1105 #endif
1107 #if 0
1108 // 66 MHz (24/3 * 8)
1109 outl(3, 0xcf005018);
1110 outl(8, 0xcf00501c);
1111 #endif
1113 outl(0xe000, 0xcf005010);
1115 udelay(2000);
1117 outl(0xa8, 0xcf00500c);
1119 #endif
1121 void system_init(void)
1123 #ifndef BOOTLOADER
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();
1130 #endif
1131 ipod_init_cache();
1132 #endif
1135 void system_reboot(void)
1137 outl(inl(0xcf005030) | 0x4, 0xcf005030);
1140 int system_memory_guard(int newmode)
1142 (void)newmode;
1143 return 0;
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;
1157 v = IRQ_REG(reg);
1158 v2 = IRQ_REG(reg);
1159 } while (v != v2);
1160 return v;
1163 #define IRQ_WRITE_WAIT(reg, val, cond) \
1164 do { unsigned long v, v2; \
1165 do { \
1166 IRQ_REG(reg) = (val); \
1167 v = IRQ_REG(reg); \
1168 v2 = IRQ_REG(reg); \
1169 } while ((v != v2) || !(cond)); \
1170 } while (0);
1172 static void undefined_int(void)
1176 void irq(void)
1178 int n = irq_read(0x100) >> 3;
1179 (*(interrupt_vector[n]))();
1182 void fiq(void)
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)
1198 int i;
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;
1224 while (1);
1227 int system_memory_guard(int newmode)
1229 (void)newmode;
1230 return 0;
1233 #endif /* CPU_ARM */
1234 #endif /* CONFIG_CPU */