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.

TMS320C6657: DSP hang-up #2

Part Number: TMS320C6657

Hi,

This is additional post to the original thread which was already locked.
Customer continues investigation and narrowed down exactly when the DVDD15 current difference happened.
Please see updated slides. Page#5 is added.
DSP hang-up2.pdf
On page#5, both waveforms are taken on the same board with the same software.
The left waveform is good case. No issue observed later on.
The right waveform is failing case. DSP hangs-up sometime later (within 10min).

These differences happens in DDR3Init() function in attached evmc6657.c.

/******************************************************************************
 * Copyright (c) 2011-2012 Texas Instruments Incorporated - http://www.ti.com
 * 
 *  Redistribution and use in source and binary forms, with or without 
 *  modification, are permitted provided that the following conditions 
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the   
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *****************************************************************************/

/******************************************************************************
 *
 * File	Name:       evmc6657.c
 *
 * Description: This contains   TMS320C6657 specific functions.
 * 
 ******************************************************************************/
 
/************************
 * Include Files
 ************************/
#include "platform_internal.h"

static void pll_delay(uint32_t ix)
{
    while (ix--) {
        asm("   NOP");
    }
}

int prog_pll1_values(PllcHwSetup *hwSetup)
{
    uint32_t temp;

    /* Check the Range for Multiplier and Divider (error > 63) here */
    if (hwSetup->pllM > 4095)
    {
        return -1;
    }

    if (hwSetup->preDiv > 63)
    {
        return -1;
    }

    /* Set the PLL Multiplier, Divider, BWADJ                                    *
     * The PLLM[5:0] bits of the multiplier are controlled by the PLLM Register  *
     * inside the PLL Controller and the PLLM[12:6] bits are controlled by the   *
     * chip-level MAINPLLCTL0 Register.                                          *
     * PLL Control Register (PLLM)  Layout                                       *
     * |31...6   |5...0        |                                                 *
     * |Reserved |PLLM         |                                                 *
     *                                                                           *
     * Main PLL Control Register (MAINPLLCTL0)                                   *
     * |31...24   |23...19   |18...12    | 11...6   |5...0 |                     *
     * |BWADJ[7:0]| Reserved |PLLM[12:6] | Reserved | PLLD |                     */

    /* Set pll multipler (13 bit field) */
    hPllcRegs->PLLM     = (hwSetup->pllM & 0x0000003F); /* bits[5:0]  */
    temp          = (hwSetup->pllM & 0x1FC0) >> 6;       /* bits[12:6] */
    hBootCfg->CORE_PLL_CTL0  &=~(0x0007F000);                /*Clear PLLM field */
    hBootCfg->CORE_PLL_CTL0  |=((temp << 12) & 0x0007F000);

    /* Set the BWADJ     (12 bit field)                                          *
     * BWADJ[11:8] and BWADJ[7:0] are located in MAINPLLCTL0 and MAINPLLCTL1     *
     * registers. BWADJ[11:0] should be programmed to a value equal to half of   *
     * PLLM[12:0] value (round down if PLLM has an odd value)                    *
     * Example: If PLLM = 15, then BWADJ = 7                                     */
    temp = ((hwSetup->pllM + 1)>> 1) - 1; /* Divide the pllm by 2 */
    hBootCfg->CORE_PLL_CTL0  &=~(0xFF000000);  /* Clear the BWADJ Field */
    hBootCfg->CORE_PLL_CTL0 |=  ((temp << 24) & 0xFF000000);
    hBootCfg->CORE_PLL_CTL1 &=~(0x0000000F);   /* Clear the BWADJ field */
    hBootCfg->CORE_PLL_CTL1 |= ((temp >> 8) & 0x0000000F);

    /* Set the pll divider (6 bit field)                                         *
     * PLLD[5:0] is located in MAINPLLCTL0                                       */
    hBootCfg->CORE_PLL_CTL0   &= ~(0x0000003F);    /* Clear the Field */
    hBootCfg->CORE_PLL_CTL0   |= (hwSetup->preDiv & 0x0000003F);

    /* Set the OUTPUT DIVIDE (4 bit field) in SECCTL */
    hPllcRegs->SECCTL    &= ~(0x00780000);     /* Clear the field       */
    hPllcRegs->SECCTL   |= ((1 << 19) & 0x00780000) ;

    return(0);
}

