DDRCTRL and DDRPHYC device tree configuration

1 Article purpose[edit]

This article explains how to configure the DDRCTRL and DDRPHYC internal peripherals from the first stage bootloader.

The configuration is performed using the device tree mechanism that provides a hardware description of the DDR subsystem (DDR controler and DDR PHY peripheral), and embeds the configuration used by the first stage bootloader to initialize the DDR before loading the second stage bootloader.

The DDR settings are only used in the device tree of the boot chain FSBL, that is, in the TF-A device tree for OpenSTLinux official delivery (or in SPL only for the DDR tuning tool).

2 DT bindings documentation[edit]

The DDR subsystem is a 'memory-controller' device represented by the device tree bindings documented below:

  • TF-A: docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt"[1]
  • U-Boot: doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt"[2]

3 DT configuration[edit]

This hardware description is a combination of the STM32 microprocessor device tree files (.dtsi extension) and board device tree files (.dts extension). See the Device tree for an explanation of the device-tree file split.

STM32CubeMX can be used to generate this DDR board device tree. Refer to How to configure the DT using STM32CubeMX for more details.

3.1 DT configuration (STM32 level)[edit]

The STM32MP1 DDR node is located in stm32mp15-ddr.dtsi[3] (see Device tree for further explanation).

 / {
 ...
 	soc {
 ...
 		ddr: ddr@5a003000{
   			compatible = "st,stm32mp1-ddr";
 
 			reg = <0x5A003000 0x550
 			       0x5A004000 0x234>;
 
 			clocks = <&rcc_clk AXIDCG>,
 				 <&rcc_clk DDRC1>,
 				 <&rcc_clk DDRC2>,
 				 <&rcc_clk DDRPHYC>,
 				 <&rcc_clk DDRCAPB>,
 				 <&rcc_clk DDRPHYCAPB>;
 
 			clock-names = "axidcg",
 				      "ddrc1",
 				      "ddrc2",
 				      "ddrphyc",
 				      "ddrcapb",
 				      "ddrphycapb";
 
 			status = "okay";
 		};
 	};
 };
Warning.png This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end user.

3.2 DT configuration (board level)[edit]

The next attributes provide the DDR information and DDR settings; the values used by the FSBL to initialize the registers of the DDR subsystem (the DDR controller and the DDR PHY).

These value are generated by DDR tools included in STM32CubeMX.

The board configuration defines each configuration needed (DDR_...) and includes the STM32-level device tree.

3.2.1 info[edit]

  • st,mem-name: name for the DDR configuration, a simple string for information
  • st,mem-speed: DDR expected speed in kHz
  • st,mem-size: DDR mem size in bytes (used in SSBL and FSBL)

3.2.2 Controller register values[edit]

  • st,ctl-reg: controller values depending on the DDR type (DDR3/LPDDR2/LPDDR3):
    • for STM32MP15x lines More info.png 25 values are requested in this order: (MSTR MRCTRL0 MRCTRL1 DERATEEN DERATEINT PWRCTL PWRTMG HWLPCTL RFSHCTL0 RFSHCTL3 CRCPARCTL0 ZQCTL0 DFITMG0 DFITMG1 DFILPCFG0 DFIUPD0 DFIUPD1 DFIUPD2 DFIPHYMSTR ODTMAP DBG0 DBG1 DBGCMD POISONCFG PCCFG)
  • st,ctl-timing: controller values depending on the DDR frequency and timing parameters:
    • for STM32MP15x lines More info.png 12 values are requested in this order: (RFSHTMG DRAMTMG0 DRAMTMG1 DRAMTMG2 DRAMTMG3 DRAMTMG4 DRAMTMG5 DRAMTMG6 DRAMTMG7 DRAMTMG8 DRAMTMG14 ODTCFG)
  • st,ctl-map: controller values depending on the address mapping:
    • for STM32MP15x lines More info.png 9 values are requested in this order: (ADDRMAP1 ADDRMAP2 ADDRMAP3 ADDRMAP4 ADDRMAP5 ADDRMAP6 ADDRMAP9 ADDRMAP10 ADDRMAP11)
  • st,ctl-perf: controller values depending on performance and scheduling:
    • for STM32MP15x lines More info.png 17 values are requested in this order: (SCHED SCHED1 PERFHPR1 PERFLPR1 PERFWR1 PCFGR_0 PCFGW_0 PCFGQOS0_0 PCFGQOS1_0 PCFGWQOS0_0 PCFGWQOS1_0 PCFGR_1 PCFGW_1 PCFGQOS0_1 PCFGQOS1_1 PCFGWQOS0_1 PCFGWQOS1_1)

