1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
24 #include "gcc_extensions.h"
25 #include "system-target.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 "pwm-imx233.h"
35 #include "icoll-imx233.h"
36 #include "lradc-imx233.h"
37 #include "rtc-imx233.h"
38 #include "power-imx233.h"
39 #include "emi-imx233.h"
41 #include "backlight-target.h"
43 #include "fmradio_i2c.h"
45 void imx233_chip_reset(void)
47 HW_CLKCTRL_RESET
= HW_CLKCTRL_RESET_CHIP
;
50 void system_reboot(void)
56 /* use watchdog to reset */
61 void system_exception_wait(void)
63 /* make sure lcd and backlight are on */
66 _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING
);
67 /* wait until button release (if a button is pressed) */
68 #ifdef HAVE_BUTTON_DATA
70 while(button_read_device(&data
));
71 /* then wait until next button press */
72 while(!button_read_device(&data
));
74 while(button_read_device());
75 /* then wait until next button press */
76 while(!button_read_device());
80 int system_memory_guard(int newmode
)
86 static void set_page_tables(void)
88 /* map every memory region to itself */
89 map_section(0, 0, 0x1000, CACHE_NONE
);
91 /* map RAM and enable caching for it */
92 map_section(DRAM_ORIG
, CACHED_DRAM_ADDR
, MEMORYSIZE
, CACHE_ALL
);
93 map_section(DRAM_ORIG
, BUFFERED_DRAM_ADDR
, MEMORYSIZE
, BUFFERED
);
96 void memory_init(void)
103 void system_init(void)
105 /* NOTE: don't use anything here that might require tick task !
106 * It is initialized by kernel_init *after* system_init().
107 * The main() will naturally set cpu speed to normal after kernel_init()
108 * so don't bother if the cpu is running at 24MHz here. */
109 imx233_clkctrl_enable_clock(CLK_PLL
, true);
112 imx233_pinctrl_init();
113 imx233_timrot_init();
122 imx233_clkctrl_enable_auto_slow_monitor(AS_CPU_INSTR
, true);
123 imx233_clkctrl_enable_auto_slow_monitor(AS_CPU_DATA
, true);
124 imx233_clkctrl_enable_auto_slow_monitor(AS_TRAFFIC
, true);
125 imx233_clkctrl_enable_auto_slow_monitor(AS_TRAFFIC_JAM
, true);
126 imx233_clkctrl_enable_auto_slow_monitor(AS_APBXDMA
, true);
127 imx233_clkctrl_enable_auto_slow_monitor(AS_APBHDMA
, true);
128 imx233_clkctrl_set_auto_slow_divisor(AS_DIV_8
);
129 imx233_clkctrl_enable_auto_slow(true);
131 cpu_frequency
= imx233_clkctrl_get_clock_freq(CLK_CPU
);
133 #if !defined(BOOTLOADER) &&(defined(SANSA_FUZEPLUS) || \
134 defined(CREATIVE_ZENXFI3) || defined(CREATIVE_ZENXFI2))
139 bool imx233_us_elapsed(uint32_t ref
, unsigned us_delay
)
141 uint32_t cur
= HW_DIGCTL_MICROSECONDS
;
142 if(ref
+ us_delay
<= ref
)
143 return !(cur
> ref
) && !(cur
< (ref
+ us_delay
));
145 return (cur
< ref
) || cur
>= (ref
+ us_delay
);
148 void imx233_reset_block(volatile uint32_t *block_reg
)
151 __REG_SET(*block_reg
) = __BLOCK_SFTRST
;
152 /* make sure block is gated off */
153 while(!(*block_reg
& __BLOCK_CLKGATE
));
154 /* bring block out of reset */
155 __REG_CLR(*block_reg
) = __BLOCK_SFTRST
;
156 while(*block_reg
& __BLOCK_SFTRST
);
157 /* make sure clock is running */
158 __REG_CLR(*block_reg
) = __BLOCK_CLKGATE
;
159 while(*block_reg
& __BLOCK_CLKGATE
);
162 void udelay(unsigned us
)
164 uint32_t ref
= HW_DIGCTL_MICROSECONDS
;
165 while(!imx233_us_elapsed(ref
, us
));
168 void imx233_digctl_set_arm_cache_timings(unsigned timings
)
171 timings
<< HW_DIGCTL_ARMCACHE__ITAG_SS_BP
|
172 timings
<< HW_DIGCTL_ARMCACHE__DTAG_SS_BP
|
173 timings
<< HW_DIGCTL_ARMCACHE__CACHE_SS_BP
|
174 timings
<< HW_DIGCTL_ARMCACHE__DRTY_SS_BP
|
175 timings
<< HW_DIGCTL_ARMCACHE__VALID_SS_BP
;
178 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
179 struct cpufreq_profile_t
186 int cpu_idiv
, cpu_fdiv
;
188 int arm_cache_timings
;
191 static struct cpufreq_profile_t cpu_profiles
[] =
193 /* clk_p@454.74 MHz, clk_h@130.91 MHz, clk_emi@130.91 MHz */
194 {IMX233_CPUFREQ_454_MHz
, 1550, 1450, 3, 1, 19, IMX233_EMIFREQ_130_MHz
, 0},
195 /* clk_p@261.82 MHz, clk_h@130.91 MHz, clk_emi@130.91 MHz */
196 {IMX233_CPUFREQ_261_MHz
, 1275, 1175, 2, 1, 33, IMX233_EMIFREQ_130_MHz
, 0},
197 /* clk_p@64 MHz, clk_h@64 MHz, clk_emi@64 MHz */
198 {IMX233_CPUFREQ_64_MHz
, 1050, 975, 1, 5, 27, IMX233_EMIFREQ_64_MHz
, 0},
200 {0, 0, 0, 0, 0, 0, 0, 0}
203 #define NR_CPU_PROFILES ((int)(sizeof(cpu_profiles)/sizeof(cpu_profiles[0])))
205 void set_cpu_frequency(long frequency
)
207 /* don't change the frequency if it is useless (changes are expensive) */
208 if(cpu_frequency
== frequency
)
211 struct cpufreq_profile_t
*prof
= cpu_profiles
;
212 while(prof
->cpu_freq
!= 0 && prof
->cpu_freq
!= frequency
)
214 if(prof
->cpu_freq
== 0)
216 /* disable auto-slow (enable back afterwards) */
217 bool as
= imx233_clkctrl_is_auto_slow_enabled();
218 imx233_clkctrl_enable_auto_slow(false);
220 /* WARNING watch out the order ! */
221 if(frequency
> cpu_frequency
)
223 /* Change VDDD regulator */
224 imx233_power_set_regulator(REGULATOR_VDDD
, prof
->vddd
, prof
->vddd_bo
);
225 /* Change ARM cache timings */
226 imx233_digctl_set_arm_cache_timings(prof
->arm_cache_timings
);
227 /* Switch CPU to crystal at 24MHz */
228 imx233_clkctrl_set_bypass_pll(CLK_CPU
, true);
229 /* Program CPU divider for PLL */
230 imx233_clkctrl_set_fractional_divisor(CLK_CPU
, prof
->cpu_fdiv
);
231 imx233_clkctrl_set_clock_divisor(CLK_CPU
, prof
->cpu_idiv
);
232 /* Change the HBUS divider to its final value */
233 imx233_clkctrl_set_clock_divisor(CLK_HBUS
, prof
->hbus_div
);
234 /* Switch back CPU to PLL */
235 imx233_clkctrl_set_bypass_pll(CLK_CPU
, false);
236 /* Set the new EMI frequency */
237 imx233_emi_set_frequency(prof
->emi_freq
);
241 /* Switch CPU to crystal at 24MHz */
242 imx233_clkctrl_set_bypass_pll(CLK_CPU
, true);
243 /* Program HBUS divider to its final value */
244 imx233_clkctrl_set_clock_divisor(CLK_HBUS
, prof
->hbus_div
);
245 /* Program CPU divider for PLL */
246 imx233_clkctrl_set_fractional_divisor(CLK_CPU
, prof
->cpu_fdiv
);
247 imx233_clkctrl_set_clock_divisor(CLK_CPU
, prof
->cpu_idiv
);
248 /* Switch back CPU to PLL */
249 imx233_clkctrl_set_bypass_pll(CLK_CPU
, false);
250 /* Set the new EMI frequency */
251 imx233_emi_set_frequency(prof
->emi_freq
);
252 /* Change ARM cache timings */
253 imx233_digctl_set_arm_cache_timings(prof
->arm_cache_timings
);
254 /* Change VDDD regulator */
255 imx233_power_set_regulator(REGULATOR_VDDD
, prof
->vddd
, prof
->vddd_bo
);
257 /* enable auto slow again */
258 imx233_clkctrl_enable_auto_slow(as
);
259 /* update frequency */
260 cpu_frequency
= frequency
;
264 void imx233_enable_usb_controller(bool enable
)
267 __REG_CLR(HW_DIGCTL_CTRL
) = HW_DIGCTL_CTRL__USB_CLKGATE
;
269 __REG_SET(HW_DIGCTL_CTRL
) = HW_DIGCTL_CTRL__USB_CLKGATE
;
272 void imx233_enable_usb_phy(bool enable
)
276 __REG_CLR(HW_USBPHY_CTRL
) = __BLOCK_CLKGATE
| __BLOCK_SFTRST
;
277 __REG_CLR(HW_USBPHY_PWD
) = HW_USBPHY_PWD__ALL
;
281 __REG_SET(HW_USBPHY_PWD
) = HW_USBPHY_PWD__ALL
;
282 __REG_SET(HW_USBPHY_CTRL
) = __BLOCK_CLKGATE
| __BLOCK_SFTRST
;