i.MX31: Add a debug menu to play around with DVFS/DPTC settings for fun, testing...
[kugel-rb.git] / firmware / target / arm / imx31 / debug-imx31.c
blobf8dacbedd5894801790ccb2ba481cd85cbf87774
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Michael Sevakis
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 ****************************************************************************/
21 #include "config.h"
22 #include "system.h"
23 #include "string.h"
24 #include "button.h"
25 #include "lcd.h"
26 #include "font.h"
27 #include "debug-target.h"
28 #include "mc13783.h"
29 #include "adc.h"
30 #include "ccm-imx31.h"
31 #include "dvfs_dptc-imx31.h"
32 #include <stdio.h>
34 bool __dbg_hw_info(void)
36 int line;
37 unsigned int pllref;
38 unsigned int mcu_pllfreq, ser_pllfreq, usb_pllfreq;
39 uint32_t mpctl, spctl, upctl;
40 unsigned int freq;
41 uint32_t regval;
43 extern volatile unsigned int dvfs_nr_dn, dvfs_nr_up,
44 dvfs_nr_pnc, dvfs_nr_no;
45 extern volatile unsigned int dptc_nr_dn, dptc_nr_up,
46 dptc_nr_pnc, dptc_nr_no;
48 lcd_clear_display();
49 lcd_setfont(FONT_SYSFIXED);
51 while (1)
53 line = 0;
54 lcd_putsf(0, line++, "Sys Rev Code: 0x%02X", iim_system_rev());
55 line++;
57 mpctl = CCM_MPCTL;
58 spctl = CCM_SPCTL;
59 upctl = CCM_UPCTL;
61 pllref = ccm_get_pll_ref_clk_rate();
63 mcu_pllfreq = ccm_calc_pll_rate(pllref, mpctl);
64 ser_pllfreq = ccm_calc_pll_rate(pllref, spctl);
65 usb_pllfreq = ccm_calc_pll_rate(pllref, upctl);
67 lcd_putsf(0, line++, "pll_ref_clk: %u", pllref);
68 line++;
70 /* MCU clock domain */
71 lcd_putsf(0, line++, "MPCTL: %08lX", mpctl);
73 lcd_putsf(0, line++, " mpl_dpdgck_clk: %u", mcu_pllfreq);
74 line++;
76 regval = CCM_PDR0;
77 lcd_putsf(0, line++, " PDR0: %08lX", regval);
79 freq = mcu_pllfreq / (((regval & 0x7) + 1));
80 lcd_putsf(0, line++, " mcu_clk: %u", freq);
82 freq = mcu_pllfreq / (((regval >> 11) & 0x7) + 1);
83 lcd_putsf(0, line++, " hsp_clk: %u", freq);
85 freq = mcu_pllfreq / (((regval >> 3) & 0x7) + 1);
86 lcd_putsf(0, line++, " hclk_clk: %u", freq);
88 lcd_putsf(0, line++, " ipg_clk: %u",
89 freq / (unsigned)(((regval >> 6) & 0x3) + 1));
91 lcd_putsf(0, line++, " nfc_clk: %u",
92 freq / (unsigned)(((regval >> 8) & 0x7) + 1));
94 line++;
96 /* Serial clock domain */
97 lcd_putsf(0, line++, "SPCTL: %08lX", spctl);
98 lcd_putsf(0, line++, " spl_dpdgck_clk: %u", ser_pllfreq);
100 line++;
102 /* USB clock domain */
103 lcd_putsf(0, line++, "UPCTL: %08lX", upctl);
105 lcd_putsf(0, line++, " upl_dpdgck_clk: %u", usb_pllfreq);
107 regval = CCM_PDR1;
108 lcd_putsf(0, line++, " PDR1: %08lX", regval);
110 freq = usb_pllfreq /
111 ((((regval >> 30) & 0x3) + 1) * (((regval >> 27) & 0x7) + 1));
112 lcd_putsf(0, line++, " usb_clk: %u", freq);
114 freq = usb_pllfreq / (((CCM_PDR0 >> 16) & 0x1f) + 1);
115 lcd_putsf(0, line++, " ipg_per_baud: %u", freq);
117 line++;
118 lcd_putsf(0, line++, "PMCR0: %08lX", CCM_PMCR0);
120 line++;
121 lcd_putsf(0, line++, "cpu_frequency: %ld Hz", cpu_frequency);
123 lcd_putsf(0, line++, "dvfs_level: %u", dvfs_get_level());
124 lcd_putsf(0, line++, "dvfs d|u|p|n: %u %u %u %u",
125 dvfs_nr_dn, dvfs_nr_up, dvfs_nr_pnc, dvfs_nr_no);
126 regval = dvfs_dptc_get_voltage();
127 lcd_putsf(0, line++, "cpu_voltage: %d.%03d V", regval / 1000,
128 regval % 1000);
130 lcd_putsf(0, line++, "dptc_wp: %u", dptc_get_wp());
131 lcd_putsf(0, line++, "dptc d|u|p|n: %u %u %u %u",
132 dptc_nr_dn, dptc_nr_up, dptc_nr_pnc, dptc_nr_no);
133 lcd_putsf(0, line++, "DVCR0,1: %08lX %08lX", CCM_DCVR0, CCM_DCVR1);
134 lcd_putsf(0, line++, "DVCR2,3: %08lX %08lX", CCM_DCVR2, CCM_DCVR3);
135 lcd_putsf(0, line++, "SWITCHERS0: %08lX", mc13783_read(MC13783_SWITCHERS0));
136 lcd_putsf(0, line++, "SWITCHERS1: %08lX", mc13783_read(MC13783_SWITCHERS1));
138 lcd_update();
140 if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
141 return false;
145 bool dbg_ports(void)
147 int line;
148 int i;
150 static const char pmic_regset[] =
152 MC13783_INTERRUPT_STATUS0,
153 MC13783_INTERRUPT_SENSE0,
154 MC13783_INTERRUPT_STATUS1,
155 MC13783_INTERRUPT_SENSE1,
156 MC13783_CHARGER,
157 MC13783_RTC_TIME,
158 MC13783_RTC_ALARM,
159 MC13783_RTC_DAY,
160 MC13783_RTC_DAY_ALARM,
163 static const char *pmic_regnames[ARRAYLEN(pmic_regset)] =
165 "Int Stat0 ",
166 "Int Sense0",
167 "Int Stat1 ",
168 "Int Sense1",
169 "Charger ",
170 "RTC Time ",
171 "RTC Alarm ",
172 "RTC Day ",
173 "RTC Day Al",
176 uint32_t pmic_regs[ARRAYLEN(pmic_regset)];
178 lcd_clear_display();
179 lcd_setfont(FONT_SYSFIXED);
181 while(1)
183 line = 0;
184 lcd_puts(0, line++, "[Ports and Registers]");
185 line++;
187 /* GPIO1 */
188 lcd_putsf(0, line++, "GPIO1: DR: %08lx GDIR: %08lx", GPIO1_DR, GPIO1_GDIR);
190 lcd_putsf(0, line++, " PSR: %08lx ICR1: %08lx", GPIO1_PSR, GPIO1_ICR1);
192 lcd_putsf(0, line++, " ICR2: %08lx IMR: %08lx", GPIO1_ICR2, GPIO1_IMR);
194 lcd_putsf(0, line++, " ISR: %08lx", GPIO1_ISR);
195 line++;
197 /* GPIO2 */
198 lcd_putsf(0, line++, "GPIO2: DR: %08lx GDIR: %08lx", GPIO2_DR, GPIO2_GDIR);
200 lcd_putsf(0, line++, " PSR: %08lx ICR1: %08lx", GPIO2_PSR, GPIO2_ICR1);
202 lcd_putsf(0, line++, " ICR2: %08lx IMR: %08lx", GPIO2_ICR2, GPIO2_IMR);
204 lcd_putsf(0, line++, " ISR: %08lx", GPIO2_ISR);
205 line++;
207 /* GPIO3 */
208 lcd_putsf(0, line++, "GPIO3: DR: %08lx GDIR: %08lx", GPIO3_DR, GPIO3_GDIR);
210 lcd_putsf(0, line++, " PSR: %08lx ICR1: %08lx", GPIO3_PSR, GPIO3_ICR1);
212 lcd_putsf(0, line++, " ICR2: %08lx IMR: %08lx", GPIO3_ICR2, GPIO3_IMR);
214 lcd_putsf(0, line++, " ISR: %08lx", GPIO3_ISR);
215 line++;
217 lcd_puts(0, line++, "PMIC Registers");
218 line++;
220 mc13783_read_regs(pmic_regset, pmic_regs, ARRAYLEN(pmic_regs));
222 for (i = 0; i < (int)ARRAYLEN(pmic_regs); i++)
224 lcd_putsf(0, line++, "%s: %08lx", pmic_regnames[i], pmic_regs[i]);
227 line++;
229 lcd_puts(0, line++, "ADC");
230 line++;
232 for (i = 0; i < NUM_ADC_CHANNELS; i += 4)
234 lcd_putsf(0, line++,
235 "CH%02d:%04u CH%02d:%04u CH%02d:%04u CH%02d:%04u",
236 i+0, adc_read(i+0),
237 i+1, adc_read(i+1),
238 i+2, adc_read(i+2),
239 i+3, adc_read(i+3));
242 lcd_update();
243 if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
244 return false;
249 bool __dbg_dvfs_dptc(void)
251 int ltwlevel;
252 unsigned long ltdetect;
253 int dvfs_wp, dvfs_mask;
254 bool dptc_on;
255 int i;
256 char buf[32];
257 unsigned long ltw[4];
258 bool ltwassert[4];
260 lcd_clear_display();
261 lcd_setfont(FONT_SYSFIXED);
263 dvfs_mask = dvfs_level_mask();
265 dvfs_wp = dvfs_enabled() ? -1 : (int)dvfs_get_level();
266 dptc_on = dptc_enabled();
267 dvfs_get_gp_sense(&ltwlevel, &ltdetect);
269 while (1)
271 int line = 0;
273 int button = button_get_w_tmo(HZ/10);
275 if (dvfs_wp < 0)
276 strcpy(buf, "Auto");
277 else
278 snprintf(buf, sizeof(buf), "%d", dvfs_wp);
280 lcd_puts(0, line, "[DVFS/DPTC]");
281 line += 2;
282 lcd_putsf(0, line, "CPU freq. point (Up/Dn) : %s", buf);
283 line += 2;
284 lcd_putsf(0, line, "DPTC volt. scale (Play) : %s",
285 dptc_on ? "Enabled" : "Disabled");
286 line += 2;
287 lcd_putsf(0, line, "GP load level (Vol +/-) : %d", ltwlevel);
288 line += 2;
289 lcd_puts(0, line, "----------------------------------------");
290 line += 2;
291 lcd_putsf(0, line++, "Frequency: %dHz", cpu_frequency);
292 i = dvfs_dptc_get_voltage();
293 lcd_putsf(0, line++, "Voltage : %d.%03d V", i / 1000, i % 1000);
295 for (i = 0; i <= 3; i++)
297 ltw[i] = dvfs_get_lt_weight(i + DVFS_LT_SIG_DVGP0);
298 ltwassert[i] = dvfs_get_gp_bit(i + DVFS_DVGP_0);
301 lcd_putsf(0, line++, "GPW (3-0): %lu%lu%lu%lu %c%c%c%c",
302 ltw[3], ltw[2], ltw[1], ltw[0],
303 ltwassert[3] ? 'y' : 'n',
304 ltwassert[2] ? 'y' : 'n',
305 ltwassert[1] ? 'y' : 'n',
306 ltwassert[0] ? 'y' : 'n');
308 line += 2;
309 lcd_puts(8, line, "(Press SELECT to revert)");
311 switch (button)
313 case DEBUG_CANCEL|BUTTON_REL:
314 return false;
316 /* CPU frequency */
317 case BUTTON_UP:
318 if (++dvfs_wp >= DVFS_NUM_LEVELS)
320 /* Going back to automatic */
321 dvfs_wp = -1;
322 dvfs_start();
324 else
326 if (dvfs_wp == 0)
328 /* Going to manual setting */
329 dvfs_stop();
332 /* Skip gaps in mask */
333 while (((1 << dvfs_wp) & dvfs_mask) == 0) dvfs_wp++;
334 dvfs_set_level(dvfs_wp);
337 break;
339 case BUTTON_DOWN:
340 if (--dvfs_wp == -1)
342 /* Going back to automatic */
343 dvfs_start();
345 else
347 if (dvfs_wp <= -2)
349 /* Going to manual setting */
350 dvfs_stop();
351 dvfs_wp = DVFS_NUM_LEVELS - 1;
354 /* Skip gaps in mask */
355 while (((1 << dvfs_wp) & dvfs_mask) == 0) dvfs_wp--;
356 dvfs_set_level(dvfs_wp);
358 break;
360 /* GP Load tracking */
361 case BUTTON_VOL_UP:
362 if (ltwlevel < 28)
363 dvfs_set_gp_sense(++ltwlevel, ltdetect);
364 break;
366 case BUTTON_VOL_DOWN:
367 if (ltwlevel > 0)
368 dvfs_set_gp_sense(--ltwlevel, ltdetect);
369 break;
371 case BUTTON_PLAY:
372 dptc_on = !dptc_enabled();
373 dptc_on ? dptc_start() : dptc_stop();
374 break;
376 case BUTTON_SELECT:
377 dvfs_start();
378 dptc_start();
379 dvfs_set_gp_sense(-1, 0);
381 dvfs_wp = dvfs_enabled() ? -1 : (int)dvfs_get_level();
382 dptc_on = dptc_enabled();
383 dvfs_get_gp_sense(&ltwlevel, &ltdetect);
384 break;
387 lcd_update();
388 yield();