diff options
Diffstat (limited to 'firmware/target/arm/imx233/clkctrl-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/clkctrl-imx233.c | 151 |
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) | 23 | void imx233_clkctrl_enable(enum imx233_clock_t clk, bool enable) |
24 | #define __CLK_BUSY (1 << 29) | ||
25 | |||
26 | void 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 | |||
34 | bool imx233_clkctrl_is_xtal_enable(enum imx233_xtal_clk_t clk) | ||
35 | { | ||
36 | return HW_CLKCTRL_XTAL & clk; | ||
37 | } | ||
38 | |||
39 | void 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 | ||
61 | bool imx233_clkctrl_is_clock_enabled(enum imx233_clock_t clk) | 51 | bool 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 | ||
72 | void imx233_clkctrl_set_clock_divisor(enum imx233_clock_t clk, int div) | 67 | void 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 | ||
88 | int imx233_clkctrl_get_clock_divisor(enum imx233_clock_t clk) | 83 | int 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 | ||
102 | void imx233_clkctrl_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv) | 97 | void 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 | ||
123 | int imx233_clkctrl_get_fractional_divisor(enum imx233_clock_t clk) | 118 | int 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 | ||
142 | void imx233_clkctrl_set_bypass_pll(enum imx233_clock_t clk, bool bypass) | 137 | void 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 | ||
160 | bool imx233_clkctrl_get_bypass_pll(enum imx233_clock_t clk) | 155 | bool 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 | ||
172 | void imx233_clkctrl_enable_usb_pll(bool enable) | 167 | void 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 | ||
180 | bool imx233_clkctrl_is_usb_pll_enabled(void) | 175 | bool 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 | ||
185 | void imx233_clkctrl_set_auto_slow_divisor(enum imx233_as_div_t div) | 180 | void 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 | ||
194 | enum imx233_as_div_t imx233_clkctrl_get_auto_slow_divisor(void) | 189 | unsigned 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 | ||
209 | void imx233_clkctrl_enable_auto_slow_monitor(enum imx233_as_monitor_t monitor, bool enable) | 204 | unsigned 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 | |||
217 | bool imx233_clkctrl_is_auto_slow_monitor_enabled(enum imx233_as_monitor_t monitor) | ||
218 | { | ||
219 | return HW_CLKCTRL_HBUS & monitor; | ||
220 | } | ||
221 | |||
222 | bool imx233_clkctrl_is_emi_sync_enabled(void) | ||
223 | { | ||
224 | return BF_RD(CLKCTRL_EMI, SYNC_MODE_EN); | ||
225 | } | ||
226 | |||
227 | unsigned 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 | |||
310 | void 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 | } | ||