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.

c6657 partial leveling fails when use smartflex enabled

Hello,

We are working on C6657 DSP using MT41J128M16JT-125:K.  The input clock is 66.67 MHZ.

We used full automatic leveling in our design. But  using the smartflex that reduce the core voltage to 0.95 then  DDR3 is stable only when the core operates in 850 MHz. In 1 GHz the DDR3 is unstable.  We do not touch the frequency of DDR3. Operates at 1333 Mhz. This is very strange.

Do you have any impression for what reason this happens?

I really appreciate if you make a review in our code and mentioned to us if something goes wrong. Regarding our design theses the lengths

DQS4 (C665x DQS0) 0.000 1.039
CK_4 (C665x CK_0) 0.000 1.529
DQS5 (C665x DQS1) 0.000 1.030
CK_5 (C665x CK_1) 0.000 0.000
DQS6 (C665x DQS2) 0.000 1.576
CK_6 (C665x CK_2) 0.000 0.000
DQS7 (C665x DQS3) 0.000 1.555

 

 

The configuration of our board is the following 

SDCFG Configuration Register
Settings Selected
  Corresponding Register Value (decimal) Corresponding Register Value (hex)
IBANK_POS 8 banks open for interleaving   0 0
DDR_TERM RZQ/6   3 3
DYN_ODT Turn Off Dynamic ODT   0 0
SDRAM_DRIVE RZQ/7   1 1
CWL CWL = 7   2 2
NM 64-bit bus width   0 0
CL CAS = 9   10 A
ROWSIZE 14 row bits   5 5
IBANK 8 bank SDRAM   3 3
EBANK Use DCE0# for all SDRAM accesses   0 0
PAGESIZE 1024-word page   2 2
Refresh Configuration 
SDRFC Configuration Selected
Datasheet Values /
 Settings
Units Corresponding Register Value (decimal) Corresponding Register Value (hex)
INITREF_DIS Normal Operation   0 0
SRT Normal Temp Range   0 0
ASR Manual self-refresh   0 0
PASR Full Array   0 0
REFRESH_PERIOD - Normal 7.81 us 5208 1458
REFRESH_PERIOD - Ext. Temp 3.91 us 2604 0A2C
REFRESH_PERIOD - Initialization 31.25 us 20833 5161

 

Using the excel DDR3 PHY Calc v11 and DDR3 Register Calc v4 we try to configure the PLL

 

Following the examples in ssprabl2d.pdf we set the registers  

 

# if defined PARTIAL_LEVELING
CSL_BootCfgGetDDRConfig(23, &ddr3config);

ddr3config |= 0x00000200; // See section 4.2.1, set for partial automatic levelling

# endif

/**************** 3.3 Partial Automatic Leveling ********************/
//NOTE:: Document ssprabl2d.pdf as reference
//NOTE:: the DATA0_PHY_WRLVL_INIT_RATIO to
// DATA8_PHY_WRLVL_INIT_RATIO fields of the DDR3_CONFIG_2 to DDR3_CONFIG_10 registersy
ddr3config = 0x00000000; CSL_BootCfgSetDDRConfig(2, ddr3config);
ddr3config = 0x00000000; CSL_BootCfgSetDDRConfig(3, ddr3config);
ddr3config = 0x00000000; CSL_BootCfgSetDDRConfig(4, ddr3config);
ddr3config = 0x0000004E; 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);

// NOTE:: initial values into the DATA0_PHY_GATELVL_RATIO to
// DATA8_PHY_GATELVL_RATIO fields of the DDR3_CONFIG_14 to DDR3_CONFIG_22 registers
// respectively. (See the tables in sections Section 4.43 to Section 4.51.)
ddr3config = 0x00000000; CSL_BootCfgSetDDRConfig(14, ddr3config);
ddr3config = 0x00000000; CSL_BootCfgSetDDRConfig(15, ddr3config);
ddr3config = 0x00000000; CSL_BootCfgSetDDRConfig(16, ddr3config);
ddr3config = 0x0000008A; 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);



