diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 5 | ||||
-rw-r--r-- | firmware/app.lds | 2 | ||||
-rw-r--r-- | firmware/export/config-ifp7xx.h | 4 | ||||
-rw-r--r-- | firmware/export/pnx0101.h | 143 | ||||
-rw-r--r-- | firmware/export/system.h | 7 | ||||
-rw-r--r-- | firmware/export/timer.h | 2 | ||||
-rw-r--r-- | firmware/kernel.c | 20 | ||||
-rw-r--r-- | firmware/system.c | 87 | ||||
-rw-r--r-- | firmware/target/arm/crt0-pnx0101.S | 229 | ||||
-rw-r--r-- | firmware/target/arm/crt0.S | 24 | ||||
-rw-r--r-- | firmware/target/arm/system-pnx0101.c | 351 | ||||
-rw-r--r-- | firmware/timer.c | 48 |
12 files changed, 795 insertions, 127 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index d83f626977..65ae84b45d 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -278,6 +278,9 @@ drivers/i2c-pnx0101.c | |||
278 | #elif CONFIG_I2C == I2C_S3C2440 | 278 | #elif CONFIG_I2C == I2C_S3C2440 |
279 | /* no i2c driver yet */ | 279 | /* no i2c driver yet */ |
280 | #endif | 280 | #endif |
281 | #if CONFIG_CPU == PNX0101 | ||
282 | target/arm/system-pnx0101.c | ||
283 | #endif | ||
281 | #if defined(CPU_PP) | 284 | #if defined(CPU_PP) |
282 | #ifdef BOOTLOADER | 285 | #ifdef BOOTLOADER |
283 | target/arm/crt0-pp-bl.S | 286 | target/arm/crt0-pp-bl.S |
@@ -286,6 +289,8 @@ target/arm/pcm-pp.c | |||
286 | target/arm/audio-pp.c | 289 | target/arm/audio-pp.c |
287 | target/arm/crt0-pp.S | 290 | target/arm/crt0-pp.S |
288 | #endif | 291 | #endif |
292 | #elif CONFIG_CPU == PNX0101 | ||
293 | target/arm/crt0-pnx0101.S | ||
289 | #elif defined(CPU_ARM) | 294 | #elif defined(CPU_ARM) |
290 | target/arm/crt0.S | 295 | target/arm/crt0.S |
291 | #endif /* defined(CPU_*) */ | 296 | #endif /* defined(CPU_*) */ |
diff --git a/firmware/app.lds b/firmware/app.lds index eb63fd8195..f1a02b56d7 100644 --- a/firmware/app.lds +++ b/firmware/app.lds | |||
@@ -9,6 +9,8 @@ OUTPUT_FORMAT(elf32-littlearm) | |||
9 | OUTPUT_ARCH(arm) | 9 | OUTPUT_ARCH(arm) |
10 | #ifdef CPU_PP | 10 | #ifdef CPU_PP |
11 | INPUT(target/arm/crt0-pp.o) | 11 | INPUT(target/arm/crt0-pp.o) |
12 | #elif CONFIG_CPU == PNX0101 | ||
13 | INPUT(target/arm/crt0-pnx0101.o) | ||
12 | #elif defined(CPU_ARM) | 14 | #elif defined(CPU_ARM) |
13 | INPUT(target/arm/crt0.o) | 15 | INPUT(target/arm/crt0.o) |
14 | #endif | 16 | #endif |
diff --git a/firmware/export/config-ifp7xx.h b/firmware/export/config-ifp7xx.h index d9c7590c0b..575571eb97 100644 --- a/firmware/export/config-ifp7xx.h +++ b/firmware/export/config-ifp7xx.h | |||
@@ -80,7 +80,7 @@ | |||
80 | #define CONFIG_BACKLIGHT BL_IRIVER_IFP7XX /* port controlled */ | 80 | #define CONFIG_BACKLIGHT BL_IRIVER_IFP7XX /* port controlled */ |
81 | 81 | ||
82 | /* Define this to the CPU frequency */ | 82 | /* Define this to the CPU frequency */ |
83 | #define CPU_FREQ 30000000 | 83 | #define CPU_FREQ 48000000 |
84 | 84 | ||
85 | #define CONFIG_LCD LCD_IFP7XX | 85 | #define CONFIG_LCD LCD_IFP7XX |
86 | 86 | ||
@@ -98,7 +98,7 @@ | |||
98 | #define HAVE_GDB_API | 98 | #define HAVE_GDB_API |
99 | 99 | ||
100 | /* Define this if you have adjustable CPU frequency */ | 100 | /* Define this if you have adjustable CPU frequency */ |
101 | //#define HAVE_ADJUSTABLE_CPU_FREQ | 101 | #define HAVE_ADJUSTABLE_CPU_FREQ |
102 | 102 | ||
103 | #define BOOTFILE_EXT "iriver" | 103 | #define BOOTFILE_EXT "iriver" |
104 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 104 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
diff --git a/firmware/export/pnx0101.h b/firmware/export/pnx0101.h index 4867c6b25d..8ff42de57a 100644 --- a/firmware/export/pnx0101.h +++ b/firmware/export/pnx0101.h | |||
@@ -78,4 +78,147 @@ | |||
78 | 78 | ||
79 | #define CODECVOL (*(volatile unsigned long *)0x80200398) | 79 | #define CODECVOL (*(volatile unsigned long *)0x80200398) |
80 | 80 | ||
81 | #ifndef ASM | ||
82 | |||
83 | /* Clock generation unit */ | ||
84 | |||
85 | struct pnx0101_cgu { | ||
86 | unsigned long base_scr[12]; | ||
87 | unsigned long base_fs1[12]; | ||
88 | unsigned long base_fs2[12]; | ||
89 | unsigned long base_ssr[12]; | ||
90 | unsigned long clk_pcr[73]; | ||
91 | unsigned long clk_psr[73]; | ||
92 | unsigned long clk_esr[67]; | ||
93 | unsigned long base_bcr[3]; | ||
94 | unsigned long base_fdc[18]; | ||
95 | }; | ||
96 | |||
97 | #define CGU (*(volatile struct pnx0101_cgu *)0x80004000) | ||
98 | |||
99 | #define PNX0101_SEL_STAGE_SYS 0 | ||
100 | #define PNX0101_SEL_STAGE_APB0 1 | ||
101 | #define PNX0101_SEL_STAGE_APB1 2 | ||
102 | #define PNX0101_SEL_STAGE_APB3 3 | ||
103 | #define PNX0101_SEL_STAGE_DAIO 9 | ||
104 | |||
105 | #define PNX0101_HIPREC_FDC 16 | ||
106 | |||
107 | #define PNX0101_FIRST_DIV_SYS 0 | ||
108 | #define PNX0101_N_DIV_SYS 7 | ||
109 | #define PNX0101_FIRST_DIV_APB0 7 | ||
110 | #define PNX0101_N_DIV_APB0 2 | ||
111 | #define PNX0101_FIRST_DIV_APB1 9 | ||
112 | #define PNX0101_N_DIV_APB1 1 | ||
113 | #define PNX0101_FIRST_DIV_APB3 10 | ||
114 | #define PNX0101_N_DIV_APB3 1 | ||
115 | #define PNX0101_FIRST_DIV_DAIO 12 | ||
116 | #define PNX0101_N_DIV_DAIO 6 | ||
117 | |||
118 | #define PNX0101_BCR_SYS 0 | ||
119 | #define PNX0101_BCR_APB0 1 | ||
120 | #define PNX0101_BCR_DAIO 2 | ||
121 | |||
122 | #define PNX0101_FIRST_ESR_SYS 0 | ||
123 | #define PNX0101_N_ESR_SYS 28 | ||
124 | #define PNX0101_FIRST_ESR_APB0 28 | ||
125 | #define PNX0101_N_ESR_APB0 9 | ||
126 | #define PNX0101_FIRST_ESR_APB1 37 | ||
127 | #define PNX0101_N_ESR_APB1 4 | ||
128 | #define PNX0101_FIRST_ESR_APB3 41 | ||
129 | #define PNX0101_N_ESR_APB3 16 | ||
130 | #define PNX0101_FIRST_ESR_DAIO 58 | ||
131 | #define PNX0101_N_ESR_DAIO 9 | ||
132 | |||
133 | #define PNX0101_ESR_APB1 0x25 | ||
134 | #define PNX0101_ESR_T0 0x26 | ||
135 | #define PNX0101_ESR_T1 0x27 | ||
136 | #define PNX0101_ESR_I2C 0x28 | ||
137 | |||
138 | #define PNX0101_CLOCK_APB1 0x25 | ||
139 | #define PNX0101_CLOCK_T0 0x26 | ||
140 | #define PNX0101_CLOCK_T1 0x27 | ||
141 | #define PNX0101_CLOCK_I2C 0x28 | ||
142 | |||
143 | #define PNX0101_MAIN_CLOCK_FAST 1 | ||
144 | #define PNX0101_MAIN_CLOCK_MAIN_PLL 9 | ||
145 | |||
146 | struct pnx0101_pll { | ||
147 | unsigned long hpfin; | ||
148 | unsigned long hpmdec; | ||
149 | unsigned long hpndec; | ||
150 | unsigned long hppdec; | ||
151 | unsigned long hpmode; | ||
152 | unsigned long hpstat; | ||
153 | unsigned long hpack; | ||
154 | unsigned long hpreq; | ||
155 | unsigned long hppad1; | ||
156 | unsigned long hppad2; | ||
157 | unsigned long hppad3; | ||
158 | unsigned long hpselr; | ||
159 | unsigned long hpseli; | ||
160 | unsigned long hpselp; | ||
161 | unsigned long lpfin; | ||
162 | unsigned long lppdn; | ||
163 | unsigned long lpmbyp; | ||
164 | unsigned long lplock; | ||
165 | unsigned long lpdbyp; | ||
166 | unsigned long lpmsel; | ||
167 | unsigned long lppsel; | ||
168 | }; | ||
169 | |||
170 | #define PLL (*(volatile struct pnx0101_pll *)0x80004cac) | ||
171 | |||
172 | struct pnx0101_emc { | ||
173 | unsigned long control; | ||
174 | unsigned long status; | ||
175 | }; | ||
176 | |||
177 | #define EMC (*(volatile struct pnx0101_emc *)0x80008000) | ||
178 | |||
179 | struct pnx0101_emcstatic { | ||
180 | unsigned long config; | ||
181 | unsigned long waitwen; | ||
182 | unsigned long waitoen; | ||
183 | unsigned long waitrd; | ||
184 | unsigned long waitpage; | ||
185 | unsigned long waitwr; | ||
186 | unsigned long waitturn; | ||
187 | }; | ||
188 | |||
189 | #define EMCSTATIC0 (*(volatile struct pnx0101_emcstatic *)0x80008200) | ||
190 | #define EMCSTATIC1 (*(volatile struct pnx0101_emcstatic *)0x80008220) | ||
191 | #define EMCSTATIC2 (*(volatile struct pnx0101_emcstatic *)0x80008240) | ||
192 | |||
193 | /* Timers */ | ||
194 | |||
195 | struct pnx0101_timer { | ||
196 | unsigned long load; | ||
197 | unsigned long value; | ||
198 | unsigned long ctrl; | ||
199 | unsigned long clr; | ||
200 | }; | ||
201 | |||
202 | #define TIMER0 (*(volatile struct pnx0101_timer *)0x80020000) | ||
203 | #define TIMER1 (*(volatile struct pnx0101_timer *)0x80020400) | ||
204 | |||
205 | /* Interrupt controller */ | ||
206 | |||
207 | #define IRQ_TIMER0 5 | ||
208 | #define IRQ_TIMER1 6 | ||
209 | #define IRQ_DMA 28 | ||
210 | |||
211 | #define INTPRIOMASK ((volatile unsigned long *)0x80300000) | ||
212 | #define INTVECTOR ((volatile unsigned long *)0x80300100) | ||
213 | #define INTPENDING (*(volatile unsigned long *)0x80300200) | ||
214 | #define INTFEATURES (*(volatile unsigned long *)0x80300300) | ||
215 | #define INTREQ ((volatile unsigned long *)0x80300400) | ||
216 | |||
217 | #define INTREQ_WEPRIO 0x10000000 | ||
218 | #define INTREQ_WETARGET 0x08000000 | ||
219 | #define INTREQ_WEENABLE 0x04000000 | ||
220 | #define INTREQ_WEACTVLO 0x02000000 | ||
221 | |||
222 | #endif /* ASM */ | ||
223 | |||
81 | #endif | 224 | #endif |
diff --git a/firmware/export/system.h b/firmware/export/system.h index 32a26a9bf5..184e4fe45a 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h | |||
@@ -296,6 +296,12 @@ static inline unsigned long swap32(unsigned long value) | |||
296 | #define CPUFREQ_NORMAL 98784000 | 296 | #define CPUFREQ_NORMAL 98784000 |
297 | #define CPUFREQ_MAX 296352000 | 297 | #define CPUFREQ_MAX 296352000 |
298 | 298 | ||
299 | #elif CONFIG_CPU == PNX0101 | ||
300 | |||
301 | #define CPUFREQ_DEFAULT 12000000 | ||
302 | #define CPUFREQ_NORMAL 48000000 | ||
303 | #define CPUFREQ_MAX 60000000 | ||
304 | |||
299 | #else | 305 | #else |
300 | 306 | ||
301 | #define CPUFREQ_DEFAULT_MULT 8 | 307 | #define CPUFREQ_DEFAULT_MULT 8 |
@@ -385,6 +391,7 @@ typedef void (*interrupt_handler_t)(void); | |||
385 | 391 | ||
386 | void irq_set_int_handler(int n, interrupt_handler_t handler); | 392 | void irq_set_int_handler(int n, interrupt_handler_t handler); |
387 | void irq_enable_int(int n); | 393 | void irq_enable_int(int n); |
394 | void irq_disable_int(int n); | ||
388 | #endif | 395 | #endif |
389 | 396 | ||
390 | #endif | 397 | #endif |
diff --git a/firmware/export/timer.h b/firmware/export/timer.h index f32a8a1790..35994ce5f2 100644 --- a/firmware/export/timer.h +++ b/firmware/export/timer.h | |||
@@ -32,6 +32,8 @@ | |||
32 | #elif defined(CPU_COLDFIRE) | 32 | #elif defined(CPU_COLDFIRE) |
33 | /* timer is based on busclk == cpuclk/2 */ | 33 | /* timer is based on busclk == cpuclk/2 */ |
34 | #define TIMER_FREQ (CPU_FREQ/2) | 34 | #define TIMER_FREQ (CPU_FREQ/2) |
35 | #elif CONFIG_CPU == PNX0101 | ||
36 | #define TIMER_FREQ 3000000 | ||
35 | #else | 37 | #else |
36 | #define TIMER_FREQ CPU_FREQ | 38 | #define TIMER_FREQ CPU_FREQ |
37 | #endif | 39 | #endif |
diff --git a/firmware/kernel.c b/firmware/kernel.c index 192728bdb2..c5e47a81ff 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c | |||
@@ -594,23 +594,21 @@ void timer_handler(void) | |||
594 | 594 | ||
595 | current_tick++; | 595 | current_tick++; |
596 | 596 | ||
597 | TIMERR0C = 1; | 597 | TIMER0.clr = 0; |
598 | } | 598 | } |
599 | 599 | ||
600 | void tick_start(unsigned int interval_in_ms) | 600 | void tick_start(unsigned int interval_in_ms) |
601 | { | 601 | { |
602 | TIMERR08 &= ~0x80; | 602 | TIMER0.ctrl &= ~0x80; /* Disable the counter */ |
603 | TIMERR0C = 1; | 603 | TIMER0.ctrl |= 0x40; /* Reload after counting down to zero */ |
604 | TIMERR08 &= ~0x80; | 604 | TIMER0.load = 3000000 * interval_in_ms / 1000; |
605 | TIMERR08 |= 0x40; | 605 | TIMER0.ctrl &= ~0xc; /* No prescaler */ |
606 | TIMERR00 = 3000000 * interval_in_ms / 1000; | 606 | TIMER0.clr = 1; /* Clear the interrupt request */ |
607 | TIMERR08 &= ~0xc; | ||
608 | TIMERR0C = 1; | ||
609 | 607 | ||
610 | irq_set_int_handler(4, timer_handler); | 608 | irq_set_int_handler(IRQ_TIMER0, timer_handler); |
611 | irq_enable_int(4); | 609 | irq_enable_int(IRQ_TIMER0); |
612 | 610 | ||
613 | TIMERR08 |= 0x80; | 611 | TIMER0.ctrl |= 0x80; /* Enable the counter */ |
614 | } | 612 | } |
615 | #elif CONFIG_CPU == S3C2440 | 613 | #elif CONFIG_CPU == S3C2440 |
616 | void tick_start(unsigned int interval_in_ms) | 614 | void tick_start(unsigned int interval_in_ms) |
diff --git a/firmware/system.c b/firmware/system.c index a9c9d9e350..f233376219 100644 --- a/firmware/system.c +++ b/firmware/system.c | |||
@@ -982,93 +982,6 @@ int system_memory_guard(int newmode) | |||
982 | return 0; | 982 | return 0; |
983 | } | 983 | } |
984 | 984 | ||
985 | #elif CONFIG_CPU==PNX0101 | ||
986 | |||
987 | interrupt_handler_t interrupt_vector[0x1d] __attribute__ ((section(".idata"))); | ||
988 | |||
989 | #define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg))) | ||
990 | |||
991 | static inline unsigned long irq_read(int reg) | ||
992 | { | ||
993 | unsigned long v, v2; | ||
994 | do | ||
995 | { | ||
996 | v = IRQ_REG(reg); | ||
997 | v2 = IRQ_REG(reg); | ||
998 | } while (v != v2); | ||
999 | return v; | ||
1000 | } | ||
1001 | |||
1002 | #define IRQ_WRITE_WAIT(reg, val, cond) \ | ||
1003 | do { unsigned long v, v2; \ | ||
1004 | do { \ | ||
1005 | IRQ_REG(reg) = (val); \ | ||
1006 | v = IRQ_REG(reg); \ | ||
1007 | v2 = IRQ_REG(reg); \ | ||
1008 | } while ((v != v2) || !(cond)); \ | ||
1009 | } while (0); | ||
1010 | |||
1011 | static void undefined_int(void) | ||
1012 | { | ||
1013 | } | ||
1014 | |||
1015 | void irq(void) | ||
1016 | { | ||
1017 | int n = irq_read(0x100) >> 3; | ||
1018 | (*(interrupt_vector[n]))(); | ||
1019 | } | ||
1020 | |||
1021 | void fiq(void) | ||
1022 | { | ||
1023 | } | ||
1024 | |||
1025 | void irq_enable_int(int n) | ||
1026 | { | ||
1027 | IRQ_WRITE_WAIT(0x404 + n * 4, 0x4010000, v & 0x10000); | ||
1028 | } | ||
1029 | |||
1030 | void irq_set_int_handler(int n, interrupt_handler_t handler) | ||
1031 | { | ||
1032 | interrupt_vector[n + 1] = handler; | ||
1033 | } | ||
1034 | |||
1035 | void system_init(void) | ||
1036 | { | ||
1037 | int i; | ||
1038 | |||
1039 | /* turn off watchdog */ | ||
1040 | (*(volatile unsigned long *)0x80002804) = 0; | ||
1041 | |||
1042 | /* | ||
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); | ||
1047 | */ | ||
1048 | |||
1049 | for (i = 0; i < 0x1c; i++) | ||
1050 | { | ||
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; | ||
1055 | } | ||
1056 | interrupt_vector[0] = undefined_int; | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | void system_reboot(void) | ||
1061 | { | ||
1062 | (*(volatile unsigned long *)0x80002804) = 1; | ||
1063 | while (1); | ||
1064 | } | ||
1065 | |||
1066 | int system_memory_guard(int newmode) | ||
1067 | { | ||
1068 | (void)newmode; | ||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | #endif /* CPU_ARM */ | 985 | #endif /* CPU_ARM */ |
1073 | #endif /* CONFIG_CPU */ | 986 | #endif /* CONFIG_CPU */ |
1074 | 987 | ||
diff --git a/firmware/target/arm/crt0-pnx0101.S b/firmware/target/arm/crt0-pnx0101.S new file mode 100644 index 0000000000..d11546edaa --- /dev/null +++ b/firmware/target/arm/crt0-pnx0101.S | |||
@@ -0,0 +1,229 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: crt0.S 11850 2006-12-29 02:49:12Z markun $ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Linus Nielsen Feltzing | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #define ASM /* do not include structure definitions from pnx0101.h */ | ||
20 | |||
21 | #include "config.h" | ||
22 | #include "cpu.h" | ||
23 | |||
24 | .section .init.text,"ax",%progbits | ||
25 | |||
26 | .global start | ||
27 | start: | ||
28 | |||
29 | /* Arm bootloader and startup code based on startup.s from the iPodLinux loader | ||
30 | * | ||
31 | * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org) | ||
32 | * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org> | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ */ | ||
37 | |||
38 | #ifndef BOOTLOADER | ||
39 | #ifndef DEBUG | ||
40 | ldr r0, =0x80105000 | ||
41 | mov r1, #1 | ||
42 | str r1, [r0, #4] | ||
43 | mov r1, #0 | ||
44 | str r1, [r0, #4] | ||
45 | 1: ldr r1, [r0] | ||
46 | cmp r1, #0 | ||
47 | bne 1b | ||
48 | mov r1, #0x74 | ||
49 | str r1, [r0, #8] | ||
50 | mov r1, #2 | ||
51 | str r1, [r0, #0x18] | ||
52 | mov r1, #2 | ||
53 | str r1, [r0, #0x20] | ||
54 | mov r1, #82 | ||
55 | str r1, [r0, #0x28] | ||
56 | mov r1, #100 | ||
57 | str r1, [r0, #0x2c] | ||
58 | mov r1, #0x120 | ||
59 | str r1, [r0, #0x30] | ||
60 | mov r1, #6 | ||
61 | str r1, [r0, #4] | ||
62 | ldr r0, =1f | ||
63 | mov r15, r0 | ||
64 | 1: | ||
65 | #endif /* !DEBUG */ | ||
66 | |||
67 | #ifndef DEBUG | ||
68 | /* Copy exception handler code to address 0 */ | ||
69 | ldr r2, =_vectorsstart | ||
70 | ldr r3, =_vectorsend | ||
71 | ldr r4, =_vectorscopy | ||
72 | 1: | ||
73 | cmp r3, r2 | ||
74 | ldrhi r5, [r4], #4 | ||
75 | strhi r5, [r2], #4 | ||
76 | bhi 1b | ||
77 | #else | ||
78 | ldr r1, =vectors | ||
79 | ldr r0, =irq_handler | ||
80 | str r0, [r1, #24] | ||
81 | ldr r0, =fiq_handler | ||
82 | str r0, [r1, #28] | ||
83 | #endif | ||
84 | |||
85 | #ifndef STUB | ||
86 | /* Zero out IBSS */ | ||
87 | ldr r2, =_iedata | ||
88 | ldr r3, =_iend | ||
89 | mov r4, #0 | ||
90 | 1: | ||
91 | cmp r3, r2 | ||
92 | strhi r4, [r2], #4 | ||
93 | bhi 1b | ||
94 | |||
95 | /* Copy the IRAM */ | ||
96 | ldr r2, =_iramcopy | ||
97 | ldr r3, =_iramstart | ||
98 | ldr r4, =_iramend | ||
99 | 1: | ||
100 | cmp r4, r3 | ||
101 | ldrhi r5, [r2], #4 | ||
102 | strhi r5, [r3], #4 | ||
103 | bhi 1b | ||
104 | #endif /* !STUB */ | ||
105 | #endif /* !BOOTLOADER */ | ||
106 | |||
107 | /* Initialise bss section to zero */ | ||
108 | ldr r2, =_edata | ||
109 | ldr r3, =_end | ||
110 | mov r4, #0 | ||
111 | 1: | ||
112 | cmp r3, r2 | ||
113 | strhi r4, [r2], #4 | ||
114 | bhi 1b | ||
115 | |||
116 | /* Set up some stack and munge it with 0xdeadbeef */ | ||
117 | ldr sp, =stackend | ||
118 | mov r3, sp | ||
119 | ldr r2, =stackbegin | ||
120 | ldr r4, =0xdeadbeef | ||
121 | 1: | ||
122 | cmp r3, r2 | ||
123 | strhi r4, [r2], #4 | ||
124 | bhi 1b | ||
125 | |||
126 | /* Set up stack for IRQ mode */ | ||
127 | msr cpsr_c, #0xd2 | ||
128 | ldr sp, =irq_stack | ||
129 | /* Set up stack for FIQ mode */ | ||
130 | msr cpsr_c, #0xd1 | ||
131 | ldr sp, =fiq_stack | ||
132 | |||
133 | /* Let abort and undefined modes use IRQ stack */ | ||
134 | msr cpsr_c, #0xd7 | ||
135 | ldr sp, =irq_stack | ||
136 | msr cpsr_c, #0xdb | ||
137 | ldr sp, =irq_stack | ||
138 | /* Switch to supervisor mode */ | ||
139 | msr cpsr_c, #0xd3 | ||
140 | ldr sp, =stackend | ||
141 | bl main | ||
142 | /* main() should never return */ | ||
143 | |||
144 | /* Exception handlers. Will be copied to address 0 after memory remapping */ | ||
145 | .section .vectors,"aw" | ||
146 | ldr pc, [pc, #24] | ||
147 | ldr pc, [pc, #24] | ||
148 | ldr pc, [pc, #24] | ||
149 | ldr pc, [pc, #24] | ||
150 | ldr pc, [pc, #24] | ||
151 | ldr pc, [pc, #24] | ||
152 | ldr pc, [pc, #24] | ||
153 | ldr pc, [pc, #24] | ||
154 | |||
155 | /* Exception vectors */ | ||
156 | .global vectors | ||
157 | vectors: | ||
158 | .word start | ||
159 | .word undef_instr_handler | ||
160 | .word software_int_handler | ||
161 | .word prefetch_abort_handler | ||
162 | .word data_abort_handler | ||
163 | .word reserved_handler | ||
164 | .word irq_handler | ||
165 | .word fiq_handler | ||
166 | |||
167 | .text | ||
168 | |||
169 | #ifndef STUB | ||
170 | .global irq | ||
171 | .global fiq | ||
172 | .global UIE | ||
173 | #endif | ||
174 | |||
175 | /* All illegal exceptions call into UIE with exception address as first | ||
176 | parameter. This is calculated differently depending on which exception | ||
177 | we're in. Second parameter is exception number, used for a string lookup | ||
178 | in UIE. | ||
179 | */ | ||
180 | undef_instr_handler: | ||
181 | mov r0, lr | ||
182 | mov r1, #0 | ||
183 | b UIE | ||
184 | |||
185 | /* We run supervisor mode most of the time, and should never see a software | ||
186 | exception being thrown. Perhaps make it illegal and call UIE? | ||
187 | */ | ||
188 | software_int_handler: | ||
189 | reserved_handler: | ||
190 | movs pc, lr | ||
191 | |||
192 | prefetch_abort_handler: | ||
193 | sub r0, lr, #4 | ||
194 | mov r1, #1 | ||
195 | b UIE | ||
196 | |||
197 | fiq_handler: | ||
198 | @ Branch straight to FIQ handler in pcm_playback.c. This also handles the | ||
199 | @ the correct return sequence. | ||
200 | stmfd sp!, {r0-r7, r12, lr} | ||
201 | bl fiq | ||
202 | ldmfd sp!, {r0-r7, r12, lr} | ||
203 | subs pc, lr, #4 | ||
204 | |||
205 | data_abort_handler: | ||
206 | sub r0, lr, #8 | ||
207 | mov r1, #2 | ||
208 | b UIE | ||
209 | |||
210 | irq_handler: | ||
211 | #ifndef STUB | ||
212 | stmfd sp!, {r0-r11, r12, lr} | ||
213 | bl irq | ||
214 | ldmfd sp!, {r0-r11, r12, lr} | ||
215 | #endif | ||
216 | subs pc, lr, #4 | ||
217 | |||
218 | #ifdef STUB | ||
219 | UIE: | ||
220 | b UIE | ||
221 | #endif | ||
222 | |||
223 | /* 256 words of IRQ stack */ | ||
224 | .space 256*4 | ||
225 | irq_stack: | ||
226 | |||
227 | /* 256 words of FIQ stack */ | ||
228 | .space 256*4 | ||
229 | fiq_stack: | ||
diff --git a/firmware/target/arm/crt0.S b/firmware/target/arm/crt0.S index c552e44320..581a997477 100644 --- a/firmware/target/arm/crt0.S +++ b/firmware/target/arm/crt0.S | |||
@@ -34,30 +34,6 @@ start: | |||
34 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ */ | 34 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ */ |
35 | 35 | ||
36 | #ifndef BOOTLOADER | 36 | #ifndef BOOTLOADER |
37 | #if CONFIG_CPU == PNX0101 | ||
38 | |||
39 | #ifndef DEBUG | ||
40 | ldr r0, =0x80105000 | ||
41 | mov r1, #1 | ||
42 | str r1, [r0, #4] | ||
43 | mov r1, #0 | ||
44 | str r1, [r0, #4] | ||
45 | 1: ldr r1, [r0] | ||
46 | cmp r1, #0 | ||
47 | bne 1b | ||
48 | mov r1, #0x74 | ||
49 | str r1, [r0, #8] | ||
50 | mov r1, #2 | ||
51 | str r1, [r0, #0x18] | ||
52 | mov r1, #0x120 | ||
53 | str r1, [r0, #0x30] | ||
54 | mov r1, #6 | ||
55 | str r1, [r0, #4] | ||
56 | ldr r0, =1f | ||
57 | mov r15, r0 | ||
58 | 1: | ||
59 | #endif /* !DEBUG */ | ||
60 | #endif /* chipset specific */ | ||
61 | 37 | ||
62 | #ifndef DEBUG | 38 | #ifndef DEBUG |
63 | /* Copy exception handler code to address 0 */ | 39 | /* Copy exception handler code to address 0 */ |
diff --git a/firmware/target/arm/system-pnx0101.c b/firmware/target/arm/system-pnx0101.c new file mode 100644 index 0000000000..9d8bb405a8 --- /dev/null +++ b/firmware/target/arm/system-pnx0101.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: $ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Tomasz Malesinski | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <stdlib.h> | ||
21 | #include "pnx0101.h" | ||
22 | #include "system.h" | ||
23 | |||
24 | static struct | ||
25 | { | ||
26 | unsigned char freq; | ||
27 | unsigned char sys_mult; | ||
28 | unsigned char sys_div; | ||
29 | unsigned char mem_conf[9]; | ||
30 | } | ||
31 | perf_modes[3] ICONST_ATTR = | ||
32 | { | ||
33 | {12, 4, 4, {2, 1, 1, 1, 1, 1, 1, 1, 1, 0}}, | ||
34 | {48, 4, 1, {5, 4, 1, 4, 4, 1, 3, 3, 1, 0}}, | ||
35 | {60, 5, 1, {6, 5, 1, 5, 5, 1, 4, 3, 1, 1}} | ||
36 | }; | ||
37 | |||
38 | static int performance_mode, bus_divider; | ||
39 | |||
40 | static void cgu_set_sel_stage_input(int clock, int input) | ||
41 | { | ||
42 | int s = CGU.base_ssr[clock]; | ||
43 | if (s & 1) | ||
44 | CGU.base_fs2[clock] = input; | ||
45 | else | ||
46 | CGU.base_fs1[clock] = input; | ||
47 | CGU.base_scr[clock] = (s & 3) ^ 3; | ||
48 | } | ||
49 | |||
50 | static void cgu_reset_sel_stage_clocks(int first_esr, int n_esr, | ||
51 | int first_div, int n_div) | ||
52 | { | ||
53 | int i; | ||
54 | for (i = 0; i < n_esr; i++) | ||
55 | CGU.clk_esr[first_esr + i] = 0; | ||
56 | for (i = 0; i < n_div; i++) | ||
57 | CGU.base_fdc[first_div + i] = 0; | ||
58 | } | ||
59 | |||
60 | static void cgu_configure_div(int div, int n, int m) | ||
61 | { | ||
62 | int msub, madd, div_size, max_n; | ||
63 | unsigned long cfg; | ||
64 | |||
65 | if (n == m) | ||
66 | { | ||
67 | CGU.base_fdc[div] = CGU.base_fdc[div] & ~1; | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | msub = -n; | ||
72 | madd = m - n; | ||
73 | div_size = (div == PNX0101_HIPREC_FDC) ? 10 : 8; | ||
74 | max_n = 1 << div_size; | ||
75 | while ((madd << 1) < max_n && (msub << 1) >= -max_n) | ||
76 | { | ||
77 | madd <<= 1; | ||
78 | msub <<= 1; | ||
79 | } | ||
80 | cfg = (((msub << div_size) | madd) << 3) | 4; | ||
81 | CGU.base_fdc[div] = CGU.base_fdc[div] & ~1; | ||
82 | CGU.base_fdc[div] = cfg | 2; | ||
83 | CGU.base_fdc[div] = cfg; | ||
84 | CGU.base_fdc[div] = cfg | 1; | ||
85 | } | ||
86 | |||
87 | static void cgu_connect_div_to_clock(int rel_div, int esr) | ||
88 | { | ||
89 | CGU.clk_esr[esr] = (rel_div << 1) | 1; | ||
90 | } | ||
91 | |||
92 | static void cgu_disconnect_div_from_clock(int esr) | ||
93 | { | ||
94 | CGU.clk_esr[esr] = 0; | ||
95 | } | ||
96 | |||
97 | static void cgu_enable_clock(int clock) | ||
98 | { | ||
99 | CGU.clk_pcr[clock] |= 1; | ||
100 | } | ||
101 | |||
102 | static void cgu_start_sel_stage_dividers(int bcr) | ||
103 | { | ||
104 | CGU.base_bcr[bcr] = 1; | ||
105 | } | ||
106 | |||
107 | /* Convert a pointer that points to IRAM (0x4xxxx) to a pointer that | ||
108 | points to the uncached page (0x0xxxx) that is also mapped to IRAM. */ | ||
109 | static inline void *noncached(void *p) { | ||
110 | return (void *)(((unsigned long)p) & 0xffff); | ||
111 | } | ||
112 | |||
113 | /* TODO: if it works, then comment it */ | ||
114 | static void do_set_mem_timings(int mode) ICODE_ATTR; | ||
115 | static void do_set_mem_timings(int mode) | ||
116 | { | ||
117 | unsigned char *mem_conf = noncached(perf_modes[mode].mem_conf); | ||
118 | int old_irq = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
119 | while ((EMC.status & 3) != 0); | ||
120 | EMC.control = 5; | ||
121 | EMCSTATIC0.waitrd = mem_conf[0]; | ||
122 | EMCSTATIC0.waitwr = mem_conf[1]; | ||
123 | EMCSTATIC1.waitrd = mem_conf[3]; | ||
124 | EMCSTATIC1.waitwr = mem_conf[4]; | ||
125 | EMCSTATIC2.waitrd = mem_conf[6]; | ||
126 | EMCSTATIC2.waitwr = mem_conf[7]; | ||
127 | EMCSTATIC0.waitoen = mem_conf[2]; | ||
128 | EMCSTATIC1.waitoen = mem_conf[5]; | ||
129 | EMCSTATIC2.waitoen = mem_conf[8]; | ||
130 | #ifndef DEBUG | ||
131 | EMCSTATIC1.config = mem_conf[9] ? 0x80081 : 0x81; | ||
132 | #endif | ||
133 | EMC.control = 1; | ||
134 | set_irq_level(old_irq); | ||
135 | } | ||
136 | |||
137 | static void emc_set_mem_timings(int mode) { | ||
138 | void (*f)(int) = noncached(do_set_mem_timings); | ||
139 | (*f)(mode); | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | static void do_enable_write_buffers(int on) ICODE_ATTR; | ||
144 | static void do_enable_write_buffers(int on) { | ||
145 | int old_irq = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
146 | while ((EMC.status & 3) != 0); | ||
147 | EMC.control = 5; | ||
148 | EMCSTATIC1.config = on ? 0x80081 : 0x81; | ||
149 | EMC.control = 1; | ||
150 | set_irq_level(old_irq); | ||
151 | } | ||
152 | |||
153 | void emc_enable_write_buffers(int on) { | ||
154 | void (*f)(int) = noncached(do_enable_write_buffers); | ||
155 | (*f)(on); | ||
156 | } | ||
157 | */ | ||
158 | |||
159 | /* can it be replaced? */ | ||
160 | static void cgu_busy_wait(int n) | ||
161 | { | ||
162 | while (n > 0) | ||
163 | { | ||
164 | n--; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static void cgu_set_sys_mult(int i) | ||
169 | { | ||
170 | cgu_set_sel_stage_input(PNX0101_SEL_STAGE_SYS, PNX0101_MAIN_CLOCK_FAST); | ||
171 | cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB3, PNX0101_MAIN_CLOCK_FAST); | ||
172 | |||
173 | PLL.lppdn = 1; | ||
174 | PLL.lpfin = 1; | ||
175 | PLL.lpmbyp = 0; | ||
176 | PLL.lpdbyp = 0; | ||
177 | PLL.lppsel = 1; | ||
178 | PLL.lpmsel = i - 1; | ||
179 | PLL.lppdn = 0; | ||
180 | while (!PLL.lplock); | ||
181 | |||
182 | cgu_configure_div(PNX0101_FIRST_DIV_SYS + 1, 1, (i == 5) ? 15 : 12); | ||
183 | cgu_connect_div_to_clock(1, 0x11); | ||
184 | cgu_enable_clock(0x11); | ||
185 | cgu_start_sel_stage_dividers(PNX0101_BCR_SYS); | ||
186 | |||
187 | cgu_set_sel_stage_input(PNX0101_SEL_STAGE_SYS, | ||
188 | PNX0101_MAIN_CLOCK_MAIN_PLL); | ||
189 | cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB3, | ||
190 | PNX0101_MAIN_CLOCK_MAIN_PLL); | ||
191 | } | ||
192 | |||
193 | static void pnx0101_set_performance_mode(int mode) | ||
194 | { | ||
195 | int old = performance_mode; | ||
196 | if (perf_modes[old].freq < perf_modes[mode].freq) | ||
197 | { | ||
198 | emc_set_mem_timings(mode); | ||
199 | if (perf_modes[old].sys_mult != perf_modes[mode].sys_mult) | ||
200 | cgu_set_sys_mult(perf_modes[mode].sys_mult); | ||
201 | if (perf_modes[old].sys_div != perf_modes[mode].sys_div) | ||
202 | cgu_configure_div(bus_divider, 1, perf_modes[mode].sys_div); | ||
203 | } | ||
204 | else if (perf_modes[old].freq > perf_modes[mode].freq) | ||
205 | { | ||
206 | if (perf_modes[old].sys_mult != perf_modes[mode].sys_mult) | ||
207 | cgu_set_sys_mult(perf_modes[mode].sys_mult); | ||
208 | if (perf_modes[old].sys_div != perf_modes[mode].sys_div) | ||
209 | cgu_configure_div(bus_divider, 1, perf_modes[mode].sys_div); | ||
210 | emc_set_mem_timings(mode); | ||
211 | } | ||
212 | performance_mode = mode; | ||
213 | } | ||
214 | |||
215 | static void pnx0101_init_clocks(void) | ||
216 | { | ||
217 | bus_divider = PNX0101_FIRST_DIV_SYS + (CGU.clk_esr[0] >> 1); | ||
218 | performance_mode = 0; | ||
219 | pnx0101_set_performance_mode(2); | ||
220 | /* | ||
221 | #ifndef DEBUG | ||
222 | emc_enable_write_buffers(1); | ||
223 | #endif | ||
224 | */ | ||
225 | cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB1, | ||
226 | PNX0101_MAIN_CLOCK_FAST); | ||
227 | cgu_reset_sel_stage_clocks(PNX0101_FIRST_ESR_APB1, PNX0101_N_ESR_APB1, | ||
228 | PNX0101_FIRST_DIV_APB1, PNX0101_N_DIV_APB1); | ||
229 | cgu_configure_div(PNX0101_FIRST_DIV_APB1, 1, 4); | ||
230 | cgu_connect_div_to_clock(0, PNX0101_ESR_APB1); | ||
231 | cgu_connect_div_to_clock(0, PNX0101_ESR_T0); | ||
232 | cgu_connect_div_to_clock(0, PNX0101_ESR_T1); | ||
233 | cgu_connect_div_to_clock(0, PNX0101_ESR_I2C); | ||
234 | cgu_enable_clock(PNX0101_CLOCK_APB1); | ||
235 | cgu_enable_clock(PNX0101_CLOCK_T0); | ||
236 | cgu_enable_clock(PNX0101_CLOCK_T1); | ||
237 | cgu_enable_clock(PNX0101_CLOCK_I2C); | ||
238 | } | ||
239 | |||
240 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
241 | void set_cpu_frequency(long frequency) | ||
242 | { | ||
243 | switch (frequency) | ||
244 | { | ||
245 | case CPUFREQ_MAX: | ||
246 | pnx0101_set_performance_mode(2); | ||
247 | cpu_frequency = CPUFREQ_MAX; | ||
248 | break; | ||
249 | case CPUFREQ_NORMAL: | ||
250 | pnx0101_set_performance_mode(1); | ||
251 | cpu_frequency = CPUFREQ_NORMAL; | ||
252 | break; | ||
253 | case CPUFREQ_DEFAULT: | ||
254 | default: | ||
255 | pnx0101_set_performance_mode(0); | ||
256 | cpu_frequency = CPUFREQ_DEFAULT; | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | } | ||
261 | #endif | ||
262 | |||
263 | interrupt_handler_t interrupt_vector[0x1d] __attribute__ ((section(".idata"))); | ||
264 | |||
265 | #define IRQ_READ(reg, dest) \ | ||
266 | do { unsigned long v2; \ | ||
267 | do { \ | ||
268 | dest = (reg); \ | ||
269 | v2 = (reg); \ | ||
270 | } while ((dest != v2)); \ | ||
271 | } while (0); | ||
272 | |||
273 | #define IRQ_WRITE_WAIT(reg, val, cond) \ | ||
274 | do { unsigned long v, v2; \ | ||
275 | do { \ | ||
276 | (reg) = (val); \ | ||
277 | v = (reg); \ | ||
278 | v2 = (reg); \ | ||
279 | } while ((v != v2) || !(cond)); \ | ||
280 | } while (0); | ||
281 | |||
282 | static void undefined_int(void) | ||
283 | { | ||
284 | } | ||
285 | |||
286 | void irq(void) | ||
287 | { | ||
288 | int n; | ||
289 | IRQ_READ(INTVECTOR[0], n) | ||
290 | (*(interrupt_vector[n >> 3]))(); | ||
291 | } | ||
292 | |||
293 | void fiq(void) | ||
294 | { | ||
295 | } | ||
296 | |||
297 | void irq_enable_int(int n) | ||
298 | { | ||
299 | IRQ_WRITE_WAIT(INTREQ[n], INTREQ_WEENABLE | INTREQ_ENABLE, v & 0x10000); | ||
300 | } | ||
301 | |||
302 | void irq_disable_int(int n) | ||
303 | { | ||
304 | IRQ_WRITE_WAIT(INTREQ[n], INTREQ_WEENABLE, (v & 0x10000) == 0); | ||
305 | } | ||
306 | |||
307 | void irq_set_int_handler(int n, interrupt_handler_t handler) | ||
308 | { | ||
309 | interrupt_vector[n] = handler; | ||
310 | } | ||
311 | |||
312 | void system_init(void) | ||
313 | { | ||
314 | int i; | ||
315 | |||
316 | /* turn off watchdog */ | ||
317 | (*(volatile unsigned long *)0x80002804) = 0; | ||
318 | |||
319 | /* | ||
320 | IRQ_WRITE_WAIT(INTVECTOR[0], 0, v == 0); | ||
321 | IRQ_WRITE_WAIT(INTVECTOR[1], 0, v == 0); | ||
322 | IRQ_WRITE_WAIT(INTPRIOMASK[0], 0, v == 0); | ||
323 | IRQ_WRITE_WAIT(INTPRIOMASK[1], 0, v == 0); | ||
324 | */ | ||
325 | |||
326 | for (i = 0; i < 0x1c; i++) | ||
327 | { | ||
328 | IRQ_WRITE_WAIT(INTREQ[i], | ||
329 | INTREQ_WEPRIO | INTREQ_WETARGET | | ||
330 | INTREQ_WEENABLE | INTREQ_WEACTVLO | 1, | ||
331 | (v & 0x3010f) == 1); | ||
332 | IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEENABLE, (v & 0x10000) == 0); | ||
333 | IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEPRIO | 1, (v & 0xf) == 1); | ||
334 | interrupt_vector[i + 1] = undefined_int; | ||
335 | } | ||
336 | interrupt_vector[0] = undefined_int; | ||
337 | pnx0101_init_clocks(); | ||
338 | } | ||
339 | |||
340 | |||
341 | void system_reboot(void) | ||
342 | { | ||
343 | (*(volatile unsigned long *)0x80002804) = 1; | ||
344 | while (1); | ||
345 | } | ||
346 | |||
347 | int system_memory_guard(int newmode) | ||
348 | { | ||
349 | (void)newmode; | ||
350 | return 0; | ||
351 | } | ||
diff --git a/firmware/timer.c b/firmware/timer.c index 849e4ba598..ca23cb890c 100644 --- a/firmware/timer.c +++ b/firmware/timer.c | |||
@@ -28,7 +28,7 @@ static void (*pfn_timer)(void) = NULL; /* timer callback */ | |||
28 | static void (*pfn_unregister)(void) = NULL; /* unregister callback */ | 28 | static void (*pfn_unregister)(void) = NULL; /* unregister callback */ |
29 | #ifdef CPU_COLDFIRE | 29 | #ifdef CPU_COLDFIRE |
30 | static int base_prescale; | 30 | static int base_prescale; |
31 | #elif defined CPU_PP | 31 | #elif defined CPU_PP || CONFIG_CPU == PNX0101 |
32 | static long cycles_new = 0; | 32 | static long cycles_new = 0; |
33 | #endif | 33 | #endif |
34 | 34 | ||
@@ -67,6 +67,24 @@ void TIMER2(void) | |||
67 | cycles_new = 0; | 67 | cycles_new = 0; |
68 | } | 68 | } |
69 | } | 69 | } |
70 | #elif CONFIG_CPU == PNX0101 | ||
71 | void TIMER1_ISR(void) | ||
72 | { | ||
73 | if (cycles_new > 0) | ||
74 | { | ||
75 | TIMER1.load = cycles_new - 1; | ||
76 | cycles_new = 0; | ||
77 | } | ||
78 | if (pfn_timer != NULL) | ||
79 | { | ||
80 | cycles_new = -1; | ||
81 | /* "lock" the variable, in case timer_set_period() | ||
82 | * is called within pfn_timer() */ | ||
83 | pfn_timer(); | ||
84 | cycles_new = 0; | ||
85 | } | ||
86 | TIMER1.clr = 1; /* clear the interrupt */ | ||
87 | } | ||
70 | #endif /* CONFIG_CPU */ | 88 | #endif /* CONFIG_CPU */ |
71 | 89 | ||
72 | static bool timer_set(long cycles, bool start) | 90 | static bool timer_set(long cycles, bool start) |
@@ -85,8 +103,26 @@ static bool timer_set(long cycles, bool start) | |||
85 | } | 103 | } |
86 | #endif | 104 | #endif |
87 | 105 | ||
88 | #if CONFIG_CPU == PNX0101 /* TODO: Implement for iFP */ | 106 | #if CONFIG_CPU == PNX0101 |
89 | (void)start; | 107 | if (start) |
108 | { | ||
109 | if (pfn_unregister != NULL) | ||
110 | { | ||
111 | pfn_unregister(); | ||
112 | pfn_unregister = NULL; | ||
113 | } | ||
114 | TIMER1.ctrl &= ~0x80; /* disable the counter */ | ||
115 | TIMER1.ctrl |= 0x40; /* reload after counting down to zero */ | ||
116 | TIMER1.ctrl &= ~0xc; /* no prescaler */ | ||
117 | TIMER1.clr = 1; /* clear an interrupt event */ | ||
118 | } | ||
119 | if (start || (cycles_new == -1)) /* within isr, cycles_new is "locked" */ | ||
120 | { /* enable timer */ | ||
121 | TIMER1.load = cycles - 1; | ||
122 | TIMER1.ctrl |= 0x80; /* enable the counter */ | ||
123 | } | ||
124 | else | ||
125 | cycles_new = cycles; | ||
90 | #endif | 126 | #endif |
91 | 127 | ||
92 | #if CONFIG_CPU == SH7034 | 128 | #if CONFIG_CPU == SH7034 |
@@ -229,6 +265,9 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), | |||
229 | #elif defined(CPU_PP) | 265 | #elif defined(CPU_PP) |
230 | /* unmask interrupt source */ | 266 | /* unmask interrupt source */ |
231 | CPU_INT_EN = TIMER2_MASK; | 267 | CPU_INT_EN = TIMER2_MASK; |
268 | #elif CONFIG_CPU == PNX0101 | ||
269 | irq_set_int_handler(IRQ_TIMER1, TIMER1_ISR); | ||
270 | irq_enable_int(IRQ_TIMER1); | ||
232 | #endif | 271 | #endif |
233 | return true; | 272 | return true; |
234 | } | 273 | } |
@@ -249,6 +288,9 @@ void timer_unregister(void) | |||
249 | #elif defined(CPU_PP) | 288 | #elif defined(CPU_PP) |
250 | TIMER2_CFG = 0; /* stop timer 2 */ | 289 | TIMER2_CFG = 0; /* stop timer 2 */ |
251 | CPU_INT_CLR = TIMER2_MASK; | 290 | CPU_INT_CLR = TIMER2_MASK; |
291 | #elif CONFIG_CPU == PNX0101 | ||
292 | TIMER1.ctrl &= ~0x80; /* disable timer 1 */ | ||
293 | irq_disable_int(5); | ||
252 | #endif | 294 | #endif |
253 | pfn_timer = NULL; | 295 | pfn_timer = NULL; |
254 | pfn_unregister = NULL; | 296 | pfn_unregister = NULL; |