1. Article purpose[edit source]
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; so in the TF-A device tree for OpenSTLinux official delivery (or in SPL only for the DDR tuning tool).
Even if the DDR node information is also present in the U-Boot device tree, only the st,mem-size is used by this SSBL.
2. DT bindings documentation[edit source]
The DDR subsystem is a 'memory-controllers' 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/ram/st,stm32mp1-ddr.tx"[2]
3. DT configuration[edit source]
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 source]
The STM32MP1 DDR node is located in stm32mp15-ddr.dtsi[3] (see Device tree for further explanation).
/ { ... soc { ... ddr: ddr@0x5A003000{ 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"; }; }; };
3.2. DT configuration (board level)[edit source]
The next attributes provide the DDR information and DDR settings: the values used by 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.
3.2.1. info[edit source]
- st,mem-name: name for DDR configuration, simple string for information
- st,mem-speed: DDR expected speed in kHz
- st,mem-size: DDR mem size in byte (used in SSBL and FSBL)
3.2.2. Controller register values[edit source]
- st,ctl-reg: controller values depending on the DDR type (DDR3/LPDDR2/LPDDR3)
- st,ctl-timing: controller values depending on frequency and timing parameters of the DDR
- st,ctl-map: controller values depending on the address mapping
- st,ctl-perf: controller values depending on performance and scheduling
3.2.3. phy register values[edit source]
- st,phy-reg: phy values depending of the DDR type (DDR3/LPDDR2/LPDDR3)
- st,phy-timing: phy values depending of frequency and timing parameter of DDR
- st,phy-cal: phy cal depending of calibration or tuning of DDR
The board configuration defines each needed configuration (DDR_...) and includes the STM32 level device tree.
3.3. DT configuration examples[edit source]
3.3.1. Simple example[edit source]
You can add the DDR configuration node with :
/ { ... soc { ddr: ddr@0x5A003000{ 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"; st,mem-name = "DDR3 2x4Gb 533MHz"; st,mem-speed = <533000>; st,mem-size = <0x40000000>; st,ctl-reg = < 0x00040401 /*MSTR*/ 0x00000010 /*MRCTRL0*/ 0x00000000 /*MRCTRL1*/ 0x00000000 /*DERATEEN*/ 0x00800000 /*DERATEINT*/ 0x00000000 /*PWRCTL*/ 0x00400010 /*PWRTMG*/ 0x00000000 /*HWLPCTL*/ 0x00210000 /*RFSHCTL0*/ 0x00000000 /*RFSHCTL3*/ 0x00000000 /*CRCPARCTL0*/ 0xC2000040 /*ZQCTL0*/ 0x02050105 /*DFITMG0*/ 0x00000202 /*DFITMG1*/ 0x07000000 /*DFILPCFG0*/ 0xC0400003 /*DFIUPD0*/ 0x00000000 /*DFIUPD1*/ 0x00000000 /*DFIUPD2*/ 0x00000000 /*DFIPHYMSTR*/ 0x00000001 /*ODTMAP*/ 0x00000000 /*DBG0*/ 0x00000000 /*DBG1*/ 0x00000000 /*DBGCMD*/ 0x00000000 /*POISONCFG*/ 0x00000010 /*PCCFG*/ >; st,ctl-timing = < 0x0080008A /*RFSHTMG*/ 0x121B2414 /*DRAMTMG0*/ 0x000D041B /*DRAMTMG1*/ 0x0607080E /*DRAMTMG2*/ 0x0050400C /*DRAMTMG3*/ 0x07040407 /*DRAMTMG4*/ 0x06060303 /*DRAMTMG5*/ 0x02020002 /*DRAMTMG6*/ 0x00000202 /*DRAMTMG7*/ 0x00001005 /*DRAMTMG8*/ 0x000D041B /*DRAMTMG14*/ 0x06000600 /*ODTCFG*/ >; st,ctl-map = < 0x00080808 /*ADDRMAP1*/ 0x00000000 /*ADDRMAP2*/ 0x00000000 /*ADDRMAP3*/ 0x00001F1F /*ADDRMAP4*/ 0x07070707 /*ADDRMAP5*/ 0x0F070707 /*ADDRMAP6*/ 0x00000000 /*ADDRMAP9*/ 0x00000000 /*ADDRMAP10*/ 0x00000000 /*ADDRMAP11*/ >; st,ctl-perf = < 0x00001201 /*SCHED*/ 0x00001201 /*SCHED*/1 0x01000001 /*PERFHPR1*/ 0x08000200 /*PERFLPR1*/ 0x08000400 /*PERFWR1*/ 0x00010000 /*PCFGR_0*/ 0x00000000 /*PCFGW_0*/ 0x02100B03 /*PCFGQOS0_0*/ 0x00800100 /*PCFGQOS1_0*/ 0x01100B03 /*PCFGWQOS0_0*/ 0x01000200 /*PCFGWQOS1_0*/ 0x00010000 /*PCFGR_1*/ 0x00000000 /*PCFGW_1*/ 0x02100B03 /*PCFGQOS0_1*/ 0x00800000 /*PCFGQOS1_1*/ 0x01100B03 /*PCFGWQOS0_1*/ 0x01000200 /*PCFGWQOS1_1*/ >; st,phy-reg = < 0x01442E02 /*PGCR*/ 0x10400812 /*ACIOCR*/ 0x00000C40 /*DXCCR*/ 0xF200001F /*DSGCR*/ 0x0000000B /*DCR*/ 0x00010000 /*ODTCR*/ 0x0000007B /*ZQ0CR1*/ 0x0000CE81 /*DX0GCR*/ 0x0000CE81 /*DX1GCR*/ 0x0000CE81 /*DX2GCR*/ 0x0000CE81 /*DX3GCR*/ >; st,phy-timing = < 0x0022A41B /*PTR0*/ 0x047C0740 /*PTR1*/ 0x042D9C80 /*PTR2*/ 0x369477D0 /*DTPR0*/ 0x098A00D8 /*DTPR1*/ 0x10023600 /*DTPR2*/ 0x00000830 /*MR0*/ 0x00000000 /*MR1*/ 0x00000208 /*MR2*/ 0x00000000 /*MR3*/ >; st,phy-cal = < 0x40000000 /*DX0DLLCR*/ 0xFFFFFFFF /*DX0DQTR*/ 0x3DB02000 /*DX0DQSTR*/ 0x40000000 /*DX1DLLCR*/ 0xFFFFFFFF /*DX1DQTR*/ 0x3DB02000 /*DX1DQSTR*/ 0x40000000 /*DX2DLLCR*/ 0xFFFFFFFF /*DX2DQTR*/ 0x3DB02000 /*DX2DQSTR*/ 0x40000000 /*DX3DLLCR*/ 0xFFFFFFFF /*DX3DQTR*/ 0x3DB02000 /*DX3DQSTR*/ >; status = "okay"; };
3.3.2. STM32CubeMX configuration file[edit source]
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 SSBL compilation, this file generates a correct device tree.
For example the file fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi is:
#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45" #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"
3.3.3. generic DDR dtsi file[edit source]
The dtsi file used with DDR_ defines for STM32MP15x lines is stm32mp15-ddr.dtsi
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause /* * Copyright (C) 2018, STMicroelectronics - All Rights Reserved */ / { soc { ddr: ddr@5a003000{ compatible = "st,stm32mp1-ddr"; reg = <0x5A003000 0x550 0x5A004000 0x234>; clocks = <&rcc AXIDCG>, <&rcc DDRC1>, <&rcc DDRC2>, <&rcc DDRPHYC>, <&rcc DDRCAPB>, <&rcc DDRPHYCAPB>; clock-names = "axidcg", "ddrc1", "ddrc2", "ddrphyc", "ddrcapb", "ddrphycapb"; st,mem-name = DDR_MEM_NAME; st,mem-speed = <DDR_MEM_SPEED>; st,mem-size = <DDR_MEM_SIZE>; st,ctl-reg = < DDR_MSTR DDR_MRCTRL0 DDR_MRCTRL1 DDR_DERATEEN DDR_DERATEINT DDR_PWRCTL DDR_PWRTMG DDR_HWLPCTL DDR_RFSHCTL0 DDR_RFSHCTL3 DDR_CRCPARCTL0 DDR_ZQCTL0 DDR_DFITMG0 DDR_DFITMG1 DDR_DFILPCFG0 DDR_DFIUPD0 DDR_DFIUPD1 DDR_DFIUPD2 DDR_DFIPHYMSTR DDR_ODTMAP DDR_DBG0 DDR_DBG1 DDR_DBGCMD DDR_POISONCFG DDR_PCCFG >; st,ctl-timing = < DDR_RFSHTMG DDR_DRAMTMG0 DDR_DRAMTMG1 DDR_DRAMTMG2 DDR_DRAMTMG3 DDR_DRAMTMG4 DDR_DRAMTMG5 DDR_DRAMTMG6 DDR_DRAMTMG7 DDR_DRAMTMG8 DDR_DRAMTMG14 DDR_ODTCFG >; st,ctl-map = < DDR_ADDRMAP1 DDR_ADDRMAP2 DDR_ADDRMAP3 DDR_ADDRMAP4 DDR_ADDRMAP5 DDR_ADDRMAP6 DDR_ADDRMAP9 DDR_ADDRMAP10 DDR_ADDRMAP11 >; st,ctl-perf = < DDR_SCHED DDR_SCHED1 DDR_PERFHPR1 DDR_PERFLPR1 DDR_PERFWR1 DDR_PCFGR_0 DDR_PCFGW_0 DDR_PCFGQOS0_0 DDR_PCFGQOS1_0 DDR_PCFGWQOS0_0 DDR_PCFGWQOS1_0 DDR_PCFGR_1 DDR_PCFGW_1 DDR_PCFGQOS0_1 DDR_PCFGQOS1_1 DDR_PCFGWQOS0_1 DDR_PCFGWQOS1_1 >; st,phy-reg = < DDR_PGCR DDR_ACIOCR DDR_DXCCR DDR_DSGCR DDR_DCR DDR_ODTCR DDR_ZQ0CR1 DDR_DX0GCR DDR_DX1GCR DDR_DX2GCR DDR_DX3GCR >; st,phy-timing = < status = "okay"; DDR_PTR0 DDR_PTR1 DDR_PTR2 DDR_DTPR0 DDR_DTPR1 DDR_DTPR2 DDR_MR0 DDR_MR1 DDR_MR2 DDR_MR3 >; st,phy-cal = < DDR_DX0DLLCR DDR_DX0DQTR DDR_DX0DQSTR DDR_DX1DLLCR DDR_DX1DQTR DDR_DX1DQSTR DDR_DX2DLLCR DDR_DX2DQTR DDR_DX2DQSTR DDR_DX3DLLCR DDR_DX3DQTR DDR_DX3DQSTR >; status = "okay"; }; }; };
4. How to configure the DT using STM32CubeMX[edit source]
The STM32CubeMX tool can be used to configure the STM32MPU device and get the corresponding platform configuration device tree files.
The STM32CubeMX support all the defines described in the above DT bindings documentation paragraph with a generated included file "stm32mp15-mx.h"; it is included in the mx dts file before the file #generic DDR dtsi file . Refer to STM32CubeMX user manual for further information.
See also How_to_create_your_board_device_tree#DDR configuration with STM32CubeMX DDR Tuning Tool.
5. References[edit source]
Please refer to the following links for additional information:
- ↑ docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt TF-A DDR binding information file
- ↑ doc/device-tree-bindings/ram/st,stm32mp1-ddr.txt U-Boot DDR binding information file
- ↑ 3.0 3.1 fdts/stm32mp15-ddr.dtsi (for TF-A): STM32MP157C device tree files