Slowing DDR3 clock for i.MX6Q

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Slowing DDR3 clock for i.MX6Q

Jump to solution
7,351 Views
frankmiller
Contributor IV

Greetings,

We're having some trouble with a custom i.MX6Q board (based on sabreSD reference).  It appears that our DDR3 is close to timing margins.  I'd like to slow the DDR3 clock rate down to 396MHz.  I tried plugging that value into the DDR3 programming spreadsheet and replacing the values in flash_header.S with the updated spreadsheet values.  However, when u-boot comes up, its still showing 528MHz for the ddr clock.  I also noticed that mx6q pll2 is set to 528MHz.  Is there something else I need to do, like change pll2 somehow?

Thanks,

FM

Labels (2)
Tags (3)
0 Kudos
1 Solution
3,426 Views
frankmiller
Contributor IV

Hi Borut,

I finally did get past this problem.  Ultimately what I was trying to do was calibrate the DDR3 RAM against the 1.2 GHz Quad core part.  I ended up having to go through this interesting procedure with the calibration tool.

First, I put the memory parameters into the DDR3 spreadsheet provided by Freescale.

I used the calibration values from this spreadsheet to seed the DDR3 calibration tool.  I then ran the tool and got new calibration values.  I took the output of this tool and fed the values back into the inputs of a second run of the tool.  I did this several times until I discovered that output values were converging.  I then took the converged output values and used them in the u-boot code for calibration and voila, the 4 GB of RAM has worked like a charm since.  I hope this helps you.

Thanks,

FM

View solution in original post

0 Kudos
21 Replies
3,327 Views
peteramond
Contributor V

@Frank Miller

Hi,

My custom hardware is based on i.MX6Q processor and 800MHz Alliance DDR3 memory AS4C256M16D3A-12BCN.Design is most related to Nitrogen6_max design.

 

I set tCL = 6 and tCWL = 8 for the calibration and ddr init script. Some boards are working for this values and for some boards I had to change tCWL = 7 for better performance. Otherwise getting segmentation faults.

 

1) How this could happen with the same ddr layout and same production line boards ?  What can we figure with this fine tuning of tCL and tCWL value of board to board ?

I'm new to custom hardware designs and I'm going to scale up my custom hardware which is functioning well with few boards.  

 

But still I'm having trouble with my hardware which is really difficult to figure out as some boards are working really well and some are not (From 50 units of production). When I do memory calibration those are really looks like same. But although many boards have similar calibration results some are working really well and some are not (As an example lets take 10 boards, only 4 are working really well)

 

Could you please go through with following calibration results of few boards. Please follow the pastebin links.

 

Board 1

Board 2

Board 3

 

Processor - i.MAX6Q

Memory - MT41K256M16TW-107 IT:P

 

From above 3 boards Board 1 and Board 2 are working really well and Board 3 is getting kernel panics while running same application on 3 boards. Can you help me to figure out any clue from this results from above 3 boards ? 

 

I did 50 units of production 6 months ago and only 30 were worked properly. But that is with Alliance memory AS4C256M16D3A-12BCN. So will this be an issue of the design ? If this is an issue of the ddr layout or whole design why some boards are working really well ? 

 

2) Will this be an issue of the manufacturing side ? Then how this could be happen with the same production ? Because some are working and some are not.

 

I don't have much experience with mass production and but I like to move forward after learning and correcting this issues. 

 

I must be thankful to you if you will kindly reply me soon.

 

Many thanks and regards,

Peter.

0 Kudos
3,332 Views
wonderwizard
Contributor III

Sounds like at least some people have having issue with DDR3 tracking constraints. I am currently laying out IMX6Q DDR3 4GB, There seems to be inconsistencies between the Hardware development guide and the Sabre reference board (LAY-27392_C.brd) and (IMX6DQ6SDLHDG Rev 1 06/2013).


The hardware development guides says (Table 3-3) that the address lines cannot be longer than SD_CLK.

The layout for the reference design has the address lines 0.09 inches longer than the ddr clock SD_CLK.


Anyone think I am wrong? If I am not wrong which is correct, the HRG, or reference design?

0 Kudos
3,335 Views
frankmiller
Contributor IV

Since I've had no luck with these solutions, let me ask a different question.  How low can I set the DDR speed with the 528 MHz sourced periph_clk?  Can I drop the DDR clk to 500? or 475? or 452? somehow without changing the input to periph_clk?  If so, how would I go about this?

Thanks,

FM

0 Kudos
3,335 Views
kladu
Contributor II

Hello Frank,

although an old topic, it is still marked "not answered". Were you able to slow down the DDR3 clock? We are experiencing similar problems.


I believe the answer to your last question is minimum 400MHz. It is defined in DDR3 chip. It depends on the CAS latency setup. Freescale uses 8 CLK CAS latency in their script, which is valid from 2.5ns to 1.875ns (400MHz to 533MHz) for an 1600MHz DDR3 device.

regards,

Borut

0 Kudos
3,427 Views
frankmiller
Contributor IV

Hi Borut,