CSL_Status CorePllcHwSetup (
        PllcHwSetup          *hwSetup
        )
{
    CSL_Status       status = CSL_SOK;
    volatile uint32_t i, loopCount;
    uint32_t temp;

    /* Unlock the Boot Config */
    CSL_BootCfgUnlockKicker();


    /* Wait for Stabilization time (min 100 us)                                *
     * The below loop is good enough for the Gel file to get minimum of        *
     * 100 micro seconds, this should be appropriately modified for port       *
     * to a C function                                                         *
     * Minimum delay in GEL can be 1 milli seconds, so program to 1ms=1000us,  *
     * more than required, but should be Okay                                  */
    pll_delay(140056);

    /* If PLL previously configured in RBL, avoid di/dt supply excursion by    *
     * matching PLL output to RefClk rate                                      *
     * if RBL configures the PLL, the BYPASS bit would be set to '0'           */
    temp = hPllcRegs->SECCTL &  0x00800000; /* Check the Bit 23 value */

    if (temp != 0) {
        /* PLL BYPASS is enabled, we assume if not in Bypass ENSAT = 1 */

        /* Usage Note 9: For optimal PLL operation, the ENSAT bit in the PLL control *
         * registers for the Main PLL, DDR3 PLL, and PA PLL should be set to 1.      *
         * The PLL initialization sequence in the boot ROM sets this bit to 0 and    *
         * could lead to non-optimal PLL operation. Software can set the bit to the  *
         * optimal value of 1 after boot                                             *
         * Ref: http://www.ti.com/lit/er/sprz334b/sprz334b.pdf                       *
         * |31...7   |6     |5 4       |3...0      |                                 *
         * |Reserved |ENSAT |Reserved  |BWADJ[11:8]|                                 */

    	hBootCfg->CORE_PLL_CTL1 = hBootCfg->CORE_PLL_CTL1 | 0x00000040;

        /* Clear PLLEN bit */
    	hPllcRegs-> PLLCTL &= ~(1 << 0);

        /* Clear PLLENSRC bit */
    	hPllcRegs-> PLLCTL &= ~(1 << 5);

        /* Wait for 4 RefClks   *
         * Assuming slowest Ref clock of 25MHz, min: 160 ns delay */
        pll_delay(225);

        /* Bypass needed to perform PWRDN cycle for C6657	                     *
         * Needed on all devices when in NOBOOT, I2C or SPI boot modes               *
         * Ref: Figure 4-2 of http://www.ti.com/lit/ug/sprugv2a/sprugv2a.pdf         *
         * PLL Secondary Control Register (SECCTL)  Layout                           *
         * |31...24  |23     |22...19       |18...0   |                              *
         * |Reserved |BYPASS |OUTPUT DIVIDE |Reserved |                              */

        hPllcRegs->SECCTL |= 0x00800000; /* Set the Bit 23 */

        /* Advisory 8: Multiple PLLs May Not Lock After Power-on Reset Issue         *
         * In order to ensure proper PLL startup, the PLL power_down pin needs to be *
         * toggled. This is accomplished by toggling the PLLPWRDN bit in the PLLCTL  *
         * register. This needs to be done before the main PLL initialization        *
         * sequence                                                                  *
         * Ref: Figure 4-1 of http://www.ti.com/lit/ug/sprugv2a/sprugv2a.pdf         *
         * PLL Control Register (PLLCTL)  Layout                                     *
         * |31...4   |3      |2        |1        |0        |                         *
         * |Reserved |PLLRST |Reserved |PLLPWRDN |Reserved |                         */

        hPllcRegs-> PLLCTL   |= 0x00000002; /*Power Down the PLL */

        /* Stay in a loop such that the bit is set for 5 �s (minimum) and           *
         * then clear the bit.                                                      */

        pll_delay(14005);

        /* Power up the PLL */  
        hPllcRegs-> PLLCTL   &= ~(0x00000002);

    }
	else
	{
        /* Clear PLLEN bit */
    	hPllcRegs-> PLLCTL &= ~(1 << 0);

        /* Clear PLLENSRC bit */
    	hPllcRegs-> PLLCTL &= ~(1 << 5);

        /* Wait for 4 RefClks   *
         * Assuming slowest Ref clock of 25MHz, min: 160 ns delay */
        pll_delay(225);
	}

    /* Program the necessary multipliers/dividers and BW adjustments             */
    prog_pll1_values(hwSetup);

    /* Set PLL dividers if needed */
    hPllcRegs->PLLDIV1_3[1] = (0x8000) | (hwSetup->pllDiv2);
    hPllcRegs->PLLDIV4_16[1] = (0x8000) | (hwSetup->pllDiv5);
    hPllcRegs->PLLDIV4_16[4] = (0x8000) | (hwSetup->pllDiv8);

    /* Program ALNCTLn */
    /* Set bit 1, 4 and 7 */
    hPllcRegs->ALNCTL |= ( (1 << 1) | (1 << 4) | (1 << 7));

    /* Set GOSET bit in PLLCMD to initiate the GO operation to change the divide *
     * values and align the SYSCLKs as programmed                                */
    hPllcRegs->PLLCMD     |= 0x00000001;

    /* go stat bit needs to be zero here    */
    /* Read the GOSTAT bit in PLLSTAT to make sure the bit returns to 0 to      *  
     * indicate that the GO operation has completed                             */
    /* wait for the GOSTAT, but don't trap if lock is never read */

    /*while ((PLL1_STAT & 0x00000001) != 0) {
            gostat_counter++;
        }*/
    for (i = 0; i < 100; i++) {
        pll_delay(300);
        if ( (hPllcRegs->PLLSTAT & 0x00000001) == 0 ) {
            break;
        }
    }
    if (i == 100) {
        return CSL_ESYS_FAIL;
    }

	/* Place PLL in Reset, In PLLCTL, write PLLRST = 1 (PLL is reset)         */
    hPllcRegs-> PLLCTL |= 0x00000008;

    /* Wait for PLL Reset assertion Time (min: 50 us)                          *
     * Minimum delay in GEL can be 1 milli seconds, so program to 1ms=1000us,  *
     * more than required, but should be Okay                                  */
    pll_delay(140050);

    /*In PLLCTL, write PLLRST = 0 to bring PLL out of reset */
    hPllcRegs->PLLCTL &= ~(0x00000008);

    /* 
     * PLL Lock Delay needs to be 500 RefClk periods * (PLLD + 1)
     * i.e., Wait for at least 500 * CLKIN cycles * (PLLD + 1) (PLL lock time)
     * Using 2000 25ns RefClk periods per DM
     * Wait for PLL to lock min 50 micro seconds
     * 
     * */
    pll_delay (140056 >> 1);

    /* In SECCTL, write BYPASS = 0 (enable PLL mux to switch to PLL mode) */
    hPllcRegs->SECCTL &= ~(0x00800000); /* Release Bypass */

    /* In PLLCTL, write PLLEN = 1 (enable PLL controller mux to switch to PLL mode) */
    hPllcRegs->PLLCTL |= (1 << 0);
	
	/* wait for the phase adj */
    pll_delay(1000);

    return status;
}

CSL_Status CorePllcGetHwSetup (
        PllcHwSetup             *hwSetup
        )
{
    CSL_Status       status   = CSL_SOK;
    volatile uint32_t i, loopCount;

    /* Unlock the Boot Config */
    CSL_BootCfgUnlockKicker();

    hwSetup->divEnable = 0;

    hwSetup->pllM       = (hPllcRegs->PLLM & 0x3F);
    hwSetup->preDiv     = hPllcRegs->PREDIV;
    hwSetup->pllDiv2    = hPllcRegs->PLLDIV1_3[1] ;
    hwSetup->pllDiv5    = hPllcRegs->PLLDIV4_16[1];
    hwSetup->pllDiv8    = hPllcRegs->PLLDIV4_16[4];

    /* wait for the GOSTAT, but don't trap if lock is never read */
    for (i = 0; i < 100; i++) {
        pll_delay(300);
        if ( (hPllcRegs->PLLSTAT & 0x00000001) == 0 ) {
            break;
        }
    }
    if (i == 100) {
        return CSL_ESYS_FAIL;
    }

    return status;
}

/***************************************************************************************
 * FUNCTION PURPOSE: Power up all the power domains
 ***************************************************************************************
 * DESCRIPTION: this function powers up the PA subsystem domains
 ***************************************************************************************/
void PowerUpDomains (void)
{
    /* Power Domain Always on*/
    CSL_PSC_enablePowerDomain (CSL_PSC_PD_ALWAYSON);

    /* Enable EMAC Clock*/
    CSL_PSC_setModuleNextState (CSL_PSC_LPSC_EMAC_SS, PSC_MODSTATE_ENABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition (CSL_PSC_PD_ALWAYSON);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (CSL_PSC_PD_ALWAYSON));

    CSL_PSC_getModuleState(CSL_PSC_LPSC_EMAC_SS);
	
	
	
#ifdef PCIE_POWER_DISABLE
    /* PCIe */
    CSL_PSC_enablePowerDomain (CSL_PSC_PD_PCIEX);

    /* Enable PCIe Clock*/
    CSL_PSC_setModuleNextState (CSL_PSC_LPSC_PCIEX, PSC_MODSTATE_ENABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition (CSL_PSC_PD_PCIEX);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (CSL_PSC_PD_PCIEX));

    CSL_PSC_getModuleState(CSL_PSC_LPSC_PCIEX);
#endif
	
	
    /* SRIO */
    CSL_PSC_enablePowerDomain (CSL_PSC_PD_SRIO);

    /* Enable PCIe Clock*/
    CSL_PSC_setModuleNextState (CSL_PSC_LPSC_SRIO, PSC_MODSTATE_ENABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition (CSL_PSC_PD_SRIO);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (CSL_PSC_PD_SRIO));

    CSL_PSC_getModuleState(CSL_PSC_LPSC_SRIO);
	

}

