# On Freescale iMX31, how can I translate SDRAM address to CPU address?

[This is a re-post of http://stackoverflow.com/q/5346225/69172]

I'm new to iMX31 and embedded systems, please help me to understand the translation from SDRAM address to ARM CPU address, especially in "special" command modes of the SDRAM controller.

Here is the SDRAM initialization code I have problem with:

    ldr r0, ESDCTL_BASE_W
mov r2, #SDRAM_BASE_ADDR /* 0x80000000 */

ldr r1, =0x92100000 /* Precharge */
str r1, [r0]
ldr r1, =0x0
ldr r12, =0x80000F00
str r1, [r12]

ldr r1, =0xA2100000 /* Auto-refresh */
str r1, [r0]
ldr r1, =0x0
str r1, [r2]

ldr r1, SDRAM_0xB2100000 /* Load Mode Register */
str r1, [r0]
ldr r1, =0x0
strb r1, [r2, #0x33]

ldr r1, =0xFF
ldr r12, =0x81000000


The RAM I have is Micron LPDDR MT46H64M32LF, and this code follows the initialization procedure nicely, but in PRECHARGE step, where is the address 0x80000F00 coming from?

From iMX31 reference manual I learned that during the PRECHARGE step, I need to set SDRAM pin A10 to HIGH which will therefore result a PRECHARGE ALL. Here is the text on PRECHARGE from RM:

...While in this mode, an access (either read or write) to the SDRAM/LPDDR address space will generate a precharge command cycle. SDRAM/LPDDR address bit A10 determines whether a single bank, or all banks, are precharged by the command. Accessing an address with the SDRAM/LPDDR address A10 low will precharge only the bank selected by the bank addresses, as illustrated in Figure 19-75. Conversely, accesses with A10 high will precharge all banks regardless of the bank address, ...Note that A10 is the SDRAM pin, not the A10 bit ARM address bus. Translation of the SDRAM A10 to the corresponding ARM address is dependent on the memory configuration.

And here is another text on multiplexed address bus during “special” mode:

During “special” mode, for example, precharge mode (SMODE=1) or load mode registers (SMODE=3) there is no address shifting, means that CPU address A0 is mapped on MA0 at all memory width. For example, in order to drive MA10 bit (for the precharge all command) the CPU A10 bit should be set (for both 16 or 32 bit external devices). The same logic is valid for the load mode register command, as can be seen on the initialization routine example on Section 19.5.4.1, “SDRAM Initialization.”

According to the text above and assuming A0 is the first bit of 0x80000000, setting A10 to 1 should give address 0x80000400, not the 0x80000F00 in the code. Why???

The code snippet I showed here is supposed to work with DDR. For SDRAM, it actually uses 0x80000400 in PRECHARGE.

Is there anything related to the characteristics of DDR? And how can I get the proper translation between SDRAM pins and ARM CPU address?

-
 Great question! Unfortunately, I'm not very experienced with respect to external RAM, but I've dropped a bounty on your question in hopes that someone else will find it. – Kevin Vermeer Mar 22 '11 at 19:36 Those two sections of the manual are contradictory, unless I'm misunderstanding. I'm inclined to believe the latter. The address bits (other than A10) may be don't-cares for PRECHARGE ALL, so the 0xF may be an attempt to set A10 regardless of the mapping. Is the memory not working with this initialization, and if not, can you describe the problem? Or are you looking to understand how the address mapping works in normal operation? – Andy Mar 27 '11 at 18:07

To answer your base question, to get to the address of pin A10 of the memory you need to look at the memory map for the ARM device...

In this case it looking at the memory map:

0x8000 0000 -> 0x8FFF FFFF is mapped to CSD0 (SDRAM/DDR)

and

0x9000 0000 -> 0x9FFF FFFF is mapped to CSD1 (SDRAM/DDR)

You'd need to know what chip select was used in the PCB design to determine your answer as to which bank your DDR is attached to.

This implies that A10 is located as either 0x8000 0400 (as you mentioned) or 0x9000 0400.

As to why 0x8000 0F00 was used in place of 0x8000 0400...reading the datasheet for that memory implies, but does not state that the other address pins, A(n) are don't cares for this operation so the coder probably just tossed in an F there instead of figuring out that it was only a 4 that was needed.

I also don't find those 2 sections of the datasheet to contradict each other. The first is basically just saying that you need to reference the device's memory map to locate the real address where the memory is mapped so you can use that address as a base.

The second quotes tells you that bit 0 of the address corresponds to address pin 0 on the memory in this mode, which may not always be the case in normal operation. It may depend on the data/address width of the memory combined with alignment issues for the core.

-
 Thank you for clearing things up, and I think how the F comes into life is just as you mentioned. I have another piece of DDR init code from Freescale in where the address for PRECHARGE ALL is 0x80000400! – jaux Mar 29 '11 at 20:21