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