I finally did get past this problem.  Ultimately what I was trying to do was calibrate the DDR3 RAM against the 1.2 GHz Quad core part.  I ended up having to go through this interesting procedure with the calibration tool.

First, I put the memory parameters into the DDR3 spreadsheet provided by Freescale.

I used the calibration values from this spreadsheet to seed the DDR3 calibration tool.  I then ran the tool and got new calibration values.  I took the output of this tool and fed the values back into the inputs of a second run of the tool.  I did this several times until I discovered that output values were converging.  I then took the converged output values and used them in the u-boot code for calibration and voila, the 4 GB of RAM has worked like a charm since.  I hope this helps you.

Thanks,

FM

0 Kudos
3,335 Views
kladu
Contributor II

Thanks!

I never thought that calibration values would converge... We'll try it out.

Best regards,

Borut

0 Kudos
3,335 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Frank

     I think the mmdc_axi_ch0 is sourced from periph_clk, and periph_clk is from pll2 which is 528M, so to get 396MHz for DDR3, you may need to switch clock source of periph_clk from pll2 to pfd396M, you need to check the CCM for clock tree, and switch this clock before DCD table of configuring MMDC. Also, I think the DDR script for 528M an 396M is different, if it still not work, you may need to check the script. But first of all, just make the clock freq right, it must be 396M.

0 Kudos
3,335 Views
frankmiller
Contributor IV

Hi Huang,

Thanks for the reply.

I've already adjusted the script in flash_header.S and that did not change the clock.  That's why I'm asking the question.

The real problem we're having is as follows.  We have 25 boards that are using an i.MX6Q @ 1.2 GHz.  Only a couple of them boot up reliably.  We had built 6 boards previously using a 1 GHz i.MX6D that ran fine.  Both processors are TO1.2 lots.  We upgraded to the 4.0.0 release as well.  We ran DDR3 stress tests on some of the boards and have discovered that there seem to be failures as the DDR3 testing gets to 528 MHz.  This behavior feels like there is some issue with timing margins or something between the processor and the DDR3 memory but we have not been able to isolate it as yet.  We were going to try slowing the memory down on the 25 boards to see if we get better results.  Do you have any other advice?  I noticed another message thread on these boards where someone else was having similar problems:  Tuning DDR3 configurations on iMX6Q board    This other thread was marked as "assumed answered" but it was not clear from that thread what the solution was.

Thanks,

FM

0 Kudos
3,335 Views
PKZ
Contributor III

Hi FM,

I created the thread Tuning DDR3 configurations on iMX6Q board.  The issue is not solved yet.Re: Tuning DDR3 configurations on iMX6Q board

I am thinking to reduce the DDR speed to 500MHz or lower as the stress test looks ok at lower speed (500MHz). Any luck on slowing the DDR speed in Android?

Thanks.

PK

0 Kudos
3,335 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Frank

     I think we need to try 396M first. For some boards that can boot up reliably, did they run @528MHz DDR freq or 396MHz? You said that you have adjust the script to 396M, but the script did not change the clock, that is why I need you to try adding the clock change first, Setting pre_periph_clk select to from pfd396M, you may need to add one DCD item in flash_header.S, DCD(0x20c4018, 0x60324) in front of the MMDC and IOMUX settng. Then you also need to add this length to DCD length parameter. See below:

/* CCM_BASE_ADDR = 0x020C4000 */