3.2.3 phy register values[edit]

  • st,phy-reg: phy values depending on the DDR type: (DDR3/LPDDR2/LPDDR3):
    • for STM32MP15x lines More info.png 11 values are requested in this order: (PGCR ACIOCR DXCCR DSGCR DCR ODTCR ZQ0CR1 DX0GCR DX1GCR DX2GCR DX3GCR)
  • st,phy-timing: phy values depending on the DDR frequency and timing parameters:
    • for STM32MP15x lines More info.png 10 values are requested in this order: (PTR0 PTR1 PTR2 DTPR0 DTPR1 DTPR2 MR0 MR1 MR2 MR3)
  • st,phy-cal: phy cal depending on the DDR calibration or tuning. This parameter is optional: when it is absent, the built-in PHY calibration is done (see the next chapter for details); when it is present:
    • for STM32MP15x lines More info.png 12 values are requested in this order: (DX0DLLCR DX0DQTR DX0DQSTR DX1DLLCR DX1DQTR DX1DQSTR DX2DLLCR DX2DQTR DX2DQSTR DX3DLLCR DX3DQTR DX3DQSTR)
3.2.3.1 st,phy-cal value and DDR tuning[edit]

By default, the st,phy-cal property is absent in device tree and the built-in PHY calibration is executed by the DDR driver to determine DXnDQTR and DXnDQSTR register values (with n = byte id, 0 to 3).

When st,phy-cal is present in device tree (e.g. when DDR_PHY_CAL_SKIP is defined), the built-in PHY calibration is skipped and the driver use the DXnDQTR and DXnDQSTR values defined in the device tree: they described the fine step delays used for DQ/DQS pin deskew and for eye centering. These optimal values are determined by the STM32CubeMX DDR Tuning Tool calibration result.

This DDR tuning is expected only during the bring-up of a new design and only when the build-in calibration is not enough to determine the optimal values for the above registers; the following procedure may be used:

  • run multiple tunings on the same board (with power ON/OFF cycle or reset), the DQ/DQS line delays are expected to be stable (1step max), otherwise a noise issue on PCB may be suspected.
  • run the DDR tuning on multiple boards to determine the best values, board to board variations are expected to be low (1 step in typical case, 2 steps in worst cases)

Then the best values are saved in the device tree and will be applied to all boards.

See #How to configure the DT using STM32CubeMX and the dedicated application note[4] for further information.

3.3 DT configuration examples[edit]

3.3.1 Simple example[edit]

