Hi,
I'm straggling with the initialization of DDR2 (Micron MT47H32M16, 8 Meg x 16 x 4 banks).
My environment is C6748 @ 300MHz, the DDR2 is 400MHz capable, and so I'm trying to configure the DSP DDR controller to 150MHz (the controller's maximum).
There are multiple problems…..
First, the TI DSP DDR2 documentation (sprugj4.pdf) indicates an initialization flow which its sequence is quite different from the one which the LogicPD (EVK) example uses.
There is also a WiKi (http://processors.wiki.ti.com/index.php/Programming_mDDR/DDR2_EMIF_on_OMAP-L1x/C674x) that includes nice spreadsheet that calculates the various DDR2 controller registers' values.
Nothing works.
I have access to the DDR2 (read and write) from the JTAG emulator, after loading one of the GEL (both cases below), but sometimes the verification fails, and always (if any section in the linker file has been allocated to reside on the DDR2) the program loading fails.
The LogicPD GEL usually runs without hangs, but it seems that either the timers or/and the refresh rate values are incorrect. (Regardless if I use the spreadsheet values, or any other).
The second GEL, which includes sequence I wrote based on the TI DSP DDR2 documentation, halts (see below where), and beside doesn't improve the behavior of loading program which some of its sections are linked to reside on the DDR2.
Any idea?
Regards,
Uri
GEL based on the LogicPD example:
/**********************************************************************************
mDDR Configuration routine:
1. mDDR Enable
2. VTP calibration
3. Configure DDR
4. Set to self-refresh, enable mclkstop and DDR Sync Reset
5. Enable DDR and disable self-refresh
int freq is MHz
***********************************************************************************/
DEVICE_mDDRConfig(unsigned int freq)
{
int i;
GEL_TextOut("\tDEVICE_mDDRConfig %d MHz","Output",1,1,1, freq);
/*Enable the Clock to EMIF3A SDRAM*/
PSC1_LPSC_enable(PD0, LPSC_DDR);
// If VTP claiberation enabled , then skip the VTP calibration
if((VTPIO_CTL & 0x00000040))
{
// Begin VTP Calibration
VTPIO_CTL |= (0x00004000); // Set IOPWRDN bit to enable input buffer powerdown enable mode
VTPIO_CTL &= ~(0x00000040); // Clear POWERDN bit (enable VTP)
// Pulse (low) CLRZ to initiate VTP IO Calibration
VTPIO_CTL |= (0x00002000); // Set CLRZ bit
VTPIO_CTL &= ~(0x00002000); // Clear CLRZ bit (CLRZ should be low for at least 2ns)
VTPIO_CTL |= 0x00002000; // Set CLRZ bit
// Polling READY bit to see when VTP calibration is done
while(!((VTPIO_CTL & 0x00008000)>>15)) {}
VTPIO_CTL |= 0x00000080; // Set LOCK bit for static mode
VTPIO_CTL |= 0x00000100; // Set PWRSAVE bit to save power
// End VTP Calibration
}
EMIF3A_SDCR |= 0x00800000; // Set BOOTUNLOCK
// **********************************************************************************************
// Setting based on 512Mb DDR MT47H32M16 on DSMP
// Config DDR timings
DDRCTL = (0x0 << 8) | // Reserved
(0x1 << 7) | // EXT_STRBEN
(0x1 << 6) | // PWRDNEN
(0x0 << 3) | // Reserved
(0x4 << 0); // RL
EMIF3A_SDCR = (EMIF3A_SDCR & 0xF0000000) | // Reserved
(0x0 << 27) | // DDR2TERM1
(0x1 << 26) | // IBANK_POS
(0x0 << 25) | // MSDRAMEN
(0x0 << 24) | // DDRDRIVE1
(0x0 << 23) | // BOOTUNLOCK
(0x0 << 22) | // DDR2DDQS
(0x0 << 21) | // DDR2TERM0
(0x1 << 20) | // DDR2EN
(0x0 << 19) | // DDRDLL_DIS
(0x0 << 18) | // DDRDRIVE0
(0x1 << 17) | // DDREN
(0x1 << 16) | // SDRAMEN
(0x1 << 15) | // TIMUNLOCK
(0x1 << 14) | // NM
(0x0 << 12) | // Reserved
(0x3 << 9) | // CL
(0x0 << 7) | // Reserved
(0x2 << 4) | // IBANK
(0x0 << 3) | // Reserved
(0x2 << 0); // PAGESIZE
// Subtracting 0.5 instead of 1 so that the int is rounded up after truncating a real value
EMIF3A_SDTIMR1 = (((unsigned int) ((97.5 * freq / 1000) - 0.5)) << 25) | // tRFC
(((unsigned int) ((18.0 * freq / 1000) - 0.5)) << 22) | // tRP
(((unsigned int) ((18.0 * freq / 1000) - 0.5)) << 19) | // tRCD
(((unsigned int) ((15.0 * freq / 1000) - 0.5)) << 16) | // tWR
(((unsigned int) ((42.0 * freq / 1000) - 0.5)) << 11) | // tRAS
(((unsigned int) ((60.0 * freq / 1000) - 0.5)) << 6) | // tRC
(((unsigned int) ((12.0 * freq / 1000) - 0.5)) << 3) | // tRRD
(EMIF3A_SDTIMR1 & 0x4) | // Reserved
(((unsigned int) ((2.0 * freq / 1000) - 0.5)) << 0); // tWTR
// Subtracting 0.5 instead of 1 so that the int is rounded up after truncating a real value
// tRASMAX is rounded down so subtracting 1
// CAS/CL = 3
EMIF3A_SDTIMR2 = (EMIF3A_SDTIMR2 & 0x80000000) | // Reserved
(((unsigned int) ((70000 * freq / 1000) - 1)) << 27) | // tRASMAX
(0x0 << 25) | // tXP
(0x0 << 23) | // tODT (Not supported)
(((unsigned int) ((120.0 * freq / 1000) - 0.5)) << 16) | // tXSNR
((200 - 1) << 8) | // tXSRD (200 Cycles)
((1 - 1) << 5) | // tRTP (1 Cycle)
(0x0 << 0); // tCKE
EMIF3A_SDCR2 = 0x00000004; // 8K rows
EMIF3A_SDRCR = (0x1 << 31) | // LPMODEN
(0x1 << 30) | // MCLKSTOPEN
(0x0 << 24) | // Reserved
(0x0 << 23) | // SR_PD
(0x0 << 16) | // Reserved
/* (((unsigned int) ((7.8 * freq) + 0.5)) << 0); // RR*/
(((unsigned int) ((3.9 * freq) + 0.5)) << 0);
/*SyncReset the Clock to EMIF3A SDRAM*/
PSC1_LPSC_SyncReset(PD0, LPSC_DDR);
/*Enable the Clock to EMIF3A SDRAM*/
PSC1_LPSC_enable(PD0, LPSC_DDR);
EMIF3A_SDRCR &= ~0xC0000000; // disable self-refresh
EMIF3A_SDCR &= ~0x00008000; // Clear TIMUNLOCK
}
GEL based on the TI documentation:
/*********************************************************************************
2.13.2 Initializing Following Device Power Up and Device RESET
Following device power up, the DDR2/mDDR memory controller is held
in reset with the internal clocks to
the module gated off. Before releasing the DDR2/mDDR memory
controller from reset, the clocks to the
module must be turned on. Perform the following steps when turning
the clocks on and initializing the
module:
1. Program PLLC1 registers to start 2X_CLK. For information on
programming PLLC1, see your
device-specific System Reference Guide.
2. Program Power and Sleep Controller (PSC) to enable the
DDR2/mDDR memory controller VCLK.
3. Perform VTP IO calibration
a. Clear CLKRZ, LOCK, and POWERDN bits in the VTP IO control
register (VTPIO_CTL) and wait at
least 1 reference clock cycle. You must wait at least 1
reference clock cycle for the CLKRZ to take
affect. The reference clock is the clock at MXI/MXO.
b. Set CLKRZ bit in VTPIO_CTL.
c. Poll READY bit in VTPIO_CTL until it changes to
logic-high.
d. Set IOPWRDN bit in VTPIO_CTL.
e. Set LOCK bit in VTPIO_CTL.
f. Set POWERDN bit in VTPIO_CTL to save power. VTP is locked
and no dynamic calibration will
happen.
4. Configure the DDR PHY control register 1 (DRPYC1R). All of
the following steps may be done in a
single register write to DRPYC1R.
a. Set the EXT_STRBEN bit to 1 to select external DQS strobe
gating.
b. Program the RL bit to the required value.
5. Program the Power and Sleep Controller (PSC) to reset
(synchReset) the DDR2/mDDR memory
controller.
6. Configure the peripheral bus burst priority register (PBBPR).
You must change its default value. See
Section 4.8.
7. Follow the register initialization procedure described in
Section 2.13.1 to complete the DDR2/mDDR
memory controller configuration.
2.13.1 Initializing Configuration Registers
Perform the following steps when configuring the DDR2/mDDR memory
controller memory-mapped
registers:
1. Program the read latency (RL) bit in the DDR PHY control
register (DRPYC1R) to the desired value.
2. Program the SDRAM configuration register (SDCR) with
BOOTUNLOCK bit set to 1 (unlocked).
3. Program the SDRAM configuration register (SDCR) to the
desired value with the BOOTUNLOCK
cleared to 0 and the TIMUNLOCK bit set to 1 (unlocked).
4. For mDDR only, program the SDRAM configuration register 2
(SDCR2) to the desired value.
5. Program the SDRAM timing register 1 (SDTIMR1) and SDRAM
timing register 2 (SDTIMR2) to the
desired values to meet the DDR2/mDDR SDRAM memory data sheet
specification.
6. Program SDCR to the desired value with the TIMUNLOCK bit
cleared to 0 (locked).
7. Program the RR bit in the SDRAM refresh control register
(SDRCR) to the desired value to meet the
refresh requirements of the DDR2/mDDR SDRAM memory.
*********************************************************************************/
VTPIO_calibtarion() {
// If VTP claiberation enabled , then skip the VTP calibration
if((VTPIO_CTL & 0x00000040)) Taken from LogicPD example since TI sequence hangs
{
// Begin VTP Calibration
VTPIO_CTL |= (0x00004000); // Set IOPWRDN bit to enable input buffer powerdown enable mode
VTPIO_CTL &= ~(0x00000040); // Clear POWERDN bit (enable VTP)
// Pulse (low) CLRZ to initiate VTP IO Calibration
VTPIO_CTL |= (0x00002000); // Set CLRZ bit
VTPIO_CTL &= ~(0x00002000); // Clear CLRZ bit (CLRZ should be low for at least 2ns)
VTPIO_CTL |= 0x00002000; // Set CLRZ bit
// Polling READY bit to see when VTP calibration is done
while(!((VTPIO_CTL & 0x00008000)>>15)) {}
VTPIO_CTL |= 0x00000080; // Set LOCK bit for static mode
VTPIO_CTL |= 0x00000100; // Set PWRSAVE bit to save power
// End VTP Calibration
}
/* 2.13.2 [3] */
// VTP IO calibration
#define VTP_CLKRZ (0x00002000)
#define VTP_LOCK (0x00000080)
#define VTP_POWERDN (0x00000040)
#define VTP_READY (0x00008000)
#define VTP_READY (0x00004000)
// VTPIO_CTL &= ~( VTP_CLKRZ | VTP_LOCK | VTP_POWERDN ); // a
// for (i = 0; i++; i<10) {} // a
// VTPIO_CTL |= VTP_CLKRZ; // b
// while(!((VTPIO_CTL & VTP_READY) >> 15)) {} // c Hangs here
// VTPIO_CTL |= VTP_READY; // d
// VTPIO_CTL |= VTP_LOCK; // e
// VTPIO_CTL |= VTP_POWERDN; // f
}
DEVICE_mDDRConfig(unsigned int freq) {
int i;
#define DRPYC1R (DDRCTL)
#define SDCR2_BOOTUNLOCK (0x00800000)
#define SDCR2_TIMUNLOCK (0x00008000)
GEL_TextOut("\tDEVICE_mDDRConfig %d MHz","Output",1,1,1, freq);
/* 2.13.2 [1] */
// Done @ device_PLL1()
GEL_TextOut("\t2.13.2 [2]","Output",1,1,1);
/* 2.13.2 [2] */
// Enable the Clock to EMIF3A SDRAM/DDR
PSC1_LPSC_enable(PD0, LPSC_DDR);
GEL_TextOut("\t2.13.2 [3]","Output",1,1,1);
/* 2.13.2 [3] */
// VTP IO calibration
VTPIO_calibtarion();
GEL_TextOut("\t2.13.2 [4]","Output",1,1,1);
/* 2.13.2 [4] */
// DDR PHY control register 1
DRPYC1R = 0x84; // EXT_STRBEN = External strobe. RL = (CAS latency + 1)
GEL_TextOut("\t2.13.2 [5]","Output",1,1,1);
/* 2.13.2 [5] */
// PSC reset
// PSC1_LPSC_SyncReset(PD0, LPSC_DDR); Hangs here
// PSC1_LPSC_enable(PD0, LPSC_DDR); Hangs here
GEL_TextOut("\t2.13.2 [6]","Output",1,1,1);
/* 2.13.2 [6] */
// 00h will ensure master priority is strictly honored (at the cost of decreased
// DDR2/mDDR memory controller efficiency)
EMIF3A_PBBPR = 0;
GEL_TextOut("\t2.13.1 [2]","Output",1,1,1);
/* 2.13.1 [2] */
// Program the SDRAM configuration register (SDCR) with BOOTUNLOCK bit set to 1 (unlocked).
EMIF3A_SDCR |= SDCR2_BOOTUNLOCK;
EMIF3A_SDCR |= SDCR2_TIMUNLOCK;
GEL_TextOut("\t2.13.1 [3]","Output",1,1,1);
/* 2.13.1 [3] */
EMIF3A_SDCR = 0x0013C622; // BOOTUNLOCK locked
GEL_TextOut("\t2.13.1 [4]","Output",1,1,1);
/* 2.13.1 [4] */
// SDCR2
EMIF3A_SDCR2 = 0x00000004; // 8K rows
GEL_TextOut("\t2.13.1 [5]","Output",1,1,1);
/* 2.13.1 [5] */
// Timers
EMIF3A_SDTIMR1 = 0x1E922A09;
EMIF3A_SDTIMR2 = 0x000000C4;
GEL_TextOut("\t2.13.1 [6]","Output",1,1,1);
/* 2.13.1 [6] */
// TIMUNLOCK locked
EMIF3A_SDCR &= ~(SDCR2_TIMUNLOCK);
GEL_TextOut("\t2.13.1 [7]","Output",1,1,1);
/* 2.13.1 [7] */
// Refresh rate
EMIF3A_SDRCR = 0x00000249;
}