/*DDR clk to 400MHz*/

    ldr r0, =CCM_BASE_ADDR

    ldr r1, =0x00060324

    str r1, [r0, #0x018]

[Anson] Change this to DCD(0x20c4018, 0x60324), please check RM to see whether this 0x60324 is right to select PFD396 as pre_periph_clk's parent.

dcd_hdr:          .word 0x40F003D2 /* Tag=0xD2, Len=125*8 + 4 + 4, Ver=0x40 */

write_dcd_cmd:    .word 0x04EC03CC /* Tag=0xCC, Len=125*8 + 4, Param=0x04 */

[Anson]As the DCD number is increased, so upper value need to changed to be 126*8 + 4 + 4 and 126*8 + 4.

     Please try it first to see whether we can make more boards boot up reliably @396M, if it helps, then we can focus on the DDR timing adjustment.

0 Kudos
3,335 Views
frankmiller
Contributor IV

OK, I tried to add this DCD (per the Anson comment to the beginning of my flash_header.S script.  The board does not boot at all now.

Regarding the 0x60324 value, I checked the RM and the the 0x6 prefix does appear to set the pre_periph_clk to 396 MHz as you suggested.  I did note however that the default value for this register is 0x22324 so your 0x60 prefix is setting different values for pre_periph_clk_sel as well as gpu2d_clk_sel, vpu_axi_clk_sel, and periph_clk2_sel?  Also, the default value for this register means that 00 (528 MHz clk) is chosen for pre_periph_clk, but the explanation for bits 18-19 state that 01 should be the default value, which yields a 396 MHz clock default.  Very confusing.  Maybe there's something going on in the ROM here?

Couple things to note here about my flash_header.S script.  We are using 4 GB of DDR3 64-bit in 8 256MB Micron devices.  I had created a script for our dual core boards and things were working fine.  So in this script where you see the // 396 MHz comments are the places I had to change to switch to the 396 MHz speed according to the spreadsheet.  I added the line you recommended at DCD item 1.  This caused me to have to renumber all the other DCD items.  I also bumped up the Len part of the dcd_hdr and write_dcd_cmd labels as directed.

Here is what my flash_header.S script looks like:

#else  /* i.MX6Q */

//dcd_hdr:          .word 0x40a002D2 /* Tag=0xD2, Len=83*8 + 4 + 4, Ver=0x40 */

//write_dcd_cmd:    .word 0x049c02CC /* Tag=0xCC, Len=83*8 + 4, Param=0x04 */

//dcd_hdr:          .word 0x40c802d2 /* Tag=0xD2, Len=88*8 + 4 + 4, Ver=0x40 */

//write_dcd_cmd:    .word 0x04c402cc /* Tag=0xCC, Len=88*8 + 4, Param=0x04 */

dcd_hdr:          .word 0x40d002d2 /* Tag=0xD2, Len=89*8 + 4 + 4, Ver=0x40 */

write_dcd_cmd:    .word 0x04cc02cc /* Tag=0xCC, Len=89*8 + 4, Param=0x04 */

/* DCD */

// <added>

// Change pre_periph_clk to pfd396M

MXC_DCD_ITEM(1, 0x020c4018, 0x00060324)

// </added>

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

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

MXC_DCD_ITEM(4, IOMUXC_BASE_ADDR + 0x588, 0x00000030)

MXC_DCD_ITEM(5, IOMUXC_BASE_ADDR + 0x594, 0x00000030)

MXC_DCD_ITEM(6, IOMUXC_BASE_ADDR + 0x56c, 0x00000030)

MXC_DCD_ITEM(7, IOMUXC_BASE_ADDR + 0x578, 0x00000030)

MXC_DCD_ITEM(8, IOMUXC_BASE_ADDR + 0x74c, 0x00000030)

MXC_DCD_ITEM(9, IOMUXC_BASE_ADDR + 0x57c, 0x00000030)

MXC_DCD_ITEM(10, IOMUXC_BASE_ADDR + 0x58c, 0x00000000)

MXC_DCD_ITEM(11, IOMUXC_BASE_ADDR + 0x59c, 0x00000030)

MXC_DCD_ITEM(12, IOMUXC_BASE_ADDR + 0x5a0, 0x00000030)

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

MXC_DCD_ITEM(14, IOMUXC_BASE_ADDR + 0x750, 0x00020000)

MXC_DCD_ITEM(15, IOMUXC_BASE_ADDR + 0x5a8, 0x00000030)

MXC_DCD_ITEM(16, IOMUXC_BASE_ADDR + 0x5b0, 0x00000030)

MXC_DCD_ITEM(17, IOMUXC_BASE_ADDR + 0x524, 0x00000030)

MXC_DCD_ITEM(18, IOMUXC_BASE_ADDR + 0x51c, 0x00000030)

MXC_DCD_ITEM(19, IOMUXC_BASE_ADDR + 0x518, 0x00000030)

MXC_DCD_ITEM(20, IOMUXC_BASE_ADDR + 0x50c, 0x00000030)

MXC_DCD_ITEM(21, IOMUXC_BASE_ADDR + 0x5b8, 0x00000030)

MXC_DCD_ITEM(22, IOMUXC_BASE_ADDR + 0x5c0, 0x00000030)

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

MXC_DCD_ITEM(24, IOMUXC_BASE_ADDR + 0x784, 0x00000030)

MXC_DCD_ITEM(25, IOMUXC_BASE_ADDR + 0x788, 0x00000030)

MXC_DCD_ITEM(26, IOMUXC_BASE_ADDR + 0x794, 0x00000030)

MXC_DCD_ITEM(27, IOMUXC_BASE_ADDR + 0x79c, 0x00000030)

MXC_DCD_ITEM(28, IOMUXC_BASE_ADDR + 0x7a0, 0x00000030)

MXC_DCD_ITEM(29, IOMUXC_BASE_ADDR + 0x7a4, 0x00000030)

MXC_DCD_ITEM(30, IOMUXC_BASE_ADDR + 0x7a8, 0x00000030)

MXC_DCD_ITEM(31, IOMUXC_BASE_ADDR + 0x748, 0x00000030)

MXC_DCD_ITEM(32, IOMUXC_BASE_ADDR + 0x5ac, 0x00000030)

MXC_DCD_ITEM(33, IOMUXC_BASE_ADDR + 0x5b4, 0x00000030)

MXC_DCD_ITEM(34, IOMUXC_BASE_ADDR + 0x528, 0x00000030)

MXC_DCD_ITEM(35, IOMUXC_BASE_ADDR + 0x520, 0x00000030)

MXC_DCD_ITEM(36, IOMUXC_BASE_ADDR + 0x514, 0x00000030)

MXC_DCD_ITEM(37, IOMUXC_BASE_ADDR + 0x510, 0x00000030)

MXC_DCD_ITEM(38, IOMUXC_BASE_ADDR + 0x5bc, 0x00000030)

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

MXC_DCD_ITEM(40, MMDC_P0_BASE_ADDR + 0x800, 0xA1390003)

MXC_DCD_ITEM(41, MMDC_P0_BASE_ADDR + 0x80c, 0x001F001F)

MXC_DCD_ITEM(42, MMDC_P0_BASE_ADDR + 0x810, 0x001F001F)

MXC_DCD_ITEM(43, MMDC_P1_BASE_ADDR + 0x80c, 0x001F001F)

MXC_DCD_ITEM(44, MMDC_P1_BASE_ADDR + 0x810, 0x001F001F)

//MXC_DCD_ITEM(45, MMDC_P0_BASE_ADDR + 0x83c, 0x4333033F)

MXC_DCD_ITEM(45, MMDC_P0_BASE_ADDR + 0x83c, 0x43270338)

//MXC_DCD_ITEM(46, MMDC_P0_BASE_ADDR + 0x840, 0x032C031D)

MXC_DCD_ITEM(46, MMDC_P0_BASE_ADDR + 0x840, 0x03200314)

//MXC_DCD_ITEM(47, MMDC_P1_BASE_ADDR + 0x83c, 0x43200332)

MXC_DCD_ITEM(47, MMDC_P1_BASE_ADDR + 0x83c, 0x431a032f)

//MXC_DCD_ITEM(48, MMDC_P1_BASE_ADDR + 0x840, 0x031A026A)

MXC_DCD_ITEM(48, MMDC_P1_BASE_ADDR + 0x840, 0x03200263)

//MXC_DCD_ITEM(49, MMDC_P0_BASE_ADDR + 0x848, 0x4D464746)

MXC_DCD_ITEM(49, MMDC_P0_BASE_ADDR + 0x848, 0x4b434748)

//MXC_DCD_ITEM(50, MMDC_P1_BASE_ADDR + 0x848, 0x47453F4D)

MXC_DCD_ITEM(50, MMDC_P1_BASE_ADDR + 0x848, 0x4445404c)

//MXC_DCD_ITEM(51, MMDC_P0_BASE_ADDR + 0x850, 0x3E434440)

MXC_DCD_ITEM(51, MMDC_P0_BASE_ADDR + 0x850, 0x38444542)

//MXC_DCD_ITEM(52, MMDC_P1_BASE_ADDR + 0x850, 0x47384839)

MXC_DCD_ITEM(52, MMDC_P1_BASE_ADDR + 0x850, 0x4935493a)

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

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

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

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

MXC_DCD_ITEM(57, MMDC_P1_BASE_ADDR + 0x81c, 0x33333333)

MXC_DCD_ITEM(58, MMDC_P1_BASE_ADDR + 0x820, 0x33333333)

MXC_DCD_ITEM(59, MMDC_P1_BASE_ADDR + 0x824, 0x33333333)

MXC_DCD_ITEM(60, MMDC_P1_BASE_ADDR + 0x828, 0x33333333)

MXC_DCD_ITEM(61, MMDC_P0_BASE_ADDR + 0x8b8, 0x00000800)

MXC_DCD_ITEM(62, MMDC_P1_BASE_ADDR + 0x8b8, 0x00000800)

//MXC_DCD_ITEM(63, MMDC_P0_BASE_ADDR + 0x004, 0x00020036)

MXC_DCD_ITEM(63, MMDC_P0_BASE_ADDR + 0x004, 0x00020024) // 396 MHz

//MXC_DCD_ITEM(64, MMDC_P0_BASE_ADDR + 0x008, 0x09444040)

MXC_DCD_ITEM(64, MMDC_P0_BASE_ADDR + 0x008, 0x00444040) // 396 MHz

//MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x00c, 0x555A7975)

MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x00c, 0x3f435313) // 396 MHz

//MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x010, 0xFF538F64)

MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x010, 0xb66e8b64) // 396 MHz

//MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x014, 0x01FF00DB)

MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x014, 0x01ff0092) // 396 MHz

//MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x018, 0x00001740)

//MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x018, 0x000f11c0)

MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x018, 0x00001740) // 396 MHz

MXC_DCD_ITEM(69, MMDC_P0_BASE_ADDR + 0x01c, 0x00008000)

MXC_DCD_ITEM(70, MMDC_P0_BASE_ADDR + 0x02c, 0x000026D2)

//MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x030, 0x005A1023)

MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x030, 0x00431023) // 396 MHz

//MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x040, 0x00000027)

//MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x040, 0x0000003f)

MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x040, 0x00000047) // 396 MHz

//MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x000, 0x831A0000)

MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x000, 0xc41a0000)

MXC_DCD_ITEM(74, MMDC_P0_BASE_ADDR + 0x01c, 0x04088032)

MXC_DCD_ITEM(75, MMDC_P0_BASE_ADDR + 0x01c, 0x00008033)

MXC_DCD_ITEM(76, MMDC_P0_BASE_ADDR + 0x01c, 0x00048031)

//MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x01c, 0x09408030)

MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x01c, 0x05208030) // 396 MHz

MXC_DCD_ITEM(78, MMDC_P0_BASE_ADDR + 0x01c, 0x04008040)

