
This is useful if the power management on the chip isn't properly initialized. It's possible to use the internal LRADC to sample various power rails and debug the problem.
Signed-off-by: Marek Vasut marex@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com --- arch/arm/cpu/arm926ejs/mxs/mxs_init.h | 2 + arch/arm/cpu/arm926ejs/mxs/spl_boot.c | 3 ++ arch/arm/cpu/arm926ejs/mxs/spl_debug.c | 89 ++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs_init.h b/arch/arm/cpu/arm926ejs/mxs/mxs_init.h index e6f837c..acb62fa 100644 --- a/arch/arm/cpu/arm926ejs/mxs/mxs_init.h +++ b/arch/arm/cpu/arm926ejs/mxs/mxs_init.h @@ -44,8 +44,10 @@ void mxs_lradc_enable_batt_measurement(void);
#ifdef CONFIG_MX28_DEBUG void mx28_common_spl_debug_halt(void); +void mx28_read_lradc(void); #else static inline void mx28_common_spl_debug_halt(void) {} +static inline void mx28_read_lradc(void) {} #endif
#endif /* __M28_INIT_H__ */ diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c index f4f0c09..ea52a53 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c @@ -104,6 +104,9 @@ void mxs_common_spl_init(const iomux_cfg_t *iomux_setup, mxs_power_init();
mxs_mem_init(); + + mx28_read_lradc(); + data->mem_dram_size = mxs_mem_get_size();
data->boot_mode_idx = bootmode; diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_debug.c b/arch/arm/cpu/arm926ejs/mxs/spl_debug.c index f0aef20..51f9b79 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_debug.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_debug.c @@ -61,3 +61,92 @@ void mx28_common_spl_debug_halt(void) /* Both magic values matched, hang. */ asm volatile("x: b x\n"); } + +static void my_print_int(uint32_t val) +{ + /* 0xffffffff = 4,294,967,295 */ + char buf[10] = {0}; + int i = 0; + + if (!val) { + serial_putc('0'); + return; + } + + for (i = 0; i < 9; i++) { + buf[i] = val % 10; + val /= 10; + } + + for (; i >= 0; i--) + if (buf[i]) + break; + for (; i >= 0; i--) + serial_putc(buf[i] + '0'); +} + +static const char * const mx28_lradc_chan_names[16] = { + "[General Purpose 0]", + "[General Purpose 1]", + "[General Purpose 2]", + "[General Purpose 3]", + "[General Purpose 4]", + "[General Purpose 5]", + "[General Purpose 6]", + "[General Purpose 7 / Battery]", + "[Temperature sense 0]", + "[Temperature sense 1]", + "[VDDIO]", + "[VTH]", + "[VDDA]", + "[VDDD]", + "[VBG]", + "[5V input]", +}; + +static void mx28_read_lradc_chans(int offset) +{ + struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + int i; + uint32_t val; + + mxs_reset_block(®s->hw_lradc_ctrl0_reg); + + /* Flush the block */ + writel(0, ®s->hw_lradc_ctrl0); + writel(0, ®s->hw_lradc_ctrl1); + writel(0, ®s->hw_lradc_ctrl2); + writel(0, ®s->hw_lradc_ctrl3); + + /* Empty the channels */ + for (i = 0; i < 8; i++) + writel(0, ®s->hw_lradc_ch0_reg + i); + + /* Map channels and trigger them */ + writel(offset ? 0xfedcba98 : 0x76543210, ®s->hw_lradc_ctrl4); + writel(0xff, ®s->hw_lradc_ctrl0_set); + + while ((readl(®s->hw_lradc_ctrl1) & 0xff) != 0xff) + ; + + /* Read and report the channels */ + for (i = 0; i < 8; i++) { + val = readl(®s->hw_lradc_ch0_reg + i); + val &= LRADC_CH_VALUE_MASK; + serial_puts("Channel "); + my_print_int(i + (offset * 8)); + serial_putc(' '); + serial_puts(mx28_lradc_chan_names[i + (offset * 8)]); + serial_puts(" = "); + my_print_int(val); + serial_putc('\n'); + } +} + +void mx28_read_lradc(void) +{ + serial_init(); + serial_putc('\n'); + mx28_read_lradc_chans(0); + mx28_read_lradc_chans(1); +}