You can add the DDR configuration node with :

  1   / {
  2   ...
  3   	soc {
  4   		ddr: ddr@5a003000{
  5     			compatible = "st,stm32mp1-ddr";
  6   
  7   			reg = <0x5A003000 0x550
  8   			       0x5A004000 0x234>;
  9   
 10   			clocks = <&rcc_clk AXIDCG>,
 11   				 <&rcc_clk DDRC1>,
 12   				 <&rcc_clk DDRC2>,
 13   				 <&rcc_clk DDRPHYC>,
 14   				 <&rcc_clk DDRCAPB>,
 15   				 <&rcc_clk DDRPHYCAPB>;
 16   
 17   			clock-names = "axidcg",
 18   				      "ddrc1",
 19   				      "ddrc2",
 20   				      "ddrphyc",
 21   				      "ddrcapb",
 22   				      "ddrphycapb";
 23   
 24   			st,mem-name = "DDR3 2x4Gb 533MHz";
 25   			st,mem-speed = <533000>;
 26   			st,mem-size = <0x40000000>;
 27   
 28   			st,ctl-reg = <
 29   				0x00040401 /*MSTR*/
 30   				0x00000010 /*MRCTRL0*/
 31   				0x00000000 /*MRCTRL1*/
 32   				0x00000000 /*DERATEEN*/
 33   				0x00800000 /*DERATEINT*/
 34   				0x00000000 /*PWRCTL*/
 35   				0x00400010 /*PWRTMG*/
 36   				0x00000000 /*HWLPCTL*/
 37   				0x00210000 /*RFSHCTL0*/
 38   				0x00000000 /*RFSHCTL3*/
 39   				0x00000000 /*CRCPARCTL0*/
 40   				0xC2000040 /*ZQCTL0*/
 41   				0x02050105 /*DFITMG0*/
 42   				0x00000202 /*DFITMG1*/
 43   				0x07000000 /*DFILPCFG0*/
 44   				0xC0400003 /*DFIUPD0*/
 45   				0x00000000 /*DFIUPD1*/
 46   				0x00000000 /*DFIUPD2*/
 47   				0x00000000 /*DFIPHYMSTR*/
 48   				0x00000001 /*ODTMAP*/
 49   				0x00000000 /*DBG0*/
 50   				0x00000000 /*DBG1*/
 51   				0x00000000 /*DBGCMD*/
 52   				0x00000000 /*POISONCFG*/
 53   				0x00000010 /*PCCFG*/
 54   			>;
 55   
 56   			st,ctl-timing = <
 57   				0x0080008A /*RFSHTMG*/
 58   				0x121B2414 /*DRAMTMG0*/
 59   				0x000D041B /*DRAMTMG1*/
 60   				0x0607080E /*DRAMTMG2*/
 61   				0x0050400C /*DRAMTMG3*/
 62   				0x07040407 /*DRAMTMG4*/
 63   				0x06060303 /*DRAMTMG5*/
 64   				0x02020002 /*DRAMTMG6*/
 65   				0x00000202 /*DRAMTMG7*/
 66   				0x00001005 /*DRAMTMG8*/
 67   				0x000D041B /*DRAMTMG14*/
 68   				0x06000600 /*ODTCFG*/
 69   			>;
 70   
 71   			st,ctl-map = <
 72   				0x00080808 /*ADDRMAP1*/
 73   				0x00000000 /*ADDRMAP2*/
 74   				0x00000000 /*ADDRMAP3*/
 75   				0x00001F1F /*ADDRMAP4*/
 76   				0x07070707 /*ADDRMAP5*/
 77   				0x0F070707 /*ADDRMAP6*/
 78   				0x00000000 /*ADDRMAP9*/
 79   				0x00000000 /*ADDRMAP10*/
 80   				0x00000000 /*ADDRMAP11*/
 81   			>;
 82   
 83   			st,ctl-perf = <
 84   				0x00001201 /*SCHED*/
 85   				0x00001201 /*SCHED*/1
 86   				0x01000001 /*PERFHPR1*/
 87   				0x08000200 /*PERFLPR1*/
 88   				0x08000400 /*PERFWR1*/
 89   				0x00010000 /*PCFGR_0*/
 90   				0x00000000 /*PCFGW_0*/
 91   				0x02100B03 /*PCFGQOS0_0*/
 92   				0x00800100 /*PCFGQOS1_0*/
 93   				0x01100B03 /*PCFGWQOS0_0*/
 94   				0x01000200 /*PCFGWQOS1_0*/
 95   				0x00010000 /*PCFGR_1*/
 96   				0x00000000 /*PCFGW_1*/
 97   				0x02100B03 /*PCFGQOS0_1*/
 98   				0x00800000 /*PCFGQOS1_1*/
 99   				0x01100B03 /*PCFGWQOS0_1*/
100   				0x01000200 /*PCFGWQOS1_1*/
101   			>;
102   
103   			st,phy-reg = <
104   				0x01442E02 /*PGCR*/
105   				0x10400812 /*ACIOCR*/
106   				0x00000C40 /*DXCCR*/
107   				0xF200001F /*DSGCR*/
108   				0x0000000B /*DCR*/
109   				0x00010000 /*ODTCR*/
110   				0x0000007B /*ZQ0CR1*/
111   				0x0000CE81 /*DX0GCR*/
112   				0x0000CE81 /*DX1GCR*/
113   				0x0000CE81 /*DX2GCR*/
114   				0x0000CE81 /*DX3GCR*/
115   			>;
116   
117   			st,phy-timing = <
118   				0x0022A41B /*PTR0*/
119   				0x047C0740 /*PTR1*/
120   				0x042D9C80 /*PTR2*/
121   				0x369477D0 /*DTPR0*/
122   				0x098A00D8 /*DTPR1*/
123   				0x10023600 /*DTPR2*/
124   				0x00000830 /*MR0*/
125   				0x00000000 /*MR1*/
126   				0x00000208 /*MR2*/
127   				0x00000000 /*MR3*/
128   			>;
129   
130   			status = "okay";
131         };

The optional node st,phy-cal allows to use a calibration result when it is present, for example:

 1   / {
 2   ...
 3   	soc {
 4   		ddr: ddr@5a003000{
 5     			compatible = "st,stm32mp1-ddr";
 6 ...  
 7   			st,phy-cal = <
 8   				0x40000000 /*DX0DLLCR*/
 9   				0xFFFFFFFF /*DX0DQTR*/
10   				0x3DB02000 /*DX0DQSTR*/
11   				0x40000000 /*DX1DLLCR*/
12   				0xFFFFFFFF /*DX1DQTR*/
13   				0x3DB02000 /*DX1DQSTR*/
14   				0x40000000 /*DX2DLLCR*/
15   				0xFFFFFFFF /*DX2DQTR*/
16   				0x3DB02000 /*DX2DQSTR*/
17   				0x40000000 /*DX3DLLCR*/
18   				0xFFFFFFFF /*DX3DQTR*/
19   				0x3DB02000 /*DX3DQSTR*/
20   			>;
21 ...
22         };

3.3.2 STM32CubeMX configuration file[edit]

STM32CubeMX generates a .dtsi file with the needed values as defines (named DDR_...), and includes the #Generic DDR dtsi file "stm32mp15-ddr.dtsi"[3]: as this dtsi file is preprocessed during FSBL compilation, it generates a correct device tree.

For example the file fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi is:

  / SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  /*
   * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs
   * DDR type: DDR3 / DDR3L
   * DDR width: 16bits
   * DDR density: 4Gb
   * System frequency: 533000Khz
   * Relaxed Timing Mode: false
   * Address mapping type: RBC
   *
   * Save Date: 2020.02.20, save Time: 18:45:20
   */
  
  #define DDR_MEM_NAME	"DDR3-DDR3L 16bits 533000Khz"
  #define DDR_MEM_SPEED	533000
  #define DDR_MEM_SIZE	0x20000000
 
  #define DDR_MSTR 0x00041401
  #define DDR_MRCTRL0 0x00000010
  #define DDR_MRCTRL1 0x00000000
  #define DDR_DERATEEN 0x00000000
  #define DDR_DERATEINT 0x00800000
  .....
  #define DDR_DX2DQSTR 0x3DB02000
  #define DDR_DX3GCR 0x0000CE80
  #define DDR_DX3DLLCR 0x40000000
  #define DDR_DX3DQTR 0xFFFFFFFF
  #define DDR_DX3DQSTR 0x3DB02000
  
  #include "stm32mp15-ddr.dtsi"

NB: the calibration values (DXnDLLCR, DXnDQTR, DXnDQSTR, with n in 1...3) are not used when DDR_PHY_CAL_SKIP is not defined

3.3.3 Generic DDR dtsi file[edit]

The dtsi file used with DDR_ defines for STM32MP15x lines More info.png is stm32mp15-ddr.dtsi

  1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  2 /*
  3  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
  4  */
  5 
  6 / {
  7 	soc {
  8 		ddr: ddr@5a003000{
  9 
 10 			compatible = "st,stm32mp1-ddr";
 11 
 12 			reg = <0x5A003000 0x550
 13 			       0x5A004000 0x234>;
 14 
 15 			clocks = <&rcc AXIDCG>,
 16 				 <&rcc DDRC1>,
 17 				 <&rcc DDRC2>,
 18 				 <&rcc DDRPHYC>,
 19 				 <&rcc DDRCAPB>,
 20 				 <&rcc DDRPHYCAPB>;
 21 
 22 			clock-names = "axidcg",
 23 				      "ddrc1",
 24 				      "ddrc2",
 25 				      "ddrphyc",
 26 				      "ddrcapb",
 27 				      "ddrphycapb";
 28 
 29 			st,mem-name = DDR_MEM_NAME;
 30 			st,mem-speed = <DDR_MEM_SPEED>;
 31 			st,mem-size = <DDR_MEM_SIZE>;
 32 
 33 			st,ctl-reg = <
 34 				DDR_MSTR
 35 				DDR_MRCTRL0
 36 				DDR_MRCTRL1
 37 				DDR_DERATEEN
 38 				DDR_DERATEINT
 39 				DDR_PWRCTL
 40 				DDR_PWRTMG
 41 				DDR_HWLPCTL
 42 				DDR_RFSHCTL0
 43 				DDR_RFSHCTL3
 44 				DDR_CRCPARCTL0
 45 				DDR_ZQCTL0
 46 				DDR_DFITMG0
 47 				DDR_DFITMG1
 48 				DDR_DFILPCFG0
 49 				DDR_DFIUPD0
 50 				DDR_DFIUPD1
 51 				DDR_DFIUPD2
 52 				DDR_DFIPHYMSTR
 53 				DDR_ODTMAP
 54 				DDR_DBG0
 55 				DDR_DBG1
 56 				DDR_DBGCMD
 57 				DDR_POISONCFG
 58 				DDR_PCCFG
 59 			>;
 60 
 61 			st,ctl-timing = <
 62 				DDR_RFSHTMG
 63 				DDR_DRAMTMG0
 64 				DDR_DRAMTMG1
 65 				DDR_DRAMTMG2
 66 				DDR_DRAMTMG3
 67 				DDR_DRAMTMG4
 68 				DDR_DRAMTMG5
 69 				DDR_DRAMTMG6
 70 				DDR_DRAMTMG7
 71 				DDR_DRAMTMG8
 72 				DDR_DRAMTMG14
 73 				DDR_ODTCFG
 74 			>;
 75 
 76 			st,ctl-map = <
 77 				DDR_ADDRMAP1
 78 				DDR_ADDRMAP2
 79 				DDR_ADDRMAP3
 80 				DDR_ADDRMAP4
 81 				DDR_ADDRMAP5
 82 				DDR_ADDRMAP6
 83 				DDR_ADDRMAP9
 84 				DDR_ADDRMAP10
 85 				DDR_ADDRMAP11
 86 			>;
 87 
 88 			st,ctl-perf = <
 89 				DDR_SCHED
 90 				DDR_SCHED1
 91 				DDR_PERFHPR1
 92 				DDR_PERFLPR1
 93 				DDR_PERFWR1
 94 				DDR_PCFGR_0
 95 				DDR_PCFGW_0
 96 				DDR_PCFGQOS0_0
 97 				DDR_PCFGQOS1_0
 98 				DDR_PCFGWQOS0_0
 99 				DDR_PCFGWQOS1_0
100 				DDR_PCFGR_1
101 				DDR_PCFGW_1
102 				DDR_PCFGQOS0_1
103 				DDR_PCFGQOS1_1
104 				DDR_PCFGWQOS0_1
105 				DDR_PCFGWQOS1_1
106 			>;
107 
108 			st,phy-reg = <
109 				DDR_PGCR
110 				DDR_ACIOCR
111 				DDR_DXCCR
112 				DDR_DSGCR
113 				DDR_DCR
114 				DDR_ODTCR
115 				DDR_ZQ0CR1
116 				DDR_DX0GCR
117 				DDR_DX1GCR
118 				DDR_DX2GCR
119 				DDR_DX3GCR
120 			>;
121 
122 			st,phy-timing = <
123 				DDR_PTR0
124 				DDR_PTR1
125 				DDR_PTR2
126 				DDR_DTPR0
127 				DDR_DTPR1
128 				DDR_DTPR2
129 				DDR_MR0
130 				DDR_MR1
131 				DDR_MR2
132 				DDR_MR3
133 			>;
134 
135 #ifdef DDR_PHY_CAL_SKIP
136 			st,phy-cal = <
137 				DDR_DX0DLLCR
138 				DDR_DX0DQTR
139 				DDR_DX0DQSTR
140 				DDR_DX1DLLCR
141 				DDR_DX1DQTR
142 				DDR_DX1DQSTR
143 				DDR_DX2DLLCR
144 				DDR_DX2DQTR
145 				DDR_DX2DQSTR
146 				DDR_DX3DLLCR
147 				DDR_DX3DQTR
148 				DDR_DX3DQSTR
149 			>;
150 #endif
151 
152 			status = "okay";
153 		};
154 	};
155 };

4 How to configure the DT using STM32CubeMX[edit]

The STM32CubeMX tool can be used to configure the STM32MPU device and get the corresponding platform configuration device tree files.

The STM32CubeMX supports all the defines described in the above DT bindings documentation paragraph with a generated included file "stm32mp15-mx.dtsi"; it is included in the mx dts file before the #Generic DDR dtsi file . Refer to the STM32CubeMX user manual and the dedicated application note[4] for further information.

See also How_to_create_your_board_device_tree#DDR configuration with STM32CubeMX DDR Tuning Tool.

If you want to use the STM32CubeMX DDR Tuning Tool calibration result, add in the generated files "stm32mp15-mx.dtsi" the line:

 #define DDR_PHY_CAL_SKIP

5 References[edit]

Please refer to the following links for additional information: