summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/clkctrl-imx233.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/clkctrl-imx233.c')
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.c151
1 files changed, 68 insertions, 83 deletions
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.c b/firmware/target/arm/imx233/clkctrl-imx233.c
index 1553889543..102ef4e432 100644
--- a/firmware/target/arm/imx233/clkctrl-imx233.c
+++ b/firmware/target/arm/imx233/clkctrl-imx233.c
@@ -20,29 +20,19 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "clkctrl-imx233.h" 21#include "clkctrl-imx233.h"
22 22
23#define __CLK_CLKGATE (1 << 31) 23void imx233_clkctrl_enable(enum imx233_clock_t clk, bool enable)
24#define __CLK_BUSY (1 << 29)
25
26void imx233_clkctrl_enable_xtal(enum imx233_xtal_clk_t xtal_clk, bool enable)
27{
28 if(enable)
29 HW_CLKCTRL_XTAL_CLR = xtal_clk;
30 else
31 HW_CLKCTRL_XTAL_SET = xtal_clk;
32}
33
34bool imx233_clkctrl_is_xtal_enable(enum imx233_xtal_clk_t clk)
35{
36 return HW_CLKCTRL_XTAL & clk;
37}
38
39void imx233_clkctrl_enable_clock(enum imx233_clock_t clk, bool enable)
40{ 24{
25 /* NOTE some registers like HW_CLKCTRL_PIX don't have a CLR/SET variant ! */
41 bool gate = !enable; 26 bool gate = !enable;
42 switch(clk) 27 switch(clk)
43 { 28 {
44 case CLK_PIX: BF_WR(CLKCTRL_PIX, CLKGATE, gate); break; 29 case CLK_PIX: BF_WR(CLKCTRL_PIX, CLKGATE, gate); break;
45 case CLK_SSP: BF_WR(CLKCTRL_SSP, CLKGATE, gate); break; 30 case CLK_SSP: BF_WR(CLKCTRL_SSP, CLKGATE, gate); break;
31 case CLK_DRI: BF_WR(CLKCTRL_XTAL, DRI_CLK24M_GATE, gate); break;
32 case CLK_PWM: BF_WR(CLKCTRL_XTAL, PWM_CLK24M_GATE, gate); break;
33 case CLK_UART: BF_WR(CLKCTRL_XTAL, UART_CLK_GATE, gate); break;
34 case CLK_FILT: BF_WR(CLKCTRL_XTAL, FILT_CLK24M_GATE, gate); break;
35 case CLK_TIMROT: BF_WR(CLKCTRL_XTAL, TIMROT_CLK32K_GATE, gate); break;
46 case CLK_PLL: 36 case CLK_PLL:
47 /* pll is a special case */ 37 /* pll is a special case */
48 if(enable) 38 if(enable)
@@ -58,18 +48,23 @@ void imx233_clkctrl_enable_clock(enum imx233_clock_t clk, bool enable)
58 } 48 }
59} 49}
60 50
61bool imx233_clkctrl_is_clock_enabled(enum imx233_clock_t clk) 51bool imx233_clkctrl_is_enabled(enum imx233_clock_t clk)
62{ 52{
63 switch(clk) 53 switch(clk)
64 { 54 {
65 case CLK_PLL: return BF_RD(CLKCTRL_PLLCTRL0, POWER); 55 case CLK_PLL: return BF_RD(CLKCTRL_PLLCTRL0, POWER);
66 case CLK_PIX: return !BF_RD(CLKCTRL_PIX, CLKGATE); 56 case CLK_PIX: return !BF_RD(CLKCTRL_PIX, CLKGATE);
67 case CLK_SSP: return !BF_RD(CLKCTRL_SSP, CLKGATE); 57 case CLK_SSP: return !BF_RD(CLKCTRL_SSP, CLKGATE);
58 case CLK_DRI: return !BF_RD(CLKCTRL_XTAL, DRI_CLK24M_GATE);
59 case CLK_PWM: return !BF_RD(CLKCTRL_XTAL, PWM_CLK24M_GATE);
60 case CLK_UART: return !BF_RD(CLKCTRL_XTAL, UART_CLK_GATE);
61 case CLK_FILT: return !BF_RD(CLKCTRL_XTAL, FILT_CLK24M_GATE);
62 case CLK_TIMROT: return !BF_RD(CLKCTRL_XTAL, TIMROT_CLK32K_GATE);
68 default: return true; 63 default: return true;
69 } 64 }
70} 65}
71 66
72void imx233_clkctrl_set_clock_divisor(enum imx233_clock_t clk, int div) 67void imx233_clkctrl_set_div(enum imx233_clock_t clk, int div)
73{ 68{
74 /* warning: some registers like HW_CLKCTRL_PIX don't have a CLR/SET variant ! 69 /* warning: some registers like HW_CLKCTRL_PIX don't have a CLR/SET variant !
75 * assume that we always derive emi and cpu from ref_XX */ 70 * assume that we always derive emi and cpu from ref_XX */
@@ -85,7 +80,7 @@ void imx233_clkctrl_set_clock_divisor(enum imx233_clock_t clk, int div)
85 } 80 }
86} 81}
87 82
88int imx233_clkctrl_get_clock_divisor(enum imx233_clock_t clk) 83int imx233_clkctrl_get_div(enum imx233_clock_t clk)
89{ 84{
90 switch(clk) 85 switch(clk)
91 { 86 {
@@ -99,7 +94,7 @@ int imx233_clkctrl_get_clock_divisor(enum imx233_clock_t clk)
99 } 94 }
100} 95}
101 96
102void imx233_clkctrl_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv) 97void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv)
103{ 98{
104#define handle_frac(dev) \ 99#define handle_frac(dev) \
105 case CLK_##dev: \ 100 case CLK_##dev: \
@@ -120,7 +115,7 @@ void imx233_clkctrl_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv)
120#undef handle_frac 115#undef handle_frac
121} 116}
122 117
123int imx233_clkctrl_get_fractional_divisor(enum imx233_clock_t clk) 118int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk)
124{ 119{
125#define handle_frac(dev) \ 120#define handle_frac(dev) \
126 case CLK_##dev:\ 121 case CLK_##dev:\
@@ -139,7 +134,7 @@ int imx233_clkctrl_get_fractional_divisor(enum imx233_clock_t clk)
139#undef handle_frac 134#undef handle_frac
140} 135}
141 136
142void imx233_clkctrl_set_bypass_pll(enum imx233_clock_t clk, bool bypass) 137void imx233_clkctrl_set_bypass(enum imx233_clock_t clk, bool bypass)
143{ 138{
144 uint32_t msk; 139 uint32_t msk;
145 switch(clk) 140 switch(clk)
@@ -157,7 +152,7 @@ void imx233_clkctrl_set_bypass_pll(enum imx233_clock_t clk, bool bypass)
157 HW_CLKCTRL_CLKSEQ_CLR = msk; 152 HW_CLKCTRL_CLKSEQ_CLR = msk;
158} 153}
159 154
160bool imx233_clkctrl_get_bypass_pll(enum imx233_clock_t clk) 155bool imx233_clkctrl_get_bypass(enum imx233_clock_t clk)
161{ 156{
162 switch(clk) 157 switch(clk)
163 { 158 {
@@ -169,7 +164,7 @@ bool imx233_clkctrl_get_bypass_pll(enum imx233_clock_t clk)
169 } 164 }
170} 165}
171 166
172void imx233_clkctrl_enable_usb_pll(bool enable) 167void imx233_clkctrl_enable_usb(bool enable)
173{ 168{
174 if(enable) 169 if(enable)
175 BF_SET(CLKCTRL_PLLCTRL0, EN_USB_CLKS); 170 BF_SET(CLKCTRL_PLLCTRL0, EN_USB_CLKS);
@@ -177,12 +172,12 @@ void imx233_clkctrl_enable_usb_pll(bool enable)
177 BF_CLR(CLKCTRL_PLLCTRL0, EN_USB_CLKS); 172 BF_CLR(CLKCTRL_PLLCTRL0, EN_USB_CLKS);
178} 173}
179 174
180bool imx233_clkctrl_is_usb_pll_enabled(void) 175bool imx233_clkctrl_is_usb_enabled(void)
181{ 176{
182 return BF_RD(CLKCTRL_PLLCTRL0, EN_USB_CLKS); 177 return BF_RD(CLKCTRL_PLLCTRL0, EN_USB_CLKS);
183} 178}
184 179
185void imx233_clkctrl_set_auto_slow_divisor(enum imx233_as_div_t div) 180void imx233_clkctrl_set_auto_slow_div(unsigned div)
186{ 181{
187 /* the SLOW_DIV must only be set when auto-slow is disabled */ 182 /* the SLOW_DIV must only be set when auto-slow is disabled */
188 bool old_status = imx233_clkctrl_is_auto_slow_enabled(); 183 bool old_status = imx233_clkctrl_is_auto_slow_enabled();
@@ -191,7 +186,7 @@ void imx233_clkctrl_set_auto_slow_divisor(enum imx233_as_div_t div)
191 imx233_clkctrl_enable_auto_slow(old_status); 186 imx233_clkctrl_enable_auto_slow(old_status);
192} 187}
193 188
194enum imx233_as_div_t imx233_clkctrl_get_auto_slow_divisor(void) 189unsigned imx233_clkctrl_get_auto_slow_div(void)
195{ 190{
196 return BF_RD(CLKCTRL_HBUS, SLOW_DIV); 191 return BF_RD(CLKCTRL_HBUS, SLOW_DIV);
197} 192}
@@ -206,30 +201,12 @@ bool imx233_clkctrl_is_auto_slow_enabled(void)
206 return BF_RD(CLKCTRL_HBUS, AUTO_SLOW_MODE); 201 return BF_RD(CLKCTRL_HBUS, AUTO_SLOW_MODE);
207} 202}
208 203
209void imx233_clkctrl_enable_auto_slow_monitor(enum imx233_as_monitor_t monitor, bool enable) 204unsigned imx233_clkctrl_get_freq(enum imx233_clock_t clk)
210{
211 if(enable)
212 HW_CLKCTRL_HBUS_SET = monitor;
213 else
214 HW_CLKCTRL_HBUS_CLR = monitor;
215}
216
217bool imx233_clkctrl_is_auto_slow_monitor_enabled(enum imx233_as_monitor_t monitor)
218{
219 return HW_CLKCTRL_HBUS & monitor;
220}
221
222bool imx233_clkctrl_is_emi_sync_enabled(void)
223{
224 return BF_RD(CLKCTRL_EMI, SYNC_MODE_EN);
225}
226
227unsigned imx233_clkctrl_get_clock_freq(enum imx233_clock_t clk)
228{ 205{
229 switch(clk) 206 switch(clk)
230 { 207 {
231 case CLK_PLL: /* PLL: 480MHz when enable */ 208 case CLK_PLL: /* PLL: 480MHz when enable */
232 return imx233_clkctrl_is_clock_enabled(CLK_PLL) ? 480000 : 0; 209 return imx233_clkctrl_is_enabled(CLK_PLL) ? 480000 : 0;
233 case CLK_XTAL: /* crystal: 24MHz */ 210 case CLK_XTAL: /* crystal: 24MHz */
234 return 24000; 211 return 24000;
235 case CLK_CPU: 212 case CLK_CPU:
@@ -238,78 +215,78 @@ unsigned imx233_clkctrl_get_clock_freq(enum imx233_clock_t clk)
238 /* In bypass mode: clk_p derived from clk_xtal via int/binfrac divider 215 /* In bypass mode: clk_p derived from clk_xtal via int/binfrac divider
239 * otherwise, clk_p derived from clk_cpu via int div and clk_cpu 216 * otherwise, clk_p derived from clk_cpu via int div and clk_cpu
240 * derived from clk_pll fracdiv */ 217 * derived from clk_pll fracdiv */
241 if(imx233_clkctrl_get_bypass_pll(CLK_CPU)) 218 if(imx233_clkctrl_get_bypass(CLK_CPU))
242 { 219 {
243 ref = imx233_clkctrl_get_clock_freq(CLK_XTAL); 220 ref = imx233_clkctrl_get_freq(CLK_XTAL);
244 /* Integer divide mode vs fractional divide mode */ 221 /* Integer divide mode vs fractional divide mode */
245 if(BF_RD(CLKCTRL_CPU, DIV_XTAL_FRAC_EN)) 222 if(BF_RD(CLKCTRL_CPU, DIV_XTAL_FRAC_EN))
246 223
247 return (ref * BF_RD(CLKCTRL_CPU, DIV_XTAL)) / 32; 224 return (ref * BF_RD(CLKCTRL_CPU, DIV_XTAL)) / 32;
248 else 225 else
249 return ref / imx233_clkctrl_get_clock_divisor(CLK_CPU); 226 return ref / imx233_clkctrl_get_div(CLK_CPU);
250 } 227 }
251 else 228 else
252 { 229 {
253 ref = imx233_clkctrl_get_clock_freq(CLK_PLL); 230 ref = imx233_clkctrl_get_freq(CLK_PLL);
254 /* fractional divider enable ? */ 231 /* fractional divider enable ? */
255 if(imx233_clkctrl_get_fractional_divisor(CLK_CPU) != 0) 232 if(imx233_clkctrl_get_frac_div(CLK_CPU) != 0)
256 ref = (ref * 18) / imx233_clkctrl_get_fractional_divisor(CLK_CPU); 233 ref = (ref * 18) / imx233_clkctrl_get_frac_div(CLK_CPU);
257 return ref / imx233_clkctrl_get_clock_divisor(CLK_CPU); 234 return ref / imx233_clkctrl_get_div(CLK_CPU);
258 } 235 }
259 } 236 }
260 case CLK_HBUS: 237 case CLK_HBUS:
261 { 238 {
262 /* Derived from clk_p via integer/fractional div */ 239 /* Derived from clk_p via integer/fractional div */
263 unsigned ref = imx233_clkctrl_get_clock_freq(CLK_CPU); 240 unsigned ref = imx233_clkctrl_get_freq(CLK_CPU);
264 if(imx233_clkctrl_get_fractional_divisor(CLK_HBUS) != 0) 241 if(imx233_clkctrl_get_frac_div(CLK_HBUS) != 0)
265 ref = (ref * imx233_clkctrl_get_fractional_divisor(CLK_HBUS)) / 32; 242 ref = (ref * imx233_clkctrl_get_frac_div(CLK_HBUS)) / 32;
266 if(imx233_clkctrl_get_clock_divisor(CLK_HBUS) != 0) 243 if(imx233_clkctrl_get_div(CLK_HBUS) != 0)
267 ref /= imx233_clkctrl_get_clock_divisor(CLK_HBUS); 244 ref /= imx233_clkctrl_get_div(CLK_HBUS);
268 return ref; 245 return ref;
269 } 246 }
270 case CLK_IO: 247 case CLK_IO:
271 { 248 {
272 /* Derived from clk_pll via fracdiv */ 249 /* Derived from clk_pll via fracdiv */
273 unsigned ref = imx233_clkctrl_get_clock_freq(CLK_PLL); 250 unsigned ref = imx233_clkctrl_get_freq(CLK_PLL);
274 if(imx233_clkctrl_get_fractional_divisor(CLK_IO) != 0) 251 if(imx233_clkctrl_get_frac_div(CLK_IO) != 0)
275 ref = (ref * 18) / imx233_clkctrl_get_fractional_divisor(CLK_IO); 252 ref = (ref * 18) / imx233_clkctrl_get_frac_div(CLK_IO);
276 return ref; 253 return ref;
277 } 254 }
278 case CLK_PIX: 255 case CLK_PIX:
279 { 256 {
280 unsigned ref; 257 unsigned ref;
281 /* Derived from clk_pll or clk_xtal */ 258 /* Derived from clk_pll or clk_xtal */
282 if(!imx233_clkctrl_is_clock_enabled(CLK_PIX)) 259 if(!imx233_clkctrl_is_enabled(CLK_PIX))
283 ref = 0; 260 ref = 0;
284 else if(imx233_clkctrl_get_bypass_pll(CLK_PIX)) 261 else if(imx233_clkctrl_get_bypass(CLK_PIX))
285 ref = imx233_clkctrl_get_clock_freq(CLK_XTAL); 262 ref = imx233_clkctrl_get_freq(CLK_XTAL);
286 else 263 else
287 { 264 {
288 ref = imx233_clkctrl_get_clock_freq(CLK_PLL); 265 ref = imx233_clkctrl_get_freq(CLK_PLL);
289 if(imx233_clkctrl_get_fractional_divisor(CLK_PIX) != 0) 266 if(imx233_clkctrl_get_frac_div(CLK_PIX) != 0)
290 ref = (ref * 18) / imx233_clkctrl_get_fractional_divisor(CLK_PIX); 267 ref = (ref * 18) / imx233_clkctrl_get_frac_div(CLK_PIX);
291 } 268 }
292 return ref / imx233_clkctrl_get_clock_divisor(CLK_PIX); 269 return ref / imx233_clkctrl_get_div(CLK_PIX);
293 } 270 }
294 case CLK_SSP: 271 case CLK_SSP:
295 { 272 {
296 unsigned ref; 273 unsigned ref;
297 /* Derived from clk_pll or clk_xtal */ 274 /* Derived from clk_pll or clk_xtal */
298 if(!imx233_clkctrl_is_clock_enabled(CLK_SSP)) 275 if(!imx233_clkctrl_is_enabled(CLK_SSP))
299 ref = 0; 276 ref = 0;
300 else if(imx233_clkctrl_get_bypass_pll(CLK_SSP)) 277 else if(imx233_clkctrl_get_bypass(CLK_SSP))
301 ref = imx233_clkctrl_get_clock_freq(CLK_XTAL); 278 ref = imx233_clkctrl_get_freq(CLK_XTAL);
302 else 279 else
303 ref = imx233_clkctrl_get_clock_freq(CLK_IO); 280 ref = imx233_clkctrl_get_freq(CLK_IO);
304 return ref / imx233_clkctrl_get_clock_divisor(CLK_SSP); 281 return ref / imx233_clkctrl_get_div(CLK_SSP);
305 } 282 }
306 case CLK_EMI: 283 case CLK_EMI:
307 { 284 {
308 unsigned ref; 285 unsigned ref;
309 /* Derived from clk_pll or clk_xtal */ 286 /* Derived from clk_pll or clk_xtal */
310 if(imx233_clkctrl_get_bypass_pll(CLK_EMI)) 287 if(imx233_clkctrl_get_bypass(CLK_EMI))
311 { 288 {
312 ref = imx233_clkctrl_get_clock_freq(CLK_XTAL); 289 ref = imx233_clkctrl_get_freq(CLK_XTAL);
313 if(BF_RD(CLKCTRL_EMI, CLKGATE)) 290 if(BF_RD(CLKCTRL_EMI, CLKGATE))
314 return 0; 291 return 0;
315 else 292 else
@@ -317,16 +294,24 @@ unsigned imx233_clkctrl_get_clock_freq(enum imx233_clock_t clk)
317 } 294 }
318 else 295 else
319 { 296 {
320 ref = imx233_clkctrl_get_clock_freq(CLK_PLL); 297 ref = imx233_clkctrl_get_freq(CLK_PLL);
321 if(imx233_clkctrl_get_fractional_divisor(CLK_EMI) != 0) 298 if(imx233_clkctrl_get_frac_div(CLK_EMI) != 0)
322 ref = (ref * 18) / imx233_clkctrl_get_fractional_divisor(CLK_EMI); 299 ref = (ref * 18) / imx233_clkctrl_get_frac_div(CLK_EMI);
323 return ref / imx233_clkctrl_get_clock_divisor(CLK_EMI); 300 return ref / imx233_clkctrl_get_div(CLK_EMI);
324 } 301 }
325 } 302 }
326 case CLK_XBUS: 303 case CLK_XBUS:
327 return imx233_clkctrl_get_clock_freq(CLK_XTAL) / 304 return imx233_clkctrl_get_freq(CLK_XTAL) / imx233_clkctrl_get_div(CLK_XBUS);
328 imx233_clkctrl_get_clock_divisor(CLK_XBUS);
329 default: 305 default:
330 return 0; 306 return 0;
331 } 307 }
332} 308}
309
310void imx233_clkctrl_init(void)
311{
312 /* set auto-slow monitor to all */
313 HW_CLKCTRL_HBUS_SET = BF_OR8(CLKCTRL_HBUS,
314 APBHDMA_AS_ENABLE(1), TRAFFIC_JAM_AS_ENABLE(1), TRAFFIC_AS_ENABLE(1),
315 APBXDMA_AS_ENABLE(1), CPU_INSTR_AS_ENABLE(1), CPU_DATA_AS_ENABLE(1),
316 DCP_AS_ENABLE(1), PXP_AS_ENABLE(1));
317}