diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc index 5d08a57..f8b09ca 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc @@ -18,100 +18,103 @@ archiver_create_makefile_for_sdk() { 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 + cat << EOF > ${ARCHIVER_OUTDIR}/Makefile.sdk +#remove default variable +LDFLAGS= +CFLAGS= +CPPFLAGS= +CC= +CPP= +AS= +AR= +LD= +NM= - echo "LOCAL_PATH=\$(PWD)" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk +LOCAL_PATH=\$(PWD) - echo "EXTRA_OEMAKE=${EXTRA_OEMAKE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk +EXTRA_OEMAKE=${EXTRA_OEMAKE} +EXTRA_OEMAKE_SERIAL=$(subst STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_SPI_NOR=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1,,${EXTRA_OEMAKE}) STM32MP_UART_PROGRAMMER=1 STM32MP_USB_PROGRAMMER=1 - # 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 config +ELF_DEBUG_ENABLE ?= ${ELF_DEBUG_ENABLE} +TF_A_CONFIG ?= ${TF_A_CONFIG} serialboot - # 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 +# Set specific OEMAKE config +TF_A_CONFIG_OEMAKE = ${tf_a_config_oemake} serialboot,"AARCH32_SP=sp_min" +# Set default TFA_DEVICETREE +TFA_DEVICETREE ?= ${TF_A_DEVICETREE} - 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 +#Set default TF_A_ENABLE_DEBUG_WRAPPER +TF_A_ENABLE_DEBUG_WRAPPER ?= ${TF_A_ENABLE_DEBUG_WRAPPER} - echo "all: tf" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk +help: + @echo + @echo "Available targets:" + @echo " all : build TF-A binaries for defined config(s)" + @echo " clean : clean build directories from generated files" + @echo + @echo "TF-A configuration:" + @echo " TF_A_CONFIG = \$(TF_A_CONFIG)" + @echo " TFA_DEVICETREE = \$(TFA_DEVICETREE)" + @echo " ELF_DEBUG_ENABLE = '\$(ELF_DEBUG_ENABLE)' ('1' to export elf files)" + @echo " TF_A_ENABLE_DEBUG_WRAPPER = '\$(TF_A_ENABLE_DEBUG_WRAPPER)' ('1' to generate tf-a for debugging)" + @echo - 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 +all: tf - 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 +host_tools: + @\$(MAKE) --no-print-directory -C \$(LOCAL_PATH)/tools/stm32image - 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 +tf: host_tools + for config in \$(TF_A_CONFIG) ; do \\ + # Init any extraoemake \\ + add_extraoemake= ; \\ + for fullconfig in \$(TF_A_CONFIG_OEMAKE) ; do \\ + extraconfig=\$\$(echo \$\$fullconfig | cut -d',' -f1) ; \\ + if [ "\$\$extraconfig" = "\$\$config" ]; then \\ + add_extraoemake=\$\$(echo \$\$fullconfig | cut -d',' -f2) ; \\ + fi ; \\ + done ; \\ + mkdir -p \$(LOCAL_PATH)/../build/\$\$config ; \\ + if test -n "\$(TFA_DEVICETREE)" ; then \\ + for dt in \$(TFA_DEVICETREE) ; do \\ + if [ "\$(TF_A_CONFIG)" != "serialboot" ]; then \\ + \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) DTB_FILE_NAME=\$\$dt.dtb BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake ; \\ + else \\ + \$(MAKE) \$(EXTRA_OEMAKE_SERIAL) -C \$(LOCAL_PATH) DTB_FILE_NAME=\$\$dt.dtb BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake ; \\ + fi \\ + # Copy binary file with explicit name \\ + 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} ; \\ + if [ "\$(TF_A_ENABLE_DEBUG_WRAPPER)" = "1" ]; then \\ + # Generate wrapper for debugging \\ + stm32wrapper4dbg -s \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-\$\$dt.${TF_A_SUFFIX} -d \$(LOCAL_PATH)/../build/\$\$config/debug-${TF_A_BASENAME}-\$\$dt-\$\$config.${TF_A_SUFFIX} ; \\ + fi \\ + done ; \\ + else \\ + \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) BUILD_PLAT=\$(LOCAL_PATH)/../build/\$\$config \$\$add_extraoemake; \\ + tf_version=\$\$(find \$(LOCAL_PATH)/../build/\$\$config -name ${TF_A_BASENAME}*.${TF_A_SUFFIX} -exec basename {} \; | sed "s/\.${TF_A_SUFFIX}//") ; \\ + # Copy binary file with explicit name \\ + cp -f \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version-\$\$config.${TF_A_SUFFIX} ; \\ + if [ "\$(TF_A_ENABLE_DEBUG_WRAPPER)" = "1" ]; then \\ + # Generate wrapper for debugging \\ + stm32wrapper4dbg -s \$(LOCAL_PATH)/../build/\$\$config/\$\$tf_version.${TF_A_SUFFIX} \$(LOCAL_PATH)/../build/\$\$config/debug-\$\$tf_version-\$\$config.${TF_A_SUFFIX} ; \\ + fi \\ + fi ; \\ + # Copy elf files with explicit name \\ + if [ "\$(ELF_DEBUG_ENABLE)" = "1" ] ; then \\ + if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} ] ; then \\ + cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL2_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL2_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\ + fi ; \\ + if [ -f \$(LOCAL_PATH)/../build/\$\$config/${BL32_ELF} ] ; then \\ + cp -f \$(LOCAL_PATH)/../build/\$\$config/${BL32_ELF} \$(LOCAL_PATH)/../build/\$\$config/${TF_A_BASENAME}-${BL32_BASENAME}-\$\$config.${TF_A_ELF_SUFFIX} ; \\ + fi ; \\ + fi ; \\ + done + +clean: + @for config in \$(TF_A_CONFIG) ; do \\ + rm -rf \$(LOCAL_PATH)/../build/\$\$config ; \\ + done +EOF } 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 cba99f6..c33e518 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc @@ -11,6 +11,13 @@ B = "${WORKDIR}/build" EXTERNALSRC_BUILD_pn-${PN} = "${WORKDIR}/build" DEPENDS += "dtc-native" +DEPENDS_append = " ${@bb.utils.contains('TF_A_ENABLE_DEBUG_WRAPPER', '1', 'stm32wrapper4dbg-native', '', d)}" + +# Extra make settings +EXTRA_OEMAKE = 'CROSS_COMPILE=${TARGET_PREFIX}' +# Debug support +EXTRA_OEMAKE += 'DEBUG=1' +EXTRA_OEMAKE += 'LOG_LEVEL=40' # Define default TF-A namings TF_A_BASENAME ?= "tf-a" @@ -32,21 +39,15 @@ BL32_NAME ?= "bl32/bl32" BL32_ELF = "${BL32_NAME}.${TF_A_ELF_SUFFIX}" BL32_BASENAME = "${@os.path.basename(d.getVar("BL32_NAME"))}" -# Extra make settings -EXTRA_OEMAKE = 'CROSS_COMPILE=${TARGET_PREFIX}' -EXTRA_OEMAKE += 'PLAT=stm32mp1' -EXTRA_OEMAKE += 'ARCH=aarch32' -EXTRA_OEMAKE += 'ARM_ARCH_MAJOR=7' - -# Debug support -EXTRA_OEMAKE += 'DEBUG=1' -EXTRA_OEMAKE += "LOG_LEVEL=40" - # Set default TF-A config TF_A_CONFIG ?= "" +#Enable the wrapper for debug +TF_A_ENABLE_DEBUG_WRAPPER ??= "1" + # ----------------------------------------------- # Enable use of work-shared folder +TFA_SHARED_SOURCES ??= "1" STAGING_TFA_DIR = "${TMPDIR}/work-shared/${MACHINE}/tfa-source" # Make sure to move ${S} to STAGING_TFA_DIR. We can't just # create the symlink in advance as the git fetcher can't cope with @@ -60,25 +61,26 @@ base_do_unpack_append () { if d.getVar('STAGING_TFA_DIR', d): d.setVar('STAGING_TFA_DIR', '${S}') - # Copy/Paste from kernel class with adaptation to TFA var - s = d.getVar("S") - if s[-1] == '/': - # drop trailing slash, so that os.symlink(tfasrc, s) doesn't use s as directory name and fail - s=s[:-1] - tfasrc = d.getVar("STAGING_TFA_DIR") - if s != tfasrc: - bb.utils.mkdirhier(tfasrc) - bb.utils.remove(tfasrc, recurse=True) - if d.getVar("EXTERNALSRC"): - # With EXTERNALSRC S will not be wiped so we can symlink to it - os.symlink(s, tfasrc) - else: - import shutil - shutil.move(s, tfasrc) - os.symlink(tfasrc, s) + shared = d.getVar("TFA_SHARED_SOURCES") + if shared and oe.types.boolean(shared): + # Copy/Paste from kernel class with adaptation to TFA var + s = d.getVar("S") + if s[-1] == '/': + # drop trailing slash, so that os.symlink(tfasrc, s) doesn't use s as directory name and fail + s=s[:-1] + tfasrc = d.getVar("STAGING_TFA_DIR") + if s != tfasrc: + bb.utils.mkdirhier(tfasrc) + bb.utils.remove(tfasrc, recurse=True) + if d.getVar("EXTERNALSRC"): + # With EXTERNALSRC S will not be wiped so we can symlink to it + os.symlink(s, tfasrc) + else: + import shutil + shutil.move(s, tfasrc) + os.symlink(tfasrc, s) } - # Manage to export any specific setting for defined configs python tfaconfig_env () { if d.getVar('TF_A_CONFIG'): @@ -106,13 +108,20 @@ do_compile() { for dt in ${TF_A_DEVICETREE}; do oe_runmake -C ${S} DTB_FILE_NAME=${dt}.dtb BUILD_PLAT=${B}/${config} ${add_extraoemake} cp ${B}/${config}/${TF_A_BASENAME}-${dt}.${TF_A_SUFFIX} ${B}/${config}/${TF_A_BASENAME}-${dt}-${config}.${TF_A_SUFFIX} + if [ "${TF_A_ENABLE_DEBUG_WRAPPER}" = "1" ]; then + stm32wrapper4dbg -s ${B}/${config}/${TF_A_BASENAME}-${dt}.${TF_A_SUFFIX} -d ${B}/${config}/debug-${TF_A_BASENAME}-${dt}-${config}.${TF_A_SUFFIX} + fi done else oe_runmake -C ${S} BUILD_PLAT=${B}/${config} ${add_extraoemake} + tf_a_binary_basename=$(find ${B}/${config} -name "${TF_A_BASENAME}-*.${TF_A_SUFFIX}" -exec basename {} \; | sed 's|\.'"${TF_A_SUFFIX}"'||g') + if [ "${TF_A_ENABLE_DEBUG_WRAPPER}" = "1" ]; then + stm32wrapper4dbg -s ${B}/${config}/${tf_a_binary_basename}.${TF_A_SUFFIX} -d ${B}/${config}/debug-${tf_a_binary_basename}.${TF_A_SUFFIX} + fi fi done } - +do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/arm-trusted-firmware" do_deploy() { install -d ${DEPLOYDIR} @@ -120,11 +129,21 @@ do_deploy() { if [ -n "${TF_A_DEVICETREE}" ]; then for dt in ${TF_A_DEVICETREE}; do install -m 644 ${B}/${config}/${TF_A_BASENAME}-${dt}-${config}.${TF_A_SUFFIX} ${DEPLOYDIR} + if [ "${TF_A_ENABLE_DEBUG_WRAPPER}" = "1" ]; then + install -d ${DEPLOYDIR}/debug + install -m 644 ${B}/${config}/debug-${TF_A_BASENAME}-${dt}-${config}.${TF_A_SUFFIX} ${DEPLOYDIR}/debug + fi done else # Get tf-a binary basename to copy tf_a_binary_basename=$(find ${B}/${config} -name "${TF_A_BASENAME}-*.${TF_A_SUFFIX}" -exec basename {} \; | sed 's|\.'"${TF_A_SUFFIX}"'||g') - install -m 644 ${B}/${config}/${tf_a_binary_basename}.${TF_A_SUFFIX} ${DEPLOYDIR}/${tf_a_binary_basename}-${config}.${TF_A_SUFFIX} + for f in ${tf_a_binary_basename}; do + install -m 644 ${B}/${config}/${f}.${TF_A_SUFFIX} ${DEPLOYDIR}/${f}-${config}.${TF_A_SUFFIX} + if [ "${TF_A_ENABLE_DEBUG_WRAPPER}" = "1" ]; then + install -d ${DEPLOYDIR}/debug + install -m 644 ${B}/${config}/debug-${f}.${TF_A_SUFFIX} ${DEPLOYDIR}/debug/debug-${f}-${config}.${TF_A_SUFFIX} + fi + done fi done diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common_2.2.inc b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common_2.2.inc new file mode 100644 index 0000000..fb6a2af --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common_2.2.inc @@ -0,0 +1,34 @@ +FILESEXTRAPATHS_prepend_stm32mpcommon := "${THISDIR}/tf-a-stm32mp:" + +SECTION = "bootloaders" + +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://license.rst;md5=1dd070c98a281d18d9eefd938729b031" + +SRC_URI = "git://github.com/ARM-software/arm-trusted-firmware.git;protocol=https;nobranch=1" +SRCREV = "a04808c16cfc126d9fe572ae7c4b5a3d39de5796" + +SRC_URI += " \ + file://0001-st-update-v2.2-r2.0.0.patch \ + " + +TF_VERSION = "2.2" +PV = "${TF_VERSION}.r1" + +S = "${WORKDIR}/git" + +# --------------------------------- +# 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_FORMAT_class-devupstream = "tfa" +#PV_class-devupstream = "${TF_VERSION}+github+${SRCPV}" +# --------------------------------- +# Configure default preference to manage dynamic selection between tarball and github +# --------------------------------- +#STM32MP_SOURCE_SELECTION ?= "tarball" + +#DEFAULT_PREFERENCE = "${@bb.utils.contains('STM32MP_SOURCE_SELECTION', 'github', '-1', '1', d)}" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-serialboot_2.2.bb b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-serialboot_2.2.bb new file mode 100644 index 0000000..89eb6ca --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-serialboot_2.2.bb @@ -0,0 +1,21 @@ +require tf-a-stm32mp-common_${PV}.inc +require tf-a-stm32mp-common.inc + +SUMMARY = "Trusted Firmware-A for STM32MP1 as serial boot loader" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://license.rst;md5=1dd070c98a281d18d9eefd938729b031" + +PROVIDES += "virtual/trusted-firmware-a-serialboot" + +TFA_SHARED_SOURCES = "0" + +# Configure stm32mp1 make settings +EXTRA_OEMAKE += 'PLAT=stm32mp1' +EXTRA_OEMAKE += 'ARCH=aarch32' +EXTRA_OEMAKE += 'ARM_ARCH_MAJOR=7' +# Configure all serial boot supports +EXTRA_OEMAKE += 'STM32MP_UART_PROGRAMMER=1' +EXTRA_OEMAKE += 'STM32MP_USB_PROGRAMMER=1' + +# Disable the wrapper for debug +TF_A_ENABLE_DEBUG_WRAPPER ?= "0" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-r1.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.2-r2.0.0.patch similarity index 50% rename from recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-r1.patch rename to recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.2-r2.0.0.patch index ae24495..c4405da 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-r1.patch +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.2-r2.0.0.patch @@ -1,250 +1,267 @@ -From b378eb77ad6177d7bd5cb1a5befc4b0c52f70e2c Mon Sep 17 00:00:00 2001 -From: christophe montaud -Date: Tue, 29 Jan 2019 18:16:44 +0100 -Subject: [PATCH] st update r1 +From 334224a627331b7278c8bc71c10b32da2db14194 Mon Sep 17 00:00:00 2001 +From: Christophe Priouzeau +Date: Tue, 9 Jun 2020 11:44:18 +0200 +Subject: [PATCH] st-update-v2.2-r2.0.0 --- - .checkpatch.conf | 18 + - Makefile | 56 +- - bl2/aarch32/bl2_arch_setup.c | 1 + - bl2/aarch32/bl2_el3_entrypoint.S | 4 + - bl2/aarch32/bl2_el3_exceptions.S | 9 + - bl2/aarch32/bl2_entrypoint.S | 9 + - bl2/bl2_image_load_v2.c | 14 +- - bl2/bl2_private.h | 3 + - bl2u/aarch32/bl2u_entrypoint.S | 9 + - bl32/sp_min/aarch32/entrypoint.S | 9 + - common/aarch32/debug.S | 54 +- - docs/devicetree/bindings/arm/secure.txt | 53 + - docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt | 324 +++ - docs/devicetree/bindings/i2c/i2c-stm32.txt | 54 + - docs/devicetree/bindings/mmc/mmci.txt | 72 + - docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt | 22 + - docs/devicetree/bindings/power/st,stm32mp1-pwr.txt | 42 + - docs/devicetree/bindings/power/st,stpmic1.txt | 132 ++ - docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt | 6 + - docs/devicetree/bindings/rng/st,stm32-rng.txt | 23 + - docs/devicetree/bindings/serial/st,stm32-usart.txt | 88 + - docs/devicetree/bindings/soc/st,stm32-etzpc.txt | 56 + - docs/devicetree/bindings/soc/st,stm32-romem.txt | 31 + - docs/devicetree/bindings/soc/st,stm32-stgen.txt | 18 + - docs/devicetree/bindings/soc/st,stm32-tamp.txt | 22 + - .../devicetree/bindings/watchdog/st,stm32-iwdg.txt | 28 + - docs/plat/stm32mp1.rst | 16 + - docs/porting-guide.rst | 44 +- - drivers/arm/pl011/aarch32/pl011_console.S | 139 +- - drivers/arm/pl011/aarch64/pl011_console.S | 3 +- - drivers/arm/tzc/tzc400.c | 129 ++ - drivers/cadence/uart/aarch64/cdns_console.S | 4 +- - drivers/console/aarch32/console.S | 105 +- - drivers/console/aarch32/deprecated_console.S | 112 + - drivers/console/aarch32/multi_console.S | 318 +++ - drivers/console/aarch64/skeleton_console.S | 9 +- - .../coreboot/cbmem_console/aarch64/cbmem_console.S | 3 +- - drivers/io/io_block.c | 8 +- - drivers/io/io_memmap.c | 5 +- - drivers/io/io_semihosting.c | 4 +- - drivers/io/io_storage.c | 2 +- - drivers/mmc/mmc.c | 23 +- - drivers/partition/gpt.c | 10 +- - drivers/partition/partition.c | 2 +- - drivers/st/bsec/bsec.c | 911 ++++++++ - drivers/st/clk/stm32mp1_clk.c | 2247 +++++++++++++++----- - drivers/st/clk/stm32mp1_clkfunc.c | 211 +- - drivers/st/clk/stm32mp_clkfunc.c | 307 +++ - drivers/st/ddr/stm32mp1_ddr.c | 484 +++-- - drivers/st/ddr/stm32mp1_ddr_helpers.c | 510 ++++- - drivers/st/ddr/stm32mp1_ram.c | 194 +- - drivers/st/etzpc/etzpc.c | 310 +++ - drivers/st/gpio/stm32_gpio.c | 267 ++- - drivers/st/hash/hash_sec.c | 369 ++++ - drivers/st/i2c/stm32_i2c.c | 1371 ++++++++++++ - drivers/st/io/io_mmc.c | 134 ++ - drivers/st/io/io_programmer_st_usb.c | 379 ++++ - drivers/st/io/io_stm32image.c | 381 ++++ - drivers/st/iwdg/stm32_iwdg.c | 289 +++ - drivers/st/mmc/stm32_sdmmc2.c | 752 +++++++ - drivers/st/nand/io_nand.c | 228 ++ - drivers/st/nand/nand.c | 1548 ++++++++++++++ - drivers/st/pmic/stm32_i2c.c | 851 -------- - drivers/st/pmic/stm32mp1_pmic.c | 346 --- - drivers/st/pmic/stm32mp_pmic.c | 522 +++++ - drivers/st/pmic/stpmic1.c | 817 +++++++ - drivers/st/pmic/stpmu1.c | 600 ------ - drivers/st/qspi/io_qspi.c | 349 +++ - drivers/st/reset/stm32mp1_reset.c | 64 +- - drivers/st/rng/stm32_rng.c | 191 ++ - drivers/st/rtc/stm32_rtc.c | 499 +++++ - drivers/st/tamper/stm32_tamp.c | 375 ++++ - drivers/st/timer/stm32_timer.c | 297 +++ - drivers/st/uart/aarch32/stm32_console.S | 151 +- - drivers/st/uart/io_programmer_uart.c | 597 ++++++ - drivers/st/uart/stm32mp1xx_hal_uart.c | 799 +++++++ - drivers/st/usb_dwc2/usb_dwc2.c | 858 ++++++++ - drivers/ti/uart/aarch64/16550_console.S | 3 +- - fdts/stm32mp15-ddr.dtsi | 2 +- - fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 121 ++ - fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 19 +- - fdts/stm32mp157-pinctrl.dtsi | 154 +- - fdts/stm32mp157a-dk1.dts | 464 ++++ - fdts/stm32mp157c-dk2.dts | 16 + - fdts/stm32mp157c-ed1.dts | 342 ++- - fdts/stm32mp157c-ev1.dts | 52 +- - fdts/stm32mp157c-security.dtsi | 71 + - fdts/stm32mp157c.dtsi | 215 +- - fdts/stm32mp157caa-pinctrl.dtsi | 8 +- - fdts/stm32mp157cab-pinctrl.dtsi | 62 + - fdts/stm32mp157cac-pinctrl.dtsi | 78 + - fdts/stm32mp157cad-pinctrl.dtsi | 62 + - include/common/aarch32/console_macros.S | 84 + - include/common/aarch64/console_macros.S | 46 +- - include/common/tbbr/tbbr_img_def.h | 8 +- - include/drivers/arm/tzc400.h | 4 + - include/drivers/io/io_driver.h | 2 +- - include/drivers/io/io_storage.h | 8 +- - include/drivers/st/bsec.h | 205 ++ - include/drivers/st/etzpc.h | 32 + - include/drivers/st/hash_sec.h | 113 + - include/drivers/st/io_mmc.h | 14 + - include/drivers/st/io_nand.h | 19 + - include/drivers/st/io_programmer.h | 51 + - include/drivers/st/io_programmer_st_usb.h | 20 + - include/drivers/st/io_qspi.h | 92 + - include/drivers/st/io_stm32image.h | 32 + - include/drivers/st/io_uart.h | 12 + - include/drivers/st/nand.h | 252 +++ - include/drivers/st/stm32_console.h | 34 + - include/drivers/st/stm32_gpio.h | 68 +- - include/drivers/st/stm32_hal_hash_reg.h | 136 ++ - include/drivers/st/stm32_i2c.h | 303 +-- - include/drivers/st/stm32_iwdg.h | 20 + - include/drivers/st/stm32_rng.h | 13 + - include/drivers/st/stm32_rtc.h | 79 + - include/drivers/st/stm32_sdmmc2.h | 31 + - include/drivers/st/stm32_tamp.h | 163 ++ - include/drivers/st/stm32_timer.h | 21 + - include/drivers/st/stm32_uart_regs.h | 199 ++ - include/drivers/st/stm32mp1_clk.h | 71 +- - include/drivers/st/stm32mp1_clkfunc.h | 18 +- - include/drivers/st/stm32mp1_ddr.h | 13 +- - include/drivers/st/stm32mp1_ddr_helpers.h | 14 +- - include/drivers/st/stm32mp1_ddr_regs.h | 15 +- - include/drivers/st/stm32mp1_pmic.h | 18 - - include/drivers/st/stm32mp1_pwr.h | 31 +- - include/drivers/st/stm32mp1_ram.h | 6 +- - include/drivers/st/stm32mp1_rcc.h | 138 +- - include/drivers/st/stm32mp1_reset.h | 15 - - include/drivers/st/stm32mp1xx_hal.h | 203 ++ - include/drivers/st/stm32mp1xx_hal_uart.h | 1586 ++++++++++++++ - include/drivers/st/stm32mp1xx_hal_uart_ex.h | 87 + - include/drivers/st/stm32mp_clkfunc.h | 28 + - include/drivers/st/stm32mp_pmic.h | 24 + - include/drivers/st/stm32mp_reset.h | 15 + - include/drivers/st/stpmic1.h | 173 ++ - include/drivers/st/stpmu1.h | 141 -- - include/drivers/st/usb_dwc2.h | 443 ++++ - include/dt-bindings/interrupt-controller/arm-gic.h | 21 + - include/dt-bindings/pinctrl/stm32-pinfunc.h | 6 + - include/dt-bindings/power/stm32mp1-power.h | 19 + - include/dt-bindings/soc/st,stm32-etzpc.h | 107 + - include/lib/aarch32/arch.h | 14 + - include/lib/aarch32/arch_helpers.h | 3 + - include/lib/cpus/aarch32/cortex_a9.h | 5 + - include/lib/optee_utils.h | 1 + - include/lib/psci/psci.h | 8 +- - include/lib/usb/usb_core.h | 352 +++ - include/lib/usb/usb_st_dfu.h | 115 + - include/lib/utils.h | 29 +- - include/lib/utils_def.h | 20 +- - include/lib/xlat_tables/xlat_tables_v2_helpers.h | 41 +- - include/plat/common/platform.h | 5 + - lib/compiler-rt/builtins/int_lib.h | 13 +- - lib/compiler-rt/builtins/lshrdi3.c | 45 + - lib/compiler-rt/compiler-rt.mk | 3 +- - lib/libfdt/fdt_ro.c | 2 +- - lib/optee/optee_utils.c | 30 + - lib/usb/usb_core.c | 732 +++++++ - lib/usb/usb_st_dfu.c | 865 ++++++++ - lib/xlat_tables/aarch32/xlat_tables.c | 9 + - lib/xlat_tables/aarch64/xlat_tables.c | 4 + - lib/xlat_tables/xlat_tables_common.c | 18 + - lib/xlat_tables_v2/xlat_tables_core.c | 7 +- - make_helpers/build_macros.mk | 15 +- - make_helpers/defaults.mk | 3 + - plat/arm/common/aarch32/arm_helpers.S | 6 +- - plat/arm/common/arm_common.mk | 4 +- - plat/arm/common/sp_min/arm_sp_min_setup.c | 7 +- - plat/common/aarch32/crash_console_helpers.S | 92 + - plat/common/aarch32/plat_sp_min_common.c | 4 + - plat/common/aarch32/platform_helpers.S | 38 + - plat/common/aarch64/crash_console_helpers.S | 92 + - plat/common/aarch64/platform_helpers.S | 4 + - plat/common/plat_log_common.c | 1 + - plat/imx/common/lpuart_console.S | 3 +- - plat/layerscape/common/aarch64/ls_console.S | 3 +- - plat/st/common/bl2_io_storage.c | 773 +++++++ - plat/st/common/include/stm32mp_auth.h | 15 + - plat/st/common/include/stm32mp_common.h | 49 + - plat/st/common/include/stm32mp_dt.h | 54 + - plat/st/common/include/stm32mp_shres_helpers.h | 86 + - plat/st/common/stm32mp_auth.c | 121 ++ - plat/st/common/stm32mp_common.c | 168 ++ - plat/st/common/stm32mp_dt.c | 559 +++++ - plat/st/common/stm32mp_shres_helpers.c | 71 + - plat/st/stm32mp1/bl2_io_storage.c | 193 -- - plat/st/stm32mp1/bl2_plat_setup.c | 447 +++- - plat/st/stm32mp1/include/boot_api.h | 411 +++- - plat/st/stm32mp1/include/platform_def.h | 64 +- - plat/st/stm32mp1/include/stm32mp1_context.h | 18 +- - plat/st/stm32mp1/include/stm32mp1_dbgmcu.h | 26 + - plat/st/stm32mp1/include/stm32mp1_dt.h | 41 - - plat/st/stm32mp1/include/stm32mp1_low_power.h | 19 + - plat/st/stm32mp1/include/stm32mp1_power_config.h | 28 + - plat/st/stm32mp1/include/stm32mp1_private.h | 30 +- - .../stm32mp1/include/stm32mp1_shared_resources.h | 83 + - plat/st/stm32mp1/include/stm32mp1_smc.h | 68 + - plat/st/stm32mp1/include/stm32mp1_usb_desc.h | 55 + - plat/st/stm32mp1/include/usb_ctx.h | 17 + - plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 49 +- - plat/st/stm32mp1/plat_image_load.c | 103 + - plat/st/stm32mp1/platform.mk | 144 +- - plat/st/stm32mp1/services/bsec_svc.c | 460 ++++ - plat/st/stm32mp1/services/bsec_svc.h | 21 + - plat/st/stm32mp1/services/low_power_svc.c | 46 + - plat/st/stm32mp1/services/low_power_svc.h | 15 + - plat/st/stm32mp1/services/pwr_svc.c | 124 ++ - plat/st/stm32mp1/services/pwr_svc.h | 13 + - plat/st/stm32mp1/services/rcc_svc.c | 477 +++++ - plat/st/stm32mp1/services/rcc_svc.h | 14 + - plat/st/stm32mp1/services/stm32mp1_svc_setup.c | 113 + - plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 14 + - plat/st/stm32mp1/sp_min/sp_min_setup.c | 243 ++- - plat/st/stm32mp1/stm32mp1.ld.S | 19 +- - plat/st/stm32mp1/stm32mp1_common.c | 101 - - plat/st/stm32mp1/stm32mp1_context.c | 220 +- - plat/st/stm32mp1/stm32mp1_dbgmcu.c | 153 ++ - plat/st/stm32mp1/stm32mp1_def.h | 441 +++- - plat/st/stm32mp1/stm32mp1_dt.c | 476 ----- - plat/st/stm32mp1/stm32mp1_gic.c | 173 +- - plat/st/stm32mp1/stm32mp1_helper.S | 248 ++- - plat/st/stm32mp1/stm32mp1_helper_dbg.S | 227 ++ - plat/st/stm32mp1/stm32mp1_low_power.c | 311 +++ - plat/st/stm32mp1/stm32mp1_pm.c | 118 +- - plat/st/stm32mp1/stm32mp1_power_config.c | 193 ++ - plat/st/stm32mp1/stm32mp1_private.c | 379 ++++ - plat/st/stm32mp1/stm32mp1_security.c | 91 +- - plat/st/stm32mp1/stm32mp1_shared_resources.c | 833 ++++++++ - plat/st/stm32mp1/stm32mp1_syscfg.c | 144 ++ - plat/st/stm32mp1/stm32mp1_usb_desc.c | 401 ++++ - tools/cert_create/Makefile | 18 +- - tools/doimage/Makefile | 20 +- - tools/fiptool/Makefile | 14 +- - tools/stm32image/Makefile | 20 +- - tools/stm32image/stm32image.c | 2 +- - 237 files changed, 34905 insertions(+), 4745 deletions(-) + CONTRIBUTING.md | 30 + + Makefile | 2 + + bl1/aarch32/bl1_entrypoint.S | 9 + + bl2/aarch32/bl2_el3_exceptions.S | 9 + + bl2/aarch32/bl2_entrypoint.S | 9 + + bl2/bl2_image_load_v2.c | 14 +- + bl2u/aarch32/bl2u_entrypoint.S | 9 + + bl32/sp_min/aarch32/entrypoint.S | 9 + + common/aarch32/debug.S | 54 +- + common/bl_common.c | 2 +- + docs/devicetree/bindings/arm/secure.txt | 53 + + .../bindings/clock/st,stm32mp1-rcc.txt | 488 ++++ + docs/devicetree/bindings/i2c/i2c-stm32.txt | 54 + + .../memory-controllers/st,stm32mp1-ddr.txt | 301 +++ + docs/devicetree/bindings/mmc/mmci.txt | 72 + + .../bindings/mmc/st,stm32-sdmmc2.txt | 22 + + .../bindings/power/st,stm32mp1-pwr.txt | 42 + + docs/devicetree/bindings/power/st,stpmic1.txt | 94 + + .../bindings/reset/st,stm32mp1-rcc.txt | 6 + + docs/devicetree/bindings/rng/st,stm32-rng.txt | 23 + + .../bindings/serial/st,stm32-usart.txt | 88 + + .../bindings/soc/st,stm32-etzpc.txt | 56 + + .../bindings/soc/st,stm32-romem.txt | 74 + + .../bindings/soc/st,stm32-stgen.txt | 18 + + .../devicetree/bindings/soc/st,stm32-tamp.txt | 22 + + .../bindings/watchdog/st,stm32-iwdg.txt | 28 + + docs/getting_started/porting-guide.rst | 30 + + docs/plat/stm32mp1.rst | 23 +- + drivers/arm/tzc/tzc400.c | 151 +- + .../intel/soc/stratix10/io/s10_memmap_qspi.c | 18 +- + drivers/io/io_block.c | 60 +- + drivers/io/io_fip.c | 6 +- + drivers/io/io_memmap.c | 30 +- + drivers/io/io_mtd.c | 248 ++ + drivers/io/io_semihosting.c | 6 +- + drivers/io/io_storage.c | 2 +- + drivers/mmc/mmc.c | 67 +- + drivers/mtd/nand/core.c | 118 + + drivers/mtd/nand/raw_nand.c | 446 ++++ + drivers/mtd/nand/spi_nand.c | 320 +++ + drivers/mtd/nor/spi_nor.c | 387 +++ + drivers/mtd/spi-mem/spi_mem.c | 288 +++ + drivers/renesas/rcar/io/io_emmcdrv.c | 20 +- + drivers/renesas/rcar/io/io_memdrv.c | 19 +- + drivers/st/bsec/{bsec.c => bsec2.c} | 460 ++-- + drivers/st/clk/stm32mp1_calib.c | 529 +++++ + drivers/st/clk/stm32mp1_clk.c | 2105 ++++++++++++++--- + drivers/st/clk/stm32mp_clkfunc.c | 237 +- + drivers/st/crypto/stm32_hash.c | 15 +- + drivers/st/ddr/stm32mp1_ddr.c | 308 ++- + drivers/st/ddr/stm32mp1_ddr_helpers.c | 572 ++++- + drivers/st/ddr/stm32mp1_ram.c | 133 +- + drivers/st/etzpc/etzpc.c | 310 +++ + drivers/st/fmc/stm32_fmc2_nand.c | 883 +++++++ + drivers/st/gpio/stm32_gpio.c | 8 + + drivers/st/i2c/stm32_i2c.c | 441 +++- + drivers/st/io/io_mmc.c | 26 +- + drivers/st/io/io_programmer_st_usb.c | 381 +++ + drivers/st/io/io_stm32image.c | 205 +- + drivers/st/iwdg/stm32_iwdg.c | 140 ++ + drivers/st/mmc/stm32_sdmmc2.c | 127 +- + drivers/st/pmic/stm32mp_pmic.c | 522 +++- + drivers/st/pmic/stpmic1.c | 116 +- + .../st/regulator/stm32mp_dummy_regulator.c | 27 + + drivers/st/regulator/stm32mp_regulator.c | 38 + + drivers/st/reset/stm32mp1_reset.c | 44 +- + drivers/st/rng/stm32_rng.c | 188 ++ + drivers/st/rtc/stm32_rtc.c | 479 ++++ + drivers/st/scmi-msg/base.c | 202 ++ + drivers/st/scmi-msg/base.h | 75 + + drivers/st/scmi-msg/clock.c | 388 +++ + drivers/st/scmi-msg/clock.h | 150 ++ + drivers/st/scmi-msg/common.h | 136 ++ + drivers/st/scmi-msg/entry.c | 63 + + drivers/st/scmi-msg/reset_domain.c | 202 ++ + drivers/st/scmi-msg/reset_domain.h | 122 + + drivers/st/scmi-msg/smt.c | 206 ++ + drivers/st/spi/stm32_qspi.c | 507 ++++ + drivers/st/tamper/stm32_tamp.c | 377 +++ + drivers/st/timer/stm32_timer.c | 316 +++ + drivers/st/uart/aarch32/stm32_console.S | 23 +- + drivers/st/uart/io_programmer_uart.c | 587 +++++ + drivers/st/uart/stm32mp1xx_hal_uart.c | 801 +++++++ + drivers/st/usb_dwc2/usb_dwc2.c | 859 +++++++ + fdts/stm32mp15-ddr.dtsi | 2 + + fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 49 +- + fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 49 +- + fdts/stm32mp15-pinctrl.dtsi | 292 +++ + fdts/stm32mp151.dtsi | 683 ++++++ + fdts/stm32mp153.dtsi | 20 + + fdts/stm32mp157-pinctrl.dtsi | 348 --- + fdts/stm32mp157.dtsi | 7 + + fdts/stm32mp157a-avenger96.dts | 255 +- + fdts/stm32mp157a-dk1.dts | 308 +-- + fdts/stm32mp157a-ed1.dts | 46 + + fdts/stm32mp157a-ev1.dts | 23 + + fdts/stm32mp157c-dk2.dts | 41 +- + fdts/stm32mp157c-ed1.dts | 316 +-- + fdts/stm32mp157c-ev1.dts | 51 +- + fdts/stm32mp157c-security.dtsi | 41 - + fdts/stm32mp157c.dtsi | 366 --- + fdts/stm32mp157caa-pinctrl.dtsi | 90 - + fdts/stm32mp157cac-pinctrl.dtsi | 78 - + fdts/stm32mp157d-dk1.dts | 49 + + fdts/stm32mp157d-ed1.dts | 46 + + fdts/stm32mp157d-ev1.dts | 22 + + fdts/stm32mp157f-dk2.dts | 55 + + fdts/stm32mp157f-ed1.dts | 51 + + fdts/stm32mp157f-ev1.dts | 22 + + fdts/stm32mp15xa.dtsi | 13 + + fdts/stm32mp15xc.dtsi | 21 + + fdts/stm32mp15xd.dtsi | 19 + + fdts/stm32mp15xf.dtsi | 21 + + fdts/stm32mp15xx-dkx.dtsi | 470 ++++ + fdts/stm32mp15xx-edx.dtsi | 479 ++++ + fdts/stm32mp15xx-evx.dtsi | 71 + + fdts/stm32mp15xxaa-pinctrl.dtsi | 86 + + fdts/stm32mp15xxab-pinctrl.dtsi | 57 + + fdts/stm32mp15xxac-pinctrl.dtsi | 74 + + fdts/stm32mp15xxad-pinctrl.dtsi | 57 + + include/arch/aarch32/arch.h | 18 +- + include/arch/aarch32/arch_helpers.h | 4 + + include/arch/aarch32/el3_common_macros.S | 10 +- + include/arch/aarch64/arch.h | 6 +- + include/common/confine_array_index.h | 145 ++ + include/common/speculation_barrier.h | 508 ++++ + include/drivers/arm/tzc400.h | 39 +- + include/drivers/io/io_driver.h | 2 +- + include/drivers/io/io_mtd.h | 59 + + include/drivers/io/io_storage.h | 7 +- + include/drivers/mmc.h | 27 +- + include/drivers/nand.h | 55 + + include/drivers/raw_nand.h | 188 ++ + include/drivers/spi_mem.h | 130 + + include/drivers/spi_nand.h | 49 + + include/drivers/spi_nor.h | 58 + + include/drivers/st/bsec.h | 152 +- + include/drivers/st/bsec2_reg.h | 98 + + include/drivers/st/etzpc.h | 32 + + include/drivers/st/io_programmer.h | 51 + + include/drivers/st/io_programmer_st_usb.h | 12 + + include/drivers/st/io_stm32image.h | 2 +- + include/drivers/st/io_uart.h | 12 + + include/drivers/st/scmi-msg.h | 207 ++ + include/drivers/st/scmi.h | 29 + + include/drivers/st/stm32_fmc2_nand.h | 12 + + include/drivers/st/stm32_i2c.h | 41 +- + include/drivers/st/stm32_iwdg.h | 1 + + include/drivers/st/stm32_qspi.h | 12 + + include/drivers/st/stm32_rng.h | 13 + + include/drivers/st/stm32_rtc.h | 78 + + include/drivers/st/stm32_sdmmc2.h | 2 + + include/drivers/st/stm32_tamp.h | 163 ++ + include/drivers/st/stm32_timer.h | 21 + + include/drivers/st/stm32mp1_calib.h | 20 + + include/drivers/st/stm32mp1_clk.h | 56 +- + include/drivers/st/stm32mp1_ddr.h | 7 +- + include/drivers/st/stm32mp1_ddr_helpers.h | 19 +- + include/drivers/st/stm32mp1_ddr_regs.h | 2 + + include/drivers/st/stm32mp1_pwr.h | 21 +- + include/drivers/st/stm32mp1_rcc.h | 29 +- + include/drivers/st/stm32mp1xx_hal.h | 204 ++ + include/drivers/st/stm32mp1xx_hal_uart.h | 1586 +++++++++++++ + include/drivers/st/stm32mp1xx_hal_uart_ex.h | 88 + + include/drivers/st/stm32mp_clkfunc.h | 16 +- + include/drivers/st/stm32mp_dummy_regulator.h | 14 + + include/drivers/st/stm32mp_pmic.h | 41 +- + include/drivers/st/stm32mp_regulator.h | 31 + + include/drivers/st/stm32mp_reset.h | 39 +- + include/drivers/st/stpmic1.h | 29 +- + include/drivers/st/usb_dwc2.h | 443 ++++ + include/dt-bindings/clock/stm32mp1-clks.h | 35 +- + include/dt-bindings/pinctrl/stm32-pinfunc.h | 9 +- + include/dt-bindings/power/stm32mp1-power.h | 19 + + include/dt-bindings/reset/stm32mp1-resets.h | 13 + + include/dt-bindings/soc/st,stm32-etzpc.h | 107 + + include/lib/optee_utils.h | 1 + + include/lib/usb/usb_core.h | 353 +++ + include/lib/usb/usb_st_dfu.h | 116 + + include/lib/utils_def.h | 19 + + .../lib/xlat_tables/xlat_tables_v2_helpers.h | 41 +- + include/plat/common/platform.h | 7 +- + lib/compiler-rt/builtins/arm/aeabi_ldivmod.S | 46 + + lib/compiler-rt/builtins/divdi3.c | 29 + + lib/compiler-rt/builtins/divmoddi4.c | 25 + + lib/compiler-rt/builtins/popcountdi2.c | 36 + + lib/compiler-rt/builtins/popcountsi2.c | 33 + + lib/compiler-rt/compiler-rt.mk | 14 +- + lib/optee/optee_utils.c | 30 + + lib/usb/usb_core.c | 733 ++++++ + lib/usb/usb_st_dfu.c | 865 +++++++ + lib/xlat_tables/aarch32/xlat_tables.c | 9 + + lib/xlat_tables/aarch64/xlat_tables.c | 4 + + lib/xlat_tables/xlat_tables_common.c | 18 + + lib/xlat_tables_v2/xlat_tables_core.c | 7 +- + make_helpers/defaults.mk | 3 + + plat/common/aarch32/platform_helpers.S | 34 + + plat/common/plat_bl_common.c | 2 +- + plat/st/common/bl2_io_storage.c | 434 +++- + plat/st/common/include/stm32mp_auth.h | 19 - + plat/st/common/include/stm32mp_common.h | 37 +- + plat/st/common/include/stm32mp_dt.h | 20 +- + .../st/common/include/stm32mp_shres_helpers.h | 65 +- + plat/st/common/stm32_gic.c | 223 ++ + plat/st/common/stm32mp_auth.c | 90 - + plat/st/common/stm32mp_common.c | 148 +- + plat/st/common/stm32mp_cot.c | 114 + + plat/st/common/stm32mp_crypto_lib.c | 174 ++ + plat/st/common/stm32mp_dt.c | 432 +++- + plat/st/common/stm32mp_img_parser_lib.c | 75 + + plat/st/common/stm32mp_shres_helpers.c | 63 + + plat/st/common/stm32mp_trusted_boot.c | 76 + + plat/st/stm32mp1/bl2_plat_setup.c | 374 ++- + plat/st/stm32mp1/include/boot_api.h | 286 ++- + plat/st/stm32mp1/include/platform_def.h | 15 + + .../stm32mp1/include/stm32mp1_boot_device.h | 18 + + plat/st/stm32mp1/include/stm32mp1_context.h | 20 +- + plat/st/stm32mp1/include/stm32mp1_low_power.h | 19 + + .../stm32mp1/include/stm32mp1_power_config.h | 28 + + plat/st/stm32mp1/include/stm32mp1_private.h | 19 +- + .../include/stm32mp1_shared_resources.h | 132 ++ + plat/st/stm32mp1/include/stm32mp1_smc.h | 148 +- + plat/st/stm32mp1/include/stm32mp1_usb_desc.h | 55 + + plat/st/stm32mp1/include/usb_ctx.h | 17 + + plat/st/stm32mp1/plat_image_load.c | 68 +- + plat/st/stm32mp1/platform.mk | 141 +- + plat/st/stm32mp1/services/bsec_svc.c | 466 +++- + plat/st/stm32mp1/services/low_power_svc.c | 22 + + plat/st/stm32mp1/services/low_power_svc.h | 14 + + plat/st/stm32mp1/services/pwr_svc.c | 102 + + plat/st/stm32mp1/services/pwr_svc.h | 12 + + plat/st/stm32mp1/services/rcc_svc.c | 172 ++ + plat/st/stm32mp1/services/rcc_svc.h | 14 + + .../st/stm32mp1/services/stm32mp1_svc_setup.c | 38 +- + plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 24 +- + plat/st/stm32mp1/sp_min/sp_min_setup.c | 318 ++- + plat/st/stm32mp1/stm32mp1_boot_device.c | 168 ++ + plat/st/stm32mp1/stm32mp1_context.c | 391 ++- + plat/st/stm32mp1/stm32mp1_dbgmcu.c | 36 +- + plat/st/stm32mp1/stm32mp1_def.h | 304 ++- + plat/st/stm32mp1/stm32mp1_gic.c | 92 - + plat/st/stm32mp1/stm32mp1_helper.S | 220 +- + plat/st/stm32mp1/stm32mp1_low_power.c | 346 +++ + plat/st/stm32mp1/stm32mp1_pm.c | 96 +- + plat/st/stm32mp1/stm32mp1_power_config.c | 187 ++ + plat/st/stm32mp1/stm32mp1_private.c | 534 ++++- + plat/st/stm32mp1/stm32mp1_scmi.c | 582 +++++ + plat/st/stm32mp1/stm32mp1_security.c | 7 +- + plat/st/stm32mp1/stm32mp1_shared_resources.c | 743 ++++++ + plat/st/stm32mp1/stm32mp1_syscfg.c | 63 +- + plat/st/stm32mp1/stm32mp1_usb_desc.c | 418 ++++ + tools/stm32image/stm32image.c | 46 +- + 252 files changed, 34319 insertions(+), 3715 deletions(-) + create mode 100644 CONTRIBUTING.md create mode 100644 docs/devicetree/bindings/arm/secure.txt create mode 100644 docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt create mode 100644 docs/devicetree/bindings/i2c/i2c-stm32.txt + create mode 100644 docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt create mode 100644 docs/devicetree/bindings/mmc/mmci.txt create mode 100644 docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt create mode 100644 docs/devicetree/bindings/power/st,stm32mp1-pwr.txt @@ -257,272 +274,213 @@ Subject: [PATCH] st update r1 create mode 100644 docs/devicetree/bindings/soc/st,stm32-stgen.txt create mode 100644 docs/devicetree/bindings/soc/st,stm32-tamp.txt create mode 100644 docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt - create mode 100644 drivers/console/aarch32/deprecated_console.S - create mode 100644 drivers/console/aarch32/multi_console.S - create mode 100644 drivers/st/bsec/bsec.c - create mode 100644 drivers/st/clk/stm32mp_clkfunc.c + create mode 100644 drivers/io/io_mtd.c + create mode 100644 drivers/mtd/nand/core.c + create mode 100644 drivers/mtd/nand/raw_nand.c + create mode 100644 drivers/mtd/nand/spi_nand.c + create mode 100644 drivers/mtd/nor/spi_nor.c + create mode 100644 drivers/mtd/spi-mem/spi_mem.c + rename drivers/st/bsec/{bsec.c => bsec2.c} (65%) + create mode 100644 drivers/st/clk/stm32mp1_calib.c create mode 100644 drivers/st/etzpc/etzpc.c - create mode 100644 drivers/st/hash/hash_sec.c - create mode 100644 drivers/st/i2c/stm32_i2c.c - create mode 100644 drivers/st/io/io_mmc.c + create mode 100644 drivers/st/fmc/stm32_fmc2_nand.c create mode 100644 drivers/st/io/io_programmer_st_usb.c - create mode 100644 drivers/st/io/io_stm32image.c - create mode 100644 drivers/st/iwdg/stm32_iwdg.c - create mode 100644 drivers/st/mmc/stm32_sdmmc2.c - create mode 100644 drivers/st/nand/io_nand.c - create mode 100644 drivers/st/nand/nand.c - delete mode 100644 drivers/st/pmic/stm32_i2c.c - delete mode 100644 drivers/st/pmic/stm32mp1_pmic.c - create mode 100644 drivers/st/pmic/stm32mp_pmic.c - create mode 100644 drivers/st/pmic/stpmic1.c - delete mode 100644 drivers/st/pmic/stpmu1.c - create mode 100644 drivers/st/qspi/io_qspi.c + create mode 100644 drivers/st/regulator/stm32mp_dummy_regulator.c + create mode 100644 drivers/st/regulator/stm32mp_regulator.c create mode 100644 drivers/st/rng/stm32_rng.c create mode 100644 drivers/st/rtc/stm32_rtc.c + create mode 100644 drivers/st/scmi-msg/base.c + create mode 100644 drivers/st/scmi-msg/base.h + create mode 100644 drivers/st/scmi-msg/clock.c + create mode 100644 drivers/st/scmi-msg/clock.h + create mode 100644 drivers/st/scmi-msg/common.h + create mode 100644 drivers/st/scmi-msg/entry.c + create mode 100644 drivers/st/scmi-msg/reset_domain.c + create mode 100644 drivers/st/scmi-msg/reset_domain.h + create mode 100644 drivers/st/scmi-msg/smt.c + create mode 100644 drivers/st/spi/stm32_qspi.c create mode 100644 drivers/st/tamper/stm32_tamp.c create mode 100644 drivers/st/timer/stm32_timer.c create mode 100644 drivers/st/uart/io_programmer_uart.c create mode 100644 drivers/st/uart/stm32mp1xx_hal_uart.c create mode 100644 drivers/st/usb_dwc2/usb_dwc2.c - create mode 100644 fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi - create mode 100644 fdts/stm32mp157a-dk1.dts - create mode 100644 fdts/stm32mp157c-dk2.dts - create mode 100644 fdts/stm32mp157c-security.dtsi - create mode 100644 fdts/stm32mp157cab-pinctrl.dtsi - create mode 100644 fdts/stm32mp157cac-pinctrl.dtsi - create mode 100644 fdts/stm32mp157cad-pinctrl.dtsi - create mode 100644 include/common/aarch32/console_macros.S - create mode 100644 include/drivers/st/bsec.h + create mode 100644 fdts/stm32mp15-pinctrl.dtsi + create mode 100644 fdts/stm32mp151.dtsi + create mode 100644 fdts/stm32mp153.dtsi + delete mode 100644 fdts/stm32mp157-pinctrl.dtsi + create mode 100644 fdts/stm32mp157.dtsi + create mode 100644 fdts/stm32mp157a-ed1.dts + create mode 100644 fdts/stm32mp157a-ev1.dts + delete mode 100644 fdts/stm32mp157c-security.dtsi + delete mode 100644 fdts/stm32mp157c.dtsi + delete mode 100644 fdts/stm32mp157caa-pinctrl.dtsi + delete mode 100644 fdts/stm32mp157cac-pinctrl.dtsi + create mode 100644 fdts/stm32mp157d-dk1.dts + create mode 100644 fdts/stm32mp157d-ed1.dts + create mode 100644 fdts/stm32mp157d-ev1.dts + create mode 100644 fdts/stm32mp157f-dk2.dts + create mode 100644 fdts/stm32mp157f-ed1.dts + create mode 100644 fdts/stm32mp157f-ev1.dts + create mode 100644 fdts/stm32mp15xa.dtsi + create mode 100644 fdts/stm32mp15xc.dtsi + create mode 100644 fdts/stm32mp15xd.dtsi + create mode 100644 fdts/stm32mp15xf.dtsi + create mode 100644 fdts/stm32mp15xx-dkx.dtsi + create mode 100644 fdts/stm32mp15xx-edx.dtsi + create mode 100644 fdts/stm32mp15xx-evx.dtsi + create mode 100644 fdts/stm32mp15xxaa-pinctrl.dtsi + create mode 100644 fdts/stm32mp15xxab-pinctrl.dtsi + create mode 100644 fdts/stm32mp15xxac-pinctrl.dtsi + create mode 100644 fdts/stm32mp15xxad-pinctrl.dtsi + create mode 100644 include/common/confine_array_index.h + create mode 100644 include/common/speculation_barrier.h + create mode 100644 include/drivers/io/io_mtd.h + create mode 100644 include/drivers/nand.h + create mode 100644 include/drivers/raw_nand.h + create mode 100644 include/drivers/spi_mem.h + create mode 100644 include/drivers/spi_nand.h + create mode 100644 include/drivers/spi_nor.h + create mode 100644 include/drivers/st/bsec2_reg.h create mode 100644 include/drivers/st/etzpc.h - create mode 100644 include/drivers/st/hash_sec.h - create mode 100644 include/drivers/st/io_mmc.h - create mode 100644 include/drivers/st/io_nand.h create mode 100644 include/drivers/st/io_programmer.h create mode 100644 include/drivers/st/io_programmer_st_usb.h - create mode 100644 include/drivers/st/io_qspi.h - create mode 100644 include/drivers/st/io_stm32image.h create mode 100644 include/drivers/st/io_uart.h - create mode 100644 include/drivers/st/nand.h - create mode 100644 include/drivers/st/stm32_console.h - create mode 100644 include/drivers/st/stm32_hal_hash_reg.h - create mode 100644 include/drivers/st/stm32_iwdg.h + create mode 100644 include/drivers/st/scmi-msg.h + create mode 100644 include/drivers/st/scmi.h + create mode 100644 include/drivers/st/stm32_fmc2_nand.h + create mode 100644 include/drivers/st/stm32_qspi.h create mode 100644 include/drivers/st/stm32_rng.h create mode 100644 include/drivers/st/stm32_rtc.h - create mode 100644 include/drivers/st/stm32_sdmmc2.h create mode 100644 include/drivers/st/stm32_tamp.h create mode 100644 include/drivers/st/stm32_timer.h - create mode 100644 include/drivers/st/stm32_uart_regs.h - delete mode 100644 include/drivers/st/stm32mp1_pmic.h - delete mode 100644 include/drivers/st/stm32mp1_reset.h + create mode 100644 include/drivers/st/stm32mp1_calib.h create mode 100644 include/drivers/st/stm32mp1xx_hal.h create mode 100644 include/drivers/st/stm32mp1xx_hal_uart.h create mode 100644 include/drivers/st/stm32mp1xx_hal_uart_ex.h - create mode 100644 include/drivers/st/stm32mp_clkfunc.h - create mode 100644 include/drivers/st/stm32mp_pmic.h - create mode 100644 include/drivers/st/stm32mp_reset.h - create mode 100644 include/drivers/st/stpmic1.h - delete mode 100644 include/drivers/st/stpmu1.h + create mode 100644 include/drivers/st/stm32mp_dummy_regulator.h + create mode 100644 include/drivers/st/stm32mp_regulator.h create mode 100644 include/drivers/st/usb_dwc2.h - create mode 100644 include/dt-bindings/interrupt-controller/arm-gic.h create mode 100644 include/dt-bindings/power/stm32mp1-power.h create mode 100644 include/dt-bindings/soc/st,stm32-etzpc.h create mode 100644 include/lib/usb/usb_core.h create mode 100644 include/lib/usb/usb_st_dfu.h - create mode 100644 lib/compiler-rt/builtins/lshrdi3.c + create mode 100644 lib/compiler-rt/builtins/arm/aeabi_ldivmod.S + create mode 100644 lib/compiler-rt/builtins/divdi3.c + create mode 100644 lib/compiler-rt/builtins/divmoddi4.c + create mode 100644 lib/compiler-rt/builtins/popcountdi2.c + create mode 100644 lib/compiler-rt/builtins/popcountsi2.c create mode 100644 lib/usb/usb_core.c create mode 100644 lib/usb/usb_st_dfu.c - create mode 100644 plat/common/aarch32/crash_console_helpers.S - create mode 100644 plat/common/aarch64/crash_console_helpers.S - create mode 100644 plat/st/common/bl2_io_storage.c - create mode 100644 plat/st/common/include/stm32mp_auth.h - create mode 100644 plat/st/common/include/stm32mp_common.h - create mode 100644 plat/st/common/include/stm32mp_dt.h - create mode 100644 plat/st/common/include/stm32mp_shres_helpers.h - create mode 100644 plat/st/common/stm32mp_auth.c - create mode 100644 plat/st/common/stm32mp_common.c - create mode 100644 plat/st/common/stm32mp_dt.c + delete mode 100644 plat/st/common/include/stm32mp_auth.h + create mode 100644 plat/st/common/stm32_gic.c + delete mode 100644 plat/st/common/stm32mp_auth.c + create mode 100644 plat/st/common/stm32mp_cot.c + create mode 100644 plat/st/common/stm32mp_crypto_lib.c + create mode 100644 plat/st/common/stm32mp_img_parser_lib.c create mode 100644 plat/st/common/stm32mp_shres_helpers.c - delete mode 100644 plat/st/stm32mp1/bl2_io_storage.c - create mode 100644 plat/st/stm32mp1/include/stm32mp1_dbgmcu.h - delete mode 100644 plat/st/stm32mp1/include/stm32mp1_dt.h + create mode 100644 plat/st/common/stm32mp_trusted_boot.c + create mode 100644 plat/st/stm32mp1/include/stm32mp1_boot_device.h create mode 100644 plat/st/stm32mp1/include/stm32mp1_low_power.h create mode 100644 plat/st/stm32mp1/include/stm32mp1_power_config.h create mode 100644 plat/st/stm32mp1/include/stm32mp1_shared_resources.h - create mode 100644 plat/st/stm32mp1/include/stm32mp1_smc.h create mode 100644 plat/st/stm32mp1/include/stm32mp1_usb_desc.h create mode 100644 plat/st/stm32mp1/include/usb_ctx.h - create mode 100644 plat/st/stm32mp1/services/bsec_svc.c - create mode 100644 plat/st/stm32mp1/services/bsec_svc.h create mode 100644 plat/st/stm32mp1/services/low_power_svc.c create mode 100644 plat/st/stm32mp1/services/low_power_svc.h create mode 100644 plat/st/stm32mp1/services/pwr_svc.c create mode 100644 plat/st/stm32mp1/services/pwr_svc.h create mode 100644 plat/st/stm32mp1/services/rcc_svc.c create mode 100644 plat/st/stm32mp1/services/rcc_svc.h - create mode 100644 plat/st/stm32mp1/services/stm32mp1_svc_setup.c - delete mode 100644 plat/st/stm32mp1/stm32mp1_common.c - create mode 100644 plat/st/stm32mp1/stm32mp1_dbgmcu.c - delete mode 100644 plat/st/stm32mp1/stm32mp1_dt.c - create mode 100644 plat/st/stm32mp1/stm32mp1_helper_dbg.S + create mode 100644 plat/st/stm32mp1/stm32mp1_boot_device.c + delete mode 100644 plat/st/stm32mp1/stm32mp1_gic.c create mode 100644 plat/st/stm32mp1/stm32mp1_low_power.c create mode 100644 plat/st/stm32mp1/stm32mp1_power_config.c - create mode 100644 plat/st/stm32mp1/stm32mp1_private.c + create mode 100644 plat/st/stm32mp1/stm32mp1_scmi.c create mode 100644 plat/st/stm32mp1/stm32mp1_shared_resources.c - create mode 100644 plat/st/stm32mp1/stm32mp1_syscfg.c create mode 100644 plat/st/stm32mp1/stm32mp1_usb_desc.c -diff --git a/.checkpatch.conf b/.checkpatch.conf -index 63bdf7b..066207b 100644 ---- a/.checkpatch.conf -+++ b/.checkpatch.conf -@@ -93,3 +93,21 @@ - # "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt" - # We allow the usage of the volatile keyword in TF. - --ignore VOLATILE +diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md +new file mode 100644 +index 000000000..3d1bacd78 +--- /dev/null ++++ b/CONTRIBUTING.md +@@ -0,0 +1,30 @@ ++# Contributing guide + -+# PREFER_KERNEL_TYPES reports this kind of messages (when using --strict): -+# "Prefer kernel type 'u32' over 'uint32_t'" -+--ignore PREFER_KERNEL_TYPES ++This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you. + -+# USLEEP_RANGE reports this kind of messages (when using --strict): -+# "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt" -+--ignore USLEEP_RANGE ++This guide mainly focuses on the proper use of Git. + -+# COMPARISON_TO_NULL reports this kind of messages (when using --strict): -+# Comparison to NULL could be written "" -+--ignore COMPARISON_TO_NULL ++## 1. Issues + -+# UNNECESSARY_PARENTHESES reports this kind of messages (when using --strict): -+# Unnecessary parentheses around "" -+--ignore UNNECESSARY_PARENTHESES ++STM32MPU projects do not activate "Github issues" feature for the time being. If you need to report an issue or question about this project deliverables, you can report them using [ ST Support Center ](https://my.st.com/ols#/ols/newrequest) or [ ST Community MPU Forum ](https://community.st.com/s/topic/0TO0X0000003u2AWAQ/stm32-mpus). + -+--ignore BRACES ++## 2. Pull Requests ++ ++STMicrolectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure. ++ ++* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual CLA (https://cla.st.com). ++* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate CLA (https://cla.st.com) mentioning your GitHub account name. ++* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account you can check here (https://cla.st.com). ++ ++Please note that: ++* The Corporate CLA will always take precedence over the Individual CLA. ++* One CLA submission is sufficient, for any project proposed by STMicroelectronics. ++ ++__How to proceed__ ++ ++* We recommend to fork the project in your GitHub account to further develop your contribution. Please use the latest commit version. ++* Please, submit one Pull Request for one new feature or proposal. This will ease the analysis and final merge if accepted. ++ ++__Note__ ++ ++Merge will not be done directly in GitHub but it will need first to follow internal integration process before public deliver in a standard release. The Pull request will stay open until it is merged and delivered. diff --git a/Makefile b/Makefile -index 23a1b0a..cda7e7d 100644 +index 721246d51..864eda7fc 100644 --- a/Makefile +++ b/Makefile -@@ -187,8 +187,48 @@ TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align - ASFLAGS_aarch32 = $(march32-directive) - ASFLAGS_aarch64 = -march=armv8-a - -+WARNING1 := -Wextra -+WARNING1 += -Wunused -Wno-unused-parameter -+WARNING1 += -Wmissing-declarations -+WARNING1 += -Wmissing-format-attribute -+WARNING1 += -Wmissing-prototypes -+WARNING1 += -Wold-style-definition -+WARNING1 += -Wunused-but-set-variable -+WARNING1 += -Wunused-const-variable -+ -+WARNING2 := -Waggregate-return -+WARNING2 += -Wcast-align -+WARNING2 += -Wdisabled-optimization -+WARNING2 += -Wnested-externs -+WARNING2 += -Wshadow -+WARNING2 += -Wlogical-op -+WARNING2 += -Wmissing-field-initializers -+WARNING2 += -Wsign-compare -+WARNING2 += -Wmaybe-uninitialized -+ -+WARNING3 := -Wbad-function-cast -+WARNING3 += -Wcast-qual -+WARNING3 += -Wconversion -+WARNING3 += -Wpacked -+WARNING3 += -Wpadded -+WARNING3 += -Wpointer-arith -+WARNING3 += -Wredundant-decls -+WARNING3 += -Wswitch-default -+WARNING3 += -Wpacked-bitfield-compat -+WARNING3 += -Wvla -+ -+ifeq (${W},1) -+WARN_OR_ERROR := $(WARNING1) -+else ifeq (${W},2) -+WARN_OR_ERROR := $(WARNING1) $(WARNING2) -+else ifeq (${W},3) -+WARN_OR_ERROR := $(WARNING1) $(WARNING2) $(WARNING3) -+else -+WARN_OR_ERROR := -Werror -+endif -+ - CPPFLAGS = ${DEFINES} ${INCLUDES} ${MBEDTLS_INC} -nostdinc \ -- -Wmissing-include-dirs -Werror -+ -Wmissing-include-dirs $(WARN_OR_ERROR) - ASFLAGS += $(CPPFLAGS) $(ASFLAGS_$(ARCH)) \ - -D__ASSEMBLY__ -ffreestanding \ - -Wa,--fatal-warnings -@@ -396,12 +436,6 @@ ifeq ($(HW_ASSISTED_COHERENCY)-$(USE_COHERENT_MEM),1-1) - $(error USE_COHERENT_MEM cannot be enabled with HW_ASSISTED_COHERENCY) - endif - --ifneq ($(MULTI_CONSOLE_API), 0) -- ifeq (${ARCH},aarch32) -- $(error "Error: MULTI_CONSOLE_API is not supported for AArch32") -- endif --endif -- - #For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1. - ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1) - $(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled") -@@ -592,6 +626,7 @@ $(eval $(call assert_boolean,USE_TBBR_DEFS)) - $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY)) - $(eval $(call assert_boolean,BL2_AT_EL3)) +@@ -700,6 +700,7 @@ $(eval $(call assert_boolean,BL2_AT_EL3)) $(eval $(call assert_boolean,BL2_IN_XIP_MEM)) + $(eval $(call assert_boolean,BL2_INV_DCACHE)) + $(eval $(call assert_boolean,USE_SPINLOCK_CAS)) +$(eval $(call assert_boolean,AARCH32_EXCEPTION_DEBUG)) $(eval $(call assert_numeric,ARM_ARCH_MAJOR)) $(eval $(call assert_numeric,ARM_ARCH_MINOR)) -@@ -644,6 +679,7 @@ $(eval $(call add_define,USE_TBBR_DEFS)) - $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY)) - $(eval $(call add_define,BL2_AT_EL3)) +@@ -766,6 +767,7 @@ $(eval $(call add_define,BL2_AT_EL3)) $(eval $(call add_define,BL2_IN_XIP_MEM)) + $(eval $(call add_define,BL2_INV_DCACHE)) + $(eval $(call add_define,USE_SPINLOCK_CAS)) +$(eval $(call add_define,AARCH32_EXCEPTION_DEBUG)) - # Define the EL3_PAYLOAD_BASE flag only if it is provided. - ifdef EL3_PAYLOAD_BASE -@@ -784,9 +820,11 @@ checkpatch: locate-checkpatch - for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \ - printf "\n[*] Checking style of '$$commit'\n\n"; \ - git log --format=email "$$commit~..$$commit" \ -- -- ${CHECK_PATHS} | ${CHECKPATCH} - || true; \ -+ -- ${CHECK_PATHS} | ${CHECKPATCH} --strict - || \ -+ true; \ - git diff --format=email "$$commit~..$$commit" \ -- -- ${CHECK_PATHS} | ${CHECKPATCH} - || true; \ -+ -- ${CHECK_PATHS} | ${CHECKPATCH} --strict - || \ -+ true; \ - done - - certtool: ${CRTTOOL} -diff --git a/bl2/aarch32/bl2_arch_setup.c b/bl2/aarch32/bl2_arch_setup.c -index db8a068..4fd8d07 100644 ---- a/bl2/aarch32/bl2_arch_setup.c -+++ b/bl2/aarch32/bl2_arch_setup.c -@@ -4,6 +4,7 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - -+#include "../bl2_private.h" - - /******************************************************************************* - * Place holder function to perform any Secure SVC specific architectural -diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S -index 0c7b064..437188e 100644 ---- a/bl2/aarch32/bl2_el3_entrypoint.S -+++ b/bl2/aarch32/bl2_el3_entrypoint.S -@@ -15,6 +15,10 @@ - - - func bl2_entrypoint -+#if STM32MP1_RESET_HALT_WORKAROUND -+ bl plat_dbg_attach_loop + ifeq (${SANITIZE_UB},trap) + $(eval $(call add_define,MONITOR_TRAPS)) +diff --git a/bl1/aarch32/bl1_entrypoint.S b/bl1/aarch32/bl1_entrypoint.S +index 6a155660b..e7e72049c 100644 +--- a/bl1/aarch32/bl1_entrypoint.S ++++ b/bl1/aarch32/bl1_entrypoint.S +@@ -21,10 +21,19 @@ + */ + vector_base bl1_vector_table + b bl1_entrypoint ++#if AARCH32_EXCEPTION_DEBUG ++ b report_undef_inst /* Undef */ ++#else + b report_exception /* Undef */ +#endif -+ - /* Save arguments x0-x3 from previous Boot loader */ - mov r9, r0 - mov r10, r1 + b bl1_aarch32_smc_handler /* SMC call */ ++#if AARCH32_EXCEPTION_DEBUG ++ b report_prefetch_abort /* Prefetch abort */ ++ b report_data_abort /* Data abort */ ++#else + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ ++#endif + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ diff --git a/bl2/aarch32/bl2_el3_exceptions.S b/bl2/aarch32/bl2_el3_exceptions.S -index 11ddf37..7058b07 100644 +index 087b6656d..dff4e36a4 100644 --- a/bl2/aarch32/bl2_el3_exceptions.S +++ b/bl2/aarch32/bl2_el3_exceptions.S @@ -12,10 +12,19 @@ @@ -546,10 +504,10 @@ index 11ddf37..7058b07 100644 b report_exception /* IRQ */ b report_exception /* FIQ */ diff --git a/bl2/aarch32/bl2_entrypoint.S b/bl2/aarch32/bl2_entrypoint.S -index d215f48..f76c1c9 100644 +index 102fd2f51..bfd721ca1 100644 --- a/bl2/aarch32/bl2_entrypoint.S +++ b/bl2/aarch32/bl2_entrypoint.S -@@ -15,10 +15,19 @@ +@@ -14,10 +14,19 @@ vector_base bl2_vector_table b bl2_entrypoint @@ -570,10 +528,10 @@ index d215f48..f76c1c9 100644 b report_exception /* IRQ */ b report_exception /* FIQ */ diff --git a/bl2/bl2_image_load_v2.c b/bl2/bl2_image_load_v2.c -index 0f40785..2e3e145 100644 +index dd53e1d2b..e89033b96 100644 --- a/bl2/bl2_image_load_v2.c +++ b/bl2/bl2_image_load_v2.c -@@ -69,17 +69,17 @@ struct entry_point_info *bl2_load_images(void) +@@ -71,17 +71,17 @@ struct entry_point_info *bl2_load_images(void) ERROR("BL2: Failed to load image (%i)\n", err); plat_error_handler(err); } @@ -598,25 +556,11 @@ index 0f40785..2e3e145 100644 /* Go to next image */ bl2_node_info = bl2_node_info->next_load_info; } -diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h -index f93a179..8e602ff 100644 ---- a/bl2/bl2_private.h -+++ b/bl2/bl2_private.h -@@ -8,6 +8,9 @@ - #define __BL2_PRIVATE_H__ - - #if BL2_IN_XIP_MEM -+ -+#include -+ - /******************************************************************************* - * Declarations of linker defined symbols which will tell us where BL2 lives - * in Trusted ROM and RAM diff --git a/bl2u/aarch32/bl2u_entrypoint.S b/bl2u/aarch32/bl2u_entrypoint.S -index 7fb64f3..b511499 100644 +index 6391f537c..426176d98 100644 --- a/bl2u/aarch32/bl2u_entrypoint.S +++ b/bl2u/aarch32/bl2u_entrypoint.S -@@ -15,10 +15,19 @@ +@@ -14,10 +14,19 @@ vector_base bl2u_vector_table b bl2u_entrypoint @@ -637,7 +581,7 @@ index 7fb64f3..b511499 100644 b report_exception /* IRQ */ b report_exception /* FIQ */ diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S -index d6853cc..2d67af3 100644 +index 0a684754c..c4a6e8e83 100644 --- a/bl32/sp_min/aarch32/entrypoint.S +++ b/bl32/sp_min/aarch32/entrypoint.S @@ -44,10 +44,19 @@ @@ -661,7 +605,7 @@ index d6853cc..2d67af3 100644 b plat_panic_handler /* IRQ */ b sp_min_handle_fiq /* FIQ */ diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S -index f506356..a058645 100644 +index f50635691..a058645e3 100644 --- a/common/aarch32/debug.S +++ b/common/aarch32/debug.S @@ -7,9 +7,16 @@ @@ -763,9 +707,22 @@ index f506356..a058645 100644 - bx r3 + bx r7 endfunc asm_print_hex +diff --git a/common/bl_common.c b/common/bl_common.c +index e6f98029e..7f2342499 100644 +--- a/common/bl_common.c ++++ b/common/bl_common.c +@@ -215,7 +215,7 @@ int load_auth_image(unsigned int image_id, image_info_t *image_data) + + do { + err = load_auth_image_internal(image_id, image_data, 0); +- } while ((err != 0) && (plat_try_next_boot_source() != 0)); ++ } while ((err != 0) && (plat_try_next_boot_source(image_id) != 0)); + + return err; + } diff --git a/docs/devicetree/bindings/arm/secure.txt b/docs/devicetree/bindings/arm/secure.txt new file mode 100644 -index 0000000..e31303f +index 000000000..e31303fb2 --- /dev/null +++ b/docs/devicetree/bindings/arm/secure.txt @@ -0,0 +1,53 @@ @@ -824,10 +781,10 @@ index 0000000..e31303f + status = "disabled"; secure-status = "disabled"; /* disabled in both */ diff --git a/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt new file mode 100644 -index 0000000..7021486 +index 000000000..a082706ee --- /dev/null +++ b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt -@@ -0,0 +1,324 @@ +@@ -0,0 +1,488 @@ +STMicroelectronics STM32 Peripheral Reset Clock Controller +========================================================== + @@ -848,8 +805,10 @@ index 0000000..7021486 + "clocks" property, containing a phandle to the clock device node, + an index specifying the clock to use. +- #reset-cells: Shall be 1 -+- interrupts: Should contain a general interrupt line and a interrupt line -+ to the wake-up of processor (CSTOP). ++- interrupts: Should contain a general interrupt line. ++- secure-interrupts: Should contain a interrupt line to the wake-up of ++ processor (CSTOP). ++- secure-status: Relates to RCC TZ_ENABLE configuration to restrict RCC access. + +Example: + rcc: rcc@50000000 { @@ -857,17 +816,10 @@ index 0000000..7021486 + reg = <0x50000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; -+ interrupts = , -+ ; ++ interrupts = ; ++ secure-interrupts = ; + }; + -+Other properties: -+- secure-status: Relates to RCC TZ_ENABLE configuration to restrict RCC access. -+- st,clksrc : The clock sources configuration array in a platform specific order. -+- st,clkdiv : The clock dividers configuration array in a paltform specific order. -+- st,pll : A specific PLL configuration -+- st,pkcs : The peripheral kernel clock distribution configuration array. -+ +Specifying clocks +================= + @@ -900,83 +852,116 @@ index 0000000..7021486 +Defining clock source distribution with property st,clksrc +========================================================== + -+Property can be used to configure the clock distribution tree. -+When used, it shall describe the whole distribution tree. ++- st,clksrc : The clock sources configuration array in a platform specific ++ order. + -+For the STM32MP15x family there are 9 clock sources selector which are -+configured in the following order: ++ Property can be used to configure the clock distribution tree. ++ When used, it shall describe the whole distribution tree. ++ ++ For the STM32MP15x family there are 9 clock sources selector which are ++ configured in the following order: + MPU AXI MCU PLL12 PLL3 PLL4 RTC MCO1 MCO2 + -+Clock source configuration values are defined by macros CLK__ -+from dt-bindings/clock/stm32mp1-clksrc.h. -+ -+Example: -+ st,clksrc = < -+ CLK_MPU_PLL1P -+ CLK_AXI_PLL2P -+ CLK_MCU_PLL3P -+ CLK_PLL12_HSE -+ CLK_PLL3_HSE -+ CLK_PLL4_HSE -+ CLK_RTC_LSE -+ CLK_MCO1_DISABLED -+ CLK_MCO2_DISABLED -+ >; ++ Clock source configuration values are defined by macros CLK__ ++ from dt-bindings/clock/stm32mp1-clksrc.h. + ++ Example: ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MCU_PLL3P ++ CLK_PLL12_HSE ++ CLK_PLL3_HSE ++ CLK_PLL4_HSE ++ CLK_RTC_LSE ++ CLK_MCO1_DISABLED ++ CLK_MCO2_DISABLED ++ >; + +Defining clock dividers with property st,clkdiv +=============================================== + -+Property can be used to configure the clock main dividers value. -+When used, it shall describe the whole clock dividers tree. ++- st,clkdiv : The clock main dividers value specified in an array ++ in a platform specific order. + -+For the STM32MP15x family there are 11 dividers values expected. -+They shall be configured in the following order: -+ MPU AXI MCU APB1 APB2 APB3 APB4 APB5 RTC MCO1 MCO2 ++ When used, it shall describe the whole clock dividers tree. + -+The each divider value uses the DIV coding defined in RCC associated -+register RCC_xxxDIVR. In most cases, it is: ++ Property can be used to configure the clock main dividers value. ++ When used, it shall describe the whole clock dividers tree. ++ ++ For the STM32MP15x family there are 11 dividers values expected. ++ They shall be configured in the following order: ++ MPU AXI MCU APB1 APB2 APB3 APB4 APB5 RTC MCO1 MCO2 ++ ++ The each divider value uses the DIV coding defined in RCC associated ++ register RCC_xxxDIVR. In most cases, it is: + 0x0: not divided + 0x1: division by 2 + 0x2: division by 4 + 0x3: division by 8 + ... + -+Note that for RTC MCO1 MCO2, the coding is different: ++ Note that for RTC MCO1 MCO2, the coding is different: + 0x0: not divided + 0x1: division by 2 + 0x2: division by 3 + 0x3: division by 4 + ... + -+Example: -+ st,clkdiv = < -+ 1 /*MPU*/ -+ 0 /*AXI*/ -+ 0 /*MCU*/ -+ 1 /*APB1*/ -+ 1 /*APB2*/ -+ 1 /*APB3*/ -+ 1 /*APB4*/ -+ 2 /*APB5*/ -+ 23 /*RTC*/ -+ 0 /*MCO1*/ -+ 0 /*MCO2*/ -+ >; ++ Example: ++ st,clkdiv = < ++ 1 /*MPU*/ ++ 0 /*AXI*/ ++ 0 /*MCU*/ ++ 1 /*APB1*/ ++ 1 /*APB2*/ ++ 1 /*APB3*/ ++ 1 /*APB4*/ ++ 2 /*APB5*/ ++ 23 /*RTC*/ ++ 0 /*MCO1*/ ++ 0 /*MCO2*/ ++ >; + -+Defining peripheral PLL frequencies with property st,pll ++Optional Properties: ++Defining peripherals kernel clock tree distribution with property st,pkcs ++========================================================================= ++ ++- st,pkcs : used to configure the peripherals kernel clock selection. ++ ++ The property is a list of peripheral kernel clock source identifiers defined ++ by macros CLK__ as defined by header file ++ dt-bindings/clock/stm32mp1-clksrc.h. ++ ++ st,pkcs may not list all the kernel clocks and has no ordering requirements. ++ ++ Example: ++ st,pkcs = < ++ CLK_STGEN_HSE ++ CLK_CKPER_HSI ++ CLK_USBPHY_PLL2P ++ CLK_DSI_PLL2Q ++ CLK_I2C46_HSI ++ CLK_UART1_HSI ++ CLK_UART24_HSI ++ >; ++ ++Defining peripheral PLL frequencies +======================================================== + -+This property can be used to configure PLL frequencies. ++- children for a PLL static configuration with "st,stm32mp1-pll" compatible + -+PLL children nodes for PLL1 to PLL4 (see ref manual for details) -+are listed with associated index 0 to 3 (st,pll@0 to st,pll@3). -+PLLx is off when the associated node is absent. ++ Each PLL children nodes for PLL1 to PLL4 (see ref manual for details) ++ are listed with associated reg 0 to 3. ++ PLLx is off when the associated node is absent or deactivated. + -+Here are the available properties for each PLL node: ++ Here are the available properties for each PLL node: ++ - compatible: should be "st,stm32mp1-pll" + -+- cfg: The parameters for PLL configuration in the following order: -+ DIVM DIVN DIVP DIVQ DIVR Output. ++ - reg: index of the pll instance ++ ++ - cfg: The parameters for PLL configuration in the following order: ++ DIVM DIVN DIVP DIVQ DIVR Output. + + DIVx values are defined as in RCC spec: + 0x0: bypass (division by 1) @@ -992,11 +977,11 @@ index 0000000..7021486 + NB: macro PQR(p,q,r) can be used to build this value + with p,q,r = 0 or 1. + -+- frac: Fractional part of the multiplication factor -+ (optional, PLL is in integer mode when absent). ++ - frac: Fractional part of the multiplication factor ++ (optional, PLL is in integer mode when absent). + -+- csg: Clock Spreading Generator (optional) with parameters in the following -+ order: MOD_PER INC_STEP SSCG_MODE. ++ - csg: Clock Spreading Generator (optional) with parameters in the ++ following order: MOD_PER INC_STEP SSCG_MODE. + + MOD_PER: Modulation Period Adjustment + INC_STEP: Modulation Depth Adjustment @@ -1005,75 +990,62 @@ index 0000000..7021486 + - SSCG_MODE_CENTER_SPREAD = 0 + - SSCG_MODE_DOWN_SPREAD = 1 + -+Example: ++ Example: + st,pll@0 { -+ cfg = < 1 53 0 0 0 1 >; -+ frac = < 0x810 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ cfg = <1 53 0 0 0 1>; ++ frac = <0x810>; + }; + st,pll@1 { -+ cfg = < 1 43 1 0 0 PQR(0,1,1) >; -+ csg = < 10 20 1 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ cfg = <1 43 1 0 0 PQR(0,1,1)>; ++ csg = <10 20 1>; + }; + st,pll@2 { -+ cfg = < 2 85 3 13 3 0 >; -+ csg = < 10 20 SSCG_MODE_CENTER_SPREAD >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ cfg = <2 85 3 13 3 0>; ++ csg = <10 20 SSCG_MODE_CENTER_SPREAD>; + }; + st,pll@3 { -+ cfg = < 2 78 4 7 9 3 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ cfg = <2 78 4 7 9 3>; + }; + -+Defining peripherals kernel clock tree distribution with property st,pkcs -+========================================================================= -+ -+This property can be used to configure the peripherals kernel clock selection. -+ -+The property is a list of peripheral kernel clock source identifiers defined -+by macros CLK__ as defined by header file -+dt-bindings/clock/stm32mp1-clksrc.h. -+ -+st,pkcs may not list all the kernel clocks and has no ordering requirements. -+ -+Example: -+ st,pkcs = < -+ CLK_STGEN_HSE -+ CLK_CKPER_HSI -+ CLK_USBPHY_PLL2P -+ CLK_DSI_PLL2Q -+ CLK_I2C46_HSI -+ CLK_UART1_HSI -+ CLK_UART24_HSI -+ >; -+ +Fixed clocks description +======================== + +The clock tree is also based on 5 fixed-clock in clocks node +used to define the state of associated ST32MP1 oscillators: -+- clk-lsi -+- clk-lse -+- clk-hsi -+- clk-hse -+- clk-csi ++ - clk-lsi ++ - clk-lse ++ - clk-hsi ++ - clk-hse ++ - clk-csi + +At boot the clock tree initialization will -+- enable oscillators present in device tree -+- disable HSI oscillator if the node is absent (always activated by bootrom) ++ - enable oscillators present in device tree and not disabled ++ (node with status="disabled"), ++ - disable HSI oscillator if the node is absent (always activated by bootrom) ++ and not disabled (node with status="disabled"). + +Optional properties : + +a) for external oscillator: "clk-lse", "clk-hse" + -+ 4 optional fields are managed -+ - "st,bypass" configures the oscillator bypass mode (HSEBYP, LSEBYP) -+ - "st,digbypass" configures the bypass mode as full-swing digital -+ signal (DIGBYP) -+ - "st,css" activates the clock security system (HSECSSON, LSECSSON) -+ - "st,drive" (only for LSE) contains the value of the drive for the -+ oscillator (see LSEDRV_ defined in the file -+ dt-bindings/clock/stm32mp1-clksrc.h) -+ -+ Example board file: ++ 4 optional fields are managed ++ - "st,bypass" configures the oscillator bypass mode (HSEBYP, LSEBYP) ++ - "st,digbypass" configures the bypass mode as full-swing digital ++ signal (DIGBYP) ++ - "st,css" activates the clock security system (HSECSSON, LSECSSON) ++ - "st,drive" (only for LSE) contains the value of the drive for the ++ oscillator (see LSEDRV_ defined in the file ++ dt-bindings/clock/stm32mp1-clksrc.h) + ++ Example board file: + / { + clocks { + clk_hse: clk-hse { @@ -1094,13 +1066,12 @@ index 0000000..7021486 + +b) for internal oscillator: "clk-hsi" + -+ Internally HSI clock is fixed to 64MHz for STM32MP157 SoC. -+ In device tree, clk-hsi is the clock after HSIDIV (clk_hsi in RCC -+ doc). So this clock frequency is used to compute the expected HSI_DIV -+ for the clock tree initialization. -+ -+ Example with HSIDIV = /1: ++ Internally HSI clock is fixed to 64MHz for STM32MP157 SoC. ++ In device tree, clk-hsi is the clock after HSIDIV (clk_hsi in RCC ++ doc). So this clock frequency is used to compute the expected HSI_DIV ++ for the clock tree initialization. + ++ Example with HSIDIV = /1: + / { + clocks { + clk_hsi: clk-hsi { @@ -1110,8 +1081,7 @@ index 0000000..7021486 + }; + }; + -+ Example with HSIDIV = /2 -+ ++ Example with HSIDIV = /2 + / { + clocks { + clk_hsi: clk-hsi { @@ -1132,8 +1102,8 @@ index 0000000..7021486 + +This feature requires that a HW timer is assigned to the calibration sequence. + -+Dedicated interrupt must be defined using "mcu_sev" name to start a calibration -+on detection of an interrupt raised by MCU. ++Dedicated secure interrupt must be defined using "mcu_sev" name to start a ++calibration on detection of an interrupt raised by MCU. + +- st,hsi-cal: used to enable HSI clock calibration feature. + @@ -1150,11 +1120,162 @@ index 0000000..7021486 + st,cal-sec = <15>; + secure-interrupts = , + ; -+ interrupt-names = "mcu_sev", "wakeup"; ++ secure-interrupt-names = "mcu_sev", "wakeup"; + }; ++ ++ ++Example of clock tree initialization ++==================================== ++ ++/ { ++ clocks { ++ clk_hse: clk-hse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ st,digbypass; ++ }; ++ ++ clk_hsi: clk-hsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <64000000>; ++ }; ++ ++ clk_lse: clk-lse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ }; ++ ++ clk_lsi: clk-lsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32000>; ++ }; ++ ++ clk_csi: clk-csi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <4000000>; ++ }; ++ }; ++ ++ soc { ++ ++ rcc: rcc@50000000 { ++ compatible = "st,stm32mp1-rcc", "syscon"; ++ reg = <0x50000000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ interrupts = ; ++ secure-interrupts = ; ++ secure-interrupt-names = "wakeup"; ++ secure-status = "okay"; ++ ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MCU_PLL3P ++ CLK_PLL12_HSE ++ CLK_PLL3_HSE ++ CLK_PLL4_HSE ++ CLK_RTC_LSE ++ CLK_MCO1_DISABLED ++ CLK_MCO2_DISABLED ++ >; ++ ++ st,clkdiv = < ++ 1 /*MPU*/ ++ 0 /*AXI*/ ++ 0 /*MCU*/ ++ 1 /*APB1*/ ++ 1 /*APB2*/ ++ 1 /*APB3*/ ++ 1 /*APB4*/ ++ 2 /*APB5*/ ++ 23 /*RTC*/ ++ 0 /*MCO1*/ ++ 0 /*MCO2*/ ++ >; ++ ++ st,pkcs = < ++ CLK_CKPER_HSE ++ CLK_FMC_ACLK ++ CLK_QSPI_ACLK ++ CLK_ETH_DISABLED ++ CLK_SDMMC12_PLL4P ++ CLK_DSI_DSIPLL ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_SPI2S1_PLL3Q ++ CLK_SPI2S23_PLL3Q ++ CLK_SPI45_HSI ++ CLK_SPI6_HSI ++ CLK_I2C46_HSI ++ CLK_SDMMC3_PLL4P ++ CLK_USBO_USBPHY ++ CLK_ADC_CKPER ++ CLK_CEC_LSE ++ CLK_I2C12_HSI ++ CLK_I2C35_HSI ++ CLK_UART1_HSI ++ CLK_UART24_HSI ++ CLK_UART35_HSI ++ CLK_UART6_HSI ++ CLK_UART78_HSI ++ CLK_SPDIF_PLL4P ++ CLK_FDCAN_PLL4Q ++ CLK_SAI1_PLL3Q ++ CLK_SAI2_PLL3Q ++ CLK_SAI3_PLL3Q ++ CLK_SAI4_PLL3Q ++ CLK_RNG1_LSI ++ CLK_RNG2_LSI ++ CLK_LPTIM1_PCLK1 ++ CLK_LPTIM23_PCLK3 ++ CLK_LPTIM45_LSE ++ >; ++ ++ /* VCO = 1300.0 MHz => P = 650 (CPU) */ ++ pll1: st,pll@0 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ cfg = <2 80 0 0 0 PQR(1,0,0)>; ++ frac = <0x800>; ++ }; ++ ++ /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), ++ R = 533 (DDR) */ ++ pll2: st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ cfg = <2 65 1 0 0 PQR(1,1,1)>; ++ frac = <0x1400>; ++ }; ++ ++ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ ++ pll3: st,pll@2 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ cfg = <1 33 1 16 36 PQR(1,1,1)>; ++ frac = <0x1a04>; ++ }; ++ ++ /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ ++ pll4: st,pll@3 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ cfg = <3 98 5 7 7 PQR(1,1,1)>; ++ }; ++ }; ++ }; ++}; diff --git a/docs/devicetree/bindings/i2c/i2c-stm32.txt b/docs/devicetree/bindings/i2c/i2c-stm32.txt new file mode 100644 -index 0000000..68aefa6 +index 000000000..68aefa6dc --- /dev/null +++ b/docs/devicetree/bindings/i2c/i2c-stm32.txt @@ -0,0 +1,54 @@ @@ -1212,9 +1333,316 @@ index 0000000..68aefa6 + st,syscfg-fmp = <&syscfg 0x4 0x1>; + }; + +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 000000000..ac6a7df43 +--- /dev/null ++++ b/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt +@@ -0,0 +1,301 @@ ++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 ++ This parameter is optional; when it is absent the built-in PHY ++ calibration is done. ++ 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/docs/devicetree/bindings/mmc/mmci.txt b/docs/devicetree/bindings/mmc/mmci.txt new file mode 100644 -index 0000000..6d3c626 +index 000000000..6d3c626e0 --- /dev/null +++ b/docs/devicetree/bindings/mmc/mmci.txt @@ -0,0 +1,72 @@ @@ -1292,7 +1720,7 @@ index 0000000..6d3c626 +}; diff --git a/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt b/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt new file mode 100644 -index 0000000..51576a3 +index 000000000..51576a384 --- /dev/null +++ b/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt @@ -0,0 +1,22 @@ @@ -1320,7 +1748,7 @@ index 0000000..51576a3 + }; diff --git a/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt new file mode 100644 -index 0000000..bd56e19 +index 000000000..bd56e1946 --- /dev/null +++ b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt @@ -0,0 +1,42 @@ @@ -1368,10 +1796,10 @@ index 0000000..bd56e19 +}; diff --git a/docs/devicetree/bindings/power/st,stpmic1.txt b/docs/devicetree/bindings/power/st,stpmic1.txt new file mode 100644 -index 0000000..54b64e2 +index 000000000..83307d23b --- /dev/null +++ b/docs/devicetree/bindings/power/st,stpmic1.txt -@@ -0,0 +1,132 @@ +@@ -0,0 +1,94 @@ +* STMicroelectronics STPMIC1 Power Management IC + +Required parent device properties: @@ -1419,43 +1847,6 @@ index 0000000..54b64e2 + IT_TWARN_R=30 + IT_TWARN_F=31 + -+Optional parent device properties: -+- st,main-control-register: -+ -bit 1: Power cycling will be performed on turn OFF condition -+ -bit 2: PWRCTRL is functional -+ -bit 3: PWRCTRL active high -+- st,pads-pull-register: -+ -bit 1: WAKEUP pull down is not active -+ -bit 2: PWRCTRL pull up is active -+ -bit 3: PWRCTRL pull down is active -+ -bit 4: WAKEUP detector is disabled -+- st,vin-control-register: -+ -bit 0: VINLOW monitoring is enabled -+ -bit [1...3]: VINLOW rising threshold -+ 000 VINOK_f + 50mV -+ 001 VINOK_f + 100mV -+ 010 VINOK_f + 150mV -+ 011 VINOK_f + 200mV -+ 100 VINOK_f + 250mV -+ 101 VINOK_f + 300mV -+ 110 VINOK_f + 350mV -+ 111 VINOK_f + 400mV -+ -bit [4...5]: VINLOW hyst -+ 00 100mV -+ 01 200mV -+ 10 300mV -+ 11 400mV -+ -bit 6: SW_OUT detector is disabled -+ -bit 7: SW_IN detector is enabled. -+- st,usb-control-register: -+ -bit 3: SW_OUT current limit -+ 0: 600mA -+ 1: 1.1A -+ -bit 4: VBUS_OTG discharge is enabled -+ -bit 5: SW_OUT discharge is enabled -+ -bit 6: VBUS_OTG detection is enabled -+ -bit 7: BOOST_OVP is disabled -+ +STPMIC1 consists in a varied group of sub-devices. +Each sub-device binding is be described in own documentation file. + @@ -1472,7 +1863,6 @@ index 0000000..54b64e2 + reg = <0x33>; + interrupt-parent = <&gpioa>; + interrupts = <0 2>; -+ st,main-control-register=<0x0c>; + interrupt-controller; + #interrupt-cells = <2>; + @@ -1506,7 +1896,7 @@ index 0000000..54b64e2 + }; diff --git a/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt b/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt new file mode 100644 -index 0000000..b4edaf7 +index 000000000..b4edaf7c7 --- /dev/null +++ b/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt @@ -0,0 +1,6 @@ @@ -1518,7 +1908,7 @@ index 0000000..b4edaf7 +Please see Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt diff --git a/docs/devicetree/bindings/rng/st,stm32-rng.txt b/docs/devicetree/bindings/rng/st,stm32-rng.txt new file mode 100644 -index 0000000..3c613d7 +index 000000000..3c613d791 --- /dev/null +++ b/docs/devicetree/bindings/rng/st,stm32-rng.txt @@ -0,0 +1,23 @@ @@ -1547,7 +1937,7 @@ index 0000000..3c613d7 + }; diff --git a/docs/devicetree/bindings/serial/st,stm32-usart.txt b/docs/devicetree/bindings/serial/st,stm32-usart.txt new file mode 100644 -index 0000000..08b4990 +index 000000000..08b499045 --- /dev/null +++ b/docs/devicetree/bindings/serial/st,stm32-usart.txt @@ -0,0 +1,88 @@ @@ -1641,7 +2031,7 @@ index 0000000..08b4990 +}; diff --git a/docs/devicetree/bindings/soc/st,stm32-etzpc.txt b/docs/devicetree/bindings/soc/st,stm32-etzpc.txt new file mode 100644 -index 0000000..a2ac263 +index 000000000..a2ac263ce --- /dev/null +++ b/docs/devicetree/bindings/soc/st,stm32-etzpc.txt @@ -0,0 +1,56 @@ @@ -1703,10 +2093,10 @@ index 0000000..a2ac263 + diff --git a/docs/devicetree/bindings/soc/st,stm32-romem.txt b/docs/devicetree/bindings/soc/st,stm32-romem.txt new file mode 100644 -index 0000000..fbff52e +index 000000000..c430fb84d --- /dev/null +++ b/docs/devicetree/bindings/soc/st,stm32-romem.txt -@@ -0,0 +1,31 @@ +@@ -0,0 +1,74 @@ +STMicroelectronics STM32 Factory-programmed data device tree bindings + +This represents STM32 Factory-programmed read only non-volatile area: locked @@ -1725,6 +2115,12 @@ index 0000000..fbff52e +Optional Data cells: +- Must be child nodes as described in nvmem.txt. + ++Optional-properties: ++- "st,non-secure-otp" specifies that the OTP can be accessed by non-secure ++ world through secure world services. Only useful for upper OTPs. This ++ property mandates 32-bit granularity of the related nvmem area, that is ++ offset and length are both multiple of 4. ++ +Example on stm32f4: + romem: nvmem@1fff7800 { + compatible = "st,stm32-romem"; @@ -1738,9 +2134,46 @@ index 0000000..fbff52e + }; + ... + }; ++ ++Example on stm32mp1: ++ bsec: nvmem@5c005000 { ++ ... ++ mac_addr: mac_addr@e4 { ++ reg = <0xe4 0x8>; ++ st,non-secure-otp; ++ }; ++ ... ++ }; ++ ++The nvmem_layout node gathers all nvmem platform-dependent layout information, ++including OTP names and phandles, in order to allow easy accesses for data ++consumers, using pre-defined string in nvmem-cell-names property. ++ ++Required properties: ++- compatible: "st,stm32-nvmem-layout" ++- nvmem-cells and nvmem-cell-names, as described in nvmem.txt. ++ ++Example on stm32mp1: ++ nvmem_layout: nvmem_layout@0 { ++ compatible = "st,stm32-nvmem-layout"; ++ nvmem-cells = <&part_number_otp>, ++ ... ++ ; ++ nvmem-cell-names = "part_number_otp", ++ ... ++ ; ++ }; ++ ++ bsec: nvmem@5c005000 { ++ ... ++ part_number_otp: part_number_otp@4 { ++ reg = <0x4 0x1>; ++ }; ++ ... ++ }; diff --git a/docs/devicetree/bindings/soc/st,stm32-stgen.txt b/docs/devicetree/bindings/soc/st,stm32-stgen.txt new file mode 100644 -index 0000000..dbd962e +index 000000000..dbd962ebc --- /dev/null +++ b/docs/devicetree/bindings/soc/st,stm32-stgen.txt @@ -0,0 +1,18 @@ @@ -1764,7 +2197,7 @@ index 0000000..dbd962e + }; diff --git a/docs/devicetree/bindings/soc/st,stm32-tamp.txt b/docs/devicetree/bindings/soc/st,stm32-tamp.txt new file mode 100644 -index 0000000..4d21c6b +index 000000000..4d21c6b8a --- /dev/null +++ b/docs/devicetree/bindings/soc/st,stm32-tamp.txt @@ -0,0 +1,22 @@ @@ -1792,7 +2225,7 @@ index 0000000..4d21c6b +}; diff --git a/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt b/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt new file mode 100644 -index 0000000..2453603 +index 000000000..2453603a1 --- /dev/null +++ b/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt @@ -0,0 +1,28 @@ @@ -1824,426 +2257,232 @@ index 0000000..2453603 + instance = <2>; + timeout-sec = <30>; +}; +diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst +index 9cca75e92..e2db1bf9a 100644 +--- a/docs/getting_started/porting-guide.rst ++++ b/docs/getting_started/porting-guide.rst +@@ -481,6 +481,36 @@ constants must also be defined: + Defines the total size of the physical address space in bytes. For example, + for a 32 bit physical address space, this value should be ``(1ULL << 32)``. + ++If the platform port uses the translation table library code, the following ++constants can be defined: ++ ++- **#define : PLAT\_BASE\_XLAT\_BASE** ++ ++ Defines the identity map base address of the translation level 1 base table ++ which memory location is common to all BLs. This feature is useful only for ++ AArch32 only architectures where all BL do share the very same MMU resources ++ since all core modes rely on a single MMU support contrary to AArch64 aware ++ architectures where EL3 and secure EL1 each rely on their specific MMU ++ configuration resources. ++ ++- **#define : PLAT\_BASE\_XLAT\_SIZE** ++ ++ Defines the byte size reserved for translation level 1 base table ++ **PLAT\_BASE\_XLAT\_BASE**. ++ ++- **#define : PLAT\_XLAT\_BASE** ++ ++ Defines the identity map base address of the translation table array which ++ is common to all BLs. This feature is useful only for AArch32 only ++ architectures where all BL do share the very same MMU resources since ++ all core modes rely on a single MMU support contrary to AArch64 aware ++ architectures where EL3 and secure EL1 each rely on their specific MMU ++ configuration resources. ++ ++- **#define : PLAT\_XLAT\_SIZE** ++ ++ Defines the byte size reserved for translation tables **PLAT\__XLAT\_BASE**. ++ + If the platform port uses the IO storage framework, the following constants + must also be defined: + diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst -index 9e731a4..10ad00e 100644 +index 88251d6af..2c372a6a3 100644 --- a/docs/plat/stm32mp1.rst +++ b/docs/plat/stm32mp1.rst -@@ -76,7 +76,23 @@ To build: +@@ -76,21 +76,34 @@ ROM code -> BL2 (compiled with BL2_AT_EL3) -> OP-TEE -> BL33 (U-Boot) + + Build Instructions + ------------------ ++Boot media(s) supported by BL2 must be specified in the build command. ++Available storage medias are: ++- ``STM32MP_SDMMC`` ++- ``STM32MP_EMMC`` ++- ``STM32MP_RAW_NAND`` ++- ``STM32MP_SPI_NAND`` ++- ``STM32MP_SPI_NOR`` + +-To build with SP_min: ++To build with SP_min and support for all bootable devices: + .. code:: bash - make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min +- make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb ++ make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1 ++ STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + +-To build TF-A with with Op-TEE support: +- ++To build TF-A with OP-TEE support for all bootable devices: + .. code:: bash + +- make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee ++ make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1 STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb ++ cd ++ make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts + cd -+ make stm32mp15_trusted_defconfig -+ make DEVICE_TREE=stm32mp157c_ev1 all -+ ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32 ++ make stm32mp15_optee_defconfig ++ make DEVICE_TREE=stm32mp157c-ev1 all ++ The following build options are supported: - - ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. -+ -+ -+Populate SD-card -+---------------- -+ -+The SD-card has to be formated with GPT. -+It should contain at least those partitions: -+ -+- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary -+- ssbl: to copy the u-boot.stm32 binary -+ -+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. -diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst -index 1667cce..bef4af6 100644 ---- a/docs/porting-guide.rst -+++ b/docs/porting-guide.rst -@@ -2554,8 +2554,13 @@ NOTE: This section assumes that your platform is enabling the MULTI_CONSOLE_API - flag in its platform.mk. Not using this flag is deprecated for new platforms. - - BL31 implements a crash reporting mechanism which prints the various registers --of the CPU to enable quick crash analysis and debugging. By default, the --definitions in ``plat/common/aarch64/platform\_helpers.S`` will cause the crash -+of the CPU to enable quick crash analysis and debugging. This mechanism relies -+on the platform implementating ``plat_crash_console_init``, -+``plat_crash_console_putc`` and ``plat_crash_console_flush``. -+ -+The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample -+implementation of all of them. Platforms may include this file to their -+makefiles in order to benefit from them. By default, they will cause the crash - output to be routed over the normal console infrastructure and get printed on - consoles configured to output in crash state. ``console_set_scope()`` can be - used to control whether a console is used for crash output. -@@ -2565,8 +2570,12 @@ normal boot console can be set up), platforms may want to control crash output - more explicitly. For these, the following functions can be overridden by - platform code. They are executed outside of a C environment and without a stack. - --Function : plat\_crash\_console\_init --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+If this behaviour is not desirable, the platform may implement functions that -+redirect the prints to the console driver (``console_xxx_core_init``, etc). Most -+platforms (including Arm platforms) do this and they can be used as an example. -+ -+Function : plat\_crash\_console\_init [mandatory] -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - :: - -@@ -2577,9 +2586,10 @@ This API is used by the crash reporting mechanism to initialize the crash - console. It must only use the general purpose registers x0 through x7 to do the - initialization and returns 1 on success. - --If you are trying to debug crashes before the console driver would normally get --registered, you can use this to register a driver from assembly with hardcoded --parameters. For example, you could register the 16550 driver like this: -+When using the sample implementation, if you are trying to debug crashes before -+the console driver would normally get registered, you can use this to register a -+driver from assembly with hardcoded parameters. For example, you could register -+the 16550 driver like this: - - :: - -@@ -2595,11 +2605,11 @@ parameters. For example, you could register the 16550 driver like this: - b console_16550_register /* tail call, returns 1 on success */ - endfunc plat_crash_console_init - --If you're trying to debug crashes in BL1, you can call the console_xxx_core_init --function exported by some console drivers from here. -+If you're trying to debug crashes in BL1, you can call the -+``console_xxx_core_init`` function exported by some console drivers from here. - --Function : plat\_crash\_console\_putc --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+Function : plat\_crash\_console\_putc [mandatory] -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - :: - -@@ -2612,13 +2622,13 @@ x2 to do its work. The parameter and the return value are in general purpose - register x0. - - If you have registered a normal console driver in ``plat_crash_console_init``, --you can keep the default implementation here (which calls ``console_putc()``). -+you can keep the sample implementation here (which calls ``console_putc()``). - --If you're trying to debug crashes in BL1, you can call the console_xxx_core_putc --function exported by some console drivers from here. -+If you're trying to debug crashes in BL1, you can call the -+``console_xxx_core_putc`` function exported by some console drivers from here. - --Function : plat\_crash\_console\_flush --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+Function : plat\_crash\_console\_flush [mandatory] -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - :: - -@@ -2631,7 +2641,7 @@ registers x0 through x5 to do its work. The return value is 0 on successful - completion; otherwise the return value is -1. - - If you have registered a normal console driver in ``plat_crash_console_init``, --you can keep the default implementation here (which calls ``console_flush()``). -+you can keep the sample implementation here (which calls ``console_flush()``). - - If you're trying to debug crashes in BL1, you can call the console_xx_core_flush - function exported by some console drivers from here. -diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S -index 3718fff..edadaa4 100644 ---- a/drivers/arm/pl011/aarch32/pl011_console.S -+++ b/drivers/arm/pl011/aarch32/pl011_console.S -@@ -1,10 +1,13 @@ +diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c +index 50d670139..801cf3046 100644 +--- a/drivers/arm/tzc/tzc400.c ++++ b/drivers/arm/tzc/tzc400.c +@@ -1,5 +1,5 @@ /* -- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ - #include - #include -+#include -+#define USE_FINISH_CONSOLE_REG_2 -+#include - #include +@@ -60,7 +60,6 @@ static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val) + GATE_KEEPER_OS_SHIFT) & \ + GATE_KEEPER_OS_MASK) - /* -@@ -13,10 +16,18 @@ - */ - #include "../../../console/aarch32/console.S" - -- .globl console_core_init -- .globl console_core_putc -- .globl console_core_getc -- .globl console_core_flush -+ /* -+ * "core" functions are low-level implementations that don't require -+ * writeable memory and are thus safe to call in BL1 crash context. -+ */ -+ .globl console_pl011_core_init -+ .globl console_pl011_core_putc -+ .globl console_pl011_core_getc -+ .globl console_pl011_core_flush -+ -+ .globl console_pl011_putc -+ .globl console_pl011_getc -+ .globl console_pl011_flush - - - /* ----------------------------------------------- -@@ -33,7 +44,7 @@ - * Clobber list : r1, r2, r3 - * ----------------------------------------------- - */ --func console_core_init -+func console_pl011_core_init - /* Check the input base address */ - cmp r0, #0 - beq core_init_fail -@@ -73,7 +84,53 @@ func console_core_init - core_init_fail: - mov r0, #0 - bx lr --endfunc console_core_init -+endfunc console_pl011_core_init -+ -+#if MULTI_CONSOLE_API -+ .globl console_pl011_register -+ -+ /* ------------------------------------------------------- -+ * init console_pl011_register(console_pl011_t *console, -+ * uintptr_t base, uint32_t clk, uint32_t baud) -+ * Function to initialize and register a new PL011 -+ * console. Storage passed in for the console struct -+ * *must* be persistent (i.e. not from the stack). -+ * In: r0 - UART register base address -+ * r1 - UART clock in Hz -+ * r2 - Baud rate -+ * r3 - pointer to empty console_pl011_t struct -+ * Out: return 1 on success, 0 on error -+ * Clobber list : r0, r1, r2 -+ * ------------------------------------------------------- -+ */ -+func console_pl011_register -+ push {r4, lr} -+ mov r4, r3 -+ cmp r4, #0 -+ beq register_fail -+ str r0, [r4, #CONSOLE_T_PL011_BASE] -+ -+ bl console_pl011_core_init -+ cmp r0, #0 -+ beq register_fail -+ -+ mov r0, r4 -+ pop {r4, lr} -+ finish_console_register pl011 putc=1, getc=1, flush=1 -+ -+register_fail: -+ pop {r4, pc} -+endfunc console_pl011_register -+#else -+ .globl console_core_init -+ .globl console_core_putc -+ .globl console_core_getc -+ .globl console_core_flush -+ .equ console_core_init, console_pl011_core_init -+ .equ console_core_putc, console_pl011_core_putc -+ .equ console_core_getc, console_pl011_core_getc -+ .equ console_core_flush, console_pl011_core_flush -+#endif - - /* -------------------------------------------------------- - * int console_core_putc(int c, uintptr_t base_addr) -@@ -85,7 +142,7 @@ endfunc console_core_init - * Clobber list : r2 - * -------------------------------------------------------- - */ --func console_core_putc -+func console_pl011_core_putc - /* Check the input parameter */ - cmp r1, #0 - beq putc_error -@@ -109,7 +166,26 @@ func console_core_putc - putc_error: - mov r0, #-1 - bx lr --endfunc console_core_putc -+endfunc console_pl011_core_putc -+ -+ /* -------------------------------------------------------- -+ * int console_pl011_putc(int c, console_pl011_t *console) -+ * Function to output a character over the console. It -+ * returns the character printed on success or -1 on error. -+ * In: r0 - character to be printed -+ * r1 - pointer to console_t structure -+ * Out : return -1 on error else return character. -+ * Clobber list: r2 -+ * ------------------------------------------------------- -+ */ -+func console_pl011_putc -+#if ENABLE_ASSERTIONS -+ cmp r1, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r1, [r1, #CONSOLE_T_PL011_BASE] -+ b console_pl011_core_putc -+endfunc console_pl011_putc - - /* --------------------------------------------- - * int console_core_getc(uintptr_t base_addr) -@@ -120,7 +196,7 @@ endfunc console_core_putc - * Clobber list : r0, r1 - * --------------------------------------------- - */ --func console_core_getc -+func console_pl011_core_getc - cmp r0, #0 - beq getc_error - 1: -@@ -134,7 +210,26 @@ func console_core_getc - getc_error: - mov r0, #-1 - bx lr --endfunc console_core_getc -+endfunc console_pl011_core_getc -+ -+ /* ------------------------------------------------ -+ * int console_pl011_getc(console_pl011_t *console) -+ * Function to get a character from the console. -+ * It returns the character grabbed on success -+ * or -1 if no character is available. -+ * In : r0 - pointer to console_t structure -+ * Out: r0 - character if available, else -1 -+ * Clobber list: r0, r1 -+ * ------------------------------------------------ -+ */ -+func console_pl011_getc -+#if ENABLE_ASSERTIONS -+ cmp r0, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r0, [r0, #CONSOLE_T_PL011_BASE] -+ b console_pl011_core_getc -+endfunc console_pl011_getc - - /* --------------------------------------------- - * int console_core_flush(uintptr_t base_addr) -@@ -145,7 +240,7 @@ endfunc console_core_getc - * Clobber list : r0, r1 - * --------------------------------------------- - */ --func console_core_flush -+func console_pl011_core_flush - cmp r0, #0 - beq flush_error - -@@ -160,4 +255,22 @@ func console_core_flush - flush_error: - mov r0, #-1 - bx lr --endfunc console_core_flush -+endfunc console_pl011_core_flush -+ -+ /* --------------------------------------------- -+ * int console_pl011_flush(console_pl011_t *console) -+ * Function to force a write of all buffered -+ * data that hasn't been output. -+ * In : r0 - pointer to console_t structure -+ * Out : return -1 on error else return 0. -+ * Clobber list: r0, r1 -+ * --------------------------------------------- -+ */ -+func console_pl011_flush -+#if ENABLE_ASSERTIONS -+ cmp r0, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r0, [r0, #CONSOLE_T_PL011_BASE] -+ b console_pl011_core_flush -+endfunc console_pl011_flush -diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S -index 448501a..c4d51c8 100644 ---- a/drivers/arm/pl011/aarch64/pl011_console.S -+++ b/drivers/arm/pl011/aarch64/pl011_console.S -@@ -6,6 +6,7 @@ - #include - #include - #include -+#define USE_FINISH_CONSOLE_REG_2 - #include - #include - -@@ -109,7 +110,7 @@ func console_pl011_register - - mov x0, x6 - mov x30, x7 -- finish_console_register pl011 -+ finish_console_register pl011 putc=1, getc=1, flush=1 - - register_fail: - ret x7 -diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c -index db4f88a..1849e5a 100644 ---- a/drivers/arm/tzc/tzc400.c -+++ b/drivers/arm/tzc/tzc400.c -@@ -68,6 +68,59 @@ DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) +- + /* Define common core functions used across different TZC peripherals. */ + DEFINE_TZC_COMMON_WRITE_ACTION(400, 400) + DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400) +@@ -70,8 +69,50 @@ DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) DEFINE_TZC_COMMON_CONFIGURE_REGION0(400) DEFINE_TZC_COMMON_CONFIGURE_REGION(400) +-static unsigned int _tzc400_get_gate_keeper(uintptr_t base, +- unsigned int filter) +static inline void tzc400_clear_it(long base, uint32_t filter) +{ -+ mmio_write_32(base + INT_CLEAR, 1 << filter); ++ mmio_write_32(base + INT_CLEAR, 1U << filter); +} + +static inline uint32_t tzc400_get_int_by_filter(long base, uint32_t filter) +{ -+ return (mmio_read_32(base + INT_STATUS) & (1 << filter)); ++ return (mmio_read_32(base + INT_STATUS) & (1U << filter)); +} + +#if DEBUG +static long tzc400_get_fail_address(long base, uint32_t filter) +{ -+ long fail_address = 0; ++ long fail_address; + -+ if (sizeof(long) == sizeof(uint32_t)) { -+ if (filter) { -+ fail_address = mmio_read_32(base + -+ FAIL_ADDRESS_LOW_OFF + -+ FILTER_OFFSET); -+ } else { -+ fail_address = mmio_read_32(base + -+ FAIL_ADDRESS_LOW_OFF); -+ } ++ if (filter != 0U) { ++ fail_address = mmio_read_32(base + FAIL_ADDRESS_LOW_OFF + ++ FILTER_OFFSET); ++#ifdef __aarch64__ ++ fail_address += mmio_read_32(base + FAIL_ADDRESS_HIGH_OFF + ++ FILTER_OFFSET) << 32; ++#endif + } else { -+ if (filter) { -+ fail_address = mmio_read_32(base + -+ FAIL_ADDRESS_LOW_OFF + -+ FILTER_OFFSET) + -+ mmio_read_32(base + -+ FAIL_ADDRESS_HIGH_OFF + -+ FILTER_OFFSET); -+ } else { -+ fail_address = mmio_read_32(base + -+ FAIL_ADDRESS_LOW_OFF) + -+ mmio_read_32(base + -+ FAIL_ADDRESS_HIGH_OFF); -+ } ++ fail_address = mmio_read_32(base + FAIL_ADDRESS_LOW_OFF); ++#ifdef __aarch64__ ++ fail_address += ++ mmio_read_32(base + FAIL_ADDRESS_HIGH_OFF) << 32; ++#endif + } ++ + return fail_address; +} +#endif + +static inline uint32_t tzc400_get_fail_control(long base, uint32_t filter) +{ -+ if (filter) { -+ return mmio_read_32(base + FAIL_CONTROL_OFF + -+ FILTER_OFFSET); ++ if (filter != 0U) { ++ return mmio_read_32(base + FAIL_CONTROL_OFF + FILTER_OFFSET); + } else { + return mmio_read_32(base + FAIL_CONTROL_OFF); + } +} + - static unsigned int _tzc400_get_gate_keeper(uintptr_t base, - unsigned int filter) ++static unsigned int _tzc400_get_gate_keeper(uintptr_t base, unsigned int filter) { -@@ -236,3 +289,79 @@ void tzc400_disable_filters(void) + unsigned int open_status; + +@@ -81,9 +122,8 @@ static unsigned int _tzc400_get_gate_keeper(uintptr_t base, + } + + /* This function is not MP safe. */ +-static void _tzc400_set_gate_keeper(uintptr_t base, +- unsigned int filter, +- int val) ++static void _tzc400_set_gate_keeper(uintptr_t base, unsigned int filter, ++ int val) + { + unsigned int open_status; + +@@ -151,7 +191,7 @@ void tzc400_init(uintptr_t base) + * changed. This function only changes the access permissions. + */ + void tzc400_configure_region0(unsigned int sec_attr, +- unsigned int ns_device_access) ++ unsigned int ns_device_access) + { + assert(tzc400.base != 0U); + assert(sec_attr <= TZC_REGION_S_RDWR); +@@ -168,11 +208,11 @@ void tzc400_configure_region0(unsigned int sec_attr, + * for this region (see comment for that function). + */ + void tzc400_configure_region(unsigned int filters, +- unsigned int region, +- unsigned long long region_base, +- unsigned long long region_top, +- unsigned int sec_attr, +- unsigned int nsaid_permissions) ++ unsigned int region, ++ unsigned long long region_base, ++ unsigned long long region_top, ++ unsigned int sec_attr, ++ unsigned int nsaid_permissions) + { + assert(tzc400.base != 0U); + +@@ -185,7 +225,7 @@ void tzc400_configure_region(unsigned int filters, + * the max and expected case. + */ + assert((region_top <= (UINT64_MAX >> (64U - tzc400.addr_width))) && +- (region_base < region_top)); ++ (region_base < region_top)); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); +@@ -193,8 +233,7 @@ void tzc400_configure_region(unsigned int filters, + assert(sec_attr <= TZC_REGION_S_RDWR); + + _tzc400_configure_region(tzc400.base, filters, region, region_base, +- region_top, +- sec_attr, nsaid_permissions); ++ region_top, sec_attr, nsaid_permissions); + } + + void tzc400_enable_filters(void) +@@ -217,8 +256,8 @@ void tzc400_enable_filters(void) + * See the 'ARM (R) CoreLink TM TZC-400 TrustZone (R) + * Address Space Controller' Technical Reference Manual. + */ +- ERROR("TZC-400 : Filter %d Gatekeeper already" +- " enabled.\n", filter); ++ ERROR("TZC-400: Filter %d Gatekeeper already enabled\n", ++ filter); + panic(); + } + _tzc400_set_gate_keeper(tzc400.base, filter, 1); +@@ -238,3 +277,79 @@ void tzc400_disable_filters(void) for (filter = 0; filter < tzc400.num_filters; filter++) _tzc400_set_gate_keeper(tzc400.base, filter, 0); } @@ -2252,9 +2491,9 @@ index db4f88a..1849e5a 100644 +{ + unsigned int filter; + -+ assert(tzc400.base); -+ for (filter = 0; filter < tzc400.num_filters; filter++) { -+ mmio_write_32(tzc400.base + INT_CLEAR, 1 << filter); ++ assert(tzc400.base != 0U); ++ for (filter = 0U; filter < tzc400.num_filters; filter++) { ++ mmio_write_32(tzc400.base + INT_CLEAR, 1U << filter); + } +} + @@ -2262,9 +2501,9 @@ index db4f88a..1849e5a 100644 +{ + unsigned int filter; + -+ assert(tzc400.base); -+ for (filter = 0; filter < tzc400.num_filters; filter++) { -+ if (mmio_read_32(tzc400.base + INT_STATUS) & (1 << filter)) { ++ assert(tzc400.base != 0U); ++ for (filter = 0U; filter < tzc400.num_filters; filter++) { ++ if (mmio_read_32(tzc400.base + INT_STATUS) & (1U << filter)) { + return 1; + } + } @@ -2273,43 +2512,43 @@ index db4f88a..1849e5a 100644 + +void tzc400_it_handler(void) +{ -+ uint32_t filter = 0; ++ uint32_t filter; + uint32_t filter_it_pending = tzc400.num_filters; -+ uint32_t control_fail = 0; ++ uint32_t control_fail; +#if DEBUG -+ long address_fail = 0; ++ long address_fail; +#endif + -+ assert(tzc400.base); ++ assert(tzc400.base != 0U); + + /* first display information conerning the fault access */ -+ for (filter = 0; (filter < tzc400.num_filters) && ++ for (filter = 0U; (filter < tzc400.num_filters) && + (filter_it_pending == tzc400.num_filters); filter++) { -+ if (tzc400_get_int_by_filter(tzc400.base, filter)) ++ if (tzc400_get_int_by_filter(tzc400.base, filter)) { + filter_it_pending = filter; ++ } + } + + if (filter_it_pending == tzc400.num_filters) { -+ ERROR("Error no it pending!!"); ++ ERROR("Error no IT pending!"); + panic(); + } + +#if DEBUG + address_fail = tzc400_get_fail_address(tzc400.base, filter_it_pending); -+ ERROR("Illegal access to 0x%lx in :\n",address_fail); ++ ERROR("Illegal access to 0x%lx in :\n", address_fail); +#endif + + control_fail = tzc400_get_fail_control(tzc400.base, filter_it_pending); + -+ -+ + if ((control_fail & FAIL_CONTROL_NS_SHIFT) == FAIL_CONTROL_NS_SECURE) { -+ ERROR("\tSecure\n"); ++ ERROR("\tNon-Secure\n"); + } else { -+ ERROR("\tNo Secure\n"); ++ ERROR("\tSecure\n"); + } + -+ if ((control_fail & FAIL_CONTROL_PRIV_SHIFT) == FAIL_CONTROL_PRIV_PRIV) { ++ if ((control_fail & FAIL_CONTROL_PRIV_SHIFT) == ++ FAIL_CONTROL_PRIV_PRIV) { + ERROR("\tPrivilege\n"); + } else { + ERROR("\tUnprivilege\n"); @@ -2323,671 +2562,24 @@ index db4f88a..1849e5a 100644 + + tzc400_clear_it(tzc400.base, filter_it_pending); +} -diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S -index 6732631..116c9d8 100644 ---- a/drivers/cadence/uart/aarch64/cdns_console.S -+++ b/drivers/cadence/uart/aarch64/cdns_console.S -@@ -7,6 +7,8 @@ - #include - #include - #include -+#define USE_FINISH_CONSOLE_REG_2 -+#include - - /* - * "core" functions are low-level implementations that don't require -@@ -76,7 +78,7 @@ func console_cdns_register - - mov x0, x6 - mov x30, v7 -- finish_console_register cdns -+ finish_console_register cdns putc=1, getc=1, flush=1 - - register_fail: - ret x7 -diff --git a/drivers/console/aarch32/console.S b/drivers/console/aarch32/console.S -index a3c6546..f909609 100644 ---- a/drivers/console/aarch32/console.S -+++ b/drivers/console/aarch32/console.S -@@ -3,104 +3,9 @@ - * - * SPDX-License-Identifier: BSD-3-Clause - */ --#include - -- .globl console_init -- .globl console_uninit -- .globl console_putc -- .globl console_getc -- .globl console_flush -- -- /* -- * The console base is in the data section and not in .bss -- * even though it is zero-init. In particular, this allows -- * the console functions to start using this variable before -- * the runtime memory is initialized for images which do not -- * need to copy the .data section from ROM to RAM. -- */ --.section .data.console_base ; .align 2 -- console_base: .word 0x0 -- -- /* ----------------------------------------------- -- * int console_init(uintptr_t base_addr, -- * unsigned int uart_clk, unsigned int baud_rate) -- * Function to initialize the console without a -- * C Runtime to print debug information. It saves -- * the console base to the data section. -- * In: r0 - console base address -- * r1 - Uart clock in Hz -- * r2 - Baud rate -- * out: return 1 on success else 0 on error -- * Clobber list : r1 - r3 -- * ----------------------------------------------- -- */ --func console_init -- /* Check the input base address */ -- cmp r0, #0 -- beq init_fail -- ldr r3, =console_base -- str r0, [r3] -- b console_core_init --init_fail: -- bx lr --endfunc console_init -- -- /* ----------------------------------------------- -- * void console_uninit(void) -- * Function to finish the use of console driver. -- * It sets the console_base as NULL so that any -- * further invocation of `console_putc` or -- * `console_getc` APIs would return error. -- * ----------------------------------------------- -- */ --func console_uninit -- mov r0, #0 -- ldr r3, =console_base -- str r0, [r3] -- bx lr --endfunc console_uninit -- -- /* --------------------------------------------- -- * int console_putc(int c) -- * Function to output a character over the -- * console. It returns the character printed on -- * success or -1 on error. -- * In : r0 - character to be printed -- * Out : return -1 on error else return character. -- * Clobber list : r1, r2 -- * --------------------------------------------- -- */ --func console_putc -- ldr r2, =console_base -- ldr r1, [r2] -- b console_core_putc --endfunc console_putc -- -- /* --------------------------------------------- -- * int console_getc(void) -- * Function to get a character from the console. -- * It returns the character grabbed on success -- * or -1 on error. -- * Clobber list : r0, r1 -- * --------------------------------------------- -- */ --func console_getc -- ldr r1, =console_base -- ldr r0, [r1] -- b console_core_getc --endfunc console_getc -- -- /* --------------------------------------------- -- * int console_flush(void) -- * Function to force a write of all buffered -- * data that hasn't been output. It returns 0 -- * upon successful completion, otherwise it -- * returns -1. -- * Clobber list : r0, r1 -- * --------------------------------------------- -- */ --func console_flush -- ldr r1, =console_base -- ldr r0, [r1] -- b console_core_flush --endfunc console_flush -+ #if MULTI_CONSOLE_API -+ #include "multi_console.S" -+ #else -+ #include "deprecated_console.S" -+ #endif -diff --git a/drivers/console/aarch32/deprecated_console.S b/drivers/console/aarch32/deprecated_console.S -new file mode 100644 -index 0000000..f7e3c4f ---- /dev/null -+++ b/drivers/console/aarch32/deprecated_console.S -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+#include -+ -+/* -+ * This is the common console core code for the deprecated single-console API. -+ * New platforms should set MULTI_CONSOLE_API=1 and not use this file. -+ */ -+#warning "Using deprecated console implementation. Please migrate to MULTI_CONSOLE_API" -+ -+ .globl console_init -+ .globl console_uninit -+ .globl console_putc -+ .globl console_getc -+ .globl console_flush -+ -+ /* -+ * The console base is in the data section and not in .bss -+ * even though it is zero-init. In particular, this allows -+ * the console functions to start using this variable before -+ * the runtime memory is initialized for images which do not -+ * need to copy the .data section from ROM to RAM. -+ */ -+.section .data.console_base ; .align 2 -+ console_base: .word 0x0 -+ -+ /* ----------------------------------------------- -+ * int console_init(uintptr_t base_addr, -+ * unsigned int uart_clk, unsigned int baud_rate) -+ * Function to initialize the console without a -+ * C Runtime to print debug information. It saves -+ * the console base to the data section. -+ * In: r0 - console base address -+ * r1 - Uart clock in Hz -+ * r2 - Baud rate -+ * out: return 1 on success else 0 on error -+ * Clobber list : r1 - r3 -+ * ----------------------------------------------- -+ */ -+func console_init -+ /* Check the input base address */ -+ cmp r0, #0 -+ beq init_fail -+ ldr r3, =console_base -+ str r0, [r3] -+ b console_core_init -+init_fail: -+ bx lr -+endfunc console_init -+ -+ /* ----------------------------------------------- -+ * void console_uninit(void) -+ * Function to finish the use of console driver. -+ * It sets the console_base as NULL so that any -+ * further invocation of `console_putc` or -+ * `console_getc` APIs would return error. -+ * ----------------------------------------------- -+ */ -+func console_uninit -+ mov r0, #0 -+ ldr r3, =console_base -+ str r0, [r3] -+ bx lr -+endfunc console_uninit -+ -+ /* --------------------------------------------- -+ * int console_putc(int c) -+ * Function to output a character over the -+ * console. It returns the character printed on -+ * success or -1 on error. -+ * In : r0 - character to be printed -+ * Out : return -1 on error else return character. -+ * Clobber list : r1, r2 -+ * --------------------------------------------- -+ */ -+func console_putc -+ ldr r2, =console_base -+ ldr r1, [r2] -+ b console_core_putc -+endfunc console_putc -+ -+ /* --------------------------------------------- -+ * int console_getc(void) -+ * Function to get a character from the console. -+ * It returns the character grabbed on success -+ * or -1 on error. -+ * Clobber list : r0, r1 -+ * --------------------------------------------- -+ */ -+func console_getc -+ ldr r1, =console_base -+ ldr r0, [r1] -+ b console_core_getc -+endfunc console_getc -+ -+ /* --------------------------------------------- -+ * int console_flush(void) -+ * Function to force a write of all buffered -+ * data that hasn't been output. It returns 0 -+ * upon successful completion, otherwise it -+ * returns -1. -+ * Clobber list : r0, r1 -+ * --------------------------------------------- -+ */ -+func console_flush -+ ldr r1, =console_base -+ ldr r0, [r1] -+ b console_core_flush -+endfunc console_flush -diff --git a/drivers/console/aarch32/multi_console.S b/drivers/console/aarch32/multi_console.S -new file mode 100644 -index 0000000..e23b20e ---- /dev/null -+++ b/drivers/console/aarch32/multi_console.S -@@ -0,0 +1,318 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+ .globl console_register -+ .globl console_unregister -+ .globl console_is_registered -+ .globl console_set_scope -+ .globl console_switch_state -+ .globl console_putc -+ .globl console_getc -+ .globl console_flush -+ -+ /* -+ * The console list pointer is in the data section and not in -+ * .bss even though it is zero-init. In particular, this allows -+ * the console functions to start using this variable before -+ * the runtime memory is initialized for images which do not -+ * need to copy the .data section from ROM to RAM. -+ */ -+.section .data.console_list ; .align 2 -+ console_list: .word 0x0 -+.section .data.console_state ; .align 0 -+ console_state: .byte CONSOLE_FLAG_BOOT -+ -+ /* ----------------------------------------------- -+ * int console_register(console_t *console) -+ * Function to insert a new console structure into -+ * the console list. Should usually be called by -+ * console__register implementations. The -+ * data structure passed will be taken over by the -+ * console framework and *MUST* be allocated in -+ * persistent memory (e.g. the data section). -+ * In : r0 - address of console_t structure -+ * Out: r0 - Always 1 (for easier tail calling) -+ * Clobber list: r0, r1 -+ * ----------------------------------------------- -+ */ -+func console_register -+ push {r6, lr} -+#if ENABLE_ASSERTIONS -+ /* Assert that r0 isn't a NULL pointer */ -+ cmp r0, #0 -+ ASM_ASSERT(ne) -+ /* Assert that the struct isn't in the stack */ -+ ldr r1, =__STACKS_START__ -+ cmp r0, r1 -+ blo not_on_stack -+ ldr r1, =__STACKS_END__ -+ cmp r0, r1 -+ ASM_ASSERT(hs) -+not_on_stack: -+ /* Assert that this struct isn't in the list */ -+ mov r1, r0 /* Preserve r0 and lr */ -+ bl console_is_registered -+ cmp r0, #0 -+ ASM_ASSERT(eq) -+ mov r0, r1 -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r6, =console_list -+ ldr r1, [r6] /* R1 = first struct in list */ -+ str r0, [r6] /* list head = new console */ -+ str r1, [r0, #CONSOLE_T_NEXT] /* new console next ptr = R1 */ -+ mov r0, #1 -+ pop {r6, pc} -+endfunc console_register -+ -+ /* ----------------------------------------------- -+ * int console_unregister(console_t *console) -+ * Function to find a specific console in the list -+ * of currently active consoles and remove it. -+ * In: r0 - address of console_t struct to remove -+ * Out: r0 - removed address, or NULL if not found -+ * Clobber list: r0, r1 -+ * ----------------------------------------------- -+ */ -+func console_unregister -+#if ENABLE_ASSERTIONS -+ /* Assert that r0 isn't a NULL pointer */ -+ cmp r0, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ push {r6} -+ ldr r6, =console_list /* R6 = ptr to first struct */ -+ ldr r1, [r6] /* R1 = first struct */ -+ -+unregister_loop: -+ cmp r1, #0 -+ beq unregister_not_found -+ cmp r0, r1 -+ beq unregister_found -+ ldr r6, [r6] /* R6 = next ptr of struct */ -+ ldr r1, [r6] /* R1 = next struct */ -+ b unregister_loop -+ -+unregister_found: -+ ldr r1, [r1] /* R1 = next struct */ -+ str r1, [r6] /* prev->next = cur->next */ -+ pop {r6} -+ bx lr -+ -+unregister_not_found: -+ mov r0, #0 /* return NULL if not found */ -+ pop {r6} -+ bx lr -+endfunc console_unregister -+ -+ /* ----------------------------------------------- -+ * int console_is_registered(console_t *console) -+ * Function to detect if a specific console is -+ * registered or not. -+ * In: r0 - address of console_t struct to remove -+ * Out: r0 - 1 if it is registered, 0 if not. -+ * Clobber list: r0 -+ * ----------------------------------------------- -+ */ -+func console_is_registered -+#if ENABLE_ASSERTIONS -+ /* Assert that r0 isn't a NULL pointer */ -+ cmp r0, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ push {r6} -+ ldr r6, =console_list -+ ldr r6, [r6] /* R6 = first console struct */ -+check_registered_loop: -+ cmp r6, #0 /* Check if end of list */ -+ beq console_not_registered -+ cmp r0, r6 /* Check if the pointers are different */ -+ beq console_registered -+ ldr r6, [r6, #CONSOLE_T_NEXT] /* Get pointer to next struct */ -+ b check_registered_loop -+console_not_registered: -+ mov r0, #0 -+ pop {r6} -+ bx lr -+console_registered: -+ mov r0, #1 -+ pop {r6} -+ bx lr -+endfunc console_is_registered -+ -+ /* ----------------------------------------------- -+ * void console_switch_state(unsigned int new_state) -+ * Function to switch the current console state. -+ * The console state determines which of the -+ * registered consoles are actually used at a time. -+ * In : r0 - global console state to move to -+ * Clobber list: r0, r1 -+ * ----------------------------------------------- -+ */ -+func console_switch_state -+ ldr r1, =console_state -+ strb r0, [r1] -+ bx lr -+endfunc console_switch_state -+ -+ /* ----------------------------------------------- -+ * void console_set_scope(console_t *console, -+ * unsigned int scope) -+ * Function to update the states that a given console -+ * may be active in. -+ * In : r0 - pointer to console_t struct -+ * : r1 - new active state mask -+ * Clobber list: r0, r1, r2 -+ * ----------------------------------------------- -+ */ -+func console_set_scope -+#if ENABLE_ASSERTIONS -+ ands r2, r1, #~CONSOLE_FLAG_SCOPE_MASK -+ ASM_ASSERT(eq) -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r2, [r0, #CONSOLE_T_FLAGS] -+ and r2, r2, #~CONSOLE_FLAG_SCOPE_MASK -+ orr r2, r2, r1 -+ str r2, [r0, #CONSOLE_T_FLAGS] -+ bx lr -+endfunc console_set_scope -+ -+ /* --------------------------------------------- -+ * int console_putc(int c) -+ * Function to output a character. Calls all -+ * active console's putc() handlers in succession. -+ * In : r0 - character to be printed -+ * Out: r0 - printed character on success, or < 0 -+ if at least one console had an error -+ * Clobber list : r0, r1, r2 -+ * --------------------------------------------- -+ */ -+func console_putc -+ push {r4-r6, lr} -+ mov r5, #ERROR_NO_VALID_CONSOLE /* R5 = current return value */ -+ mov r4, r0 /* R4 = character to print */ -+ ldr r6, =console_list -+ ldr r6, [r6] /* R6 = first console struct */ -+ -+putc_loop: -+ cmp r6, #0 -+ beq putc_done -+ ldr r1, =console_state -+ ldrb r1, [r1] -+ ldr r2, [r6, #CONSOLE_T_FLAGS] -+ tst r1, r2 -+ beq putc_continue -+ ldr r2, [r6, #CONSOLE_T_PUTC] -+ cmp r2, #0 -+ beq putc_continue -+ mov r0, r4 -+ mov r1, r6 -+ blx r2 -+ cmp r5, #ERROR_NO_VALID_CONSOLE /* update R5 if it's NOVALID */ -+ cmpne r0, #0 /* else update it if R0 < 0 */ -+ movlt r5, r0 -+putc_continue: -+ ldr r6, [r6] /* R6 = next struct */ -+ b putc_loop -+ -+putc_done: -+ mov r0, r5 -+ pop {r4-r6, pc} -+endfunc console_putc -+ -+ /* --------------------------------------------- -+ * int console_getc(void) -+ * Function to get a character from any console. -+ * Keeps looping through all consoles' getc() -+ * handlers until one of them returns a -+ * character, then stops iterating and returns -+ * that character to the caller. Will stop looping -+ * if all active consoles report real errors -+ * (other than just not having a char available). -+ * Out : r0 - read character, or < 0 on error -+ * Clobber list : r0, r1 -+ * --------------------------------------------- -+ */ -+func console_getc -+ push {r5-r6, lr} -+getc_try_again: -+ mov r5, #ERROR_NO_VALID_CONSOLE /* R5 = current return value */ -+ ldr r6, =console_list -+ ldr r6, [r6] /* R6 = first console struct */ -+ cmp r6, #0 -+ bne getc_loop -+ mov r0, r5 /* If no consoles registered */ -+ pop {r5-r6, pc} /* return immediately. */ -+ -+getc_loop: -+ ldr r0, =console_state -+ ldrb r0, [r0] -+ ldr r1, [r6, #CONSOLE_T_FLAGS] -+ tst r0, r1 -+ beq getc_continue -+ ldr r1, [r6, #CONSOLE_T_GETC] -+ cmp r1, #0 -+ beq getc_continue -+ mov r0, r6 -+ blx r1 -+ cmp r0, #0 /* if R0 >= 0: return */ -+ bge getc_found -+ cmp r5, #ERROR_NO_PENDING_CHAR /* may update R5 (NOCHAR has */ -+ movne r5, r0 /* precedence vs real errors) */ -+getc_continue: -+ ldr r6, [r6] /* R6 = next struct */ -+ cmp r6, #0 -+ bne getc_loop -+ cmp r5, #ERROR_NO_PENDING_CHAR /* Keep scanning if at least */ -+ beq getc_try_again /* one console returns NOCHAR */ -+ mov r0, r5 -+ -+getc_found: -+ pop {r5-r6, pc} -+endfunc console_getc -+ -+ /* --------------------------------------------- -+ * int console_flush(void) -+ * Function to force a write of all buffered -+ * data that hasn't been output. Calls all -+ * console's flush() handlers in succession. -+ * Out: r0 - 0 on success, < 0 if at least one error -+ * Clobber list : r0, r1, r2 -+ * --------------------------------------------- -+ */ -+func console_flush -+ push {r5-r6, lr} -+ mov r5, #ERROR_NO_VALID_CONSOLE /* R5 = current return value */ -+ ldr r6, =console_list -+ ldr r6, [r6] /* R6 = first console struct */ -+ -+flush_loop: -+ cmp r6, #0 -+ beq flush_done -+ ldr r1, =console_state -+ ldrb r1, [r1] -+ ldr r2, [r6, #CONSOLE_T_FLAGS] -+ tst r1, r2 -+ beq flush_continue -+ ldr r1, [r6, #CONSOLE_T_FLUSH] -+ cmp r1, #0 -+ beq flush_continue -+ mov r0, r6 -+ blx r1 -+ cmp r5, #ERROR_NO_VALID_CONSOLE /* update R5 if it's NOVALID */ -+ cmpne r0, #0 /* else update it if R0 < 0 */ -+ movlt r5, r0 -+flush_continue: -+ ldr r6, [r6] /* R6 = next struct */ -+ b flush_loop -+ -+flush_done: -+ mov r0, r5 -+ pop {r5-r6, pc} -+endfunc console_flush -diff --git a/drivers/console/aarch64/skeleton_console.S b/drivers/console/aarch64/skeleton_console.S -index 1b5d739..3993eef 100644 ---- a/drivers/console/aarch64/skeleton_console.S -+++ b/drivers/console/aarch64/skeleton_console.S -@@ -4,6 +4,7 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - #include -+#define USE_FINISH_CONSOLE_REG_2 - #include - - /* -@@ -60,8 +61,12 @@ func console_xxx_register - * Keep console_t pointer in x0 for later. +diff --git a/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c b/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c +index a0fc034d8..dcd199148 100644 +--- a/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c ++++ b/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c +@@ -26,9 +26,9 @@ typedef struct { + * valid. */ + int in_use; +- uintptr_t base; +- size_t file_pos; +- size_t size; ++ uintptr_t base; ++ unsigned long long file_pos; ++ unsigned long long size; + } file_state_t; -- /* Macro to finish up registration and return (needs valid x0 + x30). */ -- finish_console_register xxx -+ /* -+ * Macro to finish up registration and return (needs valid x0 + x30). -+ * If any of the argument is unspecified, then the corresponding -+ * entry in console_t is set to 0. -+ */ -+ finish_console_register xxx putc=1, getc=1, flush=1 - - /* Jump here if hardware init fails or parameters are invalid. */ - register_fail: -diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S -index 2fc0603..ae9a25b 100644 ---- a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S -+++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S -@@ -6,6 +6,7 @@ - - #include - #include -+#define USE_FINISH_CONSOLE_REG_2 - #include - - /* -@@ -39,7 +40,7 @@ func console_cbmc_register - ldr w2, [x0] - str w2, [x1, #CONSOLE_T_CBMC_SIZE] - mov x0, x1 -- finish_console_register cbmc -+ finish_console_register cbmc putc=1, flush=1 - endfunc console_cbmc_register - - /* ----------------------------------------------- -diff --git a/drivers/io/io_block.c b/drivers/io/io_block.c -index 8226554..3a2f403 100644 ---- a/drivers/io/io_block.c -+++ b/drivers/io/io_block.c -@@ -27,7 +27,7 @@ io_type_t device_type_block(void); - - static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, - io_entity_t *entity); --static int block_seek(io_entity_t *entity, int mode, ssize_t offset); -+static int block_seek(io_entity_t *entity, int mode, signed long long offset); - static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, - size_t *length_read); - static int block_write(io_entity_t *entity, const uintptr_t buffer, -@@ -67,8 +67,10 @@ io_type_t device_type_block(void) - static int find_first_block_state(const io_block_dev_spec_t *dev_spec, - unsigned int *index_out) - { -+ unsigned int index; - int result = -ENOENT; -- for (int index = 0; index < MAX_IO_BLOCK_DEVICES; ++index) { -+ -+ for (index = 0U; index < MAX_IO_BLOCK_DEVICES; ++index) { - /* dev_spec is used as identifier since it's unique */ - if (state_pool[index].dev_spec == dev_spec) { - result = 0; -@@ -144,7 +146,7 @@ static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, - } - - /* parameter offset is relative address at here */ --static int block_seek(io_entity_t *entity, int mode, ssize_t offset) -+static int block_seek(io_entity_t *entity, int mode, signed long long offset) - { - block_dev_state_t *cur; - -diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c -index 5595e60..8add0b8 100644 ---- a/drivers/io/io_memmap.c -+++ b/drivers/io/io_memmap.c -@@ -40,7 +40,7 @@ static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); + static file_state_t current_file = {0}; +@@ -44,7 +44,7 @@ static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, io_entity_t *entity); static int memmap_block_seek(io_entity_t *entity, int mode, @@ -2996,7 +2588,7 @@ index 5595e60..8add0b8 100644 static int memmap_block_len(io_entity_t *entity, size_t *length); static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, size_t length, size_t *length_read); -@@ -127,7 +127,8 @@ static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, +@@ -131,7 +131,8 @@ static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, /* Seek to a particular file offset on the memmap device */ @@ -3006,8 +2598,634 @@ index 5595e60..8add0b8 100644 { int result = -ENOENT; file_state_t *fp; +@@ -143,7 +144,8 @@ static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset) + fp = (file_state_t *) entity->info; + + /* Assert that new file position is valid */ +- assert((offset >= 0) && (offset < fp->size)); ++ assert((offset >= 0) && ++ ((unsigned long long)offset < fp->size)); + + /* Reset file position */ + fp->file_pos = offset; +@@ -171,7 +173,7 @@ static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) + { + file_state_t *fp; +- size_t pos_after; ++ unsigned long long pos_after; + + assert(entity != NULL); + assert(length_read != NULL); +@@ -198,7 +200,7 @@ static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) + { + file_state_t *fp; +- size_t pos_after; ++ unsigned long long pos_after; + + assert(entity != NULL); + assert(length_written != NULL); +diff --git a/drivers/io/io_block.c b/drivers/io/io_block.c +index f190a4307..5d45c2f17 100644 +--- a/drivers/io/io_block.c ++++ b/drivers/io/io_block.c +@@ -19,17 +19,17 @@ + typedef struct { + io_block_dev_spec_t *dev_spec; + uintptr_t base; +- size_t file_pos; +- size_t size; ++ unsigned long long file_pos; ++ unsigned long long size; + } block_dev_state_t; + +-#define is_power_of_2(x) ((x != 0) && ((x & (x - 1)) == 0)) ++#define is_power_of_2(x) (((x) != 0U) && (((x) & ((x) - 1U)) == 0U)) + + io_type_t device_type_block(void); + + static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +-static int block_seek(io_entity_t *entity, int mode, ssize_t offset); ++static int block_seek(io_entity_t *entity, int mode, signed long long offset); + static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); + static int block_write(io_entity_t *entity, const uintptr_t buffer, +@@ -148,21 +148,21 @@ static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, + } + + /* parameter offset is relative address at here */ +-static int block_seek(io_entity_t *entity, int mode, ssize_t offset) ++static int block_seek(io_entity_t *entity, int mode, signed long long offset) + { + block_dev_state_t *cur; + + assert(entity->info != (uintptr_t)NULL); + + cur = (block_dev_state_t *)entity->info; +- assert((offset >= 0) && (offset < cur->size)); ++ assert((offset >= 0) && ((unsigned long long)offset < cur->size)); + + switch (mode) { + case IO_SEEK_SET: +- cur->file_pos = offset; ++ cur->file_pos = (unsigned long long)offset; + break; + case IO_SEEK_CUR: +- cur->file_pos += offset; ++ cur->file_pos += (unsigned long long)offset; + break; + default: + return -EINVAL; +@@ -270,7 +270,7 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + buf = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((length <= cur->size) && +- (length > 0) && ++ (length > 0U) && + (ops->read != 0)); + + /* +@@ -279,7 +279,7 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + * on the low level driver. + */ + count = 0; +- for (left = length; left > 0; left -= nbytes) { ++ for (left = length; left > 0U; left -= nbytes) { + /* + * We must only request operations aligned to the block + * size. Therefore if file_pos is not block-aligned, +@@ -288,7 +288,7 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + * similarly, the number of bytes requested must be a + * block size multiple + */ +- skip = cur->file_pos & (block_size - 1); ++ skip = cur->file_pos & (block_size - 1U); + + /* + * Calculate the block number containing file_pos +@@ -296,7 +296,7 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + */ + lba = (cur->file_pos + cur->base) / block_size; + +- if (skip + left > buf->length) { ++ if ((skip + left) > buf->length) { + /* + * The underlying read buffer is too small to + * read all the required data - limit to just +@@ -311,7 +311,8 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + * block size. + */ + request = skip + left; +- request = (request + (block_size - 1)) & ~(block_size - 1); ++ request = (request + (block_size - 1U)) & ++ ~(block_size - 1U); + } + request = ops->read(lba, buf->offset, request); + +@@ -330,7 +331,7 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + * the read data when copying to the user buffer. + */ + nbytes = request - skip; +- padding = (nbytes > left) ? nbytes - left : 0; ++ padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + memcpy((void *)(buffer + count), +@@ -381,7 +382,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + buf = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((length <= cur->size) && +- (length > 0) && ++ (length > 0U) && + (ops->read != 0) && + (ops->write != 0)); + +@@ -391,7 +392,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + * on the low level driver. + */ + count = 0; +- for (left = length; left > 0; left -= nbytes) { ++ for (left = length; left > 0U; left -= nbytes) { + /* + * We must only request operations aligned to the block + * size. Therefore if file_pos is not block-aligned, +@@ -400,7 +401,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + * similarly, the number of bytes requested must be a + * block size multiple + */ +- skip = cur->file_pos & (block_size - 1); ++ skip = cur->file_pos & (block_size - 1U); + + /* + * Calculate the block number containing file_pos +@@ -408,7 +409,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + */ + lba = (cur->file_pos + cur->base) / block_size; + +- if (skip + left > buf->length) { ++ if ((skip + left) > buf->length) { + /* + * The underlying read buffer is too small to + * read all the required data - limit to just +@@ -423,7 +424,8 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + * block size. + */ + request = skip + left; +- request = (request + (block_size - 1)) & ~(block_size - 1); ++ request = (request + (block_size - 1U)) & ++ ~(block_size - 1U); + } + + /* +@@ -432,7 +434,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + * of the current request. + */ + nbytes = request - skip; +- padding = (nbytes > left) ? nbytes - left : 0; ++ padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + /* +@@ -440,14 +442,14 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + * some content and it means that we have to read before + * writing + */ +- if (skip > 0 || padding > 0) { ++ if ((skip > 0U) || (padding > 0U)) { + request = ops->read(lba, buf->offset, request); + /* + * The read may return size less than + * requested. Round down to the nearest block + * boundary + */ +- request &= ~(block_size-1); ++ request &= ~(block_size - 1U); + if (request <= skip) { + /* + * We couldn't read enough bytes to jump over +@@ -458,7 +460,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + return -EIO; + } + nbytes = request - skip; +- padding = (nbytes > left) ? nbytes - left : 0; ++ padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + } + +@@ -477,7 +479,7 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer, + * buffer + */ + nbytes = request - skip; +- padding = (nbytes > left) ? nbytes - left : 0; ++ padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + cur->file_pos += nbytes; +@@ -505,7 +507,7 @@ static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) + + assert(dev_info != NULL); + result = allocate_dev_info(&info); +- if (result) ++ if (result != 0) + return -ENOENT; + + cur = (block_dev_state_t *)info->info; +@@ -513,10 +515,10 @@ static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) + cur->dev_spec = (io_block_dev_spec_t *)dev_spec; + buffer = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; +- assert((block_size > 0) && +- (is_power_of_2(block_size) != 0) && +- ((buffer->offset % block_size) == 0) && +- ((buffer->length % block_size) == 0)); ++ assert((block_size > 0U) && ++ (is_power_of_2(block_size) != 0U) && ++ ((buffer->offset % block_size) == 0U) && ++ ((buffer->length % block_size) == 0U)); + + *dev_info = info; /* cast away const */ + (void)block_size; +diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c +index 544b37dbe..5d49fffaa 100644 +--- a/drivers/io/io_fip.c ++++ b/drivers/io/io_fip.c +@@ -304,7 +304,8 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + } + + /* Seek past the FIP header into the Table of Contents */ +- result = io_seek(backend_handle, IO_SEEK_SET, sizeof(fip_toc_header_t)); ++ result = io_seek(backend_handle, IO_SEEK_SET, ++ (signed long long)sizeof(fip_toc_header_t)); + if (result != 0) { + WARN("fip_file_open: failed to seek\n"); + result = -ENOENT; +@@ -389,7 +390,8 @@ static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + + /* Seek to the position in the FIP where the payload lives */ + file_offset = fp->entry.offset_address + fp->file_pos; +- result = io_seek(backend_handle, IO_SEEK_SET, file_offset); ++ result = io_seek(backend_handle, IO_SEEK_SET, ++ (signed long long)file_offset); + if (result != 0) { + WARN("fip_file_read: failed to seek\n"); + result = -ENOENT; +diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c +index 96590b6c0..eed50cc08 100644 +--- a/drivers/io/io_memmap.c ++++ b/drivers/io/io_memmap.c +@@ -23,10 +23,10 @@ typedef struct { + /* Use the 'in_use' flag as any value for base and file_pos could be + * valid. + */ +- int in_use; +- uintptr_t base; +- size_t file_pos; +- size_t size; ++ int in_use; ++ uintptr_t base; ++ unsigned long long file_pos; ++ unsigned long long size; + } file_state_t; + + static file_state_t current_file = {0}; +@@ -42,7 +42,7 @@ static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); + static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); + static int memmap_block_seek(io_entity_t *entity, int mode, +- ssize_t offset); ++ signed long long offset); + static int memmap_block_len(io_entity_t *entity, size_t *length); + static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +@@ -129,7 +129,8 @@ static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + + + /* Seek to a particular file offset on the memmap device */ +-static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset) ++static int memmap_block_seek(io_entity_t *entity, int mode, ++ signed long long offset) + { + int result = -ENOENT; + file_state_t *fp; +@@ -141,10 +142,11 @@ static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset) + fp = (file_state_t *) entity->info; + + /* Assert that new file position is valid */ +- assert((offset >= 0) && (offset < fp->size)); ++ assert((offset >= 0) && ++ ((unsigned long long)offset < fp->size)); + + /* Reset file position */ +- fp->file_pos = offset; ++ fp->file_pos = (unsigned long long)offset; + result = 0; + } + +@@ -158,7 +160,7 @@ static int memmap_block_len(io_entity_t *entity, size_t *length) + assert(entity != NULL); + assert(length != NULL); + +- *length = ((file_state_t *)entity->info)->size; ++ *length = (size_t)((file_state_t *)entity->info)->size; + + return 0; + } +@@ -169,7 +171,7 @@ static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) + { + file_state_t *fp; +- size_t pos_after; ++ unsigned long long pos_after; + + assert(entity != NULL); + assert(length_read != NULL); +@@ -180,7 +182,8 @@ static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + +- memcpy((void *)buffer, (void *)(fp->base + fp->file_pos), length); ++ memcpy((void *)buffer, ++ (void *)((uintptr_t)(fp->base + fp->file_pos)), length); + + *length_read = length; + +@@ -196,7 +199,7 @@ static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) + { + file_state_t *fp; +- size_t pos_after; ++ unsigned long long pos_after; + + assert(entity != NULL); + assert(length_written != NULL); +@@ -207,7 +210,8 @@ static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + +- memcpy((void *)(fp->base + fp->file_pos), (void *)buffer, length); ++ memcpy((void *)((uintptr_t)(fp->base + fp->file_pos)), ++ (void *)buffer, length); + + *length_written = length; + +diff --git a/drivers/io/io_mtd.c b/drivers/io/io_mtd.c +new file mode 100644 +index 000000000..7575fa250 +--- /dev/null ++++ b/drivers/io/io_mtd.c +@@ -0,0 +1,248 @@ ++/* ++ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++typedef struct { ++ io_mtd_dev_spec_t *dev_spec; ++ uintptr_t base; ++ unsigned long long offset; /* Offset in bytes */ ++ unsigned long long size; /* Size of device in bytes */ ++} mtd_dev_state_t; ++ ++io_type_t device_type_mtd(void); ++ ++static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, ++ io_entity_t *entity); ++static int mtd_seek(io_entity_t *entity, int mode, signed long long offset); ++static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, ++ size_t *length_read); ++static int mtd_close(io_entity_t *entity); ++static int mtd_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); ++static int mtd_dev_close(io_dev_info_t *dev_info); ++ ++static const io_dev_connector_t mtd_dev_connector = { ++ .dev_open = mtd_dev_open ++}; ++ ++static const io_dev_funcs_t mtd_dev_funcs = { ++ .type = device_type_mtd, ++ .open = mtd_open, ++ .seek = mtd_seek, ++ .read = mtd_read, ++ .close = mtd_close, ++ .dev_close = mtd_dev_close, ++}; ++ ++static mtd_dev_state_t state_pool[MAX_IO_MTD_DEVICES]; ++static io_dev_info_t dev_info_pool[MAX_IO_MTD_DEVICES]; ++ ++io_type_t device_type_mtd(void) ++{ ++ return IO_TYPE_MTD; ++} ++ ++/* Locate a MTD state in the pool, specified by address */ ++static int find_first_mtd_state(const io_mtd_dev_spec_t *dev_spec, ++ unsigned int *index_out) ++{ ++ unsigned int index; ++ int result = -ENOENT; ++ ++ for (index = 0U; index < MAX_IO_MTD_DEVICES; index++) { ++ /* dev_spec is used as identifier since it's unique */ ++ if (state_pool[index].dev_spec == dev_spec) { ++ result = 0; ++ *index_out = index; ++ break; ++ } ++ } ++ ++ return result; ++} ++ ++/* Allocate a device info from the pool */ ++static int allocate_dev_info(io_dev_info_t **dev_info) ++{ ++ unsigned int index = 0U; ++ int result; ++ ++ result = find_first_mtd_state(NULL, &index); ++ if (result != 0) { ++ return -ENOMEM; ++ } ++ ++ dev_info_pool[index].funcs = &mtd_dev_funcs; ++ dev_info_pool[index].info = (uintptr_t)&state_pool[index]; ++ *dev_info = &dev_info_pool[index]; ++ ++ return 0; ++} ++ ++/* Release a device info from the pool */ ++static int free_dev_info(io_dev_info_t *dev_info) ++{ ++ int result; ++ unsigned int index = 0U; ++ mtd_dev_state_t *state; ++ ++ state = (mtd_dev_state_t *)dev_info->info; ++ result = find_first_mtd_state(state->dev_spec, &index); ++ if (result != 0) { ++ return result; ++ } ++ ++ zeromem(state, sizeof(mtd_dev_state_t)); ++ zeromem(dev_info, sizeof(io_dev_info_t)); ++ ++ return 0; ++} ++ ++static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, ++ io_entity_t *entity) ++{ ++ mtd_dev_state_t *cur; ++ ++ assert((dev_info->info != 0UL) && (entity->info == 0UL)); ++ ++ cur = (mtd_dev_state_t *)dev_info->info; ++ entity->info = (uintptr_t)cur; ++ cur->offset = 0U; ++ ++ return 0; ++} ++ ++/* Seek to a specific position using offset */ ++static int mtd_seek(io_entity_t *entity, int mode, signed long long offset) ++{ ++ mtd_dev_state_t *cur; ++ ++ assert((entity->info != (uintptr_t)NULL) && (offset >= 0)); ++ ++ cur = (mtd_dev_state_t *)entity->info; ++ ++ switch (mode) { ++ case IO_SEEK_SET: ++ if ((offset >= 0) && ++ ((unsigned long long)offset >= cur->size)) { ++ return -EINVAL; ++ } ++ ++ cur->offset = offset; ++ break; ++ case IO_SEEK_CUR: ++ if (((cur->offset + (unsigned long long)offset) >= ++ cur->size) || ++ ((cur->offset + (unsigned long long)offset) < ++ cur->offset)) { ++ return -EINVAL; ++ } ++ ++ cur->offset += (unsigned long long)offset; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, ++ size_t *out_length) ++{ ++ mtd_dev_state_t *cur; ++ io_mtd_ops_t *ops; ++ int ret; ++ ++ assert(entity->info != (uintptr_t)NULL); ++ assert((length > 0U) && (buffer != (uintptr_t)NULL)); ++ ++ cur = (mtd_dev_state_t *)entity->info; ++ ops = &cur->dev_spec->ops; ++ assert(ops->read != NULL); ++ ++ VERBOSE("Read at %llx into %lx, length %zi\n", ++ cur->offset, buffer, length); ++ if ((cur->offset + length) > cur->dev_spec->device_size) { ++ return -EINVAL; ++ } ++ ++ ret = ops->read(cur->offset, buffer, length, out_length); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ assert(*out_length == length); ++ cur->offset += *out_length; ++ ++ return 0; ++} ++ ++static int mtd_close(io_entity_t *entity) ++{ ++ entity->info = (uintptr_t)NULL; ++ ++ return 0; ++} ++ ++static int mtd_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) ++{ ++ mtd_dev_state_t *cur; ++ io_dev_info_t *info; ++ io_mtd_ops_t *ops; ++ int result; ++ ++ result = allocate_dev_info(&info); ++ if (result != 0) { ++ return -ENOENT; ++ } ++ ++ cur = (mtd_dev_state_t *)info->info; ++ cur->dev_spec = (io_mtd_dev_spec_t *)dev_spec; ++ *dev_info = info; ++ ops = &(cur->dev_spec->ops); ++ if (ops->init != NULL) { ++ result = ops->init(&cur->dev_spec->device_size, ++ &cur->dev_spec->erase_size); ++ } ++ ++ if (result == 0) { ++ cur->size = cur->dev_spec->device_size; ++ } else { ++ cur->size = 0ULL; ++ } ++ ++ return result; ++} ++ ++static int mtd_dev_close(io_dev_info_t *dev_info) ++{ ++ return free_dev_info(dev_info); ++} ++ ++/* Exported functions */ ++ ++/* Register the MTD driver in the IO abstraction */ ++int register_io_dev_mtd(const io_dev_connector_t **dev_con) ++{ ++ int result; ++ ++ result = io_register_device(&dev_info_pool[0]); ++ if (result == 0) { ++ *dev_con = &mtd_dev_connector; ++ } ++ ++ return result; ++} diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c -index 9ca0a9d..125fea9 100644 +index 23d09c118..4ceddc6cc 100644 --- a/drivers/io/io_semihosting.c +++ b/drivers/io/io_semihosting.c @@ -25,7 +25,7 @@ static io_type_t device_type_sh(void) @@ -3028,11 +3246,20 @@ index 9ca0a9d..125fea9 100644 { long file_handle, sh_result; +@@ -98,7 +98,7 @@ static int sh_file_seek(io_entity_t *entity, int mode, ssize_t offset) + + file_handle = (long)entity->info; + +- sh_result = semihosting_file_seek(file_handle, offset); ++ sh_result = semihosting_file_seek(file_handle, (ssize_t)offset); + + return (sh_result == 0) ? 0 : -ENOENT; + } diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c -index 948f848..90282a2 100644 +index e444f87f7..b8c1d6479 100644 --- a/drivers/io/io_storage.c +++ b/drivers/io/io_storage.c -@@ -239,7 +239,7 @@ int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle) +@@ -237,7 +237,7 @@ int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle) /* Seek to a specific position in an IO entity */ @@ -3042,1170 +3269,2681 @@ index 948f848..90282a2 100644 int result = -ENODEV; assert(is_valid_entity(handle) && is_valid_seek_mode(mode)); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c -index 418ab11..4f9cecf 100644 +index b5f6a10d3..42243ea09 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -246,6 +246,13 @@ static int mmc_fill_device_info(void) - return ret; - } +@@ -25,6 +25,7 @@ + static const struct mmc_ops *ops; + static unsigned int mmc_ocr_value; + static struct mmc_csd_emmc mmc_csd; ++static struct sd_switch_status sd_switch_func_status; + static unsigned char mmc_ext_csd[512] __aligned(16); + static unsigned int mmc_flags; + static struct mmc_device_info *mmc_dev_info; +@@ -44,6 +45,11 @@ static bool is_cmd23_enabled(void) + return ((mmc_flags & MMC_FLAG_CMD23) != 0U); + } -+ do { -+ ret = mmc_device_state(); -+ if (ret < 0) { -+ return ret; -+ } -+ } while (ret != MMC_STATE_TRAN); ++static bool is_sd_cmd6_enabled(void) ++{ ++ return ((mmc_flags & MMC_FLAG_SD_CMD6) != 0U); ++} + - nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) | - (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) | - (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) | -@@ -292,7 +299,7 @@ static int mmc_fill_device_info(void) - break; - } + static int mmc_send_cmd(unsigned int idx, unsigned int arg, + unsigned int r_type, unsigned int *r_data) + { +@@ -327,6 +333,33 @@ static int mmc_fill_device_info(void) + return 0; + } -- if (ret != 0) { -+ if (ret < 0) { ++static int sd_switch(unsigned char mode, unsigned char group, ++ unsigned char func) ++{ ++ unsigned int group_shift = (group - 1U) * 4U; ++ unsigned int group_mask = GENMASK(group_shift + 3U, group_shift); ++ unsigned int arg; ++ int ret = 0; ++ ++ ret = ops->prepare(0, (uintptr_t)&sd_switch_func_status, ++ sizeof(sd_switch_func_status)); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* MMC CMD6: SWITCH_FUNC */ ++ arg = (mode << 31) | GENMASK(23, 0); ++ arg &= ~group_mask; ++ arg |= func << group_shift; ++ ret = mmc_send_cmd(MMC_CMD(6), arg, MMC_RESPONSE_R1, NULL); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return ops->read(0, (uintptr_t)&sd_switch_func_status, ++ sizeof(sd_switch_func_status)); ++} ++ + static int sd_send_op_cond(void) + { + int n; +@@ -494,7 +527,39 @@ static int mmc_enumerate(unsigned int clk, unsigned int bus_width) return ret; } -@@ -379,7 +386,10 @@ static int mmc_send_op_cond(void) - int ret, n; - unsigned int resp_data[4]; - -- mmc_reset_to_idle(); -+ ret = mmc_reset_to_idle(); +- return mmc_fill_device_info(); ++ ret = mmc_fill_device_info(); + if (ret != 0) { + return ret; -+ }; - - for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) { - ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE | -@@ -394,7 +404,7 @@ static int mmc_send_op_cond(void) - return 0; - } - -- mdelay(1); -+ mdelay(10); - } - - ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES); -@@ -409,7 +419,10 @@ static int mmc_enumerate(unsigned int clk, unsigned int bus_width) - - ops->init(); - -- mmc_reset_to_idle(); -+ ret = mmc_reset_to_idle(); -+ if (ret != 0) { -+ return ret; -+ }; - - if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { - ret = mmc_send_op_cond(); -diff --git a/drivers/partition/gpt.c b/drivers/partition/gpt.c -index 9cc917d..0c51e62 100644 ---- a/drivers/partition/gpt.c -+++ b/drivers/partition/gpt.c -@@ -13,10 +13,14 @@ - - static int unicode_to_ascii(unsigned short *str_in, unsigned char *str_out) - { -- uint8_t *name = (uint8_t *)str_in; -+ uint8_t *name; - int i; - -- assert((str_in != NULL) && (str_out != NULL) && (name[0] != '\0')); -+ assert((str_in != NULL) && (str_out != NULL)); ++ } + -+ name = (uint8_t *)str_in; ++ if (is_sd_cmd6_enabled() && ++ (mmc_dev_info->mmc_dev_type == MMC_IS_SD_HC)) { ++ /* Try to switch to High Speed Mode */ ++ ret = sd_switch(SD_SWITCH_FUNC_CHECK, 1U, 1U); ++ if (ret != 0) { ++ return ret; ++ } + -+ assert(name[0] != '\0'); - - /* check whether the unicode string is valid */ - for (i = 1; i < (EFI_NAMELEN << 1); i += 2) { -@@ -36,7 +40,7 @@ int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry) - { - int result; - -- assert((gpt_entry != 0) && (entry != 0)); -+ assert((gpt_entry != NULL) && (entry != NULL)); - - if ((gpt_entry->first_lba == 0) && (gpt_entry->last_lba == 0)) { - return -EINVAL; -diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c -index d6fb4b8..6085b86 100644 ---- a/drivers/partition/partition.c -+++ b/drivers/partition/partition.c -@@ -30,7 +30,7 @@ static void dump_entries(int num) - name[len + j] = ' '; - } - name[EFI_NAMELEN - 1] = '\0'; -- VERBOSE("%d: %s %lx-%lx\n", i + 1, name, list.list[i].start, -+ VERBOSE("%d: %s %llx-%llx\n", i + 1, name, list.list[i].start, - list.list[i].start + list.list[i].length - 4); - } ++ if ((sd_switch_func_status.support_g1 & BIT(9)) == 0U) { ++ /* High speed not supported, keep default speed */ ++ return 0; ++ } ++ ++ ret = sd_switch(SD_SWITCH_FUNC_SWITCH, 1U, 1U); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if ((sd_switch_func_status.sel_g2_g1 & 0x1U) == 0U) { ++ /* Cannot switch to high speed, keep default speed */ ++ return 0; ++ } ++ ++ mmc_dev_info->max_bus_freq = 50000000U; ++ ret = ops->set_ios(clk, bus_width); ++ } ++ ++ return ret; } -diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c + + size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size) +diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c new file mode 100644 -index 0000000..c579c41 +index 000000000..44b001e35 --- /dev/null -+++ b/drivers/st/bsec/bsec.c -@@ -0,0 +1,911 @@ ++++ b/drivers/mtd/nand/core.c +@@ -0,0 +1,118 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#include ++#include + -+#define BSEC_IP_VERSION_1_0 0x10 -+#define BSEC_COMPAT "st,stm32mp15-bsec" ++#include + -+#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) ++#include ++#include ++#include ++#include + -+static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused; ++/* ++ * Define a single nand_device used by specific NAND frameworks. ++ */ ++static struct nand_device nand_dev; ++static uint8_t scratch_buff[PLATFORM_MTD_MAX_PAGE_SIZE]; + -+static uint32_t bsec_power_safmem(bool power); -+ -+/* BSEC access protection */ -+static spinlock_t bsec_spinlock; -+static uintptr_t bsec_base; -+ -+static void bsec_lock(void) ++int nand_read(unsigned int offset, uintptr_t buffer, size_t length, ++ size_t *length_read) +{ -+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT; ++ unsigned int block = offset / nand_dev.block_size; ++ unsigned int end_block = (offset + length - 1U) / nand_dev.block_size; ++ unsigned int page_start = ++ (offset % nand_dev.block_size) / nand_dev.page_size; ++ unsigned int nb_pages = nand_dev.block_size / nand_dev.page_size; ++ unsigned int start_offset = offset % nand_dev.page_size; ++ unsigned int page; ++ unsigned int bytes_read; ++ int is_bad; ++ int ret; + -+ /* Lock is currently required only when MMU and cache are enabled */ -+ if ((read_sctlr() & mask) == mask) { -+ spin_lock(&bsec_spinlock); -+ } -+} ++ VERBOSE("Block %u - %u, page_start %u, nb %u, length %zu, offset %u\n", ++ block, end_block, page_start, nb_pages, length, offset); + -+static void bsec_unlock(void) -+{ -+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT; ++ *length_read = 0UL; + -+ /* Unlock is required only when MMU and cache are enabled */ -+ if ((read_sctlr() & mask) == mask) { -+ spin_unlock(&bsec_spinlock); -+ } -+} -+ -+static int bsec_get_dt_node(struct dt_node_info *info) -+{ -+ int node; -+ -+ node = dt_get_node(info, -1, BSEC_COMPAT); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; ++ if (((start_offset != 0U) || (length % nand_dev.page_size) != 0U) && ++ (sizeof(scratch_buff) < nand_dev.page_size)) { ++ return -EINVAL; + } + -+ return node; -+} ++ while (block <= end_block) { ++ is_bad = nand_dev.mtd_block_is_bad(block); ++ if (is_bad < 0) { ++ return is_bad; ++ } + -+#if defined(IMAGE_BL32) -+static void enable_non_secure_access(uint32_t otp) -+{ -+ otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); ++ if (is_bad == 1) { ++ /* Skip the block */ ++ uint32_t max_block = ++ nand_dev.size / nand_dev.block_size; + -+ if (bsec_shadow_register(otp) != BSEC_OK) { -+ panic(); ++ block++; ++ end_block++; ++ if ((block < max_block) && (end_block < max_block)) { ++ continue; ++ } ++ ++ return -EIO; ++ } ++ ++ for (page = page_start; page < nb_pages; page++) { ++ if ((start_offset != 0U) || ++ (length < nand_dev.page_size)) { ++ ret = nand_dev.mtd_read_page( ++ &nand_dev, ++ (block * nb_pages) + page, ++ (uintptr_t)scratch_buff); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ bytes_read = MIN((size_t)(nand_dev.page_size - ++ start_offset), ++ length); ++ ++ memcpy((uint8_t *)buffer, ++ scratch_buff + start_offset, ++ bytes_read); ++ ++ start_offset = 0U; ++ } else { ++ ret = nand_dev.mtd_read_page(&nand_dev, ++ (block * nb_pages) + page, ++ buffer); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ bytes_read = nand_dev.page_size; ++ } ++ ++ length -= bytes_read; ++ buffer += bytes_read; ++ *length_read += bytes_read; ++ ++ if (length == 0U) { ++ break; ++ } ++ } ++ ++ page_start = 0U; ++ block++; + } ++ ++ return 0; +} + -+static bool non_secure_can_access(uint32_t otp) ++struct nand_device *get_nand_device(void) +{ -+ return (otp_nsec_access[otp / __WORD_BIT] & -+ BIT(otp % __WORD_BIT)) != 0; ++ return &nand_dev; ++} +diff --git a/drivers/mtd/nand/raw_nand.c b/drivers/mtd/nand/raw_nand.c +new file mode 100644 +index 000000000..48131fcb2 +--- /dev/null ++++ b/drivers/mtd/nand/raw_nand.c +@@ -0,0 +1,446 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define ONFI_SIGNATURE_ADDR 0x20U ++ ++/* CRC calculation */ ++#define CRC_POLYNOM 0x8005U ++#define CRC_INIT_VALUE 0x4F4EU ++ ++/* Status register */ ++#define NAND_STATUS_READY BIT(6) ++ ++#define SZ_128M 0x08000000U ++#define SZ_512 0x200U ++ ++static struct rawnand_device rawnand_dev; ++ ++#pragma weak plat_get_raw_nand_data ++int plat_get_raw_nand_data(struct rawnand_device *device) ++{ ++ return 0; +} + -+static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node) ++static int nand_send_cmd(uint8_t cmd, unsigned int tim) +{ -+ int bsec_subnode; ++ struct nand_req req; + -+ fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { -+ const fdt32_t *cuint; -+ uint32_t reg; -+ uint32_t i; -+ uint32_t size; -+ uint8_t status; ++ zeromem(&req, sizeof(struct nand_req)); ++ req.nand = rawnand_dev.nand_dev; ++ req.type = NAND_REQ_CMD | cmd; ++ req.inst_delay = tim; + -+ cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); -+ if (cuint == NULL) { -+ panic(); ++ return rawnand_dev.ops->exec(&req); ++} ++ ++static int nand_send_addr(uint8_t addr, unsigned int tim) ++{ ++ struct nand_req req; ++ ++ zeromem(&req, sizeof(struct nand_req)); ++ req.nand = rawnand_dev.nand_dev; ++ req.type = NAND_REQ_ADDR; ++ req.addr = &addr; ++ req.inst_delay = tim; ++ ++ return rawnand_dev.ops->exec(&req); ++} ++ ++static int nand_send_wait(unsigned int delay, unsigned int tim) ++{ ++ struct nand_req req; ++ ++ zeromem(&req, sizeof(struct nand_req)); ++ req.nand = rawnand_dev.nand_dev; ++ req.type = NAND_REQ_WAIT; ++ req.inst_delay = tim; ++ req.delay_ms = delay; ++ ++ return rawnand_dev.ops->exec(&req); ++} ++ ++ ++static int nand_read_data(uint8_t *data, unsigned int length, bool use_8bit) ++{ ++ struct nand_req req; ++ ++ zeromem(&req, sizeof(struct nand_req)); ++ req.nand = rawnand_dev.nand_dev; ++ req.type = NAND_REQ_DATAIN | (use_8bit ? NAND_REQ_BUS_WIDTH_8 : 0U); ++ req.addr = data; ++ req.length = length; ++ ++ return rawnand_dev.ops->exec(&req); ++} ++ ++int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer, ++ unsigned int len) ++{ ++ int ret; ++ uint8_t addr[2]; ++ unsigned int i; ++ ++ ret = nand_send_cmd(NAND_CMD_CHANGE_1ST, 0U); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (rawnand_dev.nand_dev->buswidth == NAND_BUS_WIDTH_16) { ++ offset /= 2U; ++ } ++ ++ addr[0] = offset; ++ addr[1] = offset >> 8; ++ ++ for (i = 0; i < 2U; i++) { ++ ret = nand_send_addr(addr[i], 0U); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ ret = nand_send_cmd(NAND_CMD_CHANGE_2ND, NAND_TCCS_MIN); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return nand_read_data((uint8_t *)buffer, len, false); ++} ++ ++int nand_read_page_cmd(unsigned int page, unsigned int offset, ++ uintptr_t buffer, unsigned int len) ++{ ++ uint8_t addr[5]; ++ uint8_t i = 0U; ++ uint8_t j; ++ int ret; ++ ++ VERBOSE(">%s page %u offset %u buffer 0x%lx\n", __func__, page, offset, ++ buffer); ++ ++ if (rawnand_dev.nand_dev->buswidth == NAND_BUS_WIDTH_16) { ++ offset /= 2U; ++ } ++ ++ addr[i++] = offset; ++ addr[i++] = offset >> 8; ++ ++ addr[i++] = page; ++ addr[i++] = page >> 8; ++ if (rawnand_dev.nand_dev->size > SZ_128M) { ++ addr[i++] = page >> 16; ++ } ++ ++ ret = nand_send_cmd(NAND_CMD_READ_1ST, 0U); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ for (j = 0U; j < i; j++) { ++ ret = nand_send_addr(addr[j], 0U); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ ret = nand_send_cmd(NAND_CMD_READ_2ND, NAND_TWB_MAX); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = nand_send_wait(PSEC_TO_MSEC(NAND_TR_MAX), NAND_TRR_MIN); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (buffer != 0U) { ++ ret = nand_read_data((uint8_t *)buffer, len, false); ++ } ++ ++ return ret; ++} ++ ++static int nand_status(uint8_t *status) ++{ ++ int ret; ++ ++ ret = nand_send_cmd(NAND_CMD_STATUS, NAND_TWHR_MIN); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (status != NULL) { ++ ret = nand_read_data(status, 1U, true); ++ } ++ ++ return ret; ++} ++ ++int nand_wait_ready(unsigned long delay) ++{ ++ uint8_t status; ++ int ret; ++ uint64_t timeout; ++ ++ /* Wait before reading status */ ++ udelay(1); ++ ++ ret = nand_status(NULL); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ timeout = timeout_init_us(delay); ++ while (!timeout_elapsed(timeout)) { ++ ret = nand_read_data(&status, 1U, true); ++ if (ret != 0) { ++ return ret; + } + -+ reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t); -+ if (reg < STM32MP1_UPPER_OTP_START) { -+ continue; ++ if ((status & NAND_STATUS_READY) != 0U) { ++ return nand_send_cmd(NAND_CMD_READ_1ST, 0U); + } + -+ status = fdt_get_status(bsec_subnode); -+ if ((status & DT_NON_SECURE) == 0U) { -+ continue; ++ udelay(10); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++#if NAND_ONFI_DETECT ++static uint16_t nand_check_crc(uint16_t crc, uint8_t *data_in, ++ unsigned int data_len) ++{ ++ uint32_t i; ++ uint32_t j; ++ uint32_t bit; ++ ++ for (i = 0U; i < data_len; i++) { ++ uint8_t cur_param = *data_in++; ++ ++ for (j = BIT(7); j != 0U; j >>= 1) { ++ bit = crc & BIT(15); ++ crc <<= 1; ++ ++ if ((cur_param & j) != 0U) { ++ bit ^= BIT(15); ++ } ++ ++ if (bit != 0U) { ++ crc ^= CRC_POLYNOM; ++ } + } + -+ size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t); ++ crc &= GENMASK(15, 0); ++ } + -+ if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) { -+ size++; ++ return crc; ++} ++ ++static int nand_read_id(uint8_t addr, uint8_t *id, unsigned int size) ++{ ++ int ret; ++ ++ ret = nand_send_cmd(NAND_CMD_READID, 0U); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = nand_send_addr(addr, NAND_TWHR_MIN); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return nand_read_data(id, size, true); ++} ++ ++static int nand_reset(void) ++{ ++ int ret; ++ ++ ret = nand_send_cmd(NAND_CMD_RESET, NAND_TWB_MAX); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return nand_send_wait(PSEC_TO_MSEC(NAND_TRST_MAX), 0U); ++} ++ ++static int nand_read_param_page(void) ++{ ++ struct nand_param_page page; ++ uint8_t addr = 0U; ++ int ret; ++ ++ ret = nand_send_cmd(NAND_CMD_READ_PARAM_PAGE, 0U); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = nand_send_addr(addr, NAND_TWB_MAX); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = nand_send_wait(PSEC_TO_MSEC(NAND_TR_MAX), NAND_TRR_MIN); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = nand_read_data((uint8_t *)&page, sizeof(page), true); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (strncmp((char *)&page.page_sig, "ONFI", 4) != 0) { ++ WARN("Error ONFI detection\n"); ++ return -EINVAL; ++ } ++ ++ if (nand_check_crc(CRC_INIT_VALUE, (uint8_t *)&page, 254U) != ++ page.crc16) { ++ WARN("Error reading param\n"); ++ return -EINVAL; ++ } ++ ++ if ((page.features & ONFI_FEAT_BUS_WIDTH_16) != 0U) { ++ rawnand_dev.nand_dev->buswidth = NAND_BUS_WIDTH_16; ++ } else { ++ rawnand_dev.nand_dev->buswidth = NAND_BUS_WIDTH_8; ++ } ++ ++ rawnand_dev.nand_dev->block_size = page.num_pages_per_blk * ++ page.bytes_per_page; ++ rawnand_dev.nand_dev->page_size = page.bytes_per_page; ++ rawnand_dev.nand_dev->size = page.num_pages_per_blk * ++ page.bytes_per_page * ++ page.num_blk_in_lun * page.num_lun; ++ ++ if (page.nb_ecc_bits != GENMASK_32(7, 0)) { ++ rawnand_dev.nand_dev->ecc.max_bit_corr = page.nb_ecc_bits; ++ rawnand_dev.nand_dev->ecc.size = SZ_512; ++ } ++ ++ VERBOSE("Page size %u, block_size %u, Size %llu, ecc %u, buswidth %u\n", ++ rawnand_dev.nand_dev->page_size, ++ rawnand_dev.nand_dev->block_size, rawnand_dev.nand_dev->size, ++ rawnand_dev.nand_dev->ecc.max_bit_corr, ++ rawnand_dev.nand_dev->buswidth); ++ ++ return 0; ++} ++ ++static int detect_onfi(void) ++{ ++ int ret; ++ char id[4]; ++ ++ ret = nand_reset(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = nand_read_id(ONFI_SIGNATURE_ADDR, (uint8_t *)id, sizeof(id)); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (strncmp(id, "ONFI", sizeof(id)) != 0) { ++ WARN("NAND Non ONFI detected\n"); ++ return -ENODEV; ++ } ++ ++ return nand_read_param_page(); ++} ++#endif ++ ++static int nand_mtd_block_is_bad(unsigned int block) ++{ ++ unsigned int nbpages_per_block = rawnand_dev.nand_dev->block_size / ++ rawnand_dev.nand_dev->page_size; ++ uint8_t bbm_marker[2]; ++ uint8_t page; ++ int ret; ++ ++ for (page = 0U; page < 2U; page++) { ++ ret = nand_read_page_cmd(block * nbpages_per_block, ++ rawnand_dev.nand_dev->page_size, ++ (uintptr_t)bbm_marker, ++ sizeof(bbm_marker)); ++ if (ret != 0) { ++ return ret; + } + -+ for (i = reg; i < (reg + size); i++) { -+ enable_non_secure_access(i); ++ if ((bbm_marker[0] != GENMASK_32(7, 0)) || ++ (bbm_marker[1] != GENMASK_32(7, 0))) { ++ WARN("Block %u is bad\n", block); ++ return 1; + } + } + + return 0; +} ++ ++static int nand_mtd_read_page_raw(struct nand_device *nand, unsigned int page, ++ uintptr_t buffer) ++{ ++ return nand_read_page_cmd(page, 0U, buffer, ++ rawnand_dev.nand_dev->page_size); ++} ++ ++void nand_raw_ctrl_init(const struct nand_ctrl_ops *ops) ++{ ++ rawnand_dev.ops = ops; ++} ++ ++int nand_raw_init(unsigned long long *size, unsigned int *erase_size) ++{ ++ rawnand_dev.nand_dev = get_nand_device(); ++ if (rawnand_dev.nand_dev == NULL) { ++ return -EINVAL; ++ } ++ ++ rawnand_dev.nand_dev->mtd_block_is_bad = nand_mtd_block_is_bad; ++ rawnand_dev.nand_dev->mtd_read_page = nand_mtd_read_page_raw; ++ rawnand_dev.nand_dev->ecc.mode = NAND_ECC_NONE; ++ ++ if ((rawnand_dev.ops->setup == NULL) || ++ (rawnand_dev.ops->exec == NULL)) { ++ return -ENODEV; ++ } ++ ++#if NAND_ONFI_DETECT ++ if (detect_onfi() != 0) { ++ WARN("Detect ONFI failed\n"); ++ } +#endif + -+static uint32_t otp_bank_offset(uint32_t otp) -+{ -+ assert(otp <= STM32MP1_OTP_MAX_ID); -+ -+ return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * -+ sizeof(uint32_t); -+} -+ -+static uint32_t bsec_check_error(uint32_t otp) -+{ -+ 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 (plat_get_raw_nand_data(&rawnand_dev) != 0) { ++ return -EINVAL; + } + -+ if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) { -+ return BSEC_ERROR; -+ } ++ assert((rawnand_dev.nand_dev->page_size != 0U) && ++ (rawnand_dev.nand_dev->block_size != 0U) && ++ (rawnand_dev.nand_dev->size != 0U)); + -+ return BSEC_OK; ++ *size = rawnand_dev.nand_dev->size; ++ *erase_size = rawnand_dev.nand_dev->block_size; ++ ++ rawnand_dev.ops->setup(rawnand_dev.nand_dev); ++ ++ return 0; +} -+ +diff --git a/drivers/mtd/nand/spi_nand.c b/drivers/mtd/nand/spi_nand.c +new file mode 100644 +index 000000000..d01a11963 +--- /dev/null ++++ b/drivers/mtd/nand/spi_nand.c +@@ -0,0 +1,320 @@ +/* -+ * bsec_probe: initialize BSEC driver. -+ * return value: BSEC_OK if no error. ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause + */ -+uint32_t bsec_probe(void) ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define SPI_NAND_MAX_ID_LEN 4U ++#define DELAY_US_400MS 400000U ++#define MACRONIX_ID 0xC2U ++ ++static struct spinand_device spinand_dev; ++ ++#pragma weak plat_get_spi_nand_data ++int plat_get_spi_nand_data(struct spinand_device *device) +{ -+ void *fdt; -+ int node; -+ struct dt_node_info bsec_info; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ node = bsec_get_dt_node(&bsec_info); -+ if (node < 0) { -+ panic(); -+ } -+ -+ bsec_base = bsec_info.base; -+ -+#if defined(IMAGE_BL32) -+ bsec_dt_otp_nsec_access(fdt, node); -+#endif -+ return BSEC_OK; ++ return 0; +} + -+/* -+ * bsec_get_base: return BSEC base address. -+ */ -+uint32_t bsec_get_base(void) ++static int spi_nand_reg(bool read_reg, uint8_t reg, uint8_t *val, ++ enum spi_mem_data_dir dir) +{ -+ return bsec_base; -+} ++ struct spi_mem_op op; + -+/* -+ * bsec_set_config: enable and configure BSEC. -+ * cfg: pointer to param structure used to set register. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_set_config(struct bsec_config *cfg) -+{ -+ uint32_t value; -+ int32_t result; -+ -+ value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) & -+ BSEC_CONF_FRQ_MASK) | -+ (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) & -+ BSEC_CONF_PRG_WIDTH_MASK) | -+ (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) & -+ BSEC_CONF_TREAD_MASK)); -+ -+ bsec_lock(); -+ -+ mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value); -+ -+ bsec_unlock(); -+ -+ result = bsec_power_safmem((bool)cfg->power & -+ BSEC_CONF_POWER_UP_MASK); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) & -+ UPPER_OTP_LOCK_MASK) | -+ (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) & -+ DENREG_LOCK_MASK) | -+ (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) & -+ GPLOCK_LOCK_MASK)); -+ -+ bsec_lock(); -+ -+ mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value); -+ -+ bsec_unlock(); -+ -+ return BSEC_OK; -+} -+ -+/* -+ * bsec_get_config: return config parameters set in BSEC registers. -+ * cfg: config param return. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_get_config(struct bsec_config *cfg) -+{ -+ uint32_t value; -+ -+ if (cfg == NULL) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); -+ cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >> -+ BSEC_CONF_POWER_UP_SHIFT); -+ cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >> -+ BSEC_CONF_FRQ_SHIFT); -+ cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >> -+ BSEC_CONF_PRG_WIDTH_SHIFT); -+ cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >> -+ BSEC_CONF_TREAD_SHIFT); -+ -+ value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF); -+ cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >> -+ UPPER_OTP_LOCK_SHIFT); -+ cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >> -+ DENREG_LOCK_SHIFT); -+ cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >> -+ GPLOCK_LOCK_SHIFT); -+ -+ return BSEC_OK; -+} -+ -+/* -+ * bsec_shadow_register: copy SAFMEM OTP to BSEC data. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_shadow_register(uint32_t otp) -+{ -+ uint32_t result; -+ bool power_up = false; -+ -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ /* Check if shadowing of OTP is locked */ -+ if (bsec_read_sr_lock(otp)) { -+ VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n", -+ otp); -+ } -+ -+ if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { -+ result = bsec_power_safmem(true); -+ -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ power_up = true; -+ } -+ -+ 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); -+ -+ bsec_unlock(); -+ -+ if (power_up) { -+ if (bsec_power_safmem(false) != BSEC_OK) { -+ panic(); -+ } -+ } -+ -+ return result; -+} -+ -+/* -+ * bsec_read_otp: read an OTP data value. -+ * val: read value. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+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; -+} -+ -+/* -+ * bsec_write_otp: write value in BSEC data register. -+ * val: value to write. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_write_otp(uint32_t val, uint32_t otp) -+{ -+ uint32_t result; -+ -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ /* Check if programming of OTP is locked */ -+ if (bsec_read_sw_lock(otp)) { -+ VERBOSE("BSEC: OTP %i is locked and write will be ignored\n", -+ otp); -+ } -+ -+ 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; -+} -+ -+/* -+ * bsec_program_otp: program a bit in SAFMEM after the prog. -+ * The OTP data is not refreshed. -+ * val: value to program. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_program_otp(uint32_t val, uint32_t otp) -+{ -+ uint32_t result; -+ bool power_up = false; -+ -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ /* Check if programming of OTP is locked */ -+ if (bsec_read_sp_lock(otp)) { -+ WARN("BSEC: OTP locked, prog will be ignored\n"); -+ } -+ -+ if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) & -+ BIT(BSEC_LOCK_PROGRAM)) != 0U) { -+ WARN("BSEC: GPLOCK activated, prog will be ignored\n"); -+ } -+ -+ if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { -+ result = bsec_power_safmem(true); -+ -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ power_up = true; -+ } -+ -+ 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) { -+ ; -+ } -+ -+ if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { -+ result = BSEC_PROG_FAIL; ++ zeromem(&op, sizeof(struct spi_mem_op)); ++ if (read_reg) { ++ op.cmd.opcode = SPI_NAND_OP_GET_FEATURE; + } else { -+ result = bsec_check_error(otp); ++ op.cmd.opcode = SPI_NAND_OP_SET_FEATURE; + } + -+ bsec_unlock(); ++ op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.addr.val = reg; ++ op.addr.nbytes = 1U; ++ op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.data.dir = dir; ++ op.data.nbytes = 1U; ++ op.data.buf = val; + -+ if (power_up) { -+ if (bsec_power_safmem(false) != BSEC_OK) { -+ panic(); ++ return spi_mem_exec_op(&op); ++} ++ ++static int spi_nand_read_reg(uint8_t reg, uint8_t *val) ++{ ++ return spi_nand_reg(true, reg, val, SPI_MEM_DATA_IN); ++} ++ ++static int spi_nand_write_reg(uint8_t reg, uint8_t val) ++{ ++ return spi_nand_reg(false, reg, &val, SPI_MEM_DATA_OUT); ++} ++ ++static int spi_nand_update_cfg(uint8_t mask, uint8_t val) ++{ ++ int ret; ++ uint8_t cfg = spinand_dev.cfg_cache; ++ ++ cfg &= ~mask; ++ cfg |= val; ++ ++ if (cfg == spinand_dev.cfg_cache) { ++ return 0; ++ } ++ ++ ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg); ++ if (ret == 0) { ++ spinand_dev.cfg_cache = cfg; ++ } ++ ++ return ret; ++} ++ ++static int spi_nand_ecc_enable(bool enable) ++{ ++ return spi_nand_update_cfg(SPI_NAND_CFG_ECC_EN, ++ enable ? SPI_NAND_CFG_ECC_EN : 0U); ++} ++ ++static int spi_nand_quad_enable(uint8_t manufacturer_id) ++{ ++ bool enable = false; ++ ++ if (manufacturer_id != MACRONIX_ID) { ++ return 0; ++ } ++ ++ if (spinand_dev.spi_read_cache_op.data.buswidth == ++ SPI_MEM_BUSWIDTH_4_LINE) { ++ enable = true; ++ } ++ ++ return spi_nand_update_cfg(SPI_NAND_CFG_QE, ++ enable ? SPI_NAND_CFG_QE : 0U); ++} ++ ++static int spi_nand_wait_ready(uint8_t *status) ++{ ++ int ret; ++ uint64_t timeout = timeout_init_us(DELAY_US_400MS); ++ ++ while (!timeout_elapsed(timeout)) { ++ ret = spi_nand_read_reg(SPI_NAND_REG_STATUS, status); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ VERBOSE("%s Status %x\n", __func__, *status); ++ if ((*status & SPI_NAND_STATUS_BUSY) == 0U) { ++ return 0; + } + } + -+ return result; ++ return -ETIMEDOUT; ++} ++ ++static int spi_nand_reset(void) ++{ ++ struct spi_mem_op op; ++ uint8_t status; ++ int ret; ++ ++ zeromem(&op, sizeof(struct spi_mem_op)); ++ op.cmd.opcode = SPI_NAND_OP_RESET; ++ op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ ++ ret = spi_mem_exec_op(&op); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return spi_nand_wait_ready(&status); ++} ++ ++static int spi_nand_read_id(uint8_t *id) ++{ ++ struct spi_mem_op op; ++ ++ zeromem(&op, sizeof(struct spi_mem_op)); ++ op.cmd.opcode = SPI_NAND_OP_READ_ID; ++ op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.data.dir = SPI_MEM_DATA_IN; ++ op.data.nbytes = SPI_NAND_MAX_ID_LEN; ++ op.data.buf = id; ++ op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ ++ return spi_mem_exec_op(&op); ++} ++ ++static int spi_nand_load_page(unsigned int page) ++{ ++ struct spi_mem_op op; ++ uint32_t block_nb = page / spinand_dev.nand_dev->block_size; ++ uint32_t page_nb = page - (block_nb * spinand_dev.nand_dev->page_size); ++ uint32_t nbpages_per_block = spinand_dev.nand_dev->block_size / ++ spinand_dev.nand_dev->page_size; ++ uint32_t block_sh = __builtin_ctz(nbpages_per_block) + 1U; ++ ++ zeromem(&op, sizeof(struct spi_mem_op)); ++ op.cmd.opcode = SPI_NAND_OP_LOAD_PAGE; ++ op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.addr.val = (block_nb << block_sh) | page_nb; ++ op.addr.nbytes = 3U; ++ op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ ++ return spi_mem_exec_op(&op); ++} ++ ++static int spi_nand_read_from_cache(unsigned int page, unsigned int offset, ++ uint8_t *buffer, unsigned int len) ++{ ++ uint32_t nbpages_per_block = spinand_dev.nand_dev->block_size / ++ spinand_dev.nand_dev->page_size; ++ uint32_t block_nb = page / nbpages_per_block; ++ uint32_t page_sh = __builtin_ctz(spinand_dev.nand_dev->page_size) + 1U; ++ ++ spinand_dev.spi_read_cache_op.addr.val = offset; ++ ++ if ((spinand_dev.nand_dev->nb_planes > 1U) && ((block_nb % 2U) == 1U)) { ++ spinand_dev.spi_read_cache_op.addr.val |= 1U << page_sh; ++ } ++ ++ spinand_dev.spi_read_cache_op.data.buf = buffer; ++ spinand_dev.spi_read_cache_op.data.nbytes = len; ++ ++ return spi_mem_exec_op(&spinand_dev.spi_read_cache_op); ++} ++ ++static int spi_nand_read_page(unsigned int page, unsigned int offset, ++ uint8_t *buffer, unsigned int len, ++ bool ecc_enabled) ++{ ++ uint8_t status; ++ int ret; ++ ++ ret = spi_nand_ecc_enable(ecc_enabled); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nand_load_page(page); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nand_wait_ready(&status); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nand_read_from_cache(page, offset, buffer, len); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (ecc_enabled && ((status & SPI_NAND_STATUS_ECC_UNCOR) != 0U)) { ++ return -EBADMSG; ++ } ++ ++ return 0; ++} ++ ++static int spi_nand_mtd_block_is_bad(unsigned int block) ++{ ++ unsigned int nbpages_per_block = spinand_dev.nand_dev->block_size / ++ spinand_dev.nand_dev->page_size; ++ uint8_t bbm_marker[2]; ++ int ret; ++ ++ ret = spi_nand_read_page(block * nbpages_per_block, ++ spinand_dev.nand_dev->page_size, ++ bbm_marker, sizeof(bbm_marker), false); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if ((bbm_marker[0] != GENMASK_32(7, 0)) || ++ (bbm_marker[1] != GENMASK_32(7, 0))) { ++ WARN("Block %i is bad\n", block); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int spi_nand_mtd_read_page(struct nand_device *nand, unsigned int page, ++ uintptr_t buffer) ++{ ++ return spi_nand_read_page(page, 0, (uint8_t *)buffer, ++ spinand_dev.nand_dev->page_size, true); ++} ++ ++int spi_nand_init(unsigned long long *size, unsigned int *erase_size) ++{ ++ uint8_t id[SPI_NAND_MAX_ID_LEN]; ++ int ret; ++ ++ spinand_dev.nand_dev = get_nand_device(); ++ if (spinand_dev.nand_dev == NULL) { ++ return -EINVAL; ++ } ++ ++ spinand_dev.nand_dev->mtd_block_is_bad = spi_nand_mtd_block_is_bad; ++ spinand_dev.nand_dev->mtd_read_page = spi_nand_mtd_read_page; ++ spinand_dev.nand_dev->nb_planes = 1; ++ ++ spinand_dev.spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE; ++ spinand_dev.spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ spinand_dev.spi_read_cache_op.addr.nbytes = 2U; ++ spinand_dev.spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ spinand_dev.spi_read_cache_op.dummy.nbytes = 1U; ++ spinand_dev.spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ spinand_dev.spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ ++ if (plat_get_spi_nand_data(&spinand_dev) != 0) { ++ return -EINVAL; ++ } ++ ++ ret = spi_nand_reset(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nand_read_id(id); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nand_read_reg(SPI_NAND_REG_CFG, &spinand_dev.cfg_cache); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nand_quad_enable(id[0]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ VERBOSE("SPI_NAND Detected ID 0x%x 0x%x\n", id[0], id[1]); ++ ++ VERBOSE("Page size %i, Block size %i, size %lli\n", ++ spinand_dev.nand_dev->page_size, ++ spinand_dev.nand_dev->block_size, ++ spinand_dev.nand_dev->size); ++ ++ *size = spinand_dev.nand_dev->size; ++ *erase_size = spinand_dev.nand_dev->block_size; ++ ++ return 0; ++} +diff --git a/drivers/mtd/nor/spi_nor.c b/drivers/mtd/nor/spi_nor.c +new file mode 100644 +index 000000000..2b4a5d87d +--- /dev/null ++++ b/drivers/mtd/nor/spi_nor.c +@@ -0,0 +1,387 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define SR_WIP BIT(0) /* Write in progress */ ++#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ ++#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ ++#define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */ ++ ++/* Defined IDs for supported memories */ ++#define SPANSION_ID 0x01U ++#define MACRONIX_ID 0xC2U ++#define MICRON_ID 0x2CU ++ ++#define BANK_SIZE 0x1000000U ++ ++#define SPI_READY_TIMEOUT_US 40000U ++ ++static struct nor_device nor_dev; ++ ++#pragma weak plat_get_nor_data ++int plat_get_nor_data(struct nor_device *device) ++{ ++ return 0; ++} ++ ++static int spi_nor_reg(uint8_t reg, uint8_t *buf, size_t len, ++ enum spi_mem_data_dir dir) ++{ ++ struct spi_mem_op op; ++ ++ zeromem(&op, sizeof(struct spi_mem_op)); ++ op.cmd.opcode = reg; ++ op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ op.data.dir = dir; ++ op.data.nbytes = len; ++ op.data.buf = buf; ++ ++ return spi_mem_exec_op(&op); ++} ++ ++static inline int spi_nor_read_id(uint8_t *id) ++{ ++ return spi_nor_reg(SPI_NOR_OP_READ_ID, id, 1U, SPI_MEM_DATA_IN); ++} ++ ++static inline int spi_nor_read_cr(uint8_t *cr) ++{ ++ return spi_nor_reg(SPI_NOR_OP_READ_CR, cr, 1U, SPI_MEM_DATA_IN); ++} ++ ++static inline int spi_nor_read_sr(uint8_t *sr) ++{ ++ return spi_nor_reg(SPI_NOR_OP_READ_SR, sr, 1U, SPI_MEM_DATA_IN); ++} ++ ++static inline int spi_nor_read_fsr(uint8_t *fsr) ++{ ++ return spi_nor_reg(SPI_NOR_OP_READ_FSR, fsr, 1U, SPI_MEM_DATA_IN); ++} ++ ++static inline int spi_nor_write_en(void) ++{ ++ return spi_nor_reg(SPI_NOR_OP_WREN, NULL, 0U, SPI_MEM_DATA_OUT); +} + +/* -+ * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. ++ * Check if device is ready. ++ * ++ * Return 0 if ready, 1 if busy or a negative error code otherwise + */ -+uint32_t bsec_permanent_lock_otp(uint32_t otp) ++static int spi_nor_ready(void) +{ -+ uint32_t result; -+ bool power_up = false; -+ uint32_t data; -+ uint32_t addr; ++ uint8_t sr; ++ int ret; + -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; ++ ret = spi_nor_read_sr(&sr); ++ if (ret != 0) { ++ return ret; + } + -+ if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { -+ result = bsec_power_safmem(true); ++ if ((nor_dev.flags & SPI_NOR_USE_FSR) != 0U) { ++ uint8_t fsr; + -+ if (result != BSEC_OK) { -+ return result; ++ ret = spi_nor_read_fsr(&fsr); ++ if (ret != 0) { ++ return ret; + } + -+ power_up = true; ++ return (((fsr & FSR_READY) != 0U) && ((sr & SR_WIP) == 0U)) ? ++ 0 : 1; + } + -+ if (otp < STM32MP1_UPPER_OTP_START) { -+ addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT; -+ data = DATA_LOWER_OTP_PERLOCK_BIT << -+ ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); -+ } else { -+ addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U; -+ data = DATA_UPPER_OTP_PERLOCK_BIT << -+ (otp & DATA_UPPER_OTP_PERLOCK_MASK); -+ } ++ return (((sr & SR_WIP) != 0U) ? 1 : 0); ++} + -+ bsec_lock(); ++static int spi_nor_wait_ready(void) ++{ ++ int ret; ++ uint64_t timeout = timeout_init_us(SPI_READY_TIMEOUT_US); + -+ /* 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); -+ -+ while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { -+ ; -+ } -+ -+ if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { -+ result = BSEC_PROG_FAIL; -+ } else { -+ result = bsec_check_error(otp); -+ } -+ -+ bsec_unlock(); -+ -+ if (power_up) { -+ if (bsec_power_safmem(false) != BSEC_OK) { -+ panic(); ++ while (!timeout_elapsed(timeout)) { ++ ret = spi_nor_ready(); ++ if (ret <= 0) { ++ return ret; + } + } + -+ return result; ++ return -ETIMEDOUT; +} + -+/* -+ * 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. -+ */ -+uint32_t bsec_write_debug_conf(uint32_t val) ++static int spi_nor_macronix_quad_enable(void) +{ -+ uint32_t result = BSEC_ERROR; -+ uint32_t masked_val = val & BSEC_DEN_ALL_MSK; ++ uint8_t sr; ++ int ret; + -+ bsec_lock(); -+ -+ mmio_write_32(bsec_base + BSEC_DEN_OFF, masked_val); -+ -+ if ((mmio_read_32(bsec_base + BSEC_DEN_OFF) ^ masked_val) == 0U) { -+ result = BSEC_OK; ++ ret = spi_nor_read_sr(&sr); ++ if (ret != 0) { ++ return ret; + } + -+ bsec_unlock(); ++ if ((sr & SR_QUAD_EN_MX) == 0U) { ++ return 0; ++ } + -+ return result; ++ ret = spi_nor_write_en(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ sr |= SR_QUAD_EN_MX; ++ ret = spi_nor_reg(SPI_NOR_OP_WRSR, &sr, 1, SPI_MEM_DATA_OUT); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nor_wait_ready(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nor_read_sr(&sr); ++ if ((ret != 0) || ((sr & SR_QUAD_EN_MX) == 0U)) { ++ return -EINVAL; ++ } ++ ++ return 0; +} + -+/* -+ * bsec_read_debug_conf: read debug configuration. -+ */ -+uint32_t bsec_read_debug_conf(void) ++static int spi_nor_write_sr_cr(uint8_t *sr_cr) +{ -+ return mmio_read_32(bsec_base + BSEC_DEN_OFF); ++ int ret; ++ ++ ret = spi_nor_write_en(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nor_reg(SPI_NOR_OP_WRSR, sr_cr, 2, SPI_MEM_DATA_OUT); ++ if (ret != 0) { ++ return -EINVAL; ++ } ++ ++ ret = spi_nor_wait_ready(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return 0; +} + -+/* -+ * bsec_get_status: return status register value. -+ */ -+uint32_t bsec_get_status(void) ++static int spi_nor_quad_enable(void) +{ -+ return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF); ++ uint8_t sr_cr[2]; ++ int ret; ++ ++ ret = spi_nor_read_cr(&sr_cr[1]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if ((sr_cr[1] & CR_QUAD_EN_SPAN) != 0U) { ++ return 0; ++ } ++ ++ sr_cr[1] |= CR_QUAD_EN_SPAN; ++ ret = spi_nor_read_sr(&sr_cr[0]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nor_write_sr_cr(sr_cr); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nor_read_cr(&sr_cr[1]); ++ if ((ret != 0) || ((sr_cr[1] & CR_QUAD_EN_SPAN) == 0U)) { ++ return -EINVAL; ++ } ++ ++ return 0; +} + -+/* -+ * bsec_get_hw_conf: return hardware configuration. -+ */ -+uint32_t bsec_get_hw_conf(void) ++static int spi_nor_clean_bar(void) +{ -+ return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF); ++ int ret; ++ ++ if (nor_dev.selected_bank == 0U) { ++ return 0; ++ } ++ ++ nor_dev.selected_bank = 0U; ++ ++ ret = spi_nor_write_en(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return spi_nor_reg(nor_dev.bank_write_cmd, &nor_dev.selected_bank, ++ 1, SPI_MEM_DATA_OUT); +} + -+/* -+ * bsec_get_version: return BSEC version. -+ */ -+uint32_t bsec_get_version(void) ++static int spi_nor_write_bar(uint32_t offset) +{ -+ return mmio_read_32(bsec_base + BSEC_IPVR_OFF); ++ uint8_t selected_bank = offset / BANK_SIZE; ++ int ret; ++ ++ if (selected_bank == nor_dev.selected_bank) { ++ return 0; ++ } ++ ++ ret = spi_nor_write_en(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = spi_nor_reg(nor_dev.bank_write_cmd, &selected_bank, ++ 1, SPI_MEM_DATA_OUT); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ nor_dev.selected_bank = selected_bank; ++ ++ return 0; +} + -+/* -+ * bsec_get_id: return BSEC ID. -+ */ -+uint32_t bsec_get_id(void) ++static int spi_nor_read_bar(void) +{ -+ return mmio_read_32(bsec_base + BSEC_IP_ID_OFF); ++ uint8_t selected_bank = 0; ++ int ret; ++ ++ ret = spi_nor_reg(nor_dev.bank_read_cmd, &selected_bank, ++ 1, SPI_MEM_DATA_IN); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ nor_dev.selected_bank = selected_bank; ++ ++ return 0; +} + -+/* -+ * bsec_get_magic_id: return BSEC magic number. -+ */ -+uint32_t bsec_get_magic_id(void) ++int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, ++ size_t *length_read) +{ -+ return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF); -+} ++ size_t remain_len; ++ int ret; + -+/* -+ * bsec_write_sr_lock: write 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. -+ */ -+bool bsec_write_sr_lock(uint32_t otp, uint32_t value) -+{ -+ bool result = false; -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t bank_value; -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); ++ *length_read = 0; ++ nor_dev.read_op.addr.val = offset; ++ nor_dev.read_op.data.buf = (void *)buffer; + -+ bsec_lock(); ++ VERBOSE("%s offset %i length %zu\n", __func__, offset, length); + -+ bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); ++ while (length != 0U) { ++ if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { ++ ret = spi_nor_write_bar(nor_dev.read_op.addr.val); ++ if (ret != 0) { ++ return ret; ++ } + -+ 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; ++ remain_len = (BANK_SIZE * (nor_dev.selected_bank + 1)) - ++ nor_dev.read_op.addr.val; ++ nor_dev.read_op.data.nbytes = MIN(length, remain_len); + } else { -+ bank_value = bank_value & ~otp_mask; ++ nor_dev.read_op.data.nbytes = length; + } + -+ /* -+ * 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; ++ ret = spi_mem_exec_op(&nor_dev.read_op); ++ if (ret != 0) { ++ spi_nor_clean_bar(); ++ return ret; ++ } ++ ++ length -= nor_dev.read_op.data.nbytes; ++ nor_dev.read_op.addr.val += nor_dev.read_op.data.nbytes; ++ nor_dev.read_op.data.buf += nor_dev.read_op.data.nbytes; ++ *length_read += nor_dev.read_op.data.nbytes; + } + -+ bsec_unlock(); -+ -+ return result; -+} -+ -+/* -+ * bsec_read_sr_lock: read shadow-read lock. -+ * otp: OTP number. -+ * return: true if otp is locked, else false. -+ */ -+bool bsec_read_sr_lock(uint32_t otp) -+{ -+ 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); -+ -+ return (bank_value & otp_mask) != 0U; -+} -+ -+/* -+ * bsec_write_sw_lock: write 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. -+ */ -+bool bsec_write_sw_lock(uint32_t otp, uint32_t value) -+{ -+ 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; ++ if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { ++ ret = spi_nor_clean_bar(); ++ if (ret != 0) { ++ return ret; + } -+ } 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; + } + -+ bsec_unlock(); -+ -+ return result; ++ return 0; +} + -+/* -+ * bsec_read_sw_lock: read shadow-write lock. -+ * otp: OTP number. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_read_sw_lock(uint32_t otp) ++int spi_nor_init(unsigned long long *size, unsigned int *erase_size) +{ -+ 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); ++ int ret = 0; ++ uint8_t id; + -+ return (bank_value & otp_mask) != 0U; -+} ++ /* Default read command used */ ++ nor_dev.read_op.cmd.opcode = SPI_NOR_OP_READ; ++ nor_dev.read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ nor_dev.read_op.addr.nbytes = 3U; ++ nor_dev.read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ nor_dev.read_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ nor_dev.read_op.data.dir = SPI_MEM_DATA_IN; + -+/* -+ * bsec_write_sp_lock: write 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. -+ */ -+bool bsec_write_sp_lock(uint32_t otp, uint32_t value) -+{ -+ 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 (plat_get_nor_data(&nor_dev) != 0) { ++ return -EINVAL; + } + -+ bsec_unlock(); ++ assert(nor_dev.size != 0); + -+ return result; ++ if (nor_dev.size > BANK_SIZE) { ++ nor_dev.flags |= SPI_NOR_USE_BANK; ++ } ++ ++ *size = nor_dev.size; ++ ++ ret = spi_nor_read_id(&id); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { ++ switch (id) { ++ case SPANSION_ID: ++ nor_dev.bank_read_cmd = SPINOR_OP_BRRD; ++ nor_dev.bank_write_cmd = SPINOR_OP_BRWR; ++ break; ++ default: ++ nor_dev.bank_read_cmd = SPINOR_OP_RDEAR; ++ nor_dev.bank_write_cmd = SPINOR_OP_WREAR; ++ break; ++ } ++ } ++ ++ if (nor_dev.read_op.data.buswidth == 4U) { ++ switch (id) { ++ case MACRONIX_ID: ++ INFO("Enable Macronix quad support\n"); ++ ret = spi_nor_macronix_quad_enable(); ++ break; ++ case MICRON_ID: ++ break; ++ default: ++ ret = spi_nor_quad_enable(); ++ break; ++ } ++ } ++ ++ if ((ret == 0) && ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U)) { ++ ret = spi_nor_read_bar(); ++ } ++ ++ return ret; +} +diff --git a/drivers/mtd/spi-mem/spi_mem.c b/drivers/mtd/spi-mem/spi_mem.c +new file mode 100644 +index 000000000..63ea7699b +--- /dev/null ++++ b/drivers/mtd/spi-mem/spi_mem.c +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#define SPI_MEM_DEFAULT_SPEED_HZ 100000U + +/* -+ * bsec_read_sp_lock: read shadow-program lock. -+ * otp: OTP number. -+ * return: true if OTP is locked, else false. ++ * struct spi_slave - Representation of a SPI slave. ++ * ++ * @max_hz: Maximum speed for this slave in Hertz. ++ * @cs: ID of the chip select connected to the slave. ++ * @mode: SPI mode to use for this slave (see SPI mode flags). ++ * @ops: Ops defined by the bus. + */ -+bool bsec_read_sp_lock(uint32_t otp) ++struct spi_slave { ++ unsigned int max_hz; ++ unsigned int cs; ++ unsigned int mode; ++ const struct spi_bus_ops *ops; ++}; ++ ++static struct spi_slave spi_slave; ++ ++static bool spi_mem_check_buswidth_req(uint8_t buswidth, bool tx) +{ -+ 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); -+ -+ return (bank_value & otp_mask) != 0U; -+} -+ -+/* -+ * bsec_wr_lock: Read permanent lock status. -+ * otp: OTP number. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_wr_lock(uint32_t otp) -+{ -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK); -+ -+ 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. -+ */ ++ switch (buswidth) { ++ case 1U: + return true; ++ ++ case 2U: ++ if ((tx && (spi_slave.mode & (SPI_TX_DUAL | SPI_TX_QUAD)) != ++ 0U) || ++ (!tx && (spi_slave.mode & (SPI_RX_DUAL | SPI_RX_QUAD)) != ++ 0U)) { ++ return true; ++ } ++ break; ++ ++ case 4U: ++ if ((tx && (spi_slave.mode & SPI_TX_QUAD) != 0U) || ++ (!tx && (spi_slave.mode & SPI_RX_QUAD) != 0U)) { ++ return true; ++ } ++ break; ++ ++ default: ++ break; + } + + return false; +} + -+/* -+ * 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. -+ */ -+uint32_t bsec_otp_lock(uint32_t service, uint32_t value) ++static bool spi_mem_supports_op(const struct spi_mem_op *op) +{ -+ uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF; ++ if (!spi_mem_check_buswidth_req(op->cmd.buswidth, true)) { ++ return false; ++ } + -+ switch (service) { -+ case BSEC_LOCK_UPPER_OTP: -+ mmio_write_32(reg, value << BSEC_LOCK_UPPER_OTP); -+ break; -+ case BSEC_LOCK_DEBUG: -+ mmio_write_32(reg, value << BSEC_LOCK_DEBUG); -+ break; -+ case BSEC_LOCK_PROGRAM: -+ mmio_write_32(reg, value << BSEC_LOCK_PROGRAM); -+ break; -+ default: ++ if ((op->addr.nbytes != 0U) && ++ !spi_mem_check_buswidth_req(op->addr.buswidth, true)) { ++ return false; ++ } ++ ++ if ((op->dummy.nbytes != 0U) && ++ !spi_mem_check_buswidth_req(op->dummy.buswidth, true)) { ++ return false; ++ } ++ ++ if ((op->data.nbytes != 0U) && ++ !spi_mem_check_buswidth_req(op->data.buswidth, ++ op->data.dir == SPI_MEM_DATA_OUT)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static int spi_mem_set_speed_mode(void) ++{ ++ const struct spi_bus_ops *ops = spi_slave.ops; ++ int ret; ++ ++ ret = ops->set_speed(spi_slave.max_hz); ++ if (ret != 0) { ++ VERBOSE("Cannot set speed (err=%d)\n", ret); ++ return ret; ++ } ++ ++ ret = ops->set_mode(spi_slave.mode); ++ if (ret != 0) { ++ VERBOSE("Cannot set mode (err=%d)\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int spi_mem_check_bus_ops(const struct spi_bus_ops *ops) ++{ ++ bool error = false; ++ ++ if (ops->claim_bus == NULL) { ++ VERBOSE("Ops claim bus is not defined\n"); ++ error = true; ++ } ++ ++ if (ops->release_bus == NULL) { ++ VERBOSE("Ops release bus is not defined\n"); ++ error = true; ++ } ++ ++ if (ops->exec_op == NULL) { ++ VERBOSE("Ops exec op is not defined\n"); ++ error = true; ++ } ++ ++ if (ops->set_speed == NULL) { ++ VERBOSE("Ops set speed is not defined\n"); ++ error = true; ++ } ++ ++ if (ops->set_mode == NULL) { ++ VERBOSE("Ops set mode is not defined\n"); ++ error = true; ++ } ++ ++ return error ? -EINVAL : 0; ++} ++ ++/* ++ * spi_mem_exec_op() - Execute a memory operation. ++ * @op: The memory operation to execute. ++ * ++ * This function first checks that @op is supported and then tries to execute ++ * it. ++ * ++ * Return: 0 in case of success, a negative error code otherwise. ++ */ ++int spi_mem_exec_op(const struct spi_mem_op *op) ++{ ++ const struct spi_bus_ops *ops = spi_slave.ops; ++ int ret; ++ ++ VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addqr:%llx len:%x\n", ++ __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, ++ op->dummy.buswidth, op->data.buswidth, ++ op->addr.val, op->data.nbytes); ++ ++ if (!spi_mem_supports_op(op)) { ++ WARN("Error in spi_mem_support\n"); ++ return -ENOTSUP; ++ } ++ ++ ret = ops->claim_bus(spi_slave.cs); ++ if (ret != 0) { ++ WARN("Error claim_bus\n"); ++ return ret; ++ } ++ ++ ret = ops->exec_op(op); ++ ++ ops->release_bus(); ++ ++ return ret; ++} ++ ++/* ++ * spi_mem_init_slave() - SPI slave device initialization. ++ * @fdt: Pointer to the device tree blob. ++ * @bus_node: Offset of the bus node. ++ * @ops: The SPI bus ops defined. ++ * ++ * This function first checks that @ops are supported and then tries to find ++ * a SPI slave device. ++ * ++ * Return: 0 in case of success, a negative error code otherwise. ++ */ ++int spi_mem_init_slave(void *fdt, int bus_node, const struct spi_bus_ops *ops) ++{ ++ int ret; ++ int mode = 0; ++ int nchips = 0; ++ int bus_subnode = 0; ++ const fdt32_t *cuint = NULL; ++ ++ ret = spi_mem_check_bus_ops(ops); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ fdt_for_each_subnode(bus_subnode, fdt, bus_node) { ++ nchips++; ++ } ++ ++ if (nchips != 1) { ++ ERROR("Only one SPI device is currently supported\n"); ++ return -EINVAL; ++ } ++ ++ fdt_for_each_subnode(bus_subnode, fdt, bus_node) { ++ /* Get chip select */ ++ cuint = fdt_getprop(fdt, bus_subnode, "reg", NULL); ++ if (cuint == NULL) { ++ ERROR("Chip select not well defined\n"); ++ return -EINVAL; ++ } ++ spi_slave.cs = fdt32_to_cpu(*cuint); ++ ++ /* Get max slave frequency */ ++ spi_slave.max_hz = SPI_MEM_DEFAULT_SPEED_HZ; ++ cuint = fdt_getprop(fdt, bus_subnode, ++ "spi-max-frequency", NULL); ++ if (cuint != NULL) { ++ spi_slave.max_hz = fdt32_to_cpu(*cuint); ++ } ++ ++ /* Get mode */ ++ if ((fdt_getprop(fdt, bus_subnode, "spi-cpol", NULL)) != NULL) { ++ mode |= SPI_CPOL; ++ } ++ if ((fdt_getprop(fdt, bus_subnode, "spi-cpha", NULL)) != NULL) { ++ mode |= SPI_CPHA; ++ } ++ if ((fdt_getprop(fdt, bus_subnode, "spi-cs-high", NULL)) != ++ NULL) { ++ mode |= SPI_CS_HIGH; ++ } ++ if ((fdt_getprop(fdt, bus_subnode, "spi-3wire", NULL)) != ++ NULL) { ++ mode |= SPI_3WIRE; ++ } ++ if ((fdt_getprop(fdt, bus_subnode, "spi-half-duplex", NULL)) != ++ NULL) { ++ mode |= SPI_PREAMBLE; ++ } ++ ++ /* Get dual/quad mode */ ++ cuint = fdt_getprop(fdt, bus_subnode, "spi-tx-bus-width", NULL); ++ if (cuint != NULL) { ++ switch (fdt32_to_cpu(*cuint)) { ++ case 1U: ++ break; ++ case 2U: ++ mode |= SPI_TX_DUAL; ++ break; ++ case 4U: ++ mode |= SPI_TX_QUAD; ++ break; ++ default: ++ WARN("spi-tx-bus-width %d not supported\n", ++ fdt32_to_cpu(*cuint)); ++ return -EINVAL; ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, bus_subnode, "spi-rx-bus-width", NULL); ++ if (cuint != NULL) { ++ switch (fdt32_to_cpu(*cuint)) { ++ case 1U: ++ break; ++ case 2U: ++ mode |= SPI_RX_DUAL; ++ break; ++ case 4U: ++ mode |= SPI_RX_QUAD; ++ break; ++ default: ++ WARN("spi-rx-bus-width %d not supported\n", ++ fdt32_to_cpu(*cuint)); ++ return -EINVAL; ++ } ++ } ++ ++ spi_slave.mode = mode; ++ spi_slave.ops = ops; ++ } ++ ++ return spi_mem_set_speed_mode(); ++} +diff --git a/drivers/renesas/rcar/io/io_emmcdrv.c b/drivers/renesas/rcar/io/io_emmcdrv.c +index 4b464fb3e..84240d260 100644 +--- a/drivers/renesas/rcar/io/io_emmcdrv.c ++++ b/drivers/renesas/rcar/io/io_emmcdrv.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. ++ * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -25,7 +25,7 @@ static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info); + typedef struct { + uint32_t in_use; + uintptr_t base; +- ssize_t file_pos; ++ signed long long file_pos; + EMMC_PARTITION_ID partition; + } file_state_t; + +@@ -39,7 +39,7 @@ static io_type_t device_type_emmcdrv(void) + } + + static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode, +- ssize_t offset) ++ signed long long offset) + { + if (mode != IO_SEEK_SET) + return IO_FAIL; +@@ -59,12 +59,12 @@ static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer, + sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT; + sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT; + +- NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%lx(%d) len=0x%lx(%d)\n", ++ NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n", + buffer, + current_file.partition, current_file.file_pos, + sector_add, length, sector_num); + +- if (buffer + length - 1 <= UINT32_MAX) ++ if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) + emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE; + + if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num, +@@ -72,7 +72,7 @@ static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer, + result = IO_FAIL; + + *length_read = length; +- fp->file_pos += length; ++ fp->file_pos += (signed long long)length; + + return result; + } +@@ -82,7 +82,7 @@ static int32_t emmcdrv_block_open(io_dev_info_t *dev_info, + { + const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; + +- if (current_file.in_use) { ++ if (current_file.in_use != 0U) { + WARN("mmc_block: Only one open spec at a time\n"); + return IO_RESOURCES_EXHAUSTED; + } +@@ -103,9 +103,9 @@ static int32_t emmcdrv_block_open(io_dev_info_t *dev_info, + return IO_FAIL; + } + +- if (PARTITION_ID_USER == block_spec->partition || +- PARTITION_ID_BOOT_1 == block_spec->partition || +- PARTITION_ID_BOOT_2 == block_spec->partition) ++ if ((PARTITION_ID_USER == block_spec->partition) || ++ (PARTITION_ID_BOOT_1 == block_spec->partition) || ++ (PARTITION_ID_BOOT_2 == block_spec->partition)) + current_file.partition = block_spec->partition; + else + current_file.partition = emmcdrv_bootpartition; +diff --git a/drivers/renesas/rcar/io/io_memdrv.c b/drivers/renesas/rcar/io/io_memdrv.c +index 3f6b4c71b..7e8c1d3a6 100644 +--- a/drivers/renesas/rcar/io/io_memdrv.c ++++ b/drivers/renesas/rcar/io/io_memdrv.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. ++ * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -28,7 +28,7 @@ static int32_t memdrv_dev_close(io_dev_info_t *dev_info); + typedef struct { + uint32_t in_use; + uintptr_t base; +- ssize_t file_pos; ++ signed long long file_pos; + } file_state_t; + + static file_state_t current_file = { 0 }; +@@ -47,7 +47,7 @@ static int32_t memdrv_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + * spec at a time. When we have dynamic memory we can malloc and set + * entity->info. + */ +- if (current_file.in_use) ++ if (current_file.in_use != 0U) + return IO_RESOURCES_EXHAUSTED; + + /* File cursor offset for seek and incremental reads etc. */ +@@ -61,7 +61,7 @@ static int32_t memdrv_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + } + + static int32_t memdrv_block_seek(io_entity_t *entity, int32_t mode, +- ssize_t offset) ++ signed long long offset) + { + if (mode != IO_SEEK_SET) + return IO_FAIL; +@@ -78,16 +78,17 @@ static int32_t memdrv_block_read(io_entity_t *entity, uintptr_t buffer, + + fp = (file_state_t *) entity->info; + +- NOTICE("BL2: dst=0x%lx src=0x%lx len=%ld(0x%lx)\n", +- buffer, fp->base + fp->file_pos, length, length); ++ NOTICE("BL2: dst=0x%lx src=0x%llx len=%ld(0x%lx)\n", ++ buffer, (unsigned long long)fp->base + ++ (unsigned long long)fp->file_pos, length, length); + +- if (FLASH_MEMORY_SIZE < fp->file_pos + length) { ++ if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) { + ERROR("BL2: check load image (source address)\n"); + return IO_FAIL; + } + +- rcar_dma_exec(buffer, fp->base + fp->file_pos, length); +- fp->file_pos += length; ++ rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length); ++ fp->file_pos += (signed long long)length; + *cnt = length; + + return IO_SUCCESS; +diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec2.c +similarity index 65% +rename from drivers/st/bsec/bsec.c +rename to drivers/st/bsec/bsec2.c +index 01c369edc..9777e6721 100644 +--- a/drivers/st/bsec/bsec.c ++++ b/drivers/st/bsec/bsec2.c +@@ -14,11 +14,12 @@ + #include + #include + #include ++#include + #include + #include + +-#define BSEC_IP_VERSION_1_0 0x10 +-#define BSEC_COMPAT "st,stm32mp15-bsec" ++#define BSEC_IP_VERSION_1_1 U(0x11) ++#define BSEC_IP_ID_2 U(0x100032) + + #define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) + +@@ -48,7 +49,7 @@ static int bsec_get_dt_node(struct dt_node_info *info) + { + int node; + +- node = dt_get_node(info, -1, BSEC_COMPAT); ++ node = dt_get_node(info, -1, DT_BSEC_COMPAT); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } +@@ -78,33 +79,59 @@ static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node) + + fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { + const fdt32_t *cuint; +- uint32_t reg; ++ uint32_t otp; + uint32_t i; + uint32_t size; +- uint8_t status; ++ uint32_t offset; ++ uint32_t length; + + cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); + if (cuint == NULL) { + panic(); + } + +- reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t); +- if (reg < STM32MP1_UPPER_OTP_START) { +- continue; ++ offset = fdt32_to_cpu(*cuint); ++ cuint++; ++ length = fdt32_to_cpu(*cuint); ++ ++ otp = offset / sizeof(uint32_t); ++ ++ if (otp < STM32MP1_UPPER_OTP_START) { ++ unsigned int otp_end = round_up(offset + length, ++ sizeof(uint32_t)) / ++ sizeof(uint32_t); ++ ++ if (otp_end > STM32MP1_UPPER_OTP_START) { ++ /* ++ * OTP crosses Lower/Upper boundary, consider ++ * only the upper part. ++ */ ++ otp = STM32MP1_UPPER_OTP_START; ++ length -= (STM32MP1_UPPER_OTP_START * ++ sizeof(uint32_t)) - offset; ++ offset = STM32MP1_UPPER_OTP_START * ++ sizeof(uint32_t); ++ ++ WARN("OTP crosses Lower/Upper boundary\n"); ++ } else { ++ continue; ++ } + } + +- status = fdt_get_status(bsec_subnode); +- if ((status & DT_NON_SECURE) == 0U) { ++ if ((fdt_getprop(fdt, bsec_subnode, ++ "st,non-secure-otp", NULL)) == NULL) { + continue; + } + +- size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t); +- +- if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) { +- size++; ++ if (((offset % sizeof(uint32_t)) != 0) || ++ ((length % sizeof(uint32_t)) != 0)) { ++ ERROR("Unaligned non-secure OTP\n"); ++ panic(); + } + +- for (i = reg; i < (reg + size); i++) { ++ size = length / sizeof(uint32_t); ++ ++ for (i = otp; i < (otp + size); i++) { + enable_non_secure_access(i); + } + } +@@ -121,19 +148,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; + } + +@@ -158,6 +196,11 @@ uint32_t bsec_probe(void) + + bsec_base = bsec_info.base; + ++ if (((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) || ++ (bsec_get_id() != BSEC_IP_ID_2)) { ++ panic(); ++ } ++ + #if defined(IMAGE_BL32) + bsec_dt_otp_nsec_access(fdt, node); + #endif +@@ -251,6 +294,79 @@ uint32_t bsec_get_config(struct bsec_config *cfg) + return BSEC_OK; + } + ++/* ++ * bsec_find_otp_name_in_dt: get OTP ID and length in DT. ++ * name: sub-node name to look up. ++ * otp: pointer to read OTP number or NULL. ++ * otp_len: pointer to read OTP length in bits or NULL. ++ * return value: BSEC_OK if no error. ++ */ ++uint32_t bsec_find_otp_name_in_dt(const char *name, uint32_t *otp, ++ uint32_t *otp_len) ++{ ++ void *fdt; ++ int node; ++ int index, len; ++ const fdt32_t *cuint; ++ ++ if ((name == NULL) || (otp == NULL)) { + return BSEC_INVALID_PARAM; + } + -+ return BSEC_OK; -+} -+ -+/* -+ * bsec_power_safmem: Activate or deactivate SAFMEM power. -+ * power: true to power up, false to power down. -+ * return: BSEC_OK if succeed. -+ */ -+static uint32_t bsec_power_safmem(bool power) -+{ -+ uint32_t register_val; -+ uint32_t timeout = BSEC_TIMEOUT_VALUE; -+ -+ bsec_lock(); -+ -+ register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); -+ -+ if (power) { -+ register_val |= BSEC_CONF_POWER_UP_MASK; -+ } else { -+ register_val &= ~BSEC_CONF_POWER_UP_MASK; ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); + } + -+ 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)) { -+ timeout--; -+ } -+ } else { -+ while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) && -+ (timeout != 0U)) { -+ timeout--; -+ } ++ node = dt_get_node_by_compatible(DT_NVMEM_LAYOUT_COMPAT); ++ if (node < 0) { ++ return BSEC_ERROR; + } + -+ bsec_unlock(); ++ index = fdt_stringlist_search(fdt, node, "nvmem-cell-names", name); ++ if (index < 0) { ++ return BSEC_ERROR; ++ } + -+ if (timeout == 0U) { -+ return BSEC_TIMEOUT; ++ cuint = fdt_getprop(fdt, node, "nvmem-cells", &len); ++ if (cuint == NULL) { ++ return BSEC_ERROR; ++ } ++ ++ if ((index * (int)sizeof(uint32_t)) > len) { ++ return BSEC_ERROR; ++ } ++ ++ cuint += index; ++ ++ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); ++ if (node < 0) { ++ ERROR("Malformed nvmem_layout node: ignored\n"); ++ return BSEC_ERROR; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "reg", &len); ++ if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) { ++ ERROR("Malformed nvmem_layout node: ignored\n"); ++ return BSEC_ERROR; ++ } ++ ++ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { ++ ERROR("Misaligned nvmem_layout element: ignored\n"); ++ return BSEC_ERROR; ++ } ++ ++ if (otp != NULL) { ++ *otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); ++ } ++ ++ if (otp_len != NULL) { ++ cuint++; ++ *otp_len = fdt32_to_cpu(*cuint) * CHAR_BIT; + } + + return BSEC_OK; +} + -+/* -+ * 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 -+ * otp_value: read value. -+ * word: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) -+{ -+ uint32_t result; -+ -+ result = bsec_shadow_register(word); + /* + * bsec_shadow_register: copy SAFMEM OTP to BSEC data. + * otp: OTP number. +@@ -259,14 +375,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 Shadowing Error %i\n", word, result); ++ 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); + } +@@ -283,14 +401,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(); + +@@ -311,22 +428,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; + } + + /* +@@ -338,24 +447,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; +@@ -372,14 +482,23 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp) + { + uint32_t result; + bool power_up = false; ++ bool sp_lock, perm_lock; + +- if (otp > STM32MP1_OTP_MAX_ID) { +- return BSEC_INVALID_PARAM; ++ result = bsec_read_sp_lock(otp, &sp_lock); ++ 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)) { ++ result = bsec_read_permanent_lock(otp, &perm_lock); ++ if (result != BSEC_OK) { ++ ERROR("BSEC: %u permanent bit read Error %i\n", otp, result); + return result; + } + -+ result = bsec_read_otp(otp_value, word); -+ if (result != BSEC_OK) { -+ ERROR("BSEC: %u Read Error %i\n", word, result); -+ } -+ -+ return result; -+} -+ -+/* -+ * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. -+ * otp: OTP number. -+ * return: BSEC_OK if authorized access. -+ */ -+uint32_t bsec_check_nsec_access_rights(uint32_t otp) -+{ -+#if defined(IMAGE_BL32) ++ if (sp_lock || perm_lock) { + WARN("BSEC: OTP locked, prog will be ignored\n"); ++ return BSEC_PROG_FAIL; + } + + if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) & +@@ -399,10 +518,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) { +@@ -412,7 +529,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(); +@@ -464,10 +581,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); + +@@ -478,7 +593,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(); +@@ -493,7 +608,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. +@@ -517,7 +632,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) + { +@@ -533,7 +648,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) + { +@@ -541,7 +656,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) + { +@@ -549,7 +664,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) + { +@@ -557,7 +672,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) + { +@@ -565,229 +680,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; + +- return (bank_value & otp_mask) != 0U; + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + -+ 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; -+ } -+ } -+ } -+#endif ++ 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; + +- return (bank_value & otp_mask) != 0U; ++ if (otp > STM32MP1_OTP_MAX_ID) { ++ return BSEC_INVALID_PARAM; ++ } + -diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c -index f0bf363..b304315 100644 ---- a/drivers/st/clk/stm32mp1_clk.c -+++ b/drivers/st/clk/stm32mp1_clk.c -@@ -9,26 +9,34 @@ - #include - #include - #include --#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include -+#include -+#include -+#include -+#include - #include - #include --#include - #include - #include -+#include -+#if defined(IMAGE_BL32) -+#include -+#endif - #include - - #define MAX_HSI_HZ 64000000 -+#define USB_PHY_48_MHZ 48000000 - --#define TIMEOUT_200MS (plat_get_syscnt_freq2() / 5U) --#define TIMEOUT_1S plat_get_syscnt_freq2() -+#define TIMEOUT_200MS ms2tick(200) -+#define TIMEOUT_1S s2tick(1) - - #define PLLRDY_TIMEOUT TIMEOUT_200MS - #define CLKSRC_TIMEOUT TIMEOUT_200MS -@@ -36,6 +44,10 @@ - #define HSIDIV_TIMEOUT TIMEOUT_200MS - #define OSCRDY_TIMEOUT TIMEOUT_1S - -+#if defined(IMAGE_BL32) -+#define CAL_MAX_RETRY 20U -+#endif ++ bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); + - enum stm32mp1_parent_id { - /* Oscillators are defined in enum stm32mp_osc_id */ ++ *value = ((bank_value & otp_mask) != 0U); ++ ++ return BSEC_OK; + } -@@ -66,12 +78,21 @@ enum stm32mp1_parent_id { - _HCLK2, - _CK_PER, - _CK_MPU, -+ _CK_MCU, -+ _USB_PHY_48, - _PARENT_NB, - _UNKNOWN_ID = 0xff, - }; + /* +- * 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); -+/* Lists only the parent clock we are interested in */ - enum stm32mp1_parent_sel { -+ _I2C12_SEL, -+ _I2C35_SEL, -+ _STGEN_SEL, - _I2C46_SEL, -+ _SPI6_SEL, -+ _USART1_SEL, -+ _RNG1_SEL, - _UART6_SEL, - _UART24_SEL, - _UART35_SEL, -@@ -80,9 +101,10 @@ enum stm32mp1_parent_sel { - _SDMMC3_SEL, - _QSPI_SEL, - _FMC_SEL, -+ _ASS_SEL, -+ _MSS_SEL, - _USBPHY_SEL, - _USBO_SEL, -- _STGEN_SEL, - _PARENT_SEL_NB, - _UNKNOWN_SEL = 0xff, - }; -@@ -105,6 +127,7 @@ enum stm32mp1_div_id { - enum stm32mp1_clksrc_id { - CLKSRC_MPU, - CLKSRC_AXI, -+ CLKSRC_MCU, - CLKSRC_PLL12, - CLKSRC_PLL3, - CLKSRC_PLL4, -@@ -117,6 +140,7 @@ enum stm32mp1_clksrc_id { - enum stm32mp1_clkdiv_id { - CLKDIV_MPU, - CLKDIV_AXI, -+ CLKDIV_MCU, - CLKDIV_APB1, - CLKDIV_APB2, - CLKDIV_APB3, -@@ -162,9 +186,8 @@ struct stm32mp1_clk_gate { - uint8_t bit; - uint8_t index; - uint8_t set_clr; -- enum stm32mp1_parent_sel sel; -- enum stm32mp1_parent_id fixed; -- bool secure; -+ uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ -+ uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ - }; +- 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; + } - struct stm32mp1_clk_sel { -@@ -187,21 +210,34 @@ struct stm32mp1_clk_pll { - enum stm32mp_osc_id refclk[REFCLK_SIZE]; - }; ++ bsec_lock(); ++ mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask); + bsec_unlock(); --struct stm32mp1_clk_data { -- const struct stm32mp1_clk_gate *gate; -- const struct stm32mp1_clk_sel *sel; -- const struct stm32mp1_clk_pll *pll; -- const int nb_gate; -+#if defined(IMAGE_BL32) +- 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; + +- return (bank_value & otp_mask) != 0U; ++ 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 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; +@@ -799,7 +863,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) + { +@@ -818,7 +882,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)) { +@@ -841,7 +904,7 @@ static uint32_t bsec_power_safmem(bool power) + } + + /* +- * 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. +@@ -867,7 +930,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) + { +@@ -877,11 +940,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 (stm32mp_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 000000000..b764c971c +--- /dev/null ++++ b/drivers/st/clk/stm32mp1_calib.c +@@ -0,0 +1,529 @@ ++/* ++ * 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 ++ ++#define TIMEOUT_10MS 10000 ++#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_priv { -- uint32_t base; -- const struct stm32mp1_clk_data *data; -- unsigned long osc[NB_OSC]; -- uint32_t pkcs_usb_value; ++}; ++ +struct stm32mp1_clk_cal { + uint16_t *fbv; + unsigned int cal_ref; @@ -4218,526 +5956,53 @@ index f0bf363..b304315 100644 + void (*set_trim)(unsigned int cal); + unsigned int (*get_trim)(void); + struct stm32mp1_trim_boundary_t boundary[16]; - }; - --#define STM32MP1_CLK(off, b, idx, s) \ ++}; ++ +/* 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) \ - { \ - .offset = (off), \ - .bit = (b), \ -@@ -209,10 +245,10 @@ struct stm32mp1_clk_priv { - .set_clr = 0, \ - .sel = (s), \ - .fixed = _UNKNOWN_ID, \ -- .secure = 0, \ - } - --#define STM32MP1_CLK_F(off, b, idx, f) \ -+/* Clocks with fixed source and non set/clr register access */ -+#define _CLK_FIXED(off, b, idx, f) \ - { \ - .offset = (off), \ - .bit = (b), \ -@@ -220,10 +256,10 @@ struct stm32mp1_clk_priv { - .set_clr = 0, \ - .sel = _UNKNOWN_SEL, \ - .fixed = (f), \ -- .secure = 0, \ - } - --#define STM32MP1_CLK_SET_CLR(off, b, idx, s) \ -+/* Clocks with selectable source and set/clr register access */ -+#define _CLK_SC_SELEC(off, b, idx, s) \ - { \ - .offset = (off), \ - .bit = (b), \ -@@ -231,10 +267,10 @@ struct stm32mp1_clk_priv { - .set_clr = 1, \ - .sel = (s), \ - .fixed = _UNKNOWN_ID, \ -- .secure = 0, \ - } - --#define STM32MP1_CLK_SET_CLR_F(off, b, idx, f) \ -+/* Clocks with fixed source and set/clr register access */ -+#define _CLK_SC_FIXED(off, b, idx, f) \ - { \ - .offset = (off), \ - .bit = (b), \ -@@ -242,32 +278,20 @@ struct stm32mp1_clk_priv { - .set_clr = 1, \ - .sel = _UNKNOWN_SEL, \ - .fixed = (f), \ -- .secure = 0, \ -- } -- --#define STM32MP1_CLK_SEC_SET_CLR(off, b, idx, s) \ -- { \ -- .offset = (off), \ -- .bit = (b), \ -- .index = (idx), \ -- .set_clr = 1, \ -- .sel = (s), \ -- .fixed = _UNKNOWN_ID, \ -- .secure = 1, \ - } - --#define STM32MP1_CLK_PARENT(idx, off, s, m, p) \ -+#define _CLK_PARENT(idx, off, s, m, p) \ - [(idx)] = { \ - .offset = (off), \ - .src = (s), \ - .msk = (m), \ - .parent = (p), \ -- .nb_parent = ARRAY_SIZE((p)) \ -+ .nb_parent = ARRAY_SIZE(p) \ - } - --#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3, \ -- off4, off5, off6, \ -- p1, p2, p3, p4) \ -+#define _CLK_PLL(idx, type, off1, off2, off3, \ -+ off4, off5, off6, \ -+ p1, p2, p3, p4) \ - [(idx)] = { \ - .plltype = (type), \ - .rckxselr = (off1), \ -@@ -283,113 +307,180 @@ struct stm32mp1_clk_priv { - } - - static const uint8_t stm32mp1_clks[][2] = { -- {CK_PER, _CK_PER}, -- {CK_MPU, _CK_MPU}, -- {CK_AXI, _ACLK}, -- {CK_HSE, _HSE}, -- {CK_CSI, _CSI}, -- {CK_LSI, _LSI}, -- {CK_LSE, _LSE}, -- {CK_HSI, _HSI}, -- {CK_HSE_DIV2, _HSE_KER_DIV2}, -+ { CK_PER, _CK_PER }, -+ { CK_MPU, _CK_MPU }, -+ { CK_AXI, _ACLK }, -+ { CK_MCU, _CK_MCU }, -+ { CK_HSE, _HSE }, -+ { CK_CSI, _CSI }, -+ { CK_LSI, _LSI }, -+ { CK_LSE, _LSE }, -+ { CK_HSI, _HSI }, -+ { CK_HSE_DIV2, _HSE_KER_DIV2 }, - }; - -+#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) -+ - static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { -- STM32MP1_CLK(RCC_DDRITFCR, 0, DDRC1, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 1, DDRC1LP, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 2, DDRC2, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 3, DDRC2LP, _UNKNOWN_SEL), -- STM32MP1_CLK_F(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), -- STM32MP1_CLK(RCC_DDRITFCR, 5, DDRPHYCLP, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 6, DDRCAPB, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 7, DDRCAPBLP, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 8, AXIDCG, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 9, DDRPHYCAPB, _UNKNOWN_SEL), -- STM32MP1_CLK(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _UNKNOWN_SEL), -- -- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), -- -- STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), -- -- STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), -- -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 11, TZC1, _UNKNOWN_SEL), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 12, TZC2, _UNKNOWN_SEL), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), -- -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), -- -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), -- -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 5, HASH1, _UNKNOWN_SEL), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 6, RNG1_K, _CSI_KER), -- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _UNKNOWN_SEL), -- -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), -- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), -- -- STM32MP1_CLK(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), -+ _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), -+ _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), -+ _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), -+ _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), -+ _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), -+ _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), -+ _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), -+ _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), -+ _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), -+ _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), -+ _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), -+ _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), -+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), -+ _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), -+ _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_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), -+ -+ _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_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), -+ _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), -+ _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), -+ _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, 8, USBO_K, _USBO_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), -+ -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), -+ -+ _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), -+ _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), -+ _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), -+ _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, 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), -+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), -+ -+ _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), ++/* 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 const uint8_t i2c12_parents[] = { -+ _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER ++/* 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 const uint8_t i2c35_parents[] = { -+ _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER -+}; -+ -+static const uint8_t stgen_parents[] = { -+ _HSI_KER, _HSE_KER -+}; -+ -+static const uint8_t i2c46_parents[] = { -+ _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER -+}; -+ -+static const uint8_t spi6_parents[] = { -+ _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q -+}; -+ -+static const uint8_t usart1_parents[] = { -+ _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER -+}; -+ -+static const uint8_t rng1_parents[] = { -+ _CSI, _PLL4_R, _LSE, _LSI -+}; -+ -+static const uint8_t uart6_parents[] = { -+ _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER - }; - --static const uint8_t i2c46_parents[] = {_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER}; --static const uint8_t uart6_parents[] = {_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, -- _HSE_KER}; --static const uint8_t uart24_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, -- _HSE_KER}; --static const uint8_t uart35_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, -- _HSE_KER}; --static const uint8_t uart78_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, -- _HSE_KER}; --static const uint8_t sdmmc12_parents[] = {_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER}; --static const uint8_t sdmmc3_parents[] = {_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER}; --static const uint8_t qspi_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER}; --static const uint8_t fmc_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER}; --static const uint8_t usbphy_parents[] = {_HSE_KER, _PLL4_R, _HSE_KER_DIV2}; --static const uint8_t usbo_parents[] = {_PLL4_R, _USB_PHY_48}; --static const uint8_t stgen_parents[] = {_HSI_KER, _HSE_KER}; -+static const uint8_t uart234578_parents[] = { -+ _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER -+}; -+ -+static const uint8_t sdmmc12_parents[] = { -+ _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER -+}; -+ -+static const uint8_t sdmmc3_parents[] = { -+ _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER -+}; -+ -+static const uint8_t qspi_parents[] = { -+ _ACLK, _PLL3_R, _PLL4_P, _CK_PER -+}; -+ -+static const uint8_t fmc_parents[] = { -+ _ACLK, _PLL3_R, _PLL4_P, _CK_PER -+}; -+ -+static const uint8_t ass_parents[] = { -+ _HSI, _HSE, _PLL2 -+}; -+ -+static const uint8_t mss_parents[] = { -+ _HSI, _HSE, _CSI, _PLL3 -+}; -+ -+static const uint8_t usbphy_parents[] = { -+ _HSE_KER, _PLL4_R, _HSE_KER_DIV2 -+}; -+ -+static const uint8_t usbo_parents[] = { -+ _PLL4_R, _USB_PHY_48 -+}; - - static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { -- STM32MP1_CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), -- STM32MP1_CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), -- STM32MP1_CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, -- uart24_parents), -- STM32MP1_CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, -- uart35_parents), -- STM32MP1_CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, -- uart78_parents), -- STM32MP1_CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, -- sdmmc12_parents), -- STM32MP1_CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, -- sdmmc3_parents), -- STM32MP1_CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents), -- STM32MP1_CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents), -- STM32MP1_CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), -- STM32MP1_CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), -- STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), -+ _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), - }; - - /* Define characteristic of PLL according type */ -@@ -411,29 +502,33 @@ static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { - static const uint8_t pllncfgr2[_DIV_NB] = { - [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, - [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, -- [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT -+ [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, - }; - - static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { -- STM32MP1_CLK_PLL(_PLL1, PLL_1600, -- RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, -- RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, -- _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), -- STM32MP1_CLK_PLL(_PLL2, PLL_1600, -- RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, -- RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, -- _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), -- STM32MP1_CLK_PLL(_PLL3, PLL_800, -- RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, -- RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, -- _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), -- STM32MP1_CLK_PLL(_PLL4, PLL_800, -- RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, -- RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, -- _HSI, _HSE, _CSI, _I2S_CKIN), -+ _CLK_PLL(_PLL1, PLL_1600, -+ RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, -+ RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, -+ _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), -+ _CLK_PLL(_PLL2, PLL_1600, -+ RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, -+ RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, -+ _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), -+ _CLK_PLL(_PLL3, PLL_800, -+ RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, -+ RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, -+ _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), -+ _CLK_PLL(_PLL4, PLL_800, -+ RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, -+ RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, -+ _HSI, _HSE, _CSI, _I2S_CKIN), - }; - - /* Prescaler table lookups for clock computation */ -+/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ -+static const uint8_t stm32mp1_mcu_div[16] = { -+ 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 -+}; - - /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ - #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div -@@ -447,33 +542,210 @@ static const uint8_t stm32mp1_axi_div[8] = { - 1, 2, 3, 4, 4, 4, 4, 4 - }; - --static const struct stm32mp1_clk_data stm32mp1_data = { -- .gate = stm32mp1_clk_gate, -- .sel = stm32mp1_clk_sel, -- .pll = stm32mp1_clk_pll, -- .nb_gate = ARRAY_SIZE(stm32mp1_clk_gate), -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { -+ [_HSI] = "HSI", -+ [_HSE] = "HSE", -+ [_CSI] = "CSI", -+ [_LSI] = "LSI", -+ [_LSE] = "LSE", -+ [_I2S_CKIN] = "I2S_CKIN", -+ [_HSI_KER] = "HSI_KER", -+ [_HSE_KER] = "HSE_KER", -+ [_HSE_KER_DIV2] = "HSE_KER_DIV2", -+ [_CSI_KER] = "CSI_KER", -+ [_PLL1_P] = "PLL1_P", -+ [_PLL1_Q] = "PLL1_Q", -+ [_PLL1_R] = "PLL1_R", -+ [_PLL2_P] = "PLL2_P", -+ [_PLL2_Q] = "PLL2_Q", -+ [_PLL2_R] = "PLL2_R", -+ [_PLL3_P] = "PLL3_P", -+ [_PLL3_Q] = "PLL3_Q", -+ [_PLL3_R] = "PLL3_R", -+ [_PLL4_P] = "PLL4_P", -+ [_PLL4_Q] = "PLL4_Q", -+ [_PLL4_R] = "PLL4_R", -+ [_ACLK] = "ACLK", -+ [_PCLK1] = "PCLK1", -+ [_PCLK2] = "PCLK2", -+ [_PCLK3] = "PCLK3", -+ [_PCLK4] = "PCLK4", -+ [_PCLK5] = "PCLK5", -+ [_HCLK6] = "KCLK6", -+ [_HCLK2] = "HCLK2", -+ [_CK_PER] = "CK_PER", -+ [_CK_MPU] = "CK_MPU", -+ [_CK_MCU] = "CK_MCU", -+ [_USB_PHY_48] = "USB_PHY_48", -+}; -+ -+static const char * -+const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = { -+ [_I2C12_SEL] = "I2C12", -+ [_I2C35_SEL] = "I2C35", -+ [_STGEN_SEL] = "STGEN", -+ [_I2C46_SEL] = "I2C46", -+ [_SPI6_SEL] = "SPI6", -+ [_USART1_SEL] = "USART1", -+ [_RNG1_SEL] = "RNG1", -+ [_UART6_SEL] = "UART6", -+ [_UART24_SEL] = "UART24", -+ [_UART35_SEL] = "UART35", -+ [_UART78_SEL] = "UART78", -+ [_SDMMC12_SEL] = "SDMMC12", -+ [_SDMMC3_SEL] = "SDMMC3", -+ [_QSPI_SEL] = "QSPI", -+ [_FMC_SEL] = "FMC", -+ [_ASS_SEL] = "ASS", -+ [_MSS_SEL] = "MSS", -+ [_USBPHY_SEL] = "USBPHY", -+ [_USBO_SEL] = "USBO", -+}; -+#endif -+ -+/* RCC clock device driver private */ -+static unsigned long stm32mp1_osc[NB_OSC]; -+static struct spinlock reg_lock; -+static unsigned int gate_refcounts[NB_GATES]; -+static struct spinlock refcount_lock; -+ -+static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) -+{ -+ return &stm32mp1_clk_gate[idx]; -+} -+ -+static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) -+{ -+ return &stm32mp1_clk_sel[idx]; -+} -+ -+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); @@ -4748,7 +6013,7 @@ index f0bf363..b304315 100644 + .trim_max = 63, + .trim_min = -64, + .ref_freq = 0, -+ .freq_margin = 1, ++ .freq_margin = 5, + .set_trim = hsi_set_trim, + .get_trim = hsi_get_trimed_cal, +}; @@ -4758,1715 +6023,21 @@ index f0bf363..b304315 100644 + .trim_max = 15, + .trim_min = -16, + .ref_freq = 0, -+ .freq_margin = 2, ++ .freq_margin = 8, + .set_trim = csi_set_trim, + .get_trim = csi_get_trimed_cal, - }; - --static struct stm32mp1_clk_priv stm32mp1_clk_priv_data; ++}; ++ +static uint32_t timer_val; -+#endif + -+static int stm32mp1_lock_available(void) -+{ -+ /* The spinlocks are used only when MMU is enabled */ -+ return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT); -+} -+ -+static void stm32mp1_clk_lock(struct spinlock *lock) -+{ -+ if (stm32mp1_lock_available() == 0U) { -+ return; -+ } -+ -+ /* Assume interrupts are masked */ -+ spin_lock(lock); -+} -+ -+static void stm32mp1_clk_unlock(struct spinlock *lock) -+{ -+ if (stm32mp1_lock_available() == 0U) { -+ return; -+ } -+ -+ spin_unlock(lock); -+} -+ -+bool stm32mp1_rcc_is_secure(void) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0; -+} -+ -+bool stm32mp1_rcc_is_mckprot(void) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0; -+} -+ -+void stm32mp1_clk_rcc_regs_lock(void) -+{ -+ stm32mp1_clk_lock(®_lock); -+} -+ -+void stm32mp1_clk_rcc_regs_unlock(void) -+{ -+ stm32mp1_clk_unlock(®_lock); -+} -+ -+static unsigned int get_id_from_rcc_bit(unsigned int offset, unsigned int bit) -+{ -+ unsigned int idx; -+ -+ for (idx = 0U; idx < NB_GATES; idx++) { -+ const struct stm32mp1_clk_gate *gate = gate_ref(idx); - --static unsigned long stm32mp1_clk_get_fixed(struct stm32mp1_clk_priv *priv, -- enum stm32mp_osc_id idx) -+ if ((offset == gate->offset) && (bit == gate->bit)) { -+ return gate->index; -+ } -+ -+ if ((gate->set_clr != 0U) && -+ (offset == (gate->offset + RCC_MP_ENCLRR_OFFSET)) && -+ (bit == gate->bit)) { -+ return gate->index; -+ } -+ } -+ -+ /* Currently only supported gated clocks */ -+ return ~0U; -+} -+ -+static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) - { - if (idx >= NB_OSC) { - return 0; - } - -- return priv->osc[idx]; -+ return stm32mp1_osc[idx]; - } - --static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id) -+static int stm32mp1_clk_get_gated_id(unsigned long id) - { -- const struct stm32mp1_clk_gate *gate = priv->data->gate; -- int i; -- int nb_clks = priv->data->nb_gate; -+ unsigned int i; - -- for (i = 0; i < nb_clks; i++) { -- if (gate[i].index == id) { -+ for (i = 0U; i < NB_GATES; i++) { -+ if (gate_ref(i)->index == id) { - return i; - } - } -@@ -483,77 +755,70 @@ static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id) - return -EINVAL; - } - --static enum stm32mp1_parent_sel --stm32mp1_clk_get_sel(struct stm32mp1_clk_priv *priv, int i) -+static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) - { -- const struct stm32mp1_clk_gate *gate = priv->data->gate; -- -- return gate[i].sel; -+ return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); - } - --static enum stm32mp1_parent_id --stm32mp1_clk_get_fixed_parent(struct stm32mp1_clk_priv *priv, int i) -+static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) - { -- const struct stm32mp1_clk_gate *gate = priv->data->gate; -- -- return gate[i].fixed; -+ return (enum stm32mp1_parent_id)gate_ref(i)->fixed; - } - --static int stm32mp1_clk_get_parent(struct stm32mp1_clk_priv *priv, -- unsigned long id) -+static int stm32mp1_clk_get_parent(unsigned long id) - { -- const struct stm32mp1_clk_sel *sel = priv->data->sel; -+ const struct stm32mp1_clk_sel *sel; - uint32_t j, p_sel; - int i; - enum stm32mp1_parent_id p; - enum stm32mp1_parent_sel s; -+ uintptr_t rcc_base = stm32mp_rcc_base(); - -- for (j = 0; j < ARRAY_SIZE(stm32mp1_clks); j++) { -+ for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) { - if (stm32mp1_clks[j][0] == id) { - return (int)stm32mp1_clks[j][1]; - } - } - -- i = stm32mp1_clk_get_id(priv, id); -+ i = stm32mp1_clk_get_gated_id(id); - if (i < 0) { -- return i; -+ panic(); - } - -- p = stm32mp1_clk_get_fixed_parent(priv, i); -+ p = stm32mp1_clk_get_fixed_parent(i); - if (p < _PARENT_NB) { - return (int)p; - } - -- s = stm32mp1_clk_get_sel(priv, i); -- if (s >= _PARENT_SEL_NB) { -+ s = stm32mp1_clk_get_sel(i); -+ if (s == _UNKNOWN_SEL) { - return -EINVAL; - } -- -- p_sel = (mmio_read_32(priv->base + sel[s].offset) >> sel[s].src) & -- sel[s].msk; -- -- if (p_sel < sel[s].nb_parent) { -- return (int)sel[s].parent[p_sel]; -+ if (s >= _PARENT_SEL_NB) { -+ panic(); - } - -- ERROR("%s: no parents defined for clk id %ld\n", __func__, id); -+ sel = clk_sel_ref(s); -+ p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk; -+ 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", -+ __func__, -+ stm32mp1_clk_parent_name[sel->parent[p_sel]], -+ stm32mp1_clk_parent_sel_name[s], id); -+#endif -+ return (int)sel->parent[p_sel]; -+ } - - return -EINVAL; - } - --static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id) -+static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -- uint32_t selr, src; -- unsigned long refclk; -- -- selr = mmio_read_32(priv->base + pll[pll_id].rckxselr); -- src = selr & RCC_SELR_REFCLK_SRC_MASK; -+ uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); -+ uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; - -- refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]); -- -- return refclk; -+ return stm32mp1_clk_get_fixed(pll->refclk[src]); - } - - /* -@@ -562,20 +827,19 @@ static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv, - * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) - * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) - */ --static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id) -+static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; - unsigned long refclk, fvco; - uint32_t cfgr1, fracr, divm, divn; -+ uintptr_t rcc_base = stm32mp_rcc_base(); - -- cfgr1 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr1); -- fracr = mmio_read_32(priv->base + pll[pll_id].pllxfracr); -+ cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); -+ fracr = mmio_read_32(rcc_base + pll->pllxfracr); - - divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; - divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; - -- refclk = stm32mp1_pll_get_fref_ck(priv, pll_id); -+ refclk = stm32mp1_pll_get_fref(pll); - - /* - * With FRACV : -@@ -584,13 +848,13 @@ static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv, - * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) - */ - if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { -- uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) -- >> RCC_PLLNFRACR_FRACV_SHIFT; -+ uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> -+ RCC_PLLNFRACR_FRACV_SHIFT; - unsigned long long numerator, denominator; - -- numerator = ((unsigned long long)divn + 1U) << 13; -- numerator = (refclk * numerator) + fracv; -- denominator = ((unsigned long long)divm + 1U) << 13; -+ numerator = (((unsigned long long)divn + 1U) << 13) + fracv; -+ numerator = refclk * numerator; -+ denominator = ((unsigned long long)divm + 1U) << 13; - fvco = (unsigned long)(numerator / denominator); - } else { - fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); -@@ -599,11 +863,10 @@ static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv, - return fvco; - } - --static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id, -+static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, - enum stm32mp1_div_id div_id) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); - unsigned long dfout; - uint32_t cfgr2, divy; - -@@ -611,42 +874,43 @@ static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv, - return 0; - } - -- cfgr2 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr2); -+ cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); - divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; - -- dfout = stm32mp1_pll_get_fvco(priv, pll_id) / (divy + 1U); -+ dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); -+ - - return dfout; - } - --static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) -+static unsigned long get_clock_rate(int p) - { - uint32_t reg, clkdiv; - unsigned long clock = 0; -+ uintptr_t rcc_base = stm32mp_rcc_base(); - - switch (p) { - case _CK_MPU: - /* MPU sub system */ -- reg = mmio_read_32(priv->base + RCC_MPCKSELR); -+ reg = mmio_read_32(rcc_base + RCC_MPCKSELR); - switch (reg & RCC_SELR_SRC_MASK) { - case RCC_MPCKSELR_HSI: -- clock = stm32mp1_clk_get_fixed(priv, _HSI); -+ clock = stm32mp1_clk_get_fixed(_HSI); - break; - case RCC_MPCKSELR_HSE: -- clock = stm32mp1_clk_get_fixed(priv, _HSE); -+ clock = stm32mp1_clk_get_fixed(_HSE); - break; - case RCC_MPCKSELR_PLL: -- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); - break; - case RCC_MPCKSELR_PLL_MPUDIV: -- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); - -- reg = mmio_read_32(priv->base + RCC_MPCKDIVR); -+ reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); - clkdiv = reg & RCC_MPUDIV_MASK; - if (clkdiv != 0U) { - clock /= stm32mp1_mpu_div[clkdiv]; - } -- - break; - default: - break; -@@ -658,49 +922,94 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) - case _HCLK6: - case _PCLK4: - case _PCLK5: -- reg = mmio_read_32(priv->base + RCC_ASSCKSELR); -+ reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); - switch (reg & RCC_SELR_SRC_MASK) { - case RCC_ASSCKSELR_HSI: -- clock = stm32mp1_clk_get_fixed(priv, _HSI); -+ clock = stm32mp1_clk_get_fixed(_HSI); - break; - case RCC_ASSCKSELR_HSE: -- clock = stm32mp1_clk_get_fixed(priv, _HSE); -+ clock = stm32mp1_clk_get_fixed(_HSE); - break; - case RCC_ASSCKSELR_PLL: -- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); - break; - default: - break; - } - - /* System clock divider */ -- reg = mmio_read_32(priv->base + RCC_AXIDIVR); -+ reg = mmio_read_32(rcc_base + RCC_AXIDIVR); - clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; - - switch (p) { - case _PCLK4: -- reg = mmio_read_32(priv->base + RCC_APB4DIVR); -+ reg = mmio_read_32(rcc_base + RCC_APB4DIVR); - clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; - break; - case _PCLK5: -- reg = mmio_read_32(priv->base + RCC_APB5DIVR); -+ reg = mmio_read_32(rcc_base + RCC_APB5DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ default: -+ break; -+ } -+ break; -+ /* MCU sub system */ -+ case _CK_MCU: -+ case _PCLK1: -+ case _PCLK2: -+ case _PCLK3: -+ reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); -+ switch (reg & RCC_SELR_SRC_MASK) { -+ case RCC_MSSCKSELR_HSI: -+ clock = stm32mp1_clk_get_fixed(_HSI); -+ break; -+ case RCC_MSSCKSELR_HSE: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ break; -+ case RCC_MSSCKSELR_CSI: -+ clock = stm32mp1_clk_get_fixed(_CSI); -+ break; -+ case RCC_MSSCKSELR_PLL: -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); -+ break; -+ default: -+ break; -+ } -+ -+ /* MCU clock divider */ -+ reg = mmio_read_32(rcc_base + RCC_MCUDIVR); -+ clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; -+ -+ switch (p) { -+ case _PCLK1: -+ reg = mmio_read_32(rcc_base + RCC_APB1DIVR); - clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; - break; -+ case _PCLK2: -+ reg = mmio_read_32(rcc_base + RCC_APB2DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ case _PCLK3: -+ reg = mmio_read_32(rcc_base + RCC_APB3DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ case _CK_MCU: - default: - break; - } - break; - case _CK_PER: -- reg = mmio_read_32(priv->base + RCC_CPERCKSELR); -+ reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); - switch (reg & RCC_SELR_SRC_MASK) { - case RCC_CPERCKSELR_HSI: -- clock = stm32mp1_clk_get_fixed(priv, _HSI); -+ clock = stm32mp1_clk_get_fixed(_HSI); - break; - case RCC_CPERCKSELR_HSE: -- clock = stm32mp1_clk_get_fixed(priv, _HSE); -+ clock = stm32mp1_clk_get_fixed(_HSE); - break; - case RCC_CPERCKSELR_CSI: -- clock = stm32mp1_clk_get_fixed(priv, _CSI); -+ clock = stm32mp1_clk_get_fixed(_CSI); - break; - default: - break; -@@ -708,65 +1017,65 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) - break; - case _HSI: - case _HSI_KER: -- clock = stm32mp1_clk_get_fixed(priv, _HSI); -+ clock = stm32mp1_clk_get_fixed(_HSI); - break; - case _CSI: - case _CSI_KER: -- clock = stm32mp1_clk_get_fixed(priv, _CSI); -+ clock = stm32mp1_clk_get_fixed(_CSI); - break; - case _HSE: - case _HSE_KER: -- clock = stm32mp1_clk_get_fixed(priv, _HSE); -+ clock = stm32mp1_clk_get_fixed(_HSE); - break; - case _HSE_KER_DIV2: -- clock = stm32mp1_clk_get_fixed(priv, _HSE) >> 1; -+ clock = stm32mp1_clk_get_fixed(_HSE) >> 1; - break; - case _LSI: -- clock = stm32mp1_clk_get_fixed(priv, _LSI); -+ clock = stm32mp1_clk_get_fixed(_LSI); - break; - case _LSE: -- clock = stm32mp1_clk_get_fixed(priv, _LSE); -+ clock = stm32mp1_clk_get_fixed(_LSE); - break; - /* PLL */ - case _PLL1_P: -- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); - break; - case _PLL1_Q: -- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_Q); -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); - break; - case _PLL1_R: -- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_R); -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); - break; - case _PLL2_P: -- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); - break; - case _PLL2_Q: -- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_Q); -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); - break; - case _PLL2_R: -- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_R); -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); - break; - case _PLL3_P: -- clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); - break; - case _PLL3_Q: -- clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_Q); -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); - break; - case _PLL3_R: -- clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_R); -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); - break; - case _PLL4_P: -- clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_P); -+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); - break; - case _PLL4_Q: -- clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_Q); -+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); - break; - case _PLL4_R: -- clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_R); -+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); - break; - /* Other */ - case _USB_PHY_48: -- clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48); -+ clock = USB_PHY_48_MHZ; - break; - default: - break; -@@ -775,112 +1084,155 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) - return clock; - } - --bool stm32mp1_clk_is_enabled(unsigned long id) -+static void __clk_enable(struct stm32mp1_clk_gate const *gate) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ if (gate->set_clr != 0U) { -+ mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); -+ } else { -+ stm32mp_mmio_setbits_32_shregs(rcc_base + gate->offset, -+ BIT(gate->bit)); -+ } -+ -+ VERBOSE("Clock %d has been enabled", gate->index); -+} -+ -+static void __clk_disable(struct stm32mp1_clk_gate const *gate) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ if (gate->set_clr != 0U) { -+ mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, -+ BIT(gate->bit)); -+ } else { -+ stm32mp_mmio_clrbits_32_shregs(rcc_base + gate->offset, -+ BIT(gate->bit)); -+ } -+ -+ VERBOSE("Clock %d has been disabled", gate->index); -+} -+ -+static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); -+} -+ -+unsigned int stm32mp1_clk_get_refcount(unsigned long id) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; -- const struct stm32mp1_clk_gate *gate = priv->data->gate; -- int i = stm32mp1_clk_get_id(priv, id); -+ int i = stm32mp1_clk_get_gated_id(id); - - if (i < 0) { -- return false; -+ panic(); - } - -- return ((mmio_read_32(priv->base + gate[i].offset) & -- BIT(gate[i].bit)) != 0U); -+ return gate_refcounts[i]; - } - --int stm32mp1_clk_enable(unsigned long id) -+void __stm32mp1_clk_enable(unsigned long id, bool secure) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; -- const struct stm32mp1_clk_gate *gate = priv->data->gate; -- int i = stm32mp1_clk_get_id(priv, id); -+ const struct stm32mp1_clk_gate *gate; -+ int i = stm32mp1_clk_get_gated_id(id); -+ unsigned int *refcnt; - - if (i < 0) { -- return i; -+ ERROR("Clock %d can't be enabled\n", (uint32_t)id); -+ panic(); - } - -- if (gate[i].set_clr != 0U) { -- mmio_write_32(priv->base + gate[i].offset, BIT(gate[i].bit)); -- } else { -- mmio_setbits_32(priv->base + gate[i].offset, BIT(gate[i].bit)); -+ gate = gate_ref(i); -+ refcnt = &gate_refcounts[i]; -+ -+ stm32mp1_clk_lock(&refcount_lock); -+ -+ if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { -+ __clk_enable(gate); - } - -- return 0; -+ stm32mp1_clk_unlock(&refcount_lock); - } - --int stm32mp1_clk_disable(unsigned long id) -+void __stm32mp1_clk_disable(unsigned long id, bool secure) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; -- const struct stm32mp1_clk_gate *gate = priv->data->gate; -- int i = stm32mp1_clk_get_id(priv, id); -+ const struct stm32mp1_clk_gate *gate; -+ int i = stm32mp1_clk_get_gated_id(id); -+ unsigned int *refcnt; - - if (i < 0) { -- return i; -+ ERROR("Clock %d can't be disabled\n", (uint32_t)id); -+ panic(); - } - -- if (gate[i].set_clr != 0U) { -- mmio_write_32(priv->base + gate[i].offset -- + RCC_MP_ENCLRR_OFFSET, -- BIT(gate[i].bit)); -- } else { -- mmio_clrbits_32(priv->base + gate[i].offset, BIT(gate[i].bit)); -+ gate = gate_ref(i); -+ refcnt = &gate_refcounts[i]; -+ -+ stm32mp1_clk_lock(&refcount_lock); -+ -+ if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { -+ __clk_disable(gate); - } - -- return 0; -+ stm32mp1_clk_unlock(&refcount_lock); - } - --unsigned long stm32mp1_clk_get_rate(unsigned long id) -+bool stm32mp1_clk_is_enabled(unsigned long id) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; -- int p = stm32mp1_clk_get_parent(priv, id); -- unsigned long rate; -+ int i = stm32mp1_clk_get_gated_id(id); -+ -+ if (i < 0) { -+ panic(); -+ } -+ -+ return __clk_is_enabled(gate_ref(i)); -+} -+ -+unsigned long stm32mp_clk_get_rate(unsigned long id) -+{ -+ int p = stm32mp1_clk_get_parent(id); - - if (p < 0) { - return 0; - } - -- rate = stm32mp1_clk_get(priv, p); -- -- return rate; -+ return get_clock_rate(p); - } - --static void stm32mp1_ls_osc_set(int enable, uint32_t rcc, uint32_t offset, -- uint32_t mask_on) -+static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) - { -- uint32_t address = rcc + offset; -+ uint32_t address = stm32mp_rcc_base() + offset; - -- if (enable != 0) { -+ if (enable) { - mmio_setbits_32(address, mask_on); - } else { - mmio_clrbits_32(address, mask_on); - } - } - --static void stm32mp1_hs_ocs_set(int enable, uint32_t rcc, uint32_t mask_on) -+static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) - { -- if (enable != 0) { -- mmio_setbits_32(rcc + RCC_OCENSETR, mask_on); -- } else { -- mmio_setbits_32(rcc + RCC_OCENCLRR, mask_on); -- } -+ uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; -+ uint32_t address = stm32mp_rcc_base() + offset; -+ -+ mmio_write_32(address, mask_on); - } - --static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, -- uint32_t mask_rdy) -+static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) - { -- unsigned long start; -+ uint64_t start; - uint32_t mask_test; -- uint32_t address = rcc + offset; -+ uint32_t address = stm32mp_rcc_base() + offset; - -- if (enable != 0) { -+ if (enable) { - mask_test = mask_rdy; - } else { - mask_test = 0; - } - -- start = get_timer(0); -+ start = timeout_start(); - while ((mmio_read_32(address) & mask_rdy) != mask_test) { -- if (get_timer(start) > OSCRDY_TIMEOUT) { -+ if (timeout_elapsed(start, OSCRDY_TIMEOUT)) { - ERROR("OSC %x @ %x timeout for enable=%d : 0x%x\n", - mask_rdy, address, enable, mmio_read_32(address)); - return -ETIMEDOUT; -@@ -890,19 +1242,24 @@ static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, - return 0; - } - --static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv) -+static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) - { - uint32_t value; -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ if (digbyp) { -+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); -+ } - -- if (bypass) { -- mmio_setbits_32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP); -+ if (bypass || digbyp) { -+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); - } - - /* - * Warning: not recommended to switch directly from "high drive" - * to "medium low drive", and vice-versa. - */ -- value = (mmio_read_32(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> -+ value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> - RCC_BDCR_LSEDRV_SHIFT; - - while (value != lsedrv) { -@@ -912,77 +1269,85 @@ static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv) - value++; - } - -- mmio_clrsetbits_32(rcc + RCC_BDCR, -+ mmio_clrsetbits_32(rcc_base + RCC_BDCR, - RCC_BDCR_LSEDRV_MASK, - value << RCC_BDCR_LSEDRV_SHIFT); - } - -- stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON); -+ stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); - } - --static void stm32mp1_lse_wait(uint32_t rcc) -+static void stm32mp1_lse_wait(void) - { -- if (stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { -+ if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { - VERBOSE("%s: failed\n", __func__); - } - } - --static void stm32mp1_lsi_set(uint32_t rcc, int enable) -+static void stm32mp1_lsi_set(bool enable) - { -- stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION); -- if (stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != -+ stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); -+ -+ if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != - 0) { - VERBOSE("%s: failed\n", __func__); - } - } - --static void stm32mp1_hse_enable(uint32_t rcc, bool bypass, bool css) -+static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) - { -- if (bypass) { -- mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP); -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ if (digbyp) { -+ mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); -+ } -+ -+ if (bypass || digbyp) { -+ mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); - } - -- stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON); -- if (stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != -+ stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); -+ if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != - 0) { - VERBOSE("%s: failed\n", __func__); - } - - if (css) { -- mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSECSSON); -+ mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); - } - } - --static void stm32mp1_csi_set(uint32_t rcc, int enable) -+static void stm32mp1_csi_set(bool enable) - { -- stm32mp1_ls_osc_set(enable, rcc, RCC_OCENSETR, RCC_OCENR_CSION); -- if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != -+ stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); -+ if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != - 0) { - VERBOSE("%s: failed\n", __func__); - } - } - --static void stm32mp1_hsi_set(uint32_t rcc, int enable) -+static void stm32mp1_hsi_set(bool enable) - { -- stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION); -- if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != -+ stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); -+ if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != - 0) { - VERBOSE("%s: failed\n", __func__); - } - } - --static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv) -+static int stm32mp1_set_hsidiv(uint8_t hsidiv) - { -- unsigned long start; -- uint32_t address = rcc + RCC_OCRDYR; -+ uint64_t start; -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ uint32_t address = rcc_base + RCC_OCRDYR; - -- mmio_clrsetbits_32(rcc + RCC_HSICFGR, -+ mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, - RCC_HSICFGR_HSIDIV_MASK, - RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); - -- start = get_timer(0); -+ start = timeout_start(); - while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { -- if (get_timer(start) > HSIDIV_TIMEOUT) { -+ if (timeout_elapsed(start, HSIDIV_TIMEOUT)) { - ERROR("HSIDIV failed @ 0x%x: 0x%x\n", - address, mmio_read_32(address)); - return -ETIMEDOUT; -@@ -992,7 +1357,7 @@ static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv) - return 0; - } - --static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq) -+static int stm32mp1_hsidiv(unsigned long hsifreq) - { - uint8_t hsidiv; - uint32_t hsidivfreq = MAX_HSI_HZ; -@@ -1011,31 +1376,103 @@ static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq) - } - - if (hsidiv != 0U) { -- return stm32mp1_set_hsidiv(rcc, hsidiv); -+ return stm32mp1_set_hsidiv(hsidiv); - } - - return 0; - } - --static void stm32mp1_pll_start(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id) -+static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, -+ unsigned int clksrc, -+ uint32_t *pllcfg, int plloff) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ uint32_t pllxcr = rcc_base + pll->pllxcr; -+ enum stm32mp1_plltype type = pll->plltype; -+ uint32_t address = rcc_base + (clksrc >> 4); -+ unsigned long refclk; -+ uint32_t ifrge = 0U; -+ uint32_t src, value, fracv; -+ -+ /* Check PLL output */ -+ if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { -+ return false; -+ } -+ -+ /* Check current clksrc */ -+ src = mmio_read_32(address) & RCC_SELR_SRC_MASK; -+ if (src != (clksrc & RCC_SELR_SRC_MASK)) { -+ return false; -+ } -+ -+ /* Check Div */ -+ src = mmio_read_32(rcc_base + pll->rckxselr) & -+ RCC_SELR_REFCLK_SRC_MASK; -+ -+ refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / -+ (pllcfg[PLLCFG_M] + 1U); -+ -+ if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || -+ (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { -+ return false; -+ } -+ -+ if ((type == PLL_800) && (refclk >= 8000000U)) { -+ ifrge = 1U; -+ } -+ -+ value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & -+ RCC_PLLNCFGR1_DIVN_MASK; -+ value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & -+ RCC_PLLNCFGR1_DIVM_MASK; -+ value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & -+ RCC_PLLNCFGR1_IFRGE_MASK; -+ if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { -+ return false; -+ } -+ -+ /* Fractional configuration */ -+ fracv = fdt_read_uint32_default(plloff, "frac", 0); -+ -+ value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; -+ value |= RCC_PLLNFRACR_FRACLE; -+ if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { -+ return false; -+ } -+ -+ /* Output config */ -+ value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & -+ RCC_PLLNCFGR2_DIVP_MASK; -+ value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & -+ RCC_PLLNCFGR2_DIVQ_MASK; -+ value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & -+ RCC_PLLNCFGR2_DIVR_MASK; -+ if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { -+ return false; -+ } -+ -+ return true; -+} -+ -+static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; - -- mmio_write_32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_PLLON); -+ mmio_write_32(pllxcr, RCC_PLLNCR_PLLON); - } - --static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id, uint32_t output) -+static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -- uint32_t pllxcr = priv->base + pll[pll_id].pllxcr; -- unsigned long start; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; -+ uint64_t start; - -- start = get_timer(0); -+ start = timeout_start(); - /* Wait PLL lock */ - while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { -- if (get_timer(start) > PLLRDY_TIMEOUT) { -+ if (timeout_elapsed(start, PLLRDY_TIMEOUT)) { - ERROR("PLL%d start failed @ 0x%x: 0x%x\n", - pll_id, pllxcr, mmio_read_32(pllxcr)); - return -ETIMEDOUT; -@@ -1048,12 +1485,11 @@ static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv, - return 0; - } - --static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id) -+static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -- uint32_t pllxcr = priv->base + pll[pll_id].pllxcr; -- unsigned long start; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; -+ uint64_t start; - - /* Stop all output */ - mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | -@@ -1062,10 +1498,10 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, - /* Stop PLL */ - mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); - -- start = get_timer(0); -+ start = timeout_start(); - /* Wait PLL stopped */ - while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { -- if (get_timer(start) > PLLRDY_TIMEOUT) { -+ if (timeout_elapsed(start, PLLRDY_TIMEOUT)) { - ERROR("PLL%d stop failed @ 0x%x: 0x%x\n", - pll_id, pllxcr, mmio_read_32(pllxcr)); - return -ETIMEDOUT; -@@ -1075,12 +1511,11 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, - return 0; - } - --static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id, -+static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, - uint32_t *pllcfg) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -- uint32_t rcc = priv->base; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uintptr_t rcc_base = stm32mp_rcc_base(); - uint32_t value; - - value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & -@@ -1089,24 +1524,23 @@ static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv, - RCC_PLLNCFGR2_DIVQ_MASK; - value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & - RCC_PLLNCFGR2_DIVR_MASK; -- mmio_write_32(rcc + pll[pll_id].pllxcfgr2, value); -+ mmio_write_32(rcc_base + pll->pllxcfgr2, value); - } - --static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id, -+static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, - uint32_t *pllcfg, uint32_t fracv) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -- uint32_t rcc = priv->base; -- enum stm32mp1_plltype type = pll[pll_id].plltype; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t rcc_base = stm32mp_rcc_base(); -+ enum stm32mp1_plltype type = pll->plltype; - unsigned long refclk; - uint32_t ifrge = 0; - uint32_t src, value; - -- src = mmio_read_32(priv->base + pll[pll_id].rckxselr) & -+ src = mmio_read_32(rcc_base + pll->rckxselr) & - RCC_SELR_REFCLK_SRC_MASK; - -- refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]) / -+ refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / - (pllcfg[PLLCFG_M] + 1U); - - if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || -@@ -1124,28 +1558,26 @@ static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv, - RCC_PLLNCFGR1_DIVM_MASK; - value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & - RCC_PLLNCFGR1_IFRGE_MASK; -- mmio_write_32(rcc + pll[pll_id].pllxcfgr1, value); -+ mmio_write_32(rcc_base + pll->pllxcfgr1, value); - - /* Fractional configuration */ - value = 0; -- mmio_write_32(rcc + pll[pll_id].pllxfracr, value); -+ mmio_write_32(rcc_base + pll->pllxfracr, value); - - value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; -- mmio_write_32(rcc + pll[pll_id].pllxfracr, value); -+ mmio_write_32(rcc_base + pll->pllxfracr, value); - - value |= RCC_PLLNFRACR_FRACLE; -- mmio_write_32(rcc + pll[pll_id].pllxfracr, value); -+ mmio_write_32(rcc_base + pll->pllxfracr, value); - -- stm32mp1_pll_config_output(priv, pll_id, pllcfg); -+ stm32mp1_pll_config_output(pll_id, pllcfg); - - return 0; - } - --static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv, -- enum stm32mp1_pll_id pll_id, -- uint32_t *csg) -+static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) - { -- const struct stm32mp1_clk_pll *pll = priv->data->pll; -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); - uint32_t pllxcsg = 0; - - pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & -@@ -1157,21 +1589,20 @@ static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv, - pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & - RCC_PLLNCSGR_SSCG_MODE_MASK; - -- mmio_write_32(priv->base + pll[pll_id].pllxcsgr, pllxcsg); -+ mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); - } - --static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv, -- unsigned int clksrc) -+static int stm32mp1_set_clksrc(unsigned int clksrc) - { -- uint32_t address = priv->base + (clksrc >> 4); -- unsigned long start; -+ uint32_t address = stm32mp_rcc_base() + (clksrc >> 4); -+ uint64_t start; - - mmio_clrsetbits_32(address, RCC_SELR_SRC_MASK, - clksrc & RCC_SELR_SRC_MASK); - -- start = get_timer(0); -+ start = timeout_start(); - while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) { -- if (get_timer(start) > CLKSRC_TIMEOUT) { -+ if (timeout_elapsed(start, CLKSRC_TIMEOUT)) { - ERROR("CLKSRC %x start failed @ 0x%x: 0x%x\n", - clksrc, address, mmio_read_32(address)); - return -ETIMEDOUT; -@@ -1183,14 +1614,14 @@ static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv, - - static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address) - { -- unsigned long start; -+ uint64_t start; - - mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, - clkdiv & RCC_DIVR_DIV_MASK); - -- start = get_timer(0); -+ start = timeout_start(); - while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { -- if (get_timer(start) > CLKDIV_TIMEOUT) { -+ if (timeout_elapsed(start, CLKDIV_TIMEOUT)) { - ERROR("CLKDIV %x start failed @ 0x%x: 0x%x\n", - clkdiv, address, mmio_read_32(address)); - return -ETIMEDOUT; -@@ -1200,10 +1631,9 @@ static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address) - return 0; - } - --static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv, -- uint32_t clksrc, uint32_t clkdiv) -+static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) - { -- uint32_t address = priv->base + (clksrc >> 4); -+ uint32_t address = stm32mp_rcc_base() + (clksrc >> 4); - - /* - * Binding clksrc : -@@ -1224,10 +1654,9 @@ static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv, - } - } - --static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv, -- unsigned int clksrc, bool lse_css) -+static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) - { -- uint32_t address = priv->base + RCC_BDCR; -+ uint32_t address = stm32mp_rcc_base() + RCC_BDCR; - - if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || - (clksrc != (uint32_t)CLK_RTC_DISABLED)) { -@@ -1243,52 +1672,73 @@ static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv, - } - } - --#define CNTCVL_OFF 0x008 --#define CNTCVU_OFF 0x00C -- --static void stm32mp1_stgen_config(struct stm32mp1_clk_priv *priv) -+static void stm32mp1_stgen_config(void) - { - uintptr_t stgen; -- int p; - uint32_t cntfid0; - unsigned long rate; -+ unsigned long long counter; - - stgen = fdt_get_stgen_base(); -- - cntfid0 = mmio_read_32(stgen + CNTFID_OFF); -- p = stm32mp1_clk_get_parent(priv, STGEN_K); -- rate = stm32mp1_clk_get(priv, p); -+ rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); - -- if (cntfid0 != rate) { -- unsigned long long counter; -+ if (cntfid0 == rate) { -+ return; -+ } - -- mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); -- counter = (unsigned long long) -- mmio_read_32(stgen + CNTCVL_OFF); -- counter |= ((unsigned long long) -- (mmio_read_32(stgen + CNTCVU_OFF))) << 32; -- counter = (counter * rate / cntfid0); -- mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter); -- mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32)); -- mmio_write_32(stgen + CNTFID_OFF, rate); -- mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); -+ mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); -+ counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF); -+ counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32; -+ counter = (counter * rate / cntfid0); - -- write_cntfrq((u_register_t)rate); -+ mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter); -+ mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32)); -+ mmio_write_32(stgen + CNTFID_OFF, rate); -+ mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); - -- /* Need to update timer with new frequency */ -- generic_delay_timer_init(); -- } -+ write_cntfrq((u_register_t)rate); -+ -+ /* Need to update timer with new frequency */ -+ generic_delay_timer_init(); - } - --void stm32mp1_stgen_increment(unsigned long long offset_in_ms) -+unsigned long stm32mp_clk_timer_get_rate(unsigned long id) - { -- uintptr_t stgen; -- unsigned long long cnt; -+ unsigned long parent_rate; -+ uint32_t prescaler, timpre; -+ uintptr_t rcc_base = stm32mp_rcc_base(); - -- stgen = fdt_get_stgen_base(); -- -- cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) | -- mmio_read_32(stgen + CNTCVL_OFF); -+ parent_rate = stm32mp_clk_get_rate(id); -+ -+ if (id < TIM1_K) { -+ prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & -+ RCC_APBXDIV_MASK; -+ timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & -+ RCC_TIMGXPRER_TIMGXPRE; -+ } else { -+ prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & -+ RCC_APBXDIV_MASK; -+ timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & -+ RCC_TIMGXPRER_TIMGXPRE; -+ } -+ -+ if (!prescaler) { -+ return parent_rate; -+ } -+ -+ return parent_rate * (timpre + 1) * 2; -+} -+ -+void stm32mp1_stgen_increment(unsigned long long offset_in_ms) -+{ -+ uintptr_t stgen; -+ unsigned long long cnt; -+ -+ stgen = fdt_get_stgen_base(); -+ -+ cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) | -+ mmio_read_32(stgen + CNTCVL_OFF); - - cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U; - -@@ -1298,9 +1748,46 @@ void stm32mp1_stgen_increment(unsigned long long offset_in_ms) - mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); - } - --static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs) -+/******************************************************************************* -+ * This function determines the number of needed RTC calendar read operations -+ * to get consistent values (1 or 2 depending on clock frequencies). -+ * If APB1 frequency is lower than 7 times the RTC one, the software has to -+ * read the calendar time and date registers twice. -+ * Returns true if read twice is needed, false else. -+ ******************************************************************************/ -+bool stm32mp1_rtc_get_read_twice(void) - { -- uint32_t address = priv->base + ((pkcs >> 4) & 0xFFFU); -+ unsigned long apb1_freq; -+ uint32_t rtc_freq; -+ uint32_t apb1_div; -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ switch ((mmio_read_32(rcc_base + RCC_BDCR) & -+ RCC_BDCR_RTCSRC_MASK) >> RCC_BDCR_RTCSRC_SHIFT) { -+ case 1: -+ rtc_freq = stm32mp_clk_get_rate(CK_LSE); -+ break; -+ case 2: -+ rtc_freq = stm32mp_clk_get_rate(CK_LSI); -+ break; -+ case 3: -+ rtc_freq = stm32mp_clk_get_rate(CK_HSE); -+ rtc_freq /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & -+ RCC_DIVR_DIV_MASK) + 1U; -+ break; -+ default: -+ panic(); -+ } -+ -+ apb1_div = mmio_read_32(rcc_base + RCC_APB1DIVR) & RCC_APBXDIV_MASK; -+ apb1_freq = stm32mp_clk_get_rate(CK_MCU) >> apb1_div; -+ -+ return apb1_freq < (rtc_freq * 7U); -+} -+ -+static void stm32mp1_pkcs_config(uint32_t pkcs) -+{ -+ uint32_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); - uint32_t value = pkcs & 0xFU; - uint32_t mask = 0xFU; - -@@ -1314,8 +1801,7 @@ static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs) - - int stm32mp1_clk_init(void) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; -- uint32_t rcc = priv->base; -+ uint32_t rcc_base = stm32mp_rcc_base(); - unsigned int clksrc[CLKSRC_NB]; - unsigned int clkdiv[CLKDIV_NB]; - unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; -@@ -1323,11 +1809,16 @@ int stm32mp1_clk_init(void) - int ret, len; - enum stm32mp1_pll_id i; - bool lse_css = false; -- const uint32_t *pkcs_cell; -+ bool pll3_preserve = false; -+ bool pll4_preserve = false; -+ bool pll4_bootrom = false; -+ const fdt32_t *pkcs_cell; -+ int stgen_p = stm32mp1_clk_get_parent((int)STGEN_K); -+ int usbphy_p = stm32mp1_clk_get_parent((int)USBPHY_K); - - /* Check status field to disable security */ - if (!fdt_get_rcc_secure_status()) { -- mmio_write_32(rcc + RCC_TZCR, 0); -+ mmio_write_32(rcc_base + RCC_TZCR, 0); - } - - ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc, -@@ -1359,113 +1850,149 @@ int stm32mp1_clk_init(void) - } - } - -- stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); -- stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); -+ stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); -+ stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); - - /* - * Switch ON oscillator found in device-tree. - * Note: HSI already ON after BootROM stage. - */ -- if (priv->osc[_LSI] != 0U) { -- stm32mp1_lsi_set(rcc, 1); -+ if (stm32mp1_osc[_LSI] != 0U) { -+ stm32mp1_lsi_set(true); - } -- if (priv->osc[_LSE] != 0U) { -- bool bypass; -+ if (stm32mp1_osc[_LSE] != 0U) { -+ bool bypass, digbyp; - uint32_t lsedrv; - - bypass = fdt_osc_read_bool(_LSE, "st,bypass"); -+ digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); - lse_css = fdt_osc_read_bool(_LSE, "st,css"); - lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", - LSEDRV_MEDIUM_HIGH); -- stm32mp1_lse_enable(rcc, bypass, lsedrv); -+ stm32mp1_lse_enable(bypass, digbyp, lsedrv); - } -- if (priv->osc[_HSE] != 0U) { -- bool bypass, css; -+ if (stm32mp1_osc[_HSE] != 0U) { -+ bool bypass, digbyp, css; - -- bypass = fdt_osc_read_bool(_LSE, "st,bypass"); -- css = fdt_osc_read_bool(_LSE, "st,css"); -- stm32mp1_hse_enable(rcc, bypass, css); -+ bypass = fdt_osc_read_bool(_HSE, "st,bypass"); -+ digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); -+ css = fdt_osc_read_bool(_HSE, "st,css"); -+ stm32mp1_hse_enable(bypass, digbyp, css); - } - /* - * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) - * => switch on CSI even if node is not present in device tree - */ -- stm32mp1_csi_set(rcc, 1); -+ stm32mp1_csi_set(true); - - /* Come back to HSI */ -- ret = stm32mp1_set_clksrc(priv, CLK_MPU_HSI); -+ ret = stm32mp1_set_clksrc(CLK_MPU_HSI); -+ if (ret != 0) { -+ return ret; -+ } -+ ret = stm32mp1_set_clksrc(CLK_AXI_HSI); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clksrc(priv, CLK_AXI_HSI); -+ ret = stm32mp1_set_clksrc(CLK_MCU_HSI); - if (ret != 0) { - return ret; - } - -+ if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & -+ RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { -+ pll3_preserve = stm32mp1_check_pll_conf(_PLL3, -+ clksrc[CLKSRC_PLL3], -+ pllcfg[_PLL3], -+ plloff[_PLL3]); -+ pll4_preserve = stm32mp1_check_pll_conf(_PLL4, -+ clksrc[CLKSRC_PLL4], -+ pllcfg[_PLL4], -+ plloff[_PLL4]); -+ } -+ /* Don't initialize PLL4, when used by BOOTROM */ -+ if ((get_boot_device() == BOOT_DEVICE_USB) && -+ ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { -+ pll4_bootrom = true; -+ pll4_preserve = true; -+ } -+ - for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { -- if (i == _PLL4) -+ if (((i == _PLL3) && pll3_preserve) || -+ ((i == _PLL4) && pll4_preserve)) { - continue; -- ret = stm32mp1_pll_stop(priv, i); -+ } -+ -+ ret = stm32mp1_pll_stop(i); - if (ret != 0) { - return ret; - } - } - - /* Configure HSIDIV */ -- if (priv->osc[_HSI] != 0U) { -- ret = stm32mp1_hsidiv(rcc, priv->osc[_HSI]); -+ if (stm32mp1_osc[_HSI] != 0U) { -+ ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); - if (ret != 0) { - return ret; - } -- stm32mp1_stgen_config(priv); -+ stm32mp1_stgen_config(); - } - - /* Select DIV */ - /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ -- mmio_write_32(rcc + RCC_MPCKDIVR, -+ mmio_write_32(rcc_base + RCC_MPCKDIVR, - clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR); -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); -+ if (ret != 0) { -+ return ret; -+ } -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR); -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR); -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR); -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR); -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR); -+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); - if (ret != 0) { - return ret; - } - - /* No ready bit for RTC */ -- mmio_write_32(rcc + RCC_RTCDIVR, -+ mmio_write_32(rcc_base + RCC_RTCDIVR, - clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); - - /* Configure PLLs source */ -- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL12]); -+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL3]); -- if (ret != 0) { -- return ret; -+ -+ if (!pll3_preserve) { -+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); -+ if (ret != 0) { -+ return ret; -+ } - } - -- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL4]); -- if (ret != 0) { -- return ret; -+ if (!pll4_preserve) { -+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); -+ if (ret != 0) { -+ return ret; -+ } - } - - /* Configure and start PLLs */ -@@ -1473,25 +2000,36 @@ int stm32mp1_clk_init(void) - uint32_t fracv; - uint32_t csg[PLLCSG_NB]; - -+ if (((i == _PLL3) && pll3_preserve) || -+ ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { -+ continue; -+ } -+ - if (!fdt_check_node(plloff[i])) { - continue; - } - -+ if ((i == _PLL4) && pll4_bootrom) { -+ /* Set output divider if not done by the Bootrom */ -+ stm32mp1_pll_config_output(i, pllcfg[i]); -+ continue; -+ } -+ - fracv = fdt_read_uint32_default(plloff[i], "frac", 0); - -- ret = stm32mp1_pll_config(priv, i, pllcfg[i], fracv); -+ ret = stm32mp1_pll_config(i, pllcfg[i], fracv); - if (ret != 0) { - return ret; - } - ret = fdt_read_uint32_array(plloff[i], "csg", csg, - (uint32_t)PLLCSG_NB); - if (ret == 0) { -- stm32mp1_pll_csg(priv, i, csg); -+ stm32mp1_pll_csg(i, csg); - } else if (ret != -FDT_ERR_NOTFOUND) { - return ret; - } - -- stm32mp1_pll_start(priv, i); -+ stm32mp1_pll_start(i); - } - /* Wait and start PLLs ouptut when ready */ - for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { -@@ -1499,43 +2037,50 @@ int stm32mp1_clk_init(void) - continue; - } - -- ret = stm32mp1_pll_output(priv, i, pllcfg[i][PLLCFG_O]); -+ ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); - if (ret != 0) { - return ret; - } - } - /* Wait LSE ready before to use it */ -- if (priv->osc[_LSE] != 0U) { -- stm32mp1_lse_wait(rcc); -+ if (stm32mp1_osc[_LSE] != 0U) { -+ stm32mp1_lse_wait(); - } - - /* Configure with expected clock source */ -- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_MPU]); -+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_AXI]); -+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); - if (ret != 0) { - return ret; - } -- stm32mp1_set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css); -+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); -+ if (ret != 0) { -+ return ret; -+ } -+ stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); - - /* Configure PKCK */ - pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); - if (pkcs_cell != NULL) { - bool ckper_disabled = false; - uint32_t j; -+ uint32_t usbreg_bootrom = 0U; - -- priv->pkcs_usb_value = 0; -+ if (pll4_bootrom) { -+ usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR); -+ } - - for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { -- uint32_t pkcs = (uint32_t)fdt32_to_cpu(pkcs_cell[j]); -+ uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); - - if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { - ckper_disabled = true; - continue; - } -- stm32mp1_pkcs_config(priv, pkcs); -+ stm32mp1_pkcs_config(pkcs); - } - - /* -@@ -1545,18 +2090,37 @@ int stm32mp1_clk_init(void) - * => deactivated CKPER only after switching clock - */ - if (ckper_disabled) { -- stm32mp1_pkcs_config(priv, CLK_CKPER_DISABLED); -+ stm32mp1_pkcs_config(CLK_CKPER_DISABLED); -+ } -+ -+ if (pll4_bootrom) { -+ uint32_t usbreg_value, usbreg_mask; -+ const struct stm32mp1_clk_sel *sel; -+ -+ sel = clk_sel_ref(_USBPHY_SEL); -+ usbreg_mask = (uint32_t)sel->msk << sel->src; -+ sel = clk_sel_ref(_USBO_SEL); -+ usbreg_mask |= (uint32_t)sel->msk << sel->src; -+ -+ usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) & -+ usbreg_mask; -+ usbreg_bootrom &= usbreg_mask; -+ if (usbreg_bootrom != usbreg_value) { -+ VERBOSE("forbidden new USB clk path\n"); -+ VERBOSE("vs bootrom on USB boot\n"); -+ return -FDT_ERR_BADVALUE; -+ } - } - } - - /* Switch OFF HSI if not found in device-tree */ -- if (priv->osc[_HSI] == 0U) { -- stm32mp1_hsi_set(rcc, 0); -+ if (stm32mp1_osc[_HSI] == 0U) { -+ stm32mp1_hsi_set(false); - } -- stm32mp1_stgen_config(priv); -+ stm32mp1_stgen_config(); - - /* Software Self-Refresh mode (SSR) during DDR initilialization */ -- mmio_clrsetbits_32(priv->base + RCC_DDRITFCR, -+ mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, - RCC_DDRITFCR_DDRCKMOD_MASK, - RCC_DDRITFCR_DDRCKMOD_SSR << - RCC_DDRITFCR_DDRCKMOD_SHIFT); -@@ -1565,48 +2129,711 @@ int stm32mp1_clk_init(void) - } - - static void stm32mp1_osc_clk_init(const char *name, -- struct stm32mp1_clk_priv *priv, - enum stm32mp_osc_id index) - { - uint32_t frequency; - -- priv->osc[index] = 0; -+ if (fdt_osc_read_freq(name, &frequency) == 0) { -+ stm32mp1_osc[index] = frequency; -+ } -+} -+ -+#if defined(IMAGE_BL32) +/* + * 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; @@ -6482,7 +6053,8 @@ index f0bf363..b304315 100644 + 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; ++ ++ int trim = get_signed_value((uint8_t)utrim); + + if (trim + (int)stm32mp1_clk_cal_hsi.cal_ref < 0) { + return 0; @@ -6497,9 +6069,7 @@ index f0bf363..b304315 100644 + stm32mp1_clk_cal_csi.trim_max + 1; + uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) & + RCC_CSICFGR_CSITRIM_MASK; - -- if (fdt_osc_read_freq(name, &frequency) != 0) { -- ERROR("%s frequency request failed\n", name); ++ + mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_CSICFGR, + RCC_CSICFGR_CSITRIM_MASK, trim); +} @@ -6570,41 +6140,78 @@ index f0bf363..b304315 100644 + return new_cal; +} + -+static void stm32mp1_rcc_calibration(struct stm32mp1_clk_cal *clk_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) / 100); ++ ((clk_cal->ref_freq * clk_cal->freq_margin) / 1000); + 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(); ++ ((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; + -+ 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 ((freq >= min) && (freq <= max)) { ++ return; + } + -+ if (nb_retries == 0U) { -+ ERROR("Calibration Failed\n"); - panic(); -- } else { -- priv->osc[index] = frequency; - } - } - ++ trim = clk_cal->get_trim(); ++ start = timeout_init_us(CALIB_TIMEOUT); ++ 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)) { ++ 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) +{ @@ -6681,17 +6288,17 @@ index f0bf363..b304315 100644 + clk_cal->boundary_max = boundary; +} + -+bool stm32mp1_rcc_get_wakeup(void) ++bool stm32mp1_calib_get_wakeup(void) +{ + return rcc_wakeup; +} + -+void stm32mp1_rcc_set_wakeup(bool state) ++void stm32mp1_calib_set_wakeup(bool state) +{ + rcc_wakeup = state; +} + -+void stm32mp1_rcc_it_handler(uint32_t id) ++void stm32mp1_calib_it_handler(uint32_t id) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + @@ -6699,11 +6306,11 @@ index f0bf363..b304315 100644 + 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); ++ stm32mp1_calib_set_wakeup(true); + return; + + case STM32MP1_IRQ_MCU_SEV: -+ stm32mp1_rcc_set_wakeup(false); ++ stm32mp1_calib_set_wakeup(false); + if ((mmio_read_32(EXTI_BASE + EXTI_RPR3) & + EXTI_RPR3_RPIF65) != 0U) { + mmio_setbits_32(EXTI_BASE + EXTI_RPR3, @@ -6724,35 +6331,35 @@ index f0bf363..b304315 100644 + } + + if (stm32mp1_clk_cal_hsi.ref_freq != 0U) { -+ stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi); ++ rcc_calibration(&stm32mp1_clk_cal_hsi); + } + + if (stm32mp1_clk_cal_csi.ref_freq != 0U) { -+ stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi); ++ rcc_calibration(&stm32mp1_clk_cal_csi); + } + + if (timer_val != 0U) { -+ write_cntptval(timer_val); ++ write_cntp_tval(timer_val); + } +} + -+int stm32mp1_rcc_start_hsi_cal(void) ++int stm32mp1_calib_start_hsi_cal(void) +{ + if (stm32mp1_clk_cal_hsi.ref_freq == 0U) { + return -ENOENT; + } + -+ stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi); ++ rcc_calibration(&stm32mp1_clk_cal_hsi); + return 0; +} + -+int stm32mp1_rcc_start_csi_cal(void) ++int stm32mp1_calib_start_csi_cal(void) +{ + if (stm32mp1_clk_cal_csi.ref_freq == 0U) { + return -ENOENT; + } + -+ stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi); ++ rcc_calibration(&stm32mp1_clk_cal_csi); + return 0; +} + @@ -6765,7 +6372,9 @@ index f0bf363..b304315 100644 + } + + stm32_timer_freq_func(&stm32mp1_clk_cal_hsi.get_freq, HSI_CAL); -+ assert(stm32mp1_clk_cal_hsi.get_freq); ++ if (stm32mp1_clk_cal_hsi.get_freq == NULL) { ++ return; ++ } + + stm32mp1_clk_cal_hsi.ref_freq = stm32mp_clk_get_rate(CK_HSI); + @@ -6778,7 +6387,7 @@ index f0bf363..b304315 100644 + + stm32mp1_clk_cal_hsi.set_trim(stm32mp1_clk_cal_hsi.cal_ref); + -+ stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi); ++ rcc_calibration(&stm32mp1_clk_cal_hsi); +} + +static void init_csi_cal(void) @@ -6790,7 +6399,9 @@ index f0bf363..b304315 100644 + } + + stm32_timer_freq_func(&stm32mp1_clk_cal_csi.get_freq, CSI_CAL); -+ assert(stm32mp1_clk_cal_csi.get_freq); ++ if (stm32mp1_clk_cal_csi.get_freq == NULL) { ++ return; ++ } + + stm32mp1_clk_cal_csi.ref_freq = stm32mp_clk_get_rate(CK_CSI); + @@ -6803,10 +6414,10 @@ index f0bf363..b304315 100644 + + stm32mp1_clk_cal_csi.set_trim(stm32mp1_clk_cal_csi.cal_ref); + -+ stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi); ++ rcc_calibration(&stm32mp1_clk_cal_csi); +} + -+void stm32mp1_cal_init(void) ++void stm32mp1_calib_init(void) +{ + init_hsi_cal(); + init_csi_cal(); @@ -6816,41 +6427,1950 @@ index f0bf363..b304315 100644 + + if (timer_val != 0U) { + /* Load & enable timer */ -+ write_cntptval(timer_val); -+ write_cntpctl(BIT(0)); ++ 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 0cc87cc71..5efe343b8 100644 +--- a/drivers/st/clk/stm32mp1_clk.c ++++ b/drivers/st/clk/stm32mp1_clk.c +@@ -1,11 +1,12 @@ + /* +- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + + #include + #include ++#include + #include + #include + +@@ -17,7 +18,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -48,6 +49,19 @@ const char *stm32mp_osc_node_label[NB_OSC] = { + [_I2S_CKIN] = "i2s_ckin", + }; + ++/* PLL settings computation related definitions */ ++#define POST_DIVM_MIN 8000000 ++#define POST_DIVM_MAX 16000000 ++#define DIVM_MIN 0 ++#define DIVM_MAX 63 ++#define DIVN_MIN 24 ++#define DIVN_MAX 99 ++#define DIVP_MIN 0 ++#define DIVP_MAX 127 ++#define FRAC_MAX 8192 ++#define VCO_MIN 800000000 ++#define VCO_MAX 1600000000 ++ + enum stm32mp1_parent_id { + /* Oscillators are defined in enum stm32mp_osc_id */ + +@@ -105,10 +119,62 @@ enum stm32mp1_parent_sel { + _MCUS_SEL, + _USBPHY_SEL, + _USBO_SEL, ++ _RTC_SEL, ++ _MPU_SEL, ++ _PER_SEL, + _PARENT_SEL_NB, + _UNKNOWN_SEL = 0xff, + }; + ++/* State the parent clock ID straight related to a clock */ ++static const uint8_t parent_id_clock_id[_PARENT_NB] = { ++ [_HSE] = CK_HSE, ++ [_HSI] = CK_HSI, ++ [_CSI] = CK_CSI, ++ [_LSE] = CK_LSE, ++ [_LSI] = CK_LSI, ++ [_I2S_CKIN] = _UNKNOWN_ID, ++ [_USB_PHY_48] = _UNKNOWN_ID, ++ [_HSI_KER] = CK_HSI, ++ [_HSE_KER] = CK_HSE, ++ [_HSE_KER_DIV2] = CK_HSE_DIV2, ++ [_CSI_KER] = CK_CSI, ++ [_PLL1_P] = PLL1_P, ++ [_PLL1_Q] = PLL1_Q, ++ [_PLL1_R] = PLL1_R, ++ [_PLL2_P] = PLL2_P, ++ [_PLL2_Q] = PLL2_Q, ++ [_PLL2_R] = PLL2_R, ++ [_PLL3_P] = PLL3_P, ++ [_PLL3_Q] = PLL3_Q, ++ [_PLL3_R] = PLL3_R, ++ [_PLL4_P] = PLL4_P, ++ [_PLL4_Q] = PLL4_Q, ++ [_PLL4_R] = PLL4_R, ++ [_ACLK] = CK_AXI, ++ [_PCLK1] = CK_AXI, ++ [_PCLK2] = CK_AXI, ++ [_PCLK3] = CK_AXI, ++ [_PCLK4] = CK_AXI, ++ [_PCLK5] = CK_AXI, ++ [_CK_PER] = CK_PER, ++ [_CK_MPU] = CK_MPU, ++ [_CK_MCU] = CK_MCU, ++}; ++ ++static unsigned int clock_id2parent_id(unsigned long id) ++{ ++ unsigned int n = 0; ++ ++ for (n = 0; n < ARRAY_SIZE(parent_id_clock_id); n++) { ++ if (parent_id_clock_id[n] == id) { ++ return n; ++ } ++ } ++ ++ return _UNKNOWN_ID; ++} ++ + enum stm32mp1_pll_id { + _PLL1, + _PLL2, +@@ -186,6 +252,7 @@ struct stm32mp1_clk_gate { + uint8_t bit; + uint8_t index; + uint8_t set_clr; ++ uint8_t secure; + uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ + uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ + }; +@@ -210,46 +277,59 @@ struct stm32mp1_clk_pll { + enum stm32mp_osc_id refclk[REFCLK_SIZE]; + }; + ++/* Compact structure of 32bit cells, copied raw when suspending */ ++struct stm32mp1_pll_settings { ++ uint32_t valid_id; ++ uint32_t freq[PLAT_MAX_OPP_NB]; ++ uint32_t volt[PLAT_MAX_OPP_NB]; ++ uint32_t cfg[PLAT_MAX_OPP_NB][PLAT_MAX_PLLCFG_NB]; ++ uint32_t frac[PLAT_MAX_OPP_NB]; ++}; ++ + /* Clocks with selectable source and non set/clr register access */ +-#define _CLK_SELEC(off, b, idx, s) \ ++#define _CLK_SELEC(sec, off, b, idx, s) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 0, \ ++ .secure = (sec), \ + .sel = (s), \ + .fixed = _UNKNOWN_ID, \ + } + + /* Clocks with fixed source and non set/clr register access */ +-#define _CLK_FIXED(off, b, idx, f) \ ++#define _CLK_FIXED(sec, off, b, idx, f) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 0, \ ++ .secure = (sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (f), \ + } + + /* Clocks with selectable source and set/clr register access */ +-#define _CLK_SC_SELEC(off, b, idx, s) \ ++#define _CLK_SC_SELEC(sec, off, b, idx, s) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 1, \ ++ .secure = (sec), \ + .sel = (s), \ + .fixed = _UNKNOWN_ID, \ + } + + /* Clocks with fixed source and set/clr register access */ +-#define _CLK_SC_FIXED(off, b, idx, f) \ ++#define _CLK_SC_FIXED(sec, off, b, idx, f) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 1, \ ++ .secure = (sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (f), \ + } +@@ -258,7 +338,8 @@ struct stm32mp1_clk_pll { + [_ ## _label ## _SEL] = { \ + .offset = _rcc_selr, \ + .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ +- .msk = _rcc_selr ## _ ## _label ## SRC_MASK, \ ++ .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ ++ (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ + .parent = (_parents), \ + .nb_parent = ARRAY_SIZE(_parents) \ + } +@@ -280,95 +361,109 @@ struct stm32mp1_clk_pll { + .refclk[3] = (p4), \ + } + +-static const uint8_t stm32mp1_clks[][2] = { +- { CK_PER, _CK_PER }, +- { CK_MPU, _CK_MPU }, +- { CK_AXI, _ACLK }, +- { CK_MCU, _CK_MCU }, +- { CK_HSE, _HSE }, +- { CK_CSI, _CSI }, +- { CK_LSI, _LSI }, +- { CK_LSE, _LSE }, +- { CK_HSI, _HSI }, +- { CK_HSE_DIV2, _HSE_KER_DIV2 }, +-}; +- + #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) + ++#define SEC 1 ++#define N_S 0 ++ + static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { +- _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), +- _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), +- _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), +- _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), +- _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), +- _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), +- _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), +- _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), +- _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), +- _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), +- _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), +- +- _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), +- _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), +- +- _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, 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), +- +- _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, _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), +- _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), +- _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), +- _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, 8, USBO_K, _USBO_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), +- +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), +- +- _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), +- _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), +- _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), +- _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, 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), +- _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), +- _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), +- +- _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), ++ _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), ++ ++#if defined(IMAGE_BL32) ++ _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), ++#endif ++#if defined(IMAGE_BL2) ++ _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), +#endif + - static void stm32mp1_osc_init(void) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - enum stm32mp_osc_id i; ++#if defined(IMAGE_BL32) ++ _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), ++#endif ++#if defined(IMAGE_BL2) ++ _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), ++#endif ++ ++ _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), ++ ++#if defined(IMAGE_BL32) ++ _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 0, LTDC_PX, _UNKNOWN_SEL), ++#endif ++ _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), ++ ++ _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), ++ _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), ++ _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), ++ _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), ++ _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), ++ _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), ++ ++ _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), ++ ++#if defined(IMAGE_BL32) ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 0, DMA1, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 1, DMA2, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), ++#endif ++ ++#if defined(IMAGE_BL2) ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), ++#endif ++ ++ _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), ++ _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), ++ _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), ++ _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), ++ ++#if defined(IMAGE_BL32) ++ _CLK_SC_FIXED(SEC, RCC_MP_TZAHB6ENSETR, 0, MDMA, _ACLK), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 5, GPU, _UNKNOWN_SEL), ++ _CLK_SC_FIXED(N_S, RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK), ++#endif ++#if defined(IMAGE_BL2) ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), ++#endif ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), ++#if defined(IMAGE_BL32) ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), ++#endif ++ ++ _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), + }; - for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { -- stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], priv, i); -+ stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); + static const uint8_t i2c12_parents[] = { +@@ -423,12 +518,12 @@ static const uint8_t fmc_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER + }; + +-static const uint8_t ass_parents[] = { +- _HSI, _HSE, _PLL2 ++static const uint8_t axiss_parents[] = { ++ _HSI, _HSE, _PLL2_P + }; + +-static const uint8_t mss_parents[] = { +- _HSI, _HSE, _CSI, _PLL3 ++static const uint8_t mcuss_parents[] = { ++ _HSI, _HSE, _CSI, _PLL3_P + }; + + static const uint8_t usbphy_parents[] = { +@@ -439,6 +534,18 @@ static const uint8_t usbo_parents[] = { + _PLL4_R, _USB_PHY_48 + }; + ++static const uint8_t rtc_parents[] = { ++ _UNKNOWN_ID, _LSE, _LSI, _HSE ++}; ++ ++static const uint8_t mpu_parents[] = { ++ _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ ++}; ++ ++static const uint8_t per_parents[] = { ++ _HSI, _HSE, _CSI, ++}; ++ + static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), + _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), +@@ -447,6 +554,9 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _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(RTC, RCC_BDCR, rtc_parents), ++ _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), ++ _CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_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), +@@ -455,14 +565,13 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _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(AXIS, RCC_ASSCKSELR, axiss_parents), ++ _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), + _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), + _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), + }; + + /* Define characteristic of PLL according type */ +-#define DIVN_MIN 24 + static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, +@@ -520,17 +629,90 @@ static const uint8_t stm32mp1_axi_div[8] = { + 1, 2, 3, 4, 4, 4, 4, 4 + }; + ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { ++ [_HSI] = "HSI", ++ [_HSE] = "HSE", ++ [_CSI] = "CSI", ++ [_LSI] = "LSI", ++ [_LSE] = "LSE", ++ [_I2S_CKIN] = "I2S_CKIN", ++ [_HSI_KER] = "HSI_KER", ++ [_HSE_KER] = "HSE_KER", ++ [_HSE_KER_DIV2] = "HSE_KER_DIV2", ++ [_CSI_KER] = "CSI_KER", ++ [_PLL1_P] = "PLL1_P", ++ [_PLL1_Q] = "PLL1_Q", ++ [_PLL1_R] = "PLL1_R", ++ [_PLL2_P] = "PLL2_P", ++ [_PLL2_Q] = "PLL2_Q", ++ [_PLL2_R] = "PLL2_R", ++ [_PLL3_P] = "PLL3_P", ++ [_PLL3_Q] = "PLL3_Q", ++ [_PLL3_R] = "PLL3_R", ++ [_PLL4_P] = "PLL4_P", ++ [_PLL4_Q] = "PLL4_Q", ++ [_PLL4_R] = "PLL4_R", ++ [_ACLK] = "ACLK", ++ [_PCLK1] = "PCLK1", ++ [_PCLK2] = "PCLK2", ++ [_PCLK3] = "PCLK3", ++ [_PCLK4] = "PCLK4", ++ [_PCLK5] = "PCLK5", ++ [_HCLK6] = "KCLK6", ++ [_HCLK2] = "HCLK2", ++ [_CK_PER] = "CK_PER", ++ [_CK_MPU] = "CK_MPU", ++ [_CK_MCU] = "CK_MCU", ++ [_USB_PHY_48] = "USB_PHY_48", ++}; ++ ++static const char * ++const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = { ++ [_I2C12_SEL] = "I2C12", ++ [_I2C35_SEL] = "I2C35", ++ [_STGEN_SEL] = "STGEN", ++ [_I2C46_SEL] = "I2C46", ++ [_SPI6_SEL] = "SPI6", ++ [_UART1_SEL] = "USART1", ++ [_RNG1_SEL] = "RNG1", ++ [_UART6_SEL] = "UART6", ++ [_UART24_SEL] = "UART24", ++ [_UART35_SEL] = "UART35", ++ [_UART78_SEL] = "UART78", ++ [_SDMMC12_SEL] = "SDMMC12", ++ [_SDMMC3_SEL] = "SDMMC3", ++ [_QSPI_SEL] = "QSPI", ++ [_FMC_SEL] = "FMC", ++ [_AXIS_SEL] = "AXISS", ++ [_MCUS_SEL] = "MCUSS", ++ [_USBPHY_SEL] = "USBPHY", ++ [_USBO_SEL] = "USBO", ++}; ++#endif ++ + /* RCC clock device driver private */ + static unsigned long stm32mp1_osc[NB_OSC]; + static struct spinlock reg_lock; + static unsigned int gate_refcounts[NB_GATES]; + static struct spinlock refcount_lock; ++static struct stm32mp1_pll_settings pll1_settings; ++static uint32_t current_opp_khz; ++static uint32_t pll3cr; ++static uint32_t pll4cr; ++static uint32_t mssckselr; ++static uint32_t mcudivr; + + static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) + { + return &stm32mp1_clk_gate[idx]; + } + ++static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) ++{ ++ return gate->secure == N_S; ++} ++ + static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) + { + return &stm32mp1_clk_sel[idx]; +@@ -559,15 +741,17 @@ static void stm32mp1_clk_unlock(struct spinlock *lock) + bool stm32mp1_rcc_is_secure(void) + { + uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t mask = RCC_TZCR_TZEN; + +- return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0; ++ return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; + } + + bool stm32mp1_rcc_is_mckprot(void) + { + uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; + +- return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0; ++ return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; + } + + void stm32mp1_clk_rcc_regs_lock(void) +@@ -580,6 +764,28 @@ void stm32mp1_clk_rcc_regs_unlock(void) + stm32mp1_clk_unlock(®_lock); + } + ++static unsigned int get_id_from_rcc_bit(unsigned int offset, unsigned int bit) ++{ ++ unsigned int idx; ++ ++ for (idx = 0U; idx < NB_GATES; idx++) { ++ const struct stm32mp1_clk_gate *gate = gate_ref(idx); ++ ++ if ((offset == gate->offset) && (bit == gate->bit)) { ++ return gate->index; ++ } ++ ++ if ((gate->set_clr != 0U) && ++ (offset == (gate->offset + RCC_MP_ENCLRR_OFFSET)) && ++ (bit == gate->bit)) { ++ return gate->index; ++ } ++ } ++ ++ /* Currently only supported gated clocks */ ++ return ~0U; ++} ++ + static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) + { + if (idx >= NB_OSC) { +@@ -617,17 +823,16 @@ static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) + static int stm32mp1_clk_get_parent(unsigned long id) + { + const struct stm32mp1_clk_sel *sel; +- uint32_t j, p_sel; ++ uint32_t p_sel; + int i; + enum stm32mp1_parent_id p; + enum stm32mp1_parent_sel s; + uintptr_t rcc_base = stm32mp_rcc_base(); + +- for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) { +- if (stm32mp1_clks[j][0] == id) { +- return (int)stm32mp1_clks[j][1]; +- } +- } ++ /* Few non gateable clock have a static parent ID, find them */ ++ i = (int)clock_id2parent_id(id); ++ if (i != _UNKNOWN_ID) ++ return i; + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { +@@ -648,8 +853,15 @@ static int stm32mp1_clk_get_parent(unsigned long id) + } + + sel = clk_sel_ref(s); +- p_sel = (mmio_read_32(rcc_base + sel->offset) & sel->msk) >> sel->src; ++ p_sel = (mmio_read_32(rcc_base + sel->offset) & ++ (sel->msk << sel->src)) >> 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", ++ __func__, ++ stm32mp1_clk_parent_name[sel->parent[p_sel]], ++ stm32mp1_clk_parent_sel_name[s], id); ++#endif + return (int)sel->parent[p_sel]; + } + +@@ -750,9 +962,7 @@ static unsigned long get_clock_rate(int p) + + reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); + clkdiv = reg & RCC_MPUDIV_MASK; +- if (clkdiv != 0U) { +- clock /= stm32mp1_mpu_div[clkdiv]; +- } ++ clock >>= stm32mp1_mpu_div[clkdiv]; + break; + default: + break; +@@ -930,27 +1140,29 @@ static void __clk_enable(struct stm32mp1_clk_gate const *gate) + { + uintptr_t rcc_base = stm32mp_rcc_base(); + ++ VERBOSE("Enable clock %d\n", gate->index); ++ + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); + } else { +- mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); ++ stm32mp_mmio_setbits_32_shregs(rcc_base + gate->offset, ++ BIT(gate->bit)); + } +- +- VERBOSE("Clock %d has been enabled", gate->index); + } + + static void __clk_disable(struct stm32mp1_clk_gate const *gate) + { + uintptr_t rcc_base = stm32mp_rcc_base(); + ++ VERBOSE("Disable clock %d\n", gate->index); ++ + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, + BIT(gate->bit)); + } else { +- mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); ++ stm32mp_mmio_clrbits_32_shregs(rcc_base + gate->offset, ++ BIT(gate->bit)); + } +- +- VERBOSE("Clock %d has been disabled", gate->index); + } + + static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) +@@ -960,57 +1172,119 @@ static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) + return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); + } + +-unsigned int stm32mp1_clk_get_refcount(unsigned long id) ++/* Oscillators and PLLs are not gated at runtime */ ++static bool clock_is_always_on(unsigned long id) + { +- int i = stm32mp1_clk_get_gated_id(id); +- +- if (i < 0) { +- panic(); ++ CASSERT((CK_HSE == 0) && ++ ((CK_HSE + 1) == CK_CSI) && ++ ((CK_HSE + 2) == CK_LSI) && ++ ((CK_HSE + 3) == CK_LSE) && ++ ((CK_HSE + 4) == CK_HSI) && ++ ((CK_HSE + 5) == CK_HSE_DIV2) && ++ ((PLL1_P + 1) == PLL1_Q) && ++ ((PLL1_P + 2) == PLL1_R) && ++ ((PLL1_P + 3) == PLL2_P) && ++ ((PLL1_P + 4) == PLL2_Q) && ++ ((PLL1_P + 5) == PLL2_R) && ++ ((PLL1_P + 6) == PLL3_P) && ++ ((PLL1_P + 7) == PLL3_Q) && ++ ((PLL1_P + 8) == PLL3_R), ++ assert_osc_and_pll_ids_are_contiguous); ++ ++ if ((id <= CK_HSE_DIV2) || ((id >= PLL1_P) && (id <= PLL3_R))) ++ return true; ++ ++ switch (id) { ++ case CK_AXI: ++ case CK_MPU: ++ case CK_MCU: ++ return true; ++ default: ++ return false; + } +- +- return gate_refcounts[i]; + } + +-void __stm32mp1_clk_enable(unsigned long id, bool secure) ++static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) + { + const struct stm32mp1_clk_gate *gate; +- int i = stm32mp1_clk_get_gated_id(id); +- unsigned int *refcnt; ++ int i; ++ ++ if (clock_is_always_on(id)) { ++ return; ++ } + ++ i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + ERROR("Clock %d can't be enabled\n", (uint32_t)id); + panic(); + } + + gate = gate_ref(i); +- refcnt = &gate_refcounts[i]; ++ ++ if (!with_refcnt) { ++ __clk_enable(gate); ++ return; ++ } ++ ++#if defined(IMAGE_BL32) ++ if (gate_is_non_secure(gate)) { ++ /* Enable non-secure clock w/o any refcounting */ ++ __clk_enable(gate); ++ return; ++ } ++#endif + + stm32mp1_clk_lock(&refcount_lock); + +- if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { ++ if (gate_refcounts[i] == 0) { + __clk_enable(gate); + } + ++ gate_refcounts[i]++; ++ if (gate_refcounts[i] == UINT_MAX) { ++ panic(); ++ } ++ + stm32mp1_clk_unlock(&refcount_lock); + } + +-void __stm32mp1_clk_disable(unsigned long id, bool secure) ++static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) + { + const struct stm32mp1_clk_gate *gate; +- int i = stm32mp1_clk_get_gated_id(id); +- unsigned int *refcnt; ++ int i; ++ ++ if (clock_is_always_on(id)) { ++ return; ++ } + ++ i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + ERROR("Clock %d can't be disabled\n", (uint32_t)id); + panic(); + } + + gate = gate_ref(i); +- refcnt = &gate_refcounts[i]; ++ ++ if (!with_refcnt) { ++ __clk_disable(gate); ++ return; ++ } ++ ++#if defined(IMAGE_BL32) ++ if (gate_is_non_secure(gate)) { ++ /* Don't disable non-secure clocks */ ++ return; ++ } ++#endif + + stm32mp1_clk_lock(&refcount_lock); + +- if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { ++ if (gate_refcounts[i] == 0) { ++ panic(); ++ } ++ gate_refcounts[i]--; ++ ++ if (gate_refcounts[i] == 0) { + __clk_disable(gate); + } + +@@ -1027,10 +1301,25 @@ void stm32mp_clk_disable(unsigned long id) + __stm32mp1_clk_disable(id, true); + } + ++void stm32mp1_clk_force_enable(unsigned long id) ++{ ++ __stm32mp1_clk_enable(id, false); ++} ++ ++void stm32mp1_clk_force_disable(unsigned long id) ++{ ++ __stm32mp1_clk_disable(id, false); ++} ++ + bool stm32mp_clk_is_enabled(unsigned long id) + { +- int i = stm32mp1_clk_get_gated_id(id); ++ int i; ++ ++ if (clock_is_always_on(id)) { ++ return true; ++ } + ++ i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + panic(); + } +@@ -1163,6 +1452,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) +@@ -1359,11 +1655,8 @@ static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) + return 0; + } + +-static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, +- uint32_t *pllcfg) ++static uint32_t stm32mp1_pll_compute_pllxcfgr2(uint32_t *pllcfg) + { +- const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); +- uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t value; + + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & +@@ -1372,21 +1665,33 @@ static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; +- mmio_write_32(rcc_base + pll->pllxcfgr2, value); ++ ++ return value; + } + +-static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, +- uint32_t *pllcfg, uint32_t fracv) ++static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, ++ uint32_t *pllcfg) + { + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t value; ++ ++ value = stm32mp1_pll_compute_pllxcfgr2(pllcfg); ++ ++ mmio_write_32(rcc_base + pll->pllxcfgr2, value); ++} ++ ++static int stm32mp1_pll_compute_pllxcfgr1(const struct stm32mp1_clk_pll *pll, ++ uint32_t *pllcfg, uint32_t *cfgr1) ++{ + uintptr_t rcc_base = stm32mp_rcc_base(); + enum stm32mp1_plltype type = pll->plltype; + unsigned long refclk; + uint32_t ifrge = 0; +- uint32_t src, value; ++ uint32_t src; + + src = mmio_read_32(rcc_base + pll->rckxselr) & +- RCC_SELR_REFCLK_SRC_MASK; ++ RCC_SELR_REFCLK_SRC_MASK; + + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / + (pllcfg[PLLCFG_M] + 1U); +@@ -1400,23 +1705,39 @@ static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, + ifrge = 1U; + } + +- value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & +- RCC_PLLNCFGR1_DIVN_MASK; +- value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & +- RCC_PLLNCFGR1_DIVM_MASK; +- value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & +- RCC_PLLNCFGR1_IFRGE_MASK; ++ *cfgr1 = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & ++ RCC_PLLNCFGR1_DIVN_MASK; ++ *cfgr1 |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & ++ RCC_PLLNCFGR1_DIVM_MASK; ++ *cfgr1 |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & ++ RCC_PLLNCFGR1_IFRGE_MASK; ++ ++ return 0; ++} ++ ++static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, ++ uint32_t *pllcfg, uint32_t fracv) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t value; ++ int ret; ++ ++ ret = stm32mp1_pll_compute_pllxcfgr1(pll, pllcfg, &value); ++ if (ret != 0) { ++ return ret; ++ } ++ + mmio_write_32(rcc_base + pll->pllxcfgr1, value); + + /* Fractional configuration */ + value = 0; + mmio_write_32(rcc_base + pll->pllxfracr, value); + ++ /* Frac must be enabled only once its configuration is loaded */ + value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; + mmio_write_32(rcc_base + pll->pllxfracr, value); +- +- value |= RCC_PLLNFRACR_FRACLE; +- mmio_write_32(rcc_base + pll->pllxfracr, value); ++ mmio_setbits_32(rcc_base + pll->pllxfracr, RCC_PLLNFRACR_FRACLE); + + stm32mp1_pll_config_output(pll_id, pllcfg); + +@@ -1523,53 +1844,68 @@ static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) + } + } + +-static void stm32mp1_stgen_config(void) ++unsigned long stm32mp_clk_timer_get_rate(unsigned long id) + { +- uintptr_t stgen; +- uint32_t cntfid0; +- unsigned long rate; +- unsigned long long counter; ++ unsigned long parent_rate; ++ uint32_t prescaler, timpre; ++ uintptr_t rcc_base = stm32mp_rcc_base(); + +- stgen = fdt_get_stgen_base(); +- cntfid0 = mmio_read_32(stgen + CNTFID_OFF); +- rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); ++ parent_rate = stm32mp_clk_get_rate(id); + +- if (cntfid0 == rate) { +- return; ++ if (id < TIM1_K) { ++ prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & ++ RCC_APBXDIV_MASK; ++ timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & ++ RCC_TIMGXPRER_TIMGXPRE; ++ } else { ++ prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & ++ RCC_APBXDIV_MASK; ++ timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & ++ RCC_TIMGXPRER_TIMGXPRE; + } + +- mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); +- counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF); +- counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32; +- counter = (counter * rate / cntfid0); +- +- mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter); +- mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32)); +- mmio_write_32(stgen + CNTFID_OFF, rate); +- mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); +- +- write_cntfrq((u_register_t)rate); ++ if (!prescaler) { ++ return parent_rate; ++ } + +- /* Need to update timer with new frequency */ +- generic_delay_timer_init(); ++ return parent_rate * (timpre + 1) * 2; + } + +-void stm32mp1_stgen_increment(unsigned long long offset_in_ms) ++/******************************************************************************* ++ * This function determines the number of needed RTC calendar read operations ++ * to get consistent values (1 or 2 depending on clock frequencies). ++ * If APB1 frequency is lower than 7 times the RTC one, the software has to ++ * read the calendar time and date registers twice. ++ * Returns true if read twice is needed, false else. ++ ******************************************************************************/ ++bool stm32mp1_rtc_get_read_twice(void) + { +- uintptr_t stgen; +- unsigned long long cnt; +- +- stgen = fdt_get_stgen_base(); ++ unsigned long apb1_freq; ++ uint32_t rtc_freq; ++ uint32_t apb1_div; ++ uintptr_t rcc_base = stm32mp_rcc_base(); + +- cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) | +- mmio_read_32(stgen + CNTCVL_OFF); ++ switch ((mmio_read_32(rcc_base + RCC_BDCR) & ++ RCC_BDCR_RTCSRC_MASK) >> RCC_BDCR_RTCSRC_SHIFT) { ++ case 1: ++ rtc_freq = stm32mp_clk_get_rate(CK_LSE); ++ break; ++ case 2: ++ rtc_freq = stm32mp_clk_get_rate(CK_LSI); ++ break; ++ case 3: ++ rtc_freq = stm32mp_clk_get_rate(CK_HSE); ++ rtc_freq /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & ++ RCC_DIVR_DIV_MASK) + 1U; ++ break; ++ default: ++ panic(); ++ } + +- cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U; ++ apb1_div = mmio_read_32(rcc_base + RCC_APB1DIVR) & RCC_APBXDIV_MASK; ++ apb1_freq = stm32mp_clk_get_rate(CK_MCU) >> apb1_div; + +- mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); +- mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt); +- mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(cnt >> 32)); +- mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); ++ return apb1_freq < (rtc_freq * 7U); + } + + static void stm32mp1_pkcs_config(uint32_t pkcs) +@@ -1586,96 +1922,673 @@ static void stm32mp1_pkcs_config(uint32_t pkcs) + mmio_clrsetbits_32(address, mask, value); + } + +-int stm32mp1_clk_init(void) ++static bool clk_pll1_settings_are_valid(void) + { +- uintptr_t rcc_base = stm32mp_rcc_base(); +- unsigned int clksrc[CLKSRC_NB]; +- unsigned int clkdiv[CLKDIV_NB]; +- unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; +- int plloff[_PLL_NB]; +- int ret, len; +- enum stm32mp1_pll_id i; +- bool lse_css = false; +- bool pll3_preserve = false; +- bool pll4_preserve = false; +- bool pll4_bootrom = false; +- const fdt32_t *pkcs_cell; ++ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID; ++} + +- /* Check status field to disable security */ +- if (!fdt_get_rcc_secure_status()) { +- mmio_write_32(rcc_base + RCC_TZCR, 0); ++int stm32mp1_round_opp_khz(uint32_t *freq_khz) ++{ ++ unsigned int i; ++ uint32_t round_opp = 0U; ++ ++ if (!clk_pll1_settings_are_valid()) { ++ /* ++ * No OPP table in DT, or an error occurred during PLL1 ++ * settings computation, system can only work on current ++ * operating point, so return current CPU frequency. ++ */ ++ *freq_khz = current_opp_khz; ++ ++ return 0; + } + +- ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc, +- (uint32_t)CLKSRC_NB); +- if (ret < 0) { +- return -FDT_ERR_NOTFOUND; ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { ++ if ((pll1_settings.freq[i] <= *freq_khz) && ++ (pll1_settings.freq[i] > round_opp)) { ++ round_opp = pll1_settings.freq[i]; ++ } + } + +- ret = fdt_rcc_read_uint32_array("st,clkdiv", clkdiv, +- (uint32_t)CLKDIV_NB); +- if (ret < 0) { +- return -FDT_ERR_NOTFOUND; ++ *freq_khz = round_opp; ++ ++ return 0; ++} ++ ++/* ++ * Check if PLL1 can be configured on the fly. ++ * @result (-1) => config on the fly is not possible. ++ * (0) => config on the fly is possible. ++ * (+1) => same parameters, no need to reconfigure. ++ * Return value is 0 if no error. ++ */ ++static int stm32mp1_is_pll_config_on_the_fly(enum stm32mp1_pll_id pll_id, ++ uint32_t *pllcfg, uint32_t fracv, ++ int *result) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t fracr; ++ uint32_t value; ++ int ret; ++ ++ ret = stm32mp1_pll_compute_pllxcfgr1(pll, pllcfg, &value); ++ if (ret != 0) { ++ return ret; + } + +- for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { +- char name[12]; ++ if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { ++ /* Different DIVN/DIVM, can't config on the fly */ ++ *result = -1; ++ return 0; ++ } + +- snprintf(name, sizeof(name), "st,pll@%d", i); +- plloff[i] = fdt_rcc_subnode_offset(name); ++ *result = true; + +- if (!fdt_check_node(plloff[i])) { +- continue; +- } ++ fracr = fracv << RCC_PLLNFRACR_FRACV_SHIFT; ++ fracr |= RCC_PLLNFRACR_FRACLE; ++ value = stm32mp1_pll_compute_pllxcfgr2(pllcfg); + +- ret = fdt_read_uint32_array(plloff[i], "cfg", +- pllcfg[i], (int)PLLCFG_NB); +- if (ret < 0) { +- return -FDT_ERR_NOTFOUND; +- } ++ if ((mmio_read_32(rcc_base + pll->pllxfracr) == fracr) && ++ (mmio_read_32(rcc_base + pll->pllxcfgr2) == value)) { ++ /* Same parameters, no need to config */ ++ *result = 1; ++ } else { ++ *result = 0; + } + +- stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); +- stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); ++ return 0; ++} + +- /* +- * Switch ON oscillator found in device-tree. +- * Note: HSI already ON after BootROM stage. +- */ +- if (stm32mp1_osc[_LSI] != 0U) { +- stm32mp1_lsi_set(true); ++static int stm32mp1_get_mpu_div(uint32_t freq_khz) ++{ ++ unsigned long freq_pll1_p; ++ unsigned long div; ++ ++ freq_pll1_p = get_clock_rate(_PLL1_P) / 1000UL; ++ if ((freq_pll1_p % freq_khz) != 0U) { ++ return -1; + } +- if (stm32mp1_osc[_LSE] != 0U) { +- bool bypass, digbyp; +- uint32_t lsedrv; + +- bypass = fdt_osc_read_bool(_LSE, "st,bypass"); +- digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); +- lse_css = fdt_osc_read_bool(_LSE, "st,css"); +- lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", +- LSEDRV_MEDIUM_HIGH); +- stm32mp1_lse_enable(bypass, digbyp, lsedrv); ++ div = freq_pll1_p / freq_khz; ++ ++ switch (div) { ++ case 1UL: ++ case 2UL: ++ case 4UL: ++ case 8UL: ++ case 16UL: ++ return __builtin_ffs(div) - 1; ++ default: ++ return -1; + } +- if (stm32mp1_osc[_HSE] != 0U) { +- bool bypass, digbyp, css; ++} + +- bypass = fdt_osc_read_bool(_HSE, "st,bypass"); +- digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); +- css = fdt_osc_read_bool(_HSE, "st,css"); +- stm32mp1_hse_enable(bypass, digbyp, css); ++static int stm32mp1_pll1_config_from_opp_khz(uint32_t freq_khz) ++{ ++ unsigned int i; ++ int ret; ++ int div; ++ int config_on_the_fly = -1; ++ ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { ++ if (pll1_settings.freq[i] == freq_khz) { ++ break; ++ } + } +- /* +- * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) +- * => switch on CSI even if node is not present in device tree +- */ +- stm32mp1_csi_set(true); + +- /* Come back to HSI */ +- ret = stm32mp1_set_clksrc(CLK_MPU_HSI); +- if (ret != 0) { +- return ret; ++ if (i == PLAT_MAX_OPP_NB) { ++ return -ENXIO; + } +- ret = stm32mp1_set_clksrc(CLK_AXI_HSI); ++ ++ div = stm32mp1_get_mpu_div(freq_khz); ++ ++ switch (div) { ++ case -1: ++ break; ++ case 0: ++ return stm32mp1_set_clksrc(CLK_MPU_PLL1P); ++ default: ++ ret = stm32mp1_set_clkdiv(div, stm32mp_rcc_base() + ++ RCC_MPCKDIVR); ++ if (ret == 0) { ++ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P_DIV); ++ } ++ return ret; ++ } ++ ++ ret = stm32mp1_is_pll_config_on_the_fly(_PLL1, &pll1_settings.cfg[i][0], ++ pll1_settings.frac[i], ++ &config_on_the_fly); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (config_on_the_fly == 1) { ++ /* No need to reconfigure, setup already OK */ ++ return 0; ++ } ++ ++ if (config_on_the_fly == -1) { ++ /* Switch to HSI and stop PLL1 before reconfiguration */ ++ ret = stm32mp1_set_clksrc(CLK_MPU_HSI); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = stm32mp1_pll_stop(_PLL1); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ ret = stm32mp1_pll_config(_PLL1, &pll1_settings.cfg[i][0], ++ pll1_settings.frac[i]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (config_on_the_fly == -1) { ++ /* Start PLL1 and switch back to after reconfiguration */ ++ stm32mp1_pll_start(_PLL1); ++ ++ ret = stm32mp1_pll_output(_PLL1, ++ pll1_settings.cfg[i][PLLCFG_O]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int stm32mp1_set_opp_khz(uint32_t freq_khz) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t mpu_src; ++ ++ if (freq_khz == current_opp_khz) { ++ /* OPP already set, nothing to do */ ++ return 0; ++ } ++ ++ if (!clk_pll1_settings_are_valid()) { ++ /* ++ * No OPP table in DT or an error occurred during PLL1 ++ * settings computation, system can only work on current ++ * operating point so return error. ++ */ ++ return -EACCES; ++ } ++ ++ /* Check that PLL1 is MPU clock source */ ++ mpu_src = mmio_read_32(rcc_base + RCC_MPCKSELR) & RCC_SELR_SRC_MASK; ++ if ((mpu_src != RCC_MPCKSELR_PLL) && ++ (mpu_src != RCC_MPCKSELR_PLL_MPUDIV)) { ++ return -EPERM; ++ } ++ ++ if (stm32mp1_pll1_config_from_opp_khz(freq_khz) != 0) { ++ /* Restore original value */ ++ if (stm32mp1_pll1_config_from_opp_khz(current_opp_khz) != 0) { ++ ERROR("No CPU operating point can be set\n"); ++ panic(); ++ } ++ ++ return -EIO; ++ } ++ ++ current_opp_khz = freq_khz; ++ ++ return 0; ++} ++ ++static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg, ++ uint32_t *fracv, uint32_t *csg, ++ bool *csg_set) ++{ ++ int ret; ++ ++ ret = fdt_read_uint32_array(plloff, "cfg", pllcfg, (uint32_t)PLLCFG_NB); ++ if (ret < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ *fracv = fdt_read_uint32_default(plloff, "frac", 0); ++ ++ ret = fdt_read_uint32_array(plloff, "csg", csg, (uint32_t)PLLCSG_NB); ++ ++ *csg_set = (ret == 0); ++ ++ if (ret == -FDT_ERR_NOTFOUND) { ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++static int clk_compute_pll1_settings(unsigned long input_freq, ++ uint32_t freq_khz, ++ uint32_t *pllcfg, uint32_t *fracv) ++{ ++ unsigned long long output_freq = freq_khz * 1000U; ++ unsigned long long freq; ++ unsigned long long vco; ++ int divm; ++ int divn; ++ int divp; ++ int frac; ++ int i; ++ unsigned int diff; ++ unsigned int best_diff = UINT_MAX; ++ ++ /* Following parameters have always the same value */ ++ pllcfg[PLLCFG_Q] = 0; ++ pllcfg[PLLCFG_R] = 0; ++ pllcfg[PLLCFG_O] = PQR(1, 0, 0); ++ ++ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) { ++ unsigned long post_divm = input_freq / ++ (unsigned long)(divm + 1); ++ ++ if ((post_divm < POST_DIVM_MIN) || ++ (post_divm > POST_DIVM_MAX)) { ++ continue; ++ } ++ ++ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { ++ ++ freq = output_freq * (divm + 1) * (divp + 1); ++ ++ divn = (int)((freq / input_freq) - 1); ++ if ((divn < DIVN_MIN) || (divn > DIVN_MAX)) { ++ continue; ++ } ++ ++ frac = (int)(((freq * FRAC_MAX) / input_freq) - ++ ((divn + 1) * FRAC_MAX)); ++ ++ /* 2 loops to refine the fractional part */ ++ for (i = 2; i != 0; i--) { ++ if (frac > FRAC_MAX) { ++ break; ++ } ++ ++ vco = (post_divm * (divn + 1)) + ++ ((post_divm * (unsigned long long)frac) / ++ FRAC_MAX); ++ ++ if ((vco < (VCO_MIN / 2)) || ++ (vco > (VCO_MAX / 2))) { ++ frac++; ++ continue; ++ } ++ ++ freq = vco / (divp + 1); ++ if (output_freq < freq) { ++ diff = (unsigned int)(freq - ++ output_freq); ++ } else { ++ diff = (unsigned int)(output_freq - ++ freq); ++ } ++ ++ if (diff < best_diff) { ++ pllcfg[PLLCFG_M] = divm; ++ pllcfg[PLLCFG_N] = divn; ++ pllcfg[PLLCFG_P] = divp; ++ *fracv = frac; ++ ++ if (diff == 0) { ++ return 0; ++ } ++ ++ best_diff = diff; ++ } ++ ++ frac++; ++ } ++ } ++ } ++ ++ if (best_diff == UINT_MAX) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int clk_get_pll1_settings(uint32_t clksrc, uint32_t freq_khz, ++ uint32_t *pllcfg, uint32_t *fracv) ++{ ++ unsigned int i; ++ ++ assert(pllcfg != NULL); ++ assert(fracv != NULL); ++ ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { ++ if (pll1_settings.freq[i] == freq_khz) { ++ break; ++ } ++ } ++ ++ if (((i == PLAT_MAX_OPP_NB) && (pll1_settings.valid_id == 0U)) || ++ ((i < PLAT_MAX_OPP_NB) && ++ (pll1_settings.cfg[i][PLLCFG_O] == 0U))) { ++ unsigned long input_freq; ++ ++ /* ++ * Either PLL1 settings structure is completely empty, ++ * or these settings are not yet computed: do it. ++ */ ++ switch (clksrc) { ++ case CLK_PLL12_HSI: ++ input_freq = stm32mp_clk_get_rate(CK_HSI); ++ break; ++ case CLK_PLL12_HSE: ++ input_freq = stm32mp_clk_get_rate(CK_HSE); ++ break; ++ default: ++ panic(); ++ } ++ ++ return clk_compute_pll1_settings(input_freq, freq_khz, pllcfg, ++ fracv); ++ } ++ ++ if ((i < PLAT_MAX_OPP_NB) && ++ (pll1_settings.cfg[i][PLLCFG_O] != 0U)) { ++ /* ++ * Index is in range and PLL1 settings are computed: ++ * use content to answer to the request. ++ */ ++ memcpy(pllcfg, &pll1_settings.cfg[i][0], ++ sizeof(uint32_t) * PLAT_MAX_PLLCFG_NB); ++ *fracv = pll1_settings.frac[i]; ++ ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int stm32mp1_clk_get_maxfreq_opp(uint32_t *freq_khz, ++ uint32_t *voltage_mv) ++{ ++ unsigned int i; ++ uint32_t freq = 0U; ++ uint32_t voltage = 0U; ++ ++ assert(freq_khz != NULL); ++ assert(voltage_mv != NULL); ++ ++ if (!clk_pll1_settings_are_valid()) { ++ return -1; ++ } ++ ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { ++ if (pll1_settings.freq[i] > freq) { ++ freq = pll1_settings.freq[i]; ++ voltage = pll1_settings.volt[i]; ++ } ++ } ++ ++ if ((freq == 0U) || (voltage == 0U)) { ++ return -1; ++ } ++ ++ *freq_khz = freq; ++ *voltage_mv = voltage; ++ ++ return 0; ++} ++ ++static int clk_save_current_pll1_settings(uint32_t buck1_voltage) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); ++ uint32_t rcc_base = stm32mp_rcc_base(); ++ uint32_t freq; ++ unsigned int i; ++ ++ freq = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000L); ++ ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { ++ if (pll1_settings.freq[i] == freq) { ++ break; ++ } ++ } ++ ++ if ((i == PLAT_MAX_OPP_NB) || ++ ((pll1_settings.volt[i] != buck1_voltage) && ++ (buck1_voltage != 0U))) { ++ return -1; ++ } ++ ++ pll1_settings.cfg[i][PLLCFG_M] = ++ (mmio_read_32(rcc_base + pll->pllxcfgr1) & ++ RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_N] = ++ (mmio_read_32(rcc_base + pll->pllxcfgr1) & ++ RCC_PLLNCFGR1_DIVN_MASK) >> RCC_PLLNCFGR1_DIVN_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_P] = ++ (mmio_read_32(rcc_base + pll->pllxcfgr2) & ++ RCC_PLLNCFGR2_DIVP_MASK) >> RCC_PLLNCFGR2_DIVP_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_Q] = ++ (mmio_read_32(rcc_base + pll->pllxcfgr2) & ++ RCC_PLLNCFGR2_DIVQ_MASK) >> RCC_PLLNCFGR2_DIVQ_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_R] = ++ (mmio_read_32(rcc_base + pll->pllxcfgr2) & ++ RCC_PLLNCFGR2_DIVR_MASK) >> RCC_PLLNCFGR2_DIVR_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_O] = ++ mmio_read_32(rcc_base + pll->pllxcr) >> ++ RCC_PLLNCR_DIVEN_SHIFT; ++ ++ pll1_settings.frac[i] = ++ (mmio_read_32(rcc_base + pll->pllxfracr) & ++ RCC_PLLNFRACR_FRACV_MASK) >> RCC_PLLNFRACR_FRACV_SHIFT; ++ ++ return i; ++} ++ ++static uint32_t stm32mp1_clk_get_pll1_current_clksrc(void) ++{ ++ uint32_t value; ++ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); ++ uint32_t rcc_base = stm32mp_rcc_base(); ++ ++ value = mmio_read_32(rcc_base + pll->rckxselr); ++ ++ switch (value & RCC_SELR_REFCLK_SRC_MASK) { ++ case 0: ++ return CLK_PLL12_HSI; ++ case 1: ++ return CLK_PLL12_HSE; ++ default: ++ panic(); ++ } ++} ++ ++int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage) ++{ ++ int i; ++ int ret; ++ int index; ++ uint32_t count = PLAT_MAX_OPP_NB; ++ uint32_t clksrc; ++ ++ ret = dt_get_all_opp_freqvolt(&count, pll1_settings.freq, ++ pll1_settings.volt); ++ switch (ret) { ++ case 0: ++ break; ++ case -FDT_ERR_NOTFOUND: ++ VERBOSE("Cannot find OPP table in DT, use default settings.\n"); ++ return 0; ++ default: ++ ERROR("Inconsistent OPP settings found in DT, ignored.\n"); ++ return 0; ++ } ++ ++ index = clk_save_current_pll1_settings(buck1_voltage); ++ ++ clksrc = stm32mp1_clk_get_pll1_current_clksrc(); ++ ++ for (i = 0; i < (int)count; i++) { ++ if (i == index) { ++ continue; ++ } ++ ++ ret = clk_get_pll1_settings(clksrc, pll1_settings.freq[i], ++ &pll1_settings.cfg[i][0], ++ &pll1_settings.frac[i]); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ pll1_settings.valid_id = PLL1_SETTINGS_VALID_ID; ++ ++ return 0; ++} ++ ++void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data, size_t size) ++{ ++ if (size != sizeof(pll1_settings) || !clk_pll1_settings_are_valid()) { ++ panic(); ++ } ++ ++ memcpy(data, &pll1_settings, size); ++} ++ ++void stm32mp1_clk_lp_load_opp_pll1_settings(uint8_t *data, size_t size) ++{ ++ if (size != sizeof(pll1_settings)) { ++ panic(); ++ } ++ ++ memcpy(&pll1_settings, data, size); ++} ++ ++int stm32mp1_clk_init(uint32_t pll1_freq_khz) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t pllfracv[_PLL_NB]; ++ uint32_t pllcsg[_PLL_NB][PLLCSG_NB]; ++ unsigned int clksrc[CLKSRC_NB]; ++ unsigned int clkdiv[CLKDIV_NB]; ++ unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; ++ int plloff[_PLL_NB]; ++ int ret, len; ++ enum stm32mp1_pll_id i; ++ bool pllcsg_set[_PLL_NB]; ++ bool pllcfg_valid[_PLL_NB]; ++ bool lse_css = false; ++ bool pll3_preserve = false; ++ bool pll4_preserve = false; ++ bool pll4_bootrom = false; ++ const fdt32_t *pkcs_cell; ++ int stgen_p = stm32mp1_clk_get_parent((int)STGEN_K); ++ int usbphy_p = stm32mp1_clk_get_parent((int)USBPHY_K); ++ ++ /* Check status field to disable security */ ++ if (!fdt_get_rcc_secure_status()) { ++ mmio_write_32(rcc_base + RCC_TZCR, 0); ++ } ++ ++ ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc, ++ (uint32_t)CLKSRC_NB); ++ if (ret < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ ret = fdt_rcc_read_uint32_array("st,clkdiv", clkdiv, ++ (uint32_t)CLKDIV_NB); ++ if (ret < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { ++ char name[12]; ++ ++ snprintf(name, sizeof(name), "st,pll@%d", i); ++ plloff[i] = fdt_rcc_subnode_offset(name); ++ ++ pllcfg_valid[i] = fdt_check_node(plloff[i]); ++ if (pllcfg_valid[i]) { ++ ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i], ++ &pllfracv[i], ++ pllcsg[i], ++ &pllcsg_set[i]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ continue; ++ } ++ ++ if ((i == _PLL1) && (pll1_freq_khz != 0U)) { ++ ret = clk_get_pll1_settings(clksrc[CLKSRC_PLL12], ++ pll1_freq_khz, ++ pllcfg[i], &pllfracv[i]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ pllcfg_valid[i] = true; ++ } ++ } ++ ++ stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); ++ stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); ++ ++ /* ++ * Switch ON oscillator found in device-tree. ++ * Note: HSI already ON after BootROM stage. ++ */ ++ if (stm32mp1_osc[_LSI] != 0U) { ++ stm32mp1_lsi_set(true); ++ } ++ if (stm32mp1_osc[_LSE] != 0U) { ++ bool bypass, digbyp; ++ uint32_t lsedrv; ++ ++ bypass = fdt_osc_read_bool(_LSE, "st,bypass"); ++ digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); ++ lse_css = fdt_osc_read_bool(_LSE, "st,css"); ++ lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", ++ LSEDRV_MEDIUM_HIGH); ++ stm32mp1_lse_enable(bypass, digbyp, lsedrv); ++ } ++ if (stm32mp1_osc[_HSE] != 0U) { ++ bool bypass, digbyp, css; ++ ++ bypass = fdt_osc_read_bool(_HSE, "st,bypass"); ++ digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); ++ css = fdt_osc_read_bool(_HSE, "st,css"); ++ stm32mp1_hse_enable(bypass, digbyp, css); ++ } ++ /* ++ * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) ++ * => switch on CSI even if node is not present in device tree ++ */ ++ stm32mp1_csi_set(true); ++ ++ /* Come back to HSI */ ++ ret = stm32mp1_set_clksrc(CLK_MPU_HSI); ++ if (ret != 0) { ++ return ret; ++ } ++ ret = stm32mp1_set_clksrc(CLK_AXI_HSI); + if (ret != 0) { + return ret; + } +@@ -1695,6 +2608,12 @@ int stm32mp1_clk_init(void) + pllcfg[_PLL4], + plloff[_PLL4]); + } ++ /* Don't initialize PLL4, when used by BOOTROM */ ++ if ((get_boot_device() == BOOT_DEVICE_USB) && ++ ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { ++ pll4_bootrom = true; ++ pll4_preserve = true; ++ } + + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (((i == _PLL3) && pll3_preserve) || +@@ -1714,7 +2633,8 @@ int stm32mp1_clk_init(void) + if (ret != 0) { + return ret; + } +- stm32mp1_stgen_config(); ++ ++ stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); + } + + /* Select DIV */ +@@ -1776,15 +2696,12 @@ int stm32mp1_clk_init(void) + + /* Configure and start PLLs */ + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { +- uint32_t fracv; +- uint32_t csg[PLLCSG_NB]; +- + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { + continue; + } + +- if (!fdt_check_node(plloff[i])) { ++ if (!pllcfg_valid[i]) { + continue; + } + +@@ -1794,25 +2711,20 @@ int stm32mp1_clk_init(void) + continue; + } + +- fracv = fdt_read_uint32_default(plloff[i], "frac", 0); +- +- ret = stm32mp1_pll_config(i, pllcfg[i], fracv); ++ ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]); + if (ret != 0) { + return ret; + } +- ret = fdt_read_uint32_array(plloff[i], "csg", csg, +- (uint32_t)PLLCSG_NB); +- if (ret == 0) { +- stm32mp1_pll_csg(i, csg); +- } else if (ret != -FDT_ERR_NOTFOUND) { +- return ret; ++ ++ if (pllcsg_set[i]) { ++ stm32mp1_pll_csg(i, pllcsg[i]); + } + + stm32mp1_pll_start(i); + } + /* Wait and start PLLs ouptut when ready */ + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { +- if (!fdt_check_node(plloff[i])) { ++ if (!pllcfg_valid[i]) { + continue; + } + +@@ -1846,6 +2758,11 @@ int stm32mp1_clk_init(void) + if (pkcs_cell != NULL) { + bool ckper_disabled = false; + uint32_t j; ++ uint32_t usbreg_bootrom = 0U; ++ ++ if (pll4_bootrom) { ++ usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR); ++ } + + for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { + uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); +@@ -1866,13 +2783,33 @@ int stm32mp1_clk_init(void) + if (ckper_disabled) { + stm32mp1_pkcs_config(CLK_CKPER_DISABLED); + } ++ ++ if (pll4_bootrom) { ++ uint32_t usbreg_value, usbreg_mask; ++ const struct stm32mp1_clk_sel *sel; ++ ++ sel = clk_sel_ref(_USBPHY_SEL); ++ usbreg_mask = (uint32_t)sel->msk << sel->src; ++ sel = clk_sel_ref(_USBO_SEL); ++ usbreg_mask |= (uint32_t)sel->msk << sel->src; ++ ++ usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) & ++ usbreg_mask; ++ usbreg_bootrom &= usbreg_mask; ++ if (usbreg_bootrom != usbreg_value) { ++ VERBOSE("forbidden new USB clk path\n"); ++ VERBOSE("vs bootrom on USB boot\n"); ++ return -FDT_ERR_BADVALUE; ++ } ++ } + } + + /* Switch OFF HSI if not found in device-tree */ + if (stm32mp1_osc[_HSI] == 0U) { + stm32mp1_hsi_set(false); + } +- stm32mp1_stgen_config(); ++ ++ stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, +@@ -1902,18 +2839,634 @@ static void stm32mp1_osc_init(void) } } --int stm32mp1_clk_probe(void) +/* + * Lookup platform clock from enable bit location in RCC registers. + * Return a valid clock ID on success, return ~0 on error. + */ +unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit) - { -- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; ++{ + return get_id_from_rcc_bit(offset, bit); +} - -- priv->base = fdt_rcc_read_addr(); -- if (priv->base == 0U) { -- return -EINVAL; ++ ++#ifdef IMAGE_BL32 +/* + * Get the parent ID of the target parent clock, for tagging as secure + * shared clock dependencies. @@ -6865,7 +8385,7 @@ index f0bf363..b304315 100644 + case _ACLK: + case _PCLK4: + case _PCLK5: -+ s = _ASS_SEL; ++ s = _AXIS_SEL; + break; + case _PLL1_P: + case _PLL1_Q: @@ -6901,16 +8421,12 @@ index f0bf363..b304315 100644 + default: + /* Other parents have no parent */ + return -1; - } - -- priv->data = &stm32mp1_data; ++ } ++ + if (s != _UNKNOWN_SEL) { + const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); + uintptr_t rcc_base = stm32mp_rcc_base(); - -- if ((priv->data->gate == NULL) || (priv->data->sel == NULL) || -- (priv->data->pll == NULL)) { -- return -EINVAL; ++ + p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & + sel->msk; + @@ -6927,10 +8443,10 @@ index f0bf363..b304315 100644 + if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { + return (int)pll->refclk[p_sel]; + } - } - ++ } ++ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+ VERBOSE("No parent selected for %s", ++ VERBOSE("No parent selected for %s\n", + stm32mp1_clk_parent_name[parent_id]); +#endif + @@ -6942,66 +8458,40 @@ index f0bf363..b304315 100644 + int grandparent_id; + + switch (parent_id) { -+ /* Secure only the parents for these clocks */ ++ case _PLL3_P: ++ case _PLL3_Q: ++ case _PLL3_R: ++ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); ++ break; ++ ++ /* These clocks are always secure when RCC is secure */ + case _ACLK: + case _HCLK2: + case _HCLK6: + case _PCLK4: + case _PCLK5: -+ break; -+ /* PLLs */ + case _PLL1_P: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL1_P); -+ break; + case _PLL1_Q: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL1_Q); -+ break; + case _PLL1_R: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL1_R); -+ break; -+ + case _PLL2_P: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL2_P); -+ break; + case _PLL2_Q: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL2_Q); -+ break; + case _PLL2_R: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL2_R); -+ break; -+ -+ case _PLL3_P: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL3_P); -+ break; -+ case _PLL3_Q: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL3_Q); -+ break; -+ case _PLL3_R: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL3_R); -+ break; -+ -+ /* Source clocks */ + case _HSI: + case _HSI_KER: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_HSI); -+ break; + case _LSI: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_LSI); -+ break; + case _CSI: + case _CSI_KER: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_CSI); -+ break; + case _HSE: + case _HSE_KER: + case _HSE_KER_DIV2: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_HSE); -+ break; + case _LSE: -+ stm32mp1_register_secure_periph(STM32MP1_SHRES_LSE); + break; + + default: ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ VERBOSE("Cannot secure parent clock %s\n", ++ stm32mp1_clk_parent_name[parent_id]); ++#endif + panic(); + } + @@ -7021,14 +8511,12 @@ index f0bf363..b304315 100644 + + switch (clock_id) { + case PLL1: -+ parent_id = get_parent_id_parent(_PLL1_P); -+ break; + case PLL2: -+ parent_id = get_parent_id_parent(_PLL2_P); -+ break; ++ /* PLL1/PLL2 are always secure: nothing to do */ ++ return; + case PLL3: -+ parent_id = get_parent_id_parent(_PLL3_P); -+ break; ++ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); ++ return; + case PLL4: + ERROR("PLL4 cannot be secured\n"); + panic(); @@ -7040,31 +8528,397 @@ index f0bf363..b304315 100644 + } + + if (parent_id < 0) { -+ ERROR("No parent for clock %lu", clock_id); -+ panic(); ++ INFO("No parent for clock %lu\n", clock_id); ++ return; + } + + secure_parent_clocks(parent_id); +} ++#else ++void stm32mp1_register_clock_parents_secure(unsigned long clock_id) ++{ ++} ++#endif /* IMAGE_BL32 */ + -+/* Sync secure clock refcount after all drivers probe/inits, */ -+void stm32mp1_update_earlyboot_clocks_state(void) ++/* ++ * Sequence to save/restore the non-secure configuration. ++ * Restoring clocks and muxes need IPs to run on kernel clock ++ * hence on configuration is restored at resume, kernel clock ++ * should be disable: this mandates secure access. ++ * ++ * backup_mux*_cfg for the clock muxes. ++ * backup_clock_sc_cfg for the set/clear clock gating registers ++ * backup_clock_cfg for the regular full write registers ++ */ ++ ++struct backup_mux_cfg { ++ uint16_t offset; ++ uint8_t value; ++ uint8_t bit_len; ++}; ++ ++#define MUXCFG(_offset, _bit_len) \ ++ { .offset = (_offset), .bit_len = (_bit_len) } ++ ++static struct backup_mux_cfg backup_mux0_cfg[] = { ++ MUXCFG(RCC_SDMMC12CKSELR, 3), ++ MUXCFG(RCC_SPI2S23CKSELR, 3), ++ MUXCFG(RCC_SPI45CKSELR, 3), ++ MUXCFG(RCC_I2C12CKSELR, 3), ++ MUXCFG(RCC_I2C35CKSELR, 3), ++ MUXCFG(RCC_LPTIM23CKSELR, 3), ++ MUXCFG(RCC_LPTIM45CKSELR, 3), ++ MUXCFG(RCC_UART24CKSELR, 3), ++ MUXCFG(RCC_UART35CKSELR, 3), ++ MUXCFG(RCC_UART78CKSELR, 3), ++ MUXCFG(RCC_SAI1CKSELR, 3), ++ MUXCFG(RCC_ETHCKSELR, 2), ++ MUXCFG(RCC_I2C46CKSELR, 3), ++ MUXCFG(RCC_RNG2CKSELR, 2), ++ MUXCFG(RCC_SDMMC3CKSELR, 3), ++ MUXCFG(RCC_FMCCKSELR, 2), ++ MUXCFG(RCC_QSPICKSELR, 2), ++ MUXCFG(RCC_USBCKSELR, 2), ++ MUXCFG(RCC_SPDIFCKSELR, 2), ++ MUXCFG(RCC_SPI2S1CKSELR, 3), ++ MUXCFG(RCC_CECCKSELR, 2), ++ MUXCFG(RCC_LPTIM1CKSELR, 3), ++ MUXCFG(RCC_UART6CKSELR, 3), ++ MUXCFG(RCC_FDCANCKSELR, 2), ++ MUXCFG(RCC_SAI2CKSELR, 3), ++ MUXCFG(RCC_SAI3CKSELR, 3), ++ MUXCFG(RCC_SAI4CKSELR, 3), ++ MUXCFG(RCC_ADCCKSELR, 2), ++ MUXCFG(RCC_DSICKSELR, 1), ++ MUXCFG(RCC_CPERCKSELR, 2), ++ MUXCFG(RCC_RNG1CKSELR, 2), ++ MUXCFG(RCC_STGENCKSELR, 2), ++ MUXCFG(RCC_UART1CKSELR, 3), ++ MUXCFG(RCC_SPI6CKSELR, 3), ++}; ++ ++static struct backup_mux_cfg backup_mux4_cfg[] = { ++ MUXCFG(RCC_USBCKSELR, 1), ++}; ++ ++static void backup_mux_cfg(void) ++{ ++ uintptr_t base = stm32mp_rcc_base(); ++ struct backup_mux_cfg *cfg; ++ size_t i; ++ ++ cfg = backup_mux0_cfg; ++ for (i = 0U; i < ARRAY_SIZE(backup_mux0_cfg); i++) { ++ cfg[i].value = mmio_read_32(base + cfg[i].offset) & ++ GENMASK_32(cfg[i].bit_len - 1U, 0U); ++ } ++ ++ cfg = backup_mux4_cfg; ++ for (i = 0U; i < ARRAY_SIZE(backup_mux4_cfg); i++) { ++ cfg[i].value = mmio_read_32(base + cfg[i].offset) & ++ GENMASK_32(4U + cfg[i].bit_len - 1U, 4U); ++ } ++} ++ ++static void restore_mux_cfg(void) ++{ ++ uintptr_t base = stm32mp_rcc_base(); ++ struct backup_mux_cfg *cfg; ++ size_t i; ++ ++ cfg = backup_mux0_cfg; ++ for (i = 0U; i < ARRAY_SIZE(backup_mux0_cfg); i++) { ++ uint32_t mask = GENMASK_32(cfg[i].bit_len - 1U, 0U); ++ uint32_t value = cfg[i].value & mask; ++ ++ mmio_clrsetbits_32(base + cfg[i].offset, mask, value); ++ } ++ ++ cfg = backup_mux4_cfg; ++ for (i = 0U; i < ARRAY_SIZE(backup_mux4_cfg); i++) { ++ uint32_t mask = GENMASK_32(4U + cfg[i].bit_len - 1U, 4U); ++ uint32_t value = cfg[i].value & mask; ++ ++ mmio_clrsetbits_32(base + cfg[i].offset, mask, value); ++ } ++} ++ ++/* Structure is used for set/clear registers and for regular registers */ ++struct backup_clock_cfg { ++ uint32_t offset; ++ uint32_t value; ++}; ++ ++static struct backup_clock_cfg backup_clock_sc_cfg[] = { ++ { .offset = RCC_MP_APB1ENSETR }, ++ { .offset = RCC_MP_APB2ENSETR }, ++ { .offset = RCC_MP_APB3ENSETR }, ++ { .offset = RCC_MP_APB4ENSETR }, ++ { .offset = RCC_MP_APB5ENSETR }, ++ { .offset = RCC_MP_AHB2ENSETR }, ++ { .offset = RCC_MP_AHB3ENSETR }, ++ { .offset = RCC_MP_AHB4ENSETR }, ++ { .offset = RCC_MP_AHB5ENSETR }, ++ { .offset = RCC_MP_AHB6ENSETR }, ++ { .offset = RCC_MP_MLAHBENSETR }, ++}; ++ ++static struct backup_clock_cfg backup_clock_cfg[] = { ++ { .offset = RCC_MCO1CFGR }, ++ { .offset = RCC_MCO2CFGR }, ++ { .offset = RCC_PLL3CR }, ++ { .offset = RCC_PLL4CR }, ++ { .offset = RCC_PLL4CFGR2 }, ++ { .offset = RCC_MCUDIVR }, ++ { .offset = RCC_MSSCKSELR }, ++}; ++ ++static void backup_sc_cfg(void) ++{ ++ struct backup_clock_cfg *cfg = backup_clock_sc_cfg; ++ size_t count = ARRAY_SIZE(backup_clock_sc_cfg); ++ uintptr_t base = stm32mp_rcc_base(); ++ size_t i; ++ ++ for (i = 0U; i < count; i++) { ++ cfg[i].value = mmio_read_32(base + cfg[i].offset); ++ } ++} ++ ++static void restore_sc_cfg(void) ++{ ++ struct backup_clock_cfg *cfg = backup_clock_sc_cfg; ++ size_t count = ARRAY_SIZE(backup_clock_sc_cfg); ++ uintptr_t base = stm32mp_rcc_base(); ++ size_t i; ++ ++ for (i = 0U; i < count; i++) { ++ mmio_write_32(base + cfg[i].offset, cfg[i].value); ++ mmio_write_32(base + cfg[i].offset + RCC_MP_ENCLRR_OFFSET, ++ ~cfg[i].value); ++ } ++} ++ ++static void backup_regular_cfg(void) ++{ ++ struct backup_clock_cfg *cfg = backup_clock_cfg; ++ size_t count = ARRAY_SIZE(backup_clock_cfg); ++ uintptr_t base = stm32mp_rcc_base(); ++ size_t i; ++ ++ for (i = 0U; i < count; i++) { ++ cfg[i].value = mmio_read_32(base + cfg[i].offset); ++ } ++} ++ ++static void restore_regular_cfg(void) ++{ ++ struct backup_clock_cfg *cfg = backup_clock_cfg; ++ size_t count = ARRAY_SIZE(backup_clock_cfg); ++ uintptr_t base = stm32mp_rcc_base(); ++ size_t i; ++ ++ for (i = 0U; i < count; i++) { ++ mmio_write_32(base + cfg[i].offset, cfg[i].value); ++ } ++} ++ ++static void disable_kernel_clocks(void) ++{ ++ const uint32_t ker_mask = RCC_OCENR_HSIKERON | ++ RCC_OCENR_CSIKERON | ++ RCC_OCENR_HSEKERON; ++ ++ /* Disable all ck_xxx_ker clocks */ ++ mmio_write_32(stm32mp_rcc_base() + RCC_OCENCLRR, ker_mask); ++} ++ ++static void enable_kernel_clocks(void) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uint32_t reg; ++ const uint32_t ker_mask = RCC_OCENR_HSIKERON | ++ RCC_OCENR_CSIKERON | ++ RCC_OCENR_HSEKERON; ++ ++ /* Enable ck_xxx_ker clocks if ck_xxx was on */ ++ reg = mmio_read_32(rcc_base + RCC_OCENSETR) << 1U; ++ mmio_write_32(rcc_base + RCC_OCENSETR, reg & ker_mask); ++} ++ ++static void clear_rcc_reset_status(void) ++{ ++ /* Clear reset status fields */ ++ mmio_write_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR, 0U); ++} ++ ++void save_clock_pm_context(void) ++{ ++ size_t offset = 0U; ++ ++ stm32mp1_pm_save_clock_cfg(offset, ++ (uint8_t *)backup_mux0_cfg, ++ sizeof(backup_mux0_cfg)); ++ offset += sizeof(backup_mux0_cfg); ++ ++ stm32mp1_pm_save_clock_cfg(offset, ++ (uint8_t *)backup_mux4_cfg, ++ sizeof(backup_mux4_cfg)); ++ offset += sizeof(backup_mux4_cfg); ++ ++ stm32mp1_pm_save_clock_cfg(offset, ++ (uint8_t *)backup_clock_sc_cfg, ++ sizeof(backup_clock_sc_cfg)); ++ offset += sizeof(backup_clock_sc_cfg); ++ ++ stm32mp1_pm_save_clock_cfg(offset, ++ (uint8_t *)backup_clock_cfg, ++ sizeof(backup_clock_cfg)); ++ offset += sizeof(backup_clock_cfg); ++ ++ stm32mp1_pm_save_clock_cfg(offset, ++ (uint8_t *)gate_refcounts, ++ sizeof(gate_refcounts)); ++} ++ ++void restore_clock_pm_context(void) ++{ ++ size_t offset = 0U; ++ ++ stm32mp1_pm_restore_clock_cfg(offset, ++ (uint8_t *)backup_mux0_cfg, ++ sizeof(backup_mux0_cfg)); ++ offset += sizeof(backup_mux0_cfg); ++ ++ stm32mp1_pm_restore_clock_cfg(offset, ++ (uint8_t *)backup_mux4_cfg, ++ sizeof(backup_mux4_cfg)); ++ offset += sizeof(backup_mux4_cfg); ++ ++ stm32mp1_pm_restore_clock_cfg(offset, ++ (uint8_t *)backup_clock_sc_cfg, ++ sizeof(backup_clock_sc_cfg)); ++ offset += sizeof(backup_clock_sc_cfg); ++ ++ stm32mp1_pm_restore_clock_cfg(offset, ++ (uint8_t *)backup_clock_cfg, ++ sizeof(backup_clock_cfg)); ++ offset += sizeof(backup_clock_cfg); ++ ++ stm32mp1_pm_restore_clock_cfg(offset, ++ (uint8_t *)gate_refcounts, ++ sizeof(gate_refcounts)); ++} ++ ++void stm32mp1_clock_suspend(void) ++{ ++ backup_regular_cfg(); ++ backup_sc_cfg(); ++ backup_mux_cfg(); ++ clear_rcc_reset_status(); ++} ++ ++void stm32mp1_clock_resume(void) +{ + unsigned int idx; + -+ for (idx = 0U; idx < NB_GATES; idx++) { -+ const struct stm32mp1_clk_gate *gate = gate_ref(idx); -+ unsigned long clock_id = gate_ref(idx)->index; ++ restore_mux_cfg(); ++ restore_sc_cfg(); ++ restore_regular_cfg(); + -+ /* Drop non secure refcnt on non shared shareable clocks */ -+ if (__clk_is_enabled(gate) && -+ stm32mp1_clock_is_shareable(clock_id) && -+ !stm32mp1_clock_is_shared(clock_id)) { -+ stm32mp1_clk_disable_non_secure(clock_id); ++ /* Sync secure and shared clocks physical state on functional state */ ++ for (idx = 0U; idx < NB_GATES; idx++) { ++ struct stm32mp1_clk_gate const *gate = gate_ref(idx); ++ ++ if (gate_is_non_secure(gate)) { ++ continue; ++ } ++ ++ if (gate_refcounts[idx] != 0U) { ++ VERBOSE("Resume clock %d enable\n", gate->index); ++ __clk_enable(gate); ++ } else { ++ VERBOSE("Resume clock %d disable\n", gate->index); ++ __clk_disable(gate); + } + } + ++ disable_kernel_clocks(); ++} ++ ++void stm32mp1_clock_stopmode_save(void) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ /* Save registers not restored after STOP mode */ ++ pll3cr = mmio_read_32(rcc_base + RCC_PLL3CR); ++ pll4cr = mmio_read_32(rcc_base + RCC_PLL4CR); ++ mssckselr = mmio_read_32(rcc_base + RCC_MSSCKSELR); ++ mcudivr = mmio_read_32(rcc_base + RCC_MCUDIVR) & RCC_MCUDIV_MASK; ++ enable_kernel_clocks(); ++} ++ ++static bool pll_is_running(uint32_t pll_offset) ++{ ++ uintptr_t pll_cr = stm32mp_rcc_base() + pll_offset; ++ ++ return (mmio_read_32(pll_cr) & RCC_PLLNCR_PLLON) != 0U; ++} ++ ++static bool pll_was_running(uint32_t saved_value) ++{ ++ return (saved_value & RCC_PLLNCR_PLLON) != 0U; ++} ++ ++int stm32mp1_clock_stopmode_resume(void) ++{ ++ int res; ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ if (pll_was_running(pll4cr) && !pll_is_running(RCC_PLL4CR)) { ++ stm32mp1_pll_start(_PLL4); ++ } ++ ++ if (pll_was_running(pll3cr)) { ++ if (!pll_is_running(RCC_PLL3CR)) { ++ stm32mp1_pll_start(_PLL3); ++ } ++ ++ res = stm32mp1_pll_output(_PLL3, ++ pll3cr >> RCC_PLLNCR_DIVEN_SHIFT); ++ if (res != 0) { ++ return res; ++ } ++ } ++ ++ if (pll_was_running(pll4cr)) { ++ res = stm32mp1_pll_output(_PLL4, ++ pll4cr >> RCC_PLLNCR_DIVEN_SHIFT); ++ if (res != 0) { ++ return res; ++ } ++ } ++ ++ /* Restore MCU clock src after PLL3 RDY */ ++ mmio_write_32(rcc_base + RCC_MSSCKSELR, mssckselr); ++ ++ /* Restore MCUDIV */ ++ res = stm32mp1_set_clkdiv(mcudivr, rcc_base + RCC_MCUDIVR); ++ if (res != 0) { ++ return res; ++ } ++ ++ disable_kernel_clocks(); ++ ++ return 0; ++} ++ ++/* Sync secure clock refcount after all drivers probe/inits, */ ++void stm32mp1_dump_clocks_state(void) ++{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ unsigned int idx; ++ + /* Dump clocks state */ + for (idx = 0U; idx < NB_GATES; idx++) { + const struct stm32mp1_clk_gate *gate = gate_ref(idx); @@ -7080,24 +8934,18 @@ index f0bf363..b304315 100644 +#endif +} + -+static void sync_earlyboot_clocks_state(void) -+{ -+ unsigned int idx; -+ int res; + static void sync_earlyboot_clocks_state(void) + { +- if (!stm32mp_is_single_core()) { +- stm32mp1_clk_enable_secure(RTCAPB); ++ unsigned int n; + -+ for (idx = 0U; idx < NB_GATES; idx++) { -+ assert(gate_refcounts[idx] == 0); -+ } ++ for (n = 0U; n < ARRAY_SIZE(stm32mp1_clk_gate); n++) { ++ const struct stm32mp1_clk_gate *gate = gate_ref(n); + -+ /* Set a non secure refcnt for shareable clocks enabled from boot */ -+ for (idx = 0U; idx < NB_GATES; idx++) { -+ struct stm32mp1_clk_gate const *gate = gate_ref(idx); -+ -+ if (__clk_is_enabled(gate) && -+ stm32mp1_clock_is_shareable(gate->index)) { -+ gate_refcounts[idx] = SHREFCNT_NONSECURE_FLAG; -+ } -+ } ++ if (!gate_is_non_secure(gate)) ++ stm32mp1_register_clock_parents_secure(gate->index); + } + + /* + * Register secure clock parents and init a refcount for @@ -7106,301 +8954,110 @@ index f0bf363..b304315 100644 + * - TZC400, ETZPC and STGEN clocks. + * - RTCAPB clocks on multi-core + */ -+ stm32mp1_register_clock_parents_secure(DDRC1); -+ stm32mp1_clk_enable_secure(DDRC1); -+ stm32mp1_register_clock_parents_secure(DDRC1LP); -+ stm32mp1_clk_enable_secure(DDRC1LP); -+ stm32mp1_register_clock_parents_secure(DDRC2); -+ stm32mp1_clk_enable_secure(DDRC2); -+ stm32mp1_register_clock_parents_secure(DDRC2LP); -+ stm32mp1_clk_enable_secure(DDRC2LP); -+ stm32mp1_register_clock_parents_secure(DDRPHYC); -+ stm32mp1_clk_enable_secure(DDRPHYC); -+ stm32mp1_register_clock_parents_secure(DDRPHYCLP); -+ stm32mp1_clk_enable_secure(DDRPHYCLP); -+ stm32mp1_register_clock_parents_secure(DDRCAPB); -+ stm32mp1_clk_enable_secure(DDRCAPB); -+ stm32mp1_register_clock_parents_secure(AXIDCG); -+ stm32mp1_clk_enable_secure(AXIDCG); -+ stm32mp1_register_clock_parents_secure(DDRPHYCAPB); -+ stm32mp1_clk_enable_secure(DDRPHYCAPB); -+ stm32mp1_register_clock_parents_secure(DDRPHYCAPBLP); -+ stm32mp1_clk_enable_secure(DDRPHYCAPBLP); ++ stm32mp_clk_enable(AXIDCG); + -+ stm32mp1_register_clock_parents_secure(TZPC); -+ stm32mp1_clk_enable_secure(TZPC); -+ stm32mp1_register_clock_parents_secure(TZC1); -+ stm32mp1_clk_enable_secure(TZC1); -+ stm32mp1_register_clock_parents_secure(TZC2); -+ stm32mp1_clk_enable_secure(TZC2); -+ stm32mp1_register_clock_parents_secure(STGEN_K); -+ stm32mp1_clk_enable_secure(STGEN_K); ++ stm32mp_clk_enable(DDRC1); ++ stm32mp_clk_enable(DDRC1LP); ++ stm32mp_clk_enable(DDRC2); ++ stm32mp_clk_enable(DDRC2LP); ++ stm32mp_clk_enable(DDRCAPB); ++ stm32mp_clk_enable(DDRPHYC); ++ stm32mp_clk_enable(DDRPHYCLP); ++ stm32mp_clk_enable(DDRPHYCAPB); ++ stm32mp_clk_enable(DDRPHYCAPBLP); + -+ stm32mp1_register_clock_parents_secure(BSEC); -+ stm32mp1_register_clock_parents_secure(BKPSRAM); ++ stm32mp_clk_enable(TZPC); ++ stm32mp_clk_enable(TZC1); ++ stm32mp_clk_enable(TZC2); ++ stm32mp_clk_enable(STGEN_K); + -+ stm32mp1_register_clock_parents_secure(RTCAPB); ++ stm32mp_clk_enable(RTCAPB); + } + + int stm32mp1_clk_probe(void) + { ++ unsigned long freq_khz; + -+ res = stm32mp_is_single_core(); -+ if (res < 0) { -+ panic(); -+ } ++ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB); + -+ 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 -+} -+ -+int stm32mp1_clk_probe(void) -+{ stm32mp1_osc_init(); -+ sync_earlyboot_clocks_state(); + sync_earlyboot_clocks_state(); + ++ /* Save current CPU operating point value */ ++ freq_khz = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000UL); ++ if (freq_khz > (unsigned long)UINT32_MAX) { ++ panic(); ++ } ++ ++ current_opp_khz = (uint32_t)freq_khz; + return 0; } -diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c -index d4c69cb..99a7360 100644 ---- a/drivers/st/clk/stm32mp1_clkfunc.c -+++ b/drivers/st/clk/stm32mp1_clkfunc.c -@@ -7,16 +7,13 @@ - #include - #include - #include -+#include -+#include -+#include -+#include -+#include - #include - #include --#include -- --#define DT_RCC_NODE_NAME "rcc@50000000" --#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" --#define DT_RCC_COMPAT "syscon" +diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c +index 87c8e2b84..d3ea010ff 100644 +--- a/drivers/st/clk/stm32mp_clkfunc.c ++++ b/drivers/st/clk/stm32mp_clkfunc.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -10,10 +10,13 @@ + + #include + ++#include ++#include + #include + #include ++#include + -#define DT_STGEN_COMPAT "st,stm32-stgen" --#define DT_UART_COMPAT "st,stm32h7-uart" --#define DT_USART_COMPAT "st,stm32h7-usart" ++#define DT_UART_COMPAT "st,stm32h7-uart" - const char *stm32mp_osc_node_label[NB_OSC] = { - [_LSI] = "clk-lsi", -@@ -24,15 +21,14 @@ const char *stm32mp_osc_node_label[NB_OSC] = { - [_HSI] = "clk-hsi", - [_HSE] = "clk-hse", - [_CSI] = "clk-csi", -- [_I2S_CKIN] = "i2s_ckin", -- [_USB_PHY_48] = "ck_usbo_48m" -+ [_I2S_CKIN] = "i2s_ckin" - }; + /* + * Get the frequency of an oscillator from its name in device tree. +@@ -44,7 +47,8 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) + return ret; + } - /******************************************************************************* - * This function reads the frequency of an oscillator from its name. - * It reads the value indicated inside the device tree. -- * Returns 0 if success, and a negative value else. -- * If success, value is stored in the second parameter. -+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure. -+ * On success, value is stored in the second parameter. - ******************************************************************************/ - int fdt_osc_read_freq(const char *name, uint32_t *freq) +- if (strncmp(cchar, name, (size_t)ret) == 0) { ++ if ((strncmp(cchar, name, (size_t)ret) == 0) && ++ (fdt_get_status(subnode) != DT_DISABLED)) { + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", +@@ -158,39 +162,11 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, + + /* + * Get the RCC node offset from the device tree +- * @param fdt: Device tree reference + * @return: Node offset or a negative value on error + */ +-int fdt_get_rcc_node(void *fdt) ++int fdt_get_rcc_node(void) { -@@ -124,7 +120,7 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) - - /******************************************************************************* - * This function reads a value of a oscillator property from its id. -- * Returns value if success, and a default value if property not found. -+ * Returns value on success, and a default value if property not found. - * Default value is passed as parameter. - ******************************************************************************/ - uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, -@@ -166,200 +162,19 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - return dflt_value; - } - --/******************************************************************************* -- * This function reads the rcc base address. -- * It reads the value indicated inside the device tree. -- * Returns address if success, and 0 value else. -- ******************************************************************************/ +- return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); +-} +- +-/* +- * Get the RCC base address from the device tree +- * @return: RCC address or 0 on error +- */ -uint32_t fdt_rcc_read_addr(void) -{ -- int node, subnode; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return 0; -- } -- -- node = fdt_path_offset(fdt, "/soc"); -- if (node < 0) { -- return 0; -- } -- -- fdt_for_each_subnode(subnode, fdt, node) { -- const char *cchar; -- int ret; -- -- cchar = fdt_get_name(fdt, subnode, &ret); -- if (cchar == NULL) { -- return 0; -- } -- -- if (strncmp(cchar, DT_RCC_NODE_NAME, (size_t)ret) == 0) { -- const fdt32_t *cuint; -- -- cuint = fdt_getprop(fdt, subnode, "reg", NULL); -- if (cuint == NULL) { -- return 0; -- } -- -- return fdt32_to_cpu(*cuint); -- } -- } -- -- return 0; --} - - /******************************************************************************* -- * This function reads a series of parameters in rcc-clk section. -- * It reads the values indicated inside the device tree, from property name. -- * The number of parameters is also indicated as entry parameter. -+ * This function get interrupt name. -+ * It reads the values indicated the enabling status. - * Returns 0 if success, and a negative value else. -- * If success, values are stored at the second parameter address. -- ******************************************************************************/ --int fdt_rcc_read_uint32_array(const char *prop_name, -- uint32_t *array, uint32_t count) --{ - int node; - void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -- } -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -- if (node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- return fdt_read_uint32_array(node, prop_name, array, count); --} -- --/******************************************************************************* -- * This function gets the subnode offset in rcc-clk section from its name. -- * It reads the values indicated inside the device tree. -- * Returns offset if success, and a negative value else. -- ******************************************************************************/ --int fdt_rcc_subnode_offset(const char *name) --{ -- int node, subnode; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -- } -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -- if (node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- subnode = fdt_subnode_offset(fdt, node, name); -- if (subnode <= 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- return subnode; --} -- --/******************************************************************************* -- * This function gets the pointer to a rcc-clk property from its name. -- * It reads the values indicated inside the device tree. -- * Length of the property is stored in the second parameter. -- * Returns pointer if success, and NULL value else. -- ******************************************************************************/ --const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) --{ -- const uint32_t *cuint; -- int node, len; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return NULL; -- } -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -- if (node < 0) { -- return NULL; -- } -- -- cuint = fdt_getprop(fdt, node, prop_name, &len); -- if (cuint == NULL) { -- return NULL; -- } -- -- *lenp = len; -- return cuint; --} -- --/******************************************************************************* -- * This function gets the secure status for rcc node. -- * It reads secure-status in device tree. -- * Returns 1 if rcc is available from secure world, 0 else. - ******************************************************************************/ --bool fdt_get_rcc_secure_status(void) -+int fdt_rcc_enable_it(const char *name) - { -- int node; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return false; -- } -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT); -- if (node < 0) { -- return false; -- } -- -- return fdt_check_secure_status(node); --} -- --/******************************************************************************* -- * This function reads the stgen base address. -- * It reads the value indicated inside the device tree. -- * Returns address if success, and NULL value else. -- ******************************************************************************/ --uintptr_t fdt_get_stgen_base(void) --{ -- int node; - const fdt32_t *cuint; -- void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return 0; - } - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); +- node = fdt_get_rcc_node(fdt); - if (node < 0) { - return 0; - } @@ -7411,115 +9068,29 @@ index d4c69cb..99a7360 100644 - } - - return fdt32_to_cpu(*cuint); --} -- --/******************************************************************************* -- * This function gets the clock ID of the given node. -- * It reads the value indicated inside the device tree. -- * Returns ID if success, and a negative value else. -- ******************************************************************************/ --int fdt_get_clock_id(int node) --{ -- const fdt32_t *cuint; - void *fdt; ++ return dt_get_node_by_compatible(DT_RCC_CLK_COMPAT); + } - if (fdt_get_address(&fdt) == 0) { - return -ENOENT; - } + /* +@@ -204,13 +180,8 @@ int fdt_rcc_read_uint32_array(const char *prop_name, + uint32_t *array, uint32_t count) + { + int node; +- void *fdt; -- cuint = fdt_getprop(fdt, node, "clocks", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; +- if (fdt_get_address(&fdt) == 0) { +- return -ENOENT; - } - -- cuint++; -- return (int)fdt32_to_cpu(*cuint); -+ return stm32_gic_enable_spi(fdt_get_rcc_node(fdt), name); +- node = fdt_get_rcc_node(fdt); ++ node = fdt_get_rcc_node(); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } +@@ -218,6 +189,24 @@ int fdt_rcc_read_uint32_array(const char *prop_name, + return fdt_read_uint32_array(node, prop_name, array, count); } -diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c -new file mode 100644 -index 0000000..5c7e202 ---- /dev/null -+++ b/drivers/st/clk/stm32mp_clkfunc.c -@@ -0,0 +1,307 @@ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DT_STGEN_COMPAT "st,stm32-stgen" -+#define DT_UART_COMPAT "st,stm32h7-uart" -+ -+/******************************************************************************* -+ * This function returns the RCC node in the device tree. -+ ******************************************************************************/ -+int fdt_get_rcc_node(void *fdt) -+{ -+ return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -+} -+ -+/******************************************************************************* -+ * This function reads the rcc base address. -+ * It reads the value indicated inside the device tree. -+ * Returns address on success, and 0 on failure. -+ ******************************************************************************/ -+uint32_t fdt_rcc_read_addr(void) -+{ -+ int node; -+ void *fdt; -+ const fdt32_t *cuint; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return 0; -+ } -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function reads a series of parameters in rcc-clk section. -+ * It reads the values indicated inside the device tree, from property name. -+ * The number of parameters is also indicated as entry parameter. -+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure. -+ * On success, values are stored at the second parameter address. -+ ******************************************************************************/ -+int fdt_rcc_read_uint32_array(const char *prop_name, -+ uint32_t *array, uint32_t count) -+{ -+ int node; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return fdt_read_uint32_array(node, prop_name, array, count); -+} -+ + +/******************************************************************************* + * This function reads a property rcc-clk section. + * It reads the values indicated inside the device tree, from property name. @@ -7529,13 +9100,8 @@ index 0000000..5c7e202 +uint32_t fdt_rcc_read_uint32_default(const char *prop_name, uint32_t dflt_value) +{ + int node; -+ void *fdt; + -+ if (fdt_get_address(&fdt) == 0) { -+ return dflt_value; -+ } -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); ++ node = fdt_get_rcc_node(); + if (node < 0) { + return dflt_value; + } @@ -7543,135 +9109,84 @@ index 0000000..5c7e202 + return fdt_read_uint32_default(node, prop_name, dflt_value); +} + -+/******************************************************************************* -+ * This function gets the subnode offset in rcc-clk section from its name. -+ * It reads the values indicated inside the device tree. -+ * Returns offset on success, and a negative FDT/ERRNO error code on failure. -+ ******************************************************************************/ -+int fdt_rcc_subnode_offset(const char *name) -+{ -+ int node, subnode; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ subnode = fdt_subnode_offset(fdt, node, name); -+ if (subnode <= 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return subnode; -+} -+ -+/******************************************************************************* -+ * This function gets the pointer to a rcc-clk property from its name. -+ * It reads the values indicated inside the device tree. -+ * Length of the property is stored in the second parameter. -+ * Returns pointer on success, and NULL value on failure. -+ ******************************************************************************/ -+const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) -+{ -+ const fdt32_t *cuint; -+ int node, len; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return NULL; -+ } -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return NULL; -+ } -+ -+ cuint = fdt_getprop(fdt, node, prop_name, &len); -+ if (cuint == NULL) { -+ return NULL; -+ } -+ -+ *lenp = len; -+ return cuint; -+} -+ -+/******************************************************************************* -+ * This function gets the secure status for rcc node. -+ * It reads secure-status in device tree. -+ * Returns true if rcc is available from secure world, false if not. -+ ******************************************************************************/ -+bool fdt_get_rcc_secure_status(void) -+{ -+ int node; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return false; -+ } -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return false; -+ } -+ -+ return !!(fdt_get_status(node) & DT_SECURE); -+} -+ -+/******************************************************************************* -+ * This function reads the stgen base address. -+ * It reads the value indicated inside the device tree. -+ * Returns address on success, and NULL value on failure. -+ ******************************************************************************/ -+uintptr_t fdt_get_stgen_base(void) -+{ -+ int node; -+ const fdt32_t *cuint; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return 0; -+ } -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); -+ if (node < 0) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function gets the clock ID of the given node. -+ * It reads the value indicated inside the device tree. -+ * Returns ID on success, and a negative FDT/ERRNO error code on failure. -+ ******************************************************************************/ -+int fdt_get_clock_id(int node) -+{ -+ const fdt32_t *cuint; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "clocks", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ cuint++; -+ return (int)fdt32_to_cpu(*cuint); -+} + /* + * Get the subnode offset in rcc-clk section from its name in device tree + * @param name: name of the RCC property +@@ -232,7 +221,7 @@ int fdt_rcc_subnode_offset(const char *name) + return -ENOENT; + } + +- node = fdt_get_rcc_node(fdt); ++ node = fdt_get_rcc_node(); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } +@@ -261,7 +250,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) + return NULL; + } + +- node = fdt_get_rcc_node(fdt); ++ node = fdt_get_rcc_node(); + if (node < 0) { + return NULL; + } +@@ -282,13 +271,8 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) + bool fdt_get_rcc_secure_status(void) + { + int node; +- void *fdt; + +- if (fdt_get_address(&fdt) == 0) { +- return false; +- } +- +- node = fdt_get_rcc_node(fdt); ++ node = fdt_get_rcc_node(); + if (node < 0) { + return false; + } +@@ -297,30 +281,19 @@ bool fdt_get_rcc_secure_status(void) + } + + /* +- * Get the stgen base address. +- * @return: address of stgen on success, and NULL value on failure. ++ * This function gets interrupt name. ++ * It reads the values indicated the enabling status. ++ * Returns 0 if success, and a negative value else. + */ +-uintptr_t fdt_get_stgen_base(void) ++int fdt_rcc_enable_it(const char *name) + { +- int node; +- const fdt32_t *cuint; +- void *fdt; ++ int node = fdt_get_rcc_node(); + +- if (fdt_get_address(&fdt) == 0) { +- return 0; +- } +- +- node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); + if (node < 0) { +- return 0; ++ return -ENODEV; + } + +- cuint = fdt_getprop(fdt, node, "reg", NULL); +- if (cuint == NULL) { +- return 0; +- } +- +- return fdt32_to_cpu(*cuint); ++ return stm32_gic_enable_spi(node, name); + } + + /* +@@ -345,3 +318,137 @@ int fdt_get_clock_id(int node) + cuint++; + return (int)fdt32_to_cpu(*cuint); + } + +/******************************************************************************* + * This function gets the clock ID of the given node using clock-names. @@ -7715,546 +9230,370 @@ index 0000000..5c7e202 + ******************************************************************************/ +unsigned long fdt_get_uart_clock_freq(uintptr_t instance) +{ -+ int node; + void *fdt; ++ int node; ++ int clk_id; + + if (fdt_get_address(&fdt) == 0) { + return 0; + } + + /* Check for UART nodes */ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_UART_COMPAT); -+ while (node != -FDT_ERR_NOTFOUND) { -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) -+ goto next; -+ -+ if ((uintptr_t)fdt32_to_cpu(*cuint) == instance) { -+ unsigned long clk_id; -+ -+ cuint = fdt_getprop(fdt, node, "clocks", NULL); -+ if (cuint == NULL) -+ goto next; -+ -+ cuint++; -+ clk_id = (unsigned long)(fdt32_to_cpu(*cuint)); -+ -+ return stm32mp_clk_get_rate(clk_id); -+ } -+next: -+ node = fdt_node_offset_by_compatible(fdt, node, DT_UART_COMPAT); ++ node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance); ++ if (node < 0) { ++ return 0UL; + } + -+ return 0; ++ clk_id = fdt_get_clock_id(node); ++ if (clk_id < 0) { ++ return 0UL; ++ } ++ ++ return stm32mp_clk_get_rate((unsigned long)clk_id); +} ++ ++/******************************************************************************* ++ * This function checks if PLL1 hard-coded settings have been defined in DT. ++ * Returns true if PLL1 node is found and enabled, false if not. ++ ******************************************************************************/ ++bool fdt_is_pll1_predefined(void) ++{ ++ return fdt_check_node(fdt_rcc_subnode_offset(DT_PLL1_NODE_NAME)); ++} ++ ++/******************************************************************************* ++ * This function configures and restores the STGEN counter depending on the ++ * connected clock. ++ ******************************************************************************/ ++void stm32mp_stgen_config(unsigned long rate) ++{ ++ uint32_t cntfid0; ++ unsigned long long counter; ++ ++ cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); ++ ++ if (cntfid0 == rate) { ++ return; ++ } ++ ++ mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); ++ counter = stm32mp_stgen_get_counter() * rate / cntfid0; ++ ++ mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); ++ mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); ++ mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); ++ mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); ++ ++ write_cntfrq_el0((u_register_t)rate); ++ ++ /* Need to update timer with new frequency */ ++ generic_delay_timer_init(); ++} ++ ++/******************************************************************************* ++ * This function returns the STGEN counter value. ++ ******************************************************************************/ ++unsigned long long stm32mp_stgen_get_counter(void) ++{ ++ unsigned long long cnt; ++ ++ cnt = mmio_read_32(STGEN_BASE + CNTCVU_OFF); ++ cnt <<= 32; ++ cnt |= mmio_read_32(STGEN_BASE + CNTCVL_OFF); ++ ++ return cnt; ++} ++ ++/******************************************************************************* ++ * This function restores the STGEN counter value. ++ * It takes a first input value as a counter backup value to be restored and a ++ * offset in ms to be added. ++ ******************************************************************************/ ++void stm32mp_stgen_restore_counter(unsigned long long value, ++ unsigned long long offset_in_ms) ++{ ++ unsigned long long cnt = value; ++ ++ cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U; ++ ++ mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); ++ mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); ++ mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); ++ mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); ++} +diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c +index f72787d33..fcc45fada 100644 +--- a/drivers/st/crypto/stm32_hash.c ++++ b/drivers/st/crypto/stm32_hash.c +@@ -21,6 +21,8 @@ + #include + #include + ++#define TIMEOUT_US_1MS U(1000) ++ + #define DT_HASH_COMPAT "st,stm32f756-hash" + + #define HASH_CR 0x00U +@@ -251,6 +253,8 @@ int stm32_hash_final(uint8_t *digest) + mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, + 8U * stm32_remain.length); + zeromem(&stm32_remain, sizeof(stm32_remain)); ++ } else { ++ mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK); + } + + mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); +@@ -319,9 +323,16 @@ int stm32_hash_register(void) + stm32mp_clk_enable(stm32_hash.clock); + + if (hash_info.reset >= 0) { +- stm32mp_reset_assert((unsigned long)hash_info.reset); ++ uint32_t reset = hash_info.reset; ++ ++ if (stm32mp_reset_assert_to(reset, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ + udelay(20); +- stm32mp_reset_deassert((unsigned long)hash_info.reset); ++ if (stm32mp_reset_deassert_to(reset, TIMEOUT_US_1MS)) { ++ panic(); ++ } + } + + stm32mp_clk_disable(stm32_hash.clock); diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c -index eed1d76..ae5668a 100644 +index 7d89d027e..db8247522 100644 --- a/drivers/st/ddr/stm32mp1_ddr.c +++ b/drivers/st/ddr/stm32mp1_ddr.c -@@ -8,18 +8,14 @@ - #include - #include - #include --#include -+#include - #include - #include -+#include - #include --#include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include -+#include - - struct reg_desc { - const char *name; -@@ -29,7 +25,8 @@ struct reg_desc { +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ +@@ -29,6 +29,7 @@ struct reg_desc { #define INVALID_OFFSET 0xFFU --#define TIMESLOT_1US (plat_get_syscnt_freq2() / 1000000U) -+#define TIMESLOT_1US us2tick(1) -+#define TIMEOUT_1S s2tick(1) ++#define TIMESLOT_US_1US 1U + #define TIMEOUT_US_1S 1000000U #define DDRCTL_REG(x, y) \ - { \ -@@ -231,40 +228,67 @@ struct ddr_reg_info { +@@ -45,8 +46,22 @@ struct reg_desc { + .par_offset = offsetof(struct y, x) \ + } - static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { - [REG_REG] = { -- "static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE -+ .name = "static", -+ .desc = ddr_reg, -+ .size = ARRAY_SIZE(ddr_reg), -+ .base = DDR_BASE - }, - [REG_TIMING] = { -- "timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE -+ .name = "timing", -+ .desc = ddr_timing, -+ .size = ARRAY_SIZE(ddr_timing), -+ .base = DDR_BASE - }, - [REG_PERF] = { -- "perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE -+ .name = "perf", -+ .desc = ddr_perf, -+ .size = ARRAY_SIZE(ddr_perf), -+ .base = DDR_BASE - }, - [REG_MAP] = { -- "map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE -+ .name = "map", -+ .desc = ddr_map, -+ .size = ARRAY_SIZE(ddr_map), -+ .base = DDR_BASE - }, - [REGPHY_REG] = { -- "static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE -+ .name = "static", -+ .desc = ddrphy_reg, -+ .size = ARRAY_SIZE(ddrphy_reg), -+ .base = DDRPHY_BASE - }, - [REGPHY_TIMING] = { -- "timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE -+ .name = "timing", -+ .desc = ddrphy_timing, -+ .size = ARRAY_SIZE(ddrphy_timing), -+ .base = DDRPHY_BASE - }, - [REGPHY_CAL] = { -- "cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE -+ .name = "cal", -+ .desc = ddrphy_cal, -+ .size = ARRAY_SIZE(ddrphy_cal), -+ .base = DDRPHY_BASE - }, - [REG_DYN] = { -- "dyn", ddr_dyn, ARRAY_SIZE(ddr_dyn), DDR_BASE -+ .name = "dyn", -+ .desc = ddr_dyn, -+ .size = ARRAY_SIZE(ddr_dyn), -+ .base = DDR_BASE - }, - [REGPHY_DYN] = { -- "dyn", ddrphy_dyn, ARRAY_SIZE(ddrphy_dyn), DDRPHY_BASE -+ .name = "dyn", -+ .desc = ddrphy_dyn, -+ .size = ARRAY_SIZE(ddrphy_dyn), -+ .base = DDRPHY_BASE - }, ++/* ++ * 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), +@@ -75,7 +90,7 @@ static const struct reg_desc ddr_reg[] = { }; --static uint32_t get_base_addr(const struct ddr_info *priv, enum base_type base) -+static uintptr_t get_base_addr(const struct ddr_info *priv, enum base_type base) - { - if (base == DDRPHY_BASE) { -- return (uint32_t)priv->phy; -+ return (uintptr_t)priv->phy; - } else { -- return (uint32_t)priv->ctl; -+ return (uintptr_t)priv->ctl; - } - } + #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), +@@ -91,7 +106,7 @@ static const struct reg_desc ddr_timing[] = { + }; -@@ -273,21 +297,22 @@ static void set_reg(const struct ddr_info *priv, - const void *param) - { - unsigned int i; -- unsigned int *ptr, value; -+ unsigned int value; - enum base_type base = ddr_registers[type].base; -- uint32_t base_addr = get_base_addr(priv, base); -+ uintptr_t base_addr = get_base_addr(priv, base); - const struct reg_desc *desc = ddr_registers[type].desc; + #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), +@@ -104,7 +119,7 @@ static const struct reg_desc ddr_map[] = { + }; - VERBOSE("init %s\n", ddr_registers[type].name); - for (i = 0; i < ddr_registers[type].size; i++) { -- ptr = (unsigned int *)(base_addr + desc[i].offset); -+ uintptr_t ptr = base_addr + desc[i].offset; -+ - if (desc[i].par_offset == INVALID_OFFSET) { - ERROR("invalid parameter offset for %s", desc[i].name); - panic(); - } else { -- value = *((uint32_t *)((uint32_t)param + -+ value = *((uint32_t *)((uintptr_t)param + - desc[i].par_offset)); -- mmio_write_32((uint32_t)ptr, value); -+ mmio_write_32(ptr, value); - } - } - } -@@ -296,26 +321,27 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) - { - uint32_t pgsr; - int error = 0; -- unsigned long start; -- unsigned long time0, time; -+ uint64_t start, time0; + #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), +@@ -125,7 +140,7 @@ static const struct reg_desc ddr_perf[] = { + }; -- start = get_timer(0); -+ start = timeout_start(); - time0 = start; + #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), +@@ -140,7 +155,7 @@ static const struct reg_desc ddrphy_reg[] = { + }; - do { -- pgsr = mmio_read_32((uint32_t)&phy->pgsr); -- time = get_timer(start); -+ uint64_t time; -+ -+ pgsr = mmio_read_32((uintptr_t)&phy->pgsr); -+ time = timeout_start() - start; - if (time != time0) { -- VERBOSE(" > [0x%x] pgsr = 0x%x &\n", -- (uint32_t)&phy->pgsr, pgsr); -- VERBOSE(" [0x%x] pir = 0x%x (time=%x)\n", -- (uint32_t)&phy->pir, -- mmio_read_32((uint32_t)&phy->pir), -- (uint32_t)time); -+ VERBOSE(" > [0x%lx] pgsr = 0x%x &\n", -+ (uintptr_t)&phy->pgsr, pgsr); -+ VERBOSE(" [0x%lx] pir = 0x%x (time=%llx)\n", -+ (uintptr_t)&phy->pir, -+ mmio_read_32((uintptr_t)&phy->pir), -+ time); - } + #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), +@@ -154,7 +169,7 @@ static const struct reg_desc ddrphy_timing[] = { + }; - time0 = time; -- if (time > plat_get_syscnt_freq2()) { -+ if (time > TIMEOUT_1S) { - panic(); - } - if ((pgsr & DDRPHYC_PGSR_DTERR) != 0U) { -@@ -339,18 +365,18 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) - error++; - } - } while ((pgsr & DDRPHYC_PGSR_IDONE) == 0U && error == 0); -- VERBOSE("\n[0x%x] pgsr = 0x%x\n", -- (uint32_t)&phy->pgsr, pgsr); -+ VERBOSE("\n[0x%lx] pgsr = 0x%x\n", -+ (uintptr_t)&phy->pgsr, pgsr); - } + #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), +@@ -169,36 +184,9 @@ static const struct reg_desc ddrphy_cal[] = { + DDRPHY_REG_CAL(dx3dqstr), + }; - static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) - { - uint32_t pir_init = pir | DDRPHYC_PIR_INIT; +-#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, +@@ -207,12 +195,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 + }; -- mmio_write_32((uint32_t)&phy->pir, pir_init); -- VERBOSE("[0x%x] pir = 0x%x -> 0x%x\n", -- (uint32_t)&phy->pir, pir_init, -- mmio_read_32((uint32_t)&phy->pir)); -+ mmio_write_32((uintptr_t)&phy->pir, pir_init); -+ VERBOSE("[0x%lx] pir = 0x%x -> 0x%x\n", -+ (uintptr_t)&phy->pir, pir_init, -+ mmio_read_32((uintptr_t)&phy->pir)); - - /* Need to wait 10 configuration clock before start polling */ - udelay(10); -@@ -362,56 +388,57 @@ static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) - /* Start quasi dynamic register update */ - static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl) - { -- mmio_clrbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); -- VERBOSE("[0x%x] swctl = 0x%x\n", -- (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl)); -+ mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); -+ VERBOSE("[0x%lx] swctl = 0x%x\n", -+ (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); - } - - /* Wait quasi dynamic register update */ - static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl) - { -- unsigned long start; -+ uint64_t start; - uint32_t swstat; - -- mmio_setbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); -- VERBOSE("[0x%x] swctl = 0x%x\n", -- (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl)); -+ mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); -+ VERBOSE("[0x%lx] swctl = 0x%x\n", -+ (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); - -- start = get_timer(0); -+ start = timeout_start(); - do { -- swstat = mmio_read_32((uint32_t)&ctl->swstat); -- VERBOSE("[0x%x] swstat = 0x%x ", -- (uint32_t)&ctl->swstat, swstat); -- VERBOSE("timer in ms 0x%x = start 0x%lx\r", -- get_timer(0), start); -- if (get_timer(start) > plat_get_syscnt_freq2()) { -+ swstat = mmio_read_32((uintptr_t)&ctl->swstat); -+ VERBOSE("[0x%lx] swstat = 0x%x ", -+ (uintptr_t)&ctl->swstat, swstat); -+ VERBOSE("timer in ms 0x%llx = start 0x%llx\r", -+ timeout_start(), start); -+ if (timeout_elapsed(start, TIMEOUT_1S)) { - panic(); - } - } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); - -- VERBOSE("[0x%x] swstat = 0x%x\n", -- (uint32_t)&ctl->swstat, swstat); -+ VERBOSE("[0x%lx] swstat = 0x%x\n", -+ (uintptr_t)&ctl->swstat, swstat); - } - - /* Wait quasi dynamic register update */ - static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) - { -- unsigned long start; -+ uint64_t start; - uint32_t stat; -- uint32_t operating_mode; -- uint32_t selref_type; - int break_loop = 0; - -- start = get_timer(0); -+ start = timeout_start(); - for ( ; ; ) { -- stat = mmio_read_32((uint32_t)&priv->ctl->stat); -+ uint32_t operating_mode; -+ uint32_t selref_type; -+ -+ stat = mmio_read_32((uintptr_t)&priv->ctl->stat); - operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; - selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; -- VERBOSE("[0x%x] stat = 0x%x\n", -- (uint32_t)&priv->ctl->stat, stat); -- VERBOSE("timer in ms 0x%x = start 0x%lx\r", -- get_timer(0), start); -- if (get_timer(start) > plat_get_syscnt_freq2()) { -+ VERBOSE("[0x%lx] stat = 0x%x\n", -+ (uintptr_t)&priv->ctl->stat, stat); -+ VERBOSE("timer in ms 0x%llx = start 0x%llx\r", -+ timeout_start(), start); -+ if (timeout_elapsed(start, TIMEOUT_1S)) { - panic(); - } - -@@ -439,8 +466,8 @@ static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) - } - } - -- VERBOSE("[0x%x] stat = 0x%x\n", -- (uint32_t)&priv->ctl->stat, stat); -+ VERBOSE("[0x%lx] stat = 0x%x\n", -+ (uintptr_t)&priv->ctl->stat, stat); - } - - /* Mode Register Writes (MRW or MRS) */ -@@ -457,7 +484,7 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, - * No write should be performed to MRCTRL0 and MRCTRL1 - * if MRSTAT.mr_wr_busy = 1. - */ -- while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) & -+ while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & - DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { - ; - } -@@ -470,14 +497,14 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, - DDRCTRL_MRCTRL0_MR_RANK_ALL | - (((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) & - DDRCTRL_MRCTRL0_MR_ADDR_MASK); -- mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0); -- VERBOSE("[0x%x] mrctrl0 = 0x%x (0x%x)\n", -- (uint32_t)&priv->ctl->mrctrl0, -- mmio_read_32((uint32_t)&priv->ctl->mrctrl0), mrctrl0); -- mmio_write_32((uint32_t)&priv->ctl->mrctrl1, data); -- VERBOSE("[0x%x] mrctrl1 = 0x%x\n", -- (uint32_t)&priv->ctl->mrctrl1, -- mmio_read_32((uint32_t)&priv->ctl->mrctrl1)); -+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); -+ VERBOSE("[0x%lx] mrctrl0 = 0x%x (0x%x)\n", -+ (uintptr_t)&priv->ctl->mrctrl0, -+ mmio_read_32((uintptr_t)&priv->ctl->mrctrl0), mrctrl0); -+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl1, data); -+ VERBOSE("[0x%lx] mrctrl1 = 0x%x\n", -+ (uintptr_t)&priv->ctl->mrctrl1, -+ mmio_read_32((uintptr_t)&priv->ctl->mrctrl1)); - - /* - * 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This -@@ -487,22 +514,22 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, - * initiated until it is deasserted. - */ - mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR; -- mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0); -+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); - -- while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) & -+ while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & - DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { - ; - } - -- VERBOSE("[0x%x] mrctrl0 = 0x%x\n", -- (uint32_t)&priv->ctl->mrctrl0, mrctrl0); -+ VERBOSE("[0x%lx] mrctrl0 = 0x%x\n", -+ (uintptr_t)&priv->ctl->mrctrl0, mrctrl0); - } - - /* Switch DDR3 from DLL-on to DLL-off */ - static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - { -- uint32_t mr1 = mmio_read_32((uint32_t)&priv->phy->mr1); -- uint32_t mr2 = mmio_read_32((uint32_t)&priv->phy->mr2); -+ uint32_t mr1 = mmio_read_32((uintptr_t)&priv->phy->mr1); -+ uint32_t mr2 = mmio_read_32((uintptr_t)&priv->phy->mr2); - uint32_t dbgcam; - - VERBOSE("mr1: 0x%x\n", mr1); -@@ -512,10 +539,10 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - * 1. Set the DBG1.dis_hif = 1. - * This prevents further reads/writes being received on the HIF. - */ -- mmio_setbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); -- VERBOSE("[0x%x] dbg1 = 0x%x\n", -- (uint32_t)&priv->ctl->dbg1, -- mmio_read_32((uint32_t)&priv->ctl->dbg1)); -+ mmio_setbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); -+ VERBOSE("[0x%lx] dbg1 = 0x%x\n", -+ (uintptr_t)&priv->ctl->dbg1, -+ mmio_read_32((uintptr_t)&priv->ctl->dbg1)); - - /* - * 2. Ensure all commands have been flushed from the uMCTL2 by polling -@@ -526,9 +553,9 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - * DBGCAM.dbg_hpr_q_depth = 0. - */ - do { -- dbgcam = mmio_read_32((uint32_t)&priv->ctl->dbgcam); -- VERBOSE("[0x%x] dbgcam = 0x%x\n", -- (uint32_t)&priv->ctl->dbgcam, dbgcam); -+ dbgcam = mmio_read_32((uintptr_t)&priv->ctl->dbgcam); -+ VERBOSE("[0x%lx] dbgcam = 0x%x\n", -+ (uintptr_t)&priv->ctl->dbgcam, dbgcam); - } while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) == - DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) && - ((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U)); -@@ -572,11 +599,11 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - * PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure - * the DDRC has entered self-refresh. - */ -- mmio_setbits_32((uint32_t)&priv->ctl->pwrctl, -+ mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl, - DDRCTRL_PWRCTL_SELFREF_SW); -- VERBOSE("[0x%x] pwrctl = 0x%x\n", -- (uint32_t)&priv->ctl->pwrctl, -- mmio_read_32((uint32_t)&priv->ctl->pwrctl)); -+ VERBOSE("[0x%lx] pwrctl = 0x%x\n", -+ (uintptr_t)&priv->ctl->pwrctl, -+ mmio_read_32((uintptr_t)&priv->ctl->pwrctl)); - - /* - * 8. Wait until STAT.operating_mode[1:0]==11 indicating that the -@@ -592,10 +619,10 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - */ - stm32mp1_start_sw_done(priv->ctl); - -- mmio_setbits_32((uint32_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); -- VERBOSE("[0x%x] mstr = 0x%x\n", -- (uint32_t)&priv->ctl->mstr, -- mmio_read_32((uint32_t)&priv->ctl->mstr)); -+ mmio_setbits_32((uintptr_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); -+ VERBOSE("[0x%lx] mstr = 0x%x\n", -+ (uintptr_t)&priv->ctl->mstr, -+ mmio_read_32((uintptr_t)&priv->ctl->mstr)); - - stm32mp1_wait_sw_done_ack(priv->ctl); - -@@ -608,27 +635,27 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - */ - - /* Change Bypass Mode Frequency Range */ -- if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) { -- mmio_clrbits_32((uint32_t)&priv->phy->dllgcr, -+ if (stm32mp_clk_get_rate(DDRPHYC) < 100000000U) { -+ mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, - DDRPHYC_DLLGCR_BPS200); - } else { -- mmio_setbits_32((uint32_t)&priv->phy->dllgcr, -+ mmio_setbits_32((uintptr_t)&priv->phy->dllgcr, - DDRPHYC_DLLGCR_BPS200); - } - -- mmio_setbits_32((uint32_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); -+ mmio_setbits_32((uintptr_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); - -- mmio_setbits_32((uint32_t)&priv->phy->dx0dllcr, -+ mmio_setbits_32((uintptr_t)&priv->phy->dx0dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); -- mmio_setbits_32((uint32_t)&priv->phy->dx1dllcr, -+ mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); -- mmio_setbits_32((uint32_t)&priv->phy->dx2dllcr, -+ mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); -- mmio_setbits_32((uint32_t)&priv->phy->dx3dllcr, -+ mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); - - /* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ -- mmio_clrbits_32((uint32_t)&priv->ctl->pwrctl, -+ mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, - DDRCTRL_PWRCTL_SELFREF_SW); - stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); - -@@ -644,20 +671,20 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - */ - - /* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */ -- mmio_clrbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); -- VERBOSE("[0x%x] dbg1 = 0x%x\n", -- (uint32_t)&priv->ctl->dbg1, -- mmio_read_32((uint32_t)&priv->ctl->dbg1)); -+ mmio_clrbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); -+ VERBOSE("[0x%lx] dbg1 = 0x%x\n", -+ (uintptr_t)&priv->ctl->dbg1, -+ mmio_read_32((uintptr_t)&priv->ctl->dbg1)); - } - - static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) - { - stm32mp1_start_sw_done(ctl); +@@ -233,55 +215,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 + }, + }; +@@ -675,7 +645,8 @@ static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) /* Quasi-dynamic register update*/ -- mmio_setbits_32((uint32_t)&ctl->rfshctl3, -+ mmio_setbits_32((uintptr_t)&ctl->rfshctl3, + mmio_setbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); -- mmio_clrbits_32((uint32_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); -- mmio_clrbits_32((uint32_t)&ctl->dfimisc, -+ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); -+ mmio_clrbits_32((uintptr_t)&ctl->dfimisc, +- mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); ++ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN | ++ DDRCTRL_PWRCTL_SELFREF_EN); + mmio_clrbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); stm32mp1_wait_sw_done_ack(ctl); - } -@@ -667,21 +694,99 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, - { - stm32mp1_start_sw_done(ctl); - if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { -- mmio_clrbits_32((uint32_t)&ctl->rfshctl3, -+ mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, - DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); - } - if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { -- mmio_setbits_32((uint32_t)&ctl->pwrctl, -+ mmio_setbits_32((uintptr_t)&ctl->pwrctl, +@@ -693,11 +664,92 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, + mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); } -- mmio_setbits_32((uint32_t)&ctl->dfimisc, -+ mmio_setbits_32((uintptr_t)&ctl->dfimisc, ++ if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN) != 0U) { ++ mmio_setbits_32((uintptr_t)&ctl->pwrctl, ++ DDRCTRL_PWRCTL_SELFREF_EN); ++ } + mmio_setbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); stm32mp1_wait_sw_done_ack(ctl); } @@ -8280,10 +9619,9 @@ index eed1d76..ae5668a 100644 + uint64_t start) +{ + uint32_t tck_ps; -+ uint64_t time, time_us, tref, trefi, refcomp, i; ++ uint64_t time_us, tref, trefi, refcomp, i; + -+ time = timeout_start() - start; -+ time_us = time / TIMESLOT_1US; ++ time_us = timeout_init_us(0) - start; + tck_ps = 1000000000U / config->info.speed; + if (tck_ps == 0U) { + return; @@ -8339,39 +9677,19 @@ index eed1d76..ae5668a 100644 + static int board_ddr_power_init(enum ddr_type ddr_type) { -- if (dt_check_pmic()) { -+ if (dt_pmic_status() > 0) { - return pmic_ddr_power_init(ddr_type); - } - -@@ -691,13 +796,18 @@ static int board_ddr_power_init(enum ddr_type ddr_type) + if (dt_pmic_status() > 0) { +@@ -710,7 +762,7 @@ static int board_ddr_power_init(enum ddr_type ddr_type) void stm32mp1_ddr_init(struct ddr_info *priv, struct stm32mp1_ddr_config *config) { - uint32_t pir; -- int ret; + uint32_t pir, ddr_reten; -+ int ret = -EINVAL; -+ uint64_t time; + int ret = -EINVAL; if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { - ret = board_ddr_power_init(STM32MP_DDR3); -- } else { -+ } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) { - ret = board_ddr_power_init(STM32MP_LPDDR2); -+ } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) != 0U) { -+ ret = board_ddr_power_init(STM32MP_LPDDR3); -+ } else { -+ ERROR("DDR type not supported\n"); - } - - if (ret != 0) { -@@ -705,8 +815,29 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - } - +@@ -730,6 +782,27 @@ void stm32mp1_ddr_init(struct ddr_info *priv, VERBOSE("name = %s\n", config->info.name); -- VERBOSE("speed = %d MHz\n", config->info.speed); -+ VERBOSE("speed = %d kHz\n", config->info.speed); + VERBOSE("speed = %d kHz\n", config->info.speed); VERBOSE("size = 0x%x\n", config->info.size); + if (config->self_refresh) { + VERBOSE("sel-refresh exit (zdata = 0x%x)\n", config->zdata); @@ -8397,89 +9715,31 @@ index eed1d76..ae5668a 100644 /* DDR INIT SEQUENCE */ -@@ -744,11 +875,11 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - - /* 1.5. initialize registers ddr_umctl2 */ - /* Stop uMCTL2 before PHY is ready */ -- mmio_clrbits_32((uint32_t)&priv->ctl->dfimisc, -+ mmio_clrbits_32((uintptr_t)&priv->ctl->dfimisc, - DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); -- VERBOSE("[0x%x] dfimisc = 0x%x\n", -- (uint32_t)&priv->ctl->dfimisc, -- mmio_read_32((uint32_t)&priv->ctl->dfimisc)); -+ VERBOSE("[0x%lx] dfimisc = 0x%x\n", -+ (uintptr_t)&priv->ctl->dfimisc, -+ mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); - - set_reg(priv, REG_REG, &config->c_reg); - -@@ -757,23 +888,31 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) - == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { - VERBOSE("deactivate DLL OFF in mstr\n"); -- mmio_clrbits_32((uint32_t)&priv->ctl->mstr, -+ mmio_clrbits_32((uintptr_t)&priv->ctl->mstr, - DDRCTRL_MSTR_DLL_OFF_MODE); -- VERBOSE("[0x%x] mstr = 0x%x\n", -- (uint32_t)&priv->ctl->mstr, -- mmio_read_32((uint32_t)&priv->ctl->mstr)); -+ VERBOSE("[0x%lx] mstr = 0x%x\n", -+ (uintptr_t)&priv->ctl->mstr, -+ mmio_read_32((uintptr_t)&priv->ctl->mstr)); - } - +@@ -790,6 +863,12 @@ void stm32mp1_ddr_init(struct ddr_info *priv, set_reg(priv, REG_TIMING, &config->c_timing); set_reg(priv, REG_MAP, &config->c_map); -- /* Skip CTRL init, SDRAM init is done by PHY PUBL */ -- mmio_clrsetbits_32((uint32_t)&priv->ctl->init0, -- DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, -- DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL); -- VERBOSE("[0x%x] init0 = 0x%x\n", -- (uint32_t)&priv->ctl->init0, -- mmio_read_32((uint32_t)&priv->ctl->init0)); + /* Keep the controller in self-refresh mode */ + if (config->self_refresh) { + mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl, + DDRCTRL_PWRCTL_SELFREF_SW); + } + -+ { -+ /* Skip CTRL init, SDRAM init is done by PHY PUBL */ -+ mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0, -+ DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, -+ DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL); -+ VERBOSE("[0x%lx] init0 = 0x%x\n", -+ (uintptr_t)&priv->ctl->init0, -+ mmio_read_32((uintptr_t)&priv->ctl->init0)); -+ } - - set_reg(priv, REG_PERF, &config->c_perf); - -@@ -786,6 +925,7 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - * 3. start PHY init by accessing relevant PUBL registers - * (DXGCR, DCR, PTR*, MR*, DTPR*) + /* Skip CTRL init, SDRAM init is done by PHY PUBL */ + mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0, + DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, +@@ -811,7 +890,9 @@ void stm32mp1_ddr_init(struct ddr_info *priv, */ -+ set_reg(priv, REGPHY_REG, &config->p_reg); set_reg(priv, REGPHY_TIMING, &config->p_timing); - set_reg(priv, REGPHY_CAL, &config->p_cal); -@@ -795,10 +935,10 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) - == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { - VERBOSE("deactivate DLL OFF in mr1\n"); -- mmio_clrbits_32((uint32_t)&priv->phy->mr1, BIT(0)); -- VERBOSE("[0x%x] mr1 = 0x%x\n", -- (uint32_t)&priv->phy->mr1, -- mmio_read_32((uint32_t)&priv->phy->mr1)); -+ mmio_clrbits_32((uintptr_t)&priv->phy->mr1, BIT(0)); -+ VERBOSE("[0x%lx] mr1 = 0x%x\n", -+ (uintptr_t)&priv->phy->mr1, -+ mmio_read_32((uintptr_t)&priv->phy->mr1)); - } +- set_reg(priv, REGPHY_CAL, &config->p_cal); ++ if (config->p_cal_present) { ++ set_reg(priv, REGPHY_CAL, &config->p_cal); ++ } - /* -@@ -820,19 +960,31 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & +@@ -843,8 +924,20 @@ void stm32mp1_ddr_init(struct ddr_info *priv, pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */ } @@ -8500,22 +9760,7 @@ index eed1d76..ae5668a 100644 /* * 6. SET DFIMISC.dfi_init_complete_en to 1 * Enable quasi-dynamic register programming. - */ - stm32mp1_start_sw_done(priv->ctl); - -- mmio_setbits_32((uint32_t)&priv->ctl->dfimisc, -+ mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc, - DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); -- VERBOSE("[0x%x] dfimisc = 0x%x\n", -- (uint32_t)&priv->ctl->dfimisc, -- mmio_read_32((uint32_t)&priv->ctl->dfimisc)); -+ VERBOSE("[0x%lx] dfimisc = 0x%x\n", -+ (uintptr_t)&priv->ctl->dfimisc, -+ mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); - - stm32mp1_wait_sw_done_ack(priv->ctl); - -@@ -842,6 +994,13 @@ void stm32mp1_ddr_init(struct ddr_info *priv, +@@ -865,6 +958,13 @@ void stm32mp1_ddr_init(struct ddr_info *priv, */ /* Wait uMCTL2 ready */ @@ -8529,86 +9774,123 @@ index eed1d76..ae5668a 100644 stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); /* Switch to DLL OFF mode */ -@@ -851,6 +1010,8 @@ void stm32mp1_ddr_init(struct ddr_info *priv, +@@ -872,37 +972,53 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + stm32mp1_ddr3_dll_off(priv); + } - VERBOSE("DDR DQS training : "); - -+ time = timeout_start(); +- VERBOSE("DDR DQS training : "); +- +- /* +- * 8. Disable Auto refresh and power down by setting +- * - RFSHCTL3.dis_au_refresh = 1 +- * - PWRCTL.powerdown_en = 0 +- * - DFIMISC.dfiinit_complete_en = 0 +- */ +- stm32mp1_refresh_disable(priv->ctl); +- +- /* +- * 9. Program PUBL PGCR to enable refresh during training +- * and rank to train +- * not done => keep the programed value in PGCR +- */ +- +- /* +- * 10. configure PUBL PIR register to specify which training step +- * to run +- * Warning : RVTRN is not supported by this PUBL +- */ +- stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); +- +- /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ +- stm32mp1_ddrphy_idone_wait(priv->phy); ++ if (config->p_cal_present) { ++ VERBOSE("DDR DQS training skipped.\n"); ++ } else { ++ uint64_t time; + - /* - * 8. Disable Auto refresh and power down by setting - * - RFSHCTL3.dis_au_refresh = 1 -@@ -875,6 +1036,11 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ - stm32mp1_ddrphy_idone_wait(priv->phy); ++ VERBOSE("DDR DQS training.\n"); ++ ++ time = timeout_init_us(0); ++ ++ /* ++ * 8. Disable Auto refresh and power down by setting ++ * - RFSHCTL3.dis_au_refresh = 1 ++ * - PWRCTL.powerdown_en = 0 ++ * - DFIMISC.dfiinit_complete_en = 0 ++ */ ++ stm32mp1_refresh_disable(priv->ctl); ++ ++ /* ++ * 9. Program PUBL PGCR to enable refresh during training ++ * and rank to train ++ * not done => keep the programed value in PGCR ++ */ ++ ++ /* ++ * 10. configure PUBL PIR register to specify which training ++ * step to run ++ * Warning : RVTRN is not supported by this PUBL ++ */ ++ stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); ++ ++ /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training ++ * sequence ++ */ ++ stm32mp1_ddrphy_idone_wait(priv->phy); ++ ++ /* Refresh compensation: forcing refresh command */ ++ if (config->self_refresh) { ++ stm32mp1_refresh_compensation(config, priv->ctl, time); ++ } -+ /* Refresh compensation: forcing refresh command */ -+ if (config->self_refresh) { -+ stm32mp1_refresh_compensation(config, priv->ctl, time); +- /* +- * 12. set back registers in step 8 to the orginal values if desidered +- */ +- stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, +- config->c_reg.pwrctl); ++ /* ++ * 12. set back registers in step 8 to the orginal values ++ * if desidered ++ */ ++ stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, ++ config->c_reg.pwrctl); + } -+ - /* - * 12. set back registers in step 8 to the orginal values if desidered - */ -@@ -882,14 +1048,16 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - config->c_reg.pwrctl); /* Enable uMCTL2 AXI port 0 */ -- mmio_setbits_32((uint32_t)&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); -- VERBOSE("[0x%x] pctrl_0 = 0x%x\n", -- (uint32_t)&priv->ctl->pctrl_0, -- mmio_read_32((uint32_t)&priv->ctl->pctrl_0)); -+ mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_0, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", -+ (uintptr_t)&priv->ctl->pctrl_0, -+ mmio_read_32((uintptr_t)&priv->ctl->pctrl_0)); - - /* Enable uMCTL2 AXI port 1 */ -- mmio_setbits_32((uint32_t)&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); -- VERBOSE("[0x%x] pctrl_1 = 0x%x\n", -- (uint32_t)&priv->ctl->pctrl_1, -- mmio_read_32((uint32_t)&priv->ctl->pctrl_1)); -+ mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", -+ (uintptr_t)&priv->ctl->pctrl_1, -+ mmio_read_32((uintptr_t)&priv->ctl->pctrl_1)); - } + mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_0, diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c -index 325c0b8..63f254f 100644 +index fcb4cfcfd..3b8af550f 100644 --- a/drivers/st/ddr/stm32mp1_ddr_helpers.c +++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c -@@ -4,17 +4,521 @@ +@@ -1,14 +1,23 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * * SPDX-License-Identifier: BSD-3-Clause */ -+#include -+#include -+#include - #include -+#include #include --#include --#include -+#include -+ -+#define TIMEOUT_500US us2tick(500) ++#include ++#include ++#include ++#include + #include ++#include + #include + ++#define TIMEOUT_500US 500U ++ ++static enum stm32mp1_ddr_sr_mode saved_ddr_sr_mode; ++ void ddr_enable_clock(void) { -- mmio_setbits_32(RCC_BASE + RCC_DDRITFCR, -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, - RCC_DDRITFCR_DDRC1EN | - RCC_DDRITFCR_DDRC2EN | - RCC_DDRITFCR_DDRPHYCEN | - RCC_DDRITFCR_DDRPHYCAPBEN | - RCC_DDRITFCR_DDRCAPBEN); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+} + stm32mp1_clk_rcc_regs_lock(); +@@ -22,3 +31,564 @@ void ddr_enable_clock(void) + + stm32mp1_clk_rcc_regs_unlock(); + } + +static void do_sw_handshake(void) +{ @@ -8619,15 +9901,15 @@ index 325c0b8..63f254f 100644 + +static void do_sw_ack(void) +{ -+ uint64_t start; ++ uint64_t timeout; + uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); + + mmio_setbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); + -+ start = timeout_start(); ++ timeout = timeout_init_us(TIMEOUT_500US); + while ((mmio_read_32(ddrctrl_base + DDRCTRL_SWSTAT) & + DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U) { -+ if (timeout_elapsed(start, TIMEOUT_500US)) { ++ if (timeout_elapsed(timeout)) { + panic(); + } + } @@ -8635,7 +9917,7 @@ index 325c0b8..63f254f 100644 + +static int ddr_sw_self_refresh_in(void) +{ -+ uint64_t start; ++ uint64_t timeout; + uint32_t stat; + uint32_t operating_mode; + uint32_t selref_type; @@ -8661,9 +9943,9 @@ index 325c0b8..63f254f 100644 + * Poll PSTAT.rd_port_busy_n = 0 + * Poll PSTAT.wr_port_busy_n = 0 + */ -+ start = timeout_start(); ++ timeout = timeout_init_us(TIMEOUT_500US); + while (mmio_read_32(ddrctrl_base + DDRCTRL_PSTAT)) { -+ if (timeout_elapsed(start, TIMEOUT_500US)) { ++ if (timeout_elapsed(timeout)) { + goto pstat_failed; + } + } @@ -8676,8 +9958,8 @@ index 325c0b8..63f254f 100644 + * Ensure transition to self-refresh was due to software + * by checking also that STAT.selfref_type[1:0]=2. + */ -+ start = timeout_start(); -+ while (!timeout_elapsed(start, TIMEOUT_500US)) { ++ timeout = timeout_init_us(TIMEOUT_500US); ++ while (!timeout_elapsed(timeout)) { + stat = mmio_read_32(ddrctrl_base + DDRCTRL_STAT); + operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; + selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; @@ -8709,6 +9991,9 @@ index 325c0b8..63f254f 100644 + DDRPHYC_ACIOCR_CSPDD_MASK, + DDRPHYC_ACIOCR_CSPDD_0); + ++ /* Disable command/address output driver */ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); ++ + mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); + + mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); @@ -8726,10 +10011,16 @@ index 325c0b8..63f254f 100644 + /* Disable PZQ cell (PUBL register) */ + mmio_setbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); + ++ /* Set latch */ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE); ++ ++ /* Additional delay to avoid early latch */ ++ udelay(10); ++ + /* Activate sw retention in PWRCTRL */ -+ pwr_regs_lock(); ++ stm32mp_pwr_regs_lock(); + mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); -+ pwr_regs_unlock(); ++ stm32mp_pwr_regs_unlock(); + + /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ + stm32mp1_clk_rcc_regs_lock(); @@ -8784,7 +10075,7 @@ index 325c0b8..63f254f 100644 + +int ddr_sw_self_refresh_exit(void) +{ -+ uint64_t start; ++ uint64_t timeout; + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t pwr_base = stm32mp_pwr_base(); + uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -8823,7 +10114,7 @@ index 325c0b8..63f254f 100644 + DDRPHYC_DXNDLLCR_DLLDIS); + + /* Additional delay to avoid early DLL clock switch */ -+ udelay(10); ++ udelay(50); + + /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ + stm32mp1_clk_rcc_regs_lock(); @@ -8847,11 +10138,11 @@ index 325c0b8..63f254f 100644 + udelay(1); + + /* Pool end of init */ -+ start = timeout_start(); ++ timeout = timeout_init_us(TIMEOUT_500US); + + while ((mmio_read_32(ddrphyc_base + DDRPHYC_PGSR) & + DDRPHYC_PGSR_IDONE) == 0U) { -+ if (timeout_elapsed(start, TIMEOUT_500US)) { ++ if (timeout_elapsed(timeout)) { + return -1; + } + } @@ -8865,9 +10156,9 @@ index 325c0b8..63f254f 100644 + do_sw_ack(); + + /* Deactivate sw retention in PWR */ -+ pwr_regs_lock(); ++ stm32mp_pwr_regs_lock(); + mmio_clrbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); -+ pwr_regs_unlock(); ++ stm32mp_pwr_regs_unlock(); + + /* Enable PZQ cell (PUBL register) */ + mmio_clrbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); @@ -8875,6 +10166,9 @@ index 325c0b8..63f254f 100644 + /* Enable pad drivers */ + mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); + ++ /* Enable command/address output driver */ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); ++ + mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, + DDRPHYC_ACIOCR_CKPDD_MASK); + @@ -8885,6 +10179,9 @@ index 325c0b8..63f254f 100644 + + mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); + ++ /* Release latch */ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE); ++ + mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, + DDRPHYC_DSGCR_ODTPDD_MASK); + @@ -8898,11 +10195,11 @@ index 325c0b8..63f254f 100644 + DDRCTRL_PWRCTL_SELFREF_SW); + + /* Wait operating_mode == normal */ -+ start = timeout_start(); ++ timeout = timeout_init_us(TIMEOUT_500US); + while ((mmio_read_32(ddrctrl_base + DDRCTRL_STAT) & + DDRCTRL_STAT_OPERATING_MODE_MASK) != + DDRCTRL_STAT_OPERATING_MODE_NORMAL) { -+ if (timeout_elapsed(start, TIMEOUT_500US)) { ++ if (timeout_elapsed(timeout)) { + return -1; + } + } @@ -8939,14 +10236,14 @@ index 325c0b8..63f254f 100644 + } + + /* Enable I/O retention mode in standby */ -+ pwr_regs_lock(); ++ stm32mp_pwr_regs_lock(); + mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRSREN); -+ pwr_regs_unlock(); ++ stm32mp_pwr_regs_unlock(); + + return 0; +} + -+void ddr_sr_mode_ssr(void) ++static void ddr_sr_mode_ssr(void) +{ + uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; + uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -8998,7 +10295,7 @@ index 325c0b8..63f254f 100644 + DDRCTRL_PWRCTL_SELFREF_EN); +} + -+void ddr_sr_mode_asr(void) ++static void ddr_sr_mode_asr(void) +{ + uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; + uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -9039,7 +10336,7 @@ index 325c0b8..63f254f 100644 + DDRCTRL_PWRCTL_SELFREF_EN); +} + -+void ddr_sr_mode_hsr(void) ++static void ddr_sr_mode_hsr(void) +{ + uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; + uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -9076,6 +10373,57 @@ index 325c0b8..63f254f 100644 + DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); +} + ++enum stm32mp1_ddr_sr_mode ddr_read_sr_mode(void) ++{ ++ uint32_t pwrctl = mmio_read_32(stm32mp_ddrctrl_base() + DDRCTRL_PWRCTL); ++ ++ switch (pwrctl & (DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE | ++ DDRCTRL_PWRCTL_SELFREF_EN)) { ++ case 0U: ++ return DDR_SSR_MODE; ++ ++ case DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE: ++ return DDR_HSR_MODE; ++ ++ case DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE | DDRCTRL_PWRCTL_SELFREF_EN: ++ return DDR_ASR_MODE; ++ ++ default: ++ return DDR_SR_MODE_INVALID; ++ } ++} ++ ++void ddr_set_sr_mode(enum stm32mp1_ddr_sr_mode mode) ++{ ++ switch (mode) { ++ case DDR_SSR_MODE: ++ ddr_sr_mode_ssr(); ++ break; ++ ++ case DDR_HSR_MODE: ++ ddr_sr_mode_hsr(); ++ break; ++ ++ case DDR_ASR_MODE: ++ ddr_sr_mode_asr(); ++ break; ++ ++ default: ++ ERROR("Unknown Self Refresh mode\n"); ++ panic(); ++ } ++} ++ ++void ddr_save_sr_mode(void) ++{ ++ saved_ddr_sr_mode = ddr_read_sr_mode(); ++} ++ ++void ddr_restore_sr_mode(void) ++{ ++ ddr_set_sr_mode(saved_ddr_sr_mode); ++} ++ +bool ddr_is_nonsecured_area(uintptr_t address, uint32_t length) +{ + uint64_t pa; @@ -9103,71 +10451,23 @@ index 325c0b8..63f254f 100644 + } + + return false; - } ++} diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c -index 6d515ec..82b8fda 100644 +index 4ae55fcc7..e6652e504 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c -@@ -7,36 +7,30 @@ - #include - #include - #include --#include - #include - #include - #include - #include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include - - #define DDR_PATTERN 0xAAAAAAAAU - #define DDR_ANTIPATTERN 0x55555555U - - static struct ddr_info ddr_priv_data; - --int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) -+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) - { - unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; - - ddr_enable_clock(); - -- ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC); -+ ddrphy_clk = stm32mp_clk_get_rate(DDRPHYC); - -- VERBOSE("DDR: mem_speed (%d MHz), RCC %ld MHz\n", -- mem_speed, ddrphy_clk / 1000U / 1000U); -+ VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n", -+ mem_speed, ddrphy_clk / 1000U); - -- mem_speed_hz = (uint32_t)mem_speed * 1000U * 1000U; -+ mem_speed_hz = mem_speed * 1000U; - - /* Max 10% frequency delta */ - if (ddrphy_clk > mem_speed_hz) { -@@ -44,15 +38,35 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) - } else { - ddr_clk = mem_speed_hz - ddrphy_clk; - } -- if (ddr_clk > mem_speed_hz) { -- ERROR("DDR expected freq %d MHz, current is %ld MHz\n", -- mem_speed, ddrphy_clk / 1000U / 1000U); -+ if (ddr_clk > (mem_speed_hz / 10)) { -+ ERROR("DDR expected freq %d kHz, current is %ld kHz\n", -+ mem_speed, ddrphy_clk / 1000U); - return -1; - } +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ +@@ -49,6 +49,26 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) return 0; } - /******************************************************************************* ++/******************************************************************************* + * This function tests a simple read/write access to the DDR. + * Note that the previous content is restored after test. + * Returns 0 if success, and address value else. @@ -9187,103 +10487,14 @@ index 6d515ec..82b8fda 100644 + return 0; +} + -+/******************************************************************************* + /******************************************************************************* * This function tests the DDR data bus wiring. * This is inspired from the Data Bus Test algorithm written by Michael Barr - * in "Programming Embedded Systems in C and C++" book. -@@ -65,10 +79,10 @@ static uint32_t ddr_test_data_bus(void) - uint32_t pattern; - - for (pattern = 1U; pattern != 0U; pattern <<= 1) { -- mmio_write_32(STM32MP1_DDR_BASE, pattern); -+ mmio_write_32(STM32MP_DDR_BASE, pattern); - -- if (mmio_read_32(STM32MP1_DDR_BASE) != pattern) { -- return (uint32_t)STM32MP1_DDR_BASE; -+ if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { -+ return (uint32_t)STM32MP_DDR_BASE; - } - } - -@@ -92,44 +106,44 @@ static uint32_t ddr_test_addr_bus(void) - /* Write the default pattern at each of the power-of-two offsets. */ - for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; - offset <<= 1) { -- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)offset, -+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset, - DDR_PATTERN); - } - - /* Check for address bits stuck high. */ -- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, -+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, - DDR_ANTIPATTERN); - - for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; - offset <<= 1) { -- if (mmio_read_32(STM32MP1_DDR_BASE + (uint32_t)offset) != -+ if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) != - DDR_PATTERN) { -- return (uint32_t)(STM32MP1_DDR_BASE + offset); -+ return (uint32_t)(STM32MP_DDR_BASE + offset); - } - } - -- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); -+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); - - /* Check for address bits stuck low or shorted. */ - for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U; - testoffset <<= 1) { -- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, -+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, - DDR_ANTIPATTERN); - -- if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) { -- return STM32MP1_DDR_BASE; -+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { -+ return STM32MP_DDR_BASE; - } - - for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; - offset <<= 1) { -- if ((mmio_read_32(STM32MP1_DDR_BASE + -+ if ((mmio_read_32(STM32MP_DDR_BASE + - (uint32_t)offset) != DDR_PATTERN) && - (offset != testoffset)) { -- return (uint32_t)(STM32MP1_DDR_BASE + offset); -+ return (uint32_t)(STM32MP_DDR_BASE + offset); - } - } - -- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, -+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, - DDR_PATTERN); - } - -@@ -147,13 +161,13 @@ static uint32_t ddr_check_size(void) - { - uint32_t offset = sizeof(uint32_t); - -- mmio_write_32(STM32MP1_DDR_BASE, DDR_PATTERN); -+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); - -- while (offset < STM32MP1_DDR_MAX_SIZE) { -- mmio_write_32(STM32MP1_DDR_BASE + offset, DDR_ANTIPATTERN); -+ while (offset < STM32MP_DDR_MAX_SIZE) { -+ mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); - dsb(); - -- if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) { -+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { - break; - } - -@@ -171,8 +185,12 @@ static int stm32mp1_ddr_setup(void) +@@ -168,23 +188,30 @@ static int stm32mp1_ddr_setup(void) int ret; struct stm32mp1_ddr_config config; int node, len; -- uint32_t tamp_clk_off = 0, uret, idx; +- uint32_t uret, idx; + uint32_t magic, uret, idx; void *fdt; + uint32_t bkpr_core1_addr = @@ -9291,69 +10502,88 @@ index 6d515ec..82b8fda 100644 + uint32_t bkpr_core1_magic = + tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); - #define PARAM(x, y) \ +-#define PARAM(x, y) \ ++#define PARAM(x, y, z) \ { \ -@@ -208,11 +226,16 @@ static int stm32mp1_ddr_setup(void) + .name = x, \ + .offset = offsetof(struct stm32mp1_ddr_config, y), \ +- .size = sizeof(config.y) / sizeof(uint32_t) \ ++ .size = sizeof(config.y) / sizeof(uint32_t), \ ++ .present = z \ + } + +-#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) +-#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) ++#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x, NULL) ++#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x, NULL) ++#define PHY_PARAM_OPT(x) PARAM("st,phy-"#x, p_##x, &config.p_##x##_present) + + const struct { + const char *name; /* Name in DT */ + const uint32_t offset; /* Offset in config struct */ + const uint32_t size; /* Size of parameters */ ++ bool * const present; /* presence indication for opt */ + } param[] = { + CTL_PARAM(reg), + CTL_PARAM(timing), +@@ -192,16 +219,15 @@ static int stm32mp1_ddr_setup(void) + CTL_PARAM(perf), + PHY_PARAM(reg), + PHY_PARAM(timing), +- PHY_PARAM(cal) ++ PHY_PARAM_OPT(cal) + }; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); ++ node = dt_get_node_by_compatible(DT_DDR_COMPAT); + if (node < 0) { +- ERROR("%s: Cannot read DDR node in DT\n", __func__); return -EINVAL; } -- config.info.speed = -- (uint16_t)fdt_read_uint32_default(node, "st,mem-speed", -- STM32MP1_DDR_SPEED_DFLT); -- config.info.size = fdt_read_uint32_default(node, "st,mem-size", -- STM32MP1_DDR_SIZE_DFLT); -+ config.info.speed = fdt_read_uint32_default(node, "st,mem-speed", 0); -+ if (!config.info.speed) { -+ VERBOSE("%s: no st,mem-speed\n", __func__); -+ return -EINVAL; -+ } -+ config.info.size = fdt_read_uint32_default(node, "st,mem-size", 0); -+ if (!config.info.size) { -+ VERBOSE("%s: no st,mem-size\n", __func__); -+ return -EINVAL; -+ } - config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len); - if (config.info.name == NULL) { - VERBOSE("%s: no st,mem-name\n", __func__); -@@ -222,7 +245,7 @@ static int stm32mp1_ddr_setup(void) +@@ -230,13 +256,34 @@ static int stm32mp1_ddr_setup(void) - for (idx = 0; idx < ARRAY_SIZE(param); idx++) { - ret = fdt_read_uint32_array(node, param[idx].name, -- (void *)((uint32_t)&config + -+ (void *)((uintptr_t)&config + - param[idx].offset), - param[idx].size); - -@@ -235,19 +258,18 @@ 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); ++ if ((ret != 0) && ++ ((ret != -FDT_ERR_NOTFOUND) || ++ (param[idx].present == NULL))) { ++ ERROR("%s: Cannot read %s, error=%d\n", ++ __func__, param[idx].name, ret); + return -EINVAL; } ++ if (param[idx].present != NULL) { ++ /* save presence of optional parameters */ ++ *(param[idx].present) = true; ++ if (ret == -FDT_ERR_NOTFOUND) { ++ *(param[idx].present) = false; ++ } ++ } } -- if (!stm32mp1_clk_is_enabled(RTCAPB)) { -- tamp_clk_off = 1; -- if (stm32mp1_clk_enable(RTCAPB) != 0) { -- return -EINVAL; -- } -- } + config.self_refresh = false; - -- if (tamp_clk_off != 0U) { -- if (stm32mp1_clk_disable(RTCAPB) != 0) { -- return -EINVAL; -- } ++ + stm32mp_clk_enable(RTCAPB); + + magic = mmio_read_32(bkpr_core1_magic); + if (magic == BOOT_API_A7_CORE0_MAGIC_NUMBER) { + config.self_refresh = true; + config.zdata = stm32_get_zdata_from_context(); - } - ++ } ++ + stm32mp_clk_disable(RTCAPB); + /* Disable axidcg clock gating during init */ mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); -@@ -256,36 +278,60 @@ static int stm32mp1_ddr_setup(void) +@@ -245,36 +292,58 @@ static int stm32mp1_ddr_setup(void) /* Enable axidcg clock gating */ mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); @@ -9370,12 +10600,8 @@ index 6d515ec..82b8fda 100644 VERBOSE("%s : ram size(%x, %x)\n", __func__, (uint32_t)priv->info.base, (uint32_t)priv->info.size); +- write_sctlr(read_sctlr() & ~SCTLR_C_BIT); - dcsw_op_all(DC_OP_CISW); -+#ifndef DCACHE_OFF - write_sctlr(read_sctlr() & ~SCTLR_C_BIT); -+ dcsw_op_all(DC_OP_CISW); -+#endif -+ + if (config.self_refresh) { + uret = ddr_test_rw_access(); + if (uret != 0U) { @@ -9426,56 +10652,42 @@ index 6d515ec..82b8fda 100644 + } } -+#ifndef DCACHE_OFF - write_sctlr(read_sctlr() | SCTLR_C_BIT); -+#endif +- write_sctlr(read_sctlr() | SCTLR_C_BIT); ++ /* ++ * Initialization sequence has configured DDR registers with settings. ++ * The Self Refresh (SR) mode corresponding to these settings has now ++ * to be set. ++ */ ++ ddr_set_sr_mode(ddr_read_sr_mode()); return 0; } -@@ -296,12 +342,12 @@ int stm32mp1_ddr_probe(void) - - VERBOSE("STM32MP DDR probe\n"); - -- priv->ctl = (struct stm32mp1_ddrctl *)DDRCTRL_BASE; -- priv->phy = (struct stm32mp1_ddrphy *)DDRPHYC_BASE; -- priv->pwr = PWR_BASE; -- priv->rcc = RCC_BASE; -+ priv->ctl = (struct stm32mp1_ddrctl *)stm32mp_ddrctrl_base(); -+ priv->phy = (struct stm32mp1_ddrphy *)stm32mp_ddrphyc_base(); -+ priv->pwr = stm32mp_pwr_base(); -+ priv->rcc = stm32mp_rcc_base(); - -- priv->info.base = STM32MP1_DDR_BASE; -+ priv->info.base = STM32MP_DDR_BASE; - priv->info.size = 0; - - return stm32mp1_ddr_setup(); diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c new file mode 100644 -index 0000000..06c3282 +index 000000000..8795c6e00 --- /dev/null +++ b/drivers/st/etzpc/etzpc.c @@ -0,0 +1,310 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2018, STMicroelectronics ++ * Copyright (c) 2017-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 + +/* Device Tree related definitions */ +#define ETZPC_COMPAT "st,stm32-etzpc" @@ -9766,751 +10978,947 @@ index 0000000..06c3282 + + return etzpc_dt_conf_decprot(node); +} -diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c -index 200b473..fc0dce8 100644 ---- a/drivers/st/gpio/stm32_gpio.c -+++ b/drivers/st/gpio/stm32_gpio.c -@@ -4,83 +4,280 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - +diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c +new file mode 100644 +index 000000000..e976c3bdd +--- /dev/null ++++ b/drivers/st/fmc/stm32_fmc2_nand.c +@@ -0,0 +1,883 @@ ++/* ++ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ +#include - #include - #include +#include ++#include ++#include ++ +#include - #include ++ +#include - #include - #include -+#include -+#include -+#include - --static bool check_gpio(uint32_t bank, uint32_t pin) -+#define DT_GPIO_BANK_SHIFT 12 -+#define DT_GPIO_BANK_MASK 0x1F000U -+#define DT_GPIO_PIN_SHIFT 8 -+#define DT_GPIO_PIN_MASK 0xF00U -+#define DT_GPIO_MODE_MASK 0xFFU + -+/******************************************************************************* -+ * This function gets GPIO bank node in DT. -+ * Returns node offset if status is okay in DT, else return 0 -+ ******************************************************************************/ -+static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) - { -- if (pin > GPIO_PIN_MAX) { -- ERROR("%s: wrong pin number (%d)\n", __func__, pin); -- return false; -- } -+ int pinctrl_subnode; ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { -+ uint32_t bank_offset; -+ const fdt32_t *cuint; ++#define TIMEOUT_US_1MS U(1000) + -+ if (fdt_getprop(fdt, pinctrl_subnode, -+ "gpio-controller", NULL) == NULL) { -+ continue; -+ } - -- if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) { -- ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank); -- return false; -+ cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); -+ if (cuint == NULL) { -+ continue; ++/* FMC2 Compatibility */ ++#define DT_FMC2_COMPAT "st,stm32mp15-fmc2" ++#define MAX_CS 2U ++ ++/* FMC2 Controller Registers */ ++#define FMC2_BCR1 0x00U ++#define FMC2_PCR 0x80U ++#define FMC2_SR 0x84U ++#define FMC2_PMEM 0x88U ++#define FMC2_PATT 0x8CU ++#define FMC2_HECCR 0x94U ++#define FMC2_BCHISR 0x254U ++#define FMC2_BCHDSR0 0x27CU ++#define FMC2_BCHDSR1 0x280U ++#define FMC2_BCHDSR2 0x284U ++#define FMC2_BCHDSR3 0x288U ++#define FMC2_BCHDSR4 0x28CU ++ ++/* FMC2_BCR1 register */ ++#define FMC2_BCR1_FMC2EN BIT(31) ++/* FMC2_PCR register */ ++#define FMC2_PCR_PWAITEN BIT(1) ++#define FMC2_PCR_PBKEN BIT(2) ++#define FMC2_PCR_PWID_MASK GENMASK_32(5, 4) ++#define FMC2_PCR_PWID(x) (((x) << 4) & FMC2_PCR_PWID_MASK) ++#define FMC2_PCR_PWID_8 0x0U ++#define FMC2_PCR_PWID_16 0x1U ++#define FMC2_PCR_ECCEN BIT(6) ++#define FMC2_PCR_ECCALG BIT(8) ++#define FMC2_PCR_TCLR_MASK GENMASK_32(12, 9) ++#define FMC2_PCR_TCLR(x) (((x) << 9) & FMC2_PCR_TCLR_MASK) ++#define FMC2_PCR_TCLR_DEFAULT 0xFU ++#define FMC2_PCR_TAR_MASK GENMASK_32(16, 13) ++#define FMC2_PCR_TAR(x) (((x) << 13) & FMC2_PCR_TAR_MASK) ++#define FMC2_PCR_TAR_DEFAULT 0xFU ++#define FMC2_PCR_ECCSS_MASK GENMASK_32(19, 17) ++#define FMC2_PCR_ECCSS(x) (((x) << 17) & FMC2_PCR_ECCSS_MASK) ++#define FMC2_PCR_ECCSS_512 0x1U ++#define FMC2_PCR_ECCSS_2048 0x3U ++#define FMC2_PCR_BCHECC BIT(24) ++#define FMC2_PCR_WEN BIT(25) ++/* FMC2_SR register */ ++#define FMC2_SR_NWRF BIT(6) ++/* FMC2_PMEM register*/ ++#define FMC2_PMEM_MEMSET(x) (((x) & GENMASK_32(7, 0)) << 0) ++#define FMC2_PMEM_MEMWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) ++#define FMC2_PMEM_MEMHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) ++#define FMC2_PMEM_MEMHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) ++#define FMC2_PMEM_DEFAULT 0x0A0A0A0AU ++/* FMC2_PATT register */ ++#define FMC2_PATT_ATTSET(x) (((x) & GENMASK_32(7, 0)) << 0) ++#define FMC2_PATT_ATTWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) ++#define FMC2_PATT_ATTHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) ++#define FMC2_PATT_ATTHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) ++#define FMC2_PATT_DEFAULT 0x0A0A0A0AU ++/* FMC2_BCHISR register */ ++#define FMC2_BCHISR_DERF BIT(1) ++/* FMC2_BCHDSR0 register */ ++#define FMC2_BCHDSR0_DUE BIT(0) ++#define FMC2_BCHDSR0_DEF BIT(1) ++#define FMC2_BCHDSR0_DEN_MASK GENMASK_32(7, 4) ++#define FMC2_BCHDSR0_DEN_SHIFT 4U ++/* FMC2_BCHDSR1 register */ ++#define FMC2_BCHDSR1_EBP1_MASK GENMASK_32(12, 0) ++#define FMC2_BCHDSR1_EBP2_MASK GENMASK_32(28, 16) ++#define FMC2_BCHDSR1_EBP2_SHIFT 16U ++/* FMC2_BCHDSR2 register */ ++#define FMC2_BCHDSR2_EBP3_MASK GENMASK_32(12, 0) ++#define FMC2_BCHDSR2_EBP4_MASK GENMASK_32(28, 16) ++#define FMC2_BCHDSR2_EBP4_SHIFT 16U ++/* FMC2_BCHDSR3 register */ ++#define FMC2_BCHDSR3_EBP5_MASK GENMASK_32(12, 0) ++#define FMC2_BCHDSR3_EBP6_MASK GENMASK_32(28, 16) ++#define FMC2_BCHDSR3_EBP6_SHIFT 16U ++/* FMC2_BCHDSR4 register */ ++#define FMC2_BCHDSR4_EBP7_MASK GENMASK_32(12, 0) ++#define FMC2_BCHDSR4_EBP8_MASK GENMASK_32(28, 16) ++#define FMC2_BCHDSR4_EBP8_SHIFT 16U ++ ++/* Timings */ ++#define FMC2_THIZ 0x01U ++#define FMC2_TIO 8000U ++#define FMC2_TSYNC 3000U ++#define FMC2_PCR_TIMING_MASK GENMASK_32(3, 0) ++#define FMC2_PMEM_PATT_TIMING_MASK GENMASK_32(7, 0) ++ ++#define FMC2_BBM_LEN 2U ++#define FMC2_MAX_ECC_BYTES 14U ++#define TIMEOUT_US_10_MS 10000U ++#define FMC2_PSEC_PER_MSEC (1000UL * 1000UL * 1000UL) ++ ++enum stm32_fmc2_ecc { ++ FMC2_ECC_HAM = 1U, ++ FMC2_ECC_BCH4 = 4U, ++ FMC2_ECC_BCH8 = 8U ++}; ++ ++struct stm32_fmc2_cs_reg { ++ uintptr_t data_base; ++ uintptr_t cmd_base; ++ uintptr_t addr_base; ++}; ++ ++struct stm32_fmc2_nand_timings { ++ uint8_t tclr; ++ uint8_t tar; ++ uint8_t thiz; ++ uint8_t twait; ++ uint8_t thold_mem; ++ uint8_t tset_mem; ++ uint8_t thold_att; ++ uint8_t tset_att; ++}; ++ ++struct stm32_fmc2_nfc { ++ uintptr_t reg_base; ++ struct stm32_fmc2_cs_reg cs[MAX_CS]; ++ unsigned long clock_id; ++ unsigned int reset_id; ++ uint8_t cs_sel; ++}; ++ ++static struct stm32_fmc2_nfc stm32_fmc2; ++ ++static uintptr_t fmc2_base(void) ++{ ++ return stm32_fmc2.reg_base; ++} ++ ++static void stm32_fmc2_nand_setup_timing(void) ++{ ++ struct stm32_fmc2_nand_timings tims; ++ unsigned long hclk = stm32mp_clk_get_rate(stm32_fmc2.clock_id); ++ unsigned long hclkp = FMC2_PSEC_PER_MSEC / (hclk / 1000U); ++ unsigned long timing, tar, tclr, thiz, twait; ++ unsigned long tset_mem, tset_att, thold_mem, thold_att; ++ uint32_t pcr, pmem, patt; ++ ++ tar = MAX(hclkp, NAND_TAR_MIN); ++ timing = div_round_up(tar, hclkp) - 1U; ++ tims.tar = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); ++ ++ tclr = MAX(hclkp, NAND_TCLR_MIN); ++ timing = div_round_up(tclr, hclkp) - 1U; ++ tims.tclr = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); ++ ++ tims.thiz = FMC2_THIZ; ++ thiz = (tims.thiz + 1U) * hclkp; ++ ++ /* ++ * tWAIT > tRP ++ * tWAIT > tWP ++ * tWAIT > tREA + tIO ++ */ ++ twait = MAX(hclkp, NAND_TRP_MIN); ++ twait = MAX(twait, NAND_TWP_MIN); ++ twait = MAX(twait, NAND_TREA_MAX + FMC2_TIO); ++ timing = div_round_up(twait, hclkp); ++ tims.twait = CLAMP(timing, 1UL, ++ (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); ++ ++ /* ++ * tSETUP_MEM > tCS - tWAIT ++ * tSETUP_MEM > tALS - tWAIT ++ * tSETUP_MEM > tDS - (tWAIT - tHIZ) ++ */ ++ tset_mem = hclkp; ++ if ((twait < NAND_TCS_MIN) && (tset_mem < (NAND_TCS_MIN - twait))) { ++ tset_mem = NAND_TCS_MIN - twait; ++ } ++ if ((twait < NAND_TALS_MIN) && (tset_mem < (NAND_TALS_MIN - twait))) { ++ tset_mem = NAND_TALS_MIN - twait; ++ } ++ if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && ++ (tset_mem < (NAND_TDS_MIN - (twait - thiz)))) { ++ tset_mem = NAND_TDS_MIN - (twait - thiz); ++ } ++ timing = div_round_up(tset_mem, hclkp); ++ tims.tset_mem = CLAMP(timing, 1UL, ++ (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); ++ ++ /* ++ * tHOLD_MEM > tCH ++ * tHOLD_MEM > tREH - tSETUP_MEM ++ * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) ++ */ ++ thold_mem = MAX(hclkp, NAND_TCH_MIN); ++ if ((tset_mem < NAND_TREH_MIN) && ++ (thold_mem < (NAND_TREH_MIN - tset_mem))) { ++ thold_mem = NAND_TREH_MIN - tset_mem; ++ } ++ if (((tset_mem + twait) < NAND_TRC_MIN) && ++ (thold_mem < (NAND_TRC_MIN - (tset_mem + twait)))) { ++ thold_mem = NAND_TRC_MIN - (tset_mem + twait); ++ } ++ if (((tset_mem + twait) < NAND_TWC_MIN) && ++ (thold_mem < (NAND_TWC_MIN - (tset_mem + twait)))) { ++ thold_mem = NAND_TWC_MIN - (tset_mem + twait); ++ } ++ timing = div_round_up(thold_mem, hclkp); ++ tims.thold_mem = CLAMP(timing, 1UL, ++ (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); ++ ++ /* ++ * tSETUP_ATT > tCS - tWAIT ++ * tSETUP_ATT > tCLS - tWAIT ++ * tSETUP_ATT > tALS - tWAIT ++ * tSETUP_ATT > tRHW - tHOLD_MEM ++ * tSETUP_ATT > tDS - (tWAIT - tHIZ) ++ */ ++ tset_att = hclkp; ++ if ((twait < NAND_TCS_MIN) && (tset_att < (NAND_TCS_MIN - twait))) { ++ tset_att = NAND_TCS_MIN - twait; ++ } ++ if ((twait < NAND_TCLS_MIN) && (tset_att < (NAND_TCLS_MIN - twait))) { ++ tset_att = NAND_TCLS_MIN - twait; ++ } ++ if ((twait < NAND_TALS_MIN) && (tset_att < (NAND_TALS_MIN - twait))) { ++ tset_att = NAND_TALS_MIN - twait; ++ } ++ if ((thold_mem < NAND_TRHW_MIN) && ++ (tset_att < (NAND_TRHW_MIN - thold_mem))) { ++ tset_att = NAND_TRHW_MIN - thold_mem; ++ } ++ if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && ++ (tset_att < (NAND_TDS_MIN - (twait - thiz)))) { ++ tset_att = NAND_TDS_MIN - (twait - thiz); ++ } ++ timing = div_round_up(tset_att, hclkp); ++ tims.tset_att = CLAMP(timing, 1UL, ++ (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); ++ ++ /* ++ * tHOLD_ATT > tALH ++ * tHOLD_ATT > tCH ++ * tHOLD_ATT > tCLH ++ * tHOLD_ATT > tCOH ++ * tHOLD_ATT > tDH ++ * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM ++ * tHOLD_ATT > tADL - tSETUP_MEM ++ * tHOLD_ATT > tWH - tSETUP_MEM ++ * tHOLD_ATT > tWHR - tSETUP_MEM ++ * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) ++ * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) ++ */ ++ thold_att = MAX(hclkp, NAND_TALH_MIN); ++ thold_att = MAX(thold_att, NAND_TCH_MIN); ++ thold_att = MAX(thold_att, NAND_TCLH_MIN); ++ thold_att = MAX(thold_att, NAND_TCOH_MIN); ++ thold_att = MAX(thold_att, NAND_TDH_MIN); ++ if (((NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC) > tset_mem) && ++ (thold_att < (NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem))) { ++ thold_att = NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem; ++ } ++ if ((tset_mem < NAND_TADL_MIN) && ++ (thold_att < (NAND_TADL_MIN - tset_mem))) { ++ thold_att = NAND_TADL_MIN - tset_mem; ++ } ++ if ((tset_mem < NAND_TWH_MIN) && ++ (thold_att < (NAND_TWH_MIN - tset_mem))) { ++ thold_att = NAND_TWH_MIN - tset_mem; ++ } ++ if ((tset_mem < NAND_TWHR_MIN) && ++ (thold_att < (NAND_TWHR_MIN - tset_mem))) { ++ thold_att = NAND_TWHR_MIN - tset_mem; ++ } ++ if (((tset_att + twait) < NAND_TRC_MIN) && ++ (thold_att < (NAND_TRC_MIN - (tset_att + twait)))) { ++ thold_att = NAND_TRC_MIN - (tset_att + twait); ++ } ++ if (((tset_att + twait) < NAND_TWC_MIN) && ++ (thold_att < (NAND_TWC_MIN - (tset_att + twait)))) { ++ thold_att = NAND_TWC_MIN - (tset_att + twait); ++ } ++ timing = div_round_up(thold_att, hclkp); ++ tims.thold_att = CLAMP(timing, 1UL, ++ (unsigned long)FMC2_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); ++ ++ /* Set tclr/tar timings */ ++ pcr = mmio_read_32(fmc2_base() + FMC2_PCR); ++ pcr &= ~FMC2_PCR_TCLR_MASK; ++ pcr |= FMC2_PCR_TCLR(tims.tclr); ++ pcr &= ~FMC2_PCR_TAR_MASK; ++ pcr |= FMC2_PCR_TAR(tims.tar); ++ ++ /* Set tset/twait/thold/thiz timings in common bank */ ++ pmem = FMC2_PMEM_MEMSET(tims.tset_mem); ++ pmem |= FMC2_PMEM_MEMWAIT(tims.twait); ++ pmem |= FMC2_PMEM_MEMHOLD(tims.thold_mem); ++ pmem |= FMC2_PMEM_MEMHIZ(tims.thiz); ++ ++ /* Set tset/twait/thold/thiz timings in attribute bank */ ++ patt = FMC2_PATT_ATTSET(tims.tset_att); ++ patt |= FMC2_PATT_ATTWAIT(tims.twait); ++ patt |= FMC2_PATT_ATTHOLD(tims.thold_att); ++ patt |= FMC2_PATT_ATTHIZ(tims.thiz); ++ ++ mmio_write_32(fmc2_base() + FMC2_PCR, pcr); ++ mmio_write_32(fmc2_base() + FMC2_PMEM, pmem); ++ mmio_write_32(fmc2_base() + FMC2_PATT, patt); ++} ++ ++static void stm32_fmc2_set_buswidth_16(bool set) ++{ ++ mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_PWID_MASK, ++ (set ? FMC2_PCR_PWID(FMC2_PCR_PWID_16) : 0U)); ++} ++ ++static void stm32_fmc2_set_ecc(bool enable) ++{ ++ mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_ECCEN, ++ (enable ? FMC2_PCR_ECCEN : 0U)); ++} ++ ++static int stm32_fmc2_ham_correct(uint8_t *buffer, uint8_t *eccbuffer, ++ uint8_t *ecc) ++{ ++ uint8_t xor_ecc_ones; ++ uint16_t xor_ecc_1b, xor_ecc_2b, xor_ecc_3b; ++ union { ++ uint32_t val; ++ uint8_t bytes[4]; ++ } xor_ecc; ++ ++ /* Page size--------ECC_Code Size ++ * 256---------------22 bits LSB (ECC_CODE & 0x003FFFFF) ++ * 512---------------24 bits (ECC_CODE & 0x00FFFFFF) ++ * 1024--------------26 bits (ECC_CODE & 0x03FFFFFF) ++ * 2048--------------28 bits (ECC_CODE & 0x0FFFFFFF) ++ * 4096--------------30 bits (ECC_CODE & 0x3FFFFFFF) ++ * 8192--------------32 bits (ECC_CODE & 0xFFFFFFFF) ++ */ ++ ++ /* For Page size 512, ECC_Code size 24 bits */ ++ xor_ecc_1b = ecc[0] ^ eccbuffer[0]; ++ xor_ecc_2b = ecc[1] ^ eccbuffer[1]; ++ xor_ecc_3b = ecc[2] ^ eccbuffer[2]; ++ ++ xor_ecc.val = 0U; ++ xor_ecc.bytes[2] = xor_ecc_3b; ++ xor_ecc.bytes[1] = xor_ecc_2b; ++ xor_ecc.bytes[0] = xor_ecc_1b; ++ ++ if (xor_ecc.val == 0U) { ++ return 0; /* No Error */ ++ } ++ ++ xor_ecc_ones = __builtin_popcount(xor_ecc.val); ++ if (xor_ecc_ones < 23U) { ++ if (xor_ecc_ones == 12U) { ++ uint16_t bit_address, byte_address; ++ ++ /* Correctable ERROR */ ++ bit_address = ((xor_ecc_1b >> 1) & BIT(0)) | ++ ((xor_ecc_1b >> 2) & BIT(1)) | ++ ((xor_ecc_1b >> 3) & BIT(2)); ++ ++ byte_address = ((xor_ecc_1b >> 7) & BIT(0)) | ++ ((xor_ecc_2b) & BIT(1)) | ++ ((xor_ecc_2b >> 1) & BIT(2)) | ++ ((xor_ecc_2b >> 2) & BIT(3)) | ++ ((xor_ecc_2b >> 3) & BIT(4)) | ++ ((xor_ecc_3b << 4) & BIT(5)) | ++ ((xor_ecc_3b << 3) & BIT(6)) | ++ ((xor_ecc_3b << 2) & BIT(7)) | ++ ((xor_ecc_3b << 1) & BIT(8)); ++ ++ /* Correct bit error in the data */ ++ buffer[byte_address] = ++ buffer[byte_address] ^ BIT(bit_address); ++ VERBOSE("Hamming: 1 ECC error corrected\n"); ++ ++ return 0; + } + -+ bank_offset = stm32_get_gpio_bank_offset(bank); ++ /* Non Correctable ERROR */ ++ ERROR("%s: Uncorrectable ECC Errors\n", __func__); ++ return -1; ++ } + -+ if ((fdt32_to_cpu(*cuint) == bank_offset) && -+ (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) { -+ return pinctrl_subnode; ++ /* ECC ERROR */ ++ ERROR("%s: Hamming correction error\n", __func__); ++ return -1; ++} ++ ++ ++static int stm32_fmc2_ham_calculate(uint8_t *buffer, uint8_t *ecc) ++{ ++ uint32_t heccr; ++ uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); ++ ++ while ((mmio_read_32(fmc2_base() + FMC2_SR) & FMC2_SR_NWRF) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ return -ETIMEDOUT; + } - } - -- return true; ++ } ++ ++ heccr = mmio_read_32(fmc2_base() + FMC2_HECCR); ++ ++ ecc[0] = heccr; ++ ecc[1] = heccr >> 8; ++ ecc[2] = heccr >> 16; ++ ++ /* Disable ECC */ ++ stm32_fmc2_set_ecc(false); ++ + return 0; - } - --void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, -- uint32_t pull, uint32_t alternate) -+/******************************************************************************* -+ * This function gets the pin settings from DT information. -+ * When analyze and parsing is done, set the GPIO registers. -+ * Returns 0 on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+static int dt_set_gpio_config(void *fdt, int node, uint8_t status) - { -- volatile uint32_t bank_address; -+ const fdt32_t *cuint, *slewrate; -+ int len; -+ int pinctrl_node; -+ uint32_t i; -+ uint32_t speed = GPIO_SPEED_LOW; -+ uint32_t pull = GPIO_NO_PULL; ++} + -+ cuint = fdt_getprop(fdt, node, "pinmux", &len); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; ++static int stm32_fmc2_bch_correct(uint8_t *buffer, unsigned int eccsize) ++{ ++ uint32_t bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4; ++ uint16_t pos[8]; ++ int i, den; ++ uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); ++ ++ while ((mmio_read_32(fmc2_base() + FMC2_BCHISR) & ++ FMC2_BCHISR_DERF) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ return -ETIMEDOUT; ++ } + } + -+ pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); -+ if (pinctrl_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } - -- if (!check_gpio(bank, pin)) { -- return; -+ slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); -+ if (slewrate != NULL) { -+ speed = fdt32_to_cpu(*slewrate); - } - -- if (bank == GPIO_BANK_Z) { -- bank_address = STM32_GPIOZ_BANK; -+ if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { -+ pull = GPIO_PULL_UP; -+ } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { -+ pull = GPIO_PULL_DOWN; - } else { -- bank_address = STM32_GPIOA_BANK + -- (bank * STM32_GPIO_BANK_OFFSET); -+ VERBOSE("No bias configured in node %d\n", node); ++ bchdsr0 = mmio_read_32(fmc2_base() + FMC2_BCHDSR0); ++ bchdsr1 = mmio_read_32(fmc2_base() + FMC2_BCHDSR1); ++ bchdsr2 = mmio_read_32(fmc2_base() + FMC2_BCHDSR2); ++ bchdsr3 = mmio_read_32(fmc2_base() + FMC2_BCHDSR3); ++ bchdsr4 = mmio_read_32(fmc2_base() + FMC2_BCHDSR4); ++ ++ /* Disable ECC */ ++ stm32_fmc2_set_ecc(false); ++ ++ /* No error found */ ++ if ((bchdsr0 & FMC2_BCHDSR0_DEF) == 0U) { ++ return 0; + } + -+ for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { -+ uint32_t pincfg; -+ uint32_t bank; -+ uint32_t pin; -+ uint32_t mode; -+ uint32_t alternate = GPIO_ALTERNATE_(0); -+ int bank_node; -+ int clk; ++ /* Too many errors detected */ ++ if ((bchdsr0 & FMC2_BCHDSR0_DUE) != 0U) { ++ return -EBADMSG; ++ } + -+ pincfg = fdt32_to_cpu(*cuint); -+ cuint++; ++ pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; ++ pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; ++ pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; ++ pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; ++ pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; ++ pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; ++ pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; ++ pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; + -+ bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; ++ den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; ++ for (i = 0; i < den; i++) { ++ if (pos[i] < (eccsize * 8U)) { ++ uint8_t bitmask = BIT(pos[i] % 8U); ++ uint32_t offset = pos[i] / 8U; + -+ pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; -+ -+ mode = pincfg & DT_GPIO_MODE_MASK; -+ -+ switch (mode) { -+ case 0: -+ mode = GPIO_MODE_INPUT; -+ break; -+ case 1 ... 16: -+ alternate = mode - 1U; -+ mode = GPIO_MODE_ALTERNATE; -+ break; -+ case 17: -+ mode = GPIO_MODE_ANALOG; -+ break; -+ default: -+ mode = GPIO_MODE_OUTPUT; -+ break; ++ *(buffer + offset) ^= bitmask; + } -+ -+ if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { -+ mode |= GPIO_OPEN_DRAIN; -+ } -+ -+ bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); -+ if (bank_node == 0) { -+ ERROR("PINCTRL inconsistent in DT\n"); -+ panic(); -+ } -+ -+ clk = fdt_get_clock_id(bank_node); -+ if (clk < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ /* Platform knows the clock: assert it is okay */ -+ assert(clk == stm32_get_gpio_bank_clock(bank)); -+ -+ set_gpio(bank, pin, mode, speed, pull, alternate, status); + } + + return 0; +} + -+/******************************************************************************* -+ * This function gets the pin settings from DT information. -+ * When analyze and parsing is done, set the GPIO registers. -+ * Returns 0 on success and a negative FDT/ERRNO error code on failure. -+ ******************************************************************************/ -+int dt_set_pinctrl_config(int node) ++static void stm32_fmc2_hwctl(struct nand_device *nand) +{ -+ const fdt32_t *cuint; -+ int lenp = 0; -+ uint32_t i; -+ uint8_t status = fdt_get_status(node); -+ void *fdt; ++ stm32_fmc2_set_ecc(false); + -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; ++ if (nand->ecc.max_bit_corr != FMC2_ECC_HAM) { ++ mmio_clrbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_WEN); + } + -+ if (status == DT_DISABLED) { -+ return -FDT_ERR_NOTFOUND; - } - -- mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET, -+ cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; ++ stm32_fmc2_set_ecc(true); ++} ++ ++static int stm32_fmc2_read_page(struct nand_device *nand, ++ unsigned int page, uintptr_t buffer) ++{ ++ unsigned int eccsize = nand->ecc.size; ++ unsigned int eccbytes = nand->ecc.bytes; ++ unsigned int eccsteps = nand->page_size / eccsize; ++ uint8_t ecc_corr[FMC2_MAX_ECC_BYTES]; ++ uint8_t ecc_cal[FMC2_MAX_ECC_BYTES] = {0U}; ++ uint8_t *p; ++ unsigned int i; ++ unsigned int s; ++ int ret; ++ ++ VERBOSE(">%s page %i buffer %lx\n", __func__, page, buffer); ++ ++ ret = nand_read_page_cmd(page, 0U, 0U, 0U); ++ if (ret != 0) { ++ return ret; + } + -+ for (i = 0; i < ((uint32_t)lenp / 4U); i++) { -+ int p_node, p_subnode; ++ for (s = 0U, i = nand->page_size + FMC2_BBM_LEN, p = (uint8_t *)buffer; ++ s < eccsteps; ++ s++, i += eccbytes, p += eccsize) { ++ stm32_fmc2_hwctl(nand); + -+ p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); -+ if (p_node < 0) { -+ return -FDT_ERR_NOTFOUND; ++ /* Read the NAND page sector (512 bytes) */ ++ ret = nand_change_read_column_cmd(s * eccsize, (uintptr_t)p, ++ eccsize); ++ if (ret != 0) { ++ return ret; + } + -+ fdt_for_each_subnode(p_subnode, fdt, p_node) { -+ int ret = dt_set_gpio_config(fdt, p_subnode, status); -+ -+ if (ret < 0) { ++ if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { ++ ret = stm32_fmc2_ham_calculate(p, ecc_cal); ++ if (ret != 0) { + return ret; + } + } + -+ cuint++; ++ /* Read the corresponding ECC bytes */ ++ ret = nand_change_read_column_cmd(i, (uintptr_t)ecc_corr, ++ eccbytes); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Correct the data */ ++ if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { ++ ret = stm32_fmc2_ham_correct(p, ecc_corr, ecc_cal); ++ } else { ++ ret = stm32_fmc2_bch_correct(p, eccsize); ++ } ++ ++ if (ret != 0) { ++ return ret; ++ } + } + + return 0; +} + -+void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, -+ uint32_t pull, uint32_t alternate, uint8_t status) ++static void stm32_fmc2_read_data(struct nand_device *nand, ++ uint8_t *buff, unsigned int length, ++ bool use_bus8) +{ -+ uintptr_t base = stm32_get_gpio_bank_base(bank); -+ int clock = stm32_get_gpio_bank_clock(bank); ++ uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; + -+ assert(pin <= GPIO_PIN_MAX); ++ if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { ++ stm32_fmc2_set_buswidth_16(false); ++ } + -+ stm32mp_clk_enable((unsigned long)clock); ++ if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { ++ *buff = mmio_read_8(data_base); ++ buff += sizeof(uint8_t); ++ length -= sizeof(uint8_t); ++ } + -+ mmio_clrbits_32(base + GPIO_MODE_OFFSET, - ((uint32_t)GPIO_MODE_MASK << (pin << 1))); -- mmio_setbits_32(bank_address + GPIO_MODE_OFFSET, -+ mmio_setbits_32(base + GPIO_MODE_OFFSET, - (mode & ~GPIO_OPEN_DRAIN) << (pin << 1)); - - if ((mode & GPIO_OPEN_DRAIN) != 0U) { -- mmio_setbits_32(bank_address + GPIO_TYPE_OFFSET, -- BIT(pin)); -+ mmio_setbits_32(base + GPIO_TYPE_OFFSET, BIT(pin)); -+ } else { -+ mmio_clrbits_32(base + GPIO_TYPE_OFFSET, BIT(pin)); - } - -- mmio_clrbits_32(bank_address + GPIO_SPEED_OFFSET, -+ mmio_clrbits_32(base + GPIO_SPEED_OFFSET, - ((uint32_t)GPIO_SPEED_MASK << (pin << 1))); -- mmio_setbits_32(bank_address + GPIO_SPEED_OFFSET, speed << (pin << 1)); -+ mmio_setbits_32(base + GPIO_SPEED_OFFSET, speed << (pin << 1)); - -- mmio_clrbits_32(bank_address + GPIO_PUPD_OFFSET, -+ mmio_clrbits_32(base + GPIO_PUPD_OFFSET, - ((uint32_t)GPIO_PULL_MASK << (pin << 1))); -- mmio_setbits_32(bank_address + GPIO_PUPD_OFFSET, pull << (pin << 1)); -+ mmio_setbits_32(base + GPIO_PUPD_OFFSET, pull << (pin << 1)); - - if (pin < GPIO_ALT_LOWER_LIMIT) { -- mmio_clrbits_32(bank_address + GPIO_AFRL_OFFSET, -+ mmio_clrbits_32(base + GPIO_AFRL_OFFSET, - ((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2))); -- mmio_setbits_32(bank_address + GPIO_AFRL_OFFSET, -+ mmio_setbits_32(base + GPIO_AFRL_OFFSET, - alternate << (pin << 2)); - } else { -- mmio_clrbits_32(bank_address + GPIO_AFRH_OFFSET, -+ mmio_clrbits_32(base + GPIO_AFRH_OFFSET, - ((uint32_t)GPIO_ALTERNATE_MASK << - ((pin - GPIO_ALT_LOWER_LIMIT) << 2))); -- mmio_setbits_32(bank_address + GPIO_AFRH_OFFSET, -+ mmio_setbits_32(base + GPIO_AFRH_OFFSET, - alternate << ((pin - GPIO_ALT_LOWER_LIMIT) << - 2)); - } - - VERBOSE("GPIO %u mode set to 0x%x\n", bank, -- mmio_read_32(bank_address + GPIO_MODE_OFFSET)); -+ mmio_read_32(base + GPIO_MODE_OFFSET)); - VERBOSE("GPIO %u speed set to 0x%x\n", bank, -- mmio_read_32(bank_address + GPIO_SPEED_OFFSET)); -+ mmio_read_32(base + GPIO_SPEED_OFFSET)); - VERBOSE("GPIO %u mode pull to 0x%x\n", bank, -- mmio_read_32(bank_address + GPIO_PUPD_OFFSET)); -+ mmio_read_32(base + GPIO_PUPD_OFFSET)); - VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank, -- mmio_read_32(bank_address + GPIO_AFRL_OFFSET)); -+ mmio_read_32(base + GPIO_AFRL_OFFSET)); - VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, -- mmio_read_32(bank_address + GPIO_AFRH_OFFSET)); -+ mmio_read_32(base + GPIO_AFRH_OFFSET)); ++ if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && ++ (length >= sizeof(uint16_t))) { ++ *(uint16_t *)buff = mmio_read_16(data_base); ++ buff += sizeof(uint16_t); ++ length -= sizeof(uint16_t); ++ } + -+ stm32mp_clk_disable((unsigned long)clock); ++ /* 32bit aligned */ ++ while (length >= sizeof(uint32_t)) { ++ *(uint32_t *)buff = mmio_read_32(data_base); ++ buff += sizeof(uint32_t); ++ length -= sizeof(uint32_t); ++ } ++ ++ /* Read remaining bytes */ ++ if (length >= sizeof(uint16_t)) { ++ *(uint16_t *)buff = mmio_read_16(data_base); ++ buff += sizeof(uint16_t); ++ length -= sizeof(uint16_t); ++ } ++ ++ if (length != 0U) { ++ *buff = mmio_read_8(data_base); ++ } ++ ++ if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { ++ /* Reconfigure bus width to 16-bit */ ++ stm32_fmc2_set_buswidth_16(true); ++ } ++} ++ ++static void stm32_fmc2_write_data(struct nand_device *nand, ++ uint8_t *buff, unsigned int length, ++ bool use_bus8) ++{ ++ uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; ++ ++ if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { ++ /* Reconfigure bus width to 8-bit */ ++ stm32_fmc2_set_buswidth_16(false); ++ } ++ ++ if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { ++ mmio_write_8(data_base, *buff); ++ buff += sizeof(uint8_t); ++ length -= sizeof(uint8_t); ++ } ++ ++ if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && ++ (length >= sizeof(uint16_t))) { ++ mmio_write_16(data_base, *(uint16_t *)buff); ++ buff += sizeof(uint16_t); ++ length -= sizeof(uint16_t); ++ } ++ ++ /* 32bits aligned */ ++ while (length >= sizeof(uint32_t)) { ++ mmio_write_32(data_base, *(uint32_t *)buff); ++ buff += sizeof(uint32_t); ++ length -= sizeof(uint32_t); ++ } ++ ++ /* Read remaining bytes */ ++ if (length >= sizeof(uint16_t)) { ++ mmio_write_16(data_base, *(uint16_t *)buff); ++ buff += sizeof(uint16_t); ++ length -= sizeof(uint16_t); ++ } ++ ++ if (length != 0U) { ++ mmio_write_8(data_base, *buff); ++ } ++ ++ if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { ++ /* Reconfigure bus width to 16-bit */ ++ stm32_fmc2_set_buswidth_16(true); ++ } ++} ++ ++static void stm32_fmc2_ctrl_init(void) ++{ ++ uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); ++ uint32_t bcr1 = mmio_read_32(fmc2_base() + FMC2_BCR1); ++ ++ /* Enable wait feature and NAND flash memory bank */ ++ pcr |= FMC2_PCR_PWAITEN; ++ pcr |= FMC2_PCR_PBKEN; ++ ++ /* Set buswidth to 8 bits mode for identification */ ++ pcr &= ~FMC2_PCR_PWID_MASK; ++ ++ /* ECC logic is disabled */ ++ pcr &= ~FMC2_PCR_ECCEN; ++ ++ /* Default mode */ ++ pcr &= ~FMC2_PCR_ECCALG; ++ pcr &= ~FMC2_PCR_BCHECC; ++ pcr &= ~FMC2_PCR_WEN; ++ ++ /* Set default ECC sector size */ ++ pcr &= ~FMC2_PCR_ECCSS_MASK; ++ pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); ++ ++ /* Set default TCLR/TAR timings */ ++ pcr &= ~FMC2_PCR_TCLR_MASK; ++ pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); ++ pcr &= ~FMC2_PCR_TAR_MASK; ++ pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); ++ ++ /* Enable FMC2 controller */ ++ bcr1 |= FMC2_BCR1_FMC2EN; ++ ++ mmio_write_32(fmc2_base() + FMC2_BCR1, bcr1); ++ mmio_write_32(fmc2_base() + FMC2_PCR, pcr); ++ mmio_write_32(fmc2_base() + FMC2_PMEM, FMC2_PMEM_DEFAULT); ++ mmio_write_32(fmc2_base() + FMC2_PATT, FMC2_PATT_DEFAULT); ++} ++ ++static int stm32_fmc2_exec(struct nand_req *req) ++{ ++ int ret = 0; ++ ++ switch (req->type & NAND_REQ_MASK) { ++ case NAND_REQ_CMD: ++ VERBOSE("Write CMD %x\n", (uint8_t)req->type); ++ mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].cmd_base, ++ (uint8_t)req->type); ++ break; ++ case NAND_REQ_ADDR: ++ VERBOSE("Write ADDR %x\n", *(req->addr)); ++ mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].addr_base, ++ *(req->addr)); ++ break; ++ case NAND_REQ_DATAIN: ++ VERBOSE("Read data\n"); ++ stm32_fmc2_read_data(req->nand, req->addr, req->length, ++ ((req->type & NAND_REQ_BUS_WIDTH_8) != ++ 0U)); ++ break; ++ case NAND_REQ_DATAOUT: ++ VERBOSE("Write data\n"); ++ stm32_fmc2_write_data(req->nand, req->addr, req->length, ++ ((req->type & NAND_REQ_BUS_WIDTH_8) != ++ 0U)); ++ break; ++ case NAND_REQ_WAIT: ++ VERBOSE("WAIT Ready\n"); ++ ret = nand_wait_ready(req->delay_ms); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ }; ++ ++ return ret; ++} ++ ++static void stm32_fmc2_setup(struct nand_device *nand) ++{ ++ uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); ++ ++ /* Set buswidth */ ++ pcr &= ~FMC2_PCR_PWID_MASK; ++ if (nand->buswidth == NAND_BUS_WIDTH_16) { ++ pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_16); ++ } ++ ++ if (nand->ecc.mode == NAND_ECC_HW) { ++ nand->mtd_read_page = stm32_fmc2_read_page; ++ ++ pcr &= ~FMC2_PCR_ECCALG; ++ pcr &= ~FMC2_PCR_BCHECC; ++ ++ pcr &= ~FMC2_PCR_ECCSS_MASK; ++ pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); ++ ++ switch (nand->ecc.max_bit_corr) { ++ case FMC2_ECC_HAM: ++ nand->ecc.bytes = 3; ++ break; ++ case FMC2_ECC_BCH8: ++ pcr |= FMC2_PCR_ECCALG; ++ pcr |= FMC2_PCR_BCHECC; ++ nand->ecc.bytes = 13; ++ break; ++ default: ++ /* Use FMC2 ECC BCH4 */ ++ pcr |= FMC2_PCR_ECCALG; ++ nand->ecc.bytes = 7; ++ break; ++ } ++ ++ if ((nand->buswidth & NAND_BUS_WIDTH_16) != 0) { ++ nand->ecc.bytes++; ++ } ++ } ++ ++ mmio_write_32(stm32_fmc2.reg_base + FMC2_PCR, pcr); ++} ++ ++static const struct nand_ctrl_ops ctrl_ops = { ++ .setup = stm32_fmc2_setup, ++ .exec = stm32_fmc2_exec ++}; ++ ++int stm32_fmc2_init(void) ++{ ++ int fmc_node; ++ int fmc_subnode = 0; ++ int nchips = 0; ++ unsigned int i; ++ void *fdt = NULL; ++ const fdt32_t *cuint; ++ struct dt_node_info info; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ fmc_node = dt_get_node(&info, -1, DT_FMC2_COMPAT); ++ if (fmc_node == -FDT_ERR_NOTFOUND) { ++ WARN("No FMC2 node found\n"); ++ return fmc_node; ++ } ++ ++ if (info.status == DT_DISABLED) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ stm32_fmc2.reg_base = info.base; ++ ++ if ((info.clock < 0) || (info.reset < 0)) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ stm32_fmc2.clock_id = (unsigned long)info.clock; ++ stm32_fmc2.reset_id = (unsigned int)info.reset; ++ ++ cuint = fdt_getprop(fdt, fmc_node, "reg", NULL); ++ if (cuint == NULL) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ cuint += 2; ++ ++ for (i = 0U; i < MAX_CS; i++) { ++ stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*cuint); ++ stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 2)); ++ stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 4)); ++ cuint += 6; ++ } ++ ++ /* Pinctrl initialization */ ++ if (dt_set_pinctrl_config(fmc_node) != 0) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ /* Parse flash nodes */ ++ fdt_for_each_subnode(fmc_subnode, fdt, fmc_node) { ++ nchips++; ++ } ++ ++ if (nchips != 1) { ++ WARN("Only one SLC NAND device supported\n"); ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ fdt_for_each_subnode(fmc_subnode, fdt, fmc_node) { ++ /* Get chip select */ ++ cuint = fdt_getprop(fdt, fmc_subnode, "reg", NULL); ++ if (cuint == NULL) { ++ WARN("Chip select not well defined\n"); ++ return -FDT_ERR_BADVALUE; ++ } ++ stm32_fmc2.cs_sel = fdt32_to_cpu(*cuint); ++ VERBOSE("NAND CS %i\n", stm32_fmc2.cs_sel); ++ } ++ ++ /* Enable Clock */ ++ stm32mp_clk_enable(stm32_fmc2.clock_id); ++ ++ /* Reset IP */ ++ if (stm32mp_reset_assert_to(stm32_fmc2.reset_id, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ if (stm32mp_reset_deassert_to(stm32_fmc2.reset_id, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ ++ /* Setup default IP registers */ ++ stm32_fmc2_ctrl_init(); ++ ++ /* Setup default timings */ ++ stm32_fmc2_nand_setup_timing(); ++ ++ /* Init NAND RAW framework */ ++ nand_raw_ctrl_init(&ctrl_ops); ++ ++ return 0; ++} +diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c +index a13c341a8..cdb56ffbe 100644 +--- a/drivers/st/gpio/stm32_gpio.c ++++ b/drivers/st/gpio/stm32_gpio.c +@@ -254,6 +254,12 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, + mmio_read_32(base + GPIO_AFRH_OFFSET)); + + stm32mp_clk_disable(clock); + + if (status == DT_SECURE) { + stm32mp_register_secure_gpio(bank, pin); + } else { + stm32mp_register_non_secure_gpio(bank, pin); + } -+} -+ -+void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) -+{ -+ uintptr_t base = stm32_get_gpio_bank_base(bank); -+ int clock = stm32_get_gpio_bank_clock(bank); -+ -+ assert(pin <= GPIO_PIN_MAX); -+ + } + + void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) +@@ -263,6 +269,8 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) + + assert(pin <= GPIO_PIN_MAX); + + assert(!(secure && stm32mp_gpio_bank_is_non_secure(bank))); + -+ stm32mp_clk_enable((unsigned long)clock); -+ -+ if (secure) { -+ mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); -+ } else { -+ mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); -+ } -+ -+ stm32mp_clk_disable((unsigned long)clock); - } -diff --git a/drivers/st/hash/hash_sec.c b/drivers/st/hash/hash_sec.c -new file mode 100644 -index 0000000..a3c588a ---- /dev/null -+++ b/drivers/st/hash/hash_sec.c -@@ -0,0 +1,369 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define RESET 0 -+ -+#define timer_GetTimeSec() (uint32_t)read_cntpct_el0() -+ -+static void HASH_WriteData(HASH_HandleTypeDef *hHash, const uint8_t *pInBuffer, -+ uint32_t SizeInBytes); -+static void HASH_GetDigest(HASH_HandleTypeDef *hHash, uint8_t *pMsgDigest); -+static uint32_t HASH_WaitBusyClearWithTimeout(HASH_HandleTypeDef *hHash, -+ uint32_t timeout); -+static uint32_t HASH_WaitDcisClearWithTimeout(HASH_HandleTypeDef *hHash, -+ uint32_t timeout); -+ -+/***************************************************************************** -+ * -+ * Function: HASH_SHA256_Init -+ * -+ * Description: Initializes the HASH peripheral -+ * -+ * Parameters: hHash : pointer to a HASH_HandleTypeDef structure that contains -+ * the configuration information for HASH module -+ * -+ * Return: none -+ * -+ *****************************************************************************/ -+Std_ReturnType HASH_SHA256_Init(HASH_HandleTypeDef *hHash) -+{ -+ /* Check the hash handle allocation */ -+ if (!hHash) { -+ return STD_NOT_OK; -+ } -+ -+ hHash->Instance = (HASH_TypeDef *)HASH_BASE; -+ -+ /* Enable HASH1 clock */ -+ stm32mp_clk_enable(HASH1); -+ -+ hHash->Error = HASH_INIT_NOT_DONE; -+ -+ hHash->pHashInBuffPtr = NULL; -+ -+ hHash->pHashOutBuffPtr = NULL; -+ -+ /* Set the data type to 8 bits */ -+ hHash->Instance->CR |= HASH_DATATYPE_8B; -+ -+ /* Select the SHA256 mode and reset the HASH processor core, -+ * so that the HASH will be ready to compute the message digest -+ * of a new message -+ */ -+ hHash->Instance->CR |= HASH_AlgoSelection_SHA256 | HASH_CR_INIT; -+ -+ /* Return function status */ -+ hHash->Error = HASH_INIT_DONE; -+ -+ return STD_OK; -+} -+ -+/***************************************************************************** -+ * -+ * Function: HASH_SHA256_Start -+ * -+ * Description: Initializes the HASH peripheral in SHA256 mode -+ * then processes pInBuffer. -+ * The digest is available in pOutBuffer. -+ * -+ * Parameters: hHash : pointer to a HASH_HandleTypeDef structure that contains -+ * the configuration information for HASH module -+ * -+ * pInBuffer: Pointer to the input buffer (buffer to be hashed). -+ * -+ * sizeInBytes: Length of the input buffer in bytes. -+ * If the Size is not multiple of 64 bytes, -+ * the padding is managed by hardware. -+ * -+ * pOutBuffer: Pointer to the computed digest. -+ * Its size must be 32 bytes. -+ * -+ * Timeout: Specify Timeout value -+ * -+ * Return: none -+ * -+ *****************************************************************************/ -+Std_ReturnType HASH_SHA256_Start(HASH_HandleTypeDef *hHash, -+ const uint8_t *pInBuffer, uint32_t sizeInBytes, -+ uint8_t *pOutBuffer, uint32_t Timeout) -+{ -+ uint32_t timeoutDetected = 0; -+ -+ /* Check the hash handle allocation */ -+ if (!hHash) { -+ return STD_NOT_OK; -+ } -+ -+ hHash->pHashInBuffPtr = pInBuffer; -+ hHash->pHashOutBuffPtr = pOutBuffer; -+ -+ /* Configure the number of valid bits in last word 32 bits -+ * of the bit stream -+ */ -+ __HAL_HASH_SET_NBVALIDBITSINLAST32BITSWORD(sizeInBytes); -+ -+ /* Fill in entire input buffer to be hashed in HASH DIN register -+ * Note : intermediate digest is computed each time 64 bytes are written -+ * in HASH_DIN register -+ */ -+ HASH_WriteData(hHash, pInBuffer, sizeInBytes); -+ -+ /* Start the Final Digest calculation */ -+ hHash->Instance->STR |= HASH_STR_DCAL; -+ -+ /* Check for timeout */ -+ timeoutDetected = HASH_WaitBusyClearWithTimeout(hHash, Timeout); -+ if (timeoutDetected != 0) { -+ hHash->Error = HASH_TIMEOUT; -+ return STD_NOT_OK; -+ } -+ -+ /* Read the message digest in output buffer */ -+ HASH_GetDigest(hHash, pOutBuffer); -+ -+ hHash->Error = HASH_DIGEST_DONE; -+ -+ return STD_OK; -+} -+ -+/***************************************************************************** -+ * -+ * Function: HASH_SHA256_Accumulate -+ * -+ * Description: Initializes the HASH peripheral in SHA256 mode then processes -+ * pInBuffer. -+ * -+ * Parameters: hHash: pointer to a HASH_HandleTypeDef structure that contains -+ * the configuration information for HASH module -+ * -+ * pInBuffer: Pointer to the input buffer (buffer to be hashed). -+ * -+ * sizeInBytes: Length of the input buffer in bytes. -+ * If the Size is not multiple of 64 bytes, the padding is managed -+ * by hardware. -+ * -+ * Return: none -+ * -+ *****************************************************************************/ -+Std_ReturnType HASH_SHA256_Accumulate(HASH_HandleTypeDef *hHash, -+ const uint8_t *pInBuffer, -+ uint32_t sizeInBytes) -+{ -+ /* Check the hash handle allocation */ -+ if (!hHash) { -+ return STD_NOT_OK; -+ } -+ -+ hHash->pHashInBuffPtr = pInBuffer; -+ -+ /* Configure the number of valid bits in last 32 bits word -+ * of the message -+ */ -+ __HAL_HASH_SET_NBVALIDBITSINLAST32BITSWORD(sizeInBytes); -+ -+ /* Write input buffer in data register */ -+ HASH_WriteData(hHash, pInBuffer, sizeInBytes); -+ -+ /* Return function status */ -+ hHash->Error = HASH_ACCU_DONE; -+ -+ return STD_OK; -+} -+ -+/***************************************************************************** -+ * -+ * Function: HASH_SHA256_Finish -+ * -+ * Description: Returns the computed digest in SHA256. -+ * -+ * Parameters: hHash: pointer to a HASH_HandleTypeDef structure that contains -+ * the configuration information for HASH module -+ * -+ * pOutBuffer: Pointer to the computed digest. -+ * Its size must be 32 bytes. -+ * -+ * Timeout: Timeout value -+ * -+ * Return: none -+ * -+ *****************************************************************************/ -+Std_ReturnType HASH_SHA256_Finish(HASH_HandleTypeDef *hHash, -+ uint8_t *pOutBuffer, uint32_t Timeout) -+{ -+ uint32_t timeoutDetected = 0; -+ -+ /* Check the hash handle allocation */ -+ if (!hHash) { -+ return STD_NOT_OK; -+ } -+ -+ hHash->pHashOutBuffPtr = pOutBuffer; -+ -+ /* Check for the Timeout */ -+ timeoutDetected = HASH_WaitDcisClearWithTimeout(hHash, Timeout); -+ if (timeoutDetected != 0) { -+ hHash->Error = HASH_TIMEOUT; -+ return STD_NOT_OK; -+ } -+ -+ /* Read the message digest */ -+ HASH_GetDigest(hHash, pOutBuffer); -+ -+ /* Return function status */ -+ hHash->Error = HASH_FINISHED; -+ -+ return STD_OK; -+} -+ -+/* Static functions ----------------------------------------------------------*/ -+ -+/** -+ * @brief Writes the input buffer in HASH_DIN register. -+ * @param pInBuffer: Pointer to input buffer -+ * @param SizeInBytes : The size of input buffer (in bytes) -+ * @retval None -+ */ -+static void HASH_WriteData(HASH_HandleTypeDef *hHash, const uint8_t *pInBuffer, -+ uint32_t SizeInBytes) -+{ -+ uint32_t *pInWord32 = (uint32_t *)pInBuffer; -+ uint32_t nbBlocks = (SizeInBytes / HASH_BLOCK_SIZE_NB_BYTES); -+ uint32_t remainingBytesInLastBlock = (SizeInBytes % -+ HASH_BLOCK_SIZE_NB_BYTES); -+ uint32_t remainingBytesInLastWord = (SizeInBytes % 4); -+ uint32_t idxBlock = 0; -+ uint32_t idxWord32; -+ -+ /* For all blocks */ -+ for (idxBlock = 0; idxBlock < nbBlocks; idxBlock++) { -+ for (idxWord32 = 0; idxWord32 < (HASH_BLOCK_SIZE_NB_BYTES / 4); -+ idxWord32++) { -+ hHash->Instance->DIN = *pInWord32; -+ pInWord32++; -+ } -+ -+ /* Wait until end of computation of intermediate digest */ -+ while ((hHash->Instance->SR & HASH_SR_DINIS) == HASH_SR_DINIS) { -+ ; -+ } -+ } -+ -+ if (remainingBytesInLastBlock != 0) { -+ uint32_t nbWords32Remaining = (remainingBytesInLastBlock / 4); -+ -+ for (idxWord32 = 0; idxWord32 < nbWords32Remaining; -+ idxWord32++) { -+ hHash->Instance->DIN = *pInWord32; -+ pInWord32++; -+ } -+ } -+ -+ if (remainingBytesInLastWord != 0) { -+ hHash->Instance->DIN = *pInWord32; -+ } -+} -+ -+#ifndef __CC_ARM -+/* __rev is a builtin command in ARM compiler -+ * it needs to be remapped on __builtin_bswap32 for GCC -+ */ -+#define __rev __builtin_bswap32 -+#endif -+ -+/** -+ * @brief Provides the message digest result. -+ * @param hHash: Hash handle -+ * @param pMsgDigest: Pointer to the message digest -+ * @retval None -+ */ -+static void HASH_GetDigest(HASH_HandleTypeDef *hHash, uint8_t *pMsgDigest) -+{ -+ uintptr_t msgdigest = (uintptr_t)pMsgDigest; -+ -+ /* Read the message digest */ -+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[0]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[1]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[2]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[3]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[4]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(HASH_DIGEST->HR[5]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(HASH_DIGEST->HR[6]); -+ msgdigest += 4; -+ *(uintptr_t *)(msgdigest) = __rev(HASH_DIGEST->HR[7]); -+} -+ -+/** -+ * @brief This function waits until bit HASH_SR_BUSY is 1b0' before a timeout. -+ * @param [in] hHash : hash handle -+ * @param [in] timeout : timeout value -+ * -+ * @retval timeoutDetected : value 0x1 if timeout was detected while -+ * waiting for bit BUSY to be cleared. -+ ****************************************************************************** -+ */ -+ -+static uint32_t HASH_WaitBusyClearWithTimeout(HASH_HandleTypeDef *hHash, -+ uint32_t timeout) -+{ -+ uint32_t timerValInit = 0; -+ uint32_t timeoutDetected = 0; -+ -+ /* Get timer current value at start of loop */ -+ timerValInit = timer_GetTimeSec(); -+ -+ while (((hHash->Instance->SR & HASH_SR_BUSY) == HASH_SR_BUSY) && -+ (timeoutDetected == 0)) { -+ /* Sense timeout occurrence */ -+ if ((timer_GetTimeSec() - timerValInit) >= timeout) { -+ timeoutDetected = 1; -+ } -+ } -+ -+ return timeoutDetected; -+} -+ -+/** -+ * @brief This function waits until bit HASH_SR_DCIS is 1b0' before a timeout. -+ * @param [in] hHash : hash handle -+ * @param [in] timeout : timeout value -+ * -+ * @retval timeoutDetected : value 0x1 if timeout was detected while -+ * waiting for bit DCIS to be cleared. -+ ****************************************************************************** -+ */ -+ -+static uint32_t HASH_WaitDcisClearWithTimeout(HASH_HandleTypeDef *hHash, -+ uint32_t timeout) -+{ -+ uint32_t timerValInit = 0; -+ uint32_t timeoutDetected = 0; -+ -+ /* Get timer current value at start of loop */ -+ timerValInit = timer_GetTimeSec(); -+ -+ while ((HAL_IS_BIT_CLR(hHash->Instance->SR, HASH_SR_DCIS)) && -+ (timeoutDetected == 0)) { -+ /* Sense timeout occurrence */ -+ if ((timer_GetTimeSec() - timerValInit) >= timeout) { -+ timeoutDetected = 1; -+ } -+ } -+ -+ return timeoutDetected; -+} + stm32mp_clk_enable(clock); + + if (secure) { diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c -new file mode 100644 -index 0000000..694a76a ---- /dev/null +index ed880522b..f12d40516 100644 +--- a/drivers/st/i2c/stm32_i2c.c +++ b/drivers/st/i2c/stm32_i2c.c -@@ -0,0 +1,1371 @@ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * +@@ -1,10 +1,11 @@ + /* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * +- * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include + */ + + #include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* STM32 I2C registers offsets */ -+#define I2C_CR1 0x00U -+#define I2C_CR2 0x04U -+#define I2C_OAR1 0x08U -+#define I2C_OAR2 0x0CU -+#define I2C_TIMINGR 0x10U -+#define I2C_TIMEOUTR 0x14U -+#define I2C_ISR 0x18U -+#define I2C_ICR 0x1CU -+#define I2C_PECR 0x20U -+#define I2C_RXDR 0x24U -+#define I2C_TXDR 0x28U -+ -+#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU -+ -+#define MAX_NBYTE_SIZE 255U -+ -+#define I2C_NSEC_PER_SEC 1000000000L -+ + #include + #include + +@@ -38,8 +39,87 @@ + + #define I2C_NSEC_PER_SEC 1000000000L + +-/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ +-#define I2C_TIMING 0x10D07DB5 +/* + * struct i2c_spec_s - Private I2C timing specifications. + * @rate: I2C bus speed (Hz) -+ * @rate_min: 80% of I2C bus speed (Hz) -+ * @rate_max: 120% of I2C bus speed (Hz) + * @fall_max: Max fall time of both SDA and SCL signals (ns) + * @rise_max: Max rise time of both SDA and SCL signals (ns) + * @hddat_min: Min data hold time (ns) @@ -10521,8 +11929,6 @@ index 0000000..694a76a + */ +struct i2c_spec_s { + uint32_t rate; -+ uint32_t rate_min; -+ uint32_t rate_max; + uint32_t fall_max; + uint32_t rise_max; + uint32_t hddat_min; @@ -10548,18 +11954,17 @@ index 0000000..694a76a + 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] = { ++ /* Standard - 100KHz */ ++ { + .rate = STANDARD_RATE, -+ .rate_min = 8000, -+ .rate_max = 120000, + .fall_max = 300, + .rise_max = 1000, + .hddat_min = 0, @@ -10568,10 +11973,9 @@ index 0000000..694a76a + .l_min = 4700, + .h_min = 4000, + }, -+ [I2C_SPEED_FAST] = { ++ /* Fast - 400KHz */ ++ { + .rate = FAST_RATE, -+ .rate_min = 320000, -+ .rate_max = 480000, + .fall_max = 300, + .rise_max = 300, + .hddat_min = 0, @@ -10580,10 +11984,9 @@ index 0000000..694a76a + .l_min = 1300, + .h_min = 600, + }, -+ [I2C_SPEED_FAST_PLUS] = { ++ /* FastPlus - 1MHz */ ++ { + .rate = FAST_PLUS_RATE, -+ .rate_min = 800000, -+ .rate_max = 1200000, + .fall_max = 100, + .rise_max = 120, + .hddat_min = 0, @@ -10594,40 +11997,28 @@ index 0000000..694a76a + }, +}; + -+static int i2c_request_memory_write(struct i2c_handle_s *hi2c, -+ uint16_t dev_addr, uint16_t mem_addr, -+ uint16_t mem_add_size, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint64_t tick_to, uint64_t tick_start); -+ -+/* Private functions to handle flags during polling transfer */ -+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, -+ uint8_t awaited_value, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_wait_txis(struct i2c_handle_s *hi2c, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_wait_stop(struct i2c_handle_s *hi2c, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_ack_failed(struct i2c_handle_s *hi2c, -+ uint64_t tick_to, uint64_t tick_start); -+ -+/* Private function to flush TXDR register */ -+static void i2c_flush_txdr(struct i2c_handle_s *hi2c); -+ -+/* Private function to start, restart or stop a transfer */ -+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t size, uint32_t i2c_mode, -+ uint32_t request); -+ -+static void notif_i2c_timeout(struct i2c_handle_s *hi2c) + + static void notif_i2c_timeout(struct i2c_handle_s *hi2c) + { +@@ -48,6 +128,298 @@ static void notif_i2c_timeout(struct i2c_handle_s *hi2c) + hi2c->i2c_state = I2C_STATE_READY; + } + ++static const struct i2c_spec_s *get_specs(uint32_t rate) +{ -+ hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ hi2c->i2c_state = I2C_STATE_READY; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) { ++ if (rate <= i2c_specs[i].rate) { ++ return &i2c_specs[i]; ++ } ++ } ++ ++ /* NOT REACHED */ ++ return NULL; +} + ++#define RATE_MIN(rate) (((rate) / 100U) * 80U) +/* + * @brief Compute the I2C device timings. + * @param init: Ref to the initialization configuration structure @@ -10638,7 +12029,7 @@ index 0000000..694a76a +static int i2c_compute_timing(struct stm32_i2c_init_s *init, + uint32_t clock_src, uint32_t *timing) +{ -+ enum i2c_speed_e mode = init->speed_mode; ++ const struct i2c_spec_s *specs; + uint32_t speed_freq; + uint32_t i2cclk = udiv_round_nearest(I2C_NSEC_PER_SEC, clock_src); + uint32_t i2cbus; @@ -10662,24 +12053,21 @@ index 0000000..694a76a + int s = -1; + struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX]; + -+ switch (mode) { -+ case I2C_SPEED_STANDARD ... I2C_SPEED_FAST_PLUS: -+ break; -+ default: -+ ERROR("I2C speed out of bound {%d/%d}\n", -+ mode, I2C_SPEED_FAST_PLUS); ++ specs = get_specs(init->bus_rate); ++ if (specs == NULL) { ++ ERROR("I2C speed out of bound {%d}\n", init->bus_rate); + return -EINVAL; + } + -+ speed_freq = i2c_specs[mode].rate; ++ speed_freq = specs->rate; + i2cbus = udiv_round_nearest(I2C_NSEC_PER_SEC, speed_freq); + clk_error_prev = INT_MAX; + -+ if ((init->rise_time > i2c_specs[mode].rise_max) || -+ (init->fall_time > i2c_specs[mode].fall_max)) { ++ if ((init->rise_time > specs->rise_max) || ++ (init->fall_time > specs->fall_max)) { + ERROR(" I2C timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", -+ init->rise_time, i2c_specs[mode].rise_max, -+ init->fall_time, i2c_specs[mode].fall_max); ++ init->rise_time, specs->rise_max, ++ init->fall_time, specs->fall_max); + return -EINVAL; + } + @@ -10696,13 +12084,13 @@ index 0000000..694a76a + STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0); + dnf_delay = init->digital_filter_coef * i2cclk; + -+ sdadel_min = i2c_specs[mode].hddat_min + init->fall_time - ++ sdadel_min = specs->hddat_min + init->fall_time - + af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); + -+ sdadel_max = i2c_specs[mode].vddat_max - init->rise_time - ++ sdadel_max = specs->vddat_max - init->rise_time - + af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); + -+ scldel_min = init->rise_time + i2c_specs[mode].sudat_min; ++ scldel_min = init->rise_time + specs->sudat_min; + + if (sdadel_min < 0) { + sdadel_min_u = 0; @@ -10756,8 +12144,8 @@ index 0000000..694a76a + } + + tsync = af_delay_min + dnf_delay + (2 * i2cclk); -+ clk_max = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_min; -+ clk_min = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_max; ++ clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate); ++ clk_min = I2C_NSEC_PER_SEC / specs->rate; + + /* + * Among prescaler possibilities discovered above figures out SCL Low @@ -10779,7 +12167,7 @@ index 0000000..694a76a + for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { + uint32_t tscl_l = ((l + 1) * prescaler) + tsync; + -+ if ((tscl_l < i2c_specs[mode].l_min) || ++ if ((tscl_l < specs->l_min) || + (i2cclk >= + ((tscl_l - af_delay_min - dnf_delay) / 4))) { + continue; @@ -10792,7 +12180,7 @@ index 0000000..694a76a + init->fall_time; + + if ((tscl >= clk_min) && (tscl <= clk_max) && -+ (tscl_h >= i2c_specs[mode].h_min) && ++ (tscl_h >= specs->h_min) && + (i2cclk < tscl_h)) { + int clk_error = tscl - i2cbus; + @@ -10832,6 +12220,19 @@ index 0000000..694a76a + return 0; +} + ++static uint32_t get_lower_rate(uint32_t rate) ++{ ++ int i; ++ ++ for (i = ARRAY_SIZE(i2c_specs) - 1; i >= 0; i--) { ++ if (rate > i2c_specs[i].rate) { ++ return i2c_specs[i].rate; ++ } ++ } ++ ++ return i2c_specs[0].rate; ++} ++ +/* + * @brief Setup the I2C device timings. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains @@ -10847,20 +12248,29 @@ index 0000000..694a76a + int rc = 0; + uint32_t clock_src; + -+ clock_src = stm32mp_clk_get_rate(hi2c->clock); ++ clock_src = (uint32_t)stm32mp_clk_get_rate(hi2c->clock); + if (clock_src == 0U) { + ERROR("I2C clock rate is 0\n"); + 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 == hi2c->saved_frequency) { ++ *timing = hi2c->saved_timing; ++ return 0; ++ } ++ + do { + rc = i2c_compute_timing(init, clock_src, timing); + if (rc != 0) { + ERROR("Failed to compute I2C timings\n"); -+ if (init->speed_mode > I2C_SPEED_STANDARD) { -+ init->speed_mode--; ++ if (init->bus_rate > STANDARD_RATE) { ++ init->bus_rate = get_lower_rate(init->bus_rate); + WARN("Downgrade I2C speed to %uHz)\n", -+ i2c_specs[init->speed_mode].rate); ++ init->bus_rate); + } else { + break; + } @@ -10872,1078 +12282,167 @@ index 0000000..694a76a + return rc; + } + -+ VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%i)\n", -+ init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src); ++ VERBOSE("I2C Freq(%i), Clk Source(%i)\n", ++ init->bus_rate, clock_src); + VERBOSE("I2C Rise(%i) and Fall(%i) Time\n", + init->rise_time, init->fall_time); + VERBOSE("I2C Analog Filter(%s), DNF(%i)\n", + (init->analog_filter ? "On" : "Off"), + init->digital_filter_coef); + -+ return 0; -+} -+ -+/* -+ * @brief Configure I2C Analog noise filter. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C peripheral. -+ * @param analog_filter: New state of the Analog filter -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, -+ uint32_t analog_filter) -+{ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return -EBUSY; -+ } -+ -+ hi2c->lock = 1; -+ -+ hi2c->i2c_state = I2C_STATE_BUSY; -+ -+ /* Disable the selected I2C peripheral */ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -+ -+ /* Reset I2Cx ANOFF bit */ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); -+ -+ /* Set analog filter bit*/ -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); -+ -+ /* Enable the selected I2C peripheral */ -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ -+ hi2c->lock = 0; ++ hi2c->saved_timing = *timing; ++ hi2c->saved_frequency = clock_src; + + return 0; +} + -+/* -+ * @brief Get I2C setup information from the device tree and set pinctrl -+ * configuration. -+ * @param fdt: Pointer to the device tree -+ * @param node: I2C node offset -+ * @param init: Ref to the initialization configuration structure -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_get_setup_from_fdt(void *fdt, int node, -+ struct stm32_i2c_init_s *init) -+{ -+ const fdt32_t *cuint; + /* + * @brief Configure I2C Analog noise filter. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains +@@ -88,49 +460,30 @@ static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, + /* + * @brief Get I2C setup information from the device tree and set pinctrl + * configuration. +- * @param fdt: Pointer to the device tree + * @param node: I2C node offset + * @param init: Ref to the initialization configuration structure + * @retval 0 if OK, negative value else + */ +-int stm32_i2c_get_setup_from_fdt(void *fdt, int node, +- struct stm32_i2c_init_s *init) ++int stm32_i2c_get_setup_from_fdt(int node, struct stm32_i2c_init_s *init) + { +- const fdt32_t *cuint; +- +- cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); +- if (cuint == NULL) { +- init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; +- } else { +- init->rise_time = fdt32_to_cpu(*cuint); +- } +- +- cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); +- if (cuint == NULL) { +- init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; +- } else { +- init->fall_time = fdt32_to_cpu(*cuint); +- } +- +- cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); +- if (cuint == NULL) { +- init->speed_mode = STM32_I2C_SPEED_DEFAULT; +- } else { +- switch (fdt32_to_cpu(*cuint)) { +- case STANDARD_RATE: +- init->speed_mode = I2C_SPEED_STANDARD; +- break; +- case FAST_RATE: +- init->speed_mode = I2C_SPEED_FAST; +- break; +- case FAST_PLUS_RATE: +- init->speed_mode = I2C_SPEED_FAST_PLUS; +- break; +- default: +- init->speed_mode = STM32_I2C_SPEED_DEFAULT; +- break; +- } ++ uint32_t read_val; + -+ cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); -+ if (cuint == NULL) { -+ init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; -+ } else { -+ init->rise_time = fdt32_to_cpu(*cuint); -+ } ++ init->rise_time = fdt_read_uint32_default(node, ++ "i2c-scl-rising-time-ns", ++ STM32_I2C_RISE_TIME_DEFAULT); + -+ cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); -+ if (cuint == NULL) { -+ init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; -+ } else { -+ init->fall_time = fdt32_to_cpu(*cuint); -+ } ++ init->fall_time = fdt_read_uint32_default(node, ++ "i2c-scl-falling-time-ns", ++ STM32_I2C_FALL_TIME_DEFAULT); + -+ cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); -+ if (cuint == NULL) { -+ init->speed_mode = STM32_I2C_SPEED_DEFAULT; -+ } else { -+ switch (fdt32_to_cpu(*cuint)) { -+ case STANDARD_RATE: -+ init->speed_mode = I2C_SPEED_STANDARD; -+ break; -+ case FAST_RATE: -+ init->speed_mode = I2C_SPEED_FAST; -+ break; -+ case FAST_PLUS_RATE: -+ init->speed_mode = I2C_SPEED_FAST_PLUS; -+ break; -+ default: -+ init->speed_mode = STM32_I2C_SPEED_DEFAULT; -+ break; -+ } -+ } -+ -+ return dt_set_pinctrl_config(node); -+} -+ -+/* -+ * @brief Initialize the I2C device. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param init_data: Initialization configuration structure -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_init(struct i2c_handle_s *hi2c, -+ struct stm32_i2c_init_s *init_data) -+{ -+ int rc = 0; ++ read_val = fdt_read_uint32_default(node, "clock-frequency", ++ STANDARD_RATE); ++ if (read_val > FAST_PLUS_RATE) { ++ ERROR("Invalid bus speed (%i > %i)\n", read_val, ++ FAST_PLUS_RATE); ++ return -FDT_ERR_BADVALUE; + } ++ init->bus_rate = read_val; + + return dt_set_pinctrl_config(node); + } +@@ -146,7 +499,7 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data) + { + int rc = 0; +- uint32_t timing = I2C_TIMING; + uint32_t timing; -+ -+ if (hi2c == NULL) { -+ return -ENOENT; -+ } -+ -+ if (hi2c->i2c_state == I2C_STATE_RESET) { -+ hi2c->lock = 0; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY; -+ + + if (hi2c == NULL) { + return -ENOENT; +@@ -158,6 +511,11 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, + + hi2c->i2c_state = I2C_STATE_BUSY; + + rc = i2c_setup_timing(hi2c, init_data, &timing); + if (rc != 0) { + return rc; + } + -+ stm32mp_clk_enable(hi2c->clock); -+ -+ /* Disable the selected I2C peripheral */ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -+ -+ /* Configure I2Cx: Frequency range */ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, -+ timing & TIMINGR_CLEAR_MASK); -+ -+ /* Disable Own Address1 before set the Own Address1 configuration */ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); -+ -+ /* Configure I2Cx: Own Address1 and ack own address1 mode */ -+ if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { -+ mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, -+ I2C_OAR1_OA1EN | init_data->own_address1); -+ } else { /* I2C_ADDRESSINGMODE_10BIT */ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, -+ I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | -+ init_data->own_address1); -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); -+ -+ /* Configure I2Cx: Addressing Master mode */ -+ if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); -+ } -+ -+ /* -+ * Enable the AUTOEND by default, and enable NACK -+ * (should be disabled only during Slave process). -+ */ -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, -+ I2C_CR2_AUTOEND | I2C_CR2_NACK); -+ -+ /* Disable Own Address2 before set the Own Address2 configuration */ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); -+ -+ /* Configure I2Cx: Dual mode and Own Address2 */ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, -+ init_data->dual_address_mode | -+ init_data->own_address2 | -+ (init_data->own_address2_masks << 8)); -+ -+ /* Configure I2Cx: Generalcall and NoStretch mode */ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, -+ init_data->general_call_mode | -+ init_data->no_stretch_mode); -+ -+ /* Enable the selected I2C peripheral */ -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -+ -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? -+ I2C_ANALOGFILTER_ENABLE : -+ I2C_ANALOGFILTER_DISABLE); -+ if (rc != 0) { -+ ERROR("Cannot initialize I2C analog filter (%d)\n", rc); -+ stm32mp_clk_disable(hi2c->clock); -+ return rc; -+ } -+ -+ stm32mp_clk_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Generic function to write an amount of data in blocking mode -+ * (for Memory Mode and Master Mode) -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address (if Memory Mode) -+ * @param mem_add_size: Size of internal memory address (if Memory Mode) -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @param mode: Communication mode -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms, -+ enum i2c_mode_e mode) -+{ -+ uint64_t tick_start; -+ uint64_t tick_to = ms2tick(timeout_ms); -+ int rc = -EIO; -+ uint8_t *p_buff = p_data; -+ uint32_t xfer_size; -+ uint32_t xfer_count = size; -+ -+ if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { -+ return -1; -+ } -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return -EBUSY; -+ } -+ -+ if ((p_data == NULL) || (size == 0U)) { -+ return -EINVAL; -+ } -+ -+ stm32mp_clk_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ -+ tick_start = timeout_start(); -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, ms2tick(I2C_TIMEOUT_BUSY_MS), -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY_TX; -+ hi2c->i2c_mode = mode; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ if (mode == I2C_MODE_MEM) { -+ /* In Memory Mode, Send Slave Address and Memory Address */ -+ if (i2c_request_memory_write(hi2c, dev_addr, -+ mem_addr, mem_add_size, -+ tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); -+ } -+ } else { -+ /* In Master Mode, Send Slave Address */ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_RELOAD_MODE, -+ I2C_GENERATE_START_WRITE); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_AUTOEND_MODE, -+ I2C_GENERATE_START_WRITE); -+ } -+ } -+ -+ do { -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); -+ p_buff++; -+ xfer_count--; -+ xfer_size--; -+ -+ if ((xfer_count != 0U) && (xfer_size == 0U)) { -+ /* Wait until TCR flag is set */ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_RELOAD_MODE, -+ I2C_NO_STARTSTOP); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_AUTOEND_MODE, -+ I2C_NO_STARTSTOP); -+ } -+ } -+ -+ } while (xfer_count > 0U); -+ -+ /* -+ * No need to Check TC flag, with AUTOEND mode the stop -+ * is automatically generated. -+ * Wait until STOPF flag is reset. -+ */ -+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -+ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = 0; -+ -+bail: -+ hi2c->lock = 0; -+ stm32mp_clk_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Write an amount of data in blocking mode to a specific memory -+ * address. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms) -+{ -+ return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, -+ p_data, size, timeout_ms, I2C_MODE_MEM); -+} -+ -+/* -+ * @brief Transmits in master mode an amount of data in blocking mode. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms) -+{ -+ return i2c_write(hi2c, dev_addr, 0, 0, -+ p_data, size, timeout_ms, I2C_MODE_MASTER); -+} -+ -+/* -+ * @brief Generic function to read an amount of data in blocking mode -+ * (for Memory Mode and Master Mode) -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address (if Memory Mode) -+ * @param mem_add_size: Size of internal memory address (if Memory Mode) -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @param mode: Communication mode -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms, -+ enum i2c_mode_e mode) -+{ -+ uint64_t tick_start; -+ uint64_t tick_to = ms2tick(timeout_ms); -+ int rc = -EIO; -+ uint8_t *p_buff = p_data; -+ uint32_t xfer_count = size; -+ uint32_t xfer_size; -+ -+ if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { -+ return -1; -+ } -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return -EBUSY; -+ } -+ -+ if ((p_data == NULL) || (size == 0U)) { -+ return -EINVAL; -+ } -+ -+ stm32mp_clk_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ -+ tick_start = timeout_start(); -+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, ms2tick(I2C_TIMEOUT_BUSY_MS), -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY_RX; -+ hi2c->i2c_mode = mode; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ if (mode == I2C_MODE_MEM) { -+ /* Send Memory Address */ -+ if (i2c_request_memory_read(hi2c, dev_addr, -+ mem_addr, mem_add_size, -+ tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ } -+ -+ /* -+ * Send Slave Address. -+ * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE -+ * and generate RESTART. -+ */ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_RELOAD_MODE, I2C_GENERATE_START_READ); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); -+ } -+ -+ do { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); -+ p_buff++; -+ xfer_size--; -+ xfer_count--; -+ -+ if ((xfer_count != 0U) && (xfer_size == 0U)) { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_RELOAD_MODE, -+ I2C_NO_STARTSTOP); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_AUTOEND_MODE, -+ I2C_NO_STARTSTOP); -+ } -+ } -+ } while (xfer_count > 0U); -+ -+ /* -+ * No need to Check TC flag, with AUTOEND mode the stop -+ * is automatically generated. -+ * Wait until STOPF flag is reset. -+ */ -+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -+ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = 0; -+ -+bail: -+ hi2c->lock = 0; -+ stm32mp_clk_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Read an amount of data in blocking mode from a specific memory -+ * address. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms) -+{ -+ return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, -+ p_data, size, timeout_ms, I2C_MODE_MEM); -+} -+ -+/* -+ * @brief Receives in master mode an amount of data in blocking mode. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms) -+{ -+ return i2c_read(hi2c, dev_addr, 0, 0, -+ p_data, size, timeout_ms, I2C_MODE_MASTER); -+} -+ -+/* -+ * @brief Checks if target device is ready for communication. -+ * @note This function is used with Memory devices -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param trials: Number of trials -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval True if device is ready, false else -+ */ -+bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, -+ uint16_t dev_addr, uint32_t trials, -+ uint32_t timeout_ms) -+{ -+ uint32_t i2c_trials = 0U; -+ bool rc = false; -+ uint64_t tick_to = ms2tick(timeout_ms); -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return rc; -+ } -+ -+ stm32mp_clk_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != -+ 0U) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ do { -+ uint64_t tick_start; -+ -+ /* Generate Start */ -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & -+ I2C_OAR1_OA1MODE) == 0) { -+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, -+ (((uint32_t)dev_addr & I2C_CR2_SADD) | -+ I2C_CR2_START | I2C_CR2_AUTOEND) & -+ ~I2C_CR2_RD_WRN); -+ } else { -+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, -+ (((uint32_t)dev_addr & I2C_CR2_SADD) | -+ I2C_CR2_START | I2C_CR2_ADD10) & -+ ~I2C_CR2_RD_WRN); -+ } -+ -+ /* -+ * No need to Check TC flag, with AUTOEND mode the stop -+ * is automatically generated. -+ * Wait until STOPF flag is set or a NACK flag is set. -+ */ -+ tick_start = timeout_start(); -+ do { -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -+ (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { -+ break; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ goto bail; -+ } -+ } while (true); -+ -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -+ I2C_FLAG_AF) == 0U) { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, -+ I2C_FLAG_STOPF); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ -+ rc = true; -+ goto bail; -+ } -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -+ -+ if (i2c_trials == trials) { -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, -+ I2C_CR2_STOP); -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, -+ I2C_FLAG_STOPF); -+ } -+ -+ i2c_trials++; -+ } while (i2c_trials < trials); -+ -+ notif_i2c_timeout(hi2c); -+ -+bail: -+ hi2c->lock = 0; -+ stm32mp_clk_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Master sends target device address followed by internal memory -+ * address for write request. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_request_memory_write(struct i2c_handle_s *hi2c, -+ uint16_t dev_addr, uint16_t mem_addr, -+ uint16_t mem_add_size, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, -+ I2C_GENERATE_START_WRITE); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { -+ /* Send Memory Address */ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } else { -+ /* Send MSB of Memory Address */ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -+ (uint8_t)((mem_addr & 0xFF00U) >> 8)); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ /* Send LSB of Memory Address */ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief Master sends target device address followed by internal memory -+ * address for read request. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint64_t tick_to, uint64_t tick_start) -+{ -+ i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, -+ I2C_GENERATE_START_WRITE); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { -+ /* Send Memory Address */ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } else { -+ /* Send MSB of Memory Address */ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -+ (uint8_t)((mem_addr & 0xFF00U) >> 8)); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ /* Send LSB of Memory Address */ -+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief I2C Tx data register flush process. -+ * @param hi2c: I2C handle -+ * @retval None -+ */ -+static void i2c_flush_txdr(struct i2c_handle_s *hi2c) -+{ -+ /* -+ * If a pending TXIS flag is set, -+ * write a dummy data in TXDR to clear it. -+ */ -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != -+ 0U) { -+ mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); -+ } -+ -+ /* Flush TX register if not empty */ -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == -+ 0U) { -+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, -+ I2C_FLAG_TXE); -+ } -+} -+ -+/* -+ * @brief This function handles I2C Communication timeout. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param flag: Specifies the I2C flag to check -+ * @param awaited_value: The awaited bit value for the flag (0 or 1) -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, -+ uint8_t awaited_value, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ for ( ; ; ) { -+ uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); -+ -+ if (!!(isr & flag) != !!awaited_value) { -+ return 0; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -EIO; -+ } -+ } -+} -+ -+/* -+ * @brief This function handles I2C Communication timeout for specific usage -+ * of TXIS flag. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -+ I2C_FLAG_TXIS) == 0U) { -+ if (i2c_ack_failed(hi2c, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -EIO; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief This function handles I2C Communication timeout for specific -+ * usage of STOP flag. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -+ I2C_FLAG_STOPF) == 0U) { -+ if (i2c_ack_failed(hi2c, tick_to, tick_start) != 0) { -+ return -EIO; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -EIO; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief This function handles Acknowledge failed detection during -+ * an I2C Communication. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { -+ return 0; -+ } -+ -+ /* -+ * Wait until STOP Flag is reset. -+ * AutoEnd should be initiate after AF. -+ */ -+ while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -+ I2C_FLAG_STOPF) == 0U) { -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -EIO; -+ } -+ } -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); -+ -+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -+ -+ i2c_flush_txdr(hi2c); -+ -+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_err |= I2C_ERROR_AF; -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ hi2c->lock = 0; -+ -+ return -EIO; -+} -+ -+/* -+ * @brief Handles I2Cx communication when starting transfer or during transfer -+ * (TC or TCR flag are set). -+ * @param hi2c: I2C handle -+ * @param dev_addr: Specifies the slave address to be programmed -+ * @param size: Specifies the number of bytes to be programmed. -+ * This parameter must be a value between 0 and 255. -+ * @param i2c_mode: New state of the I2C START condition generation. -+ * This parameter can be one of the following values: -+ * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. -+ * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. -+ * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. -+ * @param request: New state of the I2C START condition generation. -+ * This parameter can be one of the following values: -+ * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. -+ * @arg @ref I2C_GENERATE_STOP: Generate stop condition -+ * (size should be set to 0). -+ * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. -+ * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. -+ * @retval None -+ */ -+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t size, uint32_t i2c_mode, -+ uint32_t request) -+{ -+ uint32_t clr_value, set_value; -+ -+ clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | -+ I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | -+ (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); -+ -+ set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | -+ (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | -+ i2c_mode | request; -+ -+ mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); -+} + stm32mp_clk_enable(hi2c->clock); + + /* Disable the selected I2C peripheral */ +@@ -978,4 +1336,3 @@ bail: + + return rc; + } +- diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c -new file mode 100644 -index 0000000..bc9a91a ---- /dev/null +index a239b5f3a..0b0e84ec1 100644 +--- a/drivers/st/io/io_mmc.c +++ b/drivers/st/io/io_mmc.c -@@ -0,0 +1,134 @@ -+/* +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* SDMMC device functions */ -+static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info); -+static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, -+ io_entity_t *entity); -+static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -20,14 +20,15 @@ static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info); + static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); + static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +-static int mmc_block_seek(io_entity_t *entity, int mode, ssize_t offset); +static int mmc_block_seek(io_entity_t *entity, int mode, + signed long long offset); -+static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length, -+ size_t *length_read); -+static int mmc_block_close(io_entity_t *entity); -+static int mmc_dev_close(io_dev_info_t *dev_info); -+static io_type_t device_type_mmc(void); -+ -+static int64_t seek_offset; -+ -+static const io_dev_connector_t mmc_dev_connector = { -+ .dev_open = mmc_dev_open -+}; -+ -+static const io_dev_funcs_t mmc_dev_funcs = { -+ .type = device_type_mmc, -+ .open = mmc_block_open, -+ .seek = mmc_block_seek, -+ .size = NULL, -+ .read = mmc_block_read, -+ .write = NULL, -+ .close = mmc_block_close, -+ .dev_init = mmc_dev_init, -+ .dev_close = mmc_dev_close, -+}; -+ -+static const io_dev_info_t mmc_dev_info = { -+ .funcs = &mmc_dev_funcs, -+ .info = 0, -+}; -+ -+/* Identify the device type as mmc device */ -+static io_type_t device_type_mmc(void) -+{ -+ return IO_TYPE_MMC; -+} -+ -+/* Open a connection to the mmc device */ -+static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info) -+{ -+ assert(dev_info != NULL); -+ *dev_info = (io_dev_info_t *)&mmc_dev_info; -+ -+ return 0; -+} -+ -+static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) -+{ -+ return 0; -+} -+ -+/* Close a connection to the mmc device */ -+static int mmc_dev_close(io_dev_info_t *dev_info) -+{ -+ return 0; -+} -+ -+/* Open a file on the mmc device */ -+static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, -+ io_entity_t *entity) -+{ -+ seek_offset = 0; -+ return 0; -+} -+ -+/* Seek to a particular file offset on the mmc device */ + static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); + static int mmc_block_close(io_entity_t *entity); + static int mmc_dev_close(io_dev_info_t *dev_info); + static io_type_t device_type_mmc(void); + +-static ssize_t seek_offset; ++static signed long long seek_offset; + + static const io_dev_connector_t mmc_dev_connector = { + .dev_open = mmc_dev_open +@@ -85,7 +86,8 @@ static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + } + + /* Seek to a particular file offset on the mmc device */ +-static int mmc_block_seek(io_entity_t *entity, int mode, ssize_t offset) +static int mmc_block_seek(io_entity_t *entity, int mode, + signed long long offset) -+{ -+ seek_offset = offset; -+ return 0; -+} -+ -+/* Read data from a file on the mmc device */ -+static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ + { + seek_offset = offset; + return 0; +@@ -95,12 +97,18 @@ static int mmc_block_seek(io_entity_t *entity, int mode, ssize_t offset) + static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) + { +- *length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE, +- buffer, length); + uint8_t retries = 3U; -+ + +- if (*length_read != length) { +- return -EIO; +- } + do { + retries--; + if (retries == 0U) { @@ -11954,68 +12453,48 @@ index 0000000..bc9a91a + buffer, length); + + } while (*length_read != length); -+ -+ return 0; -+} -+ -+/* Close a file on the mmc device */ -+static int mmc_block_close(io_entity_t *entity) -+{ -+ return 0; -+} -+ -+/* Register the mmc driver with the IO abstraction */ -+int register_io_dev_mmc(const io_dev_connector_t **dev_con) -+{ -+ int result; -+ -+ assert(dev_con != NULL); -+ -+ result = io_register_device(&mmc_dev_info); -+ if (result == 0) { -+ *dev_con = &mmc_dev_connector; -+ } -+ -+ return result; -+} + + return 0; + } diff --git a/drivers/st/io/io_programmer_st_usb.c b/drivers/st/io/io_programmer_st_usb.c new file mode 100644 -index 0000000..a0871f6 +index 000000000..20da9656e --- /dev/null +++ b/drivers/st/io/io_programmer_st_usb.c -@@ -0,0 +1,379 @@ +@@ -0,0 +1,381 @@ +/* -+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2020, 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 ++#include ++#include ++#include ++#include ++ ++#define USB_STATE_READY 0 ++#define USB_STATE_WRITTEN 1 ++ ++#define IO_USB_TIMEOUT_10_SEC U(10000000) ++#define DETACH_TIMEOUT U(0x100) ++#define USB_DFU_MAX_XFER_SIZE 1024 + +static uint8_t first_usb_buffer[USB_DFU_MAX_XFER_SIZE + 1] __aligned(4); +static usb_dfu_media_t usb_dfu_fops; +static uint8_t checksum_is_wrong; +static uint8_t usb_status; + -+#define USB_STATE_READY 0 -+#define USB_STATE_WRITTEN 1 -+ +/* usb device functions */ +static int usb_dev_open(const uintptr_t init_params, + io_dev_info_t **dev_info); @@ -12271,6 +12750,9 @@ index 0000000..a0871f6 + usb_dfu_set_download_addr((uintptr_t) + &local_ptr[USB_DFU_MAX_XFER_SIZE]); + } else { ++#if TRUSTED_BOARD_BOOT ++ stm32mp_save_loaded_header(header); ++#endif + memcpy((uint8_t *)local_ptr, + (uint8_t *) + &first_usb_buffer[sizeof(boot_api_image_header_t)], @@ -12284,7 +12766,7 @@ index 0000000..a0871f6 + + while (!usb_dfu_download_is_completed()) { + /* Reload watchdog */ -+ stm32_iwdg_refresh(IWDG2_INST); ++ stm32_iwdg_refresh(); + + usb_core_handle_it((usb_handle_t *)usb_dev_info.info); + } @@ -12296,41 +12778,39 @@ index 0000000..a0871f6 + local_ptr += sizeof(boot_api_image_header_t); + + /* Verify header and checksum payload */ -+ result = check_header(header, (uintptr_t)local_ptr); ++ result = stm32mp_check_header(header, (uintptr_t)local_ptr); + if (result) { + ERROR("Header check failed\n"); + return result; + } + -+#if defined(AUTHENTICATE_BL33) -+ if (current_phase.phase_id != PHASE_FLASHLAYOUT) { -+ result = check_authentication(header, (uintptr_t)local_ptr); -+ if (result != 0) { -+ ERROR("Authentication failed\n"); -+ return result; -+ } -+ } -+#else -+ NOTICE("Authentication disabled: No signature check\n"); -+#endif -+ + /* Wait Detach in case of bl33 */ + if (current_phase.phase_id == PHASE_SSBL) { -+ uint32_t timeout = IO_USB_TIMEOUT; ++ uint64_t timeout; + uint32_t detach_timeout = DETACH_TIMEOUT; + + usb_dfu_set_phase_id(0x0); + usb_dfu_set_download_addr(UNDEFINE_DOWN_ADDR); + usb_dfu_request_detach(); -+ while (timeout && detach_timeout) { ++ timeout = timeout_init_us(IO_USB_TIMEOUT_10_SEC); ++ ++ while (detach_timeout != 0U) { + usb_core_handle_it((usb_handle_t *) + usb_dev_info.info); -+ if (!usb_dfu_detach_req()) ++ ++ if (usb_dfu_detach_req() == 0U) { ++ /* ++ * Continue to handle usb core IT to assure ++ * complete data transmission ++ */ + detach_timeout--; -+ timeout--; ++ } ++ ++ if (timeout_elapsed(timeout)) { ++ return -EIO; ++ } + } -+ if (!timeout) -+ return -EIO; ++ + /* STOP the USB Handler */ + usb_core_stop((usb_handle_t *)usb_dev_info.info); + } @@ -12364,436 +12844,276 @@ index 0000000..a0871f6 + return result; +} diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c -new file mode 100644 -index 0000000..fde6269 ---- /dev/null +index 413521b1e..a50a0df97 100644 +--- a/drivers/st/io/io_stm32image.c +++ b/drivers/st/io/io_stm32image.c -@@ -0,0 +1,381 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static uintptr_t backend_dev_handle; -+static uintptr_t backend_image_spec; -+static uint32_t *stm32_img; -+static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4); -+static struct stm32image_part_info *current_part; -+ -+/* STM32 Image driver functions */ -+static int stm32image_dev_open(const uintptr_t init_params, -+ io_dev_info_t **dev_info); -+static int stm32image_partition_open(io_dev_info_t *dev_info, -+ const uintptr_t spec, io_entity_t *entity); -+static int stm32image_partition_size(io_entity_t *entity, size_t *length); -+static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read); -+static int stm32image_partition_close(io_entity_t *entity); -+static int stm32image_dev_init(io_dev_info_t *dev_info, -+ const uintptr_t init_params); -+static int stm32image_dev_close(io_dev_info_t *dev_info); -+ -+/* Identify the device type as a virtual driver */ -+static io_type_t device_type_stm32image(void) -+{ -+ return IO_TYPE_STM32IMAGE; -+} -+ -+static const io_dev_connector_t stm32image_dev_connector = { -+ .dev_open = stm32image_dev_open -+}; -+ -+static const io_dev_funcs_t stm32image_dev_funcs = { -+ .type = device_type_stm32image, -+ .open = stm32image_partition_open, -+ .size = stm32image_partition_size, -+ .read = stm32image_partition_read, -+ .close = stm32image_partition_close, -+ .dev_init = stm32image_dev_init, -+ .dev_close = stm32image_dev_close, -+}; -+ -+static io_dev_info_t stm32image_dev_info = { -+ .funcs = &stm32image_dev_funcs, -+ .info = (uintptr_t)0, -+}; -+ -+static struct stm32image_device_info stm32image_dev; -+ -+static int get_part_idx_by_binary_type(uint32_t binary_type) -+{ -+ int i; -+ -+ for (i = 0; i < STM32_PART_NUM; i++) { -+ if (stm32image_dev.part_info[i].binary_type == binary_type) { -+ return i; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+/* Open a connection to the STM32IMAGE device */ -+static int stm32image_dev_open(const uintptr_t init_params, -+ io_dev_info_t **dev_info) -+{ -+ int i; -+ struct stm32image_device_info *device_info = -+ (struct stm32image_device_info *)init_params; -+ -+ assert(dev_info != NULL); -+ *dev_info = (io_dev_info_t *)&stm32image_dev_info; -+ -+ stm32image_dev.device_size = device_info->device_size; -+ stm32image_dev.lba_size = device_info->lba_size; -+ -+ for (i = 0; i < STM32_PART_NUM; i++) { -+ memcpy(stm32image_dev.part_info[i].name, -+ device_info->part_info[i].name, MAX_PART_NAME_SIZE); -+ stm32image_dev.part_info[i].binary_type = -+ device_info->part_info[i].binary_type; -+ stm32image_dev.part_info[i].part_offset = -+ device_info->part_info[i].part_offset; -+ stm32image_dev.part_info[i].bkp_offset = -+ device_info->part_info[i].bkp_offset; -+ } -+ -+ return 0; -+} -+ -+/* Do some basic package checks */ -+static int stm32image_dev_init(io_dev_info_t *dev_info, -+ const uintptr_t init_params) -+{ -+ int result; -+ -+ if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) { -+ ERROR("STM32 Image io supports only one session\n"); -+ return -ENOMEM; -+ } -+ -+ /* Obtain a reference to the image by querying the platform layer */ -+ result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle, -+ &backend_image_spec); +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -182,53 +182,26 @@ static int stm32image_partition_size(io_entity_t *entity, size_t *length) + return result; + } + +- /* Reset magic header value */ +- header->magic = 0; +- +- while (header->magic == 0U) { +- result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img); +- if (result != 0) { +- ERROR("%s: io_seek (%i)\n", __func__, result); +- break; +- } +- +- result = io_read(backend_handle, (uintptr_t)header, +- MAX_LBA_SIZE, (size_t *)&bytes_read); +- if (result != 0) { +- if (current_part->bkp_offset == 0U) { +- ERROR("%s: io_read (%i)\n", __func__, result); +- } +- header->magic = 0; +- } +- +- if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) || +- (header->binary_type != current_part->binary_type) || +- (header->image_length >= stm32image_dev.device_size)) { +- VERBOSE("%s: partition %s not found at %x\n", +- __func__, current_part->name, *stm32_img); +- +- if (current_part->bkp_offset == 0U) { +- result = -ENOMEM; +- break; +- } +- +- /* Header not correct, check next offset for backup */ +- *stm32_img += current_part->bkp_offset; +- if (*stm32_img > stm32image_dev.device_size) { +- /* No backup found, end of device reached */ +- WARN("%s : partition %s not found\n", +- __func__, current_part->name); +- result = -ENOMEM; +- break; +- } +- header->magic = 0; +- } ++ result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img); + if (result != 0) { -+ ERROR("STM32 image error (%i)\n", result); -+ return -EINVAL; ++ ERROR("%s: io_seek (%i)\n", __func__, result); ++ goto out; + } + +- io_close(backend_handle); +- ++ result = io_read(backend_handle, (uintptr_t)header, ++ MAX_LBA_SIZE, &bytes_read); + if (result != 0) { +- return result; ++ ERROR("%s: io_read (%i)\n", __func__, result); ++ goto out; + } + ++ if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) || ++ (header->binary_type != current_part->binary_type) || ++ (header->image_length >= stm32image_dev.device_size)) { ++ VERBOSE("%s: partition %s not found at %x\n", ++ __func__, current_part->name, *stm32_img); ++ result = -ENOMEM; ++ goto out; + } + + if (header->image_length < stm32image_dev.lba_size) { +@@ -239,15 +212,21 @@ static int stm32image_partition_size(io_entity_t *entity, size_t *length) + + INFO("STM32 Image size : %lu\n", (unsigned long)*length); + +- return 0; ++out: ++ io_close(backend_handle); ++ + return result; -+} -+ -+/* Close a connection to the STM32 Image device */ -+static int stm32image_dev_close(io_dev_info_t *dev_info) -+{ -+ backend_dev_handle = 0U; -+ backend_image_spec = 0U; -+ stm32_img = NULL; -+ -+ return 0; -+} -+ -+/* Open a partition */ -+static int stm32image_partition_open(io_dev_info_t *dev_info, -+ const uintptr_t spec, io_entity_t *entity) -+{ -+ const struct stm32image_part_info *partition_spec; -+ int idx; -+ -+ assert(entity != NULL); -+ -+ partition_spec = (struct stm32image_part_info *)spec; -+ assert(partition_spec != NULL); -+ -+ idx = get_part_idx_by_binary_type(partition_spec->binary_type); -+ if ((idx < 0) || (idx > STM32_PART_NUM)) { -+ ERROR("Wrong partition index (%d)\n", idx); -+ return -EINVAL; -+ } -+ -+ current_part = &stm32image_dev.part_info[idx]; -+ stm32_img = (uint32_t *)¤t_part->part_offset; -+ -+ return 0; -+} -+ -+/* Return the size of a partition */ -+static int stm32image_partition_size(io_entity_t *entity, size_t *length) -+{ -+ int result; + } + + /* Read data from a partition */ + static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) + { +- int result; +- uint8_t *local_buffer = (uint8_t *)buffer; ++ int offset; ++ int local_length; + uintptr_t backend_handle; -+ size_t bytes_read; -+ boot_api_image_header_t *header = -+ (boot_api_image_header_t *)first_lba_buffer; ++ int result = -EINVAL; ++ uint8_t *local_buffer; + boot_api_image_header_t *header = + (boot_api_image_header_t *)first_lba_buffer; + +@@ -255,101 +234,55 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, + assert(buffer != 0U); + assert(length_read != NULL); + ++ local_buffer = (uint8_t *)buffer; + *length_read = 0U; + +- while (*length_read == 0U) { +- int offset; +- int local_length; +- uintptr_t backend_handle; +- +- if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { +- /* Check for backup as image is corrupted */ +- if (current_part->bkp_offset == 0U) { +- result = -ENOMEM; +- break; +- } +- +- *stm32_img += current_part->bkp_offset; +- if (*stm32_img >= stm32image_dev.device_size) { +- /* End of device reached */ +- result = -ENOMEM; +- break; +- } +- +- local_buffer = (uint8_t *)buffer; +- +- result = stm32image_partition_size(entity, &length); +- if (result != 0) { +- break; +- } +- } +- +- /* Part of image already loaded with the header */ +- memcpy(local_buffer, (uint8_t *)first_lba_buffer + +- sizeof(boot_api_image_header_t), +- MAX_LBA_SIZE - sizeof(boot_api_image_header_t)); +- local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); +- offset = MAX_LBA_SIZE; +- +- /* New image length to be read */ +- local_length = round_up(length - +- ((MAX_LBA_SIZE) - +- sizeof(boot_api_image_header_t)), +- stm32image_dev.lba_size); +- +- if ((header->load_address != 0U) && +- (header->load_address != buffer)) { +- ERROR("Wrong load address\n"); +- panic(); +- } +- +- result = io_open(backend_dev_handle, backend_image_spec, +- &backend_handle); +- +- if (result != 0) { +- ERROR("%s: io_open (%i)\n", __func__, result); +- break; +- } +- +- result = io_seek(backend_handle, IO_SEEK_SET, +- *stm32_img + offset); +- +- if (result != 0) { +- ERROR("%s: io_seek (%i)\n", __func__, result); +- *length_read = 0; +- io_close(backend_handle); +- break; +- } +- +- result = io_read(backend_handle, (uintptr_t)local_buffer, +- local_length, length_read); +- +- /* Adding part of size already read from header */ +- *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); +- +- if (result != 0) { +- ERROR("%s: io_read (%i)\n", __func__, result); +- *length_read = 0; +- header->magic = 0; +- continue; +- } ++#if TRUSTED_BOARD_BOOT ++ stm32mp_save_loaded_header(header); ++#endif + -+ assert(entity != NULL); -+ assert(length != NULL); ++ /* Part of image already loaded with the header */ ++ memcpy(local_buffer, (uint8_t *)first_lba_buffer + ++ sizeof(boot_api_image_header_t), ++ MAX_LBA_SIZE - sizeof(boot_api_image_header_t)); ++ local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); ++ offset = MAX_LBA_SIZE; + -+ /* Attempt to access the image */ ++ /* New image length to be read */ ++ local_length = round_up(length - ((MAX_LBA_SIZE) - ++ sizeof(boot_api_image_header_t)), ++ stm32image_dev.lba_size); ++ ++ if ((header->load_address != 0U) && (header->load_address != buffer)) { ++ ERROR("Wrong load address\n"); ++ panic(); ++ } + +- result = stm32mp_check_header(header, buffer); +- if (result != 0) { +- ERROR("Header check failed\n"); +- *length_read = 0; +- header->magic = 0; +- } + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); -+ -+ if (result < 0) { ++ if (result != 0) { + ERROR("%s: io_open (%i)\n", __func__, result); + return result; + } -+ -+ /* Reset magic header value */ -+ header->magic = 0; -+ -+ while (header->magic == 0U) { -+ result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img); -+ if (result != 0) { -+ ERROR("%s: io_seek (%i)\n", __func__, result); -+ break; -+ } -+ -+ result = io_read(backend_handle, (uintptr_t)header, -+ MAX_LBA_SIZE, (size_t *)&bytes_read); -+ if (result != 0) { -+ if (current_part->bkp_offset == 0U) { -+ ERROR("%s: io_read (%i)\n", __func__, result); -+ } -+ header->magic = 0; -+ } -+ -+ if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) || -+ (header->binary_type != current_part->binary_type) || -+ (header->image_length >= stm32image_dev.device_size)) { -+ VERBOSE("%s: partition %s not found at %x\n", -+ __func__, current_part->name, *stm32_img); -+ -+ if (current_part->bkp_offset == 0U) { -+ result = -ENOMEM; -+ break; -+ } -+ -+ /* Header not correct, check next offset for backup */ -+ *stm32_img += current_part->bkp_offset; -+ if (*stm32_img > stm32image_dev.device_size) { -+ /* No backup found, end of device reached */ -+ WARN("%s : partition %s not found\n", -+ __func__, current_part->name); -+ result = -ENOMEM; -+ break; -+ } -+ header->magic = 0; -+ } -+ } -+ -+ io_close(backend_handle); -+ + +- result = stm32mp_auth_image(header, buffer); +- if (result != 0) { +- ERROR("Authentication Failed (%i)\n", result); +- return result; +- } ++ result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img + offset); + if (result != 0) { -+ return result; ++ ERROR("%s: io_seek (%i)\n", __func__, result); ++ goto out; + } + +- io_close(backend_handle); ++ result = io_read(backend_handle, (uintptr_t)local_buffer, ++ local_length, length_read); ++ if (result != 0) { ++ ERROR("%s: io_read (%i)\n", __func__, result); ++ goto out; + } + ++ /* Adding part of size already read from header */ ++ *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); + -+ if (header->image_length < stm32image_dev.lba_size) { -+ *length = stm32image_dev.lba_size; -+ } else { -+ *length = header->image_length; -+ } -+ -+ INFO("STM32 Image size : %lu\n", (unsigned long)*length); -+ -+ return 0; -+} -+ -+/* Read data from a partition */ -+static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ -+ int result = 0; -+ uint8_t *local_buffer = (uint8_t *)buffer; -+ boot_api_image_header_t *header = -+ (boot_api_image_header_t *)first_lba_buffer; -+ -+ assert(entity != NULL); -+ assert(buffer != 0U); -+ assert(length_read != NULL); -+ -+ *length_read = 0U; -+ -+ while (*length_read == 0U) { -+ int offset; -+ int local_length; -+ uintptr_t backend_handle; -+ -+ if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { -+ /* Check for backup as image is corrupted */ -+ if (current_part->bkp_offset == 0U) { -+ result = -ENOMEM; -+ break; -+ } -+ -+ *stm32_img += current_part->bkp_offset; -+ if (*stm32_img >= stm32image_dev.device_size) { -+ /* End of device reached */ -+ result = -ENOMEM; -+ break; -+ } -+ -+ local_buffer = (uint8_t *)buffer; -+ -+ result = stm32image_partition_size(entity, &length); -+ if (result != 0) { -+ break; -+ } -+ } -+ -+ /* Part of image already loaded with the header */ -+ memcpy(local_buffer, (uint8_t *)first_lba_buffer + -+ sizeof(boot_api_image_header_t), -+ MAX_LBA_SIZE - sizeof(boot_api_image_header_t)); -+ local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); -+ offset = MAX_LBA_SIZE; -+ -+ /* New image length to be read */ -+ local_length = round_up(length - -+ ((MAX_LBA_SIZE) - -+ sizeof(boot_api_image_header_t)), -+ stm32image_dev.lba_size); -+ -+ if ((header->load_address != 0U) && -+ (header->load_address != buffer)) { -+ ERROR("Wrong load address\n"); -+ panic(); -+ } -+ -+ result = io_open(backend_dev_handle, backend_image_spec, -+ &backend_handle); -+ -+ if (result != 0) { -+ ERROR("%s: io_open (%i)\n", __func__, result); -+ break; -+ } -+ -+ result = io_seek(backend_handle, IO_SEEK_SET, -+ *stm32_img + offset); -+ -+ if (result != 0) { -+ ERROR("%s: io_seek (%i)\n", __func__, result); -+ *length_read = 0; -+ io_close(backend_handle); -+ break; -+ } -+ -+ result = io_read(backend_handle, (uintptr_t)local_buffer, -+ local_length, length_read); -+ -+ /* Adding part of size already read from header */ -+ *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); -+ -+ if (result != 0) { -+ ERROR("%s: io_read (%i)\n", __func__, result); -+ *length_read = 0; -+ header->magic = 0; -+ continue; -+ } -+ -+ result = check_header(header, buffer); -+ if (result != 0) { -+ ERROR("Header check failed\n"); -+ *length_read = 0; -+ header->magic = 0; -+ } -+ -+#ifdef AUTHENTICATE_BL33 -+ result = check_authentication(header, buffer); -+ if (result != 0) { -+ ERROR("Authentication Failed\n"); -+ return result; -+ } -+#else -+ NOTICE("Authentication disabled: No signature check\n"); -+#endif -+ -+ io_close(backend_handle); -+ } -+ -+ return result; -+} -+ -+/* Close a partition */ -+static int stm32image_partition_close(io_entity_t *entity) -+{ -+ current_part = NULL; -+ -+ return 0; -+} -+ -+/* Register the stm32image driver with the IO abstraction */ -+int register_io_dev_stm32image(const io_dev_connector_t **dev_con) -+{ -+ int result; -+ -+ assert(dev_con != NULL); -+ -+ result = io_register_device(&stm32image_dev_info); -+ if (result == 0) { -+ *dev_con = &stm32image_dev_connector; -+ } -+ -+ return result; -+} ++out: ++ io_close(backend_handle); + return result; + } + diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c -new file mode 100644 -index 0000000..6d91a9f ---- /dev/null +index ea6fbb2b9..6055e4d84 100644 +--- a/drivers/st/iwdg/stm32_iwdg.c +++ b/drivers/st/iwdg/stm32_iwdg.c -@@ -0,0 +1,289 @@ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. 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 -+ -+/* IWDG Compatibility */ -+#define IWDG_COMPAT "st,stm32mp1-iwdg" +@@ -22,11 +22,30 @@ + #include + #include + +#define IWDG_TIMEOUT_MS U(100) + -+/* IWDG registers offsets */ -+#define IWDG_KR_OFFSET 0x00U + /* IWDG registers offsets */ + #define IWDG_KR_OFFSET 0x00U +#define IWDG_PR_OFFSET 0x04U +#define IWDG_RLR_OFFSET 0x08U +#define IWDG_SR_OFFSET 0x0CU +#define IWDG_EWCR_OFFSET 0x14U -+ -+/* Registers values */ + + /* Registers values */ +#define IWDG_KR_ACCESS_KEY 0x5555 -+#define IWDG_KR_RELOAD_KEY 0xAAAA + #define IWDG_KR_RELOAD_KEY 0xAAAA +#define IWDG_KR_START_KEY 0xCCCC + +#define IWDG_PR_DIV_4 0x00 @@ -12806,31 +13126,13 @@ index 0000000..6d91a9f +#define IWDG_EWCR_EWIE BIT(15) +#define IWDG_EWCR_EWIC BIT(14) +#define IWDG_EWCR_EWIT_MASK GENMASK(11, 0) -+ -+struct stm32_iwdg_instance { -+ uintptr_t base; -+ unsigned long clock; -+ uint8_t flags; -+ int num_irq; -+}; -+ -+static struct stm32_iwdg_instance stm32_iwdg[IWDG_MAX_INSTANCE]; -+ -+static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset) -+{ -+ int node; -+ -+ node = dt_get_node(info, offset, IWDG_COMPAT); -+ if (node < 0) { -+ if (offset == -1) { -+ VERBOSE("%s: No IDWG found\n", __func__); -+ } -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return node; -+} -+ + + struct stm32_iwdg_instance { + uintptr_t base; +@@ -52,6 +71,109 @@ static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset) + return node; + } + +#if defined(IMAGE_BL32) +void __dead2 stm32_iwdg_it_handler(int id) +{ @@ -12852,7 +13154,7 @@ index 0000000..6d91a9f + + VERBOSE("CPU %x IT Watchdog %d\n", cpu, instance + 1); + -+ stm32_iwdg_refresh(instance); ++ stm32_iwdg_refresh(); + + stm32mp_clk_enable(iwdg->clock); + @@ -12934,85 +13236,21 @@ index 0000000..6d91a9f +} +#endif + -+void stm32_iwdg_refresh(uint32_t instance) -+{ -+ struct stm32_iwdg_instance *iwdg = &stm32_iwdg[instance]; -+ -+ assert(iwdg); -+ -+ stm32mp_clk_enable(iwdg->clock); -+ -+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); -+ -+ stm32mp_clk_disable(iwdg->clock); -+} -+ -+int stm32_iwdg_init(void) -+{ -+ int node = -1; + void stm32_iwdg_refresh(void) + { + uint8_t i; +@@ -74,6 +196,7 @@ void stm32_iwdg_refresh(void) + int stm32_iwdg_init(void) + { + int node = -1; + int __unused res; -+ struct dt_node_info dt_info; -+ void *fdt; -+ uint32_t __unused count = 0; -+ uint32_t idx; -+ uint32_t __unused otp_value; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ for (node = stm32_iwdg_get_dt_node(&dt_info, node); -+ node != -FDT_ERR_NOTFOUND; -+ node = stm32_iwdg_get_dt_node(&dt_info, node)) { -+ struct stm32_iwdg_instance *iwdg; -+ uint32_t hw_init; -+ -+ idx = stm32_iwdg_get_instance(dt_info.base); -+ iwdg = &stm32_iwdg[idx]; -+ iwdg->base = dt_info.base; -+ iwdg->clock = (unsigned long)dt_info.clock; -+ -+ /* DT can specify low power cases */ -+ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) != -+ NULL) { -+ iwdg->flags |= IWDG_ENABLE_ON_STOP; -+ } -+ -+ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) != -+ NULL) { -+ iwdg->flags |= IWDG_ENABLE_ON_STANDBY; -+ } -+ -+ /* Explicit list of supported bit flags */ -+ hw_init = stm32_iwdg_get_otp_config(iwdg->base); -+ -+ if ((hw_init & IWDG_HW_ENABLED) != 0) { -+ if (dt_info.status == DT_DISABLED) { -+ ERROR("OTP enabled but iwdg%d DT-disabled\n", -+ idx + 1); -+ panic(); -+ } -+ iwdg->flags |= IWDG_HW_ENABLED; -+ } -+ -+ if (dt_info.status == DT_DISABLED) { -+ zeromem((void *)iwdg, -+ sizeof(struct stm32_iwdg_instance)); -+ goto next; -+ } -+ -+ if ((hw_init & IWDG_ENABLE_ON_STOP) != 0) { -+ iwdg->flags |= IWDG_ENABLE_ON_STOP; -+ } -+ -+ if ((hw_init & IWDG_ENABLE_ON_STANDBY) != 0) { -+ iwdg->flags |= IWDG_ENABLE_ON_STANDBY; -+ } -+ -+ VERBOSE("IWDG%u found, %ssecure\n", idx + 1, -+ ((dt_info.status & DT_NON_SECURE) != 0) ? -+ "non " : ""); -+ + struct dt_node_info dt_info; + void *fdt; + uint32_t __unused count = 0; +@@ -137,6 +260,23 @@ int stm32_iwdg_init(void) + ((dt_info.status & DT_NON_SECURE) != 0) ? + "non-" : ""); + + if ((dt_info.status & DT_NON_SECURE) != 0) { + stm32mp_register_non_secure_periph_iomem(iwdg->base); + } else { @@ -13030,177 +13268,49 @@ index 0000000..6d91a9f + return res; + } +#endif -+#if defined(IMAGE_BL2) -+ if (stm32_iwdg_shadow_update(iwdg->base, iwdg->flags) != -+ BSEC_OK) { -+ return -1; -+ } -+#endif -+ -+next: -+ count++; -+ } -+ -+ VERBOSE("%u IWDG instance%s found\n", count, count > 1 ? "s" : ""); -+ -+ return 0; -+} + #if defined(IMAGE_BL2) + if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) { + return -1; diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c -new file mode 100644 -index 0000000..620087e ---- /dev/null +index 24e6efe98..782127c49 100644 +--- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c -@@ -0,0 +1,752 @@ -+/* -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ +@@ -50,6 +50,7 @@ + + /* SDMMC power control register */ + #define SDMMC_POWER_PWRCTRL GENMASK(1, 0) ++#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1) + #define SDMMC_POWER_DIRPOL BIT(4) + + /* SDMMC clock control register */ +@@ -116,6 +117,15 @@ + #define TIMEOUT_US_10_MS 10000U + #define TIMEOUT_US_1_S 1000000U + ++/* Power cycle delays in ms */ ++#define VCC_POWER_OFF_DELAY 2 ++#define VCC_POWER_ON_DELAY 2 ++#define POWER_CYCLE_DELAY 2 ++#define POWER_OFF_DELAY 2 ++#define POWER_ON_DELAY 1 + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#define TIMEOUT_US_1MS U(1000) + -+/* Registers offsets */ -+#define SDMMC_POWER 0x00U -+#define SDMMC_CLKCR 0x04U -+#define SDMMC_ARGR 0x08U -+#define SDMMC_CMDR 0x0CU -+#define SDMMC_RESPCMDR 0x10U -+#define SDMMC_RESP1R 0x14U -+#define SDMMC_RESP2R 0x18U -+#define SDMMC_RESP3R 0x1CU -+#define SDMMC_RESP4R 0x20U -+#define SDMMC_DTIMER 0x24U -+#define SDMMC_DLENR 0x28U -+#define SDMMC_DCTRLR 0x2CU -+#define SDMMC_DCNTR 0x30U -+#define SDMMC_STAR 0x34U -+#define SDMMC_ICR 0x38U -+#define SDMMC_MASKR 0x3CU -+#define SDMMC_ACKTIMER 0x40U -+#define SDMMC_IDMACTRLR 0x50U -+#define SDMMC_IDMABSIZER 0x54U -+#define SDMMC_IDMABASE0R 0x58U -+#define SDMMC_IDMABASE1R 0x5CU -+#define SDMMC_FIFOR 0x80U -+ -+/* SDMMC power control register */ -+#define SDMMC_POWER_PWRCTRL GENMASK(1, 0) -+#define SDMMC_POWER_DIRPOL BIT(4) -+ -+/* SDMMC clock control register */ -+#define SDMMC_CLKCR_WIDBUS_4 BIT(14) -+#define SDMMC_CLKCR_WIDBUS_8 BIT(15) -+#define SDMMC_CLKCR_NEGEDGE BIT(16) -+#define SDMMC_CLKCR_HWFC_EN BIT(17) -+#define SDMMC_CLKCR_SELCLKRX_0 BIT(20) -+ -+/* SDMMC command register */ -+#define SDMMC_CMDR_CMDTRANS BIT(6) -+#define SDMMC_CMDR_CMDSTOP BIT(7) -+#define SDMMC_CMDR_WAITRESP GENMASK(9, 8) -+#define SDMMC_CMDR_WAITRESP_SHORT BIT(8) -+#define SDMMC_CMDR_WAITRESP_SHORT_NOCRC BIT(9) -+#define SDMMC_CMDR_CPSMEN BIT(12) -+ -+/* SDMMC data control register */ -+#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_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) -+#define SDMMC_STAR_DCRCFAIL BIT(1) -+#define SDMMC_STAR_CTIMEOUT BIT(2) -+#define SDMMC_STAR_DTIMEOUT BIT(3) -+#define SDMMC_STAR_TXUNDERR BIT(4) -+#define SDMMC_STAR_RXOVERR BIT(5) -+#define SDMMC_STAR_CMDREND BIT(6) -+#define SDMMC_STAR_CMDSENT BIT(7) -+#define SDMMC_STAR_DATAEND BIT(8) -+#define SDMMC_STAR_DBCKEND BIT(10) -+#define SDMMC_STAR_DPSMACT BIT(12) -+#define SDMMC_STAR_RXFIFOHF BIT(15) -+#define SDMMC_STAR_RXFIFOE BIT(19) -+#define SDMMC_STAR_IDMATE BIT(27) -+#define SDMMC_STAR_IDMABTC BIT(28) -+ -+/* SDMMC DMA control register */ -+#define SDMMC_IDMACTRLR_IDMAEN BIT(0) -+ -+#define SDMMC_STATIC_FLAGS (SDMMC_STAR_CCRCFAIL | \ -+ SDMMC_STAR_DCRCFAIL | \ -+ SDMMC_STAR_CTIMEOUT | \ -+ SDMMC_STAR_DTIMEOUT | \ -+ SDMMC_STAR_TXUNDERR | \ -+ SDMMC_STAR_RXOVERR | \ -+ SDMMC_STAR_CMDREND | \ -+ SDMMC_STAR_CMDSENT | \ -+ SDMMC_STAR_DATAEND | \ -+ SDMMC_STAR_DBCKEND | \ -+ SDMMC_STAR_IDMATE | \ -+ SDMMC_STAR_IDMABTC) -+ -+#define TIMEOUT_10_MS ms2tick(10) -+#define TIMEOUT_1_S s2tick(1) -+ -+#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" -+ -+static void stm32_sdmmc2_init(void); -+static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd); -+static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd); -+static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width); -+static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size); -+static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size); -+static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size); -+ -+static const struct mmc_ops stm32_sdmmc2_ops = { -+ .init = stm32_sdmmc2_init, -+ .send_cmd = stm32_sdmmc2_send_cmd, -+ .set_ios = stm32_sdmmc2_set_ios, -+ .prepare = stm32_sdmmc2_prepare, -+ .read = stm32_sdmmc2_read, -+ .write = stm32_sdmmc2_write, -+}; -+ -+static struct stm32_sdmmc2_params sdmmc2_params; -+ -+#pragma weak plat_sdmmc2_use_dma -+bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory) -+{ -+ return false; -+} + #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" + + static void stm32_sdmmc2_init(void); +@@ -137,12 +147,35 @@ static const struct mmc_ops stm32_sdmmc2_ops = { + + static struct stm32_sdmmc2_params sdmmc2_params; + ++static bool next_cmd_is_acmd; + + #pragma weak plat_sdmmc2_use_dma + bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory) + { + return false; + } + +static void dump_registers(void) +{ + uintptr_t base = sdmmc2_params.reg_base; @@ -13222,3645 +13332,274 @@ index 0000000..620087e + INFO("SDMMC_ACKTIMER = 0x%x\n", mmio_read_32(base + SDMMC_ACKTIMER)); +} + -+static void stm32_sdmmc2_init(void) -+{ -+ uint32_t clock_div; -+ uintptr_t base = sdmmc2_params.reg_base; + static void stm32_sdmmc2_init(void) + { + uint32_t clock_div; +@@ -153,6 +186,26 @@ static void stm32_sdmmc2_init(void) + freq = MIN(sdmmc2_params.max_freq, freq); + } + ++ if (sdmmc2_params.vmmc_regu.id != -1) { ++ stm32mp_regulator_register(&sdmmc2_params.vmmc_regu); ++ stm32mp_regulator_disable(&sdmmc2_params.vmmc_regu); ++ } + -+ clock_div = div_round_up(sdmmc2_params.clk_rate, -+ STM32MP_MMC_INIT_FREQ * 2); -+ -+ mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | -+ sdmmc2_params.negedge | -+ sdmmc2_params.pin_ckin); ++ mdelay(VCC_POWER_OFF_DELAY); + + mmio_write_32(base + SDMMC_POWER, -+ SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); ++ SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol); ++ mdelay(POWER_CYCLE_DELAY); + -+ mdelay(1); -+} -+ -+static int stm32_sdmmc2_stop_transfer(void) -+{ -+ struct mmc_cmd cmd_stop; -+ -+ zeromem(&cmd_stop, sizeof(struct mmc_cmd)); -+ -+ cmd_stop.cmd_idx = MMC_CMD(12); -+ cmd_stop.resp_type = MMC_RESPONSE_R1B; -+ -+ return stm32_sdmmc2_send_cmd(&cmd_stop); -+} -+ -+static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) -+{ -+ uint64_t start; -+ uint32_t flags_cmd, status; -+ uint32_t flags_data = 0; -+ int err = 0; -+ uintptr_t base = sdmmc2_params.reg_base; -+ unsigned int cmd_reg, arg_reg; -+ -+ if (cmd == NULL) { -+ return -EINVAL; ++ if (sdmmc2_params.vmmc_regu.id != -1) { ++ stm32mp_regulator_enable(&sdmmc2_params.vmmc_regu); + } + -+ flags_cmd = SDMMC_STAR_CTIMEOUT; -+ arg_reg = cmd->cmd_arg; ++ mdelay(VCC_POWER_ON_DELAY); + -+ if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) { -+ mmio_write_32(base + SDMMC_CMDR, 0); -+ } ++ mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol); ++ mdelay(POWER_OFF_DELAY); + -+ cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN; -+ -+ if (cmd->resp_type == 0U) { -+ flags_cmd |= SDMMC_STAR_CMDSENT; -+ } -+ -+ if ((cmd->resp_type & MMC_RSP_48) != 0U) { -+ if ((cmd->resp_type & MMC_RSP_136) != 0U) { -+ flags_cmd |= SDMMC_STAR_CMDREND; -+ cmd_reg |= SDMMC_CMDR_WAITRESP; -+ } else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) { -+ flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL; -+ cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT; -+ } else { -+ flags_cmd |= SDMMC_STAR_CMDREND; -+ cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC; -+ } -+ } -+ -+ switch (cmd->cmd_idx) { -+ case MMC_CMD(1): -+ arg_reg |= OCR_POWERUP; -+ break; -+ case MMC_CMD(8): -+ if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { + clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U); + + mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | +@@ -162,7 +215,7 @@ static void stm32_sdmmc2_init(void) + mmio_write_32(base + SDMMC_POWER, + SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); + +- mdelay(1); ++ mdelay(POWER_ON_DELAY); + } + + static int stm32_sdmmc2_stop_transfer(void) +@@ -220,6 +273,20 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) + case MMC_CMD(1): + arg_reg |= OCR_POWERUP; + break; ++ case MMC_CMD(6): ++ if ((sdmmc2_params.device_info->mmc_dev_type == MMC_IS_SD_HC) && ++ (!next_cmd_is_acmd)) { + cmd_reg |= SDMMC_CMDR_CMDTRANS; -+ } -+ break; -+ case MMC_CMD(12): -+ cmd_reg |= SDMMC_CMDR_CMDSTOP; -+ break; -+ case MMC_CMD(17): -+ case MMC_CMD(18): -+ cmd_reg |= SDMMC_CMDR_CMDTRANS; -+ if (sdmmc2_params.use_dma) { -+ flags_data |= SDMMC_STAR_DCRCFAIL | -+ SDMMC_STAR_DTIMEOUT | -+ SDMMC_STAR_DATAEND | -+ SDMMC_STAR_RXOVERR | -+ SDMMC_STAR_IDMATE; -+ } -+ break; -+ case MMC_ACMD(41): -+ arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4; -+ break; -+ case MMC_ACMD(51): -+ cmd_reg |= SDMMC_CMDR_CMDTRANS; -+ if (sdmmc2_params.use_dma) { -+ flags_data |= SDMMC_STAR_DCRCFAIL | -+ SDMMC_STAR_DTIMEOUT | -+ SDMMC_STAR_DATAEND | -+ SDMMC_STAR_RXOVERR | -+ SDMMC_STAR_IDMATE | -+ SDMMC_STAR_DBCKEND; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) { -+ mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); -+ } -+ -+ mmio_write_32(base + SDMMC_ARGR, arg_reg); -+ -+ mmio_write_32(base + SDMMC_CMDR, cmd_reg); -+ -+ status = mmio_read_32(base + SDMMC_STAR); -+ -+ start = timeout_start(); -+ -+ while ((status & flags_cmd) == 0U) { -+ if (timeout_elapsed(start, TIMEOUT_10_MS)) { -+ err = -ETIMEDOUT; -+ ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n", -+ __func__, cmd->cmd_idx, status); -+ goto err_exit; -+ } -+ -+ status = mmio_read_32(base + SDMMC_STAR); -+ } -+ -+ if ((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) { -+ if ((status & SDMMC_STAR_CTIMEOUT) != 0U) { -+ err = -ETIMEDOUT; -+ /* -+ * Those timeouts can occur, and framework will handle -+ * the retries. CMD8 is expected to return this timeout -+ * for eMMC -+ */ -+ if (!((cmd->cmd_idx == MMC_CMD(1)) || -+ (cmd->cmd_idx == MMC_CMD(13)) || -+ ((cmd->cmd_idx == MMC_CMD(8)) && -+ (cmd->resp_type == MMC_RESPONSE_R7)))) { -+ ERROR("%s: CTIMEOUT (cmd = %d,status = %x)\n", -+ __func__, cmd->cmd_idx, status); -+ } -+ } else { -+ err = -EIO; -+ ERROR("%s: CRCFAIL (cmd = %d,status = %x)\n", -+ __func__, cmd->cmd_idx, status); -+ } -+ -+ goto err_exit; -+ } -+ -+ if ((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) { -+ if ((cmd->cmd_idx == MMC_CMD(9)) && -+ ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) { -+ /* Need to invert response to match CSD structure */ -+ cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R); -+ cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R); -+ cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R); -+ cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R); -+ } else { -+ cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R); -+ if ((cmd_reg & SDMMC_CMDR_WAITRESP) == -+ SDMMC_CMDR_WAITRESP) { -+ cmd->resp_data[1] = mmio_read_32(base + -+ SDMMC_RESP2R); -+ cmd->resp_data[2] = mmio_read_32(base + -+ SDMMC_RESP3R); -+ cmd->resp_data[3] = mmio_read_32(base + -+ SDMMC_RESP4R); ++ if (sdmmc2_params.use_dma) { ++ flags_data |= SDMMC_STAR_DCRCFAIL | ++ SDMMC_STAR_DTIMEOUT | ++ SDMMC_STAR_DATAEND | ++ SDMMC_STAR_RXOVERR | ++ SDMMC_STAR_IDMATE | ++ SDMMC_STAR_DBCKEND; + } + } -+ } -+ -+ if (flags_data == 0U) { -+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); -+ -+ return 0; -+ } -+ -+ status = mmio_read_32(base + SDMMC_STAR); -+ -+ start = timeout_start(); -+ -+ while ((status & flags_data) == 0U) { -+ if (timeout_elapsed(start, TIMEOUT_10_MS)) { -+ ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n", -+ __func__, cmd->cmd_idx, status); -+ err = -ETIMEDOUT; -+ goto err_exit; -+ } -+ -+ status = mmio_read_32(base + SDMMC_STAR); -+ }; -+ -+ if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL | -+ SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR | -+ SDMMC_STAR_IDMATE)) != 0U) { -+ ERROR("%s: Error flag (cmd = %d,status = %x)\n", __func__, -+ cmd->cmd_idx, status); -+ err = -EIO; -+ } -+ -+err_exit: -+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); -+ mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS); -+ -+ if ((err != 0) && ((status & SDMMC_STAR_DPSMACT) != 0U)) { -+ int ret_stop = stm32_sdmmc2_stop_transfer(); -+ -+ if (ret_stop != 0) { -+ return ret_stop; -+ } -+ } -+ -+ return err; -+} -+ -+static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd) -+{ -+ int8_t retry; -+ int err = 0; -+ -+ assert(cmd != NULL); -+ -+ for (retry = 0; retry <= 3; retry++) { -+ err = stm32_sdmmc2_send_cmd_req(cmd); -+ if (err == 0) { -+ return err; -+ } -+ -+ if ((cmd->cmd_idx == MMC_CMD(1)) || -+ (cmd->cmd_idx == MMC_CMD(13))) { -+ return 0; /* Retry managed by framework */ -+ } -+ -+ /* Command 8 is expected to fail for eMMC */ -+ if (!(cmd->cmd_idx == MMC_CMD(8))) { -+ WARN(" CMD%d, Retry: %d, Error: %d\n", -+ cmd->cmd_idx, retry, err); -+ } -+ -+ udelay(10); -+ } -+ -+ return err; -+} -+ -+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 clk_rate = sdmmc2_params.clk_rate; -+ uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq; -+ -+ switch (width) { -+ case MMC_BUS_WIDTH_1: + break; -+ case MMC_BUS_WIDTH_4: -+ bus_cfg |= SDMMC_CLKCR_WIDBUS_4; -+ break; -+ case MMC_BUS_WIDTH_8: -+ bus_cfg |= SDMMC_CLKCR_WIDBUS_8; -+ break; -+ default: -+ panic(); -+ break; -+ } + case MMC_CMD(8): + if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { + cmd_reg |= SDMMC_CMDR_CMDTRANS; +@@ -257,6 +324,8 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) + break; + } + ++ next_cmd_is_acmd = (cmd->cmd_idx == MMC_CMD(55)); + -+ if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { -+ if (max_bus_freq >= 52000000U) { -+ max_freq = STM32MP_EMMC_HIGH_SPEED_MAX_FREQ; -+ } else { -+ max_freq = STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ; -+ } -+ } else { -+ if (max_bus_freq >= 50000000U) { -+ max_freq = STM32MP_SD_HIGH_SPEED_MAX_FREQ; -+ } else { -+ max_freq = STM32MP_SD_NORMAL_SPEED_MAX_FREQ; -+ } -+ } -+ -+ clock_div = div_round_up(clk_rate, max_freq * 2); -+ -+ mmio_write_32(base + SDMMC_CLKCR, -+ SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg | -+ sdmmc2_params.negedge | -+ sdmmc2_params.pin_ckin); -+ -+ return 0; -+} -+ -+static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) -+{ -+ struct mmc_cmd cmd; -+ int ret; -+ uintptr_t base = sdmmc2_params.reg_base; -+ uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR; -+ -+ if (size == 8U) { -+ data_ctrl |= SDMMC_DBLOCKSIZE_8; -+ } else { -+ data_ctrl |= SDMMC_DBLOCKSIZE_512; -+ } -+ -+ sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf); -+ -+ if (sdmmc2_params.use_dma) { -+ inv_dcache_range(buf, size); -+ } -+ -+ /* Prepare CMD 16*/ -+ mmio_write_32(base + SDMMC_DTIMER, 0); -+ -+ mmio_write_32(base + SDMMC_DLENR, 0); -+ -+ mmio_write_32(base + SDMMC_DCTRLR, 0); -+ -+ 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.resp_type = MMC_RESPONSE_R1; -+ -+ ret = stm32_sdmmc2_send_cmd(&cmd); -+ if (ret != 0) { -+ ERROR("CMD16 failed\n"); -+ return ret; -+ } -+ -+ /* Prepare data command */ -+ mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); -+ -+ mmio_write_32(base + SDMMC_DLENR, size); -+ -+ if (sdmmc2_params.use_dma) { -+ mmio_write_32(base + SDMMC_IDMACTRLR, -+ SDMMC_IDMACTRLR_IDMAEN); -+ mmio_write_32(base + SDMMC_IDMABASE0R, buf); -+ -+ flush_dcache_range(buf, size); -+ } -+ -+ mmio_clrsetbits_32(base + SDMMC_DCTRLR, -+ SDMMC_DCTRLR_CLEAR_MASK, -+ data_ctrl); -+ -+ return 0; -+} -+ -+static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) -+{ -+ uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL | -+ SDMMC_STAR_DTIMEOUT; -+ uint32_t flags = error_flags | SDMMC_STAR_DATAEND; -+ uint32_t status; -+ uint32_t *buffer; -+ uintptr_t base = sdmmc2_params.reg_base; -+ uintptr_t fifo_reg = base + SDMMC_FIFOR; -+ unsigned int start; -+ int ret; -+ -+ /* Assert buf is 4 bytes aligned */ -+ assert((buf & GENMASK(1, 0)) == 0U); -+ -+ buffer = (uint32_t *)buf; -+ -+ if (sdmmc2_params.use_dma) { -+ inv_dcache_range(buf, size); -+ -+ return 0; -+ } -+ -+ if (size <= MMC_BLOCK_SIZE) { -+ flags |= SDMMC_STAR_DBCKEND; -+ } -+ -+ start = timeout_start(); -+ -+ do { -+ status = mmio_read_32(base + SDMMC_STAR); -+ -+ if ((status & error_flags) != 0U) { -+ ERROR("%s: Read error (status = %x)\n", __func__, -+ status); + if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) { + mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); + } +@@ -550,6 +619,7 @@ static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) + if ((status & error_flags) != 0U) { + ERROR("%s: Read error (status = %x)\n", __func__, + status); + dump_registers(); -+ mmio_write_32(base + SDMMC_DCTRLR, -+ SDMMC_DCTRLR_FIFORST); -+ -+ mmio_write_32(base + SDMMC_ICR, -+ SDMMC_STATIC_FLAGS); -+ -+ ret = stm32_sdmmc2_stop_transfer(); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ return -EIO; -+ } -+ -+ if (timeout_elapsed(start, TIMEOUT_1_S)) { -+ ERROR("%s: timeout 1s (status = %x)\n", -+ __func__, status); + mmio_write_32(base + SDMMC_DCTRLR, + SDMMC_DCTRLR_FIFORST); + +@@ -567,6 +637,7 @@ static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) + if (timeout_elapsed(timeout)) { + ERROR("%s: timeout 1s (status = %x)\n", + __func__, status); + dump_registers(); -+ mmio_write_32(base + SDMMC_ICR, -+ SDMMC_STATIC_FLAGS); -+ -+ ret = stm32_sdmmc2_stop_transfer(); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ return -ETIMEDOUT; -+ } -+ -+ if (size < (8U * sizeof(uint32_t))) { -+ if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) && -+ ((status & SDMMC_STAR_RXFIFOE) == 0U)) { -+ *buffer = mmio_read_32(fifo_reg); -+ buffer++; -+ } -+ } else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) { -+ uint32_t count; -+ -+ /* Read data from SDMMC Rx FIFO */ -+ for (count = 0; count < 8U; count++) { -+ *buffer = mmio_read_32(fifo_reg); -+ buffer++; -+ } -+ } -+ } while ((status & flags) == 0U); -+ -+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); -+ -+ if ((status & SDMMC_STAR_DPSMACT) != 0U) { -+ WARN("%s: DPSMACT=1, send stop\n", __func__); -+ return stm32_sdmmc2_stop_transfer(); -+ } -+ -+ return 0; -+} -+ -+static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size) -+{ -+ return 0; -+} -+ -+static int stm32_sdmmc2_dt_get_config(void) -+{ -+ int sdmmc_node; -+ void *fdt = NULL; -+ const fdt32_t *cuint; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ if (fdt == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT); -+ -+ while (sdmmc_node != -FDT_ERR_NOTFOUND) { -+ cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL); -+ if (cuint == NULL) { -+ continue; -+ } -+ -+ if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) { -+ break; -+ } -+ -+ sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node, -+ DT_SDMMC2_COMPAT); -+ } -+ -+ if (sdmmc_node == -FDT_ERR_NOTFOUND) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ if (fdt_get_status(sdmmc_node) == DT_DISABLED) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ if (dt_set_pinctrl_config(sdmmc_node) != 0) { -+ return -FDT_ERR_BADVALUE; -+ } -+ -+ cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ cuint++; -+ sdmmc2_params.clock_id = fdt32_to_cpu(*cuint); -+ -+ cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ cuint++; -+ sdmmc2_params.reset_id = fdt32_to_cpu(*cuint); -+ -+ if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { -+ sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; -+ } -+ -+ if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) { -+ sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL; -+ } -+ -+ if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) { -+ sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE; -+ } -+ -+ cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL); -+ if (cuint != NULL) { -+ switch (fdt32_to_cpu(*cuint)) { -+ case 4: -+ sdmmc2_params.bus_width = MMC_BUS_WIDTH_4; -+ break; -+ -+ case 8: -+ sdmmc2_params.bus_width = MMC_BUS_WIDTH_8; -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+unsigned long long stm32_sdmmc2_mmc_get_device_size(void) -+{ -+ return sdmmc2_params.device_info->device_size; -+} -+ -+int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) -+{ -+ assert((params != NULL) && -+ ((params->reg_base & MMC_BLOCK_MASK) == 0U) && -+ ((params->bus_width == MMC_BUS_WIDTH_1) || -+ (params->bus_width == MMC_BUS_WIDTH_4) || -+ (params->bus_width == MMC_BUS_WIDTH_8))); -+ -+ memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); -+ -+ if (stm32_sdmmc2_dt_get_config() != 0) { -+ ERROR("%s: DT error\n", __func__); -+ return -ENOMEM; -+ } -+ -+ stm32mp_clk_enable(sdmmc2_params.clock_id); -+ -+ stm32mp_reset_assert(sdmmc2_params.reset_id); -+ udelay(2); -+ stm32mp_reset_deassert(sdmmc2_params.reset_id); -+ mdelay(1); -+ -+ sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id); -+ -+ return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate, -+ sdmmc2_params.bus_width, sdmmc2_params.flags, -+ sdmmc2_params.device_info); -+} -diff --git a/drivers/st/nand/io_nand.c b/drivers/st/nand/io_nand.c -new file mode 100644 -index 0000000..54ac8fb ---- /dev/null -+++ b/drivers/st/nand/io_nand.c -@@ -0,0 +1,228 @@ -+/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* NAND device functions */ -+static int nand_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info); -+static int nand_block_open(io_dev_info_t *dev_info, const uintptr_t spec, -+ io_entity_t *entity); -+static int nand_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); -+static int nand_block_seek(io_entity_t *entity, int mode, -+ signed long long offset); -+static int nand_block_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read); -+static int nand_block_close(io_entity_t *entity); -+static int nand_dev_close(io_dev_info_t *dev_info); -+static io_type_t device_type_nand(void); -+ -+static NAND_HandleTypeDef *hnand; -+static uint64_t seek_offset; -+ -+static const io_dev_connector_t nand_dev_connector = { -+ .dev_open = nand_dev_open -+}; -+ -+static const io_dev_funcs_t nand_dev_funcs = { -+ .type = device_type_nand, -+ .open = nand_block_open, -+ .seek = nand_block_seek, -+ .size = NULL, -+ .read = nand_block_read, -+ .write = NULL, -+ .close = nand_block_close, -+ .dev_init = nand_dev_init, -+ .dev_close = nand_dev_close, -+}; -+ -+static const io_dev_info_t nand_dev_info = { -+ .funcs = &nand_dev_funcs, -+ .info = (uintptr_t)0, -+}; -+ -+/* Identify the device type as memmap */ -+static io_type_t device_type_nand(void) -+{ -+ return IO_TYPE_NAND; -+} -+ -+/* Open a connection to the nand device */ -+static int nand_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info) -+{ -+ uint32_t nb_page_per_block, page_size; -+ -+ assert(dev_info); -+ *dev_info = (io_dev_info_t *)&nand_dev_info; -+ -+ hnand = (NAND_HandleTypeDef *)init_params; -+ -+ if (nand_initialize(hnand) != STD_OK) -+ return -EIO; -+ -+ hnand->Info.page_size_shift = 0; -+ -+ page_size = hnand->Info.PageSize; -+ if (!IS_POWER_OF_TWO(page_size)) -+ return -EINVAL; -+ -+ while (page_size >>= 1) -+ hnand->Info.page_size_shift++; -+ -+ nb_page_per_block = hnand->Info.BlockSize; -+ if (!IS_POWER_OF_TWO(nb_page_per_block)) -+ return -EINVAL; -+ -+ /* Block size is (page_size * number of pages per blocks) */ -+ hnand->Info.block_size_shift = hnand->Info.page_size_shift; -+ while (nb_page_per_block >>= 1) -+ hnand->Info.block_size_shift++; -+ -+ return 0; -+} -+ -+static int nand_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) -+{ -+ return 0; -+} -+ -+/* Close a connection to the nand device */ -+static int nand_dev_close(io_dev_info_t *dev_info) -+{ -+ return 0; -+} -+ -+/* Open a file on the nand device */ -+static int nand_block_open(io_dev_info_t *dev_info, const uintptr_t spec, -+ io_entity_t *entity) -+{ -+ seek_offset = 0; -+ return 0; -+} -+ -+/* Seek to a particular file offset on the nand device */ -+static int nand_block_seek(io_entity_t *entity, int mode, -+ signed long long offset) -+{ -+ seek_offset = offset; -+ return 0; -+} -+ -+/* Read data from a file on the nand device */ -+static int nand_block_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ -+ uint32_t block_size_shift = hnand->Info.block_size_shift; -+ uint32_t page_size_shift = hnand->Info.page_size_shift; -+ uint32_t buffer_index = 0; -+ uint32_t num_sectors_read = seek_offset / BCH_PAGE_SECTOR; -+ uint64_t number_sectors_to_read = length / BCH_PAGE_SECTOR; -+ uint64_t nand_address_block, nand_address_page; -+ NAND_AddressTypeDef nand_address; -+ -+ *length_read = 0; -+ -+ nand_address_block = seek_offset; -+ while (block_size_shift) { -+ nand_address_block >>= 1; -+ if (!nand_address_block) -+ break; -+ block_size_shift--; -+ } -+ -+ nand_address.Block = (uint16_t)nand_address_block; -+ -+ nand_address_page = seek_offset & ((1 << hnand->Info.block_size_shift) -+ - 1); -+ while (page_size_shift) { -+ nand_address_page >>= 1; -+ if (!nand_address_page) -+ break; -+ page_size_shift--; -+ } -+ -+ nand_address.Page = (uint16_t)nand_address_page; -+ -+ while (NAND_Check_Bad_Block(hnand, &nand_address) == BAD_BLOCK) { -+ nand_address.Block++; -+ if (nand_address.Block >= hnand->Info.BlockNb) { -+ ERROR("Cannot find valid block\n"); -+ return -EIO; -+ } -+ } -+ -+ if ((length % BCH_PAGE_SECTOR) != 0) { -+ /* -+ * yes, remainder required, -+ * adjust total number of sectors required -+ * one more page needed to read, -+ * data will not fill all page -+ */ -+ number_sectors_to_read += 1; -+ } -+ -+ /* -+ * Proceed here with reading/copying of -+ * (number_of_pages_remaining_to_read * BCH_PAGE_SECTOR) -+ * from NAND memory to SYSRAM download area -+ */ -+ while (number_sectors_to_read != 0) { -+ uint32_t bch_sector_nb = num_sectors_read % -+ (hnand->Info.PageSize / BCH_PAGE_SECTOR); -+ -+ if (NAND_Read_Logical_Page(hnand, &nand_address, -+ (uint8_t *)(buffer + -+ (buffer_index * -+ BCH_PAGE_SECTOR)), -+ bch_sector_nb) != STD_OK) { -+ VERBOSE("Page read failed or end of NAND reached\n"); -+ return -EIO; -+ } -+ -+ /* Increment read sectors number */ -+ num_sectors_read++; -+ buffer_index++; -+ -+ /* Decrement sectors to read */ -+ number_sectors_to_read--; -+ -+ /* Increment the NAND address */ -+ NAND_Address_Inc(hnand, &nand_address, num_sectors_read); -+ } -+ -+ *length_read = ((num_sectors_read - (seek_offset / BCH_PAGE_SECTOR)) * -+ BCH_PAGE_SECTOR); -+ -+ return 0; -+} -+ -+/* Close a file on the nand device */ -+static int nand_block_close(io_entity_t *entity) -+{ -+ return 0; -+} -+ -+/* Exported functions */ -+ -+/* Register the nand driver with the IO abstraction */ -+int register_io_dev_nand(const io_dev_connector_t **dev_con) -+{ -+ int result; -+ -+ assert(dev_con); -+ -+ result = io_register_device(&nand_dev_info); -+ if (!result) -+ *dev_con = &nand_dev_connector; -+ -+ return result; -+} -diff --git a/drivers/st/nand/nand.c b/drivers/st/nand/nand.c -new file mode 100644 -index 0000000..7f435cc ---- /dev/null -+++ b/drivers/st/nand/nand.c -@@ -0,0 +1,1548 @@ -+/* -+ ****************************************************************************** -+ * @file nand.c -+ * @author mgentilini - MCD IntroPack team - MPU AP v1 bootROM project -+ * @version V0.1 -+ * @date 28-April-2016 -+ * @brief Nand FMC driver module for STM32MP1. -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) STMicroelectronics

-+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ * -+ ****************************************************************************** -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Other internal NAND driver definitions */ -+#define CMD_SECTION ((uint32_t)(1 << 16)) /* A16 high */ -+#define ADDR_SECTION ((uint32_t)(1 << 17)) /* A17 high */ -+#define DATA_SECTION (0) /* A16 and A17 low */ -+ -+#define EIGHT_BIT_ACCESS 0x0 -+#define SIXTEEN_BIT_ACCESS 0x1 -+ -+#define ONFI_SIG_VALUE 0x49464E4F /* "ONFI" */ -+#define EXT_PAGE_SIG_VALUE 0x53505045 /* "EPPS" */ -+ -+/* NAND instance number */ -+#define NAND_INSTANCE_NB 1 -+/* Wait Time following NAND_RESET command sent (30us) */ -+#define NAND_RST_TIMEOUT 30 -+#define NAND_READY_WAIT_TIMEOUT_VAL_250MS_AT_64MHz 16000000 -+ -+/* NAND ECC Calculation wait timeout */ -+#define NAND_ECC_CALCULATION_TIMEOUT_VAL_250MS ms2tick(250) -+ -+#define NAND_ECC_PAGE_SECTOR 512 -+#define NAND_ECC_HAMMING1 1 -+#define NAND_ECC_BCH4 4 -+#define NAND_ECC_BCH8 8 -+#define NAND_ECC_HAMMING1_BYTES_NB_8b 3 -+#define NAND_ECC_BCH4_BYTES_NB_8b 7 -+#define NAND_ECC_BCH8_BYTES_NB_8b 13 -+#define NAND_ECC_HAMMING1_BYTES_NB_16b 4 -+#define NAND_ECC_BCH4_BYTES_NB_16b 8 -+#define NAND_ECC_BCH8_BYTES_NB_16b 14 -+#define PARAM_PAGE_SIZE 256 -+ -+/* NAND memory status */ -+#define NAND_BUSY ((uint32_t)0x00000000U) -+#define NAND_ERROR ((uint32_t)0x00000001U) -+#define NAND_READY ((uint32_t)0x00000040U) -+ -+/* NAND ONFI commands */ -+#define NAND_CMD_RESET ((uint8_t)0xFFU) -+#define NAND_CMD_READID ((uint8_t)0x90U) -+#define NAND_CMD_READID_SIG_ADDR ((uint8_t)0x20U) -+#define NAND_CMD_READ_PARAM_PAGE ((uint8_t)0xECU) -+#define NAND_CMD_READ_1ST ((uint8_t)0x00U) -+#define NAND_CMD_READ_2ND ((uint8_t)0x30U) -+#define NAND_CMD_STATUS ((uint8_t)0x70U) -+#define NAND_CMD_CHANGE_1ST ((uint8_t)0x05U) -+#define NAND_CMD_CHANGE_2ND ((uint8_t)0xE0U) -+ -+/* CRC calculation */ -+#define CRC_POLYNOM 0x8005 -+#define CRC_INIT_VALUE 0x4F4E -+ -+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; -+ -+ tims->thiz = FMC_THIZ; -+ thiz = (tims->thiz + 1) * hclkp; -+ -+ /* -+ * tWAIT > tRP -+ * 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; -+ -+ /* -+ * tSETUP_MEM > tCS - tWAIT -+ * tSETUP_MEM > tALS - tWAIT -+ * tSETUP_MEM > tDS - (tWAIT - tHIZ) -+ */ -+ tset_mem = hclkp; -+ 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)) -+ 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); -+ tims->tset_mem = div_round_up(tset_mem, hclkp); -+ if (tims->tset_mem == 0) -+ tims->tset_mem = 1; -+ -+ /* -+ * 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; -+ if (tset_mem < FMC_TREH_MIN && -+ (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); -+ if ((tset_mem + twait < FMC_TWC_MIN) && -+ (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; -+ -+ /* -+ * tSETUP_ATT > tCS - tWAIT -+ * tSETUP_ATT > tCLS - tWAIT -+ * tSETUP_ATT > tALS - tWAIT -+ * tSETUP_ATT > tRHW - tHOLD_MEM -+ * tSETUP_ATT > tDS - (tWAIT - tHIZ) -+ */ -+ tset_att = hclkp; -+ 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)) -+ tset_att = FMC_TCLS_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; -+ if (twait > thiz && (twait - thiz < FMC_TDS_MIN) && -+ (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; -+ -+ /* -+ * tHOLD_ATT > tALH -+ * tHOLD_ATT > tCH -+ * tHOLD_ATT > tCLH -+ * tHOLD_ATT > tCOH -+ * tHOLD_ATT > tDH -+ * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM -+ * tHOLD_ATT > tADL - tSETUP_MEM -+ * tHOLD_ATT > tWH - tSETUP_MEM -+ * tHOLD_ATT > tWHR - tSETUP_MEM -+ * 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; -+ 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; -+ if (tset_mem < FMC_TADL_MIN && -+ (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; -+ if (tset_mem < FMC_TWHR_MIN && -+ (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); -+ if (tset_att + twait < FMC_TWC_MIN && -+ (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; -+} -+ -+/***************************************************************************** -+ * -+ * Function: Nand_Init -+ * -+ * Description: This function initializes the Nand FMC driver. -+ * -+ * Input parameters: NAND_HandleTypeDef * hNand -+ * uint32_t bus_width -+ * -+ * Output parameters: none -+ * -+ * Return: None -+ * -+ *****************************************************************************/ -+static void Nand_Init(NAND_HandleTypeDef *hNand, uint32_t bus_width, -+ uint32_t bch_algo) -+{ -+ assert(hNand); -+ -+ /* -+ * Initialize NAND control Interface -+ * Wait feature disabled, memory bank disabled, ECC logic disabled, -+ * BCH is selected, TCLR and TAR to max values, ECC sector size to 512B, -+ * BCH 8-bit is selected, enabled read access -+ * -+ * Be careful to not set ECCEN bit before Read Parameter Page command -+ * ECC logic must be enabled just before Read Logical Page -+ * Note: with PWAITEN feature, NAND controller temporizes next accesses, -+ * so no need to wait for ready/not busy after each command -+ */ -+ -+ /* -+ * Parameters should be given by boot_context -+ * Try to retrieve them with Nand_DetectAndInit -+ */ -+ if (!hNand->Info.PageSize) { -+ hNand->Instance->PCReg |= FMC_PCR_ECCALG | /* Select BCH */ -+ FMC_PCR_ECCSS_0 | /* ECCSS: Sector Size=512 bytes */ -+ FMC_PCR_BCHECC | -+ FMC_PCR_PWAITEN; -+ -+ hNand->Instance->PCReg &= ~FMC_PCR_PBKEN & -+ ~FMC_PCR_WE & -+ ~FMC_PCR_ECCSS_1 & /* ECCSS: Sector Size=512 bytes */ -+ ~FMC_PCR_ECCSS_2; /* ECCSS: Sector Size=512 bytes */ -+ -+ if (bus_width == SIXTEEN_BIT_ACCESS) { -+ hNand->Instance->PCReg |= FMC_PCR_PWID_0; -+ hNand->Instance->PCReg &= ~FMC_PCR_PWID_1; -+ } else { -+ hNand->Instance->PCReg &= ~FMC_PCR_PWID_0; -+ hNand->Instance->PCReg &= ~FMC_PCR_PWID_1; -+ } -+ -+ if (bch_algo == NAND_ECC_BCH4) { -+ /* BCH selected */ -+ hNand->Instance->PCReg |= FMC_PCR_ECCALG; -+ /* BCH4 selected */ -+ hNand->Instance->PCReg &= ~FMC_PCR_BCHECC; -+ } else if (bch_algo == NAND_ECC_BCH8) { -+ /* BCH selected */ -+ hNand->Instance->PCReg |= FMC_PCR_ECCALG; -+ /* BCH8 selected */ -+ hNand->Instance->PCReg |= FMC_PCR_BCHECC; -+ } else { -+ /* Hamming code selected */ -+ hNand->Instance->PCReg &= ~FMC_PCR_ECCALG; -+ } -+ } -+ -+ nand_calc_timing(hNand); -+ -+ /* Set tclr/tar timings */ -+ hNand->Instance->PCReg &= -+ ~FMC_PCR_TCLR_0 & /* tCLR: forced to value 0 */ -+ ~FMC_PCR_TCLR_1 & /* tCLR: forced to value 0 */ -+ ~FMC_PCR_TCLR_2 & /* tCLR: forced to value 0 */ -+ ~FMC_PCR_TCLR_3 & /* tCLR: forced to value 0 */ -+ ~FMC_PCR_TAR_0 & /* tAR: forced to value 0 */ -+ ~FMC_PCR_TAR_1 & /* tAR: forced to value 0 */ -+ ~FMC_PCR_TAR_2 & /* tAR: forced to value 0 */ -+ ~FMC_PCR_TAR_3; /* tAR: forced to value 0 */ -+ -+ hNand->Instance->PCReg |= FMC_PCR_TCLR(hNand->Info.timings.tclr); -+ hNand->Instance->PCReg |= FMC_PCR_TAR(hNand->Info.timings.tar); -+ -+ /* Set tset/twait/thold/thiz timings in common bank */ -+ hNand->Instance->PMEM = FMC_PMEM_MEMSET(hNand->Info.timings.tset_mem); -+ hNand->Instance->PMEM |= FMC_PMEM_MEMWAIT(hNand->Info.timings.twait); -+ hNand->Instance->PMEM |= -+ FMC_PMEM_MEMHOLD(hNand->Info.timings.thold_mem); -+ hNand->Instance->PMEM |= FMC_PMEM_MEMHIZ(hNand->Info.timings.thiz); -+ -+ /* Set tset/twait/thold/thiz timings in attribut bank */ -+ hNand->Instance->PATT = FMC_PATT_ATTSET(hNand->Info.timings.tset_att); -+ hNand->Instance->PATT |= FMC_PATT_ATTWAIT(hNand->Info.timings.twait); -+ hNand->Instance->PATT |= -+ FMC_PATT_ATTHOLD(hNand->Info.timings.thold_att); -+ hNand->Instance->PATT |= FMC_PATT_ATTHIZ(hNand->Info.timings.thiz); -+ -+ /* Enable the NAND device */ -+ hNand->Instance->PCReg |= FMC_PCR_PBKEN; -+ -+ /* Enable FMC Controller IP */ -+ hNand->Instance->BCR1 |= FMC_BCR1_FMCEN; -+} -+ -+/* -+ * @brief NAND memory read status -+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains -+ * the configuration information for NAND module. -+ * @retval NAND status -+ */ -+static uint32_t NAND_ReadStatus(NAND_HandleTypeDef *hNand) -+{ -+ uint32_t data; -+ uintptr_t deviceComMemAddr; -+ uintptr_t deviceAttrMemAddr; -+ -+ assert(hNand); -+ -+ /* Identify the device address */ -+ deviceComMemAddr = FLASH_COMMON_MEM_BASE; -+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE; -+ -+ /* Send Read status operation command */ -+ *(__IO uint8_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_STATUS; -+ -+ /* Read status register data */ -+ data = *(__IO uint8_t *)deviceComMemAddr; -+ -+ /* Return the status */ -+ if ((data & NAND_ERROR) == NAND_ERROR) -+ return NAND_ERROR; -+ else if ((data & NAND_READY) == NAND_READY) -+ return NAND_READY; -+ -+ return NAND_BUSY; -+} -+ -+/***************************************************************************** -+ * -+ * Function: NAND_WaitReadyWithTimeout -+ * -+ * Description: This function wait with timeout of 250 ms until -+ * NAND Ready bit is set. -+ * Nand detection and initialization. -+ * -+ * Input parameters: NAND_HandleTypeDef * hNand -+ * -+ * Return: value 0 is no timeout occurred, value 1 if 250 ms -+ * wait timeout elapsed while waiting for NAND Ready -+ * flag to raise. -+ * -+ *****************************************************************************/ -+static uint32_t NAND_WaitReadyWithTimeout(NAND_HandleTypeDef *hNand) -+{ -+ uint32_t timerValInit = 0; -+ uint32_t timeoutDetected = 0; -+ -+ /* Is Nand handle NULL ? */ -+ assert(hNand); -+ -+ /* Get timer current value at start of loop */ -+ timerValInit = (uint32_t)read_cntpct_el0(); -+ -+ /* Wait NAND Ready by a read status command until response or */ -+ /* NAND Ready timeout elapses */ -+ /* timeout = 250ms @ 64 MHz of gentimer */ -+ while ((NAND_ReadStatus(hNand) != NAND_READY) && -+ (timeoutDetected == 0)) { -+ /* Check if timeout occurred */ -+ if (((uint32_t)read_cntpct_el0() - timerValInit) >= -+ NAND_READY_WAIT_TIMEOUT_VAL_250MS_AT_64MHz) -+ timeoutDetected = 1; -+ } -+ -+ return(timeoutDetected); -+} -+ -+/***************************************************************************** -+ * -+ * Function: Nand_Reset -+ * -+ * Description: Resets NAND Flash memory. -+ * -+ * Input parameters: NAND_HandleTypeDef * hNand -+ * -+ * Output parameters: none -+ * -+ * Return: Std_ReturnType -+ * -+ *****************************************************************************/ -+static Std_ReturnType Nand_Reset(NAND_HandleTypeDef *hNand) -+{ -+ Std_ReturnType retVal = STD_NOT_OK; -+ uintptr_t deviceAddress; -+ uint32_t timeoutDetected = 0; -+ -+ /* Is Nand handle NULL ? */ -+ assert(hNand); -+ -+ /* Identify the device address */ -+ deviceAddress = FLASH_COMMON_MEM_BASE; -+ -+ /* Send NAND reset command */ -+ /* Writes the command value in command section */ -+ *(uint8_t *)(deviceAddress | CMD_SECTION) = NAND_CMD_RESET; -+ -+ /* Wait the fixed 30 us time : after the NAND Reset command sent */ -+ /* 30us @ 64 MHz of gentimer */ -+ udelay(NAND_RST_TIMEOUT); -+ -+ /* Wait NANDReady with timeout 250 ms */ -+ timeoutDetected = NAND_WaitReadyWithTimeout(hNand); -+ -+ /* If no timeout occurred : the NAND Reset phase was successful */ -+ if (timeoutDetected == 0) -+ /* Set good status on exit */ -+ retVal = STD_OK; -+ -+ return retVal; -+} -+ -+/***************************************************************************** -+ * -+ * Function: Nand_ReadIDCode -+ * -+ * Description: This function reads the NAND ID code -+ * -+ * Input parameters: NAND_HandleTypeDef * hNand: NAND handle -+ * NAND_IDTypeDef * pNAND_ID: NAND ID structure -+ * -+ * Output parameters: none -+ * -+ * Return: None -+ * -+ *****************************************************************************/ -+static void Nand_ReadIDCode(NAND_HandleTypeDef *hNand, NAND_IDTypeDef *pNAND_ID) -+{ -+ uint32_t data; -+ uintptr_t deviceComMemAddr; -+ uintptr_t deviceAttrMemAddr; -+ -+ assert(hNand); -+ -+ /* Identify the device addresses */ -+ deviceComMemAddr = FLASH_COMMON_MEM_BASE; -+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE; -+ -+ /* Send Read ID command sequence */ -+ *(__IO uint8_t *)(deviceComMemAddr | CMD_SECTION) = NAND_CMD_READID; -+ *(__IO uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00; -+ -+ udelay(NAND_RST_TIMEOUT); -+ -+ /* Read the electronic signature from NAND flash */ -+ data = *(__IO uint16_t *)deviceComMemAddr; -+ -+ /* Return the data read */ -+ pNAND_ID->Maker_Id = (uint8_t)(data); -+ pNAND_ID->Device_Id = (uint8_t)(data >> 8); -+} -+ -+/** -+ * @brief NAND check CRC16 -+ * @param crc: initial CRC value -+ * @param data_in: pointer to buffer -+ * @param data_len: length of data -+ * @retval CRC 16 bits -+ */ -+static uint16_t NAND_CheckCrc16(uint16_t crc, uint8_t *data_in, -+ uint32_t data_len) -+{ -+ /* Algorithm from ONFI standard */ -+ -+ uint32_t i, j, bit; -+ -+ for (i = 0; i < data_len; i++) { -+ uint8_t curParam = *data_in++; -+ -+ for (j = 0x80; j != 0; j >>= 1) { -+ bit = crc & 0x8000; -+ crc <<= 1; -+ -+ if (curParam & j) -+ bit ^= 0x8000; -+ -+ if (bit) -+ crc ^= CRC_POLYNOM; -+ } -+ crc &= 0xFFFF; -+ } -+ -+ return crc; -+} -+ -+/***************************************************************************** -+ * -+ * Function: Nand_ReadParameterPage -+ * -+ * Description: This function reads the NAND parameter page -+ * (command 0xEC) -+ * The Read Parameter Page command retrieves -+ * the data structure that describes -+ * the targets organization, features, timings -+ * and other behavioral parameters. -+ * There may also be additional information -+ * provided in an extended parameter page. -+ * -+ * Input parameters: NAND_HandleTypeDef * hNand -+ * -+ * Output parameters: none -+ * -+ * Return: Std_ReturnType -+ * -+ *****************************************************************************/ -+static Std_ReturnType Nand_ReadParameterPage(NAND_HandleTypeDef *hNand) -+{ -+ uint32_t index; -+ uint8_t buffer[PARAM_PAGE_SIZE]; -+ uintptr_t deviceComMemAddr; -+ uintptr_t deviceAttrMemAddr; -+ int i; -+ uint16_t crc16; -+ -+ assert(hNand); -+ -+ /* Identify the device address */ -+ deviceComMemAddr = FLASH_COMMON_MEM_BASE; -+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE; -+ -+ /* Send ONFI Parameter Page Read sequence */ -+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) = NAND_CMD_READ_PARAM_PAGE; -+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00; -+ -+ udelay(NAND_RST_TIMEOUT); -+ -+ /* -+ * Read Parameter Page -+ * Note: There are three consecutive redondant copies -+ * of parameter page -+ */ -+ for (i = 0; i < 3; i++) { -+ /* Read parameter page from NAND flash */ -+ /* Get data */ -+ for (index = 0; index < PARAM_PAGE_SIZE; index++) -+ buffer[index] = *(uint8_t *)deviceComMemAddr; -+ -+ /* -+ * Bytes 0-4: Parameter page signature -+ * This field contains the parameter page signature. -+ * When two or more bytes of the signature are valid, -+ * then it denotes that a valid copy -+ * of the parameter page is present -+ */ -+ hNand->Info.Signature = (buffer[3] << 24) | (buffer[2] << 16) | -+ (buffer[1] << 8) | buffer[0]; -+ crc16 = (buffer[254] | buffer[255] << 8); -+ -+ if ((hNand->Info.Signature == ONFI_SIG_VALUE) && -+ (NAND_CheckCrc16(CRC_INIT_VALUE, buffer, -+ PARAM_PAGE_SIZE - 2) == crc16)) -+ break; -+ } -+ -+ if (i == 3) { -+ /* Could not find ONFI parameter page */ -+ INFO("%s: No Onfi Parameter Page\n", __func__); -+ return STD_NOT_OK; -+ } -+ -+ /* Byte 6, bit 0: data bus width (8 or 16) */ -+ hNand->Info.BusWidth = buffer[6] & 0x1; -+ -+ /* Bytes 80-83: Page size */ -+ hNand->Info.PageSize = (buffer[83] << 24) | (buffer[82] << 16) | -+ (buffer[81] << 8) | buffer[80]; -+ -+ /* Bytes 92-95 : Block size in number of pages */ -+ hNand->Info.BlockSize = (buffer[95] << 24) | (buffer[94] << 16) | -+ (buffer[93] << 8) | buffer[92]; -+ -+ /* Byte 96-99: Number of blocks per logical unit */ -+ hNand->Info.BlockNb = (buffer[99] << 24) | (buffer[98] << 16) | -+ (buffer[97] << 8) | buffer[96]; -+ -+ /* -+ * Byte 112: Number of bits ECC correctability -+ * This field indicates the number of bits that the host -+ * should be able to correct per 512 bytes of data -+ */ -+ if (buffer[112] != 0xFF) { -+ hNand->Info.ECCcorrectability = buffer[112]; -+ } else if ((buffer[4] != 1) && (buffer[4] != 2) && -+ buffer[6] & (1 << 7)) { -+ /* NAND ONFI, version > 2.1, with extended parameter page */ -+ uint32_t ext_page_size = ((buffer[13] << 8) | buffer[12]); -+ uint32_t ext_page_offset = buffer[14] * PARAM_PAGE_SIZE; -+ uint32_t ecc_block_offset = 32; -+ -+ /* Send ONFI Parameter Page Read sequence */ -+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_READ_PARAM_PAGE; -+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00; -+ -+ /* Skip ONFI parameter pages to read Extended parameter page */ -+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_1ST; -+ -+ *(uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(ext_page_offset); -+ -+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(ext_page_offset); -+ -+ *(uint8_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_2ND; -+ -+ udelay(NAND_RST_TIMEOUT); -+ -+ /* Copy Extended parameter page */ -+ for (index = 0; index < PARAM_PAGE_SIZE; index++) -+ buffer[index] = *(uint8_t *)deviceComMemAddr; -+ -+ if (((buffer[5] << 24) | (buffer[4] << 16) | -+ (buffer[3] << 8) | buffer[2]) != EXT_PAGE_SIG_VALUE) { -+ WARN("Extended parameter page signature is wrong\n"); -+ return STD_NOT_OK; -+ } -+ -+ /* -+ * Extended parameter page can fit in buffer -+ * we can try to calculate its CRC -+ */ -+ if (ext_page_size <= PARAM_PAGE_SIZE) { -+ crc16 = (buffer[1] << 8) | buffer[0]; -+ -+ if (NAND_CheckCrc16(CRC_INIT_VALUE, buffer, -+ ext_page_size) != crc16) { -+ WARN("Extended page CRC failed\n"); -+ return STD_NOT_OK; -+ } -+ } -+ -+ /* -+ * Check the 8 sections of extended parameter page -+ * for an extended ECC information block (type = 2) -+ */ -+ for (i = 0; i < 8; i++) { -+ if (buffer[16 + 2 * i] == 2) -+ break; -+ -+ ecc_block_offset += buffer[17 + 2 * i]; -+ } -+ -+ if (i == 8) { -+ WARN("ECC extended block could not be found\n"); -+ return STD_NOT_OK; -+ } -+ -+ if (ext_page_size <= PARAM_PAGE_SIZE) { -+ /* -+ * ECC correctcatbility is the first byte -+ * of the ECC block -+ */ -+ hNand->Info.ECCcorrectability = -+ buffer[ecc_block_offset]; -+ } else { -+ /* Send ONFI Parameter Page Read sequence */ -+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_READ_PARAM_PAGE; -+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00; -+ -+ /* -+ * Skip ONFI parameter pages to read -+ * Extended parameter page -+ */ -+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_1ST; -+ *(uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(ext_page_offset + -+ ecc_block_offset); -+ -+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(ext_page_offset + -+ ecc_block_offset); -+ -+ *(uint8_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_2ND; -+ -+ udelay(NAND_RST_TIMEOUT); -+ -+ hNand->Info.ECCcorrectability = -+ *(uint8_t *)deviceComMemAddr; -+ } -+ } else { -+ WARN("ECC correctability could not be found\n"); -+ return STD_NOT_OK; -+ } -+ -+ return STD_OK; -+} -+ -+/***************************************************************************** -+ * -+ * Function: Nand_DetectAndInit -+ * -+ * Description: This function initializes the Nand FMC driver. -+ * Nand detection and initialization. -+ * -+ * Input parameters: NAND_HandleTypeDef * hNand -+ * -+ * Output parameters: none -+ * -+ * Return: Std_ReturnType -+ * -+ *****************************************************************************/ -+static Std_ReturnType Nand_DetectAndInit(NAND_HandleTypeDef *hNand) -+{ -+ NAND_IDTypeDef pNAND_ID; -+ uint32_t nand_param_in_otp, result; -+ -+ assert(hNand); -+ -+ /* Remark : ReadID and ReadParameterPage are commands on 8-bit */ -+ -+ /* ReadID code */ -+ Nand_ReadIDCode(hNand, &pNAND_ID); -+ -+ /* Check if NAND parameters are stored in OTP */ -+ result = bsec_shadow_read_otp(&nand_param_in_otp, NAND_OTP); -+ if (result != BSEC_OK) { -+ ERROR("BSEC: NAND_OTP Error %i\n", result); -+ return STD_NOT_OK; -+ } -+ -+ if (nand_param_in_otp & NAND_PARAM_STORED_IN_OTP) { -+ /* -+ * NAND parameter shall be read from OTP -+ */ -+ hNand->Info.BusWidth = (nand_param_in_otp & NAND_WIDTH_MASK) >> -+ NAND_WIDTH_OFFSET; -+ -+ switch ((nand_param_in_otp & NAND_PAGE_SIZE_MASK) >> -+ NAND_PAGE_SIZE_OFFSET) { -+ case NAND_PAGE_SIZE_2K: -+ hNand->Info.PageSize = 2048; -+ break; -+ -+ case NAND_PAGE_SIZE_4K: -+ hNand->Info.PageSize = 4096; -+ break; -+ -+ case NAND_PAGE_SIZE_8K: -+ hNand->Info.PageSize = 8192; -+ break; -+ -+ default: -+ hNand->Info.PageSize = 0; -+ ERROR("Cannot read NAND page size\n"); -+ return STD_NOT_OK; -+ } -+ -+ switch ((nand_param_in_otp & NAND_BLOCK_SIZE_MASK) >> -+ NAND_BLOCK_SIZE_OFFSET) { -+ case NAND_BLOCK_SIZE_64_PAGES: -+ hNand->Info.BlockSize = 64; -+ break; -+ -+ case NAND_BLOCK_SIZE_128_PAGES: -+ hNand->Info.BlockSize = 128; -+ break; -+ -+ case NAND_BLOCK_SIZE_256_PAGES: -+ hNand->Info.BlockSize = 256; -+ break; -+ -+ default: -+ hNand->Info.BlockSize = 0; -+ ERROR("Cannot read NAND block size\n"); -+ return STD_NOT_OK; -+ } -+ -+ hNand->Info.BlockNb = ((nand_param_in_otp & -+ NAND_BLOCK_NB_MASK) >> -+ NAND_BLOCK_NB_OFFSET) * -+ NAND_BLOCK_NB_UNIT; -+ -+ switch ((nand_param_in_otp & NAND_ECC_BIT_NB_MASK) >> -+ NAND_ECC_BIT_NB_OFFSET) { -+ case NAND_ECC_BIT_NB_UNSET: -+ hNand->Info.ECCcorrectability = 0; -+ break; -+ -+ case NAND_ECC_BIT_NB_1_BITS: -+ hNand->Info.ECCcorrectability = 1; -+ break; -+ -+ case NAND_ECC_BIT_NB_4_BITS: -+ hNand->Info.ECCcorrectability = 4; -+ break; -+ -+ case NAND_ECC_BIT_NB_8_BITS: -+ hNand->Info.ECCcorrectability = 8; -+ break; -+ -+ default: -+ hNand->Info.ECCcorrectability = 0; -+ ERROR("Cannot read ECCbit number\n"); -+ return STD_NOT_OK; -+ } -+ } else { -+ /* -+ * ONFI or 'ONFI compliant' NAND -+ * 'ONFI compliant' means that parameters used by bootrom are -+ * available in parameter table at same offsets as in a -+ * ONFI parameter table. -+ * NAND parameter shall be read from Parameter table. -+ */ -+ -+ uint32_t onfi_ecc; -+ -+ /* Read Nand parameter page */ -+ if (Nand_ReadParameterPage(hNand) != STD_OK) { -+ ERROR("%s: NAND not initialized\n", __func__); -+ return STD_NOT_OK; -+ } -+ -+ onfi_ecc = hNand->Info.ECCcorrectability; -+ -+ /* -+ * For ONFI nand, ECC number of bits may be overridden by a -+ * value from OTP configuration. -+ */ -+ switch ((nand_param_in_otp & NAND_ECC_BIT_NB_MASK) >> -+ NAND_ECC_BIT_NB_OFFSET) { -+ case NAND_ECC_BIT_NB_UNSET: -+ hNand->Info.ECCcorrectability = 0; -+ break; -+ -+ case NAND_ECC_BIT_NB_1_BITS: -+ hNand->Info.ECCcorrectability = 1; -+ break; -+ -+ case NAND_ECC_BIT_NB_4_BITS: -+ hNand->Info.ECCcorrectability = 4; -+ break; -+ -+ case NAND_ECC_BIT_NB_8_BITS: -+ hNand->Info.ECCcorrectability = 8; -+ break; -+ -+ default: -+ hNand->Info.ECCcorrectability = 0; -+ break; -+ } -+ -+ /* -+ * if OTP info is wrong, fall back to parameter read in ONFI -+ * parameter page -+ */ -+ if (hNand->Info.ECCcorrectability == 0) -+ hNand->Info.ECCcorrectability = onfi_ecc; -+ } -+ -+ Nand_Init(hNand, hNand->Info.BusWidth, hNand->Info.ECCcorrectability); -+ -+ /* Now NAND Flash is detected and initialized */ -+ return STD_OK; -+} -+ -+/** -+ * @brief NAND read page command sequence -+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains -+ * the configuration information for NAND module. -+ * @param colAddr: column address -+ * @param rowAddr: row address -+ * @retval Std_ReturnType -+ */ -+static void NAND_Read_Page_Cmd(NAND_HandleTypeDef *hNand, uint32_t colAddr, -+ uint32_t rowAddr) -+{ -+ uintptr_t deviceComMemAddr; -+ uintptr_t deviceAttrMemAddr; -+ -+ assert(hNand); -+ -+ /* Identify the device address */ -+ deviceComMemAddr = FLASH_COMMON_MEM_BASE; -+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE; -+ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ *(__IO uint8_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_READ_1ST; -+ -+ /* C1 */ -+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(colAddr); -+ /* C2 */ -+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(colAddr); -+ /* R1 */ -+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(rowAddr); -+ /* R2 */ -+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(rowAddr); -+ -+ /* R3 */ -+ *(__IO uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = -+ ADDR_3RD_CYCLE(rowAddr); -+ -+ *(__IO uint8_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_READ_2ND; -+ } else { -+ /* NAND 16bit */ -+ *(__IO uint16_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_READ_1ST; -+ -+ /* C1 */ -+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(colAddr); -+ /* C2 */ -+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(colAddr); -+ /* R1 */ -+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(rowAddr); -+ /* R2 */ -+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(rowAddr); -+ -+ /* R3 */ -+ *(__IO uint16_t *)(deviceAttrMemAddr | ADDR_SECTION) = -+ ADDR_3RD_CYCLE(rowAddr); -+ -+ *(__IO uint16_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_READ_2ND; -+ } -+} -+ -+/***************************************************************************** -+ * -+ * Function: _bit_count -+ * -+ * Description: Return the number of bits set to one in a 32bit word -+ * -+ * Input parameters: v 32 bit word -+ * -+ * Return: number of bits set to one in v. -+ * -+ *****************************************************************************/ -+static uint32_t _bit_count(uint32_t v) -+{ -+ uint32_t c = 0; -+ -+ for (uint32_t i = 0; i < CHAR_BIT * sizeof(typeof(v)); i++) -+ if (v & (BIT(i))) -+ c++; -+ -+ return c; -+} -+ -+/***************************************************************************** -+ * -+ * Function: NAND_Hamming_Correction -+ * -+ * Description: Consider Hamming correction code, and apply correction -+ * if needed and possible. -+ * -+ * Input parameters: Buffer : pointer to buffer containing data read. -+ * EccBuffer : pointer to buffer containing ecc code read -+ * from out of band area. -+ * EccCalculated : ECC calculated by FMC during reading of -+ * data. -+ * -+ * Return: 0 no error detected -+ * 1 one error detected and correted -+ * > 1 unrecoverable error -+ * -1 ecc error -+ * -+ *****************************************************************************/ -+static int NAND_Hamming_Correction(uint8_t *Buffer, uint8_t *EccBuffer, -+ uint32_t EccCalculated) -+{ -+ uint8_t xor_ecc_ones; -+ uint16_t xor_ecc_1b, xor_ecc_2b, xor_ecc_3b; -+ union { -+ uint32_t val; -+ uint8_t bytes[4]; -+ } xor_ecc; -+ -+ /* Page size--------ECC_Code Size -+ * 256---------------22 bits LSB (ECC_CODE & 0x003FFFFF) -+ * 512---------------24 bits (ECC_CODE & 0x00FFFFFF) -+ * 1024--------------26 bits (ECC_CODE & 0x03FFFFFF) -+ * 2048--------------28 bits (ECC_CODE & 0x0FFFFFFF) -+ * 4096--------------30 bits (ECC_CODE & 0x3FFFFFFF) -+ * 8192--------------32 bits (ECC_CODE & 0xFFFFFFFF) -+ */ -+ -+ /* For Page size 512, ECC_Code size 24 bits */ -+ xor_ecc_1b = (EccCalculated & 0x000000FF) ^ EccBuffer[0]; -+ xor_ecc_2b = ((EccCalculated & 0x0000FF00) >> 8) ^ EccBuffer[1]; -+ xor_ecc_3b = ((EccCalculated & 0x00FF0000) >> 16) ^ EccBuffer[2]; -+ -+ xor_ecc.val = 0L; -+ xor_ecc.bytes[2] = xor_ecc_3b; -+ xor_ecc.bytes[1] = xor_ecc_2b; -+ xor_ecc.bytes[0] = xor_ecc_1b; -+ -+ if (xor_ecc.val == 0) -+ return 0; /* No Error */ -+ -+ xor_ecc_ones = _bit_count(xor_ecc.val); -+ if (xor_ecc_ones < 23) { -+ if (xor_ecc_ones == 12) { -+ uint16_t bit_address, byte_address; -+ -+ /* Correctable ERROR */ -+ bit_address = ((xor_ecc_1b >> 1) & 0x01) | -+ ((xor_ecc_1b >> 2) & 0x02) | -+ ((xor_ecc_1b >> 3) & 0x04); -+ -+ byte_address = ((xor_ecc_1b >> 7) & 0x01) | -+ ((xor_ecc_2b) & 0x02) | -+ ((xor_ecc_2b >> 1) & 0x04) | -+ ((xor_ecc_2b >> 2) & 0x08) | -+ ((xor_ecc_2b >> 3) & 0x10) | -+ ((xor_ecc_3b << 4) & 0x20) | -+ ((xor_ecc_3b << 3) & 0x40) | -+ ((xor_ecc_3b << 2) & 0x80) | -+ ((xor_ecc_3b << 1) & 0x100); -+ -+ /* Correct bit error in the data */ -+ Buffer[byte_address] = (Buffer[byte_address]) ^ -+ ((uint8_t)(1 << bit_address)); -+ INFO("Hamming: 1 ECC error corrected\n"); -+ return 1; -+ } -+ -+ /* Non Correctable ERROR */ -+ ERROR("%s: Uncorrectable ECC Errors\n", __func__); -+ return 2; -+ } -+ -+ /* ECC ERROR */ -+ ERROR("%s: Hamming correction error\n", __func__); -+ return -1; -+} -+ -+/***************************************************************************** -+ * -+ * Function: NAND_Read_Logical_Page -+ * -+ * Description: Read 512B sector from NAND memory page -+ * -+ * Input parameters: hNand: pointer to a NAND_HandleTypeDef structure -+ * that contains the configuration information -+ * for NAND module. -+ * Address : pointer to NAND address structure -+ * Buffer : pointer to destination read buffer -+ * bch_sector_nb : 512B sector number in the page -+ * -+ * -+ * Return: Std_ReturnType -+ * -+ *****************************************************************************/ -+Std_ReturnType NAND_Read_Logical_Page(NAND_HandleTypeDef *hNand, -+ NAND_AddressTypeDef *Address, -+ uint8_t *Buffer, uint32_t bch_sector_nb) -+{ -+ uintptr_t deviceComMemAddr; -+ uintptr_t deviceAttrMemAddr; -+ uint32_t size = 0; -+ uint32_t index, bloc_nb, nb_pages_per_block, offset; -+ uint32_t ecc_size = 0; -+ uint32_t rowAddr = 0, colAddr = 0; -+ uint8_t EccBuffer[NAND_ECC_BCH8_BYTES_NB_16b]; -+ uint32_t heccr = 0; -+ -+ assert(hNand); -+ -+ /* Identify the device address */ -+ deviceComMemAddr = FLASH_COMMON_MEM_BASE; -+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE; -+ -+ bloc_nb = Address->Block; -+ nb_pages_per_block = hNand->Info.BlockSize; -+ -+ /* Page and block to be read */ -+ rowAddr = (bloc_nb * nb_pages_per_block) + Address->Page; -+ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ /* Byte or word in page to be read */ -+ colAddr = bch_sector_nb * NAND_ECC_PAGE_SECTOR; -+ -+ size = NAND_ECC_PAGE_SECTOR; -+ } else { -+ /* If NAND 16bit */ -+ /* Byte or word in page to be read */ -+ colAddr = (bch_sector_nb * NAND_ECC_PAGE_SECTOR) / 2; -+ -+ size = NAND_ECC_PAGE_SECTOR / 2; -+ } -+ -+ /* Reset ECC enabling */ -+ hNand->Instance->PCReg &= ~FMC_PCR_ECCEN; -+ hNand->Instance->PCReg &= ~FMC_PCR_WE; -+ hNand->Instance->PCReg |= FMC_PCR_ECCEN; -+ -+ /* Clear status */ -+ hNand->Instance->BCHICR = 0x1F; -+ -+ /* Send read page command sequence */ -+ NAND_Read_Page_Cmd(hNand, colAddr, rowAddr); -+ -+ /* Get data into destination buffer */ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ uint8_t *Buffer8b = (uint8_t *)Buffer; -+ -+ for (index = 0; index < size; index++) -+ *Buffer8b++ = *(uint8_t *)deviceComMemAddr; -+ } else { -+ /* If NAND 16bit */ -+ uint16_t *Buffer16b = (uint16_t *)Buffer; -+ -+ for (index = 0; index < size; index++) -+ *Buffer16b++ = *(uint16_t *)deviceComMemAddr; -+ } -+ -+ if (hNand->Info.ECCcorrectability == NAND_ECC_HAMMING1) { -+ /* During read of data , syndrome is calculated */ -+ /* Wait until decoding error is ready */ -+ uint32_t timerValInit = read_cntpct_el0(); -+ -+ while ((hNand->Instance->SR & FMC_SR_NWRF) != FMC_SR_NWRF) { -+ if ((read_cntpct_el0() - timerValInit) > -+ NAND_ECC_CALCULATION_TIMEOUT_VAL_250MS) { -+ ERROR("%s: syndrome calculation timeout\n", -+ __func__); -+ return STD_NOT_OK; -+ } -+ } -+ -+ heccr = hNand->Instance->HECCR; -+ } -+ -+ /* Read now corresponding ECC bytes (7 or 13) in spare area */ -+ /* Page and block to be read */ -+ -+ if (hNand->Info.ECCcorrectability == NAND_ECC_BCH4) { -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) -+ ecc_size = NAND_ECC_BCH4_BYTES_NB_8b; -+ else -+ ecc_size = NAND_ECC_BCH4_BYTES_NB_16b; -+ } else if (hNand->Info.ECCcorrectability == NAND_ECC_BCH8) { -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) -+ ecc_size = NAND_ECC_BCH8_BYTES_NB_8b; -+ else -+ ecc_size = NAND_ECC_BCH8_BYTES_NB_16b; -+ } else { -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) -+ ecc_size = NAND_ECC_HAMMING1_BYTES_NB_8b; -+ else -+ ecc_size = NAND_ECC_HAMMING1_BYTES_NB_16b; -+ } -+ -+ offset = 2; -+ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ /* Byte or word in page to be read */ -+ /* See SRS mapping */ -+ colAddr = hNand->Info.PageSize + offset + -+ (bch_sector_nb * ecc_size); -+ } else { -+ /* If NAND 16bit */ -+ /* Byte or word in page to be read */ -+ /* See SRS mapping */ -+ colAddr = (hNand->Info.PageSize + offset + -+ (bch_sector_nb * ecc_size)) / 2; -+ } -+ -+ /* Send change read column command */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ *(__IO uint8_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_1ST; -+ -+ /* C1 */ -+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(colAddr); -+ /* C2 */ -+ *(__IO uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(colAddr); -+ -+ *(__IO uint8_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_2ND; -+ } else { -+ *(__IO uint16_t *)(deviceComMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_1ST; -+ -+ /* C1 */ -+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) = -+ ADDR_1ST_CYCLE(colAddr); -+ /* C2 */ -+ *(__IO uint16_t *)(deviceAttrMemAddr | ADDR_SECTION) = -+ ADDR_2ND_CYCLE(colAddr); -+ -+ *(__IO uint16_t *)(deviceAttrMemAddr | CMD_SECTION) = -+ NAND_CMD_CHANGE_2ND; -+ } -+ -+ /* Get data into destination EccBuffer */ -+ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ uint8_t *pEccBuffer = EccBuffer; -+ -+ for (index = 0; index < ecc_size; index++) -+ *(uint8_t *)pEccBuffer++ = *(uint8_t *)deviceComMemAddr; -+ } else { -+ /* If NAND 16bit */ -+ uint16_t *pEccBuffer16b = (uint16_t *)(EccBuffer); -+ -+ for (index = 0; index < ecc_size / 2; index++) { -+ *(uint16_t *)pEccBuffer16b++ = -+ *(uint16_t *)deviceComMemAddr; -+ } -+ } -+ -+ if (hNand->Info.ECCcorrectability == NAND_ECC_HAMMING1) { -+ int nb_errors; -+ -+ nb_errors = NAND_Hamming_Correction(Buffer, EccBuffer, -+ heccr); -+ if ((nb_errors != 0) && (nb_errors != 1)) -+ return STD_NOT_OK; -+ -+ } else /* BCH error correction */ { -+ uint32_t ecc_errors_nb; -+ uint32_t i; -+ uint32_t errorPosition[8]; -+ -+ /* -+ * During read of data and parity bits, syndrome is calculated, -+ * then error location is launched -+ * Wait until decoding error is ready -+ */ -+ uint32_t timerValInit = (uint32_t)read_cntpct_el0(); -+ -+ while ((hNand->Instance->BCHISR & FMC_BCHISR_DERF) != -+ FMC_BCHISR_DERF) { -+ if (((uint32_t)read_cntpct_el0() - timerValInit) > -+ NAND_ECC_CALCULATION_TIMEOUT_VAL_250MS) -+ return STD_NOT_OK; -+ } -+ -+ /* Read decoding results */ -+ /* Check if there were uncorrectable errors */ -+ if (hNand->Instance->BCHISR & FMC_BCHISR_DUEF) { -+ VERBOSE("%s: Uncorrectable ECC Error\n", __func__); -+ return STD_NOT_OK; -+ } -+ -+ /* Check if there were errors */ -+ if (!(hNand->Instance->BCHISR & FMC_BCHISR_DEFF)) -+ return STD_OK; -+ -+ /* Read number of errors */ -+ ecc_errors_nb = hNand->Instance->BCHSR & FMC_BCHSR_DEN; -+ -+ VERBOSE("%s: ECC Errors detected: %d\n", __func__, -+ ecc_errors_nb); -+ -+ /* Retrieve the error position corresponding to the error -+ * number -+ */ -+ /* Error 1 position : FMC_BCHDSR1.EBP1 */ -+ errorPosition[0] = hNand->Instance->BCHDSR1 & FMC_BCHDSR1_EBP1; -+ /* Error 2 position : FMC_BCHDSR1.EBP2 */ -+ errorPosition[1] = (hNand->Instance->BCHDSR1 & FMC_BCHDSR1_EBP2) -+ >> FMC_EBP2_MASK; -+ /* Error 3 position : FMC_BCHDSR2.EBP1 */ -+ errorPosition[2] = hNand->Instance->BCHDSR2 & FMC_BCHDSR2_EBP1; -+ /* Error 4 position : FMC_BCHDSR2.EBP2 */ -+ errorPosition[3] = (hNand->Instance->BCHDSR2 & FMC_BCHDSR2_EBP2) -+ >> FMC_EBP2_MASK; -+ /* Error 5 position : FMC_BCHDSR3.EBP1 */ -+ errorPosition[4] = hNand->Instance->BCHDSR3 & FMC_BCHDSR3_EBP1; -+ /* Error 6 position : FMC_BCHDSR3.EBP2 */ -+ errorPosition[5] = (hNand->Instance->BCHDSR3 & FMC_BCHDSR3_EBP2) -+ >> FMC_EBP2_MASK; -+ /* Error 7 position : FMC_BCHDSR4.EBP1 */ -+ errorPosition[6] = hNand->Instance->BCHDSR4 & FMC_BCHDSR4_EBP1; -+ /* Error 8 position : FMC_BCHDSR4.EBP2 */ -+ errorPosition[7] = (hNand->Instance->BCHDSR4 & FMC_BCHDSR4_EBP2) -+ >> FMC_EBP2_MASK; -+ -+ /* Error position indicates error bit number in binary */ -+ /* Retrieve the mask of the wrong bit to correct */ -+ for (i = 0; i < ecc_errors_nb; i++) { -+ VERBOSE("%s: ECC Error position: %d\n", __func__, -+ errorPosition[i]); -+ /* Correct only if error is in data area */ -+ if (errorPosition[i] < 0x1000) { -+ /* -+ * Retrieve the mask of the wrong bit -+ * to correct -+ */ -+ uint32_t bitMask = BIT(errorPosition[i] & 0x07); -+ -+ /* -+ * Remove bit postion in the error position -+ * (to have byte to correct) -+ */ -+ errorPosition[i] >>= 0x03; -+ VERBOSE("%s: ECC Error in data area\n", -+ __func__); -+ -+ /* Fix the error : invert the wrong bit */ -+ *(Buffer + errorPosition[i]) ^= bitMask; -+ } else { -+ VERBOSE("%s: ECC Error not in data area\n", -+ __func__); -+ } -+ } -+ } -+ -+ return STD_OK; -+} -+ -+/** -+ * @brief NAND check bad blck -+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains -+ * the configuration information for NAND module. -+ * Address: pointer to NAND address structure -+ * @retval BAD_BLOCK or GOOD_BLOCK -+ */ -+uint32_t NAND_Check_Bad_Block(NAND_HandleTypeDef *hNand, -+ NAND_AddressTypeDef *Address) -+{ -+ uintptr_t deviceComMemAddr = 0; -+ uint32_t bloc_nb = 0; -+ uint32_t nb_pages_per_block = 0; -+ uint32_t page_nb; -+ uint32_t block_status = BAD_BLOCK; -+ uint32_t rowAddr = 0, colAddr = 0; -+ uint8_t bbm_marker, bbm_marker_2; -+ uint16_t bbm_marker16b; -+ -+ assert(hNand); -+ -+ /* Identify the device address */ -+ deviceComMemAddr = FLASH_COMMON_MEM_BASE; -+ -+ /* -+ * Bad block indication is is the 2 first bytes of the 1st -+ * or 2nd page of the block (depends on manufacturer) -+ */ -+ -+ /* -+ * Read the 2 first bytes of the spare area -+ * of the 1st page of the block -+ */ -+ bloc_nb = Address->Block; -+ nb_pages_per_block = hNand->Info.BlockSize; -+ -+ /* Page and block to be read */ -+ page_nb = 0; -+ rowAddr = (bloc_nb * nb_pages_per_block) + page_nb; -+ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ /* Byte or word in page to be read */ -+ colAddr = hNand->Info.PageSize; -+ } else { -+ /* If NAND 16bit */ -+ /* Byte or word in page to be read */ -+ colAddr = hNand->Info.PageSize / 2; -+ } -+ -+ /* Send read page command sequence */ -+ NAND_Read_Page_Cmd(hNand, colAddr, rowAddr); -+ -+ udelay(NAND_RST_TIMEOUT); -+ -+ /* Get data into destination buffer */ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ bbm_marker = *(uint8_t *)deviceComMemAddr; -+ bbm_marker_2 = *(uint8_t *)deviceComMemAddr; -+ -+ if ((bbm_marker != 0xFF) || (bbm_marker_2 != 0xFF)) -+ block_status = BAD_BLOCK; -+ else -+ block_status = GOOD_BLOCK; -+ -+ } else { -+ /* If NAND 16bit */ -+ bbm_marker16b = *(uint16_t *)deviceComMemAddr; -+ -+ if (bbm_marker16b != 0xFFFF) -+ block_status = BAD_BLOCK; -+ else -+ block_status = GOOD_BLOCK; -+ } -+ -+ if (block_status == BAD_BLOCK) -+ return block_status; -+ -+ /* -+ * Read the 2 first bytes of the spare area of the 2nd page -+ * of the block -+ * Page and block to be read -+ */ -+ page_nb = 1; -+ rowAddr = (bloc_nb * nb_pages_per_block) + page_nb; -+ -+ /* Send read page command sequence */ -+ NAND_Read_Page_Cmd(hNand, colAddr, rowAddr); -+ -+ udelay(NAND_RST_TIMEOUT); -+ -+ /* Get data into destination buffer */ -+ /* If NAND 8bit */ -+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) { -+ bbm_marker = *(uint8_t *)deviceComMemAddr; -+ bbm_marker_2 = *(uint8_t *)deviceComMemAddr; -+ -+ if ((bbm_marker == 0xFF) && (bbm_marker_2 == 0xFF)) -+ block_status = GOOD_BLOCK; -+ else -+ block_status = BAD_BLOCK; -+ } else { -+ /* If NAND 16bit */ -+ bbm_marker16b = *(uint16_t *)deviceComMemAddr; -+ -+ if (bbm_marker16b == 0xFFFF) -+ block_status = GOOD_BLOCK; -+ else -+ block_status = BAD_BLOCK; -+ } -+ -+ return block_status; -+} -+ -+/** -+ * @brief Increment the NAND memory address -+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains -+ * the configuration information for NAND module. -+ * @param Address: pointer to NAND address structure -+ * @retval Std_ReturnType -+ */ -+Std_ReturnType NAND_Address_Inc(NAND_HandleTypeDef *hNand, -+ NAND_AddressTypeDef *Address, -+ uint32_t numPagesRead) -+{ -+ assert(hNand); -+ -+ /* Increment page address */ -+ if ((numPagesRead % (hNand->Info.PageSize / BCH_PAGE_SECTOR)) == 0) -+ Address->Page++; -+ -+ /* Check NAND address is valid */ -+ if (Address->Page == hNand->Info.BlockSize) { -+ Address->Page = 0; -+ /* Search for next valid block */ -+ Address->Block++; -+ while (Address->Block < hNand->Info.BlockNb && -+ NAND_Check_Bad_Block(hNand, Address) == BAD_BLOCK) -+ Address->Block++; -+ -+ if (Address->Block == hNand->Info.BlockNb) -+ return STD_NOT_OK; -+ } -+ -+ return STD_OK; -+} -+ -+/** -+ * @brief Initialize driver only if needed: -+ * bootrom must have initialize NAND and bootcontext -+ * must contains correct value. -+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains -+ * the configuration information for NAND module. -+ * @retval Std_ReturnType -+ */ -+Std_ReturnType nand_initialize(NAND_HandleTypeDef *hnand) -+{ -+ if (!hnand->Info.PageSize) { -+ INFO("Reconfigure NAND\n"); -+ /* Not properly initialized by bootrom */ -+ Nand_Init(hnand, EIGHT_BIT_ACCESS, NAND_ECC_BCH8); -+ -+ if (Nand_Reset(hnand) != STD_OK) { -+ ERROR("nand: Reset error (IP base::0x%lx)\n", -+ (uintptr_t)hnand->Instance); -+ return STD_NOT_OK; -+ } -+ -+ if (Nand_DetectAndInit(hnand) != STD_OK) { -+ ERROR("nand: DetectAndInit error (IP base:0x%lx)\n", -+ (uintptr_t)hnand->Instance); -+ return STD_NOT_OK; -+ } -+ } else { -+ /* Initialization done, just need to set correct timing */ -+ Nand_Init(hnand, hnand->Info.BusWidth, -+ hnand->Info.ECCcorrectability); -+ } -+ return STD_OK; -+} -+ -diff --git a/drivers/st/pmic/stm32_i2c.c b/drivers/st/pmic/stm32_i2c.c -deleted file mode 100644 -index 0980139..0000000 ---- a/drivers/st/pmic/stm32_i2c.c -+++ /dev/null -@@ -1,851 +0,0 @@ --/* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#include --#include --#include --#include --#include --#include --#include -- --/* STM32 I2C registers offsets */ --#define I2C_CR1 0x00U --#define I2C_CR2 0x04U --#define I2C_OAR1 0x08U --#define I2C_OAR2 0x0CU --#define I2C_TIMINGR 0x10U --#define I2C_TIMEOUTR 0x14U --#define I2C_ISR 0x18U --#define I2C_ICR 0x1CU --#define I2C_PECR 0x20U --#define I2C_RXDR 0x24U --#define I2C_TXDR 0x28U -- --#define MAX_DELAY 0xFFFFFFFFU -- --/* I2C TIMING clear register Mask */ --#define TIMING_CLEAR_MASK 0xF0FFFFFFU --/* Timeout 25 ms */ --#define I2C_TIMEOUT_BUSY 25U -- --#define MAX_NBYTE_SIZE 255U -- --static int i2c_request_memory_write(struct i2c_handle_s *hi2c, -- uint16_t dev_addr, uint16_t mem_addr, -- uint16_t mem_add_size, uint32_t timeout, -- uint32_t tick_start); --static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint16_t mem_addr, uint16_t mem_add_size, -- uint32_t timeout, uint32_t tick_start); -- --/* Private functions to handle flags during polling transfer */ --static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, -- uint8_t awaited_value, uint32_t timeout, -- uint32_t tick_start); --static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout, -- uint32_t tick_start); --static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout, -- uint32_t tick_start); --static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, -- uint32_t tick_start); -- --/* Private function to flush TXDR register */ --static void i2c_flush_txdr(struct i2c_handle_s *hi2c); -- --/* Private function to start, restart or stop a transfer */ --static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint16_t size, uint32_t i2c_mode, -- uint32_t request); -- --/* -- * @brief Initialize the I2C device. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @retval 0 if OK, negative value else -- */ --int stm32_i2c_init(struct i2c_handle_s *hi2c) --{ -- if (hi2c == NULL) { -- return -ENOENT; -- } -- -- if (hi2c->i2c_state == I2C_STATE_RESET) { -- hi2c->lock = 0; -- } -- -- hi2c->i2c_state = I2C_STATE_BUSY; -- -- /* Disable the selected I2C peripheral */ -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -- -- /* Configure I2Cx: Frequency range */ -- mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, -- hi2c->i2c_init.timing & TIMING_CLEAR_MASK); -- -- /* Disable Own Address1 before set the Own Address1 configuration */ -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); -- -- /* Configure I2Cx: Own Address1 and ack own address1 mode */ -- if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) { -- mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, -- I2C_OAR1_OA1EN | hi2c->i2c_init.own_address1); -- } else { /* I2C_ADDRESSINGMODE_10BIT */ -- mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, -- I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | -- hi2c->i2c_init.own_address1); -- } -- -- /* Configure I2Cx: Addressing Master mode */ -- if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_10BIT) { -- mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); -- } -- -- /* -- * Enable the AUTOEND by default, and enable NACK -- * (should be disable only during Slave process) -- */ -- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, -- I2C_CR2_AUTOEND | I2C_CR2_NACK); -- -- /* Disable Own Address2 before set the Own Address2 configuration */ -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); -- -- /* Configure I2Cx: Dual mode and Own Address2 */ -- mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, -- hi2c->i2c_init.dual_address_mode | -- hi2c->i2c_init.own_address2 | -- (hi2c->i2c_init.own_address2_masks << 8)); -- -- /* Configure I2Cx: Generalcall and NoStretch mode */ -- mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, -- hi2c->i2c_init.general_call_mode | -- hi2c->i2c_init.no_stretch_mode); -- -- /* Enable the selected I2C peripheral */ -- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -- -- hi2c->i2c_err = I2C_ERROR_NONE; -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- return 0; --} -- --/* -- * @brief Write an amount of data in blocking mode to a specific memory address -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param dev_addr: Target device address -- * @param mem_addr: Internal memory address -- * @param mem_add_size: size of internal memory address -- * @param p_data: Pointer to data buffer -- * @param size: Amount of data to be sent -- * @param timeout: timeout duration -- * @retval 0 if OK, negative value else -- */ --int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint16_t mem_addr, uint16_t mem_add_size, -- uint8_t *p_data, uint16_t size, uint32_t timeout) --{ -- uint32_t tickstart; -- -- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -- return -EBUSY; -- } -- -- if ((p_data == NULL) || (size == 0U)) { -- return -EINVAL; -- } -- -- hi2c->lock = 1; -- -- tickstart = (uint32_t)read_cntpct_el0(); -- -- if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY, -- tickstart) != 0) { -- return -EIO; -- } -- -- hi2c->i2c_state = I2C_STATE_BUSY_TX; -- hi2c->i2c_mode = I2C_MODE_MEM; -- hi2c->i2c_err = I2C_ERROR_NONE; -- -- hi2c->p_buff = p_data; -- hi2c->xfer_count = size; -- -- /* Send Slave Address and Memory Address */ -- if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, mem_add_size, -- timeout, tickstart) != 0) { -- hi2c->lock = 0; -- return -EIO; -- } -- -- /* -- * Set NBYTES to write and reload -- * if hi2c->xfer_count > MAX_NBYTE_SIZE -- */ -- if (hi2c->xfer_count > MAX_NBYTE_SIZE) { -- hi2c->xfer_size = MAX_NBYTE_SIZE; -- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, -- I2C_RELOAD_MODE, I2C_NO_STARTSTOP); -- } else { -- hi2c->xfer_size = hi2c->xfer_count; -- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, -- I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); -- } -- -- do { -- if (i2c_wait_txis(hi2c, timeout, tickstart) != 0) { -- return -EIO; -- } -- -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *hi2c->p_buff); -- hi2c->p_buff++; -- hi2c->xfer_count--; -- hi2c->xfer_size--; -- -- if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) { -- /* Wait until TCR flag is set */ -- if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, -- tickstart) != 0) { -- return -EIO; -- } -- -- if (hi2c->xfer_count > MAX_NBYTE_SIZE) { -- hi2c->xfer_size = MAX_NBYTE_SIZE; -- i2c_transfer_config(hi2c, dev_addr, -- hi2c->xfer_size, -- I2C_RELOAD_MODE, -- I2C_NO_STARTSTOP); -- } else { -- hi2c->xfer_size = hi2c->xfer_count; -- i2c_transfer_config(hi2c, dev_addr, -- hi2c->xfer_size, -- I2C_AUTOEND_MODE, -- I2C_NO_STARTSTOP); -- } -- } -- -- } while (hi2c->xfer_count > 0U); -- -- /* -- * No need to Check TC flag, with AUTOEND mode the stop -- * is automatically generated. -- * Wait until STOPF flag is reset. -- */ -- if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) { -- return -EIO; -- } -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -- -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); -- -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- -- return 0; --} -- --/* -- * @brief Read an amount of data in blocking mode from a specific memory -- * address -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param dev_addr: Target device address -- * @param mem_addr: Internal memory address -- * @param mem_add_size: size of internal memory address -- * @param p_data: Pointer to data buffer -- * @param size: Amount of data to be sent -- * @param timeout: timeout duration -- * @retval 0 if OK, negative value else -- */ --int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint16_t mem_addr, uint16_t mem_add_size, -- uint8_t *p_data, uint16_t size, uint32_t timeout) --{ -- uint32_t tickstart; -- -- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -- return -EBUSY; -- } -- -- if ((p_data == NULL) || (size == 0U)) { -- return -EINVAL; -- } -- -- hi2c->lock = 1; -- -- tickstart = (uint32_t)read_cntpct_el0(); -- -- if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY, -- tickstart) != 0) { -- return -EIO; -- } -- -- hi2c->i2c_state = I2C_STATE_BUSY_RX; -- hi2c->i2c_mode = I2C_MODE_MEM; -- hi2c->i2c_err = I2C_ERROR_NONE; -- -- hi2c->p_buff = p_data; -- hi2c->xfer_count = size; -- -- /* Send Slave Address and Memory Address */ -- if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, mem_add_size, -- timeout, tickstart) != 0) { -- hi2c->lock = 0; -- return -EIO; -- } -- -- /* -- * Send Slave Address. -- * Set NBYTES to write and reload if hi2c->xfer_count > MAX_NBYTE_SIZE -- * and generate RESTART. -- */ -- if (hi2c->xfer_count > MAX_NBYTE_SIZE) { -- hi2c->xfer_size = MAX_NBYTE_SIZE; -- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, -- I2C_RELOAD_MODE, I2C_GENERATE_START_READ); -- } else { -- hi2c->xfer_size = hi2c->xfer_count; -- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, -- I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); -- } -- -- do { -- if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout, -- tickstart) != 0) { -- return -EIO; -- } -- -- *hi2c->p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); -- hi2c->p_buff++; -- hi2c->xfer_size--; -- hi2c->xfer_count--; -- -- if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) { -- if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, -- tickstart) != 0) { -- return -EIO; -- } -- -- if (hi2c->xfer_count > MAX_NBYTE_SIZE) { -- hi2c->xfer_size = MAX_NBYTE_SIZE; -- i2c_transfer_config(hi2c, dev_addr, -- hi2c->xfer_size, -- I2C_RELOAD_MODE, -- I2C_NO_STARTSTOP); -- } else { -- hi2c->xfer_size = hi2c->xfer_count; -- i2c_transfer_config(hi2c, dev_addr, -- hi2c->xfer_size, -- I2C_AUTOEND_MODE, -- I2C_NO_STARTSTOP); -- } -- } -- } while (hi2c->xfer_count > 0U); -- -- /* -- * No need to Check TC flag, with AUTOEND mode the stop -- * is automatically generated -- * Wait until STOPF flag is reset -- */ -- if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) { -- return -EIO; -- } -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -- -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); -- -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- -- return 0; --} -- --/* -- * @brief Checks if target device is ready for communication. -- * @note This function is used with Memory devices -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param dev_addr: Target device address -- * @param trials: Number of trials -- * @param timeout: timeout duration -- * @retval 0 if OK, negative value else -- */ --int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, -- uint16_t dev_addr, uint32_t trials, -- uint32_t timeout) --{ -- uint32_t i2c_trials = 0U; -- -- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -- return -EBUSY; -- } -- -- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != -- 0U) { -- return -EBUSY; -- } -- -- hi2c->lock = 1; -- -- hi2c->i2c_state = I2C_STATE_BUSY; -- hi2c->i2c_err = I2C_ERROR_NONE; -- -- do { -- uint32_t tickstart; -- -- /* Generate Start */ -- if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) { -- mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, -- (((uint32_t)dev_addr & I2C_CR2_SADD) | -- I2C_CR2_START | I2C_CR2_AUTOEND) & -- ~I2C_CR2_RD_WRN); -- } else { -- mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, -- (((uint32_t)dev_addr & I2C_CR2_SADD) | -- I2C_CR2_START | I2C_CR2_ADD10) & -- ~I2C_CR2_RD_WRN); -- } -- -- /* -- * No need to Check TC flag, with AUTOEND mode the stop -- * is automatically generated -- * Wait until STOPF flag is set or a NACK flag is set -- */ -- tickstart = (uint32_t)read_cntpct_el0(); -- while (((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -- (I2C_FLAG_STOPF | I2C_FLAG_AF)) == 0U) && -- (hi2c->i2c_state != I2C_STATE_TIMEOUT)) { -- if (timeout != MAX_DELAY) { -- if ((((uint32_t)read_cntpct_el0() - tickstart) > -- timeout) || (timeout == 0U)) { -- hi2c->i2c_state = I2C_STATE_READY; -- -- hi2c->i2c_err |= -- I2C_ERROR_TIMEOUT; -- -- hi2c->lock = 0; -- -- return -EIO; -- } -- } -- } -- -- /* Check if the NACKF flag has not been set */ -- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -- I2C_FLAG_AF) == 0U) { -- if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout, -- tickstart) != 0) { -- return -EIO; -- } -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, -- I2C_FLAG_STOPF); -- -- hi2c->i2c_state = I2C_STATE_READY; -- -- hi2c->lock = 0; -- -- return 0; -- } -- -- if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout, -- tickstart) != 0) { -- return -EIO; -- } -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -- -- if (i2c_trials == trials) { -- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, -- I2C_CR2_STOP); -- -- if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout, -- tickstart) != 0) { -- return -EIO; -- } -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, -- I2C_FLAG_STOPF); -- } -- -- i2c_trials++; -- } while (i2c_trials < trials); -- -- hi2c->i2c_state = I2C_STATE_READY; -- -- hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -- -- hi2c->lock = 0; -- -- return -EIO; --} -- --/* -- * @brief Master sends target device address followed by internal memory -- * address for write request. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param dev_addr: Target device address -- * @param mem_addr: Internal memory address -- * @param mem_add_size: size of internal memory address -- * @param timeout: timeout duration -- * @param tick_start Tick start value -- * @retval 0 if OK, negative value else -- */ --static int i2c_request_memory_write(struct i2c_handle_s *hi2c, -- uint16_t dev_addr, uint16_t mem_addr, -- uint16_t mem_add_size, uint32_t timeout, -- uint32_t tick_start) --{ -- i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, -- I2C_GENERATE_START_WRITE); -- -- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { -- /* Send Memory Address */ -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -- (uint8_t)(mem_addr & 0x00FFU)); -- } else { -- /* Send MSB of Memory Address */ -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -- (uint8_t)((mem_addr & 0xFF00U) >> 8)); -- -- /* Wait until TXIS flag is set */ -- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- /* Send LSB of Memory Address */ -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -- (uint8_t)(mem_addr & 0x00FFU)); -- } -- -- if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, tick_start) != -- 0) { -- return -EIO; -- } -- -- return 0; --} -- --/* -- * @brief Master sends target device address followed by internal memory -- * address for read request. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param dev_addr: Target device address -- * @param mem_addr: Internal memory address -- * @param mem_add_size: size of internal memory address -- * @param timeout: timeout duration -- * @param tick_start Tick start value -- * @retval 0 if OK, negative value else -- */ --static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint16_t mem_addr, uint16_t mem_add_size, -- uint32_t timeout, uint32_t tick_start) --{ -- i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, -- I2C_GENERATE_START_WRITE); -- -- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { -- /* Send Memory Address */ -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -- (uint8_t)(mem_addr & 0x00FFU)); -- } else { -- /* Send MSB of Memory Address */ -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -- (uint8_t)((mem_addr & 0xFF00U) >> 8)); -- -- /* Wait until TXIS flag is set */ -- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- /* Send LSB of Memory Address */ -- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, -- (uint8_t)(mem_addr & 0x00FFU)); -- } -- -- if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- return 0; --} -- --/* -- * @brief I2C Tx data register flush process. -- * @param hi2c: I2C handle. -- * @retval None -- */ --static void i2c_flush_txdr(struct i2c_handle_s *hi2c) --{ -- /* -- * If a pending TXIS flag is set, -- * write a dummy data in TXDR to clear it. -- */ -- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != -- 0U) { -- mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); -- } -- -- /* Flush TX register if not empty */ -- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == -- 0U) { -- mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, -- I2C_FLAG_TXE); -- } --} -- --/* -- * @brief This function handles I2C Communication timeout. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param flag: Specifies the I2C flag to check. -- * @param awaited_value: The awaited bit value for the flag (0 or 1). -- * @param timeout: timeout duration -- * @param tick_start: Tick start value -- * @retval 0 if OK, negative value else -- */ --static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, -- uint8_t awaited_value, uint32_t timeout, -- uint32_t tick_start) --{ -- uint8_t flag_check; -- -- do { -- flag_check = ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -- flag) == flag) ? 1U : 0U; -- -- if (timeout != MAX_DELAY) { -- if ((((uint32_t)read_cntpct_el0() - tick_start) > -- timeout) || (timeout == 0U)) { -- hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- return -EIO; -- } -- } -- } while (flag_check == awaited_value); -- -- return 0; --} -- --/* -- * @brief This function handles I2C Communication timeout for specific usage -- * of TXIS flag. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param timeout: timeout duration -- * @param tick_start: Tick start value -- * @retval 0 if OK, negative value else -- */ --static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout, -- uint32_t tick_start) --{ -- while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -- I2C_FLAG_TXIS) == 0U) { -- if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- if (timeout != MAX_DELAY) { -- if ((((uint32_t)read_cntpct_el0() - tick_start) > -- timeout) || (timeout == 0U)) { -- hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- -- return -EIO; -- } -- } -- } -- -- return 0; --} -- --/* -- * @brief This function handles I2C Communication timeout for specific -- * usage of STOP flag. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param timeout: timeout duration -- * @param tick_start: Tick start value -- * @retval 0 if OK, negative value else -- */ --static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout, -- uint32_t tick_start) --{ -- while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -- I2C_FLAG_STOPF) == 0U) { -- if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) { -- return -EIO; -- } -- -- if ((((uint32_t)read_cntpct_el0() - tick_start) > timeout) || -- (timeout == 0U)) { -- hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- -- return -EIO; -- } -- } -- -- return 0; --} -- --/* -- * @brief This function handles Acknowledge failed detection during -- * an I2C Communication. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2C. -- * @param timeout: timeout duration -- * @param tick_start: Tick start value -- * @retval 0 if OK, negative value else -- */ --static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, -- uint32_t tick_start) --{ -- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { -- return 0; -- } -- -- /* -- * Wait until STOP Flag is reset. -- * AutoEnd should be initiate after AF. -- */ -- while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & -- I2C_FLAG_STOPF) == 0U) { -- if (timeout != MAX_DELAY) { -- if ((((uint32_t)read_cntpct_el0() - tick_start) > -- timeout) || (timeout == 0U)) { -- hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- -- return -EIO; -- } -- } -- } -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); -- -- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); -- -- i2c_flush_txdr(hi2c); -- -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); -- -- hi2c->i2c_err |= I2C_ERROR_AF; -- hi2c->i2c_state = I2C_STATE_READY; -- hi2c->i2c_mode = I2C_MODE_NONE; -- -- hi2c->lock = 0; -- -- return -EIO; --} -- --/* -- * @brief Handles I2Cx communication when starting transfer or during transfer -- * (TC or TCR flag are set). -- * @param hi2c: I2C handle. -- * @param dev_addr: Specifies the slave address to be programmed. -- * @param size: Specifies the number of bytes to be programmed. -- * This parameter must be a value between 0 and 255. -- * @param i2c_mode: New state of the I2C START condition generation. -- * This parameter can be one of the following values: -- * @arg @ref I2C_RELOAD_MODE: Enable Reload mode . -- * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. -- * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. -- * @param request: New state of the I2C START condition generation. -- * This parameter can be one of the following values: -- * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. -- * @arg @ref I2C_GENERATE_STOP: Generate stop condition -- * (size should be set to 0). -- * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. -- * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. -- * @retval None -- */ --static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint16_t size, uint32_t i2c_mode, -- uint32_t request) --{ -- uint32_t clr_value, set_value; -- -- clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | -- I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | -- (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); -- -- set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | -- (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | -- i2c_mode | request; -- -- mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); --} -- --/* -- * @brief Configure I2C Analog noise filter. -- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -- * the configuration information for the specified I2Cx peripheral -- * @param analog_filter: New state of the Analog filter. -- * @retval 0 if OK, negative value else -- */ --int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c, -- uint32_t analog_filter) --{ -- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -- return -EBUSY; -- } -- -- hi2c->lock = 1; -- -- hi2c->i2c_state = I2C_STATE_BUSY; -- -- /* Disable the selected I2C peripheral */ -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -- -- /* Reset I2Cx ANOFF bit */ -- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); -- -- /* Set analog filter bit*/ -- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); -- -- /* Enable the selected I2C peripheral */ -- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -- -- hi2c->i2c_state = I2C_STATE_READY; -- -- hi2c->lock = 0; -- -- return 0; --} -diff --git a/drivers/st/pmic/stm32mp1_pmic.c b/drivers/st/pmic/stm32mp1_pmic.c -deleted file mode 100644 -index 958de08..0000000 ---- a/drivers/st/pmic/stm32mp1_pmic.c -+++ /dev/null -@@ -1,346 +0,0 @@ --/* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ --#define I2C_TIMING 0x10D07DB5 -- --#define I2C_TIMEOUT 0xFFFFF -- --#define MASK_RESET_BUCK3 BIT(2) -- --#define STPMU1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) --#define STPMU1_LDO12356_OUTPUT_SHIFT 2 --#define STPMU1_LDO3_MODE (uint8_t)(BIT(7)) --#define STPMU1_LDO3_DDR_SEL 31U --#define STPMU1_LDO3_1800000 (9U << STPMU1_LDO12356_OUTPUT_SHIFT) -- --#define STPMU1_BUCK_OUTPUT_SHIFT 2 --#define STPMU1_BUCK3_1V8 (39U << STPMU1_BUCK_OUTPUT_SHIFT) -- --#define STPMU1_DEFAULT_START_UP_DELAY_MS 1 -- --static struct i2c_handle_s i2c_handle; --static uint32_t pmic_i2c_addr; -- --static int dt_get_pmic_node(void *fdt) --{ -- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1"); --} -- --bool dt_check_pmic(void) --{ -- int node; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return false; -- } -- -- node = dt_get_pmic_node(fdt); -- if (node < 0) { -- VERBOSE("%s: No PMIC node found in DT\n", __func__); -- return false; -- } -- -- return fdt_check_status(node); --} -- --static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) --{ -- int pmic_node, i2c_node; -- void *fdt; -- const fdt32_t *cuint; -- -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -- } -- -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; -- if (pmic_i2c_addr > UINT16_MAX) { -- return -EINVAL; -- } -- -- i2c_node = fdt_parent_offset(fdt, pmic_node); -- if (i2c_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- dt_fill_device_info(i2c_info, i2c_node); -- if (i2c_info->base == 0U) { -- return -FDT_ERR_NOTFOUND; -- } -- -- return dt_set_pinctrl_config(i2c_node); --} -- --int dt_pmic_enable_boot_on_regulators(void) --{ -- int pmic_node, regulators_node, regulator_node; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -- } -- -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -- -- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -- const fdt32_t *cuint; -- const char *node_name; -- uint16_t voltage; -- -- if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", -- NULL) == NULL) { -- continue; -- } -- -- cuint = fdt_getprop(fdt, regulator_node, -- "regulator-min-microvolt", NULL); + mmio_write_32(base + SDMMC_ICR, + SDMMC_STATIC_FLAGS); + +@@ -615,6 +686,7 @@ static int stm32_sdmmc2_dt_get_config(void) + int sdmmc_node; + void *fdt = NULL; + const fdt32_t *cuint; ++ struct dt_node_info dt_info; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; +@@ -624,27 +696,14 @@ static int stm32_sdmmc2_dt_get_config(void) + return -FDT_ERR_NOTFOUND; + } + +- sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT); +- +- while (sdmmc_node != -FDT_ERR_NOTFOUND) { +- cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL); - if (cuint == NULL) { - continue; - } - -- /* DT uses microvolts, whereas driver awaits millivolts */ -- voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -- node_name = fdt_get_name(fdt, regulator_node, NULL); -- -- if (stpmu1_is_regulator_enabled(node_name) == 0U) { -- int status; -- -- status = stpmu1_regulator_voltage_set(node_name, -- voltage); -- if (status != 0) { -- return status; -- } -- -- status = stpmu1_regulator_enable(node_name); -- if (status != 0) { -- return status; -- } +- if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) { +- break; - } +- +- sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node, +- DT_SDMMC2_COMPAT); - } - -- return 0; --} -- --void initialize_pmic_i2c(void) --{ -- int ret; -- struct dt_node_info i2c_info; -- -- if (dt_pmic_i2c_config(&i2c_info) != 0) { -- ERROR("I2C configuration failed\n"); -- panic(); ++ sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, ++ sdmmc2_params.reg_base); + if (sdmmc_node == -FDT_ERR_NOTFOUND) { + return -FDT_ERR_NOTFOUND; + } + +- if (fdt_get_status(sdmmc_node) == DT_DISABLED) { ++ dt_fill_device_info(&dt_info, sdmmc_node); ++ if (dt_info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + +@@ -652,21 +711,8 @@ static int stm32_sdmmc2_dt_get_config(void) + return -FDT_ERR_BADVALUE; + } + +- cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL); +- if (cuint == NULL) { +- return -FDT_ERR_NOTFOUND; - } - -- if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) { -- ERROR("I2C clock enable failed\n"); -- panic(); +- cuint++; +- sdmmc2_params.clock_id = fdt32_to_cpu(*cuint); +- +- cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL); +- if (cuint == NULL) { +- return -FDT_ERR_NOTFOUND; - } - -- /* Initialize PMIC I2C */ -- i2c_handle.i2c_base_addr = i2c_info.base; -- i2c_handle.i2c_init.timing = I2C_TIMING; -- i2c_handle.i2c_init.own_address1 = pmic_i2c_addr; -- i2c_handle.i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; -- i2c_handle.i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; -- i2c_handle.i2c_init.own_address2 = 0; -- i2c_handle.i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; -- i2c_handle.i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; -- i2c_handle.i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; -- -- ret = stm32_i2c_init(&i2c_handle); -- if (ret != 0) { -- ERROR("Cannot initialize I2C %x (%d)\n", -- i2c_handle.i2c_base_addr, ret); -- panic(); -- } -- -- ret = stm32_i2c_config_analog_filter(&i2c_handle, -- I2C_ANALOGFILTER_ENABLE); -- if (ret != 0) { -- ERROR("Cannot initialize I2C analog filter (%d)\n", ret); -- panic(); -- } -- -- ret = stm32_i2c_is_device_ready(&i2c_handle, (uint16_t)pmic_i2c_addr, 1, -- I2C_TIMEOUT); -- if (ret != 0) { -- ERROR("I2C device not ready (%d)\n", ret); -- panic(); -- } -- -- stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr); --} -- --void initialize_pmic(void) --{ -- int status; -- uint8_t read_val; -- -- initialize_pmic_i2c(); -- -- status = stpmu1_register_read(VERSION_STATUS_REG, &read_val); -- if (status != 0) { -- panic(); -- } -- -- INFO("PMIC version = 0x%x\n", read_val); -- -- /* Keep VDD on during the reset cycle */ -- status = stpmu1_register_update(MASK_RESET_BUCK_REG, -- MASK_RESET_BUCK3, -- MASK_RESET_BUCK3); -- if (status != 0) { -- panic(); -- } --} -- --int pmic_ddr_power_init(enum ddr_type ddr_type) --{ -- bool buck3_at_1v8 = false; -- uint8_t read_val; -- int status; -- -- switch (ddr_type) { -- case STM32MP_DDR3: -- /* Set LDO3 to sync mode */ -- status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val); -- if (status != 0) { -- return status; -- } -- -- read_val &= ~STPMU1_LDO3_MODE; -- read_val &= ~STPMU1_LDO12356_OUTPUT_MASK; -- read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT; -- -- status = stpmu1_register_write(LDO3_CONTROL_REG, read_val); -- if (status != 0) { -- return status; -- } -- -- status = stpmu1_regulator_voltage_set("buck2", 1350); -- if (status != 0) { -- return status; -- } -- -- status = stpmu1_regulator_enable("buck2"); -- if (status != 0) { -- return status; -- } -- -- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); -- -- status = stpmu1_regulator_enable("vref_ddr"); -- if (status != 0) { -- return status; -- } -- -- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); -- -- status = stpmu1_regulator_enable("ldo3"); -- if (status != 0) { -- return status; -- } -- -- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); -- break; -- -- case STM32MP_LPDDR2: -- /* -- * Set LDO3 to 1.8V -- * Set LDO3 to bypass mode if BUCK3 = 1.8V -- * Set LDO3 to normal mode if BUCK3 != 1.8V -- */ -- status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val); -- if (status != 0) { -- return status; -- } -- -- if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) { -- buck3_at_1v8 = true; -- } -- -- status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val); -- if (status != 0) { -- return status; -- } -- -- read_val &= ~STPMU1_LDO3_MODE; -- read_val &= ~STPMU1_LDO12356_OUTPUT_MASK; -- read_val |= STPMU1_LDO3_1800000; -- if (buck3_at_1v8) { -- read_val |= STPMU1_LDO3_MODE; -- } -- -- status = stpmu1_register_write(LDO3_CONTROL_REG, read_val); -- if (status != 0) { -- return status; -- } -- -- status = stpmu1_regulator_voltage_set("buck2", 1200); -- if (status != 0) { -- return status; -- } -- -- status = stpmu1_regulator_enable("ldo3"); -- if (status != 0) { -- return status; -- } -- -- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); -- -- status = stpmu1_regulator_enable("buck2"); -- if (status != 0) { -- return status; -- } -- -- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); -- -- status = stpmu1_regulator_enable("vref_ddr"); -- if (status != 0) { -- return status; -- } -- -- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); -- break; -- -- default: -- break; -- }; -- -- return 0; --} +- cuint++; +- sdmmc2_params.reset_id = fdt32_to_cpu(*cuint); ++ sdmmc2_params.clock_id = dt_info.clock; ++ sdmmc2_params.reset_id = dt_info.reset; + + if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { + sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; +@@ -701,6 +747,11 @@ static int stm32_sdmmc2_dt_get_config(void) + sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); + } + ++ cuint = fdt_getprop(fdt, sdmmc_node, "vmmc-supply", NULL); ++ if (cuint != NULL) { ++ sdmmc2_params.vmmc_regu.id = fdt32_to_cpu(*cuint); ++ } ++ + return 0; + } + +@@ -719,6 +770,8 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) + + memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); + ++ sdmmc2_params.vmmc_regu.id = -1; ++ + if (stm32_sdmmc2_dt_get_config() != 0) { + ERROR("%s: DT error\n", __func__); + return -ENOMEM; +@@ -726,9 +779,13 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) + + stm32mp_clk_enable(sdmmc2_params.clock_id); + +- stm32mp_reset_assert(sdmmc2_params.reset_id); ++ if (stm32mp_reset_assert_to(sdmmc2_params.reset_id, TIMEOUT_US_1MS)) { ++ panic(); ++ } + udelay(2); +- stm32mp_reset_deassert(sdmmc2_params.reset_id); ++ if (stm32mp_reset_deassert_to(sdmmc2_params.reset_id, TIMEOUT_US_1MS)) { ++ panic(); ++ } + mdelay(1); + + sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id); diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c -new file mode 100644 -index 0000000..c8d70db ---- /dev/null +index 9e9dddc4d..07249f607 100644 +--- a/drivers/st/pmic/stm32mp_pmic.c +++ b/drivers/st/pmic/stm32mp_pmic.c -@@ -0,0 +1,522 @@ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) -+#define STPMIC1_LDO12356_OUTPUT_SHIFT 2 -+#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7)) -+#define STPMIC1_LDO3_DDR_SEL 31U -+#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT) -+ -+#define STPMIC1_BUCK_OUTPUT_SHIFT 2 -+#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT) -+ +@@ -1,9 +1,10 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include + #include + + #include +@@ -22,156 +23,396 @@ + #define STPMIC1_LDO12356_OUTPUT_SHIFT 2 + #define STPMIC1_LDO3_MODE (uint8_t)(BIT(7)) + #define STPMIC1_LDO3_DDR_SEL 31U +-#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT) + + #define STPMIC1_BUCK_OUTPUT_SHIFT 2 + #define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT) + +#define REGULATOR_MODE_STANDBY 8U + -+#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 + #define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 + ++#define CMD_GET_MIN_VOLTAGE 0U ++#define CMD_CONFIG_BOOT_ON 1U ++#define CMD_CONFIG_LP 2U + -+static struct i2c_handle_s i2c_handle; -+static uint32_t pmic_i2c_addr; + static struct i2c_handle_s i2c_handle; + static uint32_t pmic_i2c_addr; + +-static int dt_get_pmic_node(void *fdt) ++static int dt_get_pmic_node(void) + { +- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); ++ static int node = -FDT_ERR_BADOFFSET; + -+static int dt_get_pmic_node(void *fdt) -+{ -+ return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); -+} -+ -+int dt_pmic_status(void) -+{ -+ int node; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; ++ if (node == -FDT_ERR_BADOFFSET) { ++ node = dt_get_node_by_compatible("st,stpmic1"); + } + -+ node = dt_get_pmic_node(fdt); -+ if (node <= 0) { -+ return -FDT_ERR_NOTFOUND; -+ } ++ return node; + } + + int dt_pmic_status(void) + { ++ static int status = -FDT_ERR_BADVALUE; + int node; +- void *fdt; + +- if (fdt_get_address(&fdt) == 0) { +- return -ENOENT; ++ if (status != -FDT_ERR_BADVALUE) { ++ return status; + } + +- node = dt_get_pmic_node(fdt); ++ node = dt_get_pmic_node(); + if (node <= 0) { +- return -FDT_ERR_NOTFOUND; ++ status = -FDT_ERR_NOTFOUND; + -+ return fdt_get_status(node); -+} ++ return status; + } + +- return fdt_get_status(node); ++ status = (int)fdt_get_status(node); + ++ return status; + } + +-/* +- * Get PMIC and its I2C bus configuration from the device tree. +- * Return 0 on success, negative on error, 1 if no PMIC node is found. +- */ +-static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, +- struct stm32_i2c_init_s *init) +static bool dt_pmic_is_secure(void) +{ + int status = dt_pmic_status(); @@ -16870,6 +13609,285 @@ index 0000000..c8d70db + (i2c_handle.dt_status == DT_SECURE); +} + ++static int dt_pmic_get_regulator_voltage(void *fdt, int node, ++ uint16_t *min_mv, uint16_t *max_mv) + { +- int pmic_node, i2c_node; +- void *fdt; + const fdt32_t *cuint; + +- if (fdt_get_address(&fdt) == 0) { +- return -ENOENT; ++ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); ++ if (cuint == NULL) { ++ return -FDT_ERR_NOTFOUND; + } + +- pmic_node = dt_get_pmic_node(fdt); +- if (pmic_node < 0) { +- return 1; ++ if (min_mv != NULL) { ++ *min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); + } + +- cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); ++ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + +- pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; +- if (pmic_i2c_addr > UINT16_MAX) { +- return -EINVAL; ++ if (max_mv != NULL) { ++ *max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); + } + +- i2c_node = fdt_parent_offset(fdt, pmic_node); +- if (i2c_node < 0) { +- return -FDT_ERR_NOTFOUND; ++ return 0; ++} ++ ++static int pmic_config_boot_on(void *fdt, int node, const char *regu_name) ++{ ++ uint16_t voltage = 0U; ++ uint16_t voltage_min; ++ uint16_t voltage_max; ++ int status; ++ int pmic_voltage; ++ ++ if ((fdt_getprop(fdt, node, "regulator-boot-on", NULL) == NULL) && ++ (fdt_getprop(fdt, node, "regulator-always-on", NULL) == NULL)) { ++ return 0; + } + +- dt_fill_device_info(i2c_info, i2c_node); +- if (i2c_info->base == 0U) { +- return -FDT_ERR_NOTFOUND; ++ if (fdt_getprop(fdt, node, "regulator-pull-down", NULL) != NULL) { ++ ++ status = stpmic1_regulator_pull_down_set(regu_name); ++ if (status < 0) { ++ return status; ++ } ++ } ++ ++ if (fdt_getprop(fdt, node, "st,mask-reset", NULL) != NULL) { ++ ++ status = stpmic1_regulator_mask_reset_set(regu_name); ++ if (status < 0) { ++ return status; ++ } ++ } ++ ++ if (dt_pmic_get_regulator_voltage(fdt, node, &voltage_min, ++ &voltage_max) < 0) { ++ return 0; ++ } ++ ++ pmic_voltage = stpmic1_regulator_voltage_get(regu_name); ++ if (pmic_voltage < 0) { ++ return pmic_voltage; ++ } ++ ++ if ((uint16_t)pmic_voltage < voltage_min) { ++ voltage = voltage_min; ++ } ++ ++ if ((uint16_t)pmic_voltage > voltage_max) { ++ voltage = voltage_max; ++ } ++ ++ /* Only re-program voltage if not in the range provided in DT. */ ++ if (voltage != 0U) { ++ status = stpmic1_regulator_voltage_set(regu_name, voltage); ++ if (status < 0) { ++ return status; ++ } ++ } ++ ++ if (!stpmic1_is_regulator_enabled(regu_name)) { ++ status = stpmic1_regulator_enable(regu_name); ++ if (status < 0) { ++ return status; ++ } + } + +- return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); ++ return 0; + } + +-int dt_pmic_configure_boot_on_regulators(void) ++#if defined(IMAGE_BL32) ++static int pmic_config_lp(void *fdt, int node, const char *node_name, ++ const char *regu_name) + { +- int pmic_node, regulators_node, regulator_node; ++ int status; ++ const fdt32_t *cuint; ++ int regulator_state_node; ++ ++ status = stpmic1_powerctrl_on(); ++ if (status < 0) { ++ return status; ++ }; ++ ++ /* ++ * First, copy active configuration (Control register) to ++ * PWRCTRL Control register, even if regulator_state_node ++ * does not exist. ++ */ ++ status = stpmic1_lp_copy_reg(regu_name); ++ if (status < 0) { ++ return status; ++ } ++ ++ /* Then apply configs from regulator_state_node */ ++ regulator_state_node = fdt_subnode_offset(fdt, node, node_name); ++ if (regulator_state_node <= 0) { ++ return 0; ++ } ++ ++ if (fdt_getprop(fdt, regulator_state_node, "regulator-on-in-suspend", ++ NULL) != NULL) { ++ status = stpmic1_lp_reg_on_off(regu_name, 1); ++ if (status < 0) { ++ return status; ++ } ++ } ++ ++ if (fdt_getprop(fdt, regulator_state_node, "regulator-off-in-suspend", ++ NULL) != NULL) { ++ status = stpmic1_lp_reg_on_off(regu_name, 0); ++ if (status < 0) { ++ return status; ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, regulator_state_node, ++ "regulator-suspend-microvolt", NULL); ++ if (cuint != NULL) { ++ uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); ++ ++ status = stpmic1_lp_set_voltage(regu_name, voltage); ++ if (status < 0) { ++ return status; ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, regulator_state_node, "regulator-mode", NULL); ++ if (cuint != NULL) { ++ if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) { ++ status = stpmic1_lp_set_mode(regu_name, 1); ++ if (status < 0) { ++ return status; ++ } ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++static int pmic_operate(uint8_t command, const char *node_name, ++ uint16_t *voltage_mv) ++{ ++ int pmic_node, regulators_node, subnode; + void *fdt; ++ int ret = -EIO; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + +- pmic_node = dt_get_pmic_node(fdt); ++ pmic_node = dt_get_pmic_node(); + if (pmic_node < 0) { +- return -FDT_ERR_NOTFOUND; ++ return -ENOENT; + } + + regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); ++ if (regulators_node < 0) { ++ return -ENOENT; ++ } + +- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { +- const fdt32_t *cuint; +- const char *node_name = fdt_get_name(fdt, regulator_node, NULL); +- uint16_t voltage; +- int status; +- +-#if defined(IMAGE_BL2) +- if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on", +- NULL) == NULL) && +- (fdt_getprop(fdt, regulator_node, "regulator-always-on", +- NULL) == NULL)) { +-#else +- if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", +- NULL) == NULL) { +-#endif +- continue; +- } ++ fdt_for_each_subnode(subnode, fdt, regulators_node) { ++ const char *regu_name = fdt_get_name(fdt, subnode, NULL); + +- if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", +- NULL) != NULL) { ++ switch (command) { ++ case CMD_GET_MIN_VOLTAGE: ++ assert(node_name != NULL); ++ assert(voltage_mv != NULL); + +- status = stpmic1_regulator_pull_down_set(node_name); +- if (status != 0) { +- return status; ++ if (strcmp(regu_name, node_name) != 0) { ++ continue; + } +- } + +- if (fdt_getprop(fdt, regulator_node, "st,mask-reset", +- NULL) != NULL) { ++ ret = dt_pmic_get_regulator_voltage(fdt, subnode, ++ voltage_mv, NULL); ++ if (ret < 0) { ++ return -ENXIO; ++ } + +- status = stpmic1_regulator_mask_reset_set(node_name); +- if (status != 0) { +- return status; ++ return ret; ++ ++ case CMD_CONFIG_BOOT_ON: ++ ret = pmic_config_boot_on(fdt, subnode, regu_name); ++ if (ret < 0) { ++ return ret; + } ++ break; ++ ++#if defined(IMAGE_BL32) ++ case CMD_CONFIG_LP: ++ assert(node_name != NULL); ++ ++ ret = pmic_config_lp(fdt, subnode, node_name, ++ regu_name); ++ if (ret < 0) { ++ return ret; ++ } ++ break; ++#endif ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ return ret; ++} ++ +/* + * Get PMIC and its I2C bus configuration from the device tree. + * Return 0 on success, negative on error, 1 if no PMIC node is defined. @@ -16877,1113 +13895,389 @@ index 0000000..c8d70db +static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, + struct stm32_i2c_init_s *init) +{ -+ int pmic_node, i2c_node; -+ void *fdt; -+ const fdt32_t *cuint; ++ static int i2c_node = -FDT_ERR_NOTFOUND; + -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; ++ if (i2c_node == -FDT_ERR_NOTFOUND) { ++ void *fdt; ++ int pmic_node; ++ const fdt32_t *cuint; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ pmic_node = dt_get_pmic_node(); ++ if (pmic_node < 0) { ++ return 1; + } + +- cuint = fdt_getprop(fdt, regulator_node, +- "regulator-min-microvolt", NULL); ++ cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); + if (cuint == NULL) { +- continue; ++ return -FDT_ERR_NOTFOUND; + } + +- /* DT uses microvolts, whereas driver awaits millivolts */ +- voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); ++ pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; ++ if (pmic_i2c_addr > UINT16_MAX) { ++ return -FDT_ERR_BADVALUE; ++ } + +- status = stpmic1_regulator_voltage_set(node_name, voltage); +- if (status != 0) { +- return status; ++ i2c_node = fdt_parent_offset(fdt, pmic_node); ++ if (i2c_node < 0) { ++ return -FDT_ERR_NOTFOUND; + } + } -+ -+ pmic_node = dt_get_pmic_node(fdt); -+ if (pmic_node < 0) { -+ return 1; -+ } -+ -+ cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; -+ if (pmic_i2c_addr > UINT16_MAX) { -+ return -EINVAL; -+ } -+ -+ i2c_node = fdt_parent_offset(fdt, pmic_node); -+ if (i2c_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ + +- if (stpmic1_is_regulator_enabled(node_name) == 0U) { +- status = stpmic1_regulator_enable(node_name); +- if (status != 0) { +- return status; +- } + dt_fill_device_info(i2c_info, i2c_node); + if (i2c_info->base == 0U) { + return -FDT_ERR_NOTFOUND; + } + -+ return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); ++ return stm32_i2c_get_setup_from_fdt(i2c_node, init); +} + -+int dt_pmic_configure_boot_on_regulators(void) ++int pmic_configure_boot_on_regulators(void) +{ -+ int pmic_node, regulators_node, regulator_node; ++ return pmic_operate(CMD_CONFIG_BOOT_ON, NULL, NULL); ++} ++ ++int pmic_set_lp_config(const char *node_name) ++{ ++ return pmic_operate(CMD_CONFIG_LP, node_name, NULL); ++} ++ ++int dt_pmic_find_supply(const char **supply_name, const char *regu_name) ++{ ++ int pmic_node, regulators_node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; ++ return -FDT_ERR_NOTFOUND; + } + -+ pmic_node = dt_get_pmic_node(fdt); ++ pmic_node = dt_get_pmic_node(); + if (pmic_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ -+ fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -+ const fdt32_t *cuint; -+ const char *node_name = fdt_get_name(fdt, regulator_node, NULL); -+ uint16_t voltage; -+ int status; -+ -+#if defined(IMAGE_BL2) -+ if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on", -+ NULL) == NULL) && -+ (fdt_getprop(fdt, regulator_node, "regulator-always-on", -+ NULL) == NULL)) { -+#else -+ if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", -+ NULL) == NULL) { -+#endif -+ continue; -+ } -+ -+ if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", -+ NULL) != NULL) { -+ int status; -+ -+ status = stpmic1_regulator_pull_down_set(node_name); -+ if (status != 0) { -+ return status; -+ } -+ } -+ -+ if (fdt_getprop(fdt, regulator_node, "st,mask-reset", -+ NULL) != NULL) { -+ int status; -+ -+ status = stpmic1_regulator_mask_reset_set(node_name); -+ if (status != 0) { -+ return status; -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, regulator_node, -+ "regulator-min-microvolt", NULL); -+ if (cuint == NULL) { -+ continue; -+ } -+ -+ /* DT uses microvolts, whereas driver awaits millivolts */ -+ voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -+ -+ status = stpmic1_regulator_voltage_set(node_name, voltage); -+ if (status != 0) { -+ return status; -+ } -+ -+ if (stpmic1_is_regulator_enabled(node_name) == 0U) { -+ status = stpmic1_regulator_enable(node_name); -+ if (status != 0) { -+ return status; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+int dt_pmic_set_lp_config(const char *node_name) -+{ -+ int pmic_node, regulators_node, regulator_node; -+ int status; -+ void *fdt; -+ -+ if (node_name == NULL) { -+ return 0; -+ } -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ pmic_node = dt_get_pmic_node(fdt); -+ if (pmic_node < 0) { ++ if (regulators_node < 0) { + return -FDT_ERR_NOTFOUND; + } + -+ status = stpmic1_powerctrl_on(); -+ if (status != 0) { -+ return status; -+ }; ++ fdt_for_each_subnode(subnode, fdt, regulators_node) { ++ const char *name; + -+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ -+ fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -+ const fdt32_t *cuint; -+ const char *reg_name; -+ int regulator_state_node; -+ -+ /* -+ * First, copy active configuration (Control register) to -+ * PWRCTRL Control register, even if regulator_state_node -+ * does not exist. -+ */ -+ reg_name = fdt_get_name(fdt, regulator_node, NULL); -+ status = stpmic1_lp_copy_reg(reg_name); -+ if (status != 0) { -+ return status; -+ } -+ -+ /* Then apply configs from regulator_state_node */ -+ regulator_state_node = fdt_subnode_offset(fdt, -+ regulator_node, -+ node_name); -+ if (regulator_state_node <= 0) { -+ continue; -+ } -+ -+ if (fdt_getprop(fdt, regulator_state_node, -+ "regulator-on-in-suspend", NULL) != NULL) { -+ status = stpmic1_lp_reg_on_off(reg_name, 1); -+ if (status != 0) { -+ return status; -+ } -+ } -+ -+ if (fdt_getprop(fdt, regulator_state_node, -+ "regulator-off-in-suspend", NULL) != NULL) { -+ status = stpmic1_lp_reg_on_off(reg_name, 0); -+ if (status != 0) { -+ return status; -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, regulator_state_node, -+ "regulator-suspend-microvolt", NULL); -+ if (cuint != NULL) { -+ uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) / -+ 1000U); -+ -+ status = stpmic1_lp_set_voltage(reg_name, voltage); -+ if (status != 0) { -+ return status; -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, regulator_state_node, -+ "regulator-mode", NULL); -+ if (cuint != NULL) { -+ if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) { -+ status = stpmic1_lp_set_mode(reg_name, 1); -+ if (status != 0) { -+ return status; -+ } -+ } -+ } -+ } -+ -+ return 0; ++ name = fdt_getprop(fdt, subnode, "regulator-name", NULL); ++ if ((name != NULL) && ++ (strcmp(name, regu_name) == 0)) { ++ *supply_name = fdt_get_name(fdt, subnode, NULL); ++ return 0; + } + } + +- return 0; ++ return -FDT_ERR_NOTFOUND; +} + -+/* -+ * initialize_pmic_i2c - Initialize I2C for the PMIC control -+ * -+ * Return true if PMIC is available, false if not found, panics on errors -+ */ -+bool initialize_pmic_i2c(void) ++int pmic_set_regulator_min_voltage(const char *regu_name) +{ -+ int ret; -+ struct dt_node_info i2c_info; -+ struct i2c_handle_s *i2c = &i2c_handle; -+ struct stm32_i2c_init_s i2c_init; ++ int rc = -ENOENT; ++ const char *supply_name; + -+ ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); -+ if (ret < 0) { -+ ERROR("I2C configuration failed %d\n", ret); -+ panic(); -+ } -+ if (ret != 0) { -+ return false; -+ } ++ if (dt_pmic_find_supply(&supply_name, regu_name) == 0) { ++ uint16_t min_mv; + -+ /* Initialize PMIC I2C */ -+ i2c->i2c_base_addr = i2c_info.base; -+ i2c->dt_status = i2c_info.status; -+ i2c->clock = i2c_info.clock; -+ i2c_init.own_address1 = pmic_i2c_addr; -+ i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; -+ i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; -+ i2c_init.own_address2 = 0; -+ i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; -+ i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; -+ i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; -+ i2c_init.analog_filter = 1; -+ i2c_init.digital_filter_coef = 0; -+ -+ ret = stm32_i2c_init(i2c, &i2c_init); -+ if (ret != 0) { -+ ERROR("Cannot initialize I2C %x (%d)\n", -+ i2c->i2c_base_addr, ret); -+ panic(); -+ } -+ -+ if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, -+ I2C_TIMEOUT_BUSY_MS)) { -+ ERROR("I2C device not ready\n"); -+ panic(); -+ } -+ -+ stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); -+ -+ return true; -+} -+ -+#if STM32MP1_DEBUG_ENABLE -+int pmic_keep_debug_unit(void) -+{ -+ unsigned int i; -+ static const char * const regus[] = { -+ "buck1", -+ "buck3", -+ }; -+ -+ for (i = 0; i < ARRAY_SIZE(regus); i++) { -+ int res; -+ -+ WARN("Mask %s\n", regus[i]); -+ res = stpmic1_regulator_mask_reset_set(regus[i]); -+ if (res != 0) { -+ return res; ++ rc = pmic_operate(CMD_GET_MIN_VOLTAGE, supply_name, &min_mv); ++ if (rc == 0) { ++ rc = stpmic1_regulator_voltage_set(supply_name, min_mv); + } + } + -+ return 0; -+} -+#endif -+ ++ return rc; + } + + bool initialize_pmic_i2c(void) +@@ -195,6 +436,7 @@ bool initialize_pmic_i2c(void) + i2c->i2c_base_addr = i2c_info.base; + i2c->dt_status = i2c_info.status; + i2c->clock = i2c_info.clock; ++ i2c->i2c_state = I2C_STATE_RESET; + i2c_init.own_address1 = pmic_i2c_addr; + i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; + i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; +@@ -223,15 +465,104 @@ bool initialize_pmic_i2c(void) + return true; + } + +-void initialize_pmic(void) +static void register_non_secure_pmic(void) -+{ + { +- unsigned long pmic_version; + if (i2c_handle.i2c_base_addr == 0U) { + return; + } + + stm32mp_register_non_secure_periph_iomem(i2c_handle.i2c_base_addr); -+ -+ if (stm32mp1_rcc_is_secure()) { -+ stm32mp1_register_clock_parents_secure(i2c_handle.clock); -+ } +} + +static void register_secure_pmic(void) +{ + stm32mp_register_secure_periph_iomem(i2c_handle.i2c_base_addr); +} + ++static int pmic_regulator_enable(struct stm32mp_regulator *regu) ++{ ++ void *fdt; ++ const char *node_name; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ node_name = fdt_get_name(fdt, fdt_node_offset_by_phandle(fdt, regu->id), ++ NULL); ++ ++ return stpmic1_regulator_enable(node_name); ++} ++ ++static int pmic_regulator_disable(struct stm32mp_regulator *regu) ++{ ++ void *fdt; ++ const char *node_name; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ node_name = fdt_get_name(fdt, fdt_node_offset_by_phandle(fdt, regu->id), ++ NULL); ++ ++ return stpmic1_regulator_disable(node_name); ++} ++ ++static const struct stm32mp_regulator_ops pmic_regu_ops = { ++ .enable = pmic_regulator_enable, ++ .disable = pmic_regulator_disable, ++}; ++ ++bool is_pmic_regulator(struct stm32mp_regulator *regu) ++{ ++ void *fdt; ++ int parent_node; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return false; ++ } ++ ++ parent_node = fdt_parent_offset(fdt, ++ fdt_node_offset_by_phandle(fdt, ++ regu->id)); ++ return (fdt_node_check_compatible(fdt, parent_node, ++ "st,stpmic1-regulators") == 0); ++} ++ ++void bind_pmic_regulator(struct stm32mp_regulator *regu) ++{ ++ regu->ops = &pmic_regu_ops; ++} + +void initialize_pmic(void) +{ -+ unsigned long pmic_version; -+ -+ if (!initialize_pmic_i2c()) { -+ VERBOSE("No PMIC\n"); + if (!initialize_pmic_i2c()) { + VERBOSE("No PMIC\n"); + register_non_secure_pmic(); -+ return; -+ } -+ -+ if (stpmic1_get_version(&pmic_version) != 0) { -+ ERROR("Failed to access PMIC\n"); -+ panic(); -+ } -+ -+ INFO("PMIC version = 0x%02lx\n", pmic_version); -+ stpmic1_dump_regulators(); -+ + return; + } + + if (dt_pmic_is_secure()) { + register_secure_pmic(); + } else { + VERBOSE("PMIC is not secure-only hence assumed non secure\n"); + register_non_secure_pmic(); + } ++} + -+#if defined(IMAGE_BL2) -+ if (dt_pmic_configure_boot_on_regulators() != 0) { ++void configure_pmic(void) ++{ ++ if (pmic_configure_boot_on_regulators() < 0) { + panic(); + }; ++} ++ ++#if DEBUG ++void print_pmic_info_and_debug(void) ++{ ++ unsigned long pmic_version; ++ + if (stpmic1_get_version(&pmic_version) != 0) { + ERROR("Failed to access PMIC\n"); + panic(); +@@ -239,19 +570,20 @@ void initialize_pmic(void) + + INFO("PMIC version = 0x%02lx\n", pmic_version); + stpmic1_dump_regulators(); +- +-#if defined(IMAGE_BL2) +- if (dt_pmic_configure_boot_on_regulators() != 0) { +- panic(); +- }; +-#endif + } +#endif -+} + + int pmic_ddr_power_init(enum ddr_type ddr_type) + { + bool buck3_at_1v8 = false; + uint8_t read_val; + int status; ++ uint16_t buck2_mv; ++ uint16_t ldo3_mv; + -+int pmic_ddr_power_init(enum ddr_type ddr_type) -+{ -+ bool buck3_at_1v8 = false; -+ uint8_t read_val; -+ int status; ++ if (pmic_operate(CMD_GET_MIN_VOLTAGE, "buck2", &buck2_mv) != 0) { ++ return -EPERM; ++ } + + switch (ddr_type) { + case STM32MP_DDR3: +@@ -271,7 +603,7 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) + return status; + } + +- status = stpmic1_regulator_voltage_set("buck2", 1350); ++ status = stpmic1_regulator_voltage_set("buck2", buck2_mv); + if (status != 0) { + return status; + } +@@ -321,7 +653,6 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) + + read_val &= ~STPMIC1_LDO3_MODE; + read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; +- read_val |= STPMIC1_LDO3_1800000; + if (buck3_at_1v8) { + read_val |= STPMIC1_LDO3_MODE; + } +@@ -331,7 +662,16 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) + return status; + } + +- status = stpmic1_regulator_voltage_set("buck2", 1200); ++ if (pmic_operate(CMD_GET_MIN_VOLTAGE, "ldo3", &ldo3_mv) != 0) { ++ return -EPERM; ++ } + -+ switch (ddr_type) { -+ case STM32MP_DDR3: -+ /* Set LDO3 to sync mode */ -+ status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); ++ status = stpmic1_regulator_voltage_set("ldo3", ldo3_mv); + if (status != 0) { + return status; + } + -+ read_val &= ~STPMIC1_LDO3_MODE; -+ read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; -+ read_val |= STPMIC1_LDO3_DDR_SEL << -+ STPMIC1_LDO12356_OUTPUT_SHIFT; -+ -+ status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); -+ if (status != 0) { -+ return status; -+ } -+ -+ status = stpmic1_regulator_voltage_set("buck2", 1350); -+ if (status != 0) { -+ return status; -+ } -+ -+ status = stpmic1_regulator_enable("buck2"); -+ if (status != 0) { -+ return status; -+ } -+ -+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ -+ status = stpmic1_regulator_enable("vref_ddr"); -+ if (status != 0) { -+ return status; -+ } -+ -+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ -+ status = stpmic1_regulator_enable("ldo3"); -+ if (status != 0) { -+ return status; -+ } -+ -+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ break; -+ -+ case STM32MP_LPDDR2: -+ case STM32MP_LPDDR3: -+ /* -+ * Set LDO3 to 1.8V -+ * Set LDO3 to bypass mode if BUCK3 = 1.8V -+ * Set LDO3 to normal mode if BUCK3 != 1.8V -+ */ -+ status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val); -+ if (status != 0) { -+ return status; -+ } -+ -+ if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) { -+ buck3_at_1v8 = true; -+ } -+ -+ status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); -+ if (status != 0) { -+ return status; -+ } -+ -+ read_val &= ~STPMIC1_LDO3_MODE; -+ read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; -+ read_val |= STPMIC1_LDO3_1800000; -+ if (buck3_at_1v8) { -+ read_val |= STPMIC1_LDO3_MODE; -+ } -+ -+ status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); -+ if (status != 0) { -+ return status; -+ } -+ -+ status = stpmic1_regulator_voltage_set("buck2", 1200); -+ if (status != 0) { -+ return status; -+ } -+ -+ status = stpmic1_regulator_enable("ldo3"); -+ if (status != 0) { -+ return status; -+ } -+ -+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ -+ status = stpmic1_regulator_enable("buck2"); -+ if (status != 0) { -+ return status; -+ } -+ -+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ -+ status = stpmic1_regulator_enable("vref_ddr"); -+ if (status != 0) { -+ return status; -+ } -+ -+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ break; -+ -+ default: -+ break; -+ }; -+ -+ return 0; -+} ++ status = stpmic1_regulator_voltage_set("buck2", buck2_mv); + if (status != 0) { + return status; + } diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c -new file mode 100644 -index 0000000..2bd2b60 ---- /dev/null +index 999963054..a1db120dc 100644 +--- a/drivers/st/pmic/stpmic1.c +++ b/drivers/st/pmic/stpmic1.c -@@ -0,0 +1,817 @@ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define I2C_TIMEOUT_MS 25 -+ -+struct regul_struct { -+ const char *dt_node_name; -+ const uint16_t *voltage_table; -+ uint8_t voltage_table_size; -+ uint8_t control_reg; -+ uint8_t low_power_reg; -+ uint8_t pull_down_reg; -+ uint8_t pull_down; -+ uint8_t mask_reset_reg; -+ uint8_t mask_reset; +@@ -1,9 +1,10 @@ + /* +- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include + #include + + #include +@@ -419,6 +420,10 @@ static const uint16_t vref_ddr_voltage_table[] = { + 3300, + }; + ++static const uint16_t fixed_5v_voltage_table[] = { ++ 5000, +}; + -+static struct i2c_handle_s *pmic_i2c_handle; -+static uint16_t pmic_i2c_addr; -+ -+/* Voltage tables in mV */ -+static const uint16_t buck1_voltage_table[] = { -+ 725, -+ 725, -+ 725, -+ 725, -+ 725, -+ 725, -+ 750, -+ 775, -+ 800, -+ 825, -+ 850, -+ 875, -+ 900, -+ 925, -+ 950, -+ 975, -+ 1000, -+ 1025, -+ 1050, -+ 1075, -+ 1100, -+ 1125, -+ 1150, -+ 1175, -+ 1200, -+ 1225, -+ 1250, -+ 1275, -+ 1300, -+ 1325, -+ 1350, -+ 1375, -+ 1400, -+ 1425, -+ 1450, -+ 1475, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+}; -+ -+static const uint16_t buck2_voltage_table[] = { -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1050, -+ 1050, -+ 1100, -+ 1100, -+ 1150, -+ 1150, -+ 1200, -+ 1200, -+ 1250, -+ 1250, -+ 1300, -+ 1300, -+ 1350, -+ 1350, -+ 1400, -+ 1400, -+ 1450, -+ 1450, -+ 1500, -+}; -+ -+static const uint16_t buck3_voltage_table[] = { -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1100, -+ 1100, -+ 1100, -+ 1100, -+ 1200, -+ 1200, -+ 1200, -+ 1200, -+ 1300, -+ 1300, -+ 1300, -+ 1300, -+ 1400, -+ 1400, -+ 1400, -+ 1400, -+ 1500, -+ 1600, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3400, -+}; -+ -+static const uint16_t buck4_voltage_table[] = { -+ 600, -+ 625, -+ 650, -+ 675, -+ 700, -+ 725, -+ 750, -+ 775, -+ 800, -+ 825, -+ 850, -+ 875, -+ 900, -+ 925, -+ 950, -+ 975, -+ 1000, -+ 1025, -+ 1050, -+ 1075, -+ 1100, -+ 1125, -+ 1150, -+ 1175, -+ 1200, -+ 1225, -+ 1250, -+ 1275, -+ 1300, -+ 1300, -+ 1350, -+ 1350, -+ 1400, -+ 1400, -+ 1450, -+ 1450, -+ 1500, -+ 1600, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3400, -+ 3500, -+ 3600, -+ 3700, -+ 3800, -+ 3900, -+}; -+ -+static const uint16_t ldo1_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+}; -+ -+static const uint16_t ldo2_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+}; -+ -+static const uint16_t ldo3_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 500, -+ 0xFFFF, /* VREFDDR */ -+}; -+ -+static const uint16_t ldo5_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3400, -+ 3500, -+ 3600, -+ 3700, -+ 3800, -+ 3900, -+}; -+ -+static const uint16_t ldo6_voltage_table[] = { -+ 900, -+ 1000, -+ 1100, -+ 1200, -+ 1300, -+ 1400, -+ 1500, -+ 1600, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+}; -+ -+static const uint16_t ldo4_voltage_table[] = { -+ 3300, -+}; -+ -+static const uint16_t vref_ddr_voltage_table[] = { -+ 3300, -+}; -+ -+/* Table of Regulators in PMIC SoC */ -+static const struct regul_struct regulators_table[] = { + /* Table of Regulators in PMIC SoC */ + static const struct regul_struct regulators_table[] = { + { +@@ -528,6 +533,27 @@ static const struct regul_struct regulators_table[] = { + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = VREF_DDR_MASK_RESET, + }, + { -+ .dt_node_name = "buck1", -+ .voltage_table = buck1_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), -+ .control_reg = BUCK1_CONTROL_REG, -+ .low_power_reg = BUCK1_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK1_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK1_MASK_RESET, ++ .dt_node_name = "boost", ++ .voltage_table = fixed_5v_voltage_table, ++ .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), ++ .control_reg = USB_CONTROL_REG, ++ .mask_reset = BOOST_ENABLED, + }, + { -+ .dt_node_name = "buck2", -+ .voltage_table = buck2_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), -+ .control_reg = BUCK2_CONTROL_REG, -+ .low_power_reg = BUCK2_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK2_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK2_MASK_RESET, ++ .dt_node_name = "pwr_sw1", ++ .voltage_table = fixed_5v_voltage_table, ++ .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), ++ .control_reg = USB_CONTROL_REG, ++ .mask_reset = USBSW_OTG_SWITCH_ENABLED, + }, + { -+ .dt_node_name = "buck3", -+ .voltage_table = buck3_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), -+ .control_reg = BUCK3_CONTROL_REG, -+ .low_power_reg = BUCK3_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK3_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK3_MASK_RESET, ++ .dt_node_name = "pwr_sw2", ++ .voltage_table = fixed_5v_voltage_table, ++ .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), ++ .control_reg = USB_CONTROL_REG, ++ .mask_reset = SWIN_SWOUT_ENABLED, + }, -+ { -+ .dt_node_name = "buck4", -+ .voltage_table = buck4_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), -+ .control_reg = BUCK4_CONTROL_REG, -+ .low_power_reg = BUCK4_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK4_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK4_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "ldo1", -+ .voltage_table = ldo1_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), -+ .control_reg = LDO1_CONTROL_REG, -+ .low_power_reg = LDO1_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO1_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "ldo2", -+ .voltage_table = ldo2_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), -+ .control_reg = LDO2_CONTROL_REG, -+ .low_power_reg = LDO2_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO2_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "ldo3", -+ .voltage_table = ldo3_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), -+ .control_reg = LDO3_CONTROL_REG, -+ .low_power_reg = LDO3_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO3_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "ldo4", -+ .voltage_table = ldo4_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), -+ .control_reg = LDO4_CONTROL_REG, -+ .low_power_reg = LDO4_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO4_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "ldo5", -+ .voltage_table = ldo5_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), -+ .control_reg = LDO5_CONTROL_REG, -+ .low_power_reg = LDO5_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO5_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "ldo6", -+ .voltage_table = ldo6_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), -+ .control_reg = LDO6_CONTROL_REG, -+ .low_power_reg = LDO6_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO6_MASK_RESET, -+ }, -+ { -+ .dt_node_name = "vref_ddr", -+ .voltage_table = vref_ddr_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), -+ .control_reg = VREF_DDR_CONTROL_REG, -+ .low_power_reg = VREF_DDR_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = VREF_DDR_MASK_RESET, -+ }, -+}; -+ -+#define MAX_REGUL ARRAY_SIZE(regulators_table) -+ -+static const struct regul_struct *get_regulator_data(const char *name) -+{ -+ uint8_t i; -+ -+ for (i = 0 ; i < MAX_REGUL ; i++) { -+ if (strncmp(name, regulators_table[i].dt_node_name, -+ strlen(regulators_table[i].dt_node_name)) == 0) { -+ return ®ulators_table[i]; -+ } -+ } -+ -+ /* Regulator not found */ -+ panic(); -+ return NULL; -+} -+ -+static uint8_t voltage_to_index(const char *name, uint16_t millivolts) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ uint8_t i; -+ -+ for (i = 0 ; i < regul->voltage_table_size ; i++) { -+ if (regul->voltage_table[i] == millivolts) { -+ return i; -+ } -+ } -+ -+ /* Voltage not found */ -+ panic(); -+ -+ return 0; -+} -+ -+int stpmic1_powerctrl_on(void) -+{ -+ return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, -+ PWRCTRL_PIN_VALID); -+} -+ -+int stpmic1_switch_off(void) -+{ -+ return stpmic1_register_update(MAIN_CONTROL_REG, 1, -+ SOFTWARE_SWITCH_OFF_ENABLED); -+} -+ -+int stpmic1_regulator_enable(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0)); -+} -+ -+int stpmic1_regulator_disable(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->control_reg, 0, BIT(0)); -+} -+ -+uint8_t stpmic1_is_regulator_enabled(const char *name) -+{ -+ uint8_t val; -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ if (stpmic1_register_read(regul->control_reg, &val) != 0) { -+ panic(); -+ } -+ -+ return (val & 0x1U); -+} -+ -+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) -+{ -+ uint8_t voltage_index = voltage_to_index(name, millivolts); -+ const struct regul_struct *regul = get_regulator_data(name); -+ uint8_t mask; -+ -+ /* Voltage can be set for buck or ldo (except ldo4) regulators */ -+ if (strncmp(name, "buck", 4) == 0) { -+ mask = BUCK_VOLTAGE_MASK; -+ } else if ((strncmp(name, "ldo", 3) == 0) && -+ (strncmp(name, "ldo4", 4) != 0)) { -+ mask = LDO_VOLTAGE_MASK; -+ } else { -+ return 0; -+ } -+ -+ return stpmic1_register_update(regul->control_reg, -+ voltage_index << LDO_BUCK_VOLTAGE_SHIFT, -+ mask); -+} -+ -+int stpmic1_regulator_pull_down_set(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ if (regul->pull_down_reg != 0) { -+ return stpmic1_register_update(regul->pull_down_reg, -+ BIT(regul->pull_down), -+ LDO_BUCK_PULL_DOWN_MASK << -+ regul->pull_down); -+ } -+ -+ return 0; -+} -+ -+int stpmic1_regulator_mask_reset_set(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->mask_reset_reg, -+ BIT(regul->mask_reset), -+ LDO_BUCK_RESET_MASK << -+ regul->mask_reset); -+} -+ + }; + + #define MAX_REGUL ARRAY_SIZE(regulators_table) +@@ -581,17 +607,19 @@ int stpmic1_regulator_enable(const char *name) + { + const struct regul_struct *regul = get_regulator_data(name); + +- return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0)); ++ return stpmic1_register_update(regul->control_reg, LDO_BUCK_ENABLE_MASK, ++ LDO_BUCK_ENABLE_MASK); + } + + int stpmic1_regulator_disable(const char *name) + { + const struct regul_struct *regul = get_regulator_data(name); + +- return stpmic1_register_update(regul->control_reg, 0, BIT(0)); ++ return stpmic1_register_update(regul->control_reg, 0, ++ LDO_BUCK_ENABLE_MASK); + } + +-uint8_t stpmic1_is_regulator_enabled(const char *name) ++bool stpmic1_is_regulator_enabled(const char *name) + { + uint8_t val; + const struct regul_struct *regul = get_regulator_data(name); +@@ -600,7 +628,7 @@ uint8_t stpmic1_is_regulator_enabled(const char *name) + panic(); + } + +- return (val & 0x1U); ++ return (val & LDO_BUCK_ENABLE_MASK) == LDO_BUCK_ENABLE_MASK; + } + + int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) +@@ -648,11 +676,68 @@ int stpmic1_regulator_mask_reset_set(const char *name) + regul->mask_reset); + } + +/* Low-power functions */ +int stpmic1_lp_copy_reg(const char *name) +{ @@ -17991,6 +14285,10 @@ index 0000000..2bd2b60 + int status; + const struct regul_struct *regul = get_regulator_data(name); + ++ if (regul->low_power_reg == 0U) { ++ return 0; ++ } ++ + status = stpmic1_register_read(regul->control_reg, &val); + if (status != 0) { + return status; @@ -18036,1192 +14334,251 @@ index 0000000..2bd2b60 + mask); +} + -+int stpmic1_regulator_voltage_get(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ uint8_t value; -+ uint8_t mask; -+ -+ /* Voltage can be set for buck or ldo (except ldo4) regulators */ -+ if (strncmp(name, "buck", 4) == 0) { -+ mask = BUCK_VOLTAGE_MASK; -+ } else if ((strncmp(name, "ldo", 3) == 0) && -+ (strncmp(name, "ldo4", 4) != 0)) { -+ mask = LDO_VOLTAGE_MASK; -+ } else { -+ return 0; -+ } -+ -+ if (stpmic1_register_read(regul->control_reg, &value)) -+ return -1; -+ -+ value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; -+ -+ if (value > regul->voltage_table_size) -+ return -1; -+ -+ return (int)regul->voltage_table[value]; -+} -+ -+int stpmic1_register_read(uint8_t register_id, uint8_t *value) -+{ -+ return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr, -+ (uint16_t)register_id, -+ I2C_MEMADD_SIZE_8BIT, value, -+ 1, I2C_TIMEOUT_MS); -+} -+ -+int stpmic1_register_write(uint8_t register_id, uint8_t value) -+{ + int stpmic1_regulator_voltage_get(const char *name) + { + const struct regul_struct *regul = get_regulator_data(name); + uint8_t value; + uint8_t mask; + int status; -+ -+ status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr, -+ (uint16_t)register_id, -+ I2C_MEMADD_SIZE_8BIT, &value, -+ 1, I2C_TIMEOUT_MS); -+ -+#if ENABLE_ASSERTIONS -+ if (status != 0) { + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { +@@ -664,13 +749,16 @@ int stpmic1_regulator_voltage_get(const char *name) + return 0; + } + +- if (stpmic1_register_read(regul->control_reg, &value)) +- return -1; ++ status = stpmic1_register_read(regul->control_reg, &value); ++ if (status < 0) { + return status; + } -+ -+ if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { -+ uint8_t readval; -+ -+ status = stpmic1_register_read(register_id, &readval); -+ if (status != 0) { -+ return status; -+ } -+ -+ if (readval != value) { -+ return -1; -+ } + + value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; + +- if (value > regul->voltage_table_size) +- return -1; ++ if (value > regul->voltage_table_size) { ++ return -ERANGE; + } -+#endif -+ -+ return status; -+} -+ -+int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) -+{ + + return (int)regul->voltage_table[value]; + } +@@ -706,7 +794,7 @@ int stpmic1_register_write(uint8_t register_id, uint8_t value) + } + + if (readval != value) { +- return -1; ++ return -EIO; + } + } + #endif +@@ -751,12 +839,12 @@ void stpmic1_dump_regulators(void) + + int stpmic1_get_version(unsigned long *version) + { +- int rc; + uint8_t read_val; + int status; -+ uint8_t val; -+ -+ status = stpmic1_register_read(register_id, &val); -+ if (status != 0) { + +- rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val); +- if (rc) { +- return -1; ++ status = stpmic1_register_read(VERSION_STATUS_REG, &read_val); ++ if (status < 0) { + return status; -+ } + } + + *version = (unsigned long)read_val; +diff --git a/drivers/st/regulator/stm32mp_dummy_regulator.c b/drivers/st/regulator/stm32mp_dummy_regulator.c +new file mode 100644 +index 000000000..1003aba05 +--- /dev/null ++++ b/drivers/st/regulator/stm32mp_dummy_regulator.c +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ + -+ val = (val & ~mask) | (value & mask); ++#include + -+ return stpmic1_register_write(register_id, val); -+} -+ -+void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) ++static int dummy_regulator_enable(struct stm32mp_regulator *regu) +{ -+ pmic_i2c_handle = i2c_handle; -+ pmic_i2c_addr = i2c_addr; -+} -+ -+void stpmic1_dump_regulators(void) -+{ -+ uint32_t i; -+ -+ for (i = 0U; i < MAX_REGUL; i++) { -+ const char *name __unused = regulators_table[i].dt_node_name; -+ -+ VERBOSE("PMIC regul %s: %sable, %dmV", -+ name, -+ stpmic1_is_regulator_enabled(name) ? "en" : "dis", -+ stpmic1_regulator_voltage_get(name)); -+ } -+} -+ -+int stpmic1_get_version(unsigned long *version) -+{ -+ int rc; -+ uint8_t read_val; -+ -+ rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val); -+ if (rc) { -+ return -1; -+ } -+ -+ *version = (unsigned long)read_val; -+ + return 0; +} -diff --git a/drivers/st/pmic/stpmu1.c b/drivers/st/pmic/stpmu1.c -deleted file mode 100644 -index 5951899..0000000 ---- a/drivers/st/pmic/stpmu1.c -+++ /dev/null -@@ -1,600 +0,0 @@ --/* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#include --#include --#include --#include -- --struct regul_struct { -- const char *dt_node_name; -- const uint16_t *voltage_table; -- uint8_t voltage_table_size; -- uint8_t control_reg; -- uint8_t low_power_reg; --}; -- --static struct i2c_handle_s *stpmu_i2c_handle; --static uint16_t stpmu_i2c_addr; -- --/* Voltage tables in mV */ --static const uint16_t buck1_voltage_table[] = { -- 600, -- 625, -- 650, -- 675, -- 700, -- 725, -- 750, -- 775, -- 800, -- 825, -- 850, -- 875, -- 900, -- 925, -- 950, -- 975, -- 1000, -- 1025, -- 1050, -- 1075, -- 1100, -- 1125, -- 1150, -- 1175, -- 1200, -- 1225, -- 1250, -- 1275, -- 1300, -- 1325, -- 1350, -- 1350, --}; -- --static const uint16_t buck2_voltage_table[] = { -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1050, -- 1050, -- 1100, -- 1100, -- 1150, -- 1150, -- 1200, -- 1200, -- 1250, -- 1250, -- 1300, -- 1300, -- 1350, -- 1350, -- 1400, -- 1400, -- 1450, -- 1450, -- 1500, --}; -- --static const uint16_t buck3_voltage_table[] = { -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1000, -- 1100, -- 1100, -- 1100, -- 1100, -- 1200, -- 1200, -- 1200, -- 1200, -- 1300, -- 1300, -- 1300, -- 1300, -- 1400, -- 1400, -- 1400, -- 1400, -- 1500, -- 1600, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, -- 3400, --}; -- --static const uint16_t buck4_voltage_table[] = { -- 600, -- 625, -- 650, -- 675, -- 700, -- 725, -- 750, -- 775, -- 800, -- 825, -- 850, -- 875, -- 900, -- 925, -- 950, -- 975, -- 1000, -- 1025, -- 1050, -- 1075, -- 1100, -- 1125, -- 1150, -- 1175, -- 1200, -- 1225, -- 1250, -- 1275, -- 1300, -- 1300, -- 1350, -- 1350, -- 1400, -- 1400, -- 1450, -- 1450, -- 1500, -- 1600, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, -- 3400, -- 3500, -- 3600, -- 3700, -- 3800, -- 3900, --}; -- --static const uint16_t ldo1_voltage_table[] = { -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, --}; -- --static const uint16_t ldo2_voltage_table[] = { -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, --}; -- --static const uint16_t ldo3_voltage_table[] = { -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, -- 3300, -- 3300, -- 3300, -- 3300, -- 3300, -- 3300, -- 0xFFFF, /* VREFDDR */ --}; -- --static const uint16_t ldo5_voltage_table[] = { -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, -- 3400, -- 3500, -- 3600, -- 3700, -- 3800, -- 3900, --}; -- --static const uint16_t ldo6_voltage_table[] = { -- 900, -- 1000, -- 1100, -- 1200, -- 1300, -- 1400, -- 1500, -- 1600, -- 1700, -- 1800, -- 1900, -- 2000, -- 2100, -- 2200, -- 2300, -- 2400, -- 2500, -- 2600, -- 2700, -- 2800, -- 2900, -- 3000, -- 3100, -- 3200, -- 3300, --}; -- --static const uint16_t ldo4_voltage_table[] = { -- 3300, --}; -- --static const uint16_t vref_ddr_voltage_table[] = { -- 3300, --}; -- --/* Table of Regulators in PMIC SoC */ --static const struct regul_struct regulators_table[] = { -- { -- .dt_node_name = "buck1", -- .voltage_table = buck1_voltage_table, -- .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), -- .control_reg = BUCK1_CONTROL_REG, -- .low_power_reg = BUCK1_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "buck2", -- .voltage_table = buck2_voltage_table, -- .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), -- .control_reg = BUCK2_CONTROL_REG, -- .low_power_reg = BUCK2_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "buck3", -- .voltage_table = buck3_voltage_table, -- .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), -- .control_reg = BUCK3_CONTROL_REG, -- .low_power_reg = BUCK3_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "buck4", -- .voltage_table = buck4_voltage_table, -- .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), -- .control_reg = BUCK4_CONTROL_REG, -- .low_power_reg = BUCK4_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "ldo1", -- .voltage_table = ldo1_voltage_table, -- .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), -- .control_reg = LDO1_CONTROL_REG, -- .low_power_reg = LDO1_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "ldo2", -- .voltage_table = ldo2_voltage_table, -- .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), -- .control_reg = LDO2_CONTROL_REG, -- .low_power_reg = LDO2_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "ldo3", -- .voltage_table = ldo3_voltage_table, -- .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), -- .control_reg = LDO3_CONTROL_REG, -- .low_power_reg = LDO3_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "ldo4", -- .voltage_table = ldo4_voltage_table, -- .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), -- .control_reg = LDO4_CONTROL_REG, -- .low_power_reg = LDO4_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "ldo5", -- .voltage_table = ldo5_voltage_table, -- .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), -- .control_reg = LDO5_CONTROL_REG, -- .low_power_reg = LDO5_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "ldo6", -- .voltage_table = ldo6_voltage_table, -- .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), -- .control_reg = LDO6_CONTROL_REG, -- .low_power_reg = LDO6_PWRCTRL_REG, -- }, -- { -- .dt_node_name = "vref_ddr", -- .voltage_table = vref_ddr_voltage_table, -- .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), -- .control_reg = VREF_DDR_CONTROL_REG, -- .low_power_reg = VREF_DDR_PWRCTRL_REG, -- }, --}; -- --#define MAX_REGUL ARRAY_SIZE(regulators_table) -- --static const struct regul_struct *stpmu1_get_regulator_data(const char *name) --{ -- uint8_t i; -- -- for (i = 0 ; i < MAX_REGUL ; i++) { -- if (strncmp(name, regulators_table[i].dt_node_name, -- strlen(regulators_table[i].dt_node_name)) == 0) { -- return ®ulators_table[i]; -- } -- } -- -- /* Regulator not found */ -- panic(); -- return NULL; --} -- --static uint8_t stpmu1_voltage_find_index(const char *name, -- uint16_t millivolts) --{ -- const struct regul_struct *regul = stpmu1_get_regulator_data(name); -- uint8_t i; -- -- for (i = 0 ; i < regul->voltage_table_size ; i++) { -- if (regul->voltage_table[i] == millivolts) { -- return i; -- } -- } -- -- /* Voltage not found */ -- panic(); -- -- return 0; --} -- --int stpmu1_switch_off(void) --{ -- return stpmu1_register_update(MAIN_CONTROL_REG, 1, -- SOFTWARE_SWITCH_OFF_ENABLED); --} -- --int stpmu1_regulator_enable(const char *name) --{ -- const struct regul_struct *regul = stpmu1_get_regulator_data(name); -- -- return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0)); --} -- --int stpmu1_regulator_disable(const char *name) --{ -- const struct regul_struct *regul = stpmu1_get_regulator_data(name); -- -- return stpmu1_register_update(regul->control_reg, 0, BIT(0)); --} -- --uint8_t stpmu1_is_regulator_enabled(const char *name) --{ -- uint8_t val; -- const struct regul_struct *regul = stpmu1_get_regulator_data(name); -- -- if (stpmu1_register_read(regul->control_reg, &val) != 0) { -- panic(); -- } -- -- return (val & 0x1U); --} -- --int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts) --{ -- uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts); -- const struct regul_struct *regul = stpmu1_get_regulator_data(name); -- -- return stpmu1_register_update(regul->control_reg, voltage_index << 2, -- 0xFC); --} -- --int stpmu1_register_read(uint8_t register_id, uint8_t *value) --{ -- return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr, -- (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT, -- value, 1, 100000); --} -- --int stpmu1_register_write(uint8_t register_id, uint8_t value) --{ -- int status; -- -- status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr, -- (uint16_t)register_id, -- I2C_MEMADD_SIZE_8BIT, &value, 1, 100000); -- -- if (status != 0) { -- return status; -- } -- -- if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { -- uint8_t readval; -- -- status = stpmu1_register_read(register_id, &readval); -- if (status != 0) { -- return status; -- } -- -- if (readval != value) { -- return -1; -- } -- } -- -- return 0; --} -- --int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) --{ -- int status; -- uint8_t val; -- -- status = stpmu1_register_read(register_id, &val); -- if (status != 0) { -- return status; -- } -- -- /* Clear bits to update */ -- val &= ~mask; -- -- /* Update appropriate bits*/ -- val |= (value & mask); -- -- /* Send new value on I2C Bus */ -- return stpmu1_register_write(register_id, val); --} -- --void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) --{ -- stpmu_i2c_handle = i2c_handle; -- stpmu_i2c_addr = i2c_addr; --} -diff --git a/drivers/st/qspi/io_qspi.c b/drivers/st/qspi/io_qspi.c ++ ++static int dummy_regulator_disable(struct stm32mp_regulator *regu) ++{ ++ return 0; ++} ++ ++static const struct stm32mp_regulator_ops dummy_regu_ops = { ++ .enable = dummy_regulator_enable, ++ .disable = dummy_regulator_disable, ++}; ++ ++void bind_dummy_regulator(struct stm32mp_regulator *regu) ++{ ++ regu->ops = &dummy_regu_ops; ++} +diff --git a/drivers/st/regulator/stm32mp_regulator.c b/drivers/st/regulator/stm32mp_regulator.c new file mode 100644 -index 0000000..b00b7d6 +index 000000000..f0e4a4ae5 --- /dev/null -+++ b/drivers/st/qspi/io_qspi.c -@@ -0,0 +1,349 @@ ++++ b/drivers/st/regulator/stm32mp_regulator.c +@@ -0,0 +1,38 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * 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 + -+#define QSPI_COMPAT "st,stm32f469-qspi" ++#include + -+#define TIMEOUT_100_US us2tick(100) -+ -+/* QSPI device functions */ -+static int qspi_dev_open(const uintptr_t init_params, -+ io_dev_info_t **dev_info); -+static int qspi_block_open(io_dev_info_t *dev_info, const uintptr_t spec, -+ io_entity_t *entity); -+static int qspi_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); -+static int qspi_block_seek(io_entity_t *entity, int mode, -+ signed long long offset); -+static int qspi_block_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read); -+static int qspi_block_close(io_entity_t *entity); -+static int qspi_dev_close(io_dev_info_t *dev_info); -+static io_type_t device_type_qspi(void); -+ -+static QSPI_HandleTypeDef *hsd; -+static uint64_t seek_offset; -+ -+static struct dt_node_info qspi_node_info; -+static uintptr_t qspi_mm_base; -+static size_t qspi_mm_size; -+static bool qspi_memory_map; -+ -+static const io_dev_connector_t qspi_dev_connector = { -+ .dev_open = qspi_dev_open -+}; -+ -+static const io_dev_funcs_t qspi_dev_funcs = { -+ .type = device_type_qspi, -+ .open = qspi_block_open, -+ .seek = qspi_block_seek, -+ .size = NULL, -+ .read = qspi_block_read, -+ .write = NULL, -+ .close = qspi_block_close, -+ .dev_init = qspi_dev_init, -+ .dev_close = qspi_dev_close, -+}; -+ -+static const io_dev_info_t qspi_dev_info = { -+ .funcs = &qspi_dev_funcs, -+ .info = (uintptr_t)0, -+}; -+ -+/* Identify the device type as memmap */ -+static io_type_t device_type_qspi(void) ++#pragma weak plat_bind_regulator ++int plat_bind_regulator(struct stm32mp_regulator *regu) +{ -+ return IO_TYPE_QSPI; ++ return -1; +} + -+/* Open a connection to the qspi device */ -+static int qspi_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info) ++int stm32mp_regulator_enable(struct stm32mp_regulator *regu) +{ -+ int qspi_node; -+ int qspi_subnode = 0; -+ int ret; -+ uint32_t fsize; -+ uint32_t flash_max_freq = 0; -+ uint32_t div = 8U; /* Default clock divider */ -+ uint32_t presc; -+ void *fdt; -+ const fdt32_t *cuint = NULL; ++ assert((regu->ops != NULL) && (regu->ops->enable != NULL)); + -+ assert(dev_info); ++ return regu->ops->enable(regu); ++} + -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } ++int stm32mp_regulator_disable(struct stm32mp_regulator *regu) ++{ ++ assert((regu->ops != NULL) && (regu->ops->disable != NULL)); + -+ hsd = (QSPI_HandleTypeDef *)init_params; -+ -+ qspi_node = dt_get_node(&qspi_node_info, -1, QSPI_COMPAT); -+ assert(qspi_node_info.base == (uintptr_t)hsd->instance); -+ -+ *dev_info = (io_dev_info_t *)&qspi_dev_info; -+ -+ ret = fdt_get_reg_props_by_name(qspi_node, "qspi_mm", &qspi_mm_base, -+ &qspi_mm_size); -+ if (ret != 0) { -+ INFO("NOR: Indirect mode\n"); -+ qspi_memory_map = false; -+ -+ /* -+ * Indirect mode is already initialized by bootrom: -+ * no configuration to be done. -+ */ ++ if (regu->always_on) { + return 0; + } + -+ /* Size of NOR is 2^(fsise + 1) */ -+ fsize = ((__builtin_ctz(qspi_mm_size) - 1) << QSPI_DCR_FSIZE_SHIFT) & -+ QSPI_DCR_FSIZE_MASK; -+ -+ /* switch to memory mapped mode */ -+ INFO("NOR: Memory mapped mode\n"); -+ qspi_memory_map = true; -+ -+ fdt_for_each_subnode(qspi_subnode, fdt, qspi_node) { -+ cuint = fdt_getprop(fdt, qspi_subnode, "reg", NULL); -+ -+ if ((cuint != NULL) && (fdt32_to_cpu(*cuint) == 0U)) { -+ /* Flash node found */ -+ cuint = fdt_getprop(fdt, qspi_subnode, -+ "spi-max-frequency", NULL); -+ if (cuint != NULL) { -+ flash_max_freq = fdt32_to_cpu(*cuint); -+ } -+ -+ break; -+ } -+ } -+ -+ if (flash_max_freq != 0) { -+ div = div_round_up(stm32mp_clk_get_rate(qspi_node_info.clock), -+ flash_max_freq); -+ } -+ -+ presc = div - 1U; -+ -+ if (presc > UINT8_MAX) { -+ presc = UINT8_MAX; -+ } -+ -+ presc <<= QSPI_CR_PRESCALER_SHIFT; -+ -+ /* Check if QuadSPI was configured in dual flash mode */ -+ if ((hsd->instance->CR & QSPI_CR_DFM) != 0U) { -+ hsd->instance->CR = QSPI_CR_EN | presc | QSPI_CR_DFM; -+ if (hsd->is_dual == 0U) { -+ WARN("Dual NOR configured in IP\n"); -+ WARN(" but set as single in boot context\n"); -+ WARN(" -> Try Dual NOR boot\n"); -+ } -+ } else { -+ hsd->instance->CR = QSPI_CR_EN | presc; -+ if (hsd->is_dual != 0U) { -+ WARN("Single NOR configured in IP\n"); -+ WARN(" but set as dual in boot context\n"); -+ WARN(" -> Try Single NOR boot\n"); -+ } -+ } -+ -+ hsd->instance->DCR = fsize | QSPI_DCR_CSHT; -+ hsd->instance->CCR = QSPI_DFLT_READ_FLAGS | QSPI_CCR_FMODE_MM; -+ -+ return 0; ++ return regu->ops->disable(regu); +} + -+static int qspi_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) ++int stm32mp_regulator_register(struct stm32mp_regulator *regu) +{ -+ return 0; -+} -+ -+/* Close a connection to the qspi device */ -+static int qspi_dev_close(io_dev_info_t *dev_info) -+{ -+ uint64_t start; -+ -+ /* Send Abort command to end all transfers */ -+ hsd->instance->CR |= QSPI_CR_ABORT; -+ -+ start = timeout_start(); -+ while ((hsd->instance->CR & QSPI_CR_ABORT) != 0U) { -+ if (timeout_elapsed(start, TIMEOUT_100_US)) { -+ return -ETIMEDOUT; -+ } -+ } -+ -+ return 0; -+} -+ -+/* Open a file on the qspi device */ -+static int qspi_block_open(io_dev_info_t *dev_info, const uintptr_t spec, -+ io_entity_t *entity) -+{ -+ seek_offset = 0; -+ return 0; -+} -+ -+/* Seek to a particular file offset on the qspi device */ -+static int qspi_block_seek(io_entity_t *entity, int mode, -+ signed long long offset) -+{ -+ seek_offset = offset; -+ return 0; -+} -+ -+/* Read blocks in indirect mode */ -+static int qspi_block_read_indr(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ -+ uint32_t local_length = (uint32_t)length; -+ uint8_t *data = (uint8_t *)buffer; -+ uint8_t *qspi_dr_u8; -+ uint64_t start; -+ int ret = 0; -+ -+ assert(hsd); -+ -+ qspi_dr_u8 = (uint8_t *)&hsd->instance->DR; -+ -+ /* Clear all flags */ -+ hsd->instance->FCR = QSPI_SR_TCF | QSPI_SR_FTF | -+ QSPI_FCR_CTOF | QSPI_FCR_CSMF; -+ hsd->instance->DLR = local_length - 1; -+ hsd->instance->CCR = QSPI_DFLT_READ_FLAGS | QSPI_CCR_FMODE; -+ hsd->instance->AR = seek_offset; -+ -+ while (local_length != 0U) { -+ *data++ = *qspi_dr_u8; -+ local_length--; -+ } -+ -+ *length_read = length; -+ -+ start = timeout_start(); -+ while ((hsd->instance->SR & QSPI_SR_BUSY) != 0U) { -+ if (timeout_elapsed(start, TIMEOUT_100_US)) { -+ ret = -ETIMEDOUT; -+ break; -+ } -+ } -+ -+ return ret; -+} -+ -+static int qspi_block_read_mm_part(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ -+ uint64_t start; -+ int ret = 0; -+ -+ assert(hsd); -+ -+ memcpy((uint8_t *)buffer, (uint8_t *)qspi_mm_base + seek_offset, -+ length); -+ -+ *length_read = length; -+ -+ start = timeout_start(); -+ while ((hsd->instance->SR & QSPI_SR_BUSY) != 0U) { -+ if (timeout_elapsed(start, TIMEOUT_100_US)) { -+ ret = -ETIMEDOUT; -+ break; -+ } -+ } -+ -+ /* Send abort to avoid prefetch issues */ -+ hsd->instance->CR |= QSPI_CR_ABORT; -+ -+ start = timeout_start(); -+ while ((hsd->instance->CR & QSPI_CR_ABORT) != 0U) { -+ if (timeout_elapsed(start, TIMEOUT_100_US)) { -+ ret = -ETIMEDOUT; -+ break; -+ } -+ } -+ -+ return ret; -+ -+} -+ -+/* Read blocks in memory map mode */ -+static int qspi_block_read_mm(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ -+ if (seek_offset + length + 1 >= qspi_mm_size) { -+ if (length > QSPI_NOR_LBA_SIZE) { -+ size_t length_read_mm, length_read_indr; -+ -+ qspi_block_read_mm_part(entity, buffer, -+ length - QSPI_NOR_LBA_SIZE, -+ &length_read_mm); -+ -+ seek_offset += length - QSPI_NOR_LBA_SIZE; -+ -+ qspi_block_read_indr(entity, buffer + length - -+ QSPI_NOR_LBA_SIZE, -+ QSPI_NOR_LBA_SIZE, -+ &length_read_indr); -+ -+ *length_read = length_read_mm + length_read_indr; -+ } else { -+ qspi_block_read_indr(entity, buffer, length, -+ length_read); -+ } -+ } else { -+ qspi_block_read_mm_part(entity, buffer, length, length_read); -+ } -+ -+ return 0; -+ -+} -+ -+/* Read data from a file on the qspi device */ -+static int qspi_block_read(io_entity_t *entity, uintptr_t buffer, -+ size_t length, size_t *length_read) -+{ -+ if (qspi_memory_map) { -+ return qspi_block_read_mm(entity, buffer, length, length_read); -+ } -+ -+ return qspi_block_read_indr(entity, buffer, length, length_read); -+} -+ -+/* Close a file on the qspi device */ -+static int qspi_block_close(io_entity_t *entity) -+{ -+ return 0; -+} -+ -+/* Exported functions */ -+ -+/* Register the qspi driver with the IO abstraction */ -+int register_io_dev_qspi(const io_dev_connector_t **dev_con) -+{ -+ int result; -+ -+ assert(dev_con); -+ -+ result = io_register_device(&qspi_dev_info); -+ if (result == 0) { -+ *dev_con = &qspi_dev_connector; -+ } -+ -+ return result; ++ return plat_bind_regulator(regu); +} diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c -index 106bbfe..2e19ef0 100644 +index fd3f93e01..a1e6e6b86 100644 --- a/drivers/st/reset/stm32mp1_reset.c +++ b/drivers/st/reset/stm32mp1_reset.c -@@ -6,34 +6,66 @@ +@@ -6,6 +6,8 @@ - #include - #include -+#include #include - #include + ++#include ++ #include --#include --#include -+#include -+#include - #include --#define RST_CLR_OFFSET 4U -+#define RST_CLR_OFFSET 4U -+#define RESET_TIMEOUT_1MS_IN_US 1000 -+#define RESET_TIMEOUT_STEP_US 10 + #include +@@ -15,8 +17,6 @@ + #include + #include --void stm32mp1_reset_assert(uint32_t id) -+static uint32_t id2reg_offset(unsigned int reset_id) +-#define RESET_TIMEOUT_US_1MS U(1000) +- + static uint32_t id2reg_offset(unsigned int reset_id) { -- uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t); -- uint32_t bit = id % (uint32_t)__LONG_BIT; -+ return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t); -+} -+ -+static uint8_t id2reg_bit_pos(unsigned int reset_id) -+{ -+ return (uint8_t)(reset_id & GENMASK(4, 0)); -+} -+ -+void stm32mp_reset_assert(uint32_t id) -+{ -+ uint32_t offset = id2reg_offset(id); -+ uint32_t bitmsk = BIT(id2reg_bit_pos(id)); -+ int nb_tries = RESET_TIMEOUT_1MS_IN_US / RESET_TIMEOUT_STEP_US; -+ uintptr_t rcc_base = stm32mp_rcc_base(); - -- mmio_write_32(RCC_BASE + offset, BIT(bit)); -- while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) == 0U) { -- ; -+ mmio_write_32(rcc_base + offset, bitmsk); -+ -+ while (((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) && -+ (nb_tries != 0)) { -+ udelay(RESET_TIMEOUT_STEP_US); -+ nb_tries--; -+ } -+ -+ if (nb_tries == 0) { -+ ERROR("Reset timeout\n"); -+ panic(); - } + return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t); +@@ -27,36 +27,52 @@ static uint8_t id2reg_bit_pos(unsigned int reset_id) + return (uint8_t)(reset_id & GENMASK(4, 0)); } --void stm32mp1_reset_deassert(uint32_t id) -+void stm32mp_reset_deassert(uint32_t id) +-void stm32mp_reset_assert(uint32_t id) ++int stm32mp_reset_assert_to(uint32_t id, unsigned int to_us) { -- uint32_t offset = ((id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t)) + -- RST_CLR_OFFSET; -- uint32_t bit = id % (uint32_t)__LONG_BIT; -+ uint32_t offset = id2reg_offset(id) + RST_CLR_OFFSET; -+ uint32_t bitmsk = BIT(id2reg_bit_pos(id)); -+ int nb_tries = RESET_TIMEOUT_1MS_IN_US / RESET_TIMEOUT_STEP_US; -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ mmio_write_32(rcc_base + offset, bitmsk); -+ -+ while (((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) && -+ (nb_tries != 0)) { -+ udelay(RESET_TIMEOUT_STEP_US); -+ nb_tries--; -+ } + uint32_t offset = id2reg_offset(id); + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); +- uint64_t timeout_ref; + uintptr_t rcc_base = stm32mp_rcc_base(); -- mmio_write_32(RCC_BASE + offset, BIT(bit)); -- while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) != 0U) { -- ; -+ if (nb_tries == 0) { -+ ERROR("Reset timeout\n"); -+ panic(); + mmio_write_32(rcc_base + offset, bitmsk); + +- timeout_ref = timeout_init_us(RESET_TIMEOUT_US_1MS); +- while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) { +- if (timeout_elapsed(timeout_ref)) { +- panic(); ++ if (to_us != 0) { ++ uint64_t timeout_ref = timeout_init_us(to_us); ++ ++ while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) { ++ if (timeout_elapsed(timeout_ref)) { ++ break; ++ } ++ } ++ ++ if ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) { ++ return -ETIMEDOUT; + } } ++ ++ return 0; + } + +-void stm32mp_reset_deassert(uint32_t id) ++int stm32mp_reset_deassert_to(uint32_t id, unsigned int to_us) + { + uint32_t offset = id2reg_offset(id) + RCC_RSTCLRR_OFFSET; + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); +- uint64_t timeout_ref; + uintptr_t rcc_base = stm32mp_rcc_base(); + + mmio_write_32(rcc_base + offset, bitmsk); + +- timeout_ref = timeout_init_us(RESET_TIMEOUT_US_1MS); +- while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) { +- if (timeout_elapsed(timeout_ref)) { +- panic(); ++ if (to_us != 0) { ++ uint64_t timeout_ref = timeout_init_us(to_us); ++ ++ while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) { ++ if (timeout_elapsed(timeout_ref)) { ++ break; ++ } ++ } ++ ++ if ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) { ++ return -ETIMEDOUT; + } + } ++ ++ return 0; } diff --git a/drivers/st/rng/stm32_rng.c b/drivers/st/rng/stm32_rng.c new file mode 100644 -index 0000000..eec75b2 +index 000000000..b22065616 --- /dev/null +++ b/drivers/st/rng/stm32_rng.c -@@ -0,0 +1,191 @@ +@@ -0,0 +1,188 @@ +/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2018-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 + +#define DT_RNG_COMPAT "st,stm32-rng" +#define RNG_CR 0x00U @@ -19241,6 +14598,8 @@ index 0000000..eec75b2 +#define RNG_TIMEOUT_US 100000 +#define RNG_TIMEOUT_STEP_US 10 + ++#define TIMEOUT_US_1MS U(1000) ++ +struct stm32_rng_instance { + uintptr_t base; + unsigned long clock; @@ -19342,7 +14701,6 @@ index 0000000..eec75b2 + void *fdt; + struct dt_node_info dt_rng; + int node; -+ uint8_t __unused test[43]; + + if (fdt_get_address(&fdt) == 0) { + panic(); @@ -19376,47 +14734,42 @@ index 0000000..eec75b2 + stm32mp_clk_disable(stm32_rng.clock); + + if (dt_rng.reset >= 0) { -+ stm32mp_reset_assert((unsigned long)dt_rng.reset); ++ if (stm32mp_reset_assert_to((unsigned long)dt_rng.reset, ++ TIMEOUT_US_1MS)) ++ panic(); ++ + udelay(20); -+ stm32mp_reset_deassert((unsigned long)dt_rng.reset); ++ if (stm32mp_reset_deassert_to((unsigned long)dt_rng.reset, ++ TIMEOUT_US_1MS)) ++ panic(); + } + + VERBOSE("Init RNG done\n"); + -+#if STM32MP1_DEBUG_ENABLE -+ memset(test, 0xa5, sizeof(test)); -+ if (stm32_rng_read(test, sizeof(test))) { -+ ERROR("RNG test\n"); -+ panic(); -+ } -+ -+ VERBOSE("RNG test:\n"); -+ VERBOSE_HEXDUMP8(test, sizeof(test)); -+#endif -+ + return 0; +} diff --git a/drivers/st/rtc/stm32_rtc.c b/drivers/st/rtc/stm32_rtc.c new file mode 100644 -index 0000000..017c46d +index 000000000..3bfaed772 --- /dev/null +++ b/drivers/st/rtc/stm32_rtc.c -@@ -0,0 +1,499 @@ +@@ -0,0 +1,479 @@ +/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2018-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 + +#define RTC_COMPAT "st,stm32mp1-rtc" + @@ -19487,20 +14840,14 @@ index 0000000..017c46d + +void stm32_rtc_regs_lock(void) +{ -+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT; -+ -+ /* Lock is currently required only when MMU and cache are enabled */ -+ if ((read_sctlr() & mask) == mask) { ++ if (stm32mp_lock_available()) { + spin_lock(&lock); + } +} + +void stm32_rtc_regs_unlock(void) +{ -+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT; -+ -+ /* Unlock is required only when MMU and cache are enabled */ -+ if ((read_sctlr() & mask) == mask) { ++ if (stm32mp_lock_available()) { + spin_unlock(&lock); + } +} @@ -19655,20 +15002,11 @@ index 0000000..017c46d + * This function computes the fraction difference between two timestamps. + * Here again the returned value is in milliseconds. + ******************************************************************************/ -+static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -+ struct stm32_rtc_calendar *ref) ++static signed long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, ++ struct stm32_rtc_calendar *ref) +{ -+ unsigned long long val_r; -+ unsigned long long val_c; -+ -+ val_r = stm32_rtc_get_second_fraction(ref); -+ val_c = stm32_rtc_get_second_fraction(cur); -+ -+ if (val_c >= val_r) { -+ return val_c - val_r; -+ } else { -+ return 1000U - val_r + val_c; -+ } ++ return (signed long long)stm32_rtc_get_second_fraction(cur) - ++ (signed long long)stm32_rtc_get_second_fraction(ref); +} + +/******************************************************************************* @@ -19676,10 +15014,9 @@ index 0000000..017c46d + * It includes seconds, minutes and hours. + * Here again the returned value is in milliseconds. + ******************************************************************************/ -+static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) ++static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current, ++ struct stm32_rtc_time *ref) +{ -+ signed long long diff_in_s; + signed long long curr_s; + signed long long ref_s; + @@ -19691,12 +15028,7 @@ index 0000000..017c46d + (((signed long long)ref->min + + (((signed long long)ref->hour * 60))) * 60); + -+ diff_in_s = curr_s - ref_s; -+ if (diff_in_s < 0) { -+ diff_in_s += 24 * 60 * 60; -+ } -+ -+ return (unsigned long long)diff_in_s * 1000U; ++ return (curr_s - ref_s) * 1000; +} + +/******************************************************************************* @@ -19714,8 +15046,8 @@ index 0000000..017c46d + * It includes days, months, years, with exceptions. + * Here again the returned value is in milliseconds. + ******************************************************************************/ -+static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) ++static signed long long stm32_rtc_diff_date(struct stm32_rtc_time *current, ++ struct stm32_rtc_time *ref) +{ + uint32_t diff_in_days = 0; + uint32_t m; @@ -19789,7 +15121,7 @@ index 0000000..017c46d + } + } + -+ return (24ULL * 60U * 60U * 1000U) * (unsigned long long)diff_in_days; ++ return (24 * 60 * 60 * 1000) * (signed long long)diff_in_days; +} + +/******************************************************************************* @@ -19799,7 +15131,7 @@ index 0000000..017c46d +unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, + struct stm32_rtc_calendar *ref) +{ -+ unsigned long long diff_in_ms = 0; ++ signed long long diff_in_ms = 0; + struct stm32_rtc_time curr_t; + struct stm32_rtc_time ref_t; + @@ -19816,7 +15148,7 @@ index 0000000..017c46d + + stm32mp_clk_disable(rtc_dev.clock); + -+ return diff_in_ms; ++ return (unsigned long long)diff_in_ms; +} + +/******************************************************************************* @@ -19901,28 +15233,2140 @@ index 0000000..017c46d + + return 0; +} +diff --git a/drivers/st/scmi-msg/base.c b/drivers/st/scmi-msg/base.c +new file mode 100644 +index 000000000..80ce190f7 +--- /dev/null ++++ b/drivers/st/scmi-msg/base.c +@@ -0,0 +1,202 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, Linaro Limited ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static bool message_id_is_supported(unsigned int message_id); ++ ++static void report_version(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_version_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .version = SCMI_PROTOCOL_VERSION_BASE, ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void report_attributes(struct scmi_msg *msg) ++{ ++ size_t protocol_count = plat_scmi_protocol_count(); ++ struct scmi_protocol_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ /* Null agent count since agent discovery is not supported */ ++ .attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0U), ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void report_message_attributes(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; ++ struct scmi_protocol_message_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ /* For this protocol, attributes shall be zero */ ++ .attributes = 0U, ++ }; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (!message_id_is_supported(in_args->message_id)) { ++ scmi_status_response(msg, SCMI_NOT_FOUND); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void discover_vendor(struct scmi_msg *msg) ++{ ++ const char *name = plat_scmi_vendor_name(); ++ struct scmi_base_discover_vendor_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name); ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void discover_sub_vendor(struct scmi_msg *msg) ++{ ++ const char *name = plat_scmi_sub_vendor_name(); ++ struct scmi_base_discover_sub_vendor_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name); ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void discover_implementation_version(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_version_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .version = SCMI_IMPL_VERSION, ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static unsigned int count_protocols_in_list(const uint8_t *protocol_list) ++{ ++ unsigned int count = 0U; ++ ++ if (protocol_list != NULL) { ++ while (protocol_list[count] != 0U) { ++ count++; ++ } ++ } ++ ++ return count; ++} ++ ++#define MAX_PROTOCOL_IN_LIST 8U ++ ++static void discover_list_protocols(struct scmi_msg *msg) ++{ ++ const struct scmi_base_discover_list_protocols_a2p *a2p = NULL; ++ struct scmi_base_discover_list_protocols_p2a p2a = { ++ .status = SCMI_SUCCESS, ++ }; ++ uint8_t outargs[sizeof(p2a) + MAX_PROTOCOL_IN_LIST] = { 0U }; ++ const uint8_t *list = NULL; ++ unsigned int count = 0U; ++ ++ if (msg->in_size != sizeof(*a2p)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ assert(msg->out_size > sizeof(outargs)); ++ ++ a2p = (void *)msg->in; ++ ++ list = plat_scmi_protocol_list(msg->agent_id); ++ count = count_protocols_in_list(list); ++ if (count > a2p->skip) { ++ count = MIN(count - a2p->skip, MAX_PROTOCOL_IN_LIST); ++ } else { ++ count = 0U; ++ } ++ ++ p2a.num_protocols = count; ++ ++ memcpy(outargs, &p2a, sizeof(p2a)); ++ memcpy(outargs + sizeof(p2a), list + a2p->skip, count); ++ ++ scmi_write_response(msg, outargs, sizeof(outargs)); ++} ++ ++static const scmi_msg_handler_t scmi_base_handler_table[] = { ++ [SCMI_PROTOCOL_VERSION] = report_version, ++ [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, ++ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, ++ [SCMI_BASE_DISCOVER_VENDOR] = discover_vendor, ++ [SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor, ++ [SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] = ++ discover_implementation_version, ++ [SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols, ++}; ++ ++static bool message_id_is_supported(unsigned int message_id) ++{ ++ return (message_id < ARRAY_SIZE(scmi_base_handler_table)) && ++ (scmi_base_handler_table[message_id] != NULL); ++} ++ ++scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg) ++{ ++ const size_t array_size = ARRAY_SIZE(scmi_base_handler_table); ++ unsigned int message_id = 0U; ++ ++ if (msg->message_id >= array_size) { ++ VERBOSE("Base handle not found %u\n", msg->message_id); ++ return NULL; ++ } ++ ++ message_id = confine_array_index(msg->message_id, array_size); ++ ++ return scmi_base_handler_table[message_id]; ++} +diff --git a/drivers/st/scmi-msg/base.h b/drivers/st/scmi-msg/base.h +new file mode 100644 +index 000000000..689f30a8b +--- /dev/null ++++ b/drivers/st/scmi-msg/base.h +@@ -0,0 +1,75 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, Linaro Limited ++ */ ++ ++#ifndef SCMI_MSG_BASE_H ++#define SCMI_MSG_BASE_H ++ ++#include ++ ++#define SCMI_PROTOCOL_VERSION_BASE 0x20000U ++ ++#define SCMI_DEFAULT_STRING_LENGTH 16U ++ ++enum scmi_base_message_id { ++ SCMI_BASE_DISCOVER_VENDOR = 0x003, ++ SCMI_BASE_DISCOVER_SUB_VENDOR = 0x004, ++ SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x005, ++ SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x006, ++ SCMI_BASE_DISCOVER_AGENT = 0x007, ++ SCMI_BASE_NOTIFY_ERRORS = 0x008, ++}; ++ ++/* ++ * PROTOCOL_ATTRIBUTES ++ */ ++ ++#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS 0 ++#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS 8 ++ ++#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK 0xFFU ++#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK 0xFF00U ++ ++#define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \ ++ ((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \ ++ SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \ ++ (((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \ ++ SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK)) ++ ++/* ++ * BASE_DISCOVER_VENDOR ++ */ ++struct scmi_base_discover_vendor_p2a { ++ int32_t status; ++ char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; ++}; ++ ++/* ++ * BASE_DISCOVER_SUB_VENDOR ++ */ ++struct scmi_base_discover_sub_vendor_p2a { ++ int32_t status; ++ char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; ++}; ++ ++/* ++ * BASE_DISCOVER_IMPLEMENTATION_VERSION ++ * No special structure right now, see protocol_version. ++ */ ++ ++/* ++ * BASE_DISCOVER_LIST_PROTOCOLS ++ */ ++struct scmi_base_discover_list_protocols_a2p { ++ uint32_t skip; ++}; ++ ++struct scmi_base_discover_list_protocols_p2a { ++ int32_t status; ++ uint32_t num_protocols; ++ uint32_t protocols[]; ++}; ++ ++#endif /* SCMI_MSG_BASE_H */ +diff --git a/drivers/st/scmi-msg/clock.c b/drivers/st/scmi-msg/clock.c +new file mode 100644 +index 000000000..72859cbc9 +--- /dev/null ++++ b/drivers/st/scmi-msg/clock.c +@@ -0,0 +1,388 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019-2020, Linaro Limited ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++#pragma weak plat_scmi_clock_count ++#pragma weak plat_scmi_clock_get_name ++#pragma weak plat_scmi_clock_rates_array ++#pragma weak plat_scmi_clock_rates_by_step ++#pragma weak plat_scmi_clock_get_rate ++#pragma weak plat_scmi_clock_set_rate ++#pragma weak plat_scmi_clock_get_state ++#pragma weak plat_scmi_clock_set_state ++ ++static bool message_id_is_supported(unsigned int message_id); ++ ++size_t plat_scmi_clock_count(unsigned int agent_id __unused) ++{ ++ return 0U; ++} ++ ++const char *plat_scmi_clock_get_name(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused) ++{ ++ return NULL; ++} ++ ++int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ unsigned long *rates __unused, ++ size_t *nb_elts __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ unsigned long *steps __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused) ++{ ++ return 0U; ++} ++ ++int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ unsigned long rate __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ bool enable_not_disable __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++static void report_version(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_version_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .version = SCMI_PROTOCOL_VERSION_CLOCK, ++ }; ++ ++ if (msg->in_size != 0) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void report_attributes(struct scmi_msg *msg) ++{ ++ size_t agent_count = plat_scmi_clock_count(msg->agent_id); ++ struct scmi_protocol_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count), ++ }; ++ ++ if (msg->in_size != 0) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void report_message_attributes(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; ++ struct scmi_protocol_message_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ /* For this protocol, attributes shall be zero */ ++ .attributes = 0U, ++ }; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (!message_id_is_supported(in_args->message_id)) { ++ scmi_status_response(msg, SCMI_NOT_FOUND); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void scmi_clock_attributes(struct scmi_msg *msg) ++{ ++ const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in; ++ struct scmi_clock_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ }; ++ const char *name = NULL; ++ unsigned int clock_id = 0U; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ clock_id = confine_array_index(in_args->clock_id, ++ plat_scmi_clock_count(msg->agent_id)); ++ ++ name = plat_scmi_clock_get_name(msg->agent_id, clock_id); ++ if (name == NULL) { ++ scmi_status_response(msg, SCMI_NOT_FOUND); ++ return; ++ } ++ ++ COPY_NAME_IDENTIFIER(return_values.clock_name, name); ++ ++ return_values.attributes = plat_scmi_clock_get_state(msg->agent_id, ++ clock_id); ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void scmi_clock_rate_get(struct scmi_msg *msg) ++{ ++ const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in; ++ unsigned long rate = 0U; ++ struct scmi_clock_rate_get_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ }; ++ unsigned int clock_id = 0U; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ clock_id = confine_array_index(in_args->clock_id, ++ plat_scmi_clock_count(msg->agent_id)); ++ ++ rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id); ++ ++ return_values.rate[0] = (uint32_t)rate; ++ return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32); ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void scmi_clock_rate_set(struct scmi_msg *msg) ++{ ++ const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in; ++ unsigned long rate = 0U; ++ int32_t status = 0; ++ unsigned int clock_id = 0U; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ clock_id = confine_array_index(in_args->clock_id, ++ plat_scmi_clock_count(msg->agent_id)); ++ ++ rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) | ++ in_args->rate[0]); ++ ++ status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate); ++ ++ scmi_status_response(msg, status); ++} ++ ++static void scmi_clock_config_set(struct scmi_msg *msg) ++{ ++ const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in; ++ int32_t status = SCMI_GENERIC_ERROR; ++ bool enable = false; ++ unsigned int clock_id = 0U; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ clock_id = confine_array_index(in_args->clock_id, ++ plat_scmi_clock_count(msg->agent_id)); ++ ++ enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK; ++ ++ status = plat_scmi_clock_set_state(msg->agent_id, clock_id, enable); ++ ++ scmi_status_response(msg, status); ++} ++ ++#define RATES_ARRAY_SIZE_MAX (SCMI_PLAYLOAD_MAX - \ ++ sizeof(struct scmi_clock_describe_rates_p2a)) ++ ++#define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \ ++ SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \ ++ SCMI_CLOCK_RATE_FORMAT_LIST, \ ++ (_rem_rates)) ++#define SCMI_RATES_BY_STEP \ ++ SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \ ++ SCMI_CLOCK_RATE_FORMAT_RANGE, \ ++ 0U) ++ ++#define RATE_DESC_SIZE sizeof(struct scmi_clock_rate) ++ ++static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates, ++ size_t nb_elt) ++{ ++ uint32_t *out = (uint32_t *)(uintptr_t)dest; ++ size_t n; ++ ++ ASSERT_SYM_PTR_ALIGN(out); ++ ++ for (n = 0U; n < nb_elt; n++) { ++ out[2 * n] = (uint32_t)rates[n]; ++ out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32); ++ } ++} ++ ++static void scmi_clock_describe_rates(struct scmi_msg *msg) ++{ ++ const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in; ++ struct scmi_clock_describe_rates_p2a p2a = { ++ .status = SCMI_SUCCESS, ++ }; ++ size_t nb_rates; ++ int32_t status; ++ unsigned int clock_id; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ clock_id = confine_array_index(in_args->clock_id, ++ plat_scmi_clock_count(msg->agent_id)); ++ ++ /* Platform may support array rate description */ ++ status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL, ++ &nb_rates); ++ if (status == SCMI_SUCCESS) { ++ /* Currently 12 cells mex, so it's affordable for the stack */ ++ unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE]; ++ size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE; ++ size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb); ++ size_t rem_nb = nb_rates - in_args->rate_index - ret_nb; ++ ++ status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, ++ plat_rates, &ret_nb); ++ if (status == SCMI_SUCCESS) { ++ write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), ++ plat_rates, ret_nb); ++ ++ p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb, ++ rem_nb); ++ p2a.status = SCMI_SUCCESS; ++ ++ memcpy(msg->out, &p2a, sizeof(p2a)); ++ msg->out_size_out = sizeof(p2a) + ++ ret_nb * RATE_DESC_SIZE; ++ } ++ } else if (status == SCMI_NOT_SUPPORTED) { ++ unsigned long triplet[3] = { 0U, 0U, 0U }; ++ ++ /* Platform may support min§max/step triplet description */ ++ status = plat_scmi_clock_rates_by_step(msg->agent_id, clock_id, ++ triplet); ++ if (status == SCMI_SUCCESS) { ++ write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), ++ triplet, 3U); ++ ++ p2a.num_rates_flags = SCMI_RATES_BY_STEP; ++ p2a.status = SCMI_SUCCESS; ++ ++ memcpy(msg->out, &p2a, sizeof(p2a)); ++ msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE); ++ } ++ } else { ++ /* Fallthrough generic exit sequence below with error status */ ++ } ++ ++ if (status != SCMI_SUCCESS) { ++ scmi_status_response(msg, status); ++ } else { ++ /* ++ * Message payload is already writen to msg->out, and ++ * msg->out_size_out updated. ++ */ ++ } ++} ++ ++static const scmi_msg_handler_t scmi_clock_handler_table[] = { ++ [SCMI_PROTOCOL_VERSION] = report_version, ++ [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, ++ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, ++ [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes, ++ [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates, ++ [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set, ++ [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get, ++ [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set, ++}; ++ ++static bool message_id_is_supported(size_t message_id) ++{ ++ return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) && ++ (scmi_clock_handler_table[message_id] != NULL); ++} ++ ++scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg) ++{ ++ const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table); ++ unsigned int message_id = 0U; ++ ++ if (msg->message_id >= array_size) { ++ VERBOSE("Clock handle not found %u", msg->message_id); ++ return NULL; ++ } ++ ++ message_id = confine_array_index(msg->message_id, array_size); ++ ++ return scmi_clock_handler_table[message_id]; ++} +diff --git a/drivers/st/scmi-msg/clock.h b/drivers/st/scmi-msg/clock.h +new file mode 100644 +index 000000000..a637934ee +--- /dev/null ++++ b/drivers/st/scmi-msg/clock.h +@@ -0,0 +1,150 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, Linaro Limited ++ */ ++ ++#ifndef SCMI_MSG_CLOCK_H ++#define SCMI_MSG_CLOCK_H ++ ++#include ++ ++#include ++ ++#define SCMI_PROTOCOL_VERSION_CLOCK 0x20000U ++ ++/* ++ * Identifiers of the SCMI Clock Management Protocol commands ++ */ ++enum scmi_clock_command_id { ++ SCMI_CLOCK_ATTRIBUTES = 0x003, ++ SCMI_CLOCK_DESCRIBE_RATES = 0x004, ++ SCMI_CLOCK_RATE_SET = 0x005, ++ SCMI_CLOCK_RATE_GET = 0x006, ++ SCMI_CLOCK_CONFIG_SET = 0x007, ++}; ++ ++/* Protocol attributes */ ++#define SCMI_CLOCK_CLOCK_COUNT_MASK GENMASK(15, 0) ++#define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK GENMASK(23, 16) ++ ++#define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \ ++ ((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \ ++ (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK))) ++ ++struct scmi_clock_attributes_a2p { ++ uint32_t clock_id; ++}; ++ ++#define SCMI_CLOCK_NAME_LENGTH_MAX 16U ++ ++struct scmi_clock_attributes_p2a { ++ int32_t status; ++ uint32_t attributes; ++ char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; ++}; ++ ++/* ++ * Clock Rate Get ++ */ ++ ++struct scmi_clock_rate_get_a2p { ++ uint32_t clock_id; ++}; ++ ++struct scmi_clock_rate_get_p2a { ++ int32_t status; ++ uint32_t rate[2]; ++}; ++ ++/* ++ * Clock Rate Set ++ */ ++ ++/* If set, set the new clock rate asynchronously */ ++#define SCMI_CLOCK_RATE_SET_ASYNC_POS 0 ++/* If set, do not send a delayed asynchronous response */ ++#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS 1 ++/* Round up, if set, otherwise round down */ ++#define SCMI_CLOCK_RATE_SET_ROUND_UP_POS 2 ++/* If set, the platform chooses the appropriate rounding mode */ ++#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS 3 ++ ++#define SCMI_CLOCK_RATE_SET_ASYNC_MASK \ ++ BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS) ++#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \ ++ BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS) ++#define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \ ++ BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS) ++#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \ ++ BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS) ++ ++struct scmi_clock_rate_set_a2p { ++ uint32_t flags; ++ uint32_t clock_id; ++ uint32_t rate[2]; ++}; ++ ++struct scmi_clock_rate_set_p2a { ++ int32_t status; ++}; ++ ++/* ++ * Clock Config Set ++ */ ++ ++#define SCMI_CLOCK_CONFIG_SET_ENABLE_POS 0 ++ ++#define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \ ++ BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS) ++ ++struct scmi_clock_config_set_a2p { ++ uint32_t clock_id; ++ uint32_t attributes; ++}; ++ ++struct scmi_clock_config_set_p2a { ++ int32_t status; ++}; ++ ++/* ++ * Clock Describe Rates ++ */ ++ ++#define SCMI_CLOCK_RATE_FORMAT_RANGE 1U ++#define SCMI_CLOCK_RATE_FORMAT_LIST 0U ++ ++#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK GENMASK_32(31, 16) ++#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS 16 ++ ++#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK BIT(12) ++#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS 12 ++ ++#define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK GENMASK_32(11, 0) ++ ++#define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \ ++ ( \ ++ ((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \ ++ (((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \ ++ SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \ ++ (((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \ ++ SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \ ++ ) ++ ++struct scmi_clock_rate { ++ uint32_t low; ++ uint32_t high; ++}; ++ ++struct scmi_clock_describe_rates_a2p { ++ uint32_t clock_id; ++ uint32_t rate_index; ++}; ++ ++struct scmi_clock_describe_rates_p2a { ++ int32_t status; ++ uint32_t num_rates_flags; ++ struct scmi_clock_rate rates[]; ++}; ++ ++#endif /* SCMI_MSG_CLOCK_H */ +diff --git a/drivers/st/scmi-msg/common.h b/drivers/st/scmi-msg/common.h +new file mode 100644 +index 000000000..bf073418f +--- /dev/null ++++ b/drivers/st/scmi-msg/common.h +@@ -0,0 +1,136 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, Linaro Limited ++ */ ++#ifndef SCMI_MSG_COMMON_H ++#define SCMI_MSG_COMMON_H ++ ++#include ++#include ++#include ++#include ++ ++#include "base.h" ++#include "clock.h" ++#include "reset_domain.h" ++ ++#define SCMI_VERSION 0x20000U ++#define SCMI_IMPL_VERSION 0U ++ ++#define SCMI_PLAYLOAD_MAX 92U ++ ++/* ++ * Copy name identifier in target buffer following the SCMI specification ++ * that state name identifier shall be a null terminated string. ++ */ ++#define COPY_NAME_IDENTIFIER(_dst_array, _name) \ ++ do { \ ++ assert(strlen(_name) < sizeof(_dst_array)); \ ++ strlcpy((_dst_array), (_name), sizeof(_dst_array)); \ ++ } while (0) ++ ++/* Common command identifiers shared by all procotols */ ++enum scmi_common_message_id { ++ SCMI_PROTOCOL_VERSION = 0x000, ++ SCMI_PROTOCOL_ATTRIBUTES = 0x001, ++ SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002 ++}; ++ ++/* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */ ++struct scmi_protocol_version_p2a { ++ int32_t status; ++ uint32_t version; ++}; ++ ++/* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */ ++struct scmi_protocol_attributes_p2a { ++ int32_t status; ++ uint32_t attributes; ++}; ++ ++/* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */ ++struct scmi_protocol_message_attributes_a2p { ++ uint32_t message_id; ++}; ++ ++/* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */ ++struct scmi_protocol_message_attributes_p2a { ++ int32_t status; ++ uint32_t attributes; ++}; ++ ++/* ++ * struct scmi_msg - SCMI message context ++ * ++ * @agent_id: SCMI agent ID, safely set from secure world ++ * @protocol_id: SCMI protocol ID for the related message, set by caller agent ++ * @message_id: SCMI message ID for the related message, set by caller agent ++ * @in: Address of the incoming message payload copied in secure memory ++ * @in_size: Byte length of the incoming message payload, set by caller agent ++ * @out: Address of of the output message payload message in non-secure memory ++ * @out_size: Byte length of the provisionned output buffer ++ * @out_size_out: Byte length of the output message payload ++ */ ++struct scmi_msg { ++ unsigned int agent_id; ++ unsigned int protocol_id; ++ unsigned int message_id; ++ char *in; ++ size_t in_size; ++ char *out; ++ size_t out_size; ++ size_t out_size_out; ++}; ++ ++/* ++ * Type scmi_msg_handler_t is used by procotol drivers to safely find ++ * the handler function for the incoming message ID. ++ */ ++typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg); ++ ++/* ++ * scmi_msg_get_base_handler - Return a handler for a base message ++ * @msg - message to process ++ * Return a function handler for the message or NULL ++ */ ++scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg); ++ ++/* ++ * scmi_msg_get_clock_handler - Return a handler for a clock message ++ * @msg - message to process ++ * Return a function handler for the message or NULL ++ */ ++scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg); ++ ++/* ++ * scmi_msg_get_rd_handler - Return a handler for a reset domain message ++ * @msg - message to process ++ * Return a function handler for the message or NULL ++ */ ++scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg); ++ ++/* ++ * Process Read, process and write response for input SCMI message ++ * ++ * @msg: SCMI message context ++ */ ++void scmi_process_message(struct scmi_msg *msg); ++ ++/* ++ * Write SCMI response payload to output message shared memory ++ * ++ * @msg: SCMI message context ++ * @payload: Output message payload ++ * @size: Byte size of output message payload ++ */ ++void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size); ++ ++/* ++ * Write status only SCMI response payload to output message shared memory ++ * ++ * @msg: SCMI message context ++ * @status: SCMI status value returned to caller ++ */ ++void scmi_status_response(struct scmi_msg *msg, int32_t status); ++#endif /* SCMI_MSG_COMMON_H */ +diff --git a/drivers/st/scmi-msg/entry.c b/drivers/st/scmi-msg/entry.c +new file mode 100644 +index 000000000..ae1384e2b +--- /dev/null ++++ b/drivers/st/scmi-msg/entry.c +@@ -0,0 +1,63 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019-2020, Linaro Limited ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++ ++void scmi_status_response(struct scmi_msg *msg, int32_t status) ++{ ++ assert(msg->out && msg->out_size >= sizeof(int32_t)); ++ ++ memcpy(msg->out, &status, sizeof(int32_t)); ++ msg->out_size_out = sizeof(int32_t); ++} ++ ++void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size) ++{ ++ /* ++ * Output payload shall be at least the size of the status ++ * Output buffer shall be at least be the size of the status ++ * Output paylaod shall fit in output buffer ++ */ ++ assert(payload && size >= sizeof(int32_t) && size <= msg->out_size && ++ msg->out && msg->out_size >= sizeof(int32_t)); ++ ++ memcpy(msg->out, payload, size); ++ msg->out_size_out = size; ++} ++ ++void scmi_process_message(struct scmi_msg *msg) ++{ ++ scmi_msg_handler_t handler = NULL; ++ ++ switch (msg->protocol_id) { ++ case SCMI_PROTOCOL_ID_BASE: ++ handler = scmi_msg_get_base_handler(msg); ++ break; ++ case SCMI_PROTOCOL_ID_CLOCK: ++ handler = scmi_msg_get_clock_handler(msg); ++ break; ++ case SCMI_PROTOCOL_ID_RESET_DOMAIN: ++ handler = scmi_msg_get_rd_handler(msg); ++ break; ++ default: ++ break; ++ } ++ ++ if (handler) { ++ handler(msg); ++ return; ++ } ++ ++ ERROR("Agent %u Protocol 0x%x Message 0x%x: not supported", ++ msg->agent_id, msg->protocol_id, msg->message_id); ++ ++ scmi_status_response(msg, SCMI_NOT_SUPPORTED); ++} +diff --git a/drivers/st/scmi-msg/reset_domain.c b/drivers/st/scmi-msg/reset_domain.c +new file mode 100644 +index 000000000..23e205b7a +--- /dev/null ++++ b/drivers/st/scmi-msg/reset_domain.c +@@ -0,0 +1,202 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019-2020, Linaro Limited ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static bool message_id_is_supported(unsigned int message_id); ++ ++#pragma weak plat_scmi_rd_count ++#pragma weak plat_scmi_rd_get_name ++#pragma weak plat_scmi_rd_autonomous ++#pragma weak plat_scmi_rd_set_state ++ ++size_t plat_scmi_rd_count(unsigned int agent_id __unused) ++{ ++ return 0U; ++} ++ ++const char *plat_scmi_rd_get_name(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused) ++{ ++ return NULL; ++} ++ ++int32_t plat_scmi_rd_autonomous(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ unsigned int state __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++int32_t plat_scmi_rd_set_state(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ bool assert_not_deassert __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++static void report_version(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_version_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void report_attributes(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .attributes = plat_scmi_rd_count(msg->agent_id), ++ }; ++ ++ if (msg->in_size != 0U) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void report_message_attributes(struct scmi_msg *msg) ++{ ++ struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; ++ struct scmi_protocol_message_attributes_p2a return_values = { ++ .status = SCMI_SUCCESS, ++ .attributes = 0U, ++ }; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (!message_id_is_supported(in_args->message_id)) { ++ scmi_status_response(msg, SCMI_NOT_FOUND); ++ return; ++ } ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void reset_domain_attributes(struct scmi_msg *msg) ++{ ++ struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in; ++ struct scmi_reset_domain_attributes_p2a return_values; ++ const char *name = NULL; ++ unsigned int domain_id = 0U; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->domain_id >= plat_scmi_rd_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ domain_id = confine_array_index(in_args->domain_id, ++ plat_scmi_rd_count(msg->agent_id)); ++ ++ name = plat_scmi_rd_get_name(msg->agent_id, domain_id); ++ if (name == NULL) { ++ scmi_status_response(msg, SCMI_NOT_FOUND); ++ return; ++ } ++ ++ zeromem(&return_values, sizeof(return_values)); ++ return_values.status = SCMI_SUCCESS; ++ return_values.flags = 0U; /* Async and Notif are not supported */ ++ return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT; ++ COPY_NAME_IDENTIFIER(return_values.name, name); ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ ++static void reset_request(struct scmi_msg *msg) ++{ ++ struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in; ++ struct scmi_reset_domain_request_p2a out_args = { ++ .status = SCMI_SUCCESS, ++ }; ++ unsigned int domain_id = 0U; ++ ++ domain_id = confine_array_index(in_args->domain_id, ++ plat_scmi_rd_count(msg->agent_id)); ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ if (in_args->domain_id >= plat_scmi_rd_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_NOT_FOUND); ++ return; ++ } ++ ++ if ((in_args->flags & SCMI_RESET_DOMAIN_AUTO) != 0U) { ++ out_args.status = plat_scmi_rd_autonomous(msg->agent_id, ++ domain_id, ++ in_args->reset_state); ++ } else if ((in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) != 0U) { ++ out_args.status = plat_scmi_rd_set_state(msg->agent_id, ++ domain_id, true); ++ } else { ++ out_args.status = plat_scmi_rd_set_state(msg->agent_id, ++ domain_id, false); ++ } ++ ++ if (out_args.status != SCMI_SUCCESS) { ++ scmi_status_response(msg, out_args.status); ++ } else { ++ scmi_write_response(msg, &out_args, sizeof(out_args)); ++ } ++} ++ ++static const scmi_msg_handler_t scmi_rd_handler_table[] = { ++ [SCMI_PROTOCOL_VERSION] = report_version, ++ [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, ++ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, ++ [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes, ++ [SCMI_RESET_DOMAIN_REQUEST] = reset_request, ++}; ++ ++static bool message_id_is_supported(unsigned int message_id) ++{ ++ return (message_id < ARRAY_SIZE(scmi_rd_handler_table)) && ++ (scmi_rd_handler_table[message_id] != NULL); ++} ++ ++scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg) ++{ ++ const size_t array_size = ARRAY_SIZE(scmi_rd_handler_table); ++ unsigned int message_id = 0U; ++ ++ if (msg->message_id >= array_size) { ++ VERBOSE("Reset domain handle not found %u\n", msg->message_id); ++ return NULL; ++ } ++ ++ message_id = confine_array_index(msg->message_id, array_size); ++ ++ return scmi_rd_handler_table[message_id]; ++} +diff --git a/drivers/st/scmi-msg/reset_domain.h b/drivers/st/scmi-msg/reset_domain.h +new file mode 100644 +index 000000000..47bee5e39 +--- /dev/null ++++ b/drivers/st/scmi-msg/reset_domain.h +@@ -0,0 +1,122 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, Linaro Limited ++ */ ++#ifndef SCMI_MSG_RESET_DOMAIN_H ++#define SCMI_MSG_RESET_DOMAIN_H ++ ++#include ++#include ++ ++#include ++ ++#define SCMI_PROTOCOL_VERSION_RESET_DOMAIN 0x10000U ++ ++#define SCMI_RESET_STATE_ARCH BIT(31) ++#define SCMI_RESET_STATE_IMPL 0U ++ ++/* ++ * Identifiers of the SCMI Reset Domain Management Protocol commands ++ */ ++enum scmi_reset_domain_command_id { ++ SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03, ++ SCMI_RESET_DOMAIN_REQUEST = 0x04, ++ SCMI_RESET_DOMAIN_NOTIFY = 0x05, ++}; ++ ++/* ++ * Identifiers of the SCMI Reset Domain Management Protocol responses ++ */ ++enum scmi_reset_domain_response_id { ++ SCMI_RESET_ISSUED = 0x00, ++ SCMI_RESET_COMPLETE = 0x04, ++}; ++ ++/* ++ * PROTOCOL_ATTRIBUTES ++ */ ++ ++#define SCMI_RESET_DOMAIN_COUNT_MASK GENMASK_32(15, 0) ++ ++struct scmi_reset_domain_protocol_attributes_p2a { ++ int32_t status; ++ uint32_t attributes; ++}; ++ ++/* Value for scmi_reset_domain_attributes_p2a:flags */ ++#define SCMI_RESET_DOMAIN_ATTR_ASYNC BIT(31) ++#define SCMI_RESET_DOMAIN_ATTR_NOTIF BIT(30) ++ ++/* Value for scmi_reset_domain_attributes_p2a:latency */ ++#define SCMI_RESET_DOMAIN_ATTR_UNK_LAT 0x7fffffffU ++#define SCMI_RESET_DOMAIN_ATTR_MAX_LAT 0x7ffffffeU ++ ++/* Macro for scmi_reset_domain_attributes_p2a:name */ ++#define SCMI_RESET_DOMAIN_ATTR_NAME_SZ 16U ++ ++struct scmi_reset_domain_attributes_a2p { ++ uint32_t domain_id; ++}; ++ ++struct scmi_reset_domain_attributes_p2a { ++ int32_t status; ++ uint32_t flags; ++ uint32_t latency; ++ char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ]; ++}; ++ ++/* ++ * RESET ++ */ ++ ++/* Values for scmi_reset_domain_request_a2p:flags */ ++#define SCMI_RESET_DOMAIN_ASYNC BIT(2) ++#define SCMI_RESET_DOMAIN_EXPLICIT BIT(1) ++#define SCMI_RESET_DOMAIN_AUTO BIT(0) ++ ++struct scmi_reset_domain_request_a2p { ++ uint32_t domain_id; ++ uint32_t flags; ++ uint32_t reset_state; ++}; ++ ++struct scmi_reset_domain_request_p2a { ++ int32_t status; ++}; ++ ++/* ++ * RESET_NOTIFY ++ */ ++ ++/* Values for scmi_reset_notify_p2a:flags */ ++#define SCMI_RESET_DOMAIN_DO_NOTIFY BIT(0) ++ ++struct scmi_reset_domain_notify_a2p { ++ uint32_t domain_id; ++ uint32_t notify_enable; ++}; ++ ++struct scmi_reset_domain_notify_p2a { ++ int32_t status; ++}; ++ ++/* ++ * RESET_COMPLETE ++ */ ++ ++struct scmi_reset_domain_complete_p2a { ++ int32_t status; ++ uint32_t domain_id; ++}; ++ ++/* ++ * RESET_ISSUED ++ */ ++ ++struct scmi_reset_domain_issued_p2a { ++ uint32_t domain_id; ++ uint32_t reset_state; ++}; ++ ++#endif /* SCMI_MSG_RESET_DOMAIN_H */ +diff --git a/drivers/st/scmi-msg/smt.c b/drivers/st/scmi-msg/smt.c +new file mode 100644 +index 000000000..9a0502a08 +--- /dev/null ++++ b/drivers/st/scmi-msg/smt.c +@@ -0,0 +1,206 @@ ++// SPDX-License-Identifier: BSD-2-Clause ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019-2020, Linaro Limited ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++/* Legacy SMT/SCMI messages are 128 bytes at most including SMT header */ ++#define SCMI_PLAYLOAD_MAX 92U ++#define SCMI_PLAYLOAD_U32_MAX (SCMI_PLAYLOAD_MAX / sizeof(uint32_t)) ++ ++/** ++ * struct smt_header - SMT formatted header for SMT base shared memory transfer ++ * ++ * @status: Bit flags, see SMT_STATUS_* ++ * @flags: Bit flags, see SMT_FLAG_* ++ * @length: Byte size of message payload (variable) + ::message_header (32bit) ++ * payload: SCMI message payload data ++ */ ++struct smt_header { ++ uint32_t reserved0; ++ uint32_t status; ++ uint64_t reserved1; ++ uint32_t flags; ++ uint32_t length; /* message_header + payload */ ++ uint32_t message_header; ++ uint32_t payload[]; ++}; ++ ++CASSERT(SCMI_PLAYLOAD_MAX + sizeof(struct smt_header) <= SMT_BUF_SLOT_SIZE, ++ assert_scmi_message_max_length_fits_in_smt_buffer_slot); ++ ++/* Flag set in smt_header::status when SMT does not contain pending message */ ++#define SMT_STATUS_FREE BIT(0) ++/* Flag set in smt_header::status when SMT reports an error */ ++#define SMT_STATUS_ERROR BIT(1) ++ ++/* Flag set in smt_header::flags when SMT uses interrupts */ ++#define SMT_FLAG_INTR_ENABLED BIT(1) ++ ++/* Bit fields packed in smt_header::message_header */ ++#define SMT_MSG_ID_MASK GENMASK_32(7, 0) ++#define SMT_HDR_MSG_ID(_hdr) ((_hdr) & SMT_MSG_ID_MASK) ++ ++#define SMT_MSG_TYPE_MASK GENMASK_32(9, 8) ++#define SMT_HDR_TYPE_ID(_hdr) (((_hdr) & SMT_MSG_TYPE_MASK) >> 8) ++ ++#define SMT_MSG_PROT_ID_MASK GENMASK_32(17, 10) ++#define SMT_HDR_PROT_ID(_hdr) (((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10) ++ ++/* ++ * Provision input message payload buffers for fastcall SMC context entries ++ * and for interrupt context execution entries. ++ */ ++static uint32_t fast_smc_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX]; ++static uint32_t interrupt_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX]; ++ ++/* SMP protection on channel access */ ++static struct spinlock smt_channels_lock; ++ ++/* If channel is not busy, set busy and return true, otherwise return false */ ++static bool channel_set_busy(struct scmi_msg_channel *chan) ++{ ++ bool channel_is_busy; ++ ++ spin_lock(&smt_channels_lock); ++ ++ channel_is_busy = chan->busy; ++ ++ if (!channel_is_busy) { ++ chan->busy = true; ++ } ++ ++ spin_unlock(&smt_channels_lock); ++ ++ return !channel_is_busy; ++} ++ ++static void channel_release_busy(struct scmi_msg_channel *chan) ++{ ++ chan->busy = false; ++} ++ ++static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *chan) ++{ ++ return (struct smt_header *)chan->shm_addr; ++} ++ ++/* ++ * Creates a SCMI message instance in secure memory and push it in the SCMI ++ * message drivers. Message structure contains SCMI protocol meta-data and ++ * references to input payload in secure memory and output message buffer ++ * in shared memory. ++ */ ++static void scmi_proccess_smt(unsigned int agent_id, uint32_t *payload_buf) ++{ ++ struct scmi_msg_channel *chan; ++ struct smt_header *smt_hdr; ++ size_t in_payload_size; ++ uint32_t smt_status; ++ struct scmi_msg msg; ++ bool error = true; ++ ++ chan = plat_scmi_get_channel(agent_id); ++ if (chan == NULL) { ++ return; ++ } ++ ++ smt_hdr = channel_to_smt_hdr(chan); ++ assert(smt_hdr); ++ ++ smt_status = __atomic_load_n(&smt_hdr->status, __ATOMIC_RELAXED); ++ ++ if (!channel_set_busy(chan)) { ++ VERBOSE("SCMI channel %u busy", agent_id); ++ goto out; ++ } ++ ++ in_payload_size = __atomic_load_n(&smt_hdr->length, __ATOMIC_RELAXED) - ++ sizeof(smt_hdr->message_header); ++ ++ if (in_payload_size > SCMI_PLAYLOAD_MAX) { ++ VERBOSE("SCMI payload too big %u", in_payload_size); ++ goto out; ++ } ++ ++ if (smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) { ++ VERBOSE("SCMI channel bad status 0x%x", ++ smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)); ++ goto out; ++ } ++ ++ /* Fill message */ ++ zeromem(&msg, sizeof(msg)); ++ msg.in = (char *)payload_buf; ++ msg.in_size = in_payload_size; ++ msg.out = (char *)smt_hdr->payload; ++ msg.out_size = chan->shm_size - sizeof(*smt_hdr); ++ ++ assert(msg.out && msg.out_size >= sizeof(int32_t)); ++ ++ /* Here the payload is copied in secure memory */ ++ memcpy(msg.in, smt_hdr->payload, in_payload_size); ++ ++ msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header); ++ msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header); ++ msg.agent_id = agent_id; ++ ++ scmi_process_message(&msg); ++ ++ /* Update message length with the length of the response message */ ++ smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header); ++ ++ channel_release_busy(chan); ++ error = false; ++ ++out: ++ if (error) { ++ VERBOSE("SCMI error"); ++ smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE; ++ } else { ++ smt_hdr->status |= SMT_STATUS_FREE; ++ } ++} ++ ++void scmi_smt_fastcall_smc_entry(unsigned int agent_id) ++{ ++ scmi_proccess_smt(agent_id, ++ fast_smc_payload[plat_my_core_pos()]); ++} ++ ++void scmi_smt_interrupt_entry(unsigned int agent_id) ++{ ++ scmi_proccess_smt(agent_id, ++ interrupt_payload[plat_my_core_pos()]); ++} ++ ++/* Init a SMT header for a shared memory buffer: state it a free/no-error */ ++void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan) ++{ ++ if (chan != NULL) { ++ struct smt_header *smt_header = channel_to_smt_hdr(chan); ++ ++ if (smt_header != NULL) { ++ memset(smt_header, 0, sizeof(*smt_header)); ++ smt_header->status = SMT_STATUS_FREE; ++ ++ return; ++ } ++ } ++ ++ panic(); ++} +diff --git a/drivers/st/spi/stm32_qspi.c b/drivers/st/spi/stm32_qspi.c +new file mode 100644 +index 000000000..f4a13386f +--- /dev/null ++++ b/drivers/st/spi/stm32_qspi.c +@@ -0,0 +1,507 @@ ++/* ++ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TIMEOUT_US_1MS U(1000) ++ ++/* QUADSPI registers */ ++#define QSPI_CR 0x00U ++#define QSPI_DCR 0x04U ++#define QSPI_SR 0x08U ++#define QSPI_FCR 0x0CU ++#define QSPI_DLR 0x10U ++#define QSPI_CCR 0x14U ++#define QSPI_AR 0x18U ++#define QSPI_ABR 0x1CU ++#define QSPI_DR 0x20U ++#define QSPI_PSMKR 0x24U ++#define QSPI_PSMAR 0x28U ++#define QSPI_PIR 0x2CU ++#define QSPI_LPTR 0x30U ++ ++/* QUADSPI control register */ ++#define QSPI_CR_EN BIT(0) ++#define QSPI_CR_ABORT BIT(1) ++#define QSPI_CR_DMAEN BIT(2) ++#define QSPI_CR_TCEN BIT(3) ++#define QSPI_CR_SSHIFT BIT(4) ++#define QSPI_CR_DFM BIT(6) ++#define QSPI_CR_FSEL BIT(7) ++#define QSPI_CR_FTHRES_SHIFT 8U ++#define QSPI_CR_TEIE BIT(16) ++#define QSPI_CR_TCIE BIT(17) ++#define QSPI_CR_FTIE BIT(18) ++#define QSPI_CR_SMIE BIT(19) ++#define QSPI_CR_TOIE BIT(20) ++#define QSPI_CR_APMS BIT(22) ++#define QSPI_CR_PMM BIT(23) ++#define QSPI_CR_PRESCALER_MASK GENMASK_32(31, 24) ++#define QSPI_CR_PRESCALER_SHIFT 24U ++ ++/* QUADSPI device configuration register */ ++#define QSPI_DCR_CKMODE BIT(0) ++#define QSPI_DCR_CSHT_MASK GENMASK_32(10, 8) ++#define QSPI_DCR_CSHT_SHIFT 8U ++#define QSPI_DCR_FSIZE_MASK GENMASK_32(20, 16) ++#define QSPI_DCR_FSIZE_SHIFT 16U ++ ++/* QUADSPI status register */ ++#define QSPI_SR_TEF BIT(0) ++#define QSPI_SR_TCF BIT(1) ++#define QSPI_SR_FTF BIT(2) ++#define QSPI_SR_SMF BIT(3) ++#define QSPI_SR_TOF BIT(4) ++#define QSPI_SR_BUSY BIT(5) ++ ++/* QUADSPI flag clear register */ ++#define QSPI_FCR_CTEF BIT(0) ++#define QSPI_FCR_CTCF BIT(1) ++#define QSPI_FCR_CSMF BIT(3) ++#define QSPI_FCR_CTOF BIT(4) ++ ++/* QUADSPI communication configuration register */ ++#define QSPI_CCR_DDRM BIT(31) ++#define QSPI_CCR_DHHC BIT(30) ++#define QSPI_CCR_SIOO BIT(28) ++#define QSPI_CCR_FMODE_SHIFT 26U ++#define QSPI_CCR_DMODE_SHIFT 24U ++#define QSPI_CCR_DCYC_SHIFT 18U ++#define QSPI_CCR_ABSIZE_SHIFT 16U ++#define QSPI_CCR_ABMODE_SHIFT 14U ++#define QSPI_CCR_ADSIZE_SHIFT 12U ++#define QSPI_CCR_ADMODE_SHIFT 10U ++#define QSPI_CCR_IMODE_SHIFT 8U ++#define QSPI_CCR_IND_WRITE 0U ++#define QSPI_CCR_IND_READ 1U ++#define QSPI_CCR_MEM_MAP 3U ++ ++#define QSPI_MAX_CHIP 2U ++ ++#define QSPI_FIFO_TIMEOUT_US 30U ++#define QSPI_CMD_TIMEOUT_US 1000U ++#define QSPI_BUSY_TIMEOUT_US 100U ++#define QSPI_ABT_TIMEOUT_US 100U ++ ++#define DT_QSPI_COMPAT "st,stm32f469-qspi" ++ ++#define FREQ_100MHZ 100000000U ++ ++struct stm32_qspi_ctrl { ++ uintptr_t reg_base; ++ uintptr_t mm_base; ++ size_t mm_size; ++ unsigned long clock_id; ++ unsigned int reset_id; ++}; ++ ++static struct stm32_qspi_ctrl stm32_qspi; ++ ++static uintptr_t qspi_base(void) ++{ ++ return stm32_qspi.reg_base; ++} ++ ++static int stm32_qspi_wait_for_not_busy(void) ++{ ++ uint64_t timeout = timeout_init_us(QSPI_BUSY_TIMEOUT_US); ++ ++ while ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_BUSY) != 0U) { ++ if (timeout_elapsed(timeout)) { ++ ERROR("%s: busy timeout\n", __func__); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++static int stm32_qspi_wait_cmd(const struct spi_mem_op *op) ++{ ++ int ret = 0; ++ uint64_t timeout; ++ ++ if (op->data.nbytes == 0U) { ++ return stm32_qspi_wait_for_not_busy(); ++ } ++ ++ timeout = timeout_init_us(QSPI_CMD_TIMEOUT_US); ++ while ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_TCF) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ ret = -ETIMEDOUT; ++ break; ++ } ++ } ++ ++ if (ret == 0) { ++ if ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_TEF) != 0U) { ++ ERROR("%s: transfer error\n", __func__); ++ ret = -EIO; ++ } ++ } else { ++ ERROR("%s: cmd timeout\n", __func__); ++ } ++ ++ /* Clear flags */ ++ mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF | QSPI_FCR_CTEF); ++ ++ return ret; ++} ++ ++static void stm32_qspi_read_fifo(uint8_t *val, uintptr_t addr) ++{ ++ *val = mmio_read_8(addr); ++} ++ ++static void stm32_qspi_write_fifo(uint8_t *val, uintptr_t addr) ++{ ++ mmio_write_8(addr, *val); ++} ++ ++static int stm32_qspi_poll(const struct spi_mem_op *op) ++{ ++ void (*fifo)(uint8_t *val, uintptr_t addr); ++ uint32_t len; ++ uint8_t *buf; ++ ++ if (op->data.dir == SPI_MEM_DATA_IN) { ++ fifo = stm32_qspi_read_fifo; ++ } else { ++ fifo = stm32_qspi_write_fifo; ++ } ++ ++ buf = (uint8_t *)op->data.buf; ++ ++ for (len = op->data.nbytes; len != 0U; len--) { ++ uint64_t timeout = timeout_init_us(QSPI_FIFO_TIMEOUT_US); ++ ++ while ((mmio_read_32(qspi_base() + QSPI_SR) & ++ QSPI_SR_FTF) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ ERROR("%s: fifo timeout\n", __func__); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ fifo(buf++, qspi_base() + QSPI_DR); ++ } ++ ++ return 0; ++} ++ ++static int stm32_qspi_mm(const struct spi_mem_op *op) ++{ ++ memcpy(op->data.buf, ++ (void *)(stm32_qspi.mm_base + (size_t)op->addr.val), ++ op->data.nbytes); ++ ++ return 0; ++} ++ ++static int stm32_qspi_tx(const struct spi_mem_op *op, uint8_t mode) ++{ ++ if (op->data.nbytes == 0U) { ++ return 0; ++ } ++ ++ if (mode == QSPI_CCR_MEM_MAP) { ++ return stm32_qspi_mm(op); ++ } ++ ++ return stm32_qspi_poll(op); ++} ++ ++static unsigned int stm32_qspi_get_mode(uint8_t buswidth) ++{ ++ if (buswidth == 4U) { ++ return 3U; ++ } ++ ++ return buswidth; ++} ++ ++static int stm32_qspi_exec_op(const struct spi_mem_op *op) ++{ ++ uint64_t timeout; ++ uint32_t ccr; ++ size_t addr_max; ++ uint8_t mode = QSPI_CCR_IND_WRITE; ++ int ret; ++ ++ VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addr:%llx len:%x\n", ++ __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, ++ op->dummy.buswidth, op->data.buswidth, ++ op->addr.val, op->data.nbytes); ++ ++ ret = stm32_qspi_wait_for_not_busy(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ addr_max = op->addr.val + op->data.nbytes + 1U; ++ ++ if ((op->data.dir == SPI_MEM_DATA_IN) && (op->data.nbytes != 0U)) { ++ if ((addr_max < stm32_qspi.mm_size) && ++ (op->addr.buswidth != 0U)) { ++ mode = QSPI_CCR_MEM_MAP; ++ } else { ++ mode = QSPI_CCR_IND_READ; ++ } ++ } ++ ++ if (op->data.nbytes != 0U) { ++ mmio_write_32(qspi_base() + QSPI_DLR, op->data.nbytes - 1U); ++ } ++ ++ ccr = mode << QSPI_CCR_FMODE_SHIFT; ++ ccr |= op->cmd.opcode; ++ ccr |= stm32_qspi_get_mode(op->cmd.buswidth) << QSPI_CCR_IMODE_SHIFT; ++ ++ if (op->addr.nbytes != 0U) { ++ ccr |= (op->addr.nbytes - 1U) << QSPI_CCR_ADSIZE_SHIFT; ++ ccr |= stm32_qspi_get_mode(op->addr.buswidth) << ++ QSPI_CCR_ADMODE_SHIFT; ++ } ++ ++ if ((op->dummy.buswidth != 0U) && (op->dummy.nbytes != 0U)) { ++ ccr |= (op->dummy.nbytes * 8U / op->dummy.buswidth) << ++ QSPI_CCR_DCYC_SHIFT; ++ } ++ ++ if (op->data.nbytes != 0U) { ++ ccr |= stm32_qspi_get_mode(op->data.buswidth) << ++ QSPI_CCR_DMODE_SHIFT; ++ } ++ ++ mmio_write_32(qspi_base() + QSPI_CCR, ccr); ++ ++ if ((op->addr.nbytes != 0U) && (mode != QSPI_CCR_MEM_MAP)) { ++ mmio_write_32(qspi_base() + QSPI_AR, op->addr.val); ++ } ++ ++ ret = stm32_qspi_tx(op, mode); ++ ++ /* ++ * Abort in: ++ * - Error case. ++ * - Memory mapped read: prefetching must be stopped if we read the last ++ * byte of device (device size - fifo size). If device size is not ++ * known then prefetching is always stopped. ++ */ ++ if ((ret != 0) || (mode == QSPI_CCR_MEM_MAP)) { ++ goto abort; ++ } ++ ++ /* Wait end of TX in indirect mode */ ++ ret = stm32_qspi_wait_cmd(op); ++ if (ret != 0) { ++ goto abort; ++ } ++ ++ return 0; ++ ++abort: ++ mmio_setbits_32(qspi_base() + QSPI_CR, QSPI_CR_ABORT); ++ ++ /* Wait clear of abort bit by hardware */ ++ timeout = timeout_init_us(QSPI_ABT_TIMEOUT_US); ++ while ((mmio_read_32(qspi_base() + QSPI_CR) & QSPI_CR_ABORT) != 0U) { ++ if (timeout_elapsed(timeout)) { ++ ret = -ETIMEDOUT; ++ break; ++ } ++ } ++ ++ mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF); ++ ++ if (ret != 0) { ++ ERROR("%s: exec op error\n", __func__); ++ } ++ ++ return ret; ++} ++ ++static int stm32_qspi_claim_bus(unsigned int cs) ++{ ++ uint32_t cr; ++ ++ if (cs >= QSPI_MAX_CHIP) { ++ return -ENODEV; ++ } ++ ++ /* Set chip select and enable the controller */ ++ cr = QSPI_CR_EN; ++ if (cs == 1U) { ++ cr |= QSPI_CR_FSEL; ++ } ++ ++ mmio_clrsetbits_32(qspi_base() + QSPI_CR, QSPI_CR_FSEL, cr); ++ ++ return 0; ++} ++ ++static void stm32_qspi_release_bus(void) ++{ ++ mmio_clrbits_32(qspi_base() + QSPI_CR, QSPI_CR_EN); ++} ++ ++static int stm32_qspi_set_speed(unsigned int hz) ++{ ++ unsigned long qspi_clk = stm32mp_clk_get_rate(stm32_qspi.clock_id); ++ uint32_t prescaler = UINT8_MAX; ++ uint32_t csht; ++ int ret; ++ ++ if (qspi_clk == 0U) { ++ return -EINVAL; ++ } ++ ++ if (hz > 0U) { ++ prescaler = div_round_up(qspi_clk, hz) - 1U; ++ if (prescaler > UINT8_MAX) { ++ prescaler = UINT8_MAX; ++ } ++ } ++ ++ csht = div_round_up((5U * qspi_clk) / (prescaler + 1U), FREQ_100MHZ); ++ csht = ((csht - 1U) << QSPI_DCR_CSHT_SHIFT) & QSPI_DCR_CSHT_MASK; ++ ++ ret = stm32_qspi_wait_for_not_busy(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ mmio_clrsetbits_32(qspi_base() + QSPI_CR, QSPI_CR_PRESCALER_MASK, ++ prescaler << QSPI_CR_PRESCALER_SHIFT); ++ ++ mmio_clrsetbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CSHT_MASK, csht); ++ ++ VERBOSE("%s: speed=%lu\n", __func__, qspi_clk / (prescaler + 1U)); ++ ++ return 0; ++} ++ ++static int stm32_qspi_set_mode(unsigned int mode) ++{ ++ int ret; ++ ++ ret = stm32_qspi_wait_for_not_busy(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if ((mode & SPI_CS_HIGH) != 0U) { ++ return -ENODEV; ++ } ++ ++ if (((mode & SPI_CPHA) != 0U) && ((mode & SPI_CPOL) != 0U)) { ++ mmio_setbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CKMODE); ++ } else if (((mode & SPI_CPHA) == 0U) && ((mode & SPI_CPOL) == 0U)) { ++ mmio_clrbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CKMODE); ++ } else { ++ return -ENODEV; ++ } ++ ++ VERBOSE("%s: mode=0x%x\n", __func__, mode); ++ ++ if ((mode & SPI_RX_QUAD) != 0U) { ++ VERBOSE("rx: quad\n"); ++ } else if ((mode & SPI_RX_DUAL) != 0U) { ++ VERBOSE("rx: dual\n"); ++ } else { ++ VERBOSE("rx: single\n"); ++ } ++ ++ if ((mode & SPI_TX_QUAD) != 0U) { ++ VERBOSE("tx: quad\n"); ++ } else if ((mode & SPI_TX_DUAL) != 0U) { ++ VERBOSE("tx: dual\n"); ++ } else { ++ VERBOSE("tx: single\n"); ++ } ++ ++ return 0; ++} ++ ++static const struct spi_bus_ops stm32_qspi_bus_ops = { ++ .claim_bus = stm32_qspi_claim_bus, ++ .release_bus = stm32_qspi_release_bus, ++ .set_speed = stm32_qspi_set_speed, ++ .set_mode = stm32_qspi_set_mode, ++ .exec_op = stm32_qspi_exec_op, ++}; ++ ++int stm32_qspi_init(void) ++{ ++ size_t size; ++ int qspi_node; ++ struct dt_node_info info; ++ void *fdt = NULL; ++ int ret; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ qspi_node = dt_get_node(&info, -1, DT_QSPI_COMPAT); ++ if (qspi_node < 0) { ++ ERROR("No QSPI ctrl found\n"); ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if (info.status == DT_DISABLED) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ ret = fdt_get_reg_props_by_name(qspi_node, "qspi", ++ &stm32_qspi.reg_base, &size); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = fdt_get_reg_props_by_name(qspi_node, "qspi_mm", ++ &stm32_qspi.mm_base, ++ &stm32_qspi.mm_size); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (dt_set_pinctrl_config(qspi_node) != 0) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ if ((info.clock < 0) || (info.reset < 0)) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ stm32_qspi.clock_id = (unsigned long)info.clock; ++ stm32_qspi.reset_id = (unsigned int)info.reset; ++ ++ stm32mp_clk_enable(stm32_qspi.clock_id); ++ ++ if (stm32mp_reset_assert_to(stm32_qspi.reset_id, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ if (stm32mp_reset_deassert_to(stm32_qspi.reset_id, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ ++ mmio_write_32(qspi_base() + QSPI_CR, QSPI_CR_SSHIFT); ++ mmio_write_32(qspi_base() + QSPI_DCR, QSPI_DCR_FSIZE_MASK); ++ ++ return spi_mem_init_slave(fdt, qspi_node, &stm32_qspi_bus_ops); ++}; diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c new file mode 100644 -index 0000000..0bfa177 +index 000000000..216e324d5 --- /dev/null +++ b/drivers/st/tamper/stm32_tamp.c -@@ -0,0 +1,375 @@ +@@ -0,0 +1,377 @@ +/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include ++ +#include -+#include ++ +#include -+#include -+#include -+#include -+#include -+#include ++ ++#include ++#include ++#include ++#include + +#define DT_TAMP_COMPAT "st,stm32-tamp" +/* STM32 Registers */ @@ -20186,8 +17630,8 @@ index 0000000..0bfa177 + uint32_t int_id = (uint32_t)int_list[tamp].id; + + if ((it & BIT(int_id + 16U)) != 0U) { -+ if (int_list[tamp].it_handler != NULL) { -+ int_list[tamp].it_handler(); ++ if (int_list[tamp].func != NULL) { ++ int_list[tamp].func(int_id); + } + + mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, @@ -20208,8 +17652,8 @@ index 0000000..0bfa177 + uint32_t ext_id = (uint32_t)ext_list[tamp].id; + + if ((it & BIT(ext_id)) != 0U) { -+ if (ext_list[tamp].it_handler != NULL) { -+ ext_list[tamp].it_handler(); ++ if (ext_list[tamp].func != NULL) { ++ ext_list[tamp].func(ext_id); + } + + mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, @@ -20248,8 +17692,9 @@ index 0000000..0bfa177 + /* Reset Tamp register without modifying backup registers conf */ + stm32_tamp_reset_register(stm32_tamp.base); + -+ /* Check if tamper are secured */ -+ if (dt_tamp.status != DT_SECURE) { ++ /* Check if TAMP is enabled */ ++ if ((dt_tamp.status != DT_SECURE) && ++ (dt_tamp.status != DT_SHARED)) { + return 0; + } + @@ -20271,7 +17716,7 @@ index 0000000..0bfa177 + stm32_tamp_configure_or(stm32_tamp.base, 1); + } + -+ if (stm32_gic_enable_spi(node, NULL) != 0) { ++ if (stm32_gic_enable_spi(node, NULL) < 0) { + panic(); + } + @@ -20284,25 +17729,27 @@ index 0000000..0bfa177 +} diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c new file mode 100644 -index 0000000..6d36e31 +index 000000000..a4e178ec4 --- /dev/null +++ b/drivers/st/timer/stm32_timer.c -@@ -0,0 +1,297 @@ +@@ -0,0 +1,316 @@ +/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2018-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 + +#define TIM_CR1 0x00U /* Control Register 1 */ +#define TIM_CR2 0x04U /* Control Register 2 */ @@ -20349,6 +17796,7 @@ index 0000000..6d36e31 +#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; @@ -20374,12 +17822,18 @@ index 0000000..6d36e31 + 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, @@ -20400,6 +17854,8 @@ index 0000000..6d36e31 + } + + stm32mp_clk_disable(timer->clk); ++ ++ return 0; +} + +static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer) @@ -20409,7 +17865,9 @@ index 0000000..6d36e31 + 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); + @@ -20558,10 +18016,13 @@ index 0000000..6d36e31 + 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]; @@ -20571,7 +18032,10 @@ index 0000000..6d36e31 + 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; ++ } + } + } + } @@ -20586,108 +18050,14 @@ index 0000000..6d36e31 + return 0; +} diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S -index 792703a..823e38b 100644 +index ca3c1f618..0fabcc82e 100644 --- a/drivers/st/uart/aarch32/stm32_console.S +++ b/drivers/st/uart/aarch32/stm32_console.S -@@ -4,30 +4,27 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - #include -+#include -+#define USE_FINISH_CONSOLE_REG_2 -+#include -+#include -+#include - - #define USART_TIMEOUT 0x1000 - --#define USART_CR1 0x00 --#define USART_CR1_UE 0x00000001 --#define USART_CR1_TE 0x00000008 --#define USART_CR1_FIFOEN 0x20000000 -- --#define USART_CR2 0x04 --#define USART_CR2_STOP 0x00003000 -- --#define USART_BRR 0x0C -+ /* -+ * "core" functions are low-level implementations that don't require -+ * writeable memory and are thus safe to call in BL1 crash context. -+ */ -+ .globl console_stm32_core_init -+ .globl console_stm32_core_putc -+ .globl console_stm32_core_getc -+ .globl console_stm32_core_flush - --#define USART_ISR 0x1C --#define USART_ISR_TC 0x00000040 --#define USART_ISR_TXE 0x00000080 --#define USART_ISR_TEACK 0x00200000 -+ .globl console_stm32_putc -+ .globl console_stm32_flush - --#define USART_TDR 0x28 - -- .globl console_core_init -- .globl console_core_putc -- .globl console_core_getc -- .globl console_core_flush - - /* ----------------------------------------------------------------- - * int console_core_init(uintptr_t base_addr, -@@ -45,7 +42,7 @@ - * Clobber list : r1, r2, r3 - * ----------------------------------------------------------------- - */ --func console_core_init -+func console_stm32_core_init - /* Check the input base address */ - cmp r0, #0 - beq core_init_fail -@@ -88,21 +85,55 @@ teack_loop: - core_init_fail: - mov r0, #0 - bx lr --endfunc console_core_init -+endfunc console_stm32_core_init +@@ -122,17 +122,15 @@ register_fail: + pop {r4, pc} + endfunc console_stm32_register - /* --------------------------------------------------------------- -+ .globl console_stm32_register -+ -+ /* ------------------------------------------------------- -+ * int console_stm32_register(uintptr_t baseaddr, -+ * uint32_t clock, uint32_t baud, -+ * struct console_stm32 *console); -+ * Function to initialize and register a new STM32 -+ * console. Storage passed in for the console struct -+ * *must* be persistent (i.e. not from the stack). -+ * In: r0 - UART register base address -+ * r1 - UART clock in Hz -+ * r2 - Baud rate -+ * r3 - pointer to empty console_stm32 struct -+ * Out: return 1 on success, 0 on error -+ * Clobber list : r0, r1, r2 -+ * ------------------------------------------------------- -+ */ -+func console_stm32_register -+ push {r4, lr} -+ mov r4, r3 -+ cmp r4, #0 -+ beq register_fail -+ str r0, [r4, #CONSOLE_T_STM32_BASE] -+ -+ bl console_stm32_core_init -+ cmp r0, #0 -+ beq register_fail -+ -+ mov r0, r4 -+ pop {r4, lr} -+ finish_console_register stm32 putc=1, getc=0, flush=1 -+ -+register_fail: -+ pop {r4, pc} -+endfunc console_stm32_register -+ + /* -------------------------------------------------------- * int console_core_putc(int c, uintptr_t base_addr) - * @@ -20704,93 +18074,29 @@ index 792703a..823e38b 100644 + * Clobber list : r2, r3 + * -------------------------------------------------------- */ --func console_core_putc -+func console_stm32_core_putc + func console_stm32_core_putc /* Check the input parameter */ - cmp r1, #0 +@@ -140,13 +138,19 @@ func console_stm32_core_putc beq putc_error -@@ -111,26 +142,38 @@ func console_core_putc - bne 2f - 1: + /* Check Transmit Data Register Empty */ + mov r3, #USART_TIMEOUT - txe_loop_1: + txe_loop: + subs r3, r3, #1 + beq putc_error ldr r2, [r1, #USART_ISR] tst r2, #USART_ISR_TXE - beq txe_loop_1 - mov r2, #0xD - str r2, [r1, #USART_TDR] - /* Check transmit complete flag */ -+ mov r3, #USART_TIMEOUT - tc_loop_1: -+ subs r3, r3, #1 -+ beq putc_error - ldr r2, [r1, #USART_ISR] - tst r2, #USART_ISR_TC - beq tc_loop_1 - 2: - /* Check Transmit Data Register Empty */ -+ mov r3, #USART_TIMEOUT - txe_loop_2: -+ subs r3, r3, #1 -+ beq putc_error - ldr r2, [r1, #USART_ISR] - tst r2, #USART_ISR_TXE - beq txe_loop_2 + beq txe_loop str r0, [r1, #USART_TDR] /* Check transmit complete flag */ + mov r3, #USART_TIMEOUT - tc_loop_2: + tc_loop: + subs r3, r3, #1 + beq putc_error ldr r2, [r1, #USART_ISR] tst r2, #USART_ISR_TC - beq tc_loop_2 -@@ -138,7 +181,26 @@ tc_loop_2: - putc_error: - mov r0, #-1 - bx lr --endfunc console_core_putc -+endfunc console_stm32_core_putc -+ -+ /* ------------------------------------------------------------ -+ * int console_stm32_putc(int c, struct console_stm32 *console) -+ * Function to output a character over the console. It -+ * returns the character printed on success or -1 on error. -+ * In: r0 - character to be printed -+ * r1 - pointer to console_t structure -+ * Out : return -1 on error else return character. -+ * Clobber list: r2 -+ * ------------------------------------------------------------ -+ */ -+func console_stm32_putc -+#if ENABLE_ASSERTIONS -+ cmp r1, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r1, [r1, #CONSOLE_T_STM32_BASE] -+ b console_stm32_core_putc -+endfunc console_stm32_putc - - /* ----------------------------------------------------------- - * int console_core_getc(uintptr_t base_addr) -@@ -151,11 +213,11 @@ endfunc console_core_putc - * Clobber list : r0, r1 - * ----------------------------------------------------------- - */ --func console_core_getc -+func console_stm32_core_getc - /* Not supported */ - mov r0, #-1 - bx lr --endfunc console_core_getc -+endfunc console_stm32_core_getc - - /* --------------------------------------------------------------- - * int console_core_flush(uintptr_t base_addr) -@@ -165,14 +227,17 @@ endfunc console_core_getc + beq tc_loop +@@ -200,14 +204,17 @@ endfunc console_stm32_core_getc * * In : r0 - console base address * Out : return -1 on error else return 0. @@ -20798,8 +18104,7 @@ index 792703a..823e38b 100644 + * Clobber list : r0, r1, r2 * --------------------------------------------------------------- */ --func console_core_flush -+func console_stm32_core_flush + func console_stm32_core_flush cmp r0, #0 beq flush_error /* Check Transmit Data Register Empty */ @@ -20810,58 +18115,33 @@ index 792703a..823e38b 100644 ldr r1, [r0, #USART_ISR] tst r1, #USART_ISR_TXE beq txe_loop_3 -@@ -181,4 +246,22 @@ txe_loop_3: - flush_error: - mov r0, #-1 - bx lr --endfunc console_core_flush -+endfunc console_stm32_core_flush -+ -+ /* ------------------------------------------------------ -+ * int console_stm32_flush(struct console_stm32 *console) -+ * Function to force a write of all buffered -+ * data that hasn't been output. -+ * In : r0 - pointer to console_t structure -+ * Out : return -1 on error else return 0. -+ * Clobber list: r0, r1 -+ * ------------------------------------------------------ -+ */ -+func console_stm32_flush -+#if ENABLE_ASSERTIONS -+ cmp r0, #0 -+ ASM_ASSERT(ne) -+#endif /* ENABLE_ASSERTIONS */ -+ ldr r0, [r0, #CONSOLE_T_STM32_BASE] -+ b console_stm32_core_flush -+endfunc console_stm32_flush diff --git a/drivers/st/uart/io_programmer_uart.c b/drivers/st/uart/io_programmer_uart.c new file mode 100644 -index 0000000..34a7cbb +index 000000000..6d024e158 --- /dev/null +++ b/drivers/st/uart/io_programmer_uart.c -@@ -0,0 +1,597 @@ +@@ -0,0 +1,587 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, 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 ++#include ++#include ++ +/* USART bootloader protocol version V4.0*/ +#define USART_BL_VERSION 0x40 + @@ -21206,7 +18486,7 @@ index 0000000..34a7cbb + for (i = packet_size; i >= 0; i--) { + /* Reload watchdog, once every 8 loops */ + if (i % 8) -+ stm32_iwdg_refresh(IWDG2_INST); ++ stm32_iwdg_refresh(); + + if (uart_read_byte(&byte)) + return -EIO; @@ -21259,7 +18539,7 @@ index 0000000..34a7cbb + + switch (current_phase.phase_id) { + case PHASE_FLASHLAYOUT: -+ result = check_header(header, buffer + ++ result = stm32mp_check_header(header, buffer + + sizeof(boot_api_image_header_t)); + if (result) + return result; @@ -21271,19 +18551,7 @@ index 0000000..34a7cbb + start_address, BL33_BASE); + } + -+ result = check_header(header, buffer); -+ if (result) -+ return result; -+ -+#ifdef AUTHENTICATE_BL33 -+ result = check_authentication(header, buffer); -+ if (result != 0) { -+ return result; -+ } -+#else -+ NOTICE("Authentication disabled: No signature check\n"); -+#endif -+ break; ++ return stm32mp_check_header(header, buffer); + + default: + ERROR("Invalid phase ID : %i\n", current_phase.phase_id); @@ -21312,6 +18580,9 @@ index 0000000..34a7cbb + } else if (header_length_read && + ((header_length_read - + sizeof(boot_api_image_header_t)) > 0)) { ++#if TRUSTED_BOARD_BOOT ++ stm32mp_save_loaded_header(header_buffer); ++#endif + memcpy((uint8_t *)buffer, + (uint8_t *) + &header_buffer[sizeof(boot_api_image_header_t)], @@ -21325,7 +18596,7 @@ index 0000000..34a7cbb + int result; + + /* Reload watchdog */ -+ stm32_iwdg_refresh(IWDG2_INST); ++ stm32_iwdg_refresh(); + + result = uart_receive_command(&command); + if (result) { @@ -21439,10 +18710,10 @@ index 0000000..34a7cbb +} diff --git a/drivers/st/uart/stm32mp1xx_hal_uart.c b/drivers/st/uart/stm32mp1xx_hal_uart.c new file mode 100644 -index 0000000..c8e5860 +index 000000000..70ccc378e --- /dev/null +++ b/drivers/st/uart/stm32mp1xx_hal_uart.c -@@ -0,0 +1,799 @@ +@@ -0,0 +1,801 @@ +/** + ****************************************************************************** + * @file stm32mp1xx_hal_uart.c @@ -21526,12 +18797,14 @@ index 0000000..c8e5860 + +/* Includes ------------------------------------------------------------------*/ +#include -+#include -+#include -+#include -+#include +#include + ++#include ++ ++#include ++#include ++#include ++ +/** @addtogroup STM32MP1xx_HAL_Driver + * @{ + */ @@ -22244,20 +19517,21 @@ index 0000000..c8e5860 +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/drivers/st/usb_dwc2/usb_dwc2.c b/drivers/st/usb_dwc2/usb_dwc2.c new file mode 100644 -index 0000000..a920553 +index 000000000..fc0b8625e --- /dev/null +++ b/drivers/st/usb_dwc2/usb_dwc2.c -@@ -0,0 +1,858 @@ +@@ -0,0 +1,859 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#include -+#include +#include -+#include ++ ++#include ++#include ++#include + +static usb_dwc2_t dwc2_handle; + @@ -23106,99 +20380,90 @@ index 0000000..a920553 + register_usb_driver(usb_core_handle, &usb_dwc2driver, + (void *)&dwc2_handle); +} -diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S -index d46fa61..34cce95 100644 ---- a/drivers/ti/uart/aarch64/16550_console.S -+++ b/drivers/ti/uart/aarch64/16550_console.S -@@ -7,6 +7,7 @@ - #include - #include - #include -+#define USE_FINISH_CONSOLE_REG_2 - #include - #include - -@@ -111,7 +112,7 @@ func console_16550_register - - mov x0, x6 - mov x30, x7 -- finish_console_register 16550 -+ finish_console_register 16550 putc=1, getc=1, flush=1 - - register_fail: - ret x7 diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi -index be4e2c3..1a5c51c 100644 +index 4825691f9..f0657ad12 100644 --- a/fdts/stm32mp15-ddr.dtsi +++ b/fdts/stm32mp15-ddr.dtsi -@@ -5,7 +5,7 @@ +@@ -132,6 +132,7 @@ + DDR_MR3 + >; - / { - soc { -- ddr: ddr@0x5A003000{ -+ ddr: ddr@5A003000{ - - compatible = "st,stm32mp1-ddr"; ++#ifdef DDR_PHY_CAL_SKIP + st,phy-cal = < + DDR_DX0DLLCR + DDR_DX0DQTR +@@ -146,6 +147,7 @@ + DDR_DX3DQTR + DDR_DX3DQSTR + >; ++#endif + status = "okay"; + }; diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -new file mode 100644 -index 0000000..16b8cf6 ---- /dev/null +index 11e8f2bef..c0fc1f772 100644 +--- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -@@ -0,0 +1,121 @@ -+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +@@ -1,24 +1,23 @@ + // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + /* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved ++ */ ++ +/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ */ -+/* STM32MP157C DK1/DK2 BOARD configuration -+ * 1x DDR3L 4Gb, 16-bit, 533MHz. -+ * Reference used NT5CC256M16DP-DI from NANYA -+ * -+ * DDR type / Platform DDR3/3L -+ * freq 533MHz -+ * width 16 -+ * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G -+ * DDR density 4 -+ * timing mode optimized -+ * Scheduling/QoS options : type = 2 -+ * address mapping : RBC -+ * Tc > + 85C : N -+ */ ++ * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs ++ * DDR type: DDR3 / DDR3L ++ * DDR width: 16bits ++ * DDR density: 4Gb ++ * System frequency: 533000Khz ++ * Relaxed Timing Mode: false ++ * Address mapping type: RBC + * +- * STM32MP157C DK1/DK2 BOARD configuration +- * 1x DDR3L 4Gb, 16-bit, 533MHz. +- * Reference used NT5CC256M16DP-DI from NANYA +- * +- * DDR type / Platform DDR3/3L +- * freq 533MHz +- * width 16 +- * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G +- * DDR density 4 +- * timing mode optimized +- * Scheduling/QoS options : type = 2 +- * address mapping : RBC +- * Tc > + 85C : N ++ * Save Date: 2020.02.20, save Time: 18:45:20 + */ +-#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45" +-#define DDR_MEM_SPEED 533000 +-#define DDR_MEM_SIZE 0x20000000 + -+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41" -+#define DDR_MEM_SPEED 533000 -+#define DDR_MEM_SIZE 0x20000000 -+ -+#define DDR_MSTR 0x00041401 -+#define DDR_MRCTRL0 0x00000010 -+#define DDR_MRCTRL1 0x00000000 -+#define DDR_DERATEEN 0x00000000 -+#define DDR_DERATEINT 0x00800000 -+#define DDR_PWRCTL 0x00000000 -+#define DDR_PWRTMG 0x00400010 -+#define DDR_HWLPCTL 0x00000000 -+#define DDR_RFSHCTL0 0x00210000 -+#define DDR_RFSHCTL3 0x00000000 -+#define DDR_RFSHTMG 0x0081008B -+#define DDR_CRCPARCTL0 0x00000000 -+#define DDR_DRAMTMG0 0x121B2414 -+#define DDR_DRAMTMG1 0x000A041C -+#define DDR_DRAMTMG2 0x0608090F -+#define DDR_DRAMTMG3 0x0050400C -+#define DDR_DRAMTMG4 0x08040608 -+#define DDR_DRAMTMG5 0x06060403 -+#define DDR_DRAMTMG6 0x02020002 -+#define DDR_DRAMTMG7 0x00000202 -+#define DDR_DRAMTMG8 0x00001005 -+#define DDR_DRAMTMG14 0x000000A0 -+#define DDR_ZQCTL0 0xC2000040 -+#define DDR_DFITMG0 0x02060105 -+#define DDR_DFITMG1 0x00000202 -+#define DDR_DFILPCFG0 0x07000000 -+#define DDR_DFIUPD0 0xC0400003 -+#define DDR_DFIUPD1 0x00000000 -+#define DDR_DFIUPD2 0x00000000 -+#define DDR_DFIPHYMSTR 0x00000000 ++#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000Khz" ++#define DDR_MEM_SPEED 533000 ++#define DDR_MEM_SIZE 0x20000000 + + #define DDR_MSTR 0x00041401 + #define DDR_MRCTRL0 0x00000010 +@@ -50,15 +49,6 @@ + #define DDR_DFIUPD1 0x00000000 + #define DDR_DFIUPD2 0x00000000 + #define DDR_DFIPHYMSTR 0x00000000 +-#define DDR_ADDRMAP1 0x00070707 +-#define DDR_ADDRMAP2 0x00000000 +-#define DDR_ADDRMAP3 0x1F000000 +-#define DDR_ADDRMAP4 0x00001F1F +-#define DDR_ADDRMAP5 0x06060606 +-#define DDR_ADDRMAP6 0x0F060606 +-#define DDR_ADDRMAP9 0x00000000 +-#define DDR_ADDRMAP10 0x00000000 +-#define DDR_ADDRMAP11 0x00000000 + #define DDR_ODTCFG 0x06000600 + #define DDR_ODTMAP 0x00000001 + #define DDR_SCHED 0x00000C01 +@@ -83,6 +73,15 @@ + #define DDR_PCFGQOS1_1 0x00800040 + #define DDR_PCFGWQOS0_1 0x01100C03 + #define DDR_PCFGWQOS1_1 0x01000200 +#define DDR_ADDRMAP1 0x00070707 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x1F000000 @@ -23208,387 +20473,3361 @@ index 0000000..16b8cf6 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 -+#define DDR_ODTCFG 0x06000600 -+#define DDR_ODTMAP 0x00000001 -+#define DDR_SCHED 0x00000C01 -+#define DDR_SCHED1 0x00000000 -+#define DDR_PERFHPR1 0x01000001 -+#define DDR_PERFLPR1 0x08000200 -+#define DDR_PERFWR1 0x08000400 -+#define DDR_DBG0 0x00000000 -+#define DDR_DBG1 0x00000000 -+#define DDR_DBGCMD 0x00000000 -+#define DDR_POISONCFG 0x00000000 -+#define DDR_PCCFG 0x00000010 -+#define DDR_PCFGR_0 0x00010000 -+#define DDR_PCFGW_0 0x00000000 -+#define DDR_PCFGQOS0_0 0x02100C03 -+#define DDR_PCFGQOS1_0 0x00800100 -+#define DDR_PCFGWQOS0_0 0x01100C03 -+#define DDR_PCFGWQOS1_0 0x01000200 -+#define DDR_PCFGR_1 0x00010000 -+#define DDR_PCFGW_1 0x00000000 -+#define DDR_PCFGQOS0_1 0x02100C03 -+#define DDR_PCFGQOS1_1 0x00800040 -+#define DDR_PCFGWQOS0_1 0x01100C03 -+#define DDR_PCFGWQOS1_1 0x01000200 -+#define DDR_PGCR 0x01442E02 -+#define DDR_PTR0 0x0022AA5B -+#define DDR_PTR1 0x04841104 -+#define DDR_PTR2 0x042DA068 -+#define DDR_ACIOCR 0x10400812 -+#define DDR_DXCCR 0x00000C40 -+#define DDR_DSGCR 0xF200001F -+#define DDR_DCR 0x0000000B -+#define DDR_DTPR0 0x38D488D0 -+#define DDR_DTPR1 0x098B00D8 -+#define DDR_DTPR2 0x10023600 -+#define DDR_MR0 0x00000840 -+#define DDR_MR1 0x00000000 -+#define DDR_MR2 0x00000208 -+#define DDR_MR3 0x00000000 -+#define DDR_ODTCR 0x00010000 -+#define DDR_ZQ0CR1 0x00000038 -+#define DDR_DX0GCR 0x0000CE81 -+#define DDR_DX0DLLCR 0x40000000 -+#define DDR_DX0DQTR 0xFFFFFFFF -+#define DDR_DX0DQSTR 0x3DB02000 -+#define DDR_DX1GCR 0x0000CE81 -+#define DDR_DX1DLLCR 0x40000000 -+#define DDR_DX1DQTR 0xFFFFFFFF -+#define DDR_DX1DQSTR 0x3DB02000 -+#define DDR_DX2GCR 0x0000CE81 -+#define DDR_DX2DLLCR 0x40000000 -+#define DDR_DX2DQTR 0xFFFFFFFF -+#define DDR_DX2DQSTR 0x3DB02000 -+#define DDR_DX3GCR 0x0000CE81 -+#define DDR_DX3DLLCR 0x40000000 -+#define DDR_DX3DQTR 0xFFFFFFFF -+#define DDR_DX3DQSTR 0x3DB02000 -+ -+#include "stm32mp15-ddr.dtsi" -diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -index 58a4cdc..82e7104 100644 ---- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -@@ -3,7 +3,7 @@ - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - */ - --/* STM32MP157C ED1 and ED2 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 - * -@@ -15,10 +15,11 @@ - * timing mode optimized - * Scheduling/QoS options : type = 2 - * address mapping : RBC -+ * Tc > + 85C : N - */ - --#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.39" --#define DDR_MEM_SPEED 533 -+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41" -+#define DDR_MEM_SPEED 533000 - #define DDR_MEM_SIZE 0x40000000 - - #define DDR_MSTR 0x00040401 -@@ -62,7 +63,7 @@ - #define DDR_ADDRMAP11 0x00000000 - #define DDR_ODTCFG 0x06000600 - #define DDR_ODTMAP 0x00000001 --#define DDR_SCHED 0x00001201 -+#define DDR_SCHED 0x00000C01 - #define DDR_SCHED1 0x00000000 - #define DDR_PERFHPR1 0x01000001 - #define DDR_PERFLPR1 0x08000200 -@@ -74,15 +75,15 @@ - #define DDR_PCCFG 0x00000010 - #define DDR_PCFGR_0 0x00010000 - #define DDR_PCFGW_0 0x00000000 --#define DDR_PCFGQOS0_0 0x02100B03 -+#define DDR_PCFGQOS0_0 0x02100C03 - #define DDR_PCFGQOS1_0 0x00800100 --#define DDR_PCFGWQOS0_0 0x01100B03 -+#define DDR_PCFGWQOS0_0 0x01100C03 - #define DDR_PCFGWQOS1_0 0x01000200 - #define DDR_PCFGR_1 0x00010000 - #define DDR_PCFGW_1 0x00000000 --#define DDR_PCFGQOS0_1 0x02100B03 --#define DDR_PCFGQOS1_1 0x00800000 --#define DDR_PCFGWQOS0_1 0x01100B03 -+#define DDR_PCFGQOS0_1 0x02100C03 -+#define DDR_PCFGQOS1_1 0x00800040 -+#define DDR_PCFGWQOS0_1 0x01100C03 - #define DDR_PCFGWQOS1_1 0x01000200 #define DDR_PGCR 0x01442E02 #define DDR_PTR0 0x0022AA5B -diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi -index 21bd34e..8037e4f 100644 ---- a/fdts/stm32mp157-pinctrl.dtsi -+++ b/fdts/stm32mp157-pinctrl.dtsi -@@ -3,13 +3,14 @@ - * Copyright (C) STMicroelectronics 2017 - All Rights Reserved - * Author: Ludovic Barre for STMicroelectronics. - */ -- - #include + #define DDR_PTR1 0x04841104 +diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +index 4b70b6055..fc226d254 100644 +--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi ++++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +@@ -1,24 +1,23 @@ + // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + /* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved ++ */ + - / { - soc { -- pinctrl: pin-controller { ++/* ++ * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs ++ * DDR type: DDR3 / DDR3L ++ * DDR width: 32bits ++ * DDR density: 8Gb ++ * System frequency: 533000Khz ++ * Relaxed Timing Mode: false ++ * Address mapping type: RBC + * +- * STM32MP157C ED1 BOARD configuration +- * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. +- * Reference used NT5CC256M16DP-DI from NANYA +- * +- * DDR type / Platform DDR3/3L +- * freq 533MHz +- * width 32 +- * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G +- * DDR density 8 +- * timing mode optimized +- * Scheduling/QoS options : type = 2 +- * address mapping : RBC +- * Tc > + 85C : N ++ * Save Date: 2020.02.20, save Time: 18:49:33 + */ +-#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45" +-#define DDR_MEM_SPEED 533000 +-#define DDR_MEM_SIZE 0x40000000 ++ ++#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000Khz" ++#define DDR_MEM_SPEED 533000 ++#define DDR_MEM_SIZE 0x40000000 + + #define DDR_MSTR 0x00040401 + #define DDR_MRCTRL0 0x00000010 +@@ -50,15 +49,6 @@ + #define DDR_DFIUPD1 0x00000000 + #define DDR_DFIUPD2 0x00000000 + #define DDR_DFIPHYMSTR 0x00000000 +-#define DDR_ADDRMAP1 0x00080808 +-#define DDR_ADDRMAP2 0x00000000 +-#define DDR_ADDRMAP3 0x00000000 +-#define DDR_ADDRMAP4 0x00001F1F +-#define DDR_ADDRMAP5 0x07070707 +-#define DDR_ADDRMAP6 0x0F070707 +-#define DDR_ADDRMAP9 0x00000000 +-#define DDR_ADDRMAP10 0x00000000 +-#define DDR_ADDRMAP11 0x00000000 + #define DDR_ODTCFG 0x06000600 + #define DDR_ODTMAP 0x00000001 + #define DDR_SCHED 0x00000C01 +@@ -83,6 +73,15 @@ + #define DDR_PCFGQOS1_1 0x00800040 + #define DDR_PCFGWQOS0_1 0x01100C03 + #define DDR_PCFGWQOS1_1 0x01000200 ++#define DDR_ADDRMAP1 0x00080808 ++#define DDR_ADDRMAP2 0x00000000 ++#define DDR_ADDRMAP3 0x00000000 ++#define DDR_ADDRMAP4 0x00001F1F ++#define DDR_ADDRMAP5 0x07070707 ++#define DDR_ADDRMAP6 0x0F070707 ++#define DDR_ADDRMAP9 0x00000000 ++#define DDR_ADDRMAP10 0x00000000 ++#define DDR_ADDRMAP11 0x00000000 + #define DDR_PGCR 0x01442E02 + #define DDR_PTR0 0x0022AA5B + #define DDR_PTR1 0x04841104 +diff --git a/fdts/stm32mp15-pinctrl.dtsi b/fdts/stm32mp15-pinctrl.dtsi +new file mode 100644 +index 000000000..d3d1744ec +--- /dev/null ++++ b/fdts/stm32mp15-pinctrl.dtsi +@@ -0,0 +1,292 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ ++#include ++ ++&pinctrl { ++ fmc_pins_a: fmc-0 { ++ pins1 { ++ pinmux = , /* FMC_NOE */ ++ , /* FMC_NWE */ ++ , /* FMC_A16_FMC_CLE */ ++ , /* FMC_A17_FMC_ALE */ ++ , /* FMC_D0 */ ++ , /* FMC_D1 */ ++ , /* FMC_D2 */ ++ , /* FMC_D3 */ ++ , /* FMC_D4 */ ++ , /* FMC_D5 */ ++ , /* FMC_D6 */ ++ , /* FMC_D7 */ ++ ; /* FMC_NE2_FMC_NCE */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ pins2 { ++ pinmux = ; /* FMC_NWAIT */ ++ bias-pull-up; ++ }; ++ }; ++ ++ qspi_clk_pins_a: qspi-clk-0 { ++ pins { ++ pinmux = ; /* QSPI_CLK */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <3>; ++ }; ++ }; ++ ++ qspi_bk1_pins_a: qspi-bk1-0 { ++ pins1 { ++ pinmux = , /* QSPI_BK1_IO0 */ ++ , /* QSPI_BK1_IO1 */ ++ , /* QSPI_BK1_IO2 */ ++ ; /* QSPI_BK1_IO3 */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ pins2 { ++ pinmux = ; /* QSPI_BK1_NCS */ ++ bias-pull-up; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ qspi_bk2_pins_a: qspi-bk2-0 { ++ pins1 { ++ pinmux = , /* QSPI_BK2_IO0 */ ++ , /* QSPI_BK2_IO1 */ ++ , /* QSPI_BK2_IO2 */ ++ ; /* QSPI_BK2_IO3 */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ pins2 { ++ pinmux = ; /* QSPI_BK2_NCS */ ++ bias-pull-up; ++ drive-push-pull; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 { ++ pins { ++ pinmux = ; /* RTC_OUT2_RMP */ ++ }; ++ }; ++ ++ sdmmc1_b4_pins_a: sdmmc1-b4-0 { ++ pins1 { ++ pinmux = , /* SDMMC1_D0 */ ++ , /* SDMMC1_D1 */ ++ , /* SDMMC1_D2 */ ++ , /* SDMMC1_D3 */ ++ ; /* SDMMC1_CMD */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ pins2 { ++ pinmux = ; /* SDMMC1_CK */ ++ slew-rate = <2>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ }; ++ ++ sdmmc1_dir_pins_a: sdmmc1-dir-0 { ++ pins1 { ++ pinmux = , /* SDMMC1_D0DIR */ ++ , /* SDMMC1_D123DIR */ ++ ; /* SDMMC1_CDIR */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-pull-up; ++ }; ++ pins2{ ++ pinmux = ; /* SDMMC1_CKIN */ ++ bias-pull-up; ++ }; ++ }; ++ ++ sdmmc2_b4_pins_a: sdmmc2-b4-0 { ++ pins1 { ++ pinmux = , /* SDMMC2_D0 */ ++ , /* SDMMC2_D1 */ ++ , /* SDMMC2_D2 */ ++ , /* SDMMC2_D3 */ ++ ; /* SDMMC2_CMD */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-pull-up; ++ }; ++ pins2 { ++ pinmux = ; /* SDMMC2_CK */ ++ slew-rate = <2>; ++ drive-push-pull; ++ bias-pull-up; ++ }; ++ }; ++ ++ sdmmc2_b4_pins_b: sdmmc2-b4-1 { ++ pins1 { ++ pinmux = , /* SDMMC2_D0 */ ++ , /* SDMMC2_D1 */ ++ , /* SDMMC2_D2 */ ++ , /* SDMMC2_D3 */ ++ ; /* SDMMC2_CMD */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ pins2 { ++ pinmux = ; /* SDMMC2_CK */ ++ slew-rate = <2>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ }; ++ ++ sdmmc2_d47_pins_a: sdmmc2-d47-0 { ++ pins { ++ pinmux = , /* SDMMC2_D4 */ ++ , /* SDMMC2_D5 */ ++ , /* SDMMC2_D6 */ ++ ; /* SDMMC2_D7 */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-pull-up; ++ }; ++ }; ++ ++ uart4_pins_a: uart4-0 { ++ pins1 { ++ pinmux = ; /* UART4_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = ; /* UART4_RX */ ++ bias-disable; ++ }; ++ }; ++ ++ uart4_pins_b: uart4-1 { ++ pins1 { ++ pinmux = ; /* UART4_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = ; /* UART4_RX */ ++ bias-disable; ++ }; ++ }; ++ ++ uart7_pins_a: uart7-0 { ++ pins1 { ++ pinmux = ; /* UART4_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = , /* UART4_RX */ ++ , /* UART4_CTS */ ++ ; /* UART4_RTS */ ++ bias-disable; ++ }; ++ }; ++ ++ uart7_pins_b: uart7-1 { ++ pins1 { ++ pinmux = ; /* USART7_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = ; /* USART7_RX */ ++ bias-disable; ++ }; ++ }; ++ ++ usart2_pins_a: usart2-0 { ++ pins1 { ++ pinmux = , /* USART2_TX */ ++ ; /* USART2_RTS */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <3>; ++ }; ++ pins2 { ++ pinmux = , /* USART2_RX */ ++ ; /* USART2_CTS_NSS */ ++ bias-disable; ++ }; ++ }; ++ ++ usart3_pins_a: usart3-0 { ++ pins1 { ++ pinmux = , /* USART3_TX */ ++ ; /* USART3_RTS */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = , /* USART3_RX */ ++ ; /* USART3_CTS_NSS */ ++ bias-disable; ++ }; ++ }; ++ ++ usart3_pins_b: usart3-1 { ++ pins1 { ++ pinmux = , /* USART3_TX */ ++ ; /* USART3_RTS */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = , /* USART3_RX */ ++ ; /* USART3_CTS_NSS */ ++ bias-disable; ++ }; ++ }; ++ ++ usbotg_hs_pins_a: usbotg_hs-0 { ++ pins { ++ pinmux = ; /* OTG_ID */ ++ }; ++ }; ++ ++ usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { ++ pins { ++ pinmux = , /* OTG_FS_DM */ ++ ; /* OTG_FS_DP */ ++ }; ++ }; ++}; ++ ++&pinctrl_z { ++ i2c4_pins_a: i2c4-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ bias-disable; ++ drive-open-drain; ++ slew-rate = <0>; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi +new file mode 100644 +index 000000000..6e6dff4f7 +--- /dev/null ++++ b/fdts/stm32mp151.dtsi +@@ -0,0 +1,683 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ ++#include ++#include ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <0>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ nvmem-cells = <&part_number_otp>; ++ nvmem-cell-names = "part_number"; ++ }; ++ }; ++ ++ cpu0_opp_table: cpu0-opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ }; ++ ++ nvmem_layout: nvmem_layout@0 { ++ compatible = "st,stm32-nvmem-layout"; ++ ++ nvmem-cells = <&cfg0_otp>, ++ <&part_number_otp>, ++ <&monotonic_otp>, ++ <&nand_otp>, ++ <&uid_otp>, ++ <&package_otp>, ++ <&hw2_otp>; ++ ++ nvmem-cell-names = "cfg0_otp", ++ "part_number_otp", ++ "monotonic_otp", ++ "nand_otp", ++ "uid_otp", ++ "package_otp", ++ "hw2_otp"; ++ }; ++ ++ psci { ++ compatible = "arm,psci-1.0"; ++ method = "smc"; ++ }; ++ ++ intc: interrupt-controller@a0021000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0xa0021000 0x1000>, ++ <0xa0022000 0x2000>; ++ }; ++ ++ clocks { ++ clk_hse: clk-hse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ }; ++ ++ clk_hsi: clk-hsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <64000000>; ++ }; ++ ++ clk_lse: clk-lse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ }; ++ ++ clk_lsi: clk-lsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32000>; ++ }; ++ ++ clk_csi: clk-csi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <4000000>; ++ }; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ interrupt-parent = <&intc>; ++ ranges; ++ ++ timers12: timer@40006000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stm32-timers"; ++ reg = <0x40006000 0x400>; ++ clocks = <&rcc TIM12_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ usart2: serial@4000e000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x4000e000 0x400>; ++ interrupts = ; ++ clocks = <&rcc USART2_K>; ++ resets = <&rcc USART2_R>; ++ status = "disabled"; ++ }; ++ ++ usart3: serial@4000f000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x4000f000 0x400>; ++ interrupts = ; ++ clocks = <&rcc USART3_K>; ++ resets = <&rcc USART3_R>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@40010000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x40010000 0x400>; ++ interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rcc UART4_K>; ++ resets = <&rcc UART4_R>; ++ wakeup-source; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@40011000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x40011000 0x400>; ++ interrupts = ; ++ clocks = <&rcc UART5_K>; ++ resets = <&rcc UART5_R>; ++ status = "disabled"; ++ }; ++ ++ uart7: serial@40018000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x40018000 0x400>; ++ interrupts = ; ++ clocks = <&rcc UART7_K>; ++ resets = <&rcc UART7_R>; ++ status = "disabled"; ++ }; ++ ++ uart8: serial@40019000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x40019000 0x400>; ++ interrupts = ; ++ clocks = <&rcc UART8_K>; ++ resets = <&rcc UART8_R>; ++ status = "disabled"; ++ }; ++ ++ usart6: serial@44003000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x44003000 0x400>; ++ interrupts = ; ++ clocks = <&rcc USART6_K>; ++ resets = <&rcc USART6_R>; ++ status = "disabled"; ++ }; ++ ++ timers15: timer@44006000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stm32-timers"; ++ reg = <0x44006000 0x400>; ++ clocks = <&rcc TIM15_K>; ++ clock-names = "int"; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ usbotg_hs: usb-otg@49000000 { ++ compatible = "st,stm32mp1-hsotg", "snps,dwc2"; ++ reg = <0x49000000 0x10000>; ++ clocks = <&rcc USBO_K>; ++ clock-names = "otg"; ++ resets = <&rcc USBO_R>; ++ reset-names = "dwc2"; ++ interrupts = ; ++ g-rx-fifo-size = <512>; ++ g-np-tx-fifo-size = <32>; ++ g-tx-fifo-size = <256 16 16 16 16 16 16 16>; ++ dr_mode = "otg"; ++ usb33d-supply = <&usb33>; ++ status = "disabled"; ++ }; ++ ++ rcc: rcc@50000000 { ++ compatible = "st,stm32mp1-rcc", "syscon"; ++ reg = <0x50000000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ interrupts = ; ++ secure-interrupts = ; ++ secure-interrupt-names = "wakeup"; ++ }; ++ ++ pwr_regulators: pwr@50001000 { ++ compatible = "st,stm32mp1,pwr-reg"; ++ reg = <0x50001000 0x10>; ++ st,tzcr = <&rcc 0x0 0x1>; ++ ++ reg11: reg11 { ++ regulator-name = "reg11"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ }; ++ ++ reg18: reg18 { ++ regulator-name = "reg18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ usb33: usb33 { ++ regulator-name = "usb33"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ }; ++ ++ pwr_mcu: pwr_mcu@50001014 { ++ compatible = "syscon"; ++ reg = <0x50001014 0x4>; ++ }; ++ ++ pwr_irq: pwr@50001020 { ++ compatible = "st,stm32mp1-pwr"; ++ reg = <0x50001020 0x100>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ }; ++ ++ exti: interrupt-controller@5000d000 { ++ compatible = "st,stm32mp1-exti", "syscon"; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x5000d000 0x400>; ++ ++ /* exti_pwr is an extra interrupt controller used for ++ * EXTI 55 to 60. It's mapped on pwr interrupt ++ * controller. ++ */ ++ exti_pwr: exti-pwr { ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&pwr_irq>; ++ st,irq-number = <6>; ++ }; ++ }; ++ ++ syscfg: syscon@50020000 { ++ compatible = "st,stm32mp157-syscfg", "syscon"; ++ reg = <0x50020000 0x400>; ++ clocks = <&rcc SYSCFG>; ++ }; ++ ++ hash1: hash@54002000 { ++ compatible = "st,stm32f756-hash"; ++ reg = <0x54002000 0x400>; ++ interrupts = ; ++ clocks = <&rcc HASH1>; ++ resets = <&rcc HASH1_R>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ rng1: rng@54003000 { ++ compatible = "st,stm32-rng"; ++ reg = <0x54003000 0x400>; ++ clocks = <&rcc RNG1_K>; ++ resets = <&rcc RNG1_R>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ fmc: nand-controller@58002000 { ++ compatible = "st,stm32mp15-fmc2"; ++ reg = <0x58002000 0x1000>, ++ <0x80000000 0x1000>, ++ <0x88010000 0x1000>, ++ <0x88020000 0x1000>, ++ <0x81000000 0x1000>, ++ <0x89010000 0x1000>, ++ <0x89020000 0x1000>; ++ interrupts = ; ++ clocks = <&rcc FMC_K>; ++ resets = <&rcc FMC_R>; ++ status = "disabled"; ++ }; ++ ++ qspi: spi@58003000 { ++ compatible = "st,stm32f469-qspi"; ++ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; ++ reg-names = "qspi", "qspi_mm"; ++ interrupts = ; ++ clocks = <&rcc QSPI_K>; ++ resets = <&rcc QSPI_R>; ++ status = "disabled"; ++ }; ++ ++ sdmmc1: sdmmc@58005000 { ++ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; ++ arm,primecell-periphid = <0x00253180>; ++ reg = <0x58005000 0x1000>, <0x58006000 0x1000>; ++ interrupts = ; ++ interrupt-names = "cmd_irq"; ++ clocks = <&rcc SDMMC1_K>; ++ clock-names = "apb_pclk"; ++ resets = <&rcc SDMMC1_R>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ max-frequency = <120000000>; ++ status = "disabled"; ++ }; ++ ++ sdmmc2: sdmmc@58007000 { ++ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; ++ arm,primecell-periphid = <0x00253180>; ++ reg = <0x58007000 0x1000>, <0x58008000 0x1000>; ++ interrupts = ; ++ interrupt-names = "cmd_irq"; ++ clocks = <&rcc SDMMC2_K>; ++ clock-names = "apb_pclk"; ++ resets = <&rcc SDMMC2_R>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ max-frequency = <120000000>; ++ status = "disabled"; ++ }; ++ ++ iwdg2: watchdog@5a002000 { ++ compatible = "st,stm32mp1-iwdg"; ++ reg = <0x5a002000 0x400>; ++ secure-interrupts = ; ++ clocks = <&rcc IWDG2>, <&rcc CK_LSI>; ++ clock-names = "pclk", "lsi"; ++ status = "disabled"; ++ secure-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>; ++ vdda1v1-supply = <®11>; ++ vdda1v8-supply = <®18>; ++ 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>; ++ interrupts = ; ++ clocks = <&rcc USART1_K>; ++ resets = <&rcc USART1_R>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ spi6: spi@5c001000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stm32h7-spi"; ++ reg = <0x5c001000 0x400>; ++ interrupts = ; ++ clocks = <&rcc SPI6_K>; ++ resets = <&rcc SPI6_R>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ i2c4: i2c@5c002000 { ++ compatible = "st,stm32mp15-i2c"; ++ reg = <0x5c002000 0x400>; ++ interrupt-names = "event", "error"; ++ interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rcc I2C4_K>; ++ resets = <&rcc I2C4_R>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x8>; ++ wakeup-source; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ iwdg1: watchdog@5c003000 { ++ compatible = "st,stm32mp1-iwdg"; ++ reg = <0x5C003000 0x400>; ++ interrupts = ; ++ clocks = <&rcc IWDG1>, <&rcc CK_LSI>; ++ clock-names = "pclk", "lsi"; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ rtc: rtc@5c004000 { ++ compatible = "st,stm32mp1-rtc"; ++ reg = <0x5c004000 0x400>; ++ clocks = <&rcc RTCAPB>, <&rcc RTC>; ++ clock-names = "pclk", "rtc_ck"; ++ interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ bsec: nvmem@5c005000 { ++ compatible = "st,stm32mp15-bsec"; ++ reg = <0x5c005000 0x400>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cfg0_otp: cfg0_otp@0 { ++ reg = <0x0 0x1>; ++ }; ++ part_number_otp: part_number_otp@4 { ++ reg = <0x4 0x1>; ++ }; ++ monotonic_otp: monotonic_otp@10 { ++ reg = <0x10 0x4>; ++ }; ++ nand_otp: nand_otp@24 { ++ reg = <0x24 0x4>; ++ }; ++ uid_otp: uid_otp@34 { ++ reg = <0x34 0xc>; ++ }; ++ package_otp: package_otp@40 { ++ reg = <0x40 0x4>; ++ }; ++ hw2_otp: hw2_otp@48 { ++ reg = <0x48 0x4>; ++ }; ++ ts_cal1: calib@5c { ++ reg = <0x5c 0x2>; ++ }; ++ ts_cal2: calib@5e { ++ reg = <0x5e 0x2>; ++ }; ++ pkh_otp: pkh_otp@60 { ++ reg = <0x60 0x20>; ++ }; ++ mac_addr: mac_addr@e4 { ++ reg = <0xe4 0x8>; ++ st,non-secure-otp; ++ }; ++ }; ++ ++ etzpc: etzpc@5c007000 { ++ compatible = "st,stm32-etzpc"; ++ reg = <0x5C007000 0x400>; ++ clocks = <&rcc TZPC>; ++ status = "disabled"; ++ secure-status = "okay"; ++ }; ++ ++ stgen: stgen@5c008000 { ++ compatible = "st,stm32-stgen"; ++ reg = <0x5C008000 0x1000>; ++ }; ++ ++ i2c6: i2c@5c009000 { ++ compatible = "st,stm32mp15-i2c"; ++ reg = <0x5c009000 0x400>; ++ interrupt-names = "event", "error"; ++ interrupts-extended = <&exti 54 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rcc I2C6_K>; ++ resets = <&rcc I2C6_R>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x20>; ++ wakeup-source; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ tamp: tamp@5c00a000 { ++ compatible = "st,stm32-tamp", "simple-bus", "syscon", "simple-mfd"; ++ reg = <0x5c00a000 0x400>; ++ secure-interrupts = ; ++ clocks = <&rcc RTCAPB>; ++ }; ++ ++ /* ++ * Break node order to solve dependency probe issue between ++ * pinctrl and exti. ++ */ + pinctrl: pin-controller@50002000 { - #address-cells = <1>; - #size-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; - ranges = <0 0x50002000 0xa400>; - pins-are-numbered; - -@@ -134,54 +135,76 @@ - status = "disabled"; - }; - -- uart4_pins_a: uart4@0 { -+ qspi_bk1_pins_a: qspi-bk1-0 { - pins1 { ++ ranges = <0 0x50002000 0xa400>; ++ interrupt-parent = <&exti>; ++ st,syscfg = <&exti 0x60 0xff>; ++ pins-are-numbered; ++ ++ gpioa: gpio@50002000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x0 0x400>; ++ clocks = <&rcc GPIOA>; ++ st,bank-name = "GPIOA"; ++ status = "disabled"; ++ }; ++ ++ gpiob: gpio@50003000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x1000 0x400>; ++ clocks = <&rcc GPIOB>; ++ st,bank-name = "GPIOB"; ++ status = "disabled"; ++ }; ++ ++ gpioc: gpio@50004000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x2000 0x400>; ++ clocks = <&rcc GPIOC>; ++ st,bank-name = "GPIOC"; ++ status = "disabled"; ++ }; ++ ++ gpiod: gpio@50005000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x3000 0x400>; ++ clocks = <&rcc GPIOD>; ++ st,bank-name = "GPIOD"; ++ status = "disabled"; ++ }; ++ ++ gpioe: gpio@50006000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x4000 0x400>; ++ clocks = <&rcc GPIOE>; ++ st,bank-name = "GPIOE"; ++ status = "disabled"; ++ }; ++ ++ gpiof: gpio@50007000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x5000 0x400>; ++ clocks = <&rcc GPIOF>; ++ st,bank-name = "GPIOF"; ++ status = "disabled"; ++ }; ++ ++ gpiog: gpio@50008000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x6000 0x400>; ++ clocks = <&rcc GPIOG>; ++ st,bank-name = "GPIOG"; ++ status = "disabled"; ++ }; ++ ++ gpioh: gpio@50009000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x7000 0x400>; ++ clocks = <&rcc GPIOH>; ++ st,bank-name = "GPIOH"; ++ status = "disabled"; ++ }; ++ ++ gpioi: gpio@5000a000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x8000 0x400>; ++ clocks = <&rcc GPIOI>; ++ st,bank-name = "GPIOI"; ++ status = "disabled"; ++ }; ++ ++ gpioj: gpio@5000b000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x9000 0x400>; ++ clocks = <&rcc GPIOJ>; ++ st,bank-name = "GPIOJ"; ++ status = "disabled"; ++ }; ++ ++ gpiok: gpio@5000c000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0xa000 0x400>; ++ clocks = <&rcc GPIOK>; ++ st,bank-name = "GPIOK"; ++ status = "disabled"; ++ }; ++ }; ++ ++ pinctrl_z: pin-controller-z@54004000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "st,stm32mp157-z-pinctrl"; ++ ranges = <0 0x54004000 0x400>; ++ pins-are-numbered; ++ interrupt-parent = <&exti>; ++ st,syscfg = <&exti 0x60 0xff>; ++ ++ gpioz: gpio@54004000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0 0x400>; ++ clocks = <&rcc GPIOZ>; ++ st,bank-name = "GPIOZ"; ++ st,bank-ioport = <11>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp153.dtsi b/fdts/stm32mp153.dtsi +new file mode 100644 +index 000000000..617380a52 +--- /dev/null ++++ b/fdts/stm32mp153.dtsi +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp151.dtsi" ++ ++/ { ++ cpus { ++ cpu1: cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <1>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi +deleted file mode 100644 +index 8e480b2c1..000000000 +--- a/fdts/stm32mp157-pinctrl.dtsi ++++ /dev/null +@@ -1,348 +0,0 @@ +-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +-/* +- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. +- */ +-#include +- +-/ { +- soc { +- pinctrl: pin-controller@50002000 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "st,stm32mp157-pinctrl"; +- ranges = <0 0x50002000 0xa400>; +- pins-are-numbered; +- +- gpioa: gpio@50002000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x0 0x400>; +- clocks = <&rcc GPIOA>; +- st,bank-name = "GPIOA"; +- status = "disabled"; +- }; +- +- gpiob: gpio@50003000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x1000 0x400>; +- clocks = <&rcc GPIOB>; +- st,bank-name = "GPIOB"; +- status = "disabled"; +- }; +- +- gpioc: gpio@50004000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x2000 0x400>; +- clocks = <&rcc GPIOC>; +- st,bank-name = "GPIOC"; +- status = "disabled"; +- }; +- +- gpiod: gpio@50005000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x3000 0x400>; +- clocks = <&rcc GPIOD>; +- st,bank-name = "GPIOD"; +- status = "disabled"; +- }; +- +- gpioe: gpio@50006000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x4000 0x400>; +- clocks = <&rcc GPIOE>; +- st,bank-name = "GPIOE"; +- status = "disabled"; +- }; +- +- gpiof: gpio@50007000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x5000 0x400>; +- clocks = <&rcc GPIOF>; +- st,bank-name = "GPIOF"; +- status = "disabled"; +- }; +- +- gpiog: gpio@50008000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x6000 0x400>; +- clocks = <&rcc GPIOG>; +- st,bank-name = "GPIOG"; +- status = "disabled"; +- }; +- +- gpioh: gpio@50009000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x7000 0x400>; +- clocks = <&rcc GPIOH>; +- st,bank-name = "GPIOH"; +- status = "disabled"; +- }; +- +- gpioi: gpio@5000a000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x8000 0x400>; +- clocks = <&rcc GPIOI>; +- st,bank-name = "GPIOI"; +- status = "disabled"; +- }; +- +- gpioj: gpio@5000b000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x9000 0x400>; +- clocks = <&rcc GPIOJ>; +- st,bank-name = "GPIOJ"; +- status = "disabled"; +- }; +- +- gpiok: gpio@5000c000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0xa000 0x400>; +- clocks = <&rcc GPIOK>; +- st,bank-name = "GPIOK"; +- status = "disabled"; +- }; +- +- qspi_bk1_pins_a: qspi-bk1-0 { +- pins1 { +- pinmux = , /* QSPI_BK1_IO0 */ +- , /* QSPI_BK1_IO1 */ +- , /* QSPI_BK1_IO2 */ +- ; /* QSPI_BK1_IO3 */ +- bias-disable; +- drive-push-pull; +- slew-rate = <1>; +- }; +- pins2 { +- pinmux = ; /* QSPI_BK1_NCS */ +- bias-pull-up; +- drive-push-pull; +- slew-rate = <1>; +- }; +- }; +- +- qspi_bk2_pins_a: qspi-bk2-0 { +- pins1 { +- pinmux = , /* QSPI_BK2_IO0 */ +- , /* QSPI_BK2_IO1 */ +- , /* QSPI_BK2_IO2 */ +- ; /* QSPI_BK2_IO3 */ +- bias-disable; +- drive-push-pull; +- slew-rate = <1>; +- }; +- pins2 { +- pinmux = ; /* QSPI_BK2_NCS */ +- bias-pull-up; +- drive-push-pull; +- slew-rate = <1>; +- }; +- }; +- +- qspi_clk_pins_a: qspi-clk-0 { +- pins { +- pinmux = ; /* QSPI_CLK */ +- bias-disable; +- drive-push-pull; +- slew-rate = <3>; +- }; +- }; +- +- sdmmc1_b4_pins_a: sdmmc1-b4-0 { +- pins1 { +- pinmux = , /* SDMMC1_D0 */ +- , /* SDMMC1_D1 */ +- , /* SDMMC1_D2 */ +- , /* SDMMC1_D3 */ +- ; /* SDMMC1_CMD */ +- slew-rate = <1>; +- drive-push-pull; +- bias-disable; +- }; +- pins2 { +- pinmux = ; /* SDMMC1_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-disable; +- }; +- }; +- +- sdmmc1_dir_pins_a: sdmmc1-dir-0 { +- pins1 { +- pinmux = , /* SDMMC1_D0DIR */ +- , /* SDMMC1_D123DIR */ +- ; /* SDMMC1_CDIR */ +- slew-rate = <1>; +- drive-push-pull; +- bias-pull-up; +- }; +- pins2{ +- pinmux = ; /* SDMMC1_CKIN */ +- bias-pull-up; +- }; +- }; +- +- sdmmc2_b4_pins_a: sdmmc2-b4-0 { +- pins1 { +- pinmux = , /* SDMMC2_D0 */ +- , /* SDMMC2_D1 */ +- , /* SDMMC2_D2 */ +- , /* SDMMC2_D3 */ +- ; /* SDMMC2_CMD */ +- slew-rate = <1>; +- drive-push-pull; +- bias-pull-up; +- }; +- pins2 { +- pinmux = ; /* SDMMC2_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-pull-up; +- }; +- }; +- +- sdmmc2_d47_pins_a: sdmmc2-d47-0 { +- pins { +- pinmux = , /* SDMMC2_D4 */ +- , /* SDMMC2_D5 */ +- , /* SDMMC2_D6 */ +- ; /* SDMMC2_D7 */ +- slew-rate = <1>; +- drive-push-pull; +- bias-pull-up; +- }; +- }; +- +- uart4_pins_a: uart4-0 { +- pins1 { - pinmux = ; /* UART4_TX */ -+ pinmux = , /* QSPI_BK1_IO0 */ -+ , /* QSPI_BK1_IO1 */ -+ , /* QSPI_BK1_IO2 */ -+ ; /* QSPI_BK1_IO3 */ - bias-disable; - drive-push-pull; +- bias-disable; +- drive-push-pull; - slew-rate = <0>; -+ slew-rate = <1>; - }; - pins2 { +- }; +- pins2 { - pinmux = ; /* UART4_RX */ - bias-disable; -+ pinmux = ; /* QSPI_BK1_NCS */ -+ bias-pull-up; -+ drive-push-pull; -+ slew-rate = <1>; - }; - }; - -- usart3_pins_a: usart3@0 { -+ qspi_bk2_pins_a: qspi-bk2-0 { - pins1 { +- }; +- }; +- +- uart4_pins_b: uart4-1 { +- pins1 { +- pinmux = ; /* UART4_TX */ +- bias-disable; +- drive-push-pull; +- slew-rate = <0>; +- }; +- pins2 { +- pinmux = ; /* UART4_RX */ +- bias-disable; +- }; +- }; +- +- uart7_pins_a: uart7-0 { +- pins1 { +- pinmux = ; /* USART7_TX */ +- bias-disable; +- drive-push-pull; +- slew-rate = <0>; +- }; +- pins2 { +- pinmux = ; /* USART7_RX */ +- bias-disable; +- }; +- }; +- +- usart3_pins_a: usart3-0 { +- pins1 { - pinmux = , /* USART3_TX */ - ; /* USART3_RTS */ -+ pinmux = , /* QSPI_BK2_IO0 */ -+ , /* QSPI_BK2_IO1 */ -+ , /* QSPI_BK2_IO2 */ -+ ; /* QSPI_BK2_IO3 */ - bias-disable; - drive-push-pull; +- bias-disable; +- drive-push-pull; - slew-rate = <0>; -+ slew-rate = <1>; - }; - pins2 { +- }; +- pins2 { - pinmux = , /* USART3_RX */ - ; /* USART3_CTS_NSS */ - bias-disable; -+ pinmux = ; /* QSPI_BK2_NCS */ -+ bias-pull-up; -+ drive-push-pull; -+ slew-rate = <1>; - }; - }; - -- sdmmc1_b4_pins_a: sdmmc1-b4@0 { -+ qspi_clk_pins_a: qspi-clk-0 { - pins { -+ pinmux = ; /* QSPI_CLK */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <3>; -+ }; -+ }; -+ -+ sdmmc1_b4_pins_a: sdmmc1-b4-0 { -+ pins1 { - pinmux = , /* SDMMC1_D0 */ - , /* SDMMC1_D1 */ - , /* SDMMC1_D2 */ - , /* SDMMC1_D3 */ -- , /* SDMMC1_CK */ - ; /* SDMMC1_CMD */ -- slew-rate = <3>; -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC1_CK */ -+ slew-rate = <2>; - drive-push-pull; - bias-disable; - }; - }; - -- sdmmc1_dir_pins_a: sdmmc1-dir@0 { -+ sdmmc1_dir_pins_a: sdmmc1-dir-0 { - pins1 { - pinmux = , /* SDMMC1_D0DIR */ - , /* SDMMC1_D123DIR */ - ; /* SDMMC1_CDIR */ -- slew-rate = <3>; -+ slew-rate = <1>; - drive-push-pull; - bias-pull-up; - }; -@@ -191,36 +214,113 @@ - }; - }; - -- sdmmc2_b4_pins_a: sdmmc2-b4@0 { +- }; +- }; +- +- usart3_pins_b: usart3-1 { +- pins1 { +- pinmux = , /* USART3_TX */ +- ; /* USART3_RTS */ +- bias-disable; +- drive-push-pull; +- slew-rate = <0>; +- }; +- pins2 { +- pinmux = , /* USART3_RX */ +- ; /* USART3_CTS_NSS */ +- bias-disable; +- }; +- }; +- }; +- +- pinctrl_z: pin-controller-z@54004000 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "st,stm32mp157-z-pinctrl"; +- ranges = <0 0x54004000 0x400>; +- pins-are-numbered; +- +- gpioz: gpio@54004000 { +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0 0x400>; +- clocks = <&rcc GPIOZ>; +- st,bank-name = "GPIOZ"; +- st,bank-ioport = <11>; +- status = "disabled"; +- }; +- +- i2c4_pins_a: i2c4-0 { - pins { -+ sdmmc1_dir_pins_b: sdmmc1-dir-1 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0DIR */ -+ , /* SDMMC1_D123DIR */ -+ ; /* SDMMC1_CDIR */ -+ slew-rate = <3>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC1_CKIN */ -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc2_b4_pins_a: sdmmc2-b4-0 { -+ pins1 { - pinmux = , /* SDMMC2_D0 */ - , /* SDMMC2_D1 */ - , /* SDMMC2_D2 */ - , /* SDMMC2_D3 */ -- , /* SDMMC2_CK */ - ; /* SDMMC2_CMD */ -- slew-rate = <3>; -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC2_CK */ -+ slew-rate = <2>; - drive-push-pull; - bias-pull-up; - }; - }; - -- sdmmc2_d47_pins_a: sdmmc2-d47@0 { -+ sdmmc2_d47_pins_a: sdmmc2-d47-0 { - pins { - pinmux = , /* SDMMC2_D4 */ - , /* SDMMC2_D5 */ - , /* SDMMC2_D6 */ - ; /* SDMMC2_D7 */ -- slew-rate = <3>; -+ slew-rate = <1>; - drive-push-pull; - bias-pull-up; - }; - }; -+ -+ uart4_pins_a: uart4-0 { -+ pins1 { -+ pinmux = ; /* UART4_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* UART4_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ uart7_pins_a: uart7-0 { -+ pins1 { -+ pinmux = ; /* USART7_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* USART7_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_pins_a: usart3-0 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ ; /* USART3_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_pins_b: usart3-1 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ ; /* USART3_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ bias-disable; -+ }; -+ }; - }; - -- pinctrl_z: pin-controller-z { -+ pinctrl_z: pin-controller-z@54004000 { - #address-cells = <1>; - #size-cells = <1>; -+ compatible = "st,stm32mp157-z-pinctrl"; - ranges = <0 0x54004000 0x400>; - pins-are-numbered; - -@@ -236,7 +336,7 @@ - status = "disabled"; - }; - -- i2c4_pins_a: i2c4@0 { -+ i2c4_pins_a: i2c4-0 { - pins { - pinmux = , /* I2C4_SCL */ - ; /* I2C4_SDA */ -diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- }; +- }; +-}; +diff --git a/fdts/stm32mp157.dtsi b/fdts/stm32mp157.dtsi new file mode 100644 -index 0000000..fadb442 +index 000000000..c83402907 --- /dev/null -+++ b/fdts/stm32mp157a-dk1.dts -@@ -0,0 +1,464 @@ ++++ b/fdts/stm32mp157.dtsi +@@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* -+ * Copyright (C) STMicroelectronics 2018-2019 - All Rights Reserved -+ * Author: Alexandre Torgue . ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp153.dtsi" +diff --git a/fdts/stm32mp157a-avenger96.dts b/fdts/stm32mp157a-avenger96.dts +index 907940c78..d9b3d1d8f 100644 +--- a/fdts/stm32mp157a-avenger96.dts ++++ b/fdts/stm32mp157a-avenger96.dts +@@ -9,21 +9,49 @@ + + /dts-v1/; + +-#include "stm32mp157c.dtsi" +-#include "stm32mp157cac-pinctrl.dtsi" ++#include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include ++#include ++#include ++#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + + / { + model = "Arrow Electronics STM32MP157A Avenger96 board"; +- compatible = "st,stm32mp157a-avenger96", "st,stm32mp157"; ++ compatible = "arrow,stm32mp157a-avenger96", "st,stm32mp157"; + + aliases { ++ mmc0 = &sdmmc1; + serial0 = &uart4; ++ serial1 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + ++ memory@c0000000 { ++ device_type = "memory"; ++ reg = <0xc0000000 0x40000000>; ++ }; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; + }; + + &i2c4 { +@@ -43,16 +71,17 @@ + + st,main-control-register = <0x04>; + st,vin-control-register = <0xc0>; +- st,usb-control-register = <0x20>; ++ st,usb-control-register = <0x30>; + + regulators { + compatible = "st,stpmic1-regulators"; +- + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; +@@ -61,6 +90,16 @@ + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1200000>; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_ddr: buck2 { +@@ -70,6 +109,17 @@ + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd: buck3 { +@@ -80,6 +130,18 @@ + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; + }; + + v3v3: buck4 { +@@ -89,18 +151,36 @@ + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vtt_ddr: ldo3 { +@@ -109,12 +189,27 @@ + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; ++ lp-stop { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_sd: ldo5 { +@@ -122,18 +217,52 @@ + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; ++ lp-stop { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ }; ++ ++ vbus_otg: pwr_sw1 { ++ regulator-name = "vbus_otg"; ++ }; ++ ++ vbus_sw: pwr_sw2 { ++ regulator-name = "vbus_sw"; ++ regulator-active-discharge = <1>; + }; + }; + }; +@@ -142,56 +271,21 @@ + &iwdg2 { + timeout-sec = <32>; + status = "okay"; ++ secure-status = "okay"; + }; + +-&rng1 { +- status = "okay"; +-}; +- +-&rtc { +- status = "okay"; +-}; +- +-&sdmmc1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; +- broken-cd; +- st,sig-dir; +- st,neg-edge; +- st,use-ckin; +- bus-width = <4>; +- vmmc-supply = <&vdda>; +- status = "okay"; +-}; +- +-&uart4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart4_pins_b>; +- status = "okay"; +-}; +- +-/* ATF Specific */ +-#include +-#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" +-#include "stm32mp157c-security.dtsi" +- +-/ { +- aliases { +- gpio0 = &gpioa; +- gpio1 = &gpiob; +- gpio2 = &gpioc; +- gpio3 = &gpiod; +- gpio4 = &gpioe; +- gpio5 = &gpiof; +- gpio6 = &gpiog; +- gpio7 = &gpioh; +- gpio8 = &gpioi; +- gpio25 = &gpioz; +- i2c3 = &i2c4; +- }; ++&pwr_regulators { ++ 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 = ; ++ vdd-supply = <&vdd>; ++ vdd_3v3_usbfs-supply = <&vdd_usb>; + }; + +-/* CLOCK init */ + &rcc { + secure-status = "disabled"; + st,clksrc = < +@@ -260,24 +354,69 @@ + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { +- cfg = < 2 80 0 0 0 PQR(1,0,0) >; +- frac = < 0x800 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ cfg = <2 80 0 0 0 PQR(1,0,0)>; ++ frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { +- cfg = < 2 65 1 0 0 PQR(1,1,1) >; +- frac = < 0x1400 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ cfg = <2 65 1 0 0 PQR(1,1,1)>; ++ frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { +- cfg = < 1 33 1 16 36 PQR(1,1,1) >; +- frac = < 0x1a04 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ cfg = <1 33 1 16 36 PQR(1,1,1)>; ++ frac = <0x1a04>; + }; + + /* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */ + pll4: st,pll@3 { +- cfg = < 1 39 3 11 4 PQR(1,1,1) >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ cfg = <1 39 3 11 4 PQR(1,1,1)>; + }; + }; ++ ++&rng1 { ++ status = "okay"; ++ secure-status = "okay"; ++}; ++ ++&rtc { ++ status = "okay"; ++ secure-status = "okay"; ++}; ++ ++&sdmmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; ++ st,sig-dir; ++ st,neg-edge; ++ st,use-ckin; ++ bus-width = <4>; ++ vmmc-supply = <&vdd_sd>; ++ status = "okay"; ++}; ++ ++&uart4 { ++ /* On Low speed expansion header */ ++ label = "LS-UART1"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_pins_b>; ++ status = "okay"; ++}; ++ ++&uart7 { ++ /* On Low speed expansion header */ ++ label = "LS-UART0"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart7_pins_a>; ++ status = "okay"; ++}; +diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts +index 4ea83f7cd..4d506bce5 100644 +--- a/fdts/stm32mp157a-dk1.dts ++++ b/fdts/stm32mp157a-dk1.dts +@@ -1,13 +1,17 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2018-2019 - All Rights Reserved +- * Author: Alexandre Torgue . ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + + /dts-v1/; + +-#include "stm32mp157c.dtsi" +-#include "stm32mp157cac-pinctrl.dtsi" ++#include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; +@@ -22,290 +26,20 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; +- +-}; +- +-&clk_hse { +- st,digbypass; +-}; +- +-&i2c4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c4_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +- +- pmic: stpmic@33 { +- compatible = "st,stpmic1"; +- reg = <0x33>; +- interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; +- interrupt-controller; +- #interrupt-cells = <2>; +- status = "okay"; +- +- st,main-control-register = <0x04>; +- st,vin-control-register = <0xc0>; +- st,usb-control-register = <0x20>; +- +- regulators { +- compatible = "st,stpmic1-regulators"; +- +- ldo1-supply = <&v3v3>; +- ldo3-supply = <&vdd_ddr>; +- ldo6-supply = <&v3v3>; +- +- vddcore: buck1 { +- regulator-name = "vddcore"; +- regulator-min-microvolt = <1200000>; +- regulator-max-microvolt = <1350000>; +- regulator-always-on; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- vdd_ddr: buck2 { +- regulator-name = "vdd_ddr"; +- regulator-min-microvolt = <1350000>; +- regulator-max-microvolt = <1350000>; +- regulator-always-on; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- vdd: buck3 { +- regulator-name = "vdd"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- st,mask-reset; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- v3v3: buck4 { +- regulator-name = "v3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- regulator-over-current-protection; +- regulator-initial-mode = <0>; +- }; +- +- v1v8_audio: ldo1 { +- regulator-name = "v1v8_audio"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <1800000>; +- regulator-always-on; +- }; +- +- v3v3_hdmi: ldo2 { +- regulator-name = "v3v3_hdmi"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- }; +- +- vtt_ddr: ldo3 { +- regulator-name = "vtt_ddr"; +- regulator-min-microvolt = <500000>; +- regulator-max-microvolt = <750000>; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- +- vdd_usb: ldo4 { +- regulator-name = "vdd_usb"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- }; +- +- vdda: ldo5 { +- regulator-name = "vdda"; +- regulator-min-microvolt = <2900000>; +- regulator-max-microvolt = <2900000>; +- regulator-boot-on; +- }; +- +- v1v2_hdmi: ldo6 { +- regulator-name = "v1v2_hdmi"; +- regulator-min-microvolt = <1200000>; +- regulator-max-microvolt = <1200000>; +- regulator-always-on; +- }; +- +- vref_ddr: vref_ddr { +- regulator-name = "vref_ddr"; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- }; +- }; +-}; +- +-&iwdg2 { +- timeout-sec = <32>; +- status = "okay"; +-}; +- +-&pwr { +- pwr-regulators { +- vdd-supply = <&vdd>; +- }; +-}; +- +-&rng1 { +- status = "okay"; +-}; +- +-&rtc { +- status = "okay"; + }; + +-&sdmmc1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc1_b4_pins_a>; +- broken-cd; +- st,neg-edge; +- bus-width = <4>; +- vmmc-supply = <&v3v3>; +- status = "okay"; +-}; +- +-&uart4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart4_pins_a>; +- status = "okay"; +-}; +- +-&uart7 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart7_pins_a>; +- status = "disabled"; +-}; +- +-&usart3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&usart3_pins_b>; +- status = "disabled"; +-}; +- +-/* ATF Specific */ +-#include +-#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" +-#include "stm32mp157c-security.dtsi" +- +-/ { +- aliases { +- gpio0 = &gpioa; +- gpio1 = &gpiob; +- gpio2 = &gpioc; +- gpio3 = &gpiod; +- gpio4 = &gpioe; +- gpio5 = &gpiof; +- gpio6 = &gpiog; +- gpio7 = &gpioh; +- gpio8 = &gpioi; +- gpio25 = &gpioz; +- i2c3 = &i2c4; +- }; +-}; +- +-/* CLOCK init */ +-&rcc { +- secure-status = "disabled"; +- st,clksrc = < +- CLK_MPU_PLL1P +- CLK_AXI_PLL2P +- CLK_MCU_PLL3P +- CLK_PLL12_HSE +- CLK_PLL3_HSE +- CLK_PLL4_HSE +- CLK_RTC_LSE +- CLK_MCO1_DISABLED +- CLK_MCO2_DISABLED ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) + >; +- +- st,clkdiv = < +- 1 /*MPU*/ +- 0 /*AXI*/ +- 0 /*MCU*/ +- 1 /*APB1*/ +- 1 /*APB2*/ +- 1 /*APB3*/ +- 1 /*APB4*/ +- 2 /*APB5*/ +- 23 /*RTC*/ +- 0 /*MCO1*/ +- 0 /*MCO2*/ +- >; +- +- st,pkcs = < +- CLK_CKPER_HSE +- CLK_FMC_ACLK +- CLK_QSPI_ACLK +- CLK_ETH_DISABLED +- CLK_SDMMC12_PLL4P +- CLK_DSI_DSIPLL +- CLK_STGEN_HSE +- CLK_USBPHY_HSE +- CLK_SPI2S1_PLL3Q +- CLK_SPI2S23_PLL3Q +- CLK_SPI45_HSI +- CLK_SPI6_HSI +- CLK_I2C46_HSI +- CLK_SDMMC3_PLL4P +- CLK_USBO_USBPHY +- CLK_ADC_CKPER +- CLK_CEC_LSE +- CLK_I2C12_HSI +- CLK_I2C35_HSI +- CLK_UART1_HSI +- CLK_UART24_HSI +- CLK_UART35_HSI +- CLK_UART6_HSI +- CLK_UART78_HSI +- CLK_SPDIF_PLL4P +- CLK_FDCAN_PLL4R +- CLK_SAI1_PLL3Q +- CLK_SAI2_PLL3Q +- CLK_SAI3_PLL3Q +- CLK_SAI4_PLL3Q +- CLK_RNG1_LSI +- CLK_RNG2_LSI +- CLK_LPTIM1_PCLK1 +- CLK_LPTIM23_PCLK3 +- CLK_LPTIM45_LSE +- >; +- +- /* VCO = 1300.0 MHz => P = 650 (CPU) */ +- pll1: st,pll@0 { +- cfg = < 2 80 0 0 0 PQR(1,0,0) >; +- frac = < 0x800 >; +- }; +- +- /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ +- pll2: st,pll@1 { +- cfg = < 2 65 1 0 0 PQR(1,1,1) >; +- frac = < 0x1400 >; +- }; +- +- /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ +- pll3: st,pll@2 { +- cfg = < 1 33 1 16 36 PQR(1,1,1) >; +- frac = < 0x1a04 >; +- }; +- +- /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ +- pll4: st,pll@3 { +- cfg = < 3 98 5 7 7 PQR(1,1,1) >; +- }; +-}; +- +-&bsec { +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- status = "okay"; +- secure-status = "okay"; +- }; + }; +diff --git a/fdts/stm32mp157a-ed1.dts b/fdts/stm32mp157a-ed1.dts +new file mode 100644 +index 000000000..4f84ec623 +--- /dev/null ++++ b/fdts/stm32mp157a-ed1.dts +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157A eval daughter"; ++ compatible = "st,stm32mp157a-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/fdts/stm32mp157a-ev1.dts b/fdts/stm32mp157a-ev1.dts +new file mode 100644 +index 000000000..c577a9052 +--- /dev/null ++++ b/fdts/stm32mp157a-ev1.dts +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157a-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157A eval daughter on eval mother"; ++ compatible = "st,stm32mp157a-ev1", "st,stm32mp157a-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial1 = &usart3; ++ }; ++}; ++ +diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts +index fdcf4c802..436a15970 100644 +--- a/fdts/stm32mp157c-dk2.dts ++++ b/fdts/stm32mp157c-dk2.dts +@@ -1,16 +1,51 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2018 - All Rights Reserved +- * Author: Alexandre Torgue . ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + + /dts-v1/; + +-#include "stm32mp157a-dk1.dts" ++#include "stm32mp157.dtsi" ++#include "stm32mp15xc.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&cryp1 { ++ status = "okay"; + }; + ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts +index 779492552..5aadb1ff0 100644 +--- a/fdts/stm32mp157c-ed1.dts ++++ b/fdts/stm32mp157c-ed1.dts +@@ -1,12 +1,16 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + /dts-v1/; + +-#include "stm32mp157c.dtsi" +-#include "stm32mp157caa-pinctrl.dtsi" ++#include "stm32mp157.dtsi" ++#include "stm32mp15xc.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C eval daughter"; +@@ -21,297 +25,27 @@ + }; + }; + +-&clk_hse { +- st,digbypass; ++&cpu1 { ++ cpu-supply = <&vddcore>; + }; + +-&i2c4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c4_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +- +- pmic: stpmic@33 { +- compatible = "st,stpmic1"; +- reg = <0x33>; +- interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; +- interrupt-controller; +- #interrupt-cells = <2>; +- status = "okay"; +- +- st,main-control-register = <0x04>; +- st,vin-control-register = <0xc0>; +- st,usb-control-register = <0x20>; +- +- regulators { +- compatible = "st,stpmic1-regulators"; +- +- ldo1-supply = <&v3v3>; +- ldo2-supply = <&v3v3>; +- ldo3-supply = <&vdd_ddr>; +- ldo5-supply = <&v3v3>; +- ldo6-supply = <&v3v3>; +- +- vddcore: buck1 { +- regulator-name = "vddcore"; +- regulator-min-microvolt = <1200000>; +- regulator-max-microvolt = <1350000>; +- regulator-always-on; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- vdd_ddr: buck2 { +- regulator-name = "vdd_ddr"; +- regulator-min-microvolt = <1350000>; +- regulator-max-microvolt = <1350000>; +- regulator-always-on; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- vdd: buck3 { +- regulator-name = "vdd"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- st,mask-reset; +- regulator-initial-mode = <0>; +- regulator-over-current-protection; +- }; +- +- v3v3: buck4 { +- regulator-name = "v3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- regulator-over-current-protection; +- regulator-initial-mode = <0>; +- }; +- +- vdda: ldo1 { +- regulator-name = "vdda"; +- regulator-min-microvolt = <2900000>; +- regulator-max-microvolt = <2900000>; +- }; +- +- v2v8: ldo2 { +- regulator-name = "v2v8"; +- regulator-min-microvolt = <2800000>; +- regulator-max-microvolt = <2800000>; +- }; +- +- vtt_ddr: ldo3 { +- regulator-name = "vtt_ddr"; +- regulator-min-microvolt = <500000>; +- regulator-max-microvolt = <750000>; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- +- vdd_usb: ldo4 { +- regulator-name = "vdd_usb"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- }; +- +- vdd_sd: ldo5 { +- regulator-name = "vdd_sd"; +- regulator-min-microvolt = <2900000>; +- regulator-max-microvolt = <2900000>; +- regulator-boot-on; +- }; +- +- v1v8: ldo6 { +- regulator-name = "v1v8"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <1800000>; +- }; +- +- vref_ddr: vref_ddr { +- regulator-name = "vref_ddr"; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- }; +- }; +-}; +- +-&iwdg2 { +- timeout-sec = <32>; +- status = "okay"; +-}; +- +-&pwr { +- pwr-regulators { +- vdd-supply = <&vdd>; +- }; +-}; +- +-&rng1 { +- status = "okay"; +-}; +- +-&rtc { +- status = "okay"; +-}; +- +-&sdmmc1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; +- broken-cd; +- st,sig-dir; +- st,neg-edge; +- st,use-ckin; +- bus-width = <4>; +- vmmc-supply = <&vdd_sd>; +- sd-uhs-sdr12; +- sd-uhs-sdr25; +- sd-uhs-sdr50; +- sd-uhs-ddr50; +- sd-uhs-sdr104; +- status = "okay"; +-}; +- +-&sdmmc2 { +- pinctrl-names = "default"; +- pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; +- non-removable; +- no-sd; +- no-sdio; +- st,neg-edge; +- bus-width = <8>; +- vmmc-supply = <&v3v3>; +- vqmmc-supply = <&v3v3>; +- mmc-ddr-3_3v; +- status = "okay"; +-}; +- +-&uart4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart4_pins_a>; ++&cryp1 { + status = "okay"; + }; + +-/* ATF Specific */ +-#include +-#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" +-#include "stm32mp157c-security.dtsi" +- +-/ { +- aliases { +- gpio0 = &gpioa; +- gpio1 = &gpiob; +- gpio2 = &gpioc; +- gpio3 = &gpiod; +- gpio4 = &gpioe; +- gpio5 = &gpiof; +- gpio6 = &gpiog; +- gpio7 = &gpioh; +- gpio8 = &gpioi; +- gpio9 = &gpioj; +- gpio10 = &gpiok; +- gpio25 = &gpioz; +- i2c3 = &i2c4; +- }; +-}; +- +-/* CLOCK init */ +-&rcc { +- secure-status = "disabled"; +- st,clksrc = < +- CLK_MPU_PLL1P +- CLK_AXI_PLL2P +- CLK_MCU_PLL3P +- CLK_PLL12_HSE +- CLK_PLL3_HSE +- CLK_PLL4_HSE +- CLK_RTC_LSE +- CLK_MCO1_DISABLED +- CLK_MCO2_DISABLED ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) + >; +- +- st,clkdiv = < +- 1 /*MPU*/ +- 0 /*AXI*/ +- 0 /*MCU*/ +- 1 /*APB1*/ +- 1 /*APB2*/ +- 1 /*APB3*/ +- 1 /*APB4*/ +- 2 /*APB5*/ +- 23 /*RTC*/ +- 0 /*MCO1*/ +- 0 /*MCO2*/ +- >; +- +- st,pkcs = < +- CLK_CKPER_HSE +- CLK_FMC_ACLK +- CLK_QSPI_ACLK +- CLK_ETH_DISABLED +- CLK_SDMMC12_PLL4P +- CLK_DSI_DSIPLL +- CLK_STGEN_HSE +- CLK_USBPHY_HSE +- CLK_SPI2S1_PLL3Q +- CLK_SPI2S23_PLL3Q +- CLK_SPI45_HSI +- CLK_SPI6_HSI +- CLK_I2C46_HSI +- CLK_SDMMC3_PLL4P +- CLK_USBO_USBPHY +- CLK_ADC_CKPER +- CLK_CEC_LSE +- CLK_I2C12_HSI +- CLK_I2C35_HSI +- CLK_UART1_HSI +- CLK_UART24_HSI +- CLK_UART35_HSI +- CLK_UART6_HSI +- CLK_UART78_HSI +- CLK_SPDIF_PLL4P +- CLK_FDCAN_PLL4R +- CLK_SAI1_PLL3Q +- CLK_SAI2_PLL3Q +- CLK_SAI3_PLL3Q +- CLK_SAI4_PLL3Q +- CLK_RNG1_LSI +- CLK_RNG2_LSI +- CLK_LPTIM1_PCLK1 +- CLK_LPTIM23_PCLK3 +- CLK_LPTIM45_LSE +- >; +- +- /* VCO = 1300.0 MHz => P = 650 (CPU) */ +- pll1: st,pll@0 { +- cfg = < 2 80 0 0 0 PQR(1,0,0) >; +- frac = < 0x800 >; +- }; +- +- /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ +- pll2: st,pll@1 { +- cfg = < 2 65 1 0 0 PQR(1,1,1) >; +- frac = < 0x1400 >; +- }; +- +- /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ +- pll3: st,pll@2 { +- cfg = < 1 33 1 16 36 PQR(1,1,1) >; +- frac = < 0x1a04 >; +- }; +- +- /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ +- pll4: st,pll@3 { +- cfg = < 3 98 5 7 7 PQR(1,1,1) >; +- }; +-}; +- +-&bsec { +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- status = "okay"; +- secure-status = "okay"; +- }; + }; +diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts +index cfde8ed90..dd7da4195 100644 +--- a/fdts/stm32mp157c-ev1.dts ++++ b/fdts/stm32mp157c-ev1.dts +@@ -1,11 +1,12 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + /dts-v1/; + + #include "stm32mp157c-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" + + / { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; +@@ -19,49 +20,3 @@ + serial1 = &usart3; + }; + }; +- +-&fmc { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- nand: nand@0 { +- reg = <0>; +- nand-on-flash-bbt; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +-}; +- +-&qspi { +- pinctrl-names = "default"; +- pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; +- reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- +- flash0: mx66l51235l@0 { +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +- +- flash1: mx66l51235l@1 { +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +-}; +- +-&usart3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&usart3_pins_a>; +- status = "disabled"; +-}; +diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi +deleted file mode 100644 +index 165ffa0cb..000000000 +--- a/fdts/stm32mp157c-security.dtsi ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved +- * +- * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause +- */ +- +-/ { +- soc { +- stgen: stgen@5c008000 { +- compatible = "st,stm32-stgen"; +- reg = <0x5C008000 0x1000>; +- status = "okay"; +- }; +- }; +-}; +- +-&bsec { +- mac_addr: mac_addr@e4 { +- reg = <0xe4 0x6>; +- status = "okay"; +- secure-status = "okay"; +- }; +- /* Spare field to align on 32-bit OTP granularity */ +- spare_ns_ea: spare_ns_ea@ea { +- reg = <0xea 0x2>; +- status = "okay"; +- secure-status = "okay"; +- }; +-}; +- +-&hash1 { +- secure-status = "okay"; +-}; +- +-&sdmmc1 { +- compatible = "st,stm32-sdmmc2"; +-}; +- +-&sdmmc2 { +- compatible = "st,stm32-sdmmc2"; +-}; +diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi +deleted file mode 100644 +index 0942a91c2..000000000 +--- a/fdts/stm32mp157c.dtsi ++++ /dev/null +@@ -1,366 +0,0 @@ +-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +-/* +- * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. +- */ +-#include +-#include +-#include +- +-/ { +- #address-cells = <1>; +- #size-cells = <1>; +- +- intc: interrupt-controller@a0021000 { +- compatible = "arm,cortex-a7-gic"; +- #interrupt-cells = <3>; +- interrupt-controller; +- reg = <0xa0021000 0x1000>, +- <0xa0022000 0x2000>; +- }; +- +- clocks { +- clk_hse: clk-hse { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <24000000>; +- }; +- +- clk_hsi: clk-hsi { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <64000000>; +- }; +- +- clk_lse: clk-lse { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <32768>; +- }; +- +- clk_lsi: clk-lsi { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <32000>; +- }; +- +- clk_csi: clk-csi { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <4000000>; +- }; +- +- clk_i2s_ckin: i2s_ckin { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <0>; +- }; +- +- clk_dsi_phy: ck_dsi_phy { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <0>; +- }; +- }; +- +- soc { +- compatible = "simple-bus"; +- #address-cells = <1>; +- #size-cells = <1>; +- interrupt-parent = <&intc>; +- ranges; +- +- timers12: timer@40006000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40006000 0x400>; +- clocks = <&rcc TIM12_K>; +- clock-names = "int"; +- status = "disabled"; +- }; +- +- usart2: serial@4000e000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x4000e000 0x400>; +- clocks = <&rcc USART2_K>; +- resets = <&rcc USART2_R>; +- status = "disabled"; +- }; +- +- usart3: serial@4000f000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x4000f000 0x400>; +- clocks = <&rcc USART3_K>; +- resets = <&rcc USART3_R>; +- status = "disabled"; +- }; +- +- uart4: serial@40010000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x40010000 0x400>; +- clocks = <&rcc UART4_K>; +- resets = <&rcc UART4_R>; +- status = "disabled"; +- }; +- +- uart5: serial@40011000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x40011000 0x400>; +- clocks = <&rcc UART5_K>; +- resets = <&rcc UART5_R>; +- status = "disabled"; +- }; +- +- +- uart7: serial@40018000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x40018000 0x400>; +- clocks = <&rcc UART7_K>; +- resets = <&rcc UART7_R>; +- status = "disabled"; +- }; +- +- uart8: serial@40019000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x40019000 0x400>; +- clocks = <&rcc UART8_K>; +- resets = <&rcc UART8_R>; +- status = "disabled"; +- }; +- +- usart6: serial@44003000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x44003000 0x400>; +- clocks = <&rcc USART6_K>; +- resets = <&rcc USART6_R>; +- status = "disabled"; +- }; +- +- timers15: timer@44006000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x44006000 0x400>; +- clocks = <&rcc TIM15_K>; +- clock-names = "int"; +- status = "disabled"; +- }; +- +- sdmmc3: sdmmc@48004000 { +- compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x00253180>; +- reg = <0x48004000 0x400>, <0x48005000 0x400>; +- clocks = <&rcc SDMMC3_K>; +- clock-names = "apb_pclk"; +- resets = <&rcc SDMMC3_R>; +- cap-sd-highspeed; +- cap-mmc-highspeed; +- max-frequency = <120000000>; +- status = "disabled"; +- }; +- +- usbotg_hs: usb-otg@49000000 { +- compatible = "st,stm32mp1-hsotg", "snps,dwc2"; +- reg = <0x49000000 0x10000>; +- clocks = <&rcc USBO_K>; +- clock-names = "otg"; +- resets = <&rcc USBO_R>; +- reset-names = "dwc2"; +- status = "disabled"; +- }; +- +- rcc: rcc@50000000 { +- compatible = "st,stm32mp1-rcc", "syscon"; +- reg = <0x50000000 0x1000>; +- #clock-cells = <1>; +- #reset-cells = <1>; +- interrupts = ; +- }; +- +- pwr: pwr@50001000 { +- compatible = "st,stm32mp1-pwr", "syscon", "simple-mfd"; +- reg = <0x50001000 0x400>; +- }; +- +- exti: interrupt-controller@5000d000 { +- compatible = "st,stm32mp1-exti", "syscon"; +- interrupt-controller; +- #interrupt-cells = <2>; +- reg = <0x5000d000 0x400>; +- +- /* exti_pwr is an extra interrupt controller used for +- * EXTI 55 to 60. It's mapped on pwr interrupt +- * controller. +- */ +- exti_pwr: exti-pwr { +- interrupt-controller; +- #interrupt-cells = <2>; +- interrupt-parent = <&pwr>; +- st,irq-number = <6>; +- }; +- }; +- +- syscfg: syscon@50020000 { +- compatible = "st,stm32mp157-syscfg", "syscon"; +- reg = <0x50020000 0x400>; +- clocks = <&rcc SYSCFG>; +- }; +- +- cryp1: cryp@54001000 { +- compatible = "st,stm32mp1-cryp"; +- reg = <0x54001000 0x400>; +- interrupts = ; +- clocks = <&rcc CRYP1>; +- resets = <&rcc CRYP1_R>; +- status = "disabled"; +- }; +- +- hash1: hash@54002000 { +- compatible = "st,stm32f756-hash"; +- reg = <0x54002000 0x400>; +- interrupts = ; +- clocks = <&rcc HASH1>; +- resets = <&rcc HASH1_R>; +- status = "disabled"; +- }; +- +- rng1: rng@54003000 { +- compatible = "st,stm32-rng"; +- reg = <0x54003000 0x400>; +- clocks = <&rcc RNG1_K>; +- resets = <&rcc RNG1_R>; +- status = "disabled"; +- }; +- +- fmc: nand-controller@58002000 { +- compatible = "st,stm32mp15-fmc2"; +- reg = <0x58002000 0x1000>, +- <0x80000000 0x1000>, +- <0x88010000 0x1000>, +- <0x88020000 0x1000>, +- <0x81000000 0x1000>, +- <0x89010000 0x1000>, +- <0x89020000 0x1000>; +- clocks = <&rcc FMC_K>; +- resets = <&rcc FMC_R>; +- status = "disabled"; +- }; +- +- qspi: qspi@58003000 { +- compatible = "st,stm32f469-qspi"; +- reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; +- reg-names = "qspi", "qspi_mm"; +- clocks = <&rcc QSPI_K>; +- resets = <&rcc QSPI_R>; +- status = "disabled"; +- }; +- +- sdmmc1: sdmmc@58005000 { +- compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x00253180>; +- reg = <0x58005000 0x1000>, <0x58006000 0x1000>; +- clocks = <&rcc SDMMC1_K>; +- clock-names = "apb_pclk"; +- resets = <&rcc SDMMC1_R>; +- cap-sd-highspeed; +- cap-mmc-highspeed; +- max-frequency = <120000000>; +- status = "disabled"; +- }; +- +- sdmmc2: sdmmc@58007000 { +- compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x00253180>; +- reg = <0x58007000 0x1000>, <0x58008000 0x1000>; +- clocks = <&rcc SDMMC2_K>; +- clock-names = "apb_pclk"; +- resets = <&rcc SDMMC2_R>; +- cap-sd-highspeed; +- cap-mmc-highspeed; +- max-frequency = <120000000>; +- status = "disabled"; +- }; +- +- iwdg2: watchdog@5a002000 { +- compatible = "st,stm32mp1-iwdg"; +- reg = <0x5a002000 0x400>; +- clocks = <&rcc IWDG2>, <&rcc CK_LSI>; +- clock-names = "pclk", "lsi"; +- status = "disabled"; +- }; +- +- usart1: serial@5c000000 { +- compatible = "st,stm32h7-uart"; +- reg = <0x5c000000 0x400>; +- interrupt-names = "event", "wakeup"; +- interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, +- <&exti 26 1>; +- clocks = <&rcc USART1_K>; +- resets = <&rcc USART1_R>; +- status = "disabled"; +- }; +- +- spi6: spi@5c001000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; +- reg = <0x5c001000 0x400>; +- interrupts = ; +- clocks = <&rcc SPI6_K>; +- resets = <&rcc SPI6_R>; +- status = "disabled"; +- }; +- +- i2c4: i2c@5c002000 { +- compatible = "st,stm32f7-i2c"; +- reg = <0x5c002000 0x400>; +- interrupt-names = "event", "error", "wakeup"; +- interrupts-extended = <&intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, +- <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, +- <&exti 24 1>; +- clocks = <&rcc I2C4_K>; +- resets = <&rcc I2C4_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- rtc: rtc@5c004000 { +- compatible = "st,stm32mp1-rtc"; +- reg = <0x5c004000 0x400>; +- clocks = <&rcc RTCAPB>, <&rcc RTC>; +- clock-names = "pclk", "rtc_ck"; +- interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, +- <&exti 19 1>; +- status = "disabled"; +- }; +- +- bsec: nvmem@5c005000 { +- compatible = "st,stm32mp15-bsec"; +- reg = <0x5c005000 0x400>; +- #address-cells = <1>; +- #size-cells = <1>; +- ts_cal1: calib@5c { +- reg = <0x5c 0x2>; +- }; +- ts_cal2: calib@5e { +- reg = <0x5e 0x2>; +- }; +- }; +- +- i2c6: i2c@5c009000 { +- compatible = "st,stm32f7-i2c"; +- reg = <0x5c009000 0x400>; +- interrupt-names = "event", "error", "wakeup"; +- interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, +- <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, +- <&exti 54 1>; +- clocks = <&rcc I2C6_K>; +- resets = <&rcc I2C6_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- }; +-}; +diff --git a/fdts/stm32mp157caa-pinctrl.dtsi b/fdts/stm32mp157caa-pinctrl.dtsi +deleted file mode 100644 +index 9b9cd086c..000000000 +--- a/fdts/stm32mp157caa-pinctrl.dtsi ++++ /dev/null +@@ -1,90 +0,0 @@ +-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +-/* +- * Copyright (C) STMicroelectronics 2018 - All Rights Reserved +- * Author: Alexandre Torgue +- */ +- +-#include "stm32mp157-pinctrl.dtsi" +-/ { +- soc { +- pinctrl: pin-controller@50002000 { +- st,package = ; +- +- gpioa: gpio@50002000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 0 16>; +- }; +- +- gpiob: gpio@50003000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 16 16>; +- }; +- +- gpioc: gpio@50004000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 32 16>; +- }; +- +- gpiod: gpio@50005000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 48 16>; +- }; +- +- gpioe: gpio@50006000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 64 16>; +- }; +- +- gpiof: gpio@50007000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 80 16>; +- }; +- +- gpiog: gpio@50008000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 96 16>; +- }; +- +- gpioh: gpio@50009000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 112 16>; +- }; +- +- gpioi: gpio@5000a000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 128 16>; +- }; +- +- gpioj: gpio@5000b000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 144 16>; +- }; +- +- gpiok: gpio@5000c000 { +- status = "okay"; +- ngpios = <8>; +- gpio-ranges = <&pinctrl 0 160 8>; +- }; +- }; +- +- pinctrl_z: pin-controller-z@54004000 { +- st,package = ; +- +- gpioz: gpio@54004000 { +- status = "okay"; +- ngpios = <8>; +- gpio-ranges = <&pinctrl_z 0 400 8>; +- }; +- }; +- }; +-}; +diff --git a/fdts/stm32mp157cac-pinctrl.dtsi b/fdts/stm32mp157cac-pinctrl.dtsi +deleted file mode 100644 +index 777f9919d..000000000 +--- a/fdts/stm32mp157cac-pinctrl.dtsi ++++ /dev/null +@@ -1,78 +0,0 @@ +-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +-/* +- * Copyright (C) STMicroelectronics 2018 - All Rights Reserved +- * Author: Alexandre Torgue +- */ +- +-#include "stm32mp157-pinctrl.dtsi" +-/ { +- soc { +- pinctrl: pin-controller@50002000 { +- st,package = ; +- +- gpioa: gpio@50002000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 0 16>; +- }; +- +- gpiob: gpio@50003000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 16 16>; +- }; +- +- gpioc: gpio@50004000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 32 16>; +- }; +- +- gpiod: gpio@50005000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 48 16>; +- }; +- +- gpioe: gpio@50006000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 64 16>; +- }; +- +- gpiof: gpio@50007000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 80 16>; +- }; +- +- gpiog: gpio@50008000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 96 16>; +- }; +- +- gpioh: gpio@50009000 { +- status = "okay"; +- ngpios = <16>; +- gpio-ranges = <&pinctrl 0 112 16>; +- }; +- +- gpioi: gpio@5000a000 { +- status = "okay"; +- ngpios = <12>; +- gpio-ranges = <&pinctrl 0 128 12>; +- }; +- }; +- +- pinctrl_z: pin-controller-z@54004000 { +- st,package = ; +- +- gpioz: gpio@54004000 { +- status = "okay"; +- ngpios = <8>; +- gpio-ranges = <&pinctrl_z 0 400 8>; +- }; +- }; +- }; +-}; +diff --git a/fdts/stm32mp157d-dk1.dts b/fdts/stm32mp157d-dk1.dts +new file mode 100644 +index 000000000..d320f993e +--- /dev/null ++++ b/fdts/stm32mp157d-dk1.dts +@@ -0,0 +1,49 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + -+#include "stm32mp157c.dtsi" -+#include "stm32mp157cac-pinctrl.dtsi" ++#include "stm32mp157.dtsi" ++#include "stm32mp15xd.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include + +/ { -+ model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; -+ compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; ++ model = "STMicroelectronics STM32MP157D-DK1 Discovery Board"; ++ compatible = "st,stm32mp157d-dk1", "st,stm32mp157"; + + aliases { + serial0 = &uart4; @@ -23599,19 +23838,413 @@ index 0000000..fadb442 + chosen { + stdout-path = "serial0:115200n8"; + }; ++}; + ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/fdts/stm32mp157d-ed1.dts b/fdts/stm32mp157d-ed1.dts +new file mode 100644 +index 000000000..76f0614d6 +--- /dev/null ++++ b/fdts/stm32mp157d-ed1.dts +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xd.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157D eval daughter"; ++ compatible = "st,stm32mp157d-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/fdts/stm32mp157d-ev1.dts b/fdts/stm32mp157d-ev1.dts +new file mode 100644 +index 000000000..47d962b57 +--- /dev/null ++++ b/fdts/stm32mp157d-ev1.dts +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157d-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D eval daughter on eval mother"; ++ compatible = "st,stm32mp157d-ev1", "st,stm32mp157d-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial1 = &usart3; ++ }; ++}; +diff --git a/fdts/stm32mp157f-dk2.dts b/fdts/stm32mp157f-dk2.dts +new file mode 100644 +index 000000000..9c79bfb43 +--- /dev/null ++++ b/fdts/stm32mp157f-dk2.dts +@@ -0,0 +1,55 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xf.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-DK2 Discovery Board"; ++ compatible = "st,stm32mp157f-dk2", "st,stm32mp157"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/fdts/stm32mp157f-ed1.dts b/fdts/stm32mp157f-ed1.dts +new file mode 100644 +index 000000000..a659cf84d +--- /dev/null ++++ b/fdts/stm32mp157f-ed1.dts +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xf.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F eval daughter"; ++ compatible = "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++}; ++ ++&cpu1{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/fdts/stm32mp157f-ev1.dts b/fdts/stm32mp157f-ev1.dts +new file mode 100644 +index 000000000..c8598ce55 +--- /dev/null ++++ b/fdts/stm32mp157f-ev1.dts +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157f-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157F eval daughter on eval mother"; ++ compatible = "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial1 = &usart3; ++ }; ++}; +diff --git a/fdts/stm32mp15xa.dtsi b/fdts/stm32mp15xa.dtsi +new file mode 100644 +index 000000000..5ed7e594f +--- /dev/null ++++ b/fdts/stm32mp15xa.dtsi +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++&cpu0_opp_table { ++ opp-650000000 { ++ opp-hz = /bits/ 64 <650000000>; ++ opp-microvolt = <1200000>; ++ opp-supported-hw = <0x1>; ++ }; ++}; +diff --git a/fdts/stm32mp15xc.dtsi b/fdts/stm32mp15xc.dtsi +new file mode 100644 +index 000000000..68d822d8c +--- /dev/null ++++ b/fdts/stm32mp15xc.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp15xa.dtsi" ++ ++/ { ++ soc { ++ cryp1: cryp@54001000 { ++ compatible = "st,stm32mp1-cryp"; ++ reg = <0x54001000 0x400>; ++ interrupts = ; ++ clocks = <&rcc CRYP1>; ++ resets = <&rcc CRYP1_R>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp15xd.dtsi b/fdts/stm32mp15xd.dtsi +new file mode 100644 +index 000000000..18b05ee38 +--- /dev/null ++++ b/fdts/stm32mp15xd.dtsi +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++&cpu0_opp_table { ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1350000>; ++ opp-supported-hw = <0x2>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <1200000>; ++ opp-supported-hw = <0x2>; ++ opp-suspend; ++ }; ++}; +diff --git a/fdts/stm32mp15xf.dtsi b/fdts/stm32mp15xf.dtsi +new file mode 100644 +index 000000000..526a1627c +--- /dev/null ++++ b/fdts/stm32mp15xf.dtsi +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp15xd.dtsi" ++ ++/ { ++ soc { ++ cryp1: cryp@54001000 { ++ compatible = "st,stm32mp1-cryp"; ++ reg = <0x54001000 0x400>; ++ interrupts = ; ++ clocks = <&rcc CRYP1>; ++ resets = <&rcc CRYP1_R>; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi +new file mode 100644 +index 000000000..53790f29b +--- /dev/null ++++ b/fdts/stm32mp15xx-dkx.dtsi +@@ -0,0 +1,470 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include ++#include ++#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" ++ ++/ { ++ memory@c0000000 { ++ device_type = "memory"; ++ reg = <0xc0000000 0x20000000>; ++ }; ++ ++ vin: vin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vin"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++}; ++ ++&bsec { ++ board_id: board_id@ec { ++ reg = <0xec 0x4>; ++ st,non-secure-otp; ++ }; +}; + +&clk_hse { + st,digbypass; +}; + ++&cpu0{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&cpu1{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&hash1 { ++ status = "okay"; ++}; ++ +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; ++ clock-frequency = <400000>; + status = "okay"; ++ secure-status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; @@ -23620,17 +24253,24 @@ index 0000000..fadb442 + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; -+ -+ st,main-control-register = <0x04>; -+ st,vin-control-register = <0xc0>; -+ st,usb-control-register = <0x20>; ++ secure-status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; -+ ++ buck1-supply = <&vin>; ++ buck2-supply = <&vin>; ++ buck3-supply = <&vin>; ++ buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; ++ ldo2-supply = <&vin>; + ldo3-supply = <&vdd_ddr>; ++ ldo4-supply = <&vin>; ++ ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; ++ vref_ddr-supply = <&vin>; ++ boost-supply = <&vin>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; @@ -23639,6 +24279,16 @@ index 0000000..fadb442 + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1200000>; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_ddr: buck2 { @@ -23648,6 +24298,17 @@ index 0000000..fadb442 + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd: buck3 { @@ -23658,6 +24319,18 @@ index 0000000..fadb442 + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; + }; + + v3v3: buck4 { @@ -23667,6 +24340,16 @@ index 0000000..fadb442 + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; ++ lp-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v1v8_audio: ldo1 { @@ -23674,6 +24357,12 @@ index 0000000..fadb442 + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v3v3_hdmi: ldo2 { @@ -23681,6 +24370,12 @@ index 0000000..fadb442 + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vtt_ddr: ldo3 { @@ -23689,12 +24384,28 @@ index 0000000..fadb442 + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; ++ lp-stop { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdda: ldo5 { @@ -23702,6 +24413,12 @@ index 0000000..fadb442 + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v1v2_hdmi: ldo6 { @@ -23709,12 +24426,40 @@ index 0000000..fadb442 + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; ++ lp-stop { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ }; ++ ++ vbus_otg: pwr_sw1 { ++ regulator-name = "vbus_otg"; ++ }; ++ ++ vbus_sw: pwr_sw2 { ++ regulator-name = "vbus_sw"; ++ regulator-active-discharge = <1>; + }; + }; + }; @@ -23723,74 +24468,43 @@ index 0000000..fadb442 +&iwdg2 { + timeout-sec = <32>; + status = "okay"; -+}; -+ -+&pwr { -+ pwr-supply = <&vdd>; -+}; -+ -+&rng1 { -+ status = "okay"; -+}; -+ -+&rtc { -+ status = "okay"; -+}; -+ -+&sdmmc1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_b4_pins_a>; -+ broken-cd; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3>; -+ status = "okay"; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart4_pins_a>; -+ status = "okay"; -+}; -+ -+&uart7 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart7_pins_a>; -+ status = "disabled"; -+}; -+ -+&usart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usart3_pins_b>; -+ status = "disabled"; -+}; -+ -+ -+/* ATF Specific */ -+#include -+#include -+#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" -+#include "stm32mp157c-security.dtsi" -+ -+/ { -+ aliases { -+ gpio0 = &gpioa; -+ gpio1 = &gpiob; -+ gpio2 = &gpioc; -+ gpio3 = &gpiod; -+ gpio4 = &gpioe; -+ gpio5 = &gpiof; -+ gpio6 = &gpiog; -+ gpio7 = &gpioh; -+ gpio8 = &gpioi; -+ gpio25 = &gpioz; -+ i2c3 = &i2c4; -+ }; -+}; -+ -+/* CLOCK init */ -+&rcc { + secure-status = "okay"; ++}; ++ ++&nvmem_layout { ++ nvmem-cells = <&cfg0_otp>, ++ <&part_number_otp>, ++ <&monotonic_otp>, ++ <&nand_otp>, ++ <&uid_otp>, ++ <&package_otp>, ++ <&hw2_otp>, ++ <&pkh_otp>, ++ <&board_id>; ++ ++ nvmem-cell-names = "cfg0_otp", ++ "part_number_otp", ++ "monotonic_otp", ++ "nand_otp", ++ "uid_otp", ++ "package_otp", ++ "hw2_otp", ++ "pkh_otp", ++ "board_id"; ++}; ++ ++&pwr_regulators { ++ system_suspend_supported_soc_modes = < ++ STM32_PM_CSLEEP_RUN ++ STM32_PM_CSTOP_ALLOW_LP_STOP ++ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR ++ >; ++ system_off_soc_mode = ; ++ vdd-supply = <&vdd>; ++ vdd_3v3_usbfs-supply = <&vdd_usb>; ++}; ++ ++&rcc { + st,hsi-cal; + st,csi-cal; + st,cal-sec = <60>; @@ -23846,7 +24560,7 @@ index 0000000..fadb442 + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P -+ CLK_FDCAN_PLL4Q ++ CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q @@ -23858,279 +24572,177 @@ index 0000000..fadb442 + CLK_LPTIM45_LSE + >; + -+ /* VCO = 1300.0 MHz => P = 650 (CPU) */ -+ pll1: st,pll@0 { -+ cfg = < 2 80 0 0 0 PQR(1,0,0) >; -+ frac = < 0x800 >; -+ }; -+ + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { -+ cfg = < 2 65 1 0 0 PQR(1,1,1) >; -+ frac = < 0x1400 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ cfg = <2 65 1 0 0 PQR(1,1,1)>; ++ frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { -+ cfg = < 1 33 1 16 36 PQR(1,1,1) >; -+ frac = < 0x1a04 >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ cfg = <1 33 1 16 36 PQR(1,1,1)>; ++ frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { -+ cfg = < 3 98 5 7 7 PQR(1,1,1) >; ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + -+/* Security specific */ -+&etzpc { -+ st,decprot = < -+ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ >; -+}; -+ -+&iwdg2 { ++&rng1 { ++ status = "okay"; + secure-status = "okay"; +}; + -+&pwr { -+ system_suspend_supported_soc_modes = < -+ STM32_PM_CSLEEP_RUN -+ STM32_PM_CSTOP_ALLOW_LP_STOP -+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR -+ >; ++&rtc { ++ status = "okay"; ++ secure-status = "okay"; ++}; + -+ system_off_soc_mode = ; ++&sdmmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_b4_pins_a>; ++ disable-wp; ++ st,neg-edge; ++ bus-width = <4>; ++ vmmc-supply = <&v3v3>; ++ status = "okay"; +}; + +&timers15 { + secure-status = "okay"; + st,hsi-cal-input = <7>; -+ st,csi_cal-input = <8>; ++ st,csi-cal-input = <8>; +}; + -+/* Low-power states of regulators */ -+&vddcore { -+ lp-stop { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1200000>; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_pins_a>; ++ status = "okay"; +}; + -+&vdd_ddr { -+ lp-stop { -+ regulator-suspend-microvolt = <1350000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-suspend-microvolt = <1350000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&uart7 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart7_pins_b>; ++ status = "disabled"; +}; + -+&vdd { -+ lp-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; ++&usart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usart3_pins_b>; ++ uart-has-rtscts; ++ status = "disabled"; +}; + -+&v3v3 { -+ lp-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&usbotg_hs { ++ phys = <&usbphyc_port1 0>; ++ phy-names = "usb2-phy"; ++ usb-role-switch; ++ status = "okay"; +}; + -+&v1v8_audio { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&usbphyc { ++ status = "okay"; +}; + -+&v3v3_hdmi { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&usbphyc_port0 { ++ phy-supply = <&vdd_usb>; +}; + -+&vtt_ddr { -+ lp-stop { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&usbphyc_port1 { ++ phy-supply = <&vdd_usb>; +}; -+ -+&vdd_usb { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdda { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v1v2_hdmi { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vref_ddr { -+ lp-stop { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts +diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi new file mode 100644 -index 0000000..fdcf4c8 +index 000000000..dd921908b --- /dev/null -+++ b/fdts/stm32mp157c-dk2.dts -@@ -0,0 +1,16 @@ ++++ b/fdts/stm32mp15xx-edx.dtsi +@@ -0,0 +1,479 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue . ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. + */ + -+/dts-v1/; -+ -+#include "stm32mp157a-dk1.dts" ++#include ++#include ++#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + +/ { -+ model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; -+ compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; -+ -+}; -+ -diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts -index e3dabe8..0daf4be 100644 ---- a/fdts/stm32mp157c-ed1.dts -+++ b/fdts/stm32mp157c-ed1.dts -@@ -1,24 +1,30 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* -- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved - * Author: Ludovic Barre for STMicroelectronics. - */ -- - /dts-v1/; - - #include "stm32mp157c.dtsi" - #include "stm32mp157caa-pinctrl.dtsi" - - / { -- model = "STMicroelectronics STM32MP157C-ED1 pmic eval daughter"; -+ model = "STMicroelectronics STM32MP157C eval daughter"; - compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; - - chosen { -- bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram"; -- stdout-path = "serial3:115200n8"; -+ stdout-path = "serial0:115200n8"; ++ memory@c0000000 { ++ device_type = "memory"; ++ reg = <0xC0000000 0x40000000>; + }; + -+ aliases { -+ serial0 = &uart4; - }; - }; - ++ vin: vin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vin"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++}; ++ ++&bsec { ++ board_id: board_id@ec { ++ reg = <0xec 0x4>; ++ st,non-secure-otp; ++ }; ++}; ++ +&clk_hse { + st,digbypass; +}; + - &i2c4 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c4_pins_a>; -@@ -26,37 +32,88 @@ - i2c-scl-falling-time-ns = <20>; - status = "okay"; - -- pmic: stpmu1@33 { -- compatible = "st,stpmu1"; ++&cpu0{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&hash1 { ++ status = "okay"; ++}; ++ ++&i2c4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c4_pins_a>; ++ i2c-scl-rising-time-ns = <185>; ++ i2c-scl-falling-time-ns = <20>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ secure-status = "okay"; ++ + pmic: stpmic@33 { + compatible = "st,stpmic1"; - reg = <0x33>; ++ reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; - status = "okay"; - -- st,main_control_register = <0x04>; -- st,vin_control_register = <0xc0>; -- st,usb_control_register = <0x30>; -+ st,main-control-register = <0x04>; -+ st,vin-control-register = <0xc0>; -+ st,usb-control-register = <0x20>; - - regulators { -- compatible = "st,stpmu1-regulators"; -+ compatible = "st,stpmic1-regulators"; ++ status = "okay"; ++ secure-status = "okay"; + ++ regulators { ++ compatible = "st,stpmic1-regulators"; ++ buck1-supply = <&vin>; ++ buck2-supply = <&vin>; ++ buck3-supply = <&vin>; ++ buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; ++ ldo4-supply = <&vin>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; ++ vref_ddr-supply = <&vin>; ++ boost-supply = <&vin>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; @@ -24139,6 +24751,20 @@ index e3dabe8..0daf4be 100644 + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ 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; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_ddr: buck2 { @@ -24148,6 +24774,21 @@ index e3dabe8..0daf4be 100644 + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ 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; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd: buck3 { @@ -24158,28 +24799,61 @@ index e3dabe8..0daf4be 100644 + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ 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; ++ }; ++ standby-ddr-off { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; + }; - - v3v3: buck4 { - regulator-name = "v3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; -- regulator-boot-on; ++ ++ v3v3: buck4 { ++ regulator-name = "v3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vtt_ddr: ldo3 { @@ -24187,406 +24861,309 @@ index e3dabe8..0daf4be 100644 + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; - regulator-over-current-protection; -- regulator-initial-mode = <8>; -- -- regulator-state-standby { -- regulator-suspend-microvolt = <3300000>; -- regulator-unchanged-in-suspend; -- regulator-mode = <8>; -- }; -- regulator-state-mem { -- regulator-off-in-suspend; -- }; -- regulator-state-disk { -- regulator-off-in-suspend; -- }; ++ regulator-over-current-protection; ++ lp-stop { ++ regulator-off-in-suspend; ++ }; ++ lplv-stop { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; - }; - - vdd_sd: ldo5 { -@@ -64,40 +121,49 @@ - regulator-min-microvolt = <2900000>; - regulator-max-microvolt = <2900000>; - regulator-boot-on; ++ regulator-always-on; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; - -- regulator-state-standby { -- regulator-suspend-microvolt = <2900000>; -- regulator-unchanged-in-suspend; -- }; -- regulator-state-mem { -- regulator-off-in-suspend; -- }; -- regulator-state-disk { -- regulator-off-in-suspend; -- }; ++ ++ vdd_sd: ldo5 { ++ regulator-name = "vdd_sd"; ++ regulator-min-microvolt = <2900000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-boot-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; - }; - }; - }; - }; - - &iwdg2 { -- instance = <2>; - timeout-sec = <32>; - status = "okay"; - }; - -+&pwr { -+ pwr-supply = <&vdd>; -+}; ++ lp-stop { ++ regulator-on-in-suspend; ++ }; ++ lplv-stop { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; + - &rng1 { - status = "okay"; - }; - -+&rtc { -+ status = "okay"; -+}; ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ }; + - &sdmmc1 { - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; - broken-cd; -- st,dirpol; -- st,negedge; -- st,pin-ckin; -+ st,sig-dir; -+ st,neg-edge; -+ st,use-ckin; - bus-width = <4>; -+ vmmc-supply = <&vdd_sd>; - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr50; -@@ -112,22 +178,25 @@ - non-removable; - no-sd; - no-sdio; -- st,dirpol; -- st,negedge; -+ st,neg-edge; - bus-width = <8>; -+ vmmc-supply = <&v3v3>; -+ vqmmc-supply = <&v3v3>; -+ mmc-ddr-3_3v; - status = "okay"; - }; - - &uart4 { - pinctrl-names = "default"; - pinctrl-0 = <&uart4_pins_a>; -- resets = <&rcc UART4_R>; - status = "okay"; - }; - - /* ATF Specific */ - #include -+#include - #include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" -+#include "stm32mp157c-security.dtsi" - - / { - aliases { -@@ -145,21 +214,18 @@ - gpio25 = &gpioz; - i2c3 = &i2c4; - }; -- -- soc { -- stgen: stgen@5C008000 { -- compatible = "st,stm32-stgen"; -- reg = <0x5C008000 0x1000>; -- status = "okay"; -- }; -- }; - }; - - /* CLOCK init */ - &rcc { -+ secure-status = "okay"; -+ st,hsi-cal; -+ st,csi-cal; -+ st,cal-sec = <60>; - st,clksrc = < - CLK_MPU_PLL1P - CLK_AXI_PLL2P -+ CLK_MCU_PLL3P - CLK_PLL12_HSE - CLK_PLL3_HSE - CLK_PLL4_HSE -@@ -171,6 +237,7 @@ - st,clkdiv = < - 1 /*MPU*/ - 0 /*AXI*/ -+ 0 /*MCU*/ - 1 /*APB1*/ - 1 /*APB2*/ - 1 /*APB3*/ -@@ -186,7 +253,7 @@ - CLK_FMC_ACLK - CLK_QSPI_ACLK - CLK_ETH_DISABLED -- CLK_SDMMC12_PLL3R -+ CLK_SDMMC12_PLL4P - CLK_DSI_DSIPLL - CLK_STGEN_HSE - CLK_USBPHY_HSE -@@ -195,7 +262,7 @@ - CLK_SPI45_HSI - CLK_SPI6_HSI - CLK_I2C46_HSI -- CLK_SDMMC3_PLL3R -+ CLK_SDMMC3_PLL4P - CLK_USBO_USBPHY - CLK_ADC_CKPER - CLK_CEC_LSE -@@ -206,17 +273,17 @@ - CLK_UART35_HSI - CLK_UART6_HSI - CLK_UART78_HSI -- CLK_SPDIF_PLL3Q -+ CLK_SPDIF_PLL4P - CLK_FDCAN_PLL4Q - CLK_SAI1_PLL3Q - CLK_SAI2_PLL3Q - CLK_SAI3_PLL3Q - CLK_SAI4_PLL3Q -- CLK_RNG1_CSI -- CLK_RNG2_CSI -+ CLK_RNG1_LSI -+ CLK_RNG2_LSI - CLK_LPTIM1_PCLK1 - CLK_LPTIM23_PCLK3 -- CLK_LPTIM45_PCLK3 -+ CLK_LPTIM45_LSE - >; - - /* VCO = 1300.0 MHz => P = 650 (CPU) */ -@@ -231,16 +298,167 @@ - frac = < 0x1400 >; - }; - -- /* VCO = 786.4 MHz => P = 197, Q = 49, R = 98 */ -+ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ - pll3: st,pll@2 { -- cfg = < 2 97 3 15 7 PQR(1,1,1) >; -- frac = < 0x9ba >; -+ cfg = < 1 33 1 16 36 PQR(1,1,1) >; -+ frac = < 0x1a04 >; - }; - -- /* VCO = 508.0 MHz => P = 56, Q = 56, R = 56 */ -+ /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ - pll4: st,pll@3 { -- cfg = < 5 126 8 8 8 PQR(1,1,1) >; -+ cfg = < 3 98 5 7 7 PQR(1,1,1) >; - }; - }; - --/delete-node/ &clk_csi; -+/* Security specific */ -+&etzpc { -+ st,decprot = < -+ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ >; ++ vbus_otg: pwr_sw1 { ++ regulator-name = "vbus_otg"; ++ }; ++ ++ vbus_sw: pwr_sw2 { ++ regulator-name = "vbus_sw"; ++ regulator-active-discharge = <1>; ++ }; ++ }; ++ }; +}; + +&iwdg2 { ++ timeout-sec = <32>; ++ status = "okay"; + secure-status = "okay"; +}; + -+&pwr { ++&nvmem_layout { ++ nvmem-cells = <&cfg0_otp>, ++ <&part_number_otp>, ++ <&monotonic_otp>, ++ <&nand_otp>, ++ <&uid_otp>, ++ <&package_otp>, ++ <&hw2_otp>, ++ <&pkh_otp>, ++ <&board_id>; ++ ++ nvmem-cell-names = "cfg0_otp", ++ "part_number_otp", ++ "monotonic_otp", ++ "nand_otp", ++ "uid_otp", ++ "package_otp", ++ "hw2_otp", ++ "pkh_otp", ++ "board_id"; ++}; ++ ++&pwr_regulators { + 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 = ; ++ vdd-supply = <&vdd>; ++ vdd_3v3_usbfs-supply = <&vdd_usb>; ++}; ++ ++&rcc { ++ st,hsi-cal; ++ st,csi-cal; ++ st,cal-sec = <60>; ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MCU_PLL3P ++ CLK_PLL12_HSE ++ CLK_PLL3_HSE ++ CLK_PLL4_HSE ++ CLK_RTC_LSE ++ CLK_MCO1_DISABLED ++ CLK_MCO2_DISABLED ++ >; ++ ++ st,clkdiv = < ++ 1 /*MPU*/ ++ 0 /*AXI*/ ++ 0 /*MCU*/ ++ 1 /*APB1*/ ++ 1 /*APB2*/ ++ 1 /*APB3*/ ++ 1 /*APB4*/ ++ 2 /*APB5*/ ++ 23 /*RTC*/ ++ 0 /*MCO1*/ ++ 0 /*MCO2*/ ++ >; ++ ++ st,pkcs = < ++ CLK_CKPER_HSE ++ CLK_FMC_ACLK ++ CLK_QSPI_ACLK ++ CLK_ETH_DISABLED ++ CLK_SDMMC12_PLL4P ++ CLK_DSI_DSIPLL ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_SPI2S1_PLL3Q ++ CLK_SPI2S23_PLL3Q ++ CLK_SPI45_HSI ++ CLK_SPI6_HSI ++ CLK_I2C46_HSI ++ CLK_SDMMC3_PLL4P ++ CLK_USBO_USBPHY ++ CLK_ADC_CKPER ++ CLK_CEC_LSE ++ CLK_I2C12_HSI ++ CLK_I2C35_HSI ++ CLK_UART1_HSI ++ CLK_UART24_HSI ++ CLK_UART35_HSI ++ CLK_UART6_HSI ++ CLK_UART78_HSI ++ CLK_SPDIF_PLL4P ++ CLK_FDCAN_PLL4R ++ CLK_SAI1_PLL3Q ++ CLK_SAI2_PLL3Q ++ CLK_SAI3_PLL3Q ++ CLK_SAI4_PLL3Q ++ CLK_RNG1_LSI ++ CLK_RNG2_LSI ++ CLK_LPTIM1_PCLK1 ++ CLK_LPTIM23_PCLK3 ++ CLK_LPTIM45_LSE ++ >; ++ ++ /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ ++ pll2: st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ cfg = <2 65 1 0 0 PQR(1,1,1)>; ++ frac = <0x1400>; ++ }; ++ ++ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ ++ pll3: st,pll@2 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ cfg = <1 33 1 16 36 PQR(1,1,1)>; ++ frac = <0x1a04>; ++ }; ++ ++ /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ ++ pll4: st,pll@3 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ cfg = <3 98 5 7 7 PQR(1,1,1)>; ++ }; ++}; ++ ++&rng1 { ++ status = "okay"; ++ secure-status = "okay"; ++}; ++ ++&rtc { ++ status = "okay"; ++ secure-status = "okay"; ++}; ++ ++&sdmmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; ++ disable-wp; ++ st,sig-dir; ++ st,neg-edge; ++ st,use-ckin; ++ bus-width = <4>; ++ vmmc-supply = <&vdd_sd>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-ddr50; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&sdmmc2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; ++ non-removable; ++ no-sd; ++ no-sdio; ++ st,neg-edge; ++ bus-width = <8>; ++ vmmc-supply = <&v3v3>; ++ vqmmc-supply = <&vdd>; ++ mmc-ddr-3_3v; ++ status = "okay"; +}; + +&timers15 { + secure-status = "okay"; + st,hsi-cal-input = <7>; -+ st,csi_cal-input = <8>; ++ st,csi-cal-input = <8>; +}; + -+/* Low-power states of regulators */ -+&vddcore { -+ lp-stop { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1200000>; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_pins_a>; ++ status = "okay"; +}; + -+&vdd_ddr { -+ lp-stop { -+ regulator-suspend-microvolt = <1350000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-suspend-microvolt = <1350000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; ++&usbotg_hs { ++ vbus-supply = <&vbus_otg>; +}; + -+&vdd { -+ lp-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; ++&usbphyc_port0 { ++ phy-supply = <&vdd_usb>; +}; + -+&v3v3 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdda { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v2v8 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vtt_ddr { -+ lp-stop { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdd_usb { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdd_sd { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v1v8 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vref_ddr { -+ lp-stop { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts -index 98a9d35..cfde8ed 100644 ---- a/fdts/stm32mp157c-ev1.dts -+++ b/fdts/stm32mp157c-ev1.dts -@@ -3,23 +3,65 @@ - * Copyright (C) STMicroelectronics 2017 - All Rights Reserved - * Author: Ludovic Barre for STMicroelectronics. - */ -- - /dts-v1/; -+ - #include "stm32mp157c-ed1.dts" - - / { -- model = "STMicroelectronics STM32MP157C-EV1 pmic eval daughter on eval mother"; -+ model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; - compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; - - chosen { -- bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram"; -- stdout-path = "serial3:115200n8"; -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial1 = &usart3; -+ }; ++&usbphyc_port1 { ++ phy-supply = <&vdd_usb>; +}; +diff --git a/fdts/stm32mp15xx-evx.dtsi b/fdts/stm32mp15xx-evx.dtsi +new file mode 100644 +index 000000000..fee2bac86 +--- /dev/null ++++ b/fdts/stm32mp15xx-evx.dtsi +@@ -0,0 +1,71 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ + +&fmc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fmc_pins_a>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + -+ nand: nand@0 { ++ nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; @@ -24594,6 +25171,16 @@ index 98a9d35..cfde8ed 100644 + }; +}; + ++&i2c4 { ++ pmic: stpmic@33 { ++ regulators { ++ v1v8: ldo6 { ++ regulator-enable-ramp-delay = <300000>; ++ }; ++ }; ++ }; ++}; ++ +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; @@ -24610,914 +25197,1167 @@ index 98a9d35..cfde8ed 100644 + #address-cells = <1>; + #size-cells = <1>; + }; ++}; + -+ flash1: mx66l51235l@1 { -+ compatible = "jedec,spi-nor"; -+ reg = <1>; -+ spi-rx-bus-width = <4>; -+ spi-max-frequency = <108000000>; -+ #address-cells = <1>; -+ #size-cells = <1>; - }; - }; - - &usart3 { - pinctrl-names = "default"; - pinctrl-0 = <&usart3_pins_a>; -- resets = <&rcc USART3_R>; - status = "disabled"; - }; -diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi ++&timers12 { ++ status = "disabled"; ++}; ++ ++&usart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usart3_pins_a>; ++ uart-has-rtscts; ++ status = "disabled"; ++}; ++ ++&usbotg_hs { ++ pinctrl-0 = <&usbotg_hs_pins_a>; ++ pinctrl-names = "default"; ++ phys = <&usbphyc_port1 0>; ++ phy-names = "usb2-phy"; ++ status = "okay"; ++}; ++ ++&usbphyc { ++ status = "okay"; ++}; +diff --git a/fdts/stm32mp15xxaa-pinctrl.dtsi b/fdts/stm32mp15xxaa-pinctrl.dtsi new file mode 100644 -index 0000000..8d45a33 +index 000000000..341529b30 --- /dev/null -+++ b/fdts/stm32mp157c-security.dtsi -@@ -0,0 +1,71 @@ ++++ b/fdts/stm32mp15xxaa-pinctrl.dtsi +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* -+ * Copyright : STMicroelectronics 2017 -+ * -+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue + */ + -+#include ++&pinctrl { ++ st,package = ; + -+/ { -+ soc { -+ iwdg1: iwdg@5C003000 { -+ compatible = "st,stm32mp1-iwdg"; -+ reg = <0x5C003000 0x400>; -+ clocks = <&rcc IWDG1>, <&rcc CK_LSI>; -+ clock-names = "pclk", "lsi"; -+ interrupts = ; -+ status = "disabled"; -+ secure-status = "disabled"; -+ }; ++ gpioa: gpio@50002000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 0 16>; ++ }; + -+ etzpc: etzpc@5C007000 { -+ compatible = "st,stm32-etzpc"; -+ reg = <0x5C007000 0x400>; -+ clocks = <&rcc TZPC>; -+ status = "disabled"; -+ secure-status = "okay"; -+ }; ++ gpiob: gpio@50003000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 16 16>; ++ }; + -+ stgen: stgen@5C008000 { -+ compatible = "st,stm32-stgen"; -+ reg = <0x5C008000 0x1000>; -+ }; ++ gpioc: gpio@50004000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 32 16>; ++ }; ++ ++ gpiod: gpio@50005000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 48 16>; ++ }; ++ ++ gpioe: gpio@50006000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 64 16>; ++ }; ++ ++ gpiof: gpio@50007000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 80 16>; ++ }; ++ ++ gpiog: gpio@50008000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 96 16>; ++ }; ++ ++ gpioh: gpio@50009000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 112 16>; ++ }; ++ ++ gpioi: gpio@5000a000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 128 16>; ++ }; ++ ++ gpioj: gpio@5000b000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 144 16>; ++ }; ++ ++ gpiok: gpio@5000c000 { ++ status = "okay"; ++ ngpios = <8>; ++ gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + -+&bsec { -+ mac_addr: mac_addr@e4 { -+ reg = <0xe4 0x6>; ++&pinctrl_z { ++ st,package = ; ++ ++ gpioz: gpio@54004000 { ++ status = "okay"; ++ secure-status = "okay"; ++ ngpios = <8>; ++ gpio-ranges = <&pinctrl_z 0 400 8>; + }; -+ /* Spare field to align on 32-bit OTP granularity */ -+ spare_ns_ea: spare_ns_ea@ea { -+ reg = <0xea 0x2>; ++}; +diff --git a/fdts/stm32mp15xxab-pinctrl.dtsi b/fdts/stm32mp15xxab-pinctrl.dtsi +new file mode 100644 +index 000000000..d29af8986 +--- /dev/null ++++ b/fdts/stm32mp15xxab-pinctrl.dtsi +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue ++ */ ++ ++&pinctrl { ++ st,package = ; ++ ++ gpioa: gpio@50002000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 0 16>; + }; -+ board_id: board_id@ec { -+ reg = <0xec 0x4>; ++ ++ gpiob: gpio@50003000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 16 16>; ++ }; ++ ++ gpioc: gpio@50004000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 32 16>; ++ }; ++ ++ gpiod: gpio@50005000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 48 16>; ++ }; ++ ++ gpioe: gpio@50006000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 64 16>; ++ }; ++ ++ gpiof: gpio@50007000 { ++ status = "okay"; ++ ngpios = <6>; ++ gpio-ranges = <&pinctrl 6 86 6>; ++ }; ++ ++ gpiog: gpio@50008000 { ++ status = "okay"; ++ ngpios = <10>; ++ gpio-ranges = <&pinctrl 6 102 10>; ++ }; ++ ++ gpioh: gpio@50009000 { ++ status = "okay"; ++ ngpios = <2>; ++ gpio-ranges = <&pinctrl 0 112 2>; ++ }; ++}; +diff --git a/fdts/stm32mp15xxac-pinctrl.dtsi b/fdts/stm32mp15xxac-pinctrl.dtsi +new file mode 100644 +index 000000000..02070bba5 +--- /dev/null ++++ b/fdts/stm32mp15xxac-pinctrl.dtsi +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue ++ */ ++ ++&pinctrl { ++ st,package = ; ++ ++ gpioa: gpio@50002000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 0 16>; ++ }; ++ ++ gpiob: gpio@50003000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 16 16>; ++ }; ++ ++ gpioc: gpio@50004000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 32 16>; ++ }; ++ ++ gpiod: gpio@50005000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 48 16>; ++ }; ++ ++ gpioe: gpio@50006000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 64 16>; ++ }; ++ ++ gpiof: gpio@50007000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 80 16>; ++ }; ++ ++ gpiog: gpio@50008000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 96 16>; ++ }; ++ ++ gpioh: gpio@50009000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 112 16>; ++ }; ++ ++ gpioi: gpio@5000a000 { ++ status = "okay"; ++ ngpios = <12>; ++ gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + -+&iwdg2 { -+ secure-interrupts = ; -+}; ++&pinctrl_z { ++ st,package = ; + -+&rcc { -+ secure-interrupts = ; -+ interrupt-names = "wakeup"; ++ gpioz: gpio@54004000 { ++ status = "okay"; ++ secure-status = "okay"; ++ ngpios = <8>; ++ gpio-ranges = <&pinctrl_z 0 400 8>; ++ }; +}; +diff --git a/fdts/stm32mp15xxad-pinctrl.dtsi b/fdts/stm32mp15xxad-pinctrl.dtsi +new file mode 100644 +index 000000000..023f5404c +--- /dev/null ++++ b/fdts/stm32mp15xxad-pinctrl.dtsi +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue ++ */ + -+&sdmmc1 { -+ compatible = "st,stm32-sdmmc2"; -+}; ++&pinctrl { ++ st,package = ; + -+&sdmmc2 { -+ compatible = "st,stm32-sdmmc2"; -+}; ++ gpioa: gpio@50002000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 0 16>; ++ }; + -+&tamp { -+ compatible = "st,stm32-tamp"; -+ clocks = <&rcc RTCAPB>; -+ interrupts = ; -+ secure-status= "disabled"; ++ gpiob: gpio@50003000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 16 16>; ++ }; ++ ++ gpioc: gpio@50004000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 32 16>; ++ }; ++ ++ gpiod: gpio@50005000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 48 16>; ++ }; ++ ++ gpioe: gpio@50006000 { ++ status = "okay"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 64 16>; ++ }; ++ ++ gpiof: gpio@50007000 { ++ status = "okay"; ++ ngpios = <6>; ++ gpio-ranges = <&pinctrl 6 86 6>; ++ }; ++ ++ gpiog: gpio@50008000 { ++ status = "okay"; ++ ngpios = <10>; ++ gpio-ranges = <&pinctrl 6 102 10>; ++ }; ++ ++ gpioh: gpio@50009000 { ++ status = "okay"; ++ ngpios = <2>; ++ gpio-ranges = <&pinctrl 0 112 2>; ++ }; +}; -diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi -index 8b13c0e..06c2cf1 100644 ---- a/fdts/stm32mp157c.dtsi -+++ b/fdts/stm32mp157c.dtsi -@@ -1,9 +1,9 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* -- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved - * Author: Ludovic Barre for STMicroelectronics. +diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h +index 20175481f..3aa7f9126 100644 +--- a/include/arch/aarch32/arch.h ++++ b/include/arch/aarch32/arch.h +@@ -457,13 +457,13 @@ + * system level implementation of the Generic Timer. + ******************************************************************************/ + /* Physical Count register. */ +-#define CNTPCT_LO U(0x0) ++#define CNTBASEN_CNTPCT_LO U(0x0) + /* Counter Frequency register. */ + #define CNTBASEN_CNTFRQ U(0x10) + /* Physical Timer CompareValue register. */ +-#define CNTP_CVAL_LO U(0x20) ++#define CNTBASEN_CNTP_CVAL_LO U(0x20) + /* Physical Timer Control register. */ +-#define CNTP_CTL U(0x2c) ++#define CNTBASEN_CNTP_CTL U(0x2c) + + /* Physical timer control register bit fields shifts and masks */ + #define CNTP_CTL_ENABLE_SHIFT 0 +@@ -522,6 +522,9 @@ + #define HSTR p15, 4, c1, c1, 3 + #define CNTHCTL p15, 4, c14, c1, 0 + #define CNTKCTL p15, 0, c14, c1, 0 ++#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 +@@ -531,6 +534,7 @@ + #define HTCR p15, 4, c2, c0, 2 + #define HMAIR0 p15, 4, c10, c2, 0 + #define ATS1CPR p15, 0, c7, c8, 0 ++#define ATS1CPW p15, 0, c7, c8, 1 + #define ATS1HR p15, 4, c7, c8, 0 + #define DBGOSDLR p14, 0, c1, c3, 4 + +@@ -581,6 +585,12 @@ + #define ICC_ASGI1R_EL1_64 p15, 1, c12 + #define ICC_SGI0R_EL1_64 p15, 2, c12 + ++/* Fault registers. The format is: coproc, opt1, CRn, CRm, opt2 */ ++#define DFSR p15, 0, c5, c0, 0 ++#define IFSR p15, 0, c5, c0, 1 ++#define DFAR p15, 0, c6, c0, 0 ++#define IFAR p15, 0, c6, c0, 2 ++ + /******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +@@ -634,6 +644,8 @@ + /* PAR fields */ + #define PAR_F_SHIFT U(0) + #define PAR_F_MASK ULL(0x1) ++#define PAR_NS_SHIFT U(9) ++#define PAR_NS_MASK U(0x1) + #define PAR_ADDR_SHIFT U(12) + #define PAR_ADDR_MASK (BIT_64(40) - ULL(1)) /* 40-bits-wide page address */ + +diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h +index cbac84b93..8749dc91d 100644 +--- a/include/arch/aarch32/arch_helpers.h ++++ b/include/arch/aarch32/arch_helpers.h +@@ -246,6 +246,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(cntp_tval, CNTP_TVAL) ++DEFINE_COPROCR_RW_FUNCS(cntp_ctl, CNTP_CTL) ++DEFINE_COPROCR_RW_FUNCS(cntv_ctl, CNTV_CTL) + DEFINE_COPROCR_RW_FUNCS(cnthp_ctl_el2, CNTHP_CTL) + DEFINE_COPROCR_RW_FUNCS(cnthp_tval_el2, CNTHP_TVAL) + DEFINE_COPROCR_RW_FUNCS_64(cnthp_cval_el2, CNTHP_CVAL_64) +@@ -288,6 +291,7 @@ DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) + * Address translation */ -- -+#include - #include - #include + DEFINE_COPROCR_WRITE_FUNC(ats1cpr, ATS1CPR) ++DEFINE_COPROCR_WRITE_FUNC(ats1cpw, ATS1CPW) + DEFINE_COPROCR_WRITE_FUNC(ats1hr, ATS1HR) + DEFINE_COPROCR_RW_FUNCS_64(par, PAR_64) -@@ -11,15 +11,12 @@ - #address-cells = <1>; - #size-cells = <1>; - -- aliases { -- serial0 = &usart1; -- serial1 = &usart2; -- serial2 = &usart3; -- serial3 = &uart4; -- serial4 = &uart5; -- serial5 = &usart6; -- serial6 = &uart7; -- serial7 = &uart8; -+ intc: interrupt-controller@a0021000 { -+ compatible = "arm,cortex-a7-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0xa0021000 0x1000>, -+ <0xa0022000 0x2000>; - }; - - clocks { -@@ -56,7 +53,7 @@ - clk_i2s_ckin: i2s_ckin { - #clock-cells = <0>; - compatible = "fixed-clock"; -- clock-frequency = <64000000>; -+ clock-frequency = <0>; - }; - - clk_dsi_phy: ck_dsi_phy { -@@ -64,31 +61,38 @@ - compatible = "fixed-clock"; - clock-frequency = <0>; - }; -- -- clk_usbo_48m: ck_usbo_48m { -- #clock-cells = <0>; -- compatible = "fixed-clock"; -- clock-frequency = <48000000>; -- }; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; -+ interrupt-parent = <&intc>; - ranges; - -+ timers12: timer@40006000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32-timers"; -+ reg = <0x40006000 0x400>; -+ clocks = <&rcc TIM12_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ - usart2: serial@4000e000 { -- compatible = "st,stm32h7-usart"; -+ compatible = "st,stm32h7-uart"; - reg = <0x4000e000 0x400>; - clocks = <&rcc USART2_K>; -+ resets = <&rcc USART2_R>; - status = "disabled"; - }; - - usart3: serial@4000f000 { -- compatible = "st,stm32h7-usart"; -+ compatible = "st,stm32h7-uart"; - reg = <0x4000f000 0x400>; - clocks = <&rcc USART3_K>; -+ resets = <&rcc USART3_R>; - status = "disabled"; - }; - -@@ -96,6 +100,7 @@ - compatible = "st,stm32h7-uart"; - reg = <0x40010000 0x400>; - clocks = <&rcc UART4_K>; -+ resets = <&rcc UART4_R>; - status = "disabled"; - }; - -@@ -103,6 +108,7 @@ - compatible = "st,stm32h7-uart"; - reg = <0x40011000 0x400>; - clocks = <&rcc UART5_K>; -+ resets = <&rcc UART5_R>; - status = "disabled"; - }; - -@@ -111,6 +117,7 @@ - compatible = "st,stm32h7-uart"; - reg = <0x40018000 0x400>; - clocks = <&rcc UART7_K>; -+ resets = <&rcc UART7_R>; - status = "disabled"; - }; - -@@ -118,21 +125,34 @@ - compatible = "st,stm32h7-uart"; - reg = <0x40019000 0x400>; - clocks = <&rcc UART8_K>; -+ resets = <&rcc UART8_R>; - status = "disabled"; - }; - - usart6: serial@44003000 { -- compatible = "st,stm32h7-usart"; -+ compatible = "st,stm32h7-uart"; - reg = <0x44003000 0x400>; - clocks = <&rcc USART6_K>; -+ resets = <&rcc USART6_R>; -+ status = "disabled"; -+ }; -+ -+ timers15: timer@44006000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32-timers"; -+ reg = <0x44006000 0x400>; -+ clocks = <&rcc TIM15_K>; -+ clock-names = "int"; - status = "disabled"; - }; - - sdmmc3: sdmmc@48004000 { -- compatible = "st,stm32-sdmmc2"; -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; - reg = <0x48004000 0x400>, <0x48005000 0x400>; -- reg-names = "sdmmc", "delay"; - clocks = <&rcc SDMMC3_K>; -+ clock-names = "apb_pclk"; - resets = <&rcc SDMMC3_R>; - cap-sd-highspeed; - cap-mmc-highspeed; -@@ -140,18 +160,69 @@ - status = "disabled"; - }; - -+ usbotg_hs: usb-otg@49000000 { -+ compatible = "st,stm32mp1-hsotg", "snps,dwc2"; -+ reg = <0x49000000 0x10000>; -+ clocks = <&rcc USBO_K>; -+ clock-names = "otg"; -+ resets = <&rcc USBO_R>; -+ reset-names = "dwc2"; -+ status = "disabled"; -+ }; -+ - rcc: rcc@50000000 { -- compatible = "syscon", "st,stm32mp1-rcc"; -+ compatible = "st,stm32mp1-rcc", "syscon"; -+ reg = <0x50000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; -- reg = <0x50000000 0x1000>; -+ interrupts = ; -+ }; -+ -+ pwr: pwr@50001000 { -+ compatible = "st,stm32mp1-pwr", "syscon", "simple-mfd"; -+ reg = <0x50001000 0x400>; - }; - -- rcc_reboot: rcc-reboot@50000000 { -- compatible = "syscon-reboot"; -- regmap = <&rcc>; -- offset = <0x404>; -- mask = <0x1>; -+ exti: interrupt-controller@5000d000 { -+ compatible = "st,stm32mp1-exti", "syscon"; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x5000d000 0x400>; -+ -+ /* exti_pwr is an extra interrupt controller used for -+ * EXTI 55 to 60. It's mapped on pwr interrupt -+ * controller. -+ */ -+ exti_pwr: exti-pwr { -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupt-parent = <&pwr>; -+ st,irq-number = <6>; -+ }; -+ }; -+ -+ syscfg: syscon@50020000 { -+ compatible = "st,stm32mp157-syscfg", "syscon"; -+ reg = <0x50020000 0x400>; -+ clocks = <&rcc SYSCFG>; -+ }; -+ -+ cryp1: cryp@54001000 { -+ compatible = "st,stm32mp1-cryp"; -+ reg = <0x54001000 0x400>; -+ interrupts = ; -+ clocks = <&rcc CRYP1>; -+ resets = <&rcc CRYP1_R>; -+ status = "disabled"; -+ }; -+ -+ hash1: hash@54002000 { -+ compatible = "st,stm32f756-hash"; -+ reg = <0x54002000 0x400>; -+ interrupts = ; -+ clocks = <&rcc HASH1>; -+ resets = <&rcc HASH1_R>; -+ status = "disabled"; - }; - - rng1: rng@54003000 { -@@ -162,13 +233,15 @@ - status = "disabled"; - }; - -- fmc_nand: fmc_nand@58002000 { -- compatible = "st,stm32mp1-fmc"; -+ fmc: nand-controller@58002000 { -+ compatible = "st,stm32mp15-fmc2"; - reg = <0x58002000 0x1000>, -- <0x80000000 0x40000>, -- <0x81000000 0x40000>, -- <0x88000000 0x40000>, -- <0x89000000 0x40000>; -+ <0x80000000 0x1000>, -+ <0x88010000 0x1000>, -+ <0x88020000 0x1000>, -+ <0x81000000 0x1000>, -+ <0x89010000 0x1000>, -+ <0x89020000 0x1000>; - clocks = <&rcc FMC_K>; - resets = <&rcc FMC_R>; - status = "disabled"; -@@ -177,15 +250,18 @@ - qspi: qspi@58003000 { - compatible = "st,stm32f469-qspi"; - reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; -+ reg-names = "qspi", "qspi_mm"; - clocks = <&rcc QSPI_K>; -+ resets = <&rcc QSPI_R>; - status = "disabled"; - }; - - sdmmc1: sdmmc@58005000 { -- compatible = "st,stm32-sdmmc2"; -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; - reg = <0x58005000 0x1000>, <0x58006000 0x1000>; -- reg-names = "sdmmc", "delay"; - clocks = <&rcc SDMMC1_K>; -+ clock-names = "apb_pclk"; - resets = <&rcc SDMMC1_R>; - cap-sd-highspeed; - cap-mmc-highspeed; -@@ -194,10 +270,11 @@ - }; - - sdmmc2: sdmmc@58007000 { -- compatible = "st,stm32-sdmmc2"; -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; - reg = <0x58007000 0x1000>, <0x58008000 0x1000>; -- reg-names = "sdmmc", "delay"; - clocks = <&rcc SDMMC2_K>; -+ clock-names = "apb_pclk"; - resets = <&rcc SDMMC2_R>; - cap-sd-highspeed; - cap-mmc-highspeed; -@@ -205,7 +282,7 @@ - status = "disabled"; - }; - -- iwdg2: iwdg@5a002000 { -+ iwdg2: watchdog@5a002000 { - compatible = "st,stm32mp1-iwdg"; - reg = <0x5a002000 0x400>; - clocks = <&rcc IWDG2>, <&rcc CK_LSI>; -@@ -214,15 +291,34 @@ - }; - - usart1: serial@5c000000 { -- compatible = "st,stm32h7-usart"; -+ compatible = "st,stm32h7-uart"; - reg = <0x5c000000 0x400>; -+ interrupt-names = "event", "wakeup"; -+ interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 26 1>; - clocks = <&rcc USART1_K>; -+ resets = <&rcc USART1_R>; -+ status = "disabled"; -+ }; -+ -+ spi6: spi@5c001000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32h7-spi"; -+ reg = <0x5c001000 0x400>; -+ interrupts = ; -+ clocks = <&rcc SPI6_K>; -+ resets = <&rcc SPI6_R>; - status = "disabled"; - }; - - i2c4: i2c@5c002000 { - compatible = "st,stm32f7-i2c"; - reg = <0x5c002000 0x400>; -+ interrupt-names = "event", "error", "wakeup"; -+ interrupts-extended = <&intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 24 1>; - clocks = <&rcc I2C4_K>; - resets = <&rcc I2C4_R>; - #address-cells = <1>; -@@ -235,6 +331,41 @@ - reg = <0x5c004000 0x400>; - clocks = <&rcc RTCAPB>, <&rcc RTC>; - clock-names = "pclk", "rtc_ck"; -+ interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 19 1>; -+ status = "disabled"; -+ }; -+ -+ bsec: nvmem@5c005000 { -+ compatible = "st,stm32mp15-bsec"; -+ reg = <0x5c005000 0x400>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ts_cal1: calib@5c { -+ reg = <0x5c 0x2>; -+ }; -+ ts_cal2: calib@5e { -+ reg = <0x5e 0x2>; -+ }; -+ }; -+ -+ i2c6: i2c@5c009000 { -+ compatible = "st,stm32f7-i2c"; -+ reg = <0x5c009000 0x400>; -+ interrupt-names = "event", "error", "wakeup"; -+ interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 54 1>; -+ clocks = <&rcc I2C6_K>; -+ resets = <&rcc I2C6_R>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ tamp: tamp@5c00a000 { -+ compatible = "simple-bus", "syscon", "simple-mfd"; -+ reg = <0x5c00a000 0x400>; - }; - }; - }; -diff --git a/fdts/stm32mp157caa-pinctrl.dtsi b/fdts/stm32mp157caa-pinctrl.dtsi -index 774561a..9b9cd08 100644 ---- a/fdts/stm32mp157caa-pinctrl.dtsi -+++ b/fdts/stm32mp157caa-pinctrl.dtsi -@@ -7,8 +7,8 @@ - #include "stm32mp157-pinctrl.dtsi" - / { - soc { -- pinctrl: pin-controller { -- compatible = "st,stm32mp157caa-pinctrl"; -+ pinctrl: pin-controller@50002000 { -+ st,package = ; - - gpioa: gpio@50002000 { - status = "okay"; -@@ -77,8 +77,8 @@ - }; - }; - -- pinctrl_z: pin-controller-z { -- compatible = "st,stm32mp157caa-z-pinctrl"; -+ pinctrl_z: pin-controller-z@54004000 { -+ st,package = ; - - gpioz: gpio@54004000 { - status = "okay"; -diff --git a/fdts/stm32mp157cab-pinctrl.dtsi b/fdts/stm32mp157cab-pinctrl.dtsi -new file mode 100644 -index 0000000..c570cf9 ---- /dev/null -+++ b/fdts/stm32mp157cab-pinctrl.dtsi -@@ -0,0 +1,62 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <6>; -+ gpio-ranges = <&pinctrl 6 86 6>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <10>; -+ gpio-ranges = <&pinctrl 6 102 10>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <2>; -+ gpio-ranges = <&pinctrl 0 112 2>; -+ }; -+ }; -+ }; -+}; -diff --git a/fdts/stm32mp157cac-pinctrl.dtsi b/fdts/stm32mp157cac-pinctrl.dtsi -new file mode 100644 -index 0000000..777f991 ---- /dev/null -+++ b/fdts/stm32mp157cac-pinctrl.dtsi -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 80 16>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 96 16>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 112 16>; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ status = "okay"; -+ ngpios = <12>; -+ gpio-ranges = <&pinctrl 0 128 12>; -+ }; -+ }; -+ -+ pinctrl_z: pin-controller-z@54004000 { -+ st,package = ; -+ -+ gpioz: gpio@54004000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl_z 0 400 8>; -+ }; -+ }; -+ }; -+}; -diff --git a/fdts/stm32mp157cad-pinctrl.dtsi b/fdts/stm32mp157cad-pinctrl.dtsi -new file mode 100644 -index 0000000..c4c303a ---- /dev/null -+++ b/fdts/stm32mp157cad-pinctrl.dtsi -@@ -0,0 +1,62 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <6>; -+ gpio-ranges = <&pinctrl 6 86 6>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <10>; -+ gpio-ranges = <&pinctrl 6 102 10>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <2>; -+ gpio-ranges = <&pinctrl 0 112 2>; -+ }; -+ }; -+ }; -+}; -diff --git a/include/common/aarch32/console_macros.S b/include/common/aarch32/console_macros.S -new file mode 100644 -index 0000000..7c30688 ---- /dev/null -+++ b/include/common/aarch32/console_macros.S -@@ -0,0 +1,84 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+#ifndef __CONSOLE_MACROS_S__ -+#define __CONSOLE_MACROS_S__ -+ -+#include -+ -+/* -+ * This macro encapsulates the common setup that has to be done at the end of -+ * a console driver's register function. It will register all of the driver's -+ * callbacks in the console_t structure and initialize the flags field (by -+ * default consoles are enabled for the "boot" and "crash" states, this can be -+ * changed after registration with the console_set_scope() function). It ends -+ * with a tail call that will include return to the caller. -+ * REQUIRES console_t pointer in x0 and a valid return address in x30. -+ */ -+/* -+ * The USE_FINISH_CONSOLE_REG_2 guard is introduced to allow selection between -+ * the 2 variants of the finish_console_register macro and will be removed -+ * once the deprecated variant is removed. -+ */ -+#ifndef USE_FINISH_CONSOLE_REG_2 -+#if !ERROR_DEPRECATED -+ /* This version of the macro is deprecated. Use the new version */ -+ .macro finish_console_register _driver -+ /* -+ * Add these weak definitions so we will automatically write a 0 if the -+ * function doesn't exist. I'd rather use .ifdef but that only works if -+ * the function was defined (not just declared .global) above this point -+ * in the file, which we can't guarantee. -+ */ -+ .weak console_\_driver\()_putc -+ .weak console_\_driver\()_getc -+ .weak console_\_driver\()_flush -+ -+ /* Don't use adrp on weak funcs! See GNU ld bugzilla issue 22589. */ -+ ldr r1, =console_\_driver\()_putc -+ str r1, [r0, #CONSOLE_T_PUTC] -+ ldr r1, =console_\_driver\()_getc -+ str r1, [r0, #CONSOLE_T_GETC] -+ ldr r1, =console_\_driver\()_flush -+ str r1, [r0, #CONSOLE_T_FLUSH] -+ mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) -+ str r1, [r0, #CONSOLE_T_FLAGS] -+ b console_register -+ .endm -+#endif /* ERROR_DEPRECATED */ -+#else /* USE_FINISH_CONSOLE_REG_2 */ -+ /* The new version of the macro not using weak references */ -+ .macro finish_console_register _driver, putc=0, getc=0, flush=0 -+ /* -+ * If any of the callback is not specified or set as 0, then the -+ * corresponding callback entry in console_t is set to 0. -+ */ -+ .ifne \putc -+ ldr r1, =console_\_driver\()_putc -+ .else -+ mov r1, #0 -+ .endif -+ str r1, [r0, #CONSOLE_T_PUTC] -+ -+ .ifne \getc -+ ldr r1, =console_\_driver\()_getc -+ .else -+ mov r1, #0 -+ .endif -+ str r1, [r0, #CONSOLE_T_GETC] -+ -+ .ifne \flush -+ ldr r1, =console_\_driver\()_flush -+ .else -+ mov r1, #0 -+ .endif -+ str r1, [r0, #CONSOLE_T_FLUSH] -+ -+ mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) -+ str r1, [r0, #CONSOLE_T_FLAGS] -+ b console_register -+ .endm -+#endif /* USE_FINISH_CONSOLE_REG_2 */ -+#endif /* __CONSOLE_MACROS_S__ */ -diff --git a/include/common/aarch64/console_macros.S b/include/common/aarch64/console_macros.S -index 0ebea2c..b285ecc 100644 ---- a/include/common/aarch64/console_macros.S -+++ b/include/common/aarch64/console_macros.S +diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S +index 7559de446..4fd746d5a 100644 +--- a/include/arch/aarch32/el3_common_macros.S ++++ b/include/arch/aarch32/el3_common_macros.S @@ -1,5 +1,5 @@ /* -- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -@@ -17,6 +17,14 @@ - * with a tail call that will include return to the caller. - * REQUIRES console_t pointer in x0 and a valid return address in x30. - */ +@@ -329,6 +329,11 @@ + bl inv_dcache_range + #endif + ++ /* ++ * zeromem uses r12 whereas it is used to save previous BL arg3, ++ * save it in r7 ++ */ ++ mov r7, r12 + ldr r0, =__BSS_START__ + ldr r1, =__BSS_SIZE__ + bl zeromem +@@ -339,6 +344,9 @@ + bl zeromem + #endif + ++ /* Restore r12 */ ++ mov r12, r7 ++ + #if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM) + /* ----------------------------------------------------- + * Copy data from ROM to RAM. +diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h +index 3ff2912f1..307dad585 100644 +--- a/include/arch/aarch64/arch.h ++++ b/include/arch/aarch64/arch.h +@@ -670,13 +670,13 @@ + * system level implementation of the Generic Timer. + ******************************************************************************/ + /* Physical Count register. */ +-#define CNTPCT_LO U(0x0) ++#define CNTBASEN_CNTPCT_LO U(0x0) + /* Counter Frequency register. */ + #define CNTBASEN_CNTFRQ U(0x10) + /* Physical Timer CompareValue register. */ +-#define CNTP_CVAL_LO U(0x20) ++#define CNTBASEN_CNTP_CVAL_LO U(0x20) + /* Physical Timer Control register. */ +-#define CNTP_CTL U(0x2c) ++#define CNTBASEN_CNTP_CTL U(0x2c) + + /* PMCR_EL0 definitions */ + #define PMCR_EL0_RESET_VAL U(0x0) +diff --git a/include/common/confine_array_index.h b/include/common/confine_array_index.h +new file mode 100644 +index 000000000..23c8b4e67 +--- /dev/null ++++ b/include/common/confine_array_index.h +@@ -0,0 +1,145 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* Copyright (c) 2020 Linaro Limited */ ++// Copyright 2019 The Fuchsia Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ +/* -+ * The USE_FINISH_CONSOLE_REG_2 guard is introduced to allow selection between -+ * the 2 variants of the finish_console_register macro and will be removed -+ * once the deprecated variant is removed. ++ * Content of LICENSE file mentioned above: ++Copyright 2019 The Fuchsia Authors. All rights reserved. ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are ++met: ++ * Redistributions of source code must retain the above copyright ++notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above ++copyright notice, this list of conditions and the following disclaimer ++in the documentation and/or other materials provided with the ++distribution. ++ * Neither the name of Google Inc. nor the names of its ++contributors may be used to endorse or promote products derived from ++this software without specific prior written permission. ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ -+#ifndef USE_FINISH_CONSOLE_REG_2 -+#if !ERROR_DEPRECATED -+ /* This version of the macro is deprecated. Use the new version */ - .macro finish_console_register _driver - /* - * Add these weak definitions so we will automatically write a 0 if the -@@ -39,5 +47,41 @@ - str x1, [x0, #CONSOLE_T_FLAGS] - b console_register - .endm -+#endif /* ERROR_DEPRECATED */ -+#else /* USE_FINISH_CONSOLE_REG_2 */ -+ /* The new version of the macro not using weak references */ -+ .macro finish_console_register _driver, putc=0, getc=0, flush=0 ++#ifndef FBL_CONFINE_ARRAY_INDEX_H_ ++#define FBL_CONFINE_ARRAY_INDEX_H_ ++ ++#include ++ ++// confine_array_index() bounds-checks and sanitizes an array index safely in the presence of ++// speculative execution information leak bugs such as Spectre V1. confine_array_index() always ++// returns a sanitized index, even in speculative-path execution. ++// ++// Callers need to combine confine_array_index with a conventional bounds check; the bounds ++// check will return any necessary errors in the nonspeculative path, confine_array_index will ++// confine indexes in the speculative path. ++// ++// Use: ++// confine_array_index() returns |index|, if it is < size, or 0 if |index| is >= size. ++// ++// Example (may leak table1 contents): ++// 1: int lookup3(size_t index) { ++// 2: if (index >= table1_size) { ++// 3: return -1; ++// 4: } ++// 5: size_t index2 = table1[index]; ++// 6: return table2[index2]; ++// 7: } ++// ++// Converted: ++// ++// 1: int lookup3(size_t index) { ++// 2: if (index >= table1_size) { ++// 3: return -1; ++// 4: } ++// 5: size_t safe_index = confine_array_index(index, table1_size); ++// 6: size_t index2 = table1[safe_index]; ++// 7: return table2[index2]; ++// 8: } ++#ifdef __aarch64__ ++static inline size_t confine_array_index(size_t index, size_t size) { ++ size_t safe_index; ++ // Use a conditional select and a CSDB barrier to enforce validation of |index|. ++ // See "Cache Speculation Side-channels" whitepaper, section "Software Mitigation". ++ // "" The combination of both a conditional select/conditional move and the new barrier are ++ // sufficient to address this problem on ALL Arm implementations... "" ++ asm( ++ "cmp %1, %2\n" // %1 holds the unsanitized index ++ "csel %0, %1, xzr, lo\n" // Select index or zero based on carry (%1 within range) ++ "csdb\n" ++ : "=r"(safe_index) ++ : "r"(index), "r"(size) ++ : "cc"); ++ return safe_index; ++} ++#endif ++#ifdef __arm__ ++static inline size_t confine_array_index(size_t index, size_t size) ++{ ++ size_t ret_val = index; ++ + /* -+ * If any of the callback is not specified or set as 0, then the -+ * corresponding callback entry in console_t is set to 0. ++ * For the ARMv7/AArch32 case we're basing the select and barrier ++ * code on __load_no_speculate1() in as we ++ * lack the csel instruction. + */ -+ .ifne \putc -+ adrp x1, console_\_driver\()_putc -+ add x1, x1, :lo12:console_\_driver\()_putc -+ str x1, [x0, #CONSOLE_T_PUTC] -+ .else -+ str xzr, [x0, #CONSOLE_T_PUTC] -+ .endif + -+ .ifne \getc -+ adrp x1, console_\_driver\()_getc -+ add x1, x1, :lo12:console_\_driver\()_getc -+ str x1, [x0, #CONSOLE_T_GETC] -+ .else -+ str xzr, [x0, #CONSOLE_T_GETC] -+ .endif - -+ .ifne \flush -+ adrp x1, console_\_driver\()_flush -+ add x1, x1, :lo12:console_\_driver\()_flush -+ str x1, [x0, #CONSOLE_T_FLUSH] -+ .else -+ str xzr, [x0, #CONSOLE_T_FLUSH] -+ .endif ++#ifdef __thumb2__ ++ asm volatile ( ++ ".syntax unified\n" ++ "cmp %0, %1\n" ++ "it cs\n" ++#ifdef __clang__ ++#pragma clang diagnostic push ++ /* Avoid 'deprecated instruction in IT block [-Werror,-Winline-asm]' */ ++#pragma clang diagnostic ignored "-Winline-asm" ++#endif ++ "movcs %0, #0\n" ++#ifdef __clang__ ++#pragma clang diagnostic pop ++#endif ++ ".inst.n 0xf3af\t@ CSDB\n" ++ ".inst.n 0x8014\t@ CSDB" ++ : "+r" (ret_val) : "r" (size) : "cc"); ++#else ++ asm volatile ( ++ ".syntax unified\n" ++ "cmp %0, %1\n" /* %0 holds the unsanitized index */ ++ "movcs %0, #0\n" ++ ".inst 0xe320f014\t@ CSDB" ++ : "+r" (ret_val) : "r" (size) : "cc"); ++#endif + -+ mov x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) -+ str x1, [x0, #CONSOLE_T_FLAGS] -+ b console_register -+ .endm -+#endif /* USE_FINISH_CONSOLE_REG_2 */ - #endif /* __CONSOLE_MACROS_S__ */ -diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h -index a97914d..96bfb53 100644 ---- a/include/common/tbbr/tbbr_img_def.h -+++ b/include/common/tbbr/tbbr_img_def.h -@@ -77,7 +77,13 @@ - /* NT_FW_CONFIG */ - #define NT_FW_CONFIG_ID U(27) - -+/* GPT Partition */ -+#define GPT_IMAGE_ID U(28) ++ return ret_val; ++} ++#endif /* __arm__ */ + -+/* Binary with STM32 header */ -+#define STM32_IMAGE_ID U(29) ++#ifdef __x86_64__ ++static inline size_t confine_array_index(size_t index, size_t size) { ++ size_t safe_index = 0; ++ // Use a conditional move to enforce validation of |index|. ++ // The conditional move has a data dependency on the result of a comparison and cannot ++ // execute until the comparison is resolved. ++ // See "Software Techniques for Managing Speculation on AMD Processors", Mitigation V1-2. ++ // See "Analyzing potential bounds check bypass vulnerabilities", Revision 002, ++ // Section 5.2 Bounds clipping ++ __asm__( ++ "cmp %1, %2\n" ++ "cmova %1, %0\n" // Select between $0 and |index| ++ : "+r"(safe_index) ++ : "r"(index), "r"(size) ++ : "cc"); ++ return safe_index; ++} ++#endif ++#endif // FBL_CONFINE_ARRAY_INDEX_H_ +diff --git a/include/common/speculation_barrier.h b/include/common/speculation_barrier.h +new file mode 100644 +index 000000000..ef74e3617 +--- /dev/null ++++ b/include/common/speculation_barrier.h +@@ -0,0 +1,508 @@ ++/* SPDX-License-Identifier: BSL-1.0 */ ++/* Copyright (c) 2017 Arm Limited. All rights reserved. + - /* Define size of the array */ --#define MAX_NUMBER_IDS U(28) -+#define MAX_NUMBER_IDS U(30) - - #endif /* __TBBR_IMG_DEF_H__ */ ++ Boost Software License - Version 1.0 - August 17th, 2003 ++ ++ Permission is hereby granted, free of charge, to any person or organization ++ obtaining a copy of the software and accompanying documentation covered by ++ this license (the "Software") to use, reproduce, display, distribute, ++ execute, and transmit the Software, and to prepare derivative works of the ++ Software, and to permit third-parties to whom the Software is furnished to do ++ so, all subject to the following: ++ ++ The copyright notices in the Software and this entire statement, including ++ the above license grant, this restriction and the following disclaimer, must ++ be included in all copies of the Software, in whole or in part, and all ++ derivative works of the Software, unless such copies or derivative works are ++ solely in the form of machine-executable object code generated by a source ++ language processor. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ++ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ++ ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ DEALINGS IN THE SOFTWARE. */ ++ ++ ++#ifdef __HAVE_LOAD_NO_SPECULATE ++#define load_no_speculate(__ptr, __low, __high) \ ++(__extension__ ({ \ ++ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ ++ __builtin_load_no_speculate (__ptr_once, __low, __high, \ ++ 0, __ptr_once); \ ++})) ++ ++#define load_no_speculate_fail(__ptr, __low, __high, __failval) \ ++(__extension__ ({ \ ++ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ ++ __builtin_load_no_speculate (__ptr_once, __low, __high, \ ++ __failval, __ptr_once); \ ++})) ++ ++#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ ++ (__builtin_load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) ++ ++#else ++ ++#ifdef __GNUC__ ++#define __UNUSED __attribute__((unused)) ++#else ++#define __UNUSED ++#endif ++ ++#ifdef __aarch64__ ++ ++#define __load_no_speculate1(__ptr, __low, __high, __failval, \ ++ __cmpptr, __w, __sz) \ ++(__extension__ ({ \ ++ __typeof__ (0 + (*(__ptr))) __nln_val; \ ++ /* This typecasting is required to ensure correct handling of upper \ ++ bits of failval, to ensure a clean return from the CSEL below. */ \ ++ __typeof__(*(__ptr)) __fv \ ++ = (__typeof__(*(__ptr)))(unsigned long long) (__failval); \ ++ /* If __high is explicitly NULL, we must not emit the \ ++ upper-bound comparison. We need to cast __high to an \ ++ unsigned long long before handing it to __builtin_constant_p to \ ++ ensure that clang/llvm correctly detects NULL as a constant if it \ ++ is defined as (void*) 0. */ \ ++ if (__builtin_constant_p ((unsigned long long)__high) \ ++ && __high == ((void *)0)) \ ++ { \ ++ __asm__ volatile ( \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "bcc\t.ns%=\n\t" \ ++ "ldr" __sz "\t%" __w "[__v], %[__p]\n" \ ++ ".ns%=:\n\t" \ ++ "csel\t%" __w "[__v], %" __w "[__v], %" __w "[__f], cs\n\t" \ ++ "hint\t#0x14 // CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&r" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "m" (*(__ptr)), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "rZ" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ else \ ++ { \ ++ __asm__ volatile ( \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "ccmp\t%[__c], %[__h], 2, cs\n\t" \ ++ "bcs\t.ns%=\n\t" \ ++ "ldr" __sz "\t%" __w "[__v], %[__p]\n" \ ++ ".ns%=:\n\t" \ ++ "csel\t%" __w "[__v], %" __w "[__v], %" __w "[__f], cc\n\t" \ ++ "hint\t#0x14 // CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&r" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ [__h] "r" (__high), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "m" (*(__ptr)), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "rZ" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ (__typeof__ (*(__ptr))) __nln_val; \ ++})) ++ ++#define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ ++(__extension__ ({ \ ++ __typeof__ (0 + *(__ptr)) __nl_val; \ ++ \ ++ switch (sizeof(*(__ptr))) { \ ++ case 1: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, "w", "b"); \ ++ break; \ ++ case 2: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, "w", "h"); \ ++ break; \ ++ case 4: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, "w", ""); \ ++ break; \ ++ case 8: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, "x", ""); \ ++ break; \ ++ default: \ ++ { \ ++ char __static_assert_no_speculate_load_size_too_big \ ++ [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ ++ break; \ ++ } \ ++ } \ ++ \ ++ (__typeof__ (*(__ptr))) __nl_val; \ ++})) ++ ++#define load_no_speculate(__ptr, __low, __high) \ ++(__extension__ ({ \ ++ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ ++ __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ ++})) ++ ++#define load_no_speculate_fail(__ptr, __low, __high, __failval) \ ++(__extension__ ({ \ ++ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ ++ __load_no_speculate (__ptr_once, __low, __high, \ ++ __failval, __ptr_once); \ ++})) ++ ++#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ ++ (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) ++ ++/* AArch32 support for ARM and Thumb-2. Thumb-1 is not supported. */ ++#elif defined (__ARM_32BIT_STATE) && (defined (__thumb2__) || !defined (__thumb__)) ++#ifdef __thumb2__ ++/* Thumb2 case. */ ++ ++#define __load_no_speculate1(__ptr, __low, __high, __failval, \ ++ __cmpptr, __sz) \ ++(__extension__ ({ \ ++ __typeof__ (0 + *(__ptr)) __nln_val; \ ++ __typeof__(*(__ptr)) __fv \ ++ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ ++ /* If __high is explicitly NULL, we must not emit the \ ++ upper-bound comparison. We need to cast __high to an \ ++ unsigned long before handing it to __builtin_constant_p to \ ++ ensure that clang/llvm correctly detects NULL as a constant if it \ ++ is defined as (void*) 0. */ \ ++ if (__builtin_constant_p ((unsigned long)__high) \ ++ && __high == ((void *)0)) \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "bcc\t.ns%=\n\t" \ ++ "ldr" __sz "\t%[__v], %[__p]\n" \ ++ ".ns%=:\n\t" \ ++ "it\tcc\n\t" \ ++ "movcc\t%[__v], %[__f]\n\t" \ ++ ".inst.n 0xf3af\t@ CSDB\n\t" \ ++ ".inst.n 0x8014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&l" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "m" (*(__ptr)), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "r" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ else \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "it\tcs\n\t" \ ++ "cmpcs\t%[__h], %[__c]\n\t" \ ++ "bls\t.ns%=\n\t" \ ++ "ldr" __sz "\t%[__v], %[__p]\n" \ ++ ".ns%=:\n\t" \ ++ "it\tls\n\t" \ ++ "movls\t%[__v], %[__f]\n\t" \ ++ ".inst.n 0xf3af\t@ CSDB\n\t" \ ++ ".inst.n 0x8014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&l" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ [__h] "r" (__high), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "m" (*(__ptr)), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "r" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ (__typeof__ (*(__ptr))) __nln_val; \ ++})) \ ++ \ ++/* Double-word version. */ ++#define __load_no_speculate2(__ptr, __low, __high, __failval, \ ++ __cmpptr) \ ++(__extension__ ({ \ ++ __typeof__ (0 + *(__ptr)) __nln_val; \ ++ __typeof__(*(__ptr)) __fv \ ++ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ ++ /* If __high is explicitly NULL, we must not emit the \ ++ upper-bound comparison. We need to cast __high to an \ ++ unsigned long before handing it to __builtin_constant_p to \ ++ ensure that clang/llvm correctly detects NULL as a constant if it \ ++ is defined as (void*) 0. */ \ ++ if (__builtin_constant_p ((unsigned long)__high) \ ++ && __high == ((void *)0)) \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "bcc\t.ns%=\n\t" \ ++ "ldr\t%Q[__v], [%[__p]]\n\t" \ ++ "ldr\t%R[__v], [%[__p], #4]\n" \ ++ ".ns%=:\n\t" \ ++ "it\tcc\n\t" \ ++ "movcc\t%Q[__v], %Q[__f]\n\t" \ ++ "it\tcc\n\t" \ ++ "movcc\t%R[__v], %R[__f]\n\t" \ ++ ".inst.n 0xf3af\t@ CSDB\n\t" \ ++ ".inst.n 0x8014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&l" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "r" (__ptr), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "r" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ else \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "it\tcs\n\t" \ ++ "cmpcs\t%[__h], %[__c]\n\t" \ ++ "bls\t.ns%=\n\t" \ ++ "ldr\t%Q[__v], [%[__p]]\n\t" \ ++ "ldr\t%R[__v], [%[__p], #4]\n" \ ++ ".ns%=:\n\t" \ ++ "it\tls\n\t" \ ++ "movls\t%Q[__v], %Q[__f]\n\t" \ ++ "it\tls\n\t" \ ++ "movls\t%R[__v], %R[__f]\n\t" \ ++ ".inst.n 0xf3af\t@ CSDB\n\t" \ ++ ".inst.n 0x8014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&l" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ [__h] "r" (__high), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "r" (__ptr), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "r" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ (__typeof__ (*(__ptr))) __nln_val; \ ++})) ++ ++#else ++/* ARM case. */ ++ ++#define __load_no_speculate1(__ptr, __low, __high, __failval, \ ++ __cmpptr, __sz) \ ++(__extension__ ({ \ ++ __typeof__ (0 + *(__ptr)) __nln_val; \ ++ __typeof__(*(__ptr)) __fv \ ++ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ ++ /* If __high is explicitly NULL, we must not emit the \ ++ upper-bound comparison. We need to cast __high to an \ ++ unsigned long before handing it to __builtin_constant_p to \ ++ ensure that clang/llvm correctly detects NULL as a constant if it \ ++ is defined as (void*) 0. */ \ ++ if (__builtin_constant_p ((unsigned long)__high) \ ++ && __high == ((void *)0)) \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "ldr" __sz "cs\t%[__v], %[__p]\n\t" \ ++ "movcc\t%[__v], %[__f]\n\t" \ ++ ".inst 0xe320f014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&r" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "m" (*(__ptr)), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "rKI" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ else \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "cmpcs\t%[__h], %[__c]\n\t" \ ++ "ldr" __sz "hi\t%[__v], %[__p]\n\t" \ ++ "movls\t%[__v], %[__f]\n\t" \ ++ ".inst 0xe320f014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&r" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ [__h] "r" (__high), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "m" (*(__ptr)), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "rKI" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ (__typeof__ (*(__ptr))) __nln_val; \ ++})) ++ ++/* Double-word version. */ ++#define __load_no_speculate2(__ptr, __low, __high, __failval, \ ++ __cmpptr) \ ++(__extension__ ({ \ ++ __typeof__ (0 + *(__ptr)) __nln_val; \ ++ __typeof__(*(__ptr)) __fv \ ++ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ ++ /* If __high is explicitly NULL, we must not emit the \ ++ upper-bound comparison. We need to cast __high to an \ ++ unsigned long before handing it to __builtin_constant_p to \ ++ ensure that clang/llvm correctly detects NULL as a constant if it \ ++ is defined as (void*) 0. */ \ ++ if (__builtin_constant_p ((unsigned long)__high) \ ++ && __high == ((void *)0)) \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "ldrcs\t%Q[__v], [%[__p]]\n\t" \ ++ "ldrcs\t%R[__v], [%[__p], #4]\n\t" \ ++ "movcc\t%Q[__v], %Q[__f]\n\t" \ ++ "movcc\t%R[__v], %R[__f]\n\t" \ ++ ".inst 0xe320f014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&r" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "r" (__ptr), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "r" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ else \ ++ { \ ++ __asm__ volatile ( \ ++ ".syntax unified\n\t" \ ++ "cmp\t%[__c], %[__l]\n\t" \ ++ "cmpcs\t%[__h], %[__c]\n\t" \ ++ "ldrhi\t%Q[__v], [%[__p]]\n\t" \ ++ "ldrhi\t%R[__v], [%[__p], #4]\n\t" \ ++ "movls\t%Q[__v], %Q[__f]\n\t" \ ++ "movls\t%R[__v], %R[__f]\n\t" \ ++ ".inst 0xe320f014\t@ CSDB" \ ++ /* The value we have loaded, or failval if the condition check \ ++ fails. */ \ ++ : [__v] "=&r" (__nln_val) \ ++ /* The pointer we wish to use for comparisons, and the low and \ ++ high bounds to use in that comparison. Note that this need \ ++ not be the same as the pointer from which we will load. */ \ ++ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ ++ [__h] "r" (__high), \ ++ /* The memory location from which we will load. */ \ ++ [__p] "r" (__ptr), \ ++ /* The value to return if the condition check fails. */ \ ++ [__f] "r" (__fv) \ ++ /* We always clobber the condition codes. */ \ ++ : "cc"); \ ++ } \ ++ (__typeof__ (*(__ptr))) __nln_val; \ ++})) ++ ++#endif // __thumb2__ ++ ++/* Common to ARM and Thumb2. */ ++ ++#define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ ++(__extension__ ({ \ ++ __typeof__ (0 + *(__ptr)) __nl_val; \ ++ \ ++ switch (sizeof(*(__ptr))) { \ ++ case 1: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, "b"); \ ++ break; \ ++ case 2: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, "h"); \ ++ break; \ ++ case 4: \ ++ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ ++ __failval, __cmpptr, ""); \ ++ break; \ ++ case 8: \ ++ __nl_val = __load_no_speculate2 (__ptr, __low, __high, \ ++ __failval, __cmpptr); \ ++ break; \ ++ default: \ ++ { \ ++ char __static_assert_no_speculate_load_size_too_big \ ++ [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ ++ break; \ ++ } \ ++ } \ ++ \ ++ (__typeof__ (*(__ptr))) __nl_val; \ ++})) ++ ++#define load_no_speculate(__ptr, __low, __high) \ ++(__extension__ ({ \ ++ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ ++ __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ ++})) ++ ++#define load_no_speculate_fail(__ptr, __low, __high, __failval) \ ++(__extension__ ({ \ ++ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ ++ __load_no_speculate (__ptr_once, __low, __high, \ ++ __failval, __ptr_once); \ ++})) ++ ++#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ ++ (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) ++ ++#else ++#error "No fallback provided for load_no_speculate" ++#endif ++ ++#endif diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h -index 095099c..a0c7542 100644 +index 32aeb0350..a0d134d64 100644 --- a/include/drivers/arm/tzc400.h +++ b/include/drivers/arm/tzc400.h -@@ -32,6 +32,7 @@ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -33,6 +33,7 @@ #define BUILD_CONFIG_NR_SHIFT 0 - #define BUILD_CONFIG_NR_MASK 0x1f + #define BUILD_CONFIG_NR_MASK U(0x1f) +#define FILTER_OFFSET 0x10 /* * Number of gate keepers is implementation defined. But we know the max for * this device is 4. Get implementation details from BUILD_CONFIG. -@@ -112,6 +113,9 @@ void tzc400_configure_region(unsigned int filters, - void tzc400_set_action(tzc_action_t action); +@@ -103,39 +104,40 @@ + ******************************************************************************/ + void tzc400_init(uintptr_t base); + void tzc400_configure_region0(unsigned int sec_attr, +- unsigned int ns_device_access); ++ unsigned int ns_device_access); + void tzc400_configure_region(unsigned int filters, +- unsigned int region, +- unsigned long long region_base, +- unsigned long long region_top, +- unsigned int sec_attr, +- unsigned int nsaid_permissions); ++ unsigned int region, ++ unsigned long long region_base, ++ unsigned long long region_top, ++ unsigned int sec_attr, ++ unsigned int nsaid_permissions); + void tzc400_set_action(unsigned int action); void tzc400_enable_filters(void); void tzc400_disable_filters(void); +void tzc400_clear_all_interrupts(void); @@ -25526,8 +26366,48 @@ index 095099c..a0c7542 100644 static inline void tzc_init(uintptr_t base) { + tzc400_init(base); + } + +-static inline void tzc_configure_region0( +- unsigned int sec_attr, +- unsigned int ns_device_access) ++static inline void tzc_configure_region0(unsigned int sec_attr, ++ unsigned int ns_device_access) + { + tzc400_configure_region0(sec_attr, ns_device_access); + } + +-static inline void tzc_configure_region( +- unsigned int filters, +- unsigned int region, +- unsigned long long region_base, +- unsigned long long region_top, +- unsigned int sec_attr, +- unsigned int ns_device_access) ++static inline void tzc_configure_region(unsigned int filters, ++ unsigned int region, ++ unsigned long long region_base, ++ unsigned long long region_top, ++ unsigned int sec_attr, ++ unsigned int ns_device_access) + { + tzc400_configure_region(filters, region, region_base, +- region_top, sec_attr, ns_device_access); ++ region_top, sec_attr, ns_device_access); + } + + static inline void tzc_set_action(unsigned int action) +@@ -143,7 +145,6 @@ static inline void tzc_set_action(unsigned int action) + tzc400_set_action(action); + } + +- + static inline void tzc_enable_filters(void) + { + tzc400_enable_filters(); diff --git a/include/drivers/io/io_driver.h b/include/drivers/io/io_driver.h -index 8306407..3d2c3ab 100644 +index 2b704f491..d8bb435aa 100644 --- a/include/drivers/io/io_driver.h +++ b/include/drivers/io/io_driver.h @@ -39,7 +39,7 @@ typedef struct io_dev_funcs { @@ -25539,24 +26419,95 @@ index 8306407..3d2c3ab 100644 int (*size)(io_entity_t *entity, size_t *length); int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length, size_t *length_read); +diff --git a/include/drivers/io/io_mtd.h b/include/drivers/io/io_mtd.h +new file mode 100644 +index 000000000..1395ff601 +--- /dev/null ++++ b/include/drivers/io/io_mtd.h +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef IO_MTD_H ++#define IO_MTD_H ++ ++#include ++#include ++ ++#include ++ ++/* MTD devices ops */ ++typedef struct io_mtd_ops { ++ /* ++ * Initialize MTD framework and retrieve device information. ++ * ++ * @size: [out] MTD device size in bytes. ++ * @erase_size: [out] MTD erase size in bytes. ++ * Return 0 on success, a negative error code otherwise. ++ */ ++ int (*init)(unsigned long long *size, unsigned int *erase_size); ++ ++ /* ++ * Execute a read memory operation. ++ * ++ * @offset: Offset in bytes to start read operation. ++ * @buffer: [out] Buffer to store read data. ++ * @length: Required length to be read in bytes. ++ * @out_length: [out] Length read in bytes. ++ * Return 0 on success, a negative error code otherwise. ++ */ ++ int (*read)(unsigned int offset, uintptr_t buffer, size_t length, ++ size_t *out_length); ++ ++ /* ++ * Execute a write memory operation. ++ * ++ * @offset: Offset in bytes to start write operation. ++ * @buffer: Buffer to be written in device. ++ * @length: Required length to be written in bytes. ++ * Return 0 on success, a negative error code otherwise. ++ */ ++ int (*write)(unsigned int offset, uintptr_t buffer, size_t length); ++} io_mtd_ops_t; ++ ++typedef struct io_mtd_dev_spec { ++ unsigned long long device_size; ++ unsigned int erase_size; ++ io_mtd_ops_t ops; ++} io_mtd_dev_spec_t; ++ ++struct io_dev_connector; ++ ++int register_io_dev_mtd(const struct io_dev_connector **dev_con); ++ ++#endif /* IO_MTD_H */ diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h -index 485ed8c..2bf7721 100644 +index 084c67c47..f04214b69 100644 --- a/include/drivers/io/io_storage.h +++ b/include/drivers/io/io_storage.h -@@ -22,6 +22,12 @@ typedef enum { +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -22,8 +22,11 @@ typedef enum { IO_TYPE_DUMMY, IO_TYPE_FIRMWARE_IMAGE_PACKAGE, IO_TYPE_BLOCK, -+ IO_TYPE_MMC, -+ IO_TYPE_STM32IMAGE, ++ IO_TYPE_MTD, + IO_TYPE_MMC, + IO_TYPE_STM32IMAGE, + IO_TYPE_UART, -+ IO_TYPE_QSPI, -+ IO_TYPE_NAND, + IO_TYPE_USB, IO_TYPE_MAX } io_type_t; -@@ -86,7 +92,7 @@ int io_dev_close(uintptr_t dev_handle); +@@ -86,7 +89,7 @@ int io_dev_close(uintptr_t dev_handle); /* Synchronous operations */ int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle); @@ -25565,32 +26516,810 @@ index 485ed8c..2bf7721 100644 int io_size(uintptr_t handle, size_t *length); -diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h +diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h +index 7611f019a..2b4f5ab8b 100644 +--- a/include/drivers/mmc.h ++++ b/include/drivers/mmc.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -104,6 +104,7 @@ + #define MMC_STATE_SLP 10 + + #define MMC_FLAG_CMD23 (U(1) << 0) ++#define MMC_FLAG_SD_CMD6 (U(1) << 1) + + #define CMD8_CHECK_PATTERN U(0xAA) + #define VHS_2_7_3_6_V BIT(8) +@@ -111,6 +112,9 @@ + #define SD_SCR_BUS_WIDTH_1 BIT(8) + #define SD_SCR_BUS_WIDTH_4 BIT(10) + ++#define SD_SWITCH_FUNC_CHECK 0U ++#define SD_SWITCH_FUNC_SWITCH 1U ++ + struct mmc_cmd { + unsigned int cmd_idx; + unsigned int cmd_arg; +@@ -210,6 +214,27 @@ struct mmc_csd_sd_v2 { + unsigned int csd_structure: 2; + }; + ++struct sd_switch_status { ++ unsigned short max_current; ++ unsigned short support_g6; ++ unsigned short support_g5; ++ unsigned short support_g4; ++ unsigned short support_g3; ++ unsigned short support_g2; ++ unsigned short support_g1; ++ unsigned char sel_g6_g5; ++ unsigned char sel_g4_g3; ++ unsigned char sel_g2_g1; ++ unsigned char data_struct_ver; ++ unsigned short busy_g6; ++ unsigned short busy_g5; ++ unsigned short busy_g4; ++ unsigned short busy_g3; ++ unsigned short busy_g2; ++ unsigned short busy_g1; ++ unsigned short reserved[17]; ++}; ++ + enum mmc_device_type { + MMC_IS_EMMC, + MMC_IS_SD, +diff --git a/include/drivers/nand.h b/include/drivers/nand.h new file mode 100644 -index 0000000..b21bde8 +index 000000000..1dbb008f9 --- /dev/null -+++ b/include/drivers/st/bsec.h -@@ -0,0 +1,205 @@ ++++ b/include/drivers/nand.h +@@ -0,0 +1,55 @@ +/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __BSEC_H__ -+#define __BSEC_H__ ++#ifndef DRIVERS_NAND_H ++#define DRIVERS_NAND_H + -+#include ++#include +#include -+#include ++ ++#include ++ ++#define PSEC_TO_MSEC(x) div_round_up((x), 1000000000ULL) ++ ++struct ecc { ++ unsigned int mode; /* ECC mode NAND_ECC_MODE_{NONE|HW|ONDIE} */ ++ unsigned int size; /* Data byte per ECC step */ ++ unsigned int bytes; /* ECC bytes per step */ ++ unsigned int max_bit_corr; /* Max correctible bits per ECC steps */ ++}; ++ ++struct nand_device { ++ unsigned int block_size; ++ unsigned int page_size; ++ unsigned long long size; ++ unsigned int nb_planes; ++ unsigned int buswidth; ++ struct ecc ecc; ++ int (*mtd_block_is_bad)(unsigned int block); ++ int (*mtd_read_page)(struct nand_device *nand, unsigned int page, ++ uintptr_t buffer); ++}; + +/* -+ * IP configuration ++ * Read bytes from NAND device ++ * ++ * @offset: Byte offset to read from in device ++ * @buffer: [out] Bytes read from device ++ * @length: Number of bytes to read ++ * @length_read: [out] Number of bytes read from device ++ * Return: 0 on success, a negative errno on failure + */ -+#define BSEC_OTP_MASK GENMASK(4, 0) -+#define BSEC_OTP_BANK_SHIFT 5 -+#define BSEC_TIMEOUT_VALUE 0xFFFF ++int nand_read(unsigned int offset, uintptr_t buffer, size_t length, ++ size_t *length_read); + ++/* ++ * Get NAND device instance ++ * ++ * Return: NAND device instance reference ++ */ ++struct nand_device *get_nand_device(void); ++ ++#endif /* DRIVERS_NAND_H */ +diff --git a/include/drivers/raw_nand.h b/include/drivers/raw_nand.h +new file mode 100644 +index 000000000..9018f0242 +--- /dev/null ++++ b/include/drivers/raw_nand.h +@@ -0,0 +1,188 @@ ++/* ++ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef DRIVERS_RAW_NAND_H ++#define DRIVERS_RAW_NAND_H ++ ++#include ++#include ++ ++#include ++ ++/* NAND ONFI default value mode 0 in picosecond */ ++#define NAND_TADL_MIN 400000UL ++#define NAND_TALH_MIN 20000UL ++#define NAND_TALS_MIN 50000UL ++#define NAND_TAR_MIN 25000UL ++#define NAND_TCCS_MIN 500000UL ++#define NAND_TCEA_MIN 100000UL ++#define NAND_TCEH_MIN 20000UL ++#define NAND_TCH_MIN 20000UL ++#define NAND_TCHZ_MAX 100000UL ++#define NAND_TCLH_MIN 20000UL ++#define NAND_TCLR_MIN 20000UL ++#define NAND_TCLS_MIN 50000UL ++#define NAND_TCOH_MIN 0UL ++#define NAND_TCS_MIN 70000UL ++#define NAND_TDH_MIN 20000UL ++#define NAND_TDS_MIN 40000UL ++#define NAND_TFEAT_MAX 1000000UL ++#define NAND_TIR_MIN 10000UL ++#define NAND_TITC_MIN 1000000UL ++#define NAND_TR_MAX 200000000UL ++#define NAND_TRC_MIN 100000UL ++#define NAND_TREA_MAX 40000UL ++#define NAND_TREH_MIN 30000UL ++#define NAND_TRHOH_MIN 0UL ++#define NAND_TRHW_MIN 200000UL ++#define NAND_TRHZ_MAX 200000UL ++#define NAND_TRLOH_MIN 0UL ++#define NAND_TRP_MIN 50000UL ++#define NAND_TRR_MIN 40000UL ++#define NAND_TRST_MAX 250000000000ULL ++#define NAND_TWB_MAX 200000UL ++#define NAND_TWC_MIN 100000UL ++#define NAND_TWH_MIN 30000UL ++#define NAND_TWHR_MIN 120000UL ++#define NAND_TWP_MIN 50000UL ++#define NAND_TWW_MIN 100000UL ++ ++/* NAND request types */ ++#define NAND_REQ_CMD 0x0000U ++#define NAND_REQ_ADDR 0x1000U ++#define NAND_REQ_DATAIN 0x2000U ++#define NAND_REQ_DATAOUT 0x3000U ++#define NAND_REQ_WAIT 0x4000U ++#define NAND_REQ_MASK GENMASK(14, 12) ++#define NAND_REQ_BUS_WIDTH_8 BIT(15) ++ ++#define PARAM_PAGE_SIZE 256 ++ ++/* NAND ONFI commands */ ++#define NAND_CMD_READ_1ST 0x00U ++#define NAND_CMD_CHANGE_1ST 0x05U ++#define NAND_CMD_READID_SIG_ADDR 0x20U ++#define NAND_CMD_READ_2ND 0x30U ++#define NAND_CMD_STATUS 0x70U ++#define NAND_CMD_READID 0x90U ++#define NAND_CMD_CHANGE_2ND 0xE0U ++#define NAND_CMD_READ_PARAM_PAGE 0xECU ++#define NAND_CMD_RESET 0xFFU ++ ++#define ONFI_REV_21 BIT(3) ++#define ONFI_FEAT_BUS_WIDTH_16 BIT(0) ++#define ONFI_FEAT_EXTENDED_PARAM BIT(7) ++ ++/* NAND ECC type */ ++#define NAND_ECC_NONE U(0) ++#define NAND_ECC_HW U(1) ++#define NAND_ECC_ONDIE U(2) ++ ++/* NAND bus width */ ++#define NAND_BUS_WIDTH_8 U(0) ++#define NAND_BUS_WIDTH_16 U(1) ++ ++struct nand_req { ++ struct nand_device *nand; ++ uint16_t type; ++ uint8_t *addr; ++ unsigned int length; ++ unsigned int delay_ms; ++ unsigned int inst_delay; ++}; ++ ++struct nand_param_page { ++ /* Rev information and feature block */ ++ uint32_t page_sig; ++ uint16_t rev; ++ uint16_t features; ++ uint16_t opt_cmd; ++ uint8_t jtg; ++ uint8_t train_cmd; ++ uint16_t ext_param_length; ++ uint8_t nb_param_pages; ++ uint8_t reserved1[17]; ++ /* Manufacturer information */ ++ uint8_t manufacturer[12]; ++ uint8_t model[20]; ++ uint8_t manufacturer_id; ++ uint16_t data_code; ++ uint8_t reserved2[13]; ++ /* Memory organization */ ++ uint32_t bytes_per_page; ++ uint16_t spare_per_page; ++ uint32_t bytes_per_partial; ++ uint16_t spare_per_partial; ++ uint32_t num_pages_per_blk; ++ uint32_t num_blk_in_lun; ++ uint8_t num_lun; ++ uint8_t num_addr_cycles; ++ uint8_t bit_per_cell; ++ uint16_t max_bb_per_lun; ++ uint16_t blk_endur; ++ uint8_t valid_blk_begin; ++ uint16_t blk_enbur_valid; ++ uint8_t nb_prog_page; ++ uint8_t partial_prog_attr; ++ uint8_t nb_ecc_bits; ++ uint8_t plane_addr; ++ uint8_t mplanes_ops; ++ uint8_t ez_nand; ++ uint8_t reserved3[12]; ++ /* Electrical parameters */ ++ uint8_t io_pin_cap_max; ++ uint16_t sdr_timing_mode; ++ uint16_t sdr_prog_cache_timing; ++ uint16_t tprog; ++ uint16_t tbers; ++ uint16_t tr; ++ uint16_t tccs; ++ uint8_t nvddr_timing_mode; ++ uint8_t nvddr2_timing_mode; ++ uint8_t nvddr_features; ++ uint16_t clk_input_cap_typ; ++ uint16_t io_pin_cap_typ; ++ uint16_t input_pin_cap_typ; ++ uint8_t input_pin_cap_max; ++ uint8_t drv_strength_support; ++ uint16_t tr_max; ++ uint16_t tadl; ++ uint16_t tr_typ; ++ uint8_t reserved4[6]; ++ /* Vendor block */ ++ uint16_t vendor_revision; ++ uint8_t vendor[88]; ++ uint16_t crc16; ++} __packed; ++ ++struct nand_ctrl_ops { ++ int (*exec)(struct nand_req *req); ++ void (*setup)(struct nand_device *nand); ++}; ++ ++struct rawnand_device { ++ struct nand_device *nand_dev; ++ const struct nand_ctrl_ops *ops; ++}; ++ ++int nand_raw_init(unsigned long long *size, unsigned int *erase_size); ++int nand_wait_ready(unsigned long delay); ++int nand_read_page_cmd(unsigned int page, unsigned int offset, ++ uintptr_t buffer, unsigned int len); ++int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer, ++ unsigned int len); ++void nand_raw_ctrl_init(const struct nand_ctrl_ops *ops); ++ ++/* ++ * Platform can implement this to override default raw NAND instance ++ * configuration. ++ * ++ * @device: target raw NAND instance. ++ * Return 0 on success, negative value otherwise. ++ */ ++int plat_get_raw_nand_data(struct rawnand_device *device); ++ ++#endif /* DRIVERS_RAW_NAND_H */ +diff --git a/include/drivers/spi_mem.h b/include/drivers/spi_mem.h +new file mode 100644 +index 000000000..d1953acf4 +--- /dev/null ++++ b/include/drivers/spi_mem.h +@@ -0,0 +1,130 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef DRIVERS_SPI_MEM_H ++#define DRIVERS_SPI_MEM_H ++ ++#include ++#include ++#include ++ ++#define SPI_MEM_BUSWIDTH_1_LINE 1U ++#define SPI_MEM_BUSWIDTH_2_LINE 2U ++#define SPI_MEM_BUSWIDTH_4_LINE 4U ++ ++/* ++ * enum spi_mem_data_dir - Describes the direction of a SPI memory data ++ * transfer from the controller perspective. ++ * @SPI_MEM_DATA_IN: data coming from the SPI memory. ++ * @SPI_MEM_DATA_OUT: data sent to the SPI memory. ++ */ ++enum spi_mem_data_dir { ++ SPI_MEM_DATA_IN, ++ SPI_MEM_DATA_OUT, ++}; ++ ++/* ++ * struct spi_mem_op - Describes a SPI memory operation. ++ * ++ * @cmd.buswidth: Number of IO lines used to transmit the command. ++ * @cmd.opcode: Operation opcode. ++ * @addr.nbytes: Number of address bytes to send. Can be zero if the operation ++ * does not need to send an address. ++ * @addr.buswidth: Number of IO lines used to transmit the address. ++ * @addr.val: Address value. This value is always sent MSB first on the bus. ++ * Note that only @addr.nbytes are taken into account in this ++ * address value, so users should make sure the value fits in the ++ * assigned number of bytes. ++ * @dummy.nbytes: Number of dummy bytes to send after an opcode or address. Can ++ * be zero if the operation does not require dummy bytes. ++ * @dummy.buswidth: Number of IO lines used to transmit the dummy bytes. ++ * @data.buswidth: Number of IO lines used to send/receive the data. ++ * @data.dir: Direction of the transfer. ++ * @data.nbytes: Number of data bytes to transfer. ++ * @data.buf: Input or output data buffer depending on data::dir. ++ */ ++struct spi_mem_op { ++ struct { ++ uint8_t buswidth; ++ uint8_t opcode; ++ } cmd; ++ ++ struct { ++ uint8_t nbytes; ++ uint8_t buswidth; ++ uint64_t val; ++ } addr; ++ ++ struct { ++ uint8_t nbytes; ++ uint8_t buswidth; ++ } dummy; ++ ++ struct { ++ uint8_t buswidth; ++ enum spi_mem_data_dir dir; ++ unsigned int nbytes; ++ void *buf; ++ } data; ++}; ++ ++/* SPI mode flags */ ++#define SPI_CPHA BIT(0) /* clock phase */ ++#define SPI_CPOL BIT(1) /* clock polarity */ ++#define SPI_CS_HIGH BIT(2) /* CS active high */ ++#define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */ ++#define SPI_3WIRE BIT(4) /* SI/SO signals shared */ ++#define SPI_PREAMBLE BIT(5) /* Skip preamble bytes */ ++#define SPI_TX_DUAL BIT(6) /* transmit with 2 wires */ ++#define SPI_TX_QUAD BIT(7) /* transmit with 4 wires */ ++#define SPI_RX_DUAL BIT(8) /* receive with 2 wires */ ++#define SPI_RX_QUAD BIT(9) /* receive with 4 wires */ ++ ++struct spi_bus_ops { ++ /* ++ * Claim the bus and prepare it for communication. ++ * ++ * @cs: The chip select. ++ * Returns: 0 if the bus was claimed successfully, or a negative value ++ * if it wasn't. ++ */ ++ int (*claim_bus)(unsigned int cs); ++ ++ /* ++ * Release the SPI bus. ++ */ ++ void (*release_bus)(void); ++ ++ /* ++ * Set transfer speed. ++ * ++ * @hz: The transfer speed in Hertz. ++ * Returns: 0 on success, a negative error code otherwise. ++ */ ++ int (*set_speed)(unsigned int hz); ++ ++ /* ++ * Set the SPI mode/flags. ++ * ++ * @mode: Requested SPI mode (SPI_... flags). ++ * Returns: 0 on success, a negative error code otherwise. ++ */ ++ int (*set_mode)(unsigned int mode); ++ ++ /* ++ * Execute a SPI memory operation. ++ * ++ * @op: The memory operation to execute. ++ * Returns: 0 on success, a negative error code otherwise. ++ */ ++ int (*exec_op)(const struct spi_mem_op *op); ++}; ++ ++int spi_mem_exec_op(const struct spi_mem_op *op); ++int spi_mem_init_slave(void *fdt, int bus_node, ++ const struct spi_bus_ops *ops); ++ ++#endif /* DRIVERS_SPI_MEM_H */ +diff --git a/include/drivers/spi_nand.h b/include/drivers/spi_nand.h +new file mode 100644 +index 000000000..40e206375 +--- /dev/null ++++ b/include/drivers/spi_nand.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef DRIVERS_SPI_NAND_H ++#define DRIVERS_SPI_NAND_H ++ ++#include ++#include ++ ++#define SPI_NAND_OP_GET_FEATURE 0x0FU ++#define SPI_NAND_OP_SET_FEATURE 0x1FU ++#define SPI_NAND_OP_READ_ID 0x9FU ++#define SPI_NAND_OP_LOAD_PAGE 0x13U ++#define SPI_NAND_OP_RESET 0xFFU ++#define SPI_NAND_OP_READ_FROM_CACHE 0x03U ++#define SPI_NAND_OP_READ_FROM_CACHE_2X 0x3BU ++#define SPI_NAND_OP_READ_FROM_CACHE_4X 0x6BU ++ ++/* Configuration register */ ++#define SPI_NAND_REG_CFG 0xB0U ++#define SPI_NAND_CFG_ECC_EN BIT(4) ++#define SPI_NAND_CFG_QE BIT(0) ++ ++/* Status register */ ++#define SPI_NAND_REG_STATUS 0xC0U ++#define SPI_NAND_STATUS_BUSY BIT(0) ++#define SPI_NAND_STATUS_ECC_UNCOR BIT(5) ++ ++struct spinand_device { ++ struct nand_device *nand_dev; ++ struct spi_mem_op spi_read_cache_op; ++ uint8_t cfg_cache; /* Cached value of SPI NAND device register CFG */ ++}; ++ ++int spi_nand_init(unsigned long long *size, unsigned int *erase_size); ++ ++/* ++ * Platform can implement this to override default SPI-NAND instance ++ * configuration. ++ * ++ * @device: target SPI-NAND instance. ++ * Return 0 on success, negative value otherwise. ++ */ ++int plat_get_spi_nand_data(struct spinand_device *device); ++ ++#endif /* DRIVERS_SPI_NAND_H */ +diff --git a/include/drivers/spi_nor.h b/include/drivers/spi_nor.h +new file mode 100644 +index 000000000..72cfe5b34 +--- /dev/null ++++ b/include/drivers/spi_nor.h +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef DRIVERS_SPI_NOR_H ++#define DRIVERS_SPI_NOR_H ++ ++#include ++ ++/* OPCODE */ ++#define SPI_NOR_OP_WREN 0x06U /* Write enable */ ++#define SPI_NOR_OP_WRSR 0x01U /* Write status register 1 byte */ ++#define SPI_NOR_OP_READ_ID 0x9FU /* Read JEDEC ID */ ++#define SPI_NOR_OP_READ_CR 0x35U /* Read configuration register */ ++#define SPI_NOR_OP_READ_SR 0x05U /* Read status register */ ++#define SPI_NOR_OP_READ_FSR 0x70U /* Read flag status register */ ++#define SPINOR_OP_RDEAR 0xC8U /* Read Extended Address Register */ ++#define SPINOR_OP_WREAR 0xC5U /* Write Extended Address Register */ ++ ++/* Used for Spansion flashes only. */ ++#define SPINOR_OP_BRWR 0x17U /* Bank register write */ ++#define SPINOR_OP_BRRD 0x16U /* Bank register read */ ++ ++#define SPI_NOR_OP_READ 0x03U /* Read data bytes (low frequency) */ ++#define SPI_NOR_OP_READ_FAST 0x0BU /* Read data bytes (high frequency) */ ++#define SPI_NOR_OP_READ_1_1_2 0x3BU /* Read data bytes (Dual Output SPI) */ ++#define SPI_NOR_OP_READ_1_2_2 0xBBU /* Read data bytes (Dual I/O SPI) */ ++#define SPI_NOR_OP_READ_1_1_4 0x6BU /* Read data bytes (Quad Output SPI) */ ++#define SPI_NOR_OP_READ_1_4_4 0xEBU /* Read data bytes (Quad I/O SPI) */ ++ ++/* Flags for NOR specific configuration */ ++#define SPI_NOR_USE_FSR BIT(0) ++#define SPI_NOR_USE_BANK BIT(1) ++ ++struct nor_device { ++ struct spi_mem_op read_op; ++ uint32_t size; ++ uint32_t flags; ++ uint8_t selected_bank; ++ uint8_t bank_write_cmd; ++ uint8_t bank_read_cmd; ++}; ++ ++int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, ++ size_t *length_read); ++int spi_nor_init(unsigned long long *device_size, unsigned int *erase_size); ++ ++/* ++ * Platform can implement this to override default NOR instance configuration. ++ * ++ * @device: target NOR instance. ++ * Return 0 on success, negative value otherwise. ++ */ ++int plat_get_nor_data(struct nor_device *device); ++ ++#endif /* DRIVERS_SPI_NOR_H */ +diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h +index d833e7ab2..6601e56a9 100644 +--- a/include/drivers/st/bsec.h ++++ b/include/drivers/st/bsec.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -19,13 +19,6 @@ + #define BSEC_OTP_BANK_SHIFT 5 + #define BSEC_TIMEOUT_VALUE 0xFFFF + +-#define ADDR_LOWER_OTP_PERLOCK_SHIFT 0x03 +-#define DATA_LOWER_OTP_PERLOCK_BIT 0x03U /* 2 significants bits are used */ +-#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK(2, 0) +-#define ADDR_UPPER_OTP_PERLOCK_SHIFT 0x04 +-#define DATA_UPPER_OTP_PERLOCK_BIT 0x01U /* 1 significants bits are used */ +-#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK(3, 0) +- + /* + * Return status + */ +@@ -35,110 +28,34 @@ + #define BSEC_INVALID_PARAM 0xFFFFFFFCU + #define BSEC_PROG_FAIL 0xFFFFFFFBU + #define BSEC_LOCK_FAIL 0xFFFFFFFAU +-#define BSEC_WRITE_FAIL 0xFFFFFFF9U +-#define BSEC_SHADOW_FAIL 0xFFFFFFF8U +-#define BSEC_TIMEOUT 0xFFFFFFF7U +- +-/* +- * BSEC REGISTER OFFSET (base relative) +- */ +-#define BSEC_OTP_CONF_OFF 0x000U +-#define BSEC_OTP_CTRL_OFF 0x004U +-#define BSEC_OTP_WRDATA_OFF 0x008U +-#define BSEC_OTP_STATUS_OFF 0x00CU +-#define BSEC_OTP_LOCK_OFF 0x010U +-#define BSEC_DEN_OFF 0x014U +-#define BSEC_DISTURBED_OFF 0x01CU +-#define BSEC_DISTURBED1_OFF 0x020U +-#define BSEC_DISTURBED2_OFF 0x024U +-#define BSEC_ERROR_OFF 0x034U +-#define BSEC_ERROR1_OFF 0x038U +-#define BSEC_ERROR2_OFF 0x03CU +-#define BSEC_WRLOCK_OFF 0x04CU /* Safmem permanent lock */ +-#define BSEC_WRLOCK1_OFF 0x050U +-#define BSEC_WRLOCK2_OFF 0x054U +-#define BSEC_SPLOCK_OFF 0x064U /* Program safmem sticky lock */ +-#define BSEC_SPLOCK1_OFF 0x068U +-#define BSEC_SPLOCK2_OFF 0x06CU +-#define BSEC_SWLOCK_OFF 0x07CU /* Write in OTP sticky lock */ +-#define BSEC_SWLOCK1_OFF 0x080U +-#define BSEC_SWLOCK2_OFF 0x084U +-#define BSEC_SRLOCK_OFF 0x094U /* Shadowing sticky lock */ +-#define BSEC_SRLOCK1_OFF 0x098U +-#define BSEC_SRLOCK2_OFF 0x09CU +-#define BSEC_JTAG_IN_OFF 0x0ACU +-#define BSEC_JTAG_OUT_OFF 0x0B0U +-#define BSEC_SCRATCH_OFF 0x0B4U +-#define BSEC_OTP_DATA_OFF 0x200U +-#define BSEC_IPHW_CFG_OFF 0xFF0U +-#define BSEC_IPVR_OFF 0xFF4U +-#define BSEC_IP_ID_OFF 0xFF8U +-#define BSEC_IP_MAGIC_ID_OFF 0xFFCU +- +-/* +- * BSEC_CONFIGURATION Register +- */ +-#define BSEC_CONF_POWER_UP_MASK BIT(0) +-#define BSEC_CONF_POWER_UP_SHIFT 0 +-#define BSEC_CONF_FRQ_MASK GENMASK(2, 1) +-#define BSEC_CONF_FRQ_SHIFT 1 +-#define BSEC_CONF_PRG_WIDTH_MASK GENMASK(6, 3) +-#define BSEC_CONF_PRG_WIDTH_SHIFT 3 +-#define BSEC_CONF_TREAD_MASK GENMASK(8, 7) +-#define BSEC_CONF_TREAD_SHIFT 7 +- +-/* +- * BSEC_CONTROL Register +- */ +-#define BSEC_READ 0x000U +-#define BSEC_WRITE 0x100U +-#define BSEC_LOCK 0x200U ++#define BSEC_TIMEOUT 0xFFFFFFF9U ++#define BSEC_RETRY 0xFFFFFFF8U ++#define BSEC_NOT_SUPPORTED 0xFFFFFFF7U ++#define BSEC_WRITE_LOCKED 0xFFFFFFF6U ++#define BSEC_ERROR_INVALID_FVR 0xFFFFFFF5U + + /* +- * BSEC_OTP_LOCK register ++ * OTP MODE + */ +-#define UPPER_OTP_LOCK_MASK BIT(0) +-#define UPPER_OTP_LOCK_SHIFT 0 +-#define DENREG_LOCK_MASK BIT(2) +-#define DENREG_LOCK_SHIFT 2 +-#define GPLOCK_LOCK_MASK BIT(4) +-#define GPLOCK_LOCK_SHIFT 4 +- +-/* +- * BSEC_OTP_STATUS Register +- */ +-#define BSEC_MODE_STATUS_MASK GENMASK(2, 0) +-#define BSEC_MODE_BUSY_MASK BIT(3) +-#define BSEC_MODE_PROGFAIL_MASK BIT(4) +-#define BSEC_MODE_PWR_MASK BIT(5) +-#define BSEC_MODE_BIST1_LOCK_MASK BIT(6) +-#define BSEC_MODE_BIST2_LOCK_MASK BIT(7) +- +-/* OTP MODE*/ + #define BSEC_MODE_OPEN1 0x00 + #define BSEC_MODE_SECURED 0x01 + #define BSEC_MODE_OPEN2 0x02 + #define BSEC_MODE_INVALID 0x04 + +-/* BSEC_DENABLE Register */ +-#define BSEC_HDPEN BIT(4) +-#define BSEC_SPIDEN BIT(5) +-#define BSEC_SPINDEN BIT(6) +-#define BSEC_DBGSWGEN BIT(10) +-#define BSEC_DEN_ALL_MSK GENMASK(10, 0) +- +-/* BSEC_FENABLE Register */ +-#define BSEC_FEN_ALL_MSK GENMASK(14, 0) +- + /* +- * OTP Lock services definition +- * Value must corresponding to the bit number in the register ++ * OTP Lock services definition. ++ * Value must corresponding to the bit number in the register. ++ * Special case: (bit number << 1) for BSEC3. + */ + #define BSEC_LOCK_UPPER_OTP 0x00 ++#define BSEC_LOCK_GWLOCK 0x01 + #define BSEC_LOCK_DEBUG 0x02 + #define BSEC_LOCK_PROGRAM 0x03 ++#define BSEC_LOCK_KVLOCK 0x04 + +-/* Values for struct bsec_config::freq */ ++/* ++ * Values for struct bsec_config::freq ++ */ + #define FREQ_10_20_MHZ 0x0 + #define FREQ_20_30_MHZ 0x1 + #define FREQ_30_45_MHZ 0x2 +@@ -146,22 +63,28 @@ + + /* + * Device info structure, providing device-specific functions and a means of +- * adding driver-specific state ++ * adding driver-specific state. + */ + struct bsec_config { ++ uint8_t den_lock; /* ++ * Debug enable sticky lock ++ * 1 debug enable is locked until next reset ++ */ ++ ++ /* BSEC2 only */ + uint8_t tread; /* SAFMEM Reading current level default 0 */ + uint8_t pulse_width; /* SAFMEM Programming pulse width default 1 */ +- uint8_t freq; /* SAFMEM CLOCK see freq value define ++ uint8_t freq; /* ++ * SAFMEM CLOCK see freq value define + * default FREQ_45_67_MHZ + */ + uint8_t power; /* Power up SAFMEM. 1 power up, 0 power off */ +- uint8_t prog_lock; /* Programming Sticky lock ++ uint8_t prog_lock; /* ++ * Programming Sticky lock + * 1 programming is locked until next reset + */ +- uint8_t den_lock; /* Debug enable sticky lock +- * 1 debug enable is locked until next reset +- */ +- uint8_t upper_otp_lock; /* Shadowing of upper OTP sticky lock ++ uint8_t upper_otp_lock; /* ++ * Shadowing of upper OTP sticky lock + * 1 shadowing of upper OTP is locked + * until next reset + */ +@@ -173,6 +96,9 @@ uint32_t bsec_get_base(void); + uint32_t bsec_set_config(struct bsec_config *cfg); + uint32_t bsec_get_config(struct bsec_config *cfg); + ++uint32_t bsec_find_otp_name_in_dt(const char *name, uint32_t *otp, ++ uint32_t *otp_len); ++ + uint32_t bsec_shadow_register(uint32_t otp); + uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); + uint32_t bsec_write_otp(uint32_t val, uint32_t otp); +@@ -190,14 +116,14 @@ 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); + + 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/bsec2_reg.h b/include/drivers/st/bsec2_reg.h +new file mode 100644 +index 000000000..9da952603 +--- /dev/null ++++ b/include/drivers/st/bsec2_reg.h +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef BSEC2_REG_H ++#define BSEC2_REG_H ++ ++#include ++ ++/* IP configuration */ +#define ADDR_LOWER_OTP_PERLOCK_SHIFT 0x03 +#define DATA_LOWER_OTP_PERLOCK_BIT 0x03U /* 2 significants bits are used */ +#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK(2, 0) @@ -25598,58 +27327,41 @@ index 0000000..b21bde8 +#define DATA_UPPER_OTP_PERLOCK_BIT 0x01U /* 1 significants bits are used */ +#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK(3, 0) + -+/* -+ * Return status -+ */ -+#define BSEC_OK 0U -+#define BSEC_ERROR 0xFFFFFFFFU -+#define BSEC_DISTURBED 0xFFFFFFFEU -+#define BSEC_INVALID_PARAM 0xFFFFFFFCU -+#define BSEC_PROG_FAIL 0xFFFFFFFBU -+#define BSEC_LOCK_FAIL 0xFFFFFFFAU -+#define BSEC_WRITE_FAIL 0xFFFFFFF9U -+#define BSEC_SHADOW_FAIL 0xFFFFFFF8U -+#define BSEC_TIMEOUT 0xFFFFFFF7U ++/* BSEC REGISTER OFFSET (base relative) */ ++#define BSEC_OTP_CONF_OFF U(0x000) ++#define BSEC_OTP_CTRL_OFF U(0x004) ++#define BSEC_OTP_WRDATA_OFF U(0x008) ++#define BSEC_OTP_STATUS_OFF U(0x00C) ++#define BSEC_OTP_LOCK_OFF U(0x010) ++#define BSEC_DEN_OFF U(0x014) ++#define BSEC_DISTURBED_OFF U(0x01C) ++#define BSEC_DISTURBED1_OFF U(0x020) ++#define BSEC_DISTURBED2_OFF U(0x024) ++#define BSEC_ERROR_OFF U(0x034) ++#define BSEC_ERROR1_OFF U(0x038) ++#define BSEC_ERROR2_OFF U(0x03C) ++#define BSEC_WRLOCK_OFF U(0x04C) /* Safmem permanent lock */ ++#define BSEC_WRLOCK1_OFF U(0x050) ++#define BSEC_WRLOCK2_OFF U(0x054) ++#define BSEC_SPLOCK_OFF U(0x064) /* Program safmem sticky lock */ ++#define BSEC_SPLOCK1_OFF U(0x068) ++#define BSEC_SPLOCK2_OFF U(0x06C) ++#define BSEC_SWLOCK_OFF U(0x07C) /* Write in OTP sticky lock */ ++#define BSEC_SWLOCK1_OFF U(0x080) ++#define BSEC_SWLOCK2_OFF U(0x084) ++#define BSEC_SRLOCK_OFF U(0x094) /* Shadowing sticky lock */ ++#define BSEC_SRLOCK1_OFF U(0x098) ++#define BSEC_SRLOCK2_OFF U(0x09C) ++#define BSEC_JTAG_IN_OFF U(0x0AC) ++#define BSEC_JTAG_OUT_OFF U(0x0B0) ++#define BSEC_SCRATCH_OFF U(0x0B4) ++#define BSEC_OTP_DATA_OFF U(0x200) ++#define BSEC_IPHW_CFG_OFF U(0xFF0) ++#define BSEC_IPVR_OFF U(0xFF4) ++#define BSEC_IP_ID_OFF U(0xFF8) ++#define BSEC_IP_MAGIC_ID_OFF U(0xFFC) + -+/* -+ * BSEC REGISTER OFFSET (base relative) -+ */ -+#define BSEC_OTP_CONF_OFF 0x000U -+#define BSEC_OTP_CTRL_OFF 0x004U -+#define BSEC_OTP_WRDATA_OFF 0x008U -+#define BSEC_OTP_STATUS_OFF 0x00CU -+#define BSEC_OTP_LOCK_OFF 0x010U -+#define BSEC_DEN_OFF 0x014U -+#define BSEC_DISTURBED_OFF 0x01CU -+#define BSEC_DISTURBED1_OFF 0x020U -+#define BSEC_DISTURBED2_OFF 0x024U -+#define BSEC_ERROR_OFF 0x034U -+#define BSEC_ERROR1_OFF 0x038U -+#define BSEC_ERROR2_OFF 0x03CU -+#define BSEC_WRLOCK_OFF 0x04CU /* Safmem permanent lock */ -+#define BSEC_WRLOCK1_OFF 0x050U -+#define BSEC_WRLOCK2_OFF 0x054U -+#define BSEC_SPLOCK_OFF 0x064U /* Program safmem sticky lock */ -+#define BSEC_SPLOCK1_OFF 0x068U -+#define BSEC_SPLOCK2_OFF 0x06CU -+#define BSEC_SWLOCK_OFF 0x07CU /* Write in OTP sticky lock */ -+#define BSEC_SWLOCK1_OFF 0x080U -+#define BSEC_SWLOCK2_OFF 0x084U -+#define BSEC_SRLOCK_OFF 0x094U /* Shadowing sticky lock */ -+#define BSEC_SRLOCK1_OFF 0x098U -+#define BSEC_SRLOCK2_OFF 0x09CU -+#define BSEC_JTAG_IN_OFF 0x0ACU -+#define BSEC_JTAG_OUT_OFF 0x0B0U -+#define BSEC_SCRATCH_OFF 0x0B4U -+#define BSEC_OTP_DATA_OFF 0x200U -+#define BSEC_IPHW_CFG_OFF 0xFF0U -+#define BSEC_IPVR_OFF 0xFF4U -+#define BSEC_IP_ID_OFF 0xFF8U -+#define BSEC_IP_MAGIC_ID_OFF 0xFFCU -+ -+/* -+ * BSEC_CONFIGURATION Register -+ */ ++/* BSEC_CONFIGURATION Register */ +#define BSEC_CONF_POWER_UP_MASK BIT(0) +#define BSEC_CONF_POWER_UP_SHIFT 0 +#define BSEC_CONF_FRQ_MASK GENMASK(2, 1) @@ -25659,16 +27371,12 @@ index 0000000..b21bde8 +#define BSEC_CONF_TREAD_MASK GENMASK(8, 7) +#define BSEC_CONF_TREAD_SHIFT 7 + -+/* -+ * BSEC_CONTROL Register -+ */ -+#define BSEC_READ 0x000U -+#define BSEC_WRITE 0x100U -+#define BSEC_LOCK 0x200U ++/* BSEC_CONTROL Register */ ++#define BSEC_READ 0 ++#define BSEC_WRITE BIT(8) ++#define BSEC_LOCK BIT(9) + -+/* -+ * BSEC_OTP_LOCK register -+ */ ++/* BSEC_OTP_LOCK register */ +#define UPPER_OTP_LOCK_MASK BIT(0) +#define UPPER_OTP_LOCK_SHIFT 0 +#define DENREG_LOCK_MASK BIT(2) @@ -25676,9 +27384,7 @@ index 0000000..b21bde8 +#define GPLOCK_LOCK_MASK BIT(4) +#define GPLOCK_LOCK_SHIFT 4 + -+/* -+ * BSEC_OTP_STATUS Register -+ */ ++/* BSEC_OTP_STATUS Register */ +#define BSEC_MODE_STATUS_MASK GENMASK(2, 0) +#define BSEC_MODE_BUSY_MASK BIT(3) +#define BSEC_MODE_PROGFAIL_MASK BIT(4) @@ -25686,12 +27392,6 @@ index 0000000..b21bde8 +#define BSEC_MODE_BIST1_LOCK_MASK BIT(6) +#define BSEC_MODE_BIST2_LOCK_MASK BIT(7) + -+/* OTP MODE*/ -+#define BSEC_MODE_OPEN1 0x00 -+#define BSEC_MODE_SECURED 0x01 -+#define BSEC_MODE_OPEN2 0x02 -+#define BSEC_MODE_INVALID 0x04 -+ +/* BSEC_DENABLE Register */ +#define BSEC_HDPEN BIT(4) +#define BSEC_SPIDEN BIT(5) @@ -25702,88 +27402,18 @@ index 0000000..b21bde8 +/* BSEC_FENABLE Register */ +#define BSEC_FEN_ALL_MSK GENMASK(14, 0) + -+/* -+ * OTP Lock services definition -+ * Value must corresponding to the bit number in the register -+ */ -+#define BSEC_LOCK_UPPER_OTP 0x00 -+#define BSEC_LOCK_DEBUG 0x02 -+#define BSEC_LOCK_PROGRAM 0x03 ++/* BSEC_IPVR Register */ ++#define BSEC_IPVR_MSK GENMASK(7, 0) + -+/* Values for struct bsec_config::freq */ -+#define FREQ_10_20_MHZ 0x0 -+#define FREQ_20_30_MHZ 0x1 -+#define FREQ_30_45_MHZ 0x2 -+#define FREQ_45_67_MHZ 0x3 -+ -+/* -+ * Device info structure, providing device-specific functions and a means of -+ * adding driver-specific state -+ */ -+struct bsec_config { -+ uint8_t tread; /* SAFMEM Reading current level default 0 */ -+ uint8_t pulse_width; /* SAFMEM Programming pulse width default 1 */ -+ uint8_t freq; /* SAFMEM CLOCK see freq value define -+ * default FREQ_45_67_MHZ -+ */ -+ uint8_t power; /* Power up SAFMEM. 1 power up, 0 power off */ -+ uint8_t prog_lock; /* Programming Sticky lock -+ * 1 programming is locked until next reset -+ */ -+ uint8_t den_lock; /* Debug enable is sticky lock -+ * 1 debug enable is locked until next reset -+ */ -+ uint8_t upper_otp_lock; /* Shadowing of upper OTP is sticky lock -+ * 1 shadowing of upper OTP is locked -+ * until next reset -+ */ -+}; -+ -+uint32_t bsec_probe(void); -+uint32_t bsec_get_base(void); -+ -+uint32_t bsec_set_config(struct bsec_config *cfg); -+uint32_t bsec_get_config(struct bsec_config *cfg); -+ -+uint32_t bsec_shadow_register(uint32_t otp); -+uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); -+uint32_t bsec_write_otp(uint32_t val, uint32_t otp); -+uint32_t bsec_program_otp(uint32_t val, uint32_t otp); -+uint32_t bsec_permanent_lock_otp(uint32_t otp); -+ -+uint32_t bsec_write_debug_conf(uint32_t val); -+uint32_t bsec_read_debug_conf(void); -+uint32_t bsec_write_feature_conf(uint32_t val); -+uint32_t bsec_read_feature_conf(uint32_t *val); -+ -+uint32_t bsec_get_status(void); -+uint32_t bsec_get_hw_conf(void); -+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); -+ -+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); -+ -+#endif /*__BSEC_H__*/ ++#endif /* BSEC2_REG_H */ diff --git a/include/drivers/st/etzpc.h b/include/drivers/st/etzpc.h new file mode 100644 -index 0000000..c31d996 +index 000000000..c0ed06f6e --- /dev/null +++ b/include/drivers/st/etzpc.h @@ -0,0 +1,32 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -25814,178 +27444,14 @@ index 0000000..c31d996 +int etzpc_init(void); + +#endif /* __ETZPC_H__ */ -diff --git a/include/drivers/st/hash_sec.h b/include/drivers/st/hash_sec.h -new file mode 100644 -index 0000000..a8d8b9b ---- /dev/null -+++ b/include/drivers/st/hash_sec.h -@@ -0,0 +1,113 @@ -+/** -+ ****************************************************************************** -+ * @file hash_sec.h -+ * @author mgentilini - MCD IntroPack team - MPU AP v1 bootROM project -+ * @version V0.1 -+ * @date 22-Sept-2015 -+ * @brief Header file for STM32MP1 HASH driver module. -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) 2015 STMicroelectronics

-+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ * -+ ****************************************************************************** -+ */ -+ -+/* Define to prevent recursive inclusion -------------------------------------*/ -+#ifndef __HASH_SEC_H -+#define __HASH_SEC_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/* Definitions----------------------------------------------------------------*/ -+#define HASH ((HASH_TypeDef *)HASH_BASE) -+#define HASH_DIGEST ((HASH_DIGEST_TypeDef *)(HASH_BASE + 0x310)) -+ -+#define HASH_TIMEOUT_VALUE 0x500000 -+ -+/* -+ * HASH IP uses 512 bits : ie 64 bytes block in order to start computation of -+ * Hash intermediate Digest -+ * The digest intermediate computation starts only after 64 bytes are entered -+ */ -+#define HASH_BLOCK_SIZE_NB_BYTES 64 -+ -+/** -+ * @brief Set the number of valid bits in last word 32 bits written in Data -+ * register -+ * @param SIZE: size in byte of last data written in Data register. -+ * @retval None -+ */ -+ -+#define __HAL_HASH_SET_NBVALIDBITSINLAST32BITSWORD(SIZE) \ -+ do { \ -+ HASH->STR &= ~(HASH_STR_NBW); \ -+ HASH->STR |= 8 * ((SIZE) % 4); \ -+ } while (0) -+ -+/** -+ * @brief HASH Handle Structure definition -+ */ -+typedef struct { -+ HASH_TypeDef *Instance; /*!< HASH Registers base address */ -+ uint32_t State; -+ uint32_t Error; -+ const uint8_t *pHashInBuffPtr; /*!< Pointer to input buffer */ -+ const uint8_t *pHashOutBuffPtr; /*!< Pointer to output buffer */ -+} HASH_HandleTypeDef; -+ -+#define HASH_DIGEST_DONE 0x0 -+#define HASH_TIMEOUT 0x1 -+#define HASH_INIT_DONE 0x2 -+#define HASH_ACCU_DONE 0x3 -+#define HASH_FINISHED 0x4 -+#define HASH_INIT_NOT_DONE 0x5 -+ -+/** @defgroup HASH_Algo_Selection -+ * @{ -+ */ -+#define HASH_AlgoSelection_SHA256 HASH_CR_ALGO /*!< HASH function is SHA256 */ -+ -+/** -+ * @} -+ */ -+ -+/** @defgroup HASH_Data_Type -+ * @{ -+ */ -+#define HASH_DATATYPE_8B HASH_CR_DATATYPE_1 /*!< 8-bit data. All bytes are -+ * swapped -+ */ -+ -+/* Exported functions --------------------------------------------------------*/ -+ -+/* HASH processing using polling *********************************************/ -+Std_ReturnType HASH_SHA256_Init(HASH_HandleTypeDef *hHash); -+ -+Std_ReturnType HASH_SHA256_Start(HASH_HandleTypeDef *hHash, -+ const uint8_t *pInBuffer, -+ uint32_t sizeInBytes, -+ uint8_t *pOutBuffer, uint32_t Timeout); -+ -+Std_ReturnType HASH_SHA256_Accumulate(HASH_HandleTypeDef *hHash, -+ const uint8_t *pInBuffer, -+ uint32_t sizeInBytes); -+ -+Std_ReturnType HASH_SHA256_Finish(HASH_HandleTypeDef *hHash, -+ uint8_t *pOutBuffer, uint32_t Timeout); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __HASH_SEC_H */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -+ -diff --git a/include/drivers/st/io_mmc.h b/include/drivers/st/io_mmc.h -new file mode 100644 -index 0000000..de71e7d ---- /dev/null -+++ b/include/drivers/st/io_mmc.h -@@ -0,0 +1,14 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef IO_MMC_H -+#define IO_MMC_H -+ -+#include -+ -+int register_io_dev_mmc(const io_dev_connector_t **dev_con); -+ -+#endif /* IO_MMC_H */ -diff --git a/include/drivers/st/io_nand.h b/include/drivers/st/io_nand.h -new file mode 100644 -index 0000000..13c8fbf ---- /dev/null -+++ b/include/drivers/st/io_nand.h -@@ -0,0 +1,19 @@ -+/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef __IO_NAND_H__ -+#define __IO_NAND_H__ -+ -+#define STM32_NAND_MAX_BLOCK_SIZE 512 -+ -+typedef struct nand_device_info { -+ uint64_t device_size; /* Size of device in bytes */ -+ uint32_t block_size; /* block size in bytes */ -+} nand_device_info_t; -+ -+int register_io_dev_nand(const io_dev_connector_t **dev_con); -+ -+#endif /* __IO_NAND_H__ */ diff --git a/include/drivers/st/io_programmer.h b/include/drivers/st/io_programmer.h new file mode 100644 -index 0000000..454aa68 +index 000000000..c6c2de10f --- /dev/null +++ b/include/drivers/st/io_programmer.h @@ -0,0 +1,51 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -26037,12 +27503,12 @@ index 0000000..454aa68 +#endif /* __IO_PROGRAMMER_H__ */ diff --git a/include/drivers/st/io_programmer_st_usb.h b/include/drivers/st/io_programmer_st_usb.h new file mode 100644 -index 0000000..f6ad9c7 +index 000000000..79effad87 --- /dev/null +++ b/include/drivers/st/io_programmer_st_usb.h -@@ -0,0 +1,20 @@ +@@ -0,0 +1,12 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -26050,161 +27516,30 @@ index 0000000..f6ad9c7 +#ifndef __IO_USB_H__ +#define __IO_USB_H__ + -+#define IO_USB_TIMEOUT 0xFFFFF -+/* need to call the USB Handler 4 times after to have -+ * received the detach request -+ */ -+#define DETACH_TIMEOUT 0x100 -+ -+#define USB_DFU_MAX_XFER_SIZE 1024 -+ +int register_io_dev_usb(const io_dev_connector_t **dev_con); + +#endif /* __IO_USB_H__ */ -diff --git a/include/drivers/st/io_qspi.h b/include/drivers/st/io_qspi.h -new file mode 100644 -index 0000000..fc03faf ---- /dev/null -+++ b/include/drivers/st/io_qspi.h -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef __IO_QSPI_H__ -+#define __IO_QSPI_H__ -+ -+#define QSPI_FMODE_MASK 0x0C000000 -+#define QSPI_FMODE_MEMORY_MAPPED 0x0C000000 -+ -+#define QSPI_NOR_MAX_SIZE 0x10000000 /* 256 MB*/ -+#define QSPI_NOR_LBA_SIZE 0x00000200 /* 512 B*/ -+#define QSPI_NOR_BLK_SIZE 0x00040000 /* 256 KB*/ -+ -+#define QSPI_CR_EN 0x00000001 -+#define QSPI_CR_ABORT 0x00000002 -+#define QSPI_CR_TCEN 0x00000008 -+#define QSPI_CR_SSHIFT 0x00000010 -+#define QSPI_CR_DFM 0x00000040 -+#define QSPI_CR_PRESCALER_SHIFT 24 -+ -+#define QSPI_DCR_CSHT 0x00000100 -+#define QSPI_DCR_FSIZE_MASK 0x001F0000 -+#define QSPI_DCR_FSIZE_SHIFT 16 -+ -+#define QSPI_CCR_INST 0x0000000B -+#define QSPI_CCR_IMODE 0x00000100 -+#define QSPI_CCR_ADMODE 0x00000400 -+#define QSPI_CCR_ADSIZE 0x00002000 -+#define QSPI_CCR_ABMODE 0x00000000 -+#define QSPI_CCR_ABSIZE 0x00000000 -+#define QSPI_CCR_DCYC 0x00200000 -+#define QSPI_CCR_DMODE 0x01000000 -+#define QSPI_CCR_FMODE_MM 0x0C000000 -+#define QSPI_CCR_FMODE 0x04000000 -+#define QSPI_CCR_SIOO 0x00000000 -+#define QSPI_CCR_DDRM 0x00000000 -+#define QSPI_CCR_DHHC 0x00000000 -+ -+#define QSPI_SR_FLEVEL 0x1F00 -+#define QSPI_SR_BUSY 0x0020 -+#define QSPI_SR_TOF 0x0010 -+#define QSPI_SR_SMF 0x0008 -+#define QSPI_SR_FTF 0x0004 -+#define QSPI_SR_TCF 0x0002 -+#define QSPI_SR_TEF 0x0001 -+ -+#define QSPI_FCR_CTOF 0x0008 -+#define QSPI_FCR_CSMF 0x0004 -+#define QSPI_FCR_CTCF 0x0002 -+#define QSPI_FCR_CTEF 0x0001 -+ -+#define QSPI_DFLT_READ_FLAGS (QSPI_CCR_INST | QSPI_CCR_IMODE | \ -+ QSPI_CCR_ADMODE | QSPI_CCR_ADSIZE | \ -+ QSPI_CCR_ABMODE | QSPI_CCR_ABSIZE | \ -+ QSPI_CCR_DCYC | QSPI_CCR_DMODE | \ -+ QSPI_CCR_SIOO | QSPI_CCR_DDRM | \ -+ QSPI_CCR_DHHC) -+ -+/* -+ * QUAD Serial Peripheral Interface -+ */ -+ -+typedef struct { -+ volatile uint32_t CR; /* Control register */ -+ volatile uint32_t DCR; /* Device Configuration register */ -+ volatile uint32_t SR; /* Status register */ -+ volatile uint32_t FCR; /* Flag Clear register */ -+ volatile uint32_t DLR; /* Data Length register */ -+ volatile uint32_t CCR; /* Communication Configuration register */ -+ volatile uint32_t AR; /* Address register */ -+ volatile uint32_t ABR; /* Alternate Bytes register */ -+ volatile uint32_t DR; /* Data register */ -+ volatile uint32_t PSMKR; /* Polling Status Mask register */ -+ volatile uint32_t PSMAR; /* Polling Status Match register */ -+ volatile uint32_t PIR; /* Polling Interval register */ -+ volatile uint32_t LPTR; /* Low Power Timeout register */ -+} QUADSPI_TypeDef; -+ -+/* -+ * QSPI Handle Structure definition -+ */ -+typedef struct { -+ QUADSPI_TypeDef *instance; /* QSPI registers base address */ -+ uint32_t is_dual; -+} QSPI_HandleTypeDef; -+ -+int register_io_dev_qspi(const io_dev_connector_t **dev_con); -+ -+#endif /* __IO_QSPI_H__ */ diff --git a/include/drivers/st/io_stm32image.h b/include/drivers/st/io_stm32image.h -new file mode 100644 -index 0000000..b668219 ---- /dev/null +index 68060558b..f9fa3630c 100644 +--- a/include/drivers/st/io_stm32image.h +++ b/include/drivers/st/io_stm32image.h -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef IO_STM32IMAGE_H -+#define IO_STM32IMAGE_H -+ -+#include -+#include -+ -+#define MAX_LBA_SIZE 512 -+#define MAX_PART_NAME_SIZE (EFI_NAMELEN + 1) -+#define STM32_PART_NUM (PLAT_PARTITION_MAX_ENTRIES - STM32_TF_A_COPIES) -+ -+struct stm32image_part_info { -+ char name[MAX_PART_NAME_SIZE]; -+ uint32_t binary_type; -+ uintptr_t part_offset; -+ uint32_t bkp_offset; -+}; -+ -+struct stm32image_device_info { -+ struct stm32image_part_info part_info[STM32_PART_NUM]; -+ uint32_t device_size; -+ uint32_t lba_size; -+}; -+ -+int register_io_dev_stm32image(const io_dev_connector_t **dev_con); -+ -+#endif /* IO_STM32IMAGE_H */ +@@ -23,7 +23,7 @@ struct stm32image_part_info { + + struct stm32image_device_info { + struct stm32image_part_info part_info[STM32_PART_NUM]; +- uint32_t device_size; ++ unsigned long long device_size; + uint32_t lba_size; + }; + diff --git a/include/drivers/st/io_uart.h b/include/drivers/st/io_uart.h new file mode 100644 -index 0000000..2f9ecb3 +index 000000000..86f9483a9 --- /dev/null +++ b/include/drivers/st/io_uart.h @@ -0,0 +1,12 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -26215,573 +27550,286 @@ index 0000000..2f9ecb3 +int register_io_dev_uart(const io_dev_connector_t **dev_con); + +#endif /* __IO_UART_H__ */ -diff --git a/include/drivers/st/nand.h b/include/drivers/st/nand.h +diff --git a/include/drivers/st/scmi-msg.h b/include/drivers/st/scmi-msg.h new file mode 100644 -index 0000000..f92511d +index 000000000..6fa597185 --- /dev/null -+++ b/include/drivers/st/nand.h -@@ -0,0 +1,252 @@ ++++ b/include/drivers/st/scmi-msg.h +@@ -0,0 +1,207 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ +/* -+ ****************************************************************************** -+ * @file nand.h -+ * @author mgentilini - MCD IntroPack team - MPU AP v1 bootROM project -+ * @version V0.1 -+ * @date 28-April-2016 -+ * @brief Header file for STM32MP1 Nand driver module. -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) STMicroelectronics

-+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ * -+ ****************************************************************************** ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2019, Linaro Limited + */ + -+#ifndef __NAND_H -+#define __NAND_H -+ -+#include -+ -+/* FMC NAND Flash 'common memory' data area */ -+#define FLASH_COMMON_MEM_BASE 0x80000000 -+/* FMC NAND Flash 'attribute memory' data area */ -+#define FLASH_ATTRIB_MEM_BASE 0x88000000 -+ -+#define BCH_PAGE_SECTOR 512 -+ -+/* BBM */ -+#define GOOD_BLOCK 0 -+#define BAD_BLOCK 1 -+ -+/**************** Bit definition for FMC_PCR register *******************/ -+/* Wait feature enable bit */ -+#define FMC_PCR_PWAITEN ((uint32_t)0x00000002) -+/* PC Card/NAND Flash memory bank enable bit */ -+#define FMC_PCR_PBKEN ((uint32_t)0x00000004) -+ -+/* PWID[1:0] bits (NAND Flash databus width) */ -+#define FMC_PCR_PWID ((uint32_t)0x00000030) -+#define FMC_PCR_PWID_0 ((uint32_t)0x00000010) /* Bit 0 */ -+#define FMC_PCR_PWID_1 ((uint32_t)0x00000020) /* Bit 1 */ -+ -+/* ECC computation logic enable bit */ -+#define FMC_PCR_ECCEN ((uint32_t)0x00000040) -+ -+/* ECC algorithm */ -+#define FMC_PCR_ECCALG ((uint32_t)0x00000100) -+ -+/* TCLR[3:0] bits (CLE to RE delay) */ -+#define FMC_PCR_TCLR_0 ((uint32_t)0x00000200) /* Bit 0 */ -+#define FMC_PCR_TCLR_1 ((uint32_t)0x00000400) /* Bit 1 */ -+#define FMC_PCR_TCLR_2 ((uint32_t)0x00000800) /* Bit 2 */ -+#define FMC_PCR_TCLR_3 ((uint32_t)0x00001000) /* Bit 3 */ -+ -+/* TAR[3:0] bits (ALE to RE delay) */ -+#define FMC_PCR_TAR_0 ((uint32_t)0x00002000) /* Bit 0 */ -+#define FMC_PCR_TAR_1 ((uint32_t)0x00004000) /* Bit 1 */ -+#define FMC_PCR_TAR_2 ((uint32_t)0x00008000) /* Bit 2 */ -+#define FMC_PCR_TAR_3 ((uint32_t)0x00010000) /* Bit 3 */ -+ -+/* ECCSS[1:0] bits (ECC sector size) */ -+#define FMC_PCR_ECCSS ((uint32_t)0x000E0000) -+#define FMC_PCR_ECCSS_0 ((uint32_t)0x00020000) /* Bit 0 */ -+#define FMC_PCR_ECCSS_1 ((uint32_t)0x00040000) /* Bit 1 */ -+#define FMC_PCR_ECCSS_2 ((uint32_t)0x00080000) /* Bit 2 */ -+ -+/* BCH Error correction capability */ -+#define FMC_PCR_BCHECC ((uint32_t)0x01000000) -+ -+/* Write enable */ -+#define FMC_PCR_WE ((uint32_t)0x02000000) -+ -+/**************** Bit definition for FMC_BCR1 register *******************/ -+/* FMC controller enable */ -+#define FMC_BCR1_FMCEN ((uint32_t)0x80000000) -+ -+/**************** Bit definition for FMC_BCHISR register *******************/ -+/* Decoder Error Ready Flag */ -+#define FMC_BCHISR_DERF ((uint32_t)0x00000002) -+/* Decoder Uncorrectable Error Flag */ -+#define FMC_BCHISR_DUEF ((uint32_t)0x00000001) -+/* Decoder Error Found Flag */ -+#define FMC_BCHISR_DEFF ((uint32_t)0x00000004) -+ -+/**************** Bit definition for FMC_BCHSR register *******************/ -+/* Decoder Error Number */ -+#define FMC_BCHSR_DEN ((uint32_t)0x0000000F) -+ -+/**************** Bit definition for FMC_BCHDSR0 register *******************/ -+/* Decoder Uncorrectable Error */ -+#define FMC_BCHDSR0_DUE ((uint32_t)0x00000001) -+/* Decoder Error Number */ -+#define FMC_BCHDSR0_DEN ((uint32_t)0x000000F0) -+ -+/**************** Bit definition for FMC_BCHDSR1 register *******************/ -+#define FMC_BCHDSR1_EBP1 ((uint32_t)0x00001FFF) -+#define FMC_BCHDSR1_EBP2 ((uint32_t)0x1FFF0000) -+ -+/**************** Bit definition for FMC_BCHDSR2 register *******************/ -+#define FMC_BCHDSR2_EBP1 ((uint32_t)0x00001FFF) -+#define FMC_BCHDSR2_EBP2 ((uint32_t)0x1FFF0000) -+ -+/**************** Bit definition for FMC_BCHDSR3 register *******************/ -+#define FMC_BCHDSR3_EBP1 ((uint32_t)0x00001FFF) -+#define FMC_BCHDSR3_EBP2 ((uint32_t)0x1FFF0000) -+ -+/**************** Bit definition for FMC_BCHDSR4 register *******************/ -+#define FMC_BCHDSR4_EBP1 ((uint32_t)0x00001FFF) -+#define FMC_BCHDSR4_EBP2 ((uint32_t)0x1FFF0000) -+ -+/**************** Bit definition for FMC_SR register **********************/ -+#define FMC_SR_NWRF ((uint32_t)0x00000040) -+#define FMC_SR_PF ((uint32_t)0x00000010) -+ -+#define FMC_NSEC_PER_SEC 1000000000L -+ -+/* Timings */ -+#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 -+ -+/* Register: FMC_PCR */ -+#define FMC_PCR_TCLR(x) (((x) & 0xf) << 9) -+#define FMC_PCR_TAR(x) (((x) & 0xf) << 13) -+ -+/* Register: FMC_PMEM */ -+#define FMC_PMEM_MEMSET(x) (((x) & 0xff) << 0) -+#define FMC_PMEM_MEMWAIT(x) (((x) & 0xff) << 8) -+#define FMC_PMEM_MEMHOLD(x) (((x) & 0xff) << 16) -+#define FMC_PMEM_MEMHIZ(x) (((x) & 0xff) << 24) -+ -+/* Register: FMC_PATT */ -+#define FMC_PATT_ATTSET(x) (((x) & 0xff) << 0) -+#define FMC_PATT_ATTWAIT(x) (((x) & 0xff) << 8) -+#define FMC_PATT_ATTHOLD(x) (((x) & 0xff) << 16) -+#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_EBP2_MASK 16 -+ -+/* 1st addressing cycle */ -+#define ADDR_1ST_CYCLE(__ADDRESS__) (uint8_t)(__ADDRESS__) -+/* 2nd addressing cycle */ -+#define ADDR_2ND_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 8) -+/* 3rd addressing cycle */ -+#define ADDR_3RD_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 16) -+/* 4th addressing cycle */ -+#define ADDR_4TH_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 24) -+ -+typedef struct { -+ uint8_t tclr; -+ uint8_t tar; -+ uint8_t thiz; -+ uint8_t twait; -+ uint8_t thold_mem; -+ uint8_t tset_mem; -+ uint8_t thold_att; -+ uint8_t tset_att; -+} nand_timings; -+ -+typedef struct { -+ uint32_t Signature; /* NAND Parameter page signature */ -+ -+ uint32_t PageSize; /* NAND memory page (without spare area) size -+ * measured in B -+ */ -+ -+ uint32_t BlockSize; /* NAND memory block size in number -+ * of pages -+ */ -+ -+ uint32_t BlockNb; /* NAND memory number of blocks */ -+ -+ uint32_t ZoneSize; /* NAND memory zone size measured in number -+ * of blocks -+ */ -+ -+ uint32_t BusWidth; /* NAND memory bus width in bytes */ -+ -+ uint32_t ECCcorrectability; /* NAND number of bits ECC correctability */ -+ -+ uint32_t page_size_shift; -+ uint32_t block_size_shift; -+ -+ nand_timings timings; -+ -+} NAND_InfoTypeDef; -+ -+/* NAND Memory address Structure definition */ -+typedef struct { -+ uint16_t Page; /* NAND memory Page address */ -+ -+ uint16_t Zone; /* NAND memory Zone address */ -+ -+ uint16_t Block; /* NAND memory Block address */ -+} NAND_AddressTypeDef; -+ -+/* NAND Memory electronic signature Structure definition */ -+typedef struct { -+ uint8_t Maker_Id; -+ -+ uint8_t Device_Id; -+} NAND_IDTypeDef; -+ -+/* NAND handle Structure definition */ -+typedef struct { -+ FMC_TypeDef *Instance; /* Register base address */ -+ -+ NAND_InfoTypeDef Info; /* NAND characteristic information structure */ -+} NAND_HandleTypeDef; -+ -+/* Exported functions */ -+Std_ReturnType nand_initialize(NAND_HandleTypeDef *hnand); -+Std_ReturnType NAND_Read_Logical_Page(NAND_HandleTypeDef *hNand, -+ NAND_AddressTypeDef *Address, -+ uint8_t *Buffer, uint32_t bch_sector_nb); -+uint32_t NAND_Check_Bad_Block(NAND_HandleTypeDef *hNand, -+ NAND_AddressTypeDef *Address); -+Std_ReturnType NAND_Address_Inc(NAND_HandleTypeDef *hNand, -+ NAND_AddressTypeDef *Address, -+ uint32_t numPagesRead); -+ -+#endif /* __NAND_H */ -+ -diff --git a/include/drivers/st/stm32_console.h b/include/drivers/st/stm32_console.h -new file mode 100644 -index 0000000..57e6d74 ---- /dev/null -+++ b/include/drivers/st/stm32_console.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_CONSOLE_H -+#define STM32_CONSOLE_H -+ -+#include -+ -+#define CONSOLE_T_STM32_BASE CONSOLE_T_DRVDATA -+ -+#ifndef __ASSEMBLY__ ++#ifndef SCMI_MSG_H ++#define SCMI_MSG_H + ++#include ++#include +#include + -+struct console_stm32 { -+ console_t console; -+ uintptr_t base; ++/* Minimum size expected for SMT based shared memory message buffers */ ++#define SMT_BUF_SLOT_SIZE 128U ++ ++/* A channel abstract a communication path between agent and server */ ++struct scmi_msg_channel; ++ ++/* ++ * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel ++ * ++ * @shm_addr: Address of the shared memory for the SCMI channel ++ * @shm_size: Byte size of the shared memory for the SCMI channel ++ * @busy: True when channel is busy, flase when channel is free ++ * @agent_name: Agent name or NULL, SCMI protocol exposes 16 bytes max. ++ */ ++struct scmi_msg_channel { ++ uintptr_t shm_addr; ++ size_t shm_size; ++ bool busy; ++ const char *agent_name; +}; + +/* -+ * Initialize a new STM32 console instance and register it with the console -+ * framework. The |console| pointer must point to storage that will be valid -+ * for the lifetime of the console, such as a global or static local variable. -+ * Its contents will be reinitialized from scratch. ++ * Initialize SMT memory buffer, called by platform at init for each ++ * agent channel using the SMT header format. ++ * ++ * @chan: Pointer to the channel shared memory to be initialized + */ -+int console_stm32_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, -+ struct console_stm32 *console); ++void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan); + -+#endif /*__ASSEMBLY__*/ ++/* ++ * Process SMT formatted message in a fastcall SMC execution context. ++ * Called by platform on SMC entry. When returning, output message is ++ * available in shared memory for agent to read the response. ++ * ++ * @agent_id: SCMI agent ID the SMT belongs to ++ */ ++void scmi_smt_fastcall_smc_entry(unsigned int agent_id); + -+#endif /* STM32_CONSOLE_H */ -diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h -index 7a5ccd3..33cef04 100644 ---- a/include/drivers/st/stm32_gpio.h -+++ b/include/drivers/st/stm32_gpio.h -@@ -4,15 +4,11 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef __PLAT_GPIO_H__ --#define __PLAT_GPIO_H__ -+#ifndef STM32_GPIO_H -+#define STM32_GPIO_H - - #include - --#define STM32_GPIOA_BANK U(0x50002000) --#define STM32_GPIOZ_BANK U(0x54004000) --#define STM32_GPIO_BANK_OFFSET U(0x1000) -- - #define GPIO_MODE_OFFSET U(0x00) - #define GPIO_TYPE_OFFSET U(0x04) - #define GPIO_SPEED_OFFSET U(0x08) -@@ -20,56 +16,14 @@ - #define GPIO_BSRR_OFFSET U(0x18) - #define GPIO_AFRL_OFFSET U(0x20) - #define GPIO_AFRH_OFFSET U(0x24) -+#define GPIO_SECR_OFFSET U(0x30) - - #define GPIO_ALT_LOWER_LIMIT U(0x08) - --#define GPIO_BANK_A U(0x00) --#define GPIO_BANK_B U(0x01) --#define GPIO_BANK_C U(0x02) --#define GPIO_BANK_D U(0x03) --#define GPIO_BANK_E U(0x04) --#define GPIO_BANK_F U(0x05) --#define GPIO_BANK_G U(0x06) --#define GPIO_BANK_H U(0x07) --#define GPIO_BANK_I U(0x08) --#define GPIO_BANK_J U(0x09) --#define GPIO_BANK_K U(0x0A) --#define GPIO_BANK_Z U(0x19) -- --#define GPIO_PIN_0 U(0x00) --#define GPIO_PIN_1 U(0x01) --#define GPIO_PIN_2 U(0x02) --#define GPIO_PIN_3 U(0x03) --#define GPIO_PIN_4 U(0x04) --#define GPIO_PIN_5 U(0x05) --#define GPIO_PIN_6 U(0x06) --#define GPIO_PIN_7 U(0x07) --#define GPIO_PIN_8 U(0x08) --#define GPIO_PIN_9 U(0x09) --#define GPIO_PIN_10 U(0x0A) --#define GPIO_PIN_11 U(0x0B) --#define GPIO_PIN_12 U(0x0C) --#define GPIO_PIN_13 U(0x0D) --#define GPIO_PIN_14 U(0x0E) --#define GPIO_PIN_15 U(0x0F) --#define GPIO_PIN_MAX GPIO_PIN_15 -+#define GPIO_PIN_(_x) U(_x) -+#define GPIO_PIN_MAX GPIO_PIN_(15) - --#define GPIO_ALTERNATE_0 0x00 --#define GPIO_ALTERNATE_1 0x01 --#define GPIO_ALTERNATE_2 0x02 --#define GPIO_ALTERNATE_3 0x03 --#define GPIO_ALTERNATE_4 0x04 --#define GPIO_ALTERNATE_5 0x05 --#define GPIO_ALTERNATE_6 0x06 --#define GPIO_ALTERNATE_7 0x07 --#define GPIO_ALTERNATE_8 0x08 --#define GPIO_ALTERNATE_9 0x09 --#define GPIO_ALTERNATE_10 0x0A --#define GPIO_ALTERNATE_11 0x0B --#define GPIO_ALTERNATE_12 0x0C --#define GPIO_ALTERNATE_13 0x0D --#define GPIO_ALTERNATE_14 0x0E --#define GPIO_ALTERNATE_15 0x0F -+#define GPIO_ALTERNATE_(_x) U(_x) - #define GPIO_ALTERNATE_MASK U(0x0F) - - #define GPIO_MODE_INPUT 0x00 -@@ -82,8 +36,8 @@ - - #define GPIO_SPEED_LOW 0x00 - #define GPIO_SPEED_MEDIUM 0x01 --#define GPIO_SPEED_FAST 0x02 --#define GPIO_SPEED_HIGH 0x03 -+#define GPIO_SPEED_HIGH 0x02 -+#define GPIO_SPEED_VERY_HIGH 0x03 - #define GPIO_SPEED_MASK U(0x03) - - #define GPIO_NO_PULL 0x00 -@@ -94,8 +48,10 @@ - #ifndef __ASSEMBLY__ - #include - -+int dt_set_pinctrl_config(int node); - void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, -- uint32_t pull, uint32_t alternate); -+ uint32_t pull, uint32_t alternate, uint8_t status); -+void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); - #endif /*__ASSEMBLY__*/ - --#endif /*__PLAT_GPIO_H__*/ -+#endif /* STM32_GPIO_H */ -diff --git a/include/drivers/st/stm32_hal_hash_reg.h b/include/drivers/st/stm32_hal_hash_reg.h ++/* ++ * Process SMT formatted message in a secure interrupt execution context. ++ * Called by platform interrupt handler. When returning, output message is ++ * available in shared memory for agent to read the response. ++ * ++ * @agent_id: SCMI agent ID the SMT belongs to ++ */ ++void scmi_smt_interrupt_entry(unsigned int agent_id); ++ ++/* Platform callback functions */ ++ ++/* ++ * Return the SCMI channel related to an agent ++ * @agent_id: SCMI agent ID ++ * Return a pointer to channel on success, NULL otherwise ++ */ ++struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id); ++ ++/* ++ * Return how many SCMI protocols supported by the platform ++ * According to the SCMI specification, this function does not target ++ * a specific agent ID and shall return all platform known capabilities. ++ */ ++size_t plat_scmi_protocol_count(void); ++ ++/* ++ * Get the count and list of SCMI protocols (but base) supported for an agent ++ * ++ * @agent_id: SCMI agent ID ++ * Return a pointer to a null terminated array supported protocol IDs. ++ */ ++const uint8_t *plat_scmi_protocol_list(unsigned int agent_id); ++ ++/* Get the name of the SCMI vendor for the platform */ ++const char *plat_scmi_vendor_name(void); ++ ++/* Get the name of the SCMI sub-vendor for the platform */ ++const char *plat_scmi_sub_vendor_name(void); ++ ++/* Handlers for SCMI Clock protocol services */ ++ ++/* ++ * Return number of clock controllers for an agent ++ * @agent_id: SCMI agent ID ++ * Return number of clock controllers ++ */ ++size_t plat_scmi_clock_count(unsigned int agent_id); ++ ++/* ++ * Get clock controller string ID (aka name) ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * Return pointer to name or NULL ++ */ ++const char *plat_scmi_clock_get_name(unsigned int agent_id, ++ unsigned int scmi_id); ++ ++/* ++ * Get clock possible rate as an array of frequencies in Hertz. ++ * ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * @rates: If NULL, function returns, else output rates array ++ * @nb_elts: Array size of @rates. ++ * Return an SCMI compliant error code ++ */ ++int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, ++ unsigned long *rates, size_t *nb_elts); ++ ++/* ++ * Get clock possible rate as range with regular steps in Hertz ++ * ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * @min_max_step: 3 cell array for min, max and step rate data ++ * Return an SCMI compliant error code ++ */ ++int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id, ++ unsigned int scmi_id, ++ unsigned long *min_max_step); ++ ++/* ++ * Get clock rate in Hertz ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * Return clock rate or 0 if not supported ++ */ ++unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, ++ unsigned int scmi_id); ++ ++/* ++ * Set clock rate in Hertz ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * @rate: Target clock frequency in Hertz ++ * Return a compliant SCMI error code ++ */ ++int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id, ++ unsigned long rate); ++ ++/* ++ * Get clock state (enabled or disabled) ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code ++ */ ++int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id); ++ ++/* ++ * Get clock state (enabled or disabled) ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI clock ID ++ * @enable_not_disable: Enable clock if true, disable clock otherwise ++ * Return a compliant SCMI error code ++ */ ++int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, ++ bool enable_not_disable); ++ ++/* Handlers for SCMI Reset Domain protocol services */ ++ ++/* ++ * Return number of reset domains for the agent ++ * @agent_id: SCMI agent ID ++ * Return number of reset domains ++ */ ++size_t plat_scmi_rd_count(unsigned int agent_id); ++ ++/* ++ * Get reset domain string ID (aka name) ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI reset domain ID ++ * Return pointer to name or NULL ++ */ ++const char *plat_scmi_rd_get_name(unsigned int agent_id, unsigned int scmi_id); ++ ++/* ++ * Perform a reset cycle on a target reset domain ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI reset domain ID ++ * @state: Target reset state (see SCMI specification, 0 means context loss) ++ * Return a compliant SCMI error code ++ */ ++int32_t plat_scmi_rd_autonomous(unsigned int agent_id, unsigned int scmi_id, ++ unsigned int state); ++ ++/* ++ * Assert or deassert target reset domain ++ * @agent_id: SCMI agent ID ++ * @scmi_id: SCMI reset domain ID ++ * @assert_not_deassert: Assert domain if true, otherwise deassert domain ++ * Return a compliant SCMI error code ++ */ ++int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id, ++ bool assert_not_deassert); ++ ++#endif /* SCMI_MSG_H */ +diff --git a/include/drivers/st/scmi.h b/include/drivers/st/scmi.h new file mode 100644 -index 0000000..e7a589b +index 000000000..ac9c798f0 --- /dev/null -+++ b/include/drivers/st/stm32_hal_hash_reg.h -@@ -0,0 +1,136 @@ -+/** -+ ****************************************************************************** -+ * @file stm32_hal_hash_reg.h -+ * @author MCD Intropack Team - MPU AP v1 bootROM project -+ * @date 22 September 2015 -+ * @brief STM32 Device Peripheral Access Layer Header File. -+ * -+ * This file contains: -+ * - Data structures and the address mapping for all peripherals -+ * - Peripheral's registers declarations and bits definition -+ * - Macros to access peripherals registers hardware -+ * -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) 2015 STMicroelectronics

-+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ * -+ ****************************************************************************** -+ */ ++++ b/include/drivers/st/scmi.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. ++ */ ++#ifndef SCMI_MSG_SCMI_H ++#define SCMI_MSG_SCMI_H + -+#ifndef _STM32_HAL_HASH_REG_H_ -+#define _STM32_HAL_HASH_REG_H_ ++#define SCMI_PROTOCOL_ID_BASE 0x10 ++#define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11 ++#define SCMI_PROTOCOL_ID_SYS_POWER 0x12 ++#define SCMI_PROTOCOL_ID_PERF 0x13 ++#define SCMI_PROTOCOL_ID_CLOCK 0x14 ++#define SCMI_PROTOCOL_ID_SENSOR 0x15 ++#define SCMI_PROTOCOL_ID_RESET_DOMAIN 0x16 + -+#ifdef __cplusplus -+ extern "C" { -+#endif /* __cplusplus */ ++/* SCMI error codes reported to agent through server-to-agent messages */ ++#define SCMI_SUCCESS 0 ++#define SCMI_NOT_SUPPORTED (-1) ++#define SCMI_INVALID_PARAMETERS (-2) ++#define SCMI_DENIED (-3) ++#define SCMI_NOT_FOUND (-4) ++#define SCMI_OUT_OF_RANGE (-5) ++#define SCMI_BUSY (-6) ++#define SCMI_COMMS_ERROR (-7) ++#define SCMI_GENERIC_ERROR (-8) ++#define SCMI_HARDWARE_ERROR (-9) ++#define SCMI_PROTOCOL_ERROR (-10) + ++#endif /* SCMI_MSG_SCMI_H */ +diff --git a/include/drivers/st/stm32_fmc2_nand.h b/include/drivers/st/stm32_fmc2_nand.h +new file mode 100644 +index 000000000..81d5b9de1 +--- /dev/null ++++ b/include/drivers/st/stm32_fmc2_nand.h +@@ -0,0 +1,12 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ + -+/** @addtogroup Peripheral_registers_structures -+ * @{ -+ */ ++#ifndef STM32_FMC2_NAND_H ++#define STM32_FMC2_NAND_H + -+/** -+ * @brief Secure digital input/output Interface -+ */ -+#ifndef __ASM_INCLUDE__ -+/** -+ * @brief HASH -+ */ -+ -+typedef struct -+{ -+ __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ -+ __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ -+ __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ -+ __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ -+ __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ -+ __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ -+ uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ -+ __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ -+} HASH_TypeDef; -+#endif /* __ASM_INCLUDE__ */ ++int stm32_fmc2_init(void); + -+#ifndef __ASM_INCLUDE__ -+/** -+ * @brief HASH_DIGEST -+ */ -+ -+typedef struct -+{ -+ __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ -+} HASH_DIGEST_TypeDef; -+#endif /* __ASM_INCLUDE__ */ -+ -+ -+ -+ -+ -+/** @addtogroup Exported_constants -+ * @{ -+ */ -+ -+ /** @addtogroup Peripheral_Registers_Bits_Definition -+ * @{ -+ */ -+ -+/****************** Bits definition for HASH_CR register ********************/ -+#define HASH_CR_INIT ((uint32_t)0x00000004) -+#define HASH_CR_DMAE ((uint32_t)0x00000008) -+#define HASH_CR_DATATYPE ((uint32_t)0x00000030) -+#define HASH_CR_DATATYPE_0 ((uint32_t)0x00000010) -+#define HASH_CR_DATATYPE_1 ((uint32_t)0x00000020) -+#define HASH_CR_MODE ((uint32_t)0x00000040) -+#define HASH_CR_ALGO ((uint32_t)0x00040080) -+#define HASH_CR_ALGO_0 ((uint32_t)0x00000080) -+#define HASH_CR_ALGO_1 ((uint32_t)0x00040000) -+#define HASH_CR_NBW ((uint32_t)0x00000F00) -+#define HASH_CR_NBW_0 ((uint32_t)0x00000100) -+#define HASH_CR_NBW_1 ((uint32_t)0x00000200) -+#define HASH_CR_NBW_2 ((uint32_t)0x00000400) -+#define HASH_CR_NBW_3 ((uint32_t)0x00000800) -+#define HASH_CR_DINNE ((uint32_t)0x00001000) -+#define HASH_CR_MDMAT ((uint32_t)0x00002000) -+#define HASH_CR_LKEY ((uint32_t)0x00010000) -+ -+/****************** Bits definition for HASH_STR register *******************/ -+#define HASH_STR_NBW ((uint32_t)0x0000001F) -+#define HASH_STR_NBW_0 ((uint32_t)0x00000001) -+#define HASH_STR_NBW_1 ((uint32_t)0x00000002) -+#define HASH_STR_NBW_2 ((uint32_t)0x00000004) -+#define HASH_STR_NBW_3 ((uint32_t)0x00000008) -+#define HASH_STR_NBW_4 ((uint32_t)0x00000010) -+#define HASH_STR_DCAL ((uint32_t)0x00000100) -+ -+/****************** Bits definition for HASH_IMR register *******************/ -+#define HASH_IMR_DINIM ((uint32_t)0x00000001) -+#define HASH_IMR_DCIM ((uint32_t)0x00000002) -+ -+/****************** Bits definition for HASH_SR register ********************/ -+#define HASH_SR_DINIS ((uint32_t)0x00000001) -+#define HASH_SR_DCIS ((uint32_t)0x00000002) -+#define HASH_SR_DMAS ((uint32_t)0x00000004) -+#define HASH_SR_BUSY ((uint32_t)0x00000008) -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+ -+/** -+ * @} -+ */ -+ -+#ifdef __cplusplus -+} -+#endif /* __cplusplus */ -+ -+#endif /* _STM32_HAL_HASH_REG_H_ */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ ++#endif /* STM32_FMC2_NAND_H */ diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h -index 29b9d34..4d5e302 100644 +index 170d4cf81..e1a3782b2 100644 --- a/include/drivers/st/stm32_i2c.h +++ b/include/drivers/st/stm32_i2c.h -@@ -1,11 +1,11 @@ +@@ -1,7 +1,7 @@ /* - * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved * - * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ --#ifndef __STM32MP1_I2C_H --#define __STM32MP1_I2C_H -+#ifndef STM32_I2C_H -+#define STM32_I2C_H - - #include - #include -@@ -72,6 +72,21 @@ + #ifndef STM32_I2C_H +@@ -73,6 +73,21 @@ #define I2C_TIMINGR_SDADEL GENMASK(19, 16) #define I2C_TIMINGR_SCLDEL GENMASK(23, 20) #define I2C_TIMINGR_PRESC GENMASK(31, 28) @@ -26803,356 +27851,90 @@ index 29b9d34..4d5e302 100644 /* Bit definition for I2C_TIMEOUTR register */ #define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0) -@@ -110,94 +125,113 @@ +@@ -111,15 +126,9 @@ #define I2C_ICR_TIMOUTCF BIT(12) #define I2C_ICR_ALERTCF BIT(13) --struct stm32_i2c_init_s { -- uint32_t timing; /* Specifies the I2C_TIMINGR_register value -- * This parameter is calculated by referring -- * to I2C initialization section in Reference -- * manual. -- */ +-enum i2c_speed_e { +- I2C_SPEED_STANDARD, /* 100 kHz */ +- I2C_SPEED_FAST, /* 400 kHz */ +- I2C_SPEED_FAST_PLUS, /* 1 MHz */ +-}; - -- uint32_t own_address1; /* Specifies the first device own address. -- * This parameter can be a 7-bit or 10-bit -- * address. -- */ -- -- uint32_t addressing_mode; /* Specifies if 7-bit or 10-bit addressing -- * mode is selected. -- * This parameter can be a value of @ref -- * I2C_ADDRESSING_MODE. -- */ -- -- uint32_t dual_address_mode; /* Specifies if dual addressing mode is -- * selected. -- * This parameter can be a value of @ref -- * I2C_DUAL_ADDRESSING_MODE. -- */ -- -- uint32_t own_address2; /* Specifies the second device own address -- * if dual addressing mode is selected. -- * This parameter can be a 7-bit address. -- */ -- -- uint32_t own_address2_masks; /* Specifies the acknowledge mask address -- * second device own address if dual -- * addressing mode is selected. -- * This parameter can be a value of @ref -- * I2C_OWN_ADDRESS2_MASKS. -- */ -- -- uint32_t general_call_mode; /* Specifies if general call mode is -- * selected. -- * This parameter can be a value of @ref -- * I2C_GENERAL_CALL_ADDRESSING_MODE. -- */ -- -- uint32_t no_stretch_mode; /* Specifies if nostretch mode is -- * selected. -- * This parameter can be a value of @ref -- * I2C_NOSTRETCH_MODE. -- */ -+enum i2c_speed_e { -+ I2C_SPEED_STANDARD, /* 100 kHz */ -+ I2C_SPEED_FAST, /* 400 kHz */ -+ I2C_SPEED_FAST_PLUS, /* 1 MHz */ -+}; -+ -+#define STANDARD_RATE 100000 -+#define FAST_RATE 400000 -+#define FAST_PLUS_RATE 1000000 +-#define STANDARD_RATE 100000 +-#define FAST_RATE 400000 +-#define FAST_PLUS_RATE 1000000 ++#define STANDARD_RATE 100000 ++#define FAST_RATE 400000 ++#define FAST_PLUS_RATE 1000000 -+struct stm32_i2c_init_s { -+ uint32_t own_address1; /* -+ * Specifies the first device own -+ * address. This parameter can be a -+ * 7-bit or 10-bit address. -+ */ -+ -+ uint32_t addressing_mode; /* -+ * Specifies if 7-bit or 10-bit -+ * addressing mode is selected. -+ * This parameter can be a value of -+ * @ref I2C_ADDRESSING_MODE. -+ */ -+ -+ uint32_t dual_address_mode; /* -+ * Specifies if dual addressing mode is -+ * selected. -+ * This parameter can be a value of @ref -+ * I2C_DUAL_ADDRESSING_MODE. -+ */ -+ -+ uint32_t own_address2; /* -+ * Specifies the second device own -+ * address if dual addressing mode is -+ * selected. This parameter can be a -+ * 7-bit address. -+ */ -+ -+ uint32_t own_address2_masks; /* -+ * Specifies the acknowledge mask -+ * address second device own address -+ * if dual addressing mode is selected -+ * This parameter can be a value of @ref -+ * I2C_OWN_ADDRESS2_MASKS. -+ */ -+ -+ uint32_t general_call_mode; /* -+ * Specifies if general call mode is -+ * selected. -+ * This parameter can be a value of @ref -+ * I2C_GENERAL_CALL_ADDRESSING_MODE. -+ */ -+ -+ uint32_t no_stretch_mode; /* -+ * Specifies if nostretch mode is -+ * selected. -+ * This parameter can be a value of @ref -+ * I2C_NOSTRETCH_MODE. -+ */ -+ -+ uint32_t rise_time; /* -+ * Specifies the SCL clock pin rising -+ * time in nanoseconds. -+ */ -+ -+ uint32_t fall_time; /* -+ * Specifies the SCL clock pin falling -+ * time in nanoseconds. -+ */ -+ -+ enum i2c_speed_e speed_mode; /* -+ * Specifies the I2C clock source -+ * frequency mode. -+ * This parameter can be a value of @ref -+ * i2c_speed_mode_e. -+ */ -+ -+ int analog_filter; /* -+ * Specifies if the I2C analog noise -+ * filter is selected. -+ * This parameter can be 0 (filter -+ * off), all other values mean filter -+ * on. -+ */ -+ -+ uint8_t digital_filter_coef; /* -+ * Specifies the I2C digital noise -+ * filter coefficient. -+ * This parameter can be a value -+ * between 0 and -+ * STM32_I2C_DIGITAL_FILTER_MAX. -+ */ + struct stm32_i2c_init_s { + uint32_t own_address1; /* +@@ -181,12 +190,7 @@ struct stm32_i2c_init_s { + * time in nanoseconds. + */ + +- enum i2c_speed_e speed_mode; /* +- * Specifies the I2C clock source +- * frequency mode. +- * This parameter can be a value of @ref +- * i2c_speed_mode_e. +- */ ++ uint32_t bus_rate; /* Specifies the I2C clock frequency */ + + int analog_filter; /* + * Specifies if the I2C analog noise +@@ -238,6 +242,8 @@ struct i2c_handle_s { + enum i2c_state_e i2c_state; /* Communication state */ + enum i2c_mode_e i2c_mode; /* Communication mode */ + uint32_t i2c_err; /* Error code */ ++ uint32_t saved_timing; /* Saved timing value */ ++ uint32_t saved_frequency; /* Saved frequency value */ }; - enum i2c_state_e { -- I2C_STATE_RESET = 0x00U, /* Peripheral is not yet -- * initialized. -- */ -- I2C_STATE_READY = 0x20U, /* Peripheral Initialized -- * and ready for use. -- */ -- I2C_STATE_BUSY = 0x24U, /* An internal process is -- * ongoing. -- */ -- I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission process -- * is ongoing. -- */ -- I2C_STATE_BUSY_RX = 0x22U, /* Data Reception process -- * is ongoing. -- */ -- I2C_STATE_LISTEN = 0x28U, /* Address Listen Mode is -- * ongoing. -- */ -- I2C_STATE_BUSY_TX_LISTEN = 0x29U, /* Address Listen Mode -- * and Data Transmission -- * process is ongoing. -- */ -- I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /* Address Listen Mode -- * and Data Reception -- * process is ongoing. -- */ -- I2C_STATE_ABORT = 0x60U, /* Abort user request ongoing. */ -- I2C_STATE_TIMEOUT = 0xA0U, /* Timeout state. */ -- I2C_STATE_ERROR = 0xE0U /* Error. */ -- -+ I2C_STATE_RESET = 0x00U, /* Not yet initialized */ -+ I2C_STATE_READY = 0x20U, /* Ready for use */ -+ I2C_STATE_BUSY = 0x24U, /* Internal process ongoing */ -+ I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission ongoing */ -+ I2C_STATE_BUSY_RX = 0x22U, /* Data Reception ongoing */ - }; + #define I2C_ADDRESSINGMODE_7BIT 0x00000001U +@@ -299,8 +305,7 @@ struct i2c_handle_s { + #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ + #define STM32_I2C_DIGITAL_FILTER_MAX 16 - enum i2c_mode_e { -- I2C_MODE_NONE = 0x00U, /* No I2C communication on going. */ -- I2C_MODE_MASTER = 0x10U, /* I2C communication is in Master Mode. */ -- I2C_MODE_SLAVE = 0x20U, /* I2C communication is in Slave Mode. */ -- I2C_MODE_MEM = 0x40U /* I2C communication is in Memory Mode. */ -+ I2C_MODE_NONE = 0x00U, /* No active communication */ -+ I2C_MODE_MASTER = 0x10U, /* Communication in Master Mode */ -+ I2C_MODE_SLAVE = 0x20U, /* Communication in Slave Mode */ -+ I2C_MODE_MEM = 0x40U /* Communication in Memory Mode */ - - }; - -@@ -212,52 +246,38 @@ enum i2c_mode_e { - - struct i2c_handle_s { - uint32_t i2c_base_addr; /* Registers base address */ -- -- struct stm32_i2c_init_s i2c_init; /* Communication parameters */ -- -- uint8_t *p_buff; /* Pointer to transfer buffer */ -- -- uint16_t xfer_size; /* Transfer size */ -- -- uint16_t xfer_count; /* Transfer counter */ -- -- uint32_t prev_state; /* Communication previous -- * state -- */ -- -- uint8_t lock; /* Locking object */ -- -- enum i2c_state_e i2c_state; /* Communication state */ -- -- enum i2c_mode_e i2c_mode; /* Communication mode */ -- -- uint32_t i2c_err; /* Error code */ -+ unsigned int dt_status; /* DT nsec/sec status */ -+ unsigned int clock; /* Clock reference */ -+ uint8_t lock; /* Locking object */ -+ enum i2c_state_e i2c_state; /* Communication state */ -+ enum i2c_mode_e i2c_mode; /* Communication mode */ -+ uint32_t i2c_err; /* Error code */ - }; - --#define I2C_ADDRESSINGMODE_7BIT 0x00000001U --#define I2C_ADDRESSINGMODE_10BIT 0x00000002U -+#define I2C_ADDRESSINGMODE_7BIT 0x00000001U -+#define I2C_ADDRESSINGMODE_10BIT 0x00000002U - --#define I2C_DUALADDRESS_DISABLE 0x00000000U --#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN -+#define I2C_DUALADDRESS_DISABLE 0x00000000U -+#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN - --#define I2C_GENERALCALL_DISABLE 0x00000000U --#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN -+#define I2C_GENERALCALL_DISABLE 0x00000000U -+#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN - --#define I2C_NOSTRETCH_DISABLE 0x00000000U --#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH -+#define I2C_NOSTRETCH_DISABLE 0x00000000U -+#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH - --#define I2C_MEMADD_SIZE_8BIT 0x00000001U --#define I2C_MEMADD_SIZE_16BIT 0x00000002U -+#define I2C_MEMADD_SIZE_8BIT 0x00000001U -+#define I2C_MEMADD_SIZE_16BIT 0x00000002U - --#define I2C_RELOAD_MODE I2C_CR2_RELOAD --#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND --#define I2C_SOFTEND_MODE 0x00000000U -+#define I2C_RELOAD_MODE I2C_CR2_RELOAD -+#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND -+#define I2C_SOFTEND_MODE 0x00000000U - --#define I2C_NO_STARTSTOP 0x00000000U --#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) --#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ -- I2C_CR2_RD_WRN) --#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) -+#define I2C_NO_STARTSTOP 0x00000000U -+#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) -+#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ -+ I2C_CR2_RD_WRN) -+#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) - - #define I2C_FLAG_TXE I2C_ISR_TXE - #define I2C_FLAG_TXIS I2C_ISR_TXIS -@@ -280,21 +300,36 @@ struct i2c_handle_s { - I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ - I2C_CR2_RD_WRN) - --#define I2C_ANALOGFILTER_ENABLE ((uint32_t)0x00000000U) --#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF -+#define I2C_TIMEOUT_BUSY_MS 25U - --int stm32_i2c_init(struct i2c_handle_s *hi2c); -+#define I2C_ANALOGFILTER_ENABLE 0x00000000U -+#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF - -+/* STM32 specific defines */ -+#define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */ -+#define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */ -+#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD -+#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ -+#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ -+#define STM32_I2C_DIGITAL_FILTER_MAX 16 -+ -+int stm32_i2c_get_setup_from_fdt(void *fdt, int node, -+ struct stm32_i2c_init_s *init); -+int stm32_i2c_init(struct i2c_handle_s *hi2c, -+ struct stm32_i2c_init_s *init_data); +-int stm32_i2c_get_setup_from_fdt(void *fdt, int node, +- struct stm32_i2c_init_s *init); ++int stm32_i2c_get_setup_from_fdt(int node, struct stm32_i2c_init_s *init); + int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data); int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, - uint16_t mem_addr, uint16_t mem_add_size, -- uint8_t *p_data, uint16_t size, uint32_t timeout); -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms); - int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, - uint16_t mem_addr, uint16_t mem_add_size, -- uint8_t *p_data, uint16_t size, uint32_t timeout); --int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, -- uint32_t trials, uint32_t timeout); -- --int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c, -- uint32_t analog_filter); -- --#endif /* __STM32MP1_I2C_H */ -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms); -+int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms); -+int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms); -+bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint32_t trials, uint32_t timeout_ms); -+ -+#endif /* STM32_I2C_H */ diff --git a/include/drivers/st/stm32_iwdg.h b/include/drivers/st/stm32_iwdg.h -new file mode 100644 -index 0000000..b6d4769 ---- /dev/null +index bad25244a..c0c009779 100644 +--- a/include/drivers/st/stm32_iwdg.h +++ b/include/drivers/st/stm32_iwdg.h -@@ -0,0 +1,20 @@ +@@ -15,5 +15,6 @@ + + int stm32_iwdg_init(void); + void stm32_iwdg_refresh(void); ++void __dead2 stm32_iwdg_it_handler(int id); + + #endif /* STM32_IWDG_H */ +diff --git a/include/drivers/st/stm32_qspi.h b/include/drivers/st/stm32_qspi.h +new file mode 100644 +index 000000000..f47fca445 +--- /dev/null ++++ b/include/drivers/st/stm32_qspi.h +@@ -0,0 +1,12 @@ +/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * -+ * SPDX-License-Identifier: BSD-3-Clause ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + -+#ifndef __STM32_IWDG_H__ -+#define __STM32_IWDG_H__ ++#ifndef STM32_QSPI_H ++#define STM32_QSPI_H + -+#include ++int stm32_qspi_init(void); + -+#define IWDG_HW_ENABLED BIT(0) -+#define IWDG_ENABLE_ON_STOP BIT(1) -+#define IWDG_ENABLE_ON_STANDBY BIT(2) -+ -+int stm32_iwdg_init(void); -+void stm32_iwdg_refresh(uint32_t instance); -+void __dead2 stm32_iwdg_it_handler(int id); -+ -+#endif /* __STM32_IWDG_H__ */ ++#endif /* STM32_QSPI_H */ diff --git a/include/drivers/st/stm32_rng.h b/include/drivers/st/stm32_rng.h new file mode 100644 -index 0000000..a644118 +index 000000000..a64411865 --- /dev/null +++ b/include/drivers/st/stm32_rng.h @@ -0,0 +1,13 @@ @@ -27171,19 +27953,18 @@ index 0000000..a644118 +#endif /* STM32_RNG_H */ diff --git a/include/drivers/st/stm32_rtc.h b/include/drivers/st/stm32_rtc.h new file mode 100644 -index 0000000..bc9e61e +index 000000000..128dd2d14 --- /dev/null +++ b/include/drivers/st/stm32_rtc.h -@@ -0,0 +1,79 @@ +@@ -0,0 +1,78 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __PLAT_RTC_H__ -+#define __PLAT_RTC_H__ ++#ifndef STM32_RTC_H ++#define STM32_RTC_H + +#include + @@ -27253,58 +28034,41 @@ index 0000000..bc9e61e +void stm32_rtc_regs_lock(void); +void stm32_rtc_regs_unlock(void); + -+#endif /* __PLAT_RTC_H__ */ ++#endif /* STM32_RTC_H */ diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h -new file mode 100644 -index 0000000..b172659 ---- /dev/null +index 4853208c2..5b4bd0e16 100644 +--- a/include/drivers/st/stm32_sdmmc2.h +++ b/include/drivers/st/stm32_sdmmc2.h -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_SDMMC2_H -+#define STM32_SDMMC2_H -+ -+#include -+#include -+ -+struct stm32_sdmmc2_params { -+ uintptr_t reg_base; -+ unsigned int clk_rate; -+ unsigned int bus_width; -+ unsigned int flags; -+ struct mmc_device_info *device_info; -+ unsigned int pin_ckin; -+ unsigned int negedge; -+ unsigned int dirpol; -+ unsigned int clock_id; -+ unsigned int reset_id; -+ bool use_dma; -+}; -+ -+unsigned long long stm32_sdmmc2_mmc_get_device_size(void); -+int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params); -+bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory); -+ -+#endif /* STM32_SDMMC2_H */ +@@ -10,6 +10,7 @@ + #include + + #include ++#include + + struct stm32_sdmmc2_params { + uintptr_t reg_base; +@@ -24,6 +25,7 @@ struct stm32_sdmmc2_params { + unsigned int reset_id; + unsigned int max_freq; + bool use_dma; ++ struct stm32mp_regulator vmmc_regu; + }; + + unsigned long long stm32_sdmmc2_mmc_get_device_size(void); diff --git a/include/drivers/st/stm32_tamp.h b/include/drivers/st/stm32_tamp.h new file mode 100644 -index 0000000..3933c26 +index 000000000..a4a6a964f --- /dev/null +++ b/include/drivers/st/stm32_tamp.h @@ -0,0 +1,163 @@ +/* -+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2014-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __TAMPER_H__ -+#define __TAMPER_H__ ++#ifndef STM32_TAMP_H ++#define STM32_TAMP_H + +/* Internal Tamper */ +enum stm32_tamp_int_id { @@ -27391,10 +28155,10 @@ index 0000000..3933c26 +#define TAMP_ACTIVE_CKSEL_DIV_32 0x5U +#define TAMP_ACTIVE_CKSEL_DIV_64 0x6U +#define TAMP_ACTIVE_CKSEL_DIV_128 0x7U -+#define TAMP_ACTIVE_ATOSEL_OUT1_(X) (0x0U << (X * 2)) -+#define TAMP_ACTIVE_ATOSEL_OUT2_(X) (0x1U << (X * 2)) -+#define TAMP_ACTIVE_ATOSEL_OUT3_(X) (0x2U << (X * 2)) -+#define TAMP_ACTIVE_ATOSEL_OUT4_(X) (0x3U << (X * 2)) ++#define TAMP_ACTIVE_ATOSEL_OUT1_(X) (0x0U << ((X) * 2)) ++#define TAMP_ACTIVE_ATOSEL_OUT2_(X) (0x1U << ((X) * 2)) ++#define TAMP_ACTIVE_ATOSEL_OUT3_(X) (0x2U << ((X) * 2)) ++#define TAMP_ACTIVE_ATOSEL_OUT4_(X) (0x3U << ((X) * 2)) + +#define TAMP_EXT(tamp_id, trig, erase, mask) (((tamp_id) << 3) | ((trig) << 2)\ + | ((erase) << 1) | (mask)) @@ -27412,7 +28176,7 @@ index 0000000..3933c26 + +struct stm32_tamp_int { + int id; -+ void (*it_handler)(void); ++ void (*func)(int id); +}; + +struct stm32_tamp_ext { @@ -27420,7 +28184,7 @@ index 0000000..3933c26 + uint8_t mode; + uint8_t erase; + uint8_t evt_mask; -+ void (*it_handler)(void); ++ void (*func)(int id); +}; + +/* @@ -27459,15 +28223,15 @@ index 0000000..3933c26 + */ +int stm32_tamp_init(void); + -+#endif /* __TAMPER__ */ ++#endif /* STM32_TAMP_H */ diff --git a/include/drivers/st/stm32_timer.h b/include/drivers/st/stm32_timer.h new file mode 100644 -index 0000000..e62f3df +index 000000000..0e2eb91fe --- /dev/null +++ b/include/drivers/st/stm32_timer.h @@ -0,0 +1,21 @@ +/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -27487,508 +28251,205 @@ index 0000000..e62f3df +int stm32_timer_init(void); + +#endif /* STM32_TIMER_H */ -diff --git a/include/drivers/st/stm32_uart_regs.h b/include/drivers/st/stm32_uart_regs.h +diff --git a/include/drivers/st/stm32mp1_calib.h b/include/drivers/st/stm32mp1_calib.h new file mode 100644 -index 0000000..e78d3d4 +index 000000000..ef69cb456 --- /dev/null -+++ b/include/drivers/st/stm32_uart_regs.h -@@ -0,0 +1,199 @@ ++++ b/include/drivers/st/stm32mp1_calib.h +@@ -0,0 +1,20 @@ +/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef STM32_UART_REGS_H -+#define STM32_UART_REGS_H ++#ifndef STM32MP1_CALIB_H ++#define STM32MP1_CALIB_H + -+#include -+ -+#define USART_CR1 U(0x00) -+#define USART_CR2 U(0x04) -+#define USART_CR3 U(0x08) -+#define USART_BRR U(0x0C) -+#define USART_GTPR U(0x10) -+#define USART_RTOR U(0x14) -+#define USART_RQR U(0x18) -+#define USART_ISR U(0x1C) -+#define USART_ICR U(0x20) -+#define USART_RDR U(0x24) -+#define USART_TDR U(0x28) -+#define USART_PRESC U(0x2C) -+ -+/* USART_CR1 register fields */ -+#define USART_CR1_UE BIT(0) -+#define USART_CR1_UESM BIT(1) -+#define USART_CR1_RE BIT(2) -+#define USART_CR1_TE BIT(3) -+#define USART_CR1_IDLEIE BIT(4) -+#define USART_CR1_RXNEIE BIT(5) -+#define USART_CR1_TCIE BIT(6) -+#define USART_CR1_TXEIE BIT(7) -+#define USART_CR1_PEIE BIT(8) -+#define USART_CR1_PS BIT(9) -+#define USART_CR1_PCE BIT(10) -+#define USART_CR1_WAKE BIT(11) -+#define USART_CR1_M (BIT(28) | BIT(12)) -+#define USART_CR1_M0 BIT(12) -+#define USART_CR1_MME BIT(13) -+#define USART_CR1_CMIE BIT(14) -+#define USART_CR1_OVER8 BIT(15) -+#define USART_CR1_DEDT GENMASK(20, 16) -+#define USART_CR1_DEDT_0 BIT(16) -+#define USART_CR1_DEDT_1 BIT(17) -+#define USART_CR1_DEDT_2 BIT(18) -+#define USART_CR1_DEDT_3 BIT(19) -+#define USART_CR1_DEDT_4 BIT(20) -+#define USART_CR1_DEAT GENMASK(25, 21) -+#define USART_CR1_DEAT_0 BIT(21) -+#define USART_CR1_DEAT_1 BIT(22) -+#define USART_CR1_DEAT_2 BIT(23) -+#define USART_CR1_DEAT_3 BIT(24) -+#define USART_CR1_DEAT_4 BIT(25) -+#define USART_CR1_RTOIE BIT(26) -+#define USART_CR1_EOBIE BIT(27) -+#define USART_CR1_M1 BIT(28) -+#define USART_CR1_FIFOEN BIT(29) -+#define USART_CR1_TXFEIE BIT(30) -+#define USART_CR1_RXFFIE BIT(31) -+ -+/* USART_CR2 register fields */ -+#define USART_CR2_SLVEN BIT(0) -+#define USART_CR2_DIS_NSS BIT(3) -+#define USART_CR2_ADDM7 BIT(4) -+#define USART_CR2_LBDL BIT(5) -+#define USART_CR2_LBDIE BIT(6) -+#define USART_CR2_LBCL BIT(8) -+#define USART_CR2_CPHA BIT(9) -+#define USART_CR2_CPOL BIT(10) -+#define USART_CR2_CLKEN BIT(11) -+#define USART_CR2_STOP GENMASK(13, 12) -+#define USART_CR2_STOP_0 BIT(12) -+#define USART_CR2_STOP_1 BIT(13) -+#define USART_CR2_LINEN BIT(14) -+#define USART_CR2_SWAP BIT(15) -+#define USART_CR2_RXINV BIT(16) -+#define USART_CR2_TXINV BIT(17) -+#define USART_CR2_DATAINV BIT(18) -+#define USART_CR2_MSBFIRST BIT(19) -+#define USART_CR2_ABREN BIT(20) -+#define USART_CR2_ABRMODE GENMASK(22, 21) -+#define USART_CR2_ABRMODE_0 BIT(21) -+#define USART_CR2_ABRMODE_1 BIT(22) -+#define USART_CR2_RTOEN BIT(23) -+#define USART_CR2_ADD GENMASK(31, 24) -+ -+/* USART_CR3 register fields */ -+#define USART_CR3_EIE BIT(0) -+#define USART_CR3_IREN BIT(1) -+#define USART_CR3_IRLP BIT(2) -+#define USART_CR3_HDSEL BIT(3) -+#define USART_CR3_NACK BIT(4) -+#define USART_CR3_SCEN BIT(5) -+#define USART_CR3_DMAR BIT(6) -+#define USART_CR3_DMAT BIT(7) -+#define USART_CR3_RTSE BIT(8) -+#define USART_CR3_CTSE BIT(9) -+#define USART_CR3_CTSIE BIT(10) -+#define USART_CR3_ONEBIT BIT(11) -+#define USART_CR3_OVRDIS BIT(12) -+#define USART_CR3_DDRE BIT(13) -+#define USART_CR3_DEM BIT(14) -+#define USART_CR3_DEP BIT(15) -+#define USART_CR3_SCARCNT GENMASK(19, 17) -+#define USART_CR3_SCARCNT_0 BIT(17) -+#define USART_CR3_SCARCNT_1 BIT(18) -+#define USART_CR3_SCARCNT_2 BIT(19) -+#define USART_CR3_WUS GENMASK(21, 20) -+#define USART_CR3_WUS_0 BIT(20) -+#define USART_CR3_WUS_1 BIT(21) -+#define USART_CR3_WUFIE BIT(22) -+#define USART_CR3_TXFTIE BIT(23) -+#define USART_CR3_TCBGTIE BIT(24) -+#define USART_CR3_RXFTCFG GENMASK(27, 25) -+#define USART_CR3_RXFTCFG_0 BIT(25) -+#define USART_CR3_RXFTCFG_1 BIT(26) -+#define USART_CR3_RXFTCFG_2 BIT(27) -+#define USART_CR3_RXFTIE BIT(28) -+#define USART_CR3_TXFTCFG GENMASK(31, 29) -+#define USART_CR3_TXFTCFG_0 BIT(29) -+#define USART_CR3_TXFTCFG_1 BIT(30) -+#define USART_CR3_TXFTCFG_2 BIT(31) -+ -+/* USART_BRR register fields */ -+#define USART_BRR_DIV_FRACTION GENMASK(3, 0) -+#define USART_BRR_DIV_MANTISSA GENMASK(15, 4) -+ -+/* USART_GTPR register fields */ -+#define USART_GTPR_PSC GENMASK(7, 0) -+#define USART_GTPR_GT GENMASK(15, 8) -+ -+/* USART_RTOR register fields */ -+#define USART_RTOR_RTO GENMASK(23, 0) -+#define USART_RTOR_BLEN GENMASK(31, 24) -+ -+/* USART_RQR register fields */ -+#define USART_RQR_ABRRQ BIT(0) -+#define USART_RQR_SBKRQ BIT(1) -+#define USART_RQR_MMRQ BIT(2) -+#define USART_RQR_RXFRQ BIT(3) -+#define USART_RQR_TXFRQ BIT(4) -+ -+/* USART_ISR register fields */ -+#define USART_ISR_PE BIT(0) -+#define USART_ISR_FE BIT(1) -+#define USART_ISR_NE BIT(2) -+#define USART_ISR_ORE BIT(3) -+#define USART_ISR_IDLE BIT(4) -+#define USART_ISR_RXNE BIT(5) -+#define USART_ISR_TC BIT(6) -+#define USART_ISR_TXE BIT(7) -+#define USART_ISR_LBDF BIT(8) -+#define USART_ISR_CTSIF BIT(9) -+#define USART_ISR_CTS BIT(10) -+#define USART_ISR_RTOF BIT(11) -+#define USART_ISR_EOBF BIT(12) -+#define USART_ISR_UDR BIT(13) -+#define USART_ISR_ABRE BIT(14) -+#define USART_ISR_ABRF BIT(15) -+#define USART_ISR_BUSY BIT(16) -+#define USART_ISR_CMF BIT(17) -+#define USART_ISR_SBKF BIT(18) -+#define USART_ISR_RWU BIT(19) -+#define USART_ISR_WUF BIT(20) -+#define USART_ISR_TEACK BIT(21) -+#define USART_ISR_REACK BIT(22) -+#define USART_ISR_TXFE BIT(23) -+#define USART_ISR_RXFF BIT(24) -+#define USART_ISR_TCBGT BIT(25) -+#define USART_ISR_RXFT BIT(26) -+#define USART_ISR_TXFT BIT(27) -+ -+/* USART_ICR register fields */ -+#define USART_ICR_PECF BIT(0) -+#define USART_ICR_FECF BIT(1) -+#define USART_ICR_NCF BIT(2) -+#define USART_ICR_ORECF BIT(3) -+#define USART_ICR_IDLECF BIT(4) -+#define USART_ICR_TCCF BIT(6) -+#define USART_ICR_TCBGT BIT(7) -+#define USART_ICR_LBDCF BIT(8) -+#define USART_ICR_CTSCF BIT(9) -+#define USART_ICR_RTOCF BIT(11) -+#define USART_ICR_EOBCF BIT(12) -+#define USART_ICR_UDRCF BIT(13) -+#define USART_ICR_CMCF BIT(17) -+#define USART_ICR_WUCF BIT(20) -+ -+/* USART_RDR register fields */ -+#define USART_RDR_RDR GENMASK(8, 0) -+ -+/* USART_TDR register fields */ -+#define USART_TDR_TDR GENMASK(8, 0) -+ -+/* USART_PRESC register fields */ -+#define USART_PRESC_PRESCALER GENMASK(3, 0) -+ -+#endif /* STM32_UART_REGS_H */ -diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h -index 85a1eb8..0c8583a 100644 ---- a/include/drivers/st/stm32mp1_clk.h -+++ b/include/drivers/st/stm32mp1_clk.h -@@ -4,27 +4,72 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef __STM32MP1_CLK_H__ --#define __STM32MP1_CLK_H__ -+#ifndef STM32MP1_CLK_H -+#define STM32MP1_CLK_H - --#include - #include ++#include +#include + -+#include - - int stm32mp1_clk_probe(void); - int stm32mp1_clk_init(void); ++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 1ebd39ff7..ded8185f2 100644 +--- a/include/drivers/st/stm32mp1_clk.h ++++ b/include/drivers/st/stm32mp1_clk.h +@@ -22,41 +22,49 @@ enum stm32mp_osc_id { + + extern const char *stm32mp_osc_node_label[NB_OSC]; + +-int stm32mp1_clk_probe(void); +-int stm32mp1_clk_init(void); ++#define PLL1_SETTINGS_VALID_ID U(0x504C4C31) /* "PLL1" */ + +-bool stm32mp1_rcc_is_secure(void); +-bool stm32mp1_rcc_is_mckprot(void); ++int stm32mp1_clk_probe(void); ++int stm32mp1_clk_init(uint32_t pll1_freq_mhz); + +-void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); +-void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); ++int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage); ++void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data, size_t size); ++void stm32mp1_clk_lp_load_opp_pll1_settings(uint8_t *data, size_t size); + +-static inline void stm32mp1_clk_enable_non_secure(unsigned long id) +-{ +- __stm32mp1_clk_enable(id, false); +-} ++int stm32mp1_clk_get_maxfreq_opp(uint32_t *freq_mhz, uint32_t *voltage_mv); + +-static inline void stm32mp1_clk_enable_secure(unsigned long id) +-{ +- __stm32mp1_clk_enable(id, true); +-} +bool stm32mp1_rcc_is_secure(void); +bool stm32mp1_rcc_is_mckprot(void); -+ -+void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); -+void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); - bool stm32mp1_clk_is_enabled(unsigned long id); --int stm32mp1_clk_enable(unsigned long id); --int stm32mp1_clk_disable(unsigned long id); --unsigned long stm32mp1_clk_get_rate(unsigned long id); --void stm32mp1_stgen_increment(unsigned long long offset_in_ms); --static inline uint32_t get_timer(uint32_t base) -+static inline void stm32mp1_clk_enable_non_secure(unsigned long id) -+{ -+ __stm32mp1_clk_enable(id, false); -+} -+ -+static inline void stm32mp1_clk_enable_secure(unsigned long id) -+{ -+ __stm32mp1_clk_enable(id, true); -+} -+ -+static inline void stm32mp1_clk_disable_non_secure(unsigned long id) - { -- if (base == 0U) { -- return (uint32_t)(~read_cntpct_el0()); -- } -+ __stm32mp1_clk_disable(id, false); -+} +-static inline void stm32mp1_clk_disable_non_secure(unsigned long id) +-{ +- __stm32mp1_clk_disable(id, false); +-} ++void stm32mp1_clk_force_enable(unsigned long id); ++void stm32mp1_clk_force_disable(unsigned long id); -- return base - (uint32_t)(~read_cntpct_el0()); -+static inline void stm32mp1_clk_disable_secure(unsigned long id) -+{ -+ __stm32mp1_clk_disable(id, true); - } - --#endif /* __STM32MP1_CLK_H__ */ -+unsigned int stm32mp1_clk_get_refcount(unsigned long id); -+ -+unsigned long stm32mp_clk_get_rate(unsigned long id); +-static inline void stm32mp1_clk_disable_secure(unsigned long id) +-{ +- __stm32mp1_clk_disable(id, true); +-} +unsigned long stm32mp_clk_timer_get_rate(unsigned long id); -+ -+void stm32mp1_stgen_increment(unsigned long long offset_in_ms); -+ + +-unsigned int stm32mp1_clk_get_refcount(unsigned long id); +bool stm32mp1_rtc_get_read_twice(void); -+ -+/* SMP protection on RCC registers access */ -+void stm32mp1_clk_rcc_regs_lock(void); -+void stm32mp1_clk_rcc_regs_unlock(void); -+ + + /* SMP protection on RCC registers access */ + void stm32mp1_clk_rcc_regs_lock(void); + void stm32mp1_clk_rcc_regs_unlock(void); + +-void stm32mp1_stgen_increment(unsigned long long offset_in_ms); +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); -+#endif ++int stm32mp1_round_opp_khz(uint32_t *freq_khz); ++int stm32mp1_set_opp_khz(uint32_t freq_khz); + -+void stm32mp1_rcc_init_late(void); ++void stm32mp1_clock_suspend(void); ++void stm32mp1_clock_resume(void); ++ ++void stm32mp1_clock_stopmode_save(void); ++int stm32mp1_clock_stopmode_resume(void); ++ ++void restore_clock_pm_context(void); ++void save_clock_pm_context(void); + +void stm32mp1_register_clock_parents_secure(unsigned long id); + +void stm32mp1_update_earlyboot_clocks_state(void); + -+#endif /* STM32MP1_CLK_H */ -diff --git a/include/drivers/st/stm32mp1_clkfunc.h b/include/drivers/st/stm32mp1_clkfunc.h -index 635a9cd..b488478 100644 ---- a/include/drivers/st/stm32mp1_clkfunc.h -+++ b/include/drivers/st/stm32mp1_clkfunc.h -@@ -4,9 +4,10 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ ++void stm32mp1_dump_clocks_state(void); --#ifndef __STM32MP1_CLKFUNC_H__ --#define __STM32MP1_CLKFUNC_H__ -+#ifndef STM32MP1_CLKFUNC_H -+#define STM32MP1_CLKFUNC_H - -+#include - #include - - enum stm32mp_osc_id { -@@ -16,7 +17,6 @@ enum stm32mp_osc_id { - _LSI, - _LSE, - _I2S_CKIN, -- _USB_PHY_48, - NB_OSC, - _UNKNOWN_OSC_ID = 0xFF - }; -@@ -29,14 +29,6 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - const char *prop_name, - uint32_t dflt_value); - --uint32_t fdt_rcc_read_addr(void); --int fdt_rcc_read_uint32_array(const char *prop_name, -- uint32_t *array, uint32_t count); --int fdt_rcc_subnode_offset(const char *name); --const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp); --bool fdt_get_rcc_secure_status(void); -+int fdt_rcc_enable_it(const char *name); - --uintptr_t fdt_get_stgen_base(void); --int fdt_get_clock_id(int node); -- --#endif /* __STM32MP1_CLKFUNC_H__ */ -+#endif /* STM32MP1_CLKFUNC_H */ + #endif /* STM32MP1_CLK_H */ diff --git a/include/drivers/st/stm32mp1_ddr.h b/include/drivers/st/stm32mp1_ddr.h -index 0765664..b2773b0 100644 +index 4ab37d6b4..c8f8d12ad 100644 --- a/include/drivers/st/stm32mp1_ddr.h +++ b/include/drivers/st/stm32mp1_ddr.h -@@ -4,8 +4,8 @@ - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ - --#ifndef _STM32MP1_DDR_H --#define _STM32MP1_DDR_H -+#ifndef STM32MP1_DDR_H -+#define STM32MP1_DDR_H +@@ -8,9 +8,6 @@ + #define STM32MP1_DDR_H #include +-#include +- +-#define DT_DDR_COMPAT "st,stm32mp1-ddr" -@@ -152,7 +152,7 @@ struct stm32mp1_ddrphy_cal { - - struct stm32mp1_ddr_info { - const char *name; -- uint16_t speed; /* in MHZ */ -+ uint32_t speed; /* in kHZ */ - uint32_t size; /* Memory size in byte = col * row * width */ - }; - -@@ -165,9 +165,12 @@ struct stm32mp1_ddr_config { + struct stm32mp1_ddr_size { + uint64_t base; +@@ -166,9 +163,13 @@ struct stm32mp1_ddr_config { struct stm32mp1_ddrphy_reg p_reg; struct stm32mp1_ddrphy_timing p_timing; struct stm32mp1_ddrphy_cal p_cal; ++ bool p_cal_present; + bool self_refresh; + uint32_t zdata; }; --int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed); -+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed); + int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed); void stm32mp1_ddr_init(struct ddr_info *priv, struct stm32mp1_ddr_config *config); --#endif /* _STM32MP1_DDR_H */ + -+#endif /* STM32MP1_DDR_H */ + #endif /* STM32MP1_DDR_H */ diff --git a/include/drivers/st/stm32mp1_ddr_helpers.h b/include/drivers/st/stm32mp1_ddr_helpers.h -index 298a080..ecc14d2 100644 +index 38f24152a..210beee8a 100644 --- a/include/drivers/st/stm32mp1_ddr_helpers.h +++ b/include/drivers/st/stm32mp1_ddr_helpers.h -@@ -4,9 +4,17 @@ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * * SPDX-License-Identifier: BSD-3-Clause */ +@@ -7,6 +7,23 @@ + #ifndef STM32MP1_DDR_HELPERS_H + #define STM32MP1_DDR_HELPERS_H --#ifndef __STM32MP1_DDR_HELPERS_H__ --#define __STM32MP1_DDR_HELPERS_H__ -+#ifndef STM32MP1_DDR_HELPERS_H -+#define STM32MP1_DDR_HELPERS_H -+ +#include - ++#include ++ ++enum stm32mp1_ddr_sr_mode { ++ DDR_SR_MODE_INVALID = 0, ++ DDR_SSR_MODE, ++ DDR_HSR_MODE, ++ DDR_ASR_MODE, ++}; ++ void ddr_enable_clock(void); +int ddr_sw_self_refresh_exit(void); +int ddr_standby_sr_entry(uint32_t *zq0cr0_zdata); -+void ddr_sr_mode_ssr(void); -+void ddr_sr_mode_asr(void); -+void ddr_sr_mode_hsr(void); ++enum stm32mp1_ddr_sr_mode ddr_read_sr_mode(void); ++void ddr_set_sr_mode(enum stm32mp1_ddr_sr_mode mode); ++void ddr_save_sr_mode(void); ++void ddr_restore_sr_mode(void); +bool ddr_is_nonsecured_area(uintptr_t address, uint32_t length); --#endif /* __STM32MP1_DDR_HELPERS_H__ */ -+#endif /* STM32MP1_DDR_HELPERS_H */ + #endif /* STM32MP1_DDR_HELPERS_H */ diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h -index 64ad965..e928688 100644 +index 342239a52..af232a308 100644 --- a/include/drivers/st/stm32mp1_ddr_regs.h +++ b/include/drivers/st/stm32mp1_ddr_regs.h -@@ -4,9 +4,10 @@ - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ +@@ -380,6 +380,7 @@ struct stm32mp1_ddrphy { + #define DDRPHYC_PTR0_TITMSRST_OFFSET 18 + #define DDRPHYC_PTR0_TITMSRST_MASK GENMASK(21, 18) --#ifndef _RAM_STM32MP1_DDR_REGS_H --#define _RAM_STM32MP1_DDR_REGS_H -+#ifndef STM32MP1_DDR_REGS_H -+#define STM32MP1_DDR_REGS_H ++#define DDRPHYC_ACIOCR_ACOE BIT(1) + #define DDRPHYC_ACIOCR_ACPDD BIT(3) + #define DDRPHYC_ACIOCR_ACPDR BIT(4) + #define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8) +@@ -399,6 +400,7 @@ struct stm32mp1_ddrphy { + #define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20) + #define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) + #define DDRPHYC_DSGCR_NL2PD BIT(24) ++#define DDRPHYC_DSGCR_CKOE BIT(28) -+#include - #include - - /* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */ -@@ -247,11 +248,14 @@ struct stm32mp1_ddrphy { - #define DDRCTRL_DBGSTAT 0x310 - #define DDRCTRL_SWCTL 0x320 - #define DDRCTRL_SWSTAT 0x324 -+#define DDRCTRL_PSTAT 0x3FC - #define DDRCTRL_PCTRL_0 0x490 - #define DDRCTRL_PCTRL_1 0x540 - - /* DDR Controller Register fields */ - #define DDRCTRL_MSTR_DDR3 BIT(0) -+#define DDRCTRL_MSTR_LPDDR2 BIT(2) -+#define DDRCTRL_MSTR_LPDDR3 BIT(3) - #define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) - #define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0 - #define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12) -@@ -269,7 +273,7 @@ struct stm32mp1_ddrphy { - /* Only one rank supported */ - #define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 - #define DDRCTRL_MRCTRL0_MR_RANK_ALL \ -- (0x1U << DDRCTRL_MRCTRL0_MR_RANK_SHIFT) -+ BIT(DDRCTRL_MRCTRL0_MR_RANK_SHIFT) - #define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12 - #define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12) - #define DDRCTRL_MRCTRL0_MR_WR BIT(31) -@@ -367,6 +371,7 @@ struct stm32mp1_ddrphy { - - #define DDRPHYC_DLLGCR_BPS200 BIT(23) - -+#define DDRPHYC_ACDLLCR_DLLSRST BIT(30) - #define DDRPHYC_ACDLLCR_DLLDIS BIT(31) - - #define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 -@@ -408,6 +413,4 @@ struct stm32mp1_ddrphy { - #define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) - #define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 - --void ddr_enable_clock(void); -- --#endif /* _RAM_STM32MP1_DDR_REGS_H */ -+#endif /* STM32MP1_DDR_REGS_H */ -diff --git a/include/drivers/st/stm32mp1_pmic.h b/include/drivers/st/stm32mp1_pmic.h -deleted file mode 100644 -index 5d94b40..0000000 ---- a/include/drivers/st/stm32mp1_pmic.h -+++ /dev/null -@@ -1,18 +0,0 @@ --/* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#ifndef __STM32MP1_PMIC_H__ --#define __STM32MP1_PMIC_H__ -- --#include -- --bool dt_check_pmic(void); --int dt_pmic_enable_boot_on_regulators(void); --void initialize_pmic_i2c(void); --void initialize_pmic(void); --int pmic_ddr_power_init(enum ddr_type ddr_type); -- --#endif /* __STM32MP1_PMIC_H__ */ + #define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) + #define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 diff --git a/include/drivers/st/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h -index e567042..1a22824 100644 +index e17df44fb..9b662f2d1 100644 --- a/include/drivers/st/stm32mp1_pwr.h +++ b/include/drivers/st/stm32mp1_pwr.h -@@ -1,11 +1,11 @@ +@@ -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 */ - --#ifndef __STM32MP1_PWR_H__ --#define __STM32MP1_PWR_H__ -+#ifndef STM32MP1_PWR_H -+#define STM32MP1_PWR_H - - #include - -@@ -13,20 +13,43 @@ +@@ -13,20 +13,39 @@ #define PWR_CR2 U(0x08) #define PWR_CR3 U(0x0C) #define PWR_MPUCR U(0x10) @@ -28005,6 +28466,8 @@ index e567042..1a22824 100644 +#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) @@ -28019,313 +28482,94 @@ index e567042..1a22824 100644 #define PWR_MPUCR_CSTDBYDIS BIT(3) #define PWR_MPUCR_CSSF BIT(9) --#endif /* __STM32MP1_PWR_H__ */ +#define PWR_MCUCR_PDDS BIT(0) + +#define PWR_WKUPCR_MASK GENMASK(27, 16) | GENMASK(13, 8) | GENMASK(5, 0) + +#define PWR_MPUWKUPENR_MASK GENMASK(5, 0) + -+#ifndef __ASSEMBLY__ -+/* SMP protection on PWR registers access */ -+void pwr_regs_lock(void); -+void pwr_regs_unlock(void); -+#endif /* __ASSEMBLY__ */ -+ -+#endif /* STM32MP1_PWR_H */ -diff --git a/include/drivers/st/stm32mp1_ram.h b/include/drivers/st/stm32mp1_ram.h -index af96177..38360e7 100644 ---- a/include/drivers/st/stm32mp1_ram.h -+++ b/include/drivers/st/stm32mp1_ram.h -@@ -4,9 +4,9 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef _STM32MP1_RAM_H --#define _STM32MP1_RAM_H -+#ifndef STM32MP1_RAM_H -+#define STM32MP1_RAM_H - - int stm32mp1_ddr_probe(void); - --#endif /* _STM32MP1_RAM_H */ -+#endif /* STM32MP1_RAM_H */ + #endif /* STM32MP1_PWR_H */ diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h -index e28ca97..7e1b337 100644 +index 4b4aac87d..91c6f087b 100644 --- a/include/drivers/st/stm32mp1_rcc.h +++ b/include/drivers/st/stm32mp1_rcc.h -@@ -4,8 +4,8 @@ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved + * * SPDX-License-Identifier: BSD-3-Clause */ +@@ -390,7 +390,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) --#ifndef __STM32MP1_RCC_H__ --#define __STM32MP1_RCC_H__ -+#ifndef STM32MP1_RCC_H -+#define STM32MP1_RCC_H + /* Fields of RCC_CSICFGR register */ + #define RCC_CSICFGR_CSITRIM_SHIFT 8 +@@ -449,6 +450,9 @@ + #define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) + #define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) - #include - -@@ -68,6 +68,14 @@ - #define RCC_MP_AHB6ENCLRR U(0x21C) - #define RCC_MP_TZAHB6ENSETR U(0x220) - #define RCC_MP_TZAHB6ENCLRR U(0x224) -+#define RCC_MC_APB4ENSETR U(0x280) -+#define RCC_MC_APB4ENCLRR U(0x284) -+#define RCC_MC_APB5ENSETR U(0x288) -+#define RCC_MC_APB5ENCLRR U(0x28C) -+#define RCC_MC_AHB5ENSETR U(0x290) -+#define RCC_MC_AHB5ENCLRR U(0x294) -+#define RCC_MC_AHB6ENSETR U(0x298) -+#define RCC_MC_AHB6ENCLRR U(0x29C) - #define RCC_MP_APB4LPENSETR U(0x300) - #define RCC_MP_APB4LPENCLRR U(0x304) - #define RCC_MP_APB5LPENSETR U(0x308) -@@ -78,6 +86,14 @@ - #define RCC_MP_AHB6LPENCLRR U(0x31C) - #define RCC_MP_TZAHB6LPENSETR U(0x320) - #define RCC_MP_TZAHB6LPENCLRR U(0x324) -+#define RCC_MC_APB4LPENSETR U(0x380) -+#define RCC_MC_APB4LPENCLRR U(0x384) -+#define RCC_MC_APB5LPENSETR U(0x388) -+#define RCC_MC_APB5LPENCLRR U(0x38C) -+#define RCC_MC_AHB5LPENSETR U(0x390) -+#define RCC_MC_AHB5LPENCLRR U(0x394) -+#define RCC_MC_AHB6LPENSETR U(0x398) -+#define RCC_MC_AHB6LPENCLRR U(0x39C) - #define RCC_BR_RSTSCLRR U(0x400) - #define RCC_MP_GRSTCSETR U(0x404) - #define RCC_MP_RSTSCLRR U(0x408) -@@ -95,6 +111,7 @@ - #define RCC_RCK4SELR U(0x824) - #define RCC_TIMG1PRER U(0x828) - #define RCC_TIMG2PRER U(0x82C) -+#define RCC_MCUDIVR U(0x830) - #define RCC_APB1DIVR U(0x834) - #define RCC_APB2DIVR U(0x838) - #define RCC_APB3DIVR U(0x83C) -@@ -162,6 +179,22 @@ - #define RCC_MP_AHB4ENCLRR U(0xA2C) - #define RCC_MP_MLAHBENSETR U(0xA38) - #define RCC_MP_MLAHBENCLRR U(0xA3C) -+#define RCC_MC_APB1ENSETR U(0xA80) -+#define RCC_MC_APB1ENCLRR U(0xA84) -+#define RCC_MC_APB2ENSETR U(0xA88) -+#define RCC_MC_APB2ENCLRR U(0xA8C) -+#define RCC_MC_APB3ENSETR U(0xA90) -+#define RCC_MC_APB3ENCLRR U(0xA94) -+#define RCC_MC_AHB2ENSETR U(0xA98) -+#define RCC_MC_AHB2ENCLRR U(0xA9C) -+#define RCC_MC_AHB3ENSETR U(0xAA0) -+#define RCC_MC_AHB3ENCLRR U(0xAA4) -+#define RCC_MC_AHB4ENSETR U(0xAA8) -+#define RCC_MC_AHB4ENCLRR U(0xAAC) -+#define RCC_MC_AXIMENSETR U(0xAB0) -+#define RCC_MC_AXIMENCLRR U(0xAB4) -+#define RCC_MC_MLAHBENSETR U(0xAB8) -+#define RCC_MC_MLAHBENCLRR U(0xABC) - #define RCC_MP_APB1LPENSETR U(0xB00) - #define RCC_MP_APB1LPENCLRR U(0xB04) - #define RCC_MP_APB2LPENSETR U(0xB08) -@@ -178,12 +211,34 @@ - #define RCC_MP_AXIMLPENCLRR U(0xB34) - #define RCC_MP_MLAHBLPENSETR U(0xB38) - #define RCC_MP_MLAHBLPENCLRR U(0xB3C) -+#define RCC_MC_APB1LPENSETR U(0xB80) -+#define RCC_MC_APB1LPENCLRR U(0xB84) -+#define RCC_MC_APB2LPENSETR U(0xB88) -+#define RCC_MC_APB2LPENCLRR U(0xB8C) -+#define RCC_MC_APB3LPENSETR U(0xB90) -+#define RCC_MC_APB3LPENCLRR U(0xB94) -+#define RCC_MC_AHB2LPENSETR U(0xB98) -+#define RCC_MC_AHB2LPENCLRR U(0xB9C) -+#define RCC_MC_AHB3LPENSETR U(0xBA0) -+#define RCC_MC_AHB3LPENCLRR U(0xBA4) -+#define RCC_MC_AHB4LPENSETR U(0xBA8) -+#define RCC_MC_AHB4LPENCLRR U(0xBAC) -+#define RCC_MC_AXIMLPENSETR U(0xBB0) -+#define RCC_MC_AXIMLPENCLRR U(0xBB4) -+#define RCC_MC_MLAHBLPENSETR U(0xBB8) -+#define RCC_MC_MLAHBLPENCLRR U(0xBBC) -+#define RCC_MC_RSTSCLRR U(0xC00) -+#define RCC_MC_CIER U(0xC14) -+#define RCC_MC_CIFR U(0xC18) - #define RCC_VERR U(0xFF4) - #define RCC_IDR U(0xFF8) - #define RCC_SIDR U(0xFFC) - -+#define RCC_OFFSET_MASK GENMASK(11, 0) ++/* Global Control Register */ ++#define RCC_MP_GCR_BOOT_MCU BIT(0) + - /* Values for RCC_TZCR register */ - #define RCC_TZCR_TZEN BIT(0) -+#define RCC_TZCR_MCKPROT BIT(1) + /* Values of RCC_UART24CKSELR register */ + #define RCC_UART24CKSELR_HSI 0x00000002 - /* Used for most of RCC_SELR registers */ - #define RCC_SELR_SRC_MASK GENMASK(2, 0) -@@ -220,6 +275,10 @@ - #define RCC_APBXDIV_MASK GENMASK(2, 0) - #define RCC_MPUDIV_MASK GENMASK(2, 0) - #define RCC_AXIDIV_MASK GENMASK(2, 0) -+#define RCC_MCUDIV_MASK GENMASK(3, 0) -+ -+/* Used for TIMER Prescaler */ -+#define RCC_TIMGXPRER_TIMGXPRE BIT(0) +@@ -462,8 +466,15 @@ + #define RCC_MP_APB5ENSETR_USART1EN BIT(4) + #define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) + #define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) ++#define RCC_MP_APB5ENSETR_STGENEN BIT(20) - /* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ - #define RCC_MP_ENCLRR_OFFSET U(4) -@@ -228,6 +287,7 @@ - #define RCC_BDCR_LSEON BIT(0) - #define RCC_BDCR_LSEBYP BIT(1) - #define RCC_BDCR_LSERDY BIT(2) -+#define RCC_BDCR_DIGBYP BIT(3) - #define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) - #define RCC_BDCR_LSEDRV_SHIFT 4 - #define RCC_BDCR_LSECSSON BIT(8) -@@ -243,6 +303,7 @@ - /* Used for all RCC_PLLCR registers */ - #define RCC_PLLNCR_PLLON BIT(0) - #define RCC_PLLNCR_PLLRDY BIT(1) -+#define RCC_PLLNCR_SSCG_CTRL BIT(2) - #define RCC_PLLNCR_DIVPEN BIT(4) - #define RCC_PLLNCR_DIVQEN BIT(5) - #define RCC_PLLNCR_DIVREN BIT(6) -@@ -281,8 +342,12 @@ - - /* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ - #define RCC_OCENR_HSION BIT(0) -+#define RCC_OCENR_HSIKERON BIT(1) - #define RCC_OCENR_CSION BIT(4) -+#define RCC_OCENR_CSIKERON BIT(5) -+#define RCC_OCENR_DIGBYP BIT(7) - #define RCC_OCENR_HSEON BIT(8) -+#define RCC_OCENR_HSEKERON BIT(9) - #define RCC_OCENR_HSEBYP BIT(10) - #define RCC_OCENR_HSECSSON BIT(11) - -@@ -319,6 +384,16 @@ - - /* Fields of RCC_HSICFGR register */ - #define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) -+#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) -+ -+/* Fields of RCC_CSICFGR register */ -+#define RCC_CSICFGR_CSITRIM_SHIFT 8 -+#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) -+#define RCC_CSICFGR_CSICAL_SHIFT 16 -+#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) - - /* Used for RCC_MCO related operations */ - #define RCC_MCOCFG_MCOON BIT(12) -@@ -330,22 +405,37 @@ - #define RCC_DBGCFGR_DBGCKEN BIT(8) - - /* RCC register fields for reset reasons */ --#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) --#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) --#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) --#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) --#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) --#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) --#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) --#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) --#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) --#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) -+#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) -+#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) -+#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) -+#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) -+#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) -+#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) -+#define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7) -+#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) -+#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) -+#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) -+#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) -+#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) -+#define RCC_MP_RSTSCLRR_MPUP1RSTF BIT(14) - - /* Global Reset Register */ - #define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) -+#define RCC_MP_GRSTCSETR_MCURST BIT(1) -+#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) -+#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) - - /* Clock Source Interrupt Flag Register */ - #define RCC_MP_CIFR_MASK U(0x110F1F) -+#define RCC_MP_CIFR_LSIRDYF BIT(0) -+#define RCC_MP_CIFR_LSERDYF BIT(1) -+#define RCC_MP_CIFR_HSIRDYF BIT(2) -+#define RCC_MP_CIFR_HSERDYF BIT(3) -+#define RCC_MP_CIFR_CSIRDYF BIT(4) -+#define RCC_MP_CIFR_PLL1DYF BIT(8) -+#define RCC_MP_CIFR_PLL2DYF BIT(9) -+#define RCC_MP_CIFR_PLL3DYF BIT(10) -+#define RCC_MP_CIFR_PLL4DYF BIT(11) - #define RCC_MP_CIFR_WKUPF BIT(20) - - /* Stop Request Set Register */ -@@ -362,7 +452,29 @@ - /* Values of RCC_MP_APB1ENSETR register */ - #define RCC_MP_APB1ENSETR_UART4EN BIT(16) - -+/* Values of RCC_MP_APB5ENSETR register */ -+#define RCC_MP_APB5ENSETR_SPI6EN BIT(0) -+#define RCC_MP_APB5ENSETR_I2C4EN BIT(2) -+#define RCC_MP_APB5ENSETR_I2C6EN BIT(3) -+#define RCC_MP_APB5ENSETR_USART1EN BIT(4) -+#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) -+#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) -+ /* Values of RCC_MP_AHB4ENSETR register */ ++#define RCC_MP_AHB4ENSETR_GPIOAEN BIT(0) ++#define RCC_MP_AHB4ENSETR_GPIOBEN BIT(1) ++#define RCC_MP_AHB4ENSETR_GPIOCEN BIT(2) ++#define RCC_MP_AHB4ENSETR_GPIODEN BIT(3) ++#define RCC_MP_AHB4ENSETR_GPIOEEN BIT(4) ++#define RCC_MP_AHB4ENSETR_GPIOFEN BIT(5) #define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6) -+#define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7) -+ -+/* Values of RCC_MP_AHB5ENSETR register */ -+#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(0) -+#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) -+#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) -+#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) -+ -+/* Values of RCC_MP_IWDGFZSETR register */ -+#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) -+#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) -+ -+/* Values of RCC_PWRLPDLYCR register */ -+#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) + #define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7) --#endif /* __STM32MP1_RCC_H__ */ -+#endif /* STM32MP1_RCC_H */ -diff --git a/include/drivers/st/stm32mp1_reset.h b/include/drivers/st/stm32mp1_reset.h -deleted file mode 100644 -index 76ee09d..0000000 ---- a/include/drivers/st/stm32mp1_reset.h -+++ /dev/null -@@ -1,15 +0,0 @@ --/* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#ifndef __STM32MP1_RESET_H__ --#define __STM32MP1_RESET_H__ -- --#include -- --void stm32mp1_reset_assert(uint32_t reset_id); --void stm32mp1_reset_deassert(uint32_t reset_id); -- --#endif /* __STM32MP1_RESET_H__ */ +@@ -473,6 +484,12 @@ + #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_APB5LPENSETR register */ ++#define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) ++ + /* Values of RCC_MP_IWDGFZSETR register */ + #define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) + #define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) +@@ -558,4 +575,12 @@ + #define RCC_USBCKSELR_USBOSRC_MASK BIT(4) + #define RCC_USBCKSELR_USBOSRC_SHIFT 4 + ++/* RCC_MPCKSELR register fields */ ++#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) ++#define RCC_MPCKSELR_MPUSRC_SHIFT 0 ++ ++/* RCC_CPERCKSELR register fields */ ++#define RCC_CPERCKSELR_PERSRC_MASK GENMASK(1, 0) ++#define RCC_CPERCKSELR_PERSRC_SHIFT 0 ++ + #endif /* STM32MP1_RCC_H */ diff --git a/include/drivers/st/stm32mp1xx_hal.h b/include/drivers/st/stm32mp1xx_hal.h new file mode 100644 -index 0000000..5e4f9e7 +index 000000000..547f7f9ae --- /dev/null +++ b/include/drivers/st/stm32mp1xx_hal.h -@@ -0,0 +1,203 @@ +@@ -0,0 +1,204 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -28333,11 +28577,12 @@ index 0000000..5e4f9e7 +#ifndef __STM32_HAL_H +#define __STM32_HAL_H + -+#include -+#include +#include +#include -+#include ++ ++#include ++#include ++#include + +typedef enum { + HAL_OK = 0x00, @@ -28529,7 +28774,7 @@ index 0000000..5e4f9e7 +#endif /*__STM32_HAL_H*/ diff --git a/include/drivers/st/stm32mp1xx_hal_uart.h b/include/drivers/st/stm32mp1xx_hal_uart.h new file mode 100644 -index 0000000..b6af232 +index 000000000..465aa9273 --- /dev/null +++ b/include/drivers/st/stm32mp1xx_hal_uart.h @@ -0,0 +1,1586 @@ @@ -28561,8 +28806,8 @@ index 0000000..b6af232 +#define HAL_UART_MODULE_ENABLED + +/* Includes ------------------------------------------------------------------*/ -+#include -+#include ++#include ++#include + +/** + * @brief UART Init Structure definition @@ -30121,10 +30366,10 @@ index 0000000..b6af232 +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/include/drivers/st/stm32mp1xx_hal_uart_ex.h b/include/drivers/st/stm32mp1xx_hal_uart_ex.h new file mode 100644 -index 0000000..193f870 +index 000000000..28ec13c3b --- /dev/null +++ b/include/drivers/st/stm32mp1xx_hal_uart_ex.h -@@ -0,0 +1,87 @@ +@@ -0,0 +1,88 @@ +/** + ****************************************************************************** + * @file stm32mp1xx_hal_uart_ex.h @@ -30154,9 +30399,9 @@ index 0000000..193f870 +/** @defgroup UARTEx_Word_Length UART Word Length + * @{ + */ -+#define UART_WORDLENGTH_7B ((uint32_t)USART_CR1_M1) /*!< 7-bit long UART frame */ -+#define UART_WORDLENGTH_8B ((uint32_t)0x00000000U) /*!< 8-bit long UART frame */ -+#define UART_WORDLENGTH_9B ((uint32_t)USART_CR1_M0) /*!< 9-bit long UART frame */ ++#define UART_WORDLENGTH_7B ((uint32_t)USART_CR1_M1) /*!< 7-bit long UART frame */ ++#define UART_WORDLENGTH_8B ((uint32_t)0x00000000U) /*!< 8-bit long UART frame */ ++#define UART_WORDLENGTH_9B ((uint32_t)USART_CR1_M0) /*!< 9-bit long UART frame */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup UARTEx_Private_Macros UARTEx Private Macros @@ -30170,7 +30415,8 @@ index 0000000..193f870 + * This masking operation is not carried out in the case of + * DMA transfers. + * @param __HANDLE__: specifies the UART Handle. -+ * @retval None, the mask to apply to UART RDR register is stored in (__HANDLE__)->Mask field. ++ * @retval None, the mask to apply to UART RDR register is stored ++ * in (__HANDLE__)->Mask field. + */ +#define UART_MASK_COMPUTATION(__HANDLE__) \ + do { \ @@ -30207,430 +30453,298 @@ index 0000000..193f870 + (__HANDLE__)->Mask = 0x003F ; \ + } \ + } \ -+} while(0) ++} while (0) + +#endif /* __STM32MP1xx_HAL_UART_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h -new file mode 100644 -index 0000000..c77c0b5 ---- /dev/null +index 076916730..a0aaa002f 100644 +--- a/include/drivers/st/stm32mp_clkfunc.h +++ b/include/drivers/st/stm32mp_clkfunc.h -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_CLKFUNC_H -+#define STM32MP_CLKFUNC_H -+ -+#include -+#include -+ -+int fdt_get_rcc_node(void *fdt); -+uint32_t fdt_rcc_read_addr(void); -+int fdt_rcc_read_uint32_array(const char *prop_name, -+ uint32_t *array, uint32_t count); +@@ -19,15 +19,25 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, + const char *prop_name, + uint32_t dflt_value); + +-int fdt_get_rcc_node(void *fdt); +-uint32_t fdt_rcc_read_addr(void); ++int fdt_get_rcc_node(void); + int fdt_rcc_read_uint32_array(const char *prop_name, + uint32_t *array, uint32_t count); +uint32_t fdt_rcc_read_uint32_default(const char *prop_name, + uint32_t dflt_value); -+int fdt_rcc_subnode_offset(const char *name); -+const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp); -+bool fdt_get_rcc_secure_status(void); -+ -+uintptr_t fdt_get_stgen_base(void); -+int fdt_get_clock_id(int node); + int fdt_rcc_subnode_offset(const char *name); + const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp); + bool fdt_get_rcc_secure_status(void); ++int fdt_rcc_enable_it(const char *name); + +-uintptr_t fdt_get_stgen_base(void); + int fdt_get_clock_id(int node); +int fdt_get_clock_id_by_name(int node, const char *name); +unsigned long fdt_get_uart_clock_freq(uintptr_t instance); + -+#endif /* STM32MP_CLKFUNC_H */ ++bool fdt_is_pll1_predefined(void); ++ ++void stm32mp_stgen_config(unsigned long rate); ++void stm32mp_stgen_restore_counter(unsigned long long value, ++ unsigned long long offset_in_ms); ++unsigned long long stm32mp_stgen_get_counter(void); + + #endif /* STM32MP_CLKFUNC_H */ +diff --git a/include/drivers/st/stm32mp_dummy_regulator.h b/include/drivers/st/stm32mp_dummy_regulator.h +new file mode 100644 +index 000000000..6804192ba +--- /dev/null ++++ b/include/drivers/st/stm32mp_dummy_regulator.h +@@ -0,0 +1,14 @@ ++/* ++ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP_DUMMY_REGULATOR_H ++#define STM32MP_DUMMY_REGULATOR_H ++ ++#include ++ ++void bind_dummy_regulator(struct stm32mp_regulator *regu); ++ ++#endif /* STM32MP_DUMMY_REGULATOR_H */ diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h -new file mode 100644 -index 0000000..39c80e4 ---- /dev/null +index 984cd6014..898a28b44 100644 +--- a/include/drivers/st/stm32mp_pmic.h +++ b/include/drivers/st/stm32mp_pmic.h -@@ -0,0 +1,24 @@ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -11,6 +11,8 @@ + + #include + ++#include ++ + /* + * dt_pmic_status - Check PMIC status from device tree + * +@@ -25,7 +27,24 @@ int dt_pmic_status(void); + * + * Returns 0 on success, and negative values on errors + */ +-int dt_pmic_configure_boot_on_regulators(void); ++int pmic_configure_boot_on_regulators(void); ++ ++int pmic_set_lp_config(const char *node_name); ++ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * dt_pmic_find_supply - Find the supply name related to a regulator name + * -+ * SPDX-License-Identifier: BSD-3-Clause ++ * Returns 0 on success, and negative values on errors + */ ++int dt_pmic_find_supply(const char **supply_name, const char *regu_name); + -+#ifndef STM32MP_PMIC_H -+#define STM32MP_PMIC_H ++/* ++ * pmic_set_regulator_min_voltage - Set target supply to its device tree ++ * "regulator-min-microvolt" value. ++ * ++ * Returns 0 on success, and negative values on errors ++ */ ++int pmic_set_regulator_min_voltage(const char *regu_name); + + /* + * initialize_pmic_i2c - Initialize I2C for the PMIC control +@@ -41,6 +60,24 @@ bool initialize_pmic_i2c(void); + */ + void initialize_pmic(void); + ++/* ++ * configure_pmic - PMIC configuration function, called at platform init ++ * ++ * Panics on errors ++ */ ++void configure_pmic(void); + -+#include -+#include -+#include -+ -+int dt_pmic_status(void); -+int dt_pmic_configure_boot_on_regulators(void); -+int dt_pmic_set_lp_config(const char *node_name); -+bool initialize_pmic_i2c(void); -+void initialize_pmic(void); -+#if STM32MP1_DEBUG_ENABLE -+int pmic_keep_debug_unit(void); ++#if DEBUG ++void print_pmic_info_and_debug(void); ++#else ++static inline void print_pmic_info_and_debug(void) ++{ ++} +#endif -+int pmic_ddr_power_init(enum ddr_type ddr_type); + -+#endif /* STM32MP_PMIC_H */ ++bool is_pmic_regulator(struct stm32mp_regulator *regu); ++void bind_pmic_regulator(struct stm32mp_regulator *regu); ++ + /* + * pmic_ddr_power_init - Initialize regulators required for DDR + * +diff --git a/include/drivers/st/stm32mp_regulator.h b/include/drivers/st/stm32mp_regulator.h +new file mode 100644 +index 000000000..7a66b97ba +--- /dev/null ++++ b/include/drivers/st/stm32mp_regulator.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP_REGULATOR_H ++#define STM32MP_REGULATOR_H ++ ++#include ++ ++struct stm32mp_regulator; ++ ++struct stm32mp_regulator_ops { ++ int (*enable)(struct stm32mp_regulator *regu); ++ int (*disable)(struct stm32mp_regulator *regu); ++}; ++ ++struct stm32mp_regulator { ++ const struct stm32mp_regulator_ops *ops; ++ int id; ++ bool always_on; ++}; ++ ++int stm32mp_regulator_enable(struct stm32mp_regulator *regu); ++int stm32mp_regulator_disable(struct stm32mp_regulator *regu); ++int stm32mp_regulator_register(struct stm32mp_regulator *regu); ++ ++int plat_bind_regulator(struct stm32mp_regulator *regu); ++ ++#endif /* STM32MP_REGULATOR_H */ diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h -new file mode 100644 -index 0000000..5bd159f ---- /dev/null +index 2da5adf44..7114dddf0 100644 +--- a/include/drivers/st/stm32mp_reset.h +++ b/include/drivers/st/stm32mp_reset.h -@@ -0,0 +1,15 @@ +@@ -9,7 +9,42 @@ + + #include + +-void stm32mp_reset_assert(uint32_t reset_id); +-void stm32mp_reset_deassert(uint32_t reset_id); +/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * Assert target reset, if @to_us non null, wait until reset is asserted + * -+ * SPDX-License-Identifier: BSD-3-Clause ++ * @reset_id: Reset controller ID ++ * @to_us: Timeout in microsecond, or 0 if not waiting ++ * Return 0 on success and -ETIMEDOUT if waiting and timeout expired + */ ++int stm32mp_reset_assert_to(uint32_t reset_id, unsigned int to_us); + -+#ifndef STM32MP_RESET_H -+#define STM32MP_RESET_H ++/* ++ * Enable reset control for target resource ++ * ++ * @reset_id: Reset controller ID ++ */ ++static inline void stm32mp_reset_set(uint32_t reset_id) ++{ ++ (void)stm32mp_reset_assert_to(reset_id, 0); ++} + -+#include ++/* ++ * Deassert target reset, if @to_us non null, wait until reset is deasserted ++ * ++ * @reset_id: Reset controller ID ++ * @to_us: Timeout in microsecond, or 0 if not waiting ++ * Return 0 on success and -ETIMEDOUT if waiting and timeout expired ++ */ ++int stm32mp_reset_deassert_to(uint32_t reset_id, unsigned int to_us); + -+void stm32mp_reset_assert(uint32_t reset_id); -+void stm32mp_reset_deassert(uint32_t reset_id); -+ -+#endif /* STM32MP_RESET_H */ ++/* ++ * Release reset control for target resource ++ * ++ * @reset_id: Reset controller ID ++ */ ++static inline void stm32mp_reset_release(uint32_t reset_id) ++{ ++ (void)stm32mp_reset_deassert_to(reset_id, 0); ++} + + #endif /* STM32MP_RESET_H */ diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h -new file mode 100644 -index 0000000..803a69e ---- /dev/null +index f7e293b18..5c8933d84 100644 +--- a/include/drivers/st/stpmic1.h +++ b/include/drivers/st/stpmic1.h -@@ -0,0 +1,173 @@ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STPMIC1_H -+#define STPMIC1_H -+ -+#include -+#include -+ -+#define TURN_ON_REG 0x1U -+#define TURN_OFF_REG 0x2U -+#define ICC_LDO_TURN_OFF_REG 0x3U -+#define ICC_BUCK_TURN_OFF_REG 0x4U -+#define RESET_STATUS_REG 0x5U -+#define VERSION_STATUS_REG 0x6U -+#define MAIN_CONTROL_REG 0x10U -+#define PADS_PULL_REG 0x11U -+#define BUCK_PULL_DOWN_REG 0x12U -+#define LDO14_PULL_DOWN_REG 0x13U -+#define LDO56_PULL_DOWN_REG 0x14U -+#define VIN_CONTROL_REG 0x15U -+#define PONKEY_TIMER_REG 0x16U -+#define MASK_RANK_BUCK_REG 0x17U -+#define MASK_RESET_BUCK_REG 0x18U -+#define MASK_RANK_LDO_REG 0x19U -+#define MASK_RESET_LDO_REG 0x1AU -+#define WATCHDOG_CONTROL_REG 0x1BU -+#define WATCHDOG_TIMER_REG 0x1CU -+#define BUCK_ICC_TURNOFF_REG 0x1DU -+#define LDO_ICC_TURNOFF_REG 0x1EU -+#define BUCK_APM_CONTROL_REG 0x1FU -+#define BUCK1_CONTROL_REG 0x20U -+#define BUCK2_CONTROL_REG 0x21U -+#define BUCK3_CONTROL_REG 0x22U -+#define BUCK4_CONTROL_REG 0x23U -+#define VREF_DDR_CONTROL_REG 0x24U -+#define LDO1_CONTROL_REG 0x25U -+#define LDO2_CONTROL_REG 0x26U -+#define LDO3_CONTROL_REG 0x27U -+#define LDO4_CONTROL_REG 0x28U -+#define LDO5_CONTROL_REG 0x29U -+#define LDO6_CONTROL_REG 0x2AU -+#define BUCK1_PWRCTRL_REG 0x30U -+#define BUCK2_PWRCTRL_REG 0x31U -+#define BUCK3_PWRCTRL_REG 0x32U -+#define BUCK4_PWRCTRL_REG 0x33U -+#define VREF_DDR_PWRCTRL_REG 0x34U -+#define LDO1_PWRCTRL_REG 0x35U -+#define LDO2_PWRCTRL_REG 0x36U -+#define LDO3_PWRCTRL_REG 0x37U -+#define LDO4_PWRCTRL_REG 0x38U -+#define LDO5_PWRCTRL_REG 0x39U -+#define LDO6_PWRCTRL_REG 0x3AU -+#define FREQUENCY_SPREADING_REG 0x3BU -+#define USB_CONTROL_REG 0x40U -+#define ITLATCH1_REG 0x50U -+#define ITLATCH2_REG 0x51U -+#define ITLATCH3_REG 0x52U -+#define ITLATCH4_REG 0x53U -+#define ITSETLATCH1_REG 0x60U -+#define ITSETLATCH2_REG 0x61U -+#define ITSETLATCH3_REG 0x62U -+#define ITSETLATCH4_REG 0x63U -+#define ITCLEARLATCH1_REG 0x70U -+#define ITCLEARLATCH2_REG 0x71U -+#define ITCLEARLATCH3_REG 0x72U -+#define ITCLEARLATCH4_REG 0x73U -+#define ITMASK1_REG 0x80U -+#define ITMASK2_REG 0x81U -+#define ITMASK3_REG 0x82U -+#define ITMASK4_REG 0x83U -+#define ITSETMASK1_REG 0x90U -+#define ITSETMASK2_REG 0x91U -+#define ITSETMASK3_REG 0x92U -+#define ITSETMASK4_REG 0x93U -+#define ITCLEARMASK1_REG 0xA0U -+#define ITCLEARMASK2_REG 0xA1U -+#define ITCLEARMASK3_REG 0xA2U -+#define ITCLEARMASK4_REG 0xA3U -+#define ITSOURCE1_REG 0xB0U -+#define ITSOURCE2_REG 0xB1U -+#define ITSOURCE3_REG 0xB2U -+#define ITSOURCE4_REG 0xB3U -+ -+/* Registers masks */ -+#define LDO_VOLTAGE_MASK 0x7CU -+#define BUCK_VOLTAGE_MASK 0xFCU -+#define LDO_BUCK_VOLTAGE_SHIFT 2 -+#define LDO_BUCK_ENABLE_MASK 0x01U -+#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U -+#define LDO_BUCK_HPLP_SHIFT 1 -+#define LDO_BUCK_RANK_MASK 0x01U -+#define LDO_BUCK_RESET_MASK 0x01U -+#define LDO_BUCK_PULL_DOWN_MASK 0x03U -+ -+/* Pull down register */ -+#define BUCK1_PULL_DOWN_SHIFT 0 -+#define BUCK2_PULL_DOWN_SHIFT 2 -+#define BUCK3_PULL_DOWN_SHIFT 4 -+#define BUCK4_PULL_DOWN_SHIFT 6 -+#define VREF_DDR_PULL_DOWN_SHIFT 4 -+ -+/* Buck Mask reset register */ -+#define BUCK1_MASK_RESET 0 -+#define BUCK2_MASK_RESET 1 -+#define BUCK3_MASK_RESET 2 -+#define BUCK4_MASK_RESET 3 -+ -+/* LDO Mask reset register */ -+#define LDO1_MASK_RESET 0 -+#define LDO2_MASK_RESET 1 -+#define LDO3_MASK_RESET 2 -+#define LDO4_MASK_RESET 3 -+#define LDO5_MASK_RESET 4 -+#define LDO6_MASK_RESET 5 -+#define VREF_DDR_MASK_RESET 6 -+ -+/* Main PMIC Control Register (MAIN_CONTROL_REG) */ -+#define ICC_EVENT_ENABLED BIT(4) -+#define PWRCTRL_POLARITY_HIGH BIT(3) -+#define PWRCTRL_PIN_VALID BIT(2) -+#define RESTART_REQUEST_ENABLED BIT(1) -+#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) -+ -+/* Main PMIC PADS Control Register (PADS_PULL_REG) */ -+#define WAKEUP_DETECTOR_DISABLED BIT(4) -+#define PWRCTRL_PD_ACTIVE BIT(3) -+#define PWRCTRL_PU_ACTIVE BIT(2) -+#define WAKEUP_PD_ACTIVE BIT(1) -+#define PONKEY_PU_ACTIVE BIT(0) -+ -+/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ -+#define SWIN_DETECTOR_ENABLED BIT(7) -+#define SWOUT_DETECTOR_ENABLED BIT(6) -+#define VINLOW_HYST_MASK 0x3 -+#define VINLOW_HYST_SHIFT 4 -+#define VINLOW_THRESHOLD_MASK 0x7 -+#define VINLOW_THRESHOLD_SHIFT 1 -+#define VINLOW_ENABLED 0x01 -+#define VINLOW_CTRL_REG_MASK 0xFF -+ -+/* USB Control Register */ -+#define BOOST_OVP_DISABLED BIT(7) -+#define VBUS_OTG_DETECTION_DISABLED BIT(6) -+#define OCP_LIMIT_HIGH BIT(3) -+#define SWIN_SWOUT_ENABLED BIT(2) -+#define USBSW_OTG_SWITCH_ENABLED BIT(1) -+ -+int stpmic1_powerctrl_on(void); -+int stpmic1_switch_off(void); -+int stpmic1_register_read(uint8_t register_id, uint8_t *value); -+int stpmic1_register_write(uint8_t register_id, uint8_t value); -+int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); -+int stpmic1_regulator_enable(const char *name); -+int stpmic1_regulator_disable(const char *name); -+uint8_t stpmic1_is_regulator_enabled(const char *name); -+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); -+int stpmic1_regulator_voltage_get(const char *name); -+int stpmic1_regulator_pull_down_set(const char *name); -+int stpmic1_regulator_mask_reset_set(const char *name); +@@ -86,15 +86,15 @@ + #define ITSOURCE4_REG 0xB3U + + /* Registers masks */ +-#define LDO_VOLTAGE_MASK 0x7CU +-#define BUCK_VOLTAGE_MASK 0xFCU ++#define LDO_VOLTAGE_MASK GENMASK(6, 2) ++#define BUCK_VOLTAGE_MASK GENMASK(7, 2) + #define LDO_BUCK_VOLTAGE_SHIFT 2 +-#define LDO_BUCK_ENABLE_MASK 0x01U +-#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U ++#define LDO_BUCK_ENABLE_MASK BIT(0) ++#define LDO_BUCK_HPLP_ENABLE_MASK BIT(1) + #define LDO_BUCK_HPLP_SHIFT 1 +-#define LDO_BUCK_RANK_MASK 0x01U +-#define LDO_BUCK_RESET_MASK 0x01U +-#define LDO_BUCK_PULL_DOWN_MASK 0x03U ++#define LDO_BUCK_RANK_MASK BIT(0) ++#define LDO_BUCK_RESET_MASK BIT(0) ++#define LDO_BUCK_PULL_DOWN_MASK GENMASK(1, 0) + + /* Pull down register */ + #define BUCK1_PULL_DOWN_SHIFT 0 +@@ -135,12 +135,12 @@ + /* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ + #define SWIN_DETECTOR_ENABLED BIT(7) + #define SWOUT_DETECTOR_ENABLED BIT(6) +-#define VINLOW_HYST_MASK 0x3 ++#define VINLOW_HYST_MASK GENMASK(1, 0) + #define VINLOW_HYST_SHIFT 4 +-#define VINLOW_THRESHOLD_MASK 0x7 ++#define VINLOW_THRESHOLD_MASK GENMASK(2, 0) + #define VINLOW_THRESHOLD_SHIFT 1 +-#define VINLOW_ENABLED 0x01 +-#define VINLOW_CTRL_REG_MASK 0xFF ++#define VINLOW_ENABLED BIT(0) ++#define VINLOW_CTRL_REG_MASK GENMASK(7, 0) + + /* USB Control Register */ + #define BOOST_OVP_DISABLED BIT(7) +@@ -148,6 +148,7 @@ + #define OCP_LIMIT_HIGH BIT(3) + #define SWIN_SWOUT_ENABLED BIT(2) + #define USBSW_OTG_SWITCH_ENABLED BIT(1) ++#define BOOST_ENABLED BIT(0) + + int stpmic1_powerctrl_on(void); + int stpmic1_switch_off(void); +@@ -156,11 +157,15 @@ int stpmic1_register_write(uint8_t register_id, uint8_t value); + int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); + int stpmic1_regulator_enable(const char *name); + int stpmic1_regulator_disable(const char *name); +-uint8_t stpmic1_is_regulator_enabled(const char *name); ++bool stpmic1_is_regulator_enabled(const char *name); + int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); + int stpmic1_regulator_voltage_get(const char *name); + int stpmic1_regulator_pull_down_set(const char *name); + int stpmic1_regulator_mask_reset_set(const char *name); +int stpmic1_lp_copy_reg(const char *name); +int stpmic1_lp_reg_on_off(const char *name, uint8_t enable); +int stpmic1_lp_set_mode(const char *name, uint8_t hplp); +int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts); -+void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); -+ -+int stpmic1_get_version(unsigned long *version); -+void stpmic1_dump_regulators(void); -+ -+#endif /* STPMIC1_H */ -diff --git a/include/drivers/st/stpmu1.h b/include/drivers/st/stpmu1.h -deleted file mode 100644 -index 1b93ab2..0000000 ---- a/include/drivers/st/stpmu1.h -+++ /dev/null -@@ -1,141 +0,0 @@ --/* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- -- --#ifndef __STPMU1_H__ --#define __STPMU1_H__ -- --#include --#include -- --#define TURN_ON_REG 0x1U --#define TURN_OFF_REG 0x2U --#define ICC_LDO_TURN_OFF_REG 0x3U --#define ICC_BUCK_TURN_OFF_REG 0x4U --#define RESET_STATUS_REG 0x5U --#define VERSION_STATUS_REG 0x6U --#define MAIN_CONTROL_REG 0x10U --#define PADS_PULL_REG 0x11U --#define BUCK_PULL_DOWN_REG 0x12U --#define LDO14_PULL_DOWN_REG 0x13U --#define LDO56_PULL_DOWN_REG 0x14U --#define VIN_CONTROL_REG 0x15U --#define PONKEY_TIMER_REG 0x16U --#define MASK_RANK_BUCK_REG 0x17U --#define MASK_RESET_BUCK_REG 0x18U --#define MASK_RANK_LDO_REG 0x19U --#define MASK_RESET_LDO_REG 0x1AU --#define WATCHDOG_CONTROL_REG 0x1BU --#define WATCHDOG_TIMER_REG 0x1CU --#define BUCK_ICC_TURNOFF_REG 0x1DU --#define LDO_ICC_TURNOFF_REG 0x1EU --#define BUCK_APM_CONTROL_REG 0x1FU --#define BUCK1_CONTROL_REG 0x20U --#define BUCK2_CONTROL_REG 0x21U --#define BUCK3_CONTROL_REG 0x22U --#define BUCK4_CONTROL_REG 0x23U --#define VREF_DDR_CONTROL_REG 0x24U --#define LDO1_CONTROL_REG 0x25U --#define LDO2_CONTROL_REG 0x26U --#define LDO3_CONTROL_REG 0x27U --#define LDO4_CONTROL_REG 0x28U --#define LDO5_CONTROL_REG 0x29U --#define LDO6_CONTROL_REG 0x2AU --#define BUCK1_PWRCTRL_REG 0x30U --#define BUCK2_PWRCTRL_REG 0x31U --#define BUCK3_PWRCTRL_REG 0x32U --#define BUCK4_PWRCTRL_REG 0x33U --#define VREF_DDR_PWRCTRL_REG 0x34U --#define LDO1_PWRCTRL_REG 0x35U --#define LDO2_PWRCTRL_REG 0x36U --#define LDO3_PWRCTRL_REG 0x37U --#define LDO4_PWRCTRL_REG 0x38U --#define LDO5_PWRCTRL_REG 0x39U --#define LDO6_PWRCTRL_REG 0x3AU --#define FREQUENCY_SPREADING_REG 0x3BU --#define USB_CONTROL_REG 0x40U --#define ITLATCH1_REG 0x50U --#define ITLATCH2_REG 0x51U --#define ITLATCH3_REG 0x52U --#define ITLATCH4_REG 0x53U --#define ITSETLATCH1_REG 0x60U --#define ITSETLATCH2_REG 0x61U --#define ITSETLATCH3_REG 0x62U --#define ITSETLATCH4_REG 0x63U --#define ITCLEARLATCH1_REG 0x70U --#define ITCLEARLATCH2_REG 0x71U --#define ITCLEARLATCH3_REG 0x72U --#define ITCLEARLATCH4_REG 0x73U --#define ITMASK1_REG 0x80U --#define ITMASK2_REG 0x81U --#define ITMASK3_REG 0x82U --#define ITMASK4_REG 0x83U --#define ITSETMASK1_REG 0x90U --#define ITSETMASK2_REG 0x91U --#define ITSETMASK3_REG 0x92U --#define ITSETMASK4_REG 0x93U --#define ITCLEARMASK1_REG 0xA0U --#define ITCLEARMASK2_REG 0xA1U --#define ITCLEARMASK3_REG 0xA2U --#define ITCLEARMASK4_REG 0xA3U --#define ITSOURCE1_REG 0xB0U --#define ITSOURCE2_REG 0xB1U --#define ITSOURCE3_REG 0xB2U --#define ITSOURCE4_REG 0xB3U --#define LDO_VOLTAGE_MASK 0x7CU --#define BUCK_VOLTAGE_MASK 0xFCU --#define LDO_BUCK_VOLTAGE_SHIFT 2 --#define LDO_ENABLE_MASK 0x01U --#define BUCK_ENABLE_MASK 0x01U --#define BUCK_HPLP_ENABLE_MASK 0x02U --#define LDO_HPLP_ENABLE_MASK 0x02U --#define LDO_BUCK_HPLP_SHIFT 1 --#define LDO_BUCK_RANK_MASK 0x01U --#define LDO_BUCK_RESET_MASK 0x01U --#define LDO_BUCK_PULL_DOWN_MASK 0x03U -- --/* Main PMIC Control Register (MAIN_CONTROL_REG) */ --#define ICC_EVENT_ENABLED BIT(4) --#define PWRCTRL_POLARITY_HIGH BIT(3) --#define PWRCTRL_PIN_VALID BIT(2) --#define RESTART_REQUEST_ENABLED BIT(1) --#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) -- --/* Main PMIC PADS Control Register (PADS_PULL_REG) */ --#define WAKEUP_DETECTOR_DISABLED BIT(4) --#define PWRCTRL_PD_ACTIVE BIT(3) --#define PWRCTRL_PU_ACTIVE BIT(2) --#define WAKEUP_PD_ACTIVE BIT(1) --#define PONKEY_PU_ACTIVE BIT(0) -- --/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ --#define SWIN_DETECTOR_ENABLED BIT(7) --#define SWOUT_DETECTOR_ENABLED BIT(6) --#define VINLOW_HYST_MASK 0x3 --#define VINLOW_HYST_SHIFT 4 --#define VINLOW_THRESHOLD_MASK 0x7 --#define VINLOW_THRESHOLD_SHIFT 1 --#define VINLOW_ENABLED 0x01 --#define VINLOW_CTRL_REG_MASK 0xFF -- --/* USB Control Register */ --#define BOOST_OVP_DISABLED BIT(7) --#define VBUS_OTG_DETECTION_DISABLED BIT(6) --#define OCP_LIMIT_HIGH BIT(3) --#define SWIN_SWOUT_ENABLED BIT(2) --#define USBSW_OTG_SWITCH_ENABLED BIT(1) -- --int stpmu1_switch_off(void); --int stpmu1_register_read(uint8_t register_id, uint8_t *value); --int stpmu1_register_write(uint8_t register_id, uint8_t value); --int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); --int stpmu1_regulator_enable(const char *name); --int stpmu1_regulator_disable(const char *name); --uint8_t stpmu1_is_regulator_enabled(const char *name); --int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts); --void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); -- --#endif /* __STPMU1_H__ */ + void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); + + int stpmic1_get_version(unsigned long *version); diff --git a/include/drivers/st/usb_dwc2.h b/include/drivers/st/usb_dwc2.h new file mode 100644 -index 0000000..85628f1 +index 000000000..caff54669 --- /dev/null +++ b/include/drivers/st/usb_dwc2.h @@ -0,0 +1,443 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -30638,7 +30752,7 @@ index 0000000..85628f1 +#ifndef __USB_DWC2_H +#define __USB_DWC2_H + -+#include ++#include + +/* define value use in register */ + @@ -31072,57 +31186,96 @@ index 0000000..85628f1 + +#endif /* __USB_DWC2_H */ + -diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h -new file mode 100644 -index 0000000..aa9158c ---- /dev/null -+++ b/include/dt-bindings/interrupt-controller/arm-gic.h -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ -+/* -+ * This header provides constants for the ARM GIC. -+ */ +diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h +index 18bdb57f3..824dd45b2 100644 +--- a/include/dt-bindings/clock/stm32mp1-clks.h ++++ b/include/dt-bindings/clock/stm32mp1-clks.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ ++/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ + /* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. +@@ -179,6 +179,12 @@ + #define DAC12_K 168 + #define ETHPTP_K 169 + ++#define PCLK1 170 ++#define PCLK2 171 ++#define PCLK3 172 ++#define PCLK4 173 ++#define PCLK5 174 + -+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H -+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + /* PLL */ + #define PLL1 176 + #define PLL2 177 +@@ -248,4 +254,31 @@ + + #define STM32MP1_LAST_CLK 232 + ++/* SCMI clock identifiers */ ++#define CK_SCMI0_HSE 0 ++#define CK_SCMI0_HSI 1 ++#define CK_SCMI0_CSI 2 ++#define CK_SCMI0_LSE 3 ++#define CK_SCMI0_LSI 4 ++#define CK_SCMI0_PLL2_Q 5 ++#define CK_SCMI0_PLL2_R 6 ++#define CK_SCMI0_MPU 7 ++#define CK_SCMI0_AXI 8 ++#define CK_SCMI0_BSEC 9 ++#define CK_SCMI0_CRYP1 10 ++#define CK_SCMI0_GPIOZ 11 ++#define CK_SCMI0_HASH1 12 ++#define CK_SCMI0_I2C4 13 ++#define CK_SCMI0_I2C6 14 ++#define CK_SCMI0_IWDG1 15 ++#define CK_SCMI0_RNG1 16 ++#define CK_SCMI0_RTC 17 ++#define CK_SCMI0_RTCAPB 18 ++#define CK_SCMI0_SPI6 19 ++#define CK_SCMI0_USART1 20 + -+/* interrupt specifier cell 0 */ ++#define CK_SCMI1_PLL3_Q 0 ++#define CK_SCMI1_PLL3_R 1 ++#define CK_SCMI1_MCU 2 + -+#define GIC_SPI 0 -+#define GIC_PPI 1 -+ -+#define IRQ_TYPE_NONE 0 -+#define IRQ_TYPE_EDGE_RISING 1 -+#define IRQ_TYPE_EDGE_FALLING 2 -+#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) -+#define IRQ_TYPE_LEVEL_HIGH 4 -+#define IRQ_TYPE_LEVEL_LOW 8 -+ -+#endif + #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h -index e2f1f1b..7f6e4b9 100644 +index 7f6e4b94d..1bc2c40fc 100644 --- a/include/dt-bindings/pinctrl/stm32-pinfunc.h +++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h -@@ -32,4 +32,10 @@ +@@ -26,6 +26,7 @@ + #define AF14 0xf + #define AF15 0x10 + #define ANALOG 0x11 ++#define RSVD 0x12 + /* define Pins number*/ + #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) +@@ -33,9 +34,9 @@ #define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) -+/* package information */ -+#define STM32MP157CAA 0x1 -+#define STM32MP157CAB 0x2 -+#define STM32MP157CAC 0x4 -+#define STM32MP157CAD 0x8 -+ + /* package information */ +-#define STM32MP157CAA 0x1 +-#define STM32MP157CAB 0x2 +-#define STM32MP157CAC 0x4 +-#define STM32MP157CAD 0x8 ++#define STM32MP_PKG_AA 0x1 ++#define STM32MP_PKG_AB 0x2 ++#define STM32MP_PKG_AC 0x4 ++#define STM32MP_PKG_AD 0x8 + #endif /* _DT_BINDINGS_STM32_PINFUNC_H */ diff --git a/include/dt-bindings/power/stm32mp1-power.h b/include/dt-bindings/power/stm32mp1-power.h new file mode 100644 -index 0000000..bfb7f78 +index 000000000..d588dd71f --- /dev/null +++ b/include/dt-bindings/power/stm32mp1-power.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved ++ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * Author: Yann Gautier for STMicroelectronics. + */ + @@ -31139,9 +31292,31 @@ index 0000000..bfb7f78 +#define STM32_PM_MAX_SOC_MODE 7 + +#endif /* DT_BINDINGS_STM32MP1_POWER_H */ +diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h +index f0c3aaef6..bc71924fa 100644 +--- a/include/dt-bindings/reset/stm32mp1-resets.h ++++ b/include/dt-bindings/reset/stm32mp1-resets.h +@@ -105,4 +105,17 @@ + #define GPIOJ_R 19785 + #define GPIOK_R 19786 + ++/* SCMI reset domain identifiers */ ++#define RST_SCMI0_SPI6 0 ++#define RST_SCMI0_I2C4 1 ++#define RST_SCMI0_I2C6 2 ++#define RST_SCMI0_USART1 3 ++#define RST_SCMI0_STGEN 4 ++#define RST_SCMI0_GPIOZ 5 ++#define RST_SCMI0_CRYP1 6 ++#define RST_SCMI0_HASH1 7 ++#define RST_SCMI0_RNG1 8 ++#define RST_SCMI0_MDMA 9 ++#define RST_SCMI0_MCU 10 ++ + #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ diff --git a/include/dt-bindings/soc/st,stm32-etzpc.h b/include/dt-bindings/soc/st,stm32-etzpc.h new file mode 100644 -index 0000000..6678b8e +index 000000000..6678b8e66 --- /dev/null +++ b/include/dt-bindings/soc/st,stm32-etzpc.h @@ -0,0 +1,107 @@ @@ -31252,144 +31427,36 @@ index 0000000..6678b8e + +#endif /* _DT_BINDINGS_STM32_ETZPC_H */ + -diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h -index 3536d20..aa34b9c 100644 ---- a/include/lib/aarch32/arch.h -+++ b/include/lib/aarch32/arch.h -@@ -61,6 +61,9 @@ - * Generic timer memory mapped registers & offsets - ******************************************************************************/ - #define CNTCR_OFF U(0x000) -+#define CNTSR_OFF U(0x004) -+#define CNTCVL_OFF U(0x008) -+#define CNTCVU_OFF U(0x00C) - #define CNTFID_OFF U(0x020) - - #define CNTCR_EN (U(1) << 0) -@@ -457,6 +460,8 @@ - #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 VPIDR p15, 4, c0, c0, 0 - #define VMPIDR p15, 4, c0, c0, 5 - #define ISR p15, 0, c12, c1, 0 -@@ -466,6 +471,7 @@ - #define HTCR p15, 4, c2, c0, 2 - #define HMAIR0 p15, 4, c10, c2, 0 - #define ATS1CPR p15, 0, c7, c8, 0 -+#define ATS1CPW p15, 0, c7, c8, 1 - #define ATS1HR p15, 4, c7, c8, 0 - #define DBGOSDLR p14, 0, c1, c3, 4 - -@@ -514,6 +520,12 @@ - #define ICC_ASGI1R_EL1_64 p15, 1, c12 - #define ICC_SGI0R_EL1_64 p15, 2, c12 - -+/* Fault registers. The format is: coproc, opt1, CRn, CRm, opt2 */ -+#define DFSR p15, 0, c5, c0, 0 -+#define IFSR p15, 0, c5, c0, 1 -+#define DFAR p15, 0, c6, c0, 0 -+#define IFAR p15, 0, c6, c0, 2 -+ - /******************************************************************************* - * Definitions of MAIR encodings for device and normal memory - ******************************************************************************/ -@@ -567,6 +579,8 @@ - /* PAR fields */ - #define PAR_F_SHIFT U(0) - #define PAR_F_MASK ULL(0x1) -+#define PAR_NS_SHIFT U(9) -+#define PAR_NS_MASK U(0x1) - #define PAR_ADDR_SHIFT U(12) - #define PAR_ADDR_MASK (BIT_64(40) - ULL(1)) /* 40-bits-wide page address */ - -diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h -index 5d9c1c1..e48123c 100644 ---- a/include/lib/aarch32/arch_helpers.h -+++ b/include/lib/aarch32/arch_helpers.h -@@ -261,6 +261,8 @@ 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(icc_sre_el1, ICC_SRE) - DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE) -@@ -282,6 +284,7 @@ DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL) - DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) - - DEFINE_COPROCR_RW_FUNCS(ats1cpr, ATS1CPR) -+DEFINE_COPROCR_RW_FUNCS(ats1cpw, ATS1CPW) - DEFINE_COPROCR_RW_FUNCS(ats1hr, ATS1HR) - DEFINE_COPROCR_RW_FUNCS_64(par, PAR_64) - -diff --git a/include/lib/cpus/aarch32/cortex_a9.h b/include/lib/cpus/aarch32/cortex_a9.h -index be85f9b..ea8412f 100644 ---- a/include/lib/cpus/aarch32/cortex_a9.h -+++ b/include/lib/cpus/aarch32/cortex_a9.h -@@ -18,6 +18,11 @@ - #define CORTEX_A9_ACTLR_SMP_BIT (1 << 6) - #define CORTEX_A9_ACTLR_FLZW_BIT (1 << 3) - -+#if defined(ARMV7_CORTEX_A_ACTLR_FLZW_BIT) && \ -+ ARMV7_CORTEX_A_ACTLR_FLZW_BIT != CORTEX_A9_ACTLR_FLZW_BIT -+#error Cortex-A9 ACTLR field FLZW does not match -+#endif -+ - /******************************************************************************* - * CPU Power Control Register - ******************************************************************************/ diff --git a/include/lib/optee_utils.h b/include/lib/optee_utils.h -index 3d35b19..96c90bd 100644 +index 6067caff4..ba44f998e 100644 --- a/include/lib/optee_utils.h +++ b/include/lib/optee_utils.h -@@ -8,6 +8,7 @@ +@@ -9,6 +9,7 @@ - #include + #include +int get_optee_header_ep(entry_point_info_t *header_ep, uintptr_t *pc); int parse_optee_header(entry_point_info_t *header_ep, image_info_t *pager_image_info, image_info_t *paged_image_info); -diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h -index b27e481..b7febc3 100644 ---- a/include/lib/psci/psci.h -+++ b/include/lib/psci/psci.h -@@ -302,10 +302,10 @@ typedef struct plat_psci_ops { - void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); - void (*pwr_domain_suspend_finish)( - const psci_power_state_t *target_state); -- void (*pwr_domain_pwr_down_wfi)( -- const psci_power_state_t *target_state) __dead2; -- void (*system_off)(void) __dead2; -- void (*system_reset)(void) __dead2; -+ void __dead2 (*pwr_domain_pwr_down_wfi)( -+ const psci_power_state_t *target_state); -+ void __dead2 (*system_off)(void); -+ void __dead2 (*system_reset)(void); - int (*validate_power_state)(unsigned int power_state, - psci_power_state_t *req_state); - int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint); diff --git a/include/lib/usb/usb_core.h b/include/lib/usb/usb_core.h new file mode 100644 -index 0000000..eb0e87a +index 000000000..e4dd43862 --- /dev/null +++ b/include/lib/usb/usb_core.h -@@ -0,0 +1,352 @@ +@@ -0,0 +1,353 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __USBD_CORE_H -+#define __USBD_CORE_H ++#ifndef USB_CORE_H ++#define USB_CORE_H + +#include -+#include ++ ++#include + +#define USBD_MAX_NUM_INTERFACES 1 +#define USBD_MAX_NUM_CONFIGURATION 1 @@ -31730,24 +31797,25 @@ index 0000000..eb0e87a +usb_status_t register_platform(usb_handle_t *pdev, + const usb_desc_t *plat_call_back); + -+#endif /* __USBD_CORE_H */ ++#endif /* USB_CORE_H */ diff --git a/include/lib/usb/usb_st_dfu.h b/include/lib/usb/usb_st_dfu.h new file mode 100644 -index 0000000..3709683 +index 000000000..8a3a5a505 --- /dev/null +++ b/include/lib/usb/usb_st_dfu.h -@@ -0,0 +1,115 @@ +@@ -0,0 +1,116 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __USB_DFU_H -+#define __USB_DFU_H ++#ifndef USB_ST_DFU_H ++#define USB_ST_DFU_H + +#include -+#include ++ ++#include + +#define DFU_DESCRIPTOR_TYPE 0x21 + @@ -31851,85 +31919,15 @@ index 0000000..3709683 +uint32_t usb_dfu_detach_req(void); +void usb_dfu_request_detach(void); + -+#endif /* __USB_DFU_H */ -diff --git a/include/lib/utils.h b/include/lib/utils.h -index d46d846..b6ab26e 100644 ---- a/include/lib/utils.h -+++ b/include/lib/utils.h -@@ -4,8 +4,8 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef __UTILS_H__ --#define __UTILS_H__ -+#ifndef UTILS_H -+#define UTILS_H - - /* - * C code should be put in this part of the header to avoid breaking ASM files -@@ -67,6 +67,29 @@ void zero_normalmem(void *mem, u_register_t length); - * zeroing. - */ - void zeromem(void *mem, u_register_t length); -+ -+/* -+ * Utility function to return the address of a symbol. By default, the -+ * compiler generates adr/adrp instruction pair to return the reference -+ * to the symbol and this utility is used to override this compiler -+ * generated to code to use `ldr` instruction. -+ * -+ * This helps when Position Independent Executable needs to reference a symbol -+ * which is constant and does not depend on the execute address of the binary. -+ */ -+#define DEFINE_LOAD_SYM_ADDR(_name) \ -+static inline u_register_t load_addr_## _name(void) \ -+{ \ -+ u_register_t v; \ -+ /* Create a void reference to silence compiler */ \ -+ (void) _name; \ -+ __asm__ volatile ("ldr %0, =" #_name : "=r" (v)); \ -+ return v; \ -+} -+ -+/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */ -+#define LOAD_ADDR_OF(_name) (typeof(_name) *) load_addr_## _name() -+ - #endif /* !(defined(__LINKER__) || defined(__ASSEMBLY__)) */ - --#endif /* __UTILS_H__ */ -+#endif /* UTILS_H */ ++#endif /* USB_ST_DFU_H */ diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h -index 5b4fd78..51863d8 100644 +index 35ae33a68..8efa90751 100644 --- a/include/lib/utils_def.h +++ b/include/lib/utils_def.h -@@ -30,11 +30,19 @@ - * position @h. For example - * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. - */ -+#if defined(__LINKER__) || defined(__ASSEMBLY__) -+#define GENMASK_32(h, l) \ -+ (((0xFFFFFFFF) << (l)) & (0xFFFFFFFF >> (32 - 1 - (h)))) -+ -+#define GENMASK_64(h, l) \ -+ ((~0 << (l)) & (~0 >> (64 - 1 - (h)))) -+#else - #define GENMASK_32(h, l) \ - (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) +@@ -63,6 +63,16 @@ + ((val) + _div - (__typeof__(div)) 1) / _div; \ + }) - #define GENMASK_64(h, l) \ - (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) -+#endif - - #ifdef AARCH32 - #define GENMASK GENMASK_32 -@@ -50,7 +58,17 @@ - - #define div_round_up(val, div) __extension__ ({ \ - __typeof__(div) _div = (div); \ -- ((val) + _div - 1) / _div; \ -+ ((val) + _div - (__typeof__(div)) 1) / _div; \ -+}) -+ +/* + * Macro for unsigned integer division with nearest rounding variant. + * Default integer division rounds down. @@ -31938,14 +31936,32 @@ index 5b4fd78..51863d8 100644 + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (_x + (_y / 2)) / _y; \ ++}) ++ + #define MIN(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ +@@ -77,6 +87,15 @@ + _x > _y ? _x : _y; \ }) - #define MIN(x, y) __extension__ ({ \ ++#define CLAMP(x, min, max) __extension__ ({ \ ++ __typeof__(x) _x = (x); \ ++ __typeof__(min) _min = (min); \ ++ __typeof__(max) _max = (max); \ ++ (void)(&_x == &_min); \ ++ (void)(&_x == &_max); \ ++ (_x > _max ? _max : (_x < _min ? _min : _x)); \ ++}) ++ + /* + * The round_up() macro rounds up a value to the given boundary in a + * type-agnostic yet type-safe manner. The boundary must be a power of two. diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h -index fa89958..c9504b3 100644 +index b17b71a87..69f142aab 100644 --- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h +++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h -@@ -120,6 +120,37 @@ struct xlat_ctx { +@@ -122,6 +122,37 @@ struct xlat_ctx { /* do nothing */ #endif /* PLAT_XLAT_TABLES_DYNAMIC */ @@ -31983,7 +31999,7 @@ index fa89958..c9504b3 100644 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ _xlat_tables_count, _virt_addr_space_size, \ _phy_addr_space_size, _xlat_regime, _section_name)\ -@@ -131,14 +162,8 @@ struct xlat_ctx { +@@ -130,14 +161,8 @@ struct xlat_ctx { \ static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \ \ @@ -32001,10 +32017,10 @@ index fa89958..c9504b3 100644 XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ \ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h -index a30b579..1a6161e 100644 +index eeae62141..0922c5342 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h -@@ -93,6 +93,11 @@ unsigned int plat_ic_get_interrupt_id(unsigned int raw); +@@ -96,6 +96,11 @@ unsigned int plat_ic_get_interrupt_id(unsigned int raw); ******************************************************************************/ uintptr_t plat_get_my_stack(void); void plat_report_exception(unsigned int exception_type); @@ -32016,52 +32032,74 @@ index a30b579..1a6161e 100644 int plat_crash_console_init(void); int plat_crash_console_putc(int c); int plat_crash_console_flush(void); -diff --git a/lib/compiler-rt/builtins/int_lib.h b/lib/compiler-rt/builtins/int_lib.h -index 787777a..80a7c41 100644 ---- a/lib/compiler-rt/builtins/int_lib.h -+++ b/lib/compiler-rt/builtins/int_lib.h -@@ -27,27 +27,28 @@ +@@ -103,7 +108,7 @@ void plat_error_handler(int err) __dead2; + void plat_panic_handler(void) __dead2; + const char *plat_log_get_prefix(unsigned int log_level); + void bl2_plat_preload_setup(void); +-int plat_try_next_boot_source(void); ++int plat_try_next_boot_source(unsigned int image_id); - #if defined(__ELF__) - #define FNALIAS(alias_name, original_name) \ -- void alias_name() __attribute__((alias(#original_name))) -+ void alias_name() __attribute__((__alias__(#original_name))) -+#define COMPILER_RT_ALIAS(aliasee) __attribute__((__alias__(#aliasee))) - #else - #define FNALIAS(alias, name) _Pragma("GCC error(\"alias unsupported on this file format\")") -+#define COMPILER_RT_ALIAS(aliasee) _Pragma("GCC error(\"alias unsupported on this file format\")") - #endif - - /* ABI macro definitions */ - - #if __ARM_EABI__ --# define ARM_EABI_FNALIAS(aeabi_name, name) \ -- void __aeabi_##aeabi_name() __attribute__((alias("__" #name))); - # ifdef COMPILER_RT_ARMHF_TARGET - # define COMPILER_RT_ABI - # else --# define COMPILER_RT_ABI __attribute__((pcs("aapcs"))) -+# define COMPILER_RT_ABI __attribute__((__pcs__("aapcs"))) - # endif - #else --# define ARM_EABI_FNALIAS(aeabi_name, name) - # define COMPILER_RT_ABI - #endif - --#ifdef _MSC_VER -+#define AEABI_RTABI __attribute__((__pcs__("aapcs"))) -+ -+#if defined(_MSC_VER) && !defined(__clang__) - #define ALWAYS_INLINE __forceinline - #define NOINLINE __declspec(noinline) - #define NORETURN __declspec(noreturn) -diff --git a/lib/compiler-rt/builtins/lshrdi3.c b/lib/compiler-rt/builtins/lshrdi3.c + /******************************************************************************* + * Mandatory BL1 functions +diff --git a/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S b/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S new file mode 100644 -index 0000000..67b2a76 +index 000000000..038ae5d72 --- /dev/null -+++ b/lib/compiler-rt/builtins/lshrdi3.c -@@ -0,0 +1,45 @@ -+/* ===-- lshrdi3.c - Implement __lshrdi3 -----------------------------------=== ++++ b/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S +@@ -0,0 +1,46 @@ ++//===-- aeabi_ldivmod.S - EABI ldivmod implementation ---------------------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is dual licensed under the MIT and the University of Illinois Open ++// Source Licenses. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "../assembly.h" ++ ++// struct { int64_t quot, int64_t rem} ++// __aeabi_ldivmod(int64_t numerator, int64_t denominator) { ++// int64_t rem, quot; ++// quot = __divmoddi4(numerator, denominator, &rem); ++// return {quot, rem}; ++// } ++ ++#if defined(__MINGW32__) ++#define __aeabi_ldivmod __rt_sdiv64 ++#endif ++ ++ .syntax unified ++ .p2align 2 ++DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) ++ push {r6, lr} ++ sub sp, sp, #16 ++ add r6, sp, #8 ++ str r6, [sp] ++#if defined(__MINGW32__) ++ movs r6, r0 ++ movs r0, r2 ++ movs r2, r6 ++ movs r6, r1 ++ movs r1, r3 ++ movs r3, r6 ++#endif ++ bl SYMBOL_NAME(__divmoddi4) ++ ldr r2, [sp, #8] ++ ldr r3, [sp, #12] ++ add sp, sp, #16 ++ pop {r6, pc} ++END_COMPILERRT_FUNCTION(__aeabi_ldivmod) ++ ++NO_EXEC_STACK_DIRECTIVE ++ +diff --git a/lib/compiler-rt/builtins/divdi3.c b/lib/compiler-rt/builtins/divdi3.c +new file mode 100644 +index 000000000..b8eebcb20 +--- /dev/null ++++ b/lib/compiler-rt/builtins/divdi3.c +@@ -0,0 +1,29 @@ ++/* ===-- divdi3.c - Implement __divdi3 -------------------------------------=== + * + * The LLVM Compiler Infrastructure + * @@ -32070,75 +32108,177 @@ index 0000000..67b2a76 + * + * ===----------------------------------------------------------------------=== + * -+ * This file implements __lshrdi3 for the compiler_rt library. ++ * This file implements __divdi3 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + -+/* Returns: logical a >> b */ -+ -+/* Precondition: 0 <= b < bits_in_dword */ ++/* Returns: a / b */ + +COMPILER_RT_ABI di_int -+__lshrdi3(di_int a, si_int b) ++__divdi3(di_int a, di_int b) +{ -+ const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); -+ udwords input; -+ udwords result; -+ input.all = a; -+ if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ -+ { -+ result.s.high = 0; -+ result.s.low = input.s.high >> (b - bits_in_word); -+ } -+ else /* 0 <= b < bits_in_word */ -+ { -+ if (b == 0) -+ return a; -+ result.s.high = input.s.high >> b; -+ result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b); -+ } -+ return result.all; ++ const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1; ++ di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */ ++ di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */ ++ a = (a ^ s_a) - s_a; /* negate if s_a == -1 */ ++ b = (b ^ s_b) - s_b; /* negate if s_b == -1 */ ++ s_a ^= s_b; /*sign of quotient */ ++ return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */ +} +diff --git a/lib/compiler-rt/builtins/divmoddi4.c b/lib/compiler-rt/builtins/divmoddi4.c +new file mode 100644 +index 000000000..0d4df67a6 +--- /dev/null ++++ b/lib/compiler-rt/builtins/divmoddi4.c +@@ -0,0 +1,25 @@ ++/*===-- divmoddi4.c - Implement __divmoddi4 --------------------------------=== ++ * ++ * The LLVM Compiler Infrastructure ++ * ++ * This file is dual licensed under the MIT and the University of Illinois Open ++ * Source Licenses. See LICENSE.TXT for details. ++ * ++ * ===----------------------------------------------------------------------=== ++ * ++ * This file implements __divmoddi4 for the compiler_rt library. ++ * ++ * ===----------------------------------------------------------------------=== ++ */ + -+#if defined(__ARM_EABI__) -+AEABI_RTABI di_int __aeabi_llsr(di_int a, si_int b) COMPILER_RT_ALIAS(__lshrdi3); -+#endif ++#include "int_lib.h" ++ ++/* Returns: a / b, *rem = a % b */ ++ ++COMPILER_RT_ABI di_int ++__divmoddi4(di_int a, di_int b, di_int* rem) ++{ ++ di_int d = __divdi3(a,b); ++ *rem = a - (d*b); ++ return d; ++} +diff --git a/lib/compiler-rt/builtins/popcountdi2.c b/lib/compiler-rt/builtins/popcountdi2.c +new file mode 100644 +index 000000000..5e8a62f07 +--- /dev/null ++++ b/lib/compiler-rt/builtins/popcountdi2.c +@@ -0,0 +1,36 @@ ++/* ===-- popcountdi2.c - Implement __popcountdi2 ----------------------------=== ++ * ++ * The LLVM Compiler Infrastructure ++ * ++ * This file is dual licensed under the MIT and the University of Illinois Open ++ * Source Licenses. See LICENSE.TXT for details. ++ * ++ * ===----------------------------------------------------------------------=== ++ * ++ * This file implements __popcountdi2 for the compiler_rt library. ++ * ++ * ===----------------------------------------------------------------------=== ++ */ ++ ++#include "int_lib.h" ++ ++/* Returns: count of 1 bits */ ++ ++COMPILER_RT_ABI si_int ++__popcountdi2(di_int a) ++{ ++ du_int x2 = (du_int)a; ++ x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL); ++ /* Every 2 bits holds the sum of every pair of bits (32) */ ++ x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL); ++ /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (16) */ ++ x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL; ++ /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (8) */ ++ su_int x = (su_int)(x2 + (x2 >> 32)); ++ /* The lower 32 bits hold four 16 bit sums (5 significant bits). */ ++ /* Upper 32 bits are garbage */ ++ x = x + (x >> 16); ++ /* The lower 16 bits hold two 32 bit sums (6 significant bits). */ ++ /* Upper 16 bits are garbage */ ++ return (x + (x >> 8)) & 0x0000007F; /* (7 significant bits) */ ++} +diff --git a/lib/compiler-rt/builtins/popcountsi2.c b/lib/compiler-rt/builtins/popcountsi2.c +new file mode 100644 +index 000000000..44544ff49 +--- /dev/null ++++ b/lib/compiler-rt/builtins/popcountsi2.c +@@ -0,0 +1,33 @@ ++/* ===-- popcountsi2.c - Implement __popcountsi2 ---------------------------=== ++ * ++ * The LLVM Compiler Infrastructure ++ * ++ * This file is dual licensed under the MIT and the University of Illinois Open ++ * Source Licenses. See LICENSE.TXT for details. ++ * ++ * ===----------------------------------------------------------------------=== ++ * ++ * This file implements __popcountsi2 for the compiler_rt library. ++ * ++ * ===----------------------------------------------------------------------=== ++ */ ++ ++#include "int_lib.h" ++ ++/* Returns: count of 1 bits */ ++ ++COMPILER_RT_ABI si_int ++__popcountsi2(si_int a) ++{ ++ su_int x = (su_int)a; ++ x = x - ((x >> 1) & 0x55555555); ++ /* Every 2 bits holds the sum of every pair of bits */ ++ x = ((x >> 2) & 0x33333333) + (x & 0x33333333); ++ /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) */ ++ x = (x + (x >> 4)) & 0x0F0F0F0F; ++ /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) */ ++ x = (x + (x >> 16)); ++ /* The lower 16 bits hold two 8 bit sums (5 significant bits).*/ ++ /* Upper 16 bits are garbage */ ++ return (x + (x >> 8)) & 0x0000003F; /* (6 significant bits) */ ++} diff --git a/lib/compiler-rt/compiler-rt.mk b/lib/compiler-rt/compiler-rt.mk -index cb5ab31..49e497e 100644 +index 49e497eb8..40c669f98 100644 --- a/lib/compiler-rt/compiler-rt.mk +++ b/lib/compiler-rt/compiler-rt.mk -@@ -31,5 +31,6 @@ +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are met: +@@ -28,9 +28,15 @@ + # POSSIBILITY OF SUCH DAMAGE. + # + ++COMPILER_RT_SRCS := lib/compiler-rt/builtins/popcountdi2.c \ ++ lib/compiler-rt/builtins/popcountsi2.c ++ ifeq (${ARCH},aarch32) - COMPILER_RT_SRCS := lib/compiler-rt/builtins/arm/aeabi_uldivmod.S \ - lib/compiler-rt/builtins/udivmoddi4.c \ -- lib/compiler-rt/builtins/ctzdi2.c -+ lib/compiler-rt/builtins/ctzdi2.c \ -+ lib/compiler-rt/builtins/lshrdi3.c +-COMPILER_RT_SRCS := lib/compiler-rt/builtins/arm/aeabi_uldivmod.S \ +- lib/compiler-rt/builtins/udivmoddi4.c \ ++COMPILER_RT_SRCS += lib/compiler-rt/builtins/arm/aeabi_ldivmod.S \ ++ lib/compiler-rt/builtins/arm/aeabi_uldivmod.S \ + lib/compiler-rt/builtins/ctzdi2.c \ +- lib/compiler-rt/builtins/lshrdi3.c ++ lib/compiler-rt/builtins/divdi3.c \ ++ lib/compiler-rt/builtins/divmoddi4.c \ ++ lib/compiler-rt/builtins/lshrdi3.c \ ++ lib/compiler-rt/builtins/udivmoddi4.c endif -diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c -index 0459098..88aeb59 100644 ---- a/lib/libfdt/fdt_ro.c -+++ b/lib/libfdt/fdt_ro.c -@@ -597,7 +597,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) -- return -length; -+ return length; - - len = strlen(string) + 1; - end = list + length; diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c -index 34d095b..0f1e560 100644 +index 2a407939b..d5a336b55 100644 --- a/lib/optee/optee_utils.c +++ b/lib/optee/optee_utils.c @@ -132,6 +132,36 @@ static int parse_optee_image(image_info_t *image_info, + return 0; } - /******************************************************************************* ++/******************************************************************************* + * Parse the OPTEE header for an executable entry point address. + * Return 1 on success, 0 on failure. + ******************************************************************************/ @@ -32168,25 +32308,25 @@ index 34d095b..0f1e560 100644 + return 0; +} + -+/******************************************************************************* + /******************************************************************************* * Parse the OPTEE header * Return 0 on success or a negative error code otherwise. - ******************************************************************************/ diff --git a/lib/usb/usb_core.c b/lib/usb/usb_core.c new file mode 100644 -index 0000000..240c1c1 +index 000000000..fd0f20424 --- /dev/null +++ b/lib/usb/usb_core.c -@@ -0,0 +1,732 @@ +@@ -0,0 +1,733 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include -+#include -+#include "usb_core.h" ++ ++#include ++#include + +/* + * @brief Set a STALL condition over an endpoint @@ -32912,20 +33052,22 @@ index 0000000..240c1c1 +} diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c new file mode 100644 -index 0000000..2cf01f6 +index 000000000..8876b7499 --- /dev/null +++ b/lib/usb/usb_st_dfu.c @@ -0,0 +1,865 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#include -+#include +#include -+#include ++ ++#include ++ ++#include ++#include + +static uintptr_t usbd_dfu_download_address; +static uint32_t usbd_dfu_phase_id; @@ -33608,8 +33750,7 @@ index 0000000..2cf01f6 + INFO("\t\tDFU_STATE_MANIFEST\n"); + break; + case DFU_STATE_MANIFEST_WAIT_RESET: -+ INFO( -+ "\t\tDFU_STATE_MANIFEST_WAIT_RESET\n"); ++ INFO("\t\tDFU_STATE_MANIFEST_WAIT_RESET\n"); + break; + case DFU_STATE_UPLOAD_IDLE: + INFO("\t\tDFU_STATE_UPLOAD_IDLE\n"); @@ -33657,8 +33798,7 @@ index 0000000..2cf01f6 + INFO("\t\tDFU_STATE_MANIFEST\n"); + break; + case DFU_STATE_MANIFEST_WAIT_RESET: -+ INFO( -+ "\t\tDFU_STATE_MANIFEST_WAIT_RESET\n"); ++ INFO("\t\tDFU_STATE_MANIFEST_WAIT_RESET\n"); + break; + case DFU_STATE_UPLOAD_IDLE: + INFO("\t\tDFU_STATE_UPLOAD_IDLE\n"); @@ -33677,7 +33817,7 @@ index 0000000..2cf01f6 + break; + + case DFU_DETACH: -+ INFO("Receive DFU detach\n"); ++ usb_dfu_detach(pdev, req); + break; + + default: @@ -33782,10 +33922,10 @@ index 0000000..2cf01f6 + usbd_detach_req = 1; +} diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c -index 5595703..27e7207 100644 +index 4b01b9b7a..f045d3e16 100644 --- a/lib/xlat_tables/aarch32/xlat_tables.c +++ b/lib/xlat_tables/aarch32/xlat_tables.c -@@ -23,8 +23,17 @@ +@@ -26,8 +26,17 @@ #define NUM_BASE_LEVEL_ENTRIES \ GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) @@ -33804,10 +33944,10 @@ index 5595703..27e7207 100644 #if ENABLE_ASSERTIONS static unsigned long long get_max_supported_pa(void) diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c -index 4afdeed..309fda1 100644 +index c86412c9b..e62454d55 100644 --- a/lib/xlat_tables/aarch64/xlat_tables.c +++ b/lib/xlat_tables/aarch64/xlat_tables.c -@@ -22,6 +22,10 @@ +@@ -25,6 +25,10 @@ #define NUM_BASE_LEVEL_ENTRIES \ GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) @@ -33819,10 +33959,10 @@ index 4afdeed..309fda1 100644 __aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t)); diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c -index ca67f2a..9c903f9 100644 +index 23fe3f0b4..ba0ffbe19 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c -@@ -35,8 +35,17 @@ +@@ -38,8 +38,17 @@ #define UNSET_DESC ~0ULL #define MT_UNKNOWN ~0U @@ -33840,7 +33980,7 @@ index ca67f2a..9c903f9 100644 static unsigned int next_xlat; static unsigned long long xlat_max_pa; -@@ -408,6 +417,15 @@ void init_xlation_table(uintptr_t base_va, uint64_t *table, +@@ -411,6 +420,15 @@ void init_xlation_table(uintptr_t base_va, uint64_t *table, ap1_mask = 0ULL; } @@ -33857,10 +33997,10 @@ index ca67f2a..9c903f9 100644 *max_va = xlat_max_va; *max_pa = xlat_max_pa; diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c -index 003718e..a410ad6 100644 +index 4f62f469f..2982b25e6 100644 --- a/lib/xlat_tables_v2/xlat_tables_core.c +++ b/lib/xlat_tables_v2/xlat_tables_core.c -@@ -1026,7 +1026,12 @@ void init_xlat_tables_ctx(xlat_ctx_t *ctx) +@@ -1191,7 +1191,12 @@ void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) xlat_mmap_print(mm); /* All tables must be zeroed before mapping any region. */ @@ -33874,46 +34014,13 @@ index 003718e..a410ad6 100644 for (unsigned int i = 0U; i < ctx->base_table_entries; i++) ctx->base_table[i] = INVALID_DESC; -diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk -index 92a0f6e..44c537b 100644 ---- a/make_helpers/build_macros.mk -+++ b/make_helpers/build_macros.mk -@@ -450,17 +450,24 @@ endef - # $(2) = input dts - define MAKE_DTB - -+# List of DTB file(s) to generate, based on DTS file basename list - $(eval DOBJ := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) -+# List of the pre-compiled DTS file(s) - $(eval DPRE := $(addprefix $(1)/,$(patsubst %.dts,%.pre.dts,$(notdir $(2))))) --$(eval DEP := $(patsubst %.dtb,%.d,$(DOBJ))) -+# Dependencies of the pre-compiled DTS file(s) on its source and included files -+$(eval DTSDEP := $(patsubst %.dtb,%.o.d,$(DOBJ))) -+# Dependencies of the DT compilation on its pre-compiled DTS -+$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DOBJ))) - - $(DOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs - @echo " CPP $$<" -- $$(Q)$$(CPP) $$(CPPFLAGS) -x assembler-with-cpp -o $(DPRE) $$< -+ $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) -+ $$(Q)$$(CPP) $$(CPPFLAGS) -x assembler-with-cpp -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$< - @echo " DTC $$<" -- $$(Q)$$(DTC) $$(DTC_FLAGS) -i fdts -d $(DEP) -o $$@ $(DPRE) -+ $$(Q)$$(DTC) $$(DTC_FLAGS) -i fdts -d $(DTBDEP) -o $$@ $(DPRE) - ---include $(DEP) -+-include $(DTBDEP) -+-include $(DTSDEP) - - endef - diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk -index 7df4cd2..0ade4e7 100644 +index b7fb173b1..df8ab79e4 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk -@@ -79,6 +79,9 @@ ENABLE_STACK_PROTECTOR := 0 - # Flag to enable exception handling in EL3 - EL3_EXCEPTION_HANDLING := 0 +@@ -106,6 +106,9 @@ ENABLE_BTI := 0 + # Use BRANCH_PROTECTION to enable PAUTH. + ENABLE_PAUTH := 0 +# Flag to enable exception debug for AARCH32 +AARCH32_EXCEPTION_DEBUG := 0 @@ -33921,199 +34028,11 @@ index 7df4cd2..0ade4e7 100644 # Build flag to treat usage of deprecated platform and framework APIs as error. ERROR_DEPRECATED := 0 -diff --git a/plat/arm/common/aarch32/arm_helpers.S b/plat/arm/common/aarch32/arm_helpers.S -index c4cfa8a..badddd3 100644 ---- a/plat/arm/common/aarch32/arm_helpers.S -+++ b/plat/arm/common/aarch32/arm_helpers.S -@@ -48,7 +48,7 @@ func plat_crash_console_init - ldr r0, =PLAT_ARM_CRASH_UART_BASE - ldr r1, =PLAT_ARM_CRASH_UART_CLK_IN_HZ - ldr r2, =ARM_CONSOLE_BAUDRATE -- b console_core_init -+ b console_pl011_core_init - endfunc plat_crash_console_init - - /* --------------------------------------------- -@@ -60,7 +60,7 @@ endfunc plat_crash_console_init - */ - func plat_crash_console_putc - ldr r1, =PLAT_ARM_CRASH_UART_BASE -- b console_core_putc -+ b console_pl011_core_putc - endfunc plat_crash_console_putc - - /* --------------------------------------------- -@@ -73,5 +73,5 @@ endfunc plat_crash_console_putc - */ - func plat_crash_console_flush - ldr r0, =PLAT_ARM_CRASH_UART_BASE -- b console_core_flush -+ b console_pl011_core_flush - endfunc plat_crash_console_flush -diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk -index a8df5ba..9d31f08 100644 ---- a/plat/arm/common/arm_common.mk -+++ b/plat/arm/common/arm_common.mk -@@ -123,9 +123,7 @@ ENABLE_PMF := 1 - SEPARATE_CODE_AND_RODATA := 1 - - # Use the multi console API, which is only available for AArch64 for now --ifeq (${ARCH}, aarch64) -- MULTI_CONSOLE_API := 1 --endif -+MULTI_CONSOLE_API := 1 - - # Disable ARM Cryptocell by default - ARM_CRYPTOCELL_INTEG := 0 -diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c -index 10c1914..b8234c1 100644 ---- a/plat/arm/common/sp_min/arm_sp_min_setup.c -+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -61,8 +62,7 @@ void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config, - uintptr_t hw_config, void *plat_params_from_bl2) - { - /* Initialize the console to provide early debug support */ -- console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, -- ARM_CONSOLE_BAUDRATE); -+ arm_console_boot_init(); - - #if RESET_TO_SP_MIN - /* There are no parameters from BL2 if SP_MIN is a reset vector */ -@@ -152,8 +152,7 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - void arm_sp_min_plat_runtime_setup(void) - { - /* Initialize the runtime console */ -- console_init(PLAT_ARM_SP_MIN_RUN_UART_BASE, -- PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ, ARM_CONSOLE_BAUDRATE); -+ arm_console_runtime_init(); - } - - /******************************************************************************* -diff --git a/plat/common/aarch32/crash_console_helpers.S b/plat/common/aarch32/crash_console_helpers.S -new file mode 100644 -index 0000000..fc37c08 ---- /dev/null -+++ b/plat/common/aarch32/crash_console_helpers.S -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+/* -+ * If a platform wishes to use the functions in this file it has to be added to -+ * the Makefile of the platform. It is not included in the common Makefile. -+ */ -+ -+#include -+#include -+ -+ .globl plat_crash_console_init -+ .globl plat_crash_console_putc -+ .globl plat_crash_console_flush -+ -+#if MULTI_CONSOLE_API -+ -+ /* ----------------------------------------------------- -+ * int plat_crash_console_init(void) -+ * Use normal console by default. Switch it to crash -+ * mode so serial consoles become active again. -+ * NOTE: This default implementation will only work for -+ * crashes that occur after a normal console (marked -+ * valid for the crash state) has been registered with -+ * the console framework. To debug crashes that occur -+ * earlier, the platform has to override these functions -+ * with an implementation that initializes a console -+ * driver with hardcoded parameters. See -+ * docs/porting-guide.rst for more information. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_init -+#if defined(IMAGE_BL1) -+ /* -+ * BL1 code can possibly crash so early that the data segment is not yet -+ * accessible. Don't risk undefined behavior by trying to run the normal -+ * console framework. Platforms that want to debug BL1 will need to -+ * override this with custom functions that can run from registers only. -+ */ -+ mov r0, #0 -+ bx lr -+#else /* IMAGE_BL1 */ -+ mov r3, lr -+ mov r0, #CONSOLE_FLAG_CRASH -+ bl console_switch_state -+ mov r0, #1 -+ bx r3 -+#endif -+endfunc plat_crash_console_init -+ -+ /* ----------------------------------------------------- -+ * void plat_crash_console_putc(int character) -+ * Output through the normal console by default. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_putc -+ b console_putc -+endfunc plat_crash_console_putc -+ -+ /* ----------------------------------------------------- -+ * void plat_crash_console_flush(void) -+ * Flush normal console by default. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_flush -+ b console_flush -+endfunc plat_crash_console_flush -+ -+#else /* MULTI_CONSOLE_API */ -+ -+ /* ----------------------------------------------------- -+ * In the old API these are all no-op stubs that need to -+ * be overridden by the platform to be useful. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_init -+ mov r0, #0 -+ bx lr -+endfunc plat_crash_console_init -+ -+func plat_crash_console_putc -+ bx lr -+endfunc plat_crash_console_putc -+ -+func plat_crash_console_flush -+ bx lr -+endfunc plat_crash_console_flush -+ -+#endif -diff --git a/plat/common/aarch32/plat_sp_min_common.c b/plat/common/aarch32/plat_sp_min_common.c -index a9a92c7..f1b1e9c 100644 ---- a/plat/common/aarch32/plat_sp_min_common.c -+++ b/plat/common/aarch32/plat_sp_min_common.c -@@ -21,5 +21,9 @@ void sp_min_plat_runtime_setup(void) - * Finish the use of console driver in SP_MIN so that any runtime logs - * from SP_MIN will be suppressed. - */ -+#if MULTI_CONSOLE_API -+ console_switch_state(CONSOLE_FLAG_RUNTIME); -+#else - console_uninit(); -+#endif - } diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S -index d618539..91ddc47 100644 +index 5b9cb5914..d2c20b4a7 100644 --- a/plat/common/aarch32/platform_helpers.S +++ b/plat/common/aarch32/platform_helpers.S -@@ -8,9 +8,16 @@ +@@ -8,6 +8,11 @@ #include .weak plat_report_exception @@ -34121,16 +34040,11 @@ index d618539..91ddc47 100644 + .weak plat_report_undef_inst + .weak plat_report_prefetch_abort + .weak plat_report_data_abort -+#endif -+#if !ERROR_DEPRECATED - .weak plat_crash_console_init - .weak plat_crash_console_putc - .weak plat_crash_console_flush +#endif .weak plat_reset_handler .weak plat_disable_acp .weak bl1_plat_prepare_exit -@@ -26,6 +33,36 @@ func plat_report_exception +@@ -23,6 +28,35 @@ func plat_report_exception bx lr endfunc plat_report_exception @@ -34163,300 +34077,118 @@ index d618539..91ddc47 100644 +endfunc plat_report_data_abort +#endif + -+#if !ERROR_DEPRECATED /* ----------------------------------------------------- * Placeholder function which should be redefined by * each platform. -@@ -54,6 +91,7 @@ func plat_crash_console_flush - mov r0, #0 - bx lr - endfunc plat_crash_console_flush -+#endif +diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c +index b46656c7a..bf7fba807 100644 +--- a/plat/common/plat_bl_common.c ++++ b/plat/common/plat_bl_common.c +@@ -48,7 +48,7 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + return 0; + } - /* ----------------------------------------------------- - * Placeholder function which should be redefined by -diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S -new file mode 100644 -index 0000000..5af8db2 ---- /dev/null -+++ b/plat/common/aarch64/crash_console_helpers.S -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+/* -+ * If a platform wishes to use the functions in this file it has to be added to -+ * the Makefile of the platform. It is not included in the common Makefile. -+ */ -+ -+#include -+#include -+ -+ .globl plat_crash_console_init -+ .globl plat_crash_console_putc -+ .globl plat_crash_console_flush -+ -+#if MULTI_CONSOLE_API -+ -+ /* ----------------------------------------------------- -+ * int plat_crash_console_init(void) -+ * Use normal console by default. Switch it to crash -+ * mode so serial consoles become active again. -+ * NOTE: This default implementation will only work for -+ * crashes that occur after a normal console (marked -+ * valid for the crash state) has been registered with -+ * the console framework. To debug crashes that occur -+ * earlier, the platform has to override these functions -+ * with an implementation that initializes a console -+ * driver with hardcoded parameters. See -+ * docs/porting-guide.rst for more information. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_init -+#if defined(IMAGE_BL1) -+ /* -+ * BL1 code can possibly crash so early that the data segment is not yet -+ * accessible. Don't risk undefined behavior by trying to run the normal -+ * console framework. Platforms that want to debug BL1 will need to -+ * override this with custom functions that can run from registers only. -+ */ -+ mov x0, #0 -+ ret -+#else /* IMAGE_BL1 */ -+ mov x3, x30 -+ mov x0, #CONSOLE_FLAG_CRASH -+ bl console_switch_state -+ mov x0, #1 -+ ret x3 -+#endif -+endfunc plat_crash_console_init -+ -+ /* ----------------------------------------------------- -+ * void plat_crash_console_putc(int character) -+ * Output through the normal console by default. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_putc -+ b console_putc -+endfunc plat_crash_console_putc -+ -+ /* ----------------------------------------------------- -+ * void plat_crash_console_flush(void) -+ * Flush normal console by default. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_flush -+ b console_flush -+endfunc plat_crash_console_flush -+ -+#else /* MULTI_CONSOLE_API */ -+ -+ /* ----------------------------------------------------- -+ * In the old API these are all no-op stubs that need to -+ * be overridden by the platform to be useful. -+ * ----------------------------------------------------- -+ */ -+func plat_crash_console_init -+ mov x0, #0 -+ ret -+endfunc plat_crash_console_init -+ -+func plat_crash_console_putc -+ ret -+endfunc plat_crash_console_putc -+ -+func plat_crash_console_flush -+ ret -+endfunc plat_crash_console_flush -+ -+#endif -diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S -index 7214588..d3ffcaf 100644 ---- a/plat/common/aarch64/platform_helpers.S -+++ b/plat/common/aarch64/platform_helpers.S -@@ -10,9 +10,11 @@ - #include - - .weak plat_report_exception -+#if !ERROR_DEPRECATED - .weak plat_crash_console_init - .weak plat_crash_console_putc - .weak plat_crash_console_flush -+#endif - .weak plat_reset_handler - .weak plat_disable_acp - .weak bl1_plat_prepare_exit -@@ -37,6 +39,7 @@ func plat_report_exception - ret - endfunc plat_report_exception - -+#if !ERROR_DEPRECATED - #if MULTI_CONSOLE_API - /* ----------------------------------------------------- - * int plat_crash_console_init(void) -@@ -109,6 +112,7 @@ func plat_crash_console_flush - ret - endfunc plat_crash_console_flush - #endif -+#endif /* ERROR_DEPRECATED */ - - /* ----------------------------------------------------- - * Placeholder function which should be redefined by -diff --git a/plat/common/plat_log_common.c b/plat/common/plat_log_common.c -index 49e1c15..c757c6b 100644 ---- a/plat/common/plat_log_common.c -+++ b/plat/common/plat_log_common.c -@@ -5,6 +5,7 @@ - */ - - #include -+#include - - /* Allow platforms to override the log prefix string */ - #pragma weak plat_log_get_prefix -diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S -index ad71b89..668fd62 100644 ---- a/plat/imx/common/lpuart_console.S -+++ b/plat/imx/common/lpuart_console.S -@@ -6,6 +6,7 @@ - - #include - #include -+#define USE_FINISH_CONSOLE_REG_2 - #include - #include - #include "imx8_lpuart.h" -@@ -26,7 +27,7 @@ func console_lpuart_register - - mov x0, x6 - mov x30, x7 -- finish_console_register lpuart -+ finish_console_register lpuart putc=1, getc=1 - - register_fail: - ret x7 -diff --git a/plat/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S -index 5c87465..ec4390a 100644 ---- a/plat/layerscape/common/aarch64/ls_console.S -+++ b/plat/layerscape/common/aarch64/ls_console.S -@@ -6,6 +6,7 @@ - - #include - #include -+#define USE_FINISH_CONSOLE_REG_2 - #include - #include - #include "ls_16550.h" -@@ -106,7 +107,7 @@ func console_ls_16550_register - - mov x0, x6 - mov x30, x7 -- finish_console_register ls_16550 -+ finish_console_register ls_16550 putc=1, getc=1, flush=1 - - register_fail: - ret x7 +-int plat_try_next_boot_source(void) ++int plat_try_next_boot_source(unsigned int image_id) + { + return 0; + } diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c -new file mode 100644 -index 0000000..263c3ba ---- /dev/null +index 38b2a0bd7..f94a5c2c2 100644 +--- a/plat/st/common/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c -@@ -0,0 +1,773 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if STM32MP_FMC_NAND -+#include -+#endif -+#include -+#if STM32MP1_QSPI_NOR -+#include -+#endif -+#include -+#include +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,23 +14,42 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include ++#include + #include + #include ++#include ++#include + #include + #include + #include + #include + +#if STM32MP_UART_PROGRAMMER -+#include ++#include +#endif -+#include -+#include -+#if STM32MP_FMC_NAND -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef STM32MP_USB -+#include ++#if STM32MP_USB_PROGRAMMER ++#include ++#include ++#include ++#include +#include -+#include -+#include -+#endif -+#include -+ -+/* IO devices */ -+static const io_dev_connector_t *dummy_dev_con; -+static uintptr_t dummy_dev_handle; -+static uintptr_t dummy_dev_spec; -+ -+static uintptr_t image_dev_handle; -+ -+#if STM32MP_SDMMC || STM32MP_EMMC -+static io_block_spec_t gpt_block_spec = { -+ .offset = 0, -+ .length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */ -+}; -+ -+static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); -+ -+static const io_block_dev_spec_t mmc_block_dev_spec = { -+ /* It's used as temp buffer in block driver */ -+ .buffer = { -+ .offset = (size_t)&block_buffer, -+ .length = MMC_BLOCK_SIZE, -+ }, -+ .ops = { -+ .read = mmc_read_blocks, -+ .write = NULL, -+ }, -+ .block_size = MMC_BLOCK_SIZE, -+}; +#endif + + /* IO devices */ + static const io_dev_connector_t *dummy_dev_con; + static uintptr_t dummy_dev_handle; + static uintptr_t dummy_dev_spec; + + static uintptr_t image_dev_handle; +static uintptr_t storage_dev_handle; + +#if STM32MP_SDMMC || STM32MP_EMMC -+static const io_dev_connector_t *mmc_dev_con; + static io_block_spec_t gpt_block_spec = { + .offset = 0, + .length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */ +@@ -51,8 +70,63 @@ static const io_block_dev_spec_t mmc_block_dev_spec = { + .block_size = MMC_BLOCK_SIZE, + }; + +-static uintptr_t storage_dev_handle; + static const io_dev_connector_t *mmc_dev_con; ++#endif /* STM32MP_SDMMC || STM32MP_EMMC */ ++ ++#if STM32MP_SPI_NOR ++static io_mtd_dev_spec_t spi_nor_dev_spec = { ++ .ops = { ++ .init = spi_nor_init, ++ .read = spi_nor_read, ++ }, ++}; +#endif + -+#if STM32MP1_QSPI_NOR -+static const io_dev_connector_t *qspi_dev_con; -+ -+static QSPI_HandleTypeDef qspi_dev_spec = { -+ .instance = (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE, -+ .is_dual = 0, ++#if STM32MP_RAW_NAND ++static io_mtd_dev_spec_t nand_dev_spec = { ++ .ops = { ++ .init = nand_raw_init, ++ .read = nand_read, ++ }, +}; ++ ++static const io_dev_connector_t *nand_dev_con; ++#endif ++ ++#if STM32MP_SPI_NAND ++static io_mtd_dev_spec_t spi_nand_dev_spec = { ++ .ops = { ++ .init = spi_nand_init, ++ .read = nand_read, ++ }, ++}; ++#endif ++ ++#if STM32MP_SPI_NAND || STM32MP_SPI_NOR ++static const io_dev_connector_t *spi_dev_con; +#endif + +#if STM32MP_UART_PROGRAMMER -+/* uart*/ +static const io_dev_connector_t *uart_dev_con; + +static UART_HandleTypeDef uart_programmer = { @@ -34471,1296 +34203,1615 @@ index 0000000..263c3ba +}; +#endif /* STM32MP_UART_PROGRAMMER */ + -+#ifdef STM32MP_USB ++#if STM32MP_USB_PROGRAMMER +static usb_handle_t usb_core_handle; +static usb_dfu_handle_t usb_dfu_handle; +static pcd_handle_t pcd_handle; +static const io_dev_connector_t *usb_dev_con; -+#endif /*STM32MP_USB*/ -+ -+#if STM32MP_FMC_NAND -+/* nand */ -+static const io_dev_connector_t *nand_dev_con; -+static NAND_HandleTypeDef nand_dev_spec; -+#endif -+ -+#ifdef AARCH32_SP_OPTEE -+static const struct stm32image_part_info optee_header_partition_spec = { -+ .name = OPTEE_HEADER_IMAGE_NAME, -+ .binary_type = OPTEE_HEADER_BINARY_TYPE, -+}; -+ -+static const struct stm32image_part_info optee_pager_partition_spec = { -+ .name = OPTEE_PAGER_IMAGE_NAME, -+ .binary_type = OPTEE_PAGER_BINARY_TYPE, -+}; -+ -+static const struct stm32image_part_info optee_paged_partition_spec = { -+ .name = OPTEE_PAGED_IMAGE_NAME, -+ .binary_type = OPTEE_PAGED_BINARY_TYPE, -+}; -+#else -+static const io_block_spec_t bl32_block_spec = { -+ .offset = BL32_BASE, -+ .length = STM32MP_BL32_SIZE -+}; -+#endif -+ -+static const io_block_spec_t bl2_block_spec = { -+ .offset = BL2_BASE, -+ .length = STM32MP_BL2_SIZE, -+}; -+ -+static const struct stm32image_part_info bl33_partition_spec = { -+ .name = BL33_IMAGE_NAME, -+ .binary_type = BL33_BINARY_TYPE, -+}; -+ -+enum { -+ IMG_IDX_BL33, -+#ifdef AARCH32_SP_OPTEE -+ IMG_IDX_OPTEE_HEADER, -+ IMG_IDX_OPTEE_PAGER, -+ IMG_IDX_OPTEE_PAGED, -+#endif -+ IMG_IDX_NUM -+}; -+ -+static struct stm32image_device_info stm32image_dev_info_spec = { -+ .lba_size = MMC_BLOCK_SIZE, -+ .part_info[IMG_IDX_BL33] = { -+ .name = BL33_IMAGE_NAME, -+ .binary_type = BL33_BINARY_TYPE, -+ }, -+#ifdef AARCH32_SP_OPTEE -+ .part_info[IMG_IDX_OPTEE_HEADER] = { -+ .name = OPTEE_HEADER_IMAGE_NAME, -+ .binary_type = OPTEE_HEADER_BINARY_TYPE, -+ }, -+ .part_info[IMG_IDX_OPTEE_PAGER] = { -+ .name = OPTEE_PAGER_IMAGE_NAME, -+ .binary_type = OPTEE_PAGER_BINARY_TYPE, -+ }, -+ .part_info[IMG_IDX_OPTEE_PAGED] = { -+ .name = OPTEE_PAGED_IMAGE_NAME, -+ .binary_type = OPTEE_PAGED_BINARY_TYPE, -+ }, -+#endif -+}; -+ -+static io_block_spec_t stm32image_block_spec = { -+ .offset = 0, -+ .length = 0, -+}; -+ -+static const io_dev_connector_t *stm32image_dev_con; -+ -+static int open_dummy(const uintptr_t spec); -+static int open_image(const uintptr_t spec); -+static int open_storage(const uintptr_t spec); -+ -+struct plat_io_policy { -+ uintptr_t *dev_handle; -+ uintptr_t image_spec; -+ int (*check)(const uintptr_t spec); -+}; -+ -+static const struct plat_io_policy policies[] = { -+ [BL2_IMAGE_ID] = { -+ .dev_handle = &dummy_dev_handle, -+ .image_spec = (uintptr_t)&bl2_block_spec, -+ .check = open_dummy -+ }, -+#ifdef AARCH32_SP_OPTEE -+ [BL32_IMAGE_ID] = { -+ .dev_handle = &image_dev_handle, -+ .image_spec = (uintptr_t)&optee_header_partition_spec, -+ .check = open_image -+ }, -+ [BL32_EXTRA1_IMAGE_ID] = { -+ .dev_handle = &image_dev_handle, -+ .image_spec = (uintptr_t)&optee_pager_partition_spec, -+ .check = open_image -+ }, -+ [BL32_EXTRA2_IMAGE_ID] = { -+ .dev_handle = &image_dev_handle, -+ .image_spec = (uintptr_t)&optee_paged_partition_spec, -+ .check = open_image -+ }, -+#else -+ [BL32_IMAGE_ID] = { -+ .dev_handle = &dummy_dev_handle, -+ .image_spec = (uintptr_t)&bl32_block_spec, -+ .check = open_dummy -+ }, -+#endif -+ [BL33_IMAGE_ID] = { -+ .dev_handle = &image_dev_handle, -+ .image_spec = (uintptr_t)&bl33_partition_spec, -+ .check = open_image -+ }, ++#endif /* STM32MP_USB_PROGRAMMER */ + + #ifdef AARCH32_SP_OPTEE + static const struct stm32image_part_info optee_header_partition_spec = { +@@ -96,7 +170,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, +@@ -123,7 +197,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); +@@ -169,11 +243,13 @@ static const struct plat_io_policy policies[] = { + .image_spec = (uintptr_t)&bl33_partition_spec, + .check = open_image + }, +#if STM32MP_SDMMC || STM32MP_EMMC -+ [GPT_IMAGE_ID] = { -+ .dev_handle = &storage_dev_handle, -+ .image_spec = (uintptr_t)&gpt_block_spec, -+ .check = open_storage -+ }, + [GPT_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&gpt_block_spec, + .check = open_storage + }, +#endif -+ [STM32_IMAGE_ID] = { -+ .dev_handle = &storage_dev_handle, -+ .image_spec = (uintptr_t)&stm32image_block_spec, -+ .check = open_storage -+ } -+}; -+ -+static int open_dummy(const uintptr_t spec) -+{ -+ return io_dev_init(dummy_dev_handle, 0); -+} -+ -+static int open_image(const uintptr_t spec) -+{ -+ return io_dev_init(image_dev_handle, 0); -+} -+ -+static int open_storage(const uintptr_t spec) -+{ -+ return io_dev_init(storage_dev_handle, 0); -+} -+ -+static void print_boot_device(boot_api_context_t *boot_context) -+{ -+ switch (boot_context->boot_interface_selected) { -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: -+ INFO("Using SDMMC\n"); + [STM32_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&stm32image_block_spec, +@@ -205,8 +281,24 @@ static void print_boot_device(boot_api_context_t *boot_context) + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + INFO("Using EMMC\n"); + break; ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: ++ INFO("Using QSPI NOR\n"); + break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: -+ INFO("Using EMMC\n"); ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: ++ INFO("Using FMC NAND\n"); ++ break; ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: ++ INFO("Using SPI NAND\n"); + break; -+#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + INFO("Using UART\n"); + break; -+#endif -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: -+ INFO("Using NOR\n"); -+ if (boot_context->nor_isdual != 0U) { -+ INFO("NOR is configured in Dual Flash Mode\n"); -+ } -+ break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: -+ INFO("Using NAND\n"); -+ break; -+#ifdef STM32MP_USB + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + INFO("Using USB\n"); + break; -+#endif -+#ifdef STM32MP1_QSPI_NAND -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: -+ INFO("Using QSPI NAND\n"); -+ break; -+#endif -+ default: -+ ERROR("Boot interface not found\n"); -+ panic(); -+ break; + default: +- ERROR("Boot interface not found\n"); ++ ERROR("Boot interface %u not found\n", ++ boot_context->boot_interface_selected); + panic(); + break; + } +@@ -216,6 +308,7 @@ static void print_boot_device(boot_api_context_t *boot_context) + } + } + ++#if STM32MP_SDMMC || STM32MP_EMMC + static void boot_mmc(enum mmc_device_type mmc_dev_type, + uint16_t boot_interface_instance) + { +@@ -251,6 +344,10 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type, + break; + } + ++ if (mmc_dev_type == MMC_IS_SD) { ++ params.flags = MMC_FLAG_SD_CMD6; + } + -+ if (boot_context->boot_interface_instance != 0U) { -+ INFO(" Instance %d\n", boot_context->boot_interface_instance); -+ } -+} + params.device_info = &device_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); +@@ -305,6 +402,243 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type, + &image_dev_handle); + assert(io_result == 0); + } ++#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + -+#if STM32MP_EMMC || STM32MP_SDMMC -+static void print_bootrom_sd_status(boot_api_context_t *boot_context) -+{ -+ if (boot_context->sd_err_internal_timeout_cnt != 0U) { -+ WARN("BootROM: %d timeout issues\n", -+ boot_context->sd_err_internal_timeout_cnt); -+ } -+ -+ if (boot_context->sd_err_dcrc_fail_cnt != 0U) { -+ WARN("BootROM: %d DCRCFAIL error\n", -+ boot_context->sd_err_dcrc_fail_cnt); -+ } -+ -+ if (boot_context->sd_err_dtimeout_cnt != 0U) { -+ WARN("BootROM: %d DTIMEOUT error\n", -+ boot_context->sd_err_dtimeout_cnt); -+ } -+ -+ if (boot_context->sd_err_ctimeout_cnt != 0U) { -+ WARN("BootROM: %d CTIMEOUT error\n", -+ boot_context->sd_err_ctimeout_cnt); -+ } -+ -+ if (boot_context->sd_err_ccrc_fail_cnt != 0U) { -+ WARN("BootROM: %d CCRCFAIL error count\n", -+ boot_context->sd_err_ccrc_fail_cnt); -+ } -+ -+ if (boot_context->sd_overall_retry_cnt != 0U) { -+ WARN("BootROM: %d command retries\n", -+ boot_context->sd_overall_retry_cnt); -+ } -+} -+ -+static void print_bootrom_emmc_status(boot_api_context_t *boot_context) -+{ -+ INFO("BootROM: %d (0x%x) bytes copied from eMMC\n", -+ boot_context->emmc_nbbytes_rxcopied_tosysram_download_area, -+ boot_context->emmc_nbbytes_rxcopied_tosysram_download_area); -+ -+ if (boot_context->emmc_error_status != -+ BOOT_API_CTX_EMMC_ERROR_STATUS_NONE) { -+ WARN("BootROM eMMC error:\n"); -+ switch (boot_context->emmc_error_status) { -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT: -+ WARN(" CMD timeout\n"); -+ break; -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT: -+ WARN(" ACK timeout\n"); -+ break; -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL: -+ WARN(" DATA CRC failed\n"); -+ break; -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX: -+ WARN(" Not enough data copied\n"); -+ break; -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND: -+ WARN(" Header not found\n"); -+ break; -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO: -+ WARN(" Header size is zero\n"); -+ break; -+ case BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE: -+ WARN(" Image not complete\n"); -+ break; -+ default: -+ WARN(" Error not listed\n"); -+ break; -+ } -+ } -+ -+ switch (boot_context->emmc_xfer_status) { -+ case BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED: -+ WARN("BootROM: eMMC transfer status:\n"); -+ WARN(" not started\n"); -+ break; -+ case BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED: -+ break; -+ case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED: -+ WARN("BootROM: eMMC transfer status:\n"); -+ WARN(" timeout detected\n"); -+ break; -+ case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT: -+ WARN("BootROM: eMMC transfer status:\n"); -+ WARN(" data timeout detected\n"); -+ break; -+ default: -+ WARN("BootROM: eMMC transfer status:\n"); -+ WARN(" status not listed\n"); -+ break; -+ } -+} -+#endif -+ -+ -+void stm32mp_io_setup(void) ++#if STM32MP_SPI_NOR ++static void boot_spi_nor(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; ++ ++ io_result = stm32_qspi_init(); ++ assert(io_result == 0); ++ ++ io_result = register_io_dev_mtd(&spi_dev_con); ++ assert(io_result == 0); ++ ++ /* Open connections to device */ ++ io_result = io_dev_open(spi_dev_con, ++ (uintptr_t)&spi_nor_dev_spec, ++ &storage_dev_handle); ++ assert(io_result == 0); ++ ++ stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size; ++ ++ idx = IMG_IDX_BL33; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_BL33_OFFSET; ++ part->bkp_offset = 0U; ++ ++#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 = 0U; ++ ++ idx = IMG_IDX_OPTEE_PAGED; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_TEED_OFFSET; ++ part->bkp_offset = 0U; ++ ++ idx = IMG_IDX_OPTEE_PAGER; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NOR_TEEX_OFFSET; ++ part->bkp_offset = 0U; ++#endif ++ ++ 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); ++} ++#endif /* STM32MP_SPI_NOR */ ++ ++#if STM32MP_RAW_NAND ++static void boot_fmc2_nand(boot_api_context_t *boot_context) ++{ ++ int io_result __unused; ++ uint8_t idx; ++ struct stm32image_part_info *part; ++ ++ io_result = stm32_fmc2_init(); ++ assert(io_result == 0); ++ ++ /* Register the IO device on this platform */ ++ io_result = register_io_dev_mtd(&nand_dev_con); ++ assert(io_result == 0); ++ ++ /* Open connections to device */ ++ 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.device_size; ++ ++ 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.erase_size; ++ ++#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.erase_size; ++ ++ 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.erase_size; ++ ++ 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.erase_size; ++#endif ++ ++ 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); ++} ++#endif /* STM32MP_RAW_NAND */ ++ ++#if STM32MP_SPI_NAND ++static void boot_spi_nand(boot_api_context_t *boot_context) ++{ ++ int io_result __unused; ++ uint8_t idx; ++ struct stm32image_part_info *part; ++ ++ io_result = stm32_qspi_init(); ++ assert(io_result == 0); ++ ++ io_result = register_io_dev_mtd(&spi_dev_con); ++ assert(io_result == 0); ++ ++ /* Open connections to device */ ++ io_result = io_dev_open(spi_dev_con, ++ (uintptr_t)&spi_nand_dev_spec, ++ &storage_dev_handle); ++ assert(io_result == 0); ++ ++ stm32image_dev_info_spec.device_size = ++ spi_nand_dev_spec.device_size; ++ ++ idx = IMG_IDX_BL33; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_BL33_OFFSET; ++ part->bkp_offset = spi_nand_dev_spec.erase_size; ++ ++#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 = spi_nand_dev_spec.erase_size; ++ ++ idx = IMG_IDX_OPTEE_PAGED; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_TEED_OFFSET; ++ part->bkp_offset = spi_nand_dev_spec.erase_size; ++ ++ idx = IMG_IDX_OPTEE_PAGER; ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ part->part_offset = STM32MP_NAND_TEEX_OFFSET; ++ part->bkp_offset = spi_nand_dev_spec.erase_size; ++#endif ++ ++ 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); ++} ++#endif /* STM32MP_SPI_NAND */ ++ +#if STM32MP_UART_PROGRAMMER ++static void flash_uart(uint16_t boot_interface_instance) ++{ ++ int io_result __unused; + 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); ++ /* Register the IO devices on this platform */ ++ io_result = register_io_dev_uart(&uart_dev_con); ++ assert(io_result == 0); + -+ 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); ++ 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 != 0U) { ++ uart_programmer.Instance = (USART_TypeDef *)uart_addr; ++ } else { ++ WARN("UART instance not found, using default\n"); ++ uart_programmer.Instance = (USART_TypeDef *)USART2_BASE; + } + -+ io_result = register_io_dev_dummy(&dummy_dev_con); ++ /* Open connections to devices */ ++ io_result = io_dev_open(uart_dev_con, (uintptr_t)&uart_programmer, ++ &image_dev_handle); + 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) { -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: -+ dmbsy(); -+ -+#if STM32MP_EMMC || STM32MP_SDMMC -+ memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params)); -+ -+ 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_USB_PROGRAMMER ++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.state = HAL_PCD_STATE_READY; ++ ++ usb_core_handle.data = &pcd_handle; ++ ++ usb_dwc2_init_driver(&usb_core_handle, ++ (uint32_t *)USB_OTG_BASE); ++ ++ usb_dfu_register_callback(&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.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_dfu_handle.dev_status[1] = 0; ++ usb_dfu_handle.dev_status[2] = 0; ++ usb_dfu_handle.dev_status[3] = 0; ++ usb_dfu_handle.dev_status[4] = usb_dfu_handle.dev_state; ++ usb_dfu_handle.dev_status[5] = 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 */ ++ io_result = io_dev_open(usb_dev_con, ++ (uintptr_t)&usb_core_handle, ++ &image_dev_handle); ++ ++ assert(io_result == 0); ++} ++#endif + + void stm32mp_io_setup(void) + { +@@ -328,18 +662,53 @@ void stm32mp_io_setup(void) + assert(io_result == 0); + + switch (boot_context->boot_interface_selected) { +#if STM32MP_SDMMC -+ mmc_default_instance = STM32MP_SDMMC1_BASE; -+#else -+ ERROR("MMC driver is not enabled\n"); -+ panic(); + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + dmbsy(); + boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); + break; +#endif -+ } -+ -+ 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; -+ } -+ -+ params.device_info = &device_info; -+ if (stm32_sdmmc2_mmc_init(¶ms) != 0) { -+ ERROR("SDMMC%u init failed\n", -+ boot_context->boot_interface_instance); -+ panic(); -+ } -+ -+ /* Open MMC as a block device to read GPT table */ -+ io_result = register_io_dev_block(&mmc_dev_con); -+ if (io_result != 0) { -+ 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); -+ -+ stm32image_dev_info_spec.device_size = -+ stm32_sdmmc2_mmc_get_device_size(); -+ -+ 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(); -+ } -+ -+ part->part_offset = entry->start; -+ part->bkp_offset = 0U; -+ } -+ -+ /* -+ * 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; -+ -+#if STM32MP1_QSPI_NOR ++#if STM32MP_EMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + dmbsy(); + boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); + break; ++#endif ++#if STM32MP_SPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + dmbsy(); -+ -+ io_result = register_io_dev_qspi(&qspi_dev_con); -+ -+ 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; -+ -+ /* 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); -+ -+ stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE; -+ stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_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; -+ -+#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 = io_dev_open(stm32image_dev_con, -+ (uintptr_t)&stm32image_dev_info_spec, -+ &image_dev_handle); -+ assert(io_result == 0); ++ boot_spi_nor(boot_context); + break; +#endif -+ ++#if STM32MP_RAW_NAND + 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; -+ -+#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 = 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(); -+#endif ++ boot_fmc2_nand(boot_context); + break; -+ ++#endif ++#if STM32MP_SPI_NAND ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: ++ dmbsy(); ++ boot_spi_nand(boot_context); ++ break; ++#endif +#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ -+ /* 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); -+ -+ 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; -+ } -+ -+ /* 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); ++ dmbsy(); ++ flash_uart(boot_context->boot_interface_instance); + break; +#endif -+ -+#ifdef STM32MP_USB ++#if STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ usb_context = (struct usb_ctx *)boot_context->usb_context; -+ -+ pcd_handle.in_ep[0].maxpacket = 0x40; -+ pcd_handle.out_ep[0].maxpacket = 0x40; -+ -+ pcd_handle.state = HAL_PCD_STATE_READY; -+ -+ usb_core_handle.data = &pcd_handle; -+ -+ usb_dwc2_init_driver(&usb_core_handle, -+ (uint32_t *)USB_OTG_BASE); -+ -+ usb_dfu_register_callback(&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.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; -+ -+ /* 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); -+ -+ assert(io_result == 0); ++ dmbsy(); ++ flash_usb((struct usb_ctx *)boot_context->usb_context); + break; +#endif -+#ifdef STM32MP1_QSPI_NAND -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: -+ ERROR("QSPI NAND not supported\n"); -+ break; -+#endif -+ -+ default: -+ ERROR("Boot interface %d not supported\n", -+ boot_context->boot_interface_selected); -+ break; -+ } -+} + + default: + ERROR("Boot interface %d not supported\n", + boot_context->boot_interface_selected); ++ panic(); + break; + } + } +@@ -365,3 +734,58 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + + return rc; + } + +/* -+ * Return an IO device handle and specification which can be used to access -+ * an image. Use this to enforce platform load policy. ++ * This function shall return 0 if it cannot find an alternate ++ * image to be loaded and any non-zero value otherwise. + */ -+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, -+ uintptr_t *image_spec) ++int plat_try_next_boot_source(unsigned int image_id) +{ -+ int rc; ++ int io_result __unused; ++ const struct stm32image_part_info *partition_spec; ++ struct stm32image_part_info *part; + const struct plat_io_policy *policy; ++ uint32_t idx; ++ static unsigned int backup_nb; ++ static unsigned int backup_id = MAX_NUMBER_IDS; + + assert(image_id < ARRAY_SIZE(policies)); + -+ policy = &policies[image_id]; -+ rc = policy->check(policy->image_spec); -+ if (rc == 0) { -+ *image_spec = policy->image_spec; -+ *dev_handle = *(policy->dev_handle); ++ if (backup_id != image_id) { ++ backup_id = image_id; ++ backup_nb = 0; + } + -+ return rc; ++ backup_nb++; ++ ++ if (backup_nb >= PLATFORM_MTD_BACKUP_BLOCKS) { ++ return 0; ++ } ++ ++ policy = &policies[image_id]; ++ partition_spec = (struct stm32image_part_info *)policy->image_spec; ++ for (idx = 0U; idx < STM32_PART_NUM; idx++) { ++ part = &stm32image_dev_info_spec.part_info[idx]; ++ if (part->binary_type == partition_spec->binary_type) { ++ break; ++ } ++ } ++ ++ assert(idx < STM32_PART_NUM); ++ ++ if (part->bkp_offset == 0U) { ++ return 0; ++ } ++ ++ part->part_offset += part->bkp_offset; ++ /* ++ * Reopen the io_dev as it was closed in the load_auth_image() ++ * sequence. ++ */ ++ io_result = io_dev_open(stm32image_dev_con, ++ (uintptr_t)&stm32image_dev_info_spec, ++ &image_dev_handle); ++ assert(io_result == 0); ++ ++ return 1; +} diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h -new file mode 100644 -index 0000000..70f8202 ---- /dev/null -+++ b/plat/st/common/include/stm32mp_auth.h -@@ -0,0 +1,15 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_AUTH_H -+#define STM32MP_AUTH_H -+ -+#include -+ -+int check_header(boot_api_image_header_t *header, uintptr_t buffer); -+int check_authentication(boot_api_image_header_t *header, uintptr_t buffer); -+ -+#endif /* STM32MP_AUTH_H */ +deleted file mode 100644 +index 3075d18ac..000000000 +--- a/plat/st/common/include/stm32mp_auth.h ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* +- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ +- +-#ifndef STM32MP_AUTH_H +-#define STM32MP_AUTH_H +- +-struct stm32mp_auth_ops { +- uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out); +- uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in, +- uint8_t *signature, uint32_t ecc_algo); +-}; +- +-void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr); +-int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer); +- +-#endif /* STM32MP_AUTH_H */ diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h -new file mode 100644 -index 0000000..dc2568b6 ---- /dev/null +index 4f8567979..ab419f15f 100644 +--- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_COMMON_H -+#define STM32MP_COMMON_H -+ +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -7,16 +7,22 @@ + #ifndef STM32MP_COMMON_H + #define STM32MP_COMMON_H + +#include -+#include -+ + #include + + #include + +void __dead2 stm32mp_plat_reset(int cpu); + -+void stm32mp_save_boot_ctx_address(uintptr_t address); -+uintptr_t stm32mp_get_boot_ctx_address(void); -+ -+int stm32mp_is_single_core(void); -+ -+uintptr_t stm32mp_ddrctrl_base(void); -+uintptr_t stm32mp_ddrphyc_base(void); -+uintptr_t stm32mp_pwr_base(void); -+uintptr_t stm32mp_rcc_base(void); + /* Functions to save and get boot context address given by ROM code */ + void stm32mp_save_boot_ctx_address(uintptr_t address); + uintptr_t stm32mp_get_boot_ctx_address(void); + + bool stm32mp_is_single_core(void); + bool stm32mp_is_closed_device(void); ++bool stm32mp_is_auth_supported(void); + ++const char *stm32mp_get_cpu_supply_name(void); + + /* Return the base address of the DDR controller */ + uintptr_t stm32mp_ddrctrl_base(void); +@@ -30,9 +36,22 @@ uintptr_t stm32mp_pwr_base(void); + /* Return the base address of the RCC peripheral */ + uintptr_t stm32mp_rcc_base(void); + ++void stm32_gic_pcpu_init(void); ++void stm32_gic_init(void); +int stm32_gic_enable_spi(int node, const char *name); + -+uint32_t stm32_read_otp_status(uint32_t *otp_value, uint32_t word); -+uint8_t stm32_iwdg_get_instance(uintptr_t base); -+uint32_t stm32_iwdg_get_otp_config(uintptr_t base); + /* Check MMU status to allow spinlock use */ + bool stm32mp_lock_available(void); + ++/* SMP protection on PWR registers access */ ++void stm32mp_pwr_regs_lock(void); ++void stm32mp_pwr_regs_unlock(void); + -+#if defined(IMAGE_BL2) -+uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags); ++int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, ++ uint32_t *otp_len); ++int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val); ++int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val); ++ + /* Get IWDG platform instance ID from peripheral IO memory base address */ + uint32_t stm32_iwdg_get_instance(uintptr_t base); + +@@ -44,6 +63,11 @@ uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst); + uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags); + #endif + ++#if STM32MP_UART_PROGRAMMER ++/* Get the UART address from its instance number */ ++uintptr_t get_uart_address(uint32_t instance_nb); +#endif + -+uintptr_t stm32_get_gpio_bank_base(unsigned int bank); -+int stm32_get_gpio_bank_clock(unsigned int bank); -+uint32_t stm32_get_gpio_bank_offset(unsigned int bank); -+void stm32mp_print_cpuinfo(void); -+void stm32mp_print_boardinfo(void); + /* + * Platform util functions for the GPIO driver + * @bank: Target GPIO bank ID as per DT bindings +@@ -67,14 +91,17 @@ void stm32mp_print_cpuinfo(void); + /* Print board information */ + void stm32mp_print_boardinfo(void); + ++/* Check HW CPU OPP support */ ++bool stm32mp_supports_cpu_opp(uint32_t opp_id); + -+uint64_t s2tick(uint32_t timeout_s); -+uint64_t ms2tick(uint32_t timeout_ms); -+uint64_t us2tick(uint32_t timeout_us); -+uint64_t timeout_start(void); -+bool timeout_elapsed(uint64_t tick_start, uint64_t tick_to); + /* + * Util for clock gating and to get clock rate for stm32 and platform drivers + * @id: Target clock ID, ID used in clock DT bindings + */ + bool stm32mp_clk_is_enabled(unsigned long id); ++unsigned long stm32mp_clk_get_rate(unsigned long id); + void stm32mp_clk_enable(unsigned long id); + void stm32mp_clk_disable(unsigned long id); +-unsigned long stm32mp_clk_get_rate(unsigned long id); + + /* Initialise the IO layer and register platform IO devices */ + void stm32mp_io_setup(void); +@@ -87,4 +114,10 @@ void stm32mp_io_setup(void); + */ + int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer); + ++#if TRUSTED_BOARD_BOOT ++void stm32mp_save_loaded_header(void *header); ++void stm32mp_delete_loaded_header(void); ++boot_api_image_header_t *stm32mp_get_loaded_header(void); ++#endif + -+void stm32mp_io_setup(void); -+ -+#endif /* STM32MP1_COMMON_H */ + #endif /* STM32MP_COMMON_H */ diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h -new file mode 100644 -index 0000000..ee313d5 ---- /dev/null +index 74b01b3aa..873bed551 100644 +--- a/plat/st/common/include/stm32mp_dt.h +++ b/plat/st/common/include/stm32mp_dt.h -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_DT_H -+#define STM32MP_DT_H -+ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -9,6 +9,8 @@ + + #include + +#include -+#include + -+#define DT_DISABLED U(0) -+#define DT_NON_SECURE U(1) -+#define DT_SECURE U(2) -+#define DT_SHARED (DT_NON_SECURE | DT_SECURE) -+ -+struct dt_node_info { -+ uint32_t base; -+ int32_t clock; -+ int32_t reset; -+ uint8_t status; -+}; -+ -+/******************************************************************************* -+ * Function and variable prototypes -+ ******************************************************************************/ -+int dt_open_and_check(void); -+int fdt_get_address(void **fdt_addr); -+bool fdt_check_node(int node); -+uint8_t fdt_get_status(int node); + #define DT_DISABLED U(0) + #define DT_NON_SECURE U(1) + #define DT_SECURE U(2) +@@ -28,20 +30,28 @@ int dt_open_and_check(void); + int fdt_get_address(void **fdt_addr); + bool fdt_check_node(int node); + uint8_t fdt_get_status(int node); +int fdt_get_interrupt(int node, const fdt32_t **array, int *len, + bool *extended); -+uint32_t fdt_read_uint32_default(int node, const char *prop_name, -+ uint32_t dflt_value); -+int fdt_read_uint32_array(int node, const char *prop_name, -+ uint32_t *array, uint32_t count); + uint32_t fdt_read_uint32_default(int node, const char *prop_name, + uint32_t dflt_value); + int fdt_read_uint32_array(int node, const char *prop_name, + uint32_t *array, uint32_t count); +int fdt_get_reg_props_by_name(int node, const char *name, uintptr_t *base, + size_t *size); -+int dt_set_stdout_pinctrl(void); -+void dt_fill_device_info(struct dt_node_info *info, int node); -+int dt_get_node(struct dt_node_info *info, int offset, const char *compat); -+int dt_get_stdout_uart_info(struct dt_node_info *info); -+uint32_t dt_get_ddr_size(void); -+uintptr_t dt_get_ddrctrl_base(void); -+uintptr_t dt_get_ddrphyc_base(void); -+uintptr_t dt_get_pwr_base(void); -+uint32_t dt_get_pwr_vdd_voltage(void); -+uintptr_t dt_get_syscfg_base(void); -+const char *dt_get_board_model(void); + int dt_set_stdout_pinctrl(void); + void dt_fill_device_info(struct dt_node_info *info, int node); + int dt_get_node(struct dt_node_info *info, int offset, const char *compat); + int dt_get_stdout_uart_info(struct dt_node_info *info); ++int dt_get_node_by_compatible(const char *compatible); ++int dt_match_instance_by_compatible(const char *compatible, uintptr_t address); + uint32_t dt_get_ddr_size(void); +-uintptr_t dt_get_ddrctrl_base(void); +-uintptr_t dt_get_ddrphyc_base(void); +-uintptr_t dt_get_pwr_base(void); ++int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv); ++int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array, ++ uint32_t *voltage_mv_array); + uint32_t dt_get_pwr_vdd_voltage(void); +-uintptr_t dt_get_syscfg_base(void); ++const char *dt_get_cpu_regulator_name(void); + const char *dt_get_board_model(void); +int fdt_get_gpio_bank_pinctrl_node(unsigned int bank); +int fdt_get_gpioz_nbpins_from_dt(void); -+ -+#endif /* STM32MP_DT_H */ + + #endif /* STM32MP_DT_H */ diff --git a/plat/st/common/include/stm32mp_shres_helpers.h b/plat/st/common/include/stm32mp_shres_helpers.h -new file mode 100644 -index 0000000..565b3d4 ---- /dev/null +index 8b786cc04..8b048284c 100644 +--- a/plat/st/common/include/stm32mp_shres_helpers.h +++ b/plat/st/common/include/stm32mp_shres_helpers.h -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_SHRES_HELPERS_H -+#define STM32MP_SHRES_HELPERS_H -+ -+#include -+#include -+ -+/* +@@ -12,63 +12,16 @@ + #include + + /* +- * Shared reference counter: increments by 2 on secure increment +- * request, decrements by 2 on secure decrement request. Bit #0 +- * is set to 1 on non-secure increment request and reset to 0 on +- * non-secure decrement request. The counter initializes to +- * either 0, 1 or 2 upon their expect default state. +- * Counters saturates once above UINT_MAX / 2. + * Lock/unlock access to shared registers + * + * @lock - NULL or pointer to spin lock -+ */ -+ + */ +-#define SHREFCNT_NONSECURE_FLAG 0x1UL +-#define SHREFCNT_SECURE_STEP 0x2UL +-#define SHREFCNT_MAX (UINT32_MAX / 2) +- +-/* Return 1 if refcnt increments from 0, else return 0 */ +-static inline int stm32mp_incr_shrefcnt(unsigned int *refcnt, bool secure) +-{ +- int rc = !*refcnt; +- +- if (secure) { +- *refcnt += SHREFCNT_SECURE_STEP; +- if (*refcnt >= SHREFCNT_MAX) { +- panic(); +- } +- } else { +- *refcnt |= SHREFCNT_NONSECURE_FLAG; +- } +- +- return rc; +-} +- +-/* Return 1 if refcnt decrements to 0, else return 0 */ +-static inline int stm32mp_decr_shrefcnt(unsigned int *refcnt, bool secure) +-{ +- int rc = 0; +- +- if (secure) { +- if (*refcnt < SHREFCNT_MAX) { +- if (*refcnt < SHREFCNT_SECURE_STEP) { +- panic(); +- } +- *refcnt -= SHREFCNT_SECURE_STEP; +- rc = !*refcnt; +- } +- } else { +- rc = (*refcnt == SHREFCNT_NONSECURE_FLAG) ? 1 : 0; +- *refcnt &= ~SHREFCNT_NONSECURE_FLAG; +- } +- +- return rc; +-} +- +-static inline int stm32mp_incr_refcnt(unsigned int *refcnt) +-{ +- return stm32mp_incr_shrefcnt(refcnt, true); +-} + +-static inline int stm32mp_decr_refcnt(unsigned int *refcnt) +-{ +- return stm32mp_decr_shrefcnt(refcnt, true); +-} +void stm32mp_lock_shregs(void); +void stm32mp_unlock_shregs(void); +void stm32mp_mmio_clrsetbits_32_shregs(uintptr_t addr, uint32_t clear, + uint32_t set); +void stm32mp_mmio_clrbits_32_shregs(uintptr_t addr, uint32_t clear); +void stm32mp_mmio_setbits_32_shregs(uintptr_t addr, uint32_t set); -+ -+/* -+ * Shared reference counter: increments by 2 on secure increment -+ * request, decrements by 2 on secure decrement request. Bit #0 -+ * is set to 1 on non-secure increment request and reset to 0 on -+ * non-secure decrement request. The counter initializes to -+ * either 0, 1 or 2 upon their expect default state. -+ * Counters saturates once above UINT_MAX / 2. -+ */ -+#define SHREFCNT_NONSECURE_FLAG 0x1UL -+#define SHREFCNT_SECURE_STEP 0x2UL -+#define SHREFCNT_MAX (UINT32_MAX / 2) -+ -+/* Return 1 if refcnt increments from 0, else return 0 */ -+static inline int stm32mp_incr_shrefcnt(unsigned int *refcnt, bool secure) -+{ -+ int rc = !*refcnt; -+ -+ if (secure) { -+ *refcnt += SHREFCNT_SECURE_STEP; -+ if (*refcnt >= SHREFCNT_MAX) { -+ panic(); -+ } -+ } else { -+ *refcnt |= SHREFCNT_NONSECURE_FLAG; -+ } -+ -+ return rc; -+} -+ -+/* Return 1 if refcnt decrements to 0, else return 0 */ -+static inline int stm32mp_decr_shrefcnt(unsigned int *refcnt, bool secure) -+{ -+ int rc = 0; -+ -+ if (secure) { -+ if (*refcnt < SHREFCNT_MAX) { -+ if (*refcnt < SHREFCNT_SECURE_STEP) { -+ panic(); -+ } -+ *refcnt -= SHREFCNT_SECURE_STEP; -+ rc = !*refcnt; -+ } -+ } else { -+ rc = (*refcnt == SHREFCNT_NONSECURE_FLAG); -+ *refcnt &= ~SHREFCNT_NONSECURE_FLAG; -+ } -+ -+ return rc; -+} -+ -+static inline int stm32mp_incr_refcnt(unsigned int *refcnt) -+{ -+ return stm32mp_incr_shrefcnt(refcnt, true); -+} -+ -+static inline int stm32mp_decr_refcnt(unsigned int *refcnt) -+{ -+ return stm32mp_decr_shrefcnt(refcnt, true); -+} -+ -+#endif /* STM32MP_SHRES_HELPERS_H */ -diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c + + #endif /* STM32MP_SHRES_HELPERS_H */ +diff --git a/plat/st/common/stm32_gic.c b/plat/st/common/stm32_gic.c new file mode 100644 -index 0000000..773c95e +index 000000000..ec3e3525c --- /dev/null -+++ b/plat/st/common/stm32mp_auth.c -@@ -0,0 +1,121 @@ ++++ b/plat/st/common/stm32_gic.c +@@ -0,0 +1,223 @@ +/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int check_header(boot_api_image_header_t *header, uintptr_t buffer) -+{ -+ uint32_t i; -+ uint32_t img_checksum = 0; -+ -+ /* -+ * Check header/payload validity: -+ * - Header magic -+ * - Header version -+ * - Payload checksum -+ */ -+ if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { -+ ERROR("Header magic is not correct\n"); -+ return -EINVAL; -+ } -+ -+ if (header->header_version != BOOT_API_HEADER_VERSION) { -+ ERROR("Header version is not correct\n"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < header->image_length; i++) { -+ img_checksum += *(uint8_t *)(buffer + i); -+ } -+ -+ if (header->payload_checksum != img_checksum) { -+ ERROR("Payload checksum is not correct:\n"); -+ ERROR(" Computed: 0x%x (awaited: 0x%x)\n", img_checksum, -+ header->payload_checksum); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+int check_authentication(boot_api_image_header_t *header, uintptr_t buffer) -+{ -+ uint32_t sec_closed, uret; -+ HASH_HandleTypeDef hhash; -+ uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; -+ 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) { -+ ERROR("Error reading OTP configuration\n"); -+ return -EINVAL; -+ } -+ -+ /* Check Security Status */ -+ if ((sec_closed & BIT(BOOT_API_OTP_MODE_CLOSED_BIT_POS)) == 0U) { -+ if (header->option_flags != 0U) { -+ WARN("Skip signature check (header option)\n"); -+ return 0; -+ } -+ INFO("Check signature on Non-Full-Secured platform\n"); -+ } -+ -+ /* Check Public Key */ -+ if (boot_context->p_bootrom_ext_service_ecdsa_check_key -+ (header->ecc_pubk, NULL) != STD_OK) { -+ return -EINVAL; -+ } -+ -+ /* Compute end of header hash and payload hash */ -+ uret = HASH_SHA256_Init(&hhash); -+ if (uret != STD_OK) { -+ ERROR("Hash init failed\n"); -+ return -EBUSY; -+ } -+ -+ uret = HASH_SHA256_Accumulate(&hhash, -+ (uint8_t *)&header->header_version, -+ sizeof(boot_api_image_header_t) - -+ header_skip_cksum); -+ if (uret != STD_OK) { -+ ERROR("Hash of header failed\n"); -+ return -EINVAL; -+ } -+ -+ uret = HASH_SHA256_Start(&hhash, (uint8_t *)buffer, -+ header->image_length, image_hash, -+ HASH_TIMEOUT_VALUE); -+ if (uret != STD_OK) { -+ ERROR("Hash of payload failed\n"); -+ return -EINVAL; -+ } -+ -+ uret = HASH_SHA256_Finish(&hhash, image_hash, HASH_TIMEOUT_VALUE); -+ if (uret != STD_OK) { -+ ERROR("Hash of payload failed\n"); -+ return -EINVAL; -+ } -+ -+ /* Verify signature */ -+ if (boot_context->p_bootrom_ext_service_ecdsa_verify_signature -+ (image_hash, header->ecc_pubk, header->image_signature, -+ header->ecc_algo_type) != STD_OK) { -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c -new file mode 100644 -index 0000000..8efac68 ---- /dev/null -+++ b/plat/st/common/stm32mp_common.c -@@ -0,0 +1,168 @@ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include +#include -+#include -+#include -+#include -+#include ++ ++#include ++ +#include -+#include -+#include -+#include + -+uintptr_t plat_get_ns_image_entrypoint(void) ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct stm32_gic_instance { ++ uint32_t cells; ++ uint32_t phandle_node; ++}; ++ ++/****************************************************************************** ++ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 ++ * interrupts. ++ *****************************************************************************/ ++static const interrupt_prop_t stm32_interrupt_props[] = { ++ PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), ++ PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) ++}; ++ ++/* Fix target_mask_array as secondary core is not able to initialize it */ ++static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2}; ++ ++static gicv2_driver_data_t platform_gic_data = { ++ .interrupt_props = stm32_interrupt_props, ++ .interrupt_props_num = ARRAY_SIZE(stm32_interrupt_props), ++ .target_masks = target_mask_array, ++ .target_masks_num = ARRAY_SIZE(target_mask_array), ++}; ++ ++static struct stm32_gic_instance stm32_gic; ++ ++static uint32_t enable_gic_interrupt(const fdt32_t *array) +{ -+ return BL33_BASE; ++ unsigned int id, cfg; ++ ++ switch (fdt32_to_cpu(*array)) { ++ case GIC_SPI: ++ id = MIN_SPI_ID; ++ break; ++ ++ case GIC_PPI: ++ id = MIN_PPI_ID; ++ break; ++ ++ default: ++ id = MIN_SGI_ID; ++ break; ++ } ++ ++ id += fdt32_to_cpu(*(array + 1)); ++ cfg = (fdt32_to_cpu(*(array + 2)) < IRQ_TYPE_LEVEL_HIGH) ? ++ GIC_INTR_CFG_EDGE : GIC_INTR_CFG_LEVEL; ++ ++ if ((id >= MIN_SPI_ID) && (id <= MAX_SPI_ID)) { ++ VERBOSE("Enable IT %i\n", id); ++ gicv2_set_interrupt_type(id, GICV2_INTR_GROUP0); ++ gicv2_set_interrupt_priority(id, STM32MP_IRQ_SEC_SPI_PRIO); ++ gicv2_set_spi_routing(id, STM32MP_PRIMARY_CPU); ++ gicv2_interrupt_set_cfg(id, cfg); ++ gicv2_enable_interrupt(id); ++ } ++ ++ return id; +} + -+unsigned int plat_get_syscnt_freq2(void) ++static void find_next_interrupt(const fdt32_t **array) +{ -+ return read_cntfrq_el0(); ++ int node; ++ const fdt32_t *cuint; ++ void *fdt; ++ ++ assert(fdt32_to_cpu(**array) != stm32_gic.phandle_node); ++ ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); ++ } ++ ++ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(**array)); ++ if (node < 0) { ++ panic(); ++ } ++ ++ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); ++ if (cuint == NULL) { ++ panic(); ++ } ++ ++ *array += fdt32_to_cpu(*cuint) + 1; +} + ++void stm32_gic_init(void) ++{ ++ int node; ++ void *fdt; ++ const fdt32_t *cuint; ++ struct dt_node_info dt_gic; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); ++ } ++ ++ node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic"); ++ if (node < 0) { ++ panic(); ++ } ++ ++ platform_gic_data.gicd_base = dt_gic.base; ++ ++ cuint = fdt_getprop(fdt, node, "reg", NULL); ++ if (cuint == NULL) { ++ panic(); ++ } ++ ++ platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2)); ++ ++ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); ++ if (cuint == NULL) { ++ panic(); ++ } ++ ++ stm32_gic.cells = fdt32_to_cpu(*cuint); ++ ++ stm32_gic.phandle_node = fdt_get_phandle(fdt, node); ++ if (stm32_gic.phandle_node == 0U) { ++ panic(); ++ } ++ ++ gicv2_driver_init(&platform_gic_data); ++ gicv2_distif_init(); ++ ++ stm32_gic_pcpu_init(); ++} ++ ++void stm32_gic_pcpu_init(void) ++{ ++ gicv2_pcpu_distif_init(); ++ gicv2_set_pe_target_mask(plat_my_core_pos()); ++ gicv2_cpuif_enable(); ++} ++ ++int stm32_gic_enable_spi(int node, const char *name) ++{ ++ const fdt32_t *cuint; ++ void *fdt; ++ int res, len; ++ int index = -1; ++ int i = 0; ++ int id = -1; ++ bool extended; ++ const fdt32_t *t_array, *max; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); ++ } ++ ++ cuint = fdt_getprop(fdt, node, "interrupt-parent", NULL); ++ if (cuint != NULL) { ++ if (stm32_gic.phandle_node != fdt32_to_cpu(*cuint)) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ } ++ ++ if (name != NULL) { ++ switch (fdt_get_status(node)) { ++ case DT_SECURE: ++ index = fdt_stringlist_search(fdt, node, ++ "interrupt-names", name); ++ break; ++ default: ++ index = fdt_stringlist_search(fdt, node, ++ "secure-interrupt-names", ++ name); ++ break; ++ } ++ ++ if (index < 0) { ++ return index; ++ } ++ } ++ ++ res = fdt_get_interrupt(node, &t_array, &len, &extended); ++ if (res < 0) { ++ return res; ++ } ++ ++ max = t_array + (len / sizeof(uint32_t)); ++ ++ while ((t_array < max) && ((i <= index) || (index == -1))) { ++ if (!extended) { ++ if ((index == -1) || (i == index)) { ++ id = enable_gic_interrupt(t_array); ++ } ++ t_array += stm32_gic.cells; ++ } else { ++ if (fdt32_to_cpu(*t_array) == stm32_gic.phandle_node) { ++ t_array++; ++ if ((index == -1) || (i == index)) { ++ id = enable_gic_interrupt(t_array); ++ } ++ t_array += stm32_gic.cells; ++ } else { ++ find_next_interrupt(&t_array); ++ } ++ } ++ i++; ++ } ++ ++ return id; ++} +diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c +deleted file mode 100644 +index 0ef6d5454..000000000 +--- a/plat/st/common/stm32mp_auth.c ++++ /dev/null +@@ -1,90 +0,0 @@ +-/* +- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ +- +-#include +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-static const struct stm32mp_auth_ops *auth_ops; +- +-void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr) +-{ +- if ((init_ptr == NULL) || +- (init_ptr->check_key == NULL) || +- (init_ptr->verify_signature == NULL) || +- (stm32_hash_register() != 0)) { +- panic(); +- } +- +- auth_ops = init_ptr; +-} +- +-int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer) +-{ +- int ret; +- uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; +- uint32_t header_skip_cksum = sizeof(header->magic) + +- sizeof(header->image_signature) + +- sizeof(header->payload_checksum); +- +- /* Check Security Status */ +- if (!stm32mp_is_closed_device()) { +- if (header->option_flags != 0U) { +- WARN("Skip signature check (header option)\n"); +- return 0; +- } +- INFO("Check signature on Open device\n"); +- } +- +- ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE, +- STM32MP_ROM_SIZE, MT_CODE | MT_SECURE); +- if (ret != 0) { +- return ret; +- } +- +- /* Check Public Key */ +- if (auth_ops->check_key(header->ecc_pubk, NULL) != BOOT_API_RETURN_OK) { +- ret = -EINVAL; +- goto err; +- } +- +- /* Compute end of header hash and payload hash */ +- stm32_hash_init(HASH_SHA256); +- +- ret = stm32_hash_update((uint8_t *)&header->header_version, +- sizeof(boot_api_image_header_t) - +- header_skip_cksum); +- if (ret != 0) { +- ERROR("Hash of header failed, %i\n", ret); +- goto err; +- } +- +- ret = stm32_hash_final_update((uint8_t *)buffer, +- header->image_length, image_hash); +- if (ret != 0) { +- ERROR("Hash of payload failed\n"); +- goto err; +- } +- +- /* Verify signature */ +- if (auth_ops->verify_signature(image_hash, header->ecc_pubk, +- header->image_signature, +- header->ecc_algo_type) != +- BOOT_API_RETURN_OK) { +- ret = -EINVAL; +- } +- +-err: +- mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE); +- return ret; +-} +diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c +index afa87f487..e838995cc 100644 +--- a/plat/st/common/stm32mp_common.c ++++ b/plat/st/common/stm32mp_common.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -12,8 +12,15 @@ + #include + #include + #include ++#include ++#include ++#include + #include + ++#define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16) ++ ++static struct spinlock lock; ++ + uintptr_t plat_get_ns_image_entrypoint(void) + { + return BL33_BASE; +@@ -24,6 +31,12 @@ unsigned int plat_get_syscnt_freq2(void) + return read_cntfrq_el0(); + } + +#pragma weak stm32mp_plat_reset +void __dead2 stm32mp_plat_reset(int cpu) +{ + panic(); +} + -+/* Functions to save and get boot context address given by ROM code */ -+static uintptr_t boot_ctx_address; -+ -+void stm32mp_save_boot_ctx_address(uintptr_t address) + static uintptr_t boot_ctx_address; + + void stm32mp_save_boot_ctx_address(uintptr_t address) +@@ -38,54 +51,22 @@ uintptr_t stm32mp_get_boot_ctx_address(void) + + uintptr_t stm32mp_ddrctrl_base(void) + { +- static uintptr_t ddrctrl_base; +- +- if (ddrctrl_base == 0) { +- ddrctrl_base = dt_get_ddrctrl_base(); +- +- assert(ddrctrl_base == DDRCTRL_BASE); +- } +- +- return ddrctrl_base; ++ return DDRCTRL_BASE; + } + + uintptr_t stm32mp_ddrphyc_base(void) + { +- static uintptr_t ddrphyc_base; +- +- if (ddrphyc_base == 0) { +- ddrphyc_base = dt_get_ddrphyc_base(); +- +- assert(ddrphyc_base == DDRPHYC_BASE); +- } +- +- return ddrphyc_base; ++ return DDRPHYC_BASE; + } + + uintptr_t stm32mp_pwr_base(void) + { +- static uintptr_t pwr_base; +- +- if (pwr_base == 0) { +- pwr_base = dt_get_pwr_base(); +- +- assert(pwr_base == PWR_BASE); +- } +- +- return pwr_base; ++ return PWR_BASE; + } + + uintptr_t stm32mp_rcc_base(void) + { +- static uintptr_t rcc_base; +- +- if (rcc_base == 0) { +- rcc_base = fdt_rcc_read_addr(); +- +- assert(rcc_base == RCC_BASE); +- } +- +- return rcc_base; ++ return RCC_BASE; + } + + bool stm32mp_lock_available(void) +@@ -96,6 +77,20 @@ bool stm32mp_lock_available(void) + return (read_sctlr() & c_m_bits) == c_m_bits; + } + ++void stm32mp_pwr_regs_lock(void) +{ -+ boot_ctx_address = address; -+} -+ -+uintptr_t stm32mp_get_boot_ctx_address(void) -+{ -+ return boot_ctx_address; -+} -+ -+/* -+ * This function determines if one single core is presently running. This is -+ * done by OTP read. -+ * Returns 1 if yes, 0 if more that one core is running, -1 if error. -+ */ -+#pragma weak stm32mp_is_single_core -+ -+int stm32mp_is_single_core(void) -+{ -+ return 0; -+} -+ -+uintptr_t stm32mp_ddrctrl_base(void) -+{ -+ static uintptr_t ddrctrl_base; -+ -+ if (ddrctrl_base == 0) { -+ ddrctrl_base = dt_get_ddrctrl_base(); -+ -+ assert(ddrctrl_base == DDRCTRL_BASE); -+ } -+ -+ return ddrctrl_base; -+} -+ -+uintptr_t stm32mp_ddrphyc_base(void) -+{ -+ static uintptr_t ddrphyc_base; -+ -+ if (ddrphyc_base == 0) { -+ ddrphyc_base = dt_get_ddrphyc_base(); -+ -+ assert(ddrphyc_base == DDRPHYC_BASE); -+ } -+ -+ return ddrphyc_base; -+} -+ -+uintptr_t stm32mp_pwr_base(void) -+{ -+ static uintptr_t pwr_base; -+ -+ if (pwr_base == 0) { -+ pwr_base = dt_get_pwr_base(); -+ -+ assert(pwr_base == PWR_BASE); -+ } -+ -+ return pwr_base; -+} -+ -+uintptr_t stm32mp_rcc_base(void) -+{ -+ static uintptr_t rcc_base; -+ -+ if (rcc_base == 0) { -+ rcc_base = fdt_rcc_read_addr(); -+ -+ assert(rcc_base == RCC_BASE); -+ } -+ -+ return rcc_base; -+} -+ -+uintptr_t stm32_get_gpio_bank_base(unsigned int bank) -+{ -+ switch (bank) { -+ case GPIO_BANK_A ... GPIO_BANK_K: -+ return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); -+ case GPIO_BANK_Z: -+ return GPIOZ_BASE; -+ default: -+ panic(); ++ if (stm32mp_lock_available()) { ++ spin_lock(&lock); + } +} + -+/* Return clock ID on success, negative value on error */ -+int stm32_get_gpio_bank_clock(unsigned int bank) ++void stm32mp_pwr_regs_unlock(void) +{ -+ switch (bank) { -+ case GPIO_BANK_A ... GPIO_BANK_K: -+ return (int)GPIOA + (bank - GPIO_BANK_A); -+ case GPIO_BANK_Z: -+ return (int)GPIOZ; -+ default: -+ panic(); ++ if (stm32mp_lock_available()) { ++ spin_unlock(&lock); + } +} + -+uint32_t stm32_get_gpio_bank_offset(unsigned int bank) + uintptr_t stm32_get_gpio_bank_base(unsigned int bank) + { + if (bank == GPIO_BANK_Z) { +@@ -120,34 +115,89 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank) + + int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) + { +- uint32_t i; +- uint32_t img_checksum = 0U; +- + /* + * Check header/payload validity: + * - Header magic + * - Header version +- * - Payload checksum ++ * - Payload checksum if no signature verification + */ + if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { + ERROR("Header magic\n"); + return -EINVAL; + } + +- if (header->header_version != BOOT_API_HEADER_VERSION) { ++ if ((header->header_version & HEADER_VERSION_MAJOR_MASK) != ++ (BOOT_API_HEADER_VERSION & HEADER_VERSION_MAJOR_MASK)) { + ERROR("Header version\n"); + return -EINVAL; + } + +- for (i = 0U; i < header->image_length; i++) { +- img_checksum += *(uint8_t *)(buffer + i); +- } ++ if (header->option_flags == 1U) { ++ uint32_t i; ++ uint32_t img_checksum = 0U; + +- if (header->payload_checksum != img_checksum) { +- ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum, +- header->payload_checksum); +- return -EINVAL; ++ for (i = 0U; i < header->image_length; i++) { ++ img_checksum += *(uint8_t *)(buffer + i); ++ } ++ ++ if (header->payload_checksum != img_checksum) { ++ ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum, ++ header->payload_checksum); ++ return -EINVAL; ++ } + } + + return 0; + } ++ ++/* Return CPU supply name */ ++const char *stm32mp_get_cpu_supply_name(void) +{ -+ if (bank == GPIO_BANK_Z) { -+ return 0; -+ } else { -+ return bank * GPIO_BANK_OFFSET; ++ const char *regulator; ++ const char *supply = NULL; ++ ++ regulator = dt_get_cpu_regulator_name(); ++ if (regulator == NULL) { ++ return NULL; + } ++ ++ if (dt_pmic_status() > 0) { ++ if (dt_pmic_find_supply(&supply, regulator) != 0) { ++ return NULL; ++ } ++ } ++ ++ return supply; +} + -+uint64_t s2tick(uint32_t timeout_s) ++#if TRUSTED_BOARD_BOOT ++/* Save pointer to last loaded header */ ++static boot_api_image_header_t *latest_stm32_header; ++ ++/* Save last loaded header */ ++void stm32mp_save_loaded_header(void *header) +{ -+ return (uint64_t)timeout_s * read_cntfrq_el0(); ++ assert(latest_stm32_header == NULL); ++ ++ latest_stm32_header = header; +} + -+uint64_t ms2tick(uint32_t timeout_ms) ++/* Discard last loaded header */ ++void stm32mp_delete_loaded_header(void) +{ -+ return s2tick(timeout_ms) / 1000U; ++ if (latest_stm32_header == NULL) { ++ return; ++ } ++ ++ zeromem(latest_stm32_header, sizeof(boot_api_image_header_t)); ++ latest_stm32_header = NULL; +} + -+uint64_t us2tick(uint32_t timeout_us) ++/* Get last loaded header */ ++boot_api_image_header_t *stm32mp_get_loaded_header(void) +{ -+ return s2tick(timeout_us) / (1000U * 1000U); -+} ++ assert(latest_stm32_header != NULL); + -+uint64_t timeout_start(void) -+{ -+ return read_cntpct_el0(); ++ return latest_stm32_header; +} -+ -+bool timeout_elapsed(uint64_t tick_start, uint64_t tick_to) -+{ -+ return (tick_to != 0U) && ((read_cntpct_el0() - tick_start) > tick_to); -+} -diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c ++#endif /* TRUSTED_BOARD_BOOT */ +diff --git a/plat/st/common/stm32mp_cot.c b/plat/st/common/stm32mp_cot.c new file mode 100644 -index 0000000..48529cb +index 000000000..5f673fde7 --- /dev/null -+++ b/plat/st/common/stm32mp_dt.c -@@ -0,0 +1,559 @@ ++++ b/plat/st/common/stm32mp_cot.c +@@ -0,0 +1,114 @@ +/* -+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++#include ++ ++static auth_param_type_desc_t stm32_header_pk = ++ AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, 0); ++static auth_param_type_desc_t stm32_header_sig = ++ AUTH_PARAM_TYPE_DESC(AUTH_PARAM_SIG, 0); ++static auth_param_type_desc_t stm32_header_sig_alg = ++ AUTH_PARAM_TYPE_DESC(AUTH_PARAM_SIG_ALG, 0); ++static auth_param_type_desc_t stm32_load = ++ AUTH_PARAM_TYPE_DESC(AUTH_PARAM_RAW_DATA, 0); ++ ++#if defined(AARCH32_SP_OPTEE) ++static const auth_img_desc_t bl32_image = { ++ .img_id = BL32_IMAGE_ID, ++ .img_type = IMG_PLAT, ++ .parent = NULL, ++ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { ++ [0] = { ++ .type = AUTH_METHOD_SIG, ++ .param.sig = { ++ .pk = &stm32_header_pk, ++ .sig = &stm32_header_sig, ++ .alg = &stm32_header_sig_alg, ++ .data = &stm32_load ++ } ++ }, ++ }, ++}; ++ ++static const auth_img_desc_t bl32_extra1_image = { ++ .img_id = BL32_EXTRA1_IMAGE_ID, ++ .img_type = IMG_PLAT, ++ .parent = NULL, ++ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { ++ [0] = { ++ .type = AUTH_METHOD_SIG, ++ .param.sig = { ++ .pk = &stm32_header_pk, ++ .sig = &stm32_header_sig, ++ .alg = &stm32_header_sig_alg, ++ .data = &stm32_load ++ } ++ }, ++ }, ++}; ++ ++static const auth_img_desc_t bl32_extra2_image = { ++ .img_id = BL32_EXTRA2_IMAGE_ID, ++ .img_type = IMG_PLAT, ++ .parent = NULL, ++ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { ++ [0] = { ++ .type = AUTH_METHOD_SIG, ++ .param.sig = { ++ .pk = &stm32_header_pk, ++ .sig = &stm32_header_sig, ++ .alg = &stm32_header_sig_alg, ++ .data = &stm32_load ++ } ++ }, ++ }, ++}; ++#else ++static const auth_img_desc_t bl32_image = { ++ .img_id = BL32_IMAGE_ID, ++ .img_type = IMG_RAW, ++ .parent = NULL, ++ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { ++ [0] = { ++ .type = AUTH_METHOD_NONE, /* Already verified by BL1 ++ * as loaded in the same time ++ * as BL2 ++ */ ++ } ++ }, ++}; ++#endif ++ ++static const auth_img_desc_t bl33_image = { ++ .img_id = BL33_IMAGE_ID, ++ .img_type = IMG_PLAT, ++ .parent = NULL, ++ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { ++ [0] = { ++ .type = AUTH_METHOD_SIG, ++ .param.sig = { ++ .pk = &stm32_header_pk, ++ .sig = &stm32_header_sig, ++ .alg = &stm32_header_sig_alg, ++ .data = &stm32_load ++ } ++ }, ++ }, ++}; ++ ++static const auth_img_desc_t * const cot_desc[] = { ++ [BL32_IMAGE_ID] = &bl32_image, ++#if defined(AARCH32_SP_OPTEE) ++ [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, ++ [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, ++#endif ++ [BL33_IMAGE_ID] = &bl33_image, ++}; ++ ++REGISTER_COT(cot_desc); +diff --git a/plat/st/common/stm32mp_crypto_lib.c b/plat/st/common/stm32mp_crypto_lib.c +new file mode 100644 +index 000000000..6e8c6355d +--- /dev/null ++++ b/plat/st/common/stm32mp_crypto_lib.c +@@ -0,0 +1,174 @@ ++/* ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include -+#include -+#include ++#include ++ +#include -+#include -+#include -+#include -+#include + -+static int fdt_checked; ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE; ++struct stm32mp_auth_ops { ++ uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out); ++ uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in, ++ uint8_t *signature, uint32_t ecc_algo); ++}; + -+/******************************************************************************* -+ * This function checks device tree file with its header. -+ * Returns 0 on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int dt_open_and_check(void) ++static struct stm32mp_auth_ops auth_ops; ++ ++static void crypto_lib_init(void) +{ -+ int ret = fdt_check_header(fdt); ++ boot_api_context_t *boot_context = ++ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + -+ if (ret == 0) { -+ fdt_checked = 1; ++ if (!stm32mp_is_auth_supported()) { ++ return; + } + ++ auth_ops.check_key = boot_context->bootrom_ecdsa_check_key; ++ auth_ops.verify_signature = ++ boot_context->bootrom_ecdsa_verify_signature; ++ ++ if (stm32_hash_register() != 0) { ++ panic(); ++ } ++} ++ ++static int crypto_verify_signature(void *data_ptr, unsigned int data_len, ++ void *sig_ptr, unsigned int sig_len, ++ void *sig_alg, unsigned int sig_alg_len, ++ void *pk_ptr, unsigned int pk_len) ++{ ++ uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++ uint32_t option_flags; ++ uint32_t ecc_algo_type; ++ uint32_t header_len; ++ int result; ++ boot_api_image_header_t *header = stm32mp_get_loaded_header(); ++ ++ header_len = sizeof(boot_api_image_header_t) - sizeof(header->magic) - ++ sizeof(header->image_signature) - ++ sizeof(header->payload_checksum); ++ ++ if ((((size_t)sig_alg % __alignof__(uint32_t)) != 0) || ++ (sig_alg_len != sizeof(option_flags) + sizeof(ecc_algo_type))) { ++ return -EINVAL; ++ } ++ ++ option_flags = ((uint32_t *)sig_alg)[0]; ++ ecc_algo_type = ((uint32_t *)sig_alg)[1]; ++ ++ /* Check security status */ ++ if (!stm32mp_is_closed_device()) { ++ if (option_flags != 0U) { ++ WARN("Skip signature check (header option)\n"); ++ stm32mp_delete_loaded_header(); ++ return 0; ++ } ++ INFO("Check signature on Open device\n"); ++ } ++ ++ /* Check key/sign size */ ++ if ((pk_len != BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES) || ++ (sig_len != BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES)) { ++ return -EINVAL; ++ } ++ ++ result = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE, ++ STM32MP_ROM_SIZE, MT_CODE | MT_SECURE); ++ if (result != 0) { ++ return result; ++ } ++ ++ if (!stm32mp_is_closed_device()) { ++ /* ++ * Check public key here in case of non-secure device ++ * It is done in the generic framework in case of close ++ * device. ++ */ ++ if (auth_ops.check_key(pk_ptr, NULL) != BOOT_API_RETURN_OK) { ++ ERROR("ROTPK verification failed\n"); ++ result = -EINVAL; ++ goto out; ++ } else { ++ NOTICE("ROTPK verification forced and checked OK\n"); ++ } ++ } ++ ++ /* Compute hash for the data covered by the signature */ ++ stm32_hash_init(HASH_SHA256); ++ ++ result = stm32_hash_update((void *)&header->header_version, header_len); ++ if (result != 0) { ++ VERBOSE("Hash of header failed, %i\n", result); ++ goto out; ++ } ++ ++ result = stm32_hash_final_update((uint8_t *)data_ptr, ++ data_len, image_hash); ++ if (result != 0) { ++ VERBOSE("Hash of payload failed, %i\n", result); ++ goto out; ++ } ++ ++ /* Verify signature */ ++ if (auth_ops.verify_signature(image_hash, pk_ptr, sig_ptr, ++ ecc_algo_type) != BOOT_API_RETURN_OK) { ++ result = -EAUTH; ++ } ++ ++out: ++ mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE); ++ if (result != 0) { ++ stm32mp_delete_loaded_header(); ++ } ++ ++ return result; ++} ++ ++static int crypto_verify_hash(void *data_ptr, unsigned int data_len, ++ void *digest_info_ptr, ++ unsigned int digest_info_len) ++{ ++ int ret; ++ uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++ ++ if (digest_info_len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) { ++ VERBOSE("%s: unexpected digest_len\n", __func__); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ stm32_hash_init(HASH_SHA256); ++ ret = stm32_hash_final_update(data_ptr, data_len, calc_hash); ++ if (ret != 0) { ++ VERBOSE("%s: hash failed\n", __func__); ++ goto out; ++ } ++ ++ ret = memcmp(calc_hash, digest_info_ptr, digest_info_len); ++ if (ret != 0) { ++ VERBOSE("%s: not expected digest\n", __func__); ++ ret = -EAUTH; ++ } ++ ++out: ++ /* Clean header as no more used */ ++ stm32mp_delete_loaded_header(); ++ + return ret; +} + ++REGISTER_CRYPTO_LIB("stm32_crypto_lib", ++ crypto_lib_init, ++ crypto_verify_signature, ++ crypto_verify_hash); +diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c +index 17da4904a..f6de0b62a 100644 +--- a/plat/st/common/stm32mp_dt.c ++++ b/plat/st/common/stm32mp_dt.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -13,8 +13,6 @@ + + #include + #include +-#include +-#include + + #include + +@@ -92,6 +90,79 @@ uint8_t fdt_get_status(int node) + return status; + } + ++#if ENABLE_ASSERTIONS +/******************************************************************************* -+ * This function gets the address of the DT. -+ * If DT is OK, fdt_addr is filled with DT address. -+ * Returns 1 if success, 0 otherwise. ++ * This function returns the address cells from the node parent. ++ * Returns: ++ * - #address-cells value if success. ++ * - invalid value if error. ++ * - a default value if undefined #address-cells property as per libfdt ++ * implementation. + ******************************************************************************/ -+int fdt_get_address(void **fdt_addr) ++static int fdt_get_node_parent_address_cells(int node) +{ -+ if (fdt_checked == 1) { -+ *fdt_addr = fdt; ++ int parent; ++ ++ parent = fdt_parent_offset(fdt, node); ++ if (parent < 0) { ++ return -FDT_ERR_NOTFOUND; + } + -+ return fdt_checked; ++ return fdt_address_cells(fdt, parent); +} + +/******************************************************************************* -+ * This function check the presence of a node (generic use of fdt library). -+ * Returns true if present, else return false. ++ * This function returns the size cells from the node parent. ++ * Returns: ++ * - #size-cells value if success. ++ * - invalid value if error. ++ * - a default value if undefined #size-cells property as per libfdt ++ * implementation. + ******************************************************************************/ -+bool fdt_check_node(int node) ++static int fdt_get_node_parent_size_cells(int node) +{ -+ int len; -+ const char *cchar; ++ int parent; + -+ cchar = fdt_get_name(fdt, node, &len); -+ -+ return (cchar != NULL) && (len >= 0); -+} -+ -+/******************************************************************************* -+ * This function return global node status (generic use of fdt library). -+ ******************************************************************************/ -+uint8_t fdt_get_status(int node) -+{ -+ uint8_t status = DT_DISABLED; -+ int len; -+ const char *cchar; -+ -+ cchar = fdt_getprop(fdt, node, "status", &len); -+ if ((cchar == NULL) || -+ (strncmp(cchar, "okay", (size_t)len) == 0)) { -+ status |= DT_NON_SECURE; ++ parent = fdt_parent_offset(fdt, node); ++ if (parent < 0) { ++ return -FDT_ERR_NOTFOUND; + } + -+ cchar = fdt_getprop(fdt, node, "secure-status", &len); -+ if (cchar == NULL) { -+ if (status == DT_NON_SECURE) { -+ status |= DT_SECURE; -+ } -+ } else if (strncmp(cchar, "okay", (size_t)len) == 0) { -+ status |= DT_SECURE; -+ } -+ -+ return status; ++ return fdt_size_cells(fdt, parent); +} ++#endif + +/******************************************************************************* + * This function return interrupts from node. @@ -35781,12 +35832,9 @@ index 0000000..48529cb + } + break; + -+ case DT_SHARED: ++ default: + *array = fdt_getprop(fdt, node, "secure-interrupts", len); + break; -+ -+ default: -+ return -FDT_ERR_NOTFOUND; + } + + if (*array == NULL) { @@ -35796,59 +35844,13 @@ index 0000000..48529cb + return 0; +} + -+/******************************************************************************* -+ * This function reads a value of a node property (generic use of fdt -+ * library). -+ * Returns value if success, and a default value if property not found. -+ * Default value is passed as parameter. -+ ******************************************************************************/ -+uint32_t fdt_read_uint32_default(int node, const char *prop_name, -+ uint32_t dflt_value) -+{ -+ const fdt32_t *cuint; -+ int lenp; -+ -+ cuint = fdt_getprop(fdt, node, prop_name, &lenp); -+ if (cuint == NULL) { -+ return dflt_value; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function reads a series of parameters in a node property -+ * (generic use of fdt library). -+ * It reads the values inside the device tree, from property name and node. -+ * The number of parameters is also indicated as entry parameter. -+ * Returns 0 on success and a negative FDT error code on failure. -+ * If success, values are stored at the third parameter address. -+ ******************************************************************************/ -+int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, -+ uint32_t count) -+{ -+ const fdt32_t *cuint; -+ int len; -+ uint32_t i; -+ -+ cuint = fdt_getprop(fdt, node, prop_name, &len); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ if ((uint32_t)len != (count * sizeof(uint32_t))) { -+ return -FDT_ERR_BADLAYOUT; -+ } -+ -+ for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { -+ *array = fdt32_to_cpu(*cuint); -+ array++; -+ cuint++; -+ } -+ -+ return 0; -+} -+ + /******************************************************************************* + * This function reads a value of a node property (generic use of fdt + * library). +@@ -145,6 +216,46 @@ int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, + return 0; + } + +/******************************************************************************* + * This function fills reg node info (base & size) with an index found by + * checking the reg-names node. @@ -35860,6 +35862,9 @@ index 0000000..48529cb + const fdt32_t *cuint; + int index, len; + ++ assert((fdt_get_node_parent_address_cells(node) == 1) && ++ (fdt_get_node_parent_size_cells(node) == 1)); ++ + index = fdt_stringlist_search(fdt, node, "reg-names", name); + if (index < 0) { + return index; @@ -35875,299 +35880,366 @@ index 0000000..48529cb + } + + cuint += index << 1; -+ *base = fdt32_to_cpu(*cuint); ++ if (base != NULL) { ++ *base = fdt32_to_cpu(*cuint); ++ } + cuint++; -+ *size = fdt32_to_cpu(*cuint); ++ if (size != NULL) { ++ *size = fdt32_to_cpu(*cuint); ++ } + + return 0; +} + + /******************************************************************************* + * This function gets the stdout path node. + * It reads the value indicated inside the device tree. +@@ -215,6 +326,8 @@ void dt_fill_device_info(struct dt_node_info *info, int node) + { + const fdt32_t *cuint; + ++ assert(fdt_get_node_parent_address_cells(node) == 1); ++ + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint != NULL) { + info->base = fdt32_to_cpu(*cuint); +@@ -277,6 +390,53 @@ int dt_get_stdout_uart_info(struct dt_node_info *info) + return node; + } + +/******************************************************************************* -+ * This function gets the stdout path node. -+ * It reads the value indicated inside the device tree. -+ * Returns node on success and a negative FDT error code on failure. ++ * This function returns the node offset matching compatible string in the DT. ++ * It is only valid for single instance peripherals (DDR, RCC, PWR, STGEN, ++ * SYSCFG...). ++ * Returns value on success, and error value on failure. + ******************************************************************************/ -+static int dt_get_stdout_node_offset(void) ++int dt_get_node_by_compatible(const char *compatible) +{ -+ int node; -+ const char *cchar; ++ int node = fdt_node_offset_by_compatible(fdt, -1, compatible); + -+ node = fdt_path_offset(fdt, "/secure-chosen"); + if (node < 0) { -+ node = fdt_path_offset(fdt, "/chosen"); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ } -+ -+ cchar = fdt_getprop(fdt, node, "stdout-path", NULL); -+ if (cchar == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ node = -FDT_ERR_NOTFOUND; -+ if (strchr(cchar, (int)':') != NULL) { -+ const char *name; -+ char *str = (char *)cchar; -+ int len = 0; -+ -+ while (strncmp(":", str, 1)) { -+ len++; -+ str++; -+ } -+ -+ name = fdt_get_alias_namelen(fdt, cchar, len); -+ -+ if (name != NULL) { -+ node = fdt_path_offset(fdt, name); -+ } -+ } else { -+ node = fdt_path_offset(fdt, cchar); ++ INFO("Cannot find %s node in DT\n", compatible); + } + + return node; +} + +/******************************************************************************* -+ * This function gets the stdout pin configuration information from the DT. -+ * And then calls the sub-function to treat it and set GPIO registers. ++ * This function returns the node offset matching compatible string in the DT, ++ * and also matching the reg property with the given address. ++ * Returns value on success, and error value on failure. ++ ******************************************************************************/ ++int dt_match_instance_by_compatible(const char *compatible, uintptr_t address) ++{ ++ int node; ++ ++ for (node = fdt_node_offset_by_compatible(fdt, -1, compatible); ++ node != -FDT_ERR_NOTFOUND; ++ node = fdt_node_offset_by_compatible(fdt, node, compatible)) { ++ const fdt32_t *cuint; ++ ++ assert(fdt_get_node_parent_address_cells(node) == 1); ++ ++ cuint = fdt_getprop(fdt, node, "reg", NULL); ++ if (cuint == NULL) { ++ continue; ++ } ++ ++ if ((uintptr_t)fdt32_to_cpu(*cuint) == address) { ++ return node; ++ } ++ } ++ ++ return -FDT_ERR_NOTFOUND; ++} ++ ++ + /******************************************************************************* + * This function gets DDR size information from the DT. + * Returns value in bytes on success, and 0 on failure. +@@ -285,9 +445,8 @@ uint32_t dt_get_ddr_size(void) + { + int node; + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); ++ node = dt_get_node_by_compatible(DT_DDR_COMPAT); + if (node < 0) { +- INFO("%s: Cannot read DDR node in DT\n", __func__); + return 0; + } + +@@ -295,70 +454,168 @@ uint32_t dt_get_ddr_size(void) + } + + /******************************************************************************* +- * This function gets DDRCTRL base address information from the DT. +- * Returns value on success, and 0 on failure. ++ * This function gets OPP table node from the DT. ++ * Returns node offset on success and a negative FDT error code on failure. + ******************************************************************************/ +-uintptr_t dt_get_ddrctrl_base(void) ++static int dt_get_opp_table_node(void) + { +- int node; +- uint32_t array[4]; ++ return dt_get_node_by_compatible(DT_OPP_COMPAT); ++} + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); +- if (node < 0) { +- INFO("%s: Cannot read DDR node in DT\n", __func__); +- return 0; ++/******************************************************************************* ++ * This function gets OPP parameters (frequency in KHz and voltage in mV) from ++ * an OPP table subnode. Platform HW support capabilities are also checked. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ -+int dt_set_stdout_pinctrl(void) ++static int dt_get_opp_freqvolt_from_subnode(int subnode, uint32_t *freq_khz, ++ uint32_t *voltage_mv) +{ -+ int node; ++ const fdt64_t *cuint64; ++ const fdt32_t *cuint32; ++ uint64_t read_freq_64; ++ uint32_t read_voltage_32; + -+ node = dt_get_stdout_node_offset(); -+ if (node < 0) { ++ assert(freq_khz != NULL); ++ assert(voltage_mv != NULL); ++ ++ cuint32 = fdt_getprop(fdt, subnode, "opp-supported-hw", NULL); ++ if (cuint32 != NULL) { ++ if (!stm32mp_supports_cpu_opp(fdt32_to_cpu(*cuint32))) { ++ VERBOSE("Invalid opp-supported-hw 0x%x\n", ++ fdt32_to_cpu(*cuint32)); ++ return -FDT_ERR_BADVALUE; ++ } + } + +- if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { +- return 0; ++ cuint64 = fdt_getprop(fdt, subnode, "opp-hz", NULL); ++ if (cuint64 == NULL) { ++ VERBOSE("Missing opp-hz\n"); + return -FDT_ERR_NOTFOUND; + } + -+ return dt_set_pinctrl_config(node); -+} -+ -+/******************************************************************************* -+ * This function fills the generic information from a given node. -+ ******************************************************************************/ -+void dt_fill_device_info(struct dt_node_info *info, int node) -+{ -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint != NULL) { -+ info->base = fdt32_to_cpu(*cuint); -+ } else { -+ info->base = 0; ++ /* Frequency value expressed in KHz must fit on 32 bits */ ++ read_freq_64 = fdt64_to_cpu(*cuint64) / 1000ULL; ++ if (read_freq_64 > (uint64_t)UINT32_MAX) { ++ VERBOSE("Invalid opp-hz %llu\n", read_freq_64); ++ return -FDT_ERR_BADVALUE; + } + -+ cuint = fdt_getprop(fdt, node, "clocks", NULL); -+ if (cuint != NULL) { -+ cuint++; -+ info->clock = (int)fdt32_to_cpu(*cuint); -+ } else { -+ info->clock = -1; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "resets", NULL); -+ if (cuint != NULL) { -+ cuint++; -+ info->reset = (int)fdt32_to_cpu(*cuint); -+ } else { -+ info->reset = -1; -+ } -+ -+ info->status = fdt_get_status(node); -+} -+ -+/******************************************************************************* -+ * This function retrieve the generic information from DT. -+ * Returns node on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int dt_get_node(struct dt_node_info *info, int offset, const char *compat) -+{ -+ int node; -+ -+ node = fdt_node_offset_by_compatible(fdt, offset, compat); -+ if (node < 0) { ++ cuint32 = fdt_getprop(fdt, subnode, "opp-microvolt", NULL); ++ if (cuint32 == NULL) { ++ VERBOSE("Missing opp-microvolt\n"); + return -FDT_ERR_NOTFOUND; + } + -+ dt_fill_device_info(info, node); ++ /* Millivolt value must fit on 16 bits */ ++ read_voltage_32 = fdt32_to_cpu(*cuint32) / 1000U; ++ if (read_voltage_32 > (uint32_t)UINT16_MAX) { ++ VERBOSE("Invalid opp-microvolt %u\n", read_voltage_32); ++ return -FDT_ERR_BADVALUE; + } + +- return array[0]; ++ *freq_khz = (uint32_t)read_freq_64; + -+ return node; -+} ++ *voltage_mv = read_voltage_32; + -+/******************************************************************************* -+ * This function gets the UART instance info of stdout from the DT. -+ * Returns node on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int dt_get_stdout_uart_info(struct dt_node_info *info) -+{ -+ int node; ++ return 0; + } + + /******************************************************************************* +- * This function gets DDRPHYC base address information from the DT. +- * Returns value on success, and 0 on failure. ++ * This function parses OPP table in DT and finds the parameters for the ++ * highest frequency supported by the HW platform. ++ * If found, the new frequency and voltage values override the original ones. ++ * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +-uintptr_t dt_get_ddrphyc_base(void) ++int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv) + { + int node; +- uint32_t array[4]; ++ int subnode; ++ uint32_t freq = 0U; ++ uint32_t voltage = 0U; + -+ node = dt_get_stdout_node_offset(); -+ if (node < 0) { ++ assert(freq_khz != NULL); ++ assert(voltage_mv != NULL); + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); ++ node = dt_get_opp_table_node(); + if (node < 0) { +- INFO("%s: Cannot read DDR node in DT\n", __func__); +- return 0; ++ return node; + } + +- if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { +- return 0; ++ fdt_for_each_subnode(subnode, fdt, node) { ++ uint32_t read_freq; ++ uint32_t read_voltage; ++ ++ if (dt_get_opp_freqvolt_from_subnode(subnode, &read_freq, ++ &read_voltage) != 0) { ++ continue; ++ } ++ ++ if (read_freq > freq) { ++ freq = read_freq; ++ voltage = read_voltage; ++ } ++ } ++ ++ if ((freq == 0U) || (voltage == 0U)) { ++ return -FDT_ERR_NOTFOUND; + } + +- return array[2]; ++ *freq_khz = freq; ++ *voltage_mv = voltage; ++ ++ return 0; + } + + /******************************************************************************* +- * This function gets PWR base address information from the DT. +- * Returns value on success, and 0 on failure. ++ * This function parses OPP table in DT and finds all parameters supported by ++ * the HW platform. ++ * If found, the corresponding frequency and voltage values are respectively ++ * stored in @*freq_khz_array and @*voltage_mv_array. ++ * Note that @*count has to be set by caller to the effective size allocated ++ * for both tables. Its value is then replaced by the number of filled elements. ++ * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +-uintptr_t dt_get_pwr_base(void) ++int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array, ++ uint32_t *voltage_mv_array) + { + int node; +- const fdt32_t *cuint; ++ int subnode; ++ int idx = 0; ++ ++ assert(count != NULL); ++ assert(freq_khz_array != NULL); ++ assert(voltage_mv_array != NULL); + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); ++ node = dt_get_opp_table_node(); + if (node < 0) { +- INFO("%s: Cannot read PWR node in DT\n", __func__); +- return 0; ++ return node; + } + +- cuint = fdt_getprop(fdt, node, "reg", NULL); +- if (cuint == NULL) { +- return 0; ++ fdt_for_each_subnode(subnode, fdt, node) { ++ uint32_t read_freq; ++ uint32_t read_voltage; ++ ++ if (dt_get_opp_freqvolt_from_subnode(subnode, &read_freq, ++ &read_voltage) != 0) { ++ continue; ++ } ++ ++ if (idx >= *count) { ++ return -FDT_ERR_NOSPACE; ++ } ++ ++ freq_khz_array[idx] = read_freq; ++ voltage_mv_array[idx] = read_voltage; ++ idx++; + } + +- return fdt32_to_cpu(*cuint); ++ if (idx == 0U) { + return -FDT_ERR_NOTFOUND; + } + -+ dt_fill_device_info(info, node); ++ *count = idx; + -+ return node; -+} -+ -+/******************************************************************************* -+ * This function gets DDR size information from the DT. -+ * Returns value in bytes on success, and 0 on failure. -+ ******************************************************************************/ -+uint32_t dt_get_ddr_size(void) -+{ ++ return 0; + } + + /******************************************************************************* +@@ -367,22 +624,15 @@ uintptr_t dt_get_pwr_base(void) + ******************************************************************************/ + uint32_t dt_get_pwr_vdd_voltage(void) + { +- int node, pwr_regulators_node; + int node; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ if (node < 0) { -+ INFO("%s: Cannot read DDR node in DT\n", __func__); -+ return 0; -+ } -+ -+ return fdt_read_uint32_default(node, "st,mem-size", 0); -+} -+ -+/******************************************************************************* -+ * This function gets DDRCTRL base address information from the DT. -+ * Returns value on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t dt_get_ddrctrl_base(void) -+{ -+ int node; -+ uint32_t array[4]; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ if (node < 0) { -+ INFO("%s: Cannot read DDR node in DT\n", __func__); -+ return 0; -+ } -+ -+ if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { -+ return 0; -+ } -+ -+ return array[0]; -+} -+ -+/******************************************************************************* -+ * This function gets DDRPHYC base address information from the DT. -+ * Returns value on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t dt_get_ddrphyc_base(void) -+{ -+ int node; -+ uint32_t array[4]; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ if (node < 0) { -+ INFO("%s: Cannot read DDR node in DT\n", __func__); -+ return 0; -+ } -+ -+ if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { -+ return 0; -+ } -+ -+ return array[2]; -+} -+ -+/******************************************************************************* -+ * This function gets PWR base address information from the DT. -+ * Returns value on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t dt_get_pwr_base(void) -+{ -+ int node; -+ const fdt32_t *cuint; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ if (node < 0) { -+ INFO("%s: Cannot read PWR node in DT\n", __func__); -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function gets PWR VDD regulator voltage information from the DT. -+ * Returns value in microvolts on success, and 0 on failure. -+ ******************************************************************************/ -+uint32_t dt_get_pwr_vdd_voltage(void) -+{ -+ int node; -+ const fdt32_t *cuint; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ if (node < 0) { -+ INFO("%s: Cannot read PWR node in DT\n", __func__); -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "pwr-supply", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ + const fdt32_t *cuint; + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); ++ node = dt_get_node_by_compatible(DT_PWR_COMPAT); + if (node < 0) { +- INFO("%s: Cannot read PWR node in DT\n", __func__); + return 0; + } + +- 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); ++ cuint = fdt_getprop(fdt, node, "vdd-supply", NULL); + if (cuint == NULL) { + return 0; + } +@@ -401,26 +651,30 @@ uint32_t dt_get_pwr_vdd_voltage(void) + } + + /******************************************************************************* +- * This function gets SYSCFG base address information from the DT. +- * Returns value on success, and 0 on failure. ++ * This function retrieves CPU regulator name from DT. ++ * Returns string taken from supply node, NULL otherwise. + ******************************************************************************/ +-uintptr_t dt_get_syscfg_base(void) ++const char *dt_get_cpu_regulator_name(void) + { + int node; + const fdt32_t *cuint; + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT); ++ node = fdt_path_offset(fdt, "/cpus/cpu@0"); + if (node < 0) { +- INFO("%s: Cannot read SYSCFG node in DT\n", __func__); +- return 0; ++ return NULL; + } + +- cuint = fdt_getprop(fdt, node, "reg", NULL); ++ cuint = fdt_getprop(fdt, node, "cpu-supply", NULL); + if (cuint == NULL) { +- return 0; ++ return NULL; + } + +- return fdt32_to_cpu(*cuint); + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function gets SYSCFG base address information from the DT. -+ * Returns value on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t dt_get_syscfg_base(void) -+{ -+ int node; -+ const fdt32_t *cuint; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT); -+ if (node < 0) { -+ INFO("%s: Cannot read SYSCFG node in DT\n", __func__); -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function retrieves board model from DT -+ * Returns string taken from model node, NULL otherwise -+ ******************************************************************************/ -+const char *dt_get_board_model(void) -+{ -+ int node = fdt_path_offset(fdt, "/"); -+ -+ if (node < 0) { + return NULL; + } + -+ return (const char *)fdt_getprop(fdt, node, "model", NULL); -+} ++ return (const char *)fdt_getprop(fdt, node, "regulator-name", NULL); + } + + /******************************************************************************* +@@ -437,3 +691,67 @@ const char *dt_get_board_model(void) + + return (const char *)fdt_getprop(fdt, node, "model", NULL); + } + +/******************************************************************************* + * This function gets GPIO bank PINCTRL node information from the DT. @@ -36232,36 +36304,109 @@ index 0000000..48529cb + + return 0; +} -diff --git a/plat/st/common/stm32mp_shres_helpers.c b/plat/st/common/stm32mp_shres_helpers.c +diff --git a/plat/st/common/stm32mp_img_parser_lib.c b/plat/st/common/stm32mp_img_parser_lib.c new file mode 100644 -index 0000000..b8bc2ec +index 000000000..f4c8bd642 --- /dev/null -+++ b/plat/st/common/stm32mp_shres_helpers.c -@@ -0,0 +1,71 @@ ++++ b/plat/st/common/stm32mp_img_parser_lib.c +@@ -0,0 +1,75 @@ +/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++static void img_lib_init(void) ++{ ++} ++ ++static int img_check_integrity(void *img, unsigned int img_len) ++{ ++ return stm32mp_check_header(stm32mp_get_loaded_header(), ++ (uintptr_t)img); ++} ++ ++static int img_get_auth_param(const auth_param_type_desc_t *type_desc, ++ void *img, unsigned int img_len, void **param, ++ unsigned int *param_len) ++{ ++ boot_api_image_header_t *image_header = stm32mp_get_loaded_header(); ++ ++ switch (type_desc->type) { ++ case AUTH_PARAM_SIG: ++ *param_len = sizeof(image_header->image_signature); ++ *param = &image_header->image_signature; ++ break; ++ case AUTH_PARAM_SIG_ALG: ++ *param_len = sizeof(image_header->option_flags) + ++ sizeof(image_header->ecc_algo_type); ++ *param = &image_header->option_flags; ++ /* ++ * Store option_flags and ecc_alog_type in same param ++ * structure because they both have the same header fields. ++ */ ++ break; ++ case AUTH_PARAM_PUB_KEY: ++ *param_len = sizeof(image_header->ecc_pubk); ++ *param = &image_header->ecc_pubk; ++ break; ++ case AUTH_PARAM_RAW_DATA: ++ if (type_desc->cookie == NULL) { ++ *param_len = image_header->image_length; ++ *param = img; ++ } else { ++ return -EINVAL; ++ } ++ break; ++ case AUTH_PARAM_NV_CTR: ++ if (type_desc->cookie == NULL) { ++ *param_len = sizeof(image_header->image_version); ++ *param = &image_header->image_version; ++ } else { ++ return -EINVAL; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++REGISTER_IMG_PARSER_LIB(IMG_PLAT, "stm32_img_parser_lib", ++ img_lib_init, ++ img_check_integrity, ++ img_get_auth_param); +diff --git a/plat/st/common/stm32mp_shres_helpers.c b/plat/st/common/stm32mp_shres_helpers.c +new file mode 100644 +index 000000000..12633e47d +--- /dev/null ++++ b/plat/st/common/stm32mp_shres_helpers.c +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ +#include -+#include -+#include ++#include ++#include ++ +#include + +static struct spinlock shregs_lock; + -+static int stm32mp_lock_available(void) -+{ -+ /* The spinlocks are used only when MMU is enabled */ -+#ifdef AARCH32 -+ return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT); -+#else -+ return (read_sctlr_el3() & SCTLR_M_BIT) && -+ (read_sctlr_el3() & SCTLR_C_BIT); -+#endif -+} -+ +void stm32mp_lock_shregs(void) +{ + if (stm32mp_lock_available() == 0U) { @@ -36309,474 +36454,390 @@ index 0000000..b8bc2ec + + stm32mp_unlock_shregs(); +} -diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c -deleted file mode 100644 -index 7346c0c..0000000 ---- a/plat/st/stm32mp1/bl2_io_storage.c -+++ /dev/null -@@ -1,193 +0,0 @@ --/* -- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --/* IO devices */ --static const io_dev_connector_t *dummy_dev_con; --static uintptr_t dummy_dev_handle; --static uintptr_t dummy_dev_spec; -- --static const io_block_spec_t bl32_block_spec = { -- .offset = BL32_BASE, -- .length = STM32MP1_BL32_SIZE --}; -- --static const io_block_spec_t bl2_block_spec = { -- .offset = BL2_BASE, -- .length = STM32MP1_BL2_SIZE, --}; -- --static int open_dummy(const uintptr_t spec); -- --struct plat_io_policy { -- uintptr_t *dev_handle; -- uintptr_t image_spec; -- int (*check)(const uintptr_t spec); --}; -- --static const struct plat_io_policy policies[] = { -- [BL2_IMAGE_ID] = { -- .dev_handle = &dummy_dev_handle, -- .image_spec = (uintptr_t)&bl2_block_spec, -- .check = open_dummy -- }, -- [BL32_IMAGE_ID] = { -- .dev_handle = &dummy_dev_handle, -- .image_spec = (uintptr_t)&bl32_block_spec, -- .check = open_dummy -- }, --}; -- --static int open_dummy(const uintptr_t spec) --{ -- return io_dev_init(dummy_dev_handle, 0); --} -- --static void print_boot_device(boot_api_context_t *boot_context) --{ -- switch (boot_context->boot_interface_selected) { -- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: -- INFO("Using SDMMC\n"); -- break; -- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: -- INFO("Using EMMC\n"); -- break; -- default: -- ERROR("Boot interface not found\n"); -- panic(); -- break; -- } -- -- if (boot_context->boot_interface_instance != 0U) { -- INFO(" Instance %d\n", boot_context->boot_interface_instance); -- } --} -- --static void print_reset_reason(void) --{ -- uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); -- -- if (rstsr == 0U) { -- WARN("Reset reason unknown\n"); -- return; -- } -- -- INFO("Reset reason (0x%x):\n", rstsr); -- -- if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { -- if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { -- INFO("System exits from STANDBY\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) { -- INFO("MPU exits from CSTANDBY\n"); -- return; -- } -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) { -- INFO(" Power-on Reset (rst_por)\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) { -- INFO(" Brownout Reset (rst_bor)\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { -- INFO(" System reset generated by MPU (MPSYSRST)\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) { -- INFO(" Reset due to a clock failure on HSE\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) { -- INFO(" IWDG1 Reset (rst_iwdg1)\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) { -- INFO(" IWDG2 Reset (rst_iwdg2)\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { -- INFO(" Pad Reset from NRST\n"); -- return; -- } -- -- if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) { -- INFO(" Reset due to a failure of VDD_CORE\n"); -- return; -- } -- -- ERROR(" Unidentified reset reason\n"); --} -- --void stm32mp1_io_setup(void) --{ -- int io_result __unused; -- boot_api_context_t *boot_context = -- (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); -- -- print_reset_reason(); -- -- 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); --} -- --/* -- * Return an IO device handle and specification which can be used to access -- * an image. Use this to enforce platform load policy. -- */ --int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, -- uintptr_t *image_spec) --{ -- int rc; -- const struct plat_io_policy *policy; -- -- assert(image_id < ARRAY_SIZE(policies)); -- -- policy = &policies[image_id]; -- rc = policy->check(policy->image_spec); -- if (rc == 0) { -- *image_spec = policy->image_spec; -- *dev_handle = *(policy->dev_handle); -- } -- -- return rc; --} +diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c +new file mode 100644 +index 000000000..f47584206 +--- /dev/null ++++ b/plat/st/common/stm32mp_trusted_boot.c +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++static uint32_t root_pk_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES / ++ sizeof(uint32_t)]; ++ ++int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, ++ unsigned int *flags) ++{ ++ uint32_t otp_idx; ++ uint32_t otp_val; ++ uint32_t len; ++ size_t i; ++ ++ if (cookie != NULL) { ++ return -EINVAL; ++ } ++ ++ if (stm32_get_otp_index(PKH_OTP, &otp_idx, &len) != 0) { ++ VERBOSE("get_rot_pk_hash: get index error\n"); ++ return -EINVAL; ++ } ++ if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) { ++ VERBOSE("get_rot_pk_hash: length Error\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0U; i < ARRAY_SIZE(root_pk_hash); i++) { ++ if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) { ++ return -EINVAL; ++ } ++ ++ root_pk_hash[i] = bswap32(otp_val); ++ } ++ ++ *key_ptr = &root_pk_hash; ++ *key_len = BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES; ++ *flags = ROTPK_IS_HASH; ++ ++ if (!stm32mp_is_closed_device()) { ++ *flags |= ROTPK_NOT_DEPLOYED; ++ } ++ ++ return 0; ++} ++ ++int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) ++{ ++ /* ++ * This monotonic counter is the counter used by ROM code ++ * to identify BL2. ++ */ ++ if ((cookie == NULL) && ++ (stm32_get_otp_value(MONOTONIC_OTP, nv_ctr) == 0)) { ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) ++{ ++ return -EINVAL; ++} diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c -index 9f2d8bd..cd5d5b3 100644 +index d9e29b4e8..3f5eb5674 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_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. +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -@@ -8,38 +8,154 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -+#include -+#include - #include - #include -+#include - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - #include --#include --#include --#include - #include -+#include -+#include - #include - #include - #include --#include -+#include - #include - #include +@@ -18,21 +18,47 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#if STM32MP_UART_PROGRAMMER ++#include ++#endif ++#include + #include + #include + #include + #include + ++#include + #include + #include --void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, -- u_register_t arg2, u_register_t arg3) +#define PWRLP_TEMPO_5_HSI 5 + -+static struct console_stm32 console; ++#define TIMEOUT_US_1MS U(1000) ++ ++static const char debug_msg[626] = { ++ "***************************************************\n" ++ "** NOTICE NOTICE NOTICE NOTICE NOTICE **\n" ++ "** **\n" ++ "** DEBUG ACCESS PORT IS OPEN! **\n" ++ "** This boot image is only for debugging purpose **\n" ++ "** and is unsafe for production use. **\n" ++ "** **\n" ++ "** If you see this message and you are not **\n" ++ "** debugging report this immediately to your **\n" ++ "** vendor! **\n" ++ "** **\n" ++ "***************************************************\n" ++}; ++ + static struct console_stm32 console; +-static struct stm32mp_auth_ops stm32mp1_auth_ops; +static enum boot_device_e boot_device = BOOT_DEVICE_BOARD; -+ -+static void print_reset_reason(void) ++static bool wakeup_standby; + + static void print_reset_reason(void) { -- stm32mp1_save_boot_ctx_address(arg0); -+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR); -+ -+ if (rstsr == 0U) { -+ WARN("Reset reason unknown\n"); -+ return; -+ } -+ -+ INFO("Reset reason (0x%x):\n", rstsr); -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { -+ if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { -+ INFO("System exits from STANDBY\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) { -+ INFO("MPU exits from CSTANDBY\n"); -+ return; -+ } -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) { -+ INFO(" Power-on Reset (rst_por)\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) { -+ INFO(" Brownout Reset (rst_bor)\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) { -+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) -+ INFO(" System reset generated by MCU (MCSYSRST)\n"); -+ else -+ INFO(" Local reset generated by MCU (MCSYSRST)\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { -+ INFO(" System reset generated by MPU (MPSYSRST)\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) { -+ INFO(" Reset due to a clock failure on HSE\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) { -+ INFO(" IWDG1 Reset (rst_iwdg1)\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) { -+ INFO(" IWDG2 Reset (rst_iwdg2)\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) { -+ INFO(" MPU Processor 0 Reset\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) { -+ INFO(" MPU Processor 1 Reset\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { -+ INFO(" Pad Reset from NRST\n"); -+ return; -+ } -+ -+ if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) { -+ INFO(" Reset due to a failure of VDD_CORE\n"); -+ return; -+ } -+ -+ ERROR(" Unidentified reset reason\n"); -+} -+ +@@ -119,6 +145,11 @@ static void print_reset_reason(void) + ERROR(" Unidentified reset reason\n"); + } + +enum boot_device_e get_boot_device(void) +{ + return boot_device; +} + -+void bl2_el3_early_platform_setup(u_register_t arg0, -+ u_register_t arg1 __unused, -+ u_register_t arg2 __unused, -+ u_register_t arg3 __unused) -+{ -+ stm32mp_save_boot_ctx_address(arg0); - } - - void bl2_platform_setup(void) + void bl2_el3_early_platform_setup(u_register_t arg0, + u_register_t arg1 __unused, + u_register_t arg2 __unused, +@@ -131,9 +162,14 @@ void bl2_platform_setup(void) { int ret; -- if (dt_check_pmic()) { -+ if (dt_pmic_status() > 0) { - initialize_pmic(); -+#if STM32MP1_DEBUG_ENABLE -+ /* Program PMIC to keep debug ON */ -+ if ((stm32mp1_dbgmcu_boot_debug_info() == 1) && -+ (stm32mp1_dbgmcu_is_debug_on() != 0)) { -+ VERBOSE("Program PMIC to keep debug ON\n"); -+ if (pmic_keep_debug_unit() != 0) { -+ ERROR("PMIC not properly set for debug\n"); -+ } -+ } -+#endif - } +- if (dt_pmic_status() > 0) { +- initialize_pmic(); +- } ++ /* ++ * Map DDR non cacheable during its initialisation to avoid ++ * speculative loads before accesses are fully setup. ++ */ ++ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, ++ STM32MP_DDR_MAX_SIZE, ++ MT_NON_CACHEABLE | MT_RW | MT_NS); ++ assert(ret == 0); ret = stm32mp1_ddr_probe(); -@@ -48,62 +164,156 @@ void bl2_platform_setup(void) + if (ret < 0) { +@@ -141,13 +177,151 @@ void bl2_platform_setup(void) panic(); } -+#ifdef AARCH32_SP_OPTEE -+ INFO("BL2 runs OP-TEE setup\n"); -+ /* Initialize tzc400 after DDR initialization */ -+ stm32mp1_security_setup(); -+#else ++ ret = mmap_remove_dynamic_region(STM32MP_DDR_BASE, ++ STM32MP_DDR_MAX_SIZE); ++ assert(ret == 0); ++ + #ifdef AARCH32_SP_OPTEE + INFO("BL2 runs OP-TEE setup\n"); ++ ++ /* Map non secure DDR for BL33 load, now with cacheable attribute */ ++ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, ++ dt_get_ddr_size() - STM32MP_DDR_S_SIZE - ++ STM32MP_DDR_SHMEM_SIZE, ++ MT_MEMORY | MT_RW | MT_NS); ++ assert(ret == 0); ++ ++ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE + dt_get_ddr_size() - ++ STM32MP_DDR_S_SIZE - ++ STM32MP_DDR_SHMEM_SIZE, ++ STM32MP_DDR_BASE + dt_get_ddr_size() - ++ STM32MP_DDR_S_SIZE - ++ STM32MP_DDR_SHMEM_SIZE, ++ STM32MP_DDR_S_SIZE, ++ MT_MEMORY | MT_RW | MT_SECURE); ++ assert(ret == 0); ++ + /* Initialize tzc400 after DDR initialization */ + stm32mp1_security_setup(); + #else INFO("BL2 runs SP_MIN setup\n"); -+#endif ++ ++ /* Map non secure DDR for BL33 load, now with cacheable attribute */ ++ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, ++ dt_get_ddr_size(), ++ MT_MEMORY | MT_RW | MT_NS); ++ assert(ret == 0); + #endif ++ ++ if ((dt_pmic_status() > 0) && (!wakeup_standby)) { ++ configure_pmic(); ++ } ++} ++ ++static void update_monotonic_counter(void) ++{ ++ uint32_t version; ++ uint32_t otp; ++ ++ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE, ++ assert_stm32mp1_monotonic_counter_reach_max); ++ ++ /* Check if monotonic counter needs to be incremented */ ++ if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) { ++ panic(); ++ } ++ ++ if (stm32_get_otp_value(MONOTONIC_OTP, &version) != 0) { ++ panic(); ++ } ++ ++ if ((version + 1U) < BIT(STM32_TF_VERSION)) { ++ uint32_t result; ++ ++ /* Need to increment the monotonic counter. */ ++ version = BIT(STM32_TF_VERSION) - 1U; ++ ++ result = bsec_program_otp(version, otp); ++ if (result != BSEC_OK) { ++ ERROR("BSEC: MONOTONIC_OTP program Error %i\n", ++ result); ++ panic(); ++ } ++ INFO("Monotonic counter has been incremented (value 0x%x)\n", ++ version); ++ } ++} ++ ++static void initialize_clock(void) ++{ ++ uint32_t voltage_mv = 0U; ++ uint32_t freq_khz = 0U; ++ int ret = 0; ++ ++ if (wakeup_standby) { ++ ret = stm32_get_pll1_settings_from_context(); ++ } ++ ++ /* ++ * If no pre-defined PLL1 settings in DT, find the highest frequency ++ * in the OPP table (in DT, compatible with plaform capabilities, or ++ * in structure restored in RAM), and set related CPU supply voltage. ++ * If PLL1 settings found in DT, we consider CPU supply voltage in DT ++ * is consistent with it. ++ */ ++ if ((ret == 0) && !fdt_is_pll1_predefined()) { ++ if (wakeup_standby) { ++ ret = stm32mp1_clk_get_maxfreq_opp(&freq_khz, ++ &voltage_mv); ++ } else { ++ ret = dt_get_max_opp_freqvolt(&freq_khz, &voltage_mv); ++ } ++ ++ if (ret != 0) { ++ panic(); ++ } ++ ++ if (dt_pmic_status() > 0) { ++ int read_voltage; ++ const char *name; ++ ++ name = stm32mp_get_cpu_supply_name(); ++ if (name == NULL) { ++ panic(); ++ } ++ ++ read_voltage = stpmic1_regulator_voltage_get(name); ++ if (read_voltage < 0) { ++ panic(); ++ } ++ ++ if (voltage_mv != (uint32_t)read_voltage) { ++ if (stpmic1_regulator_voltage_set(name, ++ (uint16_t)voltage_mv) != 0) { ++ panic(); ++ } ++ } ++ } ++ } ++ ++ if (stm32mp1_clk_init(freq_khz) < 0) { ++ panic(); ++ } ++} ++ ++static void reset_uart(uint32_t reset) ++{ ++ if (stm32mp_reset_assert_to(reset, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ ++ udelay(2); ++ ++ if (stm32mp_reset_deassert_to(reset, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ ++ mdelay(1); } void bl2_el3_plat_arch_setup(void) - { - int32_t result; -- struct dt_node_info dt_dev_info; -+ struct dt_node_info dt_uart_info; - const char *board_model; - boot_api_context_t *boot_context = -- (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); -+ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); +@@ -160,20 +334,16 @@ void bl2_el3_plat_arch_setup(void) uint32_t clk_rate; -+ uintptr_t pwr_base; -+ uintptr_t rcc_base; + uintptr_t pwr_base; + uintptr_t rcc_base; + uint32_t bkpr_core1_magic = + tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); + uint32_t bkpr_core1_addr = + tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); -+ -+ 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, + + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + + #ifdef AARCH32_SP_OPTEE +- /* OP-TEE image needs post load processing: keep RAM read/write */ +- mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() - +- STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE, +- STM32MP_DDR_BASE + dt_get_ddr_size() - +- STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE, +- STM32MP_DDR_S_SIZE, +- MT_MEMORY | MT_RW | MT_SECURE); +- + mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, + STM32MP_OPTEE_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); +@@ -181,19 +351,12 @@ void bl2_el3_plat_arch_setup(void) + /* Prevent corruption of preloaded BL32 */ + mmap_add_region(BL32_BASE, BL32_BASE, + BL32_LIMIT - BL32_BASE, +- MT_MEMORY | MT_RO | MT_SECURE); +- + MT_RO_DATA | MT_SECURE); -+#endif -+ -+#ifdef AARCH32_SP_OPTEE -+ /* OP-TEE image needs post load processing: keep RAM read/write */ -+ mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() - -+ STM32MP_DDR_S_SIZE, -+ STM32MP_DDR_BASE + dt_get_ddr_size() - -+ STM32MP_DDR_S_SIZE, -+ STM32MP_DDR_S_SIZE, -+ MT_MEMORY | MT_RW | MT_SECURE); -+ -+ mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, -+ STM32MP_OPTEE_SIZE, -+ MT_MEMORY | MT_RW | MT_SECURE); -+#else -+ /* Prevent corruption of preloaded BL32 */ -+ mmap_add_region(BL32_BASE, BL32_BASE, -+ BL32_LIMIT - BL32_BASE, -+ MT_MEMORY | MT_RO | MT_SECURE); -+ -+#endif -+ /* Map non secure DDR for BL33 load and DDR training area restore */ -+ mmap_add_region(STM32MP_DDR_BASE, -+ STM32MP_DDR_BASE, -+ STM32MP_DDR_MAX_SIZE, -+ MT_MEMORY | MT_RW | MT_NS); -+ -+ /* Prevent corruption of preloaded Device Tree */ -+ mmap_add_region(DTB_BASE, DTB_BASE, -+ DTB_LIMIT - DTB_BASE, -+ MT_MEMORY | MT_RO | MT_SECURE); -+ -+ configure_mmu(); -+ -+ if (dt_open_and_check() < 0) { -+ panic(); -+ } -+ -+ pwr_base = stm32mp_pwr_base(); -+ rcc_base = stm32mp_rcc_base(); -+ + #endif +- /* Map non secure DDR for BL33 load and DDR training area restore */ +- mmap_add_region(STM32MP_DDR_BASE, +- STM32MP_DDR_BASE, +- STM32MP_DDR_MAX_SIZE, +- MT_MEMORY | MT_RW | MT_NS); +- + /* Prevent corruption of preloaded Device Tree */ + mmap_add_region(DTB_BASE, DTB_BASE, + DTB_LIMIT - DTB_BASE, +- MT_MEMORY | MT_RO | MT_SECURE); ++ MT_RO_DATA | MT_SECURE); + + configure_mmu(); + +@@ -204,6 +367,11 @@ void bl2_el3_plat_arch_setup(void) + pwr_base = stm32mp_pwr_base(); + rcc_base = stm32mp_rcc_base(); + + /* Clear Stop Request bits to correctly manage low-power exit */ + mmio_write_32(rcc_base + RCC_MP_SREQCLRR, + (uint32_t)(RCC_MP_SREQCLRR_STPREQ_P0 | + RCC_MP_SREQCLRR_STPREQ_P1)); - ++ /* * Disable the backup domain write protection. * The protection is enable at each reset by hardware - * and must be disabled by software. - */ -- mmio_setbits_32(PWR_BASE + PWR_CR1, PWR_CR1_DBP); -+ mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP); - -- while ((mmio_read_32(PWR_BASE + PWR_CR1) & PWR_CR1_DBP) == 0U) { -+ while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) { +@@ -215,6 +383,12 @@ void bl2_el3_plat_arch_setup(void) ; } @@ -36786,50 +36847,29 @@ index 9f2d8bd..cd5d5b3 100644 + */ + mmio_setbits_32(pwr_base + PWR_MCUCR, PWR_MCUCR_PDDS); + -+ if (bsec_probe() != 0) { -+ panic(); -+ } -+ - /* Reset backup domain on cold boot cases */ -- if ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) { -- mmio_setbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST); -+ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) { -+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); - -- while ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_VSWRST) == -+ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) == - 0U) { - ; - } - -- mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST); -+ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); + if (bsec_probe() != 0) { + panic(); + } +@@ -231,25 +405,72 @@ void bl2_el3_plat_arch_setup(void) + mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); } -- mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, -- BL_CODE_END - BL_CODE_BASE, -- MT_CODE | MT_SECURE); + /* Wait 5 HSI periods before re-enabling PLLs after STOP modes */ + mmio_clrsetbits_32(rcc_base + RCC_PWRLPDLYCR, + RCC_PWRLPDLYCR_PWRLP_DLY_MASK, + PWRLP_TEMPO_5_HSI); ++ ++ /* 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); -- /* Prevent corruption of preloaded BL32 */ -- mmap_add_region(BL32_BASE, BL32_BASE, -- BL32_LIMIT - BL32_BASE, -- MT_MEMORY | MT_RO | MT_SECURE); -+ /* 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); - -- /* Prevent corruption of preloaded Device Tree */ -- mmap_add_region(DTB_BASE, DTB_BASE, -- DTB_LIMIT - DTB_BASE, -- MT_MEMORY | MT_RO | MT_SECURE); -+ /* Disable MCKPROT */ -+ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); - -- configure_mmu(); ++ /* 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 != @@ -36837,16 +36877,16 @@ index 9f2d8bd..cd5d5b3 100644 + mmio_write_32(bkpr_core1_addr, 0); + mmio_write_32(bkpr_core1_magic, 0); + } - ++ ++ wakeup_standby = (mmio_read_32(bkpr_core1_addr) != 0U); ++ generic_delay_timer_init(); -- if (dt_open_and_check() < 0) { -- panic(); -+#ifdef STM32MP_USB ++#if STM32MP_USB_PROGRAMMER + if (boot_context->boot_interface_selected == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) { + boot_device = BOOT_DEVICE_USB; - } ++ } +#endif + +#if STM32MP_UART_PROGRAMMER @@ -36859,111 +36899,124 @@ index 9f2d8bd..cd5d5b3 100644 + ((USART_TypeDef *)uart_prog_addr)->CR1 &= ~USART_CR1_UE; + } +#endif - ++ if (stm32mp1_clk_probe() < 0) { panic(); -@@ -113,12 +323,18 @@ void bl2_el3_plat_arch_setup(void) - panic(); } -- result = dt_get_stdout_uart_info(&dt_dev_info); -+ result = dt_get_stdout_uart_info(&dt_uart_info); +- if (stm32mp1_clk_init() < 0) { +- panic(); ++ if (dt_pmic_status() > 0) { ++ initialize_pmic(); + } + +- stm32mp1_syscfg_init(); ++ initialize_clock(); + + result = dt_get_stdout_uart_info(&dt_uart_info); if ((result <= 0) || -- (dt_dev_info.status == 0U) || -- (dt_dev_info.clock < 0) || -- (dt_dev_info.reset < 0)) { -+ (dt_uart_info.status == 0U) || + (dt_uart_info.status == 0U) || +#if STM32MP_UART_PROGRAMMER + ((boot_context->boot_interface_selected == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) && + (get_uart_address(boot_context->boot_interface_instance) == + dt_uart_info.base)) || +#endif -+ (dt_uart_info.clock < 0) || -+ (dt_uart_info.reset < 0)) { + (dt_uart_info.clock < 0) || + (dt_uart_info.reset < 0)) { + goto skip_console_init; +@@ -259,12 +480,17 @@ void bl2_el3_plat_arch_setup(void) goto skip_console_init; } -@@ -126,29 +342,57 @@ void bl2_el3_plat_arch_setup(void) - goto skip_console_init; - } - -- if (stm32mp1_clk_enable((unsigned long)dt_dev_info.clock) != 0) { -- goto skip_console_init; + if (dt_uart_info.status == DT_DISABLED) { + panic(); + } else if (dt_uart_info.status == DT_SECURE) { + stm32mp_register_secure_periph_iomem(dt_uart_info.base); + } else { + stm32mp_register_non_secure_periph_iomem(dt_uart_info.base); - } - -- stm32mp1_reset_assert((uint32_t)dt_dev_info.reset); -+ stm32mp_clk_enable((unsigned long)dt_uart_info.clock); ++ } + -+ stm32mp_reset_assert((uint32_t)dt_uart_info.reset); - udelay(2); -- stm32mp1_reset_deassert((uint32_t)dt_dev_info.reset); -+ stm32mp_reset_deassert((uint32_t)dt_uart_info.reset); - mdelay(1); + stm32mp_clk_enable((unsigned long)dt_uart_info.clock); -- clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_dev_info.clock); -+ clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock); +- stm32mp_reset_assert((uint32_t)dt_uart_info.reset); +- udelay(2); +- stm32mp_reset_deassert((uint32_t)dt_uart_info.reset); +- mdelay(1); ++ reset_uart((uint32_t)dt_uart_info.reset); -- if (console_init(dt_dev_info.base, clk_rate, -- STM32MP1_UART_BAUDRATE) == 0) { -+ if (console_stm32_register(dt_uart_info.base, clk_rate, -+ STM32MP_UART_BAUDRATE, &console) == 0) { + clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock); + +@@ -285,22 +511,40 @@ void bl2_el3_plat_arch_setup(void) + + stm32mp_print_boardinfo(); + ++#if TRUSTED_BOARD_BOOT + if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) { + NOTICE("Bootrom authentication %s\n", + (boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ? + "failed" : "succeeded"); + } ++#endif + + skip_console_init: ++#if !TRUSTED_BOARD_BOOT ++ if (stm32mp_is_closed_device()) { ++ /* Closed chip required authentication */ ++ ERROR("Secured chip must enabled TRUSTED_BOARD_BOOT\n"); ++ panic(); ++ } ++#endif ++ ++ stm32mp1_syscfg_init(); ++ + if (stm32_iwdg_init() < 0) { panic(); } -+ stm32mp_print_cpuinfo(); - board_model = dt_get_board_model(); - if (board_model != NULL) { -- NOTICE("%s\n", board_model); -+ NOTICE("Model: %s\n", board_model); -+ } -+ stm32mp_print_boardinfo(); + stm32_iwdg_refresh(); + +- result = stm32mp1_dbgmcu_freeze_iwdg2(); +- if (result != 0) { +- INFO("IWDG2 freeze error : %i\n", result); ++ if (bsec_read_debug_conf() != 0U) { ++ result = stm32mp1_dbgmcu_freeze_iwdg2(); ++ if (result != 0) { ++ INFO("IWDG2 freeze error : %i\n", result); ++ } + -+ if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) { -+ NOTICE("%s\n", (boot_context->auth_status == -+ BOOT_API_CTX_AUTH_FAILED) ? -+ "Boot authentication Failed" : -+ "Boot authentication Success"); ++ if (stm32mp_is_closed_device()) { ++ NOTICE("\n%s", debug_msg); ++ } } - skip_console_init: - -+ /* Initialize IWDG Status, no startup */ -+ if (stm32_iwdg_init() < 0) { -+ panic(); -+ } -+ -+ /* Reload watchdog */ -+ stm32_iwdg_refresh(IWDG2_INST); -+ -+ result = stm32mp1_dbgmcu_freeze_iwdg2(); -+ if (result != 0) { -+ INFO("IWDG2 freeze error : %i\n", result); -+ } -+ if (stm32_save_boot_interface(boot_context->boot_interface_selected, - boot_context->boot_interface_instance) != - 0) { -@@ -157,5 +401,118 @@ skip_console_init: +@@ -309,20 +553,47 @@ skip_console_init: + ERROR("Cannot save boot interface\n"); + } +- stm32mp1_auth_ops.check_key = boot_context->bootrom_ecdsa_check_key; +- stm32mp1_auth_ops.verify_signature = +- boot_context->bootrom_ecdsa_verify_signature; +- +- stm32mp_init_auth(&stm32mp1_auth_ops); +- stm32mp1_arch_security_setup(); -- stm32mp1_io_setup(); -+ print_reset_reason(); + print_reset_reason(); + ++ update_monotonic_counter(); + -+ stm32mp_io_setup(); ++ if (dt_pmic_status() > 0) { ++ initialize_pmic(); ++ print_pmic_info_and_debug(); ++ } + -+ stm32mp1_syscfg_init(); -+} -+ -+#if defined(AARCH32_SP_OPTEE) + stm32mp_io_setup(); + } + + #if defined(AARCH32_SP_OPTEE) +static void set_mem_params_info(entry_point_info_t *ep_info, + image_info_t *unpaged, image_info_t *paged) +{ @@ -36980,117 +37033,94 @@ index 9f2d8bd..cd5d5b3 100644 + unpaged->image_max_size = STM32MP_OPTEE_SIZE; + } else { + unpaged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() - -+ STM32MP_DDR_S_SIZE; ++ STM32MP_DDR_S_SIZE - ++ STM32MP_DDR_SHMEM_SIZE; + unpaged->image_max_size = STM32MP_DDR_S_SIZE; + } + paged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() - -+ STM32MP_DDR_S_SIZE; ++ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE; + paged->image_max_size = STM32MP_DDR_S_SIZE; +} +#endif + -+/******************************************************************************* -+ * This function can be used by the platforms to update/use image -+ * information for given `image_id`. -+ ******************************************************************************/ -+int bl2_plat_handle_post_image_load(unsigned int image_id) -+{ -+ int err = 0; -+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + /******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. +@@ -331,30 +602,34 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + { + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#if defined(AARCH32_SP_OPTEE) -+ bl_mem_params_node_t *bl32_mem_params; -+ bl_mem_params_node_t *pager_mem_params; -+ bl_mem_params_node_t *paged_mem_params; + bl_mem_params_node_t *bl32_mem_params; + bl_mem_params_node_t *pager_mem_params; + bl_mem_params_node_t *paged_mem_params; ++#endif + + assert(bl_mem_params != NULL); + ++#if TRUSTED_BOARD_BOOT ++ /* Clean header to avoid loaded header reused */ ++ stm32mp_delete_loaded_header(); +#endif + -+ assert(bl_mem_params != NULL); -+ -+ switch (image_id) { -+ case BL32_IMAGE_ID: + switch (image_id) { + case BL32_IMAGE_ID: +#if defined(AARCH32_SP_OPTEE) -+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); -+ assert(pager_mem_params); -+ -+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); -+ assert(paged_mem_params); -+ -+ bl_mem_params->ep_info.pc = -+ bl_mem_params->image_info.image_base; + bl_mem_params->ep_info.pc = + bl_mem_params->image_info.image_base; + + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params != NULL); +- pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE; +- pager_mem_params->image_info.image_max_size = +- STM32MP_OPTEE_SIZE; + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params != NULL); +- paged_mem_params->image_info.image_base = STM32MP_DDR_BASE + +- (dt_get_ddr_size() - STM32MP_DDR_S_SIZE - +- STM32MP_DDR_SHMEM_SIZE); +- paged_mem_params->image_info.image_max_size = +- STM32MP_DDR_S_SIZE; + + set_mem_params_info(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); -+ -+ err = parse_optee_header(&bl_mem_params->ep_info, -+ &pager_mem_params->image_info, -+ &paged_mem_params->image_info); -+ if (err) { -+ ERROR("OPTEE header parse error.\n"); -+ panic(); -+ } -+ -+ /* Set optee boot info from parsed header data */ -+ bl_mem_params->ep_info.pc = -+ pager_mem_params->image_info.image_base; -+ bl_mem_params->ep_info.args.arg0 = -+ paged_mem_params->image_info.image_base; -+ bl_mem_params->ep_info.args.arg1 = 0; /* Unused */ -+ bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */ + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, +@@ -371,12 +646,18 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + paged_mem_params->image_info.image_base; + bl_mem_params->ep_info.args.arg1 = 0; /* Unused */ + bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */ +#endif -+ break; -+ -+ case BL33_IMAGE_ID: + break; + + case BL33_IMAGE_ID: +#ifdef AARCH32_SP_OPTEE -+ bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID); -+ assert(bl32_mem_params); -+ bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; -+#else -+ /* BL33 expects to receive : TBD */ -+ bl_mem_params->ep_info.args.arg0 = 0; -+ bl_mem_params->ep_info.spsr = -+ SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, -+ DISABLE_ALL_EXCEPTIONS); + bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID); + assert(bl32_mem_params != NULL); + bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; +#endif ++ + flush_dcache_range(bl_mem_params->image_info.image_base, + bl_mem_params->image_info.image_max_size); -+ break; -+ -+#ifdef AARCH32_SP_OPTEE -+ case BL32_EXTRA1_IMAGE_ID: -+ case BL32_EXTRA2_IMAGE_ID: -+ clean_dcache_range(bl_mem_params->image_info.image_base, -+ bl_mem_params->image_info.image_max_size); -+ break; -+#endif -+ -+ default: -+ err = -1; -+ break; -+ } -+ -+ return err; + break; + + default: +@@ -386,4 +667,3 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + + return err; } -+ +-#endif diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h -index 71c3593..5953e6e 100644 +index 2284970fa..872e2044c 100644 --- a/plat/st/stm32mp1/include/boot_api.h +++ b/plat/st/stm32mp1/include/boot_api.h -@@ -1,13 +1,108 @@ - /* -- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef __BOOT_API_H --#define __BOOT_API_H -+#ifndef BOOT_API_H -+#define BOOT_API_H - +@@ -10,6 +10,90 @@ #include -+#include -+ + #include + +/* + * Exported constants + */ @@ -37175,41 +37205,32 @@ index 71c3593..5953e6e 100644 +/* CSTANDBY Exit with MCU detected as Running */ +#define BOOT_API_CTX_CSTBY_EXIT_STATUS_MCU_RUNNING 0x02 + -+/* -+ * Possible value of boot context field 'auth_status' -+ */ -+ /* No authentication done */ -+#define BOOT_API_CTX_AUTH_NO 0x00 -+ /* Authentication done and failed */ -+#define BOOT_API_CTX_AUTH_FAILED 0x01 -+ /* Authentication done and success */ -+#define BOOT_API_CTX_AUTH_SUCCESS 0x02 - /* - * Possible value of boot context field 'boot_interface_sel' -@@ -22,6 +117,21 @@ + * Possible value of boot context field 'auth_status' + */ +@@ -33,6 +117,21 @@ /* Boot occurred on EMMC */ #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U -+/* boot occurred on NAND FMC */ ++/* Boot occurred on FMC */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U + -+/* boot occurred on QSPI NOR */ ++/* Boot occurred on QSPI NOR */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U + -+/* boot occurred on UART */ ++/* Boot occurred on UART */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U + -+/* boot occurred on USB */ ++/* Boot occurred on USB */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U + -+/* boot occurred on NAND QSPI */ ++/* Boot occurred on QSPI NAND */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U + /** * @brief Possible value of boot context field 'EmmcXferStatus' */ -@@ -45,6 +155,10 @@ +@@ -56,6 +155,10 @@ #define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U #define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U @@ -37220,10 +37241,11 @@ index 71c3593..5953e6e 100644 /* Image Header related definitions */ /* Definition of header version */ -@@ -76,6 +190,64 @@ +@@ -86,6 +189,64 @@ + #define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U - /* ++/* + * MCU Code Integrity Check related definitions + */ + @@ -37281,14 +37303,14 @@ index 71c3593..5953e6e 100644 +#define \ +BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR3_TAMP_BCK_REG_IDX 3 + -+/* + /* * TAMP_BCK4R register index * This register is used to write a Magic Number in order to restart - * Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R -@@ -90,6 +262,39 @@ +@@ -100,6 +261,39 @@ + */ #define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U - /* ++/* + * TAMP_BCK22R register index + * This register contains offset in bytes of code to Hash in RETRAM region + * Note : offset is intended as relative value from start of RETRAM @@ -37321,14 +37343,16 @@ index 71c3593..5953e6e 100644 +/* Last TAMP_BKP index of MCU Firmware signature : ie TAMP_BCK31R */ +#define BOOT_API_MCIC_SHA_DIGEST_LAST_TAMP_BCK_REG_IDX 31 + -+/* + /* * Possible value of boot context field 'hse_clock_value_in_hz' */ - #define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U -@@ -113,6 +318,57 @@ +@@ -124,7 +318,58 @@ /* Closed = OTP_CFG0[6] */ #define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6 +-#define BOOT_API_RETURN_OK 0x66U ++#define BOOT_API_RETURN_OK 0x77U ++ +/* Mapping of OTP Word and OTP bits managing SSP and useful to FSBL-SSP */ +/* OTP_CFG8 */ +#define BOOT_API_OTP_SSP_WORD_NB 8U @@ -37379,27 +37403,18 @@ index 71c3593..5953e6e 100644 + uint32_t platform_type_ver; + +} boot_api_rom_version_info_t; -+ + /* * Boot Context related definitions - */ -@@ -129,9 +385,133 @@ typedef struct { +@@ -142,9 +387,29 @@ typedef struct { */ uint16_t boot_interface_selected; uint16_t boot_interface_instance; - uint32_t reserved1[13]; -+ uint32_t reserved1; -+ uint32_t nand_data_width; -+ uint32_t nand_block_size; -+ uint32_t nand_page_size; -+ uint32_t reserved2; -+ uint32_t nand_ecc_bits; -+ uint32_t nand_block_nb; -+ uint32_t reserved3[4]; -+ uint32_t nor_isdual; ++ uint32_t reserved1[12]; + uint32_t usb_context; uint32_t otp_afmux_values[3]; -- uint32_t reserved[9]; +- uint32_t reserved[5]; + uint32_t reserved[2]; + /* + * Log to boot context, what was the kind of boot action @@ -37420,106 +37435,10 @@ index 71c3593..5953e6e 100644 + * depending on encountered situation + */ + uint32_t cstby_exit_status; -+ /* -+ * Returned authentication status : take values from defines -+ * BOOT_API_CTX_AUTH_XXX above -+ */ -+ uint32_t auth_status; -+ -+ /* -+ ******************************************************* -+ * Pointers to bootROM External Secure Services -+ * External Secure Services offered by bootROM -+ * - ECDSA check key -+ * - ECDSA verify signature -+ * - ECDSA verify signature and go -+ ******************************************************* -+ */ -+ /* -+ * Check if hash of p_pub_key_in is equal to hash by SHA-256 -+ * of OEM public key from OTP -+ * -+ * If no: => infinite loop in bootROM : boot failed -+ * -+ * else: copy p_pub_key_in to p_pub_key_out if -+ * p_pub_key_out not NULL. -+ * and return to caller. -+ * -+ * @param[in] p_pub_key_in points to an ECDSA public key : -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in/out] p_pub_key_out points to area where to store copy -+ * of public key. -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @retval STD_OK (0x77) or STD_NOT_OK (0x66) -+ */ -+ uint32_t (*p_bootrom_ext_service_ecdsa_check_key) -+ (uint8_t *p_pub_key_in, -+ uint8_t *p_pub_key_out); -+ /* -+ * verify ECDSA signature -+ * -+ * Decrypt EDCSA signature from 'p_signature' -+ * using public key passed in parameter 'p_pub_key_in' -+ * Then compare it to hash from 'p_hash_in' (SHA-256) -+ * -+ * If no match: => infinite loop in bootROM -+ * -+ * else: return to caller -+ * -+ * @param[in] p_hash_in : points on hash in (SHA-256) -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in] p_pub_key_in : points to an ECDSA public key -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in] p_signature : points to an EDCSA signature. -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in] ecc_algo : Ecc algorithm to be used P256 NIST or -+ * Brain_pool 256. -+ * -+ * @retval STD_OK (0x77) or STD_NOT_OK (0x66) -+ */ -+ uint32_t (*p_bootrom_ext_service_ecdsa_verify_signature) -+ (uint8_t *p_hash_in, uint8_t *p_pub_key_in, -+ uint8_t *p_signature, uint32_t ecc_algo); -+ /* -+ * verify ECDSA signature and branch to entry point if match -+ * -+ * Decrypt EDCSA signature from 'p_signature' -+ * using public key passed in parameter 'p_pub_key_in' -+ * Then compare it to hash from 'p_hash_in' (SHA-256) -+ * -+ * If no match: => infinite loop in bootROM -+ * -+ * else: branch CA7-0 to branch address 'p_entry_in' -+ * -+ * @param[in] p_hash_in : points on hash in (SHA-256) -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in] p_pub_key_in : points to an ECDSA public key -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in] p_signature : points to an EDCSA signature. -+ * Very Important : address alignment constraint : -+ * This address should be multiple of 4 bytes only. -+ * @param[in] ecc_algo : Ecc algorithm to be used P256 NIST or -+ * Brain_pool 256. -+ * @param[in] p_entry_in : points to branch entry point. -+ * -+ * @retval STD_NOT_OK (0x66) -+ */ -+ uint32_t (*p_bootrom_ext_service_ecdsa_verify_and_go) -+ (uint8_t *p_hash_in, uint8_t *p_pub_key_in, -+ uint8_t *p_signature_in, uint32_t ecc_algo, -+ uint32_t *p_entry_in); -+ + uint32_t auth_status; + /* - * Information specific to an SD boot - * Updated each time an SD boot is at least attempted, -@@ -161,6 +541,21 @@ typedef struct { +@@ -194,6 +459,21 @@ typedef struct { * ie FSBL partition on which the boot was successful */ uint32_t boot_partition_used_toboot; @@ -37541,119 +37460,30 @@ index 71c3593..5953e6e 100644 } __packed boot_api_context_t; -@@ -229,7 +624,9 @@ typedef struct { - */ - uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES]; - /* Pad up to 256 byte total size */ -- uint8_t pad[84]; -+ uint8_t pad[83]; -+ /* Add binary type information */ -+ uint8_t binary_type; - } __packed boot_api_image_header_t; - --#endif /* __BOOT_API_H */ -+#endif /* BOOT_API_H */ diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h -index 47e1ffc..fd1ccbf 100644 +index 263e6d6e1..694c3c4bb 100644 --- a/plat/st/stm32mp1/include/platform_def.h +++ b/plat/st/stm32mp1/include/platform_def.h -@@ -24,12 +24,22 @@ - #define PLATFORM_STACK_SIZE 0xC00 - #endif - -+#ifdef AARCH32_SP_OPTEE -+#define OPTEE_HEADER_IMAGE_NAME "teeh" -+#define OPTEE_PAGED_IMAGE_NAME "teed" -+#define OPTEE_PAGER_IMAGE_NAME "teex" -+#define OPTEE_HEADER_BINARY_TYPE U(0x20) -+#define OPTEE_PAGER_BINARY_TYPE U(0x21) -+#define OPTEE_PAGED_BINARY_TYPE U(0x22) -+#endif -+ - /* SSBL = second stage boot loader */ - #define BL33_IMAGE_NAME "ssbl" -+#define BL33_BINARY_TYPE U(0x0) - --#define STM32MP1_PRIMARY_CPU U(0x0) -+#define STM32MP_PRIMARY_CPU U(0x0) -+#define STM32MP_SECONDARY_CPU U(0x1) - --#define PLATFORM_CACHE_LINE_SIZE 64 - #define PLATFORM_CLUSTER_COUNT ULL(1) - #define PLATFORM_CLUSTER0_CORE_COUNT U(2) - #define PLATFORM_CLUSTER1_CORE_COUNT U(0) -@@ -37,8 +47,9 @@ - PLATFORM_CLUSTER0_CORE_COUNT) - #define PLATFORM_MAX_CPUS_PER_CLUSTER 2 - --#define MAX_IO_DEVICES 4 --#define MAX_IO_HANDLES 4 -+#define MAX_IO_DEVICES U(4) -+#define MAX_IO_HANDLES U(4) -+#define MAX_IO_BLOCK_DEVICES U(1) +@@ -51,6 +51,7 @@ + #define MAX_IO_DEVICES U(4) + #define MAX_IO_HANDLES U(4) + #define MAX_IO_BLOCK_DEVICES U(1) ++#define MAX_IO_MTD_DEVICES U(1) /******************************************************************************* * BL2 specific defines. -@@ -47,39 +58,45 @@ - * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug - * size plus a little space for growth. +@@ -82,6 +83,10 @@ */ --#define BL2_BASE STM32MP1_BL2_BASE --#define BL2_LIMIT (STM32MP1_BL2_BASE + \ -- STM32MP1_BL2_SIZE) -+#define BL2_BASE STM32MP_BL2_BASE -+#define BL2_LIMIT (STM32MP_BL2_BASE + \ -+ STM32MP_BL2_SIZE) + #define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE - /******************************************************************************* - * BL32 specific defines. - ******************************************************************************/ --#define BL32_BASE STM32MP1_BL32_BASE --#define BL32_LIMIT (STM32MP1_BL32_BASE + \ -- STM32MP1_BL32_SIZE) -+#ifndef AARCH32_SP_OPTEE -+#define BL32_BASE STM32MP_BL32_BASE -+#define BL32_LIMIT (STM32MP_BL32_BASE + \ -+ STM32MP_BL32_SIZE) -+#endif - - /******************************************************************************* - * BL33 specific defines. - ******************************************************************************/ --#define BL33_BASE STM32MP1_BL33_BASE -+#define BL33_BASE STM32MP_BL33_BASE - - /* - * Load address of BL33 for this platform port - */ --#define PLAT_STM32MP1_NS_IMAGE_OFFSET BL33_BASE -+#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE -+ +/* need by flash programmer */ +#define FLASHLAYOUT_BASE STM32MP_DDR_BASE +#define FLASHLAYOUT_LIMIT STM32MP_BL33_BASE - ++ /******************************************************************************* * DTB specific defines. ******************************************************************************/ --#define DTB_BASE STM32MP1_DTB_BASE --#define DTB_LIMIT (STM32MP1_DTB_BASE + \ -- STM32MP1_DTB_SIZE) -+#define DTB_BASE STM32MP_DTB_BASE -+#define DTB_LIMIT (STM32MP_DTB_BASE + \ -+ STM32MP_DTB_SIZE) - - /******************************************************************************* - * Platform specific page table and MMU setup constants - ******************************************************************************/ --#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) --#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) -+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) -+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) - - /******************************************************************************* - * Declarations and constants to access the mailboxes safely. Each mailbox is -@@ -98,6 +115,8 @@ +@@ -112,6 +117,8 @@ */ #define ARM_IRQ_SEC_PHY_TIMER U(29) @@ -37662,13 +37492,13 @@ index 47e1ffc..fd1ccbf 100644 #define ARM_IRQ_SEC_SGI_0 U(8) #define ARM_IRQ_SEC_SGI_1 U(9) #define ARM_IRQ_SEC_SGI_2 U(10) -@@ -107,7 +126,15 @@ +@@ -121,7 +128,15 @@ #define ARM_IRQ_SEC_SGI_6 U(14) #define ARM_IRQ_SEC_SGI_7 U(15) +/* Platform IRQ Priority */ +#define STM32MP1_IRQ_RCC_SEC_PRIO U(0x6) -+#define STM32MP1_IRQ_SEC_SPI_PRIO U(0x10) ++#define STM32MP_IRQ_SEC_SPI_PRIO U(0x10) + #define STM32MP1_IRQ_TZC400 U(36) +#define STM32MP1_IRQ_MCU_SEV U(176) @@ -37678,28 +37508,44 @@ index 47e1ffc..fd1ccbf 100644 #define STM32MP1_IRQ_TAMPSERRS U(229) #define STM32MP1_IRQ_AXIERRIRQ U(244) -@@ -120,9 +147,6 @@ - INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \ - GIC_HIGHEST_SEC_PRIORITY, \ - grp, GIC_INTR_CFG_LEVEL), \ -- INTR_PROP_DESC(STM32MP1_IRQ_TAMPSERRS, \ -- GIC_HIGHEST_SEC_PRIORITY, \ -- grp, GIC_INTR_CFG_LEVEL), \ - INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \ - GIC_HIGHEST_SEC_PRIORITY, \ - grp, GIC_INTR_CFG_LEVEL), \ +diff --git a/plat/st/stm32mp1/include/stm32mp1_boot_device.h b/plat/st/stm32mp1/include/stm32mp1_boot_device.h +new file mode 100644 +index 000000000..a74598395 +--- /dev/null ++++ b/plat/st/stm32mp1/include/stm32mp1_boot_device.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP1_BOOT_DEVICE_H ++#define STM32MP1_BOOT_DEVICE_H ++ ++#include ++#include ++#include ++ ++int plat_get_raw_nand_data(struct rawnand_device *device); ++int plat_get_spi_nand_data(struct spinand_device *device); ++int plat_get_nor_data(struct nor_device *device); ++ ++#endif /* STM32MP1_BOOT_DEVICE_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h -index fd08afc..4cd6643 100644 +index 698415af2..21214d35a 100644 --- a/plat/st/stm32mp1/include/stm32mp1_context.h +++ b/plat/st/stm32mp1/include/stm32mp1_context.h -@@ -4,11 +4,23 @@ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * * SPDX-License-Identifier: BSD-3-Clause */ - --#ifndef __STM32MP1_CONTEXT_H__ --#define __STM32MP1_CONTEXT_H__ -+#ifndef STM32MP1_CONTEXT_H -+#define STM32MP1_CONTEXT_H +@@ -7,8 +7,26 @@ + #ifndef STM32MP1_CONTEXT_H + #define STM32MP1_CONTEXT_H +#include #include @@ -37709,103 +37555,29 @@ index fd08afc..4cd6643 100644 +void stm32_clean_context(void); +int stm32_save_context(uint32_t zq0cr0_zdata); +int stm32_restore_context(void); ++unsigned long long stm32_get_stgen_from_context(void); +int stm32_restore_backup_reg(void); +uint32_t stm32_get_zdata_from_context(void); ++int stm32_get_pll1_settings_from_context(void); ++bool stm32_are_pll1_settings_valid_in_context(void); int stm32_save_boot_interface(uint32_t interface, uint32_t instance); +int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance); +void stm32_save_ddr_training_area(void); +void stm32_restore_ddr_training_area(void); +uint32_t stm32_pm_get_optee_ep(void); ++ ++void stm32mp1_pm_save_clock_cfg(size_t offset, uint8_t *data, size_t size); ++void stm32mp1_pm_restore_clock_cfg(size_t offset, uint8_t *data, size_t size); --#endif /* __STM32MP1_CONTEXT_H__ */ -+#endif /* STM32MP1_CONTEXT_H */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h -new file mode 100644 -index 0000000..fd97a16 ---- /dev/null -+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef __PLAT_DBGMCU_H__ -+#define __PLAT_DBGMCU_H__ -+ -+#include -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+#define VERBOSE_HEXDUMP8(buf, len) stm32mp1_dbgmcu_hexdump8(buf, len) -+#else -+#define VERBOSE_HEXDUMP8(buf, len) -+#endif -+ -+uint32_t stm32mp1_dbgmcu_get_chip_version(void); -+uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void); -+int stm32mp1_dbgmcu_freeze_iwdg2(void); -+int stm32mp1_dbgmcu_boot_debug_info(void); -+int stm32mp1_dbgmcu_clear_boot_info(void); -+uint32_t stm32mp1_dbgmcu_is_debug_on(void); -+void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len); -+ -+#endif /* __PLAT_DBGMCU_H__ */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h -deleted file mode 100644 -index 58e10d1..0000000 ---- a/plat/st/stm32mp1/include/stm32mp1_dt.h -+++ /dev/null -@@ -1,41 +0,0 @@ --/* -- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#ifndef __STM32MP1_DT_H__ --#define __STM32MP1_DT_H__ -- --#include -- --struct dt_node_info { -- uint32_t base; -- int32_t clock; -- int32_t reset; -- bool status; -- bool sec_status; --}; -- --/******************************************************************************* -- * Function and variable prototypes -- ******************************************************************************/ --int dt_open_and_check(void); --int fdt_get_address(void **fdt_addr); --bool fdt_check_node(int node); --bool fdt_check_status(int node); --bool fdt_check_secure_status(int node); --uint32_t fdt_read_uint32_default(int node, const char *prop_name, -- uint32_t dflt_value); --int fdt_read_uint32_array(int node, const char *prop_name, -- uint32_t *array, uint32_t count); --int dt_set_pinctrl_config(int node); --int dt_set_stdout_pinctrl(void); --void dt_fill_device_info(struct dt_node_info *info, int node); --int dt_get_node(struct dt_node_info *info, int offset, const char *compat); --int dt_get_stdout_uart_info(struct dt_node_info *info); --int dt_get_stdout_node_offset(void); --uint32_t dt_get_ddr_size(void); --const char *dt_get_board_model(void); -- --#endif /* __STM32MP1_DT_H__ */ + #endif /* STM32MP1_CONTEXT_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_low_power.h b/plat/st/stm32mp1/include/stm32mp1_low_power.h new file mode 100644 -index 0000000..a9b2778 +index 000000000..82b3d36c1 --- /dev/null +++ b/plat/st/stm32mp1/include/stm32mp1_low_power.h @@ -0,0 +1,19 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -37825,12 +37597,12 @@ index 0000000..a9b2778 +#endif /* STM32MP1_LOW_POWER_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_power_config.h b/plat/st/stm32mp1/include/stm32mp1_power_config.h new file mode 100644 -index 0000000..bcee6b6 +index 000000000..7bd07956a --- /dev/null +++ b/plat/st/stm32mp1/include/stm32mp1_power_config.h @@ -0,0 +1,28 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -37858,80 +37630,68 @@ index 0000000..bcee6b6 + +#endif /* STM32MP1_POWER_CONFIG_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h -index a789d53..cc6c9e7 100644 +index e38fca012..e9fadb063 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h -@@ -1,22 +1,38 @@ - /* -- * 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 - */ +@@ -9,16 +9,31 @@ --#ifndef __STM32MP1_PRIVATE_H__ --#define __STM32MP1_PRIVATE_H__ -+#ifndef STM32MP1_PRIVATE_H -+#define STM32MP1_PRIVATE_H -+ -+#include -+#include -+#include + #include + ++#include + +enum boot_device_e { + BOOT_DEVICE_USB, + BOOT_DEVICE_BOARD +}; - --void stm32mp1_io_setup(void); ++ 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); -+ + +-void stm32mp1_gic_pcpu_init(void); +-void stm32mp1_gic_init(void); +enum boot_device_e get_boot_device(void); - --void stm32mp1_save_boot_ctx_address(uintptr_t address); --uintptr_t stm32mp1_get_boot_ctx_address(void); -+#if STM32MP_UART_PROGRAMMER -+uintptr_t get_uart_address(uint32_t instance_nb); -+#endif - - void stm32mp1_gic_pcpu_init(void); - void stm32mp1_gic_init(void); - --#endif /* __STM32MP1_PRIVATE_H__ */ ++ +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); + ++void stm32mp1_init_scmi_server(void); ++void stm32mp1_pm_save_scmi_state(uint8_t *state, size_t size); ++void stm32mp1_pm_restore_scmi_state(uint8_t *state, size_t size); + -+void stm32mp1_syscfg_init(void); -+ -+#endif /* STM32MP1_PRIVATE_H */ + #endif /* STM32MP1_PRIVATE_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h new file mode 100644 -index 0000000..b161cab +index 000000000..89c333358 --- /dev/null +++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h -@@ -0,0 +1,83 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ +@@ -0,0 +1,132 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_SHARED_RESOURCES_H +#define STM32MP1_SHARED_RESOURCES_H + -+#include -+#include +#include + -+void stm32mp_clk_enable(unsigned long id); -+void stm32mp_clk_disable(unsigned long id); ++#include ++#include + -+#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + i) ++#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i)) + +enum stm32mp_shres { -+ STM32MP1_SHRES_GPIOZ_0 = 0, ++ STM32MP1_SHRES_CRYP1, ++ STM32MP1_SHRES_GPIOZ_0, + STM32MP1_SHRES_GPIOZ_1, + STM32MP1_SHRES_GPIOZ_2, + STM32MP1_SHRES_GPIOZ_3, @@ -37939,153 +37699,314 @@ index 0000000..b161cab + STM32MP1_SHRES_GPIOZ_5, + STM32MP1_SHRES_GPIOZ_6, + STM32MP1_SHRES_GPIOZ_7, -+ STM32MP1_SHRES_IWDG1, -+ STM32MP1_SHRES_USART1, -+ STM32MP1_SHRES_SPI6, -+ STM32MP1_SHRES_I2C4, -+ STM32MP1_SHRES_RNG1, + STM32MP1_SHRES_HASH1, -+ STM32MP1_SHRES_CRYP1, ++ STM32MP1_SHRES_I2C4, + STM32MP1_SHRES_I2C6, -+ STM32MP1_SHRES_RTC, ++ STM32MP1_SHRES_IWDG1, + STM32MP1_SHRES_MCU, -+ STM32MP1_SHRES_HSI, -+ STM32MP1_SHRES_LSI, -+ STM32MP1_SHRES_HSE, -+ STM32MP1_SHRES_LSE, -+ STM32MP1_SHRES_CSI, -+ STM32MP1_SHRES_PLL1, -+ STM32MP1_SHRES_PLL1_P, -+ STM32MP1_SHRES_PLL1_Q, -+ STM32MP1_SHRES_PLL1_R, -+ STM32MP1_SHRES_PLL2, -+ STM32MP1_SHRES_PLL2_P, -+ STM32MP1_SHRES_PLL2_Q, -+ STM32MP1_SHRES_PLL2_R, ++ STM32MP1_SHRES_MDMA, ++ STM32MP1_SHRES_RNG1, ++ STM32MP1_SHRES_RTC, ++ STM32MP1_SHRES_SPI6, ++ STM32MP1_SHRES_USART1, + STM32MP1_SHRES_PLL3, -+ STM32MP1_SHRES_PLL3_P, -+ STM32MP1_SHRES_PLL3_Q, -+ STM32MP1_SHRES_PLL3_R, + + STM32MP1_SHRES_COUNT +}; + -+void stm32mp1_register_secure_periph(unsigned int id); -+void stm32mp1_register_shared_periph(unsigned int id); -+void stm32mp1_register_non_secure_periph(unsigned int id); ++#ifdef IMAGE_BL32 ++/* Register a peripheral as secure or non-secure based on identifier */ ++void stm32mp_register_secure_periph(unsigned int id); ++void stm32mp_register_non_secure_periph(unsigned int id); ++ ++/* Register a peripheral as secure or non-secure based on IO base address */ +void stm32mp_register_secure_periph_iomem(uintptr_t base); +void stm32mp_register_non_secure_periph_iomem(uintptr_t base); ++ ++/* Register a GPIO as secure or non-secure based on its bank and pin numbers */ +void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin); +void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin); ++ ++/* ++ * Register a (non-)secure peripheral based on the ETZPC DECPROT configuration ++ */ +void stm32mp1_register_etzpc_decprot(unsigned int id, + enum etzpc_decprot_attributes attr); + -+bool stm32mp1_periph_is_shared(unsigned long id); ++/* Consolidate peripheral states and locknew periph registering */ ++void stm32mp_lock_periph_registering(void); ++ ++/* Get peripheral state in shared resource driver */ +bool stm32mp1_periph_is_non_secure(unsigned long id); +bool stm32mp1_periph_is_secure(unsigned long id); -+bool stm32mp1_periph_is_unregistered(unsigned long id); + -+bool stm32mp_gpio_bank_is_shared(unsigned int bank); +bool stm32mp_gpio_bank_is_non_secure(unsigned int bank); -+bool stm32mp_gpio_bank_is_secure(unsigned int bank); ++bool stm32mp_gpio_bank_is_shared(unsigned int bank); + -+bool stm32mp1_clock_is_shareable(unsigned long clock_id); -+bool stm32mp1_clock_is_shared(unsigned long clock_id); -+bool stm32mp1_clock_is_non_secure(unsigned long clock_id); ++bool stm32mp_nsec_can_access_clock(unsigned long clock_id); ++bool stm32mp_nsec_can_access_reset(unsigned int reset_id); ++#else /* IMAGE_BL32 */ ++static inline void stm32mp_register_secure_periph(unsigned int id) ++{ ++} + -+void stm32mp1_driver_init_late(void); ++static inline void stm32mp_register_non_secure_periph(unsigned int id) ++{ ++} ++ ++static inline void stm32mp_register_secure_periph_iomem(uintptr_t base) ++{ ++} ++ ++static inline void stm32mp_register_non_secure_periph_iomem(uintptr_t base) ++{ ++} ++ ++static inline void stm32mp_register_secure_gpio(unsigned int bank, ++ unsigned int pin) ++{ ++} ++ ++static inline void stm32mp_register_non_secure_gpio(unsigned int bank, ++ unsigned int pin) ++{ ++} ++ ++static inline void stm32mp1_register_etzpc_decprot(unsigned int id, ++ enum etzpc_decprot_attributes attr) ++{ ++} ++ ++static inline void stm32mp_lock_periph_registering(void) ++{ ++ /* Platform is not expected to lock a non existing database */ ++ panic(); ++} ++ ++static inline bool stm32mp1_periph_is_non_secure(unsigned long id) ++{ ++ return false; ++} ++ ++static inline bool stm32mp1_periph_is_secure(unsigned long id) ++{ ++ return true; ++} ++ ++static inline bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) ++{ ++ return false; ++} ++ ++static inline bool stm32mp_gpio_bank_is_shared(unsigned int bank) ++{ ++ return false; ++} ++#endif /* IMAGE_BL32 */ + +#endif /* STM32MP1_SHARED_RESOURCES_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h -new file mode 100644 -index 0000000..956493f ---- /dev/null +index b87275839..19ae1d0a3 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_smc.h +++ b/plat/st/stm32mp1/include/stm32mp1_smc.h -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -7,45 +7,157 @@ + #ifndef STM32MP1_SMC_H + #define STM32MP1_SMC_H + ++/* SMC service generic return codes */ ++#define STM32_SMC_OK 0x00000000U ++#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU ++#define STM32_SMC_FAILED 0xFFFFFFFEU ++#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU ++ + /* +- * SMC function IDs for STM32 Service queries ++ * SMC function IDs for STM32 Service queries. + * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF + * like this is defined in SMC calling Convention by ARM +- * for SiP (silicon Partner) ++ * for SiP (silicon Partner). + * https://developer.arm.com/docs/den0028/latest + */ + + /* Secure Service access from Non-secure */ + + /* +- * STM32_SMC_BSEC call API ++ * SMC function STM32_SMC_RCC. + * -+ * SPDX-License-Identifier: BSD-3-Clause ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx). ++ * Argument a2: (input) Register offset or physical address. ++ * (output) Register read value, if applicable. ++ * Argument a3: (input) Register target value if applicable. + */ -+ -+#ifndef __STM32MP1_SMC_H__ -+#define __STM32MP1_SMC_H__ -+ -+#include ++#define STM32_SMC_RCC 0x82001000 + +/* -+ * SMC function IDs for STM32 Service queries -+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF -+ * like this is defined in SMC calling Convention by ARM -+ * for SiP (silicon Partner) -+ * https://developer.arm.com/docs/den0028/latest ++ * SMC function STM32_SMC_PWR. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx). ++ * Argument a2: (input) Register offset or physical address. ++ * (output) Register read value, if applicable. ++ * Argument a3: (input) Register target value if applicable. + */ -+ -+/* Secure Service access from Non-secure */ -+#define STM32_SMC_RCC 0x82001000 +#define STM32_SMC_PWR 0x82001001 -+#define STM32_SMC_RCC_CAL 0x82001002 -+#define STM32_SMC_BSEC 0x82001003 + ++/* ++ * SMC functions STM32_SMC_RCC_CAL. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a1: (input) Clock ID (from DT clock bindings). ++ */ ++#define STM32_SMC_RCC_CAL 0x82001002 ++ ++/* ++ * SMC functions STM32_SMC_BSEC. + * +- * Argument a0: (input) SMCC ID +- * (output) status return code +- * Argument a1: (input) Service ID (STM32_SMC_BSEC_xxx) +- * Argument a2: (input) OTP index +- * (output) OTP read value, if applicable +- * Argument a3: (input) OTP value if applicable ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a1: (input) Service ID (STM32_SMC_READ_xxx/_PROG_xxx/_WRITE_xxx). ++ * (output) OTP read value, if applicable. ++ * Argument a2: (input) OTP index. ++ * Argument a3: (input) OTP value if applicable. + */ + #define STM32_SMC_BSEC 0x82001003 + +/* Low Power services */ -+#define STM32_SMC_SR_MODE 0x82001004 ++ ++/* ++ * SIP function STM32_SMC_PD_DOMAIN. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a2: (index) ID of target power domain to be enabled/disabled. ++ * Argument a3: (input) 0 to disable, 1 to enable target domain. ++ */ +#define STM32_SMC_PD_DOMAIN 0x82001008 + -+/* SMC function IDs for SiP Service queries */ -+#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00 -+#define STM32_SIP_SVC_UID 0x8200ff01 -+/* 0x8200ff02 is reserved */ ++/* ++ * SIP function STM32_SMC_RCC_OPP. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a1: (input) Service ID (STM32_SMC_RCC_OPP_xxx). ++ * (output) Rounded frequency, if applicable. ++ * Argument a2: (input) Requested frequency. ++ */ ++#define STM32_SMC_RCC_OPP 0x82001009 ++ ++/* ++ * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT0/1 ++ * ++ * Process SCMI message pending in SCMI shared memory buffer ++ * related to SCMI agent IDs 0 and 1. No input or output arguments ++ * passed through CPU general purpose registers, messages are transfer ++ * through a dedicated area in SYSRAM, mapped as device memory. ++ */ ++#define STM32_SMC_SCMI_MESSAGE_AGENT0 0x82002000 ++#define STM32_SMC_SCMI_MESSAGE_AGENT1 0x82002001 ++ + /* SMC function IDs for SiP Service queries */ ++ ++/* ++ * SIP function STM32_SIP_SVC_CALL_COUNT. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Dummy value 0. ++ */ + #define STM32_SIP_SVC_CALL_COUNT 0x8200ff00 ++ ++/* ++ * SIP function STM32_SIP_SVC_UID. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Lowest 32bit of the stm32mp1 SIP service UUID. ++ * Argument a1: (output) Next 32bit of the stm32mp1 SIP service UUID. ++ * Argument a2: (output) Next 32bit of the stm32mp1 SIP service UUID. ++ * Argument a3: (output) Last 32bit of the stm32mp1 SIP service UUID. ++ */ + #define STM32_SIP_SVC_UID 0x8200ff01 +-/* 0x8200ff02 is reserved */ +-#define STM32_SIP_SVC_VERSION 0x8200ff03 + +-/* STM32 SiP Service Calls version numbers */ +-#define STM32_SIP_SVC_VERSION_MAJOR 0x0 +-#define STM32_SIP_SVC_VERSION_MINOR 0x1 ++/* 0x8200ff02 is reserved */ + +-/* Number of STM32 SiP Calls implemented */ +-#define STM32_COMMON_SIP_NUM_CALLS 4 ++/* ++ * SIP function STM32_SIP_SVC_VERSION. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) STM32 SIP service major. ++ * Argument a1: (output) STM32 SIP service minor. ++ */ +#define STM32_SIP_SVC_VERSION 0x8200ff03 + ++/* Service ID for STM32_SMC_RCC/_PWR */ ++#define STM32_SMC_REG_READ 0x0 ++#define STM32_SMC_REG_WRITE 0x1 ++#define STM32_SMC_REG_SET 0x2 ++#define STM32_SMC_REG_CLEAR 0x3 + +-/* Service for BSEC */ ++/* Service ID for STM32_SMC_BSEC */ + #define STM32_SMC_READ_SHADOW 0x01 + #define STM32_SMC_PROG_OTP 0x02 + #define STM32_SMC_WRITE_SHADOW 0x03 + #define STM32_SMC_READ_OTP 0x04 ++#define STM32_SMC_READ_ALL 0x05 ++#define STM32_SMC_WRITE_ALL 0x06 ++#define STM32_SMC_WRLOCK_OTP 0x07 ++ ++/* Service ID for STM32_SMC_RCC_OPP */ ++#define STM32_SMC_RCC_OPP_SET 0x0 ++#define STM32_SMC_RCC_OPP_ROUND 0x1 ++ +/* STM32 SiP Service Calls version numbers */ +#define STM32_SIP_SVC_VERSION_MAJOR 0x0 +#define STM32_SIP_SVC_VERSION_MINOR 0x1 + +/* Number of STM32 SiP Calls implemented */ -+#define STM32_COMMON_SIP_NUM_CALLS 10 -+ -+/* Register access service use for RCC/RTC/PWR */ -+#define STM32_SMC_REG_READ 0x0 -+#define STM32_SMC_REG_WRITE 0x1 -+#define STM32_SMC_REG_SET 0x2 -+#define STM32_SMC_REG_CLEAR 0x3 -+ -+/* Service for BSEC */ -+#define STM32_SMC_READ_SHADOW 0x01 -+#define STM32_SMC_PROG_OTP 0x02 -+#define STM32_SMC_WRITE_SHADOW 0x03 -+#define STM32_SMC_READ_OTP 0x04 -+#define STM32_SMC_READ_ALL 0x05 -+#define STM32_SMC_WRITE_ALL 0x06 -+ -+/* SMC error codes */ -+#define STM32_SMC_OK 0x00000000U -+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU -+#define STM32_SMC_FAILED 0xFFFFFFFEU -+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU -+ -+/* DDR Self-Refresh modes */ -+#define STM32_SMC_SR_MODE_SSR 0x0 -+#define STM32_SMC_SR_MODE_ASR 0x1 -+#define STM32_SMC_SR_MODE_HSR 0x2 -+ -+#endif /* __STM32MP1_SMC_H__ */ ++#define STM32_COMMON_SIP_NUM_CALLS 13 + + #endif /* STM32MP1_SMC_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_usb_desc.h b/plat/st/stm32mp1/include/stm32mp1_usb_desc.h new file mode 100644 -index 0000000..71cacb3 +index 000000000..cb514b20a --- /dev/null +++ b/plat/st/stm32mp1/include/stm32mp1_usb_desc.h @@ -0,0 +1,55 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __USBD_DESC_H -+#define __USBD_DESC_H ++#ifndef STM32MP1_USB_DESC_H ++#define STM32MP1_USB_DESC_H + -+#include ++#include + +/* Max DFU Packet Size = 1024 bytes */ +#define USBD_DFU_XFER_SIZE 1024 @@ -38130,180 +38051,52 @@ index 0000000..71cacb3 + +void stm32mp_usb_init_desc(usb_handle_t *pdev); + -+#endif /* __USBD_DESC_H */ ++#endif /* STM32MP1_USB_DESC_H */ diff --git a/plat/st/stm32mp1/include/usb_ctx.h b/plat/st/stm32mp1/include/usb_ctx.h new file mode 100644 -index 0000000..0046bd0 +index 000000000..95ffa4da4 --- /dev/null +++ b/plat/st/stm32mp1/include/usb_ctx.h @@ -0,0 +1,17 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#ifndef __USB_CTX_H -+#define __USB_CTX_H ++#ifndef USB_CTX_H ++#define USB_CTX_H + -+#include ++#include + +struct usb_ctx { + usb_handle_t *pusbd_device_ctx; + pcd_handle_t *phpcd_ctx; +}; + -+#endif /* __USB_CTX_H */ -diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -index 6f5bc4c..4ef135e 100644 ---- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -@@ -26,7 +26,9 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - VERSION_2, entry_point_info_t, - SECURE | EXECUTABLE | EP_FIRST_EXE), - -+#if !defined(AARCH32_SP_OPTEE) - .ep_info.pc = BL32_BASE, -+#endif - .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, - SPSR_E_LITTLE, - DISABLE_ALL_EXCEPTIONS), -@@ -34,13 +36,48 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, - VERSION_2, image_info_t, - IMAGE_ATTRIB_PLAT_SETUP), -- -+#if defined(AARCH32_SP_OPTEE) -+ /* optee header is loaded is SYSRAM above BL2 */ -+ .image_info.image_base = STM32MP_OPTEE_BASE, -+ .image_info.image_max_size = STM32MP_OPTEE_SIZE, -+#else - .image_info.image_base = BL32_BASE, - .image_info.image_max_size = BL32_LIMIT - BL32_BASE, -- -+#endif - .next_handoff_image_id = BL33_IMAGE_ID, - }, - -+#if defined(AARCH32_SP_OPTEE) -+ /* Fill BL32 external 1 image related information */ -+ { -+ .image_id = BL32_EXTRA1_IMAGE_ID, -+ -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, -+ VERSION_2, entry_point_info_t, -+ SECURE | NON_EXECUTABLE), -+ -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, -+ }, -+ /* Fill BL32 external 2 image related information */ -+ { -+ .image_id = BL32_EXTRA2_IMAGE_ID, -+ -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, -+ VERSION_2, entry_point_info_t, -+ SECURE | NON_EXECUTABLE), -+ -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, -+ }, -+#endif /* AARCH32_SP_OPTEE */ -+ - /* Fill BL33 related information */ - { - .image_id = BL33_IMAGE_ID, -@@ -49,7 +86,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - VERSION_2, entry_point_info_t, - NON_SECURE | EXECUTABLE), - -- .ep_info.pc = PLAT_STM32MP1_NS_IMAGE_OFFSET, -+ .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET, - .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, - SPSR_E_LITTLE, - DISABLE_ALL_EXCEPTIONS), -@@ -57,9 +94,9 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, - VERSION_2, image_info_t, 0), - -- .image_info.image_base = PLAT_STM32MP1_NS_IMAGE_OFFSET, -- .image_info.image_max_size = STM32MP1_DDR_MAX_SIZE - -- (PLAT_STM32MP1_NS_IMAGE_OFFSET - STM32MP1_DDR_BASE), -+ .image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET, -+ .image_info.image_max_size = STM32MP_DDR_MAX_SIZE - -+ (PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE), - - .next_handoff_image_id = INVALID_IMAGE_ID, - } ++#endif /* USB_CTX_H */ diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c -index 3c6d677..db53c37 100644 +index a52db6cac..0a7437ba4 100644 --- a/plat/st/stm32mp1/plat_image_load.c +++ b/plat/st/stm32mp1/plat_image_load.c -@@ -4,7 +4,23 @@ +@@ -1,10 +1,14 @@ + /* +- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2020, ARM Limited and Contributors. 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 /******************************************************************************* - * This function flushes the data structures so that they are visible -@@ -12,14 +28,101 @@ - ******************************************************************************/ - void plat_flush_next_bl_params(void) - { -+ uint32_t version; -+ +@@ -16,11 +20,73 @@ void plat_flush_next_bl_params(void) flush_bl_params_desc(); -+ -+ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE, -+ assert_stm32mp1_monotonic_counter_reach_max); -+ -+ /* Check if monotonic counter need to be incremented */ -+ ; -+ if (bsec_shadow_read_otp(&version, MONOTONIC_OTP) != BSEC_OK) { -+ ERROR("BSEC: MONOTONIC_OTP Error\n"); -+ panic(); -+ } -+ -+ INFO("read version %i current version %i\n", version, STM32_TF_VERSION); -+ -+ if ((version + 1U) < BIT(STM32_TF_VERSION)) { -+ uint32_t result; -+ -+ /* need to increment the monotonic counter */ -+ version = BIT(STM32_TF_VERSION) - 1U; -+ -+ result = bsec_program_otp(version, MONOTONIC_OTP); -+ if (result != BSEC_OK) { -+ ERROR("BSEC: MONOTONIC_OTP program Error %i\n", -+ result); -+ panic(); -+ } -+ INFO("Monotonic counter has been incremented value 0x%x\n", -+ version); -+ } } +#ifdef AARCH32_SP_OPTEE @@ -38366,162 +38159,177 @@ index 3c6d677..db53c37 100644 + stm32mp_clk_disable(RTCAPB); + } + -+ bl33->image_info.image_max_size = dt_get_ddr_size(); ++ /* Max size is non-secure DDR end address minus image_base */ ++ bl33->image_info.image_max_size = STM32MP_DDR_BASE + ++ dt_get_ddr_size() - ++ STM32MP_DDR_S_SIZE - ++ STM32MP_DDR_SHMEM_SIZE - ++ bl33->image_info.image_base; + return get_bl_load_info_from_mem_params_desc(); } diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk -index 30b2932..06594f0 100644 +index 90b3e3c1e..840a38d14 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -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. +-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # -@@ -8,24 +8,78 @@ ARM_CORTEX_A7 := yes - ARM_WITH_NEON := yes +@@ -9,11 +9,31 @@ ARM_WITH_NEON := yes BL2_AT_EL3 := 1 USE_COHERENT_MEM := 0 -+MULTI_CONSOLE_API := 1 ++# Add specific ST version ++ST_VERSION := r1.0 ++VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} ++ ++TRUSTED_BOARD_BOOT := 1 ++ +# Please don't increment this value without good understanding of +# the monotonic counter STM32_TF_VERSION ?= 0 +$(eval $(call add_define_val,STM32_TF_VERSION,${STM32_TF_VERSION})) + -+# Enable software PMIC programming in case of debug purpose -+STM32MP1_DEBUG_ENABLE ?= 1 -+$(eval $(call add_define_val,STM32MP1_DEBUG_ENABLE,${STM32MP1_DEBUG_ENABLE})) ++# Enable dynamic memory mapping ++PLAT_XLAT_TABLES_DYNAMIC := 1 ++$(eval $(call assert_boolean,PLAT_XLAT_TABLES_DYNAMIC)) ++$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) ++ ++# STM32 image header version v1.0 ++STM32_HEADER_VERSION_MAJOR:= 1 ++STM32_HEADER_VERSION_MINOR:= 0 # Not needed for Cortex-A7 WORKAROUND_CVE_2017_5715:= 0 --PLAT_INCLUDES := -Iplat/st/stm32mp1/include/ --PLAT_INCLUDES += -Iinclude/common/tbbr -+# Specific modification for reset halt workaround -+STM32MP1_RESET_HALT_WORKAROUND ?= 1 -+$(eval $(call add_define,STM32MP1_RESET_HALT_WORKAROUND)) -+ +AARCH32_EXCEPTION_DEBUG := 1 + -+ifeq ($(AARCH32_SP),optee) -+$(eval $(call add_define,AARCH32_SP_OPTEE)) -+endif -+ -+# Number of TF-A copies in the device -+STM32_TF_A_COPIES := 2 -+$(eval $(call add_define,STM32_TF_A_COPIES)) -+ifeq ($(AARCH32_SP),optee) -+PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 4))) -+else -+PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1))) -+endif -+$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) -+ + # Number of TF-A copies in the device + STM32_TF_A_COPIES := 2 + $(eval $(call add_define,STM32_TF_A_COPIES)) +@@ -24,6 +44,39 @@ PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1))) + endif + $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + +# Boot devices -+STM32MP1_QSPI_NOR := 1 -+$(eval $(call add_define,STM32MP1_QSPI_NOR)) -+STM32MP_FMC_NAND := 1 -+$(eval $(call add_define,STM32MP_FMC_NAND)) -+STM32MP_EMMC := 1 -+$(eval $(call add_define,STM32MP_EMMC)) -+STM32MP_SDMMC := 1 -+$(eval $(call add_define,STM32MP_SDMMC)) -+STM32MP1_QSPI_NAND := 1 -+$(eval $(call add_define,STM32MP1_QSPI_NAND)) ++STM32MP_EMMC ?= 0 ++STM32MP_SDMMC ?= 0 ++STM32MP_RAW_NAND ?= 0 ++STM32MP_SPI_NAND ?= 0 ++STM32MP_SPI_NOR ?= 0 + -+ifeq ($(filter 1,${STM32MP1_QSPI_NOR} ${STM32MP_FMC_NAND} ${STM32MP_EMMC} ${STM32MP_SDMMC}),) ++# Serial boot devices ++STM32MP_UART_PROGRAMMER ?= 0 ++STM32MP_USB_PROGRAMMER ?= 0 ++ ++ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \ ++ ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR} ${STM32MP_UART_PROGRAMMER} \ ++ ${STM32MP_USB_PROGRAMMER}),) +$(error "No boot device driver is enabled") +endif + -+STM32MP_UART_PROGRAMMER := 1 ++$(eval $(call assert_boolean,STM32MP_EMMC)) ++$(eval $(call assert_boolean,STM32MP_SDMMC)) ++$(eval $(call assert_boolean,STM32MP_RAW_NAND)) ++$(eval $(call assert_boolean,STM32MP_SPI_NAND)) ++$(eval $(call assert_boolean,STM32MP_SPI_NOR)) ++$(eval $(call add_define,STM32MP_EMMC)) ++$(eval $(call add_define,STM32MP_SDMMC)) ++$(eval $(call add_define,STM32MP_RAW_NAND)) ++$(eval $(call add_define,STM32MP_SPI_NAND)) ++$(eval $(call add_define,STM32MP_SPI_NOR)) ++ ++$(eval $(call assert_boolean,STM32MP_UART_PROGRAMMER)) ++$(eval $(call assert_boolean,STM32MP_USB_PROGRAMMER)) +$(eval $(call add_define,STM32MP_UART_PROGRAMMER)) ++$(eval $(call add_define,STM32MP_USB_PROGRAMMER)) + -+PLAT_INCLUDES := -Iinclude/common/tbbr -+PLAT_INCLUDES += -Iinclude/drivers/partition - PLAT_INCLUDES += -Iinclude/drivers/st -+PLAT_INCLUDES += -Iplat/st/common/include/ -+PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ -+ -+PLAT_INCLUDES += -Iinclude/lib/usb -+ -+STM32MP_USB := 1 + PLAT_INCLUDES := -Iplat/st/common/include/ + PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ - # Device tree --STM32_DTB_FILE_NAME ?= stm32mp157c-ev1.dtb --FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32_DTB_FILE_NAME))) -+DTB_FILE_NAME ?= stm32mp157c-ev1.dtb -+FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) - DTC_FLAGS += -Wno-unit_address_vs_reg - - include lib/libfdt/libfdt.mk - --PLAT_BL_COMMON_SOURCES := plat/st/stm32mp1/stm32mp1_common.c -+PLAT_BL_COMMON_SOURCES := plat/st/common/stm32mp_common.c \ -+ plat/st/stm32mp1/stm32mp1_private.c - - PLAT_BL_COMMON_SOURCES += drivers/console/aarch32/console.S \ - drivers/st/uart/aarch32/stm32_console.S -@@ -43,23 +97,56 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ - drivers/arm/tzc/tzc400.c \ +@@ -51,7 +104,7 @@ PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S + PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ -+ drivers/st/bsec/bsec.c \ -+ drivers/st/clk/stm32mp_clkfunc.c \ +- drivers/st/bsec/bsec.c \ ++ drivers/st/bsec/bsec2.c \ + drivers/st/clk/stm32mp_clkfunc.c \ drivers/st/clk/stm32mp1_clk.c \ - drivers/st/clk/stm32mp1_clkfunc.c \ drivers/st/ddr/stm32mp1_ddr_helpers.c \ - drivers/st/gpio/stm32_gpio.c \ -- drivers/st/pmic/stm32_i2c.c \ -- drivers/st/pmic/stm32mp1_pmic.c \ -- drivers/st/pmic/stpmu1.c \ -+ drivers/st/i2c/stm32_i2c.c \ -+ drivers/st/iwdg/stm32_iwdg.c \ -+ drivers/st/pmic/stm32mp_pmic.c \ -+ drivers/st/pmic/stpmic1.c \ +@@ -60,8 +113,11 @@ PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ + drivers/st/iwdg/stm32_iwdg.c \ + drivers/st/pmic/stm32mp_pmic.c \ + drivers/st/pmic/stpmic1.c \ ++ drivers/st/regulator/stm32mp_dummy_regulator.c \ ++ drivers/st/regulator/stm32mp_regulator.c \ drivers/st/reset/stm32mp1_reset.c \ -+ plat/st/common/stm32mp_dt.c \ + plat/st/common/stm32mp_dt.c \ + plat/st/common/stm32mp_shres_helpers.c \ plat/st/stm32mp1/stm32mp1_context.c \ -- plat/st/stm32mp1/stm32mp1_dt.c \ -+ plat/st/stm32mp1/stm32mp1_dbgmcu.c \ + plat/st/stm32mp1/stm32mp1_dbgmcu.c \ plat/st/stm32mp1/stm32mp1_helper.S \ -- plat/st/stm32mp1/stm32mp1_security.c -+ plat/st/stm32mp1/stm32mp1_security.c \ -+ plat/st/stm32mp1/stm32mp1_shared_resources.c +@@ -70,18 +126,64 @@ PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ --BL2_SOURCES += drivers/io/io_dummy.c \ -+BL2_SOURCES += drivers/io/io_block.c \ -+ drivers/io/io_dummy.c \ + BL2_SOURCES += drivers/io/io_block.c \ + drivers/io/io_dummy.c \ ++ drivers/io/io_mtd.c \ drivers/io/io_storage.c \ -- plat/st/stm32mp1/bl2_io_storage.c \ -- plat/st/stm32mp1/bl2_plat_setup.c -+ drivers/st/hash/hash_sec.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 + drivers/st/crypto/stm32_hash.c \ + drivers/st/io/io_stm32image.c \ +- plat/st/common/stm32mp_auth.c \ + plat/st/common/bl2_io_storage.c \ + plat/st/stm32mp1/bl2_plat_setup.c + ++ifeq (${TRUSTED_BOARD_BOOT},1) ++AUTH_SOURCES := drivers/auth/auth_mod.c \ ++ drivers/auth/crypto_mod.c \ ++ drivers/auth/img_parser_mod.c + -+ifeq (${STM32MP1_QSPI_NOR},1) -+BL2_SOURCES += drivers/st/qspi/io_qspi.c -+endif -+ -+ifeq (${STM32MP_FMC_NAND},1) -+BL2_SOURCES += drivers/st/nand/io_nand.c \ -+ drivers/st/nand/nand.c ++BL2_SOURCES += $(AUTH_SOURCES) \ ++ plat/st/common/stm32mp_cot.c \ ++ plat/st/common/stm32mp_crypto_lib.c \ ++ plat/st/common/stm32mp_img_parser_lib.c \ ++ plat/st/common/stm32mp_trusted_boot.c +endif + +ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),) -+BL2_SOURCES += drivers/mmc/mmc.c \ -+ drivers/partition/gpt.c \ -+ drivers/partition/partition.c \ -+ drivers/st/io/io_mmc.c \ -+ drivers/st/mmc/stm32_sdmmc2.c + BL2_SOURCES += drivers/mmc/mmc.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/st/io/io_mmc.c \ + drivers/st/mmc/stm32_sdmmc2.c ++endif ++ ++ifeq (${STM32MP_RAW_NAND},1) ++$(eval $(call add_define_val,NAND_ONFI_DETECT,1)) ++BL2_SOURCES += drivers/mtd/nand/raw_nand.c \ ++ drivers/st/fmc/stm32_fmc2_nand.c ++endif ++ ++ifeq (${STM32MP_SPI_NAND},1) ++BL2_SOURCES += drivers/mtd/nand/spi_nand.c ++endif ++ ++ifeq (${STM32MP_SPI_NOR},1) ++BL2_SOURCES += drivers/mtd/nor/spi_nor.c ++endif ++ ++ifneq ($(filter 1,${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) ++BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \ ++ drivers/st/spi/stm32_qspi.c ++endif ++ ++ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),) ++BL2_SOURCES += drivers/mtd/nand/core.c ++endif ++ ++ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) ++BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c +endif + +ifeq (${STM32MP_UART_PROGRAMMER},1) @@ -38531,86 +38339,113 @@ index 30b2932..06594f0 100644 BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \ drivers/st/ddr/stm32mp1_ram.c -@@ -68,19 +155,36 @@ BL2_SOURCES += common/desc_image_load.c \ +@@ -90,10 +192,22 @@ BL2_SOURCES += common/desc_image_load.c \ plat/st/stm32mp1/plat_bl2_mem_params_desc.c \ plat/st/stm32mp1/plat_image_load.c --# For memory footprint optimization, build with thumb and interwork support --ASFLAGS += -mthumb -mthumb-interwork --TF_CFLAGS += -mthumb -mthumb-interwork -+ifneq (${STM32MP_USB},0) ++ifeq (${STM32MP_USB_PROGRAMMER},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) -+BL2_SOURCES += lib/optee/optee_utils.c -+endif -+ -+ifeq (${STM32MP1_RESET_HALT_WORKAROUND},1) -+BL2_SOURCES += plat/st/stm32mp1/stm32mp1_helper_dbg.S -+endif + ifeq ($(AARCH32_SP),optee) + BL2_SOURCES += lib/optee/optee_utils.c + endif + + +# Do not use neon in TF-A code, it leads to issues in low-power functions +TF_CFLAGS += -mfloat-abi=soft - ++ # Macros and rules to build TF binary STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed --STM32_DT_BASENAME := $(STM32_DTB_FILE_NAME:.dtb=) -+STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=) - STM32_TF_STM32 := ${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32 - STM32_TF_BINARY := $(STM32_TF_STM32:.stm32=.bin) - STM32_TF_MAPFILE := $(STM32_TF_STM32:.stm32=.map) - STM32_TF_LINKERFILE := $(STM32_TF_STM32:.stm32=.ld) - STM32_TF_ELF := $(STM32_TF_STM32:.stm32=.elf) --STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${STM32_DTB_FILE_NAME} -+STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME} + STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=) +@@ -105,16 +219,15 @@ STM32_TF_ELF := $(STM32_TF_STM32:.stm32=.elf) + STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME} STM32_TF_OBJS := ${BUILD_PLAT}/stm32mp1.o +-BL2_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1 +- # Variables for use with stm32image -@@ -123,7 +227,7 @@ ${STM32_TF_OBJS}: plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE - -DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \ - -c plat/st/stm32mp1/stm32mp1.S -o $@ + STM32IMAGEPATH ?= tools/stm32image + STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} ++STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c --${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S -+${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S ${BUILD_PLAT} - @echo " LDS $<" - ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@ +-.PHONY: ${STM32_TF_STM32} ++.PHONY: check_dtc_version stm32image clean_stm32image + .SUFFIXES: -diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c -new file mode 100644 -index 0000000..e4f86a2 ---- /dev/null -+++ b/plat/st/stm32mp1/services/bsec_svc.c -@@ -0,0 +1,460 @@ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ +-all: check_dtc_version ${STM32_TF_STM32} stm32image ++all: check_dtc_version stm32image ${STM32_TF_STM32} + + ifeq ($(AARCH32_SP),sp_min) + # BL32 is built only if using SP_MIN +@@ -124,7 +237,9 @@ endif + + distclean realclean clean: clean_stm32image + +-stm32image: ++stm32image: ${STM32IMAGE} + ++${STM32IMAGE}: ${STM32IMAGE_SRC} + ${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH} + + clean_stm32image: +@@ -161,10 +276,14 @@ ${STM32_TF_BINARY}: ${STM32_TF_ELF} + @echo "Built $@ successfully" + @echo + +-${STM32_TF_STM32}: stm32image ${STM32_TF_BINARY} ++${STM32_TF_STM32}: ${STM32IMAGE} ${STM32_TF_BINARY} + @echo +- @echo "Generated $@" ++ @echo "Generate $@" + $(eval LOADADDR = $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}')) + $(eval ENTRY = $(shell cat ${STM32_TF_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}')) +- ${STM32IMAGE} -s ${STM32_TF_BINARY} -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION} ++ @${STM32IMAGE} -s ${STM32_TF_BINARY} -d $@ \ ++ -l $(LOADADDR) -e ${ENTRY} \ ++ -v ${STM32_TF_VERSION} \ ++ -m ${STM32_HEADER_VERSION_MAJOR} \ ++ -n ${STM32_HEADER_VERSION_MINOR} + @echo +diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c +index 2a60e4339..e75571f98 100644 +--- a/plat/st/stm32mp1/services/bsec_svc.c ++++ b/plat/st/stm32mp1/services/bsec_svc.c +@@ -1,23 +1,451 @@ + /* +- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2020, 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 +#include -+#include -+#include -+#include -+ -+#include "bsec_svc.h" -+ + #include + + #include "bsec_svc.h" + +#define SSP_OTP_REQ BIT(BOOT_API_OTP_SSP_REQ_BIT_POS) +#define SSP_OTP_SUCCESS BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS) +#define SSP_OTP_MASK (SSP_OTP_REQ | SSP_OTP_SUCCESS) @@ -38675,8 +38510,16 @@ index 0000000..e4f86a2 + sizeof(boot_api_ssp_config_t)); +#endif + if (dt_pmic_status() > 0) { ++ const char *name; ++ + initialize_pmic(); -+ stpmic1_regulator_mask_reset_set("buck1"); ++ ++ name = stm32mp_get_cpu_supply_name(); ++ if (name == NULL) { ++ return BSEC_SSP_ERROR; ++ } ++ ++ stpmic1_regulator_mask_reset_set(name); + } + + return BSEC_SSP_SET; @@ -38684,6 +38527,7 @@ index 0000000..e4f86a2 + return BSEC_NO_SSP; +} + ++#if STM32MP_USB_PROGRAMMER || STM32MP_UART_PROGRAMMER +static uint32_t bsec_read_all_bsec(struct otp_exchange *exchange) +{ + uint32_t i; @@ -38885,7 +38729,8 @@ index 0000000..e4f86a2 + + 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; + } + } @@ -38905,7 +38750,8 @@ index 0000000..e4f86a2 + + 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; + } + } @@ -38925,7 +38771,8 @@ index 0000000..e4f86a2 + + 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; + } + } @@ -38956,12 +38803,9 @@ index 0000000..e4f86a2 + (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) { @@ -38972,152 +38816,128 @@ index 0000000..e4f86a2 + + return BSEC_OK; +} ++#endif /* STM32MP_USB_PROGRAMMER || STM32MP_UART_PROGRAMMER */ + -+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, -+ uint32_t *ret_otp_value) -+{ -+ uint32_t result; -+ uint32_t tmp_data = 0U; -+ struct otp_exchange *otp_exch = (struct otp_exchange *)(uintptr_t)x2; + uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t *ret_otp_value) + { + uint32_t result; + uint32_t tmp_data = 0U; ++ struct otp_exchange *otp_exch __unused; ++ uintptr_t map_begin __unused; ++ size_t map_size __unused = PAGE_SIZE; ++ int ret __unused; + + if ((x1 != STM32_SMC_READ_ALL) && (x1 != STM32_SMC_WRITE_ALL) && + (bsec_check_nsec_access_rights(x2) != BSEC_OK)) { -+ return BSEC_ERROR; ++ return STM32_SMC_INVALID_PARAMS; + } + -+ if (((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) && -+ (!ddr_is_nonsecured_area((uintptr_t)x2, -+ sizeof(struct otp_exchange)))) { -+ return BSEC_ERROR; -+ } ++#if STM32MP_USB_PROGRAMMER || STM32MP_UART_PROGRAMMER ++ otp_exch = NULL; ++ map_begin = 0U; + -+ switch (x1) { -+ case STM32_SMC_READ_SHADOW: -+ result = bsec_read_otp(ret_otp_value, x2); -+ break; -+ case STM32_SMC_PROG_OTP: -+ *ret_otp_value = 0U; ++ if ((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) { ++ map_begin = round_down(x2, PAGE_SIZE); ++ ++ if (round_down(x2 + sizeof(struct otp_exchange), PAGE_SIZE) != ++ map_begin) { ++ /* ++ * Buffer end is in the next page, 2 pages need to be ++ * mapped. ++ */ ++ map_size += PAGE_SIZE; ++ } ++ ++ ret = mmap_add_dynamic_region(map_begin, ++ map_begin, ++ map_size, ++ MT_MEMORY | MT_RW | MT_NS); ++ assert(ret == 0); ++ ++ if (!ddr_is_nonsecured_area(map_begin, map_size)) { ++ ret = mmap_remove_dynamic_region(map_begin, map_size); ++ assert(ret == 0); ++ ++ return STM32_SMC_INVALID_PARAMS; ++ } ++ ++ otp_exch = (struct otp_exchange *)(uintptr_t)x2; ++ } ++#endif + + switch (x1) { + case STM32_SMC_READ_SHADOW: +@@ -25,6 +453,18 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + break; + case STM32_SMC_PROG_OTP: + *ret_otp_value = 0U; + if (x2 == BOOT_API_OTP_SSP_WORD_NB) { + result = bsec_read_otp(&tmp_data, x2); + if (result != BSEC_OK) { + 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; + } + } -+ result = bsec_program_otp(x3, x2); -+ break; -+ case STM32_SMC_WRITE_SHADOW: -+ *ret_otp_value = 0; -+ result = bsec_write_otp(x3, x2); -+ break; -+ case STM32_SMC_READ_OTP: -+ *ret_otp_value = 0; -+ result = bsec_read_otp(&tmp_data, x2); -+ if (result != BSEC_OK) { -+ break; -+ } -+ -+ result = bsec_shadow_register(x2); -+ if (result != BSEC_OK) { -+ break; -+ } -+ -+ result = bsec_read_otp(ret_otp_value, x2); -+ if (result != BSEC_OK) { -+ break; -+ } -+ -+ result = bsec_write_otp(tmp_data, x2); -+ break; + result = bsec_program_otp(x3, x2); + break; + case STM32_SMC_WRITE_SHADOW: +@@ -50,11 +490,27 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + + result = bsec_write_otp(tmp_data, x2); + break; +- +- default: +- result = BSEC_ERROR; ++#if STM32MP_USB_PROGRAMMER || STM32MP_UART_PROGRAMMER + case STM32_SMC_READ_ALL: + result = bsec_read_all_bsec(otp_exch); + break; + case STM32_SMC_WRITE_ALL: + result = bsec_write_all_bsec(otp_exch, ret_otp_value); + break; ++#endif ++ case STM32_SMC_WRLOCK_OTP: ++ result = bsec_permanent_lock_otp(x2); + break; + default: -+ result = BSEC_ERROR; -+ break; ++ return STM32_SMC_INVALID_PARAMS; + } + -+ return result; -+} -diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h -new file mode 100644 -index 0000000..75c9aa3 ---- /dev/null -+++ b/plat/st/stm32mp1/services/bsec_svc.h -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (c) 2016-2017, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef BSEC_SVC_H -+#define BSEC_SVC_H -+ -+#include -+#include -+#include -+ -+/* version of this service */ -+/* must be increase at each structure modification */ -+#define BSEC_SERVICE_VERSION 0x01U -+ -+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, -+ uint32_t *ret_otp_value); -+ -+#endif /* BSEC_SVC_H */ ++#if STM32MP_USB_PROGRAMMER || STM32MP_UART_PROGRAMMER ++ if ((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) { ++ ret = mmap_remove_dynamic_region(map_begin, map_size); ++ assert(ret == 0); + } ++#endif + +- return result; ++ return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED; + } diff --git a/plat/st/stm32mp1/services/low_power_svc.c b/plat/st/stm32mp1/services/low_power_svc.c new file mode 100644 -index 0000000..a7fe026 +index 000000000..567a3c70f --- /dev/null +++ b/plat/st/stm32mp1/services/low_power_svc.c -@@ -0,0 +1,46 @@ +@@ -0,0 +1,22 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include -+#include ++ +#include +#include ++ +#include "low_power_svc.h" + -+uint32_t sr_mode_scv_handler(uint32_t x1, uint32_t x2) -+{ -+ uint32_t ret = STM32_SMC_OK; -+ -+ switch (x2) { -+ case STM32_SMC_SR_MODE_SSR: -+ ddr_sr_mode_ssr(); -+ break; -+ -+ case STM32_SMC_SR_MODE_ASR: -+ ddr_sr_mode_asr(); -+ break; -+ -+ case STM32_SMC_SR_MODE_HSR: -+ ddr_sr_mode_hsr(); -+ break; -+ -+ default: -+ ret = STM32_SMC_INVALID_PARAMS; -+ break; -+ } -+ -+ return ret; -+} -+ +uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2) +{ + if (stm32mp1_set_pm_domain_state((enum stm32mp1_pm_domain)x1, @@ -39129,12 +38949,12 @@ index 0000000..a7fe026 +} diff --git a/plat/st/stm32mp1/services/low_power_svc.h b/plat/st/stm32mp1/services/low_power_svc.h new file mode 100644 -index 0000000..1264fa1 +index 000000000..eb98e9225 --- /dev/null +++ b/plat/st/stm32mp1/services/low_power_svc.h -@@ -0,0 +1,15 @@ +@@ -0,0 +1,14 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -39144,62 +38964,39 @@ index 0000000..1264fa1 + +#include + -+uint32_t sr_mode_scv_handler(uint32_t x1, uint32_t x2); +uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2); + +#endif /* LOW_POWER_SVC_H */ diff --git a/plat/st/stm32mp1/services/pwr_svc.c b/plat/st/stm32mp1/services/pwr_svc.c new file mode 100644 -index 0000000..80dcc7c +index 000000000..1213d7ef6 --- /dev/null +++ b/plat/st/stm32mp1/services/pwr_svc.c -@@ -0,0 +1,124 @@ +@@ -0,0 +1,102 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + -+#include -+#include -+#include +#include -+#include ++ ++#include ++#include ++#include ++ +#include -+#include +#include ++ +#include "pwr_svc.h" + -+static struct spinlock lock; -+ -+void pwr_regs_lock(void) -+{ -+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT; -+ -+ /* Lock is currently required only when MMU and cache are enabled */ -+ if ((read_sctlr() & mask) == mask) { -+ spin_lock(&lock); -+ } -+} -+ -+void pwr_regs_unlock(void) -+{ -+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT; -+ -+ /* Unlock is required only when MMU and cache are enabled */ -+ if ((read_sctlr() & mask) == mask) { -+ spin_unlock(&lock); -+ } -+} -+ +static void access_allowed_mask(uint32_t request, uint32_t offset, + uint32_t value, uint32_t allowed_mask) +{ + uint32_t addr = stm32mp_pwr_base() + offset; + uint32_t masked_value = value & allowed_mask; + -+ pwr_regs_lock(); ++ stm32mp_pwr_regs_lock(); + + switch (request) { + case STM32_SMC_REG_WRITE: @@ -39224,7 +39021,7 @@ index 0000000..80dcc7c + break; + } + -+ pwr_regs_unlock(); ++ stm32mp_pwr_regs_unlock(); +} + +static void raw_allowed_access_request(uint32_t request, @@ -39280,13 +39077,12 @@ index 0000000..80dcc7c +} diff --git a/plat/st/stm32mp1/services/pwr_svc.h b/plat/st/stm32mp1/services/pwr_svc.h new file mode 100644 -index 0000000..90cf1a3 +index 000000000..6dacdf80d --- /dev/null +++ b/plat/st/stm32mp1/services/pwr_svc.h -@@ -0,0 +1,13 @@ +@@ -0,0 +1,12 @@ +/* -+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -39299,142 +39095,37 @@ index 0000000..90cf1a3 +#endif /* PWR_SVC_H */ diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c new file mode 100644 -index 0000000..1df6903 +index 000000000..640816fca --- /dev/null +++ b/plat/st/stm32mp1/services/rcc_svc.c -@@ -0,0 +1,477 @@ +@@ -0,0 +1,172 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-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 "rcc_svc.h" + -+#define STD_REG 0 -+#define SET_REG 1 -+#define CLR_REG 2 -+ -+static void shared_clk_request(uint32_t request, -+ uint32_t offset, uint32_t value) ++static bool offset_is_clear_register(uint32_t __unused offset) +{ -+ unsigned long id; -+ unsigned int bit; -+ uint32_t enable_bits = 0; -+ int clr_std_set = STD_REG; -+ -+ switch (request) { -+ case STM32_SMC_REG_WRITE: -+ case STM32_SMC_REG_SET: -+ case STM32_SMC_REG_CLEAR: -+ break; -+ default: -+ return; -+ } -+ -+ switch (offset) { -+ case RCC_MP_APB5ENSETR: -+ clr_std_set = SET_REG; -+ /* Non secure backup registers requires RTCAPB clock */ -+ enable_bits |= RCC_MP_APB5ENSETR_RTCAPBEN; -+ break; -+ case RCC_MP_APB5ENCLRR: -+ clr_std_set = CLR_REG; -+ /* Non secure backup registers requires RTCAPB clock */ -+ enable_bits |= RCC_MP_APB5ENSETR_RTCAPBEN; -+ break; -+ -+ case RCC_MP_AHB5ENSETR: -+ clr_std_set = SET_REG; -+ if (stm32mp_gpio_bank_is_shared(GPIO_BANK_Z)) { -+ enable_bits |= RCC_MP_AHB5ENSETR_GPIOZEN; -+ } -+ break; -+ case RCC_MP_AHB5ENCLRR: -+ clr_std_set = CLR_REG; -+ if (stm32mp_gpio_bank_is_shared(GPIO_BANK_Z)) { -+ enable_bits |= RCC_MP_AHB5ENSETR_GPIOZEN; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if ((clr_std_set != STD_REG) && (request == STM32_SMC_REG_CLEAR)) { -+ return; -+ } -+ -+ /* -+ * Parse bit that relate to a functional clock. -+ * Call stm32mp1_clk_enable/disable_non_secure() for that clock -+ * according to request (write/set/clear) and target register -+ * (write or set/clear). -+ */ -+ for (bit = 0; bit < __WORD_BIT; bit++) { -+ -+ if ((BIT(bit) & enable_bits) == 0U) { -+ continue; -+ } -+ -+ id = stm32mp1_clk_rcc2id(offset, bit); -+ if (id == ~0U) { -+ panic(); -+ } -+ -+ switch (clr_std_set) { -+ case SET_REG: -+ if ((BIT(bit) & value) != 0U) { -+ stm32mp1_clk_enable_non_secure(id); -+ } -+ break; -+ case CLR_REG: -+ if ((BIT(bit) & value) != 0U) { -+ stm32mp1_clk_disable_non_secure(id); -+ } -+ break; -+ default: -+ /* Standard registers case */ -+ switch (request) { -+ case STM32_SMC_REG_WRITE: -+ if ((BIT(bit) & value) != 0U) { -+ stm32mp1_clk_enable_non_secure(id); -+ } else { -+ stm32mp1_clk_disable_non_secure(id); -+ } -+ break; -+ case STM32_SMC_REG_SET: -+ if ((BIT(bit) & value) != 0U) { -+ stm32mp1_clk_enable_non_secure(id); -+ } -+ break; -+ case STM32_SMC_REG_CLEAR: -+ if ((BIT(bit) & value) != 0U) { -+ stm32mp1_clk_disable_non_secure(id); -+ } -+ break; -+ default: -+ return; -+ } -+ break; -+ } -+ -+ enable_bits &= ~BIT(bit); -+ if (enable_bits == 0U) { -+ break; -+ } -+ } ++ /* All currently allowed registers are non set/clear registers */ ++ return false; +} + +static void access_allowed_mask(uint32_t request, uint32_t offset, @@ -39445,66 +39136,31 @@ index 0000000..1df6903 + + switch (request) { + case STM32_SMC_REG_WRITE: -+ switch (offset) { -+ /* CLR registers show the SET state, not the CLR state */ -+ case RCC_OCENCLRR: -+ case RCC_MP_SREQCLRR: -+ case RCC_APB5RSTCLRR: -+ case RCC_AHB5RSTCLRR: -+ case RCC_MP_APB5ENCLRR: -+ case RCC_MP_AHB5ENCLRR: -+ case RCC_MP_APB5LPENCLRR: -+ case RCC_MP_AHB5LPENCLRR: -+ case RCC_MP_IWDGFZCLRR: ++ if (offset_is_clear_register(offset)) { + mmio_write_32(addr, masked_value); -+ break; -+ default: ++ } else { + stm32mp_mmio_clrsetbits_32_shregs(addr, allowed_mask, + masked_value); -+ break; + } + VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value, + mmio_read_32(addr)); + break; + + case STM32_SMC_REG_SET: -+ switch (offset) { -+ /* CLR registers show the SET state, not the CLR state */ -+ case RCC_OCENCLRR: -+ case RCC_MP_SREQCLRR: -+ case RCC_APB5RSTCLRR: -+ case RCC_AHB5RSTCLRR: -+ case RCC_MP_APB5ENCLRR: -+ case RCC_MP_AHB5ENCLRR: -+ case RCC_MP_APB5LPENCLRR: -+ case RCC_MP_AHB5LPENCLRR: -+ case RCC_MP_IWDGFZCLRR: ++ if (offset_is_clear_register(offset)) { + mmio_write_32(addr, masked_value); -+ break; -+ default: ++ } else { + stm32mp_mmio_setbits_32_shregs(addr, masked_value); -+ break; + } + VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value, + mmio_read_32(addr)); + break; + + case STM32_SMC_REG_CLEAR: -+ switch (offset) { -+ case RCC_OCENCLRR: -+ case RCC_MP_SREQCLRR: -+ case RCC_APB5RSTCLRR: -+ case RCC_AHB5RSTCLRR: -+ case RCC_MP_APB5ENCLRR: -+ case RCC_MP_AHB5ENCLRR: -+ case RCC_MP_APB5LPENCLRR: -+ case RCC_MP_AHB5LPENCLRR: -+ case RCC_MP_IWDGFZCLRR: ++ if (offset_is_clear_register(offset)) { + /* Nothing to do on CLR registers */ -+ break; -+ default: ++ } else { + stm32mp_mmio_clrbits_32_shregs(addr, masked_value); -+ break; + } + VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value, + mmio_read_32(addr)); @@ -39520,208 +39176,16 @@ index 0000000..1df6903 +{ + uint32_t allowed_mask = 0; + -+ /* Use UINT32_MAX if no secure restriction on register access */ + switch (offset) { -+ case RCC_OCENSETR: -+ case RCC_OCENCLRR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSI)) { -+ allowed_mask |= RCC_OCENR_HSION | RCC_OCENR_HSIKERON; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CSI)) { -+ allowed_mask |= RCC_OCENR_CSION | RCC_OCENR_CSIKERON; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSE)) { -+ allowed_mask |= RCC_OCENR_HSEON | RCC_OCENR_HSEKERON | -+ RCC_OCENR_HSEBYP | RCC_OCENR_HSECSSON | -+ RCC_OCENR_DIGBYP; -+ } -+ break; -+ -+ case RCC_HSICFGR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSI)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ -+ case RCC_CSICFGR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CSI)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ + case RCC_MP_CIER: + case RCC_MP_CIFR: -+ /* RCC_MP_CIFR_xxxRDYF matches CIER and CIFR bit mapping */ -+ allowed_mask |= RCC_MP_CIFR_WKUPF | RCC_MP_CIFR_PLL4DYF; -+ -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_LSI)) { -+ allowed_mask |= RCC_MP_CIFR_LSIRDYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_LSE)) { -+ allowed_mask |= RCC_MP_CIFR_LSERDYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSI)) { -+ allowed_mask |= RCC_MP_CIFR_HSIRDYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSE)) { -+ allowed_mask |= RCC_MP_CIFR_HSERDYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CSI)) { -+ allowed_mask |= RCC_MP_CIFR_CSIRDYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1)) { -+ allowed_mask |= RCC_MP_CIFR_PLL1DYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2)) { -+ allowed_mask |= RCC_MP_CIFR_PLL2DYF; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3)) { -+ allowed_mask |= RCC_MP_CIFR_PLL3DYF; -+ } ++ allowed_mask = RCC_MP_CIFR_WKUPF; + break; -+ -+ case RCC_PLL1CR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1_P)) { -+ allowed_mask |= RCC_PLLNCR_DIVPEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1_Q)) { -+ allowed_mask |= RCC_PLLNCR_DIVQEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1_R)) { -+ allowed_mask |= RCC_PLLNCR_DIVREN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1)) { -+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY | -+ RCC_PLLNCR_SSCG_CTRL; -+ } -+ break; -+ -+ case RCC_PLL2CR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2_P)) { -+ allowed_mask |= RCC_PLLNCR_DIVPEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2_Q)) { -+ allowed_mask |= RCC_PLLNCR_DIVQEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2_R)) { -+ allowed_mask |= RCC_PLLNCR_DIVREN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2)) { -+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY | -+ RCC_PLLNCR_SSCG_CTRL; -+ } -+ break; -+ -+ case RCC_PLL3CR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3_P)) { -+ allowed_mask |= RCC_PLLNCR_DIVPEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3_Q)) { -+ allowed_mask |= RCC_PLLNCR_DIVQEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3_R)) { -+ allowed_mask |= RCC_PLLNCR_DIVREN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3)) { -+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY | -+ RCC_PLLNCR_SSCG_CTRL; -+ } -+ break; -+ -+ case RCC_MP_BOOTCR: /* Allowed MPU/MCU reboot cfg */ -+ case RCC_MP_GCR: /* Allowed MPU/MCU reboot cfg */ -+ case RCC_MP_GRSTCSETR: /* Allowed MCU and system reset */ -+ case RCC_BR_RSTSCLRR: /* Allowed system reset status */ -+ case RCC_MC_RSTSCLRR: /* Allowed system reset status */ -+ case RCC_MP_RSTSCLRR: /* Allowed system reset status */ -+ allowed_mask = UINT32_MAX; -+ break; -+ case RCC_APB5RSTSETR: -+ case RCC_APB5RSTCLRR: -+ case RCC_MP_APB5ENSETR: -+ case RCC_MP_APB5ENCLRR: -+ case RCC_MP_APB5LPENSETR: -+ case RCC_MP_APB5LPENCLRR: -+ /* -+ * SPI6/I2C4/I2C6/USART1/IWDG1 resources may be non secure. -+ * TZPC/TZC/BSEC/STGEN resources are secure only. -+ * Bit mask RCC_MP_APB5ENSETR_xxxEN fits EN, RST and LPEN. -+ */ -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_SPI6)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_SPI6EN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C4)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_I2C4EN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C6)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_I2C6EN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_USART1)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_USART1EN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_IWDG1)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_IWDG1APBEN; -+ } -+ break; -+ case RCC_AHB5RSTSETR: -+ case RCC_AHB5RSTCLRR: -+ case RCC_MP_AHB5ENSETR: -+ case RCC_MP_AHB5ENCLRR: -+ case RCC_MP_AHB5LPENSETR: -+ case RCC_MP_AHB5LPENCLRR: -+ /* -+ * RNG1/HASH1/CRYP1/GPIOZ resources are accessible if -+ * related BKPSRAM resources are reserved to secure services. -+ * Bit mask RCC_MP_AHB5ENSETR_xxxEN fits EN, RST and LPEN. -+ */ -+ if (stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_GPIOZEN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CRYP1)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_CRYP1EN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HASH1)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_HASH1EN; -+ } -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_RNG1)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_RNG1EN; -+ } -+ break; -+ case RCC_RTCDIVR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_RTC)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_I2C46CKSELR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C4) && -+ stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C6)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_SPI6CKSELR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_SPI6)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_UART1CKSELR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_USART1)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_RNG1CKSELR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_RNG1)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_MP_IWDGFZSETR: -+ case RCC_MP_IWDGFZCLRR: -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_IWDG1)) { -+ allowed_mask |= RCC_MP_IWDGFZSETR_IWDG1; -+ } -+ allowed_mask |= RCC_MP_IWDGFZSETR_IWDG2; ++ case RCC_MP_GCR: ++ allowed_mask = RCC_MP_GCR_BOOT_MCU; + break; + default: -+ return; ++ panic(); + } + + if (allowed_mask != 0U) { @@ -39747,10 +39211,6 @@ index 0000000..1df6903 + offset &= RCC_OFFSET_MASK; + } + -+ /* Some clocks may be managed by some secure services */ -+ shared_clk_request(request, offset, value); -+ -+ /* RCC controls for non secure resource may be accessed straight */ + raw_allowed_access_request(request, offset, value); + + return STM32_SMC_OK; @@ -39762,13 +39222,13 @@ index 0000000..1df6903 + + 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; @@ -39780,15 +39240,45 @@ index 0000000..1df6903 + + return ret; +} ++ ++uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res) ++{ ++ uint32_t cmd = x1; ++ uint32_t opp = x2 / 1000U; /* KHz */ ++ ++ switch (cmd) { ++ case STM32_SMC_RCC_OPP_SET: ++ if (stm32mp1_set_opp_khz(opp) != 0) { ++ return STM32_SMC_FAILED; ++ } ++ break; ++ ++ case STM32_SMC_RCC_OPP_ROUND: ++ if (stm32mp1_round_opp_khz(&opp) != 0) { ++ return STM32_SMC_FAILED; ++ } ++ ++ if (opp > (UINT32_MAX / 1000U)) { ++ return STM32_SMC_FAILED; ++ } ++ ++ *res = opp * 1000U; ++ break; ++ ++ default: ++ return STM32_SMC_INVALID_PARAMS; ++ } ++ ++ return STM32_SMC_OK; ++} diff --git a/plat/st/stm32mp1/services/rcc_svc.h b/plat/st/stm32mp1/services/rcc_svc.h new file mode 100644 -index 0000000..75d4a3c +index 000000000..23c75824f --- /dev/null +++ b/plat/st/stm32mp1/services/rcc_svc.h @@ -0,0 +1,14 @@ +/* -+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ @@ -39798,82 +39288,41 @@ index 0000000..75d4a3c + +uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); +uint32_t rcc_cal_scv_handler(uint32_t x1); ++uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res); + +#endif /* RCC_SVC_H */ diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -new file mode 100644 -index 0000000..fff91c0 ---- /dev/null +index 72af9ff33..b2a84c15e 100644 +--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c +++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (c) 2014-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "bsec_svc.h" +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2014-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -9,12 +9,16 @@ + + #include + #include ++#include + #include + #include + + #include + + #include "bsec_svc.h" +#include "low_power_svc.h" +#include "pwr_svc.h" +#include "rcc_svc.h" -+ -+/* STM32 SiP Service UUID */ -+DEFINE_SVC_UUID2(stm32_sip_svc_uid, -+ 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e, -+ 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14); -+ -+/* Setup STM32MP1 Standard Services */ -+static int32_t stm32mp1_svc_setup(void) -+{ -+ /* -+ * PSCI is the only specification implemented as a Standard Service. -+ * Invoke PSCI setup from here. -+ */ -+ return 0; -+} -+ -+/* -+ * Top-level Standard Service SMC handler. This handler will in turn dispatch -+ * calls to PSCI SMC handler. -+ */ -+static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1, -+ u_register_t x2, u_register_t x3, -+ u_register_t x4, void *cookie, -+ void *handle, u_register_t flags) -+{ -+ uint32_t ret1 = 0U, ret2 = 0U; -+ bool ret_uid = false, ret2_enabled = false; -+ -+ switch (smc_fid) { -+ case STM32_SIP_SVC_CALL_COUNT: -+ ret1 = STM32_COMMON_SIP_NUM_CALLS; -+ break; -+ -+ case STM32_SIP_SVC_UID: -+ /* Return UUID to the caller */ -+ ret_uid = true; -+ break; -+ -+ case STM32_SIP_SVC_VERSION: -+ /* Return the version of current implementation */ -+ ret1 = STM32_SIP_SVC_VERSION_MAJOR; -+ ret2 = STM32_SIP_SVC_VERSION_MINOR; -+ ret2_enabled = true; -+ break; -+ -+ case STM32_SMC_BSEC: -+ ret1 = bsec_main(x1, x2, x3, &ret2); -+ ret2_enabled = true; -+ break; -+ + + /* STM32 SiP Service UUID */ + DEFINE_SVC_UUID2(stm32_sip_svc_uid, +@@ -65,9 +69,39 @@ static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1, + ret2_enabled = true; + break; + + case STM32_SMC_RCC: + ret1 = rcc_scv_handler(x1, x2, x3); + break; @@ -39882,51 +39331,51 @@ index 0000000..fff91c0 + ret1 = rcc_cal_scv_handler(x1); + break; + -+ case STM32_SMC_PWR: -+ ret1 = pwr_scv_handler(x1, x2, x3); ++ case STM32_SMC_RCC_OPP: ++ ret1 = rcc_opp_scv_handler(x1, x2, &ret2); ++ ret2_enabled = true; + break; + -+ case STM32_SMC_SR_MODE: -+ ret1 = sr_mode_scv_handler(x1, x2); ++ case STM32_SMC_PWR: ++ ret1 = pwr_scv_handler(x1, x2, x3); + break; + + case STM32_SMC_PD_DOMAIN: + ret1 = pm_domain_scv_handler(x1, x2); + break; + -+ default: -+ WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid); -+ ret1 = SMC_UNK; ++ case STM32_SMC_SCMI_MESSAGE_AGENT0: ++ scmi_smt_fastcall_smc_entry(0U); ++ ret1 = STM32_SMC_OK; ++ break; ++ case STM32_SMC_SCMI_MESSAGE_AGENT1: ++ scmi_smt_fastcall_smc_entry(1U); ++ ret1 = STM32_SMC_OK; + break; -+ } + -+ if (ret_uid) { -+ SMC_UUID_RET(handle, stm32_sip_svc_uid); -+ } -+ -+ if (ret2_enabled) { -+ SMC_RET2(handle, ret1, ret2); -+ } -+ -+ SMC_RET1(handle, ret1); -+} -+ -+/* Register Standard Service Calls as runtime service */ -+DECLARE_RT_SVC(stm32mp1_sip_svc, -+ OEN_SIP_START, -+ OEN_SIP_END, -+ SMC_TYPE_FAST, -+ stm32mp1_svc_setup, -+ stm32mp1_svc_smc_handler -+); + default: + WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid); +- ret1 = SMC_UNK; ++ ret1 = STM32_SMC_NOT_SUPPORTED; + break; + } + diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -index 9fde153..322d389 100644 +index 4188cc58a..2ab8e8d4b 100644 --- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -@@ -7,8 +7,15 @@ +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -7,19 +7,39 @@ 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 \ @@ -39936,69 +39385,104 @@ index 9fde153..322d389 100644 + plat/st/stm32mp1/stm32mp1_low_power.c \ plat/st/stm32mp1/stm32mp1_pm.c \ + plat/st/stm32mp1/stm32mp1_power_config.c \ ++ plat/st/stm32mp1/stm32mp1_shared_resources.c \ plat/st/stm32mp1/stm32mp1_topology.c # Generic GIC v2 BL32_SOURCES += drivers/arm/gic/common/gic_common.c \ -@@ -19,3 +26,10 @@ BL32_SOURCES += drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicv2_main.c \ + plat/common/plat_gicv2.c \ +- plat/st/stm32mp1/stm32mp1_gic.c ++ plat/st/common/stm32_gic.c # Generic PSCI BL32_SOURCES += plat/common/plat_psci_common.c -+ -+# stm32mp1 specific services -+BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \ + + # stm32mp1 specific services + BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \ + plat/st/stm32mp1/services/low_power_svc.c \ + plat/st/stm32mp1/services/pwr_svc.c \ + plat/st/stm32mp1/services/rcc_svc.c \ -+ plat/st/stm32mp1/services/stm32mp1_svc_setup.c + plat/st/stm32mp1/services/stm32mp1_svc_setup.c ++ ++# SCMI server ++BL32_SOURCES += drivers/st/scmi-msg/base.c \ ++ drivers/st/scmi-msg/clock.c \ ++ drivers/st/scmi-msg/entry.c \ ++ drivers/st/scmi-msg/reset_domain.c \ ++ drivers/st/scmi-msg/smt.c \ ++ plat/st/stm32mp1/stm32mp1_scmi.c diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c -index 56598c8..e8dc409 100644 +index e10dfbfc0..f57630604 100644 --- a/plat/st/stm32mp1/sp_min/sp_min_setup.c +++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c -@@ -7,19 +7,32 @@ - #include - #include - #include --#include -+#include - #include - #include - #include +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -17,10 +17,19 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include + #include ++#include ++#include #include -+#include - #include -+#include - #include - #include - #include + #include + #include +@@ -28,6 +37,7 @@ + #include + #include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - #include --#include -+#include +#include - #include -+#include - #include - #include - #include -@@ -30,22 +43,107 @@ - ******************************************************************************/ + + /****************************************************************************** + * Placeholder variables for copying the arguments that have been passed to +@@ -36,23 +46,168 @@ static entry_point_info_t bl33_image_ep_info; -+static struct console_stm32 console; + static struct console_stm32 console; ++static void stm32mp1_tamper_action(int id); ++ ++static const char *tamper_name[PLAT_MAX_TAMP_INT] = { ++ "RTC power domain", ++ "Temperature monitoring", ++ "LSE monitoring", ++ "HSE monitoring", ++ "RTC calendar overflow", ++ "Monotonic counter" ++}; + +static struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT] = { -+ TAMP_UNUSED, -+ TAMP_UNUSED, -+ TAMP_UNUSED, ++ { ++ .id = ITAMP1, ++ .func = stm32mp1_tamper_action, ++ }, ++ { ++ .id = ITAMP2, ++ .func = stm32mp1_tamper_action, ++ }, ++ { ++ .id = ITAMP3, ++ .func = stm32mp1_tamper_action, ++ }, ++ { ++ .id = ITAMP4, ++ .func = stm32mp1_tamper_action, ++ }, + TAMP_UNUSED, + TAMP_UNUSED, +}; @@ -40018,6 +39502,8 @@ index 56598c8..e8dc409 100644 +{ + uint32_t id; + ++ stm32mp_mask_timer(); ++ + gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_1); + + do { @@ -40030,32 +39516,68 @@ index 56598c8..e8dc409 100644 + } + } while (id <= MAX_SPI_ID); + -+ -+ isb(); -+ dsb(); -+ -+ /* Flush L1/L2 data caches */ -+ write_sctlr(read_sctlr() & ~SCTLR_C_BIT); -+ dcsw_op_all(DC_OP_CISW); -+ -+ for ( ; ; ) { -+ wfi(); -+ } ++ stm32mp_wait_cpu_reset(); +} + ++static void stm32mp1_tamper_action(int id) ++{ ++ ERROR("Tamper %s occurs\n", tamper_name[id]); ++ stm32mp_plat_reset(plat_my_core_pos()); ++} ++ ++static void configure_wakeup_interrupt(void) ++{ ++ int irq_num = fdt_rcc_enable_it("wakeup"); ++ ++ if (irq_num < 0) { ++ ERROR("irq_num = %d\n", irq_num); ++ panic(); ++ } ++ ++ plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO); ++} ++ ++static void initialize_pll1_settings(void) ++{ ++ uint32_t cpu_voltage = 0U; ++ ++ if (stm32_are_pll1_settings_valid_in_context()) { ++ return; ++ } ++ ++ if (dt_pmic_status() > 0) { ++ const char *name = stm32mp_get_cpu_supply_name(); ++ int ret; ++ ++ if (name == NULL) { ++ panic(); ++ } ++ ++ ret = stpmic1_regulator_voltage_get(name); ++ if (ret < 0) { ++ panic(); ++ } ++ ++ cpu_voltage = (uint32_t)ret; ++ } ++ ++ if (stm32mp1_clk_compute_all_pll1_settings(cpu_voltage) != 0) { ++ panic(); ++ } ++} + /******************************************************************************* * Interrupt handler for FIQ (secure IRQ) ******************************************************************************/ void sp_min_plat_fiq_handler(uint32_t id) { -- switch (id) { + uint32_t value = 0; + -+ switch (id & INT_ID_MASK) { + switch (id & INT_ID_MASK) { + 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: - ERROR("STM32MP1_IRQ_TZC400 generated\n"); @@ -40095,12 +39617,12 @@ index 56598c8..e8dc409 100644 panic(); break; default: -- ERROR("SECURE IT handler not define for it : %i", id); -+ ERROR("SECURE IT handler not define for it : %u", id); +- ERROR("SECURE IT handler not define for it : %u", id); ++ ERROR("SECURE IT handler not define for it : %u\n", id); break; } } -@@ -59,11 +157,54 @@ void sp_min_plat_fiq_handler(uint32_t id) +@@ -66,22 +221,99 @@ void sp_min_plat_fiq_handler(uint32_t id) entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) { entry_point_info_t *next_image_info; @@ -40156,69 +39678,97 @@ index 56598c8..e8dc409 100644 } return next_image_info; -@@ -75,6 +216,9 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) + } + ++CASSERT((STM32MP_SEC_SYSRAM_BASE >= STM32MP_SYSRAM_BASE) && ++ ((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <= ++ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)), ++ assert_secure_sysram_fits_into_sysram); ++ ++#ifdef STM32MP_NS_SYSRAM_BASE ++CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) && ++ ((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) == ++ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)), ++ assert_non_secure_sysram_fits_at_end_of_sysram); ++ ++CASSERT((STM32MP_NS_SYSRAM_BASE & GENMASK(11, 0)) == 0, ++ assert_non_secure_sysram_base_is_4kbyte_aligned); ++ ++/* Last 4kByte page (12 bit wide) of SYSRAM is non-secure */ ++#define TZMA1_SECURE_RANGE \ ++ (((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> 12) - 1U) ++#else ++/* STM32MP_NS_SYSRAM_BASE not defined means all SYSRAM is secure */ ++#define TZMA1_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE ++#endif /* STM32MP_NS_SYSRAM_BASE */ ++ ++#define TZMA0_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE ++ ++static void stm32mp1_etzpc_early_setup(void) ++{ ++ etzpc_init(); ++ etzpc_configure_tzma(0U, TZMA0_SECURE_RANGE); ++ etzpc_configure_tzma(1U, TZMA1_SECURE_RANGE); ++} ++ + /******************************************************************************* + * Perform any BL32 specific platform actions. + ******************************************************************************/ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { +#if STM32MP_UART_PROGRAMMER + uint32_t boot_itf, boot_instance; +#endif - struct dt_node_info dt_dev_info; + struct dt_node_info dt_uart_info; int result; bl_params_t *params_from_bl2 = (bl_params_t *)arg0; -@@ -105,18 +249,78 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, +@@ -126,9 +358,22 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, panic(); } -+ if (bsec_probe() != 0) { ++ if (etzpc_init() != 0) { + panic(); + } + - if (stm32mp1_clk_probe() < 0) { - panic(); - } - -+ /* Initialize uart for console except if it is used by programmer */ - result = dt_get_stdout_uart_info(&dt_dev_info); ++ stm32mp1_etzpc_early_setup(); ++ + result = dt_get_stdout_uart_info(&dt_uart_info); +#if STM32MP_UART_PROGRAMMER + stm32_get_boot_interface(&boot_itf, &boot_instance); -+ if ((result > 0) && dt_dev_info.status && ++ if ((result > 0) && (dt_uart_info.status != 0U) && + !((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) && -+ (get_uart_address(boot_instance) == dt_dev_info.base))) { ++ (get_uart_address(boot_instance) == dt_uart_info.base))) { +#else - if ((result > 0) && dt_dev_info.status) { -- if (console_init(dt_dev_info.base, 0, STM32MP1_UART_BAUDRATE) -- == 0) { + if ((result > 0) && (dt_uart_info.status != 0U)) { +#endif -+ if (console_stm32_register(dt_dev_info.base, 0, -+ STM32MP_UART_BAUDRATE, &console) == -+ 0) { - panic(); - } + unsigned int console_flags; + + if (console_stm32_register(dt_uart_info.base, 0, +@@ -144,6 +389,50 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + #endif + console_set_scope(&console.console, console_flags); } + + if (dt_pmic_status() > 0) { + initialize_pmic(); + } + ++ initialize_pll1_settings(); ++ + stm32mp1_init_lp_states(); +} + +/******************************************************************************* + * Set security setup in sp_min + ******************************************************************************/ -+void stm32mp1_sp_min_security_setup(void) ++static void stm32mp1_sp_min_security_setup(void) +{ + uint32_t filter_conf = 0; + uint32_t active_conf = 0; + int ret; + -+ if (etzpc_init() != 0) { -+ ERROR("ETZPC configuration issue\n"); -+ panic(); -+ } -+ + /* Init rtc driver */ + ret = stm32_rtc_init(); + if (ret < 0) { @@ -40242,256 +39792,252 @@ index 56598c8..e8dc409 100644 + } + + if (stm32_timer_init() == 0) { -+ stm32mp1_cal_init(); ++ stm32mp1_calib_init(); + } } /******************************************************************************* -@@ -128,6 +332,16 @@ void sp_min_platform_setup(void) - 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 +@@ -151,26 +440,27 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + ******************************************************************************/ + void sp_min_platform_setup(void) + { ++ ddr_save_sr_mode(); + -+ 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 */ -@@ -136,8 +350,21 @@ void sp_min_platform_setup(void) + stm32mp1_security_setup(); + generic_delay_timer_init(); - stm32mp1_gic_init(); -+ +- stm32mp1_gic_init(); ++ stm32_gic_init(); + +- /* Unlock ETZPC securable peripherals */ +-#define STM32MP1_ETZPC_BASE 0x5C007000U +-#define ETZPC_DECPROT0 0x010U +- mmio_write_32(STM32MP1_ETZPC_BASE + ETZPC_DECPROT0, 0xFFFFFFFF); +- +- /* Set GPIO bank Z as non secure */ +- for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) { +- set_gpio_secure_cfg(GPIO_BANK_Z, pin, false); +- } + /* Update security settings */ + stm32mp1_sp_min_security_setup(); + + if (stm32_iwdg_init() < 0) { + panic(); + } + -+ if (stm32_iwdg_init() < 0) { -+ panic(); -+ } ++ configure_wakeup_interrupt(); + -+ stm32mp1_driver_init_late(); ++ stm32mp_lock_periph_registering(); ++ ++ stm32mp1_init_scmi_server(); } void sp_min_plat_arch_setup(void) - { - } +diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c +new file mode 100644 +index 000000000..ee64b58c3 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_boot_device.c +@@ -0,0 +1,168 @@ ++/* ++ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ + -+void sp_min_plat_runtime_setup(void) ++#include ++ ++#include ++#include ++#include ++ ++#define SZ_512 0x200U ++#define SZ_64M 0x4000000U ++ ++#if STM32MP_RAW_NAND || STM32MP_SPI_NAND ++static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) +{ -+} -diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S -index 0d7a8bb..a9cc26b 100644 ---- a/plat/st/stm32mp1/stm32mp1.ld.S -+++ b/plat/st/stm32mp1/stm32mp1.ld.S -@@ -4,8 +4,9 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef __STM32MP1_LD_S__ --#define __STM32MP1_LD_S__ -+#ifndef STM32MP1_LD_S -+#define STM32MP1_LD_S ++ uint32_t nand_param; + - #include - #include - -@@ -16,7 +17,7 @@ ENTRY(__BL2_IMAGE_START__) - - MEMORY { - HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000 -- RAM (rwx) : ORIGIN = STM32MP1_BINARY_BASE, LENGTH = STM32MP1_BINARY_SIZE -+ RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE - } - - SECTIONS -@@ -31,7 +32,7 @@ SECTIONS - __HEADER_END__ = .; - } >HEADER - -- . = STM32MP1_BINARY_BASE; -+ . = STM32MP_BINARY_BASE; - .data . : { - . = ALIGN(PAGE_SIZE); - __DATA_START__ = .; -@@ -42,7 +43,7 @@ SECTIONS - * The strongest and only alignment contraint is MMU 4K page. - * Indeed as images below will be removed, 4K pages will be re-used. - */ -- . = ( STM32MP1_DTB_BASE - STM32MP1_BINARY_BASE ); -+ . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE ); - __DTB_IMAGE_START__ = .; - *(.dtb_image*) - __DTB_IMAGE_END__ = .; -@@ -52,20 +53,22 @@ SECTIONS - * The strongest and only alignment contraint is MMU 4K page. - * Indeed as images below will be removed, 4K pages will be re-used. - */ -- . = ( STM32MP1_BL2_BASE - STM32MP1_BINARY_BASE ); -+ . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE ); - __BL2_IMAGE_START__ = .; - *(.bl2_image*) - __BL2_IMAGE_END__ = .; - -+#ifndef AARCH32_SP_OPTEE - /* - * bl32 will be settled by bl2. - * The strongest and only alignment constraint is 8 words to simplify - * memraise8 assembly code. - */ -- . = ( STM32MP1_BL32_BASE - STM32MP1_BINARY_BASE ); -+ . = ( STM32MP_BL32_BASE - STM32MP_BINARY_BASE ); - __BL32_IMAGE_START__ = .; - *(.bl32_image*) - __BL32_IMAGE_END__ = .; ++ /* Check if NAND parameters are stored in OTP */ ++ if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) { ++ ERROR("BSEC: NAND_OTP Error\n"); ++ return -EACCES; ++ } ++ ++ if (nand_param == 0U) { ++ return 0; ++ } ++ ++ if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) { ++ goto ecc; ++ } ++ ++ /* NAND parameter shall be read from OTP */ ++ if ((nand_param & NAND_WIDTH_MASK) != 0U) { ++ nand_dev->buswidth = NAND_BUS_WIDTH_16; ++ } else { ++ nand_dev->buswidth = NAND_BUS_WIDTH_8; ++ } ++ ++ switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) { ++ case NAND_PAGE_SIZE_2K: ++ nand_dev->page_size = 0x800U; ++ break; ++ ++ case NAND_PAGE_SIZE_4K: ++ nand_dev->page_size = 0x1000U; ++ break; ++ ++ case NAND_PAGE_SIZE_8K: ++ nand_dev->page_size = 0x2000U; ++ break; ++ ++ default: ++ ERROR("Cannot read NAND page size\n"); ++ return -EINVAL; ++ } ++ ++ switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) { ++ case NAND_BLOCK_SIZE_64_PAGES: ++ nand_dev->block_size = 64U * nand_dev->page_size; ++ break; ++ ++ case NAND_BLOCK_SIZE_128_PAGES: ++ nand_dev->block_size = 128U * nand_dev->page_size; ++ break; ++ ++ case NAND_BLOCK_SIZE_256_PAGES: ++ nand_dev->block_size = 256U * nand_dev->page_size; ++ break; ++ ++ default: ++ ERROR("Cannot read NAND block size\n"); ++ return -EINVAL; ++ } ++ ++ nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >> ++ NAND_BLOCK_NB_SHIFT) * ++ NAND_BLOCK_NB_UNIT * nand_dev->block_size; ++ ++ecc: ++ if (is_slc) { ++ switch ((nand_param & NAND_ECC_BIT_NB_MASK) >> ++ NAND_ECC_BIT_NB_SHIFT) { ++ case NAND_ECC_BIT_NB_1_BITS: ++ nand_dev->ecc.max_bit_corr = 1U; ++ break; ++ ++ case NAND_ECC_BIT_NB_4_BITS: ++ nand_dev->ecc.max_bit_corr = 4U; ++ break; ++ ++ case NAND_ECC_BIT_NB_8_BITS: ++ nand_dev->ecc.max_bit_corr = 8U; ++ break; ++ ++ case NAND_ECC_ON_DIE: ++ nand_dev->ecc.mode = NAND_ECC_ONDIE; ++ break; ++ ++ default: ++ if (nand_dev->ecc.max_bit_corr == 0U) { ++ ERROR("No valid eccbit number\n"); ++ return -EINVAL; ++ } ++ } ++ } else { ++ /* Selected multiple plane NAND */ ++ if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) { ++ nand_dev->nb_planes = 2U; ++ } else { ++ nand_dev->nb_planes = 1U; ++ } ++ } ++ ++ VERBOSE("OTP: Block %i Page %i Size %lli\n", nand_dev->block_size, ++ nand_dev->page_size, nand_dev->size); ++ ++ return 0; ++} ++#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */ ++ ++#if STM32MP_RAW_NAND ++int plat_get_raw_nand_data(struct rawnand_device *device) ++{ ++ device->nand_dev->ecc.mode = NAND_ECC_HW; ++ device->nand_dev->ecc.size = SZ_512; ++ ++ return get_data_from_otp(device->nand_dev, true); ++} ++#endif ++ ++#if STM32MP_SPI_NAND ++int plat_get_spi_nand_data(struct spinand_device *device) ++{ ++ zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op)); ++ device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X; ++ device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ device->spi_read_cache_op.addr.nbytes = 2U; ++ device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ device->spi_read_cache_op.dummy.nbytes = 1U; ++ device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE; ++ device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN; ++ ++ return get_data_from_otp(device->nand_dev, false); ++} ++#endif ++ ++#if STM32MP_SPI_NOR ++int plat_get_nor_data(struct nor_device *device) ++{ ++ device->size = SZ_64M; ++ ++ zeromem(&device->read_op, sizeof(struct spi_mem_op)); ++ device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4; ++ device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ device->read_op.addr.nbytes = 3U; ++ device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ device->read_op.dummy.nbytes = 1U; ++ device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; ++ device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE; ++ device->read_op.data.dir = SPI_MEM_DATA_IN; ++ ++ return 0; ++} +#endif - - __DATA_END__ = .; - } >RAM -@@ -73,4 +76,4 @@ SECTIONS - __TF_END__ = .; - - } --#endif /*__STM32MP1_LD_S__*/ -+#endif /* STM32MP1_LD_S */ -diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c -deleted file mode 100644 -index 7d84da1..0000000 ---- a/plat/st/stm32mp1/stm32mp1_common.c -+++ /dev/null -@@ -1,101 +0,0 @@ --/* -- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define MAP_SRAM MAP_REGION_FLAT(STM32MP1_SRAM_BASE, \ -- STM32MP1_SRAM_SIZE, \ -- MT_MEMORY | \ -- MT_RW | \ -- MT_SECURE | \ -- MT_EXECUTE_NEVER) -- --#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ -- STM32MP1_DEVICE1_SIZE, \ -- MT_DEVICE | \ -- MT_RW | \ -- MT_SECURE | \ -- MT_EXECUTE_NEVER) -- --#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \ -- STM32MP1_DEVICE2_SIZE, \ -- MT_DEVICE | \ -- MT_RW | \ -- MT_SECURE | \ -- MT_EXECUTE_NEVER) -- --#define MAP_DDR MAP_REGION_FLAT(STM32MP1_DDR_BASE, \ -- STM32MP1_DDR_MAX_SIZE, \ -- MT_MEMORY | \ -- MT_RW | \ -- MT_SECURE | \ -- MT_EXECUTE_NEVER) -- --#define MAP_DDR_NS MAP_REGION_FLAT(STM32MP1_DDR_BASE, \ -- STM32MP1_DDR_MAX_SIZE, \ -- MT_MEMORY | \ -- MT_RW | \ -- MT_NS | \ -- MT_EXECUTE_NEVER) -- --#if defined(IMAGE_BL2) --static const mmap_region_t stm32mp1_mmap[] = { -- MAP_SRAM, -- MAP_DEVICE1, -- MAP_DEVICE2, -- MAP_DDR, -- {0} --}; --#endif --#if defined(IMAGE_BL32) --static const mmap_region_t stm32mp1_mmap[] = { -- MAP_SRAM, -- MAP_DEVICE1, -- MAP_DEVICE2, -- MAP_DDR_NS, -- {0} --}; --#endif -- --void configure_mmu(void) --{ -- mmap_add(stm32mp1_mmap); -- init_xlat_tables(); -- -- enable_mmu_svc_mon(0); --} -- --uintptr_t plat_get_ns_image_entrypoint(void) --{ -- return BL33_BASE; --} -- --unsigned int plat_get_syscnt_freq2(void) --{ -- return read_cntfrq_el0(); --} -- --/* Functions to save and get boot context address given by ROM code */ --static uintptr_t boot_ctx_address; -- --void stm32mp1_save_boot_ctx_address(uintptr_t address) --{ -- boot_ctx_address = address; --} -- --uintptr_t stm32mp1_get_boot_ctx_address(void) --{ -- return boot_ctx_address; --} diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c -index 245fd17..8dc1146 100644 +index cf8a91eb4..e77b8a79f 100644 --- a/plat/st/stm32mp1/stm32mp1_context.c +++ b/plat/st/stm32mp1/stm32mp1_context.c -@@ -4,39 +4,235 @@ - * SPDX-License-Identifier: BSD-3-Clause +@@ -5,19 +5,343 @@ */ -+#include -+#include -+#include -+#include - #include #include - #include - #include -+#include -+#include - #include - #include -+#include -+#include +#include -+#include + #include + +-#include ++#include ++#include ++#include ++#include ++#include + #include ++#include + #include ++#include ++#include ++#include + + #include + ++#include ++ #define TAMP_BOOT_ITF_BACKUP_REG_ID U(20) #define TAMP_BOOT_ITF_MASK U(0x0000FF00) #define TAMP_BOOT_ITF_SHIFT 8 @@ -40499,11 +40045,39 @@ index 245fd17..8dc1146 100644 +#define TRAINING_AREA_SIZE 64 + +#ifdef AARCH32_SP_OPTEE -+/* OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined */ -+#define OPTEE_MAILBOX_MAGIC_V1 0x01 -+#define OPTEE_MAILBOX_MAGIC ((OPTEE_MAILBOX_MAGIC_V1 << 16) + \ -+ TRAINING_AREA_SIZE) ++/* ++ * OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined ++ * ++ * OPTEE_MAILBOX_MAGIC_V1: ++ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer. ++ * ++ * OPTEE_MAILBOX_MAGIC_V2: ++ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer ++ * and PLL1 dual OPP settings structure (86 bytes). ++ */ ++#define OPTEE_MAILBOX_MAGIC_V1 (0x0001 << 16) ++#define OPTEE_MAILBOX_MAGIC_V2 (0x0002 << 16) ++#define OPTEE_MAILBOX_MAGIC (OPTEE_MAILBOX_MAGIC_V2 | \ ++ TRAINING_AREA_SIZE) ++ ++#define MAGIC_ID(magic) ((magic) & GENMASK_32(31, 16)) ++#define MAGIC_AREA_SIZE(magic) ((magic) & GENMASK_32(15, 0)) ++ ++#if (PLAT_MAX_OPP_NB != 2) || (PLAT_MAX_PLLCFG_NB != 6) ++#error OPTEE_MAILBOX_MAGIC_V1 does not support expected PLL1 settings +#endif ++#endif ++ ++/* pll_settings structure size definitions (reference to clock driver) */ ++#define PLL1_SETTINGS_SIZE (((PLAT_MAX_OPP_NB * \ ++ (PLAT_MAX_PLLCFG_NB + 3)) + 1) * \ ++ sizeof(uint32_t)) ++ ++/* Set to 600 bytes to be a bit flexible but could be optimized if needed */ ++#define CLOCK_CONTEXT_SIZE 600 ++ ++/* SCMI needs only 24 bits to save the state of the 24 exposed clocks */ ++#define SCMI_CONTEXT_SIZE (sizeof(uint8_t) * 4) + +struct backup_data_s { +#ifdef AARCH32_SP_OPTEE @@ -40511,12 +40085,17 @@ index 245fd17..8dc1146 100644 + uint32_t core0_resume_hint; + uint32_t zq0cr0_zdata; + uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; ++ uint8_t pll1_settings[PLL1_SETTINGS_SIZE]; +#else + smc_ctx_t saved_smc_context[PLATFORM_CORE_COUNT]; + cpu_context_t saved_cpu_context[PLATFORM_CORE_COUNT]; + uint32_t zq0cr0_zdata; + struct stm32_rtc_calendar rtc; + uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; ++ uint8_t pll1_settings[PLL1_SETTINGS_SIZE]; ++ unsigned long long stgen; ++ uint8_t clock_cfg[CLOCK_CONTEXT_SIZE]; ++ uint8_t scmi_context[SCMI_CONTEXT_SIZE]; +#endif +}; + @@ -40531,7 +40110,15 @@ index 245fd17..8dc1146 100644 + /* Context & Data to be saved at the beginning of Backup SRAM */ + backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; + -+ if (backup_data->magic != OPTEE_MAILBOX_MAGIC) { ++ switch (MAGIC_ID(backup_data->magic)) { ++ case OPTEE_MAILBOX_MAGIC_V1: ++ case OPTEE_MAILBOX_MAGIC_V2: ++ if (MAGIC_AREA_SIZE(backup_data->magic) != TRAINING_AREA_SIZE) { ++ panic(); ++ } ++ break; ++ default: ++ ERROR("PM context: bad magic\n"); + panic(); + } + @@ -40551,12 +40138,47 @@ index 245fd17..8dc1146 100644 + stm32mp_clk_disable(BKPSRAM); +} + ++void stm32mp1_pm_save_clock_cfg(size_t offset, uint8_t *data, size_t size) ++{ ++ struct backup_data_s *backup_data; ++ ++ if (offset + size > sizeof(backup_data->clock_cfg)) { ++ panic(); ++ } ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ stm32mp_clk_enable(BKPSRAM); ++ ++ memcpy(backup_data->clock_cfg + offset, data, size); ++ ++ stm32mp_clk_disable(BKPSRAM); ++} ++ ++void stm32mp1_pm_restore_clock_cfg(size_t offset, uint8_t *data, size_t size) ++{ ++ struct backup_data_s *backup_data; ++ ++ if (offset + size > sizeof(backup_data->clock_cfg)) ++ panic(); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ stm32mp_clk_enable(BKPSRAM); ++ ++ memcpy(data, backup_data->clock_cfg + offset, size); ++ ++ stm32mp_clk_disable(BKPSRAM); ++} ++ +int stm32_save_context(uint32_t zq0cr0_zdata) +{ + void *smc_context; + void *cpu_context; + struct backup_data_s *backup_data; + ++ stm32mp1_clock_suspend(); ++ + stm32mp_clk_enable(BKPSRAM); + + /* Context & Data to be saved at the beginning of Backup SRAM */ @@ -40577,6 +40199,15 @@ index 245fd17..8dc1146 100644 + backup_data->zq0cr0_zdata = zq0cr0_zdata; + + stm32_rtc_get_calendar(&backup_data->rtc); ++ backup_data->stgen = stm32mp_stgen_get_counter(); ++ ++ stm32mp1_clk_lp_save_opp_pll1_settings(backup_data->pll1_settings, ++ sizeof(backup_data->pll1_settings)); ++ ++ stm32mp1_pm_save_scmi_state(backup_data->scmi_context, ++ sizeof(backup_data->scmi_context)); ++ ++ save_clock_pm_context(); + + stm32mp_clk_disable(BKPSRAM); + @@ -40591,8 +40222,6 @@ index 245fd17..8dc1146 100644 + struct stm32_rtc_calendar current_calendar; + unsigned long long stdby_time_in_ms; + -+ stm32mp_clk_enable(BKPSRAM); -+ + /* Context & Data to be saved at the beginning of Backup SRAM */ + backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; + @@ -40602,22 +40231,50 @@ index 245fd17..8dc1146 100644 + /* Retrieve smc context struct address */ + cpu_context = cm_get_context(NON_SECURE); + ++ stm32mp_clk_enable(BKPSRAM); ++ ++ restore_clock_pm_context(); ++ ++ stm32mp1_pm_restore_scmi_state(backup_data->scmi_context, ++ sizeof(backup_data->scmi_context)); ++ + /* Restore data from Backup SRAM */ + memcpy(smc_context, backup_data->saved_smc_context, + sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT); + memcpy(cpu_context, backup_data->saved_cpu_context, + sizeof(cpu_context_t) * PLATFORM_CORE_COUNT); + -+ /* update STGEN counter with standby mode length */ ++ /* Restore STGEN counter with standby mode length */ + stm32_rtc_get_calendar(¤t_calendar); + stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, + &backup_data->rtc); -+ stm32mp1_stgen_increment(stdby_time_in_ms); ++ stm32mp_stgen_restore_counter(backup_data->stgen, stdby_time_in_ms); ++ ++ stm32mp1_clk_lp_load_opp_pll1_settings(backup_data->pll1_settings, ++ sizeof(backup_data->pll1_settings)); + + stm32mp_clk_disable(BKPSRAM); + ++ stm32mp1_clock_resume(); ++ + return 0; +} ++ ++unsigned long long stm32_get_stgen_from_context(void) ++{ ++ struct backup_data_s *backup_data; ++ unsigned long long stgen_cnt; ++ ++ stm32mp_clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ stgen_cnt = backup_data->stgen; ++ ++ stm32mp_clk_disable(BKPSRAM); ++ ++ return stgen_cnt; ++} +#endif /*AARCH32_SP_OPTEE*/ + +uint32_t stm32_get_zdata_from_context(void) @@ -40636,31 +40293,72 @@ index 245fd17..8dc1146 100644 + + return zdata; +} ++ ++#ifdef AARCH32_SP_OPTEE ++static int pll1_settings_in_context(struct backup_data_s *backup_data) ++{ ++ switch (MAGIC_ID(backup_data->magic)) { ++ case OPTEE_MAILBOX_MAGIC_V1: ++ return -ENOENT; ++ case OPTEE_MAILBOX_MAGIC_V2: ++ assert(MAGIC_AREA_SIZE(backup_data->magic) == ++ TRAINING_AREA_SIZE); ++ return 0; ++ default: ++ panic(); ++ } ++} ++#else ++static int pll1_settings_in_context(struct backup_data_s *backup_data) ++{ ++ return 0; ++} ++#endif ++ ++int stm32_get_pll1_settings_from_context(void) ++{ ++ struct backup_data_s *backup_data; ++ int ret; ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ stm32mp_clk_enable(BKPSRAM); ++ ++ ret = pll1_settings_in_context(backup_data); ++ if (ret == 0) { ++ uint8_t *data = (uint8_t *)backup_data->pll1_settings; ++ size_t size = sizeof(backup_data->pll1_settings); ++ ++ stm32mp1_clk_lp_load_opp_pll1_settings(data, size); ++ } ++ ++ stm32mp_clk_disable(BKPSRAM); ++ ++ return ret; ++} ++ ++bool stm32_are_pll1_settings_valid_in_context(void) ++{ ++ struct backup_data_s *backup_data; ++ uint32_t *data; ++ bool is_valid; ++ ++ stm32mp_clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ data = (uint32_t *)backup_data->pll1_settings; ++ ++ is_valid = (data[0] == PLL1_SETTINGS_VALID_ID); ++ ++ stm32mp_clk_disable(BKPSRAM); ++ ++ return is_valid; ++} + int stm32_save_boot_interface(uint32_t interface, uint32_t instance) { -- uint32_t tamp_clk_off = 0; uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); - -- if (!stm32mp1_clk_is_enabled(RTCAPB)) { -- tamp_clk_off = 1; -- if (stm32mp1_clk_enable(RTCAPB) != 0) { -- return -EINVAL; -- } -- } -+ stm32mp_clk_enable(RTCAPB); - - mmio_clrsetbits_32(bkpr_itf_idx, - TAMP_BOOT_ITF_MASK, - ((interface << 4) | (instance & 0xFU)) << - TAMP_BOOT_ITF_SHIFT); - -- if (tamp_clk_off != 0U) { -- if (stm32mp1_clk_disable(RTCAPB) != 0) { -- return -EINVAL; -- } -- } -+ stm32mp_clk_disable(RTCAPB); +@@ -33,3 +357,68 @@ int stm32_save_boot_interface(uint32_t interface, uint32_t instance) return 0; } @@ -40683,6 +40381,7 @@ index 245fd17..8dc1146 100644 + return 0; +} + ++#if defined(IMAGE_BL32) +/* + * When returning from STANDBY, the 64 first bytes of DDR will be overwritten + * during DDR DQS training. This area must then be saved before going to @@ -40691,18 +40390,27 @@ index 245fd17..8dc1146 100644 +void stm32_save_ddr_training_area(void) +{ + struct backup_data_s *backup_data; ++ int ret __unused; + + stm32mp_clk_enable(BKPSRAM); + + backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; + ++ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, ++ PAGE_SIZE, MT_MEMORY | MT_RW | MT_NS); ++ assert(ret == 0); ++ + memcpy(&backup_data->ddr_training_backup, + (const uint32_t *)STM32MP_DDR_BASE, + TRAINING_AREA_SIZE); + dsb(); + ++ ret = mmap_remove_dynamic_region(STM32MP_DDR_BASE, PAGE_SIZE); ++ assert(ret == 0); ++ + stm32mp_clk_disable(BKPSRAM); +} ++#endif + +void stm32_restore_ddr_training_area(void) +{ @@ -40720,228 +40428,162 @@ index 245fd17..8dc1146 100644 + stm32mp_clk_disable(BKPSRAM); +} diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c -new file mode 100644 -index 0000000..716f7d8 ---- /dev/null +index d0264968c..b9f94af0a 100644 +--- a/plat/st/stm32mp1/stm32mp1_dbgmcu.c +++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c -@@ -0,0 +1,153 @@ +@@ -4,12 +4,14 @@ + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include + #include + + #include + + #include + #include ++#include + #include + #include + #include +@@ -33,19 +35,11 @@ static uintptr_t get_rcc_base(void) + + static int stm32mp1_dbgmcu_init(void) + { +- uint32_t dbg_conf; + uintptr_t rcc_base = get_rcc_base(); + +- dbg_conf = bsec_read_debug_conf(); +- +- if ((dbg_conf & BSEC_DBGSWGEN) == 0U) { +- uint32_t result = bsec_write_debug_conf(dbg_conf | +- BSEC_DBGSWGEN); +- +- if (result != BSEC_OK) { +- ERROR("Error enabling DBGSWGEN\n"); +- return -1; +- } ++ if ((bsec_read_debug_conf() & BSEC_DBGSWGEN) == 0U) { ++ INFO("Software access to all debug components is disabled\n"); ++ return -1; + } + + mmio_setbits_32(rcc_base + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); +@@ -53,8 +47,15 @@ static int stm32mp1_dbgmcu_init(void) + return 0; + } + +/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause ++ * @brief Get silicon revision from DBGMCU registers. ++ * @param chip_version: pointer to the read value. ++ * @retval 0 on success, negative value on failure. + */ + int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version) + { ++ assert(chip_version != NULL); + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include + if (stm32mp1_dbgmcu_init() != 0) { + return -EPERM; + } +@@ -65,18 +66,29 @@ int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version) + return 0; + } + ++/* ++ * @brief Get device ID from DBGMCU registers. ++ * @param chip_dev_id: pointer to the read value. ++ * @retval 0 on success, negative value on failure. ++ */ + int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id) + { ++ assert(chip_dev_id != NULL); + -+#define DBGMCU_IDC 0x0U -+#define IDC_DEV_ID_MASK GENMASK(11, 0) -+#define DBGMCU_APB4FZ1 0x2CU -+#define DBGMCU_APB4FZ1_IWDG2 BIT(2) -+ -+#define TAMP_DBG_BACKUP_REG_ID 20 -+#define TAMP_DBG_DEBUG BIT(16) -+ -+static uintptr_t get_rcc_base(void) -+{ -+ /* This is called before stm32mp_rcc_base() is available */ -+ return RCC_BASE; -+} -+ -+static int stm32mp1_dbgmcu_init(void) -+{ -+ uint32_t dbg_conf; -+ uintptr_t rcc_base = get_rcc_base(); -+ -+ dbg_conf = bsec_read_debug_conf(); -+ -+ if ((dbg_conf & BSEC_DBGSWGEN) == 0U) { -+ uint32_t result = bsec_write_debug_conf(dbg_conf | -+ BSEC_DBGSWGEN); -+ -+ if (result != BSEC_OK) { -+ ERROR("Error enabling DBGSWGEN\n"); -+ return (int)result; -+ } -+ } -+ -+ if ((mmio_read_32(rcc_base + RCC_DBGCFGR) & RCC_DBGCFGR_DBGCKEN) == -+ 0U) { -+ mmio_setbits_32(rcc_base + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); -+ } -+ -+ return 0; -+} -+ -+#if STM32MP1_DEBUG_ENABLE -+int stm32mp1_dbgmcu_boot_debug_info(void) -+{ -+ uint32_t backup_reg_dbg; -+ -+ stm32mp_clk_enable(RTCAPB); -+ -+ backup_reg_dbg = (mmio_read_32(tamp_bkpr(TAMP_DBG_BACKUP_REG_ID)) -+ & TAMP_DBG_DEBUG); -+ -+ stm32mp_clk_disable(RTCAPB); -+ -+ if (backup_reg_dbg != 0U) { -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int stm32mp1_dbgmcu_clear_boot_info(void) -+{ -+ stm32mp_clk_enable(RTCAPB); -+ -+ mmio_clrbits_32(tamp_bkpr(TAMP_DBG_BACKUP_REG_ID), -+ TAMP_DBG_DEBUG); -+ -+ stm32mp_clk_disable(RTCAPB); -+ -+ return 0; -+} -+ -+uint32_t stm32mp1_dbgmcu_is_debug_on(void) -+{ -+ uint32_t dbg_conf; -+ -+ dbg_conf = bsec_read_debug_conf(); -+ -+ return (dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN)); -+} -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len) -+{ -+ uint32_t i; -+ -+ VERBOSE(" "); -+ for (i = 0; i < len; i++) { -+ printf("%02x ", buf[i]); -+ if (((i + 1) % 16) == 0) { -+ if ((i + 1) < len) { -+ printf("\n"); -+ VERBOSE(" "); -+ } -+ } else if (((i + 1) % 8) == 0) { -+ printf(" "); -+ } -+ } -+ printf("\n"); -+} -+#endif -+#endif -+ -+uint32_t stm32mp1_dbgmcu_get_chip_version(void) -+{ -+ if (stm32mp1_dbgmcu_init() == 0) { -+ return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) >> 16); -+ } -+ -+ return 0; -+} -+ -+uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void) -+{ -+ if (stm32mp1_dbgmcu_init() == 0) { -+ return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & -+ IDC_DEV_ID_MASK); -+ } -+ -+ return 0; -+} -+ -+int stm32mp1_dbgmcu_freeze_iwdg2(void) -+{ -+ if (stm32mp1_dbgmcu_init() == 0) { -+ uint32_t dbg_conf = bsec_read_debug_conf(); -+ -+ if (((dbg_conf & BSEC_SPIDEN) != 0U) || -+ ((dbg_conf & BSEC_SPINDEN) != 0U)) { -+ mmio_setbits_32(DBGMCU_BASE + DBGMCU_APB4FZ1, -+ DBGMCU_APB4FZ1_IWDG2); -+ } -+ -+ return 0; -+ } -+ -+ return -EPERM; -+} + if (stm32mp1_dbgmcu_init() != 0) { + return -EPERM; + } + + *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & +- DBGMCU_IDC_DEV_ID_MASK; ++ DBGMCU_IDC_DEV_ID_MASK; + + return 0; + } + ++/* ++ * @brief Freeze IWDG2 in debug mode. ++ * @retval None. ++ */ + int stm32mp1_dbgmcu_freeze_iwdg2(void) + { + uint32_t dbg_conf; diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h -index bb3fecf..a6b1a7b 100644 +index a40852bde..d458805a1 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -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. +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -@@ -7,84 +7,206 @@ - #ifndef STM32MP1_DEF_H - #define STM32MP1_DEF_H - -+#ifndef __ASSEMBLY__ -+#include -+#include -+#include -+#include +@@ -11,33 +11,51 @@ + #include + #include + #include +#include -+#include -+#include -+#include + #include + #include + + #ifndef __ASSEMBLER__ + #include ++#include + #include ++#include ++#include ++#include + + #include +-#include + #include + #include + #include ++#include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include + #include + #include +#include +#include -+#include -+#endif - #include - #include - #include ++#include + #endif -+#define AUTHENTICATE_BL33 -+ -+/******************************************************************************* -+ * CHIP ID -+ ******************************************************************************/ -+#define STM32MP157C_PART_NB U(0x05000000) -+#define STM32MP157A_PART_NB U(0x05000001) -+#define STM32MP153C_PART_NB U(0x05000024) -+#define STM32MP153A_PART_NB U(0x05000025) -+#define STM32MP151C_PART_NB U(0x0500002E) -+#define STM32MP151A_PART_NB U(0x0500002F) -+ -+#define STM32MP1_REV_A U(0x1000) -+#define STM32MP1_REV_B U(0x2000) -+ -+/******************************************************************************* -+ * PACKAGE ID -+ ******************************************************************************/ -+#define PKG_AA_LBGA448 U(4) -+#define PKG_AB_LBGA354 U(3) -+#define PKG_AC_TFBGA361 U(2) -+#define PKG_AD_TFBGA257 U(1) + /******************************************************************************* + * CHIP ID + ******************************************************************************/ ++#define STM32MP1_CHIP_ID U(0x500) + + #define STM32MP157C_PART_NB U(0x05000000) + #define STM32MP157A_PART_NB U(0x05000001) + #define STM32MP153C_PART_NB U(0x05000024) + #define STM32MP153A_PART_NB U(0x05000025) + #define STM32MP151C_PART_NB U(0x0500002E) + #define STM32MP151A_PART_NB U(0x0500002F) ++#define STM32MP157F_PART_NB U(0x05000080) ++#define STM32MP157D_PART_NB U(0x05000081) ++#define STM32MP153F_PART_NB U(0x050000A4) ++#define STM32MP153D_PART_NB U(0x050000A5) ++#define STM32MP151F_PART_NB U(0x050000AE) ++#define STM32MP151D_PART_NB U(0x050000AF) + + #define STM32MP1_REV_B U(0x2000) ++#define STM32MP1_REV_Z U(0x2001) + + /******************************************************************************* + * PACKAGE ID +@@ -47,6 +65,11 @@ + #define PKG_AC_TFBGA361 U(2) + #define PKG_AD_TFBGA257 U(1) + +/******************************************************************************* + * BOOT PARAM + ******************************************************************************/ @@ -40950,132 +40592,128 @@ index bb3fecf..a6b1a7b 100644 /******************************************************************************* * STM32MP1 memory map related constants ******************************************************************************/ -+#define STM32MP_ROM_BASE U(0x00000000) -+#define STM32MP_ROM_SIZE U(0x00020000) -+ -+#define STM32MP_SYSRAM_BASE U(0x2FFC0000) -+#define STM32MP_SYSRAM_SIZE U(0x00040000) -+ -+/* 384 Ko (128 x 3) Non secure from MCU available for TF*/ +@@ -56,12 +79,34 @@ + #define STM32MP_SYSRAM_BASE U(0x2FFC0000) + #define STM32MP_SYSRAM_SIZE U(0x00040000) + ++/* 384 KB (128 x 3) Non secure from MCU available for TF*/ +#define STM32MP_SRAM_MCU_BASE U(0x30000000) +#define STM32MP_SRAM_MCU_SIZE U(0x00060000) - --#define STM32MP1_SRAM_BASE U(0x2FFC0000) --#define STM32MP1_SRAM_SIZE U(0x00040000) ++ +#define STM32MP_RETRAM_BASE U(0x38000000) +#define STM32MP_RETRAM_SIZE U(0x00010000) + +#define STM32MP_BACKUP_RAM_BASE U(0x54000000) +#define STM32MP_BACKUP_RAM_SIZE U(0x00001000) - ++ ++#define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE ++#define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \ ++ STM32MP_SYSRAM_SIZE - \ ++ STM32MP_NS_SYSRAM_SIZE) ++ ++#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE ++#define STM32MP_SEC_SYSRAM_SIZE (STM32MP_SYSRAM_SIZE - \ ++ STM32MP_NS_SYSRAM_SIZE) ++ /* DDR configuration */ --#define STM32MP1_DDR_BASE U(0xC0000000) --#define STM32MP1_DDR_SIZE_DFLT U(0x20000000) /* 512 MB */ --#define STM32MP1_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ --#define STM32MP1_DDR_SPEED_DFLT 528 -+#define STM32MP_DDR_BASE U(0xC0000000) -+#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ -+#ifdef AARCH32_SP_OPTEE -+#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */ -+#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ + #define STM32MP_DDR_BASE U(0xC0000000) + #define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ + #ifdef AARCH32_SP_OPTEE + #define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ + #define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ +#else -+#define STM32MP_DDR_S_SIZE U(0) /* DDR is non secure */ -+#endif ++#define STM32MP_DDR_S_SIZE U(0) ++#define STM32MP_DDR_SHMEM_SIZE U(0) + #endif /* DDR power initializations */ - #ifndef __ASSEMBLY__ - enum ddr_type { - STM32MP_DDR3, - STM32MP_LPDDR2, -+ STM32MP_LPDDR3, - }; +@@ -74,76 +119,121 @@ enum ddr_type { #endif /* Section used inside TF binaries */ --#define STM32MP1_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */ -+#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */ +-#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */ ++#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */ /* 256 Octets reserved for header */ --#define STM32MP1_HEADER_SIZE U(0x00000100) -+#define STM32MP_HEADER_SIZE U(0x00000100) + #define STM32MP_HEADER_SIZE U(0x00000100) --#define STM32MP1_BINARY_BASE (STM32MP1_SRAM_BASE + \ -- STM32MP1_PARAM_LOAD_SIZE + \ -- STM32MP1_HEADER_SIZE) -+#define STM32MP_BINARY_BASE (STM32MP_SYSRAM_BASE + \ -+ STM32MP_PARAM_LOAD_SIZE + \ -+ STM32MP_HEADER_SIZE) +-#define STM32MP_BINARY_BASE (STM32MP_SYSRAM_BASE + \ ++#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE) --#define STM32MP1_BINARY_SIZE (STM32MP1_SRAM_SIZE - \ -- (STM32MP1_PARAM_LOAD_SIZE + \ -- STM32MP1_HEADER_SIZE)) -+#define STM32MP_BINARY_SIZE (STM32MP_SYSRAM_SIZE - \ -+ (STM32MP_PARAM_LOAD_SIZE + \ -+ STM32MP_HEADER_SIZE)) +-#define STM32MP_BINARY_SIZE (STM32MP_SYSRAM_SIZE - \ ++#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ + (STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE)) -+#ifdef AARCH32_SP_OPTEE -+#define STM32MP_BL32_SIZE U(0) -+ -+#define STM32MP_OPTEE_BASE STM32MP_SYSRAM_BASE -+ -+#define STM32MP_OPTEE_SIZE (STM32MP_DTB_BASE - \ -+ STM32MP_OPTEE_BASE) -+#else - #if STACK_PROTECTOR_ENABLED --#define STM32MP1_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */ -+#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ + #ifdef AARCH32_SP_OPTEE + #define STM32MP_BL32_SIZE U(0) + +-#define STM32MP_OPTEE_BASE STM32MP_SYSRAM_BASE ++#define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE + + #define STM32MP_OPTEE_SIZE (STM32MP_DTB_BASE - \ + STM32MP_OPTEE_BASE) #else --#define STM32MP1_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ -+#define STM32MP_BL32_SIZE U(0x00010000) /* 64 Ko for BL32 */ -+#endif + #if STACK_PROTECTOR_ENABLED +-#define STM32MP_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */ ++#define STM32MP_BL32_SIZE U(0x00013000) /* 76 KB for BL32 */ + #else +-#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ ++#define STM32MP_BL32_SIZE U(0x00012000) /* 72 KB for BL32 */ + #endif #endif --#define STM32MP1_BL32_BASE (STM32MP1_SRAM_BASE + \ -- STM32MP1_SRAM_SIZE - \ -- STM32MP1_BL32_SIZE) -+#define STM32MP_BL32_BASE (STM32MP_SYSRAM_BASE + \ -+ STM32MP_SYSRAM_SIZE - \ -+ STM32MP_BL32_SIZE) +-#define STM32MP_BL32_BASE (STM32MP_SYSRAM_BASE + \ +- STM32MP_SYSRAM_SIZE - \ ++#define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \ ++ STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL32_SIZE) -+#ifdef AARCH32_SP_OPTEE + #ifdef AARCH32_SP_OPTEE #if STACK_PROTECTOR_ENABLED --#define STM32MP1_BL2_SIZE U(0x00015000) /* 84 Ko for BL2 */ -+#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */ +-#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */ ++#define STM32MP_BL2_SIZE U(0x0001A000) /* 104 KB for BL2 */ #else --#define STM32MP1_BL2_SIZE U(0x00013000) /* 76 Ko for BL2 */ -+#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */ -+#endif -+#else -+#if STACK_PROTECTOR_ENABLED -+#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */ -+#else -+#define STM32MP_BL2_SIZE U(0x00016000) /* 88 Ko for BL2 */ -+#endif +-#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */ ++#define STM32MP_BL2_SIZE U(0x00018000) /* 96 KB for BL2 */ + #endif + #else + #if STACK_PROTECTOR_ENABLED +-#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */ ++#define STM32MP_BL2_SIZE U(0x00019000) /* 100 KB for BL2 */ + #else +-#define STM32MP_BL2_SIZE U(0x00016000) /* 88 Ko for BL2 */ ++#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */ + #endif #endif --#define STM32MP1_BL2_BASE (STM32MP1_BL32_BASE - \ -- STM32MP1_BL2_SIZE) -+#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ -+ STM32MP_BL2_SIZE) + #define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ + STM32MP_BL2_SIZE) -/* BL2 and BL32/sp_min require 5 tables */ -#define MAX_XLAT_TABLES 5 -+/* BL2 and BL32/sp_min require 7 tables */ -+#define MAX_XLAT_TABLES U(7) /* 28 Ko for mapping */ ++#if STM32MP_USB_PROGRAMMER ++ /* BL2 and BL32/sp_min require 5 finer granularity tables */ ++ #define MAX_XLAT_TABLES U(5) /* 20 KB for mapping */ ++#else ++ /* BL2 and BL32/sp_min require 4 finer granularity tables */ ++ #define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */ ++#endif /* * MAX_MMAP_REGIONS is usually: * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup */ #if defined(IMAGE_BL2) -+ #if (defined STM32MP_USB) ++ #if STM32MP_USB_PROGRAMMER + #define MAX_MMAP_REGIONS 12 + #else #define MAX_MMAP_REGIONS 11 + #endif #endif #if defined(IMAGE_BL32) -- #define MAX_MMAP_REGIONS 6 -+ #define MAX_MMAP_REGIONS 6 + #define MAX_MMAP_REGIONS 6 #endif +#define XLAT_TABLE_OCTETSIZE U(0x1000) @@ -41084,52 +40722,59 @@ index bb3fecf..a6b1a7b 100644 + +#define PLAT_XLAT_BASE (STM32MP_BL2_BASE - \ + PLAT_XLAT_SIZE) -+ -+/* -+ * Uncomment this to get the xlat tables back in each binary image -+ * (xlat_table sections in .lds) -+ * -+ * #undef PLAT_XLAT_BASE -+ */ + /* DTB initialization value */ --#define STM32MP1_DTB_SIZE U(0x00004000) /* 16Ko for DTB */ -+#define STM32MP_DTB_SIZE U(0x00005000) /* 20Ko for DTB */ -+ +-#define STM32MP_DTB_SIZE U(0x00005000) /* 20Ko for DTB */ ++#define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ + +-#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ +#define STM32MP_DTB_BASE (PLAT_XLAT_BASE - \ -+ STM32MP_DTB_SIZE) + STM32MP_DTB_SIZE) --#define STM32MP1_DTB_BASE (STM32MP1_BL2_BASE - \ -- STM32MP1_DTB_SIZE) -+#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) + #define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) --#define STM32MP1_BL33_BASE (STM32MP1_DDR_BASE + U(0x100000)) +/* Define Temporary Stack size use during low power mode */ -+#define STM32MP_INT_STACK_SIZE 0x400 ++#define STM32MP_INT_STACK_SIZE 0x100 ++ ++/* Define maximum page size for NAND devices */ ++#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000) ++ ++/* ++ * Only used for MTD devices that need some backup blocks. ++ * Must define a number of reserved blocks (depends on devices). ++ */ ++#define PLATFORM_MTD_BACKUP_BLOCKS U(20) /* (20 * MTD block size) */ + +/******************************************************************************* + * STM32MP1 RAW partition offset for MTD devices + ******************************************************************************/ +#define STM32MP_NOR_BL33_OFFSET U(0x00080000) +#ifdef AARCH32_SP_OPTEE -+#define STM32MP_NOR_TEEH_OFFSET U(0x00280000) -+#define STM32MP_NOR_TEED_OFFSET U(0x002C0000) -+#define STM32MP_NOR_TEEX_OFFSET U(0x00300000) ++#define STM32MP_NOR_TEEH_OFFSET U(0x00300000) ++#define STM32MP_NOR_TEED_OFFSET U(0x00340000) ++#define STM32MP_NOR_TEEX_OFFSET U(0x003C0000) +#endif + +#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 - ++ /******************************************************************************* * STM32MP1 device/io map related constants (used for MMU) -@@ -106,6 +228,60 @@ enum ddr_type { + ******************************************************************************/ +@@ -163,6 +253,32 @@ enum ddr_type { + ******************************************************************************/ #define PWR_BASE U(0x50001000) - /******************************************************************************* ++/******************************************************************************* ++ * STM32MP1 SYSCFG ++ ******************************************************************************/ ++#define SYSCFG_BASE U(0x50020000) ++ ++/******************************************************************************* + * STM32MP1 EXTI + ******************************************************************************/ +#define EXTI_BASE U(0x5000D000) @@ -41150,257 +40795,158 @@ index bb3fecf..a6b1a7b 100644 + ******************************************************************************/ +#define RTC_BASE U(0x5C004000) + -+/******************************************************************************* -+ * STM32MP1 GPIO -+ ******************************************************************************/ -+#define GPIOA_BASE U(0x50002000) -+#define GPIOB_BASE U(0x50003000) -+#define GPIOC_BASE U(0x50004000) -+#define GPIOD_BASE U(0x50005000) -+#define GPIOE_BASE U(0x50006000) -+#define GPIOF_BASE U(0x50007000) -+#define GPIOG_BASE U(0x50008000) -+#define GPIOH_BASE U(0x50009000) -+#define GPIOI_BASE U(0x5000A000) -+#define GPIOJ_BASE U(0x5000B000) -+#define GPIOK_BASE U(0x5000C000) -+#define GPIOZ_BASE U(0x54004000) -+#define GPIO_BANK_OFFSET U(0x1000) -+ -+/* Bank IDs used in GPIO driver API */ -+#define GPIO_BANK_A U(0) -+#define GPIO_BANK_B U(1) -+#define GPIO_BANK_C U(2) -+#define GPIO_BANK_D U(3) -+#define GPIO_BANK_E U(4) -+#define GPIO_BANK_F U(5) -+#define GPIO_BANK_G U(6) -+#define GPIO_BANK_H U(7) -+#define GPIO_BANK_I U(8) -+#define GPIO_BANK_J U(9) -+#define GPIO_BANK_K U(10) -+#define GPIO_BANK_Z U(25) -+ -+#define STM32MP_GPIOZ_PIN_MAX_COUNT 8 -+ -+/******************************************************************************* - * STM32MP1 UART - ******************************************************************************/ - #define USART1_BASE U(0x5C000000) -@@ -116,16 +292,31 @@ enum ddr_type { - #define USART6_BASE U(0x44003000) - #define UART7_BASE U(0x40018000) - #define UART8_BASE U(0x40019000) --#define STM32MP1_DEBUG_USART_BASE UART4_BASE --#define STM32MP1_UART_BAUDRATE 115200 -+#define STM32MP_UART_BAUDRATE U(115200) -+ -+/* For UART crash console */ -+#define STM32MP_DEBUG_USART_BASE UART4_BASE -+/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */ -+#define STM32MP_DEBUG_USART_CLK_FRQ 64000000 -+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE -+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR -+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN -+#define DEBUG_UART_TX_GPIO_PORT 11 -+#define DEBUG_UART_TX_GPIO_ALTERNATE 6 -+#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR -+#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI -+#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR -+#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN - /******************************************************************************* -- * STM32MP1 GIC-400 -+ * STM32MP1 TZPC + * STM32MP1 GPIO ******************************************************************************/ --#define STM32MP1_GICD_BASE U(0xA0021000) --#define STM32MP1_GICC_BASE U(0xA0022000) --#define STM32MP1_GICH_BASE U(0xA0024000) --#define STM32MP1_GICV_BASE U(0xA0026000) +@@ -223,6 +339,21 @@ enum ddr_type { + #define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR + #define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN + ++/******************************************************************************* ++ * STM32MP1 ETZPC ++ ******************************************************************************/ +#define STM32MP1_ETZPC_BASE U(0x5C007000) +#define STM32MP1_ETZPC_SIZE U(0x000003FF) + +#define STM32MP1_ETZPC_TZMA_ROM_ID U(0) +/*SYSRAM internal RAM*/ +#define STM32MP1_ETZPC_TZMA_RAM_ID U(1) - ++ ++/* Lowest DECPROT ID for ETZPC cannot harden TZ security */ ++#define STM32MP1_ETZPC_SEC_ID_LIMIT U(13) ++ ++#define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0) ++ /******************************************************************************* * STM32MP1 TZC (TZ400) -@@ -133,6 +324,7 @@ enum ddr_type { - #define STM32MP1_TZC_BASE U(0x5C006000) - - #define STM32MP1_TZC_A7_ID U(0) -+#define STM32MP1_TZC_M4_ID U(1) - #define STM32MP1_TZC_LCD_ID U(3) - #define STM32MP1_TZC_GPU_ID U(4) - #define STM32MP1_TZC_MDMA_ID U(5) -@@ -143,28 +335,117 @@ enum ddr_type { - #define STM32MP1_TZC_ETH_ID U(10) - #define STM32MP1_TZC_DAP_ID U(15) - --#define STM32MP1_MEMORY_NS 0 --#define STM32MP1_MEMORY_SECURE 1 -- --#define STM32MP1_FILTER_BIT_ALL 3 -+#define STM32MP1_FILTER_BIT_ALL U(3) - - /******************************************************************************* - * STM32MP1 SDMMC ******************************************************************************/ --#define STM32MP1_SDMMC1_BASE U(0x58005000) --#define STM32MP1_SDMMC2_BASE U(0x58007000) --#define STM32MP1_SDMMC3_BASE U(0x48004000) -+#define STM32MP_SDMMC1_BASE U(0x58005000) -+#define STM32MP_SDMMC2_BASE U(0x58007000) -+#define STM32MP_SDMMC3_BASE U(0x48004000) +@@ -263,15 +394,20 @@ enum ddr_type { --#define STM32MP1_SD_INIT_FREQ 400000 /*400 KHz*/ --#define STM32MP1_SD_NORMAL_SPEED_MAX_FREQ 25000000 /*25 MHz*/ --#define STM32MP1_SD_HIGH_SPEED_MAX_FREQ 50000000 /*50 MHz*/ --#define STM32MP1_EMMC_INIT_FREQ STM32MP1_SD_INIT_FREQ --#define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ --#define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ -+#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/ -+#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/ -+#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/ -+#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/ -+#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/ -+ -+/******************************************************************************* -+ * STM32MP1 QSPI -+ ******************************************************************************/ -+#define STM32MP1_QSPI1_BASE U(0x58003000) -+ -+/******************************************************************************* -+ * STM32MP1 BSEC / OTP -+ ******************************************************************************/ -+#define STM32MP1_BSEC_BASE U(0x5C005000) -+#define STM32MP1_OTP_MAX_ID 0x5FU -+#define STM32MP1_UPPER_OTP_START 0x20U -+ -+#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) -+ -+/* OTP offsets */ -+#define DATA0_OTP U(0) -+#define PART_NUMBER_OTP U(1) -+#define MONOTONIC_OTP U(4) -+#define NAND_OTP U(9) -+#define UID0_OTP U(13) -+#define UID1_OTP U(14) -+#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 */ -+#define DATA0_OTP_SECURED BIT(6) -+ -+/* PART NUMBER */ -+#define PART_SHIFT 0 -+#define PART_MASK GENMASK_32(7, 0) -+ -+/* PACKAGE */ -+#define PKG_SHIFT 27 -+#define PKG_MASK GENMASK_32(29, 27) -+ -+/* IWDG OTP */ -+#define IWDG_HW_POS 3 -+#define IWDG_FZ_STOP_POS 5 -+#define IWDG_FZ_STANDBY_POS 7 + #define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) + +-/* OTP offsets */ +-#define DATA0_OTP U(0) +-#define PART_NUMBER_OTP U(1) +-#define PACKAGE_OTP U(16) +-#define HW2_OTP U(18) ++/* OTP labels */ ++#define CFG0_OTP "cfg0_otp" ++#define PART_NUMBER_OTP "part_number_otp" ++#define PACKAGE_OTP "package_otp" ++#define HW2_OTP "hw2_otp" ++#define NAND_OTP "nand_otp" ++#define MONOTONIC_OTP "monotonic_otp" ++#define UID_OTP "uid_otp" ++#define PKH_OTP "pkh_otp" ++#define BOARD_ID_OTP "board_id" + + /* OTP mask */ +-/* DATA0 */ +-#define DATA0_OTP_SECURED BIT(6) ++/* CFG0 */ ++#define CFG0_CLOSED_DEVICE BIT(6) + + /* PART NUMBER */ + #define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) +@@ -289,11 +425,71 @@ enum ddr_type { + /* HW2 OTP */ + #define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) + ++#define MAX_MONOTONIC_VALUE 32 + +/* NAND OTP */ +/* NAND parameter storage flag */ -+#define NAND_PARAM_STORED_IN_OTP U(0x80000000) ++#define NAND_PARAM_STORED_IN_OTP BIT(31) + +/* NAND page size in bytes */ -+#define NAND_PAGE_SIZE_OFFSET 29 -+#define NAND_PAGE_SIZE_MASK U(0x60000000) -+#define NAND_PAGE_SIZE_2K 0 -+#define NAND_PAGE_SIZE_4K 1 -+#define NAND_PAGE_SIZE_8K 2 ++#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29) ++#define NAND_PAGE_SIZE_SHIFT 29 ++#define NAND_PAGE_SIZE_2K U(0) ++#define NAND_PAGE_SIZE_4K U(1) ++#define NAND_PAGE_SIZE_8K U(2) + +/* NAND block size in pages */ -+#define NAND_BLOCK_SIZE_OFFSET 27 -+#define NAND_BLOCK_SIZE_MASK U(0x18000000) -+#define NAND_BLOCK_SIZE_64_PAGES 0 -+#define NAND_BLOCK_SIZE_128_PAGES 1 -+#define NAND_BLOCK_SIZE_256_PAGES 2 ++#define NAND_BLOCK_SIZE_MASK GENMASK_32(28, 27) ++#define NAND_BLOCK_SIZE_SHIFT 27 ++#define NAND_BLOCK_SIZE_64_PAGES U(0) ++#define NAND_BLOCK_SIZE_128_PAGES U(1) ++#define NAND_BLOCK_SIZE_256_PAGES U(2) + +/* NAND number of block (in unit of 256 blocs) */ -+#define NAND_BLOCK_NB_OFFSET 19 -+#define NAND_BLOCK_NB_MASK U(0x07F80000) ++#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19) ++#define NAND_BLOCK_NB_SHIFT 19 +#define NAND_BLOCK_NB_UNIT U(256) + +/* NAND bus width in bits */ -+#define NAND_WIDTH_OFFSET 18 -+#define NAND_WIDTH_MASK 0x00040000 ++#define NAND_WIDTH_MASK BIT(18) ++#define NAND_WIDTH_SHIFT 18 + +/* NAND number of ECC bits per 512 bytes */ -+#define NAND_ECC_BIT_NB_OFFSET 16 -+#define NAND_ECC_BIT_NB_MASK U(0x00030000) -+#define NAND_ECC_BIT_NB_UNSET 0 -+#define NAND_ECC_BIT_NB_1_BITS 1 -+#define NAND_ECC_BIT_NB_4_BITS 2 -+#define NAND_ECC_BIT_NB_8_BITS 3 ++#define NAND_ECC_BIT_NB_MASK GENMASK_32(17, 15) ++#define NAND_ECC_BIT_NB_SHIFT 15 ++#define NAND_ECC_BIT_NB_UNSET U(0) ++#define NAND_ECC_BIT_NB_1_BITS U(1) ++#define NAND_ECC_BIT_NB_4_BITS U(2) ++#define NAND_ECC_BIT_NB_8_BITS U(3) ++#define NAND_ECC_ON_DIE U(4) + ++/* NAND number of planes */ ++#define NAND_PLANE_BIT_NB_MASK BIT(14) ++ ++/* MONOTONIC OTP */ +#define MAX_MONOTONIC_VALUE 32 + -+/******************************************************************************* -+ * STM32MP1 FMC -+ ******************************************************************************/ -+#define STM32MP_FMC_BASE U(0x58002000) ++/* UID OTP */ ++#define UID_WORD_NB 3 + +/******************************************************************************* + * STM32MP1 HASH + ******************************************************************************/ +#define HASH1_BASE U(0x54002000) +#define HASH_BASE HASH1_BASE - ++ /******************************************************************************* * STM32MP1 TAMP ******************************************************************************/ -+#define PLAT_MAX_TAMP_INT U(5) ++#define PLAT_MAX_TAMP_INT U(6) +#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) ++ -@@ -174,6 +455,10 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - return TAMP_BKP_REGISTER_BASE + (idx << 2); + #if !(defined(__LINKER__) || defined(__ASSEMBLER__)) + static inline uint32_t tamp_bkpr(uint32_t idx) +@@ -302,6 +498,11 @@ static inline uint32_t tamp_bkpr(uint32_t idx) } #endif + +/******************************************************************************* + * STM32MP1 USB + ******************************************************************************/ +#define USB_OTG_BASE U(0x49000000) - ++ /******************************************************************************* * STM32MP1 DDRCTRL -@@ -186,8 +471,60 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - #define DDRPHYC_BASE U(0x5A004000) + ******************************************************************************/ +@@ -323,22 +524,69 @@ static inline uint32_t tamp_bkpr(uint32_t idx) + #define IWDG2_BASE U(0x5A002000) /******************************************************************************* - * STM32MP1 I2C4 -+ * STM32MP1 IWDG -+ ******************************************************************************/ -+#define IWDG_MAX_INSTANCE U(2) -+#define IWDG1_INST U(0) -+#define IWDG2_INST U(1) -+ -+#define IWDG1_BASE U(0x5C003000) -+#define IWDG2_BASE U(0x5A002000) -+ -+/******************************************************************************* + * STM32MP1 I2C ******************************************************************************/ #define I2C4_BASE U(0x5C002000) +#define I2C6_BASE U(0x5C009000) -+ -+/******************************************************************************* -+ * STM32MP1 DBGMCU -+ ******************************************************************************/ -+#define DBGMCU_BASE U(0x50081000) -+ + + /******************************************************************************* + * STM32MP1 DBGMCU + ******************************************************************************/ + #define DBGMCU_BASE U(0x50081000) + +/******************************************************************************* + * STM32MP1 SPI + ******************************************************************************/ @@ -41417,6 +40963,11 @@ index bb3fecf..a6b1a7b 100644 +#define CRYP1_BASE U(0x54001000) + +/******************************************************************************* ++ * STM32MP1 STGEN ++ ******************************************************************************/ ++#define STGEN_BASE U(0x5C008000) ++ ++/******************************************************************************* + * STM32MP1 TIMERS + ******************************************************************************/ +#define TIM12_BASE U(0x40006000) @@ -41424,731 +40975,153 @@ index bb3fecf..a6b1a7b 100644 +#define TIM_MAX_INSTANCE U(2) + +/******************************************************************************* ++ * STM32MP1 OPP ++ ******************************************************************************/ ++#define PLAT_OPP_ID1 U(1) ++#define PLAT_OPP_ID2 U(2) ++#define PLAT_MAX_OPP_NB U(2) ++#define PLAT_MAX_PLLCFG_NB U(6) ++ ++/******************************************************************************* + * DEBUG + ******************************************************************************/ +/*#define ICACHE_OFF*/ +/*#define DCACHE_OFF*/ +/*#define MMU_OFF*/ + -+/******************************************************************************* -+ * Device Tree defines -+ ******************************************************************************/ -+#define DT_PWR_COMPAT "st,stm32mp1-pwr" -+#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" -+#define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg" + /******************************************************************************* + * Device Tree defines + ******************************************************************************/ + #define DT_BSEC_COMPAT "st,stm32mp15-bsec" ++#define DT_DDR_COMPAT "st,stm32mp1-ddr" + #define DT_IWDG_COMPAT "st,stm32mp1-iwdg" +-#define DT_PWR_COMPAT "st,stm32mp1-pwr" ++#define DT_NVMEM_LAYOUT_COMPAT "st,stm32-nvmem-layout" ++#define DT_OPP_COMPAT "operating-points-v2" ++#define DT_PWR_COMPAT "st,stm32mp1,pwr-reg" + #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" +-#define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg" ++ ++#define DT_PLL1_NODE_NAME "st,pll@0" #endif /* STM32MP1_DEF_H */ -diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c +diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c deleted file mode 100644 -index bde968a..0000000 ---- a/plat/st/stm32mp1/stm32mp1_dt.c +index 851a9cf0c..000000000 +--- a/plat/st/stm32mp1/stm32mp1_gic.c +++ /dev/null -@@ -1,476 +0,0 @@ +@@ -1,92 +0,0 @@ -/* -- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - --#include --#include -#include +- -#include --#include --#include --#include --#include --#include --#include - --#define DT_GPIO_BANK_SHIFT 12 --#define DT_GPIO_BANK_MASK 0x1F000U --#define DT_GPIO_PIN_SHIFT 8 --#define DT_GPIO_PIN_MASK 0xF00U --#define DT_GPIO_MODE_MASK 0xFFU +-#include +-#include +-#include +-#include +-#include +-#include - --static int fdt_checked; +-struct stm32_gic_instance { +- uint32_t cells; +- uint32_t phandle_node; +-}; - --static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; +-/****************************************************************************** +- * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 +- * interrupts. +- *****************************************************************************/ +-static const interrupt_prop_t stm32mp1_interrupt_props[] = { +- PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), +- PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) +-}; - --/******************************************************************************* -- * This function gets the pin settings from DT information. -- * When analyze and parsing is done, set the GPIO registers. -- * Return 0 on success, else return a negative FDT_ERR_xxx error code. -- ******************************************************************************/ --static int dt_set_gpio_config(int node) --{ -- const fdt32_t *cuint, *slewrate; -- int len, pinctrl_node, pinctrl_subnode; -- uint32_t i; -- uint32_t speed = GPIO_SPEED_LOW; -- uint32_t pull = GPIO_NO_PULL; +-/* Fix target_mask_array as secondary core is not able to initialize it */ +-static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2}; - -- cuint = fdt_getprop(fdt, node, "pinmux", &len); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } +-static gicv2_driver_data_t platform_gic_data = { +- .interrupt_props = stm32mp1_interrupt_props, +- .interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props), +- .target_masks = target_mask_array, +- .target_masks_num = ARRAY_SIZE(target_mask_array), +-}; - -- pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); -- if (pinctrl_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } +-static struct stm32_gic_instance stm32_gic; - -- slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); -- if (slewrate != NULL) { -- speed = fdt32_to_cpu(*slewrate); -- } -- -- if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { -- pull = GPIO_PULL_UP; -- } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { -- pull = GPIO_PULL_DOWN; -- } else { -- VERBOSE("No bias configured in node %d\n", node); -- } -- -- for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { -- uint32_t pincfg; -- uint32_t bank; -- uint32_t pin; -- uint32_t mode; -- uint32_t alternate = GPIO_ALTERNATE_0; -- -- pincfg = fdt32_to_cpu(*cuint); -- cuint++; -- -- bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; -- -- pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; -- -- mode = pincfg & DT_GPIO_MODE_MASK; -- -- switch (mode) { -- case 0: -- mode = GPIO_MODE_INPUT; -- break; -- case 1 ... 16: -- alternate = mode - 1U; -- mode = GPIO_MODE_ALTERNATE; -- break; -- case 17: -- mode = GPIO_MODE_ANALOG; -- break; -- default: -- mode = GPIO_MODE_OUTPUT; -- break; -- } -- -- if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { -- mode |= GPIO_OPEN_DRAIN; -- } -- -- fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { -- uint32_t bank_offset; -- const fdt32_t *cuint2; -- -- if (fdt_getprop(fdt, pinctrl_subnode, -- "gpio-controller", NULL) == NULL) { -- continue; -- } -- -- cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); -- if (cuint2 == NULL) { -- continue; -- } -- -- if (bank == GPIO_BANK_Z) { -- bank_offset = 0; -- } else { -- bank_offset = bank * STM32_GPIO_BANK_OFFSET; -- } -- -- if (fdt32_to_cpu(*cuint2) == bank_offset) { -- int clk_id = fdt_get_clock_id(pinctrl_subnode); -- -- if (clk_id < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- if (stm32mp1_clk_enable((unsigned long)clk_id) < -- 0) { -- return -FDT_ERR_BADVALUE; -- } -- -- break; -- } -- } -- -- set_gpio(bank, pin, mode, speed, pull, alternate); -- } -- -- return 0; --} -- --/******************************************************************************* -- * This function checks device tree file with its header. -- * Returns 0 if success, and a negative value else. -- ******************************************************************************/ --int dt_open_and_check(void) --{ -- int ret = fdt_check_header(fdt); -- -- if (ret == 0) { -- fdt_checked = 1; -- } -- -- return ret; --} -- --/******************************************************************************* -- * This function gets the address of the DT. -- * If DT is OK, fdt_addr is filled with DT address. -- * Returns 1 if success, 0 otherwise. -- ******************************************************************************/ --int fdt_get_address(void **fdt_addr) --{ -- if (fdt_checked == 1) { -- *fdt_addr = fdt; -- } -- -- return fdt_checked; --} -- --/******************************************************************************* -- * This function check the presence of a node (generic use of fdt library). -- * Returns true if present, false else. -- ******************************************************************************/ --bool fdt_check_node(int node) --{ -- int len; -- const char *cchar; -- -- cchar = fdt_get_name(fdt, node, &len); -- -- return (cchar != NULL) && (len >= 0); --} -- --/******************************************************************************* -- * This function check the status of a node (generic use of fdt library). -- * Returns true if "okay" or missing, false else. -- ******************************************************************************/ --bool fdt_check_status(int node) --{ -- int len; -- const char *cchar; -- -- cchar = fdt_getprop(fdt, node, "status", &len); -- if (cchar == NULL) { -- return true; -- } -- -- return strncmp(cchar, "okay", (size_t)len) == 0; --} -- --/******************************************************************************* -- * This function check the secure-status of a node (generic use of fdt library). -- * Returns true if "okay" or missing, false else. -- ******************************************************************************/ --bool fdt_check_secure_status(int node) --{ -- int len; -- const char *cchar; -- -- cchar = fdt_getprop(fdt, node, "secure-status", &len); -- if (cchar == NULL) { -- return true; -- } -- -- return strncmp(cchar, "okay", (size_t)len) == 0; --} -- --/******************************************************************************* -- * This function reads a value of a node property (generic use of fdt -- * library). -- * Returns value if success, and a default value if property not found. -- * Default value is passed as parameter. -- ******************************************************************************/ --uint32_t fdt_read_uint32_default(int node, const char *prop_name, -- uint32_t dflt_value) --{ -- const fdt32_t *cuint; -- int lenp; -- -- cuint = fdt_getprop(fdt, node, prop_name, &lenp); -- if (cuint == NULL) { -- return dflt_value; -- } -- -- return fdt32_to_cpu(*cuint); --} -- --/******************************************************************************* -- * This function reads a series of parameters in a node property -- * (generic use of fdt library). -- * It reads the values inside the device tree, from property name and node. -- * The number of parameters is also indicated as entry parameter. -- * Returns 0 if success, and a negative value else. -- * If success, values are stored at the third parameter address. -- ******************************************************************************/ --int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, -- uint32_t count) --{ -- const fdt32_t *cuint; -- int len; -- uint32_t i; -- -- cuint = fdt_getprop(fdt, node, prop_name, &len); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- if ((uint32_t)len != (count * sizeof(uint32_t))) { -- return -FDT_ERR_BADLAYOUT; -- } -- -- for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { -- *array = fdt32_to_cpu(*cuint); -- array++; -- cuint++; -- } -- -- return 0; --} -- --/******************************************************************************* -- * This function gets the pin settings from DT information. -- * When analyze and parsing is done, set the GPIO registers. -- * Returns 0 if success, and a negative value else. -- ******************************************************************************/ --int dt_set_pinctrl_config(int node) --{ -- const fdt32_t *cuint; -- int lenp = 0; -- uint32_t i; -- -- if (!fdt_check_status(node)) { -- return -FDT_ERR_NOTFOUND; -- } -- -- cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- for (i = 0; i < ((uint32_t)lenp / 4U); i++) { -- int phandle_node, phandle_subnode; -- -- phandle_node = -- fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); -- if (phandle_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) { -- int ret = dt_set_gpio_config(phandle_subnode); -- -- if (ret < 0) { -- return ret; -- } -- } -- -- cuint++; -- } -- -- return 0; --} -- --/******************************************************************************* -- * This function gets the stdout pin configuration information from the DT. -- * And then calls the sub-function to treat it and set GPIO registers. -- * Returns 0 if success, and a negative value else. -- ******************************************************************************/ --int dt_set_stdout_pinctrl(void) +-void stm32mp1_gic_init(void) -{ - int node; +- void *fdt; +- const fdt32_t *cuint; +- struct dt_node_info dt_gic; - -- node = dt_get_stdout_node_offset(); -- if (node < 0) { -- return -FDT_ERR_NOTFOUND; +- if (fdt_get_address(&fdt) == 0) { +- panic(); - } - -- return dt_set_pinctrl_config(node); --} +- node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic"); +- if (node < 0) { +- panic(); +- } - --/******************************************************************************* -- * This function fills the generic information from a given node. -- ******************************************************************************/ --void dt_fill_device_info(struct dt_node_info *info, int node) --{ -- const fdt32_t *cuint; +- platform_gic_data.gicd_base = dt_gic.base; - - cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint != NULL) { -- info->base = fdt32_to_cpu(*cuint); -- } else { -- info->base = 0; +- if (cuint == NULL) { +- panic(); - } - -- cuint = fdt_getprop(fdt, node, "clocks", NULL); -- if (cuint != NULL) { -- cuint++; -- info->clock = (int)fdt32_to_cpu(*cuint); -- } else { -- info->clock = -1; +- platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2)); +- +- cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); +- if (cuint == NULL) { +- panic(); - } - -- cuint = fdt_getprop(fdt, node, "resets", NULL); -- if (cuint != NULL) { -- cuint++; -- info->reset = (int)fdt32_to_cpu(*cuint); -- } else { -- info->reset = -1; +- stm32_gic.cells = fdt32_to_cpu(*cuint); +- +- stm32_gic.phandle_node = fdt_get_phandle(fdt, node); +- if (stm32_gic.phandle_node == 0U) { +- panic(); - } - -- info->status = fdt_check_status(node); -- info->sec_status = fdt_check_secure_status(node); +- gicv2_driver_init(&platform_gic_data); +- gicv2_distif_init(); +- +- stm32mp1_gic_pcpu_init(); -} - --/******************************************************************************* -- * This function retrieve the generic information from DT. -- * Returns node if success, and a negative value else. -- ******************************************************************************/ --int dt_get_node(struct dt_node_info *info, int offset, const char *compat) +-void stm32mp1_gic_pcpu_init(void) -{ -- int node; -- -- node = fdt_node_offset_by_compatible(fdt, offset, compat); -- if (node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- dt_fill_device_info(info, node); -- -- return node; +- gicv2_pcpu_distif_init(); +- gicv2_set_pe_target_mask(plat_my_core_pos()); +- gicv2_cpuif_enable(); -} -- --/******************************************************************************* -- * This function gets the UART instance info of stdout from the DT. -- * Returns node if success, and a negative value else. -- ******************************************************************************/ --int dt_get_stdout_uart_info(struct dt_node_info *info) --{ -- int node; -- -- node = dt_get_stdout_node_offset(); -- if (node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- dt_fill_device_info(info, node); -- -- return node; --} -- --/******************************************************************************* -- * This function gets the stdout path node. -- * It reads the value indicated inside the device tree. -- * Returns node if success, and a negative value else. -- ******************************************************************************/ --int dt_get_stdout_node_offset(void) --{ -- int node; -- const char *cchar; -- -- node = fdt_path_offset(fdt, "/chosen"); -- if (node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- cchar = fdt_getprop(fdt, node, "stdout-path", NULL); -- if (cchar == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- node = -FDT_ERR_NOTFOUND; -- if (strchr(cchar, (int)':') != NULL) { -- const char *name; -- char *str = (char *)cchar; -- int len = 0; -- -- while (strncmp(":", str, 1)) { -- len++; -- str++; -- } -- -- name = fdt_get_alias_namelen(fdt, cchar, len); -- -- if (name != NULL) { -- node = fdt_path_offset(fdt, name); -- } -- } else { -- node = fdt_path_offset(fdt, cchar); -- } -- -- return node; --} -- --/******************************************************************************* -- * This function gets DDR size information from the DT. -- * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else. -- ******************************************************************************/ --uint32_t dt_get_ddr_size(void) --{ -- int node; -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -- if (node < 0) { -- INFO("%s: Cannot read DDR node in DT\n", __func__); -- return STM32MP1_DDR_SIZE_DFLT; -- } -- -- return fdt_read_uint32_default(node, "st,mem-size", -- STM32MP1_DDR_SIZE_DFLT); --} -- --/******************************************************************************* -- * This function retrieves board model from DT -- * Returns string taken from model node, NULL otherwise -- ******************************************************************************/ --const char *dt_get_board_model(void) --{ -- int node = fdt_path_offset(fdt, "/"); -- -- if (node < 0) { -- return NULL; -- } -- -- return (const char *)fdt_getprop(fdt, node, "model", NULL); --} -diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c -index 11eb0a3..498093d 100644 ---- a/plat/st/stm32mp1/stm32mp1_gic.c -+++ b/plat/st/stm32mp1/stm32mp1_gic.c -@@ -4,13 +4,21 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - -+#include - #include -+#include - #include -+#include - #include - #include -+#include -+#include - #include - --#include -+struct stm32_gic_instance { -+ uint32_t cells; -+ uint32_t phandle_node; -+}; - - /****************************************************************************** - * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 -@@ -21,19 +29,114 @@ static const interrupt_prop_t stm32mp1_interrupt_props[] = { - PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) - }; - --static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; -+/* Fix target_mask_array as secondary core is not able to initialize it */ -+static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2}; - --static const gicv2_driver_data_t platform_gic_data = { -- .gicd_base = STM32MP1_GICD_BASE, -- .gicc_base = STM32MP1_GICC_BASE, -+static gicv2_driver_data_t platform_gic_data = { - .interrupt_props = stm32mp1_interrupt_props, - .interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props), - .target_masks = target_mask_array, - .target_masks_num = ARRAY_SIZE(target_mask_array), - }; - -+static struct stm32_gic_instance stm32_gic; -+ -+static uint32_t enable_gic_interrupt(const fdt32_t *array) -+{ -+ unsigned int id, cfg; -+ -+ switch (fdt32_to_cpu(*array)) { -+ case GIC_SPI: -+ id = MIN_SPI_ID; -+ break; -+ -+ case GIC_PPI: -+ id = MIN_PPI_ID; -+ break; -+ -+ default: -+ id = MIN_SGI_ID; -+ break; -+ } -+ -+ id += fdt32_to_cpu(*(array + 1)); -+ cfg = (fdt32_to_cpu(*(array + 2)) < IRQ_TYPE_LEVEL_HIGH) ? -+ GIC_INTR_CFG_EDGE : GIC_INTR_CFG_LEVEL; -+ -+ if ((id >= MIN_SPI_ID) && (id <= MAX_SPI_ID)) { -+ VERBOSE("Enable IT %i\n", id); -+ gicv2_set_interrupt_type(id, GICV2_INTR_GROUP0); -+ gicv2_set_interrupt_priority(id, STM32MP1_IRQ_SEC_SPI_PRIO); -+ gicv2_set_spi_routing(id, STM32MP_PRIMARY_CPU); -+ gicv2_interrupt_set_cfg(id, cfg); -+ gicv2_enable_interrupt(id); -+ } -+ -+ return id; -+} -+ -+static void find_next_interrupt(const fdt32_t **array) -+{ -+ int node; -+ const fdt32_t *cuint; -+ void *fdt; -+ -+ assert(fdt32_to_cpu(**array) != stm32_gic.phandle_node); -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(**array)); -+ if (node < 0) { -+ panic(); -+ } -+ -+ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); -+ if (cuint == NULL) { -+ panic(); -+ } -+ -+ *array += fdt32_to_cpu(*cuint) + 1; -+} -+ - void stm32mp1_gic_init(void) - { -+ int node; -+ void *fdt; -+ const fdt32_t *cuint; -+ struct dt_node_info dt_gic; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic"); -+ if (node < 0) { -+ panic(); -+ } -+ -+ platform_gic_data.gicd_base = dt_gic.base; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ panic(); -+ } -+ -+ platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2)); -+ -+ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); -+ if (cuint == NULL) { -+ panic(); -+ } -+ -+ stm32_gic.cells = fdt32_to_cpu(*cuint); -+ -+ stm32_gic.phandle_node = fdt_get_phandle(fdt, node); -+ if (stm32_gic.phandle_node == 0U) { -+ panic(); -+ } -+ - gicv2_driver_init(&platform_gic_data); - gicv2_distif_init(); - -@@ -46,3 +149,63 @@ void stm32mp1_gic_pcpu_init(void) - gicv2_set_pe_target_mask(plat_my_core_pos()); - gicv2_cpuif_enable(); - } -+ -+int stm32_gic_enable_spi(int node, const char *name) -+{ -+ const fdt32_t *cuint; -+ void *fdt; -+ int res, len; -+ int index = -1; -+ int i = 0; -+ int id = -1; -+ bool extended; -+ const fdt32_t *t_array, *max; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ cuint = fdt_getprop(fdt, node, "interrupt-parent", NULL); -+ if (cuint != NULL) { -+ if (stm32_gic.phandle_node != fdt32_to_cpu(*cuint)) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ } -+ -+ if (name != NULL) { -+ index = fdt_stringlist_search(fdt, node, "interrupt-names", -+ name); -+ if (index < 0) { -+ return index; -+ } -+ } -+ -+ res = fdt_get_interrupt(node, &t_array, &len, &extended); -+ if (res < 0) { -+ return res; -+ } -+ -+ max = t_array + (len / sizeof(uint32_t)); -+ -+ while ((t_array < max) && ((i <= index) || (index == -1))) { -+ if (!extended) { -+ if ((index == -1) || (i == index)) { -+ id = enable_gic_interrupt(t_array); -+ } -+ t_array += stm32_gic.cells; -+ } else { -+ if (fdt32_to_cpu(*t_array) == stm32_gic.phandle_node) { -+ t_array++; -+ if ((index == -1) || (i == index)) { -+ id = enable_gic_interrupt(t_array); -+ } -+ t_array += stm32_gic.cells; -+ } else { -+ find_next_interrupt(&t_array); -+ } -+ } -+ i++; -+ } -+ -+ return id; -+} diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S -index b0ea0d8..1adaaee 100644 +index bfcd991a3..b80716253 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S -@@ -8,17 +8,20 @@ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -10,12 +10,17 @@ #include - #include - #include + #include + #include +#include - #include - #include --#define GPIO_BANK_G_ADDRESS 0x50008000 --#define GPIO_TX_PORT 11 --#define GPIO_TX_SHIFT (GPIO_TX_PORT << 1) --#define GPIO_TX_ALT_SHIFT ((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2) --#define STM32MP1_HSI_CLK 64000000 -+#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) -+#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2) + #define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) +-#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2) .globl platform_mem_init .globl plat_report_exception @@ -42160,7 +41133,7 @@ index b0ea0d8..1adaaee 100644 .globl plat_get_my_entrypoint .globl plat_secondary_cold_boot_setup .globl plat_reset_handler -@@ -28,6 +31,7 @@ +@@ -25,6 +30,7 @@ .globl plat_crash_console_flush .globl plat_crash_console_putc .globl plat_panic_handler @@ -42168,7 +41141,7 @@ index b0ea0d8..1adaaee 100644 func platform_mem_init /* Nothing to do, don't need to init SYSRAM */ -@@ -35,9 +39,138 @@ func platform_mem_init +@@ -32,9 +38,138 @@ func platform_mem_init endfunc platform_mem_init func plat_report_exception @@ -42307,101 +41280,46 @@ index b0ea0d8..1adaaee 100644 func plat_reset_handler bx lr endfunc plat_reset_handler -@@ -76,7 +209,7 @@ func plat_is_my_cpu_primary - ldcopr r0, MPIDR - ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) - and r0, r1 -- cmp r0, #STM32MP1_PRIMARY_CPU -+ cmp r0, #STM32MP_PRIMARY_CPU - moveq r0, #1 - movne r0, #0 - bx lr -@@ -111,13 +244,13 @@ endfunc plat_my_core_pos - * --------------------------------------------- - */ - func plat_crash_console_init -- /* Enable GPIOs for UART4 TX */ -- ldr r1, =(RCC_BASE + RCC_MP_AHB4ENSETR) -+ /* Enable GPIOs for UART TX */ -+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) - ldr r2, [r1] -- /* Configure GPIO G11 */ -- orr r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN -+ /* Configure GPIO */ -+ orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN - str r2, [r1] -- ldr r1, =GPIO_BANK_G_ADDRESS -+ ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS - /* Set GPIO mode alternate */ - ldr r2, [r1, #GPIO_MODE_OFFSET] - bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT) -@@ -131,25 +264,24 @@ func plat_crash_console_init - ldr r2, [r1, #GPIO_PUPD_OFFSET] +@@ -129,10 +264,16 @@ func plat_crash_console_init bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) str r2, [r1, #GPIO_PUPD_OFFSET] -- /* Set alternate AF6 */ -+ /* Set alternate */ - ldr r2, [r1, #GPIO_AFRH_OFFSET] - bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT) -- orr r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT) -+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT) - str r2, [r1, #GPIO_AFRH_OFFSET] -- -- /* Enable UART clock, with HSI source */ -- ldr r1, =(RCC_BASE + RCC_UART24CKSELR) -- mov r2, #RCC_UART24CKSELR_HSI -+ /* Enable UART clock, with its source */ -+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) -+ mov r2, #DEBUG_UART_TX_CLKSRC - str r2, [r1] -- ldr r1, =(RCC_BASE + RCC_MP_APB1ENSETR) -+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG) - ldr r2, [r1] -- orr r2, r2, #RCC_MP_APB1ENSETR_UART4EN -+ orr r2, r2, #DEBUG_UART_TX_EN - str r2, [r1] - -- ldr r0, =STM32MP1_DEBUG_USART_BASE -- ldr r1, =STM32MP1_HSI_CLK -- ldr r2, =STM32MP1_UART_BAUDRATE -- b console_core_init -+ ldr r0, =STM32MP_DEBUG_USART_BASE -+ ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ -+ ldr r2, =STM32MP_UART_BAUDRATE -+ b console_stm32_core_init - endfunc plat_crash_console_init - - /* --------------------------------------------- -@@ -159,8 +291,8 @@ endfunc plat_crash_console_init - * --------------------------------------------- - */ - func plat_crash_console_flush -- ldr r1, =STM32MP1_DEBUG_USART_BASE -- b console_core_flush -+ ldr r1, =STM32MP_DEBUG_USART_BASE -+ b console_stm32_core_flush - endfunc plat_crash_console_flush - - /* --------------------------------------------- -@@ -175,6 +307,68 @@ endfunc plat_crash_console_flush - * --------------------------------------------- - */ - func plat_crash_console_putc -- ldr r1, =STM32MP1_DEBUG_USART_BASE -- b console_core_putc -+ ldr r1, =STM32MP_DEBUG_USART_BASE -+ b console_stm32_core_putc + /* Set alternate */ +- ldr r2, [r1, #GPIO_AFRH_OFFSET] +- bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT) +- orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT) +- str r2, [r1, #GPIO_AFRH_OFFSET] ++ ldr r2, =DEBUG_UART_TX_GPIO_PORT ++ cmp r2, #GPIO_ALT_LOWER_LIMIT ++ ldrge r2, [r1, #GPIO_AFRH_OFFSET] ++ bicge r2, r2, #(GPIO_ALTERNATE_MASK << ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) ++ orrge r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) ++ strge r2, [r1, #GPIO_AFRH_OFFSET] ++ ldrlt r2, [r1, #GPIO_AFRL_OFFSET] ++ biclt r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2)) ++ orrlt r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2)) ++ strlt r2, [r1, #GPIO_AFRL_OFFSET] + /* Enable UART clock, with its source */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) + mov r2, #DEBUG_UART_TX_CLKSRC +@@ -174,3 +315,70 @@ func plat_crash_console_putc + ldr r1, =STM32MP_DEBUG_USART_BASE + 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 + @@ -42445,8 +41363,8 @@ index b0ea0d8..1adaaee 100644 + str r4, [sp, #SMC_CTX_SCR] + cps #MODE32_svc + cpsie af -+ isb + dsb ++ isb + wfi + cpsid af + cps #MODE32_mon @@ -42454,283 +41372,51 @@ index b0ea0d8..1adaaee 100644 + pop {r4,r8,lr} + bx lr +endfunc wfi_svc_int_enable -diff --git a/plat/st/stm32mp1/stm32mp1_helper_dbg.S b/plat/st/stm32mp1/stm32mp1_helper_dbg.S -new file mode 100644 -index 0000000..32a86fb ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_helper_dbg.S -@@ -0,0 +1,227 @@ -+/* -+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+/***************************************************************************** -+ * This file is only needed for current Soc revision which has a limitation on -+ * debug reset halt. This can be removed when using the Soc revision that -+ * fixes the limitation. Anyway, this source code identifies the Soc revision -+ * and is only executed if it corresponds, so it can be kept on other -+ * revisions without any consequence. -+ ****************************************************************************/ -+ -+/***************************************************************************** -+ * This file has been intentionally transformed in order to use only ASM -+ * standard macros and instructions. It could then be easily back-ported to -+ * other pieces of software. -+ ****************************************************************************/ -+ -+#define BIT_(nr) ((1) << (nr)) -+ -+#define BSEC_BASE 0x5C005000 -+#define BSEC_OTP_DATA_OFF (BSEC_BASE + 0x200) -+#define BSEC_OTP_DATA0 BSEC_OTP_DATA_OFF -+#define BSEC_OTP_DATA0_CLOSED BIT_(6) -+ -+#define DBGMCU_BASE 0x50081000 -+#define DBGMCU_IDC 0x00 -+#define DBGMCU_IDC_REV_ID_DEV_ID_MSK 0xFFFF0FFF -+#define DBGMCU_IDC_REV_ID_DEV_ID_VALUE 0x20000500 -+ -+#define RCC_BASE 0x50000000 -+#define RCC_MP_APB5ENSETR 0x208 -+#define RCC_MP_APB5ENSETR_RTCAPBEN BIT_(8) -+#define RCC_DBGCFGR 0x80C -+#define RCC_DBGCFGR_DBGCKEN BIT_(8) -+ -+#define PWR_BASE 0x50001000 -+#define PWR_CR1 0x00 -+#define PWR_CR1_DBP BIT_(8) -+ -+#define TAMP_BASE 0x5C00A000 -+#define TAMP_BKP_REGISTER_BASE TAMP_BASE + 0x100 -+#define TAMP_BKP_REGISTER_20 TAMP_BKP_REGISTER_BASE + (20 << 2) -+ -+#define CA7_DBG0_BASE 0x500D0000 -+#define DBG_DSCR 0x88 -+#define DBG_DSCR_HDBGEN BIT_(14) -+ -+#define FSBL_ENTRYPOINT bl2_entrypoint -+ -+ .globl plat_dbg_attach_loop -+ -+ -+plat_dbg_attach_loop: -+ /* -+ * This function is the first call of FSBL_ENTRYPOINT. -+ * Boot rom parameters are stored in r0..r3, so we mustn't use them -+ * here. And because they are saved in r9..r12 just after the -+ * execution of this function, we should only use these registers. -+ * By this way, debug will be done in conditions closed to the initial -+ * context. -+ */ -+ -+ /* -+ * Check Sec Close bit in OTP (word 0 bit 6). If enabled, do not allow -+ * debug session and exit function. -+ */ -+ ldr r12, =BSEC_OTP_DATA0 -+ ldr r12, [r12] -+ ands r11, r12, #BSEC_OTP_DATA0_CLOSED -+ bne func_exit -+ -+ /* -+ * Enable DBGMCU clock (only if not done). -+ * Initial register content will be saved in r10. -+ * So r10 mustn't be used before restore part. -+ */ -+ ldr r12, =(RCC_BASE + RCC_DBGCFGR) -+ ldr r10, [r12] -+ tst r10, #RCC_DBGCFGR_DBGCKEN -+ bne dbgmcu_clk_enabled -+ orr r11, r10, #RCC_DBGCFGR_DBGCKEN -+ str r11, [r12] -+ -+ /* Get SoC revision ID and device ID in r11 */ -+dbgmcu_clk_enabled: -+ ldr r12, =(DBGMCU_BASE + DBGMCU_IDC) -+ ldr r12, [r12] -+ and r11, r12, #DBGMCU_IDC_REV_ID_DEV_ID_MSK -+ -+ /* Restore initial RCC_DBGCFGR content saved in r10 */ -+ ldr r12, =(RCC_BASE + RCC_DBGCFGR) -+ str r10, [r12] -+ -+ /* -+ * Check SoC revision ID and device ID in r11, -+ * exit if different from REV_ID_DEV_ID_VALUE -+ */ -+ ldr r12, =(DBGMCU_IDC_REV_ID_DEV_ID_VALUE) -+ teq r11, r12 -+ bne func_exit -+ -+ /* -+ * Enable RTC clock before reading tamper (only if not done). -+ * Initial register content will be saved in r10. -+ * So r10 mustn't be used before restore part. -+ */ -+ ldr r12, =(RCC_BASE + RCC_MP_APB5ENSETR) -+ ldr r10, [r12] -+ tst r10, #RCC_MP_APB5ENSETR_RTCAPBEN -+ bne rtc_clk_enabled -+ orr r11, r10, #RCC_MP_APB5ENSETR_RTCAPBEN -+ str r11, [r12] -+ -+rtc_clk_enabled: -+ /* -+ * Disable the backup domain write protection (only if not done). -+ * Initial register content will be saved in r9. -+ * So r9 mustn't be used before restore part. -+ */ -+ ldr r12, =(PWR_BASE + PWR_CR1) -+ ldr r9, [r12] -+ tst r9, #PWR_CR1_DBP -+ bne poll_dbp -+ orr r11, r9, #PWR_CR1_DBP -+ str r11, [r12] -+poll_dbp: -+ /* poll loop to ensure write is effective */ -+ ldr r11, [r12] -+ tst r11, #PWR_CR1_DBP -+ beq poll_dbp -+ -+ /* -+ * Clear bit 16 of TAMPER backup register 20 (only if set). -+ * Firstly read the register value. -+ * - If bit = 0, r11 = 0 after 'ands' operation. Next step is to -+ * restore RCC_MP_APB5ENSETR and PWR_CR1 contents and exit. -+ * - If bit = 1, r11 != 0 after 'ands' operation, but could be -+ * equal to 0 after 'bic' operation. Here, after clearing the bit, -+ * r11 has to be set to a non-zero value. Next step is to restore -+ * register contents and continue. -+ * -+ * So r11 mustn't be used in restore part, to keep this information -+ * for the next step, i.e. decide to continue execution (r11 = 1) or -+ * exit function (r11 = 0). -+ */ -+ ldr r12, =(TAMP_BKP_REGISTER_20) -+ ldr r11, [r12] -+ ands r11, r11, #(BIT_(16)) -+ beq restore_reg -+ ldr r11, [r12] -+ bic r11, #(BIT_(16)) -+ str r11, [r12] -+ ldr r11, =(1) -+ -+restore_reg: -+ /* Restore initial RCC_MP_APB5ENSETR content saved in r10 */ -+ ldr r12, =(RCC_BASE + RCC_MP_APB5ENSETR) -+ str r10, [r12] -+ -+ /* Restore initial PWR_CR1 content saved in r9 */ -+ ldr r12, =(PWR_BASE + PWR_CR1) -+ str r9, [r12] -+poll_cr1: -+ /* poll loop to ensure write is effective */ -+ ldr r12, =(PWR_BASE + PWR_CR1) -+ ldr r12, [r12] -+ teq r12, r9 -+ bne poll_cr1 -+ -+ /* -+ * Exit if bit 16 of TAMPER backup register 20 has been cleared. -+ * Information is saved in r11 register. -+ */ -+ teq r11, #0 -+ beq func_exit -+ -+ /* Get time counter frequency */ -+ mrc 15, 0, r12, cr14, cr0, 0 -+ /* Get current time counter value, save it in r11 as start value */ -+ mrrc 15, 0, r11, r10, cr14 -+ /* -+ * Compute (current time + 1 second) counter value, save it in r12 as -+ * end value. -+ */ -+ add r12, r12, r11 -+ -+loop: -+ /* -+ * Read CA7_DBG0 DBG_DSCR HDBGEN bit value. -+ * If set, put a software breakpoint and branch to FSBL_ENTRYPOINT. -+ * If cleared, continue and check loop time expiry -+ */ -+ ldr r10, =(CA7_DBG0_BASE + DBG_DSCR) -+ ldr r10, [r10] -+ tst r10, #DBG_DSCR_HDBGEN -+ beq loop_continue -+ /* Set a software breakpoint (ID 5) */ -+ bkpt 5 -+ /* Jump to entrypoint */ -+ b FSBL_ENTRYPOINT -+loop_continue: -+ /* -+ * Check 1 second expiry by using r11 and r12 saved values. -+ * Get current time counter value, save it in r10 as current value. -+ */ -+ mrrc 15, 0, r10, r9, cr14 -+ /* Check if MSB 64-bit increment done between start and end values */ -+ cmp r12, r11 -+ bmi msb_incr -+ /* No increment, simply check if current < end, exit if yes */ -+ cmp r12, r10 -+ bmi func_exit -+ b loop -+msb_incr: -+ /* -+ * Increment happened between start and end, here we need to check if -+ * (current > end) && (current < start). Exit if yes. -+ */ -+ cmp r12, r10 -+ bpl loop -+ cmp r11, r10 -+ bmi loop -+func_exit: -+ bx lr diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c new file mode 100644 -index 0000000..de9035c +index 000000000..fb975f5f6 --- /dev/null +++ b/plat/st/stm32mp1/stm32mp1_low_power.c -@@ -0,0 +1,311 @@ +@@ -0,0 +1,346 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, 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 -+#include -+#include -+#include -+#include -+#include -+#include ++#include ++#include ++ ++#include +#include +#include -+#include -+#include +#include -+#include +#include +#include -+#include -+#include -+#include -+#include + +static unsigned int gicc_pmr; -+static struct stm32_rtc_calendar sleep_time, current_calendar; -+static unsigned long long stdby_time_in_ms; ++static struct stm32_rtc_calendar sleep_time; +static bool enter_cstop_done; -+static uint8_t int_stack[STM32MP_INT_STACK_SIZE]; ++static uint32_t int_stack[STM32MP_INT_STACK_SIZE]; + +extern void wfi_svc_int_enable(uintptr_t stack_addr); + @@ -42796,11 +41482,11 @@ index 0000000..de9035c + panic(); + } + -+ if (dt_pmic_set_lp_config(node_name) != 0) { ++ if (pmic_set_lp_config(node_name) < 0) { + panic(); + } + -+ if (dt_pmic_configure_boot_on_regulators() != 0) { ++ if (pmic_configure_boot_on_regulators() < 0) { + panic(); + } + } @@ -42824,6 +41510,11 @@ index 0000000..de9035c + uintptr_t pwr_base = stm32mp_pwr_base(); + uintptr_t rcc_base = stm32mp_rcc_base(); + ++ stm32mp1_syscfg_disable_io_compensation(); ++ ++ /* Switch to Software Self-Refresh mode */ ++ ddr_set_sr_mode(DDR_SSR_MODE); ++ + dcsw_op_all(DC_OP_CISW); + + stm32_clean_context(); @@ -42863,7 +41554,7 @@ index 0000000..de9035c + mmio_setbits_32(rcc_base + RCC_MP_SREQSETR, + RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); + -+ stm32_iwdg_refresh(IWDG2_INST); ++ stm32_iwdg_refresh(); + + gicc_pmr = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8); + @@ -42872,7 +41563,7 @@ index 0000000..de9035c + * This is also the procedure awaited when switching off power supply. + */ + if (ddr_standby_sr_entry(&zq0cr0_zdata) != 0) { -+ return; ++ panic(); + } + + stm32mp_clk_enable(RTCAPB); @@ -42880,8 +41571,9 @@ index 0000000..de9035c + mmio_write_32(bkpr_core1_addr, 0); + mmio_write_32(bkpr_core1_magic, 0); + -+ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { ++ stm32mp1_clock_stopmode_save(); + ++ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { + /* + * Save non-secure world entrypoint after standby in Backup + * register @@ -42893,6 +41585,14 @@ index 0000000..de9035c + 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); @@ -42907,7 +41607,10 @@ index 0000000..de9035c + */ +void stm32_exit_cstop(void) +{ ++ uintptr_t pwr_base = stm32mp_pwr_base(); + uintptr_t rcc_base = stm32mp_rcc_base(); ++ unsigned long long stdby_time_in_ms; ++ struct stm32_rtc_calendar current_calendar; + + if (!enter_cstop_done) { + return; @@ -42919,6 +41622,9 @@ index 0000000..de9035c + panic(); + } + ++ /* Switch to memorized Self-Refresh mode */ ++ ddr_restore_sr_mode(); ++ + plat_ic_set_priority_mask(gicc_pmr); + + /* Disable RCC Wake-up */ @@ -42931,17 +41637,31 @@ index 0000000..de9035c + 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); + + stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, + &sleep_time); ++ stm32mp_stgen_restore_counter(stm32_get_stgen_from_context(), ++ stdby_time_in_ms); + -+ stm32mp1_stgen_increment(stdby_time_in_ms); ++ stm32mp1_syscfg_enable_io_compensation(); ++ ++ if (stm32mp1_clock_stopmode_resume() != 0) { ++ panic(); ++ } +} + +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(); @@ -42989,10 +41709,10 @@ index 0000000..de9035c +{ + 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(); @@ -43001,126 +41721,84 @@ index 0000000..de9035c + gicv2_end_of_interrupt(interrupt); + } + -+ stm32_iwdg_refresh(IWDG2_INST); ++ stm32_iwdg_refresh(); + } +} diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c -index e24af0e..20a2f5c 100644 +index cf9fa8e69..627d209da 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c -@@ -7,7 +7,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -16,14 +18,16 @@ +@@ -10,17 +10,24 @@ #include - #include - #include --#include -+#include + + #include ++#include + #include + #include + #include ++#include + #include ++#include + #include + #include + #include + #include + +#include +#include - #include - #include -+#include - --static uint32_t stm32_sec_entrypoint; -+static uintptr_t stm32_sec_entrypoint; ++ + static uintptr_t stm32_sec_entrypoint; static uint32_t cntfrq_core0; -- --#define SEND_SECURE_IT_TO_CORE_1 0x20000U +static uintptr_t saved_entrypoint; /******************************************************************************* * STM32MP1 handler called when a CPU is about to enter standby. -@@ -39,6 +43,7 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) - * Enter standby state - * dsb is good practice before using wfi to enter low power states +@@ -33,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(); +- isb(); dsb(); ++ isb(); while (interrupt == GIC_SPURIOUS_INTERRUPT) { wfi(); -@@ -56,33 +61,43 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) - /******************************************************************************* - * STM32MP1 handler called when a power domain is about to be turned on. The - * mpidr determines the CPU to be turned on. -- * call by core 0 to activate core 1 -+ * call by core 0 to activate core 1 - ******************************************************************************/ - static int stm32_pwr_domain_on(u_register_t mpidr) - { - unsigned long current_cpu_mpidr = read_mpidr_el1(); -- uint32_t tamp_clk_off = 0; - uint32_t bkpr_core1_addr = - tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); + +@@ -64,13 +72,25 @@ static int stm32_pwr_domain_on(u_register_t mpidr) uint32_t bkpr_core1_magic = tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); -+ int result; -+ -+ result = stm32mp_is_single_core(); -+ if (result < 0) { -+ return PSCI_E_INTERN_FAIL; -+ } -+ -+ if (result == 1) { -+ return PSCI_E_INTERN_FAIL; -+ } ++ if (stm32mp_is_single_core()) { ++ return PSCI_E_INTERN_FAIL; ++ } ++ if (mpidr == current_cpu_mpidr) { return PSCI_E_INVALID_PARAMS; } -- if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) || -- (stm32_sec_entrypoint > (STM32MP1_SRAM_BASE + -- (STM32MP1_SRAM_SIZE - 1)))) { +- if ((stm32_sec_entrypoint < STM32MP_SYSRAM_BASE) || +- (stm32_sec_entrypoint > (STM32MP_SYSRAM_BASE + +- (STM32MP_SYSRAM_SIZE - 1)))) { ++ /* 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); + + /* Wait for this IT to be acknowledged by ROM code. */ + udelay(10); + -+ if ((stm32_sec_entrypoint < STM32MP_SYSRAM_BASE) || -+ (stm32_sec_entrypoint > (STM32MP_SYSRAM_BASE + -+ (STM32MP_SYSRAM_SIZE - 1)))) { ++ /* Only one valid entry point */ ++ if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) { return PSCI_E_INVALID_ADDRESS; } -- if (!stm32mp1_clk_is_enabled(RTCAPB)) { -- tamp_clk_off = 1; -- if (stm32mp1_clk_enable(RTCAPB) != 0) { -- panic(); -- } -- } -+ stm32mp_clk_enable(RTCAPB); - - cntfrq_core0 = read_cntfrq_el0(); - -@@ -92,15 +107,10 @@ static int stm32_pwr_domain_on(u_register_t mpidr) - /* Write magic number in backup register */ - mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER); - -- if (tamp_clk_off != 0U) { -- if (stm32mp1_clk_disable(RTCAPB) != 0) { -- panic(); -- } -- } -+ stm32mp_clk_disable(RTCAPB); - - /* Generate an IT to core 1 */ -- mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR, -- SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0); -+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); - - return PSCI_E_SUCCESS; - } -@@ -120,7 +130,9 @@ static void stm32_pwr_domain_off(const psci_power_state_t *target_state) +@@ -107,7 +127,9 @@ static void stm32_pwr_domain_off(const psci_power_state_t *target_state) ******************************************************************************/ static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state) { @@ -43131,7 +41809,16 @@ index e24af0e..20a2f5c 100644 } /******************************************************************************* -@@ -147,22 +159,63 @@ static void stm32_pwr_domain_suspend_finish(const psci_power_state_t +@@ -118,7 +140,7 @@ static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state) + ******************************************************************************/ + static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state) + { +- stm32mp1_gic_pcpu_init(); ++ stm32_gic_pcpu_init(); + + write_cntfrq_el0(cntfrq_core0); + } +@@ -134,16 +156,59 @@ static void stm32_pwr_domain_suspend_finish(const psci_power_state_t /* Nothing to do, power domain is not disabled */ } @@ -43160,9 +41847,12 @@ index e24af0e..20a2f5c 100644 + 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 */ @@ -43174,7 +41864,7 @@ index e24af0e..20a2f5c 100644 - ERROR("stm32mpu1 System Off: operation not handled.\n"); + uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF); + -+ if (stm32mp_is_single_core() == 0) { ++ if (!stm32mp_is_single_core()) { + /* Prepare Core 1 reset */ + mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, + RCC_MP_GRSTCSETR_MPUP1RST); @@ -43190,20 +41880,7 @@ index e24af0e..20a2f5c 100644 panic(); } - static void __dead2 stm32_system_reset(void) - { -- mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); -+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, -+ RCC_MP_GRSTCSETR_MPSYSRST); - - /* Loop in case system reset is not immediately caught */ - for ( ; ; ) { -@@ -196,10 +249,12 @@ static int stm32_validate_power_state(unsigned int power_state, - static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) - { - /* The non-secure entry point must be in DDR */ -- if (entrypoint < STM32MP1_DDR_BASE) { -+ if (entrypoint < STM32MP_DDR_BASE) { +@@ -188,6 +253,8 @@ static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) return PSCI_E_INVALID_ADDRESS; } @@ -43212,7 +41889,7 @@ index e24af0e..20a2f5c 100644 return PSCI_E_SUCCESS; } -@@ -223,6 +278,12 @@ static int stm32_node_hw_state(u_register_t target_cpu, +@@ -211,6 +278,12 @@ static int stm32_node_hw_state(u_register_t target_cpu, return (int)HW_ON; } @@ -43225,7 +41902,7 @@ index e24af0e..20a2f5c 100644 /******************************************************************************* * Export the platform handlers. The ARM Standard platform layer will take care * of registering the handlers with PSCI. -@@ -239,7 +300,8 @@ static const plat_psci_ops_t stm32_psci_ops = { +@@ -227,7 +300,8 @@ static const plat_psci_ops_t stm32_psci_ops = { .system_reset = stm32_system_reset, .validate_power_state = stm32_validate_power_state, .validate_ns_entrypoint = stm32_validate_ns_entrypoint, @@ -43237,26 +41914,28 @@ index e24af0e..20a2f5c 100644 /******************************************************************************* diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c new file mode 100644 -index 0000000..ec7ecb1 +index 000000000..079c5eece --- /dev/null +++ b/plat/st/stm32mp1/stm32mp1_power_config.c -@@ -0,0 +1,193 @@ +@@ -0,0 +1,187 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include -+#include -+#include +#include -+#include +#include ++ ++#include ++ ++#include ++#include ++ +#include +#include + -+#define DT_PWR_COMPAT "st,stm32mp1-pwr" +#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes" +#define SYSTEM_OFF_MODE "system_off_soc_mode" + @@ -43264,9 +41943,9 @@ index 0000000..ec7ecb1 +static uint32_t system_off_mode; +static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE]; + -+static int dt_get_pwr_node(void *fdt) ++static int dt_get_pwr_node(void) +{ -+ return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); ++ return dt_get_node_by_compatible(DT_PWR_COMPAT); +} + +static void save_supported_mode(void *fdt, int pwr_node) @@ -43320,7 +41999,7 @@ index 0000000..ec7ecb1 + return -ENOENT; + } + -+ pwr_node = dt_get_pwr_node(fdt); ++ pwr_node = dt_get_pwr_node(); + if (pwr_node < 0) { + return -FDT_ERR_NOTFOUND; + } @@ -43376,10 +42055,20 @@ index 0000000..ec7ecb1 + return 0; +} + -+static bool is_supported_mode(uint32_t soc_mode) ++static bool is_allowed_mode(uint32_t soc_mode) +{ + assert(soc_mode < ARRAY_SIZE(stm32mp1_supported_soc_modes)); + ++ if ((soc_mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) && ++ !stm32mp1_get_pm_domain_state(STM32MP1_PD_CORE_RET)) { ++ return false; ++ } ++ ++ if ((soc_mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP) && ++ !stm32mp1_get_pm_domain_state(STM32MP1_PD_CORE)) { ++ return false; ++ } ++ + return stm32mp1_supported_soc_modes[soc_mode] == 1U; +} + @@ -43393,26 +42082,8 @@ index 0000000..ec7ecb1 + + mode = deepest_system_suspend_mode; + -+ if ((mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) && -+ ((!stm32mp1_get_pm_domain_state(STM32MP1_PD_CORE_RET)) || -+ (!is_supported_mode(mode)))) { -+ mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP; -+ } -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP) && -+ ((!stm32mp1_get_pm_domain_state(STM32MP1_PD_CORE)) || -+ (!is_supported_mode(mode)))) { -+ mode = STM32_PM_CSTOP_ALLOW_LP_STOP; -+ } -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_LP_STOP) && -+ (!is_supported_mode(mode))) { -+ mode = STM32_PM_CSTOP_ALLOW_STOP; -+ } -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_STOP) && -+ (!is_supported_mode(mode))) { -+ mode = STM32_PM_CSLEEP_RUN; ++ while ((mode > STM32_PM_CSLEEP_RUN) && !is_allowed_mode(mode)) { ++ mode--; + } + + return mode; @@ -43435,44 +42106,81 @@ index 0000000..ec7ecb1 + return 0; +} diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c -new file mode 100644 -index 0000000..c1f4c82 ---- /dev/null +index e2dcd2af7..b94857bcb 100644 +--- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c -@@ -0,0 +1,379 @@ -+/* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -10,32 +10,75 @@ + + #include + +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAP_ROM MAP_REGION_FLAT(STM32MP_ROM_BASE, \ -+ STM32MP_ROM_SIZE, \ -+ MT_MEMORY | \ -+ MT_RO | \ -+ MT_SECURE | \ -+ MT_EXECUTE) -+ -+#define MAP_SRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ -+ STM32MP_SYSRAM_SIZE, \ ++#include + #include ++#include ++#include ++#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_VARCPN_MASK GENMASK(15, 12) ++#define BOARD_ID_VARCPN_SHIFT 12 + #define BOARD_ID_REVISION_MASK GENMASK(11, 8) + #define BOARD_ID_REVISION_SHIFT 8 ++#define BOARD_ID_VARFG_MASK GENMASK(7, 4) ++#define BOARD_ID_VARFG_SHIFT 4 + #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_ID2VARCPN(_id) (((_id) & BOARD_ID_VARCPN_MASK) >> \ ++ BOARD_ID_VARCPN_SHIFT) + #define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \ + BOARD_ID_REVISION_SHIFT) ++#define BOARD_ID2VARFG(_id) (((_id) & BOARD_ID_VARFG_MASK) >> \ ++ BOARD_ID_VARFG_SHIFT) + #define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK) + +-#define MAP_SRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ ++#if defined(IMAGE_BL2) ++#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ + STM32MP_SYSRAM_SIZE, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) ++#elif defined(IMAGE_BL32) ++#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \ ++ STM32MP_SEC_SYSRAM_SIZE, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) + ++/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */ ++#define MAP_NS_SYSRAM MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \ ++ STM32MP_NS_SYSRAM_SIZE, \ ++ MT_DEVICE | \ ++ MT_RW | \ ++ MT_NS | \ ++ MT_EXECUTE_NEVER) ++#endif ++ +#define MAP_SRAM_MCU MAP_REGION_FLAT(STM32MP_SRAM_MCU_BASE, \ + STM32MP_SRAM_MCU_SIZE, \ + MT_MEMORY | \ @@ -43486,50 +42194,40 @@ index 0000000..c1f4c82 + MT_RW | \ + MT_NS | \ + MT_EXECUTE_NEVER) -+ -+#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ -+ STM32MP1_DEVICE1_SIZE, \ -+ MT_DEVICE | \ -+ MT_RW | \ -+ MT_SECURE | \ -+ MT_EXECUTE_NEVER) -+ -+#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \ -+ STM32MP1_DEVICE2_SIZE, \ -+ MT_DEVICE | \ -+ MT_RW | \ -+ MT_SECURE | \ -+ MT_EXECUTE_NEVER) -+ -+#if defined(IMAGE_BL2) -+static const mmap_region_t stm32mp1_mmap[] = { -+ MAP_ROM, -+ MAP_SRAM, -+#if defined(STM32MP_USB) + + #define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ + STM32MP1_DEVICE1_SIZE, \ +@@ -53,7 +96,10 @@ + + #if defined(IMAGE_BL2) + static const mmap_region_t stm32mp1_mmap[] = { +- MAP_SRAM, ++ MAP_SEC_SYSRAM, ++#if STM32MP_USB_PROGRAMMER + MAP_SRAM_MCU, +#endif -+ MAP_DEVICE1, -+ MAP_DEVICE2, -+ {0} -+}; -+#endif -+#if defined(IMAGE_BL32) -+static const mmap_region_t stm32mp1_mmap[] = { -+ MAP_ROM, -+ MAP_SRAM, -+ MAP_DEVICE1, -+ MAP_DEVICE2, -+ {0} -+}; -+#endif -+ -+void configure_mmu(void) -+{ + MAP_DEVICE1, + MAP_DEVICE2, + {0} +@@ -61,7 +107,8 @@ static const mmap_region_t stm32mp1_mmap[] = { + #endif + #if defined(IMAGE_BL32) + static const mmap_region_t stm32mp1_mmap[] = { +- MAP_SRAM, ++ MAP_SEC_SYSRAM, ++ MAP_NS_SYSRAM, + MAP_DEVICE1, + MAP_DEVICE2, + {0} +@@ -70,10 +117,177 @@ static const mmap_region_t stm32mp1_mmap[] = { + + void configure_mmu(void) + { +#ifndef MMU_OFF + unsigned int flags = 0; + -+ mmap_add(stm32mp1_mmap); -+ init_xlat_tables(); + mmap_add(stm32mp1_mmap); + init_xlat_tables(); +#ifdef DCACHE_OFF + flags |= DISABLE_DCACHE; +#endif @@ -43556,16 +42254,127 @@ index 0000000..c1f4c82 +{ + if (!instance_nb || instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses)) + return 0; -+ + +- enable_mmu_svc_mon(0); + return stm32mp1_uart_addresses[instance_nb - 1]; +} +#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), ++}; ++ ++#define TIMEOUT_US_1MS U(1000) ++ +void __dead2 stm32mp_plat_reset(int cpu) +{ + uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST; ++ uint32_t id; + -+ if (stm32mp_is_single_core() == 0) { ++ /* Mask timer interrupts */ ++ stm32mp_mask_timer(); ++ ++ for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) { ++ if ((!stm32mp_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) { ++ uint32_t reset = tzc_source_ip[id].reset_id; ++ ++ if (stm32mp_reset_assert_to(reset, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ if (stm32mp_reset_deassert_to(reset, TIMEOUT_US_1MS)) { ++ panic(); ++ } ++ } else { ++ /* GPU reset automatically cleared by hardware */ ++ mmio_setbits_32(stm32mp_rcc_base() + RCC_AHB6RSTSETR, ++ RCC_AHB6RSTSETR_GPURST); ++ } ++ } ++ ++ if (!stm32mp_is_single_core()) { + unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ? + STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU; + @@ -43573,230 +42382,411 @@ index 0000000..c1f4c82 + reg |= RCC_MP_GRSTCSETR_MPUP1RST; + } + ++ 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); ++ + mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg); + -+ isb(); -+ dsb(); -+ -+ /* Flush L1/L2 data caches */ -+ write_sctlr(read_sctlr() & ~SCTLR_C_BIT); -+ dcsw_op_all(DC_OP_CISW); -+ -+ for ( ; ; ) { -+ wfi(); -+ } ++ stm32mp_wait_cpu_reset(); + } + + unsigned long stm32_get_gpio_bank_clock(unsigned int bank) +@@ -87,59 +301,133 @@ unsigned long stm32_get_gpio_bank_clock(unsigned int bank) + return GPIOA + (bank - GPIO_BANK_A); + } + +-static int get_part_number(uint32_t *part_nb) ++int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, ++ uint32_t *otp_len) + { +- uint32_t part_number; +- uint32_t dev_id; ++ assert(otp_name != NULL); ++ assert(otp_idx != NULL); + +- if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) { ++ if (bsec_find_otp_name_in_dt(otp_name, otp_idx, otp_len) != BSEC_OK) { + return -1; + } + +- if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) { +- ERROR("BSEC: PART_NUMBER_OTP Error\n"); ++ return 0; +} + -+static uint32_t get_part_number(void) ++int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val) +{ -+ uint32_t part_number = 0; ++ uint32_t otp_idx; + -+ if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) { -+ ERROR("BSEC: PART_NUMBER_OTP Error\n"); ++ assert(otp_name != NULL); ++ assert(otp_val != NULL); ++ ++ if (stm32_get_otp_index(otp_name, &otp_idx, NULL) != 0) { + return -1; + } + ++ if (stm32_get_otp_value_from_idx(otp_idx, otp_val) != 0) { ++ ERROR("BSEC: %s Read Error\n", otp_name); + return -1; + } + -+ part_number = (part_number & PART_MASK) >> PART_SHIFT; -+ -+ return (part_number | (stm32mp1_dbgmcu_get_chip_dev_id() << 16)); -+} -+ -+static uint32_t get_cpu_package(void) -+{ -+ uint32_t package = 0; -+ -+ if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) { -+ ERROR("BSEC: PART_NUMBER_OTP Error\n"); -+ return -1; -+ } -+ -+ return ((package & PKG_MASK) >> PKG_SHIFT); -+} -+ -+void stm32mp_print_cpuinfo(void) -+{ -+ const char *cpu_s, *cpu_r, *pkg; -+ -+ /* MPUs Part Numbers */ -+ switch (get_part_number()) { -+ case STM32MP157C_PART_NB: -+ cpu_s = "157C"; -+ break; -+ case STM32MP157A_PART_NB: -+ cpu_s = "157A"; -+ break; -+ case STM32MP153C_PART_NB: -+ cpu_s = "153C"; -+ break; -+ case STM32MP153A_PART_NB: -+ cpu_s = "153A"; -+ break; -+ case STM32MP151C_PART_NB: -+ cpu_s = "151C"; -+ break; -+ case STM32MP151A_PART_NB: -+ cpu_s = "151A"; -+ break; -+ default: -+ cpu_s = "????"; -+ break; -+ } -+ -+ /* Package */ -+ switch (get_cpu_package()) { -+ case PKG_AA_LBGA448: -+ pkg = "AA"; -+ break; -+ case PKG_AB_LBGA354: -+ pkg = "AB"; -+ break; -+ case PKG_AC_TFBGA361: -+ pkg = "AC"; -+ break; -+ case PKG_AD_TFBGA257: -+ pkg = "AD"; -+ break; -+ default: -+ pkg = "??"; -+ break; -+ } -+ -+ /* REVISION */ -+ switch (stm32mp1_dbgmcu_get_chip_version()) { -+ case STM32MP1_REV_A: -+ cpu_r = "A"; -+ break; -+ case STM32MP1_REV_B: -+ cpu_r = "B"; -+ break; -+ default: -+ cpu_r = "?"; -+ break; -+ } -+ -+ NOTICE("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r); -+} -+ -+void stm32mp_print_boardinfo(void) -+{ -+ uint32_t board; -+ int res = 0; -+ -+ if (bsec_shadow_read_otp(&board, BOARD_OTP) != BSEC_OK) { -+ ERROR("BSEC: PART_NUMBER_OTP Error\n"); -+ res = -1; -+ } -+ -+ if ((res == 0) && (board != 0U)) { -+ char rev[1]; -+ -+ *rev = ((board >> 8) & 0xF) - 1 + 'A'; -+ NOTICE("Board: MB%04x Var%d Rev.%s-%02d\n", -+ board >> 16, -+ (board >> 12) & 0xF, -+ rev, -+ board & 0xF); -+ } -+} -+ -+/* -+ * This function determines if one single core is presently running. This is -+ * done by OTP read. -+ * Returns 1 if yes, 0 if more that one core is running, -1 if error. -+ */ -+int stm32mp_is_single_core(void) -+{ -+ uint32_t part_number = get_part_number(); -+ -+ /* STM32MP151x is a single core */ -+ if ((part_number == STM32MP151A_PART_NB) || -+ (part_number == STM32MP151C_PART_NB)) { -+ return 1; -+ } -+ + return 0; +} + -+uint8_t stm32_iwdg_get_instance(uintptr_t base) ++int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val) +{ -+ switch (base) { -+ case IWDG1_BASE: -+ return IWDG1_INST; -+ case IWDG2_BASE: -+ return IWDG2_INST; -+ default: -+ panic(); -+ } -+} ++ int ret = BSEC_NOT_SUPPORTED; + -+uint32_t stm32_iwdg_get_otp_config(uintptr_t base) -+{ -+ uint8_t idx; -+ uint32_t iwdg_cfg = 0; -+ uint32_t otp_value; ++ assert(otp_val != NULL); + +#if defined(IMAGE_BL2) -+ if (bsec_shadow_read_otp(&otp_value, HW2_OTP) != BSEC_OK) { -+ panic(); -+ } ++ ret = bsec_shadow_read_otp(otp_val, otp_idx); +#elif defined(IMAGE_BL32) -+ if (bsec_read_otp(&otp_value, HW2_OTP) != BSEC_OK) { -+ panic(); -+ } ++ ret = bsec_read_otp(otp_val, otp_idx); ++#else ++#error "Not supported" +#endif -+ -+ idx = stm32_iwdg_get_instance(base); -+ -+ if ((otp_value & BIT(idx + IWDG_HW_POS)) != 0U) { -+ iwdg_cfg |= IWDG_HW_ENABLED; ++ if (ret != BSEC_OK) { ++ ERROR("BSEC: idx=%d Read Error\n", otp_idx); ++ return -1; + } + -+ if ((otp_value & BIT(idx + IWDG_FZ_STOP_POS)) == 0U) { -+ iwdg_cfg |= IWDG_ENABLE_ON_STOP; -+ } -+ -+ if ((otp_value & BIT(idx + IWDG_FZ_STANDBY_POS)) == 0U) { -+ iwdg_cfg |= IWDG_ENABLE_ON_STANDBY; -+ } -+ -+ return iwdg_cfg; ++ return 0; +} + -+#if defined(IMAGE_BL2) -+uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags) ++static uint32_t get_part_number(void) +{ -+ uint32_t idx; -+ uint32_t otp; -+ uint32_t result; ++ static uint32_t part_number; ++ uint32_t dev_id; + -+ if (bsec_shadow_read_otp(&otp, HW2_OTP) != BSEC_OK) { ++ if (part_number != 0U) { ++ return part_number; ++ } ++ ++ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) { ++ INFO("Use default chip ID, debug disabled\n"); ++ dev_id = STM32MP1_CHIP_ID; ++ } ++ ++ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) { + panic(); + } + -+ idx = stm32_iwdg_get_instance(base); -+ -+ if ((flags & IWDG_ENABLE_ON_STOP) != 0) { -+ otp |= BIT(idx + IWDG_FZ_STOP_POS); -+ } -+ -+ if ((flags & IWDG_ENABLE_ON_STANDBY) != 0) { -+ otp |= BIT(idx + IWDG_FZ_STANDBY_POS); -+ } -+ -+ result = bsec_write_otp(otp, HW2_OTP); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ /* Sticky lock OTP_IWDG (read and write) */ -+ if (!bsec_write_sr_lock(HW2_OTP, 1U) || -+ !bsec_write_sw_lock(HW2_OTP, 1U)) { -+ return BSEC_LOCK_FAIL; -+ } -+ -+ return BSEC_OK; + part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >> + PART_NUMBER_OTP_PART_SHIFT; + +- *part_nb = part_number | (dev_id << 16); ++ part_number |= dev_id << 16; + +- return 0; ++ return part_number; + } + +-static int get_cpu_package(uint32_t *cpu_package) ++static uint32_t get_cpu_package(void) + { + uint32_t package; + +- if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) { +- ERROR("BSEC: PACKAGE_OTP Error\n"); +- return -1; ++ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) { ++ panic(); + } + +- *cpu_package = (package & PACKAGE_OTP_PKG_MASK) >> ++ package = (package & PACKAGE_OTP_PKG_MASK) >> + PACKAGE_OTP_PKG_SHIFT; + +- return 0; ++ return package; +} -+#endif ++ ++bool stm32mp_supports_cpu_opp(uint32_t opp_id) ++{ ++ uint32_t id; ++ ++ switch (opp_id) { ++ case PLAT_OPP_ID1: ++ case PLAT_OPP_ID2: ++ id = opp_id; ++ break; ++ default: ++ return false; ++ } ++ ++ switch (get_part_number()) { ++ case STM32MP157F_PART_NB: ++ case STM32MP157D_PART_NB: ++ case STM32MP153F_PART_NB: ++ case STM32MP153D_PART_NB: ++ case STM32MP151F_PART_NB: ++ case STM32MP151D_PART_NB: ++ return true; ++ default: ++ return id == PLAT_OPP_ID1; ++ } + } + + void stm32mp_print_cpuinfo(void) + { + const char *cpu_s, *cpu_r, *pkg; +- uint32_t part_number; +- uint32_t cpu_package; + uint32_t chip_dev_id; + int ret; + + /* MPUs Part Numbers */ +- ret = get_part_number(&part_number); +- if (ret < 0) { +- WARN("Cannot get part number\n"); +- return; +- } +- +- switch (part_number) { ++ switch (get_part_number()) { + case STM32MP157C_PART_NB: + cpu_s = "157C"; + break; +@@ -158,19 +446,31 @@ void stm32mp_print_cpuinfo(void) + case STM32MP151A_PART_NB: + cpu_s = "151A"; + break; ++ case STM32MP157F_PART_NB: ++ cpu_s = "157F"; ++ break; ++ case STM32MP157D_PART_NB: ++ cpu_s = "157D"; ++ break; ++ case STM32MP153F_PART_NB: ++ cpu_s = "153F"; ++ break; ++ case STM32MP153D_PART_NB: ++ cpu_s = "153D"; ++ break; ++ case STM32MP151F_PART_NB: ++ cpu_s = "151F"; ++ break; ++ case STM32MP151D_PART_NB: ++ cpu_s = "151D"; ++ break; + default: + cpu_s = "????"; + break; + } + + /* Package */ +- ret = get_cpu_package(&cpu_package); +- if (ret < 0) { +- WARN("Cannot get CPU package\n"); +- return; +- } +- +- switch (cpu_package) { ++ switch (get_cpu_package()) { + case PKG_AA_LFBGA448: + pkg = "AA"; + break; +@@ -191,14 +491,16 @@ void stm32mp_print_cpuinfo(void) + /* REVISION */ + ret = stm32mp1_dbgmcu_get_chip_version(&chip_dev_id); + if (ret < 0) { +- WARN("Cannot get CPU version\n"); +- return; ++ INFO("Cannot get CPU version, debug disabled\n"); + } + + switch (chip_dev_id) { + case STM32MP1_REV_B: + cpu_r = "B"; + break; ++ case STM32MP1_REV_Z: ++ cpu_r = "Z"; ++ break; + default: + cpu_r = "?"; + break; +@@ -209,35 +511,9 @@ void stm32mp_print_cpuinfo(void) + + void stm32mp_print_boardinfo(void) + { +- uint32_t board_id; +- 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) { +- panic(); +- } ++ uint32_t board_id = 0; + +- board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); +- +- if (bsec_shadow_read_otp(&board_id, board_otp) != BSEC_OK) { +- ERROR("BSEC: PART_NUMBER_OTP Error\n"); ++ if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) { + return; + } + +@@ -246,9 +522,10 @@ void stm32mp_print_boardinfo(void) + + rev[0] = BOARD_ID2REV(board_id) - 1 + 'A'; + rev[1] = '\0'; +- NOTICE("Board: MB%04x Var%d Rev.%s-%02d\n", ++ NOTICE("Board: MB%04x Var%d.%d Rev.%s-%02d\n", + BOARD_ID2NB(board_id), +- BOARD_ID2VAR(board_id), ++ BOARD_ID2VARCPN(board_id), ++ BOARD_ID2VARFG(board_id), + rev, + BOARD_ID2BOM(board_id)); + } +@@ -257,25 +534,15 @@ void stm32mp_print_boardinfo(void) + /* Return true when SoC provides a single Cortex-A7 core, and false otherwise */ + bool stm32mp_is_single_core(void) + { +- uint32_t part_number; +- bool ret = false; +- +- if (get_part_number(&part_number) < 0) { +- ERROR("Invalid part number, assume single core chip"); +- return true; +- } +- +- switch (part_number) { ++ switch (get_part_number()) { + case STM32MP151A_PART_NB: + case STM32MP151C_PART_NB: +- ret = true; +- break; +- ++ case STM32MP151D_PART_NB: ++ case STM32MP151F_PART_NB: ++ return true; + default: +- break; ++ return false; + } +- +- return ret; + } + + /* Return true when device is in closed state */ +@@ -283,12 +550,27 @@ bool stm32mp_is_closed_device(void) + { + uint32_t value; + +- if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) || +- (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) { ++ if (stm32_get_otp_value(CFG0_OTP, &value) != 0) { + return true; + } + +- return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED; ++ return (value & CFG0_CLOSED_DEVICE) == CFG0_CLOSED_DEVICE; ++} ++ ++/* Return true when device supports secure boot */ ++bool stm32mp_is_auth_supported(void) ++{ ++ switch (get_part_number()) { ++ case STM32MP151C_PART_NB: ++ case STM32MP151F_PART_NB: ++ case STM32MP153C_PART_NB: ++ case STM32MP153F_PART_NB: ++ case STM32MP157C_PART_NB: ++ case STM32MP157F_PART_NB: ++ return true; ++ default: ++ return false; ++ } + } + + uint32_t stm32_iwdg_get_instance(uintptr_t base) +@@ -308,13 +590,7 @@ uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst) + uint32_t iwdg_cfg = 0U; + uint32_t otp_value; + +-#if defined(IMAGE_BL2) +- if (bsec_shadow_register(HW2_OTP) != BSEC_OK) { +- panic(); +- } +-#endif +- +- if (bsec_read_otp(&otp_value, HW2_OTP) != BSEC_OK) { ++ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { + panic(); + } + +@@ -336,32 +612,82 @@ uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst) + #if defined(IMAGE_BL2) + uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags) + { ++ uint32_t otp_value; + uint32_t otp; + uint32_t result; + +- if (bsec_shadow_read_otp(&otp, HW2_OTP) != BSEC_OK) { ++ if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) { + panic(); + } + +- if ((flags & IWDG_DISABLE_ON_STOP) != 0U) { +- otp |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS); ++ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { ++ panic(); ++ } ++ ++ if ((flags & IWDG_DISABLE_ON_STOP) != 0) { ++ otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS); + } + +- if ((flags & IWDG_DISABLE_ON_STANDBY) != 0U) { +- otp |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS); ++ if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) { ++ otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS); + } + +- result = bsec_write_otp(otp, HW2_OTP); ++ result = bsec_write_otp(otp_value, otp); + if (result != BSEC_OK) { + return result; + } + + /* 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(otp) != BSEC_OK) || ++ (bsec_set_sw_lock(otp) != BSEC_OK)) { + return BSEC_LOCK_FAIL; + } + + return BSEC_OK; + } + #endif + +/* + * This function allows to split bindings between platform and ETZPC @@ -43819,240 +42809,676 @@ index 0000000..c1f4c82 + panic(); + } +} ++ ++int plat_bind_regulator(struct stm32mp_regulator *regu) ++{ ++ void *fdt; ++ int regu_node; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return false; ++ } ++ ++ if ((dt_pmic_status() > 0) && is_pmic_regulator(regu)) { ++ bind_pmic_regulator(regu); ++ } else { ++ bind_dummy_regulator(regu); ++ } ++ ++ regu_node = fdt_node_offset_by_phandle(fdt, regu->id); ++ if (fdt_getprop(fdt, regu_node, "regulator-always-on", NULL) != NULL) { ++ regu->always_on = true; ++ } ++ ++ return 0; ++} +diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c +new file mode 100644 +index 000000000..c1e91538f +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_scmi.c +@@ -0,0 +1,582 @@ ++/* ++ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TIMEOUT_US_1MS 1000U ++ ++#define SCMI_CLOCK_NAME_SIZE 16U ++#define SCMI_RD_NAME_SIZE 16U ++ ++/* ++ * struct stm32_scmi_clk - Data for the exposed clock ++ * @clock_id: Clock identifier in RCC clock driver ++ * @name: Clock string ID exposed to agent ++ * @enabled: State of the SCMI clock ++ */ ++struct stm32_scmi_clk { ++ unsigned long clock_id; ++ const char *name; ++ bool enabled; ++}; ++ ++/* ++ * struct stm32_scmi_rd - Data for the exposed reset controller ++ * @reset_id: Reset identifier in RCC reset driver ++ * @name: Reset string ID exposed to agent ++ */ ++struct stm32_scmi_rd { ++ unsigned long reset_id; ++ const char *name; ++}; ++ ++/* Locate all non-secure SMT message buffers in last page of SYSRAM */ ++#define SMT_BUFFER_BASE STM32MP_NS_SYSRAM_BASE ++#define SMT_SLOT_SIZE 0x200U ++#define SMT_BUFFER0_BASE SMT_BUFFER_BASE ++#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + SMT_SLOT_SIZE) ++#define SMT_BUFFER_END (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE) ++ ++CASSERT(SMT_BUFFER_END < (STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE), ++ assert_scmi_shm_fits_in_non_secure_sysram); ++ ++static struct scmi_msg_channel scmi_channel[] = { ++ [0] = { ++ .shm_addr = SMT_BUFFER0_BASE, ++ .shm_size = SMT_BUF_SLOT_SIZE, ++ }, ++ [1] = { ++ .shm_addr = SMT_BUFFER1_BASE, ++ .shm_size = SMT_BUF_SLOT_SIZE, ++ }, ++}; ++ ++struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id) ++{ ++ assert(agent_id < ARRAY_SIZE(scmi_channel)); ++ ++ return &scmi_channel[agent_id]; ++} ++ ++#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \ ++ [_scmi_id] = { \ ++ .clock_id = _id, \ ++ .name = _name, \ ++ .enabled = _init_enabled, \ ++ } ++ ++static struct stm32_scmi_clk stm32_scmi0_clock[] = { ++ CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true), ++ CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true), ++ CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true), ++ CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true), ++ CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true), ++ CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true), ++ CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true), ++ CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true), ++ CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true), ++ CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true), ++ CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false), ++ CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false), ++ CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false), ++ CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false), ++ CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false), ++ CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false), ++ CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true), ++ CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true), ++ CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true), ++ CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false), ++ CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false), ++}; ++ ++static struct stm32_scmi_clk stm32_scmi1_clock[] = { ++ CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true), ++ CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true), ++ CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false), ++}; ++ ++#define RESET_CELL(_scmi_id, _id, _name) \ ++ [_scmi_id] = { \ ++ .reset_id = _id, \ ++ .name = _name, \ ++ } ++ ++static struct stm32_scmi_rd stm32_scmi0_reset_domain[] = { ++ RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"), ++ RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"), ++ RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"), ++ RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"), ++ RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"), ++ RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"), ++ RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"), ++ RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"), ++ RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"), ++ RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"), ++ RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"), ++}; ++ ++struct scmi_agent_resources { ++ struct stm32_scmi_clk *clock; ++ size_t clock_count; ++ struct stm32_scmi_rd *rd; ++ size_t rd_count; ++}; ++ ++static const struct scmi_agent_resources agent_resources[] = { ++ [0] = { ++ .clock = stm32_scmi0_clock, ++ .clock_count = ARRAY_SIZE(stm32_scmi0_clock), ++ .rd = stm32_scmi0_reset_domain, ++ .rd_count = ARRAY_SIZE(stm32_scmi0_reset_domain), ++ }, ++ [1] = { ++ .clock = stm32_scmi1_clock, ++ .clock_count = ARRAY_SIZE(stm32_scmi1_clock), ++ }, ++}; ++ ++static const struct scmi_agent_resources *find_resource(unsigned int agent_id) ++{ ++ assert(agent_id < ARRAY_SIZE(agent_resources)); ++ ++ return &agent_resources[agent_id]; ++} ++ ++#if ENABLE_ASSERTIONS ++static size_t plat_scmi_protocol_count_paranoid(void) ++{ ++ unsigned int n = 0U; ++ unsigned int count = 0U; ++ ++ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) { ++ if (agent_resources[n].clock_count) { ++ count++; ++ break; ++ } ++ } ++ ++ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) { ++ if (agent_resources[n].rd_count) { ++ count++; ++ break; ++ } ++ } ++ ++ return count; ++} ++#endif ++ ++static const char vendor[] = "ST"; ++static const char sub_vendor[] = ""; ++ ++const char *plat_scmi_vendor_name(void) ++{ ++ return vendor; ++} ++ ++const char *plat_scmi_sub_vendor_name(void) ++{ ++ return sub_vendor; ++} ++ ++/* Currently supporting Clocks and Reset Domains */ ++static const uint8_t plat_protocol_list[] = { ++ SCMI_PROTOCOL_ID_CLOCK, ++ SCMI_PROTOCOL_ID_RESET_DOMAIN, ++ 0U /* Null termination */ ++}; ++ ++size_t plat_scmi_protocol_count(void) ++{ ++ const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U; ++ ++ assert(count == plat_scmi_protocol_count_paranoid()); ++ ++ return count; ++} ++ ++const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused) ++{ ++ assert(plat_scmi_protocol_count_paranoid() == ++ (ARRAY_SIZE(plat_protocol_list) - 1U)); ++ ++ return plat_protocol_list; ++} ++ ++/* ++ * Platform SCMI clocks ++ */ ++static struct stm32_scmi_clk *find_clock(unsigned int agent_id, ++ unsigned int scmi_id) ++{ ++ const struct scmi_agent_resources *resource = find_resource(agent_id); ++ size_t n = 0U; ++ ++ if (resource != NULL) { ++ for (n = 0U; n < resource->clock_count; n++) { ++ if (n == scmi_id) { ++ return &resource->clock[n]; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++size_t plat_scmi_clock_count(unsigned int agent_id) ++{ ++ const struct scmi_agent_resources *resource = find_resource(agent_id); ++ ++ if (resource == NULL) { ++ return 0U; ++ } ++ ++ return resource->clock_count; ++} ++ ++const char *plat_scmi_clock_get_name(unsigned int agent_id, ++ unsigned int scmi_id) ++{ ++ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); ++ ++ if ((clock == NULL) || ++ !stm32mp_nsec_can_access_clock(clock->clock_id)) { ++ return NULL; ++ } ++ ++ return clock->name; ++} ++ ++int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, ++ unsigned long *array, size_t *nb_elts) ++{ ++ /* ++ * Do not expose clock rates by array since not supported by ++ * Linux kernel ++ */ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id, ++ unsigned int scmi_id, ++ unsigned long *array) ++{ ++ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); ++ ++ if (clock == NULL) { ++ return SCMI_NOT_FOUND; ++ } ++ ++ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) { ++ return SCMI_DENIED; ++ } ++ ++ switch (scmi_id) { ++ case CK_SCMI0_MPU: ++ /* ++ * Pretend we support all rates for MPU clock, ++ * CLOCK_RATE_SET will reject unsupported rates. ++ */ ++ array[0] = 0U; ++ array[1] = UINT32_MAX; ++ array[2] = 1U; ++ break; ++ default: ++ array[0] = stm32mp_clk_get_rate(clock->clock_id); ++ array[1] = array[0]; ++ array[2] = 0U; ++ break; ++ } ++ return SCMI_SUCCESS; ++} ++ ++int32_t plat_scmi_clock_set_rate(unsigned int agent_id, ++ unsigned int scmi_id, ++ unsigned long rate) ++{ ++ int ret; ++ /* find_rd() returns NULL if clock exists for denied the agent */ ++ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); ++ ++ if (clock == NULL) { ++ return SCMI_NOT_FOUND; ++ } ++ ++ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) { ++ return SCMI_DENIED; ++ } ++ ++ switch (scmi_id) { ++ case CK_SCMI0_MPU: ++ ret = stm32mp1_set_opp_khz(rate / 1000UL); ++ if (ret != 0) { ++ return SCMI_INVALID_PARAMETERS; ++ } ++ break; ++ default: ++ if (rate != stm32mp_clk_get_rate(clock->clock_id)) { ++ return SCMI_INVALID_PARAMETERS; ++ } ++ break; ++ } ++ ++ return SCMI_SUCCESS; ++} ++ ++unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, ++ unsigned int scmi_id) ++{ ++ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); ++ ++ if ((clock == NULL) || ++ !stm32mp_nsec_can_access_clock(clock->clock_id)) { ++ return 0U; ++ } ++ ++ return stm32mp_clk_get_rate(clock->clock_id); ++} ++ ++int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id) ++{ ++ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); ++ ++ if ((clock == NULL) || ++ !stm32mp_nsec_can_access_clock(clock->clock_id)) { ++ return 0U; ++ } ++ ++ return (int32_t)clock->enabled; ++} ++ ++int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, ++ bool enable_not_disable) ++{ ++ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); ++ ++ if (clock == NULL) { ++ return SCMI_NOT_FOUND; ++ } ++ ++ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) { ++ return SCMI_DENIED; ++ } ++ ++ if (enable_not_disable) { ++ if (!clock->enabled) { ++ VERBOSE("SCMI clock %u enable\n", scmi_id); ++ stm32mp_clk_enable(clock->clock_id); ++ clock->enabled = true; ++ } ++ } else { ++ if (clock->enabled) { ++ VERBOSE("SCMI clock %u disable\n", scmi_id); ++ stm32mp_clk_disable(clock->clock_id); ++ clock->enabled = false; ++ } ++ } ++ ++ return SCMI_SUCCESS; ++} ++ ++/* ++ * Platform SCMI reset domains ++ */ ++static struct stm32_scmi_rd *find_rd(unsigned int agent_id, ++ unsigned int scmi_id) ++{ ++ const struct scmi_agent_resources *resource = find_resource(agent_id); ++ size_t n; ++ ++ if (resource != NULL) { ++ for (n = 0U; n < resource->rd_count; n++) { ++ if (n == scmi_id) { ++ return &resource->rd[n]; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++const char *plat_scmi_rd_get_name(unsigned int agent_id, unsigned int scmi_id) ++{ ++ const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id); ++ ++ if (rd == NULL) { ++ return NULL; ++ } ++ ++ return rd->name; ++} ++ ++size_t plat_scmi_rd_count(unsigned int agent_id) ++{ ++ const struct scmi_agent_resources *resource = find_resource(agent_id); ++ ++ if (resource == NULL) { ++ return 0U; ++ } ++ ++ return resource->rd_count; ++} ++ ++int32_t plat_scmi_rd_autonomous(unsigned int agent_id, unsigned int scmi_id, ++ uint32_t state) ++{ ++ const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id); ++ ++ if (rd == NULL) { ++ return SCMI_NOT_FOUND; ++ } ++ ++ if (!stm32mp_nsec_can_access_reset(rd->reset_id)) { ++ return SCMI_DENIED; ++ } ++ ++ /* Supports only reset with context loss */ ++ if (state != 0U) { ++ return SCMI_NOT_SUPPORTED; ++ } ++ ++ VERBOSE("SCMI reset %lu cycle\n", rd->reset_id); ++ ++ if (stm32mp_reset_assert_to(rd->reset_id, TIMEOUT_US_1MS)) { ++ return SCMI_HARDWARE_ERROR; ++ } ++ ++ if (stm32mp_reset_deassert_to(rd->reset_id, TIMEOUT_US_1MS)) { ++ return SCMI_HARDWARE_ERROR; ++ } ++ ++ return SCMI_SUCCESS; ++} ++ ++int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id, ++ bool assert_not_deassert) ++{ ++ const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id); ++ ++ if (rd == NULL) { ++ return SCMI_NOT_FOUND; ++ } ++ ++ if (!stm32mp_nsec_can_access_reset(rd->reset_id)) { ++ return SCMI_DENIED; ++ } ++ ++ if (assert_not_deassert) { ++ VERBOSE("SCMI reset %lu set\n", rd->reset_id); ++ stm32mp_reset_set(rd->reset_id); ++ } else { ++ VERBOSE("SCMI reset %lu release\n", rd->reset_id); ++ stm32mp_reset_release(rd->reset_id); ++ } ++ ++ return SCMI_SUCCESS; ++} ++ ++/* ++ * Initialize platform SCMI resources ++ */ ++void stm32mp1_init_scmi_server(void) ++{ ++ size_t i; ++ size_t j; ++ ++ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) { ++ scmi_smt_init_agent_channel(&scmi_channel[i]); ++ } ++ ++ for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) { ++ const struct scmi_agent_resources *res = &agent_resources[i]; ++ ++ for (j = 0U; j < res->clock_count; j++) { ++ struct stm32_scmi_clk *clk = &res->clock[j]; ++ ++ if ((clk->name == NULL) || ++ (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) { ++ ERROR("Invalid SCMI clock name\n"); ++ panic(); ++ } ++ ++ /* Sync SCMI clocks with their targeted initial state */ ++ if (clk->enabled && ++ stm32mp_nsec_can_access_clock(clk->clock_id)) { ++ stm32mp_clk_enable(clk->clock_id); ++ } ++ } ++ ++ for (j = 0U; j < res->rd_count; j++) { ++ struct stm32_scmi_rd *rd = &res->rd[j]; ++ ++ if ((rd->name == NULL) || ++ (strlen(rd->name) >= SCMI_RD_NAME_SIZE)) { ++ ERROR("Invalid SCMI reset domain name\n"); ++ panic(); ++ } ++ } ++ } ++} ++ ++/* ++ * Save and restore SCMI state since lost during suspend. ++ * Only clock enabled field needs to be updated. ++ */ ++void stm32mp1_pm_save_scmi_state(uint8_t *state, size_t size) ++{ ++ size_t i; ++ size_t j; ++ size_t cnt = 0U; ++ ++ zeromem(state, size); ++ ++ for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) { ++ for (j = 0U; j < agent_resources[i].clock_count; j++) { ++ if ((cnt / 8) > size) { ++ VERBOSE("state table too small\n"); ++ panic(); ++ } ++ ++ if (agent_resources[i].clock[j].enabled) { ++ *(state + (cnt / 8)) |= (uint8_t)BIT(cnt % 8); ++ } ++ ++ cnt++; ++ } ++ } ++} ++ ++void stm32mp1_pm_restore_scmi_state(uint8_t *state, size_t size) ++{ ++ size_t i; ++ size_t j; ++ size_t cnt = 0U; ++ ++ for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) { ++ for (j = 0U; j < agent_resources[i].clock_count; j++) { ++ if ((*(state + (cnt / 8)) & BIT(cnt % 8)) == 0U) { ++ agent_resources[i].clock[j].enabled = 0; ++ } else { ++ agent_resources[i].clock[j].enabled = 1; ++ } ++ ++ assert((cnt / 8) <= size); ++ cnt++; ++ } ++ } ++} diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c -index e783c14..8dfbe71 100644 +index 61db2e7c7..41762fa6b 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c -@@ -8,10 +8,10 @@ - #include - #include - #include --#include --#include -+#include - #include - #include -+#include - #include - #include "platform_def.h" +@@ -86,8 +86,11 @@ static void init_tzc400(void) + TZC_REGION_NSEC_ALL_ACCESS_RDWR); + #endif -@@ -22,13 +22,63 @@ - static void init_tzc400(void) - { - unsigned long long region_base, region_top; -- unsigned long long ddr_base = STM32MP1_DDR_BASE; -+ unsigned long long ddr_base = STM32MP_DDR_BASE; - unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size(); - - tzc400_init(STM32MP1_TZC_BASE); - - tzc400_disable_filters(); - -+#ifdef AARCH32_SP_OPTEE -+ /* Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the -+ * same configuration to all filters in the TZC. +- /* Raise an exception if a NS device tries to access secure memory */ +- tzc400_set_action(TZC_ACTION_ERR); ++ /* ++ * Raise an interrupt (secure FIQ) if a NS device tries to access ++ * secure memory + */ -+ region_base = ddr_base; -+ region_top = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE - 1U); -+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, -+ region_base, -+ region_top, -+ 0, -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)); -+ -+ /* Region 2 set to cover all secure DRAM. */ -+ region_base = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE); -+ region_top = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE - 1U); -+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2, -+ region_base, -+ region_top, -+ TZC_REGION_S_RDWR, -+ 0); -+ -+ /* Region 3 set to cover non-secure shared memory DRAM. */ -+ region_base = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE); -+ region_top = ddr_base + (ddr_size - 1U); -+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3, -+ region_base, -+ region_top, -+ 0, -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | -+ 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 - * same configuration to all filters in the TZC. - */ -@@ -42,12 +92,14 @@ static void init_tzc400(void) - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)); -+#endif ++ tzc400_set_action(TZC_ACTION_INT); - /* Raise an exception if a NS device tries to access secure memory */ - tzc400_set_action(TZC_ACTION_ERR); -@@ -62,30 +114,8 @@ static void init_tzc400(void) - ******************************************************************************/ - static void early_init_tzc400(void) - { -- uint32_t rstsr, rst_standby; -- -- rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); -- -- /* No warning if return from (C)STANDBY */ -- rst_standby = rstsr & -- (RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF); -- -- if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) { -- WARN("TZC400 port 1 clock already enable\n"); -- } -- -- if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) { -- WARN("TZC400 port 2 clock already enable\n"); -- } -- -- if (stm32mp1_clk_enable(TZC1) != 0) { -- ERROR("Cannot enable TZC1 clock\n"); -- panic(); -- } -- if (stm32mp1_clk_enable(TZC2) != 0) { -- ERROR("Cannot enable TZC2 clock\n"); -- panic(); -- } -+ stm32mp_clk_enable(TZC1); -+ stm32mp_clk_enable(TZC2); - - tzc400_init(STM32MP1_TZC_BASE); - -@@ -96,10 +126,11 @@ static void early_init_tzc400(void) - * same configuration to all filters in the TZC. - */ - tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, -- STM32MP1_DDR_BASE, -- STM32MP1_DDR_BASE + -- (STM32MP1_DDR_MAX_SIZE - 1U), -+ STM32MP_DDR_BASE, -+ STM32MP_DDR_BASE + -+ (STM32MP_DDR_MAX_SIZE - 1U), - TZC_REGION_S_RDWR, -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID)); - - /* Raise an exception if a NS device tries to access secure memory */ + tzc400_enable_filters(); + } diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c new file mode 100644 -index 0000000..2c95de0 +index 000000000..232fbebdb --- /dev/null +++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c -@@ -0,0 +1,833 @@ -+// SPDX-License-Identifier: BSD-3-Clause +@@ -0,0 +1,743 @@ +/* -+ * Copyright (c) 2017-2018, STMicroelectronics ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause + */ + -+#include +#include -+#include -+#include +#include +#include -+#include ++ ++#include ++ ++#include ++#include ++#include ++ +#include +#include ++#include + +static bool registering_locked; +static int8_t gpioz_nbpin = -1; + +/* -+ * Generic clock enable/disable from secure world. -+ * Some drivers may use non secure resources in specific execution context: -+ * when the other SMP core(s) are offline and non secure is never reached. -+ * In such cases, drivers shall enable/disable the HW clock only if it was not -+ * left enabled by the non secure world. -+ * -+ * During driver initializations, before registering_locked is locked, all -+ * driver simply enable/disable the clock as if the peripheral was secure. -+ */ -+void stm32mp_clk_enable(unsigned long id) -+{ -+ if (registering_locked) { -+ if (stm32mp1_clock_is_non_secure(id)) { -+ assert(stm32mp1_clk_get_refcount(id) == 0U); -+ -+ if (stm32mp1_clk_is_enabled(id)) { -+ return; -+ } -+ } -+ } -+ -+ stm32mp1_clk_enable_secure(id); -+} -+ -+void stm32mp_clk_disable(unsigned long id) -+{ -+ if (registering_locked) { -+ if (stm32mp1_clock_is_non_secure(id)) { -+ if (stm32mp1_clk_get_refcount(id) == 0U) { -+ return; -+ } -+ } -+ } -+ -+ stm32mp1_clk_disable_secure(id); -+} -+ -+/* + * Shared peripherals and resources. + * Defines resource that may be non secure, secure or shared. + * May be a device, a bus, a clock, a memory. ++ * Shared peripherals and resources registration + * -+ * State default to PERIPH_UNREGISTERED resource is not explicitly -+ * set here. ++ * Each resource assignation is stored in a table. The state defaults ++ * to SHRES_UNREGISTERED if the resource is not explicitly assigned. + * -+ * Resource driver not built, the resource defaults -+ * to non secure ownership. -+ * -+ * Each IO of the GPIOZ IO can be secure or non secure. -+ * When the GPIO driver is enabled, the GPIOZ bank is fully non secure -+ * only if each IO is non secure and the GPIOZ bank is shared if it -+ * includes secure and non secure IOs. -+ * -+ * BKPSRAM is assumed shared. -+ * DDR control (DDRC and DDRPHY) is secure. -+ * Inits will define the resource state according the device tree -+ * and the driver initialization sequences. -+ * -+ * The platform initialization uses these information to set the ETZPC -+ * configuration. Non secure services (as clocks or regulator accesses) -+ * rely on these information to drive the related service execution. ++ * Each IO of the GPIOZ IO can be secure or non-secure. + */ -+#define SHRES_NON_SECURE 3 -+#define SHRES_SHARED 2 ++#define SHRES_NON_SECURE 2 +#define SHRES_SECURE 1 +#define SHRES_UNREGISTERED 0 + @@ -44077,23 +43503,8 @@ index 0000000..2c95de0 + [STM32MP1_SHRES_I2C6] = "I2C6", + [STM32MP1_SHRES_RTC] = "RTC", + [STM32MP1_SHRES_MCU] = "MCU", -+ [STM32MP1_SHRES_HSI] = "HSI", -+ [STM32MP1_SHRES_LSI] = "LSI", -+ [STM32MP1_SHRES_HSE] = "HSE", -+ [STM32MP1_SHRES_LSE] = "LSE", -+ [STM32MP1_SHRES_CSI] = "CSI", -+ [STM32MP1_SHRES_PLL1] = "PLL1", -+ [STM32MP1_SHRES_PLL1_P] = "PLL1_P", -+ [STM32MP1_SHRES_PLL1_Q] = "PLL1_Q", -+ [STM32MP1_SHRES_PLL1_R] = "PLL1_R", -+ [STM32MP1_SHRES_PLL2] = "PLL2", -+ [STM32MP1_SHRES_PLL2_P] = "PLL2_P", -+ [STM32MP1_SHRES_PLL2_Q] = "PLL2_Q", -+ [STM32MP1_SHRES_PLL2_R] = "PLL2_R", ++ [STM32MP1_SHRES_MDMA] = "MDMA", + [STM32MP1_SHRES_PLL3] = "PLL3", -+ [STM32MP1_SHRES_PLL3_P] = "PLL3_P", -+ [STM32MP1_SHRES_PLL3_Q] = "PLL3_Q", -+ [STM32MP1_SHRES_PLL3_R] = "PLL3_R", +}; + +static const char *shres2str_id(unsigned int id) @@ -44102,10 +43513,9 @@ index 0000000..2c95de0 +} + +static const char *shres2str_state_tbl[4] = { -+ [SHRES_SHARED] = "shared", -+ [SHRES_NON_SECURE] = "non secure", -+ [SHRES_SECURE] = "secure", + [SHRES_UNREGISTERED] = "unregistered", ++ [SHRES_NON_SECURE] = "non-secure", ++ [SHRES_SECURE] = "secure", +}; + +static const char *shres2str_state(unsigned int id) @@ -44126,6 +43536,7 @@ index 0000000..2c95de0 + } + +#define SHRES_INVALID ~0U ++ +static const struct shres2decprot shres2decprot_tbl[] = { + SHRES2DECPROT(STM32MP1_SHRES_IWDG1, STM32MP1_ETZPC_IWDG1_ID, "IWDG1"), + SHRES2DECPROT(STM32MP1_SHRES_USART1, STM32MP1_ETZPC_USART1_ID, "UART1"), @@ -44181,20 +43592,10 @@ index 0000000..2c95de0 + return (unsigned int)gpioz_nbpin; +} + -+static bool shareable_resource(unsigned int id) -+{ -+ switch (id) { -+ default: -+ /* Currently no shareable resource */ -+ return false; -+ } -+} -+ +static void register_periph(unsigned int id, unsigned int state) +{ -+ assert(id < STM32MP1_SHRES_COUNT && -+ state > SHRES_UNREGISTERED && -+ state <= SHRES_NON_SECURE); ++ assert((id < STM32MP1_SHRES_COUNT) && ++ ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE))); + + if (registering_locked) { + if (shres_state[id] == state) { @@ -44204,9 +43605,8 @@ index 0000000..2c95de0 + panic(); + } + -+ if ((state == SHRES_SHARED && !shareable_resource(id)) || -+ ((shres_state[id] != SHRES_UNREGISTERED) && -+ (shres_state[id] != state))) { ++ if ((shres_state[id] != SHRES_UNREGISTERED) && ++ (shres_state[id] != state)) { + VERBOSE("Cannot change %s from %s to %s\n", + shres2str_id(id), + shres2str_state(shres_state[id]), @@ -44235,7 +43635,7 @@ index 0000000..2c95de0 + } + + /* Explore clock tree to lock dependencies */ -+ if ((state == SHRES_SECURE) || (state == SHRES_SHARED)) { ++ if (state == SHRES_SECURE) { + switch (id) { + case STM32MP1_SHRES_GPIOZ(0) ... STM32MP1_SHRES_GPIOZ(7): + stm32mp1_register_clock_parents_secure(GPIOZ); @@ -44267,24 +43667,6 @@ index 0000000..2c95de0 + case STM32MP1_SHRES_RTC: + stm32mp1_register_clock_parents_secure(RTC); + break; -+ case STM32MP1_SHRES_PLL1_P: -+ case STM32MP1_SHRES_PLL1_Q: -+ case STM32MP1_SHRES_PLL1_R: -+ register_periph(STM32MP1_SHRES_PLL1, SHRES_SECURE); -+ stm32mp1_register_clock_parents_secure(PLL1); -+ break; -+ case STM32MP1_SHRES_PLL2_P: -+ case STM32MP1_SHRES_PLL2_Q: -+ case STM32MP1_SHRES_PLL2_R: -+ register_periph(STM32MP1_SHRES_PLL2, SHRES_SECURE); -+ stm32mp1_register_clock_parents_secure(PLL2); -+ break; -+ case STM32MP1_SHRES_PLL3_P: -+ case STM32MP1_SHRES_PLL3_Q: -+ case STM32MP1_SHRES_PLL3_R: -+ register_periph(STM32MP1_SHRES_PLL3, SHRES_SECURE); -+ stm32mp1_register_clock_parents_secure(PLL3); -+ break; + default: + /* No expected resource dependency */ + break; @@ -44297,9 +43679,6 @@ index 0000000..2c95de0 + switch (id) { + case STM32MP1_SHRES_MCU: + case STM32MP1_SHRES_PLL3: -+ case STM32MP1_SHRES_PLL3_P: -+ case STM32MP1_SHRES_PLL3_Q: -+ case STM32MP1_SHRES_PLL3_R: + return true; + default: + return false; @@ -44307,17 +43686,12 @@ index 0000000..2c95de0 +} + +/* Register resource by ID */ -+void stm32mp1_register_secure_periph(unsigned int id) ++void stm32mp_register_secure_periph(unsigned int id) +{ + register_periph(id, SHRES_SECURE); +} + -+void stm32mp1_register_shared_periph(unsigned int id) -+{ -+ register_periph(id, SHRES_SHARED); -+} -+ -+void stm32mp1_register_non_secure_periph(unsigned int id) ++void stm32mp_register_non_secure_periph(unsigned int id) +{ + register_periph(id, SHRES_NON_SECURE); +} @@ -44375,8 +43749,8 @@ index 0000000..2c95de0 + case UART7_BASE: + case UART8_BASE: + case IWDG2_BASE: -+ /* Allow drivers to register some non secure resources */ -+ VERBOSE("IO for non secure resource 0x%x\n", ++ /* Allow drivers to register some non-secure resources */ ++ VERBOSE("IO for non-secure resource 0x%x\n", + (unsigned int)base); + if (state != SHRES_NON_SECURE) { + panic(); @@ -44444,13 +43818,26 @@ index 0000000..2c95de0 + panic(); + } + -+ id_shres = decprot2shres(id); -+ if (id_shres == SHRES_INVALID) { -+ if (state == SHRES_SECURE) { ++ switch (id) { ++ case STM32MP1_ETZPC_STGENC_ID: ++ case STM32MP1_ETZPC_BKPSRAM_ID: ++ case STM32MP1_ETZPC_DDRCTRL_ID: ++ case STM32MP1_ETZPC_DDRPHYC_ID: ++ /* We assume these must always be assigned to secure world */ ++ if (state != SHRES_SECURE) { + panic(); + } -+ } else { -+ register_periph(id_shres, state); ++ break; ++ default: ++ id_shres = decprot2shres(id); ++ if (id_shres == SHRES_INVALID) { ++ if (state == SHRES_SECURE) { ++ panic(); ++ } ++ } else { ++ register_periph(id_shres, state); ++ } ++ break; + } +} + @@ -44460,18 +43847,13 @@ index 0000000..2c95de0 + registering_locked = true; +} + -+bool stm32mp1_periph_is_shared(unsigned long id) -+{ -+ lock_registering(); -+ -+ return shres_state[id] == SHRES_SHARED; -+} -+ +bool stm32mp1_periph_is_non_secure(unsigned long id) +{ + lock_registering(); + -+ return shres_state[id] == SHRES_NON_SECURE; ++ /* Resource not registered are assumed non-secure */ ++ return (shres_state[id] == SHRES_NON_SECURE) || ++ (shres_state[id] == SHRES_UNREGISTERED); +} + +bool stm32mp1_periph_is_secure(unsigned long id) @@ -44481,13 +43863,6 @@ index 0000000..2c95de0 + return shres_state[id] == SHRES_SECURE; +} + -+bool stm32mp1_periph_is_unregistered(unsigned long id) -+{ -+ lock_registering(); -+ -+ return shres_state[id] == SHRES_UNREGISTERED; -+} -+ +bool stm32mp_gpio_bank_is_shared(unsigned int bank) +{ + unsigned int non_secure = 0; @@ -44500,8 +43875,7 @@ index 0000000..2c95de0 + } + + for (i = 0U; i < get_gpioz_nbpin(); i++) { -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i)) || -+ stm32mp1_periph_is_unregistered(STM32MP1_SHRES_GPIOZ(i))) { ++ if (!stm32mp1_periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) { + non_secure++; + } + } @@ -44521,8 +43895,7 @@ index 0000000..2c95de0 + } + + for (i = 0U; i < get_gpioz_nbpin(); i++) { -+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i)) || -+ stm32mp1_periph_is_unregistered(STM32MP1_SHRES_GPIOZ(i))) { ++ if (!stm32mp1_periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) { + non_secure++; + } + } @@ -44530,7 +43903,7 @@ index 0000000..2c95de0 + return non_secure == get_gpioz_nbpin(); +} + -+bool stm32mp_gpio_bank_is_secure(unsigned int bank) ++static bool stm32mp_gpio_bank_is_secure(unsigned int bank) +{ + unsigned int secure = 0; + unsigned int i; @@ -44550,98 +43923,116 @@ index 0000000..2c95de0 + return secure == get_gpioz_nbpin(); +} + -+bool stm32mp1_clock_is_shareable(unsigned long clock_id) ++CASSERT((CK_HSE == 0) && ++ ((CK_HSE + 1) == CK_CSI) && ++ ((CK_HSE + 2) == CK_LSI) && ++ ((CK_HSE + 3) == CK_LSE) && ++ ((CK_HSE + 4) == CK_HSI) && ++ ((CK_HSE + 5) == CK_HSE_DIV2) && ++ ((PLL1_P + 1) == PLL1_Q) && ++ ((PLL1_P + 2) == PLL1_R) && ++ ((PLL1_P + 3) == PLL2_P) && ++ ((PLL1_P + 4) == PLL2_Q) && ++ ((PLL1_P + 5) == PLL2_R) && ++ ((PLL1_P + 6) == PLL3_P) && ++ ((PLL1_P + 7) == PLL3_Q) && ++ ((PLL1_P + 8) == PLL3_R), ++ assert_clock_id_not_as_expected); ++ ++bool stm32mp_nsec_can_access_clock(unsigned long clock_id) +{ -+ switch (clock_id) { -+ case GPIOZ: -+ return get_gpioz_nbpin() > 0; -+ case RTCAPB: ++ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; ++ ++ /* Oscillators and PLLs are visible from non-secure world */ ++ if ((clock_id <= CK_HSE_DIV2) || ++ ((clock_id >= PLL1_P) && (clock_id <= PLL3_R))) { + return true; -+ default: -+ return false; -+ } -+} -+ -+bool stm32mp1_clock_is_shared(unsigned long clock_id) -+{ -+ lock_registering(); -+ -+ switch (clock_id) { -+ case GPIOZ: -+ if (get_gpioz_nbpin() > 0) { -+ return stm32mp_gpio_bank_is_shared(GPIO_BANK_Z); -+ } else { -+ return false; -+ } -+ case RTCAPB: -+ /* RTCAPB is shared for non secure backup registers */ -+ return true; -+ default: -+ return false; -+ } -+} -+ -+bool stm32mp1_clock_is_non_secure(unsigned long clock_id) -+{ -+ unsigned int shres_id; -+ -+ lock_registering(); -+ -+ if (stm32mp1_clock_is_shared(clock_id)) { -+ return false; + } + + switch (clock_id) { + case BSEC: -+ case BKPSRAM: -+ case TZPC: -+ case TZC1: -+ case TZC2: -+ case STGEN_K: -+ case DDRC1: -+ case DDRC1LP: -+ case DDRC2: -+ case DDRC2LP: -+ case DDRPHYC: -+ case DDRPHYCLP: -+ case DDRCAPB: -+ case DDRCAPBLP: -+ case AXIDCG: -+ case DDRPHYCAPB: -+ case DDRPHYCAPBLP: -+ return false; -+ case IWDG1: -+ shres_id = STM32MP1_SHRES_IWDG1; -+ break; -+ case USART1_K: -+ shres_id = STM32MP1_SHRES_USART1; -+ break; ++ case CK_AXI: ++ case CK_MPU: ++ case RTCAPB: ++ return true; ++ case GPIOZ: ++ return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z); + case SPI6_K: + shres_id = STM32MP1_SHRES_SPI6; + break; + case I2C4_K: + shres_id = STM32MP1_SHRES_I2C4; + break; -+ case RNG1_K: -+ shres_id = STM32MP1_SHRES_RNG1; ++ case I2C6_K: ++ shres_id = STM32MP1_SHRES_I2C6; + break; -+ case HASH1: -+ shres_id = STM32MP1_SHRES_HASH1; ++ case USART1_K: ++ shres_id = STM32MP1_SHRES_USART1; ++ break; ++ case IWDG1: ++ shres_id = STM32MP1_SHRES_IWDG1; + break; + case CRYP1: + shres_id = STM32MP1_SHRES_CRYP1; + break; -+ case I2C6_K: -+ shres_id = STM32MP1_SHRES_I2C6; ++ case HASH1: ++ shres_id = STM32MP1_SHRES_HASH1; ++ break; ++ case RNG1_K: ++ shres_id = STM32MP1_SHRES_RNG1; + break; + case RTC: + shres_id = STM32MP1_SHRES_RTC; + break; ++ case CK_MCU: ++ shres_id = STM32MP1_SHRES_MCU; ++ break; + default: -+ return true; ++ return false; + } + -+ return stm32mp1_periph_is_non_secure(shres_id); ++ return !stm32mp1_periph_is_secure(shres_id); ++} ++ ++bool stm32mp_nsec_can_access_reset(unsigned int reset_id) ++{ ++ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; ++ ++ switch (reset_id) { ++ case GPIOZ_R: ++ return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z); ++ case SPI6_R: ++ shres_id = STM32MP1_SHRES_SPI6; ++ break; ++ case I2C4_R: ++ shres_id = STM32MP1_SHRES_I2C4; ++ break; ++ case I2C6_R: ++ shres_id = STM32MP1_SHRES_I2C6; ++ break; ++ case USART1_R: ++ shres_id = STM32MP1_SHRES_USART1; ++ break; ++ case CRYP1_R: ++ shres_id = STM32MP1_SHRES_CRYP1; ++ break; ++ case HASH1_R: ++ shres_id = STM32MP1_SHRES_HASH1; ++ break; ++ case RNG1_R: ++ shres_id = STM32MP1_SHRES_RNG1; ++ break; ++ case MDMA_R: ++ shres_id = STM32MP1_SHRES_MDMA; ++ break; ++ case MCU_R: ++ shres_id = STM32MP1_SHRES_MCU; ++ break; ++ default: ++ return false; ++ } ++ ++ return !stm32mp1_periph_is_secure(shres_id); +} + +/* ETZPC configuration at drivers initialization completion */ @@ -44652,7 +44043,7 @@ index 0000000..2c95de0 + assert((id - STM32MP1_SHRES_GPIOZ(0)) < get_gpioz_nbpin()); + return TZPC_DECPROT_NS_RW; + default: -+ if (stm32mp1_periph_is_non_secure(id)) { ++ if (!stm32mp1_periph_is_secure(id)) { + return TZPC_DECPROT_NS_RW; + } + @@ -44671,7 +44062,7 @@ index 0000000..2c95de0 + switch (exp) { + case TZPC_DECPROT_NS_RW: + if (cur == TZPC_DECPROT_S_RW) { -+ WARN("ETZPC: %s (%d) could be non secure\n", ++ INFO("ETZPC: %s (%d) could be non secure\n", + decprot2str(id), id); + } + return true; @@ -44737,11 +44128,8 @@ index 0000000..2c95de0 + 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)) { ++ if (shres_state[n] == SHRES_SECURE) { + if ((stm32mp1_mckprot_resource(n) && (!mckprot)) || + !secure) { + ERROR("RCC %s MCKPROT %s and %s (%u) secure\n", @@ -44763,215 +44151,233 @@ index 0000000..2c95de0 + uint32_t pin; + + for (pin = 0U; pin < get_gpioz_nbpin(); pin++) { -+ bool secure = -+ stm32mp1_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin)); ++ unsigned int id = STM32MP1_SHRES_GPIOZ(pin); ++ bool secure = stm32mp1_periph_is_secure(id); + + set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure); + } +} + -+void stm32mp1_driver_init_late(void) ++void stm32mp_lock_periph_registering(void) +{ + uint32_t __unused id; + + registering_locked = true; + -+#if LOG_LEVEL >= LOG_LEVEL_INFO + for (id = 0; id < STM32MP1_SHRES_COUNT; id++) { -+ uint8_t *state = &shres_state[id]; ++ uint8_t state = shres_state[id]; + -+ /* Display only the secure and shared resources */ -+ if ((*state == SHRES_NON_SECURE) || -+ ((*state == SHRES_UNREGISTERED))) { -+ continue; ++ assert((state == SHRES_SECURE) || ++ (state == SHRES_NON_SECURE) || ++ (state == SHRES_UNREGISTERED)); ++ ++ if (state == SHRES_SECURE) { ++ INFO("stm32mp %s (%u): %s\n", ++ shres2str_id(id), id, ++ state == SHRES_SECURE ? "Secure" : ++ state == SHRES_NON_SECURE ? "Non-secure" : ++ state == SHRES_UNREGISTERED ? "Unregistered" : ++ ""); + } -+ -+ INFO("stm32mp %s (%u): %s\n", -+ shres2str_id(id), id, -+ *state == SHRES_SECURE ? "Secure only" : -+ *state == SHRES_SHARED ? "Shared" : -+ *state == SHRES_NON_SECURE ? "Non secure" : -+ *state == SHRES_UNREGISTERED ? "Unregistered" : -+ ""); + } -+#endif + -+ stm32mp1_update_earlyboot_clocks_state(); ++ stm32mp1_dump_clocks_state(); + + check_rcc_secure_configuration(); + check_etzpc_secure_configuration(); + check_gpio_secure_configuration(); +} -+ diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c -new file mode 100644 -index 0000000..3eb9893 ---- /dev/null +index 2fd06f38a..1585590bc 100644 +--- a/plat/st/stm32mp1/stm32mp1_syscfg.c +++ b/plat/st/stm32mp1/stm32mp1_syscfg.c -@@ -0,0 +1,144 @@ -+/* -+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ +@@ -7,15 +7,16 @@ + #include + + #include +-#include ++#include + #include + #include + ++#include + #include + #include + + /* +- * SYSCFG REGISTER OFFSET (base relative) ++ * SYSCFG register offsets (base relative) + */ + #define SYSCFG_BOOTR 0x00U + #define SYSCFG_IOCTRLSETR 0x18U +@@ -53,6 +54,8 @@ + #define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) + #define SYSCFG_CMPCR_ANSRC_SHIFT 24 + ++#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U + -+#include -+#include -+#include -+#include -+#include -+#include -+#include + /* + * SYSCFG_CMPENSETR Register + */ +@@ -61,20 +64,20 @@ + void stm32mp1_syscfg_init(void) + { + uint32_t bootr; +- uint32_t otp = 0; ++ uint32_t otp_value; + uint32_t vdd_voltage; +- uintptr_t syscfg_base = dt_get_syscfg_base(); ++ bool product_below_2v5; + + /* + * Interconnect update : select master using the port 1. + * LTDC = AXI_M9. + */ +- mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); ++ mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); + + /* Disable Pull-Down for boot pin connected to VDD */ +- bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR) & ++ bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) & + SYSCFG_BOOTR_BOOT_MASK; +- mmio_clrsetbits_32(syscfg_base + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, ++ mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, + bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); + + /* +@@ -92,11 +95,11 @@ void stm32mp1_syscfg_init(void) + * => 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) { ++ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { + panic(); + } + +- otp = otp & HW2_OTP_PRODUCT_BELOW_2V5; ++ product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U; + + /* Get VDD supply */ + vdd_voltage = dt_get_pwr_vdd_voltage(); +@@ -105,18 +108,18 @@ void stm32mp1_syscfg_init(void) + if (vdd_voltage == 0U) { + WARN("VDD unknown"); + } else if (vdd_voltage < 2700000U) { +- mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR, ++ mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR, + SYSCFG_IOCTRLSETR_HSLVEN_TRACE | + SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | + SYSCFG_IOCTRLSETR_HSLVEN_ETH | + SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | + SYSCFG_IOCTRLSETR_HSLVEN_SPI); + +- if (otp == 0U) { ++ if (!product_below_2v5) { + INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); + } + } else { +- if (otp != 0U) { ++ if (product_below_2v5) { + ERROR("Product_below_2v5=1:\n"); + ERROR("\tHSLVEN update is destructive,\n"); + ERROR("\tno update as VDD > 2.7V\n"); +@@ -129,29 +132,37 @@ void stm32mp1_syscfg_init(void) + + void stm32mp1_syscfg_enable_io_compensation(void) + { +- uintptr_t syscfg_base = dt_get_syscfg_base(); ++ uint64_t start; + + /* + * 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. + */ +- stm32mp1_clk_enable_non_secure(SYSCFG); ++ stm32mp1_clk_force_enable(SYSCFG); + +- mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR, ++ mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENSETR, + SYSCFG_CMPENSETR_MPU_EN); + +- while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & ++ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); + -+/* -+ * SYSCFG REGISTER OFFSET (base relative) -+ */ -+#define SYSCFG_BOOTR 0x00U -+#define SYSCFG_IOCTRLSETR 0x18U -+#define SYSCFG_ICNR 0x1CU -+#define SYSCFG_CMPCR 0x20U -+#define SYSCFG_CMPENSETR 0x24U -+ -+/* -+ * SYSCFG_BOOTR Register -+ */ -+#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) -+#define SYSCFG_BOOTR_BOOTPD_SHIFT 4 -+/* -+ * SYSCFG_IOCTRLSETR Register -+ */ -+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) -+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) -+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) -+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) -+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) -+ -+/* -+ * SYSCFG_ICNR Register -+ */ -+#define SYSCFG_ICNR_AXI_M9 BIT(9) -+ -+/* -+ * SYSCFG_CMPCR Register -+ */ -+#define SYSCFG_CMPCR_SW_CTRL BIT(1) -+#define SYSCFG_CMPCR_READY BIT(8) -+ -+/* -+ * SYSCFG_CMPENSETR Register -+ */ -+#define SYSCFG_CMPENSETR_MPU_EN BIT(0) -+ -+#define PRODUCT_BELOW_2V5 BIT(13) -+ -+void stm32mp1_syscfg_init(void) -+{ -+ uint32_t bootr; -+ uint32_t otp = 0; -+ uint32_t vdd_voltage; -+ uintptr_t syscfg_base = dt_get_syscfg_base(); -+ -+ /* -+ * Interconnect update : select master using the port 1. -+ * LTDC = AXI_M9. -+ */ -+ mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); -+ VERBOSE("[0x%x] SYSCFG.icnr = 0x%08x (LTDC)\n", -+ (uint32_t)syscfg_base + SYSCFG_ICNR, -+ mmio_read_32(syscfg_base + SYSCFG_ICNR)); -+ -+ /* Disable Pull-Down for boot pin connected to VDD */ -+ bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR); -+ bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT); -+ bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT; -+ mmio_write_32(syscfg_base + SYSCFG_BOOTR, bootr); -+ VERBOSE("[0x%x] SYSCFG.bootr = 0x%08x\n", -+ (uint32_t)syscfg_base + SYSCFG_BOOTR, -+ mmio_read_32(syscfg_base + SYSCFG_BOOTR)); -+ -+ /* -+ * 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. -+ * -+ * 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) -+ * but this value needs to be consistent with board design. -+ */ -+ if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) { -+ otp = otp & PRODUCT_BELOW_2V5; -+ } -+ -+ /* Get VDD = pwr-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"); -+ } else if (vdd_voltage < 2700000U) { -+ mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR, -+ SYSCFG_IOCTRLSETR_HSLVEN_TRACE | -+ SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | -+ SYSCFG_IOCTRLSETR_HSLVEN_ETH | -+ SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | -+ SYSCFG_IOCTRLSETR_HSLVEN_SPI); -+ -+ if (otp == 0U) { -+ INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); ++ while ((mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) & + SYSCFG_CMPCR_READY) == 0U) { +- ; ++ if (timeout_elapsed(start)) { ++ /* ++ * Failure on IO compensation enable is not a issue: ++ * warn only. ++ */ ++ WARN("IO compensation cell not ready\n"); ++ break; + } -+ } else { -+ if (otp != 0U) { -+ INFO("Product_below_2v5=1: HSLVEN update is\n"); -+ INFO(" destructive, no update as VDD>2.7V\n"); -+ } -+ } -+ -+ VERBOSE("[0x%x] SYSCFG.IOCTRLSETR = 0x%08x\n", -+ (uint32_t)syscfg_base + SYSCFG_IOCTRLSETR, -+ mmio_read_32(syscfg_base + SYSCFG_IOCTRLSETR)); -+ -+ /* -+ * Activate automatic I/O compensation. -+ * Warning: need to ensure CSI enabled and ready in clock driver. -+ */ -+ mmio_write_32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN); -+ -+ while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & -+ SYSCFG_CMPCR_READY) != 0U) { -+ ; -+ } -+ -+ mmio_clrbits_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_CMPCR, SYSCFG_CMPCR_SW_CTRL); ++ mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); + } + + void stm32mp1_syscfg_disable_io_compensation(void) + { +- uintptr_t syscfg_base = dt_get_syscfg_base(); + uint32_t value; + + /* +@@ -160,21 +171,19 @@ void stm32mp1_syscfg_disable_io_compensation(void) + * 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) >> ++ value = mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) >> + SYSCFG_CMPCR_ANSRC_SHIFT; + +- mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, ++ mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, + SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + +- value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) | ++ 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); ++ mmio_write_32(SYSCFG_BASE + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); + +- mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR, ++ mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPENSETR, + SYSCFG_CMPENSETR_MPU_EN); + +- stm32mp1_clk_disable_non_secure(SYSCFG); ++ stm32mp1_clk_force_disable(SYSCFG); + } diff --git a/plat/st/stm32mp1/stm32mp1_usb_desc.c b/plat/st/stm32mp1/stm32mp1_usb_desc.c new file mode 100644 -index 0000000..410cfa1 +index 000000000..3ca06922a --- /dev/null +++ b/plat/st/stm32mp1/stm32mp1_usb_desc.c -@@ -0,0 +1,401 @@ +@@ -0,0 +1,418 @@ +/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-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 + +/* USB Standard Device Descriptor */ +static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = { @@ -45025,7 +44431,7 @@ index 0000000..410cfa1 + +/* USB DFU device Configuration Descriptor */ +static uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = { -+ 0x09, /* bLength: Configuation Descriptor size */ ++ 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_DFU_CONFIG_DESC_SIZ, + /* wTotalLength: Bytes returned */ @@ -45109,10 +44515,22 @@ index 0000000..410cfa1 +{ + /* serial number is set to 0*/ + uint8_t i; -+ uint32_t deviceserial[3] = {0, 0, 0}; ++ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U}; ++ uint32_t otp; ++ uint32_t len; + -+ for (i = 0; i < 3; i++) { -+ if (bsec_shadow_read_otp(&deviceserial[i], i + UID0_OTP) != ++ if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) { ++ ERROR("BSEC: Get UID_OTP number Error\n"); ++ return; ++ } ++ ++ if ((len / __WORD_BIT) != UID_WORD_NB) { ++ ERROR("BSEC: Get UID_OTP length Error\n"); ++ return; ++ } ++ ++ for (i = 0; i < UID_WORD_NB; i++) { ++ if (bsec_shadow_read_otp(&deviceserial[i], i + otp) != + BSEC_OK) { + ERROR("BSEC: UID%d Error\n", i); + return; @@ -45360,231 +44778,141 @@ index 0000000..410cfa1 +{ + register_platform(pdev, &dfu_desc); +} -diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile -index 7b10e3e..c03629a 100644 ---- a/tools/cert_create/Makefile -+++ b/tools/cert_create/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -22,7 +22,7 @@ OBJECTS := src/cert.o \ - src/tbbr/tbb_ext.o \ - src/tbbr/tbb_key.o - --CFLAGS := -Wall -std=c99 -+HOSTCCFLAGS := -Wall -std=c99 - - MAKE_HELPERS_DIRECTORY := ../../make_helpers/ - include ${MAKE_HELPERS_DIRECTORY}build_macros.mk -@@ -46,9 +46,9 @@ endif - endif - - ifeq (${DEBUG},1) -- CFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40 -+ HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40 - else -- CFLAGS += -O2 -DLOG_LEVEL=20 -+ HOSTCCFLAGS += -O2 -DLOG_LEVEL=20 - endif - ifeq (${V},0) - Q := @ -@@ -57,7 +57,7 @@ else - endif - - $(eval $(call add_define,USE_TBBR_DEFS)) --CFLAGS += ${DEFINES} -+HOSTCCFLAGS += ${DEFINES} - - # Make soft links and include from local directory otherwise wrong headers - # could get pulled in from firmware tree. -@@ -72,15 +72,15 @@ HOSTCC ?= gcc - all: clean ${BINARY} - - ${BINARY}: ${OBJECTS} Makefile -- @echo " LD $@" -+ @echo " HOSTLD $@" - @echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \ - const char platform_msg[] = "${PLAT_MSG}";' | \ -- ${HOSTCC} -c ${CFLAGS} -xc - -o src/build_msg.o -+ ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o - ${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@ - - %.o: %.c -- @echo " CC $<" -- ${Q}${HOSTCC} -c ${CFLAGS} ${INC_DIR} $< -o $@ -+ @echo " HOSTCC $<" -+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@ - - clean: - $(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS}) -diff --git a/tools/doimage/Makefile b/tools/doimage/Makefile -index bc74369..9f0d89d 100644 ---- a/tools/doimage/Makefile -+++ b/tools/doimage/Makefile -@@ -7,11 +7,11 @@ - PROJECT = doimage - OBJECTS = doimage.o - --CFLAGS = -Wall -Werror -+HOSTCCFLAGS = -Wall -Werror - ifeq (${DEBUG},1) -- CFLAGS += -g -O0 -DDEBUG -+ HOSTCCFLAGS += -g -O0 -DDEBUG - else -- CFLAGS += -O2 -+ HOSTCCFLAGS += -O2 - endif - - ifeq (${MARVELL_SECURE_BOOT},1) -@@ -19,13 +19,13 @@ DOIMAGE_CC_FLAGS := -DCONFIG_MVEBU_SECURE_BOOT - DOIMAGE_LD_FLAGS := -lconfig -lmbedtls -lmbedcrypto -lmbedx509 - endif - --CFLAGS += ${DOIMAGE_CC_FLAGS} -+HOSTCCFLAGS += ${DOIMAGE_CC_FLAGS} - - # Make soft links and include from local directory otherwise wrong headers - # could get pulled in from firmware tree. - INCLUDE_PATHS = -I. - --CC := gcc -+HOSTCC ?= gcc - RM := rm -rf - - .PHONY: all clean -@@ -33,15 +33,15 @@ RM := rm -rf - all: ${PROJECT} - - ${PROJECT}: ${OBJECTS} Makefile -- @echo " LD $@" -- ${Q}${CC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@ -+ @echo " HOSTLD $@" -+ ${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@ - @echo - @echo "Built $@ successfully" - @echo - --%.o: %.c %.h Makefile -- @echo " CC $<" -- ${Q}${CC} -c ${CFLAGS} ${INCLUDE_PATHS} $< -o $@ -+%.o: %.c Makefile -+ @echo " HOSTCC $<" -+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ - - clean: - ${Q}${RM} ${PROJECT} -diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile -index 9bdafe0..ef35014 100644 ---- a/tools/fiptool/Makefile -+++ b/tools/fiptool/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -13,11 +13,11 @@ OBJECTS := fiptool.o tbbr_config.o - V ?= 0 - - override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700 --CFLAGS := -Wall -Werror -pedantic -std=c99 -+HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 - ifeq (${DEBUG},1) -- CFLAGS += -g -O0 -DDEBUG -+ HOSTCCFLAGS += -g -O0 -DDEBUG - else -- CFLAGS += -O2 -+ HOSTCCFLAGS += -O2 - endif - LDLIBS := -lcrypto - -@@ -36,15 +36,15 @@ HOSTCC ?= gcc - all: ${PROJECT} - - ${PROJECT}: ${OBJECTS} Makefile -- @echo " LD $@" -+ @echo " HOSTLD $@" - ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS} - @${ECHO_BLANK_LINE} - @echo "Built $@ successfully" - @${ECHO_BLANK_LINE} - - %.o: %.c %.h Makefile -- @echo " CC $<" -- ${Q}${HOSTCC} -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@ -+ @echo " HOSTCC $<" -+ ${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ - - clean: - $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) -diff --git a/tools/stm32image/Makefile b/tools/stm32image/Makefile -index 80dfbec..9c9b7b5 100644 ---- a/tools/stm32image/Makefile -+++ b/tools/stm32image/Makefile -@@ -12,12 +12,12 @@ PROJECT := stm32image${BIN_EXT} - OBJECTS := stm32image.o - V := 0 - --override CPPFLAGS += -D_GNU_SOURCE --CFLAGS := -Wall -Werror -pedantic -std=c99 -+HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE -+ - ifeq (${DEBUG},1) -- CFLAGS += -g -O0 -DDEBUG -+ HOSTCCFLAGS += -g -O0 -DDEBUG - else -- CFLAGS += -O2 -+ HOSTCCFLAGS += -O2 - endif - - ifeq (${V},0) -@@ -26,22 +26,22 @@ else - Q := - endif - --CC := gcc -+HOSTCC := gcc - - .PHONY: all clean distclean - - all: ${PROJECT} - - ${PROJECT}: ${OBJECTS} Makefile -- @echo " LD $@" -- ${Q}${CC} ${OBJECTS} -o $@ -+ @echo " HOSTLD $@" -+ ${Q}${HOSTCC} ${OBJECTS} -o $@ - @${ECHO_BLANK_LINE} - @echo "Built $@ successfully" - @${ECHO_BLANK_LINE} - --%.o: %.c %.h Makefile -- @echo " CC $<" -- ${Q}${CC} -c ${CFLAGS} $< -o $@ -+%.o: %.c Makefile -+ @echo " HOSTCC $<" -+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@ - - clean: - $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c -index 2607928..41024e2 100644 +index 41024e286..209e0c9d8 100644 --- a/tools/stm32image/stm32image.c +++ b/tools/stm32image/stm32image.c -@@ -22,7 +22,7 @@ - #define VER_MINOR 1 - #define VER_VARIANT 0 - #define HEADER_VERSION_V1 0x1 --#define TF_BINARY_TYPE 0x0 -+#define TF_BINARY_TYPE 0x10 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -45,8 +45,6 @@ struct stm32_header { + uint8_t binary_type; + }; - /* Default option : bit0 => no signature */ - #define HEADER_DEFAULT_OPTION (__cpu_to_le32(0x00000001)) +-static struct stm32_header stm32image_header; +- + static void stm32image_default_header(struct stm32_header *ptr) + { + if (!ptr) { +@@ -54,10 +52,9 @@ static void stm32image_default_header(struct stm32_header *ptr) + } + + ptr->magic_number = HEADER_MAGIC; +- ptr->header_version[VER_MAJOR] = HEADER_VERSION_V1; + ptr->option_flags = HEADER_DEFAULT_OPTION; +- ptr->ecdsa_algorithm = 1; +- ptr->version_number = 0; ++ ptr->ecdsa_algorithm = __cpu_to_le32(1); ++ ptr->version_number = __cpu_to_le32(0); + ptr->binary_type = TF_BINARY_TYPE; + } + +@@ -105,27 +102,33 @@ static void stm32image_print_header(const void *ptr) + } + + static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, +- uint32_t loadaddr, uint32_t ep, uint32_t ver) ++ uint32_t loadaddr, uint32_t ep, uint32_t ver, ++ uint32_t major, uint32_t minor) + { + struct stm32_header *stm32hdr = (struct stm32_header *)ptr; + + stm32image_default_header(stm32hdr); + ++ stm32hdr->header_version[VER_MAJOR] = major; ++ stm32hdr->header_version[VER_MINOR] = minor; + stm32hdr->load_address = __cpu_to_le32(loadaddr); + stm32hdr->image_entry_point = __cpu_to_le32(ep); + stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - + sizeof(struct stm32_header)); +- stm32hdr->image_checksum = stm32image_checksum(ptr, sbuf->st_size); ++ stm32hdr->image_checksum = ++ __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size)); + stm32hdr->version_number = __cpu_to_le32(ver); + } + + static int stm32image_create_header_file(char *srcname, char *destname, + uint32_t loadaddr, uint32_t entry, +- uint32_t version) ++ uint32_t version, uint32_t major, ++ uint32_t minor) + { + int src_fd, dest_fd; + struct stat sbuf; + unsigned char *ptr; ++ struct stm32_header stm32image_header; + + dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); + if (dest_fd == -1) { +@@ -177,11 +180,12 @@ static int stm32image_create_header_file(char *srcname, char *destname, + dest_fd, 0); + + if (ptr == MAP_FAILED) { +- fprintf(stderr, "Can't read %s\n", srcname); ++ fprintf(stderr, "Can't write %s\n", destname); + return -1; + } + +- stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, entry, version); ++ stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, entry, version, ++ major, minor); + + stm32image_print_header(ptr); + +@@ -193,9 +197,11 @@ static int stm32image_create_header_file(char *srcname, char *destname, + int main(int argc, char *argv[]) + { + int opt, loadaddr = -1, entry = -1, err = 0, version = 0; ++ int major = HEADER_VERSION_V1; ++ int minor = 0; + char *dest = NULL, *src = NULL; + +- while ((opt = getopt(argc, argv, ":s:d:l:e:v:")) != -1) { ++ while ((opt = getopt(argc, argv, ":s:d:l:e:v:m:n:")) != -1) { + switch (opt) { + case 's': + src = optarg; +@@ -204,17 +210,23 @@ int main(int argc, char *argv[]) + dest = optarg; + break; + case 'l': +- loadaddr = strtol(optarg, NULL, 16); ++ loadaddr = strtol(optarg, NULL, 0); + break; + case 'e': +- entry = strtol(optarg, NULL, 16); ++ entry = strtol(optarg, NULL, 0); + break; + case 'v': +- version = strtol(optarg, NULL, 10); ++ version = strtol(optarg, NULL, 0); ++ break; ++ case 'm': ++ major = strtol(optarg, NULL, 0); ++ break; ++ case 'n': ++ minor = strtol(optarg, NULL, 0); + break; + default: + fprintf(stderr, +- "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point]\n", ++ "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor]\n", + argv[0]); + return -1; + } +@@ -241,7 +253,7 @@ int main(int argc, char *argv[]) + } + + err = stm32image_create_header_file(src, dest, loadaddr, +- entry, version); ++ entry, version, major, minor); + + return err; + } -- -2.7.4 +2.17.1 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 deleted file mode 100644 index f7a557a..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-st-update-r1.1.0.patch +++ /dev/null @@ -1,5752 +0,0 @@ -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/0003-st-update-r1.2.0.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-st-update-r1.2.0.patch deleted file mode 100644 index 450dd44..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-st-update-r1.2.0.patch +++ /dev/null @@ -1,7087 +0,0 @@ -From 801e39ee5f7ecfc1cb4505d2fef5858c486571a5 Mon Sep 17 00:00:00 2001 -From: Romuald JEANNE -Date: Wed, 29 Jan 2020 14:25:17 +0100 -Subject: [PATCH] st update r1.2.0 - -Signed-off-by: Romuald JEANNE ---- - docs/devicetree/bindings/power/st,stpmic1.txt | 38 -- - docs/devicetree/bindings/soc/st,stm32-romem.txt | 43 ++ - drivers/mmc/mmc.c | 69 ++- - drivers/st/bsec/bsec.c | 129 ++++- - drivers/st/clk/stm32mp1_calib.c | 4 +- - drivers/st/clk/stm32mp1_clk.c | 680 ++++++++++++++++++++++-- - drivers/st/clk/stm32mp1_clkfunc.c | 19 +- - drivers/st/clk/stm32mp_clkfunc.c | 121 +---- - drivers/st/ddr/stm32mp1_ddr.c | 11 +- - drivers/st/ddr/stm32mp1_ddr_helpers.c | 26 +- - drivers/st/ddr/stm32mp1_ram.c | 18 +- - drivers/st/etzpc/etzpc.c | 6 +- - drivers/st/gpio/stm32_gpio.c | 6 +- - drivers/st/i2c/stm32_i2c.c | 165 +++--- - drivers/st/io/io_programmer_st_usb.c | 8 +- - drivers/st/io/io_stm32image.c | 4 +- - drivers/st/iwdg/stm32_iwdg.c | 6 +- - drivers/st/mmc/stm32_sdmmc2.c | 96 ++-- - drivers/st/nand/nand.c | 15 +- - drivers/st/pmic/stm32mp_pmic.c | 472 ++++++++++------ - drivers/st/pmic/stpmic1.c | 20 +- - drivers/st/qspi/io_qspi.c | 4 +- - drivers/st/regulator/stm32mp_dummy_regulator.c | 27 + - drivers/st/regulator/stm32mp_regulator.c | 38 ++ - drivers/st/reset/stm32mp1_reset.c | 3 +- - drivers/st/rng/stm32_rng.c | 3 +- - drivers/st/rtc/stm32_rtc.c | 42 +- - drivers/st/tamper/stm32_tamp.c | 4 +- - drivers/st/timer/stm32_timer.c | 3 +- - drivers/st/uart/io_programmer_uart.c | 5 +- - fdts/stm32mp15-ddr.dtsi | 2 +- - fdts/stm32mp157a-dk1.dts | 33 +- - fdts/stm32mp157c-ed1.dts | 33 +- - fdts/stm32mp157c-security.dtsi | 51 +- - fdts/stm32mp157c.dtsi | 17 + - include/drivers/mmc.h | 27 +- - include/drivers/st/bsec.h | 5 +- - include/drivers/st/stm32_i2c.h | 20 +- - include/drivers/st/stm32_sdmmc2.h | 2 + - include/drivers/st/stm32mp1_clk.h | 22 +- - include/drivers/st/stm32mp1_ddr_regs.h | 4 +- - include/drivers/st/stm32mp_clkfunc.h | 7 +- - include/drivers/st/stm32mp_dummy_regulator.h | 14 + - include/drivers/st/stm32mp_pmic.h | 17 +- - include/drivers/st/stm32mp_regulator.h | 31 ++ - include/drivers/st/stpmic1.h | 24 +- - lib/usb/usb_st_dfu.c | 2 +- - plat/st/common/bl2_io_storage.c | 112 +--- - plat/st/common/include/stm32mp_common.h | 11 +- - plat/st/common/include/stm32mp_dt.h | 7 + - plat/st/common/stm32mp_common.c | 8 +- - plat/st/common/stm32mp_dt.c | 272 ++++++++-- - plat/st/stm32mp1/bl2_plat_setup.c | 183 +++++-- - plat/st/stm32mp1/include/stm32mp1_context.h | 3 + - plat/st/stm32mp1/include/stm32mp1_dbgmcu.h | 10 +- - plat/st/stm32mp1/include/stm32mp1_smc.h | 143 ++++- - plat/st/stm32mp1/plat_image_load.c | 41 +- - plat/st/stm32mp1/platform.mk | 17 +- - plat/st/stm32mp1/services/bsec_svc.c | 20 +- - plat/st/stm32mp1/services/rcc_svc.c | 34 +- - plat/st/stm32mp1/services/rcc_svc.h | 4 +- - plat/st/stm32mp1/services/stm32mp1_svc_setup.c | 10 +- - plat/st/stm32mp1/sp_min/sp_min_setup.c | 26 + - plat/st/stm32mp1/stm32mp1_context.c | 91 +++- - plat/st/stm32mp1/stm32mp1_dbgmcu.c | 72 ++- - plat/st/stm32mp1/stm32mp1_def.h | 76 ++- - plat/st/stm32mp1/stm32mp1_helper_dbg.S | 10 +- - plat/st/stm32mp1/stm32mp1_low_power.c | 18 +- - plat/st/stm32mp1/stm32mp1_pm.c | 12 +- - plat/st/stm32mp1/stm32mp1_power_config.c | 9 +- - plat/st/stm32mp1/stm32mp1_private.c | 271 +++++++--- - plat/st/stm32mp1/stm32mp1_security.c | 22 +- - plat/st/stm32mp1/stm32mp1_syscfg.c | 33 +- - plat/st/stm32mp1/stm32mp1_usb_desc.c | 22 +- - tools/stm32image/stm32image.c | 18 +- - 75 files changed, 2854 insertions(+), 1097 deletions(-) - create mode 100644 drivers/st/regulator/stm32mp_dummy_regulator.c - create mode 100644 drivers/st/regulator/stm32mp_regulator.c - create mode 100644 include/drivers/st/stm32mp_dummy_regulator.h - create mode 100644 include/drivers/st/stm32mp_regulator.h - -diff --git a/docs/devicetree/bindings/power/st,stpmic1.txt b/docs/devicetree/bindings/power/st,stpmic1.txt -index 54b64e2..83307d2 100644 ---- a/docs/devicetree/bindings/power/st,stpmic1.txt -+++ b/docs/devicetree/bindings/power/st,stpmic1.txt -@@ -45,43 +45,6 @@ Required parent device properties: - IT_TWARN_R=30 - IT_TWARN_F=31 - --Optional parent device properties: --- st,main-control-register: -- -bit 1: Power cycling will be performed on turn OFF condition -- -bit 2: PWRCTRL is functional -- -bit 3: PWRCTRL active high --- st,pads-pull-register: -- -bit 1: WAKEUP pull down is not active -- -bit 2: PWRCTRL pull up is active -- -bit 3: PWRCTRL pull down is active -- -bit 4: WAKEUP detector is disabled --- st,vin-control-register: -- -bit 0: VINLOW monitoring is enabled -- -bit [1...3]: VINLOW rising threshold -- 000 VINOK_f + 50mV -- 001 VINOK_f + 100mV -- 010 VINOK_f + 150mV -- 011 VINOK_f + 200mV -- 100 VINOK_f + 250mV -- 101 VINOK_f + 300mV -- 110 VINOK_f + 350mV -- 111 VINOK_f + 400mV -- -bit [4...5]: VINLOW hyst -- 00 100mV -- 01 200mV -- 10 300mV -- 11 400mV -- -bit 6: SW_OUT detector is disabled -- -bit 7: SW_IN detector is enabled. --- st,usb-control-register: -- -bit 3: SW_OUT current limit -- 0: 600mA -- 1: 1.1A -- -bit 4: VBUS_OTG discharge is enabled -- -bit 5: SW_OUT discharge is enabled -- -bit 6: VBUS_OTG detection is enabled -- -bit 7: BOOST_OVP is disabled -- - STPMIC1 consists in a varied group of sub-devices. - Each sub-device binding is be described in own documentation file. - -@@ -98,7 +61,6 @@ pmic: pmic@33 { - reg = <0x33>; - interrupt-parent = <&gpioa>; - interrupts = <0 2>; -- st,main-control-register=<0x0c>; - interrupt-controller; - #interrupt-cells = <2>; - -diff --git a/docs/devicetree/bindings/soc/st,stm32-romem.txt b/docs/devicetree/bindings/soc/st,stm32-romem.txt -index fbff52e..c430fb8 100644 ---- a/docs/devicetree/bindings/soc/st,stm32-romem.txt -+++ b/docs/devicetree/bindings/soc/st,stm32-romem.txt -@@ -16,6 +16,12 @@ Required properties: - Optional Data cells: - - Must be child nodes as described in nvmem.txt. - -+Optional-properties: -+- "st,non-secure-otp" specifies that the OTP can be accessed by non-secure -+ world through secure world services. Only useful for upper OTPs. This -+ property mandates 32-bit granularity of the related nvmem area, that is -+ offset and length are both multiple of 4. -+ - Example on stm32f4: - romem: nvmem@1fff7800 { - compatible = "st,stm32-romem"; -@@ -29,3 +35,40 @@ Example on stm32f4: - }; - ... - }; -+ -+Example on stm32mp1: -+ bsec: nvmem@5c005000 { -+ ... -+ mac_addr: mac_addr@e4 { -+ reg = <0xe4 0x8>; -+ st,non-secure-otp; -+ }; -+ ... -+ }; -+ -+The nvmem_layout node gathers all nvmem platform-dependent layout information, -+including OTP names and phandles, in order to allow easy accesses for data -+consumers, using pre-defined string in nvmem-cell-names property. -+ -+Required properties: -+- compatible: "st,stm32-nvmem-layout" -+- nvmem-cells and nvmem-cell-names, as described in nvmem.txt. -+ -+Example on stm32mp1: -+ nvmem_layout: nvmem_layout@0 { -+ compatible = "st,stm32-nvmem-layout"; -+ nvmem-cells = <&part_number_otp>, -+ ... -+ ; -+ nvmem-cell-names = "part_number_otp", -+ ... -+ ; -+ }; -+ -+ bsec: nvmem@5c005000 { -+ ... -+ part_number_otp: part_number_otp@4 { -+ reg = <0x4 0x1>; -+ }; -+ ... -+ }; -diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c -index 3f9657d..baaddfe 100644 ---- a/drivers/mmc/mmc.c -+++ b/drivers/mmc/mmc.c -@@ -24,6 +24,7 @@ - static const struct mmc_ops *ops; - static unsigned int mmc_ocr_value; - static struct mmc_csd_emmc mmc_csd; -+static struct sd_switch_status sd_switch_func_status; - static unsigned char mmc_ext_csd[512] __aligned(16); - static unsigned int mmc_flags; - static struct mmc_device_info *mmc_dev_info; -@@ -43,6 +44,11 @@ static bool is_cmd23_enabled(void) - return ((mmc_flags & MMC_FLAG_CMD23) != 0U); - } - -+static bool is_sd_cmd6_enabled(void) -+{ -+ return ((mmc_flags & MMC_FLAG_SD_CMD6) != 0U); -+} -+ - static int mmc_send_cmd(unsigned int idx, unsigned int arg, - unsigned int r_type, unsigned int *r_data) - { -@@ -326,6 +332,33 @@ static int mmc_fill_device_info(void) - return 0; - } - -+static int sd_switch(unsigned char mode, unsigned char group, -+ unsigned char func) -+{ -+ unsigned int group_shift = (group - 1U) * 4U; -+ unsigned int group_mask = GENMASK(group_shift + 3U, group_shift); -+ unsigned int arg; -+ int ret = 0; -+ -+ ret = ops->prepare(0, (uintptr_t)&sd_switch_func_status, -+ sizeof(sd_switch_func_status)); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* MMC CMD6: SWITCH_FUNC */ -+ arg = (mode << 31) | GENMASK(23, 0); -+ arg &= ~group_mask; -+ arg |= func << group_shift; -+ ret = mmc_send_cmd(MMC_CMD(6), arg, MMC_RESPONSE_R1, NULL); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ return ops->read(0, (uintptr_t)&sd_switch_func_status, -+ sizeof(sd_switch_func_status)); -+} -+ - static int sd_send_op_cond(void) - { - int n; -@@ -360,7 +393,7 @@ static int sd_send_op_cond(void) - return 0; - } - -- mdelay(1); -+ mdelay(10); - } - - ERROR("ACMD41 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES); -@@ -493,7 +526,39 @@ static int mmc_enumerate(unsigned int clk, unsigned int bus_width) - return ret; - } - -- return mmc_fill_device_info(); -+ ret = mmc_fill_device_info(); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (is_sd_cmd6_enabled() && -+ (mmc_dev_info->mmc_dev_type == MMC_IS_SD_HC)) { -+ /* Try to switch to High Speed Mode */ -+ ret = sd_switch(SD_SWITCH_FUNC_CHECK, 1U, 1U); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if ((sd_switch_func_status.support_g1 & BIT(9)) == 0U) { -+ /* High speed not supported, keep default speed */ -+ return 0; -+ } -+ -+ ret = sd_switch(SD_SWITCH_FUNC_SWITCH, 1U, 1U); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if ((sd_switch_func_status.sel_g2_g1 & 0x1U) == 0U) { -+ /* Cannot switch to high speed, keep default speed */ -+ return 0; -+ } -+ -+ mmc_dev_info->max_bus_freq = 50000000U; -+ ret = ops->set_ios(clk, bus_width); -+ } -+ -+ return ret; - } - - size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size) -diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c -index 3dad2c2..2193a67 100644 ---- a/drivers/st/bsec/bsec.c -+++ b/drivers/st/bsec/bsec.c -@@ -1,6 +1,6 @@ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -11,9 +11,9 @@ - #include - #include - #include -+#include - #include - #include --#include - - #define BSEC_IP_VERSION_1_0 0x10 - #define BSEC_COMPAT "st,stm32mp15-bsec" -@@ -82,33 +82,59 @@ static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node) - - fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { - const fdt32_t *cuint; -- uint32_t reg; -+ uint32_t otp; - uint32_t i; - uint32_t size; -- uint8_t status; -+ uint32_t offset; -+ uint32_t length; - - cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); - if (cuint == NULL) { - panic(); - } - -- reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t); -- if (reg < STM32MP1_UPPER_OTP_START) { -- continue; -+ offset = fdt32_to_cpu(*cuint); -+ cuint++; -+ length = fdt32_to_cpu(*cuint); -+ -+ otp = offset / sizeof(uint32_t); -+ -+ if (otp < STM32MP1_UPPER_OTP_START) { -+ unsigned int otp_end = round_up(offset + length, -+ sizeof(uint32_t)) / -+ sizeof(uint32_t); -+ -+ if (otp_end > STM32MP1_UPPER_OTP_START) { -+ /* -+ * OTP crosses Lower/Upper boundary, consider -+ * only the upper part. -+ */ -+ otp = STM32MP1_UPPER_OTP_START; -+ length -= (STM32MP1_UPPER_OTP_START * -+ sizeof(uint32_t)) - offset; -+ offset = STM32MP1_UPPER_OTP_START * -+ sizeof(uint32_t); -+ -+ WARN("OTP crosses Lower/Upper boundary\n"); -+ } else { -+ continue; -+ } - } - -- status = fdt_get_status(bsec_subnode); -- if ((status & DT_NON_SECURE) == 0U) { -+ if ((fdt_getprop(fdt, bsec_subnode, -+ "st,non-secure-otp", NULL)) == NULL) { - continue; - } - -- size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t); -- -- if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) { -- size++; -+ if (((offset % sizeof(uint32_t)) != 0) || -+ ((length % sizeof(uint32_t)) != 0)) { -+ ERROR("Unaligned non-secure OTP\n"); -+ panic(); - } - -- for (i = reg; i < (reg + size); i++) { -+ size = length / sizeof(uint32_t); -+ -+ for (i = otp; i < (otp + size); i++) { - enable_non_secure_access(i); - } - } -@@ -267,6 +293,79 @@ uint32_t bsec_get_config(struct bsec_config *cfg) - } - - /* -+ * bsec_find_otp_name_in_dt: get OTP ID and length in DT. -+ * name: sub-node name to look up. -+ * otp: pointer to read OTP number or NULL. -+ * otp_len: pointer to read OTP length in bits or NULL. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_find_otp_name_in_dt(const char *name, uint32_t *otp, -+ uint32_t *otp_len) -+{ -+ void *fdt; -+ int node; -+ int index, len; -+ const fdt32_t *cuint; -+ -+ if ((name == NULL) || (otp == NULL)) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ node = dt_get_node_by_compatible(DT_NVMEM_LAYOUT_COMPAT); -+ if (node < 0) { -+ return BSEC_ERROR; -+ } -+ -+ index = fdt_stringlist_search(fdt, node, "nvmem-cell-names", name); -+ if (index < 0) { -+ return BSEC_ERROR; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "nvmem-cells", &len); -+ if (cuint == NULL) { -+ return BSEC_ERROR; -+ } -+ -+ if ((index * (int)sizeof(uint32_t)) > len) { -+ return BSEC_ERROR; -+ } -+ -+ cuint += index; -+ -+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); -+ if (node < 0) { -+ ERROR("Malformed nvmem_layout node: ignored\n"); -+ return BSEC_ERROR; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", &len); -+ if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) { -+ ERROR("Malformed nvmem_layout node: ignored\n"); -+ return BSEC_ERROR; -+ } -+ -+ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { -+ ERROR("Misaligned nvmem_layout element: ignored\n"); -+ return BSEC_ERROR; -+ } -+ -+ if (otp != NULL) { -+ *otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); -+ } -+ -+ if (otp_len != NULL) { -+ cuint++; -+ *otp_len = fdt32_to_cpu(*cuint) * CHAR_BIT; -+ } -+ -+ return BSEC_OK; -+} -+ -+/* - * bsec_shadow_register: copy SAFMEM OTP to BSEC data. - * otp: OTP number. - * return value: BSEC_OK if no error. -diff --git a/drivers/st/clk/stm32mp1_calib.c b/drivers/st/clk/stm32mp1_calib.c -index 030a84f..14d9d8d 100644 ---- a/drivers/st/clk/stm32mp1_calib.c -+++ b/drivers/st/clk/stm32mp1_calib.c -@@ -16,13 +16,11 @@ - #include - #include - #include -+#include - #include - #include - #include - #include --#include --#include --#include - #include - #include - #include -diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c -index 286234e..e5ffc11 100644 ---- a/drivers/st/clk/stm32mp1_clk.c -+++ b/drivers/st/clk/stm32mp1_clk.c -@@ -16,18 +16,14 @@ - #include - #include - #include -+#include - #include - #include - #include - #include --#include --#include --#include - #include - #include --#include - #include --#include - #include - - #define MAX_HSI_HZ 64000000 -@@ -42,6 +38,19 @@ - #define HSIDIV_TIMEOUT TIMEOUT_200MS - #define OSCRDY_TIMEOUT TIMEOUT_1S - -+/* PLL settings computation related definitions */ -+#define POST_DIVM_MIN 8000000 -+#define POST_DIVM_MAX 16000000 -+#define DIVM_MIN 0 -+#define DIVM_MAX 63 -+#define DIVN_MIN 24 -+#define DIVN_MAX 99 -+#define DIVP_MIN 0 -+#define DIVP_MAX 127 -+#define FRAC_MAX 8192 -+#define VCO_MIN 800000000 -+#define VCO_MAX 1600000000 -+ - enum stm32mp1_parent_id { - /* Oscillators are defined in enum stm32mp_osc_id */ - -@@ -204,6 +213,14 @@ struct stm32mp1_clk_pll { - enum stm32mp_osc_id refclk[REFCLK_SIZE]; - }; - -+struct stm32mp1_pll_settings { -+ uint32_t valid_id; -+ uint32_t freq[PLAT_MAX_OPP_NB]; -+ uint32_t volt[PLAT_MAX_OPP_NB]; -+ uint32_t cfg[PLAT_MAX_OPP_NB][PLAT_MAX_PLLCFG_NB]; -+ uint32_t frac[PLAT_MAX_OPP_NB]; -+}; -+ - /* Clocks with selectable source and non set/clr register access */ - #define _CLK_SELEC(off, b, idx, s) \ - { \ -@@ -460,7 +477,6 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { - }; - - /* Define characteristic of PLL according type */ --#define DIVN_MIN 24 - static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { - [PLL_800] = { - .refclk_min = 4, -@@ -585,6 +601,8 @@ static unsigned long stm32mp1_osc[NB_OSC]; - static struct spinlock reg_lock; - static unsigned int gate_refcounts[NB_GATES]; - static struct spinlock refcount_lock; -+static struct stm32mp1_pll_settings pll1_settings; -+static uint32_t current_opp_khz; - - static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) - { -@@ -1462,11 +1480,8 @@ static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) - return 0; - } - --static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, -- uint32_t *pllcfg) -+static uint32_t stm32mp1_pll_compute_pllxcfgr2(uint32_t *pllcfg) - { -- const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -- uintptr_t rcc_base = stm32mp_rcc_base(); - uint32_t value; - - value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & -@@ -1475,21 +1490,33 @@ static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, - RCC_PLLNCFGR2_DIVQ_MASK; - value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & - RCC_PLLNCFGR2_DIVR_MASK; -- mmio_write_32(rcc_base + pll->pllxcfgr2, value); -+ -+ return value; - } - --static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, -- uint32_t *pllcfg, uint32_t fracv) -+static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, -+ uint32_t *pllcfg) - { - const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ uint32_t value; -+ -+ value = stm32mp1_pll_compute_pllxcfgr2(pllcfg); -+ -+ mmio_write_32(rcc_base + pll->pllxcfgr2, value); -+} -+ -+static int stm32mp1_pll_compute_pllxcfgr1(const struct stm32mp1_clk_pll *pll, -+ uint32_t *pllcfg, uint32_t *cfgr1) -+{ - uint32_t rcc_base = stm32mp_rcc_base(); - enum stm32mp1_plltype type = pll->plltype; - unsigned long refclk; - uint32_t ifrge = 0; -- uint32_t src, value; -+ uint32_t src; - - src = mmio_read_32(rcc_base + pll->rckxselr) & -- RCC_SELR_REFCLK_SRC_MASK; -+ RCC_SELR_REFCLK_SRC_MASK; - - refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / - (pllcfg[PLLCFG_M] + 1U); -@@ -1503,23 +1530,39 @@ static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, - ifrge = 1U; - } - -- value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & -- RCC_PLLNCFGR1_DIVN_MASK; -- value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & -- RCC_PLLNCFGR1_DIVM_MASK; -- value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & -- RCC_PLLNCFGR1_IFRGE_MASK; -+ *cfgr1 = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & -+ RCC_PLLNCFGR1_DIVN_MASK; -+ *cfgr1 |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & -+ RCC_PLLNCFGR1_DIVM_MASK; -+ *cfgr1 |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & -+ RCC_PLLNCFGR1_IFRGE_MASK; -+ -+ return 0; -+} -+ -+static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, -+ uint32_t *pllcfg, uint32_t fracv) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t rcc_base = stm32mp_rcc_base(); -+ uint32_t value; -+ int ret; -+ -+ ret = stm32mp1_pll_compute_pllxcfgr1(pll, pllcfg, &value); -+ if (ret != 0) { -+ return ret; -+ } -+ - mmio_write_32(rcc_base + pll->pllxcfgr1, value); - - /* Fractional configuration */ - value = 0; - mmio_write_32(rcc_base + pll->pllxfracr, value); - -+ /* Frac must be enabled only once its configuration is loaded */ - value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; - mmio_write_32(rcc_base + pll->pllxfracr, value); -- -- value |= RCC_PLLNFRACR_FRACLE; -- mmio_write_32(rcc_base + pll->pllxfracr, value); -+ mmio_setbits_32(rcc_base + pll->pllxfracr, RCC_PLLNFRACR_FRACLE); - - stm32mp1_pll_config_output(pll_id, pllcfg); - -@@ -1684,17 +1727,24 @@ unsigned long stm32mp_clk_timer_get_rate(unsigned long id) - return parent_rate * (timpre + 1) * 2; - } - --void stm32mp1_stgen_increment(unsigned long long offset_in_ms) -+unsigned long long stm32mp1_stgen_get_counter(void) -+{ -+ uintptr_t stgen = fdt_get_stgen_base(); -+ -+ return (((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) | -+ mmio_read_32(stgen + CNTCVL_OFF)); -+} -+ -+void stm32mp1_stgen_restore_counter(unsigned long long value, -+ unsigned long long offset_in_ms) - { - uintptr_t stgen; - unsigned long long cnt; - - stgen = fdt_get_stgen_base(); - -- cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) | -- mmio_read_32(stgen + CNTCVL_OFF); -- -- cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U; -+ cnt = value + ((offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / -+ 1000U); - - mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); - mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt); -@@ -1753,6 +1803,187 @@ static void stm32mp1_pkcs_config(uint32_t pkcs) - mmio_clrsetbits_32(address, mask, value); - } - -+static bool clk_pll1_settings_are_valid(void) -+{ -+ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID; -+} -+ -+int stm32mp1_round_opp_khz(uint32_t *freq_khz) -+{ -+ unsigned int i; -+ uint32_t round_opp = 0U; -+ -+ if (!clk_pll1_settings_are_valid()) { -+ /* -+ * No OPP table in DT, or an error occurred during PLL1 -+ * settings computation, system can only work on current -+ * operating point, so return current CPU frequency. -+ */ -+ *freq_khz = current_opp_khz; -+ -+ return 0; -+ } -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if ((pll1_settings.freq[i] <= *freq_khz) && -+ (pll1_settings.freq[i] > round_opp)) { -+ round_opp = pll1_settings.freq[i]; -+ } -+ } -+ -+ *freq_khz = round_opp; -+ -+ return 0; -+} -+ -+/* -+ * Check if PLL1 can be configured on the fly. -+ * @result (-1) => config on the fly is not possible. -+ * (0) => config on the fly is possible. -+ * (+1) => same parameters, no need to reconfigure. -+ * Return value is 0 if no error. -+ */ -+static int stm32mp1_is_pll_config_on_the_fly(enum stm32mp1_pll_id pll_id, -+ uint32_t *pllcfg, uint32_t fracv, -+ int *result) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ uint32_t fracr; -+ uint32_t value; -+ int ret; -+ -+ ret = stm32mp1_pll_compute_pllxcfgr1(pll, pllcfg, &value); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { -+ /* Different DIVN/DIVM, can't config on the fly */ -+ *result = -1; -+ return 0; -+ } -+ -+ *result = true; -+ -+ fracr = fracv << RCC_PLLNFRACR_FRACV_SHIFT; -+ fracr |= RCC_PLLNFRACR_FRACLE; -+ value = stm32mp1_pll_compute_pllxcfgr2(pllcfg); -+ -+ if ((mmio_read_32(rcc_base + pll->pllxfracr) == fracr) && -+ (mmio_read_32(rcc_base + pll->pllxcfgr2) == value)) { -+ /* Same parameters, no need to config */ -+ *result = 1; -+ } else { -+ *result = 0; -+ } -+ -+ return 0; -+} -+ -+static int stm32mp1_pll1_config_from_opp_khz(uint32_t freq_khz) -+{ -+ unsigned int i; -+ int ret; -+ int config_on_the_fly = -1; -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if (pll1_settings.freq[i] == freq_khz) { -+ break; -+ } -+ } -+ -+ if (i == PLAT_MAX_OPP_NB) { -+ return -ENXIO; -+ } -+ -+ ret = stm32mp1_is_pll_config_on_the_fly(_PLL1, &pll1_settings.cfg[i][0], -+ pll1_settings.frac[i], -+ &config_on_the_fly); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (config_on_the_fly == 1) { -+ /* No need to reconfigure, setup already OK */ -+ return 0; -+ } -+ -+ if (config_on_the_fly == -1) { -+ /* Switch to HSI and stop PLL1 before reconfiguration */ -+ ret = stm32mp1_set_clksrc(CLK_MPU_HSI); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = stm32mp1_pll_stop(_PLL1); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ -+ ret = stm32mp1_pll_config(_PLL1, &pll1_settings.cfg[i][0], -+ pll1_settings.frac[i]); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (config_on_the_fly == -1) { -+ /* Start PLL1 and switch back to after reconfiguration */ -+ stm32mp1_pll_start(_PLL1); -+ -+ ret = stm32mp1_pll_output(_PLL1, -+ pll1_settings.cfg[i][PLLCFG_O]); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+int stm32mp1_set_opp_khz(uint32_t freq_khz) -+{ -+ if (freq_khz == current_opp_khz) { -+ /* OPP already set, nothing to do */ -+ return 0; -+ } -+ -+ if (!clk_pll1_settings_are_valid()) { -+ /* -+ * No OPP table in DT or an error occurred during PLL1 -+ * settings computation, system can only work on current -+ * operating point so return error. -+ */ -+ return -EACCES; -+ } -+ -+ /* Check that PLL1 (without MPUDIV) is MPU clock source */ -+ if (((mmio_read_32(stm32mp_rcc_base() + RCC_MPCKSELR) & -+ RCC_SELR_SRC_MASK)) != RCC_MPCKSELR_PLL) { -+ return -EPERM; -+ } -+ -+ if (stm32mp1_pll1_config_from_opp_khz(freq_khz) != 0) { -+ /* Restore original value */ -+ if (stm32mp1_pll1_config_from_opp_khz(current_opp_khz) != 0) { -+ ERROR("No CPU operating point can be set\n"); -+ panic(); -+ } -+ -+ return -EIO; -+ } -+ -+ current_opp_khz = freq_khz; -+ -+ return 0; -+} -+ - #if defined(IMAGE_BL32) - void stm32mp1_clk_mpu_suspend(void) - { -@@ -1779,15 +2010,349 @@ void stm32mp1_clk_mpu_resume(void) - } - #endif - --int stm32mp1_clk_init(void) -+static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg, -+ uint32_t *fracv, uint32_t *csg, -+ bool *csg_set) -+{ -+ int ret; -+ -+ ret = fdt_read_uint32_array(plloff, "cfg", pllcfg, (uint32_t)PLLCFG_NB); -+ if (ret < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ *fracv = fdt_read_uint32_default(plloff, "frac", 0); -+ -+ ret = fdt_read_uint32_array(plloff, "csg", csg, (uint32_t)PLLCSG_NB); -+ -+ *csg_set = (ret == 0); -+ -+ if (ret == -FDT_ERR_NOTFOUND) { -+ ret = 0; -+ } -+ -+ return ret; -+} -+ -+static int clk_compute_pll1_settings(unsigned long input_freq, -+ uint32_t freq_khz, -+ uint32_t *pllcfg, uint32_t *fracv) -+{ -+ unsigned long post_divm; -+ unsigned long long output_freq = freq_khz * 1000U; -+ unsigned long long freq; -+ unsigned long long vco; -+ int divm; -+ int divn; -+ int divp; -+ int frac; -+ int i; -+ unsigned int diff; -+ unsigned int best_diff = UINT_MAX; -+ -+ /* Following parameters have always the same value */ -+ pllcfg[PLLCFG_Q] = 0; -+ pllcfg[PLLCFG_R] = 0; -+ pllcfg[PLLCFG_O] = PQR(1, 0, 0); -+ -+ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) { -+ post_divm = input_freq / (unsigned long)(divm + 1); -+ -+ if ((post_divm < POST_DIVM_MIN) || -+ (post_divm > POST_DIVM_MAX)) { -+ continue; -+ } -+ -+ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { -+ -+ freq = output_freq * (divm + 1) * (divp + 1); -+ -+ divn = (int)((freq / input_freq) - 1); -+ if ((divn < DIVN_MIN) || (divn > DIVN_MAX)) { -+ continue; -+ } -+ -+ frac = (int)(((freq * FRAC_MAX) / input_freq) - -+ ((divn + 1) * FRAC_MAX)); -+ -+ /* 2 loops to refine the fractional part */ -+ for (i = 2; i != 0; i--) { -+ if (frac > FRAC_MAX) { -+ break; -+ } -+ -+ vco = (post_divm * (divn + 1)) + -+ ((post_divm * (unsigned long long)frac) / -+ FRAC_MAX); -+ -+ if ((vco < (VCO_MIN / 2)) || -+ (vco > (VCO_MAX / 2))) { -+ frac++; -+ continue; -+ } -+ -+ freq = vco / (divp + 1); -+ if (output_freq < freq) { -+ diff = (unsigned int)(freq - -+ output_freq); -+ } else { -+ diff = (unsigned int)(output_freq - -+ freq); -+ } -+ -+ if (diff < best_diff) { -+ pllcfg[PLLCFG_M] = divm; -+ pllcfg[PLLCFG_N] = divn; -+ pllcfg[PLLCFG_P] = divp; -+ *fracv = frac; -+ -+ if (diff == 0) { -+ return 0; -+ } -+ -+ best_diff = diff; -+ } -+ -+ frac++; -+ } -+ } -+ } -+ -+ if (best_diff == UINT_MAX) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int clk_get_pll1_settings(uint32_t clksrc, uint32_t freq_khz, -+ uint32_t *pllcfg, uint32_t *fracv) -+{ -+ unsigned long input_freq; -+ unsigned int i; -+ -+ assert(pllcfg != NULL); -+ assert(fracv != NULL); -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if (pll1_settings.freq[i] == freq_khz) { -+ break; -+ } -+ } -+ -+ if (((i == PLAT_MAX_OPP_NB) && (pll1_settings.valid_id == 0U)) || -+ ((i < PLAT_MAX_OPP_NB) && -+ (pll1_settings.cfg[i][PLLCFG_O] == 0U))) { -+ /* -+ * Either PLL1 settings structure is completely empty, -+ * or this frequency is not yet filled: compute settings. -+ */ -+ switch (clksrc) { -+ case CLK_PLL12_HSI: -+ input_freq = stm32mp_clk_get_rate(CK_HSI); -+ break; -+ case CLK_PLL12_HSE: -+ input_freq = stm32mp_clk_get_rate(CK_HSE); -+ break; -+ default: -+ panic(); -+ } -+ -+ return clk_compute_pll1_settings(input_freq, freq_khz, pllcfg, -+ fracv); -+ } -+ -+ if ((i < PLAT_MAX_OPP_NB) && -+ (pll1_settings.cfg[i][PLLCFG_O] != 0U)) { -+ /* -+ * Index is in range and PLL1 settings line is filled, -+ * use content to answer to the request. -+ */ -+ memcpy(pllcfg, &pll1_settings.cfg[i][0], -+ sizeof(uint32_t) * PLAT_MAX_PLLCFG_NB); -+ *fracv = pll1_settings.frac[i]; -+ -+ return 0; -+ } -+ -+ return -1; -+} -+ -+int stm32mp1_clk_get_maxfreq_opp(uint32_t *freq_khz, -+ uint32_t *voltage_mv) -+{ -+ unsigned int i; -+ uint32_t freq = 0U; -+ uint32_t voltage = 0U; -+ -+ assert(freq_khz != NULL); -+ assert(voltage_mv != NULL); -+ -+ if (!clk_pll1_settings_are_valid()) { -+ return -1; -+ } -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if (pll1_settings.freq[i] > freq) { -+ freq = pll1_settings.freq[i]; -+ voltage = pll1_settings.volt[i]; -+ } -+ } -+ -+ if ((freq == 0U) || (voltage == 0U)) { -+ return -1; -+ } -+ -+ *freq_khz = freq; -+ *voltage_mv = voltage; -+ -+ return 0; -+} -+ -+static int clk_save_current_pll1_settings(uint32_t buck1_voltage) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); -+ uint32_t rcc_base = stm32mp_rcc_base(); -+ uint32_t freq; -+ unsigned int i; -+ -+ freq = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000L); -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if (pll1_settings.freq[i] == freq) { -+ break; -+ } -+ } -+ -+ if ((i == PLAT_MAX_OPP_NB) || -+ ((pll1_settings.volt[i] != buck1_voltage) && -+ (buck1_voltage != 0U))) { -+ return -1; -+ } -+ -+ pll1_settings.cfg[i][PLLCFG_M] = -+ (mmio_read_32(rcc_base + pll->pllxcfgr1) & -+ RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT; -+ -+ pll1_settings.cfg[i][PLLCFG_N] = -+ (mmio_read_32(rcc_base + pll->pllxcfgr1) & -+ RCC_PLLNCFGR1_DIVN_MASK) >> RCC_PLLNCFGR1_DIVN_SHIFT; -+ -+ pll1_settings.cfg[i][PLLCFG_P] = -+ (mmio_read_32(rcc_base + pll->pllxcfgr2) & -+ RCC_PLLNCFGR2_DIVP_MASK) >> RCC_PLLNCFGR2_DIVP_SHIFT; -+ -+ pll1_settings.cfg[i][PLLCFG_Q] = -+ (mmio_read_32(rcc_base + pll->pllxcfgr2) & -+ RCC_PLLNCFGR2_DIVQ_MASK) >> RCC_PLLNCFGR2_DIVQ_SHIFT; -+ -+ pll1_settings.cfg[i][PLLCFG_R] = -+ (mmio_read_32(rcc_base + pll->pllxcfgr2) & -+ RCC_PLLNCFGR2_DIVR_MASK) >> RCC_PLLNCFGR2_DIVR_SHIFT; -+ -+ pll1_settings.cfg[i][PLLCFG_O] = -+ mmio_read_32(rcc_base + pll->pllxcr) >> -+ RCC_PLLNCR_DIVEN_SHIFT; -+ -+ pll1_settings.frac[i] = -+ (mmio_read_32(rcc_base + pll->pllxfracr) & -+ RCC_PLLNFRACR_FRACV_MASK) >> RCC_PLLNFRACR_FRACV_SHIFT; -+ -+ return i; -+} -+ -+static uint32_t stm32mp1_clk_get_pll1_current_clksrc(void) - { -+ uint32_t value; -+ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); - uint32_t rcc_base = stm32mp_rcc_base(); -+ -+ value = mmio_read_32(rcc_base + pll->rckxselr); -+ -+ switch (value & RCC_SELR_REFCLK_SRC_MASK) { -+ case 0: -+ return CLK_PLL12_HSI; -+ case 1: -+ return CLK_PLL12_HSE; -+ default: -+ panic(); -+ } -+} -+ -+int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage) -+{ -+ int i; -+ int ret; -+ int index; -+ uint32_t count = PLAT_MAX_OPP_NB; -+ uint32_t clksrc; -+ -+ ret = dt_get_all_opp_freqvolt(&count, pll1_settings.freq, -+ pll1_settings.volt); -+ switch (ret) { -+ case 0: -+ break; -+ case -FDT_ERR_NOTFOUND: -+ VERBOSE("Cannot find OPP table in DT, use default settings.\n"); -+ return 0; -+ default: -+ ERROR("Inconsistent OPP settings found in DT, ignored.\n"); -+ return 0; -+ } -+ -+ index = clk_save_current_pll1_settings(buck1_voltage); -+ -+ clksrc = stm32mp1_clk_get_pll1_current_clksrc(); -+ -+ for (i = 0; i < (int)count; i++) { -+ if (i == index) { -+ continue; -+ } -+ -+ ret = clk_get_pll1_settings(clksrc, pll1_settings.freq[i], -+ &pll1_settings.cfg[i][0], -+ &pll1_settings.frac[i]); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ -+ pll1_settings.valid_id = PLL1_SETTINGS_VALID_ID; -+ -+ return 0; -+} -+ -+void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data, size_t size) -+{ -+ if ((size != sizeof(pll1_settings)) || !clk_pll1_settings_are_valid()) { -+ panic(); -+ } -+ -+ memcpy(data, &pll1_settings, size); -+} -+ -+void stm32mp1_clk_lp_load_opp_pll1_settings(uint8_t *data, size_t size) -+{ -+ if (size != sizeof(pll1_settings)) { -+ panic(); -+ } -+ -+ memcpy(&pll1_settings, data, size); -+} -+ -+int stm32mp1_clk_init(uint32_t pll1_freq_khz) -+{ -+ uint32_t rcc_base = stm32mp_rcc_base(); -+ uint32_t pllfracv[_PLL_NB]; -+ uint32_t pllcsg[_PLL_NB][PLLCSG_NB]; - unsigned int clksrc[CLKSRC_NB]; - unsigned int clkdiv[CLKDIV_NB]; - unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; - int plloff[_PLL_NB]; - int ret, len; - enum stm32mp1_pll_id i; -+ bool pllcsg_set[_PLL_NB]; -+ bool pllcfg_valid[_PLL_NB]; - bool lse_css = false; - bool pll3_preserve = false; - bool pll4_preserve = false; -@@ -1819,14 +2384,27 @@ int stm32mp1_clk_init(void) - snprintf(name, sizeof(name), "st,pll@%d", i); - plloff[i] = fdt_rcc_subnode_offset(name); - -- if (!fdt_check_node(plloff[i])) { -+ pllcfg_valid[i] = fdt_check_node(plloff[i]); -+ if (pllcfg_valid[i]) { -+ ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i], -+ &pllfracv[i], pllcsg[i], -+ &pllcsg_set[i]); -+ if (ret != 0) { -+ return ret; -+ } -+ - continue; - } - -- ret = fdt_read_uint32_array(plloff[i], "cfg", -- pllcfg[i], (int)PLLCFG_NB); -- if (ret < 0) { -- return -FDT_ERR_NOTFOUND; -+ if ((i == _PLL1) && (pll1_freq_khz != 0U)) { -+ ret = clk_get_pll1_settings(clksrc[CLKSRC_PLL12], -+ pll1_freq_khz, -+ pllcfg[i], &pllfracv[i]); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ pllcfg_valid[i] = true; - } - } - -@@ -1977,15 +2555,12 @@ int stm32mp1_clk_init(void) - - /* Configure and start PLLs */ - for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { -- uint32_t fracv; -- uint32_t csg[PLLCSG_NB]; -- - if (((i == _PLL3) && pll3_preserve) || - ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { - continue; - } - -- if (!fdt_check_node(plloff[i])) { -+ if (!pllcfg_valid[i]) { - continue; - } - -@@ -1995,25 +2570,20 @@ int stm32mp1_clk_init(void) - continue; - } - -- fracv = fdt_read_uint32_default(plloff[i], "frac", 0); -- -- ret = stm32mp1_pll_config(i, pllcfg[i], fracv); -+ ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]); - if (ret != 0) { - return ret; - } -- ret = fdt_read_uint32_array(plloff[i], "csg", csg, -- (uint32_t)PLLCSG_NB); -- if (ret == 0) { -- stm32mp1_pll_csg(i, csg); -- } else if (ret != -FDT_ERR_NOTFOUND) { -- return ret; -+ -+ if (pllcsg_set[i]) { -+ stm32mp1_pll_csg(i, pllcsg[i]); - } - - stm32mp1_pll_start(i); - } - /* Wait and start PLLs ouptut when ready */ - for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { -- if (!fdt_check_node(plloff[i])) { -+ if (!pllcfg_valid[i]) { - continue; - } - -@@ -2425,9 +2995,21 @@ static void sync_earlyboot_clocks_state(void) - - int stm32mp1_clk_probe(void) - { -+ unsigned long freq_khz; -+ -+ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB); -+ - stm32mp1_osc_init(); - - sync_earlyboot_clocks_state(); - -+ /* Save current CPU operating point value */ -+ freq_khz = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000UL); -+ if (freq_khz > (unsigned long)UINT32_MAX) { -+ panic(); -+ } -+ -+ current_opp_khz = (uint32_t)freq_khz; -+ - return 0; - } -diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c -index 99a7360..1777a24 100644 ---- a/drivers/st/clk/stm32mp1_clkfunc.c -+++ b/drivers/st/clk/stm32mp1_clkfunc.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 - */ -@@ -10,8 +10,6 @@ - #include - #include - #include --#include --#include - #include - #include - -@@ -56,6 +54,10 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) - if (strncmp(cchar, name, (size_t)ret) == 0) { - const fdt32_t *cuint; - -+ if (fdt_get_status(subnode) == DT_DISABLED) { -+ goto exit; -+ } -+ - cuint = fdt_getprop(fdt, subnode, "clock-frequency", - &ret); - if (cuint == NULL) { -@@ -68,7 +70,8 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) - } - } - -- /* Oscillator not found, freq=0 */ -+exit: -+ /* Oscillator not found or disabled, freq=0 */ - *freq = 0; - return 0; - } -@@ -170,11 +173,11 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - ******************************************************************************/ - int fdt_rcc_enable_it(const char *name) - { -- void *fdt; -+ int node = fdt_get_rcc_node(); - -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -+ if (node < 0) { -+ return -ENODEV; - } - -- return stm32_gic_enable_spi(fdt_get_rcc_node(fdt), name); -+ return stm32_gic_enable_spi(node, name); - } -diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c -index 5c7e202..a8ae62e 100644 ---- a/drivers/st/clk/stm32mp_clkfunc.c -+++ b/drivers/st/clk/stm32mp_clkfunc.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 - */ -@@ -9,8 +9,6 @@ - #include - #include - #include --#include --#include - - #define DT_STGEN_COMPAT "st,stm32-stgen" - #define DT_UART_COMPAT "st,stm32h7-uart" -@@ -18,37 +16,9 @@ - /******************************************************************************* - * This function returns the RCC node in the device tree. - ******************************************************************************/ --int fdt_get_rcc_node(void *fdt) -+int fdt_get_rcc_node(void) - { -- return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); --} -- --/******************************************************************************* -- * This function reads the rcc base address. -- * It reads the value indicated inside the device tree. -- * Returns address on success, and 0 on failure. -- ******************************************************************************/ --uint32_t fdt_rcc_read_addr(void) --{ -- int node; -- void *fdt; -- const fdt32_t *cuint; -- -- if (fdt_get_address(&fdt) == 0) { -- return 0; -- } -- -- node = fdt_get_rcc_node(fdt); -- if (node < 0) { -- return 0; -- } -- -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) { -- return 0; -- } -- -- return fdt32_to_cpu(*cuint); -+ return dt_get_node_by_compatible(DT_RCC_CLK_COMPAT); - } - - /******************************************************************************* -@@ -62,13 +32,8 @@ int fdt_rcc_read_uint32_array(const char *prop_name, - uint32_t *array, uint32_t count) - { - int node; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -- } - -- node = fdt_get_rcc_node(fdt); -+ node = fdt_get_rcc_node(); - if (node < 0) { - return -FDT_ERR_NOTFOUND; - } -@@ -85,13 +50,8 @@ int fdt_rcc_read_uint32_array(const char *prop_name, - uint32_t fdt_rcc_read_uint32_default(const char *prop_name, uint32_t dflt_value) - { - int node; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return dflt_value; -- } - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -+ node = fdt_get_rcc_node(); - if (node < 0) { - return dflt_value; - } -@@ -113,7 +73,7 @@ int fdt_rcc_subnode_offset(const char *name) - return -ENOENT; - } - -- node = fdt_get_rcc_node(fdt); -+ node = fdt_get_rcc_node(); - if (node < 0) { - return -FDT_ERR_NOTFOUND; - } -@@ -142,7 +102,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) - return NULL; - } - -- node = fdt_get_rcc_node(fdt); -+ node = fdt_get_rcc_node(); - if (node < 0) { - return NULL; - } -@@ -164,13 +124,8 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) - bool fdt_get_rcc_secure_status(void) - { - int node; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return false; -- } - -- node = fdt_get_rcc_node(fdt); -+ node = fdt_get_rcc_node(); - if (node < 0) { - return false; - } -@@ -185,25 +140,7 @@ bool fdt_get_rcc_secure_status(void) - ******************************************************************************/ - uintptr_t fdt_get_stgen_base(void) - { -- int node; -- const fdt32_t *cuint; -- void *fdt; -- -- if (fdt_get_address(&fdt) == 0) { -- return 0; -- } -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); -- if (node < 0) { -- return 0; -- } -- -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) { -- return 0; -- } -- -- return fdt32_to_cpu(*cuint); -+ return dt_get_peripheral_base(DT_STGEN_COMPAT); - } - - /******************************************************************************* -@@ -273,35 +210,31 @@ unsigned long fdt_get_uart_clock_freq(uintptr_t instance) - { - int node; - void *fdt; -+ unsigned long clk_id; - - if (fdt_get_address(&fdt) == 0) { - return 0; - } - - /* Check for UART nodes */ -- node = fdt_node_offset_by_compatible(fdt, -1, DT_UART_COMPAT); -- while (node != -FDT_ERR_NOTFOUND) { -- const fdt32_t *cuint; -- -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) -- goto next; -- -- if ((uintptr_t)fdt32_to_cpu(*cuint) == instance) { -- unsigned long clk_id; -- -- cuint = fdt_getprop(fdt, node, "clocks", NULL); -- if (cuint == NULL) -- goto next; -- -- cuint++; -- clk_id = (unsigned long)(fdt32_to_cpu(*cuint)); -+ node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance); -+ if (node < 0) { -+ return 0UL; -+ } - -- return stm32mp_clk_get_rate(clk_id); -- } --next: -- node = fdt_node_offset_by_compatible(fdt, node, DT_UART_COMPAT); -+ clk_id = fdt_get_clock_id(node); -+ if (clk_id < 0) { -+ return 0UL; - } - -- return 0; -+ return stm32mp_clk_get_rate(clk_id); -+} -+ -+/******************************************************************************* -+ * This function checks if PLL1 hard-coded settings have been defined in DT. -+ * Returns true if PLL1 node is found and enabled, false if not. -+ ******************************************************************************/ -+bool fdt_is_pll1_predefined(void) -+{ -+ return fdt_check_node(fdt_rcc_subnode_offset(DT_PLL1_NODE_NAME)); - } -diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c -index 00ebb22..1be2c23 100644 ---- a/drivers/st/ddr/stm32mp1_ddr.c -+++ b/drivers/st/ddr/stm32mp1_ddr.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,8 +13,6 @@ - #include - #include - #include --#include --#include - #include - - struct reg_desc { -@@ -652,7 +650,8 @@ static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) - /* Quasi-dynamic register update*/ - mmio_setbits_32((uintptr_t)&ctl->rfshctl3, - DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); -- mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); -+ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN | -+ DDRCTRL_PWRCTL_SELFREF_EN); - mmio_clrbits_32((uintptr_t)&ctl->dfimisc, - DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); - stm32mp1_wait_sw_done_ack(ctl); -@@ -670,6 +669,10 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, - mmio_setbits_32((uintptr_t)&ctl->pwrctl, - DDRCTRL_PWRCTL_POWERDOWN_EN); - } -+ if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN) != 0U) { -+ mmio_setbits_32((uintptr_t)&ctl->pwrctl, -+ DDRCTRL_PWRCTL_SELFREF_EN); -+ } - mmio_setbits_32((uintptr_t)&ctl->dfimisc, - DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); - stm32mp1_wait_sw_done_ack(ctl); -diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c -index 63f254f..8f9d07b 100644 ---- a/drivers/st/ddr/stm32mp1_ddr_helpers.c -+++ b/drivers/st/ddr/stm32mp1_ddr_helpers.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 - */ -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - - #define TIMEOUT_500US us2tick(500) - -@@ -127,6 +126,9 @@ static int ddr_sw_self_refresh_in(void) - DDRPHYC_ACIOCR_CSPDD_MASK, - DDRPHYC_ACIOCR_CSPDD_0); - -+ /* Disable command/address output driver */ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); -+ - mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); - - mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); -@@ -144,6 +146,12 @@ static int ddr_sw_self_refresh_in(void) - /* Disable PZQ cell (PUBL register) */ - mmio_setbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); - -+ /* Set latch */ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE); -+ -+ /* Additional delay to avoid early latch */ -+ udelay(10); -+ - /* Activate sw retention in PWRCTRL */ - pwr_regs_lock(); - mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); -@@ -293,6 +301,9 @@ int ddr_sw_self_refresh_exit(void) - /* Enable pad drivers */ - mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); - -+ /* Enable command/address output driver */ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); -+ - mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, - DDRPHYC_ACIOCR_CKPDD_MASK); - -@@ -303,6 +314,9 @@ int ddr_sw_self_refresh_exit(void) - - mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); - -+ /* Release latch */ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE); -+ - mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, - DDRPHYC_DSGCR_ODTPDD_MASK); - -@@ -369,6 +383,10 @@ void ddr_sr_mode_ssr(void) - uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; - uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); - -+ if (!stm32mp_ddr_supports_ssr_asr()) { -+ return; -+ } -+ - stm32mp1_clk_rcc_regs_lock(); - - mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -@@ -421,6 +439,10 @@ void ddr_sr_mode_asr(void) - uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; - uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); - -+ if (!stm32mp_ddr_supports_ssr_asr()) { -+ return; -+ } -+ - stm32mp1_clk_rcc_regs_lock(); - - mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); -diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c -index 773c9f7..ef35a06 100644 ---- a/drivers/st/ddr/stm32mp1_ram.c -+++ b/drivers/st/ddr/stm32mp1_ram.c -@@ -1,18 +1,15 @@ - /* -- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ - - #include --#include - #include - #include - #include - #include - #include --#include --#include - - #define DDR_PATTERN 0xAAAAAAAAU - #define DDR_ANTIPATTERN 0x55555555U -@@ -220,9 +217,8 @@ static int stm32mp1_ddr_setup(void) - return -ENOENT; - } - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ node = dt_get_node_by_compatible(DT_DDR_COMPAT); - if (node < 0) { -- ERROR("%s: Cannot read DDR node in DT\n", __func__); - return -EINVAL; - } - -@@ -291,11 +287,6 @@ static int stm32mp1_ddr_setup(void) - VERBOSE("%s : ram size(%x, %x)\n", __func__, - (uint32_t)priv->info.base, (uint32_t)priv->info.size); - --#ifndef DCACHE_OFF -- write_sctlr(read_sctlr() & ~SCTLR_C_BIT); -- dcsw_op_all(DC_OP_CISW); --#endif -- - if (config.self_refresh) { - uret = ddr_test_rw_access(); - if (uret != 0U) { -@@ -329,9 +320,8 @@ static int stm32mp1_ddr_setup(void) - } - } - --#ifndef DCACHE_OFF -- write_sctlr(read_sctlr() | SCTLR_C_BIT); --#endif -+ /* Switch to Automatic Self-Refresh */ -+ ddr_sr_mode_asr(); - - return 0; - } -diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c -index 06c3282..f2ddd75 100644 ---- a/drivers/st/etzpc/etzpc.c -+++ b/drivers/st/etzpc/etzpc.c -@@ -1,6 +1,6 @@ - /* -- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -15,8 +15,6 @@ - #include - #include - #include --#include --#include - #include - - /* Device Tree related definitions */ -diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c -index fc0dce8..8c23c5b 100644 ---- a/drivers/st/gpio/stm32_gpio.c -+++ b/drivers/st/gpio/stm32_gpio.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -14,8 +14,6 @@ - #include - #include - #include --#include --#include - - #define DT_GPIO_BANK_SHIFT 12 - #define DT_GPIO_BANK_MASK 0x1F000U -@@ -165,7 +163,7 @@ int dt_set_pinctrl_config(int node) - void *fdt; - - if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -+ return -FDT_ERR_NOTFOUND; - } - - if (status == DT_DISABLED) { -diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c -index ce609ba..f57bf5a 100644 ---- a/drivers/st/i2c/stm32_i2c.c -+++ b/drivers/st/i2c/stm32_i2c.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - - /* STM32 I2C registers offsets */ -@@ -40,8 +39,6 @@ - /* - * struct i2c_spec_s - Private I2C timing specifications. - * @rate: I2C bus speed (Hz) -- * @rate_min: 80% of I2C bus speed (Hz) -- * @rate_max: 120% of I2C bus speed (Hz) - * @fall_max: Max fall time of both SDA and SCL signals (ns) - * @rise_max: Max rise time of both SDA and SCL signals (ns) - * @hddat_min: Min data hold time (ns) -@@ -52,8 +49,6 @@ - */ - struct i2c_spec_s { - uint32_t rate; -- uint32_t rate_min; -- uint32_t rate_max; - uint32_t fall_max; - uint32_t rise_max; - uint32_t hddat_min; -@@ -87,10 +82,9 @@ struct i2c_timing_s { - * [1] https://www.i2c-bus.org/specification/ - */ - static const struct i2c_spec_s i2c_specs[] = { -- [I2C_SPEED_STANDARD] = { -+ /* Standard - 100KHz */ -+ { - .rate = STANDARD_RATE, -- .rate_min = (STANDARD_RATE * 80) / 100, -- .rate_max = (STANDARD_RATE * 120) / 100, - .fall_max = 300, - .rise_max = 1000, - .hddat_min = 0, -@@ -99,10 +93,9 @@ static const struct i2c_spec_s i2c_specs[] = { - .l_min = 4700, - .h_min = 4000, - }, -- [I2C_SPEED_FAST] = { -+ /* Fast - 400KHz */ -+ { - .rate = FAST_RATE, -- .rate_min = (FAST_RATE * 80) / 100, -- .rate_max = (FAST_RATE * 120) / 100, - .fall_max = 300, - .rise_max = 300, - .hddat_min = 0, -@@ -111,10 +104,9 @@ static const struct i2c_spec_s i2c_specs[] = { - .l_min = 1300, - .h_min = 600, - }, -- [I2C_SPEED_FAST_PLUS] = { -+ /* FastPlus - 1MHz */ -+ { - .rate = FAST_PLUS_RATE, -- .rate_min = (FAST_PLUS_RATE * 80) / 100, -- .rate_max = (FAST_PLUS_RATE * 120) / 100, - .fall_max = 100, - .rise_max = 120, - .hddat_min = 0, -@@ -125,9 +117,6 @@ 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, -@@ -162,6 +151,21 @@ static void notif_i2c_timeout(struct i2c_handle_s *hi2c) - hi2c->i2c_state = I2C_STATE_READY; - } - -+static const struct i2c_spec_s *get_specs(uint32_t rate) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) { -+ if (rate <= i2c_specs[i].rate) { -+ return &i2c_specs[i]; -+ } -+ } -+ -+ /* NOT REACHED */ -+ return NULL; -+} -+ -+#define RATE_MIN(rate) (((rate) / 100U) * 80U) - /* - * @brief Compute the I2C device timings. - * @param init: Ref to the initialization configuration structure -@@ -172,7 +176,7 @@ static void notif_i2c_timeout(struct i2c_handle_s *hi2c) - static int i2c_compute_timing(struct stm32_i2c_init_s *init, - uint32_t clock_src, uint32_t *timing) - { -- enum i2c_speed_e mode = init->speed_mode; -+ const struct i2c_spec_s *specs; - uint32_t speed_freq; - uint32_t i2cclk = udiv_round_nearest(I2C_NSEC_PER_SEC, clock_src); - uint32_t i2cbus; -@@ -196,24 +200,21 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - int s = -1; - struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX]; - -- switch (mode) { -- case I2C_SPEED_STANDARD ... I2C_SPEED_FAST_PLUS: -- break; -- default: -- ERROR("I2C speed out of bound {%d/%d}\n", -- mode, I2C_SPEED_FAST_PLUS); -+ specs = get_specs(init->bus_rate); -+ if (specs == NULL) { -+ ERROR("I2C speed out of bound {%d}\n", init->bus_rate); - return -EINVAL; - } - -- speed_freq = i2c_specs[mode].rate; -+ speed_freq = specs->rate; - i2cbus = udiv_round_nearest(I2C_NSEC_PER_SEC, speed_freq); - clk_error_prev = INT_MAX; - -- if ((init->rise_time > i2c_specs[mode].rise_max) || -- (init->fall_time > i2c_specs[mode].fall_max)) { -+ if ((init->rise_time > specs->rise_max) || -+ (init->fall_time > specs->fall_max)) { - ERROR(" I2C timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", -- init->rise_time, i2c_specs[mode].rise_max, -- init->fall_time, i2c_specs[mode].fall_max); -+ init->rise_time, specs->rise_max, -+ init->fall_time, specs->fall_max); - return -EINVAL; - } - -@@ -230,13 +231,13 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0); - dnf_delay = init->digital_filter_coef * i2cclk; - -- sdadel_min = i2c_specs[mode].hddat_min + init->fall_time - -+ sdadel_min = specs->hddat_min + init->fall_time - - af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); - -- sdadel_max = i2c_specs[mode].vddat_max - init->rise_time - -+ sdadel_max = specs->vddat_max - init->rise_time - - af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); - -- scldel_min = init->rise_time + i2c_specs[mode].sudat_min; -+ scldel_min = init->rise_time + specs->sudat_min; - - if (sdadel_min < 0) { - sdadel_min_u = 0; -@@ -290,8 +291,8 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - } - - tsync = af_delay_min + dnf_delay + (2 * i2cclk); -- clk_max = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_min; -- clk_min = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_max; -+ clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate); -+ clk_min = I2C_NSEC_PER_SEC / specs->rate; - - /* - * Among prescaler possibilities discovered above figures out SCL Low -@@ -313,7 +314,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { - uint32_t tscl_l = ((l + 1) * prescaler) + tsync; - -- if ((tscl_l < i2c_specs[mode].l_min) || -+ if ((tscl_l < specs->l_min) || - (i2cclk >= - ((tscl_l - af_delay_min - dnf_delay) / 4))) { - continue; -@@ -326,7 +327,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - init->fall_time; - - if ((tscl >= clk_min) && (tscl <= clk_max) && -- (tscl_h >= i2c_specs[mode].h_min) && -+ (tscl_h >= specs->h_min) && - (i2cclk < tscl_h)) { - int clk_error = tscl - i2cbus; - -@@ -366,6 +367,19 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - return 0; - } - -+static uint32_t get_lower_rate(uint32_t rate) -+{ -+ int i; -+ -+ for (i = ARRAY_SIZE(i2c_specs) - 1; i >= 0; i--) { -+ if (rate > i2c_specs[i].rate) { -+ return i2c_specs[i].rate; -+ } -+ } -+ -+ return i2c_specs[0].rate; -+} -+ - /* - * @brief Setup the I2C device timings. - * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -@@ -379,9 +393,9 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, - uint32_t *timing) - { - int rc = 0; -- unsigned long clock_src; -+ uint32_t clock_src; - -- clock_src = stm32mp_clk_get_rate(hi2c->clock); -+ clock_src = (uint32_t)stm32mp_clk_get_rate(hi2c->clock); - if (clock_src == 0U) { - ERROR("I2C clock rate is 0\n"); - return -EINVAL; -@@ -391,8 +405,8 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, - * 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; -+ if (clock_src == hi2c->saved_frequency) { -+ *timing = hi2c->saved_timing; - return 0; - } - -@@ -400,10 +414,10 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, - rc = i2c_compute_timing(init, clock_src, timing); - if (rc != 0) { - ERROR("Failed to compute I2C timings\n"); -- if (init->speed_mode > I2C_SPEED_STANDARD) { -- init->speed_mode--; -+ if (init->bus_rate > STANDARD_RATE) { -+ init->bus_rate = get_lower_rate(init->bus_rate); - WARN("Downgrade I2C speed to %uHz)\n", -- i2c_specs[init->speed_mode].rate); -+ init->bus_rate); - } else { - break; - } -@@ -415,16 +429,16 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, - return rc; - } - -- VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%li)\n", -- init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src); -+ VERBOSE("I2C Freq(%i), Clk Source(%i)\n", -+ init->bus_rate, clock_src); - VERBOSE("I2C Rise(%i) and Fall(%i) Time\n", - init->rise_time, init->fall_time); - VERBOSE("I2C Analog Filter(%s), DNF(%i)\n", - (init->analog_filter ? "On" : "Off"), - init->digital_filter_coef); - -- saved_timing = *timing; -- saved_frequency = clock_src; -+ hi2c->saved_timing = *timing; -+ hi2c->saved_frequency = clock_src; - - return 0; - } -@@ -469,49 +483,30 @@ static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, - /* - * @brief Get I2C setup information from the device tree and set pinctrl - * configuration. -- * @param fdt: Pointer to the device tree - * @param node: I2C node offset - * @param init: Ref to the initialization configuration structure - * @retval 0 if OK, negative value else - */ --int stm32_i2c_get_setup_from_fdt(void *fdt, int node, -- struct stm32_i2c_init_s *init) -+int stm32_i2c_get_setup_from_fdt(int node, struct stm32_i2c_init_s *init) - { -- const fdt32_t *cuint; -- -- cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); -- if (cuint == NULL) { -- init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; -- } else { -- init->rise_time = fdt32_to_cpu(*cuint); -- } -- -- cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); -- if (cuint == NULL) { -- init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; -- } else { -- init->fall_time = fdt32_to_cpu(*cuint); -- } -- -- cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); -- if (cuint == NULL) { -- init->speed_mode = STM32_I2C_SPEED_DEFAULT; -- } else { -- switch (fdt32_to_cpu(*cuint)) { -- case STANDARD_RATE: -- init->speed_mode = I2C_SPEED_STANDARD; -- break; -- case FAST_RATE: -- init->speed_mode = I2C_SPEED_FAST; -- break; -- case FAST_PLUS_RATE: -- init->speed_mode = I2C_SPEED_FAST_PLUS; -- break; -- default: -- init->speed_mode = STM32_I2C_SPEED_DEFAULT; -- break; -- } -+ uint32_t read_val; -+ -+ init->rise_time = fdt_read_uint32_default(node, -+ "i2c-scl-rising-time-ns", -+ STM32_I2C_RISE_TIME_DEFAULT); -+ -+ init->fall_time = fdt_read_uint32_default(node, -+ "i2c-scl-falling-time-ns", -+ STM32_I2C_FALL_TIME_DEFAULT); -+ -+ read_val = fdt_read_uint32_default(node, "clock-frequency", -+ STANDARD_RATE); -+ if (read_val > FAST_PLUS_RATE) { -+ ERROR("Invalid bus speed (%i > %i)\n", read_val, -+ FAST_PLUS_RATE); -+ return -FDT_ERR_BADVALUE; - } -+ init->bus_rate = read_val; - - return dt_set_pinctrl_config(node); - } -diff --git a/drivers/st/io/io_programmer_st_usb.c b/drivers/st/io/io_programmer_st_usb.c -index a0871f6..878cfa3 100644 ---- a/drivers/st/io/io_programmer_st_usb.c -+++ b/drivers/st/io/io_programmer_st_usb.c -@@ -1,13 +1,12 @@ - /* -- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - #include - #include --#include - #include - #include - #include -@@ -16,10 +15,7 @@ - #include - #include - #include --#include --#include - #include --#include - #include - - static uint8_t first_usb_buffer[USB_DFU_MAX_XFER_SIZE + 1] __aligned(4); -diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c -index fde6269..8d53a0d 100644 ---- a/drivers/st/io/io_stm32image.c -+++ b/drivers/st/io/io_stm32image.c -@@ -1,11 +1,10 @@ - /* -- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - #include --#include - #include - #include - #include -@@ -13,7 +12,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c -index 1b5bfe3..ef23bfc 100644 ---- a/drivers/st/iwdg/stm32_iwdg.c -+++ b/drivers/st/iwdg/stm32_iwdg.c -@@ -1,6 +1,6 @@ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -17,8 +17,6 @@ - #include - #include - #include --#include --#include - #include - #include - -diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c -index aab0582..df9ba63 100644 ---- a/drivers/st/mmc/stm32_sdmmc2.c -+++ b/drivers/st/mmc/stm32_sdmmc2.c -@@ -17,8 +17,6 @@ - #include - #include - #include --#include --#include - #include - #include - #include -@@ -49,6 +47,7 @@ - - /* SDMMC power control register */ - #define SDMMC_POWER_PWRCTRL GENMASK(1, 0) -+#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1) - #define SDMMC_POWER_DIRPOL BIT(4) - - /* SDMMC clock control register */ -@@ -115,6 +114,13 @@ - #define TIMEOUT_10_MS ms2tick(10) - #define TIMEOUT_1_S s2tick(1) - -+/* Power cycle delays in ms */ -+#define VCC_POWER_OFF_DELAY 2 -+#define VCC_POWER_ON_DELAY 2 -+#define POWER_CYCLE_DELAY 2 -+#define POWER_OFF_DELAY 2 -+#define POWER_ON_DELAY 1 -+ - #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" - - static void stm32_sdmmc2_init(void); -@@ -136,6 +142,8 @@ static const struct mmc_ops stm32_sdmmc2_ops = { - - static struct stm32_sdmmc2_params sdmmc2_params; - -+static bool next_cmd_is_acmd; -+ - #pragma weak plat_sdmmc2_use_dma - bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory) - { -@@ -173,6 +181,26 @@ static void stm32_sdmmc2_init(void) - freq = MIN(sdmmc2_params.max_freq, STM32MP_MMC_INIT_FREQ); - } - -+ if (sdmmc2_params.vmmc_regu.id != -1) { -+ stm32mp_regulator_register(&sdmmc2_params.vmmc_regu); -+ stm32mp_regulator_disable(&sdmmc2_params.vmmc_regu); -+ } -+ -+ mdelay(VCC_POWER_OFF_DELAY); -+ -+ mmio_write_32(base + SDMMC_POWER, -+ SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol); -+ mdelay(POWER_CYCLE_DELAY); -+ -+ if (sdmmc2_params.vmmc_regu.id != -1) { -+ stm32mp_regulator_enable(&sdmmc2_params.vmmc_regu); -+ } -+ -+ mdelay(VCC_POWER_ON_DELAY); -+ -+ mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol); -+ mdelay(POWER_OFF_DELAY); -+ - clock_div = div_round_up(sdmmc2_params.clk_rate, - freq * 2); - -@@ -183,7 +211,7 @@ static void stm32_sdmmc2_init(void) - mmio_write_32(base + SDMMC_POWER, - SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); - -- mdelay(1); -+ mdelay(POWER_ON_DELAY); - } - - static int stm32_sdmmc2_stop_transfer(void) -@@ -241,6 +269,20 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) - case MMC_CMD(1): - arg_reg |= OCR_POWERUP; - break; -+ case MMC_CMD(6): -+ if ((sdmmc2_params.device_info->mmc_dev_type == MMC_IS_SD_HC) && -+ (!next_cmd_is_acmd)) { -+ cmd_reg |= SDMMC_CMDR_CMDTRANS; -+ if (sdmmc2_params.use_dma) { -+ flags_data |= SDMMC_STAR_DCRCFAIL | -+ SDMMC_STAR_DTIMEOUT | -+ SDMMC_STAR_DATAEND | -+ SDMMC_STAR_RXOVERR | -+ SDMMC_STAR_IDMATE | -+ SDMMC_STAR_DBCKEND; -+ } -+ } -+ break; - case MMC_CMD(8): - if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { - cmd_reg |= SDMMC_CMDR_CMDTRANS; -@@ -278,6 +320,8 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) - break; - } - -+ next_cmd_is_acmd = (cmd->cmd_idx == MMC_CMD(55)); -+ - if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) { - mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); - } -@@ -636,6 +680,7 @@ static int stm32_sdmmc2_dt_get_config(void) - int sdmmc_node; - void *fdt = NULL; - const fdt32_t *cuint; -+ struct dt_node_info dt_info; - - if (fdt_get_address(&fdt) == 0) { - return -FDT_ERR_NOTFOUND; -@@ -645,27 +690,14 @@ static int stm32_sdmmc2_dt_get_config(void) - return -FDT_ERR_NOTFOUND; - } - -- sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT); -- -- while (sdmmc_node != -FDT_ERR_NOTFOUND) { -- cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL); -- if (cuint == NULL) { -- continue; -- } -- -- if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) { -- break; -- } -- -- sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node, -- DT_SDMMC2_COMPAT); -- } -- -+ sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, -+ sdmmc2_params.reg_base); - if (sdmmc_node == -FDT_ERR_NOTFOUND) { - return -FDT_ERR_NOTFOUND; - } - -- if (fdt_get_status(sdmmc_node) == DT_DISABLED) { -+ dt_fill_device_info(&dt_info, sdmmc_node); -+ if (dt_info.status == DT_DISABLED) { - return -FDT_ERR_NOTFOUND; - } - -@@ -673,21 +705,8 @@ static int stm32_sdmmc2_dt_get_config(void) - return -FDT_ERR_BADVALUE; - } - -- cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- cuint++; -- sdmmc2_params.clock_id = fdt32_to_cpu(*cuint); -- -- cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- cuint++; -- sdmmc2_params.reset_id = fdt32_to_cpu(*cuint); -+ sdmmc2_params.clock_id = dt_info.clock; -+ sdmmc2_params.reset_id = dt_info.reset; - - if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { - sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; -@@ -722,6 +741,11 @@ static int stm32_sdmmc2_dt_get_config(void) - sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); - } - -+ cuint = fdt_getprop(fdt, sdmmc_node, "vmmc-supply", NULL); -+ if (cuint != NULL) { -+ sdmmc2_params.vmmc_regu.id = fdt32_to_cpu(*cuint); -+ } -+ - return 0; - } - -@@ -740,6 +764,8 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) - - memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); - -+ sdmmc2_params.vmmc_regu.id = -1; -+ - if (stm32_sdmmc2_dt_get_config() != 0) { - ERROR("%s: DT error\n", __func__); - return -ENOMEM; -diff --git a/drivers/st/nand/nand.c b/drivers/st/nand/nand.c -index 9198800..2bd076a 100644 ---- a/drivers/st/nand/nand.c -+++ b/drivers/st/nand/nand.c -@@ -23,7 +23,6 @@ - #include - #include - #include --#include - #include - - /* Other internal NAND driver definitions */ -@@ -190,10 +189,10 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand) - * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) - */ - 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); -+ thold_att = MAX(thold_att, FMC_TCH_MIN); -+ thold_att = MAX(thold_att, FMC_TCLH_MIN); -+ thold_att = MAX(thold_att, FMC_TCOH_MIN); -+ thold_att = MAX(thold_att, 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; -@@ -749,7 +748,7 @@ static Std_ReturnType Nand_ReadParameterPage(NAND_HandleTypeDef *hNand) - static Std_ReturnType Nand_DetectAndInit(NAND_HandleTypeDef *hNand) - { - NAND_IDTypeDef pNAND_ID; -- uint32_t nand_param_in_otp, result; -+ uint32_t nand_param_in_otp; - - assert(hNand); - -@@ -759,9 +758,7 @@ static Std_ReturnType Nand_DetectAndInit(NAND_HandleTypeDef *hNand) - Nand_ReadIDCode(hNand, &pNAND_ID); - - /* Check if NAND parameters are stored in OTP */ -- result = bsec_shadow_read_otp(&nand_param_in_otp, NAND_OTP); -- if (result != BSEC_OK) { -- ERROR("BSEC: NAND_OTP Error %i\n", result); -+ if (stm32_get_otp_value(NAND_OTP, &nand_param_in_otp) != 0) { - return STD_NOT_OK; - } - -diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c -index c8d70db..5abd8e6 100644 ---- a/drivers/st/pmic/stm32mp_pmic.c -+++ b/drivers/st/pmic/stm32mp_pmic.c -@@ -1,16 +1,16 @@ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -+#include - #include - #include - #include - #include - #include - #include --#include - #include - #include - #include -@@ -19,7 +19,6 @@ - #define STPMIC1_LDO12356_OUTPUT_SHIFT 2 - #define STPMIC1_LDO3_MODE (uint8_t)(BIT(7)) - #define STPMIC1_LDO3_DDR_SEL 31U --#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT) - - #define STPMIC1_BUCK_OUTPUT_SHIFT 2 - #define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT) -@@ -28,29 +27,43 @@ - - #define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 - -+#define CMD_GET_VOLTAGE 0U -+#define CMD_CONFIG_BOOT_ON 1U -+#define CMD_CONFIG_LP 2U -+ - static struct i2c_handle_s i2c_handle; - static uint32_t pmic_i2c_addr; - --static int dt_get_pmic_node(void *fdt) -+static int dt_get_pmic_node(void) - { -- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); -+ static int node = -FDT_ERR_BADOFFSET; -+ -+ if (node == -FDT_ERR_BADOFFSET) { -+ node = dt_get_node_by_compatible("st,stpmic1"); -+ } -+ -+ return node; - } - - int dt_pmic_status(void) - { -+ static int status = -FDT_ERR_BADVALUE; - int node; -- void *fdt; - -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -+ if (status != -FDT_ERR_BADVALUE) { -+ return status; - } - -- node = dt_get_pmic_node(fdt); -+ node = dt_get_pmic_node(); - if (node <= 0) { -- return -FDT_ERR_NOTFOUND; -+ status = -FDT_ERR_NOTFOUND; -+ -+ return status; - } - -- return fdt_get_status(node); -+ status = (int)fdt_get_status(node); -+ -+ return status; - } - - static bool dt_pmic_is_secure(void) -@@ -62,120 +75,126 @@ static bool dt_pmic_is_secure(void) - (i2c_handle.dt_status == DT_SECURE); - } - --/* -- * Get PMIC and its I2C bus configuration from the device tree. -- * Return 0 on success, negative on error, 1 if no PMIC node is defined. -- */ --static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, -- struct stm32_i2c_init_s *init) -+static int dt_pmic_get_regulator_voltage(void *fdt, int node, -+ uint16_t *voltage_mv) - { -- int pmic_node, i2c_node; -- void *fdt; - const fdt32_t *cuint; - -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -- } -+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); -+ if (cuint != NULL) { -+ *voltage_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); - -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- return 1; -+ return 0; - } - -- cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -+ return -FDT_ERR_NOTFOUND; -+} - -- pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; -- if (pmic_i2c_addr > UINT16_MAX) { -- return -EINVAL; -- } -+static int pmic_config_boot_on(void *fdt, int node, const char *regu_name) -+{ -+ uint16_t voltage; -+ int status; - -- i2c_node = fdt_parent_offset(fdt, pmic_node); -- if (i2c_node < 0) { -- return -FDT_ERR_NOTFOUND; -+ if ((fdt_getprop(fdt, node, "regulator-boot-on", NULL) == NULL) && -+ (fdt_getprop(fdt, node, "regulator-always-on", NULL) == NULL)) { -+ return 0; - } - -- dt_fill_device_info(i2c_info, i2c_node); -- if (i2c_info->base == 0U) { -- return -FDT_ERR_NOTFOUND; -- } -+ if (fdt_getprop(fdt, node, "regulator-pull-down", NULL) != NULL) { - -- return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); --} -+ status = stpmic1_regulator_pull_down_set(regu_name); -+ if (status < 0) { -+ return status; -+ } -+ } - --int dt_pmic_configure_boot_on_regulators(void) --{ -- int pmic_node, regulators_node, regulator_node; -- void *fdt; -+ if (fdt_getprop(fdt, node, "st,mask-reset", NULL) != NULL) { - -- if (fdt_get_address(&fdt) == 0) { -- return -ENOENT; -+ status = stpmic1_regulator_mask_reset_set(regu_name); -+ if (status < 0) { -+ return status; -+ } - } - -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- return -FDT_ERR_NOTFOUND; -+ if (dt_pmic_get_regulator_voltage(fdt, node, &voltage) < 0) { -+ return 0; - } - -- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ status = stpmic1_regulator_voltage_set(regu_name, voltage); -+ if (status < 0) { -+ return status; -+ } - -- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -- const fdt32_t *cuint; -- const char *node_name = fdt_get_name(fdt, regulator_node, NULL); -- uint16_t voltage; -- int status; -- --#if defined(IMAGE_BL2) -- if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on", -- NULL) == NULL) && -- (fdt_getprop(fdt, regulator_node, "regulator-always-on", -- NULL) == NULL)) { --#else -- if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", -- NULL) == NULL) { --#endif -- continue; -+ if (!stpmic1_is_regulator_enabled(regu_name)) { -+ status = stpmic1_regulator_enable(regu_name); -+ if (status < 0) { -+ return status; - } -+ } - -- if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", -- NULL) != NULL) { -- int status; -+ return 0; -+} - -- status = stpmic1_regulator_pull_down_set(node_name); -- if (status != 0) { -- return status; -- } -- } -+static int pmic_config_lp(void *fdt, int node, const char *node_name, -+ const char *regu_name) -+{ -+ int status; -+ const fdt32_t *cuint; -+ int regulator_state_node; -+ -+ status = stpmic1_powerctrl_on(); -+ if (status < 0) { -+ return status; -+ }; - -- if (fdt_getprop(fdt, regulator_node, "st,mask-reset", -- NULL) != NULL) { -- int status; -+ /* -+ * First, copy active configuration (Control register) to -+ * PWRCTRL Control register, even if regulator_state_node -+ * does not exist. -+ */ -+ status = stpmic1_lp_copy_reg(regu_name); -+ if (status < 0) { -+ return status; -+ } - -- status = stpmic1_regulator_mask_reset_set(node_name); -- if (status != 0) { -- return status; -- } -+ /* Then apply configs from regulator_state_node */ -+ regulator_state_node = fdt_subnode_offset(fdt, node, node_name); -+ if (regulator_state_node <= 0) { -+ return 0; -+ } -+ -+ if (fdt_getprop(fdt, regulator_state_node, "regulator-on-in-suspend", -+ NULL) != NULL) { -+ status = stpmic1_lp_reg_on_off(regu_name, 1); -+ if (status < 0) { -+ return status; - } -+ } - -- cuint = fdt_getprop(fdt, regulator_node, -- "regulator-min-microvolt", NULL); -- if (cuint == NULL) { -- continue; -+ if (fdt_getprop(fdt, regulator_state_node, "regulator-off-in-suspend", -+ NULL) != NULL) { -+ status = stpmic1_lp_reg_on_off(regu_name, 0); -+ if (status < 0) { -+ return status; - } -+ } - -- /* DT uses microvolts, whereas driver awaits millivolts */ -- voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -+ cuint = fdt_getprop(fdt, regulator_state_node, -+ "regulator-suspend-microvolt", NULL); -+ if (cuint != NULL) { -+ uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); - -- status = stpmic1_regulator_voltage_set(node_name, voltage); -- if (status != 0) { -+ status = stpmic1_lp_set_voltage(regu_name, voltage); -+ if (status < 0) { - return status; - } -+ } - -- if (stpmic1_is_regulator_enabled(node_name) == 0U) { -- status = stpmic1_regulator_enable(node_name); -- if (status != 0) { -+ cuint = fdt_getprop(fdt, regulator_state_node, "regulator-mode", NULL); -+ if (cuint != NULL) { -+ if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) { -+ status = stpmic1_lp_set_mode(regu_name, 1); -+ if (status < 0) { - return status; - } - } -@@ -184,97 +203,124 @@ int dt_pmic_configure_boot_on_regulators(void) - return 0; - } - --int dt_pmic_set_lp_config(const char *node_name) -+static int pmic_operate(uint8_t command, const char *node_name, -+ uint16_t *voltage_mv) - { -- int pmic_node, regulators_node, regulator_node; -- int status; -+ int pmic_node, regulators_node, subnode; - void *fdt; -- -- if (node_name == NULL) { -- return 0; -- } -+ int ret = -EIO; -+ const char *regu_name; - - if (fdt_get_address(&fdt) == 0) { - return -ENOENT; - } - -- pmic_node = dt_get_pmic_node(fdt); -+ pmic_node = dt_get_pmic_node(); - if (pmic_node < 0) { -- return -FDT_ERR_NOTFOUND; -+ return -ENOENT; - } - -- status = stpmic1_powerctrl_on(); -- if (status != 0) { -- return status; -- }; -- - regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); - -- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -- const fdt32_t *cuint; -- const char *reg_name; -- int regulator_state_node; -+ fdt_for_each_subnode(subnode, fdt, regulators_node) { -+ regu_name = fdt_get_name(fdt, subnode, NULL); - -- /* -- * First, copy active configuration (Control register) to -- * PWRCTRL Control register, even if regulator_state_node -- * does not exist. -- */ -- reg_name = fdt_get_name(fdt, regulator_node, NULL); -- status = stpmic1_lp_copy_reg(reg_name); -- if (status != 0) { -- return status; -- } -+ switch (command) { -+ case CMD_GET_VOLTAGE: -+ assert(node_name != NULL); -+ assert(voltage_mv != NULL); - -- /* Then apply configs from regulator_state_node */ -- regulator_state_node = fdt_subnode_offset(fdt, -- regulator_node, -- node_name); -- if (regulator_state_node <= 0) { -- continue; -- } -+ if (strcmp(regu_name, node_name) != 0) { -+ continue; -+ } - -- if (fdt_getprop(fdt, regulator_state_node, -- "regulator-on-in-suspend", NULL) != NULL) { -- status = stpmic1_lp_reg_on_off(reg_name, 1); -- if (status != 0) { -- return status; -+ ret = dt_pmic_get_regulator_voltage(fdt, subnode, -+ voltage_mv); -+ if (ret < 0) { -+ return -ENXIO; - } -- } - -- if (fdt_getprop(fdt, regulator_state_node, -- "regulator-off-in-suspend", NULL) != NULL) { -- status = stpmic1_lp_reg_on_off(reg_name, 0); -- if (status != 0) { -- return status; -+ return ret; -+ -+ case CMD_CONFIG_BOOT_ON: -+ ret = pmic_config_boot_on(fdt, subnode, regu_name); -+ if (ret < 0) { -+ return ret; - } -- } -+ break; - -- cuint = fdt_getprop(fdt, regulator_state_node, -- "regulator-suspend-microvolt", NULL); -- if (cuint != NULL) { -- uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) / -- 1000U); -+ case CMD_CONFIG_LP: -+ assert(node_name != NULL); - -- status = stpmic1_lp_set_voltage(reg_name, voltage); -- if (status != 0) { -- return status; -+ ret = pmic_config_lp(fdt, subnode, node_name, -+ regu_name); -+ if (ret < 0) { -+ return ret; - } -+ break; -+ -+ default: -+ return -EINVAL; - } -+ } - -- cuint = fdt_getprop(fdt, regulator_state_node, -- "regulator-mode", NULL); -- if (cuint != NULL) { -- if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) { -- status = stpmic1_lp_set_mode(reg_name, 1); -- if (status != 0) { -- return status; -- } -- } -+ return ret; -+} -+ -+/* -+ * Get PMIC and its I2C bus configuration from the device tree. -+ * Return 0 on success, negative on error, 1 if no PMIC node is defined. -+ */ -+static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, -+ struct stm32_i2c_init_s *init) -+{ -+ static int i2c_node = -FDT_ERR_NOTFOUND; -+ int pmic_node; -+ void *fdt; -+ const fdt32_t *cuint; -+ -+ if (i2c_node == -FDT_ERR_NOTFOUND) { -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ pmic_node = dt_get_pmic_node(); -+ if (pmic_node < 0) { -+ return 1; -+ } -+ -+ cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; -+ if (pmic_i2c_addr > UINT16_MAX) { -+ return -FDT_ERR_BADVALUE; -+ } -+ -+ i2c_node = fdt_parent_offset(fdt, pmic_node); -+ if (i2c_node < 0) { -+ return -FDT_ERR_NOTFOUND; - } - } - -- return 0; -+ dt_fill_device_info(i2c_info, i2c_node); -+ if (i2c_info->base == 0U) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return stm32_i2c_get_setup_from_fdt(i2c_node, init); -+} -+ -+int pmic_configure_boot_on_regulators(void) -+{ -+ return pmic_operate(CMD_CONFIG_BOOT_ON, NULL, NULL); -+} -+ -+int pmic_set_lp_config(const char *node_name) -+{ -+ return pmic_operate(CMD_CONFIG_LP, node_name, NULL); - } - - /* -@@ -371,43 +417,111 @@ static void register_secure_pmic(void) - stm32mp_register_secure_periph_iomem(i2c_handle.i2c_base_addr); - } - --void initialize_pmic(void) -+static int pmic_regulator_enable(struct stm32mp_regulator *regu) - { -- unsigned long pmic_version; -+ void *fdt; -+ const char *node_name; - -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ node_name = fdt_get_name(fdt, fdt_node_offset_by_phandle(fdt, regu->id), -+ NULL); -+ -+ return stpmic1_regulator_enable(node_name); -+} -+ -+static int pmic_regulator_disable(struct stm32mp_regulator *regu) -+{ -+ void *fdt; -+ const char *node_name; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ node_name = fdt_get_name(fdt, fdt_node_offset_by_phandle(fdt, regu->id), -+ NULL); -+ -+ return stpmic1_regulator_disable(node_name); -+} -+ -+static const struct stm32mp_regulator_ops pmic_regu_ops = { -+ .enable = pmic_regulator_enable, -+ .disable = pmic_regulator_disable, -+}; -+ -+bool is_pmic_regulator(struct stm32mp_regulator *regu) -+{ -+ void *fdt; -+ int parent_node; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return false; -+ } -+ -+ parent_node = fdt_parent_offset(fdt, -+ fdt_node_offset_by_phandle(fdt, -+ regu->id)); -+ return (fdt_node_check_compatible(fdt, parent_node, -+ "st,stpmic1-regulators") == 0); -+} -+ -+void bind_pmic_regulator(struct stm32mp_regulator *regu) -+{ -+ regu->ops = &pmic_regu_ops; -+} -+ -+void initialize_pmic(void) -+{ - if (!initialize_pmic_i2c()) { - VERBOSE("No PMIC\n"); - register_non_secure_pmic(); - return; - } - -- if (stpmic1_get_version(&pmic_version) != 0) { -- ERROR("Failed to access PMIC\n"); -- panic(); -- } -- -- INFO("PMIC version = 0x%02lx\n", pmic_version); -- stpmic1_dump_regulators(); -- - if (dt_pmic_is_secure()) { - register_secure_pmic(); - } else { - VERBOSE("PMIC is not secure-only hence assumed non secure\n"); - register_non_secure_pmic(); - } -+} - --#if defined(IMAGE_BL2) -- if (dt_pmic_configure_boot_on_regulators() != 0) { -+void configure_pmic(void) -+{ -+ if (pmic_configure_boot_on_regulators() < 0) { - panic(); - }; --#endif - } - -+#if DEBUG -+void print_pmic_info_and_debug(void) -+{ -+ unsigned long pmic_version; -+ -+ if (stpmic1_get_version(&pmic_version) != 0) { -+ ERROR("Failed to access PMIC\n"); -+ panic(); -+ } -+ -+ INFO("PMIC version = 0x%02lx\n", pmic_version); -+ stpmic1_dump_regulators(); -+} -+#endif -+ - int pmic_ddr_power_init(enum ddr_type ddr_type) - { - bool buck3_at_1v8 = false; - uint8_t read_val; - int status; -+ uint16_t buck2_mv; -+ uint16_t ldo3_mv; -+ -+ if (pmic_operate(CMD_GET_VOLTAGE, "buck2", &buck2_mv) != 0) { -+ return -EPERM; -+ } - - switch (ddr_type) { - case STM32MP_DDR3: -@@ -427,7 +541,7 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) - return status; - } - -- status = stpmic1_regulator_voltage_set("buck2", 1350); -+ status = stpmic1_regulator_voltage_set("buck2", buck2_mv); - if (status != 0) { - return status; - } -@@ -477,7 +591,6 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) - - read_val &= ~STPMIC1_LDO3_MODE; - read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; -- read_val |= STPMIC1_LDO3_1800000; - if (buck3_at_1v8) { - read_val |= STPMIC1_LDO3_MODE; - } -@@ -487,7 +600,16 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) - return status; - } - -- status = stpmic1_regulator_voltage_set("buck2", 1200); -+ if (pmic_operate(CMD_GET_VOLTAGE, "ldo3", &ldo3_mv) != 0) { -+ return -EPERM; -+ } -+ -+ status = stpmic1_regulator_voltage_set("ldo3", ldo3_mv); -+ if (status != 0) { -+ return status; -+ } -+ -+ status = stpmic1_regulator_voltage_set("buck2", buck2_mv); - if (status != 0) { - return status; - } -diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c -index 2bd2b60..463ef60 100644 ---- a/drivers/st/pmic/stpmic1.c -+++ b/drivers/st/pmic/stpmic1.c -@@ -581,17 +581,19 @@ int stpmic1_regulator_enable(const char *name) - { - const struct regul_struct *regul = get_regulator_data(name); - -- return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0)); -+ return stpmic1_register_update(regul->control_reg, LDO_BUCK_ENABLE_MASK, -+ LDO_BUCK_ENABLE_MASK); - } - - int stpmic1_regulator_disable(const char *name) - { - const struct regul_struct *regul = get_regulator_data(name); - -- return stpmic1_register_update(regul->control_reg, 0, BIT(0)); -+ return stpmic1_register_update(regul->control_reg, 0, -+ LDO_BUCK_ENABLE_MASK); - } - --uint8_t stpmic1_is_regulator_enabled(const char *name) -+bool stpmic1_is_regulator_enabled(const char *name) - { - uint8_t val; - const struct regul_struct *regul = get_regulator_data(name); -@@ -600,7 +602,7 @@ uint8_t stpmic1_is_regulator_enabled(const char *name) - panic(); - } - -- return (val & 0x1U); -+ return (val & LDO_BUCK_ENABLE_MASK) == LDO_BUCK_ENABLE_MASK; - } - - int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) -@@ -716,13 +718,15 @@ int stpmic1_regulator_voltage_get(const char *name) - return 0; - } - -- if (stpmic1_register_read(regul->control_reg, &value)) -+ if (stpmic1_register_read(regul->control_reg, &value)) { - return -1; -+ } - - value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; - -- if (value > regul->voltage_table_size) -+ if (value > regul->voltage_table_size) { - return -1; -+ } - - return (int)regul->voltage_table[value]; - } -@@ -803,11 +807,9 @@ void stpmic1_dump_regulators(void) - - int stpmic1_get_version(unsigned long *version) - { -- int rc; - uint8_t read_val; - -- rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val); -- if (rc) { -+ if (stpmic1_register_read(VERSION_STATUS_REG, &read_val) != 0) { - return -1; - } - -diff --git a/drivers/st/qspi/io_qspi.c b/drivers/st/qspi/io_qspi.c -index b00b7d6..00a778c 100644 ---- a/drivers/st/qspi/io_qspi.c -+++ b/drivers/st/qspi/io_qspi.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,8 +13,6 @@ - #include - #include - #include --#include --#include - #include - - #define QSPI_COMPAT "st,stm32f469-qspi" -diff --git a/drivers/st/regulator/stm32mp_dummy_regulator.c b/drivers/st/regulator/stm32mp_dummy_regulator.c -new file mode 100644 -index 0000000..23d6892 ---- /dev/null -+++ b/drivers/st/regulator/stm32mp_dummy_regulator.c -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+static int dummy_regulator_enable(struct stm32mp_regulator *regu) -+{ -+ return 0; -+} -+ -+static int dummy_regulator_disable(struct stm32mp_regulator *regu) -+{ -+ return 0; -+} -+ -+static const struct stm32mp_regulator_ops dummy_regu_ops = { -+ .enable = dummy_regulator_enable, -+ .disable = dummy_regulator_disable, -+}; -+ -+void bind_dummy_regulator(struct stm32mp_regulator *regu) -+{ -+ regu->ops = &dummy_regu_ops; -+} -diff --git a/drivers/st/regulator/stm32mp_regulator.c b/drivers/st/regulator/stm32mp_regulator.c -new file mode 100644 -index 0000000..f0e4a4a ---- /dev/null -+++ b/drivers/st/regulator/stm32mp_regulator.c -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+ -+#pragma weak plat_bind_regulator -+int plat_bind_regulator(struct stm32mp_regulator *regu) -+{ -+ return -1; -+} -+ -+int stm32mp_regulator_enable(struct stm32mp_regulator *regu) -+{ -+ assert((regu->ops != NULL) && (regu->ops->enable != NULL)); -+ -+ return regu->ops->enable(regu); -+} -+ -+int stm32mp_regulator_disable(struct stm32mp_regulator *regu) -+{ -+ assert((regu->ops != NULL) && (regu->ops->disable != NULL)); -+ -+ if (regu->always_on) { -+ return 0; -+ } -+ -+ return regu->ops->disable(regu); -+} -+ -+int stm32mp_regulator_register(struct stm32mp_regulator *regu) -+{ -+ return plat_bind_regulator(regu); -+} -diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c -index 2e19ef0..45fb988 100644 ---- a/drivers/st/reset/stm32mp1_reset.c -+++ b/drivers/st/reset/stm32mp1_reset.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - -diff --git a/drivers/st/rng/stm32_rng.c b/drivers/st/rng/stm32_rng.c -index eec75b2..94d74b0 100644 ---- a/drivers/st/rng/stm32_rng.c -+++ b/drivers/st/rng/stm32_rng.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,7 +13,6 @@ - #include - #include - #include --#include - #include - - #define DT_RNG_COMPAT "st,stm32-rng" -diff --git a/drivers/st/rtc/stm32_rtc.c b/drivers/st/rtc/stm32_rtc.c -index 017c46d..3f469d7 100644 ---- a/drivers/st/rtc/stm32_rtc.c -+++ b/drivers/st/rtc/stm32_rtc.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -12,7 +12,6 @@ - #include - #include - #include --#include - - #define RTC_COMPAT "st,stm32mp1-rtc" - -@@ -251,20 +250,11 @@ static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal) - * This function computes the fraction difference between two timestamps. - * Here again the returned value is in milliseconds. - ******************************************************************************/ --static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -- struct stm32_rtc_calendar *ref) -+static signed long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -+ struct stm32_rtc_calendar *ref) - { -- unsigned long long val_r; -- unsigned long long val_c; -- -- val_r = stm32_rtc_get_second_fraction(ref); -- val_c = stm32_rtc_get_second_fraction(cur); -- -- if (val_c >= val_r) { -- return val_c - val_r; -- } else { -- return 1000U - val_r + val_c; -- } -+ return (signed long long)stm32_rtc_get_second_fraction(cur) - -+ (signed long long)stm32_rtc_get_second_fraction(ref); - } - - /******************************************************************************* -@@ -272,10 +262,9 @@ static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, - * It includes seconds, minutes and hours. - * Here again the returned value is in milliseconds. - ******************************************************************************/ --static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -- struct stm32_rtc_time *ref) -+static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) - { -- signed long long diff_in_s; - signed long long curr_s; - signed long long ref_s; - -@@ -287,12 +276,7 @@ static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current, - (((signed long long)ref->min + - (((signed long long)ref->hour * 60))) * 60); - -- diff_in_s = curr_s - ref_s; -- if (diff_in_s < 0) { -- diff_in_s += 24 * 60 * 60; -- } -- -- return (unsigned long long)diff_in_s * 1000U; -+ return (curr_s - ref_s) * 1000; - } - - /******************************************************************************* -@@ -310,8 +294,8 @@ static bool stm32_is_a_leap_year(uint32_t year) - * It includes days, months, years, with exceptions. - * Here again the returned value is in milliseconds. - ******************************************************************************/ --static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, -- struct stm32_rtc_time *ref) -+static signed long long stm32_rtc_diff_date(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) - { - uint32_t diff_in_days = 0; - uint32_t m; -@@ -385,7 +369,7 @@ static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, - } - } - -- return (24ULL * 60U * 60U * 1000U) * (unsigned long long)diff_in_days; -+ return (24 * 60 * 60 * 1000) * (signed long long)diff_in_days; - } - - /******************************************************************************* -@@ -395,7 +379,7 @@ static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, - unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, - struct stm32_rtc_calendar *ref) - { -- unsigned long long diff_in_ms = 0; -+ signed long long diff_in_ms = 0; - struct stm32_rtc_time curr_t; - struct stm32_rtc_time ref_t; - -@@ -412,7 +396,7 @@ unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, - - stm32mp_clk_disable(rtc_dev.clock); - -- return diff_in_ms; -+ return (unsigned long long)diff_in_ms; - } - - /******************************************************************************* -diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c -index 0bfa177..b09f122 100644 ---- a/drivers/st/tamper/stm32_tamp.c -+++ b/drivers/st/tamper/stm32_tamp.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -12,8 +12,6 @@ - #include - #include - #include --#include --#include - - #define DT_TAMP_COMPAT "st,stm32-tamp" - /* STM32 Registers */ -diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c -index 4c58000..f33821e 100644 ---- a/drivers/st/timer/stm32_timer.c -+++ b/drivers/st/timer/stm32_timer.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -12,7 +12,6 @@ - #include - #include - #include --#include - - #define TIM_CR1 0x00U /* Control Register 1 */ - #define TIM_CR2 0x04U /* Control Register 2 */ -diff --git a/drivers/st/uart/io_programmer_uart.c b/drivers/st/uart/io_programmer_uart.c -index 34a7cbb..f56a552 100644 ---- a/drivers/st/uart/io_programmer_uart.c -+++ b/drivers/st/uart/io_programmer_uart.c -@@ -1,12 +1,11 @@ - /* -- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - #include - #include --#include - #include - #include - #include -@@ -16,8 +15,6 @@ - #include - #include - #include --#include --#include - #include - - /* USART bootloader protocol version V4.0*/ -diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi -index 1a5c51c..4825691 100644 ---- a/fdts/stm32mp15-ddr.dtsi -+++ b/fdts/stm32mp15-ddr.dtsi -@@ -5,7 +5,7 @@ - - / { - soc { -- ddr: ddr@5A003000{ -+ ddr: ddr@5a003000{ - - compatible = "st,stm32mp1-ddr"; - -diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts -index f081575..d852171 100644 ---- a/fdts/stm32mp157a-dk1.dts -+++ b/fdts/stm32mp157a-dk1.dts -@@ -34,6 +34,7 @@ - pinctrl-0 = <&i2c4_pins_a>; - i2c-scl-rising-time-ns = <185>; - i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; - status = "okay"; - - pmic: stpmic@33 { -@@ -43,10 +44,7 @@ - interrupt-controller; - #interrupt-cells = <2>; - status = "okay"; -- -- st,main-control-register = <0x04>; -- st,vin-control-register = <0xc0>; -- st,usb-control-register = <0x20>; -+ wakeup-source; - - regulators { - compatible = "st,stpmic1-regulators"; -@@ -283,12 +281,6 @@ - CLK_LPTIM45_LSE - >; - -- /* VCO = 1300.0 MHz => P = 650 (CPU) */ -- pll1: st,pll@0 { -- cfg = < 2 80 0 0 0 PQR(1,0,0) >; -- frac = < 0x800 >; -- }; -- - /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ - pll2: st,pll@1 { - cfg = < 2 65 1 0 0 PQR(1,1,1) >; -@@ -311,8 +303,7 @@ - &bsec { - board_id: board_id@ec { - reg = <0xec 0x4>; -- status = "okay"; -- secure-status = "okay"; -+ st,non-secure-otp; - }; - }; - -@@ -332,6 +323,24 @@ - secure-status = "okay"; - }; - -+&nvmem_layout { -+ nvmem-cells = <&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>, -+ <&board_id>; -+ -+ nvmem-cell-names = "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp", -+ "board_id"; -+}; -+ - &pwr { - system_suspend_supported_soc_modes = < - STM32_PM_CSLEEP_RUN -diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts -index 61d5301..02c4233 100644 ---- a/fdts/stm32mp157c-ed1.dts -+++ b/fdts/stm32mp157c-ed1.dts -@@ -30,6 +30,7 @@ - pinctrl-0 = <&i2c4_pins_a>; - i2c-scl-rising-time-ns = <185>; - i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; - status = "okay"; - - pmic: stpmic@33 { -@@ -39,10 +40,7 @@ - interrupt-controller; - #interrupt-cells = <2>; - status = "okay"; -- -- st,main-control-register = <0x04>; -- st,vin-control-register = <0xc0>; -- st,usb-control-register = <0x20>; -+ wakeup-source; - - regulators { - compatible = "st,stpmic1-regulators"; -@@ -288,12 +286,6 @@ - CLK_LPTIM45_LSE - >; - -- /* VCO = 1300.0 MHz => P = 650 (CPU) */ -- pll1: st,pll@0 { -- cfg = < 2 80 0 0 0 PQR(1,0,0) >; -- frac = < 0x800 >; -- }; -- - /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ - pll2: st,pll@1 { - cfg = < 2 65 1 0 0 PQR(1,1,1) >; -@@ -316,8 +308,7 @@ - &bsec { - board_id: board_id@ec { - reg = <0xec 0x4>; -- status = "okay"; -- secure-status = "okay"; -+ st,non-secure-otp; - }; - }; - -@@ -337,6 +328,24 @@ - secure-status = "okay"; - }; - -+&nvmem_layout { -+ nvmem-cells =<&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>, -+ <&board_id>; -+ -+ nvmem-cell-names = "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp", -+ "board_id"; -+}; -+ - &pwr { - system_suspend_supported_soc_modes = < - STM32_PM_CSLEEP_RUN -diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi -index 124ed53..b18c6c3 100644 ---- a/fdts/stm32mp157c-security.dtsi -+++ b/fdts/stm32mp157c-security.dtsi -@@ -1,5 +1,5 @@ - /* -- * Copyright : STMicroelectronics 2017 -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause - */ -@@ -8,7 +8,7 @@ - - / { - soc { -- iwdg1: watchdog@5C003000 { -+ iwdg1: watchdog@5c003000 { - compatible = "st,stm32mp1-iwdg"; - reg = <0x5C003000 0x400>; - clocks = <&rcc IWDG1>, <&rcc CK_LSI>; -@@ -18,7 +18,7 @@ - secure-status = "disabled"; - }; - -- etzpc: etzpc@5C007000 { -+ etzpc: etzpc@5c007000 { - compatible = "st,stm32-etzpc"; - reg = <0x5C007000 0x400>; - clocks = <&rcc TZPC>; -@@ -26,20 +26,53 @@ - secure-status = "okay"; - }; - -- stgen: stgen@5C008000 { -+ stgen: stgen@5c008000 { - compatible = "st,stm32-stgen"; - reg = <0x5C008000 0x1000>; - }; -+ -+ nvmem_layout: nvmem_layout@0 { -+ compatible = "st,stm32-nvmem-layout"; -+ -+ nvmem-cells = <&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>; -+ -+ nvmem-cell-names = "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp"; -+ }; - }; - }; - - &bsec { -- mac_addr: mac_addr@e4 { -- reg = <0xe4 0x6>; -+ part_number_otp: part_number_otp@4 { -+ reg = <0x4 0x1>; -+ }; -+ monotonic_otp: monotonic_otp@10 { -+ reg = <0x10 0x4>; - }; -- /* Spare field to align on 32-bit OTP granularity */ -- spare_ns_ea: spare_ns_ea@ea { -- reg = <0xea 0x2>; -+ nand_otp: nand_otp@24 { -+ reg = <0x24 0x4>; -+ }; -+ uid_otp: uid_otp@34 { -+ reg = <0x34 0xc>; -+ }; -+ package_otp: package_otp@40 { -+ reg = <0x40 0x4>; -+ }; -+ hw2_otp: hw2_otp@48 { -+ reg = <0x48 0x4>; -+ }; -+ mac_addr: mac_addr@e4 { -+ reg = <0xe4 0x8>; -+ st,non-secure-otp; - }; - }; - -diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi -index e649c3a..13125b1 100644 ---- a/fdts/stm32mp157c.dtsi -+++ b/fdts/stm32mp157c.dtsi -@@ -388,5 +388,22 @@ - compatible = "simple-bus", "syscon", "simple-mfd"; - reg = <0x5c00a000 0x400>; - }; -+ -+ cpu_opp_table: cpu0-opp-table { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-650000000 { -+ opp-hz = /bits/ 64 <650000000>; -+ opp-microvolt = <1200000>; -+ opp-supported-hw = <0x1>; -+ }; -+ -+ opp-800000000 { -+ opp-hz = /bits/ 64 <800000000>; -+ opp-microvolt = <1350000>; -+ opp-supported-hw = <0x2>; -+ }; -+ }; - }; - }; -diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h -index 38553b9..30580ea 100644 ---- a/include/drivers/mmc.h -+++ b/include/drivers/mmc.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -103,6 +103,7 @@ - #define MMC_STATE_SLP 10 - - #define MMC_FLAG_CMD23 (U(1) << 0) -+#define MMC_FLAG_SD_CMD6 (U(1) << 1) - - #define CMD8_CHECK_PATTERN U(0xAA) - #define VHS_2_7_3_6_V BIT(8) -@@ -110,6 +111,9 @@ - #define SD_SCR_BUS_WIDTH_1 BIT(8) - #define SD_SCR_BUS_WIDTH_4 BIT(10) - -+#define SD_SWITCH_FUNC_CHECK 0U -+#define SD_SWITCH_FUNC_SWITCH 1U -+ - struct mmc_cmd { - unsigned int cmd_idx; - unsigned int cmd_arg; -@@ -209,6 +213,27 @@ struct mmc_csd_sd_v2 { - unsigned int csd_structure: 2; - }; - -+struct sd_switch_status { -+ unsigned short max_current; -+ unsigned short support_g6; -+ unsigned short support_g5; -+ unsigned short support_g4; -+ unsigned short support_g3; -+ unsigned short support_g2; -+ unsigned short support_g1; -+ unsigned char sel_g6_g5; -+ unsigned char sel_g4_g3; -+ unsigned char sel_g2_g1; -+ unsigned char data_struct_ver; -+ unsigned short busy_g6; -+ unsigned short busy_g5; -+ unsigned short busy_g4; -+ unsigned short busy_g3; -+ unsigned short busy_g2; -+ unsigned short busy_g1; -+ unsigned short reserved[17]; -+}; -+ - enum mmc_device_type { - MMC_IS_EMMC, - MMC_IS_SD, -diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h -index 71a68c2..25f29de 100644 ---- a/include/drivers/st/bsec.h -+++ b/include/drivers/st/bsec.h -@@ -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 - */ -@@ -172,6 +172,9 @@ uint32_t bsec_get_base(void); - uint32_t bsec_set_config(struct bsec_config *cfg); - uint32_t bsec_get_config(struct bsec_config *cfg); - -+uint32_t bsec_find_otp_name_in_dt(const char *name, uint32_t *otp, -+ uint32_t *otp_len); -+ - uint32_t bsec_shadow_register(uint32_t otp); - uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); - uint32_t bsec_write_otp(uint32_t val, uint32_t otp); -diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h -index 4d5e302..7e0d93f 100644 ---- a/include/drivers/st/stm32_i2c.h -+++ b/include/drivers/st/stm32_i2c.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -125,12 +125,6 @@ - #define I2C_ICR_TIMOUTCF BIT(12) - #define I2C_ICR_ALERTCF BIT(13) - --enum i2c_speed_e { -- I2C_SPEED_STANDARD, /* 100 kHz */ -- I2C_SPEED_FAST, /* 400 kHz */ -- I2C_SPEED_FAST_PLUS, /* 1 MHz */ --}; -- - #define STANDARD_RATE 100000 - #define FAST_RATE 400000 - #define FAST_PLUS_RATE 1000000 -@@ -195,12 +189,7 @@ struct stm32_i2c_init_s { - * time in nanoseconds. - */ - -- enum i2c_speed_e speed_mode; /* -- * Specifies the I2C clock source -- * frequency mode. -- * This parameter can be a value of @ref -- * i2c_speed_mode_e. -- */ -+ uint32_t bus_rate; /* Specifies the I2C clock frequency */ - - int analog_filter; /* - * Specifies if the I2C analog noise -@@ -252,6 +241,8 @@ struct i2c_handle_s { - enum i2c_state_e i2c_state; /* Communication state */ - enum i2c_mode_e i2c_mode; /* Communication mode */ - uint32_t i2c_err; /* Error code */ -+ uint32_t saved_timing; /* Saved timing value */ -+ uint32_t saved_frequency; /* Saved frequency value */ - }; - - #define I2C_ADDRESSINGMODE_7BIT 0x00000001U -@@ -313,8 +304,7 @@ struct i2c_handle_s { - #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ - #define STM32_I2C_DIGITAL_FILTER_MAX 16 - --int stm32_i2c_get_setup_from_fdt(void *fdt, int node, -- struct stm32_i2c_init_s *init); -+int stm32_i2c_get_setup_from_fdt(int node, struct stm32_i2c_init_s *init); - int stm32_i2c_init(struct i2c_handle_s *hi2c, - struct stm32_i2c_init_s *init_data); - int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h -index 7fa9c5d..c2bb7f6 100644 ---- a/include/drivers/st/stm32_sdmmc2.h -+++ b/include/drivers/st/stm32_sdmmc2.h -@@ -9,6 +9,7 @@ - - #include - #include -+#include - - struct stm32_sdmmc2_params { - uintptr_t reg_base; -@@ -23,6 +24,7 @@ struct stm32_sdmmc2_params { - unsigned int reset_id; - unsigned int max_freq; - bool use_dma; -+ struct stm32mp_regulator vmmc_regu; - }; - - unsigned long long stm32_sdmmc2_mmc_get_device_size(void); -diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h -index 4f6930b..82f488b 100644 ---- a/include/drivers/st/stm32mp1_clk.h -+++ b/include/drivers/st/stm32mp1_clk.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -12,8 +12,16 @@ - - #include - -+#define PLL1_SETTINGS_VALID_ID U(0x504C4C31) /* "PLL1" */ -+ - int stm32mp1_clk_probe(void); --int stm32mp1_clk_init(void); -+int stm32mp1_clk_init(uint32_t pll1_freq_mhz); -+ -+int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage); -+void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data, size_t size); -+void stm32mp1_clk_lp_load_opp_pll1_settings(uint8_t *data, size_t size); -+ -+int stm32mp1_clk_get_maxfreq_opp(uint32_t *freq_mhz, uint32_t *voltage_mv); - - bool stm32mp1_rcc_is_secure(void); - bool stm32mp1_rcc_is_mckprot(void); -@@ -47,15 +55,21 @@ unsigned int stm32mp1_clk_get_refcount(unsigned long id); - unsigned long stm32mp_clk_get_rate(unsigned long id); - unsigned long stm32mp_clk_timer_get_rate(unsigned long id); - --void stm32mp1_stgen_increment(unsigned long long offset_in_ms); -- - bool stm32mp1_rtc_get_read_twice(void); - - /* SMP protection on RCC registers access */ - void stm32mp1_clk_rcc_regs_lock(void); - void stm32mp1_clk_rcc_regs_unlock(void); - -+void stm32mp1_stgen_restore_counter(unsigned long long value, -+ unsigned long long offset_in_ms); -+unsigned long long stm32mp1_stgen_get_counter(void); -+ - unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit); -+ -+int stm32mp1_round_opp_khz(uint32_t *freq_khz); -+int stm32mp1_set_opp_khz(uint32_t freq_khz); -+ - #if defined(IMAGE_BL32) - void stm32mp1_clk_mpu_suspend(void); - void stm32mp1_clk_mpu_resume(void); -diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h -index e928688..2361dcc 100644 ---- a/include/drivers/st/stm32mp1_ddr_regs.h -+++ b/include/drivers/st/stm32mp1_ddr_regs.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -381,6 +381,7 @@ struct stm32mp1_ddrphy { - #define DDRPHYC_PTR0_TITMSRST_OFFSET 18 - #define DDRPHYC_PTR0_TITMSRST_MASK GENMASK(21, 18) - -+#define DDRPHYC_ACIOCR_ACOE BIT(1) - #define DDRPHYC_ACIOCR_ACPDD BIT(3) - #define DDRPHYC_ACIOCR_ACPDR BIT(4) - #define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8) -@@ -400,6 +401,7 @@ struct stm32mp1_ddrphy { - #define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20) - #define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) - #define DDRPHYC_DSGCR_NL2PD BIT(24) -+#define DDRPHYC_DSGCR_CKOE BIT(28) - - #define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) - #define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 -diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h -index c77c0b5..c0f8694 100644 ---- a/include/drivers/st/stm32mp_clkfunc.h -+++ b/include/drivers/st/stm32mp_clkfunc.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 - */ -@@ -10,8 +10,7 @@ - #include - #include - --int fdt_get_rcc_node(void *fdt); --uint32_t fdt_rcc_read_addr(void); -+int fdt_get_rcc_node(void); - int fdt_rcc_read_uint32_array(const char *prop_name, - uint32_t *array, uint32_t count); - uint32_t fdt_rcc_read_uint32_default(const char *prop_name, -@@ -25,4 +24,6 @@ int fdt_get_clock_id(int node); - int fdt_get_clock_id_by_name(int node, const char *name); - unsigned long fdt_get_uart_clock_freq(uintptr_t instance); - -+bool fdt_is_pll1_predefined(void); -+ - #endif /* STM32MP_CLKFUNC_H */ -diff --git a/include/drivers/st/stm32mp_dummy_regulator.h b/include/drivers/st/stm32mp_dummy_regulator.h -new file mode 100644 -index 0000000..9fd83ac ---- /dev/null -+++ b/include/drivers/st/stm32mp_dummy_regulator.h -@@ -0,0 +1,14 @@ -+/* -+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_DUMMY_REGULATOR_H -+#define STM32MP_DUMMY_REGULATOR_H -+ -+#include -+ -+void bind_dummy_regulator(struct stm32mp_regulator *regu); -+ -+#endif /* STM32MP_DUMMY_REGULATOR_H */ -diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h -index 39c80e4..1147d00 100644 ---- a/include/drivers/st/stm32mp_pmic.h -+++ b/include/drivers/st/stm32mp_pmic.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 - */ -@@ -10,15 +10,26 @@ - #include - #include - #include -+#include - - int dt_pmic_status(void); --int dt_pmic_configure_boot_on_regulators(void); --int dt_pmic_set_lp_config(const char *node_name); -+int pmic_configure_boot_on_regulators(void); -+int pmic_set_lp_config(const char *node_name); - bool initialize_pmic_i2c(void); -+bool is_pmic_regulator(struct stm32mp_regulator *regu); -+void bind_pmic_regulator(struct stm32mp_regulator *regu); - void initialize_pmic(void); -+void configure_pmic(void); - #if STM32MP1_DEBUG_ENABLE - int pmic_keep_debug_unit(void); - #endif -+#if DEBUG -+void print_pmic_info_and_debug(void); -+#else -+static inline void print_pmic_info_and_debug(void) -+{ -+} -+#endif - int pmic_ddr_power_init(enum ddr_type ddr_type); - - #endif /* STM32MP_PMIC_H */ -diff --git a/include/drivers/st/stm32mp_regulator.h b/include/drivers/st/stm32mp_regulator.h -new file mode 100644 -index 0000000..7a66b97 ---- /dev/null -+++ b/include/drivers/st/stm32mp_regulator.h -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_REGULATOR_H -+#define STM32MP_REGULATOR_H -+ -+#include -+ -+struct stm32mp_regulator; -+ -+struct stm32mp_regulator_ops { -+ int (*enable)(struct stm32mp_regulator *regu); -+ int (*disable)(struct stm32mp_regulator *regu); -+}; -+ -+struct stm32mp_regulator { -+ const struct stm32mp_regulator_ops *ops; -+ int id; -+ bool always_on; -+}; -+ -+int stm32mp_regulator_enable(struct stm32mp_regulator *regu); -+int stm32mp_regulator_disable(struct stm32mp_regulator *regu); -+int stm32mp_regulator_register(struct stm32mp_regulator *regu); -+ -+int plat_bind_regulator(struct stm32mp_regulator *regu); -+ -+#endif /* STM32MP_REGULATOR_H */ -diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h -index 803a69e..50e1fa3 100644 ---- a/include/drivers/st/stpmic1.h -+++ b/include/drivers/st/stpmic1.h -@@ -86,15 +86,15 @@ - #define ITSOURCE4_REG 0xB3U - - /* Registers masks */ --#define LDO_VOLTAGE_MASK 0x7CU --#define BUCK_VOLTAGE_MASK 0xFCU -+#define LDO_VOLTAGE_MASK GENMASK(6, 2) -+#define BUCK_VOLTAGE_MASK GENMASK(7, 2) - #define LDO_BUCK_VOLTAGE_SHIFT 2 --#define LDO_BUCK_ENABLE_MASK 0x01U --#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U -+#define LDO_BUCK_ENABLE_MASK BIT(0) -+#define LDO_BUCK_HPLP_ENABLE_MASK BIT(1) - #define LDO_BUCK_HPLP_SHIFT 1 --#define LDO_BUCK_RANK_MASK 0x01U --#define LDO_BUCK_RESET_MASK 0x01U --#define LDO_BUCK_PULL_DOWN_MASK 0x03U -+#define LDO_BUCK_RANK_MASK BIT(0) -+#define LDO_BUCK_RESET_MASK BIT(0) -+#define LDO_BUCK_PULL_DOWN_MASK GENMASK(1, 0) - - /* Pull down register */ - #define BUCK1_PULL_DOWN_SHIFT 0 -@@ -135,12 +135,12 @@ - /* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ - #define SWIN_DETECTOR_ENABLED BIT(7) - #define SWOUT_DETECTOR_ENABLED BIT(6) --#define VINLOW_HYST_MASK 0x3 -+#define VINLOW_HYST_MASK GENMASK(1, 0) - #define VINLOW_HYST_SHIFT 4 --#define VINLOW_THRESHOLD_MASK 0x7 -+#define VINLOW_THRESHOLD_MASK GENMASK(2, 0) - #define VINLOW_THRESHOLD_SHIFT 1 --#define VINLOW_ENABLED 0x01 --#define VINLOW_CTRL_REG_MASK 0xFF -+#define VINLOW_ENABLED BIT(0) -+#define VINLOW_CTRL_REG_MASK GENMASK(7, 0) - - /* USB Control Register */ - #define BOOST_OVP_DISABLED BIT(7) -@@ -156,7 +156,7 @@ int stpmic1_register_write(uint8_t register_id, uint8_t value); - int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); - int stpmic1_regulator_enable(const char *name); - int stpmic1_regulator_disable(const char *name); --uint8_t stpmic1_is_regulator_enabled(const char *name); -+bool stpmic1_is_regulator_enabled(const char *name); - int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); - int stpmic1_regulator_voltage_get(const char *name); - int stpmic1_regulator_pull_down_set(const char *name); -diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c -index 2cf01f6..9a10f7b 100644 ---- a/lib/usb/usb_st_dfu.c -+++ b/lib/usb/usb_st_dfu.c -@@ -759,7 +759,7 @@ static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req) - break; - - case DFU_DETACH: -- INFO("Receive DFU detach\n"); -+ usb_dfu_detach(pdev, req); - break; - - default: -diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c -index d483c18..93f8916 100644 ---- a/plat/st/common/bl2_io_storage.c -+++ b/plat/st/common/bl2_io_storage.c -@@ -89,7 +89,6 @@ static QSPI_HandleTypeDef qspi_dev_spec = { - #endif - - #if STM32MP_UART_PROGRAMMER --/* uart*/ - static const io_dev_connector_t *uart_dev_con; - - static UART_HandleTypeDef uart_programmer = { -@@ -112,7 +111,6 @@ static const io_dev_connector_t *usb_dev_con; - #endif /*STM32MP_USB*/ - - #if STM32MP_FMC_NAND --/* nand */ - static const io_dev_connector_t *nand_dev_con; - static NAND_HandleTypeDef nand_dev_spec; - #endif -@@ -305,102 +303,6 @@ static void print_boot_device(boot_api_context_t *boot_context) - } - } - --#if STM32MP_SDMMC --static void print_bootrom_sd_status(boot_api_context_t *boot_context) --{ -- if (boot_context->sd_err_internal_timeout_cnt != 0U) { -- WARN("BootROM: %d timeout issues\n", -- boot_context->sd_err_internal_timeout_cnt); -- } -- -- if (boot_context->sd_err_dcrc_fail_cnt != 0U) { -- WARN("BootROM: %d DCRCFAIL error\n", -- boot_context->sd_err_dcrc_fail_cnt); -- } -- -- if (boot_context->sd_err_dtimeout_cnt != 0U) { -- WARN("BootROM: %d DTIMEOUT error\n", -- boot_context->sd_err_dtimeout_cnt); -- } -- -- if (boot_context->sd_err_ctimeout_cnt != 0U) { -- WARN("BootROM: %d CTIMEOUT error\n", -- boot_context->sd_err_ctimeout_cnt); -- } -- -- if (boot_context->sd_err_ccrc_fail_cnt != 0U) { -- WARN("BootROM: %d CCRCFAIL error count\n", -- boot_context->sd_err_ccrc_fail_cnt); -- } -- -- if (boot_context->sd_overall_retry_cnt != 0U) { -- WARN("BootROM: %d command retries\n", -- 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", -- boot_context->emmc_nbbytes_rxcopied_tosysram_download_area, -- boot_context->emmc_nbbytes_rxcopied_tosysram_download_area); -- -- if (boot_context->emmc_error_status != -- BOOT_API_CTX_EMMC_ERROR_STATUS_NONE) { -- WARN("BootROM eMMC error:\n"); -- switch (boot_context->emmc_error_status) { -- case BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT: -- WARN(" CMD timeout\n"); -- break; -- case BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT: -- WARN(" ACK timeout\n"); -- break; -- case BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL: -- WARN(" DATA CRC failed\n"); -- break; -- case BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX: -- WARN(" Not enough data copied\n"); -- break; -- case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND: -- WARN(" Header not found\n"); -- break; -- case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO: -- WARN(" Header size is zero\n"); -- break; -- case BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE: -- WARN(" Image not complete\n"); -- break; -- default: -- WARN(" Error not listed\n"); -- break; -- } -- } -- -- switch (boot_context->emmc_xfer_status) { -- case BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED: -- WARN("BootROM: eMMC transfer status:\n"); -- WARN(" not started\n"); -- break; -- case BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED: -- break; -- case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED: -- WARN("BootROM: eMMC transfer status:\n"); -- WARN(" timeout detected\n"); -- break; -- case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT: -- WARN("BootROM: eMMC transfer status:\n"); -- WARN(" data timeout detected\n"); -- break; -- default: -- WARN("BootROM: eMMC transfer status:\n"); -- WARN(" status not listed\n"); -- break; -- } --} --#endif -- - #if STM32MP_EMMC || STM32MP_SDMMC - static void boot_mmc(enum mmc_device_type mmc_dev_type, - uint16_t boot_interface_instance) -@@ -437,6 +339,10 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type, - break; - } - -+ if (mmc_dev_type == MMC_IS_SD) { -+ params.flags = MMC_FLAG_SD_CMD6; -+ } -+ - params.device_info = &device_info; - if (stm32_sdmmc2_mmc_init(¶ms) != 0) { - ERROR("SDMMC%u init failed\n", boot_interface_instance); -@@ -641,7 +547,7 @@ static void flash_uart(uint16_t boot_interface_instance) - /* Open connections to devices */ - io_result = io_dev_open(uart_dev_con, (uintptr_t)&uart_programmer, - &image_dev_handle); -- assert(!io_result); -+ assert(io_result == 0); - } - #endif - -@@ -672,7 +578,13 @@ static void flash_usb(struct usb_ctx *usb_context) - 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_dfu_handle.dev_status[1] = 0; -+ usb_dfu_handle.dev_status[2] = 0; -+ usb_dfu_handle.dev_status[3] = 0; -+ usb_dfu_handle.dev_status[4] = usb_dfu_handle.dev_state; -+ usb_dfu_handle.dev_status[5] = 0; - - /* Register the IO devices on this platform */ - io_result = register_io_dev_usb(&usb_dev_con); -@@ -711,13 +623,11 @@ void stm32mp_io_setup(void) - 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 -diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h -index dc2568b6..7e361d5 100644 ---- a/plat/st/common/include/stm32mp_common.h -+++ b/plat/st/common/include/stm32mp_common.h -@@ -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,7 +15,7 @@ void __dead2 stm32mp_plat_reset(int cpu); - void stm32mp_save_boot_ctx_address(uintptr_t address); - uintptr_t stm32mp_get_boot_ctx_address(void); - --int stm32mp_is_single_core(void); -+bool stm32mp_is_single_core(void); - - uintptr_t stm32mp_ddrctrl_base(void); - uintptr_t stm32mp_ddrphyc_base(void); -@@ -24,6 +24,9 @@ uintptr_t stm32mp_rcc_base(void); - - int stm32_gic_enable_spi(int node, const char *name); - -+int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, -+ uint32_t *otp_len); -+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val); - uint32_t stm32_read_otp_status(uint32_t *otp_value, uint32_t word); - uint8_t stm32_iwdg_get_instance(uintptr_t base); - uint32_t stm32_iwdg_get_otp_config(uintptr_t base); -@@ -35,6 +38,10 @@ uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags); - uintptr_t stm32_get_gpio_bank_base(unsigned int bank); - int stm32_get_gpio_bank_clock(unsigned int bank); - uint32_t stm32_get_gpio_bank_offset(unsigned int bank); -+ -+bool stm32mp_supports_cpu_opp(uint32_t opp_id); -+bool stm32mp_ddr_supports_ssr_asr(void); -+ - void stm32mp_print_cpuinfo(void); - void stm32mp_print_boardinfo(void); - -diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h -index ee313d5..581236c 100644 ---- a/plat/st/common/include/stm32mp_dt.h -+++ b/plat/st/common/include/stm32mp_dt.h -@@ -41,10 +41,17 @@ int dt_set_stdout_pinctrl(void); - void dt_fill_device_info(struct dt_node_info *info, int node); - int dt_get_node(struct dt_node_info *info, int offset, const char *compat); - int dt_get_stdout_uart_info(struct dt_node_info *info); -+int dt_get_node_by_compatible(const char *compatible); -+int dt_match_instance_by_compatible(const char *compatible, uintptr_t address); -+uintptr_t dt_get_peripheral_base(const char *compatible); - uint32_t dt_get_ddr_size(void); - uintptr_t dt_get_ddrctrl_base(void); - uintptr_t dt_get_ddrphyc_base(void); -+uintptr_t dt_get_rcc_base(void); - uintptr_t dt_get_pwr_base(void); -+int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv); -+int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array, -+ uint32_t *voltage_mv_array); - uint32_t dt_get_pwr_vdd_voltage(void); - uintptr_t dt_get_syscfg_base(void); - const char *dt_get_board_model(void); -diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c -index 8efac68..ecc41fc 100644 ---- a/plat/st/common/stm32mp_common.c -+++ b/plat/st/common/stm32mp_common.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -51,9 +51,9 @@ uintptr_t stm32mp_get_boot_ctx_address(void) - */ - #pragma weak stm32mp_is_single_core - --int stm32mp_is_single_core(void) -+bool stm32mp_is_single_core(void) - { -- return 0; -+ return false; - } - - uintptr_t stm32mp_ddrctrl_base(void) -@@ -100,7 +100,7 @@ uintptr_t stm32mp_rcc_base(void) - static uintptr_t rcc_base; - - if (rcc_base == 0) { -- rcc_base = fdt_rcc_read_addr(); -+ rcc_base = dt_get_rcc_base(); - - assert(rcc_base == RCC_BASE); - } -diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c -index 2f9951b..203b50f 100644 ---- a/plat/st/common/stm32mp_dt.c -+++ b/plat/st/common/stm32mp_dt.c -@@ -337,6 +337,74 @@ int dt_get_stdout_uart_info(struct dt_node_info *info) - } - - /******************************************************************************* -+ * This function returns the node offset matching compatible string in the DT. -+ * It is only valid for single instance peripherals (DDR, RCC, PWR, STGEN, -+ * SYSCFG...). -+ * Returns value on success, and error value on failure. -+ ******************************************************************************/ -+int dt_get_node_by_compatible(const char *compatible) -+{ -+ int node = fdt_node_offset_by_compatible(fdt, -1, compatible); -+ -+ if (node < 0) { -+ INFO("Cannot find %s node in DT\n", compatible); -+ } -+ -+ return node; -+} -+ -+/******************************************************************************* -+ * This function returns the node offset matching compatible string in the DT, -+ * and also matching the reg property with the given address. -+ * Returns value on success, and error value on failure. -+ ******************************************************************************/ -+int dt_match_instance_by_compatible(const char *compatible, uintptr_t address) -+{ -+ int node; -+ -+ for (node = fdt_node_offset_by_compatible(fdt, -1, compatible); -+ node != -FDT_ERR_NOTFOUND; -+ node = fdt_node_offset_by_compatible(fdt, node, compatible)) { -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ continue; -+ } -+ -+ if ((uintptr_t)fdt32_to_cpu(*cuint) == address) { -+ return node; -+ } -+ } -+ -+ return -FDT_ERR_NOTFOUND; -+} -+ -+/******************************************************************************* -+ * This function returns the peripheral base address information from the -+ * compatible string in the DT. It is only valid for single instance -+ * peripherals (RCC, PWR, STGEN, SYSCFG...). -+ * Returns value on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t dt_get_peripheral_base(const char *compatible) -+{ -+ int node; -+ const fdt32_t *cuint; -+ -+ node = dt_get_node_by_compatible(compatible); -+ if (node < 0) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* - * This function gets DDR size information from the DT. - * Returns value in bytes on success, and 0 on failure. - ******************************************************************************/ -@@ -344,9 +412,8 @@ uint32_t dt_get_ddr_size(void) - { - int node; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ node = dt_get_node_by_compatible(DT_DDR_COMPAT); - if (node < 0) { -- INFO("%s: Cannot read DDR node in DT\n", __func__); - return 0; - } - -@@ -362,9 +429,8 @@ uintptr_t dt_get_ddrctrl_base(void) - int node; - uint32_t array[4]; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ node = dt_get_node_by_compatible(DT_DDR_COMPAT); - if (node < 0) { -- INFO("%s: Cannot read DDR node in DT\n", __func__); - return 0; - } - -@@ -384,9 +450,8 @@ uintptr_t dt_get_ddrphyc_base(void) - int node; - uint32_t array[4]; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ node = dt_get_node_by_compatible(DT_DDR_COMPAT); - if (node < 0) { -- INFO("%s: Cannot read DDR node in DT\n", __func__); - return 0; - } - -@@ -398,26 +463,186 @@ uintptr_t dt_get_ddrphyc_base(void) - } - - /******************************************************************************* -+ * This function gets RCC base address information from the DT. -+ * Returns value on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t dt_get_rcc_base(void) -+{ -+ return dt_get_peripheral_base(DT_RCC_CLK_COMPAT); -+} -+ -+/******************************************************************************* - * This function gets PWR base address information from the DT. - * Returns value on success, and 0 on failure. - ******************************************************************************/ - uintptr_t dt_get_pwr_base(void) - { -+ return dt_get_peripheral_base(DT_PWR_COMPAT); -+} -+ -+/******************************************************************************* -+ * This function gets OPP table node from the DT. -+ * Returns node offset on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+static int dt_get_opp_table_node(void) -+{ -+ return dt_get_node_by_compatible(DT_OPP_COMPAT); -+} -+ -+/******************************************************************************* -+ * This function gets OPP parameters (frequency in KHz and voltage in mV) from -+ * an OPP table subnode. Platform HW support capabilities are also checked. -+ * Returns 0 on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+static int dt_get_opp_freqvolt_from_subnode(int subnode, uint32_t *freq_khz, -+ uint32_t *voltage_mv) -+{ -+ const fdt64_t *cuint64; -+ const fdt32_t *cuint32; -+ uint64_t read_freq_64; -+ uint32_t read_voltage_32; -+ -+ assert(freq_khz != NULL); -+ assert(voltage_mv != NULL); -+ -+ cuint32 = fdt_getprop(fdt, subnode, "opp-supported-hw", NULL); -+ if (cuint32 != NULL) { -+ if (!stm32mp_supports_cpu_opp(fdt32_to_cpu(*cuint32))) { -+ VERBOSE("Invalid opp-supported-hw 0x%x\n", -+ fdt32_to_cpu(*cuint32)); -+ return -FDT_ERR_BADVALUE; -+ } -+ } -+ -+ cuint64 = fdt_getprop(fdt, subnode, "opp-hz", NULL); -+ if (cuint64 == NULL) { -+ VERBOSE("Missing opp-hz\n"); -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ /* Frequency value expressed in KHz must fit on 32 bits */ -+ read_freq_64 = fdt64_to_cpu(*cuint64) / 1000ULL; -+ if (read_freq_64 > (uint64_t)UINT32_MAX) { -+ VERBOSE("Invalid opp-hz %llu\n", read_freq_64); -+ return -FDT_ERR_BADVALUE; -+ } -+ -+ cuint32 = fdt_getprop(fdt, subnode, "opp-microvolt", NULL); -+ if (cuint32 == NULL) { -+ VERBOSE("Missing opp-microvolt\n"); -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ /* Millivolt value must fit on 16 bits */ -+ read_voltage_32 = fdt32_to_cpu(*cuint32) / 1000U; -+ if (read_voltage_32 > (uint32_t)UINT16_MAX) { -+ VERBOSE("Invalid opp-microvolt %u\n", read_voltage_32); -+ return -FDT_ERR_BADVALUE; -+ } -+ -+ *freq_khz = (uint32_t)read_freq_64; -+ -+ *voltage_mv = read_voltage_32; -+ -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function parses OPP table in DT and finds the parameters for the -+ * highest frequency supported by the HW platform. -+ * If found, the new frequency and voltage values override the original ones. -+ * Returns 0 on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv) -+{ - int node; -- const fdt32_t *cuint; -+ int subnode; -+ uint32_t freq = 0U; -+ uint32_t voltage = 0U; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ assert(freq_khz != NULL); -+ assert(voltage_mv != NULL); -+ -+ node = dt_get_opp_table_node(); - if (node < 0) { -- INFO("%s: Cannot read PWR node in DT\n", __func__); -- return 0; -+ return node; - } - -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) { -- return 0; -+ fdt_for_each_subnode(subnode, fdt, node) { -+ uint32_t read_freq; -+ uint32_t read_voltage; -+ -+ if (dt_get_opp_freqvolt_from_subnode(subnode, &read_freq, -+ &read_voltage) != 0) { -+ continue; -+ } -+ -+ if (read_freq > freq) { -+ freq = read_freq; -+ voltage = read_voltage; -+ } - } - -- return fdt32_to_cpu(*cuint); -+ if ((freq == 0U) || (voltage == 0U)) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ *freq_khz = freq; -+ *voltage_mv = voltage; -+ -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function parses OPP table in DT and finds all parameters supported by -+ * the HW platform. -+ * If found, the corresponding frequency and voltage values are respectively -+ * stored in @*freq_khz_array and @*voltage_mv_array. -+ * Note that @*count has to be set by caller to the effective size allocated -+ * for both tables. Its value is then replaced by the number of filled elements. -+ * Returns 0 on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array, -+ uint32_t *voltage_mv_array) -+{ -+ int node; -+ int subnode; -+ int idx = 0; -+ -+ assert(count != NULL); -+ assert(freq_khz_array != NULL); -+ assert(voltage_mv_array != NULL); -+ -+ node = dt_get_opp_table_node(); -+ if (node < 0) { -+ return node; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ uint32_t read_freq; -+ uint32_t read_voltage; -+ -+ if (dt_get_opp_freqvolt_from_subnode(subnode, &read_freq, -+ &read_voltage) != 0) { -+ continue; -+ } -+ -+ if (idx >= *count) { -+ return -FDT_ERR_NOSPACE; -+ } -+ -+ freq_khz_array[idx] = read_freq; -+ voltage_mv_array[idx] = read_voltage; -+ idx++; -+ } -+ -+ if (idx == 0U) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ *count = idx; -+ -+ return 0; - } - - /******************************************************************************* -@@ -429,9 +654,8 @@ uint32_t dt_get_pwr_vdd_voltage(void) - int node, pwr_regulators_node; - const fdt32_t *cuint; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ node = dt_get_node_by_compatible(DT_PWR_COMPAT); - if (node < 0) { -- INFO("%s: Cannot read PWR node in DT\n", __func__); - return 0; - } - -@@ -465,21 +689,7 @@ uint32_t dt_get_pwr_vdd_voltage(void) - ******************************************************************************/ - uintptr_t dt_get_syscfg_base(void) - { -- int node; -- const fdt32_t *cuint; -- -- node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT); -- if (node < 0) { -- INFO("%s: Cannot read SYSCFG node in DT\n", __func__); -- return 0; -- } -- -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) { -- return 0; -- } -- -- return fdt32_to_cpu(*cuint); -+ return dt_get_peripheral_base(DT_SYSCFG_COMPAT); - } - - /******************************************************************************* -diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c -index 1a2e2d6..ef5a13d 100644 ---- a/plat/st/stm32mp1/bl2_plat_setup.c -+++ b/plat/st/stm32mp1/bl2_plat_setup.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -36,6 +37,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -146,19 +148,13 @@ void bl2_platform_setup(void) - { - int ret; - -- if (dt_pmic_status() > 0) { -- initialize_pmic(); --#if STM32MP1_DEBUG_ENABLE -- /* Program PMIC to keep debug ON */ -- if ((stm32mp1_dbgmcu_boot_debug_info() == 1) && -- (stm32mp1_dbgmcu_is_debug_on() != 0)) { -- VERBOSE("Program PMIC to keep debug ON\n"); -- if (pmic_keep_debug_unit() != 0) { -- ERROR("PMIC not properly set for debug\n"); -- } -- } --#endif -- } -+ /* -+ * Map DDR non cacheable during its initialisation to avoid -+ * speculative loads before accesses are fully setup. -+ */ -+ mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, -+ STM32MP_DDR_MAX_SIZE, -+ MT_NON_CACHEABLE | MT_RW | MT_NS); - - ret = stm32mp1_ddr_probe(); - if (ret < 0) { -@@ -166,15 +162,118 @@ void bl2_platform_setup(void) - panic(); - } - -+ mmap_remove_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_MAX_SIZE); -+ - #ifdef AARCH32_SP_OPTEE - INFO("BL2 runs OP-TEE setup\n"); -+ -+ /* Map non secure DDR for BL33 load, now with cacheable attribute */ -+ mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, -+ dt_get_ddr_size() - STM32MP_DDR_S_SIZE - -+ STM32MP_DDR_SHMEM_SIZE, -+ MT_MEMORY | MT_RW | MT_NS); -+ -+ mmap_add_dynamic_region(STM32MP_DDR_BASE + dt_get_ddr_size() - -+ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE, -+ STM32MP_DDR_BASE + dt_get_ddr_size() - -+ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE, -+ STM32MP_DDR_S_SIZE, -+ MT_MEMORY | MT_RW | MT_SECURE); -+ - /* Initialize tzc400 after DDR initialization */ - stm32mp1_security_setup(); - #else - INFO("BL2 runs SP_MIN setup\n"); -+ -+ /* Map non secure DDR for BL33 load, now with cacheable attribute */ -+ mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, -+ dt_get_ddr_size(), -+ MT_MEMORY | MT_RW | MT_NS); - #endif - } - -+static void update_monotonic_counter(void) -+{ -+ uint32_t version; -+ uint32_t otp; -+ -+ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE, -+ assert_stm32mp1_monotonic_counter_reach_max); -+ -+ /* Check if monotonic counter needs to be incremented */ -+ if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) { -+ panic(); -+ } -+ -+ if (stm32_get_otp_value(MONOTONIC_OTP, &version) != 0) { -+ panic(); -+ } -+ -+ if ((version + 1U) < BIT(STM32_TF_VERSION)) { -+ uint32_t result; -+ -+ /* Need to increment the monotonic counter */ -+ version = BIT(STM32_TF_VERSION) - 1U; -+ -+ result = bsec_program_otp(version, otp); -+ if (result != BSEC_OK) { -+ ERROR("BSEC: MONOTONIC_OTP program Error %i\n", -+ result); -+ panic(); -+ } -+ INFO("Monotonic counter has been incremented value 0x%x\n", -+ version); -+ } -+} -+ -+static void initialize_clock(bool wakeup_standby) -+{ -+ uint32_t voltage_mv = 0U; -+ uint32_t freq_khz = 0U; -+ int ret; -+ -+ if (wakeup_standby) { -+ stm32_get_pll1_settings_from_context(); -+ } -+ -+ /* -+ * If no pre-defined PLL1 settings in DT, find the highest frequency -+ * in the OPP table (in DT, compatible with plaform capabilities, or -+ * in structure restored in RAM), and set related VDDCORE voltage. -+ * If PLL1 settings found in DT, we consider VDDCORE voltage in DT is -+ * consistent with it. -+ */ -+ if (!fdt_is_pll1_predefined()) { -+ if (wakeup_standby) { -+ ret = stm32mp1_clk_get_maxfreq_opp(&freq_khz, -+ &voltage_mv); -+ } else { -+ ret = dt_get_max_opp_freqvolt(&freq_khz, &voltage_mv); -+ } -+ -+ if (ret != 0) { -+ panic(); -+ } -+ -+ if (dt_pmic_status() > 0) { -+ int read_voltage; -+ const char *name = "buck1"; -+ -+ read_voltage = stpmic1_regulator_voltage_get(name); -+ if (voltage_mv != (uint32_t)read_voltage) { -+ if (stpmic1_regulator_voltage_set(name, -+ (uint16_t)voltage_mv) != 0) { -+ panic(); -+ } -+ } -+ } -+ } -+ -+ if (stm32mp1_clk_init(freq_khz) < 0) { -+ panic(); -+ } -+} -+ - void bl2_el3_plat_arch_setup(void) - { - int32_t result; -@@ -189,6 +288,7 @@ void bl2_el3_plat_arch_setup(void) - tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); - uint32_t bkpr_core1_addr = - tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); -+ bool wakeup_standby = false; - - mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, - BL_CODE_END - BL_CODE_BASE, -@@ -201,14 +301,6 @@ void bl2_el3_plat_arch_setup(void) - #endif - - #ifdef AARCH32_SP_OPTEE -- /* OP-TEE image needs post load processing: keep RAM read/write */ -- mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() - -- STM32MP_DDR_S_SIZE, -- STM32MP_DDR_BASE + dt_get_ddr_size() - -- STM32MP_DDR_S_SIZE, -- STM32MP_DDR_S_SIZE, -- MT_MEMORY | MT_RW | MT_SECURE); -- - mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, - STM32MP_OPTEE_SIZE, - MT_MEMORY | MT_RW | MT_SECURE); -@@ -216,19 +308,12 @@ void bl2_el3_plat_arch_setup(void) - /* Prevent corruption of preloaded BL32 */ - mmap_add_region(BL32_BASE, BL32_BASE, - BL32_LIMIT - BL32_BASE, -- MT_MEMORY | MT_RO | MT_SECURE); -- -+ MT_RO_DATA | MT_SECURE); - #endif -- /* Map non secure DDR for BL33 load and DDR training area restore */ -- mmap_add_region(STM32MP_DDR_BASE, -- STM32MP_DDR_BASE, -- STM32MP_DDR_MAX_SIZE, -- MT_MEMORY | MT_RW | MT_NS); -- - /* Prevent corruption of preloaded Device Tree */ - mmap_add_region(DTB_BASE, DTB_BASE, - DTB_LIMIT - DTB_BASE, -- MT_MEMORY | MT_RO | MT_SECURE); -+ MT_RO_DATA | MT_SECURE); - - configure_mmu(); - -@@ -301,6 +386,10 @@ void bl2_el3_plat_arch_setup(void) - mmio_write_32(bkpr_core1_magic, 0); - } - -+ if (mmio_read_32(bkpr_core1_addr) != 0U) { -+ wakeup_standby = true; -+ } -+ - generic_delay_timer_init(); - - #ifdef STM32MP_USB -@@ -325,10 +414,16 @@ void bl2_el3_plat_arch_setup(void) - panic(); - } - -- if (stm32mp1_clk_init() < 0) { -- panic(); -+ if (dt_pmic_status() > 0) { -+ initialize_pmic(); -+ -+ if (!wakeup_standby) { -+ configure_pmic(); -+ } - } - -+ initialize_clock(wakeup_standby); -+ - stm32mp1_syscfg_init(); - - result = dt_get_stdout_uart_info(&dt_uart_info); -@@ -418,6 +513,23 @@ skip_console_init: - - print_reset_reason(); - -+ if (dt_pmic_status() > 0) { -+ initialize_pmic(); -+ print_pmic_info_and_debug(); -+#if STM32MP1_DEBUG_ENABLE -+ /* Program PMIC to keep debug ON */ -+ if ((stm32mp1_dbgmcu_boot_debug_info() == 1) && -+ (stm32mp1_dbgmcu_is_debug_on())) { -+ VERBOSE("Program PMIC to keep debug ON\n"); -+ if (pmic_keep_debug_unit() != 0) { -+ ERROR("PMIC not properly set for debug\n"); -+ } -+ } -+#endif -+ } -+ -+ update_monotonic_counter(); -+ - stm32mp_io_setup(); - } - -@@ -438,11 +550,12 @@ static void set_mem_params_info(entry_point_info_t *ep_info, - unpaged->image_max_size = STM32MP_OPTEE_SIZE; - } else { - unpaged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() - -- STM32MP_DDR_S_SIZE; -+ STM32MP_DDR_S_SIZE - -+ STM32MP_DDR_SHMEM_SIZE; - unpaged->image_max_size = STM32MP_DDR_S_SIZE; - } - paged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() - -- STM32MP_DDR_S_SIZE; -+ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE; - paged->image_max_size = STM32MP_DDR_S_SIZE; - } - #endif -diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h -index 4cd6643..ba325c5 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_context.h -+++ b/plat/st/stm32mp1/include/stm32mp1_context.h -@@ -15,8 +15,11 @@ - void stm32_clean_context(void); - int stm32_save_context(uint32_t zq0cr0_zdata); - int stm32_restore_context(void); -+unsigned long long stm32_get_stgen_from_context(void); - int stm32_restore_backup_reg(void); - uint32_t stm32_get_zdata_from_context(void); -+void stm32_get_pll1_settings_from_context(void); -+bool stm32_are_pll1_settings_valid_in_context(void); - int stm32_save_boot_interface(uint32_t interface, uint32_t instance); - int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance); - void stm32_save_ddr_training_area(void); -diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h -index fd97a16..c3cb0b3 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h -+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h -@@ -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,12 +15,12 @@ - #define VERBOSE_HEXDUMP8(buf, len) - #endif - --uint32_t stm32mp1_dbgmcu_get_chip_version(void); --uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void); -+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version); -+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id); - int stm32mp1_dbgmcu_freeze_iwdg2(void); - int stm32mp1_dbgmcu_boot_debug_info(void); --int stm32mp1_dbgmcu_clear_boot_info(void); --uint32_t stm32mp1_dbgmcu_is_debug_on(void); -+void stm32mp1_dbgmcu_clear_boot_info(void); -+bool stm32mp1_dbgmcu_is_debug_on(void); - void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len); - - #endif /* __PLAT_DBGMCU_H__ */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h -index 956493f..7014ff7 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_smc.h -+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h -@@ -1,68 +1,169 @@ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - --#ifndef __STM32MP1_SMC_H__ --#define __STM32MP1_SMC_H__ -+#ifndef STM32MP1_SMC_H -+#define STM32MP1_SMC_H - - #include - -+/* SMC service generic return codes */ -+#define STM32_SMC_OK 0x00000000U -+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU -+#define STM32_SMC_FAILED 0xFFFFFFFEU -+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU -+ - /* -- * SMC function IDs for STM32 Service queries -+ * SMC function IDs for STM32 Service queries. - * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF - * like this is defined in SMC calling Convention by ARM -- * for SiP (silicon Partner) -+ * for SiP (silicon Partner). - * https://developer.arm.com/docs/den0028/latest - */ - - /* Secure Service access from Non-secure */ -+ -+/* -+ * SMC function STM32_SMC_RCC. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx). -+ * Argument a2: (input) Register offset or physical address. -+ * (output) Register read value, if applicable. -+ * Argument a3: (input) Register target value if applicable. -+ */ - #define STM32_SMC_RCC 0x82001000 -+ -+/* -+ * SMC function STM32_SMC_PWR. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx). -+ * Argument a2: (input) Register offset or physical address. -+ * (output) Register read value, if applicable. -+ * Argument a3: (input) Register target value if applicable. -+ */ - #define STM32_SMC_PWR 0x82001001 -+ -+/* -+ * SMC functions STM32_SMC_RCC_CAL. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (input) Clock ID (from DT clock bindings). -+ */ - #define STM32_SMC_RCC_CAL 0x82001002 -+ -+/* -+ * SMC functions STM32_SMC_BSEC. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (input) Service ID (STM32_SMC_READ_xxx/_PROG_xxx/_WRITE_xxx). -+ * (output) OTP read value, if applicable. -+ * Argument a2: (input) OTP index. -+ * Argument a3: (input) OTP value if applicable. -+ */ - #define STM32_SMC_BSEC 0x82001003 - - /* Low Power services */ -+ -+/* -+ * SIP functions STM32_SMC_SR_MODE. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (unused). -+ * Argument a2: (input) Target selfrefresh mode (STM32_SMC_SR_MODE_xxx). -+ */ - #define STM32_SMC_SR_MODE 0x82001004 -+ -+/* -+ * SIP function STM32_SMC_PD_DOMAIN. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a2: (index) ID of target power domain to be enabled/disabled. -+ * Argument a3: (input) 0 to disable, 1 to enable target domain. -+ */ - #define STM32_SMC_PD_DOMAIN 0x82001008 - -+/* -+ * SIP function STM32_SMC_RCC_OPP. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (input) Service ID (STM32_SMC_RCC_OPP_xxx). -+ * (output) Rounded frequency, if applicable. -+ * Argument a2: (input) Requested frequency. -+ */ -+#define STM32_SMC_RCC_OPP 0x82001009 -+ - /* SMC function IDs for SiP Service queries */ -+ -+/* -+ * SIP function STM32_SIP_SVC_CALL_COUNT. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Dummy value 0. -+ */ - #define STM32_SIP_SVC_CALL_COUNT 0x8200ff00 -+ -+/* -+ * SIP function STM32_SIP_SVC_UID. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Lowest 32bit of the stm32mp1 SIP service UUID. -+ * Argument a1: (output) Next 32bit of the stm32mp1 SIP service UUID. -+ * Argument a2: (output) Next 32bit of the stm32mp1 SIP service UUID. -+ * Argument a3: (output) Last 32bit of the stm32mp1 SIP service UUID. -+ */ - #define STM32_SIP_SVC_UID 0x8200ff01 --/* 0x8200ff02 is reserved */ --#define STM32_SIP_SVC_VERSION 0x8200ff03 - --/* STM32 SiP Service Calls version numbers */ --#define STM32_SIP_SVC_VERSION_MAJOR 0x0 --#define STM32_SIP_SVC_VERSION_MINOR 0x1 -+/* 0x8200ff02 is reserved */ - --/* Number of STM32 SiP Calls implemented */ --#define STM32_COMMON_SIP_NUM_CALLS 10 -+/* -+ * SIP function STM32_SIP_SVC_VERSION. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) STM32 SIP service major. -+ * Argument a1: (output) STM32 SIP service minor. -+ */ -+#define STM32_SIP_SVC_VERSION 0x8200ff03 - --/* Register access service use for RCC/RTC/PWR */ -+/* Service ID for STM32_SMC_RCC/_PWR */ - #define STM32_SMC_REG_READ 0x0 - #define STM32_SMC_REG_WRITE 0x1 - #define STM32_SMC_REG_SET 0x2 - #define STM32_SMC_REG_CLEAR 0x3 - --/* Service for BSEC */ -+/* Service ID for STM32_SMC_BSEC */ - #define STM32_SMC_READ_SHADOW 0x01 - #define STM32_SMC_PROG_OTP 0x02 - #define STM32_SMC_WRITE_SHADOW 0x03 - #define STM32_SMC_READ_OTP 0x04 - #define STM32_SMC_READ_ALL 0x05 - #define STM32_SMC_WRITE_ALL 0x06 -- --/* SMC error codes */ --#define STM32_SMC_OK 0x00000000U --#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU --#define STM32_SMC_FAILED 0xFFFFFFFEU --#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU -+#define STM32_SMC_WRLOCK_OTP 0x07 - - /* DDR Self-Refresh modes */ - #define STM32_SMC_SR_MODE_SSR 0x0 - #define STM32_SMC_SR_MODE_ASR 0x1 - #define STM32_SMC_SR_MODE_HSR 0x2 - --#endif /* __STM32MP1_SMC_H__ */ -+/* Service ID for STM32_SMC_RCC_OPP */ -+#define STM32_SMC_RCC_OPP_SET 0x0 -+#define STM32_SMC_RCC_OPP_ROUND 0x1 -+ -+/* STM32 SiP Service Calls version numbers */ -+#define STM32_SIP_SVC_VERSION_MAJOR 0x0 -+#define STM32_SIP_SVC_VERSION_MINOR 0x1 -+ -+/* Number of STM32 SiP Calls implemented */ -+#define STM32_COMMON_SIP_NUM_CALLS 11 -+ -+#endif /* STM32MP1_SMC_H */ -diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c -index db53c37..a6ca9ce 100644 ---- a/plat/st/stm32mp1/plat_image_load.c -+++ b/plat/st/stm32mp1/plat_image_load.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -7,7 +7,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -28,37 +27,7 @@ - ******************************************************************************/ - void plat_flush_next_bl_params(void) - { -- uint32_t version; -- - flush_bl_params_desc(); -- -- CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE, -- assert_stm32mp1_monotonic_counter_reach_max); -- -- /* Check if monotonic counter need to be incremented */ -- ; -- if (bsec_shadow_read_otp(&version, MONOTONIC_OTP) != BSEC_OK) { -- ERROR("BSEC: MONOTONIC_OTP Error\n"); -- panic(); -- } -- -- INFO("read version %i current version %i\n", version, STM32_TF_VERSION); -- -- if ((version + 1U) < BIT(STM32_TF_VERSION)) { -- uint32_t result; -- -- /* need to increment the monotonic counter */ -- version = BIT(STM32_TF_VERSION) - 1U; -- -- result = bsec_program_otp(version, MONOTONIC_OTP); -- if (result != BSEC_OK) { -- ERROR("BSEC: MONOTONIC_OTP program Error %i\n", -- result); -- panic(); -- } -- INFO("Monotonic counter has been incremented value 0x%x\n", -- version); -- } - } - - #ifdef AARCH32_SP_OPTEE -@@ -121,7 +90,13 @@ bl_load_info_t *plat_get_bl_image_load_info(void) - stm32mp_clk_disable(RTCAPB); - } - -- bl33->image_info.image_max_size = dt_get_ddr_size(); -+ /* Max size is non-secure DDR end address minus image_base */ -+ bl33->image_info.image_max_size = dt_get_ddr_size() - -+#ifdef AARCH32_SP_OPTEE -+ STM32MP_DDR_S_SIZE - -+ STM32MP_DDR_SHMEM_SIZE - -+#endif -+ bl33->image_info.image_base; - - return get_bl_load_info_from_mem_params_desc(); - } -diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk -index 91bb1ca..31cc273 100644 ---- a/plat/st/stm32mp1/platform.mk -+++ b/plat/st/stm32mp1/platform.mk -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -11,7 +11,7 @@ USE_COHERENT_MEM := 0 - MULTI_CONSOLE_API := 1 - - # Add specific ST version --ST_VERSION := r1.5 -+ST_VERSION := r3.0 - VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} - - # Please don't increment this value without good understanding of -@@ -19,6 +19,11 @@ VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE - STM32_TF_VERSION ?= 0 - $(eval $(call add_define_val,STM32_TF_VERSION,${STM32_TF_VERSION})) - -+# Enable dynamic memory mapping -+PLAT_XLAT_TABLES_DYNAMIC := 1 -+$(eval $(call assert_boolean,PLAT_XLAT_TABLES_DYNAMIC)) -+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) -+ - # Enable software PMIC programming in case of debug purpose - STM32MP1_DEBUG_ENABLE ?= 1 - $(eval $(call add_define_val,STM32MP1_DEBUG_ENABLE,${STM32MP1_DEBUG_ENABLE})) -@@ -134,6 +139,8 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ - drivers/st/iwdg/stm32_iwdg.c \ - drivers/st/pmic/stm32mp_pmic.c \ - drivers/st/pmic/stpmic1.c \ -+ drivers/st/regulator/stm32mp_dummy_regulator.c \ -+ drivers/st/regulator/stm32mp_regulator.c \ - drivers/st/reset/stm32mp1_reset.c \ - plat/st/common/stm32mp_dt.c \ - plat/st/common/stm32mp_shres_helpers.c \ -@@ -219,7 +226,7 @@ STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} - .PHONY: ${STM32_TF_STM32} - .SUFFIXES: - --all: check_dtc_version ${STM32_TF_STM32} stm32image -+all: check_dtc_version stm32image ${STM32_TF_STM32} - - ifeq ($(AARCH32_SP),sp_min) - # BL32 is built only if using SP_MIN -@@ -232,6 +239,8 @@ distclean realclean clean: clean_stm32image - stm32image: - ${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH} - -+${STM32IMAGE}: stm32image -+ - clean_stm32image: - ${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean - -@@ -266,7 +275,7 @@ ${STM32_TF_BINARY}: ${STM32_TF_ELF} - @echo "Built $@ successfully" - @echo - --${STM32_TF_STM32}: stm32image ${STM32_TF_BINARY} -+${STM32_TF_STM32}: ${STM32IMAGE} ${STM32_TF_BINARY} - @echo - @echo "Generated $@" - $(eval LOADADDR = $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}')) -diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c -index b13580d..85cf3c6 100644 ---- a/plat/st/stm32mp1/services/bsec_svc.c -+++ b/plat/st/stm32mp1/services/bsec_svc.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -94,6 +94,7 @@ static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update) - return BSEC_NO_SSP; - } - -+#if STM32MP_USB || STM32MP_UART_PROGRAMMER - static uint32_t bsec_read_all_bsec(struct otp_exchange *exchange) - { - uint32_t i; -@@ -382,6 +383,7 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, - - return BSEC_OK; - } -+#endif /* STM32MP_USB || STM32MP_UART_PROGRAMMER */ - - uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t *ret_otp_value) -@@ -391,14 +393,16 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, - - if ((x1 != STM32_SMC_READ_ALL) && (x1 != STM32_SMC_WRITE_ALL) && - (bsec_check_nsec_access_rights(x2) != BSEC_OK)) { -- return BSEC_ERROR; -+ return STM32_SMC_INVALID_PARAMS; - } - -+#if STM32MP_USB || STM32MP_UART_PROGRAMMER - if (((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) && - (!ddr_is_nonsecured_area((uintptr_t)x2, - sizeof(struct otp_exchange)))) { -- return BSEC_ERROR; -+ return STM32_SMC_INVALID_PARAMS; - } -+#endif - - switch (x1) { - case STM32_SMC_READ_SHADOW: -@@ -443,6 +447,7 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, - - result = bsec_write_otp(tmp_data, x2); - break; -+#if STM32MP_USB || STM32MP_UART_PROGRAMMER - case STM32_SMC_READ_ALL: - result = bsec_read_all_bsec((struct otp_exchange *)x2); - break; -@@ -450,10 +455,13 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, - result = bsec_write_all_bsec((struct otp_exchange *)x2, - ret_otp_value); - break; -- default: -- result = BSEC_ERROR; -+#endif -+ case STM32_SMC_WRLOCK_OTP: -+ result = bsec_permanent_lock_otp(x2); - break; -+ default: -+ return STM32_SMC_INVALID_PARAMS; - } - -- return result; -+ return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED; - } -diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c -index 6e8f9d0..3dc4ab0 100644 ---- a/plat/st/stm32mp1/services/rcc_svc.c -+++ b/plat/st/stm32mp1/services/rcc_svc.c -@@ -1,6 +1,5 @@ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -475,3 +474,34 @@ uint32_t rcc_cal_scv_handler(uint32_t x1) - - return ret; - } -+ -+uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res) -+{ -+ uint32_t cmd = x1; -+ uint32_t opp = x2 / 1000U; /* KHz */ -+ -+ switch (cmd) { -+ case STM32_SMC_RCC_OPP_SET: -+ if (stm32mp1_set_opp_khz(opp) != 0) { -+ return STM32_SMC_FAILED; -+ } -+ break; -+ -+ case STM32_SMC_RCC_OPP_ROUND: -+ if (stm32mp1_round_opp_khz(&opp) != 0) { -+ return STM32_SMC_FAILED; -+ } -+ -+ if (opp > (UINT32_MAX / 1000U)) { -+ return STM32_SMC_FAILED; -+ } -+ -+ *res = opp * 1000U; -+ break; -+ -+ default: -+ return STM32_SMC_INVALID_PARAMS; -+ } -+ -+ return STM32_SMC_OK; -+} -diff --git a/plat/st/stm32mp1/services/rcc_svc.h b/plat/st/stm32mp1/services/rcc_svc.h -index 75d4a3c..23c7582 100644 ---- a/plat/st/stm32mp1/services/rcc_svc.h -+++ b/plat/st/stm32mp1/services/rcc_svc.h -@@ -1,6 +1,5 @@ - /* -- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -10,5 +9,6 @@ - - uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); - uint32_t rcc_cal_scv_handler(uint32_t x1); -+uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res); - - #endif /* RCC_SVC_H */ -diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -index fff91c0..cabaf16 100644 ---- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -@@ -1,6 +1,5 @@ - /* -- * Copyright (c) 2014-2018, STMicroelectronics - All Rights Reserved -- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2014-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -74,6 +73,11 @@ static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1, - ret1 = rcc_cal_scv_handler(x1); - break; - -+ case STM32_SMC_RCC_OPP: -+ ret1 = rcc_opp_scv_handler(x1, x2, &ret2); -+ ret2_enabled = true; -+ break; -+ - case STM32_SMC_PWR: - ret1 = pwr_scv_handler(x1, x2, x3); - break; -@@ -88,7 +92,7 @@ static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1, - - default: - WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid); -- ret1 = SMC_UNK; -+ ret1 = STM32_SMC_NOT_SUPPORTED; - break; - } - -diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c -index 8748b68..1d87080 100644 ---- a/plat/st/stm32mp1/sp_min/sp_min_setup.c -+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -97,6 +98,29 @@ static void configure_wakeup_interrupt(void) - plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO); - } - -+static void initialize_pll1_settings(void) -+{ -+ uint32_t vddcore_voltage = 0U; -+ int ret; -+ -+ if (stm32_are_pll1_settings_valid_in_context()) { -+ return; -+ } -+ -+ if (dt_pmic_status() > 0) { -+ ret = stpmic1_regulator_voltage_get("buck1"); -+ if (ret < 0) { -+ panic(); -+ } -+ -+ vddcore_voltage = (uint32_t)ret; -+ } -+ -+ if (stm32mp1_clk_compute_all_pll1_settings(vddcore_voltage) != 0) { -+ panic(); -+ } -+} -+ - /******************************************************************************* - * Interrupt handler for FIQ (secure IRQ) - ******************************************************************************/ -@@ -299,6 +323,8 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - initialize_pmic(); - } - -+ initialize_pll1_settings(); -+ - stm32mp1_init_lp_states(); - } - -diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c -index 8dc1146..362b672 100644 ---- a/plat/st/stm32mp1/stm32mp1_context.c -+++ b/plat/st/stm32mp1/stm32mp1_context.c -@@ -28,24 +28,46 @@ - #define TRAINING_AREA_SIZE 64 - - #ifdef AARCH32_SP_OPTEE --/* OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined */ --#define OPTEE_MAILBOX_MAGIC_V1 0x01 --#define OPTEE_MAILBOX_MAGIC ((OPTEE_MAILBOX_MAGIC_V1 << 16) + \ -- TRAINING_AREA_SIZE) -+/* -+ * OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined -+ * -+ * OPTEE_MAILBOX_MAGIC_V1: -+ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer. -+ * -+ * OPTEE_MAILBOX_MAGIC_V2: -+ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer -+ * and PLL1 dual OPP settings structure (86 bytes). -+ */ -+#define OPTEE_MAILBOX_MAGIC_V1 (0x0001 << 16) -+#define OPTEE_MAILBOX_MAGIC_V2 (0x0002 << 16) -+#define OPTEE_MAILBOX_MAGIC (OPTEE_MAILBOX_MAGIC_V2 | \ -+ TRAINING_AREA_SIZE) -+ -+#if (PLAT_MAX_OPP_NB != 2) || (PLAT_MAX_PLLCFG_NB != 6) -+#error OPTEE_MAILBOX_MAGIC_V1 does not support expected PLL1 settings -+#endif - #endif - -+/* pll_settings structure size definitions (reference to clock driver) */ -+#define PLL1_SETTINGS_SIZE (((PLAT_MAX_OPP_NB * \ -+ (PLAT_MAX_PLLCFG_NB + 3)) + 1) * \ -+ sizeof(uint32_t)) -+ - struct backup_data_s { - #ifdef AARCH32_SP_OPTEE - uint32_t magic; - uint32_t core0_resume_hint; - uint32_t zq0cr0_zdata; - uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; -+ uint8_t pll1_settings[PLL1_SETTINGS_SIZE]; - #else - smc_ctx_t saved_smc_context[PLATFORM_CORE_COUNT]; - cpu_context_t saved_cpu_context[PLATFORM_CORE_COUNT]; - uint32_t zq0cr0_zdata; - struct stm32_rtc_calendar rtc; - uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; -+ uint8_t pll1_settings[PLL1_SETTINGS_SIZE]; -+ unsigned long long stgen; - #endif - }; - -@@ -106,6 +128,10 @@ int stm32_save_context(uint32_t zq0cr0_zdata) - backup_data->zq0cr0_zdata = zq0cr0_zdata; - - stm32_rtc_get_calendar(&backup_data->rtc); -+ backup_data->stgen = stm32mp1_stgen_get_counter(); -+ -+ stm32mp1_clk_lp_save_opp_pll1_settings(backup_data->pll1_settings, -+ sizeof(backup_data->pll1_settings)); - - stm32mp_clk_disable(BKPSRAM); - -@@ -137,16 +163,35 @@ int stm32_restore_context(void) - memcpy(cpu_context, backup_data->saved_cpu_context, - sizeof(cpu_context_t) * PLATFORM_CORE_COUNT); - -- /* update STGEN counter with standby mode length */ -+ /* Restore STGEN counter with standby mode length */ - stm32_rtc_get_calendar(¤t_calendar); - stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, - &backup_data->rtc); -- stm32mp1_stgen_increment(stdby_time_in_ms); -+ stm32mp1_stgen_restore_counter(backup_data->stgen, stdby_time_in_ms); -+ -+ stm32mp1_clk_lp_load_opp_pll1_settings(backup_data->pll1_settings, -+ sizeof(backup_data->pll1_settings)); - - stm32mp_clk_disable(BKPSRAM); - - return 0; - } -+ -+unsigned long long stm32_get_stgen_from_context(void) -+{ -+ struct backup_data_s *backup_data; -+ unsigned long long stgen_cnt; -+ -+ stm32mp_clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ stgen_cnt = backup_data->stgen; -+ -+ stm32mp_clk_disable(BKPSRAM); -+ -+ return stgen_cnt; -+} - #endif /*AARCH32_SP_OPTEE*/ - - uint32_t stm32_get_zdata_from_context(void) -@@ -166,6 +211,40 @@ uint32_t stm32_get_zdata_from_context(void) - return zdata; - } - -+void stm32_get_pll1_settings_from_context(void) -+{ -+ struct backup_data_s *backup_data; -+ uint8_t *data; -+ -+ stm32mp_clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ data = (uint8_t *)backup_data->pll1_settings; -+ stm32mp1_clk_lp_load_opp_pll1_settings(data, -+ sizeof(backup_data->pll1_settings)); -+ -+ stm32mp_clk_disable(BKPSRAM); -+} -+ -+bool stm32_are_pll1_settings_valid_in_context(void) -+{ -+ struct backup_data_s *backup_data; -+ uint32_t *data; -+ bool is_valid; -+ -+ stm32mp_clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ data = (uint32_t *)backup_data->pll1_settings; -+ -+ is_valid = (data[0] == PLL1_SETTINGS_VALID_ID); -+ -+ stm32mp_clk_disable(BKPSRAM); -+ -+ return is_valid; -+} -+ - int stm32_save_boot_interface(uint32_t interface, uint32_t instance) - { - uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); -diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c -index 716f7d8..39cf5d7 100644 ---- a/plat/st/stm32mp1/stm32mp1_dbgmcu.c -+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c -@@ -1,9 +1,10 @@ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -+#include - #include - #include - #include -@@ -16,8 +17,12 @@ - #include - - #define DBGMCU_IDC 0x0U --#define IDC_DEV_ID_MASK GENMASK(11, 0) - #define DBGMCU_APB4FZ1 0x2CU -+ -+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0) -+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16) -+#define DBGMCU_IDC_REV_ID_SHIFT 16 -+ - #define DBGMCU_APB4FZ1_IWDG2 BIT(2) - - #define TAMP_DBG_BACKUP_REG_ID 20 -@@ -55,6 +60,10 @@ static int stm32mp1_dbgmcu_init(void) - } - - #if STM32MP1_DEBUG_ENABLE -+/* -+ * @brief Get debug mode information from backup registers. -+ * @retval 1 if debug mode is enabled, 0 otherwise. -+ */ - int stm32mp1_dbgmcu_boot_debug_info(void) - { - uint32_t backup_reg_dbg; -@@ -73,7 +82,11 @@ int stm32mp1_dbgmcu_boot_debug_info(void) - return 0; - } - --int stm32mp1_dbgmcu_clear_boot_info(void) -+/* -+ * @brief Clear debug mode information in backup registers. -+ * @retval None. -+ */ -+void stm32mp1_dbgmcu_clear_boot_info(void) - { - stm32mp_clk_enable(RTCAPB); - -@@ -81,20 +94,28 @@ int stm32mp1_dbgmcu_clear_boot_info(void) - TAMP_DBG_DEBUG); - - stm32mp_clk_disable(RTCAPB); -- -- return 0; - } - --uint32_t stm32mp1_dbgmcu_is_debug_on(void) -+/* -+ * @brief Get DBGMCU debug mode in BSEC registers. -+ * @retval True if debug mode enabled, false otherwise. -+ */ -+bool stm32mp1_dbgmcu_is_debug_on(void) - { - uint32_t dbg_conf; - - dbg_conf = bsec_read_debug_conf(); - -- return (dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN)); -+ return (dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN)) != 0U; - } - - #if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+/* -+ * @brief Dump 8-bits buffer content in hexadecimal. -+ * @param buf: Pointer to the 8-bits buffer. -+ * @parma len: Length in bytes of the dump. -+ * @retval None. -+ */ - void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len) - { - uint32_t i; -@@ -116,25 +137,48 @@ void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len) - #endif - #endif - --uint32_t stm32mp1_dbgmcu_get_chip_version(void) -+/* -+ * @brief Get silicon revision from DBGMCU registers. -+ * @param chip_version: pointer to the read value. -+ * @retval 0 on success, negative value on failure. -+ */ -+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version) - { -- if (stm32mp1_dbgmcu_init() == 0) { -- return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) >> 16); -+ assert(chip_version != NULL); -+ -+ if (stm32mp1_dbgmcu_init() != 0) { -+ return -EPERM; - } - -+ *chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & -+ DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT; -+ - return 0; - } - --uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void) -+/* -+ * @brief Get device ID from DBGMCU registers. -+ * @param chip_version: pointer to the read value. -+ * @retval 0 on success, negative value on failure. -+ */ -+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id) - { -- if (stm32mp1_dbgmcu_init() == 0) { -- return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & -- IDC_DEV_ID_MASK); -+ assert(chip_dev_id != NULL); -+ -+ if (stm32mp1_dbgmcu_init() != 0) { -+ return -EPERM; - } - -+ *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & -+ DBGMCU_IDC_DEV_ID_MASK; -+ - return 0; - } - -+/* -+ * @brief Freeze IWDG2 in debug mode. -+ * @retval None. -+ */ - int stm32mp1_dbgmcu_freeze_iwdg2(void) - { - if (stm32mp1_dbgmcu_init() == 0) { -diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h -index 7d7d773..f130eab 100644 ---- a/plat/st/stm32mp1/stm32mp1_def.h -+++ b/plat/st/stm32mp1/stm32mp1_def.h -@@ -8,12 +8,17 @@ - #define STM32MP1_DEF_H - - #ifndef __ASSEMBLY__ -+#include - #include - #include - #include - #include - #include - #include -+#include -+#include -+#include -+#include - #include - #include - #include -@@ -29,6 +34,7 @@ - #include - #include - #include -+#include - #endif - #include - #include -@@ -45,9 +51,16 @@ - #define STM32MP153A_PART_NB U(0x05000025) - #define STM32MP151C_PART_NB U(0x0500002E) - #define STM32MP151A_PART_NB U(0x0500002F) -+#define STM32MP157F_PART_NB U(0x05000080) -+#define STM32MP157D_PART_NB U(0x05000081) -+#define STM32MP153F_PART_NB U(0x050000A4) -+#define STM32MP153D_PART_NB U(0x050000A5) -+#define STM32MP151F_PART_NB U(0x050000AE) -+#define STM32MP151D_PART_NB U(0x050000AF) - - #define STM32MP1_REV_A U(0x1000) - #define STM32MP1_REV_B U(0x2000) -+#define STM32MP1_REV_Z U(0x2001) - - /******************************************************************************* - * PACKAGE ID -@@ -85,7 +98,7 @@ - #define STM32MP_DDR_BASE U(0xC0000000) - #define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ - #ifdef AARCH32_SP_OPTEE --#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */ -+#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ - #define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ - #else - #define STM32MP_DDR_S_SIZE U(0) /* DDR is non secure */ -@@ -122,9 +135,9 @@ enum ddr_type { - STM32MP_OPTEE_BASE) - #else - #if STACK_PROTECTOR_ENABLED --#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ -+#define STM32MP_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */ - #else --#define STM32MP_BL32_SIZE U(0x00010000) /* 64 Ko for BL32 */ -+#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ - #endif - #endif - -@@ -134,30 +147,35 @@ enum ddr_type { - - #ifdef AARCH32_SP_OPTEE - #if STACK_PROTECTOR_ENABLED --#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */ -+#define STM32MP_BL2_SIZE U(0x0001A000) /* 104 Ko for BL2 */ - #else --#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */ -+#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */ - #endif - #else - #if STACK_PROTECTOR_ENABLED --#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */ -+#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */ - #else --#define STM32MP_BL2_SIZE U(0x00016000) /* 88 Ko for BL2 */ -+#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */ - #endif - #endif - - #define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ - STM32MP_BL2_SIZE) - --/* BL2 and BL32/sp_min require 7 tables */ --#define MAX_XLAT_TABLES U(7) /* 28 Ko for mapping */ -+#if defined(STM32MP_USB) -+/* BL2 and BL32/sp_min require 5 finer granularity tables */ -+ #define MAX_XLAT_TABLES U(5) /* 20 Ko for mapping */ -+#else -+/* BL2 and BL32/sp_min require 4 finer granularity tables */ -+ #define MAX_XLAT_TABLES U(4) /* 16 Ko for mapping */ -+#endif - - /* - * MAX_MMAP_REGIONS is usually: - * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup - */ - #if defined(IMAGE_BL2) -- #if (defined STM32MP_USB) -+ #if defined(STM32MP_USB) - #define MAX_MMAP_REGIONS 12 - #else - #define MAX_MMAP_REGIONS 11 -@@ -365,21 +383,16 @@ enum ddr_type { - - #define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) - --/* OTP offsets */ --#define DATA0_OTP U(0) --#define PART_NUMBER_OTP U(1) --#define MONOTONIC_OTP U(4) --#define NAND_OTP U(9) --#define UID0_OTP U(13) --#define UID1_OTP U(14) --#define UID2_OTP U(15) --#define PACKAGE_OTP U(16) --#define HW2_OTP U(18) /* HW watchdog OTP */ -+/* OTP labels */ -+#define PART_NUMBER_OTP "part_number_otp" -+#define PACKAGE_OTP "package_otp" -+#define HW2_OTP "hw2_otp" -+#define NAND_OTP "nand_otp" -+#define MONOTONIC_OTP "monotonic_otp" -+#define UID_OTP "uid_otp" -+#define BOARD_ID_OTP "board_id" - - /* OTP mask */ --/* DATA0 */ --#define DATA0_OTP_SECURED BIT(6) -- - /* PART NUMBER */ - #define PART_SHIFT 0 - #define PART_MASK GENMASK_32(7, 0) -@@ -431,8 +444,12 @@ enum ddr_type { - #define NAND_ECC_BIT_NB_4_BITS 2 - #define NAND_ECC_BIT_NB_8_BITS 3 - -+/* MONOTONIC OTP */ - #define MAX_MONOTONIC_VALUE 32 - -+/* UID OTP */ -+#define UID_WORD_NB 3 -+ - /******************************************************************************* - * STM32MP1 FMC - ******************************************************************************/ -@@ -522,6 +539,14 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - #define TIM_MAX_INSTANCE U(2) - - /******************************************************************************* -+ * STM32MP1 OPP -+ ******************************************************************************/ -+#define PLAT_OPP_ID1 U(1) -+#define PLAT_OPP_ID2 U(2) -+#define PLAT_MAX_OPP_NB U(2) -+#define PLAT_MAX_PLLCFG_NB U(6) -+ -+/******************************************************************************* - * DEBUG - ******************************************************************************/ - /*#define ICACHE_OFF*/ -@@ -531,9 +556,12 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - /******************************************************************************* - * Device Tree defines - ******************************************************************************/ --#define DT_BSEC_COMPAT "st,stm32mp15-bsec" -+#define DT_NVMEM_LAYOUT_COMPAT "st,stm32-nvmem-layout" -+#define DT_OPP_COMPAT "operating-points-v2" - #define DT_PWR_COMPAT "st,stm32mp1-pwr" - #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" - #define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg" - -+#define DT_PLL1_NODE_NAME "st,pll@0" -+ - #endif /* STM32MP1_DEF_H */ -diff --git a/plat/st/stm32mp1/stm32mp1_helper_dbg.S b/plat/st/stm32mp1/stm32mp1_helper_dbg.S -index 32a86fb..6e88e5b 100644 ---- a/plat/st/stm32mp1/stm32mp1_helper_dbg.S -+++ b/plat/st/stm32mp1/stm32mp1_helper_dbg.S -@@ -10,6 +10,9 @@ - * fixes the limitation. Anyway, this source code identifies the Soc revision - * and is only executed if it corresponds, so it can be kept on other - * revisions without any consequence. -+ * The revisions that need the workaround have ID values: -+ * - 0x2000X500 -+ * - 0x2001X500 - ****************************************************************************/ - - /***************************************************************************** -@@ -18,6 +21,8 @@ - * other pieces of software. - ****************************************************************************/ - -+#include -+ - #define BIT_(nr) ((1) << (nr)) - - #define BSEC_BASE 0x5C005000 -@@ -27,7 +32,7 @@ - - #define DBGMCU_BASE 0x50081000 - #define DBGMCU_IDC 0x00 --#define DBGMCU_IDC_REV_ID_DEV_ID_MSK 0xFFFF0FFF -+#define DBGMCU_IDC_REV_ID_DEV_ID_MSK 0xFFFE0FFF - #define DBGMCU_IDC_REV_ID_DEV_ID_VALUE 0x20000500 - - #define RCC_BASE 0x50000000 -@@ -53,7 +58,7 @@ - .globl plat_dbg_attach_loop - - --plat_dbg_attach_loop: -+func plat_dbg_attach_loop - /* - * This function is the first call of FSBL_ENTRYPOINT. - * Boot rom parameters are stored in r0..r3, so we mustn't use them -@@ -225,3 +230,4 @@ msb_incr: - bmi loop - func_exit: - bx lr -+endfunc plat_dbg_attach_loop -diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c -index f8b35dd..48b7af6 100644 ---- a/plat/st/stm32mp1/stm32mp1_low_power.c -+++ b/plat/st/stm32mp1/stm32mp1_low_power.c -@@ -32,8 +32,7 @@ - #include - - static unsigned int gicc_pmr; --static struct stm32_rtc_calendar sleep_time, current_calendar; --static unsigned long long stdby_time_in_ms; -+static struct stm32_rtc_calendar sleep_time; - static bool enter_cstop_done; - static uint8_t int_stack[STM32MP_INT_STACK_SIZE]; - -@@ -101,11 +100,11 @@ void stm32_apply_pmic_suspend_config(uint32_t mode) - panic(); - } - -- if (dt_pmic_set_lp_config(node_name) != 0) { -+ if (pmic_set_lp_config(node_name) < 0) { - panic(); - } - -- if (dt_pmic_configure_boot_on_regulators() != 0) { -+ if (pmic_configure_boot_on_regulators() < 0) { - panic(); - } - } -@@ -131,6 +130,9 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) - - stm32mp1_syscfg_disable_io_compensation(); - -+ /* Switch to Software Self-Refresh */ -+ ddr_sr_mode_ssr(); -+ - dcsw_op_all(DC_OP_CISW); - - stm32_clean_context(); -@@ -225,6 +227,8 @@ void stm32_exit_cstop(void) - { - uintptr_t pwr_base = stm32mp_pwr_base(); - uintptr_t rcc_base = stm32mp_rcc_base(); -+ unsigned long long stdby_time_in_ms; -+ struct stm32_rtc_calendar current_calendar; - - if (!enter_cstop_done) { - return; -@@ -238,6 +242,9 @@ void stm32_exit_cstop(void) - panic(); - } - -+ /* Switch to Automatic Self-Refresh */ -+ ddr_sr_mode_asr(); -+ - plat_ic_set_priority_mask(gicc_pmr); - - /* Disable RCC Wake-up */ -@@ -259,7 +266,8 @@ void stm32_exit_cstop(void) - stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, - &sleep_time); - -- stm32mp1_stgen_increment(stdby_time_in_ms); -+ stm32mp1_stgen_restore_counter(stm32_get_stgen_from_context(), -+ stdby_time_in_ms); - - stm32mp1_syscfg_enable_io_compensation(); - } -diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c -index b95bc3d..e431199 100644 ---- a/plat/st/stm32mp1/stm32mp1_pm.c -+++ b/plat/st/stm32mp1/stm32mp1_pm.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 - */ -@@ -71,14 +71,8 @@ static int stm32_pwr_domain_on(u_register_t mpidr) - tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); - uint32_t bkpr_core1_magic = - tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); -- int result; - -- result = stm32mp_is_single_core(); -- if (result < 0) { -- return PSCI_E_INTERN_FAIL; -- } -- -- if (result == 1) { -+ if (stm32mp_is_single_core()) { - return PSCI_E_INTERN_FAIL; - } - -@@ -203,7 +197,7 @@ static void __dead2 stm32_system_off(void) - { - uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF); - -- if (stm32mp_is_single_core() == 0) { -+ if (!stm32mp_is_single_core()) { - /* Prepare Core 1 reset */ - mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, - RCC_MP_GRSTCSETR_MPUP1RST); -diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c -index ec7ecb1..d5dd671 100644 ---- a/plat/st/stm32mp1/stm32mp1_power_config.c -+++ b/plat/st/stm32mp1/stm32mp1_power_config.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 - */ -@@ -13,7 +13,6 @@ - #include - #include - --#define DT_PWR_COMPAT "st,stm32mp1-pwr" - #define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes" - #define SYSTEM_OFF_MODE "system_off_soc_mode" - -@@ -21,9 +20,9 @@ static uint32_t deepest_system_suspend_mode; - static uint32_t system_off_mode; - static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE]; - --static int dt_get_pwr_node(void *fdt) -+static int dt_get_pwr_node(void) - { -- return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ return dt_get_node_by_compatible(DT_PWR_COMPAT); - } - - static void save_supported_mode(void *fdt, int pwr_node) -@@ -77,7 +76,7 @@ static int dt_fill_lp_state(uint32_t *lp_state_config, const char *lp_state) - return -ENOENT; - } - -- pwr_node = dt_get_pwr_node(fdt); -+ pwr_node = dt_get_pwr_node(); - if (pwr_node < 0) { - return -FDT_ERR_NOTFOUND; - } -diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c -index aae537f..d399dc8 100644 ---- a/plat/st/stm32mp1/stm32mp1_private.c -+++ b/plat/st/stm32mp1/stm32mp1_private.c -@@ -15,6 +15,9 @@ - #include - #include - #include -+#include -+#include -+#include - #include - #include - -@@ -243,7 +246,7 @@ void __dead2 stm32mp_plat_reset(int cpu) - } - } - -- if (stm32mp_is_single_core() == 0) { -+ if (!stm32mp_is_single_core()) { - unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ? - STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU; - -@@ -266,38 +269,131 @@ void __dead2 stm32mp_plat_reset(int cpu) - stm32mp_wait_cpu_reset(); - } - --static uint32_t get_part_number(void) -+int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, -+ uint32_t *otp_len) - { -- uint32_t part_number = 0; -+ assert(otp_name != NULL); -+ assert(otp_idx != NULL); - -- if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) { -- ERROR("BSEC: PART_NUMBER_OTP Error\n"); -+ if (bsec_find_otp_name_in_dt(otp_name, otp_idx, otp_len) != BSEC_OK) { -+ ERROR("BSEC: Get %s number Error\n", otp_name); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val) -+{ -+ uint32_t otp; -+ -+ assert(otp_name != NULL); -+ assert(otp_val != NULL); -+ -+ if (stm32_get_otp_index(otp_name, &otp, NULL) != 0) { -+ return -1; -+ } -+ -+#if defined(IMAGE_BL2) -+ if (bsec_shadow_read_otp(otp_val, otp) != BSEC_OK) { -+ ERROR("BSEC: %s Read Error\n", otp_name); -+ return -1; -+ } -+#elif defined(IMAGE_BL32) -+ if (bsec_read_otp(otp_val, otp) != BSEC_OK) { -+ ERROR("BSEC: %s Read Error\n", otp_name); -+ return -1; -+ } -+#endif -+ -+ return 0; -+} -+ -+static int get_part_number(uint32_t *part_nb) -+{ -+ uint32_t part_number; -+ uint32_t dev_id; -+ -+ assert(part_nb != NULL); -+ -+ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) { -+ return -1; -+ } -+ -+ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) { - return -1; - } - - part_number = (part_number & PART_MASK) >> PART_SHIFT; - -- return (part_number | (stm32mp1_dbgmcu_get_chip_dev_id() << 16)); -+ *part_nb = part_number | (dev_id << 16); -+ -+ return 0; - } - --static uint32_t get_cpu_package(void) -+static int get_cpu_package(uint32_t *cpu_package) - { -- uint32_t package = 0; -+ uint32_t package; -+ -+ assert(cpu_package != NULL); - -- if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) { -- ERROR("BSEC: PART_NUMBER_OTP Error\n"); -+ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) { - return -1; - } - -- return ((package & PKG_MASK) >> PKG_SHIFT); -+ *cpu_package = (package & PKG_MASK) >> PKG_SHIFT; -+ -+ return 0; -+} -+ -+bool stm32mp_supports_cpu_opp(uint32_t opp_id) -+{ -+ uint32_t part_number; -+ uint32_t id; -+ -+ if (get_part_number(&part_number) != 0) { -+ ERROR("Cannot get part number\n"); -+ panic(); -+ } -+ -+ switch (opp_id) { -+ case PLAT_OPP_ID1: -+ case PLAT_OPP_ID2: -+ id = opp_id; -+ break; -+ default: -+ return false; -+ } -+ -+ switch (part_number) { -+ case STM32MP157F_PART_NB: -+ case STM32MP157D_PART_NB: -+ case STM32MP153F_PART_NB: -+ case STM32MP153D_PART_NB: -+ case STM32MP151F_PART_NB: -+ case STM32MP151D_PART_NB: -+ return true; -+ default: -+ return id == PLAT_OPP_ID1; -+ } - } - - void stm32mp_print_cpuinfo(void) - { - const char *cpu_s, *cpu_r, *pkg; -+ uint32_t part_number; -+ uint32_t cpu_package; -+ uint32_t chip_dev_id; -+ int ret; - - /* MPUs Part Numbers */ -- switch (get_part_number()) { -+ ret = get_part_number(&part_number); -+ if (ret < 0) { -+ WARN("Cannot get part number\n"); -+ return; -+ } -+ -+ switch (part_number) { - case STM32MP157C_PART_NB: - cpu_s = "157C"; - break; -@@ -316,13 +412,37 @@ void stm32mp_print_cpuinfo(void) - case STM32MP151A_PART_NB: - cpu_s = "151A"; - break; -+ case STM32MP157F_PART_NB: -+ cpu_s = "157F"; -+ break; -+ case STM32MP157D_PART_NB: -+ cpu_s = "157D"; -+ break; -+ case STM32MP153F_PART_NB: -+ cpu_s = "153F"; -+ break; -+ case STM32MP153D_PART_NB: -+ cpu_s = "153D"; -+ break; -+ case STM32MP151F_PART_NB: -+ cpu_s = "151F"; -+ break; -+ case STM32MP151D_PART_NB: -+ cpu_s = "151D"; -+ break; - default: - cpu_s = "????"; - break; - } - - /* Package */ -- switch (get_cpu_package()) { -+ ret = get_cpu_package(&cpu_package); -+ if (ret < 0) { -+ WARN("Cannot get CPU package\n"); -+ return; -+ } -+ -+ switch (cpu_package) { - case PKG_AA_LBGA448: - pkg = "AA"; - break; -@@ -341,13 +461,22 @@ void stm32mp_print_cpuinfo(void) - } - - /* REVISION */ -- switch (stm32mp1_dbgmcu_get_chip_version()) { -+ ret = stm32mp1_dbgmcu_get_chip_version(&chip_dev_id); -+ if (ret < 0) { -+ WARN("Cannot get CPU version\n"); -+ return; -+ } -+ -+ switch (chip_dev_id) { - case STM32MP1_REV_A: - cpu_r = "A"; - break; - case STM32MP1_REV_B: - cpu_r = "B"; - break; -+ case STM32MP1_REV_Z: -+ cpu_r = "Z"; -+ break; - default: - cpu_r = "?"; - break; -@@ -359,35 +488,8 @@ void stm32mp_print_cpuinfo(void) - void stm32mp_print_boardinfo(void) - { - 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_id, board_otp) != BSEC_OK) { -- ERROR("BSEC: PART_NUMBER_OTP Error\n"); -+ if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) { - return; - } - -@@ -404,22 +506,35 @@ void stm32mp_print_boardinfo(void) - } - } - --/* -- * This function determines if one single core is presently running. This is -- * done by OTP read. -- * Returns 1 if yes, 0 if more that one core is running, -1 if error. -- */ --int stm32mp_is_single_core(void) -+/* Return true when SoC provides a single Cortex-A7 core, and false otherwise */ -+bool stm32mp_is_single_core(void) - { -- uint32_t part_number = get_part_number(); -+ uint32_t part_number; - -- /* STM32MP151x is a single core */ -- if ((part_number == STM32MP151A_PART_NB) || -- (part_number == STM32MP151C_PART_NB)) { -- return 1; -+ if (get_part_number(&part_number) < 0) { -+ ERROR("Invalid part number, assume single core chip"); -+ return true; - } - -- return 0; -+ switch (part_number) { -+ case STM32MP151A_PART_NB: -+ case STM32MP151C_PART_NB: -+ case STM32MP151D_PART_NB: -+ case STM32MP151F_PART_NB: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+/* Return true if DDR supports Software/Automatic Self-Refresh */ -+bool stm32mp_ddr_supports_ssr_asr(void) -+{ -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ uint32_t mstr = mmio_read_32(ddrctrl_base + DDRCTRL_MSTR); -+ -+ return (mstr & DDRCTRL_MSTR_LPDDR2) != 0U; - } - - uint8_t stm32_iwdg_get_instance(uintptr_t base) -@@ -440,15 +555,9 @@ uint32_t stm32_iwdg_get_otp_config(uintptr_t base) - uint32_t iwdg_cfg = 0; - uint32_t otp_value; - --#if defined(IMAGE_BL2) -- if (bsec_shadow_read_otp(&otp_value, HW2_OTP) != BSEC_OK) { -+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { - panic(); - } --#elif defined(IMAGE_BL32) -- if (bsec_read_otp(&otp_value, HW2_OTP) != BSEC_OK) { -- panic(); -- } --#endif - - idx = stm32_iwdg_get_instance(base); - -@@ -471,31 +580,36 @@ uint32_t stm32_iwdg_get_otp_config(uintptr_t base) - uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags) - { - uint32_t idx; -+ uint32_t otp_value; - uint32_t otp; - uint32_t result; - -- if (bsec_shadow_read_otp(&otp, HW2_OTP) != BSEC_OK) { -+ if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) { -+ panic(); -+ } -+ -+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { - panic(); - } - - idx = stm32_iwdg_get_instance(base); - - if ((flags & IWDG_DISABLE_ON_STOP) != 0) { -- otp |= BIT(idx + IWDG_FZ_STOP_POS); -+ otp_value |= BIT(idx + IWDG_FZ_STOP_POS); - } - - if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) { -- otp |= BIT(idx + IWDG_FZ_STANDBY_POS); -+ otp_value |= BIT(idx + IWDG_FZ_STANDBY_POS); - } - -- result = bsec_write_otp(otp, HW2_OTP); -+ result = bsec_write_otp(otp_value, otp); - if (result != BSEC_OK) { - return result; - } - - /* Sticky lock OTP_IWDG (read and write) */ -- if ((bsec_set_sr_lock(HW2_OTP) != BSEC_OK) || -- (bsec_set_sw_lock(HW2_OTP) != BSEC_OK)) { -+ if ((bsec_set_sr_lock(otp) != BSEC_OK) || -+ (bsec_set_sw_lock(otp) != BSEC_OK)) { - return BSEC_LOCK_FAIL; - } - -@@ -524,3 +638,26 @@ enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode) - panic(); - } - } -+ -+int plat_bind_regulator(struct stm32mp_regulator *regu) -+{ -+ void *fdt; -+ int regu_node; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return false; -+ } -+ -+ if ((dt_pmic_status() > 0) && is_pmic_regulator(regu)) { -+ bind_pmic_regulator(regu); -+ } else { -+ bind_dummy_regulator(regu); -+ } -+ -+ regu_node = fdt_node_offset_by_phandle(fdt, regu->id); -+ if (fdt_getprop(fdt, regu_node, "regulator-always-on", NULL) != NULL) { -+ regu->always_on = true; -+ } -+ -+ return 0; -+} -diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c -index d2da110..9ad9486 100644 ---- a/plat/st/stm32mp1/stm32mp1_security.c -+++ b/plat/st/stm32mp1/stm32mp1_security.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 - */ -@@ -24,6 +24,7 @@ static void init_tzc400(void) - unsigned long long region_base, region_top; - unsigned long long ddr_base = STM32MP_DDR_BASE; - unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size(); -+ unsigned long long ddr_top = ddr_base + (ddr_size - 1U); - - tzc400_init(STM32MP1_TZC_BASE); - -@@ -35,7 +36,7 @@ static void init_tzc400(void) - * same configuration to all filters in the TZC. - */ - region_base = ddr_base; -- region_top = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE - 1U); -+ region_top = ddr_top - STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE; - tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, - region_base, - region_top, -@@ -53,8 +54,8 @@ static void init_tzc400(void) - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)); - - /* Region 2 set to cover all secure DRAM. */ -- region_base = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE); -- region_top = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE - 1U); -+ region_base = region_top + 1U; -+ region_top = ddr_top - STM32MP_DDR_SHMEM_SIZE; - tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2, - region_base, - region_top, -@@ -62,8 +63,8 @@ static void init_tzc400(void) - 0); - - /* Region 3 set to cover non-secure shared memory DRAM. */ -- region_base = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE); -- region_top = ddr_base + (ddr_size - 1U); -+ region_base = region_top + 1U; -+ region_top = ddr_top; - tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3, - region_base, - region_top, -@@ -85,7 +86,7 @@ static void init_tzc400(void) - * same configuration to all filters in the TZC. - */ - region_base = ddr_base; -- region_top = ddr_base + (ddr_size - 1U); -+ region_top = ddr_top; - tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, - region_base, - region_top, -@@ -103,8 +104,11 @@ static void init_tzc400(void) - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)); - #endif - -- /* Raise an exception if a NS device tries to access secure memory */ -- tzc400_set_action(TZC_ACTION_ERR); -+ /* -+ * Raise an interrupt (secure FIQ) if a NS device tries to access -+ * secure memory -+ */ -+ tzc400_set_action(TZC_ACTION_INT); - - tzc400_enable_filters(); - } -diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c -index 3276870..47a16ac 100644 ---- a/plat/st/stm32mp1/stm32mp1_syscfg.c -+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c -@@ -4,18 +4,18 @@ - * SPDX-License-Identifier: BSD-3-Clause - */ - --#include - #include - #include - #include - #include -+#include - #include - #include - #include - #include - - /* -- * SYSCFG REGISTER OFFSET (base relative) -+ * SYSCFG register offsets (base relative) - */ - #define SYSCFG_BOOTR 0x00U - #define SYSCFG_IOCTRLSETR 0x18U -@@ -52,6 +52,8 @@ - #define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) - #define SYSCFG_CMPCR_ANSRC_SHIFT 24 - -+#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U -+ - /* - * SYSCFG_CMPENSETR Register - */ -@@ -60,9 +62,10 @@ - void stm32mp1_syscfg_init(void) - { - uint32_t bootr; -- uint32_t otp = 0; -+ uint32_t otp_value; - uint32_t vdd_voltage; - uintptr_t syscfg_base = dt_get_syscfg_base(); -+ bool product_below_2v5; - - /* - * Interconnect update : select master using the port 1. -@@ -96,11 +99,11 @@ void stm32mp1_syscfg_init(void) - * => 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) { -+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { - panic(); - } - -- otp = otp & HW2_OTP_PRODUCT_BELOW_2V5; -+ product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U; - - /* Get VDD supply */ - vdd_voltage = dt_get_pwr_vdd_voltage(); -@@ -117,11 +120,11 @@ void stm32mp1_syscfg_init(void) - SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | - SYSCFG_IOCTRLSETR_HSLVEN_SPI); - -- if (otp == 0U) { -+ if (!product_below_2v5) { - INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); - } - } else { -- if (otp != 0U) { -+ if (product_below_2v5) { - ERROR("Product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n"); - panic(); - } -@@ -137,6 +140,7 @@ void stm32mp1_syscfg_init(void) - void stm32mp1_syscfg_enable_io_compensation(void) - { - uintptr_t syscfg_base = dt_get_syscfg_base(); -+ uint64_t start; - - /* - * Activate automatic I/O compensation. -@@ -148,9 +152,18 @@ void stm32mp1_syscfg_enable_io_compensation(void) - mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR, - SYSCFG_CMPENSETR_MPU_EN); - -+ start = timeout_start(); -+ - while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & - SYSCFG_CMPCR_READY) == 0U) { -- ; -+ if (timeout_elapsed(start, SYSCFG_CMPCR_READY_TIMEOUT_US)) { -+ /* -+ * Failure on IO compensation enable is not a issue: -+ * warn only. -+ */ -+ WARN("IO compensation cell not ready\n"); -+ break; -+ } - } - - mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); -@@ -180,9 +193,7 @@ void stm32mp1_syscfg_disable_io_compensation(void) - 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); -+ mmio_write_32(syscfg_base + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); - - VERBOSE("[0x%x] SYSCFG.cmpcr = 0x%08x\n", - (uint32_t)syscfg_base + SYSCFG_CMPCR, -diff --git a/plat/st/stm32mp1/stm32mp1_usb_desc.c b/plat/st/stm32mp1/stm32mp1_usb_desc.c -index 410cfa1..25246e9 100644 ---- a/plat/st/stm32mp1/stm32mp1_usb_desc.c -+++ b/plat/st/stm32mp1/stm32mp1_usb_desc.c -@@ -1,12 +1,14 @@ - /* -- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -148,10 +150,22 @@ static void update_serial_num_string(void) - { - /* serial number is set to 0*/ - uint8_t i; -- uint32_t deviceserial[3] = {0, 0, 0}; -+ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U}; -+ uint32_t otp; -+ uint32_t len; - -- for (i = 0; i < 3; i++) { -- if (bsec_shadow_read_otp(&deviceserial[i], i + UID0_OTP) != -+ if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) { -+ ERROR("BSEC: Get UID_OTP number Error\n"); -+ return; -+ } -+ -+ if ((len / __WORD_BIT) != UID_WORD_NB) { -+ ERROR("BSEC: Get UID_OTP length Error\n"); -+ return; -+ } -+ -+ for (i = 0; i < UID_WORD_NB; i++) { -+ if (bsec_shadow_read_otp(&deviceserial[i], i + otp) != - BSEC_OK) { - ERROR("BSEC: UID%d Error\n", i); - return; -diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c -index 41024e2..e80bf0b 100644 ---- a/tools/stm32image/stm32image.c -+++ b/tools/stm32image/stm32image.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -45,8 +45,6 @@ struct stm32_header { - uint8_t binary_type; - }; - --static struct stm32_header stm32image_header; -- - static void stm32image_default_header(struct stm32_header *ptr) - { - if (!ptr) { -@@ -56,8 +54,8 @@ static void stm32image_default_header(struct stm32_header *ptr) - ptr->magic_number = HEADER_MAGIC; - ptr->header_version[VER_MAJOR] = HEADER_VERSION_V1; - ptr->option_flags = HEADER_DEFAULT_OPTION; -- ptr->ecdsa_algorithm = 1; -- ptr->version_number = 0; -+ ptr->ecdsa_algorithm = __cpu_to_le32(1); -+ ptr->version_number = __cpu_to_le32(0); - ptr->binary_type = TF_BINARY_TYPE; - } - -@@ -115,7 +113,8 @@ static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, - stm32hdr->image_entry_point = __cpu_to_le32(ep); - stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - - sizeof(struct stm32_header)); -- stm32hdr->image_checksum = stm32image_checksum(ptr, sbuf->st_size); -+ stm32hdr->image_checksum = -+ __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size)); - stm32hdr->version_number = __cpu_to_le32(ver); - } - -@@ -126,6 +125,7 @@ static int stm32image_create_header_file(char *srcname, char *destname, - int src_fd, dest_fd; - struct stat sbuf; - unsigned char *ptr; -+ struct stm32_header stm32image_header; - - dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); - if (dest_fd == -1) { -@@ -204,13 +204,13 @@ int main(int argc, char *argv[]) - dest = optarg; - break; - case 'l': -- loadaddr = strtol(optarg, NULL, 16); -+ loadaddr = strtol(optarg, NULL, 0); - break; - case 'e': -- entry = strtol(optarg, NULL, 16); -+ entry = strtol(optarg, NULL, 0); - break; - case 'v': -- version = strtol(optarg, NULL, 10); -+ version = strtol(optarg, NULL, 0); - break; - default: - fprintf(stderr, --- -2.7.4 - diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/README.HOW_TO.txt b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/README.HOW_TO.txt index 3039a77..a186b64 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/README.HOW_TO.txt +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/README.HOW_TO.txt @@ -16,17 +16,17 @@ For tf-a build you need to install: Fedora: sudo yum install git If you have never configured you git configuration: - $> git config --global user.name "your_name" - $> git config --global user.email "your_email@example.com" + $ git config --global user.name "your_name" + $ git config --global user.email "your_email@example.com" 2. Initialise cross-compilation via SDK: --------------------------------------- Source SDK environment: - $> source /environment-setup-cortexa7t2hf-neon-vfpv4-openstlinux_weston-linux-gnueabi + $ source /environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi To verify if your cross-compilation environment have put in place: - $> set | grep CROSS - CROSS_COMPILE=arm-openstlinux_weston-linux-gnueabi- + $ set | grep CROSS + CROSS_COMPILE=arm-ostl-linux-gnueabi- Warning: the environment are valid only on the shell session where you have sourced the sdk environment. @@ -35,48 +35,46 @@ sourced the sdk environment. ------------------------ If you have the tarball and the list of patch then you must extract the tarball and apply the patch. - $> tar xfz .tar.gz - or - $> tar xfj .tar.bz2 - or - $> tar xfJ .tar.xz + $> tar xfz ##BP##-##PR##.tar.gz A new directory containing tf-a standard source code will be created, go into it: - $> cd + $> cd ##BP## NB: if there is no git management on source code and you would like to have a git management on the code see section 4 [Management of tf-a source code] if there is some patch, please apply it on source code - $> for p in `ls -1 /*.patch`; do patch -p1 < $p; done + $> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done 4. Management of tf-a source code: ----------------------------------- If you like to have a better management of change made on tf-a source, you can use git: - $> cd - $> test -d .git || git init . && git add . && git commit -m "tf-a source code" && git gc - $> git checkout -b WORKING - $> for p in `ls -1 /*.patch`; do git am $p; done + $ cd + $ test -d .git || git init . && git add . && git commit -m "tf-a source code" && git gc + $ git checkout -b WORKING + $ for p in `ls -1 /*.patch`; do git am $p; done NB: you can use directly the source from the community: URL: git://github.com/ARM-software/arm-trusted-firmware.git Branch: ##GIT_BRANCH## Revision: ##GIT_SRCREV## - $> git clone git://github.com/ARM-software/arm-trusted-firmware.git -b ##GIT_BRANCH## - $> cd - $> git checkout -b WORKING ##GIT_SRCREV## - $> for p in `ls -1 /*.patch`; do git am $p; done + $ git clone git://github.com/ARM-software/arm-trusted-firmware.git -b ##GIT_BRANCH## + $ cd + $ git checkout -b WORKING ##GIT_SRCREV## + $ for p in `ls -1 /*.patch`; do git am $p; done 5. Build tf-a source code: -------------------------------- To compile tf-a source code - $> cd $> make -f $PWD/../Makefile.sdk all or for a specific config : - $> make -f $PWD/../Makefile.sdk TFA_DEVICETREE=stm32mp157c-ev1 TF_A_CONFIG=trusted ELF_DEBUG_ENABLE='1' all + $ make -f $PWD/../Makefile.sdk TFA_DEVICETREE=stm32mp157c-ev1 TF_A_CONFIG=trusted ELF_DEBUG_ENABLE='1' all NB: TFA_DEVICETREE flag must be set to switch to correct board configuration. +Files generated should be as follow: + #> ../build/*/tf-a-*.stm32 + 6. Update software on board: ---------------------------- 6.1. partitioning of binaries: @@ -90,11 +88,11 @@ Copy the binary (tf-a-*.stm32) on the dedicated partition, on SDCARD/USB disk the partition "fsbl1" are the partition 1: - SDCARD: /dev/mmcblkXp1 (where X is the instance number) - SDCARD via USB reader: /dev/sdX1 (where X is the instance number) - $> dd if= of=/dev/ bs=1M conv=fdatasync + $ dd if= of=/dev/ bs=1M conv=fdatasync FAQ: to found the partition associated to a specific label, just plug the SDCARD/USB disk on your PC and call the following command: - $> ls -l /dev/disk/by-partlabel/ + $ ls -l /dev/disk/by-partlabel/ total 0 lrwxrwxrwx 1 root root 10 Jan 17 17:38 bootfs -> ../../mmcblk0p4 lrwxrwxrwx 1 root root 10 Jan 17 17:38 fsbl1 -> ../../mmcblk0p1 ➔ FSBL (TF-A) @@ -117,4 +115,4 @@ lrwxrwxrwx 1 root root 10 Jan 17 17:38 userfs -> ../../mmcblk0p6 For SDCARD: ums 0 mmc 0 For USB disk: ums 0 usb 0 -* Follow section 6.2 to put tf-a-*.stm32 on SDCARD/USB disk +* Follow section 6.2 to put tf-a-*.stm32 on SDCARD/USB disk \ No newline at end of file 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 deleted file mode 100644 index f237585..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.0.bb +++ /dev/null @@ -1,42 +0,0 @@ -SUMMARY = "Trusted Firmware-A for STM32MP1" -SECTION = "bootloaders" -LICENSE = "BSD-3-Clause" -LIC_FILES_CHKSUM = "file://license.rst;md5=e927e02bca647e14efd87e9e914b2443" - -SRC_URI = "https://github.com/ARM-software/arm-trusted-firmware/archive/v${PV}.tar.gz" -SRC_URI[md5sum] = "21038abbf572c273fa87d296bcd5dad2" -SRC_URI[sha256sum] = "7d699a1683bb7a5909de37b6eb91b6e38db32cd6fc5ae48a08eb0718d6504ae4" - -SRC_URI += " \ - file://0001-st-update-r1.patch \ - file://0002-st-update-r1.1.0.patch \ - file://0003-st-update-r1.2.0.patch \ - " - -TF_VERSION = "2.0" -PV = "${TF_VERSION}" - -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 = "5148fa0d1272cdf714ba0d7f0c38e0f72fa27020" -SRCREV_FORMAT_class-devupstream = "tfa" -PV_class-devupstream = "${TF_VERSION}+github+${SRCPV}" -# --------------------------------- -# Configure default preference to manage dynamic selection between tarball and github -# --------------------------------- -STM32MP_SOURCE_SELECTION ?= "tarball" - -DEFAULT_PREFERENCE = "${@bb.utils.contains('STM32MP_SOURCE_SELECTION', 'github', '-1', '1', d)}" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.2.bb b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.2.bb new file mode 100644 index 0000000..6e5760d --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.2.bb @@ -0,0 +1,26 @@ +require tf-a-stm32mp-common_${PV}.inc +require tf-a-stm32mp-common.inc + +SUMMARY = "Trusted Firmware-A for STM32MP1" +LICENSE = "BSD-3-Clause" + +PROVIDES += "virtual/trusted-firmware-a" + +# Configure stm32mp1 make settings +EXTRA_OEMAKE += 'PLAT=stm32mp1' +EXTRA_OEMAKE += 'ARCH=aarch32' +EXTRA_OEMAKE += 'ARM_ARCH_MAJOR=7' +# Configure default mode (All supported device type) +EXTRA_OEMAKE += 'STM32MP_SDMMC=1' +EXTRA_OEMAKE += 'STM32MP_EMMC=1' +EXTRA_OEMAKE += 'STM32MP_SPI_NOR=1' +EXTRA_OEMAKE += 'STM32MP_RAW_NAND=1' +EXTRA_OEMAKE += 'STM32MP_SPI_NAND=1' + +# Enable the wrapper for debug +TF_A_ENABLE_DEBUG_WRAPPER ?= "1" + +# --------------------------------- +# Configure archiver use +# --------------------------------- +include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'tf-a-stm32mp-archiver.inc','')}