New USB stack
[kugel-rb.git] / firmware / target / arm / system-pp502x.c
blob5dfcfa9ea9307936ef6a77928dc83c9437499dde
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 "system.h"
20 #include "thread.h"
21 #include "i2s.h"
22 #include "i2c-pp.h"
23 #include "as3514.h"
24 #ifdef HAVE_USBSTACK
25 #include "usb_drv.h"
26 #endif
28 #ifndef BOOTLOADER
29 extern void TIMER1(void);
30 extern void TIMER2(void);
31 extern void ipod_mini_button_int(void); /* iPod Mini 1st gen only */
32 extern void ipod_4g_button_int(void); /* iPod 4th gen and higher only */
33 extern void microsd_int(void); /* Sansa E200 and C200 */
34 #ifdef SANSA_E200
35 extern void button_int(void);
36 extern void clickwheel_int(void);
37 #endif
39 void irq(void)
41 if(CURRENT_CORE == CPU)
43 if (CPU_INT_STAT & TIMER1_MASK) {
44 TIMER1();
45 } else if (CPU_INT_STAT & TIMER2_MASK)
46 TIMER2();
47 #if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */
48 else if (CPU_HI_INT_STAT & GPIO0_MASK)
49 ipod_mini_button_int();
50 #elif CONFIG_KEYPAD == IPOD_4G_PAD /* except Mini 1st gen, handled above */
51 else if (CPU_HI_INT_STAT & I2C_MASK)
52 ipod_4g_button_int();
53 #elif defined(SANSA_E200)
54 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
55 if (GPIOA_INT_STAT & 0x80)
56 microsd_int();
58 else if (CPU_HI_INT_STAT & GPIO1_MASK) {
59 if (GPIOF_INT_STAT & 0xff)
60 button_int();
61 if (GPIOH_INT_STAT & 0xc0)
62 clickwheel_int();
64 #elif defined(SANSA_C200)
65 else if (CPU_HI_INT_STAT & GPIO2_MASK) {
66 if (GPIOL_INT_STAT & 0x08)
67 microsd_int();
69 #endif
70 #ifdef HAVE_USBSTACK
71 else if (CPU_INT_STAT & USB_MASK) {
72 usb_drv_int();
74 #endif
75 } else {
76 if (COP_INT_STAT & TIMER2_MASK)
77 TIMER2();
80 #endif /* BOOTLOADER */
82 /* TODO: The following function has been lifted straight from IPL, and
83 hence has a lot of numeric addresses used straight. I'd like to use
84 #defines for these, but don't know what most of them are for or even what
85 they should be named. Because of this I also have no way of knowing how
86 to extend the funtions to do alternate cache configurations. */
88 #ifndef BOOTLOADER
89 void flush_icache(void) ICODE_ATTR;
90 void flush_icache(void)
92 if (CACHE_CTL & CACHE_CTL_ENABLE)
94 CACHE_OPERATION |= CACHE_OP_FLUSH;
95 while ((CACHE_CTL & CACHE_CTL_BUSY) != 0);
99 void invalidate_icache(void) ICODE_ATTR;
100 void invalidate_icache(void)
102 if (CACHE_CTL & CACHE_CTL_ENABLE)
104 CACHE_OPERATION |= CACHE_OP_FLUSH | CACHE_OP_INVALIDATE;
105 while ((CACHE_CTL & CACHE_CTL_BUSY) != 0);
106 nop; nop; nop; nop;
110 static void init_cache(void)
112 /* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
114 /* cache init mode */
115 CACHE_CTL |= CACHE_CTL_INIT;
117 /* what's this do? */
118 CACHE_PRIORITY |= CURRENT_CORE == CPU ? 0x10 : 0x20;
120 /* Cache if (addr & mask) >> 16 == (mask & match) >> 16:
121 * yes: 0x00000000 - 0x03ffffff
122 * no: 0x04000000 - 0x1fffffff
123 * yes: 0x20000000 - 0x23ffffff
124 * no: 0x24000000 - 0x3fffffff
126 CACHE_MASK = 0x00001c00;
127 CACHE_OPERATION = 0xfc0;
129 /* enable cache */
130 CACHE_CTL |= CACHE_CTL_INIT | CACHE_CTL_ENABLE | CACHE_CTL_RUN;
131 nop; nop; nop; nop;
134 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
135 void scale_suspend_core(bool suspend) ICODE_ATTR;
136 void scale_suspend_core(bool suspend)
138 unsigned int core = CURRENT_CORE;
139 unsigned int othercore = 1 - core;
140 static unsigned long proc_bits IBSS_ATTR;
141 static int oldstatus IBSS_ATTR;
143 if (suspend)
145 oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
146 proc_bits = PROC_CTL(othercore) & 0xc0000000;
147 PROC_CTL(othercore) = 0x40000000; nop;
148 PROC_CTL(core) = 0x48000003; nop;
150 else
152 PROC_CTL(core) = 0x4800001f; nop;
153 if (proc_bits == 0)
154 PROC_CTL(othercore) = 0;
155 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
159 void set_cpu_frequency(long frequency) ICODE_ATTR;
160 void set_cpu_frequency(long frequency)
161 #else
162 static void pp_set_cpu_frequency(long frequency)
163 #endif
165 #if defined(HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
166 spinlock_lock(&boostctrl_spin);
167 #endif
169 scale_suspend_core(true);
171 cpu_frequency = frequency;
173 switch (frequency)
175 /* Note: The PP5022 PLL must be run at >= 96MHz
176 * Bits 20..21 select the post divider (1/2/4/8).
177 * PP5026 is similar to PP5022 except it doesn't
178 * have this limitation (and the post divider?) */
179 case CPUFREQ_MAX:
180 CLOCK_SOURCE = 0x10007772; /* source #1: 24MHz, #2, #3, #4: PLL */
181 DEV_TIMING1 = 0x00000303;
182 #ifdef IPOD_NANO
183 IDE0_CFG |= (0x10000000); /* Set CPU > 65MHz bit */
184 #endif
185 #ifdef IPOD_MINI2G
186 MLCD_SCLK_DIV = 0x00000001; /* Mono LCD bridge serial clock divider */
187 #endif
188 #if CONFIG_CPU == PP5020
189 PLL_CONTROL = 0x8a020a03; /* 10/3 * 24MHz */
190 PLL_STATUS = 0xd19b; /* unlock frequencies > 66MHz */
191 PLL_CONTROL = 0x8a020a03; /* repeat setup */
192 scale_suspend_core(false);
193 udelay(500); /* wait for relock */
194 #elif (CONFIG_CPU == PP5022) || (CONFIG_CPU == PP5024)
195 PLL_CONTROL = 0x8a121403; /* (20/3 * 24MHz) / 2 */
196 scale_suspend_core(false);
197 udelay(250);
198 while (!(PLL_STATUS & 0x80000000)); /* wait for relock */
199 #endif
200 scale_suspend_core(true);
201 break;
203 case CPUFREQ_NORMAL:
204 CLOCK_SOURCE = 0x10007772; /* source #1: 24MHz, #2, #3, #4: PLL */
205 DEV_TIMING1 = 0x00000303;
206 #ifdef IPOD_NANO
207 IDE0_CFG &=~(0x10000000); /* clear > 65MHz bit */
208 #endif
209 #ifdef IPOD_MINI2G
210 MLCD_SCLK_DIV = 0x00000000; /* Mono LCD bridge serial clock divider */
211 #endif
212 #if CONFIG_CPU == PP5020
213 PLL_CONTROL = 0x8a020504; /* 5/4 * 24MHz */
214 scale_suspend_core(false);
215 udelay(500); /* wait for relock */
216 #elif (CONFIG_CPU == PP5022) || (CONFIG_CPU == PP5024)
217 PLL_CONTROL = 0x8a220501; /* (5/1 * 24MHz) / 4 */
218 scale_suspend_core(false);
219 udelay(250);
220 while (!(PLL_STATUS & 0x80000000)); /* wait for relock */
221 #endif
222 scale_suspend_core(true);
223 break;
225 case CPUFREQ_SLEEP:
226 CLOCK_SOURCE = 0x10002202; /* source #2: 32kHz, #1, #3, #4: 24MHz */
227 PLL_CONTROL &= ~0x80000000; /* disable PLL */
228 scale_suspend_core(false);
229 udelay(10000); /* let 32kHz source stabilize? */
230 scale_suspend_core(true);
231 break;
233 default:
234 CLOCK_SOURCE = 0x10002222; /* source #1, #2, #3, #4: 24MHz */
235 DEV_TIMING1 = 0x00000303;
236 #ifdef IPOD_MINI2G
237 MLCD_SCLK_DIV = 0x00000000; /* Mono LCD bridge serial clock divider */
238 #endif
239 #ifdef IPOD_NANO
240 IDE0_CFG &=~(0x10000000); /* clear > 65MHz bit */
241 #endif
242 PLL_CONTROL &= ~0x80000000; /* disable PLL */
243 cpu_frequency = CPUFREQ_DEFAULT;
244 PROC_CTL(CURRENT_CORE) = 0x4800001f; nop;
245 break;
248 if (frequency == CPUFREQ_MAX)
249 DEV_TIMING1 = 0x00000808;
251 CLOCK_SOURCE = (CLOCK_SOURCE & ~0xf0000000) | 0x20000000; /* select source #2 */
253 scale_suspend_core(false);
255 #if defined(HAVE_ADJUSTABLE_CPU_FREQ) && (NUM_CORES > 1)
256 spinlock_unlock(&boostctrl_spin);
257 #endif
259 #endif /* !BOOTLOADER */
261 void system_init(void)
263 #ifndef BOOTLOADER
264 if (CURRENT_CORE == CPU)
266 #if defined(SANSA_E200) || defined(SANSA_C200)
267 /* Reset all devices */
268 DEV_RS2 |= 0x20;
269 DEV_RS = 0x3bfffef8;
270 DEV_RS2 = -1;
271 DEV_RS = 0;
272 DEV_RS2 = 0;
273 #elif defined (IRIVER_H10)
274 DEV_RS = 0x3ffffef8;
275 DEV_RS2 = -1;
276 outl(inl(0x70000024) | 0xc0, 0x70000024);
277 DEV_RS = 0;
278 DEV_RS2 = 0;
279 #endif
281 #if !defined(SANSA_E200) && !defined(SANSA_C200)
282 /* Remap the flash ROM on CPU, keep hidden from COP:
283 * 0x00000000-0x3fffffff = 0x20000000-0x23ffffff */
284 MMAP1_LOGICAL = 0x20003c00;
285 MMAP1_PHYSICAL = 0x00003084 |
286 MMAP_PHYS_READ_MASK | MMAP_PHYS_WRITE_MASK |
287 MMAP_PHYS_DATA_MASK | MMAP_PHYS_CODE_MASK;
288 #endif
290 /* disable all irqs */
291 COP_HI_INT_CLR = -1;
292 CPU_HI_INT_CLR = -1;
293 HI_INT_FORCED_CLR = -1;
295 COP_INT_CLR = -1;
296 CPU_INT_CLR = -1;
297 INT_FORCED_CLR = -1;
299 GPIOA_INT_EN = 0;
300 GPIOB_INT_EN = 0;
301 GPIOC_INT_EN = 0;
302 GPIOD_INT_EN = 0;
303 GPIOE_INT_EN = 0;
304 GPIOF_INT_EN = 0;
305 GPIOG_INT_EN = 0;
306 GPIOH_INT_EN = 0;
307 GPIOI_INT_EN = 0;
308 GPIOJ_INT_EN = 0;
309 GPIOK_INT_EN = 0;
310 GPIOL_INT_EN = 0;
312 #if defined(SANSA_E200) || defined(SANSA_C200)
313 /* outl(0x00000000, 0x6000b000); */
314 outl(inl(0x6000a000) | 0x80000000, 0x6000a000); /* Init DMA controller? */
315 #endif
317 DEV_INIT2 |= 1 << 30; /* enable PLL power */
319 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
320 #if NUM_CORES > 1
321 cpu_boost_init();
322 #endif
323 #else
324 pp_set_cpu_frequency(CPUFREQ_MAX);
325 #endif
328 init_cache();
329 #endif /* BOOTLOADER */
332 void system_reboot(void)
334 /* Reboot */
335 #ifdef SANSA_C200
336 CACHE_CTL &= ~CACHE_CTL_VECT_REMAP;
338 pp_i2c_send(AS3514_I2C_ADDR, DCDC15, 0x0); /* backlight off */
340 /* Magic used by the c200 OF: 0x23066000
341 Magic used by the c200 BL: 0x23066b7b
342 In both cases, the OF executes these 2 commands from iram. */
343 STRAP_OPT_A = 0x23066b7b;
344 DEV_RS = DEV_SYSTEM;
345 #else
346 DEV_RS |= DEV_SYSTEM;
347 #endif
350 int system_memory_guard(int newmode)
352 (void)newmode;
353 return 0;