TF-A Porting for STM32MP157
This document covers the TF-A (Trusted Firmware-A) porting process for the STM32MP157DAC-based development board.
Prerequisites
Obtain the STM32MP1 Developer Package containing the compiler SDK and official source code:
- STM32MP1 OpenSTLinux Developer Package https://www.st.com.cn/zh/embedded-software/stm32mp1dev.html
- Developer Package Installation Guide https://wiki.stmicroelectronics.cn/stm32mpu/wiki/STM32MPU_Developer_Package
Extracting and Preparing Source
Extract the TF-A source package and navigate to the directory:
cd tf-a-stm32mp-v2.8.15-stm32mp-r2-r0
Extract the archive and apply patch files:
tar -xvf tf-a-stm32mp-v2.8.15-stm32mp-r2-r0.tar.xz
cd tf-a-stm32mp-v2.8.15-stm32mp-r2
for p in `ls -1 ../*.patch`; do patch -p1 < $p; done
Base the new device tree on the official stm32mp157d-dk1 configuration. Since the target board uses stm32mp157dac, the "d" suffix variant is required due to differences in internal peripherals:
cp fdts/stm32mp157d-dk1.dts fdts/stm32mp157d-custom.dts
cp fdts/stm32mp157d-dk1-fw-config.dts fdts/stm32mp157d-custom-fw-config.dts
cp fdts/stm32mp15xx-dkx.dtsi fdts/stm32mp15xx-custom.dtsi
Update stm32mp157d-custom.dts to reference the custom dtsi:
// #include "stm32mp15xx-dkx.dtsi"
#include "stm32mp15xx-custom.dtsi"
Device Tree Modifications
DDR Configuration
The default DDR device tree stm32mp15-ddr3-1x4Gb-1066-binG.dtsi does not match the target board's memory configuration. The board uses a 2x2GB memory arrangement. Use the alternative DDR configuration:
#define DDR_MEM_COMPATIBLE ddr3l-custom-1066-888-bin-g-2x2gb-533mhz
#define DDR_MEM_NAME "DDR3L 32bits 2x2Gb 533MHz"
#define DDR_MEM_SPEED 533000
#define DDR_MEM_SIZE 0x20000000
#define DDR_MSTR 0x00040401
#define DDR_MRCTRL0 0x00000010
#define DDR_MRCTRL1 0x00000000
#define DDR_DERATEEN 0x00000000
#define DDR_DERATEINT 0x00800000
#define DDR_PWRCTL 0x00000000
#define DDR_PWRTMG 0x00400010
#define DDR_HWLPCTL 0x00000000
#define DDR_RFSHCTL0 0x00210000
#define DDR_RFSHCTL3 0x00000000
#define DDR_RFSHTMG 0x0040008B
#define DDR_CRCPARCTL0 0x00000000
#define DDR_DRAMTMG0 0x121B1214
#define DDR_DRAMTMG1 0x000A041C
#define DDR_DRAMTMG2 0x0608090F
#define DDR_DRAMTMG3 0x0050400C
#define DDR_DRAMTMG4 0x08040608
#define DDR_DRAMTMG5 0x06060403
#define DDR_DRAMTMG6 0x02020002
#define DDR_DRAMTMG7 0x00000202
#define DDR_DRAMTMG8 0x00001005
#define DDR_DRAMTMG14 0x000000A0
#define DDR_ZQCTL0 0xC2000040
#define DDR_DFITMG0 0x02060105
#define DDR_DFITMG1 0x00000202
#define DDR_DFILPCFG0 0x07000000
#define DDR_DFIUPD0 0xC0400003
#define DDR_DFIUPD1 0x00000000
#define DDR_DFIUPD2 0x00000000
#define DDR_DFIPHYMSTR 0x00000000
#define DDR_ODTCFG 0x06000600
#define DDR_ODTMAP 0x00000001
#define DDR_SCHED 0x00000C01
#define DDR_SCHED1 0x00000000
#define DDR_PERFHPR1 0x01000001
#define DDR_PERFLPR1 0x08000200
#define DDR_PERFWR1 0x08000400
#define DDR_DBG0 0x00000000
#define DDR_DBG1 0x00000000
#define DDR_DBGCMD 0x00000000
#define DDR_POISONCFG 0x00000000
#define DDR_PCCFG 0x00000010
#define DDR_PCFGR_0 0x00010000
#define DDR_PCFGW_0 0x00000000
#define DDR_PCFGQOS0_0 0x02100C03
#define DDR_PCFGQOS1_0 0x00800100
#define DDR_PCFGWQOS0_0 0x01100C03
#define DDR_PCFGWQOS1_0 0x01000200
#define DDR_PCFGR_1 0x00010000
#define DDR_PCFGW_1 0x00000000
#define DDR_PCFGQOS0_1 0x02100C03
#define DDR_PCFGQOS1_1 0x00800040
#define DDR_PCFGWQOS0_1 0x01100C03
#define DDR_PCFGWQOS1_1 0x01000200
#define DDR_ADDRMAP1 0x00080808
#define DDR_ADDRMAP2 0x00000000
#define DDR_ADDRMAP3 0x00000000
#define DDR_ADDRMAP4 0x00001F1F
#define DDR_ADDRMAP5 0x07070707
#define DDR_ADDRMAP6 0x0F0F0707
#define DDR_ADDRMAP9 0x00000000
#define DDR_ADDRMAP10 0x00000000
#define DDR_ADDRMAP11 0x00000000
#define DDR_PGCR 0x01442E02
#define DDR_PTR0 0x0022AA5B
#define DDR_PTR1 0x04841104
#define DDR_PTR2 0x042DA068
#define DDR_ACIOCR 0x10400812
#define DDR_DXCCR 0x00000C40
#define DDR_DSGCR 0xF200011F
#define DDR_DCR 0x0000000B
#define DDR_DTPR0 0x38D488D0
#define DDR_DTPR1 0x098B00D8
#define DDR_DTPR2 0x10023600
#define DDR_MR0 0x00000840
#define DDR_MR1 0x00000000
#define DDR_MR2 0x00000248
#define DDR_MR3 0x00000000
#define DDR_ODTCR 0x00010000
#define DDR_ZQ0CR1 0x00000038
#define DDR_DX0GCR 0x0000CE81
#define DDR_DX1GCR 0x0000CE81
#define DDR_DX2GCR 0x0000CE81
#define DDR_DX3GCR 0x0000CE81
#include "stm32mp15-ddr.dtsi"
Update stm32mp15xx-custom.dtsi to use the new DDR device tree:
// #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
#include "stm32mp15-ddr3-custom-2x2Gb-1066-binG.dtsi"
Power Regulator Configuration
The SOM uses discrete power supplies instead of an integrated PMIC. Modify stm32mp15xx-custom.dtsi to remove I2C4 configurations and add fixed voltage regulators:
// Remove &i2c4 section entirely
&i2c4 {
...
};
// Add fixed voltage regulators
vdd: vdd
vddcore: vddcore
vdd_usb: vdd_usb
v3v3: v3v3
Clock Source Configuration
The SOM uses an active crystal oscillator. Remove the digital bypass setting:
// Remove from &clk_hse
&clk_hse {
st,digbypass;
};
eMMC Support
Enable eMMC through SDMMC2:
&sdmmc2 {
..
};
Debug UART GPIO Configuration
custom_uart_pins: uart4-0 {
pinmux = <STM32_PINMUX('A', 11, AF6)>; /* UART4_RX */
pinmux = <STM32_PINMUX('A', 12, AF6)>; /* UART4_TX */
Complete Device Tree Configuration
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Copyright (c) 2019-2023, STMicroelectronics - All Rights Reserved
* Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
#include <dt-bindings/clock/stm32mp1-clksrc.h>
// #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
#include "stm32mp15-ddr3-custom-2x2Gb-1066-binG.dtsi"
/ {
memory@c0000000 {
device_type = "memory";
reg = <0xc0000000 0x20000000>;
};
vin: vin {
compatible = "regulator-fixed";
regulator-name = "vin";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
vdd: vdd {
compatible = "regulator-fixed";
regulator-name = "vdd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vddcore: vddcore {
compatible = "regulator-fixed";
regulator-name = "vddcore";
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <1250000>;
regulator-always-on;
};
vdd_usb: vdd_usb {
compatible = "regulator-fixed";
regulator-name = "vdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
v3v3: v3v3 {
compatible = "regulator-fixed";
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
&bsec {
board_id: board_id@ec {
reg = <0xec 0x4>;
st,non-secure-otp;
};
};
&cpu0 {
cpu-supply = <&vddcore>;
};
&cpu1 {
cpu-supply = <&vddcore>;
};
&hash1 {
status = "okay";
};
&iwdg1 {
timeout-sec = <32>;
status = "okay";
};
&pwr_regulators {
vdd-supply = <&vdd>;
vdd_3v3_usbfs-supply = <&vdd_usb>;
};
&rcc {
compatible = "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon";
st,clksrc = <
CLK_MPU_PLL1P
CLK_AXI_PLL2P
CLK_MCU_PLL3P
CLK_MCO1_DISABLED
CLK_MCO2_DISABLED
CLK_CKPER_HSE
CLK_FMC_ACLK
CLK_QSPI_ACLK
CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
CLK_USBPHY_HSE
CLK_SPI2S1_PLL3Q
CLK_SPI2S23_PLL3Q
CLK_SPI45_HSI
CLK_SPI6_HSI
CLK_I2C46_HSI
CLK_SDMMC3_PLL4P
CLK_USBO_USBPHY
CLK_ADC_CKPER
CLK_CEC_LSE
CLK_I2C12_HSI
CLK_I2C35_HSI
CLK_UART1_HSI
CLK_UART24_HSI
CLK_UART35_HSI
CLK_UART6_HSI
CLK_UART78_HSI
CLK_SPDIF_PLL4P
CLK_FDCAN_PLL4R
CLK_SAI1_PLL3Q
CLK_SAI2_PLL3Q
CLK_SAI3_PLL3Q
CLK_SAI4_PLL3Q
CLK_RNG1_CSI
CLK_RNG2_LSI
CLK_LPTIM1_PCLK1
CLK_LPTIM23_PCLK3
CLK_LPTIM45_LSE
>;
st,clkdiv = <
DIV(DIV_MPU, 1)
DIV(DIV_AXI, 0)
DIV(DIV_MCU, 0)
DIV(DIV_APB1, 1)
DIV(DIV_APB2, 1)
DIV(DIV_APB3, 1)
DIV(DIV_APB4, 1)
DIV(DIV_APB5, 2)
DIV(DIV_MCO1, 0)
DIV(DIV_MCO2, 0)
>;
st,pll_vco {
pll2_vco_1066Mhz: pll2-vco-1066Mhz {
src = <CLK_PLL12_HSE>;
divmn = <2 65>;
frac = <0x1400>;
};
pll3_vco_417Mhz: pll3-vco-417Mhz {
src = <CLK_PLL3_HSE>;
divmn = <1 33>;
frac = <0x1a04>;
};
pll4_vco_594Mhz: pll4-vco-594Mhz {
src = <CLK_PLL4_HSE>;
divmn = <3 98>;
};
};
pll2: st,pll@1 {
compatible = "st,stm32mp1-pll";
reg = <1>;
st,pll = <&pll2_cfg1>;
pll2_cfg1: pll2_cfg1 {
st,pll_vco = <&pll2_vco_1066Mhz>;
st,pll_div_pqr = <1 0 0>;
};
};
pll3: st,pll@2 {
compatible = "st,stm32mp1-pll";
reg = <2>;
st,pll = <&pll3_cfg1>;
pll3_cfg1: pll3_cfg1 {
st,pll_vco = <&pll3_vco_417Mhz>;
st,pll_div_pqr = <1 16 36>;
};
};
pll4: st,pll@3 {
compatible = "st,stm32mp1-pll";
reg = <3>;
st,pll = <&pll4_cfg1>;
pll4_cfg1: pll4_cfg1 {
st,pll_vco = <&pll4_vco_594Mhz>;
st,pll_div_pqr = <5 7 7>;
};
};
};
&rng1 {
status = "okay";
};
&rtc {
status = "okay";
};
&sdmmc1 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc1_b4_pins_a>;
disable-wp;
st,neg-edge;
bus-width = <4>;
vmmc-supply = <&v3v3>;
status = "okay";
};
&sdmmc2 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
non-removable;
no-sd;
no-sdio;
st,dirpol;
st,negedge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&v3v3>;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&custom_uart_pins>;
status = "okay";
};
&uart7 {
pinctrl-names = "default";
pinctrl-0 = <&uart7_pins_c>;
status = "disabled";
};
&usart3 {
pinctrl-names = "default";
pinctrl-0 = <&usart3_pins_c>;
uart-has-rtscts;
status = "disabled";
};
&usbotg_hs {
phys = <&usbphyc_port1 0>;
phy-names = "usb2-phy";
usb-role-switch;
status = "okay";
};
&usbphyc {
status = "okay";
};
&usbphyc_port0 {
phy-supply = <&vdd_usb>;
};
&usbphyc_port1 {
phy-supply = <&vdd_usb>;
};
&pinctrl {
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>,
<STM32_PINMUX('B', 15, AF9)>,
<STM32_PINMUX('B', 3, AF9)>,
<STM32_PINMUX('B', 4, AF9)>,
<STM32_PINMUX('G', 6, AF10)>;
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>;
slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
};
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>,
<STM32_PINMUX('A', 9, AF10)>,
<STM32_PINMUX('E', 5, AF9)>,
<STM32_PINMUX('D', 3, AF9)>;
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
};
custom_uart_pins: uart4-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 11, AF6)>;
bias-disable;
};
pins2 {
pinmux = <STM32_PINMUX('A', 12, AF6)>;
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
};
};
Source Code Modifications
Since fixed regulators were added to the device tree, update plat/st/stm32mp1/stm32mp1_def.h to reflect the new count:
// #define PLAT_NB_FIXED_REGUS U(2)
#define PLAT_NB_FIXED_REGUS U(10)
Building TF-A
Source the SDK environment:
source ~/MP157/weston/v5.1/sdk/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
export FIP_DEPLOYDIR_ROOT=$PWD/../../FIP_artifacts
make -f $PWD/../Makefile.sdk TF_A_DEVICETREE=stm32mp157d-custom TF_A_CONFIG=usb all
make -f $PWD/../Makefile.sdk TF_A_DEVICETREE=stm32mp157d-custom TF_A_CONFIG=optee-sdcard all
make -f $PWD/../Makefile.sdk TF_A_DEVICETREE=stm32mp157d-custom TF_A_CONFIG=optee-emmc all
The following error can be safely ignored as it indicates missing OP-TEE and U-Boot files:
[ERROR] some files are not present, please provide it or change the paremeters
Successful builds produce these artifacts in the deploy directory:
tf-a-stm32mp-v2.8.15-stm32mp-r2$ ls ../deploy/
debug metadata.bin tf-a-stm32mp157d-custom-optee-sdcard.stm32
fwconfig tf-a-stm32mp157d-custom-optee-emmc.stm32 tf-a-stm32mp157d-custom-usb.stm32
The *.stm32 and metadata.bin files require flashing to the target.
Flashing Process
Extract the STM32MP1 Starter Package and copy the newly compiled *.stm32 and metadata.bin files to images\stm32mp1\arm-trusted-firmware. Create a new flash layout based on the provided template:
#Opt Id Name Type IP Offset Binary
- 0x01 fsbl-boot Binary none 0x0 arm-trusted-firmware/tf-a-stm32mp157d-custom-usb.stm32
Flash using STM32CubeProgrammer:
STM32_Programmer_CLI.exe -c port=usb1 -w .\flashlayout_st-image-weston\optee\FlashLayout_sdcard_stm32mp157d-custom-optee.tsv
Expected serial output upon successful TF-A execution:
NOTICE: CPU: STM32MP157DAC Rev.Z
NOTICE: Model: STMicroelectronics STM32MP157D-DK1 Discovery Board
INFO: Reset reason (0x14):
INFO: Pad Reset from NRST
INFO: FCONF: Reading TB_FW firmware configuration file from: 0x2ffe2000
INFO: FCONF: Reading firmware configuration information for: stm32mp_io
INFO: FCONF: Reading firmware configuration information for: stm32mp_fuse
INFO: Using USB
INFO: Instance 2
INFO: Boot used partition fsbl1
NOTICE: BL2: v2.8-stm32mp1-r2.0(debug):fb87407-dirty(fb87407f)
NOTICE: BL2: Built : 16:22:40, Oct 24 2024
INFO: BL2: Doing platform setup
INFO: RAM: DDR3L 32bits 2x2Gb 533MHz
INFO: Memory size = 0x20000000 (512 MB)
INFO: DFU USB START...
To enable verbose logging, modify include/common/debug.h:
#undef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_VERBOSE
This outputs detailed initialization information including regulator setup, DDR calibration phases, and clock configuration.