AnsweredAssumed Answered

i.MX53 sometimes hangs during boot

Question asked by Mogens Lauridsen on Jun 25, 2018
Latest reply on Jun 27, 2018 by Mogens Lauridsen

Hi,

 

We are using the iMX53 (iMX538). Some of the boards we manufacture have problems booting. This might be something like 5% of the boards. After one or more reset caused by watchdog the board finally boots. This can delay the startup from 6 sec to 1-2 minutes.

 

I have tried to find where it stops/hangs, and it happens while initializing the PLL's.

We use barebox but I have found the same sequence in u-boot:

 

First PLL3 is set to 400 MHz, then some peripheral is switched to PLL3 and finally PLL3 is changed to 216 MHz.
Does anyone know why PLL3 first is set to 400MHz and later to 216MHz?

 

See "imx5_setup_pll_400((void __iomem *)MX53_PLL2_BASE_ADDR);" and

"imx5_setup_pll_216((void __iomem *)MX53_PLL3_BASE_ADDR);" in the barebox code below.

Our boards seem to boot fine if I change the code to set PLL3 to 216 MHz in the first place and don't change PLL3 later.
But does this have any side effects?

Since this is only seen on some of the boards, I am guessing that something in some of the iMX53's doesn't run reliable at 400MHz, and hangs the boot process.

 

barebox: arch/arm/mach-imx/imx53.c:

void imx53_init_lowlevel_early(unsigned int cpufreq_mhz)
{
    void __iomem *ccm = (void __iomem *)MX53_CCM_BASE_ADDR;
    u32 r;

 

    imx5_init_lowlevel();

 

    /*
     * AIPS setup - Only setup MPROTx registers.
     * The PACR default values are good.
     * Set all MPROTx to be non-bufferable, trusted for R/W,
     * not forced to user-mode.
     */
    writel(0x77777777, MX53_AIPS1_BASE_ADDR + 0);
    writel(0x77777777, MX53_AIPS1_BASE_ADDR + 4);
    writel(0x77777777, MX53_AIPS2_BASE_ADDR + 0);
    writel(0x77777777, MX53_AIPS2_BASE_ADDR + 4);

 

    /* Gate of clocks to the peripherals first */
    writel(0x3fffffff, ccm + MX5_CCM_CCGR0);
    writel(0x00000000, ccm + MX5_CCM_CCGR1);
    writel(0x00000000, ccm + MX5_CCM_CCGR2);
    writel(0x00000000, ccm + MX5_CCM_CCGR3);
    writel(0x00030000, ccm + MX5_CCM_CCGR4);
    writel(0x00fff030, ccm + MX5_CCM_CCGR5);
    writel(0x0f00030f, ccm + MX5_CCM_CCGR6);
    writel(0x00000000, ccm + MX53_CCM_CCGR7);

 

    /* Switch ARM to step clock */
    writel(0x4, ccm + MX5_CCM_CCSR);

 

    if (cpufreq_mhz == 1000)
        imx5_setup_pll_1000((void __iomem *)MX53_PLL1_BASE_ADDR);
    else
        imx5_setup_pll_800((void __iomem *)MX53_PLL1_BASE_ADDR);

 

    imx5_setup_pll_400((void __iomem *)MX53_PLL3_BASE_ADDR);

 

        /* Switch peripheral to PLL3 */
    writel(0x00015154, ccm + MX5_CCM_CBCMR);
    writel(0x02888945 | (1<<16), ccm + MX5_CCM_CBCDR);

 

    /* make sure change is effective */
    while (readl(ccm + MX5_CCM_CDHIPR));

 

    imx5_setup_pll_400((void __iomem *)MX53_PLL2_BASE_ADDR);  <------------ 400MHz

 

    /* Switch peripheral to PLL2 */
    r = 0x00808145 |
        (2 << 10) |
        (0 << 16) |
        (1 << 19);

 

    writel(r, ccm + MX5_CCM_CBCDR);

 

    writel(0x00016154, ccm + MX5_CCM_CBCMR);

 

    r = readl(ccm + MX5_CCM_CSCMR1);

 

    /* change uart clk parent to pll2 */
    r &= ~MX5_CCM_CSCMR1_UART_CLK_SEL_MASK;
    r |= 1 << MX5_CCM_CSCMR1_UART_CLK_SEL_OFFSET;

 

    /* USB phy clock from osc */
    r &= ~(1 << MX5_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET);

 

    writel(r, ccm + MX5_CCM_CSCMR1);

 

    /* make sure change is effective */
    while (readl(ccm + MX5_CCM_CDHIPR));

 

    imx5_setup_pll_216((void __iomem *)MX53_PLL3_BASE_ADDR);  <------------ 216MHz
    imx5_setup_pll_455((void __iomem *)MX53_PLL4_BASE_ADDR);

 

    /* Set the platform clock dividers */
    writel(0x00000124, MX53_ARM_BASE_ADDR + 0x14);

 

    writel(0, ccm + MX5_CCM_CACRR);

 

    /* Switch ARM back to PLL 1. */
    writel(0, ccm + MX5_CCM_CCSR);

 

    /* make uart div = 6*/
    r = readl(ccm + MX5_CCM_CSCDR1);
    r &= ~0x3f;
    r |= 0x0a;

 

    r &= ~MX5_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK;
    r &= ~MX5_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK;
    r |= 1 << MX5_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET;

 

    r &= ~MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK;
    r &= ~MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK;
    r |= 1 << MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET;

 

    r &= ~MX5_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
    r &= ~MX5_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;

 

    r |= 3 << MX5_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
    r |= 1 << MX5_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;

 

    writel(r, ccm + MX5_CCM_CSCDR1);

 

    /* Restore the default values in the Gate registers */
    writel(0xffffffff, ccm + MX5_CCM_CCGR0);
    writel(0xffffffff, ccm + MX5_CCM_CCGR1);
    writel(0xffffffff, ccm + MX5_CCM_CCGR2);
    writel(0xffffffff, ccm + MX5_CCM_CCGR3);
    writel(0xffffffff, ccm + MX5_CCM_CCGR4);
    writel(0xffffffff, ccm + MX5_CCM_CCGR5);
    writel(0xffffffff, ccm + MX5_CCM_CCGR6);
    writel(0xffffffff, ccm + MX53_CCM_CCGR7);

 

    writel(0, ccm + MX5_CCM_CCDR);
}

Outcomes