This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How/where to Disable DLL Refclk in code?

Other Parts Discussed in Thread: DA8XX

Hi,

I'm working on an OMAP L138 based product. We're facing a couple of issues related to ESD on the system very likely related to the issues discussed in Section 2.1.4 of the document linked below.

http://www.ti.com/lit/er/sprz301m/sprz301m.pdf

The document mentions a couple of suggestions for mitigation and possibly elimination of the problem but it's not clear how this should be done in code. I've tried to implement the recommendations in the Linux kernel and uboot and run into different issues in both cases. Details below:

Changes made to Linux kernel:

In the board specific init function I added the following lines of code to set the DLL REFCLK field.

#define DA8XX_DRYPC1R   0xe4

ddr_ctl_base = da8xx_get_mem_ctlr();
ddr_pcr = __raw_readl(ddr_ctl_base + DA8XX_DRPYC1R_REG);
pr_alert("### Default value of DRPYC1R: 0x%x\n", ddr_pcr);
ddr_pcr |= 0x00002000;

#if 1
__raw_writel((ddr_ctl_base + DA8XX_DRPYC1R_REG), ddr_pcr);

#endif

Without the write command, the kernel boots as expected and reads the value written to DRPYC1R by uBoot correctly. However, as soon as the write command is introduced the kernel does not boot, presumably because I'm writing to the DDR registers without unlocking them for write.

To get pass this I moved my changes over to uboot. Modified version of da850_ddr_setup() in 

uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c is shown below. The line of code I added is shown in bold text.

int da850_ddr_setup(void)
{
   unsigned long tmp;

 /* Enable the Clock to DDR2/mDDR */
 lpsc_on(DAVINCI_LPSC_DDR_EMIF);

 tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
 if ((tmp & VTP_POWERDWN) == VTP_POWERDWN) {
      /* Begin VTP Calibration */
     clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN);
     clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK);
    setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
    clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
    setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);

    /* Polling READY bit to see when VTP calibration is done */
    tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
   while ((tmp & VTP_READY) != VTP_READY)
        tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);

     setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK);
    setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN);

    setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN);
 }

 writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);
 clrbits_le32(&davinci_syscfg1_regs->ddr_slew,
                          (1 << DDR_SLEW_CMOSEN_BIT));
 
 /*
 * SDRAM Configuration Register (SDCR):
 * First set the BOOTUNLOCK bit to make configuration bits
 * writeable.
 */
 setbits_le32(&dv_ddr2_regs_ctrl->sdbcr, DV_DDR_BOOTUNLOCK);

 /*
 * Write the new value of these bits and clear BOOTUNLOCK.
 * At the same time, set the TIMUNLOCK bit to allow changing
 * the timing registers
 */
 tmp = CONFIG_SYS_DA850_DDR2_SDBCR;

 tmp &= ~DV_DDR_BOOTUNLOCK;
 tmp |= DV_DDR_TIMUNLOCK;
 writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);

/* write memory configuration and timing */
writel(CONFIG_SYS_DA850_DDR2_SDBCR2, &dv_ddr2_regs_ctrl->sdbcr2);
writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr);
writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2);

/* clear the TIMUNLOCK bit and write the value of the CL field */
tmp &= ~DV_DDR_TIMUNLOCK;
writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);

 /*
 * LPMODEN and MCLKSTOPEN must be set!
 * Without this bits set, PSC don;t switch states !!
 */
writel(CONFIG_SYS_DA850_DDR2_SDRCR |
               DV_DDR_SDRCR_LPMODEN |
               DV_DDR_SDRCR_MCLKSTOPEN,
               &dv_ddr2_regs_ctrl->sdrcr); 

/* Disable DLL REFCLK */
#if 1
     setbits_le32(&dv_ddr2_regs_ctrl->ddrphycr, 0x2000 );
#endif


 /* SyncReset the Clock to EMIF3A SDRAM */
lpsc_syncreset(DAVINCI_LPSC_DDR_EMIF);
 /* Enable the Clock to EMIF3A SDRAM */
 lpsc_on(DAVINCI_LPSC_DDR_EMIF);

 /* disable self refresh */
