From d9efd47c036e8990d001baf245f5d0a31cfcb56b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 30 Dec 2014 17:24:01 +0800 Subject: imx:mx6sx add dram io configure for mx6sx Define two structure mx6sx_iomux_ddr_regs and mx6sx_iomux_grp_regs. Add a new function mx6sx_dram_iocfg to configure dram io. Since mx6sx only have one channel mmdc0, define a new empty macro MMDC1 to replace mmdc1->entry=value for mx6sx. And to other mx6 soc, MMDC1 effects as "mmdc1->entry=value". Signed-off-by: Peng Fan --- arch/arm/cpu/armv7/mx6/ddr.c | 96 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 14 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c index 7a9b03a68f..fef2231a39 100644 --- a/arch/arm/cpu/armv7/mx6/ddr.c +++ b/arch/arm/cpu/armv7/mx6/ddr.c @@ -12,6 +12,65 @@ #include #include +#if defined(CONFIG_MX6SX) +/* Configure MX6SX mmdc iomux */ +void mx6sx_dram_iocfg(unsigned width, + const struct mx6sx_iomux_ddr_regs *ddr, + const struct mx6sx_iomux_grp_regs *grp) +{ + struct mx6sx_iomux_ddr_regs *mx6_ddr_iomux; + struct mx6sx_iomux_grp_regs *mx6_grp_iomux; + + mx6_ddr_iomux = (struct mx6sx_iomux_ddr_regs *)MX6SX_IOM_DDR_BASE; + mx6_grp_iomux = (struct mx6sx_iomux_grp_regs *)MX6SX_IOM_GRP_BASE; + + /* DDR IO TYPE */ + writel(grp->grp_ddr_type, &mx6_grp_iomux->grp_ddr_type); + writel(grp->grp_ddrpke, &mx6_grp_iomux->grp_ddrpke); + + /* CLOCK */ + writel(ddr->dram_sdclk_0, &mx6_ddr_iomux->dram_sdclk_0); + + /* ADDRESS */ + writel(ddr->dram_cas, &mx6_ddr_iomux->dram_cas); + writel(ddr->dram_ras, &mx6_ddr_iomux->dram_ras); + writel(grp->grp_addds, &mx6_grp_iomux->grp_addds); + + /* Control */ + writel(ddr->dram_reset, &mx6_ddr_iomux->dram_reset); + writel(ddr->dram_sdba2, &mx6_ddr_iomux->dram_sdba2); + writel(ddr->dram_sdcke0, &mx6_ddr_iomux->dram_sdcke0); + writel(ddr->dram_sdcke1, &mx6_ddr_iomux->dram_sdcke1); + writel(ddr->dram_odt0, &mx6_ddr_iomux->dram_odt0); + writel(ddr->dram_odt1, &mx6_ddr_iomux->dram_odt1); + writel(grp->grp_ctlds, &mx6_grp_iomux->grp_ctlds); + + /* Data Strobes */ + writel(grp->grp_ddrmode_ctl, &mx6_grp_iomux->grp_ddrmode_ctl); + writel(ddr->dram_sdqs0, &mx6_ddr_iomux->dram_sdqs0); + writel(ddr->dram_sdqs1, &mx6_ddr_iomux->dram_sdqs1); + if (width >= 32) { + writel(ddr->dram_sdqs2, &mx6_ddr_iomux->dram_sdqs2); + writel(ddr->dram_sdqs3, &mx6_ddr_iomux->dram_sdqs3); + } + + /* Data */ + writel(grp->grp_ddrmode, &mx6_grp_iomux->grp_ddrmode); + writel(grp->grp_b0ds, &mx6_grp_iomux->grp_b0ds); + writel(grp->grp_b1ds, &mx6_grp_iomux->grp_b1ds); + if (width >= 32) { + writel(grp->grp_b2ds, &mx6_grp_iomux->grp_b2ds); + writel(grp->grp_b3ds, &mx6_grp_iomux->grp_b3ds); + } + writel(ddr->dram_dqm0, &mx6_ddr_iomux->dram_dqm0); + writel(ddr->dram_dqm1, &mx6_ddr_iomux->dram_dqm1); + if (width >= 32) { + writel(ddr->dram_dqm2, &mx6_ddr_iomux->dram_dqm2); + writel(ddr->dram_dqm3, &mx6_ddr_iomux->dram_dqm3); + } +} +#endif + #if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6Q) || defined(CONFIG_MX6D) /* Configure MX6DQ mmdc iomux */ void mx6dq_dram_iocfg(unsigned width, @@ -184,12 +243,19 @@ void mx6sdl_dram_iocfg(unsigned width, */ #define MR(val, ba, cmd, cs1) \ ((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba) +#ifdef CONFIG_MX6SX +#define MMDC1(entry, value) do {} while (0) +#else +#define MMDC1(entry, value) do { mmdc1->entry = value; } while (0) +#endif void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, const struct mx6_mmdc_calibration *calib, const struct mx6_ddr3_cfg *ddr3_cfg) { volatile struct mmdc_p_regs *mmdc0; +#ifndef CONFIG_MX6SX volatile struct mmdc_p_regs *mmdc1; +#endif u32 val; u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd; u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl; @@ -203,7 +269,9 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, int cs; mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR; +#ifndef CONFIG_MX6SX mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR; +#endif /* MX6D/MX6Q: 1066 MHz memory clock, clkper = 1.894ns = 1894ps */ if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) { @@ -362,12 +430,12 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, mmdc0->mprddlctl = calib->p0_mprddlctl; mmdc0->mpwrdlctl = calib->p0_mpwrdlctl; if (sysinfo->dsize > 1) { - mmdc1->mpwldectrl0 = calib->p1_mpwldectrl0; - mmdc1->mpwldectrl1 = calib->p1_mpwldectrl1; - mmdc1->mpdgctrl0 = calib->p1_mpdgctrl0; - mmdc1->mpdgctrl1 = calib->p1_mpdgctrl1; - mmdc1->mprddlctl = calib->p1_mprddlctl; - mmdc1->mpwrdlctl = calib->p1_mpwrdlctl; + MMDC1(mpwldectrl0, calib->p1_mpwldectrl0); + MMDC1(mpwldectrl1, calib->p1_mpwldectrl1); + MMDC1(mpdgctrl0, calib->p1_mpdgctrl0); + MMDC1(mpdgctrl1, calib->p1_mpdgctrl1); + MMDC1(mprddlctl, calib->p1_mprddlctl); + MMDC1(mpwrdlctl, calib->p1_mpwrdlctl); } /* Read data DQ Byte0-3 delay */ @@ -379,23 +447,23 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, } if (sysinfo->dsize > 1) { - mmdc1->mprddqby0dl = 0x33333333; - mmdc1->mprddqby1dl = 0x33333333; - mmdc1->mprddqby2dl = 0x33333333; - mmdc1->mprddqby3dl = 0x33333333; + MMDC1(mprddqby0dl, 0x33333333); + MMDC1(mprddqby1dl, 0x33333333); + MMDC1(mprddqby2dl, 0x33333333); + MMDC1(mprddqby3dl, 0x33333333); } /* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */ val = (sysinfo->rtt_nom == 2) ? 0x00011117 : 0x00022227; mmdc0->mpodtctrl = val; if (sysinfo->dsize > 1) - mmdc1->mpodtctrl = val; + MMDC1(mpodtctrl, val); /* complete calibration */ val = (1 << 11); /* Force measurement on delay-lines */ mmdc0->mpmur0 = val; if (sysinfo->dsize > 1) - mmdc1->mpmur0 = val; + MMDC1(mpmur0, val); /* Step 1: configuration request */ mmdc0->mdscr = (u32)(1 << 15); /* config request */ @@ -435,7 +503,7 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, val = 0xa1390001; /* one-time HW ZQ calib */ mmdc0->mpzqhwctrl = val; if (sysinfo->dsize > 1) - mmdc1->mpzqhwctrl = val; + MMDC1(mpzqhwctrl, val); /* Step 7: Enable MMDC with desired chip select */ mmdc0->mdctl |= (1 << 31) | /* SDE_0 for CS0 */ @@ -477,7 +545,7 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, val = 0xa1390003; mmdc0->mpzqhwctrl = val; if (sysinfo->dsize > 1) - mmdc1->mpzqhwctrl = val; + MMDC1(mpzqhwctrl, val); /* Step 12: Configure and activate periodic refresh */ mmdc0->mdref = (1 << 14) | /* REF_SEL: Periodic refresh cycle: 32kHz */ -- cgit v1.2.1 From e8cdeefc222ff32a80282dd571be0426156cd9d9 Mon Sep 17 00:00:00 2001 From: "Ye.Li" Date: Wed, 14 Jan 2015 17:18:12 +0800 Subject: imx: mx6: Fixed AIPS3 base address issue Should use AIPS3 configuration address 0x0227C000 to set AIPS3, not the AIPS3 base address. Additional, replace AIPS1_BASE_ADDR to AIPS3_ARB_BASE_ADDR to align with AIPS1 and AIPS2, and resolve the AIPS3_ARB_BASE_ADDR undefine problem. Signed-off-by: Ye.Li --- arch/arm/cpu/armv7/mx6/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index 5f5f497201..e599a12b3a 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -109,7 +109,7 @@ void init_aips(void) aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR; aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR; #ifdef CONFIG_MX6SX - aips3 = (struct aipstz_regs *)AIPS3_BASE_ADDR; + aips3 = (struct aipstz_regs *)AIPS3_CONFIG_BASE_ADDR; #endif /* -- cgit v1.2.1 From 950eaf6230496585e72ebb965c458d35c6c7eac1 Mon Sep 17 00:00:00 2001 From: Graeme Russ Date: Sun, 25 Jan 2015 12:07:51 +1100 Subject: arm: mxs: Add debug outputs and comments to mxs SPL source files It is difficult to track down fail to boot issues in the mxs SPL. Implement the following to make it easier: - Add debug outputs to allow tracing of SPL progress in order to track where failure to boot occurs. DEUBUG and CONFIG_SPL_SERIAL_SUPPORT must be defined to enable debug output in SPL - Add TODO comments where it is not clear if the code is doing what it is meant to be doing, even tough the board boots properly (these comments refer to existing code, not to any code added by this patch) Signed-off-by: Graeme Russ --- arch/arm/cpu/arm926ejs/mxs/spl_boot.c | 1 + arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c | 13 +++- arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c | 18 +++++ arch/arm/cpu/arm926ejs/mxs/spl_power_init.c | 100 +++++++++++++++++++++++++++- 4 files changed, 127 insertions(+), 5 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c index d29b9aaf3d..2a5f8175d0 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c @@ -147,6 +147,7 @@ void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); mxs_spl_console_init(); + debug("SPL: Serial Console Initialised\n"); mxs_power_init(); diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c index cdfcddd824..96bd32f8ad 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c @@ -18,6 +18,8 @@ void mxs_lradc_init(void) { struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + debug("SPL: Initialisating LRADC\n"); + writel(LRADC_CTRL0_SFTRST, ®s->hw_lradc_ctrl0_clr); writel(LRADC_CTRL0_CLKGATE, ®s->hw_lradc_ctrl0_clr); writel(LRADC_CTRL0_ONCHIP_GROUNDREF, ®s->hw_lradc_ctrl0_clr); @@ -37,9 +39,15 @@ void mxs_lradc_enable_batt_measurement(void) { struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + debug("SPL: Enabling LRADC battery measurement\n"); + /* Check if the channel is present at all. */ - if (!(readl(®s->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) + if (!(readl(®s->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) { + debug("SPL: LRADC channel 7 is not present - aborting\n"); return; + } + + debug("SPL: LRADC channel 7 is present - configuring\n"); writel(LRADC_CTRL1_LRADC7_IRQ_EN, ®s->hw_lradc_ctrl1_clr); writel(LRADC_CTRL1_LRADC7_IRQ, ®s->hw_lradc_ctrl1_clr); @@ -65,6 +73,7 @@ void mxs_lradc_enable_batt_measurement(void) 100, ®s->hw_lradc_delay3); writel(0xffffffff, ®s->hw_lradc_ch7_clr); - writel(LRADC_DELAY_KICK, ®s->hw_lradc_delay3_set); + + debug("SPL: LRADC channel 7 configuration complete\n"); } diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c index 97ef67d8c5..a744e5d499 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c @@ -92,6 +92,7 @@ static uint32_t dram_vals[] = { __weak void mxs_adjust_memory_params(uint32_t *dram_vals) { + debug("SPL: Using default SDRAM parameters\n"); } #ifdef CONFIG_MX28 @@ -99,8 +100,10 @@ static void initialize_dram_values(void) { int i; + debug("SPL: Setting mx28 board specific SDRAM parameters\n"); mxs_adjust_memory_params(dram_vals); + debug("SPL: Applying SDRAM parameters\n"); for (i = 0; i < ARRAY_SIZE(dram_vals); i++) writel(dram_vals[i], MXS_DRAM_BASE + (4 * i)); } @@ -109,6 +112,7 @@ static void initialize_dram_values(void) { int i; + debug("SPL: Setting mx23 board specific SDRAM parameters\n"); mxs_adjust_memory_params(dram_vals); /* @@ -120,6 +124,7 @@ static void initialize_dram_values(void) * HW_DRAM_CTL8 is setup as the last element. * So skip the initialization of these HW_DRAM_CTL registers. */ + debug("SPL: Applying SDRAM parameters\n"); for (i = 0; i < ARRAY_SIZE(dram_vals); i++) { if (i == 8 || i == 27 || i == 28 || i == 35) continue; @@ -146,6 +151,8 @@ static void mxs_mem_init_clock(void) const unsigned char divider = 21; #endif + debug("SPL: Initialising FRAC0\n"); + /* Gate EMI clock */ writeb(CLKCTRL_FRAC_CLKGATE, &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]); @@ -170,6 +177,7 @@ static void mxs_mem_init_clock(void) &clkctrl_regs->hw_clkctrl_clkseq_clr); early_delay(10000); + debug("SPL: FRAC0 Initialised\n"); } static void mxs_mem_setup_cpu_and_hbus(void) @@ -177,6 +185,8 @@ static void mxs_mem_setup_cpu_and_hbus(void) struct mxs_clkctrl_regs *clkctrl_regs = (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + debug("SPL: Setting CPU and HBUS clock frequencies\n"); + /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz * and ungate CPU clock */ writeb(19 & CLKCTRL_FRAC_FRAC_MASK, @@ -209,6 +219,8 @@ static void mxs_mem_setup_vdda(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Configuring VDDA\n"); + writel((0xc << POWER_VDDACTRL_TRG_OFFSET) | (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) | POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW, @@ -240,6 +252,8 @@ static void mx23_mem_setup_vddmem(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Setting mx23 VDDMEM\n"); + /* We must wait before and after disabling the current limiter! */ early_delay(10000); @@ -252,6 +266,8 @@ static void mx23_mem_setup_vddmem(void) static void mx23_mem_init(void) { + debug("SPL: Initialising mx23 SDRAM Controller\n"); + /* * Reset/ungate the EMI block. This is essential, otherwise the system * suffers from memory instability. This thing is mx23 specific and is @@ -297,6 +313,8 @@ static void mx28_mem_init(void) struct mxs_pinctrl_regs *pinctrl_regs = (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE; + debug("SPL: Initialising mx28 SDRAM Controller\n"); + /* Set DDR2 mode */ writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set); diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c index 1c54ab7de3..7fb734e9dc 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c @@ -26,6 +26,8 @@ static void mxs_power_clock2xtal(void) struct mxs_clkctrl_regs *clkctrl_regs = (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + debug("SPL: Switching CPU clock to 24MHz XTAL\n"); + /* Set XTAL as CPU reference clock */ writel(CLKCTRL_CLKSEQ_BYPASS_CPU, &clkctrl_regs->hw_clkctrl_clkseq_set); @@ -43,9 +45,23 @@ static void mxs_power_clock2pll(void) struct mxs_clkctrl_regs *clkctrl_regs = (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + debug("SPL: Switching CPU core clock source to PLL\n"); + + /* + * TODO: Are we really? It looks like we turn on PLL0, but we then + * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already + * set by mxs_power_clock2xtal()). Clearing this bit here seems to + * introduce some instability (causing the CPU core to hang). Maybe + * we aren't giving PLL0 enough time to stabilise? + */ setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0, CLKCTRL_PLL0CTRL0_POWER); early_delay(100); + + /* + * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a + * wait on the PLL0 LOCK bit? + */ setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq, CLKCTRL_CLKSEQ_BYPASS_CPU); } @@ -62,6 +78,8 @@ static void mxs_power_set_auto_restart(void) struct mxs_rtc_regs *rtc_regs = (struct mxs_rtc_regs *)MXS_RTC_BASE; + debug("SPL: Setting auto-restart bit\n"); + writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr); while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST) ; @@ -101,14 +119,17 @@ static void mxs_power_set_linreg(void) (struct mxs_power_regs *)MXS_POWER_BASE; /* Set linear regulator 25mV below switching converter */ + debug("SPL: Setting VDDD 25mV below DC-DC converters\n"); clrsetbits_le32(&power_regs->hw_power_vdddctrl, POWER_VDDDCTRL_LINREG_OFFSET_MASK, POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); + debug("SPL: Setting VDDA 25mV below DC-DC converters\n"); clrsetbits_le32(&power_regs->hw_power_vddactrl, POWER_VDDACTRL_LINREG_OFFSET_MASK, POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW); + debug("SPL: Setting VDDIO 25mV below DC-DC converters\n"); clrsetbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDIOCTRL_LINREG_OFFSET_MASK, POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW); @@ -127,6 +148,8 @@ static int mxs_get_batt_volt(void) volt &= POWER_BATTMONITOR_BATT_VAL_MASK; volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET; volt *= 8; + + debug("SPL: Battery Voltage = %dmV\n", volt); return volt; } @@ -154,8 +177,10 @@ static int mxs_is_batt_good(void) (struct mxs_power_regs *)MXS_POWER_BASE; uint32_t volt = mxs_get_batt_volt(); - if ((volt >= 2400) && (volt <= 4300)) + if ((volt >= 2400) && (volt <= 4300)) { + debug("SPL: Battery is good\n"); return 1; + } clrsetbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, @@ -175,16 +200,21 @@ static int mxs_is_batt_good(void) volt = mxs_get_batt_volt(); - if (volt >= 3500) + if (volt >= 3500) { + debug("SPL: Battery Voltage too high\n"); return 0; + } - if (volt >= 2400) + if (volt >= 2400) { + debug("SPL: Battery is good\n"); return 1; + } writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK, &power_regs->hw_power_charge_clr); writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set); + debug("SPL: Battery Voltage too low\n"); return 0; } @@ -203,6 +233,7 @@ static void mxs_power_setup_5v_detect(void) (struct mxs_power_regs *)MXS_POWER_BASE; /* Start 5V detection */ + debug("SPL: Starting 5V input detection comparator\n"); clrsetbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_VBUSVALID_TRSH_MASK, POWER_5VCTRL_VBUSVALID_TRSH_4V4 | @@ -220,6 +251,8 @@ static void mxs_src_power_init(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Pre-Configuring power block\n"); + /* Improve efficieny and reduce transient ripple */ writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST | POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set); @@ -257,6 +290,8 @@ static void mxs_power_init_4p2_params(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Configuring common 4P2 regulator params\n"); + /* Setup 4P2 parameters */ clrsetbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK, @@ -289,6 +324,8 @@ static void mxs_enable_4p2_dcdc_input(int xfer) uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo; uint32_t prev_5v_brnout, prev_5v_droop; + debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling"); + prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) & POWER_5VCTRL_PWDN_5VBRNOUT; prev_5v_droop = readl(&power_regs->hw_power_ctrl) & @@ -390,6 +427,8 @@ static void mxs_power_init_4p2_regulator(void) (struct mxs_power_regs *)MXS_POWER_BASE; uint32_t tmp, tmp2; + debug("SPL: Enabling 4P2 regulator\n"); + setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2); writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set); @@ -407,6 +446,7 @@ static void mxs_power_init_4p2_regulator(void) * gradually to avoid large inrush current from the 5V cable which can * cause transients/problems */ + debug("SPL: Charging 4P2 capacitor\n"); mxs_enable_4p2_dcdc_input(0); if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) { @@ -420,6 +460,8 @@ static void mxs_power_init_4p2_regulator(void) POWER_DCDC4P2_ENABLE_DCDC); writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, &power_regs->hw_power_5vctrl_set); + + debug("SPL: Unable to recover from mx23 errata 5837\n"); hang(); } @@ -433,6 +475,7 @@ static void mxs_power_init_4p2_regulator(void) * current limit until the brownout status is false or until we've * reached our maximum defined 4p2 current limit. */ + debug("SPL: Setting 4P2 brownout level\n"); clrsetbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK, 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */ @@ -479,8 +522,11 @@ static void mxs_power_init_dcdc_4p2_source(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Switching DC-DC converters to 4P2\n"); + if (!(readl(&power_regs->hw_power_dcdc4p2) & POWER_DCDC4P2_ENABLE_DCDC)) { + debug("SPL: Already switched - aborting\n"); hang(); } @@ -509,6 +555,8 @@ static void mxs_power_enable_4p2(void) uint32_t vdddctrl, vddactrl, vddioctrl; uint32_t tmp; + debug("SPL: Powering up 4P2 regulator\n"); + vdddctrl = readl(&power_regs->hw_power_vdddctrl); vddactrl = readl(&power_regs->hw_power_vddactrl); vddioctrl = readl(&power_regs->hw_power_vddioctrl); @@ -559,6 +607,8 @@ static void mxs_power_enable_4p2(void) if (tmp) writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr); + + debug("SPL: 4P2 regulator powered-up\n"); } /** @@ -574,6 +624,8 @@ static void mxs_boot_valid_5v(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Booting from 5V supply\n"); + /* * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V * disconnect event. FIXME @@ -601,6 +653,9 @@ static void mxs_powerdown(void) { struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("Powering Down\n"); + writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset); writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, &power_regs->hw_power_reset); @@ -617,6 +672,8 @@ static void mxs_batt_boot(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Configuring power block to boot from battery\n"); + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT); clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC); @@ -672,6 +729,8 @@ static void mxs_handle_5v_conflict(void) (struct mxs_power_regs *)MXS_POWER_BASE; uint32_t tmp; + debug("SPL: Resolving 5V conflict\n"); + setbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDIOCTRL_BO_OFFSET_MASK); @@ -683,19 +742,27 @@ static void mxs_handle_5v_conflict(void) * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes * unreliable */ + debug("SPL: VDDIO has a brownout\n"); mxs_powerdown(); break; } if (tmp & POWER_STS_VDD5V_GT_VDDIO) { + debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n"); mxs_boot_valid_5v(); break; } else { + debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n"); mxs_powerdown(); break; } + /* + * TODO: I can't see this being reached. We'll either + * powerdown or boot from a stable 5V supply. + */ if (tmp & POWER_STS_PSWITCH_MASK) { + debug("SPL: POWER_STS_PSWITCH_MASK is set\n"); mxs_batt_boot(); break; } @@ -713,21 +780,26 @@ static void mxs_5v_boot(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Configuring power block to boot from 5V input\n"); + /* * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID, * but their implementation always returns 1 so we omit it here. */ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + debug("SPL: 5V VDD good\n"); mxs_boot_valid_5v(); return; } early_delay(1000); if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + debug("SPL: 5V VDD good (after delay)\n"); mxs_boot_valid_5v(); return; } + debug("SPL: 5V VDD not good\n"); mxs_handle_5v_conflict(); } @@ -742,6 +814,8 @@ static void mxs_init_batt_bo(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Initialising battery brown-out level to 3.0V\n"); + /* Brownout at 3V */ clrsetbits_le32(&power_regs->hw_power_battmonitor, POWER_BATTMONITOR_BRWNOUT_LVL_MASK, @@ -762,6 +836,8 @@ static void mxs_switch_vddd_to_dcdc_source(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Switching VDDD to DC-DC converters\n"); + clrsetbits_le32(&power_regs->hw_power_vdddctrl, POWER_VDDDCTRL_LINREG_OFFSET_MASK, POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); @@ -788,6 +864,8 @@ static void mxs_power_configure_power_source(void) struct mxs_lradc_regs *lradc_regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + debug("SPL: Configuring power source\n"); + mxs_src_power_init(); if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { @@ -811,6 +889,10 @@ static void mxs_power_configure_power_source(void) mxs_batt_boot(); } + /* + * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced + * from USB VBUS + */ mxs_power_clock2pll(); mxs_init_batt_bo(); @@ -819,6 +901,7 @@ static void mxs_power_configure_power_source(void) #ifdef CONFIG_MX23 /* Fire up the VDDMEM LinReg now that we're all set. */ + debug("SPL: Enabling mx23 VDDMEM linear regulator\n"); writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT, &power_regs->hw_power_vddmemctrl); #endif @@ -838,6 +921,8 @@ static void mxs_enable_output_rail_protection(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Enabling output rail protection\n"); + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr); @@ -1077,6 +1162,8 @@ static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg, */ static void mxs_setup_batt_detect(void) { + debug("SPL: Starting battery voltage measurement logic\n"); + mxs_lradc_init(); mxs_lradc_enable_batt_measurement(); early_delay(10); @@ -1111,6 +1198,8 @@ void mxs_power_init(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Initialising Power Block\n"); + mxs_ungate_power(); mxs_power_clock2xtal(); @@ -1123,9 +1212,13 @@ void mxs_power_init(void) mxs_power_configure_power_source(); mxs_enable_output_rail_protection(); + debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n"); mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150); + + debug("SPL: Setting VDDD to 1V5 (brownout @ 1v0)\n"); mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000); #ifdef CONFIG_MX23 + debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n"); mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700); #endif writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | @@ -1150,6 +1243,7 @@ void mxs_power_wait_pswitch(void) struct mxs_power_regs *power_regs = (struct mxs_power_regs *)MXS_POWER_BASE; + debug("SPL: Waiting for power switch input\n"); while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK)) ; } -- cgit v1.2.1 From 7a086037071401ee781425c382846dddfe80df68 Mon Sep 17 00:00:00 2001 From: Graeme Russ Date: Sun, 25 Jan 2015 12:07:52 +1100 Subject: arm: mxs: Enable booting of mx28 without battery Section 4.1.2 of Freescale Application Note AN4199 describes the configuration required to operate the mx28 from a 5V source without a battery. This patch changes the behaviour of the dropout control of the DC-DC converter (refer to section 11.12.9 of the mx28 Application Processor Reference Manual - Document Number: MCIMX28RM, Rev 2, 08/2013) to the following: - Always use 4P2 Linear Regulator if CONFIG_SYS_MXS_VDD5V_ONLY is defined - Switch between 4P2 Linear Regulator and Battery, using whichever has the highest voltage if CONFIG_SYS_MXS_VDD5V_ONLY isnot set (this is the same as the pre-patch behaviour) Signed-off-by: Graeme Russ Signed-off-by: Damien Gotfroi --- arch/arm/cpu/arm926ejs/mxs/spl_power_init.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c index 7fb734e9dc..c342217fa9 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c @@ -14,6 +14,13 @@ #include "mxs_init.h" +#ifdef CONFIG_SYS_MXS_VDD5V_ONLY +#define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \ + POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2 +#else +#define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \ + POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL +#endif /** * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL * @@ -303,8 +310,7 @@ static void mxs_power_init_4p2_params(void) clrsetbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_DROPOUT_CTRL_MASK, - POWER_DCDC4P2_DROPOUT_CTRL_100MV | - POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL); + DCDC4P2_DROPOUT_CONFIG); clrsetbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, -- cgit v1.2.1 From 2d6286ab7983b1fca45b7cc2d670286ec4898ffd Mon Sep 17 00:00:00 2001 From: Graeme Russ Date: Sun, 25 Jan 2015 12:07:53 +1100 Subject: arm: mxs: Add 'Wait for JTAG user' if booted in JTAG mode When booting in JTAG mode, there is no way to use soft break-points, and no way of knowing when SPL has finished executing (so the user can issue a 'halt' command to load u-boot.bin for example) Add a debug output and simple loop to stop execution at the completion of the SPL initialisation as a pseudo break-point when booting in JTAG mode Signed-off-by: Graeme Russ --- arch/arm/cpu/arm926ejs/mxs/spl_boot.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c index 2a5f8175d0..d7956e57de 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c @@ -157,6 +157,11 @@ void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, data->boot_mode_idx = bootmode; mxs_power_wait_pswitch(); + + if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) { + debug("SPL: Waiting for JTAG user\n"); + asm volatile ("x: b x"); + } } /* Support aparatus */ -- cgit v1.2.1