how to change DDR clock of i.mx6

cancel
Showing results for 
Search instead for 
Did you mean: 

how to change DDR clock of i.mx6

27,709 Views
Tony_Luo
Contributor II

Hi all, the DDR clock of i.mx6 is 528MHz on boot time, but I want to change it to lower(may be 400MHz).

I read the Datasheet and found the below introduction:

"

18.2.1.5.3 PLL clock change

If software wants to change pll clock output of a specific pll, or if software wants to stop

a specific pll, then software needs first to move all the clocks generated from this pll to

another pll which is not changed.

This should be done via the glitch less mux's for the clocks which cant be stopped (core

and bus clocks). Procedure of PLL clock change is described in anatop module spec.

"

But I can't found the "anatop module spec".

By the way, in i.mx5,the clock is configure int the file of "lowlevel_init.S" by the macro of "init_clock" & "setup_pll pll, freq",

But in i.mx6,the macro of "setup_pll pll, freq" is empty and "PLL1, PLL2, and PLL3 are configured by ROM", so I have no idea of how to change DDR clock of i.mx6.

If anyone can help me please?

Labels (1)
26 Replies

2,738 Views
sheik
Contributor I

Hi,

I am trying to calibrate imx6ul processor which is having MT41J128M16 DDR3 SDRAM, I would like to calibrate the DDR below 396MHZ. I have updated the calibration sheet with 300MHZ and tried to calibrate.

Calibration was successful but device still runs in 396 MHZ. Will imx6ul work below 396MHZ DDR clock frequency?

I have updated all the Write leveling, DQS Gating, Read and write calibration register values in my .cfg file, device got booted successfully but it still runs in 396MHZ frequency. 

Could you please let me know where else I have update to make the device runs in 297MHZ clock frequency.

I have attached my calibration sheet and DDR calibration log here.

Kindly provide your inputs on the same. Please do let me know if I am missing out on anything

Thanks,

Sheik Ajith

0 Kudos

4,405 Views
abraham_v
Contributor IV

Not to go off-topic, but on another board my company made (based on a Samsung chipset) there was an issue with DDR initialization. Simply put, when writing values to the DDR, we weren't able to read the same values. Due to limited documentation, the team fixed that issue with 'trial-and-error'. Basically testing out different combinations for the DDR settings until they found something that worked; obviously it took them a long time to fix things.

I'm worried about facing the same problem with an upcoming iMX6 dual core board we are designing. From what I've understood with this discussion, the DDR gets initialized in the boot ROM and neither uboot nor linux touch that initialization afterwards. Is this correct? The reference board we have is the iMX6 sabresd (quad core). From the schematics, I understand that its databus is 64bits with 1GB worth of DDR3. Our target board is designed with a databus of 32-bits of 1GB DDR3, using chipsets from a different manufacturer.

