Hello all.
I have custom board with AM3894 and DDR3
DDR3 (size 1GB, two chips K4B4G1646B-HIH9 x16 as one space x32) connect to EMIF0, EMIF1 not use.
default Gel-file TI816x_DDR3 don't work
Calculated values according to the instructions given in the files DM816x_C6A816x_AM389x_EMIF4_Register_Settings and RatioSeed
and create the modified file AM3894_RW.gel
Connect to device and run DDR3_SlaveRatio_ByteWiseSearch_TI816x.out
Get optimal values for WR DQS, RD DQS and RD DQS GATE.
Change Gel-file.
DDR is working correctly.
But i need initialization DDR in the my program. When I initialize the DDR in your program using the same values as in Gel file, i read zero only from DDR space.
Core in Supervisor mode.
Init code:
#define _CONFIG_
#include "am3894.h"
#include "config.h"
unsigned long MAILPLL();
unsigned long DDRPLL();
unsigned long DDR_PRMC();
unsigned long MAILPLL(){
pMAINPLL_CTRL |= 0x4; //Set MAIN_BP bit in MAINPLL_CTRL to 1 to put MAINPLL in bypass mode.
if(!(pMAINPLL_CTRL & 0x8)){ //Initializing and Enabling MAINPLL from Power Down Mode
pMAINPLL_CTRL |= 0x8; //Set MAIN_PLLEN bit in MAINPLL_CTRL to 1 to bring MAINPLL out of power-down mode.
}
pMAINPLL_PWD &= 0x0B; //Clear PWD_CLK1 to PWD_CLK7 bits in MAINPLL_PWD to 0
pMAINPLL_CTRL &= 0xFFFFFFFE; //Set or clear MAIN_LOC_CTL bit in MAINPLL_CTRL to select MAINPLL lock output polarity CLEAR
pMAINPLL_CTRL = (((pMAINPLL_CTRL & 0xFF)|0x100)|0x00400000); //Program the required pre-divider and multiplier values
//Program MAIN_INTFREQx and MAIN_FRACFREQx bit fields
pMAINPLL_FREQ2 = (1<<28)|(MAIN_INTFREQ2<<24)| MAIN_FRACFREQ2;
pMAINPLL_FREQ4 = (1<<28)|(MAIN_INTFREQ4<<24)| MAIN_FRACFREQ4;
pMAINPLL_FREQ5 = (1<<28)|(MAIN_INTFREQ5<<24)| MAIN_FRACFREQ5;
//Program MAIN_MDIVx bit field
pMAINPLL_DIV2 = MAIN_MDIV2;
pMAINPLL_DIV4 = MAIN_MDIV4;
pMAINPLL_DIV5 = MAIN_MDIV5;
pMAINPLL_DIV6 = MAIN_MDIV6;
pMAINPLL_DIV7 = MAIN_MDIV7;
//set MAIN_LDMDIVx bit to 1 in MAINPLL_DIVx to load the Post Divider into Main Synthesizer x and
//set MAIN_LDFREQx bit to 1 in MAINPLL_FREQx to load integer and fraction values into Main Synthesizer x.
pMAINPLL_DIV2 |= (unsigned long)(1<<8);
pMAINPLL_FREQ2 |= (unsigned long)(1<<31);
pMAINPLL_DIV4 |= (unsigned long)(1<<8);
pMAINPLL_FREQ4 |= (unsigned long)(1<<31);
pMAINPLL_DIV5 |= (unsigned long)(1<<8);
pMAINPLL_FREQ5 |= (unsigned long)(1<<31);
pMAINPLL_DIV6 |= (unsigned long)(1<<8);
pMAINPLL_DIV7 |= (unsigned long)(1<<8);
if(pMAINPLL_CTRL & 0x1){
while(pMAINPLL_CTRL & 0x80);
pMAINPLL_CTRL &= 0xFFFFFFFB;
}
else{
while(!(pMAINPLL_CTRL & 0x80));
pMAINPLL_CTRL &= 0xFFFFFFFB;
}
return TRUE;
}
unsigned long DDRPLL(){
pDDRPLL_CTRL &= 0xFFFFFFFB; //Clear DDR_BP bit in DDRPLL_CTRL to 0 to put DDRPLL in bypass mode
if(!(pDDRPLL_CTRL & 0x8)){ //Initializing and Enabling DDRPLL from Power Down Mode
pDDRPLL_CTRL |= 0x8; //Set DDR_PLLEN bit in DDRPLL_CTRL to 1 to bring DDRPLL out of power-down mode
}
pDDRPLL_PWD = 0x0; //Clear PWD_CLK1 to PWD_CLK5 bits in DDRPLL_PWD to 0 to bring individual output clocks of DDRPLL out of power-down mode
pDDRPLL_CTRL &= 0xFFFFFFFE; //Set or clear DDR_LOC_CTL bit in DDRPLL_CTRL to select DDRPLL lock output polarity (DDR_LOCK bit in DDRPLL_CTRL). - CLEAR
pDDRPLL_CTRL = (((pDDRPLL_CTRL & 0xFF)|0x100)|0x003B0000); //Program the required pre-divider and multiplier values in DDR_P and DDR_N bit fields of DDRPLL_CTRL
//Program DDR_INTFREQx and DDR_FRACFREQx bit fields
pDDRPLL_FREQ2 = (1<<28)|(DDR_INTFREQ2<<24)|DDR_FRACFREQ2;
pDDRPLL_FREQ3 = (1<<28)|(DDR_INTFREQ3<<24)|DDR_FRACFREQ3;
//Program DDR_MDIVx bit field
pDDRPLL_DIV1 = DDR_MDIV1;
pDDRPLL_DIV2 = DDR_MDIV2;
pDDRPLL_DIV3 = DDR_MDIV3;
//set DDR_LDMDIVx bit to 1 in DDRPLL_DIVx to load the Post Divider into DDR Synthesizer x and
//set DDR_LDFREQx bit to 1 in DDRPLL_FREQx to load integer and fraction values into DDR Synthesizer x.
pDDRPLL_DIV1 |= (unsigned long)(1<<8);
pDDRPLL_DIV2 |= (unsigned long)(1<<8);
pDDRPLL_FREQ2 |= (unsigned long)(1<<31);
pDDRPLL_DIV3 |= (unsigned long)(1<<8);
pDDRPLL_FREQ3 |= (unsigned long)(1<<31);
while (!(pDDRPLL_CTRL & 0x8)); //Wait for PLL to Lock: Poll for DDR_LOCK bit in DDRPLL_CTRL to become 1
pDDRPLL_CTRL |= 4; //Set the DDR_BP bit in DDRPLL_CTRL to 1 to bring DDRPLL out of bypass mode.
pDDR_RCD = 0x1; //Set PWRDN bit in DDR_RCD to 1 to bring the Reset Clock Distribution module of DDR out of powerdown mode.
return TRUE;
}
unsigned long DDR_PRMC()
{
pCM_DEFAULT_FW_CLKCTRL = 0x2;
pCM_DEFAULT_L3_FAST_CLKSTCTRL = 0x2;
pCM_DEFAULT_EMIF_0_CLKCTRL = 0x2;
pCM_DEFAULT_EMIF_1_CLKCTRL = 0x2;
while((pCM_DEFAULT_L3_FAST_CLKSTCTRL & 0x300)!= 0x300);
while((pCM_DEFAULT_EMIF_0_CLKCTRL & 0x30000)!= 0x0);
while((pCM_DEFAULT_EMIF_1_CLKCTRL & 0x30000)!= 0x0);
pCM_DEFAULT_DMM_CLKCTRL = 0x2;
while((pCM_DEFAULT_DMM_CLKCTRL & 0x30000)!= 0x0);
return TRUE;
}
unsigned long DDR_INIT(){
DDRPLL();
DDR_PRMC();
//Program DDR PHY
//Write 1 to DATA0/1/2/3_REG_PHY_USE_RANK0_DELAYS register to use rank 0 delays for all ranks during read/write operation.
pDATA0_REG_PHY_USE_RANK0_DELAYS = 1;
pDATA1_REG_PHY_USE_RANK0_DELAYS = 1;
pDATA2_REG_PHY_USE_RANK0_DELAYS = 1;
pDATA3_REG_PHY_USE_RANK0_DELAYS = 1;
//Write 1 to CMD0/1/2_REG_PHY_INVERT_CLKOUT_0 register to send inverted DDR Clock to DRAM. 0 - NOT INVERT
pCMD0_REG_PHY_INVERT_CLKOUT_0 = 1;
pCMD1_REG_PHY_INVERT_CLKOUT_0 = 1;
pCMD2_REG_PHY_INVERT_CLKOUT_0 = 1;
//Program CMD0/1/2_REG_PHY_CTRL_SLAVE_RATIO_0 register. If CMD0/1/2_REG_PHY_INVERT_CLKOUT_0 is cleared to 0, program 80h; else, program to 100h
if(pCMD0_REG_PHY_INVERT_CLKOUT_0 == 0) pCMD0_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x80;
else pCMD0_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x100;
if(pCMD1_REG_PHY_INVERT_CLKOUT_0 == 0) pCMD1_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x80;
else pCMD1_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x100;
if(pCMD2_REG_PHY_INVERT_CLKOUT_0 == 0) pCMD2_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x80;
else pCMD2_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x100;
//Write 5h to CMD0/1/2_IO_CONFIG_I_0 register.
pCMD0_IO_CONFIG_I_0 = 0x5;
pCMD1_IO_CONFIG_I_0 = 0x5;
pCMD2_IO_CONFIG_I_0 = 0x5;
//Write 5h to CMD0/1/2_IO_CONFIG_I_CLK_0 register
pCMD0_IO_CONFIG_I_CLK_0 = 0x5;
pCMD1_IO_CONFIG_I_CLK_0 = 0x5;
pCMD2_IO_CONFIG_I_CLK_0 = 0x5;
//Write 4h to DATA0/1/2/3_IO_CONFIG_I_0 register
pDATA0_IO_CONFIG_I_0 = 0x4;
pDATA1_IO_CONFIG_I_0 = 0x4;
pDATA2_IO_CONFIG_I_0 = 0x4;
pDATA3_IO_CONFIG_I_0 = 0x4;
//Write 4h to DATA0/1/2/3_IO_CONFIG_I_CLK_0 register
pDATA0_IO_CONFIG_I_CLK_0 = 0x4;
pDATA1_IO_CONFIG_I_CLK_0 = 0x4;
pDATA2_IO_CONFIG_I_CLK_0 = 0x4;
pDATA3_IO_CONFIG_I_CLK_0 = 0x4;
pDMM_LISA_MAP__0 = 0x80600100; // WR_MEM_32(DMM_LISA_MAP__0, 0x80600100);
//Enable Tiled Access
pDMM_PAT_BASE_ADDR = 0x80000000; //WR_MEM_32(DMM_PAT_BASE_ADDR, 0x80000000);
pEMIF4_0_SDRAM_TIM_1 = EMIF_TIM1_DDR3; //0x1557B9BD
pEMIF4_0_SDRAM_TIM_1_SHADOW = EMIF_TIM1_DDR3;
pEMIF4_0_SDRAM_TIM_2 = EMIF_TIM2_DDR3; // 0x40C77FEB
pEMIF4_0_SDRAM_TIM_2_SHADOW = EMIF_TIM2_DDR3;
pEMIF4_0_SDRAM_TIM_3 = EMIF_TIM3_DDR3; //0x001F8EFF
pEMIF4_0_SDRAM_TIM_3_SHADOW = EMIF_TIM3_DDR3;
pEMIF4_0_SDRAM_CONFIG = EMIF_SDCFG_DDR3; //0x62A73832
pEMIF4_0_DDR_PHY_CTRL_1 = EMIF_PHYCFG_DDR3; //0x00000110
pEMIF4_0_DDR_PHY_CTRL_1_SHADOW = EMIF_PHYCFG_DDR3;
pEMIF4_0_SDRAM_REF_CTRL = ((pEMIF4_0_SDRAM_REF_CTRL&0xFFFF0000)|EMIF_SDREF_DDR3); //0x00001840
pEMIF4_0_SDRAM_REF_CTRL |= 0x10000000;
pEMIF4_0_SDRAM_REF_CTRL &= 0x7FFFFFFF;
pDDR_VTP_CTRL_0 &= 0xFFFFFFEF; //Write 0 WR_LEVEL bit in DDR_VTP_CTRL_0
pDATA0_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE0;
pDATA1_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE1;
pDATA2_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE2;
pDATA3_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE3;
pDATA0_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE0;
pDATA1_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE1;
pDATA2_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE2;
pDATA3_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE3;
pDATA0_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE0;
pDATA1_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE1;
pDATA2_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE2;
pDATA3_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE3;
pDATA0_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE0;
pDATA1_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE1;
pDATA2_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE2;
pDATA3_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE3;
return TRUE;
}
unsigned long ConfigHardware(void)
{
MAILPLL();
DDR_INIT();
return TRUE;
}