/***************** 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 = 0x80000000; */
CSL_EMIF4F_SetLevelingControlInfo(1, 0, 0, 0, 0);

/************************************************************
Wait for min 1048576 DDR clock cycles for leveling to complete
= 1048576 * 1.5ns = 1572864ns = 1.57ms.
Actual time = ~10-15 ms
**************************************************************/
cycles_delay(4201680); //Wait 3ms for leveling to complete
# if defined PARTIAL_LEVELING
hEmif->RDWR_LVL_RMP_WIN = 0x00000502;
hEmif->RDWR_LVL_RMP_CTRL = 0x80000000;
hEmif->RDWR_LVL_CTRL = 0xFF090900;


Please find the attachment the source code.

Thank you in advance

 

 

 

 

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();

     // NOTE: document http://www.ti.com/lit/ug/sprugv2g/sprugv2g.pdf
     // Section 3.1.1
    /* 1. 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                                  */
    cycles_delay(140056);

    /* 2. 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 */
    {
        /* 2a. 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;

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

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

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

        /* 2e. 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 */

        /* 2f. 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 */

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

        cycles_delay(14005);

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

    }
    else
    {
        /* 3. Enable BYPASS in the PLL contoller */

        /* 3a. Clear PLLEN bit (bypass enabled in PLL controller mux) */
        hPllcRegs->PLLCTL &= ~(1 << 0);

        /* 3b. Clear PLLENSRC bit (enable PLLEN to control PLL controller mux) */
        hPllcRegs->PLLCTL &= ~(1 << 5);

        /* 3c. Wait for 4 RefClks (to make sure the PLL controller *
         * mux switches properly to bypass)                        *
         * Assuming slowest Ref clock of 25MHz, min: 160 ns delay  */
        cycles_delay(225);
    }

    /* 4, 5, 6 and 7 are done here:                                              *
     * Program the necessary multipliers/dividers and BW adjustments             */
    prog_pll1_values(hwSetup);

    /* 8. Set PLL dividers if needed */

    /* part of 8, 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                */
    for (i = 0; i < 100; i++) {
        cycles_delay(300);
        if ( (hPllcRegs->PLLSTAT & 0x00000001) == 0 ) {
            break;
        }
    }
    if (i == 100) {
        return CSL_ESYS_FAIL;
    }

    /* part of 8, 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);

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

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

    /* part of 8, 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                           */
    for (i = 0; i < 100; i++) {
        cycles_delay(300);
        if ( (hPllcRegs->PLLSTAT & 0x00000001) == 0 ) {
            break;
        }
    }
    if (i == 100) {
        return CSL_ESYS_FAIL;
    }

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

    /* 10. Wait for PLL Reset assertion Time (min: 7 us)                         */
    cycles_delay (14006);

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

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

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

    /* 14. In PLLCTL, write PLLEN = 1 (enable PLL contoller mux to switch to PLL mode) */
    hPllcRegs->PLLCTL |= (1 << 0);

    /* 15. The PLL and PLL Controller are now initialized in PLL mode - Completed. */

    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++) {
        cycles_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)
{
    CSL_PSC_MODSTATE mdstat;

    /* 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));

    mdstat = CSL_PSC_getModuleState(CSL_PSC_LPSC_EMAC_SS);
    if(mdstat ){}
}

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();
    // NOTE: DDR3 PLL Initialization Sequence
    // document http://www.ti.com/lit/ug/sprugv2g/sprugv2g.pdf section 3.5
    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)                                */
        /*cycles_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 */

        /*Wait 4 cycles for the slowest of PLLOUT or reference clock source (CLKIN)*/
        /*cycles_delay(4);*/

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

        /* 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 Multipler values */
        hBootCfg->DDR3_PLL_CTL0 &= ~(0x0007FFC0);
        hBootCfg->DDR3_PLL_CTL0 |= ((ddr3_pllm << 6) & 0x0007FFC0 );

        /* 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*/
        cycles_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*/
        cycles_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()
{

    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);

#	if defined     PARTIAL_LEVELING
    CSL_BootCfgGetDDRConfig(23, &ddr3config);

    ddr3config |= 0x00000200;    // See section 4.2.1, set for partial automatic levelling

#	endif

    /**************** 3.3 Partial Automatic Leveling ********************/
    	//NOTE::  Document ssprabl2d.pdf as reference
       //NOTE::   the DATA0_PHY_WRLVL_INIT_RATIO to
       // DATA8_PHY_WRLVL_INIT_RATIO fields of the DDR3_CONFIG_2 to DDR3_CONFIG_10 registersy
       ddr3config = 0x00000000;        CSL_BootCfgSetDDRConfig(2,  ddr3config);
       ddr3config = 0x00000000;        CSL_BootCfgSetDDRConfig(3,  ddr3config);
       ddr3config = 0x00000000;        CSL_BootCfgSetDDRConfig(4,  ddr3config);
       ddr3config = 0x0000004E;       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);

       // NOTE::  initial values into the DATA0_PHY_GATELVL_RATIO to
       // DATA8_PHY_GATELVL_RATIO fields of the DDR3_CONFIG_14 to DDR3_CONFIG_22 registers
       // respectively. (See the tables in sections Section 4.43 to Section 4.51.)
       ddr3config = 0x00000000;        CSL_BootCfgSetDDRConfig(14,  ddr3config);
       ddr3config = 0x00000000;        CSL_BootCfgSetDDRConfig(15,  ddr3config);
       ddr3config = 0x00000000;        CSL_BootCfgSetDDRConfig(16,  ddr3config);
       ddr3config = 0x0000008A;        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);



    /*Do a PHY reset. Toggle DDR_PHY_CTRL_1 bit 15 0->1->0 */
    CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency);
    ddrPhyCtrl &= ~(0x00008000);
    CSL_EMIF4F_SetPhyControl(ddrPhyCtrl,  ddrPHYReadLatency);

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

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

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

    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   = 0x40877FEC; */
    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   = 0x55BF87FF; */
    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; */
    //Maximum value possible = CAS latency + 7
    // RL = AL + CL
    ddrPHYReadLatency   = 0x0F;
    ddrPhyCtrl          = (0x0010010F);
    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     = 0x63077AB3; */
    CSL_EMIF4F_GetSDRAMConfig (&sdramcfg);

