FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / firmware / target / arm / as3525 / system-as3525.c
blobd68f2c4f003a0426c57b341c5ca325882ddf2381
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 by Rob Purchase
11 * Copyright © 2008 Rafaël Carré
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 #include "kernel.h"
24 #include "system.h"
25 #include "panic.h"
26 #include "ascodec-target.h"
27 #include "adc.h"
28 #include "dma-target.h"
29 #include "clock-target.h"
30 #include "fmradio_i2c.h"
31 #include "button-target.h"
32 #ifndef BOOTLOADER
33 #include "mmu-arm.h"
34 #endif
35 #include "backlight-target.h"
37 #define default_interrupt(name) \
38 extern __attribute__((weak,alias("UIRQ"))) void name (void)
40 void irq_handler(void) __attribute__((interrupt ("IRQ"), naked));
41 void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked));
43 default_interrupt(INT_WATCHDOG);
44 default_interrupt(INT_TIMER1);
45 default_interrupt(INT_TIMER2);
46 default_interrupt(INT_USB);
47 default_interrupt(INT_DMAC);
48 default_interrupt(INT_NAND);
49 default_interrupt(INT_IDE);
50 default_interrupt(INT_MCI0);
51 default_interrupt(INT_MCI1);
52 default_interrupt(INT_AUDIO);
53 default_interrupt(INT_SSP);
54 default_interrupt(INT_I2C_MS);
55 default_interrupt(INT_I2C_AUDIO);
56 default_interrupt(INT_I2SIN);
57 default_interrupt(INT_I2SOUT);
58 default_interrupt(INT_UART);
59 default_interrupt(INT_GPIOD);
60 default_interrupt(RESERVED1); /* Interrupt 17 : unused */
61 default_interrupt(INT_CGU);
62 default_interrupt(INT_MEMORY_STICK);
63 default_interrupt(INT_DBOP);
64 default_interrupt(RESERVED2); /* Interrupt 21 : unused */
65 default_interrupt(RESERVED3); /* Interrupt 22 : unused */
66 default_interrupt(RESERVED4); /* Interrupt 23 : unused */
67 default_interrupt(RESERVED5); /* Interrupt 24 : unused */
68 default_interrupt(RESERVED6); /* Interrupt 25 : unused */
69 default_interrupt(RESERVED7); /* Interrupt 26 : unused */
70 default_interrupt(RESERVED8); /* Interrupt 27 : unused */
71 default_interrupt(RESERVED9); /* Interrupt 28 : unused */
72 default_interrupt(INT_GPIOA);
73 default_interrupt(INT_GPIOB);
74 default_interrupt(INT_GPIOC);
76 static const char * const irqname[] =
78 "INT_WATCHDOG", "INT_TIMER1", "INT_TIMER2", "INT_USB", "INT_DMAC", "INT_NAND",
79 "INT_IDE", "INT_MCI0", "INT_MCI1", "INT_AUDIO", "INT_SSP", "INT_I2C_MS",
80 "INT_I2C_AUDIO", "INT_I2SIN", "INT_I2SOUT", "INT_UART", "INT_GPIOD", "RESERVED1",
81 "INT_CGU", "INT_MEMORY_STICK", "INT_DBOP", "RESERVED2", "RESERVED3", "RESERVED4",
82 "RESERVED5", "RESERVED6", "RESERVED7", "RESERVED8", "RESERVED9", "INT_GPIOA",
83 "INT_GPIOB", "INT_GPIOC"
86 static void UIRQ(void)
88 unsigned int irq_no = 0;
89 int status = VIC_IRQ_STATUS;
91 if(status == 0)
92 panicf("Unhandled IRQ (source unknown!)");
94 while((status >>= 1))
95 irq_no++;
97 panicf("Unhandled IRQ %02X: %s", irq_no, irqname[irq_no]);
100 struct vec_int_src
102 int source;
103 void (*isr) (void);
106 /* Vectored interrupts (16 available) */
107 struct vec_int_src vec_int_srcs[] =
109 { INT_SRC_TIMER1, INT_TIMER1 },
110 { INT_SRC_TIMER2, INT_TIMER2 },
111 { INT_SRC_DMAC, INT_DMAC },
112 { INT_SRC_NAND, INT_NAND },
113 { INT_SRC_MCI0, INT_MCI0 },
114 { INT_SRC_GPIOA, INT_GPIOA, },
115 { INT_SRC_GPIOB, INT_GPIOB, },
118 static void setup_vic(void)
120 volatile unsigned long *vic_vect_addrs = VIC_VECT_ADDRS;
121 volatile unsigned long *vic_vect_cntls = VIC_VECT_CNTLS;
122 const unsigned int n = sizeof(vec_int_srcs)/sizeof(vec_int_srcs[0]);
123 unsigned int i;
125 CGU_PERI |= CGU_VIC_CLOCK_ENABLE; /* enable VIC */
126 VIC_INT_EN_CLEAR = 0xffffffff; /* disable all interrupt lines */
127 VIC_INT_SELECT = 0; /* only IRQ, no FIQ */
129 VIC_DEF_VECT_ADDR = (unsigned long)UIRQ;
131 for(i = 0; i < n; i++)
133 vic_vect_addrs[i] = (unsigned long)vec_int_srcs[i].isr;
134 vic_vect_cntls[i] = (1<<5) | vec_int_srcs[i].source;
138 void irq_handler(void)
140 asm volatile( "stmfd sp!, {r0-r5,ip,lr} \n" /* Store context */
141 "ldr r5, =0xC6010030 \n" /* VIC_VECT_ADDR */
142 "mov lr, pc \n" /* Return from ISR */
143 "ldr pc, [r5] \n" /* execute ISR */
144 "str r0, [r5] \n" /* Ack interrupt */
145 "ldmfd sp!, {r0-r5,ip,lr} \n" /* Restore context */
146 "subs pc, lr, #4 \n" /* Return from IRQ */
150 void fiq_handler(void)
152 asm volatile (
153 "subs pc, lr, #4 \r\n"
157 #ifdef BOOTLOADER
158 static void sdram_delay(void)
160 int delay = 1024; /* arbitrary */
161 while (delay--) ;
164 /* Use the same initialization than OF */
165 static void sdram_init(void)
167 CGU_PERI |= (1<<26)|(1<<27); /* extmem & extmem intf clocks */
169 MPMC_CONTROL = 0x1; /* enable MPMC */
171 MPMC_DYNAMIC_CONTROL = 0x183; /* SDRAM NOP, all clocks high */
172 sdram_delay();
174 MPMC_DYNAMIC_CONTROL = 0x103; /* SDRAM PALL, all clocks high */
175 sdram_delay();
177 MPMC_DYNAMIC_REFRESH = 0x138; /* 0x138 * 16 HCLK ticks between SDRAM refresh cycles */
179 MPMC_CONFIG = 0; /* little endian, HCLK:MPMCCLKOUT[3:0] ratio = 1:1 */
181 if(MPMC_PERIPH_ID2 & 0xf0)
182 MPMC_DYNAMIC_READ_CONFIG = 0x1; /* command delayed, clock out not delayed */
184 /* timings */
185 MPMC_DYNAMIC_tRP = 2;
186 MPMC_DYNAMIC_tRAS = 4;
187 MPMC_DYNAMIC_tSREX = 5;
188 MPMC_DYNAMIC_tAPR = 0;
189 MPMC_DYNAMIC_tDAL = 4;
190 MPMC_DYNAMIC_tWR = 2;
191 MPMC_DYNAMIC_tRC = 5;
192 MPMC_DYNAMIC_tRFC = 5;
193 MPMC_DYNAMIC_tXSR = 5;
194 MPMC_DYNAMIC_tRRD = 2;
195 MPMC_DYNAMIC_tMRD = 2;
197 #if defined(SANSA_CLIP) || defined(SANSA_M200V4) || defined(SANSA_C200V2)
198 /* 16 bits external bus, low power SDRAM, 16 Mbits = 2 Mbytes */
199 #define MEMORY_MODEL 0x21
201 #elif defined(SANSA_E200V2) || defined(SANSA_FUZE)
202 /* 16 bits external bus, high performance SDRAM, 64 Mbits = 8 Mbytes */
203 #define MEMORY_MODEL 0x5
205 #else
206 #error "The external memory in your player is unknown"
207 #endif
209 MPMC_DYNAMIC_RASCAS_0 = (2<<8)|2; /* CAS & RAS latency = 2 clock cycles */
210 MPMC_DYNAMIC_CONFIG_0 = (MEMORY_MODEL << 7);
212 MPMC_DYNAMIC_RASCAS_1 = MPMC_DYNAMIC_CONFIG_1 =
213 MPMC_DYNAMIC_RASCAS_2 = MPMC_DYNAMIC_CONFIG_2 =
214 MPMC_DYNAMIC_RASCAS_3 = MPMC_DYNAMIC_CONFIG_3 = 0;
216 MPMC_DYNAMIC_CONTROL = 0x82; /* SDRAM MODE, MPMCCLKOUT runs continuously */
218 /* program the SDRAM mode register */
219 /* FIXME: details the exact settings of mode register */
220 asm volatile(
221 "ldr r4, [%0]\n"
222 : : "p"(0x30000000+0x2300*MEM) : "r4");
224 MPMC_DYNAMIC_CONTROL = 0x2; /* SDRAM NORMAL, MPMCCLKOUT runs continuously */
226 MPMC_DYNAMIC_CONFIG_0 |= (1<<19); /* buffer enable */
228 #else
229 void memory_init(void)
231 ttb_init();
232 /* map every region to itself, uncached */
233 map_section(0, 0, 4096, CACHE_NONE);
235 /* IRAM */
236 map_section(0, IRAM_ORIG, 1, CACHE_ALL);
237 map_section(0, UNCACHED_ADDR(IRAM_ORIG), 1, CACHE_NONE);
239 /* DRAM */
240 map_section(0x30000000, DRAM_ORIG, MEMORYSIZE, CACHE_ALL);
241 map_section(0x30000000, UNCACHED_ADDR(DRAM_ORIG), MEMORYSIZE, CACHE_NONE);
243 /* map 1st mbyte of DRAM at 0x0 to have exception vectors available */
244 map_section(0x30000000, 0, 1, CACHE_ALL);
246 enable_mmu();
248 #endif
250 void system_init(void)
252 unsigned int reset_loops = 640;
254 CCU_SRC = 0x1fffff0
255 & ~(1<<18); /* FIXME */
256 while(reset_loops--)
257 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
258 CCU_SRC = CCU_SRL = 0;
260 CCU_SCON = 1; /* AHB master's priority configuration :
261 TIC (Test Interface Controller) > DMA > USB > IDE > ARM */
263 CGU_PROC = 0; /* fclk 24 MHz */
264 CGU_PERI &= ~0x7f; /* pclk 24 MHz */
266 CGU_PLLA = AS3525_PLLA_SETTING;
267 while(!(CGU_INTCTRL & (1<<0))); /* wait until PLLA is locked */
269 /* Set FCLK frequency */
270 CGU_PROC = ((AS3525_FCLK_POSTDIV << 4) |
271 (AS3525_FCLK_PREDIV << 2) |
272 AS3525_FCLK_SEL);
273 /* Set PCLK frequency */
274 CGU_PERI = ((CGU_PERI & 0xffffff80) | /* reset divider bits 0:6 */
275 (AS3525_PCLK_DIV0 << 2) |
276 (AS3525_PCLK_DIV1 << 6) |
277 AS3525_PCLK_SEL);
279 asm volatile(
280 "mrc p15, 0, r0, c1, c0 \n" /* control register */
281 "bic r0, r0, #3<<30 \n" /* clears bus bits : sets fastbus */
282 "mcr p15, 0, r0, c1, c0 \n"
283 : : : "r0" );
285 #ifdef BOOTLOADER
286 sdram_init();
287 #endif /* BOOTLOADER */
289 #if 0 /* the GPIO clock is already enabled by the dualboot function */
290 CGU_PERI |= CGU_GPIO_CLOCK_ENABLE;
291 #endif
293 /* enable timer interface for TIMER1 & TIMER2 */
294 CGU_PERI |= CGU_TIMERIF_CLOCK_ENABLE;
296 setup_vic();
298 dma_init();
300 ascodec_init();
302 #ifndef BOOTLOADER
303 /* Initialize power management settings */
304 ascodec_write(AS3514_CVDD_DCDC3, AS314_CP_DCDC3_SETTING);
305 #ifdef CONFIG_TUNER
306 fmradio_i2c_init();
307 #endif
308 #endif /* !BOOTLOADER */
311 void system_reboot(void)
313 _backlight_off();
314 /* use watchdog to reset */
315 CGU_PERI |= (CGU_WDOCNT_CLOCK_ENABLE | CGU_WDOIF_CLOCK_ENABLE);
316 WDT_LOAD = 1; /* set counter to 1 */
317 WDT_CONTROL = 3; /* enable watchdog counter & reset */
318 while(1);
321 void system_exception_wait(void)
323 while(!button_read_device());
326 int system_memory_guard(int newmode)
328 (void)newmode;
329 return 0;
332 #ifndef BOOTLOADER
333 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
334 void set_cpu_frequency(long frequency)
336 if(frequency == CPUFREQ_MAX)
338 #ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE
339 /* Increasing frequency so boost voltage before change */
340 ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_20));
342 /* Wait for voltage to be at least 1.20v before making fclk > 200 MHz */
343 while(adc_read(ADC_CVDD) < 480) /* 480 * .0025 = 1.20V */
345 #endif
346 asm volatile(
347 "mrc p15, 0, r0, c1, c0 \n"
349 #ifdef ASYNCHRONOUS_BUS
350 "orr r0, r0, #3<<30 \n" /* asynchronous bus clocking */
351 #else
352 "bic r0, r0, #3<<30 \n" /* clear bus bits */
353 "orr r0, r0, #1<<30 \n" /* synchronous bus clocking */
354 #endif
356 "mcr p15, 0, r0, c1, c0 \n"
357 : : : "r0" );
359 cpu_frequency = CPUFREQ_MAX;
361 else
363 asm volatile(
364 "mrc p15, 0, r0, c1, c0 \n"
365 "bic r0, r0, #3<<30 \n" /* fastbus clocking */
366 "mcr p15, 0, r0, c1, c0 \n"
367 : : : "r0" );
368 #ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE
369 /* Decreasing frequency so reduce voltage after change */
370 ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_10));
371 #endif
372 cpu_frequency = CPUFREQ_NORMAL;
375 #endif /* HAVE_ADJUSTABLE_CPU_FREQ */
376 #endif /* !BOOTLOADER */