CSL_Status SetDDR3PllConfig(void) 
{

    uint32_t ddr3pllctl0val = hBootCfg->DDR3_PLL_CTL0;
    uint32_t obsclkval = hBootCfg->OBSCLK_CTL;
    uint32_t ddr3_pllm = PLLM_DDR3;
    uint32_t ddr3_plld = PLLD_DDR3;
    uint32_t temp;

    /* Unlock the Boot Config */
    CSL_BootCfgUnlockKicker();

    if (DNUM == 0)
    {
        /* Usage Note 9: For optimal PLL operation, the ENSAT bit in the PLL control *
         * registers for the Main PLL, DDR3 PLL, and PA PLL should be set to 1.      *
         * The PLL initialization sequence in the boot ROM sets this bit to 0 and    *
         * could lead to non-optimal PLL operation. Software can set the bit to the  *
         * optimal value of 1 after boot                                             *
         * DDR3PLLCTL1_REG Bit map                                                   *
         * |31...7   |6     |5 4       |3...0      |                                 *
         * |Reserved |ENSAT |Reserved  |BWADJ[11:8]|                                 */

    	hBootCfg->DDR3_PLL_CTL1 |= 0x00000040;

        /* Wait for the PLL Reset time (min: 1000 ns)                                */
        /*pll_delay(1400);*/

        /* Put the PLL in Bypass Mode                                                *
         * DDR3PLLCTL0_REG Bit map                                                     *
         * |31...24    |23     |22...19       |18...6   |5...0 |                     *
         * |BWADJ[7:0] |BYPASS |Reserved      |PLLM     |PLLD  |                     */

    	hBootCfg->DDR3_PLL_CTL0 |= 0x00800000; /* Set the Bit 23 */

        /* Set the Multipler values */
        hBootCfg->DDR3_PLL_CTL0 &= ~(0x0007FFC0);
        hBootCfg->DDR3_PLL_CTL0 |= ((ddr3_pllm << 6) & 0x0007FFC0 );
        /* Program the necessary multipliers/dividers and BW adjustments             */
        /* Set the divider values */
        hBootCfg->DDR3_PLL_CTL0 &= ~(0x0000003F);
        hBootCfg->DDR3_PLL_CTL0 |= (ddr3_plld & 0x0000003F);

        /* Set the BWADJ */
        temp = ((ddr3_pllm + 1) >> 1) - 1;
        hBootCfg->DDR3_PLL_CTL0 &= ~(0xFF000000);
        hBootCfg->DDR3_PLL_CTL0 |= ((temp << 24) & 0xFF000000);
        hBootCfg->DDR3_PLL_CTL1 &= ~(0x0000000F);
        hBootCfg->DDR3_PLL_CTL1 |= ((temp >> 8) & 0x0000000F);

        /* In PLL Controller, reset the PLL (bit 13) in DDR3PLLCTL1_REG register       */
    	hBootCfg->DDR3_PLL_CTL1 |= 0x00002000;

        /*Wait for PLL to lock min 5 micro seconds*/
        pll_delay(7000);

        /*In DDR3PLLCTL1_REG, write PLLRST = 0 to bring PLL out of reset */
        hBootCfg->DDR3_PLL_CTL1 &= ~(0x00002000);

        /*Wait for PLL to lock min 50 micro seconds*/
        pll_delay(70000);

        /* Put the PLL in PLL Mode                                                   *
         * DDR3PLLCTL0_REG Bit map                                                   *
         * |31...24    |23     |22...19       |18...6   |5...0 |                     *
         * |BWADJ[7:0] |BYPASS |Reserved      |PLLM     |PLLD  |                     */
        hBootCfg->DDR3_PLL_CTL0 &= ~(0x00800000); /* ReSet the Bit 23 */

        ddr3pllctl0val = hBootCfg->DDR3_PLL_CTL0;

        /* Tells the multiplier value for the DDR3 PLL */
        ddr3_pllm = (((ddr3pllctl0val & 0x0007FFC0) >> 6) + 1);
        IFPRINT(platform_write("DDR3 PLL programmable multiplier = %d\n", ddr3_pllm));

        /* Tells the divider value for the DDR3 PLL */
        ddr3_plld = (((ddr3pllctl0val & 0x0000003F) >> 0) +1);
        IFPRINT(platform_write("DDR3 PLL programmable divider = %d\n", ddr3_plld));

        IFPRINT(platform_write("PLL2 Setup... Done.\n" ));

        return CSL_SOK;

    }
    else
    {
        IFPRINT(platform_write("DSP core #%d cannot set DDR3 PLL \n", DNUM));
        return CSL_ESYS_FAIL;
    }
}