#	if defined CHIP_6654 || CHIP_6657
    //NOTE:check this again
    sdramcfg.pageSize           = 2; //2;
#	else
	#error MKSTR(__FILE__)  MKSTR(__LINE__)
#	endif
    sdramcfg.eBank              = 0;
    sdramcfg.iBank              = 3;
    sdramcfg.rowSize            = 5;
    sdramcfg.CASLatency         = 10;
    sdramcfg.narrowMode         = 1;

#	if defined CHIP_6654 || CHIP_6657
    sdramcfg.CASWriteLat        = 2; //
#	else
	#error MKSTR(__FILE__)  MKSTR(__LINE__)
#	endif
    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);

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

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

    /***************** 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          =  0x80000000; */
    CSL_EMIF4F_SetLevelingControlInfo(1, 0, 0, 0, 0);

    /************************************************************
      Wait for min 1048576 DDR clock cycles for leveling to complete
      = 1048576 * 1.5ns = 1572864ns = 1.57ms.
      Actual time = ~10-15 ms
     **************************************************************/
    cycles_delay(4201680); //Wait 3ms for leveling to complete
#	if defined PARTIAL_LEVELING
    hEmif->RDWR_LVL_RMP_WIN  = 0x00000502;
	hEmif->RDWR_LVL_RMP_CTRL = 0x80000000;
	hEmif->RDWR_LVL_CTRL 	 = 0xFF090900;
#	else
    //http://www.ti.com/lit/an/sprabl2d/sprabl2d.pdf
    //Full  leveling example 25
    hEmif->RDWR_LVL_RMP_WIN  = 0x00000000;
    hEmif->RDWR_LVL_RMP_CTRL = 0x80000000;
    hEmif->RDWR_LVL_CTRL 	 = 0x7F090900;

    //cycles_delay(12500000);
    //wait 500 ms before disable Incremental leveling
   cycles_delay(500000000);
    hEmif->RDWR_LVL_RMP_CTRL = 0x0;
    hEmif->RDWR_LVL_CTRL 	 = 0x0;

