diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc new file mode 100644 index 0000000..5d08a57 --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc @@ -0,0 +1,117 @@ +# +# Archiver Configuration +# +SRC_URI_append = " file://README.HOW_TO.txt " + +inherit archiver +ARCHIVER_MODE[src] = "original" +COPYLEFT_LICENSE_INCLUDE_append = " BSD-3* " + +inherit archiver_stm32mp_clean + +archiver_create_makefile_for_sdk() { + . ${T}/tfaconfig_env + + # Init internal var for tfa_config_oemake: should be 'config,extraoemake' + for config in ${TF_A_CONFIG}; do + tf_a_config_oemake="${tf_a_config_oemake} ${config},\"$(eval echo \$TF_A_CONFIG_${config})\"" + done + + mkdir -p ${ARCHIVER_OUTDIR} + #remove default variable + echo "LDFLAGS=" > ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "CFLAGS=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "CPPFLAGS=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "CC=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "CPP=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "AS=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "AR=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "LD=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "NM=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "LOCAL_PATH=\$(PWD)" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "EXTRA_OEMAKE=${EXTRA_OEMAKE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + # Set default config + echo "ELF_DEBUG_ENABLE ?= ${ELF_DEBUG_ENABLE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "TF_A_CONFIG ?= ${TF_A_CONFIG}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + # Set specific OEMAKE config + echo "TF_A_CONFIG_OEMAKE = ${tf_a_config_oemake}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + # Set default TFA_DEVICETREE with configured TF_A_DEVICETREE + if [ -n "${TF_A_DEVICETREE}" ]; then + echo "TFA_DEVICETREE ?= ${TF_A_DEVICETREE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + else + echo "TFA_DEVICETREE ?=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + fi + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "help:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \"Available targets:\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \" all : build TF-A binaries for defined config(s)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \" clean : clean build directories from generated files\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \"TF-A configuration:\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \" TF_A_CONFIG = \$(TF_A_CONFIG)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \" TFA_DEVICETREE = \$(TFA_DEVICETREE)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo \" ELF_DEBUG_ENABLE = '\$(ELF_DEBUG_ENABLE)' ('1' to export elf files)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @echo" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "all: tf" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "host_tools:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @\$(MAKE) --no-print-directory -C \$(LOCAL_PATH)/tools/stm32image" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "tf: host_tools" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " for config in \$(TF_A_CONFIG) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + # Init any extraoemake + echo " add_extraoemake= ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " for fullconfig in \$(TF_A_CONFIG_OEMAKE) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " extraconfig=\$\$(echo \$\$fullconfig | cut -d',' -f1) ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " if [ \"\$\$extraconfig\" = \"\$\$config\" ]; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " add_extraoemake=\$\$(echo \$\$fullconfig | cut -d',' -f2) ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " done ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " mkdir -p \$(LOCAL_PATH)/../build/\$\$config ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " if test -n \"\$(TFA_DEVICETREE)\" ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " for dt in \$(TFA_DEVICETREE) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) DTB_FILE_NAME=\$\$dt.dtb BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + # Copy binary file with explicit name + echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt-\$\$config.${TF_A_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " done ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " else \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + # Copy binary file with explicit name + echo " tf_version=\$\$(find \$(LOCAL_PATH)/../build/\$\$config -name ${TF_A_BASENAME}*.${TF_A_SUFFIX} -exec basename {} \; | sed \"s/\.${TF_A_SUFFIX}//\") ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version-\$\$config.${TF_A_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + # Copy elf files with explicit name + echo " if [ \"\$(ELF_DEBUG_ENABLE)\" = \"1\" ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL1_ELF} ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL1_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL1_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL2_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL32_ELF} ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL32_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL32_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " done" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + + echo "clean:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " @for config in \$(TF_A_CONFIG) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " rm -rf \$(LOCAL_PATH)/../build/\$\$config ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " done" >> ${ARCHIVER_OUTDIR}/Makefile.sdk +} +do_ar_original[prefuncs] += "tfaconfig_env archiver_create_makefile_for_sdk" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc index 8b6e702..cba99f6 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc @@ -143,119 +143,3 @@ do_deploy() { fi } addtask deploy before do_build after do_compile - - -# ----------------------------------------------- -# Archiver -inherit archiver -ARCHIVER_MODE[src] = "${@'original' if d.getVar('ST_ARCHIVER_ENABLE') == '1' else ''}" - -inherit archiver_stm32mp_clean -SRC_URI =+ " file://README.HOW_TO.txt " - -archiver_create_makefile_for_sdk() { - . ${T}/tfaconfig_env - - # Init internal var for tfa_config_oemake: should be 'config,extraoemake' - for config in ${TF_A_CONFIG}; do - tf_a_config_oemake="${tf_a_config_oemake} ${config},$(eval echo \$TF_A_CONFIG_${config})" - done - - mkdir -p ${ARCHIVER_OUTDIR} - #remove default variable - echo "LDFLAGS=" > ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "CFLAGS=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "CPPFLAGS=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "CC=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "CPP=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "AS=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "AR=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "LD=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "NM=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "LOCAL_PATH=\$(PWD)" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "EXTRA_OEMAKE=${EXTRA_OEMAKE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - # Set default config - echo "ELF_DEBUG_ENABLE ?= ${ELF_DEBUG_ENABLE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "TF_A_CONFIG ?= ${TF_A_CONFIG}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - # Set specific OEMAKE config - echo "TF_A_CONFIG_OEMAKE = ${tf_a_config_oemake}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - # Set default TFA_DEVICETREE with configured TF_A_DEVICETREE - if [ -n "${TF_A_DEVICETREE}" ]; then - echo "TFA_DEVICETREE ?= ${TF_A_DEVICETREE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - else - echo "TFA_DEVICETREE ?=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - fi - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "help:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \"Available targets:\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \" all : build TF-A binaries for defined config(s)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \" clean : clean build directories from generated files\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \"TF-A configuration:\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \" TF_A_CONFIG = \$(TF_A_CONFIG)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \" TFA_DEVICETREE = \$(TFA_DEVICETREE)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo \" ELF_DEBUG_ENABLE = '\$(ELF_DEBUG_ENABLE)' ('1' to export elf files)\"" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @echo" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "all: tf" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "host_tools:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @\$(MAKE) --no-print-directory -C \$(LOCAL_PATH)/tools/stm32image" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "tf: host_tools" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " for config in \$(TF_A_CONFIG) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - # Init any extraoemake - echo " add_extraoemake= ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " for fullconfig in \$(TF_A_CONFIG_OEMAKE) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " extraconfig=\$\$(echo \$\$fullconfig | cut -d',' -f1) ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " if [ \"\$\$extraconfig\" = \"\$\$config\" ]; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " add_extraoemake=\$\$(echo \$\$fullconfig | cut -d',' -f2) ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " done ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " mkdir -p \$(LOCAL_PATH)/../build/\$\$config ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " if test -n \"\$(TFA_DEVICETREE)\" ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " for dt in \$(TFA_DEVICETREE) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) DTB_FILE_NAME=\$\$dt.dtb BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - # Copy binary file with explicit name - echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt-\$\$config.${TF_A_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " done ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " else \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - # Copy binary file with explicit name - echo " tf_version=\$\$(find \$(LOCAL_PATH)/../build/\$\$config -name ${TF_A_BASENAME}*.${TF_A_SUFFIX} -exec basename {} \; | sed \"s/\.${TF_A_SUFFIX}//\") ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version-\$\$config.${TF_A_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - # Copy elf files with explicit name - echo " if [ \"\$(ELF_DEBUG_ENABLE)\" = \"1\" ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL1_ELF} ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL1_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL1_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL2_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL32_ELF} ] ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL32_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL32_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " fi ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " done" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - - echo "clean:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " @for config in \$(TF_A_CONFIG) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " rm -rf \$(LOCAL_PATH)/../build/\$\$config ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " done" >> ${ARCHIVER_OUTDIR}/Makefile.sdk -} -do_ar_original[prefuncs] += "tfaconfig_env archiver_create_makefile_for_sdk" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-st-update-r1.1.0.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-st-update-r1.1.0.patch new file mode 100644 index 0000000..f7a557a --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-st-update-r1.1.0.patch @@ -0,0 +1,5752 @@ +From 74771d5557e59fd428c2a6df2323601da27c19ea Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Tue, 17 Sep 2019 12:30:44 +0200 +Subject: [PATCH] st update r1.1.0 + +--- + .../memory-controllers/st,stm32mp1-ddr.txt | 299 +++++++++++ + drivers/mmc/mmc.c | 10 +- + drivers/st/bsec/bsec.c | 334 +++++------- + drivers/st/clk/stm32mp1_calib.c | 530 +++++++++++++++++++ + drivers/st/clk/stm32mp1_clk.c | 578 +++------------------ + drivers/st/ddr/stm32mp1_ddr.c | 93 ++-- + drivers/st/ddr/stm32mp1_ram.c | 4 +- + drivers/st/i2c/stm32_i2c.c | 41 +- + drivers/st/iwdg/stm32_iwdg.c | 20 +- + drivers/st/mmc/stm32_sdmmc2.c | 47 +- + drivers/st/nand/nand.c | 136 ++--- + drivers/st/timer/stm32_timer.c | 27 +- + fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 13 +- + fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 10 +- + fdts/stm32mp157a-dk1.dts | 16 +- + fdts/stm32mp157c-ed1.dts | 35 +- + fdts/stm32mp157c-security.dtsi | 5 +- + fdts/stm32mp157c.dtsi | 21 + + include/drivers/mmc.h | 1 + + include/drivers/st/bsec.h | 19 +- + include/drivers/st/nand.h | 48 +- + include/drivers/st/stm32_iwdg.h | 4 +- + include/drivers/st/stm32_sdmmc2.h | 3 +- + include/drivers/st/stm32mp1_calib.h | 20 + + include/drivers/st/stm32mp1_clk.h | 11 +- + include/drivers/st/stm32mp1_pwr.h | 2 + + include/drivers/st/stm32mp1_rcc.h | 86 ++- + include/lib/aarch32/arch.h | 5 +- + include/lib/aarch32/arch_helpers.h | 5 +- + plat/st/common/bl2_io_storage.c | 550 ++++++++++---------- + plat/st/common/include/stm32mp_auth.h | 8 + + plat/st/common/stm32mp_auth.c | 23 +- + plat/st/common/stm32mp_dt.c | 15 +- + plat/st/stm32mp1/bl2_plat_setup.c | 23 +- + plat/st/stm32mp1/include/stm32mp1_private.h | 5 + + plat/st/stm32mp1/platform.mk | 41 +- + plat/st/stm32mp1/services/bsec_svc.c | 27 +- + plat/st/stm32mp1/services/rcc_svc.c | 4 +- + plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 1 + + plat/st/stm32mp1/sp_min/sp_min_setup.c | 60 ++- + plat/st/stm32mp1/stm32mp1_def.h | 17 +- + plat/st/stm32mp1/stm32mp1_helper.S | 13 +- + plat/st/stm32mp1/stm32mp1_low_power.c | 32 +- + plat/st/stm32mp1/stm32mp1_pm.c | 17 +- + plat/st/stm32mp1/stm32mp1_private.c | 203 +++++++- + plat/st/stm32mp1/stm32mp1_security.c | 17 +- + plat/st/stm32mp1/stm32mp1_shared_resources.c | 4 +- + plat/st/stm32mp1/stm32mp1_syscfg.c | 77 ++- + 48 files changed, 2200 insertions(+), 1360 deletions(-) + create mode 100644 docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt + create mode 100644 drivers/st/clk/stm32mp1_calib.c + create mode 100644 include/drivers/st/stm32mp1_calib.h + +diff --git a/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt b/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt +new file mode 100644 +index 0000000..ee708ce +--- /dev/null ++++ b/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt +@@ -0,0 +1,299 @@ ++ST,stm32mp1 DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL and DDRPHYC) ++ ++-------------------- ++Required properties: ++-------------------- ++- compatible : Should be "st,stm32mp1-ddr" ++- reg : controleur (DDRCTRL) and phy (DDRPHYC) base address ++- clocks : controller clocks handle ++- clock-names : associated controller clock names ++ the "ddrphyc" clock is used to check the DDR frequency ++ at phy level according the expected value in "mem-speed" field ++ ++the next attributes are DDR parameters, they are generated by DDR tools ++included in STM32 Cube tool ++ ++info attributes: ++---------------- ++- st,mem-name : name for DDR configuration, simple string for information ++- st,mem-speed : DDR expected speed for the setting in kHz ++- st,mem-size : DDR mem size in byte ++ ++ ++controlleur attributes: ++----------------------- ++- st,ctl-reg : controleur values depending of the DDR type ++ (DDR3/LPDDR2/LPDDR3) ++ for STM32MP15x: 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 : controleur values depending of frequency and timing parameter ++ of DDR ++ for STM32MP15x: 12 values are requested in this order ++ RFSHTMG ++ DRAMTMG0 ++ DRAMTMG1 ++ DRAMTMG2 ++ DRAMTMG3 ++ DRAMTMG4 ++ DRAMTMG5 ++ DRAMTMG6 ++ DRAMTMG7 ++ DRAMTMG8 ++ DRAMTMG14 ++ ODTCFG ++ ++- st,ctl-map : controleur values depending of address mapping ++ for STM32MP15x: 9 values are requested in this order ++ ADDRMAP1 ++ ADDRMAP2 ++ ADDRMAP3 ++ ADDRMAP4 ++ ADDRMAP5 ++ ADDRMAP6 ++ ADDRMAP9 ++ ADDRMAP10 ++ ADDRMAP11 ++ ++- st,ctl-perf : controleur values depending of performance and scheduling ++ for STM32MP15x: 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 ++ ++phyc attributes: ++---------------- ++- st,phy-reg : phy values depending of the DDR type (DDR3/LPDDR2/LPDDR3) ++ for STM32MP15x: 11 values are requested in this order ++ PGCR ++ ACIOCR ++ DXCCR ++ DSGCR ++ DCR ++ ODTCR ++ ZQ0CR1 ++ DX0GCR ++ DX1GCR ++ DX2GCR ++ DX3GCR ++ ++- st,phy-timing : phy values depending of frequency and timing parameter of DDR ++ for STM32MP15x: 10 values are requested in this order ++ PTR0 ++ PTR1 ++ PTR2 ++ DTPR0 ++ DTPR1 ++ DTPR2 ++ MR0 ++ MR1 ++ MR2 ++ MR3 ++ ++- st,phy-cal : phy cal depending of calibration or tuning of DDR ++ for STM32MP15x: 12 values are requested in this order ++ DX0DLLCR ++ DX0DQTR ++ DX0DQSTR ++ DX1DLLCR ++ DX1DQTR ++ DX1DQSTR ++ DX2DLLCR ++ DX2DQTR ++ DX2DQSTR ++ DX3DLLCR ++ DX3DQTR ++ DX3DQSTR ++ ++Example: ++ ++/ { ++ soc { ++ u-boot,dm-spl; ++ ++ ddr: ddr@0x5A003000{ ++ u-boot,dm-spl; ++ u-boot,dm-pre-reloc; ++ ++ 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 /*DRAMTMG1*/4 ++ 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"; ++ }; ++ }; ++}; +diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c +index 4f9cecf..3f9657d 100644 +--- a/drivers/mmc/mmc.c ++++ b/drivers/mmc/mmc.c +@@ -28,6 +28,7 @@ static unsigned char mmc_ext_csd[512] __aligned(16); + static unsigned int mmc_flags; + static struct mmc_device_info *mmc_dev_info; + static unsigned int rca; ++static unsigned int scr[2] __aligned(16) = { 0 }; + + static const unsigned char tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80 +@@ -89,7 +90,8 @@ static int mmc_device_state(void) + ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, &resp_data[0]); + if (ret != 0) { +- return ret; ++ retries--; ++ continue; + } + + if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) { +@@ -128,7 +130,6 @@ static int mmc_sd_switch(unsigned int bus_width) + { + int ret; + int retries = MMC_DEFAULT_MAX_RETRIES; +- unsigned int scr[2] = { 0 }; + unsigned int bus_width_arg = 0; + + ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr)); +@@ -340,8 +341,9 @@ static int sd_send_op_cond(void) + } + + /* ACMD41: SD_SEND_OP_COND */ +- ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R3, +- &resp_data[0]); ++ ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS | ++ mmc_dev_info->ocr_voltage, MMC_RESPONSE_R3, ++ &resp_data[0]); + if (ret != 0) { + return ret; + } +diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c +index c579c41..3dad2c2 100644 +--- a/drivers/st/bsec/bsec.c ++++ b/drivers/st/bsec/bsec.c +@@ -125,19 +125,30 @@ static uint32_t otp_bank_offset(uint32_t otp) + sizeof(uint32_t); + } + +-static uint32_t bsec_check_error(uint32_t otp) ++/* ++ * bsec_check_error: check BSEC error status. ++ * otp: OTP number. ++ * check_disturbed: check only error (false), ++ * or error and disturbed status (true). ++ * return value: BSEC_OK if no error. ++ */ ++static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed) + { + uint32_t bit = BIT(otp & BSEC_OTP_MASK); + uint32_t bank = otp_bank_offset(otp); + +- if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { +- return BSEC_DISTURBED; +- } +- + if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) { + return BSEC_ERROR; + } + ++ if (!check_disturbed) { ++ return BSEC_OK; ++ } ++ ++ if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { ++ return BSEC_DISTURBED; ++ } ++ + return BSEC_OK; + } + +@@ -263,14 +274,16 @@ uint32_t bsec_get_config(struct bsec_config *cfg) + uint32_t bsec_shadow_register(uint32_t otp) + { + uint32_t result; ++ bool value; + bool power_up = false; + +- if (otp > STM32MP1_OTP_MAX_ID) { +- return BSEC_INVALID_PARAM; ++ result = bsec_read_sr_lock(otp, &value); ++ if (result != BSEC_OK) { ++ ERROR("BSEC: %u Sticky-read bit read Error %i\n", otp, result); ++ return result; + } + +- /* Check if shadowing of OTP is locked */ +- if (bsec_read_sr_lock(otp)) { ++ if (value) { + VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n", + otp); + } +@@ -287,14 +300,13 @@ uint32_t bsec_shadow_register(uint32_t otp) + + bsec_lock(); + +- /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */ + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + +- result = bsec_check_error(otp); ++ result = bsec_check_error(otp, true); + + bsec_unlock(); + +@@ -315,22 +327,14 @@ uint32_t bsec_shadow_register(uint32_t otp) + */ + uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) + { +- uint32_t result; +- + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + +- bsec_lock(); +- + *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t))); + +- result = bsec_check_error(otp); +- +- bsec_unlock(); +- +- return result; ++ return BSEC_OK; + } + + /* +@@ -342,24 +346,25 @@ uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) + uint32_t bsec_write_otp(uint32_t val, uint32_t otp) + { + uint32_t result; ++ bool value; + +- if (otp > STM32MP1_OTP_MAX_ID) { +- return BSEC_INVALID_PARAM; ++ result = bsec_read_sw_lock(otp, &value); ++ if (result != BSEC_OK) { ++ ERROR("BSEC: %u Sticky-write bit read Error %i\n", otp, result); ++ return result; + } + +- /* Check if programming of OTP is locked */ +- if (bsec_read_sw_lock(otp)) { ++ if (value) { + VERBOSE("BSEC: OTP %i is locked and write will be ignored\n", + otp); + } + ++ /* Ensure integrity of each register access sequence */ + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t)), val); + +- result = bsec_check_error(otp); +- + bsec_unlock(); + + return result; +@@ -376,13 +381,15 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp) + { + uint32_t result; + bool power_up = false; ++ bool value; + +- if (otp > STM32MP1_OTP_MAX_ID) { +- return BSEC_INVALID_PARAM; ++ result = bsec_read_sp_lock(otp, &value); ++ if (result != BSEC_OK) { ++ ERROR("BSEC: %u Sticky-prog bit read Error %i\n", otp, result); ++ return result; + } + +- /* Check if programming of OTP is locked */ +- if (bsec_read_sp_lock(otp)) { ++ if (value) { + WARN("BSEC: OTP locked, prog will be ignored\n"); + } + +@@ -403,10 +410,8 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp) + + bsec_lock(); + +- /* Set value in write register */ + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val); + +- /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */ + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { +@@ -416,7 +421,7 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp) + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { +- result = bsec_check_error(otp); ++ result = bsec_check_error(otp, true); + } + + bsec_unlock(); +@@ -468,10 +473,8 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp) + + bsec_lock(); + +- /* Set value in write register */ + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data); + +- /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */ + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, + addr | BSEC_WRITE | BSEC_LOCK); + +@@ -482,7 +485,7 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp) + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { +- result = bsec_check_error(otp); ++ result = bsec_check_error(otp, false); + } + + bsec_unlock(); +@@ -497,7 +500,7 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp) + } + + /* +- * bsec_write_debug_conf: write value in debug feature ++ * bsec_write_debug_conf: write value in debug feature. + * to enable/disable debug service. + * val: value to write. + * return value: BSEC_OK if no error. +@@ -521,7 +524,7 @@ uint32_t bsec_write_debug_conf(uint32_t val) + } + + /* +- * bsec_read_debug_conf: read debug configuration. ++ * bsec_read_debug_conf: return debug configuration register value. + */ + uint32_t bsec_read_debug_conf(void) + { +@@ -537,7 +540,7 @@ uint32_t bsec_get_status(void) + } + + /* +- * bsec_get_hw_conf: return hardware configuration. ++ * bsec_get_hw_conf: return hardware configuration register value. + */ + uint32_t bsec_get_hw_conf(void) + { +@@ -545,7 +548,7 @@ uint32_t bsec_get_hw_conf(void) + } + + /* +- * bsec_get_version: return BSEC version. ++ * bsec_get_version: return BSEC version register value. + */ + uint32_t bsec_get_version(void) + { +@@ -553,7 +556,7 @@ uint32_t bsec_get_version(void) + } + + /* +- * bsec_get_id: return BSEC ID. ++ * bsec_get_id: return BSEC ID register value. + */ + uint32_t bsec_get_id(void) + { +@@ -561,7 +564,7 @@ uint32_t bsec_get_id(void) + } + + /* +- * bsec_get_magic_id: return BSEC magic number. ++ * bsec_get_magic_id: return BSEC magic number register value. + */ + uint32_t bsec_get_magic_id(void) + { +@@ -569,229 +572,178 @@ uint32_t bsec_get_magic_id(void) + } + + /* +- * bsec_write_sr_lock: write shadow-read lock. ++ * bsec_set_sr_lock: set shadow-read lock. + * otp: OTP number. +- * value: value to write in the register. +- * Must be always 1. +- * return: true if OTP is locked, else false. ++ * return value: BSEC_OK if no error. + */ +-bool bsec_write_sr_lock(uint32_t otp, uint32_t value) ++uint32_t bsec_set_sr_lock(uint32_t otp) + { +- bool result = false; + uint32_t bank = otp_bank_offset(otp); +- uint32_t bank_value; + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + +- bsec_lock(); +- +- bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); +- +- if ((bank_value & otp_mask) == value) { +- /* +- * In case of write don't need to write, +- * the lock is already set. +- */ +- if (value != 0U) { +- result = true; +- } +- } else { +- if (value != 0U) { +- bank_value = bank_value | otp_mask; +- } else { +- bank_value = bank_value & ~otp_mask; +- } +- +- /* +- * We can write 0 in all other OTP +- * if the lock is activated in one of other OTP. +- * Write 0 has no effect. +- */ +- mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, bank_value); +- result = true; ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; + } + ++ bsec_lock(); ++ mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, otp_mask); + bsec_unlock(); + +- return result; ++ return BSEC_OK; + } + + /* + * bsec_read_sr_lock: read shadow-read lock. + * otp: OTP number. +- * return: true if otp is locked, else false. ++ * value: read value (true or false). ++ * return value: BSEC_OK if no error. + */ +-bool bsec_read_sr_lock(uint32_t otp) ++uint32_t bsec_read_sr_lock(uint32_t otp, bool *value) + { + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); +- uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); ++ uint32_t bank_value; ++ ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; ++ } + +- return (bank_value & otp_mask) != 0U; ++ bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); ++ ++ *value = ((bank_value & otp_mask) != 0U); ++ ++ return BSEC_OK; + } + + /* +- * bsec_write_sw_lock: write shadow-write lock. ++ * bsec_set_sw_lock: set shadow-write lock. + * otp: OTP number. +- * value: Value to write in the register. +- * Must be always 1. +- * return: true if OTP is locked, else false. ++ * return value: BSEC_OK if no error. + */ +-bool bsec_write_sw_lock(uint32_t otp, uint32_t value) ++uint32_t bsec_set_sw_lock(uint32_t otp) + { +- bool result = false; + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); +- uint32_t bank_value; +- +- bsec_lock(); + +- bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); +- +- if ((bank_value & otp_mask) == value) { +- /* +- * In case of write don't need to write, +- * the lock is already set. +- */ +- if (value != 0U) { +- result = true; +- } +- } else { +- if (value != 0U) { +- bank_value = bank_value | otp_mask; +- } else { +- bank_value = bank_value & ~otp_mask; +- } +- +- /* +- * We can write 0 in all other OTP +- * if the lock is activated in one of other OTP. +- * Write 0 has no effect. +- */ +- mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, bank_value); +- result = true; ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; + } + ++ bsec_lock(); ++ mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, otp_mask); + bsec_unlock(); + +- return result; ++ return BSEC_OK; + } + + /* + * bsec_read_sw_lock: read shadow-write lock. + * otp: OTP number. +- * return: true if OTP is locked, else false. ++ * value: read value (true or false). ++ * return value: BSEC_OK if no error. + */ +-bool bsec_read_sw_lock(uint32_t otp) ++uint32_t bsec_read_sw_lock(uint32_t otp, bool *value) + { + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); +- uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); ++ uint32_t bank_value; ++ ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; ++ } + +- return (bank_value & otp_mask) != 0U; ++ bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); ++ ++ *value = ((bank_value & otp_mask) != 0U); ++ ++ return BSEC_OK; + } + + /* +- * bsec_write_sp_lock: write shadow-program lock. ++ * bsec_set_sp_lock: set shadow-program lock. + * otp: OTP number. +- * value: Value to write in the register. +- * Must be always 1. +- * return: true if OTP is locked, else false. ++ * return value: BSEC_OK if no error. + */ +-bool bsec_write_sp_lock(uint32_t otp, uint32_t value) ++uint32_t bsec_set_sp_lock(uint32_t otp) + { +- bool result = false; + uint32_t bank = otp_bank_offset(otp); +- uint32_t bank_value; + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + +- bsec_lock(); +- +- bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); +- +- if ((bank_value & otp_mask) == value) { +- /* +- * In case of write don't need to write, +- * the lock is already set. +- */ +- if (value != 0U) { +- result = true; +- } +- } else { +- if (value != 0U) { +- bank_value = bank_value | otp_mask; +- } else { +- bank_value = bank_value & ~otp_mask; +- } +- +- /* +- * We can write 0 in all other OTP +- * if the lock is activated in one of other OTP. +- * Write 0 has no effect. +- */ +- mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, bank_value); +- result = true; ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; + } + ++ bsec_lock(); ++ mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask); + bsec_unlock(); + +- return result; ++ return BSEC_OK; + } + + /* + * bsec_read_sp_lock: read shadow-program lock. + * otp: OTP number. +- * return: true if OTP is locked, else false. ++ * value: read value (true or false). ++ * return value: BSEC_OK if no error. + */ +-bool bsec_read_sp_lock(uint32_t otp) ++uint32_t bsec_read_sp_lock(uint32_t otp, bool *value) + { + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); +- uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); ++ uint32_t bank_value; ++ ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; ++ } ++ ++ bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); ++ ++ *value = ((bank_value & otp_mask) != 0U); + +- return (bank_value & otp_mask) != 0U; ++ return BSEC_OK; + } + + /* +- * bsec_wr_lock: Read permanent lock status. ++ * bsec_read_permanent_lock: Read permanent lock status. + * otp: OTP number. +- * return: true if OTP is locked, else false. ++ * value: read value (true or false). ++ * return value: BSEC_OK if no error. + */ +-bool bsec_wr_lock(uint32_t otp) ++uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value) + { + uint32_t bank = otp_bank_offset(otp); +- uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK); ++ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); ++ uint32_t bank_value; + +- if ((mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank) & +- lock_bit) != 0U) { +- /* +- * In case of write don't need to write, +- * the lock is already set. +- */ +- return true; ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; + } + +- return false; ++ bank_value = mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank); ++ ++ *value = ((bank_value & otp_mask) != 0U); ++ ++ return BSEC_OK; + } + + /* +- * bsec_otp_lock: Lock Upper OTP or Global programming or debug enable +- * service: Service to lock see header file. +- * value: Value to write must always set to 1 (only use for debug purpose). +- * return: BSEC_OK if succeed. ++ * bsec_otp_lock: Lock Upper OTP or Global Programming or Debug Enable. ++ * service: Service to lock, see header file. ++ * return value: BSEC_OK if no error. + */ +-uint32_t bsec_otp_lock(uint32_t service, uint32_t value) ++uint32_t bsec_otp_lock(uint32_t service) + { + uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF; + + switch (service) { + case BSEC_LOCK_UPPER_OTP: +- mmio_write_32(reg, value << BSEC_LOCK_UPPER_OTP); ++ mmio_write_32(reg, BIT(BSEC_LOCK_UPPER_OTP)); + break; + case BSEC_LOCK_DEBUG: +- mmio_write_32(reg, value << BSEC_LOCK_DEBUG); ++ mmio_write_32(reg, BIT(BSEC_LOCK_DEBUG)); + break; + case BSEC_LOCK_PROGRAM: +- mmio_write_32(reg, value << BSEC_LOCK_PROGRAM); ++ mmio_write_32(reg, BIT(BSEC_LOCK_PROGRAM)); + break; + default: + return BSEC_INVALID_PARAM; +@@ -803,7 +755,7 @@ uint32_t bsec_otp_lock(uint32_t service, uint32_t value) + /* + * bsec_power_safmem: Activate or deactivate SAFMEM power. + * power: true to power up, false to power down. +- * return: BSEC_OK if succeed. ++ * return value: BSEC_OK if no error. + */ + static uint32_t bsec_power_safmem(bool power) + { +@@ -822,7 +774,6 @@ static uint32_t bsec_power_safmem(bool power) + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val); + +- /* Waiting loop */ + if (power) { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) && + (timeout != 0U)) { +@@ -845,23 +796,7 @@ static uint32_t bsec_power_safmem(bool power) + } + + /* +- * bsec_mode_is_closed_device: read OTP secure sub-mode. +- * return: false if open_device and true of closed_device. +- */ +-bool bsec_mode_is_closed_device(void) +-{ +- uint32_t value; +- +- if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) || +- (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) { +- return true; +- } +- +- return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED; +-} +- +-/* +- * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value ++ * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value. + * otp_value: read value. + * word: OTP number. + * return value: BSEC_OK if no error. +@@ -887,7 +822,7 @@ uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) + /* + * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. + * otp: OTP number. +- * return: BSEC_OK if authorized access. ++ * return value: BSEC_OK if authorized access. + */ + uint32_t bsec_check_nsec_access_rights(uint32_t otp) + { +@@ -897,11 +832,8 @@ uint32_t bsec_check_nsec_access_rights(uint32_t otp) + } + + if (otp >= STM32MP1_UPPER_OTP_START) { +- /* Check if BSEC is in OTP-SECURED closed_device state. */ +- if (bsec_mode_is_closed_device()) { +- if (!non_secure_can_access(otp)) { +- return BSEC_ERROR; +- } ++ if (!non_secure_can_access(otp)) { ++ return BSEC_ERROR; + } + } + #endif +diff --git a/drivers/st/clk/stm32mp1_calib.c b/drivers/st/clk/stm32mp1_calib.c +new file mode 100644 +index 0000000..030a84f +--- /dev/null ++++ b/drivers/st/clk/stm32mp1_calib.c +@@ -0,0 +1,530 @@ ++/* ++ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TIMEOUT_10MS ms2tick(10) ++#define CALIB_TIMEOUT TIMEOUT_10MS ++ ++struct stm32mp1_trim_boundary_t { ++ /* Max boundary trim value around forbidden value */ ++ unsigned int x1; ++ /* Min boundary trim value around forbidden value */ ++ unsigned int x2; ++}; ++ ++struct stm32mp1_clk_cal { ++ uint16_t *fbv; ++ unsigned int cal_ref; ++ int trim_max; ++ int trim_min; ++ unsigned int boundary_max; ++ unsigned long ref_freq; ++ unsigned int freq_margin; ++ unsigned long (*get_freq)(void); ++ void (*set_trim)(unsigned int cal); ++ unsigned int (*get_trim)(void); ++ struct stm32mp1_trim_boundary_t boundary[16]; ++}; ++ ++/* RCC Wakeup status */ ++static bool rcc_wakeup; ++ ++/* List of forbiden values for HSI */ ++static uint16_t fbv_hsi[] = { ++ 512, ++ 480, ++ 448, ++ 416, ++ 384, ++ 352, ++ 320, ++ 288, ++ 256, ++ 224, ++ 192, ++ 160, ++ 128, ++ 96, ++ 64, ++ 32, ++ 0 ++}; ++ ++/* List of forbiden values for CSI */ ++static uint16_t fbv_csi[] = { ++ 256, ++ 240, ++ 224, ++ 208, ++ 192, ++ 176, ++ 160, ++ 144, ++ 128, ++ 112, ++ 96, ++ 80, ++ 64, ++ 48, ++ 32, ++ 16, ++ 0 ++}; ++ ++static void hsi_set_trim(unsigned int cal); ++static unsigned int hsi_get_trimed_cal(void); ++static void csi_set_trim(unsigned int cal); ++static unsigned int csi_get_trimed_cal(void); ++ ++static struct stm32mp1_clk_cal stm32mp1_clk_cal_hsi = { ++ .fbv = fbv_hsi, ++ .trim_max = 63, ++ .trim_min = -64, ++ .ref_freq = 0, ++ .freq_margin = 5, ++ .set_trim = hsi_set_trim, ++ .get_trim = hsi_get_trimed_cal, ++}; ++ ++static struct stm32mp1_clk_cal stm32mp1_clk_cal_csi = { ++ .fbv = fbv_csi, ++ .trim_max = 15, ++ .trim_min = -16, ++ .ref_freq = 0, ++ .freq_margin = 8, ++ .set_trim = csi_set_trim, ++ .get_trim = csi_get_trimed_cal, ++}; ++ ++static uint32_t timer_val; ++ ++/* ++ * HSI Calibration part ++ */ ++static int get_signed_value(uint8_t val) ++{ ++ return ((int8_t)(val << 1)) >> 1; ++} ++ ++static void hsi_set_trim(unsigned int cal) ++{ ++ int clk_trim = (int)cal - (int)stm32mp1_clk_cal_hsi.cal_ref; ++ uint32_t trim = ((uint32_t)clk_trim << RCC_HSICFGR_HSITRIM_SHIFT) & ++ RCC_HSICFGR_HSITRIM_MASK; ++ ++ mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_HSICFGR, ++ RCC_HSICFGR_HSITRIM_MASK, trim); ++} ++ ++static unsigned int hsi_get_trimed_cal(void) ++{ ++ uint32_t utrim = (mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR) & ++ RCC_HSICFGR_HSITRIM_MASK) >> ++ RCC_HSICFGR_HSITRIM_SHIFT; ++ ++ int trim = get_signed_value((uint8_t)utrim); ++ ++ if (trim + (int)stm32mp1_clk_cal_hsi.cal_ref < 0) { ++ return 0; ++ } ++ ++ return stm32mp1_clk_cal_hsi.cal_ref + trim; ++} ++ ++static void csi_set_trim(unsigned int cal) ++{ ++ int clk_trim = (int)cal - (int)stm32mp1_clk_cal_csi.cal_ref + ++ stm32mp1_clk_cal_csi.trim_max + 1; ++ uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) & ++ RCC_CSICFGR_CSITRIM_MASK; ++ ++ mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_CSICFGR, ++ RCC_CSICFGR_CSITRIM_MASK, trim); ++} ++ ++static unsigned int csi_get_trimed_cal(void) ++{ ++ uint32_t trim = (mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) & ++ RCC_CSICFGR_CSITRIM_MASK) >> ++ RCC_CSICFGR_CSITRIM_SHIFT; ++ ++ return (int)trim - stm32mp1_clk_cal_csi.trim_max + ++ (int)stm32mp1_clk_cal_csi.cal_ref - 1; ++} ++ ++static unsigned int trim_increase(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int cal) ++{ ++ struct stm32mp1_trim_boundary_t *boundary; ++ unsigned int new_cal; ++ int i; ++ ++ /* By default: last calibration value */ ++ new_cal = cal; ++ ++ /* Start from Lowest cal value */ ++ for (i = (int)clk_cal->boundary_max - 1; i >= 0; i--) { ++ boundary = &clk_cal->boundary[i]; ++ ++ if (cal < boundary->x2) { ++ new_cal = boundary->x2; ++ break; ++ } ++ ++ if ((cal >= boundary->x2) && (cal < boundary->x1)) { ++ new_cal = cal + 1; ++ break; ++ } ++ } ++ ++ return new_cal; ++} ++ ++static unsigned int trim_decrease(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int cal) ++{ ++ struct stm32mp1_trim_boundary_t *boundary; ++ unsigned int new_cal; ++ unsigned int i; ++ ++ /* By default: last calibration value */ ++ new_cal = cal; ++ ++ /* Start from Highest cal value */ ++ for (i = 0; i < clk_cal->boundary_max; i++) { ++ boundary = &clk_cal->boundary[i]; ++ ++ if (cal > boundary->x1) { ++ new_cal = boundary->x1; ++ break; ++ } ++ ++ if ((cal > boundary->x2) && (cal <= boundary->x1)) { ++ new_cal = cal - 1; ++ break; ++ } ++ } ++ ++ return new_cal; ++} ++ ++static void rcc_calibration(struct stm32mp1_clk_cal *clk_cal) ++{ ++ unsigned long freq = clk_cal->get_freq(); ++ unsigned long min = clk_cal->ref_freq - ++ ((clk_cal->ref_freq * clk_cal->freq_margin) / 1000); ++ unsigned long max = clk_cal->ref_freq + ++ ((clk_cal->ref_freq * clk_cal->freq_margin) / 1000); ++ int trim, new_trim; ++ unsigned long conv; ++ unsigned long min_conv = ULONG_MAX; ++ uint64_t start; ++ ++ if ((freq >= min) && (freq <= max)) { ++ return; ++ } ++ ++ trim = clk_cal->get_trim(); ++ start = timeout_start(); ++ do { ++ if (freq < clk_cal->ref_freq) { ++ new_trim = trim_increase(clk_cal, trim); ++ } else { ++ new_trim = trim_decrease(clk_cal, trim); ++ } ++ ++ clk_cal->set_trim(new_trim); ++ freq = clk_cal->get_freq(); ++ if (freq == 0U) { ++ /* Calibration will be stopped */ ++ clk_cal->ref_freq = 0U; ++ return; ++ } ++ conv = (clk_cal->ref_freq < freq) ? ++ freq - clk_cal->ref_freq : clk_cal->ref_freq - freq; ++ if (conv < min_conv) { ++ min_conv = conv; ++ trim = new_trim; ++ } ++ ++ if (timeout_elapsed(start, CALIB_TIMEOUT)) { ++ break; ++ } ++ ++ } while (conv == min_conv); ++ ++ clk_cal->set_trim(trim); ++ freq = clk_cal->get_freq(); ++ if ((freq < min) || (freq > max)) { ++ ERROR("%s Calibration : Freq %lu, trim %i\n", ++ (clk_cal->set_trim == hsi_set_trim) ? "HSI" : "CSI", ++ freq, trim); ++#if DEBUG ++ /* ++ * Show the steps around the selected trim value ++ * to correct the margin if needed ++ */ ++ new_trim = trim_decrease(clk_cal, trim); ++ clk_cal->set_trim(new_trim); ++ ERROR("%s Calibration : Freq %lu, trim %i\n", ++ (clk_cal->set_trim == hsi_set_trim) ? ++ "HSI" : "CSI", clk_cal->get_freq(), ++ new_trim); ++ new_trim = trim_increase(clk_cal, trim); ++ clk_cal->set_trim(new_trim); ++ ERROR("%s Calibration : Freq %lu, trim %i\n", ++ (clk_cal->set_trim == hsi_set_trim) ? ++ "HSI" : "CSI", clk_cal->get_freq(), ++ new_trim); ++#endif ++ } ++} ++ ++static void save_trim(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int i, unsigned int x1, unsigned int x2) ++{ ++ clk_cal->boundary[i].x1 = x1; ++ clk_cal->boundary[i].x2 = x2; ++} ++ ++static int trim_find_prev_boundary(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int x1) ++{ ++ unsigned int x = x1; ++ unsigned long freq; ++ ++ clk_cal->set_trim(x1 + 1); ++ freq = clk_cal->get_freq(); ++ ++ while (x >= (clk_cal->cal_ref + clk_cal->trim_min)) { ++ x--; ++ clk_cal->set_trim(x); ++ ++ if (clk_cal->get_freq() <= freq) { ++ break; ++ } ++ }; ++ ++ return x; ++} ++ ++static void trim_table_init(struct stm32mp1_clk_cal *clk_cal) ++{ ++ uint16_t *trim_fbv = clk_cal->fbv; ++ unsigned int min; ++ unsigned int max; ++ int boundary = 0; ++ int i = 0; ++ ++ max = clk_cal->cal_ref + clk_cal->trim_max; ++ min = clk_cal->cal_ref + clk_cal->trim_min; ++ ++ while (trim_fbv[i]) { ++ unsigned int x; ++ unsigned int x1 = trim_fbv[i]; ++ unsigned int x2 = trim_fbv[i + 1]; ++ ++ if ((max <= x2) || (min >= x1)) { ++ i++; ++ if (boundary != 0) { ++ goto out; ++ } ++ continue; ++ } ++ ++ /* Take forbiden value + 1 */ ++ x2 = x2 + 1; ++ if (x2 < min) { ++ x2 = min; ++ } ++ ++ if (boundary == 0) { ++ /* Save first boundary */ ++ save_trim(clk_cal, boundary, max, x2); ++ boundary++; ++ i++; ++ continue; ++ } ++ ++ x = trim_find_prev_boundary(clk_cal, x1); ++ /* Save boundary values */ ++ save_trim(clk_cal, boundary, x - 1, x2); ++ boundary++; ++ i++; ++ }; ++out: ++ clk_cal->boundary_max = boundary; ++} ++ ++bool stm32mp1_calib_get_wakeup(void) ++{ ++ return rcc_wakeup; ++} ++ ++void stm32mp1_calib_set_wakeup(bool state) ++{ ++ rcc_wakeup = state; ++} ++ ++void stm32mp1_calib_it_handler(uint32_t id) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ switch (id) { ++ case STM32MP1_IRQ_RCC_WAKEUP: ++ plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY); ++ mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF); ++ stm32mp1_calib_set_wakeup(true); ++ return; ++ ++ case STM32MP1_IRQ_MCU_SEV: ++ stm32mp1_calib_set_wakeup(false); ++ if ((mmio_read_32(EXTI_BASE + EXTI_RPR3) & ++ EXTI_RPR3_RPIF65) != 0U) { ++ mmio_setbits_32(EXTI_BASE + EXTI_RPR3, ++ EXTI_RPR3_RPIF65); ++ } ++ ++ if ((mmio_read_32(EXTI_BASE + EXTI_FPR3) & ++ EXTI_FPR3_FPIF65) != 0U) { ++ mmio_setbits_32(EXTI_BASE + EXTI_FPR3, ++ EXTI_FPR3_FPIF65); ++ } ++ ++ break; ++ ++ case ARM_IRQ_SEC_PHY_TIMER: ++ default: ++ break; ++ } ++ ++ if (stm32mp1_clk_cal_hsi.ref_freq != 0U) { ++ rcc_calibration(&stm32mp1_clk_cal_hsi); ++ } ++ ++ if (stm32mp1_clk_cal_csi.ref_freq != 0U) { ++ rcc_calibration(&stm32mp1_clk_cal_csi); ++ } ++ ++ if (timer_val != 0U) { ++ write_cntp_tval(timer_val); ++ } ++} ++ ++int stm32mp1_calib_start_hsi_cal(void) ++{ ++ if (stm32mp1_clk_cal_hsi.ref_freq == 0U) { ++ return -ENOENT; ++ } ++ ++ rcc_calibration(&stm32mp1_clk_cal_hsi); ++ return 0; ++} ++ ++int stm32mp1_calib_start_csi_cal(void) ++{ ++ if (stm32mp1_clk_cal_csi.ref_freq == 0U) { ++ return -ENOENT; ++ } ++ ++ rcc_calibration(&stm32mp1_clk_cal_csi); ++ return 0; ++} ++ ++static void init_hsi_cal(void) ++{ ++ int len; ++ ++ if (fdt_rcc_read_prop("st,hsi-cal", &len) == NULL) { ++ return; ++ } ++ ++ stm32_timer_freq_func(&stm32mp1_clk_cal_hsi.get_freq, HSI_CAL); ++ if (stm32mp1_clk_cal_hsi.get_freq == NULL) { ++ return; ++ } ++ ++ stm32mp1_clk_cal_hsi.ref_freq = stm32mp_clk_get_rate(CK_HSI); ++ ++ /* Read initial value */ ++ stm32mp1_clk_cal_hsi.cal_ref = ++ ((mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR) ++ & RCC_HSICFGR_HSICAL_MASK) >> RCC_HSICFGR_HSICAL_SHIFT); ++ ++ trim_table_init(&stm32mp1_clk_cal_hsi); ++ ++ stm32mp1_clk_cal_hsi.set_trim(stm32mp1_clk_cal_hsi.cal_ref); ++ ++ rcc_calibration(&stm32mp1_clk_cal_hsi); ++} ++ ++static void init_csi_cal(void) ++{ ++ int len; ++ ++ if (fdt_rcc_read_prop("st,csi-cal", &len) == NULL) { ++ return; ++ } ++ ++ stm32_timer_freq_func(&stm32mp1_clk_cal_csi.get_freq, CSI_CAL); ++ if (stm32mp1_clk_cal_csi.get_freq == NULL) { ++ return; ++ } ++ ++ stm32mp1_clk_cal_csi.ref_freq = stm32mp_clk_get_rate(CK_CSI); ++ ++ /* Read initial value */ ++ stm32mp1_clk_cal_csi.cal_ref = ++ ((mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) & ++ RCC_CSICFGR_CSICAL_MASK) >> RCC_CSICFGR_CSICAL_SHIFT); ++ ++ trim_table_init(&stm32mp1_clk_cal_csi); ++ ++ stm32mp1_clk_cal_csi.set_trim(stm32mp1_clk_cal_csi.cal_ref); ++ ++ rcc_calibration(&stm32mp1_clk_cal_csi); ++} ++ ++void stm32mp1_calib_init(void) ++{ ++ init_hsi_cal(); ++ init_csi_cal(); ++ ++ timer_val = fdt_rcc_read_uint32_default("st,cal-sec", 0) * ++ plat_get_syscnt_freq2(); ++ ++ if (timer_val != 0U) { ++ /* Load & enable timer */ ++ write_cntp_tval(timer_val); ++ write_cntp_ctl(BIT(0)); ++ }; ++ ++ if (fdt_rcc_enable_it("mcu_sev") < 0) { ++ VERBOSE("No MCU calibration\n"); ++ } ++} +diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c +index b304315..286234e 100644 +--- a/drivers/st/clk/stm32mp1_clk.c ++++ b/drivers/st/clk/stm32mp1_clk.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -27,9 +28,6 @@ + #include + #include + #include +-#if defined(IMAGE_BL32) +-#include +-#endif + #include + + #define MAX_HSI_HZ 64000000 +@@ -44,10 +42,6 @@ + #define HSIDIV_TIMEOUT TIMEOUT_200MS + #define OSCRDY_TIMEOUT TIMEOUT_1S + +-#if defined(IMAGE_BL32) +-#define CAL_MAX_RETRY 20U +-#endif +- + enum stm32mp1_parent_id { + /* Oscillators are defined in enum stm32mp_osc_id */ + +@@ -91,7 +85,7 @@ enum stm32mp1_parent_sel { + _STGEN_SEL, + _I2C46_SEL, + _SPI6_SEL, +- _USART1_SEL, ++ _UART1_SEL, + _RNG1_SEL, + _UART6_SEL, + _UART24_SEL, +@@ -101,8 +95,8 @@ enum stm32mp1_parent_sel { + _SDMMC3_SEL, + _QSPI_SEL, + _FMC_SEL, +- _ASS_SEL, +- _MSS_SEL, ++ _AXIS_SEL, ++ _MCUS_SEL, + _USBPHY_SEL, + _USBO_SEL, + _PARENT_SEL_NB, +@@ -210,32 +204,6 @@ struct stm32mp1_clk_pll { + enum stm32mp_osc_id refclk[REFCLK_SIZE]; + }; + +-#if defined(IMAGE_BL32) +-struct stm32mp1_trim_boundary_t { +- /* Max boundary trim value around forbidden value */ +- unsigned int x1; +- /* Min boundary trim value around forbidden value */ +- unsigned int x2; +-}; +- +-struct stm32mp1_clk_cal { +- uint16_t *fbv; +- unsigned int cal_ref; +- int trim_max; +- int trim_min; +- unsigned int boundary_max; +- unsigned long ref_freq; +- unsigned int freq_margin; +- unsigned long (*get_freq)(void); +- void (*set_trim)(unsigned int cal); +- unsigned int (*get_trim)(void); +- struct stm32mp1_trim_boundary_t boundary[16]; +-}; +- +-/* RCC Wakeup status */ +-static bool rcc_wakeup; +-#endif +- + /* Clocks with selectable source and non set/clr register access */ + #define _CLK_SELEC(off, b, idx, s) \ + { \ +@@ -280,13 +248,13 @@ static bool rcc_wakeup; + .fixed = (f), \ + } + +-#define _CLK_PARENT(idx, off, s, m, p) \ +- [(idx)] = { \ +- .offset = (off), \ +- .src = (s), \ +- .msk = (m), \ +- .parent = (p), \ +- .nb_parent = ARRAY_SIZE(p) \ ++#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ ++ [_ ## _label ## _SEL] = { \ ++ .offset = _rcc_selr, \ ++ .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ ++ .msk = _rcc_selr ## _ ## _label ## SRC_MASK, \ ++ .parent = (_parents), \ ++ .nb_parent = ARRAY_SIZE(_parents) \ + } + + #define _CLK_PLL(idx, type, off1, off2, off3, \ +@@ -347,6 +315,9 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), + _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), + ++ _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), ++ ++ _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 0, LTDC_PX, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), +@@ -354,7 +325,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), +- _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _USART1_SEL), ++ _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), +@@ -363,6 +334,8 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), + ++ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 0, DMA1, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 1, DMA2, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), + _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), + +@@ -384,6 +357,9 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), + _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), + ++ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 0, MDMA, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 5, GPU, _UNKNOWN_SEL), ++ _CLK_SC_FIXED(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), +@@ -462,25 +438,25 @@ static const uint8_t usbo_parents[] = { + }; + + static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { +- _CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents), +- _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents), +- _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), +- _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), +- _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), +- _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), +- _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), +- _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), +- _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), +- _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), +- _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), +- _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents), +- _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents), +- _CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents), +- _CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents), +- _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents), +- _CLK_PARENT(_MSS_SEL, RCC_MSSCKSELR, 0, 0x3, mss_parents), +- _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), +- _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), ++ _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), ++ _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), ++ _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), ++ _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), ++ _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), ++ _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), ++ _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), ++ _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), ++ _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), ++ _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), ++ _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), ++ _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), ++ _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), ++ _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), ++ _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), ++ _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents), ++ _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents), ++ _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), ++ _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), + }; + + /* Define characteristic of PLL according type */ +@@ -587,7 +563,7 @@ const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = { + [_STGEN_SEL] = "STGEN", + [_I2C46_SEL] = "I2C46", + [_SPI6_SEL] = "SPI6", +- [_USART1_SEL] = "USART1", ++ [_UART1_SEL] = "USART1", + [_RNG1_SEL] = "RNG1", + [_UART6_SEL] = "UART6", + [_UART24_SEL] = "UART24", +@@ -597,8 +573,8 @@ const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = { + [_SDMMC3_SEL] = "SDMMC3", + [_QSPI_SEL] = "QSPI", + [_FMC_SEL] = "FMC", +- [_ASS_SEL] = "ASS", +- [_MSS_SEL] = "MSS", ++ [_AXIS_SEL] = "ASS", ++ [_MCUS_SEL] = "MSS", + [_USBPHY_SEL] = "USBPHY", + [_USBO_SEL] = "USBO", + }; +@@ -625,41 +601,6 @@ static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) + return &stm32mp1_clk_pll[idx]; + } + +-#if defined(IMAGE_BL32) +-/* List of forbiden values for hsi */ +-static uint16_t fbv_hsi[] = { 512, 480, 448, 416, 384, 352, 320, 288, 256, 224, +- 192, 160, 128, 96, 64, 32, 0 }; +-static uint16_t fbv_csi[] = { 256, 240, 224, 208, 192, 176, 160, 144, 128, 112, +- 96, 80, 64, 48, 32, 16, 0 }; +- +-static void hsi_set_trim(unsigned int cal); +-static unsigned int hsi_get_trimed_cal(void); +-static void csi_set_trim(unsigned int cal); +-static unsigned int csi_get_trimed_cal(void); +- +-static struct stm32mp1_clk_cal stm32mp1_clk_cal_hsi = { +- .fbv = fbv_hsi, +- .trim_max = 63, +- .trim_min = -64, +- .ref_freq = 0, +- .freq_margin = 1, +- .set_trim = hsi_set_trim, +- .get_trim = hsi_get_trimed_cal, +-}; +- +-static struct stm32mp1_clk_cal stm32mp1_clk_cal_csi = { +- .fbv = fbv_csi, +- .trim_max = 15, +- .trim_min = -16, +- .ref_freq = 0, +- .freq_margin = 2, +- .set_trim = csi_set_trim, +- .get_trim = csi_get_trimed_cal, +-}; +- +-static uint32_t timer_val; +-#endif +- + static int stm32mp1_lock_available(void) + { + /* The spinlocks are used only when MMU is enabled */ +@@ -799,7 +740,7 @@ static int stm32mp1_clk_get_parent(unsigned long id) + } + + sel = clk_sel_ref(s); +- p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk; ++ p_sel = (mmio_read_32(rcc_base + sel->offset) & sel->msk) >> sel->src; + if (p_sel < sel->nb_parent) { + #if LOG_LEVEL >= LOG_LEVEL_VERBOSE + VERBOSE("%s: %s clock is the parent %s of clk id %ld\n", +@@ -1315,6 +1256,13 @@ static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) + if (css) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); + } ++ ++#if defined(STM32MP_USB) || defined(STM32MP_UART) ++ if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) && ++ (!(digbyp || bypass))) { ++ panic(); ++ } ++#endif + } + + static void stm32mp1_csi_set(bool enable) +@@ -1460,7 +1408,10 @@ static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + +- mmio_write_32(pllxcr, RCC_PLLNCR_PLLON); ++ mmio_clrsetbits_32(pllxcr, ++ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | ++ RCC_PLLNCR_DIVREN, ++ RCC_PLLNCR_PLLON); + } + + static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) +@@ -1590,6 +1541,9 @@ static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) + RCC_PLLNCSGR_SSCG_MODE_MASK; + + mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); ++ ++ mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, ++ RCC_PLLNCR_SSCG_CTRL); + } + + static int stm32mp1_set_clksrc(unsigned int clksrc) +@@ -1799,6 +1753,32 @@ static void stm32mp1_pkcs_config(uint32_t pkcs) + mmio_clrsetbits_32(address, mask, value); + } + ++#if defined(IMAGE_BL32) ++void stm32mp1_clk_mpu_suspend(void) ++{ ++ uintptr_t mpckselr = stm32mp_rcc_base() + RCC_MPCKSELR; ++ ++ if (((mmio_read_32(mpckselr) & RCC_SELR_SRC_MASK)) == ++ RCC_MPCKSELR_PLL) { ++ if (stm32mp1_set_clksrc(CLK_MPU_PLL1P_DIV) != 0) { ++ panic(); ++ } ++ } ++} ++ ++void stm32mp1_clk_mpu_resume(void) ++{ ++ uintptr_t mpckselr = stm32mp_rcc_base() + RCC_MPCKSELR; ++ ++ if (((mmio_read_32(mpckselr) & RCC_SELR_SRC_MASK)) == ++ RCC_MPCKSELR_PLL_MPUDIV) { ++ if (stm32mp1_set_clksrc(CLK_MPU_PLL1P) != 0) { ++ panic(); ++ } ++ } ++} ++#endif ++ + int stm32mp1_clk_init(void) + { + uint32_t rcc_base = stm32mp_rcc_base(); +@@ -2138,365 +2118,6 @@ static void stm32mp1_osc_clk_init(const char *name, + } + } + +-#if defined(IMAGE_BL32) +-/* +- * HSI Calibration part +- */ +-static void hsi_set_trim(unsigned int cal) +-{ +- int clk_trim = (int)cal - (int)stm32mp1_clk_cal_hsi.cal_ref; +- uint32_t trim = ((uint32_t)clk_trim << RCC_HSICFGR_HSITRIM_SHIFT) & +- RCC_HSICFGR_HSITRIM_MASK; +- +- mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_HSICFGR, +- RCC_HSICFGR_HSITRIM_MASK, trim); +-} +- +-static unsigned int hsi_get_trimed_cal(void) +-{ +- uint32_t utrim = (mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR) & +- RCC_HSICFGR_HSITRIM_MASK) >> +- RCC_HSICFGR_HSITRIM_SHIFT; +- int trim = (int)utrim - stm32mp1_clk_cal_hsi.trim_max; +- +- if (trim + (int)stm32mp1_clk_cal_hsi.cal_ref < 0) { +- return 0; +- } +- +- return stm32mp1_clk_cal_hsi.cal_ref + trim; +-} +- +-static void csi_set_trim(unsigned int cal) +-{ +- int clk_trim = (int)cal - (int)stm32mp1_clk_cal_csi.cal_ref + +- stm32mp1_clk_cal_csi.trim_max + 1; +- uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) & +- RCC_CSICFGR_CSITRIM_MASK; +- +- mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_CSICFGR, +- RCC_CSICFGR_CSITRIM_MASK, trim); +-} +- +-static unsigned int csi_get_trimed_cal(void) +-{ +- uint32_t trim = (mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) & +- RCC_CSICFGR_CSITRIM_MASK) >> +- RCC_CSICFGR_CSITRIM_SHIFT; +- +- return (int)trim - stm32mp1_clk_cal_csi.trim_max + +- (int)stm32mp1_clk_cal_csi.cal_ref - 1; +-} +- +-static unsigned int trim_increase(struct stm32mp1_clk_cal *clk_cal, +- unsigned int cal) +-{ +- struct stm32mp1_trim_boundary_t *boundary; +- unsigned int new_cal; +- int i; +- +- /* By default: last calibration value */ +- new_cal = cal; +- +- /* Start from Lowest cal value */ +- for (i = (int)clk_cal->boundary_max - 1; i >= 0; i--) { +- boundary = &clk_cal->boundary[i]; +- +- if (cal < boundary->x2) { +- new_cal = boundary->x2; +- break; +- } +- +- if ((cal >= boundary->x2) && (cal < boundary->x1)) { +- new_cal = cal + 1; +- break; +- } +- } +- +- return new_cal; +-} +- +-static unsigned int trim_decrease(struct stm32mp1_clk_cal *clk_cal, +- unsigned int cal) +-{ +- struct stm32mp1_trim_boundary_t *boundary; +- unsigned int new_cal; +- unsigned int i; +- +- /* By default: last calibration value */ +- new_cal = cal; +- +- /* Start from Highest cal value */ +- for (i = 0; i < clk_cal->boundary_max; i++) { +- boundary = &clk_cal->boundary[i]; +- +- if (cal > boundary->x1) { +- new_cal = boundary->x1; +- break; +- } +- +- if ((cal > boundary->x2) && (cal <= boundary->x1)) { +- new_cal = cal - 1; +- break; +- } +- } +- +- return new_cal; +-} +- +-static void stm32mp1_rcc_calibration(struct stm32mp1_clk_cal *clk_cal) +-{ +- unsigned long freq = clk_cal->get_freq(); +- unsigned long min = clk_cal->ref_freq - +- ((clk_cal->ref_freq * clk_cal->freq_margin) / 100); +- unsigned long max = clk_cal->ref_freq + +- ((clk_cal->ref_freq * clk_cal->freq_margin) / 100); +- unsigned int nb_retries = CAL_MAX_RETRY; +- int cal = clk_cal->get_trim(); +- +- VERBOSE("Freq is %lu min %lu max %lu\n", freq, min, max); +- +- while (((freq < min) || (freq > max)) && (nb_retries != 0U)) { +- +- if (freq < min) { +- cal = trim_increase(clk_cal, cal); +- } else { +- cal = trim_decrease(clk_cal, cal); +- } +- +- clk_cal->set_trim(cal); +- +- freq = clk_cal->get_freq(); +- +- nb_retries--; +- } +- +- if (nb_retries == 0U) { +- ERROR("Calibration Failed\n"); +- panic(); +- } +-} +- +-static void save_trim(struct stm32mp1_clk_cal *clk_cal, +- unsigned int i, unsigned int x1, unsigned int x2) +-{ +- clk_cal->boundary[i].x1 = x1; +- clk_cal->boundary[i].x2 = x2; +-} +- +-static int trim_find_prev_boundary(struct stm32mp1_clk_cal *clk_cal, +- unsigned int x1) +-{ +- unsigned int x = x1; +- unsigned long freq; +- +- clk_cal->set_trim(x1 + 1); +- freq = clk_cal->get_freq(); +- +- while (x >= (clk_cal->cal_ref + clk_cal->trim_min)) { +- x--; +- clk_cal->set_trim(x); +- +- if (clk_cal->get_freq() <= freq) { +- break; +- } +- }; +- +- return x; +-} +- +-static void trim_table_init(struct stm32mp1_clk_cal *clk_cal) +-{ +- uint16_t *trim_fbv = clk_cal->fbv; +- unsigned int min; +- unsigned int max; +- int boundary = 0; +- int i = 0; +- +- max = clk_cal->cal_ref + clk_cal->trim_max; +- min = clk_cal->cal_ref + clk_cal->trim_min; +- +- while (trim_fbv[i]) { +- unsigned int x; +- unsigned int x1 = trim_fbv[i]; +- unsigned int x2 = trim_fbv[i + 1]; +- +- if ((max <= x2) || (min >= x1)) { +- i++; +- if (boundary != 0) { +- goto out; +- } +- continue; +- } +- +- /* Take forbiden value + 1 */ +- x2 = x2 + 1; +- if (x2 < min) { +- x2 = min; +- } +- +- if (boundary == 0) { +- /* Save first boundary */ +- save_trim(clk_cal, boundary, max, x2); +- boundary++; +- i++; +- continue; +- } +- +- x = trim_find_prev_boundary(clk_cal, x1); +- /* Save boundary values */ +- save_trim(clk_cal, boundary, x - 1, x2); +- boundary++; +- i++; +- }; +-out: +- clk_cal->boundary_max = boundary; +-} +- +-bool stm32mp1_rcc_get_wakeup(void) +-{ +- return rcc_wakeup; +-} +- +-void stm32mp1_rcc_set_wakeup(bool state) +-{ +- rcc_wakeup = state; +-} +- +-void stm32mp1_rcc_it_handler(uint32_t id) +-{ +- uintptr_t rcc_base = stm32mp_rcc_base(); +- +- switch (id) { +- case STM32MP1_IRQ_RCC_WAKEUP: +- plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY); +- mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF); +- stm32mp1_rcc_set_wakeup(true); +- return; +- +- case STM32MP1_IRQ_MCU_SEV: +- stm32mp1_rcc_set_wakeup(false); +- if ((mmio_read_32(EXTI_BASE + EXTI_RPR3) & +- EXTI_RPR3_RPIF65) != 0U) { +- mmio_setbits_32(EXTI_BASE + EXTI_RPR3, +- EXTI_RPR3_RPIF65); +- } +- +- if ((mmio_read_32(EXTI_BASE + EXTI_FPR3) & +- EXTI_FPR3_FPIF65) != 0U) { +- mmio_setbits_32(EXTI_BASE + EXTI_FPR3, +- EXTI_FPR3_FPIF65); +- } +- +- break; +- +- case ARM_IRQ_SEC_PHY_TIMER: +- default: +- break; +- } +- +- if (stm32mp1_clk_cal_hsi.ref_freq != 0U) { +- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi); +- } +- +- if (stm32mp1_clk_cal_csi.ref_freq != 0U) { +- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi); +- } +- +- if (timer_val != 0U) { +- write_cntptval(timer_val); +- } +-} +- +-int stm32mp1_rcc_start_hsi_cal(void) +-{ +- if (stm32mp1_clk_cal_hsi.ref_freq == 0U) { +- return -ENOENT; +- } +- +- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi); +- return 0; +-} +- +-int stm32mp1_rcc_start_csi_cal(void) +-{ +- if (stm32mp1_clk_cal_csi.ref_freq == 0U) { +- return -ENOENT; +- } +- +- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi); +- return 0; +-} +- +-static void init_hsi_cal(void) +-{ +- int len; +- +- if (fdt_rcc_read_prop("st,hsi-cal", &len) == NULL) { +- return; +- } +- +- stm32_timer_freq_func(&stm32mp1_clk_cal_hsi.get_freq, HSI_CAL); +- assert(stm32mp1_clk_cal_hsi.get_freq); +- +- stm32mp1_clk_cal_hsi.ref_freq = stm32mp_clk_get_rate(CK_HSI); +- +- /* Read initial value */ +- stm32mp1_clk_cal_hsi.cal_ref = +- ((mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR) +- & RCC_HSICFGR_HSICAL_MASK) >> RCC_HSICFGR_HSICAL_SHIFT); +- +- trim_table_init(&stm32mp1_clk_cal_hsi); +- +- stm32mp1_clk_cal_hsi.set_trim(stm32mp1_clk_cal_hsi.cal_ref); +- +- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi); +-} +- +-static void init_csi_cal(void) +-{ +- int len; +- +- if (fdt_rcc_read_prop("st,csi-cal", &len) == NULL) { +- return; +- } +- +- stm32_timer_freq_func(&stm32mp1_clk_cal_csi.get_freq, CSI_CAL); +- assert(stm32mp1_clk_cal_csi.get_freq); +- +- stm32mp1_clk_cal_csi.ref_freq = stm32mp_clk_get_rate(CK_CSI); +- +- /* Read initial value */ +- stm32mp1_clk_cal_csi.cal_ref = +- ((mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) & +- RCC_CSICFGR_CSICAL_MASK) >> RCC_CSICFGR_CSICAL_SHIFT); +- +- trim_table_init(&stm32mp1_clk_cal_csi); +- +- stm32mp1_clk_cal_csi.set_trim(stm32mp1_clk_cal_csi.cal_ref); +- +- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi); +-} +- +-void stm32mp1_cal_init(void) +-{ +- init_hsi_cal(); +- init_csi_cal(); +- +- timer_val = fdt_rcc_read_uint32_default("st,cal-sec", 0) * +- plat_get_syscnt_freq2(); +- +- if (timer_val != 0U) { +- /* Load & enable timer */ +- write_cntptval(timer_val); +- write_cntpctl(BIT(0)); +- }; +- +- if (fdt_rcc_enable_it("mcu_sev") < 0) { +- VERBOSE("No MCU calibration\n"); +- } +-} +-#endif +- + static void stm32mp1_osc_init(void) + { + enum stm32mp_osc_id i; +@@ -2529,7 +2150,7 @@ static int get_parent_id_parent(unsigned int parent_id) + case _ACLK: + case _PCLK4: + case _PCLK5: +- s = _ASS_SEL; ++ s = _AXIS_SEL; + break; + case _PLL1_P: + case _PLL1_Q: +@@ -2743,7 +2364,6 @@ void stm32mp1_update_earlyboot_clocks_state(void) + static void sync_earlyboot_clocks_state(void) + { + unsigned int idx; +- int res; + + for (idx = 0U; idx < NB_GATES; idx++) { + assert(gate_refcounts[idx] == 0); +@@ -2800,33 +2420,7 @@ static void sync_earlyboot_clocks_state(void) + stm32mp1_register_clock_parents_secure(BKPSRAM); + + stm32mp1_register_clock_parents_secure(RTCAPB); +- +- res = stm32mp_is_single_core(); +- if (res < 0) { +- panic(); +- } +- +- if (res == 0) { +- stm32mp1_clk_enable_secure(RTCAPB); +- } +-} +- +-void stm32mp1_rcc_init_late(void) +-{ +-#if defined(IMAGE_BL32) +- int irq_num; +- +- if (!stm32mp1_rcc_is_secure()) { +- return; +- } +- +- irq_num = fdt_rcc_enable_it("wakeup"); +- if (irq_num < 0) { +- panic(); +- } +- +- plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO); +-#endif ++ stm32mp1_clk_enable_secure(RTCAPB); + } + + int stm32mp1_clk_probe(void) +diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c +index ae5668a..00ebb22 100644 +--- a/drivers/st/ddr/stm32mp1_ddr.c ++++ b/drivers/st/ddr/stm32mp1_ddr.c +@@ -42,8 +42,22 @@ struct reg_desc { + .par_offset = offsetof(struct y, x) \ + } + ++/* ++ * PARAMETERS: value get from device tree : ++ * size / order need to be aligned with binding ++ * modification NOT ALLOWED !!! ++ */ ++#define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */ ++#define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */ ++#define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */ ++#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ ++ ++#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ ++#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ ++#define DDRPHY_REG_CAL_SIZE 12 /* st,phy-cal */ ++ + #define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) +-static const struct reg_desc ddr_reg[] = { ++static const struct reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { + DDRCTL_REG_REG(mstr), + DDRCTL_REG_REG(mrctrl0), + DDRCTL_REG_REG(mrctrl1), +@@ -72,7 +86,7 @@ static const struct reg_desc ddr_reg[] = { + }; + + #define DDRCTL_REG_TIMING(x) DDRCTL_REG(x, stm32mp1_ddrctrl_timing) +-static const struct reg_desc ddr_timing[] = { ++static const struct reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = { + DDRCTL_REG_TIMING(rfshtmg), + DDRCTL_REG_TIMING(dramtmg0), + DDRCTL_REG_TIMING(dramtmg1), +@@ -88,7 +102,7 @@ static const struct reg_desc ddr_timing[] = { + }; + + #define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp1_ddrctrl_map) +-static const struct reg_desc ddr_map[] = { ++static const struct reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = { + DDRCTL_REG_MAP(addrmap1), + DDRCTL_REG_MAP(addrmap2), + DDRCTL_REG_MAP(addrmap3), +@@ -101,7 +115,7 @@ static const struct reg_desc ddr_map[] = { + }; + + #define DDRCTL_REG_PERF(x) DDRCTL_REG(x, stm32mp1_ddrctrl_perf) +-static const struct reg_desc ddr_perf[] = { ++static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { + DDRCTL_REG_PERF(sched), + DDRCTL_REG_PERF(sched1), + DDRCTL_REG_PERF(perfhpr1), +@@ -122,7 +136,7 @@ static const struct reg_desc ddr_perf[] = { + }; + + #define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) +-static const struct reg_desc ddrphy_reg[] = { ++static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = { + DDRPHY_REG_REG(pgcr), + DDRPHY_REG_REG(aciocr), + DDRPHY_REG_REG(dxccr), +@@ -137,7 +151,7 @@ static const struct reg_desc ddrphy_reg[] = { + }; + + #define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) +-static const struct reg_desc ddrphy_timing[] = { ++static const struct reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = { + DDRPHY_REG_TIMING(ptr0), + DDRPHY_REG_TIMING(ptr1), + DDRPHY_REG_TIMING(ptr2), +@@ -151,7 +165,7 @@ static const struct reg_desc ddrphy_timing[] = { + }; + + #define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) +-static const struct reg_desc ddrphy_cal[] = { ++static const struct reg_desc ddrphy_cal[DDRPHY_REG_CAL_SIZE] = { + DDRPHY_REG_CAL(dx0dllcr), + DDRPHY_REG_CAL(dx0dqtr), + DDRPHY_REG_CAL(dx0dqstr), +@@ -166,36 +180,9 @@ static const struct reg_desc ddrphy_cal[] = { + DDRPHY_REG_CAL(dx3dqstr), + }; + +-#define DDR_REG_DYN(x) \ +- { \ +- .name = #x, \ +- .offset = offsetof(struct stm32mp1_ddrctl, x), \ +- .par_offset = INVALID_OFFSET \ +- } +- +-static const struct reg_desc ddr_dyn[] = { +- DDR_REG_DYN(stat), +- DDR_REG_DYN(init0), +- DDR_REG_DYN(dfimisc), +- DDR_REG_DYN(dfistat), +- DDR_REG_DYN(swctl), +- DDR_REG_DYN(swstat), +- DDR_REG_DYN(pctrl_0), +- DDR_REG_DYN(pctrl_1), +-}; +- +-#define DDRPHY_REG_DYN(x) \ +- { \ +- .name = #x, \ +- .offset = offsetof(struct stm32mp1_ddrphy, x), \ +- .par_offset = INVALID_OFFSET \ +- } +- +-static const struct reg_desc ddrphy_dyn[] = { +- DDRPHY_REG_DYN(pir), +- DDRPHY_REG_DYN(pgsr), +-}; +- ++/* ++ * REGISTERS ARRAY: used to parse device tree and interactive mode ++ */ + enum reg_type { + REG_REG, + REG_TIMING, +@@ -204,12 +191,6 @@ enum reg_type { + REGPHY_REG, + REGPHY_TIMING, + REGPHY_CAL, +-/* +- * Dynamic registers => managed in driver or not changed, +- * can be dumped in interactive mode. +- */ +- REG_DYN, +- REGPHY_DYN, + REG_TYPE_NB + }; + +@@ -230,55 +211,43 @@ static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { + [REG_REG] = { + .name = "static", + .desc = ddr_reg, +- .size = ARRAY_SIZE(ddr_reg), ++ .size = DDRCTL_REG_REG_SIZE, + .base = DDR_BASE + }, + [REG_TIMING] = { + .name = "timing", + .desc = ddr_timing, +- .size = ARRAY_SIZE(ddr_timing), ++ .size = DDRCTL_REG_TIMING_SIZE, + .base = DDR_BASE + }, + [REG_PERF] = { + .name = "perf", + .desc = ddr_perf, +- .size = ARRAY_SIZE(ddr_perf), ++ .size = DDRCTL_REG_PERF_SIZE, + .base = DDR_BASE + }, + [REG_MAP] = { + .name = "map", + .desc = ddr_map, +- .size = ARRAY_SIZE(ddr_map), ++ .size = DDRCTL_REG_MAP_SIZE, + .base = DDR_BASE + }, + [REGPHY_REG] = { + .name = "static", + .desc = ddrphy_reg, +- .size = ARRAY_SIZE(ddrphy_reg), ++ .size = DDRPHY_REG_REG_SIZE, + .base = DDRPHY_BASE + }, + [REGPHY_TIMING] = { + .name = "timing", + .desc = ddrphy_timing, +- .size = ARRAY_SIZE(ddrphy_timing), ++ .size = DDRPHY_REG_TIMING_SIZE, + .base = DDRPHY_BASE + }, + [REGPHY_CAL] = { + .name = "cal", + .desc = ddrphy_cal, +- .size = ARRAY_SIZE(ddrphy_cal), +- .base = DDRPHY_BASE +- }, +- [REG_DYN] = { +- .name = "dyn", +- .desc = ddr_dyn, +- .size = ARRAY_SIZE(ddr_dyn), +- .base = DDR_BASE +- }, +- [REGPHY_DYN] = { +- .name = "dyn", +- .desc = ddrphy_dyn, +- .size = ARRAY_SIZE(ddrphy_dyn), ++ .size = DDRPHY_REG_CAL_SIZE, + .base = DDRPHY_BASE + }, + }; +diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c +index 82b8fda..773c9f7 100644 +--- a/drivers/st/ddr/stm32mp1_ram.c ++++ b/drivers/st/ddr/stm32mp1_ram.c +@@ -252,8 +252,8 @@ static int stm32mp1_ddr_setup(void) + VERBOSE("%s: %s[0x%x] = %d\n", __func__, + param[idx].name, param[idx].size, ret); + if (ret != 0) { +- ERROR("%s: Cannot read %s\n", +- __func__, param[idx].name); ++ ERROR("%s: Cannot read %s, error=%d\n", ++ __func__, param[idx].name, ret); + return -EINVAL; + } + } +diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c +index 694a76a..ce609ba 100644 +--- a/drivers/st/i2c/stm32_i2c.c ++++ b/drivers/st/i2c/stm32_i2c.c +@@ -79,18 +79,18 @@ struct i2c_timing_s { + bool is_saved; + }; + +-/** +- * All these values are coming from I2C Specification, Version 6.0, 4th of +- * April 2014. ++/* ++ * I2C specification values as per version 6.0, 4th of April 2014 [1], ++ * table 10 page 48: Characteristics of the SDA and SCL bus lines for ++ * Standard, Fast, and Fast-mode Plus I2C-bus devices. + * +- * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast, +- * and Fast-mode Plus I2C-bus devices. ++ * [1] https://www.i2c-bus.org/specification/ + */ + static const struct i2c_spec_s i2c_specs[] = { + [I2C_SPEED_STANDARD] = { + .rate = STANDARD_RATE, +- .rate_min = 8000, +- .rate_max = 120000, ++ .rate_min = (STANDARD_RATE * 80) / 100, ++ .rate_max = (STANDARD_RATE * 120) / 100, + .fall_max = 300, + .rise_max = 1000, + .hddat_min = 0, +@@ -101,8 +101,8 @@ static const struct i2c_spec_s i2c_specs[] = { + }, + [I2C_SPEED_FAST] = { + .rate = FAST_RATE, +- .rate_min = 320000, +- .rate_max = 480000, ++ .rate_min = (FAST_RATE * 80) / 100, ++ .rate_max = (FAST_RATE * 120) / 100, + .fall_max = 300, + .rise_max = 300, + .hddat_min = 0, +@@ -113,8 +113,8 @@ static const struct i2c_spec_s i2c_specs[] = { + }, + [I2C_SPEED_FAST_PLUS] = { + .rate = FAST_PLUS_RATE, +- .rate_min = 800000, +- .rate_max = 1200000, ++ .rate_min = (FAST_PLUS_RATE * 80) / 100, ++ .rate_max = (FAST_PLUS_RATE * 120) / 100, + .fall_max = 100, + .rise_max = 120, + .hddat_min = 0, +@@ -125,6 +125,9 @@ static const struct i2c_spec_s i2c_specs[] = { + }, + }; + ++static uint32_t saved_timing; ++static unsigned long saved_frequency; ++ + static int i2c_request_memory_write(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint16_t mem_addr, + uint16_t mem_add_size, +@@ -376,7 +379,7 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, + uint32_t *timing) + { + int rc = 0; +- uint32_t clock_src; ++ unsigned long clock_src; + + clock_src = stm32mp_clk_get_rate(hi2c->clock); + if (clock_src == 0U) { +@@ -384,6 +387,15 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, + return -EINVAL; + } + ++ /* ++ * If the timing has already been computed, and the frequency is the ++ * same as when it was computed, then use the saved timing. ++ */ ++ if (clock_src == saved_frequency) { ++ *timing = saved_timing; ++ return 0; ++ } ++ + do { + rc = i2c_compute_timing(init, clock_src, timing); + if (rc != 0) { +@@ -403,7 +415,7 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, + return rc; + } + +- VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%i)\n", ++ VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%li)\n", + init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src); + VERBOSE("I2C Rise(%i) and Fall(%i) Time\n", + init->rise_time, init->fall_time); +@@ -411,6 +423,9 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, + (init->analog_filter ? "On" : "Off"), + init->digital_filter_coef); + ++ saved_timing = *timing; ++ saved_frequency = clock_src; ++ + return 0; + } + +diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c +index 6d91a9f..1b5bfe3 100644 +--- a/drivers/st/iwdg/stm32_iwdg.c ++++ b/drivers/st/iwdg/stm32_iwdg.c +@@ -182,6 +182,10 @@ void stm32_iwdg_refresh(uint32_t instance) + + assert(iwdg); + ++ if (iwdg->base == 0U) { ++ return; ++ } ++ + stm32mp_clk_enable(iwdg->clock); + + mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); +@@ -215,14 +219,14 @@ int stm32_iwdg_init(void) + iwdg->clock = (unsigned long)dt_info.clock; + + /* DT can specify low power cases */ +- if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) != ++ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) == + NULL) { +- iwdg->flags |= IWDG_ENABLE_ON_STOP; ++ iwdg->flags |= IWDG_DISABLE_ON_STOP; + } + +- if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) != ++ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) == + NULL) { +- iwdg->flags |= IWDG_ENABLE_ON_STANDBY; ++ iwdg->flags |= IWDG_DISABLE_ON_STANDBY; + } + + /* Explicit list of supported bit flags */ +@@ -243,12 +247,12 @@ int stm32_iwdg_init(void) + goto next; + } + +- if ((hw_init & IWDG_ENABLE_ON_STOP) != 0) { +- iwdg->flags |= IWDG_ENABLE_ON_STOP; ++ if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) { ++ iwdg->flags |= IWDG_DISABLE_ON_STOP; + } + +- if ((hw_init & IWDG_ENABLE_ON_STANDBY) != 0) { +- iwdg->flags |= IWDG_ENABLE_ON_STANDBY; ++ if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) { ++ iwdg->flags |= IWDG_DISABLE_ON_STANDBY; + } + + VERBOSE("IWDG%u found, %ssecure\n", idx + 1, +diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c +index 620087e..aab0582 100644 +--- a/drivers/st/mmc/stm32_sdmmc2.c ++++ b/drivers/st/mmc/stm32_sdmmc2.c +@@ -70,20 +70,14 @@ + #define SDMMC_DCTRLR_DTEN BIT(0) + #define SDMMC_DCTRLR_DTDIR BIT(1) + #define SDMMC_DCTRLR_DTMODE GENMASK(3, 2) +-#define SDMMC_DCTRLR_DBLOCKSIZE_0 BIT(4) +-#define SDMMC_DCTRLR_DBLOCKSIZE_1 BIT(5) +-#define SDMMC_DCTRLR_DBLOCKSIZE_3 BIT(7) + #define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4) ++#define SDMMC_DCTRLR_DBLOCKSIZE_SHIFT 4 + #define SDMMC_DCTRLR_FIFORST BIT(13) + + #define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \ + SDMMC_DCTRLR_DTDIR | \ + SDMMC_DCTRLR_DTMODE | \ + SDMMC_DCTRLR_DBLOCKSIZE) +-#define SDMMC_DBLOCKSIZE_8 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \ +- SDMMC_DCTRLR_DBLOCKSIZE_1) +-#define SDMMC_DBLOCKSIZE_512 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \ +- SDMMC_DCTRLR_DBLOCKSIZE_3) + + /* SDMMC status register */ + #define SDMMC_STAR_CCRCFAIL BIT(0) +@@ -172,10 +166,15 @@ static void dump_registers(void) + static void stm32_sdmmc2_init(void) + { + uint32_t clock_div; ++ uint32_t freq = STM32MP_MMC_INIT_FREQ; + uintptr_t base = sdmmc2_params.reg_base; + ++ if (sdmmc2_params.max_freq != 0U) { ++ freq = MIN(sdmmc2_params.max_freq, STM32MP_MMC_INIT_FREQ); ++ } ++ + clock_div = div_round_up(sdmmc2_params.clk_rate, +- STM32MP_MMC_INIT_FREQ * 2); ++ freq * 2); + + mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | + sdmmc2_params.negedge | +@@ -426,7 +425,7 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width) + { + uintptr_t base = sdmmc2_params.reg_base; + uint32_t bus_cfg = 0; +- uint32_t clock_div, max_freq; ++ uint32_t clock_div, max_freq, freq; + uint32_t clk_rate = sdmmc2_params.clk_rate; + uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq; + +@@ -458,7 +457,13 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width) + } + } + +- clock_div = div_round_up(clk_rate, max_freq * 2); ++ if (sdmmc2_params.max_freq != 0U) { ++ freq = MIN(sdmmc2_params.max_freq, max_freq); ++ } else { ++ freq = max_freq; ++ } ++ ++ clock_div = div_round_up(clk_rate, freq * 2); + + mmio_write_32(base + SDMMC_CLKCR, + SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg | +@@ -474,11 +479,12 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) + int ret; + uintptr_t base = sdmmc2_params.reg_base; + uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR; ++ uint32_t arg_size; + +- if (size == 8U) { +- data_ctrl |= SDMMC_DBLOCKSIZE_8; ++ if (size > MMC_BLOCK_SIZE) { ++ arg_size = MMC_BLOCK_SIZE; + } else { +- data_ctrl |= SDMMC_DBLOCKSIZE_512; ++ arg_size = size; + } + + sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf); +@@ -497,12 +503,7 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) + zeromem(&cmd, sizeof(struct mmc_cmd)); + + cmd.cmd_idx = MMC_CMD(16); +- if (size > MMC_BLOCK_SIZE) { +- cmd.cmd_arg = MMC_BLOCK_SIZE; +- } else { +- cmd.cmd_arg = size; +- } +- ++ cmd.cmd_arg = arg_size; + cmd.resp_type = MMC_RESPONSE_R1; + + ret = stm32_sdmmc2_send_cmd(&cmd); +@@ -524,6 +525,8 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) + flush_dcache_range(buf, size); + } + ++ data_ctrl |= __builtin_ctz(arg_size) << SDMMC_DCTRLR_DBLOCKSIZE_SHIFT; ++ + mmio_clrsetbits_32(base + SDMMC_DCTRLR, + SDMMC_DCTRLR_CLEAR_MASK, + data_ctrl); +@@ -714,6 +717,11 @@ static int stm32_sdmmc2_dt_get_config(void) + } + } + ++ cuint = fdt_getprop(fdt, sdmmc_node, "max-frequency", NULL); ++ if (cuint != NULL) { ++ sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); ++ } ++ + return 0; + } + +@@ -745,6 +753,7 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) + mdelay(1); + + sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id); ++ sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4; + + return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate, + sdmmc2_params.bus_width, sdmmc2_params.flags, +diff --git a/drivers/st/nand/nand.c b/drivers/st/nand/nand.c +index 7f435cc..9198800 100644 +--- a/drivers/st/nand/nand.c ++++ b/drivers/st/nand/nand.c +@@ -83,21 +83,16 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand) + nand_timings *tims = &hNand->Info.timings; + unsigned long hclk = stm32mp_clk_get_rate(FMC_K); + unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000); +- int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att; +- +- tar = hclkp; +- if (tar < FMC_TAR_MIN) +- tar = FMC_TAR_MIN; +- tims->tar = div_round_up(tar, hclkp) - 1; +- if (tims->tar > FMC_PCR_TIMING_MASK) +- tims->tar = FMC_PCR_TIMING_MASK; +- +- tclr = hclkp; +- if (tclr < FMC_TCLR_MIN) +- tclr = FMC_TCLR_MIN; +- tims->tclr = div_round_up(tclr, hclkp) - 1; +- if (tims->tclr > FMC_PCR_TIMING_MASK) +- tims->tclr = FMC_PCR_TIMING_MASK; ++ unsigned long timing, tar, tclr, thiz, twait; ++ unsigned long tset_mem, tset_att, thold_mem, thold_att; ++ ++ tar = MAX(hclkp, FMC_TAR_MIN); ++ timing = div_round_up(tar, hclkp) - 1; ++ tims->tar = MIN(timing, FMC_PCR_TIMING_MASK); ++ ++ tclr = MAX(hclkp, FMC_TCLR_MIN); ++ timing = div_round_up(tclr, hclkp) - 1; ++ tims->tclr = MIN(timing, FMC_PCR_TIMING_MASK); + + tims->thiz = FMC_THIZ; + thiz = (tims->thiz + 1) * hclkp; +@@ -107,16 +102,11 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand) + * tWAIT > tWP + * tWAIT > tREA + tIO + */ +- twait = hclkp; +- if (twait < FMC_TRP_MIN) +- twait = FMC_TRP_MIN; +- if (twait < FMC_TWP_MIN) +- twait = FMC_TWP_MIN; +- if (twait < FMC_TREA_MAX + FMC_TIO) +- twait = FMC_TREA_MAX + FMC_TIO; +- tims->twait = div_round_up(twait, hclkp); +- if (tims->twait == 0) +- tims->twait = 1; ++ twait = MAX(hclkp, FMC_TRP_MIN); ++ twait = MAX(twait, FMC_TWP_MIN); ++ twait = MAX(twait, FMC_TREA_MAX + FMC_TIO); ++ timing = div_round_up(twait, hclkp); ++ tims->twait = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK); + + /* + * tSETUP_MEM > tCS - tWAIT +@@ -124,37 +114,39 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand) + * tSETUP_MEM > tDS - (tWAIT - tHIZ) + */ + tset_mem = hclkp; +- if (twait < FMC_TCS_MIN && (tset_mem < FMC_TCS_MIN - twait)) ++ if (twait < FMC_TCS_MIN && (tset_mem < FMC_TCS_MIN - twait)) { + tset_mem = FMC_TCS_MIN - twait; +- if (twait < FMC_TALS_MIN && (tset_mem < FMC_TALS_MIN - twait)) ++ } ++ if (twait < FMC_TALS_MIN && (tset_mem < FMC_TALS_MIN - twait)) { + tset_mem = FMC_TALS_MIN - twait; ++ } + if (twait > thiz && (twait - thiz < FMC_TDS_MIN) && +- (tset_mem < FMC_TDS_MIN - (twait - thiz))) ++ (tset_mem < FMC_TDS_MIN - (twait - thiz))) { + tset_mem = FMC_TDS_MIN - (twait - thiz); +- tims->tset_mem = div_round_up(tset_mem, hclkp); +- if (tims->tset_mem == 0) +- tims->tset_mem = 1; ++ } ++ timing = div_round_up(tset_mem, hclkp); ++ tims->tset_mem = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK); + + /* + * tHOLD_MEM > tCH + * tHOLD_MEM > tREH - tSETUP_MEM + * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) + */ +- thold_mem = hclkp; +- if (thold_mem < FMC_TCH_MIN) +- thold_mem = FMC_TCH_MIN; ++ thold_mem = MAX(hclkp, FMC_TCH_MIN); + if (tset_mem < FMC_TREH_MIN && +- (thold_mem < FMC_TREH_MIN - tset_mem)) ++ (thold_mem < FMC_TREH_MIN - tset_mem)) { + thold_mem = FMC_TREH_MIN - tset_mem; ++ } + if ((tset_mem + twait < FMC_TRC_MIN) && +- (thold_mem < FMC_TRC_MIN - (tset_mem + twait))) ++ (thold_mem < FMC_TRC_MIN - (tset_mem + twait))) { + thold_mem = FMC_TRC_MIN - (tset_mem + twait); ++ } + if ((tset_mem + twait < FMC_TWC_MIN) && +- (thold_mem < FMC_TWC_MIN - (tset_mem + twait))) ++ (thold_mem < FMC_TWC_MIN - (tset_mem + twait))) { + thold_mem = FMC_TWC_MIN - (tset_mem + twait); +- tims->thold_mem = div_round_up(thold_mem, hclkp); +- if (tims->thold_mem == 0) +- tims->thold_mem = 1; ++ } ++ timing = div_round_up(thold_mem, hclkp); ++ tims->thold_mem = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK); + + /* + * tSETUP_ATT > tCS - tWAIT +@@ -164,21 +156,25 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand) + * tSETUP_ATT > tDS - (tWAIT - tHIZ) + */ + tset_att = hclkp; +- if (twait < FMC_TCS_MIN && (tset_att < FMC_TCS_MIN - twait)) ++ if (twait < FMC_TCS_MIN && (tset_att < FMC_TCS_MIN - twait)) { + tset_att = FMC_TCS_MIN - twait; +- if (twait < FMC_TCLS_MIN && (tset_att < FMC_TCLS_MIN - twait)) ++ } ++ if (twait < FMC_TCLS_MIN && (tset_att < FMC_TCLS_MIN - twait)) { + tset_att = FMC_TCLS_MIN - twait; +- if (twait < FMC_TALS_MIN && (tset_att < FMC_TALS_MIN - twait)) ++ } ++ if (twait < FMC_TALS_MIN && (tset_att < FMC_TALS_MIN - twait)) { + tset_att = FMC_TALS_MIN - twait; ++ } + if (thold_mem < FMC_TRHW_MIN && +- (tset_att < FMC_TRHW_MIN - thold_mem)) ++ (tset_att < FMC_TRHW_MIN - thold_mem)) { + tset_att = FMC_TRHW_MIN - thold_mem; ++ } + if (twait > thiz && (twait - thiz < FMC_TDS_MIN) && +- (tset_att < FMC_TDS_MIN - (twait - thiz))) ++ (tset_att < FMC_TDS_MIN - (twait - thiz))) { + tset_att = FMC_TDS_MIN - (twait - thiz); +- tims->tset_att = div_round_up(tset_att, hclkp); +- if (tims->tset_att == 0) +- tims->tset_att = 1; ++ } ++ timing = div_round_up(tset_att, hclkp); ++ tims->tset_att = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK); + + /* + * tHOLD_ATT > tALH +@@ -193,38 +189,42 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand) + * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) + * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) + */ +- thold_att = hclkp; +- if (thold_att < FMC_TALH_MIN) +- thold_att = FMC_TALH_MIN; +- if (thold_att < FMC_TCH_MIN) +- thold_att = FMC_TCH_MIN; +- if (thold_att < FMC_TCLH_MIN) +- thold_att = FMC_TCLH_MIN; +- if (thold_att < FMC_TCOH_MIN) +- thold_att = FMC_TCOH_MIN; +- if (thold_att < FMC_TDH_MIN) +- thold_att = FMC_TDH_MIN; ++ thold_att = MAX(hclkp, FMC_TALH_MIN); ++ thold_att = MAX(hclkp, FMC_TCH_MIN); ++ thold_att = MAX(hclkp, FMC_TCLH_MIN); ++ thold_att = MAX(hclkp, FMC_TCOH_MIN); ++ thold_att = MAX(hclkp, FMC_TDH_MIN); + if ((FMC_TWB_MAX + FMC_TIO + FMC_TSYNC > tset_mem) && +- (thold_att < FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem)) ++ (thold_att < FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem)) { + thold_att = FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem; ++ } + if (tset_mem < FMC_TADL_MIN && +- (thold_att < FMC_TADL_MIN - tset_mem)) ++ (thold_att < FMC_TADL_MIN - tset_mem)) { + thold_att = FMC_TADL_MIN - tset_mem; ++ } + if (tset_mem < FMC_TWH_MIN && +- (thold_att < FMC_TWH_MIN - tset_mem)) ++ (thold_att < FMC_TWH_MIN - tset_mem)) { + thold_att = FMC_TWH_MIN - tset_mem; ++ } + if (tset_mem < FMC_TWHR_MIN && +- (thold_att < FMC_TWHR_MIN - tset_mem)) ++ (thold_att < FMC_TWHR_MIN - tset_mem)) { + thold_att = FMC_TWHR_MIN - tset_mem; ++ } + if (tset_att + twait < FMC_TRC_MIN && +- (thold_att < FMC_TRC_MIN - (tset_att + twait))) ++ (thold_att < FMC_TRC_MIN - (tset_att + twait))) { + thold_att = FMC_TRC_MIN - (tset_att + twait); ++ } + if (tset_att + twait < FMC_TWC_MIN && +- (thold_att < FMC_TWC_MIN - (tset_att + twait))) ++ (thold_att < FMC_TWC_MIN - (tset_att + twait))) { + thold_att = FMC_TWC_MIN - (tset_att + twait); +- tims->thold_att = div_round_up(thold_att, hclkp); +- if (tims->thold_att == 0) +- tims->thold_att = 1; ++ } ++ timing = div_round_up(thold_att, hclkp); ++ tims->thold_att = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK); ++ ++ VERBOSE("Nand timings: %u - %u - %u - %u - %u - %u - %u - %u\n", ++ tims->tclr, tims->tar, tims->thiz, tims->twait, ++ tims->thold_mem, tims->tset_mem, ++ tims->thold_att, tims->tset_att); + } + + /***************************************************************************** +diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c +index 6d36e31..4c58000 100644 +--- a/drivers/st/timer/stm32_timer.c ++++ b/drivers/st/timer/stm32_timer.c +@@ -59,6 +59,7 @@ + #define TIM_TIMEOUT_STEP_US 10 + #define TIM_PRESCAL_HSI 10U + #define TIM_PRESCAL_CSI 7U ++#define TIM_MIN_FREQ_CALIB 50000000U + + struct stm32_timer_instance { + uintptr_t base; +@@ -84,12 +85,18 @@ static int stm32_timer_get_dt_node(struct dt_node_info *info, int offset) + return node; + } + +-static void stm32_timer_config(struct stm32_timer_instance *timer) ++static int stm32_timer_config(struct stm32_timer_instance *timer) + { + stm32mp_clk_enable(timer->clk); + + timer->freq = stm32mp_clk_timer_get_rate(timer->clk); + ++ if (timer->freq < TIM_MIN_FREQ_CALIB) { ++ WARN("Timer is not accurate enough for calibration\n"); ++ stm32mp_clk_disable(timer->clk); ++ return -EINVAL; ++ } ++ + if ((mmio_read_32(timer->base + TIM_TISEL) & TIM_TISEL_TI1SEL_MASK) != + timer->cal_input) { + mmio_clrsetbits_32(timer->base + TIM_CCMR1, +@@ -110,6 +117,8 @@ static void stm32_timer_config(struct stm32_timer_instance *timer) + } + + stm32mp_clk_disable(timer->clk); ++ ++ return 0; + } + + static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer) +@@ -119,7 +128,9 @@ static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer) + uint32_t old_counter = 0U; + int twice = 0; + +- stm32_timer_config(timer); ++ if (stm32_timer_config(timer) < 0) { ++ return 0U; ++ } + + stm32mp_clk_enable(timer->clk); + +@@ -268,10 +279,13 @@ int stm32_timer_init(void) + stm32mp_clk_timer_get_rate(timer->clk); + timer->cal_input = + (uint8_t)fdt32_to_cpu(*cuint); +- stm32_timer_config(timer); ++ if (stm32_timer_config(timer) < 0) { ++ timer->base = 0; ++ continue; ++ } + } + +- cuint = fdt_getprop(fdt, node, "st,csi_cal-input", ++ cuint = fdt_getprop(fdt, node, "st,csi-cal-input", + NULL); + if (cuint != NULL) { + timer = &stm32_timer[CSI_CAL]; +@@ -281,7 +295,10 @@ int stm32_timer_init(void) + stm32mp_clk_timer_get_rate(timer->clk); + timer->cal_input = + (uint8_t)fdt32_to_cpu(*cuint); +- stm32_timer_config(timer); ++ if (stm32_timer_config(timer) < 0) { ++ timer->base = 0; ++ continue; ++ } + } + } + } +diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +index 16b8cf6..11e8f2b 100644 +--- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi ++++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +@@ -1,8 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + /* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved +- */ +-/* STM32MP157C DK1/DK2 BOARD configuration ++ * ++ * STM32MP157C DK1/DK2 BOARD configuration + * 1x DDR3L 4Gb, 16-bit, 533MHz. + * Reference used NT5CC256M16DP-DI from NANYA + * +@@ -16,8 +16,7 @@ + * address mapping : RBC + * Tc > + 85C : N + */ +- +-#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41" ++#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45" + #define DDR_MEM_SPEED 533000 + #define DDR_MEM_SIZE 0x20000000 + +@@ -90,7 +89,7 @@ + #define DDR_PTR2 0x042DA068 + #define DDR_ACIOCR 0x10400812 + #define DDR_DXCCR 0x00000C40 +-#define DDR_DSGCR 0xF200001F ++#define DDR_DSGCR 0xF200011F + #define DDR_DCR 0x0000000B + #define DDR_DTPR0 0x38D488D0 + #define DDR_DTPR1 0x098B00D8 +@@ -109,11 +108,11 @@ + #define DDR_DX1DLLCR 0x40000000 + #define DDR_DX1DQTR 0xFFFFFFFF + #define DDR_DX1DQSTR 0x3DB02000 +-#define DDR_DX2GCR 0x0000CE81 ++#define DDR_DX2GCR 0x0000CE80 + #define DDR_DX2DLLCR 0x40000000 + #define DDR_DX2DQTR 0xFFFFFFFF + #define DDR_DX2DQSTR 0x3DB02000 +-#define DDR_DX3GCR 0x0000CE81 ++#define DDR_DX3GCR 0x0000CE80 + #define DDR_DX3DLLCR 0x40000000 + #define DDR_DX3DQTR 0xFFFFFFFF + #define DDR_DX3DQSTR 0x3DB02000 +diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +index 82e7104..4b70b60 100644 +--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi ++++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +@@ -1,9 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + /* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved +- */ +- +-/* STM32MP157C ED1 BOARD configuration ++ * ++ * STM32MP157C ED1 BOARD configuration + * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. + * Reference used NT5CC256M16DP-DI from NANYA + * +@@ -17,8 +16,7 @@ + * address mapping : RBC + * Tc > + 85C : N + */ +- +-#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41" ++#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45" + #define DDR_MEM_SPEED 533000 + #define DDR_MEM_SIZE 0x40000000 + +@@ -91,7 +89,7 @@ + #define DDR_PTR2 0x042DA068 + #define DDR_ACIOCR 0x10400812 + #define DDR_DXCCR 0x00000C40 +-#define DDR_DSGCR 0xF200001F ++#define DDR_DSGCR 0xF200011F + #define DDR_DCR 0x0000000B + #define DDR_DTPR0 0x38D488D0 + #define DDR_DTPR1 0x098B00D8 +diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts +index fadb442..f081575 100644 +--- a/fdts/stm32mp157a-dk1.dts ++++ b/fdts/stm32mp157a-dk1.dts +@@ -149,7 +149,9 @@ + }; + + &pwr { +- pwr-supply = <&vdd>; ++ pwr-regulators { ++ vdd-supply = <&vdd>; ++ }; + }; + + &rng1 { +@@ -269,7 +271,7 @@ + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P +- CLK_FDCAN_PLL4Q ++ CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q +@@ -306,6 +308,14 @@ + }; + + /* Security specific */ ++&bsec { ++ board_id: board_id@ec { ++ reg = <0xec 0x4>; ++ status = "okay"; ++ secure-status = "okay"; ++ }; ++}; ++ + &etzpc { + st,decprot = < + DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) +@@ -335,7 +345,7 @@ + &timers15 { + secure-status = "okay"; + st,hsi-cal-input = <7>; +- st,csi_cal-input = <8>; ++ st,csi-cal-input = <8>; + }; + + /* Low-power states of regulators */ +diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts +index 0daf4be..61d5301 100644 +--- a/fdts/stm32mp157c-ed1.dts ++++ b/fdts/stm32mp157c-ed1.dts +@@ -144,7 +144,9 @@ + }; + + &pwr { +- pwr-supply = <&vdd>; ++ pwr-regulators { ++ vdd-supply = <&vdd>; ++ }; + }; + + &rng1 { +@@ -274,7 +276,7 @@ + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P +- CLK_FDCAN_PLL4Q ++ CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q +@@ -311,6 +313,14 @@ + }; + + /* Security specific */ ++&bsec { ++ board_id: board_id@ec { ++ reg = <0xec 0x4>; ++ status = "okay"; ++ secure-status = "okay"; ++ }; ++}; ++ + &etzpc { + st,decprot = < + DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) +@@ -331,6 +341,7 @@ + system_suspend_supported_soc_modes = < + STM32_PM_CSLEEP_RUN + STM32_PM_CSTOP_ALLOW_LP_STOP ++ STM32_PM_CSTOP_ALLOW_LPLV_STOP + STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR + >; + system_off_soc_mode = ; +@@ -339,7 +350,7 @@ + &timers15 { + secure-status = "okay"; + st,hsi-cal-input = <7>; +- st,csi_cal-input = <8>; ++ st,csi-cal-input = <8>; + }; + + /* Low-power states of regulators */ +@@ -348,6 +359,10 @@ + regulator-on-in-suspend; + regulator-suspend-microvolt = <1200000>; + }; ++ lplv-stop { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; + standby-ddr-sr { + regulator-off-in-suspend; + }; +@@ -361,6 +376,10 @@ + regulator-suspend-microvolt = <1350000>; + regulator-on-in-suspend; + }; ++ lplv-stop { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; + standby-ddr-sr { + regulator-suspend-microvolt = <1350000>; + regulator-on-in-suspend; +@@ -375,6 +394,10 @@ + regulator-suspend-microvolt = <3300000>; + regulator-on-in-suspend; + }; ++ lplv-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; + standby-ddr-sr { + regulator-suspend-microvolt = <3300000>; + regulator-on-in-suspend; +@@ -416,6 +439,9 @@ + lp-stop { + regulator-off-in-suspend; + }; ++ lplv-stop { ++ regulator-off-in-suspend; ++ }; + standby-ddr-sr { + regulator-off-in-suspend; + }; +@@ -455,6 +481,9 @@ + lp-stop { + regulator-on-in-suspend; + }; ++ lplv-stop { ++ regulator-on-in-suspend; ++ }; + standby-ddr-sr { + regulator-on-in-suspend; + }; +diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi +index 8d45a33..124ed53 100644 +--- a/fdts/stm32mp157c-security.dtsi ++++ b/fdts/stm32mp157c-security.dtsi +@@ -8,7 +8,7 @@ + + / { + soc { +- iwdg1: iwdg@5C003000 { ++ iwdg1: watchdog@5C003000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5C003000 0x400>; + clocks = <&rcc IWDG1>, <&rcc CK_LSI>; +@@ -41,9 +41,6 @@ + spare_ns_ea: spare_ns_ea@ea { + reg = <0xea 0x2>; + }; +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- }; + }; + + &iwdg2 { +diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi +index 06c2cf1..e649c3a 100644 +--- a/fdts/stm32mp157c.dtsi ++++ b/fdts/stm32mp157c.dtsi +@@ -290,6 +290,27 @@ + status = "disabled"; + }; + ++ usbphyc: usbphyc@5a006000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <0>; ++ compatible = "st,stm32mp1-usbphyc"; ++ reg = <0x5a006000 0x1000>; ++ clocks = <&rcc USBPHY_K>; ++ resets = <&rcc USBPHY_R>; ++ status = "disabled"; ++ ++ usbphyc_port0: usb-phy@0 { ++ #phy-cells = <0>; ++ reg = <0>; ++ }; ++ ++ usbphyc_port1: usb-phy@1 { ++ #phy-cells = <1>; ++ reg = <1>; ++ }; ++ }; ++ + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; +diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h +index 9900630..38553b9 100644 +--- a/include/drivers/mmc.h ++++ b/include/drivers/mmc.h +@@ -219,6 +219,7 @@ struct mmc_device_info { + unsigned long long device_size; /* Size of device in bytes */ + unsigned int block_size; /* Block size in bytes */ + unsigned int max_bus_freq; /* Max bus freq in Hz */ ++ unsigned int ocr_voltage; /* OCR voltage */ + enum mmc_device_type mmc_dev_type; /* Type of MMC */ + }; + +diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h +index b21bde8..71a68c2 100644 +--- a/include/drivers/st/bsec.h ++++ b/include/drivers/st/bsec.h +@@ -135,7 +135,7 @@ + */ + #define BSEC_LOCK_UPPER_OTP 0x00 + #define BSEC_LOCK_DEBUG 0x02 +-#define BSEC_LOCK_PROGRAM 0x03 ++#define BSEC_LOCK_PROGRAM 0x04 + + /* Values for struct bsec_config::freq */ + #define FREQ_10_20_MHZ 0x0 +@@ -189,16 +189,15 @@ uint32_t bsec_get_version(void); + uint32_t bsec_get_id(void); + uint32_t bsec_get_magic_id(void); + +-bool bsec_write_sr_lock(uint32_t otp, uint32_t value); +-bool bsec_read_sr_lock(uint32_t otp); +-bool bsec_write_sw_lock(uint32_t otp, uint32_t value); +-bool bsec_read_sw_lock(uint32_t otp); +-bool bsec_write_sp_lock(uint32_t otp, uint32_t value); +-bool bsec_read_sp_lock(uint32_t otp); +-bool bsec_wr_lock(uint32_t otp); +-uint32_t bsec_otp_lock(uint32_t service, uint32_t value); ++uint32_t bsec_set_sr_lock(uint32_t otp); ++uint32_t bsec_read_sr_lock(uint32_t otp, bool *value); ++uint32_t bsec_set_sw_lock(uint32_t otp); ++uint32_t bsec_read_sw_lock(uint32_t otp, bool *value); ++uint32_t bsec_set_sp_lock(uint32_t otp); ++uint32_t bsec_read_sp_lock(uint32_t otp, bool *value); ++uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value); ++uint32_t bsec_otp_lock(uint32_t service); + +-bool bsec_mode_is_closed_device(void); + uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word); + uint32_t bsec_check_nsec_access_rights(uint32_t otp); + +diff --git a/include/drivers/st/nand.h b/include/drivers/st/nand.h +index f92511d..23d2dd2 100644 +--- a/include/drivers/st/nand.h ++++ b/include/drivers/st/nand.h +@@ -120,8 +120,8 @@ + #define FMC_THIZ 1 + #define FMC_TIO 8000 + #define FMC_TSYNC 3000 +-#define FMC_PCR_TIMING_MASK 0xf +-#define FMC_PMEM_PATT_TIMING_MASK 0xff ++#define FMC_PCR_TIMING_MASK 0xFUL ++#define FMC_PMEM_PATT_TIMING_MASK 0xFFUL + + /* Register: FMC_PCR */ + #define FMC_PCR_TCLR(x) (((x) & 0xf) << 9) +@@ -140,28 +140,28 @@ + #define FMC_PATT_ATTHIZ(x) (((x) & 0xff) << 24) + + /* NAND ONFI Default Value Mode 0 */ +-#define FMC_TADL_MIN 200000 +-#define FMC_TALH_MIN 20000 +-#define FMC_TALS_MIN 50000 +-#define FMC_TAR_MIN 25000 +-#define FMC_TCH_MIN 20000 +-#define FMC_TCLH_MIN 20000 +-#define FMC_TCLR_MIN 20000 +-#define FMC_TCLS_MIN 50000 +-#define FMC_TCOH_MIN 0 +-#define FMC_TCS_MIN 70000 +-#define FMC_TDH_MIN 20000 +-#define FMC_TDS_MIN 40000 +-#define FMC_TRC_MIN 100000 +-#define FMC_TREA_MAX 40000 +-#define FMC_TREH_MIN 30000 +-#define FMC_TRHW_MIN 200000 +-#define FMC_TRP_MIN 50000 +-#define FMC_TWB_MAX 200000 +-#define FMC_TWC_MIN 100000 +-#define FMC_TWH_MIN 30000 +-#define FMC_TWHR_MIN 120000 +-#define FMC_TWP_MIN 50000 ++#define FMC_TADL_MIN 400000UL ++#define FMC_TALH_MIN 20000UL ++#define FMC_TALS_MIN 50000UL ++#define FMC_TAR_MIN 25000UL ++#define FMC_TCH_MIN 20000UL ++#define FMC_TCLH_MIN 20000UL ++#define FMC_TCLR_MIN 20000UL ++#define FMC_TCLS_MIN 50000UL ++#define FMC_TCOH_MIN 0UL ++#define FMC_TCS_MIN 70000UL ++#define FMC_TDH_MIN 20000UL ++#define FMC_TDS_MIN 40000UL ++#define FMC_TRC_MIN 100000UL ++#define FMC_TREA_MAX 40000UL ++#define FMC_TREH_MIN 30000UL ++#define FMC_TRHW_MIN 200000UL ++#define FMC_TRP_MIN 50000UL ++#define FMC_TWB_MAX 200000UL ++#define FMC_TWC_MIN 100000UL ++#define FMC_TWH_MIN 30000UL ++#define FMC_TWHR_MIN 120000UL ++#define FMC_TWP_MIN 50000UL + + + #define FMC_EBP2_MASK 16 +diff --git a/include/drivers/st/stm32_iwdg.h b/include/drivers/st/stm32_iwdg.h +index b6d4769..06ad9d5 100644 +--- a/include/drivers/st/stm32_iwdg.h ++++ b/include/drivers/st/stm32_iwdg.h +@@ -10,8 +10,8 @@ + #include + + #define IWDG_HW_ENABLED BIT(0) +-#define IWDG_ENABLE_ON_STOP BIT(1) +-#define IWDG_ENABLE_ON_STANDBY BIT(2) ++#define IWDG_DISABLE_ON_STOP BIT(1) ++#define IWDG_DISABLE_ON_STANDBY BIT(2) + + int stm32_iwdg_init(void); + void stm32_iwdg_refresh(uint32_t instance); +diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h +index b172659..7fa9c5d 100644 +--- a/include/drivers/st/stm32_sdmmc2.h ++++ b/include/drivers/st/stm32_sdmmc2.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -21,6 +21,7 @@ struct stm32_sdmmc2_params { + unsigned int dirpol; + unsigned int clock_id; + unsigned int reset_id; ++ unsigned int max_freq; + bool use_dma; + }; + +diff --git a/include/drivers/st/stm32mp1_calib.h b/include/drivers/st/stm32mp1_calib.h +new file mode 100644 +index 0000000..ef69cb4 +--- /dev/null ++++ b/include/drivers/st/stm32mp1_calib.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP1_CALIB_H ++#define STM32MP1_CALIB_H ++ ++#include ++#include ++ ++bool stm32mp1_calib_get_wakeup(void); ++void stm32mp1_calib_set_wakeup(bool state); ++void stm32mp1_calib_it_handler(uint32_t id); ++int stm32mp1_calib_start_hsi_cal(void); ++int stm32mp1_calib_start_csi_cal(void); ++void stm32mp1_calib_init(void); ++ ++#endif /* STM32MP1_CLK_H */ +diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h +index 0c8583a..4f6930b 100644 +--- a/include/drivers/st/stm32mp1_clk.h ++++ b/include/drivers/st/stm32mp1_clk.h +@@ -56,18 +56,11 @@ void stm32mp1_clk_rcc_regs_lock(void); + void stm32mp1_clk_rcc_regs_unlock(void); + + unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit); +- + #if defined(IMAGE_BL32) +-bool stm32mp1_rcc_get_wakeup(void); +-void stm32mp1_rcc_set_wakeup(bool state); +-void stm32mp1_rcc_it_handler(uint32_t id); +-int stm32mp1_rcc_start_hsi_cal(void); +-int stm32mp1_rcc_start_csi_cal(void); +-void stm32mp1_cal_init(void); ++void stm32mp1_clk_mpu_suspend(void); ++void stm32mp1_clk_mpu_resume(void); + #endif + +-void stm32mp1_rcc_init_late(void); +- + void stm32mp1_register_clock_parents_secure(unsigned long id); + + void stm32mp1_update_earlyboot_clocks_state(void); +diff --git a/include/drivers/st/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h +index 1a22824..9753d7c 100644 +--- a/include/drivers/st/stm32mp1_pwr.h ++++ b/include/drivers/st/stm32mp1_pwr.h +@@ -26,6 +26,8 @@ + + #define PWR_CR2_BREN BIT(0) + #define PWR_CR2_RREN BIT(1) ++#define PWR_CR2_BRRDY BIT(16) ++#define PWR_CR2_RRRDY BIT(17) + + #define PWR_CR3_VBE BIT(8) + #define PWR_CR3_VBRS BIT(9) +diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h +index 7e1b337..903a0d3 100644 +--- a/include/drivers/st/stm32mp1_rcc.h ++++ b/include/drivers/st/stm32mp1_rcc.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -387,7 +387,8 @@ + #define RCC_HSICFGR_HSITRIM_SHIFT 8 + #define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) + #define RCC_HSICFGR_HSICAL_SHIFT 16 +-#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) ++#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16) ++#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25) + + /* Fields of RCC_CSICFGR register */ + #define RCC_CSICFGR_CSITRIM_SHIFT 8 +@@ -470,6 +471,9 @@ + #define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) + #define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) + ++/* Values of RCC_AHB6RSTSETR register */ ++#define RCC_AHB6RSTSETR_GPURST BIT(5) ++ + /* Values of RCC_MP_IWDGFZSETR register */ + #define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) + #define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) +@@ -477,4 +481,82 @@ + /* Values of RCC_PWRLPDLYCR register */ + #define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) + ++/* RCC_I2C46CKSELR register fields */ ++#define RCC_I2C46CKSELR_I2C46SRC_MASK GENMASK(2, 0) ++#define RCC_I2C46CKSELR_I2C46SRC_SHIFT 0 ++ ++/* RCC_SPI6CKSELR register fields */ ++#define RCC_SPI6CKSELR_SPI6SRC_MASK GENMASK(2, 0) ++#define RCC_SPI6CKSELR_SPI6SRC_SHIFT 0 ++ ++/* RCC_UART1CKSELR register fields */ ++#define RCC_UART1CKSELR_UART1SRC_MASK GENMASK(2, 0) ++#define RCC_UART1CKSELR_UART1SRC_SHIFT 0 ++ ++/* RCC_RNG1CKSELR register fields */ ++#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) ++#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 ++ ++/* RCC_STGENCKSELR register fields */ ++#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) ++#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 ++ ++/* RCC_I2C12CKSELR register fields */ ++#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) ++#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 ++ ++/* RCC_I2C35CKSELR register fields */ ++#define RCC_I2C35CKSELR_I2C35SRC_MASK GENMASK(2, 0) ++#define RCC_I2C35CKSELR_I2C35SRC_SHIFT 0 ++ ++/* RCC_UART6CKSELR register fields */ ++#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) ++#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 ++ ++/* RCC_UART24CKSELR register fields */ ++#define RCC_UART24CKSELR_UART24SRC_MASK GENMASK(2, 0) ++#define RCC_UART24CKSELR_UART24SRC_SHIFT 0 ++ ++/* RCC_UART35CKSELR register fields */ ++#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) ++#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 ++ ++/* RCC_UART78CKSELR register fields */ ++#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) ++#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 ++ ++/* RCC_SDMMC12CKSELR register fields */ ++#define RCC_SDMMC12CKSELR_SDMMC12SRC_MASK GENMASK(2, 0) ++#define RCC_SDMMC12CKSELR_SDMMC12SRC_SHIFT 0 ++ ++/* RCC_SDMMC3CKSELR register fields */ ++#define RCC_SDMMC3CKSELR_SDMMC3SRC_MASK GENMASK(2, 0) ++#define RCC_SDMMC3CKSELR_SDMMC3SRC_SHIFT 0 ++ ++/* RCC_ETHCKSELR register fields */ ++#define RCC_ETHCKSELR_ETHSRC_MASK GENMASK(1, 0) ++#define RCC_ETHCKSELR_ETHSRC_SHIFT 0 ++ ++/* RCC_QSPICKSELR register fields */ ++#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) ++#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 ++ ++/* RCC_FMCCKSELR register fields */ ++#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) ++#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 ++ ++/* RCC_ASSCKSELR register fields */ ++#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) ++#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 ++ ++/* RCC_MSSCKSELR register fields */ ++#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(2, 0) ++#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 ++ ++/* RCC_USBCKSELR register fields */ ++#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) ++#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 ++#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) ++#define RCC_USBCKSELR_USBOSRC_SHIFT 4 ++ + #endif /* STM32MP1_RCC_H */ +diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h +index aa34b9c..f3ded20 100644 +--- a/include/lib/aarch32/arch.h ++++ b/include/lib/aarch32/arch.h +@@ -460,8 +460,9 @@ + #define HSTR p15, 4, c1, c1, 3 + #define CNTHCTL p15, 4, c14, c1, 0 + #define CNTKCTL p15, 0, c14, c1, 0 +-#define CNTPTVAL p15, 0, c14, c2, 0 +-#define CNTPCTL p15, 0, c14, c2, 1 ++#define CNTP_TVAL p15, 0, c14, c2, 0 ++#define CNTP_CTL p15, 0, c14, c2, 1 ++#define CNTV_CTL p15, 0, c14, c3, 1 + #define VPIDR p15, 4, c0, c0, 0 + #define VMPIDR p15, 4, c0, c0, 5 + #define ISR p15, 0, c12, c1, 0 +diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h +index e48123c..9d56fc5 100644 +--- a/include/lib/aarch32/arch_helpers.h ++++ b/include/lib/aarch32/arch_helpers.h +@@ -261,8 +261,9 @@ DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64) + DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64) + DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR) + DEFINE_COPROCR_RW_FUNCS(hstr, HSTR) +-DEFINE_COPROCR_RW_FUNCS(cntptval, CNTPTVAL) +-DEFINE_COPROCR_RW_FUNCS(cntpctl, CNTPCTL) ++DEFINE_COPROCR_RW_FUNCS(cntp_tval, CNTP_TVAL) ++DEFINE_COPROCR_RW_FUNCS(cntp_ctl, CNTP_CTL) ++DEFINE_COPROCR_RW_FUNCS(cntv_ctl, CNTV_CTL) + + DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE) + DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE) +diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c +index 263c3ba..d483c18 100644 +--- a/plat/st/common/bl2_io_storage.c ++++ b/plat/st/common/bl2_io_storage.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -159,7 +159,7 @@ enum { + IMG_IDX_NUM + }; + +-static struct stm32image_device_info stm32image_dev_info_spec = { ++static struct stm32image_device_info stm32image_dev_info_spec __unused = { + .lba_size = MMC_BLOCK_SIZE, + .part_info[IMG_IDX_BL33] = { + .name = BL33_IMAGE_NAME, +@@ -186,7 +186,7 @@ static io_block_spec_t stm32image_block_spec = { + .length = 0, + }; + +-static const io_dev_connector_t *stm32image_dev_con; ++static const io_dev_connector_t *stm32image_dev_con __unused; + + static int open_dummy(const uintptr_t spec); + static int open_image(const uintptr_t spec); +@@ -305,7 +305,7 @@ static void print_boot_device(boot_api_context_t *boot_context) + } + } + +-#if STM32MP_EMMC || STM32MP_SDMMC ++#if STM32MP_SDMMC + static void print_bootrom_sd_status(boot_api_context_t *boot_context) + { + if (boot_context->sd_err_internal_timeout_cnt != 0U) { +@@ -338,7 +338,9 @@ static void print_bootrom_sd_status(boot_api_context_t *boot_context) + boot_context->sd_overall_retry_cnt); + } + } ++#endif + ++#if STM32MP_EMMC + static void print_bootrom_emmc_status(boot_api_context_t *boot_context) + { + INFO("BootROM: %d (0x%x) bytes copied from eMMC\n", +@@ -399,342 +401,344 @@ static void print_bootrom_emmc_status(boot_api_context_t *boot_context) + } + #endif + +- +-void stm32mp_io_setup(void) ++#if STM32MP_EMMC || STM32MP_SDMMC ++static void boot_mmc(enum mmc_device_type mmc_dev_type, ++ uint16_t boot_interface_instance) + { + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; +-#if STM32MP_UART_PROGRAMMER +- uintptr_t uart_addr; +-#endif +-#if STM32MP_SDMMC || STM32MP_EMMC + struct stm32_sdmmc2_params params; + struct mmc_device_info device_info; +- uintptr_t mmc_default_instance; + const partition_entry_t *entry; +-#endif +-#ifdef STM32MP_USB +- struct usb_ctx *usb_context; +-#endif +- boot_api_context_t *boot_context = +- (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + +- print_boot_device(boot_context); ++ zeromem(&device_info, sizeof(struct mmc_device_info)); ++ zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); + +- if ((boot_context->boot_partition_used_toboot == 1U) || +- (boot_context->boot_partition_used_toboot == 2U)) { +- INFO("Boot used partition fsbl%d\n", +- boot_context->boot_partition_used_toboot); +- } ++ device_info.mmc_dev_type = mmc_dev_type; + +- io_result = register_io_dev_dummy(&dummy_dev_con); +- assert(io_result == 0); ++ switch (boot_interface_instance) { ++ case 1: ++ params.reg_base = STM32MP_SDMMC1_BASE; ++ break; ++ case 2: ++ params.reg_base = STM32MP_SDMMC2_BASE; ++ break; ++ case 3: ++ params.reg_base = STM32MP_SDMMC3_BASE; ++ break; ++ default: ++ WARN("SDMMC instance not found, using default\n"); ++ if (mmc_dev_type == MMC_IS_SD) { ++ params.reg_base = STM32MP_SDMMC1_BASE; ++ } else { ++ params.reg_base = STM32MP_SDMMC2_BASE; ++ } ++ break; ++ } + +- io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, +- &dummy_dev_handle); +- assert(io_result == 0); ++ params.device_info = &device_info; ++ if (stm32_sdmmc2_mmc_init(¶ms) != 0) { ++ ERROR("SDMMC%u init failed\n", boot_interface_instance); ++ panic(); ++ } + +- switch (boot_context->boot_interface_selected) { +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: +- dmbsy(); ++ /* Open MMC as a block device to read GPT table */ ++ io_result = register_io_dev_block(&mmc_dev_con); ++ if (io_result != 0) { ++ panic(); ++ } + +-#if STM32MP_EMMC || STM32MP_SDMMC +- memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params)); ++ io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec, ++ &storage_dev_handle); ++ assert(io_result == 0); + +- if (boot_context->boot_interface_selected == +- BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) { +- device_info.mmc_dev_type = MMC_IS_EMMC; +- print_bootrom_emmc_status(boot_context); +-#if STM32MP_EMMC +- mmc_default_instance = STM32MP_SDMMC2_BASE; +-#else +- ERROR("MMC driver is not enabled\n"); +- panic(); +-#endif +- } else { +- device_info.mmc_dev_type = MMC_IS_SD; +- print_bootrom_sd_status(boot_context); +-#if STM32MP_SDMMC +- mmc_default_instance = STM32MP_SDMMC1_BASE; +-#else +- ERROR("MMC driver is not enabled\n"); +- panic(); +-#endif +- } ++ partition_init(GPT_IMAGE_ID); + +- switch (boot_context->boot_interface_instance) { +- case 1: +- params.reg_base = STM32MP_SDMMC1_BASE; +- break; +- case 2: +- params.reg_base = STM32MP_SDMMC2_BASE; +- break; +- case 3: +- params.reg_base = STM32MP_SDMMC3_BASE; +- break; +- default: +- WARN("SDMMC instance not found, using default\n"); +- params.reg_base = mmc_default_instance; +- break; +- } ++ io_result = io_dev_close(storage_dev_handle); ++ assert(io_result == 0); + +- params.device_info = &device_info; +- if (stm32_sdmmc2_mmc_init(¶ms) != 0) { +- ERROR("SDMMC%u init failed\n", +- boot_context->boot_interface_instance); +- panic(); +- } ++ stm32image_dev_info_spec.device_size = ++ stm32_sdmmc2_mmc_get_device_size(); + +- /* Open MMC as a block device to read GPT table */ +- io_result = register_io_dev_block(&mmc_dev_con); +- if (io_result != 0) { ++ for (idx = 0U; idx < IMG_IDX_NUM; idx++) { ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ entry = get_partition_entry(part->name); ++ if (entry == NULL) { ++ ERROR("Partition %s not found\n", part->name); + panic(); + } + +- io_result = io_dev_open(mmc_dev_con, +- (uintptr_t)&mmc_block_dev_spec, +- &storage_dev_handle); +- assert(io_result == 0); +- +- partition_init(GPT_IMAGE_ID); +- +- io_result = io_dev_close(storage_dev_handle); +- assert(io_result == 0); ++ part->part_offset = entry->start; ++ part->bkp_offset = 0U; ++ } + +- stm32image_dev_info_spec.device_size = +- stm32_sdmmc2_mmc_get_device_size(); ++ /* ++ * Re-open MMC with io_mmc, for better perfs compared to ++ * io_block. ++ */ ++ io_result = register_io_dev_mmc(&mmc_dev_con); ++ assert(io_result == 0); + +- for (idx = 0U; idx < IMG_IDX_NUM; idx++) { +- part = &stm32image_dev_info_spec.part_info[idx]; +- entry = get_partition_entry(part->name); +- if (entry == NULL) { +- ERROR("Partition %s not found\n", +- part->name); +- panic(); +- } ++ io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle); ++ assert(io_result == 0); + +- part->part_offset = entry->start; +- part->bkp_offset = 0U; +- } ++ io_result = register_io_dev_stm32image(&stm32image_dev_con); ++ assert(io_result == 0); + +- /* +- * Re-open MMC with io_mmc, for better perfs compared to +- * io_block. +- */ +- io_result = register_io_dev_mmc(&mmc_dev_con); +- assert(io_result == 0); +- +- io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle); +- assert(io_result == 0); +- +- io_result = register_io_dev_stm32image(&stm32image_dev_con); +- assert(io_result == 0); +- +- io_result = io_dev_open(stm32image_dev_con, +- (uintptr_t)&stm32image_dev_info_spec, +- &image_dev_handle); +- assert(io_result == 0); +-#else /* STM32MP_EMMC || STM32MP_SDMMC */ +- ERROR("EMMC or SDMMC driver not enabled\n"); +- panic(); +-#endif /* STM32MP_EMMC || STM32MP_SDMMC */ +- break; ++ io_result = io_dev_open(stm32image_dev_con, ++ (uintptr_t)&stm32image_dev_info_spec, ++ &image_dev_handle); ++ assert(io_result == 0); ++} ++#endif + + #if STM32MP1_QSPI_NOR +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: +- dmbsy(); ++static void boot_qspi_nor(boot_api_context_t *boot_context) ++{ ++ int io_result __unused; ++ uint8_t idx; ++ struct stm32image_part_info *part; + +- io_result = register_io_dev_qspi(&qspi_dev_con); ++ io_result = register_io_dev_qspi(&qspi_dev_con); ++ assert(io_result == 0); + +- assert(io_result == 0); +- switch (boot_context->boot_interface_instance) { +- case 1: +- qspi_dev_spec.instance = +- (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE; +- break; +- default: +- WARN("NOR instance not found, using default\n"); +- qspi_dev_spec.instance = +- (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE; +- break; +- } +- qspi_dev_spec.is_dual = boot_context->nor_isdual; ++ if (boot_context->boot_interface_instance != 1U) { ++ WARN("NOR instance not found, using default\n"); ++ } + +- /* Open connections to devices and cache the handles */ +- io_result = io_dev_open(qspi_dev_con, +- (uintptr_t)&qspi_dev_spec, +- &storage_dev_handle); +- assert(io_result == 0); ++ qspi_dev_spec.instance = (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE; ++ qspi_dev_spec.is_dual = boot_context->nor_isdual; + +- stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE; +- stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_SIZE; ++ /* Open connections to devices */ ++ io_result = io_dev_open(qspi_dev_con, ++ (uintptr_t)&qspi_dev_spec, ++ &storage_dev_handle); ++ assert(io_result == 0); + +- idx = IMG_IDX_BL33; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NOR_BL33_OFFSET; +- part->bkp_offset = QSPI_NOR_BLK_SIZE; ++ stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE; ++ stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_SIZE; + +-#ifdef AARCH32_SP_OPTEE +- idx = IMG_IDX_OPTEE_HEADER; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NOR_TEEH_OFFSET; +- part->bkp_offset = QSPI_NOR_BLK_SIZE; +- +- idx = IMG_IDX_OPTEE_PAGED; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NOR_TEED_OFFSET; +- part->bkp_offset = QSPI_NOR_BLK_SIZE; ++ idx = IMG_IDX_BL33; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_BL33_OFFSET; ++ part->bkp_offset = QSPI_NOR_BLK_SIZE; + +- idx = IMG_IDX_OPTEE_PAGER; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NOR_TEEX_OFFSET; +- part->bkp_offset = QSPI_NOR_BLK_SIZE; ++#ifdef AARCH32_SP_OPTEE ++ idx = IMG_IDX_OPTEE_HEADER; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_TEEH_OFFSET; ++ part->bkp_offset = QSPI_NOR_BLK_SIZE; ++ ++ idx = IMG_IDX_OPTEE_PAGED; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_TEED_OFFSET; ++ part->bkp_offset = QSPI_NOR_BLK_SIZE; ++ ++ idx = IMG_IDX_OPTEE_PAGER; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_TEEX_OFFSET; ++ part->bkp_offset = QSPI_NOR_BLK_SIZE; + #endif + +- io_result = register_io_dev_stm32image(&stm32image_dev_con); +- assert(io_result == 0); ++ io_result = register_io_dev_stm32image(&stm32image_dev_con); ++ assert(io_result == 0); + +- io_result = io_dev_open(stm32image_dev_con, +- (uintptr_t)&stm32image_dev_info_spec, +- &image_dev_handle); +- assert(io_result == 0); +- break; ++ io_result = io_dev_open(stm32image_dev_con, ++ (uintptr_t)&stm32image_dev_info_spec, ++ &image_dev_handle); ++ assert(io_result == 0); ++} + #endif + +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: +- + #if STM32MP_FMC_NAND +- dmbsy(); +- +- /* Register the IO devices on this platform */ +- io_result = register_io_dev_nand(&nand_dev_con); +- assert(io_result == 0); +- +- nand_dev_spec.Instance = (FMC_TypeDef *)STM32MP_FMC_BASE; +- nand_dev_spec.Info.PageSize = boot_context->nand_page_size; +- nand_dev_spec.Info.BlockSize = boot_context->nand_block_size; +- nand_dev_spec.Info.BlockNb = boot_context->nand_block_nb; +- nand_dev_spec.Info.BusWidth = boot_context->nand_data_width; +- nand_dev_spec.Info.ECCcorrectability = +- boot_context->nand_ecc_bits; +- +- /* Open connections to devices and cache the handles */ +- io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, +- &storage_dev_handle); +- assert(io_result == 0); +- +- stm32image_dev_info_spec.device_size = +- nand_dev_spec.Info.PageSize * +- nand_dev_spec.Info.BlockSize * +- nand_dev_spec.Info.BlockNb; +- stm32image_dev_info_spec.lba_size = BCH_PAGE_SECTOR; +- +- idx = IMG_IDX_BL33; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NAND_BL33_OFFSET; +- part->bkp_offset = nand_dev_spec.Info.PageSize * +- nand_dev_spec.Info.BlockSize; ++static void boot_fmc_nand(boot_api_context_t *boot_context) ++{ ++ int io_result __unused; ++ uint8_t idx; ++ struct stm32image_part_info *part; + +-#ifdef AARCH32_SP_OPTEE +- idx = IMG_IDX_OPTEE_HEADER; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NAND_TEEH_OFFSET; +- part->bkp_offset = nand_dev_spec.Info.PageSize * +- nand_dev_spec.Info.BlockSize; ++ /* Register the IO devices on this platform */ ++ io_result = register_io_dev_nand(&nand_dev_con); ++ assert(io_result == 0); + +- idx = IMG_IDX_OPTEE_PAGED; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NAND_TEED_OFFSET; +- part->bkp_offset = nand_dev_spec.Info.PageSize * +- nand_dev_spec.Info.BlockSize; ++ nand_dev_spec.Instance = (FMC_TypeDef *)STM32MP_FMC_BASE; ++ nand_dev_spec.Info.PageSize = boot_context->nand_page_size; ++ nand_dev_spec.Info.BlockSize = boot_context->nand_block_size; ++ nand_dev_spec.Info.BlockNb = boot_context->nand_block_nb; ++ nand_dev_spec.Info.BusWidth = boot_context->nand_data_width; ++ nand_dev_spec.Info.ECCcorrectability = ++ boot_context->nand_ecc_bits; ++ ++ /* Open connections to devices */ ++ io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, ++ &storage_dev_handle); ++ assert(io_result == 0); + +- idx = IMG_IDX_OPTEE_PAGER; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NAND_TEEX_OFFSET; +- part->bkp_offset = nand_dev_spec.Info.PageSize * +- nand_dev_spec.Info.BlockSize; ++ stm32image_dev_info_spec.device_size = ++ nand_dev_spec.Info.PageSize * ++ nand_dev_spec.Info.BlockSize * ++ nand_dev_spec.Info.BlockNb; ++ stm32image_dev_info_spec.lba_size = BCH_PAGE_SECTOR; ++ ++ idx = IMG_IDX_BL33; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_BL33_OFFSET; ++ part->bkp_offset = nand_dev_spec.Info.PageSize * ++ nand_dev_spec.Info.BlockSize; ++ ++#ifdef AARCH32_SP_OPTEE ++ idx = IMG_IDX_OPTEE_HEADER; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_TEEH_OFFSET; ++ part->bkp_offset = nand_dev_spec.Info.PageSize * ++ nand_dev_spec.Info.BlockSize; ++ ++ idx = IMG_IDX_OPTEE_PAGED; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_TEED_OFFSET; ++ part->bkp_offset = nand_dev_spec.Info.PageSize * ++ nand_dev_spec.Info.BlockSize; ++ ++ idx = IMG_IDX_OPTEE_PAGER; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_TEEX_OFFSET; ++ part->bkp_offset = nand_dev_spec.Info.PageSize * ++ nand_dev_spec.Info.BlockSize; + #endif + +- io_result = register_io_dev_stm32image(&stm32image_dev_con); +- assert(io_result == 0); ++ io_result = register_io_dev_stm32image(&stm32image_dev_con); ++ assert(io_result == 0); + +- io_result = io_dev_open(stm32image_dev_con, +- (uintptr_t)&stm32image_dev_info_spec, +- &image_dev_handle); +- assert(io_result == 0); +-#else +- ERROR("FMC NAND driver is not enabled\n"); +- panic(); ++ io_result = io_dev_open(stm32image_dev_con, ++ (uintptr_t)&stm32image_dev_info_spec, ++ &image_dev_handle); ++ assert(io_result == 0); ++} + #endif +- break; + + #if STM32MP_UART_PROGRAMMER +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++static void flash_uart(uint16_t boot_interface_instance) ++{ ++ int io_result __unused; ++ uintptr_t uart_addr; + +- /* Register the IO devices on this platform */ +- io_result = register_io_dev_uart(&uart_dev_con); +- assert(io_result == 0); ++ /* Register the IO devices on this platform */ ++ io_result = register_io_dev_uart(&uart_dev_con); ++ assert(io_result == 0); + +- uart_programmer.Init.WordLength = UART_WORDLENGTH_9B; +- uart_programmer.Init.Parity = UART_PARITY_EVEN; +- uart_addr = +- get_uart_address(boot_context->boot_interface_instance); ++ uart_programmer.Init.WordLength = UART_WORDLENGTH_9B; ++ uart_programmer.Init.Parity = UART_PARITY_EVEN; ++ uart_addr = get_uart_address(boot_interface_instance); + +- if (uart_addr) { +- uart_programmer.Instance = (USART_TypeDef *)uart_addr; +- } else { +- WARN("UART instance not found, using default\n"); +- uart_programmer.Instance = (USART_TypeDef *)USART2_BASE; +- } ++ if (uart_addr != 0U) { ++ uart_programmer.Instance = (USART_TypeDef *)uart_addr; ++ } else { ++ WARN("UART instance not found, using default\n"); ++ uart_programmer.Instance = (USART_TypeDef *)USART2_BASE; ++ } + +- /* Open connections to devices and cache the handles */ +- io_result = io_dev_open(uart_dev_con, +- (uintptr_t)&uart_programmer, +- &image_dev_handle); +- assert(!io_result); +- break; ++ /* Open connections to devices */ ++ io_result = io_dev_open(uart_dev_con, (uintptr_t)&uart_programmer, ++ &image_dev_handle); ++ assert(!io_result); ++} + #endif + + #ifdef STM32MP_USB +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: +- usb_context = (struct usb_ctx *)boot_context->usb_context; ++static void flash_usb(struct usb_ctx *usb_context) ++{ ++ int io_result __unused; + +- pcd_handle.in_ep[0].maxpacket = 0x40; +- pcd_handle.out_ep[0].maxpacket = 0x40; ++ pcd_handle.in_ep[0].maxpacket = 0x40; ++ pcd_handle.out_ep[0].maxpacket = 0x40; + +- pcd_handle.state = HAL_PCD_STATE_READY; ++ pcd_handle.state = HAL_PCD_STATE_READY; + +- usb_core_handle.data = &pcd_handle; ++ usb_core_handle.data = &pcd_handle; + +- usb_dwc2_init_driver(&usb_core_handle, +- (uint32_t *)USB_OTG_BASE); ++ usb_dwc2_init_driver(&usb_core_handle, ++ (uint32_t *)USB_OTG_BASE); + +- usb_dfu_register_callback(&usb_core_handle); ++ usb_dfu_register_callback(&usb_core_handle); + +- stm32mp_usb_init_desc(&usb_core_handle); ++ stm32mp_usb_init_desc(&usb_core_handle); + +- usb_core_handle.ep_in[0].maxpacket = 0x40; +- usb_core_handle.ep_out[0].maxpacket = 0x40; ++ usb_core_handle.ep_in[0].maxpacket = 0x40; ++ usb_core_handle.ep_out[0].maxpacket = 0x40; + +- usb_core_handle.ep0_state = +- usb_context->pusbd_device_ctx->ep0_state; +- usb_core_handle.dev_state = USBD_STATE_CONFIGURED; ++ usb_core_handle.ep0_state = ++ usb_context->pusbd_device_ctx->ep0_state; ++ usb_core_handle.dev_state = USBD_STATE_CONFIGURED; + +- usb_core_handle.class_data = &usb_dfu_handle; +- usb_dfu_handle.dev_state = DFU_STATE_IDLE; ++ usb_core_handle.class_data = &usb_dfu_handle; ++ usb_dfu_handle.dev_state = DFU_STATE_IDLE; + +- /* Register the IO devices on this platform */ +- io_result = register_io_dev_usb(&usb_dev_con); +- assert(io_result == 0); ++ /* Register the IO devices on this platform */ ++ io_result = register_io_dev_usb(&usb_dev_con); ++ assert(io_result == 0); + +- /* Open connections to devices and cache the handles */ +- io_result = io_dev_open(usb_dev_con, +- (uintptr_t)&usb_core_handle, +- &image_dev_handle); ++ /* Open connections to devices */ ++ io_result = io_dev_open(usb_dev_con, ++ (uintptr_t)&usb_core_handle, ++ &image_dev_handle); + +- assert(io_result == 0); ++ assert(io_result == 0); ++} ++#endif ++ ++void stm32mp_io_setup(void) ++{ ++ int io_result __unused; ++ boot_api_context_t *boot_context = ++ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); ++ ++ print_boot_device(boot_context); ++ ++ if ((boot_context->boot_partition_used_toboot == 1U) || ++ (boot_context->boot_partition_used_toboot == 2U)) { ++ INFO("Boot used partition fsbl%d\n", ++ boot_context->boot_partition_used_toboot); ++ } ++ ++ io_result = register_io_dev_dummy(&dummy_dev_con); ++ assert(io_result == 0); ++ ++ io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, ++ &dummy_dev_handle); ++ assert(io_result == 0); ++ ++ switch (boot_context->boot_interface_selected) { ++#if STM32MP_SDMMC ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: ++ print_bootrom_sd_status(boot_context); ++ boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); ++ break; ++#endif ++#if STM32MP_EMMC ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: ++ print_bootrom_emmc_status(boot_context); ++ boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); ++ break; ++#endif ++#if STM32MP1_QSPI_NOR ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: ++ boot_qspi_nor(boot_context); ++ break; ++#endif ++#if STM32MP_FMC_NAND ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: ++ boot_fmc_nand(boot_context); ++ break; ++#endif ++#if STM32MP_UART_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++ flash_uart(boot_context->boot_interface_instance); ++ break; ++#endif ++#ifdef STM32MP_USB ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: ++ flash_usb((struct usb_ctx *)boot_context->usb_context); + break; + #endif + #ifdef STM32MP1_QSPI_NAND +diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h +index 70f8202..b5a2bf9 100644 +--- a/plat/st/common/include/stm32mp_auth.h ++++ b/plat/st/common/include/stm32mp_auth.h +@@ -9,6 +9,14 @@ + + #include + ++struct auth_ops { ++ uint32_t (*check_key)(uint8_t *p_pub_key_in, ++ uint8_t *p_pub_key_out); ++ uint32_t (*verify_signature)(uint8_t *p_hash_in, uint8_t *p_pub_key_in, ++ uint8_t *p_signature, uint32_t ecc_algo); ++}; ++ ++void stm32mp_init_auth(struct auth_ops *init_ptr); + int check_header(boot_api_image_header_t *header, uintptr_t buffer); + int check_authentication(boot_api_image_header_t *header, uintptr_t buffer); + +diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c +index 773c95e..aa784cf 100644 +--- a/plat/st/common/stm32mp_auth.c ++++ b/plat/st/common/stm32mp_auth.c +@@ -12,6 +12,19 @@ + #include + #include + ++static const struct auth_ops *stm32mp_auth_ops; ++ ++void stm32mp_init_auth(struct auth_ops *init_ptr) ++{ ++ if ((init_ptr == NULL) || ++ (init_ptr->check_key == NULL) || ++ (init_ptr->verify_signature == NULL)) { ++ panic(); ++ } ++ ++ stm32mp_auth_ops = init_ptr; ++} ++ + int check_header(boot_api_image_header_t *header, uintptr_t buffer) + { + uint32_t i; +@@ -55,8 +68,6 @@ int check_authentication(boot_api_image_header_t *header, uintptr_t buffer) + uint32_t header_skip_cksum = sizeof(header->magic) + + sizeof(header->image_signature) + + sizeof(header->payload_checksum); +- boot_api_context_t *boot_context = +- (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + + uret = bsec_read_otp(&sec_closed, BOOT_API_OTP_MODE_WORD_NB); + if (uret != 0) { +@@ -74,8 +85,7 @@ int check_authentication(boot_api_image_header_t *header, uintptr_t buffer) + } + + /* Check Public Key */ +- if (boot_context->p_bootrom_ext_service_ecdsa_check_key +- (header->ecc_pubk, NULL) != STD_OK) { ++ if (stm32mp_auth_ops->check_key(header->ecc_pubk, NULL) != STD_OK) { + return -EINVAL; + } + +@@ -110,8 +120,9 @@ int check_authentication(boot_api_image_header_t *header, uintptr_t buffer) + } + + /* Verify signature */ +- if (boot_context->p_bootrom_ext_service_ecdsa_verify_signature +- (image_hash, header->ecc_pubk, header->image_signature, ++ if (stm32mp_auth_ops->verify_signature ++ (image_hash, header->ecc_pubk, ++ header->image_signature, + header->ecc_algo_type) != STD_OK) { + return -EINVAL; + } +diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c +index 48529cb..2f9951b 100644 +--- a/plat/st/common/stm32mp_dt.c ++++ b/plat/st/common/stm32mp_dt.c +@@ -106,12 +106,9 @@ int fdt_get_interrupt(int node, const fdt32_t **array, int *len, bool *extended) + } + break; + +- case DT_SHARED: ++ default: + *array = fdt_getprop(fdt, node, "secure-interrupts", len); + break; +- +- default: +- return -FDT_ERR_NOTFOUND; + } + + if (*array == NULL) { +@@ -429,7 +426,7 @@ uintptr_t dt_get_pwr_base(void) + ******************************************************************************/ + uint32_t dt_get_pwr_vdd_voltage(void) + { +- int node; ++ int node, pwr_regulators_node; + const fdt32_t *cuint; + + node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); +@@ -438,7 +435,13 @@ uint32_t dt_get_pwr_vdd_voltage(void) + return 0; + } + +- cuint = fdt_getprop(fdt, node, "pwr-supply", NULL); ++ pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators"); ++ if (node < 0) { ++ INFO("%s: Cannot read pwr-regulators node in DT\n", __func__); ++ return 0; ++ } ++ ++ cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL); + if (cuint == NULL) { + return 0; + } +diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c +index cd5d5b3..1a2e2d6 100644 +--- a/plat/st/stm32mp1/bl2_plat_setup.c ++++ b/plat/st/stm32mp1/bl2_plat_setup.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -42,6 +43,7 @@ + + static struct console_stm32 console; + static enum boot_device_e boot_device = BOOT_DEVICE_BOARD; ++static struct auth_ops stm32mp_auth_ops; + + static void print_reset_reason(void) + { +@@ -280,13 +282,17 @@ void bl2_el3_plat_arch_setup(void) + RCC_PWRLPDLYCR_PWRLP_DLY_MASK, + PWRLP_TEMPO_5_HSI); + +- /* Keep retention and backup ram content in standby */ +- mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN); +- mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_RREN); ++ /* Disable retention and backup RAM content after standby */ ++ mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN); + + /* Disable MCKPROT */ + mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); + ++ /* Enable BKP Register protection */ ++ mmio_write_32(TAMP_SMCR, ++ TAMP_BKP_SEC_NUMBER << TAMP_BKP_SEC_WDPROT_SHIFT | ++ TAMP_BKP_SEC_NUMBER << TAMP_BKP_SEC_RWDPROT_SHIFT); ++ + if ((boot_context->boot_action != + BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY) && + (boot_context->boot_action != +@@ -323,6 +329,8 @@ void bl2_el3_plat_arch_setup(void) + panic(); + } + ++ stm32mp1_syscfg_init(); ++ + result = dt_get_stdout_uart_info(&dt_uart_info); + + if ((result <= 0) || +@@ -399,13 +407,18 @@ skip_console_init: + ERROR("Cannot save boot interface\n"); + } + ++ stm32mp_auth_ops.check_key = ++ boot_context->p_bootrom_ext_service_ecdsa_check_key; ++ stm32mp_auth_ops.verify_signature = ++ boot_context->p_bootrom_ext_service_ecdsa_verify_signature; ++ ++ stm32mp_init_auth(&stm32mp_auth_ops); ++ + stm32mp1_arch_security_setup(); + + print_reset_reason(); + + stm32mp_io_setup(); +- +- stm32mp1_syscfg_init(); + } + + #if defined(AARCH32_SP_OPTEE) +diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h +index cc6c9e7..0983575 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_private.h ++++ b/plat/st/stm32mp1/include/stm32mp1_private.h +@@ -18,6 +18,9 @@ enum boot_device_e { + + void configure_mmu(void); + ++void stm32mp_mask_timer(void); ++void __dead2 stm32mp_wait_cpu_reset(void); ++ + void stm32mp1_arch_security_setup(void); + void stm32mp1_security_setup(void); + void stm32mp1_sp_min_security_setup(void); +@@ -34,5 +37,7 @@ void stm32mp1_gic_init(void); + enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode); + + void stm32mp1_syscfg_init(void); ++void stm32mp1_syscfg_enable_io_compensation(void); ++void stm32mp1_syscfg_disable_io_compensation(void); + + #endif /* STM32MP1_PRIVATE_H */ +diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk +index 06594f0..91bb1ca 100644 +--- a/plat/st/stm32mp1/platform.mk ++++ b/plat/st/stm32mp1/platform.mk +@@ -10,6 +10,10 @@ BL2_AT_EL3 := 1 + USE_COHERENT_MEM := 0 + MULTI_CONSOLE_API := 1 + ++# Add specific ST version ++ST_VERSION := r1.5 ++VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} ++ + # Please don't increment this value without good understanding of + # the monotonic counter + STM32_TF_VERSION ?= 0 +@@ -42,6 +46,25 @@ PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1))) + endif + $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + ++STM32MP_BOOT_ONLY ?= 0 ++STM32MP_FLASHLOADER_ONLY ?= 0 ++ ++ifeq (${STM32MP_BOOT_ONLY},1) ++ifeq (${STM32MP_FLASHLOADER_ONLY},1) ++$(error "You cannot choose both STM32MP_BOOT_ONLY and STM32MP_FLASHLOADER_ONLY") ++endif ++STM32MP_BOOT_DEVICES = 1 ++STM32MP_FLASHLOADER = 0 ++endif ++ifeq (${STM32MP_FLASHLOADER_ONLY},1) ++STM32MP_BOOT_DEVICES = 0 ++STM32MP_FLASHLOADER = 1 ++endif ++ ++STM32MP_BOOT_DEVICES ?= 1 ++STM32MP_FLASHLOADER ?= 1 ++ ++ifeq (${STM32MP_BOOT_DEVICES},1) + # Boot devices + STM32MP1_QSPI_NOR := 1 + $(eval $(call add_define,STM32MP1_QSPI_NOR)) +@@ -57,9 +80,15 @@ $(eval $(call add_define,STM32MP1_QSPI_NAND)) + ifeq ($(filter 1,${STM32MP1_QSPI_NOR} ${STM32MP_FMC_NAND} ${STM32MP_EMMC} ${STM32MP_SDMMC}),) + $(error "No boot device driver is enabled") + endif ++endif #STM32MP_BOOT_DEVICES ++ ++ifeq (${STM32MP_FLASHLOADER},1) ++STM32MP_USB := 1 ++$(eval $(call add_define,STM32MP_USB)) + + STM32MP_UART_PROGRAMMER := 1 + $(eval $(call add_define,STM32MP_UART_PROGRAMMER)) ++endif #STM32MP_FLASHLOADER + + PLAT_INCLUDES := -Iinclude/common/tbbr + PLAT_INCLUDES += -Iinclude/drivers/partition +@@ -69,8 +98,6 @@ PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ + + PLAT_INCLUDES += -Iinclude/lib/usb + +-STM32MP_USB := 1 +- + # Device tree + DTB_FILE_NAME ?= stm32mp157c-ev1.dtb + FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) +@@ -114,7 +141,8 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ + plat/st/stm32mp1/stm32mp1_dbgmcu.c \ + plat/st/stm32mp1/stm32mp1_helper.S \ + plat/st/stm32mp1/stm32mp1_security.c \ +- plat/st/stm32mp1/stm32mp1_shared_resources.c ++ plat/st/stm32mp1/stm32mp1_shared_resources.c \ ++ plat/st/stm32mp1/stm32mp1_syscfg.c + + BL2_SOURCES += drivers/io/io_block.c \ + drivers/io/io_dummy.c \ +@@ -123,8 +151,7 @@ BL2_SOURCES += drivers/io/io_block.c \ + drivers/st/io/io_stm32image.c \ + plat/st/common/bl2_io_storage.c \ + plat/st/common/stm32mp_auth.c \ +- plat/st/stm32mp1/bl2_plat_setup.c \ +- plat/st/stm32mp1/stm32mp1_syscfg.c ++ plat/st/stm32mp1/bl2_plat_setup.c + + ifeq (${STM32MP1_QSPI_NOR},1) + BL2_SOURCES += drivers/st/qspi/io_qspi.c +@@ -155,14 +182,12 @@ BL2_SOURCES += common/desc_image_load.c \ + plat/st/stm32mp1/plat_bl2_mem_params_desc.c \ + plat/st/stm32mp1/plat_image_load.c + +-ifneq (${STM32MP_USB},0) ++ifeq (${STM32MP_USB},1) + BL2_SOURCES += drivers/st/io/io_programmer_st_usb.c \ + drivers/st/usb_dwc2/usb_dwc2.c \ + lib/usb/usb_core.c \ + lib/usb/usb_st_dfu.c \ + plat/st/stm32mp1/stm32mp1_usb_desc.c +- +-TF_CFLAGS += -DSTM32MP_USB + endif + + ifeq ($(AARCH32_SP),optee) +diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c +index e4f86a2..b13580d 100644 +--- a/plat/st/stm32mp1/services/bsec_svc.c ++++ b/plat/st/stm32mp1/services/bsec_svc.c +@@ -295,7 +295,8 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, + + value = (exchange->programming_lock[j] >> i) & 1U; + if (value != 0U) { +- if (!bsec_write_sp_lock((32U * j) + i, 1U)) { ++ if (bsec_set_sp_lock((32U * j) + i) != ++ BSEC_OK) { + return BSEC_ERROR; + } + } +@@ -315,7 +316,8 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, + + value = (exchange->shadow_write_lock[j] >> i) & 1U; + if (value != 0U) { +- if (!bsec_write_sw_lock((32U * j) + i, 1U)) { ++ if (bsec_set_sw_lock((32U * j) + i) != ++ BSEC_OK) { + return BSEC_ERROR; + } + } +@@ -335,7 +337,8 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, + + value = (exchange->shadow_read_lock[j] >> i) & 1U; + if (value != 0U) { +- if (!bsec_write_sr_lock((32U * j) + i, 1U)) { ++ if (bsec_set_sr_lock((32U * j) + i) != ++ BSEC_OK) { + return BSEC_ERROR; + } + } +@@ -366,12 +369,9 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, + (uint8_t)(exchange->general_lock & GPLOCK_LOCK_MASK) >> + GPLOCK_LOCK_SHIFT; + +- if (!bsec_mode_is_closed_device()) { +- config_param.upper_otp_lock = +- (uint8_t)(exchange->general_lock & +- UPPER_OTP_LOCK_MASK) >> +- UPPER_OTP_LOCK_SHIFT; +- } ++ config_param.upper_otp_lock = ++ (uint8_t)(exchange->general_lock & UPPER_OTP_LOCK_MASK) >> ++ UPPER_OTP_LOCK_SHIFT; + + ret = bsec_set_config(&config_param); + if (ret != BSEC_OK) { +@@ -388,7 +388,6 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + { + uint32_t result; + uint32_t tmp_data = 0U; +- struct otp_exchange *otp_exch = (struct otp_exchange *)(uintptr_t)x2; + + if ((x1 != STM32_SMC_READ_ALL) && (x1 != STM32_SMC_WRITE_ALL) && + (bsec_check_nsec_access_rights(x2) != BSEC_OK)) { +@@ -413,8 +412,7 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + break; + } + +- *ret_otp_value = (uint32_t)bsec_check_ssp(tmp_data, +- otp_exch->otp_value[x2]); ++ *ret_otp_value = (uint32_t)bsec_check_ssp(tmp_data, x3); + if (*ret_otp_value == (uint32_t)BSEC_SSP_ERROR) { + result = BSEC_OK; + break; +@@ -446,10 +444,11 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + result = bsec_write_otp(tmp_data, x2); + break; + case STM32_SMC_READ_ALL: +- result = bsec_read_all_bsec(otp_exch); ++ result = bsec_read_all_bsec((struct otp_exchange *)x2); + break; + case STM32_SMC_WRITE_ALL: +- result = bsec_write_all_bsec(otp_exch, ret_otp_value); ++ result = bsec_write_all_bsec((struct otp_exchange *)x2, ++ ret_otp_value); + break; + default: + result = BSEC_ERROR; +diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c +index 1df6903..6e8f9d0 100644 +--- a/plat/st/stm32mp1/services/rcc_svc.c ++++ b/plat/st/stm32mp1/services/rcc_svc.c +@@ -457,13 +457,13 @@ uint32_t rcc_cal_scv_handler(uint32_t x1) + + switch (x1) { + case CK_CSI: +- if (stm32mp1_rcc_start_csi_cal() == 0) { ++ if (stm32mp1_calib_start_csi_cal() == 0) { + ret = STM32_SMC_OK; + } + break; + + case CK_HSI: +- if (stm32mp1_rcc_start_hsi_cal() == 0) { ++ if (stm32mp1_calib_start_hsi_cal() == 0) { + ret = STM32_SMC_OK; + } + break; +diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +index 322d389..416b5a2 100644 +--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk ++++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +@@ -7,6 +7,7 @@ + SP_MIN_WITH_SECURE_FIQ := 1 + + BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \ ++ drivers/st/clk/stm32mp1_calib.c \ + drivers/st/etzpc/etzpc.c \ + drivers/st/rng/stm32_rng.c \ + drivers/st/rtc/stm32_rtc.c \ +diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c +index e8dc409..8748b68 100644 +--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c ++++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -68,6 +68,8 @@ static void stm32_sgi1_it_handler(void) + { + uint32_t id; + ++ stm32mp_mask_timer(); ++ + gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_1); + + do { +@@ -80,17 +82,19 @@ static void stm32_sgi1_it_handler(void) + } + } while (id <= MAX_SPI_ID); + ++ stm32mp_wait_cpu_reset(); ++} + +- isb(); +- dsb(); +- +- /* Flush L1/L2 data caches */ +- write_sctlr(read_sctlr() & ~SCTLR_C_BIT); +- dcsw_op_all(DC_OP_CISW); ++static void configure_wakeup_interrupt(void) ++{ ++ int irq_num = fdt_rcc_enable_it("wakeup"); + +- for ( ; ; ) { +- wfi(); ++ if (irq_num < 0) { ++ ERROR("irq_num = %d\n", irq_num); ++ panic(); + } ++ ++ plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO); + } + + /******************************************************************************* +@@ -104,7 +108,7 @@ void sp_min_plat_fiq_handler(uint32_t id) + case ARM_IRQ_SEC_PHY_TIMER: + case STM32MP1_IRQ_MCU_SEV: + case STM32MP1_IRQ_RCC_WAKEUP: +- stm32mp1_rcc_it_handler(id); ++ stm32mp1_calib_it_handler(id); + break; + case STM32MP1_IRQ_TZC400: + tzc400_init(STM32MP1_TZC_BASE); +@@ -232,6 +236,22 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + + bl_params_node_t *bl_params = params_from_bl2->head; + ++ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, ++ BL_CODE_END - BL_CODE_BASE, ++ MT_CODE | MT_SECURE); ++ ++#if SEPARATE_CODE_AND_RODATA ++ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, ++ BL_RO_DATA_LIMIT - BL_RO_DATA_BASE, ++ MT_RO_DATA | MT_SECURE); ++#endif ++ ++ mmap_add_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, ++ dt_get_ddr_size() - STM32MP_DDR_S_SIZE, ++ MT_MEMORY | MT_RW | MT_NS); ++ ++ configure_mmu(); ++ + /* + * Copy BL33 entry point information. + * They are stored in Secure RAM, in BL2's address space. +@@ -319,7 +339,7 @@ void stm32mp1_sp_min_security_setup(void) + } + + if (stm32_timer_init() == 0) { +- stm32mp1_cal_init(); ++ stm32mp1_calib_init(); + } + } + +@@ -328,22 +348,6 @@ void stm32mp1_sp_min_security_setup(void) + ******************************************************************************/ + void sp_min_platform_setup(void) + { +- mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, +- BL_CODE_END - BL_CODE_BASE, +- MT_CODE | MT_SECURE); +- +-#if SEPARATE_CODE_AND_RODATA +- mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, +- BL_RO_DATA_LIMIT - BL_RO_DATA_BASE, +- MT_RO_DATA | MT_SECURE); +-#endif +- +- mmap_add_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, +- dt_get_ddr_size() - STM32MP_DDR_S_SIZE, +- MT_MEMORY | MT_RW | MT_NS); +- +- configure_mmu(); +- + /* Initialize tzc400 after DDR initialization */ + stm32mp1_security_setup(); + +@@ -358,6 +362,8 @@ void sp_min_platform_setup(void) + panic(); + } + ++ configure_wakeup_interrupt(); ++ + stm32mp1_driver_init_late(); + } + +diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h +index a6b1a7b..7d7d773 100644 +--- a/plat/st/stm32mp1/stm32mp1_def.h ++++ b/plat/st/stm32mp1/stm32mp1_def.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -203,9 +204,9 @@ enum ddr_type { + + #define STM32MP_NAND_BL33_OFFSET U(0x00200000) + #ifdef AARCH32_SP_OPTEE +-#define STM32MP_NAND_TEEH_OFFSET U(0x00400000) +-#define STM32MP_NAND_TEED_OFFSET U(0x00480000) +-#define STM32MP_NAND_TEEX_OFFSET U(0x00500000) ++#define STM32MP_NAND_TEEH_OFFSET U(0x00600000) ++#define STM32MP_NAND_TEED_OFFSET U(0x00680000) ++#define STM32MP_NAND_TEEX_OFFSET U(0x00700000) + #endif + + /******************************************************************************* +@@ -374,7 +375,6 @@ enum ddr_type { + #define UID2_OTP U(15) + #define PACKAGE_OTP U(16) + #define HW2_OTP U(18) /* HW watchdog OTP */ +-#define BOARD_OTP U(59) + + /* OTP mask */ + /* DATA0 */ +@@ -393,6 +393,9 @@ enum ddr_type { + #define IWDG_FZ_STOP_POS 5 + #define IWDG_FZ_STANDBY_POS 7 + ++/* HW2 OTP */ ++#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) ++ + /* NAND OTP */ + /* NAND parameter storage flag */ + #define NAND_PARAM_STORED_IN_OTP U(0x80000000) +@@ -447,7 +450,12 @@ enum ddr_type { + #define PLAT_MAX_TAMP_INT U(5) + #define PLAT_MAX_TAMP_EXT U(3) + #define TAMP_BASE U(0x5C00A000) ++#define TAMP_SMCR (TAMP_BASE + U(0x20)) + #define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100)) ++#define TAMP_BKP_SEC_NUMBER U(10) ++#define TAMP_BKP_SEC_WDPROT_SHIFT U(16) ++#define TAMP_BKP_SEC_RWDPROT_SHIFT U(0) ++ + + #if !(defined(__LINKER__) || defined(__ASSEMBLY__)) + static inline uint32_t tamp_bkpr(uint32_t idx) +@@ -523,6 +531,7 @@ static inline uint32_t tamp_bkpr(uint32_t idx) + /******************************************************************************* + * Device Tree defines + ******************************************************************************/ ++#define DT_BSEC_COMPAT "st,stm32mp15-bsec" + #define DT_PWR_COMPAT "st,stm32mp1-pwr" + #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" + #define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg" +diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S +index 1adaaee..afaa1f4 100644 +--- a/plat/st/stm32mp1/stm32mp1_helper.S ++++ b/plat/st/stm32mp1/stm32mp1_helper.S +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -311,15 +311,20 @@ func plat_crash_console_putc + b console_stm32_core_putc + endfunc plat_crash_console_putc + +- /* ----------------------------------------------------- ++ /* ---------------------------------------------------------- + * void plat_panic_handler(void) __dead2; + * Report exception + endless loop. +- * ----------------------------------------------------- ++ * ++ * r6 holds the address where the fault occurred. ++ * Filling lr with this value allows debuggers to reconstruct ++ * the backtrace. ++ * ---------------------------------------------------------- + */ + func plat_panic_handler + mrs r0, cpsr + and r0, #MODE32_MASK + bl plat_report_exception ++ mov lr, r6 + b . + endfunc plat_panic_handler + +@@ -363,8 +368,8 @@ func wfi_svc_int_enable + str r4, [sp, #SMC_CTX_SCR] + cps #MODE32_svc + cpsie af +- isb + dsb ++ isb + wfi + cpsid af + cps #MODE32_mon +diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c +index de9035c..f8b35dd 100644 +--- a/plat/st/stm32mp1/stm32mp1_low_power.c ++++ b/plat/st/stm32mp1/stm32mp1_low_power.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -129,6 +129,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) + uintptr_t pwr_base = stm32mp_pwr_base(); + uintptr_t rcc_base = stm32mp_rcc_base(); + ++ stm32mp1_syscfg_disable_io_compensation(); ++ + dcsw_op_all(DC_OP_CISW); + + stm32_clean_context(); +@@ -141,6 +143,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) + stm32_save_ddr_training_area(); + } + ++ stm32mp1_clk_mpu_suspend(); ++ + if (dt_pmic_status() > 0) { + stm32_apply_pmic_suspend_config(mode); + +@@ -186,7 +190,6 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) + mmio_write_32(bkpr_core1_magic, 0); + + if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { +- + /* + * Save non-secure world entrypoint after standby in Backup + * register +@@ -198,6 +201,14 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) + if (stm32_save_context(zq0cr0_zdata) != 0) { + panic(); + } ++ ++ /* Keep retention and backup RAM content in standby */ ++ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | ++ PWR_CR2_RREN); ++ while ((mmio_read_32(pwr_base + PWR_CR2) & ++ (PWR_CR2_BRRDY | PWR_CR2_RRRDY)) == 0U) { ++ ; ++ } + } + + stm32mp_clk_disable(RTCAPB); +@@ -212,6 +223,7 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) + */ + void stm32_exit_cstop(void) + { ++ uintptr_t pwr_base = stm32mp_pwr_base(); + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (!enter_cstop_done) { +@@ -220,6 +232,8 @@ void stm32_exit_cstop(void) + + enter_cstop_done = false; + ++ stm32mp1_clk_mpu_resume(); ++ + if (ddr_sw_self_refresh_exit() != 0) { + panic(); + } +@@ -236,6 +250,9 @@ void stm32_exit_cstop(void) + dsb(); + isb(); + ++ /* Disable retention and backup RAM content after stop */ ++ mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN); ++ + /* Update STGEN counter with low power mode duration */ + stm32_rtc_get_calendar(¤t_calendar); + +@@ -243,10 +260,17 @@ void stm32_exit_cstop(void) + &sleep_time); + + stm32mp1_stgen_increment(stdby_time_in_ms); ++ ++ stm32mp1_syscfg_enable_io_compensation(); + } + + static void enter_shutdown(void) + { ++ /* Set DDR in Self-refresh before shutting down the platform */ ++ if (ddr_standby_sr_entry(NULL) != 0) { ++ WARN("DDR can't be set in Self-refresh mode\n"); ++ } ++ + if (dt_pmic_status() > 0) { + if (!initialize_pmic_i2c()) { + panic(); +@@ -294,10 +318,10 @@ void stm32_pwr_down_wfi(void) + { + uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; + +- stm32mp1_rcc_set_wakeup(false); ++ stm32mp1_calib_set_wakeup(false); + + while (interrupt == GIC_SPURIOUS_INTERRUPT && +- !stm32mp1_rcc_get_wakeup()) { ++ !stm32mp1_calib_get_wakeup()) { + wfi_svc_int_enable((uintptr_t)&int_stack[0]); + + interrupt = gicv2_acknowledge_interrupt(); +diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c +index 20a2f5c..b95bc3d 100644 +--- a/plat/st/stm32mp1/stm32mp1_pm.c ++++ b/plat/st/stm32mp1/stm32mp1_pm.c +@@ -40,11 +40,12 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) + assert(cpu_state == ARM_LOCAL_STATE_RET); + + /* +- * Enter standby state +- * dsb is good practice before using wfi to enter low power states ++ * Enter standby state. ++ * Synchronize on memory accesses and instruction flow before the WFI ++ * instruction. + */ +- isb(); + dsb(); ++ isb(); + while (interrupt == GIC_SPURIOUS_INTERRUPT) { + wfi(); + +@@ -85,6 +86,9 @@ static int stm32_pwr_domain_on(u_register_t mpidr) + return PSCI_E_INVALID_PARAMS; + } + ++ /* Reset backup register content */ ++ mmio_write_32(bkpr_core1_magic, 0); ++ + /* Need to send additional IT 0 after individual core 1 reset */ + gicv2_raise_sgi(ARM_IRQ_NON_SEC_SGI_0, STM32MP_SECONDARY_CPU); + +@@ -183,9 +187,12 @@ static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t + mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, + RCC_MP_GRSTCSETR_MPUP1RST); + +- /* wfi is required for an auto-reset */ +- isb(); ++ /* ++ * Synchronize on memory accesses and instruction flow before ++ * auto-reset from the WFI instruction. ++ */ + dsb(); ++ isb(); + wfi(); + + /* This shouldn't be reached */ +diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c +index c1f4c82..aae537f 100644 +--- a/plat/st/stm32mp1/stm32mp1_private.c ++++ b/plat/st/stm32mp1/stm32mp1_private.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -15,8 +15,26 @@ + #include + #include + #include ++#include + #include + ++/* Internal layout of the 32bit OTP word board_id */ ++#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16) ++#define BOARD_ID_BOARD_NB_SHIFT 16 ++#define BOARD_ID_VARIANT_MASK GENMASK(15, 12) ++#define BOARD_ID_VARIANT_SHIFT 12 ++#define BOARD_ID_REVISION_MASK GENMASK(11, 8) ++#define BOARD_ID_REVISION_SHIFT 8 ++#define BOARD_ID_BOM_MASK GENMASK(3, 0) ++ ++#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \ ++ BOARD_ID_BOARD_NB_SHIFT) ++#define BOARD_ID2VAR(_id) (((_id) & BOARD_ID_VARIANT_MASK) >> \ ++ BOARD_ID_VARIANT_SHIFT) ++#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \ ++ BOARD_ID_REVISION_SHIFT) ++#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK) ++ + #define MAP_ROM MAP_REGION_FLAT(STM32MP_ROM_BASE, \ + STM32MP_ROM_SIZE, \ + MT_MEMORY | \ +@@ -119,9 +137,111 @@ uintptr_t get_uart_address(uint32_t instance_nb) + } + #endif + ++#define ARM_CNTXCTL_IMASK BIT(1) ++ ++void stm32mp_mask_timer(void) ++{ ++ /* Mask timer interrupts */ ++ write_cntp_ctl(read_cntp_ctl() | ARM_CNTXCTL_IMASK); ++ write_cntv_ctl(read_cntv_ctl() | ARM_CNTXCTL_IMASK); ++} ++ ++void __dead2 stm32mp_wait_cpu_reset(void) ++{ ++ uint32_t id; ++ ++ dcsw_op_all(DC_OP_CISW); ++ write_sctlr(read_sctlr() & ~SCTLR_C_BIT); ++ dcsw_op_all(DC_OP_CISW); ++ __asm__("clrex"); ++ ++ dsb(); ++ isb(); ++ ++ for ( ; ; ) { ++ do { ++ id = plat_ic_get_pending_interrupt_id(); ++ ++ if (id <= MAX_SPI_ID) { ++ gicv2_end_of_interrupt(id); ++ ++ plat_ic_disable_interrupt(id); ++ } ++ } while (id <= MAX_SPI_ID); ++ ++ wfi(); ++ } ++} ++ ++/* ++ * tzc_source_ip contains the TZC transaction source IPs that need to be reset ++ * before a C-A7 subsystem is reset (i.e. independent reset): ++ * - C-A7 subsystem is reset separately later in the sequence, ++ * - C-M4 subsystem is not concerned here, ++ * - DAP is excluded for debug purpose, ++ * - IPs are stored with their ETZPC IDs (STM32MP1_ETZPC_MAX_ID if not ++ * applicable) because some of them need to be reset only if they are not ++ * configured in MCU isolation mode inside ETZPC device tree. ++ */ ++struct tzc_source_ip { ++ uint32_t reset_id; ++ uint32_t clock_id; ++ uint32_t decprot_id; ++}; ++ ++#define _TZC_FIXED(res, clk) \ ++ { \ ++ .reset_id = (res), \ ++ .clock_id = (clk), \ ++ .decprot_id = STM32MP1_ETZPC_MAX_ID, \ ++ } ++ ++#define _TZC_COND(res, clk, decprot) \ ++ { \ ++ .reset_id = (res), \ ++ .clock_id = (clk), \ ++ .decprot_id = (decprot), \ ++ } ++ ++static const struct tzc_source_ip tzc_source_ip[] = { ++ _TZC_FIXED(LTDC_R, LTDC_PX), ++ _TZC_FIXED(GPU_R, GPU), ++ _TZC_FIXED(USBH_R, USBH), ++ _TZC_FIXED(SDMMC1_R, SDMMC1_K), ++ _TZC_FIXED(SDMMC2_R, SDMMC2_K), ++ _TZC_FIXED(MDMA_R, MDMA), ++ _TZC_COND(USBO_R, USBO_K, STM32MP1_ETZPC_OTG_ID), ++ _TZC_COND(SDMMC3_R, SDMMC3_K, STM32MP1_ETZPC_SDMMC3_ID), ++ _TZC_COND(ETHMAC_R, ETHMAC, STM32MP1_ETZPC_ETH_ID), ++ _TZC_COND(DMA1_R, DMA1, STM32MP1_ETZPC_DMA1_ID), ++ _TZC_COND(DMA2_R, DMA2, STM32MP1_ETZPC_DMA2_ID), ++}; ++ + void __dead2 stm32mp_plat_reset(int cpu) + { + uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST; ++ uint32_t id; ++ ++ /* Mask timer interrupts */ ++ stm32mp_mask_timer(); ++ ++ for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) { ++ if ((!stm32mp1_clk_is_enabled(tzc_source_ip[id].clock_id)) || ++ ((tzc_source_ip[id].decprot_id != STM32MP1_ETZPC_MAX_ID) && ++ (etzpc_get_decprot(tzc_source_ip[id].decprot_id) == ++ TZPC_DECPROT_MCU_ISOLATION))) { ++ continue; ++ } ++ ++ if (tzc_source_ip[id].reset_id != GPU_R) { ++ stm32mp_reset_assert(tzc_source_ip[id].reset_id); ++ stm32mp_reset_deassert(tzc_source_ip[id].reset_id); ++ } else { ++ /* GPU reset automatically cleared by hardware */ ++ mmio_setbits_32(stm32mp_rcc_base() + RCC_AHB6RSTSETR, ++ RCC_AHB6RSTSETR_GPURST); ++ } ++ } + + if (stm32mp_is_single_core() == 0) { + unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ? +@@ -131,18 +251,19 @@ void __dead2 stm32mp_plat_reset(int cpu) + reg |= RCC_MP_GRSTCSETR_MPUP1RST; + } + +- mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg); ++ do { ++ id = plat_ic_get_pending_interrupt_id(); + +- isb(); +- dsb(); ++ if (id <= MAX_SPI_ID) { ++ gicv2_end_of_interrupt(id); + +- /* Flush L1/L2 data caches */ +- write_sctlr(read_sctlr() & ~SCTLR_C_BIT); +- dcsw_op_all(DC_OP_CISW); ++ plat_ic_disable_interrupt(id); ++ } ++ } while (id <= MAX_SPI_ID); + +- for ( ; ; ) { +- wfi(); +- } ++ mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg); ++ ++ stm32mp_wait_cpu_reset(); + } + + static uint32_t get_part_number(void) +@@ -237,23 +358,49 @@ void stm32mp_print_cpuinfo(void) + + void stm32mp_print_boardinfo(void) + { +- uint32_t board; +- int res = 0; ++ uint32_t board_id = 0; ++ uint32_t board_otp; ++ int bsec_node, bsec_board_id_node; ++ void *fdt; ++ const fdt32_t *cuint; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); ++ } ++ ++ bsec_node = fdt_node_offset_by_compatible(fdt, -1, DT_BSEC_COMPAT); ++ if (bsec_node < 0) { ++ return; ++ } ++ ++ bsec_board_id_node = fdt_subnode_offset(fdt, bsec_node, "board_id"); ++ if (bsec_board_id_node <= 0) { ++ return; ++ } ++ ++ cuint = fdt_getprop(fdt, bsec_board_id_node, "reg", NULL); ++ if (cuint == NULL) { ++ ERROR("board_id node without reg property\n"); ++ panic(); ++ } ++ ++ board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); + +- if (bsec_shadow_read_otp(&board, BOARD_OTP) != BSEC_OK) { ++ if (bsec_shadow_read_otp(&board_id, board_otp) != BSEC_OK) { + ERROR("BSEC: PART_NUMBER_OTP Error\n"); +- res = -1; ++ return; + } + +- if ((res == 0) && (board != 0U)) { +- char rev[1]; ++ if (board_id != 0U) { ++ char rev[2]; + +- *rev = ((board >> 8) & 0xF) - 1 + 'A'; ++ rev[0] = BOARD_ID2REV(board_id) - 1 + 'A'; ++ rev[1] = '\0'; + NOTICE("Board: MB%04x Var%d Rev.%s-%02d\n", +- board >> 16, +- (board >> 12) & 0xF, ++ BOARD_ID2NB(board_id), ++ BOARD_ID2VAR(board_id), + rev, +- board & 0xF); ++ BOARD_ID2BOM(board_id)); + } + } + +@@ -309,12 +456,12 @@ uint32_t stm32_iwdg_get_otp_config(uintptr_t base) + iwdg_cfg |= IWDG_HW_ENABLED; + } + +- if ((otp_value & BIT(idx + IWDG_FZ_STOP_POS)) == 0U) { +- iwdg_cfg |= IWDG_ENABLE_ON_STOP; ++ if ((otp_value & BIT(idx + IWDG_FZ_STOP_POS)) != 0U) { ++ iwdg_cfg |= IWDG_DISABLE_ON_STOP; + } + +- if ((otp_value & BIT(idx + IWDG_FZ_STANDBY_POS)) == 0U) { +- iwdg_cfg |= IWDG_ENABLE_ON_STANDBY; ++ if ((otp_value & BIT(idx + IWDG_FZ_STANDBY_POS)) != 0U) { ++ iwdg_cfg |= IWDG_DISABLE_ON_STANDBY; + } + + return iwdg_cfg; +@@ -333,11 +480,11 @@ uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags) + + idx = stm32_iwdg_get_instance(base); + +- if ((flags & IWDG_ENABLE_ON_STOP) != 0) { ++ if ((flags & IWDG_DISABLE_ON_STOP) != 0) { + otp |= BIT(idx + IWDG_FZ_STOP_POS); + } + +- if ((flags & IWDG_ENABLE_ON_STANDBY) != 0) { ++ if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) { + otp |= BIT(idx + IWDG_FZ_STANDBY_POS); + } + +@@ -347,8 +494,8 @@ uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags) + } + + /* Sticky lock OTP_IWDG (read and write) */ +- if (!bsec_write_sr_lock(HW2_OTP, 1U) || +- !bsec_write_sw_lock(HW2_OTP, 1U)) { ++ if ((bsec_set_sr_lock(HW2_OTP) != BSEC_OK) || ++ (bsec_set_sw_lock(HW2_OTP) != BSEC_OK)) { + return BSEC_LOCK_FAIL; + } + +diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c +index 8dfbe71..d2da110 100644 +--- a/plat/st/stm32mp1/stm32mp1_security.c ++++ b/plat/st/stm32mp1/stm32mp1_security.c +@@ -30,7 +30,8 @@ static void init_tzc400(void) + tzc400_disable_filters(); + + #ifdef AARCH32_SP_OPTEE +- /* Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the ++ /* ++ * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the + * same configuration to all filters in the TZC. + */ + region_base = ddr_base; +@@ -38,7 +39,7 @@ static void init_tzc400(void) + tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, + region_base, + region_top, +- 0, ++ TZC_REGION_S_NONE, + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | +@@ -66,7 +67,7 @@ static void init_tzc400(void) + tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3, + region_base, + region_top, +- 0, ++ TZC_REGION_S_NONE, + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | +@@ -79,7 +80,8 @@ static void init_tzc400(void) + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)); + #else +- /* Region 1 set to cover all DRAM at 0xC000_0000. Apply the ++ /* ++ * Region 1 set to cover all DRAM at 0xC000_0000. Apply the + * same configuration to all filters in the TZC. + */ + region_base = ddr_base; +@@ -87,7 +89,7 @@ static void init_tzc400(void) + tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, + region_base, + region_top, +- TZC_REGION_S_RDWR, ++ TZC_REGION_S_NONE, + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | +@@ -121,10 +123,7 @@ static void early_init_tzc400(void) + + tzc400_disable_filters(); + +- /* +- * Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the +- * same configuration to all filters in the TZC. +- */ ++ /* Region 1 set to cover Non-Secure DRAM at 0xC000_0000 */ + tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, + STM32MP_DDR_BASE, + STM32MP_DDR_BASE + +diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c +index 2c95de0..09d9136 100644 +--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c ++++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: BSD-3-Clause + /* +- * Copyright (c) 2017-2018, STMicroelectronics ++ * Copyright (c) 2017-2019, STMicroelectronics + */ + + #include +@@ -765,8 +765,6 @@ static void check_rcc_secure_configuration(void) + bool mckprot = stm32mp1_rcc_is_mckprot(); + bool secure = stm32mp1_rcc_is_secure(); + +- stm32mp1_rcc_init_late(); +- + for (n = 0; n < ARRAY_SIZE(shres_state); n++) { + if ((shres_state[n] == SHRES_SECURE) || + (shres_state[n] == SHRES_SHARED)) { +diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c +index 3eb9893..3276870 100644 +--- a/plat/st/stm32mp1/stm32mp1_syscfg.c ++++ b/plat/st/stm32mp1/stm32mp1_syscfg.c +@@ -6,9 +6,11 @@ + + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + +@@ -45,14 +47,16 @@ + */ + #define SYSCFG_CMPCR_SW_CTRL BIT(1) + #define SYSCFG_CMPCR_READY BIT(8) ++#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16) ++#define SYSCFG_CMPCR_RANSRC_SHIFT 16 ++#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) ++#define SYSCFG_CMPCR_ANSRC_SHIFT 24 + + /* + * SYSCFG_CMPENSETR Register + */ + #define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +-#define PRODUCT_BELOW_2V5 BIT(13) +- + void stm32mp1_syscfg_init(void) + { + uint32_t bootr; +@@ -81,28 +85,30 @@ void stm32mp1_syscfg_init(void) + /* + * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI + * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. +- * The customer will have to disable this for low frequencies +- * or if AFMUX is selected but the function not used, typically for +- * TRACE. Otherwise, impact on power consumption. ++ * It could be disabled for low frequencies or if AFMUX is selected ++ * but the function not used, typically for TRACE. ++ * Otherwise, impact on power consumption. + * + * WARNING: + * Enabling High Speed mode while VDD > 2.7V + * with the OTP product_below_2v5 (OTP 18, BIT 13) + * erroneously set to 1 can damage the IC! +- * => TF-A sets the register only if VDD < 2.7V (in DT) ++ * => TF-A enables the low power mode only if VDD < 2.7V (in DT) + * but this value needs to be consistent with board design. + */ + if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) { +- otp = otp & PRODUCT_BELOW_2V5; ++ panic(); + } + +- /* Get VDD = pwr-supply */ ++ otp = otp & HW2_OTP_PRODUCT_BELOW_2V5; ++ ++ /* Get VDD supply */ + vdd_voltage = dt_get_pwr_vdd_voltage(); + VERBOSE("VDD regulator voltage = %d\n", vdd_voltage); + + /* Check if VDD is Low Voltage */ + if (vdd_voltage == 0U) { +- INFO("VDD unknown"); ++ WARN("VDD unknown"); + } else if (vdd_voltage < 2700000U) { + mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR, + SYSCFG_IOCTRLSETR_HSLVEN_TRACE | +@@ -116,8 +122,8 @@ void stm32mp1_syscfg_init(void) + } + } else { + if (otp != 0U) { +- INFO("Product_below_2v5=1: HSLVEN update is\n"); +- INFO(" destructive, no update as VDD>2.7V\n"); ++ ERROR("Product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n"); ++ panic(); + } + } + +@@ -125,14 +131,25 @@ void stm32mp1_syscfg_init(void) + (uint32_t)syscfg_base + SYSCFG_IOCTRLSETR, + mmio_read_32(syscfg_base + SYSCFG_IOCTRLSETR)); + ++ stm32mp1_syscfg_enable_io_compensation(); ++} ++ ++void stm32mp1_syscfg_enable_io_compensation(void) ++{ ++ uintptr_t syscfg_base = dt_get_syscfg_base(); ++ + /* + * Activate automatic I/O compensation. + * Warning: need to ensure CSI enabled and ready in clock driver. ++ * Enable non-secure clock, we assume non-secure is suspended. + */ +- mmio_write_32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN); ++ stm32mp1_clk_enable_non_secure(SYSCFG); ++ ++ mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR, ++ SYSCFG_CMPENSETR_MPU_EN); + + while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & +- SYSCFG_CMPCR_READY) != 0U) { ++ SYSCFG_CMPCR_READY) == 0U) { + ; + } + +@@ -142,3 +159,37 @@ void stm32mp1_syscfg_init(void) + (uint32_t)syscfg_base + SYSCFG_CMPCR, + mmio_read_32(syscfg_base + SYSCFG_CMPCR)); + } ++ ++void stm32mp1_syscfg_disable_io_compensation(void) ++{ ++ uintptr_t syscfg_base = dt_get_syscfg_base(); ++ uint32_t value; ++ ++ /* ++ * Deactivate automatic I/O compensation. ++ * Warning: CSI is disabled automatically in STOP if not ++ * requested for other usages and always OFF in STANDBY. ++ * Disable non-secure SYSCFG clock, we assume non-secure is suspended. ++ */ ++ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >> ++ SYSCFG_CMPCR_ANSRC_SHIFT; ++ ++ mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, ++ SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); ++ ++ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) | ++ (value << SYSCFG_CMPCR_RANSRC_SHIFT); ++ ++ mmio_write_32(syscfg_base + SYSCFG_CMPCR, value); ++ ++ mmio_setbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); ++ ++ VERBOSE("[0x%x] SYSCFG.cmpcr = 0x%08x\n", ++ (uint32_t)syscfg_base + SYSCFG_CMPCR, ++ mmio_read_32(syscfg_base + SYSCFG_CMPCR)); ++ ++ mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR, ++ SYSCFG_CMPENSETR_MPU_EN); ++ ++ stm32mp1_clk_disable_non_secure(SYSCFG); ++} +-- +2.7.4 + diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.0.bb b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.0.bb index 7933bba..6272e09 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.0.bb +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.0.bb @@ -9,6 +9,7 @@ SRC_URI[sha256sum] = "7d699a1683bb7a5909de37b6eb91b6e38db32cd6fc5ae48a08eb0718d6 SRC_URI += " \ file://0001-st-update-r1.patch \ + file://0002-st-update-r1.1.0.patch \ " TF_VERSION = "2.0" @@ -18,13 +19,18 @@ S = "${WORKDIR}/arm-trusted-firmware-${PV}" require tf-a-stm32mp-common.inc +# --------------------------------- +# Configure archiver use +# --------------------------------- +include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'tf-a-stm32mp-archiver.inc','')} + # --------------------------------- # Configure devupstream class usage # --------------------------------- BBCLASSEXTEND = "devupstream:target" SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/arm-trusted-firmware.git;protocol=https;name=tfa;branch=v2.0-stm32mp" -SRCREV_class-devupstream = "d0233623681124a85b069f97a447d7edb1cc1c02" +SRCREV_class-devupstream = "69cc28c5a1b877cf67def7f94dece087f3917b1c" SRCREV_FORMAT_class-devupstream = "tfa" PV_class-devupstream = "${TF_VERSION}+github+${SRCPV}" # ---------------------------------