hm60x/hm801: Buttons rework.
[maemo-rb.git] / firmware / target / arm / imx233 / system-imx233.c
blob75196875680d10d61fcbf31f783e6a3c22ff9760
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2011 by amaury Pouly
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 "gcc_extensions.h"
25 #include "system-target.h"
26 #include "cpu.h"
27 #include "clkctrl-imx233.h"
28 #include "pinctrl-imx233.h"
29 #include "timrot-imx233.h"
30 #include "dma-imx233.h"
31 #include "ssp-imx233.h"
32 #include "i2c-imx233.h"
33 #include "dcp-imx233.h"
34 #include "lradc-imx233.h"
35 #include "lcd.h"
36 #include "backlight-target.h"
37 #include "button.h"
38 #include "fmradio_i2c.h"
40 #define default_interrupt(name) \
41 extern __attribute__((weak, alias("UIRQ"))) void name(void)
43 static void UIRQ (void) __attribute__((interrupt ("IRQ")));
44 void irq_handler(void) __attribute__((interrupt("IRQ")));
45 void fiq_handler(void) __attribute__((interrupt("FIQ")));
47 default_interrupt(INT_USB_CTRL);
48 default_interrupt(INT_TIMER0);
49 default_interrupt(INT_TIMER1);
50 default_interrupt(INT_TIMER2);
51 default_interrupt(INT_TIMER3);
52 default_interrupt(INT_LCDIF_DMA);
53 default_interrupt(INT_LCDIF_ERROR);
54 default_interrupt(INT_SSP1_DMA);
55 default_interrupt(INT_SSP1_ERROR);
56 default_interrupt(INT_SSP2_DMA);
57 default_interrupt(INT_SSP2_ERROR);
58 default_interrupt(INT_I2C_DMA);
59 default_interrupt(INT_I2C_ERROR);
60 default_interrupt(INT_GPIO0);
61 default_interrupt(INT_GPIO1);
62 default_interrupt(INT_GPIO2);
63 default_interrupt(INT_VDD5V);
64 default_interrupt(INT_LRADC_CH0);
65 default_interrupt(INT_LRADC_CH1);
66 default_interrupt(INT_LRADC_CH2);
67 default_interrupt(INT_LRADC_CH3);
68 default_interrupt(INT_LRADC_CH4);
69 default_interrupt(INT_LRADC_CH5);
70 default_interrupt(INT_LRADC_CH6);
71 default_interrupt(INT_LRADC_CH7);
72 default_interrupt(INT_DAC_DMA);
73 default_interrupt(INT_DAC_ERROR);
74 default_interrupt(INT_ADC_DMA);
75 default_interrupt(INT_ADC_ERROR);
76 default_interrupt(INT_DCP);
78 typedef void (*isr_t)(void);
80 static isr_t isr_table[INT_SRC_NR_SOURCES] =
82 [INT_SRC_USB_CTRL] = INT_USB_CTRL,
83 [INT_SRC_TIMER(0)] = INT_TIMER0,
84 [INT_SRC_TIMER(1)] = INT_TIMER1,
85 [INT_SRC_TIMER(2)] = INT_TIMER2,
86 [INT_SRC_TIMER(3)] = INT_TIMER3,
87 [INT_SRC_LCDIF_DMA] = INT_LCDIF_DMA,
88 [INT_SRC_LCDIF_ERROR] = INT_LCDIF_ERROR,
89 [INT_SRC_SSP1_DMA] = INT_SSP1_DMA,
90 [INT_SRC_SSP1_ERROR] = INT_SSP1_ERROR,
91 [INT_SRC_SSP2_DMA] = INT_SSP2_DMA,
92 [INT_SRC_SSP2_ERROR] = INT_SSP2_ERROR,
93 [INT_SRC_I2C_DMA] = INT_I2C_DMA,
94 [INT_SRC_I2C_ERROR] = INT_I2C_ERROR,
95 [INT_SRC_GPIO0] = INT_GPIO0,
96 [INT_SRC_GPIO1] = INT_GPIO1,
97 [INT_SRC_GPIO2] = INT_GPIO2,
98 [INT_SRC_VDD5V] = INT_VDD5V,
99 [INT_SRC_LRADC_CHx(0)] = INT_LRADC_CH0,
100 [INT_SRC_LRADC_CHx(1)] = INT_LRADC_CH1,
101 [INT_SRC_LRADC_CHx(2)] = INT_LRADC_CH2,
102 [INT_SRC_LRADC_CHx(3)] = INT_LRADC_CH3,
103 [INT_SRC_LRADC_CHx(4)] = INT_LRADC_CH4,
104 [INT_SRC_LRADC_CHx(5)] = INT_LRADC_CH5,
105 [INT_SRC_LRADC_CHx(6)] = INT_LRADC_CH6,
106 [INT_SRC_LRADC_CHx(7)] = INT_LRADC_CH7,
107 [INT_SRC_DAC_DMA] = INT_DAC_DMA,
108 [INT_SRC_DAC_ERROR] = INT_DAC_ERROR,
109 [INT_SRC_ADC_DMA] = INT_ADC_DMA,
110 [INT_SRC_ADC_ERROR] = INT_ADC_ERROR,
111 [INT_SRC_DCP] = INT_DCP,
114 static void UIRQ(void)
116 panicf("Unhandled IRQ %02X",
117 (unsigned int)(HW_ICOLL_VECTOR - (uint32_t)isr_table) / 4);
120 void irq_handler(void)
122 HW_ICOLL_VECTOR = HW_ICOLL_VECTOR; /* notify icoll that we entered ISR */
123 (*(isr_t *)HW_ICOLL_VECTOR)();
124 /* acknowledge completion of IRQ (all use the same priority 0) */
125 HW_ICOLL_LEVELACK = HW_ICOLL_LEVELACK__LEVEL0;
128 void fiq_handler(void)
132 void imx233_chip_reset(void)
134 HW_CLKCTRL_RESET = HW_CLKCTRL_RESET_CHIP;
137 void system_reboot(void)
139 _backlight_off();
141 disable_irq();
143 /* use watchdog to reset */
144 imx233_chip_reset();
145 while(1);
148 void system_exception_wait(void)
150 /* make sure lcd and backlight are on */
151 lcd_update();
152 _backlight_on();
153 _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING);
154 /* wait until button release (if a button is pressed) */
155 while(button_read_device());
156 /* then wait until next button press */
157 while(!button_read_device());
160 int system_memory_guard(int newmode)
162 (void)newmode;
163 return 0;
166 void imx233_enable_interrupt(int src, bool enable)
168 if(enable)
169 __REG_SET(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__ENABLE;
170 else
171 __REG_CLR(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__ENABLE;
174 void imx233_softirq(int src, bool enable)
176 if(enable)
177 __REG_SET(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__SOFTIRQ;
178 else
179 __REG_CLR(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__SOFTIRQ;
182 static void set_page_tables(void)
184 /* map every memory region to itself */
185 map_section(0, 0, 0x1000, CACHE_NONE);
187 /* map RAM and enable caching for it */
188 map_section(DRAM_ORIG, CACHED_DRAM_ADDR, MEMORYSIZE, CACHE_ALL);
189 map_section(DRAM_ORIG, BUFFERED_DRAM_ADDR, MEMORYSIZE, BUFFERED);
192 void memory_init(void)
194 ttb_init();
195 set_page_tables();
196 enable_mmu();
199 void system_init(void)
201 imx233_reset_block(&HW_ICOLL_CTRL);
202 /* disable all interrupts */
203 for(int i = 0; i < INT_SRC_NR_SOURCES; i++)
205 /* priority = 0, disable, disable fiq */
206 HW_ICOLL_INTERRUPT(i) = 0;
208 /* setup vbase as isr_table */
209 HW_ICOLL_VBASE = (uint32_t)&isr_table;
210 /* enable final irq bit */
211 __REG_SET(HW_ICOLL_CTRL) = HW_ICOLL_CTRL__IRQ_FINAL_ENABLE;
213 imx233_pinctrl_init();
214 imx233_timrot_init();
215 imx233_dma_init();
216 imx233_ssp_init();
217 imx233_dcp_init();
218 imx233_lradc_init();
219 imx233_i2c_init();
220 #if defined(SANSA_FUZEPLUS) && !defined(BOOTLOADER)
221 fmradio_i2c_init();
222 #endif
225 bool imx233_us_elapsed(uint32_t ref, unsigned us_delay)
227 uint32_t cur = HW_DIGCTL_MICROSECONDS;
228 if(ref + us_delay <= ref)
229 return !(cur > ref) && !(cur < (ref + us_delay));
230 else
231 return (cur < ref) || cur >= (ref + us_delay);
234 void imx233_reset_block(volatile uint32_t *block_reg)
236 /* soft-reset */
237 __REG_SET(*block_reg) = __BLOCK_SFTRST;
238 /* make sure block is gated off */
239 while(!(*block_reg & __BLOCK_CLKGATE));
240 /* bring block out of reset */
241 __REG_CLR(*block_reg) = __BLOCK_SFTRST;
242 while(*block_reg & __BLOCK_SFTRST);
243 /* make sure clock is running */
244 __REG_CLR(*block_reg) = __BLOCK_CLKGATE;
245 while(*block_reg & __BLOCK_CLKGATE);
248 void udelay(unsigned us)
250 uint32_t ref = HW_DIGCTL_MICROSECONDS;
251 while(!imx233_us_elapsed(ref, us));
254 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
255 void set_cpu_frequency(long frequency)
257 switch(frequency)
259 #if 0
260 case IMX233_CPUFREQ_454_MHz:
261 /* clk_h@clk_p/3 */
262 imx233_set_clock_divisor(CLK_AHB, 3);
263 /* clk_p@ref_cpu/1*18/19 */
264 imx233_set_fractional_divisor(CLK_CPU, 19);
265 imx233_set_clock_divisor(CLK_CPU, 1);
266 /* ref_cpu@480 MHz
267 * clk_p@454.74 MHz
268 * clk_h@151.58 MHz */
269 break;
270 #endif
271 default:
272 break;
275 #endif
277 void imx233_enable_usb_controller(bool enable)
279 if(enable)
280 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
281 else
282 __REG_SET(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
285 void imx233_enable_usb_phy(bool enable)
287 if(enable)
289 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
290 __REG_CLR(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL;
292 else
294 __REG_SET(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL;
295 __REG_SET(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;