// <added>

MXC_DCD_ITEM(79, MMDC_P0_BASE_ADDR + 0x01c, 0x0408803a)

MXC_DCD_ITEM(80, MMDC_P0_BASE_ADDR + 0x01c, 0x0000803b)

MXC_DCD_ITEM(81, MMDC_P0_BASE_ADDR + 0x01c, 0x00048039)

//MXC_DCD_ITEM(82, MMDC_P0_BASE_ADDR + 0x01c, 0x09408038)

MXC_DCD_ITEM(82, MMDC_P0_BASE_ADDR + 0x01c, 0x05208038) // 396 MHz

MXC_DCD_ITEM(83, MMDC_P0_BASE_ADDR + 0x01c, 0x04008048)

// </added>

MXC_DCD_ITEM(84, MMDC_P0_BASE_ADDR + 0x020, 0x00005800)

MXC_DCD_ITEM(85, MMDC_P0_BASE_ADDR + 0x818, 0x00011117)

MXC_DCD_ITEM(86, MMDC_P1_BASE_ADDR + 0x818, 0x00011117)

//MXC_DCD_ITEM(87, MMDC_P0_BASE_ADDR + 0x004, 0x00025576)

MXC_DCD_ITEM(87, MMDC_P0_BASE_ADDR + 0x004, 0x00025564) // 396 MHz

MXC_DCD_ITEM(88, MMDC_P0_BASE_ADDR + 0x404, 0x00011006)

MXC_DCD_ITEM(89, MMDC_P0_BASE_ADDR + 0x01c, 0x00000000)

#endif

0 Kudos
3,335 Views
AnsonHuang
NXP Employee
NXP Employee

Hi, Frank

     below(sorry I do NOT know how to attach a file) is the flash_header.S of 400MHz DDR using plugin mode, this is a debug version when I was trying 400MHz for DDR3, you can have a reference, but I am not sure whether it works on your platform.

#include <config.h>

#include <asm/arch/mx6.h>

#ifdef CONFIG_FLASH_HEADER

#ifndef CONFIG_FLASH_HEADER_OFFSET

# error "Must define the offset of flash header"

#endif

.section ".text.flasheader", "x"

  b _start

  .org CONFIG_FLASH_HEADER_OFFSET

/* First IVT to copy the plugin that initializes the system into OCRAM */

ivt_header:             .long 0x402000D1    /*Tag=0xD1, Len=0x0020, Ver=0x40 */

app_code_jump_v:        .long 0x00907458    /* Plugin entry point, address after the second IVT table */

reserv1:                .long 0x0

dcd_ptr:                .long 0x0

boot_data_ptr:          .long 0x00907420

self_ptr:               .long 0x00907400

app_code_csf:           .long 0x0

reserv2:                .long 0x0

boot_data:              .long 0x00907000

image_len:              .long 16*1024  /* plugin can be upto 16KB in size */

plugin:                 .long 0x1  /* Enable plugin flag */

/* Second IVT to give entry point into the bootloader copied to DDR */

ivt2_header:            .long 0x402000D1    /*Tag=0xD1, Len=0x0020, Ver=0x40 */

app2_code_jump_v:       .long _start       /* Entry point for uboot */

reserv3:                .long 0x0

dcd2_ptr:               .long 0x0

boot_data2_ptr:         .long boot_data2

self_ptr2:              .long ivt2_header

app_code_csf2:          .long 0x0

reserv4:                .long 0x0

boot_data2:             .long TEXT_BASE

image_len2:             .long _end_of_copy  - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET

plugin2:                .long 0x0

/* Here starts the plugin code */

plugin_start:

/* Save the return address and the function arguments */

    push    {r0-r4, lr}

/*

* Note: The DDR settings provided below are specific to Freescale development boards and are the latest settings at the time of release.

* However, it is recommended to contact your Freescale representative in case there are any improvements to these settings.

*/

    /* 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]

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

    The following is to fill in those arguments for this ROM function

    pu_irom_hwcnfg_setup(void **start, size_t *bytes, const void *boot_data)

    This function is used to copy data from the storage media into DDR.

    start - Initial (possibly partial) image load address on entry.  Final image load address on exit.

    bytes - Initial (possibly partial) image size on entry.  Final image size on exit.

    boot_data - Initial @ref ivt Boot Data load address.

*/

    adr r0, DDR_DEST_ADDR

    adr r1, COPY_SIZE

    adr r2, BOOT_DATA

/*

* check the _pu_irom_api_table for the address

*/

before_calling_rom___pu_irom_hwcnfg_setup:

    mov r4, #0x2000

    add r4, r4, #0xed

    blx r4 /* This address might change in future ROM versions */

after_calling_rom___pu_irom_hwcnfg_setup:

/* To return to ROM from plugin, we need to fill in these argument.

* Here is what need to do:

* Need to construct the paramters for this function before return to ROM:

* plugin_download(void **start, size_t *bytes, UINT32 *ivt_offset)

*/

    pop {r0-r4, lr}

    ldr r5, DDR_DEST_ADDR

    str r5, [r0]

    ldr r5, COPY_SIZE

    str r5, [r1]

    mov r5, #0x400  /* Point to the second IVT table at offset 0x42C */

    add r5, r5, #0x2C

    str r5, [r2]

    mov r0, #1

    bx lr          /* return back to ROM code */

DDR_DEST_ADDR:    .word   TEXT_BASE

COPY_SIZE:        .word   _end_of_copy  - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET

BOOT_DATA:        .word   TEXT_BASE

                  .word   _end_of_copy  - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET

                  .word   0

#endif

0 Kudos
3,335 Views
frankmiller
Contributor IV

Hi Huang,

I'm confused.  The only difference between this code and what you posted before is the expanded headers.  I don't think those are the problem.  You are still using the same code to redirect the periph clk which I alread told you doesn't work.  Can you comment on the items I discussed about the use of 0x60324 to accomplish that?

Thanks,

FM

0 Kudos
3,335 Views
byungchul
Contributor II

Also, I was trying to same ploblems.

Results are 480Mhz operations good, but 400Mhz was failed.

<u-boot>

528Mhz --> 480Mhz --> 400Mhz step operation is success, using the clk command in the u-boot.

It's not working problems(400Mhz) is thought to be caused by something happens in the BOOTROM.

<DCD Values for 480Mhz Clock>

# 480MHZ

#CBCDR, 480MHz
MXC_DCD_ITEM(39, CCM_BASE_ADDR + 0x14, 0x02018d00)
#CBCMR, 480MHz
MXC_DCD_ITEM(40, CCM_BASE_ADDR + 0x18, 0x00020324)

MXC_DCD_ITEM(41, MMDC_P0_BASE_ADDR + 0x800, 0xA1390003)

MXC_DCD_ITEM(42, MMDC_P0_BASE_ADDR + 0x80c, 0x001F001F)
MXC_DCD_ITEM(43, MMDC_P0_BASE_ADDR + 0x810, 0x001F001F)
MXC_DCD_ITEM(44, MMDC_P1_BASE_ADDR + 0x80c, 0x001F001F)
MXC_DCD_ITEM(45, MMDC_P1_BASE_ADDR + 0x810, 0x001F001F)

MXC_DCD_ITEM(46, MMDC_P0_BASE_ADDR + 0x83c, 0x4333033F)
MXC_DCD_ITEM(47, MMDC_P0_BASE_ADDR + 0x840, 0x032C031D)
MXC_DCD_ITEM(48, MMDC_P1_BASE_ADDR + 0x83c, 0x43200332)
MXC_DCD_ITEM(49, MMDC_P1_BASE_ADDR + 0x840, 0x031A026A)
MXC_DCD_ITEM(50, MMDC_P0_BASE_ADDR + 0x848, 0x4D464746)
MXC_DCD_ITEM(51, MMDC_P1_BASE_ADDR + 0x848, 0x47453F4D)
MXC_DCD_ITEM(52, MMDC_P0_BASE_ADDR + 0x850, 0x3E434440)
MXC_DCD_ITEM(53, MMDC_P1_BASE_ADDR + 0x850, 0x47384839)

MXC_DCD_ITEM(54, MMDC_P0_BASE_ADDR + 0x81c, 0x33333333)
MXC_DCD_ITEM(55, MMDC_P0_BASE_ADDR + 0x820, 0x33333333)
MXC_DCD_ITEM(56, MMDC_P0_BASE_ADDR + 0x824, 0x33333333)
MXC_DCD_ITEM(57, MMDC_P0_BASE_ADDR + 0x828, 0x33333333)
MXC_DCD_ITEM(58, MMDC_P1_BASE_ADDR + 0x81c, 0x33333333)
MXC_DCD_ITEM(59, MMDC_P1_BASE_ADDR + 0x820, 0x33333333)
MXC_DCD_ITEM(60, MMDC_P1_BASE_ADDR + 0x824, 0x33333333)
MXC_DCD_ITEM(61, MMDC_P1_BASE_ADDR + 0x828, 0x33333333)

MXC_DCD_ITEM(62, MMDC_P0_BASE_ADDR + 0x8b8, 0x00000800)
MXC_DCD_ITEM(63, MMDC_P1_BASE_ADDR + 0x8b8, 0x00000800)

#MMDC init
MXC_DCD_ITEM(64, MMDC_P0_BASE_ADDR + 0x004, 0x0002002D)
MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x008, 0x00333040)
MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x00c, 0x3F4352F3)
MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x010, 0xB66D8B63)
MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x014, 0x01FF00DB)

