i.MX31/Gigabeat S: Implement frequency and voltage scaling-- 1.6V for 528MHz, and...
[kugel-rb.git] / firmware / target / arm / imx31 / gigabeat-s / system-gigabeat-s.c
blob7c0d30c7833101a98b5cdb4997e4395f7bbd7048
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 by James Espinoza
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "kernel.h"
23 #include "system.h"
24 #include "panic.h"
25 #include "avic-imx31.h"
26 #include "gpio-imx31.h"
27 #include "mmu-imx31.h"
28 #include "system-target.h"
29 #include "powermgmt-target.h"
30 #include "lcd.h"
31 #include "serial-imx31.h"
32 #include "debug.h"
33 #include "ccm-imx31.h"
34 #include "mc13783.h"
35 #include "dvfs_dptc-imx31.h"
37 static unsigned long product_rev;
38 static unsigned long system_rev;
40 /** IC revision info routines **/
41 unsigned int iim_system_rev(void)
43 return system_rev & IIM_SREV_SREV;
46 unsigned int iim_prod_rev(void)
48 return product_rev;
51 static void iim_init(void)
53 /* Initialize the IC revision info (required by SDMA) */
54 ccm_module_clock_gating(CG_IIM, CGM_ON_RUN_WAIT);
55 product_rev = IIM_PREV;
56 system_rev = IIM_SREV;
59 /** Watchdog timer routines **/
61 /* Initialize the watchdog timer */
62 void watchdog_init(unsigned int half_seconds)
64 uint16_t wcr = ((half_seconds << WDOG_WCR_WT_POS) & WDOG_WCR_WT) |
65 WDOG_WCR_WOE | /* WDOG output enabled */
66 WDOG_WCR_WDA | /* WDOG assertion - no effect */
67 WDOG_WCR_SRS | /* System reset - no effect */
68 WDOG_WCR_WRE; /* Generate a WDOG signal */
70 ccm_module_clock_gating(CG_WDOG, CGM_ON_RUN_WAIT);
72 WDOG_WCR = wcr;
73 WDOG_WSR = 0x5555;
74 WDOG_WCR = wcr | WDOG_WCR_WDE; /* Enable timer - hardware does
75 not allow a disable now */
76 WDOG_WSR = 0xaaaa;
79 /* Service the watchdog timer */
80 void watchdog_service(void)
82 WDOG_WSR = 0x5555;
83 WDOG_WSR = 0xaaaa;
86 /** GPT timer routines - basis for udelay **/
88 /* Start the general-purpose timer (1MHz) */
89 void gpt_start(void)
91 ccm_module_clock_gating(CG_GPT, CGM_ON_RUN_WAIT);
92 unsigned int ipg_mhz = ccm_get_ipg_clk() / 1000000;
94 GPTCR &= ~GPTCR_EN; /* Disable counter */
95 GPTCR |= GPTCR_SWR; /* Reset module */
96 while (GPTCR & GPTCR_SWR);
97 /* No output
98 * No capture
99 * Enable in run mode only (doesn't tick while in WFI)
100 * Freerun mode (count to 0xFFFFFFFF and roll-over to 0x00000000)
102 GPTCR = GPTCR_FRR | GPTCR_CLKSRC_IPG_CLK;
103 GPTPR = ipg_mhz - 1;
104 GPTCR |= GPTCR_EN;
107 /* Stop the general-purpose timer */
108 void gpt_stop(void)
110 GPTCR &= ~GPTCR_EN;
113 int system_memory_guard(int newmode)
115 (void)newmode;
116 return 0;
119 void system_halt(void)
121 disable_interrupt(IRQ_FIQ_STATUS);
122 avic_set_ni_level(AVIC_NIL_DISABLE);
123 while (1)
124 core_idle();
127 void system_reboot(void)
129 /* Multi-context so no SPI available (WDT?) */
130 system_halt();
133 void system_exception_wait(void)
135 /* Called in many contexts so button reading may be a chore */
136 system_halt();
139 void system_init(void)
141 static const int disable_clocks[] =
143 /* CGR0 */
144 CG_SD_MMC1,
145 CG_SD_MMC2,
146 CG_IIM,
147 CG_SDMA,
148 CG_CSPI3,
149 CG_RNG,
150 CG_UART1,
151 CG_UART2,
152 CG_SSI1,
153 CG_I2C1,
154 CG_I2C2,
155 CG_I2C3,
157 /* CGR1 */
158 CG_HANTRO,
159 CG_MEMSTICK1,
160 CG_MEMSTICK2,
161 CG_CSI,
162 CG_RTC,
163 CG_WDOG,
164 CG_PWM,
165 CG_SIM,
166 CG_ECT,
167 CG_USBOTG,
168 CG_KPP,
169 CG_UART3,
170 CG_UART4,
171 CG_UART5,
172 CG_1_WIRE,
174 /* CGR2 */
175 CG_SSI2,
176 CG_CSPI1,
177 CG_CSPI2,
178 CG_GACC,
179 CG_RTIC,
180 CG_FIR
183 unsigned int i;
185 /* Initialize frequency with current */
186 cpu_frequency = ccm_get_mcu_clk();
188 /* MCR WFI enables wait mode (CCM_CCMR_LPM_WAIT_MODE = 0) */
189 imx31_regclr32(&CCM_CCMR, CCM_CCMR_LPM);
191 iim_init();
193 imx31_regset32(&SDHC1_CLOCK_CONTROL, STOP_CLK);
194 imx31_regset32(&SDHC2_CLOCK_CONTROL, STOP_CLK);
195 imx31_regset32(&RNGA_CONTROL, RNGA_CONTROL_SLEEP);
196 imx31_regclr32(&UCR1_1, EUARTUCR1_UARTEN);
197 imx31_regclr32(&UCR1_2, EUARTUCR1_UARTEN);
198 imx31_regclr32(&UCR1_3, EUARTUCR1_UARTEN);
199 imx31_regclr32(&UCR1_4, EUARTUCR1_UARTEN);
200 imx31_regclr32(&UCR1_5, EUARTUCR1_UARTEN);
202 for (i = 0; i < ARRAYLEN(disable_clocks); i++)
203 ccm_module_clock_gating(disable_clocks[i], CGM_OFF);
205 avic_init();
206 gpt_start();
207 gpio_init();
210 void __attribute__((naked)) imx31_regmod32(volatile uint32_t *reg_p,
211 uint32_t value,
212 uint32_t mask)
214 asm volatile("and r1, r1, r2 \n"
215 "mrs ip, cpsr \n"
216 "cpsid if \n"
217 "ldr r3, [r0] \n"
218 "bic r3, r3, r2 \n"
219 "orr r3, r3, r1 \n"
220 "str r3, [r0] \n"
221 "msr cpsr_c, ip \n"
222 "bx lr \n");
223 (void)reg_p; (void)value; (void)mask;
226 void __attribute__((naked)) imx31_regset32(volatile uint32_t *reg_p,
227 uint32_t mask)
229 asm volatile("mrs r3, cpsr \n"
230 "cpsid if \n"
231 "ldr r2, [r0] \n"
232 "orr r2, r2, r1 \n"
233 "str r2, [r0] \n"
234 "msr cpsr_c, r3 \n"
235 "bx lr \n");
236 (void)reg_p; (void)mask;
239 void __attribute__((naked)) imx31_regclr32(volatile uint32_t *reg_p,
240 uint32_t mask)
242 asm volatile("mrs r3, cpsr \n"
243 "cpsid if \n"
244 "ldr r2, [r0] \n"
245 "bic r2, r2, r1 \n"
246 "str r2, [r0] \n"
247 "msr cpsr_c, r3 \n"
248 "bx lr \n");
249 (void)reg_p; (void)mask;
253 void system_prepare_fw_start(void)
255 dvfs_dptc_stop();
256 mc13783_close();
257 tick_stop();
258 disable_interrupt(IRQ_FIQ_STATUS);
259 avic_set_ni_level(AVIC_NIL_DISABLE);
263 #ifndef BOOTLOADER
264 void rolo_restart_firmware(const unsigned char *source, unsigned char *dest,
265 int length) __attribute__((noreturn));
267 void __attribute__((noreturn))
268 rolo_restart(const unsigned char *source, unsigned char *dest, int length)
270 /* Some housekeeping tasks must be performed for a safe changeover */
271 charging_algorithm_close();
272 system_prepare_fw_start();
274 /* Copying routine where new image is run */
275 rolo_restart_firmware(source, dest, length);
277 #endif /* BOOTLOADER */
280 inline void dumpregs(void)
282 asm volatile ("mov %0,r0\n\t"
283 "mov %1,r1\n\t"
284 "mov %2,r2\n\t"
285 "mov %3,r3":
286 "=r"(regs.r0),"=r"(regs.r1),
287 "=r"(regs.r2),"=r"(regs.r3):);
289 asm volatile ("mov %0,r4\n\t"
290 "mov %1,r5\n\t"
291 "mov %2,r6\n\t"
292 "mov %3,r7":
293 "=r"(regs.r4),"=r"(regs.r5),
294 "=r"(regs.r6),"=r"(regs.r7):);
296 asm volatile ("mov %0,r8\n\t"
297 "mov %1,r9\n\t"
298 "mov %2,r10\n\t"
299 "mov %3,r12":
300 "=r"(regs.r8),"=r"(regs.r9),
301 "=r"(regs.r10),"=r"(regs.r11):);
303 asm volatile ("mov %0,r12\n\t"
304 "mov %1,sp\n\t"
305 "mov %2,lr\n\t"
306 "mov %3,pc\n"
307 "sub %3,%3,#8":
308 "=r"(regs.r12),"=r"(regs.sp),
309 "=r"(regs.lr),"=r"(regs.pc):);
310 #ifdef HAVE_SERIAL
311 dprintf("Register Dump :\n");
312 dprintf("R0=0x%x\tR1=0x%x\tR2=0x%x\tR3=0x%x\n",regs.r0,regs.r1,regs.r2,regs.r3);
313 dprintf("R4=0x%x\tR5=0x%x\tR6=0x%x\tR7=0x%x\n",regs.r4,regs.r5,regs.r6,regs.r7);
314 dprintf("R8=0x%x\tR9=0x%x\tR10=0x%x\tR11=0x%x\n",regs.r8,regs.r9,regs.r10,regs.r11);
315 dprintf("R12=0x%x\tSP=0x%x\tLR=0x%x\tPC=0x%x\n",regs.r12,regs.sp,regs.lr,regs.pc);
316 //dprintf("CPSR=0x%x\t\n",regs.cpsr);
317 #endif
318 DEBUGF("Register Dump :\n");
319 DEBUGF("R0=0x%x\tR1=0x%x\tR2=0x%x\tR3=0x%x\n",regs.r0,regs.r1,regs.r2,regs.r3);
320 DEBUGF("R4=0x%x\tR5=0x%x\tR6=0x%x\tR7=0x%x\n",regs.r4,regs.r5,regs.r6,regs.r7);
321 DEBUGF("R8=0x%x\tR9=0x%x\tR10=0x%x\tR11=0x%x\n",regs.r8,regs.r9,regs.r10,regs.r11);
322 DEBUGF("R12=0x%x\tSP=0x%x\tLR=0x%x\tPC=0x%x\n",regs.r12,regs.sp,regs.lr,regs.pc);
323 //DEBUGF("CPSR=0x%x\t\n",regs.cpsr);
327 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
329 void set_cpu_frequency(long frequency)
331 (void)freqency;
334 #endif