/*--------------------------------------------------------------*/
/* xmc_setup()                                                  */
/* XMC MPAX register setting to access DDR3 config space        */
/*--------------------------------------------------------------*/
void xmc_setup()
{  
    /* mapping for ddr emif registers XMPAX*2 */
    CSL_XMC_XMPAXL    mpaxl;
    CSL_XMC_XMPAXH    mpaxh;

    /* base addr + seg size (64KB)*/    //"1B"-->"B" by xj */
    mpaxh.bAddr     = (0x2100000B >> 12);
    mpaxh.segSize   = (0x2100000B & 0x0000001F);

    /* replacement addr + perm*/
    mpaxl.rAddr     = 0x100000;
    mpaxl.sr        = 1;
    mpaxl.sw        = 1;
    mpaxl.sx        = 1;
    mpaxl.ur        = 1;
    mpaxl.uw        = 1;
    mpaxl.ux        = 1;

    /* set the xmpax for index2 */
    CSL_XMC_setXMPAXH(2, &mpaxh);
    CSL_XMC_setXMPAXL(2, &mpaxl);    
}

/* Set the desired DDR3 configuration -- assumes 66.67 MHz DDR3 clock input */
CSL_Status DDR3Init(uint8_t ddr) 
{

    CSL_Status status = CSL_SOK;    
    volatile unsigned int loopCount;
    uint32_t ddr3config, ddrPhyCtrl;
    uint8_t ddrPHYReadLatency;
    EMIF4F_TIMING1_CONFIG sdram_tim1;
    EMIF4F_TIMING2_CONFIG sdram_tim2;
    EMIF4F_TIMING3_CONFIG sdram_tim3;
    EMIF4F_OUTPUT_IMP_CONFIG    zqcfg;
    EMIF4F_PWR_MGMT_CONFIG      pwrmgmtcfg;
    EMIF4F_SDRAM_CONFIG         sdramcfg;

    CSL_BootCfgUnlockKicker();        

    /* Wait for PLL to lock = min 500 ref clock cycles. 
       With refclk = 100MHz, = 5000 ns = 5us */
    platform_delaycycles(50000);

    /**************** 3.3 Leveling Register Configuration ********************/
    CSL_BootCfgGetDDRConfig(0, &ddr3config);
    ddr3config &= ~(0x007FE000);  // clear ctrl_slave_ratio field
    CSL_BootCfgSetDDRConfig(0, ddr3config);

    CSL_BootCfgGetDDRConfig(0, &ddr3config);
    ddr3config |= 0x00200000;     // set ctrl_slave_ratio to 0x100
    CSL_BootCfgSetDDRConfig(0, ddr3config);

    CSL_BootCfgGetDDRConfig(12, &ddr3config);
    ddr3config |= 0x08000000;    // Set invert_clkout = 1
    CSL_BootCfgSetDDRConfig(12, ddr3config);

    CSL_BootCfgGetDDRConfig(0, &ddr3config);
    ddr3config |= 0xF;            // set dll_lock_diff to 15
    CSL_BootCfgSetDDRConfig(0, ddr3config);

    CSL_BootCfgGetDDRConfig(23, &ddr3config);
    ddr3config |= 0x00000200;    // See section 4.2.1, set for partial automatic levelling
    CSL_BootCfgSetDDRConfig(23, ddr3config);

    /**************** 3.3 Partial Automatic Leveling ********************/
	if (ddr & PLATFORM_EVM6657L)
	{
	    ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(2,  ddr3config);
        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(3,  ddr3config);
        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(4,  ddr3config);
        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(5,  ddr3config);
        ddr3config = 0x00000033;  CSL_BootCfgSetDDRConfig(6,  ddr3config);
        ddr3config = 0x0000003A;  CSL_BootCfgSetDDRConfig(7,  ddr3config);
        ddr3config = 0x0000002C;  CSL_BootCfgSetDDRConfig(8,  ddr3config);
        ddr3config = 0x0000002C;  CSL_BootCfgSetDDRConfig(9,  ddr3config);
        ddr3config = 0x0000001C;  CSL_BootCfgSetDDRConfig(10, ddr3config);

        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(14,  ddr3config);
        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(15,  ddr3config);
        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(16,  ddr3config);
        ddr3config = 0x00;        CSL_BootCfgSetDDRConfig(17,  ddr3config);
        ddr3config = 0x000000B7;  CSL_BootCfgSetDDRConfig(18,  ddr3config);
        ddr3config = 0x000000B1;  CSL_BootCfgSetDDRConfig(19,  ddr3config);
        ddr3config = 0x000000A4;  CSL_BootCfgSetDDRConfig(20,  ddr3config);
        ddr3config = 0x000000A4;  CSL_BootCfgSetDDRConfig(21,  ddr3config);
        ddr3config = 0x00000098;  CSL_BootCfgSetDDRConfig(22,  ddr3config);
	}
	else
	{
#if 0
        ddr3config = 0x0000004D;  CSL_BootCfgSetDDRConfig(2,  ddr3config);
        ddr3config = 0x0000004C;  CSL_BootCfgSetDDRConfig(3,  ddr3config);
        ddr3config = 0x0000005E;  CSL_BootCfgSetDDRConfig(4,  ddr3config);
        ddr3config = 0x0000005D;  CSL_BootCfgSetDDRConfig(5,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(6,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(7,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(8,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(9,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(10, ddr3config);

        ddr3config = 0x00000086;  CSL_BootCfgSetDDRConfig(14,  ddr3config);
        ddr3config = 0x00000088;  CSL_BootCfgSetDDRConfig(15,  ddr3config);
        ddr3config = 0x00000096;  CSL_BootCfgSetDDRConfig(16,  ddr3config);
        ddr3config = 0x00000097;  CSL_BootCfgSetDDRConfig(17,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(18,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(19,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(20,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(21,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(22,  ddr3config);
#else
        //Anise design
        ddr3config = 0x00000082;  CSL_BootCfgSetDDRConfig(2,  ddr3config);
        ddr3config = 0x00000085;  CSL_BootCfgSetDDRConfig(3,  ddr3config);
        ddr3config = 0x00000080;  CSL_BootCfgSetDDRConfig(4,  ddr3config);
        ddr3config = 0x0000007E;  CSL_BootCfgSetDDRConfig(5,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(6,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(7,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(8,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(9,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(10, ddr3config);

        ddr3config = 0x000000BC;  CSL_BootCfgSetDDRConfig(14,  ddr3config);
        ddr3config = 0x000000B9;  CSL_BootCfgSetDDRConfig(15,  ddr3config);
        ddr3config = 0x000000BE;  CSL_BootCfgSetDDRConfig(16,  ddr3config);
        ddr3config = 0x000000C0;  CSL_BootCfgSetDDRConfig(17,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(18,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(19,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(20,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(21,  ddr3config);
        ddr3config = 0x00000000;  CSL_BootCfgSetDDRConfig(22,  ddr3config);
#endif
	}
	
	/* Errata Advisory 29 */
	ddr3config = (0x01000000);  // clear ctrl_slave_ratio field
    CSL_BootCfgSetDDRConfig(1, ddr3config);
	
    /*Do a PHY reset. Toggle DDR_PHY_CTRL_1 bit 15 0->1->0 */
    CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency);
    ddrPhyCtrl &= ~(0x00008000 >> 5);
    CSL_EMIF4F_SetPhyControl(ddrPhyCtrl,  ddrPHYReadLatency);

    CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency);
    ddrPhyCtrl |= (0x00008000 >> 5);
    CSL_EMIF4F_SetPhyControl(ddrPhyCtrl,  ddrPHYReadLatency);

    CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency);
    ddrPhyCtrl &= ~(0x00008000 >> 5);
    CSL_EMIF4F_SetPhyControl(ddrPhyCtrl,  ddrPHYReadLatency);

    /***************** 3.4 Basic Controller and DRAM configuration ************/
    /* enable configuration */
    /*    hEmif->SDRAM_REF_CTRL    = 0x00005161; */
    CSL_EMIF4F_EnableInitRefresh();
    CSL_EMIF4F_SetRefreshRate(0x5161);

	/*    hEmif->SDRAM_TIM_1   = 0x1113783C; */
    sdram_tim1.t_wtr    = 4;
    sdram_tim1.t_rrd    = 7;
    sdram_tim1.t_rc     = 0x20;
    sdram_tim1.t_ras    = 0x17;
    sdram_tim1.t_wr     = 0x09;
    sdram_tim1.t_rcd    = 0x08;
    sdram_tim1.t_rp     = 0x08;
    CSL_EMIF4F_SetTiming1Config(&sdram_tim1);

    /*    hEmif->SDRAM_TIM_2   = 0x30717FE3; */
    sdram_tim2.t_cke    = 3;
    sdram_tim2.t_rtp    = 4;
    sdram_tim2.t_xsrd   = 0x1FF;
    sdram_tim2.t_xsnr   = 0x071;
    sdram_tim2.t_xp     = 3;
    sdram_tim2.t_odt    = 0;
    CSL_EMIF4F_SetTiming2Config (&sdram_tim2);

    /*    hEmif->SDRAM_TIM_3   = 0x559F86AF; */
    sdram_tim3.t_rasMax     = 0xF;
    sdram_tim3.t_rfc        = 0x06A;
    sdram_tim3.t_tdqsckmax  = 0;
    sdram_tim3.zq_zqcs      = 0x3F;
    sdram_tim3.t_ckesr      = 4;
    sdram_tim3.t_csta       = 0x5;
    sdram_tim3.t_pdll_ul    = 0x5;
    CSL_EMIF4F_SetTiming3Config (&sdram_tim3);

    /*    hEmif->DDR_PHY_CTRL_1   = 0x0010010F; */
    ddrPHYReadLatency   = 0x0F;
    ddrPhyCtrl          = (0x0010010F >> 5);
    CSL_EMIF4F_SetPhyControl(ddrPhyCtrl,  ddrPHYReadLatency);

    /*    hEmif->ZQ_CONFIG        = 0x70074C1F; */
    zqcfg.zqRefInterval     = 0x4C1F;
    zqcfg.zqZQCLMult        = 3;
    zqcfg.zqZQCLInterval    = 1;
    zqcfg.zqSFEXITEn        = 1;
    zqcfg.zqDualCSEn        = 1;
    zqcfg.zqCS0En           = 1;
    zqcfg.zqCS1En           = 0;
    CSL_EMIF4F_SetOutputImpedanceConfig(&zqcfg);

    /*    hEmif->PWR_MGMT_CTRL    = 0x0; */
    pwrmgmtcfg.csTime           = 0;
    pwrmgmtcfg.srTime           = 0;
    pwrmgmtcfg.lpMode           = 0;
    pwrmgmtcfg.dpdEnable        = 0;
    pwrmgmtcfg.pdTime           = 0;
    CSL_EMIF4F_SetPowerMgmtConfig  (&pwrmgmtcfg);

    /* New value with DYN_ODT disabled and SDRAM_DRIVE = RZQ/7 */
    /*    hEmif->SDRAM_CONFIG     = 0x62466AB2; */
    CSL_EMIF4F_GetSDRAMConfig (&sdramcfg);
    sdramcfg.pageSize           = 2;
    sdramcfg.eBank              = 0;
    sdramcfg.iBank              = 3;
    sdramcfg.rowSize            = 5;
    sdramcfg.CASLatency         = 10;
    sdramcfg.narrowMode         = 1;
    sdramcfg.CASWriteLat        = 2;
    sdramcfg.SDRAMDrive         = 1;
    sdramcfg.disableDLL         = 0;
    sdramcfg.dynODT             = 2;
    sdramcfg.ddrDDQS            = 0;
    sdramcfg.ddrTerm            = 2;
    sdramcfg.iBankPos           = 0;
    sdramcfg.type               = 3;
    CSL_EMIF4F_SetSDRAMConfig (&sdramcfg);

    pll_delay(840336); /*Wait 600us for HW init to complete*/

    /* Refresh rate = (7.8*666MHz] */
    /*    hEmif->SDRAM_REF_CTRL   = 0x00001458;     */
    CSL_EMIF4F_SetRefreshRate(0x00001458);

    /***************** 4.2.1 Partial automatic leveling ************/
    /* http://www.ti.com/lit/an/sprabl2d/sprabl2d.pdf	*/
    /* 3.2.1 Executing Partial Automatic Leveling		*/

    /*    DDR3_CONFIG_REG_52 |= 0x00000200; */
    CSL_BootCfgGetDDRConfig(52, &ddr3config);
    ddr3config |= (0x00000200);
    CSL_BootCfgSetDDRConfig(52, ddr3config);
	/*    DDR3_CONFIG_REG_53 |= 0x00000200; */
    CSL_BootCfgGetDDRConfig(53, &ddr3config);
    ddr3config |= (0x00000200);
    CSL_BootCfgSetDDRConfig(53, ddr3config);
	/*    DDR3_CONFIG_REG_54 |= 0x00000200; */
    CSL_BootCfgGetDDRConfig(54, &ddr3config);
    ddr3config |= (0x00000200);
    CSL_BootCfgSetDDRConfig(54, ddr3config);
	/*    DDR3_CONFIG_REG_55 |= 0x00000200; */
    CSL_BootCfgGetDDRConfig(55, &ddr3config);
    ddr3config |= (0x00000200);
    CSL_BootCfgSetDDRConfig(55, ddr3config);
	/*    DDR3_CONFIG_REG_60 |= 0x00000200; */
    CSL_BootCfgGetDDRConfig(60, &ddr3config);
    ddr3config |= (0x00000200);
    CSL_BootCfgSetDDRConfig(60, ddr3config);

    
    /***************** 4.2.1 Partial automatic leveling ************/
    /*    hEmif->RDWR_LVL_RMP_CTRL      =  0x80000000; */
    CSL_EMIF4F_SetLevelingRampControlInfo(1, 0, 0, 0, 0);

    /* Trigger full leveling - This ignores read DQS leveling result and uses ratio forced value */
    /*    hEmif->RDWR_LVL_CTRL          =  0x80400000; */
    CSL_EMIF4F_SetLevelingControlInfo(1, 0, 64, 0, 0);

    /************************************************************
      Wait for min 1048576 DDR clock cycles for leveling to complete
      = 1048576 * 1.5ns = 1572864ns = 1.57ms.
      Actual time = ~10-15 ms
     **************************************************************/
    pll_delay(4201680); //Wait 3ms for leveling to complete

    // wait for STATUS register
    while(1)
	{
		// Debug log output
		IFPRINT(platform_write("IFRDY = %d, WRLVLT0 = %d, RDLVLT0 = %d, RDLVGATET0 = %d\n", 
		                       CSL_EMIF4F_IsDDRPhyRead(),
		                       CSL_EMIF4F_IsWriteLevelingTimeout(),
		                       CSL_EMIF4F_IsReadDataEyeTrainingTimeout(),
		                       CSL_EMIF4F_IsReadDQSGateTrainingTimeout()));
		
		// Return error if either WRLVLT0, RDLVLT0 or RDLVGATET0 is timeout
		if( CSL_EMIF4F_IsWriteLevelingTimeout()       || 
			CSL_EMIF4F_IsReadDataEyeTrainingTimeout() || 
			CSL_EMIF4F_IsReadDQSGateTrainingTimeout()   )
		{
			return CSL_ESYS_FAIL;
		}
		
		// Exist loop if IFRDY =1
		if( CSL_EMIF4F_IsDDRPhyRead() )
		{
			break;
		}
		
	}
    
    return (status);

}

The code run at initialization sequence after reset.
The red arrow in the waveform is the timing when below code (line#719) is executed.

    /* Trigger full leveling - This ignores read DQS leveling result and uses ratio forced value */
    /*    hEmif->RDWR_LVL_CTRL          =  0x80400000; */
    CSL_EMIF4F_SetLevelingControlInfo(1, 0, 64, 0, 0);

I guess something wrong in leveling in the right case and leveling may be failed.
There is a bug relating to DDR Automatic Leveling (Advisory 3), but it seems the code sequence follows Workaround#1 (Partial Automatic Leveling).

Is there any suspicious point in the DDRInit() sequence?
Or any points customer should check on their board?

Thanks and regards,
Koichiro Tashiro

  • Hi Koichiro,

    My apologies for the long delay.  I've reviewed the documents and I believe that the C6657 is not leveling correctly in all instances leading to a bad access to the memory. The reasons for the leveling failures are multiple and we need to start working through the possibilities. 

    On the C6657 technical documents tab you will find the KeyStone I DDR3 interface bring-up document.  This document has a number of spreadsheets that need to be populated so we can evaluate each step of the design process for any possible reason for the failure. 

    One additional question is on the bootmode selected.  You made some assumptions on page 3 you identify a number of steps in the bootloader.  I am assuming the bootloader code would be loaded after the ROM bootcode has finished and bootcomplete released.  How are you setting the bootmode pins?

    Regards, Bill

  • Hi Bill,

    Thanks for your reply.
    I asked customer to fill these spreadsheets and check anything is wrong in the design.
    Please wait for a while.

    Regarding boot mode, SPI boot mode is used.

    Thanks and regards,
    Koichiro Tashiro

  • Hi Bill,

    I got partial results of SPRACL8_KeyStone DDR3 Length Rules Template v1p0.xlsx.
    I sent the file to you offline.

    As you can see many signals are filed in “ACCC Groups Length Rules” and “Data Group Length Rules”.
    “Layout Checklist” sheet will be checked later.

    Customer afraid layout mismatch causes this issue, but they are not sure this is the exact root cause of the issue customer observes.
    Is there any way to confirm the leveling is failed by checking status register, etc.?

    Thanks and regards,
    Koichiro Tashiro

  • Hi Koichiro,

    Unfortunately the DDR status registers only indicate if the leveling has completed.  It does not indicate if the leveling has completed successfully.  If the initialization completes but the layout does not meet the guideline published, the leveling values may cause errors to occur while accessing the memory.  

    Regards, Bill