summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.c245
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.h81
-rw-r--r--firmware/target/arm/imx233/debug-imx233.c122
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
26void imx233_enable_xtal_clock(enum imx233_xtal_clkt_t xtal_clk, bool enable) 26void 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
34bool imx233_is_xtal_clock_enable(enum imx233_xtal_clk_t clk)
35{
36 return HW_CLKCTRL_XTAL & clk;
37}
38
34void imx233_enable_clock(enum imx233_clock_t clk, bool enable) 39void 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
63bool 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
58void imx233_set_clock_divisor(enum imx233_clock_t clk, int div) 77void 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
115int 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
86void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv) 133void 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
156int 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
104void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass) 180void 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
198bool 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
121void imx233_enable_usb_pll(bool enable) 213void 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
221bool imx233_is_usb_pll_enable(void)
222{
223 return HW_CLKCTRL_PLLCTRL0 & HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
224}
225
226void 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
232enum imx233_as_div_t imx233_get_auto_slow_divisor(void)
233{
234 return __XTRACT(HW_CLKCTRL_HBUS, SLOW_DIV);
235}
236
237void 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
245bool imx233_is_auto_slow_enable(void)
246{
247 return HW_CLKCTRL_HBUS & HW_CLKCTRL_HBUS__AUTO_SLOW_MODE;
248}
249
250void 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
258bool imx233_is_auto_slow_monitor_enable(enum imx233_as_monitor_t monitor)
259{
260 return HW_CLKCTRL_HBUS & monitor;
261}
262
263unsigned 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
80enum imx233_clock_t 101enum 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
89enum imx233_xtal_clkt_t 114enum 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 */
122enum 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
134enum 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 */
97void imx233_enable_xtal_clock(enum imx233_xtal_clkt_t xtal_clk, bool enable); 145void imx233_enable_xtal_clock(enum imx233_xtal_clk_t xtal_clk, bool enable);
146bool 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) */
99void imx233_enable_clock(enum imx233_clock_t clk, bool enable); 148void imx233_enable_clock(enum imx233_clock_t clk, bool enable);
149bool imx233_is_clock_enable(enum imx233_clock_t cl);
100void imx233_set_clock_divisor(enum imx233_clock_t clk, int div); 150void imx233_set_clock_divisor(enum imx233_clock_t clk, int div);
151int 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 */
102void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv); 153void imx233_set_fractional_divisor(enum imx233_clock_t clk, int fracdiv);
154/* 0 means fractional dividor disable */
155int imx233_get_fractional_divisor(enum imx233_clock_t clk);
103void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass); 156void imx233_set_bypass_pll(enum imx233_clock_t clk, bool bypass);
157bool imx233_get_bypass_pll(enum imx233_clock_t clk);
104void imx233_enable_usb_pll(bool enable); 158void imx233_enable_usb_pll(bool enable);
159bool imx233_is_usb_pll_enable(void);
160unsigned imx233_get_clock_freq(enum imx233_clock_t clk);
161
162void imx233_set_auto_slow_divisor(enum imx233_as_div_t div);
163enum imx233_as_div_t imx233_get_auto_slow_divisor(void);
164void imx233_enable_auto_slow(bool enable);
165bool imx233_is_auto_slow_enable(void);
166void imx233_enable_auto_slow_monitor(enum imx233_as_monitor_t monitor, bool enable);
167bool 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
33static struct 35static 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
156static 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
178static 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
194bool 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
154bool dbg_hw_info(void) 272bool 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