Is the DCD table as defined in the uboot source file "board/freescale/mx6q_sabresd/flash_header.S" my only point for DDR configuration? (I'm using the uboot obtained from git://git.freescale.com/imx/uboot-imx.git as suggested by the 'Android_User_Guide.pdf' document) Or am I missing something obvious?

0 Kudos

4,405 Views
patricesarrasin
Contributor III

Hi Abraham,

                  I have the same understanding as you, the DDR is initialize in the first couple of call to the CPU before U-Boot is copied into RAM. After that nobody touch it... You will probably have to adjust the DDR configuration file depending on your memory chipset. The DDR configuration file (board/freescale/mx6q_sabresd/flash_header.S or board\freescale\imx\ddr\mx6q_4x_mt41j128.cfg) depend on which version of u-boot you are using. The latest u-boot version use the .cfg file.

Let me know if you have more quesitons, I will try my best to help you.

Regards

Patrice

4,405 Views
abraham_v
Contributor IV

Thanks for your reply Patrice.

Its good to know that I'm not the only developer who came to the conclusion that the DDR cannot be configured AFTER uboot starts. But that puzzles me too. The iMX6 reference manual has a chapter called "Multi Mode DDR Controller" (chapter 44) which speaks of configuring the MMDC with information like DDR type ... etc. If, as a developer I can't access (or do anything meaningful) with the registers it mentions, why bother with having such a chapter at all?

Off to decypher the DCD table,

Abraham V.

0 Kudos

4,439 Views
patricesarrasin
Contributor III

Hi,

There was some code to modify the DDR clock and do the calibration ( see attached files). It worked in baremetal and I was trying to integrate inside u-boot... For now, I didn't find the correct place to put it inside u-boot. I have to find the place where I can implement this logic before we the jump into RAM.

Any ideas for the correct place?

Thanks

Pat

0 Kudos

4,439 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, all

     If I remembered right, we didn't support changing DDR clk in runtime under uboot. Which means if you want a dedicated DDR freq, you need to change the DCD table as you mentioned upper, which is in charge of DDR controller's initialization. Different DDR freq may need different DDR script(DCD setting) to make it work stably.

0 Kudos

4,405 Views
wei_li
Contributor I

Hi, Yongcai,

I also hadDDR clk issue that reducing 528MHZ to 400MHZ caused u-boot halted. therefore I still use 528MHZ.  Also I am trying to figure out how to reduce 1 Gigabyte DDR3 RAM to 512Mega Bytes (half of 1 Gigabyte) in mx6 sabresd code of '/u-boot- fslc/v2016.07+gitAUTOINC+e6b42411ab-r0 ' and hardware design. Please see my 'Question X'.


The original reference design of i.MX6 had a total of 1 Gigabyte DDR3 RAM. The implementation was using four Micron MT41K128M16 parts. Each part is a 256 Mega Bytes ( 256 M * 4 = 1Gbytes).


Question 1: Is there any hardware change for reducing 1 Gigabyte DDR3 RAM to 512MegaByte?

My hardware design follows the original reference design for 1 Gigabyte DDR3 RAM, but there are only two MT41K128M16 parts soldered on a board. That means that there are only 512 Mega bytes (256M * 2 = 512 M) physical ram parts.


To extend RAM size, there should be hardware changes. But in my case, I am trying to reduce RAM. Therefore, 1 Gigabyte RAM hardware should accommodate 512Mbyte RAM without any modification. Correct?


Question 2: Let's assume that there is no change in hardware which is same to 1Gbyte RAM original reference design, what should be changed in u-boot software?


Here are what MDCTL and MDMISC are shown in "MX6DL_SabreSD_DDR3_register_programming_aid_v2.1.xlsx "


Reg name Reg address Reg value

MDCTL 0x021B0000 0x831A0000

MDMISC 0x021B0018 0x00001740


Here is what MDCTL and MDMISC are shown in

"/home/sw/fsl-community-bsp/build/tmp/work/imx6dlsabresd-poky-linux-gnueabi/u-boot- fslc/v2016.07+gitAUTOINC+e6b42411ab-r0/git/board/freescale/mx6sabresd/mx6q_4x_mt41j128.cfg".


DATA 4 0x021b0000 0x831A0000

DATA 4 0x021b0018 0x00081740 (Question 3, why this value is not 0x00001740? )


Here is what MDCTL and MDMISC are shown in

"/home/sw/fsl-community-bsp/build/tmp/work/imx6dlsabresd-poky-linux-gnueabi/u-boot-fslc/v2016.07+gitAUTOINC+e6b42411ab-r0/git/board/freescale/mx6sabresd/mx6sabresd.cfg".


DATA 4 0x021b0000 0x831A0000

DATA 4 0x021b0018 0x00001740


Here is how 1 Gbytes Ram has been calculated in

"/home/sw/fsl-community-bsp/build/tmp/work/imx6dlsabresd-poky-linux-gnueabi/u-boot-fslc/v2016.07+gitAUTOINC+e6b42411ab-r0/git/arch/arm/imx-common/cpu.c"


---------------------------code in cpu.c ---------------------------------------------------------

#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
#if defined(CONFIG_MX53)
#define MEMCTL_BASE ESDCTL_BASE_ADDR
#else
#define MEMCTL_BASE MMDC_P0_BASE_ADDR /* Question 4: MMDC_P0_BASE_ADDR must be 0x021b0000, correct? */
#endif
static const unsigned char col_lookup[] = {9, 10, 11, 8, 12, 9, 9, 9}; /*Question 5: how do I know these values are correct? */
static const unsigned char bank_lookup[] = {3, 2}; /*Question 6: how are these values associated with ram bank? */

/* these MMDC registers are common to the IMX53 and IMX6 */
struct esd_mmdc_regs {
uint32_t ctl;
uint32_t pdc;
uint32_t otc;
uint32_t cfg0;
uint32_t cfg1;
uint32_t cfg2;
uint32_t misc;
};

#define ESD_MMDC_CTL_GET_ROW(mdctl) ((ctl >> 24) & 7)
#define ESD_MMDC_CTL_GET_COLUMN(mdctl) ((ctl >> 20) & 7)
#define ESD_MMDC_CTL_GET_WIDTH(mdctl) ((ctl >> 16) & 3)
#define ESD_MMDC_CTL_GET_CS1(mdctl) ((ctl >> 30) & 1)
#define ESD_MMDC_MISC_GET_BANK(mdmisc) ((misc >> 5) & 1) /* Question 7: it seems that MDMISC register needs a new value to reduce Ram from 1 Gbytes to 512 bytes. What is the exact value ? For 1Gytes value, it is 0x00001740 */

/*
* imx_ddr_size - return size in bytes of DRAM according MMDC config
* The MMDC MDCTL register holds the number of bits for row, col, and data
* width and the MMDC MDMISC register holds the number of banks. Combine
* all these bits to determine the meme size the MMDC has been configured for
*/
unsigned imx_ddr_size(void)
{

struct esd_mmdc_regs *mem = (struct esd_mmdc_regs *)MEMCTL_BASE;
unsigned ctl = readl(&mem->ctl);
unsigned misc = readl(&mem->misc);
int bits = 11 + 0 + 0 + 1; /* row + col + bank + width */ /* Question 8: where do 11, 0, 0, 1 values come ? */


bits += ESD_MMDC_CTL_GET_ROW(ctl);
bits += col_lookup[ESD_MMDC_CTL_GET_COLUMN(ctl)];
bits += bank_lookup[ESD_MMDC_MISC_GET_BANK(misc)];
bits += ESD_MMDC_CTL_GET_WIDTH(ctl);
bits += ESD_MMDC_CTL_GET_CS1(ctl);

/* The MX6 can do only 3840 MiB of DRAM */
if (bits == 32)
return 0xf0000000;

return 1 << bits;
}
#endif

-----------------------end of code in cpu.c -----------------------------------------------------

Thanks.

0 Kudos

4,439 Views
patricesarrasin
Contributor III

Ok thanks for info! I will stop trying to change it in runtime under u-boot... Do you already have a working script for 500Mhz or 400Mhz so I can based myself on it?

Best regards

Pat

0 Kudos

4,439 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Pat

     Sorry, I don't have a 500M script, I only have a flash_header when I was trying 400M on iMX6Q sabresd board, this is a debug version, the script is not the latest one, you can try it to see whether it works on your board first, and you should contact the DDR owner to get the latest script for 400M.

    /* Init the DDR according the init script */

    ldr r0, =CCM_BASE_ADDR

    /* select 400MHz for pre_periph_clk_sel */

    ldr r1, =0x00060324

    str r1, [r0,#0x18]

  /* 64-bit DDR3 */

    /* IOMUX setting */

    ldr r0, =IOMUXC_BASE_ADDR

    mov r1, #0x30

    str r1, [r0,#0x5a8]

    str r1, [r0,#0x5b0]

    str r1, [r0,#0x524]

    str r1, [r0,#0x51c]

    str r1, [r0,#0x518]

    str r1, [r0,#0x50c]

    str r1, [r0,#0x5b8]

    str r1, [r0,#0x5c0]

    ldr r1, =0x00020030

    str r1, [r0,#0x5ac]

    str r1, [r0,#0x5b4]

    str r1, [r0,#0x528]

    str r1, [r0,#0x520]

    str r1, [r0,#0x514]

    str r1, [r0,#0x510]

    str r1, [r0,#0x5bc]

    str r1, [r0,#0x5c4]

    str r1, [r0,#0x56c]

    str r1, [r0,#0x578]

    str r1, [r0,#0x588]

    str r1, [r0,#0x594]

    str r1, [r0,#0x57c]

    ldr r1, =0x00003000

    str r1, [r0,#0x590]

    str r1, [r0,#0x598]

    mov r1, #0x00

    str r1, [r0,#0x58c]

    ldr r1, =0x00003030

    str r1, [r0,#0x59c]

    str r1, [r0,#0x5a0]

    ldr r1, =0x00000030

    str r1, [r0,#0x784]

    str r1, [r0,#0x788]

    str r1, [r0,#0x794]

    str r1, [r0,#0x79c]

    str r1, [r0,#0x7a0]

    str r1, [r0,#0x7a4]

    str r1, [r0,#0x7a8]

    str r1, [r0,#0x748]

    str r1, [r0,#0x74c]

    mov r1, #0x00020000

    str r1, [r0,#0x750]

    mov r1, #0x00000000

    str r1, [r0,#0x758]

    mov r1, #0x00020000

    str r1, [r0,#0x774]

    mov r1, #0x30

    str r1, [r0,#0x78c]

    mov r1, #0x000c0000

    str r1, [r0,#0x798]

    /* Initialize 2GB DDR3 - Micron MT41J128M */

    ldr r0, =MMDC_P0_BASE_ADDR

    ldr r2, =MMDC_P1_BASE_ADDR

    ldr r1, =0x02020207

    str r1, [r0,#0x83c]

    ldr r1, =0x02020201

    str r1, [r0,#0x840]

    ldr r1, =0x02020207

    str r1, [r2,#0x83c]

    ldr r1, =0x02150203

    str r1, [r2,#0x840]

    ldr r1, =0x3E35353B

    str r1, [r0,#0x848]

    ldr r1, =0x3A393541

    str r1, [r2,#0x848]

    ldr r1, =0x41424744

    str r1, [r0,#0x850]

    ldr r1, =0x4937483B

    str r1, [r2,#0x850]

    ldr r1, =0x33333333

    str r1, [r0,#0x81c]

    str r1, [r0,#0x820]

    str r1, [r0,#0x824]

    str r1, [r0,#0x828]

    str r1, [r2,#0x81c]

    str r1, [r2,#0x820]

    str r1, [r2,#0x824]

    str r1, [r2,#0x828]

    ldr r1, =0x00081740

    str r1, [r0,#0x18]

    ldr r1, =0x00008000

    str r1, [r0,#0x1c]

    ldr r1, =0x555b99a4

    str r1, [r0,#0x0c]

    ldr r1, =0xfe730e64

    str r1, [r0,#0x10]

    ldr r1, =0x01ff00db

    str r1, [r0,#0x14]

    ldr r1, =0x000026d2

    str r1, [r0,#0x2c]

    ldr r1, =0x005b0e21

    str r1, [r0,#0x30]

    ldr r1, =0x1b334000

    str r1, [r0,#0x08]

    ldr r1, =0x0003002d

    str r1, [r0,#0x04]

    ldr r1, =0x00000027

    str r1, [r0,#0x40]

    ldr r1, =0xc31a0000

    str r1, [r0,#0x00]

    ldr r1, =0x00000800

    str r1, [r0,#0x8b8]

    ldr r1, =0x04088032

    str r1, [r0,#0x1c]

    ldr r1, =0x0408803a

    str r1, [r0,#0x1c]

    ldr r1, =0x00008033

    str r1, [r0,#0x1c]

    ldr r1, =0x0000803b

    str r1, [r0,#0x1c]

    ldr r1, =0x00428031

    str r1, [r0,#0x1c]

    ldr r1, =0x00428039

    str r1, [r0,#0x1c]

    ldr r1, =0x09308030

    str r1, [r0,#0x1c]

    ldr r1, =0x09308038

    str r1, [r0,#0x1c]

    ldr r1, =0x04008040

    str r1, [r0,#0x1c]

    ldr r1, =0x04008048

    str r1, [r0,#0x1c]

    ldr r1, =0xa5380003

    str r1, [r0,#0x800]

    ldr r1, =0x00005800

    str r1, [r0,#0x20]

    ldr r1, =0x00022221

    str r1, [r0,#0x818]

    ldr r1, =0x00022221

    str r1, [r2,#0x818]

    ldr r1, =0x00000000

    str r1, [r0,#0x1c]

4,414 Views
宗標廖
Contributor V

Hello, Huang

I tried your script on i.MX6QSabreSd board,the u-boot can't start up.

I used the DCD tables(in flash_header.S) and I set values for registers according to your script.

Is there anything else that  I need to do?

Thank you!

ZongbiaoLiao

0 Kudos

4,439 Views
patricesarrasin
Contributor III

Hi,

    we also have a custom board based on mx6sabrelite and we need to reduce the DDR speed to 500Mhz instead of the 528Mhz as the final solution. Maybe for now the 400Mhz should be enough, but I cannot get it to work with the indication found in this post. I was hoping someone could give me some pointers....

I am using the latest u-boot release 2013.04 and it seems that the DDR initialisation structure changed a little bit. It seems there is no more flash_header.S and the way the DCD structure is declared as changed...

I modify the following line in board\freescale\imx\ddr\mx6q_4x_mt41j128.cfg, but for now the boot hang...

DATA 4 0x020e0774 0x00020000

DATA 4 0x020e078c 0x00000030

DATA 4 0x020e0798 0x000C0000

/*************MY ADDITION**************

DATA 4 0x020C4018 0x00060324

/********************************************

DATA 4 0x021b081c 0x33333333

DATA 4 0x021b0820 0x33333333

DATA 4 0x021b0824 0x33333333

Any ideas will be welcome

best regards

Patrice

0 Kudos

4,439 Views
jithinmdas
Contributor I

Hi,

Remove the comments and put it in the starting of DCD configuration. This worked for me.

0 Kudos

4,439 Views
LeonardoSandova
Specialist I

Hi Patrice,

i am working on a similar issue but on a sabre SD board. Have you tried the u-boot command clk? just stop the booting process on U-boot and type clk ddr 400. This is not a permanent change but at least in the testing phase it can help.

Leo

0 Kudos

4,439 Views
patricesarrasin
Contributor III

Hi,

    which u-boot are you using? In my version this command doesn't exist... I am trying to do the integration of it from the source code I found here:

u-boot-gazelle/common/cmd_clk.c at master · bandwidthcrunch/u-boot-gazelle · GitHub

Thanks

Pat

0 Kudos

4,439 Views
AnsonHuang
NXP Employee
NXP Employee

BTW, this code should be done before DDR init, normally it should be in flash_header.S, if you use DCD mode, then you should add these config into DCD items.

0 Kudos

4,439 Views
Tony_Luo
Contributor II

Hi Yongcai,

    Thanks so much for pointing me to the DCD table feature. But I add the CCM config into DCD items between IOMUXC items and MMDC items like below:

"

MXC_DCD_ITEM(37, IOMUXC_BASE_ADDR + 0x758, 0x00000000)

MXC_DCD_ITEM(38, IOMUXC_BASE_ADDR + 0x774, 0x00020000)

MXC_DCD_ITEM(39, IOMUXC_BASE_ADDR + 0x78c, 0x00000030)

MXC_DCD_ITEM(40, IOMUXC_BASE_ADDR + 0x798, 0x000C0000)

MXC_DCD_ITEM(41, CCM_BASE_ADDR + 0x18, 0x00060324)               //add here

MXC_DCD_ITEM(42, MMDC_P0_BASE_ADDR + 0x81c, 0x33333333)

MXC_DCD_ITEM(43, MMDC_P0_BASE_ADDR + 0x820, 0x33333333)

MXC_DCD_ITEM(44, MMDC_P0_BASE_ADDR + 0x824, 0x33333333)

MXC_DCD_ITEM(45, MMDC_P0_BASE_ADDR + 0x828, 0x33333333)

"

and the MfgTool load u-boot fail and info "Reason is unknown,failed to run comman".

0 Kudos

4,439 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Tony

     If you add one item to DCD table, some parameters need to be changed, please search the below two lines code, the DCD length must be changed, such as below, if there is 59 items, then Len = 59*8+4+4=0x1E0, so there is E001 in the dcd_hdr, and same as write_dcd_cmd, it is DC01. You can try it.

66 dcd_hdr:          .word 0x40E001D2 /* Tag=0xD2, Len=59*8 + 4 + 4, Ver=0x40 */

67 write_dcd_cmd:    .word 0x04DC01CC /* Tag=0xCC, Len=59*8 + 4, Param=0x04 */

0 Kudos

4,439 Views
Tony_Luo
Contributor II

Hi Yongcai,

    Thanks for your quick replying, I have changed the "dcd_hdr" and "write_dcd_cmd" to the right value,but get the same error.

    By the way, what I use is Sabrelite, and please see the attach file for my modify.

0 Kudos

4,439 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Tony

     If so, then I guess you need to adjust DDR script to make it work at 400M. The DDR script means those DCD items of MMDC configure.

4,439 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Tony

     See below code for reference, it makes the DDR's clock root from 396M PFD.  if you want to make DDR running at 400M, you need to switch periph_clk to 400M, which is MMDC clock's parent, and periph_clk is from pre_periph_clk, so you need to switch it from 528M PLL2 to 396M PFD. Normally, 528M DDR script should work for 400M, but if you find it can NOT work, then maybe DDR script need improvement. BTW, you can set CCM_CCOSR to output mmdc_axi_ch0's clock root to CLKO pin, then you can monitor whether it is the frequency you need. 

  /* Init the DDR according the init script */

    ldr r0, =CCM_BASE_ADDR

    /* select 400MHz for pre_periph_clk_sel */

    ldr r1, =0x00060324

    str r1, [r0,#0x18]

0 Kudos