#MDMISC
MXC_DCD_ITEM(69, MMDC_P0_BASE_ADDR + 0x018, 0x00001740)
MXC_DCD_ITEM(70, MMDC_P0_BASE_ADDR + 0x01c, 0x00008000)
MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x02c, 0x000026D2)
MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x030, 0x00431023)
MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x040, 0x00000027)
MXC_DCD_ITEM(74, MMDC_P0_BASE_ADDR + 0x000, 0x831A0000)

# Initialize 2GB DDR3 - Micron MT41J128M
MXC_DCD_ITEM(75, MMDC_P0_BASE_ADDR + 0x01c, 0x02008032)
MXC_DCD_ITEM(76, MMDC_P0_BASE_ADDR + 0x01c, 0x00008033)
MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x01c, 0x00048031)
MXC_DCD_ITEM(78, MMDC_P0_BASE_ADDR + 0x01c, 0x05208030)
MXC_DCD_ITEM(79, MMDC_P0_BASE_ADDR + 0x01c, 0x04008040)

MXC_DCD_ITEM(80, MMDC_P0_BASE_ADDR + 0x020, 0x00007800)

MXC_DCD_ITEM(81, MMDC_P0_BASE_ADDR + 0x818, 0x00022227)
MXC_DCD_ITEM(82, MMDC_P1_BASE_ADDR + 0x818, 0x00022227)

MXC_DCD_ITEM(83, MMDC_P0_BASE_ADDR + 0x004, 0x0002556D)
MXC_DCD_ITEM(84, MMDC_P0_BASE_ADDR + 0x404, 0x00011006)
MXC_DCD_ITEM(85, MMDC_P0_BASE_ADDR + 0x01c, 0x00000000)

0 Kudos
3,335 Views
frankmiller
Contributor IV

How did you use the clk command?  I was under the impression that this was not implemented for mx6q u-boot?

Thanks,

FM

0 Kudos
3,335 Views
byungchul
Contributor II

Hi, FM

clk command usage.

*. step 1 --> 2 is ok, but direct to go down step2 failed.

MX6Q U-Boot > help clk
clk - Clock sub system

Usage:
clk Setup/Display clock
clk - Display all clocks
clk core <core clock in MHz> - Setup/Display core clock
clk periph <peripheral clock in MHz> -Setup/Display peripheral clock
clk ddr <DDR clock in MHz> - Setup/Display DDR clock
clk nfc <NFC clk in MHz> - Setup/Display NFC clock
Example:
clk - Show various clocks
clk core 665 - Set core clock to 665MHz
clk periph 600 - Set peripheral clock to 600MHz
clk ddr 166 - Set DDR clock to 166MHz

1. Down 480Mhz.

MX6Q U-Boot > clk periph 480
source=pll3

CBCMR=00020324
CBCDR=02018d00


MX6Q U-Boot > clk
cpu clock: 984MHz
mx6q pll1: 984MHz
mx6q pll2: 528MHz
mx6q pll3: 480MHz
mx6q pll8: 50MHz
ipg clock     : 60000000Hz
ipg per clock : 60000000Hz
uart clock    : 80000000Hz
cspi clock    : 60000000Hz
ahb clock     : 120000000Hz
axi clock   : 240000000Hz
emi_slow clock: 120000000Hz
ddr clock     : 480000000Hz
usdhc1 clock  : 198000000Hz
usdhc2 clock  : 198000000Hz
usdhc3 clock  : 198000000Hz
usdhc4 clock  : 198000000Hz
nfc clock     : 11000000Hz

2. Down 400Mhz.

MX6Q U-Boot > clk periph 400
source=pll2_pfd_400m

CBCMR=00060324
CBCDR=00018d00
MX6Q U-Boot > clk
cpu clock: 984MHz
mx6q pll1: 984MHz
mx6q pll2: 528MHz
mx6q pll3: 480MHz
mx6q pll8: 50MHz
ipg clock     : 49500000Hz
ipg per clock : 49500000Hz
uart clock    : 80000000Hz
cspi clock    : 60000000Hz
ahb clock     : 99000000Hz
axi clock   : 198000000Hz
emi_slow clock: 99000000Hz
ddr clock     : 396000000Hz
usdhc1 clock  : 198000000Hz
usdhc2 clock  : 198000000Hz
usdhc3 clock  : 198000000Hz
usdhc4 clock  : 198000000Hz
nfc clock     : 11000000Hz

0 Kudos
3,335 Views
frankmiller
Contributor IV

Thanks for this.  I was using 'clk ddr ...' and that did not change the ddr clk.  Interesting that 'clk periph ...' changes the ddr clk when there is a specific subcommand to set the ddr clk.

When I do 'clk periph 480' it seems to take.  When I do 'clk periph 400' the board hangs.  I do not get the source, CBCMR and CBCDR output.  Did you modify your code to do that?

Thanks,

FM

0 Kudos
3,335 Views
byungchul
Contributor II

Yes,  i modified source code, as bellows.

u-boot : u-boot-2009.08

file : cpu/arm_cortexa8/mx6/generic.c

static int config_periph_clk(u32 ref, u32 freq)
{
u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
u32 pll2_freq = __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ);
u32 pll3_freq = __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ);