clrbits_le32(&dv_ddr2_regs_ctrl->sdrcr, DV_DDR_SDRCR_LPMODEN | DV_DDR_SDRCR_MCLKSTOPEN);

writel(CONFIG_SYS_DA850_DDR2_PBBPR, &dv_ddr2_regs_ctrl->pbbpr);

return 0;

}

After flashing the version of uboot with the changes listed above the system fails to boot. In this case I'm assuming it's because the instruction setting the DLL Refclk bit is misplaced in the sequence.

What is the correct the way to make this change and where should this be done (kernel or uboot)? Any pointers of where this should be placed in the sequence?

Thanks,

Dinesh

 

 

 

  • Hi,

    Can you please make this changes in board def file at u-boot source.

    I assume that you are using da850evm.h board definition file.

    Ex:

    include/configs/da850evm.h

    #define CONFIG_SYS_DA850_DDR2_DDRPHYCR (DV_DDR_PHY_PWRDNEN | \
                        DV_DDR_PHY_EXT_STRBEN | \
                        (0x4 << DV_DDR_PHY_RD_LATENCY_SHIFT))

  • Hi Dinesh,

    In addition to what Stalin is asking, I will add that we recommend that you do the PHY refclk disable as early as possible in the system, so doing this in the uboot is preferred instead of doing it in the linux kernel. So your second approach is correct, as you are putting this close to where the DDR initialization is done, as shown in the advisory.

    Please make sure you are doing the mods to DDR PHY register correctly, the advisory shows an "OR" when writing to disable etc. It would be good to make sure you are not wiping out any DDR PHY register settings from the DDR init section when you do the REFCLK disable.

    Regards

    Mukul

  • Hi Mukul,

    Thanks for the explanation. I do not write to the DRPYCR1 register in one go. The first instruction that writes to DRPYCR1 already exists in code. I add another instruction much later in the sequence that sets bit 13 of this register. Do you recommend that all this be done in one step? Scroll a few lines below for code snippet.

    Titus,

    Thanks for the info. We use our own config that is very similar to da850evm.h. Here's the config specific to our board. Note that the default configuration does not modify the DDL disable bit.

    #define CONFIG_SYS_DA850_DDR2_DDRPHYCR (DV_DDR_PHY_PWRDNEN | \                                                                                                DV_DDR_PHY_EXT_STRBEN | \                                                                                                                                                    (0x3 << DV_DDR_PHY_RD_LATENCY_SHIFT))

    The exact sequence of instructions used to disable the DLL refclk is listed below. Look for lines in bold text.

    writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);

    clrbits_le32(&davinci_syscfg1_regs->ddr_slew,
    (1 << DDR_SLEW_CMOSEN_BIT));

    /*
    * SDRAM Configuration Register (SDCR):
    * First set the BOOTUNLOCK bit to make configuration bits
    * writeable.
    */
    setbits_le32(&dv_ddr2_regs_ctrl->sdbcr, DV_DDR_BOOTUNLOCK);

    /*
    * Write the new value of these bits and clear BOOTUNLOCK.
    * At the same time, set the TIMUNLOCK bit to allow changing
    * the timing registers
    */
    tmp = CONFIG_SYS_DA850_DDR2_SDBCR;
    tmp &= ~DV_DDR_BOOTUNLOCK;
    tmp |= DV_DDR_TIMUNLOCK;
    writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);

    /* write memory configuration and timing */
    writel(CONFIG_SYS_DA850_DDR2_SDBCR2, &dv_ddr2_regs_ctrl->sdbcr2);
    writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr);
    writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2);

    /* clear the TIMUNLOCK bit and write the value of the CL field */
    tmp &= ~DV_DDR_TIMUNLOCK;
    writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);

    /*
    * LPMODEN and MCLKSTOPEN must be set!
    * Without this bits set, PSC don;t switch states !!
    */
    #if 0 /* DLB_CHANGE */
    writel(CONFIG_SYS_DA850_DDR2_SDRCR |
    (1 << DV_DDR_SRCR_LPMODEN_SHIFT) |
    (1 << DV_DDR_SRCR_MCLKSTOPEN_SHIFT),
    &dv_ddr2_regs_ctrl->sdrcr);
    #else
    writel(CONFIG_SYS_DA850_DDR2_SDRCR |
    DV_DDR_SDRCR_LPMODEN |
    DV_DDR_SDRCR_MCLKSTOPEN,
    &dv_ddr2_regs_ctrl->sdrcr);
    #endif

    /* CHANGE - START */
    /* Disable DLL REFCLK */
    #if 1
    setbits_le32(&dv_ddr2_regs_ctrl->ddrphycr, 0x2000 );

    #endif
    /* CHANGE - END */

    In the process of trying this change I managed to brick my board; the device fails to boot; it does not  even get to the uboot prompt.  Subsequent attempts to rewrite the flash image always fail with the error shown below (tried this using CCS and loadti.bat)

     ARM9_0: GEL: Error while executing OnTargetConnect(): execution state prevented access   at (*((unsigned int *) ((0x01C10000+0x800)+(4*LPSC_num)))&0x3F) [DLB_BLACKFOREST_ARM.gel:995]     at PSC0_LPSC_enable(0, 0) [DLB_BLACKFOREST_ARM.gel:553] at PSC_All_On_Full_EVM() [DLB_BLACKFOREST_ARM.gel:251]        at OnTargetConnect() .

     Any thoughts on how I can recover from this situation?  

  • Hi Dinesh,

    To confirm whether the issue is h/w or s/w side,

    Have you tried to disable DLL_Ref clock in DRPYC1R register in gel file through CCS and tried to load any example projects ?

    If yes, What about results?

    If no,

    Can you please make the following changes in gel file, and try to load any example projects in any core.

    Comment out "Set_DDR2_150MHz" function

    /*
    Set_DDR2_150MHz() {
        GEL_TextOut("\tDDR initialization is in progress....\n","Output",1,1,1);
        Set_DDRPLL_150MHz();
        DEVICE_DDRConfig(DDR2, 150);
        GEL_TextOut("\tDDR2 init for 150 MHz is done\n","Output",1,1,1);
    }
    */


    //titus

    Set_DDR2_150MHz() {

        unsigned int k=0,i;

        GEL_TextOut("\tDDR initialization is in progress....\n","Output",1,1,1);

        Set_DDRPLL_150MHz();

        DEVICE_DDRConfig(DDR2, 150);

        GEL_TextOut("\tDDR2 init for 150 MHz is done ##BEFORE### DRPYC1R = %x  DRPYC1R = %d \n","Output",1,1,1,DRPYC1R,DRPYC1R);
            
        for(i=0;i<200;i++)    {}
      
        k = *(unsigned int*) (0xC0000000);

        DRPYC1R |= 0x00002000;

        GEL_TextOut("\tDDR2 init for 150 MHz is done ##AFTER### DRPYC1R = %x  DRPYC1R = %d \n","Output",1,1,1,DRPYC1R,DRPYC1R);
    }

    I think, this test case will useful to confirm whether the issue is due to h/w or s/w side,

    I will update u-boot changes for disabling the DLL REF clock in soon,

  • Hi Dinesh,

    As per the "DaVinci-PSP-SDK-03.22.00.02" TI SDK release,

    This "uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c" file will compile only for NOR boot configuration unless you modify the u-boot def config file manually,

    include/configs/da850evm.h

    #ifdef CONFIG_DIRECT_NOR_BOOT
    #define CONFIG_ARCH_CPU_INIT
    #define CONFIG_DA8XX_GPIO
    #define CONFIG_SYS_TEXT_BASE        0x60000000
    #define CONFIG_SYS_DV_NOR_BOOT_CFG    (0x11)
    #define CONFIG_DA850_LOWLEVEL
    #else
    #define CONFIG_SYS_TEXT_BASE        0xc1080000
    #endif

    uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinci/Makefile

    include $(TOPDIR)/config.mk

    LIB    = $(obj)lib$(SOC).o

    COBJS-y                += cpu.o misc.o timer.o psc.o pinmux.o
    COBJS-$(CONFIG_DA850_LOWLEVEL)    += da850_lowlevel.o
    COBJS-$(CONFIG_SOC_DM355)    += dm355.o
    COBJS-$(CONFIG_SOC_DM365)    += dm365.o

    ------

    ifdef CONFIG_SPL_BUILD
    COBJS-y    += spl.o
    COBJS-$(CONFIG_SOC_DM365)    += dm365_lowlevel.o
    COBJS-$(CONFIG_SOC_DA8XX)    += da850_lowlevel.o
    endif

    I could not find "da850_lowlevel.o under u-boot source tree uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinci after u-boot building,

    Did you changed anything in u-boot source?

    Have you defined "#define CONFIG_DA850_LOWLEVEL" like this or "#define CONFIG_SPL_BUILD "  to compile da850_lowlevel.c file in u-boot def config?

    What is your uboot def config file?

    Also, DDR PHY control register location in u-boot source , uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinc/lowlevel_init.S

        /* Program PHY Control Register */
        ldr    r6, DDRCTL
        ldr    r7, DDRCTL_VAL
        str    r7, [r6]

    -----------

    /* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */
    DDRCTL:
        .word    0x200000e4
    DDRCTL_VAL:
        .word    0x50006405
    SDREF:

    This "DDRCTL_VAL" seems that already u-boot source got errata fix for ESD as you mentioned.

    Ex:

     0x50006405 | 0x2000  =  0x50006405

    Please check your u-boot source code,

    Can you please answer the above questions to proceed further.

  • Hi,

    Thanks for the info. We use our own config that is very similar to da850evm.h. Here's the config specific to our board. Note that the default configuration does not modify the DDL disable bit.

    Yes, I knew, I told you to modify it,

    If you need changes "uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c"

    Remove the  " writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);"  this line and add the below line,

    /* Titus Debug :  Disable DLL REFCLK */
    #if 1
        writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);
        int tmp_val;
        tmp_val = readl(&dv_ddr2_regs_ctrl->ddrphycr);
        tmp_val |= 0x2000;
        writel(tmp_val, &dv_ddr2_regs_ctrl->ddrphycr);
    #endif

    PFA of the same.

    /*
     * SoC-specific lowlevel code for DA850
     *
     * Copyright (C) 2011
     * Heiko Schocher, DENX Software Engineering, hs@denx.de.
     *
     * See file CREDITS for list of people who contributed to this
     * project.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     */
    #include <common.h>
    #include <nand.h>
    #include <ns16550.h>
    #include <post.h>
    #include <asm/arch/da850_lowlevel.h>
    #include <asm/arch/hardware.h>
    #include <asm/arch/davinci_misc.h>
    #include <asm/arch/ddr2_defs.h>
    #include <asm/arch/emif_defs.h>
    #include <asm/arch/pll_defs.h>
    
    #if defined(CONFIG_SYS_DA850_PLL_INIT)
    void da850_waitloop(unsigned long loopcnt)
    {
    	unsigned long	i;
    
    	for (i = 0; i < loopcnt; i++)
    		asm("   NOP");
    }
    
    int da850_pll_init(struct davinci_pllc_regs *reg, unsigned long pllmult)
    {
    	if (reg == davinci_pllc0_regs)
    		/* Unlock PLL registers. */
    		clrbits_le32(&davinci_syscfg_regs->cfgchip0, PLL_MASTER_LOCK);
    
    	/*
    	 * Set PLLENSRC '0',bit 5, PLL Enable(PLLEN) selection is controlled
    	 * through MMR
    	 */
    	clrbits_le32(&reg->pllctl, PLLCTL_PLLENSRC);
    	/* PLLCTL.EXTCLKSRC bit 9 should be left at 0 for Freon */
    	clrbits_le32(&reg->pllctl, PLLCTL_EXTCLKSRC);
    
    	/* Set PLLEN=0 => PLL BYPASS MODE */
    	clrbits_le32(&reg->pllctl, PLLCTL_PLLEN);
    
    	da850_waitloop(150);
    
    	if (reg == davinci_pllc0_regs) {
    		/*
    		 * Select the Clock Mode bit 8 as External Clock or On Chip
    		 * Oscilator
    		 */
    		dv_maskbits(&reg->pllctl, ~PLLCTL_RES_9);
    		setbits_le32(&reg->pllctl,
    			(CONFIG_SYS_DV_CLKMODE << PLLCTL_CLOCK_MODE_SHIFT));
    	}
    
    	/* Clear PLLRST bit to reset the PLL */
    	clrbits_le32(&reg->pllctl, PLLCTL_PLLRST);
    
    	/* Disable the PLL output */
    	setbits_le32(&reg->pllctl, PLLCTL_PLLDIS);
    
    	/* PLL initialization sequence */
    	/*
    	 * Power up the PLL- PWRDN bit set to 0 to bring the PLL out of
    	 * power down bit
    	 */
    	clrbits_le32(&reg->pllctl, PLLCTL_PLLPWRDN);
    
    	/* Enable the PLL from Disable Mode PLLDIS bit to 0 */
    	clrbits_le32(&reg->pllctl, PLLCTL_PLLDIS);
    
    #if defined(CONFIG_SYS_DA850_PLL0_PREDIV)
    	/* program the prediv */
    	if (reg == davinci_pllc0_regs && CONFIG_SYS_DA850_PLL0_PREDIV)
    		writel((PLL_DIVEN | CONFIG_SYS_DA850_PLL0_PREDIV),
    			&reg->prediv);
    #endif
    
    	/* Program the required multiplier value in PLLM */
    	writel(pllmult, &reg->pllm);
    
    	/* program the postdiv */
    	if (reg == davinci_pllc0_regs)
    		writel((PLL_POSTDEN | CONFIG_SYS_DA850_PLL0_POSTDIV),
    			&reg->postdiv);
    	else
    		writel((PLL_POSTDEN | CONFIG_SYS_DA850_PLL1_POSTDIV),
    			&reg->postdiv);
    
    	/*
    	 * Check for the GOSTAT bit in PLLSTAT to clear to 0 to indicate that
    	 * no GO operation is currently in progress
    	 */
    	while ((readl(&reg->pllstat) & PLLCMD_GOSTAT) == PLLCMD_GOSTAT)
    		;
    
    	if (reg == davinci_pllc0_regs) {
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV1, &reg->plldiv1);
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV2, &reg->plldiv2);
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV3, &reg->plldiv3);
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV4, &reg->plldiv4);
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV5, &reg->plldiv5);
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV6, &reg->plldiv6);
    		writel(CONFIG_SYS_DA850_PLL0_PLLDIV7, &reg->plldiv7);
    	} else {
    		writel(CONFIG_SYS_DA850_PLL1_PLLDIV1, &reg->plldiv1);
    		writel(CONFIG_SYS_DA850_PLL1_PLLDIV2, &reg->plldiv2);
    		writel(CONFIG_SYS_DA850_PLL1_PLLDIV3, &reg->plldiv3);
    	}
    
    	/*
    	 * Set the GOSET bit in PLLCMD to 1 to initiate a new divider
    	 * transition.
    	 */
    	setbits_le32(&reg->pllcmd, PLLCMD_GOSTAT);
    
    	/*
    	 * Wait for the GOSTAT bit in PLLSTAT to clear to 0
    	 * (completion of phase alignment).
    	 */
    	while ((readl(&reg->pllstat) & PLLCMD_GOSTAT) == PLLCMD_GOSTAT)
    		;
    
    	/* Wait for PLL to reset properly. See PLL spec for PLL reset time */
    	da850_waitloop(200);
    
    	/* Set the PLLRST bit in PLLCTL to 1 to bring the PLL out of reset */
    	setbits_le32(&reg->pllctl, PLLCTL_PLLRST);
    
    	/* Wait for PLL to lock. See PLL spec for PLL lock time */
    	da850_waitloop(2400);
    
    	/*
    	 * Set the PLLEN bit in PLLCTL to 1 to remove the PLL from bypass
    	 * mode
    	 */
    	setbits_le32(&reg->pllctl, PLLCTL_PLLEN);
    
    
    	/*
    	 * clear EMIFA and EMIFB clock source settings, let them
    	 * run off SYSCLK
    	 */
    	if (reg == davinci_pllc0_regs)
    		dv_maskbits(&davinci_syscfg_regs->cfgchip3,
    			~(PLL_SCSCFG3_DIV45PENA | PLL_SCSCFG3_EMA_CLKSRC));
    
    	return 0;
    }
    #endif /* CONFIG_SYS_DA850_PLL_INIT */
    
    #if defined(CONFIG_SYS_DA850_DDR_INIT)
    int da850_ddr_setup(void)
    {
    	unsigned long	tmp;
    
    	/* Enable the Clock to DDR2/mDDR */
    	lpsc_on(DAVINCI_LPSC_DDR_EMIF);
    
    	tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
    	if ((tmp & VTP_POWERDWN) == VTP_POWERDWN) {
    		/* Begin VTP Calibration */
    		clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN);
    		clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK);
    		setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
    		clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
    		setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
    
    		/* Polling READY bit to see when VTP calibration is done */
    		tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
    		while ((tmp & VTP_READY) != VTP_READY)
    			tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
    
    		setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK);
    		setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN);
    
    		setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN);
    	}
    
    //	writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);
    
    /* Titus Debug :  Disable DLL REFCLK */
    
    /* TODO : Need to print values of PHY register before and after excute */
    
    #if 1
    	writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);
    	int tmp_val;
    	tmp_val = readl(&dv_ddr2_regs_ctrl->ddrphycr);
    	tmp_val |= 0x2000;
    	writel(tmp_val, &dv_ddr2_regs_ctrl->ddrphycr);
    #endif
    
    
    	clrbits_le32(&davinci_syscfg1_regs->ddr_slew,
    		(1 << DDR_SLEW_CMOSEN_BIT));
    
    	/*
    	 * SDRAM Configuration Register (SDCR):
    	 * First set the BOOTUNLOCK bit to make configuration bits
    	 * writeable.
    	 */
    	setbits_le32(&dv_ddr2_regs_ctrl->sdbcr, DV_DDR_BOOTUNLOCK);
    
    	/*
    	 * Write the new value of these bits and clear BOOTUNLOCK.
    	 * At the same time, set the TIMUNLOCK bit to allow changing
    	 * the timing registers
    	 */
    	tmp = CONFIG_SYS_DA850_DDR2_SDBCR;
    	tmp &= ~DV_DDR_BOOTUNLOCK;
    	tmp |= DV_DDR_TIMUNLOCK;
    	writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);
    
    	/* write memory configuration and timing */
    	writel(CONFIG_SYS_DA850_DDR2_SDBCR2, &dv_ddr2_regs_ctrl->sdbcr2);
    	writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr);
    	writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2);
    
    	/* clear the TIMUNLOCK bit and write the value of the CL field */
    	tmp &= ~DV_DDR_TIMUNLOCK;
    	writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);
    
    	/*
    	 * LPMODEN and MCLKSTOPEN must be set!
    	 * Without this bits set, PSC don;t switch states !!
    	 */
    	writel(CONFIG_SYS_DA850_DDR2_SDRCR |
    		(1 << DV_DDR_SRCR_LPMODEN_SHIFT) |
    		(1 << DV_DDR_SRCR_MCLKSTOPEN_SHIFT),
    		&dv_ddr2_regs_ctrl->sdrcr);
    
    	/* SyncReset the Clock to EMIF3A SDRAM */
    	lpsc_syncreset(DAVINCI_LPSC_DDR_EMIF);
    	/* Enable the Clock to EMIF3A SDRAM */
    	lpsc_on(DAVINCI_LPSC_DDR_EMIF);
    
    	/* disable self refresh */
    	clrbits_le32(&dv_ddr2_regs_ctrl->sdrcr,
    		DV_DDR_SDRCR_LPMODEN | DV_DDR_SDRCR_LPMODEN);
    	writel(CONFIG_SYS_DA850_DDR2_PBBPR, &dv_ddr2_regs_ctrl->pbbpr);
    
    	return 0;
    }
    #endif /* CONFIG_SYS_DA850_DDR_INIT */
    
    __attribute__((weak))
    void board_gpio_init(void)
    {
    	return;
    }
    
    int arch_cpu_init(void)
    {
    	/* Unlock kick registers */
    	writel(DV_SYSCFG_KICK0_UNLOCK, &davinci_syscfg_regs->kick0);
    	writel(DV_SYSCFG_KICK1_UNLOCK, &davinci_syscfg_regs->kick1);
    
    	dv_maskbits(&davinci_syscfg_regs->suspsrc,
    		CONFIG_SYS_DA850_SYSCFG_SUSPSRC);
    
    	/* configure pinmux settings */
    	if (davinci_configure_pin_mux_items(pinmuxes, pinmuxes_size))
    		return 1;
    
    #if defined(CONFIG_SYS_DA850_PLL_INIT)
    	/* PLL setup */
    	da850_pll_init(davinci_pllc0_regs, CONFIG_SYS_DA850_PLL0_PLLM);
    	da850_pll_init(davinci_pllc1_regs, CONFIG_SYS_DA850_PLL1_PLLM);
    #endif
    	/* setup CSn config */
    #if defined(CONFIG_SYS_DA850_CS2CFG)
    	writel(CONFIG_SYS_DA850_CS2CFG, &davinci_emif_regs->ab1cr);
    #endif
    #if defined(CONFIG_SYS_DA850_CS3CFG)
    	writel(CONFIG_SYS_DA850_CS3CFG, &davinci_emif_regs->ab2cr);
    #endif
    
    	da8xx_configure_lpsc_items(lpsc, lpsc_size);
    
    	/* GPIO setup */
    	board_gpio_init();
    
    
    	NS16550_init((NS16550_t)(CONFIG_SYS_NS16550_COM1),
    			CONFIG_SYS_NS16550_CLK / 16 / CONFIG_BAUDRATE);
    
    	/*
    	 * Fix Power and Emulation Management Register
    	 * see sprufw3a.pdf page 37 Table 24
    	 */
    	writel((DAVINCI_UART_PWREMU_MGMT_FREE | DAVINCI_UART_PWREMU_MGMT_URRST |
    		DAVINCI_UART_PWREMU_MGMT_UTRST),
    	       &davinci_uart2_ctrl_regs->pwremu_mgmt);
    
    #if defined(CONFIG_SYS_DA850_DDR_INIT)
    	da850_ddr_setup();
    #endif
    
    	return 0;
    }
    

    Please let us know the status.

  • Hi, Dinesh

    Would you please share with us your analysis report? How did you determine this is a failure event caused by ESD? Does an ESD event get manually introudcue onto the board? If this is an ESD test, how do you connect your board ground to the external chassis ground?

    The board is 8 layers, with four being signals and four being GND/Power plane, do you have GND plane for each signal plane? How does the stackup look like?

    Thanks

    David

  • Hi Titus,

    Thanks for the detailed instructions. The code snippet was very helpful but I did have to experiment a little to find out where this had to placed in the sequence. If the DLL is disabled at the beginning of the sequence, the system does not boot. 

    In the GEL sample you provided the DLL is disabled after DDR configuration is complete. After moving the sequence of instructions you provided to the end of ddr_setup() uboot boots successfully. This change also seems to make the system more immune to ESD.

    Thanks again for your assistance.

  • Hi Dinesh,

    Thanks for your update,

    One small correction,

    We have to declare "tmp_value" should be in "unsigned int" and not "int"

    /* Disable DLL REFCLK */
    #if 1
        writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);
        unsigned  int tmp_val;
        tmp_val = readl(&dv_ddr2_regs_ctrl->ddrphycr);
        tmp_val |= 0x2000;
        writel(tmp_val, &dv_ddr2_regs_ctrl->ddrphycr);
    #endif