diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-12-03 15:34:40 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-12-03 15:34:40 +0000 |
commit | dd865bcd1ef03b32df1bd65508e991d0ae9e5f63 (patch) | |
tree | 9bf2a25ba8e960f7beb36b24124cce50b6a7dfe8 /firmware | |
parent | 66c53d528f7707b7ce11ba4db56a3085fe7a3d69 (diff) | |
download | rockbox-dd865bcd1ef03b32df1bd65508e991d0ae9e5f63.tar.gz rockbox-dd865bcd1ef03b32df1bd65508e991d0ae9e5f63.zip |
imx233: add control for more clocks, add debug clock debug screen
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31121 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/imx233/clkctrl-imx233.c | 245 | ||||
-rw-r--r-- | firmware/target/arm/imx233/clkctrl-imx233.h | 81 | ||||
-rw-r--r-- | firmware/target/arm/imx233/debug-imx233.c | 122 |
3 files changed, 434 insertions, 14 deletions
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.c b/firmware/target/arm/imx233/clkctrl-imx233.c index 31fccd3e3b..fa94f23a0f 100644 --- a/firmware/target/arm/imx233/clkctrl-imx233.c +++ b/firmware/target/arm/imx233/clkctrl-imx233.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #define __CLK_CLKGATE (1 << 31) | 23 | #define __CLK_CLKGATE (1 << 31) |
24 | #define __CLK_BUSY (1 << 29) | 24 | #define __CLK_BUSY (1 << 29) |
25 | 25 | ||
26 | void imx233_enable_xtal_clock(enum imx233_xtal_clkt_t xtal_clk, bool enable) | 26 | void imx233_enable_xtal_clock(enum imx233_xtal_clk_t xtal_clk, bool enable) |
27 | { | 27 | { |
28 | if(enable) | 28 | if(enable) |
29 | __REG_CLR(HW_CLKCTRL_XTAL) = xtal_clk; | 29 | __REG_CLR(HW_CLKCTRL_XTAL) = xtal_clk; |
@@ -31,6 +31,11 @@ void imx233_enable_xtal_clock(enum imx233_xtal_clkt_t xtal_clk, bool enable) | |||
31 | __REG_SET(HW_CLKCTRL_XTAL) = xtal_clk; | 31 | __REG_SET(HW_CLKCTRL_XTAL) = xtal_clk; |
32 | } | 32 | } |
33 | 33 | ||
34 | bool imx233_is_xtal_clock_enable(enum imx233_xtal_clk_t clk) | ||
35 | { | ||
36 | return HW_CLKCTRL_XTAL & clk; | ||
37 | } | ||
38 | |||
34 | void imx233_enable_clock(enum imx233_clock_t clk, bool enable) | 39 | void imx233_enable_clock(enum imx233_clock_t clk, bool enable) |
35 | { | 40 | { |
36 | volatile uint32_t *REG; | 41 | volatile uint32_t *REG; |
@@ -55,6 +60,20 @@ void imx233_enable_clock(enum imx233_clock_t clk, bool enable) | |||
55 | } | 60 | } |
56 | } | 61 | } |
57 | 62 | ||
63 | bool imx233_is_clock_enable(enum imx233_clock_t clk) | ||
64 | { | ||
65 | volatile uint32_t *REG; | ||
66 | switch(clk) | ||
67 | { | ||
68 | case CLK_PLL: return HW_CLKCTRL_PLLCTRL0 & HW_CLKCTRL_PLLCTRL0__POWER; | ||
69 | case CLK_PIX: REG = &HW_CLKCTRL_PIX; break; | ||
70 | case CLK_SSP: REG = &HW_CLKCTRL_SSP; break; | ||
71 | default: return true; | ||
72 | } | ||
73 | |||
74 | return !((*REG) & __CLK_CLKGATE); | ||
75 | } | ||
76 | |||
58 | void imx233_set_clock_divisor(enum imx233_clock_t clk, int div) | 77 | void imx233_set_clock_divisor(enum imx233_clock_t clk, int div) |
59 | { | 78 | { |
60 | switch(clk) | 79 | switch(clk) |
@@ -74,24 +93,57 @@ void imx233_set_clock_divisor(enum imx233_clock_t clk, int div) | |||
74 | __REG_SET(HW_CLKCTRL_CPU) = div; | 93 | __REG_SET(HW_CLKCTRL_CPU) = div; |
75 | while(HW_CLKCTRL_CPU & HW_CLKCTRL_CPU__BUSY_REF_CPU); | 94 | while(HW_CLKCTRL_CPU & HW_CLKCTRL_CPU__BUSY_REF_CPU); |
76 | break; | 95 | break; |
77 | case CLK_AHB: | 96 | case CLK_EMI: |
78 | __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__DIV_BM; | 97 | __REG_CLR(HW_CLKCTRL_EMI) = HW_CLKCTRL_EMI__DIV_EMI_BM; |
98 | __REG_SET(HW_CLKCTRL_EMI) = div; | ||
99 | while(HW_CLKCTRL_EMI & HW_CLKCTRL_EMI__BUSY_REF_EMI); | ||
100 | break; | ||
101 | case CLK_HBUS: | ||
102 | __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__DIV_BM | HW_CLKCTRL_HBUS__DIV_FRAC_EN; | ||
79 | __REG_SET(HW_CLKCTRL_HBUS) = div; | 103 | __REG_SET(HW_CLKCTRL_HBUS) = div; |
80 | while(HW_CLKCTRL_HBUS & __CLK_BUSY); | 104 | while(HW_CLKCTRL_HBUS & __CLK_BUSY); |
81 | break; | 105 | break; |
106 | case CLK_XBUS: | ||
107 | __REG_CLR(HW_CLKCTRL_XBUS) = HW_CLKCTRL_XBUS__DIV_BM; | ||
108 | __REG_SET(HW_CLKCTRL_XBUS) = div; | ||
109 | while(HW_CLKCTRL_XBUS & __CLK_BUSY); | ||
110 | break; | ||
82 | default: return; | 111 | default: return; |
83 | } | 112 | } |
84 | } | 113 | } |
85 | 114 | ||
115 | int imx233_get_clock_divisor(enum imx233_clock_t clk) | ||
116 | { | ||
117 | switch(clk) | ||
118 | { | ||
119 | case CLK_PIX: return __XTRACT(HW_CLKCTRL_PIX, DIV); | ||
120 | case CLK_SSP: return __XTRACT(HW_CLKCTRL_SSP, DIV); | ||
121 | case CLK_CPU: return __XTRACT(HW_CLKCTRL_CPU, DIV_CPU); | ||
122 | case CLK_EMI: return __XTRACT(HW_CLKCTRL_EMI, DIV_EMI); | ||
123 | case CLK_HBUS: | ||
124 | if(HW_CLKCTRL_HBUS & HW_CLKCTRL_HBUS__DIV_FRAC_EN) | ||
125 | return 0; | ||
126 | else | ||
127 | return __XTRACT(HW_CLKCTRL_HBUS, DIV); | ||
128 | case CLK_XBUS: return __XTRACT(HW_CLKCTRL_XBUS, DIV); | ||
129 | default: return 0; | ||
130 | } | ||
131 | } | ||
132 | |||
86 | void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv) | 133 | void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv) |
87 | { | 134 | { |
88 | /* NOTE: HW_CLKCTRL_FRAC only support byte access ! */ | 135 | /* NOTE: HW_CLKCTRL_FRAC only support byte access ! */ |
89 | volatile uint8_t *REG; | 136 | volatile uint8_t *REG; |
90 | switch(clk) | 137 | switch(clk) |
91 | { | 138 | { |
139 | case CLK_HBUS: | ||
140 | __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__DIV_BM; | ||
141 | __REG_SET(HW_CLKCTRL_HBUS) = fracdiv | HW_CLKCTRL_HBUS__DIV_FRAC_EN; | ||
142 | return; | ||
92 | case CLK_PIX: REG = &HW_CLKCTRL_FRAC_PIX; break; | 143 | case CLK_PIX: REG = &HW_CLKCTRL_FRAC_PIX; break; |
93 | case CLK_IO: REG = &HW_CLKCTRL_FRAC_IO; break; | 144 | case CLK_IO: REG = &HW_CLKCTRL_FRAC_IO; break; |
94 | case CLK_CPU: REG = &HW_CLKCTRL_FRAC_CPU; break; | 145 | case CLK_CPU: REG = &HW_CLKCTRL_FRAC_CPU; break; |
146 | case CLK_EMI: REG = &HW_CLKCTRL_FRAC_EMI; break; | ||
95 | default: return; | 147 | default: return; |
96 | } | 148 | } |
97 | 149 | ||
@@ -101,6 +153,30 @@ void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv) | |||
101 | *REG = HW_CLKCTRL_FRAC_XX__CLKGATEXX;; | 153 | *REG = HW_CLKCTRL_FRAC_XX__CLKGATEXX;; |
102 | } | 154 | } |
103 | 155 | ||
156 | int imx233_get_fractional_divisor(enum imx233_clock_t clk) | ||
157 | { | ||
158 | /* NOTE: HW_CLKCTRL_FRAC only support byte access ! */ | ||
159 | volatile uint8_t *REG; | ||
160 | switch(clk) | ||
161 | { | ||
162 | case CLK_HBUS: | ||
163 | if(HW_CLKCTRL_HBUS & HW_CLKCTRL_HBUS__DIV_FRAC_EN) | ||
164 | return __XTRACT(HW_CLKCTRL_HBUS, DIV); | ||
165 | else | ||
166 | return 0; | ||
167 | case CLK_PIX: REG = &HW_CLKCTRL_FRAC_PIX; break; | ||
168 | case CLK_IO: REG = &HW_CLKCTRL_FRAC_IO; break; | ||
169 | case CLK_CPU: REG = &HW_CLKCTRL_FRAC_CPU; break; | ||
170 | case CLK_EMI: REG = &HW_CLKCTRL_FRAC_EMI; break; | ||
171 | default: return 0; | ||
172 | } | ||
173 | |||
174 | if((*REG) & HW_CLKCTRL_FRAC_XX__CLKGATEXX) | ||
175 | return 0; | ||
176 | else | ||
177 | return *REG & ~HW_CLKCTRL_FRAC_XX__XX_STABLE; | ||
178 | } | ||
179 | |||
104 | void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass) | 180 | void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass) |
105 | { | 181 | { |
106 | uint32_t msk; | 182 | uint32_t msk; |
@@ -109,6 +185,7 @@ void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass) | |||
109 | case CLK_PIX: msk = HW_CLKCTRL_CLKSEQ__BYPASS_PIX; break; | 185 | case CLK_PIX: msk = HW_CLKCTRL_CLKSEQ__BYPASS_PIX; break; |
110 | case CLK_SSP: msk = HW_CLKCTRL_CLKSEQ__BYPASS_SSP; break; | 186 | case CLK_SSP: msk = HW_CLKCTRL_CLKSEQ__BYPASS_SSP; break; |
111 | case CLK_CPU: msk = HW_CLKCTRL_CLKSEQ__BYPASS_CPU; break; | 187 | case CLK_CPU: msk = HW_CLKCTRL_CLKSEQ__BYPASS_CPU; break; |
188 | case CLK_EMI: msk = HW_CLKCTRL_CLKSEQ__BYPASS_EMI; break; | ||
112 | default: return; | 189 | default: return; |
113 | } | 190 | } |
114 | 191 | ||
@@ -118,6 +195,21 @@ void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass) | |||
118 | __REG_CLR(HW_CLKCTRL_CLKSEQ) = msk; | 195 | __REG_CLR(HW_CLKCTRL_CLKSEQ) = msk; |
119 | } | 196 | } |
120 | 197 | ||
198 | bool imx233_get_bypass_pll(enum imx233_clock_t clk) | ||
199 | { | ||
200 | uint32_t msk; | ||
201 | switch(clk) | ||
202 | { | ||
203 | case CLK_PIX: msk = HW_CLKCTRL_CLKSEQ__BYPASS_PIX; break; | ||
204 | case CLK_SSP: msk = HW_CLKCTRL_CLKSEQ__BYPASS_SSP; break; | ||
205 | case CLK_CPU: msk = HW_CLKCTRL_CLKSEQ__BYPASS_CPU; break; | ||
206 | case CLK_EMI: msk = HW_CLKCTRL_CLKSEQ__BYPASS_EMI; break; | ||
207 | default: return false; | ||
208 | } | ||
209 | |||
210 | return HW_CLKCTRL_CLKSEQ & msk; | ||
211 | } | ||
212 | |||
121 | void imx233_enable_usb_pll(bool enable) | 213 | void imx233_enable_usb_pll(bool enable) |
122 | { | 214 | { |
123 | if(enable) | 215 | if(enable) |
@@ -126,3 +218,150 @@ void imx233_enable_usb_pll(bool enable) | |||
126 | __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; | 218 | __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; |
127 | } | 219 | } |
128 | 220 | ||
221 | bool imx233_is_usb_pll_enable(void) | ||
222 | { | ||
223 | return HW_CLKCTRL_PLLCTRL0 & HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; | ||
224 | } | ||
225 | |||
226 | void imx233_set_auto_slow_divisor(enum imx233_as_div_t div) | ||
227 | { | ||
228 | __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__SLOW_DIV_BM; | ||
229 | __REG_SET(HW_CLKCTRL_HBUS) = div; | ||
230 | } | ||
231 | |||
232 | enum imx233_as_div_t imx233_get_auto_slow_divisor(void) | ||
233 | { | ||
234 | return __XTRACT(HW_CLKCTRL_HBUS, SLOW_DIV); | ||
235 | } | ||
236 | |||
237 | void imx233_enable_auto_slow(bool enable) | ||
238 | { | ||
239 | if(enable) | ||
240 | __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__AUTO_SLOW_MODE; | ||
241 | else | ||
242 | __REG_SET(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__AUTO_SLOW_MODE; | ||
243 | } | ||
244 | |||
245 | bool imx233_is_auto_slow_enable(void) | ||
246 | { | ||
247 | return HW_CLKCTRL_HBUS & HW_CLKCTRL_HBUS__AUTO_SLOW_MODE; | ||
248 | } | ||
249 | |||
250 | void imx233_enable_auto_slow_monitor(enum imx233_as_monitor_t monitor, bool enable) | ||
251 | { | ||
252 | if(enable) | ||
253 | __REG_SET(HW_CLKCTRL_HBUS) = monitor; | ||
254 | else | ||
255 | __REG_CLR(HW_CLKCTRL_HBUS) = monitor; | ||
256 | } | ||
257 | |||
258 | bool imx233_is_auto_slow_monitor_enable(enum imx233_as_monitor_t monitor) | ||
259 | { | ||
260 | return HW_CLKCTRL_HBUS & monitor; | ||
261 | } | ||
262 | |||
263 | unsigned imx233_get_clock_freq(enum imx233_clock_t clk) | ||
264 | { | ||
265 | switch(clk) | ||
266 | { | ||
267 | case CLK_PLL: /* PLL: 480MHz when enable */ | ||
268 | return imx233_is_clock_enable(CLK_PLL) ? 480000 : 0; | ||
269 | case CLK_XTAL: /* crytsal: 24MHz */ | ||
270 | return 24000; | ||
271 | case CLK_CPU: | ||
272 | { | ||
273 | unsigned ref; | ||
274 | /* In bypass mode: clk_p derived from clk_xtal via int/binfrac divider | ||
275 | * otherwise, clk_p derived from clk_cpu via int div and clk_cpu | ||
276 | * derived from clk_pll fracdiv */ | ||
277 | if(imx233_get_bypass_pll(CLK_CPU)) | ||
278 | { | ||
279 | ref = imx233_get_clock_freq(CLK_XTAL); | ||
280 | /* Integer divide mode vs fractional divide mode */ | ||
281 | if(HW_CLKCTRL_CPU & HW_CLKCTRL_CPU__DIV_XTAL_FRAC_EN) | ||
282 | |||
283 | return (ref * __XTRACT(HW_CLKCTRL_CPU, DIV_XTAL)) / 32; | ||
284 | else | ||
285 | return ref / imx233_get_clock_divisor(CLK_CPU); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | ref = imx233_get_clock_freq(CLK_PLL); | ||
290 | /* fractional divider enable ? */ | ||
291 | if(imx233_get_fractional_divisor(CLK_CPU) != 0) | ||
292 | ref = (ref * 18) / imx233_get_fractional_divisor(CLK_CPU); | ||
293 | return ref / imx233_get_clock_divisor(CLK_CPU); | ||
294 | } | ||
295 | } | ||
296 | case CLK_HBUS: | ||
297 | { | ||
298 | /* Derived from clk_p via integer/fractional div */ | ||
299 | unsigned ref = imx233_get_clock_freq(CLK_CPU); | ||
300 | if(imx233_get_fractional_divisor(CLK_HBUS) != 0) | ||
301 | ref = (ref * imx233_get_fractional_divisor(CLK_HBUS)) / 32; | ||
302 | if(imx233_get_clock_divisor(CLK_HBUS) != 0) | ||
303 | ref /= imx233_get_clock_divisor(CLK_HBUS); | ||
304 | return ref; | ||
305 | } | ||
306 | case CLK_IO: | ||
307 | { | ||
308 | /* Derived from clk_pll via fracdiv */ | ||
309 | unsigned ref = imx233_get_clock_freq(CLK_PLL); | ||
310 | if(imx233_get_fractional_divisor(CLK_IO) != 0) | ||
311 | ref = (ref * 18) / imx233_get_fractional_divisor(CLK_IO); | ||
312 | return ref; | ||
313 | } | ||
314 | case CLK_PIX: | ||
315 | { | ||
316 | unsigned ref; | ||
317 | /* Derived from clk_pll or clk_xtal */ | ||
318 | if(!imx233_is_clock_enable(CLK_PIX)) | ||
319 | ref = 0; | ||
320 | else if(imx233_get_bypass_pll(CLK_PIX)) | ||
321 | ref = imx233_get_clock_freq(CLK_XTAL); | ||
322 | else | ||
323 | { | ||
324 | ref = imx233_get_clock_freq(CLK_PLL); | ||
325 | if(imx233_get_fractional_divisor(CLK_PIX) != 0) | ||
326 | ref = (ref * 18) / imx233_get_fractional_divisor(CLK_PIX); | ||
327 | } | ||
328 | return ref / imx233_get_clock_divisor(CLK_PIX); | ||
329 | } | ||
330 | case CLK_SSP: | ||
331 | { | ||
332 | unsigned ref; | ||
333 | /* Derived from clk_pll or clk_xtal */ | ||
334 | if(!imx233_is_clock_enable(CLK_SSP)) | ||
335 | ref = 0; | ||
336 | else if(imx233_get_bypass_pll(CLK_SSP)) | ||
337 | ref = imx233_get_clock_freq(CLK_XTAL); | ||
338 | else | ||
339 | ref = imx233_get_clock_freq(CLK_IO); | ||
340 | return ref / imx233_get_clock_divisor(CLK_SSP); | ||
341 | } | ||
342 | case CLK_EMI: | ||
343 | { | ||
344 | unsigned ref; | ||
345 | /* Derived from clk_pll or clk_xtal */ | ||
346 | if(imx233_get_bypass_pll(CLK_EMI)) | ||
347 | { | ||
348 | ref = imx233_get_clock_freq(CLK_XTAL); | ||
349 | if(HW_CLKCTRL_EMI & HW_CLKCTRL_EMI__CLKGATE) | ||
350 | return 0; | ||
351 | else | ||
352 | return ref / __XTRACT(HW_CLKCTRL_EMI, DIV_XTAL); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | ref = imx233_get_clock_freq(CLK_PLL); | ||
357 | if(imx233_get_fractional_divisor(CLK_EMI) != 0) | ||
358 | ref = (ref * 18) / imx233_get_fractional_divisor(CLK_EMI); | ||
359 | return ref / imx233_get_clock_divisor(CLK_EMI); | ||
360 | } | ||
361 | } | ||
362 | case CLK_XBUS: | ||
363 | return imx233_get_clock_freq(CLK_XTAL) / imx233_get_clock_divisor(CLK_XBUS); | ||
364 | default: | ||
365 | return 0; | ||
366 | } | ||
367 | } | ||
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.h b/firmware/target/arm/imx233/clkctrl-imx233.h index e59f954071..fc835c813a 100644 --- a/firmware/target/arm/imx233/clkctrl-imx233.h +++ b/firmware/target/arm/imx233/clkctrl-imx233.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define HW_CLKCTRL_BASE 0x80040000 | 28 | #define HW_CLKCTRL_BASE 0x80040000 |
29 | 29 | ||
30 | #define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0)) | 30 | #define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0)) |
31 | #define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16) | ||
31 | #define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18) | 32 | #define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18) |
32 | #define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BP 20 | 33 | #define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BP 20 |
33 | #define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BM (3 << 20) | 34 | #define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BM (3 << 20) |
@@ -37,11 +38,19 @@ | |||
37 | #define HW_CLKCTRL_CPU (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20)) | 38 | #define HW_CLKCTRL_CPU (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20)) |
38 | #define HW_CLKCTRL_CPU__DIV_CPU_BP 0 | 39 | #define HW_CLKCTRL_CPU__DIV_CPU_BP 0 |
39 | #define HW_CLKCTRL_CPU__DIV_CPU_BM 0x3f | 40 | #define HW_CLKCTRL_CPU__DIV_CPU_BM 0x3f |
41 | #define HW_CLKCTRL_CPU__INTERRUPT_WAIT (1 << 12) | ||
42 | #define HW_CLKCTRL_CPU__DIV_XTAL_BP 16 | ||
43 | #define HW_CLKCTRL_CPU__DIV_XTAL_BM (0x3ff << 16) | ||
44 | #define HW_CLKCTRL_CPU__DIV_XTAL_FRAC_EN (1 << 26) | ||
40 | #define HW_CLKCTRL_CPU__BUSY_REF_CPU (1 << 28) | 45 | #define HW_CLKCTRL_CPU__BUSY_REF_CPU (1 << 28) |
41 | 46 | ||
42 | #define HW_CLKCTRL_HBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30)) | 47 | #define HW_CLKCTRL_HBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30)) |
43 | #define HW_CLKCTRL_HBUS__DIV_BP 0 | 48 | #define HW_CLKCTRL_HBUS__DIV_BP 0 |
44 | #define HW_CLKCTRL_HBUS__DIV_BM 0x1f | 49 | #define HW_CLKCTRL_HBUS__DIV_BM 0x1f |
50 | #define HW_CLKCTRL_HBUS__DIV_FRAC_EN (1 << 5) | ||
51 | #define HW_CLKCTRL_HBUS__SLOW_DIV_BP 16 | ||
52 | #define HW_CLKCTRL_HBUS__SLOW_DIV_BM (0x7 << 16) | ||
53 | #define HW_CLKCTRL_HBUS__AUTO_SLOW_MODE (1 << 20) | ||
45 | 54 | ||
46 | #define HW_CLKCTRL_XBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40)) | 55 | #define HW_CLKCTRL_XBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40)) |
47 | #define HW_CLKCTRL_XBUS__DIV_BP 0 | 56 | #define HW_CLKCTRL_XBUS__DIV_BP 0 |
@@ -54,14 +63,26 @@ | |||
54 | #define HW_CLKCTRL_XTAL__FILT_CLK24M_GATE (1 << 30) | 63 | #define HW_CLKCTRL_XTAL__FILT_CLK24M_GATE (1 << 30) |
55 | 64 | ||
56 | #define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60)) | 65 | #define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60)) |
66 | #define HW_CLKCTRL_PIX__DIV_BP 0 | ||
57 | #define HW_CLKCTRL_PIX__DIV_BM 0xfff | 67 | #define HW_CLKCTRL_PIX__DIV_BM 0xfff |
58 | 68 | ||
59 | #define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70)) | 69 | #define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70)) |
70 | #define HW_CLKCTRL_SSP__DIV_BP 0 | ||
60 | #define HW_CLKCTRL_SSP__DIV_BM 0x1ff | 71 | #define HW_CLKCTRL_SSP__DIV_BM 0x1ff |
61 | 72 | ||
73 | #define HW_CLKCTRL_EMI (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xa0)) | ||
74 | #define HW_CLKCTRL_EMI__DIV_EMI_BP 0 | ||
75 | #define HW_CLKCTRL_EMI__DIV_EMI_BM 0x3f | ||
76 | #define HW_CLKCTRL_EMI__DIV_XTAL_BP 8 | ||
77 | #define HW_CLKCTRL_EMI__DIV_XTAL_BM (0xf << 8) | ||
78 | #define HW_CLKCTRL_EMI__BUSY_REF_EMI (1 << 28) | ||
79 | #define HW_CLKCTRL_EMI__SYNC_MODE_EN (1 << 30) | ||
80 | #define HW_CLKCTRL_EMI__CLKGATE (1 << 31) | ||
81 | |||
62 | #define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110)) | 82 | #define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110)) |
63 | #define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1) | 83 | #define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1) |
64 | #define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5) | 84 | #define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5) |
85 | #define HW_CLKCTRL_CLKSEQ__BYPASS_EMI (1 << 6) | ||
65 | #define HW_CLKCTRL_CLKSEQ__BYPASS_CPU (1 << 7) | 86 | #define HW_CLKCTRL_CLKSEQ__BYPASS_CPU (1 << 7) |
66 | 87 | ||
67 | #define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0)) | 88 | #define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0)) |
@@ -79,28 +100,70 @@ | |||
79 | 100 | ||
80 | enum imx233_clock_t | 101 | enum imx233_clock_t |
81 | { | 102 | { |
82 | CLK_PIX, /* div, frac */ | 103 | CLK_PIX, /* freq, div, frac, bypass, enable */ |
83 | CLK_SSP, /* div, frac */ | 104 | CLK_SSP, /* freq, div, bypass, enable */ |
84 | CLK_IO, /* div */ | 105 | CLK_IO, /* freq, frac */ |
85 | CLK_CPU, /* div, frac */ | 106 | CLK_CPU, /* freq, div, frac, bypass */ |
86 | CLK_AHB /* div */ | 107 | CLK_HBUS, /* freq, div, frac */ |
108 | CLK_PLL, /* freq */ | ||
109 | CLK_XTAL, /* freq */ | ||
110 | CLK_EMI, /* freq */ | ||
111 | CLK_XBUS, /* freq, div */ | ||
87 | }; | 112 | }; |
88 | 113 | ||
89 | enum imx233_xtal_clkt_t | 114 | enum imx233_xtal_clk_t |
90 | { | 115 | { |
91 | XTAL_FILT = 1 << 30, | 116 | XTAL_FILT = 1 << 30, |
92 | XTAL_DRI = 1 << 28, | 117 | XTAL_DRI = 1 << 28, |
93 | XTAL_TIMROT = 1 << 26, | 118 | XTAL_TIMROT = 1 << 26, |
94 | }; | 119 | }; |
95 | 120 | ||
121 | /* Auto-Slow monitoring */ | ||
122 | enum imx233_as_monitor_t | ||
123 | { | ||
124 | AS_CPU_INSTR = 1 << 21, /* Monitor CPU instruction access to AHB */ | ||
125 | AS_CPU_DATA = 1 << 22, /* Monitor CPU data access to AHB */ | ||
126 | AS_TRAFFIC = 1 << 23, /* Monitor AHB master activity */ | ||
127 | AS_TRAFFIC_JAM = 1 << 24, /* Monitor AHB masters (>=3) activity */ | ||
128 | AS_APBXDMA = 1 << 25, /* Monitor APBX DMA activity */ | ||
129 | AS_APBHDMA = 1 << 26, /* Monitor APBH DMA activity */ | ||
130 | AS_PXP = 1 << 27, /* Monitor PXP activity */ | ||
131 | AS_DCP = 1 << 28, /* Monitor DCP activity */ | ||
132 | }; | ||
133 | |||
134 | enum imx233_as_div_t | ||
135 | { | ||
136 | AS_DIV_1 = 0, | ||
137 | AS_DIV_2 = 1, | ||
138 | AS_DIV_4 = 2, | ||
139 | AS_DIV_8 = 3, | ||
140 | AS_DIV_16 = 4, | ||
141 | AS_DIV_32 = 5 | ||
142 | }; | ||
143 | |||
96 | /* can use a mask of clocks */ | 144 | /* can use a mask of clocks */ |
97 | void imx233_enable_xtal_clock(enum imx233_xtal_clkt_t xtal_clk, bool enable); | 145 | void imx233_enable_xtal_clock(enum imx233_xtal_clk_t xtal_clk, bool enable); |
146 | bool imx233_is_xtal_clock_enable(enum imx233_xtal_clk_t clk); | ||
98 | /* only use it for non-fractional clocks (ie not for IO) */ | 147 | /* only use it for non-fractional clocks (ie not for IO) */ |
99 | void imx233_enable_clock(enum imx233_clock_t clk, bool enable); | 148 | void imx233_enable_clock(enum imx233_clock_t clk, bool enable); |
149 | bool imx233_is_clock_enable(enum imx233_clock_t cl); | ||
100 | void imx233_set_clock_divisor(enum imx233_clock_t clk, int div); | 150 | void imx233_set_clock_divisor(enum imx233_clock_t clk, int div); |
151 | int imx233_get_clock_divisor(enum imx233_clock_t clk); | ||
101 | /* call with fracdiv=0 to disable it */ | 152 | /* call with fracdiv=0 to disable it */ |
102 | void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv); | 153 | void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv); |
154 | /* 0 means fractional dividor disable */ | ||
155 | int imx233_get_fractional_divisor(enum imx233_clock_t clk); | ||
103 | void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass); | 156 | void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass); |
157 | bool imx233_get_bypass_pll(enum imx233_clock_t clk); | ||
104 | void imx233_enable_usb_pll(bool enable); | 158 | void imx233_enable_usb_pll(bool enable); |
159 | bool imx233_is_usb_pll_enable(void); | ||
160 | unsigned imx233_get_clock_freq(enum imx233_clock_t clk); | ||
161 | |||
162 | void imx233_set_auto_slow_divisor(enum imx233_as_div_t div); | ||
163 | enum imx233_as_div_t imx233_get_auto_slow_divisor(void); | ||
164 | void imx233_enable_auto_slow(bool enable); | ||
165 | bool imx233_is_auto_slow_enable(void); | ||
166 | void imx233_enable_auto_slow_monitor(enum imx233_as_monitor_t monitor, bool enable); | ||
167 | bool imx233_is_auto_slow_monitor_enable(enum imx233_as_monitor_t monitor); | ||
105 | 168 | ||
106 | #endif /* CLKCTRL_IMX233_H */ | 169 | #endif /* CLKCTRL_IMX233_H */ |
diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c index 7eacbf7523..e6b07aef58 100644 --- a/firmware/target/arm/imx233/debug-imx233.c +++ b/firmware/target/arm/imx233/debug-imx233.c | |||
@@ -28,7 +28,9 @@ | |||
28 | #include "adc.h" | 28 | #include "adc.h" |
29 | #include "adc-imx233.h" | 29 | #include "adc-imx233.h" |
30 | #include "power-imx233.h" | 30 | #include "power-imx233.h" |
31 | #include "clkctrl-imx233.h" | ||
31 | #include "powermgmt.h" | 32 | #include "powermgmt.h" |
33 | #include "string.h" | ||
32 | 34 | ||
33 | static struct | 35 | static struct |
34 | { | 36 | { |
@@ -88,7 +90,7 @@ bool dbg_hw_info_power(void) | |||
88 | 90 | ||
89 | while(1) | 91 | while(1) |
90 | { | 92 | { |
91 | int button = get_action(CONTEXT_STD, HZ / 25); | 93 | int button = get_action(CONTEXT_STD, HZ / 10); |
92 | switch(button) | 94 | switch(button) |
93 | { | 95 | { |
94 | case ACTION_STD_NEXT: | 96 | case ACTION_STD_NEXT: |
@@ -151,9 +153,125 @@ bool dbg_hw_info_adc(void) | |||
151 | } | 153 | } |
152 | } | 154 | } |
153 | 155 | ||
156 | static struct | ||
157 | { | ||
158 | enum imx233_clock_t clk; | ||
159 | const char *name; | ||
160 | bool has_enable; | ||
161 | bool has_bypass; | ||
162 | bool has_idiv; | ||
163 | bool has_fdiv; | ||
164 | bool has_freq; | ||
165 | } dbg_clk[] = | ||
166 | { | ||
167 | { CLK_PLL, "pll", true, false, false, false, true}, | ||
168 | { CLK_XTAL, "xtal", false, false, false, false, true}, | ||
169 | { CLK_PIX, "pix", true, true, true, true, true }, | ||
170 | { CLK_SSP, "ssp", true, true, true, false, true }, | ||
171 | { CLK_IO, "io", false, false, false, true, true }, | ||
172 | { CLK_CPU, "cpu", false, true, true, true, true }, | ||
173 | { CLK_HBUS, "hbus", false, false, true, true, true }, | ||
174 | { CLK_EMI, "emi", false, true, true, true, true }, | ||
175 | { CLK_XBUS, "xbus", false, false, true, false, true } | ||
176 | }; | ||
177 | |||
178 | static struct | ||
179 | { | ||
180 | enum imx233_as_monitor_t monitor; | ||
181 | const char *name; | ||
182 | } dbg_as_monitor[] = | ||
183 | { | ||
184 | { AS_CPU_INSTR, "cpu inst" }, | ||
185 | { AS_CPU_DATA, "cpu data" }, | ||
186 | { AS_TRAFFIC, "traffic" }, | ||
187 | { AS_TRAFFIC_JAM, "traffic jam" }, | ||
188 | { AS_APBXDMA, "apbx" }, | ||
189 | { AS_APBHDMA, "apbh" }, | ||
190 | { AS_PXP, "pxp" }, | ||
191 | { AS_DCP, "dcp" } | ||
192 | }; | ||
193 | |||
194 | bool dbg_hw_info_clkctrl(void) | ||
195 | { | ||
196 | lcd_setfont(FONT_SYSFIXED); | ||
197 | imx233_enable_auto_slow_monitor(AS_CPU_INSTR, true); | ||
198 | imx233_enable_auto_slow_monitor(AS_CPU_DATA, true); | ||
199 | imx233_enable_auto_slow_monitor(AS_TRAFFIC, true); | ||
200 | imx233_enable_auto_slow_monitor(AS_TRAFFIC_JAM, true); | ||
201 | imx233_enable_auto_slow_monitor(AS_APBXDMA, true); | ||
202 | imx233_enable_auto_slow_monitor(AS_APBHDMA, true); | ||
203 | |||
204 | while(1) | ||
205 | { | ||
206 | int button = get_action(CONTEXT_STD, HZ / 10); | ||
207 | switch(button) | ||
208 | { | ||
209 | case ACTION_STD_NEXT: | ||
210 | case ACTION_STD_PREV: | ||
211 | case ACTION_STD_OK: | ||
212 | case ACTION_STD_MENU: | ||
213 | lcd_setfont(FONT_UI); | ||
214 | return true; | ||
215 | case ACTION_STD_CANCEL: | ||
216 | lcd_setfont(FONT_UI); | ||
217 | return false; | ||
218 | } | ||
219 | |||
220 | lcd_clear_display(); | ||
221 | |||
222 | /* 012345678901234567890123456789 */ | ||
223 | lcd_putsf(0, 0, "name en by idiv fdiv frequency"); | ||
224 | for(unsigned i = 0; i < ARRAYLEN(dbg_clk); i++) | ||
225 | { | ||
226 | #define c dbg_clk[i] | ||
227 | lcd_putsf(0, i + 1, "%4s", c.name); | ||
228 | if(c.has_enable) | ||
229 | lcd_putsf(5, i + 1, "%2d", imx233_is_clock_enable(c.clk)); | ||
230 | if(c.has_bypass) | ||
231 | lcd_putsf(8, i + 1, "%2d", imx233_get_bypass_pll(c.clk)); | ||
232 | if(c.has_idiv && imx233_get_clock_divisor(c.clk) != 0) | ||
233 | lcd_putsf(10, i + 1, "%4d", imx233_get_clock_divisor(c.clk)); | ||
234 | if(c.has_fdiv && imx233_get_fractional_divisor(c.clk) != 0) | ||
235 | lcd_putsf(16, i + 1, "%4d", imx233_get_fractional_divisor(c.clk)); | ||
236 | if(c.has_freq) | ||
237 | lcd_putsf(21, i + 1, "%9d", imx233_get_clock_freq(c.clk)); | ||
238 | #undef c | ||
239 | } | ||
240 | int line = ARRAYLEN(dbg_clk) + 1; | ||
241 | lcd_putsf(0, line, "auto slow: %d", imx233_is_auto_slow_enable()); | ||
242 | line++; | ||
243 | lcd_putsf(0, line, "as monitor: "); | ||
244 | int x_off = 12; | ||
245 | bool first = true; | ||
246 | unsigned line_w = lcd_getwidth() / font_get_width(font_get(lcd_getfont()), ' '); | ||
247 | for(unsigned i = 0; i < ARRAYLEN(dbg_as_monitor); i++) | ||
248 | { | ||
249 | if(!imx233_is_auto_slow_monitor_enable(dbg_as_monitor[i].monitor)) | ||
250 | continue; | ||
251 | if(!first) | ||
252 | { | ||
253 | lcd_putsf(x_off, line, ", "); | ||
254 | x_off += 2; | ||
255 | } | ||
256 | first = false; | ||
257 | if((x_off + strlen(dbg_as_monitor[i].name)) > line_w) | ||
258 | { | ||
259 | x_off = 1; | ||
260 | line++; | ||
261 | } | ||
262 | lcd_putsf(x_off, line, "%s", dbg_as_monitor[i].name); | ||
263 | x_off += strlen(dbg_as_monitor[i].name); | ||
264 | } | ||
265 | line++; | ||
266 | |||
267 | lcd_update(); | ||
268 | yield(); | ||
269 | } | ||
270 | } | ||
271 | |||
154 | bool dbg_hw_info(void) | 272 | bool dbg_hw_info(void) |
155 | { | 273 | { |
156 | return dbg_hw_info_dma() && dbg_hw_info_adc() && dbg_hw_info_power() && | 274 | return dbg_hw_info_clkctrl() && dbg_hw_info_dma() && dbg_hw_info_adc() && dbg_hw_info_power() && |
157 | dbg_hw_target_info(); | 275 | dbg_hw_target_info(); |
158 | } | 276 | } |
159 | 277 | ||