if (freq >=  pll2_freq) {
  printf("source=pll2\n");
  /* PLL2 */
  writel(cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK,
   CCM_BASE_ADDR + CLKCTL_CBCMR);
  writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL,
   CCM_BASE_ADDR + CLKCTL_CBCDR);
} else if (freq < pll2_freq && freq >= pll3_freq) {
  printf("source=pll3\n");
  /* PLL3 */
  writel(cbcmr & ~MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK,
   CCM_BASE_ADDR + CLKCTL_CBCMR);
  writel(cbcdr | MXC_CCM_CBCDR_PERIPH_CLK_SEL,
   CCM_BASE_ADDR + CLKCTL_CBCDR);
} else if (freq < pll3_freq && freq >= PLL2_PFD2_FREQ) {
  printf("source=pll2_pfd_400m\n");
  /* 400M PLL2 PFD */
  cbcmr = (cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) |
   (1 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
  writel(cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR);
  writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL,
   CCM_BASE_ADDR + CLKCTL_CBCDR);
} else if (freq < PLL2_PFD2_FREQ && freq >= PLL2_PFD0_FREQ) {
  printf("source=pll2_pfd_325m\n");
  /* 352M PLL2 PFD */
  cbcmr = (cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) |
   (2 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
  writel(cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR);
  writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL,
   CCM_BASE_ADDR + CLKCTL_CBCDR);
} else if (freq == PLL2_PFD2_DIV_FREQ) {
  printf("source=pll2_pfd_200m\n");
  /* 200M PLL2 PFD */
  cbcmr = (cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) |
   (3 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
  writel(cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR);
  writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL,
   CCM_BASE_ADDR + CLKCTL_CBCDR);
} else {
  printf("Frequency requested not within range [%d-%d] MHz\n",
   PLL2_PFD2_DIV_FREQ / SZ_DEC_1M, pll2_freq / SZ_DEC_1M);
  return -1;
}
puts("\n");

// bcchae
printf("CBCMR=%08lx\n",readl(CCM_BASE_ADDR + CLKCTL_CBCMR));
printf("CBCDR=%08lx\n",readl(CCM_BASE_ADDR + CLKCTL_CBCDR));

return 0;
}

0 Kudos
3,335 Views
Chris1z
Contributor III

Hi byungchul,

I have a couple of questions for you:

1) What version of Android/Linux BSP are you running.  I see that your initial clock values are different than mine.  I'm using Android 4.2.2-1.1.0 ga on a SabreSD board.  We have different cpu, ipg, ahb, axi and emi clocks.

MX6Q SABRESD U-Boot > clk

cpu clock: 792MHz

mx6q pll1: 792MHz

mx6q pll2: 528MHz

mx6q pll3: 480MHz

mx6q pll8: 50MHz

ipg clock     : 66000000Hz

ipg per clock : 66000000Hz

uart clock    : 80000000Hz

cspi clock    : 60000000Hz

ahb clock     : 132000000Hz

axi clock   : 264000000Hz

emi_slow clock: 132000000Hz

ddr clock     : 528000000Hz

usdhc1 clock  : 198000000Hz

usdhc2 clock  : 198000000Hz

usdhc3 clock  : 198000000Hz

usdhc4 clock  : 198000000Hz

nfc clock     : 24000000Hz

2) If I use your procedure of changing the periph clock down to 480 first and then down to 400 I am able to see the clock change without hanging.  But as soon as I type 'boot', it hangs when loading the kernel.  Do you see this as well? 

0 Kudos
3,335 Views
byungchul
Contributor II

Hi, FM

The answers are

1) What version of Android/Linux BSP are you running.  I see that your initial clock values are different than mine.  I'm using Android 4.2.2-1.1.0 ga on a SabreSD board.  We have different cpu, ipg, ahb, axi and emi clocks.

MX6Q SABRESD U-Boot > clk

cpu clock: 792MHz

mx6q pll1: 792MHz

mx6q pll2: 528MHz

mx6q pll3: 480MHz

mx6q pll8: 50MHz

ipg clock    : 66000000Hz

ipg per clock : 66000000Hz

uart clock    : 80000000Hz

cspi clock    : 60000000Hz

ahb clock    : 132000000Hz

axi clock  : 264000000Hz

emi_slow clock: 132000000Hz

ddr clock    : 528000000Hz

usdhc1 clock  : 198000000Hz

usdhc2 clock  : 198000000Hz

usdhc3 clock  : 198000000Hz

usdhc4 clock  : 198000000Hz

nfc clock    : 24000000Hz

OS : Linux 3.0.35, No android

Board : SabreSD

As cpu clock & pll1 is differrent, don't mind this values.

I was modified change the init cpu clock, for the fast booting.

2) If I use your procedure of changing the periph clock down to 480 first and then down to 400 I am able to see the clock change without hanging.  But as soon as I type 'boot', it hangs when loading the kernel.  Do you see this as well?

OS booting failed at 400Mhz clock, but memory test is good in the u-boot.

0 Kudos