#	endif
    return (status);

}

/******************************************************************************
 * platform_get_frequency
 *
 * Internal function to read frequency from PLL.
 *
 ******************************************************************************/
static inline uint32_t platform_get_frequency(void)
{
    CSL_Status      status;
    PllcHwSetup     hwSetupRead;
    uint32_t        dsp_freq;

    status = CorePllcGetHwSetup (&hwSetupRead);

    if (status != CSL_SOK) {
        IFPRINT(platform_write("platform_get_info: Hardware setup parameters reading... Failed.\n"));
        IFPRINT(platform_write("\tReason: Error setting in hardware validation."\
                " [status = 0x%x].\n", status));
        platform_errno = PLATFORM_ERRNO_GENERIC;
        return (uint32_t)-1;
    } else {
        /* Compute the real dsp freq (*100) */
        dsp_freq = (hwSetupRead.pllM + 1)>> 1;
        dsp_freq = (dsp_freq * PLATFORM_BASE_CLK_RATE_MHZ)/(hwSetupRead.preDiv + 1);
    }

    return (dsp_freq);
}

Bool serial_num_isvalid ( char c )
{
    if (
        ((c >= '0') && (c <= '9'))    ||
        ((c >= 'a') && (c <= 'z'))    ||
        ((c >= 'A') && (c <= 'Z'))
       )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/*Enable EDC on L1P*/
static int enableL1PEDC ()
{
    unsigned int status = 0;

    *(unsigned int *)(L1PEDCMD) = 0x1;  //Set EN(bit0)=1

    /* Check the status */
    status = *(unsigned int *)(L1PEDSTAT);

    if ((status<<28) == 0x10000000)
        /* Enabled */
        return 1;

    /* Failed */
    return 0;
}


/*Enable EDC on L2*/
static int enableL2EDC ()
{
    unsigned int status = 0;

    *(unsigned int *)(L2EDCMD) = 0x1;

    /* Check the status */
    status = *(unsigned int *)(L2EDSTAT);

    if ((status<<28) == 0x10000000)
        /* Enabled */
        return 1;

    /* Failed */
    return 0;
}

/*Enable all bits in L2EDCEN*/
static int enableEDCL2EDCEN ()
{
    /* Set DL2CEN(bit0),PL2CEN(bit1),DL2SEN(bit2),PL2SEN(bit3),SDMAEN(bit4)=1 */
    *(unsigned int *)(L2EDCEN) |= 0x1F;
    return 1;
}

Platform_STATUS platform_init(platform_init_flags  * p_flags,
                              platform_init_config * p_config)
{
    CSL_Status              status;
    PllcHwSetup             pllc_hwSetup;
    PllcHwSetup             pllc_hwSetupRead;

    /*************************************************************************
     * This routine may be called before BIOS or the application has loaded.
     * Do not try and write debug statements from here.
     ***********************************************************************/

    if ((p_flags == 0) || (p_config == 0)){
        platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
        return ( (Platform_STATUS) Platform_EFAIL);
    }

    /* Start TCSL so its free running */
    CSL_chipWriteTSCL(0);


    platform_errno = 0;

        /* PLLC module handle structure */
    if (p_flags->pll) {

        /* Set the Core PLL */
        /* Clear local data structures */
        memset(&pllc_hwSetup, 0, sizeof(PllcHwSetup));

        /* Setup PLLC hardware parameters */
        pllc_hwSetup.divEnable  = (CSL_BitMask32) (PLLC_DIVEN_PLLDIV2 |
                                                   PLLC_DIVEN_PLLDIV5 |
                                                   PLLC_DIVEN_PLLDIV8) ;

        /* Setup PLLC hardware parameters */
        pllc_hwSetup.pllM       =
                (((p_config->pllm) ? p_config->pllm : PLATFORM_PLL1_PLLM_val) - 1);
        pllc_hwSetup.preDiv   = PLATFORM_PLL_PREDIV_val - 1;
        pllc_hwSetup.pllDiv2  = PLATFORM_PLLDIV2_val - 1;
        pllc_hwSetup.pllDiv5  = PLATFORM_PLLDIV5_val - 1;
        pllc_hwSetup.pllDiv8  = PLATFORM_PLLDIV8_val - 1;
        pllc_hwSetup.postDiv  = PLATFORM_PLL_POSTDIV_val -1;

        /* set Pll */
        status = CorePllcHwSetup (&pllc_hwSetup);

        if (status != CSL_SOK) {
             platform_errno = PLATFORM_ERRNO_PLL_SETUP;
            return ( (Platform_STATUS) Platform_EFAIL);
        }

        /* Read back */
        status = CorePllcGetHwSetup (&pllc_hwSetupRead);

        if (status != CSL_SOK) {
            platform_errno = PLATFORM_ERRNO_PLL_SETUP;
            return ( (Platform_STATUS) Platform_EFAIL);
        }

        /* Set the DDR3 PLL if DDR flag is set */
        if (p_flags->ddr) {
            status = SetDDR3PllConfig();
            if (status != CSL_SOK) {
                platform_errno = PLATFORM_ERRNO_PLL_SETUP;
                return ( (Platform_STATUS) Platform_EFAIL);
            }
        }
    }
    /* Initialize DDR3 */
    if (p_flags->ddr) {
        xmc_setup();

        status = DDR3Init();

        if (status != CSL_SOK) {
            platform_errno = PLATFORM_ERRNO_GENERIC;
            return ( (Platform_STATUS) Platform_EFAIL);
        }
    }


    /* Run DDR3 test */
    //if (platform_memory_test(PLL_REINIT_DDR3_TEST_START_ADDR,
    //        PLL_REINIT_DDR3_TEST_END_ADDR) == Platform_EOK) {
    //    break;
    //}
    /* Save frequency, its needed by  platform_delay */
    if(!platform_mcb.frequency) {
      platform_mcb.frequency = platform_get_frequency();
    }
  //  PowerUpDomains();

    /* Enable Error Correction for memory */
    if (p_flags->ecc) {
           enableL1PEDC();
           enableEDCL2EDCEN();
           enableL2EDC();
    }


    return Platform_EOK;
}



platform_internal - Copy.h

  • George,

    As referenced in the other thread, please use the resources provided.  We cannot review the code of every user.  We will review the PHY_CALC and REG_CALC spreadsheets.  We will also review your report showing that the length matching rules have been met.  Finally, once all of this is gathered, we will review a modified GEL file which has only the register value changes needed for your board implementation.

    Tom

  • Hello,
    I understood this. I really apologized for post again for the same issue.

    But the documents are very complicating. In any case, the code that I pasted based on the code that TI provides.

    Could you please tell me only if the partial leveling is correct ?

    I will really appreciate to you if you give me this information.

    I am in a deadlock and I try to exclude the possible errors.

    See the code below.

    /***************** 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 = 0x80000000; */
    CSL_EMIF4F_SetLevelingControlInfo(1, 0, 0, 0, 0);

    /************************************************************
    Wait for min 1048576 DDR clock cycles for leveling to complete
    = 1048576 * 1.5ns = 1572864ns = 1.57ms.
    Actual time = ~10-15 ms
    **************************************************************/
    cycles_delay(4201680); //Wait 3ms for leveling to complete
    # if defined PARTIAL_LEVELING
    hEmif->RDWR_LVL_RMP_WIN = 0x00000502;
    hEmif->RDWR_LVL_RMP_CTRL = 0x80000000;
    hEmif->RDWR_LVL_CTRL = 0xFF090900;

    Best regards
    George

  • George,

    Your code appears to be extracted from the example code within MCSDK.  I cannot review this code.  There are too many dependencies on implementation.  Also note that Partial Automatic Leveling requires more than the lines you have shown.

    The C665x GEL file change is in Keystone1 emupack release and is available at:

    http://software-dl.ti.com/sdoemb/sdoemb_public_sw/ti_emupack_keystone1/latest/index_FDS.html.

     

    You can also get the latest release from CCS by clicking “Help” -> “Check for Updates” and select keystone 1 emupack package.

     

    DDR3 initialization is in the function ddr3_setup_auto_lvl_1333().  We need to get the code working through GEL before moving to C-code.

     

    You are continuing to avoid the hardware-level steps.  These must be completed before the code is tuned.

     

    Tom

     

  • Hello,

    I asked so many times because I am confused and I want to reduce the probability to have a problem in the sw implementation. I am the software guy that takes the HW specification and try to program the PLL. I have only a general view of layout specification

     I  used the TI code as reference. I believe that this code is a correct one and safe to use.

    But I made the appropriate changes to be compatible with our design using the excels .

     I did not change in any dealy that is needed before or after a action.  I noticed that all the time delays are greater than the min limits TI provides in its documets.  The min reference clock for the calculation  is 25 MHz. and in  our desing we use 66,67 MHZ

    Short story about problem:

    Until now , we used full automatic leveling and we did not face any problem. Our application was robust, has operated for more than four months. But hardware side reduced the core volatge from 1.10 to 0.95 after the board  is powered up, using smartflex. Then a strange behaviour in DDR3 appeared  when the processor operates in 1GHz. In lower frequency there is not problem.   Does the voltage affect the DDR3 frequency? Can we reduce the voltage after power up the board?

    I will be very happy if you give some hints about these as well . Anyway these are  other issues.

    In the issue with the leveling. First of  all, it is not cleat to me if I can  use incremental leveling in c6657 with partial leveling ?

    This is described in example 23 but the RDWR_LVL_RMP_WIN is reserved and the bits 30-0 are reserved also in RDWR_LVL_RMP_CTRL.

    IMoreover, I  cannot use the GEL file to test my code. Our application  is a master slave application. The master downloads  the  bootloader that programs the PLL and then download and execute the applidcation code.

    However we have done memory test using custom GEL that were passed. 

    In addition, I used as pattern the evm6657 gel and created a new one  based on c code that I have writtern.

    I kept only the PLL intiliazation routins and DDR3  initialization routine as well.

    I have checked the original GEL file and the steps are the same as in the code that I have written in C.

    6657_gel.gel

  • George,

    Yes, the core voltage can affect DDR3 timing since the PHY logic does exist in the core domain.

    Smart reflex use is required to meet reliability targets.  You mention a shift in core voltage recently.  Was this when an AVS compliant power solution was used or is this some type of fixed configuration?

    There is no requirement for incremental leveling.  That is why it is not in the GEL.  Similarly, that is why Full Automatic Leveling is not in the GEL.

    The hardware design team must have designed the board per the routing rules.  If they did not, the board design may be marginal.  This is why I keep stressing this issue.  Is this a board that will become a product or is it simply a design project for a university class?  If it will be manufactured, then the routing rules need to be verified.

    Tom

  • Hello Tom,

    We found was gone wrong.

    It was  the frequency of input clock of the dsp cpu core. We used a wrong value for this. We switched in partial leveling.DDR3 is stable.

    One question and close this thread. You told me that there is no requirement for incremental leveling. But we use incremental leveling with partial leveling.

    From your experience will this create us problems? It would be better to use partial leveling without incremental leveling?

    Best regards

    George

  • George,

    Recommendations for incremental leveling use are in the KeyStone I DDR3 Initialization Application Report (SPRABL2D).  Incremental leveling really has no value after Partial Automatic Leveling.  Additionally, as stated in that document, only the gate training value can be incrementally updated in that mode.  The write leveling functionality must be disabled due to the erratum and read eye leveling functionality is disabled due to the workaround implemented as part of the Partial Automatic Leveling workaround.

    I am glad to hear that you found the solution to your problem.

    Tom

  • Hello Tom,
    I checked the registers , write leveling functionality and read eye leveling functionality are disabled. However, if I do not put incremental leveling in my configuration then the DDR3 will be unstable. If you have time have a look in my GEL file function ddr3_setup_auto_lvl_1333().
    Best regards
    George