From 4e63a23ff6b9b9cb51aaec90589ef6a3e44a905f Mon Sep 17 00:00:00 2001 From: Christophe Priouzeau Date: Mon, 6 Jun 2022 15:15:43 +0200 Subject: [PATCH] TF-A: v2.6-stm32mp1-r1 Signed-off-by: Christophe Priouzeau Change-Id: I23dff9a9a33a1094bfcf01c2fa8e555f349d0782 --- .../tf-a-stm32mp-archiver.inc | 83 +- .../tf-a-stm32mp-common.inc | 119 +- .../tf-a-stm32mp-config.inc | 18 +- .../0001-correct-DTC-version-detection.patch | 26 - .../0001-st-update-v2.4-r1.0.0.patch | 37632 ----------- .../tf-a-stm32mp/0001-v2.6-stm32mp-r1.patch | 55558 ++++++++++++++++ .../0002-v2.4-stm32mp-r1.1-rc1.patch | 157 - .../tf-a-stm32mp/0003-v2.4-stm32mp-r2.patch | 8216 --- ...0099-Modify-Reset-reason-trace-level.patch | 25 + .../tf-a-stm32mp/README.HOW_TO.txt | 85 +- .../tf-a-stm32mp_%.bbappend | 3 + ...f-a-stm32mp_2.4.bb => tf-a-stm32mp_2.6.bb} | 18 +- ...se-a-root-key-password-from-command-.patch | 70 +- .../{tf-a-tools_2.4.bb => tf-a-tools_2.6.bb} | 4 +- 14 files changed, 55773 insertions(+), 46241 deletions(-) delete mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-correct-DTC-version-detection.patch delete mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.4-r1.0.0.patch create mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-v2.6-stm32mp-r1.patch delete mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-v2.4-stm32mp-r1.1-rc1.patch delete mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-v2.4-stm32mp-r2.patch create mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0099-Modify-Reset-reason-trace-level.patch create mode 100644 recipes-bsp/trusted-firmware-a/tf-a-stm32mp_%.bbappend rename recipes-bsp/trusted-firmware-a/{tf-a-stm32mp_2.4.bb => tf-a-stm32mp_2.6.bb} (80%) rename recipes-bsp/trusted-firmware-a/{tf-a-tools_2.4.bb => tf-a-tools_2.6.bb} (92%) 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 77f5976..7e6fc7b 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-archiver.inc @@ -23,15 +23,8 @@ FWCONFIG_DEPLOYDIR ?= \$(DEPLOYDIR)/fwconfig # Configure default TF-A features TF_A_ENABLE_DEBUG_WRAPPER ?= ${TF_A_ENABLE_DEBUG_WRAPPER} -# Configure FIP -ENABLE_FIP ?= ${@bb.utils.contains('MACHINE_FEATURES', 'fip', '1', '', d)} - # Set default TF-A config -ifeq (\$(ENABLE_FIP), 1) TF_A_CONFIG ?= ${TF_A_CONFIG} -else -TF_A_CONFIG ?= ${BOOTSCHEME_LABELS} ${TF_A_CONFIG_4LEGACY} -endif # Default TF-A overall settings to null TF_A_BINARY ?= @@ -39,7 +32,8 @@ TF_A_DEVICETREE ?= TF_A_MAKE_TARGET ?= TF_A_EXTRA_OPTFLAGS ?= -ifeq (\$(ENABLE_FIP), 1) +# Default TF-A metadata template +TF_A_METADATA_JSON ?= \$(SRC_PATH)/${TF_A_METADATA_JSON} EOF unset i @@ -55,45 +49,6 @@ TF_A_MAKE_TARGET_$config ?= $(echo ${TF_A_MAKE_TARGET} | cut -d',' -f${i}) EOF done cat << EOF >> ${ARCHIVER_OUTDIR}/Makefile.sdk -else - -EOF - for bootscheme in ${BOOTSCHEME_LABELS}; do - unset i - for config in ${TF_A_CONFIG}; do - i=$(expr $i + 1) - if [ "$bootscheme" = "$config" ]; then - cat << EOF >> ${ARCHIVER_OUTDIR}/Makefile.sdk -# Init default config settings -TF_A_DEVICETREE_$config ?= $(echo ${TF_A_DEVICETREE} | cut -d',' -f${i}) -TF_A_EXTRA_OPTFLAGS_$config ?= $(echo ${TF_A_EXTRA_OPTFLAGS} | cut -d',' -f${i}) ${TF_A_EXTRACONF_LEGACY} -TF_A_BINARY_$config ?= $(echo ${TF_A_BINARIES} | cut -d',' -f${i}) -TF_A_MAKE_TARGET_$config ?= - -EOF - fi - done - done - - cat << EOF >> ${ARCHIVER_OUTDIR}/Makefile.sdk -TF_A_DEVICETREE_$(echo ${TF_A_CONFIG_4LEGACY} | xargs) ?= -TF_A_EXTRA_OPTFLAGS_$(echo ${TF_A_CONFIG_4LEGACY} | xargs) ?= -TF_A_BINARY_$(echo ${TF_A_CONFIG_4LEGACY} | xargs) ?= -TF_A_MAKE_TARGET_$(echo ${TF_A_CONFIG_4LEGACY} | xargs) ?= - -ifeq (\$(TF_A_DEVICETREE_$(echo ${TF_A_CONFIG_4LEGACY} | xargs)),) -\$(error "Please, define the variable TF_A_DEVICETREE_$(echo ${TF_A_CONFIG_4LEGACY} | xargs)") -endif - -ifeq (\$(TF_A_EXTRA_OPTFLAGS_$(echo ${TF_A_CONFIG_4LEGACY} | xargs)),) -\$(error "Please, define the variable TF_A_EXTRA_OPTFLAGS_$(echo ${TF_A_CONFIG_4LEGACY} | xargs)") -endif - -ifeq (\$(TF_A_BINARY_$(echo ${TF_A_CONFIG_4LEGACY} | xargs)),) -\$(error "Please, define the variable TF_A_BINARY_$(echo ${TF_A_CONFIG_4LEGACY} | xargs)") -endif - -endif # Reset default variables LDFLAGS = @@ -108,9 +63,6 @@ NM = # Define default make options EXTRA_OEMAKE ?= ${EXTRA_OEMAKE} -# Configure overall devicetree list for FIP -TF_A_DEVICETREE_ALL = $(echo "${TF_A_DEVICETREE}" | sed 's/,/ /g' | xargs -n1 | sort -u | xargs) - # Display TF-A config details define tf-configs echo " \$(1)" ; \\ @@ -172,9 +124,8 @@ endef # Set dependencies list for building all DEPS = \$(addprefix deploy-,\$(TF_A_CONFIG)) -ifeq (\$(ENABLE_FIP), 1) DEPS += fip -endif +DEPS += metadata help: @echo @@ -200,16 +151,17 @@ help: @echo " FWCONFIG_DEPLOYDIR = \$(DEPLOYDIR)/fwconfig" @echo @echo "FIP configuration:" - @echo " ENABLE_FIP = \$(ENABLE_FIP) ('1' to generate fip binary)" -ifeq (\$(ENABLE_FIP),1) @echo " Do not forget to set FIP deploydir folders (such as FIP_DEPLOYDIR_ROOT) to provide path to needed binaries" -endif + @echo + @echo "METADATA configuration:" + @echo " TF_A_METADATA_JSON = \$(TF_A_METADATA_JSON)" @echo @echo "Available targets:" - @echo " all : build TF-A binaries for defined config(s)" - @echo " fip : build FIP binaries" - @echo " stm32 : build TF-A stm32 binaries" - @echo " clean : clean build directories from generated files" + @echo " all : build TF-A binaries for defined config(s)" + @echo " fip : build FIP binaries" + @echo " metadata : build the TF-A metadata binary" + @echo " stm32 : build TF-A stm32 binaries" + @echo " clean : clean build directories from generated files" @echo all: \$(DEPS) @@ -224,10 +176,21 @@ host_tools: \$(foreach config, \$(TF_A_CONFIG), \$(eval \$(call deploy-rules,\$(config),\$(if \$(TF_A_BINARY),\$(TF_A_BINARY),\$(TF_A_BINARY_\$(config)))))) fip: \$(addprefix deploy-,\$(TF_A_CONFIG)) - FIP_DEPLOYDIR_TFA=\$(BL32_DEPLOYDIR) FIP_DEPLOYDIR_FWCONF=\$(FWCONFIG_DEPLOYDIR) FIP_DEVICETREE="\$(if \$(TF_A_DEVICETREE),\$(TF_A_DEVICETREE),\$(TF_A_DEVICETREE_ALL))" fiptool-stm32mp + for config in \$(TF_A_CONFIG) ; do \\ + if [ "\$\$config" = "trusted" ]; then \\ + FIP_DEPLOYDIR_TFA=\$(BL32_DEPLOYDIR) FIP_DEPLOYDIR_FWCONF=\$(FWCONFIG_DEPLOYDIR) FIP_DEVICETREE="\$(if \$(TF_A_DEVICETREE),\$(TF_A_DEVICETREE),\$(TF_A_DEVICETREE_trusted))" FIP_CONFIG="trusted" FIP_BL32_CONF="tfa" fiptool-stm32mp ; \\ + fi ; \\ + if [ "\$\$config" = "optee" ]; then \\ + FIP_DEPLOYDIR_TFA=\$(BL32_DEPLOYDIR) FIP_DEPLOYDIR_FWCONF=\$(FWCONFIG_DEPLOYDIR) FIP_DEVICETREE="\$(if \$(TF_A_DEVICETREE),\$(TF_A_DEVICETREE),\$(TF_A_DEVICETREE_optee))" FIP_CONFIG="optee" FIP_BL32_CONF="optee" fiptool-stm32mp ; \\ + fi ; \\ + done stm32: \$(addprefix deploy-,\$(TF_A_CONFIG)) +metadata: + @mkdir -p \$(DEPLOYDIR) + \$(SRC_PATH)/${TF_A_METADATA_TOOL} jsonparse "\$(TF_A_METADATA_JSON)" -b \$(DEPLOYDIR)/${TF_A_METADATA_BINARY} + clean: @for config in \$(TF_A_CONFIG) ; do \\ echo "Removing \$(BLD_PATH)/\$\$config ..." ; \\ 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 9732da5..565ac79 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-common.inc @@ -3,7 +3,7 @@ PACKAGE_ARCH = "${MACHINE_ARCH}" FILESEXTRAPATHS:prepend := "${THISDIR}/tf-a-stm32mp:" inherit deploy -inherit ${@bb.utils.contains('MACHINE_FEATURES', 'fip', 'fip-utils-stm32mp', '', d)} +inherit fip-utils-stm32mp # Include TF-A config definitions include tf-a-stm32mp-config.inc @@ -33,7 +33,9 @@ DEPENDS += "dtc-native" DEPENDS:append = " ${@bb.utils.contains('TF_A_ENABLE_DEBUG_WRAPPER', '1', 'stm32wrapper4dbg-native', '', d)}" # Default log level -ST_TF_A_DEBUG_LOG_LEVEL ??= "40" +ST_TF_A_DEBUG ??= "1" +ST_TF_A_LOG_LEVEL_RELEASE ??= "20" +ST_TF_A_LOG_LEVEL_DEBUG ??= "40" # Configure make settings EXTRA_OEMAKE += 'PLAT=${TFA_PLATFORM}' @@ -41,8 +43,8 @@ EXTRA_OEMAKE += 'ARCH=${TFA_ARM_ARCH}' EXTRA_OEMAKE += 'ARM_ARCH_MAJOR=${TFA_ARM_MAJOR}' EXTRA_OEMAKE += 'CROSS_COMPILE=${TARGET_PREFIX}' # Debug support -EXTRA_OEMAKE += '${@bb.utils.contains('ST_TF_A_DEBUG_TRACE', '1', 'DEBUG=1', '', d)}' -EXTRA_OEMAKE += '${@bb.utils.contains('ST_TF_A_DEBUG_TRACE', '1', 'LOG_LEVEL=${ST_TF_A_DEBUG_LOG_LEVEL}', '', d)}' +EXTRA_OEMAKE += "${@bb.utils.contains('ST_TF_A_DEBUG_TRACE', '1', 'DEBUG=${ST_TF_A_DEBUG}', '', d)}" +EXTRA_OEMAKE += "${@bb.utils.contains('ST_TF_A_DEBUG_TRACE', '1', 'LOG_LEVEL=${ST_TF_A_LOG_LEVEL_DEBUG}', 'LOG_LEVEL=${ST_TF_A_LOG_LEVEL_RELEASE}', d)}" # Define default TF-A namings TF_A_BASENAME ?= "tf-a" @@ -85,10 +87,21 @@ TF_A_ENABLE_DEBUG_WRAPPER ??= "1" # Set default configuration to allow signing TF_A_SIGN_ENABLE ??= "0" +TF_A_ENCRYPTED_ENABLE ??= "0" + +# Set metadata generation +TF_A_ENABLE_METADATA ??= "${@bb.utils.contains('MACHINE_FEATURES', 'fw-update', '1', '0', 'd')}" +TF_A_METADATA_NAME ?= "metadata" +TF_A_METADATA_SUFFIX ?= "bin" +TF_A_METADATA_BINARY ??= "${TF_A_METADATA_NAME}.${TF_A_METADATA_SUFFIX}" + +TF_A_METADATA_TOOL ?= "tools/fwu_gen_metadata/fwumd_tool.py" +TF_A_METADATA_JSON ?= "plat/st/stm32mp1/default_metadata.json" # Configure specific build flags EXTRA_OEMAKE += "${@bb.utils.contains('TF_A_SIGN_ENABLE', '1', 'TRUSTED_BOARD_BOOT=1', '', d)}" EXTRA_OEMAKE += "${@bb.utils.contains('TF_A_SIGN_ENABLE', '1', 'MBEDTLS_DIR=${TFA_MBEDTLS_DIR}', '', d)}" +EXTRA_OEMAKE += "${@bb.utils.contains('TF_A_ENCRYPTED_ENABLE', '1', 'DECRYPTION_SUPPORT=aes_gcm ENCRYPT_BL32=1', '', d)}" # ----------------------------------------------- # Handle TF-A config and set internal vars @@ -152,6 +165,14 @@ python () { else: d.appendVar('TF_A_FILES', 'bl2' + ',') break + + # Manage case of signature: + # If signature are activated, for winning space, the debug parameter will be remove and levele of trace decrease + signature_val = d.getVar('TF_A_SIGN_ENABLE') + if signature_val and signature_val == "1": + bb.warn("TF-A SIGNATURE: force to disable DEBUG and decrease log level") + # force no debug and log level to release + d.setVar('ST_TF_A_DEBUG_TRACE', "0") } # ----------------------------------------------- @@ -217,24 +238,29 @@ do_compile() { fi done fi - oe_runmake -C ${S} BUILD_PLAT=${B}/${config}${soc_suffix} DTB_FILE_NAME=${dt}.dtb ${extra_opt} ${soc_extra_opt} ${tf_a_make_target} + mkdir -p ${B}/${config}${soc_suffix} + oe_runmake -C "${S}" BUILD_PLAT="${B}/${config}${soc_suffix}" DTB_FILE_NAME="${dt}.dtb" ${extra_opt} ${soc_extra_opt} ${tf_a_make_target} # Copy TF-A binary with explicit devicetree filename - if [ -f ${B}/${config}${soc_suffix}/${tfa_basename}-${dt}.${TF_A_SUFFIX} ]; then - cp ${B}/${config}${soc_suffix}/${tfa_basename}-${dt}.${TF_A_SUFFIX} ${B}/${config}${soc_suffix}/${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/${tfa_basename}-${dt}.${TF_A_SUFFIX}" ]; then + cp "${B}/${config}${soc_suffix}/${tfa_basename}-${dt}.${TF_A_SUFFIX}" "${B}/${config}${soc_suffix}/${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX}" if [ "${TF_A_ENABLE_DEBUG_WRAPPER}" = "1" ]; then - stm32wrapper4dbg -s ${B}/${config}${soc_suffix}/${tfa_basename}-${dt}.${TF_A_SUFFIX} -d ${B}/${config}${soc_suffix}/debug-${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX} + stm32wrapper4dbg -s "${B}/${config}${soc_suffix}/${tfa_basename}-${dt}.${TF_A_SUFFIX}" -d "${B}/${config}${soc_suffix}/debug-${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX}" fi fi # Specific for bl32 target if [ "$(echo ${tf_a_make_target} | grep -cw 'bl32')" = "1" ]; then # Move 'bl32.elf' file to explicit file name with 'soc_suffix' info (same file for all devicetree build) # This avoid unexpected deployment for other config (cf. do_deploy task) - if [ -f ${B}/${config}${soc_suffix}/${BL32_ELF} ]; then - mv -f ${B}/${config}${soc_suffix}/${BL32_ELF} ${B}/${config}${soc_suffix}/${TF_A_BASENAME}-${BL32_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/${BL32_ELF}" ]; then + mv -f "${B}/${config}${soc_suffix}/${BL32_ELF}" "${B}/${config}${soc_suffix}/${TF_A_BASENAME}-${BL32_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX}" fi fi done done + + if [ "${TF_A_ENABLE_METADATA}" = "1" ]; then + ${S}/${TF_A_METADATA_TOOL} jsonparse "${S}/${TF_A_METADATA_JSON}" -b "${B}/${TF_A_METADATA_NAME}.${TF_A_METADATA_SUFFIX}" + fi } do_deploy() { @@ -257,83 +283,90 @@ do_deploy() { done fi for file_type in ${tfa_file_type}; do - case ${file_type} in + case "${file_type}" in bl2) # Install TF-A binary - if [ -f ${B}/${config}${soc_suffix}/${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX} ]; then - install -m 644 ${B}/${config}${soc_suffix}/${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/ + if [ -f "${B}/${config}${soc_suffix}/${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX}" ]; then + install -m 644 "${B}/${config}${soc_suffix}/${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/" if [ "${TF_A_ENABLE_DEBUG_WRAPPER}" = "1" ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/debug - install -m 644 ${B}/${config}${soc_suffix}/debug-${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/debug/ + install -d "${DEPLOYDIR}/arm-trusted-firmware/debug" + install -m 644 "${B}/${config}${soc_suffix}/debug-${tfa_basename}-${dt}-${config}.${TF_A_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/debug/" fi fi if [ -n "${ELF_DEBUG_ENABLE}" ]; then install -d ${DEPLOYDIR}/arm-trusted-firmware/debug - if [ -f ${B}/${config}${soc_suffix}/${BL2_ELF} ]; then - install -m 644 ${B}/${config}${soc_suffix}/${BL2_ELF} ${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL2_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/${BL2_ELF}" ]; then + install -m 644 "${B}/${config}${soc_suffix}/${BL2_ELF}" "${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL2_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX}" fi fi ;; bl31) # Install BL31 files - if [ -f ${B}/${config}${soc_suffix}/${BL31_BASENAME}.${BL31_SUFFIX} ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/bl31 + if [ -f "${B}/${config}${soc_suffix}/${BL31_BASENAME}.${BL31_SUFFIX}" ]; then + install -d "${DEPLOYDIR}/arm-trusted-firmware/bl31" # Install BL31 binary - install -m 644 ${B}/${config}${soc_suffix}/${BL31_BASENAME}.${BL31_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/bl31/${tfa_basename}-${BL31_BASENAME_DEPLOY}${soc_suffix}.${BL31_SUFFIX} + install -m 644 "${B}/${config}${soc_suffix}/${BL31_BASENAME}.${BL31_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/bl31/${tfa_basename}-${BL31_BASENAME_DEPLOY}${soc_suffix}.${BL31_SUFFIX}" if [ -n "${ELF_DEBUG_ENABLE}" ]; then - if [ -f ${B}/${config}${soc_suffix}/${tfa_basename}-${BL31_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX} ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/bl32/debug - install -m 644 ${B}/${config}${soc_suffix}/${tfa_basename}-${BL31_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/bl31/debug/${tfa_basename}-${BL31_BASENAME_DEPLOY}${soc_suffix}.${TF_A_ELF_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/${tfa_basename}-${BL31_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX}" ]; then + install -d "${DEPLOYDIR}/arm-trusted-firmware/bl32/debug" + install -m 644 "${B}/${config}${soc_suffix}/${tfa_basename}-${BL31_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/bl31/debug/${tfa_basename}-${BL31_BASENAME_DEPLOY}${soc_suffix}.${TF_A_ELF_SUFFIX}" fi fi fi if [ -n "${ELF_DEBUG_ENABLE}" ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/debug - if [ -f ${B}/${config}${soc_suffix}/${BL31_ELF} ]; then - install -m 644 ${B}/${config}${soc_suffix}/${BL31_ELF} ${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL31_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX} + install -d "${DEPLOYDIR}/arm-trusted-firmware/debug" + if [ -f "${B}/${config}${soc_suffix}/${BL31_ELF}" ]; then + install -m 644 "${B}/${config}${soc_suffix}/${BL31_ELF}" "${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL31_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX}" fi fi ;; bl32) # Install BL32 files - if [ -f ${B}/${config}${soc_suffix}/${BL32_BASENAME}.${BL32_SUFFIX} ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/bl32 + if [ -f "${B}/${config}${soc_suffix}/${BL32_BASENAME}.${BL32_SUFFIX}" ]; then + install -d "${DEPLOYDIR}/arm-trusted-firmware/bl32" # Install BL32 binary - install -m 644 ${B}/${config}${soc_suffix}/${BL32_BASENAME}.${BL32_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/bl32/${tfa_basename}-${BL32_BASENAME_DEPLOY}${soc_suffix}.${BL32_SUFFIX} + install -m 644 "${B}/${config}${soc_suffix}/${BL32_BASENAME}.${BL32_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/bl32/${tfa_basename}-${BL32_BASENAME_DEPLOY}${soc_suffix}.${BL32_SUFFIX}" # Install BL32 devicetree - if [ -f ${B}/${config}${soc_suffix}/fdts/${dt}-${BL32_BASENAME}.${DT_SUFFIX} ]; then - install -m 644 ${B}/${config}${soc_suffix}/fdts/${dt}-${BL32_BASENAME}.${DT_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/bl32/${dt}-${BL32_BASENAME}.${DT_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/fdts/${dt}-${BL32_BASENAME}.${DT_SUFFIX}" ]; then + install -m 644 "${B}/${config}${soc_suffix}/fdts/${dt}-${BL32_BASENAME}.${DT_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/bl32/${dt}-${BL32_BASENAME}.${DT_SUFFIX}" fi if [ -n "${ELF_DEBUG_ENABLE}" ]; then - if [ -f ${B}/${config}${soc_suffix}/${tfa_basename}-${BL32_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX} ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/bl32/debug - install -m 644 ${B}/${config}${soc_suffix}/${tfa_basename}-${BL32_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/bl32/debug/${tfa_basename}-${BL32_BASENAME_DEPLOY}${soc_suffix}.${TF_A_ELF_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/${tfa_basename}-${BL32_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX}" ]; then + install -d "${DEPLOYDIR}/arm-trusted-firmware/bl32/debug" + install -m 644 "${B}/${config}${soc_suffix}/${tfa_basename}-${BL32_BASENAME}${soc_suffix}.${TF_A_ELF_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/bl32/debug/${tfa_basename}-${BL32_BASENAME_DEPLOY}${soc_suffix}.${TF_A_ELF_SUFFIX}" fi fi fi if [ -n "${ELF_DEBUG_ENABLE}" ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/debug - if [ -f ${B}/${config}${soc_suffix}/${BL32_ELF} ]; then - install -m 644 ${B}/${config}${soc_suffix}/${BL32_ELF} ${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL32_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX} + install -d "${DEPLOYDIR}/arm-trusted-firmware/debug" + if [ -f "${B}/${config}${soc_suffix}/${BL32_ELF}" ]; then + install -m 644 "${B}/${config}${soc_suffix}/${BL32_ELF}" "${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL32_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX}" fi fi ;; fwconfig) # Install fwconfig - if [ -f ${B}/${config}${soc_suffix}/fdts/${dt}-${FWCONFIG_NAME}.${DT_SUFFIX} ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/fwconfig - install -m 644 ${B}/${config}${soc_suffix}/fdts/${dt}-${FWCONFIG_NAME}.${DT_SUFFIX} ${DEPLOYDIR}/arm-trusted-firmware/fwconfig/${dt}-${FWCONFIG_NAME}-${config}.${DT_SUFFIX} + if [ -f "${B}/${config}${soc_suffix}/fdts/${dt}-${FWCONFIG_NAME}.${DT_SUFFIX}" ]; then + install -d "${DEPLOYDIR}/arm-trusted-firmware/fwconfig" + install -m 644 "${B}/${config}${soc_suffix}/fdts/${dt}-${FWCONFIG_NAME}.${DT_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/fwconfig/${dt}-${FWCONFIG_NAME}-${config}.${DT_SUFFIX}" fi ;; esac done # for file_type in ${tfa_file_type} done # for dt in ${dt_config} if [ -n "${ELF_DEBUG_ENABLE}" ]; then - install -d ${DEPLOYDIR}/arm-trusted-firmware/debug - if [ -f ${B}/${config}${soc_suffix}/${BL1_ELF} ]; then - install -m 644 ${B}/${config}${soc_suffix}/${BL1_ELF} ${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL1_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX} + install -d "${DEPLOYDIR}/arm-trusted-firmware/debug" + if [ -f "${B}/${config}${soc_suffix}/${BL1_ELF}" ]; then + install -m 644 "${B}/${config}${soc_suffix}/${BL1_ELF}" "${DEPLOYDIR}/arm-trusted-firmware/debug/${tfa_basename}-${BL1_BASENAME_DEPLOY}-${config}.${TF_A_ELF_SUFFIX}" fi fi done # for config in ${TF_A_CONFIG} + + if [ "${TF_A_ENABLE_METADATA}" = "1" ]; then + install -d "${DEPLOYDIR}/arm-trusted-firmware" + if [ -f "${B}/${TF_A_METADATA_NAME}.${TF_A_METADATA_SUFFIX}" ]; then + install -m 644 "${B}/${TF_A_METADATA_NAME}.${TF_A_METADATA_SUFFIX}" "${DEPLOYDIR}/arm-trusted-firmware/${TF_A_METADATA_BIN}" + fi + fi } addtask deploy before do_build after do_compile diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-config.inc b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-config.inc index 87050bb..385cbec 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-config.inc +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-config.inc @@ -1,23 +1,15 @@ -# Configure default mode (All supported device type) -TF_A_EXTRACONF_LEGACY += "STM32MP_SDMMC=1" -TF_A_EXTRACONF_LEGACY += "STM32MP_EMMC=1" -TF_A_EXTRACONF_LEGACY += "STM32MP_SPI_NOR=1" -TF_A_EXTRACONF_LEGACY += "STM32MP_RAW_NAND=1" -TF_A_EXTRACONF_LEGACY += "STM32MP_SPI_NAND=1" -TF_A_EXTRACONF_LEGACY += "STM32MP_USE_STM32IMAGE=1" - # Define config for each TF_A_CONFIG # TF_A_CONFIG[config] ?= ",,,," -TF_A_CONFIG[optee] ?= "${STM32MP_DEVICETREE},AARCH32_SP=optee ${@bb.utils.contains('MACHINE_FEATURES', 'fip', '', '${TF_A_EXTRACONF_LEGACY}', d)},,${@bb.utils.contains('MACHINE_FEATURES', 'fip', bb.utils.contains('FIP_BL31_ENABLE', '1', 'bl31 dtbs', 'dtbs', d), '', d)},${@bb.utils.contains('MACHINE_FEATURES', 'fip', bb.utils.contains('FIP_BL31_ENABLE', '1', 'bl31 fwconfig', 'fwconfig', d), '', d)}" -TF_A_CONFIG[trusted] ?= "${STM32MP_DEVICETREE},AARCH32_SP=sp_min ${@bb.utils.contains('MACHINE_FEATURES', 'fip', '', '${TF_A_EXTRACONF_LEGACY}', d)},,${@bb.utils.contains('MACHINE_FEATURES', 'fip', 'bl32 dtbs', '', d)},${@bb.utils.contains('MACHINE_FEATURES', 'fip', 'bl32 fwconfig', '', d)}" +TF_A_CONFIG[optee] ?= "${STM32MP_DEVICETREE},AARCH32_SP=optee,,${@bb.utils.contains('FIP_BL31_ENABLE', '1', 'bl31 dtbs', 'dtbs', d)},${@bb.utils.contains('FIP_BL31_ENABLE', '1', 'bl31 fwconfig', 'fwconfig', d)}" +TF_A_CONFIG[trusted] ?= "${@' '.join(d for d in '${STM32MP_DEVICETREE}'.split() if 'stm32mp15' in d)},AARCH32_SP=sp_min,,bl32 dtbs,bl32 fwconfig" TF_A_CONFIG[serialboot] ?= "${STM32MP_DEVICETREE},AARCH32_SP=sp_min STM32MP_UART_PROGRAMMER=1 STM32MP_USB_PROGRAMMER=1 STM32MP_USE_STM32IMAGE=1" -TF_A_CONFIG[emmc] ?= "${DEVICE_BOARD_ENABLE:EMMC},STM32MP_EMMC=1" +TF_A_CONFIG[emmc] ?= "${DEVICE_BOARD_ENABLE:EMMC},STM32MP_EMMC=1 ${@bb.utils.contains('MACHINE_FEATURES', 'fw-update', 'PSA_FWU_SUPPORT=1', '', d)}" TF_A_CONFIG[nand] ?= "${DEVICE_BOARD_ENABLE:NAND},STM32MP_RAW_NAND=1 ${@'STM32MP_FORCE_MTD_START_OFFSET=${TF_A_MTD_START_OFFSET_NAND}' if ${TF_A_MTD_START_OFFSET_NAND} else ''}" -TF_A_CONFIG[nor] ?= "${DEVICE_BOARD_ENABLE:NOR},STM32MP_SPI_NOR=1 ${@'STM32MP_FORCE_MTD_START_OFFSET=${TF_A_MTD_START_OFFSET_NOR}' if ${TF_A_MTD_START_OFFSET_NOR} else ''}" -TF_A_CONFIG[sdcard] ?= "${DEVICE_BOARD_ENABLE:SDCARD},STM32MP_SDMMC=1" +TF_A_CONFIG[nor] ?= "${DEVICE_BOARD_ENABLE:NOR},STM32MP_SPI_NOR=1 ${@bb.utils.contains('MACHINE_FEATURES', 'fw-update', 'PSA_FWU_SUPPORT=1', '', d)} ${@'STM32MP_FORCE_MTD_START_OFFSET=${TF_A_MTD_START_OFFSET_NOR}' if ${TF_A_MTD_START_OFFSET_NOR} else ''}" +TF_A_CONFIG[sdcard] ?= "${DEVICE_BOARD_ENABLE:SDCARD},STM32MP_SDMMC=1 ${@bb.utils.contains('MACHINE_FEATURES', 'fw-update', 'PSA_FWU_SUPPORT=1', '', d)}" TF_A_CONFIG[spinand] ?= "${DEVICE_BOARD_ENABLE:SPINAND},STM32MP_SPI_NAND=1 ${@'STM32MP_FORCE_MTD_START_OFFSET=${TF_A_MTD_START_OFFSET_SPINAND}' if ${TF_A_MTD_START_OFFSET_SPINAND} else ''}" TF_A_CONFIG[uart] ?= "${STM32MP_DEVICETREE},STM32MP_UART_PROGRAMMER=1" TF_A_CONFIG[usb] ?= "${STM32MP_DEVICETREE},STM32MP_USB_PROGRAMMER=1" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-correct-DTC-version-detection.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-correct-DTC-version-detection.patch deleted file mode 100644 index 3cccaeb..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-correct-DTC-version-detection.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a9163bb270c27524c36cfc216ddb61169a7ccef8 Mon Sep 17 00:00:00 2001 -From: Christophe Priouzeau -Date: Fri, 29 Apr 2022 16:57:28 +0200 -Subject: [PATCH] correct DTC version detection - -Signed-off-by: Christophe Priouzeau ---- - plat/st/stm32mp1/platform.mk | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk -index 55acd6742..2db7b506c 100644 ---- a/plat/st/stm32mp1/platform.mk -+++ b/plat/st/stm32mp1/platform.mk -@@ -109,7 +109,7 @@ endif - endif - - $(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) --$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g"))) -+$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g" | grep -o [0-9]*))) - DTC_CPPFLAGS += ${INCLUDES} - DTC_FLAGS += -Wno-unit_address_vs_reg - ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0) --- -2.25.1 - diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.4-r1.0.0.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.4-r1.0.0.patch deleted file mode 100644 index d4e7b71..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-st-update-v2.4-r1.0.0.patch +++ /dev/null @@ -1,37632 +0,0 @@ -From 423ad55f481adefb98fdd57f391e185213733ec6 Mon Sep 17 00:00:00 2001 -From: Romuald JEANNE -Date: Mon, 15 Mar 2021 17:31:45 +0100 -Subject: [PATCH] st update v2.4-r1.0.0 - ---- - .editorconfig | 6 +- - CONTRIBUTING.md | 30 + - Makefile | 10 +- - bl1/aarch32/bl1_entrypoint.S | 14 +- - bl2/aarch32/bl2_el3_entrypoint.S | 5 +- - 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 | 22 +- - bl32/sp_min/sp_min.ld.S | 10 +- - common/aarch32/debug.S | 52 +- - common/bl_common.c | 2 +- - common/fdt_fixup.c | 44 +- - docs/devicetree/bindings/arm/secure.txt | 53 + - .../bindings/clock/st,stm32mp1-rcc.txt | 496 +++++ - 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 | 43 + - 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 | 25 + - docs/plat/stm32mp1.rst | 169 +- - drivers/arm/tzc/tzc400.c | 135 +- - drivers/arm/tzc/tzc_common_private.h | 21 + - drivers/auth/auth_mod.c | 14 + - drivers/auth/mbedtls/mbedtls_common.mk | 2 +- - drivers/auth/mbedtls/mbedtls_x509_parser.c | 4 +- - drivers/auth/tbbr/tbbr_cot_bl1.c | 15 - - drivers/auth/tbbr/tbbr_cot_bl2.c | 1 + - drivers/auth/tbbr/tbbr_cot_common.c | 15 + - drivers/clk/clk.c | 64 + - drivers/io/io_mtd.c | 68 +- - drivers/mmc/mmc.c | 67 +- - drivers/mtd/nand/core.c | 43 +- - drivers/mtd/nor/spi_nor.c | 20 +- - drivers/st/bsec/{bsec.c => bsec2.c} | 534 +++-- - drivers/st/clk/stm32mp1_calib.c | 536 +++++ - drivers/st/clk/stm32mp1_clk.c | 1829 ++++++++++++++--- - drivers/st/clk/stm32mp_clkfunc.c | 220 +- - drivers/st/crypto/stm32_hash.c | 19 +- - drivers/st/ddr/stm32mp1_ddr.c | 331 ++- - drivers/st/ddr/stm32mp1_ddr_helpers.c | 593 +++++- - drivers/st/ddr/stm32mp1_ram.c | 120 +- - drivers/st/etzpc/etzpc.c | 50 +- - drivers/st/fmc/stm32_fmc2_nand.c | 5 +- - drivers/st/gpio/stm32_gpio.c | 9 +- - drivers/st/i2c/stm32_i2c.c | 460 ++++- - drivers/st/io/io_stm32image.c | 196 +- - drivers/st/iwdg/stm32_iwdg.c | 151 +- - drivers/st/mmc/stm32_sdmmc2.c | 125 +- - drivers/st/pmic/stm32mp_pmic.c | 484 ++++- - 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 | 31 +- - drivers/st/rng/stm32_rng.c | 193 ++ - drivers/st/rtc/stm32_rtc.c | 480 +++++ - drivers/st/spi/stm32_qspi.c | 5 +- - drivers/st/tamper/stm32_tamp.c | 379 ++++ - drivers/st/timer/stm32_timer.c | 323 +++ - drivers/st/uart/aarch32/stm32_console.S | 23 +- - drivers/st/uart/stm32_uart.c | 405 ++++ - drivers/st/usb_dwc2/usb_dwc2.c | 1094 ++++++++++ - fdts/stm32mp15-bl2.dtsi | 116 ++ - fdts/stm32mp15-bl32.dtsi | 42 + - fdts/stm32mp15-ddr-1g-fw-config.dts | 63 + - fdts/stm32mp15-ddr-512m-fw-config.dts | 63 + - fdts/stm32mp15-ddr.dtsi | 12 + - fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 4 +- - fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 4 +- - fdts/stm32mp15-pinctrl.dtsi | 87 +- - fdts/stm32mp15-ssp-bl2.dtsi | 125 ++ - fdts/stm32mp151.dtsi | 95 +- - fdts/stm32mp153.dtsi | 1 + - fdts/stm32mp157a-avenger96-fw-config.dts | 6 + - fdts/stm32mp157a-avenger96.dts | 20 + - fdts/stm32mp157a-dk1-fw-config.dts | 6 + - fdts/stm32mp157a-dk1.dts | 18 + - fdts/stm32mp157a-ed1-fw-config.dts | 6 + - fdts/stm32mp157a-ed1.dts | 38 + - fdts/stm32mp157a-ev1-fw-config.dts | 6 + - fdts/stm32mp157a-ev1.dts | 24 + - fdts/stm32mp157c-dk2-fw-config.dts | 6 + - fdts/stm32mp157c-dk2.dts | 18 + - fdts/stm32mp157c-ed1-fw-config.dts | 6 + - fdts/stm32mp157c-ed1.dts | 329 +-- - fdts/stm32mp157c-ev1-fw-config.dts | 6 + - fdts/stm32mp157c-ev1.dts | 47 +- - fdts/stm32mp157d-dk1-fw-config.dts | 6 + - fdts/stm32mp157d-dk1.dts | 45 + - fdts/stm32mp157d-ed1-fw-config.dts | 6 + - fdts/stm32mp157d-ed1.dts | 39 + - fdts/stm32mp157d-ev1-fw-config.dts | 6 + - fdts/stm32mp157d-ev1.dts | 23 + - fdts/stm32mp157f-dk2-fw-config.dts | 6 + - fdts/stm32mp157f-dk2.dts | 51 + - fdts/stm32mp157f-ed1-fw-config.dts | 6 + - fdts/stm32mp157f-ed1.dts | 43 + - fdts/stm32mp157f-ev1-fw-config.dts | 6 + - fdts/stm32mp157f-ev1.dts | 23 + - fdts/stm32mp15xa.dtsi | 13 + - fdts/stm32mp15xc.dtsi | 3 + - fdts/stm32mp15xd.dtsi | 19 + - fdts/stm32mp15xf.dtsi | 21 + - fdts/stm32mp15xx-dkx.dtsi | 180 +- - fdts/stm32mp15xx-edx.dtsi | 518 +++++ - fdts/stm32mp15xx-evx.dtsi | 73 + - fdts/stm32mp15xxaa-pinctrl.dtsi | 3 +- - fdts/stm32mp15xxab-pinctrl.dtsi | 2 +- - fdts/stm32mp15xxac-pinctrl.dtsi | 3 +- - fdts/stm32mp15xxad-pinctrl.dtsi | 2 +- - include/arch/aarch32/arch.h | 18 +- - include/arch/aarch32/arch_helpers.h | 4 + - include/arch/aarch32/el3_common_macros.S | 42 +- - include/arch/aarch64/arch.h | 6 +- - include/common/bl_common.ld.h | 9 + - include/common/tbbr/cot_def.h | 2 +- - include/drivers/arm/tzc400.h | 44 +- - include/drivers/auth/tbbr_cot_common.h | 1 + - include/drivers/clk.h | 28 + - include/drivers/io/io_mtd.h | 13 +- - include/drivers/mmc.h | 27 +- - include/drivers/nand.h | 12 +- - include/drivers/st/bsec.h | 159 +- - include/drivers/st/bsec2_reg.h | 98 + - include/drivers/st/stm32_i2c.h | 41 +- - include/drivers/st/stm32_iwdg.h | 1 + - 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/stm32_uart.h | 170 ++ - include/drivers/st/stm32mp1_calib.h | 20 + - include/drivers/st/stm32mp1_clk.h | 52 +- - include/drivers/st/stm32mp1_ddr.h | 13 +- - include/drivers/st/stm32mp1_ddr_helpers.h | 20 +- - include/drivers/st/stm32mp1_ddr_regs.h | 14 +- - include/drivers/st/stm32mp1_pwr.h | 21 +- - include/drivers/st/stm32mp1_ram.h | 3 +- - include/drivers/st/stm32mp1_rcc.h | 32 +- - include/drivers/st/stm32mp_clkfunc.h | 19 +- - 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 | 14 +- - include/drivers/st/stpmic1.h | 29 +- - include/drivers/st/usb_dwc2.h | 19 + - include/dt-bindings/clock/stm32mp1-clks.h | 6 + - include/dt-bindings/power/stm32mp1-power.h | 19 + - include/dt-bindings/reset/stm32mp1-resets.h | 2 + - include/dt-bindings/soc/st,stm32-etzpc.h | 86 + - include/dt-bindings/soc/stm32mp1-tzc400.h | 37 + - include/lib/optee_utils.h | 1 + - include/lib/psci/psci.h | 1 + - include/lib/usb/usb_core.h | 277 +++ - include/lib/usb/usb_st_dfu.h | 85 + - include/lib/utils_def.h | 10 + - include/plat/common/platform.h | 9 +- - lib/aarch32/misc_helpers.S | 126 ++ - lib/optee/optee_utils.c | 37 +- - lib/psci/psci_private.h | 1 - - lib/usb/usb_core.c | 838 ++++++++ - lib/usb/usb_st_dfu.c | 537 +++++ - make_helpers/defaults.mk | 8 +- - plat/common/aarch32/platform_helpers.S | 34 + - plat/common/plat_bl_common.c | 2 +- - plat/st/common/bl2_io_storage.c | 506 ++--- - plat/st/common/bl2_stm32_io_storage.c | 769 +++++++ - plat/st/common/include/stm32cubeprogrammer.h | 67 + - plat/st/common/include/stm32mp_auth.h | 19 - - plat/st/common/include/stm32mp_common.h | 53 +- - plat/st/common/include/stm32mp_dt.h | 16 +- - plat/st/common/include/stm32mp_fconf_getter.h | 29 + - plat/st/common/include/stm32mp_io_storage.h | 23 + - .../st/common/include/stm32mp_shres_helpers.h | 65 +- - plat/st/common/stm32_gic.c | 223 ++ - plat/st/common/stm32cubeprogrammer_uart.c | 690 +++++++ - plat/st/common/stm32cubeprogrammer_usb.c | 352 ++++ - plat/st/common/stm32mp_auth.c | 90 - - plat/st/common/stm32mp_common.c | 158 +- - plat/st/common/stm32mp_cot.c | 114 + - plat/st/common/stm32mp_crypto_lib.c | 447 ++++ - plat/st/common/stm32mp_dt.c | 347 +++- - plat/st/common/stm32mp_fconf_io.c | 136 ++ - plat/st/common/stm32mp_img_parser_lib.c | 75 + - plat/st/common/stm32mp_shres_helpers.c | 63 + - plat/st/common/stm32mp_trusted_boot.c | 143 ++ - plat/st/stm32mp1/bl2_plat_setup.c | 516 ++++- - plat/st/stm32mp1/include/boot_api.h | 552 ++++- - plat/st/stm32mp1/include/platform_def.h | 40 +- - .../include/stm32mp15_mbedtls_config.h | 119 ++ - plat/st/stm32mp1/include/stm32mp1_context.h | 29 +- - .../stm32mp1/include/stm32mp1_critic_power.h | 22 + - plat/st/stm32mp1/include/stm32mp1_low_power.h | 23 + - .../stm32mp1/include/stm32mp1_power_config.h | 29 + - plat/st/stm32mp1/include/stm32mp1_private.h | 33 +- - .../include/stm32mp1_shared_resources.h | 17 + - plat/st/stm32mp1/include/stm32mp1_smc.h | 87 +- - plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 71 +- - .../stm32mp1/plat_bl2_stm32_mem_params_desc.c | 111 + - plat/st/stm32mp1/plat_image_load.c | 35 +- - plat/st/stm32mp1/platform.mk | 258 ++- - plat/st/stm32mp1/services/bsec_svc.c | 455 +++- - 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 | 169 ++ - plat/st/stm32mp1/services/rcc_svc.h | 14 + - .../st/stm32mp1/services/stm32mp1_svc_setup.c | 34 +- - plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 30 +- - plat/st/stm32mp1/sp_min/sp_min_setup.c | 487 ++++- - plat/st/stm32mp1/stm32mp1.S | 4 +- - plat/st/stm32mp1/stm32mp1.ld.S | 14 +- - plat/st/stm32mp1/stm32mp1_boot_device.c | 6 +- - plat/st/stm32mp1/stm32mp1_context.c | 483 ++++- - plat/st/stm32mp1/stm32mp1_critic_power.c | 91 + - .../stm32mp1/stm32mp1_critic_power_wrapper.S | 62 + - plat/st/stm32mp1/stm32mp1_dbgmcu.c | 48 +- - plat/st/stm32mp1/stm32mp1_def.h | 438 ++-- - plat/st/stm32mp1/stm32mp1_fconf_firewall.c | 124 ++ - plat/st/stm32mp1/stm32mp1_gic.c | 92 - - plat/st/stm32mp1/stm32mp1_helper.S | 135 +- - plat/st/stm32mp1/stm32mp1_low_power.c | 455 ++++ - plat/st/stm32mp1/stm32mp1_pm.c | 107 +- - plat/st/stm32mp1/stm32mp1_power_config.c | 223 ++ - plat/st/stm32mp1/stm32mp1_private.c | 625 +++++- - plat/st/stm32mp1/stm32mp1_scmi.c | 131 +- - plat/st/stm32mp1/stm32mp1_security.c | 119 +- - plat/st/stm32mp1/stm32mp1_shared_resources.c | 211 +- - plat/st/stm32mp1/stm32mp1_ssp.c | 1039 ++++++++++ - plat/st/stm32mp1/stm32mp1_ssp.mk | 84 + - plat/st/stm32mp1/stm32mp1_syscfg.c | 51 +- - plat/st/stm32mp1/stm32mp1_usb.c | 491 +++++ - tools/cert_create/Makefile | 8 +- - tools/cert_create/include/key.h | 6 +- - tools/cert_create/src/key.c | 20 +- - tools/cert_create/src/main.c | 3 +- - tools/encrypt_fw/Makefile | 8 +- - tools/fiptool/Makefile | 8 +- - tools/stm32image/stm32image.c | 46 +- - 252 files changed, 26563 insertions(+), 3015 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 - create mode 100644 docs/devicetree/bindings/power/st,stpmic1.txt - create mode 100644 docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt - create mode 100644 docs/devicetree/bindings/rng/st,stm32-rng.txt - create mode 100644 docs/devicetree/bindings/serial/st,stm32-usart.txt - create mode 100644 docs/devicetree/bindings/soc/st,stm32-etzpc.txt - create mode 100644 docs/devicetree/bindings/soc/st,stm32-romem.txt - 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/clk/clk.c - rename drivers/st/bsec/{bsec.c => bsec2.c} (62%) - create mode 100644 drivers/st/clk/stm32mp1_calib.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/tamper/stm32_tamp.c - create mode 100644 drivers/st/timer/stm32_timer.c - create mode 100644 drivers/st/uart/stm32_uart.c - create mode 100644 drivers/st/usb_dwc2/usb_dwc2.c - create mode 100644 fdts/stm32mp15-bl2.dtsi - create mode 100644 fdts/stm32mp15-bl32.dtsi - create mode 100644 fdts/stm32mp15-ddr-1g-fw-config.dts - create mode 100644 fdts/stm32mp15-ddr-512m-fw-config.dts - create mode 100644 fdts/stm32mp15-ssp-bl2.dtsi - create mode 100644 fdts/stm32mp157a-avenger96-fw-config.dts - create mode 100644 fdts/stm32mp157a-dk1-fw-config.dts - create mode 100644 fdts/stm32mp157a-ed1-fw-config.dts - create mode 100644 fdts/stm32mp157a-ed1.dts - create mode 100644 fdts/stm32mp157a-ev1-fw-config.dts - create mode 100644 fdts/stm32mp157a-ev1.dts - create mode 100644 fdts/stm32mp157c-dk2-fw-config.dts - create mode 100644 fdts/stm32mp157c-ed1-fw-config.dts - create mode 100644 fdts/stm32mp157c-ev1-fw-config.dts - create mode 100644 fdts/stm32mp157d-dk1-fw-config.dts - create mode 100644 fdts/stm32mp157d-dk1.dts - create mode 100644 fdts/stm32mp157d-ed1-fw-config.dts - create mode 100644 fdts/stm32mp157d-ed1.dts - create mode 100644 fdts/stm32mp157d-ev1-fw-config.dts - create mode 100644 fdts/stm32mp157d-ev1.dts - create mode 100644 fdts/stm32mp157f-dk2-fw-config.dts - create mode 100644 fdts/stm32mp157f-dk2.dts - create mode 100644 fdts/stm32mp157f-ed1-fw-config.dts - create mode 100644 fdts/stm32mp157f-ed1.dts - create mode 100644 fdts/stm32mp157f-ev1-fw-config.dts - create mode 100644 fdts/stm32mp157f-ev1.dts - create mode 100644 fdts/stm32mp15xa.dtsi - create mode 100644 fdts/stm32mp15xd.dtsi - create mode 100644 fdts/stm32mp15xf.dtsi - create mode 100644 fdts/stm32mp15xx-edx.dtsi - create mode 100644 fdts/stm32mp15xx-evx.dtsi - create mode 100644 include/drivers/clk.h - create mode 100644 include/drivers/st/bsec2_reg.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_tamp.h - create mode 100644 include/drivers/st/stm32_timer.h - create mode 100644 include/drivers/st/stm32_uart.h - create mode 100644 include/drivers/st/stm32mp1_calib.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/power/stm32mp1-power.h - create mode 100644 include/dt-bindings/soc/stm32mp1-tzc400.h - create mode 100644 include/lib/usb/usb_core.h - create mode 100644 include/lib/usb/usb_st_dfu.h - create mode 100644 lib/usb/usb_core.c - create mode 100644 lib/usb/usb_st_dfu.c - create mode 100644 plat/st/common/bl2_stm32_io_storage.c - create mode 100644 plat/st/common/include/stm32cubeprogrammer.h - delete mode 100644 plat/st/common/include/stm32mp_auth.h - create mode 100644 plat/st/common/include/stm32mp_fconf_getter.h - create mode 100644 plat/st/common/include/stm32mp_io_storage.h - create mode 100644 plat/st/common/stm32_gic.c - create mode 100644 plat/st/common/stm32cubeprogrammer_uart.c - create mode 100644 plat/st/common/stm32cubeprogrammer_usb.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_fconf_io.c - create mode 100644 plat/st/common/stm32mp_img_parser_lib.c - create mode 100644 plat/st/common/stm32mp_shres_helpers.c - create mode 100644 plat/st/common/stm32mp_trusted_boot.c - create mode 100644 plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h - create mode 100644 plat/st/stm32mp1/include/stm32mp1_critic_power.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/plat_bl2_stm32_mem_params_desc.c - 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/stm32mp1_critic_power.c - create mode 100644 plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S - create mode 100644 plat/st/stm32mp1/stm32mp1_fconf_firewall.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_ssp.c - create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.mk - create mode 100644 plat/st/stm32mp1/stm32mp1_usb.c - -diff --git a/.editorconfig b/.editorconfig -index f523ca19da..12f786de5a 100644 ---- a/.editorconfig -+++ b/.editorconfig -@@ -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 - # -@@ -38,10 +38,10 @@ indent_style = tab - insert_final_newline = true - - # [LCS] Chapter 2: Breaking long lines and strings --# "The limit on the length of lines is 80 columns" -+# "The limit on the length of lines is 100 columns" - # This is a "soft" requirement for Arm-TF, and should not be the sole - # reason for changes. --max_line_length = 80 -+max_line_length = 100 - - # [LCS] Chapter 1: Indentation - # "Tabs are 8 characters" -diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md -new file mode 100644 -index 0000000000..3d1bacd78a ---- /dev/null -+++ b/CONTRIBUTING.md -@@ -0,0 +1,30 @@ -+# Contributing guide -+ -+This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you. -+ -+This guide mainly focuses on the proper use of Git. -+ -+## 1. Issues -+ -+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). -+ -+## 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 5c9186ece3..db60400b8b 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -548,11 +548,9 @@ endif - endif - BL31_CFLAGS += -fpie - BL31_LDFLAGS += $(PIE_LDFLAGS) --ifeq ($(ARCH),aarch64) - BL32_CFLAGS += -fpie - BL32_LDFLAGS += $(PIE_LDFLAGS) - endif --endif - - ifeq (${ARCH},aarch64) - BL1_CPPFLAGS += -DIMAGE_AT_EL3 -@@ -918,6 +916,7 @@ $(eval $(call assert_booleans,\ - RAS_TRAP_LOWER_EL_ERR_ACCESS \ - COT_DESC_IN_DTB \ - USE_SP804_TIMER \ -+ AARCH32_EXCEPTION_DEBUG \ - ))) - - $(eval $(call assert_numerics,\ -@@ -1007,6 +1006,7 @@ $(eval $(call add_defines,\ - RAS_TRAP_LOWER_EL_ERR_ACCESS \ - COT_DESC_IN_DTB \ - USE_SP804_TIMER \ -+ AARCH32_EXCEPTION_DEBUG \ - ))) - - ifeq (${SANITIZE_UB},trap) -@@ -1224,7 +1224,7 @@ certtool: ${CRTTOOL} - - .PHONY: ${CRTTOOL} - ${CRTTOOL}: -- ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} --no-print-directory -C ${CRTTOOLPATH} -+ ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} CRTTOOL=${CRTTOOL} --no-print-directory -C ${CRTTOOLPATH} - @${ECHO_BLANK_LINE} - @echo "Built $@ successfully" - @${ECHO_BLANK_LINE} -@@ -1299,7 +1299,7 @@ enctool: ${ENCTOOL} - - .PHONY: ${ENCTOOL} - ${ENCTOOL}: -- ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} --no-print-directory -C ${ENCTOOLPATH} -+ ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 ENCTOOL=${ENCTOOL} --no-print-directory -C ${ENCTOOLPATH} - @${ECHO_BLANK_LINE} - @echo "Built $@ successfully" - @${ECHO_BLANK_LINE} -diff --git a/bl1/aarch32/bl1_entrypoint.S b/bl1/aarch32/bl1_entrypoint.S -index 6a155660b6..09ad3b035e 100644 ---- a/bl1/aarch32/bl1_entrypoint.S -+++ b/bl1/aarch32/bl1_entrypoint.S -@@ -1,5 +1,5 @@ - /* -- * 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 - */ -@@ -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 - 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 */ -@@ -49,7 +58,8 @@ func bl1_entrypoint - _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ - _init_memory=1 \ - _init_c_runtime=1 \ -- _exception_vectors=bl1_vector_table -+ _exception_vectors=bl1_vector_table \ -+ _pie_fixup_size=0 - - /* ----------------------------------------------------- - * Perform BL1 setup -diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S -index 2e851e61a4..49d48980c0 100644 ---- a/bl2/aarch32/bl2_el3_entrypoint.S -+++ b/bl2/aarch32/bl2_el3_entrypoint.S -@@ -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 - */ -@@ -26,7 +26,8 @@ func bl2_entrypoint - _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ - _init_memory=1 \ - _init_c_runtime=1 \ -- _exception_vectors=bl2_vector_table -+ _exception_vectors=bl2_vector_table \ -+ _pie_fixup_size=0 - - /* - * Restore parameters of boot rom -diff --git a/bl2/aarch32/bl2_el3_exceptions.S b/bl2/aarch32/bl2_el3_exceptions.S -index 087b6656dc..dff4e36a4a 100644 ---- a/bl2/aarch32/bl2_el3_exceptions.S -+++ b/bl2/aarch32/bl2_el3_exceptions.S -@@ -12,10 +12,19 @@ - - vector_base bl2_vector_table - b bl2_entrypoint -+#if AARCH32_EXCEPTION_DEBUG -+ b report_undef_inst /* Undef */ -+#else - b report_exception /* Undef */ -+#endif - b report_exception /* SVC 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_entrypoint.S b/bl2/aarch32/bl2_entrypoint.S -index 102fd2f514..bfd721ca1d 100644 ---- a/bl2/aarch32/bl2_entrypoint.S -+++ b/bl2/aarch32/bl2_entrypoint.S -@@ -14,10 +14,19 @@ - - vector_base bl2_vector_table - b bl2_entrypoint -+#if AARCH32_EXCEPTION_DEBUG -+ b report_undef_inst /* Undef */ -+#else - b report_exception /* Undef */ -+#endif - b report_exception /* SVC 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/bl2_image_load_v2.c b/bl2/bl2_image_load_v2.c -index 48c9beca6c..4fb0e030d0 100644 ---- a/bl2/bl2_image_load_v2.c -+++ b/bl2/bl2_image_load_v2.c -@@ -74,17 +74,17 @@ struct entry_point_info *bl2_load_images(void) - bl2_node_info->image_id, err); - plat_error_handler(err); - } -+ -+ /* Allow platform to handle image information. */ -+ err = bl2_plat_handle_post_image_load(bl2_node_info->image_id); -+ if (err != 0) { -+ ERROR("BL2: Failure in post image load handling (%i)\n", err); -+ plat_error_handler(err); -+ } - } else { - INFO("BL2: Skip loading image id %d\n", bl2_node_info->image_id); - } - -- /* Allow platform to handle image information. */ -- err = bl2_plat_handle_post_image_load(bl2_node_info->image_id); -- if (err != 0) { -- ERROR("BL2: Failure in post image load handling (%i)\n", err); -- plat_error_handler(err); -- } -- - /* Go to next image */ - bl2_node_info = bl2_node_info->next_load_info; - } -diff --git a/bl2u/aarch32/bl2u_entrypoint.S b/bl2u/aarch32/bl2u_entrypoint.S -index 6391f537cd..426176d98e 100644 ---- a/bl2u/aarch32/bl2u_entrypoint.S -+++ b/bl2u/aarch32/bl2u_entrypoint.S -@@ -14,10 +14,19 @@ - - vector_base bl2u_vector_table - b bl2u_entrypoint -+#if AARCH32_EXCEPTION_DEBUG -+ b report_undef_inst /* Undef */ -+#else - b report_exception /* Undef */ -+#endif - b report_exception /* SVC 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/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S -index f3a1e440b7..b73943aca8 100644 ---- a/bl32/sp_min/aarch32/entrypoint.S -+++ b/bl32/sp_min/aarch32/entrypoint.S -@@ -1,5 +1,5 @@ - /* -- * 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 - */ -@@ -23,6 +23,8 @@ - .globl sp_min_handle_smc - .globl sp_min_handle_fiq - -+#define FIXUP_SIZE ((BL32_LIMIT) - (BL32_BASE)) -+ - .macro route_fiq_to_sp_min reg - /* ----------------------------------------------------- - * FIQs are secure interrupts trapped by Monitor and non -@@ -47,10 +49,19 @@ - - vector_base sp_min_vector_table - b sp_min_entrypoint -+#if AARCH32_EXCEPTION_DEBUG -+ b report_undef_inst /* Undef */ -+#else - b plat_panic_handler /* Undef */ -+#endif - b sp_min_handle_smc /* Syscall */ -+#if AARCH32_EXCEPTION_DEBUG -+ b report_prefetch_abort /* Prefetch abort */ -+ b report_data_abort /* Data abort */ -+#else - b plat_panic_handler /* Prefetch abort */ - b plat_panic_handler /* Data abort */ -+#endif - b plat_panic_handler /* Reserved */ - b plat_panic_handler /* IRQ */ - b sp_min_handle_fiq /* FIQ */ -@@ -87,7 +98,8 @@ func sp_min_entrypoint - _secondary_cold_boot=0 \ - _init_memory=0 \ - _init_c_runtime=1 \ -- _exception_vectors=sp_min_vector_table -+ _exception_vectors=sp_min_vector_table \ -+ _pie_fixup_size=FIXUP_SIZE - - /* --------------------------------------------------------------------- - * Relay the previous bootloader's arguments to the platform layer -@@ -106,7 +118,8 @@ func sp_min_entrypoint - _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ - _init_memory=1 \ - _init_c_runtime=1 \ -- _exception_vectors=sp_min_vector_table -+ _exception_vectors=sp_min_vector_table \ -+ _pie_fixup_size=FIXUP_SIZE - - /* --------------------------------------------------------------------- - * For RESET_TO_SP_MIN systems, BL32 (SP_MIN) is the first bootloader -@@ -306,7 +319,8 @@ func sp_min_warm_entrypoint - _secondary_cold_boot=0 \ - _init_memory=0 \ - _init_c_runtime=0 \ -- _exception_vectors=sp_min_vector_table -+ _exception_vectors=sp_min_vector_table \ -+ _pie_fixup_size=0 - - /* - * We're about to enable MMU and participate in PSCI state coordination. -diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S -index f202c7ada8..175305aa07 100644 ---- a/bl32/sp_min/sp_min.ld.S -+++ b/bl32/sp_min/sp_min.ld.S -@@ -92,6 +92,7 @@ SECTIONS - __RW_START__ = . ; - - DATA_SECTION >RAM -+ RELA_SECTION >RAM - - #ifdef BL32_PROGBITS_LIMIT - ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.") -@@ -101,8 +102,6 @@ SECTIONS - BSS_SECTION >RAM - XLAT_TABLE_SECTION >RAM - -- __BSS_SIZE__ = SIZEOF(.bss); -- - #if USE_COHERENT_MEM - /* - * The base address of the coherent memory section must be page-aligned (4K) -@@ -128,9 +127,6 @@ SECTIONS - . = ALIGN(PAGE_SIZE); - __COHERENT_RAM_END__ = .; - } >RAM -- -- __COHERENT_RAM_UNALIGNED_SIZE__ = -- __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; - #endif - - /* -@@ -141,5 +137,9 @@ SECTIONS - - __BL32_END__ = .; - -+ /DISCARD/ : { -+ *(.dynsym .dynstr .hash .gnu.hash) -+ } -+ - ASSERT(. <= BL32_LIMIT, "BL32 image has exceeded its limit.") - } -diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S -index 9d410df07e..69b1ed4ed5 100644 ---- a/common/aarch32/debug.S -+++ b/common/aarch32/debug.S -@@ -14,6 +14,11 @@ - .globl asm_assert - .globl do_panic - .globl report_exception -+#if AARCH32_EXCEPTION_DEBUG -+ .globl report_undef_inst -+ .globl report_prefetch_abort -+ .globl report_data_abort -+#endif - - /* Since the max decimal input number is 65536 */ - #define MAX_DEC_DIVISOR 10000 -@@ -113,10 +118,10 @@ endfunc asm_assert - - /* - * This function prints a string from address in r4 -- * Clobber: lr, r0 - r4 -+ * Clobber: lr, r0 - r4, r7 - */ - func asm_print_str -- mov r3, lr -+ mov r7, lr - 1: - ldrb r0, [r4], #0x1 - cmp r0, #0 -@@ -124,20 +129,20 @@ func asm_print_str - bl plat_crash_console_putc - b 1b - 2: -- bx r3 -+ bx r7 - endfunc asm_print_str - - /* - * This function prints a hexadecimal number in r4. - * In: r4 = the hexadecimal to print. -- * Clobber: lr, r0 - r3, r5 -+ * Clobber: lr, r0 - r3, r5, r7 - */ - func asm_print_hex - mov r5, #32 /* No of bits to convert to ascii */ - - /* Convert to ascii number of bits in r5 */ - asm_print_hex_bits: -- mov r3, lr -+ mov r7, lr - 1: - sub r5, r5, #4 - lsr r0, r4, r5 -@@ -153,7 +158,7 @@ asm_print_hex_bits: - bl plat_crash_console_putc - cmp r5, #0 - bne 1b -- bx r3 -+ bx r7 - endfunc asm_print_hex - - /*********************************************************** -@@ -205,3 +210,38 @@ func report_exception - bl plat_report_exception - no_ret plat_panic_handler - endfunc report_exception -+ -+#if AARCH32_EXCEPTION_DEBUG -+ /*********************************************************** -+ * This function is called from the vector table for -+ * undefined instruction. The lr_und is given as an -+ * argument to platform handler. -+ ***********************************************************/ -+func report_undef_inst -+ mrs r0, lr_und -+ bl plat_report_undef_inst -+ no_ret plat_panic_handler -+endfunc report_undef_inst -+ -+ /*********************************************************** -+ * This function is called from the vector table for -+ * unhandled exceptions. The lr_abt is given as an -+ * argument to platform handler. -+ ***********************************************************/ -+func report_prefetch_abort -+ mrs r0, lr_abt -+ bl plat_report_prefetch_abort -+ no_ret plat_panic_handler -+endfunc report_prefetch_abort -+ -+ /*********************************************************** -+ * This function is called from the vector table for -+ * unhandled exceptions. The lr_abt is given as an -+ * argument to platform handler. -+ ***********************************************************/ -+func report_data_abort -+ mrs r0, lr_abt -+ bl plat_report_data_abort -+ no_ret plat_panic_handler -+endfunc report_data_abort -+#endif -diff --git a/common/bl_common.c b/common/bl_common.c -index f17afcb115..22a0daf18c 100644 ---- a/common/bl_common.c -+++ b/common/bl_common.c -@@ -241,7 +241,7 @@ int load_auth_image(unsigned int image_id, image_info_t *image_data) - - do { - err = load_auth_image_internal(image_id, image_data); -- } 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/common/fdt_fixup.c b/common/fdt_fixup.c -index e88a550080..f6d5963890 100644 ---- a/common/fdt_fixup.c -+++ b/common/fdt_fixup.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -195,23 +195,51 @@ int fdt_add_reserved_memory(void *dtb, const char *node_name, - uintptr_t base, size_t size) - { - int offs = fdt_path_offset(dtb, "/reserved-memory"); -- uint32_t addresses[3]; -+ uint32_t addr_len = sizeof(base) / sizeof(uint32_t); -+ uint32_t size_len = sizeof(size) / sizeof(uint32_t); -+ uint32_t addresses[4]; - - if (offs < 0) { /* create if not existing yet */ - offs = fdt_add_subnode(dtb, 0, "reserved-memory"); - if (offs < 0) - return offs; -- fdt_setprop_u32(dtb, offs, "#address-cells", 2); -- fdt_setprop_u32(dtb, offs, "#size-cells", 1); -+ -+ fdt_setprop_u32(dtb, offs, "#address-cells", addr_len); -+ fdt_setprop_u32(dtb, offs, "#size-cells", size_len); - fdt_setprop(dtb, offs, "ranges", NULL, 0); -+ } else { -+ const fdt32_t *prop; -+ int len; -+ -+ prop = fdt_getprop(dtb, offs, "#address-cells", &len); -+ if ((prop == NULL) || (fdt32_to_cpu(*prop) != addr_len)) { -+ return -1; -+ } -+ -+ prop = fdt_getprop(dtb, offs, "#size-cells", &len); -+ if ((prop == NULL) || (fdt32_to_cpu(*prop) != size_len)) { -+ return -1; -+ } -+ } -+ -+ if (addr_len == 1U) { -+ addresses[0] = cpu_to_fdt32(base & 0xffffffff); -+ } else { -+ addresses[0] = cpu_to_fdt32(HIGH_BITS(base)); -+ addresses[1] = cpu_to_fdt32(base & 0xffffffff); -+ } -+ -+ if (size_len == 1U) { -+ addresses[addr_len] = cpu_to_fdt32(size & 0xffffffff); -+ } else { -+ addresses[addr_len] = cpu_to_fdt32(HIGH_BITS(size)); -+ addresses[addr_len + 1U] = cpu_to_fdt32(size & 0xffffffff); - } - -- addresses[0] = cpu_to_fdt32(HIGH_BITS(base)); -- addresses[1] = cpu_to_fdt32(base & 0xffffffff); -- addresses[2] = cpu_to_fdt32(size & 0xffffffff); - offs = fdt_add_subnode(dtb, offs, node_name); - fdt_setprop(dtb, offs, "no-map", NULL, 0); -- fdt_setprop(dtb, offs, "reg", addresses, 12); -+ fdt_setprop(dtb, offs, "reg", addresses, -+ (addr_len + size_len) * sizeof(uint32_t)); - - return 0; - } -diff --git a/docs/devicetree/bindings/arm/secure.txt b/docs/devicetree/bindings/arm/secure.txt -new file mode 100644 -index 0000000000..e31303fb23 ---- /dev/null -+++ b/docs/devicetree/bindings/arm/secure.txt -@@ -0,0 +1,53 @@ -+* ARM Secure world bindings -+ -+ARM CPUs with TrustZone support have two distinct address spaces, -+"Normal" and "Secure". Most devicetree consumers (including the Linux -+kernel) are not TrustZone aware and run entirely in either the Normal -+world or the Secure world. However some devicetree consumers are -+TrustZone aware and need to be able to determine whether devices are -+visible only in the Secure address space, only in the Normal address -+space, or visible in both. (One example of that situation would be a -+virtual machine which boots Secure firmware and wants to tell the -+firmware about the layout of the machine via devicetree.) -+ -+The general principle of the naming scheme for Secure world bindings -+is that any property that needs a different value in the Secure world -+can be supported by prefixing the property name with "secure-". So for -+instance "secure-foo" would override "foo". For property names with -+a vendor prefix, the Secure variant of "vendor,foo" would be -+"vendor,secure-foo". If there is no "secure-" property then the Secure -+world value is the same as specified for the Normal world by the -+non-prefixed property. However, only the properties listed below may -+validly have "secure-" versions; this list will be enlarged on a -+case-by-case basis. -+ -+Defining the bindings in this way means that a device tree which has -+been annotated to indicate the presence of Secure-only devices can -+still be processed unmodified by existing Non-secure software (and in -+particular by the kernel). -+ -+Note that it is still valid for bindings intended for purely Secure -+world consumers (like kernels that run entirely in Secure) to simply -+describe the view of Secure world using the standard bindings. These -+secure- bindings only need to be used where both the Secure and Normal -+world views need to be described in a single device tree. -+ -+Valid Secure world properties: -+ -+- secure-status : specifies whether the device is present and usable -+ in the secure world. The combination of this with "status" allows -+ the various possible combinations of device visibility to be -+ specified. If "secure-status" is not specified it defaults to the -+ same value as "status"; if "status" is not specified either then -+ both default to "okay". This means the following combinations are -+ possible: -+ -+ /* Neither specified: default to visible in both S and NS */ -+ secure-status = "okay"; /* visible in both */ -+ status = "okay"; /* visible in both */ -+ status = "okay"; secure-status = "okay"; /* visible in both */ -+ secure-status = "disabled"; /* NS-only */ -+ status = "okay"; secure-status = "disabled"; /* NS-only */ -+ status = "disabled"; secure-status = "okay"; /* S-only */ -+ status = "disabled"; /* disabled in both */ -+ 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 0000000000..7d2b5be9d7 ---- /dev/null -+++ b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt -@@ -0,0 +1,496 @@ -+STMicroelectronics STM32 Peripheral Reset Clock Controller -+========================================================== -+ -+The RCC IP is both a reset and a clock controller. -+ -+RCC makes also power management (resume/supend and wakeup interrupt). -+ -+Please also refer to reset.txt for common reset controller binding usage. -+ -+Please also refer to clock-bindings.txt for common clock controller -+binding usage. -+ -+ -+Required properties: -+- compatible: "st,stm32mp1-rcc", "syscon" -+- reg: should be register base and length as documented in the datasheet -+- #clock-cells: 1, device nodes should specify the clock in their -+ "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. -+- 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 { -+ compatible = "st,stm32mp1-rcc", "syscon"; -+ reg = <0x50000000 0x1000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ interrupts = ; -+ secure-interrupts = ; -+ }; -+ -+Specifying clocks -+================= -+ -+All available clocks are defined as preprocessor macros in -+dt-bindings/clock/stm32mp1-clks.h header and can be used in device -+tree sources. -+ -+Specifying softreset control of devices -+======================================= -+ -+Device nodes should specify the reset channel required in their "resets" -+property, containing a phandle to the reset device node and an index specifying -+which channel to use. -+The index is the bit number within the RCC registers bank, starting from RCC -+base address. -+It is calculated as: index = register_offset / 4 * 32 + bit_offset. -+Where bit_offset is the bit offset within the register. -+ -+For example on STM32MP1, for LTDC reset: -+ ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset -+ = 0x180 / 4 * 32 + 0 = 3072 -+ -+The list of valid indices for STM32MP1 is available in: -+include/dt-bindings/reset-controller/stm32mp1-resets.h -+ -+This file implements defines like: -+#define LTDC_R 3072 -+ -+ -+Defining clock source distribution with property st,clksrc -+========================================================== -+ -+- st,clksrc : The clock sources configuration array in a platform specific -+ 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 -+ >; -+ -+Defining clock dividers with property st,clkdiv -+=============================================== -+ -+- st,clkdiv : The clock main dividers value specified in an array -+ in a platform specific order. -+ -+ When used, it shall describe the whole clock dividers tree. -+ -+ 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: -+ 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*/ -+ >; -+ -+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 -+======================================================== -+ -+- children for a PLL static configuration with "st,stm32mp1-pll" compatible -+ -+ Each PLL children nodes for PLL1 to PLL4 (see ref manual for details) -+ are listed with associated reg 0 to 3. -+ -+ PLL2, PLL3 or PLL4 are off when their associated nodes are absent or -+ deactivated. -+ -+ The configuration of PLL1, the source clock of Cortex-A7 core, with st,pll@0 -+ node, is optional as TF-A automatically selects the most suitable operating -+ point for the platform. -+ The node st,pll@0 node should be absent; it is only used if you want to -+ override the PLL1 properties computed by TF-A (clock spreading for example). -+ -+ Here are the available properties for each PLL node: -+ - compatible: should be "st,stm32mp1-pll" -+ -+ - 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) -+ 0x1: division by 2 -+ 0x2: division by 3 -+ 0x3: division by 4 -+ ... -+ -+ Output contains a bitfield for each output value (1:ON/0:OFF) -+ BIT(0) => output P : DIVPEN -+ BIT(1) => output Q : DIVQEN -+ BIT(2) => output R : DIVREN -+ 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). -+ -+ - 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 -+ SSCG_MODE: Spread spectrum clock generator mode, with associated -+ defined from stm32mp1-clksrc.h: -+ - SSCG_MODE_CENTER_SPREAD = 0 -+ - SSCG_MODE_DOWN_SPREAD = 1 -+ -+ Example: -+ st,pll@0 { -+ compatible = "st,stm32mp1-pll"; -+ reg = <0>; -+ cfg = <1 53 0 0 0 1>; -+ frac = <0x810>; -+ }; -+ st,pll@1 { -+ compatible = "st,stm32mp1-pll"; -+ reg = <1>; -+ cfg = <1 43 1 0 0 PQR(0,1,1)>; -+ csg = <10 20 1>; -+ }; -+ st,pll@2 { -+ compatible = "st,stm32mp1-pll"; -+ reg = <2>; -+ cfg = <2 85 3 13 3 0>; -+ csg = <10 20 SSCG_MODE_CENTER_SPREAD>; -+ }; -+ st,pll@3 { -+ compatible = "st,stm32mp1-pll"; -+ reg = <3>; -+ cfg = <2 78 4 7 9 3>; -+ }; -+ -+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 -+ -+At boot the clock tree initialization will -+ - 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: -+ / { -+ clocks { -+ clk_hse: clk-hse { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <64000000>; -+ st,bypass; -+ }; -+ -+ clk_lse: clk-lse { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32768>; -+ st,css; -+ st,drive = ; -+ }; -+ }; -+ -+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: -+ / { -+ clocks { -+ clk_hsi: clk-hsi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <64000000>; -+ }; -+ }; -+ -+ Example with HSIDIV = /2 -+ / { -+ clocks { -+ clk_hsi: clk-hsi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32000000>; -+ }; -+ }; -+ -+HSI & CSI calibration -+======================== -+ -+Calibration is an optional feature that may be enabled from device tree. It -+allows to request calibration of the HSI or the CSI clocks from several means: -+ - SiP SMC service -+ - Periodic calibration every X seconds -+ - Interrupt raised by the MCU -+ -+This feature requires that a HW timer is assigned to the calibration sequence. -+ -+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. -+ -+- st,csi-cal; used to enable CSI clock calibration feature. -+ -+- st,cal-sec: used to enable periodic calibration every specified seconds from -+ secure monitor. Time must be given in seconds. If not specified, calibration -+ is processed for each incoming request. -+ -+Example: -+ &rcc { -+ st,hsi-cal; -+ st,csi-cal; -+ st,cal-sec = <15>; -+ secure-interrupts = , -+ ; -+ 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 0000000000..68aefa6dc4 ---- /dev/null -+++ b/docs/devicetree/bindings/i2c/i2c-stm32.txt -@@ -0,0 +1,54 @@ -+* I2C controller embedded in STMicroelectronics STM32 I2C platform -+ -+Required properties : -+- compatible : Must be one of the following -+ - "st,stm32f7-i2c" -+- reg : Offset and length of the register set for the device -+- resets: Must contain the phandle to the reset controller. -+- clocks: Must contain the input clock of the I2C instance. -+- A pinctrl state named "default" must be defined to set pins in mode of -+ operation for I2C transfer. An optional pinctrl state named "sleep" has to -+ be defined as well as to put I2C in low power mode in suspend mode. -+- #address-cells = <1>; -+- #size-cells = <0>; -+ -+Optional properties : -+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified, -+ the default 100 kHz frequency will be used. -+- i2c-scl-rising-time-ns : Only for STM32F7, I2C SCL Rising time for the board -+ (default: 25) -+- i2c-scl-falling-time-ns : Only for STM32F7, I2C SCL Falling time for the board -+ (default: 10) -+ I2C Timings are derived from these 2 values -+- st,syscfg-fmp: Only for STM32F7, use to set Fast Mode Plus bit within SYSCFG -+ whether Fast Mode Plus speed is selected by slave. -+ 1st cell : phandle to syscfg -+ 2nd cell : register offset within SYSCFG -+ 3rd cell : register bitmask for FMP bit -+ -+Example : -+ -+ i2c@40005400 { -+ compatible = "st,stm32f4-i2c"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x40005400 0x400>; -+ resets = <&rcc 277>; -+ clocks = <&rcc 0 149>; -+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>; -+ pinctrl-names = "default"; -+ }; -+ -+ i2c@40005400 { -+ compatible = "st,stm32f7-i2c"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x40005400 0x400>; -+ resets = <&rcc STM32F7_APB1_RESET(I2C1)>; -+ clocks = <&rcc 1 CLK_I2C1>; -+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>; -+ pinctrl-1 = <&i2c1_sda_pin_sleep>, <&i2c1_scl_pin_sleep>; -+ pinctrl-names = "default", "sleep"; -+ 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 0000000000..ac6a7df432 ---- /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 0000000000..6d3c626e01 ---- /dev/null -+++ b/docs/devicetree/bindings/mmc/mmci.txt -@@ -0,0 +1,72 @@ -+* ARM PrimeCell MultiMedia Card Interface (MMCI) PL180/1 -+ -+The ARM PrimeCell MMCI PL180 and PL181 provides an interface for -+reading and writing to MultiMedia and SD cards alike. -+ -+This file documents differences between the core properties described -+by mmc.txt and the properties used by the mmci driver. Using "st" as -+the prefix for a property, indicates support by the ST Micro variant. -+ -+Required properties: -+- compatible : contains "arm,pl18x", "arm,primecell". -+- vmmc-supply : phandle to the regulator device tree node, mentioned -+ as the VCC/VDD supply in the eMMC/SD specs. -+ -+Optional properties: -+- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides -+ the ID provided by the HW -+- resets : phandle to internal reset line. -+ Should be defined for sdmmc variant. -+- vqmmc-supply : phandle to the regulator device tree node, mentioned -+ as the VCCQ/VDD_IO supply in the eMMC/SD specs. -+specific for ux500 variant: -+- st,sig-dir-dat0 : bus signal direction pin used for DAT[0]. -+- st,sig-dir-dat2 : bus signal direction pin used for DAT[2]. -+- st,sig-dir-dat31 : bus signal direction pin used for DAT[3] and DAT[1]. -+- st,sig-dir-dat74 : bus signal direction pin used for DAT[4] to DAT[7]. -+- st,sig-dir-cmd : cmd signal direction pin used for CMD. -+- st,sig-pin-fbclk : feedback clock signal pin used. -+ -+specific for sdmmc variant: -+- st,sig-dir : signal direction polarity used for cmd, dat0 dat123. -+- st,neg-edge : data & command phase relation, generated on -+ sd clock falling edge. -+- st,use-ckin : use ckin pin from an external driver to sample -+ the receive data (example: with voltage -+ switch transceiver). -+ -+Deprecated properties: -+- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable. -+- mmc-cap-sd-highspeed : indicates whether SD is high speed capable. -+ -+Example: -+ -+sdi0_per1@80126000 { -+ compatible = "arm,pl18x", "arm,primecell"; -+ reg = <0x80126000 0x1000>; -+ interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>; -+ -+ dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */ -+ <&dma 29 0 0x0>; /* Logical - MemToDev */ -+ dma-names = "rx", "tx"; -+ -+ clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>; -+ clock-names = "sdi", "apb_pclk"; -+ -+ max-frequency = <100000000>; -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ cd-gpios = <&gpio2 31 0x4>; // 95 -+ st,sig-dir-dat0; -+ st,sig-dir-dat2; -+ st,sig-dir-cmd; -+ st,sig-pin-fbclk; -+ -+ vmmc-supply = <&ab8500_ldo_aux3_reg>; -+ vqmmc-supply = <&vmmci>; -+ -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&sdi0_default_mode>; -+ pinctrl-1 = <&sdi0_sleep_mode>; -+}; -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 0000000000..51576a3844 ---- /dev/null -+++ b/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt -@@ -0,0 +1,22 @@ -+* STMicroelectronics STM32 SDMMC2 controller -+ -+The highspeed MMC host controller on STM32 soc family -+provides an interface for MMC, SD and SDIO types of memory cards. -+ -+This file documents differences between the core properties described -+by mmci.txt and the properties used by the sdmmc2 driver. -+ -+Required properties: -+ - compatible: should be one of: -+ "st,stm32-sdmmc2" -+ -+Example: -+ sdmmc1: sdmmc@0x58005000 { -+ compatible = "st,stm32-sdmmc2"; -+ reg = <0x58005000 0x1000>; -+ clocks = <&rcc SDMMC1_K>; -+ resets = <&rcc SDMMC1_R>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ status = "disabled"; -+ }; -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 0000000000..22779b05af ---- /dev/null -+++ b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt -@@ -0,0 +1,43 @@ -+STMicroelectronics STM32MP1 Power Management Controller -+======================================================= -+ -+The PWR IP is responsible for handling the power related resources such as -+clocks, power supplies and resets. It provides 6 wake-up pins that are handled -+by an interrupt-controller. Wake-up pin can be used to wake-up from STANDBY SoC -+state. -+ -+Required properties: -+- compatible should be: "st,stm32mp1-pwr", "st,stm32-pwr" -+- reg: should be register base and length as documented in the -+ datasheet -+ -+Optional Properties: -+- Nodes corresponding to PSCI commands issued by kernel: -+ - system_suspend_supported_soc_modes: list of supported SoC modes in suspend -+ - system_off_soc_mode: SoC mode for shutdown -+ - st,retram-enabled-in-standby-ddr-sr: enable retram during standby-ddr-sr -+ -+The list of SoC modes is in include/dt-bindings/power/stm32mp1-power.h: -+ - modes for system_suspend -+ 1 -> STM32_PM_CSTOP_ALLOW_STOP -+ 2 -> STM32_PM_CSTOP_ALLOW_LP_STOP -+ 3 -> STM32_PM_CSTOP_ALLOW_LPLV_STOP -+ 4 -> STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR -+ - modes for system_off -+ 6 -> STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF -+ 7 -> STM32_PM_SHUTDOWN -+ -+Example: -+ -+pwr: pwr@50001000 { -+ compatible = "st,stm32mp1-pwr", "st,stm32-pwr", "syscon", "simple-mfd"; -+ reg = <0x50001000 0x400>; -+ -+ 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 = ; -+}; -diff --git a/docs/devicetree/bindings/power/st,stpmic1.txt b/docs/devicetree/bindings/power/st,stpmic1.txt -new file mode 100644 -index 0000000000..83307d23b4 ---- /dev/null -+++ b/docs/devicetree/bindings/power/st,stpmic1.txt -@@ -0,0 +1,94 @@ -+* STMicroelectronics STPMIC1 Power Management IC -+ -+Required parent device properties: -+- compatible: "st,stpmic1" -+- reg: The I2C slave address for the STPMIC1 chip. -+- interrupts: The interrupt lines the device is connected to. -+ The second interrupt is used for wake-up. -+- #interrupt-cells: Should be 2. -+- interrupt-controller: Describes the STPMIC1 as an interrupt -+ controller (has its own domain). Interrupt number are the following: -+ /* Interrupt Register 1 (0x50 for latch) */ -+ IT_SWOUT_R=0 -+ IT_SWOUT_F=1 -+ IT_VBUS_OTG_R=2 -+ IT_VBUS_OTG_F=3 -+ IT_WAKEUP_R=4 -+ IT_WAKEUP_F=5 -+ IT_PONKEY_R=6 -+ IT_PONKEY_F=7 -+ /* Interrupt Register 2 (0x51 for latch) */ -+ IT_OVP_BOOST=8 -+ IT_OCP_BOOST=9 -+ IT_OCP_SWOUT=10 -+ IT_OCP_OTG=11 -+ IT_CURLIM_BUCK4=12 -+ IT_CURLIM_BUCK3=13 -+ IT_CURLIM_BUCK2=14 -+ IT_CURLIM_BUCK1=15 -+ /* Interrupt Register 3 (0x52 for latch) */ -+ IT_SHORT_SWOUT=16 -+ IT_SHORT_SWOTG=17 -+ IT_CURLIM_LDO6=18 -+ IT_CURLIM_LDO5=19 -+ IT_CURLIM_LDO4=20 -+ IT_CURLIM_LDO3=21 -+ IT_CURLIM_LDO2=22 -+ IT_CURLIM_LDO1=23 -+ /* Interrupt Register 3 (0x52 for latch) */ -+ IT_SWIN_R=24 -+ IT_SWIN_F=25 -+ IT_RESERVED_1=26 -+ IT_RESERVED_2=27 -+ IT_VINLOW_R=28 -+ IT_VINLOW_F=29 -+ IT_TWARN_R=30 -+ IT_TWARN_F=31 -+ -+STPMIC1 consists in a varied group of sub-devices. -+Each sub-device binding is be described in own documentation file. -+ -+Device Description -+------ ------------ -+st,stpmic1-onkey : Power on key, see ../input/st,stpmic1-onkey.txt -+st,stpmic1-regulators : Regulators, see ../regulator/st,stpmic1-regulator.txt -+st,stpmic1-wdt : Watchdog, see ../watchdog/st,stpmic1-wdt.txt -+ -+Example: -+ -+pmic: pmic@33 { -+ compatible = "st,stpmic1"; -+ reg = <0x33>; -+ interrupt-parent = <&gpioa>; -+ interrupts = <0 2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ -+ onkey { -+ compatible = "st,stpmic1-onkey"; -+ interrupts = ,; -+ interrupt-names = "onkey-falling", "onkey-rising"; -+ power-off-time-sec = <10>; -+ }; -+ -+ watchdog { -+ compatible = "st,stpmic1-wdt"; -+ }; -+ -+ regulators { -+ compatible = "st,stpmic1-regulators"; -+ -+ vdd_core: buck1 { -+ regulator-name = "vdd_core"; -+ regulator-boot-on; -+ regulator-min-microvolt = <700000>; -+ regulator-max-microvolt = <1200000>; -+ }; -+ vdd: buck3 { -+ regulator-name = "vdd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-pull-down; -+ }; -+ }; -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 0000000000..b4edaf7c7f ---- /dev/null -+++ b/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt -@@ -0,0 +1,6 @@ -+STMicroelectronics STM32MP1 Peripheral Reset Controller -+======================================================= -+ -+The RCC IP is both a reset and a clock controller. -+ -+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 0000000000..3c613d7914 ---- /dev/null -+++ b/docs/devicetree/bindings/rng/st,stm32-rng.txt -@@ -0,0 +1,23 @@ -+STMicroelectronics STM32 HW RNG -+=============================== -+ -+The STM32 hardware random number generator is a simple fixed purpose IP and -+is fully separated from other crypto functions. -+ -+Required properties: -+ -+- compatible : Should be "st,stm32-rng" -+- reg : Should be register base and length as documented in the datasheet -+- clocks : The clock needed to enable the RNG -+ -+Optional properties: -+- resets : The reset to properly start RNG -+- clock-error-detect : Enable the clock detection management -+ -+Example: -+ -+ rng: rng@50060800 { -+ compatible = "st,stm32-rng"; -+ reg = <0x50060800 0x400>; -+ clocks = <&rcc 0 38>; -+ }; -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 0000000000..08b499045a ---- /dev/null -+++ b/docs/devicetree/bindings/serial/st,stm32-usart.txt -@@ -0,0 +1,88 @@ -+* STMicroelectronics STM32 USART -+ -+Required properties: -+- compatible: can be either: -+ - "st,stm32-uart", -+ - "st,stm32f7-uart", -+ - "st,stm32h7-uart". -+ depending is compatible with stm32(f4), stm32f7 or stm32h7. -+- reg: The address and length of the peripheral registers space -+- interrupts: -+ - The interrupt line for the USART instance, -+ - An optional wake-up interrupt. -+- interrupt-names: Contains "event" for the USART interrupt line. -+- clocks: The input clock of the USART instance -+ -+Optional properties: -+- resets: Must contain the phandle to the reset controller. -+- pinctrl-names: Set to "default". An additional "sleep" state can be defined -+ to set pins in sleep state when in low power. In case the device is used as -+ a wakeup source, "idle" state is defined in order to keep RX pin active. -+ For a console device, an optional state "no_console_suspend" can be defined -+ to enable console messages during suspend. Typically, "no_console_suspend" and -+ "default" states can refer to the same pin configuration. -+- pinctrl-n: Phandle(s) pointing to pin configuration nodes. -+ For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt -+- st,hw-flow-ctrl: bool flag to enable hardware flow control. -+- rs485-rts-delay, rs485-rx-during-tx, rs485-rts-active-low, -+ linux,rs485-enabled-at-boot-time: see rs485.txt. -+- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt -+- dma-names: "rx" and/or "tx" -+- wakeup-source: bool flag to indicate this device has wakeup capabilities -+- interrupt-names : Should contain "wakeup" if optional wake-up interrupt is -+ used. -+ -+Note for dma using: -+- "tx" dma can be used without any constraint since it uses single -+dma transfers. -+- "rx" dma using requires some attention: -+ 1) if you cannot anticipate the length of your received packets -+ and if your usart device embeds an internal fifo, then DON'T use -+ dma mode. -+ 2) if you enable dma mode WITHOUT mdma intermediate copy (cf. -+ stm32-dma.txt), then the availability of the received data will -+ depend on the dma driver policy and it may be delayed until dma -+ internal fifo is full. The usart driver will see this checking -+ the dma residue when rx interrupt (RXNE or RTO) occurs. -+ 3) if you enable dma mode WITH mdma intermediate copy (cf. -+ stm32-dma.txt) then the usart driver will never see the dma -+ residue becoming smaller than RX_BUF_P but it will get its -+ rx dma complete callback called when the cyclic transfer period -+ (RX_BUF_P) is reached. -+The three possibilities above are ordered from the most cpu time -+consuming one to the least one. The counterpart of this optimisation -+is the reception granularity achievable by the usart driver, from -+one byte up to RX_BUF_P. -+ -+Examples: -+usart4: serial@40004c00 { -+ compatible = "st,stm32-uart"; -+ reg = <0x40004c00 0x400>; -+ interrupts = <52>; -+ clocks = <&clk_pclk1>; -+ pinctrl-names = "default", "sleep", "idle", "no_console_suspend"; -+ pinctrl-0 = <&pinctrl_usart4>; -+ pinctrl-1 = <&pinctrl_usart4_sleep>; -+ pinctrl-2 = <&pinctrl_usart4_idle>; -+ pinctrl-3 = <&pinctrl_usart4>; -+}; -+ -+usart2: serial@40004400 { -+ compatible = "st,stm32-uart"; -+ reg = <0x40004400 0x400>; -+ interrupts = <38>; -+ clocks = <&clk_pclk1>; -+ st,hw-flow-ctrl; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rtscts>; -+}; -+ -+usart1: serial@40011000 { -+ compatible = "st,stm32-uart"; -+ reg = <0x40011000 0x400>; -+ interrupts = <37>; -+ clocks = <&rcc 0 164>; -+ dmas = <&dma2 2 4 0x414 0x0>, -+ <&dma2 7 4 0x414 0x0>; -+ dma-names = "rx", "tx"; -+}; -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 0000000000..a2ac263cec ---- /dev/null -+++ b/docs/devicetree/bindings/soc/st,stm32-etzpc.txt -@@ -0,0 +1,56 @@ -+STM32 ETZPC -+--------------------------------- -+ -+Required properties: -+- compatible: should be "st,stm32-etzpc" -+- reg: physical base address and length of the registers set for the device -+- clocks: reference to the clock entry -+ -+Optional property: -+- st,decprot: Configure option to properly set firewall for IPs. -+ -+Examples: -+etzpc: etzpc@5C007000 { -+ compatible = "st,stm32-etzpc"; -+ reg = <0x5C007000 0x400>; -+ clocks = <&rcc TZPC>; -+ status = "disabled"; -+ secure-status = "okay"; -+ }; -+ -+Firewall specifications -+======================= -+ -+DECPROT macro must be used to properly configure IP firewalling. It must -+specify ID, domain and locking register status. -+ -+The macro is defined in the binding header file [1]. -+ -+Example: -+ ... { -+ st,decprot = < -+ DECPROT(STM32MP1_ETZPC_I2C4_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_GPIOZ_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>; -+ }; -+ -+Specify Peripheral IDs -+======================= -+ -+Each peripheral is identified with a specific ID. Each platform defines the -+identifiers relevant to that platform. Peripheral IDs are defined in [1]. -+ -+Specify domain -+============== -+Firewall controls peripherals in specific domains: -+ -+DECPROT_S_RW 0x0 -> Read/write Secure -+DECPROT_NS_R_S_W 0x1 -> Non secure read / Read/write Secure -+DECPROT_MCU_ISOLATION 0x2 -> MCU access only -+DECPROT_NS_RW 0x3 -> Non secure read/write -+ -+ -+[1] include/dt-bindings/soc/st,stm32-etzpc.h -+ -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 0000000000..c430fb84d7 ---- /dev/null -+++ b/docs/devicetree/bindings/soc/st,stm32-romem.txt -@@ -0,0 +1,74 @@ -+STMicroelectronics STM32 Factory-programmed data device tree bindings -+ -+This represents STM32 Factory-programmed read only non-volatile area: locked -+flash, OTP, read-only HW regs... This contains various information such as: -+analog calibration data for temperature sensor (e.g. TS_CAL1, TS_CAL2), -+internal vref (VREFIN_CAL), unique device ID... -+ -+Required properties: -+- compatible: Should be one of: -+ "st,stm32-romem" -+ "st,stm32mp15-bsec" -+- reg: Offset and length of factory-programmed area. -+- #address-cells: Should be '<1>'. -+- #size-cells: Should be '<1>'. -+ -+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"; -+ reg = <0x1fff7800 0x400>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ /* Data cells: ts_cal1 at 0x1fff7a2c */ -+ ts_cal1: calib@22c { -+ reg = <0x22c 0x2>; -+ }; -+ ... -+ }; -+ -+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 0000000000..dbd962ebc4 ---- /dev/null -+++ b/docs/devicetree/bindings/soc/st,stm32-stgen.txt -@@ -0,0 +1,18 @@ -+STMicroelectronics STM32 STGEN -+=============================== -+ -+The STM32 System Generic Counter generate a time count value. This -+is a 64 bits wide counter. -+ -+Required properties: -+ -+- compatible : Should be "st,stm32-stgen" -+- reg : Should be register base and length as documented in the datasheet -+ -+Example: -+ -+ stgen: stgen@5C008000 { -+ compatible = "st,stm32-stgen"; -+ reg = <0x5C008000 0x1000>; -+ status = "okay"; -+ }; -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 0000000000..4d21c6b8a3 ---- /dev/null -+++ b/docs/devicetree/bindings/soc/st,stm32-tamp.txt -@@ -0,0 +1,22 @@ -+STM32 TAMPER -+--------------------------------- -+ -+Required properties: -+- compatible: should be "st,stm32-tamp" -+- reg: physical base address and length of the registers set for the device -+- clocks: reference to the clock entry -+- secure-status: Required to properly disable/enable secure IP -+ -+Optional property: -+- st,out3-pc13: Configure option register to map OUT3 on PC13 -+- wakeup-source : Configure tamp as wakeup-src -+ -+Examples: -+tamp: tamp@5C00A000 { -+ compatible = "st,stm32-tamp"; -+ reg = <0x5C00A000 0x100>; -+ clocks = <&rcc_clk RTCAPB>; -+ st,out3-pc13; -+ wakeup-source; -+ secure-status = "okay"; -+}; -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 0000000000..2453603a17 ---- /dev/null -+++ b/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt -@@ -0,0 +1,28 @@ -+STM32 Independent WatchDoG (IWDG) -+--------------------------------- -+ -+Required properties: -+- compatible: should be "st,stm32mp1-iwdg". -+- reg: physical base address and length of the registers set for the device. -+- clocks: reference to the clock entry lsi. Additional pclk clock entry. -+ is required only for st,stm32mp1-iwdg. -+- clock-names: name of the clocks used. -+ "pclk", "lsi" for st,stm32mp1-iwdg. -+ -+Optional properties: -+- timeout-sec: Watchdog timeout value in seconds. -+- secure-timeout-sec: Watchdog early timeout management in seconds. -+- stm32,enable-on-stop: Keep watchdog enable during stop. -+- stm32,enable-on-standby: Keep watchdog enable durung standby. -+- secure-status: Required to properly enable/disable secure IP. -+ -+Examples: -+ -+iwdg2: iwdg@5a002000 { -+ compatible = "st,stm32mp1-iwdg"; -+ reg = <0x5a002000 0x400>; -+ clocks = <&rcc IWDG2>, <&clk_lsi>; -+ clock-names = "pclk", "lsi"; -+ instance = <2>; -+ timeout-sec = <30>; -+}; -diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst -index 19e26e4ea1..ba816fae58 100644 ---- a/docs/getting_started/porting-guide.rst -+++ b/docs/getting_started/porting-guide.rst -@@ -796,6 +796,31 @@ The function returns 0 on success. Any other value means the counter value - either could not be updated or the authentication image descriptor indicates - that it is not allowed to be updated. - -+Function: plat_get_hashed_pk() -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+ -+:: -+ -+ Argument : void *, unsigned int, void **, unsigned int * -+ Return : int -+ -+This function is optional when Trusted Board Boot is enabled, and only -+used if the platform saves a hash of the ROTPK. -+First argument is the BER ROTPK. -+Second argument is its size. -+Third argument is used to return a pointer to a buffer, which hash should -+be the one saved in OTP -+Fourth argument is a pointer to return its size -+ -+Most platforms save the hash of the BER ROTPK, but some may save the hash of -+a non encapsulated public key or a platform specific encapsulated ROT public -+key. Defining this function allows to transform the BER ROTPK used to verify -+the signature to the buffer (a platform specific encapsulated public key) which -+hash is saved in OTP. -+ -+The function returns 0 on success. Any other value means the expected -+public key buffer cannot be extracted from the BER public key. -+ - Common mandatory function modifications - --------------------------------------- - -diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst -index f597460db2..fb7afdbbb0 100644 ---- a/docs/plat/stm32mp1.rst -+++ b/docs/plat/stm32mp1.rst -@@ -37,6 +37,15 @@ The TF-A image must be properly formatted with a STM32 header structure - for ROM code is able to load this image. - Tool stm32image can be used to prepend this header to the generated TF-A binary. - -+Boot with FIP -+~~~~~~~~~~~~~ -+The use of FIP is now the recommended way to boot STM32MP1 platform. -+Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are -+inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective -+device tree blobs. -+ -+STM32IMAGE bootchain (deprecated) -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - At compilation step, BL2, BL32 and DTB file are linked together in a single - binary. The stm32image tool is also generated and the header is added to TF-A - binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32. -@@ -55,15 +64,17 @@ Memory mapping - | ... | - | | - 0x2FFC0000 +-----------------+ \ -- | | | -+ | BL32 DTB | | -+ 0x2FFC5000 +-----------------+ | -+ | BL32 | | -+ 0x2FFDF000 +-----------------+ | - | ... | | -- | | | -- 0x2FFD8000 +-----------------+ | -- | TF-A DTB | | Embedded SRAM -- 0x2FFDC000 +-----------------+ | -+ 0x2FFE3000 +-----------------+ | -+ | BL2 DTB | | Embedded SRAM -+ 0x2FFEA000 +-----------------+ | - | BL2 | | -- 0x2FFEF000 +-----------------+ | -- | BL32 | | -+ 0x2FFFF000 +-----------------+ | -+ | SCMI mailbox | | - 0x30000000 +-----------------+ / - | | - | ... | -@@ -95,41 +106,169 @@ 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 and support for all bootable devices: -+Boot with FIP -+~~~~~~~~~~~~~ -+You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary. -+ -+U-Boot -+______ - - .. code:: bash - -- 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 OP-TEE support for all bootable devices: -+OP-TEE (optional) -+_________________ -+ - .. code:: bash - -- 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 -+ make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \ -+ CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts -+ -+ -+TF-A BL32 (SP_min) -+__________________ -+If you choose not to use OP-TEE, you can use TF-A SP_min. -+To build TF-A BL32, and its device tree file: -+ -+.. code:: bash -+ -+ make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -+ AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb bl32 dtbs -+ -+TF-A BL2 -+________ -+To build TF-A BL2 with its STM32 header for SD-card boot: -+ -+.. code:: bash -+ -+ make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -+ DTB_FILE_NAME=stm32mp157c-ev1.dtb -+ -+This BL2 is independent of the BL32 used (SP_min or OP-TEE) -+ -+ -+FIP -+___ -+With BL32 SP_min: -+ -+.. code:: bash -+ -+ make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -+ AARCH32_SP=sp_min \ -+ DTB_FILE_NAME=stm32mp157c-ev1.dtb \ -+ BL33=/u-boot-nodtb.bin \ -+ BL33_CFG=/u-boot.dtb \ -+ fip -+ -+With OP-TEE: -+ -+.. code:: bash -+ -+ make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -+ DTB_FILE_NAME=stm32mp157c-ev1.dtb \ -+ BL33=/u-boot-nodtb.bin \ -+ BL33_CFG=/u-boot.dtb \ -+ BL32=/tee-header_v2.bin \ -+ BL32_EXTRA1=/tee-pager_v2.bin -+ BL32_EXTRA2=/tee-pageable_v2.bin -+ fip -+ -+Trusted Boot Board -+__________________ -+ -+.. code:: shell -+ -+ tools/cert_create/cert_create -n --rot-key "build/stm32mp1/debug/rot_key.pem" \ -+ --tfw-nvctr 0 \ -+ --ntfw-nvctr 0 \ -+ --key-alg ecdsa --hash-alg sha256 \ -+ --trusted-key-cert build/stm32mp1/cert_images/trusted-key-cert.key-crt \ -+ --tb-fw=build/stm32mp1/debug/bl2.bin \ -+ --tb-fw-cert build/stm32mp1/cert_images/trusted-boot-fw.key-crt\ -+ --tos-fw /tee-header_v2.bin \ -+ --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \ -+ --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \ -+ --tos-fw-extra1 /tee-pager_v2.bin \ -+ --tos-fw-extra2 /tee-pageable_v2.bin \ -+ --nt-fw /u-boot-nodtb.bin \ -+ --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \ -+ --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \ -+ --hw-config /u-boot.dtb -+ --fw-config build/stm32mp1/debug/fdts/fw-config.dtb -+ -+ tools/fiptool/fiptool create --tos-fw /tee-header_v2.bin \ -+ --tos-fw-extra1 /tee-pager_v2.bin \ -+ --tos-fw-extra2 /tee-pageable_v2.bin \ -+ --nt-fw /u-boot-nodtb.bin \ -+ --hw-config /uboot-nodtb.dtb \ -+ --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \ -+ --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \ -+ --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \ -+ --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \ -+ --trusted-key-cert build/stm32mp1/cert_images/trusted-key-cert.key-crt \ -+ --tb-fw-cert build/stm32mp1/cert_images/trusted-boot-fw.key-crt stm32mp1.fip -+ -+ -+STM32IMAGE bootchain (deprecated) -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+You need to add the following flag to the make command: -+``STM32MP_USE_STM32IMAGE=1`` -+ -+To build with SP_min and support for SD-card boot: -+ -+.. code:: bash -+ -+ make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -+ AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ -+ STM32MP_USE_STM32IMAGE=1 -+ - cd - make stm32mp15_trusted_defconfig - make DEVICE_TREE=stm32mp157c-ev1 all - -+To build TF-A with OP-TEE support for SD-card boot: - --The following build options are supported: -+.. code:: bash - --- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. -+ make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -+ AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ -+ STM32MP_USE_STM32IMAGE=1 -+ -+ 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 - - - Populate SD-card - ---------------- - -+Boot with FIP -+~~~~~~~~~~~~~ -+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 (BL2) -+- fip: which contains the FIP binary -+ -+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. -+ -+STM32IMAGE bootchain (deprecated) -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The SD-card has to be formated with GPT. - It should contain at least those partitions: - -diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c -index 95a5e7f77f..fa32a695e0 100644 ---- a/drivers/arm/tzc/tzc400.c -+++ b/drivers/arm/tzc/tzc400.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include "tzc_common_private.h" - -@@ -60,18 +61,54 @@ static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val) - GATE_KEEPER_OS_SHIFT) & \ - GATE_KEEPER_OS_MASK) - -- - /* Define common core functions used across different TZC peripherals. */ - DEFINE_TZC_COMMON_WRITE_ACTION(400, 400) - DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400) - DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400) - DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400) - DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) -+DEFINE_TZC_COMMON_UPDATE_FILTERS(400, 400) - DEFINE_TZC_COMMON_CONFIGURE_REGION0(400) - DEFINE_TZC_COMMON_CONFIGURE_REGION(400) - -+static inline void tzc400_clear_it(long base, uint32_t filter) -+{ -+ mmio_write_32(base + INT_CLEAR, BIT(filter)); -+} -+ -+static inline uint32_t tzc400_get_int_by_filter(long base, uint32_t filter) -+{ -+ return (mmio_read_32(base + INT_STATUS) & BIT(filter)); -+} -+ -+#if DEBUG -+static unsigned long tzc400_get_fail_address(long base, uint32_t filter) -+{ -+ unsigned long fail_address; -+ -+ fail_address = mmio_read_32(base + FAIL_ADDRESS_LOW_OFF + -+ (filter * FILTER_OFFSET)); -+#ifdef __aarch64__ -+ fail_address += mmio_read_32(base + FAIL_ADDRESS_HIGH_OFF + -+ (filter * FILTER_OFFSET)) << 32; -+#endif -+ -+ return fail_address; -+} -+ -+static inline uint32_t tzc400_get_fail_id(long base, uint32_t filter) -+{ -+ return mmio_read_32(base + FAIL_ID + (filter * FILTER_OFFSET)); -+} -+ -+static inline uint32_t tzc400_get_fail_control(long base, uint32_t filter) -+{ -+ return mmio_read_32(base + FAIL_CONTROL_OFF + (filter * FILTER_OFFSET)); -+} -+#endif -+ - static unsigned int _tzc400_get_gate_keeper(uintptr_t base, -- unsigned int filter) -+ unsigned int filter) - { - unsigned int open_status; - -@@ -81,9 +118,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 +187,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 +204,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 +221,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 +229,16 @@ 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_update_filters(unsigned int region, unsigned int filters) -+{ -+ /* Do range checks on filters and regions. */ -+ assert(((filters >> tzc400.num_filters) == 0U) && -+ (region < tzc400.num_regions)); -+ -+ _tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters); - } - - void tzc400_enable_filters(void) -@@ -217,8 +261,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 +282,62 @@ void tzc400_disable_filters(void) - for (filter = 0; filter < tzc400.num_filters; filter++) - _tzc400_set_gate_keeper(tzc400.base, filter, 0); - } -+ -+void tzc400_it_handler(void) -+{ -+ uint32_t filter; -+ uint32_t filter_it_pending = tzc400.num_filters; -+#if DEBUG -+ uint32_t control_fail; -+ uint32_t fail_id; -+ unsigned long address_fail; -+#endif -+ -+ assert(tzc400.base != 0U); -+ -+ /* first display information conerning the fault access */ -+ for (filter = 0U; (filter < tzc400.num_filters) && -+ (filter_it_pending == tzc400.num_filters); 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!"); -+ panic(); -+ } -+ -+#if DEBUG -+ address_fail = tzc400_get_fail_address(tzc400.base, filter_it_pending); -+ ERROR("Illegal access to 0x%lx:\n", address_fail); -+ -+ fail_id = tzc400_get_fail_id(tzc400.base, filter_it_pending); -+ ERROR("\tFAIL_ID = 0x%x\n", fail_id); -+ -+ control_fail = tzc400_get_fail_control(tzc400.base, filter_it_pending); -+ -+ if (((control_fail & BIT(FAIL_CONTROL_NS_SHIFT)) >> FAIL_CONTROL_NS_SHIFT) == -+ FAIL_CONTROL_NS_NONSECURE) { -+ ERROR("\tNon-Secure\n"); -+ } else { -+ ERROR("\tSecure\n"); -+ } -+ -+ if (((control_fail & BIT(FAIL_CONTROL_PRIV_SHIFT)) >> FAIL_CONTROL_PRIV_SHIFT) == -+ FAIL_CONTROL_PRIV_PRIV) { -+ ERROR("\tPrivilege\n"); -+ } else { -+ ERROR("\tUnprivilege\n"); -+ } -+ -+ if (((control_fail & BIT(FAIL_CONTROL_DIR_SHIFT)) >> FAIL_CONTROL_DIR_SHIFT) == -+ FAIL_CONTROL_DIR_WRITE) { -+ ERROR("\tWrite\n"); -+ } else { -+ ERROR("\tRead\n"); -+ } -+#endif -+ -+ tzc400_clear_it(tzc400.base, filter_it_pending); -+} -diff --git a/drivers/arm/tzc/tzc_common_private.h b/drivers/arm/tzc/tzc_common_private.h -index 1d99077ad1..b2af140fb7 100644 ---- a/drivers/arm/tzc/tzc_common_private.h -+++ b/drivers/arm/tzc/tzc_common_private.h -@@ -89,6 +89,27 @@ - val); \ - } - -+/* -+ * It is used to modify the filters status for a defined region. -+ */ -+#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name) \ -+ static inline void _tzc##fn_name##_update_filters( \ -+ uintptr_t base, \ -+ unsigned int region_no, \ -+ unsigned int nbfilters, \ -+ unsigned int filters) \ -+ { \ -+ uint32_t filters_mask = GENMASK(nbfilters - 1U, 0); \ -+ \ -+ mmio_clrsetbits_32(base + \ -+ TZC_REGION_OFFSET( \ -+ TZC_##macro_name##_REGION_SIZE, \ -+ region_no) + \ -+ TZC_##macro_name##_REGION_ATTR_0_OFFSET, \ -+ filters_mask << TZC_REGION_ATTR_F_EN_SHIFT, \ -+ filters << TZC_REGION_ATTR_F_EN_SHIFT); \ -+ } -+ - /* - * It is used to program region 0 ATTRIBUTES and ACCESS register. - */ -diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c -index 91ee1bea97..a84787fc39 100644 ---- a/drivers/auth/auth_mod.c -+++ b/drivers/auth/auth_mod.c -@@ -30,6 +30,7 @@ - } while (0) - - #pragma weak plat_set_nv_ctr2 -+#pragma weak plat_get_hashed_pk - - - static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a, -@@ -201,6 +202,10 @@ static int auth_signature(const auth_method_param_sig_t *param, - NOTICE("ROTPK is not deployed on platform. " - "Skipping ROTPK verification.\n"); - } else { -+ /* platform may store the hash of a prefixed, suffixed or modified pk */ -+ rc = plat_get_hashed_pk(pk_ptr, pk_len, &pk_ptr, &pk_len); -+ return_if_error(rc); -+ - /* Ask the crypto-module to verify the key hash */ - rc = crypto_mod_verify_hash(pk_ptr, pk_len, - pk_hash_ptr, pk_hash_len); -@@ -292,6 +297,15 @@ int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused, - return plat_set_nv_ctr(cookie, nv_ctr); - } - -+int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, -+ void **hashed_pk_ptr, unsigned int *hashed_pk_len) -+{ -+ *hashed_pk_ptr = full_pk_ptr; -+ *hashed_pk_len = full_pk_len; -+ -+ return 0; -+} -+ - /* - * Return the parent id in the output parameter '*parent_id' - * -diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk -index 53ebe30b63..ace4312cf3 100644 ---- a/drivers/auth/mbedtls/mbedtls_common.mk -+++ b/drivers/auth/mbedtls/mbedtls_common.mk -@@ -16,7 +16,7 @@ endif - MBEDTLS_INC = -I${MBEDTLS_DIR}/include - - # Specify mbed TLS configuration file --MBEDTLS_CONFIG_FILE := "" -+MBEDTLS_CONFIG_FILE ?= "" - $(eval $(call add_define,MBEDTLS_CONFIG_FILE)) - - MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_common.c -diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c -index 129566bd69..7b3ecd1a31 100644 ---- a/drivers/auth/mbedtls/mbedtls_x509_parser.c -+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c -@@ -114,10 +114,10 @@ static int get_ext(const char *oid, void **ext, unsigned int *ext_len) - oid_len = mbedtls_oid_get_numeric_string(oid_str, - MAX_OID_STR_LEN, - &extn_oid); -- if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { -+ if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) { - return IMG_PARSER_ERR; - } -- if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { -+ if (((size_t)oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { - *ext = (void *)p; - *ext_len = (unsigned int)len; - return IMG_PARSER_OK; -diff --git a/drivers/auth/tbbr/tbbr_cot_bl1.c b/drivers/auth/tbbr/tbbr_cot_bl1.c -index e4c92213ae..15a35431d6 100644 ---- a/drivers/auth/tbbr/tbbr_cot_bl1.c -+++ b/drivers/auth/tbbr/tbbr_cot_bl1.c -@@ -150,21 +150,6 @@ static const auth_img_desc_t tb_fw_config = { - } - }; - --static const auth_img_desc_t fw_config = { -- .img_id = FW_CONFIG_ID, -- .img_type = IMG_RAW, -- .parent = &trusted_boot_fw_cert, -- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { -- [0] = { -- .type = AUTH_METHOD_HASH, -- .param.hash = { -- .data = &raw_data, -- .hash = &fw_config_hash -- } -- } -- } --}; -- - /* - * TBBR Chain of trust definition - */ -diff --git a/drivers/auth/tbbr/tbbr_cot_bl2.c b/drivers/auth/tbbr/tbbr_cot_bl2.c -index 65a0478abf..de7ad8f902 100644 ---- a/drivers/auth/tbbr/tbbr_cot_bl2.c -+++ b/drivers/auth/tbbr/tbbr_cot_bl2.c -@@ -671,6 +671,7 @@ static const auth_img_desc_t * const cot_desc[] = { - [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, - [BL33_IMAGE_ID] = &bl33_image, - [NT_FW_CONFIG_ID] = &nt_fw_config, -+ [FW_CONFIG_ID] = &fw_config, - #if defined(SPD_spmd) - [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert, - [SP_PKG1_ID] = &sp_pkg1, -diff --git a/drivers/auth/tbbr/tbbr_cot_common.c b/drivers/auth/tbbr/tbbr_cot_common.c -index ff3f22de15..279f30e2e2 100644 ---- a/drivers/auth/tbbr/tbbr_cot_common.c -+++ b/drivers/auth/tbbr/tbbr_cot_common.c -@@ -124,3 +124,18 @@ const auth_img_desc_t hw_config = { - } - } - }; -+ -+const auth_img_desc_t fw_config = { -+ .img_id = FW_CONFIG_ID, -+ .img_type = IMG_RAW, -+ .parent = &trusted_boot_fw_cert, -+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { -+ [0] = { -+ .type = AUTH_METHOD_HASH, -+ .param.hash = { -+ .data = &raw_data, -+ .hash = &fw_config_hash -+ } -+ } -+ } -+}; -diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -new file mode 100644 -index 0000000000..9336b88b4f ---- /dev/null -+++ b/drivers/clk/clk.c -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * Author(s): Ludovic Barre, for STMicroelectronics. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+static const clk_ops_t *ops; -+ -+int clk_enable(unsigned long id) -+{ -+ assert((ops != NULL) && (ops->enable != NULL)); -+ -+ return ops->enable(id); -+} -+ -+void clk_disable(unsigned long id) -+{ -+ assert((ops != NULL) && (ops->disable != NULL)); -+ -+ ops->disable(id); -+} -+ -+unsigned long clk_get_rate(unsigned long id) -+{ -+ assert((ops != NULL) && (ops->get_rate != NULL)); -+ -+ return ops->get_rate(id); -+} -+ -+int clk_get_parent(unsigned long id) -+{ -+ assert((ops != NULL) && (ops->get_parent != NULL)); -+ -+ return ops->get_parent(id); -+} -+ -+bool clk_is_enabled(unsigned long id) -+{ -+ assert((ops != NULL) && (ops->is_enabled != NULL)); -+ -+ return ops->is_enabled(id); -+} -+ -+/* -+ * Initialize the clk. The fields in the provided clk -+ * ops pointer must be valid. -+ */ -+void clk_register(const clk_ops_t *ops_ptr) -+{ -+ assert((ops_ptr != NULL) && (ops_ptr->enable != NULL) && -+ (ops_ptr->disable != NULL) && -+ (ops_ptr->get_rate != NULL) && -+ (ops_ptr->get_parent != NULL) && -+ (ops_ptr->is_enabled != NULL)); -+ -+ ops = ops_ptr; -+} -diff --git a/drivers/io/io_mtd.c b/drivers/io/io_mtd.c -index 7575fa2503..a9f41a18c6 100644 ---- a/drivers/io/io_mtd.c -+++ b/drivers/io/io_mtd.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -18,8 +18,9 @@ - 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 */ -+ unsigned long long pos; /* Offset in bytes */ -+ unsigned long long size; /* Size of device in bytes */ -+ unsigned long long extra_offset; /* Extra offset in bytes */ - } mtd_dev_state_t; - - io_type_t device_type_mtd(void); -@@ -110,16 +111,47 @@ static int free_dev_info(io_dev_info_t *dev_info) - return 0; - } - -+static int mtd_add_extra_offset(mtd_dev_state_t *cur, size_t *extra_offset) -+{ -+ io_mtd_ops_t *ops = &cur->dev_spec->ops; -+ int ret; -+ -+ if (ops->seek == NULL) { -+ return 0; -+ } -+ -+ ret = ops->seek(cur->base, cur->pos, extra_offset); -+ if (ret != 0) { -+ ERROR("%s: Seek error %d\n", __func__, ret); -+ return ret; -+ } -+ -+ 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; -+ io_block_spec_t *region; -+ size_t extra_offset = 0U; -+ int ret; - - assert((dev_info->info != 0UL) && (entity->info == 0UL)); - -+ region = (io_block_spec_t *)spec; - cur = (mtd_dev_state_t *)dev_info->info; - entity->info = (uintptr_t)cur; -- cur->offset = 0U; -+ cur->base = region->offset; -+ cur->pos = 0U; -+ cur->extra_offset = 0U; -+ -+ ret = mtd_add_extra_offset(cur, &extra_offset); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ cur->base += extra_offset; - - return 0; - } -@@ -128,6 +160,8 @@ static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, - static int mtd_seek(io_entity_t *entity, int mode, signed long long offset) - { - mtd_dev_state_t *cur; -+ size_t extra_offset = 0U; -+ int ret; - - assert((entity->info != (uintptr_t)NULL) && (offset >= 0)); - -@@ -140,22 +174,29 @@ static int mtd_seek(io_entity_t *entity, int mode, signed long long offset) - return -EINVAL; - } - -- cur->offset = offset; -+ cur->pos = offset; - break; - case IO_SEEK_CUR: -- if (((cur->offset + (unsigned long long)offset) >= -+ if (((cur->base + cur->pos + (unsigned long long)offset) >= - cur->size) || -- ((cur->offset + (unsigned long long)offset) < -- cur->offset)) { -+ ((cur->base + cur->pos + (unsigned long long)offset) < -+ cur->base + cur->pos)) { - return -EINVAL; - } - -- cur->offset += (unsigned long long)offset; -+ cur->pos += (unsigned long long)offset; - break; - default: - return -EINVAL; - } - -+ ret = mtd_add_extra_offset(cur, &extra_offset); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ cur->extra_offset = extra_offset; -+ - return 0; - } - -@@ -174,18 +215,19 @@ static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, - 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) { -+ cur->base + cur->pos, buffer, length); -+ if ((cur->base + cur->pos + length) > cur->dev_spec->device_size) { - return -EINVAL; - } - -- ret = ops->read(cur->offset, buffer, length, out_length); -+ ret = ops->read(cur->base + cur->pos + cur->extra_offset, buffer, -+ length, out_length); - if (ret < 0) { - return ret; - } - - assert(*out_length == length); -- cur->offset += *out_length; -+ cur->pos += *out_length; - - return 0; - } -diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c -index b5f6a10d38..42243ea096 100644 ---- a/drivers/mmc/mmc.c -+++ b/drivers/mmc/mmc.c -@@ -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); - } - -+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) - { -@@ -327,6 +333,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; -@@ -494,7 +527,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/mtd/nand/core.c b/drivers/mtd/nand/core.c -index 44b001e35b..d961c24630 100644 ---- a/drivers/mtd/nand/core.c -+++ b/drivers/mtd/nand/core.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -112,6 +112,47 @@ int nand_read(unsigned int offset, uintptr_t buffer, size_t length, - return 0; - } - -+int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset) -+{ -+ unsigned int block; -+ unsigned int offset_block; -+ unsigned int max_block; -+ int is_bad; -+ size_t count_bb = 0U; -+ -+ block = base / nand_dev.block_size; -+ -+ if (offset != 0U) { -+ offset_block = (base + offset - 1U) / nand_dev.block_size; -+ } else { -+ offset_block = block; -+ } -+ -+ max_block = nand_dev.size / nand_dev.block_size; -+ -+ while (block <= offset_block) { -+ if (offset_block >= max_block) { -+ return -EIO; -+ } -+ -+ is_bad = nand_dev.mtd_block_is_bad(block); -+ if (is_bad < 0) { -+ return is_bad; -+ } -+ -+ if (is_bad == 1) { -+ count_bb++; -+ offset_block++; -+ } -+ -+ block++; -+ } -+ -+ *extra_offset = count_bb * nand_dev.block_size; -+ -+ return 0; -+} -+ - struct nand_device *get_nand_device(void) - { - return &nand_dev; -diff --git a/drivers/mtd/nor/spi_nor.c b/drivers/mtd/nor/spi_nor.c -index 108f893d3f..2ed562a677 100644 ---- a/drivers/mtd/nor/spi_nor.c -+++ b/drivers/mtd/nor/spi_nor.c -@@ -103,7 +103,7 @@ static int spi_nor_ready(void) - 0 : 1; - } - -- return (((sr & SR_WIP) != 0U) ? 1 : 0); -+ return (((sr & SR_WIP) == 0U) ? 0 : 1); - } - - static int spi_nor_wait_ready(void) -@@ -131,7 +131,7 @@ static int spi_nor_macronix_quad_enable(void) - return ret; - } - -- if ((sr & SR_QUAD_EN_MX) == 0U) { -+ if ((sr & SR_QUAD_EN_MX) != 0U) { - return 0; - } - -@@ -141,7 +141,7 @@ static int spi_nor_macronix_quad_enable(void) - } - - sr |= SR_QUAD_EN_MX; -- ret = spi_nor_reg(SPI_NOR_OP_WRSR, &sr, 1, SPI_MEM_DATA_OUT); -+ ret = spi_nor_reg(SPI_NOR_OP_WRSR, &sr, 1U, SPI_MEM_DATA_OUT); - if (ret != 0) { - return ret; - } -@@ -168,7 +168,7 @@ static int spi_nor_write_sr_cr(uint8_t *sr_cr) - return ret; - } - -- ret = spi_nor_reg(SPI_NOR_OP_WRSR, sr_cr, 2, SPI_MEM_DATA_OUT); -+ ret = spi_nor_reg(SPI_NOR_OP_WRSR, sr_cr, 2U, SPI_MEM_DATA_OUT); - if (ret != 0) { - return -EINVAL; - } -@@ -230,7 +230,7 @@ static int spi_nor_clean_bar(void) - } - - return spi_nor_reg(nor_dev.bank_write_cmd, &nor_dev.selected_bank, -- 1, SPI_MEM_DATA_OUT); -+ 1U, SPI_MEM_DATA_OUT); - } - - static int spi_nor_write_bar(uint32_t offset) -@@ -248,7 +248,7 @@ static int spi_nor_write_bar(uint32_t offset) - } - - ret = spi_nor_reg(nor_dev.bank_write_cmd, &selected_bank, -- 1, SPI_MEM_DATA_OUT); -+ 1U, SPI_MEM_DATA_OUT); - if (ret != 0) { - return ret; - } -@@ -260,11 +260,11 @@ static int spi_nor_write_bar(uint32_t offset) - - static int spi_nor_read_bar(void) - { -- uint8_t selected_bank = 0; -+ uint8_t selected_bank = 0U; - int ret; - - ret = spi_nor_reg(nor_dev.bank_read_cmd, &selected_bank, -- 1, SPI_MEM_DATA_IN); -+ 1U, SPI_MEM_DATA_IN); - if (ret != 0) { - return ret; - } -@@ -280,7 +280,7 @@ int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, - size_t remain_len; - int ret; - -- *length_read = 0; -+ *length_read = 0U; - nor_dev.read_op.addr.val = offset; - nor_dev.read_op.data.buf = (void *)buffer; - -@@ -339,7 +339,7 @@ int spi_nor_init(unsigned long long *size, unsigned int *erase_size) - return -EINVAL; - } - -- assert(nor_dev.size != 0); -+ assert(nor_dev.size != 0U); - - if (nor_dev.size > BANK_SIZE) { - nor_dev.flags |= SPI_NOR_USE_BANK; -diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec2.c -similarity index 62% -rename from drivers/st/bsec/bsec.c -rename to drivers/st/bsec/bsec2.c -index 01c369edcd..de00a65812 100644 ---- a/drivers/st/bsec/bsec.c -+++ b/drivers/st/bsec/bsec2.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 - */ -@@ -14,11 +14,13 @@ - #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_VERSION_2_0 U(0x20) -+#define BSEC_IP_ID_2 U(0x100032) - - #define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) - -@@ -44,11 +46,12 @@ static void bsec_unlock(void) - } - } - -+#if defined(IMAGE_BL32) - 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; - } -@@ -56,7 +59,6 @@ static int bsec_get_dt_node(struct dt_node_info *info) - return node; - } - --#if defined(IMAGE_BL32) - static void enable_non_secure_access(uint32_t otp) - { - otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); -@@ -78,39 +80,85 @@ 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); - } - } - - return 0; - } -+ -+static void bsec_late_init(void) -+{ -+ 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(); -+ } -+ -+ assert(bsec_base == bsec_info.base); -+ -+ bsec_dt_otp_nsec_access(fdt, node); -+} - #endif - - static uint32_t otp_bank_offset(uint32_t otp) -@@ -121,19 +169,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; - } - -@@ -143,23 +202,16 @@ static uint32_t bsec_check_error(uint32_t otp) - */ - uint32_t bsec_probe(void) - { -- void *fdt; -- int node; -- struct dt_node_info bsec_info; -- -- if (fdt_get_address(&fdt) == 0) { -- panic(); -- } -+ bsec_base = BSEC_BASE; - -- node = bsec_get_dt_node(&bsec_info); -- if (node < 0) { -+ if ((((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) && -+ ((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_2_0)) || -+ (bsec_get_id() != BSEC_IP_ID_2)) { - panic(); - } - -- bsec_base = bsec_info.base; -- - #if defined(IMAGE_BL32) -- bsec_dt_otp_nsec_access(fdt, node); -+ bsec_late_init(); - #endif - return BSEC_OK; - } -@@ -251,6 +303,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; -+ } -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, 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. -@@ -259,14 +384,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); - } -@@ -283,14 +410,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 +437,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 +456,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 +491,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; -+ } -+ -+ 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; - } - -- /* Check if programming of OTP is locked */ -- if (bsec_read_sp_lock(otp)) { -+ 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 +527,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 +538,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 +590,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 +602,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,37 +617,46 @@ 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. -+ * return value: none. - */ --uint32_t bsec_write_debug_conf(uint32_t val) -+void bsec_write_debug_conf(uint32_t val) - { -- uint32_t result = BSEC_ERROR; -- uint32_t masked_val = val & BSEC_DEN_ALL_MSK; -- - 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; -- } -- -+ mmio_write_32(bsec_base + BSEC_DEN_OFF, val & BSEC_DEN_ALL_MSK); - bsec_unlock(); -- -- return result; - } - - /* -- * bsec_read_debug_conf: read debug configuration. -+ * bsec_read_debug_conf: return debug configuration register value. - */ - uint32_t bsec_read_debug_conf(void) - { - return mmio_read_32(bsec_base + BSEC_DEN_OFF); - } - -+/* -+ * bsec_write_scratch: write value in scratch register. -+ * val: value to write. -+ * return value: none. -+ */ -+void bsec_write_scratch(uint32_t val) -+{ -+ bsec_lock(); -+ mmio_write_32(bsec_base + BSEC_SCRATCH_OFF, val); -+ bsec_unlock(); -+} -+ -+/* -+ * bsec_read_scratch: return scratch register value. -+ */ -+uint32_t bsec_read_scratch(void) -+{ -+ return mmio_read_32(bsec_base + BSEC_SCRATCH_OFF); -+} -+ - /* - * bsec_get_status: return status register value. - */ -@@ -533,7 +666,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 +674,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 +682,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 +690,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 +698,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; -+ } -+ -+ bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); -+ -+ *value = ((bank_value & otp_mask) != 0U); - -- return (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; -+ } -+ -+ 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; -@@ -799,7 +881,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 +900,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 +922,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 +948,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 +958,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 0000000000..11a334303c ---- /dev/null -+++ b/drivers/st/clk/stm32mp1_calib.c -@@ -0,0 +1,536 @@ -+/* -+ * 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 -+#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_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_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) -+{ -+ 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 = 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 = 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 > INT32_MAX) { -+ timer_val = INT32_MAX; -+ } -+ -+ if (timer_val != 0U) { -+ /* Load & enable timer */ -+ INFO("Set calibration timer to %u sec\n", -+ timer_val / plat_get_syscnt_freq2()); -+ 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 564bd87989..00954cb2e8 100644 ---- a/drivers/st/clk/stm32mp1_clk.c -+++ b/drivers/st/clk/stm32mp1_clk.c -@@ -6,6 +6,7 @@ - - #include - #include -+#include - #include - #include - -@@ -17,8 +18,9 @@ - #include - #include - #include -+#include - #include --#include -+#include - #include - #include - #include -@@ -49,6 +51,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 */ - -@@ -239,6 +254,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 */ - }; -@@ -263,46 +279,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), \ - } -@@ -336,81 +365,105 @@ struct stm32mp1_clk_pll { - - #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_BDCR, 20, RTC, _RTC_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 -+ -+#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 -+ -+ _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), -+ -+ _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), - }; - - static const uint8_t i2c12_parents[] = { -@@ -465,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[] = { -@@ -512,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, -@@ -614,17 +666,55 @@ static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { - [_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", -+}; -+ - /* 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; -+#if STM32MP_SP_MIN_IN_DDR -+static uint32_t mpapb_iwdg1; -+static uint32_t mpapb_iwdg2; -+#endif - - 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]; -@@ -747,6 +837,12 @@ static int stm32mp1_clk_get_parent(unsigned long id) - 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]; - } - -@@ -847,9 +943,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; -@@ -1057,17 +1151,6 @@ 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) --{ -- int i = stm32mp1_clk_get_gated_id(id); -- -- if (i < 0) { -- panic(); -- } -- -- return gate_refcounts[i]; --} -- - /* Oscillators and PLLs are not gated at runtime */ - static bool clock_is_always_on(unsigned long id) - { -@@ -1086,17 +1169,19 @@ static bool clock_is_always_on(unsigned long id) - case PLL3_P: - case PLL3_Q: - case PLL3_R: -+ case CK_AXI: -+ case CK_MPU: -+ case CK_MCU: - return true; - default: - return false; - } - } - --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; -- unsigned int *refcnt; - - if (clock_is_always_on(id)) { - return; -@@ -1109,22 +1194,38 @@ void __stm32mp1_clk_enable(unsigned long id, bool secure) - } - - 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; -- unsigned int *refcnt; - - if (clock_is_always_on(id)) { - return; -@@ -1137,28 +1238,56 @@ void __stm32mp1_clk_disable(unsigned long id, bool secure) - } - - 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); - } - - stm32mp1_clk_unlock(&refcount_lock); - } - --void stm32mp_clk_enable(unsigned long id) -+static int stm32mp_clk_enable(unsigned long id) - { - __stm32mp1_clk_enable(id, true); -+ -+ return 0; - } - --void stm32mp_clk_disable(unsigned long id) -+static void stm32mp_clk_disable(unsigned long id) - { - __stm32mp1_clk_disable(id, true); - } - --bool stm32mp_clk_is_enabled(unsigned long id) -+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); -+} -+ -+static bool stm32mp_clk_is_enabled(unsigned long id) - { - int i; - -@@ -1174,15 +1303,55 @@ bool stm32mp_clk_is_enabled(unsigned long id) - return __clk_is_enabled(gate_ref(i)); - } - --unsigned long stm32mp_clk_get_rate(unsigned long id) -+static unsigned long stm32mp_clk_get_rate(unsigned long id) - { -+ uintptr_t rcc_base = stm32mp_rcc_base(); - int p = stm32mp1_clk_get_parent(id); -+ uint32_t prescaler, timpre; -+ unsigned long parent_rate; - - if (p < 0) { - return 0; - } - -- return get_clock_rate(p); -+ parent_rate = get_clock_rate(p); -+ -+ switch (id) { -+ case TIM2_K: -+ case TIM3_K: -+ case TIM4_K: -+ case TIM5_K: -+ case TIM6_K: -+ case TIM7_K: -+ case TIM12_K: -+ case TIM13_K: -+ case TIM14_K: -+ prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & -+ RCC_APBXDIV_MASK; -+ timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & -+ RCC_TIMGXPRER_TIMGXPRE; -+ break; -+ -+ case TIM1_K: -+ case TIM8_K: -+ case TIM15_K: -+ case TIM16_K: -+ case TIM17_K: -+ prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & -+ RCC_APBXDIV_MASK; -+ timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & -+ RCC_TIMGXPRER_TIMGXPRE; -+ break; -+ -+ default: -+ return parent_rate; -+ } -+ -+ if (prescaler == 0U) { -+ return parent_rate; -+ } -+ -+ return parent_rate * (timpre + 1U) * 2U; - } - - static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) -@@ -1299,6 +1468,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) -@@ -1498,11 +1674,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) & -@@ -1511,21 +1684,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); -@@ -1539,23 +1724,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); - -@@ -1662,48 +1863,41 @@ static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) - } - } - --static void stm32mp1_stgen_config(void) -+/******************************************************************************* -+ * 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 cntfid0; -- unsigned long rate; -- unsigned long long counter; -- -- cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); -- rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); -+ unsigned long apb1_freq; -+ uint32_t rtc_freq; -+ uint32_t apb1_div; -+ uintptr_t rcc_base = stm32mp_rcc_base(); - -- if (cntfid0 == rate) { -- return; -+ 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(); - } - -- mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); -- counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF); -- counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32; -- counter = (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((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 long cnt; -- -- cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | -- mmio_read_32(STGEN_BASE + CNTCVL_OFF); -- -- cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + 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_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); -+ return apb1_freq < (rtc_freq * 7U); - } - - static void stm32mp1_pkcs_config(uint32_t pkcs) -@@ -1720,152 +1914,740 @@ 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; -- void *fdt; -+ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID; -+} - -- if (fdt_get_address(&fdt) == 0) { -- return false; -- } -+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; - -- /* Check status field to disable security */ -- if (!fdt_get_rcc_secure_status()) { -- mmio_write_32(rcc_base + RCC_TZCR, 0); -+ return 0; - } - -- ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, -- clksrc); -- 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", (uint32_t)CLKDIV_NB, -- clkdiv); -- 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(fdt, plloff[i], "cfg", -- (int)PLLCFG_NB, pllcfg[i]); -- 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); -- if (ret != 0) { -+ -+ 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_set_clksrc(CLK_MCU_HSI); -+ -+ 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 ((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]); -+ if (config_on_the_fly == 1) { -+ /* No need to reconfigure, setup already OK */ -+ return 0; - } - -- for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { -- if (((i == _PLL3) && pll3_preserve) || -- ((i == _PLL4) && pll4_preserve)) { -- continue; -- } -- -- ret = stm32mp1_pll_stop(i); -+ 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; - } -- } - -- /* Configure HSIDIV */ -- if (stm32mp1_osc[_HSI] != 0U) { -- ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); -+ ret = stm32mp1_pll_stop(_PLL1); - if (ret != 0) { - return ret; - } -- stm32mp1_stgen_config(); - } - -- /* Select DIV */ -- /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ -- mmio_write_32(rcc_base + RCC_MPCKDIVR, -- clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); -+ ret = stm32mp1_pll_config(_PLL1, &pll1_settings.cfg[i][0], -+ pll1_settings.frac[i]); - if (ret != 0) { - return ret; - } -- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); -- if (ret != 0) { -+ -+ 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) -+{ -+ void *fdt; -+ int ret; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB, -+ pllcfg); -+ if (ret < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ *fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); -+ -+ ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB, -+ csg); -+ -+ *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; -+ void *fdt; -+ int stgen_p = stm32mp1_clk_get_parent((int)STGEN_K); -+ int usbphy_p = stm32mp1_clk_get_parent((int)USBPHY_K); -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, -+ clksrc); -+ if (ret < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, -+ clkdiv); -+ 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) { -+ const char *name = stm32mp_osc_node_label[_LSE]; -+ bool bypass, digbyp; -+ uint32_t lsedrv; -+ -+ bypass = fdt_clk_read_bool(name, "st,bypass"); -+ digbyp = fdt_clk_read_bool(name, "st,digbypass"); -+ lse_css = fdt_clk_read_bool(name, "st,css"); -+ lsedrv = fdt_clk_read_uint32_default(name, "st,drive", -+ LSEDRV_MEDIUM_HIGH); -+ stm32mp1_lse_enable(bypass, digbyp, lsedrv); -+ } -+ if (stm32mp1_osc[_HSE] != 0U) { -+ const char *name = stm32mp_osc_node_label[_HSE]; -+ bool bypass, digbyp, css; -+ -+ bypass = fdt_clk_read_bool(name, "st,bypass"); -+ digbyp = fdt_clk_read_bool(name, "st,digbypass"); -+ css = fdt_clk_read_bool(name, "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; -+ } -+ 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 == _PLL3) && pll3_preserve) || -+ ((i == _PLL4) && pll4_preserve)) { -+ continue; -+ } -+ -+ ret = stm32mp1_pll_stop(i); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ -+ /* Configure HSIDIV */ -+ if (stm32mp1_osc[_HSI] != 0U) { -+ ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); -+ } -+ -+ /* Select DIV */ -+ /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ -+ mmio_write_32(rcc_base + RCC_MPCKDIVR, -+ clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); -+ 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_APB5], rcc_base + RCC_APB5DIVR); -@@ -1915,15 +2697,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; - } - -@@ -1933,25 +2712,20 @@ int stm32mp1_clk_init(void) - continue; - } - -- fracv = fdt_read_uint32_default(fdt, 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(fdt, plloff[i], "csg", -- (uint32_t)PLLCSG_NB, csg); -- 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; - } - -@@ -1985,6 +2759,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]); -@@ -2005,13 +2784,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, -@@ -2200,6 +2999,429 @@ void stm32mp1_register_clock_parents_secure(unsigned long clock_id) - } - #endif /* STM32MP_SHARED_RESOURCES */ - -+/* -+ * 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; -+ -+ restore_mux_cfg(); -+ restore_sc_cfg(); -+ restore_regular_cfg(); -+ -+ /* 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; -+#if STM32MP_SP_MIN_IN_DDR -+ mpapb_iwdg2 = (mmio_read_32(rcc_base + RCC_MP_APB4ENSETR) & -+ RCC_MP_APB4ENSETR_IWDG2APBEN); -+ mpapb_iwdg1 = (mmio_read_32(rcc_base + RCC_MP_APB5ENSETR) & -+ RCC_MP_APB5ENSETR_IWDG1APBEN); -+#endif -+ -+ 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; -+ } -+ -+#if STM32MP_SP_MIN_IN_DDR -+ /* Restore IWDG clock */ -+ mmio_clrsetbits_32(rcc_base + RCC_MP_APB5ENSETR, -+ RCC_MP_APB5ENSETR_IWDG1APBEN, -+ mpapb_iwdg1); -+ -+ mmio_clrsetbits_32(rcc_base + RCC_MP_APB4ENSETR, -+ RCC_MP_APB4ENSETR_IWDG2APBEN, -+ mpapb_iwdg2); -+#endif -+ -+ disable_kernel_clocks(); -+ -+ return 0; -+} -+ -+void stm32mp1_clk_mcuss_protect(bool enable) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ if (enable) { -+ mmio_setbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); -+ } else { -+ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); -+ } -+} -+ -+/* 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); -+ unsigned long __unused clock_id = gate->index; -+ unsigned int __unused refcnt = gate_refcounts[idx]; -+ int __unused p = stm32mp1_clk_get_parent(clock_id); -+ -+ VERBOSE("stm32mp1 clk %lu %sabled (refcnt %d) (parent %d %s)\n", -+ clock_id, __clk_is_enabled(gate) ? "en" : "dis", -+ refcnt, p, -+ p < 0 ? "n.a" : stm32mp1_clk_parent_sel_name[p]); -+ } -+#endif -+} -+ - static void sync_earlyboot_clocks_state(void) - { - unsigned int idx; -@@ -2210,6 +3432,7 @@ static void sync_earlyboot_clocks_state(void) - DDRC2, DDRC2LP, - DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, - DDRPHYC, DDRPHYCLP, -+ RTCAPB, - TZC1, TZC2, - TZPC, - STGEN_K, -@@ -2218,17 +3441,41 @@ static void sync_earlyboot_clocks_state(void) - for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { - stm32mp_clk_enable(secure_enable[idx]); - } -- -- if (!stm32mp_is_single_core()) { -- stm32mp1_clk_enable_secure(RTCAPB); -- } - } - -+static const clk_ops_t stm32mp_clk_ops = { -+ .enable = stm32mp_clk_enable, -+ .disable = stm32mp_clk_disable, -+ .is_enabled = stm32mp_clk_is_enabled, -+ .get_rate = stm32mp_clk_get_rate, -+ .get_parent = stm32mp1_clk_get_parent, -+}; -+ - int stm32mp1_clk_probe(void) - { -+ unsigned long freq_khz; -+ -+ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB); -+ -+#if defined(IMAGE_BL32) -+ if (!fdt_get_rcc_secure_state()) { -+ mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U); -+ } -+#endif -+ - 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; -+ -+ clk_register(&stm32mp_clk_ops); -+ - return 0; - } -diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c -index 8333f6dfbf..a119bbf386 100644 ---- a/drivers/st/clk/stm32mp_clkfunc.c -+++ b/drivers/st/clk/stm32mp_clkfunc.c -@@ -10,9 +10,15 @@ - - #include - -+#include - #include -+#include -+#include - #include - #include -+#include -+ -+#define DT_UART_COMPAT "st,stm32h7-uart" - - /* - * Get the frequency of an oscillator from its name in device tree. -@@ -43,7 +49,8 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) - return ret; - } - -- 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", -@@ -69,7 +76,7 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) - * @param prop_name: property name - * @return: true/false regarding search result. - */ --bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) -+bool fdt_clk_read_bool(const char *node_label, const char *prop_name) - { - int node, subnode; - void *fdt; -@@ -78,10 +85,6 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) - return false; - } - -- if (osc_id >= NB_OSC) { -- return false; -- } -- - node = fdt_path_offset(fdt, "/clocks"); - if (node < 0) { - return false; -@@ -96,8 +99,7 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) - return false; - } - -- if (strncmp(cchar, stm32mp_osc_node_label[osc_id], -- (size_t)ret) != 0) { -+ if (strncmp(cchar, node_label, (size_t)ret) != 0) { - continue; - } - -@@ -110,13 +112,13 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) - } - - /* -- * Get the value of a oscillator property from its ID. -- * @param osc_id: oscillator ID -+ * Get the value of a oscillator property from its name. -+ * @param node_label: oscillator name - * @param prop_name: property name - * @param dflt_value: default value - * @return oscillator value on success, default value if property not found. - */ --uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, -+uint32_t fdt_clk_read_uint32_default(const char *node_label, - const char *prop_name, uint32_t dflt_value) - { - int node, subnode; -@@ -126,10 +128,6 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - return dflt_value; - } - -- if (osc_id >= NB_OSC) { -- return dflt_value; -- } -- - node = fdt_path_offset(fdt, "/clocks"); - if (node < 0) { - return dflt_value; -@@ -144,8 +142,7 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - return dflt_value; - } - -- if (strncmp(cchar, stm32mp_osc_node_label[osc_id], -- (size_t)ret) != 0) { -+ if (strncmp(cchar, node_label, (size_t)ret) != 0) { - continue; - } - -@@ -161,9 +158,15 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - * @param fdt: Device tree reference - * @return: Node offset or a negative value on error - */ --int fdt_get_rcc_node(void *fdt) -+static int fdt_get_rcc_node(void *fdt) - { -- return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -+ static int node; -+ -+ if (node <= 0) { -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -+ } -+ -+ return node; - } - - /* -@@ -191,6 +194,29 @@ int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, - return fdt_read_uint32_array(fdt, node, prop_name, count, array); - } - -+/******************************************************************************* -+ * This function reads a property rcc-clk section. -+ * It reads the values indicated inside the device tree, from property name. -+ * Returns dflt_value if property is not found, and a property value on -+ * success. -+ ******************************************************************************/ -+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_get_rcc_node(fdt); -+ if (node < 0) { -+ return dflt_value; -+ } -+ -+ return fdt_read_uint32_default(fdt, node, prop_name, dflt_value); -+} -+ - /* - * Get the subnode offset in rcc-clk section from its name in device tree - * @param name: name of the RCC property -@@ -249,24 +275,38 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) - } - - /* -- * Get the secure status for rcc node in device tree. -- * @return: true if rcc is available from secure world, false if not. -+ * Get the secure state for rcc node in device tree. -+ * @return: true if rcc is configured for secure world access, false if not. - */ --bool fdt_get_rcc_secure_status(void) -+bool fdt_get_rcc_secure_state(void) - { -- int node; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return false; - } - -- node = fdt_get_rcc_node(fdt); -- if (node < 0) { -+ if (fdt_node_offset_by_compatible(fdt, -1, DT_RCC_SEC_CLK_COMPAT) < 0) { - return false; - } - -- return !!(fdt_get_status(node) & DT_SECURE); -+ return true; -+} -+ -+/* -+ * This function gets interrupt name. -+ * It reads the values indicated the enabling status. -+ * Returns 0 if success, and a negative value else. -+ */ -+int fdt_rcc_enable_it(const char *name) -+{ -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ return stm32_gic_enable_spi(fdt_get_rcc_node(fdt), name); - } - - /* -@@ -291,3 +331,131 @@ 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. -+ * 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_by_name(int node, const char *name) -+{ -+ const fdt32_t *cuint; -+ void *fdt; -+ int index, len; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ index = fdt_stringlist_search(fdt, node, "clock-names", name); -+ if (index < 0) { -+ return index; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "clocks", &len); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ if ((index * (int)sizeof(uint32_t)) > len) { -+ return -FDT_ERR_BADVALUE; -+ } -+ -+ cuint += (index << 1) + 1; -+ return (int)fdt32_to_cpu(*cuint); -+} -+ -+/* -+ * Get the frequency of the specified UART instance. -+ * @param instance: UART interface registers base address. -+ * @return: clock frequency on success, 0 value on failure. -+ */ -+unsigned long fdt_get_uart_clock_freq(uintptr_t instance) -+{ -+ void *fdt; -+ int node; -+ int clk_id; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return 0UL; -+ } -+ -+ /* Check for UART nodes */ -+ node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance); -+ if (node < 0) { -+ return 0UL; -+ } -+ -+ clk_id = fdt_get_clock_id(node); -+ if (clk_id < 0) { -+ return 0UL; -+ } -+ -+ return 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) -+{ -+ return (((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | -+ mmio_read_32(STGEN_BASE + CNTCVL_OFF)); -+} -+ -+/******************************************************************************* -+ * 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; -+ -+ cnt = value + ((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 317fd9eb88..9ee64a57e7 100644 ---- a/drivers/st/crypto/stm32_hash.c -+++ b/drivers/st/crypto/stm32_hash.c -@@ -14,6 +14,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -189,7 +190,7 @@ int stm32_hash_update(const uint8_t *buffer, size_t length) - return 0; - } - -- stm32mp_clk_enable(stm32_hash.clock); -+ clk_enable(stm32_hash.clock); - - if (stm32_remain.length != 0U) { - uint32_t copysize; -@@ -231,7 +232,7 @@ int stm32_hash_update(const uint8_t *buffer, size_t length) - } - - exit: -- stm32mp_clk_disable(stm32_hash.clock); -+ clk_disable(stm32_hash.clock); - - return ret; - } -@@ -240,12 +241,12 @@ int stm32_hash_final(uint8_t *digest) - { - int ret; - -- stm32mp_clk_enable(stm32_hash.clock); -+ clk_enable(stm32_hash.clock); - - if (stm32_remain.length != 0U) { - ret = hash_write_data(stm32_remain.buffer); - if (ret != 0) { -- stm32mp_clk_disable(stm32_hash.clock); -+ clk_disable(stm32_hash.clock); - return ret; - } - -@@ -260,7 +261,7 @@ int stm32_hash_final(uint8_t *digest) - - ret = hash_get_digest(digest); - -- stm32mp_clk_disable(stm32_hash.clock); -+ clk_disable(stm32_hash.clock); - - return ret; - } -@@ -280,11 +281,11 @@ int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, - - void stm32_hash_init(enum stm32_hash_algo_mode mode) - { -- stm32mp_clk_enable(stm32_hash.clock); -+ clk_enable(stm32_hash.clock); - - hash_hw_init(mode); - -- stm32mp_clk_disable(stm32_hash.clock); -+ clk_disable(stm32_hash.clock); - - zeromem(&stm32_remain, sizeof(stm32_remain)); - } -@@ -321,7 +322,7 @@ int stm32_hash_register(void) - stm32_hash.base = hash_info.base; - stm32_hash.clock = hash_info.clock; - -- stm32mp_clk_enable(stm32_hash.clock); -+ clk_enable(stm32_hash.clock); - - if (hash_info.reset >= 0) { - uint32_t id = (uint32_t)hash_info.reset; -@@ -335,7 +336,7 @@ int stm32_hash_register(void) - } - } - -- stm32mp_clk_disable(stm32_hash.clock); -+ clk_disable(stm32_hash.clock); - - return 0; - } -diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c -index 7d89d027e6..7e8041743e 100644 ---- a/drivers/st/ddr/stm32mp1_ddr.c -+++ b/drivers/st/ddr/stm32mp1_ddr.c -@@ -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 - */ -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -29,6 +30,7 @@ struct reg_desc { - - #define INVALID_OFFSET 0xFFU - -+#define TIMESLOT_US_1US 1U - #define TIMEOUT_US_1S 1000000U - - #define DDRCTL_REG(x, y) \ -@@ -45,8 +47,34 @@ 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 */ -+#if STM32MP_DDR_DUAL_AXI_PORT -+#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ -+#else -+#define DDRCTL_REG_PERF_SIZE 11 /* st,ctl-perf */ -+#endif -+ -+#if STM32MP_DDR_DUAL_AXI_PORT -+#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ -+#else -+#define DDRPHY_REG_REG_SIZE 9 /* st,phy-reg */ -+#endif -+#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ -+#if STM32MP_DDR_DUAL_AXI_PORT -+#define DDRPHY_REG_CAL_SIZE 12 /* st,phy-cal */ -+#else -+#define DDRPHY_REG_CAL_SIZE 6 /* st,phy-cal */ -+#endif -+ - #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 +103,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), -@@ -91,7 +119,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), -@@ -104,7 +132,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), -@@ -116,16 +144,18 @@ static const struct reg_desc ddr_perf[] = { - DDRCTL_REG_PERF(pcfgqos1_0), - DDRCTL_REG_PERF(pcfgwqos0_0), - DDRCTL_REG_PERF(pcfgwqos1_0), -+#if STM32MP_DDR_DUAL_AXI_PORT - DDRCTL_REG_PERF(pcfgr_1), - DDRCTL_REG_PERF(pcfgw_1), - DDRCTL_REG_PERF(pcfgqos0_1), - DDRCTL_REG_PERF(pcfgqos1_1), - DDRCTL_REG_PERF(pcfgwqos0_1), - DDRCTL_REG_PERF(pcfgwqos1_1), -+#endif - }; - - #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), -@@ -135,12 +165,14 @@ static const struct reg_desc ddrphy_reg[] = { - DDRPHY_REG_REG(zq0cr1), - DDRPHY_REG_REG(dx0gcr), - DDRPHY_REG_REG(dx1gcr), -+#if STM32MP_DDR_DUAL_AXI_PORT - DDRPHY_REG_REG(dx2gcr), - DDRPHY_REG_REG(dx3gcr), -+#endif - }; - - #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,51 +186,26 @@ 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), - DDRPHY_REG_CAL(dx1dllcr), - DDRPHY_REG_CAL(dx1dqtr), - DDRPHY_REG_CAL(dx1dqstr), -+#if STM32MP_DDR_DUAL_AXI_PORT - DDRPHY_REG_CAL(dx2dllcr), - DDRPHY_REG_CAL(dx2dqtr), - DDRPHY_REG_CAL(dx2dqstr), - DDRPHY_REG_CAL(dx3dllcr), - DDRPHY_REG_CAL(dx3dqtr), - DDRPHY_REG_CAL(dx3dqstr), -+#endif - }; - --#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 +214,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 - }; - -@@ -233,55 +234,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 - }, - }; -@@ -627,7 +616,7 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - */ - - /* Change Bypass Mode Frequency Range */ -- if (stm32mp_clk_get_rate(DDRPHYC) < 100000000U) { -+ if (clk_get_rate(DDRPHYC) < 100000000U) { - mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, - DDRPHYC_DLLGCR_BPS200); - } else { -@@ -641,10 +630,12 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) - DDRPHYC_DXNDLLCR_DLLDIS); - mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); -+#if STM32MP_DDR_DUAL_AXI_PORT - mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); - mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr, - DDRPHYC_DXNDLLCR_DLLDIS); -+#endif - - /* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ - mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, -@@ -675,7 +666,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); -@@ -693,11 +685,92 @@ 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); - } - -+static void stm32mp1_refresh_cmd(struct stm32mp1_ddrctl *ctl) -+{ -+ uint32_t dbgstat; -+ -+ do { -+ dbgstat = mmio_read_32((uintptr_t)&ctl->dbgstat); -+ } while ((dbgstat & DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY) != 0U); -+ -+ mmio_setbits_32((uintptr_t)&ctl->dbgcmd, DDRCTRL_DBGCMD_RANK0_REFRESH); -+} -+ -+/* Refresh compensation by forcing refresh command -+ * Rule1: Tref should be always < tREFW ? R x tREBW/8 -+ * Rule2: refcomp = RU(Tref/tREFI) = RU(RxTref/tREFW) -+ */ -+static -+void stm32mp1_refresh_compensation(const struct stm32mp1_ddr_config *config, -+ struct stm32mp1_ddrctl *ctl, -+ uint64_t start) -+{ -+ uint32_t tck_ps; -+ uint64_t time_us, tref, trefi, refcomp, i; -+ -+ time_us = timeout_init_us(0) - start; -+ tck_ps = 1000000000U / config->info.speed; -+ if (tck_ps == 0U) { -+ return; -+ } -+ /* ref = refresh time in tck */ -+ tref = time_us * 1000000U / tck_ps; -+ trefi = ((mmio_read_32((uintptr_t)&ctl->rfshtmg) & -+ DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK) -+ >> DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT) * 32U; -+ if (trefi == 0U) { -+ return; -+ } -+ -+ /* div round up : number of refresh to compensate */ -+ refcomp = (tref + trefi - 1U) / trefi; -+ -+ for (i = 0; i < refcomp; i++) { -+ stm32mp1_refresh_cmd(ctl); -+ } -+} -+ -+static void stm32mp1_self_refresh_zcal(struct ddr_info *priv, uint32_t zdata) -+{ -+ /* sequence for PUBL I/O Data Retention during Power-Down */ -+ -+ /* 10. Override ZQ calibration with previously (pre-retention) -+ * calibrated values. This is done by writing 1 to ZQ0CRN.ZDEN -+ * and the override data to ZQ0CRN.ZDATA. -+ */ -+ mmio_setbits_32((uintptr_t)&priv->phy->zq0cr0, DDRPHYC_ZQ0CRN_ZDEN); -+ -+ mmio_clrsetbits_32((uintptr_t)&priv->phy->zq0cr0, -+ DDRPHYC_ZQ0CRN_ZDATA_MASK, -+ zdata << DDRPHYC_ZQ0CRN_ZDATA_SHIFT); -+ -+ /* 11. De-assert the PHY_top data retention enable signals -+ * (ret_en or ret_en_i/ret_en_n_i). -+ */ -+ mmio_setbits_32((uintptr_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRSRDIS); -+ mmio_clrbits_32((uintptr_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRRETEN); -+ -+ /* 12. Remove ZQ calibration override by writing 0 to ZQ0CRN.ZDEN. */ -+ mmio_clrbits_32((uintptr_t)&priv->phy->zq0cr0, DDRPHYC_ZQ0CRN_ZDEN); -+ -+ /* 13. Trigger ZQ calibration by writing 1 to PIR.INIT -+ * and '1' to PIR.ZCAL -+ */ -+ /* 14. Wait for ZQ calibration to finish by polling a 1 status -+ * on PGSR.IDONE. -+ */ -+ stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_ZCAL); -+} -+ - static int board_ddr_power_init(enum ddr_type ddr_type) - { - if (dt_pmic_status() > 0) { -@@ -710,7 +783,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; -+ uint32_t pir, ddr_reten; - int ret = -EINVAL; - - if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { -@@ -730,6 +803,25 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - VERBOSE("name = %s\n", config->info.name); - 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); -+ } -+ -+ /* Check DDR PHY pads retention */ -+ ddr_reten = mmio_read_32((uint32_t)(priv->pwr) + PWR_CR3) & -+ PWR_CR3_DDRRETEN; -+ if (config->self_refresh) { -+ if (ddr_reten == 0U) { -+ VERBOSE("self-refresh aborted: no retention\n"); -+ config->self_refresh = false; -+ } -+ } -+ -+ if (!config->self_refresh) { -+ VERBOSE("disable DDR PHY retention\n"); -+ mmio_setbits_32((uint32_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRSRDIS); -+ mmio_clrbits_32((uint32_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRRETEN); -+ } - - /* DDR INIT SEQUENCE */ - -@@ -790,6 +882,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); - -+ /* 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, -@@ -811,7 +909,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); -+ if (config->p_cal_present) { -+ set_reg(priv, REGPHY_CAL, &config->p_cal); -+ } - - /* DDR3 = don't set DLLOFF for init mode */ - if ((config->c_reg.mstr & -@@ -843,8 +943,20 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */ - } - -+ /* Treat self-refresh exit : hot boot */ -+ if (config->self_refresh) { -+ /* DDR in self refresh mode, remove zcal & reset & init */ -+ pir &= ~(DDRPHYC_PIR_ZCAL & DDRPHYC_PIR_DRAMRST -+ & DDRPHYC_PIR_DRAMINIT); -+ pir |= DDRPHYC_PIR_ZCALBYP; -+ } -+ - stm32mp1_ddrphy_init(priv->phy, pir); - -+ if (config->self_refresh) { -+ stm32mp1_self_refresh_zcal(priv, config->zdata); -+ } -+ - /* - * 6. SET DFIMISC.dfi_init_complete_en to 1 - * Enable quasi-dynamic register programming. -@@ -865,6 +977,13 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - */ - - /* Wait uMCTL2 ready */ -+ -+ /* Trigger self-refresh exit */ -+ if (config->self_refresh) { -+ mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, -+ DDRCTRL_PWRCTL_SELFREF_SW); -+ } -+ - stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); - - /* Switch to DLL OFF mode */ -@@ -872,37 +991,53 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - stm32mp1_ddr3_dll_off(priv); - } - -- 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; -+ -+ 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); -+ } - -- /* -- * 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); -+ } - - /* Enable uMCTL2 AXI port 0 */ - mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_0, -@@ -911,10 +1046,12 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - (uintptr_t)&priv->ctl->pctrl_0, - mmio_read_32((uintptr_t)&priv->ctl->pctrl_0)); - -+#if STM32MP_DDR_DUAL_AXI_PORT - /* Enable uMCTL2 AXI port 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)); -+#endif - } -diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c -index fcb4cfcfdf..dab63d191b 100644 ---- a/drivers/st/ddr/stm32mp1_ddr_helpers.c -+++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c -@@ -1,24 +1,615 @@ - /* -- * 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 - -+#define TIMEOUT_500US 500U -+ -+static enum stm32mp1_ddr_sr_mode saved_ddr_sr_mode; -+ - void ddr_enable_clock(void) - { - stm32mp1_clk_rcc_regs_lock(); - - mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, - RCC_DDRITFCR_DDRC1EN | -+#if STM32MP_DDR_DUAL_AXI_PORT - RCC_DDRITFCR_DDRC2EN | -+#endif - RCC_DDRITFCR_DDRPHYCEN | - RCC_DDRITFCR_DDRPHYCAPBEN | - RCC_DDRITFCR_DDRCAPBEN); - - stm32mp1_clk_rcc_regs_unlock(); - } -+ -+static void do_sw_handshake(void) -+{ -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); -+} -+ -+static void do_sw_ack(void) -+{ -+ uint64_t timeout; -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); -+ -+ timeout = timeout_init_us(TIMEOUT_500US); -+ while ((mmio_read_32(ddrctrl_base + DDRCTRL_SWSTAT) & -+ DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U) { -+ if (timeout_elapsed(timeout)) { -+ panic(); -+ } -+ } -+} -+ -+static int ddr_sw_self_refresh_in(void) -+{ -+ uint64_t timeout; -+ uint32_t stat; -+ uint32_t operating_mode; -+ uint32_t selref_type; -+ uint8_t op_mode_changed = 0; -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ uintptr_t pwr_base = stm32mp_pwr_base(); -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base(); -+ -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ /* Blocks AXI ports from taking anymore transactions */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PCTRL_0, -+ DDRCTRL_PCTRL_N_PORT_EN); -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PCTRL_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+#endif -+ -+ /* Waits unit all AXI ports are idle -+ * Poll PSTAT.rd_port_busy_n = 0 -+ * Poll PSTAT.wr_port_busy_n = 0 -+ */ -+ timeout = timeout_init_us(TIMEOUT_500US); -+ while (mmio_read_32(ddrctrl_base + DDRCTRL_PSTAT)) { -+ if (timeout_elapsed(timeout)) { -+ goto pstat_failed; -+ } -+ } -+ /* SW Self-Refresh entry */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_SELFREF_SW); -+ -+ /* Wait operating mode change in self-refresh mode -+ * with STAT.operating_mode[1:0]==11. -+ * Ensure transition to self-refresh was due to software -+ * by checking also that STAT.selfref_type[1:0]=2. -+ */ -+ 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; -+ -+ if ((operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) && -+ (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) { -+ op_mode_changed = 1; -+ break; -+ } -+ } -+ -+ if (op_mode_changed == 0U) -+ goto selfref_sw_failed; -+ -+ /* IOs powering down (PUBL registers) */ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); -+ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDR); -+ -+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CKPDD_MASK, -+ DDRPHYC_ACIOCR_CKPDD_0); -+ -+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CKPDR_MASK, -+ DDRPHYC_ACIOCR_CKPDR_0); -+ -+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR, -+ 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); -+ -+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_DSGCR, -+ DDRPHYC_DSGCR_ODTPDD_MASK, -+ DDRPHYC_DSGCR_ODTPDD_0); -+ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); -+ -+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_DSGCR, -+ DDRPHYC_DSGCR_CKEPDD_MASK, -+ DDRPHYC_DSGCR_CKEPDD_0); -+ -+ /* 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 */ -+ stm32mp_pwr_regs_lock(); -+ mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); -+ stm32mp_pwr_regs_unlock(); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ -+ stm32mp1_clk_rcc_regs_lock(); -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ /* Disable all DLLs: GLITCH window */ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX0DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX1DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX2DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX3DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+#endif -+ -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL output clock */ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ -+ /* Deactivate all DDR clocks */ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, -+ RCC_DDRITFCR_DDRC1EN | -+#if STM32MP_DDR_DUAL_AXI_PORT -+ RCC_DDRITFCR_DDRC2EN | -+#endif -+ RCC_DDRITFCR_DDRCAPBEN | -+ RCC_DDRITFCR_DDRPHYCAPBEN); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ return 0; -+ -+selfref_sw_failed: -+ /* This bit should be cleared to restore DDR in its previous state */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_SELFREF_SW); -+ -+pstat_failed: -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_0, -+ DDRCTRL_PCTRL_N_PORT_EN); -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+#endif -+ -+ return -1; -+} -+ -+int ddr_sw_self_refresh_exit(void) -+{ -+ uint64_t timeout; -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ uintptr_t pwr_base = stm32mp_pwr_base(); -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base(); -+ -+ /* Enable all clocks */ -+ ddr_enable_clock(); -+ -+ do_sw_handshake(); -+ -+ /* Mask dfi_init_complete_en */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_DFIMISC, -+ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); -+ -+ do_sw_ack(); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ -+ stm32mp1_clk_rcc_regs_lock(); -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ /* Enable all DLLs: GLITCH window */ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX0DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX1DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX2DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX3DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+#endif -+ -+ /* Additional delay to avoid early DLL clock switch */ -+ udelay(50); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ -+ stm32mp1_clk_rcc_regs_lock(); -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLSRST); -+ -+ udelay(10); -+ -+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLSRST); -+ -+ /* PHY partial init: (DLL lock and ITM reset) */ -+ mmio_write_32(ddrphyc_base + DDRPHYC_PIR, -+ DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | -+ DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_INIT); -+ -+ /* Need to wait at least 10 clock cycles before accessing PGSR */ -+ udelay(1); -+ -+ /* Pool end of init */ -+ timeout = timeout_init_us(TIMEOUT_500US); -+ -+ while ((mmio_read_32(ddrphyc_base + DDRPHYC_PGSR) & -+ DDRPHYC_PGSR_IDONE) == 0U) { -+ if (timeout_elapsed(timeout)) { -+ return -1; -+ } -+ } -+ -+ do_sw_handshake(); -+ -+ /* Unmask dfi_init_complete_en to uMCTL2 */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_DFIMISC, -+ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); -+ -+ do_sw_ack(); -+ -+ /* Deactivate sw retention in PWR */ -+ stm32mp_pwr_regs_lock(); -+ mmio_clrbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); -+ stm32mp_pwr_regs_unlock(); -+ -+ /* Enable PZQ cell (PUBL register) */ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); -+ -+ /* 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); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CSPDD_MASK); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); -+ -+ 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); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); -+ -+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, -+ DDRPHYC_DSGCR_CKEPDD_MASK); -+ -+ /* Remove selfrefresh */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_SELFREF_SW); -+ -+ /* Wait operating_mode == normal */ -+ 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(timeout)) { -+ return -1; -+ } -+ } -+ -+ /* AXI ports are no longer blocked from taking transactions */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_0, -+ DDRCTRL_PCTRL_N_PORT_EN); -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+#endif -+ -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ return 0; -+} -+ -+uint32_t ddr_get_io_calibration_val(void) -+{ -+ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base(); -+ -+ return mmio_read_32(ddrphyc_base + DDRPHYC_ZQ0CR0) & -+ DDRPHYC_ZQ0CRN_ZDATA_MASK; -+} -+ -+int ddr_standby_sr_entry(void) -+{ -+ uintptr_t pwr_base = stm32mp_pwr_base(); -+ -+ /* Put DDR in Self-Refresh */ -+ if (ddr_sw_self_refresh_in() != 0) { -+ return -1; -+ } -+ -+ /* Enable I/O retention mode in standby */ -+ stm32mp_pwr_regs_lock(); -+ mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRSREN); -+ stm32mp_pwr_regs_unlock(); -+ -+ return 0; -+} -+ -+static void ddr_sr_mode_ssr(void) -+{ -+ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1EN); -+ -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2EN); -+#endif -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBLPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBLPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCEN); -+ -+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); -+ -+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ /* Disable HW LP interface of uMCTL2 */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_HWLPCTL, -+ DDRCTRL_HWLPCTL_HW_LP_EN); -+ -+ /* Configure Automatic LP modes of uMCTL2 */ -+ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG, -+ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK, -+ DDRCTRL_PWRTMG_SELFREF_TO_X32_0); -+ -+ /* -+ * Disable Clock disable with LP modes -+ * (used in RUN mode for LPDDR2 with specific timing). -+ */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); -+ -+ /* Disable automatic Self-Refresh mode */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_SELFREF_EN); -+} -+ -+static void ddr_sr_mode_asr(void) -+{ -+ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -+ -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -+#endif -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); -+ -+ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, -+ RCC_DDRITFCR_DDRCKMOD_ASR1); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ /* Enable HW LP interface of uMCTL2 */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_HWLPCTL, -+ DDRCTRL_HWLPCTL_HW_LP_EN); -+ -+ /* Configure Automatic LP modes of uMCTL2 */ -+ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG, -+ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK, -+ DDRCTRL_PWRTMG_SELFREF_TO_X32_0); -+ -+ /* -+ * Enable Clock disable with LP modes -+ * (used in RUN mode for LPDDR2 with specific timing). -+ */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); -+ -+ /* Enable automatic Self-Refresh for ASR mode */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_SELFREF_EN); -+} -+ -+static void ddr_sr_mode_hsr(void) -+{ -+ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; -+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); -+ -+ stm32mp1_clk_rcc_regs_lock(); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); -+ -+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -+ -+#if STM32MP_DDR_DUAL_AXI_PORT -+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -+#endif -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); -+ -+ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, -+ RCC_DDRITFCR_DDRCKMOD_HSR1); -+ -+ stm32mp1_clk_rcc_regs_unlock(); -+ -+ /* Enable HW LP interface of uMCTL2 */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_HWLPCTL, -+ DDRCTRL_HWLPCTL_HW_LP_EN); -+ -+ /* Configure Automatic LP modes of uMCTL2 */ -+ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG, -+ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK, -+ DDRCTRL_PWRTMG_SELFREF_TO_X32_0); -+ -+ /* -+ * Enable Clock disable with LP modes -+ * (used in RUN mode for LPDDR2 with specific timing). -+ */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ 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; -+ -+ write_ats1cpw(address); -+ -+ isb(); -+ -+ pa = read64_par(); -+ -+ if ((((pa >> PAR_NS_SHIFT) & PAR_NS_MASK) != PAR_NS_MASK) || -+ (((pa >> PAR_F_SHIFT) & PAR_F_MASK) == PAR_F_MASK)) { -+ return false; -+ } -+ -+ write_ats1cpw(address + length - 1U); -+ -+ isb(); -+ -+ pa = read64_par(); -+ -+ if ((((pa >> PAR_NS_SHIFT) & PAR_NS_MASK) == PAR_NS_MASK) && -+ (((pa >> PAR_F_SHIFT) & PAR_F_MASK) != PAR_F_MASK)) { -+ return true; -+ } -+ -+ return false; -+} -diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c -index b21c8949fe..3918eb7be5 100644 ---- a/drivers/st/ddr/stm32mp1_ram.c -+++ b/drivers/st/ddr/stm32mp1_ram.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -22,6 +23,7 @@ - #define DDR_ANTIPATTERN 0x55555555U - - static struct ddr_info ddr_priv_data; -+static bool ddr_self_refresh; - - int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) - { -@@ -29,7 +31,7 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) - - ddr_enable_clock(); - -- ddrphy_clk = stm32mp_clk_get_rate(DDRPHYC); -+ ddrphy_clk = clk_get_rate(DDRPHYC); - - VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n", - mem_speed, ddrphy_clk / 1000U); -@@ -50,6 +52,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. -+ ******************************************************************************/ -+static uint32_t ddr_test_rw_access(void) -+{ -+ uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE); -+ -+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); -+ -+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { -+ return (uint32_t)STM32MP_DDR_BASE; -+ } -+ -+ mmio_write_32(STM32MP_DDR_BASE, saved_value); -+ -+ return 0; -+} -+ - /******************************************************************************* - * This function tests the DDR data bus wiring. - * This is inspired from the Data Bus Test algorithm written by Michael Barr -@@ -172,20 +194,23 @@ static int stm32mp1_ddr_setup(void) - uint32_t uret, idx; - void *fdt; - --#define PARAM(x, y) \ -+#define PARAM(x, y, z) \ - { \ - .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), -@@ -193,7 +218,7 @@ 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) { -@@ -231,11 +256,27 @@ 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; -+ } -+ } -+ } -+ -+ config.self_refresh = false; -+ -+ if (stm32mp1_is_wakeup_from_standby()) { -+ config.self_refresh = true; -+ config.zdata = stm32_get_zdata_from_context(); - } - - /* Disable axidcg clock gating during init */ -@@ -255,34 +296,61 @@ static int stm32mp1_ddr_setup(void) - panic(); - } - -- uret = ddr_test_data_bus(); -- if (uret != 0U) { -- ERROR("DDR data bus test: can't access memory @ 0x%x\n", -- uret); -- panic(); -- } -+ if (config.self_refresh) { -+ uret = ddr_test_rw_access(); -+ if (uret != 0U) { -+ ERROR("DDR rw test: Can't access memory @ 0x%x\n", -+ uret); -+ panic(); -+ } - -- uret = ddr_test_addr_bus(); -- if (uret != 0U) { -- ERROR("DDR addr bus test: can't access memory @ 0x%x\n", -- uret); -- panic(); -- } -+ /* Restore area overwritten by training */ -+ stm32_restore_ddr_training_area(); -+ } else { -+ uret = ddr_test_data_bus(); -+ if (uret != 0U) { -+ ERROR("DDR data bus test: can't access memory @ 0x%x\n", -+ uret); -+ panic(); -+ } - -- uret = ddr_check_size(); -- if (uret < config.info.size) { -- ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", -- uret, config.info.size); -- panic(); -+ uret = ddr_test_addr_bus(); -+ if (uret != 0U) { -+ ERROR("DDR addr bus test: can't access memory @ 0x%x\n", -+ uret); -+ panic(); -+ } -+ -+ uret = ddr_check_size(); -+ if (uret < config.info.size) { -+ ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", -+ uret, config.info.size); -+ panic(); -+ } - } - -+ /* -+ * 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()); -+ - if (stm32mp_unmap_ddr() != 0) { - panic(); - } - -+ /* Save DDR self_refresh state */ -+ ddr_self_refresh = config.self_refresh; -+ - return 0; - } - -+bool stm32mp1_ddr_is_restored(void) -+{ -+ return ddr_self_refresh; -+} -+ - int stm32mp1_ddr_probe(void) - { - struct ddr_info *priv = &ddr_priv_data; -diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c -index ff52a22d9d..eb1c79cf7b 100644 ---- a/drivers/st/etzpc/etzpc.c -+++ b/drivers/st/etzpc/etzpc.c -@@ -66,6 +66,10 @@ struct etzpc_instance { - /* Only 1 instance of the ETZPC is expected per platform */ - static struct etzpc_instance etzpc_dev; - -+struct dt_id_attr { -+ fdt32_t id_attr[STM32MP1_ETZPC_MAX_ID]; -+}; -+ - /* - * Implementation uses uint8_t to store each securable DECPROT configuration. - * When resuming from deep suspend, the DECPROT configurations are restored. -@@ -85,6 +89,50 @@ static bool valid_tzma_id(unsigned int id) - } - #endif - -+static int etzpc_dt_conf_decprot(int node) -+{ -+ const struct dt_id_attr *conf_list; -+ void *fdt; -+ unsigned int i; -+ int len = 0; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ conf_list = (const struct dt_id_attr *)fdt_getprop(fdt, node, -+ "st,decprot", &len); -+ if (conf_list == NULL) { -+ INFO("No ETZPC configuration in DT, use default\n"); -+ return 0; -+ } -+ -+ for (i = 0U; i < (unsigned int)len / sizeof(uint32_t); i++) { -+ enum etzpc_decprot_attributes attr; -+ uint32_t value; -+ uint32_t id; -+ uint32_t mode; -+ -+ value = fdt32_to_cpu(conf_list->id_attr[i]); -+ -+ id = ((value >> ETZPC_ID_SHIFT) & ETZPC_ID_MASK); -+ assert(valid_decprot_id(id)); -+ -+ mode = (value >> ETZPC_MODE_SHIFT) & ETZPC_MODE_MASK; -+ attr = stm32mp_etzpc_binding2decprot(mode); -+ -+ stm32mp1_register_etzpc_decprot(id, attr); -+ -+ etzpc_configure_decprot(id, attr); -+ -+ if ((value & ETZPC_LOCK_MASK) != 0U) { -+ etzpc_lock_decprot(id); -+ } -+ } -+ -+ return 0; -+} -+ - /* - * etzpc_configure_decprot : Load a DECPROT configuration - * decprot_id : ID of the IP -@@ -254,5 +302,5 @@ int etzpc_init(void) - - VERBOSE("ETZPC version 0x%x", etzpc_dev.revision); - -- return 0; -+ return etzpc_dt_conf_decprot(node); - } -diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c -index a58a243ad6..503e259876 100644 ---- a/drivers/st/fmc/stm32_fmc2_nand.c -+++ b/drivers/st/fmc/stm32_fmc2_nand.c -@@ -14,6 +14,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -162,7 +163,7 @@ static uintptr_t fmc2_base(void) - 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 hclk = 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; -@@ -918,7 +919,7 @@ int stm32_fmc2_init(void) - } - - /* Enable Clock */ -- stm32mp_clk_enable(stm32_fmc2.clock_id); -+ clk_enable(stm32_fmc2.clock_id); - - /* Reset IP */ - ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); -diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c -index 7d63262d71..75707e63a1 100644 ---- a/drivers/st/gpio/stm32_gpio.c -+++ b/drivers/st/gpio/stm32_gpio.c -@@ -14,6 +14,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -208,7 +209,7 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, - - assert(pin <= GPIO_PIN_MAX); - -- stm32mp_clk_enable(clock); -+ clk_enable(clock); - - mmio_clrbits_32(base + GPIO_MODE_OFFSET, - ((uint32_t)GPIO_MODE_MASK << (pin << 1))); -@@ -254,7 +255,7 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, - VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, - mmio_read_32(base + GPIO_AFRH_OFFSET)); - -- stm32mp_clk_disable(clock); -+ clk_disable(clock); - - if (status == DT_SECURE) { - stm32mp_register_secure_gpio(bank, pin); -@@ -273,7 +274,7 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) - - assert(pin <= GPIO_PIN_MAX); - -- stm32mp_clk_enable(clock); -+ clk_enable(clock); - - if (secure) { - mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); -@@ -281,5 +282,5 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) - mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); - } - -- stm32mp_clk_disable(clock); -+ clk_disable(clock); - } -diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c -index ed880522b0..3e4b96a2c3 100644 ---- a/drivers/st/i2c/stm32_i2c.c -+++ b/drivers/st/i2c/stm32_i2c.c -@@ -1,10 +1,11 @@ - /* -- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved - * -- * SPDX-License-Identifier: BSD-3-Clause -+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ - - #include -+#include - #include - #include - -@@ -13,6 +14,8 @@ - #include - - #include -+#include -+#include - #include - #include - #include -@@ -38,8 +41,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) -+ * @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) -+ * @vddat_max: Max data valid time (ns) -+ * @sudat_min: Min data setup time (ns) -+ * @l_min: Min low period of the SCL clock (ns) -+ * @h_min: Min high period of the SCL clock (ns) -+ */ -+struct i2c_spec_s { -+ uint32_t rate; -+ uint32_t fall_max; -+ uint32_t rise_max; -+ uint32_t hddat_min; -+ uint32_t vddat_max; -+ uint32_t sudat_min; -+ uint32_t l_min; -+ uint32_t h_min; -+}; -+ -+/* -+ * struct i2c_timing_s - Private I2C output parameters. -+ * @scldel: Data setup time -+ * @sdadel: Data hold time -+ * @sclh: SCL high period (master mode) -+ * @sclh: SCL low period (master mode) -+ * @is_saved: True if relating to a configuration candidate -+ */ -+struct i2c_timing_s { -+ uint8_t scldel; -+ uint8_t sdadel; -+ uint8_t sclh; -+ uint8_t scll; -+ bool is_saved; -+}; -+ -+/* -+ * 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. -+ * -+ * [1] https://www.i2c-bus.org/specification/ -+ */ -+static const struct i2c_spec_s i2c_specs[] = { -+ /* Standard - 100KHz */ -+ { -+ .rate = STANDARD_RATE, -+ .fall_max = 300, -+ .rise_max = 1000, -+ .hddat_min = 0, -+ .vddat_max = 3450, -+ .sudat_min = 250, -+ .l_min = 4700, -+ .h_min = 4000, -+ }, -+ /* Fast - 400KHz */ -+ { -+ .rate = FAST_RATE, -+ .fall_max = 300, -+ .rise_max = 300, -+ .hddat_min = 0, -+ .vddat_max = 900, -+ .sudat_min = 100, -+ .l_min = 1300, -+ .h_min = 600, -+ }, -+ /* FastPlus - 1MHz */ -+ { -+ .rate = FAST_PLUS_RATE, -+ .fall_max = 100, -+ .rise_max = 120, -+ .hddat_min = 0, -+ .vddat_max = 450, -+ .sudat_min = 50, -+ .l_min = 500, -+ .h_min = 260, -+ }, -+}; -+ - - static void notif_i2c_timeout(struct i2c_handle_s *hi2c) - { -@@ -48,6 +130,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) -+{ -+ size_t i; -+ -+ for (i = 0U; 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 -+ * @param clock_src: I2C clock source frequency (Hz) -+ * @param timing: Pointer to the final computed timing result -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_compute_timing(struct stm32_i2c_init_s *init, -+ uint32_t clock_src, uint32_t *timing) -+{ -+ 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; -+ uint32_t p_prev = I2C_TIMINGR_PRESC_MAX; -+ uint32_t af_delay_min; -+ uint32_t af_delay_max; -+ uint32_t dnf_delay; -+ uint32_t tsync; -+ uint32_t clk_min; -+ uint32_t clk_max; -+ int clk_error_prev; -+ uint16_t p; -+ uint16_t l; -+ uint16_t a; -+ uint16_t h; -+ int sdadel_min; -+ int sdadel_max; -+ uint32_t sdadel_min_u; -+ uint32_t sdadel_max_u; -+ uint32_t scldel_min; -+ int s = -1; -+ struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX]; -+ -+ specs = get_specs(init->bus_rate); -+ if (specs == NULL) { -+ ERROR("I2C speed out of bound {%d}\n", init->bus_rate); -+ return -EINVAL; -+ } -+ -+ speed_freq = specs->rate; -+ i2cbus = udiv_round_nearest(I2C_NSEC_PER_SEC, speed_freq); -+ clk_error_prev = INT_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, specs->rise_max, -+ init->fall_time, specs->fall_max); -+ return -EINVAL; -+ } -+ -+ if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) { -+ ERROR("DNF out of bound %d/%d\n", -+ init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX); -+ return -EINVAL; -+ } -+ -+ /* Analog and Digital Filters */ -+ af_delay_min = (init->analog_filter ? -+ STM32_I2C_ANALOG_FILTER_DELAY_MIN : 0); -+ af_delay_max = (init->analog_filter ? -+ STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0); -+ dnf_delay = init->digital_filter_coef * i2cclk; -+ -+ sdadel_min = specs->hddat_min + init->fall_time - -+ af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); -+ -+ sdadel_max = specs->vddat_max - init->rise_time - -+ af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); -+ -+ scldel_min = init->rise_time + specs->sudat_min; -+ -+ if (sdadel_min < 0) { -+ sdadel_min_u = 0; -+ } else { -+ sdadel_min_u = (uint32_t)sdadel_min; -+ } -+ -+ if (sdadel_max < 0) { -+ sdadel_max_u = 0; -+ } else { -+ sdadel_max_u = (uint32_t)sdadel_max; -+ } -+ -+ VERBOSE("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u\n", -+ sdadel_min_u, sdadel_max_u, scldel_min); -+ -+ zeromem(&solutions, sizeof(solutions)); -+ -+ /* Compute possible values for PRESC, SCLDEL and SDADEL */ -+ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { -+ for (l = 0; l < I2C_TIMINGR_SCLDEL_MAX; l++) { -+ uint32_t scldel = (l + 1) * (p + 1) * i2cclk; -+ -+ if (scldel < scldel_min) { -+ continue; -+ } -+ -+ for (a = 0; a < I2C_TIMINGR_SDADEL_MAX; a++) { -+ uint32_t sdadel = (a * (p + 1) + 1) * i2cclk; -+ -+ if ((sdadel >= sdadel_min_u) && -+ (sdadel <= sdadel_max_u) && -+ (p != p_prev)) { -+ solutions[p].scldel = l; -+ solutions[p].sdadel = a; -+ solutions[p].is_saved = true; -+ p_prev = p; -+ break; -+ } -+ } -+ -+ if (p_prev == p) { -+ break; -+ } -+ } -+ } -+ -+ if (p_prev == I2C_TIMINGR_PRESC_MAX) { -+ ERROR(" I2C no Prescaler solution\n"); -+ return -EPERM; -+ } -+ -+ tsync = af_delay_min + dnf_delay + (2 * i2cclk); -+ 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 -+ * and High Period. Provided: -+ * - SCL Low Period has to be higher than Low Period of the SCL Clock -+ * defined by I2C Specification. I2C Clock has to be lower than -+ * (SCL Low Period - Analog/Digital filters) / 4. -+ * - SCL High Period has to be lower than High Period of the SCL Clock -+ * defined by I2C Specification. -+ * - I2C Clock has to be lower than SCL High Period. -+ */ -+ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { -+ uint32_t prescaler = (p + 1) * i2cclk; -+ -+ if (!solutions[p].is_saved) { -+ continue; -+ } -+ -+ for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { -+ uint32_t tscl_l = ((l + 1) * prescaler) + tsync; -+ -+ if ((tscl_l < specs->l_min) || -+ (i2cclk >= -+ ((tscl_l - af_delay_min - dnf_delay) / 4))) { -+ continue; -+ } -+ -+ for (h = 0; h < I2C_TIMINGR_SCLH_MAX; h++) { -+ uint32_t tscl_h = ((h + 1) * prescaler) + tsync; -+ uint32_t tscl = tscl_l + tscl_h + -+ init->rise_time + -+ init->fall_time; -+ -+ if ((tscl >= clk_min) && (tscl <= clk_max) && -+ (tscl_h >= specs->h_min) && -+ (i2cclk < tscl_h)) { -+ int clk_error = tscl - i2cbus; -+ -+ if (clk_error < 0) { -+ clk_error = -clk_error; -+ } -+ -+ if (clk_error < clk_error_prev) { -+ clk_error_prev = clk_error; -+ solutions[p].scll = l; -+ solutions[p].sclh = h; -+ s = p; -+ } -+ } -+ } -+ } -+ } -+ -+ if (s < 0) { -+ ERROR(" I2C no solution at all\n"); -+ return -EPERM; -+ } -+ -+ /* Finalize timing settings */ -+ *timing = I2C_SET_TIMINGR_PRESC(s) | -+ I2C_SET_TIMINGR_SCLDEL(solutions[s].scldel) | -+ I2C_SET_TIMINGR_SDADEL(solutions[s].sdadel) | -+ I2C_SET_TIMINGR_SCLH(solutions[s].sclh) | -+ I2C_SET_TIMINGR_SCLL(solutions[s].scll); -+ -+ VERBOSE("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%i/%i\n", -+ s, solutions[s].scldel, solutions[s].sdadel); -+ VERBOSE("I2C TIMINGR (SCLH/SCLL): %i/%i\n", -+ solutions[s].sclh, solutions[s].scll); -+ VERBOSE("I2C TIMINGR: 0x%x\n", *timing); -+ -+ 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 -+ * the configuration information for the specified I2C. -+ * @param init: Ref to the initialization configuration structure -+ * @param timing: Pointer to the final computed timing result -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_setup_timing(struct i2c_handle_s *hi2c, -+ struct stm32_i2c_init_s *init, -+ uint32_t *timing) -+{ -+ int rc = 0; -+ uint32_t clock_src; -+ -+ clock_src = (uint32_t)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->bus_rate > STANDARD_RATE) { -+ init->bus_rate = get_lower_rate(init->bus_rate); -+ WARN("Downgrade I2C speed to %uHz)\n", -+ init->bus_rate); -+ } else { -+ break; -+ } -+ } -+ } while (rc != 0); -+ -+ if (rc != 0) { -+ ERROR("Impossible to compute I2C timings\n"); -+ return rc; -+ } -+ -+ 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); -+ -+ hi2c->saved_timing = *timing; -+ hi2c->saved_frequency = clock_src; -+ -+ return 0; -+} -+ - /* - * @brief Configure I2C Analog noise filter. - * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -@@ -88,49 +462,35 @@ 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; -+ uint32_t read_val; -+ void *fdt; - -- 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); -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; - } - -- 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->rise_time = fdt_read_uint32_default(fdt, node, -+ "i2c-scl-rising-time-ns", -+ STM32_I2C_RISE_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; -- } -+ init->fall_time = fdt_read_uint32_default(fdt, node, -+ "i2c-scl-falling-time-ns", -+ STM32_I2C_FALL_TIME_DEFAULT); -+ -+ read_val = fdt_read_uint32_default(fdt, 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 +506,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; -@@ -158,7 +518,12 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, - - hi2c->i2c_state = I2C_STATE_BUSY; - -- stm32mp_clk_enable(hi2c->clock); -+ rc = i2c_setup_timing(hi2c, init_data, &timing); -+ if (rc != 0) { -+ return rc; -+ } -+ -+ clk_enable(hi2c->clock); - - /* Disable the selected I2C peripheral */ - mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); -@@ -220,11 +585,11 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, - I2C_ANALOGFILTER_DISABLE); - if (rc != 0) { - ERROR("Cannot initialize I2C analog filter (%d)\n", rc); -- stm32mp_clk_disable(hi2c->clock); -+ clk_disable(hi2c->clock); - return rc; - } - -- stm32mp_clk_disable(hi2c->clock); -+ clk_disable(hi2c->clock); - - return rc; - } -@@ -548,7 +913,7 @@ static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, - return -EINVAL; - } - -- stm32mp_clk_enable(hi2c->clock); -+ clk_enable(hi2c->clock); - - hi2c->lock = 1; - -@@ -648,7 +1013,7 @@ static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, - - bail: - hi2c->lock = 0; -- stm32mp_clk_disable(hi2c->clock); -+ clk_disable(hi2c->clock); - - return rc; - } -@@ -729,7 +1094,7 @@ static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, - return -EINVAL; - } - -- stm32mp_clk_enable(hi2c->clock); -+ clk_enable(hi2c->clock); - - hi2c->lock = 1; - -@@ -817,7 +1182,7 @@ static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, - - bail: - hi2c->lock = 0; -- stm32mp_clk_disable(hi2c->clock); -+ clk_disable(hi2c->clock); - - return rc; - } -@@ -882,7 +1247,7 @@ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, - return rc; - } - -- stm32mp_clk_enable(hi2c->clock); -+ clk_enable(hi2c->clock); - - hi2c->lock = 1; - hi2c->i2c_mode = I2C_MODE_NONE; -@@ -974,8 +1339,7 @@ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, - - bail: - hi2c->lock = 0; -- stm32mp_clk_disable(hi2c->clock); -+ clk_disable(hi2c->clock); - - return rc; - } -- -diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c -index 3e377cd483..ccd3379a39 100644 ---- a/drivers/st/io/io_stm32image.c -+++ b/drivers/st/io/io_stm32image.c -@@ -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("%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,17 +212,24 @@ 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; - } - - /* 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; -+ int offset; -+ int local_length; -+ uintptr_t backend_handle; -+ int result = -EINVAL; - uint8_t *local_buffer; - boot_api_image_header_t *header = - (boot_api_image_header_t *)first_lba_buffer; -+ size_t hdr_sz = sizeof(boot_api_image_header_t); - - assert(entity != NULL); - assert(buffer != 0U); -@@ -258,99 +238,53 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, - 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; -- } -- } -+#if TRUSTED_BOARD_BOOT -+ stm32mp_save_loaded_header(header); -+#endif - -- /* 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(); -- } -+ /* Part of image already loaded with the header */ -+ memcpy(local_buffer, (uint8_t *)first_lba_buffer + hdr_sz, -+ MAX_LBA_SIZE - hdr_sz); -+ local_buffer += MAX_LBA_SIZE - hdr_sz; -+ offset = MAX_LBA_SIZE; - -- result = io_open(backend_dev_handle, backend_image_spec, -- &backend_handle); -+ /* New image length to be read */ -+ local_length = round_up(length - ((MAX_LBA_SIZE) - hdr_sz), -+ stm32image_dev.lba_size); - -- 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); -+ if ((header->load_address != 0U) && (header->load_address != buffer)) { -+ ERROR("Wrong load address\n"); -+ panic(); -+ } - -- /* Adding part of size already read from header */ -- *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t); -+ result = io_open(backend_dev_handle, backend_image_spec, -+ &backend_handle); -+ if (result != 0) { -+ ERROR("%s: io_open (%i)\n", __func__, result); -+ return result; -+ } - -- if (result != 0) { -- ERROR("%s: io_read (%i)\n", __func__, result); -- *length_read = 0; -- header->magic = 0; -- continue; -- } -+ result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img + offset); -+ if (result != 0) { -+ ERROR("%s: io_seek (%i)\n", __func__, result); -+ goto out; -+ } - -- result = stm32mp_check_header(header, buffer); -- if (result != 0) { -- ERROR("Header check failed\n"); -- *length_read = 0; -- header->magic = 0; -- } -+ 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; -+ } - -- result = stm32mp_auth_image(header, buffer); -- if (result != 0) { -- ERROR("Authentication Failed (%i)\n", result); -- return result; -- } -+ /* Adding part of size already read from header */ -+ *length_read += MAX_LBA_SIZE - hdr_sz; - -- io_close(backend_handle); -- } -+ inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz), -+ CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz); - -+out: -+ io_close(backend_handle); - return result; - } - -diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c -index c052b4dfbe..f68f95371f 100644 ---- a/drivers/st/iwdg/stm32_iwdg.c -+++ b/drivers/st/iwdg/stm32_iwdg.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -22,11 +23,30 @@ - #include - #include - -+#define IWDG_TIMEOUT_MS U(100) -+ - /* 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 */ -+#define IWDG_KR_ACCESS_KEY 0x5555 - #define IWDG_KR_RELOAD_KEY 0xAAAA -+#define IWDG_KR_START_KEY 0xCCCC -+ -+#define IWDG_PR_DIV_4 0x00 -+#define IWDG_PR_DIV_256 0x06 -+ -+#define IWDG_RLR_MAX_VAL 0xFFF -+ -+#define IWDG_SR_EWU BIT(3) -+ -+#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; -@@ -52,6 +72,122 @@ 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) -+{ -+ struct stm32_iwdg_instance *iwdg; -+ unsigned int instance; -+ -+ for (instance = 0; instance < IWDG_MAX_INSTANCE; instance++) { -+ if (stm32_iwdg[instance].num_irq == id) { -+ break; -+ } -+ } -+ -+ if (instance == IWDG_MAX_INSTANCE) { -+ panic(); -+ } -+ -+ iwdg = &stm32_iwdg[instance]; -+ -+#if DEBUG -+ INFO("CPU %x IT Watchdog %u\n", plat_my_core_pos(), instance + 1U); -+ -+ stm32mp_dump_core_registers(true); -+#endif -+ stm32_iwdg_refresh(); -+ -+ clk_enable(iwdg->clock); -+ -+ mmio_clrsetbits_32(iwdg->base + IWDG_EWCR_OFFSET, -+ IWDG_EWCR_EWIE, IWDG_EWCR_EWIC); -+ -+ clk_disable(iwdg->clock); -+ -+ /* Ack interrupt as we do not return from next call */ -+ gicv2_end_of_interrupt(id); -+ -+#if DEBUG -+ if (!stm32mp_is_single_core()) { -+ unsigned int sec_cpu = (plat_my_core_pos() == STM32MP_PRIMARY_CPU) ? -+ STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU; -+ -+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, sec_cpu); -+ } -+#endif -+ -+ for ( ; ; ) { -+ ; -+ } -+} -+ -+static int stm32_iwdg_get_secure_timeout(int node) -+{ -+ void *fdt; -+ const fdt32_t *cuint; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -1; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "secure-timeout-sec", NULL); -+ if (cuint == NULL) { -+ return -1; -+ } -+ -+ return (int)fdt32_to_cpu(*cuint); -+} -+ -+static int stm32_iwdg_conf_etimeout(int node, struct stm32_iwdg_instance *iwdg) -+{ -+ int id_lsi; -+ int dt_secure_timeout = stm32_iwdg_get_secure_timeout(node); -+ uint32_t reload, status; -+ unsigned int timeout = IWDG_TIMEOUT_MS; -+ unsigned long long reload_ll; -+ -+ if (dt_secure_timeout < 0) { -+ return 0; -+ } -+ -+ if (dt_secure_timeout == 0) { -+ return -EINVAL; -+ } -+ -+ id_lsi = fdt_get_clock_id_by_name(node, "lsi"); -+ if (id_lsi < 0) { -+ return -EINVAL; -+ } -+ -+ /* Prescaler fix to 256 */ -+ reload_ll = (unsigned long long)dt_secure_timeout * clk_get_rate(id_lsi); -+ reload = ((uint32_t)(reload_ll >> 8) - 1U) & IWDG_EWCR_EWIT_MASK; -+ -+ clk_enable(iwdg->clock); -+ -+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_START_KEY); -+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); -+ mmio_write_32(iwdg->base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); -+ mmio_write_32(iwdg->base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIE | reload); -+ -+ do { -+ status = mmio_read_32(iwdg->base + IWDG_SR_OFFSET) & -+ IWDG_SR_EWU; -+ timeout--; -+ mdelay(1); -+ } while ((status != 0U) && (timeout != 0U)); -+ -+ iwdg->num_irq = stm32_gic_enable_spi(node, NULL); -+ if (iwdg->num_irq < 0) { -+ panic(); -+ } -+ -+ clk_disable(iwdg->clock); -+ -+ return (timeout == 0U) ? -ETIMEDOUT : 0; -+} -+#endif -+ - void stm32_iwdg_refresh(void) - { - uint8_t i; -@@ -61,12 +197,12 @@ void stm32_iwdg_refresh(void) - - /* 0x00000000 is not a valid address for IWDG peripherals */ - if (iwdg->base != 0U) { -- stm32mp_clk_enable(iwdg->clock); -+ clk_enable(iwdg->clock); - - mmio_write_32(iwdg->base + IWDG_KR_OFFSET, - IWDG_KR_RELOAD_KEY); - -- stm32mp_clk_disable(iwdg->clock); -+ clk_disable(iwdg->clock); - } - } - } -@@ -74,6 +210,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; -@@ -143,6 +280,14 @@ int stm32_iwdg_init(void) - stm32mp_register_secure_periph_iomem(iwdg->base); - } - -+#if defined(IMAGE_BL32) -+ res = stm32_iwdg_conf_etimeout(node, iwdg); -+ if (res != 0) { -+ ERROR("IWDG%x early timeout config failed (%d)\n", -+ idx + 1, res); -+ return res; -+ } -+#endif - #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 -index cff3a344f7..8c203a4c03 100644 ---- a/drivers/st/mmc/stm32_sdmmc2.c -+++ b/drivers/st/mmc/stm32_sdmmc2.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -50,6 +51,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 */ -@@ -117,6 +119,13 @@ - #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 -+ - #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" - - static void stm32_sdmmc2_init(void); -@@ -138,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; -+ -+ INFO("SDMMC_POWER = 0x%x\n", mmio_read_32(base + SDMMC_POWER)); -+ INFO("SDMMC_CLKCR = 0x%x\n", mmio_read_32(base + SDMMC_CLKCR)); -+ INFO("SDMMC_ARGR = 0x%x\n", mmio_read_32(base + SDMMC_ARGR)); -+ INFO("SDMMC_CMDR = 0x%x\n", mmio_read_32(base + SDMMC_CMDR)); -+ INFO("SDMMC_RESPCMDR = 0x%x\n", mmio_read_32(base + SDMMC_RESPCMDR)); -+ INFO("SDMMC_RESP1R = 0x%x\n", mmio_read_32(base + SDMMC_RESP1R)); -+ INFO("SDMMC_RESP2R = 0x%x\n", mmio_read_32(base + SDMMC_RESP2R)); -+ INFO("SDMMC_RESP3R = 0x%x\n", mmio_read_32(base + SDMMC_RESP3R)); -+ INFO("SDMMC_RESP4R = 0x%x\n", mmio_read_32(base + SDMMC_RESP4R)); -+ INFO("SDMMC_DTIMER = 0x%x\n", mmio_read_32(base + SDMMC_DTIMER)); -+ INFO("SDMMC_DLENR = 0x%x\n", mmio_read_32(base + SDMMC_DLENR)); -+ INFO("SDMMC_DCTRLR = 0x%x\n", mmio_read_32(base + SDMMC_DCTRLR)); -+ INFO("SDMMC_DCNTR = 0x%x\n", mmio_read_32(base + SDMMC_DCNTR)); -+ INFO("SDMMC_MASKR = 0x%x\n", mmio_read_32(base + SDMMC_MASKR)); -+ INFO("SDMMC_ACKTIMER = 0x%x\n", mmio_read_32(base + SDMMC_ACKTIMER)); -+} -+ - static void stm32_sdmmc2_init(void) - { - uint32_t clock_div; -@@ -154,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); -+ } -+ -+ 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 * 2U); - - mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | -@@ -163,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) -@@ -221,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; -+ 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; -@@ -258,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)); -+ - mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); - - /* -@@ -265,8 +333,7 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) - * Skip CMD55 as the next command could be data related, and - * the register could have been set in prepare function. - */ -- if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && -- (cmd->cmd_idx != MMC_CMD(55))) { -+ if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && !next_cmd_is_acmd) { - mmio_write_32(base + SDMMC_DCTRLR, 0U); - } - -@@ -563,6 +630,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); - -@@ -580,6 +648,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); - -@@ -628,6 +697,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; -@@ -637,27 +707,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; - } - -@@ -665,21 +722,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; -@@ -714,6 +758,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; - } - -@@ -734,12 +783,14 @@ 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; - } - -- stm32mp_clk_enable(sdmmc2_params.clock_id); -+ clk_enable(sdmmc2_params.clock_id); - - rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS); - if (rc != 0) { -@@ -752,7 +803,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.clk_rate = 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, -diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c -index b2bb482f9d..4e505debdf 100644 ---- a/drivers/st/pmic/stm32mp_pmic.c -+++ b/drivers/st/pmic/stm32mp_pmic.c -@@ -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,36 +23,56 @@ - #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 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 int dt_get_pmic_node(void *fdt) - { -- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); -+ static int node = -FDT_ERR_BADOFFSET; -+ -+ if (node == -FDT_ERR_BADOFFSET) { -+ node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); -+ } -+ -+ return node; - } - - int dt_pmic_status(void) - { -+ static int status = -FDT_ERR_BADVALUE; - int node; - void *fdt; - -+ if (status != -FDT_ERR_BADVALUE) { -+ return status; -+ } -+ - if (fdt_get_address(&fdt) == 0) { - return -ENOENT; - } - - node = dt_get_pmic_node(fdt); - 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) -@@ -63,53 +84,173 @@ 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 found. -- */ --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 *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; -+} -+ -+#if defined(IMAGE_BL32) -+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; -+ }; -+ -+ /* -+ * 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 - --int dt_pmic_configure_boot_on_regulators(void) -+static int pmic_operate(uint8_t command, const char *node_name, -+ uint16_t *voltage_mv) - { -- int pmic_node, regulators_node, regulator_node; -+ int pmic_node, regulators_node, subnode; - void *fdt; -+ int ret = -EIO; - - if (fdt_get_address(&fdt) == 0) { - return -ENOENT; -@@ -117,70 +258,166 @@ int dt_pmic_configure_boot_on_regulators(void) - - pmic_node = dt_get_pmic_node(fdt); - 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. -+ */ -+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; -+ -+ 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(fdt); -+ 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; - } -+ } - -- 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(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); -+} -+ -+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 -FDT_ERR_NOTFOUND; -+ } -+ -+ pmic_node = dt_get_pmic_node(fdt); -+ if (pmic_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ if (regulators_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, regulators_node) { -+ const char *name; -+ -+ 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; -+} -+ -+int pmic_set_regulator_min_voltage(const char *regu_name) -+{ -+ int rc = -ENOENT; -+ const char *supply_name; -+ -+ if (dt_pmic_find_supply(&supply_name, regu_name) == 0) { -+ uint16_t min_mv; -+ -+ rc = pmic_operate(CMD_GET_MIN_VOLTAGE, supply_name, &min_mv); -+ if (rc == 0) { -+ rc = stpmic1_regulator_voltage_set(supply_name, min_mv); -+ } -+ } -+ -+ return rc; - } - - bool initialize_pmic_i2c(void) -@@ -204,6 +441,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; -@@ -245,16 +483,83 @@ static void register_pmic_shared_peripherals(void) - } - } - --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"); - return; - } - - register_pmic_shared_peripherals(); -+} -+ -+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"); -@@ -263,19 +568,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; -+ -+ if (pmic_operate(CMD_GET_MIN_VOLTAGE, "buck2", &buck2_mv) != 0) { -+ return -EPERM; -+ } - - switch (ddr_type) { - case STM32MP_DDR3: -@@ -295,7 +601,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; - } -@@ -345,7 +651,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; - } -@@ -355,7 +660,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; -+ } -+ -+ 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 9999630545..a1db120dc1 100644 ---- a/drivers/st/pmic/stpmic1.c -+++ b/drivers/st/pmic/stpmic1.c -@@ -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, -+}; -+ - /* 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 = "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 = "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 = "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, -+ }, - }; - - #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) -+{ -+ uint8_t val; -+ 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; -+ } -+ -+ return stpmic1_register_write(regul->low_power_reg, val); -+} -+ -+int stpmic1_lp_reg_on_off(const char *name, uint8_t enable) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->low_power_reg, enable, -+ LDO_BUCK_ENABLE_MASK); -+} -+ -+int stpmic1_lp_set_mode(const char *name, uint8_t hplp) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->low_power_reg, -+ hplp << LDO_BUCK_HPLP_SHIFT, -+ LDO_BUCK_HPLP_ENABLE_MASK); -+} -+ -+int stpmic1_lp_set_voltage(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->low_power_reg, voltage_index << 2, -+ mask); -+} -+ - 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; - - /* 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; -+ } - - value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; - -- if (value > regul->voltage_table_size) -- return -1; -+ if (value > regul->voltage_table_size) { -+ return -ERANGE; -+ } - - 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; - -- 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 0000000000..1003aba054 ---- /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 0000000000..f0e4a4ae5c ---- /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 98c8dcf710..a803923fca 100644 ---- a/drivers/st/reset/stm32mp1_reset.c -+++ b/drivers/st/reset/stm32mp1_reset.c -@@ -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 - */ -@@ -67,3 +67,32 @@ int stm32mp_reset_deassert(uint32_t id, unsigned int to_us) - - return 0; - } -+ -+void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ /* -+ * The RCC_MP_GCR is a read/write register. -+ * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit -+ * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit -+ */ -+ if (assert_not_deassert) { -+ mmio_clrbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); -+ } else { -+ mmio_setbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); -+ } -+} -+ -+void __dead2 stm32mp_system_reset(void) -+{ -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ mmio_setbits_32(rcc_base + RCC_MP_GRSTCSETR, -+ RCC_MP_GRSTCSETR_MPSYSRST); -+ -+ /* Loop in case system reset is not immediately caught */ -+ for ( ; ; ) { -+ ; -+ } -+} -diff --git a/drivers/st/rng/stm32_rng.c b/drivers/st/rng/stm32_rng.c -new file mode 100644 -index 0000000000..461d50c814 ---- /dev/null -+++ b/drivers/st/rng/stm32_rng.c -@@ -0,0 +1,193 @@ -+/* -+ * 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 -+ -+#define DT_RNG_COMPAT "st,stm32-rng" -+#define RNG_CR 0x00U -+#define RNG_SR 0x04U -+#define RNG_DR 0x08U -+ -+#define RNG_CR_RNGEN BIT(2) -+#define RNG_CR_IE BIT(3) -+#define RNG_CR_CED BIT(5) -+ -+#define RNG_SR_DRDY BIT(0) -+#define RNG_SR_CECS BIT(1) -+#define RNG_SR_SECS BIT(2) -+#define RNG_SR_CEIS BIT(5) -+#define RNG_SR_SEIS BIT(6) -+ -+#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; -+}; -+ -+static struct stm32_rng_instance stm32_rng; -+ -+/* -+ * stm32_rng_read - Read a number of random bytes from RNG -+ * out: pointer to the output buffer -+ * size: number of bytes to be read -+ * Return 0 on success, non-0 on failure -+ */ -+int stm32_rng_read(uint8_t *out, uint32_t size) -+{ -+ uint8_t *buf = out; -+ uint32_t len = size; -+ int nb_tries; -+ uint32_t data32; -+ int rc = 0; -+ int count; -+ -+ if (stm32_rng.base == 0U) { -+ return -EPERM; -+ } -+ -+ clk_enable(stm32_rng.clock); -+ -+ if ((mmio_read_32(stm32_rng.base + RNG_CR) & RNG_CR_RNGEN) == 0U) { -+ mmio_write_32(stm32_rng.base + RNG_CR, -+ RNG_CR_RNGEN | RNG_CR_CED); -+ } -+ -+ while (len != 0U) { -+ nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US; -+ do { -+ uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR); -+ -+ if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) { -+ uint8_t i; -+ -+ /* Recommended by the SoC reference manual */ -+ mmio_clrbits_32(stm32_rng.base + RNG_SR, -+ RNG_SR_SEIS); -+ dmb(); -+ for (i = 12; i != 0; i--) { -+ (void)mmio_read_32(stm32_rng.base + -+ RNG_DR); -+ } -+ dmb(); -+ -+ if ((mmio_read_32(stm32_rng.base + RNG_SR) & -+ RNG_SR_SEIS) != 0U) { -+ ERROR("RNG noise\n"); -+ panic(); -+ } -+ } -+ -+ udelay(RNG_TIMEOUT_STEP_US); -+ nb_tries--; -+ if (nb_tries == 0) { -+ rc = -ETIMEDOUT; -+ goto bail; -+ } -+ } while ((mmio_read_32(stm32_rng.base + RNG_SR) & -+ RNG_SR_DRDY) == 0U); -+ -+ count = 4; -+ while (len != 0U) { -+ data32 = mmio_read_32(stm32_rng.base + RNG_DR); -+ count--; -+ -+ memcpy(buf, &data32, MIN(len, sizeof(uint32_t))); -+ buf += MIN(len, sizeof(uint32_t)); -+ len -= MIN(len, sizeof(uint32_t)); -+ -+ if (count == 0) { -+ break; -+ } -+ } -+ } -+ -+bail: -+ clk_disable(stm32_rng.clock); -+ -+ if (rc != 0) { -+ memset(out, 0, buf - out); -+ } -+ -+ return rc; -+} -+ -+/* -+ * stm32_rng_init: Initialize rng from DT -+ * return 0 on success, negative value on failure -+ */ -+int stm32_rng_init(void) -+{ -+ void *fdt; -+ struct dt_node_info dt_rng; -+ int node; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ panic(); -+ } -+ -+ node = dt_get_node(&dt_rng, -1, DT_RNG_COMPAT); -+ if (node < 0) { -+ return 0; -+ } -+ -+ if ((dt_rng.status & DT_SECURE) == 0) { -+ return 0; -+ } -+ -+ assert(dt_rng.base != 0U); -+ -+ stm32_rng.base = dt_rng.base; -+ -+ if ((dt_rng.status & DT_NON_SECURE) == DT_NON_SECURE) { -+ stm32mp_register_non_secure_periph_iomem(stm32_rng.base); -+ } else { -+ stm32mp_register_secure_periph_iomem(stm32_rng.base); -+ } -+ -+ if (dt_rng.clock < 0) { -+ panic(); -+ } -+ stm32_rng.clock = (unsigned long)dt_rng.clock; -+ -+ if (dt_rng.reset >= 0) { -+ int ret; -+ -+ ret = stm32mp_reset_assert((unsigned long)dt_rng.reset, -+ TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ -+ udelay(20); -+ -+ ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset, -+ TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ } -+ -+ VERBOSE("Init RNG done\n"); -+ -+ return 0; -+} -diff --git a/drivers/st/rtc/stm32_rtc.c b/drivers/st/rtc/stm32_rtc.c -new file mode 100644 -index 0000000000..58d599b17a ---- /dev/null -+++ b/drivers/st/rtc/stm32_rtc.c -@@ -0,0 +1,480 @@ -+/* -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define RTC_COMPAT "st,stm32mp1-rtc" -+ -+#define RTC_TR_SU_MASK GENMASK(3, 0) -+#define RTC_TR_ST_MASK GENMASK(6, 4) -+#define RTC_TR_ST_SHIFT 4 -+#define RTC_TR_MNU_MASK GENMASK(11, 8) -+#define RTC_TR_MNU_SHIFT 8 -+#define RTC_TR_MNT_MASK GENMASK(14, 12) -+#define RTC_TR_MNT_SHIFT 12 -+#define RTC_TR_HU_MASK GENMASK(19, 16) -+#define RTC_TR_HU_SHIFT 16 -+#define RTC_TR_HT_MASK GENMASK(21, 20) -+#define RTC_TR_HT_SHIFT 20 -+#define RTC_TR_PM BIT(22) -+ -+#define RTC_DR_DU_MASK GENMASK(3, 0) -+#define RTC_DR_DT_MASK GENMASK(5, 4) -+#define RTC_DR_DT_SHIFT 4 -+#define RTC_DR_MU_MASK GENMASK(11, 8) -+#define RTC_DR_MU_SHIFT 8 -+#define RTC_DR_MT BIT(12) -+#define RTC_DR_MT_SHIFT 12 -+#define RTC_DR_WDU_MASK GENMASK(15, 13) -+#define RTC_DR_WDU_SHIFT 13 -+#define RTC_DR_YU_MASK GENMASK(19, 16) -+#define RTC_DR_YU_SHIFT 16 -+#define RTC_DR_YT_MASK GENMASK(23, 20) -+#define RTC_DR_YT_SHIFT 20 -+ -+#define RTC_SSR_SS_MASK GENMASK(15, 0) -+ -+#define RTC_ICSR_ALRAWF BIT(0) -+#define RTC_ICSR_RSF BIT(5) -+ -+#define RTC_PRER_PREDIV_S_MASK GENMASK(14, 0) -+ -+#define RTC_CR_BYPSHAD BIT(5) -+#define RTC_CR_BYPSHAD_SHIFT 5 -+#define RTC_CR_ALRAE BIT(8) -+#define RTC_CR_ALRAIE BIT(12) -+#define RTC_CR_TAMPTS BIT(25) -+ -+#define RTC_SMCR_TS_DPROT BIT(3) -+ -+#define RTC_TSDR_DU_MASK GENMASK(3, 0) -+#define RTC_TSDR_DU_SHIFT 0 -+#define RTC_TSDR_DT_MASK GENMASK(5, 4) -+#define RTC_TSDR_DT_SHIFT 4 -+#define RTC_TSDR_MU_MASK GENMASK(11, 8) -+#define RTC_TSDR_MU_SHIFT 8 -+ -+#define RTC_ALRMAR_DU_SHIFT 24 -+ -+#define RTC_SR_TSF BIT(3) -+#define RTC_SR_TSOVF BIT(4) -+ -+#define RTC_SCR_CTSF BIT(3) -+#define RTC_SCR_CTSOVF BIT(4) -+ -+#define RTC_WPR_KEY1 0xCA -+#define RTC_WPR_KEY2 0x53 -+#define RTC_WPR_KEY_LOCK 0xFF -+ -+static struct dt_node_info rtc_dev; -+ -+static struct spinlock lock; -+ -+void stm32_rtc_regs_lock(void) -+{ -+ if (stm32mp_lock_available()) { -+ spin_lock(&lock); -+ } -+} -+ -+void stm32_rtc_regs_unlock(void) -+{ -+ if (stm32mp_lock_available()) { -+ spin_unlock(&lock); -+ } -+} -+ -+static void stm32_rtc_write_unprotect(void) -+{ -+ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY1); -+ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY2); -+} -+ -+static void stm32_rtc_write_protect(void) -+{ -+ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY_LOCK); -+} -+ -+/******************************************************************************* -+ * This function gets the BYPSHAD bit value of the RTC_CR register. -+ * It will determine if we need to reset RTC_ISCR.RSF after each RTC calendar -+ * read, and also wait for RTC_ISCR.RSF=1 before next read. -+ * Returns true or false depending on the bit value. -+ ******************************************************************************/ -+static bool stm32_rtc_get_bypshad(void) -+{ -+ return ((mmio_read_32(rtc_dev.base + RTC_CR) & RTC_CR_BYPSHAD) >> -+ RTC_CR_BYPSHAD_SHIFT) != 0U; -+} -+ -+/******************************************************************************* -+ * This function reads the RTC calendar register values. -+ * If shadow registers are not bypassed, then a reset/poll is done. -+ ******************************************************************************/ -+static void stm32_rtc_read_calendar(struct stm32_rtc_calendar *calendar) -+{ -+ bool bypshad = stm32_rtc_get_bypshad(); -+ -+ if (!bypshad) { -+ mmio_clrbits_32((uint32_t)(rtc_dev.base + RTC_ICSR), -+ RTC_ICSR_RSF); -+ while ((mmio_read_32(rtc_dev.base + RTC_ICSR) & RTC_ICSR_RSF) != -+ RTC_ICSR_RSF) { -+ ; -+ } -+ } -+ -+ calendar->ssr = mmio_read_32(rtc_dev.base + RTC_SSR); -+ calendar->tr = mmio_read_32(rtc_dev.base + RTC_TR); -+ calendar->dr = mmio_read_32(rtc_dev.base + RTC_DR); -+} -+ -+/******************************************************************************* -+ * This function fill the rtc_time structure based on rtc_calendar register. -+ ******************************************************************************/ -+static void stm32_rtc_get_time(struct stm32_rtc_calendar *cal, -+ struct stm32_rtc_time *tm) -+{ -+ assert(cal != NULL); -+ assert(tm != NULL); -+ -+ tm->hour = (((cal->tr & RTC_TR_HT_MASK) >> RTC_TR_HT_SHIFT) * 10U) + -+ ((cal->tr & RTC_TR_HU_MASK) >> RTC_TR_HU_SHIFT); -+ -+ if ((cal->tr & RTC_TR_PM) != 0U) { -+ tm->hour += 12U; -+ } -+ -+ tm->min = (((cal->tr & RTC_TR_MNT_MASK) >> RTC_TR_MNT_SHIFT) * 10U) + -+ ((cal->tr & RTC_TR_MNU_MASK) >> RTC_TR_MNU_SHIFT); -+ tm->sec = (((cal->tr & RTC_TR_ST_MASK) >> RTC_TR_ST_SHIFT) * 10U) + -+ (cal->tr & RTC_TR_SU_MASK); -+} -+ -+/******************************************************************************* -+ * This function fill the rtc_time structure with the given date register. -+ ******************************************************************************/ -+static void stm32_rtc_get_date(struct stm32_rtc_calendar *cal, -+ struct stm32_rtc_time *tm) -+{ -+ assert(cal != NULL); -+ assert(tm != NULL); -+ -+ tm->wday = (((cal->dr & RTC_DR_WDU_MASK) >> RTC_DR_WDU_SHIFT)); -+ -+ tm->day = (((cal->dr & RTC_DR_DT_MASK) >> RTC_DR_DT_SHIFT) * 10U) + -+ (cal->dr & RTC_DR_DU_MASK); -+ -+ tm->month = (((cal->dr & RTC_DR_MT) >> RTC_DR_MT_SHIFT) * 10U) + -+ ((cal->dr & RTC_DR_MU_MASK) >> RTC_DR_MU_SHIFT); -+ -+ tm->year = (((cal->dr & RTC_DR_YT_MASK) >> RTC_DR_YT_SHIFT) * 10U) + -+ ((cal->dr & RTC_DR_YU_MASK) >> RTC_DR_YU_SHIFT) + 2000U; -+} -+ -+/******************************************************************************* -+ * This function reads the RTC timestamp register values and update time -+ * structure with the corresponding value. -+ ******************************************************************************/ -+static void stm32_rtc_read_timestamp(struct stm32_rtc_time *time) -+{ -+ assert(time != NULL); -+ -+ struct stm32_rtc_calendar cal_tamp; -+ -+ cal_tamp.tr = mmio_read_32(rtc_dev.base + RTC_TSTR); -+ cal_tamp.dr = mmio_read_32(rtc_dev.base + RTC_TSDR); -+ stm32_rtc_get_time(&cal_tamp, time); -+ stm32_rtc_get_date(&cal_tamp, time); -+} -+ -+/******************************************************************************* -+ * This function gets the RTC calendar register values. -+ * It takes into account the need of reading twice or not, depending on -+ * frequencies previously setted, and the bypass or not of the shadow -+ * registers. This service is exposed externally. -+ ******************************************************************************/ -+void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar) -+{ -+ bool read_twice = stm32mp1_rtc_get_read_twice(); -+ -+ stm32_rtc_regs_lock(); -+ clk_enable(rtc_dev.clock); -+ -+ stm32_rtc_read_calendar(calendar); -+ -+ if (read_twice) { -+ uint32_t tr_save = calendar->tr; -+ -+ stm32_rtc_read_calendar(calendar); -+ -+ if (calendar->tr != tr_save) { -+ stm32_rtc_read_calendar(calendar); -+ } -+ } -+ -+ clk_disable(rtc_dev.clock); -+ stm32_rtc_regs_unlock(); -+} -+ -+/******************************************************************************* -+ * This function computes the second fraction in milliseconds. -+ * The returned value is a uint32_t between 0 and 1000. -+ ******************************************************************************/ -+static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal) -+{ -+ uint32_t prediv_s = mmio_read_32(rtc_dev.base + RTC_PRER) & -+ RTC_PRER_PREDIV_S_MASK; -+ uint32_t ss = cal->ssr & RTC_SSR_SS_MASK; -+ -+ return ((prediv_s - ss) * 1000U) / (prediv_s + 1U); -+} -+ -+/******************************************************************************* -+ * This function computes the fraction difference between two timestamps. -+ * Here again the returned value is in milliseconds. -+ ******************************************************************************/ -+static signed long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -+ struct stm32_rtc_calendar *ref) -+{ -+ return (signed long long)stm32_rtc_get_second_fraction(cur) - -+ (signed long long)stm32_rtc_get_second_fraction(ref); -+} -+ -+/******************************************************************************* -+ * This function computes the time difference between two timestamps. -+ * It includes seconds, minutes and hours. -+ * Here again the returned value is in milliseconds. -+ ******************************************************************************/ -+static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) -+{ -+ signed long long curr_s; -+ signed long long ref_s; -+ -+ curr_s = (signed long long)current->sec + -+ (((signed long long)current->min + -+ (((signed long long)current->hour * 60))) * 60); -+ -+ ref_s = (signed long long)ref->sec + -+ (((signed long long)ref->min + -+ (((signed long long)ref->hour * 60))) * 60); -+ -+ return (curr_s - ref_s) * 1000; -+} -+ -+/******************************************************************************* -+ * This function determines if the year is leap or not. -+ * Returned value is true or false. -+ ******************************************************************************/ -+static bool stm32_is_a_leap_year(uint32_t year) -+{ -+ return ((year % 4U) == 0U) && -+ (((year % 100U) != 0U) || ((year % 400U) == 0U)); -+} -+ -+/******************************************************************************* -+ * This function computes the date difference between two timestamps. -+ * It includes days, months, years, with exceptions. -+ * Here again the returned value is in milliseconds. -+ ******************************************************************************/ -+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; -+ static const uint8_t month_len[NB_MONTHS] = { -+ 31, 28, 31, 30, 31, 30, -+ 31, 31, 30, 31, 30, 31 -+ }; -+ -+ /* Get the number of non-entire month days */ -+ if (current->day >= ref->day) { -+ diff_in_days += current->day - ref->day; -+ } else { -+ diff_in_days += (uint32_t)month_len[ref->month - 1U] - -+ ref->day + current->day; -+ } -+ -+ /* Get the number of entire months, and compute the related days */ -+ if (current->month > (ref->month + 1U)) { -+ for (m = (ref->month + 1U); (m < current->month) && -+ (m < 12U); m++) { -+ diff_in_days += (uint32_t)month_len[m - 1U]; -+ } -+ } -+ -+ if (current->month < (ref->month - 1U)) { -+ for (m = 1U; (m < current->month) && (m < 12U); m++) { -+ diff_in_days += (uint32_t)month_len[m - 1U]; -+ } -+ -+ for (m = (ref->month + 1U); m < 12U; m++) { -+ diff_in_days += (uint32_t)month_len[m - 1U]; -+ } -+ } -+ -+ /* Get complete years */ -+ if (current->year > (ref->year + 1U)) { -+ diff_in_days += (current->year - ref->year - 1U) * 365U; -+ } -+ -+ /* Particular cases: leap years (one day more) */ -+ if (diff_in_days > 0U) { -+ if (current->year == ref->year) { -+ if (stm32_is_a_leap_year(current->year)) { -+ if ((ref->month <= 2U) && -+ (current->month >= 3U) && -+ (current->day <= 28U)) { -+ diff_in_days++; -+ } -+ } -+ } else { -+ uint32_t y; -+ -+ /* Ref year is leap */ -+ if ((stm32_is_a_leap_year(ref->year)) && -+ (ref->month <= 2U) && (ref->day <= 28U)) { -+ diff_in_days++; -+ } -+ -+ /* Current year is leap */ -+ if ((stm32_is_a_leap_year(current->year)) && -+ (current->month >= 3U)) { -+ diff_in_days++; -+ } -+ -+ /* Interleaved years are leap */ -+ for (y = ref->year + 1U; y < current->year; y++) { -+ if (stm32_is_a_leap_year(y)) { -+ diff_in_days++; -+ } -+ } -+ } -+ } -+ -+ return (24 * 60 * 60 * 1000) * (signed long long)diff_in_days; -+} -+ -+/******************************************************************************* -+ * This function computes the date difference between two rtc value. -+ * Here again the returned value is in milliseconds. -+ ******************************************************************************/ -+unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, -+ struct stm32_rtc_calendar *ref) -+{ -+ signed long long diff_in_ms = 0; -+ struct stm32_rtc_time curr_t; -+ struct stm32_rtc_time ref_t; -+ -+ clk_enable(rtc_dev.clock); -+ -+ stm32_rtc_get_date(cur, &curr_t); -+ stm32_rtc_get_date(ref, &ref_t); -+ stm32_rtc_get_time(cur, &curr_t); -+ stm32_rtc_get_time(ref, &ref_t); -+ -+ diff_in_ms += stm32_rtc_diff_frac(cur, ref); -+ diff_in_ms += stm32_rtc_diff_time(&curr_t, &ref_t); -+ diff_in_ms += stm32_rtc_diff_date(&curr_t, &ref_t); -+ -+ clk_disable(rtc_dev.clock); -+ -+ return (unsigned long long)diff_in_ms; -+} -+ -+/******************************************************************************* -+ * This function fill the RTC timestamp structure. -+ ******************************************************************************/ -+void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts) -+{ -+ stm32_rtc_regs_lock(); -+ clk_enable(rtc_dev.clock); -+ -+ if ((mmio_read_32(rtc_dev.base + RTC_SR) & RTC_SR_TSF) != 0U) { -+ /* Print timestamp for tamper event */ -+ stm32_rtc_read_timestamp(tamp_ts); -+ mmio_setbits_32(rtc_dev.base + RTC_SCR, RTC_SCR_CTSF); -+ if ((mmio_read_32(rtc_dev.base + RTC_SR) & RTC_SR_TSOVF) != -+ 0U) { -+ /* Overflow detected */ -+ mmio_setbits_32(rtc_dev.base + RTC_SCR, RTC_SCR_CTSOVF); -+ } -+ } -+ -+ clk_disable(rtc_dev.clock); -+ stm32_rtc_regs_unlock(); -+} -+ -+/******************************************************************************* -+ * This function enable the timestamp bit for tamper and secure timestamp -+ * access. -+ ******************************************************************************/ -+void stm32_rtc_set_tamper_timestamp(void) -+{ -+ stm32_rtc_regs_lock(); -+ clk_enable(rtc_dev.clock); -+ -+ stm32_rtc_write_unprotect(); -+ -+ /* Enable tamper timestamper */ -+ mmio_setbits_32(rtc_dev.base + RTC_CR, RTC_CR_TAMPTS); -+ -+ /* Secure Timestamp bit */ -+ mmio_clrbits_32(rtc_dev.base + RTC_SMCR, RTC_SMCR_TS_DPROT); -+ -+ stm32_rtc_write_protect(); -+ -+ clk_disable(rtc_dev.clock); -+ stm32_rtc_regs_unlock(); -+} -+ -+/******************************************************************************* -+ * This function return state of tamper timestamp. -+ ******************************************************************************/ -+bool stm32_rtc_is_timestamp_enable(void) -+{ -+ bool ret; -+ -+ clk_enable(rtc_dev.clock); -+ -+ ret = (mmio_read_32(rtc_dev.base + RTC_CR) & RTC_CR_TAMPTS) != 0U; -+ -+ clk_disable(rtc_dev.clock); -+ -+ return ret; -+} -+ -+/******************************************************************************* -+ * RTC initialisation function. -+ ******************************************************************************/ -+int stm32_rtc_init(void) -+{ -+ int node; -+ -+ node = dt_get_node(&rtc_dev, -1, RTC_COMPAT); -+ if (node < 0) { -+ return node; -+ } -+ -+ if (rtc_dev.status == DT_SECURE) { -+ stm32mp_register_secure_periph_iomem(rtc_dev.base); -+ } else { -+ stm32mp_register_non_secure_periph_iomem(rtc_dev.base); -+ } -+ -+ return 0; -+} -diff --git a/drivers/st/spi/stm32_qspi.c b/drivers/st/spi/stm32_qspi.c -index d67f8313f3..966716d68f 100644 ---- a/drivers/st/spi/stm32_qspi.c -+++ b/drivers/st/spi/stm32_qspi.c -@@ -10,6 +10,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -363,7 +364,7 @@ static void stm32_qspi_release_bus(void) - - static int stm32_qspi_set_speed(unsigned int hz) - { -- unsigned long qspi_clk = stm32mp_clk_get_rate(stm32_qspi.clock_id); -+ unsigned long qspi_clk = clk_get_rate(stm32_qspi.clock_id); - uint32_t prescaler = UINT8_MAX; - uint32_t csht; - int ret; -@@ -493,7 +494,7 @@ int stm32_qspi_init(void) - stm32_qspi.clock_id = (unsigned long)info.clock; - stm32_qspi.reset_id = (unsigned int)info.reset; - -- stm32mp_clk_enable(stm32_qspi.clock_id); -+ clk_enable(stm32_qspi.clock_id); - - ret = stm32mp_reset_assert(stm32_qspi.reset_id, TIMEOUT_US_1_MS); - if (ret != 0) { -diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c -new file mode 100644 -index 0000000000..c9a9e9aef8 ---- /dev/null -+++ b/drivers/st/tamper/stm32_tamp.c -@@ -0,0 +1,379 @@ -+/* -+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DT_TAMP_COMPAT "st,stm32-tamp" -+/* STM32 Registers */ -+#define STM32_TAMP_CR1 0x00U -+#define STM32_TAMP_CR2 0x04U -+#define STM32_TAMP_FLTCR 0x0CU -+#define STM32_TAMP_ATCR 0x10U -+#define STM32_TAMP_ATSEEDR 0x14U -+#define STM32_TAMP_ATOR 0x18U -+#define STM32_TAMP_SMCR 0x20U -+#define STM32_TAMP_IER 0x2CU -+#define STM32_TAMP_SR 0x30U -+#define STM32_TAMP_SCR 0x3CU -+#define STM32_TAMP_COUNTR 0x40U -+#define STM32_TAMP_OR 0x50U -+#define STM32_TAMP_HWCFGR2 0x3ECU -+#define STM32_TAMP_HWCFGR1 0x3F0U -+#define STM32_TAMP_VERR 0x3F4U -+#define STM32_TAMP_IPIDR 0x3F8U -+#define STM32_TAMP_SIDR 0x3FCU -+ -+/* STM32_TAMP_FLTCR bit fields */ -+#define STM32_TAMP_FLTCR_TAMPFREQ GENMASK(2, 0) -+#define STM32_TAMP_FLTCR_TAMPFLT GENMASK(4, 3) -+#define STM32_TAMP_FLTCR_TAMPPRCH GENMASK(6, 5) -+#define STM32_TAMP_FLTCR_TAMPPUDIS BIT(7) -+ -+/* STM32_TAMP_ATCR bit fields */ -+#define STM32_TAMP_ATCR_ATCKSEL GENMASK(18, 16) -+#define STM32_TAMP_ATCR_ATPER GENMASK(26, 24) -+#define STM32_TAMP_ATCR_ATOSHARE BIT(30) -+#define STM32_TAMP_ATCR_FLTEN BIT(31) -+ -+/* STM32_TAMP_ATOR bit fields */ -+#define STM32_TAMP_PRNG GENMASK(7, 0) -+#define STM32_TAMP_SEEDF BIT(14) -+#define STM32_TAMP_INITS BIT(15) -+ -+/* STM32_TAMP_IER bit fields */ -+#define STM32_TAMP_IER_TAMPXIE_ALL GENMASK(7, 0) -+#define STM32_TAMP_IER_ITAMPXIE_ALL GENMASK(31, 16) -+ -+/* STM32_TAMP_SR bit fields */ -+#define STM32_TAMP_SR_TAMPXF_MASK GENMASK(7, 0) -+#define STM32_TAMP_SR_ITAMPXF_MASK GENMASK(31, 16) -+ -+/* STM32_TAMP_SMCR but fields */ -+#define STM32_TAMP_SMCR_DPROT BIT(31) -+ -+/* STM32_TAMP_CFGR bit fields */ -+#define STM32_TAMP_OR_OUT3RMP BIT(0) -+ -+/* STM32_TAMP_HWCFGR2 bit fields */ -+#define STM32_TAMP_HWCFGR2_TZ GENMASK(11, 8) -+#define STM32_TAMP_HWCFGR2_OR GENMASK(7, 0) -+ -+/* STM32_TAMP_HWCFGR1 bit fields */ -+#define STM32_TAMP_HWCFGR1_BKPREG GENMASK(7, 0) -+#define STM32_TAMP_HWCFGR1_TAMPER GENMASK(11, 8) -+#define STM32_TAMP_HWCFGR1_ACTIVE GENMASK(15, 12) -+#define STM32_TAMP_HWCFGR1_INTERN GENMASK(31, 16) -+ -+/* STM32_TAMP_VERR bit fields */ -+#define STM32_TAMP_VERR_MINREV GENMASK(3, 0) -+#define STM32_TAMP_VERR_MAJREV GENMASK(7, 4) -+ -+#define STM32_TAMP_MAX_INTERNAL 16U -+#define STM32_TAMP_MAX_EXTERNAL 8U -+ -+struct stm32_tamp_instance { -+ uintptr_t base; -+ uint32_t clock; -+ uint32_t hwconf1; -+ uint32_t hwconf2; -+ uint16_t int_nbtamp; -+ uint8_t ext_nbtamp; -+ struct stm32_tamp_int *int_tamp; -+ struct stm32_tamp_ext *ext_tamp; -+}; -+ -+static struct stm32_tamp_instance stm32_tamp; -+ -+static void stm32_tamp_set_secured(unsigned long base) -+{ -+ mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT); -+} -+ -+static void stm32_tamp_configure_or(unsigned long base, uint32_t out3) -+{ -+ mmio_setbits_32(base + STM32_TAMP_OR, out3); -+} -+ -+static int stm32_tamp_seed_init(unsigned long base) -+{ -+ /* Need RNG access */ -+ uint32_t timeout = 100; -+ uint8_t idx; -+ -+ for (idx = 0; idx < 4U; idx++) { -+ uint32_t rnd; -+ -+ if (stm32_rng_read((uint8_t *)&rnd, sizeof(uint32_t)) != 0) { -+ return -1; -+ } -+ -+ VERBOSE("Seed init %u\n", rnd); -+ mmio_write_32(base + STM32_TAMP_ATSEEDR, rnd); -+ } -+ -+ while (((mmio_read_32(base + STM32_TAMP_ATOR) & -+ STM32_TAMP_SEEDF) != 0U) && -+ (timeout != 0U)) { -+ timeout--; -+ } -+ -+ if (timeout == 0U) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static void stm32_tamp_reset_register(unsigned long base) -+{ -+ /* Disable all internal tamper */ -+ mmio_write_32(base + STM32_TAMP_CR1, 0U); -+ -+ /* Disable all external tamper */ -+ mmio_write_32(base + STM32_TAMP_CR2, 0U); -+ -+ /* Clean configuration registers */ -+ mmio_write_32(base + STM32_TAMP_FLTCR, 0U); -+ mmio_write_32(base + STM32_TAMP_ATCR, 0U); -+ mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT); -+ -+ /* Clean Tamper IT */ -+ mmio_write_32(base + STM32_TAMP_IER, 0U); -+ mmio_write_32(base + STM32_TAMP_SCR, ~0U); -+ -+ mmio_clrbits_32(base + STM32_TAMP_OR, STM32_TAMP_OR_OUT3RMP); -+} -+ -+void stm32_tamp_write_mcounter(void) -+{ -+ mmio_write_32(stm32_tamp.base + STM32_TAMP_COUNTR, 1U); -+} -+ -+void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list, -+ uint16_t nb_tamper) -+{ -+ uint16_t i; -+ -+ assert(nb_tamper < STM32_TAMP_MAX_INTERNAL); -+ -+ for (i = 0; i < nb_tamper; i++) { -+ int id = tamper_list[i].id; -+ uint32_t u_id; -+ -+ if (id == -1) { -+ continue; -+ } -+ -+ u_id = (uint32_t)id; -+ -+ if ((stm32_tamp.hwconf1 & BIT(u_id + 16U)) != 0U) { -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1, -+ BIT(u_id + 16U)); -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER, -+ BIT(u_id + 16U)); -+ } -+ } -+ -+ stm32_tamp.int_tamp = tamper_list; -+ stm32_tamp.int_nbtamp = nb_tamper; -+} -+ -+void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list, -+ uint8_t nb_tamper, uint32_t passive_conf, -+ uint32_t active_conf) -+{ -+ /* External configuration */ -+ uint8_t i, active_tamp = 0; -+ -+ assert(nb_tamper < STM32_TAMP_MAX_EXTERNAL); -+ -+ /* Enable external Tamp */ -+ for (i = 0; i < nb_tamper; i++) { -+ int id = ext_tamper_list[i].id; -+ uint32_t reg = 0, u_id; -+ -+ if (id == -1) { -+ continue; -+ } -+ -+ u_id = (uint32_t)id; -+ -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1, -+ BIT(u_id)); -+ -+ if (ext_tamper_list[i].mode == TAMP_TRIG_ON) { -+ reg |= BIT(u_id + 24U); -+ } -+ -+ if (ext_tamper_list[i].mode == TAMP_ACTIVE) { -+ active_tamp |= BIT(u_id); -+ } -+ -+ if (ext_tamper_list[i].erase != 0U) { -+ reg |= BIT(u_id); -+ } -+ -+ if (ext_tamper_list[i].evt_mask != 0U) { -+ reg |= BIT(u_id + 16U); -+ } else { -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER, -+ BIT(u_id)); -+ } -+ -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR2, reg); -+ } -+ -+ /* Filter mode register set */ -+ mmio_write_32(stm32_tamp.base + STM32_TAMP_FLTCR, passive_conf); -+ -+ /* Active mode configuration */ -+ if (active_tamp != 0U) { -+ mmio_write_32(stm32_tamp.base + STM32_TAMP_ATCR, -+ active_conf | active_tamp); -+ if (stm32_tamp_seed_init(stm32_tamp.base) != 0) { -+ ERROR("Active tamper: SEED not initialized\n"); -+ panic(); -+ } -+ } -+ -+ stm32_tamp.ext_tamp = ext_tamper_list; -+ stm32_tamp.ext_nbtamp = nb_tamper; -+} -+ -+void stm32_tamp_it_handler(void) -+{ -+ uint32_t it = mmio_read_32(stm32_tamp.base + STM32_TAMP_SR); -+ uint8_t tamp = 0; -+ struct stm32_rtc_time tamp_ts; -+ struct stm32_tamp_int *int_list = stm32_tamp.int_tamp; -+ struct stm32_tamp_ext *ext_list = stm32_tamp.ext_tamp; -+ -+ if (stm32_rtc_is_timestamp_enable()) { -+ stm32_rtc_get_timestamp(&tamp_ts); -+ INFO("Tamper Event Occurred\n"); -+ INFO("Date : %u/%u\n \t Time : %u:%u:%u\n", -+ tamp_ts.day, tamp_ts.month, tamp_ts.hour, -+ tamp_ts.min, tamp_ts.sec); -+ } -+ -+ /* Internal tamper interrupt */ -+ if ((it & STM32_TAMP_IER_ITAMPXIE_ALL) == 0U) { -+ goto tamp_ext; -+ } -+ -+ while ((it != 0U) && (tamp < stm32_tamp.int_nbtamp)) { -+ uint32_t int_id = (uint32_t)int_list[tamp].id; -+ -+ if ((it & BIT(int_id + 16U)) != 0U) { -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, BIT(int_id + 16U)); -+ it &= ~BIT(int_id + 16U); -+ if (int_list[tamp].func != NULL) { -+ int_list[tamp].func(int_id); -+ } -+ } -+ tamp++; -+ } -+ -+tamp_ext: -+ tamp = 0; -+ /* External tamper interrupt */ -+ if ((it == 0U) || ((it & STM32_TAMP_IER_TAMPXIE_ALL) == 0U)) { -+ return; -+ } -+ -+ while ((it != 0U) && (tamp < stm32_tamp.ext_nbtamp)) { -+ uint32_t ext_id = (uint32_t)ext_list[tamp].id; -+ -+ if ((it & BIT(ext_id)) != 0U) { -+ if (ext_list[tamp].func != NULL) { -+ ext_list[tamp].func(ext_id); -+ } -+ -+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, -+ BIT(ext_id)); -+ it &= ~BIT(ext_id); -+ } -+ tamp++; -+ } -+} -+ -+int stm32_tamp_init(void) -+{ -+ int node; -+ struct dt_node_info dt_tamp; -+ void *fdt; -+ uint32_t rev __unused; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -EPERM; -+ } -+ -+ node = dt_get_node(&dt_tamp, -1, DT_TAMP_COMPAT); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ assert(dt_tamp.base != 0U); -+ assert(dt_tamp.clock != -1); -+ -+ stm32_tamp.base = dt_tamp.base; -+ stm32_tamp.clock = (uint32_t)dt_tamp.clock; -+ -+ /* Init Tamp clock */ -+ clk_enable(stm32_tamp.clock); -+ -+ /* Reset Tamp register without modifying backup registers conf */ -+ stm32_tamp_reset_register(stm32_tamp.base); -+ -+ /* Check if TAMP is enabled */ -+ if ((dt_tamp.status != DT_SECURE) && -+ (dt_tamp.status != DT_SHARED)) { -+ return 0; -+ } -+ -+ stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR1); -+ stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR2); -+ -+ rev = mmio_read_32(stm32_tamp.base + STM32_TAMP_VERR); -+ VERBOSE("STM32 TAMPER V%u.%u\n", (rev & STM32_TAMP_VERR_MAJREV) >> 4, -+ rev & STM32_TAMP_VERR_MINREV); -+ -+ if ((stm32_tamp.hwconf2 & STM32_TAMP_HWCFGR2_TZ) == 0U) { -+ ERROR("Tamper IP doesn't support trustzone"); -+ return -EPERM; -+ } -+ -+ stm32_tamp_set_secured(stm32_tamp.base); -+ -+ if (dt_set_pinctrl_config(node) != -FDT_ERR_NOTFOUND) { -+ if (fdt_getprop(fdt, node, "st,out3-pc13", NULL) != NULL) { -+ stm32_tamp_configure_or(stm32_tamp.base, 1); -+ } -+ } -+ -+ if (stm32_gic_enable_spi(node, NULL) < 0) { -+ panic(); -+ } -+ -+ if (fdt_getprop(fdt, node, "wakeup-source", NULL) != NULL) { -+ mmio_setbits_32(EXTI_BASE + EXTI_TZENR1, EXTI_TZENR1_TZEN18); -+ mmio_setbits_32(EXTI_BASE + EXTI_C1IMR1, EXTI_IMR1_IM18); -+ } -+ -+ return 1; -+} -diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c -new file mode 100644 -index 0000000000..1899707f76 ---- /dev/null -+++ b/drivers/st/timer/stm32_timer.c -@@ -0,0 +1,323 @@ -+/* -+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define TIM_CR1 0x00U /* Control Register 1 */ -+#define TIM_CR2 0x04U /* Control Register 2 */ -+#define TIM_SMCR 0x08U /* Slave mode control reg */ -+#define TIM_DIER 0x0CU /* DMA/interrupt register */ -+#define TIM_SR 0x10U /* Status register */ -+#define TIM_EGR 0x14U /* Event Generation Reg */ -+#define TIM_CCMR1 0x18U /* Capt/Comp 1 Mode Reg */ -+#define TIM_CCMR2 0x1CU /* Capt/Comp 2 Mode Reg */ -+#define TIM_CCER 0x20U /* Capt/Comp Enable Reg */ -+#define TIM_CNT 0x24U /* Counter */ -+#define TIM_PSC 0x28U /* Prescaler */ -+#define TIM_ARR 0x2CU /* Auto-Reload Register */ -+#define TIM_CCR1 0x34U /* Capt/Comp Register 1 */ -+#define TIM_CCR2 0x38U /* Capt/Comp Register 2 */ -+#define TIM_CCR3 0x3CU /* Capt/Comp Register 3 */ -+#define TIM_CCR4 0x40U /* Capt/Comp Register 4 */ -+#define TIM_BDTR 0x44U /* Break and Dead-Time Reg */ -+#define TIM_DCR 0x48U /* DMA control register */ -+#define TIM_DMAR 0x4CU /* DMA transfer register */ -+#define TIM_AF1 0x60U /* Alt Function Reg 1 */ -+#define TIM_AF2 0x64U /* Alt Function Reg 2 */ -+#define TIM_TISEL 0x68U /* Input Selection */ -+ -+#define TIM_CR1_CEN BIT(0) -+#define TIM_SMCR_SMS GENMASK(2, 0) /* Slave mode selection */ -+#define TIM_SMCR_TS GENMASK(6, 4) /* Trigger selection */ -+#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */ -+#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */ -+#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */ -+#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */ -+#define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */ -+#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */ -+#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */ -+#define TIM_SR_UIF BIT(0) /* UIF interrupt flag */ -+#define TIM_SR_CC1IF BIT(1) /* CC1 interrupt flag */ -+#define TIM_TISEL_TI1SEL_MASK GENMASK(3, 0) -+#define TIM_SMCR_SMS_RESET 0x4U -+#define TIM_SMCR_TS_SHIFT 4U -+#define TIM_SMCR_TS_TI1FP1 0x5U -+ -+#define TIM_COMPAT "st,stm32-timers" -+#define TIM_TIMEOUT_US 100000 -+#define TIM_TIMEOUT_STEP_US 10 -+#define TIM_PRESCAL_HSI 10U -+#define TIM_PRESCAL_CSI 7U -+#define TIM_MIN_FREQ_CALIB 50000000U -+#define TIM_THRESHOLD 1U -+ -+struct stm32_timer_instance { -+ uintptr_t base; -+ unsigned long clk; -+ unsigned long freq; -+ uint8_t cal_input; -+}; -+ -+static struct stm32_timer_instance stm32_timer[TIM_MAX_INSTANCE]; -+ -+static int stm32_timer_get_dt_node(struct dt_node_info *info, int offset) -+{ -+ int node; -+ -+ node = dt_get_node(info, offset, TIM_COMPAT); -+ if (node < 0) { -+ if (offset == -1) { -+ WARN("%s: No TIMER found\n", __func__); -+ } -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return node; -+} -+ -+static int stm32_timer_config(struct stm32_timer_instance *timer) -+{ -+ clk_enable(timer->clk); -+ -+ timer->freq = clk_get_rate(timer->clk); -+ -+ if (timer->freq < TIM_MIN_FREQ_CALIB) { -+ WARN("Timer is not accurate enough for calibration\n"); -+ 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, -+ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC1S_TI2, -+ TIM_CCMR_CC1S_TI1); -+ -+ mmio_clrbits_32(timer->base + TIM_CCER, -+ TIM_CCER_CC1P | TIM_CCER_CC1NP); -+ -+ mmio_clrsetbits_32(timer->base + TIM_SMCR, -+ TIM_SMCR_TS | TIM_SMCR_SMS, -+ (TIM_SMCR_TS_TI1FP1 << TIM_SMCR_TS_SHIFT) | -+ TIM_SMCR_SMS_RESET); -+ -+ mmio_write_32(timer->base + TIM_TISEL, timer->cal_input); -+ mmio_setbits_32(timer->base + TIM_CR1, TIM_CR1_CEN); -+ mmio_setbits_32(timer->base + TIM_CCER, TIM_CCER_CC1E); -+ } -+ -+ clk_disable(timer->clk); -+ -+ return 0; -+} -+ -+static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer) -+{ -+ uint32_t timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US; -+ uint32_t counter = 0U; -+ uint32_t old_counter; -+ uint64_t conv_timeout; -+ -+ if (stm32_timer_config(timer) < 0) { -+ return 0U; -+ } -+ -+ clk_enable(timer->clk); -+ -+ mmio_write_32(timer->base + TIM_SR, 0U); -+ while (((mmio_read_32(timer->base + TIM_SR) & -+ TIM_SR_UIF) == 0U) && (timeout != 0U)) { -+ udelay(TIM_TIMEOUT_STEP_US); -+ timeout--; -+ } -+ -+ if (timeout == 0U) { -+ goto out; -+ } -+ -+ mmio_write_32(timer->base + TIM_SR, 0U); -+ -+ conv_timeout = timeout_init_us(TIM_TIMEOUT_US); -+ do { -+ if (timeout_elapsed(conv_timeout)) { -+ WARN("Timer counter not stable\n"); -+ timeout = 0U; -+ goto out; -+ } -+ -+ timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US; -+ while (((mmio_read_32(timer->base + TIM_SR) & -+ TIM_SR_CC1IF) == 0U) && (timeout != 0U)) { -+ udelay(TIM_TIMEOUT_STEP_US); -+ timeout--; -+ } -+ -+ if (timeout == 0U) { -+ goto out; -+ } -+ -+ old_counter = counter; -+ counter = mmio_read_32(timer->base + TIM_CCR1); -+ } while ((MAX(counter, old_counter) - MIN(counter, old_counter)) > -+ TIM_THRESHOLD); -+ -+out: -+ clk_disable(timer->clk); -+ -+ if (timeout == 0U) { -+ return 0U; -+ } -+ -+ return counter; -+} -+ -+unsigned long stm32_timer_hsi_freq(void) -+{ -+ struct stm32_timer_instance *timer = &stm32_timer[HSI_CAL]; -+ unsigned long hsi_freq; -+ uint32_t counter; -+ -+ if (timer->base == 0) { -+ return 0; -+ } -+ -+ counter = stm32_timer_start_capture(timer); -+ VERBOSE("Counter value %i\n", counter); -+ -+ if (counter == 0U) { -+ return 0; -+ } -+ -+ hsi_freq = (timer->freq / counter) << TIM_PRESCAL_HSI; -+ -+ return hsi_freq; -+} -+ -+unsigned long stm32_timer_csi_freq(void) -+{ -+ struct stm32_timer_instance *timer = &stm32_timer[CSI_CAL]; -+ unsigned long csi_freq; -+ uint32_t counter; -+ -+ if (timer->base == 0) { -+ return 0; -+ } -+ -+ counter = stm32_timer_start_capture(timer); -+ VERBOSE("Counter value %i\n", counter); -+ -+ if (counter == 0U) { -+ return 0; -+ } -+ -+ csi_freq = (timer->freq / counter) << TIM_PRESCAL_CSI; -+ -+ return csi_freq; -+} -+ -+/* -+ * Get the timer frequence callback function for a target clock calibration -+ * @timer_freq_cb - Output callback function -+ * @type - Target clock calibration ID -+ */ -+void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void), -+ enum timer_cal type) -+{ -+ switch (type) { -+ case HSI_CAL: -+ if (stm32_timer[HSI_CAL].base != 0) { -+ *timer_freq_cb = stm32_timer_hsi_freq; -+ } -+ break; -+ -+ case CSI_CAL: -+ if (stm32_timer[CSI_CAL].base != 0) { -+ *timer_freq_cb = stm32_timer_csi_freq; -+ } -+ break; -+ -+ default: -+ panic(); -+ } -+} -+ -+/* -+ * Initialize timer from DT -+ * return 0 if disabled, 1 if enabled, else < 0 -+ */ -+int stm32_timer_init(void) -+{ -+ void *fdt; -+ struct dt_node_info dt_timer; -+ int node = -1; -+ uint8_t nb_timer = 0; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -EPERM; -+ } -+ -+ for (node = stm32_timer_get_dt_node(&dt_timer, node); -+ node != -FDT_ERR_NOTFOUND; -+ node = stm32_timer_get_dt_node(&dt_timer, node)) { -+ -+ if (dt_timer.status == DT_SECURE) { -+ struct stm32_timer_instance *timer; -+ const fdt32_t *cuint; -+ -+ nb_timer++; -+ -+ cuint = fdt_getprop(fdt, node, "st,hsi-cal-input", -+ NULL); -+ if (cuint != NULL) { -+ timer = &stm32_timer[HSI_CAL]; -+ timer->base = dt_timer.base; -+ timer->clk = dt_timer.clock; -+ timer->freq = clk_get_rate(timer->clk); -+ timer->cal_input = -+ (uint8_t)fdt32_to_cpu(*cuint); -+ if (stm32_timer_config(timer) < 0) { -+ timer->base = 0; -+ continue; -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, node, "st,csi-cal-input", -+ NULL); -+ if (cuint != NULL) { -+ timer = &stm32_timer[CSI_CAL]; -+ timer->base = dt_timer.base; -+ timer->clk = dt_timer.clock; -+ timer->freq = clk_get_rate(timer->clk); -+ timer->cal_input = -+ (uint8_t)fdt32_to_cpu(*cuint); -+ if (stm32_timer_config(timer) < 0) { -+ timer->base = 0; -+ continue; -+ } -+ } -+ } -+ } -+ -+ VERBOSE("%u TIMER instance%s found\n", nb_timer, -+ nb_timer > 1 ? "s" : ""); -+ -+ if (nb_timer == 0U) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return 0; -+} -diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S -index 686b18b969..2cb04a88fc 100644 ---- a/drivers/st/uart/aarch32/stm32_console.S -+++ b/drivers/st/uart/aarch32/stm32_console.S -@@ -122,17 +122,15 @@ register_fail: - pop {r4, pc} - endfunc console_stm32_register - -- /* --------------------------------------------------------------- -+ /* -------------------------------------------------------- - * int console_core_putc(int c, uintptr_t base_addr) -- * -- * Function to output a character over the console. It returns the -- * character printed on success or -1 on error. -- * -+ * 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 - console base address - * Out : return -1 on error else return character. -- * Clobber list : r2 -- * --------------------------------------------------------------- -+ * Clobber list : r2, r3 -+ * -------------------------------------------------------- - */ - func console_stm32_core_putc - /* Check the input parameter */ -@@ -140,13 +138,19 @@ func console_stm32_core_putc - beq putc_error - - /* Check Transmit Data Register Empty */ -+ mov r3, #USART_TIMEOUT - txe_loop: -+ subs r3, r3, #1 -+ beq putc_error - ldr r2, [r1, #USART_ISR] - tst r2, #USART_ISR_TXE - beq txe_loop - str r0, [r1, #USART_TDR] - /* Check transmit complete flag */ -+ mov r3, #USART_TIMEOUT - tc_loop: -+ subs r3, r3, #1 -+ beq putc_error - ldr r2, [r1, #USART_ISR] - tst r2, #USART_ISR_TC - beq tc_loop -@@ -200,7 +204,7 @@ endfunc console_stm32_core_getc - * - * In : r0 - console base address - * Out : void. -- * Clobber list : r0, r1 -+ * Clobber list : r0, r1, r2 - * --------------------------------------------------------------- - */ - func console_stm32_core_flush -@@ -209,7 +213,10 @@ func console_stm32_core_flush - ASM_ASSERT(ne) - #endif /* ENABLE_ASSERTIONS */ - /* Check Transmit Data Register Empty */ -+ mov r2, #USART_TIMEOUT - txe_loop_3: -+ subs r2, r2, #1 -+ beq plat_panic_handler - ldr r1, [r0, #USART_ISR] - tst r1, #USART_ISR_TXE - beq txe_loop_3 -diff --git a/drivers/st/uart/stm32_uart.c b/drivers/st/uart/stm32_uart.c -new file mode 100644 -index 0000000000..a0d21dcf33 ---- /dev/null -+++ b/drivers/st/uart/stm32_uart.c -@@ -0,0 +1,405 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* UART time-out value */ -+#define STM32_UART_TIMEOUT_US 20000U -+ -+/* Mask to clear ALL the configuration register */ -+ -+#define STM32_UART_CR1_FIELDS \ -+ (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ -+ USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN) -+ -+#define STM32_UART_CR2_FIELDS \ -+ (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \ -+ USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ -+ USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ -+ USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \ -+ USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \ -+ USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \ -+ USART_CR2_RTOEN | USART_CR2_ADD) -+ -+#define STM32_UART_CR3_FIELDS \ -+ (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \ -+ USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \ -+ USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \ -+ USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ -+ USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \ -+ USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \ -+ USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \ -+ USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG) -+ -+#define STM32_UART_ISR_ERRORS \ -+ (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE) -+ -+static const uint16_t presc_table[STM32_UART_PRESCALER_MAX + 1] = { -+ 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U -+}; -+ -+/* @brief BRR division operation to set BRR register in 8-bit oversampling -+ * mode. -+ * @param clockfreq: UART clock. -+ * @param baud_rate: Baud rate set by the user. -+ * @param prescaler: UART prescaler value. -+ * @retval Division result. -+ */ -+static uint32_t uart_div_sampling8(unsigned long clockfreq, -+ uint32_t baud_rate, -+ uint32_t prescaler) -+{ -+ uint32_t scaled_freq = clockfreq / presc_table[prescaler]; -+ -+ return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate; -+ -+} -+ -+/* @brief BRR division operation to set BRR register in 16-bit oversampling -+ * mode. -+ * @param clockfreq: UART clock. -+ * @param baud_rate: Baud rate set by the user. -+ * @param prescaler: UART prescaler value. -+ * @retval Division result. -+ */ -+static uint32_t uart_div_sampling16(unsigned long clockfreq, -+ uint32_t baud_rate, -+ uint32_t prescaler) -+{ -+ uint32_t scaled_freq = clockfreq / presc_table[prescaler]; -+ -+ return (scaled_freq + (baud_rate / 2)) / baud_rate; -+ -+} -+ -+/* -+ * @brief Return the UART clock frequency. -+ * @param huart: UART handle. -+ * @retval Frequency value in Hz. -+ */ -+static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart) -+{ -+ return fdt_get_uart_clock_freq((uintptr_t)huart->base); -+} -+ -+/* -+ * @brief Configure the UART peripheral. -+ * @param huart: UART handle. -+ * @retval UART status. -+ */ -+static int uart_set_config(struct stm32_uart_handle_s *huart, -+ const struct stm32_uart_init_s *init) -+{ -+ uint32_t tmpreg; -+ unsigned long clockfreq; -+ uint32_t brrtemp; -+ -+ /* -+ * ---------------------- USART CR1 Configuration -------------------- -+ * Clear M, PCE, PS, TE, RE and OVER8 bits and configure -+ * the UART word length, parity, mode and oversampling: -+ * - set the M bits according to init->word_length value, -+ * - set PCE and PS bits according to init->parity value, -+ * - set TE and RE bits according to init->mode value, -+ * - set OVER8 bit according to init->over_sampling value. -+ */ -+ tmpreg = init->word_length | -+ init->parity | -+ init->mode | -+ init->over_sampling | -+ init->fifo_mode; -+ mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg); -+ -+ /* -+ * --------------------- USART CR2 Configuration --------------------- -+ * Configure the UART Stop Bits: Set STOP[13:12] bits according -+ * to init->stop_bits value. -+ */ -+ mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS, -+ init->stop_bits); -+ -+ /* -+ * --------------------- USART CR3 Configuration --------------------- -+ * Configure: -+ * - UART HardWare Flow Control: set CTSE and RTSE bits according -+ * to init->hw_flow_control value, -+ * - one-bit sampling method versus three samples' majority rule -+ * according to init->one_bit_sampling (not applicable to -+ * LPUART), -+ * - set TXFTCFG bit according to init->tx_fifo_threshold value, -+ * - set RXFTCFG bit according to init->rx_fifo_threshold value. -+ */ -+ tmpreg = init->hw_flow_control | init->one_bit_sampling; -+ -+ if (init->fifo_mode == USART_CR1_FIFOEN) { -+ tmpreg |= init->tx_fifo_threshold | -+ init->rx_fifo_threshold; -+ } -+ -+ mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg); -+ -+ /* -+ * --------------------- USART PRESC Configuration ------------------- -+ * Configure UART Clock Prescaler : set PRESCALER according to -+ * init->prescaler value. -+ */ -+ assert(init->prescaler <= STM32_UART_PRESCALER_MAX); -+ mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER, -+ init->prescaler); -+ -+ /*---------------------- USART BRR configuration --------------------*/ -+ clockfreq = uart_get_clock_freq(huart); -+ if (clockfreq == 0UL) { -+ return -ENODEV; -+ } -+ -+ if (init->over_sampling == STM32_UART_OVERSAMPLING_8) { -+ uint32_t usartdiv = uart_div_sampling8(clockfreq, -+ init->baud_rate, -+ init->prescaler); -+ -+ brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) | -+ ((usartdiv & USART_BRR_DIV_FRACTION) >> 1); -+ } else { -+ brrtemp = uart_div_sampling16(clockfreq, -+ init->baud_rate, -+ init->prescaler) & -+ (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA); -+ } -+ mmio_write_32(huart->base + USART_BRR, brrtemp); -+ -+ return 0U; -+} -+ -+/* -+ * @brief Handle UART communication timeout. -+ * @param huart: UART handle. -+ * @param flag: Specifies the UART flag to check. -+ * @retval UART status. -+ */ -+static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag) -+{ -+ uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US); -+ -+ while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) { -+ if (timeout_elapsed(timeout_ref)) { -+ return -ETIMEDOUT; -+ } -+ } -+ -+ return 0U; -+} -+ -+/* -+ * @brief Check the UART idle State. -+ * @param huart: UART handle. -+ * @retval UART status. -+ */ -+static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart) -+{ -+ int ret; -+ -+ /* Check if the transmitter is enabled */ -+ if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) { -+ ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK); -+ if (ret != 0U) { -+ return ret; -+ } -+ } -+ -+ /* Check if the receiver is enabled */ -+ if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) { -+ ret = stm32_uart_wait_flag(huart, USART_ISR_REACK); -+ if (ret != 0U) { -+ return ret; -+ } -+ } -+ -+ return 0U; -+} -+ -+/* -+ * @brief Compute RDR register mask depending on word length. -+ * @param huart: UART handle. -+ * @retval Mask value. -+ */ -+static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init) -+{ -+ unsigned int mask; -+ -+ switch (init->word_length) { -+ case STM32_UART_WORDLENGTH_9B: -+ mask = GENMASK(8, 0); -+ break; -+ case STM32_UART_WORDLENGTH_8B: -+ mask = GENMASK(7, 0); -+ break; -+ case STM32_UART_WORDLENGTH_7B: -+ mask = GENMASK(6, 0); -+ break; -+ default: -+ return 0U; -+ } -+ -+ if (init->parity != STM32_UART_PARITY_NONE) { -+ mask >>= 1; -+ } -+ -+ return mask; -+} -+ -+/* -+ * @brief Stop the UART. -+ * @param base: UART base address. -+ */ -+void stm32_uart_stop(uintptr_t base) -+{ -+ mmio_clrbits_32(base + USART_CR1, USART_CR1_UE); -+} -+ -+/* -+ * @brief Initialize UART. -+ * @param huart: UART handle. -+ * @param base_addr: base address of UART. -+ * @param init: UART initialization parameter. -+ * @retval UART status. -+ */ -+ -+int stm32_uart_init(struct stm32_uart_handle_s *huart, -+ uintptr_t base_addr, -+ const struct stm32_uart_init_s *init) -+{ -+ int ret; -+ -+ if (huart == NULL || init == NULL || base_addr == 0U) { -+ return -EINVAL; -+ } -+ -+ huart->base = base_addr; -+ -+ /* Disable the peripheral */ -+ stm32_uart_stop(huart->base); -+ -+ /* Computation of UART mask to apply to RDR register */ -+ huart->rdr_mask = stm32_uart_rdr_mask(init); -+ -+ /* Init the peripheral */ -+ ret = uart_set_config(huart, init); -+ if (ret != 0U) { -+ return ret; -+ } -+ -+ /* Enable the peripheral */ -+ mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE); -+ -+ /* TEACK and/or REACK to check */ -+ return stm32_uart_check_idle(huart); -+} -+ -+/* -+ * @brief Check interrupt and status errors. -+ * @retval True if error detected, false otherwise. -+ */ -+static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart) -+{ -+ return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U; -+} -+ -+/* -+ * @brief Clear status errors. -+ */ -+static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart) -+{ -+ mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS); -+} -+ -+/* -+ * @brief Transmit one data in no blocking mode -+ * @param huart: UART handle. -+ * @param c: data to sent. -+ * @retval UART status. -+ */ -+int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c) -+{ -+ int ret; -+ -+ if (huart == NULL) { -+ return -EINVAL; -+ } -+ -+ ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); -+ if (ret != 0) { -+ return ret; -+ -+ } -+ mmio_write_32(huart->base + USART_TDR, c); -+ if (stm32_uart_error_detected(huart)) { -+ stm32_uart_error_clear(huart); -+ return -EFAULT; -+ } -+ -+ return 0U; -+} -+ -+/* -+ * @brief Flush TX Transmit fifo -+ * @param huart: UART handle. -+ * @retval UART status. -+ */ -+int stm32_uart_flush(struct stm32_uart_handle_s *huart) -+{ -+ int ret; -+ -+ if (huart == NULL) { -+ return -EINVAL; -+ } -+ ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); -+ if (ret != 0) { -+ return ret; -+ -+ } -+ ret = stm32_uart_wait_flag(huart, USART_ISR_TC); -+ -+ return ret; -+} -+ -+/* -+ * @brief Receive a data in no blocking mode. -+ * @retval value if >0 or UART status. -+ */ -+int stm32_uart_getc(struct stm32_uart_handle_s *huart) -+{ -+ uint32_t data; -+ -+ if (huart == NULL) { -+ return -EINVAL; -+ } -+ -+ /* check if data is available */ -+ if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) { -+ return -EAGAIN; -+ } -+ -+ data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask; -+ -+ if (stm32_uart_error_detected(huart)) { -+ stm32_uart_error_clear(huart); -+ return -EFAULT; -+ } -+ -+ return data; -+} -diff --git a/drivers/st/usb_dwc2/usb_dwc2.c b/drivers/st/usb_dwc2/usb_dwc2.c -new file mode 100644 -index 0000000000..fc3f771c7c ---- /dev/null -+++ b/drivers/st/usb_dwc2/usb_dwc2.c -@@ -0,0 +1,1094 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define USB_OTG_MODE_DEVICE 0U -+#define USB_OTG_MODE_HOST 1U -+#define USB_OTG_MODE_DRD 2U -+ -+#define EP_TYPE_CTRL 0U -+#define EP_TYPE_ISOC 1U -+#define EP_TYPE_BULK 2U -+#define EP_TYPE_INTR 3U -+ -+#define USBD_FIFO_FLUSH_TIMEOUT_US 1000U -+#define EP0_FIFO_SIZE 64U -+ -+/* OTG registers offsets */ -+#define OTG_GOTGINT 0x004U -+#define OTG_GAHBCFG 0x008U -+#define OTG_GUSBCFG 0x00CU -+#define OTG_GRSTCTL 0x010U -+#define OTG_GINTSTS 0x014U -+#define OTG_GINTMSK 0x018U -+#define OTG_GRXSTSP 0x020U -+#define OTG_GLPMCFG 0x054U -+#define OTG_DCFG 0x800U -+#define OTG_DCTL 0x804U -+#define OTG_DSTS 0x808U -+#define OTG_DIEPMSK 0x810U -+#define OTG_DOEPMSK 0x814U -+#define OTG_DAINT 0x818U -+#define OTG_DAINTMSK 0x81CU -+#define OTG_DIEPEMPMSK 0x834U -+ -+/* Definitions for OTG_DIEPx registers */ -+#define OTG_DIEP_BASE 0x900U -+#define OTG_DIEP_SIZE 0x20U -+#define OTG_DIEPCTL 0x00U -+#define OTG_DIEPINT 0x08U -+#define OTG_DIEPTSIZ 0x10U -+#define OTG_DIEPDMA 0x14U -+#define OTG_DTXFSTS 0x18U -+#define OTG_DIEP_MAX_NB 9U -+ -+/* Definitions for OTG_DOEPx registers */ -+#define OTG_DOEP_BASE 0xB00U -+#define OTG_DOEP_SIZE 0x20U -+#define OTG_DOEPCTL 0x00U -+#define OTG_DOEPINT 0x08U -+#define OTG_DOEPTSIZ 0x10U -+#define OTG_DOEPDMA 0x14U -+#define OTG_D0EP_MAX_NB 9U -+ -+/* Definitions for OTG_DAINT registers */ -+#define OTG_DAINT_OUT_MASK GENMASK(31, 16) -+#define OTG_DAINT_OUT_SHIFT 16U -+#define OTG_DAINT_IN_MASK GENMASK(15, 0) -+#define OTG_DAINT_IN_SHIFT 0U -+ -+#define OTG_DAINT_EP0_IN BIT(16) -+#define OTG_DAINT_EP0_OUT BIT(0) -+ -+/* Definitions for FIFOs */ -+#define OTG_FIFO_BASE 0x1000U -+#define OTG_FIFO_SIZE 0x1000U -+ -+/* Bit definitions for OTG_GOTGINT register */ -+#define OTG_GOTGINT_SEDET BIT(2) -+ -+/* Bit definitions for OTG_GAHBCFG register */ -+#define OTG_GAHBCFG_GINT BIT(0) -+ -+/* Bit definitions for OTG_GUSBCFG register */ -+#define OTG_GUSBCFG_TRDT GENMASK(13, 10) -+#define OTG_GUSBCFG_TRDT_SHIFT 10U -+ -+#define USBD_HS_TRDT_VALUE 9U -+ -+/* Bit definitions for OTG_GRSTCTL register */ -+#define OTG_GRSTCTL_RXFFLSH BIT(4) -+#define OTG_GRSTCTL_TXFFLSH BIT(5) -+#define OTG_GRSTCTL_TXFNUM_SHIFT 6U -+ -+/* Bit definitions for OTG_GINTSTS register */ -+#define OTG_GINTSTS_CMOD BIT(0) -+#define OTG_GINTSTS_MMIS BIT(1) -+#define OTG_GINTSTS_OTGINT BIT(2) -+#define OTG_GINTSTS_SOF BIT(3) -+#define OTG_GINTSTS_RXFLVL BIT(4) -+#define OTG_GINTSTS_USBSUSP BIT(11) -+#define OTG_GINTSTS_USBRST BIT(12) -+#define OTG_GINTSTS_ENUMDNE BIT(13) -+#define OTG_GINTSTS_IEPINT BIT(18) -+#define OTG_GINTSTS_OEPINT BIT(19) -+#define OTG_GINTSTS_IISOIXFR BIT(20) -+#define OTG_GINTSTS_IPXFR_INCOMPISOOUT BIT(21) -+#define OTG_GINTSTS_LPMINT BIT(27) -+#define OTG_GINTSTS_SRQINT BIT(30) -+#define OTG_GINTSTS_WKUPINT BIT(31) -+ -+/* Bit definitions for OTG_GRXSTSP register */ -+#define OTG_GRXSTSP_EPNUM GENMASK(3, 0) -+#define OTG_GRXSTSP_BCNT GENMASK(14, 4) -+#define OTG_GRXSTSP_BCNT_SHIFT 4U -+#define OTG_GRXSTSP_PKTSTS GENMASK(20, 17) -+#define OTG_GRXSTSP_PKTSTS_SHIFT 17U -+ -+#define STS_GOUT_NAK 1U -+#define STS_DATA_UPDT 2U -+#define STS_XFER_COMP 3U -+#define STS_SETUP_COMP 4U -+#define STS_SETUP_UPDT 6U -+ -+/* Bit definitions for OTG_GLPMCFG register */ -+#define OTG_GLPMCFG_BESL GENMASK(5, 2) -+ -+/* Bit definitions for OTG_DCFG register */ -+#define OTG_DCFG_DAD GENMASK(10, 4) -+#define OTG_DCFG_DAD_SHIFT 4U -+ -+/* Bit definitions for OTG_DCTL register */ -+#define OTG_DCTL_RWUSIG BIT(0) -+#define OTG_DCTL_SDIS BIT(1) -+#define OTG_DCTL_CGINAK BIT(8) -+ -+/* Bit definitions for OTG_DSTS register */ -+#define OTG_DSTS_SUSPSTS BIT(0) -+#define OTG_DSTS_ENUMSPD_MASK GENMASK(2, 1) -+#define OTG_DSTS_FNSOF0 BIT(8) -+ -+#define OTG_DSTS_ENUMSPD(val) ((val) << 1) -+#define OTG_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(0U) -+#define OTG_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(1U) -+#define OTG_DSTS_ENUMSPD_LS_PHY_6MHZ OTG_DSTS_ENUMSPD(2U) -+#define OTG_DSTS_ENUMSPD_FS_PHY_48MHZ OTG_DSTS_ENUMSPD(3U) -+ -+/* Bit definitions for OTG_DIEPMSK register */ -+#define OTG_DIEPMSK_XFRCM BIT(0) -+#define OTG_DIEPMSK_EPDM BIT(1) -+#define OTG_DIEPMSK_TOM BIT(3) -+ -+/* Bit definitions for OTG_DOEPMSK register */ -+#define OTG_DOEPMSK_XFRCM BIT(0) -+#define OTG_DOEPMSK_EPDM BIT(1) -+#define OTG_DOEPMSK_STUPM BIT(3) -+ -+/* Bit definitions for OTG_DIEPCTLx registers */ -+#define OTG_DIEPCTL_MPSIZ GENMASK(10, 0) -+#define OTG_DIEPCTL_STALL BIT(21) -+#define OTG_DIEPCTL_CNAK BIT(26) -+#define OTG_DIEPCTL_SD0PID_SEVNFRM BIT(28) -+#define OTG_DIEPCTL_SODDFRM BIT(29) -+#define OTG_DIEPCTL_EPDIS BIT(30) -+#define OTG_DIEPCTL_EPENA BIT(31) -+ -+/* Bit definitions for OTG_DIEPINTx registers */ -+#define OTG_DIEPINT_XFRC BIT(0) -+#define OTG_DIEPINT_EPDISD BIT(1) -+#define OTG_DIEPINT_TOC BIT(3) -+#define OTG_DIEPINT_ITTXFE BIT(4) -+#define OTG_DIEPINT_INEPNE BIT(6) -+#define OTG_DIEPINT_TXFE BIT(7) -+#define OTG_DIEPINT_TXFE_SHIFT 7U -+ -+#define OTG_DIEPINT_MASK (BIT(13) | BIT(11) | GENMASK(9, 0)) -+ -+/* Bit definitions for OTG_DIEPTSIZx registers */ -+#define OTG_DIEPTSIZ_XFRSIZ GENMASK(18, 0) -+#define OTG_DIEPTSIZ_PKTCNT GENMASK(28, 19) -+#define OTG_DIEPTSIZ_PKTCNT_SHIFT 19U -+#define OTG_DIEPTSIZ_MCNT_MASK GENMASK(30, 29) -+#define OTG_DIEPTSIZ_MCNT_DATA0 BIT(29) -+ -+#define OTG_DIEPTSIZ_PKTCNT_1 BIT(19) -+ -+/* Bit definitions for OTG_DTXFSTSx registers */ -+#define OTG_DTXFSTS_INEPTFSAV GENMASK(15, 0) -+ -+/* Bit definitions for OTG_DOEPCTLx registers */ -+#define OTG_DOEPCTL_STALL BIT(21) -+#define OTG_DOEPCTL_CNAK BIT(26) -+#define OTG_DOEPCTL_SD0PID_SEVNFRM BIT(28) /* other than endpoint 0 */ -+#define OTG_DOEPCTL_SD1PID_SODDFRM BIT(29) /* other than endpoint 0 */ -+#define OTG_DOEPCTL_EPDIS BIT(30) -+#define OTG_DOEPCTL_EPENA BIT(31) -+ -+/* Bit definitions for OTG_DOEPTSIZx registers */ -+#define OTG_DOEPTSIZ_XFRSIZ GENMASK(18, 0) -+#define OTG_DOEPTSIZ_PKTCNT GENMASK(28, 19) -+#define OTG_DOEPTSIZ_RXDPID_STUPCNT GENMASK(30, 29) -+ -+/* Bit definitions for OTG_DOEPINTx registers */ -+#define OTG_DOEPINT_XFRC BIT(0) -+#define OTG_DOEPINT_STUP BIT(3) -+#define OTG_DOEPINT_OTEPDIS BIT(4) -+ -+#define OTG_DOEPINT_MASK (GENMASK(15, 12) | GENMASK(9, 8) | GENMASK(6, 0)) -+ -+#define EP_NB 15U -+#define EP_ALL 0x10U -+ -+/* -+ * @brief Flush TX FIFO. -+ * @param handle: PCD handle. -+ * @param num: FIFO number. -+ * This parameter can be a value from 1 to 15 or EP_ALL. -+ * EP_ALL= 0x10 means Flush all TX FIFOs -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_flush_tx_fifo(void *handle, uint32_t num) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); -+ -+ mmio_write_32(usb_base_addr + OTG_GRSTCTL, -+ OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << OTG_GRSTCTL_TXFNUM_SHIFT)); -+ -+ while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & -+ OTG_GRSTCTL_TXFFLSH) == OTG_GRSTCTL_TXFFLSH) -+ if (timeout_elapsed(timeout)) { -+ return USBD_TIMEOUT; -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Flush RX FIFO. -+ * @param handle: PCD handle. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_flush_rx_fifo(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); -+ -+ mmio_write_32(usb_base_addr + OTG_GRSTCTL, OTG_GRSTCTL_RXFFLSH); -+ -+ while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & -+ OTG_GRSTCTL_RXFFLSH) == OTG_GRSTCTL_RXFFLSH) -+ if (timeout_elapsed(timeout)) { -+ return USBD_TIMEOUT; -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Return the global USB interrupt status. -+ * @param handle: PCD handle. -+ * @retval Interrupt register value. -+ */ -+static uint32_t usb_dwc2_read_int(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ return mmio_read_32(usb_base_addr + OTG_GINTSTS) & -+ mmio_read_32(usb_base_addr + OTG_GINTMSK); -+} -+ -+/* -+ * @brief Return the USB device OUT endpoints interrupt. -+ * @param handle: PCD handle. -+ * @retval Device OUT endpoint interrupts. -+ */ -+static uint32_t usb_dwc2_all_out_ep_int(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ return ((mmio_read_32(usb_base_addr + OTG_DAINT) & -+ mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & -+ OTG_DAINT_OUT_MASK) >> OTG_DAINT_OUT_SHIFT; -+} -+ -+/* -+ * @brief Return the USB device IN endpoints interrupt. -+ * @param handle: PCD handle. -+ * @retval Device IN endpoint interrupts. -+ */ -+static uint32_t usb_dwc2_all_in_ep_int(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ return ((mmio_read_32(usb_base_addr + OTG_DAINT) & -+ mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & -+ OTG_DAINT_IN_MASK) >> OTG_DAINT_IN_SHIFT; -+} -+ -+/* -+ * @brief Return Device OUT EP interrupt register. -+ * @param handle: PCD handle. -+ * @param epnum: Endpoint number. -+ * This parameter can be a value from 0 to 15. -+ * @retval Device OUT EP Interrupt register. -+ */ -+static uint32_t usb_dwc2_out_ep_int(void *handle, uint8_t epnum) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ return mmio_read_32(usb_base_addr + OTG_DOEP_BASE + -+ (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT) & -+ mmio_read_32(usb_base_addr + OTG_DOEPMSK); -+} -+ -+/* -+ * @brief Return Device IN EP interrupt register. -+ * @param handle: PCD handle. -+ * @param epnum: Endpoint number. -+ * This parameter can be a value from 0 to 15. -+ * @retval Device IN EP Interrupt register. -+ */ -+static uint32_t usb_dwc2_in_ep_int(void *handle, uint8_t epnum) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t msk; -+ uint32_t emp; -+ -+ msk = mmio_read_32(usb_base_addr + OTG_DIEPMSK); -+ emp = mmio_read_32(usb_base_addr + OTG_DIEPEMPMSK); -+ msk |= ((emp >> epnum) << OTG_DIEPINT_TXFE_SHIFT) & OTG_DIEPINT_TXFE; -+ -+ return mmio_read_32(usb_base_addr + OTG_DIEP_BASE + -+ (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT) & msk; -+} -+ -+/* -+ * @brief Return USB core mode. -+ * @param handle: PCD handle. -+ * @retval Core mode. -+ * This parameter can be one of the these values: -+ * 0 : Host. -+ * 1 : Device. -+ */ -+static uint32_t usb_dwc2_get_mode(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ return mmio_read_32(usb_base_addr + OTG_GINTSTS) & OTG_GINTSTS_CMOD; -+} -+ -+/* -+ * @brief Activate EP0 for detup transactions. -+ * @param handle: PCD handle. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_activate_setup(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE; -+ -+ /* Set the MPS of the IN EP based on the enumeration speed */ -+ mmio_clrbits_32(reg_offset + OTG_DIEPCTL, OTG_DIEPCTL_MPSIZ); -+ -+ if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_ENUMSPD_MASK) == -+ OTG_DSTS_ENUMSPD_LS_PHY_6MHZ) { -+ mmio_setbits_32(reg_offset + OTG_DIEPCTL, 3U); -+ } -+ -+ mmio_setbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_CGINAK); -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Prepare the EP0 to start the first control setup. -+ * @param handle: Selected device. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_ep0_out_start(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE + OTG_DIEPTSIZ; -+ uint32_t reg_value = 0U; -+ -+ /* PKTCNT = 1 and XFRSIZ = 24 bytes for endpoint 0 */ -+ reg_value |= OTG_DIEPTSIZ_PKTCNT_1; -+ reg_value |= (EP0_FIFO_SIZE & OTG_DIEPTSIZ_XFRSIZ); -+ reg_value |= OTG_DOEPTSIZ_RXDPID_STUPCNT; -+ -+ mmio_write_32(reg_offset, reg_value); -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Write a packet into the TX FIFO associated with the EP/channel. -+ * @param handle: Selected device. -+ * @param src: Pointer to source buffer. -+ * @param ch_ep_num: Endpoint or host channel number. -+ * @param len: Number of bytes to write. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_write_packet(void *handle, uint8_t *src, -+ uint8_t ch_ep_num, uint16_t len) -+{ -+ uint32_t reg_offset; -+ uint32_t count32b = (len + 3U) / 4U; -+ uint32_t i; -+ -+ reg_offset = (uintptr_t)handle + OTG_FIFO_BASE + -+ (ch_ep_num * OTG_FIFO_SIZE); -+ -+ for (i = 0U; i < count32b; i++) { -+ uint32_t src_copy = 0U; -+ uint32_t j; -+ -+ /* Data written to FIFO need to be 4 bytes aligned */ -+ for (j = 0U; j < 4U; j++) { -+ src_copy += (*(src + j)) << (8U * j); -+ } -+ -+ mmio_write_32(reg_offset, src_copy); -+ src += 4U; -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Read a packet from the RX FIFO associated with the EP/channel. -+ * @param handle: Selected device. -+ * @param src: Source pointer. -+ * @param ch_ep_num: Endpoint or host channel number. -+ * @param len: Number of bytes to read. -+ * @retval Pointer to destination buffer. -+ */ -+static void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len) -+{ -+ uint32_t reg_offset; -+ uint32_t count32b = (len + 3U) / 4U; -+ uint32_t i; -+ -+ VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest); -+ -+ reg_offset = (uintptr_t)handle + OTG_FIFO_BASE; -+ -+ for (i = 0U; i < count32b; i++) { -+ *(uint32_t *)dest = mmio_read_32(reg_offset); -+ dest += 4U; -+ dsb(); -+ } -+ -+ return (void *)dest; -+} -+ -+/* -+ * @brief Setup and start a transfer over an EP. -+ * @param handle: Selected device -+ * @param ep: Pointer to endpoint structure. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_ep_start_xfer(void *handle, usbd_ep_t *ep) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t reg_offset; -+ uint32_t reg_value; -+ uint32_t clear_value; -+ -+ if (ep->is_in) { -+ reg_offset = usb_base_addr + OTG_DIEP_BASE + (ep->num * OTG_DIEP_SIZE); -+ clear_value = OTG_DIEPTSIZ_PKTCNT | OTG_DIEPTSIZ_XFRSIZ; -+ if (ep->xfer_len == 0U) { -+ reg_value = OTG_DIEPTSIZ_PKTCNT_1; -+ } else { -+ /* -+ * Program the transfer size and packet count -+ * as follows: -+ * xfersize = N * maxpacket + short_packet -+ * pktcnt = N + (short_packet exist ? 1 : 0) -+ */ -+ reg_value = (OTG_DIEPTSIZ_PKTCNT & -+ (((ep->xfer_len + ep->maxpacket - 1U) / -+ ep->maxpacket) << OTG_DIEPTSIZ_PKTCNT_SHIFT)) -+ | ep->xfer_len; -+ -+ if (ep->type == EP_TYPE_ISOC) { -+ clear_value |= OTG_DIEPTSIZ_MCNT_MASK; -+ reg_value |= OTG_DIEPTSIZ_MCNT_DATA0; -+ } -+ } -+ -+ mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, clear_value, reg_value); -+ -+ if ((ep->type != EP_TYPE_ISOC) && (ep->xfer_len > 0U)) { -+ /* Enable the TX FIFO empty interrupt for this EP */ -+ mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(ep->num)); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ reg_value = OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA; -+ -+ if (ep->type == EP_TYPE_ISOC) { -+ if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { -+ reg_value |= OTG_DIEPCTL_SODDFRM; -+ } else { -+ reg_value |= OTG_DIEPCTL_SD0PID_SEVNFRM; -+ } -+ } -+ -+ mmio_setbits_32(reg_offset + OTG_DIEPCTL, reg_value); -+ -+ if (ep->type == EP_TYPE_ISOC) { -+ usb_dwc2_write_packet(handle, ep->xfer_buff, ep->num, ep->xfer_len); -+ } -+ } else { -+ reg_offset = usb_base_addr + OTG_DOEP_BASE + (ep->num * OTG_DOEP_SIZE); -+ /* -+ * Program the transfer size and packet count as follows: -+ * pktcnt = N -+ * xfersize = N * maxpacket -+ */ -+ if (ep->xfer_len == 0U) { -+ reg_value = ep->maxpacket | OTG_DIEPTSIZ_PKTCNT_1; -+ } else { -+ uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket; -+ -+ reg_value = (pktcnt << OTG_DIEPTSIZ_PKTCNT_SHIFT) | -+ (ep->maxpacket * pktcnt); -+ } -+ -+ mmio_clrsetbits_32(reg_offset + OTG_DOEPTSIZ, -+ OTG_DOEPTSIZ_XFRSIZ & OTG_DOEPTSIZ_PKTCNT, -+ reg_value); -+ -+ /* EP enable */ -+ reg_value = OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA; -+ -+ if (ep->type == EP_TYPE_ISOC) { -+ if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { -+ reg_value |= OTG_DOEPCTL_SD1PID_SODDFRM; -+ } else { -+ reg_value |= OTG_DOEPCTL_SD0PID_SEVNFRM; -+ } -+ } -+ -+ mmio_setbits_32(reg_offset + OTG_DOEPCTL, reg_value); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Setup and start a transfer over the EP0. -+ * @param handle: Selected device. -+ * @param ep: Pointer to endpoint structure. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_ep0_start_xfer(void *handle, usbd_ep_t *ep) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t reg_offset; -+ uint32_t reg_value; -+ -+ if (ep->is_in) { -+ reg_offset = usb_base_addr + OTG_DIEP_BASE + -+ (ep->num * OTG_DIEP_SIZE); -+ -+ if (ep->xfer_len == 0U) { -+ reg_value = OTG_DIEPTSIZ_PKTCNT_1; -+ } else { -+ /* -+ * Program the transfer size and packet count -+ * as follows: -+ * xfersize = N * maxpacket + short_packet -+ * pktcnt = N + (short_packet exist ? 1 : 0) -+ */ -+ -+ if (ep->xfer_len > ep->maxpacket) { -+ ep->xfer_len = ep->maxpacket; -+ } -+ -+ reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->xfer_len; -+ } -+ -+ mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, -+ OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, -+ reg_value); -+ -+ /* Enable the TX FIFO empty interrupt for this EP */ -+ if (ep->xfer_len > 0U) { -+ mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, -+ BIT(ep->num)); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ mmio_setbits_32(reg_offset + OTG_DIEPCTL, -+ OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA); -+ } else { -+ reg_offset = usb_base_addr + OTG_DOEP_BASE + -+ (ep->num * OTG_DOEP_SIZE); -+ -+ /* -+ * Program the transfer size and packet count as follows: -+ * pktcnt = N -+ * xfersize = N * maxpacket -+ */ -+ if (ep->xfer_len > 0U) { -+ ep->xfer_len = ep->maxpacket; -+ } -+ -+ reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->maxpacket; -+ -+ mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, -+ OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, -+ reg_value); -+ -+ /* EP enable */ -+ mmio_setbits_32(reg_offset + OTG_DOEPCTL, -+ OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Set a stall condition over an EP. -+ * @param handle: Selected device. -+ * @param ep: Pointer to endpoint structure. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_ep_set_stall(void *handle, usbd_ep_t *ep) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t reg_offset; -+ uint32_t reg_value; -+ -+ if (ep->is_in) { -+ reg_offset = usb_base_addr + OTG_DIEP_BASE + -+ (ep->num * OTG_DIEP_SIZE); -+ reg_value = mmio_read_32(reg_offset + OTG_DIEPCTL); -+ -+ if ((reg_value & OTG_DIEPCTL_EPENA) == 0U) { -+ reg_value &= ~OTG_DIEPCTL_EPDIS; -+ } -+ -+ reg_value |= OTG_DIEPCTL_STALL; -+ -+ mmio_write_32(reg_offset + OTG_DIEPCTL, reg_value); -+ } else { -+ reg_offset = usb_base_addr + OTG_DOEP_BASE + -+ (ep->num * OTG_DOEP_SIZE); -+ reg_value = mmio_read_32(reg_offset + OTG_DOEPCTL); -+ -+ if ((reg_value & OTG_DOEPCTL_EPENA) == 0U) { -+ reg_value &= ~OTG_DOEPCTL_EPDIS; -+ } -+ -+ reg_value |= OTG_DOEPCTL_STALL; -+ -+ mmio_write_32(reg_offset + OTG_DOEPCTL, reg_value); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Stop the USB device mode. -+ * @param handle: Selected device. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_stop_device(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t i; -+ -+ /* Disable Int */ -+ mmio_clrbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); -+ -+ /* Clear pending interrupts */ -+ for (i = 0U; i < EP_NB; i++) { -+ mmio_write_32(usb_base_addr + OTG_DIEP_BASE + (i * OTG_DIEP_SIZE) + OTG_DIEPINT, -+ OTG_DIEPINT_MASK); -+ mmio_write_32(usb_base_addr + OTG_DOEP_BASE + (i * OTG_DOEP_SIZE) + OTG_DOEPINT, -+ OTG_DOEPINT_MASK); -+ } -+ -+ mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); -+ -+ /* Clear interrupt masks */ -+ mmio_write_32(usb_base_addr + OTG_DIEPMSK, 0U); -+ mmio_write_32(usb_base_addr + OTG_DOEPMSK, 0U); -+ mmio_write_32(usb_base_addr + OTG_DAINTMSK, 0U); -+ -+ /* Flush the FIFO */ -+ usb_dwc2_flush_rx_fifo(handle); -+ usb_dwc2_flush_tx_fifo(handle, EP_ALL); -+ -+ /* Disconnect the USB device by disabling the pull-up/pull-down. */ -+ mmio_setbits_32((uintptr_t)handle + OTG_DCTL, OTG_DCTL_SDIS); -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Stop the USB device mode. -+ * @param handle: Selected device. -+ * @param address: New device address to be assigned. -+ * This parameter can be a value from 0 to 255. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_set_address(void *handle, uint8_t address) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ mmio_clrsetbits_32(usb_base_addr + OTG_DCFG, -+ OTG_DCFG_DAD, -+ address << OTG_DCFG_DAD_SHIFT); -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Check FIFO for the next packet to be loaded. -+ * @param handle: Selected device. -+ * @param epnum : Endpoint number. -+ * @param xfer_len: Block length. -+ * @param xfer_count: Number of blocks. -+ * @param maxpacket: Max packet length. -+ * @param xfer_buff: Buffer pointer. -+ * @retval USB status. -+ */ -+static usb_status_t usb_dwc2_write_empty_tx_fifo(void *handle, -+ uint32_t epnum, -+ uint32_t xfer_len, -+ uint32_t *xfer_count, -+ uint32_t maxpacket, -+ uint8_t **xfer_buff) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t reg_offset; -+ int32_t len; -+ uint32_t len32b; -+ usb_status_t ret; -+ -+ len = xfer_len - *xfer_count; -+ -+ if ((len > 0) && ((uint32_t)len > maxpacket)) { -+ len = maxpacket; -+ } -+ -+ len32b = (len + 3U) / 4U; -+ -+ reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE); -+ -+ while (((mmio_read_32(reg_offset + OTG_DTXFSTS) & -+ OTG_DTXFSTS_INEPTFSAV) > len32b) && -+ (*xfer_count < xfer_len) && (xfer_len != 0U)) { -+ /* Write the FIFO */ -+ len = xfer_len - *xfer_count; -+ -+ if ((len > 0) && ((uint32_t)len > maxpacket)) { -+ len = maxpacket; -+ } -+ -+ len32b = (len + 3U) / 4U; -+ -+ ret = usb_dwc2_write_packet(handle, *xfer_buff, epnum, len); -+ if (ret != USBD_OK) { -+ return ret; -+ } -+ -+ *xfer_buff += len; -+ *xfer_count += len; -+ } -+ -+ if (len <= 0) { -+ mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Handle PCD interrupt request. -+ * @param handle: PCD handle. -+ * @param param: Pointer to information updated by the IT handling. -+ * @retval Action to do after IT handling. -+ */ -+static usb_action_t usb_dwc2_it_handler(void *handle, uint32_t *param) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ uint32_t ep_intr; -+ uint32_t epint; -+ uint32_t epnum; -+ uint32_t temp; -+ usb_status_t ret; -+ -+ if (usb_dwc2_get_mode(handle) != USB_OTG_MODE_DEVICE) { -+ return USB_NOTHING; -+ } -+ -+ /* Avoid spurious interrupt */ -+ if (usb_dwc2_read_int(handle) == 0U) { -+ return USB_NOTHING; -+ } -+ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_MMIS) != 0U) { -+ /* Incorrect mode, acknowledge the interrupt */ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_MMIS); -+ } -+ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OEPINT) != 0U) { -+ uint32_t reg_offset; -+ -+ /* Read in the device interrupt bits */ -+ ep_intr = usb_dwc2_all_out_ep_int(handle); -+ epnum = 0U; -+ while ((ep_intr & BIT(0)) != BIT(0)) { -+ epnum++; -+ ep_intr >>= 1; -+ } -+ -+ reg_offset = usb_base_addr + OTG_DOEP_BASE + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT; -+ -+ epint = usb_dwc2_out_ep_int(handle, epnum); -+ -+ if ((epint & OTG_DOEPINT_XFRC) == OTG_DOEPINT_XFRC) { -+ mmio_write_32(reg_offset, OTG_DOEPINT_XFRC); -+ *param = epnum; -+ -+ return USB_DATA_OUT; -+ } -+ -+ if ((epint & OTG_DOEPINT_STUP) == OTG_DOEPINT_STUP) { -+ /* Inform that a setup packet is available */ -+ mmio_write_32(reg_offset, OTG_DOEPINT_STUP); -+ -+ return USB_SETUP; -+ } -+ -+ if ((epint & OTG_DOEPINT_OTEPDIS) == OTG_DOEPINT_OTEPDIS) { -+ mmio_write_32(reg_offset, OTG_DOEPINT_OTEPDIS); -+ } -+ } -+ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IEPINT) != 0U) { -+ uint32_t reg_offset; -+ -+ /* Read in the device interrupt bits */ -+ ep_intr = usb_dwc2_all_in_ep_int(handle); -+ epnum = 0U; -+ while ((ep_intr & BIT(0)) != BIT(0)) { -+ epnum++; -+ ep_intr >>= 1; -+ } -+ -+ reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT; -+ -+ epint = usb_dwc2_in_ep_int(handle, epnum); -+ -+ if ((epint & OTG_DIEPINT_XFRC) == OTG_DIEPINT_XFRC) { -+ mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); -+ mmio_write_32(reg_offset, OTG_DIEPINT_XFRC); -+ *param = epnum; -+ -+ return USB_DATA_IN; -+ } -+ -+ if ((epint & OTG_DIEPINT_TOC) == OTG_DIEPINT_TOC) { -+ mmio_write_32(reg_offset, OTG_DIEPINT_TOC); -+ } -+ -+ if ((epint & OTG_DIEPINT_ITTXFE) == OTG_DIEPINT_ITTXFE) { -+ mmio_write_32(reg_offset, OTG_DIEPINT_ITTXFE); -+ } -+ -+ if ((epint & OTG_DIEPINT_INEPNE) == OTG_DIEPINT_INEPNE) { -+ mmio_write_32(reg_offset, OTG_DIEPINT_INEPNE); -+ } -+ -+ if ((epint & OTG_DIEPINT_EPDISD) == OTG_DIEPINT_EPDISD) { -+ mmio_write_32(reg_offset, OTG_DIEPINT_EPDISD); -+ } -+ -+ if ((epint & OTG_DIEPINT_TXFE) == OTG_DIEPINT_TXFE) { -+ *param = epnum; -+ -+ return USB_WRITE_EMPTY; -+ } -+ } -+ -+ /* Handle resume interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_WKUPINT) != 0U) { -+ INFO("handle USB : Resume\n"); -+ -+ /* Clear the remote wake-up signaling */ -+ mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_WKUPINT); -+ -+ return USB_RESUME; -+ } -+ -+ /* Handle suspend interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBSUSP) != 0U) { -+ INFO("handle USB : Suspend int\n"); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBSUSP); -+ -+ if ((mmio_read_32(usb_base_addr + OTG_DSTS) & -+ OTG_DSTS_SUSPSTS) == OTG_DSTS_SUSPSTS) { -+ return USB_SUSPEND; -+ } -+ } -+ -+ /* Handle LPM interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_LPMINT) != 0U) { -+ INFO("handle USB : LPM int enter in suspend\n"); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_LPMINT); -+ *param = (mmio_read_32(usb_base_addr + OTG_GLPMCFG) & -+ OTG_GLPMCFG_BESL) >> 2; -+ -+ return USB_LPM; -+ } -+ -+ /* Handle reset interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBRST) != 0U) { -+ INFO("handle USB : Reset\n"); -+ -+ mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); -+ -+ usb_dwc2_flush_tx_fifo(handle, 0U); -+ -+ mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); -+ mmio_setbits_32(usb_base_addr + OTG_DAINTMSK, OTG_DAINT_EP0_IN | OTG_DAINT_EP0_OUT); -+ -+ mmio_setbits_32(usb_base_addr + OTG_DOEPMSK, OTG_DOEPMSK_STUPM | -+ OTG_DOEPMSK_XFRCM | -+ OTG_DOEPMSK_EPDM); -+ mmio_setbits_32(usb_base_addr + OTG_DIEPMSK, OTG_DIEPMSK_TOM | -+ OTG_DIEPMSK_XFRCM | -+ OTG_DIEPMSK_EPDM); -+ -+ /* Set default address to 0 */ -+ mmio_clrbits_32(usb_base_addr + OTG_DCFG, OTG_DCFG_DAD); -+ -+ /* Setup EP0 to receive SETUP packets */ -+ ret = usb_dwc2_ep0_out_start(handle); -+ if (ret != USBD_OK) { -+ return ret; -+ } -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBRST); -+ -+ return USB_RESET; -+ } -+ -+ /* Handle enumeration done interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_ENUMDNE) != 0U) { -+ ret = usb_dwc2_activate_setup(handle); -+ if (ret != USBD_OK) { -+ return ret; -+ } -+ -+ mmio_clrbits_32(usb_base_addr + OTG_GUSBCFG, OTG_GUSBCFG_TRDT); -+ -+ mmio_setbits_32(usb_base_addr + OTG_GUSBCFG, -+ (USBD_HS_TRDT_VALUE << OTG_GUSBCFG_TRDT_SHIFT) & OTG_GUSBCFG_TRDT); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_ENUMDNE); -+ -+ return USB_ENUM_DONE; -+ } -+ -+ /* Handle RXQLevel interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_RXFLVL) != 0U) { -+ mmio_clrbits_32(usb_base_addr + OTG_GINTMSK, -+ OTG_GINTSTS_RXFLVL); -+ -+ temp = mmio_read_32(usb_base_addr + OTG_GRXSTSP); -+ -+ *param = temp & OTG_GRXSTSP_EPNUM; -+ *param |= (temp & OTG_GRXSTSP_BCNT) << (USBD_OUT_COUNT_SHIFT - -+ OTG_GRXSTSP_BCNT_SHIFT); -+ -+ if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == STS_DATA_UPDT) { -+ if ((temp & OTG_GRXSTSP_BCNT) != 0U) { -+ mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); -+ -+ return USB_READ_DATA_PACKET; -+ } -+ } else if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == -+ STS_SETUP_UPDT) { -+ mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); -+ -+ return USB_READ_SETUP_PACKET; -+ } -+ -+ mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); -+ } -+ -+ /* Handle SOF interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SOF) != 0U) { -+ INFO("handle USB : SOF\n"); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SOF); -+ -+ return USB_SOF; -+ } -+ -+ /* Handle incomplete ISO IN interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IISOIXFR) != 0U) { -+ INFO("handle USB : ISO IN\n"); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, -+ OTG_GINTSTS_IISOIXFR); -+ } -+ -+ /* Handle incomplete ISO OUT interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IPXFR_INCOMPISOOUT) != -+ 0U) { -+ INFO("handle USB : ISO OUT\n"); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, -+ OTG_GINTSTS_IPXFR_INCOMPISOOUT); -+ } -+ -+ /* Handle connection event interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SRQINT) != 0U) { -+ INFO("handle USB : Connect\n"); -+ -+ mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SRQINT); -+ } -+ -+ /* Handle disconnection event interrupt */ -+ if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OTGINT) != 0U) { -+ INFO("handle USB : Disconnect\n"); -+ -+ temp = mmio_read_32(usb_base_addr + OTG_GOTGINT); -+ -+ if ((temp & OTG_GOTGINT_SEDET) == OTG_GOTGINT_SEDET) { -+ return USB_DISCONNECT; -+ } -+ } -+ -+ return USB_NOTHING; -+} -+ -+/* -+ * @brief Start the usb device mode -+ * @param usb_core_handle: USB core driver handle. -+ * @retval None. -+ * return USB status. -+ */ -+static usb_status_t usb_dwc2_start_device(void *handle) -+{ -+ uintptr_t usb_base_addr = (uintptr_t)handle; -+ -+ mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_SDIS); -+ mmio_setbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); -+ -+ return USBD_OK; -+} -+ -+static const usb_driver_t usb_dwc2driver = { -+ .ep0_out_start = usb_dwc2_ep0_out_start, -+ .ep_start_xfer = usb_dwc2_ep_start_xfer, -+ .ep0_start_xfer = usb_dwc2_ep0_start_xfer, -+ .write_packet = usb_dwc2_write_packet, -+ .read_packet = usb_dwc2_read_packet, -+ .ep_set_stall = usb_dwc2_ep_set_stall, -+ .start_device = usb_dwc2_start_device, -+ .stop_device = usb_dwc2_stop_device, -+ .set_address = usb_dwc2_set_address, -+ .write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo, -+ .it_handler = usb_dwc2_it_handler -+}; -+ -+/* -+ * @brief Initialize USB DWC2 driver. -+ * @param usb_core_handle: USB core driver handle. -+ * @param pcd_handle: PCD handle. -+ * @param base_register: USB global register base address. -+ * @retval None. -+ */ -+void usb_dwc2_init_driver(usb_handle_t *usb_core_handle, -+ pcd_handle_t *pcd_handle, -+ void *base_register) -+{ -+ register_usb_driver(usb_core_handle, pcd_handle, &usb_dwc2driver, -+ base_register); -+} -diff --git a/fdts/stm32mp15-bl2.dtsi b/fdts/stm32mp15-bl2.dtsi -new file mode 100644 -index 0000000000..4e3573fb12 ---- /dev/null -+++ b/fdts/stm32mp15-bl2.dtsi -@@ -0,0 +1,116 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved -+ */ -+ -+/ { -+#if !(STM32MP_EMMC || STM32MP_SDMMC) -+ aliases { -+ /delete-property/ mmc0; -+ }; -+#endif -+ -+ cpus { -+ /delete-node/ cpu@1; -+ }; -+ -+ /delete-node/ psci; -+ -+ soc { -+ /delete-node/ timer@40006000; -+ /delete-node/ timer@44006000; -+ /delete-node/ pwr_mcu@50001014; -+ /delete-node/ cryp@54001000; -+ /delete-node/ rng@54003000; -+ /delete-node/ spi@5c001000; -+ /delete-node/ rtc@5c004000; -+ /delete-node/ etzpc@5c007000; -+ /delete-node/ stgen@5c008000; -+ /delete-node/ i2c@5c009000; -+ /delete-node/ tamp@5c00a000; -+#if !(STM32MP_EMMC || STM32MP_SDMMC) -+ /delete-node/ sdmmc@58005000; -+ /delete-node/ sdmmc@58007000; -+#endif -+#if !STM32MP_RAW_NAND -+ /delete-node/ memory-controller@58002000; -+#endif -+#if !(STM32MP_SPI_NAND || STM32MP_SPI_NOR) -+ /delete-node/ spi@58003000; -+#endif -+#if !STM32MP_USB_PROGRAMMER -+ /delete-node/ usb-otg@49000000; -+ /delete-node/ usbphyc@5a006000; -+#endif -+ -+ pin-controller@50002000 { -+ /delete-node/ rtc-out2-rmp-pins-0; -+#if !(STM32MP_EMMC || STM32MP_SDMMC) -+ /delete-node/ sdmmc1-b4-0; -+ /delete-node/ sdmmc1-dir-0; -+ /delete-node/ sdmmc2-b4-0; -+ /delete-node/ sdmmc2-b4-1; -+ /delete-node/ sdmmc2-d47-0; -+#endif -+#if !STM32MP_RAW_NAND -+ /delete-node/ fmc-0; -+#endif -+#if !(STM32MP_SPI_NAND || STM32MP_SPI_NOR) -+ /delete-node/ qspi-clk-0; -+ /delete-node/ qspi-bk1-0; -+ /delete-node/ qspi-bk2-0; -+#endif -+#if !STM32MP_USB_PROGRAMMER -+ /delete-node/ usbotg_hs-0; -+ /delete-node/ usbotg-fs-dp-dm-0; -+#endif -+ }; -+ }; -+ -+#if !STM32MP_USE_STM32IMAGE -+ /* -+ * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in -+ * network order (big endian) -+ */ -+ -+ st-io_policies { -+ fip-handles { -+ compatible = "st,io-fip-handle"; -+ fw_cfg_uuid = <0x5807e16a 0x845947be 0x8ed5648e 0x8dddab0e>; -+ bl32_uuid = <0x05d0e189 0x53dc1347 0x8d2b500a 0x4b7a3e38>; -+ bl32_extra1_uuid = <0x0b70c29b 0x2a5a7840 0x9f650a56 0x82738288>; -+ bl32_extra2_uuid = <0x8ea87bb1 0xcfa23f4d 0x85fde7bb 0xa50220d9>; -+ bl33_uuid = <0xd6d0eea7 0xfcead54b 0x97829934 0xf234b6e4>; -+ hw_cfg_uuid = <0x08b8f1d9 0xc9cf9349 0xa9626fbc 0x6b7265cc>; -+ tos_fw_cfg_uuid = <0x26257c1a 0xdbc67f47 0x8d96c4c4 0xb0248021>; -+ nt_fw_cfg_uuid = <0x28da9815 0x93e87e44 0xac661aaf 0x801550f9>; -+#if TRUSTED_BOARD_BOOT -+ t_key_cert_uuid = <0x827ee890 0xf860e411 0xa1b4777a 0x21b4f94c>; -+ t_boot_fw_cert_uuid = <0xd6e269ea 0x5d63e411 0x8d8c9fba 0xbe9956a5>; -+ tos_fw_key_cert_uuid = <0x9477d603 0xfb60e411 0x85ddb710 0x5b8cee04>; -+ nt_fw_key_cert_uuid = <0x8ad5832a 0xfb60e411 0x8aafdf30 0xbbc49859>; -+ tos_fw_content_cert_uuid = <0xa49f4411 0x5e63e411 0x87283f05 0x722af33d>; -+ nt_fw_content_cert_uuid = <0x8ec4c1f3 0x5d63e411 0xa7a987ee 0x40b23fa7>; -+#endif -+ }; -+ }; -+ -+#if TRUSTED_BOARD_BOOT -+ tb_fw-config { -+ compatible = "arm,tb_fw"; -+ -+ /* Disable authentication for development */ -+ disable_auth = <0x0>; -+ -+ /* -+ * The following two entries are placeholders for Mbed TLS -+ * heap information. -+ */ -+ mbedtls_heap_addr = <0x0 0x0>; -+ mbedtls_heap_size = <0x0>; -+ }; -+ -+#include "cot_descriptors.dtsi" -+#endif -+#endif /* !STM32MP_USE_STM32IMAGE */ -+}; -diff --git a/fdts/stm32mp15-bl32.dtsi b/fdts/stm32mp15-bl32.dtsi -new file mode 100644 -index 0000000000..d237f0d275 ---- /dev/null -+++ b/fdts/stm32mp15-bl32.dtsi -@@ -0,0 +1,42 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved -+ */ -+ -+/ { -+ aliases { -+ /delete-property/ mmc0; -+ }; -+ -+ cpus { -+ /delete-node/ cpu@1; -+ }; -+ -+ /delete-node/ psci; -+ -+ soc { -+ /delete-node/ usb-otg@49000000; -+ /delete-node/ hash@54002000; -+ /delete-node/ memory-controller@58002000; -+ /delete-node/ spi@58003000; -+ /delete-node/ sdmmc@58005000; -+ /delete-node/ sdmmc@58007000; -+ /delete-node/ spi@5c001000; -+ /delete-node/ stgen@5c008000; -+ /delete-node/ i2c@5c009000; -+ -+ pin-controller@50002000 { -+ /delete-node/ fmc-0; -+ /delete-node/ qspi-clk-0; -+ /delete-node/ qspi-bk1-0; -+ /delete-node/ qspi-bk2-0; -+ /delete-node/ sdmmc1-b4-0; -+ /delete-node/ sdmmc1-dir-0; -+ /delete-node/ sdmmc2-b4-0; -+ /delete-node/ sdmmc2-b4-1; -+ /delete-node/ sdmmc2-d47-0; -+ /delete-node/ usbotg_hs-0; -+ /delete-node/ usbotg-fs-dp-dm-0; -+ }; -+ }; -+}; -diff --git a/fdts/stm32mp15-ddr-1g-fw-config.dts b/fdts/stm32mp15-ddr-1g-fw-config.dts -new file mode 100644 -index 0000000000..c871463062 ---- /dev/null -+++ b/fdts/stm32mp15-ddr-1g-fw-config.dts -@@ -0,0 +1,63 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+ -+#include -+#include -+ -+/dts-v1/; -+ -+/ { -+ dtb-registry { -+ compatible = "fconf,dyn_cfg-dtb_registry"; -+ -+ hw-config { -+ load-address = <0x0 STM32MP_HW_CONFIG_BASE>; -+ max-size = ; -+ id = ; -+ }; -+ -+ nt_fw { -+ load-address = <0x0 STM32MP_BL33_BASE>; -+ max-size = ; -+ id = ; -+ }; -+ -+#ifdef AARCH32_SP_OPTEE -+ tos_fw { -+ load-address = <0x0 0x2FFC0000>; -+ max-size = <0x0001F000>; -+ id = ; -+ }; -+#else -+ tos_fw { -+ load-address = <0x0 STM32MP_BL32_BASE>; -+ max-size = ; -+ id = ; -+ }; -+ -+ tos_fw-config { -+ load-address = <0x0 STM32MP_BL32_DTB_BASE>; -+ max-size = ; -+ id = ; -+ }; -+#endif -+ }; -+ -+ st-mem-firewall { -+ compatible = "st,mem-firewall"; -+#ifdef AARCH32_SP_OPTEE -+ memory-ranges = < -+ 0xc0000000 0x3e000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR -+ 0xfe000000 0x01e00000 TZC_REGION_S_RDWR 0 -+ 0xffe00000 0x00200000 TZC_REGION_S_NONE -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; -+#else -+ memory-ranges = < -+ 0xc0000000 0x40000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; -+#endif -+ }; -+}; -diff --git a/fdts/stm32mp15-ddr-512m-fw-config.dts b/fdts/stm32mp15-ddr-512m-fw-config.dts -new file mode 100644 -index 0000000000..3d0722181a ---- /dev/null -+++ b/fdts/stm32mp15-ddr-512m-fw-config.dts -@@ -0,0 +1,63 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+ -+#include -+#include -+ -+/dts-v1/; -+ -+/ { -+ dtb-registry { -+ compatible = "fconf,dyn_cfg-dtb_registry"; -+ -+ hw-config { -+ load-address = <0x0 STM32MP_HW_CONFIG_BASE>; -+ max-size = ; -+ id = ; -+ }; -+ -+ nt_fw { -+ load-address = <0x0 STM32MP_BL33_BASE>; -+ max-size = ; -+ id = ; -+ }; -+ -+#ifdef AARCH32_SP_OPTEE -+ tos_fw { -+ load-address = <0x0 0x2FFC0000>; -+ max-size = <0x0001F000>; -+ id = ; -+ }; -+#else -+ tos_fw { -+ load-address = <0x0 STM32MP_BL32_BASE>; -+ max-size = ; -+ id = ; -+ }; -+ -+ tos_fw-config { -+ load-address = <0x0 STM32MP_BL32_DTB_BASE>; -+ max-size = ; -+ id = ; -+ }; -+#endif -+ }; -+ -+ st-mem-firewall { -+ compatible = "st,mem-firewall"; -+#ifdef AARCH32_SP_OPTEE -+ memory-ranges = < -+ 0xc0000000 0x1e000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR -+ 0xde000000 0x01e00000 TZC_REGION_S_RDWR 0 -+ 0xdfe00000 0x00200000 TZC_REGION_S_NONE -+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; -+#else -+ memory-ranges = < -+ 0xc0000000 0x20000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; -+#endif -+ }; -+}; -diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi -index 4825691f90..734943c0ea 100644 ---- a/fdts/stm32mp15-ddr.dtsi -+++ b/fdts/stm32mp15-ddr.dtsi -@@ -14,14 +14,18 @@ - - clocks = <&rcc AXIDCG>, - <&rcc DDRC1>, -+#if STM32MP_DDR_DUAL_AXI_PORT - <&rcc DDRC2>, -+#endif - <&rcc DDRPHYC>, - <&rcc DDRCAPB>, - <&rcc DDRPHYCAPB>; - - clock-names = "axidcg", - "ddrc1", -+#if STM32MP_DDR_DUAL_AXI_PORT - "ddrc2", -+#endif - "ddrphyc", - "ddrcapb", - "ddrphycapb"; -@@ -97,12 +101,14 @@ - DDR_PCFGQOS1_0 - DDR_PCFGWQOS0_0 - DDR_PCFGWQOS1_0 -+#if STM32MP_DDR_DUAL_AXI_PORT - DDR_PCFGR_1 - DDR_PCFGW_1 - DDR_PCFGQOS0_1 - DDR_PCFGQOS1_1 - DDR_PCFGWQOS0_1 - DDR_PCFGWQOS1_1 -+#endif - >; - - st,phy-reg = < -@@ -115,8 +121,10 @@ - DDR_ZQ0CR1 - DDR_DX0GCR - DDR_DX1GCR -+#if STM32MP_DDR_DUAL_AXI_PORT - DDR_DX2GCR - DDR_DX3GCR -+#endif - >; - - st,phy-timing = < -@@ -132,6 +140,7 @@ - DDR_MR3 - >; - -+#ifdef DDR_PHY_CAL_SKIP - st,phy-cal = < - DDR_DX0DLLCR - DDR_DX0DQTR -@@ -139,13 +148,16 @@ - DDR_DX1DLLCR - DDR_DX1DQTR - DDR_DX1DQSTR -+#if STM32MP_DDR_DUAL_AXI_PORT - DDR_DX2DLLCR - DDR_DX2DQTR - DDR_DX2DQSTR - DDR_DX3DLLCR - DDR_DX3DQTR - DDR_DX3DQSTR -+#endif - >; -+#endif - - status = "okay"; - }; -diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -index c0fc1f772e..127053b86a 100644 ---- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -+++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -@@ -61,13 +61,13 @@ - #define DDR_DBGCMD 0x00000000 - #define DDR_POISONCFG 0x00000000 - #define DDR_PCCFG 0x00000010 --#define DDR_PCFGR_0 0x00010000 -+#define DDR_PCFGR_0 0x00000000 - #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_PCFGR_1 0x00000000 - #define DDR_PCFGW_1 0x00000000 - #define DDR_PCFGQOS0_1 0x02100C03 - #define DDR_PCFGQOS1_1 0x00800040 -diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -index fc226d2544..5ae861fee1 100644 ---- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -@@ -61,13 +61,13 @@ - #define DDR_DBGCMD 0x00000000 - #define DDR_POISONCFG 0x00000000 - #define DDR_PCCFG 0x00000010 --#define DDR_PCFGR_0 0x00010000 -+#define DDR_PCFGR_0 0x00000000 - #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_PCFGR_1 0x00000000 - #define DDR_PCFGW_1 0x00000000 - #define DDR_PCFGQOS0_1 0x02100C03 - #define DDR_PCFGQOS1_1 0x00800040 -diff --git a/fdts/stm32mp15-pinctrl.dtsi b/fdts/stm32mp15-pinctrl.dtsi -index d3d1744ec4..16c40cbff9 100644 ---- a/fdts/stm32mp15-pinctrl.dtsi -+++ b/fdts/stm32mp15-pinctrl.dtsi -@@ -194,33 +194,89 @@ - - uart7_pins_a: uart7-0 { - pins1 { -- pinmux = ; /* UART4_TX */ -+ pinmux = ; /* UART7_TX */ - bias-disable; - drive-push-pull; - slew-rate = <0>; - }; - pins2 { -- pinmux = , /* UART4_RX */ -- , /* UART4_CTS */ -- ; /* UART4_RTS */ -+ pinmux = , /* UART7_RX */ -+ , /* UART7_CTS */ -+ ; /* UART7_RTS */ - bias-disable; - }; - }; - - uart7_pins_b: uart7-1 { - pins1 { -- pinmux = ; /* USART7_TX */ -+ pinmux = ; /* UART7_TX */ - bias-disable; - drive-push-pull; - slew-rate = <0>; - }; - pins2 { -- pinmux = ; /* USART7_RX */ -+ pinmux = ; /* UART7_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ uart7_pins_c: uart7-2 { -+ pins1 { -+ pinmux = ; /* UART7_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* UART7_RX */ -+ bias-pull-up; -+ }; -+ }; -+ -+ uart8_pins_a: uart8-0 { -+ pins1 { -+ pinmux = ; /* UART8_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* UART8_RX */ - bias-disable; - }; - }; - - usart2_pins_a: usart2-0 { -+ pins1 { -+ pinmux = , /* USART2_TX */ -+ ; /* USART2_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART2_RX */ -+ ; /* USART2_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ -+ usart2_pins_b: usart2-1 { -+ pins1 { -+ pinmux = , /* USART2_TX */ -+ ; /* USART2_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART2_RX */ -+ ; /* USART2_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ -+ usart2_pins_c: usart2-2 { - pins1 { - pinmux = , /* USART2_TX */ - ; /* USART2_RTS */ -@@ -236,6 +292,19 @@ - }; - - usart3_pins_a: usart3-0 { -+ pins1 { -+ pinmux = ; /* USART3_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* USART3_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_pins_b: usart3-1 { - pins1 { - pinmux = , /* USART3_TX */ - ; /* USART3_RTS */ -@@ -250,7 +319,7 @@ - }; - }; - -- usart3_pins_b: usart3-1 { -+ usart3_pins_c: usart3-2 { - pins1 { - pinmux = , /* USART3_TX */ - ; /* USART3_RTS */ -@@ -261,11 +330,11 @@ - pins2 { - pinmux = , /* USART3_RX */ - ; /* USART3_CTS_NSS */ -- bias-disable; -+ bias-pull-up; - }; - }; - -- usbotg_hs_pins_a: usbotg_hs-0 { -+ usbotg_hs_pins_a: usbotg-hs-0 { - pins { - pinmux = ; /* OTG_ID */ - }; -diff --git a/fdts/stm32mp15-ssp-bl2.dtsi b/fdts/stm32mp15-ssp-bl2.dtsi -new file mode 100644 -index 0000000000..107f6e2166 ---- /dev/null -+++ b/fdts/stm32mp15-ssp-bl2.dtsi -@@ -0,0 +1,125 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved -+ */ -+ -+/ { -+ cpus { -+ /delete-node/ cpu@1; -+ }; -+ -+#if STM32MP_USB_PROGRAMMER -+ aliases { -+ /delete-property/ serial1; -+ }; -+#endif -+ -+ /delete-node/ cpu0_opp_table; -+ -+ nvmem_layout@0 { -+ /delete-property/ nvmem-cells; -+ /delete-property/ nvmem-cell-names; -+ -+ nvmem-cells = <&cfg0_otp>, -+ <&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>, -+ <&pkh_otp>, -+ <&cfg2_otp>, -+ <&ssp_otp>, -+ <&chip_otp>, -+ <&rma_otp>; -+ -+ nvmem-cell-names = "cfg0_otp", -+ "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp", -+ "pkh_otp", -+ "cfg2_otp", -+ "ssp_otp", -+ "chip_otp", -+ "rma_otp"; -+ }; -+ -+ /delete-node/ psci; -+ -+ soc { -+ efuse@5c005000 { -+ cfg2_otp: cfg2_otp@8 { -+ reg = <0x8 0x4>; -+ }; -+ -+ ssp_otp: ssp_otp@20 { -+ reg = <0x20 0x4>; -+ }; -+ -+ chip_otp: chip_otp@a0 { -+ reg = <0xa0 0x40>; -+ }; -+ -+ rma_otp: rma_otp@e0 { -+ reg = <0xe0 0x4>; -+ }; -+ }; -+ -+ /delete-node/ timer@40006000; -+ /delete-node/ timer@44006000; -+ /delete-node/ pwr_mcu@50001014; -+ /delete-node/ cryp@54001000; -+ /delete-node/ rng@54003000; -+ /delete-node/ memory-controller@58002000; -+ /delete-node/ spi@58003000; -+ /delete-node/ sdmmc@58005000; -+ /delete-node/ sdmmc@58007000; -+ /delete-node/ ddr@5a003000; -+ /delete-node/ spi@5c001000; -+ /delete-node/ rtc@5c004000; -+ /delete-node/ etzpc@5c007000; -+ /delete-node/ stgen@5c008000; -+ /delete-node/ i2c@5c009000; -+ /delete-node/ tamp@5c00a000; -+#if STM32MP_USB_PROGRAMMER -+ /delete-node/ serial@4000e000; -+ /delete-node/ serial@4000f000; -+ /delete-node/ serial@40011000; -+ /delete-node/ serial@40018000; -+ /delete-node/ serial@40019000; -+ /delete-node/ serial@44003000; -+ /delete-node/ serial@5c000000; -+#endif -+#if STM32MP_UART_PROGRAMMER -+ /delete-node/ usb-otg@49000000; -+ /delete-node/ usbphyc@5a006000; -+#endif -+ -+ pin-controller@50002000 { -+ /delete-node/ fmc-0; -+ /delete-node/ qspi-clk-0; -+ /delete-node/ qspi-bk1-0; -+ /delete-node/ qspi-bk2-0; -+ /delete-node/ rtc-out2-rmp-pins-0; -+ /delete-node/ sdmmc1-b4-0; -+ /delete-node/ sdmmc1-dir-0; -+ /delete-node/ sdmmc2-b4-0; -+ /delete-node/ sdmmc2-b4-1; -+ /delete-node/ sdmmc2-d47-0; -+#if STM32MP_USB_PROGRAMMER -+ /delete-node/ uart7-0; -+ /delete-node/ uart7-1; -+ /delete-node/ usart2-0; -+ /delete-node/ usart3-0; -+ /delete-node/ usart3-1; -+#endif -+#if STM32MP_UART_PROGRAMMER -+ /delete-node/ usbotg_hs-0; -+ /delete-node/ usbotg-fs-dp-dm-0; -+#endif -+ }; -+ }; -+}; -diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi -index 8f175a6492..714d94710f 100644 ---- a/fdts/stm32mp151.dtsi -+++ b/fdts/stm32mp151.dtsi -@@ -19,9 +19,41 @@ - 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>, -+ <&pkh_otp>; -+ -+ nvmem-cell-names = "cfg0_otp", -+ "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp", -+ "pkh_otp"; -+ }; -+ - psci { - compatible = "arm,psci-1.0"; - method = "smc"; -@@ -82,12 +114,13 @@ - clocks = <&rcc TIM12_K>; - clock-names = "int"; - status = "disabled"; -+ secure-status = "disabled"; - }; - - usart2: serial@4000e000 { - compatible = "st,stm32h7-uart"; - reg = <0x4000e000 0x400>; -- interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - clocks = <&rcc USART2_K>; - resets = <&rcc USART2_R>; - status = "disabled"; -@@ -96,7 +129,7 @@ - usart3: serial@4000f000 { - compatible = "st,stm32h7-uart"; - reg = <0x4000f000 0x400>; -- interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - clocks = <&rcc USART3_K>; - resets = <&rcc USART3_R>; - status = "disabled"; -@@ -115,7 +148,7 @@ - uart5: serial@40011000 { - compatible = "st,stm32h7-uart"; - reg = <0x40011000 0x400>; -- interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - clocks = <&rcc UART5_K>; - resets = <&rcc UART5_R>; - status = "disabled"; -@@ -124,7 +157,7 @@ - uart7: serial@40018000 { - compatible = "st,stm32h7-uart"; - reg = <0x40018000 0x400>; -- interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - clocks = <&rcc UART7_K>; - resets = <&rcc UART7_R>; - status = "disabled"; -@@ -133,7 +166,7 @@ - uart8: serial@40019000 { - compatible = "st,stm32h7-uart"; - reg = <0x40019000 0x400>; -- interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - clocks = <&rcc UART8_K>; - resets = <&rcc UART8_R>; - status = "disabled"; -@@ -142,7 +175,7 @@ - usart6: serial@44003000 { - compatible = "st,stm32h7-uart"; - reg = <0x44003000 0x400>; -- interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - clocks = <&rcc USART6_K>; - resets = <&rcc USART6_R>; - status = "disabled"; -@@ -156,16 +189,17 @@ - clocks = <&rcc TIM15_K>; - clock-names = "int"; - status = "disabled"; -+ secure-status = "disabled"; - }; - - usbotg_hs: usb-otg@49000000 { -- compatible = "st,stm32mp1-hsotg", "snps,dwc2"; -+ compatible = "st,stm32mp15-hsotg", "snps,dwc2"; - reg = <0x49000000 0x10000>; - clocks = <&rcc USBO_K>; - clock-names = "otg"; - resets = <&rcc USBO_R>; - reset-names = "dwc2"; -- interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = ; - g-rx-fifo-size = <512>; - g-np-tx-fifo-size = <32>; - g-tx-fifo-size = <256 16 16 16 16 16 16 16>; -@@ -175,7 +209,7 @@ - }; - - rcc: rcc@50000000 { -- compatible = "st,stm32mp1-rcc", "syscon"; -+ compatible = "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon"; - reg = <0x50000000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; -@@ -254,6 +288,7 @@ - clocks = <&rcc HASH1>; - resets = <&rcc HASH1_R>; - status = "disabled"; -+ secure-status = "disabled"; - }; - - rng1: rng@54003000 { -@@ -262,6 +297,7 @@ - clocks = <&rcc RNG1_K>; - resets = <&rcc RNG1_R>; - status = "disabled"; -+ secure-status = "disabled"; - }; - - fmc: memory-controller@58002000 { -@@ -301,6 +337,8 @@ - interrupts = ; - clocks = <&rcc QSPI_K>; - resets = <&rcc QSPI_R>; -+ #address-cells = <1>; -+ #size-cells = <0>; - status = "disabled"; - }; - -@@ -341,6 +379,7 @@ - clocks = <&rcc IWDG2>, <&rcc CK_LSI>; - clock-names = "pclk", "lsi"; - status = "disabled"; -+ secure-status = "disabled"; - }; - - usbphyc: usbphyc@5a006000 { -@@ -373,6 +412,7 @@ - clocks = <&rcc USART1_K>; - resets = <&rcc USART1_R>; - status = "disabled"; -+ secure-status = "disabled"; - }; - - spi6: spi@5c001000 { -@@ -384,6 +424,7 @@ - clocks = <&rcc SPI6_K>; - resets = <&rcc SPI6_R>; - status = "disabled"; -+ secure-status = "disabled"; - }; - - i2c4: i2c@5c002000 { -@@ -399,6 +440,7 @@ - st,syscfg-fmp = <&syscfg 0x4 0x8>; - wakeup-source; - status = "disabled"; -+ secure-status = "disabled"; - }; - - iwdg1: watchdog@5c003000 { -@@ -408,6 +450,7 @@ - clocks = <&rcc IWDG1>, <&rcc CK_LSI>; - clock-names = "pclk", "lsi"; - status = "disabled"; -+ secure-status = "disabled"; - }; - - rtc: rtc@5c004000 { -@@ -417,19 +460,49 @@ - clock-names = "pclk", "rtc_ck"; - interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; -+ secure-status = "disabled"; - }; - -- bsec: nvmem@5c005000 { -+ bsec: efuse@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>; -+ }; -+ ethernet_mac_address: mac@e4 { -+ reg = <0xe4 0x8>; -+ st,non-secure-otp; -+ }; - }; - - etzpc: etzpc@5c007000 { -@@ -458,6 +531,7 @@ - st,syscfg-fmp = <&syscfg 0x4 0x20>; - wakeup-source; - status = "disabled"; -+ secure-status = "disabled"; - }; - - tamp: tamp@5c00a000 { -@@ -621,6 +695,7 @@ - st,bank-name = "GPIOZ"; - st,bank-ioport = <11>; - status = "disabled"; -+ secure-status = "disabled"; - }; - }; - }; -diff --git a/fdts/stm32mp153.dtsi b/fdts/stm32mp153.dtsi -index 0a0bb8dc19..617380a52f 100644 ---- a/fdts/stm32mp153.dtsi -+++ b/fdts/stm32mp153.dtsi -@@ -14,6 +14,7 @@ - reg = <1>; - clocks = <&rcc CK_MPU>; - clock-names = "cpu"; -+ operating-points-v2 = <&cpu0_opp_table>; - }; - }; - }; -diff --git a/fdts/stm32mp157a-avenger96-fw-config.dts b/fdts/stm32mp157a-avenger96-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157a-avenger96-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157a-avenger96.dts b/fdts/stm32mp157a-avenger96.dts -index b967736e47..57c1b02d46 100644 ---- a/fdts/stm32mp157a-avenger96.dts -+++ b/fdts/stm32mp157a-avenger96.dts -@@ -10,9 +10,11 @@ - /dts-v1/; - - #include "stm32mp157.dtsi" -+#include "stm32mp15xa.dtsi" - #include "stm32mp15-pinctrl.dtsi" - #include "stm32mp15xxac-pinctrl.dtsi" - #include -+#include - #include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" - - / { -@@ -35,6 +37,22 @@ - }; - }; - -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c4_pins_a>; -@@ -273,10 +291,12 @@ - - &rng1 { - status = "okay"; -+ secure-status = "okay"; - }; - - &rtc { - status = "okay"; -+ secure-status = "okay"; - }; - - &sdmmc1 { -diff --git a/fdts/stm32mp157a-dk1-fw-config.dts b/fdts/stm32mp157a-dk1-fw-config.dts -new file mode 100644 -index 0000000000..256d0db935 ---- /dev/null -+++ b/fdts/stm32mp157a-dk1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-512m-fw-config.dts" -diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts -index a73bef8ee4..5d5c0a5f74 100644 ---- a/fdts/stm32mp157a-dk1.dts -+++ b/fdts/stm32mp157a-dk1.dts -@@ -7,9 +7,11 @@ - /dts-v1/; - - #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"; -@@ -25,3 +27,19 @@ - stdout-path = "serial0:115200n8"; - }; - }; -+ -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-ed1-fw-config.dts b/fdts/stm32mp157a-ed1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157a-ed1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157a-ed1.dts b/fdts/stm32mp157a-ed1.dts -new file mode 100644 -index 0000000000..1527b642a4 ---- /dev/null -+++ b/fdts/stm32mp157a-ed1.dts -@@ -0,0 +1,38 @@ -+// 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"; -+ }; -+}; -+ -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-fw-config.dts b/fdts/stm32mp157a-ev1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157a-ev1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157a-ev1.dts b/fdts/stm32mp157a-ev1.dts -new file mode 100644 -index 0000000000..3cb35698ad ---- /dev/null -+++ b/fdts/stm32mp157a-ev1.dts -@@ -0,0 +1,24 @@ -+// 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 { -+ serial0 = &uart4; -+ serial1 = &usart3; -+ }; -+}; -+ -diff --git a/fdts/stm32mp157c-dk2-fw-config.dts b/fdts/stm32mp157c-dk2-fw-config.dts -new file mode 100644 -index 0000000000..256d0db935 ---- /dev/null -+++ b/fdts/stm32mp157c-dk2-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-512m-fw-config.dts" -diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts -index be8300e9e0..ff5c4509fe 100644 ---- a/fdts/stm32mp157c-dk2.dts -+++ b/fdts/stm32mp157c-dk2.dts -@@ -11,6 +11,7 @@ - #include "stm32mp15-pinctrl.dtsi" - #include "stm32mp15xxac-pinctrl.dtsi" - #include "stm32mp15xx-dkx.dtsi" -+#include - - / { - model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; -@@ -31,3 +32,20 @@ - &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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-fw-config.dts b/fdts/stm32mp157c-ed1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157c-ed1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts -index a6b98b7d93..8d80147518 100644 ---- a/fdts/stm32mp157c-ed1.dts -+++ b/fdts/stm32mp157c-ed1.dts -@@ -1,7 +1,7 @@ - // 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/; - -@@ -9,8 +9,8 @@ - #include "stm32mp15xc.dtsi" - #include "stm32mp15-pinctrl.dtsi" - #include "stm32mp15xxaa-pinctrl.dtsi" --#include --#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" -+#include "stm32mp15xx-edx.dtsi" -+#include - - / { - model = "STMicroelectronics STM32MP157C eval daughter"; -@@ -19,318 +19,25 @@ - chosen { - stdout-path = "serial0:115200n8"; - }; -- -- -- memory@c0000000 { -- device_type = "memory"; -- reg = <0xC0000000 0x40000000>; -- }; -- -- aliases { -- serial0 = &uart4; -- }; --}; -- --&bsec { -- board_id: board_id@ec { -- reg = <0xec 0x4>; -- status = "okay"; -- secure-status = "okay"; -- }; --}; -- --&clk_hse { -- st,digbypass; --}; -- --&cpu0 { -- cpu-supply = <&vddcore>; --}; -- --&cpu1 { -- cpu-supply = <&vddcore>; - }; - - &cryp1 { -- status="okay"; --}; -- --&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"; -- -- pmic: stpmic@33 { -- compatible = "st,stpmic1"; -- reg = <0x33>; -- interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; -- interrupt-controller; -- #interrupt-cells = <2>; -- status = "okay"; -- -- 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"; -- 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"; -- }; -- -- 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; -- }; -- -- 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>; -- }; -- }; -- -- onkey { -- compatible = "st,stpmic1-onkey"; -- power-off-time-sec = <10>; -- status = "okay"; -- }; -- -- watchdog { -- compatible = "st,stpmic1-wdt"; -- status = "disabled"; -- }; -- }; --}; -- --&iwdg2 { -- timeout-sec = <32>; - status = "okay"; - }; - --&pwr_regulators { -- vdd-supply = <&vdd>; -- vdd_3v3_usbfs-supply = <&vdd_usb>; --}; -- --&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 -- >; -- -- 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 -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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) - >; -- -- /* 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) >; -- }; --}; -- --&rng1 { -- status = "okay"; --}; -- --&rtc { -- 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; -- 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"; --}; -- --&uart4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&uart4_pins_a>; -- status = "okay"; - }; -diff --git a/fdts/stm32mp157c-ev1-fw-config.dts b/fdts/stm32mp157c-ev1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157c-ev1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts -index c5d12e3b23..d12d30093c 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-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-ed1.dts" -+#include "stm32mp15xx-evx.dtsi" - - / { - model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; -@@ -16,47 +17,7 @@ - }; - - aliases { -+ serial0 = &uart4; - serial1 = &usart3; - }; - }; -- --&fmc { -- pinctrl-names = "default"; -- pinctrl-0 = <&fmc_pins_a>; -- status = "okay"; -- -- nand-controller@4,0 { -- status = "okay"; -- -- 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>; -- 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>; -- }; --}; -- --&usart3 { -- pinctrl-names = "default"; -- pinctrl-0 = <&usart3_pins_a>; -- status = "disabled"; --}; -diff --git a/fdts/stm32mp157d-dk1-fw-config.dts b/fdts/stm32mp157d-dk1-fw-config.dts -new file mode 100644 -index 0000000000..256d0db935 ---- /dev/null -+++ b/fdts/stm32mp157d-dk1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-512m-fw-config.dts" -diff --git a/fdts/stm32mp157d-dk1.dts b/fdts/stm32mp157d-dk1.dts -new file mode 100644 -index 0000000000..79297b831f ---- /dev/null -+++ b/fdts/stm32mp157d-dk1.dts -@@ -0,0 +1,45 @@ -+// 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 "stm32mp15xxac-pinctrl.dtsi" -+#include "stm32mp15xx-dkx.dtsi" -+#include -+ -+/ { -+ model = "STMicroelectronics STM32MP157D-DK1 Discovery Board"; -+ compatible = "st,stm32mp157d-dk1", "st,stm32mp157"; -+ -+ aliases { -+ serial0 = &uart4; -+ serial1 = &usart3; -+ serial2 = &uart7; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+}; -+ -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-fw-config.dts b/fdts/stm32mp157d-ed1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157d-ed1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157d-ed1.dts b/fdts/stm32mp157d-ed1.dts -new file mode 100644 -index 0000000000..2c67ec0acb ---- /dev/null -+++ b/fdts/stm32mp157d-ed1.dts -@@ -0,0 +1,39 @@ -+// 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"; -+ }; -+}; -+ -+ -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-fw-config.dts b/fdts/stm32mp157d-ev1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157d-ev1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157d-ev1.dts b/fdts/stm32mp157d-ev1.dts -new file mode 100644 -index 0000000000..4a40f5fe51 ---- /dev/null -+++ b/fdts/stm32mp157d-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 "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 { -+ serial0 = &uart4; -+ serial1 = &usart3; -+ }; -+}; -diff --git a/fdts/stm32mp157f-dk2-fw-config.dts b/fdts/stm32mp157f-dk2-fw-config.dts -new file mode 100644 -index 0000000000..256d0db935 ---- /dev/null -+++ b/fdts/stm32mp157f-dk2-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-512m-fw-config.dts" -diff --git a/fdts/stm32mp157f-dk2.dts b/fdts/stm32mp157f-dk2.dts -new file mode 100644 -index 0000000000..680ca0f6e7 ---- /dev/null -+++ b/fdts/stm32mp157f-dk2.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 "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"; -+ }; -+}; -+ -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-fw-config.dts b/fdts/stm32mp157f-ed1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157f-ed1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157f-ed1.dts b/fdts/stm32mp157f-ed1.dts -new file mode 100644 -index 0000000000..1aa26cdbbe ---- /dev/null -+++ b/fdts/stm32mp157f-ed1.dts -@@ -0,0 +1,43 @@ -+// 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"; -+ }; -+}; -+ -+&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_NS_R_S_W, DECPROT_LOCK) -+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-fw-config.dts b/fdts/stm32mp157f-ev1-fw-config.dts -new file mode 100644 -index 0000000000..10f9402c4a ---- /dev/null -+++ b/fdts/stm32mp157f-ev1-fw-config.dts -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include "stm32mp15-ddr-1g-fw-config.dts" -diff --git a/fdts/stm32mp157f-ev1.dts b/fdts/stm32mp157f-ev1.dts -new file mode 100644 -index 0000000000..caf5dfe11a ---- /dev/null -+++ b/fdts/stm32mp157f-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 "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 { -+ serial0 = &uart4; -+ serial1 = &usart3; -+ }; -+}; -diff --git a/fdts/stm32mp15xa.dtsi b/fdts/stm32mp15xa.dtsi -new file mode 100644 -index 0000000000..5ed7e594f4 ---- /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 -index b06a55a2fa..68d822d8c1 100644 ---- a/fdts/stm32mp15xc.dtsi -+++ b/fdts/stm32mp15xc.dtsi -@@ -4,6 +4,8 @@ - * Author: Alexandre Torgue for STMicroelectronics. - */ - -+#include "stm32mp15xa.dtsi" -+ - / { - soc { - cryp1: cryp@54001000 { -@@ -13,6 +15,7 @@ - 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 0000000000..18b05ee380 ---- /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 0000000000..526a1627cf ---- /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 -index 52b914b84e..e5166706ee 100644 ---- a/fdts/stm32mp15xx-dkx.dtsi -+++ b/fdts/stm32mp15xx-dkx.dtsi -@@ -5,6 +5,7 @@ - */ - - #include -+#include - #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" - - / { -@@ -52,6 +53,7 @@ - i2c-scl-falling-time-ns = <20>; - clock-frequency = <400000>; - status = "okay"; -+ secure-status = "okay"; - - pmic: stpmic@33 { - compatible = "st,stpmic1"; -@@ -60,6 +62,7 @@ - interrupt-controller; - #interrupt-cells = <2>; - status = "okay"; -+ secure-status = "okay"; - - regulators { - compatible = "st,stpmic1-regulators"; -@@ -139,9 +142,6 @@ - - vdd_usb: ldo4 { - regulator-name = "vdd_usb"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; - }; - - vdda: ldo5 { -@@ -182,17 +182,48 @@ - - &iwdg2 { - timeout-sec = <32>; -+ secure-timeout-sec = <5>; - status = "okay"; - 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 { -- secure-status = "disabled"; -+ st,hsi-cal; -+ st,csi-cal; -+ st,cal-sec = <60>; - st,clksrc = < - CLK_MPU_PLL1P - CLK_AXI_PLL2P -@@ -257,14 +288,6 @@ - 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"; -@@ -291,10 +314,12 @@ - - &rng1 { - status = "okay"; -+ secure-status = "okay"; - }; - - &rtc { - status = "okay"; -+ secure-status = "okay"; - }; - - &sdmmc1 { -@@ -309,6 +334,8 @@ - - &timers15 { - secure-status = "okay"; -+ st,hsi-cal-input = <7>; -+ st,csi-cal-input = <8>; - }; - - &uart4 { -@@ -319,13 +346,13 @@ - - &uart7 { - pinctrl-names = "default"; -- pinctrl-0 = <&uart7_pins_b>; -+ pinctrl-0 = <&uart7_pins_c>; - status = "disabled"; - }; - - &usart3 { - pinctrl-names = "default"; -- pinctrl-0 = <&usart3_pins_b>; -+ pinctrl-0 = <&usart3_pins_c>; - uart-has-rtscts; - status = "disabled"; - }; -@@ -348,3 +375,128 @@ - &usbphyc_port1 { - phy-supply = <&vdd_usb>; - }; -+ -+/* Low-power states of regulators */ -+&v1v2_hdmi { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v1v8_audio { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&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; -+ }; -+}; -+ -+&v3v3_hdmi { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&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; -+ }; -+}; -+ -+&vdda { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&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; -+ }; -+}; -+ -+&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; -+ }; -+}; -+ -+&vdd_usb { -+ 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; -+ }; -+}; -+ -+&vtt_ddr { -+ lp-stop { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi -new file mode 100644 -index 0000000000..540f5b9d97 ---- /dev/null -+++ b/fdts/stm32mp15xx-edx.dtsi -@@ -0,0 +1,518 @@ -+// 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 "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" -+ -+/ { -+ 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; -+}; -+ -+&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"; -+ reg = <0x33>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ 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"; -+ 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"; -+ }; -+ -+ 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; -+ }; -+ -+ 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>; -+ }; -+ }; -+ }; -+}; -+ -+&iwdg2 { -+ timeout-sec = <32>; -+ secure-timeout-sec = <5>; -+ status = "okay"; -+ 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_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; -+ 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>; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart4_pins_a>; -+ status = "okay"; -+}; -+ -+&usbotg_hs { -+ vbus-supply = <&vbus_otg>; -+}; -+ -+&usbphyc_port0 { -+ phy-supply = <&vdd_usb>; -+}; -+ -+&usbphyc_port1 { -+ phy-supply = <&vdd_usb>; -+}; -+ -+/* Low-power states of regulators */ -+&v1v8 { -+ 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; -+ }; -+}; -+ -+&v3v3 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdd { -+ 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; -+ }; -+}; -+ -+&vdda { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vddcore { -+ 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 { -+ 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_sd { -+ 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; -+ }; -+}; -+ -+&vref_ddr { -+ 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; -+ }; -+}; -+ -+&vtt_ddr { -+ 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; -+ }; -+}; -diff --git a/fdts/stm32mp15xx-evx.dtsi b/fdts/stm32mp15xx-evx.dtsi -new file mode 100644 -index 0000000000..ce1982d45a ---- /dev/null -+++ b/fdts/stm32mp15xx-evx.dtsi -@@ -0,0 +1,73 @@ -+// 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"; -+ -+ nand-controller@4,0 { -+ status = "okay"; -+ -+ nand@0 { -+ reg = <0>; -+ nand-on-flash-bbt; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+ }; -+}; -+ -+&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>; -+ 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>; -+ }; -+}; -+ -+&timers12 { -+ status = "disabled"; -+}; -+ -+&usart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usart3_pins_b>; -+ 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 -index 64e566bf82..4f4130effd 100644 ---- a/fdts/stm32mp15xxaa-pinctrl.dtsi -+++ b/fdts/stm32mp15xxaa-pinctrl.dtsi -@@ -1,7 +1,7 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* - * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -+ * Author: Alexandre Torgue for STMicroelectronics. - */ - - &pinctrl { -@@ -79,6 +79,7 @@ - - gpioz: gpio@54004000 { - status = "okay"; -+ secure-status = "okay"; - ngpios = <8>; - gpio-ranges = <&pinctrl_z 0 400 8>; - }; -diff --git a/fdts/stm32mp15xxab-pinctrl.dtsi b/fdts/stm32mp15xxab-pinctrl.dtsi -index d29af8986f..328dad140e 100644 ---- a/fdts/stm32mp15xxab-pinctrl.dtsi -+++ b/fdts/stm32mp15xxab-pinctrl.dtsi -@@ -1,7 +1,7 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* - * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -+ * Author: Alexandre Torgue for STMicroelectronics. - */ - - &pinctrl { -diff --git a/fdts/stm32mp15xxac-pinctrl.dtsi b/fdts/stm32mp15xxac-pinctrl.dtsi -index 5d8199fd19..866c050daf 100644 ---- a/fdts/stm32mp15xxac-pinctrl.dtsi -+++ b/fdts/stm32mp15xxac-pinctrl.dtsi -@@ -1,7 +1,7 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* - * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -+ * Author: Alexandre Torgue for STMicroelectronics. - */ - - &pinctrl { -@@ -67,6 +67,7 @@ - - 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 -index 023f5404c4..b63e207de2 100644 ---- a/fdts/stm32mp15xxad-pinctrl.dtsi -+++ b/fdts/stm32mp15xxad-pinctrl.dtsi -@@ -1,7 +1,7 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* - * Copyright (C) STMicroelectronics 2019 - All Rights Reserved -- * Author: Alexandre Torgue -+ * Author: Alexandre Torgue for STMicroelectronics. - */ - - &pinctrl { -diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h -index db8938ff1f..9cf8c8ee80 100644 ---- a/include/arch/aarch32/arch.h -+++ b/include/arch/aarch32/arch.h -@@ -461,13 +461,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 -@@ -526,6 +526,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 -@@ -535,6 +538,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 - -@@ -585,6 +589,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 - ******************************************************************************/ -@@ -638,6 +648,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 82efb188a4..9998034396 100644 ---- a/include/arch/aarch32/arch_helpers.h -+++ b/include/arch/aarch32/arch_helpers.h -@@ -248,6 +248,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) -@@ -290,6 +293,7 @@ DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) - * Address translation - */ - 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) - -diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S -index 4fd746d5a4..6bbcde2e0a 100644 ---- a/include/arch/aarch32/el3_common_macros.S -+++ b/include/arch/aarch32/el3_common_macros.S -@@ -10,6 +10,9 @@ - #include - #include - #include -+#include -+ -+#define PAGE_START_MASK ~(PAGE_SIZE_MASK) - - /* - * Helper macro to initialise EL3 registers we care about. -@@ -199,11 +202,18 @@ - * - * _exception_vectors: - * Address of the exception vectors to program in the VBAR_EL3 register. -+ * -+ * _pie_fixup_size: -+ * Size of memory region to fixup Global Descriptor Table (GDT). -+ * -+ * A non-zero value is expected when firmware needs GDT to be fixed-up. -+ * - * ----------------------------------------------------------------------------- - */ - .macro el3_entrypoint_common \ - _init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \ -- _init_memory, _init_c_runtime, _exception_vectors -+ _init_memory, _init_c_runtime, _exception_vectors, \ -+ _pie_fixup_size - - /* Make sure we are in Secure Mode */ - #if ENABLE_ASSERTIONS -@@ -255,6 +265,27 @@ - bxne r0 - .endif /* _warm_boot_mailbox */ - -+ .if \_pie_fixup_size -+#if ENABLE_PIE -+ /* -+ * ------------------------------------------------------------ -+ * If PIE is enabled fixup the Global descriptor Table only -+ * once during primary core cold boot path. -+ * -+ * Compile time base address, required for fixup, is calculated -+ * using "pie_fixup" label present within first page. -+ * ------------------------------------------------------------ -+ */ -+ pie_fixup: -+ ldr r0, =pie_fixup -+ ldr r1, =PAGE_START_MASK -+ and r0, r0, r1 -+ mov_imm r1, \_pie_fixup_size -+ add r1, r1, r0 -+ bl fixup_gdt_reloc -+#endif /* ENABLE_PIE */ -+ .endif /* _pie_fixup_size */ -+ - /* --------------------------------------------------------------------- - * Set the exception vectors (VBAR/MVBAR). - * --------------------------------------------------------------------- -@@ -335,12 +366,14 @@ - */ - mov r7, r12 - ldr r0, =__BSS_START__ -- ldr r1, =__BSS_SIZE__ -+ ldr r1, =__BSS_END__ -+ sub r1, r1, r0 - bl zeromem - - #if USE_COHERENT_MEM - ldr r0, =__COHERENT_RAM_START__ -- ldr r1, =__COHERENT_RAM_UNALIGNED_SIZE__ -+ ldr r1, =__COHERENT_RAM_END_UNALIGNED__ -+ sub r1, r1, r0 - bl zeromem - #endif - -@@ -354,7 +387,8 @@ - */ - ldr r0, =__DATA_RAM_START__ - ldr r1, =__DATA_ROM_START__ -- ldr r2, =__DATA_SIZE__ -+ ldr r2, =__DATA_RAM_END__ -+ sub r2, r2, r0 - bl memcpy4 - #endif - .endif /* _init_c_runtime */ -diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h -index 33e1134dd5..f50a5a57c3 100644 ---- a/include/arch/aarch64/arch.h -+++ b/include/arch/aarch64/arch.h -@@ -735,13 +735,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/bl_common.ld.h b/include/common/bl_common.ld.h -index ab3391aa21..cb71d9aea8 100644 ---- a/include/common/bl_common.ld.h -+++ b/include/common/bl_common.ld.h -@@ -105,12 +105,21 @@ - * .rela.dyn needs to come after .data for the read-elf utility to parse - * this section correctly. - */ -+#if __aarch64__ - #define RELA_SECTION \ - .rela.dyn : ALIGN(STRUCT_ALIGN) { \ - __RELA_START__ = .; \ - *(.rela*) \ - __RELA_END__ = .; \ - } -+#else -+#define RELA_SECTION \ -+ .rel.dyn : ALIGN(STRUCT_ALIGN) { \ -+ __RELA_START__ = .; \ -+ *(.rel*) \ -+ __RELA_END__ = .; \ -+ } -+#endif - - #if !(defined(IMAGE_BL31) && RECLAIM_INIT_CODE) - #define STACK_SECTION \ -diff --git a/include/common/tbbr/cot_def.h b/include/common/tbbr/cot_def.h -index 6ce7f80c17..0d2d9acfe5 100644 ---- a/include/common/tbbr/cot_def.h -+++ b/include/common/tbbr/cot_def.h -@@ -35,7 +35,7 @@ - #error "Invalid value for TF_MBEDTLS_KEY_SIZE" - #endif - #else /* Only using ECDSA keys. */ --#define PK_DER_LEN 91 -+#define PK_DER_LEN 92 - #endif - - #if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256 -diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h -index 32aeb03502..88c9237cf1 100644 ---- a/include/drivers/arm/tzc400.h -+++ b/include/drivers/arm/tzc400.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -32,7 +32,6 @@ - #define BUILD_CONFIG_AW_MASK U(0x3f) - #define BUILD_CONFIG_NR_SHIFT 0 - #define BUILD_CONFIG_NR_MASK U(0x1f) -- - /* - * Number of gate keepers is implementation defined. But we know the max for - * this device is 4. Get implementation details from BUILD_CONFIG. -@@ -65,8 +64,8 @@ - #define FAIL_CONTROL_NS_SECURE U(0) - #define FAIL_CONTROL_NS_NONSECURE U(1) - #define FAIL_CONTROL_PRIV_SHIFT 20 --#define FAIL_CONTROL_PRIV_PRIV U(0) --#define FAIL_CONTROL_PRIV_UNPRIV U(1) -+#define FAIL_CONTROL_PRIV_UNPRIV U(0) -+#define FAIL_CONTROL_PRIV_PRIV U(1) - - /* - * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific. -@@ -93,6 +92,8 @@ - #define TZC_400_REGION_SIZE U(0x20) - #define TZC_400_ACTION_OFF U(0x4) - -+#define FILTER_OFFSET U(0x10) -+ - #ifndef __ASSEMBLER__ - - #include -@@ -103,39 +104,39 @@ - ******************************************************************************/ - 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_update_filters(unsigned int region, unsigned int filters); - void tzc400_set_action(unsigned int action); - void tzc400_enable_filters(void); - void tzc400_disable_filters(void); -+void tzc400_it_handler(void); - - 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 +144,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/auth/tbbr_cot_common.h b/include/drivers/auth/tbbr_cot_common.h -index a51faee1aa..21bcd520a4 100644 ---- a/include/drivers/auth/tbbr_cot_common.h -+++ b/include/drivers/auth/tbbr_cot_common.h -@@ -25,5 +25,6 @@ extern auth_param_type_desc_t fw_config_hash; - - extern const auth_img_desc_t trusted_boot_fw_cert; - extern const auth_img_desc_t hw_config; -+extern const auth_img_desc_t fw_config; - - #endif /* TBBR_COT_COMMON_H */ -diff --git a/include/drivers/clk.h b/include/drivers/clk.h -new file mode 100644 -index 0000000000..960dce742a ---- /dev/null -+++ b/include/drivers/clk.h -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CLK_H -+#define CLK_H -+ -+#include -+ -+typedef struct clk_ops { -+ int (*enable)(unsigned long id); -+ void (*disable)(unsigned long id); -+ unsigned long (*get_rate)(unsigned long id); -+ int (*get_parent)(unsigned long id); -+ bool (*is_enabled)(unsigned long id); -+} clk_ops_t; -+ -+int clk_enable(unsigned long id); -+void clk_disable(unsigned long id); -+unsigned long clk_get_rate(unsigned long id); -+bool clk_is_enabled(unsigned long id); -+int clk_get_parent(unsigned long id); -+ -+void clk_register(const clk_ops_t *ops); -+ -+#endif /* CLK_H */ -diff --git a/include/drivers/io/io_mtd.h b/include/drivers/io/io_mtd.h -index 1395ff6019..b2c90205d4 100644 ---- a/include/drivers/io/io_mtd.h -+++ b/include/drivers/io/io_mtd.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -44,11 +44,22 @@ typedef struct io_mtd_ops { - * Return 0 on success, a negative error code otherwise. - */ - int (*write)(unsigned int offset, uintptr_t buffer, size_t length); -+ -+ /* -+ * Look for an offset to be added to the given offset. -+ * -+ * @base: Base address of the area. -+ * @offset: Offset in bytes to start read operation. -+ * @extra_offset: [out] Offset to be added to the previous offset. -+ * Return 0 on success, a negative error code otherwise. -+ */ -+ int (*seek)(uintptr_t base, unsigned int offset, size_t *extra_offset); - } io_mtd_ops_t; - - typedef struct io_mtd_dev_spec { - unsigned long long device_size; - unsigned int erase_size; -+ size_t offset; - io_mtd_ops_t ops; - } io_mtd_dev_spec_t; - -diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h -index 7611f019a1..2b4f5ab8b3 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 -index 1dbb008f9c..862e1792a4 100644 ---- a/include/drivers/nand.h -+++ b/include/drivers/nand.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -45,6 +45,16 @@ struct nand_device { - int nand_read(unsigned int offset, uintptr_t buffer, size_t length, - size_t *length_read); - -+/* -+ * Look for an extra offset to be added in case of bad blocks -+ * -+ * @base: Base address of the area -+ * @offset: Byte offset to read from in device -+ * @extra_offset: [out] Extra offset to be added if bad blocks are found -+ * Return: 0 on success, a negative errno on failure -+ */ -+int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset); -+ - /* - * Get NAND device instance - * -diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h -index d833e7ab27..273a4e98ac 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-2020, 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 -- --/* -- * BSEC_OTP_LOCK register -- */ --#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 -+#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_STATUS Register -+ * OTP MODE - */ --#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,16 +96,20 @@ 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); - 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); -+void 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); -+ -+void bsec_write_scratch(uint32_t val); -+uint32_t bsec_read_scratch(void); - - uint32_t bsec_get_status(void); - uint32_t bsec_get_hw_conf(void); -@@ -190,14 +117,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 0000000000..9da9526031 ---- /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) -+#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) -+ -+/* 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_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 0 -+#define BSEC_WRITE BIT(8) -+#define BSEC_LOCK BIT(9) -+ -+/* BSEC_OTP_LOCK register */ -+#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) -+ -+/* 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) -+ -+/* BSEC_IPVR Register */ -+#define BSEC_IPVR_MSK GENMASK(7, 0) -+ -+#endif /* BSEC2_REG_H */ -diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h -index 170d4cf815..e1a3782b2e 100644 ---- a/include/drivers/st/stm32_i2c.h -+++ b/include/drivers/st/stm32_i2c.h -@@ -1,7 +1,7 @@ - /* - * 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 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) -+#define I2C_TIMINGR_SCLL_MAX (I2C_TIMINGR_SCLL + 1) -+#define I2C_TIMINGR_SCLH_MAX ((I2C_TIMINGR_SCLH >> 8) + 1) -+#define I2C_TIMINGR_SDADEL_MAX ((I2C_TIMINGR_SDADEL >> 16) + 1) -+#define I2C_TIMINGR_SCLDEL_MAX ((I2C_TIMINGR_SCLDEL >> 20) + 1) -+#define I2C_TIMINGR_PRESC_MAX ((I2C_TIMINGR_PRESC >> 28) + 1) -+#define I2C_SET_TIMINGR_SCLL(n) ((n) & \ -+ (I2C_TIMINGR_SCLL_MAX - 1)) -+#define I2C_SET_TIMINGR_SCLH(n) (((n) & \ -+ (I2C_TIMINGR_SCLH_MAX - 1)) << 8) -+#define I2C_SET_TIMINGR_SDADEL(n) (((n) & \ -+ (I2C_TIMINGR_SDADEL_MAX - 1)) << 16) -+#define I2C_SET_TIMINGR_SCLDEL(n) (((n) & \ -+ (I2C_TIMINGR_SCLDEL_MAX - 1)) << 20) -+#define I2C_SET_TIMINGR_PRESC(n) (((n) & \ -+ (I2C_TIMINGR_PRESC_MAX - 1)) << 28) - - /* Bit definition for I2C_TIMEOUTR register */ - #define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0) -@@ -111,15 +126,9 @@ - #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 -+#define STANDARD_RATE 100000 -+#define FAST_RATE 400000 -+#define FAST_PLUS_RATE 1000000 - - 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 */ - }; - - #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 - --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_iwdg.h b/include/drivers/st/stm32_iwdg.h -index bad25244a8..c0c009779e 100644 ---- a/include/drivers/st/stm32_iwdg.h -+++ b/include/drivers/st/stm32_iwdg.h -@@ -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_rng.h b/include/drivers/st/stm32_rng.h -new file mode 100644 -index 0000000000..a644118656 ---- /dev/null -+++ b/include/drivers/st/stm32_rng.h -@@ -0,0 +1,13 @@ -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_RNG_H -+#define STM32_RNG_H -+ -+int stm32_rng_read(uint8_t *out, uint32_t size); -+int stm32_rng_init(void); -+ -+#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 0000000000..128dd2d14a ---- /dev/null -+++ b/include/drivers/st/stm32_rtc.h -@@ -0,0 +1,78 @@ -+/* -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_RTC_H -+#define STM32_RTC_H -+ -+#include -+ -+#define RTC_TR 0x00U -+#define RTC_DR 0x04U -+#define RTC_SSR 0x08U -+#define RTC_ICSR 0x0CU -+#define RTC_PRER 0x10U -+#define RTC_WUTR 0x14U -+#define RTC_CR 0x18U -+#define RTC_SMCR 0x20U -+#define RTC_WPR 0x24U -+#define RTC_CALR 0x28U -+#define RTC_SHIFTR 0x2CU -+#define RTC_TSTR 0x30U -+#define RTC_TSDR 0x34U -+#define RTC_TSSSR 0x38U -+#define RTC_ALRMAR 0x40U -+#define RTC_ALRMASSR 0x44U -+#define RTC_ALRMBR 0x48U -+#define RTC_ALRMBSSR 0x4CU -+#define RTC_SR 0x50U -+#define RTC_SCR 0x5CU -+#define RTC_OR 0x60U -+ -+struct stm32_rtc_calendar { -+ uint32_t ssr; -+ uint32_t tr; -+ uint32_t dr; -+}; -+ -+enum months { -+ JANUARY = 1, -+ FEBRUARY, -+ MARCH, -+ APRIL, -+ MAY, -+ JUNE, -+ JULY, -+ AUGUST, -+ SEPTEMBER, -+ OCTOBER, -+ NOVEMBER, -+ DECEMBER, -+ NB_MONTHS = 12 -+}; -+ -+struct stm32_rtc_time { -+ uint32_t hour; -+ uint32_t min; -+ uint32_t sec; -+ uint32_t wday; -+ uint32_t day; -+ enum months month; -+ uint32_t year; -+}; -+ -+void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar); -+unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *current, -+ struct stm32_rtc_calendar *ref); -+void stm32_rtc_set_tamper_timestamp(void); -+bool stm32_rtc_is_timestamp_enable(void); -+void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts); -+int stm32_rtc_init(void); -+ -+/* SMP protection on RTC registers access */ -+void stm32_rtc_regs_lock(void); -+void stm32_rtc_regs_unlock(void); -+ -+#endif /* STM32_RTC_H */ -diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h -index 4853208c2b..5b4bd0e167 100644 ---- a/include/drivers/st/stm32_sdmmc2.h -+++ b/include/drivers/st/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 0000000000..424cbb205a ---- /dev/null -+++ b/include/drivers/st/stm32_tamp.h -@@ -0,0 +1,163 @@ -+/* -+ * Copyright (c) 2014-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_TAMP_H -+#define STM32_TAMP_H -+ -+/* Internal Tamper */ -+enum stm32_tamp_int_id { -+ ITAMP1 = 0, -+ ITAMP2, -+ ITAMP3, -+ ITAMP4, -+ ITAMP5, -+ ITAMP6, -+ ITAMP7, -+ ITAMP8, -+ ITAMP9, -+ ITAMP10, -+ ITAMP11, -+ ITAMP12, -+ ITAMP13, -+ ITAMP14, -+ ITAMP15, -+ ITAMP16 -+}; -+ -+/* External Tamper */ -+enum stm32_tamp_ext_id { -+ EXT_TAMP1 = 0, -+ EXT_TAMP2, -+ EXT_TAMP3, -+ EXT_TAMP4, -+ EXT_TAMP5, -+ EXT_TAMP6, -+ EXT_TAMP7, -+ EXT_TAMP8 -+}; -+ -+enum stm32_tamp_state { -+ TAMP_DISABLE = 0, -+ TAMP_ENABLE -+}; -+ -+#define TAMP_UNUSED {.id = -1} -+ -+/* define TAMPER modes */ -+#define TAMP_TRIG_OFF 0x0U -+#define TAMP_TRIG_ON 0x1U -+#define TAMP_ACTIVE 0x2U -+#define TAMP_ERASE 0x0U -+#define TAMP_NOERASE 0x1U -+#define TAMP_NO_EVT_MASK 0x0U -+#define TAMP_EVT_MASK 0x1U -+ -+/* define Passive FILTER mode */ -+#define TAMP_FILTER_PRECHARGE 0x0U -+#define TAMP_FILTER_PULL_UP_DISABLE 0x1U -+#define TAMP_FILTER_DURATION_1_CYCLE 0x0U -+#define TAMP_FILTER_DURATION_2_CYCLES 0x1U -+#define TAMP_FILTER_DURATION_3_CYCLES 0x2U -+#define TAMP_FILTER_DURATION_4_CYCLES 0x3U -+#define TAMP_FILTER_COUNT_1 0x0U -+#define TAMP_FILTER_COUNT_2 0x1U -+#define TAMP_FILTER_COUNT_4 0x2U -+#define TAMP_FILTER_COUNT_8 0x3U -+#define TAMP_FILTER_SAMPLING_32768 0x0U -+#define TAMP_FILTER_SAMPLING_16384 0x1U -+#define TAMP_FILTER_SAMPLING_8192 0x2U -+#define TAMP_FILTER_SAMPLING_4096 0x3U -+#define TAMP_FILTER_SAMPLING_2048 0x4U -+#define TAMP_FILTER_SAMPLING_1024 0x5U -+#define TAMP_FILTER_SAMPLING_512 0x6U -+#define TAMP_FILTER_SAMPLING_256 0x7U -+ -+/* define active filter */ -+#define TAMP_ACTIVE_FILTER_OFF 0x0U -+#define TAMP_ACTIVE_FILTER_ON 0x1U -+#define TAMP_ACTIVE_ATO_DEDICATED 0x0U -+#define TAMP_ACTIVE_ATO_TAMPOUTSEL 0x1U -+#define TAMP_ACTIVE_APER_1_OUTPUT 0x0U -+#define TAMP_ACTIVE_APER_2_OUTPUTS 0x1U -+#define TAMP_ACTIVE_APER_3_4_OUTPUTS 0x2U -+#define TAMP_ACTIVE_APER_5_OUTPUTS 0x3U -+#define TAMP_ACTIVE_CKSEL_DIV_0 0x0U -+#define TAMP_ACTIVE_CKSEL_DIV_2 0x1U -+#define TAMP_ACTIVE_CKSEL_DIV_4 0x2U -+#define TAMP_ACTIVE_CKSEL_DIV_8 0x3U -+#define TAMP_ACTIVE_CKSEL_DIV_16 0x4U -+#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_EXT(tamp_id, trig, erase, mask) (((tamp_id) << 3) | ((trig) << 2)\ -+ | ((erase) << 1) | (mask)) -+ -+#define TAMP_FLTCR(precharge, duration, count, sample) (((precharge) << 7) |\ -+ ((duration) << 5) |\ -+ ((count) << 3) |\ -+ (sample)) -+ -+#define TAMP_ACT(filter, ato, aper, atcksel, atosel) (((filter) << 31) |\ -+ ((ato) << 30) |\ -+ ((aper) << 24) |\ -+ ((atcksel) << 16) |\ -+ (atosel) << 8) -+ -+struct stm32_tamp_int { -+ int id; -+ void (*func)(int id); -+}; -+ -+struct stm32_tamp_ext { -+ int id; -+ uint8_t mode; -+ uint8_t erase; -+ uint8_t evt_mask; -+ void (*func)(int id); -+}; -+ -+/* -+ * stm32_tamp_write_mcounter : Increase monotonic counter -+ */ -+void stm32_tamp_write_mcounter(void); -+ -+/* -+ * stm32_tamp_it_handler : Interrupt handler -+ */ -+void stm32_tamp_it_handler(void); -+ -+/* -+ * stm32_tamp_configure_internal: Configure internal tamper -+ * tamper_list: List of tamper to enable -+ * nb_tamper: Number of tamper in list -+ */ -+void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list, -+ uint16_t nb_tamper); -+ -+/* -+ * stm32_tamp_configure_external: Configure external tamper and associated -+ * configuration for filtering -+ * ext_tamp_list: List of external tamper to configure -+ * nb_tamper: Number of tamper in list -+ * passive_conf: Filter configuration -+ * active_conf: Configuration for active tamper -+ */ -+void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list, -+ uint8_t nb_tamper, uint32_t passive_conf, -+ uint32_t active_conf); -+ -+/* -+ * stm32_tamp_init: Initialize tamper from DT -+ * return 0 if disabled, 1 if enabled, else < 0 -+ */ -+int stm32_tamp_init(void); -+ -+#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 0000000000..0e2eb91fe9 ---- /dev/null -+++ b/include/drivers/st/stm32_timer.h -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_TIMER_H -+#define STM32_TIMER_H -+ -+enum timer_cal { -+ HSI_CAL = 0, -+ CSI_CAL -+}; -+ -+unsigned long stm32_timer_hsi_freq(void); -+unsigned long stm32_timer_csi_freq(void); -+void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void), -+ enum timer_cal type); -+int stm32_timer_init(void); -+ -+#endif /* STM32_TIMER_H */ -diff --git a/include/drivers/st/stm32_uart.h b/include/drivers/st/stm32_uart.h -new file mode 100644 -index 0000000000..f00da852fe ---- /dev/null -+++ b/include/drivers/st/stm32_uart.h -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32_UART_H -+#define STM32_UART_H -+ -+/* UART word length */ -+#define STM32_UART_WORDLENGTH_7B USART_CR1_M1 -+#define STM32_UART_WORDLENGTH_8B 0x00000000U -+#define STM32_UART_WORDLENGTH_9B USART_CR1_M0 -+ -+/* UART number of stop bits */ -+#define STM32_UART_STOPBITS_0_5 USART_CR2_STOP_0 -+#define STM32_UART_STOPBITS_1 0x00000000U -+#define STM32_UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) -+#define STM32_UART_STOPBITS_2 USART_CR2_STOP_1 -+ -+/* UART parity */ -+#define STM32_UART_PARITY_NONE 0x00000000U -+#define STM32_UART_PARITY_EVEN USART_CR1_PCE -+#define STM32_UART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) -+ -+/* UART transfer mode */ -+#define STM32_UART_MODE_RX USART_CR1_RE -+#define STM32_UART_MODE_TX USART_CR1_TE -+#define STM32_UART_MODE_TX_RX (USART_CR1_TE | USART_CR1_RE) -+ -+/* UART hardware flow control */ -+#define STM32_UART_HWCONTROL_NONE 0x00000000U -+#define STM32_UART_HWCONTROL_RTS USART_CR3_RTSE -+#define STM32_UART_HWCONTROL_CTS USART_CR3_CTSE -+#define STM32_UART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) -+ -+/* UART over sampling */ -+#define STM32_UART_OVERSAMPLING_16 0x00000000U -+#define STM32_UART_OVERSAMPLING_8 USART_CR1_OVER8 -+ -+/* UART prescaler */ -+#define STM32_UART_PRESCALER_DIV1 0x00000000U -+#define STM32_UART_PRESCALER_DIV2 0x00000001U -+#define STM32_UART_PRESCALER_DIV4 0x00000002U -+#define STM32_UART_PRESCALER_DIV6 0x00000003U -+#define STM32_UART_PRESCALER_DIV8 0x00000004U -+#define STM32_UART_PRESCALER_DIV10 0x00000005U -+#define STM32_UART_PRESCALER_DIV12 0x00000006U -+#define STM32_UART_PRESCALER_DIV16 0x00000007U -+#define STM32_UART_PRESCALER_DIV32 0x00000008U -+#define STM32_UART_PRESCALER_DIV64 0x00000009U -+#define STM32_UART_PRESCALER_DIV128 0x0000000AU -+#define STM32_UART_PRESCALER_DIV256 0x0000000BU -+#define STM32_UART_PRESCALER_MAX STM32_UART_PRESCALER_DIV256 -+ -+/* UART fifo mode */ -+#define STM32_UART_FIFOMODE_EN USART_CR1_FIFOEN -+#define STM32_UART_FIFOMODE_DIS 0x00000000U -+ -+/* UART TXFIFO threshold level */ -+#define STM32_UART_TXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U -+#define STM32_UART_TXFIFO_THRESHOLD_1QUARTERFUL USART_CR3_TXFTCFG_0 -+#define STM32_UART_TXFIFO_THRESHOLD_HALFFULL USART_CR3_TXFTCFG_1 -+#define STM32_UART_TXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_TXFTCFG_0 | USART_CR3_TXFTCFG_1) -+#define STM32_UART_TXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_TXFTCFG_2 -+#define STM32_UART_TXFIFO_THRESHOLD_EMPTY (USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0) -+ -+/* UART RXFIFO threshold level */ -+#define STM32_UART_RXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U -+#define STM32_UART_RXFIFO_THRESHOLD_1QUARTERFULL USART_CR3_RXFTCFG_0 -+#define STM32_UART_RXFIFO_THRESHOLD_HALFFULL USART_CR3_RXFTCFG_1 -+#define STM32_UART_RXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_RXFTCFG_0 | USART_CR3_RXFTCFG_1) -+#define STM32_UART_RXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_RXFTCFG_2 -+#define STM32_UART_RXFIFO_THRESHOLD_FULL (USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0) -+ -+struct stm32_uart_init_s { -+ uint32_t baud_rate; /* -+ * Configures the UART communication -+ * baud rate. -+ */ -+ -+ uint32_t word_length; /* -+ * Specifies the number of data bits -+ * transmitted or received in a frame. -+ * This parameter can be a value of -+ * @ref STM32_UART_WORDLENGTH_*. -+ */ -+ -+ uint32_t stop_bits; /* -+ * Specifies the number of stop bits -+ * transmitted. This parameter can be -+ * a value of @ref STM32_UART_STOPBITS_*. -+ */ -+ -+ uint32_t parity; /* -+ * Specifies the parity mode. -+ * This parameter can be a value of -+ * @ref STM32_UART_PARITY_*. -+ */ -+ -+ uint32_t mode; /* -+ * Specifies whether the receive or -+ * transmit mode is enabled or -+ * disabled. This parameter can be a -+ * value of @ref @ref STM32_UART_MODE_*. -+ */ -+ -+ uint32_t hw_flow_control; /* -+ * Specifies whether the hardware flow -+ * control mode is enabled or -+ * disabled. This parameter can be a -+ * value of @ref STM32_UARTHWCONTROL_*. -+ */ -+ -+ uint32_t over_sampling; /* -+ * Specifies whether the over sampling -+ * 8 is enabled or disabled. -+ * This parameter can be a value of -+ * @ref STM32_UART_OVERSAMPLING_*. -+ */ -+ -+ uint32_t one_bit_sampling; /* -+ * Specifies whether a single sample -+ * or three samples' majority vote is -+ * selected. This parameter can be 0 -+ * or USART_CR3_ONEBIT. -+ */ -+ -+ uint32_t prescaler; /* -+ * Specifies the prescaler value used -+ * to divide the UART clock source. -+ * This parameter can be a value of -+ * @ref STM32_UART_PRESCALER_*. -+ */ -+ -+ uint32_t fifo_mode; /* -+ * Specifies if the FIFO mode will be -+ * used. This parameter can be a value -+ * of @ref STM32_UART_FIFOMODE_*. -+ */ -+ -+ uint32_t tx_fifo_threshold; /* -+ * Specifies the TXFIFO threshold -+ * level. This parameter can be a -+ * value of @ref -+ * STM32_UART_TXFIFO_THRESHOLD_*. -+ */ -+ -+ uint32_t rx_fifo_threshold; /* -+ * Specifies the RXFIFO threshold -+ * level. This parameter can be a -+ * value of @ref -+ * STM32_UART_RXFIFO_THRESHOLD_*. -+ */ -+}; -+ -+struct stm32_uart_handle_s { -+ uint32_t base; -+ uint32_t rdr_mask; -+}; -+ -+int stm32_uart_init(struct stm32_uart_handle_s *huart, -+ uintptr_t base_addr, -+ const struct stm32_uart_init_s *init); -+void stm32_uart_stop(uintptr_t base_addr); -+int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c); -+int stm32_uart_flush(struct stm32_uart_handle_s *huart); -+int stm32_uart_getc(struct stm32_uart_handle_s *huart); -+ -+#endif /* STM32_UART_H */ -diff --git a/include/drivers/st/stm32mp1_calib.h b/include/drivers/st/stm32mp1_calib.h -new file mode 100644 -index 0000000000..ef69cb4563 ---- /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 c46892b78e..c62fb20784 100644 ---- a/include/drivers/st/stm32mp1_clk.h -+++ b/include/drivers/st/stm32mp1_clk.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 - */ -@@ -22,42 +22,44 @@ enum stm32mp_osc_id { - - extern const char *stm32mp_osc_node_label[NB_OSC]; - -+#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); - --void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); --void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); -+void stm32mp1_clk_force_enable(unsigned long id); -+void stm32mp1_clk_force_disable(unsigned long id); - --static inline void stm32mp1_clk_enable_non_secure(unsigned long id) --{ -- __stm32mp1_clk_enable(id, false); --} -+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); - --static inline void stm32mp1_clk_enable_secure(unsigned long id) --{ -- __stm32mp1_clk_enable(id, true); --} -+int stm32mp1_round_opp_khz(uint32_t *freq_khz); -+int stm32mp1_set_opp_khz(uint32_t freq_khz); - --static inline void stm32mp1_clk_disable_non_secure(unsigned long id) --{ -- __stm32mp1_clk_disable(id, false); --} -+void stm32mp1_clock_suspend(void); -+void stm32mp1_clock_resume(void); - --static inline void stm32mp1_clk_disable_secure(unsigned long id) --{ -- __stm32mp1_clk_disable(id, true); --} -+void stm32mp1_clock_stopmode_save(void); -+int stm32mp1_clock_stopmode_resume(void); - --unsigned int stm32mp1_clk_get_refcount(unsigned long id); -+void restore_clock_pm_context(void); -+void save_clock_pm_context(void); - --/* SMP protection on RCC registers access */ --void stm32mp1_clk_rcc_regs_lock(void); --void stm32mp1_clk_rcc_regs_unlock(void); -+void stm32mp1_clk_mcuss_protect(bool enable); - --void stm32mp1_stgen_increment(unsigned long long offset_in_ms); -+void stm32mp1_dump_clocks_state(void); - - #ifdef STM32MP_SHARED_RESOURCES - void stm32mp1_register_clock_parents_secure(unsigned long id); -diff --git a/include/drivers/st/stm32mp1_ddr.h b/include/drivers/st/stm32mp1_ddr.h -index 4ab37d6b44..245ad52cc2 100644 ---- a/include/drivers/st/stm32mp1_ddr.h -+++ b/include/drivers/st/stm32mp1_ddr.h -@@ -8,9 +8,6 @@ - #define STM32MP1_DDR_H - - #include --#include -- --#define DT_DDR_COMPAT "st,stm32mp1-ddr" - - struct stm32mp1_ddr_size { - uint64_t base; -@@ -101,12 +98,14 @@ struct stm32mp1_ddrctrl_perf { - uint32_t pcfgqos1_0; - uint32_t pcfgwqos0_0; - uint32_t pcfgwqos1_0; -+#if STM32MP_DDR_DUAL_AXI_PORT - uint32_t pcfgr_1; - uint32_t pcfgw_1; - uint32_t pcfgqos0_1; - uint32_t pcfgqos1_1; - uint32_t pcfgwqos0_1; - uint32_t pcfgwqos1_1; -+#endif - }; - - struct stm32mp1_ddrphy_reg { -@@ -119,8 +118,10 @@ struct stm32mp1_ddrphy_reg { - uint32_t zq0cr1; - uint32_t dx0gcr; - uint32_t dx1gcr; -+#if STM32MP_DDR_DUAL_AXI_PORT - uint32_t dx2gcr; - uint32_t dx3gcr; -+#endif - }; - - struct stm32mp1_ddrphy_timing { -@@ -143,12 +144,14 @@ struct stm32mp1_ddrphy_cal { - uint32_t dx1dllcr; - uint32_t dx1dqtr; - uint32_t dx1dqstr; -+#if STM32MP_DDR_DUAL_AXI_PORT - uint32_t dx2dllcr; - uint32_t dx2dqtr; - uint32_t dx2dqstr; - uint32_t dx3dllcr; - uint32_t dx3dqtr; - uint32_t dx3dqstr; -+#endif - }; - - struct stm32mp1_ddr_info { -@@ -166,9 +169,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, uint32_t mem_speed); - void stm32mp1_ddr_init(struct ddr_info *priv, - struct stm32mp1_ddr_config *config); -+ - #endif /* STM32MP1_DDR_H */ -diff --git a/include/drivers/st/stm32mp1_ddr_helpers.h b/include/drivers/st/stm32mp1_ddr_helpers.h -index 38f24152a9..f09f05d555 100644 ---- a/include/drivers/st/stm32mp1_ddr_helpers.h -+++ b/include/drivers/st/stm32mp1_ddr_helpers.h -@@ -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,24 @@ - #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); -+uint32_t ddr_get_io_calibration_val(void); -+int ddr_standby_sr_entry(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 */ -diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h -index 342239a52d..e298fcf77b 100644 ---- a/include/drivers/st/stm32mp1_ddr_regs.h -+++ b/include/drivers/st/stm32mp1_ddr_regs.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -128,6 +128,7 @@ struct stm32mp1_ddrctl { - uint32_t pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1 */ - uint8_t reserved4a4[0x4b4 - 0x4a4]; - -+#if STM32MP_DDR_DUAL_AXI_PORT - /* PORT 1 */ - uint32_t pcfgr_1; /* 0x4b4 Configuration Read */ - uint32_t pcfgw_1; /* 0x4b8 Configuration Write */ -@@ -137,6 +138,7 @@ struct stm32mp1_ddrctl { - uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */ - uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */ - uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */ -+#endif - } __packed; - - /* DDR Physical Interface Control (DDRPHYC) registers*/ -@@ -214,6 +216,7 @@ struct stm32mp1_ddrphy { - uint32_t dx1dqtr; /* 0x210 Byte lane 1 DQ Timing */ - uint32_t dx1dqstr; /* 0x214 Byte lane 1 QS Timing */ - uint8_t res6[0x240 - 0x218]; /* 0x218 */ -+#if STM32MP_DDR_DUAL_AXI_PORT - uint32_t dx2gcr; /* 0x240 Byte lane 2 General Configuration */ - uint32_t dx2gsr0; /* 0x244 Byte lane 2 General Status 0 */ - uint32_t dx2gsr1; /* 0x248 Byte lane 2 General Status 1 */ -@@ -227,6 +230,7 @@ struct stm32mp1_ddrphy { - uint32_t dx3dllcr; /* 0x28c Byte lane 3 DLL Control */ - uint32_t dx3dqtr; /* 0x290 Byte lane 3 DQ Timing */ - uint32_t dx3dqstr; /* 0x294 Byte lane 3 QS Timing */ -+#endif - } __packed; - - /* DDR Controller registers offsets */ -@@ -249,7 +253,9 @@ struct stm32mp1_ddrphy { - #define DDRCTRL_SWSTAT 0x324 - #define DDRCTRL_PSTAT 0x3FC - #define DDRCTRL_PCTRL_0 0x490 -+#if STM32MP_DDR_DUAL_AXI_PORT - #define DDRCTRL_PCTRL_1 0x540 -+#endif - - /* DDR Controller Register fields */ - #define DDRCTRL_MSTR_DDR3 BIT(0) -@@ -284,7 +290,7 @@ struct stm32mp1_ddrphy { - #define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) - #define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) - --#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(19, 12) -+#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16) - #define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) - - #define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) -@@ -339,10 +345,12 @@ struct stm32mp1_ddrphy { - #define DDRPHYC_DX0DLLCR 0x1CC - #define DDRPHYC_DX1GCR 0x200 - #define DDRPHYC_DX1DLLCR 0x20C -+#if STM32MP_DDR_DUAL_AXI_PORT - #define DDRPHYC_DX2GCR 0x240 - #define DDRPHYC_DX2DLLCR 0x24C - #define DDRPHYC_DX3GCR 0x280 - #define DDRPHYC_DX3DLLCR 0x28C -+#endif - - /* DDR PHY Register fields */ - #define DDRPHYC_PIR_INIT BIT(0) -@@ -380,6 +388,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) -@@ -399,6 +408,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/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h -index e17df44fb7..9b662f2d1c 100644 ---- a/include/drivers/st/stm32mp1_pwr.h -+++ b/include/drivers/st/stm32mp1_pwr.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 - */ -@@ -13,20 +13,39 @@ - #define PWR_CR2 U(0x08) - #define PWR_CR3 U(0x0C) - #define PWR_MPUCR U(0x10) -+#define PWR_MCUCR U(0x14) - #define PWR_WKUPCR U(0x20) - #define PWR_MPUWKUPENR U(0x28) - -+#define PWR_OFFSET_MASK GENMASK(9, 0) -+ - #define PWR_CR1_LPDS BIT(0) - #define PWR_CR1_LPCFG BIT(1) - #define PWR_CR1_LVDS BIT(2) - #define PWR_CR1_DBP BIT(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) - #define PWR_CR3_DDRSREN BIT(10) - #define PWR_CR3_DDRSRDIS BIT(11) - #define PWR_CR3_DDRRETEN BIT(12) -+#define PWR_CR3_USB33DEN BIT(24) -+#define PWR_CR3_REG18EN BIT(28) -+#define PWR_CR3_REG11EN BIT(30) - - #define PWR_MPUCR_PDDS BIT(0) - #define PWR_MPUCR_CSTDBYDIS BIT(3) - #define PWR_MPUCR_CSSF BIT(9) - -+#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) -+ - #endif /* STM32MP1_PWR_H */ -diff --git a/include/drivers/st/stm32mp1_ram.h b/include/drivers/st/stm32mp1_ram.h -index 38360e7595..adecd409df 100644 ---- a/include/drivers/st/stm32mp1_ram.h -+++ b/include/drivers/st/stm32mp1_ram.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -7,6 +7,7 @@ - #ifndef STM32MP1_RAM_H - #define STM32MP1_RAM_H - -+bool stm32mp1_ddr_is_restored(void); - int stm32mp1_ddr_probe(void); - - #endif /* STM32MP1_RAM_H */ -diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h -index 2ffc3b2bc2..feaac43a13 100644 ---- a/include/drivers/st/stm32mp1_rcc.h -+++ b/include/drivers/st/stm32mp1_rcc.h -@@ -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 - */ -@@ -394,7 +394,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 -@@ -453,12 +454,18 @@ - #define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) - #define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) - -+/* Global Control Register */ -+#define RCC_MP_GCR_BOOT_MCU BIT(0) -+ - /* Values of RCC_UART24CKSELR register */ - #define RCC_UART24CKSELR_HSI 0x00000002 - - /* Values of RCC_MP_APB1ENSETR register */ - #define RCC_MP_APB1ENSETR_UART4EN BIT(16) - -+/* Values of RCC_MP_APB4ENSETR register */ -+#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) -+ - /* Values of RCC_MP_APB5ENSETR register */ - #define RCC_MP_APB5ENSETR_SPI6EN BIT(0) - #define RCC_MP_APB5ENSETR_I2C4EN BIT(2) -@@ -466,8 +473,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) - - /* 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) - -@@ -477,6 +491,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) -@@ -562,4 +582,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/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h -index c7e0b6e6fb..1386fa6e29 100644 ---- a/include/drivers/st/stm32mp_clkfunc.h -+++ b/include/drivers/st/stm32mp_clkfunc.h -@@ -14,18 +14,29 @@ - #include - - int fdt_osc_read_freq(const char *name, uint32_t *freq); --bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name); --uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, -+bool fdt_clk_read_bool(const char *node_label, const char *prop_name); -+uint32_t fdt_clk_read_uint32_default(const char *node_label, - const char *prop_name, - uint32_t dflt_value); - --int fdt_get_rcc_node(void *fdt); - int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, - uint32_t *array); -+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); -+bool fdt_get_rcc_secure_state(void); -+int fdt_rcc_enable_it(const char *name); - - 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); -+ -+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 0000000000..6804192ba0 ---- /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 984cd60143..898a28b44c 100644 ---- a/include/drivers/st/stm32mp_pmic.h -+++ b/include/drivers/st/stm32mp_pmic.h -@@ -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); -+ -+/* -+ * dt_pmic_find_supply - Find the supply name related to a regulator name -+ * -+ * Returns 0 on success, and negative values on errors -+ */ -+int dt_pmic_find_supply(const char **supply_name, const char *regu_name); -+ -+/* -+ * 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); -+ -+#if DEBUG -+void print_pmic_info_and_debug(void); -+#else -+static inline void print_pmic_info_and_debug(void) -+{ -+} -+#endif -+ -+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 0000000000..7a66b97ba7 ---- /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 -index 84448050d7..8c43c0b5b1 100644 ---- a/include/drivers/st/stm32mp_reset.h -+++ b/include/drivers/st/stm32mp_reset.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 - */ -@@ -47,4 +47,16 @@ static inline void stm32mp_reset_release(uint32_t reset_id) - (void)stm32mp_reset_deassert(reset_id, 0U); - } - -+/* -+ * Manage reset control for the MCU reset -+ * -+ * @assert_not_deassert: reset requested state -+ */ -+void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert); -+ -+/* -+ * Manage system reset control -+ */ -+void __dead2 stm32mp_system_reset(void); -+ - #endif /* STM32MP_RESET_H */ -diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h -index f7e293b189..5c8933d84d 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) -@@ -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); -diff --git a/include/drivers/st/usb_dwc2.h b/include/drivers/st/usb_dwc2.h -new file mode 100644 -index 0000000000..58a0e4b6e5 ---- /dev/null -+++ b/include/drivers/st/usb_dwc2.h -@@ -0,0 +1,19 @@ -+/* -+ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef USB_DWC2_H -+#define USB_DWC2_H -+ -+#include -+ -+#define USB_MAX_ENDPOINT_NB 0x10 -+ -+void usb_dwc2_init_driver(usb_handle_t *usb_core_handle, -+ pcd_handle_t *pcd_handle, -+ void *base_register); -+ -+#endif /* USB_DWC2_H */ -+ -diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h -index 67e66b23fd..cfda43310b 100644 ---- a/include/dt-bindings/clock/stm32mp1-clks.h -+++ b/include/dt-bindings/clock/stm32mp1-clks.h -@@ -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 -+ - /* PLL */ - #define PLL1 176 - #define PLL2 177 -diff --git a/include/dt-bindings/power/stm32mp1-power.h b/include/dt-bindings/power/stm32mp1-power.h -new file mode 100644 -index 0000000000..d588dd71f3 ---- /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) 2018-2019, STMicroelectronics - All Rights Reserved -+ * Author: Yann Gautier for STMicroelectronics. -+ */ -+ -+#ifndef DT_BINDINGS_STM32MP1_POWER_H -+#define DT_BINDINGS_STM32MP1_POWER_H -+ -+#define STM32_PM_CSLEEP_RUN 0 -+#define STM32_PM_CSTOP_ALLOW_STOP 1 -+#define STM32_PM_CSTOP_ALLOW_LP_STOP 2 -+#define STM32_PM_CSTOP_ALLOW_LPLV_STOP 3 -+#define STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR 4 -+#define STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF 5 -+#define STM32_PM_SHUTDOWN 6 -+#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 bc71924faa..f3a0ed3178 100644 ---- a/include/dt-bindings/reset/stm32mp1-resets.h -+++ b/include/dt-bindings/reset/stm32mp1-resets.h -@@ -7,6 +7,7 @@ - #ifndef _DT_BINDINGS_STM32MP1_RESET_H_ - #define _DT_BINDINGS_STM32MP1_RESET_H_ - -+#define MCU_HOLD_BOOT_R 2144 - #define LTDC_R 3072 - #define DSI_R 3076 - #define DDRPERFM_R 3080 -@@ -117,5 +118,6 @@ - #define RST_SCMI0_RNG1 8 - #define RST_SCMI0_MDMA 9 - #define RST_SCMI0_MCU 10 -+#define RST_SCMI0_MCU_HOLD_BOOT 11 - - #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 -index 3f9fb3b12f..199c83154d 100644 ---- a/include/dt-bindings/soc/st,stm32-etzpc.h -+++ b/include/dt-bindings/soc/st,stm32-etzpc.h -@@ -17,4 +17,90 @@ - #define DECPROT_UNLOCK 0x0 - #define DECPROT_LOCK 0x1 - -+/* ETZPC ID */ -+#define STM32MP1_ETZPC_STGENC_ID 0 -+#define STM32MP1_ETZPC_BKPSRAM_ID 1 -+#define STM32MP1_ETZPC_IWDG1_ID 2 -+#define STM32MP1_ETZPC_USART1_ID 3 -+#define STM32MP1_ETZPC_SPI6_ID 4 -+#define STM32MP1_ETZPC_I2C4_ID 5 -+#define STM32MP1_ETZPC_RNG1_ID 7 -+#define STM32MP1_ETZPC_HASH1_ID 8 -+#define STM32MP1_ETZPC_CRYP1_ID 9 -+#define STM32MP1_ETZPC_DDRCTRL_ID 10 -+#define STM32MP1_ETZPC_DDRPHYC_ID 11 -+#define STM32MP1_ETZPC_I2C6_ID 12 -+#define STM32MP1_ETZPC_TIM2_ID 16 -+#define STM32MP1_ETZPC_TIM3_ID 17 -+#define STM32MP1_ETZPC_TIM4_ID 18 -+#define STM32MP1_ETZPC_TIM5_ID 19 -+#define STM32MP1_ETZPC_TIM6_ID 20 -+#define STM32MP1_ETZPC_TIM7_ID 21 -+#define STM32MP1_ETZPC_TIM12_ID 22 -+#define STM32MP1_ETZPC_TIM13_ID 23 -+#define STM32MP1_ETZPC_TIM14_ID 24 -+#define STM32MP1_ETZPC_LPTIM1_ID 25 -+#define STM32MP1_ETZPC_WWDG1_ID 26 -+#define STM32MP1_ETZPC_SPI2_ID 27 -+#define STM32MP1_ETZPC_SPI3_ID 28 -+#define STM32MP1_ETZPC_SPDIFRX_ID 29 -+#define STM32MP1_ETZPC_USART2_ID 30 -+#define STM32MP1_ETZPC_USART3_ID 31 -+#define STM32MP1_ETZPC_UART4_ID 32 -+#define STM32MP1_ETZPC_UART5_ID 33 -+#define STM32MP1_ETZPC_I2C1_ID 34 -+#define STM32MP1_ETZPC_I2C2_ID 35 -+#define STM32MP1_ETZPC_I2C3_ID 36 -+#define STM32MP1_ETZPC_I2C5_ID 37 -+#define STM32MP1_ETZPC_CEC_ID 38 -+#define STM32MP1_ETZPC_DAC_ID 39 -+#define STM32MP1_ETZPC_UART7_ID 40 -+#define STM32MP1_ETZPC_UART8_ID 41 -+#define STM32MP1_ETZPC_MDIOS_ID 44 -+#define STM32MP1_ETZPC_TIM1_ID 48 -+#define STM32MP1_ETZPC_TIM8_ID 49 -+#define STM32MP1_ETZPC_USART6_ID 51 -+#define STM32MP1_ETZPC_SPI1_ID 52 -+#define STM32MP1_ETZPC_SPI4_ID 53 -+#define STM32MP1_ETZPC_TIM15_ID 54 -+#define STM32MP1_ETZPC_TIM16_ID 55 -+#define STM32MP1_ETZPC_TIM17_ID 56 -+#define STM32MP1_ETZPC_SPI5_ID 57 -+#define STM32MP1_ETZPC_SAI1_ID 58 -+#define STM32MP1_ETZPC_SAI2_ID 59 -+#define STM32MP1_ETZPC_SAI3_ID 60 -+#define STM32MP1_ETZPC_DFSDM_ID 61 -+#define STM32MP1_ETZPC_TT_FDCAN_ID 62 -+#define STM32MP1_ETZPC_LPTIM2_ID 64 -+#define STM32MP1_ETZPC_LPTIM3_ID 65 -+#define STM32MP1_ETZPC_LPTIM4_ID 66 -+#define STM32MP1_ETZPC_LPTIM5_ID 67 -+#define STM32MP1_ETZPC_SAI4_ID 68 -+#define STM32MP1_ETZPC_VREFBUF_ID 69 -+#define STM32MP1_ETZPC_DCMI_ID 70 -+#define STM32MP1_ETZPC_CRC2_ID 71 -+#define STM32MP1_ETZPC_ADC_ID 72 -+#define STM32MP1_ETZPC_HASH2_ID 73 -+#define STM32MP1_ETZPC_RNG2_ID 74 -+#define STM32MP1_ETZPC_CRYP2_ID 75 -+#define STM32MP1_ETZPC_SRAM1_ID 80 -+#define STM32MP1_ETZPC_SRAM2_ID 81 -+#define STM32MP1_ETZPC_SRAM3_ID 82 -+#define STM32MP1_ETZPC_SRAM4_ID 83 -+#define STM32MP1_ETZPC_RETRAM_ID 84 -+#define STM32MP1_ETZPC_OTG_ID 85 -+#define STM32MP1_ETZPC_SDMMC3_ID 86 -+#define STM32MP1_ETZPC_DLYBSD3_ID 87 -+#define STM32MP1_ETZPC_DMA1_ID 88 -+#define STM32MP1_ETZPC_DMA2_ID 89 -+#define STM32MP1_ETZPC_DMAMUX_ID 90 -+#define STM32MP1_ETZPC_FMC_ID 91 -+#define STM32MP1_ETZPC_QSPI_ID 92 -+#define STM32MP1_ETZPC_DLYBQ_ID 93 -+#define STM32MP1_ETZPC_ETH_ID 94 -+ -+#define STM32MP1_ETZPC_MAX_ID 96 -+ -+#define DECPROT(id, mode, lock) (((id) << 16) | ((mode) << 8) | (lock)) -+ - #endif /* _DT_BINDINGS_STM32_ETZPC_H */ -diff --git a/include/dt-bindings/soc/stm32mp1-tzc400.h b/include/dt-bindings/soc/stm32mp1-tzc400.h -new file mode 100644 -index 0000000000..88fbcdd814 ---- /dev/null -+++ b/include/dt-bindings/soc/stm32mp1-tzc400.h -@@ -0,0 +1,37 @@ -+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ -+/* -+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved -+ * Author(s): Lionel DEBIEVE for STMicroelectronics. -+ */ -+ -+#ifndef _DT_BINDINGS_STM32MP1_TZC400_H -+#define _DT_BINDINGS_STM32MP1_TZC400_H -+ -+#include -+ -+#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) -+#define STM32MP1_TZC_DMA_ID U(6) -+#define STM32MP1_TZC_USB_HOST_ID U(7) -+#define STM32MP1_TZC_USB_OTG_ID U(8) -+#define STM32MP1_TZC_SDMMC_ID U(9) -+#define STM32MP1_TZC_ETH_ID U(10) -+#define STM32MP1_TZC_DAP_ID U(15) -+ -+#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ -+ (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)) -+ -+#endif /* _DT_BINDINGS_STM32MP1_TZC400_H */ -diff --git a/include/lib/optee_utils.h b/include/lib/optee_utils.h -index 6067caff42..ba44f998ec 100644 ---- a/include/lib/optee_utils.h -+++ b/include/lib/optee_utils.h -@@ -9,6 +9,7 @@ - - #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 b56e98b5f3..9f2a80ebeb 100644 ---- a/include/lib/psci/psci.h -+++ b/include/lib/psci/psci.h -@@ -349,6 +349,7 @@ int psci_node_hw_state(u_register_t target_cpu, - int psci_features(unsigned int psci_fid); - void __dead2 psci_power_down_wfi(void); - void psci_arch_setup(void); -+unsigned int psci_is_last_on_cpu(void); - - #endif /*__ASSEMBLER__*/ - -diff --git a/include/lib/usb/usb_core.h b/include/lib/usb/usb_core.h -new file mode 100644 -index 0000000000..dbc311d8bb ---- /dev/null -+++ b/include/lib/usb/usb_core.h -@@ -0,0 +1,277 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef USB_CORE_H -+#define USB_CORE_H -+ -+#include -+ -+#include -+ -+#define USBD_MAX_NUM_INTERFACES 1 -+#define USBD_MAX_NUM_CONFIGURATION 1 -+ -+#define USB_LEN_DEV_QUALIFIER_DESC 0x0A -+#define USB_LEN_DEV_DESC 0x12 -+#define USB_LEN_CFG_DESC 0x09 -+#define USB_LEN_IF_DESC 0x09 -+#define USB_LEN_EP_DESC 0x07 -+#define USB_LEN_OTG_DESC 0x03 -+#define USB_LEN_LANGID_STR_DESC 0x04 -+#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09 -+ -+#define USBD_IDX_LANGID_STR 0x00 -+#define USBD_IDX_MFC_STR 0x01 -+#define USBD_IDX_PRODUCT_STR 0x02 -+#define USBD_IDX_SERIAL_STR 0x03 -+#define USBD_IDX_CONFIG_STR 0x04 -+#define USBD_IDX_INTERFACE_STR 0x05 -+#define USBD_IDX_USER0_STR 0x06 -+ -+#define USB_REQ_TYPE_STANDARD 0x00 -+#define USB_REQ_TYPE_CLASS 0x20 -+#define USB_REQ_TYPE_VENDOR 0x40 -+#define USB_REQ_TYPE_MASK 0x60 -+ -+#define USB_REQ_RECIPIENT_DEVICE 0x00 -+#define USB_REQ_RECIPIENT_INTERFACE 0x01 -+#define USB_REQ_RECIPIENT_ENDPOINT 0x02 -+#define USB_REQ_RECIPIENT_MASK 0x1F -+ -+#define USB_REQ_DIRECTION 0x80 -+ -+#define USB_REQ_GET_STATUS 0x00 -+#define USB_REQ_CLEAR_FEATURE 0x01 -+#define USB_REQ_SET_FEATURE 0x03 -+#define USB_REQ_SET_ADDRESS 0x05 -+#define USB_REQ_GET_DESCRIPTOR 0x06 -+#define USB_REQ_SET_DESCRIPTOR 0x07 -+#define USB_REQ_GET_CONFIGURATION 0x08 -+#define USB_REQ_SET_CONFIGURATION 0x09 -+#define USB_REQ_GET_INTERFACE 0x0A -+#define USB_REQ_SET_INTERFACE 0x0B -+#define USB_REQ_SYNCH_FRAME 0x0C -+ -+#define USB_DESC_TYPE_DEVICE 0x01 -+#define USB_DESC_TYPE_CONFIGURATION 0x02 -+#define USB_DESC_TYPE_STRING 0x03 -+#define USB_DESC_TYPE_INTERFACE 0x04 -+#define USB_DESC_TYPE_ENDPOINT 0x05 -+#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 -+#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 -+#define USB_DESC_TYPE_BOS 0x0F -+ -+#define USB_CONFIG_REMOTE_WAKEUP 2 -+#define USB_CONFIG_SELF_POWERED 1 -+ -+#define USB_FEATURE_EP_HALT 0 -+#define USB_FEATURE_REMOTE_WAKEUP 1 -+#define USB_FEATURE_TEST_MODE 2 -+ -+#define USB_DEVICE_CAPABITY_TYPE 0x10 -+ -+#define USB_MAX_EP0_SIZE 64 -+ -+/* Device Status */ -+#define USBD_STATE_DEFAULT 1 -+#define USBD_STATE_ADDRESSED 2 -+#define USBD_STATE_CONFIGURED 3 -+#define USBD_STATE_SUSPENDED 4 -+ -+/* EP0 State */ -+#define USBD_EP0_IDLE 0 -+#define USBD_EP0_SETUP 1 -+#define USBD_EP0_DATA_IN 2 -+#define USBD_EP0_DATA_OUT 3 -+#define USBD_EP0_STATUS_IN 4 -+#define USBD_EP0_STATUS_OUT 5 -+#define USBD_EP0_STALL 6 -+ -+#define USBD_EP_TYPE_CTRL 0 -+#define USBD_EP_TYPE_ISOC 1 -+#define USBD_EP_TYPE_BULK 2 -+#define USBD_EP_TYPE_INTR 3 -+ -+#define USB_OTG_SPEED_HIGH 0 -+#define USB_OTG_SPEED_HIGH_IN_FULL 1 -+#define USB_OTG_SPEED_LOW 2 -+#define USB_OTG_SPEED_FULL 3 -+ -+#define USBD_OUT_EPNUM_MASK GENMASK(15, 0) -+#define USBD_OUT_COUNT_MASK GENMASK(31, 16) -+#define USBD_OUT_COUNT_SHIFT 16U -+ -+#define LOBYTE(x) ((uint8_t)((x) & 0x00FF)) -+#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00) >> 8)) -+ -+typedef struct { -+ uint8_t bm_request; -+ uint8_t b_request; -+ uint16_t value; -+ uint16_t index; -+ uint16_t length; -+} usb_setup_req_t; -+ -+struct usb_handle; -+ -+typedef struct { -+ uint8_t (*init)(struct usb_handle *pdev, uint8_t cfgidx); -+ uint8_t (*de_init)(struct usb_handle *pdev, uint8_t cfgidx); -+ /* Control Endpoints*/ -+ uint8_t (*setup)(struct usb_handle *pdev, usb_setup_req_t *req); -+ uint8_t (*ep0_tx_sent)(struct usb_handle *pdev); -+ uint8_t (*ep0_rx_ready)(struct usb_handle *pdev); -+ /* Class Specific Endpoints*/ -+ uint8_t (*data_in)(struct usb_handle *pdev, uint8_t epnum); -+ uint8_t (*data_out)(struct usb_handle *pdev, uint8_t epnum); -+ uint8_t (*sof)(struct usb_handle *pdev); -+ uint8_t (*iso_in_incomplete)(struct usb_handle *pdev, uint8_t epnum); -+ uint8_t (*iso_out_incomplete)(struct usb_handle *pdev, uint8_t epnum); -+} usb_class_t; -+ -+/* Following USB Device status */ -+typedef enum { -+ USBD_OK = 0, -+ USBD_BUSY, -+ USBD_FAIL, -+ USBD_TIMEOUT -+} usb_status_t; -+ -+/* Action to do after IT handling */ -+typedef enum { -+ USB_NOTHING = 0, -+ USB_DATA_OUT, -+ USB_DATA_IN, -+ USB_SETUP, -+ USB_ENUM_DONE, -+ USB_READ_DATA_PACKET, -+ USB_READ_SETUP_PACKET, -+ USB_RESET, -+ USB_RESUME, -+ USB_SUSPEND, -+ USB_LPM, -+ USB_SOF, -+ USB_DISCONNECT, -+ USB_WRITE_EMPTY -+} usb_action_t; -+ -+/* USB Device descriptors structure */ -+typedef struct { -+ uint8_t *(*get_device_desc)(uint16_t *length); -+ uint8_t *(*get_lang_id_desc)(uint16_t *length); -+ uint8_t *(*get_manufacturer_desc)(uint16_t *length); -+ uint8_t *(*get_product_desc)(uint16_t *length); -+ uint8_t *(*get_serial_desc)(uint16_t *length); -+ uint8_t *(*get_configuration_desc)(uint16_t *length); -+ uint8_t *(*get_interface_desc)(uint16_t *length); -+ uint8_t *(*get_usr_desc)(uint8_t index, uint16_t *length); -+ uint8_t *(*get_config_desc)(uint16_t *length); -+ uint8_t *(*get_device_qualifier_desc)(uint16_t *length); -+} usb_desc_t; -+ -+/* USB Device handle structure */ -+typedef struct { -+ uint32_t status; -+ uint32_t total_length; -+ uint32_t rem_length; -+ uint32_t maxpacket; -+} usb_endpoint_t; -+ -+typedef struct { -+ uint8_t num; /* Endpoint number -+ * This parameter must be a number between Min_Data = 1 -+ * and Max_Data = 15 -+ */ -+ bool is_in; /* Endpoint direction */ -+ uint8_t type; /* Endpoint type */ -+ uint32_t maxpacket; /* Endpoint Max packet size -+ * This parameter must be a number between -+ * Min_Data = 0 and Max_Data = 64KB -+ */ -+ uint8_t *xfer_buff; /* Pointer to transfer buffer */ -+ uint32_t xfer_len; /* Current transfer length */ -+ uint32_t xfer_count; /* Partial transfer length in case of multi -+ * packet transfer -+ */ -+} usbd_ep_t; -+ -+typedef enum { -+ LPM_L0 = 0x00, /* on */ -+ LPM_L1 = 0x01, /* LPM L1 sleep */ -+ LPM_L2 = 0x02, /* suspend */ -+ LPM_L3 = 0x03, /* off */ -+} pcd_lpm_state_t; -+ -+/* USB Device descriptors structure */ -+typedef struct { -+ usb_status_t (*ep0_out_start)(void *handle); -+ usb_status_t (*ep_start_xfer)(void *handle, usbd_ep_t *ep); -+ usb_status_t (*ep0_start_xfer)(void *handle, usbd_ep_t *ep); -+ usb_status_t (*write_packet)(void *handle, uint8_t *src, -+ uint8_t ch_ep_num, uint16_t len); -+ void *(*read_packet)(void *handle, uint8_t *dest, uint16_t len); -+ usb_status_t (*ep_set_stall)(void *handle, usbd_ep_t *ep); -+ usb_status_t (*start_device)(void *handle); -+ usb_status_t (*stop_device)(void *handle); -+ usb_status_t (*set_address)(void *handle, uint8_t address); -+ usb_status_t (*write_empty_tx_fifo)(void *handle, -+ uint32_t epnum, uint32_t xfer_len, -+ uint32_t *xfer_count, -+ uint32_t maxpacket, -+ uint8_t **xfer_buff); -+ usb_action_t (*it_handler)(void *handle, uint32_t *param); -+} usb_driver_t; -+ -+/* USB Peripheral Controller Drivers */ -+typedef struct { -+ void *instance; /* Register base address */ -+ usbd_ep_t in_ep[15]; /* IN endpoint parameters */ -+ usbd_ep_t out_ep[15]; /* OUT endpoint parameters */ -+ uint32_t setup[12]; /* Setup packet buffer */ -+ pcd_lpm_state_t lpm_state; /* LPM State */ -+} pcd_handle_t; -+ -+/* USB Device handle structure */ -+typedef struct usb_handle { -+ uint8_t id; -+ uint32_t dev_config; -+ uint32_t dev_config_status; -+ usb_endpoint_t ep_in[15]; -+ usb_endpoint_t ep_out[15]; -+ uint32_t ep0_state; -+ uint32_t ep0_data_len; -+ uint8_t dev_state; -+ uint8_t dev_old_state; -+ uint8_t dev_address; -+ uint32_t dev_remote_wakeup; -+ usb_setup_req_t request; -+ const usb_desc_t *desc; -+ usb_class_t *class; -+ void *class_data; -+ void *user_data; -+ pcd_handle_t *data; -+ const usb_driver_t *driver; -+} usb_handle_t; -+ -+usb_status_t usb_core_handle_it(usb_handle_t *pdev); -+usb_status_t usb_core_receive(usb_handle_t *pdev, uint8_t ep_addr, -+ uint8_t *p_buf, uint32_t len); -+usb_status_t usb_core_transmit(usb_handle_t *pdev, uint8_t ep_addr, -+ uint8_t *p_buf, uint32_t len); -+usb_status_t usb_core_receive_ep0(usb_handle_t *pdev, uint8_t *p_buf, -+ uint32_t len); -+usb_status_t usb_core_transmit_ep0(usb_handle_t *pdev, uint8_t *p_buf, -+ uint32_t len); -+void usb_core_ctl_error(usb_handle_t *pdev); -+usb_status_t usb_core_start(usb_handle_t *pdev); -+usb_status_t usb_core_stop(usb_handle_t *pdev); -+usb_status_t register_usb_driver(usb_handle_t *pdev, pcd_handle_t *pcd_handle, -+ const usb_driver_t *driver, -+ void *driver_handle); -+usb_status_t register_platform(usb_handle_t *pdev, -+ const usb_desc_t *plat_call_back); -+ -+#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 0000000000..bc043c091f ---- /dev/null -+++ b/include/lib/usb/usb_st_dfu.h -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef USB_ST_DFU_H -+#define USB_ST_DFU_H -+ -+#include -+ -+#include -+ -+#define DFU_DESCRIPTOR_TYPE 0x21 -+ -+/* Max DFU Packet Size = 1024 bytes */ -+#define USBD_DFU_XFER_SIZE 1024 -+ -+#define TRANSFER_SIZE_BYTES(size) \ -+ ((uint8_t)((size) & 0xFF)), /* XFERSIZEB0 */\ -+ ((uint8_t)((size) >> 8)) /* XFERSIZEB1 */ -+ -+/* Descriptor of DFU interface 0 Alternate setting n */ -+#define USBD_DFU_IF_DESC(n) 0x09, /* Interface Descriptor size */\ -+ USB_DESC_TYPE_INTERFACE, /* descriptor type */\ -+ 0x00, /* Number of Interface */\ -+ (n), /* Alternate setting */\ -+ 0x00, /* bNumEndpoints*/\ -+ 0xFE, /* Application Specific Class Code */\ -+ 0x01, /* Device Firmware Upgrade Code */\ -+ 0x02, /* DFU mode protocol */ \ -+ USBD_IDX_USER0_STR + (n) /* iInterface: -+ * Index of string -+ * descriptor -+ */ -+ -+/* DFU1.1 Standard */ -+#define USB_DFU_VERSION 0x0110 -+#define USB_DFU_ITF_SIZ 9 -+#define USB_DFU_DESC_SIZ(itf) (USB_DFU_ITF_SIZ * ((itf) + 2)) -+ -+/* bmAttribute : -+ * bitCanDnload = 1(bit 0) -+ * bitCanUpload = 1(bit 1) -+ * bitManifestationTolerant = 1 (bit 2) -+ * bitWillDetach = 1(bit 3) -+ * Reserved (bit4-6) -+ * bitAcceleratedST = 0(bit 7) -+ */ -+#define DFU_BM_ATTRIBUTE 0x0F -+ -+#define DFU_MEDIA_STATE_READY 0x00 -+#define DFU_MEDIA_STATE_WRITTEN 0x01 -+#define DFU_MEDIA_STATE_ERROR 0x02 -+ -+#define DFU_STATUS_SIZE 6U -+ -+typedef void (*p_function)(void); -+ -+/* Callback for media access */ -+typedef struct { -+ int (*upload)(uint8_t alt, uintptr_t *buffer, uint32_t *len, -+ void *user_data); -+ int (*download)(uint8_t alt, uintptr_t *buffer, uint32_t *len, -+ void *user_data); -+ int (*manifestation)(uint8_t alt, void *user_data); -+} usb_dfu_media_t; -+ -+/* Internal DFU handle */ -+typedef struct { -+ uint8_t status[DFU_STATUS_SIZE]; -+ uint8_t dev_state; -+ uint8_t dev_status; -+ uint32_t alt_setting; -+ const usb_dfu_media_t *callback; -+} usb_dfu_handle_t; -+ -+void usb_dfu_register(usb_handle_t *pdev, usb_dfu_handle_t *phandle); -+ -+int usb_dfu_loop(usb_handle_t *pdev, const usb_dfu_media_t *pmedia); -+ -+/* Function provided by plat */ -+usb_handle_t *usb_dfu_plat_init(void); -+ -+#endif /* USB_ST_DFU_H */ -diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h -index 2d0e9c08eb..bf93444505 100644 ---- a/include/lib/utils_def.h -+++ b/include/lib/utils_def.h -@@ -64,6 +64,16 @@ - ((val) + _div - (__typeof__(div)) 1) / _div; \ - }) - -+/* -+ * Macro for unsigned integer division with nearest rounding variant. -+ * Default integer division rounds down. -+ */ -+#define udiv_round_nearest(x, y) __extension__ ({ \ -+ __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); \ -diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h -index ebcc855774..ab05be1aed 100644 ---- a/include/plat/common/platform.h -+++ b/include/plat/common/platform.h -@@ -109,6 +109,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); -+#if AARCH32_EXCEPTION_DEBUG -+void plat_report_undef_inst(unsigned int fault_address); -+void plat_report_prefetch_abort(unsigned int fault_address); -+void plat_report_data_abort(unsigned int fault_address); -+#endif - int plat_crash_console_init(void); - int plat_crash_console_putc(int c); - void plat_crash_console_flush(void); -@@ -116,7 +121,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); - - /******************************************************************************* - * Mandatory BL1 functions -@@ -284,6 +289,8 @@ int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr); - int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr); - int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc, - unsigned int nv_ctr); -+int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, -+ void **hashed_pk_ptr, unsigned int *hash_pk_len); - int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size); - int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key, - size_t *key_len, unsigned int *flags, -diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S -index e9734ac2c6..aea975c0ad 100644 ---- a/lib/aarch32/misc_helpers.S -+++ b/lib/aarch32/misc_helpers.S -@@ -7,6 +7,8 @@ - #include - #include - #include -+#include -+#include - - .globl smc - .globl zeromem -@@ -14,6 +16,9 @@ - .globl memcpy4 - .globl disable_mmu_icache_secure - .globl disable_mmu_secure -+ .globl fixup_gdt_reloc -+ -+#define PAGE_START_MASK ~(PAGE_SIZE_MASK) - - func smc - /* -@@ -187,3 +192,124 @@ func disable_mmu_icache_secure - ldr r1, =(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) - b do_disable_mmu - endfunc disable_mmu_icache_secure -+ -+/* --------------------------------------------------------------------------- -+ * Helper to fixup Global Descriptor table (GDT) and dynamic relocations -+ * (.rel.dyn) at runtime. -+ * -+ * This function is meant to be used when the firmware is compiled with -fpie -+ * and linked with -pie options. We rely on the linker script exporting -+ * appropriate markers for start and end of the section. For GOT, we -+ * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect -+ * __RELA_START__ and __RELA_END__. -+ * -+ * The function takes the limits of the memory to apply fixups to as -+ * arguments (which is usually the limits of the relocable BL image). -+ * r0 - the start of the fixup region -+ * r1 - the limit of the fixup region -+ * These addresses have to be 4KB page aligned. -+ * --------------------------------------------------------------------------- -+ */ -+ -+/* Relocation codes */ -+#define R_ARM_RELATIVE 23 -+ -+func fixup_gdt_reloc -+ mov r6, r0 -+ mov r7, r1 -+ -+#if ENABLE_ASSERTIONS -+ /* Test if the limits are 4K aligned */ -+ orr r0, r0, r1 -+ mov r1, #(PAGE_SIZE_MASK) -+ tst r0, r1 -+ ASM_ASSERT(eq) -+#endif -+ /* -+ * Calculate the offset based on return address in lr. -+ * Assume that this function is called within a page at the start of -+ * fixup region. -+ */ -+ ldr r1, =PAGE_START_MASK -+ and r2, lr, r1 -+ subs r0, r2, r6 /* Diff(S) = Current Address - Compiled Address */ -+ beq 3f /* Diff(S) = 0. No relocation needed */ -+ -+ ldr r1, =__GOT_START__ -+ add r1, r1, r0 -+ ldr r2, =__GOT_END__ -+ add r2, r2, r0 -+ -+ /* -+ * GOT is an array of 32_bit addresses which must be fixed up as -+ * new_addr = old_addr + Diff(S). -+ * The new_addr is the address currently the binary is executing from -+ * and old_addr is the address at compile time. -+ */ -+1: ldr r3, [r1] -+ -+ /* Skip adding offset if address is < lower limit */ -+ cmp r3, r6 -+ blo 2f -+ -+ /* Skip adding offset if address is > upper limit */ -+ cmp r3, r7 -+ bhi 2f -+ add r3, r3, r0 -+ str r3, [r1] -+ -+2: add r1, r1, #4 -+ cmp r1, r2 -+ blo 1b -+ -+ /* Starting dynamic relocations. Use ldr to get RELA_START and END */ -+3: ldr r1, =__RELA_START__ -+ add r1, r1, r0 -+ ldr r2, =__RELA_END__ -+ add r2, r2, r0 -+ -+ /* -+ * According to ELF-32 specification, the RELA data structure is as -+ * follows: -+ * typedef struct { -+ * Elf32_Addr r_offset; -+ * Elf32_Xword r_info; -+ * } Elf32_Rela; -+ * -+ * r_offset is address of reference -+ * r_info is symbol index and type of relocation (in this case -+ * code 23 which corresponds to R_ARM_RELATIVE). -+ * -+ * Size of Elf32_Rela structure is 8 bytes. -+ */ -+ -+ /* Skip R_ARM_NONE entry with code 0 */ -+1: ldr r3, [r1, #4] -+ ands r3, r3, #0xff -+ beq 2f -+ -+#if ENABLE_ASSERTIONS -+ /* Assert that the relocation type is R_ARM_RELATIVE */ -+ cmp r3, #R_ARM_RELATIVE -+ ASM_ASSERT(eq) -+#endif -+ ldr r3, [r1] /* r_offset */ -+ add r3, r0, r3 /* Diff(S) + r_offset */ -+ ldr r4, [r3] -+ -+ /* Skip adding offset if address is < lower limit */ -+ cmp r4, r6 -+ blo 2f -+ -+ /* Skip adding offset if address is >= upper limit */ -+ cmp r4, r7 -+ bhs 2f -+ -+ add r4, r0, r4 -+ str r4, [r3] -+ -+2: add r1, r1, #8 -+ cmp r1, r2 -+ blo 1b -+ bx lr -+endfunc fixup_gdt_reloc -diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c -index 0ad108242e..18dbfe319a 100644 ---- a/lib/optee/optee_utils.c -+++ b/lib/optee/optee_utils.c -@@ -86,7 +86,7 @@ static int parse_optee_image(image_info_t *image_info, - * -1 indicates loader decided address; take our pre-mapped area - * for current image since arm-tf could not allocate memory dynamically - */ -- if (init_load_addr == -1) -+ if (init_load_addr == (uintptr_t)-1) - init_load_addr = image_info->image_base; - - /* Check that the default end address doesn't overflow */ -@@ -129,6 +129,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. -+ ******************************************************************************/ -+int get_optee_header_ep(entry_point_info_t *header_ep, uintptr_t *pc) -+{ -+ optee_header_t *optee_header; -+ uint32_t num; -+ -+ assert(pc && header_ep && header_ep->pc); -+ optee_header = (optee_header_t *)header_ep->pc; -+ -+ if (!tee_validate_header(optee_header)) -+ return 0; -+ -+ for (num = 0U; num < optee_header->nb_images; num++) { -+ optee_image_t *optee_image = -+ &optee_header->optee_image_list[num]; -+ -+ if (optee_image->image_id != OPTEE_PAGER_IMAGE_ID) -+ continue; -+ -+ *pc = ((uint64_t)optee_image->load_addr_hi << 32) | -+ optee_image->load_addr_lo; -+ return 1; -+ } -+ -+ return 0; -+} -+ - /******************************************************************************* - * Parse the OPTEE header - * Return 0 on success or a negative error code otherwise. -@@ -139,7 +169,8 @@ int parse_optee_header(entry_point_info_t *header_ep, - - { - optee_header_t *header; -- int num, ret; -+ uint32_t num; -+ int ret; - - assert(header_ep); - header = (optee_header_t *)header_ep->pc; -@@ -182,7 +213,7 @@ int parse_optee_header(entry_point_info_t *header_ep, - } - - /* Parse OPTEE image */ -- for (num = 0; num < header->nb_images; num++) { -+ for (num = 0U; num < header->nb_images; num++) { - if (header->optee_image_list[num].image_id == - OPTEE_PAGER_IMAGE_ID) { - ret = parse_optee_image(pager_image_info, -diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h -index e2dcfa8b1e..deb1d2d815 100644 ---- a/lib/psci/psci_private.h -+++ b/lib/psci/psci_private.h -@@ -286,7 +286,6 @@ unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info); - unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info); - void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl); - void psci_print_power_domain_map(void); --unsigned int psci_is_last_on_cpu(void); - int psci_spd_migrate_info(u_register_t *mpidr); - void psci_do_pwrdown_sequence(unsigned int power_level); - -diff --git a/lib/usb/usb_core.c b/lib/usb/usb_core.c -new file mode 100644 -index 0000000000..1f33095af4 ---- /dev/null -+++ b/lib/usb/usb_core.c -@@ -0,0 +1,838 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+ -+#include -+#include -+ -+/* define for field bEndpointAddress */ -+#define EP_DIR_MASK BIT(7) -+#define EP_DIR_IN BIT(7) -+#define EP_NUM_MASK GENMASK(3, 0) -+ -+#define EP0_IN (0U | EP_DIR_IN) -+#define EP0_OUT 0U -+ -+/* USB address between 1 through 127 = 0x7F mask */ -+#define ADDRESS_MASK GENMASK(6, 0) -+ -+/* -+ * @brief Set a STALL condition over an endpoint -+ * @param pdev: USB handle -+ * @param ep_addr: endpoint address -+ * @retval HAL status -+ */ -+static usb_status_t usb_core_set_stall(usb_handle_t *pdev, uint8_t ep_addr) -+{ -+ usbd_ep_t *ep; -+ pcd_handle_t *hpcd = (pcd_handle_t *)pdev->data; -+ uint8_t num; -+ -+ num = ep_addr & EP_NUM_MASK; -+ if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) { -+ ep = &hpcd->in_ep[num]; -+ ep->is_in = true; -+ } else { -+ ep = &hpcd->out_ep[num]; -+ ep->is_in = false; -+ } -+ ep->num = num; -+ -+ pdev->driver->ep_set_stall(hpcd->instance, ep); -+ if (num == 0U) { -+ pdev->driver->ep0_out_start(hpcd->instance); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_get_desc -+ * Handle Get Descriptor requests -+ * pdev : device instance -+ * req : usb request -+ * return : status -+ */ -+static void usb_core_get_desc(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ uint16_t len; -+ uint8_t *pbuf; -+ uint8_t desc_type = HIBYTE(req->value); -+ uint8_t desc_idx = LOBYTE(req->value); -+ -+ switch (desc_type) { -+ case USB_DESC_TYPE_DEVICE: -+ pbuf = pdev->desc->get_device_desc(&len); -+ break; -+ -+ case USB_DESC_TYPE_CONFIGURATION: -+ pbuf = (uint8_t *)pdev->desc->get_config_desc(&len); -+ pbuf[1] = USB_DESC_TYPE_CONFIGURATION; -+ break; -+ -+ case USB_DESC_TYPE_STRING: -+ switch (desc_idx) { -+ case USBD_IDX_LANGID_STR: -+ pbuf = pdev->desc->get_lang_id_desc(&len); -+ break; -+ -+ case USBD_IDX_MFC_STR: -+ pbuf = pdev->desc->get_manufacturer_desc(&len); -+ break; -+ -+ case USBD_IDX_PRODUCT_STR: -+ pbuf = pdev->desc->get_product_desc(&len); -+ break; -+ -+ case USBD_IDX_SERIAL_STR: -+ pbuf = pdev->desc->get_serial_desc(&len); -+ break; -+ -+ case USBD_IDX_CONFIG_STR: -+ pbuf = pdev->desc->get_configuration_desc(&len); -+ break; -+ -+ case USBD_IDX_INTERFACE_STR: -+ pbuf = pdev->desc->get_interface_desc(&len); -+ break; -+ -+ /* for all USER string */ -+ case USBD_IDX_USER0_STR: -+ default: -+ pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len); -+ break; -+ } -+ break; -+ -+ case USB_DESC_TYPE_DEVICE_QUALIFIER: -+ pbuf = (uint8_t *)pdev->desc->get_device_qualifier_desc(&len); -+ break; -+ -+ case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: -+ pbuf = (uint8_t *)pdev->desc->get_config_desc(&len); -+ pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; -+ break; -+ -+ default: -+ ERROR("Unknown request %i\n", desc_type); -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ if ((len != 0U) && (req->length != 0U)) { -+ len = MIN(len, req->length); -+ -+ /* Start the transfer */ -+ usb_core_transmit_ep0(pdev, pbuf, len); -+ } -+} -+ -+/* -+ * usb_core_set_config -+ * Handle Set device configuration request -+ * pdev : device instance -+ * req : usb request -+ * return : status -+ */ -+static void usb_core_set_config(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ static uint8_t cfgidx; -+ -+ cfgidx = LOBYTE(req->value); -+ -+ if (cfgidx > USBD_MAX_NUM_CONFIGURATION) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ switch (pdev->dev_state) { -+ case USBD_STATE_ADDRESSED: -+ if (cfgidx != 0U) { -+ pdev->dev_config = cfgidx; -+ pdev->dev_state = USBD_STATE_CONFIGURED; -+ if (!pdev->class) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ /* Set configuration and Start the Class */ -+ if (pdev->class->init(pdev, cfgidx) != 0U) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ } -+ break; -+ -+ case USBD_STATE_CONFIGURED: -+ if (cfgidx == 0U) { -+ pdev->dev_state = USBD_STATE_ADDRESSED; -+ pdev->dev_config = cfgidx; -+ pdev->class->de_init(pdev, cfgidx); -+ } else if (cfgidx != pdev->dev_config) { -+ if (pdev->class != NULL) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ /* Clear old configuration */ -+ pdev->class->de_init(pdev, pdev->dev_config); -+ /* Set new configuration */ -+ pdev->dev_config = cfgidx; -+ /* Set configuration and start the Class*/ -+ if (pdev->class->init(pdev, cfgidx) != 0U) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ } -+ break; -+ -+ default: -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ /* Send status */ -+ usb_core_transmit_ep0(pdev, NULL, 0U); -+} -+ -+/* -+ * usb_core_get_status -+ * Handle Get Status request -+ * pdev : device instance -+ * req : usb request -+ * return : status -+ */ -+static void usb_core_get_status(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ if ((pdev->dev_state != USBD_STATE_ADDRESSED) && -+ (pdev->dev_state != USBD_STATE_CONFIGURED)) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ pdev->dev_config_status = USB_CONFIG_SELF_POWERED; -+ -+ if (pdev->dev_remote_wakeup != 0U) { -+ pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; -+ } -+ -+ /* Start the transfer */ -+ usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U); -+} -+ -+/* -+ * usb_core_set_address -+ * Set device address -+ * pdev : device instance -+ * req : usb request -+ * return : status -+ */ -+static void usb_core_set_address(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ uint8_t dev_addr; -+ -+ if ((req->index != 0U) || (req->length != 0U)) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ dev_addr = req->value & ADDRESS_MASK; -+ if (pdev->dev_state != USBD_STATE_DEFAULT) { -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ pdev->dev_address = dev_addr; -+ pdev->driver->set_address(((pcd_handle_t *)(pdev->data))->instance, dev_addr); -+ -+ /* Send status */ -+ usb_core_transmit_ep0(pdev, NULL, 0U); -+ -+ if (dev_addr != 0U) { -+ pdev->dev_state = USBD_STATE_ADDRESSED; -+ } else { -+ pdev->dev_state = USBD_STATE_DEFAULT; -+ } -+} -+ -+/* -+ * usb_core_dev_req -+ * Handle standard usb device requests -+ * pdev : device instance -+ * req : usb request -+ * return : status -+ */ -+static usb_status_t usb_core_dev_req(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ VERBOSE("receive request %i\n", req->b_request); -+ switch (req->b_request) { -+ case USB_REQ_GET_DESCRIPTOR: -+ usb_core_get_desc(pdev, req); -+ break; -+ -+ case USB_REQ_SET_CONFIGURATION: -+ usb_core_set_config(pdev, req); -+ break; -+ -+ case USB_REQ_GET_STATUS: -+ usb_core_get_status(pdev, req); -+ break; -+ -+ case USB_REQ_SET_ADDRESS: -+ usb_core_set_address(pdev, req); -+ break; -+ -+ case USB_REQ_GET_CONFIGURATION: -+ case USB_REQ_SET_FEATURE: -+ case USB_REQ_CLEAR_FEATURE: -+ default: -+ ERROR("NOT SUPPORTED %i\n", req->b_request); -+ usb_core_ctl_error(pdev); -+ break; -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_itf_req -+ * Handle standard usb interface requests -+ * pdev : device instance -+ * req : usb request -+ * return : status -+ */ -+static usb_status_t usb_core_itf_req(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ if (pdev->dev_state != USBD_STATE_CONFIGURED) { -+ usb_core_ctl_error(pdev); -+ return USBD_OK; -+ } -+ -+ if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) { -+ pdev->class->setup(pdev, req); -+ -+ if (req->length == 0U) { -+ usb_core_transmit_ep0(pdev, NULL, 0U); -+ } -+ } else { -+ usb_core_ctl_error(pdev); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief USBD_ParseSetupRequest -+ * Copy buffer into setup structure -+ * @param pdev: device instance -+ * @param req: usb request -+ * @retval None -+ */ -+static void usb_core_parse_req(usb_setup_req_t *req, uint8_t *pdata) -+{ -+ req->bm_request = pdata[0]; -+ req->b_request = pdata[1]; -+ req->value = pdata[2] + (pdata[3] << 8); -+ req->index = pdata[4] + (pdata[5] << 8); -+ req->length = pdata[6] + (pdata[7] << 8); -+} -+ -+/* -+ * usb_core_setup_stage -+ * Handle the setup stage -+ * pdev: device instance -+ * return : status -+ */ -+static usb_status_t usb_core_setup_stage(usb_handle_t *pdev, uint8_t *psetup) -+{ -+ usb_core_parse_req(&pdev->request, psetup); -+ -+ pdev->ep0_state = USBD_EP0_SETUP; -+ pdev->ep0_data_len = pdev->request.length; -+ -+ switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) { -+ case USB_REQ_RECIPIENT_DEVICE: -+ usb_core_dev_req(pdev, &pdev->request); -+ break; -+ -+ case USB_REQ_RECIPIENT_INTERFACE: -+ usb_core_itf_req(pdev, &pdev->request); -+ break; -+ -+ case USB_REQ_RECIPIENT_ENDPOINT: -+ default: -+ ERROR("receive unsupported request %i", -+ pdev->request.bm_request & USB_REQ_RECIPIENT_MASK); -+ usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION); -+ return USBD_FAIL; -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_data_out -+ * Handle data OUT stage -+ * pdev: device instance -+ * epnum: endpoint index -+ * return : status -+ */ -+static usb_status_t usb_core_data_out(usb_handle_t *pdev, uint8_t epnum, -+ uint8_t *pdata) -+{ -+ usb_endpoint_t *pep; -+ -+ if (epnum == 0U) { -+ pep = &pdev->ep_out[0]; -+ if (pdev->ep0_state == USBD_EP0_DATA_OUT) { -+ if (pep->rem_length > pep->maxpacket) { -+ pep->rem_length -= pep->maxpacket; -+ -+ usb_core_receive(pdev, 0U, pdata, -+ MIN(pep->rem_length, -+ pep->maxpacket)); -+ } else { -+ if (pdev->class->ep0_rx_ready && -+ (pdev->dev_state == USBD_STATE_CONFIGURED)) -+ pdev->class->ep0_rx_ready(pdev); -+ -+ usb_core_transmit_ep0(pdev, NULL, 0U); -+ } -+ } -+ } else if (pdev->class->data_out != NULL && -+ (pdev->dev_state == USBD_STATE_CONFIGURED)) { -+ pdev->class->data_out(pdev, epnum); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_data_in -+ * Handle data in stage -+ * pdev: device instance -+ * epnum: endpoint index -+ * return : status -+ */ -+static usb_status_t usb_core_data_in(usb_handle_t *pdev, uint8_t epnum, -+ uint8_t *pdata) -+{ -+ if (epnum == 0U) { -+ usb_endpoint_t *pep = &pdev->ep_in[0]; -+ -+ if (pdev->ep0_state == USBD_EP0_DATA_IN) { -+ if (pep->rem_length > pep->maxpacket) { -+ pep->rem_length -= pep->maxpacket; -+ -+ usb_core_transmit(pdev, 0U, pdata, -+ pep->rem_length); -+ -+ /* Prepare endpoint for premature -+ * end of transfer -+ */ -+ usb_core_receive(pdev, 0U, NULL, 0U); -+ } else { -+ /* Last packet is MPS multiple, -+ * so send ZLP packet -+ */ -+ if ((pep->total_length % pep->maxpacket == 0U) && -+ (pep->total_length >= pep->maxpacket) && -+ (pep->total_length < pdev->ep0_data_len)) { -+ usb_core_transmit(pdev, 0U, NULL, 0U); -+ -+ pdev->ep0_data_len = 0U; -+ -+ /* Prepare endpoint for premature -+ * end of transfer -+ */ -+ usb_core_receive(pdev, 0U, NULL, 0U); -+ } else { -+ if (pdev->class->ep0_tx_sent != NULL && -+ (pdev->dev_state == -+ USBD_STATE_CONFIGURED)) -+ pdev->class->ep0_tx_sent(pdev); -+ -+ /* Start the transfer */ -+ usb_core_receive_ep0(pdev, NULL, 0U); -+ } -+ } -+ } -+ } else if (pdev->class->data_in != NULL && -+ (pdev->dev_state == USBD_STATE_CONFIGURED)) { -+ pdev->class->data_in(pdev, epnum); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_suspend -+ * Handle suspend event -+ * pdev : device instance -+ * return : status -+ */ -+ -+static usb_status_t usb_core_suspend(usb_handle_t *pdev) -+{ -+ INFO("USB Suspend mode\n"); -+ pdev->dev_old_state = pdev->dev_state; -+ pdev->dev_state = USBD_STATE_SUSPENDED; -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_resume -+ * Handle resume event -+ * pdev : device instance -+ * return : status -+ */ -+ -+static usb_status_t usb_core_resume(usb_handle_t *pdev) -+{ -+ INFO("USB Resume\n"); -+ pdev->dev_state = pdev->dev_old_state; -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_sof -+ * Handle SOF event -+ * pdev : device instance -+ * return : status -+ */ -+ -+static usb_status_t usb_core_sof(usb_handle_t *pdev) -+{ -+ if (pdev->dev_state == USBD_STATE_CONFIGURED) { -+ if (pdev->class->sof != NULL) -+ pdev->class->sof(pdev); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_disconnect -+ * Handle device disconnection event -+ * pdev : device instance -+ * return : status -+ */ -+static usb_status_t usb_core_disconnect(usb_handle_t *pdev) -+{ -+ /* Free class resources */ -+ pdev->dev_state = USBD_STATE_DEFAULT; -+ pdev->class->de_init(pdev, pdev->dev_config); -+ -+ return USBD_OK; -+} -+ -+usb_status_t usb_core_handle_it(usb_handle_t *pdev) -+{ -+ uint32_t param = 0U; -+ uint32_t len = 0U; -+ usbd_ep_t *ep; -+ -+ switch (pdev->driver->it_handler(pdev->data->instance, ¶m)) { -+ case USB_DATA_OUT: -+ usb_core_data_out(pdev, param, -+ pdev->data->out_ep[param].xfer_buff); -+ break; -+ -+ case USB_DATA_IN: -+ usb_core_data_in(pdev, param, -+ pdev->data->in_ep[param].xfer_buff); -+ break; -+ -+ case USB_SETUP: -+ usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup); -+ break; -+ -+ case USB_ENUM_DONE: -+ break; -+ -+ case USB_READ_DATA_PACKET: -+ ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; -+ len = (param & USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT; -+ pdev->driver->read_packet(pdev->data->instance, -+ ep->xfer_buff, len); -+ ep->xfer_buff += len; -+ ep->xfer_count += len; -+ break; -+ -+ case USB_READ_SETUP_PACKET: -+ ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; -+ len = (param & USBD_OUT_COUNT_MASK) >> 0x10; -+ pdev->driver->read_packet(pdev->data->instance, -+ (uint8_t *)pdev->data->setup, 8); -+ ep->xfer_count += len; -+ break; -+ -+ case USB_RESET: -+ pdev->dev_state = USBD_STATE_DEFAULT; -+ break; -+ -+ case USB_RESUME: -+ if (pdev->data->lpm_state == LPM_L1) { -+ pdev->data->lpm_state = LPM_L0; -+ } else { -+ usb_core_resume(pdev); -+ } -+ break; -+ -+ case USB_SUSPEND: -+ usb_core_suspend(pdev); -+ break; -+ -+ case USB_LPM: -+ if (pdev->data->lpm_state == LPM_L0) { -+ pdev->data->lpm_state = LPM_L1; -+ } else { -+ usb_core_suspend(pdev); -+ } -+ break; -+ -+ case USB_SOF: -+ usb_core_sof(pdev); -+ break; -+ -+ case USB_DISCONNECT: -+ usb_core_disconnect(pdev); -+ break; -+ -+ case USB_WRITE_EMPTY: -+ pdev->driver->write_empty_tx_fifo(pdev->data->instance, param, -+ pdev->data->in_ep[param].xfer_len, -+ (uint32_t *)&pdev->data->in_ep[param].xfer_count, -+ pdev->data->in_ep[param].maxpacket, -+ &pdev->data->in_ep[param].xfer_buff); -+ break; -+ -+ case USB_NOTHING: -+ default: -+ break; -+ } -+ -+ return USBD_OK; -+} -+ -+/** -+ * @brief Receive an amount of data -+ * @param pdev: USB handle -+ * @param ep_addr: endpoint address -+ * @param pBuf: pointer to the reception buffer -+ * @param len: amount of data to be received -+ * @retval status -+ */ -+usb_status_t usb_core_receive(usb_handle_t *pdev, uint8_t ep_addr, -+ uint8_t *buf, uint32_t len) -+{ -+ usbd_ep_t *ep; -+ pcd_handle_t *hpcd = (pcd_handle_t *)pdev->data; -+ uint8_t num; -+ -+ num = ep_addr & EP_NUM_MASK; -+ ep = &hpcd->out_ep[num]; -+ -+ /* Setup and start the Xfer */ -+ ep->xfer_buff = buf; -+ ep->xfer_len = len; -+ ep->xfer_count = 0U; -+ ep->is_in = false; -+ ep->num = num; -+ -+ if (num == 0U) { -+ pdev->driver->ep0_start_xfer(hpcd->instance, ep); -+ } else { -+ pdev->driver->ep_start_xfer(hpcd->instance, ep); -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief Send an amount of data -+ * @param pdev: USB handle -+ * @param ep_addr: endpoint address -+ * @param pBuf: pointer to the transmission buffer -+ * @param len: amount of data to be sent -+ * @retval status -+ */ -+usb_status_t usb_core_transmit(usb_handle_t *pdev, uint8_t ep_addr, -+ uint8_t *buf, uint32_t len) -+{ -+ usbd_ep_t *ep; -+ pcd_handle_t *hpcd = (pcd_handle_t *)pdev->data; -+ uint8_t num; -+ -+ num = ep_addr & EP_NUM_MASK; -+ ep = &hpcd->in_ep[num]; -+ -+ /* Setup and start the Xfer */ -+ ep->xfer_buff = buf; -+ ep->xfer_len = len; -+ ep->xfer_count = 0U; -+ ep->is_in = true; -+ ep->num = num; -+ -+ if (num == 0U) { -+ pdev->driver->ep0_start_xfer(hpcd->instance, ep); -+ } else { -+ pdev->driver->ep_start_xfer(hpcd->instance, ep); -+ } -+ -+ return USBD_OK; -+} -+ -+/** -+ * @brief Receive an amount of data on ep0 -+ * @param pdev: USB handle -+ * @param buf: pointer to the reception buffer -+ * @param len: amount of data to be received -+ * @retval status -+ */ -+usb_status_t usb_core_receive_ep0(usb_handle_t *pdev, uint8_t *buf, -+ uint32_t len) -+{ -+ /* Prepare the reception of the buffer over EP0 */ -+ if (len != 0U) { -+ pdev->ep0_state = USBD_EP0_DATA_OUT; -+ } else { -+ pdev->ep0_state = USBD_EP0_STATUS_OUT; -+ } -+ -+ pdev->ep_out[0].total_length = len; -+ pdev->ep_out[0].rem_length = len; -+ -+ /* Start the transfer */ -+ return usb_core_receive(pdev, 0U, buf, len); -+} -+ -+/* -+ * @brief Send an amount of data on ep0 -+ * @param pdev: USB handle -+ * @param buf: pointer to the transmission buffer -+ * @param len: amount of data to be sent -+ * @retval status -+ */ -+usb_status_t usb_core_transmit_ep0(usb_handle_t *pdev, uint8_t *buf, -+ uint32_t len) -+{ -+ /* Set EP0 State */ -+ if (len != 0U) { -+ pdev->ep0_state = USBD_EP0_DATA_IN; -+ } else { -+ pdev->ep0_state = USBD_EP0_STATUS_IN; -+ } -+ -+ pdev->ep_in[0].total_length = len; -+ pdev->ep_in[0].rem_length = len; -+ -+ /* Start the transfer */ -+ return usb_core_transmit(pdev, 0U, buf, len); -+} -+ -+/* -+ * @brief usb_core_ctl_error -+ * Handle USB low level error -+ * @param pdev: device instance -+ * @param req: usb request -+ * @retval None -+ */ -+ -+void usb_core_ctl_error(usb_handle_t *pdev) -+{ -+ ERROR("%s : Send an ERROR\n", __func__); -+ usb_core_set_stall(pdev, EP0_IN); -+ usb_core_set_stall(pdev, EP0_OUT); -+} -+ -+/* -+ * usb_core_start -+ * Start the USB device core. -+ * pdev: Device Handle -+ * return : USBD Status -+ */ -+usb_status_t usb_core_start(usb_handle_t *pdev) -+{ -+ /* Start the low level driver */ -+ pdev->driver->start_device(pdev->data->instance); -+ -+ return USBD_OK; -+} -+ -+/* -+ * usb_core_stop -+ * Stop the USB device core. -+ * pdev: Device Handle -+ * return : USBD Status -+ */ -+usb_status_t usb_core_stop(usb_handle_t *pdev) -+{ -+ /* Free class resources */ -+ pdev->class->de_init(pdev, pdev->dev_config); -+ -+ /* Stop the low level driver */ -+ pdev->driver->stop_device(pdev->data->instance); -+ -+ return USBD_OK; -+} -+ -+/* -+ * register_usb_driver -+ * Stop the USB device core. -+ * pdev: Device Handle -+ * @param hpcd: PCD handle -+ * @param driver: USB driver -+ * @param driver_handle: USB driver handle -+ * return : USBD Status -+ */ -+usb_status_t register_usb_driver(usb_handle_t *pdev, pcd_handle_t *pcd_handle, -+ const usb_driver_t *driver, -+ void *driver_handle) -+{ -+ uint8_t i; -+ -+ assert(pdev != NULL); -+ assert(pcd_handle != NULL); -+ assert(driver != NULL); -+ assert(driver_handle != NULL); -+ -+ /* Free class resources */ -+ pdev->driver = driver; -+ pdev->data = pcd_handle; -+ pdev->data->instance = driver_handle; -+ pdev->dev_state = USBD_STATE_DEFAULT; -+ pdev->ep0_state = USBD_EP0_IDLE; -+ -+ /* Copy endpoint information */ -+ for (i = 0U; i < 15U; i++) { -+ pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket; -+ pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket; -+ } -+ -+ return USBD_OK; -+} -+ -+/* -+ * register_platform -+ * Register the USB device core. -+ * pdev: Device Handle -+ * plat_call_back: callback -+ * return : USBD Status -+ */ -+usb_status_t register_platform(usb_handle_t *pdev, -+ const usb_desc_t *plat_call_back) -+{ -+ assert(pdev != NULL); -+ assert(plat_call_back != NULL); -+ -+ /* Save platform info in class resources */ -+ pdev->desc = plat_call_back; -+ -+ return USBD_OK; -+} -diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c -new file mode 100644 -index 0000000000..18f5415990 ---- /dev/null -+++ b/lib/usb/usb_st_dfu.c -@@ -0,0 +1,537 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+/* DFU Requests DFU states */ -+#define APP_STATE_IDLE 0 -+#define APP_STATE_DETACH 1 -+#define DFU_STATE_IDLE 2 -+#define DFU_STATE_DNLOAD_SYNC 3 -+#define DFU_STATE_DNLOAD_BUSY 4 -+#define DFU_STATE_DNLOAD_IDLE 5 -+#define DFU_STATE_MANIFEST_SYNC 6 -+#define DFU_STATE_MANIFEST 7 -+#define DFU_STATE_MANIFEST_WAIT_RESET 8 -+#define DFU_STATE_UPLOAD_IDLE 9 -+#define DFU_STATE_ERROR 10 -+ -+/* DFU errors */ -+#define DFU_ERROR_NONE 0x00 -+#define DFU_ERROR_TARGET 0x01 -+#define DFU_ERROR_FILE 0x02 -+#define DFU_ERROR_WRITE 0x03 -+#define DFU_ERROR_ERASE 0x04 -+#define DFU_ERROR_CHECK_ERASED 0x05 -+#define DFU_ERROR_PROG 0x06 -+#define DFU_ERROR_VERIFY 0x07 -+#define DFU_ERROR_ADDRESS 0x08 -+#define DFU_ERROR_NOTDONE 0x09 -+#define DFU_ERROR_FIRMWARE 0x0A -+#define DFU_ERROR_VENDOR 0x0B -+#define DFU_ERROR_USB 0x0C -+#define DFU_ERROR_POR 0x0D -+#define DFU_ERROR_UNKNOWN 0x0E -+#define DFU_ERROR_STALLEDPKT 0x0F -+ -+typedef enum { -+ DFU_DETACH = 0, -+ DFU_DNLOAD, -+ DFU_UPLOAD, -+ DFU_GETSTATUS, -+ DFU_CLRSTATUS, -+ DFU_GETSTATE, -+ DFU_ABORT -+} dfu_request_t; -+ -+static bool usb_dfu_detach_req; -+ -+/* -+ * @brief usb_dfu_init -+ * Initialize the DFU interface -+ * @param pdev: device instance -+ * @param cfgidx: Configuration index -+ * @retval status -+ */ -+static uint8_t usb_dfu_init(usb_handle_t *pdev, uint8_t cfgidx) -+{ -+ /* Nothing to do in this stage */ -+ return USBD_OK; -+} -+ -+/** -+ * @brief usb_dfu_de_init -+ * De-Initialize the DFU layer -+ * @param pdev: device instance -+ * @param cfgidx: Configuration index -+ * @retval status -+ */ -+static uint8_t usb_dfu_de_init(usb_handle_t *pdev, uint8_t cfgidx) -+{ -+ /* Nothing to do in this stage */ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_data_in -+ * handle data IN Stage -+ * @param pdev: device instance -+ * @param epnum: endpoint index -+ * @retval status -+ */ -+static uint8_t usb_dfu_data_in(usb_handle_t *pdev, uint8_t epnum) -+{ -+ (void)pdev; -+ (void)epnum; -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_ep0_rx_ready -+ * handle EP0 Rx Ready event -+ * @param pdev: device instance -+ * @retval status -+ */ -+static uint8_t usb_dfu_ep0_rx_ready(usb_handle_t *pdev) -+{ -+ (void)pdev; -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_ep0_tx_ready -+ * handle EP0 TRx Ready event -+ * @param pdev: device instance -+ * @retval status -+ */ -+static uint8_t usb_dfu_ep0_tx_ready(usb_handle_t *pdev) -+{ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_sof -+ * handle SOF event -+ * @param pdev: device instance -+ * @retval status -+ */ -+static uint8_t usb_dfu_sof(usb_handle_t *pdev) -+{ -+ (void)pdev; -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_iso_in_incomplete -+ * handle data ISO IN Incomplete event -+ * @param pdev: device instance -+ * @param epnum: endpoint index -+ * @retval status -+ */ -+static uint8_t usb_dfu_iso_in_incomplete(usb_handle_t *pdev, uint8_t epnum) -+{ -+ (void)pdev; -+ (void)epnum; -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_iso_out_incomplete -+ * handle data ISO OUT Incomplete event -+ * @param pdev: device instance -+ * @param epnum: endpoint index -+ * @retval status -+ */ -+static uint8_t usb_dfu_iso_out_incomplete(usb_handle_t *pdev, uint8_t epnum) -+{ -+ (void)pdev; -+ (void)epnum; -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_data_out -+ * handle data OUT Stage -+ * @param pdev: device instance -+ * @param epnum: endpoint index -+ * @retval status -+ */ -+static uint8_t usb_dfu_data_out(usb_handle_t *pdev, uint8_t epnum) -+{ -+ (void)pdev; -+ (void)epnum; -+ -+ return USBD_OK; -+} -+ -+/* -+ * @brief usb_dfu_detach -+ * Handles the DFU DETACH request. -+ * @param pdev: device instance -+ * @param req: pointer to the request structure. -+ * @retval None. -+ */ -+static void usb_dfu_detach(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ INFO("Receive DFU Detach\n"); -+ -+ if ((hdfu->dev_state == DFU_STATE_IDLE) || -+ (hdfu->dev_state == DFU_STATE_DNLOAD_SYNC) || -+ (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE) || -+ (hdfu->dev_state == DFU_STATE_MANIFEST_SYNC) || -+ (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) { -+ /* Update the state machine */ -+ hdfu->dev_state = DFU_STATE_IDLE; -+ hdfu->dev_status = DFU_ERROR_NONE; -+ } -+ -+ usb_dfu_detach_req = true; -+} -+ -+/* -+ * @brief usb_dfu_download -+ * Handles the DFU DNLOAD request. -+ * @param pdev: device instance -+ * @param req: pointer to the request structure -+ * @retval None -+ */ -+static void usb_dfu_download(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ uintptr_t data_ptr; -+ uint32_t length; -+ int ret; -+ -+ /* Data setup request */ -+ if (req->length > 0) { -+ /* Unsupported state */ -+ if ((hdfu->dev_state != DFU_STATE_IDLE) && -+ (hdfu->dev_state != DFU_STATE_DNLOAD_IDLE)) { -+ /* Call the error management function (command will be nacked) */ -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ /* Get the data address */ -+ length = req->length; -+ ret = hdfu->callback->download(hdfu->alt_setting, &data_ptr, -+ &length, pdev->user_data); -+ if (ret == 0U) { -+ /* Update the state machine */ -+ hdfu->dev_state = DFU_STATE_DNLOAD_SYNC; -+ /* Start the transfer */ -+ usb_core_receive_ep0(pdev, (uint8_t *)data_ptr, length); -+ } else { -+ usb_core_ctl_error(pdev); -+ } -+ } else { -+ /* End of DNLOAD operation*/ -+ if (hdfu->dev_state != DFU_STATE_DNLOAD_IDLE) { -+ /* Call the error management function (command will be nacked) */ -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ /* End of DNLOAD operation*/ -+ hdfu->dev_state = DFU_STATE_MANIFEST_SYNC; -+ ret = hdfu->callback->manifestation(hdfu->alt_setting, pdev->user_data); -+ if (ret == 0U) { -+ hdfu->dev_state = DFU_STATE_MANIFEST_SYNC; -+ } else { -+ usb_core_ctl_error(pdev); -+ } -+ } -+} -+ -+/* -+ * @brief usb_dfu_upload -+ * Handles the DFU UPLOAD request. -+ * @param pdev: instance -+ * @param req: pointer to the request structure -+ * @retval status -+ */ -+static void usb_dfu_upload(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ uintptr_t data_ptr; -+ uint32_t length; -+ int ret; -+ -+ /* Data setup request */ -+ if (req->length == 0) { -+ /* No Data setup request */ -+ hdfu->dev_state = DFU_STATE_IDLE; -+ return; -+ } -+ -+ /* Unsupported state */ -+ if ((hdfu->dev_state != DFU_STATE_IDLE) && (hdfu->dev_state != DFU_STATE_UPLOAD_IDLE)) { -+ ERROR("UPLOAD : Unsupported State\n"); -+ /* Call the error management function (command will be nacked) */ -+ usb_core_ctl_error(pdev); -+ return; -+ } -+ -+ /* Update the data address */ -+ length = req->length; -+ ret = hdfu->callback->upload(hdfu->alt_setting, &data_ptr, &length, pdev->user_data); -+ if (ret == 0U) { -+ /* Short frame */ -+ hdfu->dev_state = (req->length > length) ? DFU_STATE_IDLE : DFU_STATE_UPLOAD_IDLE; -+ -+ /* Start the transfer */ -+ usb_core_transmit_ep0(pdev, (uint8_t *)data_ptr, length); -+ } else { -+ ERROR("UPLOAD : bad block %i on alt %i\n", req->value, req->index); -+ hdfu->dev_state = DFU_STATE_ERROR; -+ hdfu->dev_status = DFU_ERROR_STALLEDPKT; -+ -+ /* Call the error management function (command will be nacked) */ -+ usb_core_ctl_error(pdev); -+ } -+} -+ -+/* -+ * @brief usb_dfu_get_status -+ * Handles the DFU GETSTATUS request. -+ * @param pdev: instance -+ * @retval status -+ */ -+static void usb_dfu_get_status(usb_handle_t *pdev) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ hdfu->status[0] = hdfu->dev_status; /* bStatus */ -+ hdfu->status[1] = 0; /* bwPollTimeout[3]; */ -+ hdfu->status[2] = 0; -+ hdfu->status[3] = 0; -+ hdfu->status[4] = hdfu->dev_state; /* bState */ -+ hdfu->status[5] = 0; /* iString */ -+ -+ /* next step */ -+ switch (hdfu->dev_state) { -+ case DFU_STATE_DNLOAD_SYNC: -+ hdfu->dev_state = DFU_STATE_DNLOAD_IDLE; -+ break; -+ case DFU_STATE_MANIFEST_SYNC: -+ /* We're MainfestationTolerant */ -+ hdfu->status[4] = DFU_STATE_MANIFEST; -+ hdfu->status[1] = 1U; /* bwPollTimeout = 1ms */ -+ hdfu->dev_state = DFU_STATE_IDLE; -+ break; -+ -+ default: -+ break; -+ } -+ -+ /* Start the transfer */ -+ usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->status[0], sizeof(hdfu->status)); -+} -+ -+/* -+ * @brief usb_dfu_clear_status -+ * Handles the DFU CLRSTATUS request. -+ * @param pdev: device instance -+ * @retval status -+ */ -+static void usb_dfu_clear_status(usb_handle_t *pdev) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ if (hdfu->dev_state == DFU_STATE_ERROR) { -+ hdfu->dev_state = DFU_STATE_IDLE; -+ hdfu->dev_status = DFU_ERROR_NONE; -+ } else { -+ /* State Error */ -+ hdfu->dev_state = DFU_STATE_ERROR; -+ hdfu->dev_status = DFU_ERROR_UNKNOWN; -+ } -+} -+ -+/* -+ * @brief usb_dfu_get_state -+ * Handles the DFU GETSTATE request. -+ * @param pdev: device instance -+ * @retval None -+ */ -+static void usb_dfu_get_state(usb_handle_t *pdev) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ /* Return the current state of the DFU interface */ -+ usb_core_transmit_ep0(pdev, &hdfu->dev_state, 1); -+} -+ -+/* -+ * @brief usb_dfu_abort -+ * Handles the DFU ABORT request. -+ * @param pdev: device instance -+ * @retval None -+ */ -+static void usb_dfu_abort(usb_handle_t *pdev) -+{ -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ if ((hdfu->dev_state == DFU_STATE_IDLE) || -+ (hdfu->dev_state == DFU_STATE_DNLOAD_SYNC) || -+ (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE) || -+ (hdfu->dev_state == DFU_STATE_MANIFEST_SYNC) || -+ (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) { -+ hdfu->dev_state = DFU_STATE_IDLE; -+ hdfu->dev_status = DFU_ERROR_NONE; -+ } -+} -+ -+/* -+ * @brief usb_dfu_setup -+ * Handle the DFU specific requests -+ * @param pdev: instance -+ * @param req: usb requests -+ * @retval status -+ */ -+static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req) -+{ -+ uint8_t *pbuf = NULL; -+ uint16_t len = 0U; -+ uint8_t ret = USBD_OK; -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ switch (req->bm_request & USB_REQ_TYPE_MASK) { -+ case USB_REQ_TYPE_CLASS: -+ switch (req->b_request) { -+ case DFU_DNLOAD: -+ usb_dfu_download(pdev, req); -+ break; -+ -+ case DFU_UPLOAD: -+ usb_dfu_upload(pdev, req); -+ break; -+ -+ case DFU_GETSTATUS: -+ usb_dfu_get_status(pdev); -+ break; -+ -+ case DFU_CLRSTATUS: -+ usb_dfu_clear_status(pdev); -+ break; -+ -+ case DFU_GETSTATE: -+ usb_dfu_get_state(pdev); -+ break; -+ -+ case DFU_ABORT: -+ usb_dfu_abort(pdev); -+ break; -+ -+ case DFU_DETACH: -+ usb_dfu_detach(pdev, req); -+ break; -+ -+ default: -+ ERROR("unkwon request %x on alternate %i\n", -+ req->b_request, hdfu->alt_setting); -+ usb_core_ctl_error(pdev); -+ ret = USBD_FAIL; -+ break; -+ } -+ break; -+ case USB_REQ_TYPE_STANDARD: -+ switch (req->b_request) { -+ case USB_REQ_GET_DESCRIPTOR: -+ if (HIBYTE(req->value) == DFU_DESCRIPTOR_TYPE) { -+ pbuf = pdev->desc->get_config_desc(&len); -+ /* DFU descriptor at the end of the USB */ -+ pbuf += len - 9U; -+ len = 9U; -+ len = MIN(len, req->length); -+ } -+ -+ /* Start the transfer */ -+ usb_core_transmit_ep0(pdev, pbuf, len); -+ -+ break; -+ -+ case USB_REQ_GET_INTERFACE: -+ /* Start the transfer */ -+ usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->alt_setting, 1U); -+ break; -+ -+ case USB_REQ_SET_INTERFACE: -+ hdfu->alt_setting = LOBYTE(req->value); -+ break; -+ -+ default: -+ usb_core_ctl_error(pdev); -+ ret = USBD_FAIL; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+static const usb_class_t USBD_DFU_initvalue = { -+ .init = usb_dfu_init, -+ .de_init = usb_dfu_de_init, -+ .setup = usb_dfu_setup, -+ .ep0_tx_sent = usb_dfu_ep0_tx_ready, -+ .ep0_rx_ready = usb_dfu_ep0_rx_ready, -+ .data_in = usb_dfu_data_in, -+ .data_out = usb_dfu_data_out, -+ .sof = usb_dfu_sof, -+ .iso_in_incomplete = usb_dfu_iso_in_incomplete, -+ .iso_out_incomplete = usb_dfu_iso_out_incomplete, -+}; -+ -+void usb_dfu_register(usb_handle_t *pdev, usb_dfu_handle_t *phandle) -+{ -+ pdev->class = (usb_class_t *)&USBD_DFU_initvalue; -+ pdev->class_data = phandle; -+ -+ phandle->dev_state = DFU_STATE_IDLE; -+ phandle->dev_status = DFU_ERROR_NONE; -+} -+ -+int usb_dfu_loop(usb_handle_t *pdev, const usb_dfu_media_t *pmedia) -+{ -+ uint32_t it_count; -+ usb_status_t ret; -+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data; -+ -+ hdfu->callback = pmedia; -+ usb_dfu_detach_req = false; -+ /* Continue to handle USB core IT to assure complete data transmission */ -+ it_count = 100U; -+ -+ /* DFU infinite loop until DETACH_REQ */ -+ while (it_count != 0U) { -+ ret = usb_core_handle_it(pdev); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ /* detach request received */ -+ if (usb_dfu_detach_req) { -+ it_count--; -+ } -+ } -+ -+ return 0; -+} -diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk -index 578bd59876..4d1f63b4b4 100644 ---- a/make_helpers/defaults.mk -+++ b/make_helpers/defaults.mk -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2016-2020, ARM Limited. All rights reserved. -+# Copyright (c) 2016-2021, ARM Limited. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -126,6 +126,9 @@ ENC_KEY := 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef - # Default dummy nonce for firmware encryption - ENC_NONCE := 1234567890abcdef12345678 - -+# Flag to enable exception debug for AARCH32 -+AARCH32_EXCEPTION_DEBUG := 0 -+ - # Build flag to treat usage of deprecated platform and framework APIs as error. - ERROR_DEPRECATED := 0 - -@@ -323,8 +326,5 @@ RAS_TRAP_LOWER_EL_ERR_ACCESS := 0 - # Build option to create cot descriptors using fconf - COT_DESC_IN_DTB := 0 - --# Build option to provide openssl directory path --OPENSSL_DIR := /usr -- - # Build option to use the SP804 timer instead of the generic one - USE_SP804_TIMER := 0 -diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S -index 5b9cb59146..d2c20b4a7d 100644 ---- a/plat/common/aarch32/platform_helpers.S -+++ b/plat/common/aarch32/platform_helpers.S -@@ -8,6 +8,11 @@ - #include - - .weak plat_report_exception -+#if AARCH32_EXCEPTION_DEBUG -+ .weak plat_report_undef_inst -+ .weak plat_report_prefetch_abort -+ .weak plat_report_data_abort -+#endif - .weak plat_reset_handler - .weak plat_disable_acp - .weak bl1_plat_prepare_exit -@@ -23,6 +28,35 @@ func plat_report_exception - bx lr - endfunc plat_report_exception - -+#if AARCH32_EXCEPTION_DEBUG -+ /* ----------------------------------------------------- -+ * Placeholder function which should be redefined by -+ * each platform. -+ * ----------------------------------------------------- -+ */ -+func plat_report_undef_inst -+ bx lr -+endfunc plat_report_undef_inst -+ -+ /* ----------------------------------------------------- -+ * Placeholder function which should be redefined by -+ * each platform. -+ * ----------------------------------------------------- -+ */ -+func plat_report_prefetch_abort -+ bx lr -+endfunc plat_report_prefetch_abort -+ -+ /* ----------------------------------------------------- -+ * Placeholder function which should be redefined by -+ * each platform. -+ * ----------------------------------------------------- -+ */ -+func plat_report_data_abort -+ bx lr -+endfunc plat_report_data_abort -+#endif -+ - /* ----------------------------------------------------- - * Placeholder function which should be redefined by - * each platform. -diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c -index 89b77ba6ce..5bbd73bd94 100644 ---- a/plat/common/plat_bl_common.c -+++ b/plat/common/plat_bl_common.c -@@ -69,7 +69,7 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) - return 0; - } - --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 -index 3ec7d4048a..23794db963 100644 ---- a/plat/st/common/bl2_io_storage.c -+++ b/plat/st/common/bl2_io_storage.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 - */ -@@ -13,7 +13,8 @@ - #include - #include - #include --#include -+#include -+#include - #include - #include - #include -@@ -22,28 +23,29 @@ - #include - #include - #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; -+uintptr_t fip_dev_handle; -+uintptr_t storage_dev_handle; - --static uintptr_t image_dev_handle; --static uintptr_t storage_dev_handle; -+static const io_dev_connector_t *fip_dev_con; -+static uint32_t nand_bkp_offset; - - #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 = { -@@ -76,6 +78,7 @@ static io_mtd_dev_spec_t nand_dev_spec = { - .ops = { - .init = nand_raw_init, - .read = nand_read, -+ .seek = nand_seek_bb - }, - }; - -@@ -87,6 +90,7 @@ static io_mtd_dev_spec_t spi_nand_dev_spec = { - .ops = { - .init = spi_nand_init, - .read = nand_read, -+ .seek = nand_seek_bb - }, - }; - #endif -@@ -95,146 +99,21 @@ static io_mtd_dev_spec_t spi_nand_dev_spec = { - static const io_dev_connector_t *spi_dev_con; - #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, -+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER -+static const io_dev_connector_t *memmap_dev_con; - #endif -- IMG_IDX_NUM --}; - --static struct stm32image_device_info stm32image_dev_info_spec __unused = { -- .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 = { -+io_block_spec_t image_block_spec = { - .offset = 0, - .length = 0, - }; - --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); --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 -- }, --#if STM32MP_SDMMC || STM32MP_EMMC -- [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) -+int open_fip(const uintptr_t spec) - { -- return io_dev_init(image_dev_handle, 0); -+ return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); - } - --static int open_storage(const uintptr_t spec) -+int open_storage(const uintptr_t spec) - { - return io_dev_init(storage_dev_handle, 0); - } -@@ -248,17 +127,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"); -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI: -+ INFO("Using SPI NOR\n"); - break; - 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: -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI: - INFO("Using SPI NAND\n"); - break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ INFO("Using UART\n"); -+ break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ INFO("Using USB\n"); -+ break; - default: -- ERROR("Boot interface not found\n"); -+ ERROR("Boot interface %u not found\n", -+ boot_context->boot_interface_selected); - panic(); - break; - } -@@ -273,11 +159,8 @@ 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; - struct stm32_sdmmc2_params params; - struct mmc_device_info device_info; -- const partition_entry_t *entry; - - zeromem(&device_info, sizeof(struct mmc_device_info)); - zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); -@@ -304,6 +187,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); -@@ -319,44 +206,6 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type, - 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); - } - #endif /* STM32MP_SDMMC || STM32MP_EMMC */ - -@@ -364,8 +213,6 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type, - 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); -@@ -378,38 +225,6 @@ static void boot_spi_nor(boot_api_context_t *boot_context) - (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 */ - -@@ -417,8 +232,6 @@ static void boot_spi_nor(boot_api_context_t *boot_context) - 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); -@@ -432,37 +245,7 @@ static void boot_fmc2_nand(boot_api_context_t *boot_context) - &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); -+ nand_bkp_offset = nand_dev_spec.erase_size; - } - #endif /* STM32MP_RAW_NAND */ - -@@ -470,8 +253,6 @@ static void boot_fmc2_nand(boot_api_context_t *boot_context) - 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); -@@ -485,40 +266,57 @@ static void boot_spi_nand(boot_api_context_t *boot_context) - &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 -+ nand_bkp_offset = spi_nand_dev_spec.erase_size; -+} -+#endif /* STM32MP_SPI_NAND */ -+ -+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER -+static void mmap_io_setup(void) -+{ -+ int io_result __unused; - -- io_result = register_io_dev_stm32image(&stm32image_dev_con); -+ io_result = register_io_dev_memmap(&memmap_dev_con); - assert(io_result == 0); - -- io_result = io_dev_open(stm32image_dev_con, -- (uintptr_t)&stm32image_dev_info_spec, -- &image_dev_handle); -+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, -+ &storage_dev_handle); - assert(io_result == 0); - } --#endif /* STM32MP_SPI_NAND */ -+#endif -+ -+#if STM32MP_UART_PROGRAMMER -+static void stm32cubeprogrammer_uart(unsigned int image_id) -+{ -+ int ret __unused; -+ boot_api_context_t *boot_context = -+ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); -+ uintptr_t uart_base; -+ -+ uart_base = get_uart_address(boot_context->boot_interface_instance); -+ ret = stm32cubeprog_uart_load(image_id, uart_base, FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE, -+ DWL_BUFFER_BASE, DWL_BUFFER_SIZE); -+ assert(ret == 0); -+ -+ flush_dcache_range(FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE); -+} -+#endif -+ -+#if STM32MP_USB_PROGRAMMER -+static void stm32cubeprogrammer_usb(unsigned int image_id) -+{ -+ usb_handle_t *pdev; -+ int ret __unused; -+ -+ /* init USB on platform */ -+ pdev = usb_dfu_plat_init(); -+ -+ ret = stm32cubeprog_usb_load(image_id, pdev, FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE, -+ DWL_BUFFER_BASE, DWL_BUFFER_SIZE); -+ assert(ret == 0); -+ -+ flush_dcache_range(FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE); -+} -+#endif - - void stm32mp_io_setup(void) - { -@@ -534,12 +332,11 @@ void stm32mp_io_setup(void) - boot_context->boot_partition_used_toboot); - } - -- io_result = register_io_dev_dummy(&dummy_dev_con); -+ io_result = register_io_dev_fip(&fip_dev_con); - assert(io_result == 0); - -- io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, -- &dummy_dev_handle); -- assert(io_result == 0); -+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, -+ &fip_dev_handle); - - switch (boot_context->boot_interface_selected) { - #if STM32MP_SDMMC -@@ -555,7 +352,7 @@ void stm32mp_io_setup(void) - break; - #endif - #if STM32MP_SPI_NOR -- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI: - dmbsy(); - boot_spi_nor(boot_context); - break; -@@ -567,19 +364,106 @@ void stm32mp_io_setup(void) - break; - #endif - #if STM32MP_SPI_NAND -- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI: - dmbsy(); - boot_spi_nand(boot_context); - break; - #endif -- -+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER -+#if STM32MP_UART_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+#endif -+#if STM32MP_USB_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+#endif -+ dmbsy(); -+ mmap_io_setup(); -+ break; -+#endif - default: - ERROR("Boot interface %d not supported\n", - boot_context->boot_interface_selected); -+ panic(); - break; - } - } - -+int bl2_plat_handle_pre_image_load(unsigned int image_id) -+{ -+ static bool gpt_init_done __unused; -+ uint16_t boot_itf = stm32mp_get_boot_itf_selected(); -+ -+ switch (boot_itf) { -+#if STM32MP_SDMMC || STM32MP_EMMC -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: -+ if (!gpt_init_done) { -+ const partition_entry_t *entry; -+ -+ partition_init(GPT_IMAGE_ID); -+ entry = get_partition_entry(FIP_IMAGE_NAME); -+ if (entry == NULL) { -+ ERROR("Could NOT find the %s partition!\n", -+ FIP_IMAGE_NAME); -+ return -ENOENT; -+ } -+ -+ image_block_spec.offset = entry->start; -+ image_block_spec.length = entry->length; -+ -+ gpt_init_done = true; -+ } -+ -+ break; -+#endif -+ -+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND -+#if STM32MP_RAW_NAND -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: -+#endif -+#if STM32MP_SPI_NAND -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI: -+#endif -+ image_block_spec.offset = STM32MP_NAND_FIP_OFFSET; -+ break; -+#endif -+ -+#if STM32MP_SPI_NOR -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI: -+ image_block_spec.offset = STM32MP_NOR_FIP_OFFSET; -+ break; -+#endif -+ -+#if STM32MP_UART_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ if (image_id == FW_CONFIG_ID) { -+ stm32cubeprogrammer_uart(FIP_IMAGE_ID); -+ /* BL33 at SSBL load address */ -+ image_block_spec.offset = DWL_BUFFER_BASE; -+ image_block_spec.length = DWL_BUFFER_SIZE; -+ } -+ break; -+#endif -+ -+#if STM32MP_USB_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ if (image_id == FW_CONFIG_ID) { -+ stm32cubeprogrammer_usb(FIP_IMAGE_ID); -+ /* BL33 at SSBL load address */ -+ image_block_spec.offset = DWL_BUFFER_BASE; -+ image_block_spec.length = DWL_BUFFER_SIZE; -+ } -+ break; -+#endif -+ -+ default: -+ ERROR("FIP Not found\n"); -+ panic(); -+ } -+ -+ return 0; -+} -+ - /* - * Return an IO device handle and specification which can be used to access - * an image. Use this to enforce platform load policy. -@@ -590,9 +474,7 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, - int rc; - const struct plat_io_policy *policy; - -- assert(image_id < ARRAY_SIZE(policies)); -- -- policy = &policies[image_id]; -+ policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id); - rc = policy->check(policy->image_spec); - if (rc == 0) { - *image_spec = policy->image_spec; -@@ -601,3 +483,33 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, - - return rc; - } -+ -+/* -+ * This function shall return 0 if it cannot find an alternate -+ * image to be loaded or it returns 1 otherwise. -+ */ -+int plat_try_next_boot_source(unsigned int image_id) -+{ -+ static unsigned int backup_id; -+ static unsigned int backup_nb; -+ -+ /* No backup available */ -+ if (nand_bkp_offset == 0U) { -+ return 0; -+ } -+ -+ if (backup_id != image_id) { -+ backup_nb = 0; -+ backup_id = image_id; -+ } -+ -+ backup_nb++; -+ -+ if (backup_nb >= PLATFORM_MTD_BACKUP_BLOCKS) { -+ return 0; -+ } -+ -+ image_block_spec.offset += nand_bkp_offset; -+ -+ return 1; -+} -diff --git a/plat/st/common/bl2_stm32_io_storage.c b/plat/st/common/bl2_stm32_io_storage.c -new file mode 100644 -index 0000000000..5e7ecfad48 ---- /dev/null -+++ b/plat/st/common/bl2_stm32_io_storage.c -@@ -0,0 +1,769 @@ -+/* -+ * Copyright (c) 2015-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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* IO devices */ -+#ifndef AARCH32_SP_OPTEE -+static const io_dev_connector_t *dummy_dev_con; -+static uintptr_t dummy_dev_handle; -+static uintptr_t dummy_dev_spec; -+#endif -+ -+static uintptr_t image_dev_handle; -+static uintptr_t storage_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, -+}; -+ -+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 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 || STM32MP_USB_PROGRAMMER -+static const io_dev_connector_t *memmap_dev_con; -+#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_core_partition_spec = { -+ .name = OPTEE_CORE_IMAGE_NAME, -+ .binary_type = OPTEE_CORE_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 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_CORE, -+ IMG_IDX_OPTEE_PAGED, -+#endif -+ IMG_IDX_NUM -+}; -+ -+static struct stm32image_device_info stm32image_dev_info_spec __unused = { -+ .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_CORE] = { -+ .name = OPTEE_CORE_IMAGE_NAME, -+ .binary_type = OPTEE_CORE_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 image_block_spec = { -+ .offset = 0, -+ .length = 0, -+}; -+ -+static const io_dev_connector_t *stm32image_dev_con __unused; -+ -+#ifndef AARCH32_SP_OPTEE -+static int open_dummy(const uintptr_t spec); -+#endif -+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[] = { -+#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_core_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 -+ }, -+#if STM32MP_SDMMC || STM32MP_EMMC -+ [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)&image_block_spec, -+ .check = open_storage -+ }, -+}; -+ -+#ifndef AARCH32_SP_OPTEE -+static int open_dummy(const uintptr_t spec) -+{ -+ return io_dev_init(dummy_dev_handle, 0); -+} -+#endif -+ -+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"); -+ break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: -+ INFO("Using EMMC\n"); -+ break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI: -+ INFO("Using SPI NOR\n"); -+ break; -+ 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_SPI: -+ INFO("Using SPI NAND\n"); -+ break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ INFO("Using UART\n"); -+ break; -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ INFO("Using USB\n"); -+ break; -+ default: -+ ERROR("Boot interface %u not found\n", -+ boot_context->boot_interface_selected); -+ panic(); -+ break; -+ } -+ -+ if (boot_context->boot_interface_instance != 0U) { -+ INFO(" Instance %d\n", boot_context->boot_interface_instance); -+ } -+} -+ -+static void stm32image_io_setup(void) -+{ -+ int io_result __unused; -+ -+ 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); -+} -+ -+#if STM32MP_SDMMC || STM32MP_EMMC -+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; -+ struct stm32_sdmmc2_params params; -+ struct mmc_device_info device_info; -+ const partition_entry_t *entry; -+ -+ zeromem(&device_info, sizeof(struct mmc_device_info)); -+ zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); -+ -+ device_info.mmc_dev_type = mmc_dev_type; -+ -+ 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; -+ } -+ -+ 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); -+ 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); -+} -+#endif /* STM32MP_SDMMC || STM32MP_EMMC */ -+ -+#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_CORE; -+ part = &stm32image_dev_info_spec.part_info[idx]; -+ part->part_offset = STM32MP_NOR_TEEX_OFFSET; -+ part->bkp_offset = 0U; -+#endif -+} -+#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_CORE; -+ part = &stm32image_dev_info_spec.part_info[idx]; -+ part->part_offset = STM32MP_NAND_TEEX_OFFSET; -+ part->bkp_offset = nand_dev_spec.erase_size; -+#endif -+} -+#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_CORE; -+ 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 -+} -+#endif /* STM32MP_SPI_NAND */ -+ -+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER -+static void mmap_io_setup(void) -+{ -+ int io_result __unused; -+ -+ io_result = register_io_dev_memmap(&memmap_dev_con); -+ assert(io_result == 0); -+ -+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, -+ &storage_dev_handle); -+ assert(io_result == 0); -+} -+ -+static void stm32image_mmap_setup(void) -+{ -+ uint8_t idx; -+ struct stm32image_part_info *part; -+ -+ stm32image_dev_info_spec.device_size = DWL_BUFFER_SIZE; -+ -+ idx = IMG_IDX_BL33; -+ part = &stm32image_dev_info_spec.part_info[idx]; -+ part->part_offset = 0; -+ part->bkp_offset = 0; -+} -+#endif -+ -+#if STM32MP_UART_PROGRAMMER -+static void stm32cubeprogrammer_uart(unsigned int image_id) -+{ -+ int ret __unused; -+ boot_api_context_t *boot_context = -+ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); -+ uintptr_t uart_base; -+ -+ uart_base = get_uart_address(boot_context->boot_interface_instance); -+ ret = stm32cubeprog_uart_load(image_id, uart_base, FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE, -+ DWL_BUFFER_BASE, DWL_BUFFER_SIZE); -+ assert(ret == 0); -+ -+ flush_dcache_range(FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE); -+} -+#endif -+ -+#if STM32MP_USB_PROGRAMMER -+static void stm32cubeprogrammer_usb(unsigned int image_id) -+{ -+ usb_handle_t *pdev; -+ int ret __unused; -+ -+ /* init USB on platform */ -+ pdev = usb_dfu_plat_init(); -+ -+ ret = stm32cubeprog_usb_load(image_id, pdev, FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE, -+ DWL_BUFFER_BASE, DWL_BUFFER_SIZE); -+ assert(ret == 0); -+ -+ flush_dcache_range(FLASHLAYOUT_BASE, FLASHLAYOUT_SIZE); -+} -+#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); -+ } -+ -+#ifndef AARCH32_SP_OPTEE -+ 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); -+#endif -+ -+ switch (boot_context->boot_interface_selected) { -+#if STM32MP_SDMMC -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: -+ dmbsy(); -+ boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); -+ stm32image_io_setup(); -+ break; -+#endif -+#if STM32MP_EMMC -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: -+ dmbsy(); -+ boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); -+ stm32image_io_setup(); -+ break; -+#endif -+#if STM32MP_SPI_NOR -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI: -+ dmbsy(); -+ boot_spi_nor(boot_context); -+ stm32image_io_setup(); -+ break; -+#endif -+#if STM32MP_RAW_NAND -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: -+ dmbsy(); -+ boot_fmc2_nand(boot_context); -+ stm32image_io_setup(); -+ break; -+#endif -+#if STM32MP_SPI_NAND -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI: -+ dmbsy(); -+ boot_spi_nand(boot_context); -+ stm32image_io_setup(); -+ break; -+#endif -+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER -+#if STM32MP_UART_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+#endif -+#if STM32MP_USB_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+#endif -+ dmbsy(); -+ mmap_io_setup(); -+ stm32image_mmap_setup(); -+ stm32image_io_setup(); -+ break; -+#endif -+ default: -+ ERROR("Boot interface %d not supported\n", -+ boot_context->boot_interface_selected); -+ panic(); -+ break; -+ } -+} -+ -+int bl2_plat_handle_pre_image_load(unsigned int image_id) -+{ -+ boot_api_context_t *boot_context = -+ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); -+ -+ switch (boot_context->boot_interface_selected) { -+#if STM32MP_UART_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ if (image_id == BL33_IMAGE_ID) { -+ stm32cubeprogrammer_uart(STM32_IMAGE_ID); -+ /* BL33 at SSBL load address */ -+ image_block_spec.offset = DWL_BUFFER_BASE; -+ image_block_spec.length = DWL_BUFFER_SIZE; -+ } -+ break; -+#endif -+#if STM32MP_USB_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ if (image_id == BL33_IMAGE_ID) { -+ stm32cubeprogrammer_usb(STM32_IMAGE_ID); -+ /* BL33 at SSBL load address */ -+ image_block_spec.offset = DWL_BUFFER_BASE; -+ image_block_spec.length = DWL_BUFFER_SIZE; -+ } -+ break; -+#endif -+ default: -+ break; -+ } -+ -+ return 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; -+} -+ -+/* -+ * This function shall return 0 if it cannot find an alternate -+ * image to be loaded and any non-zero value otherwise. -+ */ -+int plat_try_next_boot_source(unsigned int image_id) -+{ -+ 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)); -+ -+ if (backup_id != image_id) { -+ backup_id = image_id; -+ backup_nb = 0; -+ } -+ -+ 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/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h -new file mode 100644 -index 0000000000..947ad43aea ---- /dev/null -+++ b/plat/st/common/include/stm32cubeprogrammer.h -@@ -0,0 +1,67 @@ -+/* -+ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32CUBEPROGRAMMER_H -+#define STM32CUBEROGRAMMER_H -+ -+/* Phase definition */ -+#define PHASE_FLASHLAYOUT 0U -+#define PHASE_FSBL1 1U -+#define PHASE_FSBL2 2U -+#define PHASE_SSBL 3U -+#define PHASE_CMD 0xF1U -+#define PHASE_SSP 0xF3U -+#define PHASE_RESET 0xFFU -+ -+/* Command definition */ -+#define GET_CMD_COMMAND 0x00U -+#define GET_VER_COMMAND 0x01U -+#define GET_ID_COMMAND 0x02U -+#define PHASE_COMMAND 0x03U -+#define READ_PART_COMMAND 0x12U -+#define START_COMMAND 0x21U -+#define DOWNLOAD_COMMAND 0x31U -+ -+/* Answer defines */ -+#define INIT_BYTE 0x7FU -+#define ACK_BYTE 0x79U -+#define NACK_BYTE 0x1FU -+#define ABORT 0x5FU -+ -+#define DEVICE_ID_BYTE1 0x05U -+#define DEVICE_ID_BYTE2 0x00U -+ -+/* Functions provided by plat */ -+uint8_t usb_dfu_get_phase(uint8_t alt); -+ -+typedef struct usb_handle usb_handle_t; -+int stm32cubeprog_usb_load(unsigned int image_id, -+ usb_handle_t *usb_core_handle, -+ uintptr_t flashlayout_base, -+ size_t flashlayout_len, -+ uintptr_t ssbl_base, -+ size_t ssbl_len); -+ -+int stm32cubeprog_uart_load(unsigned int image_id, -+ uintptr_t instance, -+ uintptr_t flashlayout_base, -+ size_t flashlayout_len, -+ uintptr_t ssbl_base, -+ size_t ssbl_len); -+ -+int stm32cubeprog_usb_ssp(usb_handle_t *usb_core_handle, -+ uintptr_t cert_base, -+ size_t cert_len, -+ uintptr_t ssp_base, -+ size_t ssp_len); -+ -+int stm32cubeprog_uart_ssp(uintptr_t instance, -+ uintptr_t cert_base, -+ size_t cert_len, -+ uintptr_t ssp_base, -+ size_t ssp_len); -+ -+#endif /* STM32CUBEROGRAMMER_H */ -diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h -deleted file mode 100644 -index 3075d18ac7..0000000000 ---- 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 -index feeb4a790d..022e22742a 100644 ---- a/plat/st/common/include/stm32mp_common.h -+++ b/plat/st/common/include/stm32mp_common.h -@@ -7,16 +7,26 @@ - #ifndef STM32MP_COMMON_H - #define STM32MP_COMMON_H - -+#include - #include - - #include - -+void __dead2 stm32mp_plat_reset(int cpu); -+ - /* 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); -+uint16_t stm32mp_get_boot_itf_selected(void); -+uint32_t stm32mp_get_boot_action(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); -+const char *stm32mp_get_vdd_supply_name(void); -+const char *stm32mp_get_usb_phy_supply_name(void); - - /* Return the base address of the DDR controller */ - uintptr_t stm32mp_ddrctrl_base(void); -@@ -30,9 +40,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); -+ - /* 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); -+ -+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 +67,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 || defined(IMAGE_BL32) -+/* Get the UART address from its instance number */ -+uintptr_t get_uart_address(uint32_t instance_nb); -+#endif -+ - /* - * Platform util functions for the GPIO driver - * @bank: Target GPIO bank ID as per DT bindings -@@ -64,24 +92,26 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank); - /* Return node offset for target GPIO bank ID @bank or a FDT error code */ - int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank); - -+/* Get the chip revision */ -+int stm32mp_get_chip_version(uint32_t *chip_version); -+ -+/* Get SOC name */ -+#define STM32_SOC_NAME_SIZE 20 -+void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]); -+ - /* Print CPU information */ - void stm32mp_print_cpuinfo(void); - - /* Print board information */ - void stm32mp_print_boardinfo(void); - --/* -- * 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); --void stm32mp_clk_enable(unsigned long id); --void stm32mp_clk_disable(unsigned long id); --unsigned long stm32mp_clk_get_rate(unsigned long id); -+/* Check HW CPU OPP support */ -+bool stm32mp_supports_cpu_opp(uint32_t opp_id); - - /* Initialise the IO layer and register platform IO devices */ - void stm32mp_io_setup(void); - -+#if STM32MP_USE_STM32IMAGE - /* - * Check that the STM32 header of a .stm32 binary image is valid - * @param header: pointer to the stm32 image header -@@ -89,6 +119,13 @@ void stm32mp_io_setup(void); - * @return: 0 on success, negative value in case of error - */ - int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer); -+#endif -+ -+#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 - - /* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */ - int stm32mp_map_ddr_non_cacheable(void); -diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h -index e3b4e597ee..0ff30a3827 100644 ---- a/plat/st/common/include/stm32mp_dt.h -+++ b/plat/st/common/include/stm32mp_dt.h -@@ -1,6 +1,6 @@ - /* - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -- * 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,9 @@ - #define STM32MP_DT_H - - #include -+#include -+ -+#include - - #define DT_DISABLED U(0) - #define DT_NON_SECURE U(1) -@@ -25,16 +28,25 @@ struct dt_node_info { - /******************************************************************************* - * Function and variable prototypes - ******************************************************************************/ --int dt_open_and_check(void); -+int dt_open_and_check(uintptr_t dt_addr); - 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); - 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_match_instance_by_compatible(const char *compatible, uintptr_t address); - uint32_t dt_get_ddr_size(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); -+const char *dt_get_vdd_regulator_name(void); -+const char *dt_get_cpu_regulator_name(void); -+const char *dt_get_usb_phy_regulator_name(void); - const char *dt_get_board_model(void); - int fdt_get_gpio_bank_pin_count(unsigned int bank); - -diff --git a/plat/st/common/include/stm32mp_fconf_getter.h b/plat/st/common/include/stm32mp_fconf_getter.h -new file mode 100644 -index 0000000000..09d853f8f3 ---- /dev/null -+++ b/plat/st/common/include/stm32mp_fconf_getter.h -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_FCONF_GETTER -+#define STM32MP_FCONF_GETTER -+ -+#include -+ -+#include -+ -+/* IO policies */ -+#define stm32mp__io_policies_getter(id) __extension__ ({ \ -+ assert((id) < MAX_NUMBER_IDS); \ -+ &policies[id]; \ -+}) -+ -+struct plat_io_policy { -+ uintptr_t *dev_handle; -+ uintptr_t image_spec; -+ int (*check)(const uintptr_t spec); -+}; -+ -+extern struct plat_io_policy policies[]; -+int fconf_populate_stm32mp_io_policies(uintptr_t config); -+ -+#endif /* STM32MP_FCONF_GETTER */ -diff --git a/plat/st/common/include/stm32mp_io_storage.h b/plat/st/common/include/stm32mp_io_storage.h -new file mode 100644 -index 0000000000..48418a5bf6 ---- /dev/null -+++ b/plat/st/common/include/stm32mp_io_storage.h -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+#ifndef STM32MP_IO_STORAGE_H -+#define STM32MP_IO_STORAGE_H -+ -+#include -+ -+#include -+ -+/* IO devices handle */ -+extern uintptr_t storage_dev_handle; -+extern uintptr_t fip_dev_handle; -+ -+extern io_block_spec_t image_block_spec; -+ -+/* Function declarations */ -+int open_fip(const uintptr_t spec); -+int open_storage(const uintptr_t spec); -+ -+#endif /* STM32MP_IO_STORAGE_H */ -diff --git a/plat/st/common/include/stm32mp_shres_helpers.h b/plat/st/common/include/stm32mp_shres_helpers.h -index 8b786cc040..8b048284c6 100644 ---- a/plat/st/common/include/stm32mp_shres_helpers.h -+++ b/plat/st/common/include/stm32mp_shres_helpers.h -@@ -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); - - #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 0000000000..ec3e3525cf ---- /dev/null -+++ b/plat/st/common/stm32_gic.c -@@ -0,0 +1,223 @@ -+/* -+ * 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 -+ -+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) -+{ -+ 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; -+} -+ -+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 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/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c -new file mode 100644 -index 0000000000..3fd16aa39c ---- /dev/null -+++ b/plat/st/common/stm32cubeprogrammer_uart.c -@@ -0,0 +1,690 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define PROGRAMMER_TIMEOUT_US 20000U -+ -+/* USART bootloader protocol version V4.0 */ -+#define USART_BL_VERSION 0x40 -+#define UNDEFINED_DOWN_ADDR 0xFFFFFFFF -+ -+static const uint8_t command_tab[] = { -+ GET_CMD_COMMAND, -+ GET_VER_COMMAND, -+ GET_ID_COMMAND, -+ PHASE_COMMAND, -+#if STM32MP_SSP -+ READ_PART_COMMAND, -+#endif -+ START_COMMAND, -+ DOWNLOAD_COMMAND -+}; -+ -+/* STM32CubeProgrammer over UART handle */ -+struct stm32prog_uart_handle_s { -+ struct stm32_uart_handle_s uart; -+ uint32_t packet; -+ uint8_t *addr; -+ uint32_t len; -+ uint8_t phase; -+#if STM32MP_SSP -+ uintptr_t cert_base; -+ size_t cert_len; -+#endif -+ /* error msg buffer: max 255 in UART protocol, reduced in TF-A */ -+ uint8_t error[64]; -+} handle; -+ -+/* Trace and handle unrecoverable UART protocol error */ -+#define STM32PROG_ERROR(...) \ -+ { \ -+ ERROR(__VA_ARGS__); \ -+ if (handle.phase != PHASE_RESET) { \ -+ snprintf((char *)&handle.error, sizeof(handle.error), __VA_ARGS__); \ -+ handle.phase = PHASE_RESET; \ -+ handle.addr = (uint8_t *)UNDEFINED_DOWN_ADDR; \ -+ handle.len = 0U; \ -+ handle.packet = 0U; \ -+ } \ -+ } -+ -+static int uart_write(const uint8_t *addr, uint16_t size) -+{ -+ while (size) { -+ if (stm32_uart_putc(&handle.uart, *addr) != 0) { -+ return -EIO; -+ } -+ -+ size--; -+ addr++; -+ } -+ -+ return 0; -+} -+ -+static int uart_write_8(uint8_t byte) -+{ -+ return stm32_uart_putc(&handle.uart, byte); -+} -+ -+static int uart_write_32(uint32_t value) -+{ -+ return uart_write((uint8_t *)&value, 4U); -+} -+ -+static int uart_read_8(uint8_t *byte) -+{ -+ int ret; -+ uint64_t timeout_ref = timeout_init_us(PROGRAMMER_TIMEOUT_US); -+ -+ do { -+ ret = stm32_uart_getc(&handle.uart); -+ if (ret == -EAGAIN) { -+ if (timeout_elapsed(timeout_ref)) { -+ return -ETIMEDOUT; -+ } -+ } else if (ret < 0) { -+ return ret; -+ } -+ } while (ret == -EAGAIN); -+ -+ *byte = (uint8_t)ret; -+ -+ return 0; -+} -+ -+static int uart_flush_and_nack(void) -+{ -+ int ret; -+ -+ /* read all pending data */ -+ do { -+ ret = stm32_uart_getc(&handle.uart); -+ } while (ret >= 0); -+ -+ return uart_write_8(NACK_BYTE); -+} -+ -+static inline int is_valid_header(fip_toc_header_t *header) -+{ -+ if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) { -+ return 1; -+ } else { -+ return 0; -+ } -+} -+ -+static int uart_receive_command(uint8_t *command) -+{ -+ uint8_t byte = 0U; -+ uint8_t xor = 0U; -+ unsigned int count; -+ bool found = false; -+ int ret; -+ -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* handle reconnection request */ -+ if (byte == INIT_BYTE) { -+ *command = byte; -+ return 0; -+ } -+ -+ for (count = 0U; count < ARRAY_SIZE(command_tab); count++) { -+ if (command_tab[count] == byte) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) { -+ VERBOSE("UART: Command unknown (byte=0x%x)\n", byte); -+ return -EPROTO; -+ } -+ -+ ret = uart_read_8(&xor); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if ((byte ^ xor) != 0xFF) { -+ VERBOSE("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n", -+ byte, xor); -+ return -EPROTO; -+ } -+ -+ *command = byte; -+ -+ return 0; -+} -+ -+static int get_cmd_command(void) -+{ -+ int ret; -+ const uint8_t msg[2] = { -+ sizeof(command_tab), /* Length of data - 1 */ -+ USART_BL_VERSION -+ }; -+ -+ ret = uart_write(msg, sizeof(msg)); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ return uart_write(command_tab, sizeof(command_tab)); -+} -+ -+static int get_version_command(void) -+{ -+ return uart_write_8(STM32_TF_VERSION); -+} -+ -+static int get_id_command(void) -+{ -+ const uint8_t msg[3] = { -+ sizeof(msg) - 1, -+ DEVICE_ID_BYTE1, -+ DEVICE_ID_BYTE2 -+ }; -+ -+ return uart_write(msg, sizeof(msg)); -+} -+ -+static int uart_send_phase(uint32_t address) -+{ -+ int ret; -+ uint8_t msg_size = 5U; /* Length of data - 1 */ -+ uint8_t error_size = 0U; -+ -+ /* additionnal information only for RESET phase */ -+ if (handle.phase == PHASE_RESET) { -+ error_size = strnlen((char *)&handle.error, sizeof(handle.error)); -+ } -+ -+ ret = uart_write_8(msg_size + error_size); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* Send the ID of next partition */ -+ ret = uart_write_8(handle.phase); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* Destination address */ -+ ret = uart_write_32(address); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = uart_write_8(error_size); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* Additional information: message error */ -+ if (error_size > 0U) { -+ ret = uart_write(handle.error, error_size); -+ } -+ -+ return ret; -+} -+ -+static int uart_download_part(void) -+{ -+ uint8_t operation = 0U; -+ uint8_t xor; -+ uint8_t byte = 0U; -+ uint32_t packet_number = 0U; -+ uint32_t packet_size = 0U; -+ uint32_t i = 0; -+ int ret; -+ -+ /* Get operation number */ -+ ret = uart_read_8(&operation); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ xor = operation; -+ -+ /* Get packet Number */ -+ for (i = 3U; i > 0U; i--) { -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ xor ^= byte; -+ packet_number = (packet_number << 8) | byte; -+ } -+ -+ if (packet_number != handle.packet) { -+ WARN("UART: Bad packet number receive: %i, expected %i\n", -+ packet_number, handle.packet); -+ return -EPROTO; -+ } -+ -+ /* Checksum */ -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (xor != byte) { -+ VERBOSE("UART: Download Command checksum xor: %x, received %x\n", -+ xor, byte); -+ return -EPROTO; -+ } -+ -+ ret = uart_write_8(ACK_BYTE); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ xor = byte; -+ packet_size = byte + 1U; -+ if (handle.len < packet_size) { -+ STM32PROG_ERROR("Download overflow at %p\n", handle.addr + packet_size); -+ return 0; -+ } -+ -+ for (i = 0U; i < packet_size; i++) { -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ *(handle.addr + i) = byte; -+ xor ^= byte; -+ } -+ -+ /* Checksum */ -+ ret = uart_read_8(&byte) != 0; -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (xor != byte) { -+ VERBOSE("UART: Download Data checksum xor: %x, received %x\n", -+ xor, byte); -+ return -EPROTO; -+ } -+ -+ /* packet treated */ -+ handle.packet++; -+ handle.addr += packet_size; -+ handle.len -= packet_size; -+ -+ return 0; -+} -+ -+static int uart_start_cmd(unsigned int image_id, uintptr_t buffer) -+{ -+ uint8_t byte = 0U; -+ uint8_t xor = 0U; -+ int8_t i; -+ uint32_t start_address = 0U; -+ int ret; -+ -+ /* Get address */ -+ for (i = 4; i > 0; i--) { -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ xor ^= byte; -+ start_address = (start_address << 8) | byte; -+ } -+ -+ /* Checksum */ -+ ret = uart_read_8(&byte); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (xor != byte) { -+ VERBOSE("UART: Start Command checksum xor: %x, received %x\n", -+ xor, byte); -+ return -EPROTO; -+ } -+ -+ if (start_address != UNDEFINED_DOWN_ADDR) { -+ STM32PROG_ERROR("Invalid start at %x, for phase %d\n", -+ start_address, handle.phase); -+ return 0; -+ } -+ -+#if !STM32MP_USE_STM32IMAGE -+ if (image_id == FIP_IMAGE_ID) { -+ if (!is_valid_header((fip_toc_header_t *)buffer)) { -+ STM32PROG_ERROR("FIP Header check failed at phase %d\n", -+ (uint32_t)buffer); -+ return -EIO; -+ } -+ -+ VERBOSE("FIP header looks OK.\n"); -+ } -+#else -+ if (image_id == STM32_IMAGE_ID) { -+ /* Verify header and checksum payload */ -+ ret = stm32mp_check_header((boot_api_image_header_t *)buffer, -+ buffer + sizeof(boot_api_image_header_t)); -+ if (ret != 0U) { -+ STM32PROG_ERROR("STM32IMAGE check error at %x\n", -+ (uint32_t)buffer); -+ return -EIO; -+ } -+ -+ VERBOSE("STM32 header looks OK.\n"); -+ } -+#endif -+ -+ return 0; -+} -+ -+#if STM32MP_SSP -+static int uart_read_part(void) -+{ -+ uint8_t byte = 0U; -+ uint8_t xor = 0U; -+ uint8_t partid = 0U; -+ uint16_t size = 0U; -+ uint32_t start_address = 0U; -+ uint32_t i; -+ size_t length; -+ uint8_t *buffer; -+ -+ /* Get partition id */ -+ if (uart_read_8(&partid) != 0) { -+ return -EIO; -+ } -+ -+ if ((partid != PHASE_FLASHLAYOUT) && (partid != PHASE_SSP)) { -+ return -EPERM; -+ } -+ -+ xor = partid; -+ -+ /* Get address */ -+ for (i = 4U; i > 0U; i--) { -+ if (uart_read_8(&byte) != 0) { -+ return -EIO; -+ } -+ -+ xor ^= byte; -+ start_address = (start_address << 8) | byte; -+ } -+ -+ /* Checksum */ -+ if (uart_read_8(&byte) != 0) { -+ return -EIO; -+ } -+ -+ if (xor != byte) { -+ WARN("UART: Start cmd: address checksum: %x != %x\n", -+ xor, byte); -+ return -EPROTO; -+ } -+ /* OFFSET != 0 not supported */ -+ if (start_address != 0U) { -+ return -EIO; -+ } -+ -+ uart_write_8(ACK_BYTE); -+ -+ /* Get number of bytes to send */ -+ if (uart_read_8(&byte) != 0) { -+ return -EIO; -+ } -+ -+ xor = byte; -+ -+ /* Send Size + 1 */ -+ size = byte++; -+ -+ /* Checksum */ -+ if (uart_read_8(&byte) != 0) { -+ return -EIO; -+ } -+ -+ if ((xor ^ byte) != 0xFF) { -+ WARN("UART: Start cmd: length checksum: %x != %x\n", xor, byte); -+ return -EPROTO; -+ } -+ -+ uart_write_8(ACK_BYTE); -+ -+ if (partid != PHASE_SSP) { -+ WARN("Not supported\n"); -+ return -EPROTO; -+ } -+ -+ length = handle.cert_len; -+ buffer = (uint8_t *)handle.cert_base; -+ -+ for (i = 0U; i < length; i++, buffer++) { -+ uart_write_8(*buffer); -+ } -+ for (; i < size; i++) { -+ uart_write_8(0x0); -+ } -+ -+ return 0; -+} -+#endif /* STM32MP_SSP */ -+ -+static int uart_read(unsigned int image_id, uint8_t id, uintptr_t buffer, size_t length) -+{ -+ bool start_done = false; -+ int ret; -+ uint8_t command = 0U; -+ -+ handle.phase = id; -+ handle.packet = 0U; -+ handle.addr = (uint8_t *)buffer; -+ handle.len = length; -+ -+ INFO("UART: read phase %i at 0x%lx size 0x%x\n", -+ id, buffer, length); -+ while (!start_done) { -+ -+ stm32_iwdg_refresh(); -+ -+ ret = uart_receive_command(&command); -+ if (ret != 0U) { -+ /* delay to wait STM32CubeProgrammer end of transmission */ -+ mdelay(2); -+ -+ ret = uart_flush_and_nack(); -+ if (ret != 0U) { -+ return ret; -+ } -+ -+ continue; -+ } -+ -+ uart_write_8(ACK_BYTE); -+ -+ switch (command) { -+ case INIT_BYTE: -+ INFO("UART: Connected\n"); -+ /* Nothing to do */ -+ continue; -+ -+ case GET_CMD_COMMAND: -+ ret = get_cmd_command(); -+ break; -+ -+ case GET_VER_COMMAND: -+ ret = get_version_command(); -+ break; -+ -+ case GET_ID_COMMAND: -+ ret = get_id_command(); -+ break; -+ -+ case PHASE_COMMAND: -+ ret = uart_send_phase((uint32_t)buffer); -+ if ((ret == 0U) && (handle.phase == PHASE_RESET)) { -+ start_done = true; -+ INFO("UART: Reset\n"); -+ } -+ break; -+ -+ case DOWNLOAD_COMMAND: -+ ret = uart_download_part(); -+ break; -+#if STM32MP_SSP -+ case READ_PART_COMMAND: -+ ret = uart_read_part(); -+ break; -+#endif -+ case START_COMMAND: -+ ret = uart_start_cmd(image_id, buffer); -+ if ((ret == 0U) && (handle.phase == id)) { -+ INFO("UART: Start phase %d\n", handle.phase); -+#if STM32MP_SSP -+ if (handle.phase == PHASE_SSP) { -+ handle.phase = PHASE_RESET; -+ break; -+ } -+#endif -+ start_done = true; -+ } -+ break; -+ -+ default: -+ /* Not supported command */ -+ WARN("UART: Unknown command\n"); -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (ret == 0U) { -+ ret = uart_write_8(ACK_BYTE); -+ } else { -+ ret = uart_flush_and_nack(); -+ } -+ -+ if (ret != 0U) { -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+/* Init UART: 115200, 8bit 1stop parity even and enable FIFO mode */ -+const struct stm32_uart_init_s init = { -+ .baud_rate = U(115200), -+ .word_length = STM32_UART_WORDLENGTH_9B, -+ .stop_bits = STM32_UART_STOPBITS_1, -+ .parity = STM32_UART_PARITY_EVEN, -+ .hw_flow_control = STM32_UART_HWCONTROL_NONE, -+ .mode = STM32_UART_MODE_TX_RX, -+ .over_sampling = STM32_UART_OVERSAMPLING_16, -+ .fifo_mode = STM32_UART_FIFOMODE_EN, -+}; -+ -+#if STM32MP_SSP -+int stm32cubeprog_uart_ssp(uintptr_t instance, -+ uintptr_t cert_base, -+ size_t cert_len, -+ uintptr_t ssp_base, -+ size_t ssp_len) -+{ -+ int ret; -+ -+ if (stm32_uart_init(&handle.uart, instance, &init) != 0U) { -+ return -EIO; -+ } -+ -+ /* NACK to synchronize STM32CubeProgrammer */ -+ ret = uart_flush_and_nack(); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (cert_base == UNDEFINED_DOWN_ADDR) { -+ /* Send Provisioning message to programmer for reboot */ -+ STM32PROG_ERROR("Provisioning\n"); -+ } else { -+ handle.cert_base = cert_base; -+ handle.cert_len = cert_len; -+ handle.phase = PHASE_SSP; -+ } -+ -+ return uart_read(MAX_IMAGE_IDS, handle.phase, ssp_base, ssp_len); -+ -+} -+#endif -+ -+int stm32cubeprog_uart_load(unsigned int image_id, -+ uintptr_t instance, -+ uintptr_t flashlayout_base, -+ size_t flashlayout_len, -+ uintptr_t ssbl_base, -+ size_t ssbl_len) -+{ -+ int ret; -+ -+ if (stm32_uart_init(&handle.uart, instance, &init) != 0U) { -+ return -EIO; -+ } -+ -+ /* -+ * The following NACK_BYTE is written because STM32CubeProgrammer has -+ * already sent its command before TF-A has reached this point, and -+ * because FIFO was not configured by BootROM. -+ * The byte in the UART_RX register is then the checksum and not the -+ * command. NACK_BYTE has to be written, so that the programmer will -+ * re-send the good command. -+ */ -+ ret = uart_flush_and_nack(); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* Get FlashLayout with PhaseId=0 */ -+ if (flashlayout_len > 0U) { -+ ret = uart_read(STM32_IMAGE_ID, PHASE_FLASHLAYOUT, -+ flashlayout_base, flashlayout_len); -+ if (ret != 0U) { -+ return ret; -+ } -+ } -+ -+ ret = uart_read(image_id, PHASE_SSBL, ssbl_base, ssbl_len); -+ -+ return ret; -+} -diff --git a/plat/st/common/stm32cubeprogrammer_usb.c b/plat/st/common/stm32cubeprogrammer_usb.c -new file mode 100644 -index 0000000000..eefe6413b5 ---- /dev/null -+++ b/plat/st/common/stm32cubeprogrammer_usb.c -@@ -0,0 +1,352 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+/* Undefined download address */ -+#define UNDEFINED_DOWN_ADDR 0xFFFFFFFF -+ -+#define USB_STATE_READY 0 -+#define USB_STATE_WRITTEN 1 -+ -+#define USB_DFU_MAX_XFER_SIZE USBD_DFU_XFER_SIZE -+ -+typedef struct { -+ unsigned int image_id; -+ uint8_t phase; -+ uintptr_t base; -+ size_t len; -+ uintptr_t address; -+ /* parameter */ -+ uintptr_t ssbl_base; -+ size_t ssbl_len; -+#if STM32MP_SSP -+ uintptr_t cert_base; -+ size_t cert_len; -+#endif -+ /* working buffer */ -+ uint8_t buffer[255]; -+} dfu_state_t; -+ -+static dfu_state_t dfu_state; -+ -+#define DFU_ERROR(...) \ -+ { \ -+ ERROR(__VA_ARGS__); \ -+ if (dfu->phase != PHASE_RESET) { \ -+ snprintf((char *)&dfu->buffer[9], \ -+ sizeof(dfu->buffer) - 9, __VA_ARGS__); \ -+ dfu->phase = PHASE_RESET; \ -+ dfu->address = UNDEFINED_DOWN_ADDR; \ -+ dfu->len = 0; \ -+ } \ -+ } -+ -+static inline bool is_valid_header(fip_toc_header_t *header) -+{ -+ if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0U)) { -+ return true; -+ } -+ -+ return false; -+} -+ -+static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, -+ void *user_data) -+{ -+ int result = 0; -+ uint32_t length = 0; -+ dfu_state_t *dfu = (dfu_state_t *)user_data; -+ -+ switch (usb_dfu_get_phase(alt)) { -+ case PHASE_CMD: -+ /* Get Pḧase */ -+#if STM32MP_SSP -+ if (dfu->phase == PHASE_SSP) { -+ dfu->buffer[0] = PHASE_FLASHLAYOUT; -+ } else { -+ dfu->buffer[0] = dfu->phase; -+ } -+#else -+ dfu->buffer[0] = dfu->phase; -+#endif -+ dfu->buffer[1] = (uint8_t)(dfu->address); -+ dfu->buffer[2] = (uint8_t)(dfu->address >> 8); -+ dfu->buffer[3] = (uint8_t)(dfu->address >> 16); -+ dfu->buffer[4] = (uint8_t)(dfu->address >> 24); -+ dfu->buffer[5] = 0x00; -+ dfu->buffer[6] = 0x00; -+ dfu->buffer[7] = 0x00; -+ dfu->buffer[8] = 0x00; -+ length = 9; -+ if (dfu->phase == PHASE_FLASHLAYOUT && -+ dfu->address == UNDEFINED_DOWN_ADDR) { -+ INFO("Send detach request\n"); -+ dfu->buffer[9] = 0x01; -+ length = 10; -+ } -+ if (dfu->phase == PHASE_RESET) { -+ length = 8 + strnlen((char *)&dfu->buffer[9], -+ sizeof(dfu->buffer) - 9); -+ } -+ break; -+ -+#if STM32MP_SSP -+ case PHASE_SSP: -+ /* Fix phase to flashlayout phase */ -+ dfu->buffer[0] = PHASE_FLASHLAYOUT; -+ dfu->buffer[1] = (uint8_t)(dfu_state.cert_base); -+ dfu->buffer[2] = (uint8_t)(dfu_state.cert_base >> 8); -+ dfu->buffer[3] = (uint8_t)(dfu_state.cert_base >> 16); -+ dfu->buffer[4] = (uint8_t)(dfu_state.cert_base >> 24); -+ dfu->buffer[5] = 0x00; -+ dfu->buffer[6] = 0x00; -+ dfu->buffer[7] = 0x00; -+ dfu->buffer[8] = 0x00; -+ length = 9U; -+ -+ if ((length + dfu_state.cert_len) <= sizeof(dfu->buffer)) { -+ memcpy(&dfu->buffer[9], (uint8_t *)dfu_state.cert_base, -+ dfu_state.cert_len); -+ length += dfu_state.cert_len; -+ } -+ -+ break; -+#endif -+ default: -+ DFU_ERROR("phase ID :%i, alternate %i for phase %i\n", -+ dfu->phase, alt, usb_dfu_get_phase(alt)); -+ result = -EIO; -+ break; -+ } -+ -+ if (result == 0) { -+ *len = length; -+ *buffer = (uintptr_t)dfu->buffer; -+ } -+ -+ return result; -+} -+ -+static int dfu_callback_download(uint8_t alt, uintptr_t *buffer, uint32_t *len, -+ void *user_data) -+{ -+ dfu_state_t *dfu = (dfu_state_t *)user_data; -+ -+ if ((dfu->phase != usb_dfu_get_phase(alt)) || -+ (dfu->address == UNDEFINED_DOWN_ADDR)) { -+ DFU_ERROR("phase ID :%i, alternate %i, address %x\n", -+ dfu->phase, alt, (uint32_t)dfu->address); -+ return -EIO; -+ } -+ -+ VERBOSE("Download %d %lx %x\n", alt, dfu->address, *len); -+ *buffer = dfu->address; -+ dfu->address += *len; -+ -+ if (dfu->address - dfu->base > dfu->len) { -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int dfu_callback_manifestation(uint8_t alt, void *user_data) -+{ -+#if STM32MP_USE_STM32IMAGE -+ int result; -+#endif -+ boot_api_image_header_t *header __unused; -+ dfu_state_t *dfu = (dfu_state_t *)user_data; -+ -+ if (dfu->phase != usb_dfu_get_phase(alt)) { -+ ERROR("Manifestation phase ID :%i, alternate %i, address %lx\n", -+ dfu->phase, alt, dfu->address); -+ return -EIO; -+ } -+ -+ INFO("phase ID :%i, Manifestation %d at %lx\n", -+ dfu->phase, alt, dfu->address); -+ switch (dfu->phase) { -+#if STM32MP_SSP -+ case PHASE_SSP: -+ /* Configure End with request detach */ -+ dfu->phase = PHASE_FLASHLAYOUT; -+ dfu->address = UNDEFINED_DOWN_ADDR; -+ dfu->len = 0; -+ break; -+#else -+ case PHASE_FLASHLAYOUT: -+ header = (boot_api_image_header_t *)(dfu->base); -+ -+ /* TODO check data flush */ -+ flush_dcache_range((unsigned long)header, -+ header->image_length + -+ sizeof(boot_api_image_header_t)); -+ -+#if STM32MP_USE_STM32IMAGE -+ /* Verify header and checksum payload */ -+ INFO("Flashlayout Header check at %lx\n", -+ (uintptr_t)header); -+ result = stm32mp_check_header(header, -+ (unsigned long)header + -+ sizeof(boot_api_image_header_t)); -+ if (result != 0) { -+ DFU_ERROR("Header check failed for phase %d\n", alt); -+ return -EIO; -+ } -+#endif -+ /* Configure U-Boot loading */ -+ dfu->phase = PHASE_SSBL; -+ dfu->address = dfu->ssbl_base; -+ dfu->base = dfu->ssbl_base; -+ dfu->len = dfu->ssbl_len; -+ break; -+ -+ case PHASE_SSBL: -+#if !STM32MP_USE_STM32IMAGE -+ if (dfu->image_id == FIP_IMAGE_ID) { -+ if (!is_valid_header((fip_toc_header_t *)dfu->base)) { -+ DFU_ERROR("FIP Header check failed for phase %d\n", alt); -+ return -EIO; -+ } -+ -+ VERBOSE("FIP header looks OK.\n"); -+ } -+#else -+ if (dfu->image_id == STM32_IMAGE_ID) { -+ header = (boot_api_image_header_t *)dfu->base; -+ /* Verify header and checksum payload */ -+ result = stm32mp_check_header(header, -+ dfu->base + -+ sizeof(boot_api_image_header_t)); -+ if (result != 0) { -+ DFU_ERROR("STM32 Header check failed for phase %d\n", alt); -+ return -EIO; -+ } -+ -+ VERBOSE("STM32 header looks OK.\n"); -+ } -+#endif -+ /* Configure End with request detach */ -+ dfu->phase = PHASE_FLASHLAYOUT; -+ dfu->address = UNDEFINED_DOWN_ADDR; -+ dfu->len = 0; -+ break; -+#endif /* STM32MP_SSP */ -+ default: -+ DFU_ERROR("Unknown phase\n"); -+ } -+ -+ return 0; -+} -+ -+/* Open a connection to the USB device */ -+static const usb_dfu_media_t usb_dfu_fops = { -+ .upload = dfu_callback_upload, -+ .download = dfu_callback_download, -+ .manifestation = dfu_callback_manifestation, -+}; -+ -+#if STM32MP_SSP -+int stm32cubeprog_usb_ssp(usb_handle_t *usb_core_handle, -+ uintptr_t cert_base, -+ size_t cert_len, -+ uintptr_t ssp_base, -+ size_t ssp_len) -+{ -+ int ret; -+ -+ usb_core_handle->user_data = (void *)&dfu_state; -+ -+ INFO("DFU USB START...\n"); -+ ret = usb_core_start(usb_core_handle); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ if (cert_base == UNDEFINED_DOWN_ADDR) { -+ dfu_state_t *dfu = (dfu_state_t *)usb_core_handle->user_data; -+ -+ /* Send Provisioning message to programmer for reboot */ -+ DFU_ERROR("Provisioning\n"); -+ } else { -+ dfu_state.phase = PHASE_SSP; -+ dfu_state.image_id = MAX_IMAGE_IDS; -+ dfu_state.address = ssp_base; -+ dfu_state.base = ssp_base; -+ dfu_state.len = ssp_len; -+ dfu_state.cert_base = cert_base; -+ dfu_state.cert_len = cert_len; -+ } -+ -+ ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ INFO("DFU USB STOP...\n"); -+ ret = usb_core_stop(usb_core_handle); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ return 0; -+} -+#endif -+ -+int stm32cubeprog_usb_load(unsigned int image_id, -+ usb_handle_t *usb_core_handle, -+ uintptr_t flashlayout_base, -+ size_t flashlayout_len, -+ uintptr_t ssbl_base, -+ size_t ssbl_len) -+{ -+ int ret; -+ -+ usb_core_handle->user_data = (void *)&dfu_state; -+ -+ INFO("DFU USB START...\n"); -+ ret = usb_core_start(usb_core_handle); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ dfu_state.image_id = image_id; -+ dfu_state.ssbl_base = ssbl_base; -+ dfu_state.ssbl_len = ssbl_len; -+ -+ if (flashlayout_len) { -+ dfu_state.phase = PHASE_FLASHLAYOUT; -+ dfu_state.address = flashlayout_base; -+ dfu_state.base = flashlayout_base; -+ dfu_state.len = flashlayout_len; -+ } else { -+ dfu_state.phase = PHASE_SSBL; -+ dfu_state.address = ssbl_base; -+ dfu_state.base = ssbl_base; -+ dfu_state.len = ssbl_len; -+ } -+ -+ ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ INFO("DFU USB STOP...\n"); -+ ret = usb_core_stop(usb_core_handle); -+ if (ret != USBD_OK) { -+ return -EIO; -+ } -+ -+ return 0; -+} -diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c -deleted file mode 100644 -index 0ef6d54548..0000000000 ---- 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 89d8078386..3f385ca317 100644 ---- a/plat/st/common/stm32mp_common.c -+++ b/plat/st/common/stm32mp_common.c -@@ -12,9 +12,16 @@ - #include - #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; -@@ -25,11 +32,23 @@ unsigned int plat_get_syscnt_freq2(void) - return read_cntfrq_el0(); - } - -+#pragma weak stm32mp_plat_reset -+void __dead2 stm32mp_plat_reset(int cpu) -+{ -+ panic(); -+} -+ - static uintptr_t boot_ctx_address; -+static uint16_t boot_itf_selected; -+static uint32_t boot_action_saved; - - void stm32mp_save_boot_ctx_address(uintptr_t address) - { -+ boot_api_context_t *boot_context = (boot_api_context_t *)address; -+ - boot_ctx_address = address; -+ boot_itf_selected = boot_context->boot_interface_selected; -+ boot_action_saved = boot_context->boot_action; - } - - uintptr_t stm32mp_get_boot_ctx_address(void) -@@ -37,6 +56,16 @@ uintptr_t stm32mp_get_boot_ctx_address(void) - return boot_ctx_address; - } - -+uint16_t stm32mp_get_boot_itf_selected(void) -+{ -+ return boot_itf_selected; -+} -+ -+uint32_t stm32mp_get_boot_action(void) -+{ -+ return boot_action_saved; -+} -+ - uintptr_t stm32mp_ddrctrl_base(void) - { - return DDRCTRL_BASE; -@@ -65,45 +94,148 @@ bool stm32mp_lock_available(void) - return (read_sctlr() & c_m_bits) == c_m_bits; - } - --int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) -+void stm32mp_pwr_regs_lock(void) -+{ -+ if (stm32mp_lock_available()) { -+ spin_lock(&lock); -+ } -+} -+ -+void stm32mp_pwr_regs_unlock(void) - { -- uint32_t i; -- uint32_t img_checksum = 0U; -+ if (stm32mp_lock_available()) { -+ spin_unlock(&lock); -+ } -+} - -+#if STM32MP_USE_STM32IMAGE -+int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) -+{ - /* - * 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; - } -+#endif -+ -+/* Return CPU supply name */ -+const char *stm32mp_get_cpu_supply_name(void) -+{ -+ 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; -+} -+ -+/* Return VDD supply name */ -+const char *stm32mp_get_vdd_supply_name(void) -+{ -+ const char *supply = NULL; -+ -+ if (dt_pmic_status() > 0) { -+ const char *regulator = dt_get_vdd_regulator_name(); -+ -+ if (regulator != NULL) { -+ dt_pmic_find_supply(&supply, regulator); -+ } -+ } -+ -+ return supply; -+} -+ -+/* Return USB phy supply name */ -+const char *stm32mp_get_usb_phy_supply_name(void) -+{ -+ const char *supply = NULL; -+ -+ if (dt_pmic_status() > 0) { -+ const char *regulator = dt_get_usb_phy_regulator_name(); -+ -+ if (regulator != NULL) { -+ dt_pmic_find_supply(&supply, regulator); -+ } -+ } -+ -+ return supply; -+} -+ -+#if TRUSTED_BOARD_BOOT && STM32MP_USE_STM32IMAGE -+/* 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) -+{ -+ assert(latest_stm32_header == NULL); -+ -+ latest_stm32_header = header; -+} -+ -+/* Discard last loaded header */ -+void stm32mp_delete_loaded_header(void) -+{ -+ if (latest_stm32_header == NULL) { -+ return; -+ } -+ -+ zeromem(latest_stm32_header, sizeof(boot_api_image_header_t)); -+ latest_stm32_header = NULL; -+} -+ -+/* Get last loaded header */ -+boot_api_image_header_t *stm32mp_get_loaded_header(void) -+{ -+ assert(latest_stm32_header != NULL); -+ -+ return latest_stm32_header; -+} -+#endif /* TRUSTED_BOARD_BOOT */ - - int stm32mp_map_ddr_non_cacheable(void) - { - return mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, - STM32MP_DDR_MAX_SIZE, -- MT_NON_CACHEABLE | MT_RW | MT_NS); -+ MT_NON_CACHEABLE | MT_RW | MT_SECURE); - } - - int stm32mp_unmap_ddr(void) -diff --git a/plat/st/common/stm32mp_cot.c b/plat/st/common/stm32mp_cot.c -new file mode 100644 -index 0000000000..5f673fde78 ---- /dev/null -+++ b/plat/st/common/stm32mp_cot.c -@@ -0,0 +1,114 @@ -+/* -+ * 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 0000000000..de9601d2b8 ---- /dev/null -+++ b/plat/st/common/stm32mp_crypto_lib.c -@@ -0,0 +1,447 @@ -+/* -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+ -+#if !STM32MP_USE_STM32IMAGE -+#include -+#include -+#include -+#include -+#include -+#endif -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CRYPTO_HASH_MAX_SIZE 32U -+#define CRYPTO_SIGN_MAX_SIZE 64U -+#define CRYPTO_PUBKEY_MAX_SIZE 64U -+ -+struct stm32mp_auth_ops { -+ uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in, -+ uint8_t *signature, uint32_t ecc_algo); -+}; -+ -+static struct stm32mp_auth_ops auth_ops; -+ -+static void crypto_lib_init(void) -+{ -+ boot_api_context_t *boot_context = -+ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); -+ -+ if (!stm32mp_is_auth_supported()) { -+ return; -+ } -+ -+ auth_ops.verify_signature = -+ boot_context->bootrom_ecdsa_verify_signature; -+ -+ if (stm32_hash_register() != 0) { -+ panic(); -+ } -+} -+ -+#if STM32MP_USE_STM32IMAGE -+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_2MB_ALIGNED, MT_CODE | MT_SECURE); -+ if (result != 0) { -+ return result; -+ } -+ -+ /* 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_2MB_ALIGNED); -+ 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; -+} -+#else /* STM32MP_USE_STM32IMAGE */ -+int get_plain_pk_from_asn1(void *pk_ptr, unsigned int pk_len, void **plain_pk, -+ unsigned int *len, int *pk_alg) -+{ -+ int ret; -+ mbedtls_pk_context mbedtls_pk = {0}; -+ unsigned char *p, *end; -+ mbedtls_asn1_buf alg_params = {0}; -+ mbedtls_asn1_buf alg_oid = {0}; -+ -+ *plain_pk = NULL; -+ *len = 0U; -+ -+ /* Parse the public key */ -+ mbedtls_pk_init(&mbedtls_pk); -+ p = (unsigned char *)pk_ptr; -+ end = (unsigned char *)(p + pk_len); -+ -+ ret = mbedtls_asn1_get_tag(&p, end, len, -+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); -+ if (ret != 0) { -+ return -EINVAL; -+ } -+ -+ end = p + *len; -+ ret = mbedtls_asn1_get_alg(&p, end, &alg_oid, &alg_params); -+ if (ret != 0) { -+ VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret); -+ return -EINVAL; -+ } -+ -+ if (pk_alg != NULL) { -+ if ((strlen(MBEDTLS_OID_EC_GRP_SECP256R1) == alg_params.len) && -+ (memcmp(MBEDTLS_OID_EC_GRP_SECP256R1, alg_params.p, alg_params.len) == 0)) { -+ *pk_alg = BOOT_API_ECDSA_ALGO_TYPE_P256NIST; -+ } else { -+ *pk_alg = BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256; -+ } -+ } -+ -+ ret = mbedtls_asn1_get_bitstring_null(&p, end, len); -+ if (ret != 0) { -+ VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret); -+ return -EINVAL; -+ } -+ -+ /* we remove the ident (0x04) first byte. */ -+ if ((*len < 1U) || (p[0] != MBEDTLS_ASN1_OCTET_STRING)) { -+ VERBOSE("%s: not expected len or tag\n", __func__); -+ return -EINVAL; -+ } -+ -+ *len = *len - 1U; -+ *plain_pk = p + 1U; -+ -+ return 0; -+} -+ -+int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, -+ void **hashed_pk_ptr, unsigned int *hashed_pk_len) -+{ -+ return get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, hashed_pk_ptr, hashed_pk_len, NULL); -+} -+ -+static int get_plain_digest_from_asn1(void *digest_ptr, unsigned int digest_len, -+ uint8_t **out, size_t *out_len, mbedtls_md_type_t *md_alg) -+{ -+ int ret; -+ mbedtls_asn1_buf hash_oid, params; -+ size_t len; -+ unsigned char *p, *end; -+ -+ *out = NULL; -+ *out_len = 0U; -+ -+ /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ -+ p = (unsigned char *)digest_ptr; -+ end = p + digest_len; -+ ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | -+ MBEDTLS_ASN1_SEQUENCE); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* Get the hash algorithm */ -+ ret = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = mbedtls_oid_get_md_alg(&hash_oid, md_alg); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ /* Length of hash must match the algorithm's size */ -+ if (len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) { -+ return -1; -+ } -+ -+ *out = p; -+ *out_len = len; -+ -+ return 0; -+} -+ -+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[CRYPTO_HASH_MAX_SIZE]; -+ uint8_t sig[CRYPTO_SIGN_MAX_SIZE]; -+ uint8_t my_pk[CRYPTO_PUBKEY_MAX_SIZE]; -+ int ret; -+ size_t len; -+ mbedtls_asn1_sequence seq; -+ unsigned char *p, *end; -+ int curve_id; -+ mbedtls_asn1_buf sig_oid, sig_params; -+ mbedtls_md_type_t md_alg; -+ mbedtls_pk_type_t pk_alg; -+ -+ /* Get pointers to signature OID and parameters */ -+ p = (unsigned char *)sig_alg; -+ end = (unsigned char *)(p + sig_alg_len); -+ ret = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); -+ if (ret != 0) { -+ VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ /* Get the actual signature algorithm (MD + PK) */ -+ ret = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); -+ if (ret != 0) { -+ VERBOSE("%s: mbedtls_oid_get_sig_alg (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ if ((md_alg != MBEDTLS_MD_SHA256) || (pk_alg != MBEDTLS_PK_ECDSA)) { -+ VERBOSE("%s: md_alg=%d pk_alg=%d\n", __func__, md_alg, pk_alg); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ ret = get_plain_pk_from_asn1(pk_ptr, pk_len, &pk_ptr, &pk_len, &curve_id); -+ if (ret != 0) { -+ VERBOSE("%s: get_plain_pk_from_asn1 (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ /* We expect a known pk_len */ -+ if (pk_len != sizeof(my_pk)) { -+ VERBOSE("%s: pk_len=%d sizeof(my_pk)=%d)\n", __func__, pk_len, sizeof(my_pk)); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ /* Need to copy as auth_ops.verify_signature -+ * expects aligned public key. -+ */ -+ memcpy(my_pk, pk_ptr, sizeof(my_pk)); -+ -+ /* Get the signature (bitstring) */ -+ p = (unsigned char *)sig_ptr; -+ end = (unsigned char *)(p + sig_len); -+ ret = mbedtls_asn1_get_bitstring_null(&p, end, &len); -+ if (ret != 0) { -+ VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ /* Get r and s from sequence */ -+ ret = mbedtls_asn1_get_sequence_of(&p, end, &seq, MBEDTLS_ASN1_INTEGER); -+ if (ret != 0) { -+ VERBOSE("%s: mbedtls_asn1_get_sequence_of (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ /* We expect only 2 integers (r and s) from the sequence */ -+ if (seq.next->next != NULL) { -+ mbedtls_asn1_sequence *cur = seq.next; -+ mbedtls_asn1_sequence *next; -+ -+ VERBOSE("%s: nb seq != 2\n", __func__); -+ /* Free all the sequences */ -+ while (cur != NULL) { -+ next = cur->next; -+ mbedtls_free(cur); -+ cur = next; -+ } -+ -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ /* Integer sequence may (sometime) start with 0x00 as MSB, but we can only -+ * manage exactly 2*32 bytes, we remove this higher byte -+ * if there are not 00, we will fail either. -+ */ -+ memcpy(sig, seq.buf.p + seq.buf.len - sizeof(sig) / 2U, sizeof(sig) / 2U); -+ memcpy(sig + sizeof(sig) / 2U, -+ seq.next->buf.p + seq.next->buf.len - sizeof(sig) / 2U, -+ sizeof(sig) / 2U); -+ /* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */ -+ mbedtls_free(seq.next); -+ -+ /* Compute hash for the data covered by the signature */ -+ stm32_hash_init(HASH_SHA256); -+ -+ ret = stm32_hash_final_update((uint8_t *)data_ptr, data_len, image_hash); -+ if (ret != 0) { -+ VERBOSE("%s: stm32_hash_final_update (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE, -+ STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE); -+ if (ret != 0) { -+ VERBOSE("%s: mmap_add_dynamic_region (%d)\n", __func__, ret); -+ return CRYPTO_ERR_SIGNATURE; -+ } -+ -+ ret = auth_ops.verify_signature(image_hash, my_pk, sig, curve_id); -+ if (ret != BOOT_API_RETURN_OK) { -+ VERBOSE("%s: auth_ops.verify_signature (%d)\n", __func__, ret); -+ ret = CRYPTO_ERR_SIGNATURE; -+ } else { -+ ret = 0; -+ } -+ -+ mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED); -+ -+ return ret; -+} -+ -+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]; -+ unsigned char *p; -+ mbedtls_md_type_t md_alg; -+ size_t len; -+ -+ /* we receive an asn1 encapsulated digest, we flatten it */ -+ ret = get_plain_digest_from_asn1(digest_info_ptr, -+ digest_info_len, &p, &len, -+ &md_alg); -+ if ((ret != 0) || (md_alg != MBEDTLS_MD_SHA256)) { -+ return CRYPTO_ERR_HASH; -+ } -+ -+ digest_info_ptr = p; -+ digest_info_len = len; -+ -+ 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__); -+ return CRYPTO_ERR_HASH; -+ } -+ -+ ret = memcmp(calc_hash, digest_info_ptr, digest_info_len); -+ if (ret != 0) { -+ VERBOSE("%s: not expected digest\n", __func__); -+ ret = CRYPTO_ERR_HASH; -+ } -+ -+ return ret; -+} -+#endif -+ -+REGISTER_CRYPTO_LIB("stm32_crypto_lib", -+ crypto_lib_init, -+ crypto_verify_signature, -+ crypto_verify_hash, -+ NULL); -diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c -index 391e5f0547..a3584cbc12 100644 ---- a/plat/st/common/stm32mp_dt.c -+++ b/plat/st/common/stm32mp_dt.c -@@ -14,25 +14,22 @@ - #include - #include - #include --#include --#include - - #include - --static int fdt_checked; -- --static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE; -+static void *fdt; - - /******************************************************************************* - * 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) -+int dt_open_and_check(uintptr_t dt_addr) - { -- int ret = fdt_check_header(fdt); -+ int ret; - -+ ret = fdt_check_header((void *)dt_addr); - if (ret == 0) { -- fdt_checked = 1; -+ fdt = (void *)dt_addr; - } - - return ret; -@@ -45,11 +42,13 @@ int dt_open_and_check(void) - ******************************************************************************/ - int fdt_get_address(void **fdt_addr) - { -- if (fdt_checked == 1) { -- *fdt_addr = fdt; -+ if (fdt == NULL) { -+ return 0; - } - -- return fdt_checked; -+ *fdt_addr = fdt; -+ -+ return 1; - } - - /******************************************************************************* -@@ -115,6 +114,37 @@ static int fdt_get_node_parent_address_cells(int node) - } - #endif - -+/******************************************************************************* -+ * This function return interrupts from node. -+ ******************************************************************************/ -+int fdt_get_interrupt(int node, const fdt32_t **array, int *len, bool *extended) -+{ -+ uint8_t status = fdt_get_status(node); -+ -+ *extended = false; -+ -+ switch (status) { -+ case DT_SECURE: -+ *array = fdt_getprop(fdt, node, "interrupts-extended", len); -+ if (*array == NULL) { -+ *array = fdt_getprop(fdt, node, "interrupts", len); -+ } else { -+ *extended = true; -+ } -+ break; -+ -+ default: -+ *array = fdt_getprop(fdt, node, "secure-interrupts", len); -+ break; -+ } -+ -+ if (*array == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ 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. -@@ -203,21 +233,223 @@ int dt_get_stdout_uart_info(struct dt_node_info *info) - 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; -+ -+ 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. - ******************************************************************************/ - uint32_t dt_get_ddr_size(void) - { -+ static uint32_t size; - int node; - -+ if (size != 0U) { -+ return size; -+ } -+ - 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(fdt, node, "st,mem-size", 0); -+ size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U); -+ -+ flush_dcache_range((uintptr_t)&size, sizeof(uint32_t)); -+ -+ return size; -+} -+ -+/******************************************************************************* -+ * 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 fdt_node_offset_by_compatible(fdt, -1, 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; -+ int subnode; -+ uint32_t freq = 0U; -+ uint32_t voltage = 0U; -+ -+ assert(freq_khz != NULL); -+ assert(voltage_mv != 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 (read_freq > freq) { -+ freq = read_freq; -+ voltage = read_voltage; -+ } -+ } -+ -+ 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; -+ uint32_t idx = 0U; -+ -+ 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; - } - - /******************************************************************************* -@@ -226,22 +458,15 @@ uint32_t dt_get_ddr_size(void) - ******************************************************************************/ - uint32_t dt_get_pwr_vdd_voltage(void) - { -- int node, pwr_regulators_node; -+ 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; - } - -- pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators"); -- if (pwr_regulators_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; - } -@@ -259,6 +484,84 @@ uint32_t dt_get_pwr_vdd_voltage(void) - return fdt32_to_cpu(*cuint); - } - -+/******************************************************************************* -+ * This function return the real regulator name from DT. -+ ******************************************************************************/ -+static const char *dt_get_regulator_name(int node, const char *regu_name) -+{ -+ const fdt32_t *cuint; -+ -+ if ((node < 0) || (regu_name == NULL)) { -+ return NULL; -+ } -+ -+ cuint = fdt_getprop(fdt, node, regu_name, NULL); -+ if (cuint == NULL) { -+ return NULL; -+ } -+ -+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); -+ if (node < 0) { -+ return NULL; -+ } -+ -+ return (const char *)fdt_getprop(fdt, node, "regulator-name", NULL); -+} -+ -+/******************************************************************************* -+ * This function retrieves VDD regulator name from DT. -+ * Returns string taken from supply node, NULL otherwise. -+ ******************************************************************************/ -+const char *dt_get_vdd_regulator_name(void) -+{ -+ int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ -+ if (node < 0) { -+ return NULL; -+ } -+ -+ return dt_get_regulator_name(node, "vdd-supply"); -+} -+ -+/******************************************************************************* -+ * This function retrieves CPU regulator name from DT. -+ * Returns string taken from supply node, NULL otherwise. -+ ******************************************************************************/ -+const char *dt_get_cpu_regulator_name(void) -+{ -+ int node = fdt_path_offset(fdt, "/cpus/cpu@0"); -+ -+ if (node < 0) { -+ return NULL; -+ } -+ -+ return dt_get_regulator_name(node, "cpu-supply"); -+} -+ -+/******************************************************************************* -+ * This function retrieves USB phy regulator name from DT. -+ * Returns string taken from supply node, NULL otherwise. -+ ******************************************************************************/ -+const char *dt_get_usb_phy_regulator_name(void) -+{ -+ int node = fdt_node_offset_by_compatible(fdt, -1, DT_USBPHYC_COMPAT); -+ int subnode; -+ const char *reg_name = NULL; -+ -+ if (node < 0) { -+ return NULL; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ reg_name = dt_get_regulator_name(subnode, "phy-supply"); -+ if (reg_name != NULL) { -+ return reg_name; -+ } -+ } -+ -+ return NULL; -+} -+ - /******************************************************************************* - * This function retrieves board model from DT - * Returns string taken from model node, NULL otherwise -diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c -new file mode 100644 -index 0000000000..d07067531f ---- /dev/null -+++ b/plat/st/common/stm32mp_fconf_io.c -@@ -0,0 +1,136 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 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 -+ -+#if STM32MP_SDMMC || STM32MP_EMMC -+static io_block_spec_t gpt_block_spec = { -+ .offset = 0, -+ .length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */ -+}; -+#endif -+ -+/* By default, STM32 platforms load images from the FIP */ -+struct plat_io_policy policies[MAX_NUMBER_IDS] = { -+ [FIP_IMAGE_ID] = { -+ &storage_dev_handle, -+ (uintptr_t)&image_block_spec, -+ open_storage -+ }, -+#if STM32MP_SDMMC || STM32MP_EMMC -+ [GPT_IMAGE_ID] = { -+ &storage_dev_handle, -+ (uintptr_t)&gpt_block_spec, -+ open_storage -+ }, -+#endif -+}; -+ -+#if TRUSTED_BOARD_BOOT -+#define FCONF_ST_IO_UUID_NUMBER U(14) -+#else -+#define FCONF_ST_IO_UUID_NUMBER U(8) -+#endif -+ -+static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER]; -+static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids); -+ -+struct policies_load_info { -+ unsigned int image_id; -+ const char *name; -+}; -+ -+/* image id to property name table */ -+static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = { -+ {FW_CONFIG_ID, "fw_cfg_uuid"}, -+ {BL32_IMAGE_ID, "bl32_uuid"}, -+ {BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"}, -+ {BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"}, -+ {BL33_IMAGE_ID, "bl33_uuid"}, -+ {HW_CONFIG_ID, "hw_cfg_uuid"}, -+ {TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"}, -+ {NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"}, -+#if TRUSTED_BOARD_BOOT -+ {TRUSTED_BOOT_FW_CERT_ID, "t_boot_fw_cert_uuid"}, -+ {TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"}, -+ {TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"}, -+ {NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"}, -+ {TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"}, -+ {NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"}, -+#endif /* TRUSTED_BOARD_BOOT */ -+}; -+ -+int fconf_populate_stm32mp_io_policies(uintptr_t config) -+{ -+ int node; -+ unsigned int i; -+ -+ /* As libfdt uses void *, we can't avoid this cast */ -+ const void *dtb = (void *)config; -+ -+ /* Assert the node offset point to "st,io-fip-handle" compatible property */ -+ const char *compatible_str = "st,io-fip-handle"; -+ -+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); -+ if (node < 0) { -+ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); -+ return node; -+ } -+ -+ /* Locate the uuid cells and read the value for all the load info uuid */ -+ for (i = 0U; i < FCONF_ST_IO_UUID_NUMBER; i++) { -+ union uuid_helper_t uuid_helper; -+ io_uuid_spec_t *uuid_ptr; -+ int err; -+ unsigned int j; -+ -+ uuid_ptr = pool_alloc(&fconf_stm32mp_uuids_pool); -+ err = fdt_read_uint32_array(dtb, node, load_info[i].name, -+ 4, uuid_helper.word); -+ if (err < 0) { -+ WARN("FCONF: Read cell failed for %s\n", load_info[i].name); -+ return err; -+ } -+ -+ /* Convert uuid from big endian to little endian */ -+ for (j = 0U; j < 4U; j++) { -+ uuid_helper.word[j] = -+ ((uuid_helper.word[j] >> 24U) & 0xff) | -+ ((uuid_helper.word[j] << 8U) & 0xff0000) | -+ ((uuid_helper.word[j] >> 8U) & 0xff00) | -+ ((uuid_helper.word[j] << 24U) & 0xff000000); -+ } -+ -+ VERBOSE("FCONF: stm32mp-io_policies.%s found with value = 0x%x 0x%x 0x%x 0x%x\n", -+ load_info[i].name, -+ uuid_helper.word[0], uuid_helper.word[1], -+ uuid_helper.word[2], uuid_helper.word[3]); -+ -+ uuid_ptr->uuid = uuid_helper.uuid_struct; -+ policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr; -+ policies[load_info[i].image_id].dev_handle = &fip_dev_handle; -+ policies[load_info[i].image_id].check = open_fip; -+ } -+ -+ return 0; -+} -+ -+FCONF_REGISTER_POPULATOR(TB_FW, stm32mp_io, fconf_populate_stm32mp_io_policies); -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 0000000000..f4c8bd642f ---- /dev/null -+++ b/plat/st/common/stm32mp_img_parser_lib.c -@@ -0,0 +1,75 @@ -+/* -+ * 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 0000000000..12633e47d2 ---- /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 -+ -+static struct spinlock shregs_lock; -+ -+void stm32mp_lock_shregs(void) -+{ -+ if (stm32mp_lock_available() == 0U) { -+ return; -+ } -+ -+ /* Assume interrupts are masked */ -+ spin_lock(&shregs_lock); -+} -+ -+void stm32mp_unlock_shregs(void) -+{ -+ if (stm32mp_lock_available() == 0U) { -+ return; -+ } -+ -+ spin_unlock(&shregs_lock); -+} -+ -+/* Shared register access: upon shared resource lock */ -+void stm32mp_mmio_clrsetbits_32_shregs(uintptr_t addr, uint32_t clear, -+ uint32_t set) -+{ -+ stm32mp_lock_shregs(); -+ -+ mmio_clrsetbits_32(addr, clear, set); -+ -+ stm32mp_unlock_shregs(); -+} -+ -+void stm32mp_mmio_clrbits_32_shregs(uintptr_t addr, uint32_t clear) -+{ -+ stm32mp_lock_shregs(); -+ -+ mmio_clrbits_32(addr, clear); -+ -+ stm32mp_unlock_shregs(); -+} -+ -+void stm32mp_mmio_setbits_32_shregs(uintptr_t addr, uint32_t set) -+{ -+ stm32mp_lock_shregs(); -+ -+ mmio_setbits_32(addr, set); -+ -+ stm32mp_unlock_shregs(); -+} -diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c -new file mode 100644 -index 0000000000..1ea30abf9b ---- /dev/null -+++ b/plat/st/common/stm32mp_trusted_boot.c -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if STM32MP_USE_STM32IMAGE -+static uint8_t root_pk_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; -+#else -+static uint8_t der_sha256_header[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, -+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; -+static uint8_t root_pk_hash[HASH_DER_LEN]; -+#endif -+ -+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; -+ size_t start_copy_idx = 0U; -+ -+ 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; -+ } -+ -+#if !STM32MP_USE_STM32IMAGE -+ memcpy(root_pk_hash, der_sha256_header, sizeof(der_sha256_header)); -+ start_copy_idx = sizeof(der_sha256_header); -+#endif -+ -+ for (i = 0U; i < BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES / sizeof(uint32_t); i++) { -+ uint32_t temp; -+ -+ if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) { -+ return -EINVAL; -+ } -+ -+ temp = bswap32(otp_val); -+ memcpy(root_pk_hash + i * sizeof(uint32_t) + start_copy_idx, &temp, sizeof(temp)); -+ } -+ -+#if STM32MP_USE_STM32IMAGE -+ *key_len = BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES; -+#else -+ *key_len = HASH_DER_LEN; -+#endif -+ *key_ptr = &root_pk_hash; -+ *flags = ROTPK_IS_HASH; -+ -+ if (!stm32mp_is_closed_device()) { -+ /* Check if key hash values in OTP are 0 or 0xFFFFFFFFF programmed : Invalid Key */ -+ uint32_t res; -+ uint32_t rootpk; -+ uint8_t *proot_pk = root_pk_hash; -+ uint8_t idx = sizeof(uint32_t); -+ -+#if !STM32MP_USE_STM32IMAGE -+ idx += sizeof(der_sha256_header); -+ proot_pk = root_pk_hash + sizeof(der_sha256_header); -+#endif -+ memcpy(&res, proot_pk, sizeof(uint32_t)); -+ if ((res == 0U) || (res == 0xFFFFFFFFU)) { -+ while (idx < ARRAY_SIZE(root_pk_hash)) { -+ memcpy(&rootpk, (proot_pk + idx), sizeof(uint32_t)); -+ if (res != rootpk) { -+ return 0; -+ } -+ -+ idx += sizeof(uint32_t); -+ } -+ -+ *flags |= ROTPK_NOT_DEPLOYED; -+ } -+ } -+ -+ return 0; -+} -+ -+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) -+{ -+#if STM32MP_USE_STM32IMAGE -+ if (cookie != NULL) { -+ return -EINVAL; -+ } -+#endif -+ -+ /* -+ * This monotonic counter is the counter used by ROM code -+ * to identify BL2. -+ */ -+ if (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; -+} -+ -+#if !STM32MP_USE_STM32IMAGE -+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) -+{ -+ assert(heap_addr != NULL); -+ assert(heap_size != NULL); -+ -+#if STM32MP_USE_EXTERNAL_HEAP -+ /* Retrieve the already allocated heap's info from DTB */ -+ *heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr); -+ *heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size); -+ -+ return 0; -+#else -+ return get_mbedtls_heap_helper(heap_addr, heap_size); -+#endif -+} -+#endif -diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c -index e09ce63c21..13ce3042a5 100644 ---- a/plat/st/stm32mp1/bl2_plat_setup.c -+++ b/plat/st/stm32mp1/bl2_plat_setup.c -@@ -1,10 +1,11 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - #include -+#include - #include - - #include -@@ -13,28 +14,51 @@ - #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 RESET_TIMEOUT_US_1MS 1000U - -+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 console_t 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) - { -@@ -121,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, -@@ -132,11 +161,6 @@ void bl2_el3_early_platform_setup(u_register_t arg0, - void bl2_platform_setup(void) - { - int ret; -- uint32_t ddr_ns_size; -- -- if (dt_pmic_status() > 0) { -- initialize_pmic(); -- } - - ret = stm32mp1_ddr_probe(); - if (ret < 0) { -@@ -144,29 +168,150 @@ void bl2_platform_setup(void) - panic(); - } - -- ddr_ns_size = stm32mp_get_ddr_ns_size(); -- assert(ddr_ns_size > 0U); -- -- /* Map non secure DDR for BL33 load, now with cacheable attribute */ -- ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, -- ddr_ns_size, MT_MEMORY | MT_RW | MT_NS); -- assert(ret == 0); -- -+#if STM32MP_USE_STM32IMAGE - #ifdef AARCH32_SP_OPTEE - INFO("BL2 runs OP-TEE setup\n"); -- -- /* Map secure DDR for OP-TEE paged area */ -- ret = mmap_add_dynamic_region(STM32MP_DDR_BASE + ddr_ns_size, -- STM32MP_DDR_BASE + ddr_ns_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 -+#endif -+ -+ if (!stm32mp1_ddr_is_restored()) { -+ 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); -+ -+ /* Clear backup register */ -+ mmio_write_32(bkpr_core1_addr, 0); -+ /* Clear backup register magic */ -+ mmio_write_32(bkpr_core1_magic, 0); -+ -+ /* Clear the context in BKPSRAM */ -+ stm32_clean_context(); -+ -+ if (dt_pmic_status() > 0) { -+ configure_pmic(); -+ } -+ } -+ -+ /* Map DDR for binary load, now with cacheable attribute */ -+ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, -+ STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE); -+ if (ret < 0) { -+ ERROR("DDR mapping: error %d\n", ret); -+ panic(); -+ } -+} -+ -+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 (stm32mp1_is_wakeup_from_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 (stm32mp1_is_wakeup_from_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) -+{ -+ int ret; -+ -+ ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ -+ udelay(2); -+ -+ ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ -+ mdelay(1); - } - - void bl2_el3_plat_arch_setup(void) -@@ -179,16 +324,20 @@ void bl2_el3_plat_arch_setup(void) - uint32_t clk_rate; - uintptr_t pwr_base; - uintptr_t rcc_base; -+ bool serial_uart_interface __unused = -+ (boot_context->boot_interface_selected == -+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART); -+ uintptr_t uart_prog_addr __unused; -+ -+ if (bsec_probe() != 0) { -+ panic(); -+ } - - mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, - BL_CODE_END - BL_CODE_BASE, - MT_CODE | MT_SECURE); - --#ifdef AARCH32_SP_OPTEE -- mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, -- STM32MP_OPTEE_SIZE, -- MT_MEMORY | MT_RW | MT_SECURE); --#else -+#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) - /* Prevent corruption of preloaded BL32 */ - mmap_add_region(BL32_BASE, BL32_BASE, - BL32_LIMIT - BL32_BASE, -@@ -201,7 +350,7 @@ void bl2_el3_plat_arch_setup(void) - - configure_mmu(); - -- if (dt_open_and_check() < 0) { -+ if (dt_open_and_check(STM32MP_DTB_BASE) < 0) { - panic(); - } - -@@ -219,10 +368,6 @@ void bl2_el3_plat_arch_setup(void) - ; - } - -- 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); -@@ -235,25 +380,45 @@ void bl2_el3_plat_arch_setup(void) - mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); - } - -- /* 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); - - generic_delay_timer_init(); - -+#if STM32MP_UART_PROGRAMMER -+ uart_prog_addr = get_uart_address(boot_context->boot_interface_instance); -+ -+ /* Disable programmer UART before changing clock tree */ -+ if (serial_uart_interface) { -+ stm32_uart_stop(uart_prog_addr); -+ } -+#endif -+#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 (stm32mp1_clk_probe() < 0) { - panic(); - } - -- 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_uart_info.status == 0U) || -+ (dt_uart_info.status == DT_DISABLED) || -+#if STM32MP_UART_PROGRAMMER -+ (serial_uart_interface && -+ (uart_prog_addr == dt_uart_info.base)) || -+#endif - (dt_uart_info.clock < 0) || - (dt_uart_info.reset < 0)) { - goto skip_console_init; -@@ -263,23 +428,15 @@ void bl2_el3_plat_arch_setup(void) - goto skip_console_init; - } - -- stm32mp_clk_enable((unsigned long)dt_uart_info.clock); -- -- if (stm32mp_reset_assert((uint32_t)dt_uart_info.reset, -- RESET_TIMEOUT_US_1MS) != 0) { -+ if (dt_uart_info.status == DT_DISABLED) { - panic(); - } - -- udelay(2); -- -- if (stm32mp_reset_deassert((uint32_t)dt_uart_info.reset, -- RESET_TIMEOUT_US_1MS) != 0) { -- panic(); -- } -+ clk_enable((unsigned long)dt_uart_info.clock); - -- mdelay(1); -+ reset_uart((uint32_t)dt_uart_info.reset); - -- clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock); -+ clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock); - - if (console_stm32_register(dt_uart_info.base, clk_rate, - STM32MP_UART_BAUDRATE, &console) == 0) { -@@ -298,22 +455,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(); - } - - 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 (stm32mp_is_closed_device()) { -+ NOTICE("\n%s", debug_msg); -+ } - } - - if (stm32_save_boot_interface(boot_context->boot_interface_selected, -@@ -322,20 +497,57 @@ 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(); - - print_reset_reason(); - -+ update_monotonic_counter(); -+ -+ stm32mp1_syscfg_enable_io_compensation_finish(); -+ -+ if (dt_pmic_status() > 0) { -+ initialize_pmic(); -+ print_pmic_info_and_debug(); -+ } -+ -+#if STM32MP_USE_STM32IMAGE -+ if (!stm32mp1_ddr_is_restored()) { -+ stm32mp_io_setup(); -+ } -+#else -+ fconf_populate("TB_FW", STM32MP_DTB_BASE); -+ - stm32mp_io_setup(); -+#endif - } - --#if defined(AARCH32_SP_OPTEE) -+#if defined(AARCH32_SP_OPTEE) && STM32MP_USE_STM32IMAGE -+static void set_mem_params_info(entry_point_info_t *ep_info, -+ image_info_t *unpaged, image_info_t *paged) -+{ -+ uintptr_t bl32_ep = 0; -+ -+ /* Use the default dram setup if no valid ep found */ -+ if (get_optee_header_ep(ep_info, &bl32_ep) && -+ (bl32_ep >= STM32MP_OPTEE_BASE) && -+ (bl32_ep < (STM32MP_OPTEE_BASE + STM32MP_OPTEE_SIZE))) { -+ assert((STM32MP_OPTEE_BASE >= BL2_LIMIT) || -+ ((STM32MP_OPTEE_BASE + STM32MP_OPTEE_SIZE) <= BL2_BASE)); -+ -+ unpaged->image_base = STM32MP_OPTEE_BASE; -+ unpaged->image_max_size = STM32MP_OPTEE_SIZE; -+ } else { -+ unpaged->image_base = STM32MP_DDR_BASE + dt_get_ddr_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_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`. -@@ -345,50 +557,160 @@ 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); - 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 *pager_mem_params __unused; -+ bl_mem_params_node_t *paged_mem_params __unused; -+#if !STM32MP_USE_STM32IMAGE -+ const struct dyn_cfg_dtb_info_t *config_info; -+ bl_mem_params_node_t *tos_fw_mem_params; -+ unsigned int i; -+ unsigned long long ddr_top __unused; -+ bool wakeup_ddr_sr = stm32mp1_ddr_is_restored(); -+ const unsigned int image_ids[] = { -+ BL32_IMAGE_ID, -+ BL33_IMAGE_ID, -+ HW_CONFIG_ID, -+ TOS_FW_CONFIG_ID, -+ }; -+#endif - - assert(bl_mem_params != NULL); - -+#if TRUSTED_BOARD_BOOT && STM32MP_USE_STM32IMAGE -+ /* Clean header to avoid loaded header reused */ -+ stm32mp_delete_loaded_header(); -+#endif -+ - switch (image_id) { -+#if !STM32MP_USE_STM32IMAGE -+ case FW_CONFIG_ID: -+ /* Set global DTB info for fixed fw_config information */ -+ set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID); -+ fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE); -+ -+ /* Iterate through all the fw config IDs */ -+ for (i = 0; i < ARRAY_SIZE(image_ids); i++) { -+ bl_mem_params = get_bl_mem_params_node(image_ids[i]); -+ assert(bl_mem_params != NULL); -+ -+ config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]); -+ if (config_info == NULL) { -+ continue; -+ } -+ -+ bl_mem_params->image_info.image_base = config_info->config_addr; -+ bl_mem_params->image_info.image_max_size = config_info->config_max_size; -+ -+ /* -+ * If going back from CSTANDBY / STANDBY and DDR was in Self-Refresh, -+ * DDR partitions must not be reloaded. -+ */ -+ if (!(wakeup_ddr_sr && (config_info->config_addr >= STM32MP_DDR_BASE))) { -+ bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; -+ } -+ -+ switch (image_ids[i]) { -+ case BL32_IMAGE_ID: -+ bl_mem_params->ep_info.pc = config_info->config_addr; -+ -+ /* In case of OPTEE, initialize address space with tos_fw addr */ -+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); -+ pager_mem_params->image_info.image_base = config_info->config_addr; -+ pager_mem_params->image_info.image_max_size = -+ config_info->config_max_size; -+ -+ /* Init base and size for pager if exist */ -+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); -+ paged_mem_params->image_info.image_base = STM32MP_DDR_BASE + -+ (dt_get_ddr_size() - STM32MP_DDR_S_SIZE); -+ paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE; -+ break; -+ -+ case BL33_IMAGE_ID: -+ if (wakeup_ddr_sr) { -+ /* -+ * Set ep_info PC to 0, to inform BL32 it is a reset -+ * after STANDBY -+ */ -+ bl_mem_params->ep_info.pc = 0U; -+ } else { -+ bl_mem_params->ep_info.pc = config_info->config_addr; -+ } -+ break; -+ -+ case HW_CONFIG_ID: -+ case TOS_FW_CONFIG_ID: -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ break; -+#endif /* !STM32MP_USE_STM32IMAGE */ -+ - case BL32_IMAGE_ID: -- 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 + -- stm32mp_get_ddr_ns_size(); -- paged_mem_params->image_info.image_max_size = -- STM32MP_DDR_S_SIZE; -- -- 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(); -+#if defined(AARCH32_SP_OPTEE) || !STM32MP_USE_STM32IMAGE -+ bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base; -+ if (get_optee_header_ep(&bl_mem_params->ep_info, &bl_mem_params->ep_info.pc) == 1) { -+ /* BL32 is OP-TEE header */ -+#if !STM32MP_USE_STM32IMAGE -+ if (wakeup_ddr_sr) { -+ bl_mem_params->ep_info.pc = stm32_pm_get_optee_ep(); -+ if (stm32mp1_addr_inside_backupsram(bl_mem_params->ep_info.pc)) { -+ clk_enable(BKPSRAM); -+ } -+ -+ break; -+ } -+#endif -+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); -+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); -+ assert((pager_mem_params != NULL) && (paged_mem_params != NULL)); -+ -+#if STM32MP_USE_STM32IMAGE -+ set_mem_params_info(&bl_mem_params->ep_info, &pager_mem_params->image_info, -+ &paged_mem_params->image_info); -+#endif -+ -+ 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.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 */ -+ } else { -+#if STM32MP_USE_STM32IMAGE -+ bl_mem_params->ep_info.pc = STM32MP_BL32_BASE; -+#else -+ tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID); -+ bl_mem_params->image_info.image_max_size += -+ tos_fw_mem_params->image_info.image_max_size; -+#endif -+ bl_mem_params->ep_info.args.arg0 = 0; - } - -- /* 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 */ -+ if (bl_mem_params->ep_info.pc >= STM32MP_DDR_BASE) { -+ stm32_context_save_bl2_param(); -+ } -+#endif - break; - - case BL33_IMAGE_ID: - 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; -+ -+#if STM32MP_USB_PROGRAMMER || STM32MP_UART_PROGRAMMER -+ /* Invalidate downloaded package from cache */ -+ inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE); -+#endif - break; - - default: -@@ -398,4 +720,8 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) - - return err; - } --#endif -+ -+void bl2_el3_plat_prepare_exit(void) -+{ -+ stm32mp1_security_setup(); -+} -diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h -index c16639ac40..8c9d3afb49 100644 ---- a/plat/st/stm32mp1/include/boot_api.h -+++ b/plat/st/stm32mp1/include/boot_api.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -10,6 +10,90 @@ - #include - #include - -+/* -+ * Exported constants -+ */ -+ -+/* -+ * Boot Context related definitions -+ */ -+ -+/* -+ * Possible value of boot context field 'boot_action' -+ */ -+/* Boot action is Process Cold Boot */ -+#define BOOT_API_CTX_BOOT_ACTION_COLD_BOOT_PROCESS 0x09U -+/* Boot action is Process Wakeup from CSTANDBY */ -+#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY 0x0AU -+/* Boot action is Process Wakeup from STANDBY */ -+#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY 0x0BU -+/* Boot action is Process Engineering Boot */ -+#define BOOT_API_CTX_BOOT_ACTION_ENGI_BOOT 0x0CU -+ -+#define BOOT_API_CTX_BOOT_ACTION_MPU_CORE0_RESET_PROCESS 0x0F -+ -+/* -+ * Possible value of boot context field 'stby_exit_status' -+ */ -+ -+/* The boot reason is not a STANDBY Exit reason */ -+#define BOOT_API_CTX_STBY_EXIT_STATUS_NO_STANDBY 0x00 -+ -+/* STANDBY Exit with MPU_BEN=1, MCU_BEN=0 */ -+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MPU_ONLY 0x01 -+ -+/* -+ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MPU will go for cold boot -+ * MCU restarted by bootROM -+ */ -+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES 0x02 -+ -+/* -+ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MPU will go for cold boot -+ * but MCU restart aborted (code integrity check) : have not been restarted -+ * by bootROM -+ */ -+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES_MCU_ABT 0x03 -+ -+/* -+ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MPU gone to CSTANDBY, -+ * MCU restarted correctly by bootROM -+ * This value should never be read by FSBL, because not executed in that case -+ */ -+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY 0x04 -+ -+/* -+ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MCU restart aborted -+ * due code integrity check, then MPU will go for cold boot despite -+ * was not planned initially -+ */ -+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY_MCU_ABT 0x05 -+ -+/* -+ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MCU restart aborted -+ * due to MCU security perimeter issue -+ */ -+#define \ -+BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES_MCU_ABT_SEC_PERIMETER_ISSUE 0x06 -+ -+/* -+ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MCU restart aborted -+ * due to MCU security perimeter issue, then MPU will go for cold boot -+ * despite was not planned initially -+ */ -+#define \ -+BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY_MCU_ABT_SEC_PERIMETER_ISSUE 0x07 -+ -+/* -+ * Possible value of boot context field 'cstby_exit_status' -+ */ -+/* The boot reason is not a CSTANDBY Exit reason */ -+#define BOOT_API_CTX_CSTBY_EXIT_STATUS_NO_CSTBY 0x00 -+/* CSTANDBY Exit with MCU detected as Not running */ -+#define BOOT_API_CTX_CSTBY_EXIT_STATUS_MCU_NOT_RUNNING 0x01 -+/* 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' - */ -@@ -37,10 +121,16 @@ - #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U - - /* Boot occurred on QSPI NOR */ --#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U -+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI 0x4U -+ -+/* Boot occurred on UART */ -+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U -+ -+/* Boot occurred on USB */ -+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U - - /* Boot occurred on QSPI NAND */ --#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U -+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI 0x7U - - /** - * @brief Possible value of boot context field 'EmmcXferStatus' -@@ -65,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 - -+/* Definitions relative to 'p_rom_version_info->platform_type_ver' field */ -+#define BOOT_API_CTX_ROM_VERSION_PLAT_VER_IC_EMU_FPGA 0xAA -+#define BOOT_API_CTX_ROM_VERSION_PLAT_VER_FPGA_ONLY 0xBB -+ - /* Image Header related definitions */ - - /* Definition of header version */ -@@ -95,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 -+ */ -+ -+/* -+ * Defines to identify RTC backup registers to be used for MCU code integrity -+ * check -+ */ -+ -+/* -+ * TAMP_BCK0R contains two bits -+ * bit 0 : wanted value of 'RCC_TZCR.TZEN' -+ * bit 1 : wanted value of 'RCC_TZCR.MCKPROT' -+ */ -+ -+/* -+ * TAMP_BCK0R bit position coding wanted value of 'RCC_TZCR.TZEN' -+ * trustZone aware domain enabling/disabling -+ */ -+#define BOOT_API_MCIC_MCU_SECURITY_PERIMETER_TZEN_BIT 0 -+ -+/* -+ * TAMP_BCK0R bit position coding wanted value of 'RCC_TZCR.MCKPROT' -+ * ability of MCU to modify some clock settings in RCC -+ */ -+#define BOOT_API_MCIC_MCU_SECURITY_PERIMETER_MCKPROT_BIT 1 -+ -+/* TAMP_BCK0R register index */ -+#define \ -+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_TZEN_MCKPROT_TAMP_BCK_REG_IDX 0 -+ -+/* -+ * TAMP_BCK1R register index -+ * This register is coding the wanted value of register 'EXTI_TZENR1' -+ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1 -+ * that is MCU quick restart requested -+ */ -+#define \ -+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR1_TAMP_BCK_REG_IDX 1 -+ -+/* -+ * TAMP_BCK2R register index -+ * This register is coding the wanted value of register 'EXTI_TZENR2' -+ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1 -+ * that is MCU quick restart requested -+ */ -+#define \ -+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR2_TAMP_BCK_REG_IDX 2 -+ -+/* -+ * TAMP_BCK3R register index -+ * This register is coding the wanted value of register 'EXTI_TZENR3' -+ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1 -+ * that is MCU quick restart requested -+ */ -+#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 -@@ -109,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 -+ */ -+#define \ -+BOOT_API_MCIC_OFFSET_IN_BYTES_CODE_TO_HASH_RETRAM_TAMP_BCK_REG_IDX 22 -+ -+/* -+ * TAMP_BCK23R register index -+ * This register contains the size in bytes of the single consecutive region -+ * of MCU Firmware in RETRAM (Retention RAM) to hash (by SHA-256) -+ * Note : This is required as a MCU firmware Code Integrity Check (aka : MCIC) -+ * to avoid bootROM restarting MCU on a corrupted firmware -+ */ -+#define \ -+BOOT_API_MCIC_RETRAM_REGION_TO_HASH_IN_BYTES_TAMP_BCK_REG_IDX 23 -+ -+/* -+ * TAMP_BCK24R to TAMP_BCK31R register indexes -+ * Those registers contains SHA-256 digest of RETRAM MCU Firmware code between -+ * [(RETRAM_start + offset) -- (RETRAM_start + offset + size_to_hash)] -+ * in this order -+ * This is the MCU Code Integrity Check MCU Firmware signature -+ * value on 256 bits -+ */ -+ -+/* First TAMP_BKP index of MCU Firmware signature : ie TAMP_BCK24R */ -+#define BOOT_API_MCIC_SHA_DIGEST_FIRST_TAMP_BCK_REG_IDX 24 -+ -+/* 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' - */ -@@ -135,6 +320,320 @@ - - #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 -+/* SSP_REQ = OTP_CFG8[8] */ -+#define BOOT_API_OTP_SSP_REQ_BIT_POS 8 -+/* SSP_SUCCESS = OTP_CFG8[9] */ -+#define BOOT_API_OTP_SSP_SUCCESS_BIT_POS 9 -+ -+/* -+ * Possible values of boot context field -+ * 'ssp_config_ptr_in->ssp_cmd' -+ */ -+/* 'K' 'B' 'U' 'P' -.> 'PUBK' */ -+#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK 0x4B425550 -+ -+#if STM32MP_SSP -+/* 'V' 'O' 'R' 'P' -.> 'PROV' */ -+#define BOOT_API_CTX_SSP_CMD_PROV_SECRET 0x564F5250 -+/* -+ * Possible values of boot context field -+ * 'ssp_config_ptr_in->ssp_cmd' written by bootROM as Acknowledge -+ * of a request of SSP by FSBL. -+ */ -+ -+/* Written by bootROM on SSP error */ -+#define BOOT_API_CTX_SSP_CMD_INVALID 0x00000000 -+/* -+ * 'A' 'B' 'U' 'P' -.> 'PUBA' : ACK of ECIES_CHIP_PUBK calculation -+ * request by bootROM. -+ */ -+#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK 0x41425550 -+/* -+ * 'A' 'O' 'R' 'P' -.> 'PROA' : ACK of OEM Secret Provisioning request -+ * by bootROM. -+ */ -+#define BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK 0x414F5250 -+ -+/* -+ * Constants required for SSP -+ */ -+/* '.' 'P' 'S' 'S' -.> 'SSP.' */ -+#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_NORMAL 0x2E505353 -+/* 'L' 'P' 'S' 'S' -.> 'SSPL' */ -+#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_LIVE 0x4C505353 -+/* version 1 */ -+#define BOOT_API_SSP_LICENSE_LAYOUT_VERSION_TO_MATCH 0x00000001 -+/* 'P' 'P' 'S' 'S' -.> 'SSPP' */ -+#define BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP 0x50505353 -+/* IV AES on 128 bits = 16 bytes and KEY AES on 128 bits = 16 bytes */ -+#define BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES 32 -+/* version 1 */ -+#define BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH 0x00000001 -+/* -+ * Scalar in Elliptic curve cryptography is an integer (often a Prime) -+ * the number of bytes of this scalar is defined below. -+ */ -+#define BOOT_API_SSP_SCALAR_SIZE_BYTES 32 -+ -+/* -+ * In Elliptic curve cryptography coordinates of points are 2D P -+ * (Px, Py) as concatenation of two scalars. -+ */ -+#define BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES \ -+ (2 * BOOT_API_SSP_SCALAR_SIZE_BYTES) -+ -+/* In Elliptic curve cryptography Private Keys are scalars */ -+#define BOOT_API_SSP_PRIVK_KEY_SIZE_BYTES \ -+ BOOT_API_SSP_SCALAR_SIZE_BYTES -+ -+/* -+ * In ECIES algorithm the Shared Secret (SS) is -+ * the x coordinate (Px) of a point P(Px,Py) obtained on reference -+ * chosen NIST-P256 Elliptic curve. -+ */ -+#define BOOT_API_SSP_ECDH_SHARED_SECRET_SIZE_BYTES \ -+ BOOT_API_SSP_SCALAR_SIZE_BYTES -+ -+/* -+ * In Elliptic curve cryptography Public Keys are Points on chosen -+ * Elliptic curve P(x,y). -+ * Public Key is the x, y coordinates concatenated -+ * Ecies_eph_pubk and OEM_ECDSA_PUBK are each 64 bytes = 512 bits key -+ * sizes. -+ */ -+#define BOOT_API_SSP_PUBK_KEY_SIZE_BYTES \ -+ BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES -+ -+/* -+ * Size in bytes of ECIES_Chip_pubk obtained from bootROM at end of SSP -+ * phase 1 : Chip public key calculation. -+ */ -+#define BOOT_API_SSP_ECIES_CHIP_PUBK_SIZE_BYTES \ -+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES -+ -+/* AES-GCM authentication tag size is 16 bytes = 128 bits */ -+#define BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES 16 -+ -+/* AES-GCM Symmetric Key size is 16 bytes = 128 bits */ -+#define BOOT_API_SSP_AES_GCM_KEY_SIZE_BYTES 16 -+ -+/* AES-GCM Initialization Vector (IV) size is of 16 bytes = 128 bits */ -+#define BOOT_API_SSP_AES_GCM_IV_SIZE_BYTES 16 -+ -+/* -+ * 88 bytes (license_type, live_session_id, license_version, -+ * fsbl_min_version, rfu[8], eph_ecies_pubk[]) -+ */ -+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE 88 -+ -+/* -+ * 32 bytes AAD License Secret from 2nd round KDF-SHA-256 -+ * from ECDH Shared Secret hence KDF[32..63] aka "Authorization Token" -+ */ -+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF 32 -+ -+/* -+ * Total License AAD size = 88 + 32 = 120 bytes -+ */ -+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_SIZE_BYTES \ -+ (BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE + \ -+ BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF) -+ -+/* -+ * AAD for Payload size : composed of : -+ * payload_magic, payload_protocol_version, oem_ecdsa_pubk[], oem_secret_size -+ * = 4 + 4 + 64 + 4 = 76 bytes AAD for Payload -+ */ -+#define BOOT_API_SSP_AES_GCM_PAYLOAD_AAD_SIZE_BYTES 76 -+ -+/* -+ * OEM Secrets max size in bytes : -+ * [OTP[95:59] + OTP_CFG56 (RMA Unlock and Relock passwords)] x 4 bytes -+ * by OTP word = 152 bytes -+ */ -+#define BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES 152 -+ -+/* -+ * Possible values of boot context field 'ssp_status' -+ * as can be read by FSBL-SSP -+ */ -+#define BOOT_API_CTX_SSP_STATUS_NO_SSP 0 -+#define BOOT_API_CTX_SSP_STATUS_CHIP_PUBK_CALC_FINISHED 1 -+#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FINISHED 2 -+#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FORBIDDEN 3 -+ -+/* -+ * Reserved size for future use -+ */ -+#define BOOT_API_SSP_HSM_OEM_RFU_SIZE 8 -+ -+/* -+ * Exported types -+ */ -+ -+/* -+ * SSP related definitions -+ */ -+/* -+ * SSP BLOB License structure : Binary Large OBject License structure -+ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret -+ * provisioning. -+ * License information data, the structure is read by bootROM. -+ */ -+typedef struct { -+ /* -+ * License Type provided by HSM-OEM tool -+ * should match Normal SSP License of Live SSP License. -+ */ -+ uint32_t license_type; -+ -+ /* Live Session ID provided by HSM-OEM tool */ -+ uint32_t live_session_id; -+ -+ /* -+ * Version of the License Protocol (Structure) -+ * should be incremented each time a new. -+ */ -+ uint32_t license_version; -+ -+ /* -+ * Minimum FSBL version to be compared -+ * with FSBL Header field 'imageVersion'. -+ */ -+ uint32_t fsbl_min_version; -+ -+ /* RFU provided by HSM-OEM tool */ -+ uint8_t rfu[BOOT_API_SSP_HSM_OEM_RFU_SIZE]; -+ -+ /* -+ * Ephemeral ECIES Public Key from HSM-OEM -+ * 64 bytes = 512 bits. -+ */ -+ uint8_t eph_ecies_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES]; -+ -+ /* -+ * Encrypted (IV,Key) : with Shared Secret based on -+ * 'Ephemeral ECIES Key pair' and 'ECIES Chip Key pair'. -+ */ -+ uint8_t encrypted_iv_and_key -+ [BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES]; -+ -+ /* -+ * AUTH_TAG AES-GCM from encryption of (IV, Key) -+ * in HSM-OEM with License AAD scheme -+ * License Tag is 16 bytes = 128 bits. -+ */ -+ uint8_t license_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES]; -+ -+} boot_api_ssp_blob_license_t; -+ -+/* -+ * SSP BLOB Payload structure : Binary Large OBject Payload Structure -+ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret -+ * provisioning input data, the structure is read by bootROM -+ * The BLOB Payload size is fixed to a max size of 244 bytes based -+ * on a max number of bytes of OEM secret derived from OTP upper free -+ * area in STM32MP15xx cut 2.0.In this table oem_encrypted_secrets[] -+ * of max size only the first 'p_blob_payload->oem_secret_size_bytes' -+ * bytes will be considered and used by bootROM. -+ */ -+typedef struct { -+ /* -+ * BLOB Payload Magic : for memory validity check of BLOB Payload -+ * to match against BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP by bootROM. -+ */ -+ uint32_t payload_magic; -+ -+ /* -+ * SSP Payload protocol version : on 32 bits -+ * to be checked by bootROM for equality with -+ * BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH -+ * ie : 0x00000001 : version 1 of SSP Payload -+ */ -+ uint32_t payload_protocol_version; -+ -+ /* -+ * OEM_ECDSA_PUBK Public Key defined by OEM -+ * 64 bytes = 512 bits -+ */ -+ uint8_t oem_ecdsa_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES]; -+ -+ /* -+ * Size of Table of OEM Secrets encrypted with AES-GCM (Key,IV) from -+ * License field 'encrypted_iv_and_key[]' -+ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES: -+ * is verified by bootROM. -+ */ -+ uint32_t oem_secret_size_bytes; -+ -+ /* -+ * AUTH_TAG AES-GCM computed by HSM-OEM when encrypting OEM Secrets with -+ * (Key,IV) using special AAD scheme for Payload. -+ * 16 bytes = 128 bits -+ */ -+ uint8_t payload_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES]; -+ -+ /* -+ * OEM Secrets encrypted with AES-GCM (IV, Key) from -+ * License field 'encrypted_iv_and_key[]'. -+ * The payload size is 'oem_secret_size_bytes' -+ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES = -+ * 152 bytes : OEM Secrets max size in bytes : -+ * [OTP_CFG56, OTP_CFG59, OTP_CFG60..95] x 4 bytes by OTP word. -+ */ -+ uint8_t oem_encrypted_secrets[BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES]; -+ -+} boot_api_ssp_blob_payload_t; -+#endif -+ -+/* SSP Configuration structure */ -+typedef struct { -+ /* SSP Command*/ -+ uint32_t ssp_cmd; -+#if STM32MP_SSP -+ /* ECIES chip public key */ -+ uint8_t *p_chip_pubk; -+ /* Blob License Address */ -+ boot_api_ssp_blob_license_t *p_blob_license; -+ /* Blob Payload Address */ -+ boot_api_ssp_blob_payload_t *p_blob_payload; -+ /* Secrets Decrypted Address */ -+ uint8_t *p_ssp_oem_secrets_decrypted; -+ /* Reserved for Future Use (RFU) */ -+ uint32_t padding_rfu; -+#else -+ uint8_t reserved[20]; -+#endif -+} boot_api_ssp_config_t; -+ -+/* -+ * bootROM version information structure definition -+ * Total size = 24 bytes = 6 uint32_t -+ */ -+typedef struct { -+ /* Chip Version */ -+ uint32_t chip_ver; -+ -+ /* Cut version within a fixed chip version */ -+ uint32_t cut_ver; -+ -+ /* Version of ROM Mask within a fixed cut version */ -+ uint32_t rom_mask_ver; -+ -+ /* Internal Version of bootROM code */ -+ uint32_t bootrom_ver; -+ -+ /* Version of bootROM adapted */ -+ uint32_t for_chip_design_rtl_ver; -+ -+ /* Restriction on compiled platform when it applies */ -+ uint32_t platform_type_ver; -+ -+} boot_api_rom_version_info_t; -+ - /* - * Boot Context related definitions - */ -@@ -153,26 +652,38 @@ typedef struct { - uint16_t boot_interface_instance; - uint32_t reserved1[13]; - uint32_t otp_afmux_values[3]; -- uint32_t reserved[5]; -+ uint32_t reserved[2]; -+ /* -+ * Log to boot context, what was the kind of boot action -+ * takes values from defines BOOT_API_BOOT_ACTION_XXX above -+ */ -+ uint32_t boot_action; -+ /* -+ * STANDBY Exit status to be checked by FSBL in case -+ * field 'boot_action' == BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY -+ * take values from defines above 'BOOT_API_CTX_STBY_EXIT_STATUS_XXX' -+ * depending on encountered situation -+ */ -+ uint32_t stby_exit_status; -+ /* -+ * CSTANDBY Exit status to be checked by FSBL in case -+ * boot_action == BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY -+ * take values from defines above 'BOOT_API_CTX_CSTBY_EXIT_STATUS_XXX' -+ * depending on encountered situation -+ */ -+ uint32_t cstby_exit_status; - uint32_t auth_status; - - /* - * Pointers to bootROM External Secure Services -- * - ECDSA check key - * - ECDSA verify signature -- * - ECDSA verify signature and go - */ -- uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in, -- uint8_t *pubkey_out); -+ uint32_t reserved3; - uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in, - uint8_t *pubkey_in, - uint8_t *signature, - uint32_t ecc_algo); -- uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in, -- uint8_t *pub_key_in, -- uint8_t *signature, -- uint32_t ecc_algo, -- uint32_t *entry_in); -+ uint32_t reserved4; - - /* - * Information specific to an SD boot -@@ -203,6 +714,21 @@ typedef struct { - * ie FSBL partition on which the boot was successful - */ - uint32_t boot_partition_used_toboot; -+ /* -+ * Address of SSP configuration structure : -+ * given and defined by bootROM -+ * and used by FSBL. The structure is of type -+ * 'boot_api_ssp_config_t' -+ */ -+ boot_api_ssp_config_t *p_ssp_config; -+ /* -+ * boot context field containing bootROM updated SSP Status -+ * Values can be of type BOOT_API_CTX_SSP_STATUS_XXX -+ */ -+ uint32_t ssp_status; -+ -+ /* Pointer on ROM constant containing ROM information */ -+ const boot_api_rom_version_info_t *p_rom_version_info; - - } __packed boot_api_context_t; - -diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h -index 7076a7105f..4434afa172 100644 ---- a/plat/st/stm32mp1/include/platform_def.h -+++ b/plat/st/stm32mp1/include/platform_def.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -25,18 +25,22 @@ - #define PLATFORM_STACK_SIZE 0xC00 - #endif - -+#if STM32MP_USE_STM32IMAGE - #ifdef AARCH32_SP_OPTEE - #define OPTEE_HEADER_IMAGE_NAME "teeh" -+#define OPTEE_CORE_IMAGE_NAME "teex" - #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_CORE_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) -+#else /* STM32MP_USE_STM32IMAGE */ -+#define FIP_IMAGE_NAME "fip" -+#endif /* STM32MP_USE_STM32IMAGE */ - - #define STM32MP_PRIMARY_CPU U(0x0) - #define STM32MP_SECONDARY_CPU U(0x1) -@@ -64,14 +68,26 @@ - #define BL2_LIMIT (STM32MP_BL2_BASE + \ - STM32MP_BL2_SIZE) - -+#define BL2_RO_BASE STM32MP_BL2_RO_BASE -+#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \ -+ STM32MP_BL2_RO_SIZE) -+ -+#define BL2_RW_BASE STM32MP_BL2_RW_BASE -+#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \ -+ STM32MP_BL2_RW_SIZE) - /******************************************************************************* - * BL32 specific defines. - ******************************************************************************/ --#ifndef AARCH32_SP_OPTEE -+#if STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) -+#if ENABLE_PIE -+#define BL32_BASE 0 -+#define BL32_LIMIT STM32MP_BL32_SIZE -+#else - #define BL32_BASE STM32MP_BL32_BASE - #define BL32_LIMIT (STM32MP_BL32_BASE + \ - STM32MP_BL32_SIZE) - #endif -+#endif - - /******************************************************************************* - * BL33 specific defines. -@@ -83,6 +99,12 @@ - */ - #define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE - -+/* Needed by STM32CubeProgrammer support */ -+#define FLASHLAYOUT_BASE STM32MP_DDR_BASE -+#define FLASHLAYOUT_SIZE 0x00100000 -+#define DWL_BUFFER_BASE (STM32MP_DDR_BASE + 0x08000000) -+#define DWL_BUFFER_SIZE 0x08000000 -+ - /******************************************************************************* - * DTB specific defines. - ******************************************************************************/ -@@ -113,6 +135,8 @@ - */ - #define ARM_IRQ_SEC_PHY_TIMER U(29) - -+#define ARM_IRQ_NON_SEC_SGI_0 U(0) -+ - #define ARM_IRQ_SEC_SGI_0 U(8) - #define ARM_IRQ_SEC_SGI_1 U(9) - #define ARM_IRQ_SEC_SGI_2 U(10) -@@ -122,7 +146,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 STM32MP_IRQ_SEC_SPI_PRIO U(0x10) -+ - #define STM32MP1_IRQ_TZC400 U(36) -+#define STM32MP1_IRQ_MCU_SEV U(176) -+#define STM32MP1_IRQ_RCC_WAKEUP U(177) -+#define STM32MP1_IRQ_IWDG1 U(182) -+#define STM32MP1_IRQ_IWDG2 U(183) - #define STM32MP1_IRQ_TAMPSERRS U(229) - #define STM32MP1_IRQ_AXIERRIRQ U(244) - -diff --git a/plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h b/plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h -new file mode 100644 -index 0000000000..0023fecd94 ---- /dev/null -+++ b/plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h -@@ -0,0 +1,119 @@ -+/* -+ * Copyright (c) 2015-2020, Arm Limited. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+#ifndef MBEDTLS_CONFIG_H -+#define MBEDTLS_CONFIG_H -+ -+/* -+ * Key algorithms currently supported on mbed TLS libraries -+ */ -+#define TF_MBEDTLS_USE_RSA 0 -+#define TF_MBEDTLS_USE_ECDSA 1 -+ -+/* -+ * Hash algorithms currently supported on mbed TLS libraries -+ */ -+#define TF_MBEDTLS_SHA256 1 -+#define TF_MBEDTLS_SHA384 2 -+#define TF_MBEDTLS_SHA512 3 -+ -+/* -+ * Configuration file to build mbed TLS with the required features for -+ * Trusted Boot -+ */ -+ -+#define MBEDTLS_PLATFORM_MEMORY -+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -+/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */ -+#define MBEDTLS_PLATFORM_SNPRINTF_ALT -+ -+#define MBEDTLS_PKCS1_V21 -+ -+#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -+#define MBEDTLS_X509_CHECK_KEY_USAGE -+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -+ -+#define MBEDTLS_ASN1_PARSE_C -+#define MBEDTLS_ASN1_WRITE_C -+ -+#define MBEDTLS_BASE64_C -+#define MBEDTLS_BIGNUM_C -+ -+#define MBEDTLS_ERROR_C -+#define MBEDTLS_MD_C -+ -+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C -+#define MBEDTLS_OID_C -+ -+#define MBEDTLS_PK_C -+#define MBEDTLS_PK_PARSE_C -+#define MBEDTLS_PK_WRITE_C -+ -+#define MBEDTLS_PLATFORM_C -+ -+#if TF_MBEDTLS_USE_ECDSA -+#define MBEDTLS_ECDSA_C -+#define MBEDTLS_ECP_C -+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -+#define MBEDTLS_ECP_NO_INTERNAL_RNG -+#endif -+#if TF_MBEDTLS_USE_RSA -+#define MBEDTLS_RSA_C -+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT -+#endif -+ -+#define MBEDTLS_SHA256_C -+#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256) -+#define MBEDTLS_SHA512_C -+#endif -+ -+#define MBEDTLS_VERSION_C -+ -+#define MBEDTLS_X509_USE_C -+#define MBEDTLS_X509_CRT_PARSE_C -+ -+#if TF_MBEDTLS_USE_AES_GCM -+#define MBEDTLS_AES_C -+#define MBEDTLS_CIPHER_C -+#define MBEDTLS_GCM_C -+#endif -+ -+/* MPI / BIGNUM options */ -+#define MBEDTLS_MPI_WINDOW_SIZE 2 -+ -+#if TF_MBEDTLS_USE_RSA -+#if TF_MBEDTLS_KEY_SIZE <= 2048 -+#define MBEDTLS_MPI_MAX_SIZE 256 -+#else -+#define MBEDTLS_MPI_MAX_SIZE 512 -+#endif -+#else -+#define MBEDTLS_MPI_MAX_SIZE 256 -+#endif -+ -+/* Memory buffer allocator options */ -+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8 -+ -+/* -+ * Prevent the use of 128-bit division which -+ * creates dependency on external libraries. -+ */ -+#define MBEDTLS_NO_UDBL_DIVISION -+ -+#ifndef __ASSEMBLER__ -+/* System headers required to build mbed TLS with the current configuration */ -+#include -+#include -+#endif -+ -+/* -+ * Mbed TLS heap size is smal as we only use the asn1 -+ * parsing functions -+ * digest, signature and crypto algorithm are done by -+ * other library. -+ */ -+ -+#define TF_MBEDTLS_HEAP_SIZE U(5120) -+#endif /* MBEDTLS_CONFIG_H */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h -index 698415af2c..2c035cdca4 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_context.h -+++ b/plat/st/stm32mp1/include/stm32mp1_context.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2018, 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,8 +7,33 @@ - #ifndef STM32MP1_CONTEXT_H - #define STM32MP1_CONTEXT_H - -+#include - #include - --int stm32_save_boot_interface(uint32_t interface, uint32_t instance); -+#include -+ -+#define DDR_CRC_GRANULE 32 -+ -+void stm32_clean_context(void); -+int stm32_save_context(uint32_t zq0cr0_zdata, -+ struct stm32_rtc_calendar *rtc_time, -+ unsigned long long stgen_cnt); -+int stm32_restore_context(void); -+unsigned long long stm32_get_stgen_from_context(void); -+int stm32_restore_backup_reg(void); -+void stm32_context_get_bl2_low_power_params(uintptr_t *bl2_code_base, -+ uintptr_t *bl2_code_end, -+ uintptr_t *bl2_end); -+void stm32_context_save_bl2_param(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); -+bool stm32_pm_context_is_valid(void); -+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 */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_critic_power.h b/plat/st/stm32mp1/include/stm32mp1_critic_power.h -new file mode 100644 -index 0000000000..cd7099c444 ---- /dev/null -+++ b/plat/st/stm32mp1/include/stm32mp1_critic_power.h -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP1_CRITIC_POWER_H -+#define STM32MP1_CRITIC_POWER_H -+ -+ /* Only BL32 compilation unit need stm32_pwr_down_wfi -+ * function/variable symbol -+ */ -+#if defined(IMAGE_BL32) -+ #if STM32MP_SP_MIN_IN_DDR -+extern void (*stm32_pwr_down_wfi)(bool is_cstop); -+ #else -+extern void stm32_pwr_down_wfi(bool is_cstop); -+ #endif -+#endif -+extern void stm32_pwr_down_wfi_wrapper(bool is_cstop); -+ -+#endif /* STM32MP1_CRITIC_POWER_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 0000000000..79ae3bfc92 ---- /dev/null -+++ b/plat/st/stm32mp1/include/stm32mp1_low_power.h -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP1_LOW_POWER_H -+#define STM32MP1_LOW_POWER_H -+ -+#include -+#include -+ -+#include -+ -+void stm32_rcc_wakeup_update(bool state); -+void stm32_apply_pmic_suspend_config(uint32_t mode); -+bool stm32_is_cstop_done(void); -+void stm32_exit_cstop(void); -+void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr); -+void stm32_auto_stop(void); -+void stm32_init_low_power(void); -+ -+#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 0000000000..37312c8de6 ---- /dev/null -+++ b/plat/st/stm32mp1/include/stm32mp1_power_config.h -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP1_POWER_CONFIG_H -+#define STM32MP1_POWER_CONFIG_H -+ -+#include -+#include -+ -+#define PSCI_MODE_SYSTEM_SUSPEND 0 -+#define PSCI_MODE_SYSTEM_OFF 1 -+ -+enum stm32mp1_pm_domain { -+ STM32MP1_PD_VSW, -+ STM32MP1_PD_CORE_RET, -+ STM32MP1_PD_CORE, -+ STM32MP1_PD_MAX_PM_DOMAIN -+}; -+ -+void stm32mp1_init_lp_states(void); -+int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status); -+uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode); -+int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode); -+bool stm32mp1_get_retram_enabled(void); -+ -+#endif /* STM32MP1_POWER_CONFIG_H */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h -index b6cb91efa0..ebf9e52bc9 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_private.h -+++ b/plat/st/stm32mp1/include/stm32mp1_private.h -@@ -9,19 +9,46 @@ - - #include - -+#include -+ -+enum boot_device_e { -+ BOOT_DEVICE_USB, -+ BOOT_DEVICE_BOARD -+}; -+ - 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_gic_pcpu_init(void); --void stm32mp1_gic_init(void); -+enum boot_device_e get_boot_device(void); -+ -+bool stm32mp1_addr_inside_backupsram(uintptr_t addr); -+bool stm32mp1_is_wakeup_from_standby(void); -+ -+int stm32_save_boot_interface(uint32_t interface, uint32_t instance); -+int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance); -+bool stm32_boot_is_serial(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_enable_io_compensation_start(void); -+void stm32mp1_syscfg_enable_io_compensation_finish(void); - void stm32mp1_syscfg_disable_io_compensation(void); - -+#if STM32MP_USE_STM32IMAGE - uint32_t stm32mp_get_ddr_ns_size(void); -+#endif - - 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); -+ -+#if defined(IMAGE_BL32) && DEBUG -+void stm32mp_dump_core_registers(bool fcore); -+#endif - #endif /* STM32MP1_PRIVATE_H */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h -index 3f6367ebef..519a67bad8 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h -+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h -@@ -7,6 +7,8 @@ - #ifndef STM32MP1_SHARED_RESOURCES_H - #define STM32MP1_SHARED_RESOURCES_H - -+#include -+ - #include - - #define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i)) -@@ -35,4 +37,19 @@ enum stm32mp_shres { - - STM32MP1_SHRES_COUNT - }; -+ -+#ifdef STM32MP_SHARED_RESOURCES -+/* -+ * Register a (non-)secure peripheral based on the ETZPC DECPROT configuration -+ */ -+void stm32mp1_register_etzpc_decprot(unsigned int id, -+ enum etzpc_decprot_attributes attr); -+#else -+static inline -+void stm32mp1_register_etzpc_decprot(unsigned int id, -+ enum etzpc_decprot_attributes attr) -+{ -+} -+#endif -+ - #endif /* STM32MP1_SHARED_RESOURCES_H */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h -index 57240bcaf3..62210a4dd9 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_smc.h -+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h -@@ -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 - */ -@@ -17,6 +17,39 @@ - - /* 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 -+ - /* - * STM32_SMC_BSEC call API - * -@@ -29,6 +62,37 @@ - */ - #define STM32_SMC_BSEC 0x82001003 - -+/* Low Power services */ -+ -+/* -+ * 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 -+ -+/* -+ * SIP function STM32_SMC_AUTO_STOP - CPU auto stop for OS driver suspend -+ * -+ * Argument a0: (input) This SMCC ID: STM32_SMC_AUTO_STOP -+ * (output) Status return code. -+ */ -+#define STM32_SMC_AUTO_STOP 0x8200100a -+ - /* - * STM32_SIP_SMC_SCMI_AGENT0 - * STM32_SIP_SMC_SCMI_AGENT1 -@@ -50,12 +114,31 @@ - #define STM32_SIP_SVC_VERSION_MINOR 0x1 - - /* Number of STM32 SiP Calls implemented */ --#define STM32_COMMON_SIP_NUM_CALLS 3 -+#define STM32_COMMON_SIP_NUM_CALLS 9 -+ -+/* 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 */ - #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 -+ -+/* 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 -+ -+/* Service ID for STM32_SMC_RCC_OPP */ -+#define STM32_SMC_RCC_OPP_SET 0x0 -+#define STM32_SMC_RCC_OPP_ROUND 0x1 - - #endif /* STM32MP1_SMC_H */ -diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -index 1d407bb72b..d322da0090 100644 ---- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -@@ -1,5 +1,5 @@ - /* -- * 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 - */ -@@ -19,6 +19,22 @@ - * the next executable image id. - ******************************************************************************/ - static bl_mem_params_node_t bl2_mem_params_descs[] = { -+ /* Fill FW_CONFIG related information if it exists */ -+ { -+ .image_id = FW_CONFIG_ID, -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -+ VERSION_2, entry_point_info_t, -+ SECURE | NON_EXECUTABLE), -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_PLAT_SETUP), -+ -+ .image_info.image_base = STM32MP_FW_CONFIG_BASE, -+ .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE, -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, -+ }, -+ - /* Fill BL32 related information */ - { - .image_id = BL32_IMAGE_ID, -@@ -27,28 +43,17 @@ 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), - - 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 in 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 -+ IMAGE_ATTRIB_SKIP_LOADING), -+ - .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, -@@ -77,7 +82,31 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - - .next_handoff_image_id = INVALID_IMAGE_ID, - }, --#endif /* AARCH32_SP_OPTEE */ -+ -+ /* Fill HW_CONFIG related information if it exists */ -+ { -+ .image_id = HW_CONFIG_ID, -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -+ VERSION_2, entry_point_info_t, -+ NON_SECURE | NON_EXECUTABLE), -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, -+ }, -+ -+ { -+ .image_id = TOS_FW_CONFIG_ID, -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -+ VERSION_2, entry_point_info_t, -+ SECURE | NON_EXECUTABLE), -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, -+ }, - - /* Fill BL33 related information */ - { -@@ -87,17 +116,17 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - VERSION_2, entry_point_info_t, - NON_SECURE | EXECUTABLE), - -- .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET, -+#if BL33_HYP -+ .ep_info.spsr = SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, -+#else - .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, -+#endif - SPSR_E_LITTLE, - DISABLE_ALL_EXCEPTIONS), - - SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, -- VERSION_2, image_info_t, 0), -- -- .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), -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), - - .next_handoff_image_id = INVALID_IMAGE_ID, - } -diff --git a/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c -new file mode 100644 -index 0000000000..2d1332ee89 ---- /dev/null -+++ b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c -@@ -0,0 +1,111 @@ -+/* -+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+/******************************************************************************* -+ * Following descriptor provides BL image/ep information that gets used -+ * by BL2 to load the images and also subset of this information is -+ * passed to next BL image. The image loading sequence is managed by -+ * populating the images in required loading order. The image execution -+ * sequence is managed by populating the `next_handoff_image_id` with -+ * the next executable image id. -+ ******************************************************************************/ -+static bl_mem_params_node_t bl2_mem_params_descs[] = { -+ /* Fill BL32 related information */ -+ { -+ .image_id = BL32_IMAGE_ID, -+ -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, -+ VERSION_2, entry_point_info_t, -+ SECURE | EXECUTABLE | EP_FIRST_EXE), -+ -+#if !defined(AARCH32_SP_OPTEE) -+ .ep_info.pc = STM32MP_BL32_BASE, -+#endif -+ .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, -+ SPSR_E_LITTLE, -+ DISABLE_ALL_EXCEPTIONS), -+ -+ 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 in SYSRAM above BL2 */ -+ .image_info.image_base = STM32MP_OPTEE_BASE, -+ .image_info.image_max_size = STM32MP_OPTEE_SIZE, -+#else -+ .image_info.image_base = STM32MP_BL32_BASE, -+ .image_info.image_max_size = STM32MP_BL32_BIN_SIZE, -+#endif -+ .next_handoff_image_id = BL33_IMAGE_ID, -+ }, -+ -+ /* 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, -+ }, -+ -+ /* Fill BL33 related information */ -+ { -+ .image_id = BL33_IMAGE_ID, -+ -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, -+ VERSION_2, entry_point_info_t, -+ NON_SECURE | EXECUTABLE), -+ -+ .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET, -+ -+#if BL33_HYP -+ .ep_info.spsr = SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, -+#else -+ .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, -+#endif -+ SPSR_E_LITTLE, -+ DISABLE_ALL_EXCEPTIONS), -+ -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, -+ VERSION_2, image_info_t, -+ 0), -+ -+ .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, -+ } -+}; -+ -+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) -diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c -index 6d7af741a0..c6a30de5bb 100644 ---- a/plat/st/stm32mp1/plat_image_load.c -+++ b/plat/st/stm32mp1/plat_image_load.c -@@ -6,7 +6,10 @@ - - #include - -+#include - #include -+#include -+#include - #include - - /******************************************************************************* -@@ -23,12 +26,38 @@ void plat_flush_next_bl_params(void) - ******************************************************************************/ - bl_load_info_t *plat_get_bl_image_load_info(void) - { -+#if STM32MP_USE_STM32IMAGE - bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID); - uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size(); - -+ /* -+ * If going back from CSTANDBY / STANDBY and DDR was in Self-Refresh, -+ * BL33 must not be loaded as it would overwrite the code already -+ * in DDR. For this, the BL33 part of the bl_mem_params_desc_ptr -+ * struct should be modified to skip its loading -+ */ -+ if (stm32mp1_is_wakeup_from_standby()) { -+ bl_mem_params_node_t *bl32; -+ -+ bl33->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING; -+ bl32 = get_bl_mem_params_node(BL32_IMAGE_ID); -+ bl32->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING; -+#if defined(AARCH32_SP_OPTEE) -+ bl32->ep_info.pc = stm32_pm_get_optee_ep(); -+ -+ if (stm32mp1_addr_inside_backupsram(bl32->ep_info.pc)) { -+ clk_enable(BKPSRAM); -+ } -+#else -+ /* Set ep_info PC to 0, to inform BL32 it is a reset after STANDBY */ -+ bl33->ep_info.pc = 0; -+#endif -+ } -+ - /* Max size is non-secure DDR end address minus image_base */ - bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size - - bl33->image_info.image_base; -+#endif /* STM32MP_USE_STM32IMAGE */ - - return get_bl_load_info_from_mem_params_desc(); - } -@@ -38,5 +67,9 @@ bl_load_info_t *plat_get_bl_image_load_info(void) - ******************************************************************************/ - bl_params_t *plat_get_next_bl_params(void) - { -- return get_next_bl_params_from_mem_params_desc(); -+ bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc(); -+ -+ populate_next_bl_params_config(bl_params); -+ -+ return bl_params; - } -diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk -index 359581925a..067e1fff9f 100644 ---- a/plat/st/stm32mp1/platform.mk -+++ b/plat/st/stm32mp1/platform.mk -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -9,26 +9,68 @@ ARM_WITH_NEON := yes - BL2_AT_EL3 := 1 - USE_COHERENT_MEM := 0 - -+# Allow TF-A to concatenate BL2 & BL32 binaries in a single file, -+# share DTB file between BL2 and BL32 -+# If it is set to 0, then FIP and FCONF are used -+STM32MP_USE_STM32IMAGE ?= 0 -+ -+# Add specific ST version -+ST_VERSION := r1.0 -+ifeq ($(STM32MP_USE_STM32IMAGE),1) -+ST_VERSION := ${ST_VERSION}-nofip -+endif -+VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} -+ -+ifneq ($(STM32MP_USE_STM32IMAGE),1) -+ENABLE_PIE := 1 -+endif -+TRUSTED_BOARD_BOOT ?= 0 -+STM32MP_USE_EXTERNAL_HEAP ?= 0 -+ -+# Please don't increment this value without good understanding of -+# the monotonic counter - STM32_TF_VERSION ?= 0 - - # Enable dynamic memory mapping - PLAT_XLAT_TABLES_DYNAMIC := 1 - -+ifeq ($(STM32MP_USE_STM32IMAGE),1) -+BL2_IN_XIP_MEM := 0 -+else -+BL2_IN_XIP_MEM := 1 -+endif -+ -+# DDR controller with dual AXI port -+STM32MP_DDR_DUAL_AXI_PORT:= 1 -+ -+# STM32 image header version v1.0 -+STM32_HEADER_VERSION_MAJOR:= 1 -+STM32_HEADER_VERSION_MINOR:= 0 -+ -+# STM32 Secure Secret Provisioning mode (SSP) -+STM32MP_SSP ?= 0 -+ - ifeq ($(AARCH32_SP),sp_min) - # Disable Neon support: sp_min runtime may conflict with non-secure world - TF_CFLAGS += -mfloat-abi=soft - endif - -+TF_CFLAGS += -Wsign-compare -+ - # Not needed for Cortex-A7 - WORKAROUND_CVE_2017_5715:= 0 - -+AARCH32_EXCEPTION_DEBUG := 1 -+ - # Number of TF-A copies in the device - STM32_TF_A_COPIES := 2 - STM32_BL33_PARTS_NUM := 1 - ifeq ($(AARCH32_SP),optee) - STM32_RUNTIME_PARTS_NUM := 3 --else -+else ifeq ($(STM32MP_USE_STM32IMAGE),1) - STM32_RUNTIME_PARTS_NUM := 0 -+else -+STM32_RUNTIME_PARTS_NUM := 1 - endif - PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + \ - $(STM32_BL33_PARTS_NUM) + \ -@@ -41,14 +83,31 @@ STM32MP_RAW_NAND ?= 0 - STM32MP_SPI_NAND ?= 0 - STM32MP_SPI_NOR ?= 0 - --ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \ -- ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) --$(error "No boot device driver is enabled") --endif -+# Serial boot devices -+STM32MP_USB_PROGRAMMER ?= 0 -+STM32MP_UART_PROGRAMMER ?= 0 -+ -+# Hypervisor mode -+BL33_HYP ?= 0 - - # Device tree - DTB_FILE_NAME ?= stm32mp157c-ev1.dtb -+ifeq ($(STM32MP_USE_STM32IMAGE),1) -+ifeq ($(AARCH32_SP),optee) -+BL2_DTSI := stm32mp15-bl2.dtsi -+FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) -+else - FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) -+endif -+else -+BL2_DTSI := stm32mp15-bl2.dtsi -+FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) -+ifeq ($(AARCH32_SP),sp_min) -+BL32_DTSI := stm32mp15-bl32.dtsi -+FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME))) -+endif -+endif -+DTC_CPPFLAGS += ${INCLUDES} - DTC_FLAGS += -Wno-unit_address_vs_reg - - # Macros and rules to build TF binary -@@ -66,6 +125,39 @@ endif - # Variables for use with stm32image - STM32IMAGEPATH ?= tools/stm32image - STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} -+STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c -+ -+ifneq (${STM32MP_USE_STM32IMAGE},1) -+FIP_DEPS += dtbs -+STM32MP_NT_FW_CONFIG := ${BL33_CFG} -+STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME)) -+STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME) -+ifneq (${AARCH32_SP},none) -+FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME))) -+endif -+# Add the FW_CONFIG to FIP and specify the same to certtool -+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config)) -+# Add the NT_FW_CONFIG to FIP and specify the same to certtool -+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_NT_FW_CONFIG},--hw-config)) -+ifeq (${GENERATE_COT},1) -+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) -+endif -+$(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/bl2.bin,--tb-fw)) -+CRT_DEPS+=${BUILD_PLAT}/bl2.bin -+ifeq ($(AARCH32_SP),sp_min) -+STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME))) -+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config)) -+else -+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images -+# in the FIP if the platform requires. -+ifneq ($(BL32_EXTRA1),) -+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) -+endif -+ifneq ($(BL32_EXTRA2),) -+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) -+endif -+endif -+endif - - # Enable flags for C files - $(eval $(call assert_booleans,\ -@@ -76,12 +168,19 @@ $(eval $(call assert_booleans,\ - STM32MP_SPI_NAND \ - STM32MP_SPI_NOR \ - PLAT_XLAT_TABLES_DYNAMIC \ -+ STM32MP_UART_PROGRAMMER \ -+ STM32MP_USB_PROGRAMMER \ -+ STM32MP_USE_STM32IMAGE \ -+ STM32MP_DDR_DUAL_AXI_PORT \ -+ STM32MP_SSP \ -+ BL33_HYP \ - ))) - - $(eval $(call assert_numerics,\ - $(sort \ - STM32_TF_A_COPIES \ - PLAT_PARTITION_MAX_ENTRIES \ -+ STM32_TF_VERSION \ - ))) - - $(eval $(call add_defines,\ -@@ -94,6 +193,13 @@ $(eval $(call add_defines,\ - PLAT_XLAT_TABLES_DYNAMIC \ - STM32_TF_A_COPIES \ - PLAT_PARTITION_MAX_ENTRIES \ -+ STM32MP_UART_PROGRAMMER \ -+ STM32MP_USB_PROGRAMMER \ -+ STM32_TF_VERSION \ -+ STM32MP_USE_STM32IMAGE \ -+ STM32MP_DDR_DUAL_AXI_PORT \ -+ STM32MP_SSP \ -+ BL33_HYP \ - ))) - - # Include paths and source files -@@ -118,9 +224,10 @@ PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} - PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S - - PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ -+ drivers/clk/clk.c \ - drivers/delay_timer/delay_timer.c \ - drivers/delay_timer/generic_delay_timer.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/ddr/stm32mp1_ddr_helpers.c \ -@@ -129,24 +236,73 @@ 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_shres_helpers.c \ - plat/st/stm32mp1/stm32mp1_context.c \ - plat/st/stm32mp1/stm32mp1_dbgmcu.c \ - plat/st/stm32mp1/stm32mp1_helper.S \ -- plat/st/stm32mp1/stm32mp1_security.c \ - plat/st/stm32mp1/stm32mp1_syscfg.c - -+ifneq (${STM32MP_USE_STM32IMAGE},1) -+BL2_SOURCES += drivers/io/io_fip.c \ -+ plat/st/common/bl2_io_storage.c \ -+ plat/st/stm32mp1/plat_bl2_mem_params_desc.c -+ -+BL2_SOURCES += lib/fconf/fconf.c \ -+ lib/fconf/fconf_dyn_cfg_getter.c \ -+ plat/st/common/stm32mp_fconf_io.c \ -+ plat/st/stm32mp1/stm32mp1_fconf_firewall.c -+else -+BL2_SOURCES += drivers/io/io_dummy.c \ -+ drivers/st/io/io_stm32image.c \ -+ plat/st/common/bl2_stm32_io_storage.c \ -+ plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c \ -+ plat/st/stm32mp1/stm32mp1_security.c -+endif -+ - BL2_SOURCES += drivers/io/io_block.c \ -- drivers/io/io_dummy.c \ - drivers/io/io_mtd.c \ - drivers/io/io_storage.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 -+ -+ifneq (${STM32MP_USE_STM32IMAGE},1) -+ifeq (${GENERATE_COT},1) -+TFW_NVCTR_VAL := 0 -+NTFW_NVCTR_VAL := 0 -+KEY_SIZE := -+KEY_ALG := ecdsa -+HASH_ALG := sha256 -+endif -+TF_MBEDTLS_KEY_ALG := ecdsa -+MBEDTLS_CONFIG_FILE ?= "" -+ -+include drivers/auth/mbedtls/mbedtls_x509.mk -+ -+ -+AUTH_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \ -+ lib/fconf/fconf_tbbr_getter.c \ -+ plat/st/common/stm32mp_crypto_lib.c -+ -+BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_bl2.c -+else -+AUTH_SOURCES += plat/st/common/stm32mp_cot.c \ -+ plat/st/common/stm32mp_crypto_lib.c \ -+ plat/st/common/stm32mp_img_parser_lib.c -+endif -+ -+BL2_SOURCES += $(AUTH_SOURCES) \ -+ 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 \ -@@ -166,6 +322,10 @@ BL2_SOURCES += drivers/mtd/nand/spi_nand.c - endif - - ifeq (${STM32MP_SPI_NOR},1) -+ifneq (${STM32MP_FORCE_MTD_START_OFFSET},) -+$(eval $(call add_define_val,STM32MP_NOR_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET})) -+$(eval $(call add_define_val,STM32MP_NOR_BASE_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET})) -+endif - BL2_SOURCES += drivers/mtd/nor/spi_nor.c - endif - -@@ -175,6 +335,10 @@ BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \ - endif - - ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),) -+ifneq (${STM32MP_FORCE_MTD_START_OFFSET},) -+$(eval $(call add_define_val,STM32MP_NAND_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET})) -+$(eval $(call add_define_val,STM32MP_NAND_BASE_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET})) -+endif - BL2_SOURCES += drivers/mtd/nand/core.c - endif - -@@ -182,25 +346,60 @@ ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) - BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c - endif - -+ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),) -+BL2_SOURCES += drivers/io/io_memmap.c -+endif -+ -+ifeq (${STM32MP_UART_PROGRAMMER},1) -+BL2_SOURCES += drivers/st/uart/stm32_uart.c \ -+ plat/st/common/stm32cubeprogrammer_uart.c -+endif -+ -+ifeq (${STM32MP_USB_PROGRAMMER},1) -+BL2_SOURCES += drivers/st/usb_dwc2/usb_dwc2.c \ -+ lib/usb/usb_core.c \ -+ lib/usb/usb_st_dfu.c \ -+ plat/st/common/stm32cubeprogrammer_usb.c \ -+ plat/st/stm32mp1/stm32mp1_usb.c -+endif -+ - BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \ - drivers/st/ddr/stm32mp1_ram.c - - BL2_SOURCES += common/desc_image_load.c \ -- plat/st/stm32mp1/plat_bl2_mem_params_desc.c \ - plat/st/stm32mp1/plat_image_load.c - --ifeq ($(AARCH32_SP),optee) - BL2_SOURCES += lib/optee/optee_utils.c -+ -+BL2_SOURCES += plat/st/stm32mp1/stm32mp1_critic_power.c -+BL2_SOURCES += plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S -+ -+ifeq ($(STM32MP_SSP),1) -+include plat/st/stm32mp1/stm32mp1_ssp.mk - endif - - # Compilation rules --.PHONY: check_dtc_version stm32image clean_stm32image -+.PHONY: check_dtc_version stm32image clean_stm32image check_boot_device - .SUFFIXES: - - all: check_dtc_version stm32image ${STM32_TF_STM32} - - distclean realclean clean: clean_stm32image - -+bl2: check_boot_device -+ -+check_boot_device: -+ @if [ ${STM32MP_EMMC} != 1 ] && \ -+ [ ${STM32MP_SDMMC} != 1 ] && \ -+ [ ${STM32MP_RAW_NAND} != 1 ] && \ -+ [ ${STM32MP_SPI_NAND} != 1 ] && \ -+ [ ${STM32MP_SPI_NOR} != 1 ] && \ -+ [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \ -+ [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \ -+ echo "No boot device driver is enabled"; \ -+ false; \ -+ fi -+ - stm32image: ${STM32IMAGE} - - ${STM32IMAGE}: ${STM32IMAGE_SRC} -@@ -217,12 +416,35 @@ check_dtc_version: - false; \ - fi - -- -+ifeq ($(STM32MP_USE_STM32IMAGE)$(AARCH32_SP),1sp_min) - ${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} -+ @echo " AS stm32mp1.S" -+ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ -+ -DDTB_BIN_PATH=\"$<\" \ -+ -c $(word 2,$^) -o $@ -+else -+# Create DTB file for BL2 -+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs -+ @echo '#include "$(patsubst fdts/%,%,$<)"' > $@ -+ @echo '#include "${BL2_DTSI}"' >> $@ -+ -+${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts -+ -+ifeq ($(AARCH32_SP),sp_min) -+# Create DTB file for BL32 -+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs -+ @echo '#include "$(patsubst fdts/%,%,$<)"' > $@ -+ @echo '#include "${BL32_DTSI}"' >> $@ -+ -+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts -+endif -+ -+${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2 - @echo " AS stm32mp1.S" - ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ - -DDTB_BIN_PATH=\"$<\" \ - -c plat/st/stm32mp1/stm32mp1.S -o $@ -+endif - - $(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,2)) - -@@ -243,5 +465,7 @@ tf-a-%.stm32: ${STM32IMAGE} tf-a-%.bin - $(eval ENTRY = $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}')) - ${Q}${STM32IMAGE} -s $(word 2,$^) -d $@ \ - -l $(LOADADDR) -e ${ENTRY} \ -- -v ${STM32_TF_VERSION} -+ -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 2a60e43393..e3d845d2ec 100644 ---- a/plat/st/stm32mp1/services/bsec_svc.c -+++ b/plat/st/stm32mp1/services/bsec_svc.c -@@ -1,23 +1,444 @@ - /* -- * 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 "bsec_svc.h" - -+enum bsec_ssp_status { -+ BSEC_NO_SSP = 0, -+ BSEC_SSP_SET, -+ BSEC_SSP_ERROR -+}; -+ -+struct otp_exchange { -+ uint32_t version; -+ uint32_t configuration; -+ uint32_t reserved; -+ uint32_t status; -+ uint32_t general_lock; -+ uint32_t debug_conf; -+ uint32_t reserved1[2]; -+ uint32_t otp_disturb[3]; -+ uint32_t reserved2[3]; -+ uint32_t error_status[3]; -+ uint32_t reserved3[3]; -+ uint32_t permanent_lock[3]; -+ uint32_t reserved4[3]; -+ uint32_t programming_lock[3]; -+ uint32_t reserved5[3]; -+ uint32_t shadow_write_lock[3]; -+ uint32_t reserved6[3]; -+ uint32_t shadow_read_lock[3]; -+ uint32_t reserved7[3]; -+ uint32_t otp_value[STM32MP1_OTP_MAX_ID + 1]; -+ uint32_t reserved8[112]; -+ uint32_t bsec_hw_conf; -+ uint32_t ip_version; -+ uint32_t ip_id; -+ uint32_t ip_magic_id; -+}; -+ -+static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update) -+{ -+ boot_api_context_t *boot_context = -+ (boot_api_context_t *)BOOT_PARAM_ADDR; -+ -+ /* No SSP update or SSP already done*/ -+ if ((((otp & SSP_OTP_MASK) == 0U) && ((update & SSP_OTP_MASK) == 0U)) || -+ (((otp & SSP_OTP_MASK) == SSP_OTP_MASK) && -+ ((update & SSP_OTP_MASK) == SSP_OTP_MASK))) { -+ return BSEC_NO_SSP; -+ } -+ -+ /* SSP update */ -+ if ((update & SSP_OTP_MASK) != 0U) { -+ if ((update & SSP_OTP_SUCCESS) != 0U) { -+ return BSEC_SSP_ERROR; -+ } -+ -+ /* SSP boot process */ -+ boot_context->p_ssp_config->ssp_cmd = -+ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK; -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, -+ sizeof(boot_api_ssp_config_t)); -+#endif -+ if (dt_pmic_status() > 0) { -+ const char *name; -+ -+ initialize_pmic(); -+ -+ name = stm32mp_get_cpu_supply_name(); -+ if (name == NULL) { -+ return BSEC_SSP_ERROR; -+ } -+ -+ stpmic1_regulator_mask_reset_set(name); -+ } -+ -+ return BSEC_SSP_SET; -+ } -+ return BSEC_NO_SSP; -+} -+ -+static uint32_t bsec_read_all_bsec(struct otp_exchange *exchange) -+{ -+ uint32_t i; -+ uint32_t result; -+ -+ if (exchange == NULL) { -+ return BSEC_ERROR; -+ } -+ -+ exchange->version = BSEC_SERVICE_VERSION; -+ -+ for (i = 0U; i <= STM32MP1_OTP_MAX_ID; i++) { -+ if (bsec_check_nsec_access_rights(i) == BSEC_OK) { -+ result = bsec_shadow_register(i); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ result = bsec_read_otp(&exchange->otp_value[i], i); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ } -+ } -+ -+ exchange->configuration = mmio_read_32(bsec_get_base() + -+ BSEC_OTP_CONF_OFF); -+ -+ exchange->status = mmio_read_32(bsec_get_base() + BSEC_OTP_STATUS_OFF); -+ -+ exchange->general_lock = mmio_read_32(bsec_get_base() + -+ BSEC_OTP_LOCK_OFF); -+ -+ exchange->debug_conf = mmio_read_32(bsec_get_base() + BSEC_DEN_OFF); -+ -+ exchange->otp_disturb[0] = mmio_read_32(bsec_get_base() + -+ BSEC_DISTURBED_OFF); -+ -+ exchange->otp_disturb[1] = mmio_read_32(bsec_get_base() + -+ BSEC_DISTURBED1_OFF); -+ -+ exchange->otp_disturb[2] = mmio_read_32(bsec_get_base() + -+ BSEC_DISTURBED2_OFF); -+ -+ exchange->error_status[0] = mmio_read_32(bsec_get_base() + -+ BSEC_ERROR_OFF); -+ -+ exchange->error_status[1] = mmio_read_32(bsec_get_base() + -+ BSEC_ERROR1_OFF); -+ -+ exchange->error_status[2] = mmio_read_32(bsec_get_base() + -+ BSEC_ERROR2_OFF); -+ -+ exchange->permanent_lock[0] = mmio_read_32(bsec_get_base() + -+ BSEC_WRLOCK_OFF); -+ -+ exchange->permanent_lock[1] = mmio_read_32(bsec_get_base() + -+ BSEC_WRLOCK1_OFF); -+ -+ exchange->permanent_lock[2] = mmio_read_32(bsec_get_base() + -+ BSEC_WRLOCK2_OFF); -+ -+ exchange->programming_lock[0] = mmio_read_32(bsec_get_base() + -+ BSEC_SPLOCK_OFF); -+ -+ exchange->programming_lock[1] = mmio_read_32(bsec_get_base() + -+ BSEC_SPLOCK1_OFF); -+ -+ exchange->programming_lock[2] = mmio_read_32(bsec_get_base() + -+ BSEC_SPLOCK2_OFF); -+ -+ exchange->shadow_write_lock[0] = mmio_read_32(bsec_get_base() + -+ BSEC_SWLOCK_OFF); -+ -+ exchange->shadow_write_lock[1] = mmio_read_32(bsec_get_base() + -+ BSEC_SWLOCK1_OFF); -+ -+ exchange->shadow_write_lock[2] = mmio_read_32(bsec_get_base() + -+ BSEC_SWLOCK2_OFF); -+ -+ exchange->shadow_read_lock[0] = mmio_read_32(bsec_get_base() + -+ BSEC_SRLOCK_OFF); -+ -+ exchange->shadow_read_lock[1] = mmio_read_32(bsec_get_base() + -+ BSEC_SRLOCK1_OFF); -+ -+ exchange->shadow_read_lock[2] = mmio_read_32(bsec_get_base() + -+ BSEC_SRLOCK2_OFF); -+ -+ exchange->bsec_hw_conf = mmio_read_32(bsec_get_base() + -+ BSEC_IPHW_CFG_OFF); -+ -+ exchange->ip_version = mmio_read_32(bsec_get_base() + BSEC_IPVR_OFF); -+ -+ exchange->ip_id = mmio_read_32(bsec_get_base() + BSEC_IP_ID_OFF); -+ -+ exchange->ip_magic_id = mmio_read_32(bsec_get_base() + -+ BSEC_IP_MAGIC_ID_OFF); -+ -+ return BSEC_OK; -+} -+ -+static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, -+ uint32_t *ret_otp_value) -+{ -+ uint32_t i; -+ uint32_t j; -+ uint32_t start_otp = 0U; -+ uint32_t value = 0U; -+ uint32_t ret; -+ struct bsec_config config_param; -+ -+ *ret_otp_value = 0U; -+ -+ if (exchange == NULL) { -+ return BSEC_ERROR; -+ } -+ -+ if (exchange->version != BSEC_SERVICE_VERSION) { -+ return BSEC_ERROR; -+ } -+ -+ for (i = start_otp; i <= STM32MP1_OTP_MAX_ID; i++) { -+ if (bsec_check_nsec_access_rights(i) != BSEC_OK) { -+ continue; -+ } -+ -+ ret = bsec_shadow_register(i); -+ if (ret != BSEC_OK) { -+ return ret; -+ } -+ -+ ret = bsec_read_otp(&value, i); -+ if (ret != BSEC_OK) { -+ return ret; -+ } -+ -+ if ((value == exchange->otp_value[i]) && -+ (i != BOOT_API_OTP_SSP_WORD_NB)) { -+ continue; -+ } -+ -+ if (i == BOOT_API_OTP_SSP_WORD_NB) { -+ *ret_otp_value = (uint32_t)bsec_check_ssp(value, -+ exchange->otp_value[i]); -+ VERBOSE("Result OTP SSP %d\n", *ret_otp_value); -+ if (*ret_otp_value == (uint32_t)BSEC_SSP_ERROR) { -+ continue; -+ } -+ } -+ -+ ret = bsec_program_otp(exchange->otp_value[i], i); -+ if (ret != BSEC_OK) { -+ return ret; -+ } -+ -+ ret = bsec_write_otp(exchange->otp_value[i], i); -+ if (ret != BSEC_OK) { -+ return ret; -+ } -+ } -+ -+ bsec_write_debug_conf(exchange->debug_conf); -+ -+ for (j = 0U; j < 3U; j++) { -+ if (exchange->permanent_lock[j] == 0U) { -+ continue; -+ } -+ -+ for (i = 0U; i < 32U; i++) { -+ if (bsec_check_nsec_access_rights((32U * j) + i) != -+ BSEC_OK) { -+ continue; -+ } -+ -+ value = (exchange->permanent_lock[j] >> i) & 1U; -+ if (value != 0U) { -+ ret = bsec_permanent_lock_otp((32U * j) + i); -+ if (ret != BSEC_OK) { -+ return ret; -+ } -+ } -+ } -+ } -+ -+ for (j = 0U; j < 3U; j++) { -+ if (exchange->programming_lock[j] == 0U) { -+ continue; -+ } -+ -+ for (i = 0U; i < 32U; i++) { -+ if (bsec_check_nsec_access_rights((32U * j) + i) != -+ BSEC_OK) { -+ continue; -+ } -+ -+ value = (exchange->programming_lock[j] >> i) & 1U; -+ if (value != 0U) { -+ if (bsec_set_sp_lock((32U * j) + i) != -+ BSEC_OK) { -+ return BSEC_ERROR; -+ } -+ } -+ } -+ } -+ -+ for (j = 0U; j < 3U; j++) { -+ if (exchange->shadow_write_lock[j] == 0U) { -+ continue; -+ } -+ -+ for (i = 0U; i < 32U; i++) { -+ if (bsec_check_nsec_access_rights((32U * j) + i) != -+ BSEC_OK) { -+ continue; -+ } -+ -+ value = (exchange->shadow_write_lock[j] >> i) & 1U; -+ if (value != 0U) { -+ if (bsec_set_sw_lock((32U * j) + i) != -+ BSEC_OK) { -+ return BSEC_ERROR; -+ } -+ } -+ } -+ } -+ -+ for (j = 0U; j < 3U; j++) { -+ if (exchange->shadow_read_lock[j] == 0U) { -+ continue; -+ } -+ -+ for (i = 0U; i < 32U; i++) { -+ if (bsec_check_nsec_access_rights((32U * j) + i) != -+ BSEC_OK) { -+ continue; -+ } -+ -+ value = (exchange->shadow_read_lock[j] >> i) & 1U; -+ if (value != 0U) { -+ if (bsec_set_sr_lock((32U * j) + i) != -+ BSEC_OK) { -+ return BSEC_ERROR; -+ } -+ } -+ } -+ } -+ -+ ret = bsec_get_config(&config_param); -+ if (ret != BSEC_OK) { -+ return ret; -+ } -+ -+ config_param.power = -+ (uint8_t)(exchange->configuration & BSEC_CONF_POWER_UP_MASK) >> -+ BSEC_CONF_POWER_UP_SHIFT; -+ config_param.freq = -+ (uint8_t)(exchange->configuration & BSEC_CONF_FRQ_MASK) >> -+ BSEC_CONF_FRQ_SHIFT; -+ config_param.pulse_width = -+ (uint8_t)(exchange->configuration & BSEC_CONF_PRG_WIDTH_MASK) >> -+ BSEC_CONF_PRG_WIDTH_SHIFT; -+ config_param.tread = -+ (uint8_t)((exchange->configuration & BSEC_CONF_TREAD_MASK) >> -+ BSEC_CONF_TREAD_SHIFT); -+ config_param.den_lock = -+ (uint8_t)(exchange->general_lock & DENREG_LOCK_MASK) >> -+ DENREG_LOCK_SHIFT; -+ config_param.prog_lock = -+ (uint8_t)(exchange->general_lock & GPLOCK_LOCK_MASK) >> -+ GPLOCK_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) { -+ return ret; -+ } -+ -+ INFO("write all otp succeed\n"); -+ -+ return BSEC_OK; -+} -+ - 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 STM32_SMC_INVALID_PARAMS; -+ } -+ -+ otp_exch = NULL; -+ map_begin = 0U; -+ -+ if ((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) { -+ if (!stm32_boot_is_serial()) { -+ return STM32_SMC_FAILED; -+ } -+ -+ 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; -+ } - - switch (x1) { - case STM32_SMC_READ_SHADOW: -@@ -25,6 +446,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, 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: -@@ -50,11 +483,23 @@ 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; -+ 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; -+ case STM32_SMC_WRLOCK_OTP: -+ result = bsec_permanent_lock_otp(x2); -+ break; -+ default: -+ return STM32_SMC_INVALID_PARAMS; -+ } -+ -+ if ((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) { -+ ret = mmap_remove_dynamic_region(map_begin, map_size); -+ assert(ret == 0); - } - -- 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 0000000000..567a3c70f5 ---- /dev/null -+++ b/plat/st/stm32mp1/services/low_power_svc.c -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+#include -+ -+#include "low_power_svc.h" -+ -+uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2) -+{ -+ if (stm32mp1_set_pm_domain_state((enum stm32mp1_pm_domain)x1, -+ (bool)x2) < 0) { -+ return STM32_SMC_FAILED; -+ } -+ -+ return STM32_SMC_OK; -+} -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 0000000000..eb98e92252 ---- /dev/null -+++ b/plat/st/stm32mp1/services/low_power_svc.h -@@ -0,0 +1,14 @@ -+/* -+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef LOW_POWER_SVC_H -+#define LOW_POWER_SVC_H -+ -+#include -+ -+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 0000000000..1213d7ef64 ---- /dev/null -+++ b/plat/st/stm32mp1/services/pwr_svc.c -@@ -0,0 +1,102 @@ -+/* -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "pwr_svc.h" -+ -+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; -+ -+ stm32mp_pwr_regs_lock(); -+ -+ switch (request) { -+ case STM32_SMC_REG_WRITE: -+ mmio_clrsetbits_32(addr, allowed_mask, masked_value); -+ VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value, -+ mmio_read_32(addr)); -+ break; -+ -+ case STM32_SMC_REG_SET: -+ mmio_setbits_32(addr, masked_value); -+ VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value, -+ mmio_read_32(addr)); -+ break; -+ -+ case STM32_SMC_REG_CLEAR: -+ mmio_clrbits_32(addr, masked_value); -+ VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value, -+ mmio_read_32(addr)); -+ break; -+ -+ default: -+ break; -+ } -+ -+ stm32mp_pwr_regs_unlock(); -+} -+ -+static void raw_allowed_access_request(uint32_t request, -+ uint32_t offset, uint32_t value) -+{ -+ uint32_t allowed_mask = 0; -+ -+ switch (offset) { -+ case PWR_CR3: -+ allowed_mask |= PWR_CR3_VBE | PWR_CR3_VBRS | PWR_CR3_USB33DEN | -+ PWR_CR3_REG18EN | PWR_CR3_REG11EN; -+ break; -+ -+ case PWR_WKUPCR: -+ allowed_mask |= PWR_WKUPCR_MASK; -+ break; -+ -+ case PWR_MPUWKUPENR: -+ allowed_mask |= PWR_MPUWKUPENR_MASK; -+ break; -+ -+ default: -+ return; -+ } -+ -+ if (allowed_mask != 0U) { -+ access_allowed_mask(request, offset, value, allowed_mask); -+ } -+} -+ -+uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) -+{ -+ uint32_t request = x1; -+ uint32_t offset = x2; -+ uint32_t value = x3; -+ -+ /* -+ * x2 may be either the PWR register offset or the register -+ * full physical address. -+ */ -+ if ((offset & ~PWR_OFFSET_MASK) != 0) { -+ if ((offset & ~PWR_OFFSET_MASK) != stm32mp_pwr_base()) { -+ return STM32_SMC_INVALID_PARAMS; -+ } -+ -+ offset &= PWR_OFFSET_MASK; -+ } -+ -+ /* PWR controls for non secure resource may be accessed straight */ -+ raw_allowed_access_request(request, offset, value); -+ -+ return STM32_SMC_OK; -+} -diff --git a/plat/st/stm32mp1/services/pwr_svc.h b/plat/st/stm32mp1/services/pwr_svc.h -new file mode 100644 -index 0000000000..6dacdf80d7 ---- /dev/null -+++ b/plat/st/stm32mp1/services/pwr_svc.h -@@ -0,0 +1,12 @@ -+/* -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef PWR_SVC_H -+#define PWR_SVC_H -+ -+uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); -+ -+#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 0000000000..0be76bbda4 ---- /dev/null -+++ b/plat/st/stm32mp1/services/rcc_svc.c -@@ -0,0 +1,169 @@ -+/* -+ * 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 "rcc_svc.h" -+ -+static bool offset_is_clear_register(uint32_t __unused offset) -+{ -+ /* All currently allowed registers are non set/clear registers */ -+ return false; -+} -+ -+static void access_allowed_mask(uint32_t request, uint32_t offset, -+ uint32_t value, uint32_t allowed_mask) -+{ -+ uint32_t addr = stm32mp_rcc_base() + offset; -+ uint32_t masked_value = value & allowed_mask; -+ -+ switch (request) { -+ case STM32_SMC_REG_WRITE: -+ if (offset_is_clear_register(offset)) { -+ mmio_write_32(addr, masked_value); -+ } else { -+ stm32mp_mmio_clrsetbits_32_shregs(addr, allowed_mask, -+ masked_value); -+ } -+ VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value, -+ mmio_read_32(addr)); -+ break; -+ -+ case STM32_SMC_REG_SET: -+ if (offset_is_clear_register(offset)) { -+ mmio_write_32(addr, masked_value); -+ } else { -+ stm32mp_mmio_setbits_32_shregs(addr, masked_value); -+ } -+ VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value, -+ mmio_read_32(addr)); -+ break; -+ -+ case STM32_SMC_REG_CLEAR: -+ if (offset_is_clear_register(offset)) { -+ /* Nothing to do on CLR registers */ -+ } else { -+ stm32mp_mmio_clrbits_32_shregs(addr, masked_value); -+ } -+ VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value, -+ mmio_read_32(addr)); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static uint32_t raw_allowed_access_request(uint32_t request, -+ uint32_t offset, uint32_t value) -+{ -+ uint32_t allowed_mask = 0; -+ -+ switch (offset) { -+ case RCC_MP_CIER: -+ case RCC_MP_CIFR: -+ allowed_mask = RCC_MP_CIFR_WKUPF; -+ break; -+ default: -+ return STM32_SMC_INVALID_PARAMS; -+ } -+ -+ if (allowed_mask != 0U) { -+ access_allowed_mask(request, offset, value, allowed_mask); -+ } -+ -+ return STM32_SMC_OK; -+} -+ -+uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) -+{ -+ uint32_t request = x1; -+ uint32_t offset = x2; -+ uint32_t value = x3; -+ -+ /* -+ * x2 may be either the RCC register offset or the register -+ * full physical address. -+ */ -+ if ((offset & ~RCC_OFFSET_MASK) != 0) { -+ if ((offset & ~RCC_OFFSET_MASK) != stm32mp_rcc_base()) { -+ return STM32_SMC_INVALID_PARAMS; -+ } -+ -+ offset &= RCC_OFFSET_MASK; -+ } -+ -+ return raw_allowed_access_request(request, offset, value); -+} -+ -+uint32_t rcc_cal_scv_handler(uint32_t x1) -+{ -+ uint32_t ret = STM32_SMC_FAILED; -+ -+ switch (x1) { -+ case CK_CSI: -+ if (stm32mp1_calib_start_csi_cal() == 0) { -+ ret = STM32_SMC_OK; -+ } -+ break; -+ -+ case CK_HSI: -+ if (stm32mp1_calib_start_hsi_cal() == 0) { -+ ret = STM32_SMC_OK; -+ } -+ break; -+ -+ default: -+ ret = STM32_SMC_INVALID_PARAMS; -+ break; -+ } -+ -+ 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 0000000000..23c75824f0 ---- /dev/null -+++ b/plat/st/stm32mp1/services/rcc_svc.h -@@ -0,0 +1,14 @@ -+/* -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef RCC_SVC_H -+#define RCC_SVC_H -+ -+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 49375a62d0..037a0b40b8 100644 ---- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c -@@ -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 - */ -@@ -13,9 +13,13 @@ - #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, -@@ -66,6 +70,32 @@ 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; -+ -+ case STM32_SMC_RCC_CAL: -+ 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; -+ -+ case STM32_SMC_PD_DOMAIN: -+ ret1 = pm_domain_scv_handler(x1, x2); -+ break; -+ -+ case STM32_SMC_AUTO_STOP: -+ stm32_auto_stop(); -+ ret1 = STM32_SMC_OK; -+ break; -+ - case STM32_SIP_SMC_SCMI_AGENT0: - scmi_smt_fastcall_smc_entry(0); - break; -@@ -75,7 +105,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-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -index 8866fb556c..dd81d13a08 100644 ---- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -@@ -1,17 +1,31 @@ - # --# 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 - # - - SP_MIN_WITH_SECURE_FIQ := 1 - -+# Allow SP_min to be placed in DDR -+STM32MP_SP_MIN_IN_DDR ?= 0 -+ -+$(eval $(call assert_booleans, STM32MP_SP_MIN_IN_DDR)) -+ -+$(eval $(call add_defines, STM32MP_SP_MIN_IN_DDR)) -+ - BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES - --BL32_SOURCES += drivers/st/etzpc/etzpc.c \ -+BL32_SOURCES += drivers/st/clk/stm32mp1_calib.c \ -+ drivers/st/etzpc/etzpc.c \ -+ drivers/st/rng/stm32_rng.c \ -+ drivers/st/rtc/stm32_rtc.c \ -+ drivers/st/tamper/stm32_tamp.c \ -+ drivers/st/timer/stm32_timer.c \ - plat/common/aarch32/platform_mp_stack.S \ - plat/st/stm32mp1/sp_min/sp_min_setup.c \ -+ 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 - -@@ -20,11 +34,14 @@ include drivers/arm/gic/v2/gicv2.mk - - BL32_SOURCES += ${GICV2_SOURCES} \ - 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 - -+# Generic FDT -+BL32_SOURCES += common/fdt_fixup.c -+ - # SCMI server drivers - BL32_SOURCES += drivers/st/scmi-msg/base.c \ - drivers/st/scmi-msg/clock.c \ -@@ -34,8 +51,15 @@ BL32_SOURCES += drivers/st/scmi-msg/base.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/stm32mp1_scmi.c - - # Arm Archtecture services - BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c -+ -+ifneq ($(STM32MP_SP_MIN_IN_DDR),1) -+BL32_SOURCES += plat/st/stm32mp1/stm32mp1_critic_power.c -+endif -diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c -index b639fcb358..0065be44fd 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-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,16 +12,27 @@ - #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 -@@ -29,6 +40,9 @@ - #include - - #include -+#include -+#include -+#include - - /****************************************************************************** - * Placeholder variables for copying the arguments that have been passed to -@@ -37,6 +51,132 @@ - static entry_point_info_t bl33_image_ep_info; - - static console_t 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] = { -+ { -+ .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, -+}; -+ -+static struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT] = { -+ TAMP_UNUSED, -+ TAMP_UNUSED, -+ TAMP_UNUSED, -+}; -+ -+static void stm32_sgi1_it_handler(void) -+{ -+ uint32_t id; -+ -+ stm32mp_mask_timer(); -+ -+#if DEBUG -+ stm32mp_dump_core_registers(false); -+#endif -+ -+ gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_1); -+ -+ 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); -+ -+ stm32mp_wait_cpu_reset(); -+} -+ -+static void stm32mp1_tamper_action(int id) -+{ -+ ERROR("Tamper %s occurs\n", tamper_name[id]); -+ stm32mp_system_reset(); -+} -+ -+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(); -+ } -+} -+ -+static void disable_usb_phy_regulator(void) -+{ -+ if (dt_pmic_status() > 0) { -+ const char *name = stm32mp_get_usb_phy_supply_name(); -+ int ret; -+ -+ if (name == NULL) { -+ return; -+ } -+ -+ ret = stpmic1_regulator_disable(name); -+ if (ret < 0) { -+ WARN("USBPHYC phy-supply (%s) disable failed\n", name); -+ } -+ } -+} - - /******************************************************************************* - * Interrupt handler for FIQ (secure IRQ) -@@ -44,20 +184,75 @@ static console_t console; - void sp_min_plat_fiq_handler(uint32_t id) - { - switch (id & INT_ID_MASK) { -+ case ARM_IRQ_SEC_PHY_TIMER: -+ case STM32MP1_IRQ_MCU_SEV: -+ case STM32MP1_IRQ_RCC_WAKEUP: -+ stm32mp1_calib_it_handler(id); -+ break; - case STM32MP1_IRQ_TZC400: -- ERROR("STM32MP1_IRQ_TZC400 generated\n"); -+ tzc400_init(STM32MP1_TZC_BASE); -+ tzc400_it_handler(); - panic(); - break; -+ case STM32MP1_IRQ_TAMPSERRS: -+ stm32_tamp_it_handler(); -+ break; -+ case ARM_IRQ_SEC_SGI_1: -+ stm32_sgi1_it_handler(); -+ break; -+ case ARM_IRQ_SEC_SGI_6: -+ /* tell the primary cpu to exit from stm32_pwr_down_wfi() */ -+ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) { -+ stm32mp1_calib_set_wakeup(true); -+ } -+ gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_6); -+ break; -+ case STM32MP1_IRQ_IWDG1: -+ case STM32MP1_IRQ_IWDG2: -+ stm32_iwdg_it_handler(id); -+ break; - case STM32MP1_IRQ_AXIERRIRQ: - ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n"); - panic(); - break; - default: -- ERROR("SECURE IT handler not define for it : %u", id); -+ ERROR("SECURE IT handler not define for it : %u\n", id); - break; - } - } - -+/******************************************************************************* -+ * Return the value of the saved PC from the backup register if present -+ ******************************************************************************/ -+static uintptr_t get_saved_pc(void) -+{ -+ uint32_t bkpr_core1_addr = -+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); -+ uint32_t saved_pc; -+ uint32_t bkpr_core1_magic = -+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); -+ uint32_t magic_nb; -+ -+ clk_enable(RTCAPB); -+ -+ magic_nb = mmio_read_32(bkpr_core1_magic); -+ saved_pc = mmio_read_32(bkpr_core1_addr); -+ -+ clk_disable(RTCAPB); -+ -+ if (magic_nb != BOOT_API_A7_CORE0_MAGIC_NUMBER) { -+ return 0U; -+ } -+ -+ /* BL33 return address should be in DDR */ -+ if ((saved_pc < STM32MP_DDR_BASE) || -+ (saved_pc > (STM32MP_DDR_BASE + (dt_get_ddr_size() - 1U)))) { -+ panic(); -+ } -+ -+ return saved_pc; -+} -+ - /******************************************************************************* - * Return a pointer to the 'entry_point_info' structure of the next image for - * the security state specified. BL33 corresponds to the non-secure image type -@@ -66,12 +261,36 @@ 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; -- -- next_image_info = &bl33_image_ep_info; -+ entry_point_info_t *next_image_info = &bl33_image_ep_info; - -+ /* -+ * PC is set to 0 when resetting after STANDBY -+ * The context should be restored, and the image information -+ * should be filled with what was saved -+ */ - if (next_image_info->pc == 0U) { -- return NULL; -+ void *cpu_context; -+ uintptr_t saved_pc; -+ -+ if (stm32_restore_context() != 0) { -+ panic(); -+ } -+ -+ cpu_context = cm_get_context(NON_SECURE); -+ -+ next_image_info->spsr = read_ctx_reg(get_regs_ctx(cpu_context), -+ CTX_SPSR); -+ -+ /* PC should be retrieved in backup register if OK, else it can -+ * be retrieved from non-secure context -+ */ -+ saved_pc = get_saved_pc(); -+ if (saved_pc != 0U) { -+ next_image_info->pc = saved_pc; -+ } else { -+ next_image_info->pc = -+ read_ctx_reg(get_regs_ctx(cpu_context), CTX_LR); -+ } - } - - return next_image_info; -@@ -108,15 +327,107 @@ static void stm32mp1_etzpc_early_setup(void) - etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE); - } - -+#if !STM32MP_USE_STM32IMAGE -+static void populate_ns_dt(u_register_t ns_dt_addr, uintptr_t sec_base, size_t sec_size) -+{ -+ void *external_fdt = (void *)ns_dt_addr; -+ int ret; -+ -+ if (sec_base < STM32MP_DDR_BASE) { -+ /* No need to reserve memory if secure monitor is not in DDR */ -+ return; -+ } -+ -+ /* Map Base Non Secure DDR for Non secure DT update */ -+ ret = mmap_add_dynamic_region(ns_dt_addr, ns_dt_addr, STM32MP_HW_CONFIG_MAX_SIZE, -+ MT_NON_CACHEABLE | MT_EXECUTE_NEVER | MT_RW | MT_NS); -+ assert(ret == 0); -+ -+ if (fdt_check_header(external_fdt) != 0) { -+ INFO("Non-secure device tree not found\n"); -+ -+ goto out; -+ } -+ -+ ret = fdt_open_into(external_fdt, external_fdt, STM32MP_HW_CONFIG_MAX_SIZE); -+ if (ret < 0) { -+ WARN("Error opening DT %i\n", ret); -+ goto out; -+ } -+ -+ ret = fdt_add_reserved_memory(external_fdt, "tf-a", sec_base, sec_size); -+ if (ret < 0) { -+ WARN("Error updating DT %i\n", ret); -+ goto out; -+ } -+ -+ ret = fdt_pack(external_fdt); -+ if (ret < 0) { -+ WARN("Error packing DT %i\n", ret); -+ } -+ -+out: -+ ret = mmap_remove_dynamic_region(ns_dt_addr, STM32MP_HW_CONFIG_MAX_SIZE); -+ assert(ret == 0); -+} -+#endif -+ -+/******************************************************************************* -+ * Setup UART console using device tree information. -+ ******************************************************************************/ -+static void setup_uart_console(void) -+{ -+ struct dt_node_info dt_uart_info; -+ unsigned int console_flags; -+ int result; -+ uint32_t boot_itf; -+ uint32_t boot_instance; -+ -+ result = dt_get_stdout_uart_info(&dt_uart_info); -+ if ((result <= 0) || (dt_uart_info.status == DT_DISABLED)) { -+ return; -+ } -+ -+ stm32_get_boot_interface(&boot_itf, &boot_instance); -+ -+ if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) && -+ (get_uart_address(boot_instance) == dt_uart_info.base)) { -+ return; -+ } -+ -+ if (console_stm32_register(dt_uart_info.base, 0, -+ STM32MP_UART_BAUDRATE, &console) == 0U) { -+ panic(); -+ } -+ -+ console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | -+ CONSOLE_FLAG_TRANSLATE_CRLF; -+#ifdef DEBUG -+ console_flags |= CONSOLE_FLAG_RUNTIME; -+#endif -+ console_set_scope(&console, console_flags); -+} -+ - /******************************************************************************* - * 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) - { -- struct dt_node_info dt_uart_info; -- int result; - bl_params_t *params_from_bl2 = (bl_params_t *)arg0; -+#if STM32MP_USE_STM32IMAGE -+ uintptr_t dt_addr = STM32MP_DTB_BASE; -+#else -+ uintptr_t dt_addr = arg1; -+ uintptr_t sec_base = 0U; -+ size_t sec_size = 0U; -+#endif -+#if STM32MP_SP_MIN_IN_DDR -+ uintptr_t bl2_code_base = 0U; -+ uintptr_t bl2_code_end = 0U; -+ uintptr_t bl2_end = 0U; -+ int result __unused; -+#endif - - /* Imprecise aborts can be masked in NonSecure */ - write_scr(read_scr() | SCR_AW_BIT); -@@ -125,59 +436,152 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - BL_CODE_END - BL_CODE_BASE, - MT_CODE | MT_SECURE); - -+#if STM32MP_SP_MIN_IN_DDR -+ /* BL32 data*/ -+ mmap_add_region(BL_CODE_END, BL_CODE_END, -+ BL_END - BL_CODE_END, -+ MT_RW_DATA | MT_SECURE); -+ -+ /* BL32 Device Tree Blob */ -+ mmap_add_region(dt_addr, dt_addr, -+ STM32MP_BL32_DTB_SIZE, -+ MT_RO_DATA | MT_SECURE); -+ -+ /* Map SCMI shared buffers */ -+ mmap_add_region(STM32MP_SCMI_NS_SHM_BASE, STM32MP_SCMI_NS_SHM_BASE, -+ STM32MP_SCMI_NS_SHM_SIZE, -+ MT_DEVICE | MT_RW | MT_NS | MT_EXECUTE_NEVER); -+#endif -+ - configure_mmu(); - -+ if (dt_open_and_check(dt_addr) < 0) { -+ panic(); -+ } -+ -+ if (bsec_probe() != 0) { -+ panic(); -+ } -+ -+ if (stm32mp1_clk_probe() < 0) { -+ panic(); -+ } -+ -+ setup_uart_console(); -+ -+ stm32mp1_etzpc_early_setup(); -+ -+#if STM32MP_SP_MIN_IN_DDR -+ stm32_context_get_bl2_low_power_params(&bl2_code_base, &bl2_code_end, &bl2_end); -+ -+ /* BL2 Code */ -+ result = mmap_add_dynamic_region(bl2_code_base, bl2_code_base, -+ bl2_code_end - bl2_code_base, -+ MT_CODE | MT_SECURE); -+ assert(result == 0); -+ -+ /* BL2 RW memory */ -+ result = mmap_add_dynamic_region(bl2_code_end, bl2_code_end, -+ bl2_end - bl2_code_end, -+ MT_RW_DATA | MT_SECURE); -+ assert(result == 0); -+#endif -+ - assert(params_from_bl2 != NULL); - assert(params_from_bl2->h.type == PARAM_BL_PARAMS); - assert(params_from_bl2->h.version >= VERSION_2); - - bl_params_node_t *bl_params = params_from_bl2->head; - -- /* -- * Copy BL33 entry point information. -- * They are stored in Secure RAM, in BL2's address space. -- */ - while (bl_params != NULL) { -+ /* -+ * Copy BL33 entry point information. -+ * They are stored in Secure RAM, in BL2's address space. -+ */ - if (bl_params->image_id == BL33_IMAGE_ID) { - bl33_image_ep_info = *bl_params->ep_info; -- break; -+ /* -+ * Check if hw_configuration is given to BL32 and -+ * share it to BL33 -+ */ -+ if (arg2 != 0U) { -+ bl33_image_ep_info.args.arg0 = 0U; -+ bl33_image_ep_info.args.arg1 = 0U; -+ bl33_image_ep_info.args.arg2 = arg2; -+ } - } - -+#if !STM32MP_USE_STM32IMAGE -+ if (bl_params->image_id == BL32_IMAGE_ID) { -+ sec_base = bl_params->image_info->image_base; -+ sec_size = bl_params->image_info->image_max_size; -+ } -+#endif -+ - bl_params = bl_params->next_params_info; - } - -- if (dt_open_and_check() < 0) { -- panic(); -- } -+#if !STM32MP_USE_STM32IMAGE -+ if (arg2 != 0U) { -+ /* This will expect the BL32 DT and BL32 are grouped */ -+ if (dt_addr < sec_base) { -+ sec_size = sec_size + sec_base - dt_addr; -+ sec_base = dt_addr; -+ } else { -+ sec_size = dt_addr - sec_base + STM32MP_BL32_DTB_SIZE; -+ } - -- if (bsec_probe() != 0) { -- panic(); -+ populate_ns_dt(arg2, sec_base, sec_size); -+ } else { -+ INFO("Non-secure device tree not found\n"); - } -+#endif - -- if (stm32mp1_clk_probe() < 0) { -- panic(); -+ if (dt_pmic_status() > 0) { -+ initialize_pmic(); - } - -- result = dt_get_stdout_uart_info(&dt_uart_info); -+ disable_usb_phy_regulator(); - -- if ((result > 0) && (dt_uart_info.status != 0U)) { -- unsigned int console_flags; -+ initialize_pll1_settings(); - -- if (console_stm32_register(dt_uart_info.base, 0, -- STM32MP_UART_BAUDRATE, &console) == -- 0) { -- panic(); -- } -+ stm32mp1_init_lp_states(); -+} - -- console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | -- CONSOLE_FLAG_TRANSLATE_CRLF; --#ifdef DEBUG -- console_flags |= CONSOLE_FLAG_RUNTIME; --#endif -- console_set_scope(&console, console_flags); -+static void init_sec_peripherals(void) -+{ -+ uint32_t filter_conf = 0; -+ uint32_t active_conf = 0; -+ int ret; -+ -+ /* Disable MCU subsystem protection */ -+ stm32mp1_clk_mcuss_protect(false); -+ -+ /* Init rtc driver */ -+ ret = stm32_rtc_init(); -+ if (ret < 0) { -+ WARN("RTC driver init error %i\n", ret); - } - -- stm32mp1_etzpc_early_setup(); -+ /* Init rng driver */ -+ ret = stm32_rng_init(); -+ if (ret < 0) { -+ WARN("RNG driver init error %i\n", ret); -+ } -+ -+ /* Init tamper */ -+ if (stm32_tamp_init() > 0) { -+ stm32_tamp_configure_internal(int_tamp, PLAT_MAX_TAMP_INT); -+ stm32_tamp_configure_external(ext_tamp, PLAT_MAX_TAMP_EXT, -+ filter_conf, active_conf); -+ -+ /* Enable timestamp for tamper */ -+ stm32_rtc_set_tamper_timestamp(); -+ } -+ -+ if (stm32_timer_init() == 0) { -+ stm32mp1_calib_init(); -+ } - } - - /******************************************************************************* -@@ -185,17 +589,22 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - ******************************************************************************/ - void sp_min_platform_setup(void) - { -- /* Initialize tzc400 after DDR initialization */ -- stm32mp1_security_setup(); -+ stm32_init_low_power(); -+ -+ ddr_save_sr_mode(); - - generic_delay_timer_init(); - -- stm32mp1_gic_init(); -+ stm32_gic_init(); -+ -+ init_sec_peripherals(); - - if (stm32_iwdg_init() < 0) { - panic(); - } - -+ configure_wakeup_interrupt(); -+ - stm32mp_lock_periph_registering(); - - stm32mp1_init_scmi_server(); -diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S -index 7255fe5aa9..1b7e9e7eff 100644 ---- a/plat/st/stm32mp1/stm32mp1.S -+++ b/plat/st/stm32mp1/stm32mp1.S -@@ -1,13 +1,15 @@ - /* -- * 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 - */ - -+#if STM32MP_USE_STM32IMAGE - #ifdef BL32_BIN_PATH - .section .bl32_image - .incbin BL32_BIN_PATH - #endif -+#endif - - .section .bl2_image - .incbin BL2_BIN_PATH -diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S -index b347baddf7..43e2733397 100644 ---- a/plat/st/stm32mp1/stm32mp1.ld.S -+++ b/plat/st/stm32mp1/stm32mp1.ld.S -@@ -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 - */ -@@ -16,7 +16,7 @@ OUTPUT_ARCH(PLATFORM_LINKER_ARCH) - ENTRY(__BL2_IMAGE_START__) - - MEMORY { -- HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000 -+ HEADER (rw) : ORIGIN = 0x00000000, LENGTH = STM32MP_HEADER_RESERVED_SIZE - RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE - } - -@@ -43,7 +43,11 @@ SECTIONS - * The strongest and only alignment contraint is MMU 4K page. - * Indeed as images below will be removed, 4K pages will be re-used. - */ -+#if STM32MP_USE_STM32IMAGE - . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE ); -+#else -+ . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE ); -+#endif - __DTB_IMAGE_START__ = .; - *(.dtb_image*) - __DTB_IMAGE_END__ = .; -@@ -53,12 +57,16 @@ SECTIONS - * The strongest and only alignment contraint is MMU 4K page. - * Indeed as images below will be removed, 4K pages will be re-used. - */ -+#if SEPARATE_CODE_AND_RODATA -+ . = ( STM32MP_BL2_RO_BASE - STM32MP_BINARY_BASE ); -+#else - . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE ); -+#endif - __BL2_IMAGE_START__ = .; - *(.bl2_image*) - __BL2_IMAGE_END__ = .; - --#ifndef AARCH32_SP_OPTEE -+#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) - /* - * bl32 will be settled by bl2. - * The strongest and only alignment constraint is 8 words to simplify -diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c -index 997335d0da..690d8f04c9 100644 ---- a/plat/st/stm32mp1/stm32mp1_boot_device.c -+++ b/plat/st/stm32mp1/stm32mp1_boot_device.c -@@ -19,13 +19,11 @@ - #if STM32MP_RAW_NAND || STM32MP_SPI_NAND - static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) - { -- int result; - uint32_t nand_param; - - /* Check if NAND parameters are stored in OTP */ -- result = bsec_shadow_read_otp(&nand_param, NAND_OTP); -- if (result != BSEC_OK) { -- ERROR("BSEC: NAND_OTP Error %i\n", result); -+ if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) { -+ ERROR("BSEC: NAND_OTP Error\n"); - return -EACCES; - } - -diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c -index cf8a91eb41..027475ed40 100644 ---- a/plat/st/stm32mp1/stm32mp1_context.c -+++ b/plat/st/stm32mp1/stm32mp1_context.c -@@ -1,35 +1,492 @@ - /* -- * 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 - */ - - #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 -+#include -+#include - --int stm32_save_boot_interface(uint32_t interface, uint32_t instance) -+#define TRAINING_AREA_SIZE 64 -+ -+#define BL32_CANARY_ID U(0x424c3332) -+ -+/* -+ * MAILBOX_MAGIC relates to struct backup_data_s as defined -+ * -+ * MAILBOX_MAGIC_V1: -+ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer. -+ * -+ * MAILBOX_MAGIC_V2: -+ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer -+ * and PLL1 dual OPP settings structure (86 bytes). -+ * -+ * MAILBOX_MAGIC_V3: -+ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer -+ * and PLL1 dual OPP settings structure, low power entry point, BL2 code start, end and BL2_END -+ * (102 bytes). -+ */ -+#define MAILBOX_MAGIC_V1 (0x0001 << 16) -+#define MAILBOX_MAGIC_V2 (0x0002 << 16) -+#define MAILBOX_MAGIC_V3 (0x0003 << 16) -+#define MAILBOX_MAGIC (MAILBOX_MAGIC_V3 | \ -+ 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 MAILBOX_MAGIC_V2/_V3 does not support expected PLL1 settings -+#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 { -+ 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]; -+ uint32_t low_power_ep; -+ uint32_t bl2_code_base; -+ uint32_t bl2_code_end; -+ uint32_t bl2_end; -+}; -+ -+#if defined(IMAGE_BL32) -+struct backup_bl32_data_s { -+ uint32_t canary_id; -+ smc_ctx_t saved_smc_context[PLATFORM_CORE_COUNT]; -+ cpu_context_t saved_cpu_context[PLATFORM_CORE_COUNT]; -+ struct stm32_rtc_calendar rtc; -+ unsigned long long stgen; -+ uint8_t clock_cfg[CLOCK_CONTEXT_SIZE]; -+ uint8_t scmi_context[SCMI_CONTEXT_SIZE]; -+}; -+ -+static struct backup_bl32_data_s *get_bl32_backup_data(void) -+{ -+ return (struct backup_bl32_data_s *)(STM32MP_BACKUP_RAM_BASE + -+ sizeof(struct backup_data_s)); -+} -+ -+#if STM32MP_SP_MIN_IN_DDR -+void (*stm32_pwr_down_wfi)(bool is_cstop); -+#endif -+#endif -+ -+uint32_t stm32_pm_get_optee_ep(void) -+{ -+ struct backup_data_s *backup_data; -+ uint32_t ep; -+ -+ clk_enable(BKPSRAM); -+ -+ /* Context & Data to be saved at the beginning of Backup SRAM */ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ switch (MAGIC_ID(backup_data->magic)) { -+ case MAILBOX_MAGIC_V1: -+ case MAILBOX_MAGIC_V2: -+ case MAILBOX_MAGIC_V3: -+ if (MAGIC_AREA_SIZE(backup_data->magic) != TRAINING_AREA_SIZE) { -+ panic(); -+ } -+ break; -+ default: -+ ERROR("PM context: bad magic\n"); -+ panic(); -+ } -+ -+ ep = backup_data->core0_resume_hint; -+ -+ clk_disable(BKPSRAM); -+ -+ return ep; -+} -+ -+void stm32_clean_context(void) -+{ -+ clk_enable(BKPSRAM); -+ -+#if defined(IMAGE_BL2) -+ zeromem((void *)STM32MP_BACKUP_RAM_BASE, sizeof(struct backup_data_s)); -+#elif defined(IMAGE_BL32) -+ zeromem((void *)get_bl32_backup_data(), sizeof(struct backup_bl32_data_s)); -+#endif -+ -+ clk_disable(BKPSRAM); -+} -+ -+#if defined(IMAGE_BL32) -+void stm32mp1_pm_save_clock_cfg(size_t offset, uint8_t *data, size_t size) -+{ -+ struct backup_bl32_data_s *backup_data = get_bl32_backup_data(); -+ -+ if (offset + size > sizeof(backup_data->clock_cfg)) { -+ panic(); -+ } -+ -+ clk_enable(BKPSRAM); -+ -+ memcpy(backup_data->clock_cfg + offset, data, size); -+ -+ clk_disable(BKPSRAM); -+} -+ -+void stm32mp1_pm_restore_clock_cfg(size_t offset, uint8_t *data, size_t size) -+{ -+ struct backup_bl32_data_s *backup_data = get_bl32_backup_data(); -+ -+ if (offset + size > sizeof(backup_data->clock_cfg)) -+ panic(); -+ -+ clk_enable(BKPSRAM); -+ -+ memcpy(data, backup_data->clock_cfg + offset, size); -+ -+ clk_disable(BKPSRAM); -+} -+ -+int stm32_save_context(uint32_t zq0cr0_zdata, -+ struct stm32_rtc_calendar *rtc_time, -+ unsigned long long stgen_cnt) - { -- uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); -+ void *smc_context; -+ void *cpu_context; -+ struct backup_data_s *backup_data; -+ struct backup_bl32_data_s *backup_bl32_data; -+ -+ stm32mp1_clock_suspend(); -+ -+ clk_enable(BKPSRAM); -+ -+ /* Context & Data to be saved at the beginning of Backup SRAM */ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ /* Save BL32 context data provided to BL2 */ -+ backup_data->magic = MAILBOX_MAGIC; -+ -+ backup_data->zq0cr0_zdata = zq0cr0_zdata; -+ -+ stm32mp1_clk_lp_save_opp_pll1_settings(backup_data->pll1_settings, -+ sizeof(backup_data->pll1_settings)); -+ -+ /* Save the BL32 specific data */ -+ backup_bl32_data = get_bl32_backup_data(); -+ -+ backup_bl32_data->canary_id = BL32_CANARY_ID; -+ -+ /* Retrieve smc context struct address */ -+ smc_context = smc_get_ctx(NON_SECURE); -+ -+ /* Retrieve smc context struct address */ -+ cpu_context = cm_get_context(NON_SECURE); -+ -+ /* Save context in Backup SRAM */ -+ memcpy(&backup_bl32_data->saved_smc_context[0], smc_context, -+ sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT); -+ memcpy(&backup_bl32_data->saved_cpu_context[0], cpu_context, -+ sizeof(cpu_context_t) * PLATFORM_CORE_COUNT); -+ -+ memcpy(&backup_bl32_data->rtc, rtc_time, sizeof(struct stm32_rtc_calendar)); -+ backup_bl32_data->stgen = stgen_cnt; - -- stm32mp_clk_enable(RTCAPB); -+ stm32mp1_pm_save_scmi_state(backup_bl32_data->scmi_context, -+ sizeof(backup_bl32_data->scmi_context)); - -- mmio_clrsetbits_32(bkpr_itf_idx, -- TAMP_BOOT_ITF_MASK, -- ((interface << 4) | (instance & 0xFU)) << -- TAMP_BOOT_ITF_SHIFT); -+ save_clock_pm_context(); - -- stm32mp_clk_disable(RTCAPB); -+ clk_disable(BKPSRAM); - - return 0; - } -+ -+int stm32_restore_context(void) -+{ -+ void *smc_context; -+ void *cpu_context; -+ struct backup_data_s *backup_data; -+ struct backup_bl32_data_s *backup_bl32_data; -+ struct stm32_rtc_calendar current_calendar; -+ unsigned long long stdby_time_in_ms; -+ -+ /* Context & Data to be saved at the beginning of Backup SRAM */ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ clk_enable(BKPSRAM); -+ -+ stm32mp1_clk_lp_load_opp_pll1_settings(backup_data->pll1_settings, -+ sizeof(backup_data->pll1_settings)); -+ -+ backup_bl32_data = get_bl32_backup_data(); -+ -+ if (backup_bl32_data->canary_id != BL32_CANARY_ID) { -+ ERROR("Incorrect BL32 backup data\n"); -+ return -EINVAL; -+ } -+ -+ /* Retrieve smc context struct address */ -+ smc_context = smc_get_ctx(NON_SECURE); -+ -+ /* Retrieve smc context struct address */ -+ cpu_context = cm_get_context(NON_SECURE); -+ -+ restore_clock_pm_context(); -+ -+ stm32mp1_pm_restore_scmi_state(backup_bl32_data->scmi_context, -+ sizeof(backup_bl32_data->scmi_context)); -+ -+ /* Restore data from Backup SRAM */ -+ memcpy(smc_context, backup_bl32_data->saved_smc_context, -+ sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT); -+ memcpy(cpu_context, backup_bl32_data->saved_cpu_context, -+ sizeof(cpu_context_t) * PLATFORM_CORE_COUNT); -+ -+ /* Restore STGEN counter with standby mode length */ -+ stm32_rtc_get_calendar(¤t_calendar); -+ stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, -+ &backup_bl32_data->rtc); -+ stm32mp_stgen_restore_counter(backup_bl32_data->stgen, stdby_time_in_ms); -+ -+ clk_disable(BKPSRAM); -+ -+ stm32mp1_clock_resume(); -+ -+ return 0; -+} -+ -+unsigned long long stm32_get_stgen_from_context(void) -+{ -+ struct backup_bl32_data_s *backup_data; -+ unsigned long long stgen_cnt; -+ -+ clk_enable(BKPSRAM); -+ -+ backup_data = get_bl32_backup_data(); -+ -+ stgen_cnt = backup_data->stgen; -+ -+ clk_disable(BKPSRAM); -+ -+ return stgen_cnt; -+} -+ -+void stm32_context_get_bl2_low_power_params(uintptr_t *bl2_code_base, -+ uintptr_t *bl2_code_end, -+ uintptr_t *bl2_end) -+{ -+ struct backup_data_s *backup_data; -+ -+ clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ if (MAGIC_ID(backup_data->magic) != MAILBOX_MAGIC_V3) { -+ panic(); -+ } -+ -+#if STM32MP_SP_MIN_IN_DDR -+ stm32_pwr_down_wfi = (void (*)(bool))backup_data->low_power_ep; -+#endif -+ *bl2_code_base = (uintptr_t)backup_data->bl2_code_base; -+ *bl2_code_end = (uintptr_t)backup_data->bl2_code_end; -+ *bl2_end = (uintptr_t)backup_data->bl2_end; -+ -+ clk_disable(BKPSRAM); -+} -+ -+#endif /* IMAGE_BL32 */ -+ -+#if defined(IMAGE_BL2) -+void stm32_context_save_bl2_param(void) -+{ -+ struct backup_data_s *backup_data; -+ -+ clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ backup_data->low_power_ep = (uint32_t)&stm32_pwr_down_wfi_wrapper; -+ backup_data->bl2_code_base = BL_CODE_BASE; -+ backup_data->bl2_code_end = BL_CODE_END; -+ backup_data->bl2_end = BL2_END; -+ backup_data->magic = MAILBOX_MAGIC_V3; -+ -+ clk_disable(BKPSRAM); -+} -+#endif -+ -+uint32_t stm32_get_zdata_from_context(void) -+{ -+ struct backup_data_s *backup_data; -+ uint32_t zdata; -+ -+ clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ zdata = (backup_data->zq0cr0_zdata >> DDRPHYC_ZQ0CRN_ZDATA_SHIFT) & -+ DDRPHYC_ZQ0CRN_ZDATA_MASK; -+ -+ clk_disable(BKPSRAM); -+ -+ return zdata; -+} -+ -+static int pll1_settings_in_context(struct backup_data_s *backup_data) -+{ -+ switch (MAGIC_ID(backup_data->magic)) { -+ case MAILBOX_MAGIC_V1: -+ return -ENOENT; -+ case MAILBOX_MAGIC_V2: -+ case MAILBOX_MAGIC_V3: -+ assert(MAGIC_AREA_SIZE(backup_data->magic) == -+ TRAINING_AREA_SIZE); -+ return 0; -+ default: -+ panic(); -+ } -+} -+ -+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; -+ -+ 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); -+ } -+ -+ 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; -+ -+ 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); -+ -+ clk_disable(BKPSRAM); -+ -+ return is_valid; -+} -+ -+bool stm32_pm_context_is_valid(void) -+{ -+ struct backup_data_s *backup_data; -+ bool ret; -+ -+ clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ switch (MAGIC_ID(backup_data->magic)) { -+ case MAILBOX_MAGIC_V1: -+ case MAILBOX_MAGIC_V2: -+ case MAILBOX_MAGIC_V3: -+ ret = true; -+ break; -+ default: -+ ret = false; -+ break; -+ } -+ -+ clk_disable(BKPSRAM); -+ -+ return ret; -+} -+ -+#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 -+ * standby, and will be restored after -+ */ -+void stm32_save_ddr_training_area(void) -+{ -+ struct backup_data_s *backup_data; -+ int ret __unused; -+ -+ 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); -+ -+ clk_disable(BKPSRAM); -+} -+#endif -+ -+void stm32_restore_ddr_training_area(void) -+{ -+ struct backup_data_s *backup_data; -+ -+ clk_enable(BKPSRAM); -+ -+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; -+ -+ memcpy((uint32_t *)STM32MP_DDR_BASE, -+ &backup_data->ddr_training_backup, -+ TRAINING_AREA_SIZE); -+ dsb(); -+ -+ clk_disable(BKPSRAM); -+} -diff --git a/plat/st/stm32mp1/stm32mp1_critic_power.c b/plat/st/stm32mp1/stm32mp1_critic_power.c -new file mode 100644 -index 0000000000..583cf93fad ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_critic_power.c -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static void cstop_critic_enter(void) -+{ -+ /* -+ * Set DDR in Self-refresh,. -+ * This is also the procedure awaited when switching off power supply. -+ */ -+ if (ddr_standby_sr_entry() != 0) { -+ ERROR("Unable to put DDR in SR\n"); -+ panic(); -+ } -+} -+ -+/* -+ * stm32_exit_cstop_critic - Exit from CSTOP mode reenable DDR -+ */ -+static void cstop_critic_exit(void) -+{ -+ if (ddr_sw_self_refresh_exit() != 0) { -+ panic(); -+ } -+} -+ -+void stm32_pwr_down_wfi_load(bool is_cstop) -+{ -+ if (is_cstop) { -+ cstop_critic_enter(); -+ } -+ -+ /* -+ * Synchronize on memory accesses and instruction flow before the WFI -+ * instruction. -+ */ -+ dsb(); -+ isb(); -+ wfi(); -+ -+ stm32_iwdg_refresh(); -+ -+ if (is_cstop) { -+ cstop_critic_exit(); -+ } -+} -+ -+#if defined(IMAGE_BL32) && !STM32MP_SP_MIN_IN_DDR -+extern void wfi_svc_int_enable(uintptr_t stack_addr); -+static uint32_t int_stack[STM32MP_INT_STACK_SIZE]; -+ -+void stm32_pwr_down_wfi(bool is_cstop) -+{ -+ uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; -+ -+ if (is_cstop) { -+ cstop_critic_enter(); -+ } -+ -+ stm32mp1_calib_set_wakeup(false); -+ -+ while (interrupt == GIC_SPURIOUS_INTERRUPT && -+ !stm32mp1_calib_get_wakeup()) { -+ wfi_svc_int_enable((uintptr_t)&int_stack[0]); -+ -+ interrupt = gicv2_acknowledge_interrupt(); -+ -+ if (interrupt != GIC_SPURIOUS_INTERRUPT) { -+ gicv2_end_of_interrupt(interrupt); -+ } -+ -+ stm32_iwdg_refresh(); -+ } -+ -+ if (is_cstop) { -+ cstop_critic_exit(); -+ } -+} -+#endif -diff --git a/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S -new file mode 100644 -index 0000000000..2c4dd844d2 ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+ .global stm32_pwr_down_wfi_load -+ .global stm32_pwr_down_wfi_wrapper -+ .global bl2_vector_table -+ .global disable_mmu_secure -+ .global __STACKS_END__ -+ -+func stm32_pwr_down_wfi_wrapper -+ push {r4,r5,r6,lr} -+ -+ # Save current sp in r4 -+ mov r4, sp -+ # Save current VBAR in r5 -+ ldcopr r5, VBAR -+ # Save current MVBAR in r6 -+ ldcopr r6, MVBAR -+ -+ # Reuse BL2 vector table for VBAR and MVBAR -+ ldr r1, =bl2_vector_table -+ stcopr r1, VBAR -+ stcopr r1, MVBAR -+ -+ # Set sp to BL2 STACK (as BL2 is not using it anymore) -+ ldr sp, =__STACKS_END__ -+ -+ # Disable MMU as TLB are still stored in DDR, -+ # and in few instructions DDR won't be readable -+ bl disable_mmu_secure -+ -+ # dsb is done in disable mmu -+ # isb is done in disable mmu -+ -+ # We didn't change R0 to keep it as first parameter -+ bl stm32_pwr_down_wfi_load -+ -+ # Restore stack -+ mov sp, r4 -+ # Restore VBAR -+ stcopr r5, VBAR -+ # Restore MVBAR -+ stcopr r6, MVBAR -+ -+ # Synchronize on memory access and instruction -+ # after resetting stack/IT handler -+ dsb -+ isb -+ -+ pop {r4,r5,r6,pc} -+endfunc stm32_pwr_down_wfi_wrapper -diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c -index d0264968c6..eac2cf68c5 100644 ---- a/plat/st/stm32mp1/stm32mp1_dbgmcu.c -+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c -@@ -1,15 +1,17 @@ - /* -- * 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 -@@ -25,36 +27,27 @@ - - #define DBGMCU_APB4FZ1_IWDG2 BIT(2) - --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 -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); -+ mmio_setbits_32(RCC_BASE + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); - - return 0; - } - -+/* -+ * @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); -+ - if (stm32mp1_dbgmcu_init() != 0) { - return -EPERM; - } -@@ -65,18 +58,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); -+ - 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 ee04a23fd9..027dba1bde 100644 ---- a/plat/st/stm32mp1/stm32mp1_def.h -+++ b/plat/st/stm32mp1/stm32mp1_def.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -11,18 +11,22 @@ - #include - #include - #include -+#include - #include - #include - - #ifndef __ASSEMBLER__ - #include -+#include - #include -+#include -+#include - - #include --#include - #include - #include - #include -+#include - #include - #include - #include -@@ -31,6 +35,8 @@ - /******************************************************************************* - * 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) -@@ -55,15 +61,27 @@ - #define PKG_AC_TFBGA361 U(2) - #define PKG_AD_TFBGA257 U(1) - -+/******************************************************************************* -+ * BOOT PARAM -+ ******************************************************************************/ -+#define BOOT_PARAM_ADDR U(0x2FFC0078) -+ - /******************************************************************************* - * STM32MP1 memory map related constants - ******************************************************************************/ - #define STM32MP_ROM_BASE U(0x00000000) - #define STM32MP_ROM_SIZE U(0x00020000) -+#define STM32MP_ROM_SIZE_2MB_ALIGNED U(0x00200000) - - #define STM32MP_SYSRAM_BASE U(0x2FFC0000) - #define STM32MP_SYSRAM_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 - \ -@@ -79,12 +97,13 @@ - /* DDR configuration */ - #define STM32MP_DDR_BASE U(0xC0000000) - #define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ --#ifdef AARCH32_SP_OPTEE -+#if STM32MP_USE_STM32IMAGE - #define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ -+#ifdef AARCH32_SP_OPTEE - #define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ -+#endif - #else --#define STM32MP_DDR_S_SIZE U(0) --#define STM32MP_DDR_SHMEM_SIZE U(0) -+#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */ - #endif - - /* DDR power initializations */ -@@ -100,6 +119,8 @@ enum ddr_type { - #define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */ - /* 256 Octets reserved for header */ - #define STM32MP_HEADER_SIZE U(0x00000100) -+/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */ -+#define STM32MP_HEADER_RESERVED_SIZE U(0x3000) - - #define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \ - STM32MP_PARAM_LOAD_SIZE + \ -@@ -109,83 +130,214 @@ enum ddr_type { - (STM32MP_PARAM_LOAD_SIZE + \ - STM32MP_HEADER_SIZE)) - --#ifdef AARCH32_SP_OPTEE --#define STM32MP_BL32_SIZE U(0) -+#if !STM32MP_SSP -+#if STM32MP_USE_STM32IMAGE -+#define STM32MP_BL2_SIZE U(0x0001C000) /* 112 KB for BL2 */ - -+#ifdef AARCH32_SP_OPTEE - #define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE - --#define STM32MP_OPTEE_SIZE (STM32MP_DTB_BASE - \ -+#define STM32MP_OPTEE_SIZE (TF_A_MAPPING_START - \ - STM32MP_OPTEE_BASE) --#else --#if STACK_PROTECTOR_ENABLED --#define STM32MP_BL32_SIZE U(0x00012000) /* 72 KB for BL32 */ --#else --#define STM32MP_BL32_SIZE U(0x00011000) /* 68 KB for BL32 */ --#endif --#endif -+ -+#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ -+ STM32MP_SEC_SYSRAM_SIZE - \ -+ STM32MP_BL2_SIZE) -+ -+#define STM32MP_BL32_BASE STM32MP_SEC_SYSRAM_BASE -+ -+#else /* AARCH32_SP_OPTEE */ -+#define STM32MP_BL32_SIZE U(0x0001A000) /* 104 KB for BL32 */ -+#define STM32MP_BL32_BIN_SIZE STM32MP_BL32_SIZE - - #define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \ - STM32MP_SEC_SYSRAM_SIZE - \ - STM32MP_BL32_SIZE) - --#ifdef AARCH32_SP_OPTEE --#if STACK_PROTECTOR_ENABLED --#define STM32MP_BL2_SIZE U(0x0001A000) /* 100 KB for BL2 */ -+#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ -+ STM32MP_BL2_SIZE) -+#endif /* AARCH32_SP_OPTEE */ -+#else /* STM32MP_USE_STM32IMAGE */ -+#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP -+#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */ -+#define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */ - #else --#define STM32MP_BL2_SIZE U(0x00018000) /* 92 KB for BL2 */ -+#define STM32MP_BL2_RO_SIZE U(0x00010000) /* 64 KB */ -+#define STM32MP_BL2_SIZE U(0x00015000) /* 84 KB for BL2 */ - #endif -+ -+#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ -+ STM32MP_SEC_SYSRAM_SIZE - \ -+ STM32MP_BL2_SIZE) -+ -+#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE -+ -+#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \ -+ STM32MP_BL2_RO_SIZE) -+ -+#define STM32MP_BL2_RW_SIZE STM32MP_SEC_SYSRAM_BASE + \ -+ STM32MP_SEC_SYSRAM_SIZE - \ -+ STM32MP_BL2_RW_BASE -+ -+#if STM32MP_SP_MIN_IN_DDR -+#define STM32MP_BL32_SIZE U(0x00025000) /* 148 KB for BL32 */ - #else --#if STACK_PROTECTOR_ENABLED --#define STM32MP_BL2_SIZE U(0x00019000) /* 96 KB for BL2 */ --#else --#define STM32MP_BL2_SIZE U(0x00017000) /* 88 KB for BL2 */ -+#define STM32MP_BL32_SIZE U(0x0001A000) /* 100 KB for BL32 */ - #endif -+#endif /* STM32MP_USE_STM32IMAGE */ -+#endif /* STM32MP_SSP */ -+ -+#if defined(IMAGE_BL2) -+ #define STM32MP_DEFAULT_XLAT U(2) /* 8 KB for mapping */ - #endif - --#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ -- STM32MP_BL2_SIZE) -+/* BL32/sp_min require finer granularity tables */ -+#if defined(IMAGE_BL32) -+ #define STM32MP_DEFAULT_XLAT U(4) /* 16 KB for mapping */ -+#endif - --/* BL2 and BL32/sp_min require 4 tables */ --#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */ -+#if STM32MP_SP_MIN_IN_DDR && defined(IMAGE_BL32) -+ #define STM32MP_SP_MIN_IN_DDR_XLAT U(3) /* 12KB for mapping -+ * (BL32 data, BL32 DT, SCMI buffers) -+ */ -+#else -+ #define STM32MP_SP_MIN_IN_DDR_XLAT U(0) -+#endif - -+#define MAX_XLAT_TABLES (STM32MP_DEFAULT_XLAT + \ -+ STM32MP_SP_MIN_IN_DDR_XLAT) - /* - * MAX_MMAP_REGIONS is usually: - * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup - */ - #if defined(IMAGE_BL2) -- #define MAX_MMAP_REGIONS 11 -+ #if STM32MP_USB_PROGRAMMER -+ #define MAX_MMAP_REGIONS 8 -+ #else -+ #if STM32MP_USE_STM32IMAGE -+ #define MAX_MMAP_REGIONS 8 -+ #else -+ #define MAX_MMAP_REGIONS 7 -+ #endif -+ #endif - #endif - #if defined(IMAGE_BL32) -- #define MAX_MMAP_REGIONS 6 -+ #if STM32MP_USE_STM32IMAGE -+ #define MAX_MMAP_REGIONS 6 -+ #else -+ #define MAX_MMAP_REGIONS 10 -+ #endif - #endif - -+#if STM32MP_SSP -+#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */ -+ -+#define STM32MP_BL2_DTB_BASE (STM32MP_SYSRAM_BASE + \ -+ STM32MP_HEADER_RESERVED_SIZE) -+ -+#define STM32MP_BL2_RO_SIZE U(0x0000C000) /* 48 Ko for BL2 */ -+ -+#define STM32MP_BL2_RO_BASE STM32MP_BL2_DTB_BASE + \ -+ STM32MP_BL2_DTB_SIZE -+ -+#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \ -+ STM32MP_BL2_RO_SIZE) -+ -+#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \ -+ STM32MP_SYSRAM_SIZE - \ -+ STM32MP_BL2_RW_BASE) -+ -+#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE -+#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE -+ -+#define TF_A_MAPPING_START STM32MP_BL2_DTB_BASE -+#else -+#if STM32MP_USE_STM32IMAGE - /* DTB initialization value */ --#define STM32MP_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ -+#define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ - --#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ -+#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ - STM32MP_DTB_SIZE) -+#define TF_A_MAPPING_START STM32MP_DTB_BASE -+#else /* STM32MP_USE_STM32IMAGE */ -+#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */ -+#define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \ -+ STM32MP_BL2_DTB_SIZE) - -+#define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ -+#define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE -+ -+#define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \ -+ STM32MP_BL32_DTB_SIZE) -+ -+#if defined(IMAGE_BL2) -+#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE -+#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE -+#endif -+#if defined(IMAGE_BL32) -+#define STM32MP_DTB_SIZE STM32MP_BL32_DTB_SIZE -+#define STM32MP_DTB_BASE STM32MP_BL32_DTB_BASE -+#endif -+#define TF_A_MAPPING_START STM32MP_BL2_DTB_BASE -+#endif /* STM32MP_USE_STM32IMAGE */ -+#endif /* STM32MP_SSP */ -+ -+#define STM32MP_FW_CONFIG_BASE (STM32MP_SYSRAM_BASE + \ -+ STM32MP_SYSRAM_SIZE - \ -+ PAGE_SIZE) -+#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE - #define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) -+#define STM32MP_BL33_MAX_SIZE U(0x400000) -+#define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \ -+ STM32MP_BL33_MAX_SIZE) -+#define STM32MP_HW_CONFIG_MAX_SIZE U(0x20000) -+ -+/* Define Temporary Stack size use during low power mode */ -+#define STM32MP_INT_STACK_SIZE 0x200 - - /* 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) -+#if STM32MP_USE_STM32IMAGE -+#ifndef STM32MP_NOR_BASE_OFFSET -+#define STM32MP_NOR_BASE_OFFSET U(0x00080000) -+#endif -+#define STM32MP_NOR_BL33_OFFSET STM32MP_NOR_BASE_OFFSET - #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) -+#ifndef STM32MP_NAND_BASE_OFFSET -+#define STM32MP_NAND_BASE_OFFSET U(0x00200000) -+#endif -+#define STM32MP_NAND_BL33_OFFSET STM32MP_NAND_BASE_OFFSET - #ifdef AARCH32_SP_OPTEE --#define STM32MP_NAND_TEEH_OFFSET U(0x00600000) --#define STM32MP_NAND_TEED_OFFSET U(0x00680000) --#define STM32MP_NAND_TEEX_OFFSET U(0x00700000) -+#define STM32MP_NAND_TEEH_OFFSET (STM32MP_NAND_BASE_OFFSET + \ -+ U(0x00400000)) -+#define STM32MP_NAND_TEED_OFFSET (STM32MP_NAND_BASE_OFFSET + \ -+ U(0x00480000)) -+#define STM32MP_NAND_TEEX_OFFSET (STM32MP_NAND_BASE_OFFSET + \ -+ U(0x00500000)) - #endif -+#else /* STM32MP_USE_STM32IMAGE */ -+#ifndef STM32MP_NOR_FIP_OFFSET -+#define STM32MP_NOR_FIP_OFFSET U(0x00080000) -+#endif -+#ifndef STM32MP_NAND_FIP_OFFSET -+#define STM32MP_NAND_FIP_OFFSET U(0x00200000) -+#endif -+#endif /* STM32MP_USE_STM32IMAGE */ - - /******************************************************************************* - * STM32MP1 device/io map related constants (used for MMU) -@@ -206,6 +358,22 @@ enum ddr_type { - ******************************************************************************/ - #define PWR_BASE U(0x50001000) - -+/******************************************************************************* -+ * STM32MP1 EXTI -+ ******************************************************************************/ -+#define EXTI_BASE U(0x5000D000) -+#define EXTI_TZENR1 U(0x14) -+#define EXTI_RPR3 U(0x4C) -+#define EXTI_FPR3 U(0x50) -+#define EXTI_C1IMR1 U(0x80) -+#define EXTI_C2IMR1 U(0xC0) -+#define EXTI_C2IMR2 U(0xD0) -+#define EXTI_C2IMR3 U(0xE0) -+#define EXTI_TZENR1_TZEN18 BIT(18) -+#define EXTI_IMR1_IM18 BIT(18) -+#define EXTI_RPR3_RPIF65 BIT(1) -+#define EXTI_FPR3_FPIF65 BIT(1) -+ - /******************************************************************************* - * STM32MP1 GPIO - ******************************************************************************/ -@@ -277,111 +445,12 @@ enum ddr_type { - - #define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0) - --/* ETZPC DECPROT IDs */ --#define STM32MP1_ETZPC_STGENC_ID 0 --#define STM32MP1_ETZPC_BKPSRAM_ID 1 --#define STM32MP1_ETZPC_IWDG1_ID 2 --#define STM32MP1_ETZPC_USART1_ID 3 --#define STM32MP1_ETZPC_SPI6_ID 4 --#define STM32MP1_ETZPC_I2C4_ID 5 --#define STM32MP1_ETZPC_RNG1_ID 7 --#define STM32MP1_ETZPC_HASH1_ID 8 --#define STM32MP1_ETZPC_CRYP1_ID 9 --#define STM32MP1_ETZPC_DDRCTRL_ID 10 --#define STM32MP1_ETZPC_DDRPHYC_ID 11 --#define STM32MP1_ETZPC_I2C6_ID 12 --#define STM32MP1_ETZPC_SEC_ID_LIMIT 13 -- --#define STM32MP1_ETZPC_TIM2_ID 16 --#define STM32MP1_ETZPC_TIM3_ID 17 --#define STM32MP1_ETZPC_TIM4_ID 18 --#define STM32MP1_ETZPC_TIM5_ID 19 --#define STM32MP1_ETZPC_TIM6_ID 20 --#define STM32MP1_ETZPC_TIM7_ID 21 --#define STM32MP1_ETZPC_TIM12_ID 22 --#define STM32MP1_ETZPC_TIM13_ID 23 --#define STM32MP1_ETZPC_TIM14_ID 24 --#define STM32MP1_ETZPC_LPTIM1_ID 25 --#define STM32MP1_ETZPC_WWDG1_ID 26 --#define STM32MP1_ETZPC_SPI2_ID 27 --#define STM32MP1_ETZPC_SPI3_ID 28 --#define STM32MP1_ETZPC_SPDIFRX_ID 29 --#define STM32MP1_ETZPC_USART2_ID 30 --#define STM32MP1_ETZPC_USART3_ID 31 --#define STM32MP1_ETZPC_UART4_ID 32 --#define STM32MP1_ETZPC_UART5_ID 33 --#define STM32MP1_ETZPC_I2C1_ID 34 --#define STM32MP1_ETZPC_I2C2_ID 35 --#define STM32MP1_ETZPC_I2C3_ID 36 --#define STM32MP1_ETZPC_I2C5_ID 37 --#define STM32MP1_ETZPC_CEC_ID 38 --#define STM32MP1_ETZPC_DAC_ID 39 --#define STM32MP1_ETZPC_UART7_ID 40 --#define STM32MP1_ETZPC_UART8_ID 41 --#define STM32MP1_ETZPC_MDIOS_ID 44 --#define STM32MP1_ETZPC_TIM1_ID 48 --#define STM32MP1_ETZPC_TIM8_ID 49 --#define STM32MP1_ETZPC_USART6_ID 51 --#define STM32MP1_ETZPC_SPI1_ID 52 --#define STM32MP1_ETZPC_SPI4_ID 53 --#define STM32MP1_ETZPC_TIM15_ID 54 --#define STM32MP1_ETZPC_TIM16_ID 55 --#define STM32MP1_ETZPC_TIM17_ID 56 --#define STM32MP1_ETZPC_SPI5_ID 57 --#define STM32MP1_ETZPC_SAI1_ID 58 --#define STM32MP1_ETZPC_SAI2_ID 59 --#define STM32MP1_ETZPC_SAI3_ID 60 --#define STM32MP1_ETZPC_DFSDM_ID 61 --#define STM32MP1_ETZPC_TT_FDCAN_ID 62 --#define STM32MP1_ETZPC_LPTIM2_ID 64 --#define STM32MP1_ETZPC_LPTIM3_ID 65 --#define STM32MP1_ETZPC_LPTIM4_ID 66 --#define STM32MP1_ETZPC_LPTIM5_ID 67 --#define STM32MP1_ETZPC_SAI4_ID 68 --#define STM32MP1_ETZPC_VREFBUF_ID 69 --#define STM32MP1_ETZPC_DCMI_ID 70 --#define STM32MP1_ETZPC_CRC2_ID 71 --#define STM32MP1_ETZPC_ADC_ID 72 --#define STM32MP1_ETZPC_HASH2_ID 73 --#define STM32MP1_ETZPC_RNG2_ID 74 --#define STM32MP1_ETZPC_CRYP2_ID 75 --#define STM32MP1_ETZPC_SRAM1_ID 80 --#define STM32MP1_ETZPC_SRAM2_ID 81 --#define STM32MP1_ETZPC_SRAM3_ID 82 --#define STM32MP1_ETZPC_SRAM4_ID 83 --#define STM32MP1_ETZPC_RETRAM_ID 84 --#define STM32MP1_ETZPC_OTG_ID 85 --#define STM32MP1_ETZPC_SDMMC3_ID 86 --#define STM32MP1_ETZPC_DLYBSD3_ID 87 --#define STM32MP1_ETZPC_DMA1_ID 88 --#define STM32MP1_ETZPC_DMA2_ID 89 --#define STM32MP1_ETZPC_DMAMUX_ID 90 --#define STM32MP1_ETZPC_FMC_ID 91 --#define STM32MP1_ETZPC_QSPI_ID 92 --#define STM32MP1_ETZPC_DLYBQ_ID 93 --#define STM32MP1_ETZPC_ETH_ID 94 --#define STM32MP1_ETZPC_RSV_ID 95 -- --#define STM32MP_ETZPC_MAX_ID 96 -- - /******************************************************************************* - * STM32MP1 TZC (TZ400) - ******************************************************************************/ - #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) --#define STM32MP1_TZC_DMA_ID U(6) --#define STM32MP1_TZC_USB_HOST_ID U(7) --#define STM32MP1_TZC_USB_OTG_ID U(8) --#define STM32MP1_TZC_SDMMC_ID U(9) --#define STM32MP1_TZC_ETH_ID U(10) --#define STM32MP1_TZC_DAP_ID U(15) -- --#define STM32MP1_FILTER_BIT_ALL U(3) -+#define STM32MP1_FILTER_BIT_ALL (BIT(1) | BIT(0)) - - /******************************************************************************* - * STM32MP1 SDMMC -@@ -404,16 +473,44 @@ 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 NAND_OTP U(9) --#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" -+#define CFG2_OTP "cfg2_otp" -+#define SSP_OTP "ssp_otp" -+#define CHIP_CERTIFICATE_OTP "chip_otp" -+#define RMA_OTP "rma_otp" - - /* OTP mask */ --/* DATA0 */ --#define DATA0_OTP_SECURED BIT(6) -+/* CFG0 */ -+#define CFG0_CLOSED_DEVICE BIT(6) -+ -+/* CFG2 */ -+#define OTP_CFG2_SEC_COUNTER_MASK GENMASK_32(27, 20) -+#define OTP_CFG2_SEC_COUNTER_SHIFT U(20) -+#define OTP_CFG2_ST_KEY_MASK GENMASK_32(31, 28) -+#define OTP_CFG2_ST_KEY_SHIFT U(28) -+ -+/* SSP */ -+#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 GENMASK_32(BOOT_API_OTP_SSP_SUCCESS_BIT_POS, \ -+ BOOT_API_OTP_SSP_REQ_BIT_POS) -+#define SSP_OTP_SECRET_BASE U(59) -+#define SSP_OTP_SECRET_END U(95) -+ -+/* CHIP_CERT */ -+#define CHIP_CERTIFICATE_MAX_SIZE U(0x40) -+ -+/* RMA */ -+#define RMA_OTP_MASK GENMASK_32(29, 0) - - /* PART NUMBER */ - #define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) -@@ -470,11 +567,24 @@ enum ddr_type { - /* NAND number of planes */ - #define NAND_PLANE_BIT_NB_MASK BIT(14) - -+/* MONOTONIC OTP */ -+#define MAX_MONOTONIC_VALUE 32 -+ -+/* UID OTP */ -+#define UID_WORD_NB 3 -+ - /******************************************************************************* - * STM32MP1 TAMP - ******************************************************************************/ -+#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) -+ - - #if !(defined(__LINKER__) || defined(__ASSEMBLER__)) - static inline uint32_t tamp_bkpr(uint32_t idx) -@@ -483,6 +593,11 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - } - #endif - -+/******************************************************************************* -+ * STM32MP1 USB -+ ******************************************************************************/ -+#define USB_OTG_BASE U(0x49000000) -+ - /******************************************************************************* - * STM32MP1 DDRCTRL - ******************************************************************************/ -@@ -518,12 +633,41 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - #define STGEN_BASE U(0x5c008000) - #define SYSCFG_BASE U(0x50020000) - -+/******************************************************************************* -+ * STM32MP1 TIMERS -+ ******************************************************************************/ -+#define TIM12_BASE U(0x40006000) -+#define TIM15_BASE U(0x44006000) -+#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_BSEC_COMPAT "st,stm32mp15-bsec" -+#define DT_DDR_COMPAT "st,stm32mp1-ddr" - #define DT_IWDG_COMPAT "st,stm32mp1-iwdg" -+#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_RCC_SEC_CLK_COMPAT "st,stm32mp1-rcc-secure" -+#define DT_USBPHYC_COMPAT "st,stm32mp1-usbphyc" -+ -+#define DT_PLL1_NODE_NAME "st,pll@0" - - #endif /* STM32MP1_DEF_H */ -diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c -new file mode 100644 -index 0000000000..16aee904e7 ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define STM32MP_REGION_PARAMS 4 -+#define STM32MP_MAX_REGIONS 8 -+#define FORCE_SEC_REGION BIT(31) -+ -+static uint32_t nb_regions; -+ -+struct dt_id_attr { -+ fdt32_t id_attr[STM32MP_MAX_REGIONS]; -+}; -+ -+void stm32mp1_arch_security_setup(void) -+{ -+ clk_enable(TZC1); -+ clk_enable(TZC2); -+ -+ tzc400_init(STM32MP1_TZC_BASE); -+ tzc400_disable_filters(); -+ -+ /* -+ * Region 0 set to cover all DRAM at 0xC000_0000 -+ * Only secure access is granted in read/write. -+ */ -+ tzc400_configure_region0(TZC_REGION_S_RDWR, 0); -+ -+ tzc400_set_action(TZC_ACTION_ERR); -+ tzc400_enable_filters(); -+} -+ -+void stm32mp1_security_setup(void) -+{ -+ uint8_t i; -+ -+ assert(nb_regions > 0U); -+ -+ tzc400_init(STM32MP1_TZC_BASE); -+ tzc400_disable_filters(); -+ -+ /* -+ * Region 0 set to cover all DRAM at 0xC000_0000 -+ * No access is allowed. -+ */ -+ tzc400_configure_region0(TZC_REGION_S_NONE, 0); -+ -+ for (i = 1U; i <= nb_regions; i++) { -+ tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL); -+ } -+ -+ tzc400_set_action(TZC_ACTION_INT); -+ tzc400_enable_filters(); -+} -+ -+static int fconf_populate_stm32mp1_firewall(uintptr_t config) -+{ -+ int node, len; -+ unsigned int i; -+ const struct dt_id_attr *conf_list; -+ const void *dtb = (const void *)config; -+ -+ /* Assert the node offset point to "st,mem-firewall" compatible property */ -+ const char *compatible_str = "st,mem-firewall"; -+ -+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); -+ if (node < 0) { -+ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); -+ return node; -+ } -+ -+ conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len); -+ if (conf_list == NULL) { -+ WARN("FCONF: Read cell failed for %s\n", "memory-ranges"); -+ return -1; -+ } -+ -+ /* Locate the memory cells and read all values */ -+ for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) { -+ uint32_t base; -+ uint32_t size; -+ uint32_t sec_attr; -+ uint32_t nsaid; -+ -+ base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]); -+ size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]); -+ sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]); -+ nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]); -+ -+ VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n", -+ base, size, sec_attr, nsaid); -+ -+ nb_regions++; -+ -+ /* Configure region but keep disabled for secure access for BL2 load */ -+ tzc400_configure_region(0, nb_regions, (unsigned long long)base, -+ (unsigned long long)base + size - 1ULL, sec_attr, nsaid); -+ } -+ -+ /* Force flush as the value will be used cache off */ -+ flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t)); -+ -+ return 0; -+} -+ -+FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall); -diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c -deleted file mode 100644 -index 851a9cf0c4..0000000000 ---- a/plat/st/stm32mp1/stm32mp1_gic.c -+++ /dev/null -@@ -1,92 +0,0 @@ --/* -- * 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 -- --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 stm32mp1_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 = 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; -- --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(); -- -- stm32mp1_gic_pcpu_init(); --} -- --void stm32mp1_gic_pcpu_init(void) --{ -- gicv2_pcpu_distif_init(); -- gicv2_set_pe_target_mask(plat_my_core_pos()); -- gicv2_cpuif_enable(); --} -diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S -index 3021362365..bc2d73cebb 100644 ---- a/plat/st/stm32mp1/stm32mp1_helper.S -+++ b/plat/st/stm32mp1/stm32mp1_helper.S -@@ -10,11 +10,17 @@ - #include - #include - #include -+#include - - #define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) - - .globl platform_mem_init - .globl plat_report_exception -+#if AARCH32_EXCEPTION_DEBUG -+ .globl plat_report_undef_inst -+ .globl plat_report_prefetch_abort -+ .globl plat_report_data_abort -+#endif - .globl plat_get_my_entrypoint - .globl plat_secondary_cold_boot_setup - .globl plat_reset_handler -@@ -24,6 +30,7 @@ - .globl plat_crash_console_flush - .globl plat_crash_console_putc - .globl plat_panic_handler -+ .globl wfi_svc_int_enable - - func platform_mem_init - /* Nothing to do, don't need to init SYSRAM */ -@@ -75,6 +82,96 @@ print_exception_info: - #endif - endfunc plat_report_exception - -+#if AARCH32_EXCEPTION_DEBUG -+func plat_report_undef_inst -+#if DEBUG -+ mov r8, lr -+ -+ mov r9, r0 -+ -+ ldr r4, =undefined_str -+ bl asm_print_str -+ -+ mov r4, r9 -+ sub r4, r4, #4 -+ bl asm_print_hex -+ -+ ldr r4, =end_error_str -+ bl asm_print_str -+ -+ bx r8 -+#else -+ bx lr -+#endif -+endfunc plat_report_undef_inst -+ -+func plat_report_prefetch_abort -+#if DEBUG -+ mov r8, lr -+ mov r9, r0 -+ -+ ldr r4, =prefetch_abort_str -+ bl asm_print_str -+ -+ mov r4, r9 -+ sub r4, r4, #4 -+ bl asm_print_hex -+ -+ ldr r4, =ifsr_str -+ bl asm_print_str -+ -+ ldcopr r4, IFSR -+ bl asm_print_hex -+ -+ ldr r4, =ifar_str -+ bl asm_print_str -+ -+ ldcopr r4, IFAR -+ bl asm_print_hex -+ -+ ldr r4, =end_error_str -+ bl asm_print_str -+ -+ bx r8 -+#else -+ bx lr -+#endif -+endfunc plat_report_prefetch_abort -+ -+func plat_report_data_abort -+#if DEBUG -+ mov r8, lr -+ mov r9, r0 -+ -+ ldr r4, =data_abort_str -+ bl asm_print_str -+ -+ mov r4, r9 -+ sub r4, r4, #8 -+ bl asm_print_hex -+ -+ ldr r4, =dfsr_str -+ bl asm_print_str -+ -+ ldcopr r4, DFSR -+ bl asm_print_hex -+ -+ ldr r4, =dfar_str -+ bl asm_print_str -+ -+ ldcopr r4, DFAR -+ bl asm_print_hex -+ -+ ldr r4, =end_error_str -+ bl asm_print_str -+ -+ bx r8 -+#else -+ bx lr -+#endif -+endfunc plat_report_data_abort -+#endif -+ - func plat_reset_handler - bx lr - endfunc plat_reset_handler -@@ -204,7 +301,7 @@ endfunc plat_crash_console_init - * --------------------------------------------- - */ - func plat_crash_console_flush -- ldr r1, =STM32MP_DEBUG_USART_BASE -+ ldr r0, =STM32MP_DEBUG_USART_BASE - b console_stm32_core_flush - endfunc plat_crash_console_flush - -@@ -245,12 +342,48 @@ endfunc plat_panic_handler - .section .rodata.rev_err_str, "aS" - abort_str: - .asciz "\nAbort at: 0x" -+#if AARCH32_EXCEPTION_DEBUG -+prefetch_abort_str: -+ .asciz "\nPrefetch Abort at: 0x" -+data_abort_str: -+ .asciz "\nData Abort at: 0x" -+#endif - undefined_str: - .asciz "\nUndefined instruction at: 0x" - exception_start_str: - .asciz "\nException mode=0x" - exception_end_str: - .asciz " at: 0x" -+#if AARCH32_EXCEPTION_DEBUG -+dfsr_str: -+ .asciz " DFSR = 0x" -+dfar_str: -+ .asciz " DFAR = 0x" -+ifsr_str: -+ .asciz " IFSR = 0x" -+ifar_str: -+ .asciz " IFAR = 0x" -+#endif - end_error_str: - .asciz "\n\r" - #endif -+ -+func wfi_svc_int_enable -+ push {r4,r8,lr} -+ ldcopr r4, SCR -+ mov r8, sp -+ mov sp, r0 -+ add r0, r0, #STM32MP_INT_STACK_SIZE -+ str r0, [sp, #SMC_CTX_SP_MON] -+ str r4, [sp, #SMC_CTX_SCR] -+ cps #MODE32_svc -+ cpsie af -+ dsb -+ isb -+ wfi -+ cpsid af -+ cps #MODE32_mon -+ mov sp, r8 -+ pop {r4,r8,lr} -+ bx lr -+endfunc wfi_svc_int_enable -diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c -new file mode 100644 -index 0000000000..ae6fd88c88 ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_low_power.c -@@ -0,0 +1,455 @@ -+/* -+ * 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 -+ -+static unsigned int gicc_pmr; -+static struct stm32_rtc_calendar sleep_time; -+static bool enter_cstop_done; -+static unsigned long long stgen_cnt; -+ -+struct pwr_lp_config { -+ uint32_t pwr_cr1; -+ uint32_t pwr_mpucr; -+ const char *regul_suspend_node_name; -+}; -+ -+#define PWRLP_TEMPO_5_HSI 5 -+ -+#define PWR_CR1_MASK (PWR_CR1_LPDS | PWR_CR1_LPCFG | PWR_CR1_LVDS) -+#define PWR_MPUCR_MASK (PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | PWR_MPUCR_PDDS) -+ -+static const struct pwr_lp_config config_pwr[STM32_PM_MAX_SOC_MODE] = { -+ [STM32_PM_CSLEEP_RUN] = { -+ .pwr_cr1 = 0U, -+ .pwr_mpucr = PWR_MPUCR_CSSF, -+ .regul_suspend_node_name = NULL, -+ }, -+ [STM32_PM_CSTOP_ALLOW_STOP] = { -+ .pwr_cr1 = 0U, -+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF, -+ .regul_suspend_node_name = NULL, -+ }, -+ [STM32_PM_CSTOP_ALLOW_LP_STOP] = { -+ .pwr_cr1 = PWR_CR1_LPDS, -+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF, -+ .regul_suspend_node_name = "lp-stop", -+ }, -+ [STM32_PM_CSTOP_ALLOW_LPLV_STOP] = { -+ .pwr_cr1 = PWR_CR1_LVDS | PWR_CR1_LPDS | PWR_CR1_LPCFG, -+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF, -+ .regul_suspend_node_name = "lplv-stop", -+ }, -+ [STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR] = { -+ .pwr_cr1 = 0U, -+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | -+ PWR_MPUCR_PDDS, -+ .regul_suspend_node_name = "standby-ddr-sr", -+ }, -+ [STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF] = { -+ .pwr_cr1 = 0U, -+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | -+ PWR_MPUCR_PDDS, -+ .regul_suspend_node_name = "standby-ddr-off", -+ }, -+ [STM32_PM_SHUTDOWN] = { -+ .pwr_cr1 = 0U, -+ .pwr_mpucr = 0U, -+ .regul_suspend_node_name = "standby-ddr-off", -+ }, -+}; -+ -+#define GICC_PMR_PRIORITY_8 U(0x8) -+ -+enum { -+ STATE_NONE = 0, -+ STATE_AUTOSTOP_ENTRY, -+ STATE_AUTOSTOP_EXIT, -+}; -+ -+static struct spinlock lp_lock; -+static volatile int cpu0_state = STATE_NONE; -+static volatile int cpu1_state = STATE_NONE; -+ -+void stm32_apply_pmic_suspend_config(uint32_t mode) -+{ -+ const char *node_name; -+ -+ assert(mode < ARRAY_SIZE(config_pwr)); -+ -+ node_name = config_pwr[mode].regul_suspend_node_name; -+ -+ if (node_name != NULL) { -+ if (!initialize_pmic_i2c()) { -+ panic(); -+ } -+ -+ if (pmic_set_lp_config(node_name) < 0) { -+ panic(); -+ } -+ -+ if (pmic_configure_boot_on_regulators() < 0) { -+ panic(); -+ } -+ } -+} -+ -+/* -+ * stm32_enter_cstop - Prepare CSTOP mode -+ * -+ * @mode - Target low power mode -+ * @nsec_addr - Non secure resume entry point -+ * Return 0 if succeed to suspend, non 0 else. -+ */ -+static void enter_cstop(uint32_t mode, uint32_t nsec_addr) -+{ -+ uint32_t zq0cr0_zdata; -+ uint32_t bkpr_core1_addr = -+ 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); -+ uint32_t pwr_cr1 = config_pwr[mode].pwr_cr1; -+ 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(); -+ -+ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { -+ /* -+ * The first 64 bytes of DDR need to be saved for DDR DQS -+ * training -+ */ -+ stm32_save_ddr_training_area(); -+ } -+ -+ if (dt_pmic_status() > 0) { -+ stm32_apply_pmic_suspend_config(mode); -+ -+ if (mode == STM32_PM_CSTOP_ALLOW_LP_STOP) { -+ pwr_cr1 |= PWR_CR1_LPCFG; -+ } -+ } -+ -+ /* Clear RCC interrupt before enabling it */ -+ mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF); -+ -+ /* Enable RCC Wake-up */ -+ mmio_setbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); -+ -+ /* Configure low power mode */ -+ mmio_clrsetbits_32(pwr_base + PWR_MPUCR, PWR_MPUCR_MASK, -+ config_pwr[mode].pwr_mpucr); -+ mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK, -+ pwr_cr1); -+ -+ /* Clear RCC pending interrupt flags */ -+ mmio_write_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_MASK); -+ -+ /* Request CSTOP mode to RCC */ -+ mmio_setbits_32(rcc_base + RCC_MP_SREQSETR, -+ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); -+ -+ stm32_iwdg_refresh(); -+ -+ gicc_pmr = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8); -+ -+ zq0cr0_zdata = ddr_get_io_calibration_val(); -+ -+ clk_enable(RTCAPB); -+ -+ mmio_write_32(bkpr_core1_addr, 0); -+ mmio_write_32(bkpr_core1_magic, 0); -+ -+ stm32mp1_clock_stopmode_save(); -+ -+ stm32_rtc_get_calendar(&sleep_time); -+ stgen_cnt = stm32mp_stgen_get_counter(); -+ -+ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { -+ /* -+ * Save non-secure world entrypoint after standby in Backup -+ * register -+ */ -+ mmio_write_32(bkpr_core1_addr, nsec_addr); -+ mmio_write_32(bkpr_core1_magic, -+ BOOT_API_A7_CORE0_MAGIC_NUMBER); -+ -+ if (stm32_save_context(zq0cr0_zdata, &sleep_time, -+ stgen_cnt) != 0) { -+ panic(); -+ } -+ -+ if (stm32mp1_get_retram_enabled()) { -+ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_RREN); -+ while ((mmio_read_32(pwr_base + PWR_CR2) & -+ PWR_CR2_RRRDY) == 0U) { -+ ; -+ } -+ } -+ -+ /* Keep backup RAM content in standby */ -+ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN); -+ while ((mmio_read_32(pwr_base + PWR_CR2) & -+ PWR_CR2_BRRDY) == 0U) { -+ ; -+ } -+ } -+ -+ clk_disable(RTCAPB); -+ -+ enter_cstop_done = true; -+} -+ -+bool stm32_is_cstop_done(void) -+{ -+ return enter_cstop_done; -+} -+ -+/* -+ * stm32_exit_cstop - Exit from CSTOP mode -+ */ -+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; -+ } -+ -+ enter_cstop_done = false; -+ -+ stm32mp1_syscfg_enable_io_compensation_start(); -+ -+ plat_ic_set_priority_mask(gicc_pmr); -+ -+ /* Disable RCC Wake-up */ -+ mmio_clrbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); -+ -+ /* Disable STOP request */ -+ mmio_setbits_32(rcc_base + RCC_MP_SREQCLRR, -+ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); -+ -+ 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(stgen_cnt, stdby_time_in_ms); -+ -+ if (stm32mp1_clock_stopmode_resume() != 0) { -+ panic(); -+ } -+ -+ stm32mp1_syscfg_enable_io_compensation_finish(); -+} -+ -+static int get_locked(volatile int *state) -+{ -+ volatile int val; -+ -+ spin_lock(&lp_lock); -+ val = *state; -+ spin_unlock(&lp_lock); -+ -+ return val; -+} -+ -+static void set_locked(volatile int *state, int val) -+{ -+ spin_lock(&lp_lock); -+ *state = val; -+ spin_unlock(&lp_lock); -+} -+ -+static void smp_synchro(int state, bool wake_up) -+{ -+ /* if the other CPU is stopped, no need to synchronize */ -+ if (psci_is_last_on_cpu() == 1U) { -+ return; -+ } -+ -+ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) { -+ set_locked(&cpu0_state, state); -+ -+ while (get_locked(&cpu1_state) != state) { -+ if (wake_up) { -+ /* wakeup secondary CPU */ -+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_6, -+ STM32MP_SECONDARY_CPU); -+ udelay(10); -+ } -+ }; -+ } else { -+ while (get_locked(&cpu0_state) != state) { -+ if (wake_up) { -+ /* wakeup primary CPU */ -+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_6, -+ STM32MP_PRIMARY_CPU); -+ udelay(10); -+ } -+ }; -+ -+ set_locked(&cpu1_state, state); -+ } -+} -+ -+static void stm32_auto_stop_cpu0(void) -+{ -+ smp_synchro(STATE_AUTOSTOP_ENTRY, false); -+ -+ enter_cstop(STM32_PM_CSTOP_ALLOW_LP_STOP, 0); -+ -+ stm32_pwr_down_wfi(true); -+ -+ stm32_exit_cstop(); -+ -+ smp_synchro(STATE_AUTOSTOP_EXIT, true); -+} -+ -+static void stm32_auto_stop_cpu1(void) -+{ -+ unsigned int gicc_pmr_cpu1; -+ -+ /* clear cache before the DDR is being disabled by cpu0 */ -+ dcsw_op_all(DC_OP_CISW); -+ -+ smp_synchro(STATE_AUTOSTOP_ENTRY, false); -+ -+ gicc_pmr_cpu1 = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8); -+ wfi(); -+ plat_ic_set_priority_mask(gicc_pmr_cpu1); -+ -+ smp_synchro(STATE_AUTOSTOP_EXIT, true); -+} -+ -+void stm32_auto_stop(void) -+{ -+ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) { -+ stm32_auto_stop_cpu0(); -+ } else { -+ stm32_auto_stop_cpu1(); -+ } -+} -+ -+static void enter_shutdown(void) -+{ -+ /* Set DDR in Self-refresh before shutting down the platform */ -+ if (ddr_standby_sr_entry() != 0) { -+ WARN("DDR can't be set in Self-refresh mode\n"); -+ } -+ -+ if (dt_pmic_status() > 0) { -+ if (!initialize_pmic_i2c()) { -+ panic(); -+ } -+ -+ stpmic1_switch_off(); -+ -+ udelay(100); -+ -+ /* Shouldn't be reached */ -+ panic(); -+ } -+} -+ -+static void enter_csleep(void) -+{ -+ uintptr_t pwr_base = stm32mp_pwr_base(); -+ -+ mmio_clrsetbits_32(pwr_base + PWR_MPUCR, PWR_MPUCR_MASK, -+ config_pwr[STM32_PM_CSLEEP_RUN].pwr_mpucr); -+ mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK, -+ config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1); -+ -+ stm32_pwr_down_wfi(false); -+} -+ -+void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr) -+{ -+ switch (mode) { -+ case STM32_PM_SHUTDOWN: -+ enter_shutdown(); -+ break; -+ -+ case STM32_PM_CSLEEP_RUN: -+ enter_csleep(); -+ break; -+ -+ default: -+ enter_cstop(mode, nsec_addr); -+ break; -+ } -+} -+ -+void stm32_init_low_power(void) -+{ -+ uintptr_t pwr_base = stm32mp_pwr_base(); -+ uintptr_t rcc_base = stm32mp_rcc_base(); -+ -+ /* -+ * Configure Standby mode available for MCU by default -+ * and allow to switch in standby SoC in all case -+ */ -+ mmio_setbits_32(pwr_base + PWR_MCUCR, PWR_MCUCR_PDDS); -+ -+ /* Disable STOP request */ -+ mmio_setbits_32(rcc_base + RCC_MP_SREQCLRR, -+ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); -+ -+ /* Disable retention and backup RAM content after standby */ -+ mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN); -+ -+ /* 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); -+} -diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c -index 31a9ae7f13..962a992243 100644 ---- a/plat/st/stm32mp1/stm32mp1_pm.c -+++ b/plat/st/stm32mp1/stm32mp1_pm.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 - */ -@@ -14,14 +14,21 @@ - #include - #include - #include --#include -+#include -+#include -+#include -+#include - #include - #include - #include - #include - -+#include -+#include -+ - static uintptr_t stm32_sec_entrypoint; - static uint32_t cntfrq_core0; -+static uintptr_t saved_entrypoint; - - /******************************************************************************* - * STM32MP1 handler called when a CPU is about to enter standby. -@@ -34,11 +41,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(); - -@@ -65,16 +73,29 @@ 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); - -+ if (stm32mp_is_single_core()) { -+ return PSCI_E_INTERN_FAIL; -+ } -+ - if (mpidr == current_cpu_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); -+ -+ /* Wait for this IT to be acknowledged by ROM code. */ -+ udelay(10); -+ - /* Only one valid entry point */ - if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) { - return PSCI_E_INVALID_ADDRESS; - } - -- stm32mp_clk_enable(RTCAPB); -+ clk_enable(RTCAPB); - - cntfrq_core0 = read_cntfrq_el0(); - -@@ -84,7 +105,7 @@ 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); - -- stm32mp_clk_disable(RTCAPB); -+ clk_disable(RTCAPB); - - /* Generate an IT to core 1 */ - gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); -@@ -107,7 +128,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) - { -- /* Nothing to do, power domain is not disabled */ -+ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND); -+ -+ stm32_enter_low_power(soc_mode, saved_entrypoint); - } - - /******************************************************************************* -@@ -118,7 +141,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,28 +157,65 @@ static void stm32_pwr_domain_suspend_finish(const psci_power_state_t - /* Nothing to do, power domain is not disabled */ - } - -+/******************************************************************************* -+ * STM32MP1 handler called when a core tries to power itself down. If this -+ * call is made by core 0, it is a return from stop mode. In this case, we -+ * should restore previous context and jump to secure entrypoint. -+ ******************************************************************************/ - static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t - *target_state) - { -- ERROR("stm32mpu1 Power Down WFI: operation not handled.\n"); -+ if (MPIDR_AFFLVL0_VAL(read_mpidr_el1()) == STM32MP_PRIMARY_CPU) { -+ void (*warm_entrypoint)(void) = -+ (void (*)(void))stm32_sec_entrypoint; -+ -+ stm32_pwr_down_wfi(stm32_is_cstop_done()); -+ -+ stm32_exit_cstop(); -+ -+ disable_mmu_icache_secure(); -+ -+ warm_entrypoint(); -+ } -+ -+ mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, -+ RCC_MP_GRSTCSETR_MPUP1RST); -+ -+ /* -+ * Synchronize on memory accesses and instruction flow before -+ * auto-reset from the WFI instruction. -+ */ -+ dsb(); -+ isb(); -+ wfi(); -+ -+ /* This shouldn't be reached */ - panic(); - } - - static void __dead2 stm32_system_off(void) - { -- 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()) { -+ /* Prepare Core 1 reset */ -+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, -+ RCC_MP_GRSTCSETR_MPUP1RST); -+ /* Send IT to core 1 to put itself in WFI */ -+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, STM32MP_SECONDARY_CPU); -+ } -+ -+ stm32_enter_low_power(soc_mode, 0); -+ -+ stm32_pwr_down_wfi(false); -+ -+ /* This shouldn't be reached */ - panic(); - } - - static void __dead2 stm32_system_reset(void) - { -- mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, -- RCC_MP_GRSTCSETR_MPSYSRST); -- -- /* Loop in case system reset is not immediately caught */ -- for ( ; ; ) { -- ; -- } -+ stm32mp_system_reset(); - } - - static int stm32_validate_power_state(unsigned int power_state, -@@ -188,6 +248,8 @@ static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) - return PSCI_E_INVALID_ADDRESS; - } - -+ saved_entrypoint = entrypoint; -+ - return PSCI_E_SUCCESS; - } - -@@ -211,6 +273,12 @@ static int stm32_node_hw_state(u_register_t target_cpu, - return (int)HW_ON; - } - -+static void stm32_get_sys_suspend_power_state(psci_power_state_t *req_state) -+{ -+ req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_OFF; -+ req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_OFF; -+} -+ - /******************************************************************************* - * Export the platform handlers. The ARM Standard platform layer will take care - * of registering the handlers with PSCI. -@@ -227,7 +295,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, -- .get_node_hw_state = stm32_node_hw_state -+ .get_node_hw_state = stm32_node_hw_state, -+ .get_sys_suspend_power_state = stm32_get_sys_suspend_power_state, - }; - - /******************************************************************************* -diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c -new file mode 100644 -index 0000000000..1b22b3122f ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_power_config.c -@@ -0,0 +1,223 @@ -+/* -+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes" -+#define SYSTEM_OFF_MODE "system_off_soc_mode" -+#define RETRAM_ENABLED "st,retram-enabled-in-standby-ddr-sr" -+ -+static uint32_t deepest_system_suspend_mode; -+static uint32_t system_off_mode; -+static bool retram_enabled; -+static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE]; -+ -+static int dt_get_pwr_node(void *fdt) -+{ -+ return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+} -+ -+static void save_supported_mode(void *fdt, int pwr_node) -+{ -+ int len; -+ uint32_t count; -+ unsigned int i; -+ uint32_t supported[ARRAY_SIZE(stm32mp1_supported_soc_modes)]; -+ const void *prop; -+ -+ prop = fdt_getprop(fdt, pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES, &len); -+ if (prop == NULL) { -+ panic(); -+ } -+ -+ count = (uint32_t)len / sizeof(uint32_t); -+ if (count > STM32_PM_MAX_SOC_MODE) { -+ panic(); -+ } -+ -+ if (fdt_read_uint32_array(fdt, pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES, -+ count, &supported[0]) < 0) { -+ ERROR("PWR DT\n"); -+ panic(); -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (supported[i] >= STM32_PM_MAX_SOC_MODE) { -+ ERROR("Invalid mode\n"); -+ panic(); -+ } -+ stm32mp1_supported_soc_modes[supported[i]] = 1U; -+ } -+ -+ /* Initialize to deepest possible mode */ -+ for (i = STM32_PM_MAX_SOC_MODE - 1U; i != STM32_PM_CSLEEP_RUN; i--) { -+ if (stm32mp1_supported_soc_modes[i] == 1U) { -+ deepest_system_suspend_mode = i; -+ break; -+ } -+ } -+} -+ -+static int dt_fill_lp_state(uint32_t *lp_state_config, const char *lp_state) -+{ -+ int pwr_node; -+ void *fdt; -+ const fdt32_t *cuint; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ pwr_node = dt_get_pwr_node(fdt); -+ if (pwr_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ cuint = fdt_getprop(fdt, pwr_node, lp_state, NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ *lp_state_config = fdt32_to_cpu(*cuint); -+ -+ save_supported_mode(fdt, pwr_node); -+ -+ return 0; -+} -+ -+static int dt_fill_retram_enabled(void) -+{ -+ int pwr_node; -+ void *fdt; -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ pwr_node = dt_get_pwr_node(fdt); -+ if (pwr_node < 0) { -+ return -ENOENT; -+ } -+ -+ if (fdt_getprop(fdt, pwr_node, RETRAM_ENABLED, NULL) == NULL) { -+ retram_enabled = false; -+ } else { -+ retram_enabled = true; -+ } -+ -+ return 0; -+} -+ -+void stm32mp1_init_lp_states(void) -+{ -+ if (dt_fill_lp_state(&system_off_mode, SYSTEM_OFF_MODE) < 0) { -+ ERROR("Node %s not found\n", SYSTEM_OFF_MODE); -+ panic(); -+ } -+ -+ if (dt_fill_retram_enabled() < 0) { -+ ERROR("could not configure retram state\n"); -+ panic(); -+ } -+} -+ -+/* Init with all domains ON */ -+static bool pm_dom[STM32MP1_PD_MAX_PM_DOMAIN] = { -+ [STM32MP1_PD_VSW] = false, -+ [STM32MP1_PD_CORE_RET] = false, -+ [STM32MP1_PD_CORE] = false -+}; -+ -+static bool stm32mp1_get_pm_domain_state(uint8_t mode) -+{ -+ bool res = true; -+ enum stm32mp1_pm_domain id = STM32MP1_PD_MAX_PM_DOMAIN; -+ -+ while (res && (id > mode)) { -+ id--; -+ res &= pm_dom[id]; -+ } -+ -+ return res; -+} -+ -+int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status) -+{ -+ if (domain >= STM32MP1_PD_MAX_PM_DOMAIN) { -+ return -EINVAL; -+ } -+ -+ pm_dom[domain] = status; -+ -+ return 0; -+} -+ -+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; -+} -+ -+uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode) -+{ -+ uint32_t mode; -+ -+ if (psci_mode == PSCI_MODE_SYSTEM_OFF) { -+ return system_off_mode; -+ } -+ -+ mode = deepest_system_suspend_mode; -+ -+ while ((mode > STM32_PM_CSLEEP_RUN) && !is_allowed_mode(mode)) { -+ mode--; -+ } -+ -+ return mode; -+} -+ -+int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode) -+{ -+ if (soc_mode >= STM32_PM_MAX_SOC_MODE) { -+ return -EINVAL; -+ } -+ -+ if (psci_mode == PSCI_MODE_SYSTEM_SUSPEND) { -+ deepest_system_suspend_mode = soc_mode; -+ } -+ -+ if (psci_mode == PSCI_MODE_SYSTEM_OFF) { -+ system_off_mode = soc_mode; -+ } -+ -+ return 0; -+} -+ -+bool stm32mp1_get_retram_enabled(void) -+{ -+ return retram_enabled; -+} -diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c -index bc77ee3342..09afe1a6ea 100644 ---- a/plat/st/stm32mp1/stm32mp1_private.c -+++ b/plat/st/stm32mp1/stm32mp1_private.c -@@ -10,8 +10,18 @@ - - #include - -+#include -+#include -+#include - #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) -@@ -34,6 +44,10 @@ - BOARD_ID_VARFG_SHIFT) - #define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK) - -+#define TAMP_BOOT_ITF_BACKUP_REG_ID U(20) -+#define TAMP_BOOT_ITF_MASK U(0x0000FF00) -+#define TAMP_BOOT_ITF_SHIFT 8 -+ - #if defined(IMAGE_BL2) - #define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ - STM32MP_SYSRAM_SIZE, \ -@@ -58,6 +72,13 @@ - MT_EXECUTE_NEVER) - #endif - -+#define MAP_RETRAM MAP_REGION_FLAT(STM32MP_RETRAM_BASE, \ -+ STM32MP_RETRAM_SIZE, \ -+ MT_MEMORY | \ -+ MT_RW | \ -+ MT_NS | \ -+ MT_EXECUTE_NEVER) -+ - #define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ - STM32MP1_DEVICE1_SIZE, \ - MT_DEVICE | \ -@@ -76,14 +97,18 @@ - static const mmap_region_t stm32mp1_mmap[] = { - MAP_SEC_SYSRAM, - MAP_DEVICE1, -+#if STM32MP_RAW_NAND - MAP_DEVICE2, -+#endif - {0} - }; - #endif - #if defined(IMAGE_BL32) - static const mmap_region_t stm32mp1_mmap[] = { -+#if !STM32MP_SP_MIN_IN_DDR - MAP_SEC_SYSRAM, - MAP_NS_SYSRAM, -+#endif - MAP_DEVICE1, - MAP_DEVICE2, - {0} -@@ -92,10 +117,156 @@ 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(); -+#ifdef DCACHE_OFF -+ flags |= DISABLE_DCACHE; -+#endif -+ enable_mmu_svc_mon(flags); -+#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), -+}; - -- enable_mmu_svc_mon(0); -+#define TIMEOUT_US_1MS U(1000) -+ -+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 ((!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) == -+ ETZPC_DECPROT_MCU_ISOLATION))) { -+ continue; -+ } -+ -+ if (tzc_source_ip[id].reset_id != GPU_R) { -+ uint32_t reset = tzc_source_ip[id].reset_id; -+ int ret; -+ -+ ret = stm32mp_reset_assert(reset, TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ ret = stm32mp_reset_deassert(reset, TIMEOUT_US_1MS); -+ if (ret != 0) { -+ 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; -+ -+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, sec_cpu); -+ 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); -+ -+ stm32mp_wait_cpu_reset(); - } - - uintptr_t stm32_get_gpio_bank_base(unsigned int bank) -@@ -120,6 +291,32 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank) - return bank * GPIO_BANK_OFFSET; - } - -+#if STM32MP_UART_PROGRAMMER || defined(IMAGE_BL32) -+/* -+ * UART Management -+ */ -+static const uintptr_t stm32mp1_uart_addresses[8] = { -+ USART1_BASE, -+ USART2_BASE, -+ USART3_BASE, -+ UART4_BASE, -+ UART5_BASE, -+ USART6_BASE, -+ UART7_BASE, -+ UART8_BASE, -+}; -+ -+uintptr_t get_uart_address(uint32_t instance_nb) -+{ -+ if ((instance_nb == 0U) || -+ (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) { -+ return 0U; -+ } -+ -+ return stm32mp1_uart_addresses[instance_nb - 1U]; -+} -+#endif -+ - unsigned long stm32_get_gpio_bank_clock(unsigned int bank) - { - if (bank == GPIO_BANK_Z) { -@@ -153,63 +350,138 @@ int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank) - } - } - --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 (bsec_find_otp_name_in_dt(otp_name, otp_idx, otp_len) != BSEC_OK) { -+ return -1; -+ } - -- assert(part_nb != NULL); -+ return 0; -+} - -- if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) { -+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val) -+{ -+ uint32_t otp_idx; -+ -+ 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; - } - -- if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) { -- ERROR("BSEC: PART_NUMBER_OTP Error\n"); -+ return 0; -+} -+ -+int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val) -+{ -+ int ret = BSEC_NOT_SUPPORTED; -+ -+ assert(otp_val != NULL); -+ -+#if defined(IMAGE_BL2) -+ ret = bsec_shadow_read_otp(otp_val, otp_idx); -+#elif defined(IMAGE_BL32) -+ ret = bsec_read_otp(otp_val, otp_idx); -+#else -+#error "Not supported" -+#endif -+ if (ret != BSEC_OK) { -+ ERROR("BSEC: idx=%d Read Error\n", otp_idx); - return -1; - } - -+ return 0; -+} -+ -+int stm32mp_get_chip_version(uint32_t *chip_version) -+{ -+ return stm32mp1_dbgmcu_get_chip_version(chip_version); -+} -+ -+static uint32_t get_part_number(void) -+{ -+ static uint32_t part_number; -+ uint32_t dev_id; -+ -+ 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(); -+ } -+ - 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; - -- assert(cpu_package != NULL); -- -- 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; - } - --void stm32mp_print_cpuinfo(void) -+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_get_soc_name(char name[STM32_SOC_NAME_SIZE]) - { -- const char *cpu_s, *cpu_r, *pkg; -- uint32_t part_number; -- uint32_t cpu_package; -+ char *cpu_s, *cpu_r, *pkg; - 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; -@@ -252,13 +524,7 @@ void stm32mp_print_cpuinfo(void) - } - - /* 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; -@@ -277,10 +543,9 @@ void stm32mp_print_cpuinfo(void) - } - - /* REVISION */ -- ret = stm32mp1_dbgmcu_get_chip_version(&chip_dev_id); -+ ret = stm32mp_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) { -@@ -295,40 +560,23 @@ void stm32mp_print_cpuinfo(void) - break; - } - -- NOTICE("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r); -+ snprintf(name, STM32_SOC_NAME_SIZE, -+ "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r); - } - --void stm32mp_print_boardinfo(void) -+void stm32mp_print_cpuinfo(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(); -- } -+ char name[STM32_SOC_NAME_SIZE]; - -- 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(); -- } -+ stm32mp_get_soc_name(name); -+ NOTICE("CPU: %s\n", name); -+} - -- board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); -+void stm32mp_print_boardinfo(void) -+{ -+ uint32_t board_id = 0; - -- 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; - } - -@@ -349,20 +597,12 @@ 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; -- -- 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: - case STM32MP151D_PART_NB: - case STM32MP151F_PART_NB: - return true; -- - default: - return false; - } -@@ -373,12 +613,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) -@@ -398,13 +653,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(); - } - -@@ -426,29 +675,34 @@ 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 (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { - panic(); - } - -- if ((flags & IWDG_DISABLE_ON_STOP) != 0U) { -- otp |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS); -+ 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; - } - -@@ -456,6 +710,52 @@ uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags) - } - #endif - -+/* -+ * This function allows to split bindings between platform and ETZPC -+ * HW mapping. If this conversion was done at driver level, the driver -+ * should include all supported platform bindings. ETZPC may be used on -+ * other platforms. -+ */ -+enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode) -+{ -+ switch (mode) { -+ case DECPROT_S_RW: -+ return ETZPC_DECPROT_S_RW; -+ case DECPROT_NS_R_S_W: -+ return ETZPC_DECPROT_NS_R_S_W; -+ case DECPROT_MCU_ISOLATION: -+ return ETZPC_DECPROT_MCU_ISOLATION; -+ case DECPROT_NS_RW: -+ return ETZPC_DECPROT_NS_RW; -+ default: -+ 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; -+} -+ -+#if STM32MP_USE_STM32IMAGE - /* Get the non-secure DDR size */ - uint32_t stm32mp_get_ddr_ns_size(void) - { -@@ -467,12 +767,145 @@ uint32_t stm32mp_get_ddr_ns_size(void) - } - - ddr_size = dt_get_ddr_size(); -- if ((ddr_size <= (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE)) || -- (ddr_size > STM32MP_DDR_MAX_SIZE)) { -+ if ((ddr_size <= STM32MP_DDR_S_SIZE) || (ddr_size > STM32MP_DDR_MAX_SIZE)) { - panic(); - } - -+#if defined(AARCH32_SP_OPTEE) - ddr_ns_size = ddr_size - (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE); -+#else -+ ddr_ns_size = ddr_size; -+#endif - - return ddr_ns_size; - } -+#endif -+ -+bool stm32mp1_addr_inside_backupsram(uintptr_t addr) -+{ -+ return (addr >= STM32MP_BACKUP_RAM_BASE) && -+ (addr < (STM32MP_BACKUP_RAM_BASE + STM32MP_BACKUP_RAM_SIZE)); -+} -+ -+bool stm32mp1_is_wakeup_from_standby(void) -+{ -+ uint32_t bkpr_core1_addr = tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); -+ uint32_t nsec_address; -+ -+ if (stm32mp_get_boot_action() != BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY) { -+ return false; -+ } -+ -+ clk_enable(RTCAPB); -+ nsec_address = mmio_read_32(bkpr_core1_addr); -+ clk_disable(RTCAPB); -+ -+ if (nsec_address == 0U) { -+ return false; -+ } -+ -+ return stm32_pm_context_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); -+ -+ clk_enable(RTCAPB); -+ -+ mmio_clrsetbits_32(bkpr_itf_idx, -+ TAMP_BOOT_ITF_MASK, -+ ((interface << 4) | (instance & 0xFU)) << -+ TAMP_BOOT_ITF_SHIFT); -+ -+ clk_disable(RTCAPB); -+ -+ return 0; -+} -+ -+int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance) -+{ -+ static uint32_t itf; -+ -+ if (itf == 0U) { -+ uint32_t bkpr = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); -+ -+ clk_enable(RTCAPB); -+ -+ itf = (mmio_read_32(bkpr) & TAMP_BOOT_ITF_MASK) >> TAMP_BOOT_ITF_SHIFT; -+ -+ clk_disable(RTCAPB); -+ } -+ -+ *interface = itf >> 4; -+ *instance = itf & 0xFU; -+ -+ return 0; -+} -+ -+bool stm32_boot_is_serial(void) -+{ -+ uint32_t boot_itf; -+ uint32_t boot_instance; -+ -+ stm32_get_boot_interface(&boot_itf, &boot_instance); -+ -+ if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) || -+ (boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB)) { -+ return true; -+ } -+ -+ return false; -+} -+ -+#if defined(IMAGE_BL32) && DEBUG -+static const char *const dump_table[] = { -+ "sp_usr ", -+ "lr_usr ", -+ "spsr_irq", -+ "sp_irq ", -+ "lr_irq ", -+ "spsr_fiq", -+ "sp_fiq ", -+ "lr_fiq ", -+ "spsr_svc", -+ "sp_svc ", -+ "lr_svc ", -+ "spsr_abt", -+ "sp_abt ", -+ "lr_abt ", -+ "spsr_und", -+ "sp_und ", -+ "lr_und ", -+ "spsr_mon", -+ "sp_mon", -+ "lr_mon", -+ "scr", -+ "pmcr", -+}; -+ -+/* -+ * Dump CPU registers when entering in monitor. -+ */ -+void stm32mp_dump_core_registers(bool fcore) -+{ -+ static bool firstcore; -+ unsigned int i; -+ smc_ctx_t *ctx = smc_get_ctx(NON_SECURE); -+ uint32_t *reg = (uint32_t *)&ctx->sp_usr; -+ -+ if (fcore) { -+ firstcore = true; -+ } -+ -+ if (!firstcore) { -+ return; -+ } -+ -+ INFO("CPU : %i\n", plat_my_core_pos()); -+ -+ for (i = 0U; i < ARRAY_SIZE(dump_table); i++) { -+ INFO("%s : 0x%x\n", dump_table[i], reg[i]); -+ } -+} -+#endif -diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c -index 80faf0c6e0..a6086f93fd 100644 ---- a/plat/st/stm32mp1/stm32mp1_scmi.c -+++ b/plat/st/stm32mp1/stm32mp1_scmi.c -@@ -8,12 +8,14 @@ - - #include - -+#include - #include - #include - #include - #include - #include - #include -+#include - - #define TIMEOUT_US_1MS 1000U - -@@ -124,6 +126,7 @@ static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = { - RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"), - RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"), - RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"), -+ RESET_CELL(RST_SCMI0_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"), - }; - - struct scmi_agent_resources { -@@ -260,6 +263,17 @@ const char *plat_scmi_clock_get_name(unsigned int agent_id, - - 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); - -@@ -271,12 +285,50 @@ int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, - return SCMI_DENIED; - } - -- if (array == NULL) { -- *nb_elts = 1U; -- } else if (*nb_elts == 1U) { -- *array = stm32mp_clk_get_rate(clock->clock_id); -- } else { -- return SCMI_GENERIC_ERROR; -+ 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] = 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) -+{ -+ 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: -+ if (stm32mp1_set_opp_khz(rate / 1000UL) != 0) { -+ return SCMI_INVALID_PARAMETERS; -+ } -+ break; -+ default: -+ if (rate != clk_get_rate(clock->clock_id)) { -+ return SCMI_INVALID_PARAMETERS; -+ } -+ break; - } - - return SCMI_SUCCESS; -@@ -292,7 +344,7 @@ unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, - return 0U; - } - -- return stm32mp_clk_get_rate(clock->clock_id); -+ return clk_get_rate(clock->clock_id); - } - - int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id) -@@ -323,13 +375,13 @@ int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, - if (enable_not_disable) { - if (!clock->enabled) { - VERBOSE("SCMI clock %u enable\n", scmi_id); -- stm32mp_clk_enable(clock->clock_id); -+ 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); -+ clk_disable(clock->clock_id); - clock->enabled = false; - } - } -@@ -388,6 +440,10 @@ int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id, - return SCMI_NOT_FOUND; - } - -+ if (rstd->reset_id == MCU_HOLD_BOOT_R) { -+ return SCMI_NOT_SUPPORTED; -+ } -+ - if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) { - return SCMI_DENIED; - } -@@ -423,6 +479,13 @@ int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id, - return SCMI_DENIED; - } - -+ if (rstd->reset_id == MCU_HOLD_BOOT_R) { -+ VERBOSE("SCMI MCU reset %s\n", -+ assert_not_deassert ? "set" : "release"); -+ stm32mp_reset_assert_deassert_to_mcu(assert_not_deassert); -+ return SCMI_SUCCESS; -+ } -+ - if (assert_not_deassert) { - VERBOSE("SCMI reset %lu set\n", rstd->reset_id); - stm32mp_reset_set(rstd->reset_id); -@@ -461,7 +524,7 @@ void stm32mp1_init_scmi_server(void) - /* 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); -+ clk_enable(clk->clock_id); - } - } - -@@ -476,3 +539,51 @@ void stm32mp1_init_scmi_server(void) - } - } - } -+ -+/* -+ * 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 3a29ba9661..b1838db26e 100644 ---- a/plat/st/stm32mp1/stm32mp1_security.c -+++ b/plat/st/stm32mp1/stm32mp1_security.c -@@ -10,22 +10,50 @@ - - #include - #include -+#include - #include - #include -+#include - #include - --#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ -- 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) -+static unsigned int region_nb; -+ -+static void init_tzc400_begin(unsigned int region0_attr) -+{ -+ tzc400_init(STM32MP1_TZC_BASE); -+ tzc400_disable_filters(); -+ -+ /* Region 0 set to cover all DRAM at 0xC000_0000 */ -+ tzc400_configure_region0(region0_attr, 0); -+ -+ region_nb = 1U; -+} -+ -+static void init_tzc400_end(unsigned int action) -+{ -+ tzc400_set_action(action); -+ tzc400_enable_filters(); -+} -+ -+static void tzc400_add_region(unsigned long long region_base, -+ unsigned long long region_top, bool sec) -+{ -+ unsigned int sec_attr; -+ unsigned int nsaid_permissions; -+ -+ if (sec) { -+ sec_attr = TZC_REGION_S_RDWR; -+ nsaid_permissions = 0; -+ } else { -+ sec_attr = TZC_REGION_S_NONE; -+ nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR; -+ } -+ -+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base, -+ region_top, sec_attr, nsaid_permissions); -+ -+ region_nb++; -+} - - /******************************************************************************* - * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access -@@ -38,10 +66,9 @@ static void init_tzc400(void) - unsigned long long ddr_ns_size = - (unsigned long long)stm32mp_get_ddr_ns_size(); - unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U); -+ unsigned long long ddr_top __unused; - -- tzc400_init(STM32MP1_TZC_BASE); -- -- tzc400_disable_filters(); -+ init_tzc400_begin(TZC_REGION_S_NONE); - - /* - * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the -@@ -49,36 +76,28 @@ static void init_tzc400(void) - */ - region_base = ddr_base; - region_top = ddr_ns_top; -- tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, -- region_base, -- region_top, -- TZC_REGION_S_NONE, -- TZC_REGION_NSEC_ALL_ACCESS_RDWR); -+ tzc400_add_region(region_base, region_top, false); - --#ifdef AARCH32_SP_OPTEE -+#if defined(AARCH32_SP_OPTEE) - /* Region 2 set to cover all secure DRAM. */ - region_base = region_top + 1U; - region_top += STM32MP_DDR_S_SIZE; -- 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 = region_top + 1U; -- region_top += STM32MP_DDR_SHMEM_SIZE; -- tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3, -- region_base, -- region_top, -- TZC_REGION_S_NONE, -- TZC_REGION_NSEC_ALL_ACCESS_RDWR); -+ tzc400_add_region(region_base, region_top, true); -+ -+ ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U; -+ if (region_top < ddr_top) { -+ /* Region 3 set to cover non-secure memory DRAM after BL32. */ -+ region_base = region_top + 1U; -+ region_top = ddr_top; -+ tzc400_add_region(region_base, region_top, false); -+ } - #endif - -- /* Raise an exception if a NS device tries to access secure memory */ -- tzc400_set_action(TZC_ACTION_ERR); -- -- tzc400_enable_filters(); -+ /* -+ * Raise an interrupt (secure FIQ) if a NS device tries to access -+ * secure memory -+ */ -+ init_tzc400_end(TZC_ACTION_INT); - } - - /******************************************************************************* -@@ -88,26 +107,14 @@ static void init_tzc400(void) - ******************************************************************************/ - static void early_init_tzc400(void) - { -- stm32mp_clk_enable(TZC1); -- stm32mp_clk_enable(TZC2); -- -- tzc400_init(STM32MP1_TZC_BASE); -+ clk_enable(TZC1); -+ clk_enable(TZC2); - -- tzc400_disable_filters(); -- -- /* 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 + -- (STM32MP_DDR_MAX_SIZE - 1U), -- TZC_REGION_S_NONE, -- TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | -- TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID)); -+ /* Region 0 set to cover all DRAM secure at 0xC000_0000 */ -+ init_tzc400_begin(TZC_REGION_S_RDWR); - - /* Raise an exception if a NS device tries to access secure memory */ -- tzc400_set_action(TZC_ACTION_ERR); -- -- tzc400_enable_filters(); -+ init_tzc400_end(TZC_ACTION_ERR); - } - - /******************************************************************************* -diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c -index 208e34a8b0..01fb499c1a 100644 ---- a/plat/st/stm32mp1/stm32mp1_shared_resources.c -+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c -@@ -87,6 +87,64 @@ static const char __unused *shres2str_state(unsigned int state) - return shres2str_state_tbl[state]; - } - -+struct shres2decprot { -+ unsigned int shres_id; -+ unsigned int decprot_id; -+ const char *decprot_str; -+}; -+ -+#define SHRES2DECPROT(shres, decprot, str) { \ -+ .shres_id = shres, \ -+ .decprot_id = decprot, \ -+ .decprot_str = str, \ -+ } -+ -+#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"), -+ SHRES2DECPROT(STM32MP1_SHRES_SPI6, STM32MP1_ETZPC_SPI6_ID, "SPI6"), -+ SHRES2DECPROT(STM32MP1_SHRES_I2C4, STM32MP1_ETZPC_I2C4_ID, "I2C4"), -+ SHRES2DECPROT(STM32MP1_SHRES_RNG1, STM32MP1_ETZPC_RNG1_ID, "RNG1"), -+ SHRES2DECPROT(STM32MP1_SHRES_HASH1, STM32MP1_ETZPC_HASH1_ID, "HASH1"), -+ SHRES2DECPROT(STM32MP1_SHRES_CRYP1, STM32MP1_ETZPC_CRYP1_ID, "CRYP1"), -+ SHRES2DECPROT(STM32MP1_SHRES_I2C6, STM32MP1_ETZPC_I2C6_ID, "I2C6"), -+ /* Below are specific IDs without a 1-to-1 mapping to SHRES IDs */ -+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_STGENC_ID, "STGEN"), -+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_BKPSRAM_ID, "BKPSRAM"), -+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRCTRL_ID, "DDRCTRL"), -+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRPHYC_ID, "DDRPHY"), -+}; -+ -+static unsigned int decprot2shres(unsigned int decprot_id) -+{ -+ uint32_t i; -+ -+ for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) { -+ if (shres2decprot_tbl[i].decprot_id == decprot_id) { -+ return shres2decprot_tbl[i].shres_id; -+ } -+ } -+ -+ VERBOSE("No shared resource %u", decprot_id); -+ return SHRES_INVALID; -+} -+ -+static const char *decprot2str(unsigned int decprot_id) -+{ -+ size_t i; -+ -+ for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) { -+ if (shres2decprot_tbl[i].decprot_id == decprot_id) { -+ return shres2decprot_tbl[i].decprot_str; -+ } -+ } -+ -+ ERROR("Invalid ID %u", decprot_id); -+ panic(); -+} -+ - /* Get resource state: these accesses lock the registering support */ - static void lock_registering(void) - { -@@ -114,7 +172,7 @@ static unsigned int get_gpio_nbpin(unsigned int bank) - if (bank != GPIO_BANK_Z) { - int count = fdt_get_gpio_bank_pin_count(bank); - -- assert((count >= 0) || (count <= (GPIO_PIN_MAX + 1))); -+ assert((count >= 0) || ((unsigned int)count <= (GPIO_PIN_MAX + 1))); - - return (unsigned int)count; - } -@@ -163,7 +221,7 @@ static void register_periph(enum stm32mp_shres id, unsigned int state) - - if ((id >= STM32MP1_SHRES_GPIOZ(0)) && - (id <= STM32MP1_SHRES_GPIOZ(7)) && -- ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) { -+ ((unsigned int)(id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) { - ERROR("Invalid GPIO pin %u, %u pin(s) available\n", - id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin()); - panic(); -@@ -334,6 +392,53 @@ void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) - } - } - -+void stm32mp1_register_etzpc_decprot(unsigned int id, -+ enum etzpc_decprot_attributes attr) -+{ -+ unsigned int state = SHRES_SECURE; -+ unsigned int id_shres; -+ -+ switch (attr) { -+ case ETZPC_DECPROT_S_RW: -+ break; -+ case ETZPC_DECPROT_NS_R_S_W: -+ case ETZPC_DECPROT_MCU_ISOLATION: -+ case ETZPC_DECPROT_NS_RW: -+ state = SHRES_NON_SECURE; -+ break; -+ default: -+ panic(); -+ } -+ -+ switch (id) { -+ case STM32MP1_ETZPC_STGENC_ID: -+ case STM32MP1_ETZPC_BKPSRAM_ID: -+ /* We assume these must always be assigned to secure world */ -+ if (state != SHRES_SECURE) { -+ panic(); -+ } -+ break; -+ case STM32MP1_ETZPC_DDRCTRL_ID: -+ case STM32MP1_ETZPC_DDRPHYC_ID: -+ /* allow write only for secure world */ -+ if ((attr != ETZPC_DECPROT_S_RW) && -+ (attr != ETZPC_DECPROT_NS_R_S_W)) { -+ panic(); -+ } -+ break; -+ default: -+ id_shres = decprot2shres(id); -+ if (id_shres == SHRES_INVALID) { -+ if (state == SHRES_SECURE) { -+ panic(); -+ } -+ } else { -+ register_periph(id_shres, state); -+ } -+ break; -+ } -+} -+ - static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) - { - unsigned int non_secure = 0U; -@@ -379,12 +484,15 @@ bool stm32mp_nsec_can_access_clock(unsigned long clock_id) - enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; - - switch (clock_id) { -+ case BSEC: -+ case CK_AXI: - case CK_CSI: - case CK_HSE: - case CK_HSE_DIV2: - case CK_HSI: - case CK_LSE: - case CK_LSI: -+ case CK_MPU: - case PLL1_P: - case PLL1_Q: - case PLL1_R: -@@ -454,6 +562,7 @@ bool stm32mp_nsec_can_access_reset(unsigned int reset_id) - shres_id = STM32MP1_SHRES_I2C6; - break; - case MCU_R: -+ case MCU_HOLD_BOOT_R: - shres_id = STM32MP1_SHRES_MCU; - break; - case MDMA_R: -@@ -499,33 +608,81 @@ static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id) - return ETZPC_DECPROT_S_RW; - } - --static void set_etzpc_secure_configuration(void) -+static bool check_decprot(unsigned int id, enum etzpc_decprot_attributes exp) - { -- /* Some system peripherals shall be secure */ -- etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); -- etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); -- etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID, -- ETZPC_DECPROT_NS_R_S_W); -- etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID, -- ETZPC_DECPROT_NS_R_S_W); -- -- /* Configure ETZPC with peripheral registering */ -- etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID, -- shres2decprot_attr(STM32MP1_SHRES_CRYP1)); -- etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID, -- shres2decprot_attr(STM32MP1_SHRES_HASH1)); -- etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID, -- shres2decprot_attr(STM32MP1_SHRES_I2C4)); -- etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID, -- shres2decprot_attr(STM32MP1_SHRES_I2C6)); -- etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID, -- shres2decprot_attr(STM32MP1_SHRES_IWDG1)); -- etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID, -- shres2decprot_attr(STM32MP1_SHRES_RNG1)); -- etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID, -+ enum etzpc_decprot_attributes cur = etzpc_get_decprot(id); -+ -+ if (cur == exp) { -+ return true; -+ } -+ -+ switch (exp) { -+ case ETZPC_DECPROT_NS_RW: -+ if (cur == ETZPC_DECPROT_S_RW) { -+ INFO("ETZPC: %s (%d) could be non secure\n", -+ decprot2str(id), id); -+ } -+ return true; -+ -+ case ETZPC_DECPROT_S_RW: -+ ERROR("ETZPC: %s (%d) expected secure but DECPROT = %d\n", -+ decprot2str(id), id, cur); -+ break; -+ -+ case ETZPC_DECPROT_NS_R_S_W: -+ case ETZPC_DECPROT_MCU_ISOLATION: -+ break; -+ default: -+ panic(); -+ } -+ -+ return false; -+} -+ -+static void check_etzpc_secure_configuration(void) -+{ -+ bool error = false; -+ -+ assert(registering_locked); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_USART1_ID, - shres2decprot_attr(STM32MP1_SHRES_USART1)); -- etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID, -+ -+ error |= !check_decprot(STM32MP1_ETZPC_I2C4_ID, -+ shres2decprot_attr(STM32MP1_SHRES_I2C4)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_SPI6_ID, - shres2decprot_attr(STM32MP1_SHRES_SPI6)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_RNG1_ID, -+ shres2decprot_attr(STM32MP1_SHRES_RNG1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_HASH1_ID, -+ shres2decprot_attr(STM32MP1_SHRES_HASH1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_CRYP1_ID, -+ shres2decprot_attr(STM32MP1_SHRES_CRYP1)); -+ -+ error |= !((check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, -+ ETZPC_DECPROT_NS_R_S_W)) || -+ (check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, -+ ETZPC_DECPROT_S_RW))); -+ -+ error |= !((check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, -+ ETZPC_DECPROT_NS_R_S_W)) || -+ (check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, -+ ETZPC_DECPROT_S_RW))); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_I2C6_ID, -+ shres2decprot_attr(STM32MP1_SHRES_I2C6)); -+ -+ if (error) { -+ panic(); -+ } - } - - static void check_rcc_secure_configuration(void) -@@ -592,6 +749,6 @@ void stm32mp_lock_periph_registering(void) - print_shared_resources_state(); - - check_rcc_secure_configuration(); -- set_etzpc_secure_configuration(); -+ check_etzpc_secure_configuration(); - set_gpio_secure_configuration(); - } -diff --git a/plat/st/stm32mp1/stm32mp1_ssp.c b/plat/st/stm32mp1/stm32mp1_ssp.c -new file mode 100644 -index 0000000000..bcbf374782 ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_ssp.c -@@ -0,0 +1,1039 @@ -+/* -+ * 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 -+ -+#define CERT_CHIP_ID_LEN U(3) -+#define CERT_SECURITY_COUNTER_LEN U(2) -+#define CERT_SECURITY_COUNTER_SHIFT CERT_CHIP_ID_LEN -+#define CERT_RFU_LEN U(1) -+#define CERT_RFU_SHIFT (CERT_SECURITY_COUNTER_LEN + \ -+ CERT_SECURITY_COUNTER_SHIFT) -+#define CERT_PRODUCT_KEY_LEN U(2) -+#define CERT_PRODUCT_KEY_SHIFT (CERT_RFU_LEN + CERT_RFU_SHIFT) -+#define CERT_PRODUCT_ID_SIZE (CERT_PRODUCT_KEY_LEN + \ -+ CERT_PRODUCT_KEY_SHIFT) -+#define CERT_SIGNATURE_LEN CHIP_CERTIFICATE_MAX_SIZE -+#define CERT_SIGNATURE_SHIFT (CERT_PRODUCT_ID_SIZE + \ -+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES) -+#define CERTIFICATE_SIZE (CERT_PRODUCT_ID_SIZE + \ -+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES + \ -+ CERT_SIGNATURE_LEN) /* 136 bytes */ -+#define RESET_TIMEOUT_US_1MS U(1000) -+#define BLOB_FILE_MAX_ADDR BL2_RW_LIMIT -+ -+/* Local status for SSP processing sequences */ -+typedef enum { -+ SSP_NONE, -+ SSP_GET_CERT, -+ SSP_FLASH_OEM, -+ SSP_DONE, -+ SSP_ERROR -+} ssp_result_e; -+ -+struct otp_val { -+ uint32_t idx; -+ uint32_t nb; -+}; -+ -+static struct otp_val otp_ssp; -+static struct otp_val otp_rma; -+static struct otp_val otp_pubkey; -+ -+#if DEBUG -+static console_t console; -+#endif -+ -+/* Platform empty definition required */ -+void bl2_platform_setup(void) {} -+struct bl_params *plat_get_next_bl_params(void) { return NULL; } -+void plat_flush_next_bl_params(void) {} -+struct bl_load_info *plat_get_bl_image_load_info(void) { return NULL; } -+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, -+ uintptr_t *image_spec) -+{ -+ return 0; -+} -+ -+/* -+ * Initialized OTP index from device tree. -+ */ -+static int initialize_otp(void) -+{ -+ uint32_t len; -+ -+ /* OTP SSP */ -+ if (stm32_get_otp_index(SSP_OTP, &otp_ssp.idx, NULL) != 0) { -+ VERBOSE("%s: get index error\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* OTP public key */ -+ if (stm32_get_otp_index(PKH_OTP, &otp_pubkey.idx, &len) != 0) { -+ VERBOSE("%s: get index error\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) { -+ VERBOSE("%s: length Error\n", __func__); -+ return -EINVAL; -+ } -+ -+ otp_pubkey.nb = len / __WORD_BIT; -+ -+ /* OTP RMA */ -+ if (stm32_get_otp_index(RMA_OTP, &otp_rma.idx, NULL) != 0) { -+ VERBOSE("%s: get index error\n", __func__); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Compute HASH from public key and burn it in OTP. -+ */ -+static int ssp_pub_key_prog(boot_api_context_t *boot_context) -+{ -+ uint8_t key_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES] __aligned(4); -+ uint8_t *pubk = (uint8_t *) -+ boot_context->p_ssp_config->p_blob_payload->oem_ecdsa_pubk; -+ uint32_t *value = (uint32_t *)key_hash; -+ uint32_t i; -+ -+ if (stm32_hash_register() != 0) { -+ return -EINVAL; -+ } -+ -+ stm32_hash_init(HASH_SHA256); -+ -+ if (stm32_hash_final_update(pubk, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES, -+ key_hash) != 0) { -+ ERROR("Hash of payload failed\n"); -+ return -EINVAL; -+ } -+ -+ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) { -+ if (bsec_program_otp(bswap32(*value), i) != BSEC_OK) { -+ return -EINVAL; -+ } -+ -+ value++; -+ if (bsec_permanent_lock_otp(i) != BSEC_OK) { -+ ERROR("Error locking OTP %i\n", i); -+ panic(); -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * Burn OTP to close device. -+ */ -+static int ssp_close_device(void) -+{ -+ uint32_t otp; -+ uint32_t value; -+ -+ if (stm32_get_otp_index(CFG0_OTP, &otp, NULL) != 0) { -+ return -EINVAL; -+ } -+ -+ if (bsec_read_otp(&value, otp) != BSEC_OK) { -+ return -EINVAL; -+ } -+ -+ if ((value & CFG0_CLOSED_DEVICE) != 0U) { -+ ERROR("Device already closed\n"); -+ return -EINVAL; -+ } -+ -+ value |= CFG0_CLOSED_DEVICE; -+ if (bsec_program_otp(value, otp) != BSEC_OK) { -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * OTP initial check to detect previous values. -+ */ -+static int ssp_secrets_check(boot_api_context_t *boot_ctx) -+{ -+ uint32_t i; -+ uint32_t check_val; -+ uint32_t otp_bytes = boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes; -+ uint32_t otp_decrypted; -+ -+ if (otp_bytes == 0U) { -+ return -EINVAL; -+ } -+ -+ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) { -+ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) { -+ return -EINVAL; -+ } -+ -+ if (check_val != 0U) { -+ ERROR("OTP %u value already programmed\n", i); -+ return -EINVAL; -+ } -+ } -+ -+ otp_decrypted = round_up(otp_bytes, sizeof(uint32_t)) / sizeof(uint32_t); -+ -+ /* OTP decrypted include RMA password */ -+ if (otp_decrypted > (2U + SSP_OTP_SECRET_END - SSP_OTP_SECRET_BASE)) { -+ return -EINVAL; -+ } -+ -+ /* Check RMA password */ -+ if (stm32_get_otp_value_from_idx(otp_rma.idx, &check_val) != 0) { -+ return -EINVAL; -+ } -+ -+ if (check_val != 0U) { -+ ERROR("OTP %s value already programmed\n", RMA_OTP); -+ return -EINVAL; -+ } -+ -+ /* Check all OTP available */ -+ for (i = SSP_OTP_SECRET_BASE; i < SSP_OTP_SECRET_BASE + otp_decrypted - 1U; i++) { -+ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) { -+ return -EINVAL; -+ } -+ -+ if (check_val != 0U) { -+ ERROR("OTP %u value already programmed\n", i); -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * Burn OTP with the decrypted secret received. -+ */ -+static int ssp_secrets_flash(boot_api_context_t *boot_ctx) -+{ -+ uint32_t i; -+ uint32_t *val; -+ uint32_t otp_bytes = -+ boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes; -+ uint32_t otp_decrypted; -+ uint32_t otp_mask = 0U; -+ -+ if (otp_bytes == 0U) { -+ return -EINVAL; -+ } -+ -+ if (otp_bytes % sizeof(uint32_t) != 0U) { -+ otp_mask = GENMASK_32(((otp_bytes % sizeof(uint32_t)) * -+ sizeof(uint32_t)) - 1, 0); -+ } -+ -+ val = (uint32_t *)boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted; -+ -+ otp_decrypted = round_up(otp_bytes, sizeof(uint32_t)) / sizeof(uint32_t); -+ -+ /* Burn RMA password */ -+ if (bsec_program_otp((*val & RMA_OTP_MASK), otp_rma.idx) != BSEC_OK) { -+ WARN("RMA programing failed\n"); -+ return -EINVAL; -+ } -+ -+ val++; -+ otp_decrypted--; -+ for (i = SSP_OTP_SECRET_BASE; i < (SSP_OTP_SECRET_BASE + otp_decrypted - 1U); i++) { -+ if (*val == 0U) { -+ val++; -+ continue; -+ } -+ -+ if (bsec_program_otp(*val, i) != BSEC_OK) { -+ WARN("Error writing OTP %i\n", i); -+ return -EINVAL; -+ } -+ -+ if (bsec_permanent_lock_otp(i) != BSEC_OK) { -+ WARN("Error locking OTP %i\n", i); -+ return -EINVAL; -+ } -+ -+ val++; -+ } -+ -+ if (*val == 0U) { -+ return 0; -+ } -+ -+ /* Mask the last OTP value if needed */ -+ if (otp_mask != 0U) { -+ *val &= otp_mask; -+ } -+ -+ if (bsec_program_otp(*val, i) != BSEC_OK) { -+ WARN("Error writing OTP %i\n", i); -+ return -EINVAL; -+ } -+ -+ if (bsec_permanent_lock_otp(i) != BSEC_OK) { -+ WARN("Error locking OTP %i\n", i); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Finish SSP processing by fusing OTP SSP success. -+ */ -+static int ssp_finish_process(void) -+{ -+ uint32_t val; -+ -+ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) { -+ return -EINVAL; -+ } -+ -+ if ((val & SSP_OTP_SUCCESS) != 0U) { -+ WARN("Error while configuring OTP\n"); -+ return -EINVAL; -+ } -+ -+ val |= SSP_OTP_SUCCESS; -+ if (bsec_program_otp(val, otp_ssp.idx) != BSEC_OK) { -+ return -EINVAL; -+ } -+ -+ VERBOSE("Write OTP Success\n"); -+ -+ return 0; -+} -+ -+/* -+ * Transform integer to string. -+ */ -+static void itoa(uint32_t num, char *str, int nb) -+{ -+ if (num == 0U) { -+ while (nb-- != 0U) { -+ str[nb] = '0'; -+ } -+ -+ return; -+ } -+ -+ while (num != 0U) { -+ int rem = num % 16; -+ -+ str[--nb] = (rem > 9) ? (rem - 10) + 'A' : rem + '0'; -+ num /= 16; -+ } -+ -+ while (nb != 0) { -+ str[--nb] = '0'; -+ } -+} -+ -+/* -+ * Return chip product ID. -+ */ -+static int ssp_get_product_id(char *msg) -+{ -+ uint32_t otp; -+ uint32_t otp_idx; -+ uint32_t chip_id; -+ -+ if (stm32_get_otp_index(CFG2_OTP, &otp_idx, NULL) != 0) { -+ VERBOSE("Get index error\n"); -+ return -EINVAL; -+ } -+ -+ if (stm32_get_otp_value_from_idx(otp_idx, &otp) != 0) { -+ return -EINVAL; -+ } -+ -+ if (stm32mp1_dbgmcu_get_chip_dev_id(&chip_id) < 0) { -+ return -EINVAL; -+ } -+ -+ itoa(chip_id, msg, CERT_CHIP_ID_LEN); -+ itoa((otp & OTP_CFG2_SEC_COUNTER_MASK) >> OTP_CFG2_SEC_COUNTER_SHIFT, -+ msg + CERT_SECURITY_COUNTER_SHIFT, -+ CERT_SECURITY_COUNTER_LEN); -+ -+ itoa(0, msg + CERT_RFU_SHIFT, CERT_RFU_LEN); -+ itoa((otp & OTP_CFG2_ST_KEY_MASK) >> OTP_CFG2_ST_KEY_SHIFT, -+ msg + CERT_PRODUCT_KEY_SHIFT, -+ CERT_PRODUCT_KEY_LEN); -+ -+ return 0; -+} -+ -+/* -+ * Construct SSP certificate. -+ */ -+static int prepare_certificate(uint8_t *cert, const uint8_t *pubkey) -+{ -+ uint32_t i; -+ uint32_t j; -+ uint32_t otp; -+ uint32_t otp_idx; -+ uint32_t otp_len; -+ -+ /* Prepare the ROM Security constant */ -+ if (ssp_get_product_id((char *)cert) != 0) { -+ return -EINVAL; -+ } -+ -+ /* Prepare public key and certificate for flashloader */ -+ /* Read Public Key from boot_context */ -+ memcpy(cert + CERT_PRODUCT_ID_SIZE, pubkey, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); -+ -+ if (stm32_get_otp_index(CHIP_CERTIFICATE_OTP, -+ &otp_idx, &otp_len) != 0) { -+ VERBOSE("Get index error\n"); -+ return -EINVAL; -+ } -+ -+ if (otp_len != (CHAR_BIT * CHIP_CERTIFICATE_MAX_SIZE)) { -+ VERBOSE("Length error\n"); -+ return -EINVAL; -+ } -+ -+ otp_len /= __WORD_BIT; -+ -+ /* Read Certificat from OTP */ -+ for (i = otp_idx, j = 0U; i < (otp_idx + otp_len); i++, j++) { -+ uint32_t otp_s; -+ -+ if (stm32_get_otp_value_from_idx(i, &otp) != 0) { -+ return -EINVAL; -+ } -+ -+ otp_s = bswap32(otp); -+ memcpy(&cert[CERT_SIGNATURE_SHIFT + (sizeof(uint32_t) * j)], -+ &otp_s, sizeof(uint32_t)); -+ } -+ -+ return 0; -+} -+ -+/* -+ * Clean external data and bootrom context secret values. -+ */ -+static void ssp_cleanup(boot_api_context_t *boot_context) -+{ -+ boot_api_ssp_config_t *ssp_config = boot_context->p_ssp_config; -+ -+ /* Cleanup boot_context */ -+ if (ssp_config->p_ssp_oem_secrets_decrypted != NULL) { -+ zeromem(ssp_config->p_ssp_oem_secrets_decrypted, -+ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES); -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)ssp_config->p_ssp_oem_secrets_decrypted, -+ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES); -+#endif -+ ssp_config->p_ssp_oem_secrets_decrypted = NULL; -+ } -+ -+ if (ssp_config->p_chip_pubk != NULL) { -+ zeromem(ssp_config->p_chip_pubk, -+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)ssp_config->p_chip_pubk, -+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); -+#endif -+ ssp_config->p_chip_pubk = NULL; -+ } -+ -+ if (ssp_config->p_blob_license != NULL) { -+ zeromem(ssp_config->p_blob_license, -+ sizeof(boot_api_ssp_blob_license_t)); -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)ssp_config->p_blob_license, -+ sizeof(boot_api_ssp_blob_license_t)); -+#endif -+ ssp_config->p_blob_license = NULL; -+ } -+ -+ if (ssp_config->p_blob_payload != NULL) { -+ zeromem(ssp_config->p_blob_payload, -+ sizeof(boot_api_ssp_blob_payload_t)); -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)ssp_config->p_blob_payload, -+ sizeof(boot_api_ssp_blob_payload_t)); -+#endif -+ ssp_config->p_blob_payload = NULL; -+ } -+ -+ ssp_config->ssp_cmd = 0U; -+ -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, -+ sizeof(boot_api_ssp_config_t)); -+#endif -+} -+ -+/* -+ * Send certificate to the programmer and retrieve the associated -+ * encrypted file. -+ */ -+static int ssp_download_phase(boot_api_context_t *boot_ctx) -+{ -+ uint8_t *blob_file; -+#if STM32MP_USB_PROGRAMMER -+ usb_handle_t *pdev; -+#endif -+#if STM32MP_UART_PROGRAMMER -+ uintptr_t uart_base; -+#endif -+ int result = 0; -+ uint8_t cert[CERTIFICATE_SIZE]; -+ -+ blob_file = (uint8_t *)page_align(BLOB_FILE_MAX_ADDR - -+ sizeof(boot_api_ssp_blob_license_t) - -+ sizeof(boot_api_ssp_blob_payload_t), -+ DOWN); -+ -+ if (prepare_certificate(cert, boot_ctx->p_ssp_config->p_chip_pubk) != 0) { -+ return -EINVAL; -+ } -+ -+ switch (boot_ctx->boot_interface_selected) { -+#if STM32MP_USB_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ -+ /* init USB on platform */ -+ pdev = usb_dfu_plat_init(); -+ -+ result = stm32cubeprog_usb_ssp(pdev, (uintptr_t)cert, -+ sizeof(cert), (uintptr_t)blob_file, -+ sizeof(boot_api_ssp_blob_license_t) + -+ sizeof(boot_api_ssp_blob_payload_t)); -+ if (result != 0) { -+ return -EINVAL; -+ } -+ -+ break; -+#endif -+ -+#if STM32MP_UART_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ uart_base = get_uart_address(boot_ctx->boot_interface_instance); -+ -+ if (uart_base == 0U) { -+ return -EINVAL; -+ } -+ -+ result = stm32cubeprog_uart_ssp(uart_base, (uintptr_t)cert, sizeof(cert), -+ (uintptr_t)blob_file, -+ sizeof(boot_api_ssp_blob_license_t) + -+ sizeof(boot_api_ssp_blob_payload_t)); -+ if (result != 0) { -+ return -EINVAL; -+ } -+ break; -+#endif -+ default: -+ return -EINVAL; -+ } -+ -+ boot_ctx->p_ssp_config->p_blob_license = -+ (boot_api_ssp_blob_license_t *)blob_file; -+ -+ /* Payload is concatened with license file */ -+ boot_ctx->p_ssp_config->p_blob_payload = -+ (boot_api_ssp_blob_payload_t *)(blob_file + -+ sizeof(boot_api_ssp_blob_license_t)); -+ -+#ifndef DCACHE_OFF -+ flush_dcache_range((uintptr_t)blob_file, -+ sizeof(boot_api_ssp_blob_license_t) + -+ sizeof(boot_api_ssp_blob_payload_t)); -+#endif -+ -+ /* Set return address for decrypted_secrets */ -+ boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted = -+ boot_ctx->p_ssp_config->p_blob_payload->oem_encrypted_secrets; -+ -+ return result; -+} -+ -+/* -+ * Burn decrypted secrets into OTP, clean memory and close the device. -+ */ -+static int ssp_secret_programming(boot_api_context_t *boot_context) -+{ -+ int result; -+ -+ result = ssp_secrets_check(boot_context); -+ if (result != 0) { -+ ERROR("SSP ERROR checking OTP\n"); -+ goto clean; -+ } -+ -+ result = ssp_pub_key_prog(boot_context); -+ if (result != 0) { -+ ERROR("SSP ERROR writing HASH key\n"); -+ goto clean; -+ } -+ -+ result = ssp_close_device(); -+ if (result != 0) { -+ ERROR("SSP close device failed\n"); -+ goto clean; -+ } -+ -+ result = ssp_secrets_flash(boot_context); -+ if (result != 0) { -+ ERROR("SSP Secret flash failed\n"); -+ } -+ -+clean: -+ ssp_cleanup(boot_context); -+ -+ if (result != 0) { -+ return result; -+ } -+ -+ return ssp_finish_process(); -+} -+ -+/* -+ * Enable the SSP processing. -+ */ -+static int ssp_enable_processing(boot_api_context_t *boot_context) -+{ -+ uint32_t val; -+ int result; -+#if STM32MP_USB_PROGRAMMER -+ usb_handle_t *pdev; -+#endif -+#if STM32MP_UART_PROGRAMMER -+ uintptr_t uart_base; -+#endif -+ -+ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) { -+ return -EINVAL; -+ } -+ -+ if (((val & SSP_OTP_MASK) == SSP_OTP_MASK) || -+ ((val & SSP_OTP_MASK) == SSP_OTP_SUCCESS)) { -+ return -EINVAL; -+ } -+ -+ if ((val & SSP_OTP_MASK) == 0U) { -+ if (bsec_program_otp(SSP_OTP_REQ, otp_ssp.idx) != BSEC_OK) { -+ return -EINVAL; -+ } -+ } -+ -+ switch (boot_context->boot_interface_selected) { -+#if STM32MP_USB_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: -+ /* init USB on platform */ -+ pdev = usb_dfu_plat_init(); -+ -+ result = stm32cubeprog_usb_ssp(pdev, (uintptr_t)-1, 0, -+ (uintptr_t)NULL, 0); -+ if (result != 0) { -+ return -EINVAL; -+ } -+ -+ break; -+#endif -+ -+#if STM32MP_UART_PROGRAMMER -+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: -+ uart_base = get_uart_address(boot_context->boot_interface_instance); -+ if (uart_base == 0U) { -+ return -EINVAL; -+ } -+ -+ result = stm32cubeprog_uart_ssp(uart_base, (uintptr_t)-1, 0, -+ (uintptr_t)NULL, 0); -+ if (result != 0) { -+ return -EINVAL; -+ } -+ break; -+#endif -+ default: -+ return -EINVAL; -+ } -+ -+ boot_context->p_ssp_config->ssp_cmd = -+ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK; -+ -+ return 0; -+} -+ -+/* -+ * Retrieve the current status of the SSP from bootrom context and OTP value. -+ */ -+static ssp_result_e ssp_check_status(boot_api_context_t *boot_context) -+{ -+ uint32_t otp; -+ -+ if (initialize_otp() < 0) { -+ return SSP_ERROR; -+ } -+ -+ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &otp) != 0) { -+ return SSP_ERROR; -+ } -+ -+ if ((otp & SSP_OTP_REQ) == 0U) { -+ return SSP_NONE; -+ } -+ -+ if ((otp & SSP_OTP_SUCCESS) != 0U) { -+ return SSP_DONE; -+ } -+ -+ VERBOSE("Start Get ssp_cmd : %x\n", -+ boot_context->p_ssp_config->ssp_cmd); -+ -+ switch (boot_context->p_ssp_config->ssp_cmd) { -+ case BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK: -+ INFO("Detected start SSP Phase 2\n"); -+ return SSP_GET_CERT; -+ case BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK: -+ INFO("Detected start SSP Phase 3\n"); -+ return SSP_FLASH_OEM; -+ default: -+ return SSP_NONE; -+ } -+} -+ -+/* -+ * Start the SSP processing. -+ */ -+static void ssp_start(boot_api_context_t *boot_context) -+{ -+ int result; -+ uint8_t ssp_phase = ssp_check_status(boot_context); -+ -+ switch (ssp_phase) { -+ case SSP_GET_CERT: -+ result = ssp_download_phase(boot_context); -+ if (result != 0) { -+ /* -+ * Download Phase failed, clean, reset -+ */ -+ ssp_cleanup(boot_context); -+ -+ ERROR("SSP_Error: Resetting target\n"); -+ } else { -+ /* Process completed, go to Phase 3 */ -+ boot_context->p_ssp_config->ssp_cmd = -+ BOOT_API_CTX_SSP_CMD_PROV_SECRET; -+ } -+ -+ break; -+ -+ case SSP_FLASH_OEM: -+ result = ssp_secret_programming(boot_context); -+ if (result != 0) { -+ ERROR("Error during provisionning\n"); -+ } else { -+ NOTICE("Provisioning completed\n"); -+ } -+ -+ break; -+ -+ case SSP_ERROR: -+ /* -+ * Error during bootrom SSP processing -+ */ -+ result = -EINVAL; -+ ERROR("SSP_Error: Resetting target\n"); -+ break; -+ -+ case SSP_NONE: -+ default: -+ result = ssp_enable_processing(boot_context); -+ if (result != 0) { -+ ERROR("Start SSP Failed (%i)\n", result); -+ } -+ } -+ -+ if ((result != 0) || (ssp_phase == SSP_FLASH_OEM)) { -+ goto out; -+ } -+ -+ /* -+ * Keep VDDCORE && VDD enabled if pmic used to generate -+ * the required MPSYSRST. -+ */ -+ if (dt_pmic_status() > 0) { -+ const char *name; -+ -+ name = stm32mp_get_cpu_supply_name(); -+ if (name == NULL) { -+ goto out; -+ } -+ -+ if (stpmic1_regulator_mask_reset_set(name) != 0) { -+ WARN("Failed to write %s reset mask\n", name); -+ } -+ -+ name = stm32mp_get_vdd_supply_name(); -+ if (name == NULL) { -+ goto out; -+ } -+ -+ if (stpmic1_regulator_mask_reset_set(name) != 0) { -+ WARN("Failed to write %s reset mask\n", name); -+ } -+ } else { -+ static const char debug_msg[] = { -+ "SSP next step will be only guarantee if the VDD\n" -+ "domain is maintained during system reset\n" -+ }; -+ -+ NOTICE("%s", debug_msg); -+ } -+ -+out: -+#ifndef DCACHE_OFF -+ if (boot_context->p_ssp_config != NULL) { -+ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, -+ sizeof(boot_api_ssp_config_t)); -+ } -+#endif -+ -+ stm32mp_system_reset(); -+} -+ -+#if DEBUG -+static void reset_uart(uint32_t reset) -+{ -+ int ret; -+ -+ ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ -+ udelay(2); -+ -+ ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS); -+ if (ret != 0) { -+ panic(); -+ } -+ -+ mdelay(1); -+} -+#endif -+ -+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_el3_plat_arch_setup(void) -+{ -+#if DEBUG -+ int32_t result; -+ struct dt_node_info dt_uart_info; -+ const char *board_model; -+ uint32_t clk_rate; -+#endif -+ uintptr_t pwr_base; -+ uintptr_t rcc_base; -+ -+ boot_api_context_t *boot_context = -+ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); -+ bool serial_uart_interface __unused = -+ (boot_context->boot_interface_selected == -+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART); -+ uintptr_t uart_prog_addr __unused; -+ -+ if (bsec_probe() != 0) { -+ panic(); -+ } -+ -+ 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_END - BL_RO_DATA_BASE, -+ MT_RO_DATA | MT_SECURE); -+#endif -+ -+ /* Prevent corruption of preloaded Device Tree */ -+ mmap_add_region(DTB_BASE, DTB_BASE, -+ DTB_LIMIT - DTB_BASE, -+ MT_RO_DATA | MT_SECURE); -+ -+ configure_mmu(); -+ -+ if (dt_open_and_check(STM32MP_DTB_BASE) < 0) { -+ panic(); -+ } -+ -+ pwr_base = stm32mp_pwr_base(); -+ rcc_base = stm32mp_rcc_base(); -+ -+ /* -+ * 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); -+ -+ while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) { -+ ; -+ } -+ -+ /* 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); -+ -+ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) == -+ 0U) { -+ ; -+ } -+ -+ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); -+ } -+ -+ -+ generic_delay_timer_init(); -+ -+#if STM32MP_UART_PROGRAMMER -+ uart_prog_addr = get_uart_address(boot_context->boot_interface_instance); -+ -+ /* Disable programmer UART before changing clock tree */ -+ if (serial_uart_interface) { -+ stm32_uart_stop(uart_prog_addr); -+ } -+#endif -+ -+ if (stm32mp1_clk_probe() < 0) { -+ panic(); -+ } -+ -+ if (dt_pmic_status() > 0) { -+ initialize_pmic(); -+ } -+ -+#if DEBUG -+ result = dt_get_stdout_uart_info(&dt_uart_info); -+ -+ if ((result <= 0) || -+ (dt_uart_info.status == DT_DISABLED) || -+#if STM32MP_UART_PROGRAMMER -+ (serial_uart_interface && -+ (uart_prog_addr == dt_uart_info.base)) || -+#endif -+ (dt_uart_info.clock < 0) || -+ (dt_uart_info.reset < 0)) { -+ goto skip_console_init; -+ } -+ -+ if (dt_set_stdout_pinctrl() != 0) { -+ goto skip_console_init; -+ } -+ -+ if (dt_uart_info.status == DT_DISABLED) { -+ panic(); -+ } -+ -+ clk_enable((unsigned long)dt_uart_info.clock); -+ -+ reset_uart((uint32_t)dt_uart_info.reset); -+ -+ clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock); -+ -+ if (console_stm32_register(dt_uart_info.base, clk_rate, -+ STM32MP_UART_BAUDRATE, &console) == 0) { -+ panic(); -+ } -+ -+ console_set_scope(&console, CONSOLE_FLAG_BOOT | -+ CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF); -+ -+ stm32mp_print_cpuinfo(); -+ -+ board_model = dt_get_board_model(); -+ if (board_model != NULL) { -+ NOTICE("Model: %s\n", board_model); -+ } -+ -+ if ((boot_context->p_ssp_config == NULL) || -+ (boot_context->p_ssp_config->ssp_cmd != -+ BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK)) { -+ stm32mp_print_cpuinfo(); -+ if (!stm32mp_is_auth_supported()) { -+ ERROR("Chip doesn't support SSP\n"); -+ panic(); -+ } -+ } -+ -+skip_console_init: -+#endif -+ if (stm32mp_is_closed_device()) { -+ /* Closed chip required authentication */ -+ ERROR("SSP not supported on closed chip\n"); -+ panic(); -+ } -+ -+ if (stm32_iwdg_init() < 0) { -+ panic(); -+ } -+ -+ stm32_iwdg_refresh(); -+ -+ if (dt_pmic_status() > 0) { -+ initialize_pmic(); -+ print_pmic_info_and_debug(); -+ } -+ -+ ssp_start(boot_context); -+ -+ /* This must not be reached */ -+ panic(); -+} -diff --git a/plat/st/stm32mp1/stm32mp1_ssp.mk b/plat/st/stm32mp1/stm32mp1_ssp.mk -new file mode 100644 -index 0000000000..9041e6a032 ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_ssp.mk -@@ -0,0 +1,84 @@ -+# -+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. -+# -+# SPDX-License-Identifier: BSD-3-Clause -+# -+ -+ST_VERSION := r1.0-ssp -+VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} -+ -+# Required to use BL2_IN_XIP_MEM -+BL2_IN_XIP_MEM := 1 -+ -+SEPARATE_CODE_AND_RODATA := 1 -+ -+TRUSTED_BOARD_BOOT := 0 -+ -+# Macros and rules to build TF-A binary -+STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-ssp-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME))) -+ -+PLAT_BL_COMMON_SOURCES := common/fdt_wrappers.c \ -+ plat/st/common/stm32mp_common.c \ -+ plat/st/stm32mp1/stm32mp1_private.c -+ -+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} -+ -+PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S -+ -+PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S -+ -+PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ -+ drivers/clk/clk.c \ -+ drivers/delay_timer/delay_timer.c \ -+ drivers/delay_timer/generic_delay_timer.c \ -+ drivers/st/bsec/bsec2.c \ -+ drivers/st/clk/stm32mp_clkfunc.c \ -+ drivers/st/gpio/stm32_gpio.c \ -+ drivers/st/i2c/stm32_i2c.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_shres_helpers.c \ -+ plat/st/stm32mp1/stm32mp1_dbgmcu.c \ -+ plat/st/stm32mp1/stm32mp1_helper.S \ -+ plat/st/stm32mp1/stm32mp1_syscfg.c -+ -+PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c -+ -+BL2_SOURCES := drivers/io/io_storage.c \ -+ drivers/st/crypto/stm32_hash.c \ -+ plat/st/stm32mp1/stm32mp1_ssp.c -+ -+ifeq (${STM32MP_UART_PROGRAMMER},1) -+BL2_SOURCES += drivers/st/uart/stm32_uart.c \ -+ plat/st/common/stm32cubeprogrammer_uart.c -+endif -+ -+ifeq (${STM32MP_USB_PROGRAMMER},1) -+BL2_SOURCES += drivers/st/usb_dwc2/usb_dwc2.c \ -+ lib/usb/usb_core.c \ -+ lib/usb/usb_st_dfu.c \ -+ plat/st/common/stm32cubeprogrammer_usb.c \ -+ plat/st/stm32mp1/stm32mp1_usb.c -+endif -+ -+BL2_DTSI := stm32mp15-ssp-bl2.dtsi -+ -+check_boot_ssp: -+ @if ([ ${STM32MP_UART_PROGRAMMER} = 1 ] && [ ${STM32MP_USB_PROGRAMMER} = 1 ]) || \ -+ ([ ${STM32MP_UART_PROGRAMMER} = 0 ] && [ ${STM32MP_USB_PROGRAMMER} = 0 ]); then \ -+ echo "Error selecting serial boot device"; \ -+ false; \ -+ fi -+ -+bl2: check_boot_ssp -+ -+${BUILD_PLAT}/stm32mp1-ssp-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2 -+ @echo " SSP AS stm32mp1.S" -+ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ -+ -DDTB_BIN_PATH=\"$<\" \ -+ -c plat/st/stm32mp1/stm32mp1.S -o $@ -diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c -index 109725c8ac..2c5fa082fc 100644 ---- a/plat/st/stm32mp1/stm32mp1_syscfg.c -+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c -@@ -7,21 +7,24 @@ - #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 - #define SYSCFG_ICNR 0x1CU - #define SYSCFG_CMPCR 0x20U - #define SYSCFG_CMPENSETR 0x24U -+#define SYSCFG_CMPENCLRR 0x28U - - /* - * SYSCFG_BOOTR Register -@@ -53,6 +56,8 @@ - #define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) - #define SYSCFG_CMPCR_ANSRC_SHIFT 24 - -+#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U -+ - /* - * SYSCFG_CMPENSETR Register - */ -@@ -61,8 +66,9 @@ - void stm32mp1_syscfg_init(void) - { - uint32_t bootr; -- uint32_t otp = 0; -+ uint32_t otp_value; - uint32_t vdd_voltage; -+ bool product_below_2v5; - - /* - * Interconnect update : select master using the port 1. -@@ -91,18 +97,18 @@ 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(); - - /* Check if VDD is Low Voltage */ - if (vdd_voltage == 0U) { -- WARN("VDD unknown"); -+ WARN("VDD unknown\n"); - } else if (vdd_voltage < 2700000U) { - mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR, - SYSCFG_IOCTRLSETR_HSLVEN_TRACE | -@@ -111,11 +117,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:\n"); - ERROR("\tHSLVEN update is destructive,\n"); - ERROR("\tno update as VDD > 2.7V\n"); -@@ -123,24 +129,38 @@ void stm32mp1_syscfg_init(void) - } - } - -- stm32mp1_syscfg_enable_io_compensation(); -+ stm32mp1_syscfg_enable_io_compensation_start(); - } - --void stm32mp1_syscfg_enable_io_compensation(void) -+void stm32mp1_syscfg_enable_io_compensation_start(void) - { - /* - * 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, - SYSCFG_CMPENSETR_MPU_EN); -+} -+ -+void stm32mp1_syscfg_enable_io_compensation_finish(void) -+{ -+ uint64_t start; -+ -+ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); - - 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; -+ } - } - - mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); -@@ -150,6 +170,8 @@ void stm32mp1_syscfg_disable_io_compensation(void) - { - uint32_t value; - -+ stm32mp1_clk_force_enable(SYSCFG); -+ - /* - * Deactivate automatic I/O compensation. - * Warning: CSI is disabled automatically in STOP if not -@@ -167,8 +189,7 @@ void stm32mp1_syscfg_disable_io_compensation(void) - - mmio_write_32(SYSCFG_BASE + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); - -- mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPENSETR, -- SYSCFG_CMPENSETR_MPU_EN); -+ mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENCLRR, SYSCFG_CMPENSETR_MPU_EN); - -- stm32mp1_clk_disable_non_secure(SYSCFG); -+ stm32mp1_clk_force_disable(SYSCFG); - } -diff --git a/plat/st/stm32mp1/stm32mp1_usb.c b/plat/st/stm32mp1/stm32mp1_usb.c -new file mode 100644 -index 0000000000..c63db4a2ff ---- /dev/null -+++ b/plat/st/stm32mp1/stm32mp1_usb.c -@@ -0,0 +1,491 @@ -+/* -+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* String size (1 byte) + type (1 byte) + 24 UTF16 characters */ -+/* (2 bytes per character) */ -+#define USB_SIZ_STRING_SERIAL (1 + 1 + (24 * 2)) -+#define USBD_MAX_STR_DESC_SIZ 0x100 -+#define USBD_VID 0x0483 -+#define USBD_PID 0xDF11 -+#define USBD_LANGID_STRING 0x409 -+#define USBD_MANUFACTURER_STRING "STMicroelectronics" -+#define USBD_CONFIGURATION_STRING "DFU Config" -+#define USBD_INTERFACE_STRING "DFU Interface" -+ -+#define USB_DFU_ITF_NUM 6 -+ -+#define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM) -+ -+/* DFU devices */ -+static usb_dfu_handle_t usb_dfu_handle; -+ -+/* USB Standard Device Descriptor */ -+static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = { -+ USB_LEN_DEV_DESC, /* bLength */ -+ USB_DESC_TYPE_DEVICE, /* bDescriptorType */ -+ 0x00, /* bcdUSB */ -+ 0x02, /* version */ -+ 0x00, /* bDeviceClass */ -+ 0x00, /* bDeviceSubClass */ -+ 0x00, /* bDeviceProtocol */ -+ USB_MAX_EP0_SIZE, /* bMaxPacketSize */ -+ LOBYTE(USBD_VID), /* idVendor */ -+ HIBYTE(USBD_VID), /* idVendor */ -+ LOBYTE(USBD_PID), /* idVendor */ -+ HIBYTE(USBD_PID), /* idVendor */ -+ 0x00, /* bcdDevice rel. 2.00 */ -+ 0x02, -+ USBD_IDX_MFC_STR, /* Index of manufacturer string */ -+ USBD_IDX_PRODUCT_STR, /* Index of product string */ -+ USBD_IDX_SERIAL_STR, /* Index of serial number string */ -+ USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */ -+}; /* USB_DeviceDescriptor */ -+ -+/* USB Standard String Descriptor */ -+static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = { -+ USB_LEN_LANGID_STR_DESC, -+ USB_DESC_TYPE_STRING, -+ LOBYTE(USBD_LANGID_STRING), -+ HIBYTE(USBD_LANGID_STRING), -+}; -+ -+/* USB Standard Device Descriptor */ -+static const uint8_t -+usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = { -+ USB_LEN_DEV_QUALIFIER_DESC, -+ USB_DESC_TYPE_DEVICE_QUALIFIER, -+ 0x00, -+ 0x02, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x40, -+ 0x01, -+ 0x00, -+}; -+ -+static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1] = { -+ USB_SIZ_STRING_SERIAL, -+ USB_DESC_TYPE_STRING, -+}; -+ -+/* USB DFU device Configuration Descriptor */ -+static uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = { -+ 0x09, /* bLength: Configuration Descriptor size */ -+ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ -+ USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ -+ 0x00, -+ 0x01, /* bNumInterfaces: 1 interface */ -+ 0x01, /* bConfigurationValue: Configuration value */ -+ 0x02, /* iConfiguration: Index of string descriptor -+ * describing the configuration -+ */ -+ 0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */ -+ 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ -+ /* 09 */ -+ -+ /* Descriptor of DFU interface 0 Alternate setting 0..N */ -+ USBD_DFU_IF_DESC(0), -+ USBD_DFU_IF_DESC(1), -+ USBD_DFU_IF_DESC(2), -+#if USB_DFU_ITF_NUM > 3 -+ USBD_DFU_IF_DESC(3), -+ USBD_DFU_IF_DESC(4), -+ USBD_DFU_IF_DESC(5), -+#endif -+ /* DFU Functional Descriptor */ -+ 0x09, /* blength = 9 Bytes */ -+ DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */ -+ DFU_BM_ATTRIBUTE, /* bmAttribute -+ * bitCanDnload = 1 (bit 0) -+ * bitCanUpload = 1 (bit 1) -+ * bitManifestationTolerant = 1 (bit 2) -+ * bitWillDetach = 1 (bit 3) -+ * Reserved (bit4-6) -+ * bitAcceleratedST = 0 (bit 7) -+ */ -+ 0xFF, /* DetachTimeOut = 255 ms */ -+ 0x00, -+ /* WARNING: In DMA mode the multiple MPS packets feature -+ * is still not supported ==> In this case, -+ * when using DMA USBD_DFU_XFER_SIZE should be set -+ * to 64 in usbd_conf.h -+ */ -+ TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */ -+ ((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */ -+ ((USB_DFU_VERSION >> 8) & 0xFF) -+}; -+ -+static uint8_t usb_local_string_dec[USBD_MAX_STR_DESC_SIZ]; -+ -+/* -+ * Convert Hex 32Bits value into char -+ * value: value to convert -+ * pbuf: pointer to the buffer -+ * len: buffer length -+ */ -+static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) -+{ -+ uint8_t idx; -+ -+ for (idx = 0U; idx < len; idx++) { -+ if (((value >> 28)) < 0xA) { -+ pbuf[2U * idx] = (value >> 28) + '0'; -+ } else { -+ pbuf[2U * idx] = (value >> 28) + 'A' - 10U; -+ } -+ value = value << 4; -+ pbuf[(2U * idx) + 1U] = 0U; -+ } -+} -+ -+/* -+ * Convert Hex 32Bits value into string with a fixed length (as sprintf %0X) -+ * value: value to convert -+ * pstr: pointer to the string -+ * len: buffer length -+ */ -+static void int_to_str(uint32_t value, uint8_t *pstr, uint8_t len) -+{ -+ uint8_t idx, v; -+ -+ if (len > 9U) { -+ len = 9U; -+ } -+ -+ for (idx = 0U; idx < len - 1U; idx++) { -+ v = (value >> (4U * (len - 2U - idx))) & 0xFU; -+ if (v < 0xAU) { -+ pstr[idx] = '0' + v; -+ } else { -+ pstr[idx] = 'A' + v - 0xAU; -+ } -+ } -+ pstr[len - 1] = 0U; -+} -+ -+/* -+ * Create the serial number string descriptor -+ */ -+static void update_serial_num_string(void) -+{ -+ uint8_t i; -+ /* serial number is set to 0 */ -+ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U}; -+ uint32_t otp; -+ uint32_t len; -+ -+ 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; -+ } -+ } -+ -+ int_to_unicode(deviceserial[0], (uint8_t *)&usb_stm32mp1_serial[2], 8); -+ int_to_unicode(deviceserial[1], (uint8_t *)&usb_stm32mp1_serial[18], 8); -+ int_to_unicode(deviceserial[2], (uint8_t *)&usb_stm32mp1_serial[34], 8); -+} -+ -+/* -+ * usb_get_qualifier_desc -+ * return Device Qualifier descriptor -+ * param : length : pointer data length -+ * return : pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length) -+{ -+ *length = sizeof(usbd_stm32mp1_qualifier_desc); -+ -+ return (uint8_t *)usbd_stm32mp1_qualifier_desc; -+} -+ -+/* -+ * stm32mp1_get_config_desc -+ * return configuration descriptor -+ * param : speed : current device speed -+ * param : length : pointer data length -+ * return : pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_get_config_desc(uint16_t *length) -+{ -+ *length = sizeof(usb_stm32mp1_config_desc); -+ -+ return (uint8_t *)usb_stm32mp1_config_desc; -+} -+ -+/* -+ * stm32mp1_get_string -+ * Convert Ascii string into unicode one -+ * param : desc : descriptor buffer -+ * param : unicode : Formatted string buffer (unicode) -+ * param : len : descriptor length -+ * return : None -+ */ -+static void stm32mp1_get_string(uint8_t *desc, uint8_t *unicode, uint16_t *len) -+{ -+ uint8_t idx = 0; -+ -+ if (desc == NULL) { -+ return; -+ } -+ -+ *len = strlen((char *)desc) * 2 + 2; -+ unicode[idx++] = *len; -+ unicode[idx++] = USB_DESC_TYPE_STRING; -+ -+ while (*desc != '\0') { -+ unicode[idx++] = *desc++; -+ unicode[idx++] = 0x00; -+ } -+} -+ -+/* -+ * stm32mp1_device_desc -+ * Returns the device descriptor. -+ * length: Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_device_desc(uint16_t *length) -+{ -+ *length = sizeof(usb_stm32mp1_desc); -+ -+ return (uint8_t *)usb_stm32mp1_desc; -+} -+ -+/* -+ * stm32mp1_lang_id_desc -+ * Returns the LangID string descriptor. -+ * speed: Current device speed -+ * length: Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_lang_id_desc(uint16_t *length) -+{ -+ *length = sizeof(usb_stm32mp1_lang_id_desc); -+ -+ return (uint8_t *)usb_stm32mp1_lang_id_desc; -+} -+ -+/* -+ * stm32mp1_product_desc -+ * Returns the product string descriptor. -+ * length: Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_product_desc(uint16_t *length) -+{ -+ char name[STM32_SOC_NAME_SIZE]; -+ char product[128]; -+ uint32_t chip_version; -+ char str_chip_id[4]; -+ char str_chip_version[5]; -+ -+ stm32mp_get_soc_name(name); -+ stm32mp_get_chip_version(&chip_version); -+ -+ int_to_str(STM32MP1_CHIP_ID, (uint8_t *)str_chip_id, 4); -+ int_to_str(chip_version, (uint8_t *)str_chip_version, 5); -+ snprintf(product, sizeof(product), -+ "DFU @Device ID /0x%s, @Revision ID /0x%s, @Name /%s,", -+ str_chip_id, str_chip_version, name); -+ -+ stm32mp1_get_string((uint8_t *)product, usb_local_string_dec, length); -+ -+ return usb_local_string_dec; -+} -+ -+/* -+ * stm32mp1_manufacturer_desc -+ * Returns the manufacturer string descriptor. -+ * length: Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length) -+{ -+ stm32mp1_get_string((uint8_t *)USBD_MANUFACTURER_STRING, -+ usb_local_string_dec, length); -+ -+ return usb_local_string_dec; -+} -+ -+/* -+ * stm32mp1_serial_desc -+ * Returns the serial number string descriptor. -+ * length: Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_serial_desc(uint16_t *length) -+{ -+ *length = USB_SIZ_STRING_SERIAL; -+ -+ /* Update the serial number string descriptor -+ * with the data from the unique ID -+ */ -+ update_serial_num_string(); -+ -+ return (uint8_t *)usb_stm32mp1_serial; -+} -+ -+/* -+ * stm32mp1_Config_desc -+ * Returns the configuration string descriptor. -+ * length: Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_config_desc(uint16_t *length) -+{ -+ stm32mp1_get_string((uint8_t *)USBD_CONFIGURATION_STRING, -+ usb_local_string_dec, length); -+ -+ return usb_local_string_dec; -+} -+ -+/* -+ * stm32mp1_interface_desc -+ * Returns the interface string descriptor. -+ * length : Pointer to data length variable -+ * return : Pointer to descriptor buffer -+ */ -+static uint8_t *stm32mp1_interface_desc(uint16_t *length) -+{ -+ stm32mp1_get_string((uint8_t *)USBD_INTERFACE_STRING, -+ usb_local_string_dec, length); -+ -+ return usb_local_string_dec; -+} -+ -+/* -+ * stm32mp1_get_usr_desc -+ * Manages the transfer of memory interfaces string descriptors. -+ * param : index: descriptor index -+ * param : length : pointer data length -+ * return : pointer to the descriptor table or NULL if the descriptor -+ * is not supported. -+ */ -+static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length) -+{ -+ uint8_t *ret; -+ -+ switch (index) { -+ case 0: -+ stm32mp1_get_string((uint8_t *)"@Partition0 /0x00/1*256Ke", -+ usb_local_string_dec, length); -+ ret = usb_local_string_dec; -+ break; -+ case 1: -+ stm32mp1_get_string((uint8_t *)"@FSBL /0x01/1*1Me", -+ usb_local_string_dec, length); -+ ret = usb_local_string_dec; -+ break; -+ case 2: -+ stm32mp1_get_string((uint8_t *)"@Partition2 /0x02/1*1Me", -+ usb_local_string_dec, length); -+ ret = usb_local_string_dec; -+ break; -+ case 3: -+ stm32mp1_get_string((uint8_t *)"@Partition3 /0x03/1*16Me", -+ usb_local_string_dec, length); -+ ret = usb_local_string_dec; -+ break; -+ case 4: -+ stm32mp1_get_string((uint8_t *)"@Partition4 /0x04/1*16Me", -+ usb_local_string_dec, length); -+ ret = usb_local_string_dec; -+ break; -+ case 5: -+ stm32mp1_get_string((uint8_t *)"@virtual /0xF1/1*512Ba", -+ usb_local_string_dec, length); -+ ret = usb_local_string_dec; -+ break; -+ default: -+ ret = NULL; -+ break; -+ } -+ -+ return ret; -+} -+ -+static const usb_desc_t dfu_desc = { -+ .get_device_desc = stm32mp1_device_desc, -+ .get_lang_id_desc = stm32mp1_lang_id_desc, -+ .get_manufacturer_desc = stm32mp1_manufacturer_desc, -+ .get_product_desc = stm32mp1_product_desc, -+ .get_configuration_desc = stm32mp1_config_desc, -+ .get_serial_desc = stm32mp1_serial_desc, -+ .get_interface_desc = stm32mp1_interface_desc, -+ .get_usr_desc = stm32mp1_get_usr_desc, -+ .get_config_desc = stm32mp1_get_config_desc, -+ .get_device_qualifier_desc = stm32mp1_get_qualifier_desc, -+}; -+ -+static usb_handle_t usb_core_handle; -+static pcd_handle_t pcd_handle; -+ -+usb_handle_t *usb_dfu_plat_init(void) -+{ -+ /* prepare USB Driver */ -+ pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE; -+ pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE; -+ usb_dwc2_init_driver(&usb_core_handle, &pcd_handle, -+ (uint32_t *)USB_OTG_BASE); -+ -+ /* STM32MP15 = keep the configuration from ROM code */ -+ usb_core_handle.ep0_state = USBD_EP0_DATA_IN; -+ usb_core_handle.dev_state = USBD_STATE_CONFIGURED; -+ -+ /* prepare USB DFU stack */ -+ usb_dfu_register(&usb_core_handle, &usb_dfu_handle); -+ -+ /* register descriptor in USB stack */ -+ register_platform(&usb_core_handle, &dfu_desc); -+ -+ return &usb_core_handle; -+} -+ -+/* Link between USB alternate and STM32CubeProgramer phase */ -+uint8_t usb_dfu_get_phase(uint8_t alt) -+{ -+ switch (alt) { -+ case 0: -+#if STM32MP_SSP -+ return PHASE_SSP; -+#else -+ return PHASE_FLASHLAYOUT; -+#endif -+ case 3: -+ return PHASE_SSBL; -+ case 5: -+ return PHASE_CMD; -+ default: -+ return PHASE_RESET; -+ } -+} -diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile -index 0ec08b0540..5ef8faf522 100644 ---- a/tools/cert_create/Makefile -+++ b/tools/cert_create/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -9,7 +9,7 @@ V ?= 0 - DEBUG := 0 - CRTTOOL ?= cert_create${BIN_EXT} - BINARY := $(notdir ${CRTTOOL}) --OPENSSL_DIR := /usr -+OPENSSL_DIR ?= /usr - COT := tbbr - - MAKE_HELPERS_DIRECTORY := ../../make_helpers/ -@@ -53,13 +53,13 @@ HOSTCCFLAGS += ${DEFINES} - # could get pulled in from firmware tree. - INC_DIR := -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include - LIB_DIR := -L ${OPENSSL_DIR}/lib --LIB := -lssl -lcrypto -+LIB := -lssl -lcrypto -lpthread - - HOSTCC ?= gcc - - .PHONY: all clean realclean - --all: clean ${BINARY} -+all: ${BINARY} - - ${BINARY}: ${OBJECTS} Makefile - @echo " HOSTLD $@" -diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h -index d96d9839a2..3409502d82 100644 ---- a/tools/cert_create/include/key.h -+++ b/tools/cert_create/include/key.h -@@ -22,7 +22,8 @@ enum { - enum { - KEY_ALG_RSA, /* RSA PSS as defined by PKCS#1 v2.1 (default) */ - #ifndef OPENSSL_NO_EC -- KEY_ALG_ECDSA, -+ KEY_ALG_ECDSA_NIST, -+ KEY_ALG_ECDSA_BRAINPOOL, - #endif /* OPENSSL_NO_EC */ - KEY_ALG_MAX_NUM - }; -@@ -42,7 +43,8 @@ enum{ - static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = { - { 2048, 1024, 3072, 4096 }, /* KEY_ALG_RSA */ - #ifndef OPENSSL_NO_EC -- {} /* KEY_ALG_ECDSA */ -+ {}, /* KEY_ALG_ECDSA_NIST */ -+ {} /* KEY_ALG_ECDSA_BRAINPOOL */ - #endif /* OPENSSL_NO_EC */ - }; - -diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c -index fcc9d53162..25d7d4bd9b 100644 ---- a/tools/cert_create/src/key.c -+++ b/tools/cert_create/src/key.c -@@ -76,11 +76,11 @@ err: - } - - #ifndef OPENSSL_NO_EC --static int key_create_ecdsa(key_t *key, int key_bits) -+static int key_create_ecdsa(key_t *key, int key_bits, int curve_id) - { - EC_KEY *ec; - -- ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); -+ ec = EC_KEY_new_by_curve_name(curve_id); - if (ec == NULL) { - printf("Cannot create EC key\n"); - goto err; -@@ -101,13 +101,25 @@ err: - EC_KEY_free(ec); - return 0; - } -+ -+static int key_create_ecdsa_nist(key_t *key, int key_bits) -+{ -+ return key_create_ecdsa(key, key_bits, NID_X9_62_prime256v1); -+} -+ -+static int key_create_ecdsa_brainpool(key_t *key, int key_bits) -+{ -+ return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1); -+} -+ - #endif /* OPENSSL_NO_EC */ - - typedef int (*key_create_fn_t)(key_t *key, int key_bits); - static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { -- key_create_rsa, /* KEY_ALG_RSA */ -+ [KEY_ALG_RSA] = key_create_rsa, - #ifndef OPENSSL_NO_EC -- key_create_ecdsa, /* KEY_ALG_ECDSA */ -+ [KEY_ALG_ECDSA_NIST] = key_create_ecdsa_nist, -+ [KEY_ALG_ECDSA_BRAINPOOL] = key_create_ecdsa_brainpool, - #endif /* OPENSSL_NO_EC */ - }; - -diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c -index 2ba110132a..8a1e02e62f 100644 ---- a/tools/cert_create/src/main.c -+++ b/tools/cert_create/src/main.c -@@ -84,7 +84,8 @@ static char *strdup(const char *str) - static const char *key_algs_str[] = { - [KEY_ALG_RSA] = "rsa", - #ifndef OPENSSL_NO_EC -- [KEY_ALG_ECDSA] = "ecdsa" -+ [KEY_ALG_ECDSA_NIST] = "ecdsa", -+ [KEY_ALG_ECDSA_BRAINPOOL] = "ecdsa-brainpool" - #endif /* OPENSSL_NO_EC */ - }; - -diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile -index 6eb6fae7a8..7f959abeb3 100644 ---- a/tools/encrypt_fw/Makefile -+++ b/tools/encrypt_fw/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2019-2020, Linaro Limited. All rights reserved. -+# Copyright (c) 2019-2021, Linaro Limited. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -9,7 +9,7 @@ BUILD_INFO ?= 1 - DEBUG := 0 - ENCTOOL ?= encrypt_fw${BIN_EXT} - BINARY := $(notdir ${ENCTOOL}) --OPENSSL_DIR := /usr -+OPENSSL_DIR ?= /usr - - OBJECTS := src/encrypt.o \ - src/cmd_opt.o \ -@@ -40,13 +40,13 @@ endif - # could get pulled in from firmware tree. - INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include - LIB_DIR := -L ${OPENSSL_DIR}/lib --LIB := -lssl -lcrypto -+LIB := -lssl -lcrypto -lpthread - - HOSTCC ?= gcc - - .PHONY: all clean realclean - --all: clean ${BINARY} -+all: ${BINARY} - - ${BINARY}: ${OBJECTS} Makefile - @echo " HOSTLD $@" -diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile -index df8ab5c7be..0ef5c42707 100644 ---- a/tools/fiptool/Makefile -+++ b/tools/fiptool/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -8,6 +8,7 @@ MAKE_HELPERS_DIRECTORY := ../../make_helpers/ - include ${MAKE_HELPERS_DIRECTORY}build_macros.mk - include ${MAKE_HELPERS_DIRECTORY}build_env.mk - -+OPENSSL_DIR ?= /usr - FIPTOOL ?= fiptool${BIN_EXT} - PROJECT := $(notdir ${FIPTOOL}) - OBJECTS := fiptool.o tbbr_config.o -@@ -20,7 +21,8 @@ ifeq (${DEBUG},1) - else - HOSTCCFLAGS += -O2 - endif --LDLIBS := -lcrypto -+LIB_DIR := -L ${OPENSSL_DIR}/lib -+LDLIBS := -lcrypto -lpthread - - ifeq (${V},0) - Q := @ -@@ -38,7 +40,7 @@ all: ${PROJECT} - - ${PROJECT}: ${OBJECTS} Makefile - @echo " HOSTLD $@" -- ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS} -+ ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LIB_DIR} ${LDLIBS} - @${ECHO_BLANK_LINE} - @echo "Built $@ successfully" - @${ECHO_BLANK_LINE} -diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c -index 41024e2866..209e0c9d80 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) { -@@ -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.17.1 - diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-v2.6-stm32mp-r1.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-v2.6-stm32mp-r1.patch new file mode 100644 index 0000000..f9d108f --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0001-v2.6-stm32mp-r1.patch @@ -0,0 +1,55558 @@ +From bad40a0d5fd54b94b16ece24d8b280b4c5f12fcc Mon Sep 17 00:00:00 2001 +From: Christophe Priouzeau +Date: Mon, 30 May 2022 11:19:54 +0200 +Subject: [PATCH] v2.6-stm32mp-r1 + +--- + .commitlintrc.js | 2 +- + CONTRIBUTING.md | 30 + + Makefile | 17 +- + SECURITY.md | 8 + + bl1/aarch32/bl1_entrypoint.S | 9 + + bl2/aarch32/bl2_el3_exceptions.S | 9 + + bl2/aarch32/bl2_entrypoint.S | 9 + + bl2u/aarch32/bl2u_entrypoint.S | 9 + + bl32/sp_min/aarch32/entrypoint.S | 9 + + common/aarch32/debug.S | 52 +- + common/bl_common.c | 2 +- + docs/devicetree/bindings/arm/secure.txt | 53 + + .../bindings/clock/st,stm32mp1-rcc.txt | 496 ++++ + .../bindings/clock/st,stm32mp13-rcc.txt | 640 +++++ + docs/devicetree/bindings/i2c/i2c-stm32.txt | 54 + + .../memory-controllers/st,stm32mp1-ddr.txt | 289 ++ + docs/devicetree/bindings/mmc/mmci.txt | 72 + + .../bindings/mmc/st,stm32-sdmmc2.txt | 22 + + .../bindings/power/st,stm32mp1-pwr.txt | 43 + + 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 | 54 + + .../bindings/soc/st,stm32-romem.txt | 52 + + .../bindings/soc/st,stm32-stgen.txt | 18 + + .../devicetree/bindings/soc/st,stm32-tamp.txt | 20 + + .../bindings/watchdog/st,stm32-iwdg.txt | 27 + + docs/getting_started/porting-guide.rst | 46 +- + docs/plat/stm32mp1.rst | 143 +- + drivers/auth/auth_mod.c | 14 + + drivers/auth/mbedtls/mbedtls_common.mk | 2 +- + drivers/auth/mbedtls/mbedtls_x509_parser.c | 4 +- + drivers/auth/tbbr/tbbr_cot_bl1.c | 15 - + drivers/auth/tbbr/tbbr_cot_bl2.c | 1 + + drivers/auth/tbbr/tbbr_cot_common.c | 15 + + drivers/clk/clk.c | 65 + + drivers/fwu/fwu.c | 17 +- + drivers/mmc/mmc.c | 67 +- + drivers/mtd/nand/core.c | 21 +- + drivers/partition/gpt.c | 6 +- + drivers/partition/partition.c | 29 +- + drivers/regulator/regulator_core.c | 1131 ++++++++ + drivers/scmi-msg/base.c | 4 +- + drivers/scmi-msg/clock.c | 76 + + drivers/scmi-msg/clock.h | 12 + + drivers/st/bsec/{bsec.c => bsec2.c} | 518 ++-- + drivers/st/clk/clk-stm32-core.c | 1115 ++++++++ + drivers/st/clk/clk-stm32-core.h | 405 +++ + drivers/st/clk/clk-stm32mp13.c | 2380 +++++++++++++++++ + drivers/st/clk/stm32mp1_calib.c | 536 ++++ + drivers/st/clk/stm32mp1_clk.c | 1761 ++++++++++-- + drivers/st/clk/stm32mp_clkfunc.c | 211 +- + drivers/st/crypto/stm32_hash.c | 55 +- + drivers/st/crypto/stm32_pka.c | 704 +++++ + drivers/st/crypto/stm32_saes.c | 1074 ++++++++ + drivers/st/ddr/stm32mp1_ddr.c | 481 ++-- + drivers/st/ddr/stm32mp1_ddr_helpers.c | 546 +++- + drivers/st/ddr/stm32mp1_ram.c | 262 +- + drivers/st/ddr/stm32mp_ddr.c | 268 ++ + drivers/st/ddr/stm32mp_ddr_test.c | 148 + + drivers/st/ddr/stm32mp_ram.c | 59 + + drivers/st/etzpc/etzpc.c | 72 +- + drivers/st/fmc/stm32_fmc2_nand.c | 5 +- + drivers/st/gpio/stm32_gpio.c | 108 +- + drivers/st/i2c/stm32_i2c.c | 459 +++- + drivers/st/io/io_stm32image.c | 379 --- + drivers/st/iwdg/stm32_iwdg.c | 151 +- + drivers/st/mce/stm32_mce.c | 411 +++ + drivers/st/mmc/stm32_sdmmc2.c | 63 +- + drivers/st/pmic/stm32mp_pmic.c | 564 ++-- + drivers/st/pmic/stpmic1.c | 217 +- + drivers/st/regulator/regulator_fixed.c | 91 + + drivers/st/reset/stm32mp1_reset.c | 33 +- + drivers/st/rng/stm32_rng.c | 246 ++ + drivers/st/rtc/stm32_rtc.c | 480 ++++ + drivers/st/spi/stm32_qspi.c | 18 +- + drivers/st/tamper/stm32_tamp.c | 681 +++++ + drivers/st/timer/stm32_timer.c | 322 +++ + drivers/st/uart/aarch32/stm32_console.S | 42 +- + drivers/st/uart/stm32_uart.c | 440 +++ + fdts/stm32mp13-bl2.dtsi | 88 + + fdts/stm32mp13-ddr.dtsi | 184 ++ + fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi | 100 + + fdts/stm32mp13-fw-config-mem-encrypt.dtsi | 11 + + fdts/stm32mp13-fw-config.dtsi | 56 + + fdts/stm32mp13-pinctrl.dtsi | 103 + + fdts/stm32mp13-ssp-bl2.dtsi | 52 + + fdts/stm32mp131.dtsi | 579 ++++ + fdts/stm32mp133.dtsi | 7 + + fdts/stm32mp135.dtsi | 7 + + fdts/stm32mp135d-dk-fw-config.dts | 7 + + fdts/stm32mp135d-dk.dts | 320 +++ + fdts/stm32mp135f-dk-fw-config.dts | 8 + + fdts/stm32mp135f-dk.dts | 329 +++ + fdts/stm32mp13xa.dtsi | 5 + + fdts/stm32mp13xc.dtsi | 27 + + fdts/stm32mp13xd.dtsi | 5 + + fdts/stm32mp13xf.dtsi | 26 + + fdts/stm32mp15-bl2.dtsi | 40 +- + fdts/stm32mp15-bl32.dtsi | 1 - + fdts/stm32mp15-ddr.dtsi | 15 - + fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 12 - + fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 12 - + fdts/stm32mp15-fw-config.dtsi | 20 +- + fdts/stm32mp15-ssp-bl2.dtsi | 98 + + fdts/stm32mp151.dtsi | 61 +- + fdts/stm32mp153.dtsi | 1 + + fdts/stm32mp157a-avenger96.dts | 21 +- + fdts/stm32mp157a-dk1.dts | 18 + + fdts/stm32mp157a-ed1.dts | 38 + + fdts/stm32mp157a-ev1.dts | 24 + + fdts/stm32mp157c-dk2.dts | 18 + + fdts/stm32mp157c-ed1.dts | 331 +-- + fdts/stm32mp157c-ev1.dts | 44 +- + fdts/stm32mp157c-odyssey-som.dtsi | 2 +- + fdts/stm32mp157d-dk1.dts | 45 + + fdts/stm32mp157d-ed1.dts | 39 + + fdts/stm32mp157d-ev1.dts | 23 + + fdts/stm32mp157f-dk2.dts | 51 + + fdts/stm32mp157f-ed1.dts | 43 + + fdts/stm32mp157f-ev1.dts | 23 + + fdts/stm32mp15xa.dtsi | 13 + + fdts/stm32mp15xc.dtsi | 2 + + fdts/stm32mp15xd.dtsi | 19 + + fdts/stm32mp15xf.dtsi | 20 + + fdts/stm32mp15xx-dkx.dtsi | 158 +- + fdts/stm32mp15xx-edx.dtsi | 491 ++++ + fdts/stm32mp15xx-evx.dtsi | 73 + + fdts/stm32mp15xx-osd32.dtsi | 2 +- + fdts/stm32mp15xxaa-pinctrl.dtsi | 2 +- + fdts/stm32mp15xxac-pinctrl.dtsi | 2 +- + include/arch/aarch32/arch.h | 18 +- + include/arch/aarch32/arch_helpers.h | 4 + + include/arch/aarch64/arch.h | 6 +- + include/common/tbbr/cot_def.h | 2 +- + include/drivers/auth/tbbr_cot_common.h | 1 + + include/drivers/clk.h | 28 + + include/drivers/fwu/fwu.h | 1 + + include/drivers/io/io_storage.h | 3 +- + include/drivers/mmc.h | 25 + + include/drivers/nand.h | 2 + + include/drivers/partition/efi.h | 37 + + include/drivers/partition/gpt.h | 9 +- + include/drivers/partition/partition.h | 10 +- + include/drivers/regulator.h | 155 ++ + include/drivers/st/bsec.h | 156 +- + include/drivers/st/bsec2_reg.h | 105 + + include/drivers/st/io_stm32image.h | 32 - + include/drivers/st/regulator_fixed.h | 12 + + include/drivers/st/stm32_gpio.h | 12 +- + include/drivers/st/stm32_hash.h | 8 +- + include/drivers/st/stm32_i2c.h | 38 +- + include/drivers/st/stm32_iwdg.h | 1 + + include/drivers/st/stm32_mce.h | 34 + + include/drivers/st/stm32_pka.h | 46 + + include/drivers/st/stm32_rng.h | 13 + + include/drivers/st/stm32_rtc.h | 78 + + include/drivers/st/stm32_saes.h | 66 + + include/drivers/st/stm32_sdmmc2.h | 2 + + include/drivers/st/stm32_tamp.h | 252 ++ + include/drivers/st/stm32_timer.h | 21 + + include/drivers/st/stm32_uart.h | 159 ++ + include/drivers/st/stm32mp13_rcc.h | 1878 +++++++++++++ + include/drivers/st/stm32mp15_rcc.h | 2328 ++++++++++++++++ + include/drivers/st/stm32mp1_calib.h | 20 + + include/drivers/st/stm32mp1_clk.h | 50 +- + include/drivers/st/stm32mp1_ddr.h | 65 +- + include/drivers/st/stm32mp1_ddr_helpers.h | 18 +- + include/drivers/st/stm32mp1_ddr_regs.h | 235 +- + include/drivers/st/stm32mp1_pwr.h | 24 +- + include/drivers/st/stm32mp1_ram.h | 3 +- + include/drivers/st/stm32mp1_rcc.h | 2328 +--------------- + include/drivers/st/stm32mp_clkfunc.h | 19 +- + include/drivers/st/stm32mp_ddr.h | 78 + + include/drivers/st/stm32mp_ddr_test.h | 15 + + include/drivers/st/stm32mp_ddrctrl_regs.h | 270 ++ + include/drivers/st/stm32mp_pmic.h | 32 +- + include/drivers/st/stm32mp_ram.h | 33 + + include/drivers/st/stm32mp_reset.h | 14 +- + include/drivers/st/stpmic1.h | 35 +- + include/dt-bindings/clock/stm32mp1-clks.h | 278 +- + include/dt-bindings/clock/stm32mp1-clksrc.h | 284 +- + include/dt-bindings/clock/stm32mp13-clks.h | 230 ++ + include/dt-bindings/clock/stm32mp13-clksrc.h | 394 +++ + include/dt-bindings/clock/stm32mp15-clks.h | 278 ++ + include/dt-bindings/clock/stm32mp15-clksrc.h | 282 ++ + include/dt-bindings/power/stm32mp1-power.h | 20 + + include/dt-bindings/reset/stm32mp1-resets.h | 126 +- + include/dt-bindings/reset/stm32mp13-resets.h | 96 + + include/dt-bindings/reset/stm32mp15-resets.h | 123 + + include/dt-bindings/soc/st,stm32-etzpc.h | 86 + + include/dt-bindings/soc/stm32mp13-mce.h | 12 + + include/dt-bindings/soc/stm32mp13-tzc400.h | 34 + + include/lib/fconf/fconf_dyn_cfg_getter.h | 5 +- + include/lib/psci/psci.h | 1 + + include/lib/utils_def.h | 10 + + include/plat/common/platform.h | 12 +- + lib/aarch32/misc_helpers.S | 4 +- + lib/aarch64/misc_helpers.S | 8 +- + lib/fconf/fconf_dyn_cfg_getter.c | 19 +- + lib/psci/psci_private.h | 1 - + make_helpers/build_macros.mk | 9 +- + make_helpers/defaults.mk | 10 +- + plat/arm/common/arm_io_storage.c | 2 +- + plat/common/aarch32/platform_helpers.S | 34 + + plat/common/plat_bl_common.c | 2 +- + plat/st/common/bl2_io_storage.c | 313 ++- + plat/st/common/bl2_stm32_io_storage.c | 665 ----- + plat/st/common/include/stm32cubeprogrammer.h | 15 + + plat/st/common/include/stm32mp_auth.h | 19 - + plat/st/common/include/stm32mp_common.h | 65 +- + plat/st/common/include/stm32mp_dt.h | 11 + + plat/st/common/include/stm32mp_efi.h | 15 + + plat/st/common/include/stm32mp_fconf_getter.h | 2 + + plat/st/common/include/stm32mp_io_storage.h | 4 + + .../st/common/include/stm32mp_shres_helpers.h | 65 +- + plat/st/common/stm32cubeprogrammer_uart.c | 661 +++++ + plat/st/common/stm32cubeprogrammer_usb.c | 96 + + plat/st/common/stm32mp_auth.c | 90 - + plat/st/common/stm32mp_common.c | 220 +- + plat/st/common/stm32mp_crypto_lib.c | 652 +++++ + plat/st/common/stm32mp_dt.c | 338 ++- + plat/st/common/stm32mp_fconf_io.c | 79 +- + plat/st/common/stm32mp_gic.c | 219 ++ + plat/st/common/stm32mp_shres_helpers.c | 63 + + plat/st/common/stm32mp_trusted_boot.c | 206 ++ + plat/st/stm32mp1/bl2_plat_setup.c | 353 ++- + plat/st/stm32mp1/default_metadata.json | 37 + + plat/st/stm32mp1/include/boot_api.h | 716 ++++- + plat/st/stm32mp1/include/platform_def.h | 43 +- + .../include/stm32mp15_mbedtls_config.h | 119 + + plat/st/stm32mp1/include/stm32mp1_context.h | 30 +- + .../stm32mp1/include/stm32mp1_critic_power.h | 22 + + plat/st/stm32mp1/include/stm32mp1_dbgmcu.h | 9 +- + plat/st/stm32mp1/include/stm32mp1_low_power.h | 23 + + .../stm32mp1/include/stm32mp1_power_config.h | 29 + + plat/st/stm32mp1/include/stm32mp1_private.h | 40 +- + .../include/stm32mp1_shared_resources.h | 17 + + plat/st/stm32mp1/include/stm32mp1_smc.h | 64 +- + plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 4 + + .../stm32mp1/plat_bl2_stm32_mem_params_desc.c | 103 - + plat/st/stm32mp1/plat_image_load.c | 11 +- + plat/st/stm32mp1/platform.mk | 315 ++- + plat/st/stm32mp1/services/bsec_svc.c | 308 ++- + plat/st/stm32mp1/services/bsec_svc.h | 4 - + 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 | 140 + + plat/st/stm32mp1/services/rcc_svc.h | 13 + + .../st/stm32mp1/services/stm32mp1_svc_setup.c | 26 + + plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 26 +- + plat/st/stm32mp1/sp_min/sp_min_setup.c | 437 ++- + plat/st/stm32mp1/stm32mp1.S | 9 +- + plat/st/stm32mp1/stm32mp1.ld.S | 24 +- + plat/st/stm32mp1/stm32mp1_boot_device.c | 48 +- + plat/st/stm32mp1/stm32mp1_context.c | 523 +++- + plat/st/stm32mp1/stm32mp1_critic_power.c | 167 ++ + .../stm32mp1/stm32mp1_critic_power_wrapper.S | 134 + + plat/st/stm32mp1/stm32mp1_dbgmcu.c | 65 +- + plat/st/stm32mp1/stm32mp1_def.h | 432 ++- + plat/st/stm32mp1/stm32mp1_fconf_firewall.c | 11 +- + plat/st/stm32mp1/stm32mp1_fip_def.h | 106 +- + plat/st/stm32mp1/stm32mp1_gic.c | 92 - + plat/st/stm32mp1/stm32mp1_helper.S | 133 + + plat/st/stm32mp1/stm32mp1_low_power.c | 441 +++ + plat/st/stm32mp1/stm32mp1_pm.c | 112 +- + plat/st/stm32mp1/stm32mp1_power_config.c | 229 ++ + plat/st/stm32mp1/stm32mp1_private.c | 622 ++++- + plat/st/stm32mp1/stm32mp1_scmi.c | 131 +- + plat/st/stm32mp1/stm32mp1_security.c | 135 - + plat/st/stm32mp1/stm32mp1_shared_resources.c | 207 +- + plat/st/stm32mp1/stm32mp1_ssp.c | 1001 +++++++ + plat/st/stm32mp1/stm32mp1_ssp.mk | 103 + + plat/st/stm32mp1/stm32mp1_stm32image_def.h | 73 - + plat/st/stm32mp1/stm32mp1_syscfg.c | 330 ++- + plat/st/stm32mp1/stm32mp1_usb_dfu.c | 82 +- + tools/cert_create/Makefile | 4 +- + tools/cert_create/include/key.h | 6 +- + tools/cert_create/src/key.c | 20 +- + tools/cert_create/src/main.c | 3 +- + tools/encrypt_fw/Makefile | 6 +- + tools/fiptool/Makefile | 6 +- + tools/fwu_gen_metadata/README.md | 87 + + tools/fwu_gen_metadata/fwumd_tool.py | 181 ++ + tools/fwu_gen_metadata/src/metadata.py | 102 + + tools/fwu_gen_metadata/src/structs.py | 262 ++ + tools/fwu_gen_metadata/src/utils.py | 69 + + tools/fwu_gen_metadata/src/uuid_t.py | 79 + + tools/fwu_gen_metadata/tests/testall.sh | 21 + + .../fwu_gen_metadata/tests/validate_stable.sh | 8 + + tools/stm32image/stm32image.c | 188 +- + 294 files changed, 39291 insertions(+), 7795 deletions(-) + create mode 100644 CONTRIBUTING.md + create mode 100644 SECURITY.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/clock/st,stm32mp13-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 + create mode 100644 docs/devicetree/bindings/power/st,stpmic1.txt + create mode 100644 docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt + create mode 100644 docs/devicetree/bindings/rng/st,stm32-rng.txt + create mode 100644 docs/devicetree/bindings/serial/st,stm32-usart.txt + create mode 100644 docs/devicetree/bindings/soc/st,stm32-etzpc.txt + create mode 100644 docs/devicetree/bindings/soc/st,stm32-romem.txt + 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/clk/clk.c + create mode 100644 drivers/regulator/regulator_core.c + rename drivers/st/bsec/{bsec.c => bsec2.c} (63%) + create mode 100644 drivers/st/clk/clk-stm32-core.c + create mode 100644 drivers/st/clk/clk-stm32-core.h + create mode 100644 drivers/st/clk/clk-stm32mp13.c + create mode 100644 drivers/st/clk/stm32mp1_calib.c + create mode 100644 drivers/st/crypto/stm32_pka.c + create mode 100644 drivers/st/crypto/stm32_saes.c + create mode 100644 drivers/st/ddr/stm32mp_ddr.c + create mode 100644 drivers/st/ddr/stm32mp_ddr_test.c + create mode 100644 drivers/st/ddr/stm32mp_ram.c + delete mode 100644 drivers/st/io/io_stm32image.c + create mode 100644 drivers/st/mce/stm32_mce.c + create mode 100644 drivers/st/regulator/regulator_fixed.c + create mode 100644 drivers/st/rng/stm32_rng.c + create mode 100644 drivers/st/rtc/stm32_rtc.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/stm32_uart.c + create mode 100644 fdts/stm32mp13-bl2.dtsi + create mode 100644 fdts/stm32mp13-ddr.dtsi + create mode 100644 fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi + create mode 100644 fdts/stm32mp13-fw-config-mem-encrypt.dtsi + create mode 100644 fdts/stm32mp13-fw-config.dtsi + create mode 100644 fdts/stm32mp13-pinctrl.dtsi + create mode 100644 fdts/stm32mp13-ssp-bl2.dtsi + create mode 100644 fdts/stm32mp131.dtsi + create mode 100644 fdts/stm32mp133.dtsi + create mode 100644 fdts/stm32mp135.dtsi + create mode 100644 fdts/stm32mp135d-dk-fw-config.dts + create mode 100644 fdts/stm32mp135d-dk.dts + create mode 100644 fdts/stm32mp135f-dk-fw-config.dts + create mode 100644 fdts/stm32mp135f-dk.dts + create mode 100644 fdts/stm32mp13xa.dtsi + create mode 100644 fdts/stm32mp13xc.dtsi + create mode 100644 fdts/stm32mp13xd.dtsi + create mode 100644 fdts/stm32mp13xf.dtsi + create mode 100644 fdts/stm32mp15-ssp-bl2.dtsi + create mode 100644 fdts/stm32mp157a-ed1.dts + create mode 100644 fdts/stm32mp157a-ev1.dts + 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/stm32mp15xd.dtsi + create mode 100644 fdts/stm32mp15xf.dtsi + create mode 100644 fdts/stm32mp15xx-edx.dtsi + create mode 100644 fdts/stm32mp15xx-evx.dtsi + create mode 100644 include/drivers/clk.h + create mode 100644 include/drivers/partition/efi.h + create mode 100644 include/drivers/regulator.h + create mode 100644 include/drivers/st/bsec2_reg.h + delete mode 100644 include/drivers/st/io_stm32image.h + create mode 100644 include/drivers/st/regulator_fixed.h + create mode 100644 include/drivers/st/stm32_mce.h + create mode 100644 include/drivers/st/stm32_pka.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_saes.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.h + create mode 100644 include/drivers/st/stm32mp13_rcc.h + create mode 100644 include/drivers/st/stm32mp15_rcc.h + create mode 100644 include/drivers/st/stm32mp1_calib.h + create mode 100644 include/drivers/st/stm32mp_ddr.h + create mode 100644 include/drivers/st/stm32mp_ddr_test.h + create mode 100644 include/drivers/st/stm32mp_ddrctrl_regs.h + create mode 100644 include/drivers/st/stm32mp_ram.h + create mode 100644 include/dt-bindings/clock/stm32mp13-clks.h + create mode 100644 include/dt-bindings/clock/stm32mp13-clksrc.h + create mode 100644 include/dt-bindings/clock/stm32mp15-clks.h + create mode 100644 include/dt-bindings/clock/stm32mp15-clksrc.h + create mode 100644 include/dt-bindings/power/stm32mp1-power.h + create mode 100644 include/dt-bindings/reset/stm32mp13-resets.h + create mode 100644 include/dt-bindings/reset/stm32mp15-resets.h + create mode 100644 include/dt-bindings/soc/stm32mp13-mce.h + create mode 100644 include/dt-bindings/soc/stm32mp13-tzc400.h + delete mode 100644 plat/st/common/bl2_stm32_io_storage.c + delete mode 100644 plat/st/common/include/stm32mp_auth.h + create mode 100644 plat/st/common/include/stm32mp_efi.h + create mode 100644 plat/st/common/stm32cubeprogrammer_uart.c + delete mode 100644 plat/st/common/stm32mp_auth.c + create mode 100644 plat/st/common/stm32mp_crypto_lib.c + create mode 100644 plat/st/common/stm32mp_gic.c + create mode 100644 plat/st/common/stm32mp_shres_helpers.c + create mode 100644 plat/st/common/stm32mp_trusted_boot.c + create mode 100644 plat/st/stm32mp1/default_metadata.json + create mode 100644 plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h + create mode 100644 plat/st/stm32mp1/include/stm32mp1_critic_power.h + create mode 100644 plat/st/stm32mp1/include/stm32mp1_low_power.h + create mode 100644 plat/st/stm32mp1/include/stm32mp1_power_config.h + delete mode 100644 plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c + 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/stm32mp1_critic_power.c + create mode 100644 plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S + 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 + delete mode 100644 plat/st/stm32mp1/stm32mp1_security.c + create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.c + create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.mk + delete mode 100644 plat/st/stm32mp1/stm32mp1_stm32image_def.h + create mode 100644 tools/fwu_gen_metadata/README.md + create mode 100755 tools/fwu_gen_metadata/fwumd_tool.py + create mode 100644 tools/fwu_gen_metadata/src/metadata.py + create mode 100644 tools/fwu_gen_metadata/src/structs.py + create mode 100644 tools/fwu_gen_metadata/src/utils.py + create mode 100644 tools/fwu_gen_metadata/src/uuid_t.py + create mode 100755 tools/fwu_gen_metadata/tests/testall.sh + create mode 100755 tools/fwu_gen_metadata/tests/validate_stable.sh + +diff --git a/.commitlintrc.js b/.commitlintrc.js +index 3bd68bb6c..f97048188 100644 +--- a/.commitlintrc.js ++++ b/.commitlintrc.js +@@ -46,7 +46,7 @@ module.exports = { + "change-id-exists": [1, "always", "Change-Id:"], /* Warning */ + "signed-off-by-exists": [1, "always", "Signed-off-by:"], /* Warning */ + +- "scope-case": [2, "always", "kebab-case"], /* Error */ ++ "scope-case": [2, "always", "lower-case"], /* Error */ + "scope-enum": [1, "always", scopes] /* Warning */ + }, + }; +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 ++ ++This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you. ++ ++This guide mainly focuses on the proper use of Git. ++ ++## 1. Issues ++ ++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). ++ ++## 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 73007b413..35644b832 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -170,6 +170,11 @@ FIP_DEPS += enctool + FWU_FIP_DEPS += enctool + endif + ++ifeq (${PSA_FWU_SUPPORT},1) ++FWUMD_ARGS += --nb-fw-imgs ${NR_OF_FW_BANKS} ++FWUMD_ARGS += --nb-banks ${NR_OF_IMAGES_IN_FW_BANK} ++endif ++ + ################################################################################ + # Toolchain + ################################################################################ +@@ -918,6 +923,10 @@ ENCTOOL ?= ${ENCTOOLPATH}/encrypt_fw${BIN_EXT} + FIPTOOLPATH ?= tools/fiptool + FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT} + ++# Variables for use with Firmware Update Metadata ++FWUMDTOOLPATH ?= tools/fwu_gen_metadata/ ++FWUMDTOOL ?= ${FWUMDTOOLPATH}/fwumd_tool.py ++ + # Variables for use with sptool + SPTOOLPATH ?= tools/sptool + SPTOOL ?= ${SPTOOLPATH}/sptool${BIN_EXT} +@@ -1041,6 +1050,7 @@ $(eval $(call assert_booleans,\ + ENABLE_FEAT_HCX \ + ENABLE_MPMM \ + ENABLE_MPMM_FCONF \ ++ AARCH32_EXCEPTION_DEBUG \ + ))) + + $(eval $(call assert_numerics,\ +@@ -1153,6 +1163,7 @@ $(eval $(call add_defines,\ + ENABLE_FEAT_HCX \ + ENABLE_MPMM \ + ENABLE_MPMM_FCONF \ ++ AARCH32_EXCEPTION_DEBUG \ + ))) + + ifeq (${SANITIZE_UB},trap) +@@ -1382,7 +1393,7 @@ checkpatch: locate-checkpatch + certtool: ${CRTTOOL} + + ${CRTTOOL}: FORCE +- ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} --no-print-directory -C ${CRTTOOLPATH} ++ ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} CRTTOOL=${CRTTOOL} --no-print-directory -C ${CRTTOOLPATH} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} +@@ -1452,7 +1463,7 @@ doc: + enctool: ${ENCTOOL} + + ${ENCTOOL}: FORCE +- ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} --no-print-directory -C ${ENCTOOLPATH} ++ ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 ENCTOOL=${ENCTOOL} --no-print-directory -C ${ENCTOOLPATH} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} +diff --git a/SECURITY.md b/SECURITY.md +new file mode 100644 +index 000000000..4b3e4e6ba +--- /dev/null ++++ b/SECURITY.md +@@ -0,0 +1,8 @@ ++# Report potential product security vulnerabilities ++ST places a high priority on security, and our Product Security Incident Response Team (PSIRT) is committed to rapidly addressing potential security vulnerabilities affecting our products. PSIRT's long history and vast experience in security allows ST to perform clear analyses and provide appropriate guidance on mitigations and solutions when applicable. ++If you wish to report potential security vulnerabilities regarding our products, **please do not report them through public GitHub issues.** Instead, we encourage you to report them to our ST PSIRT following the process described at: **https://www.st.com/content/st_com/en/security/report-vulnerabilities.html** ++ ++### IMPORTANT - READ CAREFULLY: ++STMicroelectronics International N.V., on behalf of itself, its affiliates and subsidiaries, (collectively “ST”) takes all potential security vulnerability reports or other related communications (“Report(s)”) seriously. In order to review Your Report (the terms “You” and “Yours” include your employer, and all affiliates, subsidiaries and related persons or entities) and take actions as deemed appropriate, ST requires that we have the rights and Your permission to do so. ++As such, by submitting Your Report to ST, You agree that You have the right to do so, and You grant to ST the rights to use the Report for purposes related to security vulnerability analysis, testing, correction, patching, reporting and any other related purpose or function. ++By submitting Your Report, You agree that ST’s [Privacy Policy](https://www.st.com/content/st_com/en/common/privacy-portal.html) applies to all related communications. +diff --git a/bl1/aarch32/bl1_entrypoint.S b/bl1/aarch32/bl1_entrypoint.S +index 94dfd3738..f6abfb166 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 + 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 087b6656d..dff4e36a4 100644 +--- a/bl2/aarch32/bl2_el3_exceptions.S ++++ b/bl2/aarch32/bl2_el3_exceptions.S +@@ -12,10 +12,19 @@ + + vector_base bl2_vector_table + b bl2_entrypoint ++#if AARCH32_EXCEPTION_DEBUG ++ b report_undef_inst /* Undef */ ++#else + b report_exception /* Undef */ ++#endif + b report_exception /* SVC 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_entrypoint.S b/bl2/aarch32/bl2_entrypoint.S +index 6e8e2c1e1..dfcec18ee 100644 +--- a/bl2/aarch32/bl2_entrypoint.S ++++ b/bl2/aarch32/bl2_entrypoint.S +@@ -14,10 +14,19 @@ + + vector_base bl2_vector_table + b bl2_entrypoint ++#if AARCH32_EXCEPTION_DEBUG ++ b report_undef_inst /* Undef */ ++#else + b report_exception /* Undef */ ++#endif + b report_exception /* SVC 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/bl2u/aarch32/bl2u_entrypoint.S b/bl2u/aarch32/bl2u_entrypoint.S +index e4dd03dec..f48bc8249 100644 +--- a/bl2u/aarch32/bl2u_entrypoint.S ++++ b/bl2u/aarch32/bl2u_entrypoint.S +@@ -14,10 +14,19 @@ + + vector_base bl2u_vector_table + b bl2u_entrypoint ++#if AARCH32_EXCEPTION_DEBUG ++ b report_undef_inst /* Undef */ ++#else + b report_exception /* Undef */ ++#endif + b report_exception /* SVC 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/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S +index 39f1065f0..8508d443d 100644 +--- a/bl32/sp_min/aarch32/entrypoint.S ++++ b/bl32/sp_min/aarch32/entrypoint.S +@@ -49,10 +49,19 @@ + + vector_base sp_min_vector_table + b sp_min_entrypoint ++#if AARCH32_EXCEPTION_DEBUG ++ b report_undef_inst /* Undef */ ++#else + b plat_panic_handler /* Undef */ ++#endif + b sp_min_handle_smc /* Syscall */ ++#if AARCH32_EXCEPTION_DEBUG ++ b report_prefetch_abort /* Prefetch abort */ ++ b report_data_abort /* Data abort */ ++#else + b plat_panic_handler /* Prefetch abort */ + b plat_panic_handler /* Data abort */ ++#endif + b plat_panic_handler /* Reserved */ + b plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ +diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S +index 9d410df07..69b1ed4ed 100644 +--- a/common/aarch32/debug.S ++++ b/common/aarch32/debug.S +@@ -14,6 +14,11 @@ + .globl asm_assert + .globl do_panic + .globl report_exception ++#if AARCH32_EXCEPTION_DEBUG ++ .globl report_undef_inst ++ .globl report_prefetch_abort ++ .globl report_data_abort ++#endif + + /* Since the max decimal input number is 65536 */ + #define MAX_DEC_DIVISOR 10000 +@@ -113,10 +118,10 @@ endfunc asm_assert + + /* + * This function prints a string from address in r4 +- * Clobber: lr, r0 - r4 ++ * Clobber: lr, r0 - r4, r7 + */ + func asm_print_str +- mov r3, lr ++ mov r7, lr + 1: + ldrb r0, [r4], #0x1 + cmp r0, #0 +@@ -124,20 +129,20 @@ func asm_print_str + bl plat_crash_console_putc + b 1b + 2: +- bx r3 ++ bx r7 + endfunc asm_print_str + + /* + * This function prints a hexadecimal number in r4. + * In: r4 = the hexadecimal to print. +- * Clobber: lr, r0 - r3, r5 ++ * Clobber: lr, r0 - r3, r5, r7 + */ + func asm_print_hex + mov r5, #32 /* No of bits to convert to ascii */ + + /* Convert to ascii number of bits in r5 */ + asm_print_hex_bits: +- mov r3, lr ++ mov r7, lr + 1: + sub r5, r5, #4 + lsr r0, r4, r5 +@@ -153,7 +158,7 @@ asm_print_hex_bits: + bl plat_crash_console_putc + cmp r5, #0 + bne 1b +- bx r3 ++ bx r7 + endfunc asm_print_hex + + /*********************************************************** +@@ -205,3 +210,38 @@ func report_exception + bl plat_report_exception + no_ret plat_panic_handler + endfunc report_exception ++ ++#if AARCH32_EXCEPTION_DEBUG ++ /*********************************************************** ++ * This function is called from the vector table for ++ * undefined instruction. The lr_und is given as an ++ * argument to platform handler. ++ ***********************************************************/ ++func report_undef_inst ++ mrs r0, lr_und ++ bl plat_report_undef_inst ++ no_ret plat_panic_handler ++endfunc report_undef_inst ++ ++ /*********************************************************** ++ * This function is called from the vector table for ++ * unhandled exceptions. The lr_abt is given as an ++ * argument to platform handler. ++ ***********************************************************/ ++func report_prefetch_abort ++ mrs r0, lr_abt ++ bl plat_report_prefetch_abort ++ no_ret plat_panic_handler ++endfunc report_prefetch_abort ++ ++ /*********************************************************** ++ * This function is called from the vector table for ++ * unhandled exceptions. The lr_abt is given as an ++ * argument to platform handler. ++ ***********************************************************/ ++func report_data_abort ++ mrs r0, lr_abt ++ bl plat_report_data_abort ++ no_ret plat_panic_handler ++endfunc report_data_abort ++#endif +diff --git a/common/bl_common.c b/common/bl_common.c +index eb2352a77..7b6d89887 100644 +--- a/common/bl_common.c ++++ b/common/bl_common.c +@@ -263,7 +263,7 @@ int load_auth_image(unsigned int image_id, image_info_t *image_data) + #else + do { + err = load_auth_image_internal(image_id, image_data); +- } while ((err != 0) && (plat_try_next_boot_source() != 0)); ++ } while ((err != 0) && (plat_try_next_boot_source(image_id) != 0)); + #endif /* PSA_FWU_SUPPORT */ + + return err; +diff --git a/docs/devicetree/bindings/arm/secure.txt b/docs/devicetree/bindings/arm/secure.txt +new file mode 100644 +index 000000000..e31303fb2 +--- /dev/null ++++ b/docs/devicetree/bindings/arm/secure.txt +@@ -0,0 +1,53 @@ ++* ARM Secure world bindings ++ ++ARM CPUs with TrustZone support have two distinct address spaces, ++"Normal" and "Secure". Most devicetree consumers (including the Linux ++kernel) are not TrustZone aware and run entirely in either the Normal ++world or the Secure world. However some devicetree consumers are ++TrustZone aware and need to be able to determine whether devices are ++visible only in the Secure address space, only in the Normal address ++space, or visible in both. (One example of that situation would be a ++virtual machine which boots Secure firmware and wants to tell the ++firmware about the layout of the machine via devicetree.) ++ ++The general principle of the naming scheme for Secure world bindings ++is that any property that needs a different value in the Secure world ++can be supported by prefixing the property name with "secure-". So for ++instance "secure-foo" would override "foo". For property names with ++a vendor prefix, the Secure variant of "vendor,foo" would be ++"vendor,secure-foo". If there is no "secure-" property then the Secure ++world value is the same as specified for the Normal world by the ++non-prefixed property. However, only the properties listed below may ++validly have "secure-" versions; this list will be enlarged on a ++case-by-case basis. ++ ++Defining the bindings in this way means that a device tree which has ++been annotated to indicate the presence of Secure-only devices can ++still be processed unmodified by existing Non-secure software (and in ++particular by the kernel). ++ ++Note that it is still valid for bindings intended for purely Secure ++world consumers (like kernels that run entirely in Secure) to simply ++describe the view of Secure world using the standard bindings. These ++secure- bindings only need to be used where both the Secure and Normal ++world views need to be described in a single device tree. ++ ++Valid Secure world properties: ++ ++- secure-status : specifies whether the device is present and usable ++ in the secure world. The combination of this with "status" allows ++ the various possible combinations of device visibility to be ++ specified. If "secure-status" is not specified it defaults to the ++ same value as "status"; if "status" is not specified either then ++ both default to "okay". This means the following combinations are ++ possible: ++ ++ /* Neither specified: default to visible in both S and NS */ ++ secure-status = "okay"; /* visible in both */ ++ status = "okay"; /* visible in both */ ++ status = "okay"; secure-status = "okay"; /* visible in both */ ++ secure-status = "disabled"; /* NS-only */ ++ status = "okay"; secure-status = "disabled"; /* NS-only */ ++ status = "disabled"; secure-status = "okay"; /* S-only */ ++ status = "disabled"; /* disabled in both */ ++ 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 000000000..f227b8c55 +--- /dev/null ++++ b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt +@@ -0,0 +1,496 @@ ++STMicroelectronics STM32 Peripheral Reset Clock Controller ++========================================================== ++ ++The RCC IP is both a reset and a clock controller. ++ ++RCC makes also power management (resume/supend and wakeup interrupt). ++ ++Please also refer to reset.txt for common reset controller binding usage. ++ ++Please also refer to clock-bindings.txt for common clock controller ++binding usage. ++ ++ ++Required properties: ++- compatible: "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon" ++ Adding "st,stm32mp1-rcc-secure" in the compatible list restricts ++ RCC access through RCC TZ_ENABLE bit. ++- reg: should be register base and length as documented in the datasheet ++- #clock-cells: 1, device nodes should specify the clock in their ++ "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. ++- secure-interrupts: Should contain a interrupt line to the wake-up of ++ processor (CSTOP). ++ ++Example: ++ rcc: rcc@50000000 { ++ compatible = "st,stm32mp1-rcc", "syscon"; ++ reg = <0x50000000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ interrupts = ; ++ secure-interrupts = ; ++ }; ++ ++Specifying clocks ++================= ++ ++All available clocks are defined as preprocessor macros in ++dt-bindings/clock/stm32mp1-clks.h header and can be used in device ++tree sources. ++ ++Specifying softreset control of devices ++======================================= ++ ++Device nodes should specify the reset channel required in their "resets" ++property, containing a phandle to the reset device node and an index specifying ++which channel to use. ++The index is the bit number within the RCC registers bank, starting from RCC ++base address. ++It is calculated as: index = register_offset / 4 * 32 + bit_offset. ++Where bit_offset is the bit offset within the register. ++ ++For example on STM32MP1, for LTDC reset: ++ ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset ++ = 0x180 / 4 * 32 + 0 = 3072 ++ ++The list of valid indices for STM32MP1 is available in: ++include/dt-bindings/reset-controller/stm32mp1-resets.h ++ ++This file implements defines like: ++#define LTDC_R 3072 ++ ++ ++Defining clock source distribution with property st,clksrc ++========================================================== ++ ++- st,clksrc : The clock sources configuration array in a platform specific ++ 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 ++ >; ++ ++Defining clock dividers with property st,clkdiv ++=============================================== ++ ++- st,clkdiv : The clock main dividers value specified in an array ++ in a platform specific order. ++ ++ When used, it shall describe the whole clock dividers tree. ++ ++ 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: ++ 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*/ ++ >; ++ ++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 ++======================================================== ++ ++- children for a PLL static configuration with "st,stm32mp1-pll" compatible ++ ++ Each PLL children nodes for PLL1 to PLL4 (see ref manual for details) ++ are listed with associated reg 0 to 3. ++ ++ PLL2, PLL3 or PLL4 are off when their associated nodes are absent or ++ deactivated. ++ ++ The configuration of PLL1, the source clock of Cortex-A7 core, with st,pll@0 ++ node, is optional as TF-A automatically selects the most suitable operating ++ point for the platform. ++ The node st,pll@0 node should be absent; it is only used if you want to ++ override the PLL1 properties computed by TF-A (clock spreading for example). ++ ++ Here are the available properties for each PLL node: ++ - compatible: should be "st,stm32mp1-pll" ++ ++ - 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) ++ 0x1: division by 2 ++ 0x2: division by 3 ++ 0x3: division by 4 ++ ... ++ ++ Output contains a bitfield for each output value (1:ON/0:OFF) ++ BIT(0) => output P : DIVPEN ++ BIT(1) => output Q : DIVQEN ++ BIT(2) => output R : DIVREN ++ 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). ++ ++ - 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 ++ SSCG_MODE: Spread spectrum clock generator mode, with associated ++ defined from stm32mp1-clksrc.h: ++ - SSCG_MODE_CENTER_SPREAD = 0 ++ - SSCG_MODE_DOWN_SPREAD = 1 ++ ++ Example: ++ st,pll@0 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ cfg = <1 53 0 0 0 1>; ++ frac = <0x810>; ++ }; ++ st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ cfg = <1 43 1 0 0 PQR(0,1,1)>; ++ csg = <10 20 1>; ++ }; ++ st,pll@2 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ cfg = <2 85 3 13 3 0>; ++ csg = <10 20 SSCG_MODE_CENTER_SPREAD>; ++ }; ++ st,pll@3 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ cfg = <2 78 4 7 9 3>; ++ }; ++ ++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 ++ ++At boot the clock tree initialization will ++ - 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: ++ / { ++ clocks { ++ clk_hse: clk-hse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <64000000>; ++ st,bypass; ++ }; ++ ++ clk_lse: clk-lse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ st,css; ++ st,drive = ; ++ }; ++ }; ++ ++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: ++ / { ++ clocks { ++ clk_hsi: clk-hsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <64000000>; ++ }; ++ }; ++ ++ Example with HSIDIV = /2 ++ / { ++ clocks { ++ clk_hsi: clk-hsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32000000>; ++ }; ++ }; ++ ++HSI & CSI calibration ++======================== ++ ++Calibration is an optional feature that may be enabled from device tree. It ++allows to request calibration of the HSI or the CSI clocks from several means: ++ - SiP SMC service ++ - Periodic calibration every X seconds ++ - Interrupt raised by the MCU ++ ++This feature requires that a HW timer is assigned to the calibration sequence. ++ ++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. ++ ++- st,csi-cal; used to enable CSI clock calibration feature. ++ ++- st,cal-sec: used to enable periodic calibration every specified seconds from ++ secure monitor. Time must be given in seconds. If not specified, calibration ++ is processed for each incoming request. ++ ++Example: ++ &rcc { ++ st,hsi-cal; ++ st,csi-cal; ++ st,cal-sec = <15>; ++ secure-interrupts = , ++ ; ++ 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"; ++ ++ 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/clock/st,stm32mp13-rcc.txt b/docs/devicetree/bindings/clock/st,stm32mp13-rcc.txt +new file mode 100644 +index 000000000..eb23449c2 +--- /dev/null ++++ b/docs/devicetree/bindings/clock/st,stm32mp13-rcc.txt +@@ -0,0 +1,640 @@ ++STMicroelectronics STM32 Peripheral Reset Clock Controller ++========================================================== ++ ++The RCC IP is both a reset and a clock controller. ++ ++RCC makes also power management (resume/supend and wakeup interrupt). ++ ++Please also refer to reset.txt for common reset controller binding usage. ++ ++Please also refer to clock-bindings.txt for common clock controller ++binding usage. ++ ++ ++Required properties: ++- compatible: "st,stm32mp13-rcc", "syscon" ++- reg: should be register base and length as documented in the datasheet ++- #clock-cells: 1, device nodes should specify the clock in their ++ "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. ++- secure-interrupts: Should contain an interrupt line to the wake-up of ++ processor (CSTOP). ++ ++Example: ++ rcc: rcc@50000000 { ++ compatible = "st,stm32mp13-rcc", "syscon"; ++ reg = <0x50000000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ interrupts = ; ++ secure-interrupts = ; ++ }; ++ ++Specifying clocks ++================= ++ ++All available clocks are defined as preprocessor macros in ++dt-bindings/clock/stm32mp13-clks.h header and can be used in device ++tree sources. ++ ++Specifying softreset control of devices ++======================================= ++ ++Device nodes should specify the reset channel required in their "resets" ++property, containing a phandle to the reset device node and an index specifying ++which channel to use. ++The index is the bit number within the RCC registers bank, starting from RCC ++base address. ++It is calculated as: index = register_offset / 4 * 32 + bit_offset. ++Where bit_offset is the bit offset within the register. ++ ++For example on STM32MP13, for I2C2 reset: ++ i2c2 = APB1_RSTSETR_offset / 4 * 32 + I2C2_bit_offset ++ = 0x6A0 / 4 * 32 + 22 = 13590 ++ ++The list of valid indices for STM32MP13 is available in: ++include/dt-bindings/reset/stm32mp13-resets.h ++ ++This file implements defines like: ++#define I2C2_R 13590 ++ ++ ++Defining clock source distribution with property st,clksrc ++========================================================== ++ ++- st,clksrc : 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/stm32mp13-clksrc.h. ++ ++ st,clksrc may not list all the kernel clocks and has no ordering requirements. ++ ++ Property can be used to configure the clock distribution tree. ++ ++ Example: ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MLAHBS_PLL3 ++ CLK_RTC_LSE ++ CLK_MCO1_DISABLED ++ CLK_MCO2_DISABLED ++ CLK_ETH1_PLL4P ++ CLK_ETH2_PLL4P ++ CLK_SDMMC1_PLL4P ++ CLK_SDMMC2_PLL4P ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_I2C4_HSI ++ >; ++ ++Defining clock dividers with property st,clkdiv ++=============================================== ++ ++- st,clkdiv : The property is a list of dividers defined ++ by macros DIV(DIV_, value) as defined by header file ++ dt-bindings/clock/stm32mp13-clksrc.h. ++ ++ Property can be used to configure the clock main dividers value. ++ ++ For the STM32MP13 family there are 12 dividers values expected. ++ MPU AXI MLAHB APB1 APB2 APB3 APB4 APB5 APB6 RTC MCO1 MCO2 ++ ++ 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 the coding is different for: ++ ++ RTC MCO1 MCO2 ++ 0x0: not divided ++ 0x1: division by 2 ++ 0x2: division by 3 ++ 0x3: division by 4 ++ ... ++ ++ DIV_MPU ++ 0x0: no clock generated ++ 0x1: division by 2 ++ 0x2: division by 3 ++ 0x3: division by 4 ++ ... ++ 0xf: division by 16 ++ ++ Example: ++ st,clkdiv = < ++ DIV(DIV_MPU, 1) ++ DIV(DIV_AXI, 0) ++ DIV(DIV_MLAHB, 0) ++ DIV(DIV_APB1, 1) ++ DIV(DIV_APB2, 1) ++ DIV(DIV_APB3, 1) ++ DIV(DIV_APB4, 1) ++ DIV(DIV_APB5, 2) ++ DIV(DIV_APB6, 1) ++ DIV(DIV_RTC, 23) ++ DIV(DIV_MCO1, 0) ++ DIV(DIV_MCO2, 0) ++ >; ++ ++Defining peripheral PLL frequencies ++======================================================== ++ ++- children for a PLL static configuration with "st,stm32mp1-pll" compatible ++ ++ Each PLL children node for PLL1 to PLL4 (see ref manual for details) ++ are listed with associated reg 0 to 3. ++ ++ PLL2, PLL3 or PLL4 are off when their associated nodes are absent or ++ deactivated. ++ ++ The configuration of PLL1, the source clock of Cortex-A7 core, is mandatory ++ for TF-A. ++ ++ Here are the available properties for each PLL node: ++ - compatible: should be "st,stm32mp1-pll" ++ ++ - reg: index of the pll instance ++ ++ - st,pll: Phandle of the default pll configuration. ++ A pll could have several configuration (5 max) and shoud be described in a subnode ++ just below. ++ ++ - pllx_cfgx node: The PLL configuration node is composed of 2 mandatory parameters: ++ - st,pll_vco: Phandle of pll vco configuration. ++ See description of 'st,pll_vco' node. ++ ++ - st,pll_div_pqr: The parameters for PLL configuration in the following order: ++ DIVP DIVQ DIVR Output. ++ ++ DIVx values are defined as in RCC spec: ++ 0x0: bypass (division by 1) ++ 0x1: division by 2 ++ 0x2: division by 3 ++ 0x3: division by 4 ++ ... ++ Note that in the next stage (e.g. OPTEE) the phandle of the default pll configuration ++ ('st,pll') could be optional (the configuration of TF-A will be kept). ++ The DVFS could apllied configuration at run-time from pllx_cfgx node. ++ ++- st,pll_vco node: This node will contain all vco configuration of all PLLs in subnodes. ++ We will found theses parameters in each subnodes. ++ ++ -src: Clock source configuration values are defined by macros CLK__ ++ from dt-bindings/clock/stm32mp13-clksrc.h. ++ ++ -divmn: The parameters for PLL divider (DIVM) and multiplication factor (DIVN) ++ configuration. ++ ++ - 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. ++ ++ MOD_PER: Modulation Period Adjustment ++ INC_STEP: Modulation Depth Adjustment ++ SSCG_MODE: Spread spectrum clock generator mode, with associated ++ defined from stm32mp13-clksrc.h: ++ - SSCG_MODE_CENTER_SPREAD = 0 ++ - SSCG_MODE_DOWN_SPREAD = 1 ++ ++ Example: ++ st,pll_vco { ++ pll1_vco_1300Mhz: pll1-vco-1300Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 80 >; ++ frac = < 0x800 >; ++ }; ++ ... ++ pll2_vco_1066Mhz: pll2-vco-1066Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 65 >; ++ frac = < 0x1400 >; ++ csg = <10 20 1>; ++ }; ++ ... ++ }; ++ ++ pll1:st,pll@0 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ ++ st,pll = < &pll1_cfg1 >; ++ ++ pll1_cfg1: pll1_cfg1 { ++ st,pll_vco = < &pll1_vco_1300Mhz >; ++ st,pll_div_pqr = < 0 1 1 >; ++ }; ++ }; ++ ++ st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ ++ st,pll = < &pll2_cfg1 >; ++ ++ pll2_cfg1: pll2_cfg1 { ++ st,pll_vco = < &pll2_vco_1066Mhz >; ++ st,pll_div_pqr = < 1 0 1 >; ++ }; ++ }; ++ ++ Note: pll1 and pll2 have same source clock, if source clock is different ++ between pll1 and pll2 a panic will be generated. ++ ++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 ++ ++At boot the clock tree initialization will ++ - 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) ++ or 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/stm32mp13-clksrc.h) ++ ++ Example board file: ++ / { ++ clocks { ++ clk_hse: clk-hse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ st,bypass; ++ }; ++ ++ clk_lse: clk-lse { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ st,css; ++ st,drive = ; ++ }; ++ }; ++ ++b) for internal oscillator: "clk-hsi" ++ ++ Internally HSI clock is fixed to 64MHz for STM32MP13 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 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <64000000>; ++ }; ++ }; ++ ++ Example with HSIDIV = /2 ++ / { ++ clocks { ++ clk_hsi: clk-hsi { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32000000>; ++ }; ++ }; ++ ++HSI & CSI calibration ++======================== ++ ++Calibration is an optional feature that may be enabled from device tree. It ++allows to request calibration of the HSI or the CSI clocks from several means: ++ - SiP SMC service ++ - Periodic calibration every X seconds ++ ++This feature requires that a HW timer is assigned to the calibration sequence. ++ ++- st,hsi-cal: used to enable HSI clock calibration feature. ++ ++- st,csi-cal: used to enable CSI clock calibration feature. ++ ++- st,cal-sec: used to enable periodic calibration every specified seconds from ++ secure monitor. Time must be given in seconds. If not specified, calibration ++ is processed for each incoming request. ++ ++Example: ++ &rcc { ++ st,hsi-cal; ++ st,csi-cal; ++ st,cal-sec = <15>; ++ secure-interrupts = ; ++ secure-interrupt-names = "wakeup"; ++ }; ++ ++ ++Clocks and Operating Performance Points ++======================================= ++ ++- st,clk_opp node: This node will contain all operating point configurations. ++ We can have 3 operating points: ++ - st,ck_mpu ++ - st,ck_axi ++ - ck_mlahbs ++ These nodes are not mandatory, but we have to respect the naming. ++ ++ Each node will contain a list of operating point configurations (cfg_1, cfg_2...) ++ ++ These configuration subnodes contain these properties: ++ ++ mandatory parameters: ++ -hz: Operating point frequency in hertz ++ ++ -st,clksrc: The clock source (same syntax of 'st,clksrc' property below) ++ ++ optional parameters: ++ -st,clkdiv: The clock divider value (same syntax of 'st,clkdiv' property below) ++ ++ -st,pll: Phandle of the pll configuration (See description of 'pllx_cfgx' node) ++ ++ Note that this OPP configuration will be apllied at the run-time and will override the clock tree ++ configuration. ++ ++ Example: ++ st,clk_opp { ++ st,ck_mpu { ++ cfg_1 { ++ hz = < 900000000 >; ++ st,clksrc = < CLK_MPU_PLL1P >; ++ st,pll = < &pll1_cfg1 >; ++ }; ++ ++ cfg_2 { ++ hz = < 650000000 >; ++ st,clksrc = < CLK_MPU_PLL1P >; ++ st,pll = < &pll1_cfg2 >; ++ } ++ ++ ++Example of clock tree initialization and Operating Points Performance ++===================================================================== ++ ++/ { ++ 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,stm32mp13-rcc", "syscon"; ++ reg = <0x50000000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ interrupts = ; ++ secure-interrupts = ; ++ secure-interrupt-names = "wakeup"; ++ ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MLAHBS_PLL3 ++ CLK_RTC_LSE ++ CLK_MCO1_DISABLED ++ CLK_MCO2_DISABLED ++ CLK_CKPER_HSE ++ CLK_ETH1_PLL4P ++ CLK_ETH2_PLL4P ++ CLK_SDMMC1_PLL4P ++ CLK_SDMMC2_PLL4P ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_I2C4_HSI ++ CLK_USBO_USBPHY ++ CLK_ADC2_CKPER ++ CLK_I2C12_HSI ++ CLK_UART2_HSI ++ CLK_UART4_HSI ++ CLK_SAES_AXI ++ CLK_DCMIPP_PLL2Q ++ CLK_LPTIM3_PCLK3 ++ >; ++ ++ st,clkdiv = < ++ DIV(DIV_MPU, 1) ++ DIV(DIV_AXI, 0) ++ DIV(DIV_MLAHB, 0) ++ DIV(DIV_APB1, 1) ++ DIV(DIV_APB2, 1) ++ DIV(DIV_APB3, 1) ++ DIV(DIV_APB4, 1) ++ DIV(DIV_APB5, 2) ++ DIV(DIV_APB6, 1) ++ DIV(DIV_RTC, 0) ++ DIV(DIV_MCO1, 0) ++ DIV(DIV_MCO2, 0) ++ >; ++ ++ st,pll_vco { ++ pll1_vco_1800Mhz: pll1-vco-1800Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 1 74 >; ++ }; ++ ++ pll1_vco_1300Mhz: pll1-vco-1300Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 80 >; ++ frac = < 0x800 >; ++ }; ++ ++ pll2_vco_1066Mhz: pll2-vco-1066Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 65 >; ++ frac = < 0x1400 >; ++ }; ++ ++ pll3_vco_417_8Mhz: pll3-vco-417_8Mhz { ++ src = < CLK_PLL3_HSE >; ++ divmn = < 1 33 >; ++ frac = < 0x1a04 >; ++ }; ++ ++ pll4_vco_600Mhz: pll4-vco-600Mhz { ++ src = < CLK_PLL4_HSE >; ++ divmn = < 1 49 >; ++ }; ++ }; ++ ++ /* VCO = 1300.0 MHz => P = 650 (CPU) */ ++ pll1:st,pll@0 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ ++ st,pll = < &pll1_cfg1 >; ++ ++ pll1_cfg1: pll1_cfg1 { ++ st,pll_vco = < &pll1_vco_1300Mhz >; ++ st,pll_div_pqr = < 0 1 1 >; ++ }; ++ ++ pll1_cfg2: pll2_cfg1 { ++ st,pll_vco = < &pll1_vco_1800Mhz >; ++ st,pll_div_pqr = < 0 1 1 >; ++ }; ++ }; ++ ++ /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ ++ pll2:st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ ++ st,pll = < &pll2_cfg1 >; ++ ++ pll2_cfg1: pll2_cfg1 { ++ st,pll_vco = < &pll2_vco_1066Mhz >; ++ st,pll_div_pqr = < 1 0 1 >; ++ }; ++ }; ++ ++ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ ++ pll3:st,pll@2 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ ++ st,pll = < &pll3_cfg1 >; ++ ++ pll3_cfg1: pll3_cfg1 { ++ st,pll_vco = < &pll3_vco_417_8Mhz >; ++ st,pll_div_pqr = < 1 16 1 >; ++ }; ++ }; ++ ++ /* VCO = 600.0 MHz => P = 50, Q = 10, R = 100 */ ++ pll4:st,pll@3 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ st,pll = < &pll4_cfg1 >; ++ ++ pll4_cfg1: pll4_cfg1 { ++ st,pll_vco = < &pll4_vco_600Mhz >; ++ st,pll_div_pqr = < 11 59 5 >; ++ }; ++ }; ++ ++ st,clk_opp { ++ st,ck_mpu { ++ cfg_1 { ++ hz = < 900000000 >; ++ st,clksrc = < CLK_MPU_PLL1P >; ++ st,pll = < &pll1_cfg1 >; ++ }; ++ ++ cfg_2 { ++ hz = < 650000000 >; ++ st,clksrc = < CLK_MPU_PLL1P >; ++ st,pll = < &pll1_cfg2 >; ++ }; ++ ++ cfg_3 { ++ hz = < 450000000 >; ++ st,clksrc = < CLK_MPU_PLL1P_DIV >; ++ st,clkdiv = < DIV(DIV_MPU, 1) >; ++ st,pll = < &pll1_cfg1 >; ++ }; ++ ++ cfg_4 { ++ hz = <64000000>; ++ st,clksrc = < CLK_MPU_HSI >; ++ }; ++ ++ cfg_5 { ++ hz = <24000000>; ++ st,clksrc = < CLK_MPU_HSE >; ++ }; ++ }; ++ ++ st,ck_axi { ++ cfg_1 { ++ hz = <266500000>; ++ st,clksrc = < CLK_AXI_PLL2P >; ++ st,clkdiv = < DIV(DIV_AXI, 0) >; ++ st,pll = < &pll2_cfg1 >; ++ }; ++ ++ cfg_2 { ++ hz = <64000000>; ++ st,clksrc = < CLK_AXI_HSI>; ++ st,clkdiv = < DIV(DIV_AXI, 0) >; ++ }; ++ }; ++ ++ st,ck_mlahbs { ++ cfg_1 { ++ hz = <208877930>; ++ st,clksrc = < CLK_MLAHBS_PLL3 >; ++ st,clkdiv = < DIV(DIV_MLAHB, 0) >; ++ st,pll = < &pll3_cfg1 >; ++ }; ++ ++ cfg_2 { ++ hz = <12000000>; ++ st,clksrc = < CLK_MLAHBS_HSE>; ++ st,clkdiv = < DIV(DIV_MLAHB, 1) >; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; +diff --git a/docs/devicetree/bindings/i2c/i2c-stm32.txt b/docs/devicetree/bindings/i2c/i2c-stm32.txt +new file mode 100644 +index 000000000..68aefa6dc +--- /dev/null ++++ b/docs/devicetree/bindings/i2c/i2c-stm32.txt +@@ -0,0 +1,54 @@ ++* I2C controller embedded in STMicroelectronics STM32 I2C platform ++ ++Required properties : ++- compatible : Must be one of the following ++ - "st,stm32f7-i2c" ++- reg : Offset and length of the register set for the device ++- resets: Must contain the phandle to the reset controller. ++- clocks: Must contain the input clock of the I2C instance. ++- A pinctrl state named "default" must be defined to set pins in mode of ++ operation for I2C transfer. An optional pinctrl state named "sleep" has to ++ be defined as well as to put I2C in low power mode in suspend mode. ++- #address-cells = <1>; ++- #size-cells = <0>; ++ ++Optional properties : ++- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified, ++ the default 100 kHz frequency will be used. ++- i2c-scl-rising-time-ns : Only for STM32F7, I2C SCL Rising time for the board ++ (default: 25) ++- i2c-scl-falling-time-ns : Only for STM32F7, I2C SCL Falling time for the board ++ (default: 10) ++ I2C Timings are derived from these 2 values ++- st,syscfg-fmp: Only for STM32F7, use to set Fast Mode Plus bit within SYSCFG ++ whether Fast Mode Plus speed is selected by slave. ++ 1st cell : phandle to syscfg ++ 2nd cell : register offset within SYSCFG ++ 3rd cell : register bitmask for FMP bit ++ ++Example : ++ ++ i2c@40005400 { ++ compatible = "st,stm32f4-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x40005400 0x400>; ++ resets = <&rcc 277>; ++ clocks = <&rcc 0 149>; ++ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>; ++ pinctrl-names = "default"; ++ }; ++ ++ i2c@40005400 { ++ compatible = "st,stm32f7-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x40005400 0x400>; ++ resets = <&rcc STM32F7_APB1_RESET(I2C1)>; ++ clocks = <&rcc 1 CLK_I2C1>; ++ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>; ++ pinctrl-1 = <&i2c1_sda_pin_sleep>, <&i2c1_scl_pin_sleep>; ++ pinctrl-names = "default", "sleep"; ++ 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..ec610925b +--- /dev/null ++++ b/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt +@@ -0,0 +1,289 @@ ++ST,stm32mp1 DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL and DDRPHYC) ++ ++-------------------- ++Required properties: ++-------------------- ++- compatible : Should be "st,stm32mp1-ddr" for STM32MP15x ++ Should be "st,stm32mp13-ddr" for STM32MP13x ++- 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 STM32MP13x and 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 STM32MP13x and 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 STM32MP13x and 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 STM32MP13x: 11 values are requested in this order ++ SCHED ++ SCHED1 ++ PERFHPR1 ++ PERFLPR1 ++ PERFWR1 ++ PCFGR_0 ++ PCFGW_0 ++ PCFGQOS0_0 ++ PCFGQOS1_0 ++ PCFGWQOS0_0 ++ PCFGWQOS1_0 ++ ++ 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 STM32MP13x: 9 values are requested in this order ++ PGCR ++ ACIOCR ++ DXCCR ++ DSGCR ++ DCR ++ ODTCR ++ ZQ0CR1 ++ DX0GCR ++ DX1GCR ++ ++ 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 STM32MP13x and STM32MP15x: 10 values are requested in this order ++ PTR0 ++ PTR1 ++ PTR2 ++ DTPR0 ++ DTPR1 ++ DTPR2 ++ MR0 ++ MR1 ++ MR2 ++ MR3 ++ ++Example: ++ ++/ { ++ soc { ++ ddr: ddr@0x5A003000{ ++ compatible = "st,stm32mp1-ddr"; ++ ++ reg = <0x5A003000 0x550 ++ 0x5A004000 0x234>; ++ ++ clocks = <&rcc_clk AXIDCG>, ++ <&rcc_clk DDRC1>, ++ <&rcc_clk DDRC2>, ++ <&rcc_clk DDRPHYC>, ++ <&rcc_clk DDRCAPB>, ++ <&rcc_clk DDRPHYCAPB>; ++ ++ clock-names = "axidcg", ++ "ddrc1", ++ "ddrc2", ++ "ddrphyc", ++ "ddrcapb", ++ "ddrphycapb"; ++ ++ st,mem-name = "DDR3 2x4Gb 533MHz"; ++ st,mem-speed = <533000>; ++ st,mem-size = <0x40000000>; ++ ++ st,ctl-reg = < ++ 0x00040401 /*MSTR*/ ++ 0x00000010 /*MRCTRL0*/ ++ 0x00000000 /*MRCTRL1*/ ++ 0x00000000 /*DERATEEN*/ ++ 0x00800000 /*DERATEINT*/ ++ 0x00000000 /*PWRCTL*/ ++ 0x00400010 /*PWRTMG*/ ++ 0x00000000 /*HWLPCTL*/ ++ 0x00210000 /*RFSHCTL0*/ ++ 0x00000000 /*RFSHCTL3*/ ++ 0x00000000 /*CRCPARCTL0*/ ++ 0xC2000040 /*ZQCTL0*/ ++ 0x02050105 /*DFITMG0*/ ++ 0x00000202 /*DFITMG1*/ ++ 0x07000000 /*DFILPCFG0*/ ++ 0xC0400003 /*DFIUPD0*/ ++ 0x00000000 /*DFIUPD1*/ ++ 0x00000000 /*DFIUPD2*/ ++ 0x00000000 /*DFIPHYMSTR*/ ++ 0x00000001 /*ODTMAP*/ ++ 0x00000000 /*DBG0*/ ++ 0x00000000 /*DBG1*/ ++ 0x00000000 /*DBGCMD*/ ++ 0x00000000 /*POISONCFG*/ ++ 0x00000010 /*PCCFG*/ ++ >; ++ ++ st,ctl-timing = < ++ 0x0080008A /*RFSHTMG*/ ++ 0x121B2414 /*DRAMTMG0*/ ++ 0x000D041B /*DRAMTMG1*/ ++ 0x0607080E /*DRAMTMG2*/ ++ 0x0050400C /*DRAMTMG3*/ ++ 0x07040407 /*DRAMTMG4*/ ++ 0x06060303 /*DRAMTMG5*/ ++ 0x02020002 /*DRAMTMG6*/ ++ 0x00000202 /*DRAMTMG7*/ ++ 0x00001005 /*DRAMTMG8*/ ++ 0x000D041B /*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*/ ++ >; ++ ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/docs/devicetree/bindings/mmc/mmci.txt b/docs/devicetree/bindings/mmc/mmci.txt +new file mode 100644 +index 000000000..6d3c626e0 +--- /dev/null ++++ b/docs/devicetree/bindings/mmc/mmci.txt +@@ -0,0 +1,72 @@ ++* ARM PrimeCell MultiMedia Card Interface (MMCI) PL180/1 ++ ++The ARM PrimeCell MMCI PL180 and PL181 provides an interface for ++reading and writing to MultiMedia and SD cards alike. ++ ++This file documents differences between the core properties described ++by mmc.txt and the properties used by the mmci driver. Using "st" as ++the prefix for a property, indicates support by the ST Micro variant. ++ ++Required properties: ++- compatible : contains "arm,pl18x", "arm,primecell". ++- vmmc-supply : phandle to the regulator device tree node, mentioned ++ as the VCC/VDD supply in the eMMC/SD specs. ++ ++Optional properties: ++- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides ++ the ID provided by the HW ++- resets : phandle to internal reset line. ++ Should be defined for sdmmc variant. ++- vqmmc-supply : phandle to the regulator device tree node, mentioned ++ as the VCCQ/VDD_IO supply in the eMMC/SD specs. ++specific for ux500 variant: ++- st,sig-dir-dat0 : bus signal direction pin used for DAT[0]. ++- st,sig-dir-dat2 : bus signal direction pin used for DAT[2]. ++- st,sig-dir-dat31 : bus signal direction pin used for DAT[3] and DAT[1]. ++- st,sig-dir-dat74 : bus signal direction pin used for DAT[4] to DAT[7]. ++- st,sig-dir-cmd : cmd signal direction pin used for CMD. ++- st,sig-pin-fbclk : feedback clock signal pin used. ++ ++specific for sdmmc variant: ++- st,sig-dir : signal direction polarity used for cmd, dat0 dat123. ++- st,neg-edge : data & command phase relation, generated on ++ sd clock falling edge. ++- st,use-ckin : use ckin pin from an external driver to sample ++ the receive data (example: with voltage ++ switch transceiver). ++ ++Deprecated properties: ++- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable. ++- mmc-cap-sd-highspeed : indicates whether SD is high speed capable. ++ ++Example: ++ ++sdi0_per1@80126000 { ++ compatible = "arm,pl18x", "arm,primecell"; ++ reg = <0x80126000 0x1000>; ++ interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>; ++ ++ dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */ ++ <&dma 29 0 0x0>; /* Logical - MemToDev */ ++ dma-names = "rx", "tx"; ++ ++ clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>; ++ clock-names = "sdi", "apb_pclk"; ++ ++ max-frequency = <100000000>; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ cd-gpios = <&gpio2 31 0x4>; // 95 ++ st,sig-dir-dat0; ++ st,sig-dir-dat2; ++ st,sig-dir-cmd; ++ st,sig-pin-fbclk; ++ ++ vmmc-supply = <&ab8500_ldo_aux3_reg>; ++ vqmmc-supply = <&vmmci>; ++ ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&sdi0_default_mode>; ++ pinctrl-1 = <&sdi0_sleep_mode>; ++}; +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 000000000..51576a384 +--- /dev/null ++++ b/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt +@@ -0,0 +1,22 @@ ++* STMicroelectronics STM32 SDMMC2 controller ++ ++The highspeed MMC host controller on STM32 soc family ++provides an interface for MMC, SD and SDIO types of memory cards. ++ ++This file documents differences between the core properties described ++by mmci.txt and the properties used by the sdmmc2 driver. ++ ++Required properties: ++ - compatible: should be one of: ++ "st,stm32-sdmmc2" ++ ++Example: ++ sdmmc1: sdmmc@0x58005000 { ++ compatible = "st,stm32-sdmmc2"; ++ reg = <0x58005000 0x1000>; ++ clocks = <&rcc SDMMC1_K>; ++ resets = <&rcc SDMMC1_R>; ++ cap-sd-highspeed; ++ cap-mmc-highspeed; ++ status = "disabled"; ++ }; +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 000000000..22779b05a +--- /dev/null ++++ b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt +@@ -0,0 +1,43 @@ ++STMicroelectronics STM32MP1 Power Management Controller ++======================================================= ++ ++The PWR IP is responsible for handling the power related resources such as ++clocks, power supplies and resets. It provides 6 wake-up pins that are handled ++by an interrupt-controller. Wake-up pin can be used to wake-up from STANDBY SoC ++state. ++ ++Required properties: ++- compatible should be: "st,stm32mp1-pwr", "st,stm32-pwr" ++- reg: should be register base and length as documented in the ++ datasheet ++ ++Optional Properties: ++- Nodes corresponding to PSCI commands issued by kernel: ++ - system_suspend_supported_soc_modes: list of supported SoC modes in suspend ++ - system_off_soc_mode: SoC mode for shutdown ++ - st,retram-enabled-in-standby-ddr-sr: enable retram during standby-ddr-sr ++ ++The list of SoC modes is in include/dt-bindings/power/stm32mp1-power.h: ++ - modes for system_suspend ++ 1 -> STM32_PM_CSTOP_ALLOW_STOP ++ 2 -> STM32_PM_CSTOP_ALLOW_LP_STOP ++ 3 -> STM32_PM_CSTOP_ALLOW_LPLV_STOP ++ 4 -> STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR ++ - modes for system_off ++ 6 -> STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF ++ 7 -> STM32_PM_SHUTDOWN ++ ++Example: ++ ++pwr: pwr@50001000 { ++ compatible = "st,stm32mp1-pwr", "st,stm32-pwr", "syscon", "simple-mfd"; ++ reg = <0x50001000 0x400>; ++ ++ 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 = ; ++}; +diff --git a/docs/devicetree/bindings/power/st,stpmic1.txt b/docs/devicetree/bindings/power/st,stpmic1.txt +new file mode 100644 +index 000000000..83307d23b +--- /dev/null ++++ b/docs/devicetree/bindings/power/st,stpmic1.txt +@@ -0,0 +1,94 @@ ++* STMicroelectronics STPMIC1 Power Management IC ++ ++Required parent device properties: ++- compatible: "st,stpmic1" ++- reg: The I2C slave address for the STPMIC1 chip. ++- interrupts: The interrupt lines the device is connected to. ++ The second interrupt is used for wake-up. ++- #interrupt-cells: Should be 2. ++- interrupt-controller: Describes the STPMIC1 as an interrupt ++ controller (has its own domain). Interrupt number are the following: ++ /* Interrupt Register 1 (0x50 for latch) */ ++ IT_SWOUT_R=0 ++ IT_SWOUT_F=1 ++ IT_VBUS_OTG_R=2 ++ IT_VBUS_OTG_F=3 ++ IT_WAKEUP_R=4 ++ IT_WAKEUP_F=5 ++ IT_PONKEY_R=6 ++ IT_PONKEY_F=7 ++ /* Interrupt Register 2 (0x51 for latch) */ ++ IT_OVP_BOOST=8 ++ IT_OCP_BOOST=9 ++ IT_OCP_SWOUT=10 ++ IT_OCP_OTG=11 ++ IT_CURLIM_BUCK4=12 ++ IT_CURLIM_BUCK3=13 ++ IT_CURLIM_BUCK2=14 ++ IT_CURLIM_BUCK1=15 ++ /* Interrupt Register 3 (0x52 for latch) */ ++ IT_SHORT_SWOUT=16 ++ IT_SHORT_SWOTG=17 ++ IT_CURLIM_LDO6=18 ++ IT_CURLIM_LDO5=19 ++ IT_CURLIM_LDO4=20 ++ IT_CURLIM_LDO3=21 ++ IT_CURLIM_LDO2=22 ++ IT_CURLIM_LDO1=23 ++ /* Interrupt Register 3 (0x52 for latch) */ ++ IT_SWIN_R=24 ++ IT_SWIN_F=25 ++ IT_RESERVED_1=26 ++ IT_RESERVED_2=27 ++ IT_VINLOW_R=28 ++ IT_VINLOW_F=29 ++ IT_TWARN_R=30 ++ IT_TWARN_F=31 ++ ++STPMIC1 consists in a varied group of sub-devices. ++Each sub-device binding is be described in own documentation file. ++ ++Device Description ++------ ------------ ++st,stpmic1-onkey : Power on key, see ../input/st,stpmic1-onkey.txt ++st,stpmic1-regulators : Regulators, see ../regulator/st,stpmic1-regulator.txt ++st,stpmic1-wdt : Watchdog, see ../watchdog/st,stpmic1-wdt.txt ++ ++Example: ++ ++pmic: pmic@33 { ++ compatible = "st,stpmic1"; ++ reg = <0x33>; ++ interrupt-parent = <&gpioa>; ++ interrupts = <0 2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ onkey { ++ compatible = "st,stpmic1-onkey"; ++ interrupts = ,; ++ interrupt-names = "onkey-falling", "onkey-rising"; ++ power-off-time-sec = <10>; ++ }; ++ ++ watchdog { ++ compatible = "st,stpmic1-wdt"; ++ }; ++ ++ regulators { ++ compatible = "st,stpmic1-regulators"; ++ ++ vdd_core: buck1 { ++ regulator-name = "vdd_core"; ++ regulator-boot-on; ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1200000>; ++ }; ++ vdd: buck3 { ++ regulator-name = "vdd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-pull-down; ++ }; ++ }; +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 000000000..b4edaf7c7 +--- /dev/null ++++ b/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt +@@ -0,0 +1,6 @@ ++STMicroelectronics STM32MP1 Peripheral Reset Controller ++======================================================= ++ ++The RCC IP is both a reset and a clock controller. ++ ++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 000000000..3c613d791 +--- /dev/null ++++ b/docs/devicetree/bindings/rng/st,stm32-rng.txt +@@ -0,0 +1,23 @@ ++STMicroelectronics STM32 HW RNG ++=============================== ++ ++The STM32 hardware random number generator is a simple fixed purpose IP and ++is fully separated from other crypto functions. ++ ++Required properties: ++ ++- compatible : Should be "st,stm32-rng" ++- reg : Should be register base and length as documented in the datasheet ++- clocks : The clock needed to enable the RNG ++ ++Optional properties: ++- resets : The reset to properly start RNG ++- clock-error-detect : Enable the clock detection management ++ ++Example: ++ ++ rng: rng@50060800 { ++ compatible = "st,stm32-rng"; ++ reg = <0x50060800 0x400>; ++ clocks = <&rcc 0 38>; ++ }; +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 000000000..08b499045 +--- /dev/null ++++ b/docs/devicetree/bindings/serial/st,stm32-usart.txt +@@ -0,0 +1,88 @@ ++* STMicroelectronics STM32 USART ++ ++Required properties: ++- compatible: can be either: ++ - "st,stm32-uart", ++ - "st,stm32f7-uart", ++ - "st,stm32h7-uart". ++ depending is compatible with stm32(f4), stm32f7 or stm32h7. ++- reg: The address and length of the peripheral registers space ++- interrupts: ++ - The interrupt line for the USART instance, ++ - An optional wake-up interrupt. ++- interrupt-names: Contains "event" for the USART interrupt line. ++- clocks: The input clock of the USART instance ++ ++Optional properties: ++- resets: Must contain the phandle to the reset controller. ++- pinctrl-names: Set to "default". An additional "sleep" state can be defined ++ to set pins in sleep state when in low power. In case the device is used as ++ a wakeup source, "idle" state is defined in order to keep RX pin active. ++ For a console device, an optional state "no_console_suspend" can be defined ++ to enable console messages during suspend. Typically, "no_console_suspend" and ++ "default" states can refer to the same pin configuration. ++- pinctrl-n: Phandle(s) pointing to pin configuration nodes. ++ For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt ++- st,hw-flow-ctrl: bool flag to enable hardware flow control. ++- rs485-rts-delay, rs485-rx-during-tx, rs485-rts-active-low, ++ linux,rs485-enabled-at-boot-time: see rs485.txt. ++- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt ++- dma-names: "rx" and/or "tx" ++- wakeup-source: bool flag to indicate this device has wakeup capabilities ++- interrupt-names : Should contain "wakeup" if optional wake-up interrupt is ++ used. ++ ++Note for dma using: ++- "tx" dma can be used without any constraint since it uses single ++dma transfers. ++- "rx" dma using requires some attention: ++ 1) if you cannot anticipate the length of your received packets ++ and if your usart device embeds an internal fifo, then DON'T use ++ dma mode. ++ 2) if you enable dma mode WITHOUT mdma intermediate copy (cf. ++ stm32-dma.txt), then the availability of the received data will ++ depend on the dma driver policy and it may be delayed until dma ++ internal fifo is full. The usart driver will see this checking ++ the dma residue when rx interrupt (RXNE or RTO) occurs. ++ 3) if you enable dma mode WITH mdma intermediate copy (cf. ++ stm32-dma.txt) then the usart driver will never see the dma ++ residue becoming smaller than RX_BUF_P but it will get its ++ rx dma complete callback called when the cyclic transfer period ++ (RX_BUF_P) is reached. ++The three possibilities above are ordered from the most cpu time ++consuming one to the least one. The counterpart of this optimisation ++is the reception granularity achievable by the usart driver, from ++one byte up to RX_BUF_P. ++ ++Examples: ++usart4: serial@40004c00 { ++ compatible = "st,stm32-uart"; ++ reg = <0x40004c00 0x400>; ++ interrupts = <52>; ++ clocks = <&clk_pclk1>; ++ pinctrl-names = "default", "sleep", "idle", "no_console_suspend"; ++ pinctrl-0 = <&pinctrl_usart4>; ++ pinctrl-1 = <&pinctrl_usart4_sleep>; ++ pinctrl-2 = <&pinctrl_usart4_idle>; ++ pinctrl-3 = <&pinctrl_usart4>; ++}; ++ ++usart2: serial@40004400 { ++ compatible = "st,stm32-uart"; ++ reg = <0x40004400 0x400>; ++ interrupts = <38>; ++ clocks = <&clk_pclk1>; ++ st,hw-flow-ctrl; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rtscts>; ++}; ++ ++usart1: serial@40011000 { ++ compatible = "st,stm32-uart"; ++ reg = <0x40011000 0x400>; ++ interrupts = <37>; ++ clocks = <&rcc 0 164>; ++ dmas = <&dma2 2 4 0x414 0x0>, ++ <&dma2 7 4 0x414 0x0>; ++ dma-names = "rx", "tx"; ++}; +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 000000000..ec58557ad +--- /dev/null ++++ b/docs/devicetree/bindings/soc/st,stm32-etzpc.txt +@@ -0,0 +1,54 @@ ++STM32 ETZPC ++--------------------------------- ++ ++Required properties: ++- compatible: should be "st,stm32-etzpc" ++- reg: physical base address and length of the registers set for the device ++- clocks: reference to the clock entry ++ ++Optional property: ++- st,decprot: Configure option to properly set firewall for IPs. ++ ++Examples: ++etzpc: etzpc@5C007000 { ++ compatible = "st,stm32-etzpc"; ++ reg = <0x5C007000 0x400>; ++ clocks = <&rcc TZPC>; ++ }; ++ ++Firewall specifications ++======================= ++ ++DECPROT macro must be used to properly configure IP firewalling. It must ++specify ID, domain and locking register status. ++ ++The macro is defined in the binding header file [1]. ++ ++Example: ++ ... { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_I2C4_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_GPIOZ_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>; ++ }; ++ ++Specify Peripheral IDs ++======================= ++ ++Each peripheral is identified with a specific ID. Each platform defines the ++identifiers relevant to that platform. Peripheral IDs are defined in [1]. ++ ++Specify domain ++============== ++Firewall controls peripherals in specific domains: ++ ++DECPROT_S_RW 0x0 -> Read/write Secure ++DECPROT_NS_R_S_W 0x1 -> Non secure read / Read/write Secure ++DECPROT_MCU_ISOLATION 0x2 -> MCU access only ++DECPROT_NS_RW 0x3 -> Non secure read/write ++ ++ ++[1] include/dt-bindings/soc/st,stm32-etzpc.h ++ +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 000000000..424e18a5c +--- /dev/null ++++ b/docs/devicetree/bindings/soc/st,stm32-romem.txt +@@ -0,0 +1,52 @@ ++STMicroelectronics STM32 Factory-programmed data device tree bindings ++ ++This represents STM32 Factory-programmed read only non-volatile area: locked ++flash, OTP, read-only HW regs... This contains various information such as: ++analog calibration data for temperature sensor (e.g. TS_CAL1, TS_CAL2), ++internal vref (VREFIN_CAL), unique device ID... ++ ++Required properties: ++- compatible: Should be one of: ++ "st,stm32f4-otp" ++ "st,stm32mp13-bsec" ++ "st,stm32mp15-bsec" ++- reg: Offset and length of factory-programmed area. ++- #address-cells: Should be '<1>'. ++- #size-cells: Should be '<1>'. ++ ++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: efuse@1fff7800 { ++ compatible = "st,stm32f4-otp"; ++ reg = <0x1fff7800 0x400>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ /* Data cells: ts_cal1 at 0x1fff7a2c */ ++ ts_cal1: calib@22c { ++ reg = <0x22c 0x2>; ++ }; ++ ... ++ }; ++ ++Example on stm32mp15: ++ bsec: efuse@5c005000 { ++ compatible = "st,stm32mp15-bsec"; ++ reg = <0x5c005000 0x400>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mac_addr: mac_addr@e4 { ++ reg = <0xe4 0x8>; ++ st,non-secure-otp; ++ }; ++ ... ++ }; +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 000000000..dbd962ebc +--- /dev/null ++++ b/docs/devicetree/bindings/soc/st,stm32-stgen.txt +@@ -0,0 +1,18 @@ ++STMicroelectronics STM32 STGEN ++=============================== ++ ++The STM32 System Generic Counter generate a time count value. This ++is a 64 bits wide counter. ++ ++Required properties: ++ ++- compatible : Should be "st,stm32-stgen" ++- reg : Should be register base and length as documented in the datasheet ++ ++Example: ++ ++ stgen: stgen@5C008000 { ++ compatible = "st,stm32-stgen"; ++ reg = <0x5C008000 0x1000>; ++ status = "okay"; ++ }; +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 000000000..e903b466a +--- /dev/null ++++ b/docs/devicetree/bindings/soc/st,stm32-tamp.txt +@@ -0,0 +1,20 @@ ++STM32 TAMPER ++--------------------------------- ++ ++Required properties: ++- compatible: should be "st,stm32-tamp" ++- reg: physical base address and length of the registers set for the device ++- clocks: reference to the clock entry ++ ++Optional property: ++- st,out3-pc13: Configure option register to map OUT3 on PC13 ++- wakeup-source : Configure tamp as wakeup-src ++ ++Examples: ++tamp: tamp@5C00A000 { ++ compatible = "st,stm32-tamp"; ++ reg = <0x5C00A000 0x100>; ++ clocks = <&rcc_clk RTCAPB>; ++ st,out3-pc13; ++ wakeup-source; ++}; +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 000000000..2d35e978d +--- /dev/null ++++ b/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt +@@ -0,0 +1,27 @@ ++STM32 Independent WatchDoG (IWDG) ++--------------------------------- ++ ++Required properties: ++- compatible: should be "st,stm32mp1-iwdg". ++- reg: physical base address and length of the registers set for the device. ++- clocks: reference to the clock entry lsi. Additional pclk clock entry. ++ is required only for st,stm32mp1-iwdg. ++- clock-names: name of the clocks used. ++ "pclk", "lsi" for st,stm32mp1-iwdg. ++ ++Optional properties: ++- timeout-sec: Watchdog timeout value in seconds. ++- secure-timeout-sec: Watchdog early timeout management in seconds. ++- stm32,enable-on-stop: Keep watchdog enable during stop. ++- stm32,enable-on-standby: Keep watchdog enable durung standby. ++ ++Examples: ++ ++iwdg2: iwdg@5a002000 { ++ compatible = "st,stm32mp1-iwdg"; ++ reg = <0x5a002000 0x400>; ++ clocks = <&rcc IWDG2>, <&clk_lsi>; ++ clock-names = "pclk", "lsi"; ++ instance = <2>; ++ timeout-sec = <30>; ++}; +diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst +index 92ff39fdd..27bcca094 100644 +--- a/docs/getting_started/porting-guide.rst ++++ b/docs/getting_started/porting-guide.rst +@@ -787,6 +787,31 @@ The function returns 0 on success. Any other value means the counter value + either could not be updated or the authentication image descriptor indicates + that it is not allowed to be updated. + ++Function: plat_get_hashed_pk() ++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ ++:: ++ ++ Argument : void *, unsigned int, void **, unsigned int * ++ Return : int ++ ++This function is optional when Trusted Board Boot is enabled, and only ++used if the platform saves a hash of the ROTPK. ++First argument is the BER ROTPK. ++Second argument is its size. ++Third argument is used to return a pointer to a buffer, which hash should ++be the one saved in OTP ++Fourth argument is a pointer to return its size ++ ++Most platforms save the hash of the BER ROTPK, but some may save the hash of ++a non encapsulated public key or a platform specific encapsulated ROT public ++key. Defining this function allows to transform the BER ROTPK used to verify ++the signature to the buffer (a platform specific encapsulated public key) which ++hash is saved in OTP. ++ ++The function returns 0 on success. Any other value means the expected ++public key buffer cannot be extracted from the BER public key. ++ + Common mandatory function modifications + --------------------------------------- + +@@ -889,7 +914,7 @@ Function : plat_fwu_set_images_source() [when PSA_FWU_SUPPORT == 1] + + :: + +- Argument : struct fwu_metadata *metadata ++ Argument : const struct fwu_metadata *metadata + Return : void + + This function is mandatory when PSA_FWU_SUPPORT is enabled. +@@ -932,6 +957,25 @@ It returns '0' on success, otherwise a negative error value on error. + Alongside, returns device handle and image specification from the I/O policy + of the requested FWU metadata image. + ++Function : plat_fwu_get_boot_idx() [when PSA_FWU_SUPPORT == 1] ++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ ++:: ++ ++ Argument : void ++ Return : uint32_t ++ ++This function is mandatory when PSA_FWU_SUPPORT is enabled. It provides the ++means to retrieve the boot index value from the platform. The boot index is the ++bank from which the platform has booted the firmware images. ++ ++By default, the platform will read the metadata structure and try to boot from ++the active bank. If the platform fails to boot from the active bank due to ++reasons like an Authentication failure, or on crossing a set number of watchdog ++resets while booting from the active bank, the platform can then switch to boot ++from a different bank. This function then returns the bank that the platform ++should boot its images from. ++ + Common optional modifications + ----------------------------- + +diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst +index af302c628..2403b275a 100644 +--- a/docs/plat/stm32mp1.rst ++++ b/docs/plat/stm32mp1.rst +@@ -2,15 +2,34 @@ STMicroelectronics STM32MP1 + =========================== + + STM32MP1 is a microprocessor designed by STMicroelectronics +-based on a dual Arm Cortex-A7. ++based on Arm Cortex-A7. + It is an Armv7-A platform, using dedicated code from TF-A. +-The STM32MP1 chip also embeds a Cortex-M4. + More information can be found on `STM32MP1 Series`_ page. + + + STM32MP1 Versions + ----------------- +-The STM32MP1 series is available in 3 different lines which are pin-to-pin compatible: ++ ++There are 2 variants for STM32MP1: STM32MP13 and STM32MP15 ++ ++STM32MP13 Versions ++~~~~~~~~~~~~~~~~~~ ++The STM32MP13 series is available in 3 different lines which are pin-to-pin compatible: ++ ++- STM32MP131: Single Cortex-A7 core ++- STM32MP133: STM32MP131 + 2*CAN, ETH2(GMAC), ADC1 ++- STM32MP135: STM32MP133 + DCMIPP, LTDC ++ ++Each line comes with a security option (cryptography & secure boot) and a Cortex-A frequency option: ++ ++- A Cortex-A7 @ 650 MHz ++- C Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz ++- D Cortex-A7 @ 900 MHz ++- F Secure Boot + HW Crypto + Cortex-A7 @ 900 MHz ++ ++STM32MP15 Versions ++~~~~~~~~~~~~~~~~~~ ++The STM32MP15 series is available in 3 different lines which are pin-to-pin compatible: + + - STM32MP157: Dual Cortex-A7 cores, Cortex-M4 core @ 209 MHz, 3D GPU, DSI display interface and CAN FD + - STM32MP153: Dual Cortex-A7 cores, Cortex-M4 core @ 209 MHz and CAN FD +@@ -44,15 +63,6 @@ Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are + inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective + device tree blobs. + +-STM32IMAGE bootchain +-~~~~~~~~~~~~~~~~~~~~ +-Although still supported, this way of booting is not recommended. +-Pease use FIP instead. +-At compilation step, BL2, BL32 and DTB file are linked together in a single +-binary. The stm32image tool is also generated and the header is added to TF-A +-binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32. +-It can then be copied in the first partition of the boot device. +- + + Memory mapping + ~~~~~~~~~~~~~~ +@@ -115,6 +125,30 @@ Available storage medias are: + - ``STM32MP_SPI_NAND`` + - ``STM32MP_SPI_NOR`` + ++Serial boot devices: ++ ++- ``STM32MP_UART_PROGRAMMER`` ++- ``STM32MP_USB_PROGRAMMER`` ++ ++ ++Other configuration flags: ++ ++- | ``DTB_FILE_NAME``: to precise board device-tree blob to be used. ++ | Default: stm32mp157c-ev1.dtb ++- | ``STM32MP_EARLY_CONSOLE``: to enable early traces before clock driver is setup. ++ | Default: 0 (disabled) ++- | ``STM32MP_UART_BAUDRATE``: to select UART baud rate. ++ | Default: 115200 ++- | ``STM32_TF_VERSION``: to manage BL2 monotonic counter. ++ | Default: 0 ++- | ``DWL_BUFFER_BASE``: the 'serial boot' load address of FIP, ++ | default location (end of the first 128MB) is used when absent ++- | ``STM32MP13``: to select STM32MP13 variant configuration. ++ | Default: 0 ++- | ``STM32MP15``: to select STM32MP15 variant configuration. ++ | Default: 1 ++ ++ + Boot with FIP + ~~~~~~~~~~~~~ + You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary. +@@ -190,44 +224,41 @@ With OP-TEE: + BL32_EXTRA2=/tee-pageable_v2.bin + fip + ++Trusted Boot Board ++__________________ + +-STM32IMAGE bootchain +-~~~~~~~~~~~~~~~~~~~~ +-You need to add the following flag to the make command: +-``STM32MP_USE_STM32IMAGE=1`` +- +-To build with SP_min and support for SD-card boot: +- +-.. code:: bash +- +- make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ +- AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ +- STM32MP_USE_STM32IMAGE=1 +- +- cd +- make stm32mp15_trusted_defconfig +- make DEVICE_TREE=stm32mp157c-ev1 all +- +-To build TF-A with OP-TEE support for SD-card boot: +- +-.. code:: bash +- +- make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ +- AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ +- STM32MP_USE_STM32IMAGE=1 +- +- 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 +- +- +-The following build options are supported: ++.. code:: shell ++ ++ tools/cert_create/cert_create -n --rot-key "build/stm32mp1/debug/rot_key.pem" \ ++ --tfw-nvctr 0 \ ++ --ntfw-nvctr 0 \ ++ --key-alg ecdsa --hash-alg sha256 \ ++ --trusted-key-cert build/stm32mp1/cert_images/trusted-key-cert.key-crt \ ++ --tb-fw=build/stm32mp1/debug/bl2.bin \ ++ --tb-fw-cert build/stm32mp1/cert_images/trusted-boot-fw.key-crt\ ++ --tos-fw /tee-header_v2.bin \ ++ --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \ ++ --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \ ++ --tos-fw-extra1 /tee-pager_v2.bin \ ++ --tos-fw-extra2 /tee-pageable_v2.bin \ ++ --nt-fw /u-boot-nodtb.bin \ ++ --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \ ++ --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \ ++ --hw-config /u-boot.dtb \ ++ --fw-config build/stm32mp1/debug/fdts/fw-config.dtb ++ ++ tools/fiptool/fiptool create --tos-fw /tee-header_v2.bin \ ++ --tos-fw-extra1 /tee-pager_v2.bin \ ++ --tos-fw-extra2 /tee-pageable_v2.bin \ ++ --nt-fw /u-boot-nodtb.bin \ ++ --hw-config /u-boot.dtb \ ++ --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \ ++ --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \ ++ --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \ ++ --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \ ++ --trusted-key-cert build/stm32mp1/cert_images/trusted-key-cert.key-crt \ ++ --tb-fw-cert build/stm32mp1/cert_images/trusted-boot-fw.key-crt stm32mp1.fip + +-- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. + + + Populate SD-card +@@ -243,22 +274,6 @@ It should contain at least those partitions: + + Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. + +-STM32IMAGE bootchain +-~~~~~~~~~~~~~~~~~~~~ +-The SD-card has to be formatted 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. +- +-OP-TEE artifacts go into separate partitions as follows: +- +-- teeh: tee-header_v2.stm32 +-- teed: tee-pageable_v2.stm32 +-- teex: tee-pager_v2.stm32 +- + + .. _STM32MP1 Series: https://www.st.com/en/microcontrollers-microprocessors/stm32mp1-series.html + .. _STM32MP1 part number codification: https://wiki.st.com/stm32mpu/wiki/STM32MP15_microprocessor#Part_number_codification +diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c +index 917ee4a28..b4f3949f3 100644 +--- a/drivers/auth/auth_mod.c ++++ b/drivers/auth/auth_mod.c +@@ -31,6 +31,7 @@ + } while (0) + + #pragma weak plat_set_nv_ctr2 ++#pragma weak plat_get_hashed_pk + + + static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a, +@@ -202,6 +203,10 @@ static int auth_signature(const auth_method_param_sig_t *param, + NOTICE("ROTPK is not deployed on platform. " + "Skipping ROTPK verification.\n"); + } else { ++ /* platform may store the hash of a prefixed, suffixed or modified pk */ ++ rc = plat_get_hashed_pk(pk_ptr, pk_len, &pk_ptr, &pk_len); ++ return_if_error(rc); ++ + /* Ask the crypto-module to verify the key hash */ + rc = crypto_mod_verify_hash(pk_ptr, pk_len, + pk_hash_ptr, pk_hash_len); +@@ -301,6 +306,15 @@ int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused, + return plat_set_nv_ctr(cookie, nv_ctr); + } + ++int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, ++ void **hashed_pk_ptr, unsigned int *hashed_pk_len) ++{ ++ *hashed_pk_ptr = full_pk_ptr; ++ *hashed_pk_len = full_pk_len; ++ ++ return 0; ++} ++ + /* + * Return the parent id in the output parameter '*parent_id' + * +diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk +index 53ebe30b6..ace4312cf 100644 +--- a/drivers/auth/mbedtls/mbedtls_common.mk ++++ b/drivers/auth/mbedtls/mbedtls_common.mk +@@ -16,7 +16,7 @@ endif + MBEDTLS_INC = -I${MBEDTLS_DIR}/include + + # Specify mbed TLS configuration file +-MBEDTLS_CONFIG_FILE := "" ++MBEDTLS_CONFIG_FILE ?= "" + $(eval $(call add_define,MBEDTLS_CONFIG_FILE)) + + MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_common.c +diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c +index 129566bd6..7b3ecd1a3 100644 +--- a/drivers/auth/mbedtls/mbedtls_x509_parser.c ++++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c +@@ -114,10 +114,10 @@ static int get_ext(const char *oid, void **ext, unsigned int *ext_len) + oid_len = mbedtls_oid_get_numeric_string(oid_str, + MAX_OID_STR_LEN, + &extn_oid); +- if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { ++ if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) { + return IMG_PARSER_ERR; + } +- if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { ++ if (((size_t)oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { + *ext = (void *)p; + *ext_len = (unsigned int)len; + return IMG_PARSER_OK; +diff --git a/drivers/auth/tbbr/tbbr_cot_bl1.c b/drivers/auth/tbbr/tbbr_cot_bl1.c +index e4c92213a..15a35431d 100644 +--- a/drivers/auth/tbbr/tbbr_cot_bl1.c ++++ b/drivers/auth/tbbr/tbbr_cot_bl1.c +@@ -150,21 +150,6 @@ static const auth_img_desc_t tb_fw_config = { + } + }; + +-static const auth_img_desc_t fw_config = { +- .img_id = FW_CONFIG_ID, +- .img_type = IMG_RAW, +- .parent = &trusted_boot_fw_cert, +- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { +- [0] = { +- .type = AUTH_METHOD_HASH, +- .param.hash = { +- .data = &raw_data, +- .hash = &fw_config_hash +- } +- } +- } +-}; +- + /* + * TBBR Chain of trust definition + */ +diff --git a/drivers/auth/tbbr/tbbr_cot_bl2.c b/drivers/auth/tbbr/tbbr_cot_bl2.c +index 65a0478ab..de7ad8f90 100644 +--- a/drivers/auth/tbbr/tbbr_cot_bl2.c ++++ b/drivers/auth/tbbr/tbbr_cot_bl2.c +@@ -671,6 +671,7 @@ static const auth_img_desc_t * const cot_desc[] = { + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, + [NT_FW_CONFIG_ID] = &nt_fw_config, ++ [FW_CONFIG_ID] = &fw_config, + #if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert, + [SP_PKG1_ID] = &sp_pkg1, +diff --git a/drivers/auth/tbbr/tbbr_cot_common.c b/drivers/auth/tbbr/tbbr_cot_common.c +index ff3f22de1..279f30e2e 100644 +--- a/drivers/auth/tbbr/tbbr_cot_common.c ++++ b/drivers/auth/tbbr/tbbr_cot_common.c +@@ -124,3 +124,18 @@ const auth_img_desc_t hw_config = { + } + } + }; ++ ++const auth_img_desc_t fw_config = { ++ .img_id = FW_CONFIG_ID, ++ .img_type = IMG_RAW, ++ .parent = &trusted_boot_fw_cert, ++ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { ++ [0] = { ++ .type = AUTH_METHOD_HASH, ++ .param.hash = { ++ .data = &raw_data, ++ .hash = &fw_config_hash ++ } ++ } ++ } ++}; +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +new file mode 100644 +index 000000000..b3000ff76 +--- /dev/null ++++ b/drivers/clk/clk.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved ++ * Author(s): Ludovic Barre, for STMicroelectronics. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++static const struct clk_ops *ops; ++ ++int clk_enable(unsigned long id) ++{ ++ assert((ops != NULL) && (ops->enable != NULL)); ++ ++ return ops->enable(id); ++} ++ ++void clk_disable(unsigned long id) ++{ ++ assert((ops != NULL) && (ops->disable != NULL)); ++ ++ ops->disable(id); ++} ++ ++unsigned long clk_get_rate(unsigned long id) ++{ ++ assert((ops != NULL) && (ops->get_rate != NULL)); ++ ++ return ops->get_rate(id); ++} ++ ++int clk_get_parent(unsigned long id) ++{ ++ assert((ops != NULL) && (ops->get_parent != NULL)); ++ ++ return ops->get_parent(id); ++} ++ ++bool clk_is_enabled(unsigned long id) ++{ ++ assert((ops != NULL) && (ops->is_enabled != NULL)); ++ ++ return ops->is_enabled(id); ++} ++ ++/* ++ * Initialize the clk. The fields in the provided clk ++ * ops pointer must be valid. ++ */ ++void clk_register(const struct clk_ops *ops_ptr) ++{ ++ assert((ops_ptr != NULL) && ++ (ops_ptr->enable != NULL) && ++ (ops_ptr->disable != NULL) && ++ (ops_ptr->get_rate != NULL) && ++ (ops_ptr->get_parent != NULL) && ++ (ops_ptr->is_enabled != NULL)); ++ ++ ops = ops_ptr; ++} +diff --git a/drivers/fwu/fwu.c b/drivers/fwu/fwu.c +index 7cb4c2982..55da110a9 100644 +--- a/drivers/fwu/fwu.c ++++ b/drivers/fwu/fwu.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -25,7 +25,7 @@ CASSERT((offsetof(struct fwu_metadata, crc_32) == 0), + crc_32_must_be_first_member_of_structure); + + static struct fwu_metadata metadata; +-static bool is_fwu_initialized; ++static bool is_metadata_initialized; + + /******************************************************************************* + * Compute CRC32 of the FWU metadata, and check it against the CRC32 value +@@ -142,7 +142,7 @@ bool fwu_is_trial_run_state(void) + { + bool trial_run = false; + +- assert(is_fwu_initialized == true); ++ assert(is_metadata_initialized); + + for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { + struct fwu_image_entry *entry = &metadata.img_entry[i]; +@@ -157,6 +157,13 @@ bool fwu_is_trial_run_state(void) + return trial_run; + } + ++const struct fwu_metadata *fwu_get_metadata(void) ++{ ++ assert(is_metadata_initialized); ++ ++ return &metadata; ++} ++ + /******************************************************************************* + * Load verified copy of FWU metadata image kept in the platform NV storage + * into local FWU metadata structure. +@@ -181,7 +188,7 @@ void fwu_init(void) + } + } + +- plat_fwu_set_images_source(&metadata); ++ is_metadata_initialized = true; + +- is_fwu_initialized = true; ++ plat_fwu_set_images_source(&metadata); + } +diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c +index c327e71d2..2671bf4ee 100644 +--- a/drivers/mmc/mmc.c ++++ b/drivers/mmc/mmc.c +@@ -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); + } + ++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) + { +@@ -357,6 +363,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; +@@ -524,7 +557,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/mtd/nand/core.c b/drivers/mtd/nand/core.c +index 9f0331ad7..ce697b238 100644 +--- a/drivers/mtd/nand/core.c ++++ b/drivers/mtd/nand/core.c +@@ -19,7 +19,18 @@ + * 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]; ++ ++#pragma weak plat_get_scratch_buffer ++void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size) ++{ ++ static uint8_t scratch_buff[PLATFORM_MTD_MAX_PAGE_SIZE]; ++ ++ assert(buffer_addr != NULL); ++ assert(buf_size != NULL); ++ ++ *buffer_addr = (void *)scratch_buff; ++ *buf_size = sizeof(scratch_buff); ++} + + int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read) +@@ -34,6 +45,12 @@ int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + unsigned int bytes_read; + int is_bad; + int ret; ++ uint8_t *scratch_buff; ++ size_t scratch_buff_size; ++ ++ plat_get_scratch_buffer((void **)&scratch_buff, &scratch_buff_size); ++ ++ assert(scratch_buff != NULL); + + VERBOSE("Block %u - %u, page_start %u, nb %u, length %zu, offset %u\n", + block, end_block, page_start, nb_pages, length, offset); +@@ -41,7 +58,7 @@ int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + *length_read = 0UL; + + if (((start_offset != 0U) || (length % nand_dev.page_size) != 0U) && +- (sizeof(scratch_buff) < nand_dev.page_size)) { ++ (scratch_buff_size < nand_dev.page_size)) { + return -EINVAL; + } + +diff --git a/drivers/partition/gpt.c b/drivers/partition/gpt.c +index 1b804deef..4fe832244 100644 +--- a/drivers/partition/gpt.c ++++ b/drivers/partition/gpt.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -9,6 +9,7 @@ + #include + + #include ++#include + #include + #include + +@@ -57,5 +58,8 @@ int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry) + entry->length = (uint64_t)(gpt_entry->last_lba - + gpt_entry->first_lba + 1) * + PLAT_PARTITION_BLOCK_SIZE; ++ guidcpy(&entry->part_guid, &gpt_entry->unique_uuid); ++ guidcpy(&entry->type_guid, &gpt_entry->type_uuid); ++ + return 0; + } +diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c +index fdea10dbd..a8fdf6566 100644 +--- a/drivers/partition/partition.c ++++ b/drivers/partition/partition.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -11,6 +11,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -246,6 +247,32 @@ const partition_entry_t *get_partition_entry(const char *name) + return NULL; + } + ++const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid) ++{ ++ int i; ++ ++ for (i = 0; i < list.entry_count; i++) { ++ if (guidcmp(type_uuid, &list.list[i].type_guid) == 0) { ++ return &list.list[i]; ++ } ++ } ++ ++ return NULL; ++} ++ ++const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) ++{ ++ int i; ++ ++ for (i = 0; i < list.entry_count; i++) { ++ if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) { ++ return &list.list[i]; ++ } ++ } ++ ++ return NULL; ++} ++ + const partition_entry_list_t *get_partition_entry_list(void) + { + return &list; +diff --git a/drivers/regulator/regulator_core.c b/drivers/regulator/regulator_core.c +new file mode 100644 +index 000000000..05a1b4511 +--- /dev/null ++++ b/drivers/regulator/regulator_core.c +@@ -0,0 +1,1131 @@ ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#define MAX_PROPERTY_LEN 64 ++ ++static struct rdev rdev_array[PLAT_NB_RDEVS]; ++ ++#pragma weak plat_get_lp_mode_name ++const char *plat_get_lp_mode_name(int mode) ++{ ++ return NULL; ++} ++ ++#define for_each_rdev(rdev) \ ++ for (rdev = rdev_array; rdev < (rdev_array + PLAT_NB_RDEVS); rdev++) ++ ++#define for_each_registered_rdev(rdev) \ ++ for (rdev = rdev_array; \ ++ (rdev < (rdev_array + PLAT_NB_RDEVS)) && (rdev->desc != NULL); rdev++) ++ ++static void lock_driver(const struct rdev *rdev) ++{ ++ if (rdev->desc->ops->lock != NULL) { ++ rdev->desc->ops->lock(rdev->desc); ++ } ++} ++ ++static void unlock_driver(const struct rdev *rdev) ++{ ++ if (rdev->desc->ops->unlock != NULL) { ++ rdev->desc->ops->unlock(rdev->desc); ++ } ++} ++ ++static struct rdev *regulator_get_by_phandle(int32_t phandle) ++{ ++ struct rdev *rdev; ++ ++ for_each_registered_rdev(rdev) { ++ if (rdev->phandle == phandle) { ++ return rdev; ++ } ++ } ++ ++ WARN("%s: phandle %d not found\n", __func__, phandle); ++ return NULL; ++} ++ ++/* ++ * Get a regulator from its node name ++ * ++ * @fdt - pointer to device tree memory ++ * @node_name - name of the node "ldo1" ++ * Return pointer to rdev if succeed, NULL else. ++ */ ++struct rdev *regulator_get_by_name(const char *node_name) ++{ ++ struct rdev *rdev; ++ ++ assert(node_name != NULL); ++ VERBOSE("get %s\n", node_name); ++ ++ for_each_registered_rdev(rdev) { ++ if (strcmp(rdev->desc->node_name, node_name) == 0) { ++ return rdev; ++ } ++ } ++ ++ WARN("%s: %s not found\n", __func__, node_name); ++ return NULL; ++} ++ ++static int32_t get_supply_phandle(const void *fdt, int node, const char *name) ++{ ++ const fdt32_t *cuint; ++ int len __unused; ++ int supply_phandle = -FDT_ERR_NOTFOUND; ++ char prop_name[MAX_PROPERTY_LEN]; ++ ++ len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name); ++ assert((len >= 0) && (len < MAX_PROPERTY_LEN - 1)); ++ ++ cuint = fdt_getprop(fdt, node, prop_name, NULL); ++ if (cuint != NULL) { ++ supply_phandle = fdt32_to_cpu(*cuint); ++ VERBOSE("%s: supplied by %d\n", name, supply_phandle); ++ } ++ ++ return supply_phandle; ++} ++ ++/* ++ * Get a regulator from a supply name ++ * ++ * @fdt - pointer to device tree memory ++ * @node - offset of the node that contains the supply description ++ * @name - name of the supply "vdd" for "vdd-supply' ++ * Return pointer to rdev if succeed, NULL else. ++ */ ++struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name) ++{ ++ const int p = get_supply_phandle(fdt, node, name); ++ ++ if (p < 0) { ++ return NULL; ++ } ++ ++ return regulator_get_by_phandle(p); ++} ++ ++static int __regulator_set_state(struct rdev *rdev, bool state) ++{ ++ if (rdev->desc->ops->set_state == NULL) { ++ return -ENODEV; ++ } ++ ++ return rdev->desc->ops->set_state(rdev->desc, state); ++} ++ ++#if defined(IMAGE_BL32) ++/* ++ * Enable regulator supply ++ * Enable regulator if use_count == 0 ++ * Apply ramp delay ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++static int __regulator_enable(struct rdev *rdev) ++{ ++ VERBOSE("%s: en\n", rdev->desc->node_name); ++ ++ if (rdev->desc->ops->set_state == NULL) { ++ return -ENODEV; ++ } ++ ++ if (rdev->supply_dev != NULL) ++ regulator_enable(rdev->supply_dev); ++ ++ lock_driver(rdev); ++ ++ if (rdev->use_count == 0) { ++ int ret; ++ ++ ret = __regulator_set_state(rdev, STATE_ENABLE); ++ if (ret != 0) { ++ ERROR("regul %s set state failed: err:%d\n", ++ rdev->desc->node_name, ret); ++ unlock_driver(rdev); ++ return ret; ++ } ++ ++ udelay(rdev->enable_ramp_delay); ++ } ++ ++ rdev->use_count++; ++ ++ assert(rdev->use_count != UINT8_MAX); ++ ++ VERBOSE("%s: en count:%u\n", rdev->desc->node_name, rdev->use_count); ++ ++ unlock_driver(rdev); ++ ++ return 0; ++} ++ ++/* ++ * Enable regulator ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_enable(struct rdev *rdev) ++{ ++ assert(rdev != NULL); ++ ++ if (rdev->flags & REGUL_ALWAYS_ON) { ++ return 0; ++ } ++ ++ return __regulator_enable(rdev); ++} ++ ++/* ++ * Disable regulator if use_count fall to zero ++ * Warn if count is < 0 because too many disable were requested ++ * Disable regulator supply ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++static int __regulator_disable(struct rdev *rdev) ++{ ++ VERBOSE("%s: dis\n", rdev->desc->node_name); ++ ++ if (rdev->desc->ops->set_state == NULL) { ++ return -ENODEV; ++ } ++ ++ lock_driver(rdev); ++ ++ if (rdev->use_count == 1) { ++ int ret; ++ ++ ret = __regulator_set_state(rdev, STATE_DISABLE); ++ if (ret != 0) { ++ ERROR("regul %s set state failed: err:%d\n", ++ rdev->desc->node_name, ret); ++ unlock_driver(rdev); ++ return ret; ++ } ++ } ++ ++ if (rdev->use_count == 0) { ++ WARN("regulator %s unbalanced disable\n", rdev->desc->node_name); ++ } else { ++ rdev->use_count--; ++ } ++ ++ VERBOSE("%s: dis count:%u\n", rdev->desc->node_name, rdev->use_count); ++ ++ unlock_driver(rdev); ++ ++ if (rdev->supply_dev != NULL) { ++ regulator_disable(rdev->supply_dev); ++ } ++ ++ return 0; ++} ++ ++/* ++ * Disable regulator ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_disable(struct rdev *rdev) ++{ ++ assert(rdev != NULL); ++ ++ if (rdev->flags & REGUL_ALWAYS_ON) { ++ return 0; ++ } ++ ++ return __regulator_disable(rdev); ++} ++#else ++/* ++ * Enable regulator ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_enable(struct rdev *rdev) ++{ ++ int ret; ++ ++ assert(rdev != NULL); ++ ++ ret = __regulator_set_state(rdev, STATE_ENABLE); ++ ++ udelay(rdev->enable_ramp_delay); ++ ++ return ret; ++} ++ ++/* ++ * Disable regulator ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_disable(struct rdev *rdev) ++{ ++ int ret; ++ ++ assert(rdev != NULL); ++ ++ if (rdev->flags & REGUL_ALWAYS_ON) { ++ return 0; ++ } ++ ++ ret = __regulator_set_state(rdev, STATE_DISABLE); ++ ++ udelay(rdev->enable_ramp_delay); ++ ++ return ret; ++} ++#endif ++ ++/* ++ * Regulator enabled query ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if disabled, 1 if enabled, <0 else. ++ */ ++int regulator_is_enabled(const struct rdev *rdev) ++{ ++ int ret = 0; ++ ++ assert(rdev != NULL); ++ ++ VERBOSE("%s: is en\n", rdev->desc->node_name); ++ ++ if (rdev->desc->ops->get_state == NULL) { ++ return -ENODEV; ++ } ++ ++ lock_driver(rdev); ++ ++ ret = rdev->desc->ops->get_state(rdev->desc); ++ if (ret < 0) { ++ ERROR("regul %s get state failed: err:%d\n", ++ rdev->desc->node_name, ret); ++ } ++ ++ unlock_driver(rdev); ++ ++ return ret; ++} ++ ++/* ++ * Set regulator voltage ++ * ++ * @rdev - pointer to rdev struct ++ * @mvolt - Target voltage level in millivolt ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt) ++{ ++ int ret = 0; ++ ++ assert(rdev != NULL); ++ ++ VERBOSE("%s: set mvolt\n", rdev->desc->node_name); ++ ++ if (rdev->desc->ops->set_voltage == NULL) { ++ return -ENODEV; ++ } ++ ++ if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) { ++ return -EPERM; ++ } ++ ++ lock_driver(rdev); ++ ++ ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt); ++ if (ret < 0) { ++ ERROR("regul %s set volt failed: err:%d\n", ++ rdev->desc->node_name, ret); ++ } ++ ++ unlock_driver(rdev); ++ ++ return ret; ++} ++ ++/* ++ * Set regulator min voltage ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_set_min_voltage(struct rdev *rdev) ++{ ++ return regulator_set_voltage(rdev, rdev->min_mv); ++} ++ ++/* ++ * Get regulator voltage ++ * ++ * @rdev - pointer to rdev struct ++ * Return milli volts if succeed, <0 else. ++ */ ++int regulator_get_voltage(const struct rdev *rdev) ++{ ++ int ret = 0; ++ ++ assert(rdev != NULL); ++ ++ VERBOSE("%s: get volt\n", rdev->desc->node_name); ++ ++ if (rdev->desc->ops->get_voltage == NULL) { ++ return rdev->min_mv; ++ } ++ ++ lock_driver(rdev); ++ ++ ret = rdev->desc->ops->get_voltage(rdev->desc); ++ if (ret < 0) { ++ ERROR("regul %s get voltage failed: err:%d\n", ++ rdev->desc->node_name, ret); ++ } ++ ++ unlock_driver(rdev); ++ ++ return ret; ++} ++ ++/* ++ * List regulator voltages ++ * ++ * @rdev - pointer to rdev struct ++ * @levels - out: array of supported millitvolt levels from min to max value ++ * @count - out: number of possible millivolt values ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count) ++{ ++ int ret; ++ size_t n; ++ ++ assert(rdev != NULL); ++ assert(levels != NULL); ++ assert(count != NULL); ++ ++ VERBOSE("%s: list volt\n", rdev->desc->node_name); ++ ++ if (rdev->desc->ops->list_voltages == NULL) { ++ return -ENODEV; ++ } ++ ++ lock_driver(rdev); ++ ++ ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count); ++ ++ unlock_driver(rdev); ++ ++ if (ret < 0) { ++ ERROR("regul %s list_voltages failed: err: %d\n", ++ rdev->desc->node_name, ret); ++ return ret; ++ } ++ ++ /* ++ * Reduce the possible values depending on min and max from device-tree ++ */ ++ n = *count; ++ while (((*levels)[n - 1U] > rdev->max_mv) && (n > 1U)) { ++ n--; ++ } ++ ++ /* Verify that max val is a valid value */ ++ if (rdev->max_mv != (*levels)[n - 1]) { ++ ERROR("regul %s: max value %u is invalid\n", ++ rdev->desc->node_name, rdev->max_mv); ++ return -EINVAL; ++ } ++ ++ while (((*levels[0U]) < rdev->min_mv) && (n > 1U)) { ++ (*levels)++; ++ n--; ++ } ++ ++ /* Verify that min is not too high */ ++ if (n == 0U) { ++ ERROR("regul %s set min voltage is too high\n", ++ rdev->desc->node_name); ++ return -EINVAL; ++ } ++ ++ /* Verify that min val is a valid vlue */ ++ if (rdev->min_mv != (*levels)[0U]) { ++ ERROR("regul %s: min value %u is invalid\n", ++ rdev->desc->node_name, rdev->min_mv); ++ return -EINVAL; ++ } ++ ++ *count = n; ++ ++ VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv); ++ ++ return 0; ++} ++ ++/* ++ * Get regulator voltages range ++ * ++ * @rdev - pointer to rdev struct ++ * @min_mv - out: min possible millivolt value ++ * @max_mv - out: max possible millivolt value ++ * Return 0 if succeed, non 0 else. ++ */ ++void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv) ++{ ++ assert(rdev != NULL); ++ ++ if (min_mv != NULL) { ++ *min_mv = rdev->min_mv; ++ } ++ if (max_mv != NULL) { ++ *max_mv = rdev->max_mv; ++ } ++} ++ ++/* ++ * Set regulator flag ++ * ++ * @rdev - pointer to rdev struct ++ * @flag - flag value to set (eg: REGUL_OCP) ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_set_flag(struct rdev *rdev, uint16_t flag) ++{ ++ int ret; ++ ++ /* check that only one bit is set on flag */ ++ if (__builtin_popcount(flag) != 1) { ++ return -EINVAL; ++ } ++ ++ /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */ ++ if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) { ++ rdev->flags |= flag; ++ return 0; ++ } ++ ++ if (rdev->desc->ops->set_flag == NULL) { ++ ERROR("%s can not set any flag\n", rdev->desc->node_name); ++ return -ENODEV; ++ } ++ ++ lock_driver(rdev); ++ ++ ret = rdev->desc->ops->set_flag(rdev->desc, flag); ++ ++ unlock_driver(rdev); ++ ++ if (ret != 0) { ++ ERROR("%s: could not set flag %d ret=%d\n", ++ rdev->desc->node_name, flag, ret); ++ return ret; ++ } ++ ++ rdev->flags |= flag; ++ ++ return 0; ++} ++ ++#if defined(IMAGE_BL32) ++ ++struct regul_property { ++ char *name; ++ uint16_t flag; ++}; ++ ++static struct regul_property flag_prop[] = { ++ { ++ .name = "regulator-always-on", ++ .flag = REGUL_ALWAYS_ON, ++ }, ++ { ++ .name = "regulator-boot-on", ++ .flag = REGUL_BOOT_ON, ++ }, ++ { ++ .name = "regulator-active-discharge", ++ .flag = REGUL_ACTIVE_DISCHARGE, ++ }, ++ { ++ .name = "regulator-over-current-protection", ++ .flag = REGUL_OCP, ++ }, ++ { ++ .name = "regulator-pull-down", ++ .flag = REGUL_PULL_DOWN, ++ }, ++ { ++ .name = "st,mask-reset", ++ .flag = REGUL_MASK_RESET, ++ }, ++ { ++ .name = "st,regulator-sink-source", ++ .flag = REGUL_SINK_SOURCE, ++ }, ++ { ++ .name = "st,regulator-bypass", ++ .flag = REGUL_ENABLE_BYPASS, ++ }, ++}; ++ ++static int parse_properties(const void *fdt, struct rdev *rdev, int node) ++{ ++ const fdt32_t *cuint; ++ int ret = 0; ++ struct regul_property *prop; ++ ++ for (prop = flag_prop; prop < (flag_prop + ARRAY_SIZE(flag_prop)); prop++) { ++ if (fdt_getprop(fdt, node, prop->name, NULL) != NULL) { ++ VERBOSE("%s: prop 0x%x\n", rdev->desc->node_name, prop->flag); ++ ret = regulator_set_flag(rdev, prop->flag); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, node, "regulator-enable-ramp-delay", NULL); ++ if (cuint != NULL) { ++ rdev->enable_ramp_delay = (uint32_t)(fdt32_to_cpu(*cuint)); ++ VERBOSE("%s: enable_ramp_delay=%u\n", rdev->desc->node_name, ++ rdev->enable_ramp_delay); ++ } ++ ++ rdev->reg_name = fdt_getprop(fdt, node, "regulator-name", NULL); ++ ++ return 0; ++} ++ ++static void parse_supply(const void *fdt, struct rdev *rdev, int node) ++{ ++ const char *name = rdev->desc->supply_name; ++ ++ if (name == NULL) { ++ name = rdev->desc->node_name; ++ } ++ ++ rdev->supply_phandle = get_supply_phandle(fdt, node, name); ++ if (rdev->supply_phandle < 0) { ++ node = fdt_parent_offset(fdt, node); ++ rdev->supply_phandle = get_supply_phandle(fdt, node, name); ++ } ++} ++ ++static void parse_low_power_mode(const void *fdt, struct rdev *rdev, int node, int mode) ++{ ++ const fdt32_t *cuint; ++ ++ rdev->lp_state[mode] = 0; ++ ++ if (fdt_getprop(fdt, node, "regulator-off-in-suspend", NULL) != NULL) { ++ VERBOSE("%s: mode:%d OFF\n", rdev->desc->node_name, mode); ++ rdev->lp_state[mode] |= LP_STATE_OFF; ++ } else if (fdt_getprop(fdt, node, "regulator-on-in-suspend", NULL) != NULL) { ++ VERBOSE("%s: mode:%d ON\n", rdev->desc->node_name, mode); ++ rdev->lp_state[mode] |= LP_STATE_ON; ++ } else { ++ rdev->lp_state[mode] |= LP_STATE_UNCHANGED; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "regulator-suspend-microvolt", NULL); ++ if (cuint != NULL) { ++ uint16_t mv; ++ ++ mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); ++ VERBOSE("%s: mode:%d suspend mv=%u\n", rdev->desc->node_name, ++ mode, mv); ++ ++ rdev->lp_state[mode] |= LP_STATE_SET_VOLT; ++ rdev->lp_mv[mode] = mv; ++ } ++} ++ ++static void parse_low_power_modes(const void *fdt, struct rdev *rdev, int node) ++{ ++ int i; ++ ++ for (i = 0; i < PLAT_NB_SUSPEND_MODES; i++) { ++ const char *lp_mode_name = plat_get_lp_mode_name(i); ++ int n; ++ ++ if (lp_mode_name == NULL) { ++ continue; ++ } ++ ++ /* Get the configs from regulator_state_node subnode */ ++ n = fdt_subnode_offset(fdt, node, lp_mode_name); ++ if (n >= 0) { ++ parse_low_power_mode(fdt, rdev, n, i); ++ } ++ } ++} ++#else ++static int parse_properties(const void *fdt, struct rdev *rdev, int node) ++{ ++ int ret; ++ ++ if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { ++ VERBOSE("%s: set regulator-always-on\n", rdev->desc->node_name); ++ ret = regulator_set_flag(rdev, REGUL_ALWAYS_ON); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++/* ++ * Parse the device-tree for a regulator ++ * ++ * Read min/max voltage from dt and check its validity ++ * Read the properties, and call the driver to set flags ++ * Read power supply phandle ++ * Read and store low power mode states ++ * ++ * @rdev - pointer to rdev struct ++ * @node - device-tree node offset of the regulator ++ * Return 0 if disabled, 1 if enabled, <0 else. ++ */ ++static int parse_dt(struct rdev *rdev, int node) ++{ ++ void *fdt; ++ const fdt32_t *cuint; ++ const uint16_t *levels; ++ size_t size; ++ int ret = 0; ++ ++ VERBOSE("%s: parse dt\n", rdev->desc->node_name); ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ rdev->phandle = fdt_get_phandle(fdt, node); ++ ++ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); ++ if (cuint != NULL) { ++ uint16_t min_mv; ++ ++ min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); ++ VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv); ++ if (min_mv <= rdev->max_mv) { ++ rdev->min_mv = min_mv; ++ } else { ++ ERROR("%s: min_mv=%d is too high\n", ++ rdev->desc->node_name, (int)min_mv); ++ return -EINVAL; ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); ++ if (cuint != NULL) { ++ uint16_t max_mv; ++ ++ max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); ++ VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv); ++ if (max_mv >= rdev->min_mv) { ++ rdev->max_mv = max_mv; ++ } else { ++ ERROR("%s: max_mv=%d is too low\n", ++ rdev->desc->node_name, (int)max_mv); ++ return -EINVAL; ++ } ++ } ++ ++ /* validate that min and max values can be used */ ++ ret = regulator_list_voltages(rdev, &levels, &size); ++ if ((ret != 0) && (ret != -ENODEV)) { ++ return ret; ++ } ++ ++ ret = parse_properties(fdt, rdev, node); ++ if (ret != 0) { ++ return ret; ++ } ++ ++#if defined(IMAGE_BL32) ++ parse_supply(fdt, rdev, node); ++ ++ parse_low_power_modes(fdt, rdev, node); ++#endif ++ ++ return 0; ++} ++ ++/* ++ * Register a regulator driver in regulator framework. ++ * Initialize voltage range from driver description ++ * ++ * @desc - pointer to the regulator description ++ * @node - device-tree node offset of the regulator ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_register(const struct regul_description *desc, int node) ++{ ++ struct rdev *rdev; ++ ++ assert(desc != NULL); ++ ++ VERBOSE("register %s\n", desc->node_name); ++ ++ for_each_rdev(rdev) { ++ if (rdev->desc == NULL) { ++ break; ++ } ++ } ++ ++ if (rdev == rdev_array + PLAT_NB_RDEVS) { ++ WARN("out of memory\n"); ++ return -ENOMEM; ++ } ++ ++ rdev->desc = desc; ++ rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay; ++ ++ if (rdev->desc->ops->list_voltages != NULL) { ++ int ret = 0; ++ const uint16_t *levels; ++ size_t count; ++ ++ lock_driver(rdev); ++ ++ ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count); ++ ++ unlock_driver(rdev); ++ ++ if (ret < 0) { ++ ERROR("regul %s set state failed: err:%d\n", ++ rdev->desc->node_name, ret); ++ return ret; ++ } ++ ++ rdev->min_mv = levels[0]; ++ rdev->max_mv = levels[count - 1U]; ++ } else { ++ rdev->max_mv = UINT16_MAX; ++ } ++ ++ return parse_dt(rdev, node); ++} ++ ++#if defined(IMAGE_BL32) ++/* ++ * Suspend a single regulator before low power entry ++ * Call regulator suspend call back, ++ * Enable the regulator if boot_on flag is set as regulator is needed during ++ * boot/resume from suspend sequences. ++ * ++ * @rdev - pointer to rdev struct ++ * @mode - low power mode index ++ * Return 0 if succeed, non 0 else. ++ */ ++static int suspend_regulator(struct rdev *rdev, int mode) ++{ ++ int ret = 0; ++ ++ if (rdev->desc->ops->suspend != NULL) { ++ lock_driver(rdev); ++ ret = rdev->desc->ops->suspend(rdev->desc, ++ rdev->lp_state[mode], ++ rdev->lp_mv[mode]); ++ unlock_driver(rdev); ++ if (ret != 0) { ++ ERROR("%s failed to suspend: %d\n", rdev->desc->node_name, ret); ++ return ret; ++ } ++ } ++ ++ if (rdev->flags & REGUL_BOOT_ON) { ++ ret = regulator_enable(rdev); ++ } ++ ++ return ret; ++} ++ ++/* ++ * Resume a single regulator after low power ++ * ++ * @rdev - pointer to rdev struct ++ * Return 0 if succeed, non 0 else. ++ */ ++static int resume_regulator(struct rdev *rdev) ++{ ++ int ret = 0; ++ ++ if (rdev->flags & REGUL_BOOT_ON) { ++ /* Revert to the state it was before suspend */ ++ ret = regulator_disable(rdev); ++ if (ret != 0) { ++ ERROR("%s failed to resume: %d\n", rdev->desc->node_name, ret); ++ } ++ } ++ ++ return ret; ++} ++ ++/* ++ * Suspend regulators before entering low power ++ * ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_core_suspend(int mode) ++{ ++ struct rdev *rdev; ++ ++ VERBOSE("Regulator core suspend\n"); ++ ++ if (mode >= PLAT_NB_SUSPEND_MODES) { ++ return -EINVAL; ++ } ++ ++ /* Suspend each regulator */ ++ for_each_registered_rdev(rdev) { ++ if (suspend_regulator(rdev, mode) != 0) { ++ panic(); ++ } ++ } ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ regulator_core_dump(); ++#endif ++ ++ return 0; ++} ++ ++/* ++ * Resume regulators from low power ++ * ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_core_resume(void) ++{ ++ struct rdev *rdev; ++ ++ VERBOSE("Regulator core resume\n"); ++ ++ /* Resume each regulator */ ++ for_each_registered_rdev(rdev) { ++ if (resume_regulator(rdev) != 0) { ++ panic(); ++ } ++ } ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ regulator_core_dump(); ++#endif ++ ++ return 0; ++} ++ ++/* ++ * save regulators data ++ * ++ * @backup_area - pointer to save data ++ * @backup_size - size of the backup area ++ */ ++void regulator_core_backup_context(void *backup_area, size_t backup_size) ++{ ++ int8_t *data = (int8_t *)backup_area; ++ struct rdev *rdev; ++ ++ assert(data != NULL); ++ assert(backup_size == PLAT_BACKUP_REGULATOR_SIZE); ++ ++ for_each_rdev(rdev) { ++ *data = rdev->use_count; ++ data++; ++ } ++} ++ ++/* ++ * restore regulators data ++ * ++ * @backup_area - pointer to retrieve saved data ++ * @backup_size - size of the backup area ++ */ ++void regulator_core_restore_context(void *backup_area, size_t backup_size) ++{ ++ int8_t *data = (int8_t *)backup_area; ++ struct rdev *rdev; ++ ++ assert(data != NULL); ++ assert(backup_size == PLAT_BACKUP_REGULATOR_SIZE); ++ ++ for_each_rdev(rdev) { ++ rdev->use_count = *data; ++ data++; ++ } ++} ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++static void sprint_name(char *dest, const char *src, int len) ++{ ++ int l; ++ ++ if (src == NULL) { ++ src = ""; ++ } ++ ++ l = strlen(src); ++ if (l > len) { ++ l = len; ++ } ++ ++ memset(dest, ' ', len); ++ memcpy(dest, src, l); ++ dest[len] = 0; ++} ++ ++/* ++ * Log regulators state ++ */ ++void regulator_core_dump(void) ++{ ++ struct rdev *rdev; ++ ++ VERBOSE("Dump Regulators\n"); ++ ++ INFO("reg name use\ten\tmV\tmin\tmax\tflags\tsupply\n"); ++ ++ for_each_registered_rdev(rdev) { ++ uint16_t min_mv, max_mv; ++ char reg[9] = ""; ++ char name[9]; ++ const char *supply = ""; ++ ++ sprint_name(name, rdev->desc->node_name, 8); ++ sprint_name(reg, rdev->reg_name, 8); ++ ++ regulator_get_range(rdev, &min_mv, &max_mv); ++ if (rdev->supply_dev != NULL) ++ supply = rdev->supply_dev->desc->node_name; ++ ++ INFO("%s %s %d\t%d\t%d\t%d\t%d\t0x%x\t%s\n", ++ reg, name, ++ rdev->use_count, ++ regulator_is_enabled(rdev), ++ regulator_get_voltage(rdev), min_mv, max_mv, ++ rdev->flags, supply); ++ } ++} ++#endif ++ ++/* ++ * Connect each regulator to its supply ++ * Apply min voltage if the voltage is outside the authorized range ++ * Enable always-on regulators ++ * ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_core_config(void) ++{ ++ int ret; ++ struct rdev *rdev; ++ ++ VERBOSE("Regul Core config\n"); ++ ++ for_each_registered_rdev(rdev) { ++ if (rdev->supply_phandle >= 0) { ++ struct rdev *s; ++ ++ VERBOSE("%s: connect supply\n", rdev->desc->node_name); ++ ++ s = regulator_get_by_phandle(rdev->supply_phandle); ++ if (s == NULL) { ++ return -EINVAL; ++ } ++ ++ rdev->supply_dev = s; ++ } ++ } ++ ++ for_each_registered_rdev(rdev) { ++ uint16_t mv, min_mv, max_mv; ++ ++ regulator_get_range(rdev, &min_mv, &max_mv); ++ ++ ret = regulator_get_voltage(rdev); ++ if (ret >= 0) { ++ mv = ret; ++ if ((mv < min_mv) || (mv > max_mv)) { ++ ret = regulator_set_voltage(rdev, min_mv); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ } else { ++ return ret; ++ } ++ ++ /* ++ * Enable always-on regulator and increment its use_count so that ++ * the regulator is not being disabled during clean-up sequence. ++ */ ++ if (rdev->flags & REGUL_ALWAYS_ON) { ++ ret = __regulator_enable(rdev); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Sync hardware regulator state with use refcount ++ * ++ * Return 0 if succeed, non 0 else. ++ */ ++int regulator_core_cleanup(void) ++{ ++ struct rdev *rdev; ++ ++ VERBOSE("Regul Core cleanup\n"); ++ ++ for_each_registered_rdev(rdev) { ++ if (!(rdev->flags & REGUL_BOOT_ON)) { ++ if ((rdev->use_count == 0) && (regulator_is_enabled(rdev) == 1)) { ++ VERBOSE("disable %s during cleanup\n", rdev->desc->node_name); ++ /* force disable to synchronize the framework */ ++ __regulator_set_state(rdev, STATE_DISABLE); ++ } ++ } ++ } ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ regulator_core_dump(); ++#endif ++ ++ return 0; ++} ++ ++#endif +diff --git a/drivers/scmi-msg/base.c b/drivers/scmi-msg/base.c +index 2d7203451..522819c09 100644 +--- a/drivers/scmi-msg/base.c ++++ b/drivers/scmi-msg/base.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause + /* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. +- * Copyright (c) 2019-2020, Linaro Limited ++ * Copyright (c) 2019-2022, Linaro Limited + */ + #include + #include +@@ -165,7 +165,7 @@ static void discover_list_protocols(struct scmi_msg *msg) + memcpy(outargs, &p2a, sizeof(p2a)); + memcpy(outargs + sizeof(p2a), list + a2p->skip, count); + +- scmi_write_response(msg, outargs, sizeof(outargs)); ++ scmi_write_response(msg, outargs, sizeof(p2a) + round_up(count, sizeof(uint32_t))); + } + + static const scmi_msg_handler_t scmi_base_handler_table[] = { +diff --git a/drivers/scmi-msg/clock.c b/drivers/scmi-msg/clock.c +index e96cede6e..c169b8e69 100644 +--- a/drivers/scmi-msg/clock.c ++++ b/drivers/scmi-msg/clock.c +@@ -20,6 +20,8 @@ + #pragma weak plat_scmi_clock_set_rate + #pragma weak plat_scmi_clock_get_state + #pragma weak plat_scmi_clock_set_state ++#pragma weak plat_scmi_clock_get_duty_cycle ++#pragma weak plat_scmi_clock_get_round_rate + + static bool message_id_is_supported(unsigned int message_id); + +@@ -75,6 +77,21 @@ int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused, + return SCMI_NOT_SUPPORTED; + } + ++int32_t plat_scmi_clock_get_duty_cycle(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ unsigned int *num __unused, ++ unsigned int *den __unused) ++{ ++ return SCMI_NOT_SUPPORTED; ++} ++ ++int32_t plat_scmi_clock_get_round_rate(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused) ++{ ++ /* Return the clock rate */ ++ return plat_scmi_clock_get_rate(agent_id, scmi_id); ++} ++ + static void report_version(struct scmi_msg *msg) + { + struct scmi_protocol_version_p2a return_values = { +@@ -193,6 +210,35 @@ static void scmi_clock_rate_get(struct scmi_msg *msg) + scmi_write_response(msg, &return_values, sizeof(return_values)); + } + ++static void scmi_clock_round_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; ++ } ++ ++ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); ++ ++ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ rate = plat_scmi_clock_get_round_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; +@@ -220,6 +266,34 @@ static void scmi_clock_rate_set(struct scmi_msg *msg) + scmi_status_response(msg, status); + } + ++static void scmi_clock_duty_cycle_get(struct scmi_msg *msg) ++{ ++ const struct scmi_clock_duty_cycle_get_a2p *in_args = (void *)msg->in; ++ struct scmi_clock_duty_cycle_get_p2a return_values = { }; ++ unsigned int clock_id = 0U; ++ unsigned int numerator = 1U; ++ unsigned int denominator = 2U; ++ ++ if (msg->in_size != sizeof(*in_args)) { ++ scmi_status_response(msg, SCMI_PROTOCOL_ERROR); ++ return; ++ } ++ ++ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); ++ ++ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { ++ scmi_status_response(msg, SCMI_INVALID_PARAMETERS); ++ return; ++ } ++ ++ plat_scmi_clock_get_duty_cycle(msg->agent_id, clock_id, ++ &numerator, &denominator); ++ return_values.num = numerator; ++ return_values.den = denominator; ++ ++ scmi_write_response(msg, &return_values, sizeof(return_values)); ++} ++ + static void scmi_clock_config_set(struct scmi_msg *msg) + { + const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in; +@@ -359,6 +433,8 @@ static const scmi_msg_handler_t scmi_clock_handler_table[] = { + [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set, + [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get, + [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set, ++ [SCMI_CLOCK_DUTY_CYCLE_GET] = scmi_clock_duty_cycle_get, ++ [SCMI_CLOCK_ROUND_RATE_GET] = scmi_clock_round_rate_get, + }; + + static bool message_id_is_supported(size_t message_id) +diff --git a/drivers/scmi-msg/clock.h b/drivers/scmi-msg/clock.h +index a637934ee..eacbf0d27 100644 +--- a/drivers/scmi-msg/clock.h ++++ b/drivers/scmi-msg/clock.h +@@ -22,6 +22,8 @@ enum scmi_clock_command_id { + SCMI_CLOCK_RATE_SET = 0x005, + SCMI_CLOCK_RATE_GET = 0x006, + SCMI_CLOCK_CONFIG_SET = 0x007, ++ SCMI_CLOCK_DUTY_CYCLE_GET = 0x008, ++ SCMI_CLOCK_ROUND_RATE_GET = 0x009, + }; + + /* Protocol attributes */ +@@ -57,6 +59,16 @@ struct scmi_clock_rate_get_p2a { + uint32_t rate[2]; + }; + ++struct scmi_clock_duty_cycle_get_a2p { ++ uint32_t clock_id; ++}; ++ ++struct scmi_clock_duty_cycle_get_p2a { ++ int32_t status; ++ uint32_t num; ++ uint32_t den; ++}; ++ + /* + * Clock Rate Set + */ +diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec2.c +similarity index 63% +rename from drivers/st/bsec/bsec.c +rename to drivers/st/bsec/bsec2.c +index 01c369edc..6a8af5c13 100644 +--- a/drivers/st/bsec/bsec.c ++++ b/drivers/st/bsec/bsec2.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,11 +14,13 @@ + #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_VERSION_2_0 U(0x20) ++#define BSEC_IP_ID_2 U(0x100032) + + #define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) + +@@ -44,11 +46,23 @@ static void bsec_unlock(void) + } + } + ++static bool is_otp_invalid_mode(void) ++{ ++ bool ret = ((bsec_get_status() & BSEC_MODE_INVALID) == BSEC_MODE_INVALID); ++ ++ if (ret) { ++ ERROR("OTP mode is OTP-INVALID\n"); ++ } ++ ++ return ret; ++} ++ ++#if defined(IMAGE_BL32) + 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; + } +@@ -56,7 +70,6 @@ static int bsec_get_dt_node(struct dt_node_info *info) + return node; + } + +-#if defined(IMAGE_BL32) + static void enable_non_secure_access(uint32_t otp) + { + otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); +@@ -78,39 +91,85 @@ 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); + } + } + + return 0; + } ++ ++static void bsec_late_init(void) ++{ ++ 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(); ++ } ++ ++ assert(bsec_base == bsec_info.base); ++ ++ bsec_dt_otp_nsec_access(fdt, node); ++} + #endif + + static uint32_t otp_bank_offset(uint32_t otp) +@@ -121,19 +180,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; + } + +@@ -143,23 +213,20 @@ static uint32_t bsec_check_error(uint32_t otp) + */ + uint32_t bsec_probe(void) + { +- void *fdt; +- int node; +- struct dt_node_info bsec_info; ++ bsec_base = BSEC_BASE; + +- if (fdt_get_address(&fdt) == 0) { +- panic(); ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; + } + +- node = bsec_get_dt_node(&bsec_info); +- if (node < 0) { ++ if ((((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) && ++ ((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_2_0)) || ++ (bsec_get_id() != BSEC_IP_ID_2)) { + panic(); + } + +- bsec_base = bsec_info.base; +- + #if defined(IMAGE_BL32) +- bsec_dt_otp_nsec_access(fdt, node); ++ bsec_late_init(); + #endif + return BSEC_OK; + } +@@ -182,6 +249,10 @@ uint32_t bsec_set_config(struct bsec_config *cfg) + uint32_t value; + int32_t result; + ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } ++ + value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) & + BSEC_CONF_FRQ_MASK) | + (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) & +@@ -259,15 +330,21 @@ 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; ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } ++ ++ 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)) { +- VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n", ++ if (value) { ++ VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", + otp); + } + +@@ -283,14 +360,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 +387,18 @@ uint32_t bsec_shadow_register(uint32_t otp) + */ + uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) + { +- uint32_t result; ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } + + 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 +410,29 @@ 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; ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } ++ ++ 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)) { +- VERBOSE("BSEC: OTP %i is locked and write will be ignored\n", ++ if (value) { ++ VERBOSE("BSEC: OTP %u 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 +449,27 @@ 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; ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } ++ ++ 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; ++ } ++ ++ 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; + } + +- /* Check if programming of OTP is locked */ +- if (bsec_read_sp_lock(otp)) { ++ 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 +489,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 +500,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(); +@@ -438,6 +526,10 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp) + uint32_t data; + uint32_t addr; + ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } ++ + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } +@@ -464,10 +556,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 +568,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,35 +583,56 @@ 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. ++ * return value: none. + */ +-uint32_t bsec_write_debug_conf(uint32_t val) ++void bsec_write_debug_conf(uint32_t val) + { +- uint32_t result = BSEC_ERROR; +- uint32_t masked_val = val & BSEC_DEN_ALL_MSK; ++ if (is_otp_invalid_mode()) { ++ return; ++ } + + bsec_lock(); ++ mmio_write_32(bsec_base + BSEC_DEN_OFF, val & BSEC_DEN_ALL_MSK); ++ bsec_unlock(); ++} + +- mmio_write_32(bsec_base + BSEC_DEN_OFF, masked_val); ++/* ++ * bsec_read_debug_conf: return debug configuration register value. ++ */ ++uint32_t bsec_read_debug_conf(void) ++{ ++ return mmio_read_32(bsec_base + BSEC_DEN_OFF); ++} + +- if ((mmio_read_32(bsec_base + BSEC_DEN_OFF) ^ masked_val) == 0U) { +- result = BSEC_OK; ++/* ++ * bsec_write_scratch: write value in scratch register. ++ * val: value to write. ++ * return value: none. ++ */ ++void bsec_write_scratch(uint32_t val) ++{ ++#if defined(IMAGE_BL32) ++ if (is_otp_invalid_mode()) { ++ return; + } + ++ bsec_lock(); ++ mmio_write_32(bsec_base + BSEC_SCRATCH_OFF, val); + bsec_unlock(); +- +- return result; ++#else ++ mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val); ++#endif + } + + /* +- * bsec_read_debug_conf: read debug configuration. ++ * bsec_read_scratch: return scratch register value. + */ +-uint32_t bsec_read_debug_conf(void) ++uint32_t bsec_read_scratch(void) + { +- return mmio_read_32(bsec_base + BSEC_DEN_OFF); ++ return mmio_read_32(bsec_base + BSEC_SCRATCH_OFF); + } + + /* +@@ -533,7 +644,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 +652,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 +660,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 +668,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 +676,194 @@ 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; +- } ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } + +- /* +- * 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; ++ } ++ ++ 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; +- } ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } + +- /* +- * 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; ++ } ++ ++ 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; +- } ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } + +- /* +- * 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; + +- 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; + ++ if (is_otp_invalid_mode()) { ++ return BSEC_ERROR; ++ } ++ + 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 +875,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 +894,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 +916,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. +@@ -852,13 +927,13 @@ uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) + + result = bsec_shadow_register(word); + if (result != BSEC_OK) { +- ERROR("BSEC: %u Shadowing Error %i\n", word, result); ++ ERROR("BSEC: %u Shadowing Error %u\n", word, result); + return result; + } + + result = bsec_read_otp(otp_value, word); + if (result != BSEC_OK) { +- ERROR("BSEC: %u Read Error %i\n", word, result); ++ ERROR("BSEC: %u Read Error %u\n", word, result); + } + + return result; +@@ -867,7 +942,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 +952,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/clk-stm32-core.c b/drivers/st/clk/clk-stm32-core.c +new file mode 100644 +index 000000000..16a1c78b1 +--- /dev/null ++++ b/drivers/st/clk/clk-stm32-core.c +@@ -0,0 +1,1115 @@ ++/* ++ * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-stm32-core.h" ++ ++static struct spinlock reg_lock; ++static struct spinlock refcount_lock; ++ ++static struct stm32_clk_priv *stm32_clock_data; ++ ++const struct stm32_clk_ops clk_mux_ops; ++ ++struct stm32_clk_priv *clk_stm32_get_priv(void) ++{ ++ return stm32_clock_data; ++} ++ ++static void stm32mp1_clk_lock(struct spinlock *lock) ++{ ++ if (stm32mp_lock_available()) { ++ /* Assume interrupts are masked */ ++ spin_lock(lock); ++ } ++} ++ ++static void stm32mp1_clk_unlock(struct spinlock *lock) ++{ ++ if (stm32mp_lock_available()) { ++ spin_unlock(lock); ++ } ++} ++ ++void stm32mp1_clk_rcc_regs_lock(void) ++{ ++ stm32mp1_clk_lock(®_lock); ++} ++ ++void stm32mp1_clk_rcc_regs_unlock(void) ++{ ++ stm32mp1_clk_unlock(®_lock); ++} ++ ++#define TIMEOUT_US_1S U(1000000) ++#define OSCRDY_TIMEOUT TIMEOUT_US_1S ++ ++struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct stm32_osc_cfg *osc_cfg = clk->clock_cfg; ++ int osc_id = osc_cfg->osc_id; ++ ++ return &priv->osci_data[osc_id]; ++} ++ ++void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ struct stm32_clk_bypass *bypass_data = osc_data->bypass; ++ uintptr_t address; ++ ++ if (bypass_data == NULL) { ++ return; ++ } ++ ++ address = priv->base + bypass_data->offset; ++ ++ if (digbyp) { ++ mmio_setbits_32(address, BIT(bypass_data->bit_digbyp)); ++ } ++ ++ if (bypass || digbyp) { ++ mmio_setbits_32(address, BIT(bypass_data->bit_byp)); ++ } ++} ++ ++void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ struct stm32_clk_css *css_data = osc_data->css; ++ uintptr_t address; ++ ++ if (css_data == NULL) { ++ return; ++ } ++ ++ address = priv->base + css_data->offset; ++ ++ if (css) { ++ mmio_setbits_32(address, BIT(css_data->bit_css)); ++ } ++} ++ ++void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ struct stm32_clk_drive *drive_data = osc_data->drive; ++ uintptr_t address; ++ uint32_t mask; ++ uint32_t value; ++ ++ if (drive_data == NULL) { ++ return; ++ } ++ ++ address = priv->base + drive_data->offset; ++ ++ mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift; ++ ++ /* ++ * Warning: not recommended to switch directly from "high drive" ++ * to "medium low drive", and vice-versa. ++ */ ++ value = (mmio_read_32(address) & mask) >> drive_data->drv_shift; ++ ++ while (value != lsedrv) { ++ if (value > lsedrv) { ++ value--; ++ } else { ++ value++; ++ } ++ ++ mmio_clrsetbits_32(address, mask, value << drive_data->drv_shift); ++ } ++} ++ ++int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ return _clk_stm32_gate_wait_ready(priv, osc_data->gate_id, ready_on); ++} ++ ++int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id) ++{ ++ return clk_oscillator_wait_ready(priv, id, true); ++} ++ ++int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id) ++{ ++ return clk_oscillator_wait_ready(priv, id, false); ++} ++ ++static int clk_gate_enable(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_gate_cfg *cfg = clk->clock_cfg; ++ ++ stm32mp_mmio_setbits_32_shregs(priv->base + cfg->offset, BIT(cfg->bit_idx)); ++ ++ return 0; ++} ++ ++static void clk_gate_disable(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_gate_cfg *cfg = clk->clock_cfg; ++ ++ stm32mp_mmio_clrbits_32_shregs(priv->base + cfg->offset, BIT(cfg->bit_idx)); ++} ++ ++static bool clk_gate_is_enabled(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_gate_cfg *cfg = clk->clock_cfg; ++ ++ return ((mmio_read_32(priv->base + cfg->offset) & BIT(cfg->bit_idx)) != 0U); ++} ++ ++const struct stm32_clk_ops clk_gate_ops = { ++ .enable = clk_gate_enable, ++ .disable = clk_gate_disable, ++ .is_enabled = clk_gate_is_enabled, ++}; ++ ++void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id) ++{ ++ const struct gate_cfg *gate = &priv->gates[gate_id]; ++ uintptr_t addr = priv->base + gate->offset; ++ ++ if (gate->set_clr != 0U) { ++ mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); ++ } else { ++ stm32mp_mmio_clrbits_32_shregs(addr, BIT(gate->bit_idx)); ++ } ++} ++ ++int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id) ++{ ++ const struct gate_cfg *gate = &priv->gates[gate_id]; ++ uintptr_t addr = priv->base + gate->offset; ++ ++ if (gate->set_clr != 0U) { ++ mmio_write_32(addr, BIT(gate->bit_idx)); ++ ++ } else { ++ stm32mp_mmio_setbits_32_shregs(addr, BIT(gate->bit_idx)); ++ } ++ ++ return 0; ++} ++ ++const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id) ++{ ++ return priv->clks[id].name; ++} ++ ++const char *clk_stm32_get_name(struct stm32_clk_priv *priv, ++ unsigned long binding_id) ++{ ++ int id; ++ ++ id = clk_get_index(priv, binding_id); ++ if (id == -EINVAL) { ++ return NULL; ++ } ++ ++ return _clk_stm32_get_name(priv, id); ++} ++ ++const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id) ++{ ++ if ((unsigned int)id < priv->num) { ++ return &priv->clks[id]; ++ } ++ ++ return NULL; ++} ++ ++#define clk_div_mask(_width) GENMASK(((_width) - 1U), 0U) ++ ++static unsigned int _get_table_div(const struct clk_div_table *table, ++ unsigned int val) ++{ ++ const struct clk_div_table *clkt; ++ ++ for (clkt = table; clkt->div; clkt++) { ++ if (clkt->val == val) { ++ return clkt->div; ++ } ++ } ++ ++ return 0; ++} ++ ++static unsigned int _get_div(const struct clk_div_table *table, ++ unsigned int val, unsigned long flags, ++ uint8_t width) ++{ ++ if ((flags & CLK_DIVIDER_ONE_BASED) != 0UL) { ++ return val; ++ } ++ ++ if ((flags & CLK_DIVIDER_POWER_OF_TWO) != 0UL) { ++ return BIT(val); ++ } ++ ++ if ((flags & CLK_DIVIDER_MAX_AT_ZERO) != 0UL) { ++ return (val != 0U) ? val : BIT(width); ++ } ++ ++ if (table != NULL) { ++ return _get_table_div(table, val); ++ } ++ ++ return val + 1U; ++} ++ ++#define TIMEOUT_US_200MS U(200000) ++#define CLKSRC_TIMEOUT TIMEOUT_US_200MS ++ ++int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel) ++{ ++ const struct parent_cfg *parents = &priv->parents[pid & MUX_PARENT_MASK]; ++ const struct mux_cfg *mux = parents->mux; ++ uintptr_t address = priv->base + mux->offset; ++ uint32_t mask; ++ uint64_t timeout; ++ ++ mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); ++ ++ mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask); ++ ++ if (mux->bitrdy == MUX_NO_BIT_RDY) { ++ return 0; ++ } ++ ++ timeout = timeout_init_us(CLKSRC_TIMEOUT); ++ ++ mask = BIT(mux->bitrdy); ++ ++ while ((mmio_read_32(address) & mask) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int clk, int clkp) ++{ ++ const struct parent_cfg *parents; ++ uint16_t pid; ++ uint8_t sel; ++ int old_parent; ++ ++ pid = priv->clks[clk].parent; ++ ++ if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { ++ return -EINVAL; ++ } ++ ++ old_parent = _clk_stm32_get_parent(priv, clk); ++ if (old_parent < 0) { ++ return old_parent; ++ } ++ if (old_parent == clkp) { ++ return 0; ++ } ++ ++ parents = &priv->parents[pid & MUX_PARENT_MASK]; ++ ++ for (sel = 0; sel < parents->num_parents; sel++) { ++ if (parents->id_parents[sel] == (uint16_t)clkp) { ++ bool clk_was_enabled = _clk_stm32_is_enabled(priv, clk); ++ int err = 0; ++ ++ /* Enable the parents (for glitch free mux) */ ++ _clk_stm32_enable(priv, clkp); ++ _clk_stm32_enable(priv, old_parent); ++ ++ err = clk_mux_set_parent(priv, pid, sel); ++ ++ _clk_stm32_disable(priv, old_parent); ++ ++ if (clk_was_enabled) { ++ _clk_stm32_disable(priv, old_parent); ++ } ++ else { ++ _clk_stm32_disable(priv, clkp); ++ } ++ ++ return err; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id) ++{ ++ const struct parent_cfg *parent; ++ const struct mux_cfg *mux; ++ uint32_t mask; ++ ++ if (mux_id >= priv->nb_parents) { ++ panic(); ++ } ++ ++ parent = &priv->parents[mux_id]; ++ mux = parent->mux; ++ ++ mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); ++ ++ return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift; ++} ++ ++int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel) ++{ ++ uint16_t pid; ++ ++ pid = priv->clks[clk].parent; ++ ++ if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { ++ return -EINVAL; ++ } ++ ++ return clk_mux_set_parent(priv, pid, sel); ++} ++ ++int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int clk_id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, clk_id); ++ const struct parent_cfg *parent; ++ uint16_t mux_id; ++ int sel; ++ ++ mux_id = priv->clks[clk_id].parent; ++ if (mux_id == CLK_IS_ROOT) { ++ return CLK_IS_ROOT; ++ } ++ ++ if (mux_id < MUX_MAX_PARENTS) { ++ return mux_id & MUX_PARENT_MASK; ++ } ++ ++ mux_id &= MUX_PARENT_MASK; ++ parent = &priv->parents[mux_id]; ++ ++ if (clk->ops->get_parent != NULL) { ++ sel = clk->ops->get_parent(priv, clk_id); ++ } else { ++ sel = clk_mux_get_parent(priv, mux_id); ++ } ++ ++ if ((sel >= 0) && (sel < parent->num_parents)) { ++ return parent->id_parents[sel]; ++ } ++ ++ return -EINVAL; ++} ++ ++int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id) ++{ ++ uint16_t mux_id; ++ ++ mux_id = priv->clks[clk_id].parent; ++ if (mux_id == CLK_IS_ROOT) { ++ return CLK_IS_ROOT; ++ } ++ ++ if (mux_id < MUX_MAX_PARENTS) { ++ return mux_id & MUX_PARENT_MASK; ++ } ++ ++ mux_id &= MUX_PARENT_MASK; ++ ++ return clk_mux_get_parent(priv, mux_id); ++} ++ ++int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx) ++{ ++ const struct parent_cfg *parent; ++ uint16_t mux_id; ++ ++ mux_id = priv->clks[clk_id].parent; ++ if (mux_id == CLK_IS_ROOT) { ++ return CLK_IS_ROOT; ++ } ++ ++ if (mux_id < MUX_MAX_PARENTS) { ++ return mux_id & MUX_PARENT_MASK; ++ } ++ ++ mux_id &= MUX_PARENT_MASK; ++ parent = &priv->parents[mux_id]; ++ ++ if (idx < parent->num_parents) { ++ return parent->id_parents[idx]; ++ } ++ ++ return -EINVAL; ++} ++ ++int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id) ++{ ++ unsigned int i; ++ ++ for (i = 0U; i < priv->num; i++) { ++ if (binding_id == priv->clks[i].binding) { ++ return (int)i; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ int parent; ++ unsigned long rate = 0UL; ++ ++ if ((unsigned int)id >= priv->num) { ++ return rate; ++ } ++ ++ parent = _clk_stm32_get_parent(priv, id); ++ if (parent < 0) { ++ return 0UL; ++ } ++ ++ if (clk->ops->recalc_rate != NULL) { ++ unsigned long prate = 0UL; ++ ++ if (parent != CLK_IS_ROOT) { ++ prate = _clk_stm32_get_rate(priv, parent); ++ } ++ ++ rate = clk->ops->recalc_rate(priv, id, prate); ++ ++ return rate; ++ } ++ ++ switch (parent) { ++ case CLK_IS_ROOT: ++ panic(); ++ ++ default: ++ rate = _clk_stm32_get_rate(priv, parent); ++ break; ++ } ++ return rate; ++ ++} ++ ++unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id) ++{ ++ int parent_id = _clk_stm32_get_parent(priv, id); ++ ++ if (parent_id < 0) { ++ return 0UL; ++ } ++ ++ return _clk_stm32_get_rate(priv, parent_id); ++} ++ ++static uint8_t _stm32_clk_get_flags(struct stm32_clk_priv *priv, int id) ++{ ++ return priv->clks[id].flags; ++} ++ ++bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag) ++{ ++ if (_stm32_clk_get_flags(priv, id) & flag) { ++ return true; ++ } ++ ++ return false; ++} ++ ++int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ ++ if (clk->ops->enable != NULL) { ++ clk->ops->enable(priv, id); ++ } ++ ++ return 0; ++} ++ ++static int _clk_stm32_enable_core(struct stm32_clk_priv *priv, int id) ++{ ++ int parent; ++ int ret = 0; ++ ++ if (priv->gate_refcounts[id] == 0U) { ++ parent = _clk_stm32_get_parent(priv, id); ++ if (parent < 0) { ++ return parent; ++ } ++ if (parent != CLK_IS_ROOT) { ++ ret = _clk_stm32_enable_core(priv, parent); ++ if (ret) { ++ return ret; ++ } ++ } ++ clk_stm32_enable_call_ops(priv, id); ++ } ++ ++ priv->gate_refcounts[id]++; ++ ++ if (priv->gate_refcounts[id] == UINT_MAX) { ++ ERROR("%s: %d max enable count !", __func__, id); ++ panic(); ++ } ++ ++ return 0; ++} ++ ++int _clk_stm32_enable(struct stm32_clk_priv *priv, int id) ++{ ++ int ret; ++ ++ stm32mp1_clk_lock(&refcount_lock); ++ ret = _clk_stm32_enable_core(priv, id); ++ stm32mp1_clk_unlock(&refcount_lock); ++ ++ return ret; ++} ++ ++void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ ++ if (clk->ops->disable != NULL) { ++ clk->ops->disable(priv, id); ++ } ++} ++ ++static void _clk_stm32_disable_core(struct stm32_clk_priv *priv, int id) ++{ ++ int parent; ++ ++ if ((priv->gate_refcounts[id] == 1U) && _stm32_clk_is_flags(priv, id, CLK_IS_CRITICAL)) { ++ return; ++ } ++ ++ if (priv->gate_refcounts[id] == 0U) { ++ /* case of clock ignore unused */ ++ if (_clk_stm32_is_enabled(priv, id)) { ++ clk_stm32_disable_call_ops(priv, id); ++ return; ++ } ++ VERBOSE("%s: %d already disabled !\n\n", __func__, id); ++ return; ++ } ++ ++ if (--priv->gate_refcounts[id] > 0U) { ++ return; ++ } ++ ++ clk_stm32_disable_call_ops(priv, id); ++ ++ parent = _clk_stm32_get_parent(priv, id); ++ if ((parent >= 0) && (parent != CLK_IS_ROOT)) { ++ _clk_stm32_disable_core(priv, parent); ++ } ++} ++ ++void _clk_stm32_disable(struct stm32_clk_priv *priv, int id) ++{ ++ stm32mp1_clk_lock(&refcount_lock); ++ ++ _clk_stm32_disable_core(priv, id); ++ ++ stm32mp1_clk_unlock(&refcount_lock); ++} ++ ++bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ ++ if (clk->ops->is_enabled != NULL) { ++ return clk->ops->is_enabled(priv, id); ++ } ++ ++ return priv->gate_refcounts[id]; ++} ++ ++static int clk_stm32_enable(unsigned long binding_id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int id; ++ ++ id = clk_get_index(priv, binding_id); ++ if (id == -EINVAL) { ++ return id; ++ } ++ ++ return _clk_stm32_enable(priv, id); ++} ++ ++static void clk_stm32_disable(unsigned long binding_id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int id; ++ ++ id = clk_get_index(priv, binding_id); ++ if (id != -EINVAL) { ++ _clk_stm32_disable(priv, id); ++ } ++} ++ ++static bool clk_stm32_is_enabled(unsigned long binding_id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int id; ++ ++ id = clk_get_index(priv, binding_id); ++ if (id == -EINVAL) { ++ return false; ++ } ++ ++ return _clk_stm32_is_enabled(priv, id); ++} ++ ++static unsigned long clk_stm32_get_rate(unsigned long binding_id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int id; ++ ++ id = clk_get_index(priv, binding_id); ++ if (id == -EINVAL) { ++ return 0UL; ++ } ++ ++ return _clk_stm32_get_rate(priv, id); ++} ++ ++static int clk_stm32_get_parent(unsigned long binding_id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int id; ++ ++ id = clk_get_index(priv, binding_id); ++ if (id == -EINVAL) { ++ return id; ++ } ++ ++ return _clk_stm32_get_parent(priv, id); ++} ++ ++static const struct clk_ops stm32mp_clk_ops = { ++ .enable = clk_stm32_enable, ++ .disable = clk_stm32_disable, ++ .is_enabled = clk_stm32_is_enabled, ++ .get_rate = clk_stm32_get_rate, ++ .get_parent = clk_stm32_get_parent, ++}; ++ ++void clk_stm32_enable_critical_clocks(void) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ unsigned int i; ++ ++ for (i = 0U; i < priv->num; i++) { ++ if (_stm32_clk_is_flags(priv, i, CLK_IS_CRITICAL)) { ++ _clk_stm32_enable(priv, i); ++ } ++ } ++} ++ ++static void stm32_clk_register(void) ++{ ++ clk_register(&stm32mp_clk_ops); ++} ++ ++uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id) ++{ ++ const struct div_cfg *divider = &priv->div[div_id]; ++ uint32_t val = 0; ++ ++ val = mmio_read_32(priv->base + divider->offset) >> divider->shift; ++ val &= clk_div_mask(divider->width); ++ ++ return val; ++} ++ ++unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, ++ int div_id, ++ unsigned long prate) ++{ ++ const struct div_cfg *divider = &priv->div[div_id]; ++ uint32_t val = clk_stm32_div_get_value(priv, div_id); ++ unsigned int div = 0U; ++ ++ div = _get_div(divider->table, val, divider->flags, divider->width); ++ if (div == 0U) { ++ return prate; ++ } ++ ++ return div_round_up((uint64_t)prate, div); ++} ++ ++unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int id, ++ unsigned long prate) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_stm32_div_cfg *div_cfg = clk->clock_cfg; ++ ++ return _clk_stm32_divider_recalc(priv, div_cfg->id, prate); ++} ++ ++const struct stm32_clk_ops clk_stm32_divider_ops = { ++ .recalc_rate = clk_stm32_divider_recalc, ++}; ++ ++int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value) ++{ ++ const struct div_cfg *divider; ++ uintptr_t address; ++ uint64_t timeout; ++ uint32_t mask; ++ ++ if (div_id >= priv->nb_div) { ++ panic(); ++ } ++ ++ divider = &priv->div[div_id]; ++ address = priv->base + divider->offset; ++ ++ mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); ++ mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask); ++ ++ if (divider->bitrdy == DIV_NO_BIT_RDY) { ++ return 0; ++ } ++ ++ timeout = timeout_init_us(CLKSRC_TIMEOUT); ++ mask = BIT(divider->bitrdy); ++ ++ while ((mmio_read_32(address) & mask) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, ++ bool ready_on) ++{ ++ const struct gate_cfg *gate = &priv->gates[gate_id]; ++ uintptr_t address = priv->base + gate->offset; ++ uint32_t mask_rdy = BIT(gate->bit_idx); ++ uint64_t timeout; ++ uint32_t mask_test; ++ ++ if (ready_on) { ++ mask_test = BIT(gate->bit_idx); ++ } else { ++ mask_test = 0U; ++ } ++ ++ timeout = timeout_init_us(OSCRDY_TIMEOUT); ++ ++ while ((mmio_read_32(address) & mask_rdy) != mask_test) { ++ if (timeout_elapsed(timeout)) { ++ break; ++ } ++ } ++ ++ if ((mmio_read_32(address) & mask_rdy) != mask_test) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; ++ const struct gate_cfg *gate = &priv->gates[cfg->id]; ++ uintptr_t addr = priv->base + gate->offset; ++ ++ if (gate->set_clr != 0U) { ++ mmio_write_32(addr, BIT(gate->bit_idx)); ++ ++ } else { ++ stm32mp_mmio_setbits_32_shregs(addr, BIT(gate->bit_idx)); ++ } ++ ++ return 0; ++} ++ ++void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; ++ const struct gate_cfg *gate = &priv->gates[cfg->id]; ++ uintptr_t addr = priv->base + gate->offset; ++ ++ if (gate->set_clr != 0U) { ++ mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); ++ } else { ++ stm32mp_mmio_clrbits_32_shregs(addr, BIT(gate->bit_idx)); ++ } ++} ++ ++bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id) ++{ ++ const struct gate_cfg *gate; ++ uint32_t addr; ++ ++ gate = &priv->gates[gate_id]; ++ addr = priv->base + gate->offset; ++ ++ return ((mmio_read_32(addr) & BIT(gate->bit_idx)) != 0U); ++} ++ ++bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; ++ ++ return _clk_stm32_gate_is_enabled(priv, cfg->id); ++} ++ ++const struct stm32_clk_ops clk_stm32_gate_ops = { ++ .enable = clk_stm32_gate_enable, ++ .disable = clk_stm32_gate_disable, ++ .is_enabled = clk_stm32_gate_is_enabled, ++}; ++ ++const struct stm32_clk_ops clk_fixed_factor_ops = { ++ .recalc_rate = fixed_factor_recalc_rate, ++}; ++ ++unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, ++ int id, unsigned long prate) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ const struct fixed_factor_cfg *cfg = clk->clock_cfg; ++ unsigned long long rate; ++ ++ rate = (unsigned long long)prate * cfg->mult; ++ ++ if (cfg->div == 0U) { ++ ERROR("division by zero\n"); ++ panic(); ++ } ++ ++ return (unsigned long)(rate / cfg->div); ++}; ++ ++#define APB_DIV_MASK GENMASK(2, 0) ++#define TIM_PRE_MASK BIT(0) ++ ++static unsigned long timer_recalc_rate(struct stm32_clk_priv *priv, ++ int id, unsigned long prate) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ const struct clk_timer_cfg *cfg = clk->clock_cfg; ++ uint32_t prescaler, timpre; ++ uintptr_t rcc_base = priv->base; ++ ++ prescaler = mmio_read_32(rcc_base + cfg->apbdiv) & ++ APB_DIV_MASK; ++ ++ timpre = mmio_read_32(rcc_base + cfg->timpre) & ++ TIM_PRE_MASK; ++ ++ if (prescaler == 0U) { ++ return prate; ++ } ++ ++ return prate * (timpre + 1U) * 2U; ++}; ++ ++const struct stm32_clk_ops clk_timer_ops = { ++ .recalc_rate = timer_recalc_rate, ++}; ++ ++static unsigned long clk_fixed_rate_recalc(struct stm32_clk_priv *priv, int id, ++ unsigned long prate) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct clk_stm32_fixed_rate_cfg *cfg = clk->clock_cfg; ++ ++ return cfg->rate; ++} ++ ++const struct stm32_clk_ops clk_stm32_fixed_rate_ops = { ++ .recalc_rate = clk_fixed_rate_recalc, ++}; ++ ++static unsigned long clk_stm32_osc_recalc_rate(struct stm32_clk_priv *priv, ++ int id, unsigned long prate) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ return osc_data->frequency; ++}; ++ ++bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ return _clk_stm32_gate_is_enabled(priv, osc_data->gate_id); ++ ++} ++ ++int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ _clk_stm32_gate_enable(priv, osc_data->gate_id); ++ ++ if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, true) != 0U) { ++ ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); ++ panic(); ++ } ++ ++ return 0; ++} ++ ++void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ ++ _clk_stm32_gate_disable(priv, osc_data->gate_id); ++ ++ if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, false) != 0U) { ++ ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); ++ panic(); ++ } ++} ++ ++static unsigned long clk_stm32_get_dt_oscillator_frequency(const char *name) ++{ ++ void *fdt = NULL; ++ int node = 0; ++ int subnode = 0; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); ++ } ++ ++ node = fdt_path_offset(fdt, "/clocks"); ++ if (node < 0) { ++ return 0UL; ++ } ++ ++ fdt_for_each_subnode(subnode, fdt, node) { ++ const char *cchar = NULL; ++ const fdt32_t *cuint = 0; ++ int ret = 0; ++ ++ cchar = fdt_get_name(fdt, subnode, &ret); ++ if (cchar == NULL) { ++ continue; ++ } ++ ++ if (strncmp(cchar, name, (size_t)ret) || ++ fdt_get_status(subnode) == DT_DISABLED) { ++ continue; ++ } ++ ++ cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); ++ if (cuint == NULL) { ++ return 0UL; ++ } ++ ++ return fdt32_to_cpu(*cuint); ++ } ++ ++ return 0UL; ++} ++ ++void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); ++ const char *name = osc_data->name; ++ ++ osc_data->frequency = clk_stm32_get_dt_oscillator_frequency(name); ++} ++ ++const struct stm32_clk_ops clk_stm32_osc_ops = { ++ .recalc_rate = clk_stm32_osc_recalc_rate, ++ .is_enabled = clk_stm32_osc_gate_is_enabled, ++ .enable = clk_stm32_osc_gate_enable, ++ .disable = clk_stm32_osc_gate_disable, ++ .init = clk_stm32_osc_init, ++}; ++ ++const struct stm32_clk_ops clk_stm32_osc_nogate_ops = { ++ .recalc_rate = clk_stm32_osc_recalc_rate, ++ .init = clk_stm32_osc_init, ++}; ++ ++int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb) ++{ ++ const fdt32_t *cell; ++ int len = 0; ++ uint32_t i; ++ ++ cell = fdt_getprop(fdt, node, name, &len); ++ if (cell == NULL) { ++ *nb = 0U; ++ return 0; ++ } ++ ++ for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { ++ uint32_t val = fdt32_to_cpu(cell[i]); ++ ++ tab[i] = val; ++ } ++ ++ *nb = (uint32_t)len / sizeof(uint32_t); ++ ++ return 0; ++} ++ ++int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base) ++{ ++ unsigned int i; ++ ++ stm32_clock_data = priv; ++ ++ priv->base = base; ++ ++ for (i = 0U; i < priv->num; i++) { ++ const struct clk_stm32 *clk = _clk_get(priv, i); ++ ++ assert(clk->ops != NULL); ++ ++ if (clk->ops->init != NULL) { ++ clk->ops->init(priv, i); ++ } ++ } ++ ++ stm32_clk_register(); ++ ++ return 0; ++} +diff --git a/drivers/st/clk/clk-stm32-core.h b/drivers/st/clk/clk-stm32-core.h +new file mode 100644 +index 000000000..c771c6fbf +--- /dev/null ++++ b/drivers/st/clk/clk-stm32-core.h +@@ -0,0 +1,405 @@ ++/* ++ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ ++#ifndef CLK_STM32_CORE_H ++#define CLK_STM32_CORE_H ++ ++struct mux_cfg { ++ uint16_t offset; ++ uint8_t shift; ++ uint8_t width; ++ uint8_t bitrdy; ++}; ++ ++struct gate_cfg { ++ uint16_t offset; ++ uint8_t bit_idx; ++ uint8_t set_clr; ++}; ++ ++struct clk_div_table { ++ unsigned int val; ++ unsigned int div; ++}; ++ ++struct div_cfg { ++ uint16_t offset; ++ uint8_t shift; ++ uint8_t width; ++ uint8_t flags; ++ uint8_t bitrdy; ++ const struct clk_div_table *table; ++}; ++ ++struct parent_cfg { ++ uint8_t num_parents; ++ const uint16_t *id_parents; ++ struct mux_cfg *mux; ++}; ++ ++struct stm32_clk_priv; ++ ++struct stm32_clk_ops { ++ unsigned long (*recalc_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate); ++ int (*get_parent)(struct stm32_clk_priv *priv, int id); ++ int (*set_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate, ++ unsigned long prate); ++ int (*enable)(struct stm32_clk_priv *priv, int id); ++ void (*disable)(struct stm32_clk_priv *priv, int id); ++ bool (*is_enabled)(struct stm32_clk_priv *priv, int id); ++ void (*init)(struct stm32_clk_priv *priv, int id); ++}; ++ ++struct clk_stm32 { ++ const char *name; ++ uint16_t binding; ++ uint16_t parent; ++ uint8_t flags; ++ void *clock_cfg; ++ const struct stm32_clk_ops *ops; ++}; ++ ++struct stm32_clk_priv { ++ uintptr_t base; ++ const uint32_t num; ++ const struct clk_stm32 *clks; ++ const struct parent_cfg *parents; ++ const uint32_t nb_parents; ++ const struct gate_cfg *gates; ++ const uint32_t nb_gates; ++ const struct div_cfg *div; ++ const uint32_t nb_div; ++ struct clk_oscillator_data *osci_data; ++ const uint32_t nb_osci_data; ++ uint32_t *gate_refcounts; ++ void *pdata; ++}; ++ ++struct stm32_clk_bypass { ++ uint16_t offset; ++ uint8_t bit_byp; ++ uint8_t bit_digbyp; ++}; ++ ++struct stm32_clk_css { ++ uint16_t offset; ++ uint8_t bit_css; ++}; ++ ++struct stm32_clk_drive { ++ uint16_t offset; ++ uint8_t drv_shift; ++ uint8_t drv_width; ++ uint8_t drv_default; ++}; ++ ++struct clk_oscillator_data { ++ const char *name; ++ uint16_t id_clk; ++ unsigned long frequency; ++ uint16_t gate_id; ++ uint16_t gate_rdy_id; ++ struct stm32_clk_bypass *bypass; ++ struct stm32_clk_css *css; ++ struct stm32_clk_drive *drive; ++}; ++ ++struct clk_fixed_rate { ++ const char *name; ++ unsigned long fixed_rate; ++}; ++ ++struct clk_gate_cfg { ++ uint32_t offset; ++ uint8_t bit_idx; ++}; ++ ++/* CLOCK FLAGS */ ++#define CLK_IS_CRITICAL BIT(0) ++#define CLK_IGNORE_UNUSED BIT(1) ++#define CLK_SET_RATE_PARENT BIT(2) ++ ++#define CLK_DIVIDER_ONE_BASED BIT(0) ++#define CLK_DIVIDER_POWER_OF_TWO BIT(1) ++#define CLK_DIVIDER_ALLOW_ZERO BIT(2) ++#define CLK_DIVIDER_HIWORD_MASK BIT(3) ++#define CLK_DIVIDER_ROUND_CLOSEST BIT(4) ++#define CLK_DIVIDER_READ_ONLY BIT(5) ++#define CLK_DIVIDER_MAX_AT_ZERO BIT(6) ++#define CLK_DIVIDER_BIG_ENDIAN BIT(7) ++ ++#define MUX_MAX_PARENTS U(0x8000) ++#define MUX_PARENT_MASK GENMASK(14, 0) ++#define MUX_FLAG U(0x8000) ++#define MUX(mux) ((mux) | MUX_FLAG) ++ ++#define NO_GATE 0 ++#define _NO_ID UINT16_MAX ++#define CLK_IS_ROOT UINT16_MAX ++#define MUX_NO_BIT_RDY UINT8_MAX ++#define DIV_NO_BIT_RDY UINT8_MAX ++ ++#define MASK_WIDTH_SHIFT(_width, _shift) \ ++ GENMASK(((_width) + (_shift) - 1U), _shift) ++ ++int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base); ++void clk_stm32_enable_critical_clocks(void); ++ ++struct stm32_clk_priv *clk_stm32_get_priv(void); ++ ++int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id); ++const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id); ++ ++void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass); ++void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv); ++void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css); ++ ++int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, bool ready_on); ++ ++int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on); ++int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id); ++int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id); ++ ++const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id); ++const char *clk_stm32_get_name(struct stm32_clk_priv *priv, unsigned long binding_id); ++int clk_stm32_get_counter(unsigned long binding_id); ++ ++void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id); ++int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id); ++ ++int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int id, int src_id); ++int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel); ++ ++int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int id); ++int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx); ++int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id); ++ ++unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id); ++unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id); ++ ++bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag); ++ ++int _clk_stm32_enable(struct stm32_clk_priv *priv, int id); ++void _clk_stm32_disable(struct stm32_clk_priv *priv, int id); ++ ++int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id); ++void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id); ++ ++bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id); ++ ++int _clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int div_id, ++ unsigned long rate, unsigned long parent_rate); ++ ++ int clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate, ++ unsigned long prate); ++ ++unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, ++ int div_id, ++ unsigned long prate); ++ ++unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int idx, ++ unsigned long prate); ++ ++int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int idx); ++void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int idx); ++ ++bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id); ++bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int idx); ++ ++uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id); ++int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value); ++int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel); ++int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id); ++ ++int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb); ++ ++#ifdef CFG_STM32_CLK_DEBUG ++void clk_stm32_display_clock_info(void); ++#endif ++ ++struct clk_stm32_div_cfg { ++ int id; ++}; ++ ++#define STM32_DIV(idx, _binding, _parent, _flags, _div_id) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_binding),\ ++ .parent = (_parent),\ ++ .flags = (_flags),\ ++ .clock_cfg = &(struct clk_stm32_div_cfg){\ ++ .id = (_div_id),\ ++ },\ ++ .ops = &clk_stm32_divider_ops,\ ++ } ++ ++struct clk_stm32_gate_cfg { ++ int id; ++}; ++ ++#define STM32_GATE(idx, _binding, _parent, _flags, _gate_id) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_binding),\ ++ .parent = (_parent),\ ++ .flags = (_flags),\ ++ .clock_cfg = &(struct clk_stm32_gate_cfg){\ ++ .id = (_gate_id),\ ++ },\ ++ .ops = &clk_stm32_gate_ops,\ ++ } ++ ++struct fixed_factor_cfg { ++ unsigned int mult; ++ unsigned int div; ++}; ++ ++unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, ++ int _idx, unsigned long prate); ++ ++#define FIXED_FACTOR(idx, _idx, _parent, _mult, _div) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_idx),\ ++ .parent = (_parent),\ ++ .clock_cfg = &(struct fixed_factor_cfg){\ ++ .mult = (_mult),\ ++ .div = (_div),\ ++ },\ ++ .ops = &clk_fixed_factor_ops,\ ++ } ++ ++#define GATE(idx, _binding, _parent, _flags, _offset, _bit_idx) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_binding),\ ++ .parent = (_parent),\ ++ .flags = (_flags),\ ++ .clock_cfg = &(struct clk_gate_cfg){\ ++ .offset = (_offset),\ ++ .bit_idx = (_bit_idx),\ ++ },\ ++ .ops = &clk_gate_ops,\ ++ } ++ ++#define STM32_MUX(idx, _binding, _mux_id, _flags) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_binding),\ ++ .parent = (MUX(_mux_id)),\ ++ .flags = (_flags),\ ++ .clock_cfg = NULL,\ ++ .ops = (&clk_mux_ops),\ ++ } ++ ++struct clk_timer_cfg { ++ uint32_t apbdiv; ++ uint32_t timpre; ++}; ++ ++#define CK_TIMER(idx, _idx, _parent, _flags, _apbdiv, _timpre) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_idx),\ ++ .parent = (_parent),\ ++ .flags = (CLK_SET_RATE_PARENT | (_flags)),\ ++ .clock_cfg = &(struct clk_timer_cfg){\ ++ .apbdiv = (_apbdiv),\ ++ .timpre = (_timpre),\ ++ },\ ++ .ops = &clk_timer_ops,\ ++ } ++ ++struct clk_stm32_fixed_rate_cfg { ++ unsigned long rate; ++}; ++ ++#define CLK_FIXED_RATE(idx, _binding, _rate) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_binding),\ ++ .parent = (CLK_IS_ROOT),\ ++ .clock_cfg = &(struct clk_stm32_fixed_rate_cfg){\ ++ .rate = (_rate),\ ++ },\ ++ .ops = &clk_stm32_fixed_rate_ops,\ ++ } ++ ++#define BYPASS(_offset, _bit_byp, _bit_digbyp) &(struct stm32_clk_bypass){\ ++ .offset = (_offset),\ ++ .bit_byp = (_bit_byp),\ ++ .bit_digbyp = (_bit_digbyp),\ ++} ++ ++#define CSS(_offset, _bit_css) &(struct stm32_clk_css){\ ++ .offset = (_offset),\ ++ .bit_css = (_bit_css),\ ++} ++ ++#define DRIVE(_offset, _shift, _width, _default) &(struct stm32_clk_drive){\ ++ .offset = (_offset),\ ++ .drv_shift = (_shift),\ ++ .drv_width = (_width),\ ++ .drv_default = (_default),\ ++} ++ ++#define OSCILLATOR(idx_osc, _id, _name, _gate_id, _gate_rdy_id, _bypass, _css, _drive) \ ++ [(idx_osc)] = (struct clk_oscillator_data){\ ++ .name = (_name),\ ++ .id_clk = (_id),\ ++ .gate_id = (_gate_id),\ ++ .gate_rdy_id = (_gate_rdy_id),\ ++ .bypass = (_bypass),\ ++ .css = (_css),\ ++ .drive = (_drive),\ ++ } ++ ++struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id); ++ ++void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id); ++bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id); ++int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id); ++void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id); ++ ++struct stm32_osc_cfg { ++ int osc_id; ++}; ++ ++#define CLK_OSC(idx, _idx, _parent, _osc_id) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_idx),\ ++ .parent = (_parent),\ ++ .flags = CLK_IS_CRITICAL,\ ++ .clock_cfg = &(struct stm32_osc_cfg){\ ++ .osc_id = (_osc_id),\ ++ },\ ++ .ops = &clk_stm32_osc_ops,\ ++ } ++ ++#define CLK_OSC_FIXED(idx, _idx, _parent, _osc_id) \ ++ [(idx)] = (struct clk_stm32){ \ ++ .name = #idx,\ ++ .binding = (_idx),\ ++ .parent = (_parent),\ ++ .flags = CLK_IS_CRITICAL,\ ++ .clock_cfg = &(struct stm32_osc_cfg){\ ++ .osc_id = (_osc_id),\ ++ },\ ++ .ops = &clk_stm32_osc_nogate_ops,\ ++ } ++ ++extern const struct stm32_clk_ops clk_mux_ops; ++extern const struct stm32_clk_ops clk_stm32_divider_ops; ++extern const struct stm32_clk_ops clk_stm32_gate_ops; ++extern const struct stm32_clk_ops clk_fixed_factor_ops; ++extern const struct stm32_clk_ops clk_gate_ops; ++extern const struct stm32_clk_ops clk_timer_ops; ++extern const struct stm32_clk_ops clk_stm32_fixed_rate_ops; ++extern const struct stm32_clk_ops clk_stm32_osc_ops; ++extern const struct stm32_clk_ops clk_stm32_osc_nogate_ops; ++ ++#endif /* CLK_STM32_CORE_H */ +diff --git a/drivers/st/clk/clk-stm32mp13.c b/drivers/st/clk/clk-stm32mp13.c +new file mode 100644 +index 000000000..19613d021 +--- /dev/null ++++ b/drivers/st/clk/clk-stm32mp13.c +@@ -0,0 +1,2380 @@ ++/* ++ * Copyright (C) 2018-2022, 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-stm32-core.h" ++ ++struct stm32_osci_dt_cfg { ++ unsigned long freq; ++ bool bypass; ++ bool digbyp; ++ bool css; ++ uint32_t drive; ++}; ++ ++enum pll_mn { ++ PLL_CFG_M, ++ PLL_CFG_N, ++ PLL_DIV_MN_NB ++}; ++ ++enum pll_pqr { ++ PLL_CFG_P, ++ PLL_CFG_Q, ++ PLL_CFG_R, ++ PLL_DIV_PQR_NB ++}; ++ ++enum pll_csg { ++ PLL_CSG_MOD_PER, ++ PLL_CSG_INC_STEP, ++ PLL_CSG_SSCG_MODE, ++ PLL_CSG_NB ++}; ++ ++struct stm32_pll_vco { ++ uint32_t status; ++ uint32_t src; ++ uint32_t div_mn[PLL_DIV_MN_NB]; ++ uint32_t frac; ++ bool csg_enabled; ++ uint32_t csg[PLL_CSG_NB]; ++}; ++ ++struct stm32_pll_output { ++ uint32_t output[PLL_DIV_PQR_NB]; ++}; ++ ++struct stm32_pll_dt_cfg { ++ struct stm32_pll_vco vco; ++ struct stm32_pll_output output; ++}; ++ ++struct stm32_clk_platdata { ++ uint32_t nosci; ++ struct stm32_osci_dt_cfg *osci; ++ uint32_t npll; ++ struct stm32_pll_dt_cfg *pll; ++ uint32_t nclksrc; ++ uint32_t *clksrc; ++ uint32_t nclkdiv; ++ uint32_t *clkdiv; ++}; ++ ++enum stm32_clock { ++ /* ROOT CLOCKS */ ++ _CK_OFF, ++ _CK_HSI, ++ _CK_HSE, ++ _CK_CSI, ++ _CK_LSI, ++ _CK_LSE, ++ _I2SCKIN, ++ _CSI_DIV122, ++ _HSE_DIV, ++ _HSE_DIV2, ++ _CK_PLL1, ++ _CK_PLL2, ++ _CK_PLL3, ++ _CK_PLL4, ++ _PLL1P, ++ _PLL1P_DIV, ++ _PLL2P, ++ _PLL2Q, ++ _PLL2R, ++ _PLL3P, ++ _PLL3Q, ++ _PLL3R, ++ _PLL4P, ++ _PLL4Q, ++ _PLL4R, ++ _PCLK1, ++ _PCLK2, ++ _PCLK3, ++ _PCLK4, ++ _PCLK5, ++ _PCLK6, ++ _CKMPU, ++ _CKAXI, ++ _CKMLAHB, ++ _CKPER, ++ _CKTIMG1, ++ _CKTIMG2, ++ _CKTIMG3, ++ _USB_PHY_48, ++ _MCO1_K, ++ _MCO2_K, ++ _TRACECK, ++ /* BUS and KERNEL CLOCKS */ ++ _DDRC1, ++ _DDRC1LP, ++ _DDRPHYC, ++ _DDRPHYCLP, ++ _DDRCAPB, ++ _DDRCAPBLP, ++ _AXIDCG, ++ _DDRPHYCAPB, ++ _DDRPHYCAPBLP, ++ _SYSCFG, ++ _DDRPERFM, ++ _IWDG2APB, ++ _USBPHY_K, ++ _USBO_K, ++ _RTCAPB, ++ _TZC, ++ _ETZPC, ++ _IWDG1APB, ++ _BSEC, ++ _STGENC, ++ _USART1_K, ++ _USART2_K, ++ _I2C3_K, ++ _I2C4_K, ++ _I2C5_K, ++ _TIM12, ++ _TIM15, ++ _RTCCK, ++ _GPIOA, ++ _GPIOB, ++ _GPIOC, ++ _GPIOD, ++ _GPIOE, ++ _GPIOF, ++ _GPIOG, ++ _GPIOH, ++ _GPIOI, ++ _PKA, ++ _SAES_K, ++ _CRYP1, ++ _HASH1, ++ _RNG1_K, ++ _BKPSRAM, ++ _SDMMC1_K, ++ _SDMMC2_K, ++ _DBGCK, ++ _USART3_K, ++ _UART4_K, ++ _UART5_K, ++ _UART7_K, ++ _UART8_K, ++ _USART6_K, ++ _MCE, ++ _FMC_K, ++ _QSPI_K, ++#if defined(IMAGE_BL32) ++ _LTDC, ++ _DMA1, ++ _DMA2, ++ _MDMA, ++ _ETH1MAC, ++ _USBH, ++ _TIM2, ++ _TIM3, ++ _TIM4, ++ _TIM5, ++ _TIM6, ++ _TIM7, ++ _LPTIM1_K, ++ _SPI2_K, ++ _SPI3_K, ++ _SPDIF_K, ++ _TIM1, ++ _TIM8, ++ _SPI1_K, ++ _SAI1_K, ++ _SAI2_K, ++ _DFSDM, ++ _FDCAN_K, ++ _TIM13, ++ _TIM14, ++ _TIM16, ++ _TIM17, ++ _SPI4_K, ++ _SPI5_K, ++ _I2C1_K, ++ _I2C2_K, ++ _ADFSDM, ++ _LPTIM2_K, ++ _LPTIM3_K, ++ _LPTIM4_K, ++ _LPTIM5_K, ++ _VREF, ++ _DTS, ++ _PMBCTRL, ++ _HDP, ++ _STGENRO, ++ _DCMIPP_K, ++ _DMAMUX1, ++ _DMAMUX2, ++ _DMA3, ++ _ADC1_K, ++ _ADC2_K, ++ _TSC, ++ _AXIMC, ++ _ETH1CK, ++ _ETH1TX, ++ _ETH1RX, ++ _CRC1, ++ _ETH2CK, ++ _ETH2TX, ++ _ETH2RX, ++ _ETH2MAC, ++#endif ++ CK_LAST ++}; ++ ++/* PARENT CONFIG */ ++static const uint16_t RTC_src[] = { ++ _CK_OFF, _CK_LSE, _CK_LSI, _CK_HSE ++}; ++ ++static const uint16_t MCO1_src[] = { ++ _CK_HSI, _CK_HSE, _CK_CSI, _CK_LSI, _CK_LSE ++}; ++ ++static const uint16_t MCO2_src[] = { ++ _CKMPU, _CKAXI, _CKMLAHB, _PLL4P, _CK_HSE, _CK_HSI ++}; ++ ++static const uint16_t PLL12_src[] = { ++ _CK_HSI, _CK_HSE ++}; ++ ++static const uint16_t PLL3_src[] = { ++ _CK_HSI, _CK_HSE, _CK_CSI ++}; ++ ++static const uint16_t PLL4_src[] = { ++ _CK_HSI, _CK_HSE, _CK_CSI, _I2SCKIN ++}; ++ ++static const uint16_t MPU_src[] = { ++ _CK_HSI, _CK_HSE, _PLL1P, _PLL1P_DIV ++}; ++ ++static const uint16_t AXI_src[] = { ++ _CK_HSI, _CK_HSE, _PLL2P ++}; ++ ++static const uint16_t MLAHBS_src[] = { ++ _CK_HSI, _CK_HSE, _CK_CSI, _PLL3P ++}; ++ ++static const uint16_t CKPER_src[] = { ++ _CK_HSI, _CK_CSI, _CK_HSE, _CK_OFF ++}; ++ ++static const uint16_t I2C12_src[] = { ++ _PCLK1, _PLL4R, _CK_HSI, _CK_CSI ++}; ++ ++static const uint16_t I2C3_src[] = { ++ _PCLK6, _PLL4R, _CK_HSI, _CK_CSI ++}; ++ ++static const uint16_t I2C4_src[] = { ++ _PCLK6, _PLL4R, _CK_HSI, _CK_CSI ++}; ++ ++static const uint16_t I2C5_src[] = { ++ _PCLK6, _PLL4R, _CK_HSI, _CK_CSI ++}; ++ ++static const uint16_t SPI1_src[] = { ++ _PLL4P, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R ++}; ++ ++static const uint16_t SPI23_src[] = { ++ _PLL4P, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R ++}; ++ ++static const uint16_t SPI4_src[] = { ++ _PCLK6, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE, _I2SCKIN ++}; ++ ++static const uint16_t SPI5_src[] = { ++ _PCLK6, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE ++}; ++ ++static const uint16_t UART1_src[] = { ++ _PCLK6, _PLL3Q, _CK_HSI, _CK_CSI, _PLL4Q, _CK_HSE ++}; ++ ++static const uint16_t UART2_src[] = { ++ _PCLK6, _PLL3Q, _CK_HSI, _CK_CSI, _PLL4Q, _CK_HSE ++}; ++ ++static const uint16_t UART35_src[] = { ++ _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE ++}; ++ ++static const uint16_t UART4_src[] = { ++ _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE ++}; ++ ++static const uint16_t UART6_src[] = { ++ _PCLK2, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE ++}; ++ ++static const uint16_t UART78_src[] = { ++ _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE ++}; ++ ++static const uint16_t LPTIM1_src[] = { ++ _PCLK1, _PLL4P, _PLL3Q, _CK_LSE, _CK_LSI, _CKPER ++}; ++ ++static const uint16_t LPTIM2_src[] = { ++ _PCLK3, _PLL4Q, _CKPER, _CK_LSE, _CK_LSI ++}; ++ ++static const uint16_t LPTIM3_src[] = { ++ _PCLK3, _PLL4Q, _CKPER, _CK_LSE, _CK_LSI ++}; ++ ++static const uint16_t LPTIM45_src[] = { ++ _PCLK3, _PLL4P, _PLL3Q, _CK_LSE, _CK_LSI, _CKPER ++}; ++ ++static const uint16_t SAI1_src[] = { ++ _PLL4Q, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R ++}; ++ ++static const uint16_t SAI2_src[] = { ++ _PLL4Q, _PLL3Q, _I2SCKIN, _CKPER, _NO_ID, _PLL3R ++}; ++ ++static const uint16_t FDCAN_src[] = { ++ _CK_HSE, _PLL3Q, _PLL4Q, _PLL4R ++}; ++ ++static const uint16_t SPDIF_src[] = { ++ _PLL4P, _PLL3Q, _CK_HSI ++}; ++ ++static const uint16_t ADC1_src[] = { ++ _PLL4R, _CKPER, _PLL3Q ++}; ++ ++static const uint16_t ADC2_src[] = { ++ _PLL4R, _CKPER, _PLL3Q ++}; ++ ++static const uint16_t SDMMC1_src[] = { ++ _CKAXI, _PLL3R, _PLL4P, _CK_HSI ++}; ++ ++static const uint16_t SDMMC2_src[] = { ++ _CKAXI, _PLL3R, _PLL4P, _CK_HSI ++}; ++ ++static const uint16_t ETH1_src[] = { ++ _PLL4P, _PLL3Q ++}; ++ ++static const uint16_t ETH2_src[] = { ++ _PLL4P, _PLL3Q ++}; ++ ++static const uint16_t USBPHY_src[] = { ++ _CK_HSE, _PLL4R, _HSE_DIV2 ++}; ++ ++static const uint16_t USBO_src[] = { ++ _PLL4R, _USB_PHY_48 ++}; ++ ++static const uint16_t QSPI_src[] = { ++ _CKAXI, _PLL3R, _PLL4P, _CKPER ++}; ++ ++static const uint16_t FMC_src[] = { ++ _CKAXI, _PLL3R, _PLL4P, _CKPER ++}; ++ ++/* Position 2 of RNG1 mux is reserved */ ++static const uint16_t RNG1_src[] = { ++ _CK_CSI, _PLL4R, _CK_OFF, _CK_LSI ++}; ++ ++static const uint16_t STGEN_src[] = { ++ _CK_HSI, _CK_HSE ++}; ++ ++static const uint16_t DCMIPP_src[] = { ++ _CKAXI, _PLL2Q, _PLL4P, _CKPER ++}; ++ ++static const uint16_t SAES_src[] = { ++ _CKAXI, _CKPER, _PLL4R, _CK_LSI ++}; ++ ++#define MUX_CFG(id, src, _offset, _shift, _witdh)[id] = {\ ++ .id_parents = src,\ ++ .num_parents = ARRAY_SIZE(src),\ ++ .mux = &(struct mux_cfg) {\ ++ .offset = (_offset),\ ++ .shift = (_shift),\ ++ .width = (_witdh),\ ++ .bitrdy = MUX_NO_BIT_RDY,\ ++ },\ ++} ++ ++#define MUX_RDY_CFG(id, src, _offset, _shift, _witdh)[id] = {\ ++ .id_parents = src,\ ++ .num_parents = ARRAY_SIZE(src),\ ++ .mux = &(struct mux_cfg) {\ ++ .offset = (_offset),\ ++ .shift = (_shift),\ ++ .width = (_witdh),\ ++ .bitrdy = 31,\ ++ },\ ++} ++ ++static const struct parent_cfg parent_mp13[] = { ++ MUX_CFG(MUX_ADC1, ADC1_src, RCC_ADC12CKSELR, 0, 2), ++ MUX_CFG(MUX_ADC2, ADC2_src, RCC_ADC12CKSELR, 2, 2), ++ MUX_RDY_CFG(MUX_AXI, AXI_src, RCC_ASSCKSELR, 0, 3), ++ MUX_CFG(MUX_CKPER, CKPER_src, RCC_CPERCKSELR, 0, 2), ++ MUX_CFG(MUX_DCMIPP, DCMIPP_src, RCC_DCMIPPCKSELR, 0, 2), ++ MUX_CFG(MUX_ETH1, ETH1_src, RCC_ETH12CKSELR, 0, 2), ++ MUX_CFG(MUX_ETH2, ETH2_src, RCC_ETH12CKSELR, 8, 2), ++ MUX_CFG(MUX_FDCAN, FDCAN_src, RCC_FDCANCKSELR, 0, 2), ++ MUX_CFG(MUX_FMC, FMC_src, RCC_FMCCKSELR, 0, 2), ++ MUX_CFG(MUX_I2C12, I2C12_src, RCC_I2C12CKSELR, 0, 3), ++ MUX_CFG(MUX_I2C3, I2C3_src, RCC_I2C345CKSELR, 0, 3), ++ MUX_CFG(MUX_I2C4, I2C4_src, RCC_I2C345CKSELR, 3, 3), ++ MUX_CFG(MUX_I2C5, I2C5_src, RCC_I2C345CKSELR, 6, 3), ++ MUX_CFG(MUX_LPTIM1, LPTIM1_src, RCC_LPTIM1CKSELR, 0, 3), ++ MUX_CFG(MUX_LPTIM2, LPTIM2_src, RCC_LPTIM23CKSELR, 0, 3), ++ MUX_CFG(MUX_LPTIM3, LPTIM3_src, RCC_LPTIM23CKSELR, 3, 3), ++ MUX_CFG(MUX_LPTIM45, LPTIM45_src, RCC_LPTIM45CKSELR, 0, 3), ++ MUX_CFG(MUX_MCO1, MCO1_src, RCC_MCO1CFGR, 0, 3), ++ MUX_CFG(MUX_MCO2, MCO2_src, RCC_MCO2CFGR, 0, 3), ++ MUX_RDY_CFG(MUX_MLAHB, MLAHBS_src, RCC_MSSCKSELR, 0, 2), ++ MUX_RDY_CFG(MUX_MPU, MPU_src, RCC_MPCKSELR, 0, 2), ++ MUX_RDY_CFG(MUX_PLL12, PLL12_src, RCC_RCK12SELR, 0, 2), ++ MUX_RDY_CFG(MUX_PLL3, PLL3_src, RCC_RCK3SELR, 0, 2), ++ MUX_RDY_CFG(MUX_PLL4, PLL4_src, RCC_RCK4SELR, 0, 2), ++ MUX_CFG(MUX_QSPI, QSPI_src, RCC_QSPICKSELR, 0, 2), ++ MUX_CFG(MUX_RNG1, RNG1_src, RCC_RNG1CKSELR, 0, 2), ++ MUX_CFG(MUX_RTC, RTC_src, RCC_BDCR, 16, 2), ++ MUX_CFG(MUX_SAES, SAES_src, RCC_SAESCKSELR, 0, 2), ++ MUX_CFG(MUX_SAI1, SAI1_src, RCC_SAI1CKSELR, 0, 3), ++ MUX_CFG(MUX_SAI2, SAI2_src, RCC_SAI2CKSELR, 0, 3), ++ MUX_CFG(MUX_SDMMC1, SDMMC1_src, RCC_SDMMC12CKSELR, 0, 3), ++ MUX_CFG(MUX_SDMMC2, SDMMC2_src, RCC_SDMMC12CKSELR, 3, 3), ++ MUX_CFG(MUX_SPDIF, SPDIF_src, RCC_SPDIFCKSELR, 0, 2), ++ MUX_CFG(MUX_SPI1, SPI1_src, RCC_SPI2S1CKSELR, 0, 3), ++ MUX_CFG(MUX_SPI23, SPI23_src, RCC_SPI2S23CKSELR, 0, 3), ++ MUX_CFG(MUX_SPI4, SPI4_src, RCC_SPI45CKSELR, 0, 3), ++ MUX_CFG(MUX_SPI5, SPI5_src, RCC_SPI45CKSELR, 3, 3), ++ MUX_CFG(MUX_STGEN, STGEN_src, RCC_STGENCKSELR, 0, 2), ++ MUX_CFG(MUX_UART1, UART1_src, RCC_UART12CKSELR, 0, 3), ++ MUX_CFG(MUX_UART2, UART2_src, RCC_UART12CKSELR, 3, 3), ++ MUX_CFG(MUX_UART35, UART35_src, RCC_UART35CKSELR, 0, 3), ++ MUX_CFG(MUX_UART4, UART4_src, RCC_UART4CKSELR, 0, 3), ++ MUX_CFG(MUX_UART6, UART6_src, RCC_UART6CKSELR, 0, 3), ++ MUX_CFG(MUX_UART78, UART78_src, RCC_UART78CKSELR, 0, 3), ++ MUX_CFG(MUX_USBO, USBO_src, RCC_USBCKSELR, 4, 1), ++ MUX_CFG(MUX_USBPHY, USBPHY_src, RCC_USBCKSELR, 0, 2), ++}; ++ ++/* ++ * GATE CONFIG ++ */ ++ ++enum enum_gate_cfg { ++ GATE_ZERO, /* reserved for no gate */ ++ GATE_LSE, ++ GATE_RTCCK, ++ GATE_LSI, ++ GATE_HSI, ++ GATE_CSI, ++ GATE_HSE, ++ GATE_LSI_RDY, ++ GATE_CSI_RDY, ++ GATE_LSE_RDY, ++ GATE_HSE_RDY, ++ GATE_HSI_RDY, ++ GATE_MCO1, ++ GATE_MCO2, ++ GATE_DBGCK, ++ GATE_TRACECK, ++ GATE_PLL1, ++ GATE_PLL1_DIVP, ++ GATE_PLL1_DIVQ, ++ GATE_PLL1_DIVR, ++ GATE_PLL2, ++ GATE_PLL2_DIVP, ++ GATE_PLL2_DIVQ, ++ GATE_PLL2_DIVR, ++ GATE_PLL3, ++ GATE_PLL3_DIVP, ++ GATE_PLL3_DIVQ, ++ GATE_PLL3_DIVR, ++ GATE_PLL4, ++ GATE_PLL4_DIVP, ++ GATE_PLL4_DIVQ, ++ GATE_PLL4_DIVR, ++ GATE_DDRC1, ++ GATE_DDRC1LP, ++ GATE_DDRPHYC, ++ GATE_DDRPHYCLP, ++ GATE_DDRCAPB, ++ GATE_DDRCAPBLP, ++ GATE_AXIDCG, ++ GATE_DDRPHYCAPB, ++ GATE_DDRPHYCAPBLP, ++ GATE_TIM2, ++ GATE_TIM3, ++ GATE_TIM4, ++ GATE_TIM5, ++ GATE_TIM6, ++ GATE_TIM7, ++ GATE_LPTIM1, ++ GATE_SPI2, ++ GATE_SPI3, ++ GATE_USART3, ++ GATE_UART4, ++ GATE_UART5, ++ GATE_UART7, ++ GATE_UART8, ++ GATE_I2C1, ++ GATE_I2C2, ++ GATE_SPDIF, ++ GATE_TIM1, ++ GATE_TIM8, ++ GATE_SPI1, ++ GATE_USART6, ++ GATE_SAI1, ++ GATE_SAI2, ++ GATE_DFSDM, ++ GATE_ADFSDM, ++ GATE_FDCAN, ++ GATE_LPTIM2, ++ GATE_LPTIM3, ++ GATE_LPTIM4, ++ GATE_LPTIM5, ++ GATE_VREF, ++ GATE_DTS, ++ GATE_PMBCTRL, ++ GATE_HDP, ++ GATE_SYSCFG, ++ GATE_DCMIPP, ++ GATE_DDRPERFM, ++ GATE_IWDG2APB, ++ GATE_USBPHY, ++ GATE_STGENRO, ++ GATE_LTDC, ++ GATE_RTCAPB, ++ GATE_TZC, ++ GATE_ETZPC, ++ GATE_IWDG1APB, ++ GATE_BSEC, ++ GATE_STGENC, ++ GATE_USART1, ++ GATE_USART2, ++ GATE_SPI4, ++ GATE_SPI5, ++ GATE_I2C3, ++ GATE_I2C4, ++ GATE_I2C5, ++ GATE_TIM12, ++ GATE_TIM13, ++ GATE_TIM14, ++ GATE_TIM15, ++ GATE_TIM16, ++ GATE_TIM17, ++ GATE_DMA1, ++ GATE_DMA2, ++ GATE_DMAMUX1, ++ GATE_DMA3, ++ GATE_DMAMUX2, ++ GATE_ADC1, ++ GATE_ADC2, ++ GATE_USBO, ++ GATE_TSC, ++ GATE_GPIOA, ++ GATE_GPIOB, ++ GATE_GPIOC, ++ GATE_GPIOD, ++ GATE_GPIOE, ++ GATE_GPIOF, ++ GATE_GPIOG, ++ GATE_GPIOH, ++ GATE_GPIOI, ++ GATE_PKA, ++ GATE_SAES, ++ GATE_CRYP1, ++ GATE_HASH1, ++ GATE_RNG1, ++ GATE_BKPSRAM, ++ GATE_AXIMC, ++ GATE_MCE, ++ GATE_ETH1CK, ++ GATE_ETH1TX, ++ GATE_ETH1RX, ++ GATE_ETH1MAC, ++ GATE_FMC, ++ GATE_QSPI, ++ GATE_SDMMC1, ++ GATE_SDMMC2, ++ GATE_CRC1, ++ GATE_USBH, ++ GATE_ETH2CK, ++ GATE_ETH2TX, ++ GATE_ETH2RX, ++ GATE_ETH2MAC, ++ GATE_MDMA, ++ ++ LAST_GATE ++}; ++ ++#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\ ++ .offset = (_offset),\ ++ .bit_idx = (_bit_idx),\ ++ .set_clr = (_offset_clr),\ ++} ++ ++static const struct gate_cfg gates_mp13[LAST_GATE] = { ++ GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0), ++ GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0), ++ GATE_CFG(GATE_LSI, RCC_RDLSICR, 0, 0), ++ GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1), ++ GATE_CFG(GATE_CSI, RCC_OCENSETR, 4, 1), ++ GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1), ++ GATE_CFG(GATE_LSI_RDY, RCC_RDLSICR, 1, 0), ++ GATE_CFG(GATE_CSI_RDY, RCC_OCRDYR, 4, 0), ++ GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0), ++ GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0), ++ GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0), ++ GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), ++ GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 12, 0), ++ GATE_CFG(GATE_DBGCK, RCC_DBGCFGR, 8, 0), ++ GATE_CFG(GATE_TRACECK, RCC_DBGCFGR, 9, 0), ++ GATE_CFG(GATE_PLL1, RCC_PLL1CR, 0, 0), ++ GATE_CFG(GATE_PLL1_DIVP, RCC_PLL1CR, 4, 0), ++ GATE_CFG(GATE_PLL1_DIVQ, RCC_PLL1CR, 5, 0), ++ GATE_CFG(GATE_PLL1_DIVR, RCC_PLL1CR, 6, 0), ++ GATE_CFG(GATE_PLL2, RCC_PLL2CR, 0, 0), ++ GATE_CFG(GATE_PLL2_DIVP, RCC_PLL2CR, 4, 0), ++ GATE_CFG(GATE_PLL2_DIVQ, RCC_PLL2CR, 5, 0), ++ GATE_CFG(GATE_PLL2_DIVR, RCC_PLL2CR, 6, 0), ++ GATE_CFG(GATE_PLL3, RCC_PLL3CR, 0, 0), ++ GATE_CFG(GATE_PLL3_DIVP, RCC_PLL3CR, 4, 0), ++ GATE_CFG(GATE_PLL3_DIVQ, RCC_PLL3CR, 5, 0), ++ GATE_CFG(GATE_PLL3_DIVR, RCC_PLL3CR, 6, 0), ++ GATE_CFG(GATE_PLL4, RCC_PLL4CR, 0, 0), ++ GATE_CFG(GATE_PLL4_DIVP, RCC_PLL4CR, 4, 0), ++ GATE_CFG(GATE_PLL4_DIVQ, RCC_PLL4CR, 5, 0), ++ GATE_CFG(GATE_PLL4_DIVR, RCC_PLL4CR, 6, 0), ++ GATE_CFG(GATE_DDRC1, RCC_DDRITFCR, 0, 0), ++ GATE_CFG(GATE_DDRC1LP, RCC_DDRITFCR, 1, 0), ++ GATE_CFG(GATE_DDRPHYC, RCC_DDRITFCR, 4, 0), ++ GATE_CFG(GATE_DDRPHYCLP, RCC_DDRITFCR, 5, 0), ++ GATE_CFG(GATE_DDRCAPB, RCC_DDRITFCR, 6, 0), ++ GATE_CFG(GATE_DDRCAPBLP, RCC_DDRITFCR, 7, 0), ++ GATE_CFG(GATE_AXIDCG, RCC_DDRITFCR, 8, 0), ++ GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9, 0), ++ GATE_CFG(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10, 0), ++ GATE_CFG(GATE_TIM2, RCC_MP_APB1ENSETR, 0, 1), ++ GATE_CFG(GATE_TIM3, RCC_MP_APB1ENSETR, 1, 1), ++ GATE_CFG(GATE_TIM4, RCC_MP_APB1ENSETR, 2, 1), ++ GATE_CFG(GATE_TIM5, RCC_MP_APB1ENSETR, 3, 1), ++ GATE_CFG(GATE_TIM6, RCC_MP_APB1ENSETR, 4, 1), ++ GATE_CFG(GATE_TIM7, RCC_MP_APB1ENSETR, 5, 1), ++ GATE_CFG(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9, 1), ++ GATE_CFG(GATE_SPI2, RCC_MP_APB1ENSETR, 11, 1), ++ GATE_CFG(GATE_SPI3, RCC_MP_APB1ENSETR, 12, 1), ++ GATE_CFG(GATE_USART3, RCC_MP_APB1ENSETR, 15, 1), ++ GATE_CFG(GATE_UART4, RCC_MP_APB1ENSETR, 16, 1), ++ GATE_CFG(GATE_UART5, RCC_MP_APB1ENSETR, 17, 1), ++ GATE_CFG(GATE_UART7, RCC_MP_APB1ENSETR, 18, 1), ++ GATE_CFG(GATE_UART8, RCC_MP_APB1ENSETR, 19, 1), ++ GATE_CFG(GATE_I2C1, RCC_MP_APB1ENSETR, 21, 1), ++ GATE_CFG(GATE_I2C2, RCC_MP_APB1ENSETR, 22, 1), ++ GATE_CFG(GATE_SPDIF, RCC_MP_APB1ENSETR, 26, 1), ++ GATE_CFG(GATE_TIM1, RCC_MP_APB2ENSETR, 0, 1), ++ GATE_CFG(GATE_TIM8, RCC_MP_APB2ENSETR, 1, 1), ++ GATE_CFG(GATE_SPI1, RCC_MP_APB2ENSETR, 8, 1), ++ GATE_CFG(GATE_USART6, RCC_MP_APB2ENSETR, 13, 1), ++ GATE_CFG(GATE_SAI1, RCC_MP_APB2ENSETR, 16, 1), ++ GATE_CFG(GATE_SAI2, RCC_MP_APB2ENSETR, 17, 1), ++ GATE_CFG(GATE_DFSDM, RCC_MP_APB2ENSETR, 20, 1), ++ GATE_CFG(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21, 1), ++ GATE_CFG(GATE_FDCAN, RCC_MP_APB2ENSETR, 24, 1), ++ GATE_CFG(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0, 1), ++ GATE_CFG(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1, 1), ++ GATE_CFG(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2, 1), ++ GATE_CFG(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3, 1), ++ GATE_CFG(GATE_VREF, RCC_MP_APB3ENSETR, 13, 1), ++ GATE_CFG(GATE_DTS, RCC_MP_APB3ENSETR, 16, 1), ++ GATE_CFG(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17, 1), ++ GATE_CFG(GATE_HDP, RCC_MP_APB3ENSETR, 20, 1), ++ GATE_CFG(GATE_SYSCFG, RCC_MP_S_APB3ENSETR, 0, 1), ++ GATE_CFG(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1, 1), ++ GATE_CFG(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8, 1), ++ GATE_CFG(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15, 1), ++ GATE_CFG(GATE_USBPHY, RCC_MP_APB4ENSETR, 16, 1), ++ GATE_CFG(GATE_STGENRO, RCC_MP_APB4ENSETR, 20, 1), ++ GATE_CFG(GATE_LTDC, RCC_MP_S_APB4ENSETR, 0, 1), ++ GATE_CFG(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8, 1), ++ GATE_CFG(GATE_TZC, RCC_MP_APB5ENSETR, 11, 1), ++ GATE_CFG(GATE_ETZPC, RCC_MP_APB5ENSETR, 13, 1), ++ GATE_CFG(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15, 1), ++ GATE_CFG(GATE_BSEC, RCC_MP_APB5ENSETR, 16, 1), ++ GATE_CFG(GATE_STGENC, RCC_MP_APB5ENSETR, 20, 1), ++ GATE_CFG(GATE_USART1, RCC_MP_APB6ENSETR, 0, 1), ++ GATE_CFG(GATE_USART2, RCC_MP_APB6ENSETR, 1, 1), ++ GATE_CFG(GATE_SPI4, RCC_MP_APB6ENSETR, 2, 1), ++ GATE_CFG(GATE_SPI5, RCC_MP_APB6ENSETR, 3, 1), ++ GATE_CFG(GATE_I2C3, RCC_MP_APB6ENSETR, 4, 1), ++ GATE_CFG(GATE_I2C4, RCC_MP_APB6ENSETR, 5, 1), ++ GATE_CFG(GATE_I2C5, RCC_MP_APB6ENSETR, 6, 1), ++ GATE_CFG(GATE_TIM12, RCC_MP_APB6ENSETR, 7, 1), ++ GATE_CFG(GATE_TIM13, RCC_MP_APB6ENSETR, 8, 1), ++ GATE_CFG(GATE_TIM14, RCC_MP_APB6ENSETR, 9, 1), ++ GATE_CFG(GATE_TIM15, RCC_MP_APB6ENSETR, 10, 1), ++ GATE_CFG(GATE_TIM16, RCC_MP_APB6ENSETR, 11, 1), ++ GATE_CFG(GATE_TIM17, RCC_MP_APB6ENSETR, 12, 1), ++ GATE_CFG(GATE_DMA1, RCC_MP_AHB2ENSETR, 0, 1), ++ GATE_CFG(GATE_DMA2, RCC_MP_AHB2ENSETR, 1, 1), ++ GATE_CFG(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2, 1), ++ GATE_CFG(GATE_DMA3, RCC_MP_AHB2ENSETR, 3, 1), ++ GATE_CFG(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4, 1), ++ GATE_CFG(GATE_ADC1, RCC_MP_AHB2ENSETR, 5, 1), ++ GATE_CFG(GATE_ADC2, RCC_MP_AHB2ENSETR, 6, 1), ++ GATE_CFG(GATE_USBO, RCC_MP_AHB2ENSETR, 8, 1), ++ GATE_CFG(GATE_TSC, RCC_MP_AHB4ENSETR, 15, 1), ++ ++ GATE_CFG(GATE_GPIOA, RCC_MP_S_AHB4ENSETR, 0, 1), ++ GATE_CFG(GATE_GPIOB, RCC_MP_S_AHB4ENSETR, 1, 1), ++ GATE_CFG(GATE_GPIOC, RCC_MP_S_AHB4ENSETR, 2, 1), ++ GATE_CFG(GATE_GPIOD, RCC_MP_S_AHB4ENSETR, 3, 1), ++ GATE_CFG(GATE_GPIOE, RCC_MP_S_AHB4ENSETR, 4, 1), ++ GATE_CFG(GATE_GPIOF, RCC_MP_S_AHB4ENSETR, 5, 1), ++ GATE_CFG(GATE_GPIOG, RCC_MP_S_AHB4ENSETR, 6, 1), ++ GATE_CFG(GATE_GPIOH, RCC_MP_S_AHB4ENSETR, 7, 1), ++ GATE_CFG(GATE_GPIOI, RCC_MP_S_AHB4ENSETR, 8, 1), ++ ++ GATE_CFG(GATE_PKA, RCC_MP_AHB5ENSETR, 2, 1), ++ GATE_CFG(GATE_SAES, RCC_MP_AHB5ENSETR, 3, 1), ++ GATE_CFG(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4, 1), ++ GATE_CFG(GATE_HASH1, RCC_MP_AHB5ENSETR, 5, 1), ++ GATE_CFG(GATE_RNG1, RCC_MP_AHB5ENSETR, 6, 1), ++ GATE_CFG(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8, 1), ++ GATE_CFG(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16, 1), ++ GATE_CFG(GATE_MCE, RCC_MP_AHB6ENSETR, 1, 1), ++ GATE_CFG(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7, 1), ++ GATE_CFG(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8, 1), ++ GATE_CFG(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9, 1), ++ GATE_CFG(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10, 1), ++ GATE_CFG(GATE_FMC, RCC_MP_AHB6ENSETR, 12, 1), ++ GATE_CFG(GATE_QSPI, RCC_MP_AHB6ENSETR, 14, 1), ++ GATE_CFG(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16, 1), ++ GATE_CFG(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17, 1), ++ GATE_CFG(GATE_CRC1, RCC_MP_AHB6ENSETR, 20, 1), ++ GATE_CFG(GATE_USBH, RCC_MP_AHB6ENSETR, 24, 1), ++ GATE_CFG(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27, 1), ++ GATE_CFG(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28, 1), ++ GATE_CFG(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29, 1), ++ GATE_CFG(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30, 1), ++ GATE_CFG(GATE_MDMA, RCC_MP_S_AHB6ENSETR, 0, 1), ++}; ++ ++/* ++ * DIV CONFIG ++ */ ++ ++static const struct clk_div_table axi_div_table[] = { ++ { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, ++ { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 }, ++ { 0 }, ++}; ++ ++static const struct clk_div_table mlahb_div_table[] = { ++ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, ++ { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 }, ++ { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 }, ++ { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 }, ++ { 0 }, ++}; ++ ++static const struct clk_div_table apb_div_table[] = { ++ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, ++ { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, ++ { 0 }, ++}; ++ ++#define DIV_CFG(id, _offset, _shift, _width, _flags, _table, _bitrdy)[id] = {\ ++ .offset = _offset,\ ++ .shift = _shift,\ ++ .width = _width,\ ++ .flags = _flags,\ ++ .table = _table,\ ++ .bitrdy = _bitrdy,\ ++} ++ ++static const struct div_cfg dividers_mp13[] = { ++ DIV_CFG(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table, 31), ++ DIV_CFG(DIV_MLAHB, RCC_MLAHBDIVR, 0, 4, 0, mlahb_div_table, 31), ++ DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, 31), ++ DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, 31), ++ DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, 31), ++ DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, 31), ++ DIV_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, 31), ++ DIV_CFG(DIV_APB6, RCC_APB6DIVR, 0, 3, 0, apb_div_table, 31), ++ DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), ++ ++ DIV_CFG(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_BIT_RDY), ++ ++ DIV_CFG(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), ++ DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL, DIV_NO_BIT_RDY), ++}; ++ ++#define MAX_HSI_HZ 64000000 ++#define USB_PHY_48_MHZ 48000000 ++ ++#define TIMEOUT_US_200MS U(200000) ++#define TIMEOUT_US_1S U(1000000) ++ ++#define PLLRDY_TIMEOUT TIMEOUT_US_200MS ++#define CLKSRC_TIMEOUT TIMEOUT_US_200MS ++#define CLKDIV_TIMEOUT TIMEOUT_US_200MS ++#define HSIDIV_TIMEOUT TIMEOUT_US_200MS ++#define OSCRDY_TIMEOUT TIMEOUT_US_1S ++ ++enum stm32_osc { ++ OSC_HSI, ++ OSC_HSE, ++ OSC_CSI, ++ OSC_LSI, ++ OSC_LSE, ++ OSC_I2SCKIN, ++ NB_OSCILLATOR ++}; ++ ++enum stm32mp1_pll_id { ++ _PLL1, ++ _PLL2, ++ _PLL3, ++ _PLL4, ++ _PLL_NB ++}; ++ ++enum stm32mp1_plltype { ++ PLL_800, ++ PLL_1600, ++ PLL_2000, ++ PLL_TYPE_NB ++}; ++ ++#define RCC_OFFSET_PLLXCR 0 ++#define RCC_OFFSET_PLLXCFGR1 4 ++#define RCC_OFFSET_PLLXCFGR2 8 ++#define RCC_OFFSET_PLLXFRACR 12 ++#define RCC_OFFSET_PLLXCSGR 16 ++ ++struct stm32_clk_pll { ++ enum stm32mp1_plltype plltype; ++ uint16_t clk_id; ++ uint16_t reg_pllxcr; ++}; ++ ++struct stm32mp1_pll { ++ uint8_t refclk_min; ++ uint8_t refclk_max; ++}; ++ ++/* Define characteristic of PLL according type */ ++static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { ++ [PLL_800] = { ++ .refclk_min = 4, ++ .refclk_max = 16, ++ }, ++ [PLL_1600] = { ++ .refclk_min = 8, ++ .refclk_max = 16, ++ }, ++ [PLL_2000] = { ++ .refclk_min = 8, ++ .refclk_max = 16, ++ }, ++}; ++ ++#if STM32MP_USB_PROGRAMMER ++static bool pll4_bootrom; ++#endif ++ ++/* RCC clock device driver private */ ++static unsigned int refcounts_mp13[CK_LAST]; ++ ++static const struct stm32_clk_pll *clk_st32_pll_data(unsigned int idx); ++ ++void stm32mp1_clk_force_enable(unsigned long id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int idx = clk_get_index(priv, id); ++ ++ if (!_stm32_clk_is_flags(priv, idx, CLK_IS_CRITICAL)) { ++ _clk_stm32_enable(priv, idx); ++ } ++} ++ ++void stm32mp1_clk_force_disable(unsigned long id) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int idx = clk_get_index(priv, id); ++ ++ if (!_stm32_clk_is_flags(priv, idx, CLK_IS_CRITICAL)) { ++ _clk_stm32_disable(priv, idx); ++ } ++} ++ ++#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER ++static void clk_oscillator_check_bypass(struct stm32_clk_priv *priv, int idx, ++ bool digbyp, bool bypass) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, idx); ++ struct stm32_clk_bypass *bypass_data = osc_data->bypass; ++ uintptr_t address; ++ ++ if (bypass_data == NULL) { ++ return; ++ } ++ ++ address = priv->base + bypass_data->offset; ++ if ((mmio_read_32(address) & RCC_OCENR_HSEBYP) && ++ (!(digbyp || bypass))) { ++ panic(); ++ } ++} ++#endif ++ ++static void stm32_enable_oscillator_hse(struct stm32_clk_priv *priv) ++{ ++ struct stm32_clk_platdata *pdata = priv->pdata; ++ struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE]; ++ bool digbyp = osci->digbyp; ++ bool bypass = osci->bypass; ++ bool css = osci->css; ++ ++ if (_clk_stm32_get_rate(priv, _CK_HSE) == 0U) { ++ return; ++ } ++ ++ clk_oscillator_set_bypass(priv, _CK_HSE, digbyp, bypass); ++ ++ _clk_stm32_enable(priv, _CK_HSE); ++ ++#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER ++ clk_oscillator_check_bypass(priv, _CK_HSE, digbyp, bypass); ++#endif ++ ++ clk_oscillator_set_css(priv, _CK_HSE, css); ++} ++ ++static void stm32_enable_oscillator_lse(struct stm32_clk_priv *priv) ++{ ++ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, _CK_LSE); ++ struct stm32_clk_platdata *pdata = priv->pdata; ++ struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; ++ bool digbyp = osci->digbyp; ++ bool bypass = osci->bypass; ++ uint8_t drive = osci->drive; ++ ++ if (_clk_stm32_get_rate(priv, _CK_LSE) == 0U) { ++ return; ++ } ++ ++ /* Do not reconfigure LSE if already enabled */ ++ if (_clk_stm32_gate_is_enabled(priv, osc_data->gate_id)) { ++ return; ++ } ++ ++ clk_oscillator_set_bypass(priv, _CK_LSE, digbyp, bypass); ++ ++ clk_oscillator_set_drive(priv, _CK_LSE, drive); ++ ++ _clk_stm32_gate_enable(priv, osc_data->gate_id); ++} ++ ++static int stm32mp1_set_hsidiv(uint8_t hsidiv) ++{ ++ uint64_t timeout; ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uintptr_t address = rcc_base + RCC_OCRDYR; ++ ++ mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, ++ RCC_HSICFGR_HSIDIV_MASK, ++ RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); ++ ++ timeout = timeout_init_us(HSIDIV_TIMEOUT); ++ while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", ++ address, mmio_read_32(address)); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++static int stm32mp1_hsidiv(unsigned long hsifreq) ++{ ++ uint8_t hsidiv; ++ uint32_t hsidivfreq = MAX_HSI_HZ; ++ ++ for (hsidiv = 0; hsidiv < 4U; hsidiv++) { ++ if (hsidivfreq == hsifreq) { ++ break; ++ } ++ ++ hsidivfreq /= 2U; ++ } ++ ++ if (hsidiv == 4U) { ++ ERROR("Invalid clk-hsi frequency\n"); ++ return -1; ++ } ++ ++ if (hsidiv != 0U) { ++ return stm32mp1_set_hsidiv(hsidiv); ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_oscillators_lse_set_css(struct stm32_clk_priv *priv) ++{ ++ struct stm32_clk_platdata *pdata = priv->pdata; ++ struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; ++ ++ clk_oscillator_set_css(priv, _CK_LSE, osci->css); ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * 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) ++{ ++ unsigned long apb1_freq; ++ unsigned long rtc_freq; ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ ++ rtc_freq = _clk_stm32_get_rate(priv, _RTCCK); ++ apb1_freq = _clk_stm32_get_rate(priv, _PCLK1); ++ ++ return apb1_freq < (rtc_freq * 7U); ++} ++ ++static int stm32mp1_come_back_to_hsi(void) ++{ ++ int ret; ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ ++ /* Come back to HSI */ ++ ret = _clk_stm32_set_parent(priv, _CKMPU, _CK_HSI); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = _clk_stm32_set_parent(priv, _CKAXI, _CK_HSI); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = _clk_stm32_set_parent(priv, _CKMLAHB, _CK_HSI); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int stm32_clk_configure_clk_get_binding_id(struct stm32_clk_priv *priv, uint32_t data) ++{ ++ unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT; ++ ++ return clk_get_index(priv, binding_id); ++} ++ ++static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data) ++{ ++ int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT; ++ int enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT; ++ int clk_id; ++ int ret; ++ ++ clk_id = stm32_clk_configure_clk_get_binding_id(priv, data); ++ if (clk_id < 0) { ++ return clk_id; ++ } ++ ++ ret = _clk_stm32_set_parent_by_index(priv, clk_id, sel); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (enable) { ++ clk_stm32_enable_call_ops(priv, clk_id); ++ } else { ++ clk_stm32_disable_call_ops(priv, clk_id); ++ } ++ ++ return 0; ++} ++ ++int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data) ++{ ++ int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; ++ int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; ++ ++ return clk_mux_set_parent(priv, mux, sel); ++} ++ ++static int stm32_clk_dividers_configure(struct stm32_clk_priv *priv) ++{ ++ struct stm32_clk_platdata *pdata = priv->pdata; ++ uint32_t i; ++ ++ for (i = 0; i < pdata->nclkdiv; i++) { ++ int div_id, div_n; ++ int val; ++ int ret; ++ ++ val = pdata->clkdiv[i] & CMD_DATA_MASK; ++ div_id = (val & DIV_ID_MASK) >> DIV_ID_SHIFT; ++ div_n = (val & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; ++ ++ ret = clk_stm32_set_div(priv, div_id, div_n); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_source_configure(struct stm32_clk_priv *priv) ++{ ++ struct stm32_clk_platdata *pdata = priv->pdata; ++ bool ckper_disabled = false; ++ int clk_id; ++ int ret; ++ uint32_t i; ++ ++ for (i = 0; i < pdata->nclksrc; i++) { ++ uint32_t val = pdata->clksrc[i]; ++ uint32_t cmd, cmd_data; ++ ++ if (val == (uint32_t)CLK_CKPER_DISABLED) { ++ ckper_disabled = true; ++ continue; ++ } ++ ++ if (val == (uint32_t)CLK_RTC_DISABLED) { ++ continue; ++ } ++ ++ cmd = (val & CMD_MASK) >> CMD_SHIFT; ++ cmd_data = val & ~CMD_MASK; ++ ++ switch (cmd) { ++ case CMD_MUX: ++ ret = stm32_clk_configure_mux(priv, cmd_data); ++ break; ++ ++ case CMD_CLK: ++ clk_id = stm32_clk_configure_clk_get_binding_id(priv, cmd_data); ++ ++ if (clk_id == _RTCCK) { ++ if ((_clk_stm32_is_enabled(priv, _RTCCK) == true)) { ++ continue; ++ } ++ } ++ ++ ret = stm32_clk_configure_clk(priv, cmd_data); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ /* ++ * CKPER is source for some peripheral clocks ++ * (FMC-NAND / QPSI-NOR) and switching source is allowed ++ * only if previous clock is still ON ++ * => deactivate CKPER only after switching clock ++ */ ++ if (ckper_disabled) { ++ ret = stm32_clk_configure_mux(priv, CLK_CKPER_DISABLED & CMD_MASK); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_stgen_configure(struct stm32_clk_priv *priv, int id) ++{ ++ unsigned long stgen_freq; ++ ++ stgen_freq = _clk_stm32_get_rate(priv, id); ++ ++ stm32mp_stgen_config(stgen_freq); ++ ++ return 0; ++} ++ ++#define CLK_PLL_CFG(_idx, _clk_id, _type, _reg)\ ++ [(_idx)] = {\ ++ .clk_id = (_clk_id),\ ++ .plltype = (_type),\ ++ .reg_pllxcr = (_reg),\ ++ } ++ ++static int clk_stm32_pll_compute_cfgr1(struct stm32_clk_priv *priv, ++ const struct stm32_clk_pll *pll, ++ struct stm32_pll_vco *vco, ++ uint32_t *value) ++{ ++ uint32_t divm = vco->div_mn[PLL_CFG_M]; ++ uint32_t divn = vco->div_mn[PLL_CFG_N]; ++ unsigned long prate = 0UL; ++ unsigned long refclk = 0UL; ++ ++ prate = _clk_stm32_get_parent_rate(priv, pll->clk_id); ++ refclk = prate / (divm + 1U); ++ ++ if ((refclk < (stm32mp1_pll[pll->plltype].refclk_min * 1000000U)) || ++ (refclk > (stm32mp1_pll[pll->plltype].refclk_max * 1000000U))) { ++ return -1; ++ } ++ ++ *value = 0; ++ ++ if ((pll->plltype == PLL_800) && (refclk >= 8000000U)) { ++ *value = 1U << RCC_PLLNCFGR1_IFRGE_SHIFT; ++ } ++ ++ *value |= (divn << RCC_PLLNCFGR1_DIVN_SHIFT) & RCC_PLLNCFGR1_DIVN_MASK; ++ *value |= (divm << RCC_PLLNCFGR1_DIVM_SHIFT) & RCC_PLLNCFGR1_DIVM_MASK; ++ ++ return 0; ++} ++ ++static uint32_t clk_stm32_pll_compute_cfgr2(struct stm32_pll_output *out) ++{ ++ uint32_t value = 0; ++ ++ value |= (out->output[PLL_CFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & RCC_PLLNCFGR2_DIVP_MASK; ++ value |= (out->output[PLL_CFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & RCC_PLLNCFGR2_DIVQ_MASK; ++ value |= (out->output[PLL_CFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & RCC_PLLNCFGR2_DIVR_MASK; ++ ++ return value; ++} ++ ++static void clk_stm32_pll_config_vco(struct stm32_clk_priv *priv, ++ const struct stm32_clk_pll *pll, ++ struct stm32_pll_vco *vco) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ uint32_t value = 0; ++ ++ if (clk_stm32_pll_compute_cfgr1(priv, pll, vco, &value) != 0) { ++ ERROR("Invalid Vref clock !\n"); ++ panic(); ++ } ++ ++ /* Write N / M / IFREGE fields */ ++ mmio_write_32(pll_base + RCC_OFFSET_PLLXCFGR1, value); ++ ++ /* Fractional configuration */ ++ mmio_write_32(pll_base + RCC_OFFSET_PLLXFRACR, 0); ++ ++ /* Frac must be enabled only once its configuration is loaded */ ++ mmio_write_32(pll_base + RCC_OFFSET_PLLXFRACR, vco->frac << RCC_PLLNFRACR_FRACV_SHIFT); ++ mmio_setbits_32(pll_base + RCC_OFFSET_PLLXFRACR, RCC_PLLNFRACR_FRACLE); ++} ++ ++static void clk_stm32_pll_config_csg(struct stm32_clk_priv *priv, ++ const struct stm32_clk_pll *pll, ++ struct stm32_pll_vco *vco) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ uint32_t mod_per = 0; ++ uint32_t inc_step = 0; ++ uint32_t sscg_mode = 0; ++ uint32_t value = 0; ++ ++ if (!vco->csg_enabled) { ++ return; ++ } ++ ++ mod_per = vco->csg[PLL_CSG_MOD_PER]; ++ inc_step = vco->csg[PLL_CSG_INC_STEP]; ++ sscg_mode = vco->csg[PLL_CSG_SSCG_MODE]; ++ ++ value |= (mod_per << RCC_PLLNCSGR_MOD_PER_SHIFT) & RCC_PLLNCSGR_MOD_PER_MASK; ++ value |= (inc_step << RCC_PLLNCSGR_INC_STEP_SHIFT) & RCC_PLLNCSGR_INC_STEP_MASK; ++ value |= (sscg_mode << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & RCC_PLLNCSGR_SSCG_MODE_MASK; ++ ++ mmio_write_32(pll_base + RCC_OFFSET_PLLXCSGR, value); ++ mmio_setbits_32(pll_base+ RCC_OFFSET_PLLXCR, RCC_PLLNCR_SSCG_CTRL); ++} ++ ++static void clk_stm32_pll_config_out(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll, ++ struct stm32_pll_output *out) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ uint32_t value = 0; ++ ++ value = clk_stm32_pll_compute_cfgr2(out); ++ ++ mmio_write_32(pll_base + RCC_OFFSET_PLLXCFGR2, value); ++} ++ ++static inline struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ struct stm32_clk_platdata *pdata = priv->pdata; ++ ++ return &pdata->pll[pll_idx]; ++} ++ ++static bool _clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ ++ return ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLON) != 0U); ++} ++ ++static void _clk_stm32_pll_set_on(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ ++ /* Preserve RCC_PLLNCR_SSCG_CTRL value */ ++ mmio_clrsetbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN, ++ RCC_PLLNCR_PLLON); ++} ++ ++static void _clk_stm32_pll_set_off(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ ++ /* Stop all output */ ++ mmio_clrbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); ++ ++ /* Stop PLL */ ++ mmio_clrbits_32(pll_base, RCC_PLLNCR_PLLON); ++} ++ ++static int _clk_stm32_pll_wait_ready_on(struct stm32_clk_priv *priv, ++ const struct stm32_clk_pll *pll) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); ++ ++ /* Wait PLL lock */ ++ while ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLRDY) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ ERROR("%d clock start failed @ 0x%x: 0x%x\n", ++ pll->clk_id, pll->reg_pllxcr, mmio_read_32(pll_base)); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int _clk_stm32_pll_wait_ready_off(struct stm32_clk_priv *priv, ++ const struct stm32_clk_pll *pll) ++{ ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); ++ ++ /* Wait PLL lock */ ++ while ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLRDY) != 0U) { ++ if (timeout_elapsed(timeout)) { ++ ERROR("%d clock stop failed @ 0x%x: 0x%x\n", ++ pll->clk_id, pll->reg_pllxcr, mmio_read_32(pll_base)); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int _clk_stm32_pll_enable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) ++{ ++ if (_clk_stm32_pll_is_enabled(priv, pll)) { ++ return 0; ++ } ++ ++ /* Preserve RCC_PLLNCR_SSCG_CTRL value */ ++ _clk_stm32_pll_set_on(priv, pll); ++ ++ /* Wait PLL lock */ ++ return _clk_stm32_pll_wait_ready_on(priv, pll); ++} ++ ++static void _clk_stm32_pll_disable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) ++{ ++ if (!_clk_stm32_pll_is_enabled(priv, pll)) { ++ return; ++ } ++ ++ /* Stop all ouput and the PLL */ ++ _clk_stm32_pll_set_off(priv, pll); ++ ++ /* Wait PLL stopped */ ++ _clk_stm32_pll_wait_ready_off(priv, pll); ++} ++ ++static int _clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx, ++ struct stm32_pll_dt_cfg *pll_conf) ++{ ++ const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_idx); ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ int ret = 0; ++ ++ /* Configure PLLs source */ ++ ret = stm32_clk_configure_mux(priv, pll_conf->vco.src); ++ if (ret) { ++ return ret; ++ } ++ ++#if STM32MP_USB_PROGRAMMER ++ if ((pll_idx == _PLL4) && pll4_bootrom) { ++ clk_stm32_pll_config_out(priv, pll, &pll_conf->output); ++ ++ mmio_setbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN| ++ RCC_PLLNCR_DIVREN); ++ ++ return 0; ++ } ++#endif ++ /* Stop the PLL before */ ++ _clk_stm32_pll_disable(priv, pll); ++ ++ clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); ++ clk_stm32_pll_config_out(priv, pll, &pll_conf->output); ++ clk_stm32_pll_config_csg(priv, pll, &pll_conf->vco); ++ ++ ret = _clk_stm32_pll_enable(priv, pll); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ mmio_setbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); ++ ++ return 0; ++} ++ ++static int clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx) ++{ ++ struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(pll_idx); ++ ++ if (pll_conf->vco.status) { ++ return _clk_stm32_pll_init(priv, pll_idx, pll_conf); ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_pll_configure(struct stm32_clk_priv *priv) ++{ ++ int err = 0; ++ ++ err = clk_stm32_pll_init(priv, _PLL1); ++ if (err) { ++ return err; ++ } ++ ++ err = clk_stm32_pll_init(priv, _PLL2); ++ if (err) { ++ return err; ++ } ++ ++ err = clk_stm32_pll_init(priv, _PLL3); ++ if (err) { ++ return err; ++ } ++ ++ err = clk_stm32_pll_init(priv, _PLL4); ++ if (err) { ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_oscillators_wait_lse_ready(struct stm32_clk_priv *priv) ++{ ++ int ret = 0; ++ ++ if (_clk_stm32_get_rate(priv, _CK_LSE) != 0U) { ++ ret = clk_oscillator_wait_ready_on(priv, _CK_LSE); ++ } ++ ++ return ret; ++} ++ ++static void stm32_clk_oscillators_enable(struct stm32_clk_priv *priv) ++{ ++ stm32_enable_oscillator_hse(priv); ++ stm32_enable_oscillator_lse(priv); ++ _clk_stm32_enable(priv, _CK_LSI); ++ _clk_stm32_enable(priv, _CK_CSI); ++} ++ ++static int stm32_clk_hsidiv_configure(struct stm32_clk_priv *priv) ++{ ++ return stm32mp1_hsidiv(_clk_stm32_get_rate(priv, _CK_HSI)); ++} ++ ++#if STM32MP_USB_PROGRAMMER ++static bool stm32mp1_clk_is_pll4_used_by_bootrom(struct stm32_clk_priv *priv, int usbphy_p) ++{ ++ /* Don't initialize PLL4, when used by BOOTROM */ ++ if ((stm32mp_get_boot_itf_selected() == ++ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && ++ (usbphy_p == _PLL4R)) { ++ return true; ++ } ++ ++ return false; ++} ++ ++static int stm32mp1_clk_check_usb_conflict(struct stm32_clk_priv *priv, int usbphy_p, int usbo_p) ++{ ++ int _usbo_p; ++ int _usbphy_p; ++ ++ if (!pll4_bootrom) { ++ return 0; ++ } ++ ++ _usbo_p = _clk_stm32_get_parent(priv, _USBO_K); ++ _usbphy_p = _clk_stm32_get_parent(priv, _USBPHY_K); ++ ++ if ((_usbo_p != usbo_p) || (_usbphy_p != usbphy_p)) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ return 0; ++} ++#endif ++ ++static struct clk_oscillator_data stm32mp13_osc_data[NB_OSCILLATOR] = { ++ OSCILLATOR(OSC_HSI, _CK_HSI, "clk-hsi", GATE_HSI, GATE_HSI_RDY, ++ NULL, NULL, NULL), ++ ++ OSCILLATOR(OSC_LSI, _CK_LSI, "clk-lsi", GATE_LSI, GATE_LSI_RDY, ++ NULL, NULL, NULL), ++ ++ OSCILLATOR(OSC_CSI, _CK_CSI, "clk-csi", GATE_CSI, GATE_CSI_RDY, ++ NULL, NULL, NULL), ++ ++ OSCILLATOR(OSC_LSE, _CK_LSE, "clk-lse", GATE_LSE, GATE_LSE_RDY, ++ BYPASS(RCC_BDCR, 1, 3), ++ CSS(RCC_BDCR, 8), ++ DRIVE(RCC_BDCR, 4, 2, 2)), ++ ++ OSCILLATOR(OSC_HSE, _CK_HSE, "clk-hse", GATE_HSE, GATE_HSE_RDY, ++ BYPASS(RCC_OCENSETR, 10, 7), ++ CSS(RCC_OCENSETR, 11), ++ NULL), ++ ++ OSCILLATOR(OSC_I2SCKIN, _I2SCKIN, "i2s_ckin", NO_GATE, NO_GATE, ++ NULL, NULL, NULL), ++}; ++ ++const char *clk_stm32_get_oscillator_name(enum stm32_osc id) ++{ ++ if (id < NB_OSCILLATOR) { ++ return stm32mp13_osc_data[id].name; ++ } ++ ++ return NULL; ++} ++ ++#define CLK_PLL_CFG(_idx, _clk_id, _type, _reg)\ ++ [(_idx)] = {\ ++ .clk_id = (_clk_id),\ ++ .plltype = (_type),\ ++ .reg_pllxcr = (_reg),\ ++ } ++ ++static const struct stm32_clk_pll stm32_mp13_clk_pll[_PLL_NB] = { ++ CLK_PLL_CFG(_PLL1, _CK_PLL1, PLL_2000, RCC_PLL1CR), ++ CLK_PLL_CFG(_PLL2, _CK_PLL2, PLL_1600, RCC_PLL2CR), ++ CLK_PLL_CFG(_PLL3, _CK_PLL3, PLL_800, RCC_PLL3CR), ++ CLK_PLL_CFG(_PLL4, _CK_PLL4, PLL_800, RCC_PLL4CR), ++}; ++ ++static const struct stm32_clk_pll *clk_st32_pll_data(unsigned int idx) ++{ ++ return &stm32_mp13_clk_pll[idx]; ++} ++ ++struct stm32_pll_cfg { ++ int pll_id; ++}; ++ ++static unsigned long clk_stm32_pll_recalc_rate(struct stm32_clk_priv *priv, int id, ++ unsigned long prate) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; ++ const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); ++ uintptr_t pll_base = priv->base + pll->reg_pllxcr; ++ uint32_t cfgr1, fracr, divm, divn; ++ unsigned long fvco; ++ ++ cfgr1 = mmio_read_32(pll_base + RCC_OFFSET_PLLXCFGR1); ++ fracr = mmio_read_32(pll_base + RCC_OFFSET_PLLXFRACR); ++ ++ divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; ++ divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; ++ ++ /* ++ * With FRACV : ++ * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) ++ * Without FRACV ++ * 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; ++ unsigned long long numerator, denominator; ++ ++ numerator = (((unsigned long long)divn + 1U) << 13) + fracv; ++ numerator = prate * numerator; ++ denominator = ((unsigned long long)divm + 1U) << 13; ++ fvco = (unsigned long)(numerator / denominator); ++ } else { ++ fvco = (unsigned long)(prate * (divn + 1U) / (divm + 1U)); ++ } ++ ++ return fvco; ++}; ++ ++static bool clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; ++ const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); ++ ++ return _clk_stm32_pll_is_enabled(priv, pll); ++} ++ ++static int clk_stm32_pll_enable(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; ++ const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); ++ ++ return _clk_stm32_pll_enable(priv, pll); ++} ++ ++static void clk_stm32_pll_disable(struct stm32_clk_priv *priv, int id) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, id); ++ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; ++ const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); ++ ++ _clk_stm32_pll_disable(priv, pll); ++} ++ ++const struct stm32_clk_ops clk_stm32_pll_ops = { ++ .recalc_rate = clk_stm32_pll_recalc_rate, ++ .enable = clk_stm32_pll_enable, ++ .disable = clk_stm32_pll_disable, ++ .is_enabled = clk_stm32_pll_is_enabled, ++}; ++ ++#define CLK_PLL(idx, _idx, _parent, _gate, _pll_id, _flags)[idx] = {\ ++ .name = #idx,\ ++ .binding = _idx,\ ++ .parent = _parent,\ ++ .flags = (_flags),\ ++ .clock_cfg = &(struct stm32_pll_cfg) {\ ++ .pll_id = _pll_id,\ ++ },\ ++ .ops = &clk_stm32_pll_ops,\ ++} ++ ++struct clk_stm32_composite_cfg { ++ int gate_id; ++ int div_id; ++}; ++ ++static unsigned long clk_stm32_composite_recalc_rate(struct stm32_clk_priv *priv, ++ int idx, unsigned long prate) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, idx); ++ struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; ++ ++ return _clk_stm32_divider_recalc(priv, composite_cfg->div_id, prate); ++}; ++ ++bool clk_stm32_composite_gate_is_enabled(struct stm32_clk_priv *priv, int idx) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, idx); ++ struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; ++ ++ return _clk_stm32_gate_is_enabled(priv, composite_cfg->gate_id); ++} ++ ++int clk_stm32_composite_gate_enable(struct stm32_clk_priv *priv, int idx) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, idx); ++ struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; ++ ++ return _clk_stm32_gate_enable(priv, composite_cfg->gate_id); ++} ++ ++void clk_stm32_composite_gate_disable(struct stm32_clk_priv *priv, int idx) ++{ ++ const struct clk_stm32 *clk = _clk_get(priv, idx); ++ struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; ++ ++ _clk_stm32_gate_disable(priv, composite_cfg->gate_id); ++} ++ ++const struct stm32_clk_ops clk_stm32_composite_ops = { ++ .recalc_rate = clk_stm32_composite_recalc_rate, ++ .is_enabled = clk_stm32_composite_gate_is_enabled, ++ .enable = clk_stm32_composite_gate_enable, ++ .disable = clk_stm32_composite_gate_disable, ++}; ++ ++#define STM32_COMPOSITE(idx, _binding, _parent, _flags, _gate_id,\ ++ _div_id)[idx] = {\ ++ .name = #idx,\ ++ .binding = (_binding),\ ++ .parent = (_parent),\ ++ .flags = (_flags),\ ++ .clock_cfg = &(struct clk_stm32_composite_cfg) {\ ++ .gate_id = (_gate_id),\ ++ .div_id = (_div_id),\ ++ },\ ++ .ops = &clk_stm32_composite_ops,\ ++} ++ ++static const struct clk_stm32 stm32mp13_clk[CK_LAST] = { ++ /* ROOT CLOCKS */ ++ CLK_FIXED_RATE(_CK_OFF, _NO_ID, 0), ++ CLK_OSC(_CK_HSE, CK_HSE, CLK_IS_ROOT, OSC_HSE), ++ CLK_OSC(_CK_HSI, CK_HSI, CLK_IS_ROOT, OSC_HSI), ++ CLK_OSC(_CK_CSI, CK_CSI, CLK_IS_ROOT, OSC_CSI), ++ CLK_OSC(_CK_LSI, CK_LSI, CLK_IS_ROOT, OSC_LSI), ++ CLK_OSC(_CK_LSE, CK_LSE, CLK_IS_ROOT, OSC_LSE), ++ ++ CLK_OSC_FIXED(_I2SCKIN, _NO_ID, CLK_IS_ROOT, OSC_I2SCKIN), ++ ++ CLK_FIXED_RATE(_USB_PHY_48, _NO_ID, USB_PHY_48_MHZ), ++ ++ STM32_DIV(_HSE_DIV, _NO_ID, _CK_HSE, 0, DIV_RTC), ++ ++ FIXED_FACTOR(_HSE_DIV2, CK_HSE_DIV2, _CK_HSE, 1, 2), ++ FIXED_FACTOR(_CSI_DIV122, _NO_ID, _CK_CSI, 1, 122), ++ ++ CLK_PLL(_CK_PLL1, PLL1, MUX(MUX_PLL12), GATE_PLL1, _PLL1, 0), ++ CLK_PLL(_CK_PLL2, PLL2, MUX(MUX_PLL12), GATE_PLL2, _PLL2, 0), ++ CLK_PLL(_CK_PLL3, PLL3, MUX(MUX_PLL3), GATE_PLL3, _PLL3, 0), ++ CLK_PLL(_CK_PLL4, PLL4, MUX(MUX_PLL4), GATE_PLL4, _PLL4, 0), ++ ++ STM32_COMPOSITE(_PLL1P, PLL1_P, _CK_PLL1, CLK_IS_CRITICAL, GATE_PLL1_DIVP, DIV_PLL1DIVP), ++ STM32_DIV(_PLL1P_DIV, _NO_ID, _CK_PLL1, 0, DIV_MPU), ++ ++ STM32_COMPOSITE(_PLL2P, PLL2_P, _CK_PLL2, CLK_IS_CRITICAL, GATE_PLL2_DIVP, DIV_PLL2DIVP), ++ STM32_COMPOSITE(_PLL2Q, PLL2_Q, _CK_PLL2, 0, GATE_PLL2_DIVQ, DIV_PLL2DIVQ), ++ STM32_COMPOSITE(_PLL2R, PLL2_R, _CK_PLL2, CLK_IS_CRITICAL, GATE_PLL2_DIVR, DIV_PLL2DIVR), ++ ++ STM32_COMPOSITE(_PLL3P, PLL3_P, _CK_PLL3, 0, GATE_PLL3_DIVP, DIV_PLL3DIVP), ++ STM32_COMPOSITE(_PLL3Q, PLL3_Q, _CK_PLL3, 0, GATE_PLL3_DIVQ, DIV_PLL3DIVQ), ++ STM32_COMPOSITE(_PLL3R, PLL3_R, _CK_PLL3, 0, GATE_PLL3_DIVR, DIV_PLL3DIVR), ++ ++ STM32_COMPOSITE(_PLL4P, PLL4_P, _CK_PLL4, 0, GATE_PLL4_DIVP, DIV_PLL4DIVP), ++ STM32_COMPOSITE(_PLL4Q, PLL4_Q, _CK_PLL4, 0, GATE_PLL4_DIVQ, DIV_PLL4DIVQ), ++ STM32_COMPOSITE(_PLL4R, PLL4_R, _CK_PLL4, 0, GATE_PLL4_DIVR, DIV_PLL4DIVR), ++ ++ STM32_MUX(_CKMPU, CK_MPU, MUX_MPU, 0), ++ STM32_DIV(_CKAXI, CK_AXI, MUX(MUX_AXI), 0, DIV_AXI), ++ STM32_DIV(_CKMLAHB, CK_MLAHB, MUX(MUX_MLAHB), CLK_IS_CRITICAL, DIV_MLAHB), ++ STM32_MUX(_CKPER, CK_PER, MUX(MUX_CKPER), 0), ++ ++ STM32_DIV(_PCLK1, PCLK1, _CKMLAHB, 0, DIV_APB1), ++ STM32_DIV(_PCLK2, PCLK2, _CKMLAHB, 0, DIV_APB2), ++ STM32_DIV(_PCLK3, PCLK3, _CKMLAHB, 0, DIV_APB3), ++ STM32_DIV(_PCLK4, PCLK4, _CKAXI, 0, DIV_APB4), ++ STM32_DIV(_PCLK5, PCLK5, _CKAXI, 0, DIV_APB5), ++ STM32_DIV(_PCLK6, PCLK6, _CKMLAHB, 0, DIV_APB6), ++ ++ CK_TIMER(_CKTIMG1, CK_TIMG1, _PCLK1, 0, RCC_APB1DIVR, RCC_TIMG1PRER), ++ CK_TIMER(_CKTIMG2, CK_TIMG2, _PCLK2, 0, RCC_APB2DIVR, RCC_TIMG2PRER), ++ CK_TIMER(_CKTIMG3, CK_TIMG3, _PCLK6, 0, RCC_APB6DIVR, RCC_TIMG3PRER), ++ ++ /* END ROOT CLOCKS */ ++ ++ STM32_GATE(_DDRC1, DDRC1, _CKAXI, CLK_IS_CRITICAL, GATE_DDRC1), ++ STM32_GATE(_DDRC1LP, DDRC1LP, _CKAXI, CLK_IS_CRITICAL, GATE_DDRC1LP), ++ STM32_GATE(_DDRPHYC, DDRPHYC, _PLL2R, CLK_IS_CRITICAL, GATE_DDRPHYC), ++ STM32_GATE(_DDRPHYCLP, DDRPHYCLP, _PLL2R, CLK_IS_CRITICAL, GATE_DDRPHYCLP), ++ STM32_GATE(_DDRCAPB, DDRCAPB, _PCLK4, CLK_IS_CRITICAL, GATE_DDRCAPB), ++ STM32_GATE(_DDRCAPBLP, DDRCAPBLP, _PCLK4, CLK_IS_CRITICAL, GATE_DDRCAPBLP), ++ STM32_GATE(_AXIDCG, AXIDCG, _CKAXI, CLK_IS_CRITICAL, GATE_AXIDCG), ++ STM32_GATE(_DDRPHYCAPB, DDRPHYCAPB, _PCLK4, CLK_IS_CRITICAL, GATE_DDRPHYCAPB), ++ STM32_GATE(_DDRPHYCAPBLP, DDRPHYCAPBLP, _PCLK4, CLK_IS_CRITICAL, GATE_DDRPHYCAPBLP), ++ ++ STM32_GATE(_SYSCFG, SYSCFG, _PCLK3, 0, GATE_SYSCFG), ++ STM32_GATE(_DDRPERFM, DDRPERFM, _PCLK4, 0, GATE_DDRPERFM), ++ STM32_GATE(_IWDG2APB, IWDG2, _PCLK4, 0, GATE_IWDG2APB), ++ STM32_GATE(_USBPHY_K, USBPHY_K, MUX(MUX_USBPHY), 0, GATE_USBPHY), ++ STM32_GATE(_USBO_K, USBO_K, MUX(MUX_USBO), 0, GATE_USBO), ++ ++ STM32_GATE(_RTCAPB, RTCAPB, _PCLK5, CLK_IS_CRITICAL, GATE_RTCAPB), ++ STM32_GATE(_TZC, TZC, _PCLK5, CLK_IS_CRITICAL, GATE_TZC), ++ STM32_GATE(_ETZPC, TZPC, _PCLK5, CLK_IS_CRITICAL, GATE_ETZPC), ++ STM32_GATE(_IWDG1APB, IWDG1, _PCLK5, 0, GATE_IWDG1APB), ++ STM32_GATE(_BSEC, BSEC, _PCLK5, CLK_IS_CRITICAL, GATE_BSEC), ++ STM32_GATE(_STGENC, STGEN_K, MUX(MUX_STGEN), CLK_IS_CRITICAL, GATE_STGENC), ++ ++ STM32_GATE(_USART1_K, USART1_K, MUX(MUX_UART1), 0, GATE_USART1), ++ STM32_GATE(_USART2_K, USART2_K, MUX(MUX_UART2), 0, GATE_USART2), ++ STM32_GATE(_I2C3_K, I2C3_K, MUX(MUX_I2C3), 0, GATE_I2C3), ++ STM32_GATE(_I2C4_K, I2C4_K, MUX(MUX_I2C4), 0, GATE_I2C4), ++ STM32_GATE(_I2C5_K, I2C5_K, MUX(MUX_I2C5), 0, GATE_I2C5), ++ STM32_GATE(_TIM12, TIM12_K, _CKTIMG3, 0, GATE_TIM12), ++ STM32_GATE(_TIM15, TIM15_K, _CKTIMG3, 0, GATE_TIM15), ++ ++ STM32_GATE(_RTCCK, RTC, MUX(MUX_RTC), 0, GATE_RTCCK), ++ ++ STM32_GATE(_GPIOA, GPIOA, _CKMLAHB, 0, GATE_GPIOA), ++ STM32_GATE(_GPIOB, GPIOB, _CKMLAHB, 0, GATE_GPIOB), ++ STM32_GATE(_GPIOC, GPIOC, _CKMLAHB, 0, GATE_GPIOC), ++ STM32_GATE(_GPIOD, GPIOD, _CKMLAHB, 0, GATE_GPIOD), ++ STM32_GATE(_GPIOE, GPIOE, _CKMLAHB, 0, GATE_GPIOE), ++ STM32_GATE(_GPIOF, GPIOF, _CKMLAHB, 0, GATE_GPIOF), ++ STM32_GATE(_GPIOG, GPIOG, _CKMLAHB, 0, GATE_GPIOG), ++ STM32_GATE(_GPIOH, GPIOH, _CKMLAHB, 0, GATE_GPIOH), ++ STM32_GATE(_GPIOI, GPIOI, _CKMLAHB, 0, GATE_GPIOI), ++ ++ STM32_GATE(_PKA, PKA, _CKAXI, 0, GATE_PKA), ++ STM32_GATE(_SAES_K, SAES_K, MUX(MUX_SAES), 0, GATE_SAES), ++ STM32_GATE(_CRYP1, CRYP1, _PCLK5, 0, GATE_CRYP1), ++ STM32_GATE(_HASH1, HASH1, _PCLK5, 0, GATE_HASH1), ++ ++ STM32_GATE(_RNG1_K, RNG1_K, MUX(MUX_RNG1), 0, GATE_RNG1), ++ STM32_GATE(_BKPSRAM, BKPSRAM, _PCLK5, CLK_IS_CRITICAL, GATE_BKPSRAM), ++ ++ STM32_GATE(_SDMMC1_K, SDMMC1_K, MUX(MUX_SDMMC1), 0, GATE_SDMMC1), ++ STM32_GATE(_SDMMC2_K, SDMMC2_K, MUX(MUX_SDMMC2), 0, GATE_SDMMC2), ++ STM32_GATE(_DBGCK, CK_DBG, _CKAXI, 0, GATE_DBGCK), ++ ++/* TODO: CHECK CLOCK FOR BL2/BL32 AND IF ONLY FOR TEST OR NOT */ ++ STM32_GATE(_USART3_K, USART3_K, MUX(MUX_UART35), 0, GATE_USART3), ++ STM32_GATE(_UART4_K, UART4_K, MUX(MUX_UART4), 0, GATE_UART4), ++ STM32_GATE(_UART5_K, UART5_K, MUX(MUX_UART35), 0, GATE_UART5), ++ STM32_GATE(_UART7_K, UART7_K, MUX(MUX_UART78), 0, GATE_UART7), ++ STM32_GATE(_UART8_K, UART8_K, MUX(MUX_UART78), 0, GATE_UART8), ++ STM32_GATE(_USART6_K, USART6_K, MUX(MUX_UART6), 0, GATE_USART6), ++ STM32_GATE(_MCE, MCE, _CKAXI, CLK_IS_CRITICAL, GATE_MCE), ++ STM32_GATE(_FMC_K, FMC_K, MUX(MUX_FMC), 0, GATE_FMC), ++ STM32_GATE(_QSPI_K, QSPI_K, MUX(MUX_QSPI), 0, GATE_QSPI), ++ ++ STM32_COMPOSITE(_MCO1_K, CK_MCO1, MUX(MUX_MCO1), 0, GATE_MCO1, DIV_MCO1), ++ STM32_COMPOSITE(_MCO2_K, CK_MCO2, MUX(MUX_MCO2), 0, GATE_MCO2, DIV_MCO2), ++ STM32_COMPOSITE(_TRACECK, CK_TRACE, _CKAXI, 0, GATE_TRACECK, DIV_TRACE), ++ ++#if defined(IMAGE_BL32) ++ STM32_GATE(_TIM2, TIM2_K, _CKTIMG1, 0, GATE_TIM2), ++ STM32_GATE(_TIM3, TIM3_K, _CKTIMG1, 0, GATE_TIM3), ++ STM32_GATE(_TIM4, TIM4_K, _CKTIMG1, 0, GATE_TIM4), ++ STM32_GATE(_TIM5, TIM5_K, _CKTIMG1, 0, GATE_TIM5), ++ STM32_GATE(_TIM6, TIM6_K, _CKTIMG1, 0, GATE_TIM6), ++ STM32_GATE(_TIM7, TIM7_K, _CKTIMG1, 0, GATE_TIM7), ++ STM32_GATE(_TIM13, TIM13_K, _CKTIMG3, 0, GATE_TIM13), ++ STM32_GATE(_TIM14, TIM14_K, _CKTIMG3, 0, GATE_TIM14), ++ STM32_GATE(_LPTIM1_K, LPTIM1_K, MUX(MUX_LPTIM1), 0, GATE_LPTIM1), ++ STM32_GATE(_SPI2_K, SPI2_K, MUX(MUX_SPI23), 0, GATE_SPI2), ++ STM32_GATE(_SPI3_K, SPI3_K, MUX(MUX_SPI23), 0, GATE_SPI3), ++ STM32_GATE(_SPDIF_K, SPDIF_K, MUX(MUX_SPDIF), 0, GATE_SPDIF), ++ STM32_GATE(_TIM1, TIM1_K, _CKTIMG2, 0, GATE_TIM1), ++ STM32_GATE(_TIM8, TIM8_K, _CKTIMG2, 0, GATE_TIM8), ++ STM32_GATE(_TIM16, TIM16_K, _CKTIMG3, 0, GATE_TIM16), ++ STM32_GATE(_TIM17, TIM17_K, _CKTIMG3, 0, GATE_TIM17), ++ STM32_GATE(_SPI1_K, SPI1_K, MUX(MUX_SPI1), 0, GATE_SPI1), ++ STM32_GATE(_SPI4_K, SPI4_K, MUX(MUX_SPI4), 0, GATE_SPI4), ++ STM32_GATE(_SPI5_K, SPI5_K, MUX(MUX_SPI5), 0, GATE_SPI5), ++ STM32_GATE(_SAI1_K, SAI1_K, MUX(MUX_SAI1), 0, GATE_SAI1), ++ STM32_GATE(_SAI2_K, SAI2_K, MUX(MUX_SAI2), 0, GATE_SAI2), ++ STM32_GATE(_DFSDM, DFSDM_K, MUX(MUX_SAI1), 0, GATE_DFSDM), ++ STM32_GATE(_FDCAN_K, FDCAN_K, MUX(MUX_FDCAN), 0, GATE_FDCAN), ++ STM32_GATE(_USBH, USBH, _CKAXI, 0, GATE_USBH), ++ STM32_GATE(_I2C1_K, I2C1_K, MUX(MUX_I2C12), 0, GATE_I2C1), ++ STM32_GATE(_I2C2_K, I2C2_K, MUX(MUX_I2C12), 0, GATE_I2C2), ++ STM32_GATE(_ADFSDM, ADFSDM_K, MUX(MUX_SAI1), 0, GATE_ADFSDM), ++ STM32_GATE(_LPTIM2_K, LPTIM2_K, MUX(MUX_LPTIM2), 0, GATE_LPTIM2), ++ STM32_GATE(_LPTIM3_K, LPTIM3_K, MUX(MUX_LPTIM3), 0, GATE_LPTIM3), ++ STM32_GATE(_LPTIM4_K, LPTIM4_K, MUX(MUX_LPTIM45), 0, GATE_LPTIM4), ++ STM32_GATE(_LPTIM5_K, LPTIM5_K, MUX(MUX_LPTIM45), 0, GATE_LPTIM5), ++ STM32_GATE(_VREF, VREF, _PCLK3, 0, GATE_VREF), ++ STM32_GATE(_DTS, TMPSENS, _PCLK3, 0, GATE_DTS), ++ STM32_GATE(_PMBCTRL, PMBCTRL, _PCLK3, 0, GATE_HDP), ++ STM32_GATE(_HDP, HDP, _PCLK3, 0, GATE_PMBCTRL), ++ STM32_GATE(_STGENRO, STGENRO, _PCLK4, 0, GATE_DCMIPP), ++ STM32_GATE(_DCMIPP_K, DCMIPP_K, MUX(MUX_DCMIPP), 0, GATE_DCMIPP), ++ STM32_GATE(_DMAMUX1, DMAMUX1, _CKAXI, 0, GATE_DMAMUX1), ++ STM32_GATE(_DMAMUX2, DMAMUX2, _CKAXI, 0, GATE_DMAMUX2), ++ STM32_GATE(_DMA3, DMA3, _CKAXI, 0, GATE_DMAMUX2), ++ STM32_GATE(_ADC1_K, ADC1_K, MUX(MUX_ADC1), 0, GATE_ADC1), ++ STM32_GATE(_ADC2_K, ADC2_K, MUX(MUX_ADC2), 0, GATE_ADC2), ++ STM32_GATE(_TSC, TSC, _CKAXI, 0, GATE_TSC), ++ STM32_GATE(_AXIMC, AXIMC, _CKAXI, 0, GATE_AXIMC), ++ STM32_GATE(_CRC1, CRC1, _CKAXI, 0, GATE_ETH1TX), ++ STM32_GATE(_ETH1CK, ETH1CK_K, MUX(MUX_ETH1), 0, GATE_ETH1CK), ++ STM32_GATE(_ETH1TX, ETH1TX, _CKAXI, 0, GATE_ETH1TX), ++ STM32_GATE(_ETH1RX, ETH1RX, _CKAXI, 0, GATE_ETH1RX), ++ STM32_GATE(_ETH2CK, ETH2CK_K, MUX(MUX_ETH2), 0, GATE_ETH2CK), ++ STM32_GATE(_ETH2TX, ETH2TX, _CKAXI, 0, GATE_ETH2TX), ++ STM32_GATE(_ETH2RX, ETH2RX, _CKAXI, 0, GATE_ETH2RX), ++ STM32_GATE(_ETH2MAC, ETH2MAC, _CKAXI, 0, GATE_ETH2MAC), ++#endif ++}; ++ ++struct stm32_pll_dt_cfg mp13_pll[_PLL_NB]; ++ ++struct stm32_osci_dt_cfg mp13_osci[NB_OSCILLATOR]; ++ ++uint32_t mp13_clksrc[MUX_MAX]; ++ ++uint32_t mp13_clkdiv[DIV_MAX]; ++ ++struct stm32_clk_platdata stm32mp13_clock_pdata = { ++ .osci = mp13_osci, ++ .nosci = NB_OSCILLATOR, ++ .pll = mp13_pll, ++ .npll = _PLL_NB, ++ .clksrc = mp13_clksrc, ++ .nclksrc = MUX_MAX, ++ .clkdiv = mp13_clkdiv, ++ .nclkdiv = DIV_MAX, ++}; ++ ++static struct stm32_clk_priv stm32mp13_clock_data = { ++ .base = RCC_BASE, ++ .num = ARRAY_SIZE(stm32mp13_clk), ++ .clks = stm32mp13_clk, ++ .parents = parent_mp13, ++ .nb_parents = ARRAY_SIZE(parent_mp13), ++ .gates = gates_mp13, ++ .nb_gates = ARRAY_SIZE(gates_mp13), ++ .div = dividers_mp13, ++ .nb_div = ARRAY_SIZE(dividers_mp13), ++ .osci_data = stm32mp13_osc_data, ++ .nb_osci_data = ARRAY_SIZE(stm32mp13_osc_data), ++ .gate_refcounts = refcounts_mp13, ++ .pdata = &stm32mp13_clock_pdata, ++}; ++ ++static int stm32mp1_init_clock_tree(void) ++{ ++ struct stm32_clk_priv *priv = clk_stm32_get_priv(); ++ int ret; ++ ++#if STM32MP_USB_PROGRAMMER ++ int usbphy_p = _clk_stm32_get_parent(priv, _USBPHY_K); ++ int usbo_p = _clk_stm32_get_parent(priv, _USBO_K); ++ ++ /* Don't initialize PLL4, when used by BOOTROM */ ++ pll4_bootrom = stm32mp1_clk_is_pll4_used_by_bootrom(priv, usbphy_p); ++#endif ++ ++ /* ++ * Switch ON oscillators found in device-tree. ++ * Note: HSI already ON after BootROM stage. ++ */ ++ stm32_clk_oscillators_enable(priv); ++ ++ /* Come back to HSI */ ++ ret = stm32mp1_come_back_to_hsi(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = stm32_clk_hsidiv_configure(priv); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = stm32_clk_stgen_configure(priv, _STGENC); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ ret = stm32_clk_dividers_configure(priv); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ ret = stm32_clk_pll_configure(priv); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ /* Wait LSE ready before to use it */ ++ ret = stm32_clk_oscillators_wait_lse_ready(priv); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ /* Configure with expected clock source */ ++ ret = stm32_clk_source_configure(priv); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ /* Configure LSE css after RTC source configuration */ ++ ret = stm32_clk_oscillators_lse_set_css(priv); ++ if (ret != 0) { ++ panic(); ++ } ++ ++#if STM32MP_USB_PROGRAMMER ++ ret = stm32mp1_clk_check_usb_conflict(priv, usbphy_p, usbo_p); ++ if (ret != 0) { ++ return ret; ++ } ++#endif ++ /* reconfigure STGEN with DT config */ ++ ret = stm32_clk_stgen_configure(priv, _STGENC); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ /* Software Self-Refresh mode (SSR) during DDR initilialization */ ++ mmio_clrsetbits_32(priv->base + RCC_DDRITFCR, ++ RCC_DDRITFCR_DDRCKMOD_MASK, ++ RCC_DDRITFCR_DDRCKMOD_SSR << ++ RCC_DDRITFCR_DDRCKMOD_SHIFT); ++ ++ return 0; ++} ++ ++#define LSEDRV_MEDIUM_HIGH 2 ++ ++int clk_stm32_parse_oscillator_fdt(void *fdt, int node, const char *name, ++ struct stm32_osci_dt_cfg *osci) ++{ ++ int subnode = 0; ++ ++ /* default value oscillator not found, freq=0 */ ++ osci->freq = 0; ++ ++ fdt_for_each_subnode(subnode, fdt, node) { ++ const char *cchar = NULL; ++ const fdt32_t *cuint = NULL; ++ int ret = 0; ++ ++ cchar = fdt_get_name(fdt, subnode, &ret); ++ if (cchar == NULL) { ++ return ret; ++ } ++ ++ if (strncmp(cchar, name, (size_t)ret) || ++ fdt_get_status(subnode) == DT_DISABLED) { ++ continue; ++ } ++ ++ cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); ++ if (cuint == NULL) { ++ return ret; ++ } ++ ++ osci->freq = fdt32_to_cpu(*cuint); ++ ++ if (fdt_getprop(fdt, subnode, "st,bypass", NULL) != NULL) { ++ osci->bypass = true; ++ } ++ ++ if (fdt_getprop(fdt, subnode, "st,digbypass", NULL) != NULL) { ++ osci->digbyp = true; ++ } ++ ++ if (fdt_getprop(fdt, subnode, "st,css", NULL) != NULL) { ++ osci->css = true; ++ } ++ ++ osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH); ++ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_parse_fdt_all_oscillator(void *fdt, struct stm32_clk_platdata *pdata) ++{ ++ int fdt_err = 0; ++ uint32_t i = 0; ++ int node = 0; ++ ++ node = fdt_path_offset(fdt, "/clocks"); ++ if (node < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ for (i = 0; i < pdata->nosci; i++) { ++ const char *name = NULL; ++ ++ name = clk_stm32_get_oscillator_name((enum stm32_osc) i); ++ if (name == NULL) { ++ continue; ++ } ++ ++ fdt_err = clk_stm32_parse_oscillator_fdt(fdt, node, name, &pdata->osci[i]); ++ if (fdt_err < 0) { ++ panic(); ++ } ++ } ++ ++ return 0; ++} ++ ++#define RCC_PLL_NAME_SIZE 12 ++ ++static int clk_stm32_load_vco_config(void * fdt, int subnode, struct stm32_pll_vco *vco) ++{ ++ int err = 0; ++ ++ err = fdt_read_uint32_array(fdt, subnode, "divmn", (int)PLL_DIV_MN_NB, vco->div_mn); ++ if (err != 0) { ++ return err; ++ } ++ ++ err = fdt_read_uint32_array(fdt, subnode, "csg", (int)PLL_CSG_NB, vco->csg); ++ ++ vco->csg_enabled = (err == 0); ++ ++ if (err == -FDT_ERR_NOTFOUND) { ++ err = 0; ++ } ++ ++ if (err != 0) { ++ return err; ++ } ++ ++ vco->status = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN | RCC_PLLNCR_PLLON; ++ ++ vco->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0); ++ ++ vco->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX); ++ ++ return 0; ++} ++ ++static int clk_stm32_load_output_config(void * fdt, int subnode, struct stm32_pll_output *output) ++{ ++ int err = 0; ++ ++ err = fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", (int)PLL_DIV_PQR_NB, ++ output->output); ++ if (err != 0) { ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) ++{ ++ const fdt32_t *cuint = NULL; ++ int subnode_pll = 0; ++ int subnode_vco = 0; ++ int err = 0; ++ ++ cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); ++ if (!cuint) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); ++ if (subnode_pll < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL); ++ if (!cuint) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); ++ if (subnode_vco < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ err = clk_stm32_load_vco_config(fdt, subnode_vco, &pll->vco); ++ if (err != 0) { ++ return err; ++ } ++ ++ err = clk_stm32_load_output_config(fdt, subnode_pll, &pll->output); ++ if (err != 0) { ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata) ++{ ++ size_t i = 0; ++ ++ for (i = _PLL1; i < pdata->npll; i++) { ++ struct stm32_pll_dt_cfg *pll = pdata->pll + i; ++ char name[RCC_PLL_NAME_SIZE]; ++ int subnode = 0; ++ int err = 0; ++ ++ snprintf(name, sizeof(name), "st,pll@%d", i); ++ ++ subnode = fdt_subnode_offset(fdt, node, name); ++ if (!fdt_check_node(subnode)) { ++ continue; ++ } ++ ++ err = clk_stm32_parse_pll_fdt(fdt, subnode, pll); ++ if (err != 0) { ++ panic(); ++ } ++ } ++ ++ return 0; ++} ++ ++static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata) ++{ ++ void *fdt = NULL; ++ int node; ++ uint32_t err; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); ++ if (node < 0) { ++ panic(); ++ } ++ ++ err = stm32_clk_parse_fdt_all_oscillator(fdt, pdata); ++ if (err != 0) { ++ return err; ++ } ++ ++ err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); ++ if (err != 0) { ++ return err; ++ } ++ ++ err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, &pdata->nclkdiv); ++ if (err != 0) { ++ return err; ++ } ++ ++ err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, &pdata->nclksrc); ++ if (err != 0) { ++ return err; ++ } ++ ++ return 0; ++} ++ ++int stm32mp1_clk_init(uint32_t pll1_freq_khz) ++{ ++ return 0; ++} ++ ++int stm32mp1_clk_probe(void) ++{ ++ uintptr_t base = RCC_BASE; ++ int ret; ++ ++ ret = stm32_clk_parse_fdt(&stm32mp13_clock_pdata); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = clk_stm32_init(&stm32mp13_clock_data, base); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = stm32mp1_init_clock_tree(); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ clk_stm32_enable_critical_clocks(); ++ ++ return 0; ++} +diff --git a/drivers/st/clk/stm32mp1_calib.c b/drivers/st/clk/stm32mp1_calib.c +new file mode 100644 +index 000000000..11a334303 +--- /dev/null ++++ b/drivers/st/clk/stm32mp1_calib.c +@@ -0,0 +1,536 @@ ++/* ++ * 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 ++#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_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_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) ++{ ++ 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 = 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 = 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 > INT32_MAX) { ++ timer_val = INT32_MAX; ++ } ++ ++ if (timer_val != 0U) { ++ /* Load & enable timer */ ++ INFO("Set calibration timer to %u sec\n", ++ timer_val / plat_get_syscnt_freq2()); ++ 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 3ebc376cd..3e11438ad 100644 +--- a/drivers/st/clk/stm32mp1_clk.c ++++ b/drivers/st/clk/stm32mp1_clk.c +@@ -1,11 +1,12 @@ + /* +- * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + + #include + #include ++#include + #include + #include + +@@ -17,8 +18,8 @@ + #include + #include + #include ++#include + #include +-#include + #include + #include + #include +@@ -49,6 +50,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 */ + +@@ -233,7 +247,6 @@ enum stm32mp1_plltype { + struct stm32mp1_pll { + uint8_t refclk_min; + uint8_t refclk_max; +- uint8_t divn_max; + }; + + struct stm32mp1_clk_gate { +@@ -241,6 +254,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 */ + }; +@@ -265,46 +279,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), \ + } +@@ -338,81 +365,90 @@ struct stm32mp1_clk_pll { + + #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_BDCR, 20, RTC, _RTC_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 ++ _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), ++ ++#if defined(IMAGE_BL32) ++ _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), ++#endif ++ _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), ++ ++ _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), ++ ++ _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), ++ ++#if defined(IMAGE_BL32) ++ _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 ++ ++ _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), ++ ++ _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_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(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), ++ _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), + }; + + static const uint8_t i2c12_parents[] = { +@@ -521,17 +557,14 @@ 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, + .refclk_max = 16, +- .divn_max = 99, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, +- .divn_max = 199, + }, + }; + +@@ -622,12 +655,28 @@ 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; ++#if defined(IMAGE_BL32) ++static uint32_t save_current_opp_khz; ++static uint32_t pll3cr; ++static uint32_t pll4cr; ++static uint32_t mssckselr; ++static uint32_t mcudivr; ++#endif + + static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) + { + return &stm32mp1_clk_gate[idx]; + } + ++#if defined(IMAGE_BL32) ++static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) ++{ ++ return gate->secure == N_S; ++} ++#endif ++ + static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) + { + return &stm32mp1_clk_sel[idx]; +@@ -1037,7 +1086,8 @@ static void __clk_enable(struct stm32mp1_clk_gate const *gate) + 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)); + } + } + +@@ -1051,7 +1101,8 @@ static void __clk_disable(struct stm32mp1_clk_gate const *gate) + 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)); + } + } + +@@ -1062,17 +1113,6 @@ 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) +-{ +- int i = stm32mp1_clk_get_gated_id(id); +- +- if (i < 0) { +- panic(); +- } +- +- return gate_refcounts[i]; +-} +- + /* Oscillators and PLLs are not gated at runtime */ + static bool clock_is_always_on(unsigned long id) + { +@@ -1101,11 +1141,10 @@ static bool clock_is_always_on(unsigned long id) + } + } + +-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; +- unsigned int *refcnt; + + if (clock_is_always_on(id)) { + return; +@@ -1118,22 +1157,38 @@ void __stm32mp1_clk_enable(unsigned long id, bool secure) + } + + 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; +- unsigned int *refcnt; + + if (clock_is_always_on(id)) { + return; +@@ -1146,28 +1201,56 @@ void __stm32mp1_clk_disable(unsigned long id, bool secure) + } + + 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); + } + + stm32mp1_clk_unlock(&refcount_lock); + } + +-void stm32mp_clk_enable(unsigned long id) ++static int stm32mp_clk_enable(unsigned long id) + { + __stm32mp1_clk_enable(id, true); ++ ++ return 0; + } + +-void stm32mp_clk_disable(unsigned long id) ++static void stm32mp_clk_disable(unsigned long id) + { + __stm32mp1_clk_disable(id, true); + } + +-bool stm32mp_clk_is_enabled(unsigned long id) ++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); ++} ++ ++static bool stm32mp_clk_is_enabled(unsigned long id) + { + int i; + +@@ -1183,15 +1266,55 @@ bool stm32mp_clk_is_enabled(unsigned long id) + return __clk_is_enabled(gate_ref(i)); + } + +-unsigned long stm32mp_clk_get_rate(unsigned long id) ++static unsigned long stm32mp_clk_get_rate(unsigned long id) + { ++ uintptr_t rcc_base = stm32mp_rcc_base(); + int p = stm32mp1_clk_get_parent(id); ++ uint32_t prescaler, timpre; ++ unsigned long parent_rate; + + if (p < 0) { + return 0; + } + +- return get_clock_rate(p); ++ parent_rate = get_clock_rate(p); ++ ++ switch (id) { ++ case TIM2_K: ++ case TIM3_K: ++ case TIM4_K: ++ case TIM5_K: ++ case TIM6_K: ++ case TIM7_K: ++ case TIM12_K: ++ case TIM13_K: ++ case TIM14_K: ++ prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & ++ RCC_APBXDIV_MASK; ++ timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & ++ RCC_TIMGXPRER_TIMGXPRE; ++ break; ++ ++ case TIM1_K: ++ case TIM8_K: ++ case TIM15_K: ++ case TIM16_K: ++ case TIM17_K: ++ prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & ++ RCC_APBXDIV_MASK; ++ timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & ++ RCC_TIMGXPRER_TIMGXPRE; ++ break; ++ ++ default: ++ return parent_rate; ++ } ++ ++ if (prescaler == 0U) { ++ return parent_rate; ++ } ++ ++ return parent_rate * (timpre + 1U) * 2U; + } + + static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) +@@ -1242,6 +1365,11 @@ static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) + uint32_t value; + uintptr_t rcc_base = stm32mp_rcc_base(); + ++ /* Do not reconfigure LSE if it is already ON */ ++ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEON) == RCC_BDCR_LSEON) { ++ return; ++ } ++ + if (digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); + } +@@ -1308,6 +1436,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 STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER ++ if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) && ++ (!(digbyp || bypass))) { ++ panic(); ++ } ++#endif + } + + static void stm32mp1_csi_set(bool enable) +@@ -1507,11 +1642,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) & +@@ -1520,21 +1652,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); +@@ -1548,23 +1692,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); + +@@ -1671,48 +1831,41 @@ static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) + } + } + +-static void stm32mp1_stgen_config(void) ++/******************************************************************************* ++ * 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 cntfid0; +- unsigned long rate; +- unsigned long long counter; +- +- cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); +- rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); ++ unsigned long apb1_freq; ++ uint32_t rtc_freq; ++ uint32_t apb1_div; ++ uintptr_t rcc_base = stm32mp_rcc_base(); + +- if (cntfid0 == rate) { +- return; ++ 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(); + } + +- mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); +- counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF); +- counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32; +- counter = (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((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 long cnt; +- +- cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | +- mmio_read_32(STGEN_BASE + CNTCVL_OFF); +- +- cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + 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_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); ++ return apb1_freq < (rtc_freq * 7U); + } + + static void stm32mp1_pkcs_config(uint32_t pkcs) +@@ -1729,152 +1882,743 @@ 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; +- void *fdt; ++ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID; ++} + +- if (fdt_get_address(&fdt) == 0) { +- return -FDT_ERR_NOTFOUND; +- } ++#if defined(IMAGE_BL32) ++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; + +- /* Check status field to disable security */ +- if (!fdt_get_rcc_secure_status()) { +- mmio_write_32(rcc_base + RCC_TZCR, 0); ++ return 0; + } + +- ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, +- clksrc); +- 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", (uint32_t)CLKDIV_NB, +- clkdiv); +- 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(fdt, plloff[i], "cfg", +- (int)PLLCFG_NB, pllcfg[i]); +- 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); +- if (ret != 0) { ++ ++ 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_set_clksrc(CLK_MCU_HSI); ++ ++ 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 ((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]); ++ if (config_on_the_fly == 1) { ++ /* No need to reconfigure, setup already OK */ ++ return 0; + } + +- for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { +- if (((i == _PLL3) && pll3_preserve) || +- ((i == _PLL4) && pll4_preserve)) { +- continue; +- } +- +- ret = stm32mp1_pll_stop(i); ++ 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; + } +- } + +- /* Configure HSIDIV */ +- if (stm32mp1_osc[_HSI] != 0U) { +- ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); ++ ret = stm32mp1_pll_stop(_PLL1); + if (ret != 0) { + return ret; + } +- stm32mp1_stgen_config(); + } + +- /* Select DIV */ +- /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ +- mmio_write_32(rcc_base + RCC_MPCKDIVR, +- clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); +- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); ++ ret = stm32mp1_pll_config(_PLL1, &pll1_settings.cfg[i][0], ++ pll1_settings.frac[i]); + if (ret != 0) { + return ret; + } +- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); +- if (ret != 0) { ++ ++ 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; ++} ++#endif /* IMAGE_BL32 */ ++ ++static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg, ++ uint32_t *fracv, uint32_t *csg, ++ bool *csg_set) ++{ ++ void *fdt; ++ int ret; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB, ++ pllcfg); ++ if (ret < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ *fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); ++ ++ ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB, ++ csg); ++ ++ *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; ++ void *fdt; ++ int stgen_p = stm32mp1_clk_get_parent(STGEN_K); ++ int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K); ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, ++ clksrc); ++ if (ret < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, ++ clkdiv); ++ 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) { ++ const char *name = stm32mp_osc_node_label[_LSE]; ++ bool bypass, digbyp; ++ uint32_t lsedrv; ++ ++ bypass = fdt_clk_read_bool(name, "st,bypass"); ++ digbyp = fdt_clk_read_bool(name, "st,digbypass"); ++ lse_css = fdt_clk_read_bool(name, "st,css"); ++ lsedrv = fdt_clk_read_uint32_default(name, "st,drive", ++ LSEDRV_MEDIUM_HIGH); ++ stm32mp1_lse_enable(bypass, digbyp, lsedrv); ++ } ++ if (stm32mp1_osc[_HSE] != 0U) { ++ const char *name = stm32mp_osc_node_label[_HSE]; ++ bool bypass, digbyp, css; ++ ++ bypass = fdt_clk_read_bool(name, "st,bypass"); ++ digbyp = fdt_clk_read_bool(name, "st,digbypass"); ++ css = fdt_clk_read_bool(name, "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; ++ } ++ 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 ((stm32mp_get_boot_itf_selected() == ++ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_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) || ++ ((i == _PLL4) && pll4_preserve)) { ++ continue; ++ } ++ ++ ret = stm32mp1_pll_stop(i); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ /* Configure HSIDIV */ ++ if (stm32mp1_osc[_HSI] != 0U) { ++ ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); ++ } ++ ++ /* Select DIV */ ++ /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ ++ mmio_write_32(rcc_base + RCC_MPCKDIVR, ++ clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); ++ 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_APB5], rcc_base + RCC_APB5DIVR); +@@ -1924,15 +2668,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; + } + +@@ -1942,25 +2683,20 @@ int stm32mp1_clk_init(void) + continue; + } + +- fracv = fdt_read_uint32_default(fdt, 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(fdt, plloff[i], "csg", +- (uint32_t)PLLCSG_NB, csg); +- 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; + } + +@@ -1994,6 +2730,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]); +@@ -2014,13 +2755,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, +@@ -2210,6 +2971,410 @@ void stm32mp1_register_clock_parents_secure(unsigned long clock_id) + } + #endif /* STM32MP_SHARED_RESOURCES */ + ++#if defined(IMAGE_BL32) ++/* ++ * 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)); ++ offset += sizeof(gate_refcounts); ++ ++ save_current_opp_khz = current_opp_khz; ++ ++ stm32mp1_pm_save_clock_cfg(offset, ++ (uint8_t *)&save_current_opp_khz, ++ sizeof(save_current_opp_khz)); ++} ++ ++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)); ++ offset += sizeof(gate_refcounts); ++ ++ stm32mp1_pm_restore_clock_cfg(offset, ++ (uint8_t *)&save_current_opp_khz, ++ sizeof(save_current_opp_khz)); ++ ++ stm32mp1_set_opp_khz(save_current_opp_khz); ++} ++ ++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; ++ ++ restore_mux_cfg(); ++ restore_sc_cfg(); ++ restore_regular_cfg(); ++ ++ /* 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 (clock_is_always_on(gate->index)) { ++ continue; ++ } ++ ++ 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; ++} ++#endif /* IMAGE_BL32 */ ++ ++void stm32mp1_clk_mcuss_protect(bool enable) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ if (enable) { ++ mmio_setbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); ++ } else { ++ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); ++ } ++} ++ + static void sync_earlyboot_clocks_state(void) + { + unsigned int idx; +@@ -2231,11 +3396,39 @@ static void sync_earlyboot_clocks_state(void) + } + } + ++static const struct clk_ops stm32mp_clk_ops = { ++ .enable = stm32mp_clk_enable, ++ .disable = stm32mp_clk_disable, ++ .is_enabled = stm32mp_clk_is_enabled, ++ .get_rate = stm32mp_clk_get_rate, ++ .get_parent = stm32mp1_clk_get_parent, ++}; ++ + int stm32mp1_clk_probe(void) + { ++ unsigned long freq_khz; ++ ++ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB); ++ ++#if defined(IMAGE_BL32) ++ if (!fdt_get_rcc_secure_state()) { ++ mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U); ++ } ++#endif ++ + 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; ++ ++ clk_register(&stm32mp_clk_ops); ++ + return 0; + } +diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c +index d57f120b9..37e87d7cd 100644 +--- a/drivers/st/clk/stm32mp_clkfunc.c ++++ b/drivers/st/clk/stm32mp_clkfunc.c +@@ -10,9 +10,13 @@ + + #include + ++#include + #include ++#include ++#include + #include + #include ++#include + + /* + * Get the frequency of an oscillator from its name in device tree. +@@ -43,7 +47,8 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) + return ret; + } + +- 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", +@@ -69,7 +74,7 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) + * @param prop_name: property name + * @return: true/false regarding search result. + */ +-bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) ++bool fdt_clk_read_bool(const char *node_label, const char *prop_name) + { + int node, subnode; + void *fdt; +@@ -78,10 +83,6 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) + return false; + } + +- if (osc_id >= NB_OSC) { +- return false; +- } +- + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return false; +@@ -96,8 +97,7 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) + return false; + } + +- if (strncmp(cchar, stm32mp_osc_node_label[osc_id], +- (size_t)ret) != 0) { ++ if (strncmp(cchar, node_label, (size_t)ret) != 0) { + continue; + } + +@@ -110,13 +110,13 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) + } + + /* +- * Get the value of a oscillator property from its ID. +- * @param osc_id: oscillator ID ++ * Get the value of a oscillator property from its name. ++ * @param node_label: oscillator name + * @param prop_name: property name + * @param dflt_value: default value + * @return oscillator value on success, default value if property not found. + */ +-uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, ++uint32_t fdt_clk_read_uint32_default(const char *node_label, + const char *prop_name, uint32_t dflt_value) + { + int node, subnode; +@@ -126,10 +126,6 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, + return dflt_value; + } + +- if (osc_id >= NB_OSC) { +- return dflt_value; +- } +- + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return dflt_value; +@@ -144,8 +140,7 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, + return dflt_value; + } + +- if (strncmp(cchar, stm32mp_osc_node_label[osc_id], +- (size_t)ret) != 0) { ++ if (strncmp(cchar, node_label, (size_t)ret) != 0) { + continue; + } + +@@ -197,6 +192,29 @@ int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, + return fdt_read_uint32_array(fdt, node, prop_name, count, array); + } + ++/******************************************************************************* ++ * This function reads a property rcc-clk section. ++ * It reads the values indicated inside the device tree, from property name. ++ * Returns dflt_value if property is not found, and a property value on ++ * success. ++ ******************************************************************************/ ++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_get_rcc_node(fdt); ++ if (node < 0) { ++ return dflt_value; ++ } ++ ++ return fdt_read_uint32_default(fdt, node, prop_name, dflt_value); ++} ++ + /* + * Get the subnode offset in rcc-clk section from its name in device tree + * @param name: name of the RCC property +@@ -255,24 +273,38 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) + } + + /* +- * Get the secure status for rcc node in device tree. +- * @return: true if rcc is available from secure world, false if not. ++ * Get the secure state for rcc node in device tree. ++ * @return: true if rcc is configured for secure world access, false if not. + */ +-bool fdt_get_rcc_secure_status(void) ++bool fdt_get_rcc_secure_state(void) + { +- int node; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + +- node = fdt_get_rcc_node(fdt); +- if (node < 0) { ++ if (fdt_node_offset_by_compatible(fdt, -1, DT_RCC_SEC_CLK_COMPAT) < 0) { + return false; + } + +- return !!(fdt_get_status(node) & DT_SECURE); ++ return true; ++} ++ ++/* ++ * This function gets interrupt name. ++ * It reads the values indicated the enabling status. ++ * Returns 0 if success, and a negative value else. ++ */ ++int fdt_rcc_enable_it(const char *name) ++{ ++ void *fdt; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ return stm32mp_gic_enable_spi(fdt_get_rcc_node(fdt), name); + } + + /* +@@ -297,3 +329,134 @@ 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. ++ * 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_by_name(int node, const char *name) ++{ ++ const fdt32_t *cuint; ++ void *fdt; ++ int index, len; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ index = fdt_stringlist_search(fdt, node, "clock-names", name); ++ if (index < 0) { ++ return index; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "clocks", &len); ++ if (cuint == NULL) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if ((index * (int)sizeof(uint32_t)) > len) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ cuint += (index << 1) + 1; ++ return (int)fdt32_to_cpu(*cuint); ++} ++ ++/* ++ * Get the frequency of the specified UART instance. ++ * @param instance: UART interface registers base address. ++ * @return: clock frequency on success, 0 value on failure. ++ */ ++unsigned long fdt_get_uart_clock_freq(uintptr_t instance) ++{ ++ void *fdt; ++ int node; ++ int clk_id; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return 0UL; ++ } ++ ++ /* Check for UART nodes */ ++ node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance); ++ if (node < 0) { ++ return 0UL; ++ } ++ ++ clk_id = fdt_get_clock_id(node); ++ if (clk_id < 0) { ++ return 0UL; ++ } ++ ++ return clk_get_rate((unsigned long)clk_id); ++} ++ ++/******************************************************************************* ++ * 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 restores CPU generic timer rate from the STGEN clock rate. ++ ******************************************************************************/ ++void stm32mp_stgen_restore_rate(void) ++{ ++ unsigned long rate; ++ ++ rate = mmio_read_32(STGEN_BASE + CNTFID_OFF); ++ ++ write_cntfrq_el0((u_register_t)rate); ++} ++ ++/******************************************************************************* ++ * This function returns the STGEN counter value. ++ ******************************************************************************/ ++unsigned long long stm32mp_stgen_get_counter(void) ++{ ++ return (((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | ++ mmio_read_32(STGEN_BASE + CNTCVL_OFF)); ++} ++ ++/******************************************************************************* ++ * 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; ++ ++ cnt = value + ((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 317fd9eb8..ed0c5bdd9 100644 +--- a/drivers/st/crypto/stm32_hash.c ++++ b/drivers/st/crypto/stm32_hash.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,6 +14,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -21,7 +22,12 @@ + #include + #include + ++#if STM32MP13 ++#define DT_HASH_COMPAT "st,stm32mp13-hash" ++#endif ++#if STM32MP15 + #define DT_HASH_COMPAT "st,stm32f756-hash" ++#endif + + #define HASH_CR 0x00U + #define HASH_DIN 0x04U +@@ -32,11 +38,22 @@ + /* Control Register */ + #define HASH_CR_INIT BIT(2) + #define HASH_CR_DATATYPE_SHIFT U(4) +- ++#if STM32MP13 ++#define HASH_CR_ALGO_SHIFT U(17) ++#define HASH_CR_ALGO_SHA1 (0x0U << HASH_CR_ALGO_SHIFT) ++#define HASH_CR_ALGO_SHA224 (0x2U << HASH_CR_ALGO_SHIFT) ++#define HASH_CR_ALGO_SHA256 (0x3U << HASH_CR_ALGO_SHIFT) ++#define HASH_CR_ALGO_SHA384 (0xCU << HASH_CR_ALGO_SHIFT) ++#define HASH_CR_ALGO_SHA512_224 (0xDU << HASH_CR_ALGO_SHIFT) ++#define HASH_CR_ALGO_SHA512_256 (0xEU << HASH_CR_ALGO_SHIFT) ++#define HASH_CR_ALGO_SHA512 (0xFU << HASH_CR_ALGO_SHIFT) ++#endif ++#if STM32MP15 + #define HASH_CR_ALGO_SHA1 0x0U + #define HASH_CR_ALGO_MD5 BIT(7) + #define HASH_CR_ALGO_SHA224 BIT(18) + #define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) ++#endif + + /* Status Flags */ + #define HASH_SR_DCIS BIT(1) +@@ -50,6 +67,10 @@ + #define SHA1_DIGEST_SIZE 20U + #define SHA224_DIGEST_SIZE 28U + #define SHA256_DIGEST_SIZE 32U ++#define SHA384_DIGEST_SIZE 48U ++#define SHA512_224_DIGEST_SIZE 28U ++#define SHA512_256_DIGEST_SIZE 32U ++#define SHA512_DIGEST_SIZE 64U + + #define RESET_TIMEOUT_US_1MS 1000U + #define HASH_TIMEOUT_US 10000U +@@ -130,10 +151,12 @@ static void hash_hw_init(enum stm32_hash_algo_mode mode) + reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); + + switch (mode) { ++#if STM32MP15 + case HASH_MD5SUM: + reg |= HASH_CR_ALGO_MD5; + stm32_hash.digest_size = MD5_DIGEST_SIZE; + break; ++#endif + case HASH_SHA1: + reg |= HASH_CR_ALGO_SHA1; + stm32_hash.digest_size = SHA1_DIGEST_SIZE; +@@ -142,6 +165,16 @@ static void hash_hw_init(enum stm32_hash_algo_mode mode) + reg |= HASH_CR_ALGO_SHA224; + stm32_hash.digest_size = SHA224_DIGEST_SIZE; + break; ++#if STM32MP13 ++ case HASH_SHA384: ++ reg |= HASH_CR_ALGO_SHA384; ++ stm32_hash.digest_size = SHA384_DIGEST_SIZE; ++ break; ++ case HASH_SHA512: ++ reg |= HASH_CR_ALGO_SHA512; ++ stm32_hash.digest_size = SHA512_DIGEST_SIZE; ++ break; ++#endif + /* Default selected algo is SHA256 */ + case HASH_SHA256: + default: +@@ -189,7 +222,7 @@ int stm32_hash_update(const uint8_t *buffer, size_t length) + return 0; + } + +- stm32mp_clk_enable(stm32_hash.clock); ++ clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + uint32_t copysize; +@@ -231,7 +264,7 @@ int stm32_hash_update(const uint8_t *buffer, size_t length) + } + + exit: +- stm32mp_clk_disable(stm32_hash.clock); ++ clk_disable(stm32_hash.clock); + + return ret; + } +@@ -240,12 +273,12 @@ int stm32_hash_final(uint8_t *digest) + { + int ret; + +- stm32mp_clk_enable(stm32_hash.clock); ++ clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { +- stm32mp_clk_disable(stm32_hash.clock); ++ clk_disable(stm32_hash.clock); + return ret; + } + +@@ -260,7 +293,7 @@ int stm32_hash_final(uint8_t *digest) + + ret = hash_get_digest(digest); + +- stm32mp_clk_disable(stm32_hash.clock); ++ clk_disable(stm32_hash.clock); + + return ret; + } +@@ -280,11 +313,11 @@ int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, + + void stm32_hash_init(enum stm32_hash_algo_mode mode) + { +- stm32mp_clk_enable(stm32_hash.clock); ++ clk_enable(stm32_hash.clock); + + hash_hw_init(mode); + +- stm32mp_clk_disable(stm32_hash.clock); ++ clk_disable(stm32_hash.clock); + + zeromem(&stm32_remain, sizeof(stm32_remain)); + } +@@ -321,7 +354,7 @@ int stm32_hash_register(void) + stm32_hash.base = hash_info.base; + stm32_hash.clock = hash_info.clock; + +- stm32mp_clk_enable(stm32_hash.clock); ++ clk_enable(stm32_hash.clock); + + if (hash_info.reset >= 0) { + uint32_t id = (uint32_t)hash_info.reset; +@@ -335,7 +368,7 @@ int stm32_hash_register(void) + } + } + +- stm32mp_clk_disable(stm32_hash.clock); ++ clk_disable(stm32_hash.clock); + + return 0; + } +diff --git a/drivers/st/crypto/stm32_pka.c b/drivers/st/crypto/stm32_pka.c +new file mode 100644 +index 000000000..e60ca3d12 +--- /dev/null ++++ b/drivers/st/crypto/stm32_pka.c +@@ -0,0 +1,704 @@ ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* ++ * For our comprehension in this file ++ * _len are in BITs ++ * _size are in BYTEs ++ * _nbw are in number of PKA_word (PKA_word = u64) ++ */ ++ ++#define INT8_LEN U(8) ++#define INT64_LEN (INT8_LEN * sizeof(uint64_t)) ++#define WORD_SIZE (sizeof(uint64_t)) ++#define OP_NBW_FROM_LEN(len) (DIV_ROUND_UP_2EVAL(len, INT64_LEN) + 1) ++#define OP_NBW_FROM_SIZE(s) OP_NBW_FROM_LEN((s) * INT8_LEN) ++#define OP_SIZE_FROM_SIZE(s) (OP_NBW_FROM_SIZE(s) * WORD_SIZE) ++ ++#define DT_PKA_COMPAT "st,stm32-pka64" ++ ++#define MAX_ECC_SIZE_LEN 640 ++#define MAX_EO_NBW OP_NBW_FROM_LEN(MAX_ECC_SIZE_LEN) ++ ++/* PKA registers */ ++/* PKA control register */ ++#define _PKA_CR U(0x0) ++/* PKA status register */ ++#define _PKA_SR U(0x4) ++/* PKA clear flag register */ ++#define _PKA_CLRFR U(0x8) ++/* PKA version register */ ++#define _PKA_VERR U(0x1FF4) ++/* PKA identification register */ ++#define _PKA_IPIDR U(0x1FF8) ++ ++/* PKA control register fields */ ++#define _PKA_CR_MODE_MASK GENMASK(13, 8) ++#define _PKA_CR_MODE_SHIFT U(8) ++#define _PKA_CR_MODE_ADD U(0x9) ++#define _PKA_CR_MODE_ECDSA_VERIF U(0x26) ++#define _PKA_CR_START BIT(1) ++#define _PKA_CR_EN BIT(0) ++ ++/* PKA status register fields */ ++#define _PKA_SR_BUSY BIT(16) ++#define _PKA_SR_LMF BIT(1) ++#define _PKA_SR_INITOK BIT(0) ++ ++/* PKA it flag fields (used in CR, SR and CLRFR) */ ++#define _PKA_IT_MASK (GENMASK(21, 19) | BIT(17)) ++#define _PKA_IT_SHIFT U(17) ++#define _PKA_IT_OPERR BIT(21) ++#define _PKA_IT_ADDRERR BIT(20) ++#define _PKA_IT_RAMERR BIT(19) ++#define _PKA_IT_PROCEND BIT(17) ++ ++/* PKA version register fields */ ++#define _PKA_VERR_MAJREV_MASK GENMASK(7, 4) ++#define _PKA_VERR_MAJREV_SHIFT U(4) ++#define _PKA_VERR_MINREV_MASK GENMASK(3, 0) ++#define _PKA_VERR_MINREV_SHIFT U(0) ++ ++/* PKA identification register value */ ++#define _PKA_IDID U(0x00170072) ++ ++/* RAM magic offset */ ++#define _PKA_RAM_START U(0x400) ++#define _PKA_RAM_SIZE U(5336) ++ ++/* ECDSA verification */ ++#define _PKA_RAM_N_LEN U(0x408) /* 64 */ ++#define _PKA_RAM_P_LEN U(0x4C8) /* 64 */ ++#define _PKA_RAM_A_SIGN U(0x468) /* 64 */ ++#define _PKA_RAM_A U(0x470) /* EOS */ ++#define _PKA_RAM_P U(0x4D0) /* EOS */ ++#define _PKA_RAM_XG U(0x678) /* EOS */ ++#define _PKA_RAM_YG U(0x6D0) /* EOS */ ++#define _PKA_RAM_XQ U(0x12F8) /* EOS */ ++#define _PKA_RAM_YQ U(0x1350) /* EOS */ ++#define _PKA_RAM_SIGN_R U(0x10E0) /* EOS */ ++#define _PKA_RAM_SIGN_S U(0xC68) /* EOS */ ++#define _PKA_RAM_HASH_Z U(0x13A8) /* EOS */ ++#define _PKA_RAM_PRIME_N U(0x1088) /* EOS */ ++#define _PKA_RAM_ECDSA_VERIFY U(0x5D0) /* 64 */ ++#define _PKA_RAM_ECDSA_VERIFY_VALID ULL(0xD60D) ++#define _PKA_RAM_ECDSA_VERIFY_INVALID ULL(0xA3B7) ++ ++#define PKA_TIMEOUT_US U(1000000) ++#define TIMEOUT_US_1MS U(1000) ++#define PKA_RESET_DELAY U(20) ++ ++struct curve_parameters { ++ uint32_t a_sign; /* 0 positive, 1 negative */ ++ uint8_t *a; /* Curve coefficient |a| */ ++ size_t a_size; ++ uint8_t *p; /* Curve modulus value */ ++ uint32_t p_len; ++ uint8_t *xg; /* Curve base point G coordinate x */ ++ size_t xg_size; ++ uint8_t *yg; /* Curve base point G coordinate y */ ++ size_t yg_size; ++ uint8_t *n; /* Curve prime order n */ ++ uint32_t n_len; ++}; ++ ++static struct curve_parameters curve_def[] = { ++#if PKA_USE_NIST_P256 ++ [PKA_NIST_P256] = { ++ .p_len = 256U, ++ .n_len = 256U, ++ .p = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, ++ .n = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, ++ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}, ++ .a_sign = 1U, ++ .a = (uint8_t[]){0x03}, ++ .a_size = 1U, ++ .xg = (uint8_t[]){0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, ++ 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, ++ 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, ++ 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96}, ++ .xg_size = 32U, ++ .yg = (uint8_t[]){0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, ++ 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, ++ 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, ++ 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5}, ++ .yg_size = 32U, ++ }, ++#endif ++#if PKA_USE_BRAINPOOL_P256R1 ++ [PKA_BRAINPOOL_P256R1] = { ++ .p_len = 256, ++ .n_len = 256, ++ .p = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, ++ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, ++ 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, ++ 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77}, ++ .n = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, ++ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, ++ 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, ++ 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7}, ++ .a = (uint8_t[]){0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, ++ 0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7, ++ 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C, ++ 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9}, ++ .a_size = 32U, ++ .xg = (uint8_t[]){0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, ++ 0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF, ++ 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2, ++ 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62}, ++ .xg_size = 32U, ++ .yg = (uint8_t[]){0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, ++ 0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9, ++ 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54, ++ 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97}, ++ .yg_size = 32U, ++ }, ++#endif ++#if PKA_USE_BRAINPOOL_P256T1 ++ [PKA_BRAINPOOL_P256T1] = { ++ .p_len = 256, ++ .n_len = 256, ++ .p = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, ++ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, ++ 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, ++ 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77}, ++ .n = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, ++ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, ++ 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, ++ 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7}, ++ .a = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, ++ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, ++ 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, ++ 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74}, ++ .a_size = 32U, ++ .xg = (uint8_t[]){0xA3, 0xE8, 0xEB, 0x3C, 0xC1, 0xCF, 0xE7, 0xB7, ++ 0x73, 0x22, 0x13, 0xB2, 0x3A, 0x65, 0x61, 0x49, ++ 0xAF, 0xA1, 0x42, 0xC4, 0x7A, 0xAF, 0xBC, 0x2B, ++ 0x79, 0xA1, 0x91, 0x56, 0x2E, 0x13, 0x05, 0xF4}, ++ .xg_size = 32U, ++ .yg = (uint8_t[]){0x2D, 0x99, 0x6C, 0x82, 0x34, 0x39, 0xC5, 0x6D, ++ 0x7F, 0x7B, 0x22, 0xE1, 0x46, 0x44, 0x41, 0x7E, ++ 0x69, 0xBC, 0xB6, 0xDE, 0x39, 0xD0, 0x27, 0x00, ++ 0x1D, 0xAB, 0xE8, 0xF3, 0x5B, 0x25, 0xC9, 0xBE}, ++ .yg_size = 32U, ++ }, ++#endif ++#if PKA_USE_NIST_P521 ++ [PKA_NIST_P521] = { ++ .p_len = 521, ++ .n_len = 521, ++ .p = (uint8_t[]){ 0x01, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, ++ .n = (uint8_t[]){ 0x01, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, ++ 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, ++ 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, ++ 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, ++ 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09}, ++ .a_sign = 1, ++ .a = (uint8_t[]){0x03}, ++ .a_size = 1U, ++ .xg = (uint8_t[]){ 0xc6, ++ 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, ++ 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, ++ 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, ++ 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, ++ 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, ++ 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, ++ 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, ++ 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66}, ++ .xg_size = 65U, ++ .yg = (uint8_t[]){ 0x01, 0x18, ++ 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, ++ 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, ++ 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, ++ 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, ++ 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, ++ 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, ++ 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, ++ 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50}, ++ .yg_size = 66U, ++ }, ++#endif ++}; ++ ++static struct stm32_pka_platdata pka_pdata; ++ ++__attribute__((weak)) ++int stm32_pka_get_platdata(struct stm32_pka_platdata *pdata) ++{ ++ return -ENODEV; ++} ++ ++static int stm32_pka_parse_fdt(void) ++{ ++ int node; ++ struct dt_node_info info; ++ void *fdt; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ node = dt_get_node(&info, -1, DT_PKA_COMPAT); ++ if (node < 0) { ++ ERROR("No PKA entry in DT\n"); ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if (info.status == DT_DISABLED) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if ((info.base == 0) || (info.clock < 0) || (info.reset < 0)) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ pka_pdata.base = (uintptr_t)info.base; ++ pka_pdata.clock_id = (unsigned long)info.clock; ++ pka_pdata.reset_id = (unsigned int)info.reset; ++ ++ return 0; ++} ++ ++static int pka_wait_bit(uintptr_t base, uint32_t bit) ++{ ++ uint64_t timeout = timeout_init_us(PKA_TIMEOUT_US); ++ ++ while ((mmio_read_32(base + _PKA_SR) & bit) != bit) { ++ if (timeout_elapsed(timeout)) { ++ WARN("timeout waiting %x\n", bit); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++ ++} ++ ++static void pka_disable(uintptr_t base) ++{ ++ mmio_clrbits_32(base + _PKA_CR, _PKA_CR_EN); ++} ++ ++static int pka_enable(uintptr_t base, uint32_t mode) ++{ ++ /* set mode and disable interrupts */ ++ mmio_clrsetbits_32(base + _PKA_CR, _PKA_IT_MASK | _PKA_CR_MODE_MASK, ++ _PKA_CR_MODE_MASK & (mode << _PKA_CR_MODE_SHIFT)); ++ ++ mmio_setbits_32(base + _PKA_CR, _PKA_CR_EN); ++ ++ return pka_wait_bit(base, _PKA_SR_INITOK); ++} ++ ++/* ++ * Data are already loaded in PKA internal RAM ++ * MODE is set ++ * we start process, and wait for its end. ++ */ ++static int stm32_pka_process(uintptr_t base) ++{ ++ mmio_setbits_32(base + _PKA_CR, _PKA_CR_START); ++ ++ return pka_wait_bit(base, _PKA_IT_PROCEND); ++} ++ ++/** ++ * @brief Write ECC operand to PKA RAM. ++ * @note PKA expect to write u64 word, each u64 are: the least significant bit is ++ * bit 0; the most significant bit is bit 63. ++ * We write eo_nbw (ECC operand Size) u64, value that depends of the chosen ++ * prime modulus length in bits. ++ * First less signicant u64 is written to low address ++ * Most significant u64 to higher address. ++ * And at last address we write a u64(0x0) ++ * @note This function doesn't only manage endianness (as bswap64 do), but also ++ * complete most significant incomplete u64 with 0 (if data is not a u64 ++ * multiple), and fill u64 last address with 0. ++ * @param addr: PKA_RAM address to write the buffer 'data' ++ * @param data: is a BYTE list with most significant bytes first ++ * @param data_size: nb of byte in data ++ * @param eo_nbw: is ECC Operand size in 64bits word (including the extra 0) ++ * (note it depends of the prime modulus length, not the data size) ++ * @retval 0 if OK. ++ * -EINVAL if data_size and eo_nbw are inconsistent, ie data doesn't ++ * fit in defined eo_nbw, or eo_nbw bigger than hardware limit. ++ */ ++static int write_eo_data(uintptr_t addr, uint8_t *data, unsigned int data_size, ++ unsigned int eo_nbw) ++{ ++ uint32_t word_index; ++ int data_index; ++ ++ if ((eo_nbw < OP_NBW_FROM_SIZE(data_size)) || (eo_nbw > MAX_EO_NBW)) { ++ return -EINVAL; ++ } ++ ++ /* fill value */ ++ data_index = (int)data_size - 1; ++ for (word_index = 0U; word_index < eo_nbw; word_index++) { ++ uint64_t tmp = 0ULL; ++ unsigned int i = 0U; /* index in the tmp U64 word */ ++ ++ /* Stop if end of tmp or end of data */ ++ while ((i < sizeof(tmp)) && (data_index >= 0)) { ++ tmp |= (uint64_t)(data[data_index]) << (INT8_LEN * i); ++ i++; /* Move byte index in current (u64)tmp */ ++ data_index--; /* Move to just next most significat byte */ ++ } ++ ++ mmio_write_64(addr + word_index * sizeof(tmp), tmp); ++ } ++ ++ return 0; ++} ++ ++static unsigned int get_ecc_op_nbword(enum stm32_pka_ecdsa_curve_id cid) ++{ ++ return OP_NBW_FROM_LEN(curve_def[cid].n_len); ++} ++ ++static int stm32_pka_ecdsa_verif_configure_curve(uintptr_t base, enum stm32_pka_ecdsa_curve_id cid) ++{ ++ int ret; ++ unsigned int eo_nbw = get_ecc_op_nbword(cid); ++ ++ mmio_write_64(base + _PKA_RAM_N_LEN, curve_def[cid].n_len); ++ mmio_write_64(base + _PKA_RAM_P_LEN, curve_def[cid].p_len); ++ mmio_write_64(base + _PKA_RAM_A_SIGN, curve_def[cid].a_sign); ++ ++ ret = write_eo_data(base + _PKA_RAM_A, curve_def[cid].a, curve_def[cid].a_size, eo_nbw); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = write_eo_data(base + _PKA_RAM_PRIME_N, ++ curve_def[cid].n, div_round_up(curve_def[cid].n_len, INT8_LEN), ++ eo_nbw); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = write_eo_data(base + _PKA_RAM_P, curve_def[cid].p, ++ div_round_up(curve_def[cid].p_len, INT8_LEN), eo_nbw); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = write_eo_data(base + _PKA_RAM_XG, curve_def[cid].xg, curve_def[cid].xg_size, eo_nbw); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = write_eo_data(base + _PKA_RAM_YG, curve_def[cid].yg, curve_def[cid].yg_size, eo_nbw); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int stm32_pka_ecdsa_verif_check_return(uintptr_t base) ++{ ++ uint64_t value; ++ uint32_t sr; ++ ++ sr = mmio_read_32(base + _PKA_SR); ++ if ((sr & (_PKA_IT_OPERR | _PKA_IT_ADDRERR | _PKA_IT_RAMERR)) != 0) { ++ WARN("Detected error(s): %s%s%s\n", ++ (sr & _PKA_IT_OPERR) ? "Operation " : "", ++ (sr & _PKA_IT_ADDRERR) ? "Address " : "", ++ (sr & _PKA_IT_RAMERR) ? "RAM" : ""); ++ return -EINVAL; ++ } ++ ++ value = mmio_read_64(base + _PKA_RAM_ECDSA_VERIFY); ++ if (value == _PKA_RAM_ECDSA_VERIFY_VALID) { ++ return 0; ++ } ++ ++ if (value == _PKA_RAM_ECDSA_VERIFY_INVALID) { ++ return -EAUTH; ++ } ++ ++ return -EINVAL; ++} ++ ++/** ++ * @brief Check if BigInt stored in data is 0 ++ * ++ * @param data: a BYTE array with most significant bytes first ++ * @param size: data size ++ * ++ * @retval: true: if data represents a 0 value (ie all bytes == 0) ++ * false: if data represents a non-zero value. ++ */ ++static bool is_zero(uint8_t *data, unsigned int size) ++{ ++ unsigned int i; ++ ++ for (i = 0U; i < size; i++) { ++ if (data[i] != 0U) { ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++/** ++ * @brief Compare two BigInt: ++ * @param xdata_a: a BYTE array with most significant bytes first ++ * @param size_a: nb of Byte of 'a' ++ * @param data_b: a BYTE array with most significant bytes first ++ * @param size_b: nb of Byte of 'b' ++ * ++ * @retval: true if data_a < data_b ++ * false if data_a >= data_b ++ */ ++static bool is_smaller(uint8_t *data_a, unsigned int size_a, ++ uint8_t *data_b, unsigned int size_b) ++{ ++ unsigned int i; ++ ++ i = MAX(size_a, size_b) + 1; ++ do { ++ uint8_t a, b; ++ ++ i--; ++ if (size_a < i) { ++ a = 0U; ++ } else { ++ a = data_a[size_a - i]; ++ } ++ ++ if (size_b < i) { ++ b = 0U; ++ } else { ++ b = data_b[size_b - i]; ++ } ++ ++ if (a < b) { ++ return true; ++ } ++ ++ if (a > b) { ++ return false; ++ } ++ } while (i != 0U); ++ ++ return false; ++} ++ ++static int stm32_pka_ecdsa_check_param(void *sig_r_ptr, unsigned int sig_r_size, ++ void *sig_s_ptr, unsigned int sig_s_size, ++ void *pk_x_ptr, unsigned int pk_x_size, ++ void *pk_y_ptr, unsigned int pk_y_size, ++ enum stm32_pka_ecdsa_curve_id cid) ++{ ++ /* Public Key check */ ++ /* Check Xq < p */ ++ if (!is_smaller(pk_x_ptr, pk_x_size, ++ curve_def[cid].p, div_round_up(curve_def[cid].p_len, INT8_LEN))) { ++ WARN("%s Xq < p inval\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Check Yq < p */ ++ if (!is_smaller(pk_y_ptr, pk_y_size, ++ curve_def[cid].p, div_round_up(curve_def[cid].p_len, INT8_LEN))) { ++ WARN("%s Yq < p inval\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Signature check */ ++ /* Check 0 < r < n */ ++ if (!is_smaller(sig_r_ptr, sig_r_size, ++ curve_def[cid].n, div_round_up(curve_def[cid].n_len, INT8_LEN)) && ++ !is_zero(sig_r_ptr, sig_r_size)) { ++ WARN("%s 0< r < n inval\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Check 0 < s < n */ ++ if (!is_smaller(sig_s_ptr, sig_s_size, ++ curve_def[cid].n, div_round_up(curve_def[cid].n_len, INT8_LEN)) && ++ !is_zero(sig_s_ptr, sig_s_size)) { ++ WARN("%s 0< s < n inval\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Initialize the PKA driver. ++ * @param None. ++ * @retval 0 if OK, negative value else. ++ */ ++int stm32_pka_init(void) ++{ ++ int err; ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ uint32_t ver; ++ uint32_t id; ++#endif ++ ++ err = stm32_pka_parse_fdt(); ++ if (err != 0) { ++ err = stm32_pka_get_platdata(&pka_pdata); ++ if (err != 0) { ++ return err; ++ } ++ } ++ ++ clk_enable(pka_pdata.clock_id); ++ ++ if (stm32mp_reset_assert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) { ++ panic(); ++ } ++ ++ udelay(PKA_RESET_DELAY); ++ if (stm32mp_reset_deassert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) { ++ panic(); ++ } ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ id = mmio_read_32(pka_pdata.base + _PKA_IPIDR); ++ ver = mmio_read_32(pka_pdata.base + _PKA_VERR); ++ ++ VERBOSE("STM32 PKA[%x] V%u.%u\n", id, ++ (ver & _PKA_VERR_MAJREV_MASK) >> _PKA_VERR_MAJREV_SHIFT, ++ (ver & _PKA_VERR_MINREV_MASK) >> _PKA_VERR_MINREV_SHIFT); ++#endif ++ return 0; ++} ++ ++int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size, ++ void *sig_r_ptr, unsigned int sig_r_size, ++ void *sig_s_ptr, unsigned int sig_s_size, ++ void *pk_x_ptr, unsigned int pk_x_size, ++ void *pk_y_ptr, unsigned int pk_y_size, ++ enum stm32_pka_ecdsa_curve_id cid) ++{ ++ int ret; ++ uintptr_t base = pka_pdata.base; ++ unsigned int eo_nbw = get_ecc_op_nbword(cid); ++ ++ if ((hash == NULL) || (sig_r_ptr == NULL) || (sig_s_ptr == NULL) || ++ (pk_x_ptr == NULL) || (pk_y_ptr == NULL)) { ++ INFO("%s invalid input param\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = stm32_pka_ecdsa_check_param(sig_r_ptr, sig_r_size, ++ sig_s_ptr, sig_s_size, ++ pk_x_ptr, pk_x_size, ++ pk_y_ptr, pk_y_size, ++ cid); ++ if (ret < 0) { ++ INFO("%s check param error %d\n", __func__, ret); ++ goto out; ++ } ++ ++ if ((mmio_read_32(base + _PKA_SR) & _PKA_SR_BUSY) == _PKA_SR_BUSY) { ++ INFO("%s busy\n", __func__); ++ ret = -EBUSY; ++ goto out; ++ } ++ ++ /* Fill PKA RAM */ ++ /* With curve id values */ ++ ret = stm32_pka_ecdsa_verif_configure_curve(base, cid); ++ if (ret < 0) { ++ goto out; ++ } ++ ++ /* With pubkey */ ++ ret = write_eo_data(base + _PKA_RAM_XQ, pk_x_ptr, pk_x_size, eo_nbw); ++ if (ret < 0) { ++ goto out; ++ } ++ ++ ret = write_eo_data(base + _PKA_RAM_YQ, pk_y_ptr, pk_y_size, eo_nbw); ++ if (ret < 0) { ++ goto out; ++ } ++ ++ /* With hash */ ++ ret = write_eo_data(base + _PKA_RAM_HASH_Z, hash, hash_size, eo_nbw); ++ if (ret < 0) { ++ goto out; ++ } ++ ++ /* With signature */ ++ ret = write_eo_data(base + _PKA_RAM_SIGN_R, sig_r_ptr, sig_r_size, eo_nbw); ++ if (ret < 0) { ++ goto out; ++ } ++ ++ ret = write_eo_data(base + _PKA_RAM_SIGN_S, sig_s_ptr, sig_s_size, eo_nbw); ++ if (ret < 0) { ++ goto out; ++ } ++ ++ /* Set mode to ecdsa signature verification */ ++ ret = pka_enable(base, _PKA_CR_MODE_ECDSA_VERIF); ++ if (ret < 0) { ++ WARN("%s set mode pka error %d\n", __func__, ret); ++ goto out; ++ } ++ ++ /* Start processing and wait end */ ++ ret = stm32_pka_process(base); ++ if (ret < 0) { ++ WARN("%s process error %d\n", __func__, ret); ++ goto out; ++ } ++ ++ /* Check return status */ ++ ret = stm32_pka_ecdsa_verif_check_return(base); ++ ++ /* Unset end proc */ ++ mmio_setbits_32(base + _PKA_CLRFR, _PKA_IT_PROCEND); ++ ++out: ++ /* Disable PKA (will stop all pending proccess and reset RAM) */ ++ pka_disable(base); ++ ++ return ret; ++} +diff --git a/drivers/st/crypto/stm32_saes.c b/drivers/st/crypto/stm32_saes.c +new file mode 100644 +index 000000000..13358eeda +--- /dev/null ++++ b/drivers/st/crypto/stm32_saes.c +@@ -0,0 +1,1074 @@ ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define INT8_BIT U(8) ++#define AES_BLOCK_SIZE_BIT 128U ++#define AES_BLOCK_SIZE (AES_BLOCK_SIZE_BIT / INT8_BIT) ++ ++#define AES_KEYSIZE_128 16U ++#define AES_KEYSIZE_256 32U ++#define AES_IVSIZE 16U ++ ++/* SAES control register */ ++#define _SAES_CR 0x0U ++/* SAES status register */ ++#define _SAES_SR 0x04U ++/* SAES data input register */ ++#define _SAES_DINR 0x08U ++/* SAES data output register */ ++#define _SAES_DOUTR 0x0CU ++/* SAES key registers [0-3] */ ++#define _SAES_KEYR0 0x10U ++#define _SAES_KEYR1 0x14U ++#define _SAES_KEYR2 0x18U ++#define _SAES_KEYR3 0x1CU ++/* SAES initialization vector registers [0-3] */ ++#define _SAES_IVR0 0x20U ++#define _SAES_IVR1 0x24U ++#define _SAES_IVR2 0x28U ++#define _SAES_IVR3 0x2CU ++/* SAES key registers [4-7] */ ++#define _SAES_KEYR4 0x30U ++#define _SAES_KEYR5 0x34U ++#define _SAES_KEYR6 0x38U ++#define _SAES_KEYR7 0x3CU ++/* SAES suspend registers [0-7] */ ++#define _SAES_SUSPR0 0x40U ++#define _SAES_SUSPR1 0x44U ++#define _SAES_SUSPR2 0x48U ++#define _SAES_SUSPR3 0x4CU ++#define _SAES_SUSPR4 0x50U ++#define _SAES_SUSPR5 0x54U ++#define _SAES_SUSPR6 0x58U ++#define _SAES_SUSPR7 0x5CU ++/* SAES Interrupt Enable Register */ ++#define _SAES_IER 0x300U ++/* SAES Interrupt Status Register */ ++#define _SAES_ISR 0x304U ++/* SAES Interrupt Clear Register */ ++#define _SAES_ICR 0x308U ++ ++/* SAES control register fields */ ++#define _SAES_CR_RESET_VALUE 0x0U ++#define _SAES_CR_IPRST BIT(31) ++#define _SAES_CR_KEYSEL_MASK GENMASK(30, 28) ++#define _SAES_CR_KEYSEL_SHIFT 28U ++#define _SAES_CR_KEYSEL_SOFT 0x0U ++#define _SAES_CR_KEYSEL_DHUK 0x1U ++#define _SAES_CR_KEYSEL_BHK 0x2U ++#define _SAES_CR_KEYSEL_BHU_XOR_BH_K 0x4U ++#define _SAES_CR_KEYSEL_TEST 0x7U ++#define _SAES_CR_KSHAREID_MASK GENMASK(27, 26) ++#define _SAES_CR_KSHAREID_SHIFT 26U ++#define _SAES_CR_KSHAREID_CRYP 0x0U ++#define _SAES_CR_KEYMOD_MASK GENMASK(25, 24) ++#define _SAES_CR_KEYMOD_SHIFT 24U ++#define _SAES_CR_KEYMOD_NORMAL 0x0U ++#define _SAES_CR_KEYMOD_WRAPPED 0x1U ++#define _SAES_CR_KEYMOD_SHARED 0x2U ++#define _SAES_CR_NPBLB_MASK GENMASK(23, 20) ++#define _SAES_CR_NPBLB_SHIFT 20U ++#define _SAES_CR_KEYPROT BIT(19) ++#define _SAES_CR_KEYSIZE BIT(18) ++#define _SAES_CR_GCMPH_MASK GENMASK(14, 13) ++#define _SAES_CR_GCMPH_SHIFT 13U ++#define _SAES_CR_GCMPH_INIT 0U ++#define _SAES_CR_GCMPH_HEADER 1U ++#define _SAES_CR_GCMPH_PAYLOAD 2U ++#define _SAES_CR_GCMPH_FINAL 3U ++#define _SAES_CR_DMAOUTEN BIT(12) ++#define _SAES_CR_DMAINEN BIT(11) ++#define _SAES_CR_CHMOD_MASK (BIT(16) | GENMASK(6, 5)) ++#define _SAES_CR_CHMOD_SHIFT 5U ++#define _SAES_CR_CHMOD_ECB 0x0U ++#define _SAES_CR_CHMOD_CBC 0x1U ++#define _SAES_CR_CHMOD_CTR 0x2U ++#define _SAES_CR_CHMOD_GCM 0x3U ++#define _SAES_CR_CHMOD_GMAC 0x3U ++#define _SAES_CR_CHMOD_CCM 0x800U ++#define _SAES_CR_MODE_MASK GENMASK(4, 3) ++#define _SAES_CR_MODE_SHIFT 3U ++#define _SAES_CR_MODE_ENC 0U ++#define _SAES_CR_MODE_KEYPREP 1U ++#define _SAES_CR_MODE_DEC 2U ++#define _SAES_CR_DATATYPE_MASK GENMASK(2, 1) ++#define _SAES_CR_DATATYPE_SHIFT 1U ++#define _SAES_CR_DATATYPE_NONE 0U ++#define _SAES_CR_DATATYPE_HALF_WORD 1U ++#define _SAES_CR_DATATYPE_BYTE 2U ++#define _SAES_CR_DATATYPE_BIT 3U ++#define _SAES_CR_EN BIT(0) ++ ++/* SAES status register fields */ ++#define _SAES_SR_KEYVALID BIT(7) ++#define _SAES_SR_BUSY BIT(3) ++#define _SAES_SR_WRERR BIT(2) ++#define _SAES_SR_RDERR BIT(1) ++#define _SAES_SR_CCF BIT(0) ++ ++/* SAES interrupt registers fields */ ++#define _SAES_I_RNG_ERR BIT(3) ++#define _SAES_I_KEY_ERR BIT(2) ++#define _SAES_I_RW_ERR BIT(1) ++#define _SAES_I_CC BIT(0) ++ ++#define SAES_TIMEOUT_US 100000U ++#define TIMEOUT_US_1MS 1000U ++#define SAES_RESET_DELAY U(20) ++ ++#define IS_CHAINING_MODE(mod, cr) \ ++ (((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT)) ++ ++#define SET_CHAINING_MODE(mod, cr) \ ++ mmio_clrsetbits_32((cr), _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT) ++ ++static struct stm32_saes_platdata saes_pdata; ++ ++__attribute__((weak)) ++int stm32_saes_get_platdata(struct stm32_saes_platdata *pdata) ++{ ++ return -ENODEV; ++} ++ ++static int stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata) ++{ ++ int node; ++ struct dt_node_info info; ++ void *fdt; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ node = dt_get_node(&info, -1, DT_SAES_COMPAT); ++ if (node < 0) { ++ ERROR("No SAES entry in DT\n"); ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if (info.status == DT_DISABLED) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if ((info.base == 0U) || (info.clock < 0) || (info.reset < 0)) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ pdata->base = (uintptr_t)info.base; ++ pdata->clock_id = (unsigned long)info.clock; ++ pdata->reset_id = (unsigned int)info.reset; ++ ++ return 0; ++} ++ ++static bool does_chaining_mode_need_iv(uint32_t cr) ++{ ++ return !(IS_CHAINING_MODE(ECB, cr)); ++} ++ ++static bool is_encrypt(uint32_t cr) ++{ ++ return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT); ++} ++ ++static bool is_decrypt(uint32_t cr) ++{ ++ return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT); ++} ++ ++static int wait_computation_completed(uintptr_t base) ++{ ++ uint64_t timeout = timeout_init_us(SAES_TIMEOUT_US); ++ ++ while ((mmio_read_32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) { ++ if (timeout_elapsed(timeout)) { ++ WARN("%s: timeout\n", __func__); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++static void clear_computation_completed(uintptr_t base) ++{ ++ mmio_setbits_32(base + _SAES_ICR, _SAES_I_CC); ++} ++ ++static int saes_start(struct stm32_saes_context *ctx) ++{ ++ uint64_t timeout; ++ ++ /* Reset IP */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); ++ udelay(SAES_RESET_DELAY); ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); ++ ++ timeout = timeout_init_us(SAES_TIMEOUT_US); ++ while ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) == _SAES_SR_BUSY) { ++ if (timeout_elapsed(timeout)) { ++ WARN("%s: timeout\n", __func__); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++static void saes_end(struct stm32_saes_context *ctx, int prev_error) ++{ ++ if (prev_error != 0) { ++ /* Reset IP */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); ++ udelay(SAES_RESET_DELAY); ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); ++ } ++ ++ /* Disable the SAES peripheral */ ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++} ++ ++static void saes_write_iv(struct stm32_saes_context *ctx) ++{ ++ /* If chaining mode need to restore IV */ ++ if (does_chaining_mode_need_iv(ctx->cr)) { ++ uint8_t i; ++ ++ /* Restore the _SAES_IVRx */ ++ for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) { ++ mmio_write_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]); ++ } ++ } ++ ++} ++ ++static void saes_write_key(struct stm32_saes_context *ctx) ++{ ++ /* Restore the _SAES_KEYRx if SOFTWARE key */ ++ if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == (_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT)) { ++ uint8_t i; ++ ++ for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) { ++ mmio_write_32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]); ++ } ++ ++ if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) { ++ for (i = 0U; i < (AES_KEYSIZE_256 / 2U) / sizeof(uint32_t); i++) { ++ mmio_write_32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t), ++ ctx->key[i + 4U]); ++ } ++ } ++ } ++} ++ ++static int saes_prepare_key(struct stm32_saes_context *ctx) ++{ ++ /* Disable the SAES peripheral */ ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ ++ /* Set key size */ ++ if ((ctx->cr & _SAES_CR_KEYSIZE) != 0U) { ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); ++ } else { ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); ++ } ++ ++ saes_write_key(ctx); ++ ++ /* For ECB/CBC decryption, key preparation mode must be selected to populate the key */ ++ if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) && ++ is_decrypt(ctx->cr)) { ++ int ret; ++ ++ /* Select Mode 2 */ ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, ++ _SAES_CR_MODE_KEYPREP << _SAES_CR_MODE_SHIFT); ++ ++ /* Enable SAES */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ ++ /* Wait Computation completed */ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ clear_computation_completed(ctx->base); ++ ++ /* Set Mode 3 */ ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, ++ _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT); ++ } ++ ++ return 0; ++} ++ ++static int save_context(struct stm32_saes_context *ctx) ++{ ++ if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_CCF) != 0U) { ++ /* Device should not be in a processing phase */ ++ return -EINVAL; ++ } ++ ++ /* Save CR */ ++ ctx->cr = mmio_read_32(ctx->base + _SAES_CR); ++ ++ /* If chaining mode need to save current IV */ ++ if (does_chaining_mode_need_iv(ctx->cr)) { ++ uint8_t i; ++ ++ /* Save IV */ ++ for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) { ++ ctx->iv[i] = mmio_read_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t)); ++ } ++ } ++ ++ /* Disable the SAES peripheral */ ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ ++ return 0; ++} ++ ++/* To resume the processing of a message */ ++static int restore_context(struct stm32_saes_context *ctx) ++{ ++ int ret; ++ ++ /* IP should be disabled */ ++ if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) { ++ VERBOSE("%s: Device is still enabled\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Reset internal state */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); ++ ++ /* Restore the _SAES_CR */ ++ mmio_write_32(ctx->base + _SAES_CR, ctx->cr); ++ ++ /* Preparation decrypt key */ ++ ret = saes_prepare_key(ctx); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ saes_write_iv(ctx); ++ ++ /* Enable the SAES peripheral */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ ++ return 0; ++} ++ ++/** ++ * @brief Initialize SAES driver. ++ * @param None. ++ * @retval 0 if OK; negative value else. ++ */ ++int stm32_saes_driver_init(void) ++{ ++ int err; ++ ++ err = stm32_saes_parse_fdt(&saes_pdata); ++ if (err != 0) { ++ err = stm32_saes_get_platdata(&saes_pdata); ++ if (err != 0) { ++ return err; ++ } ++ } ++ ++ clk_enable(saes_pdata.clock_id); ++ if (stm32mp_reset_assert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) { ++ panic(); ++ } ++ ++ udelay(SAES_RESET_DELAY); ++ if (stm32mp_reset_deassert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) { ++ panic(); ++ } ++ ++ return 0; ++} ++ ++/** ++ * @brief Start a AES computation. ++ * @param ctx: SAES process context ++ * @param is_dec: true if decryption, false if encryption ++ * @param ch_mode: define the chaining mode ++ * @param key_select: define where the key comes from. ++ * @param key: pointer to key (if key_select is KEY_SOFT, else unused) ++ * @param key_size: key size ++ * @param iv: pointer to initialization vectore (unsed if ch_mode is ECB) ++ * @param iv_size: iv size ++ * @note this function doesn't access to hardware but store in ctx the values ++ * ++ * @retval 0 if OK; negative value else. ++ */ ++int stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec, ++ enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select, ++ const void *key, size_t key_size, const void *iv, size_t iv_size) ++{ ++ unsigned int i; ++ const uint32_t *iv_u32; ++ const uint32_t *key_u32; ++ ++ ctx->assoc_len = 0U; ++ ctx->load_len = 0U; ++ ++ ctx->base = saes_pdata.base; ++ ctx->cr = _SAES_CR_RESET_VALUE; ++ ++ /* We want buffer to be u32 aligned */ ++ assert((uintptr_t)key % __alignof__(uint32_t) == 0); ++ assert((uintptr_t)iv % __alignof__(uint32_t) == 0); ++ ++ iv_u32 = iv; ++ key_u32 = key; ++ ++ if (is_dec) { ++ /* Save Mode 3 = decrypt */ ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK, ++ _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT); ++ } else { ++ /* Save Mode 1 = crypt */ ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK, ++ _SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT); ++ } ++ ++ /* Save chaining mode */ ++ switch (ch_mode) { ++ case STM32_SAES_MODE_ECB: ++ SET_CHAINING_MODE(ECB, (uintptr_t)&(ctx->cr)); ++ break; ++ case STM32_SAES_MODE_CBC: ++ SET_CHAINING_MODE(CBC, (uintptr_t)&(ctx->cr)); ++ break; ++ case STM32_SAES_MODE_CTR: ++ SET_CHAINING_MODE(CTR, (uintptr_t)&(ctx->cr)); ++ break; ++ case STM32_SAES_MODE_GCM: ++ SET_CHAINING_MODE(GCM, (uintptr_t)&(ctx->cr)); ++ break; ++ case STM32_SAES_MODE_CCM: ++ SET_CHAINING_MODE(CCM, (uintptr_t)&(ctx->cr)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data. ++ * so we won't need to ++ * htobe32(data) before write to DINR ++ * nor ++ * be32toh after reading from DOUTR ++ * ++ * But note that wrap key only accept _SAES_CR_DATATYPE_NONE ++ */ ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK, ++ _SAES_CR_DATATYPE_BYTE << _SAES_CR_DATATYPE_SHIFT); ++ ++ /* Configure keysize */ ++ switch (key_size) { ++ case AES_KEYSIZE_128: ++ mmio_clrbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE); ++ break; ++ case AES_KEYSIZE_256: ++ mmio_setbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Configure key */ ++ switch (key_select) { ++ case STM32_SAES_KEY_SOFT: ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, ++ _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT); ++ /* Save key */ ++ switch (key_size) { ++ case AES_KEYSIZE_128: ++ /* First 16 bytes == 4 u32 */ ++ for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) { ++ mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[3 - i])); ++ /* /!\ we save the key in HW byte order ++ * and word order : key[i] is for _SAES_KEYRi ++ */ ++ } ++ break; ++ case AES_KEYSIZE_256: ++ for (i = 0U; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) { ++ mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[7 - i])); ++ /* /!\ we save the key in HW byte order ++ * and word order : key[i] is for _SAES_KEYRi ++ */ ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case STM32_SAES_KEY_DHU: ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, ++ _SAES_CR_KEYSEL_DHUK << _SAES_CR_KEYSEL_SHIFT); ++ break; ++ case STM32_SAES_KEY_BH: ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, ++ _SAES_CR_KEYSEL_BHK << _SAES_CR_KEYSEL_SHIFT); ++ break; ++ case STM32_SAES_KEY_BHU_XOR_BH: ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, ++ _SAES_CR_KEYSEL_BHU_XOR_BH_K << _SAES_CR_KEYSEL_SHIFT); ++ break; ++ case STM32_SAES_KEY_WRAPPED: ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, ++ _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT); ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* Save IV */ ++ if (ch_mode != STM32_SAES_MODE_ECB) { ++ if ((iv == NULL) || (iv_size != AES_IVSIZE)) { ++ return -EINVAL; ++ } ++ for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) { ++ mmio_write_32((uintptr_t)(ctx->iv + i), htobe32(iv_u32[3 - i])); ++ /* /!\ We save the iv in HW byte order */ ++ } ++ } ++ return saes_start(ctx); ++} ++ ++/** ++ * @brief Update (or start) a AES authentificate process of associated data (CCM or GCM). ++ * @param ctx: SAES process context ++ * @param last_block: true if last assoc data block ++ * @param data: pointer to associated data ++ * @param data_size: data size ++ * ++ * @retval 0 if OK; negative value else. ++ */ ++int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block, ++ uint8_t *data, size_t data_size) ++{ ++ int ret; ++ uint32_t *data_u32; ++ unsigned int i = 0U; ++ ++ /* We want buffers to be u32 aligned */ ++ assert((uintptr_t)data % __alignof__(uint32_t) == 0); ++ data_u32 = (uint32_t *)data; ++ ++ /* Init phase */ ++ ret = restore_context(ctx); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ clear_computation_completed(ctx->base); ++ ++ if ((data == NULL) || (data_size == 0U)) { ++ /* No associated data */ ++ /* ret already = 0 */ ++ goto out; ++ } ++ ++ /* There is an header/associated data phase */ ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, ++ _SAES_CR_GCMPH_HEADER << _SAES_CR_GCMPH_SHIFT); ++ ++ /* Enable the SAES peripheral */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ ++ while (i < round_down(data_size, AES_BLOCK_SIZE)) { ++ unsigned int w; /* Word index */ ++ ++ w = i / sizeof(uint32_t); ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 0U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 1U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 2U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 3U]); ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ clear_computation_completed(ctx->base); ++ ++ /* Process next block */ ++ i += AES_BLOCK_SIZE; ++ ctx->assoc_len += AES_BLOCK_SIZE_BIT; ++ } ++ ++ /* Manage last block if not a block size multiple */ ++ if ((last_block) && (i < data_size)) { ++ /* We don't manage unaligned last block yet */ ++ ret = -ENODEV; ++ goto out; ++ } ++ ++out: ++ if (ret != 0) { ++ saes_end(ctx, ret); ++ } ++ ++ return ret; ++} ++ ++/** ++ * @brief Update (or start) a AES authenticate and de/encrypt with payload data (CCM or GCM). ++ * @param ctx: SAES process context ++ * @param last_block: true if last payload data block ++ * @param data_in: pointer to payload ++ * @param data_out: pointer where to save de/encrypted payload ++ * @param data_size: payload size ++ * ++ * @retval 0 if OK; negative value else. ++ */ ++int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block, ++ uint8_t *data_in, uint8_t *data_out, size_t data_size) ++{ ++ int ret = 0; ++ uint32_t *data_in_u32; ++ uint32_t *data_out_u32; ++ unsigned int i = 0U; ++ uint32_t prev_cr; ++ ++ /* We want buffers to be u32 aligned */ ++ assert((uintptr_t)data_in % __alignof__(uint32_t) == 0); ++ assert((uintptr_t)data_out % __alignof__(uint32_t) == 0); ++ data_in_u32 = (uint32_t *)data_in; ++ data_out_u32 = (uint32_t *)data_out; ++ ++ prev_cr = mmio_read_32(ctx->base + _SAES_CR); ++ ++ if ((data_in == NULL) || (data_size == 0U)) { ++ /* there is no data */ ++ goto out; ++ } ++ ++ /* There is a load phase */ ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, ++ _SAES_CR_GCMPH_PAYLOAD << _SAES_CR_GCMPH_SHIFT); ++ ++ if ((prev_cr & _SAES_CR_GCMPH_MASK) == ++ (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) { ++ /* Still in initialization phase, no header ++ * We need to enable the SAES peripheral ++ */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ } ++ ++ while (i < round_down(data_size, AES_BLOCK_SIZE)) { ++ unsigned int w; /* Word index */ ++ ++ w = i / sizeof(uint32_t); ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]); ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ ++ clear_computation_completed(ctx->base); ++ ++ /* Process next block */ ++ i += AES_BLOCK_SIZE; ++ ctx->load_len += AES_BLOCK_SIZE_BIT; ++ } ++ /* Manage last block if not a block size multiple */ ++ if ((last_block) && (i < data_size)) { ++ uint32_t block_in[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0}; ++ uint32_t block_out[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0}; ++ ++ memcpy(block_in, data_in + i, data_size - i); ++ ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ mmio_write_32(ctx->base + _SAES_DINR, block_in[0U]); ++ mmio_write_32(ctx->base + _SAES_DINR, block_in[1U]); ++ mmio_write_32(ctx->base + _SAES_DINR, block_in[2U]); ++ mmio_write_32(ctx->base + _SAES_DINR, block_in[3U]); ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ VERBOSE("%s %d\n", __func__, __LINE__); ++ goto out; ++ } ++ ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ block_out[0U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ block_out[1U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ block_out[2U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ block_out[3U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ ++ clear_computation_completed(ctx->base); ++ ++ memcpy(data_out + i, block_out, data_size - i); ++ ++ ctx->load_len += (data_size - i) * INT8_BIT; ++ } ++ ++out: ++ if (ret != 0) { ++ saes_end(ctx, ret); ++ } ++ ++ return ret; ++} ++ ++/** ++ * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM). ++ * @param ctx: SAES process context ++ * @param tag: pointer where to save the tag ++ * @param data_size: tag size ++ * ++ * @retval 0 if OK; negative value else. ++ */ ++int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, ++ size_t tag_size) ++{ ++ int ret; ++ uint32_t tag_u32[4]; ++ uint32_t prev_cr; ++ ++ prev_cr = mmio_read_32(ctx->base + _SAES_CR); ++ ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, ++ _SAES_CR_GCMPH_FINAL << _SAES_CR_GCMPH_SHIFT); ++ ++ if ((prev_cr & _SAES_CR_GCMPH_MASK) == (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) { ++ /* Still in initialization phase, no header ++ * We need to enable the SAES peripheral ++ */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ } ++ ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ mmio_write_32(ctx->base + _SAES_DINR, 0); ++ mmio_write_32(ctx->base + _SAES_DINR, ctx->assoc_len); ++ mmio_write_32(ctx->base + _SAES_DINR, 0); ++ mmio_write_32(ctx->base + _SAES_DINR, ctx->load_len); ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ tag_u32[0] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ tag_u32[1] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ tag_u32[2] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ tag_u32[3] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ ++ clear_computation_completed(ctx->base); ++ ++ memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size)); ++ ++out: ++ saes_end(ctx, ret); ++ ++ return ret; ++} ++ ++/** ++ * @brief Update (or start) a AES de/encrypt process (ECB, CBC or CTR). ++ * @param ctx: SAES process context ++ * @param last_block: true if last payload data block ++ * @param data_in: pointer to payload ++ * @param data_out: pointer where to save de/encrypted payload ++ * @param data_size: payload size ++ * ++ * @retval 0 if OK; negative value else. ++ */ ++int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block, ++ uint8_t *data_in, uint8_t *data_out, size_t data_size) ++{ ++ int ret; ++ uint32_t *data_in_u32; ++ uint32_t *data_out_u32; ++ unsigned int i = 0U; ++ ++ /* We want buffers to be u32 aligned */ ++ assert((uintptr_t)data_in % __alignof__(uint32_t) == 0); ++ assert((uintptr_t)data_out % __alignof__(uint32_t) == 0); ++ data_in_u32 = (uint32_t *)data_in; ++ data_out_u32 = (uint32_t *)data_out; ++ ++ if ((!last_block) && ++ (round_down(data_size, AES_BLOCK_SIZE) != data_size)) { ++ ERROR("%s: non last block must be multiple of 128 bits\n", ++ __func__); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* In CBC encryption we need to manage specifically last 2 128bits ++ * blocks if total size in not a block size aligned ++ * work TODO. Currently return ENODEV. ++ * Morevoer as we need to know last 2 block, if unaligned and ++ * call with less than two block, return -EINVAL. ++ */ ++ if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) && ++ (round_down(data_size, AES_BLOCK_SIZE) != data_size)) { ++ if (data_size < AES_BLOCK_SIZE * 2) { ++ ERROR("if CBC, size of the last part should be at least 2*AES_BLOCK_SIZE\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ /* Moreover the CBC specific padding for encrypt is not yet implemented */ ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ ret = restore_context(ctx); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ while (i < round_down(data_size, AES_BLOCK_SIZE)) { ++ unsigned int w; /* Word index */ ++ ++ w = i / sizeof(uint32_t); ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]); ++ mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]); ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ /* No need to htobe() as we configure the HW to swap bytes */ ++ data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR); ++ ++ clear_computation_completed(ctx->base); ++ ++ /* Process next block */ ++ i += AES_BLOCK_SIZE; ++ } ++ /* Manage last block if not a block size multiple */ ++ ++ if ((last_block) && (i < data_size)) { ++ /* In and out buffer have same size so should be AES_BLOCK_SIZE multiple */ ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ if (!last_block) { ++ ret = save_context(ctx); ++ } ++ ++out: ++ /* If last block or error, end of SAES process */ ++ if (last_block || (ret != 0)) { ++ saes_end(ctx, ret); ++ } ++ ++ return ret; ++} ++ ++static int stm32_saes_derived_key(struct stm32_saes_context *ctx, bool is_dec, ++ bool protect_key, bool shared_key, ++ enum stm32_saes_chaining_mode ch_mode, ++ enum stm32_saes_key_selection key_select, ++ const void *key, size_t key_size, const void *iv, size_t iv_size, ++ const void *in_data, const void *out_data) ++{ ++ int ret = 0; ++ uint32_t *out_data_u32; ++ uint32_t *in_data_u32; ++ size_t i, j; ++ ++ switch (key_size) { ++ case AES_KEYSIZE_128: ++ case AES_KEYSIZE_256: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (ch_mode) { ++ case STM32_SAES_MODE_GCM: ++ /* GCM is not a supported algo for derived key */ ++ return -EINVAL; ++ case STM32_SAES_MODE_CCM: ++ case STM32_SAES_MODE_CTR: ++ /* not yet tested */ ++ return -EINVAL; ++ default: ++ break; ++ } ++ ++ /* We want buffers to be u32 aligned */ ++ assert((uintptr_t)in_data % __alignof__(uint32_t) == 0); ++ assert((uintptr_t)out_data % __alignof__(uint32_t) == 0); ++ in_data_u32 = (uint32_t *)in_data; ++ out_data_u32 = (uint32_t *)out_data; ++ ++ ret = stm32_saes_init(ctx, is_dec, ch_mode, key_select, key, key_size, ++ iv, iv_size); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ /* IP should be disabled */ ++ if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) { ++ VERBOSE("%s: Device is still enabled\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Unwrap and wrap key expec DATATYPE=NONE */ ++ mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK, ++ _SAES_CR_DATATYPE_NONE << _SAES_CR_DATATYPE_SHIFT); ++ ++ /* Select KEYMOD wrap key/shared key */ ++ if (shared_key) { ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYMOD_MASK, ++ _SAES_CR_KEYMOD_SHARED << _SAES_CR_KEYMOD_SHIFT); ++ } else { ++ mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYMOD_MASK, ++ _SAES_CR_KEYMOD_WRAPPED << _SAES_CR_KEYMOD_SHIFT); ++ } ++ ++ if (protect_key) { ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYPROT); ++ } else { ++ mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYPROT); ++ } ++ ++ /* Write CR defined by init */ ++ mmio_write_32(ctx->base + _SAES_CR, ctx->cr); ++ ++ /* Preparation decrypt key */ ++ ret = saes_prepare_key(ctx); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ saes_write_iv(ctx); ++ ++ /* Enable the SAES peripheral */ ++ mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); ++ ++ for (i = 0; i < key_size / sizeof(uint32_t); i += (AES_BLOCK_SIZE / sizeof(uint32_t))) { ++ for (j = 0; j < AES_BLOCK_SIZE / sizeof(uint32_t); j++) { ++ /* Need to htobe() as keyshared need the HW in NO swap mode */ ++ mmio_write_32(ctx->base + _SAES_DINR, htobe32(in_data_u32[i + j])); ++ } ++ ++ ret = wait_computation_completed(ctx->base); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) && ++ (!is_dec)) { ++ for (j = 0; j < AES_BLOCK_SIZE / sizeof(uint32_t); j++) { ++ out_data_u32[i + j] = be32toh(mmio_read_32(ctx->base + ++ _SAES_DOUTR)); ++ } ++ } ++ ++ clear_computation_completed(ctx->base); ++ } ++ ++out: ++ /* Disable the SAES peripheral and reset SAES in case of error */ ++ saes_end(ctx, ret); ++ ++ return ret; ++} ++ ++/** ++ * @brief Wrap (encrypt) application keys (not appplicable for CTR chaining ++ * mode algorithm) ++ * @param ch_mod: select chaining mode algorithm ++ * @param key_select: select key origin ++ * @param key: pointer to key use to encrypt (if key_select == SOFT) ++ * else not used. ++ * @param key_size: len of the encrypt key, key to encrypt and encrypted key. ++ * (16 or 32) ++ * @param iv: pointer to IV used to encrypt (not use for ECB) ++ * @param iv_size: iv size should be 16 (not use for ECB) ++ * @param in_key: key to encrypt (same size as 'key'), not used for CCM ++ * @param out_data: encrypted key (ECM, CBC) (same size as 'key'), ++ * or authentication tag for CCM (size = 16) ++ * @retval HAL status ++ */ ++int stm32_saes_wrap_key(enum stm32_saes_chaining_mode ch_mode, ++ enum stm32_saes_key_selection key_select, const void *key, size_t key_size, ++ const void *iv, size_t iv_size, const void *in_key, const void *out_data) ++{ ++ struct stm32_saes_context ctx; ++ ++ return stm32_saes_derived_key(&ctx, false, ++ true, false, ch_mode, key_select, ++ key, key_size, iv, iv_size, in_key, out_data); ++} ++ ++/** ++ * @brief Unwrap (decrypt) application keys ++ * @param ch_mod: select chaining mode algorithm ++ * @param key_select: select key origin ++ * @param key: pointer to key used to decrypt (if key_select == SOFT) ++ * for other key_select, not used. ++ * @param key_size: len of the decrypt key, key to decrypt and decrypted key. ++ * (16 or 32) ++ * @param iv: pointer to IV used to encrypt (not use for ECB) ++ * @param iv_size: iv size should be 16 (not use for ECB) ++ * @param in_data: key to decrypt (same size as 'key') for ECB and CBC, ++ * authentication tag for CCM (size = 16) ++ * not used for CTR. ++ * @retval HAL status ++ */ ++int stm32_saes_unwrap_key(enum stm32_saes_chaining_mode ch_mode, ++ enum stm32_saes_key_selection key_select, const void *key, ++ size_t key_size, const void *iv, size_t iv_size, const void *in_data) ++{ ++ struct stm32_saes_context ctx; ++ ++ return stm32_saes_derived_key(&ctx, true, ++ true, false, ch_mode, key_select, ++ key, key_size, iv, iv_size, in_data, NULL); ++} +diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c +index 7d89d027e..befdfacbf 100644 +--- a/drivers/st/ddr/stm32mp1_ddr.c ++++ b/drivers/st/ddr/stm32mp1_ddr.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ +@@ -12,8 +12,9 @@ + #include + #include + #include ++#include + #include +-#include ++#include + #include + #include + #include +@@ -21,32 +22,45 @@ + #include + #include + +-struct reg_desc { +- const char *name; +- uint16_t offset; /* Offset for base address */ +- uint8_t par_offset; /* Offset for parameter array */ +-}; +- +-#define INVALID_OFFSET 0xFFU +- +-#define TIMEOUT_US_1S 1000000U ++#define TIMESLOT_US_1US 1U + + #define DDRCTL_REG(x, y) \ + { \ + .name = #x, \ +- .offset = offsetof(struct stm32mp1_ddrctl, x), \ ++ .offset = offsetof(struct stm32mp_ddrctl, x), \ + .par_offset = offsetof(struct y, x) \ + } + + #define DDRPHY_REG(x, y) \ + { \ + .name = #x, \ +- .offset = offsetof(struct stm32mp1_ddrphy, x), \ ++ .offset = offsetof(struct stm32mp_ddrphy, x), \ + .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 */ ++#if STM32MP_DDR_DUAL_AXI_PORT ++#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ ++#else ++#define DDRCTL_REG_PERF_SIZE 11 /* st,ctl-perf */ ++#endif ++ ++#if STM32MP_DDR_32BIT_INTERFACE ++#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ ++#else ++#define DDRPHY_REG_REG_SIZE 9 /* st,phy-reg */ ++#endif ++#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ ++ + #define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) +-static const struct reg_desc ddr_reg[] = { ++static const struct stm32mp_ddr_reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { + DDRCTL_REG_REG(mstr), + DDRCTL_REG_REG(mrctrl0), + DDRCTL_REG_REG(mrctrl1), +@@ -75,7 +89,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 stm32mp_ddr_reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = { + DDRCTL_REG_TIMING(rfshtmg), + DDRCTL_REG_TIMING(dramtmg0), + DDRCTL_REG_TIMING(dramtmg1), +@@ -91,7 +105,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 stm32mp_ddr_reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = { + DDRCTL_REG_MAP(addrmap1), + DDRCTL_REG_MAP(addrmap2), + DDRCTL_REG_MAP(addrmap3), +@@ -104,7 +118,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 stm32mp_ddr_reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { + DDRCTL_REG_PERF(sched), + DDRCTL_REG_PERF(sched1), + DDRCTL_REG_PERF(perfhpr1), +@@ -116,16 +130,18 @@ static const struct reg_desc ddr_perf[] = { + DDRCTL_REG_PERF(pcfgqos1_0), + DDRCTL_REG_PERF(pcfgwqos0_0), + DDRCTL_REG_PERF(pcfgwqos1_0), ++#if STM32MP_DDR_DUAL_AXI_PORT + DDRCTL_REG_PERF(pcfgr_1), + DDRCTL_REG_PERF(pcfgw_1), + DDRCTL_REG_PERF(pcfgqos0_1), + DDRCTL_REG_PERF(pcfgqos1_1), + DDRCTL_REG_PERF(pcfgwqos0_1), + DDRCTL_REG_PERF(pcfgwqos1_1), ++#endif + }; + + #define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) +-static const struct reg_desc ddrphy_reg[] = { ++static const struct stm32mp_ddr_reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = { + DDRPHY_REG_REG(pgcr), + DDRPHY_REG_REG(aciocr), + DDRPHY_REG_REG(dxccr), +@@ -135,12 +151,14 @@ static const struct reg_desc ddrphy_reg[] = { + DDRPHY_REG_REG(zq0cr1), + DDRPHY_REG_REG(dx0gcr), + DDRPHY_REG_REG(dx1gcr), ++#if STM32MP_DDR_32BIT_INTERFACE + DDRPHY_REG_REG(dx2gcr), + DDRPHY_REG_REG(dx3gcr), ++#endif + }; + + #define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) +-static const struct reg_desc ddrphy_timing[] = { ++static const struct stm32mp_ddr_reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = { + DDRPHY_REG_TIMING(ptr0), + DDRPHY_REG_TIMING(ptr1), + DDRPHY_REG_TIMING(ptr2), +@@ -153,174 +171,49 @@ static const struct reg_desc ddrphy_timing[] = { + DDRPHY_REG_TIMING(mr3), + }; + +-#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) +-static const struct reg_desc ddrphy_cal[] = { +- DDRPHY_REG_CAL(dx0dllcr), +- DDRPHY_REG_CAL(dx0dqtr), +- DDRPHY_REG_CAL(dx0dqstr), +- DDRPHY_REG_CAL(dx1dllcr), +- DDRPHY_REG_CAL(dx1dqtr), +- DDRPHY_REG_CAL(dx1dqstr), +- DDRPHY_REG_CAL(dx2dllcr), +- DDRPHY_REG_CAL(dx2dqtr), +- DDRPHY_REG_CAL(dx2dqstr), +- DDRPHY_REG_CAL(dx3dllcr), +- DDRPHY_REG_CAL(dx3dqtr), +- 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), +-}; +- +-enum reg_type { +- REG_REG, +- REG_TIMING, +- REG_PERF, +- REG_MAP, +- REGPHY_REG, +- REGPHY_TIMING, +- REGPHY_CAL, + /* +- * Dynamic registers => managed in driver or not changed, +- * can be dumped in interactive mode. ++ * REGISTERS ARRAY: used to parse device tree and interactive mode + */ +- REG_DYN, +- REGPHY_DYN, +- REG_TYPE_NB +-}; +- +-enum base_type { +- DDR_BASE, +- DDRPHY_BASE, +- NONE_BASE +-}; +- +-struct ddr_reg_info { +- const char *name; +- const struct reg_desc *desc; +- uint8_t size; +- enum base_type base; +-}; +- +-static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { ++static const struct stm32mp_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), +- .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_TIMING_SIZE, + .base = DDRPHY_BASE + }, + }; + +-static uintptr_t get_base_addr(const struct ddr_info *priv, enum base_type base) +-{ +- if (base == DDRPHY_BASE) { +- return (uintptr_t)priv->phy; +- } else { +- return (uintptr_t)priv->ctl; +- } +-} +- +-static void set_reg(const struct ddr_info *priv, +- enum reg_type type, +- const void *param) +-{ +- unsigned int i; +- unsigned int value; +- enum base_type base = ddr_registers[type].base; +- uintptr_t base_addr = get_base_addr(priv, base); +- const struct reg_desc *desc = ddr_registers[type].desc; +- +- VERBOSE("init %s\n", ddr_registers[type].name); +- for (i = 0; i < ddr_registers[type].size; i++) { +- 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 *)((uintptr_t)param + +- desc[i].par_offset)); +- mmio_write_32(ptr, value); +- } +- } +-} +- +-static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) ++static void stm32mp1_ddrphy_idone_wait(struct stm32mp_ddrphy *phy) + { + uint32_t pgsr; + int error = 0; +@@ -365,7 +258,7 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) + (uintptr_t)&phy->pgsr, pgsr); + } + +-static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) ++static void stm32mp1_ddrphy_init(struct stm32mp_ddrphy *phy, uint32_t pir) + { + uint32_t pir_init = pir | DDRPHYC_PIR_INIT; + +@@ -381,40 +274,8 @@ static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) + stm32mp1_ddrphy_idone_wait(phy); + } + +-/* Start quasi dynamic register update */ +-static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl) +-{ +- 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) +-{ +- uint64_t timeout; +- uint32_t swstat; +- +- 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)); +- +- timeout = timeout_init_us(TIMEOUT_US_1S); +- do { +- swstat = mmio_read_32((uintptr_t)&ctl->swstat); +- VERBOSE("[0x%lx] swstat = 0x%x ", +- (uintptr_t)&ctl->swstat, swstat); +- if (timeout_elapsed(timeout)) { +- panic(); +- } +- } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); +- +- 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) ++static void stm32mp1_wait_operating_mode(struct stm32mp_ddr_priv *priv, uint32_t mode) + { + uint64_t timeout; + uint32_t stat; +@@ -463,7 +324,7 @@ static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) + } + + /* Mode Register Writes (MRW or MRS) */ +-static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, ++static void stm32mp1_mode_register_write(struct stm32mp_ddr_priv *priv, uint8_t addr, + uint32_t data) + { + uint32_t mrctrl0; +@@ -518,7 +379,7 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, + } + + /* Switch DDR3 from DLL-on to DLL-off */ +-static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) ++static void stm32mp1_ddr3_dll_off(struct stm32mp_ddr_priv *priv) + { + uint32_t mr1 = mmio_read_32((uintptr_t)&priv->phy->mr1); + uint32_t mr2 = mmio_read_32((uintptr_t)&priv->phy->mr2); +@@ -609,14 +470,14 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) + * 9. Set the MSTR.dll_off_mode = 1. + * warning: MSTR.dll_off_mode is a quasi-dynamic type 2 field + */ +- stm32mp1_start_sw_done(priv->ctl); ++ stm32mp_ddr_start_sw_done(priv->ctl); + + 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); ++ stm32mp_ddr_wait_sw_done_ack(priv->ctl); + + /* 10. Change the clock frequency to the desired value. */ + +@@ -627,7 +488,7 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) + */ + + /* Change Bypass Mode Frequency Range */ +- if (stm32mp_clk_get_rate(DDRPHYC) < 100000000U) { ++ if (clk_get_rate(DDRPHYC) < 100000000U) { + mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, + DDRPHYC_DLLGCR_BPS200); + } else { +@@ -641,14 +502,15 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) + DDRPHYC_DXNDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); ++#if STM32MP_DDR_32BIT_INTERFACE + mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); ++#endif + + /* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ +- mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, +- DDRCTRL_PWRCTL_SELFREF_SW); ++ stm32mp_ddr_sw_selfref_exit(priv->ctl); + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); + + /* +@@ -663,62 +525,153 @@ 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((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)); ++ stm32mp_ddr_enable_host_interface(priv->ctl); + } + +-static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) ++static void stm32mp1_refresh_disable(struct stm32mp_ddrctl *ctl) + { +- stm32mp1_start_sw_done(ctl); +- /* Quasi-dynamic register update*/ ++ /* ++ * Manage quasi-dynamic registers modification ++ * dfimisc.dfi_init_complete_en : Group 3 ++ * AXI ports not yet enabled, don't disable them ++ */ ++ stm32mp_ddr_disable_host_interface(ctl); ++ stm32mp_ddr_start_sw_done(ctl); ++ + mmio_setbits_32((uintptr_t)&ctl->rfshctl3, + DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); +- mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); ++ stm32mp_ddr_wait_refresh_update_done_ack(ctl); ++ ++ 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); ++ ++ stm32mp_ddr_wait_sw_done_ack(ctl); ++ stm32mp_ddr_enable_host_interface(ctl); + } + +-static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, ++static void stm32mp1_refresh_restore(struct stm32mp_ddrctl *ctl, + uint32_t rfshctl3, uint32_t pwrctl) + { +- stm32mp1_start_sw_done(ctl); ++ /* ++ * Manage quasi-dynamic registers modification ++ * dfimisc.dfi_init_complete_en : Group 3 ++ * AXI ports not yet enabled, don't disable them ++ */ ++ stm32mp_ddr_disable_host_interface(ctl); ++ stm32mp_ddr_start_sw_done(ctl); ++ + if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { + mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, + DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); ++ stm32mp_ddr_wait_refresh_update_done_ack(ctl); + } + if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { + 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); ++ ++ stm32mp_ddr_wait_sw_done_ack(ctl); ++ stm32mp_ddr_enable_host_interface(ctl); + } + +-static int board_ddr_power_init(enum ddr_type ddr_type) ++static void stm32mp1_refresh_cmd(struct stm32mp_ddrctl *ctl) + { +- if (dt_pmic_status() > 0) { +- return pmic_ddr_power_init(ddr_type); ++ uint32_t dbgstat; ++ ++ do { ++ dbgstat = mmio_read_32((uintptr_t)&ctl->dbgstat); ++ } while ((dbgstat & DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY) != 0U); ++ ++ mmio_setbits_32((uintptr_t)&ctl->dbgcmd, DDRCTRL_DBGCMD_RANK0_REFRESH); ++} ++ ++/* Refresh compensation by forcing refresh command ++ * Rule1: Tref should be always < tREFW ? R x tREBW/8 ++ * Rule2: refcomp = RU(Tref/tREFI) = RU(RxTref/tREFW) ++ */ ++static ++void stm32mp1_refresh_compensation(const struct stm32mp_ddr_config *config, ++ struct stm32mp_ddrctl *ctl, ++ uint64_t start) ++{ ++ uint32_t tck_ps; ++ uint64_t time_us, tref, trefi, refcomp, i; ++ ++ time_us = timeout_init_us(0) - start; ++ tck_ps = 1000000000U / config->info.speed; ++ if (tck_ps == 0U) { ++ return; + } ++ /* ref = refresh time in tck */ ++ tref = time_us * 1000000U / tck_ps; ++ trefi = ((mmio_read_32((uintptr_t)&ctl->rfshtmg) & ++ DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK) ++ >> DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT) * 32U; ++ if (trefi == 0U) { ++ return; ++ } ++ ++ /* div round up : number of refresh to compensate */ ++ refcomp = (tref + trefi - 1U) / trefi; + +- return 0; ++ for (i = 0; i < refcomp; i++) { ++ stm32mp1_refresh_cmd(ctl); ++ } + } + +-void stm32mp1_ddr_init(struct ddr_info *priv, +- struct stm32mp1_ddr_config *config) ++static void stm32mp1_self_refresh_zcal(struct stm32mp_ddr_priv *priv, uint32_t zdata) + { +- uint32_t pir; ++ /* sequence for PUBL I/O Data Retention during Power-Down */ ++ ++ /* 10. Override ZQ calibration with previously (pre-retention) ++ * calibrated values. This is done by writing 1 to ZQ0CRN.ZDEN ++ * and the override data to ZQ0CRN.ZDATA. ++ */ ++ mmio_setbits_32((uintptr_t)&priv->phy->zq0cr0, DDRPHYC_ZQ0CRN_ZDEN); ++ ++ mmio_clrsetbits_32((uintptr_t)&priv->phy->zq0cr0, ++ DDRPHYC_ZQ0CRN_ZDATA_MASK, ++ zdata << DDRPHYC_ZQ0CRN_ZDATA_SHIFT); ++ ++ /* 11. De-assert the PHY_top data retention enable signals ++ * (ret_en or ret_en_i/ret_en_n_i). ++ */ ++ mmio_setbits_32((uintptr_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRSRDIS); ++ mmio_clrbits_32((uintptr_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRRETEN); ++ ++ /* 12. Remove ZQ calibration override by writing 0 to ZQ0CRN.ZDEN. */ ++ mmio_clrbits_32((uintptr_t)&priv->phy->zq0cr0, DDRPHYC_ZQ0CRN_ZDEN); ++ ++ /* 13. Trigger ZQ calibration by writing 1 to PIR.INIT ++ * and '1' to PIR.ZCAL ++ */ ++ /* 14. Wait for ZQ calibration to finish by polling a 1 status ++ * on PGSR.IDONE. ++ */ ++ stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_ZCAL); ++} ++ ++void stm32mp1_ddr_init(struct stm32mp_ddr_priv *priv, ++ struct stm32mp_ddr_config *config) ++{ ++ uint32_t pir, ddr_reten; ++ uint64_t time; + int ret = -EINVAL; + + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { +- ret = board_ddr_power_init(STM32MP_DDR3); ++ ret = stm32mp_board_ddr_power_init(STM32MP_DDR3); + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) { +- ret = board_ddr_power_init(STM32MP_LPDDR2); ++ ret = stm32mp_board_ddr_power_init(STM32MP_LPDDR2); + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) != 0U) { +- ret = board_ddr_power_init(STM32MP_LPDDR3); ++ ret = stm32mp_board_ddr_power_init(STM32MP_LPDDR3); + } else { + ERROR("DDR type not supported\n"); + } +@@ -728,8 +681,27 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + } + + VERBOSE("name = %s\n", config->info.name); +- VERBOSE("speed = %d kHz\n", config->info.speed); ++ VERBOSE("speed = %u 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); ++ } ++ ++ /* Check DDR PHY pads retention */ ++ ddr_reten = mmio_read_32((uint32_t)(priv->pwr) + PWR_CR3) & ++ PWR_CR3_DDRRETEN; ++ if (config->self_refresh) { ++ if (ddr_reten == 0U) { ++ VERBOSE("self-refresh aborted: no retention\n"); ++ config->self_refresh = false; ++ } ++ } ++ ++ if (!config->self_refresh) { ++ VERBOSE("disable DDR PHY retention\n"); ++ mmio_setbits_32((uint32_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRSRDIS); ++ mmio_clrbits_32((uint32_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRRETEN); ++ } + + /* DDR INIT SEQUENCE */ + +@@ -773,7 +745,7 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); + +- set_reg(priv, REG_REG, &config->c_reg); ++ stm32mp_ddr_set_reg(priv, REG_REG, &config->c_reg, ddr_registers); + + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & +@@ -787,8 +759,14 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); + } + +- set_reg(priv, REG_TIMING, &config->c_timing); +- set_reg(priv, REG_MAP, &config->c_map); ++ stm32mp_ddr_set_reg(priv, REG_TIMING, &config->c_timing, ddr_registers); ++ stm32mp_ddr_set_reg(priv, REG_MAP, &config->c_map, ddr_registers); ++ ++ /* 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, +@@ -798,7 +776,7 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + (uintptr_t)&priv->ctl->init0, + mmio_read_32((uintptr_t)&priv->ctl->init0)); + +- set_reg(priv, REG_PERF, &config->c_perf); ++ stm32mp_ddr_set_reg(priv, REG_PERF, &config->c_perf, ddr_registers); + + /* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); +@@ -809,9 +787,8 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + * 3. start PHY init by accessing relevant PUBL registers + * (DXGCR, DCR, PTR*, MR*, DTPR*) + */ +- set_reg(priv, REGPHY_REG, &config->p_reg); +- set_reg(priv, REGPHY_TIMING, &config->p_timing); +- set_reg(priv, REGPHY_CAL, &config->p_cal); ++ stm32mp_ddr_set_reg(priv, REGPHY_REG, &config->p_reg, ddr_registers); ++ stm32mp_ddr_set_reg(priv, REGPHY_TIMING, &config->p_timing, ddr_registers); + + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & +@@ -843,13 +820,25 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */ + } + ++ /* Treat self-refresh exit : hot boot */ ++ if (config->self_refresh) { ++ /* DDR in self refresh mode, remove zcal & reset & init */ ++ pir &= ~(DDRPHYC_PIR_ZCAL & DDRPHYC_PIR_DRAMRST ++ & DDRPHYC_PIR_DRAMINIT); ++ pir |= DDRPHYC_PIR_ZCALBYP; ++ } ++ + stm32mp1_ddrphy_init(priv->phy, pir); + ++ if (config->self_refresh) { ++ stm32mp1_self_refresh_zcal(priv, config->zdata); ++ } ++ + /* + * 6. SET DFIMISC.dfi_init_complete_en to 1 + * Enable quasi-dynamic register programming. + */ +- stm32mp1_start_sw_done(priv->ctl); ++ stm32mp_ddr_start_sw_done(priv->ctl); + + mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); +@@ -857,7 +846,7 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); + +- stm32mp1_wait_sw_done_ack(priv->ctl); ++ stm32mp_ddr_wait_sw_done_ack(priv->ctl); + + /* + * 7. Wait for DWC_ddr_umctl2 to move to normal operation mode +@@ -865,6 +854,12 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + */ + + /* Wait uMCTL2 ready */ ++ ++ /* Trigger self-refresh exit */ ++ if (config->self_refresh) { ++ stm32mp_ddr_sw_selfref_exit(priv->ctl); ++ } ++ + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); + + /* Switch to DLL OFF mode */ +@@ -872,7 +867,9 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + stm32mp1_ddr3_dll_off(priv); + } + +- VERBOSE("DDR DQS training : "); ++ VERBOSE("DDR DQS training.\n"); ++ ++ time = timeout_init_us(0); + + /* + * 8. Disable Auto refresh and power down by setting +@@ -891,30 +888,28 @@ void stm32mp1_ddr_init(struct ddr_info *priv, + /* + * 10. configure PUBL PIR register to specify which training step + * to run +- * Warning : RVTRN is not supported by this PUBL ++ * RVTRN is executed only on LPDDR2/LPDDR3 + */ +- stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); ++ pir = DDRPHYC_PIR_QSTRN; ++ if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) == 0U) { ++ pir |= DDRPHYC_PIR_RVTRN; ++ } + +- /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ ++ stm32mp1_ddrphy_init(priv->phy, pir); ++ ++ /* 11. monitor PUB PGSR.IDONE to poll completion 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); ++ } ++ + /* + * 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); + +- /* Enable uMCTL2 AXI port 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((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)); ++ stm32mp_ddr_enable_axi_port(priv->ctl); + } +diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c +index fcb4cfcfd..49f9c3d09 100644 +--- a/drivers/st/ddr/stm32mp1_ddr_helpers.c ++++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c +@@ -1,13 +1,20 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + #include + ++#include ++#include ++#include ++#include ++#include + #include ++#include + #include ++#include + + void ddr_enable_clock(void) + { +@@ -15,10 +22,547 @@ void ddr_enable_clock(void) + + mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, + RCC_DDRITFCR_DDRC1EN | ++#if STM32MP_DDR_DUAL_AXI_PORT + RCC_DDRITFCR_DDRC2EN | ++#endif + RCC_DDRITFCR_DDRPHYCEN | + RCC_DDRITFCR_DDRPHYCAPBEN | + RCC_DDRITFCR_DDRCAPBEN); + + stm32mp1_clk_rcc_regs_unlock(); + } ++ ++static int ddr_sw_self_refresh_in(void) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uintptr_t pwr_base = stm32mp_pwr_base(); ++ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); ++ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base(); ++ ++ stm32mp1_clk_rcc_regs_lock(); ++ ++ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); ++ ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ /* Blocks AXI ports from taking anymore transactions */ ++ if (stm32mp_ddr_disable_axi_port((struct stm32mp_ddrctl *)ddrctrl_base) != 0U) { ++ goto pstat_failed; ++ } ++ ++ /* SW Self-Refresh entry */ ++ if (stm32mp_ddr_sw_selfref_entry((struct stm32mp_ddrctl *)ddrctrl_base) != 0U) { ++ goto selfref_sw_failed; ++ } ++ ++ /* IOs powering down (PUBL registers) */ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); ++ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDR); ++ ++ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR, ++ DDRPHYC_ACIOCR_CKPDD_MASK, ++ DDRPHYC_ACIOCR_CKPDD_0); ++ ++ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR, ++ DDRPHYC_ACIOCR_CKPDR_MASK, ++ DDRPHYC_ACIOCR_CKPDR_0); ++ ++ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR, ++ 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); ++ ++ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_DSGCR, ++ DDRPHYC_DSGCR_ODTPDD_MASK, ++ DDRPHYC_DSGCR_ODTPDD_0); ++ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); ++ ++ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_DSGCR, ++ DDRPHYC_DSGCR_CKEPDD_MASK, ++ DDRPHYC_DSGCR_CKEPDD_0); ++ ++ /* 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 */ ++ stm32mp_pwr_regs_lock(); ++ mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); ++ stm32mp_pwr_regs_unlock(); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ ++ stm32mp1_clk_rcc_regs_lock(); ++ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ /* Disable all DLLs: GLITCH window */ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, ++ DDRPHYC_ACDLLCR_DLLDIS); ++ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX0DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX1DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++ ++#if STM32MP_DDR_32BIT_INTERFACE ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX2DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX3DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++#endif ++ ++ stm32mp1_clk_rcc_regs_lock(); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL output clock */ ++ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ ++ /* Deactivate all DDR clocks */ ++ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, ++ RCC_DDRITFCR_DDRC1EN | ++#if STM32MP_DDR_DUAL_AXI_PORT ++ RCC_DDRITFCR_DDRC2EN | ++#endif ++ RCC_DDRITFCR_DDRCAPBEN | ++ RCC_DDRITFCR_DDRPHYCAPBEN); ++ ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ return 0; ++ ++selfref_sw_failed: ++ /* Restore DDR in its previous state */ ++ stm32mp_ddr_sw_selfref_exit((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++pstat_failed: ++ stm32mp_ddr_enable_axi_port((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ return -1; ++} ++ ++int ddr_sw_self_refresh_exit(void) ++{ ++ uint64_t timeout; ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ uintptr_t pwr_base = stm32mp_pwr_base(); ++ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); ++ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base(); ++ ++ /* Enable all clocks */ ++ ddr_enable_clock(); ++ ++ /* ++ * Manage quasi-dynamic registers modification ++ * dfimisc.dfi_init_complete_en : Group 3 ++ */ ++ stm32mp_ddr_set_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Mask dfi_init_complete_en */ ++ mmio_clrbits_32(ddrctrl_base + DDRCTRL_DFIMISC, ++ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); ++ ++ stm32mp_ddr_unset_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ ++ stm32mp1_clk_rcc_regs_lock(); ++ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ /* Enable all DLLs: GLITCH window */ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, ++ DDRPHYC_ACDLLCR_DLLDIS); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX0DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX1DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++ ++#if STM32MP_DDR_32BIT_INTERFACE ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX2DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX3DLLCR, ++ DDRPHYC_DXNDLLCR_DLLDIS); ++#endif ++ ++ /* Additional delay to avoid early DLL clock switch */ ++ udelay(50); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ ++ stm32mp1_clk_rcc_regs_lock(); ++ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, ++ DDRPHYC_ACDLLCR_DLLSRST); ++ ++ udelay(10); ++ ++ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACDLLCR, ++ DDRPHYC_ACDLLCR_DLLSRST); ++ ++ /* PHY partial init: (DLL lock and ITM reset) */ ++ mmio_write_32(ddrphyc_base + DDRPHYC_PIR, ++ DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | ++ DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_INIT); ++ ++ /* Need to wait at least 10 clock cycles before accessing PGSR */ ++ udelay(1); ++ ++ /* Pool end of init */ ++ timeout = timeout_init_us(TIMEOUT_500US); ++ ++ while ((mmio_read_32(ddrphyc_base + DDRPHYC_PGSR) & ++ DDRPHYC_PGSR_IDONE) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ return -1; ++ } ++ } ++ ++ /* ++ * Manage quasi-dynamic registers modification ++ * dfimisc.dfi_init_complete_en : Group 3 ++ */ ++ stm32mp_ddr_set_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Unmask dfi_init_complete_en to uMCTL2 */ ++ mmio_setbits_32(ddrctrl_base + DDRCTRL_DFIMISC, ++ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); ++ ++ stm32mp_ddr_unset_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Deactivate sw retention in PWR */ ++ stm32mp_pwr_regs_lock(); ++ mmio_clrbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN); ++ stm32mp_pwr_regs_unlock(); ++ ++ /* Enable PZQ cell (PUBL register) */ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); ++ ++ /* 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); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, ++ DDRPHYC_ACIOCR_CSPDD_MASK); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); ++ ++ 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); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); ++ ++ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, ++ DDRPHYC_DSGCR_CKEPDD_MASK); ++ ++ /* Remove selfrefresh */ ++ stm32mp_ddr_sw_selfref_exit((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Wait operating_mode == normal */ ++ 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(timeout)) { ++ return -1; ++ } ++ } ++ ++ /* AXI ports are no longer blocked from taking transactions */ ++ stm32mp_ddr_enable_axi_port((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ stm32mp1_clk_rcc_regs_lock(); ++ ++ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); ++ ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ return 0; ++} ++ ++uint32_t ddr_get_io_calibration_val(void) ++{ ++ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base(); ++ ++ return mmio_read_32(ddrphyc_base + DDRPHYC_ZQ0CR0) & ++ DDRPHYC_ZQ0CRN_ZDATA_MASK; ++} ++ ++int ddr_standby_sr_entry(void) ++{ ++ uintptr_t pwr_base = stm32mp_pwr_base(); ++ ++ /* Put DDR in Self-Refresh */ ++ if (ddr_sw_self_refresh_in() != 0) { ++ return -1; ++ } ++ ++ /* Enable I/O retention mode in standby */ ++ stm32mp_pwr_regs_lock(); ++ mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRSREN); ++ stm32mp_pwr_regs_unlock(); ++ ++ return 0; ++} ++ ++static void ddr_sr_mode_ssr(void) ++{ ++ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; ++ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); ++ ++ stm32mp1_clk_rcc_regs_lock(); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1EN); ++ ++#if STM32MP_DDR_DUAL_AXI_PORT ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2EN); ++#endif ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBLPEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBLPEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCEN); ++ ++ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); ++ ++ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK); ++ ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ /* ++ * Manage quasi-dynamic registers modification ++ * hwlpctl.hw_lp_en : Group 3 ++ * pwrtmg.selfref_to_x32 & powerdown_to_x32 : Group 4 ++ * Group 3 is the most restrictive, apply its conditions for all ++ */ ++ stm32mp_ddr_set_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Disable HW LP interface of uMCTL2 */ ++ mmio_clrbits_32(ddrctrl_base + DDRCTRL_HWLPCTL, ++ DDRCTRL_HWLPCTL_HW_LP_EN); ++ ++ /* Configure Automatic LP modes of uMCTL2 */ ++ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG, ++ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK, ++ DDRCTRL_PWRTMG_SELFREF_TO_X32_0); ++ ++ stm32mp_ddr_unset_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* ++ * Disable Clock disable with LP modes ++ * (used in RUN mode for LPDDR2 with specific timing). ++ */ ++ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); ++ ++ /* Disable automatic Self-Refresh mode */ ++ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_SELFREF_EN); ++} ++ ++static void ddr_sr_mode_asr(void) ++{ ++ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; ++ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); ++ ++ stm32mp1_clk_rcc_regs_lock(); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); ++ ++#if STM32MP_DDR_DUAL_AXI_PORT ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); ++#endif ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); ++ ++ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, ++ RCC_DDRITFCR_DDRCKMOD_ASR1); ++ ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ /* ++ * Manage quasi-dynamic registers modification ++ * hwlpctl.hw_lp_en : Group 3 ++ * pwrtmg.selfref_to_x32 & powerdown_to_x32 : Group 4 ++ * Group 3 is the most restrictive, apply its conditions for all ++ */ ++ stm32mp_ddr_set_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Enable HW LP interface of uMCTL2 */ ++ mmio_setbits_32(ddrctrl_base + DDRCTRL_HWLPCTL, ++ DDRCTRL_HWLPCTL_HW_LP_EN); ++ ++ /* Configure Automatic LP modes of uMCTL2 */ ++ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG, ++ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK, ++ DDRCTRL_PWRTMG_SELFREF_TO_X32_0); ++ ++ stm32mp_ddr_unset_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* ++ * Enable Clock disable with LP modes ++ * (used in RUN mode for LPDDR2 with specific timing). ++ */ ++ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); ++ ++ /* Enable automatic Self-Refresh for ASR mode */ ++ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_SELFREF_EN); ++} ++ ++static void ddr_sr_mode_hsr(void) ++{ ++ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; ++ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); ++ ++ stm32mp1_clk_rcc_regs_lock(); ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); ++ ++ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); ++ ++#if STM32MP_DDR_DUAL_AXI_PORT ++ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); ++#endif ++ ++ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); ++ ++ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, ++ RCC_DDRITFCR_DDRCKMOD_HSR1); ++ ++ stm32mp1_clk_rcc_regs_unlock(); ++ ++ /* ++ * Manage quasi-dynamic registers modification ++ * hwlpctl.hw_lp_en : Group 3 ++ * pwrtmg.selfref_to_x32 & powerdown_to_x32 : Group 4 ++ * Group 3 is the most restrictive, apply its conditions for all ++ */ ++ stm32mp_ddr_set_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* Enable HW LP interface of uMCTL2 */ ++ mmio_setbits_32(ddrctrl_base + DDRCTRL_HWLPCTL, ++ DDRCTRL_HWLPCTL_HW_LP_EN); ++ ++ /* Configure Automatic LP modes of uMCTL2 */ ++ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG, ++ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK, ++ DDRCTRL_PWRTMG_SELFREF_TO_X32_0); ++ ++ stm32mp_ddr_unset_qd3_update_conditions((struct stm32mp_ddrctl *)ddrctrl_base); ++ ++ /* ++ * Enable Clock disable with LP modes ++ * (used in RUN mode for LPDDR2 with specific timing). ++ */ ++ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, ++ 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(); ++ } ++} ++ ++bool ddr_is_nonsecured_area(uintptr_t address, uint32_t length) ++{ ++ uint64_t pa; ++ ++ write_ats1cpw(address); ++ ++ isb(); ++ ++ pa = read64_par(); ++ ++ if ((((pa >> PAR_NS_SHIFT) & PAR_NS_MASK) != PAR_NS_MASK) || ++ (((pa >> PAR_F_SHIFT) & PAR_F_MASK) == PAR_F_MASK)) { ++ return false; ++ } ++ ++ write_ats1cpw(address + length - 1U); ++ ++ isb(); ++ ++ pa = read64_par(); ++ ++ if ((((pa >> PAR_NS_SHIFT) & PAR_NS_MASK) == PAR_NS_MASK) && ++ (((pa >> PAR_F_SHIFT) & PAR_F_MASK) != PAR_F_MASK)) { ++ return true; ++ } ++ ++ return false; ++} +diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c +index b21c8949f..615fa2862 100644 +--- a/drivers/st/ddr/stm32mp1_ram.c ++++ b/drivers/st/ddr/stm32mp1_ram.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ +@@ -13,25 +13,27 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + #include + #include + #include + #include + +-#define DDR_PATTERN 0xAAAAAAAAU +-#define DDR_ANTIPATTERN 0x55555555U ++static struct stm32mp_ddr_priv ddr_priv_data; ++static bool ddr_self_refresh; + +-static struct ddr_info ddr_priv_data; +- +-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) ++int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed) + { + unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; + + ddr_enable_clock(); + +- ddrphy_clk = stm32mp_clk_get_rate(DDRPHYC); ++ ddrphy_clk = clk_get_rate(DDRPHYC); + +- VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n", ++ VERBOSE("DDR: mem_speed (%u kHz), RCC %lu kHz\n", + mem_speed, ddrphy_clk / 1000U); + + mem_speed_hz = mem_speed * 1000U; +@@ -43,157 +45,29 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) + ddr_clk = mem_speed_hz - ddrphy_clk; + } + if (ddr_clk > (mem_speed_hz / 10)) { +- ERROR("DDR expected freq %d kHz, current is %ld kHz\n", ++ ERROR("DDR expected freq %u kHz, current is %lu kHz\n", + mem_speed, ddrphy_clk / 1000U); + return -1; + } + 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. +- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ +- * File: memtest.c - This source code belongs to Public Domain. +- * Returns 0 if success, and address value else. +- ******************************************************************************/ +-static uint32_t ddr_test_data_bus(void) +-{ +- uint32_t pattern; +- +- for (pattern = 1U; pattern != 0U; pattern <<= 1) { +- mmio_write_32(STM32MP_DDR_BASE, pattern); +- +- if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { +- return (uint32_t)STM32MP_DDR_BASE; +- } +- } +- +- return 0; +-} +- +-/******************************************************************************* +- * This function tests the DDR address bus wiring. +- * This is inspired from the Data Bus Test algorithm written by Michael Barr +- * in "Programming Embedded Systems in C and C++" book. +- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ +- * File: memtest.c - This source code belongs to Public Domain. +- * Returns 0 if success, and address value else. +- ******************************************************************************/ +-static uint32_t ddr_test_addr_bus(void) +-{ +- uint64_t addressmask = (ddr_priv_data.info.size - 1U); +- uint64_t offset; +- uint64_t testoffset = 0; +- +- /* 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(STM32MP_DDR_BASE + (uint32_t)offset, +- DDR_PATTERN); +- } +- +- /* Check for address bits stuck high. */ +- 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(STM32MP_DDR_BASE + (uint32_t)offset) != +- DDR_PATTERN) { +- return (uint32_t)(STM32MP_DDR_BASE + offset); +- } +- } +- +- 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(STM32MP_DDR_BASE + (uint32_t)testoffset, +- DDR_ANTIPATTERN); +- +- 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(STM32MP_DDR_BASE + +- (uint32_t)offset) != DDR_PATTERN) && +- (offset != testoffset)) { +- return (uint32_t)(STM32MP_DDR_BASE + offset); +- } +- } +- +- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, +- DDR_PATTERN); +- } +- +- return 0; +-} +- +-/******************************************************************************* +- * This function checks the DDR size. It has to be run with Data Cache off. +- * This test is run before data have been put in DDR, and is only done for +- * cold boot. The DDR data can then be overwritten, and it is not useful to +- * restore its content. +- * Returns DDR computed size. +- ******************************************************************************/ +-static uint32_t ddr_check_size(void) +-{ +- uint32_t offset = sizeof(uint32_t); +- +- mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); +- +- while (offset < STM32MP_DDR_MAX_SIZE) { +- mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); +- dsb(); +- +- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { +- break; +- } +- +- offset <<= 1; +- } +- +- INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U)); +- +- return offset; +-} +- + static int stm32mp1_ddr_setup(void) + { +- struct ddr_info *priv = &ddr_priv_data; ++ struct stm32mp_ddr_priv *priv = &ddr_priv_data; + int ret; +- struct stm32mp1_ddr_config config; +- int node, len; +- uint32_t uret, idx; ++ struct stm32mp_ddr_config config; ++ int node; ++ uint32_t uret; + void *fdt; + +-#define PARAM(x, y) \ +- { \ +- .name = x, \ +- .offset = offsetof(struct stm32mp1_ddr_config, y), \ +- .size = sizeof(config.y) / sizeof(uint32_t) \ +- } +- +-#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) +-#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) +- +- const struct { +- const char *name; /* Name in DT */ +- const uint32_t offset; /* Offset in config struct */ +- const uint32_t size; /* Size of parameters */ +- } param[] = { ++ const struct stm32mp_ddr_param param[] = { + CTL_PARAM(reg), + CTL_PARAM(timing), + CTL_PARAM(map), + CTL_PARAM(perf), + PHY_PARAM(reg), + PHY_PARAM(timing), +- PHY_PARAM(cal) + }; + + if (fdt_get_address(&fdt) == 0) { +@@ -206,36 +80,21 @@ static int stm32mp1_ddr_setup(void) + return -EINVAL; + } + +- ret = fdt_read_uint32(fdt, node, "st,mem-speed", &config.info.speed); ++ ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); + if (ret < 0) { +- VERBOSE("%s: no st,mem-speed\n", __func__); +- return -EINVAL; ++ return ret; + } +- ret = fdt_read_uint32(fdt, node, "st,mem-size", &config.info.size); ++ ++ ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); + if (ret < 0) { +- 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__); +- return -EINVAL; ++ return ret; + } +- INFO("RAM: %s\n", config.info.name); +- +- for (idx = 0; idx < ARRAY_SIZE(param); idx++) { +- ret = fdt_read_uint32_array(fdt, node, param[idx].name, +- param[idx].size, +- (void *)((uintptr_t)&config + +- param[idx].offset)); +- +- 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); +- return -EINVAL; +- } ++ ++ config.self_refresh = false; ++ ++ if (stm32mp1_is_wakeup_from_standby()) { ++ config.self_refresh = true; ++ config.zdata = stm32_get_zdata_from_context(); + } + + /* Disable axidcg clock gating during init */ +@@ -255,42 +114,69 @@ static int stm32mp1_ddr_setup(void) + panic(); + } + +- uret = ddr_test_data_bus(); +- if (uret != 0U) { +- ERROR("DDR data bus test: can't access memory @ 0x%x\n", +- uret); +- panic(); +- } ++ if (config.self_refresh) { ++ uret = stm32mp_ddr_test_rw_access(); ++ if (uret != 0U) { ++ ERROR("DDR rw test: Can't access memory @ 0x%x\n", ++ uret); ++ panic(); ++ } + +- uret = ddr_test_addr_bus(); +- if (uret != 0U) { +- ERROR("DDR addr bus test: can't access memory @ 0x%x\n", +- uret); +- panic(); +- } ++ /* Restore area overwritten by training */ ++ stm32_restore_ddr_training_area(); ++ } else { ++ uret = stm32mp_ddr_test_data_bus(); ++ if (uret != 0U) { ++ ERROR("DDR data bus test: can't access memory @ 0x%x\n", ++ uret); ++ panic(); ++ } + +- uret = ddr_check_size(); +- if (uret < config.info.size) { +- ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", +- uret, config.info.size); +- panic(); ++ uret = stm32mp_ddr_test_addr_bus(config.info.size); ++ if (uret != 0U) { ++ ERROR("DDR addr bus test: can't access memory @ 0x%x\n", ++ uret); ++ panic(); ++ } ++ ++ uret = stm32mp_ddr_check_size(); ++ if (uret < config.info.size) { ++ ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", ++ uret, config.info.size); ++ panic(); ++ } + } + ++ /* ++ * 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()); ++ + if (stm32mp_unmap_ddr() != 0) { + panic(); + } + ++ /* Save DDR self_refresh state */ ++ ddr_self_refresh = config.self_refresh; ++ + return 0; + } + ++bool stm32mp1_ddr_is_restored(void) ++{ ++ return ddr_self_refresh; ++} ++ + int stm32mp1_ddr_probe(void) + { +- struct ddr_info *priv = &ddr_priv_data; ++ struct stm32mp_ddr_priv *priv = &ddr_priv_data; + + VERBOSE("STM32MP DDR probe\n"); + +- priv->ctl = (struct stm32mp1_ddrctl *)stm32mp_ddrctrl_base(); +- priv->phy = (struct stm32mp1_ddrphy *)stm32mp_ddrphyc_base(); ++ priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); ++ priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); + priv->pwr = stm32mp_pwr_base(); + priv->rcc = stm32mp_rcc_base(); + +diff --git a/drivers/st/ddr/stm32mp_ddr.c b/drivers/st/ddr/stm32mp_ddr.c +new file mode 100644 +index 000000000..d162c75d1 +--- /dev/null ++++ b/drivers/st/ddr/stm32mp_ddr.c +@@ -0,0 +1,268 @@ ++/* ++ * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define INVALID_OFFSET 0xFFU ++ ++static uintptr_t get_base_addr(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_base_type base) ++{ ++ if (base == DDRPHY_BASE) { ++ return (uintptr_t)priv->phy; ++ } else { ++ return (uintptr_t)priv->ctl; ++ } ++} ++ ++void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type, ++ const void *param, const struct stm32mp_ddr_reg_info *ddr_registers) ++{ ++ unsigned int i; ++ unsigned int value; ++ enum stm32mp_ddr_base_type base = ddr_registers[type].base; ++ uintptr_t base_addr = get_base_addr(priv, base); ++ const struct stm32mp_ddr_reg_desc *desc = ddr_registers[type].desc; ++ ++ VERBOSE("init %s\n", ddr_registers[type].name); ++ for (i = 0; i < ddr_registers[type].size; i++) { ++ 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 *)((uintptr_t)param + ++ desc[i].par_offset)); ++ mmio_write_32(ptr, value); ++ } ++ } ++} ++ ++/* Start quasi dynamic register update */ ++void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl) ++{ ++ 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 */ ++void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl) ++{ ++ uint64_t timeout; ++ uint32_t swstat; ++ ++ 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)); ++ ++ timeout = timeout_init_us(TIMEOUT_US_1S); ++ do { ++ swstat = mmio_read_32((uintptr_t)&ctl->swstat); ++ VERBOSE("[0x%lx] swstat = 0x%x ", ++ (uintptr_t)&ctl->swstat, swstat); ++ if (timeout_elapsed(timeout)) { ++ panic(); ++ } ++ } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); ++ ++ VERBOSE("[0x%lx] swstat = 0x%x\n", ++ (uintptr_t)&ctl->swstat, swstat); ++} ++ ++void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl) ++{ ++ /* Enable uMCTL2 AXI port 0 */ ++ mmio_setbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); ++ VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0, ++ mmio_read_32((uintptr_t)&ctl->pctrl_0)); ++ ++#if STM32MP_DDR_DUAL_AXI_PORT ++ /* Enable uMCTL2 AXI port 1 */ ++ mmio_setbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); ++ VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1, ++ mmio_read_32((uintptr_t)&ctl->pctrl_1)); ++#endif ++} ++ ++int stm32mp_ddr_disable_axi_port(struct stm32mp_ddrctl *ctl) ++{ ++ uint64_t timeout; ++ uint32_t pstat; ++ ++ /* Disable uMCTL2 AXI port 0 */ ++ mmio_clrbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); ++ VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0, ++ mmio_read_32((uintptr_t)&ctl->pctrl_0)); ++ ++#if STM32MP_DDR_DUAL_AXI_PORT ++ /* Disable uMCTL2 AXI port 1 */ ++ mmio_clrbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); ++ VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1, ++ mmio_read_32((uintptr_t)&ctl->pctrl_1)); ++#endif ++ ++ /* ++ * Waits until all AXI ports are idle ++ * Poll PSTAT.rd_port_busy_n = 0 ++ * Poll PSTAT.wr_port_busy_n = 0 ++ */ ++ timeout = timeout_init_us(TIMEOUT_US_1S); ++ do { ++ pstat = mmio_read_32((uintptr_t)&ctl->pstat); ++ VERBOSE("[0x%lx] pstat = 0x%x ", ++ (uintptr_t)&ctl->pstat, pstat); ++ if (timeout_elapsed(timeout)) { ++ return -1; ++ } ++ } while (pstat != 0U); ++ ++ return 0; ++} ++ ++void stm32mp_ddr_enable_host_interface(struct stm32mp_ddrctl *ctl) ++{ ++ mmio_clrbits_32((uintptr_t)&ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); ++ VERBOSE("[0x%lx] dbg1 = 0x%x\n", ++ (uintptr_t)&ctl->dbg1, ++ mmio_read_32((uintptr_t)&ctl->dbg1)); ++} ++ ++void stm32mp_ddr_disable_host_interface(struct stm32mp_ddrctl *ctl) ++{ ++ uint64_t timeout; ++ uint32_t dbgcam; ++ int count = 0; ++ ++ mmio_setbits_32((uintptr_t)&ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); ++ VERBOSE("[0x%lx] dbg1 = 0x%x\n", ++ (uintptr_t)&ctl->dbg1, ++ mmio_read_32((uintptr_t)&ctl->dbg1)); ++ ++ /* ++ * Waits until all queues and pipelines are empty ++ * Poll DBGCAM.dbg_wr_q_empty = 1 ++ * Poll DBGCAM.dbg_rd_q_empty = 1 ++ * Poll DBGCAM.dbg_wr_data_pipeline_empty = 1 ++ * Poll DBGCAM.dbg_rd_data_pipeline_empty = 1 ++ * ++ * data_pipeline fields must be polled twice to ensure ++ * value propoagation, so count is added to loop condition. ++ */ ++ timeout = timeout_init_us(TIMEOUT_US_1S); ++ do { ++ dbgcam = mmio_read_32((uintptr_t)&ctl->dbgcam); ++ VERBOSE("[0x%lx] dbgcam = 0x%x ", ++ (uintptr_t)&ctl->dbgcam, dbgcam); ++ if (timeout_elapsed(timeout)) { ++ panic(); ++ } ++ count++; ++ } while (((dbgcam & DDRCTRL_DBG_Q_AND_DATA_PIPELINE_EMPTY) != ++ DDRCTRL_DBG_Q_AND_DATA_PIPELINE_EMPTY) || (count < 2)); ++} ++ ++int stm32mp_ddr_sw_selfref_entry(struct stm32mp_ddrctl *ctl) ++{ ++ uint64_t timeout; ++ uint32_t stat; ++ uint32_t operating_mode; ++ uint32_t selref_type; ++ ++ mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW); ++ VERBOSE("[0x%lx] pwrctl = 0x%x\n", ++ (uintptr_t)&ctl->pwrctl, ++ mmio_read_32((uintptr_t)&ctl->pwrctl)); ++ ++ /* ++ * Wait operating mode change in self-refresh mode ++ * with STAT.operating_mode[1:0]==11. ++ * Ensure transition to self-refresh was due to software ++ * by checking also that STAT.selfref_type[1:0]=2. ++ */ ++ timeout = timeout_init_us(TIMEOUT_500US); ++ while (!timeout_elapsed(timeout)) { ++ stat = mmio_read_32((uintptr_t)&ctl->stat); ++ operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; ++ selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; ++ ++ if ((operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) && ++ (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) { ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++void stm32mp_ddr_sw_selfref_exit(struct stm32mp_ddrctl *ctl) ++{ ++ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW); ++ VERBOSE("[0x%lx] pwrctl = 0x%x\n", ++ (uintptr_t)&ctl->pwrctl, ++ mmio_read_32((uintptr_t)&ctl->pwrctl)); ++} ++ ++void stm32mp_ddr_set_qd3_update_conditions(struct stm32mp_ddrctl *ctl) ++{ ++ if (stm32mp_ddr_disable_axi_port(ctl) != 0) { ++ panic(); ++ } ++ stm32mp_ddr_disable_host_interface(ctl); ++ stm32mp_ddr_start_sw_done(ctl); ++} ++ ++void stm32mp_ddr_unset_qd3_update_conditions(struct stm32mp_ddrctl *ctl) ++{ ++ stm32mp_ddr_wait_sw_done_ack(ctl); ++ stm32mp_ddr_enable_host_interface(ctl); ++ stm32mp_ddr_enable_axi_port(ctl); ++} ++ ++void stm32mp_ddr_wait_refresh_update_done_ack(struct stm32mp_ddrctl *ctl) ++{ ++ uint64_t timeout; ++ uint32_t rfshctl3; ++ uint32_t refresh_update_level = DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL; ++ ++ /* Toggle rfshctl3.refresh_update_level */ ++ rfshctl3 = mmio_read_32((uintptr_t)&ctl->rfshctl3); ++ if ((rfshctl3 & refresh_update_level) == refresh_update_level) { ++ mmio_setbits_32((uintptr_t)&ctl->rfshctl3, refresh_update_level); ++ } else { ++ mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, refresh_update_level); ++ refresh_update_level = 0U; ++ } ++ ++ VERBOSE("[0x%lx] rfshctl3 = 0x%x\n", ++ (uintptr_t)&ctl->rfshctl3, mmio_read_32((uintptr_t)&ctl->rfshctl3)); ++ ++ timeout = timeout_init_us(TIMEOUT_US_1S); ++ do { ++ rfshctl3 = mmio_read_32((uintptr_t)&ctl->rfshctl3); ++ VERBOSE("[0x%lx] rfshctl3 = 0x%x ", (uintptr_t)&ctl->rfshctl3, rfshctl3); ++ if (timeout_elapsed(timeout)) { ++ panic(); ++ } ++ } while ((rfshctl3 & DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL) != refresh_update_level); ++ ++ VERBOSE("[0x%lx] rfshctl3 = 0x%x\n", (uintptr_t)&ctl->rfshctl3, rfshctl3); ++} ++ ++int stm32mp_board_ddr_power_init(enum ddr_type ddr_type) ++{ ++ if (dt_pmic_status() > 0) { ++ return pmic_ddr_power_init(ddr_type); ++ } ++ ++ return 0; ++} +diff --git a/drivers/st/ddr/stm32mp_ddr_test.c b/drivers/st/ddr/stm32mp_ddr_test.c +new file mode 100644 +index 000000000..45920b7f8 +--- /dev/null ++++ b/drivers/st/ddr/stm32mp_ddr_test.c +@@ -0,0 +1,148 @@ ++/* ++ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++#include ++ ++#define DDR_PATTERN 0xAAAAAAAAU ++#define DDR_ANTIPATTERN 0x55555555U ++ ++/******************************************************************************* ++ * 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. ++ ******************************************************************************/ ++uint32_t stm32mp_ddr_test_rw_access(void) ++{ ++ uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE); ++ ++ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); ++ ++ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { ++ return (uint32_t)STM32MP_DDR_BASE; ++ } ++ ++ mmio_write_32(STM32MP_DDR_BASE, saved_value); ++ ++ 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. ++ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ ++ * File: memtest.c - This source code belongs to Public Domain. ++ * Returns 0 if success, and address value else. ++ ******************************************************************************/ ++uint32_t stm32mp_ddr_test_data_bus(void) ++{ ++ uint32_t pattern; ++ ++ for (pattern = 1U; pattern != 0U; pattern <<= 1) { ++ mmio_write_32(STM32MP_DDR_BASE, pattern); ++ ++ if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { ++ return (uint32_t)STM32MP_DDR_BASE; ++ } ++ } ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * This function tests the DDR address bus wiring. ++ * This is inspired from the Data Bus Test algorithm written by Michael Barr ++ * in "Programming Embedded Systems in C and C++" book. ++ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ ++ * File: memtest.c - This source code belongs to Public Domain. ++ * size: size in bytes of the DDR memory device. ++ * Returns 0 if success, and address value else. ++ ******************************************************************************/ ++uint32_t stm32mp_ddr_test_addr_bus(uint64_t size) ++{ ++ uint64_t addressmask = size - 1U; ++ uint64_t offset; ++ uint64_t testoffset = 0; ++ ++ /* 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(STM32MP_DDR_BASE + (uint32_t)offset, ++ DDR_PATTERN); ++ } ++ ++ /* Check for address bits stuck high. */ ++ 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(STM32MP_DDR_BASE + (uint32_t)offset) != ++ DDR_PATTERN) { ++ return (uint32_t)(STM32MP_DDR_BASE + offset); ++ } ++ } ++ ++ 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(STM32MP_DDR_BASE + (uint32_t)testoffset, ++ DDR_ANTIPATTERN); ++ ++ 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(STM32MP_DDR_BASE + ++ (uint32_t)offset) != DDR_PATTERN) && ++ (offset != testoffset)) { ++ return (uint32_t)(STM32MP_DDR_BASE + offset); ++ } ++ } ++ ++ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, ++ DDR_PATTERN); ++ } ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * This function checks the DDR size. It has to be run with Data Cache off. ++ * This test is run before data have been put in DDR, and is only done for ++ * cold boot. The DDR data can then be overwritten, and it is not useful to ++ * restore its content. ++ * Returns DDR computed size. ++ ******************************************************************************/ ++uint32_t stm32mp_ddr_check_size(void) ++{ ++ uint32_t offset = sizeof(uint32_t); ++ ++ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); ++ ++ while (offset < STM32MP_DDR_MAX_SIZE) { ++ mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); ++ dsb(); ++ ++ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { ++ break; ++ } ++ ++ offset <<= 1; ++ } ++ ++ INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U)); ++ ++ return offset; ++} +diff --git a/drivers/st/ddr/stm32mp_ram.c b/drivers/st/ddr/stm32mp_ram.c +new file mode 100644 +index 000000000..c20a65f6b +--- /dev/null ++++ b/drivers/st/ddr/stm32mp_ram.c +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++int stm32mp_ddr_dt_get_info(void *fdt, int node, struct stm32mp_ddr_info *info) ++{ ++ int ret; ++ ++ ret = fdt_read_uint32(fdt, node, "st,mem-speed", &info->speed); ++ if (ret < 0) { ++ VERBOSE("%s: no st,mem-speed\n", __func__); ++ return -EINVAL; ++ } ++ ret = fdt_read_uint32(fdt, node, "st,mem-size", &info->size); ++ if (ret < 0) { ++ VERBOSE("%s: no st,mem-size\n", __func__); ++ return -EINVAL; ++ } ++ info->name = fdt_getprop(fdt, node, "st,mem-name", NULL); ++ if (info->name == NULL) { ++ VERBOSE("%s: no st,mem-name\n", __func__); ++ return -EINVAL; ++ } ++ ++ INFO("RAM: %s\n", info->name); ++ ++ return 0; ++} ++ ++int stm32mp_ddr_dt_get_param(void *fdt, int node, const struct stm32mp_ddr_param *param, ++ uint32_t param_size, uintptr_t config) ++{ ++ int ret; ++ uint32_t idx; ++ ++ for (idx = 0U; idx < param_size; idx++) { ++ ret = fdt_read_uint32_array(fdt, node, param[idx].name, param[idx].size, ++ (void *)(config + param[idx].offset)); ++ ++ VERBOSE("%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); ++ if (ret != 0) { ++ ERROR("%s: Cannot read %s, error=%d\n", __func__, param[idx].name, ret); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} +diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c +index ff52a22d9..94f3721bd 100644 +--- a/drivers/st/etzpc/etzpc.c ++++ b/drivers/st/etzpc/etzpc.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -66,6 +66,10 @@ struct etzpc_instance { + /* Only 1 instance of the ETZPC is expected per platform */ + static struct etzpc_instance etzpc_dev; + ++struct dt_id_attr { ++ fdt32_t id_attr[STM32MP1_ETZPC_MAX_ID]; ++}; ++ + /* + * Implementation uses uint8_t to store each securable DECPROT configuration. + * When resuming from deep suspend, the DECPROT configurations are restored. +@@ -85,6 +89,56 @@ static bool valid_tzma_id(unsigned int id) + } + #endif + ++static int etzpc_dt_conf_decprot(void) ++{ ++ const struct dt_id_attr *conf_list; ++ void *fdt; ++ unsigned int i; ++ int len = 0; ++ int node; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ node = fdt_node_offset_by_compatible(fdt, -1, ETZPC_COMPAT); ++ if (node < 0) { ++ return -EIO; ++ } ++ ++ conf_list = (const struct dt_id_attr *)fdt_getprop(fdt, node, ++ "st,decprot", &len); ++ if (conf_list == NULL) { ++ INFO("No ETZPC configuration in DT, use default\n"); ++ return 0; ++ } ++ ++ for (i = 0U; i < (unsigned int)len / sizeof(uint32_t); i++) { ++ enum etzpc_decprot_attributes attr; ++ uint32_t value; ++ uint32_t id; ++ uint32_t mode; ++ ++ value = fdt32_to_cpu(conf_list->id_attr[i]); ++ ++ id = ((value >> ETZPC_ID_SHIFT) & ETZPC_ID_MASK); ++ assert(valid_decprot_id(id)); ++ ++ mode = (value >> ETZPC_MODE_SHIFT) & ETZPC_MODE_MASK; ++ attr = stm32mp_etzpc_binding2decprot(mode); ++ ++ stm32mp1_register_etzpc_decprot(id, attr); ++ ++ etzpc_configure_decprot(id, attr); ++ ++ if ((value & ETZPC_LOCK_MASK) != 0U) { ++ etzpc_lock_decprot(id); ++ } ++ } ++ ++ return 0; ++} ++ + /* + * etzpc_configure_decprot : Load a DECPROT configuration + * decprot_id : ID of the IP +@@ -225,20 +279,8 @@ uintptr_t etzpc_get_base_address(void) + int etzpc_init(void) + { + uint32_t hwcfg; +- int node; +- struct dt_node_info etzpc_info; +- +- node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT); +- if (node < 0) { +- return -EIO; +- } +- +- /* Check ETZPC is secure only */ +- if (etzpc_info.status != DT_SECURE) { +- return -EACCES; +- } + +- etzpc_dev.base = etzpc_info.base; ++ etzpc_dev.base = STM32MP1_ETZPC_BASE; + + hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR); + +@@ -254,5 +296,5 @@ int etzpc_init(void) + + VERBOSE("ETZPC version 0x%x", etzpc_dev.revision); + +- return 0; ++ return etzpc_dt_conf_decprot(); + } +diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c +index 453069bae..e9ab6dafd 100644 +--- a/drivers/st/fmc/stm32_fmc2_nand.c ++++ b/drivers/st/fmc/stm32_fmc2_nand.c +@@ -14,6 +14,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -162,7 +163,7 @@ static uintptr_t fmc2_base(void) + 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 hclk = 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; +@@ -909,7 +910,7 @@ int stm32_fmc2_init(void) + } + + /* Enable Clock */ +- stm32mp_clk_enable(stm32_fmc2.clock_id); ++ clk_enable(stm32_fmc2.clock_id); + + /* Reset IP */ + ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); +diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c +index 7d63262d7..dbd11ccdd 100644 +--- a/drivers/st/gpio/stm32_gpio.c ++++ b/drivers/st/gpio/stm32_gpio.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,6 +14,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -25,6 +26,10 @@ + #define DT_GPIO_PIN_MASK GENMASK(11, 8) + #define DT_GPIO_MODE_MASK GENMASK(7, 0) + ++static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, ++ uint32_t speed, uint32_t pull, uint32_t od, ++ uint32_t alternate, uint8_t status); ++ + /******************************************************************************* + * This function gets GPIO bank node in DT. + * Returns node offset if status is okay in DT, else return 0 +@@ -99,6 +104,8 @@ static int dt_set_gpio_config(void *fdt, int node, uint8_t status) + uint32_t pin; + uint32_t mode; + uint32_t alternate = GPIO_ALTERNATE_(0); ++ uint32_t type; ++ uint32_t od = 0U; + int bank_node; + int clk; + +@@ -128,7 +135,23 @@ static int dt_set_gpio_config(void *fdt, int node, uint8_t status) + } + + if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { +- mode |= GPIO_OPEN_DRAIN; ++ type = GPIO_TYPE_OPEN_DRAIN; ++ } else { ++ type = GPIO_TYPE_PUSH_PULL; ++ } ++ ++ if (fdt_getprop(fdt, node, "output-high", NULL) != NULL) { ++ if (mode == GPIO_MODE_INPUT) { ++ mode = GPIO_MODE_OUTPUT; ++ od = 1U; ++ } ++ } ++ ++ if (fdt_getprop(fdt, node, "output-low", NULL) != NULL) { ++ if (mode == GPIO_MODE_INPUT) { ++ mode = GPIO_MODE_OUTPUT; ++ od = 0U; ++ } + } + + bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); +@@ -145,7 +168,7 @@ static int dt_set_gpio_config(void *fdt, int node, uint8_t status) + /* Platform knows the clock: assert it is okay */ + assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank)); + +- set_gpio(bank, pin, mode, speed, pull, alternate, status); ++ set_gpio(bank, pin, mode, type, speed, pull, od, alternate, status); + } + + return 0; +@@ -159,7 +182,7 @@ static int dt_set_gpio_config(void *fdt, int node, uint8_t status) + int dt_set_pinctrl_config(int node) + { + const fdt32_t *cuint; +- int lenp = 0; ++ int lenp; + uint32_t i; + uint8_t status; + void *fdt; +@@ -200,51 +223,53 @@ int dt_set_pinctrl_config(int node) + 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 set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, ++ uint32_t speed, uint32_t pull, uint32_t od, ++ uint32_t alternate, uint8_t status) + { + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + +- stm32mp_clk_enable(clock); ++ clk_enable(clock); + +- mmio_clrbits_32(base + GPIO_MODE_OFFSET, +- ((uint32_t)GPIO_MODE_MASK << (pin << 1))); +- mmio_setbits_32(base + GPIO_MODE_OFFSET, +- (mode & ~GPIO_OPEN_DRAIN) << (pin << 1)); ++ mmio_clrsetbits_32(base + GPIO_MODE_OFFSET, ++ (uint32_t)GPIO_MODE_MASK << (pin << 1), ++ mode << (pin << 1)); + +- if ((mode & GPIO_OPEN_DRAIN) != 0U) { +- mmio_setbits_32(base + GPIO_TYPE_OFFSET, BIT(pin)); +- } else { +- mmio_clrbits_32(base + GPIO_TYPE_OFFSET, BIT(pin)); +- } ++ mmio_clrsetbits_32(base + GPIO_TYPE_OFFSET, ++ (uint32_t)GPIO_TYPE_MASK << pin, ++ type << pin); + +- mmio_clrbits_32(base + GPIO_SPEED_OFFSET, +- ((uint32_t)GPIO_SPEED_MASK << (pin << 1))); +- mmio_setbits_32(base + GPIO_SPEED_OFFSET, speed << (pin << 1)); ++ mmio_clrsetbits_32(base + GPIO_SPEED_OFFSET, ++ (uint32_t)GPIO_SPEED_MASK << (pin << 1), ++ speed << (pin << 1)); + +- mmio_clrbits_32(base + GPIO_PUPD_OFFSET, +- ((uint32_t)GPIO_PULL_MASK << (pin << 1))); +- mmio_setbits_32(base + GPIO_PUPD_OFFSET, pull << (pin << 1)); ++ mmio_clrsetbits_32(base + GPIO_PUPD_OFFSET, ++ (uint32_t)GPIO_PULL_MASK << (pin << 1), ++ pull << (pin << 1)); + + if (pin < GPIO_ALT_LOWER_LIMIT) { +- mmio_clrbits_32(base + GPIO_AFRL_OFFSET, +- ((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2))); +- mmio_setbits_32(base + GPIO_AFRL_OFFSET, +- alternate << (pin << 2)); ++ mmio_clrsetbits_32(base + GPIO_AFRL_OFFSET, ++ (uint32_t)GPIO_ALTERNATE_MASK << (pin << 2), ++ alternate << (pin << 2)); + } else { +- mmio_clrbits_32(base + GPIO_AFRH_OFFSET, +- ((uint32_t)GPIO_ALTERNATE_MASK << +- ((pin - GPIO_ALT_LOWER_LIMIT) << 2))); +- mmio_setbits_32(base + GPIO_AFRH_OFFSET, +- alternate << ((pin - GPIO_ALT_LOWER_LIMIT) << +- 2)); ++ size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; ++ ++ mmio_clrsetbits_32(base + GPIO_AFRH_OFFSET, ++ (uint32_t)GPIO_ALTERNATE_MASK << shift, ++ alternate << shift); + } + ++ mmio_clrsetbits_32(base + GPIO_OD_OFFSET, ++ (uint32_t)GPIO_OD_MASK << pin, ++ od << pin); ++ + VERBOSE("GPIO %u mode set to 0x%x\n", bank, + mmio_read_32(base + GPIO_MODE_OFFSET)); ++ VERBOSE("GPIO %u type set to 0x%x\n", bank, ++ mmio_read_32(base + GPIO_TYPE_OFFSET)); + VERBOSE("GPIO %u speed set to 0x%x\n", bank, + mmio_read_32(base + GPIO_SPEED_OFFSET)); + VERBOSE("GPIO %u mode pull to 0x%x\n", bank, +@@ -253,16 +278,22 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, + mmio_read_32(base + GPIO_AFRL_OFFSET)); + VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, + mmio_read_32(base + GPIO_AFRH_OFFSET)); ++ VERBOSE("GPIO %u output data set to 0x%x\n", bank, ++ mmio_read_32(base + GPIO_OD_OFFSET)); + +- stm32mp_clk_disable(clock); ++ clk_disable(clock); + + if (status == DT_SECURE) { + stm32mp_register_secure_gpio(bank, pin); ++#if !IMAGE_BL2 + set_gpio_secure_cfg(bank, pin, true); ++#endif + + } else { + stm32mp_register_non_secure_gpio(bank, pin); ++#if !IMAGE_BL2 + set_gpio_secure_cfg(bank, pin, false); ++#endif + } + } + +@@ -273,7 +304,7 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) + + assert(pin <= GPIO_PIN_MAX); + +- stm32mp_clk_enable(clock); ++ clk_enable(clock); + + if (secure) { + mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); +@@ -281,5 +312,12 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) + mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } + +- stm32mp_clk_disable(clock); ++ clk_disable(clock); ++} ++ ++void set_gpio_reset_cfg(uint32_t bank, uint32_t pin) ++{ ++ set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_TYPE_PUSH_PULL, ++ GPIO_SPEED_LOW, GPIO_NO_PULL, 0U, GPIO_ALTERNATE_(0), DT_DISABLED); ++ set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank)); + } +diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c +index ed880522b..068a99810 100644 +--- a/drivers/st/i2c/stm32_i2c.c ++++ b/drivers/st/i2c/stm32_i2c.c +@@ -1,10 +1,11 @@ + /* +- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * +- * SPDX-License-Identifier: BSD-3-Clause ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + + #include ++#include + #include + #include + +@@ -13,6 +14,8 @@ + #include + + #include ++#include ++#include + #include + #include + #include +@@ -38,8 +41,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) ++ * @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) ++ * @vddat_max: Max data valid time (ns) ++ * @sudat_min: Min data setup time (ns) ++ * @l_min: Min low period of the SCL clock (ns) ++ * @h_min: Min high period of the SCL clock (ns) ++ */ ++struct i2c_spec_s { ++ uint32_t rate; ++ uint32_t fall_max; ++ uint32_t rise_max; ++ uint32_t hddat_min; ++ uint32_t vddat_max; ++ uint32_t sudat_min; ++ uint32_t l_min; ++ uint32_t h_min; ++}; ++ ++/* ++ * struct i2c_timing_s - Private I2C output parameters. ++ * @scldel: Data setup time ++ * @sdadel: Data hold time ++ * @sclh: SCL high period (master mode) ++ * @sclh: SCL low period (master mode) ++ * @is_saved: True if relating to a configuration candidate ++ */ ++struct i2c_timing_s { ++ uint8_t scldel; ++ uint8_t sdadel; ++ uint8_t sclh; ++ uint8_t scll; ++ bool is_saved; ++}; ++ ++/* ++ * 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. ++ * ++ * [1] https://www.i2c-bus.org/specification/ ++ */ ++static const struct i2c_spec_s i2c_specs[] = { ++ /* Standard - 100KHz */ ++ { ++ .rate = STANDARD_RATE, ++ .fall_max = 300, ++ .rise_max = 1000, ++ .hddat_min = 0, ++ .vddat_max = 3450, ++ .sudat_min = 250, ++ .l_min = 4700, ++ .h_min = 4000, ++ }, ++ /* Fast - 400KHz */ ++ { ++ .rate = FAST_RATE, ++ .fall_max = 300, ++ .rise_max = 300, ++ .hddat_min = 0, ++ .vddat_max = 900, ++ .sudat_min = 100, ++ .l_min = 1300, ++ .h_min = 600, ++ }, ++ /* FastPlus - 1MHz */ ++ { ++ .rate = FAST_PLUS_RATE, ++ .fall_max = 100, ++ .rise_max = 120, ++ .hddat_min = 0, ++ .vddat_max = 450, ++ .sudat_min = 50, ++ .l_min = 500, ++ .h_min = 260, ++ }, ++}; ++ + + static void notif_i2c_timeout(struct i2c_handle_s *hi2c) + { +@@ -48,6 +130,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) ++{ ++ size_t i; ++ ++ for (i = 0U; 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 ++ * @param clock_src: I2C clock source frequency (Hz) ++ * @param timing: Pointer to the final computed timing result ++ * @retval 0 if OK, negative value else ++ */ ++static int i2c_compute_timing(struct stm32_i2c_init_s *init, ++ uint32_t clock_src, uint32_t *timing) ++{ ++ 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; ++ uint32_t p_prev = I2C_TIMINGR_PRESC_MAX; ++ uint32_t af_delay_min; ++ uint32_t af_delay_max; ++ uint32_t dnf_delay; ++ uint32_t tsync; ++ uint32_t clk_min; ++ uint32_t clk_max; ++ int clk_error_prev; ++ uint16_t p; ++ uint16_t l; ++ uint16_t a; ++ uint16_t h; ++ int sdadel_min; ++ int sdadel_max; ++ uint32_t sdadel_min_u; ++ uint32_t sdadel_max_u; ++ uint32_t scldel_min; ++ int s = -1; ++ struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX]; ++ ++ specs = get_specs(init->bus_rate); ++ if (specs == NULL) { ++ ERROR("I2C speed out of bound {%d}\n", init->bus_rate); ++ return -EINVAL; ++ } ++ ++ speed_freq = specs->rate; ++ i2cbus = udiv_round_nearest(I2C_NSEC_PER_SEC, speed_freq); ++ clk_error_prev = INT_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, specs->rise_max, ++ init->fall_time, specs->fall_max); ++ return -EINVAL; ++ } ++ ++ if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) { ++ ERROR("DNF out of bound %d/%d\n", ++ init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX); ++ return -EINVAL; ++ } ++ ++ /* Analog and Digital Filters */ ++ af_delay_min = (init->analog_filter ? ++ STM32_I2C_ANALOG_FILTER_DELAY_MIN : 0); ++ af_delay_max = (init->analog_filter ? ++ STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0); ++ dnf_delay = init->digital_filter_coef * i2cclk; ++ ++ sdadel_min = specs->hddat_min + init->fall_time - ++ af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); ++ ++ sdadel_max = specs->vddat_max - init->rise_time - ++ af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); ++ ++ scldel_min = init->rise_time + specs->sudat_min; ++ ++ if (sdadel_min < 0) { ++ sdadel_min_u = 0; ++ } else { ++ sdadel_min_u = (uint32_t)sdadel_min; ++ } ++ ++ if (sdadel_max < 0) { ++ sdadel_max_u = 0; ++ } else { ++ sdadel_max_u = (uint32_t)sdadel_max; ++ } ++ ++ VERBOSE("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u\n", ++ sdadel_min_u, sdadel_max_u, scldel_min); ++ ++ zeromem(&solutions, sizeof(solutions)); ++ ++ /* Compute possible values for PRESC, SCLDEL and SDADEL */ ++ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { ++ for (l = 0; l < I2C_TIMINGR_SCLDEL_MAX; l++) { ++ uint32_t scldel = (l + 1) * (p + 1) * i2cclk; ++ ++ if (scldel < scldel_min) { ++ continue; ++ } ++ ++ for (a = 0; a < I2C_TIMINGR_SDADEL_MAX; a++) { ++ uint32_t sdadel = (a * (p + 1) + 1) * i2cclk; ++ ++ if ((sdadel >= sdadel_min_u) && ++ (sdadel <= sdadel_max_u) && ++ (p != p_prev)) { ++ solutions[p].scldel = l; ++ solutions[p].sdadel = a; ++ solutions[p].is_saved = true; ++ p_prev = p; ++ break; ++ } ++ } ++ ++ if (p_prev == p) { ++ break; ++ } ++ } ++ } ++ ++ if (p_prev == I2C_TIMINGR_PRESC_MAX) { ++ ERROR(" I2C no Prescaler solution\n"); ++ return -EPERM; ++ } ++ ++ tsync = af_delay_min + dnf_delay + (2 * i2cclk); ++ 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 ++ * and High Period. Provided: ++ * - SCL Low Period has to be higher than Low Period of the SCL Clock ++ * defined by I2C Specification. I2C Clock has to be lower than ++ * (SCL Low Period - Analog/Digital filters) / 4. ++ * - SCL High Period has to be lower than High Period of the SCL Clock ++ * defined by I2C Specification. ++ * - I2C Clock has to be lower than SCL High Period. ++ */ ++ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { ++ uint32_t prescaler = (p + 1) * i2cclk; ++ ++ if (!solutions[p].is_saved) { ++ continue; ++ } ++ ++ for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { ++ uint32_t tscl_l = ((l + 1) * prescaler) + tsync; ++ ++ if ((tscl_l < specs->l_min) || ++ (i2cclk >= ++ ((tscl_l - af_delay_min - dnf_delay) / 4))) { ++ continue; ++ } ++ ++ for (h = 0; h < I2C_TIMINGR_SCLH_MAX; h++) { ++ uint32_t tscl_h = ((h + 1) * prescaler) + tsync; ++ uint32_t tscl = tscl_l + tscl_h + ++ init->rise_time + ++ init->fall_time; ++ ++ if ((tscl >= clk_min) && (tscl <= clk_max) && ++ (tscl_h >= specs->h_min) && ++ (i2cclk < tscl_h)) { ++ int clk_error = tscl - i2cbus; ++ ++ if (clk_error < 0) { ++ clk_error = -clk_error; ++ } ++ ++ if (clk_error < clk_error_prev) { ++ clk_error_prev = clk_error; ++ solutions[p].scll = l; ++ solutions[p].sclh = h; ++ s = p; ++ } ++ } ++ } ++ } ++ } ++ ++ if (s < 0) { ++ ERROR(" I2C no solution at all\n"); ++ return -EPERM; ++ } ++ ++ /* Finalize timing settings */ ++ *timing = I2C_SET_TIMINGR_PRESC(s) | ++ I2C_SET_TIMINGR_SCLDEL(solutions[s].scldel) | ++ I2C_SET_TIMINGR_SDADEL(solutions[s].sdadel) | ++ I2C_SET_TIMINGR_SCLH(solutions[s].sclh) | ++ I2C_SET_TIMINGR_SCLL(solutions[s].scll); ++ ++ VERBOSE("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%i/%i\n", ++ s, solutions[s].scldel, solutions[s].sdadel); ++ VERBOSE("I2C TIMINGR (SCLH/SCLL): %i/%i\n", ++ solutions[s].sclh, solutions[s].scll); ++ VERBOSE("I2C TIMINGR: 0x%x\n", *timing); ++ ++ 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 ++ * the configuration information for the specified I2C. ++ * @param init: Ref to the initialization configuration structure ++ * @param timing: Pointer to the final computed timing result ++ * @retval 0 if OK, negative value else ++ */ ++static int i2c_setup_timing(struct i2c_handle_s *hi2c, ++ struct stm32_i2c_init_s *init, ++ uint32_t *timing) ++{ ++ int rc = 0; ++ uint32_t clock_src; ++ ++ clock_src = (uint32_t)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->bus_rate > STANDARD_RATE) { ++ init->bus_rate = get_lower_rate(init->bus_rate); ++ WARN("Downgrade I2C speed to %uHz)\n", ++ init->bus_rate); ++ } else { ++ break; ++ } ++ } ++ } while (rc != 0); ++ ++ if (rc != 0) { ++ ERROR("Impossible to compute I2C timings\n"); ++ return rc; ++ } ++ ++ 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); ++ ++ hi2c->saved_timing = *timing; ++ hi2c->saved_frequency = clock_src; ++ ++ return 0; ++} ++ + /* + * @brief Configure I2C Analog noise filter. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains +@@ -96,41 +470,24 @@ static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, + int stm32_i2c_get_setup_from_fdt(void *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(fdt, node, ++ "i2c-scl-rising-time-ns", ++ STM32_I2C_RISE_TIME_DEFAULT); ++ ++ init->fall_time = fdt_read_uint32_default(fdt, node, ++ "i2c-scl-falling-time-ns", ++ STM32_I2C_FALL_TIME_DEFAULT); ++ ++ read_val = fdt_read_uint32_default(fdt, 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 +503,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; +@@ -158,7 +515,12 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, + + hi2c->i2c_state = I2C_STATE_BUSY; + +- stm32mp_clk_enable(hi2c->clock); ++ rc = i2c_setup_timing(hi2c, init_data, &timing); ++ if (rc != 0) { ++ return rc; ++ } ++ ++ clk_enable(hi2c->clock); + + /* Disable the selected I2C peripheral */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); +@@ -220,11 +582,11 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, + I2C_ANALOGFILTER_DISABLE); + if (rc != 0) { + ERROR("Cannot initialize I2C analog filter (%d)\n", rc); +- stm32mp_clk_disable(hi2c->clock); ++ clk_disable(hi2c->clock); + return rc; + } + +- stm32mp_clk_disable(hi2c->clock); ++ clk_disable(hi2c->clock); + + return rc; + } +@@ -548,7 +910,7 @@ static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + return -EINVAL; + } + +- stm32mp_clk_enable(hi2c->clock); ++ clk_enable(hi2c->clock); + + hi2c->lock = 1; + +@@ -648,7 +1010,7 @@ static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + + bail: + hi2c->lock = 0; +- stm32mp_clk_disable(hi2c->clock); ++ clk_disable(hi2c->clock); + + return rc; + } +@@ -729,7 +1091,7 @@ static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + return -EINVAL; + } + +- stm32mp_clk_enable(hi2c->clock); ++ clk_enable(hi2c->clock); + + hi2c->lock = 1; + +@@ -817,7 +1179,7 @@ static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + + bail: + hi2c->lock = 0; +- stm32mp_clk_disable(hi2c->clock); ++ clk_disable(hi2c->clock); + + return rc; + } +@@ -882,7 +1244,7 @@ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, + return rc; + } + +- stm32mp_clk_enable(hi2c->clock); ++ clk_enable(hi2c->clock); + + hi2c->lock = 1; + hi2c->i2c_mode = I2C_MODE_NONE; +@@ -974,8 +1336,7 @@ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, + + bail: + hi2c->lock = 0; +- stm32mp_clk_disable(hi2c->clock); ++ clk_disable(hi2c->clock); + + return rc; + } +- +diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c +deleted file mode 100644 +index 9fa0c50fd..000000000 +--- a/drivers/st/io/io_stm32image.c ++++ /dev/null +@@ -1,379 +0,0 @@ +-/* +- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ +- +-#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); +- if (result != 0) { +- ERROR("STM32 image error (%i)\n", result); +- return -EINVAL; +- } +- +- 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; +- uintptr_t backend_handle; +- size_t bytes_read; +- boot_api_image_header_t *header = +- (boot_api_image_header_t *)first_lba_buffer; +- +- assert(entity != NULL); +- assert(length != NULL); +- +- /* Attempt to access the image */ +- result = io_open(backend_dev_handle, backend_image_spec, +- &backend_handle); +- +- 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); +- +- if (result != 0) { +- return result; +- } +- +- 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 = -EINVAL; +- uint8_t *local_buffer; +- boot_api_image_header_t *header = +- (boot_api_image_header_t *)first_lba_buffer; +- size_t hdr_sz = sizeof(boot_api_image_header_t); +- +- assert(entity != NULL); +- 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 + hdr_sz, +- MAX_LBA_SIZE - hdr_sz); +- local_buffer += MAX_LBA_SIZE - hdr_sz; +- offset = MAX_LBA_SIZE; +- +- /* New image length to be read */ +- local_length = round_up(length - ((MAX_LBA_SIZE) - hdr_sz), +- 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 - hdr_sz; +- +- if (result != 0) { +- ERROR("%s: io_read (%i)\n", __func__, result); +- *length_read = 0; +- header->magic = 0; +- continue; +- } +- +- result = stm32mp_check_header(header, buffer); +- if (result != 0) { +- ERROR("Header check failed\n"); +- *length_read = 0; +- header->magic = 0; +- } +- +- result = stm32mp_auth_image(header, buffer); +- if (result != 0) { +- ERROR("Authentication Failed (%i)\n", result); +- return result; +- } +- +- inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz), +- CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz); +- +- 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; +-} +diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c +index c052b4dfb..a9f86d722 100644 +--- a/drivers/st/iwdg/stm32_iwdg.c ++++ b/drivers/st/iwdg/stm32_iwdg.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -22,11 +23,30 @@ + #include + #include + ++#define IWDG_TIMEOUT_MS U(100) ++ + /* 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 */ ++#define IWDG_KR_ACCESS_KEY 0x5555 + #define IWDG_KR_RELOAD_KEY 0xAAAA ++#define IWDG_KR_START_KEY 0xCCCC ++ ++#define IWDG_PR_DIV_4 0x00 ++#define IWDG_PR_DIV_256 0x06 ++ ++#define IWDG_RLR_MAX_VAL 0xFFF ++ ++#define IWDG_SR_EWU BIT(3) ++ ++#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; +@@ -52,6 +72,122 @@ 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) ++{ ++ struct stm32_iwdg_instance *iwdg; ++ unsigned int instance; ++ ++ for (instance = 0; instance < IWDG_MAX_INSTANCE; instance++) { ++ if (stm32_iwdg[instance].num_irq == id) { ++ break; ++ } ++ } ++ ++ if (instance == IWDG_MAX_INSTANCE) { ++ panic(); ++ } ++ ++ iwdg = &stm32_iwdg[instance]; ++ ++#if DEBUG ++ INFO("CPU %x IT Watchdog %u\n", plat_my_core_pos(), instance + 1U); ++ ++ stm32mp_dump_core_registers(true); ++#endif ++ stm32_iwdg_refresh(); ++ ++ clk_enable(iwdg->clock); ++ ++ mmio_clrsetbits_32(iwdg->base + IWDG_EWCR_OFFSET, ++ IWDG_EWCR_EWIE, IWDG_EWCR_EWIC); ++ ++ clk_disable(iwdg->clock); ++ ++ /* Ack interrupt as we do not return from next call */ ++ gicv2_end_of_interrupt(id); ++ ++#if DEBUG ++ if (!stm32mp_is_single_core()) { ++ unsigned int sec_cpu = (plat_my_core_pos() == STM32MP_PRIMARY_CPU) ? ++ STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU; ++ ++ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, sec_cpu); ++ } ++#endif ++ ++ for ( ; ; ) { ++ ; ++ } ++} ++ ++static int stm32_iwdg_get_secure_timeout(int node) ++{ ++ void *fdt; ++ const fdt32_t *cuint; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -1; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "secure-timeout-sec", NULL); ++ if (cuint == NULL) { ++ return -1; ++ } ++ ++ return (int)fdt32_to_cpu(*cuint); ++} ++ ++static int stm32_iwdg_conf_etimeout(int node, struct stm32_iwdg_instance *iwdg) ++{ ++ int id_lsi; ++ int dt_secure_timeout = stm32_iwdg_get_secure_timeout(node); ++ uint32_t reload, status; ++ unsigned int timeout = IWDG_TIMEOUT_MS; ++ unsigned long long reload_ll; ++ ++ if (dt_secure_timeout < 0) { ++ return 0; ++ } ++ ++ if (dt_secure_timeout == 0) { ++ return -EINVAL; ++ } ++ ++ id_lsi = fdt_get_clock_id_by_name(node, "lsi"); ++ if (id_lsi < 0) { ++ return -EINVAL; ++ } ++ ++ /* Prescaler fix to 256 */ ++ reload_ll = (unsigned long long)dt_secure_timeout * clk_get_rate(id_lsi); ++ reload = ((uint32_t)(reload_ll >> 8) - 1U) & IWDG_EWCR_EWIT_MASK; ++ ++ clk_enable(iwdg->clock); ++ ++ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_START_KEY); ++ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); ++ mmio_write_32(iwdg->base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); ++ mmio_write_32(iwdg->base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIE | reload); ++ ++ do { ++ status = mmio_read_32(iwdg->base + IWDG_SR_OFFSET) & ++ IWDG_SR_EWU; ++ timeout--; ++ mdelay(1); ++ } while ((status != 0U) && (timeout != 0U)); ++ ++ iwdg->num_irq = stm32mp_gic_enable_spi(node, NULL); ++ if (iwdg->num_irq < 0) { ++ panic(); ++ } ++ ++ clk_disable(iwdg->clock); ++ ++ return (timeout == 0U) ? -ETIMEDOUT : 0; ++} ++#endif ++ + void stm32_iwdg_refresh(void) + { + uint8_t i; +@@ -61,12 +197,12 @@ void stm32_iwdg_refresh(void) + + /* 0x00000000 is not a valid address for IWDG peripherals */ + if (iwdg->base != 0U) { +- stm32mp_clk_enable(iwdg->clock); ++ clk_enable(iwdg->clock); + + mmio_write_32(iwdg->base + IWDG_KR_OFFSET, + IWDG_KR_RELOAD_KEY); + +- stm32mp_clk_disable(iwdg->clock); ++ clk_disable(iwdg->clock); + } + } + } +@@ -74,6 +210,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; +@@ -143,6 +280,14 @@ int stm32_iwdg_init(void) + stm32mp_register_secure_periph_iomem(iwdg->base); + } + ++#if defined(IMAGE_BL32) ++ res = stm32_iwdg_conf_etimeout(node, iwdg); ++ if (res != 0) { ++ ERROR("IWDG%x early timeout config failed (%d)\n", ++ idx + 1, res); ++ return res; ++ } ++#endif + #if defined(IMAGE_BL2) + if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) { + return -1; +diff --git a/drivers/st/mce/stm32_mce.c b/drivers/st/mce/stm32_mce.c +new file mode 100644 +index 000000000..114bec6bc +--- /dev/null ++++ b/drivers/st/mce/stm32_mce.c +@@ -0,0 +1,411 @@ ++/* ++ * Copyright (c) 2020-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* MCE registers (base relative) */ ++#define MCE_CR U(0x0000) /* MCE configuration register */ ++#define MCE_SR U(0x0004) /* MCE status register */ ++#define MCE_IASR U(0x0008) /* MCE illegal access status register */ ++#define MCE_IACR U(0x000C) /* MCE illegal access clear register */ ++#define MCE_IAIER U(0x0010) /* MCE illegal access interrupt enable reg */ ++#define MCE_PRIVCFGR U(0x001C) /* MCE privileged configuration register */ ++#define MCE_REGCR U(0x0040) /* MCE region configuration register */ ++#define MCE_SADDR U(0x0044) /* MCE start address for region register */ ++#define MCE_EADDR U(0x0048) /* MCE end address for region register */ ++#define MCE_MKEYR U(0x0200) /* MCE master key register offset */ ++#define MCE_HWCFGR3 U(0x03E8) /* MCE hardware configuration register 3 */ ++#define MCE_HWCFGR2 U(0x03EC) /* MCE hardware configuration register 2 */ ++#define MCE_HWCFGR1 U(0x03F0) /* MCE hardware configuration register 1 */ ++#define MCE_VERR U(0x03F4) /* MCE version register */ ++#define MCE_IPIDR U(0x03F8) /* MCE identification register */ ++#define MCE_SIDR U(0x03FC) /* MCE size ID register */ ++ ++/* MCE configuration register */ ++#define MCE_CR_GLOCK BIT(0) ++#define MCE_CR_MKLOCK BIT(1) ++ ++/* MCE status register */ ++#define MCE_SR_MKVALID BIT(0) ++#define MCE_SR_ENCDIS BIT(4) ++ ++/* MCE privileged configuration register */ ++#define MCE_PRIVCFGR_PRIV BIT(0) ++ ++/* MCE region configuration register */ ++#define MCE_REGCR_BREN BIT(0) ++#define MCE_REGCR_ENC BIT(15) ++ ++/* MCE start address for region register */ ++#define MCE_SADDR_BADDSTART_MASK GENMASK(31, 16) ++ ++/* MCE end address for region register */ ++#define MCE_EADDR_BADDEND_MASK GENMASK(31, 16) ++ ++/* MCE version register */ ++#define MCE_VERR_MINREV_MASK GENMASK(3, 0) ++#define MCE_VERR_MINREV_SHIFT 0 ++#define MCE_VERR_MAJREV_MASK GENMASK(7, 4) ++#define MCE_VERR_MAJREV_SHIFT 4 ++ ++/* IP configuration */ ++#define MCE_MAJREV 1U ++#define MCE_MINREV 0U ++#define MCE_IP_ID 0x00170081U ++#define MCE_SIZE_ID 0xA3C5DD01U ++#define MCE_ADDR_GRANULARITY 0x10000U ++ ++/* Other definitions */ ++#define MCE_TIMEOUT_1MS_IN_US 1000U ++#define DDR_BASE_EXTRA_MASK GENMASK_32(31, 30) ++#define MCE_REGION_PARAMS 3 ++ ++struct mce_version_s { ++ uint32_t major; ++ uint32_t minor; ++ uint32_t ip_id; ++ uint32_t size_id; ++}; ++ ++struct mce_dt_id_attr { ++ fdt32_t id_attr[MCE_IP_MAX_REGION_NB]; ++}; ++ ++struct stm32_mce_region_s { ++ uint32_t encrypt_mode; /* ++ * Specifies the region encryption mode. ++ * This parameter can be a value of ++ * @ref MCE_*_MODE (in driver header file). ++ */ ++ uint32_t start_address; /* Specifies the region start address */ ++ uint32_t end_address; /* Specifies the region end address */ ++}; ++ ++/* ++ * @brief Configure privileged access to the MCE registers. ++ * @param privilege: Only privileged (true) or all (false) access are granted. ++ * @retval None. ++ */ ++static void configure_privilege(bool privilege) ++{ ++ if (privilege) { ++ mmio_setbits_32(MCE_BASE + MCE_PRIVCFGR, MCE_PRIVCFGR_PRIV); ++ } else { ++ mmio_clrbits_32(MCE_BASE + MCE_PRIVCFGR, MCE_PRIVCFGR_PRIV); ++ } ++} ++ ++/* ++ * @brief Check consistency of region settings. ++ * @param config: Ref to the region configuration structure. ++ * @retval 0 if OK, negative value else. ++ */ ++static int check_region_settings(struct stm32_mce_region_s *config) ++{ ++ uint32_t end; ++ ++ if (config->encrypt_mode > MCE_ENCRYPTION_MODE_MAX) { ++ ERROR("MCE: encryption mode out of range error\n"); ++ return -EINVAL; ++ } ++ ++ if ((config->start_address < STM32MP_DDR_BASE) || ++ (config->end_address < STM32MP_DDR_BASE)) { ++ ERROR("MCE: start/end address lower than DDR base\n"); ++ return -EINVAL; ++ } ++ ++ end = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U; ++ if ((config->start_address > end) || (config->end_address > end)) { ++ ERROR("MCE: start/end address higher than physical end\n"); ++ return -EINVAL; ++ } ++ ++ if (config->start_address >= config->end_address) { ++ ERROR("MCE: start address higher than or equal to end one\n"); ++ return -EINVAL; ++ } ++ ++ if (((config->start_address % MCE_ADDR_GRANULARITY) != 0U) || ++ (((config->end_address + 1U) % MCE_ADDR_GRANULARITY) != 0U)) { ++ ERROR("MCE: start/end address granularity not respected\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Configure (and enable) the MCE region. ++ * @param index: Region index (first region is 0). ++ * @param config: Ref to the region configuration structure. ++ * @retval 0 if OK, negative value else. ++ */ ++static int stm32_mce_configure_region(uint32_t index, struct stm32_mce_region_s *config) ++{ ++ int ret; ++ ++ if ((index >= MCE_IP_MAX_REGION_NB) || (config == NULL)) { ++ return -EINVAL; ++ } ++ ++ ret = check_region_settings(config); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ mmio_clrbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_BREN); ++ ++ mmio_clrsetbits_32(MCE_BASE + MCE_SADDR, MCE_SADDR_BADDSTART_MASK, ++ config->start_address & MCE_SADDR_BADDSTART_MASK); ++ mmio_clrsetbits_32(MCE_BASE + MCE_EADDR, MCE_EADDR_BADDEND_MASK, ++ config->end_address & MCE_EADDR_BADDEND_MASK); ++ ++ if (config->encrypt_mode == MCE_ENCRYPT_MODE) { ++ mmio_setbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_BREN | MCE_REGCR_ENC); ++ ++ if (!stm32_mce_is_hw_encryption_functional()) { ++ ERROR("MCE: encryption feature error\n"); ++ return -EIO; ++ } ++ } else { ++ mmio_clrbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_ENC); ++ mmio_setbits_32(MCE_BASE + MCE_REGCR, MCE_REGCR_BREN); ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Initialize the MCE driver. ++ * @param None. ++ * @retval None. ++ */ ++void stm32_mce_init(void) ++{ ++ const struct mce_version_s exp_version = { ++ .major = MCE_MAJREV, ++ .minor = MCE_MINREV, ++ .ip_id = MCE_IP_ID, ++ .size_id = MCE_SIZE_ID ++ }; ++ struct mce_version_s version; ++ ++ clk_enable(MCE); ++ ++ version = (struct mce_version_s) { ++ .major = (mmio_read_32(MCE_BASE + MCE_VERR) & ++ MCE_VERR_MAJREV_MASK) >> MCE_VERR_MAJREV_SHIFT, ++ .minor = (mmio_read_32(MCE_BASE + MCE_VERR) & ++ MCE_VERR_MINREV_MASK) >> MCE_VERR_MINREV_SHIFT, ++ .ip_id = mmio_read_32(MCE_BASE + MCE_IPIDR), ++ .size_id = mmio_read_32(MCE_BASE + MCE_SIDR) ++ }; ++ ++ if ((version.major != exp_version.major) || ++ (version.minor != exp_version.minor) || ++ (version.ip_id != exp_version.ip_id) || ++ (version.size_id != exp_version.size_id)) { ++ ERROR("MCE: unexpected IP version { 0x%x, 0x%x, 0x%x, 0x%x }\n", ++ version.major, version.minor, version.ip_id, version.size_id); ++ panic(); ++ } ++ ++ configure_privilege(true); ++} ++ ++/* ++ * @brief Write the MCE master key. ++ * @param mkey: Pointer to the master key buffer. ++ * @retval 0 if OK, negative value else. ++ */ ++int stm32_mce_write_master_key(uint8_t *mkey) ++{ ++ uint64_t timeout_ref; ++ uint8_t i; ++ ++ if (mkey == NULL) { ++ return -EINVAL; ++ } ++ ++ if ((mmio_read_32(MCE_BASE + MCE_CR) & MCE_CR_MKLOCK) == MCE_CR_MKLOCK) { ++ return -EPERM; ++ } ++ ++ for (i = 0U; i < MCE_KEY_SIZE_IN_BYTES; i += sizeof(uint32_t)) { ++ uint32_t key_val = 0U; ++ ++ memcpy(&key_val, mkey + i, sizeof(uint32_t)); ++ ++ mmio_write_32(MCE_BASE + MCE_MKEYR + i, key_val); ++ } ++ ++ timeout_ref = timeout_init_us(MCE_TIMEOUT_1MS_IN_US); ++ ++ while ((mmio_read_32(MCE_BASE + MCE_SR) & MCE_SR_MKVALID) != MCE_SR_MKVALID) { ++ if (timeout_elapsed(timeout_ref)) { ++ return -EIO; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Lock the MCE master key. ++ * @param None. ++ * @retval None. ++ */ ++void stm32_mce_lock_master_key(void) ++{ ++ mmio_setbits_32(MCE_BASE + MCE_CR, MCE_CR_MKLOCK); ++} ++ ++/* ++ * @brief Get the MCE master key lock state. ++ * @param None. ++ * @retval True if locked, false else. ++ */ ++bool stm32_mce_is_master_key_locked(void) ++{ ++ return (mmio_read_32(MCE_BASE + MCE_CR) & MCE_CR_MKLOCK) == MCE_CR_MKLOCK; ++} ++ ++/* ++ * @brief Lock the MCE IP registers. ++ * @param None. ++ * @retval None. ++ */ ++void stm32_mce_lock_global(void) ++{ ++ mmio_setbits_32(MCE_BASE + MCE_CR, MCE_CR_GLOCK); ++} ++ ++/* ++ * @brief Get the MCE global lock state. ++ * @param None. ++ * @retval True if locked, false else. ++ */ ++bool stm32_mce_is_globally_locked(void) ++{ ++ return (mmio_read_32(MCE_BASE + MCE_CR) & MCE_CR_GLOCK) == MCE_CR_GLOCK; ++} ++ ++/* ++ * @brief Get the MCE encryption HW feature state. ++ * @param None. ++ * @retval True if functional, false else. ++ */ ++bool stm32_mce_is_hw_encryption_functional(void) ++{ ++ return (mmio_read_32(MCE_BASE + MCE_SR) & MCE_SR_ENCDIS) != MCE_SR_ENCDIS; ++} ++ ++/* ++ * @brief Get the encryption state of an address. ++ * @param index: Memory address. ++ * @param state: Ref to the encryption state. ++ * @retval 0 if OK, negative value else. ++ */ ++int stm32_mce_get_address_encryption_state(uint32_t address, uint32_t *state) ++{ ++ struct stm32_mce_region_s config; ++ ++ if ((address < STM32MP_DDR_BASE) || ++ (address > (STM32MP_DDR_BASE + dt_get_ddr_size() - 1U)) || ++ (state == NULL)) { ++ return -EINVAL; ++ } ++ ++ if ((mmio_read_32(MCE_BASE + MCE_REGCR) & MCE_REGCR_ENC) != MCE_REGCR_ENC) { ++ /* No encrypted region, all DDR area is in plain text */ ++ *state = MCE_BYPASS_MODE; ++ return 0; ++ } ++ ++ if (!stm32_mce_is_hw_encryption_functional()) { ++ ERROR("MCE: encryption feature error\n"); ++ return -EIO; ++ } ++ ++ /* ++ * When MCE_SADDR and MCE_EADDR are accessed in read, the 2 MSB bits ++ * return zeros. So DDR base address mask has to be ORed. ++ */ ++ config.start_address = mmio_read_32(MCE_BASE + MCE_SADDR) | ++ (STM32MP_DDR_BASE & DDR_BASE_EXTRA_MASK); ++ ++ config.end_address = mmio_read_32(MCE_BASE + MCE_EADDR) | ++ (STM32MP_DDR_BASE & DDR_BASE_EXTRA_MASK); ++ ++ if ((address >= config.start_address) && (address <= config.end_address)) { ++ *state = MCE_ENCRYPT_MODE; ++ } else { ++ *state = MCE_BYPASS_MODE; ++ } ++ ++ return 0; ++} ++ ++static int fconf_populate_mce(uintptr_t config) ++{ ++ int node, len; ++ unsigned int i; ++ const struct mce_dt_id_attr *conf_list; ++ const void *dtb = (const void *)config; ++ ++ /* Check the node offset point to "st,mem-encrypt" compatible property */ ++ const char *compatible_str = "st,mem-encrypt"; ++ ++ if (!stm32mp_is_closed_device() && !stm32mp_is_auth_supported()) { ++ return 0; ++ } ++ ++ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); ++ if (node < 0) { ++ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); ++ return node; ++ } ++ ++ conf_list = (const struct mce_dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len); ++ if (conf_list == NULL) { ++ WARN("FCONF: Read cell failed for %s\n", "memory-ranges"); ++ return -1; ++ } ++ ++ /* Consider only complete set of values */ ++ len -= len % MCE_REGION_PARAMS; ++ ++ /* Locate the memory cells and read all values */ ++ for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * MCE_REGION_PARAMS)); i++) { ++ uint32_t size; ++ struct stm32_mce_region_s region; ++ ++ region.start_address = fdt32_to_cpu(conf_list->id_attr[i * MCE_REGION_PARAMS]); ++ size = fdt32_to_cpu(conf_list->id_attr[i * MCE_REGION_PARAMS + 1U]); ++ region.end_address = region.start_address + size - 1U; ++ region.encrypt_mode = fdt32_to_cpu(conf_list->id_attr[i * MCE_REGION_PARAMS + 2U]); ++ ++ VERBOSE("FCONF: mce cell found with value = 0x%x 0x%x 0x%x\n", ++ region.start_address, size, region.encrypt_mode); ++ ++ if (stm32_mce_configure_region(i, ®ion) != 0) { ++ panic(); ++ } ++ } ++ ++ return 0; ++} ++ ++FCONF_REGISTER_POPULATOR(FW_CONFIG, mce_config, fconf_populate_mce); +diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c +index d3adeab13..66c7a2271 100644 +--- a/drivers/st/mmc/stm32_sdmmc2.c ++++ b/drivers/st/mmc/stm32_sdmmc2.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -50,6 +51,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 */ +@@ -117,7 +119,16 @@ + #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 ++ ++#ifndef DT_SDMMC2_COMPAT + #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" ++#endif + + static void stm32_sdmmc2_init(void); + static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd); +@@ -138,6 +149,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) + { +@@ -154,6 +167,25 @@ static void stm32_sdmmc2_init(void) + freq = MIN(sdmmc2_params.max_freq, freq); + } + ++ if (sdmmc2_params.vmmc_regu != NULL) { ++ 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 != NULL) { ++ 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 * 2U); + + mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | +@@ -163,7 +195,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) +@@ -221,6 +253,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; +@@ -258,6 +304,8 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) + break; + } + ++ next_cmd_is_acmd = (cmd->cmd_idx == MMC_CMD(55)); ++ + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + /* +@@ -265,8 +313,7 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) + * Skip CMD55 as the next command could be data related, and + * the register could have been set in prepare function. + */ +- if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && +- (cmd->cmd_idx != MMC_CMD(55))) { ++ if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && !next_cmd_is_acmd) { + mmio_write_32(base + SDMMC_DCTRLR, 0U); + } + +@@ -689,6 +736,8 @@ static int stm32_sdmmc2_dt_get_config(void) + sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); + } + ++ sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc"); ++ + return 0; + } + +@@ -709,12 +758,14 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) + + memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); + ++ sdmmc2_params.vmmc_regu = NULL; ++ + if (stm32_sdmmc2_dt_get_config() != 0) { + ERROR("%s: DT error\n", __func__); + return -ENOMEM; + } + +- stm32mp_clk_enable(sdmmc2_params.clock_id); ++ clk_enable(sdmmc2_params.clock_id); + + rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS); + if (rc != 0) { +@@ -727,7 +778,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.clk_rate = 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, +diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c +index be410a1f4..961cdcc56 100644 +--- a/drivers/st/pmic/stm32mp_pmic.c ++++ b/drivers/st/pmic/stm32mp_pmic.c +@@ -1,57 +1,72 @@ + /* +- * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2022, 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 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) +- +-#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 ++#include + + static struct i2c_handle_s i2c_handle; + static uint32_t pmic_i2c_addr; ++#if defined(IMAGE_BL32) ++static struct spinlock lock; ++#endif ++ ++static int register_pmic(void); + + static int dt_get_pmic_node(void *fdt) + { +- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); ++ static int node = -FDT_ERR_BADOFFSET; ++ ++ if (node == -FDT_ERR_BADOFFSET) { ++ node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); ++ } ++ ++ return node; + } + + int dt_pmic_status(void) + { ++ static int status = -FDT_ERR_BADVALUE; + int node; + void *fdt; + ++ if (status != -FDT_ERR_BADVALUE) { ++ return status; ++ } ++ + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = dt_get_pmic_node(fdt); + if (node <= 0) { +- return -FDT_ERR_NOTFOUND; ++ status = -FDT_ERR_NOTFOUND; ++ ++ return status; + } + +- return fdt_get_status(node); ++#if defined(IMAGE_BL2) ++ status = DT_SECURE; ++#else ++ status = (int)fdt_get_status(node); ++#endif ++ ++ return status; + } + + static bool dt_pmic_is_secure(void) +@@ -65,125 +80,53 @@ static bool dt_pmic_is_secure(void) + + /* + * 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. ++ * 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) + { +- 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 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; +- } +- +- 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); +-} +- +-int dt_pmic_configure_boot_on_regulators(void) +-{ +- int pmic_node, regulators_node, regulator_node; ++ static int i2c_node = -FDT_ERR_NOTFOUND; + 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"); +- if (regulators_node < 0) { +- return -ENOENT; +- } +- +- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { ++ if (i2c_node == -FDT_ERR_NOTFOUND) { ++ int pmic_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; ++ pmic_node = dt_get_pmic_node(fdt); ++ if (pmic_node < 0) { ++ return 1; + } + +- if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", +- NULL) != NULL) { +- +- status = stpmic1_regulator_pull_down_set(node_name); +- if (status != 0) { +- return status; +- } +- } +- +- if (fdt_getprop(fdt, regulator_node, "st,mask-reset", +- NULL) != NULL) { +- +- status = stpmic1_regulator_mask_reset_set(node_name); +- if (status != 0) { +- return status; +- } +- } +- +- 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); +- +- status = stpmic1_regulator_voltage_set(node_name, voltage); +- if (status != 0) { +- return status; ++ pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; ++ if (pmic_i2c_addr > UINT16_MAX) { ++ return -FDT_ERR_BADVALUE; + } + +- if (stpmic1_is_regulator_enabled(node_name) == 0U) { +- status = stpmic1_regulator_enable(node_name); +- if (status != 0) { +- return status; +- } ++ 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; ++ } ++ ++#if defined(IMAGE_BL2) ++ i2c_info->status = DT_SECURE; ++#endif ++ ++ return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); + } + + bool initialize_pmic_i2c(void) +@@ -251,8 +194,6 @@ static void register_pmic_shared_peripherals(void) + + void initialize_pmic(void) + { +- unsigned long pmic_version; +- + if (!initialize_pmic_i2c()) { + VERBOSE("No PMIC\n"); + return; +@@ -260,70 +201,89 @@ void initialize_pmic(void) + + register_pmic_shared_peripherals(); + ++ if (register_pmic() < 0) { ++ panic(); ++ } ++ ++ if (stpmic1_powerctrl_on() < 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(); + } + + INFO("PMIC version = 0x%02lx\n", pmic_version); +- stpmic1_dump_regulators(); +- +-#if defined(IMAGE_BL2) +- if (dt_pmic_configure_boot_on_regulators() != 0) { +- panic(); +- }; ++#if defined(IMAGE_BL32) ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ regulator_core_dump(); ++#endif + #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 buck3_min_mv; ++ struct rdev *buck2, *buck3, *vref; ++ struct rdev *ldo3 __unused; + +- switch (ddr_type) { +- case STM32MP_DDR3: +- /* Set LDO3 to sync mode */ +- status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); +- if (status != 0) { +- return status; +- } ++ buck2 = regulator_get_by_name("buck2"); ++ if (buck2 == NULL) { ++ return -ENOENT; ++ } ++ ++#if STM32MP15 ++ ldo3 = regulator_get_by_name("ldo3"); ++ if (ldo3 == NULL) { ++ return -ENOENT; ++ } ++#endif + +- read_val &= ~STPMIC1_LDO3_MODE; +- read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; +- read_val |= STPMIC1_LDO3_DDR_SEL << +- STPMIC1_LDO12356_OUTPUT_SHIFT; ++ vref = regulator_get_by_name("vref_ddr"); ++ if (vref == NULL) { ++ return -ENOENT; ++ } + +- status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); ++ switch (ddr_type) { ++ case STM32MP_DDR3: ++#if STM32MP15 ++ status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE); + if (status != 0) { + return status; + } ++#endif + +- status = stpmic1_regulator_voltage_set("buck2", 1350); ++ status = regulator_set_min_voltage(buck2); + if (status != 0) { + return status; + } + +- status = stpmic1_regulator_enable("buck2"); ++ status = regulator_enable(buck2); + if (status != 0) { + return status; + } + +- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); +- +- status = stpmic1_regulator_enable("vref_ddr"); ++ status = regulator_enable(vref); + if (status != 0) { + return status; + } + +- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); +- +- status = stpmic1_regulator_enable("ldo3"); ++#if STM32MP15 ++ status = regulator_enable(ldo3); + if (status != 0) { + return status; + } +- +- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); ++#endif + break; + + case STM32MP_LPDDR2: +@@ -333,62 +293,314 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) + * 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; ++ buck3 = regulator_get_by_name("buck3"); ++ if (buck3 == NULL) { ++ return -ENOENT; + } + +- if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) { +- buck3_at_1v8 = true; ++ regulator_get_range(buck3, &buck3_min_mv, NULL); ++ ++#if STM32MP15 ++ if (buck3_min_mv != 1800) { ++ status = regulator_set_min_voltage(ldo3); ++ if (status != 0) { ++ return status; ++ } ++ } else { ++ status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS); ++ if (status != 0) { ++ return status; ++ } + } ++#endif + +- status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); ++ status = regulator_set_min_voltage(buck2); + 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 STM32MP15 ++ status = regulator_enable(ldo3); + if (status != 0) { + return status; + } ++#endif + +- status = stpmic1_regulator_voltage_set("buck2", 1200); ++ status = regulator_enable(buck2); + if (status != 0) { + return status; + } + +- status = stpmic1_regulator_enable("ldo3"); ++ status = regulator_enable(vref); + if (status != 0) { + return status; + } ++ break; + +- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); ++ default: ++ break; ++ }; + +- status = stpmic1_regulator_enable("buck2"); +- if (status != 0) { +- return status; ++ return 0; ++} ++ ++int pmic_voltages_init(void) ++{ ++#if STM32MP13 ++ struct rdev *buck1, *buck4; ++ int status; ++ ++ buck1 = regulator_get_by_name("buck1"); ++ if (buck1 == NULL) { ++ return -ENOENT; ++ } ++ ++ buck4 = regulator_get_by_name("buck4"); ++ if (buck4 == NULL) { ++ return -ENOENT; ++ } ++ ++ status = regulator_set_min_voltage(buck1); ++ if (status != 0) { ++ return status; ++ } ++ ++ status = regulator_set_min_voltage(buck4); ++ if (status != 0) { ++ return status; ++ } ++#endif ++ ++ return 0; ++} ++ ++void pmic_switch_off(void) ++{ ++ stpmic1_switch_off(); ++ udelay(100); ++ ++ /* Shouldn't be reached */ ++ panic(); ++} ++ ++enum { ++ STPMIC1_BUCK1 = 0, ++ STPMIC1_BUCK2, ++ STPMIC1_BUCK3, ++ STPMIC1_BUCK4, ++ STPMIC1_LDO1, ++ STPMIC1_LDO2, ++ STPMIC1_LDO3, ++ STPMIC1_LDO4, ++ STPMIC1_LDO5, ++ STPMIC1_LDO6, ++ STPMIC1_VREF_DDR, ++ STPMIC1_BOOST, ++ STPMIC1_VBUS_OTG, ++ STPMIC1_SW_OUT, ++}; ++ ++static int pmic_set_state(const struct regul_description *desc, bool enable) ++{ ++ VERBOSE("%s: set state to %u\n", desc->node_name, enable); ++ ++ if (enable == STATE_ENABLE) { ++ return stpmic1_regulator_enable(desc->node_name); ++ } else { ++ return stpmic1_regulator_disable(desc->node_name); ++ } ++} ++ ++static int pmic_get_state(const struct regul_description *desc) ++{ ++ VERBOSE("%s: get state\n", desc->node_name); ++ ++ return stpmic1_is_regulator_enabled(desc->node_name); ++} ++ ++static int pmic_get_voltage(const struct regul_description *desc) ++{ ++ VERBOSE("%s: get volt\n", desc->node_name); ++ ++ return stpmic1_regulator_voltage_get(desc->node_name); ++} ++ ++static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) ++{ ++ VERBOSE("%s: get volt\n", desc->node_name); ++ ++ return stpmic1_regulator_voltage_set(desc->node_name, mv); ++} ++ ++static int pmic_list_voltages(const struct regul_description *desc, ++ const uint16_t **levels, size_t *count) ++{ ++ VERBOSE("%s: list volt\n", desc->node_name); ++ ++ return stpmic1_regulator_levels_mv(desc->node_name, levels, count); ++} ++ ++static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) ++{ ++ VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); ++ ++ switch (flag) { ++ case REGUL_OCP: ++ return stpmic1_regulator_icc_set(desc->node_name); ++ ++ case REGUL_ACTIVE_DISCHARGE: ++ return stpmic1_active_discharge_mode_set(desc->node_name); ++ ++ case REGUL_PULL_DOWN: ++ return stpmic1_regulator_pull_down_set(desc->node_name); ++ ++ case REGUL_MASK_RESET: ++ return stpmic1_regulator_mask_reset_set(desc->node_name); ++ ++ case REGUL_SINK_SOURCE: ++ return stpmic1_regulator_sink_mode_set(desc->node_name); ++ ++ case REGUL_ENABLE_BYPASS: ++ return stpmic1_regulator_bypass_mode_set(desc->node_name); ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++#if defined(IMAGE_BL32) ++static int driver_suspend(const struct regul_description *desc, uint8_t state, uint16_t mv) ++{ ++ int ret; ++ ++ VERBOSE("%s: suspend state:%d volt:%d\n", desc->node_name, (int)state, mv); ++ ++ ret = stpmic1_lp_copy_reg(desc->node_name); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if ((state & LP_STATE_OFF) != 0U) { ++ ret = stpmic1_lp_reg_on_off(desc->node_name, 0); ++ if (ret != 0) { ++ return ret; + } ++ } + +- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); ++ if ((state & LP_STATE_ON) != 0U) { ++ ret = stpmic1_lp_reg_on_off(desc->node_name, 1); ++ if (ret != 0) { ++ return ret; ++ } ++ } + +- status = stpmic1_regulator_enable("vref_ddr"); +- if (status != 0) { +- return status; ++ if ((state & LP_STATE_SET_VOLT) != 0U) { ++ ret = stpmic1_lp_set_voltage(desc->node_name, mv); ++ if (ret != 0) { ++ return ret; + } ++ } + +- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); +- break; ++ return 0; ++} + +- default: +- break; +- }; ++static void driver_lock(const struct regul_description *desc) ++{ ++ if (stm32mp_lock_available()) { ++ spin_lock(&lock); ++ } ++} ++ ++static void driver_unlock(const struct regul_description *desc) ++{ ++ if (stm32mp_lock_available()) { ++ spin_unlock(&lock); ++ } ++} ++#endif ++ ++struct regul_ops pmic_ops = { ++ .set_state = pmic_set_state, ++ .get_state = pmic_get_state, ++ .set_voltage = pmic_set_voltage, ++ .get_voltage = pmic_get_voltage, ++ .list_voltages = pmic_list_voltages, ++ .set_flag = pmic_set_flag, ++#if defined(IMAGE_BL32) ++ .lock = driver_lock, ++ .unlock = driver_unlock, ++ .suspend = driver_suspend, ++#endif ++}; ++ ++#define DEFINE_REGU(name) { \ ++ .node_name = name, \ ++ .ops = &pmic_ops, \ ++ .driver_data = NULL, \ ++ .enable_ramp_delay = 1000, \ ++} ++ ++static const struct regul_description pmic_regs[] = { ++ [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), ++ [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), ++ [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), ++ [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), ++ [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), ++ [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), ++ [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), ++ [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), ++ [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), ++ [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), ++ [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), ++ [STPMIC1_BOOST] = DEFINE_REGU("boost"), ++ [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), ++ [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), ++}; ++ ++#define NB_REG ARRAY_SIZE(pmic_regs) ++ ++static int register_pmic(void) ++{ ++ void *fdt; ++ int pmic_node, regulators_node, subnode; ++ ++ VERBOSE("Register pmic\n"); ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ pmic_node = dt_get_pmic_node(fdt); ++ if (pmic_node < 0) { ++ return pmic_node; ++ } ++ ++ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); ++ if (regulators_node < 0) { ++ return -ENOENT; ++ } ++ ++ fdt_for_each_subnode(subnode, fdt, regulators_node) { ++ const char *reg_name = fdt_get_name(fdt, subnode, NULL); ++ const struct regul_description *desc; ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < NB_REG; i++) { ++ desc = &pmic_regs[i]; ++ if (strcmp(desc->node_name, reg_name) == 0) { ++ break; ++ } ++ } ++ assert(i < NB_REG); ++ ++ ret = regulator_register(desc, subnode); ++ if (ret != 0) { ++ WARN("%s:%d failed to register %s\n", __func__, ++ __LINE__, reg_name); ++ return ret; ++ } ++ } + + return 0; + } +diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c +index 0a35df372..6a0f893a1 100644 +--- a/drivers/st/pmic/stpmic1.c ++++ b/drivers/st/pmic/stpmic1.c +@@ -23,10 +23,17 @@ struct regul_struct { + uint8_t pull_down; + uint8_t mask_reset_reg; + uint8_t mask_reset; ++ uint8_t icc_reg; ++ uint8_t icc_mask; + }; + + static struct i2c_handle_s *pmic_i2c_handle; + static uint16_t pmic_i2c_addr; ++/* ++ * Special mode corresponds to LDO3 in sink source mode or in bypass mode. ++ * LDO3 doesn't switch back from special to normal mode. ++ */ ++static bool ldo3_special_mode; + + /* Voltage tables in mV */ + static const uint16_t buck1_voltage_table[] = { +@@ -347,8 +354,11 @@ static const uint16_t ldo3_voltage_table[] = { + 3300, + 3300, + 3300, +- 500, +- 0xFFFF, /* VREFDDR */ ++}; ++ ++/* Special mode table is used for sink source OR bypass mode */ ++static const uint16_t ldo3_special_mode_table[] = { ++ 0, + }; + + static const uint16_t ldo5_voltage_table[] = { +@@ -421,6 +431,10 @@ static const uint16_t vref_ddr_voltage_table[] = { + 3300, + }; + ++static const uint16_t fixed_5v_voltage_table[] = { ++ 5000, ++}; ++ + /* Table of Regulators in PMIC SoC */ + static const struct regul_struct regulators_table[] = { + { +@@ -434,6 +448,8 @@ static const struct regul_struct regulators_table[] = { + .pull_down = BUCK1_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK1_MASK_RESET, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = BUCK1_ICC_SHIFT, + }, + { + .dt_node_name = "buck2", +@@ -446,6 +462,8 @@ static const struct regul_struct regulators_table[] = { + .pull_down = BUCK2_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK2_MASK_RESET, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = BUCK2_ICC_SHIFT, + }, + { + .dt_node_name = "buck3", +@@ -458,6 +476,8 @@ static const struct regul_struct regulators_table[] = { + .pull_down = BUCK3_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK3_MASK_RESET, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = BUCK3_ICC_SHIFT, + }, + { + .dt_node_name = "buck4", +@@ -470,6 +490,8 @@ static const struct regul_struct regulators_table[] = { + .pull_down = BUCK4_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK4_MASK_RESET, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = BUCK4_ICC_SHIFT, + }, + { + .dt_node_name = "ldo1", +@@ -480,6 +502,8 @@ static const struct regul_struct regulators_table[] = { + .low_power_reg = LDO1_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO1_MASK_RESET, ++ .icc_reg = LDO_ICC_TURNOFF_REG, ++ .icc_mask = LDO1_ICC_SHIFT, + }, + { + .dt_node_name = "ldo2", +@@ -490,6 +514,8 @@ static const struct regul_struct regulators_table[] = { + .low_power_reg = LDO2_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO2_MASK_RESET, ++ .icc_reg = LDO_ICC_TURNOFF_REG, ++ .icc_mask = LDO2_ICC_SHIFT, + }, + { + .dt_node_name = "ldo3", +@@ -500,6 +526,8 @@ static const struct regul_struct regulators_table[] = { + .low_power_reg = LDO3_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO3_MASK_RESET, ++ .icc_reg = LDO_ICC_TURNOFF_REG, ++ .icc_mask = LDO3_ICC_SHIFT, + }, + { + .dt_node_name = "ldo4", +@@ -510,6 +538,8 @@ static const struct regul_struct regulators_table[] = { + .low_power_reg = LDO4_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO4_MASK_RESET, ++ .icc_reg = LDO_ICC_TURNOFF_REG, ++ .icc_mask = LDO4_ICC_SHIFT, + }, + { + .dt_node_name = "ldo5", +@@ -520,6 +550,8 @@ static const struct regul_struct regulators_table[] = { + .low_power_reg = LDO5_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO5_MASK_RESET, ++ .icc_reg = LDO_ICC_TURNOFF_REG, ++ .icc_mask = LDO5_ICC_SHIFT, + }, + { + .dt_node_name = "ldo6", +@@ -530,6 +562,8 @@ static const struct regul_struct regulators_table[] = { + .low_power_reg = LDO6_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO6_MASK_RESET, ++ .icc_reg = LDO_ICC_TURNOFF_REG, ++ .icc_mask = LDO6_ICC_SHIFT, + }, + { + .dt_node_name = "vref_ddr", +@@ -541,6 +575,33 @@ static const struct regul_struct regulators_table[] = { + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = VREF_DDR_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, ++ .enable_mask = BOOST_ENABLED, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = BOOST_ICC_SHIFT, ++ }, ++ { ++ .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, ++ .enable_mask = USBSW_OTG_SWITCH_ENABLED, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = PWR_SW1_ICC_SHIFT, ++ }, ++ { ++ .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, ++ .enable_mask = SWIN_SWOUT_ENABLED, ++ .icc_reg = BUCK_ICC_TURNOFF_REG, ++ .icc_mask = PWR_SW2_ICC_SHIFT, ++ }, + }; + + #define MAX_REGUL ARRAY_SIZE(regulators_table) +@@ -606,7 +667,7 @@ int stpmic1_regulator_disable(const char *name) + regul->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); +@@ -615,7 +676,7 @@ uint8_t stpmic1_is_regulator_enabled(const char *name) + panic(); + } + +- return (val & regul->enable_mask); ++ return (val & regul->enable_mask) == regul->enable_mask; + } + + int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) +@@ -624,6 +685,16 @@ int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask; + ++ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) { ++ /* ++ * when the LDO3 is in special mode, we do not change voltage, ++ * because by setting voltage, the LDO would leaves sink-source ++ * mode. There is obviously no reason to leave sink-source mode ++ * at runtime. ++ */ ++ return 0; ++ } ++ + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; +@@ -657,12 +728,146 @@ int stpmic1_regulator_mask_reset_set(const char *name) + { + const struct regul_struct *regul = get_regulator_data(name); + ++ if (regul->mask_reset_reg == 0U) { ++ return -EPERM; ++ } ++ + return stpmic1_register_update(regul->mask_reset_reg, + BIT(regul->mask_reset), + LDO_BUCK_RESET_MASK << + regul->mask_reset); + } + ++int stpmic1_regulator_icc_set(const char *name) ++{ ++ const struct regul_struct *regul = get_regulator_data(name); ++ ++ if (regul->mask_reset_reg == 0U) { ++ return -EPERM; ++ } ++ ++ return stpmic1_register_update(regul->icc_reg, ++ BIT(regul->icc_mask), ++ BIT(regul->icc_mask)); ++} ++ ++int stpmic1_regulator_sink_mode_set(const char *name) ++{ ++ if (strncmp(name, "ldo3", 4) != 0) { ++ return -EPERM; ++ } ++ ++ ldo3_special_mode = true; ++ ++ /* disable bypass mode, enable sink mode */ ++ return stpmic1_register_update(LDO3_CONTROL_REG, ++ LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT, ++ LDO3_BYPASS | LDO_VOLTAGE_MASK); ++} ++ ++int stpmic1_regulator_bypass_mode_set(const char *name) ++{ ++ if (strncmp(name, "ldo3", 4) != 0) { ++ return -EPERM; ++ } ++ ++ ldo3_special_mode = true; ++ ++ /* enable bypass mode, disable sink mode */ ++ return stpmic1_register_update(LDO3_CONTROL_REG, ++ LDO3_BYPASS, ++ LDO3_BYPASS | LDO_VOLTAGE_MASK); ++} ++ ++int stpmic1_active_discharge_mode_set(const char *name) ++{ ++ if (strncmp(name, "pwr_sw1", 7) == 0) { ++ return stpmic1_register_update(USB_CONTROL_REG, ++ VBUS_OTG_DISCHARGE, ++ VBUS_OTG_DISCHARGE); ++ } ++ ++ if (strncmp(name, "pwr_sw2", 7) == 0) { ++ return stpmic1_register_update(USB_CONTROL_REG, ++ SW_OUT_DISCHARGE, ++ SW_OUT_DISCHARGE); ++ } ++ ++ return -EPERM; ++} ++ ++/* Low-power functions */ ++int stpmic1_lp_copy_reg(const char *name) ++{ ++ uint8_t val; ++ 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; ++ } ++ ++ return stpmic1_register_write(regul->low_power_reg, val); ++} ++ ++int stpmic1_lp_reg_on_off(const char *name, uint8_t enable) ++{ ++ const struct regul_struct *regul = get_regulator_data(name); ++ ++ return stpmic1_register_update(regul->low_power_reg, enable, ++ LDO_BUCK_ENABLE_MASK); ++} ++ ++int stpmic1_lp_set_mode(const char *name, uint8_t hplp) ++{ ++ const struct regul_struct *regul = get_regulator_data(name); ++ ++ return stpmic1_register_update(regul->low_power_reg, ++ hplp << LDO_BUCK_HPLP_SHIFT, ++ LDO_BUCK_HPLP_ENABLE_MASK); ++} ++ ++int stpmic1_lp_set_voltage(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->low_power_reg, voltage_index << 2, ++ mask); ++} ++ ++int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, ++ size_t *levels_count) ++{ ++ const struct regul_struct *regul = get_regulator_data(name); ++ ++ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) { ++ *levels_count = ARRAY_SIZE(ldo3_special_mode_table); ++ *levels = ldo3_special_mode_table; ++ } else { ++ *levels_count = regul->voltage_table_size; ++ *levels = regul->voltage_table; ++ } ++ ++ return 0; ++} ++ + int stpmic1_regulator_voltage_get(const char *name) + { + const struct regul_struct *regul = get_regulator_data(name); +@@ -670,6 +875,10 @@ int stpmic1_regulator_voltage_get(const char *name) + uint8_t mask; + int status; + ++ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) { ++ return 0; ++ } ++ + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; +diff --git a/drivers/st/regulator/regulator_fixed.c b/drivers/st/regulator/regulator_fixed.c +new file mode 100644 +index 000000000..56593717f +--- /dev/null ++++ b/drivers/st/regulator/regulator_fixed.c +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#ifndef PLAT_NB_FIXED_REGS ++#error "Missing PLAT_NB_FIXED_REGS" ++#endif ++ ++#define FIXED_NAME_LEN 32U ++ ++struct fixed_data { ++ char name[FIXED_NAME_LEN]; ++ uint16_t volt; ++ struct regul_description desc; ++}; ++ ++static struct fixed_data data[PLAT_NB_FIXED_REGS]; ++ ++static int fixed_set_state(const struct regul_description *desc, bool state) ++{ ++ return 0; ++} ++ ++static int fixed_get_state(const struct regul_description *desc) ++{ ++ return 1; ++} ++ ++static struct regul_ops fixed_ops = { ++ .set_state = fixed_set_state, ++ .get_state = fixed_get_state, ++}; ++ ++int fixed_regulator_register(void) ++{ ++ uint32_t count = 0; ++ void *fdt; ++ int node = 0; ++ ++ VERBOSE("fixed reg init!\n"); ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ do { ++ size_t len __unused; ++ int ret; ++ struct fixed_data *d = &data[count]; ++ const char *reg_name; ++ ++ node = fdt_node_offset_by_compatible(fdt, node, "regulator-fixed"); ++ if (node < 0) { ++ break; ++ } ++ ++ reg_name = fdt_get_name(fdt, node, NULL); ++ ++ VERBOSE("register fixed reg %s!\n", reg_name); ++ ++ len = snprintf(d->name, FIXED_NAME_LEN - 1, "%s", reg_name); ++ assert((len > 0) && (len < (FIXED_NAME_LEN - 1))); ++ ++ d->desc.node_name = d->name; ++ d->desc.driver_data = d; ++ d->desc.ops = &fixed_ops; ++ ++ ret = regulator_register(&d->desc, node); ++ if (ret != 0) { ++ WARN("%s:%d failed to register %s\n", __func__, ++ __LINE__, reg_name); ++ return ret; ++ } ++ ++ count++; ++ assert(count <= PLAT_NB_FIXED_REGS); ++ ++ } while (node > 0); ++ ++ return 0; ++} +diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c +index 98c8dcf71..fb025cad3 100644 +--- a/drivers/st/reset/stm32mp1_reset.c ++++ b/drivers/st/reset/stm32mp1_reset.c +@@ -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 + */ +@@ -67,3 +67,34 @@ int stm32mp_reset_deassert(uint32_t id, unsigned int to_us) + + return 0; + } ++ ++#if STM32MP15 ++void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ /* ++ * The RCC_MP_GCR is a read/write register. ++ * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit ++ * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit ++ */ ++ if (assert_not_deassert) { ++ mmio_clrbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); ++ } else { ++ mmio_setbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); ++ } ++} ++#endif ++ ++void __dead2 stm32mp_system_reset(void) ++{ ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ mmio_setbits_32(rcc_base + RCC_MP_GRSTCSETR, ++ RCC_MP_GRSTCSETR_MPSYSRST); ++ ++ /* Loop in case system reset is not immediately caught */ ++ for ( ; ; ) { ++ ; ++ } ++} +diff --git a/drivers/st/rng/stm32_rng.c b/drivers/st/rng/stm32_rng.c +new file mode 100644 +index 000000000..5a1bfd88f +--- /dev/null ++++ b/drivers/st/rng/stm32_rng.c +@@ -0,0 +1,246 @@ ++/* ++ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if STM32MP13 ++#define DT_RNG_COMPAT "st,stm32mp13-rng" ++#endif ++#if STM32MP15 ++#define DT_RNG_COMPAT "st,stm32-rng" ++#endif ++#define RNG_CR 0x00U ++#define RNG_SR 0x04U ++#define RNG_DR 0x08U ++ ++#define RNG_CR_RNGEN BIT(2) ++#define RNG_CR_IE BIT(3) ++#define RNG_CR_CED BIT(5) ++#define RNG_CR_CONDRST BIT(30) ++ ++#define RNG_SR_DRDY BIT(0) ++#define RNG_SR_CECS BIT(1) ++#define RNG_SR_SECS BIT(2) ++#define RNG_SR_CEIS BIT(5) ++#define RNG_SR_SEIS BIT(6) ++ ++#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; ++}; ++ ++static struct stm32_rng_instance stm32_rng; ++ ++static void seed_error_recovery(void) ++{ ++ uint8_t i __unused; ++ ++ /* Recommended by the SoC reference manual */ ++ mmio_clrbits_32(stm32_rng.base + RNG_SR, RNG_SR_SEIS); ++ dmbsy(); ++ ++#if STM32MP15 ++ /* No Auto-reset on STM32MP15, need to clean FIFO */ ++ for (i = 12U; i != 0U; i--) { ++ (void)mmio_read_32(stm32_rng.base + RNG_DR); ++ } ++ ++ dmbsy(); ++#endif ++ ++ if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_SEIS) != 0U) { ++ ERROR("RNG noise\n"); ++ panic(); ++ } ++} ++ ++static int stm32_rng_enable(void) ++{ ++ uint32_t sr; ++ uint64_t timeout; ++ ++#if STM32MP13 ++ /* Reset internal block and disable CED bit */ ++ mmio_setbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST | RNG_CR_CED); ++ mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); ++#endif ++#if STM32MP15 ++ mmio_write_32(stm32_rng.base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED); ++#endif ++ ++ timeout = timeout_init_us(RNG_TIMEOUT_US); ++ sr = mmio_read_32(stm32_rng.base + RNG_SR); ++ while ((sr & RNG_SR_DRDY) == 0U) { ++ if (timeout_elapsed(timeout)) { ++ WARN("Timeout waiting\n"); ++ return -ETIMEDOUT; ++ } ++ ++ if ((sr & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) { ++ seed_error_recovery(); ++ timeout = timeout_init_us(RNG_TIMEOUT_US); ++ } ++ ++ udelay(RNG_TIMEOUT_STEP_US); ++ sr = mmio_read_32(stm32_rng.base + RNG_SR); ++ } ++ ++ VERBOSE("Init RNG done\n"); ++ ++ return 0; ++} ++ ++/* ++ * stm32_rng_read - Read a number of random bytes from RNG ++ * out: pointer to the output buffer ++ * size: number of bytes to be read ++ * Return 0 on success, non-0 on failure ++ */ ++int stm32_rng_read(uint8_t *out, uint32_t size) ++{ ++ uint8_t *buf = out; ++ size_t len = size; ++ int nb_tries; ++ uint32_t data32; ++ int rc = 0; ++ int count; ++ ++ if (stm32_rng.base == 0U) { ++ return -EPERM; ++ } ++ ++ while (len != 0U) { ++ nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US; ++ do { ++ uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR); ++ ++ if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) { ++ seed_error_recovery(); ++ } ++ ++ udelay(RNG_TIMEOUT_STEP_US); ++ nb_tries--; ++ if (nb_tries == 0) { ++ rc = -ETIMEDOUT; ++ goto bail; ++ } ++ } while ((mmio_read_32(stm32_rng.base + RNG_SR) & ++ RNG_SR_DRDY) == 0U); ++ ++ count = 4; ++ while (len != 0U) { ++ data32 = mmio_read_32(stm32_rng.base + RNG_DR); ++ count--; ++ ++ memcpy(buf, &data32, MIN(len, sizeof(uint32_t))); ++ buf += MIN(len, sizeof(uint32_t)); ++ len -= MIN(len, sizeof(uint32_t)); ++ ++ if (count == 0) { ++ break; ++ } ++ } ++ } ++ ++bail: ++ if (rc != 0) { ++ memset(out, 0, buf - out); ++ } ++ ++ return rc; ++} ++ ++/* ++ * stm32_rng_init: Initialize rng from DT ++ * return 0 on success, negative value on failure ++ */ ++int stm32_rng_init(void) ++{ ++ void *fdt; ++ struct dt_node_info dt_rng; ++ int node; ++ ++ if (stm32_rng.base != 0U) { ++ /* Driver is already initialized */ ++ return 0; ++ } ++ ++ if (fdt_get_address(&fdt) == 0) { ++ panic(); ++ } ++ ++ node = dt_get_node(&dt_rng, -1, DT_RNG_COMPAT); ++ if (node < 0) { ++ return 0; ++ } ++ ++#if defined(IMAGE_BL2) ++ if (dt_rng.status == DT_DISABLED) { ++ return 0; ++ } ++#else ++ if ((dt_rng.status & DT_SECURE) == 0U) { ++ return 0; ++ } ++#endif ++ ++ assert(dt_rng.base != 0U); ++ ++ stm32_rng.base = dt_rng.base; ++ ++#if defined(IMAGE_BL32) ++ if ((dt_rng.status & DT_NON_SECURE) == DT_NON_SECURE) { ++ stm32mp_register_non_secure_periph_iomem(stm32_rng.base); ++ } else { ++ stm32mp_register_secure_periph_iomem(stm32_rng.base); ++ } ++#endif ++ ++ if (dt_rng.clock < 0) { ++ panic(); ++ } ++ ++ stm32_rng.clock = (unsigned long)dt_rng.clock; ++ clk_enable(stm32_rng.clock); ++ ++ if (dt_rng.reset >= 0) { ++ int ret; ++ ++ ret = stm32mp_reset_assert((unsigned long)dt_rng.reset, ++ TIMEOUT_US_1MS); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ udelay(20); ++ ++ ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset, ++ TIMEOUT_US_1MS); ++ if (ret != 0) { ++ panic(); ++ } ++ } ++ ++ return stm32_rng_enable(); ++} +diff --git a/drivers/st/rtc/stm32_rtc.c b/drivers/st/rtc/stm32_rtc.c +new file mode 100644 +index 000000000..58d599b17 +--- /dev/null ++++ b/drivers/st/rtc/stm32_rtc.c +@@ -0,0 +1,480 @@ ++/* ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RTC_COMPAT "st,stm32mp1-rtc" ++ ++#define RTC_TR_SU_MASK GENMASK(3, 0) ++#define RTC_TR_ST_MASK GENMASK(6, 4) ++#define RTC_TR_ST_SHIFT 4 ++#define RTC_TR_MNU_MASK GENMASK(11, 8) ++#define RTC_TR_MNU_SHIFT 8 ++#define RTC_TR_MNT_MASK GENMASK(14, 12) ++#define RTC_TR_MNT_SHIFT 12 ++#define RTC_TR_HU_MASK GENMASK(19, 16) ++#define RTC_TR_HU_SHIFT 16 ++#define RTC_TR_HT_MASK GENMASK(21, 20) ++#define RTC_TR_HT_SHIFT 20 ++#define RTC_TR_PM BIT(22) ++ ++#define RTC_DR_DU_MASK GENMASK(3, 0) ++#define RTC_DR_DT_MASK GENMASK(5, 4) ++#define RTC_DR_DT_SHIFT 4 ++#define RTC_DR_MU_MASK GENMASK(11, 8) ++#define RTC_DR_MU_SHIFT 8 ++#define RTC_DR_MT BIT(12) ++#define RTC_DR_MT_SHIFT 12 ++#define RTC_DR_WDU_MASK GENMASK(15, 13) ++#define RTC_DR_WDU_SHIFT 13 ++#define RTC_DR_YU_MASK GENMASK(19, 16) ++#define RTC_DR_YU_SHIFT 16 ++#define RTC_DR_YT_MASK GENMASK(23, 20) ++#define RTC_DR_YT_SHIFT 20 ++ ++#define RTC_SSR_SS_MASK GENMASK(15, 0) ++ ++#define RTC_ICSR_ALRAWF BIT(0) ++#define RTC_ICSR_RSF BIT(5) ++ ++#define RTC_PRER_PREDIV_S_MASK GENMASK(14, 0) ++ ++#define RTC_CR_BYPSHAD BIT(5) ++#define RTC_CR_BYPSHAD_SHIFT 5 ++#define RTC_CR_ALRAE BIT(8) ++#define RTC_CR_ALRAIE BIT(12) ++#define RTC_CR_TAMPTS BIT(25) ++ ++#define RTC_SMCR_TS_DPROT BIT(3) ++ ++#define RTC_TSDR_DU_MASK GENMASK(3, 0) ++#define RTC_TSDR_DU_SHIFT 0 ++#define RTC_TSDR_DT_MASK GENMASK(5, 4) ++#define RTC_TSDR_DT_SHIFT 4 ++#define RTC_TSDR_MU_MASK GENMASK(11, 8) ++#define RTC_TSDR_MU_SHIFT 8 ++ ++#define RTC_ALRMAR_DU_SHIFT 24 ++ ++#define RTC_SR_TSF BIT(3) ++#define RTC_SR_TSOVF BIT(4) ++ ++#define RTC_SCR_CTSF BIT(3) ++#define RTC_SCR_CTSOVF BIT(4) ++ ++#define RTC_WPR_KEY1 0xCA ++#define RTC_WPR_KEY2 0x53 ++#define RTC_WPR_KEY_LOCK 0xFF ++ ++static struct dt_node_info rtc_dev; ++ ++static struct spinlock lock; ++ ++void stm32_rtc_regs_lock(void) ++{ ++ if (stm32mp_lock_available()) { ++ spin_lock(&lock); ++ } ++} ++ ++void stm32_rtc_regs_unlock(void) ++{ ++ if (stm32mp_lock_available()) { ++ spin_unlock(&lock); ++ } ++} ++ ++static void stm32_rtc_write_unprotect(void) ++{ ++ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY1); ++ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY2); ++} ++ ++static void stm32_rtc_write_protect(void) ++{ ++ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY_LOCK); ++} ++ ++/******************************************************************************* ++ * This function gets the BYPSHAD bit value of the RTC_CR register. ++ * It will determine if we need to reset RTC_ISCR.RSF after each RTC calendar ++ * read, and also wait for RTC_ISCR.RSF=1 before next read. ++ * Returns true or false depending on the bit value. ++ ******************************************************************************/ ++static bool stm32_rtc_get_bypshad(void) ++{ ++ return ((mmio_read_32(rtc_dev.base + RTC_CR) & RTC_CR_BYPSHAD) >> ++ RTC_CR_BYPSHAD_SHIFT) != 0U; ++} ++ ++/******************************************************************************* ++ * This function reads the RTC calendar register values. ++ * If shadow registers are not bypassed, then a reset/poll is done. ++ ******************************************************************************/ ++static void stm32_rtc_read_calendar(struct stm32_rtc_calendar *calendar) ++{ ++ bool bypshad = stm32_rtc_get_bypshad(); ++ ++ if (!bypshad) { ++ mmio_clrbits_32((uint32_t)(rtc_dev.base + RTC_ICSR), ++ RTC_ICSR_RSF); ++ while ((mmio_read_32(rtc_dev.base + RTC_ICSR) & RTC_ICSR_RSF) != ++ RTC_ICSR_RSF) { ++ ; ++ } ++ } ++ ++ calendar->ssr = mmio_read_32(rtc_dev.base + RTC_SSR); ++ calendar->tr = mmio_read_32(rtc_dev.base + RTC_TR); ++ calendar->dr = mmio_read_32(rtc_dev.base + RTC_DR); ++} ++ ++/******************************************************************************* ++ * This function fill the rtc_time structure based on rtc_calendar register. ++ ******************************************************************************/ ++static void stm32_rtc_get_time(struct stm32_rtc_calendar *cal, ++ struct stm32_rtc_time *tm) ++{ ++ assert(cal != NULL); ++ assert(tm != NULL); ++ ++ tm->hour = (((cal->tr & RTC_TR_HT_MASK) >> RTC_TR_HT_SHIFT) * 10U) + ++ ((cal->tr & RTC_TR_HU_MASK) >> RTC_TR_HU_SHIFT); ++ ++ if ((cal->tr & RTC_TR_PM) != 0U) { ++ tm->hour += 12U; ++ } ++ ++ tm->min = (((cal->tr & RTC_TR_MNT_MASK) >> RTC_TR_MNT_SHIFT) * 10U) + ++ ((cal->tr & RTC_TR_MNU_MASK) >> RTC_TR_MNU_SHIFT); ++ tm->sec = (((cal->tr & RTC_TR_ST_MASK) >> RTC_TR_ST_SHIFT) * 10U) + ++ (cal->tr & RTC_TR_SU_MASK); ++} ++ ++/******************************************************************************* ++ * This function fill the rtc_time structure with the given date register. ++ ******************************************************************************/ ++static void stm32_rtc_get_date(struct stm32_rtc_calendar *cal, ++ struct stm32_rtc_time *tm) ++{ ++ assert(cal != NULL); ++ assert(tm != NULL); ++ ++ tm->wday = (((cal->dr & RTC_DR_WDU_MASK) >> RTC_DR_WDU_SHIFT)); ++ ++ tm->day = (((cal->dr & RTC_DR_DT_MASK) >> RTC_DR_DT_SHIFT) * 10U) + ++ (cal->dr & RTC_DR_DU_MASK); ++ ++ tm->month = (((cal->dr & RTC_DR_MT) >> RTC_DR_MT_SHIFT) * 10U) + ++ ((cal->dr & RTC_DR_MU_MASK) >> RTC_DR_MU_SHIFT); ++ ++ tm->year = (((cal->dr & RTC_DR_YT_MASK) >> RTC_DR_YT_SHIFT) * 10U) + ++ ((cal->dr & RTC_DR_YU_MASK) >> RTC_DR_YU_SHIFT) + 2000U; ++} ++ ++/******************************************************************************* ++ * This function reads the RTC timestamp register values and update time ++ * structure with the corresponding value. ++ ******************************************************************************/ ++static void stm32_rtc_read_timestamp(struct stm32_rtc_time *time) ++{ ++ assert(time != NULL); ++ ++ struct stm32_rtc_calendar cal_tamp; ++ ++ cal_tamp.tr = mmio_read_32(rtc_dev.base + RTC_TSTR); ++ cal_tamp.dr = mmio_read_32(rtc_dev.base + RTC_TSDR); ++ stm32_rtc_get_time(&cal_tamp, time); ++ stm32_rtc_get_date(&cal_tamp, time); ++} ++ ++/******************************************************************************* ++ * This function gets the RTC calendar register values. ++ * It takes into account the need of reading twice or not, depending on ++ * frequencies previously setted, and the bypass or not of the shadow ++ * registers. This service is exposed externally. ++ ******************************************************************************/ ++void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar) ++{ ++ bool read_twice = stm32mp1_rtc_get_read_twice(); ++ ++ stm32_rtc_regs_lock(); ++ clk_enable(rtc_dev.clock); ++ ++ stm32_rtc_read_calendar(calendar); ++ ++ if (read_twice) { ++ uint32_t tr_save = calendar->tr; ++ ++ stm32_rtc_read_calendar(calendar); ++ ++ if (calendar->tr != tr_save) { ++ stm32_rtc_read_calendar(calendar); ++ } ++ } ++ ++ clk_disable(rtc_dev.clock); ++ stm32_rtc_regs_unlock(); ++} ++ ++/******************************************************************************* ++ * This function computes the second fraction in milliseconds. ++ * The returned value is a uint32_t between 0 and 1000. ++ ******************************************************************************/ ++static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal) ++{ ++ uint32_t prediv_s = mmio_read_32(rtc_dev.base + RTC_PRER) & ++ RTC_PRER_PREDIV_S_MASK; ++ uint32_t ss = cal->ssr & RTC_SSR_SS_MASK; ++ ++ return ((prediv_s - ss) * 1000U) / (prediv_s + 1U); ++} ++ ++/******************************************************************************* ++ * This function computes the fraction difference between two timestamps. ++ * Here again the returned value is in milliseconds. ++ ******************************************************************************/ ++static signed long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, ++ struct stm32_rtc_calendar *ref) ++{ ++ return (signed long long)stm32_rtc_get_second_fraction(cur) - ++ (signed long long)stm32_rtc_get_second_fraction(ref); ++} ++ ++/******************************************************************************* ++ * This function computes the time difference between two timestamps. ++ * It includes seconds, minutes and hours. ++ * Here again the returned value is in milliseconds. ++ ******************************************************************************/ ++static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current, ++ struct stm32_rtc_time *ref) ++{ ++ signed long long curr_s; ++ signed long long ref_s; ++ ++ curr_s = (signed long long)current->sec + ++ (((signed long long)current->min + ++ (((signed long long)current->hour * 60))) * 60); ++ ++ ref_s = (signed long long)ref->sec + ++ (((signed long long)ref->min + ++ (((signed long long)ref->hour * 60))) * 60); ++ ++ return (curr_s - ref_s) * 1000; ++} ++ ++/******************************************************************************* ++ * This function determines if the year is leap or not. ++ * Returned value is true or false. ++ ******************************************************************************/ ++static bool stm32_is_a_leap_year(uint32_t year) ++{ ++ return ((year % 4U) == 0U) && ++ (((year % 100U) != 0U) || ((year % 400U) == 0U)); ++} ++ ++/******************************************************************************* ++ * This function computes the date difference between two timestamps. ++ * It includes days, months, years, with exceptions. ++ * Here again the returned value is in milliseconds. ++ ******************************************************************************/ ++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; ++ static const uint8_t month_len[NB_MONTHS] = { ++ 31, 28, 31, 30, 31, 30, ++ 31, 31, 30, 31, 30, 31 ++ }; ++ ++ /* Get the number of non-entire month days */ ++ if (current->day >= ref->day) { ++ diff_in_days += current->day - ref->day; ++ } else { ++ diff_in_days += (uint32_t)month_len[ref->month - 1U] - ++ ref->day + current->day; ++ } ++ ++ /* Get the number of entire months, and compute the related days */ ++ if (current->month > (ref->month + 1U)) { ++ for (m = (ref->month + 1U); (m < current->month) && ++ (m < 12U); m++) { ++ diff_in_days += (uint32_t)month_len[m - 1U]; ++ } ++ } ++ ++ if (current->month < (ref->month - 1U)) { ++ for (m = 1U; (m < current->month) && (m < 12U); m++) { ++ diff_in_days += (uint32_t)month_len[m - 1U]; ++ } ++ ++ for (m = (ref->month + 1U); m < 12U; m++) { ++ diff_in_days += (uint32_t)month_len[m - 1U]; ++ } ++ } ++ ++ /* Get complete years */ ++ if (current->year > (ref->year + 1U)) { ++ diff_in_days += (current->year - ref->year - 1U) * 365U; ++ } ++ ++ /* Particular cases: leap years (one day more) */ ++ if (diff_in_days > 0U) { ++ if (current->year == ref->year) { ++ if (stm32_is_a_leap_year(current->year)) { ++ if ((ref->month <= 2U) && ++ (current->month >= 3U) && ++ (current->day <= 28U)) { ++ diff_in_days++; ++ } ++ } ++ } else { ++ uint32_t y; ++ ++ /* Ref year is leap */ ++ if ((stm32_is_a_leap_year(ref->year)) && ++ (ref->month <= 2U) && (ref->day <= 28U)) { ++ diff_in_days++; ++ } ++ ++ /* Current year is leap */ ++ if ((stm32_is_a_leap_year(current->year)) && ++ (current->month >= 3U)) { ++ diff_in_days++; ++ } ++ ++ /* Interleaved years are leap */ ++ for (y = ref->year + 1U; y < current->year; y++) { ++ if (stm32_is_a_leap_year(y)) { ++ diff_in_days++; ++ } ++ } ++ } ++ } ++ ++ return (24 * 60 * 60 * 1000) * (signed long long)diff_in_days; ++} ++ ++/******************************************************************************* ++ * This function computes the date difference between two rtc value. ++ * Here again the returned value is in milliseconds. ++ ******************************************************************************/ ++unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, ++ struct stm32_rtc_calendar *ref) ++{ ++ signed long long diff_in_ms = 0; ++ struct stm32_rtc_time curr_t; ++ struct stm32_rtc_time ref_t; ++ ++ clk_enable(rtc_dev.clock); ++ ++ stm32_rtc_get_date(cur, &curr_t); ++ stm32_rtc_get_date(ref, &ref_t); ++ stm32_rtc_get_time(cur, &curr_t); ++ stm32_rtc_get_time(ref, &ref_t); ++ ++ diff_in_ms += stm32_rtc_diff_frac(cur, ref); ++ diff_in_ms += stm32_rtc_diff_time(&curr_t, &ref_t); ++ diff_in_ms += stm32_rtc_diff_date(&curr_t, &ref_t); ++ ++ clk_disable(rtc_dev.clock); ++ ++ return (unsigned long long)diff_in_ms; ++} ++ ++/******************************************************************************* ++ * This function fill the RTC timestamp structure. ++ ******************************************************************************/ ++void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts) ++{ ++ stm32_rtc_regs_lock(); ++ clk_enable(rtc_dev.clock); ++ ++ if ((mmio_read_32(rtc_dev.base + RTC_SR) & RTC_SR_TSF) != 0U) { ++ /* Print timestamp for tamper event */ ++ stm32_rtc_read_timestamp(tamp_ts); ++ mmio_setbits_32(rtc_dev.base + RTC_SCR, RTC_SCR_CTSF); ++ if ((mmio_read_32(rtc_dev.base + RTC_SR) & RTC_SR_TSOVF) != ++ 0U) { ++ /* Overflow detected */ ++ mmio_setbits_32(rtc_dev.base + RTC_SCR, RTC_SCR_CTSOVF); ++ } ++ } ++ ++ clk_disable(rtc_dev.clock); ++ stm32_rtc_regs_unlock(); ++} ++ ++/******************************************************************************* ++ * This function enable the timestamp bit for tamper and secure timestamp ++ * access. ++ ******************************************************************************/ ++void stm32_rtc_set_tamper_timestamp(void) ++{ ++ stm32_rtc_regs_lock(); ++ clk_enable(rtc_dev.clock); ++ ++ stm32_rtc_write_unprotect(); ++ ++ /* Enable tamper timestamper */ ++ mmio_setbits_32(rtc_dev.base + RTC_CR, RTC_CR_TAMPTS); ++ ++ /* Secure Timestamp bit */ ++ mmio_clrbits_32(rtc_dev.base + RTC_SMCR, RTC_SMCR_TS_DPROT); ++ ++ stm32_rtc_write_protect(); ++ ++ clk_disable(rtc_dev.clock); ++ stm32_rtc_regs_unlock(); ++} ++ ++/******************************************************************************* ++ * This function return state of tamper timestamp. ++ ******************************************************************************/ ++bool stm32_rtc_is_timestamp_enable(void) ++{ ++ bool ret; ++ ++ clk_enable(rtc_dev.clock); ++ ++ ret = (mmio_read_32(rtc_dev.base + RTC_CR) & RTC_CR_TAMPTS) != 0U; ++ ++ clk_disable(rtc_dev.clock); ++ ++ return ret; ++} ++ ++/******************************************************************************* ++ * RTC initialisation function. ++ ******************************************************************************/ ++int stm32_rtc_init(void) ++{ ++ int node; ++ ++ node = dt_get_node(&rtc_dev, -1, RTC_COMPAT); ++ if (node < 0) { ++ return node; ++ } ++ ++ if (rtc_dev.status == DT_SECURE) { ++ stm32mp_register_secure_periph_iomem(rtc_dev.base); ++ } else { ++ stm32mp_register_non_secure_periph_iomem(rtc_dev.base); ++ } ++ ++ return 0; ++} +diff --git a/drivers/st/spi/stm32_qspi.c b/drivers/st/spi/stm32_qspi.c +index 4b1a0296c..731844067 100644 +--- a/drivers/st/spi/stm32_qspi.c ++++ b/drivers/st/spi/stm32_qspi.c +@@ -11,6 +11,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -138,10 +139,6 @@ 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)) { +@@ -162,6 +159,10 @@ static int stm32_qspi_wait_cmd(const struct spi_mem_op *op) + /* Clear flags */ + mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF | QSPI_FCR_CTEF); + ++ if (ret == 0) { ++ ret = stm32_qspi_wait_for_not_busy(); ++ } ++ + return ret; + } + +@@ -250,11 +251,6 @@ static int stm32_qspi_exec_op(const struct spi_mem_op *op) + 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)) { +@@ -364,7 +360,7 @@ static void stm32_qspi_release_bus(void) + + static int stm32_qspi_set_speed(unsigned int hz) + { +- unsigned long qspi_clk = stm32mp_clk_get_rate(stm32_qspi.clock_id); ++ unsigned long qspi_clk = clk_get_rate(stm32_qspi.clock_id); + uint32_t prescaler = UINT8_MAX; + uint32_t csht; + int ret; +@@ -494,7 +490,7 @@ int stm32_qspi_init(void) + stm32_qspi.clock_id = (unsigned long)info.clock; + stm32_qspi.reset_id = (unsigned int)info.reset; + +- stm32mp_clk_enable(stm32_qspi.clock_id); ++ clk_enable(stm32_qspi.clock_id); + + ret = stm32mp_reset_assert(stm32_qspi.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { +diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c +new file mode 100644 +index 000000000..e75caee29 +--- /dev/null ++++ b/drivers/st/tamper/stm32_tamp.c +@@ -0,0 +1,681 @@ ++/* ++ * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DT_TAMP_COMPAT "st,stm32-tamp" ++/* STM32 Registers */ ++#define _TAMP_CR1 0x00U ++#define _TAMP_CR2 0x04U ++#define _TAMP_FLTCR 0x0CU ++#define _TAMP_ATCR1 0x10U ++#define _TAMP_ATSEEDR 0x14U ++#define _TAMP_ATOR 0x18U ++#define _TAMP_SMCR 0x20U ++#define _TAMP_IER 0x2CU ++#define _TAMP_SR 0x30U ++#define _TAMP_MISR 0x34U ++#define _TAMP_SMISR 0x38U ++#define _TAMP_SCR 0x3CU ++#define _TAMP_COUNTR 0x40U ++#define _TAMP_OR 0x50U ++#define _TAMP_HWCFGR2 0x3ECU ++#define _TAMP_HWCFGR1 0x3F0U ++#define _TAMP_VERR 0x3F4U ++#define _TAMP_IPIDR 0x3F8U ++#define _TAMP_SIDR 0x3FCU ++ ++/* _TAMP_CR1 bit filds */ ++#define _TAMP_CR1_ITAMP(id) BIT((id) + 16U) ++#define _TAMP_CR1_ETAMP(id) BIT((id)) ++ ++/* _TAMP_CR2 bit filds */ ++#define _TAMP_CR2_ETAMPTRG(id) BIT((id) + 24U) ++#define _TAMP_CR2_ETAMPMSK_MAX_ID 3U ++#define _TAMP_CR2_ETAMPMSK(id) BIT((id) + 16U) ++#define _TAMP_CR2_ETAMPNOER(id) BIT((id)) ++ ++/* _TAMP_FLTCR bit fields */ ++#define _TAMP_FLTCR_TAMPFREQ GENMASK(2, 0) ++#define _TAMP_FLTCR_TAMPFLT GENMASK(4, 3) ++#define _TAMP_FLTCR_TAMPPRCH GENMASK(6, 5) ++#define _TAMP_FLTCR_TAMPPUDIS BIT(7) ++ ++/* _TAMP_ATCR bit fields */ ++#define _TAMP_ATCR1_ATCKSEL GENMASK(18, 16) ++#define _TAMP_ATCR1_ATPER GENMASK(26, 24) ++#define _TAMP_ATCR1_COMMON_MASK GENMASK(31, 16) ++#define _TAMP_ATCR1_ETAMPAM(id) BIT((id)) ++#define _TAMP_ATCR1_ATOSEL_MASK(i) GENMASK(((i) + 1) * 2U + 7U, (i) * 2U + 8U) ++#define _TAMP_ATCR1_ATOSEL(i, o) (((o) - 1U) << ((i) * 2U + 8U)) ++ ++/* _TAMP_ATOR bit fields */ ++#define _TAMP_PRNG GENMASK(7, 0) ++#define _TAMP_SEEDF BIT(14) ++#define _TAMP_INITS BIT(15) ++ ++/* _TAMP_IER bit fields */ ++#define _TAMP_IER_ITAMP(id) BIT((id) + 16U) ++#define _TAMP_IER_ETAMP(id) BIT((id)) ++ ++/* _TAMP_SR bit fields */ ++#define _TAMP_SR_ETAMPXF_MASK GENMASK(7, 0) ++#define _TAMP_SR_ITAMPXF_MASK GENMASK(31, 16) ++#define _TAMP_SR_ITAMP(id) BIT((id) + 16U) ++#define _TAMP_SR_ETAMP(id) BIT((id)) ++ ++/* _TAMP_SCR bit fields */ ++#define _TAMP_SCR_ITAMP(id) BIT((id) + 16U) ++#define _TAMP_SCR_ETAMP(id) BIT((id)) ++ ++/* _TAMP_SMCR bit fields */ ++#define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK(7, 0) ++#define _TAMP_SMCR_BKPRWDPROT_SHIFT U(0) ++#define _TAMP_SMCR_BKPWDPROT_MASK GENMASK(23, 16) ++#define _TAMP_SMCR_BKPWDPROT_SHIFT U(16) ++#define _TAMP_SMCR_DPROT BIT(31) ++ ++/* _TAMP_OR bit fields */ ++#define _TAMP_OR_OUT3RMP_PI8 0U ++#define _TAMP_OR_OUT3RMP_PC13 BIT(0) ++ ++/* _TAMP_HWCFGR2 bit fields */ ++#define _TAMP_HWCFGR2_TZ GENMASK(11, 8) ++#define _TAMP_HWCFGR2_OR GENMASK(7, 0) ++ ++/* _TAMP_HWCFGR1 bit fields */ ++#define _TAMP_HWCFGR1_BKPREG GENMASK(7, 0) ++#define _TAMP_HWCFGR1_TAMPER GENMASK(11, 8) ++#define _TAMP_HWCFGR1_ACTIVE GENMASK(15, 12) ++#define _TAMP_HWCFGR1_INTERN GENMASK(31, 16) ++#define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U ++#define _TAMP_HWCFGR1_ITAMP(id) BIT((id) + 16U) ++ ++/* _TAMP_VERR bit fields */ ++#define _TAMP_VERR_MINREV GENMASK(3, 0) ++#define _TAMP_VERR_MAJREV GENMASK(7, 4) ++ ++#define _TAMP_NB_MONOTONIC_COUNTER 0x1 ++ ++/* ++ * Macro to manage bit manipulation when we work on local variable ++ * before writing only once to the real register ++ */ ++ ++#define CLRBITS(v, bits) (v) &= ~(bits) ++#define SETBITS(v, bits) (v) |= (bits) ++#define CLRSETBITS(v, mask, bits) (v) = ((v) & ~(mask)) | (bits) ++ ++struct stm32_tamp_int { ++ const uint32_t id; ++ uint32_t mode; ++ int (*func)(int id); ++}; ++ ++struct stm32_tamp_ext { ++ const uint32_t id; ++ uint32_t mode; ++ uint8_t out_pin; ++ int (*func)(int id); ++}; ++ ++struct stm32_tamp_instance { ++ uintptr_t base; ++ uint32_t clock; ++ uint32_t hwconf1; ++ uint32_t hwconf2; ++ uint32_t secret_list_conf; ++ uint32_t privilege_conf; ++ uint32_t secure_conf; ++ uint32_t passive_conf; ++ uint32_t active_conf; ++ struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT]; ++ struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT]; ++}; ++ ++/* 0 is the expected initial values for all fields but .id */ ++static struct stm32_tamp_instance stm32_tamp = { ++ .int_tamp = { ++ { ++ .id = INT_TAMP1, ++ }, ++ { ++ .id = INT_TAMP2, ++ }, ++ { ++ .id = INT_TAMP3, ++ }, ++ { ++ .id = INT_TAMP4, ++ }, ++ { ++ .id = INT_TAMP5, ++ }, ++ { ++ .id = INT_TAMP8, ++ }, ++ }, ++ .ext_tamp = { ++ { ++ .id = EXT_TAMP1, ++ }, ++ { ++ .id = EXT_TAMP2, ++ }, ++ { ++ .id = EXT_TAMP3, ++ }, ++ } ++}; ++ ++static void stm32_tamp_set_secure(unsigned long base, uint32_t mode) ++{ ++ if (mode & TAMP_REGS_IT_SECURE) { ++ mmio_clrbits_32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); ++ } else { ++ mmio_setbits_32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); ++ } ++} ++ ++static void stm32_tamp_set_privilege(unsigned long base __unused, uint32_t mode __unused) ++{ ++} ++ ++static void stm32_tamp_set_output_pin(unsigned long base, uint32_t out) ++{ ++ mmio_setbits_32(base + _TAMP_OR, out); ++} ++ ++static int stm32_tamp_set_seed(unsigned long base) ++{ ++ /* Need RNG access. */ ++ uint32_t timeout = 100; ++ uint8_t idx; ++ ++ for (idx = 0; idx < 4U; idx++) { ++ uint32_t rnd; ++ ++ if (stm32_rng_read((uint8_t *)&rnd, sizeof(uint32_t)) != 0) { ++ return -1; ++ } ++ ++ VERBOSE("Seed init %u\n", rnd); ++ mmio_write_32(base + _TAMP_ATSEEDR, rnd); ++ } ++ ++ while (((mmio_read_32(base + _TAMP_ATOR) & _TAMP_SEEDF) != 0U) && ++ (timeout != 0U)) { ++ timeout--; ++ } ++ ++ if (timeout == 0U) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static bool is_int_tamp_id_valid(uint32_t id) ++{ ++ if (id > _TAMP_HWCFGR1_ITAMP_MAX_ID) { ++ return false; ++ } ++ ++ return (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_ITAMP(id)) ++ == _TAMP_HWCFGR1_ITAMP(id); ++} ++ ++static bool is_ext_tamp_id_valid(uint32_t id) ++{ ++ if (id > PLAT_MAX_TAMP_EXT) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static int stm32_tamp_set_int_config(struct stm32_tamp_int *tamp_int, ++ uint32_t *cr1, uint32_t *cr3, uint32_t *ier) ++{ ++ uint32_t id; ++ ++ if (tamp_int == NULL) { ++ return -EINVAL; ++ } ++ ++ id = tamp_int->id; ++ ++ if (!is_int_tamp_id_valid(id)) { ++ return -EINVAL; ++ } ++ ++ /* If etamp is disabled */ ++ if ((tamp_int->mode & TAMP_ENABLE) != TAMP_ENABLE) { ++ CLRBITS(*cr1, _TAMP_CR1_ITAMP(id)); ++ CLRBITS(*ier, _TAMP_IER_ITAMP(id)); ++ return 0; ++ } ++ ++ SETBITS(*cr1, _TAMP_CR1_ITAMP(id)); ++ SETBITS(*ier, _TAMP_IER_ITAMP(id)); ++ ++ return 0; ++} ++ ++static int stm32_tamp_set_ext_config(struct stm32_tamp_ext *tamp_ext, ++ uint32_t *cr1, uint32_t *cr2, ++ uint32_t *atcr1, uint32_t *atcr2, uint32_t *ier) ++{ ++ uint32_t id; ++ ++ if (tamp_ext == NULL) { ++ return -EINVAL; ++ } ++ ++ id = tamp_ext->id; ++ ++ /* Exit if not a valid TAMP_ID */ ++ if (!is_ext_tamp_id_valid(id)) { ++ return -EINVAL; ++ } ++ ++ /* If etamp is disabled */ ++ if ((tamp_ext->mode & TAMP_ENABLE) != TAMP_ENABLE) { ++ CLRBITS(*cr1, _TAMP_CR1_ETAMP(id)); ++ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id)); ++ CLRBITS(*cr2, _TAMP_CR2_ETAMPTRG(id)); ++ CLRBITS(*cr2, _TAMP_CR2_ETAMPNOER(id)); ++ CLRBITS(*ier, _TAMP_IER_ETAMP(id)); ++ return 0; ++ } ++ ++ SETBITS(*cr1, _TAMP_CR1_ETAMP(id)); ++ ++ if ((tamp_ext->mode & TAMP_TRIG_ON) == TAMP_TRIG_ON) { ++ SETBITS(*cr2, _TAMP_CR2_ETAMPTRG(id)); ++ } else { ++ CLRBITS(*cr2, _TAMP_CR2_ETAMPTRG(id)); ++ } ++ ++ if ((tamp_ext->mode & TAMP_ACTIVE) == TAMP_ACTIVE) { ++ SETBITS(*atcr1, _TAMP_ATCR1_ETAMPAM(id)); ++ } else { ++ CLRBITS(*atcr1, _TAMP_ATCR1_ETAMPAM(id)); ++ } ++ ++ if ((tamp_ext->mode & TAMP_NOERASE) == TAMP_NOERASE) { ++ SETBITS(*cr2, _TAMP_CR2_ETAMPNOER(id)); ++ } else { ++ CLRBITS(*cr2, _TAMP_CR2_ETAMPNOER(id)); ++ } ++ ++ /* Configure output pin: ++ * For the case out_pin = 0, we select same output pin than the input one. ++ */ ++ if (tamp_ext->out_pin == TAMPOUTSEL_SAME_AS_INPUT) { ++ tamp_ext->out_pin = id + 1; ++ } ++ ++ if (tamp_ext->out_pin < PLAT_MAX_TAMP_EXT + 1U) { ++ CLRSETBITS(*atcr1, _TAMP_ATCR1_ATOSEL_MASK(id), ++ _TAMP_ATCR1_ATOSEL(id, tamp_ext->out_pin)); ++ } ++ ++ if (id < _TAMP_CR2_ETAMPMSK_MAX_ID) { ++ /* ++ * Only external TAMP 1, 2 and 3 can be masked ++ */ ++ if ((tamp_ext->mode & TAMP_EVT_MASK) == TAMP_EVT_MASK) { ++ /* ++ * ETAMP(id) event generates a trigger event. This ETAMP(id) is masked ++ * and internally cleared by hardware. The backup registers are not erased. ++ */ ++ CLRBITS(*ier, _TAMP_IER_ETAMP(id)); ++ SETBITS(*cr2, _TAMP_CR2_ETAMPMSK(id)); ++ } else { ++ /* ++ * normal ETAMP interrupt: ++ * ETAMP(id) event generates a trigger event and TAMP(id)F must be cleared ++ * by software to * allow next tamper event detection. ++ */ ++ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id)); ++ SETBITS(*ier, _TAMP_IER_ETAMP(id)); ++ } ++ } else { ++ /* other than 1,2,3 external TAMP, we want its interruption */ ++ SETBITS(*ier, _TAMP_IER_ETAMP(id)); ++ } ++ ++ return 0; ++} ++ ++int stm32_tamp_set_secure_bkpregs(struct bkpregs_conf *bkpregs_conf) ++{ ++ uint32_t first_z2; ++ uint32_t first_z3; ++ ++ if (bkpregs_conf == NULL) { ++ return -EINVAL; ++ } ++ ++ first_z2 = bkpregs_conf->nb_zone1_regs; ++ first_z3 = bkpregs_conf->nb_zone1_regs + bkpregs_conf->nb_zone2_regs; ++ ++ if ((first_z2 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG)) || ++ (first_z3 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG))) { ++ return -ENODEV; ++ } ++ ++ mmio_clrsetbits_32(stm32_tamp.base + _TAMP_SMCR, ++ _TAMP_SMCR_BKPRWDPROT_MASK, ++ (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & ++ _TAMP_SMCR_BKPRWDPROT_MASK); ++ ++ mmio_clrsetbits_32(stm32_tamp.base + _TAMP_SMCR, ++ _TAMP_SMCR_BKPWDPROT_MASK, ++ (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & ++ _TAMP_SMCR_BKPWDPROT_MASK); ++ return 0; ++} ++ ++int stm32_tamp_set_config(void) ++{ ++ int ret; ++ uint32_t i; ++ uint32_t cr1 = 0, cr2 = 0, cr3 = 0; ++ uint32_t atcr1 = 0, atcr2 = 0; ++ uint32_t fltcr = 0; ++ uint32_t ier = 0; ++ ++ /* Select access in secure or unsecure */ ++ stm32_tamp_set_secure(stm32_tamp.base, stm32_tamp.secure_conf); ++ ++ /* Select acces in privileged mode or unprivileged mode */ ++ stm32_tamp_set_privilege(stm32_tamp.base, stm32_tamp.privilege_conf); ++ ++ if (stm32_tamp.passive_conf != 0U) { ++ /* Filter mode register set */ ++ fltcr = stm32_tamp.passive_conf; ++ } ++ ++ if (stm32_tamp.active_conf != 0U) { ++ /* Active mode configuration */ ++ CLRSETBITS(atcr1, _TAMP_ATCR1_COMMON_MASK, ++ (stm32_tamp.active_conf & _TAMP_ATCR1_COMMON_MASK)); ++ } ++ ++ for (i = 0U; i < PLAT_MAX_TAMP_INT; i++) { ++ ret = stm32_tamp_set_int_config(&(stm32_tamp.int_tamp[i]), ++ &cr1, &cr3, &ier); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ for (i = 0U; i < PLAT_MAX_TAMP_EXT; i++) { ++ ret = stm32_tamp_set_ext_config(&(stm32_tamp.ext_tamp[i]), ++ &cr1, &cr2, &atcr1, &atcr2, &ier); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ /* ++ * We apply configuration all in a row: ++ * As for active ext tamper "all the needed tampers must be enabled in the same write ++ * access". ++ */ ++ mmio_write_32(stm32_tamp.base + _TAMP_FLTCR, fltcr); ++ /* Active filter configuration applied only if not already done. */ ++ if (((mmio_read_32(stm32_tamp.base + _TAMP_ATOR) & _TAMP_INITS) != _TAMP_INITS)) { ++ mmio_write_32(stm32_tamp.base + _TAMP_ATCR1, atcr1); ++ } ++ ++ mmio_write_32(stm32_tamp.base + _TAMP_CR1, cr1); ++ mmio_write_32(stm32_tamp.base + _TAMP_CR2, cr2); ++ /* If active tamper we reinit the seed. */ ++ if (stm32_tamp.active_conf != 0U) { ++ if (stm32_tamp_set_seed(stm32_tamp.base) != 0) { ++ ERROR("Active tamper: SEED not initialized\n"); ++ return -EPERM; ++ } ++ } ++ ++ /* Ack all pending interrupt */ ++ mmio_write_32(stm32_tamp.base + _TAMP_SCR, ~0U); ++ /* Enable interrupts. */ ++ mmio_write_32(stm32_tamp.base + _TAMP_IER, ier); ++ ++ return 0; ++} ++ ++int stm32_tamp_write_mcounter(int counter_idx) ++{ ++ mmio_write_32(stm32_tamp.base + _TAMP_COUNTR, 1U); ++ ++ return 0; ++} ++ ++uint32_t stm32_tamp_read_mcounter(int counter_idx) ++{ ++ return mmio_read_32(stm32_tamp.base + _TAMP_COUNTR); ++} ++ ++void stm32_tamp_configure_secret_list(uint32_t secret_list_conf) ++{ ++ stm32_tamp.secret_list_conf = secret_list_conf; ++} ++ ++void stm32_tamp_configure_privilege_access(uint32_t privilege_conf) ++{ ++ stm32_tamp.privilege_conf = privilege_conf; ++} ++ ++void stm32_tamp_configure_secure_access(uint32_t secure_conf) ++{ ++ stm32_tamp.secure_conf = secure_conf; ++} ++ ++void stm32_tamp_configure_passive(uint32_t passive_conf) ++{ ++ stm32_tamp.passive_conf = passive_conf; ++} ++ ++void stm32_tamp_configure_active(uint32_t active_conf) ++{ ++ stm32_tamp.active_conf = active_conf; ++} ++ ++int stm32_tamp_configure_internal(enum stm32_tamp_int_id id, uint32_t mode, int (*callback)(int id)) ++{ ++ uint32_t i; ++ uint32_t itamp_id = id; ++ struct stm32_tamp_int *tamp_int = NULL; ++ ++ /* Find internal Tamp struct*/ ++ for (i = 0U; i < PLAT_MAX_TAMP_INT; i++) { ++ if (stm32_tamp.int_tamp[i].id == itamp_id) { ++ tamp_int = &(stm32_tamp.int_tamp[i]); ++ break; ++ } ++ } ++ ++ if (tamp_int == NULL) { ++ return -EINVAL; ++ } ++ ++ tamp_int->mode = mode; ++ tamp_int->func = callback; ++ ++ return 0; ++} ++ ++int stm32_tamp_configure_external(enum stm32_tamp_ext_id id, uint32_t mode, ++ enum stm32_tamp_ext_out_id out_pin, int (*callback)(int id)) ++{ ++ uint32_t i; ++ uint32_t etamp_id = id; ++ struct stm32_tamp_ext *tamp_ext = NULL; ++ ++ /* Find external Tamp struct */ ++ for (i = 0U; i < PLAT_MAX_TAMP_EXT; i++) { ++ if (stm32_tamp.ext_tamp[i].id == etamp_id) { ++ tamp_ext = &(stm32_tamp.ext_tamp[i]); ++ break; ++ } ++ } ++ ++ if (tamp_ext == NULL) { ++ return -EINVAL; ++ } ++ ++ tamp_ext->mode = mode; ++ tamp_ext->out_pin = out_pin; ++ tamp_ext->func = callback; ++ ++ return 0; ++} ++ ++void stm32_tamp_it_handler(void) ++{ ++ uint32_t it = mmio_read_32(stm32_tamp.base + _TAMP_SR); ++ uint32_t int_it = it & _TAMP_SR_ITAMPXF_MASK; ++ uint32_t ext_it = it & _TAMP_SR_ETAMPXF_MASK; ++ uint8_t tamp = 0; ++ struct stm32_rtc_time tamp_ts; ++ ++ if (stm32_rtc_is_timestamp_enable()) { ++ stm32_rtc_get_timestamp(&tamp_ts); ++ INFO("Tamper Event Occurred\n"); ++ INFO("Date : %u/%u\n \t Time : %u:%u:%u\n", ++ tamp_ts.day, tamp_ts.month, tamp_ts.hour, ++ tamp_ts.min, tamp_ts.sec); ++ } ++ ++ while ((int_it != 0U) && (tamp < PLAT_MAX_TAMP_INT)) { ++ int ret = -1; ++ uint32_t int_id = stm32_tamp.int_tamp[tamp].id; ++ ++ if ((it & _TAMP_SR_ITAMP(int_id)) != 0U) { ++ if (stm32_tamp.int_tamp[tamp].func != NULL) { ++ ret = stm32_tamp.int_tamp[tamp].func(int_id); ++ } ++ ++ if (ret >= 0) { ++ mmio_setbits_32(stm32_tamp.base + _TAMP_SCR, ++ _TAMP_SR_ITAMP(int_id)); ++ ext_it &= ~_TAMP_SR_ITAMP(int_id); ++ ++ if (ret > 0) { ++ stm32mp_system_reset(); ++ } ++ } ++ } ++ tamp++; ++ } ++ ++ tamp = 0; ++ /* External tamper interrupt */ ++ while ((ext_it != 0U) && (tamp < PLAT_MAX_TAMP_EXT)) { ++ int ret = -1; ++ uint32_t ext_id = stm32_tamp.ext_tamp[tamp].id; ++ ++ if ((ext_it & _TAMP_SR_ETAMP(ext_id)) != 0U) { ++ if (stm32_tamp.ext_tamp[tamp].func != NULL) { ++ ret = stm32_tamp.ext_tamp[tamp].func(ext_id); ++ } ++ ++ if (ret >= 0) { ++ mmio_setbits_32(stm32_tamp.base + _TAMP_SCR, ++ _TAMP_SCR_ETAMP(ext_id)); ++ ext_it &= ~_TAMP_SR_ETAMP(ext_id); ++ ++ if (ret > 0) { ++ stm32mp_system_reset(); ++ } ++ } ++ } ++ tamp++; ++ } ++ ++ gicv2_end_of_interrupt(STM32MP1_IRQ_TAMPSERRS); ++} ++ ++int stm32_tamp_init(void) ++{ ++ int node; ++ struct dt_node_info dt_tamp; ++ void *fdt; ++ uint32_t rev __unused; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -EPERM; ++ } ++ ++ node = dt_get_node(&dt_tamp, -1, DT_TAMP_COMPAT); ++ if (node < 0) { ++ return -EINVAL; ++ } ++ ++ assert(dt_tamp.base != 0U); ++ assert(dt_tamp.clock != -1); ++ ++ stm32_tamp.base = dt_tamp.base; ++ stm32_tamp.clock = (uint32_t)dt_tamp.clock; ++ ++ /* Init Tamp clock */ ++ clk_enable(stm32_tamp.clock); ++ ++ /* Check if TAMP is enabled */ ++ if (dt_tamp.status == DT_DISABLED) { ++ return 0; ++ } ++ ++ stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + _TAMP_HWCFGR1); ++ stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + _TAMP_HWCFGR2); ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ rev = mmio_read_32(stm32_tamp.base + _TAMP_VERR); ++ VERBOSE("STM32 TAMPER V%u.%u\n", (rev & _TAMP_VERR_MAJREV) >> 4, ++ rev & _TAMP_VERR_MINREV); ++#endif ++ ++ if ((stm32_tamp.hwconf2 & _TAMP_HWCFGR2_TZ) == 0U) { ++ ERROR("Tamper IP doesn't support trustzone"); ++ return -EPERM; ++ } ++ ++ if (dt_set_pinctrl_config(node) != -FDT_ERR_NOTFOUND) { ++ if (fdt_getprop(fdt, node, "st,out3-pc13", NULL) != NULL) { ++ stm32_tamp_set_output_pin(stm32_tamp.base, _TAMP_OR_OUT3RMP_PC13); ++ } ++ } ++ ++ if (stm32mp_gic_enable_spi(node, NULL) < 0) { ++ return -EPERM; ++ } ++ ++ if (fdt_getprop(fdt, node, "wakeup-source", NULL) != NULL) { ++ mmio_setbits_32(EXTI_BASE + EXTI_TZENR1, EXTI_TZENR1_TZEN18); ++ mmio_setbits_32(EXTI_BASE + EXTI_C1IMR1, EXTI_IMR1_IM18); ++ } ++ ++ return 1; ++} +diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c +new file mode 100644 +index 000000000..980367688 +--- /dev/null ++++ b/drivers/st/timer/stm32_timer.c +@@ -0,0 +1,322 @@ ++/* ++ * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define TIM_CR1 0x00U /* Control Register 1 */ ++#define TIM_CR2 0x04U /* Control Register 2 */ ++#define TIM_SMCR 0x08U /* Slave mode control reg */ ++#define TIM_DIER 0x0CU /* DMA/interrupt register */ ++#define TIM_SR 0x10U /* Status register */ ++#define TIM_EGR 0x14U /* Event Generation Reg */ ++#define TIM_CCMR1 0x18U /* Capt/Comp 1 Mode Reg */ ++#define TIM_CCMR2 0x1CU /* Capt/Comp 2 Mode Reg */ ++#define TIM_CCER 0x20U /* Capt/Comp Enable Reg */ ++#define TIM_CNT 0x24U /* Counter */ ++#define TIM_PSC 0x28U /* Prescaler */ ++#define TIM_ARR 0x2CU /* Auto-Reload Register */ ++#define TIM_CCR1 0x34U /* Capt/Comp Register 1 */ ++#define TIM_CCR2 0x38U /* Capt/Comp Register 2 */ ++#define TIM_CCR3 0x3CU /* Capt/Comp Register 3 */ ++#define TIM_CCR4 0x40U /* Capt/Comp Register 4 */ ++#define TIM_BDTR 0x44U /* Break and Dead-Time Reg */ ++#define TIM_DCR 0x48U /* DMA control register */ ++#define TIM_DMAR 0x4CU /* DMA transfer register */ ++#define TIM_AF1 0x60U /* Alt Function Reg 1 */ ++#define TIM_AF2 0x64U /* Alt Function Reg 2 */ ++#define TIM_TISEL 0x68U /* Input Selection */ ++ ++#define TIM_CR1_CEN BIT(0) ++#define TIM_SMCR_SMS GENMASK(2, 0) /* Slave mode selection */ ++#define TIM_SMCR_TS GENMASK(6, 4) /* Trigger selection */ ++#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */ ++#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */ ++#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */ ++#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */ ++#define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */ ++#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */ ++#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */ ++#define TIM_SR_UIF BIT(0) /* UIF interrupt flag */ ++#define TIM_SR_CC1IF BIT(1) /* CC1 interrupt flag */ ++#define TIM_TISEL_TI1SEL_MASK GENMASK(3, 0) ++#define TIM_SMCR_SMS_RESET 0x4U ++#define TIM_SMCR_TS_SHIFT 4U ++#define TIM_SMCR_TS_TI1FP1 0x5U ++ ++#define TIM_COMPAT "st,stm32-timers" ++#define TIM_TIMEOUT_US 100000 ++#define TIM_TIMEOUT_STEP_US 10 ++#define TIM_PRESCAL_HSI 10U ++#define TIM_PRESCAL_CSI 7U ++#define TIM_MIN_FREQ_CALIB 50000000U ++#define TIM_THRESHOLD 1U ++ ++struct stm32_timer_instance { ++ uintptr_t base; ++ unsigned long clk; ++ unsigned long freq; ++ uint8_t cal_input; ++}; ++ ++static struct stm32_timer_instance stm32_timer[TIM_MAX_INSTANCE]; ++ ++static int stm32_timer_get_dt_node(struct dt_node_info *info, int offset) ++{ ++ int node; ++ ++ node = dt_get_node(info, offset, TIM_COMPAT); ++ if (node < 0) { ++ if (offset == -1) { ++ WARN("%s: No TIMER found\n", __func__); ++ } ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ return node; ++} ++ ++static int stm32_timer_config(struct stm32_timer_instance *timer) ++{ ++ clk_enable(timer->clk); ++ ++ timer->freq = clk_get_rate(timer->clk); ++ ++ if (timer->freq < TIM_MIN_FREQ_CALIB) { ++ WARN("Timer is not accurate enough for calibration\n"); ++ 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, ++ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC1S_TI2, ++ TIM_CCMR_CC1S_TI1); ++ ++ mmio_clrbits_32(timer->base + TIM_CCER, ++ TIM_CCER_CC1P | TIM_CCER_CC1NP); ++ ++ mmio_clrsetbits_32(timer->base + TIM_SMCR, ++ TIM_SMCR_TS | TIM_SMCR_SMS, ++ (TIM_SMCR_TS_TI1FP1 << TIM_SMCR_TS_SHIFT) | ++ TIM_SMCR_SMS_RESET); ++ ++ mmio_write_32(timer->base + TIM_TISEL, timer->cal_input); ++ mmio_setbits_32(timer->base + TIM_CR1, TIM_CR1_CEN); ++ mmio_setbits_32(timer->base + TIM_CCER, TIM_CCER_CC1E); ++ } ++ ++ clk_disable(timer->clk); ++ ++ return 0; ++} ++ ++static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer) ++{ ++ uint32_t timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US; ++ uint32_t counter = 0U; ++ uint32_t old_counter; ++ uint64_t conv_timeout; ++ ++ if (stm32_timer_config(timer) < 0) { ++ return 0U; ++ } ++ ++ clk_enable(timer->clk); ++ ++ mmio_write_32(timer->base + TIM_SR, 0U); ++ while (((mmio_read_32(timer->base + TIM_SR) & ++ TIM_SR_UIF) == 0U) && (timeout != 0U)) { ++ udelay(TIM_TIMEOUT_STEP_US); ++ timeout--; ++ } ++ ++ if (timeout == 0U) { ++ goto out; ++ } ++ ++ mmio_write_32(timer->base + TIM_SR, 0U); ++ ++ conv_timeout = timeout_init_us(TIM_TIMEOUT_US); ++ do { ++ if (timeout_elapsed(conv_timeout)) { ++ WARN("Timer counter not stable\n"); ++ timeout = 0U; ++ goto out; ++ } ++ ++ timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US; ++ while (((mmio_read_32(timer->base + TIM_SR) & ++ TIM_SR_CC1IF) == 0U) && (timeout != 0U)) { ++ udelay(TIM_TIMEOUT_STEP_US); ++ timeout--; ++ } ++ ++ if (timeout == 0U) { ++ goto out; ++ } ++ ++ old_counter = counter; ++ counter = mmio_read_32(timer->base + TIM_CCR1); ++ } while ((MAX(counter, old_counter) - MIN(counter, old_counter)) > ++ TIM_THRESHOLD); ++ ++out: ++ clk_disable(timer->clk); ++ ++ if (timeout == 0U) { ++ return 0U; ++ } ++ ++ return counter; ++} ++ ++unsigned long stm32_timer_hsi_freq(void) ++{ ++ struct stm32_timer_instance *timer = &stm32_timer[HSI_CAL]; ++ unsigned long hsi_freq; ++ uint32_t counter; ++ ++ if (timer->base == 0) { ++ return 0; ++ } ++ ++ counter = stm32_timer_start_capture(timer); ++ VERBOSE("Counter value %i\n", counter); ++ ++ if (counter == 0U) { ++ return 0; ++ } ++ ++ hsi_freq = (timer->freq / counter) << TIM_PRESCAL_HSI; ++ ++ return hsi_freq; ++} ++ ++unsigned long stm32_timer_csi_freq(void) ++{ ++ struct stm32_timer_instance *timer = &stm32_timer[CSI_CAL]; ++ unsigned long csi_freq; ++ uint32_t counter; ++ ++ if (timer->base == 0) { ++ return 0; ++ } ++ ++ counter = stm32_timer_start_capture(timer); ++ VERBOSE("Counter value %i\n", counter); ++ ++ if (counter == 0U) { ++ return 0; ++ } ++ ++ csi_freq = (timer->freq / counter) << TIM_PRESCAL_CSI; ++ ++ return csi_freq; ++} ++ ++/* ++ * Get the timer frequence callback function for a target clock calibration ++ * @timer_freq_cb - Output callback function ++ * @type - Target clock calibration ID ++ */ ++void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void), ++ enum timer_cal type) ++{ ++ switch (type) { ++ case HSI_CAL: ++ if (stm32_timer[HSI_CAL].base != 0) { ++ *timer_freq_cb = stm32_timer_hsi_freq; ++ } ++ break; ++ ++ case CSI_CAL: ++ if (stm32_timer[CSI_CAL].base != 0) { ++ *timer_freq_cb = stm32_timer_csi_freq; ++ } ++ break; ++ ++ default: ++ panic(); ++ } ++} ++ ++/* ++ * Initialize timer from DT ++ * return 0 if disabled, 1 if enabled, else < 0 ++ */ ++int stm32_timer_init(void) ++{ ++ void *fdt; ++ struct dt_node_info dt_timer; ++ int node = -1; ++ uint8_t nb_timer = 0; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -EPERM; ++ } ++ ++ for (node = stm32_timer_get_dt_node(&dt_timer, node); ++ node != -FDT_ERR_NOTFOUND; ++ node = stm32_timer_get_dt_node(&dt_timer, node)) { ++ if (dt_timer.status != DT_DISABLED) { ++ struct stm32_timer_instance *timer; ++ const fdt32_t *cuint; ++ ++ nb_timer++; ++ ++ cuint = fdt_getprop(fdt, node, "st,hsi-cal-input", ++ NULL); ++ if (cuint != NULL) { ++ timer = &stm32_timer[HSI_CAL]; ++ timer->base = dt_timer.base; ++ timer->clk = dt_timer.clock; ++ timer->freq = clk_get_rate(timer->clk); ++ timer->cal_input = ++ (uint8_t)fdt32_to_cpu(*cuint); ++ if (stm32_timer_config(timer) < 0) { ++ timer->base = 0; ++ continue; ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, node, "st,csi-cal-input", ++ NULL); ++ if (cuint != NULL) { ++ timer = &stm32_timer[CSI_CAL]; ++ timer->base = dt_timer.base; ++ timer->clk = dt_timer.clock; ++ timer->freq = clk_get_rate(timer->clk); ++ timer->cal_input = ++ (uint8_t)fdt32_to_cpu(*cuint); ++ if (stm32_timer_config(timer) < 0) { ++ timer->base = 0; ++ continue; ++ } ++ } ++ } ++ } ++ ++ VERBOSE("%u TIMER instance%s found\n", nb_timer, ++ nb_timer > 1 ? "s" : ""); ++ ++ if (nb_timer == 0U) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ return 0; ++} +diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S +index 2b8879a11..ab1c3bdcc 100644 +--- a/drivers/st/uart/aarch32/stm32_console.S ++++ b/drivers/st/uart/aarch32/stm32_console.S +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -67,9 +67,24 @@ func console_stm32_core_init + bic r3, r3, #USART_CR2_STOP + str r3, [r0, #USART_CR2] + /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ +- lsl r3, r2, #1 ++ lsr r3, r2, #1 + add r3, r1, r3 + udiv r3, r3, r2 ++ cmp r3, #16 ++ bhi 2f ++ /* Oversampling 8 */ ++ /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ ++ lsr r3, r2, #1 ++ add r3, r3, r1, lsl #1 ++ udiv r3, r3, r2 ++ and r1, r3, #USART_BRR_DIV_FRACTION ++ lsr r1, r1, #1 ++ bic r3, r3, #USART_BRR_DIV_FRACTION ++ orr r3, r3, r1 ++ ldr r1, [r0, #USART_CR1] ++ orr r1, r1, #USART_CR1_OVER8 ++ str r1, [r0, #USART_CR1] ++2: + str r3, [r0, #USART_BRR] + /* Enable UART */ + ldr r3, [r0, #USART_CR1] +@@ -127,17 +142,15 @@ register_fail: + pop {r4, pc} + endfunc console_stm32_register + +- /* --------------------------------------------------------------- ++ /* -------------------------------------------------------- + * int console_core_putc(int c, uintptr_t base_addr) +- * +- * Function to output a character over the console. It returns the +- * character printed on success or -1 on error. +- * ++ * 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 - console base address + * Out : return -1 on error else return character. +- * Clobber list : r2 +- * --------------------------------------------------------------- ++ * Clobber list : r2, r3 ++ * -------------------------------------------------------- + */ + func console_stm32_core_putc + /* Check the input parameter */ +@@ -145,13 +158,19 @@ func console_stm32_core_putc + beq putc_error + + /* Check Transmit Data Register Empty */ ++ mov r3, #USART_TIMEOUT + txe_loop: ++ subs r3, r3, #1 ++ beq putc_error + ldr r2, [r1, #USART_ISR] + tst r2, #USART_ISR_TXE + beq txe_loop + str r0, [r1, #USART_TDR] + /* Check transmit complete flag */ ++ mov r3, #USART_TIMEOUT + tc_loop: ++ subs r3, r3, #1 ++ beq putc_error + ldr r2, [r1, #USART_ISR] + tst r2, #USART_ISR_TC + beq tc_loop +@@ -205,7 +224,7 @@ endfunc console_stm32_core_getc + * + * In : r0 - console base address + * Out : void. +- * Clobber list : r0, r1 ++ * Clobber list : r0, r1, r2 + * --------------------------------------------------------------- + */ + func console_stm32_core_flush +@@ -214,7 +233,10 @@ func console_stm32_core_flush + ASM_ASSERT(ne) + #endif /* ENABLE_ASSERTIONS */ + /* Check Transmit Data Register Empty */ ++ mov r2, #USART_TIMEOUT + txe_loop_3: ++ subs r2, r2, #1 ++ beq plat_panic_handler + ldr r1, [r0, #USART_ISR] + tst r1, #USART_ISR_TXE + beq txe_loop_3 +diff --git a/drivers/st/uart/stm32_uart.c b/drivers/st/uart/stm32_uart.c +new file mode 100644 +index 000000000..588a634aa +--- /dev/null ++++ b/drivers/st/uart/stm32_uart.c +@@ -0,0 +1,440 @@ ++/* ++ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* UART time-out value */ ++#define STM32_UART_TIMEOUT_US 20000U ++ ++/* Mask to clear ALL the configuration registers */ ++ ++#define STM32_UART_CR1_FIELDS \ ++ (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ ++ USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN) ++ ++#define STM32_UART_CR2_FIELDS \ ++ (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \ ++ USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ ++ USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ ++ USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \ ++ USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \ ++ USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \ ++ USART_CR2_RTOEN | USART_CR2_ADD) ++ ++#define STM32_UART_CR3_FIELDS \ ++ (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \ ++ USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \ ++ USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \ ++ USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ ++ USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \ ++ USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \ ++ USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \ ++ USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG) ++ ++#define STM32_UART_ISR_ERRORS \ ++ (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE) ++ ++static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = { ++ 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U ++}; ++ ++/* @brief BRR division operation to set BRR register in 8-bit oversampling ++ * mode. ++ * @param clockfreq: UART clock. ++ * @param baud_rate: Baud rate set by the user. ++ * @param prescaler: UART prescaler value. ++ * @retval Division result. ++ */ ++static uint32_t uart_div_sampling8(unsigned long clockfreq, ++ uint32_t baud_rate, ++ uint32_t prescaler) ++{ ++ uint32_t scaled_freq = clockfreq / presc_table[prescaler]; ++ ++ return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate; ++ ++} ++ ++/* @brief BRR division operation to set BRR register in 16-bit oversampling ++ * mode. ++ * @param clockfreq: UART clock. ++ * @param baud_rate: Baud rate set by the user. ++ * @param prescaler: UART prescaler value. ++ * @retval Division result. ++ */ ++static uint32_t uart_div_sampling16(unsigned long clockfreq, ++ uint32_t baud_rate, ++ uint32_t prescaler) ++{ ++ uint32_t scaled_freq = clockfreq / presc_table[prescaler]; ++ ++ return (scaled_freq + (baud_rate / 2)) / baud_rate; ++ ++} ++ ++/* ++ * @brief Return the UART clock frequency. ++ * @param huart: UART handle. ++ * @retval Frequency value in Hz. ++ */ ++static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart) ++{ ++ return fdt_get_uart_clock_freq((uintptr_t)huart->base); ++} ++ ++/* ++ * @brief Configure the UART peripheral. ++ * @param huart: UART handle. ++ * @retval UART status. ++ */ ++static int uart_set_config(struct stm32_uart_handle_s *huart, ++ const struct stm32_uart_init_s *init) ++{ ++ uint32_t tmpreg; ++ unsigned long clockfreq; ++ unsigned long int_div; ++ uint32_t brrtemp; ++ uint32_t over_sampling; ++ ++ ++ /*---------------------- USART BRR configuration --------------------*/ ++ clockfreq = uart_get_clock_freq(huart); ++ if (clockfreq == 0UL) { ++ return -ENODEV; ++ } ++ ++ int_div = clockfreq / init->baud_rate; ++ if (int_div < 16U) { ++ uint32_t usartdiv = uart_div_sampling8(clockfreq, ++ init->baud_rate, ++ init->prescaler); ++ ++ brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) | ++ ((usartdiv & USART_BRR_DIV_FRACTION) >> 1); ++ over_sampling = USART_CR1_OVER8; ++ } else { ++ brrtemp = uart_div_sampling16(clockfreq, ++ init->baud_rate, ++ init->prescaler) & ++ (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA); ++ over_sampling = 0x0U; ++ } ++ mmio_write_32(huart->base + USART_BRR, brrtemp); ++ ++ /* ++ * ---------------------- USART CR1 Configuration -------------------- ++ * Clear M, PCE, PS, TE, RE and OVER8 bits and configure ++ * the UART word length, parity, mode and oversampling: ++ * - set the M bits according to init->word_length value, ++ * - set PCE and PS bits according to init->parity value, ++ * - set TE and RE bits according to init->mode value, ++ * - set OVER8 bit according baudrate and clock. ++ */ ++ tmpreg = init->word_length | ++ init->parity | ++ init->mode | ++ over_sampling | ++ init->fifo_mode; ++ mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg); ++ ++ /* ++ * --------------------- USART CR2 Configuration --------------------- ++ * Configure the UART Stop Bits: Set STOP[13:12] bits according ++ * to init->stop_bits value. ++ */ ++ mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS, ++ init->stop_bits); ++ ++ /* ++ * --------------------- USART CR3 Configuration --------------------- ++ * Configure: ++ * - UART HardWare Flow Control: set CTSE and RTSE bits according ++ * to init->hw_flow_control value, ++ * - one-bit sampling method versus three samples' majority rule ++ * according to init->one_bit_sampling (not applicable to ++ * LPUART), ++ * - set TXFTCFG bit according to init->tx_fifo_threshold value, ++ * - set RXFTCFG bit according to init->rx_fifo_threshold value. ++ */ ++ tmpreg = init->hw_flow_control | init->one_bit_sampling; ++ ++ if (init->fifo_mode == USART_CR1_FIFOEN) { ++ tmpreg |= init->tx_fifo_threshold | ++ init->rx_fifo_threshold; ++ } ++ ++ mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg); ++ ++ /* ++ * --------------------- USART PRESC Configuration ------------------- ++ * Configure UART Clock Prescaler : set PRESCALER according to ++ * init->prescaler value. ++ */ ++ assert(init->prescaler < STM32_UART_PRESCALER_NB); ++ mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER, ++ init->prescaler); ++ ++ return 0; ++} ++ ++/* ++ * @brief Handle UART communication timeout. ++ * @param huart: UART handle. ++ * @param flag: Specifies the UART flag to check. ++ * @retval UART status. ++ */ ++static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag) ++{ ++ uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US); ++ ++ while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) { ++ if (timeout_elapsed(timeout_ref)) { ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Check the UART idle State. ++ * @param huart: UART handle. ++ * @retval UART status. ++ */ ++static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart) ++{ ++ int ret; ++ ++ /* Check if the transmitter is enabled */ ++ if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) { ++ ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ /* Check if the receiver is enabled */ ++ if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) { ++ ret = stm32_uart_wait_flag(huart, USART_ISR_REACK); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Compute RDR register mask depending on word length. ++ * @param huart: UART handle. ++ * @retval Mask value. ++ */ ++static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init) ++{ ++ unsigned int mask = 0U; ++ ++ switch (init->word_length) { ++ case STM32_UART_WORDLENGTH_9B: ++ mask = GENMASK(8, 0); ++ break; ++ case STM32_UART_WORDLENGTH_8B: ++ mask = GENMASK(7, 0); ++ break; ++ case STM32_UART_WORDLENGTH_7B: ++ mask = GENMASK(6, 0); ++ break; ++ default: ++ break; /* not reached */ ++ } ++ ++ if (init->parity != STM32_UART_PARITY_NONE) { ++ mask >>= 1; ++ } ++ ++ return mask; ++} ++ ++/* ++ * @brief Check interrupt and status errors. ++ * @retval True if error detected, false otherwise. ++ */ ++static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart) ++{ ++ return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U; ++} ++ ++/* ++ * @brief Clear status errors. ++ */ ++static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart) ++{ ++ mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS); ++} ++ ++/* ++ * @brief Stop the UART. ++ * @param base: UART base address. ++ */ ++void stm32_uart_stop(uintptr_t base) ++{ ++ mmio_clrbits_32(base + USART_CR1, USART_CR1_UE); ++} ++ ++/* ++ * @brief Initialize UART. ++ * @param huart: UART handle. ++ * @param base_addr: base address of UART. ++ * @param init: UART initialization parameter. ++ * @retval UART status. ++ */ ++int stm32_uart_init(struct stm32_uart_handle_s *huart, ++ uintptr_t base_addr, ++ const struct stm32_uart_init_s *init) ++{ ++ int ret; ++ int uart_node; ++ int clk; ++ void *fdt = NULL; ++ ++ if (huart == NULL || init == NULL || base_addr == 0U) { ++ return -EINVAL; ++ } ++ ++ huart->base = base_addr; ++ ++ /* Search UART instance in DT */ ++ if (fdt_get_address(&fdt) == 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ if (fdt == NULL) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ uart_node = dt_match_instance_by_compatible(DT_UART_COMPAT, base_addr); ++ if (uart_node == -FDT_ERR_NOTFOUND) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ /* Pinctrl initialization */ ++ if (dt_set_pinctrl_config(uart_node) != 0) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ /* Clock initialization */ ++ clk = fdt_get_clock_id(uart_node); ++ if (clk < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ clk_enable(clk); ++ ++ /* Disable the peripheral */ ++ stm32_uart_stop(huart->base); ++ ++ /* Computation of UART mask to apply to RDR register */ ++ huart->rdr_mask = stm32_uart_rdr_mask(init); ++ ++ /* Init the peripheral */ ++ ret = uart_set_config(huart, init); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Enable the peripheral */ ++ mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE); ++ ++ /* TEACK and/or REACK to check */ ++ return stm32_uart_check_idle(huart); ++} ++ ++/* ++ * @brief Transmit one data in no blocking mode. ++ * @param huart: UART handle. ++ * @param c: data to sent. ++ * @retval UART status. ++ */ ++int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c) ++{ ++ int ret; ++ ++ if (huart == NULL) { ++ return -EINVAL; ++ } ++ ++ ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ mmio_write_32(huart->base + USART_TDR, c); ++ if (stm32_uart_error_detected(huart)) { ++ stm32_uart_error_clear(huart); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/* ++ * @brief Flush TX Transmit fifo ++ * @param huart: UART handle. ++ * @retval UART status. ++ */ ++int stm32_uart_flush(struct stm32_uart_handle_s *huart) ++{ ++ int ret; ++ ++ if (huart == NULL) { ++ return -EINVAL; ++ } ++ ++ ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return stm32_uart_wait_flag(huart, USART_ISR_TC); ++} ++ ++/* ++ * @brief Receive a data in no blocking mode. ++ * @retval value if >0 or UART status. ++ */ ++int stm32_uart_getc(struct stm32_uart_handle_s *huart) ++{ ++ uint32_t data; ++ ++ if (huart == NULL) { ++ return -EINVAL; ++ } ++ ++ /* Check if data is available */ ++ if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) { ++ return -EAGAIN; ++ } ++ ++ data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask; ++ ++ if (stm32_uart_error_detected(huart)) { ++ stm32_uart_error_clear(huart); ++ return -EFAULT; ++ } ++ ++ return (int)data; ++} +diff --git a/fdts/stm32mp13-bl2.dtsi b/fdts/stm32mp13-bl2.dtsi +new file mode 100644 +index 000000000..5eca49c67 +--- /dev/null ++++ b/fdts/stm32mp13-bl2.dtsi +@@ -0,0 +1,88 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved ++ */ ++ ++/ { ++ aliases { ++#if !STM32MP_EMMC && !STM32MP_SDMMC ++ /delete-property/ mmc0; ++#endif ++ }; ++ ++ soc { ++#if !STM32MP_USB_PROGRAMMER ++ /delete-node/ usb-otg@49000000; ++#endif ++#if !STM32MP_RAW_NAND ++ /delete-node/ memory-controller@58002000; ++#endif ++#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR ++ /delete-node/ spi@58003000; ++#endif ++#if !STM32MP_EMMC && !STM32MP_SDMMC ++ /delete-node/ mmc@58005000; ++ /delete-node/ mmc@58007000; ++#endif ++#if !STM32MP_USB_PROGRAMMER ++ /delete-node/ usbh-ohci@5800c000; ++ /delete-node/ usbh-ehci@5800d000; ++#endif ++#if !STM32MP_USB_PROGRAMMER ++ /delete-node/ usbphyc@5a006000; ++#endif ++ ++ pin-controller@50002000 { ++#if !STM32MP_EMMC && !STM32MP_SDMMC ++ /delete-node/ sdmmc1-b4-0; ++ /delete-node/ sdmmc2-b4-0; ++#endif ++ }; ++ }; ++ ++ /* ++ * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in ++ * network order (big endian) ++ */ ++ ++ st-io_policies { ++ fip-handles { ++ compatible = "st,io-fip-handle"; ++ fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e"; ++ bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38"; ++ bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288"; ++ bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9"; ++ bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4"; ++ hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc"; ++ tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; ++ nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; ++#if TRUSTED_BOARD_BOOT ++ t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c"; ++ t_boot_fw_cert_uuid = "d6e269ea-5d63-e411-8d8c-9fbabe9956a5"; ++ tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04"; ++ nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859"; ++ tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d"; ++ nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7"; ++#endif ++ }; ++ }; ++ ++#if TRUSTED_BOARD_BOOT ++ tb_fw-config { ++ compatible = "arm,tb_fw"; ++ ++ /* Disable authentication for development */ ++ disable_auth = <0x0>; ++ ++ /* ++ * The following two entries are placeholders for Mbed TLS ++ * heap information. ++ */ ++ mbedtls_heap_addr = <0x0 0x30004000>; /* SRAM2_BASE */ ++ mbedtls_heap_size = <0x2000>; /* SRAM2_SIZE */ ++ }; ++ ++#include "cot_descriptors.dtsi" ++#endif ++ ++}; +diff --git a/fdts/stm32mp13-ddr.dtsi b/fdts/stm32mp13-ddr.dtsi +new file mode 100644 +index 000000000..78cdbc3b3 +--- /dev/null ++++ b/fdts/stm32mp13-ddr.dtsi +@@ -0,0 +1,184 @@ ++// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++/* ++ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved ++ */ ++ ++&ddr { ++ st,mem-name = DDR_MEM_NAME; ++ st,mem-speed = ; ++ st,mem-size = ; ++ ++ st,ctl-reg = < ++ DDR_MSTR ++ DDR_MRCTRL0 ++ DDR_MRCTRL1 ++ DDR_DERATEEN ++ DDR_DERATEINT ++ DDR_PWRCTL ++ DDR_PWRTMG ++ DDR_HWLPCTL ++ DDR_RFSHCTL0 ++ DDR_RFSHCTL3 ++ DDR_CRCPARCTL0 ++ DDR_ZQCTL0 ++ DDR_DFITMG0 ++ DDR_DFITMG1 ++ DDR_DFILPCFG0 ++ DDR_DFIUPD0 ++ DDR_DFIUPD1 ++ DDR_DFIUPD2 ++ DDR_DFIPHYMSTR ++ DDR_ODTMAP ++ DDR_DBG0 ++ DDR_DBG1 ++ DDR_DBGCMD ++ DDR_POISONCFG ++ DDR_PCCFG ++ >; ++ ++ st,ctl-timing = < ++ DDR_RFSHTMG ++ DDR_DRAMTMG0 ++ DDR_DRAMTMG1 ++ DDR_DRAMTMG2 ++ DDR_DRAMTMG3 ++ DDR_DRAMTMG4 ++ DDR_DRAMTMG5 ++ DDR_DRAMTMG6 ++ DDR_DRAMTMG7 ++ DDR_DRAMTMG8 ++ DDR_DRAMTMG14 ++ DDR_ODTCFG ++ >; ++ ++ st,ctl-map = < ++ DDR_ADDRMAP1 ++ DDR_ADDRMAP2 ++ DDR_ADDRMAP3 ++ DDR_ADDRMAP4 ++ DDR_ADDRMAP5 ++ DDR_ADDRMAP6 ++ DDR_ADDRMAP9 ++ DDR_ADDRMAP10 ++ DDR_ADDRMAP11 ++ >; ++ ++ st,ctl-perf = < ++ DDR_SCHED ++ DDR_SCHED1 ++ DDR_PERFHPR1 ++ DDR_PERFLPR1 ++ DDR_PERFWR1 ++ DDR_PCFGR_0 ++ DDR_PCFGW_0 ++ DDR_PCFGQOS0_0 ++ DDR_PCFGQOS1_0 ++ DDR_PCFGWQOS0_0 ++ DDR_PCFGWQOS1_0 ++ >; ++ ++ st,phy-reg = < ++ DDR_PGCR ++ DDR_ACIOCR ++ DDR_DXCCR ++ DDR_DSGCR ++ DDR_DCR ++ DDR_ODTCR ++ DDR_ZQ0CR1 ++ DDR_DX0GCR ++ DDR_DX1GCR ++ >; ++ ++ st,phy-timing = < ++ DDR_PTR0 ++ DDR_PTR1 ++ DDR_PTR2 ++ DDR_DTPR0 ++ DDR_DTPR1 ++ DDR_DTPR2 ++ DDR_MR0 ++ DDR_MR1 ++ DDR_MR2 ++ DDR_MR3 ++ >; ++}; ++ ++#undef DDR_MEM_NAME ++#undef DDR_MEM_SPEED ++#undef DDR_MEM_SIZE ++#undef DDR_MSTR ++#undef DDR_MRCTRL0 ++#undef DDR_MRCTRL1 ++#undef DDR_DERATEEN ++#undef DDR_DERATEINT ++#undef DDR_PWRCTL ++#undef DDR_PWRTMG ++#undef DDR_HWLPCTL ++#undef DDR_RFSHCTL0 ++#undef DDR_RFSHCTL3 ++#undef DDR_RFSHTMG ++#undef DDR_CRCPARCTL0 ++#undef DDR_DRAMTMG0 ++#undef DDR_DRAMTMG1 ++#undef DDR_DRAMTMG2 ++#undef DDR_DRAMTMG3 ++#undef DDR_DRAMTMG4 ++#undef DDR_DRAMTMG5 ++#undef DDR_DRAMTMG6 ++#undef DDR_DRAMTMG7 ++#undef DDR_DRAMTMG8 ++#undef DDR_DRAMTMG14 ++#undef DDR_ZQCTL0 ++#undef DDR_DFITMG0 ++#undef DDR_DFITMG1 ++#undef DDR_DFILPCFG0 ++#undef DDR_DFIUPD0 ++#undef DDR_DFIUPD1 ++#undef DDR_DFIUPD2 ++#undef DDR_DFIPHYMSTR ++#undef DDR_ADDRMAP1 ++#undef DDR_ADDRMAP2 ++#undef DDR_ADDRMAP3 ++#undef DDR_ADDRMAP4 ++#undef DDR_ADDRMAP5 ++#undef DDR_ADDRMAP6 ++#undef DDR_ADDRMAP9 ++#undef DDR_ADDRMAP10 ++#undef DDR_ADDRMAP11 ++#undef DDR_ODTCFG ++#undef DDR_ODTMAP ++#undef DDR_SCHED ++#undef DDR_SCHED1 ++#undef DDR_PERFHPR1 ++#undef DDR_PERFLPR1 ++#undef DDR_PERFWR1 ++#undef DDR_DBG0 ++#undef DDR_DBG1 ++#undef DDR_DBGCMD ++#undef DDR_POISONCFG ++#undef DDR_PCCFG ++#undef DDR_PCFGR_0 ++#undef DDR_PCFGW_0 ++#undef DDR_PCFGQOS0_0 ++#undef DDR_PCFGQOS1_0 ++#undef DDR_PCFGWQOS0_0 ++#undef DDR_PCFGWQOS1_0 ++#undef DDR_PGCR ++#undef DDR_PTR0 ++#undef DDR_PTR1 ++#undef DDR_PTR2 ++#undef DDR_ACIOCR ++#undef DDR_DXCCR ++#undef DDR_DSGCR ++#undef DDR_DCR ++#undef DDR_DTPR0 ++#undef DDR_DTPR1 ++#undef DDR_DTPR2 ++#undef DDR_MR0 ++#undef DDR_MR1 ++#undef DDR_MR2 ++#undef DDR_MR3 ++#undef DDR_ODTCR ++#undef DDR_ZQ0CR1 ++#undef DDR_DX0GCR ++#undef DDR_DX1GCR +diff --git a/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi b/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi +new file mode 100644 +index 000000000..f3844ce52 +--- /dev/null ++++ b/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi +@@ -0,0 +1,100 @@ ++// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++/* ++ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * STM32MP135C DISCO BOARD configuration ++ * 1x DDR3L 4Gb, 16-bit, 533MHz. ++ * Reference used MT41K256M16TW-107 P from Micron ++ * ++ * DDR type / Platform DDR3/3L ++ * freq 533MHz ++ * width 16 ++ * datasheet 1 ++ * DDR density 4 ++ * timing mode optimized ++ * Scheduling/QoS options : type = 6 ++ * address mapping : RBC ++ * Tc > + 85C : N ++ */ ++#define DDR_MEM_NAME "DDR3-1066 bin F 1x4Gb 533MHz v1.53" ++#define DDR_MEM_SPEED 533000 ++#define DDR_MEM_SIZE 0x20000000 ++ ++#define DDR_MSTR 0x00040401 ++#define DDR_MRCTRL0 0x00000010 ++#define DDR_MRCTRL1 0x00000000 ++#define DDR_DERATEEN 0x00000000 ++#define DDR_DERATEINT 0x00800000 ++#define DDR_PWRCTL 0x00000000 ++#define DDR_PWRTMG 0x00400010 ++#define DDR_HWLPCTL 0x00000000 ++#define DDR_RFSHCTL0 0x00210000 ++#define DDR_RFSHCTL3 0x00000000 ++#define DDR_RFSHTMG 0x0081008B ++#define DDR_CRCPARCTL0 0x00000000 ++#define DDR_DRAMTMG0 0x121B2414 ++#define DDR_DRAMTMG1 0x000A041B ++#define DDR_DRAMTMG2 0x0607080F ++#define DDR_DRAMTMG3 0x0050400C ++#define DDR_DRAMTMG4 0x07040607 ++#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 0x02050105 ++#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_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 0x00000F01 ++#define DDR_SCHED1 0x00000000 ++#define DDR_PERFHPR1 0x00000001 ++#define DDR_PERFLPR1 0x04000200 ++#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 0x00000000 ++#define DDR_PCFGW_0 0x00000000 ++#define DDR_PCFGQOS0_0 0x00100009 ++#define DDR_PCFGQOS1_0 0x00000020 ++#define DDR_PCFGWQOS0_0 0x01100B03 ++#define DDR_PCFGWQOS1_0 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 0xF200011F ++#define DDR_DCR 0x0000000B ++#define DDR_DTPR0 0x36D477D0 ++#define DDR_DTPR1 0x098B00D8 ++#define DDR_DTPR2 0x10023600 ++#define DDR_MR0 0x00000830 ++#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_DX1GCR 0x0000CE81 ++ ++#include "stm32mp13-ddr.dtsi" +diff --git a/fdts/stm32mp13-fw-config-mem-encrypt.dtsi b/fdts/stm32mp13-fw-config-mem-encrypt.dtsi +new file mode 100644 +index 000000000..f426ce1cf +--- /dev/null ++++ b/fdts/stm32mp13-fw-config-mem-encrypt.dtsi +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved ++ */ ++ ++/ { ++ st-mem-encrypt { ++ compatible = "st,mem-encrypt"; ++ memory-ranges = ; ++ }; ++}; +diff --git a/fdts/stm32mp13-fw-config.dtsi b/fdts/stm32mp13-fw-config.dtsi +new file mode 100644 +index 000000000..e6f6e637b +--- /dev/null ++++ b/fdts/stm32mp13-fw-config.dtsi +@@ -0,0 +1,56 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#ifndef DDR_SIZE ++#error "DDR_SIZE is not defined" ++#endif ++ ++#define DDR_NS_BASE STM32MP_DDR_BASE ++#define DDR_SEC_SIZE 0x01e00000 ++#define DDR_SEC_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SEC_SIZE)) ++#define DDR_SHARE_SIZE 0x00200000 ++#define DDR_SHARE_BASE (DDR_SEC_BASE - DDR_SHARE_SIZE) ++#define DDR_NS_SIZE (DDR_SHARE_BASE - DDR_NS_BASE) ++ ++/dts-v1/; ++ ++/ { ++ dtb-registry { ++ compatible = "fconf,dyn_cfg-dtb_registry"; ++ ++ hw-config { ++ load-address = <0x0 STM32MP_HW_CONFIG_BASE>; ++ max-size = ; ++ id = ; ++ }; ++ ++ nt_fw { ++ load-address = <0x0 STM32MP_BL33_BASE>; ++ max-size = ; ++ id = ; ++ }; ++ ++ tos_fw { ++ load-address = <0x0 DDR_SEC_BASE>; ++ max-size = ; ++ id = ; ++ }; ++ }; ++ ++ st-mem-firewall { ++ compatible = "st,mem-firewall"; ++ memory-ranges = < ++ DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR ++ DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE ++ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) ++ DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0>; ++ }; ++}; +diff --git a/fdts/stm32mp13-pinctrl.dtsi b/fdts/stm32mp13-pinctrl.dtsi +new file mode 100644 +index 000000000..5d81f964c +--- /dev/null ++++ b/fdts/stm32mp13-pinctrl.dtsi +@@ -0,0 +1,103 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue ++ */ ++#include ++ ++&pinctrl { ++ i2c4_pins_a: i2c4-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ bias-disable; ++ drive-open-drain; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ sdmmc1_b4_pins_a: sdmmc1-b4-0 { ++ pins { ++ pinmux = , /* SDMMC1_D0 */ ++ , /* SDMMC1_D1 */ ++ , /* SDMMC1_D2 */ ++ , /* SDMMC1_D3 */ ++ ; /* SDMMC1_CMD */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ }; ++ ++ sdmmc1_clk_pins_a: sdmmc1-clk-0 { ++ pins { ++ pinmux = ; /* SDMMC1_CK */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-disable; ++ }; ++ }; ++ ++ sdmmc2_b4_pins_a: sdmmc2-b4-0 { ++ pins { ++ pinmux = , /* SDMMC2_D0 */ ++ , /* SDMMC2_D1 */ ++ , /* SDMMC2_D2 */ ++ , /* SDMMC2_D3 */ ++ ; /* SDMMC2_CMD */ ++ slew-rate = <1>; ++ drive-push-pull; ++ bias-pull-up; ++ }; ++ }; ++ ++ sdmmc2_clk_pins_a: sdmmc2-clk-0 { ++ pins { ++ pinmux = ; /* SDMMC2_CK */ ++ 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; ++ }; ++ }; ++ ++ usart1_pins_a: usart1-0 { ++ pins1 { ++ pinmux = , /* USART1_TX */ ++ ; /* USART1_RTS */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = , /* USART1_RX */ ++ ; /* USART1_CTS_NSS */ ++ bias-pull-up; ++ }; ++ }; ++ ++ uart8_pins_a: uart8-0 { ++ pins1 { ++ pinmux = ; /* UART8_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = ; /* UART8_RX */ ++ bias-pull-up; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp13-ssp-bl2.dtsi b/fdts/stm32mp13-ssp-bl2.dtsi +new file mode 100644 +index 000000000..7de2d743c +--- /dev/null ++++ b/fdts/stm32mp13-ssp-bl2.dtsi +@@ -0,0 +1,52 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved ++ */ ++ ++/ { ++ aliases { ++ /delete-property/ mmc0; ++ }; ++ ++ soc { ++ efuse@5c005000 { ++ cfg0_otp: cfg0_otp@0 { ++ reg = <0x0 0x2>; ++ }; ++ cfg2_otp: cfg2_otp@8 { ++ reg = <0x8 0x4>; ++ }; ++ ssp_otp: cfg9_otp@24 { ++ reg = <0x24 0x4>; ++ }; ++ chip_otp: chip_otp@a0 { ++ reg = <0xa0 0x40>; ++ }; ++ rma_otp: rma_otp@e0 { ++ reg = <0xe0 0x4>; ++ }; ++ pkh_otp: pkh_otp@60 { ++ reg = <0x60 0x20>; ++ }; ++ }; ++ ++#if STM32MP_UART_PROGRAMMER ++ /delete-node/ usb-otg@49000000; ++#endif ++ /delete-node/ spi@58003000; ++ /delete-node/ mmc@58005000; ++ /delete-node/ mmc@58007000; ++#if STM32MP_UART_PROGRAMMER ++ /delete-node/ usbh-ohci@5800c000; ++ /delete-node/ usbh-ehci@5800d000; ++#endif ++#if STM32MP_UART_PROGRAMMER ++ /delete-node/ usbphyc@5a006000; ++#endif ++ ++ pin-controller@50002000 { ++ /delete-node/ sdmmc1-b4-0; ++ /delete-node/ sdmmc2-b4-0; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp131.dtsi b/fdts/stm32mp131.dtsi +new file mode 100644 +index 000000000..bc91c8370 +--- /dev/null ++++ b/fdts/stm32mp131.dtsi +@@ -0,0 +1,579 @@ ++// 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"; ++ nvmem-cells = <&part_number_otp>; ++ nvmem-cell-names = "part_number"; ++ }; ++ }; ++ ++ 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; ++ ++ 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 = ; ++ clocks = <&rcc UART4_K>; ++ resets = <&rcc UART4_R>; ++ 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"; ++ }; ++ ++ usbotg_hs: usb-otg@49000000 { ++ compatible = "st,stm32mp15-hsotg", "snps,dwc2"; ++ reg = <0x49000000 0x40000>; ++ 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"; ++ }; ++ ++ usart1: serial@4c000000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x4c000000 0x400>; ++ interrupts = ; ++ clocks = <&rcc USART1_K>; ++ resets = <&rcc USART1_R>; ++ status = "disabled"; ++ }; ++ ++ usart2: serial@4c001000 { ++ compatible = "st,stm32h7-uart"; ++ reg = <0x4c001000 0x400>; ++ interrupts = ; ++ clocks = <&rcc USART2_K>; ++ resets = <&rcc USART2_R>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@4c004000 { ++ compatible = "st,stm32mp13-i2c"; ++ reg = <0x4c004000 0x400>; ++ interrupt-names = "event", "error"; ++ interrupts-extended = <&exti 23 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rcc I2C3_K>; ++ resets = <&rcc I2C3_R>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x4>; ++ i2c-analog-filter; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@4c005000 { ++ compatible = "st,stm32mp13-i2c"; ++ reg = <0x4c005000 0x400>; ++ interrupt-names = "event", "error"; ++ interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rcc I2C4_K>; ++ resets = <&rcc I2C4_R>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x8>; ++ i2c-analog-filter; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@4c006000 { ++ compatible = "st,stm32mp13-i2c"; ++ reg = <0x4c006000 0x400>; ++ interrupt-names = "event", "error"; ++ interrupts-extended = <&exti 25 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rcc I2C5_K>; ++ resets = <&rcc I2C5_R>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x10>; ++ i2c-analog-filter; ++ status = "disabled"; ++ }; ++ ++ rcc: rcc@50000000 { ++ compatible = "st,stm32mp13-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>; ++ ++ 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>; ++ }; ++ }; ++ ++ exti: interrupt-controller@5000d000 { ++ compatible = "st,stm32mp13-exti", "syscon"; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x5000d000 0x400>; ++ }; ++ ++ syscfg: syscon@50020000 { ++ compatible = "st,stm32mp157-syscfg", "syscon"; ++ reg = <0x50020000 0x400>; ++ clocks = <&rcc SYSCFG>; ++ }; ++ ++ hash: hash@54003000 { ++ compatible = "st,stm32mp13-hash"; ++ reg = <0x54003000 0x400>; ++ clocks = <&rcc HASH1>; ++ resets = <&rcc HASH1_R>; ++ status = "disabled"; ++ }; ++ ++ rng: rng@54004000 { ++ compatible = "st,stm32mp13-rng"; ++ reg = <0x54004000 0x400>; ++ clocks = <&rcc RNG1_K>; ++ resets = <&rcc RNG1_R>; ++ status = "disabled"; ++ }; ++ ++ fmc: memory-controller@58002000 { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "st,stm32mp1-fmc2-ebi"; ++ reg = <0x58002000 0x1000>; ++ clocks = <&rcc FMC_K>; ++ resets = <&rcc FMC_R>; ++ status = "disabled"; ++ ++ ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ ++ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ ++ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ ++ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ ++ <4 0 0x80000000 0x10000000>; /* NAND */ ++ ++ nand-controller@4,0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stm32mp1-fmc2-nfc"; ++ reg = <4 0x00000000 0x1000>, ++ <4 0x08010000 0x1000>, ++ <4 0x08020000 0x1000>, ++ <4 0x01000000 0x1000>, ++ <4 0x09010000 0x1000>, ++ <4 0x09020000 0x1000>; ++ interrupts = ; ++ 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: mmc@58005000 { ++ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; ++ arm,primecell-periphid = <0x20253180>; ++ 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 = <130000000>; ++ status = "disabled"; ++ }; ++ ++ sdmmc2: mmc@58007000 { ++ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; ++ arm,primecell-periphid = <0x20253180>; ++ 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 = <130000000>; ++ status = "disabled"; ++ }; ++ ++ usbh_ohci: usbh-ohci@5800c000 { ++ compatible = "generic-ohci"; ++ reg = <0x5800c000 0x1000>; ++ clocks = <&rcc USBH>; ++ resets = <&rcc USBH_R>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usbh_ehci: usbh-ehci@5800d000 { ++ compatible = "generic-ehci"; ++ reg = <0x5800d000 0x1000>; ++ clocks = <&rcc USBH>; ++ resets = <&rcc USBH_R>; ++ interrupts = ; ++ companion = <&usbh_ohci>; ++ status = "disabled"; ++ }; ++ ++ iwdg2: watchdog@5a002000 { ++ compatible = "st,stm32mp1-iwdg"; ++ reg = <0x5a002000 0x400>; ++ clocks = <&rcc IWDG2>, <&rcc CK_LSI>; ++ clock-names = "pclk", "lsi"; ++ status = "disabled"; ++ }; ++ ++ ddr: ddr@5a003000{ ++ compatible = "st,stm32mp13-ddr"; ++ reg = <0x5a003000 0x550>, <0x5a004000 0x234>; ++ clocks = <&rcc AXIDCG>, ++ <&rcc DDRC1>, ++ <&rcc DDRPHYC>, ++ <&rcc DDRCAPB>, ++ <&rcc DDRPHYCAPB>; ++ clock-names = "axidcg", ++ "ddrc1", ++ "ddrphyc", ++ "ddrcapb", ++ "ddrphycapb"; ++ }; ++ ++ 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>; ++ }; ++ }; ++ ++ iwdg1: watchdog@5c003000 { ++ compatible = "st,stm32mp1-iwdg"; ++ reg = <0x5c003000 0x400>; ++ interrupts = ; ++ clocks = <&rcc IWDG1>, <&rcc CK_LSI>; ++ clock-names = "pclk", "lsi"; ++ status = "disabled"; ++ }; ++ ++ bsec: efuse@5c005000 { ++ compatible = "st,stm32mp13-bsec"; ++ reg = <0x5c005000 0x400>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cfg0_otp: cfg0_otp@0 { ++ reg = <0x0 0x2>; ++ }; ++ part_number_otp: part_number_otp@4 { ++ reg = <0x4 0x2>; ++ }; ++ monotonic_otp: monotonic_otp@10 { ++ reg = <0x10 0x4>; ++ }; ++ nand_otp: cfg9_otp@24 { ++ reg = <0x24 0x4>; ++ }; ++ nand2_otp: cfg10_otp@28 { ++ reg = <0x28 0x4>; ++ }; ++ uid_otp: uid_otp@34 { ++ reg = <0x34 0xc>; ++ }; ++ 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 0xc>; ++ st,non-secure-otp; ++ }; ++ enckey_otp: enckey_otp@170 { ++ reg = <0x170 0x10>; ++ }; ++ }; ++ /* ++ * Break node order to solve dependency probe issue between ++ * pinctrl and exti. ++ */ ++ pinctrl: pin-controller@50002000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "st,stm32mp135-pinctrl"; ++ ranges = <0 0x50002000 0x8400>; ++ 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"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 0 16>; ++ }; ++ ++ gpiob: gpio@50003000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x1000 0x400>; ++ clocks = <&rcc GPIOB>; ++ st,bank-name = "GPIOB"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 16 16>; ++ }; ++ ++ gpioc: gpio@50004000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x2000 0x400>; ++ clocks = <&rcc GPIOC>; ++ st,bank-name = "GPIOC"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 32 16>; ++ }; ++ ++ gpiod: gpio@50005000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x3000 0x400>; ++ clocks = <&rcc GPIOD>; ++ st,bank-name = "GPIOD"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 48 16>; ++ }; ++ ++ gpioe: gpio@50006000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x4000 0x400>; ++ clocks = <&rcc GPIOE>; ++ st,bank-name = "GPIOE"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 64 16>; ++ }; ++ ++ gpiof: gpio@50007000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x5000 0x400>; ++ clocks = <&rcc GPIOF>; ++ st,bank-name = "GPIOF"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 80 16>; ++ }; ++ ++ gpiog: gpio@50008000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x6000 0x400>; ++ clocks = <&rcc GPIOG>; ++ st,bank-name = "GPIOG"; ++ ngpios = <16>; ++ gpio-ranges = <&pinctrl 0 96 16>; ++ }; ++ ++ gpioh: gpio@50009000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x7000 0x400>; ++ clocks = <&rcc GPIOH>; ++ st,bank-name = "GPIOH"; ++ ngpios = <15>; ++ gpio-ranges = <&pinctrl 0 112 15>; ++ }; ++ ++ gpioi: gpio@5000a000 { ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ reg = <0x8000 0x400>; ++ clocks = <&rcc GPIOI>; ++ st,bank-name = "GPIOI"; ++ ngpios = <8>; ++ gpio-ranges = <&pinctrl 0 128 8>; ++ }; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp133.dtsi b/fdts/stm32mp133.dtsi +new file mode 100644 +index 000000000..41d288f39 +--- /dev/null ++++ b/fdts/stm32mp133.dtsi +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp131.dtsi" +diff --git a/fdts/stm32mp135.dtsi b/fdts/stm32mp135.dtsi +new file mode 100644 +index 000000000..c818b6480 +--- /dev/null ++++ b/fdts/stm32mp135.dtsi +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp133.dtsi" +diff --git a/fdts/stm32mp135d-dk-fw-config.dts b/fdts/stm32mp135d-dk-fw-config.dts +new file mode 100644 +index 000000000..21f82422b +--- /dev/null ++++ b/fdts/stm32mp135d-dk-fw-config.dts +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved ++ */ ++ ++#define DDR_SIZE 0x20000000 /* 512MB */ ++#include "stm32mp13-fw-config.dtsi" +diff --git a/fdts/stm32mp135d-dk.dts b/fdts/stm32mp135d-dk.dts +new file mode 100644 +index 000000000..debf5cf0a +--- /dev/null ++++ b/fdts/stm32mp135d-dk.dts +@@ -0,0 +1,320 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include ++#include "stm32mp135.dtsi" ++#include "stm32mp13xd.dtsi" ++#include "stm32mp13-ddr3-1x4Gb-1066-binF.dtsi" ++#include "stm32mp13-pinctrl.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP135D-DK Discovery Board"; ++ compatible = "st,stm32mp135d-dk", "st,stm32mp135"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart1; ++ serial2 = &uart8; ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ 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; ++ }; ++ ++ v3v3_ao: v3v3_ao { ++ compatible = "regulator-fixed"; ++ regulator-name = "v3v3_ao"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++}; ++ ++&bsec { ++ board_id: board_id@f0 { ++ reg = <0xf0 0x4>; ++ st,non-secure-otp; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vddcpu>; ++}; ++ ++&hash { ++ 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"; ++ ++ pmic: stpmic@33 { ++ compatible = "st,stpmic1"; ++ reg = <0x33>; ++ ++ status = "okay"; ++ ++ regulators { ++ compatible = "st,stpmic1-regulators"; ++ buck1-supply = <&vin>; ++ buck2-supply = <&vin>; ++ buck3-supply = <&vin>; ++ buck4-supply = <&vin>; ++ ldo1-supply = <&vin>; ++ ldo4-supply = <&vin>; ++ ldo5-supply = <&vin>; ++ ldo6-supply = <&vin>; ++ vref_ddr-supply = <&vin>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&v3v3_ao>; ++ ++ vddcpu: buck1 { ++ regulator-name = "vddcpu"; ++ regulator-min-microvolt = <1250000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd_ddr: buck2 { ++ regulator-name = "vdd_ddr"; ++ regulator-min-microvolt = <1350000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd: buck3 { ++ regulator-name = "vdd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ st,mask-reset; ++ regulator-over-current-protection; ++ }; ++ ++ vddcore: buck4 { ++ regulator-name = "vddcore"; ++ regulator-min-microvolt = <1250000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd_adc: ldo1 { ++ regulator-name = "vdd_adc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ 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 = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ }; ++ ++ v1v8_periph: ldo6 { ++ regulator-name = "v1v8_periph"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ vref_ddr: vref_ddr { ++ regulator-name = "vref_ddr"; ++ regulator-always-on; ++ }; ++ ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ }; ++ ++ v3v3_sw: pwr_sw2 { ++ regulator-name = "v3v3_sw"; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++}; ++ ++&iwdg2 { ++ timeout-sec = <32>; ++ status = "okay"; ++}; ++ ++&pwr_regulators { ++ vdd-supply = <&vdd>; ++ vdd_3v3_usbfs-supply = <&vdd_usb>; ++}; ++ ++&rcc { ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MLAHBS_PLL3 ++ CLK_CKPER_HSE ++ CLK_RTC_LSE ++ CLK_SDMMC1_PLL4P ++ CLK_SDMMC2_PLL4P ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_I2C4_HSI ++ CLK_USBO_USBPHY ++ CLK_I2C12_HSI ++ CLK_UART2_HSI ++ CLK_UART4_HSI ++ >; ++ ++ st,clkdiv = < ++ DIV(DIV_AXI, 0) ++ DIV(DIV_MLAHB, 0) ++ DIV(DIV_APB1, 1) ++ DIV(DIV_APB2, 1) ++ DIV(DIV_APB3, 1) ++ DIV(DIV_APB4, 1) ++ DIV(DIV_APB5, 2) ++ DIV(DIV_APB6, 1) ++ DIV(DIV_RTC, 0) ++ >; ++ ++ st,pll_vco { ++ pll1_vco_1300Mhz: pll1-vco-1300Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 80 >; ++ frac = < 0x800 >; ++ }; ++ ++ pll2_vco_1066Mhz: pll2-vco-1066Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 65 >; ++ frac = < 0x1400 >; ++ }; ++ ++ pll3_vco_417_8Mhz: pll2-vco-417_8Mhz { ++ src = < CLK_PLL3_HSE >; ++ divmn = < 1 33 >; ++ frac = < 0x1a04 >; ++ }; ++ ++ pll4_vco_600Mhz: pll2-vco-600Mhz { ++ src = < CLK_PLL4_HSE >; ++ divmn = < 1 49 >; ++ }; ++ }; ++ ++ /* VCO = 1300.0 MHz => P = 650 (CPU) */ ++ pll1:st,pll@0 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ ++ st,pll = < &pll1_cfg1 >; ++ ++ pll1_cfg1: pll1_cfg1 { ++ st,pll_vco = < &pll1_vco_1300Mhz >; ++ st,pll_div_pqr = < 0 1 1 >; ++ }; ++ }; ++ ++ /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ ++ pll2:st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ ++ st,pll = < &pll2_cfg1 >; ++ ++ pll2_cfg1: pll2_cfg1 { ++ st,pll_vco = < &pll2_vco_1066Mhz >; ++ st,pll_div_pqr = < 1 1 0 >; ++ }; ++ }; ++ ++ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 209 */ ++ pll3:st,pll@2 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ ++ st,pll = < &pll3_cfg1 >; ++ ++ pll3_cfg1: pll3_cfg1 { ++ st,pll_vco = < &pll3_vco_417_8Mhz >; ++ st,pll_div_pqr = < 1 16 1 >; ++ }; ++ }; ++ ++ /* VCO = 600.0 MHz => P = 50, Q = 10, R = 100 */ ++ pll4:st,pll@3 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ ++ st,pll = < &pll4_cfg1 >; ++ ++ pll4_cfg1: pll4_cfg1 { ++ st,pll_vco = < &pll4_vco_600Mhz >; ++ st,pll_div_pqr = < 11 59 5 >; ++ }; ++ }; ++}; ++ ++&rng { ++ status = "okay"; ++}; ++ ++&sdmmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>; ++ disable-wp; ++ st,neg-edge; ++ bus-width = <4>; ++ vmmc-supply = <&vdd_sd>; ++ status = "okay"; ++}; ++ ++&uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_pins_a>; ++ status = "okay"; ++}; ++ ++&uart8 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart8_pins_a>; ++ status = "disabled"; ++}; ++ ++&usart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usart1_pins_a>; ++ uart-has-rtscts; ++ status = "disabled"; ++}; +diff --git a/fdts/stm32mp135f-dk-fw-config.dts b/fdts/stm32mp135f-dk-fw-config.dts +new file mode 100644 +index 000000000..1bad8e2fe +--- /dev/null ++++ b/fdts/stm32mp135f-dk-fw-config.dts +@@ -0,0 +1,8 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved ++ */ ++ ++#define DDR_SIZE 0x20000000 /* 512MB */ ++#include "stm32mp13-fw-config.dtsi" ++#include "stm32mp13-fw-config-mem-encrypt.dtsi" +diff --git a/fdts/stm32mp135f-dk.dts b/fdts/stm32mp135f-dk.dts +new file mode 100644 +index 000000000..9dce65f0d +--- /dev/null ++++ b/fdts/stm32mp135f-dk.dts +@@ -0,0 +1,329 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2021 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include ++#include "stm32mp135.dtsi" ++#include "stm32mp13xf.dtsi" ++#include "stm32mp13-ddr3-1x4Gb-1066-binF.dtsi" ++#include "stm32mp13-pinctrl.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP135F-DK Discovery Board"; ++ compatible = "st,stm32mp135f-dk", "st,stm32mp135"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart1; ++ serial2 = &uart8; ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ 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; ++ }; ++ ++ v3v3_ao: v3v3_ao { ++ compatible = "regulator-fixed"; ++ regulator-name = "v3v3_ao"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++}; ++ ++&bsec { ++ board_id: board_id@f0 { ++ reg = <0xf0 0x4>; ++ st,non-secure-otp; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vddcpu>; ++}; ++ ++&hash { ++ 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"; ++ ++ pmic: stpmic@33 { ++ compatible = "st,stpmic1"; ++ reg = <0x33>; ++ ++ status = "okay"; ++ ++ regulators { ++ compatible = "st,stpmic1-regulators"; ++ buck1-supply = <&vin>; ++ buck2-supply = <&vin>; ++ buck3-supply = <&vin>; ++ buck4-supply = <&vin>; ++ ldo1-supply = <&vin>; ++ ldo4-supply = <&vin>; ++ ldo5-supply = <&vin>; ++ ldo6-supply = <&vin>; ++ vref_ddr-supply = <&vin>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&v3v3_ao>; ++ ++ vddcpu: buck1 { ++ regulator-name = "vddcpu"; ++ regulator-min-microvolt = <1250000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd_ddr: buck2 { ++ regulator-name = "vdd_ddr"; ++ regulator-min-microvolt = <1350000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd: buck3 { ++ regulator-name = "vdd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ st,mask-reset; ++ regulator-over-current-protection; ++ }; ++ ++ vddcore: buck4 { ++ regulator-name = "vddcore"; ++ regulator-min-microvolt = <1250000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ }; ++ ++ vdd_adc: ldo1 { ++ regulator-name = "vdd_adc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ 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 = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ }; ++ ++ v1v8_periph: ldo6 { ++ regulator-name = "v1v8_periph"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ vref_ddr: vref_ddr { ++ regulator-name = "vref_ddr"; ++ regulator-always-on; ++ }; ++ ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ }; ++ ++ v3v3_sw: pwr_sw2 { ++ regulator-name = "v3v3_sw"; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++}; ++ ++&iwdg2 { ++ timeout-sec = <32>; ++ status = "okay"; ++}; ++ ++&pka { ++ status = "okay"; ++}; ++ ++&pwr_regulators { ++ vdd-supply = <&vdd>; ++ vdd_3v3_usbfs-supply = <&vdd_usb>; ++}; ++ ++&rcc { ++ st,clksrc = < ++ CLK_MPU_PLL1P ++ CLK_AXI_PLL2P ++ CLK_MLAHBS_PLL3 ++ CLK_CKPER_HSE ++ CLK_RTC_LSE ++ CLK_SDMMC1_PLL4P ++ CLK_SDMMC2_PLL4P ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_I2C4_HSI ++ CLK_USBO_USBPHY ++ CLK_I2C12_HSI ++ CLK_UART2_HSI ++ CLK_UART4_HSI ++ CLK_SAES_AXI ++ >; ++ ++ st,clkdiv = < ++ DIV(DIV_AXI, 0) ++ DIV(DIV_MLAHB, 0) ++ DIV(DIV_APB1, 1) ++ DIV(DIV_APB2, 1) ++ DIV(DIV_APB3, 1) ++ DIV(DIV_APB4, 1) ++ DIV(DIV_APB5, 2) ++ DIV(DIV_APB6, 1) ++ DIV(DIV_RTC, 0) ++ >; ++ ++ st,pll_vco { ++ pll1_vco_1300Mhz: pll1-vco-1300Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 80 >; ++ frac = < 0x800 >; ++ }; ++ ++ pll2_vco_1066Mhz: pll2-vco-1066Mhz { ++ src = < CLK_PLL12_HSE >; ++ divmn = < 2 65 >; ++ frac = < 0x1400 >; ++ }; ++ ++ pll3_vco_417_8Mhz: pll2-vco-417_8Mhz { ++ src = < CLK_PLL3_HSE >; ++ divmn = < 1 33 >; ++ frac = < 0x1a04 >; ++ }; ++ ++ pll4_vco_600Mhz: pll2-vco-600Mhz { ++ src = < CLK_PLL4_HSE >; ++ divmn = < 1 49 >; ++ }; ++ }; ++ ++ /* VCO = 1300.0 MHz => P = 650 (CPU) */ ++ pll1:st,pll@0 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <0>; ++ ++ st,pll = < &pll1_cfg1 >; ++ ++ pll1_cfg1: pll1_cfg1 { ++ st,pll_vco = < &pll1_vco_1300Mhz >; ++ st,pll_div_pqr = < 0 1 1 >; ++ }; ++ }; ++ ++ /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ ++ pll2:st,pll@1 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <1>; ++ ++ st,pll = < &pll2_cfg1 >; ++ ++ pll2_cfg1: pll2_cfg1 { ++ st,pll_vco = < &pll2_vco_1066Mhz >; ++ st,pll_div_pqr = < 1 1 0 >; ++ }; ++ }; ++ ++ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 209 */ ++ pll3:st,pll@2 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <2>; ++ ++ st,pll = < &pll3_cfg1 >; ++ ++ pll3_cfg1: pll3_cfg1 { ++ st,pll_vco = < &pll3_vco_417_8Mhz >; ++ st,pll_div_pqr = < 1 16 1 >; ++ }; ++ }; ++ ++ /* VCO = 600.0 MHz => P = 50, Q = 10, R = 100 */ ++ pll4:st,pll@3 { ++ compatible = "st,stm32mp1-pll"; ++ reg = <3>; ++ ++ st,pll = < &pll4_cfg1 >; ++ ++ pll4_cfg1: pll4_cfg1 { ++ st,pll_vco = < &pll4_vco_600Mhz >; ++ st,pll_div_pqr = < 11 59 5 >; ++ }; ++ }; ++}; ++ ++&rng { ++ status = "okay"; ++}; ++ ++&saes { ++ status = "okay"; ++}; ++ ++&sdmmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>; ++ disable-wp; ++ st,neg-edge; ++ bus-width = <4>; ++ vmmc-supply = <&vdd_sd>; ++ status = "okay"; ++}; ++ ++&uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_pins_a>; ++ status = "okay"; ++}; ++ ++&uart8 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart8_pins_a>; ++ status = "disabled"; ++}; ++ ++&usart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usart1_pins_a>; ++ uart-has-rtscts; ++ status = "disabled"; ++}; +diff --git a/fdts/stm32mp13xa.dtsi b/fdts/stm32mp13xa.dtsi +new file mode 100644 +index 000000000..20e52cd27 +--- /dev/null ++++ b/fdts/stm32mp13xa.dtsi +@@ -0,0 +1,5 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ +diff --git a/fdts/stm32mp13xc.dtsi b/fdts/stm32mp13xc.dtsi +new file mode 100644 +index 000000000..94ba3bc71 +--- /dev/null ++++ b/fdts/stm32mp13xc.dtsi +@@ -0,0 +1,27 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++#include "stm32mp13xa.dtsi" ++ ++/ { ++ soc { ++ saes: saes@54005000 { ++ compatible = "st,stm32-saes"; ++ reg = <0x54005000 0x400>; ++ clocks = <&rcc SAES_K>; ++ resets = <&rcc SAES_R>; ++ status = "disabled"; ++ }; ++ ++ pka: pka@54006000 { ++ compatible = "st,stm32-pka64"; ++ reg = <0x54006000 0x2000>; ++ clocks = <&rcc PKA>; ++ resets = <&rcc PKA_R>; ++ status = "disabled"; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp13xd.dtsi b/fdts/stm32mp13xd.dtsi +new file mode 100644 +index 000000000..aa8e23568 +--- /dev/null ++++ b/fdts/stm32mp13xd.dtsi +@@ -0,0 +1,5 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2021 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ +diff --git a/fdts/stm32mp13xf.dtsi b/fdts/stm32mp13xf.dtsi +new file mode 100644 +index 000000000..ca155ac50 +--- /dev/null ++++ b/fdts/stm32mp13xf.dtsi +@@ -0,0 +1,26 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2021 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++#include "stm32mp13xd.dtsi" ++ ++/ { ++ soc { ++ saes: saes@54005000 { ++ compatible = "st,stm32-saes"; ++ reg = <0x54005000 0x400>; ++ clocks = <&rcc SAES_K>; ++ resets = <&rcc SAES_R>; ++ status = "disabled"; ++ }; ++ ++ pka: pka@54006000 { ++ compatible = "st,stm32-pka64"; ++ reg = <0x54006000 0x2000>; ++ clocks = <&rcc PKA>; ++ resets = <&rcc PKA_R>; ++ status = "disabled"; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp15-bl2.dtsi b/fdts/stm32mp15-bl2.dtsi +index 074414bb2..66067a40a 100644 +--- a/fdts/stm32mp15-bl2.dtsi ++++ b/fdts/stm32mp15-bl2.dtsi +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved ++ * Copyright (C) STMicroelectronics 2020-2022 - All Rights Reserved + */ + + / { +@@ -68,7 +68,6 @@ + }; + }; + +-#if !STM32MP_USE_STM32IMAGE + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) +@@ -85,7 +84,42 @@ + hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; ++#if TRUSTED_BOARD_BOOT ++ t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c"; ++ t_boot_fw_cert_uuid = "d6e269ea-5d63-e411-8d8c-9fbabe9956a5"; ++ tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04"; ++ nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859"; ++ tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d"; ++ nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7"; ++#endif + }; + }; +-#endif /* !STM32MP_USE_STM32IMAGE */ ++ ++#if TRUSTED_BOARD_BOOT ++ tb_fw-config { ++ compatible = "arm,tb_fw"; ++ ++ /* Disable authentication for development */ ++ disable_auth = <0x0>; ++ ++ /* ++ * The following two entries are placeholders for Mbed TLS ++ * heap information. ++ */ ++ mbedtls_heap_addr = <0x0 0x0>; ++ mbedtls_heap_size = <0x0>; ++ }; ++ ++#include "cot_descriptors.dtsi" ++#endif ++}; ++ ++&rcc { ++ /* 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>; ++ }; + }; +diff --git a/fdts/stm32mp15-bl32.dtsi b/fdts/stm32mp15-bl32.dtsi +index ca4bb3ea5..0e198f0db 100644 +--- a/fdts/stm32mp15-bl32.dtsi ++++ b/fdts/stm32mp15-bl32.dtsi +@@ -22,7 +22,6 @@ + /delete-node/ spi@58003000; + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; +- /delete-node/ usbphyc@5a006000; + /delete-node/ spi@5c001000; + /delete-node/ stgen@5c008000; + /delete-node/ i2c@5c009000; +diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi +index e5efd9256..2e09a613c 100644 +--- a/fdts/stm32mp15-ddr.dtsi ++++ b/fdts/stm32mp15-ddr.dtsi +@@ -109,19 +109,4 @@ + DDR_MR2 + DDR_MR3 + >; +- +- st,phy-cal = < +- DDR_DX0DLLCR +- DDR_DX0DQTR +- DDR_DX0DQSTR +- DDR_DX1DLLCR +- DDR_DX1DQTR +- DDR_DX1DQSTR +- DDR_DX2DLLCR +- DDR_DX2DQTR +- DDR_DX2DQSTR +- DDR_DX3DLLCR +- DDR_DX3DQTR +- DDR_DX3DQSTR +- >; + }; +diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +index c6d6434a9..81c52b67f 100644 +--- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi ++++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +@@ -100,20 +100,8 @@ + #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 0x0000CE80 +-#define DDR_DX2DLLCR 0x40000000 +-#define DDR_DX2DQTR 0xFFFFFFFF +-#define DDR_DX2DQSTR 0x3DB02000 + #define DDR_DX3GCR 0x0000CE80 +-#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 9614ab4c8..83867e512 100644 +--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi ++++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +@@ -100,20 +100,8 @@ + #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-fw-config.dtsi b/fdts/stm32mp15-fw-config.dtsi +index 8aece289a..ef5808183 100644 +--- a/fdts/stm32mp15-fw-config.dtsi ++++ b/fdts/stm32mp15-fw-config.dtsi +@@ -14,14 +14,14 @@ + + #define DDR_NS_BASE STM32MP_DDR_BASE + #ifdef AARCH32_SP_OPTEE +-/* OP-TEE reserved shared memory: located at DDR top */ +-#define DDR_SHARE_SIZE STM32MP_DDR_SHMEM_SIZE +-#define DDR_SHARE_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE)) +-/* OP-TEE secure memory: located right below OP-TEE reserved shared memory */ +-#define DDR_SEC_SIZE STM32MP_DDR_S_SIZE +-#define DDR_SEC_BASE (DDR_SHARE_BASE - DDR_SEC_SIZE) +-#define DDR_NS_SIZE (DDR_SEC_BASE - DDR_NS_BASE) +-#else /* !AARCH32_SP_OPTEE */ ++/* OP-TEE secure memory: located at DDR top */ ++#define DDR_SEC_SIZE 0x01e00000 ++#define DDR_SEC_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SEC_SIZE)) ++/* OP-TEE reserved shared memory: located right below OP-TEE secure memory */ ++#define DDR_SHARE_SIZE 0x00200000 ++#define DDR_SHARE_BASE (DDR_SEC_BASE - DDR_SHARE_SIZE) ++#define DDR_NS_SIZE (DDR_SHARE_BASE - DDR_NS_BASE) ++#else /* AARCH32_SP_OPTEE */ + #define DDR_NS_SIZE DDR_SIZE + #endif /* AARCH32_SP_OPTEE */ + +@@ -69,9 +69,9 @@ + #ifdef AARCH32_SP_OPTEE + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR +- DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0 + DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE +- TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; ++ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) ++ DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0>; + #else + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; +diff --git a/fdts/stm32mp15-ssp-bl2.dtsi b/fdts/stm32mp15-ssp-bl2.dtsi +new file mode 100644 +index 000000000..eac8036bb +--- /dev/null ++++ b/fdts/stm32mp15-ssp-bl2.dtsi +@@ -0,0 +1,98 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved ++ */ ++ ++/ { ++ cpus { ++ /delete-node/ cpu@1; ++ }; ++ ++#if STM32MP_USB_PROGRAMMER ++ aliases { ++ /delete-property/ serial1; ++ /delete-property/ serial2; ++ /delete-property/ serial3; ++ }; ++#endif ++ ++ /delete-node/ cpu0_opp_table; ++ /delete-node/ psci; ++ ++ soc { ++ efuse@5c005000 { ++ cfg2_otp: cfg2_otp@8 { ++ reg = <0x8 0x4>; ++ }; ++ ++ ssp_otp: ssp_otp@20 { ++ reg = <0x20 0x4>; ++ }; ++ ++ chip_otp: chip_otp@a0 { ++ reg = <0xa0 0x40>; ++ }; ++ ++ rma_otp: rma_otp@e0 { ++ reg = <0xe0 0x4>; ++ }; ++ }; ++ ++ /delete-node/ timer@40006000; ++#if STM32MP_USB_PROGRAMMER ++ /delete-node/ serial@4000e000; ++ /delete-node/ serial@4000f000; ++ /delete-node/ serial@40011000; ++ /delete-node/ serial@40018000; ++ /delete-node/ serial@40019000; ++ /delete-node/ serial@44003000; ++#endif ++ /delete-node/ timer@44006000; ++#if STM32MP_UART_PROGRAMMER ++ /delete-node/ usb-otg@49000000; ++#endif ++ /delete-node/ pwr_mcu@50001014; ++ /delete-node/ cryp@54001000; ++ /delete-node/ rng@54003000; ++ /delete-node/ memory-controller@58002000; ++ /delete-node/ spi@58003000; ++ /delete-node/ mmc@58005000; ++ /delete-node/ mmc@58007000; ++ /delete-node/ ddr@5a003000; ++#if STM32MP_UART_PROGRAMMER ++ /delete-node/ usbphyc@5a006000; ++#endif ++#if STM32MP_USB_PROGRAMMER ++ /delete-node/ serial@5c000000; ++#endif ++ /delete-node/ spi@5c001000; ++ /delete-node/ rtc@5c004000; ++ /delete-node/ etzpc@5c007000; ++ /delete-node/ stgen@5c008000; ++ /delete-node/ i2c@5c009000; ++ /delete-node/ tamp@5c00a000; ++ ++ pin-controller@50002000 { ++ /delete-node/ fmc-0; ++ /delete-node/ qspi-clk-0; ++ /delete-node/ qspi-bk1-0; ++ /delete-node/ qspi-bk2-0; ++ /delete-node/ sdmmc1-b4-0; ++ /delete-node/ sdmmc1-dir-0; ++ /delete-node/ sdmmc2-b4-0; ++ /delete-node/ sdmmc2-b4-1; ++ /delete-node/ sdmmc2-d47-0; ++#if STM32MP_USB_PROGRAMMER ++ /delete-node/ uart7-0; ++ /delete-node/ uart7-1; ++ /delete-node/ usart2-0; ++ /delete-node/ usart3-0; ++ /delete-node/ usart3-1; ++#endif ++#if STM32MP_UART_PROGRAMMER ++ /delete-node/ usbotg_hs-0; ++ /delete-node/ usbotg-fs-dp-dm-0; ++#endif ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi +index ca93f0c35..b2fd7f875 100644 +--- a/fdts/stm32mp151.dtsi ++++ b/fdts/stm32mp151.dtsi +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ + #include +@@ -19,9 +19,19 @@ + 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; ++ }; ++ + psci { + compatible = "arm,psci-1.0"; + method = "smc"; +@@ -87,7 +97,7 @@ + usart2: serial@4000e000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000e000 0x400>; +- interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; + status = "disabled"; +@@ -96,7 +106,7 @@ + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; +- interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; + status = "disabled"; +@@ -115,7 +125,7 @@ + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; +- interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; + status = "disabled"; +@@ -139,7 +149,7 @@ + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; +- interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; + status = "disabled"; +@@ -148,7 +158,7 @@ + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; +- interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; + status = "disabled"; +@@ -157,7 +167,7 @@ + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; +- interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; + status = "disabled"; +@@ -180,7 +190,7 @@ + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; +- interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = ; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; + g-tx-fifo-size = <256 16 16 16 16 16 16 16>; +@@ -190,7 +200,7 @@ + }; + + rcc: rcc@50000000 { +- compatible = "st,stm32mp1-rcc", "syscon"; ++ compatible = "st,stm32mp1-rcc-secure", "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; +@@ -316,6 +326,8 @@ + interrupts = ; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; ++ #address-cells = <1>; ++ #size-cells = <0>; + status = "disabled"; + }; + +@@ -457,20 +469,47 @@ + 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>; ++ }; ++ ethernet_mac_address: mac@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 { +diff --git a/fdts/stm32mp153.dtsi b/fdts/stm32mp153.dtsi +index 0a0bb8dc1..617380a52 100644 +--- a/fdts/stm32mp153.dtsi ++++ b/fdts/stm32mp153.dtsi +@@ -14,6 +14,7 @@ + reg = <1>; + clocks = <&rcc CK_MPU>; + clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + }; + }; +diff --git a/fdts/stm32mp157a-avenger96.dts b/fdts/stm32mp157a-avenger96.dts +index b967736e4..5ebc1a998 100644 +--- a/fdts/stm32mp157a-avenger96.dts ++++ b/fdts/stm32mp157a-avenger96.dts +@@ -10,9 +10,11 @@ + /dts-v1/; + + #include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxac-pinctrl.dtsi" + #include ++#include + #include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + + / { +@@ -35,6 +37,22 @@ + }; + }; + ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; +@@ -165,7 +183,6 @@ + &iwdg2 { + timeout-sec = <32>; + status = "okay"; +- secure-status = "okay"; + }; + + &pwr_regulators { +@@ -174,7 +191,7 @@ + }; + + &rcc { +- secure-status = "disabled"; ++ compatible = "st,stm32mp1-rcc", "syscon"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P +diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts +index a73bef8ee..5d5c0a5f7 100644 +--- a/fdts/stm32mp157a-dk1.dts ++++ b/fdts/stm32mp157a-dk1.dts +@@ -7,9 +7,11 @@ + /dts-v1/; + + #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"; +@@ -25,3 +27,19 @@ + stdout-path = "serial0:115200n8"; + }; + }; ++ ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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-ed1.dts b/fdts/stm32mp157a-ed1.dts +new file mode 100644 +index 000000000..1527b642a +--- /dev/null ++++ b/fdts/stm32mp157a-ed1.dts +@@ -0,0 +1,38 @@ ++// 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"; ++ }; ++}; ++ ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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..3cb35698a +--- /dev/null ++++ b/fdts/stm32mp157a-ev1.dts +@@ -0,0 +1,24 @@ ++// 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 { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ }; ++}; ++ +diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts +index be8300e9e..ff5c4509f 100644 +--- a/fdts/stm32mp157c-dk2.dts ++++ b/fdts/stm32mp157c-dk2.dts +@@ -11,6 +11,7 @@ + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxac-pinctrl.dtsi" + #include "stm32mp15xx-dkx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; +@@ -31,3 +32,20 @@ + &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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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 11e0a6111..55d16fa31 100644 +--- a/fdts/stm32mp157c-ed1.dts ++++ b/fdts/stm32mp157c-ed1.dts +@@ -9,8 +9,8 @@ + #include "stm32mp15xc.dtsi" + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxaa-pinctrl.dtsi" +-#include +-#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C eval daughter"; +@@ -19,325 +19,26 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; +- +- memory@c0000000 { +- device_type = "memory"; +- reg = <0xC0000000 0x40000000>; +- }; +- +- aliases { +- serial0 = &uart4; +- }; +-}; +- +-&bsec { +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- status = "okay"; +- secure-status = "okay"; +- }; +-}; +- +-&clk_hse { +- st,digbypass; +-}; +- +-&cpu0 { +- cpu-supply = <&vddcore>; +-}; +- +-&cpu1 { +- cpu-supply = <&vddcore>; + }; + + &cryp1 { + status = "okay"; + }; + +-&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"; +- +- pmic: stpmic@33 { +- compatible = "st,stpmic1"; +- reg = <0x33>; +- interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; +- interrupt-controller; +- #interrupt-cells = <2>; +- status = "okay"; +- +- 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"; +- 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"; +- }; +- +- 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; +- }; +- +- 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>; +- }; +- }; +- +- onkey { +- compatible = "st,stpmic1-onkey"; +- power-off-time-sec = <10>; +- status = "okay"; +- }; +- +- watchdog { +- compatible = "st,stpmic1-wdt"; +- status = "disabled"; +- }; +- }; +-}; +- +-&iwdg2 { +- timeout-sec = <32>; +- status = "okay"; +-}; +- +-&pwr_regulators { +- vdd-supply = <&vdd>; +- vdd_3v3_usbfs-supply = <&vdd_usb>; +-}; +- +-&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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_PLL4P +- CLK_SDMMC12_PLL4P +- CLK_DSI_DSIPLL +- CLK_STGEN_HSE +- CLK_USBPHY_HSE +- CLK_SPI2S1_PLL3Q +- CLK_SPI2S23_PLL3Q +- CLK_SPI45_HSI +- CLK_SPI6_HSI +- CLK_I2C46_HSI +- CLK_SDMMC3_PLL4P +- CLK_USBO_USBPHY +- CLK_ADC_CKPER +- CLK_CEC_LSE +- CLK_I2C12_HSI +- CLK_I2C35_HSI +- CLK_UART1_HSI +- CLK_UART24_HSI +- CLK_UART35_HSI +- CLK_UART6_HSI +- CLK_UART78_HSI +- CLK_SPDIF_PLL4P +- CLK_FDCAN_PLL4R +- CLK_SAI1_PLL3Q +- CLK_SAI2_PLL3Q +- CLK_SAI3_PLL3Q +- CLK_SAI4_PLL3Q +- CLK_RNG1_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)>; +- }; +-}; +- +-&rng1 { +- status = "okay"; +-}; +- +-&rtc { +- 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; +- 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"; +-}; +- +-&uart4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart4_pins_a>; +- status = "okay"; +-}; +diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts +index 02840a2e5..9c9b04156 100644 +--- a/fdts/stm32mp157c-ev1.dts ++++ b/fdts/stm32mp157c-ev1.dts +@@ -6,6 +6,7 @@ + /dts-v1/; + + #include "stm32mp157c-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" + + / { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; +@@ -16,48 +17,7 @@ + }; + + aliases { ++ serial0 = &uart4; + serial1 = &usart3; + }; + }; +- +-&fmc { +- pinctrl-names = "default"; +- pinctrl-0 = <&fmc_pins_a>; +- status = "okay"; +- +- nand-controller@4,0 { +- status = "okay"; +- +- 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>; +- 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>; +- }; +-}; +- +-&usart3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&usart3_pins_b>; +- uart-has-rtscts; +- status = "disabled"; +-}; +diff --git a/fdts/stm32mp157c-odyssey-som.dtsi b/fdts/stm32mp157c-odyssey-som.dtsi +index 6bed33968..2fede6276 100644 +--- a/fdts/stm32mp157c-odyssey-som.dtsi ++++ b/fdts/stm32mp157c-odyssey-som.dtsi +@@ -205,7 +205,7 @@ + }; + + &rcc { +- secure-status = "disabled"; ++ compatible = "st,stm32mp1-rcc", "syscon"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P +diff --git a/fdts/stm32mp157d-dk1.dts b/fdts/stm32mp157d-dk1.dts +new file mode 100644 +index 000000000..79297b831 +--- /dev/null ++++ b/fdts/stm32mp157d-dk1.dts +@@ -0,0 +1,45 @@ ++// 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 "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157D-DK1 Discovery Board"; ++ compatible = "st,stm32mp157d-dk1", "st,stm32mp157"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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..2c67ec0ac +--- /dev/null ++++ b/fdts/stm32mp157d-ed1.dts +@@ -0,0 +1,39 @@ ++// 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"; ++ }; ++}; ++ ++ ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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..4a40f5fe5 +--- /dev/null ++++ b/fdts/stm32mp157d-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 "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 { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ }; ++}; +diff --git a/fdts/stm32mp157f-dk2.dts b/fdts/stm32mp157f-dk2.dts +new file mode 100644 +index 000000000..680ca0f6e +--- /dev/null ++++ b/fdts/stm32mp157f-dk2.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 "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"; ++ }; ++}; ++ ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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..1aa26cdbb +--- /dev/null ++++ b/fdts/stm32mp157f-ed1.dts +@@ -0,0 +1,43 @@ ++// 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"; ++ }; ++}; ++ ++&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_NS_R_S_W, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, 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..caf5dfe11 +--- /dev/null ++++ b/fdts/stm32mp157f-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 "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 { ++ serial0 = &uart4; ++ 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 +index b06a55a2f..f729b0d1b 100644 +--- a/fdts/stm32mp15xc.dtsi ++++ b/fdts/stm32mp15xc.dtsi +@@ -4,6 +4,8 @@ + * Author: Alexandre Torgue for STMicroelectronics. + */ + ++#include "stm32mp15xa.dtsi" ++ + / { + soc { + cryp1: cryp@54001000 { +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..ae4a14af6 +--- /dev/null ++++ b/fdts/stm32mp15xf.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 "stm32mp15xd.dtsi" ++ ++/ { ++ soc { ++ cryp1: cryp@54001000 { ++ compatible = "st,stm32mp1-cryp"; ++ reg = <0x54001000 0x400>; ++ interrupts = ; ++ clocks = <&rcc CRYP1>; ++ resets = <&rcc CRYP1_R>; ++ status = "disabled"; ++ }; ++ }; ++}; +diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi +index 9cc5368d8..c878f6368 100644 +--- a/fdts/stm32mp15xx-dkx.dtsi ++++ b/fdts/stm32mp15xx-dkx.dtsi +@@ -1,10 +1,11 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + + #include ++#include + #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + + / { +@@ -131,10 +132,9 @@ + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; +- regulator-min-microvolt = <500000>; +- regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; ++ st,regulator-sink-source; + }; + + vdd_usb: ldo4 { +@@ -160,7 +160,6 @@ + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; +- regulator-over-current-protection; + }; + + bst_out: boost { +@@ -181,17 +180,25 @@ + + &iwdg2 { + timeout-sec = <32>; ++ secure-timeout-sec = <5>; + status = "okay"; +- secure-status = "okay"; + }; + + &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 { +- secure-status = "disabled"; ++ st,hsi-cal; ++ st,csi-cal; ++ st,cal-sec = <60>; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P +@@ -249,21 +256,13 @@ + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q +- CLK_RNG1_LSI ++ CLK_RNG1_CSI + 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"; +@@ -307,7 +306,9 @@ + }; + + &timers15 { +- secure-status = "okay"; ++ status = "okay"; ++ st,hsi-cal-input = <7>; ++ st,csi-cal-input = <8>; + }; + + &uart4 { +@@ -347,3 +348,128 @@ + &usbphyc_port1 { + phy-supply = <&vdd_usb>; + }; ++ ++/* Low-power states of regulators */ ++&v1v2_hdmi { ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; ++ ++&v1v8_audio { ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; ++ ++&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; ++ }; ++}; ++ ++&v3v3_hdmi { ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; ++ ++&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; ++ }; ++}; ++ ++&vdda { ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; ++ ++&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; ++ }; ++}; ++ ++&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; ++ }; ++}; ++ ++&vdd_usb { ++ 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; ++ }; ++}; ++ ++&vtt_ddr { ++ lp-stop { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; +diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi +new file mode 100644 +index 000000000..f906ed63a +--- /dev/null ++++ b/fdts/stm32mp15xx-edx.dtsi +@@ -0,0 +1,491 @@ ++// 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 "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" ++ ++/ { ++ 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; ++}; ++ ++&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"; ++ ++ pmic: stpmic@33 { ++ compatible = "st,stpmic1"; ++ reg = <0x33>; ++ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ 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"; ++ 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-always-on; ++ regulator-over-current-protection; ++ st,regulator-sink-source; ++ }; ++ ++ 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; ++ }; ++ ++ 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>; ++ }; ++ }; ++ }; ++}; ++ ++&iwdg2 { ++ timeout-sec = <32>; ++ secure-timeout-sec = <5>; ++ status = "okay"; ++}; ++ ++&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_PLL4P ++ CLK_SDMMC12_PLL4P ++ CLK_DSI_DSIPLL ++ CLK_STGEN_HSE ++ CLK_USBPHY_HSE ++ CLK_SPI2S1_PLL3Q ++ CLK_SPI2S23_PLL3Q ++ CLK_SPI45_HSI ++ CLK_SPI6_HSI ++ CLK_I2C46_HSI ++ CLK_SDMMC3_PLL4P ++ CLK_USBO_USBPHY ++ CLK_ADC_CKPER ++ CLK_CEC_LSE ++ CLK_I2C12_HSI ++ CLK_I2C35_HSI ++ CLK_UART1_HSI ++ CLK_UART24_HSI ++ CLK_UART35_HSI ++ CLK_UART6_HSI ++ CLK_UART78_HSI ++ CLK_SPDIF_PLL4P ++ CLK_FDCAN_PLL4R ++ CLK_SAI1_PLL3Q ++ CLK_SAI2_PLL3Q ++ CLK_SAI3_PLL3Q ++ CLK_SAI4_PLL3Q ++ CLK_RNG1_CSI ++ CLK_RNG2_LSI ++ CLK_LPTIM1_PCLK1 ++ CLK_LPTIM23_PCLK3 ++ CLK_LPTIM45_LSE ++ >; ++ ++ /* 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"; ++}; ++ ++&rtc { ++ 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; ++ 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 { ++ status = "okay"; ++ st,hsi-cal-input = <7>; ++ st,csi-cal-input = <8>; ++}; ++ ++&uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_pins_a>; ++ status = "okay"; ++}; ++ ++&usbotg_hs { ++ vbus-supply = <&vbus_otg>; ++}; ++ ++&usbphyc_port0 { ++ phy-supply = <&vdd_usb>; ++}; ++ ++&usbphyc_port1 { ++ phy-supply = <&vdd_usb>; ++}; ++ ++/* Low-power states of regulators */ ++&v1v8 { ++ 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; ++ }; ++}; ++ ++&v3v3 { ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; ++ ++&vdd { ++ 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; ++ }; ++}; ++ ++&vdda { ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++}; ++ ++&vddcore { ++ 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 { ++ 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_sd { ++ 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; ++ }; ++}; ++ ++&vref_ddr { ++ 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; ++ }; ++}; ++ ++&vtt_ddr { ++ 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; ++ }; ++}; +diff --git a/fdts/stm32mp15xx-evx.dtsi b/fdts/stm32mp15xx-evx.dtsi +new file mode 100644 +index 000000000..8362b8d89 +--- /dev/null ++++ b/fdts/stm32mp15xx-evx.dtsi +@@ -0,0 +1,73 @@ ++// 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"; ++ ++ nand-controller@4,0 { ++ status = "okay"; ++ ++ nand@0 { ++ reg = <0>; ++ nand-on-flash-bbt; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ }; ++}; ++ ++&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>; ++ 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>; ++ }; ++}; ++ ++&timers12 { ++ status = "disabled"; ++}; ++ ++&usart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usart3_pins_b>; ++ 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/stm32mp15xx-osd32.dtsi b/fdts/stm32mp15xx-osd32.dtsi +index 76a25613a..29cf83afe 100644 +--- a/fdts/stm32mp15xx-osd32.dtsi ++++ b/fdts/stm32mp15xx-osd32.dtsi +@@ -183,7 +183,7 @@ + + /* CLOCK init */ + &rcc { +- secure-status = "disabled"; ++ compatible = "st,stm32mp1-rcc", "syscon"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P +diff --git a/fdts/stm32mp15xxaa-pinctrl.dtsi b/fdts/stm32mp15xxaa-pinctrl.dtsi +index f1d540abe..baf74d2c9 100644 +--- a/fdts/stm32mp15xxaa-pinctrl.dtsi ++++ b/fdts/stm32mp15xxaa-pinctrl.dtsi +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +diff --git a/fdts/stm32mp15xxac-pinctrl.dtsi b/fdts/stm32mp15xxac-pinctrl.dtsi +index 11e7e0344..9b87e3309 100644 +--- a/fdts/stm32mp15xxac-pinctrl.dtsi ++++ b/fdts/stm32mp15xxac-pinctrl.dtsi +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h +index a1bd94291..ecc0746e6 100644 +--- a/include/arch/aarch32/arch.h ++++ b/include/arch/aarch32/arch.h +@@ -486,13 +486,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 +@@ -553,6 +553,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 +@@ -562,6 +565,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 + +@@ -612,6 +616,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 + ******************************************************************************/ +@@ -665,6 +675,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 033098915..310da7837 100644 +--- a/include/arch/aarch32/arch_helpers.h ++++ b/include/arch/aarch32/arch_helpers.h +@@ -249,6 +249,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) +@@ -292,6 +295,7 @@ DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) + * Address translation + */ + 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) + +diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h +index 0fb4e7436..c99fd5ab6 100644 +--- a/include/arch/aarch64/arch.h ++++ b/include/arch/aarch64/arch.h +@@ -894,13 +894,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/tbbr/cot_def.h b/include/common/tbbr/cot_def.h +index 800ad07eb..dea5507e7 100644 +--- a/include/common/tbbr/cot_def.h ++++ b/include/common/tbbr/cot_def.h +@@ -39,7 +39,7 @@ + #error "Invalid value for TF_MBEDTLS_KEY_SIZE" + #endif + #else /* Only using ECDSA keys. */ +-#define PK_DER_LEN 91 ++#define PK_DER_LEN 92 + #endif + + #if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256 +diff --git a/include/drivers/auth/tbbr_cot_common.h b/include/drivers/auth/tbbr_cot_common.h +index a51faee1a..21bcd520a 100644 +--- a/include/drivers/auth/tbbr_cot_common.h ++++ b/include/drivers/auth/tbbr_cot_common.h +@@ -25,5 +25,6 @@ extern auth_param_type_desc_t fw_config_hash; + + extern const auth_img_desc_t trusted_boot_fw_cert; + extern const auth_img_desc_t hw_config; ++extern const auth_img_desc_t fw_config; + + #endif /* TBBR_COT_COMMON_H */ +diff --git a/include/drivers/clk.h b/include/drivers/clk.h +new file mode 100644 +index 000000000..84950eb7f +--- /dev/null ++++ b/include/drivers/clk.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef CLK_H ++#define CLK_H ++ ++#include ++ ++struct clk_ops { ++ int (*enable)(unsigned long id); ++ void (*disable)(unsigned long id); ++ unsigned long (*get_rate)(unsigned long id); ++ int (*get_parent)(unsigned long id); ++ bool (*is_enabled)(unsigned long id); ++}; ++ ++int clk_enable(unsigned long id); ++void clk_disable(unsigned long id); ++unsigned long clk_get_rate(unsigned long id); ++bool clk_is_enabled(unsigned long id); ++int clk_get_parent(unsigned long id); ++ ++void clk_register(const struct clk_ops *ops); ++ ++#endif /* CLK_H */ +diff --git a/include/drivers/fwu/fwu.h b/include/drivers/fwu/fwu.h +index ae06da98f..9f18e221c 100644 +--- a/include/drivers/fwu/fwu.h ++++ b/include/drivers/fwu/fwu.h +@@ -11,5 +11,6 @@ + + void fwu_init(void); + bool fwu_is_trial_run_state(void); ++const struct fwu_metadata *fwu_get_metadata(void); + + #endif /* FWU_H */ +diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h +index f2d641c2d..8f30ed050 100644 +--- a/include/drivers/io/io_storage.h ++++ b/include/drivers/io/io_storage.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -24,7 +24,6 @@ typedef enum { + IO_TYPE_BLOCK, + IO_TYPE_MTD, + IO_TYPE_MMC, +- IO_TYPE_STM32IMAGE, + IO_TYPE_ENCRYPTED, + IO_TYPE_MAX + } io_type_t; +diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h +index 834a80f4a..ccf8e6b65 100644 +--- a/include/drivers/mmc.h ++++ b/include/drivers/mmc.h +@@ -110,6 +110,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) +@@ -117,6 +118,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; +@@ -216,6 +220,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 +index 1b78ad41b..bb0cdde60 100644 +--- a/include/drivers/nand.h ++++ b/include/drivers/nand.h +@@ -33,6 +33,8 @@ struct nand_device { + uintptr_t buffer); + }; + ++void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size); ++ + /* + * Read bytes from NAND device + * +diff --git a/include/drivers/partition/efi.h b/include/drivers/partition/efi.h +new file mode 100644 +index 000000000..e463f9657 +--- /dev/null ++++ b/include/drivers/partition/efi.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 2021, Linaro Limited ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#ifndef DRIVERS_PARTITION_EFI_H ++#define DRIVERS_PARTITION_EFI_H ++ ++#include ++ ++#include ++ ++#define EFI_NAMELEN 36 ++ ++static inline int guidcmp(const void *g1, const void *g2) ++{ ++ return memcmp(g1, g2, sizeof(struct efi_guid)); ++} ++ ++static inline void *guidcpy(void *dst, const void *src) ++{ ++ return memcpy(dst, src, sizeof(struct efi_guid)); ++} ++ ++#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ ++ { (a) & 0xffffffff, \ ++ (b) & 0xffff, \ ++ (c) & 0xffff, \ ++ { (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } } ++ ++#define NULL_GUID \ ++ EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) ++ ++#endif /* DRIVERS_PARTITION_EFI_H */ +diff --git a/include/drivers/partition/gpt.h b/include/drivers/partition/gpt.h +index d923e9535..c2a229e33 100644 +--- a/include/drivers/partition/gpt.h ++++ b/include/drivers/partition/gpt.h +@@ -7,19 +7,20 @@ + #ifndef GPT_H + #define GPT_H + ++#include + #include ++#include + + #define PARTITION_TYPE_GPT 0xee + #define GPT_HEADER_OFFSET PLAT_PARTITION_BLOCK_SIZE + #define GPT_ENTRY_OFFSET (GPT_HEADER_OFFSET + \ + PLAT_PARTITION_BLOCK_SIZE) +-#define GUID_LEN 16 + + #define GPT_SIGNATURE "EFI PART" + + typedef struct gpt_entry { +- unsigned char type_uuid[GUID_LEN]; +- unsigned char unique_uuid[GUID_LEN]; ++ struct efi_guid type_uuid; ++ struct efi_guid unique_uuid; + unsigned long long first_lba; + unsigned long long last_lba; + unsigned long long attr; +@@ -36,7 +37,7 @@ typedef struct gpt_header { + unsigned long long backup_lba; + unsigned long long first_lba; + unsigned long long last_lba; +- unsigned char disk_uuid[16]; ++ struct efi_guid disk_uuid; + /* starting LBA of array of partition entries */ + unsigned long long part_lba; + /* number of partition entries in array */ +diff --git a/include/drivers/partition/partition.h b/include/drivers/partition/partition.h +index 5f6483373..31432a3f4 100644 +--- a/include/drivers/partition/partition.h ++++ b/include/drivers/partition/partition.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -10,6 +10,8 @@ + #include + + #include ++#include ++#include + + #if !PLAT_PARTITION_MAX_ENTRIES + # define PLAT_PARTITION_MAX_ENTRIES 128 +@@ -27,12 +29,12 @@ CASSERT((PLAT_PARTITION_BLOCK_SIZE == 512) || + + #define LEGACY_PARTITION_BLOCK_SIZE 512 + +-#define EFI_NAMELEN 36 +- + typedef struct partition_entry { + uint64_t start; + uint64_t length; + char name[EFI_NAMELEN]; ++ struct efi_guid part_guid; ++ struct efi_guid type_guid; + } partition_entry_t; + + typedef struct partition_entry_list { +@@ -42,6 +44,8 @@ typedef struct partition_entry_list { + + int load_partition_table(unsigned int image_id); + const partition_entry_t *get_partition_entry(const char *name); ++const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_guid); ++const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid); + const partition_entry_list_t *get_partition_entry_list(void); + void partition_init(unsigned int image_id); + +diff --git a/include/drivers/regulator.h b/include/drivers/regulator.h +new file mode 100644 +index 000000000..06249eff8 +--- /dev/null ++++ b/include/drivers/regulator.h +@@ -0,0 +1,155 @@ ++/* ++ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++#ifndef REGULATOR_H ++#define REGULATOR_H ++ ++#include ++ ++#ifndef PLAT_NB_RDEVS ++#error "Missing PLAT_NB_RDEVS" ++#endif ++ ++#ifndef PLAT_NB_SUSPEND_MODES ++#error "Missing PLAT_NB_SUSPEND_MODES" ++#endif ++ ++const char *plat_get_lp_mode_name(int mode); ++ ++/* ++ * Consumer interface ++ */ ++ ++/* regulator-always-on : regulator should never be disabled */ ++#define REGUL_ALWAYS_ON BIT(0) ++/* ++ * regulator-boot-on: ++ * It's expected that this regulator was left on by the bootloader. ++ * The core shouldn't prevent it from being turned off later. ++ * The regulator is needed to exit from suspend so it is turned on during suspend entry. ++ */ ++#define REGUL_BOOT_ON BIT(1) ++/* regulator-over-current-protection: Enable over current protection. */ ++#define REGUL_OCP BIT(2) ++/* regulator-active-discharge: enable active discharge. */ ++#define REGUL_ACTIVE_DISCHARGE BIT(3) ++/* regulator-pull-down: Enable pull down resistor when the regulator is disabled. */ ++#define REGUL_PULL_DOWN BIT(4) ++/* ++ * st,mask-reset: set mask reset for the regulator, meaning that the regulator ++ * setting is maintained during pmic reset. ++ */ ++#define REGUL_MASK_RESET BIT(5) ++/* st,regulator-sink-source: set the regulator in sink source mode */ ++#define REGUL_SINK_SOURCE BIT(6) ++/* st,regulator-bypass: set the regulator in bypass mode */ ++#define REGUL_ENABLE_BYPASS BIT(7) ++ ++struct rdev *regulator_get_by_name(const char *node_name); ++struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name); ++ ++int regulator_enable(struct rdev *rdev); ++int regulator_disable(struct rdev *rdev); ++int regulator_is_enabled(const struct rdev *rdev); ++ ++int regulator_set_voltage(struct rdev *rdev, uint16_t volt); ++int regulator_set_min_voltage(struct rdev *rdev); ++int regulator_get_voltage(const struct rdev *rdev); ++ ++int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count); ++void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv); ++int regulator_set_flag(struct rdev *rdev, uint16_t flag); ++ ++/* ++ * Driver Interface ++ */ ++ ++/* set_state() arguments */ ++#define STATE_DISABLE false ++#define STATE_ENABLE true ++ ++/* suspend() arguments */ ++#define LP_STATE_OFF BIT(0) ++#define LP_STATE_ON BIT(1) ++#define LP_STATE_UNCHANGED BIT(2) ++#define LP_STATE_SET_VOLT BIT(3) ++ ++struct regul_description { ++ const char *node_name; ++ const struct regul_ops *ops; ++ const void *driver_data; ++ const char *supply_name; ++ const uint32_t enable_ramp_delay; ++}; ++ ++struct regul_ops { ++ int (*set_state)(const struct regul_description *desc, bool state); ++ int (*get_state)(const struct regul_description *desc); ++ int (*set_voltage)(const struct regul_description *desc, uint16_t mv); ++ int (*get_voltage)(const struct regul_description *desc); ++ int (*list_voltages)(const struct regul_description *desc, ++ const uint16_t **levels, size_t *count); ++ int (*set_flag)(const struct regul_description *desc, uint16_t flag); ++ void (*lock)(const struct regul_description *desc); ++ void (*unlock)(const struct regul_description *desc); ++#if defined(IMAGE_BL32) ++ int (*suspend)(const struct regul_description *desc, uint8_t state, ++ uint16_t mv); ++#endif ++}; ++ ++int regulator_register(const struct regul_description *desc, int node); ++ ++/* ++ * Internal regulator structure ++ * The structure is internal to the core, and the content should not be used ++ * by a consumer nor a driver. ++ */ ++struct rdev { ++ const struct regul_description *desc; ++ ++ int32_t phandle; ++ ++ uint16_t min_mv; ++ uint16_t max_mv; ++ ++ uint16_t flags; ++ ++ uint32_t enable_ramp_delay; ++#if defined(IMAGE_BL32) ++ const char *reg_name; ++ ++ uint8_t use_count; ++ ++ int32_t supply_phandle; ++ struct rdev *supply_dev; ++ ++ uint8_t lp_state[PLAT_NB_SUSPEND_MODES]; ++ uint16_t lp_mv[PLAT_NB_SUSPEND_MODES]; ++#endif ++}; ++ ++#if defined(IMAGE_BL32) ++ ++/* Boot and init */ ++int regulator_core_config(void); ++int regulator_core_cleanup(void); ++ ++/* Suspend resume operations */ ++#define PLAT_BACKUP_REGULATOR_SIZE (sizeof(int8_t) * PLAT_NB_RDEVS) ++ ++int regulator_core_suspend(int mode); ++int regulator_core_resume(void); ++ ++void regulator_core_backup_context(void *backup_area, size_t backup_size); ++void regulator_core_restore_context(void *backup_area, size_t backup_size); ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++void regulator_core_dump(void); ++#endif ++ ++#endif ++ ++#endif /* REGULATOR_H */ +diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h +index d833e7ab2..145f9d783 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-2021, 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 + */ +@@ -179,10 +102,11 @@ 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); ++void 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); ++ ++void bsec_write_scratch(uint32_t val); ++uint32_t bsec_read_scratch(void); + + uint32_t bsec_get_status(void); + uint32_t bsec_get_hw_conf(void); +@@ -190,14 +114,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..0d8fedc48 +--- /dev/null ++++ b/include/drivers/st/bsec2_reg.h +@@ -0,0 +1,105 @@ ++/* ++ * 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) ++#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) ++ ++/* 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) ++ ++#define BSEC_WRLOCK(n) (BSEC_WRLOCK_OFF + U(0x04) * (n)) ++#define BSEC_SPLOCK(n) (BSEC_SPLOCK_OFF + U(0x04) * (n)) ++#define BSEC_SWLOCK(n) (BSEC_SWLOCK_OFF + U(0x04) * (n)) ++#define BSEC_SRLOCK(n) (BSEC_SRLOCK_OFF + U(0x04) * (n)) ++ ++/* 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 0 ++#define BSEC_WRITE BIT(8) ++#define BSEC_LOCK BIT(9) ++ ++/* BSEC_OTP_LOCK register */ ++#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_SECURE_MASK BIT(0) ++#define BSEC_MODE_FULLDBG_MASK BIT(1) ++#define BSEC_MODE_INVALID_MASK BIT(2) ++#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) ++ ++/* 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) ++ ++/* BSEC_IPVR Register */ ++#define BSEC_IPVR_MSK GENMASK(7, 0) ++ ++#endif /* BSEC2_REG_H */ +diff --git a/include/drivers/st/io_stm32image.h b/include/drivers/st/io_stm32image.h +deleted file mode 100644 +index f9fa3630c..000000000 +--- a/include/drivers/st/io_stm32image.h ++++ /dev/null +@@ -1,32 +0,0 @@ +-/* +- * 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]; +- unsigned long long device_size; +- uint32_t lba_size; +-}; +- +-int register_io_dev_stm32image(const io_dev_connector_t **dev_con); +- +-#endif /* IO_STM32IMAGE_H */ +diff --git a/include/drivers/st/regulator_fixed.h b/include/drivers/st/regulator_fixed.h +new file mode 100644 +index 000000000..b03c6e38c +--- /dev/null ++++ b/include/drivers/st/regulator_fixed.h +@@ -0,0 +1,12 @@ ++/* ++ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef REGULATOR_FIXED_H ++#define REGULATOR_FIXED_H ++ ++int fixed_regulator_register(void); ++ ++#endif /* REGULATOR_FIXED_H */ +diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h +index e241f584f..84ef3b8be 100644 +--- a/include/drivers/st/stm32_gpio.h ++++ b/include/drivers/st/stm32_gpio.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -13,6 +13,7 @@ + #define GPIO_TYPE_OFFSET U(0x04) + #define GPIO_SPEED_OFFSET U(0x08) + #define GPIO_PUPD_OFFSET U(0x0C) ++#define GPIO_OD_OFFSET U(0x14) + #define GPIO_BSRR_OFFSET U(0x18) + #define GPIO_AFRL_OFFSET U(0x20) + #define GPIO_AFRH_OFFSET U(0x24) +@@ -32,7 +33,9 @@ + #define GPIO_MODE_ANALOG 0x03 + #define GPIO_MODE_MASK U(0x03) + +-#define GPIO_OPEN_DRAIN U(0x10) ++#define GPIO_TYPE_PUSH_PULL 0x00 ++#define GPIO_TYPE_OPEN_DRAIN 0x01 ++#define GPIO_TYPE_MASK U(0x01) + + #define GPIO_SPEED_LOW 0x00 + #define GPIO_SPEED_MEDIUM 0x01 +@@ -45,13 +48,14 @@ + #define GPIO_PULL_DOWN 0x02 + #define GPIO_PULL_MASK U(0x03) + ++#define GPIO_OD_MASK U(0x01) ++ + #ifndef __ASSEMBLER__ + #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, uint8_t status); + void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); ++void set_gpio_reset_cfg(uint32_t bank, uint32_t pin); + #endif /*__ASSEMBLER__*/ + + #endif /* STM32_GPIO_H */ +diff --git a/include/drivers/st/stm32_hash.h b/include/drivers/st/stm32_hash.h +index df04730d6..4614b87a6 100644 +--- a/include/drivers/st/stm32_hash.h ++++ b/include/drivers/st/stm32_hash.h +@@ -8,10 +8,16 @@ + #define STM32_HASH_H + + enum stm32_hash_algo_mode { ++#if STM32MP15 + HASH_MD5SUM, ++#endif + HASH_SHA1, + HASH_SHA224, +- HASH_SHA256 ++ HASH_SHA256, ++#if STM32MP13 ++ HASH_SHA384, ++ HASH_SHA512, ++#endif + }; + + int stm32_hash_update(const uint8_t *buffer, size_t length); +diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h +index 170d4cf81..4844a8f44 100644 +--- a/include/drivers/st/stm32_i2c.h ++++ b/include/drivers/st/stm32_i2c.h +@@ -1,7 +1,7 @@ + /* + * 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 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) ++#define I2C_TIMINGR_SCLL_MAX (I2C_TIMINGR_SCLL + 1) ++#define I2C_TIMINGR_SCLH_MAX ((I2C_TIMINGR_SCLH >> 8) + 1) ++#define I2C_TIMINGR_SDADEL_MAX ((I2C_TIMINGR_SDADEL >> 16) + 1) ++#define I2C_TIMINGR_SCLDEL_MAX ((I2C_TIMINGR_SCLDEL >> 20) + 1) ++#define I2C_TIMINGR_PRESC_MAX ((I2C_TIMINGR_PRESC >> 28) + 1) ++#define I2C_SET_TIMINGR_SCLL(n) ((n) & \ ++ (I2C_TIMINGR_SCLL_MAX - 1)) ++#define I2C_SET_TIMINGR_SCLH(n) (((n) & \ ++ (I2C_TIMINGR_SCLH_MAX - 1)) << 8) ++#define I2C_SET_TIMINGR_SDADEL(n) (((n) & \ ++ (I2C_TIMINGR_SDADEL_MAX - 1)) << 16) ++#define I2C_SET_TIMINGR_SCLDEL(n) (((n) & \ ++ (I2C_TIMINGR_SCLDEL_MAX - 1)) << 20) ++#define I2C_SET_TIMINGR_PRESC(n) (((n) & \ ++ (I2C_TIMINGR_PRESC_MAX - 1)) << 28) + + /* Bit definition for I2C_TIMEOUTR register */ + #define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0) +@@ -111,15 +126,9 @@ + #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 ++#define STANDARD_RATE 100000 ++#define FAST_RATE 400000 ++#define FAST_PLUS_RATE 1000000 + + 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 */ + }; + + #define I2C_ADDRESSINGMODE_7BIT 0x00000001U +diff --git a/include/drivers/st/stm32_iwdg.h b/include/drivers/st/stm32_iwdg.h +index bad25244a..c0c009779 100644 +--- a/include/drivers/st/stm32_iwdg.h ++++ b/include/drivers/st/stm32_iwdg.h +@@ -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_mce.h b/include/drivers/st/stm32_mce.h +new file mode 100644 +index 000000000..e796ecb31 +--- /dev/null ++++ b/include/drivers/st/stm32_mce.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_MCE_H ++#define STM32_MCE_H ++ ++#include ++#include ++ ++#include ++ ++/* MCE encryption modes */ ++#define MCE_BYPASS_MODE MCE_PLAINTEXT ++#define MCE_ENCRYPT_MODE MCE_ENCRYPT ++#define MCE_ENCRYPTION_MODE_MAX MCE_ENCRYPT_MODE ++ ++/* IP configuration */ ++#define MCE_IP_MAX_REGION_NB 1U ++ ++void stm32_mce_init(void); ++ ++int stm32_mce_write_master_key(uint8_t *mkey); ++void stm32_mce_lock_master_key(void); ++bool stm32_mce_is_master_key_locked(void); ++ ++void stm32_mce_lock_global(void); ++bool stm32_mce_is_globally_locked(void); ++bool stm32_mce_is_hw_encryption_functional(void); ++ ++int stm32_mce_get_address_encryption_state(uint32_t address, uint32_t *state); ++#endif /* STM32_MCE_H */ +diff --git a/include/drivers/st/stm32_pka.h b/include/drivers/st/stm32_pka.h +new file mode 100644 +index 000000000..8958d1f7d +--- /dev/null ++++ b/include/drivers/st/stm32_pka.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_PKA_H ++#define STM32_PKA_H ++ ++#include ++ ++#if !PKA_USE_NIST_P256 && !PKA_USE_BRAINPOOL_P256R1 && !PKA_USE_BRAINPOOL_P256T1 && \ ++ !PKA_USE_NIST_P521 ++#error "At least one ECDSA curve needs to be selected" ++#endif ++ ++enum stm32_pka_ecdsa_curve_id { ++#if PKA_USE_NIST_P256 ++ PKA_NIST_P256, ++#endif ++#if PKA_USE_BRAINPOOL_P256R1 ++ PKA_BRAINPOOL_P256R1, ++#endif ++#if PKA_USE_BRAINPOOL_P256T1 ++ PKA_BRAINPOOL_P256T1, ++#endif ++#if PKA_USE_NIST_P521 ++ PKA_NIST_P521, ++#endif ++}; ++ ++struct stm32_pka_platdata { ++ uintptr_t base; ++ unsigned long clock_id; ++ unsigned int reset_id; ++}; ++ ++int stm32_pka_init(void); ++int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size, ++ void *sig_r_ptr, unsigned int sig_r_size, ++ void *sig_s_ptr, unsigned int sig_s_size, ++ void *pk_x_ptr, unsigned int pk_x_size, ++ void *pk_y_ptr, unsigned int pk_y_size, ++ enum stm32_pka_ecdsa_curve_id cid); ++ ++#endif /* STM32_PKA_H */ +diff --git a/include/drivers/st/stm32_rng.h b/include/drivers/st/stm32_rng.h +new file mode 100644 +index 000000000..ea228433f +--- /dev/null ++++ b/include/drivers/st/stm32_rng.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_RNG_H ++#define STM32_RNG_H ++ ++int stm32_rng_read(uint8_t *out, uint32_t size); ++int stm32_rng_init(void); ++ ++#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 000000000..128dd2d14 +--- /dev/null ++++ b/include/drivers/st/stm32_rtc.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_RTC_H ++#define STM32_RTC_H ++ ++#include ++ ++#define RTC_TR 0x00U ++#define RTC_DR 0x04U ++#define RTC_SSR 0x08U ++#define RTC_ICSR 0x0CU ++#define RTC_PRER 0x10U ++#define RTC_WUTR 0x14U ++#define RTC_CR 0x18U ++#define RTC_SMCR 0x20U ++#define RTC_WPR 0x24U ++#define RTC_CALR 0x28U ++#define RTC_SHIFTR 0x2CU ++#define RTC_TSTR 0x30U ++#define RTC_TSDR 0x34U ++#define RTC_TSSSR 0x38U ++#define RTC_ALRMAR 0x40U ++#define RTC_ALRMASSR 0x44U ++#define RTC_ALRMBR 0x48U ++#define RTC_ALRMBSSR 0x4CU ++#define RTC_SR 0x50U ++#define RTC_SCR 0x5CU ++#define RTC_OR 0x60U ++ ++struct stm32_rtc_calendar { ++ uint32_t ssr; ++ uint32_t tr; ++ uint32_t dr; ++}; ++ ++enum months { ++ JANUARY = 1, ++ FEBRUARY, ++ MARCH, ++ APRIL, ++ MAY, ++ JUNE, ++ JULY, ++ AUGUST, ++ SEPTEMBER, ++ OCTOBER, ++ NOVEMBER, ++ DECEMBER, ++ NB_MONTHS = 12 ++}; ++ ++struct stm32_rtc_time { ++ uint32_t hour; ++ uint32_t min; ++ uint32_t sec; ++ uint32_t wday; ++ uint32_t day; ++ enum months month; ++ uint32_t year; ++}; ++ ++void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar); ++unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *current, ++ struct stm32_rtc_calendar *ref); ++void stm32_rtc_set_tamper_timestamp(void); ++bool stm32_rtc_is_timestamp_enable(void); ++void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts); ++int stm32_rtc_init(void); ++ ++/* SMP protection on RTC registers access */ ++void stm32_rtc_regs_lock(void); ++void stm32_rtc_regs_unlock(void); ++ ++#endif /* STM32_RTC_H */ +diff --git a/include/drivers/st/stm32_saes.h b/include/drivers/st/stm32_saes.h +new file mode 100644 +index 000000000..17d24e6c2 +--- /dev/null ++++ b/include/drivers/st/stm32_saes.h +@@ -0,0 +1,66 @@ ++/* ++ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_SAES_H ++#define STM32_SAES_H ++ ++#include ++#include ++#include ++ ++#define DT_SAES_COMPAT "st,stm32-saes" ++ ++struct stm32_saes_platdata { ++ uintptr_t base; ++ unsigned long clock_id; ++ unsigned int reset_id; ++}; ++ ++enum stm32_saes_chaining_mode { ++ STM32_SAES_MODE_ECB, ++ STM32_SAES_MODE_CBC, ++ STM32_SAES_MODE_CTR, ++ STM32_SAES_MODE_GCM, ++ STM32_SAES_MODE_CCM, /* Not use in TF-A */ ++}; ++ ++enum stm32_saes_key_selection { ++ STM32_SAES_KEY_SOFT, ++ STM32_SAES_KEY_DHU, /* Derived HW unique key */ ++ STM32_SAES_KEY_BH, /* Boot HW key */ ++ STM32_SAES_KEY_BHU_XOR_BH, /* XOR of DHUK and BHK */ ++ STM32_SAES_KEY_WRAPPED ++}; ++ ++struct stm32_saes_context { ++ uintptr_t base; ++ uint32_t cr; ++ uint32_t assoc_len; ++ uint32_t load_len; ++ uint32_t key[8]; /* In HW byte order */ ++ uint32_t iv[4]; /* In HW byte order */ ++}; ++ ++int stm32_saes_driver_init(void); ++ ++int stm32_saes_init(struct stm32_saes_context *ctx, bool is_decrypt, ++ enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select, ++ const void *key, size_t key_len, const void *iv, size_t iv_len); ++int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block, ++ uint8_t *data_in, uint8_t *data_out, size_t data_len); ++int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block, ++ uint8_t *data, size_t data_len); ++int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block, ++ uint8_t *data_in, uint8_t *data_out, size_t data_len); ++int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, size_t tag_len); ++ ++int stm32_saes_wrap_key(enum stm32_saes_chaining_mode ch_mode, ++ enum stm32_saes_key_selection key_select, const void *key, size_t key_size, ++ const void *iv, size_t iv_size, const void *in_key, const void *out_data); ++int stm32_saes_unwrap_key(enum stm32_saes_chaining_mode ch_mode, ++ enum stm32_saes_key_selection key_select, const void *key, ++ size_t key_size, const void *iv, size_t iv_size, const void *in_data); ++#endif +diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h +index 4853208c2..af02b91ea 100644 +--- a/include/drivers/st/stm32_sdmmc2.h ++++ b/include/drivers/st/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 rdev *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 000000000..11dc96df6 +--- /dev/null ++++ b/include/drivers/st/stm32_tamp.h +@@ -0,0 +1,252 @@ ++/* ++ * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_TAMP_H ++#define STM32_TAMP_H ++ ++/* Internal Tamper */ ++enum stm32_tamp_int_id { ++ INT_TAMP1 = 0, ++ INT_TAMP2, ++ INT_TAMP3, ++ INT_TAMP4, ++ INT_TAMP5, ++ INT_TAMP6, ++ INT_TAMP7, ++ INT_TAMP8, ++ INT_TAMP9, ++ INT_TAMP10, ++ INT_TAMP11, ++ INT_TAMP12, ++ INT_TAMP13, ++ INT_TAMP14, ++ INT_TAMP15, ++ INT_TAMP16 ++}; ++ ++/* External Tamper */ ++enum stm32_tamp_ext_id { ++ EXT_TAMP1 = 0, ++ EXT_TAMP2, ++ EXT_TAMP3, ++ EXT_TAMP4, ++ EXT_TAMP5, ++ EXT_TAMP6, ++ EXT_TAMP7, ++ EXT_TAMP8 ++}; ++ ++/* Out pin to compare for external Tamper */ ++enum stm32_tamp_ext_out_id { ++ TAMPOUTSEL_SAME_AS_INPUT = 0, ++ TAMPOUTSEL1 = 1, ++ TAMPOUTSEL2, ++ TAMPOUTSEL3, ++ TAMPOUTSEL4, ++ TAMPOUTSEL5, ++ TAMPOUTSEL6, ++ TAMPOUTSEL7, ++ TAMPOUTSEL8, ++}; ++ ++/* Define number of backup registers in zone 1 and zone 2 (remaining are in ++ * zone 3) ++ * ++ * backup registers in zone 1 : read/write only in secure mode ++ * zone 2 : write only in secure mode, read in secure ++ * and non-secure mode ++ * zone 3 : read/write in secure and non-secure mode ++ * ++ * Protection zone 1 if nb_zone1_regs == 0 no backup register are in zone 1 ++ * else backup registers from TAMP_BKP0R to TAMP_BKPxR ++ * with x = nb_zone1_regs - 1 are in zone 1. ++ * Protection zone 2 if nb_zone2_regs == 0 no backup register are in zone 2 ++ * else backup registers from TAMP_BKPyR with y = nb_zone1_regs ++ * to TAMP_BKPzR with z = (nb_zone1_regs1 + nb_zone2_regs - 1) ++ * are in zone 2. ++ * Protection zone 3 backup registers from TAMP_BKPtR ++ * with t = nb_zone1_regs1 + nb_zone2_regs to last backup ++ * register are in zone 3. ++ */ ++struct bkpregs_conf { ++ uint32_t nb_zone1_regs; ++ uint32_t nb_zone2_regs; ++}; ++ ++/* Define TAMPER modes */ ++#define TAMP_DISABLE 0x0U ++#define TAMP_ENABLE 0x1U ++#define TAMP_TRIG_OFF 0x0U ++#define TAMP_TRIG_ON 0x2U ++#define TAMP_ACTIVE 0x4U ++#define TAMP_ERASE 0x0U ++#define TAMP_NOERASE 0x8U ++#define TAMP_NO_EVT_MASK 0x0U ++#define TAMP_EVT_MASK 0x10U ++ ++/* Define Passive FILTER mode */ ++#define TAMP_FILTER_TAMPPUDIS_OFFSET 7U ++#define TAMP_FILTER_PRECHARGE (0x0U << TAMP_FILTER_TAMPPUDIS_OFFSET) ++#define TAMP_FILTER_PULL_UP_DISABLE (0x1U << TAMP_FILTER_TAMPPUDIS_OFFSET) ++#define TAMP_FILTER_TAMPPRCH_OFFSET 5U ++#define TAMP_FILTER_DURATION_1_CYCLE (0x0U << TAMP_FILTER_TAMPPRCH_OFFSET) ++#define TAMP_FILTER_DURATION_2_CYCLES (0x1U << TAMP_FILTER_TAMPPRCH_OFFSET) ++#define TAMP_FILTER_DURATION_4_CYCLES (0x2U << TAMP_FILTER_TAMPPRCH_OFFSET) ++#define TAMP_FILTER_DURATION_8_CYCLES (0x3U << TAMP_FILTER_TAMPPRCH_OFFSET) ++#define TAMP_FILTER_TAMPFLT_OFFSET 3U ++#define TAMP_FILTER_COUNT_1 (0x0U << TAMP_FILTER_TAMPFLT_OFFSET) ++#define TAMP_FILTER_COUNT_2 (0x1U << TAMP_FILTER_TAMPFLT_OFFSET) ++#define TAMP_FILTER_COUNT_4 (0x2U << TAMP_FILTER_TAMPFLT_OFFSET) ++#define TAMP_FILTER_COUNT_8 (0x3U << TAMP_FILTER_TAMPFLT_OFFSET) ++#define TAMP_FILTER_TAMPFREQ_OFFSET 0U ++#define TAMP_FILTER_SAMPLING_32768 (0x0U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_16384 (0x1U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_8192 (0x2U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_4096 (0x3U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_2048 (0x4U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_1024 (0x5U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_512 (0x6U << TAMP_FILTER_TAMPFREQ_OFFSET) ++#define TAMP_FILTER_SAMPLING_256 (0x7U << TAMP_FILTER_TAMPFREQ_OFFSET) ++ ++/* Define active filter */ ++#define TAMP_ACTIVE_FLTEN_OFFSET 31U ++#define TAMP_ACTIVE_FILTER_OFF (0x0U << TAMP_ACTIVE_FLTEN_OFFSET) ++#define TAMP_ACTIVE_FILTER_ON (0x1U << TAMP_ACTIVE_FLTEN_OFFSET) ++#define TAMP_FILTER_ATOSHARE_OFFSET 30U ++#define TAMP_FILTER_USE_DEDICATED_OUT (0x0U << TAMP_FILTER_ATOSHARE_OFFSET) ++#define TAMP_FILTER_SELECT_OUT (0x1U << TAMP_FILTER_ATOSHARE_OFFSET) ++#define TAMP_ACTIVE_ATPER_OFFSET 24U ++#define TAMP_ACTIVE_ATPER_1_OUTPUT (0x0U << TAMP_ACTIVE_ATPER_OFFSET) ++#define TAMP_ACTIVE_ATPER_2_OUTPUTS (0x1U << TAMP_ACTIVE_ATPER_OFFSET) ++#define TAMP_ACTIVE_ATPER_3_4_OUTPUTS (0x2U << TAMP_ACTIVE_ATPER_OFFSET) ++#define TAMP_ACTIVE_ATPER_5_OUTPUTS (0x3U << TAMP_ACTIVE_ATPER_OFFSET) ++#define TAMP_ACTIVE_ATCKSEL_OFFSET 16U ++#define TAMP_ACTIVE_CKSEL_DIV_0 (0x0U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_2 (0x1U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_4 (0x2U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_8 (0x3U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_16 (0x4U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_32 (0x5U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_64 (0x6U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++#define TAMP_ACTIVE_CKSEL_DIV_128 (0x7U << TAMP_ACTIVE_ATCKSEL_OFFSET) ++ ++/* Define secure mode acces */ ++/* Tamper configuration and interrupt can be written when the APB access is secure or nonsecure.*/ ++#define TAMP_REGS_IT_UNSECURE 0U ++/* Tamper configuration and interrupt can be written only when the APB access is secure.*/ ++#define TAMP_REGS_IT_SECURE BIT(31) ++ ++/* ++ * stm32_tamp_write_mcounter : Increase monotonic counter[counter_idx] ++ */ ++int stm32_tamp_write_mcounter(int counter_idx); ++uint32_t stm32_tamp_read_mcounter(int counter_idx); ++ ++/* ++ * stm32_tamp_it_handler : Interrupt handler ++ */ ++void stm32_tamp_it_handler(void); ++ ++/* ++ * stm32_tamp_configure_secure_access: Configure which registers can be ++ * read/write from unsecure world ++ * secure_conf is a bit field from TAMP_.*_{UN,}SECURE define ++ */ ++void stm32_tamp_configure_secure_access(uint32_t secure_conf); ++ ++/* ++ * stm32_tamp_configure_privilege_access: Configure which registers can be ++ * read/write from unpriviliged world ++ * privilege_conf is a bit field from TAMP_.*_{UN,}PRIVILEGE define ++ */ ++void stm32_tamp_configure_privilege_access(uint32_t privilege_conf); ++ ++/* ++ * stm32_tamp_configure_passive: Configure passive mode ++ * passive_conf is a bit field from TAMP_FILTER_* define ++ */ ++void stm32_tamp_configure_passive(uint32_t passive_conf); ++ ++/* ++ * stm32_tamp_configure_ctive: Configure active mode ++ * passive_conf is a bit field from TAMP_ACTIVE_* define ++ */ ++void stm32_tamp_configure_active(uint32_t active_conf); ++ ++/* ++ * stm32_tamp_configure_internal: Configure one internal tamper ++ * id: internal tamper id ++ * mode: bitmask from TAMPER modes define ++ * callback: function to call when tamper is raised (can be NULL), ++ * called in interrupt context, ++ * if callback returns negative value, blocked secrets stay blocked ++ * (driver doesn't release this specific tamper). ++ * if callback returns 0 this specific tamp is ack (in case of no-erase ++ * tamper, blocked secret are unblocked) ++ * if callback returns positive value, this specific tamp is ack (in ++ * case of no-erase tamper, blocked secret are unblocked) and system is ++ * rebooted). ++ * ++ * return: -EINVAL if 'id' is not a valid internal tamp id, else 0 ++ */ ++int stm32_tamp_configure_internal(enum stm32_tamp_int_id id, uint32_t mode, ++ int (*callback)(int id)); ++ ++/* ++ * stm32_tamp_configure_external: Configure one external tamper ++ * id: external tamper id ++ * mode: bitmask from TAMPER modes define ++ * pin_out; output pin connected to input pin (linekd with selected ext tamp id) ++ * callback: function to call when tamper is raised (can be NULL), ++ * called in interrupt context, ++ * if callback returns negative value, blocked secrets stay blocked ++ * (driver doesn't release this specific tamper). ++ * if callback returns 0 this specific tamp is ack (in case of no-erase ++ * tamper, blocked secret are unblocked) ++ * if callback returns positive value, this specific tamp is ack (in ++ * case of no-erase tamper, blocked secret are unblocked) and system is ++ * rebooted). ++ * ++ * return: -EINVAL if 'id' is not a valid external tamp id, else 0 ++ */ ++int stm32_tamp_configure_external(enum stm32_tamp_ext_id id, uint32_t mode, ++ enum stm32_tamp_ext_out_id out_pin, int (*callback)(int id)); ++ ++/* ++ * stm32_tamp_init: Initialize tamper from DT ++ * return 0 if disabled, 1 if enabled, else < 0 ++ */ ++int stm32_tamp_init(void); ++ ++/* ++ * stm32_tamp_set_secure_bkprwregs : Configure backup registers zone. ++ * registers in zone 1 : read/write only in secure mode ++ * zone 2 : write only in secure mode, read in secure and non-secure mode ++ * zone 3 : read/write in secure and non-secure mode ++ * ++ * bkpregs_conf : a pointer to struct bkpregs_conf that define the number of registers in zone 1 ++ * and zone 2 (remaining backup registers will be in zone 3). ++ * ++ * return 0 if OK, -ENODEV if zone 1 and/or zone 2 definition are out of range. ++ */ ++int stm32_tamp_set_secure_bkpregs(struct bkpregs_conf *bkpregs_conf); ++ ++/* ++ * stm32_tamp_set_config: apply configuration ++ * default one if no previous call to any of : ++ * stm32_tamp_configure_passive() ++ * stm32_tamp_configure_active() ++ * stm32_tamp_configure_internal() ++ * stm32_tamp_configure_external() ++ * stm32_tamp_configure_secret_list() ++ * stm32_tamp_configure_secure_access() ++ * stm32_tamp_configure_privilige_access() ++ * ++ * return: < 0 if unable to apply configuration, else 0 ++ */ ++int stm32_tamp_set_config(void); ++ ++#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 000000000..0e2eb91fe +--- /dev/null ++++ b/include/drivers/st/stm32_timer.h +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_TIMER_H ++#define STM32_TIMER_H ++ ++enum timer_cal { ++ HSI_CAL = 0, ++ CSI_CAL ++}; ++ ++unsigned long stm32_timer_hsi_freq(void); ++unsigned long stm32_timer_csi_freq(void); ++void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void), ++ enum timer_cal type); ++int stm32_timer_init(void); ++ ++#endif /* STM32_TIMER_H */ +diff --git a/include/drivers/st/stm32_uart.h b/include/drivers/st/stm32_uart.h +new file mode 100644 +index 000000000..f906cf8ad +--- /dev/null ++++ b/include/drivers/st/stm32_uart.h +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32_UART_H ++#define STM32_UART_H ++ ++/* UART word length */ ++#define STM32_UART_WORDLENGTH_7B USART_CR1_M1 ++#define STM32_UART_WORDLENGTH_8B 0x00000000U ++#define STM32_UART_WORDLENGTH_9B USART_CR1_M0 ++ ++/* UART number of stop bits */ ++#define STM32_UART_STOPBITS_0_5 USART_CR2_STOP_0 ++#define STM32_UART_STOPBITS_1 0x00000000U ++#define STM32_UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) ++#define STM32_UART_STOPBITS_2 USART_CR2_STOP_1 ++ ++/* UART parity */ ++#define STM32_UART_PARITY_NONE 0x00000000U ++#define STM32_UART_PARITY_EVEN USART_CR1_PCE ++#define STM32_UART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) ++ ++/* UART transfer mode */ ++#define STM32_UART_MODE_RX USART_CR1_RE ++#define STM32_UART_MODE_TX USART_CR1_TE ++#define STM32_UART_MODE_TX_RX (USART_CR1_TE | USART_CR1_RE) ++ ++/* UART hardware flow control */ ++#define STM32_UART_HWCONTROL_NONE 0x00000000U ++#define STM32_UART_HWCONTROL_RTS USART_CR3_RTSE ++#define STM32_UART_HWCONTROL_CTS USART_CR3_CTSE ++#define STM32_UART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) ++ ++/* UART prescaler */ ++#define STM32_UART_PRESCALER_DIV1 0x00000000U ++#define STM32_UART_PRESCALER_DIV2 0x00000001U ++#define STM32_UART_PRESCALER_DIV4 0x00000002U ++#define STM32_UART_PRESCALER_DIV6 0x00000003U ++#define STM32_UART_PRESCALER_DIV8 0x00000004U ++#define STM32_UART_PRESCALER_DIV10 0x00000005U ++#define STM32_UART_PRESCALER_DIV12 0x00000006U ++#define STM32_UART_PRESCALER_DIV16 0x00000007U ++#define STM32_UART_PRESCALER_DIV32 0x00000008U ++#define STM32_UART_PRESCALER_DIV64 0x00000009U ++#define STM32_UART_PRESCALER_DIV128 0x0000000AU ++#define STM32_UART_PRESCALER_DIV256 0x0000000BU ++#define STM32_UART_PRESCALER_NB 0x0000000CU ++ ++/* UART fifo mode */ ++#define STM32_UART_FIFOMODE_EN USART_CR1_FIFOEN ++#define STM32_UART_FIFOMODE_DIS 0x00000000U ++ ++/* UART TXFIFO threshold level */ ++#define STM32_UART_TXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U ++#define STM32_UART_TXFIFO_THRESHOLD_1QUARTERFUL USART_CR3_TXFTCFG_0 ++#define STM32_UART_TXFIFO_THRESHOLD_HALFFULL USART_CR3_TXFTCFG_1 ++#define STM32_UART_TXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_TXFTCFG_0 | USART_CR3_TXFTCFG_1) ++#define STM32_UART_TXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_TXFTCFG_2 ++#define STM32_UART_TXFIFO_THRESHOLD_EMPTY (USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0) ++ ++/* UART RXFIFO threshold level */ ++#define STM32_UART_RXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U ++#define STM32_UART_RXFIFO_THRESHOLD_1QUARTERFULL USART_CR3_RXFTCFG_0 ++#define STM32_UART_RXFIFO_THRESHOLD_HALFFULL USART_CR3_RXFTCFG_1 ++#define STM32_UART_RXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_RXFTCFG_0 | USART_CR3_RXFTCFG_1) ++#define STM32_UART_RXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_RXFTCFG_2 ++#define STM32_UART_RXFIFO_THRESHOLD_FULL (USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0) ++ ++struct stm32_uart_init_s { ++ uint32_t baud_rate; /* ++ * Configures the UART communication ++ * baud rate. ++ */ ++ ++ uint32_t word_length; /* ++ * Specifies the number of data bits ++ * transmitted or received in a frame. ++ * This parameter can be a value of ++ * @ref STM32_UART_WORDLENGTH_*. ++ */ ++ ++ uint32_t stop_bits; /* ++ * Specifies the number of stop bits ++ * transmitted. This parameter can be ++ * a value of @ref STM32_UART_STOPBITS_*. ++ */ ++ ++ uint32_t parity; /* ++ * Specifies the parity mode. ++ * This parameter can be a value of ++ * @ref STM32_UART_PARITY_*. ++ */ ++ ++ uint32_t mode; /* ++ * Specifies whether the receive or ++ * transmit mode is enabled or ++ * disabled. This parameter can be a ++ * value of @ref @ref STM32_UART_MODE_*. ++ */ ++ ++ uint32_t hw_flow_control; /* ++ * Specifies whether the hardware flow ++ * control mode is enabled or ++ * disabled. This parameter can be a ++ * value of @ref STM32_UARTHWCONTROL_*. ++ */ ++ ++ uint32_t one_bit_sampling; /* ++ * Specifies whether a single sample ++ * or three samples' majority vote is ++ * selected. This parameter can be 0 ++ * or USART_CR3_ONEBIT. ++ */ ++ ++ uint32_t prescaler; /* ++ * Specifies the prescaler value used ++ * to divide the UART clock source. ++ * This parameter can be a value of ++ * @ref STM32_UART_PRESCALER_*. ++ */ ++ ++ uint32_t fifo_mode; /* ++ * Specifies if the FIFO mode will be ++ * used. This parameter can be a value ++ * of @ref STM32_UART_FIFOMODE_*. ++ */ ++ ++ uint32_t tx_fifo_threshold; /* ++ * Specifies the TXFIFO threshold ++ * level. This parameter can be a ++ * value of @ref ++ * STM32_UART_TXFIFO_THRESHOLD_*. ++ */ ++ ++ uint32_t rx_fifo_threshold; /* ++ * Specifies the RXFIFO threshold ++ * level. This parameter can be a ++ * value of @ref ++ * STM32_UART_RXFIFO_THRESHOLD_*. ++ */ ++}; ++ ++struct stm32_uart_handle_s { ++ uint32_t base; ++ uint32_t rdr_mask; ++}; ++ ++int stm32_uart_init(struct stm32_uart_handle_s *huart, ++ uintptr_t base_addr, ++ const struct stm32_uart_init_s *init); ++void stm32_uart_stop(uintptr_t base_addr); ++int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c); ++int stm32_uart_flush(struct stm32_uart_handle_s *huart); ++int stm32_uart_getc(struct stm32_uart_handle_s *huart); ++ ++#endif /* STM32_UART_H */ +diff --git a/include/drivers/st/stm32mp13_rcc.h b/include/drivers/st/stm32mp13_rcc.h +new file mode 100644 +index 000000000..9f992e771 +--- /dev/null ++++ b/include/drivers/st/stm32mp13_rcc.h +@@ -0,0 +1,1878 @@ ++/* ++ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP13_RCC_H ++#define STM32MP13_RCC_H ++ ++#include ++ ++#define RCC_SECCFGR U(0X0) ++#define RCC_MP_SREQSETR U(0X100) ++#define RCC_MP_SREQCLRR U(0X104) ++#define RCC_MP_APRSTCR U(0X108) ++#define RCC_MP_APRSTSR U(0X10C) ++#define RCC_PWRLPDLYCR U(0X110) ++#define RCC_MP_GRSTCSETR U(0X114) ++#define RCC_BR_RSTSCLRR U(0X118) ++#define RCC_MP_RSTSSETR U(0X11C) ++#define RCC_MP_RSTSCLRR U(0X120) ++#define RCC_MP_IWDGFZSETR U(0X124) ++#define RCC_MP_IWDGFZCLRR U(0X128) ++#define RCC_MP_CIER U(0X200) ++#define RCC_MP_CIFR U(0X204) ++#define RCC_BDCR U(0X400) ++#define RCC_RDLSICR U(0X404) ++#define RCC_OCENSETR U(0X420) ++#define RCC_OCENCLRR U(0X424) ++#define RCC_OCRDYR U(0X428) ++#define RCC_HSICFGR U(0X440) ++#define RCC_CSICFGR U(0X444) ++#define RCC_MCO1CFGR U(0X460) ++#define RCC_MCO2CFGR U(0X464) ++#define RCC_DBGCFGR U(0X468) ++#define RCC_RCK12SELR U(0X480) ++#define RCC_RCK3SELR U(0X484) ++#define RCC_RCK4SELR U(0X488) ++#define RCC_PLL1CR U(0X4A0) ++#define RCC_PLL1CFGR1 U(0X4A4) ++#define RCC_PLL1CFGR2 U(0X4A8) ++#define RCC_PLL1FRACR U(0X4AC) ++#define RCC_PLL1CSGR U(0X4B0) ++#define RCC_PLL2CR U(0X4D0) ++#define RCC_PLL2CFGR1 U(0X4D4) ++#define RCC_PLL2CFGR2 U(0X4D8) ++#define RCC_PLL2FRACR U(0X4DC) ++#define RCC_PLL2CSGR U(0X4E0) ++#define RCC_PLL3CR U(0X500) ++#define RCC_PLL3CFGR1 U(0X504) ++#define RCC_PLL3CFGR2 U(0X508) ++#define RCC_PLL3FRACR U(0X50C) ++#define RCC_PLL3CSGR U(0X510) ++#define RCC_PLL4CR U(0X520) ++#define RCC_PLL4CFGR1 U(0X524) ++#define RCC_PLL4CFGR2 U(0X528) ++#define RCC_PLL4FRACR U(0X52C) ++#define RCC_PLL4CSGR U(0X530) ++#define RCC_MPCKSELR U(0X540) ++#define RCC_ASSCKSELR U(0X544) ++#define RCC_MSSCKSELR U(0X548) ++#define RCC_CPERCKSELR U(0X54C) ++#define RCC_RTCDIVR U(0X560) ++#define RCC_MPCKDIVR U(0X564) ++#define RCC_AXIDIVR U(0X568) ++#define RCC_MLAHBDIVR U(0X56C) ++#define RCC_APB1DIVR U(0X570) ++#define RCC_APB2DIVR U(0X574) ++#define RCC_APB3DIVR U(0X578) ++#define RCC_APB4DIVR U(0X57C) ++#define RCC_APB5DIVR U(0X580) ++#define RCC_APB6DIVR U(0X584) ++#define RCC_TIMG1PRER U(0X5A0) ++#define RCC_TIMG2PRER U(0X5A4) ++#define RCC_TIMG3PRER U(0X5A8) ++#define RCC_DDRITFCR U(0X5C0) ++#define RCC_I2C12CKSELR U(0X600) ++#define RCC_I2C345CKSELR U(0X604) ++#define RCC_SPI2S1CKSELR U(0X608) ++#define RCC_SPI2S23CKSELR U(0X60C) ++#define RCC_SPI45CKSELR U(0X610) ++#define RCC_UART12CKSELR U(0X614) ++#define RCC_UART35CKSELR U(0X618) ++#define RCC_UART4CKSELR U(0X61C) ++#define RCC_UART6CKSELR U(0X620) ++#define RCC_UART78CKSELR U(0X624) ++#define RCC_LPTIM1CKSELR U(0X628) ++#define RCC_LPTIM23CKSELR U(0X62C) ++#define RCC_LPTIM45CKSELR U(0X630) ++#define RCC_SAI1CKSELR U(0X634) ++#define RCC_SAI2CKSELR U(0X638) ++#define RCC_FDCANCKSELR U(0X63C) ++#define RCC_SPDIFCKSELR U(0X640) ++#define RCC_ADC12CKSELR U(0X644) ++#define RCC_SDMMC12CKSELR U(0X648) ++#define RCC_ETH12CKSELR U(0X64C) ++#define RCC_USBCKSELR U(0X650) ++#define RCC_QSPICKSELR U(0X654) ++#define RCC_FMCCKSELR U(0X658) ++#define RCC_RNG1CKSELR U(0X65C) ++#define RCC_STGENCKSELR U(0X660) ++#define RCC_DCMIPPCKSELR U(0X664) ++#define RCC_SAESCKSELR U(0X668) ++#define RCC_APB1RSTSETR U(0X6A0) ++#define RCC_APB1RSTCLRR U(0X6A4) ++#define RCC_APB2RSTSETR U(0X6A8) ++#define RCC_APB2RSTCLRR U(0X6AC) ++#define RCC_APB3RSTSETR U(0X6B0) ++#define RCC_APB3RSTCLRR U(0X6B4) ++#define RCC_APB4RSTSETR U(0X6B8) ++#define RCC_APB4RSTCLRR U(0X6BC) ++#define RCC_APB5RSTSETR U(0X6C0) ++#define RCC_APB5RSTCLRR U(0X6C4) ++#define RCC_APB6RSTSETR U(0X6C8) ++#define RCC_APB6RSTCLRR U(0X6CC) ++#define RCC_AHB2RSTSETR U(0X6D0) ++#define RCC_AHB2RSTCLRR U(0X6D4) ++#define RCC_AHB4RSTSETR U(0X6E0) ++#define RCC_AHB4RSTCLRR U(0X6E4) ++#define RCC_AHB5RSTSETR U(0X6E8) ++#define RCC_AHB5RSTCLRR U(0X6EC) ++#define RCC_AHB6RSTSETR U(0X6F0) ++#define RCC_AHB6RSTCLRR U(0X6F4) ++#define RCC_MP_APB1ENSETR U(0X700) ++#define RCC_MP_APB1ENCLRR U(0X704) ++#define RCC_MP_APB2ENSETR U(0X708) ++#define RCC_MP_APB2ENCLRR U(0X70C) ++#define RCC_MP_APB3ENSETR U(0X710) ++#define RCC_MP_APB3ENCLRR U(0X714) ++#define RCC_MP_S_APB3ENSETR U(0X718) ++#define RCC_MP_S_APB3ENCLRR U(0X71C) ++#define RCC_MP_NS_APB3ENSETR U(0X720) ++#define RCC_MP_NS_APB3ENCLRR U(0X724) ++#define RCC_MP_APB4ENSETR U(0X728) ++#define RCC_MP_APB4ENCLRR U(0X72C) ++#define RCC_MP_S_APB4ENSETR U(0X730) ++#define RCC_MP_S_APB4ENCLRR U(0X734) ++#define RCC_MP_NS_APB4ENSETR U(0X738) ++#define RCC_MP_NS_APB4ENCLRR U(0X73C) ++#define RCC_MP_APB5ENSETR U(0X740) ++#define RCC_MP_APB5ENCLRR U(0X744) ++#define RCC_MP_APB6ENSETR U(0X748) ++#define RCC_MP_APB6ENCLRR U(0X74C) ++#define RCC_MP_AHB2ENSETR U(0X750) ++#define RCC_MP_AHB2ENCLRR U(0X754) ++#define RCC_MP_AHB4ENSETR U(0X760) ++#define RCC_MP_AHB4ENCLRR U(0X764) ++#define RCC_MP_S_AHB4ENSETR U(0X768) ++#define RCC_MP_S_AHB4ENCLRR U(0X76C) ++#define RCC_MP_NS_AHB4ENSETR U(0X770) ++#define RCC_MP_NS_AHB4ENCLRR U(0X774) ++#define RCC_MP_AHB5ENSETR U(0X778) ++#define RCC_MP_AHB5ENCLRR U(0X77C) ++#define RCC_MP_AHB6ENSETR U(0X780) ++#define RCC_MP_AHB6ENCLRR U(0X784) ++#define RCC_MP_S_AHB6ENSETR U(0X788) ++#define RCC_MP_S_AHB6ENCLRR U(0X78C) ++#define RCC_MP_NS_AHB6ENSETR U(0X790) ++#define RCC_MP_NS_AHB6ENCLRR U(0X794) ++#define RCC_MP_APB1LPENSETR U(0X800) ++#define RCC_MP_APB1LPENCLRR U(0X804) ++#define RCC_MP_APB2LPENSETR U(0X808) ++#define RCC_MP_APB2LPENCLRR U(0X80C) ++#define RCC_MP_APB3LPENSETR U(0X810) ++#define RCC_MP_APB3LPENCLRR U(0X814) ++#define RCC_MP_S_APB3LPENSETR U(0X818) ++#define RCC_MP_S_APB3LPENCLRR U(0X81C) ++#define RCC_MP_NS_APB3LPENSETR U(0X820) ++#define RCC_MP_NS_APB3LPENCLRR U(0X824) ++#define RCC_MP_APB4LPENSETR U(0X828) ++#define RCC_MP_APB4LPENCLRR U(0X82C) ++#define RCC_MP_S_APB4LPENSETR U(0X830) ++#define RCC_MP_S_APB4LPENCLRR U(0X834) ++#define RCC_MP_NS_APB4LPENSETR U(0X838) ++#define RCC_MP_NS_APB4LPENCLRR U(0X83C) ++#define RCC_MP_APB5LPENSETR U(0X840) ++#define RCC_MP_APB5LPENCLRR U(0X844) ++#define RCC_MP_APB6LPENSETR U(0X848) ++#define RCC_MP_APB6LPENCLRR U(0X84C) ++#define RCC_MP_AHB2LPENSETR U(0X850) ++#define RCC_MP_AHB2LPENCLRR U(0X854) ++#define RCC_MP_AHB4LPENSETR U(0X858) ++#define RCC_MP_AHB4LPENCLRR U(0X85C) ++#define RCC_MP_S_AHB4LPENSETR U(0X868) ++#define RCC_MP_S_AHB4LPENCLRR U(0X86C) ++#define RCC_MP_NS_AHB4LPENSETR U(0X870) ++#define RCC_MP_NS_AHB4LPENCLRR U(0X874) ++#define RCC_MP_AHB5LPENSETR U(0X878) ++#define RCC_MP_AHB5LPENCLRR U(0X87C) ++#define RCC_MP_AHB6LPENSETR U(0X880) ++#define RCC_MP_AHB6LPENCLRR U(0X884) ++#define RCC_MP_S_AHB6LPENSETR U(0X888) ++#define RCC_MP_S_AHB6LPENCLRR U(0X88C) ++#define RCC_MP_NS_AHB6LPENSETR U(0X890) ++#define RCC_MP_NS_AHB6LPENCLRR U(0X894) ++#define RCC_MP_S_AXIMLPENSETR U(0X898) ++#define RCC_MP_S_AXIMLPENCLRR U(0X89C) ++#define RCC_MP_NS_AXIMLPENSETR U(0X8A0) ++#define RCC_MP_NS_AXIMLPENCLRR U(0X8A4) ++#define RCC_MP_MLAHBLPENSETR U(0X8A8) ++#define RCC_MP_MLAHBLPENCLRR U(0X8AC) ++#define RCC_APB3SECSR U(0X8C0) ++#define RCC_APB4SECSR U(0X8C4) ++#define RCC_APB5SECSR U(0X8C8) ++#define RCC_APB6SECSR U(0X8CC) ++#define RCC_AHB2SECSR U(0X8D0) ++#define RCC_AHB4SECSR U(0X8D4) ++#define RCC_AHB5SECSR U(0X8D8) ++#define RCC_AHB6SECSR U(0X8DC) ++#define RCC_VERR U(0XFF4) ++#define RCC_IDR U(0XFF8) ++#define RCC_SIDR U(0XFFC) ++ ++/* RCC_SECCFGR register fields */ ++#define RCC_SECCFGR_HSISEC BIT(0) ++#define RCC_SECCFGR_CSISEC BIT(1) ++#define RCC_SECCFGR_HSESEC BIT(2) ++#define RCC_SECCFGR_LSISEC BIT(3) ++#define RCC_SECCFGR_LSESEC BIT(4) ++#define RCC_SECCFGR_PLL12SEC BIT(8) ++#define RCC_SECCFGR_PLL3SEC BIT(9) ++#define RCC_SECCFGR_PLL4SEC BIT(10) ++#define RCC_SECCFGR_MPUSEC BIT(11) ++#define RCC_SECCFGR_AXISEC BIT(12) ++#define RCC_SECCFGR_MLAHBSEC BIT(13) ++#define RCC_SECCFGR_APB3DIVSEC BIT(16) ++#define RCC_SECCFGR_APB4DIVSEC BIT(17) ++#define RCC_SECCFGR_APB5DIVSEC BIT(18) ++#define RCC_SECCFGR_APB6DIVSEC BIT(19) ++#define RCC_SECCFGR_TIMG3SEC BIT(20) ++#define RCC_SECCFGR_CPERSEC BIT(21) ++#define RCC_SECCFGR_MCO1SEC BIT(22) ++#define RCC_SECCFGR_MCO2SEC BIT(23) ++#define RCC_SECCFGR_STPSEC BIT(24) ++#define RCC_SECCFGR_RSTSEC BIT(25) ++#define RCC_SECCFGR_PWRSEC BIT(31) ++ ++/* RCC_MP_SREQSETR register fields */ ++#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) ++ ++/* RCC_MP_SREQCLRR register fields */ ++#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) ++ ++/* RCC_MP_APRSTCR register fields */ ++#define RCC_MP_APRSTCR_RDCTLEN BIT(0) ++#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) ++#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 ++ ++/* RCC_MP_APRSTSR register fields */ ++#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) ++#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 ++ ++/* RCC_PWRLPDLYCR register fields */ ++#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) ++#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 ++ ++/* RCC_MP_GRSTCSETR register fields */ ++#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) ++#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) ++ ++/* RCC_BR_RSTSCLRR register fields */ ++#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) ++#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) ++#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) ++#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) ++#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) ++#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) ++#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) ++#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) ++#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) ++#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) ++ ++/* RCC_MP_RSTSSETR register fields */ ++#define RCC_MP_RSTSSETR_PORRSTF BIT(0) ++#define RCC_MP_RSTSSETR_BORRSTF BIT(1) ++#define RCC_MP_RSTSSETR_PADRSTF BIT(2) ++#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) ++#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) ++#define RCC_MP_RSTSSETR_VCPURSTF BIT(5) ++#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) ++#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) ++#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) ++#define RCC_MP_RSTSSETR_STP2RSTF BIT(10) ++#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) ++#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) ++#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) ++#define RCC_MP_RSTSSETR_SPARE BIT(15) ++ ++/* RCC_MP_RSTSCLRR register fields */ ++#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_VCPURSTF BIT(5) ++#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_STP2RSTF BIT(10) ++#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_SPARE BIT(15) ++ ++/* RCC_MP_IWDGFZSETR register fields */ ++#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) ++#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) ++ ++/* RCC_MP_IWDGFZCLRR register fields */ ++#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) ++#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) ++ ++/* RCC_MP_CIER register fields */ ++#define RCC_MP_CIER_LSIRDYIE BIT(0) ++#define RCC_MP_CIER_LSERDYIE BIT(1) ++#define RCC_MP_CIER_HSIRDYIE BIT(2) ++#define RCC_MP_CIER_HSERDYIE BIT(3) ++#define RCC_MP_CIER_CSIRDYIE BIT(4) ++#define RCC_MP_CIER_PLL1DYIE BIT(8) ++#define RCC_MP_CIER_PLL2DYIE BIT(9) ++#define RCC_MP_CIER_PLL3DYIE BIT(10) ++#define RCC_MP_CIER_PLL4DYIE BIT(11) ++#define RCC_MP_CIER_LSECSSIE BIT(16) ++#define RCC_MP_CIER_WKUPIE BIT(20) ++ ++/* RCC_MP_CIFR register fields */ ++#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_LSECSSF BIT(16) ++#define RCC_MP_CIFR_WKUPF BIT(20) ++ ++/* RCC_BDCR register fields */ ++#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) ++#define RCC_BDCR_LSECSSD BIT(9) ++#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) ++#define RCC_BDCR_RTCSRC_SHIFT 16 ++#define RCC_BDCR_RTCCKEN BIT(20) ++#define RCC_BDCR_VSWRST BIT(31) ++ ++#define RCC_BDCR_LSEBYP_BIT 1 ++#define RCC_BDCR_LSERDY_BIT 2 ++#define RCC_BDCR_DIGBYP_BIT 3 ++#define RCC_BDCR_LSECSSON_BIT 8 ++ ++#define RCC_BDCR_LSEDRV_WIDTH 2 ++ ++/* RCC_RDLSICR register fields */ ++#define RCC_RDLSICR_LSION BIT(0) ++#define RCC_RDLSICR_LSIRDY BIT(1) ++#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) ++#define RCC_RDLSICR_MRD_SHIFT 16 ++#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) ++#define RCC_RDLSICR_EADLY_SHIFT 24 ++#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) ++#define RCC_RDLSICR_SPARE_SHIFT 27 ++ ++#define RCC_RDLSICR_LSIRDY_BIT 1 ++ ++/* RCC_OCENSETR register fields */ ++#define RCC_OCENSETR_HSION BIT(0) ++#define RCC_OCENSETR_HSIKERON BIT(1) ++#define RCC_OCENSETR_CSION BIT(4) ++#define RCC_OCENSETR_CSIKERON BIT(5) ++#define RCC_OCENSETR_DIGBYP BIT(7) ++#define RCC_OCENSETR_HSEON BIT(8) ++#define RCC_OCENSETR_HSEKERON BIT(9) ++#define RCC_OCENSETR_HSEBYP BIT(10) ++#define RCC_OCENSETR_HSECSSON BIT(11) ++ ++#define RCC_OCENR_DIGBYP_BIT 7 ++#define RCC_OCENR_HSEBYP_BIT 10 ++#define RCC_OCENR_HSECSSON_BIT 11 ++ ++/* RCC_OCENCLRR register fields */ ++#define RCC_OCENCLRR_HSION BIT(0) ++#define RCC_OCENCLRR_HSIKERON BIT(1) ++#define RCC_OCENCLRR_CSION BIT(4) ++#define RCC_OCENCLRR_CSIKERON BIT(5) ++#define RCC_OCENCLRR_DIGBYP BIT(7) ++#define RCC_OCENCLRR_HSEON BIT(8) ++#define RCC_OCENCLRR_HSEKERON BIT(9) ++#define RCC_OCENCLRR_HSEBYP BIT(10) ++ ++/* RCC_OCRDYR register fields */ ++#define RCC_OCRDYR_HSIRDY BIT(0) ++#define RCC_OCRDYR_HSIDIVRDY BIT(2) ++#define RCC_OCRDYR_CSIRDY BIT(4) ++#define RCC_OCRDYR_HSERDY BIT(8) ++#define RCC_OCRDYR_MPUCKRDY BIT(23) ++#define RCC_OCRDYR_AXICKRDY BIT(24) ++ ++#define RCC_OCRDYR_HSIRDY_BIT 0 ++#define RCC_OCRDYR_HSIDIVRDY_BIT 2 ++#define RCC_OCRDYR_CSIRDY_BIT 4 ++#define RCC_OCRDYR_HSERDY_BIT 8 ++ ++/* RCC_HSICFGR register fields */ ++#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) ++#define RCC_HSICFGR_HSIDIV_SHIFT 0 ++#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) ++#define RCC_HSICFGR_HSITRIM_SHIFT 8 ++#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) ++#define RCC_HSICFGR_HSICAL_SHIFT 16 ++ ++/* RCC_CSICFGR register fields */ ++#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) ++#define RCC_CSICFGR_CSITRIM_SHIFT 8 ++#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) ++#define RCC_CSICFGR_CSICAL_SHIFT 16 ++ ++/* RCC_MCO1CFGR register fields */ ++#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) ++#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 ++#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) ++#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 ++#define RCC_MCO1CFGR_MCO1ON BIT(12) ++ ++/* RCC_MCO2CFGR register fields */ ++#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) ++#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 ++#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) ++#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 ++#define RCC_MCO2CFGR_MCO2ON BIT(12) ++ ++/* RCC_DBGCFGR register fields */ ++#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) ++#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 ++#define RCC_DBGCFGR_DBGCKEN BIT(8) ++#define RCC_DBGCFGR_TRACECKEN BIT(9) ++#define RCC_DBGCFGR_DBGRST BIT(12) ++ ++/* RCC_RCK12SELR register fields */ ++#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) ++#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 ++#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) ++ ++/* RCC_RCK3SELR register fields */ ++#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) ++#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 ++#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) ++ ++/* RCC_RCK4SELR register fields */ ++#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) ++#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 ++#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) ++ ++/* RCC_PLL1CR register fields */ ++#define RCC_PLL1CR_PLLON BIT(0) ++#define RCC_PLL1CR_PLL1RDY BIT(1) ++#define RCC_PLL1CR_SSCG_CTRL BIT(2) ++#define RCC_PLL1CR_DIVPEN BIT(4) ++#define RCC_PLL1CR_DIVQEN BIT(5) ++#define RCC_PLL1CR_DIVREN BIT(6) ++ ++/* RCC_PLL1CFGR1 register fields */ ++#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL1CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) ++#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 ++ ++/* RCC_PLL1CFGR2 register fields */ ++#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL1CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL1CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL1FRACR register fields */ ++#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL1FRACR_FRACV_SHIFT 3 ++#define RCC_PLL1FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL1CSGR register fields */ ++#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL1CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 ++ ++/* RCC_PLL2CR register fields */ ++#define RCC_PLL2CR_PLLON BIT(0) ++#define RCC_PLL2CR_PLL2RDY BIT(1) ++#define RCC_PLL2CR_SSCG_CTRL BIT(2) ++#define RCC_PLL2CR_DIVPEN BIT(4) ++#define RCC_PLL2CR_DIVQEN BIT(5) ++#define RCC_PLL2CR_DIVREN BIT(6) ++ ++/* RCC_PLL2CFGR1 register fields */ ++#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL2CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) ++#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 ++ ++/* RCC_PLL2CFGR2 register fields */ ++#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL2CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL2CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL2FRACR register fields */ ++#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL2FRACR_FRACV_SHIFT 3 ++#define RCC_PLL2FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL2CSGR register fields */ ++#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL2CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 ++ ++/* RCC_PLL3CR register fields */ ++#define RCC_PLL3CR_PLLON BIT(0) ++#define RCC_PLL3CR_PLL3RDY BIT(1) ++#define RCC_PLL3CR_SSCG_CTRL BIT(2) ++#define RCC_PLL3CR_DIVPEN BIT(4) ++#define RCC_PLL3CR_DIVQEN BIT(5) ++#define RCC_PLL3CR_DIVREN BIT(6) ++ ++/* RCC_PLL3CFGR1 register fields */ ++#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL3CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) ++#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 ++#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) ++#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 ++ ++/* RCC_PLL3CFGR2 register fields */ ++#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL3CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL3CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL3FRACR register fields */ ++#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL3FRACR_FRACV_SHIFT 3 ++#define RCC_PLL3FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL3CSGR register fields */ ++#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL3CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 ++ ++/* RCC_PLL4CR register fields */ ++#define RCC_PLL4CR_PLLON BIT(0) ++#define RCC_PLL4CR_PLL4RDY BIT(1) ++#define RCC_PLL4CR_SSCG_CTRL BIT(2) ++#define RCC_PLL4CR_DIVPEN BIT(4) ++#define RCC_PLL4CR_DIVQEN BIT(5) ++#define RCC_PLL4CR_DIVREN BIT(6) ++ ++/* RCC_PLL4CFGR1 register fields */ ++#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL4CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) ++#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 ++#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) ++#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 ++ ++/* RCC_PLL4CFGR2 register fields */ ++#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL4CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL4CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL4FRACR register fields */ ++#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL4FRACR_FRACV_SHIFT 3 ++#define RCC_PLL4FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL4CSGR register fields */ ++#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL4CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 ++ ++/* RCC_MPCKSELR register fields */ ++#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) ++#define RCC_MPCKSELR_MPUSRC_SHIFT 0 ++#define RCC_MPCKSELR_MPUSRCRDY BIT(31) ++ ++/* RCC_ASSCKSELR register fields */ ++#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) ++#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 ++#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) ++ ++/* RCC_MSSCKSELR register fields */ ++#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK(1, 0) ++#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 ++#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) ++ ++/* RCC_CPERCKSELR register fields */ ++#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) ++#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 ++ ++/* RCC_RTCDIVR register fields */ ++#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) ++#define RCC_RTCDIVR_RTCDIV_SHIFT 0 ++ ++/* RCC_MPCKDIVR register fields */ ++#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(3, 0) ++#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 ++#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) ++ ++/* RCC_AXIDIVR register fields */ ++#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) ++#define RCC_AXIDIVR_AXIDIV_SHIFT 0 ++#define RCC_AXIDIVR_AXIDIVRDY BIT(31) ++ ++/* RCC_MLAHBDIVR register fields */ ++#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK(3, 0) ++#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 ++#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) ++ ++/* RCC_APB1DIVR register fields */ ++#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) ++#define RCC_APB1DIVR_APB1DIV_SHIFT 0 ++#define RCC_APB1DIVR_APB1DIVRDY BIT(31) ++ ++/* RCC_APB2DIVR register fields */ ++#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) ++#define RCC_APB2DIVR_APB2DIV_SHIFT 0 ++#define RCC_APB2DIVR_APB2DIVRDY BIT(31) ++ ++/* RCC_APB3DIVR register fields */ ++#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) ++#define RCC_APB3DIVR_APB3DIV_SHIFT 0 ++#define RCC_APB3DIVR_APB3DIVRDY BIT(31) ++ ++/* RCC_APB4DIVR register fields */ ++#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) ++#define RCC_APB4DIVR_APB4DIV_SHIFT 0 ++#define RCC_APB4DIVR_APB4DIVRDY BIT(31) ++ ++/* RCC_APB5DIVR register fields */ ++#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) ++#define RCC_APB5DIVR_APB5DIV_SHIFT 0 ++#define RCC_APB5DIVR_APB5DIVRDY BIT(31) ++ ++/* RCC_APB6DIVR register fields */ ++#define RCC_APB6DIVR_APB6DIV_MASK GENMASK(2, 0) ++#define RCC_APB6DIVR_APB6DIV_SHIFT 0 ++#define RCC_APB6DIVR_APB6DIVRDY BIT(31) ++ ++/* RCC_TIMG1PRER register fields */ ++#define RCC_TIMG1PRER_TIMG1PRE BIT(0) ++#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) ++ ++/* RCC_TIMG2PRER register fields */ ++#define RCC_TIMG2PRER_TIMG2PRE BIT(0) ++#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) ++ ++/* RCC_TIMG3PRER register fields */ ++#define RCC_TIMG3PRER_TIMG3PRE BIT(0) ++#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) ++ ++/* RCC_DDRITFCR register fields */ ++#define RCC_DDRITFCR_DDRC1EN BIT(0) ++#define RCC_DDRITFCR_DDRC1LPEN BIT(1) ++#define RCC_DDRITFCR_DDRPHYCEN BIT(4) ++#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) ++#define RCC_DDRITFCR_DDRCAPBEN BIT(6) ++#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) ++#define RCC_DDRITFCR_AXIDCGEN BIT(8) ++#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) ++#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) ++#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) ++#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 ++#define RCC_DDRITFCR_DDRCAPBRST BIT(14) ++#define RCC_DDRITFCR_DDRCAXIRST BIT(15) ++#define RCC_DDRITFCR_DDRCORERST BIT(16) ++#define RCC_DDRITFCR_DPHYAPBRST BIT(17) ++#define RCC_DDRITFCR_DPHYRST BIT(18) ++#define RCC_DDRITFCR_DPHYCTLRST BIT(19) ++#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) ++#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 ++#define RCC_DDRITFCR_GSKPMOD BIT(23) ++#define RCC_DDRITFCR_GSKPCTRL BIT(24) ++#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) ++#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 ++#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) ++#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 ++ ++/* RCC_I2C12CKSELR register fields */ ++#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) ++#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 ++ ++/* RCC_I2C345CKSELR register fields */ ++#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK(2, 0) ++#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 ++#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK(5, 3) ++#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 ++#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK(8, 6) ++#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 ++ ++/* RCC_SPI2S1CKSELR register fields */ ++#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) ++#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 ++ ++/* RCC_SPI2S23CKSELR register fields */ ++#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) ++#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 ++ ++/* RCC_SPI45CKSELR register fields */ ++#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK(2, 0) ++#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 ++#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK(5, 3) ++#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 ++ ++/* RCC_UART12CKSELR register fields */ ++#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK(2, 0) ++#define RCC_UART12CKSELR_UART1SRC_SHIFT 0 ++#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK(5, 3) ++#define RCC_UART12CKSELR_UART2SRC_SHIFT 3 ++ ++/* RCC_UART35CKSELR register fields */ ++#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) ++#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 ++ ++/* RCC_UART4CKSELR register fields */ ++#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK(2, 0) ++#define RCC_UART4CKSELR_UART4SRC_SHIFT 0 ++ ++/* RCC_UART6CKSELR register fields */ ++#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) ++#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 ++ ++/* RCC_UART78CKSELR register fields */ ++#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) ++#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 ++ ++/* RCC_LPTIM1CKSELR register fields */ ++#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) ++#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 ++ ++/* RCC_LPTIM23CKSELR register fields */ ++#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK(2, 0) ++#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 ++#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK(5, 3) ++#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 ++ ++/* RCC_LPTIM45CKSELR register fields */ ++#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) ++#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 ++ ++/* RCC_SAI1CKSELR register fields */ ++#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) ++#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 ++ ++/* RCC_SAI2CKSELR register fields */ ++#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) ++#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 ++ ++/* RCC_FDCANCKSELR register fields */ ++#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) ++#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 ++ ++/* RCC_SPDIFCKSELR register fields */ ++#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) ++#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 ++ ++/* RCC_ADC12CKSELR register fields */ ++#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK(1, 0) ++#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 ++#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK(3, 2) ++#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 ++ ++/* RCC_SDMMC12CKSELR register fields */ ++#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK(2, 0) ++#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 ++#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK(5, 3) ++#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 ++ ++/* RCC_ETH12CKSELR register fields */ ++#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK(1, 0) ++#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 ++#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK(7, 4) ++#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 ++#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK(9, 8) ++#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 ++#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK(15, 12) ++#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 ++ ++/* RCC_USBCKSELR register fields */ ++#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) ++#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 ++#define RCC_USBCKSELR_USBOSRC BIT(4) ++ ++/* 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_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_DCMIPPCKSELR register fields */ ++#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK(1, 0) ++#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 ++ ++/* RCC_SAESCKSELR register fields */ ++#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK(1, 0) ++#define RCC_SAESCKSELR_SAESSRC_SHIFT 0 ++ ++/* RCC_APB1RSTSETR register fields */ ++#define RCC_APB1RSTSETR_TIM2RST BIT(0) ++#define RCC_APB1RSTSETR_TIM3RST BIT(1) ++#define RCC_APB1RSTSETR_TIM4RST BIT(2) ++#define RCC_APB1RSTSETR_TIM5RST BIT(3) ++#define RCC_APB1RSTSETR_TIM6RST BIT(4) ++#define RCC_APB1RSTSETR_TIM7RST BIT(5) ++#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) ++#define RCC_APB1RSTSETR_SPI2RST BIT(11) ++#define RCC_APB1RSTSETR_SPI3RST BIT(12) ++#define RCC_APB1RSTSETR_USART3RST BIT(15) ++#define RCC_APB1RSTSETR_UART4RST BIT(16) ++#define RCC_APB1RSTSETR_UART5RST BIT(17) ++#define RCC_APB1RSTSETR_UART7RST BIT(18) ++#define RCC_APB1RSTSETR_UART8RST BIT(19) ++#define RCC_APB1RSTSETR_I2C1RST BIT(21) ++#define RCC_APB1RSTSETR_I2C2RST BIT(22) ++#define RCC_APB1RSTSETR_SPDIFRST BIT(26) ++ ++/* RCC_APB1RSTCLRR register fields */ ++#define RCC_APB1RSTCLRR_TIM2RST BIT(0) ++#define RCC_APB1RSTCLRR_TIM3RST BIT(1) ++#define RCC_APB1RSTCLRR_TIM4RST BIT(2) ++#define RCC_APB1RSTCLRR_TIM5RST BIT(3) ++#define RCC_APB1RSTCLRR_TIM6RST BIT(4) ++#define RCC_APB1RSTCLRR_TIM7RST BIT(5) ++#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) ++#define RCC_APB1RSTCLRR_SPI2RST BIT(11) ++#define RCC_APB1RSTCLRR_SPI3RST BIT(12) ++#define RCC_APB1RSTCLRR_USART3RST BIT(15) ++#define RCC_APB1RSTCLRR_UART4RST BIT(16) ++#define RCC_APB1RSTCLRR_UART5RST BIT(17) ++#define RCC_APB1RSTCLRR_UART7RST BIT(18) ++#define RCC_APB1RSTCLRR_UART8RST BIT(19) ++#define RCC_APB1RSTCLRR_I2C1RST BIT(21) ++#define RCC_APB1RSTCLRR_I2C2RST BIT(22) ++#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) ++ ++/* RCC_APB2RSTSETR register fields */ ++#define RCC_APB2RSTSETR_TIM1RST BIT(0) ++#define RCC_APB2RSTSETR_TIM8RST BIT(1) ++#define RCC_APB2RSTSETR_SPI1RST BIT(8) ++#define RCC_APB2RSTSETR_USART6RST BIT(13) ++#define RCC_APB2RSTSETR_SAI1RST BIT(16) ++#define RCC_APB2RSTSETR_SAI2RST BIT(17) ++#define RCC_APB2RSTSETR_DFSDMRST BIT(20) ++#define RCC_APB2RSTSETR_FDCANRST BIT(24) ++ ++/* RCC_APB2RSTCLRR register fields */ ++#define RCC_APB2RSTCLRR_TIM1RST BIT(0) ++#define RCC_APB2RSTCLRR_TIM8RST BIT(1) ++#define RCC_APB2RSTCLRR_SPI1RST BIT(8) ++#define RCC_APB2RSTCLRR_USART6RST BIT(13) ++#define RCC_APB2RSTCLRR_SAI1RST BIT(16) ++#define RCC_APB2RSTCLRR_SAI2RST BIT(17) ++#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) ++#define RCC_APB2RSTCLRR_FDCANRST BIT(24) ++ ++/* RCC_APB3RSTSETR register fields */ ++#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) ++#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) ++#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) ++#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) ++#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) ++#define RCC_APB3RSTSETR_VREFRST BIT(13) ++#define RCC_APB3RSTSETR_DTSRST BIT(16) ++#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) ++ ++/* RCC_APB3RSTCLRR register fields */ ++#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) ++#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) ++#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) ++#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) ++#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) ++#define RCC_APB3RSTCLRR_VREFRST BIT(13) ++#define RCC_APB3RSTCLRR_DTSRST BIT(16) ++#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) ++ ++/* RCC_APB4RSTSETR register fields */ ++#define RCC_APB4RSTSETR_LTDCRST BIT(0) ++#define RCC_APB4RSTSETR_DCMIPPRST BIT(1) ++#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) ++#define RCC_APB4RSTSETR_USBPHYRST BIT(16) ++ ++/* RCC_APB4RSTCLRR register fields */ ++#define RCC_APB4RSTCLRR_LTDCRST BIT(0) ++#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) ++#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) ++#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) ++ ++/* RCC_APB5RSTSETR register fields */ ++#define RCC_APB5RSTSETR_STGENRST BIT(20) ++ ++/* RCC_APB5RSTCLRR register fields */ ++#define RCC_APB5RSTCLRR_STGENRST BIT(20) ++ ++/* RCC_APB6RSTSETR register fields */ ++#define RCC_APB6RSTSETR_USART1RST BIT(0) ++#define RCC_APB6RSTSETR_USART2RST BIT(1) ++#define RCC_APB6RSTSETR_SPI4RST BIT(2) ++#define RCC_APB6RSTSETR_SPI5RST BIT(3) ++#define RCC_APB6RSTSETR_I2C3RST BIT(4) ++#define RCC_APB6RSTSETR_I2C4RST BIT(5) ++#define RCC_APB6RSTSETR_I2C5RST BIT(6) ++#define RCC_APB6RSTSETR_TIM12RST BIT(7) ++#define RCC_APB6RSTSETR_TIM13RST BIT(8) ++#define RCC_APB6RSTSETR_TIM14RST BIT(9) ++#define RCC_APB6RSTSETR_TIM15RST BIT(10) ++#define RCC_APB6RSTSETR_TIM16RST BIT(11) ++#define RCC_APB6RSTSETR_TIM17RST BIT(12) ++ ++/* RCC_APB6RSTCLRR register fields */ ++#define RCC_APB6RSTCLRR_USART1RST BIT(0) ++#define RCC_APB6RSTCLRR_USART2RST BIT(1) ++#define RCC_APB6RSTCLRR_SPI4RST BIT(2) ++#define RCC_APB6RSTCLRR_SPI5RST BIT(3) ++#define RCC_APB6RSTCLRR_I2C3RST BIT(4) ++#define RCC_APB6RSTCLRR_I2C4RST BIT(5) ++#define RCC_APB6RSTCLRR_I2C5RST BIT(6) ++#define RCC_APB6RSTCLRR_TIM12RST BIT(7) ++#define RCC_APB6RSTCLRR_TIM13RST BIT(8) ++#define RCC_APB6RSTCLRR_TIM14RST BIT(9) ++#define RCC_APB6RSTCLRR_TIM15RST BIT(10) ++#define RCC_APB6RSTCLRR_TIM16RST BIT(11) ++#define RCC_APB6RSTCLRR_TIM17RST BIT(12) ++ ++/* RCC_AHB2RSTSETR register fields */ ++#define RCC_AHB2RSTSETR_DMA1RST BIT(0) ++#define RCC_AHB2RSTSETR_DMA2RST BIT(1) ++#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) ++#define RCC_AHB2RSTSETR_DMA3RST BIT(3) ++#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) ++#define RCC_AHB2RSTSETR_ADC1RST BIT(5) ++#define RCC_AHB2RSTSETR_ADC2RST BIT(6) ++#define RCC_AHB2RSTSETR_USBORST BIT(8) ++ ++/* RCC_AHB2RSTCLRR register fields */ ++#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) ++#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) ++#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) ++#define RCC_AHB2RSTCLRR_DMA3RST BIT(3) ++#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) ++#define RCC_AHB2RSTCLRR_ADC1RST BIT(5) ++#define RCC_AHB2RSTCLRR_ADC2RST BIT(6) ++#define RCC_AHB2RSTCLRR_USBORST BIT(8) ++ ++/* RCC_AHB4RSTSETR register fields */ ++#define RCC_AHB4RSTSETR_GPIOARST BIT(0) ++#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) ++#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) ++#define RCC_AHB4RSTSETR_GPIODRST BIT(3) ++#define RCC_AHB4RSTSETR_GPIOERST BIT(4) ++#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) ++#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) ++#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) ++#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) ++#define RCC_AHB4RSTSETR_TSCRST BIT(15) ++ ++/* RCC_AHB4RSTCLRR register fields */ ++#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) ++#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) ++#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) ++#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) ++#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) ++#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) ++#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) ++#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) ++#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) ++#define RCC_AHB4RSTCLRR_TSCRST BIT(15) ++ ++/* RCC_AHB5RSTSETR register fields */ ++#define RCC_AHB5RSTSETR_PKARST BIT(2) ++#define RCC_AHB5RSTSETR_SAESRST BIT(3) ++#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) ++#define RCC_AHB5RSTSETR_HASH1RST BIT(5) ++#define RCC_AHB5RSTSETR_RNG1RST BIT(6) ++#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) ++ ++/* RCC_AHB5RSTCLRR register fields */ ++#define RCC_AHB5RSTCLRR_PKARST BIT(2) ++#define RCC_AHB5RSTCLRR_SAESRST BIT(3) ++#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) ++#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) ++#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) ++#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) ++ ++/* RCC_AHB6RSTSETR register fields */ ++#define RCC_AHB6RSTSETR_MDMARST BIT(0) ++#define RCC_AHB6RSTSETR_MCERST BIT(1) ++#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) ++#define RCC_AHB6RSTSETR_FMCRST BIT(12) ++#define RCC_AHB6RSTSETR_QSPIRST BIT(14) ++#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) ++#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) ++#define RCC_AHB6RSTSETR_CRC1RST BIT(20) ++#define RCC_AHB6RSTSETR_USBHRST BIT(24) ++#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) ++ ++/* RCC_AHB6RSTCLRR register fields */ ++#define RCC_AHB6RSTCLRR_MDMARST BIT(0) ++#define RCC_AHB6RSTCLRR_MCERST BIT(1) ++#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) ++#define RCC_AHB6RSTCLRR_FMCRST BIT(12) ++#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) ++#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) ++#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) ++#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) ++#define RCC_AHB6RSTCLRR_USBHRST BIT(24) ++#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) ++ ++/* RCC_MP_APB1ENSETR register fields */ ++#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) ++#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) ++#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) ++#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) ++#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) ++#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) ++#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) ++#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) ++#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) ++#define RCC_MP_APB1ENSETR_USART3EN BIT(15) ++#define RCC_MP_APB1ENSETR_UART4EN BIT(16) ++#define RCC_MP_APB1ENSETR_UART5EN BIT(17) ++#define RCC_MP_APB1ENSETR_UART7EN BIT(18) ++#define RCC_MP_APB1ENSETR_UART8EN BIT(19) ++#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) ++#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) ++#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) ++ ++/* RCC_MP_APB1ENCLRR register fields */ ++#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) ++#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) ++#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) ++#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) ++#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) ++#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) ++#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) ++#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) ++#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) ++#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) ++#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) ++#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) ++#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) ++#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) ++#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) ++#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) ++#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) ++ ++/* RCC_MP_APB2ENSETR register fields */ ++#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) ++#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) ++#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) ++#define RCC_MP_APB2ENSETR_USART6EN BIT(13) ++#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) ++#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) ++#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) ++#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) ++#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) ++ ++/* RCC_MP_APB2ENCLRR register fields */ ++#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) ++#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) ++#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) ++#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) ++#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) ++#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) ++#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) ++#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) ++#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) ++ ++/* RCC_MP_APB3ENSETR register fields */ ++#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) ++#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) ++#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) ++#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) ++#define RCC_MP_APB3ENSETR_VREFEN BIT(13) ++#define RCC_MP_APB3ENSETR_DTSEN BIT(16) ++#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) ++#define RCC_MP_APB3ENSETR_HDPEN BIT(20) ++ ++/* RCC_MP_APB3ENCLRR register fields */ ++#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) ++#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) ++#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) ++#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) ++#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) ++#define RCC_MP_APB3ENCLRR_DTSEN BIT(16) ++#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) ++#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) ++ ++/* RCC_MP_S_APB3ENSETR register fields */ ++#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) ++ ++/* RCC_MP_S_APB3ENCLRR register fields */ ++#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) ++ ++/* RCC_MP_NS_APB3ENSETR register fields */ ++#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) ++ ++/* RCC_MP_NS_APB3ENCLRR register fields */ ++#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) ++ ++/* RCC_MP_APB4ENSETR register fields */ ++#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) ++#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) ++#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) ++#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) ++#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) ++ ++/* RCC_MP_APB4ENCLRR register fields */ ++#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) ++#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) ++#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) ++#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) ++#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) ++ ++/* RCC_MP_S_APB4ENSETR register fields */ ++#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) ++ ++/* RCC_MP_S_APB4ENCLRR register fields */ ++#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) ++ ++/* RCC_MP_NS_APB4ENSETR register fields */ ++#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) ++ ++/* RCC_MP_NS_APB4ENCLRR register fields */ ++#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) ++ ++/* RCC_MP_APB5ENSETR register fields */ ++#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) ++#define RCC_MP_APB5ENSETR_TZCEN BIT(11) ++#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) ++#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) ++#define RCC_MP_APB5ENSETR_BSECEN BIT(16) ++#define RCC_MP_APB5ENSETR_STGENCEN BIT(20) ++ ++/* RCC_MP_APB5ENCLRR register fields */ ++#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) ++#define RCC_MP_APB5ENCLRR_TZCEN BIT(11) ++#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) ++#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) ++#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) ++#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) ++ ++/* RCC_MP_APB6ENSETR register fields */ ++#define RCC_MP_APB6ENSETR_USART1EN BIT(0) ++#define RCC_MP_APB6ENSETR_USART2EN BIT(1) ++#define RCC_MP_APB6ENSETR_SPI4EN BIT(2) ++#define RCC_MP_APB6ENSETR_SPI5EN BIT(3) ++#define RCC_MP_APB6ENSETR_I2C3EN BIT(4) ++#define RCC_MP_APB6ENSETR_I2C4EN BIT(5) ++#define RCC_MP_APB6ENSETR_I2C5EN BIT(6) ++#define RCC_MP_APB6ENSETR_TIM12EN BIT(7) ++#define RCC_MP_APB6ENSETR_TIM13EN BIT(8) ++#define RCC_MP_APB6ENSETR_TIM14EN BIT(9) ++#define RCC_MP_APB6ENSETR_TIM15EN BIT(10) ++#define RCC_MP_APB6ENSETR_TIM16EN BIT(11) ++#define RCC_MP_APB6ENSETR_TIM17EN BIT(12) ++ ++/* RCC_MP_APB6ENCLRR register fields */ ++#define RCC_MP_APB6ENCLRR_USART1EN BIT(0) ++#define RCC_MP_APB6ENCLRR_USART2EN BIT(1) ++#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) ++#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) ++#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) ++#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) ++#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) ++#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) ++#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) ++#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) ++#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) ++#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) ++#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) ++ ++/* RCC_MP_AHB2ENSETR register fields */ ++#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) ++#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) ++#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) ++#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) ++#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) ++#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) ++#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) ++#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) ++ ++/* RCC_MP_AHB2ENCLRR register fields */ ++#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) ++#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) ++#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) ++#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) ++#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) ++#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) ++#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) ++#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) ++ ++/* RCC_MP_AHB4ENSETR register fields */ ++#define RCC_MP_AHB4ENSETR_TSCEN BIT(15) ++ ++/* RCC_MP_AHB4ENCLRR register fields */ ++#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) ++ ++/* RCC_MP_S_AHB4ENSETR register fields */ ++#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) ++#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) ++#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) ++#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) ++#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) ++#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) ++#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) ++#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) ++#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) ++ ++/* RCC_MP_S_AHB4ENCLRR register fields */ ++#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) ++#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) ++#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) ++#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) ++#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) ++#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) ++#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) ++#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) ++#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) ++ ++/* RCC_MP_NS_AHB4ENSETR register fields */ ++#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) ++#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) ++#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) ++#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) ++#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) ++#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) ++#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) ++#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) ++#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) ++ ++/* RCC_MP_NS_AHB4ENCLRR register fields */ ++#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) ++#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) ++#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) ++ ++/* RCC_MP_AHB5ENSETR register fields */ ++#define RCC_MP_AHB5ENSETR_PKAEN BIT(2) ++#define RCC_MP_AHB5ENSETR_SAESEN BIT(3) ++#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) ++#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) ++#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) ++#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) ++#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) ++ ++/* RCC_MP_AHB5ENCLRR register fields */ ++#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) ++#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) ++#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) ++#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) ++#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) ++#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) ++#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) ++ ++/* RCC_MP_AHB6ENSETR register fields */ ++#define RCC_MP_AHB6ENSETR_MCEEN BIT(1) ++#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) ++#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) ++#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) ++#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) ++#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) ++#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) ++#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) ++#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) ++#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) ++#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) ++#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) ++#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) ++#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) ++#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) ++ ++/* RCC_MP_AHB6ENCLRR register fields */ ++#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) ++#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) ++#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) ++#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) ++#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) ++#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) ++#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) ++#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) ++#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) ++#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) ++#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) ++#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) ++#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) ++#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) ++#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) ++ ++/* RCC_MP_S_AHB6ENSETR register fields */ ++#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) ++ ++/* RCC_MP_S_AHB6ENCLRR register fields */ ++#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) ++ ++/* RCC_MP_NS_AHB6ENSETR register fields */ ++#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) ++ ++/* RCC_MP_NS_AHB6ENCLRR register fields */ ++#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) ++ ++/* RCC_MP_APB1LPENSETR register fields */ ++#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) ++#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) ++#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) ++#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) ++#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) ++#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) ++#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) ++#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) ++#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) ++#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) ++#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) ++#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) ++#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) ++#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) ++#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) ++#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) ++#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) ++ ++/* RCC_MP_APB1LPENCLRR register fields */ ++#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) ++#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) ++#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) ++#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) ++#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) ++#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) ++#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) ++#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) ++#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) ++#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) ++#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) ++#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) ++#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) ++#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) ++#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) ++#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) ++#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) ++ ++/* RCC_MP_APB2LPENSETR register fields */ ++#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) ++#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) ++#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) ++#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) ++#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) ++#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) ++#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) ++#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) ++#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) ++ ++/* RCC_MP_APB2LPENCLRR register fields */ ++#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) ++#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) ++#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) ++#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) ++#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) ++#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) ++#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) ++#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) ++#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) ++ ++/* RCC_MP_APB3LPENSETR register fields */ ++#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) ++#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) ++#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) ++#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) ++#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) ++#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) ++#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) ++ ++/* RCC_MP_APB3LPENCLRR register fields */ ++#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) ++#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) ++#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) ++#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) ++#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) ++#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) ++#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) ++ ++/* RCC_MP_S_APB3LPENSETR register fields */ ++#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) ++ ++/* RCC_MP_S_APB3LPENCLRR register fields */ ++#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) ++ ++/* RCC_MP_NS_APB3LPENSETR register fields */ ++#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) ++ ++/* RCC_MP_NS_APB3LPENCLRR register fields */ ++#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) ++ ++/* RCC_MP_APB4LPENSETR register fields */ ++#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) ++#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) ++#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) ++#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) ++#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) ++#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) ++ ++/* RCC_MP_APB4LPENCLRR register fields */ ++#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) ++#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) ++#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) ++#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) ++#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) ++#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) ++ ++/* RCC_MP_S_APB4LPENSETR register fields */ ++#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) ++ ++/* RCC_MP_S_APB4LPENCLRR register fields */ ++#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) ++ ++/* RCC_MP_NS_APB4LPENSETR register fields */ ++#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) ++ ++/* RCC_MP_NS_APB4LPENCLRR register fields */ ++#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) ++ ++/* RCC_MP_APB5LPENSETR register fields */ ++#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) ++#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) ++#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) ++#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) ++#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) ++#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) ++#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) ++ ++/* RCC_MP_APB5LPENCLRR register fields */ ++#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) ++#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) ++#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) ++#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) ++#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) ++#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) ++#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) ++ ++/* RCC_MP_APB6LPENSETR register fields */ ++#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) ++#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) ++#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) ++#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) ++#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) ++#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) ++#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) ++#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) ++#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) ++#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) ++#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) ++#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) ++#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) ++ ++/* RCC_MP_APB6LPENCLRR register fields */ ++#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) ++#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) ++#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) ++#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) ++#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) ++#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) ++#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) ++#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) ++#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) ++#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) ++#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) ++#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) ++#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) ++ ++/* RCC_MP_AHB2LPENSETR register fields */ ++#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) ++#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) ++#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) ++#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) ++#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) ++#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) ++#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) ++#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) ++ ++/* RCC_MP_AHB2LPENCLRR register fields */ ++#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) ++#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) ++#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) ++#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) ++#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) ++#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) ++#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) ++#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) ++ ++/* RCC_MP_AHB4LPENSETR register fields */ ++#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) ++ ++/* RCC_MP_AHB4LPENCLRR register fields */ ++#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) ++ ++/* RCC_MP_S_AHB4LPENSETR register fields */ ++#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) ++#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) ++#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) ++#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) ++#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) ++#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) ++#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) ++#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) ++#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) ++ ++/* RCC_MP_S_AHB4LPENCLRR register fields */ ++#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) ++#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) ++#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) ++ ++/* RCC_MP_NS_AHB4LPENSETR register fields */ ++#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) ++#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) ++#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) ++ ++/* RCC_MP_NS_AHB4LPENCLRR register fields */ ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) ++#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) ++ ++/* RCC_MP_AHB5LPENSETR register fields */ ++#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) ++#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) ++#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) ++#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) ++#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) ++#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) ++ ++/* RCC_MP_AHB5LPENCLRR register fields */ ++#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) ++#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) ++#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) ++#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) ++#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) ++#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) ++ ++/* RCC_MP_AHB6LPENSETR register fields */ ++#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) ++#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) ++#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) ++#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) ++#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) ++#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) ++#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) ++#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) ++#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) ++#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) ++#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) ++#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) ++#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) ++#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) ++#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) ++#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) ++#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) ++ ++/* RCC_MP_AHB6LPENCLRR register fields */ ++#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) ++#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) ++#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) ++#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) ++#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) ++#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) ++#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) ++#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) ++#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) ++#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) ++#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) ++#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) ++#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) ++#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) ++#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) ++#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) ++#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) ++ ++/* RCC_MP_S_AHB6LPENSETR register fields */ ++#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) ++ ++/* RCC_MP_S_AHB6LPENCLRR register fields */ ++#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) ++ ++/* RCC_MP_NS_AHB6LPENSETR register fields */ ++#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) ++ ++/* RCC_MP_NS_AHB6LPENCLRR register fields */ ++#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) ++ ++/* RCC_MP_S_AXIMLPENSETR register fields */ ++#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MP_S_AXIMLPENCLRR register fields */ ++#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MP_NS_AXIMLPENSETR register fields */ ++#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MP_NS_AXIMLPENCLRR register fields */ ++#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MP_MLAHBLPENSETR register fields */ ++#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) ++#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) ++#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) ++ ++/* RCC_MP_MLAHBLPENCLRR register fields */ ++#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) ++#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) ++#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) ++ ++/* RCC_APB3SECSR register fields */ ++#define RCC_APB3SECSR_LPTIM2SECF BIT(0) ++#define RCC_APB3SECSR_LPTIM3SECF BIT(1) ++#define RCC_APB3SECSR_VREFSECF BIT(13) ++ ++/* RCC_APB4SECSR register fields */ ++#define RCC_APB4SECSR_DCMIPPSECF BIT(1) ++#define RCC_APB4SECSR_USBPHYSECF BIT(16) ++ ++/* RCC_APB5SECSR register fields */ ++#define RCC_APB5SECSR_RTCSECF BIT(8) ++#define RCC_APB5SECSR_TZCSECF BIT(11) ++#define RCC_APB5SECSR_ETZPCSECF BIT(13) ++#define RCC_APB5SECSR_IWDG1SECF BIT(15) ++#define RCC_APB5SECSR_BSECSECF BIT(16) ++#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK(21, 20) ++#define RCC_APB5SECSR_STGENCSECF_SHIFT 20 ++ ++/* RCC_APB6SECSR register fields */ ++#define RCC_APB6SECSR_USART1SECF BIT(0) ++#define RCC_APB6SECSR_USART2SECF BIT(1) ++#define RCC_APB6SECSR_SPI4SECF BIT(2) ++#define RCC_APB6SECSR_SPI5SECF BIT(3) ++#define RCC_APB6SECSR_I2C3SECF BIT(4) ++#define RCC_APB6SECSR_I2C4SECF BIT(5) ++#define RCC_APB6SECSR_I2C5SECF BIT(6) ++#define RCC_APB6SECSR_TIM12SECF BIT(7) ++#define RCC_APB6SECSR_TIM13SECF BIT(8) ++#define RCC_APB6SECSR_TIM14SECF BIT(9) ++#define RCC_APB6SECSR_TIM15SECF BIT(10) ++#define RCC_APB6SECSR_TIM16SECF BIT(11) ++#define RCC_APB6SECSR_TIM17SECF BIT(12) ++ ++/* RCC_AHB2SECSR register fields */ ++#define RCC_AHB2SECSR_DMA3SECF BIT(3) ++#define RCC_AHB2SECSR_DMAMUX2SECF BIT(4) ++#define RCC_AHB2SECSR_ADC1SECF BIT(5) ++#define RCC_AHB2SECSR_ADC2SECF BIT(6) ++#define RCC_AHB2SECSR_USBOSECF BIT(8) ++ ++/* RCC_AHB4SECSR register fields */ ++#define RCC_AHB4SECSR_TSCSECF BIT(15) ++ ++/* RCC_AHB5SECSR register fields */ ++#define RCC_AHB5SECSR_PKASECF BIT(2) ++#define RCC_AHB5SECSR_SAESSECF BIT(3) ++#define RCC_AHB5SECSR_CRYP1SECF BIT(4) ++#define RCC_AHB5SECSR_HASH1SECF BIT(5) ++#define RCC_AHB5SECSR_RNG1SECF BIT(6) ++#define RCC_AHB5SECSR_BKPSRAMSECF BIT(8) ++ ++/* RCC_AHB6SECSR register fields */ ++#define RCC_AHB6SECSR_MCESECF BIT(1) ++#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK(11, 7) ++#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 ++#define RCC_AHB6SECSR_FMCSECF BIT(12) ++#define RCC_AHB6SECSR_QSPISECF BIT(14) ++#define RCC_AHB6SECSR_SDMMC1SECF BIT(16) ++#define RCC_AHB6SECSR_SDMMC2SECF BIT(17) ++#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK(31, 27) ++#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 ++ ++/* RCC_VERR register fields */ ++#define RCC_VERR_MINREV_MASK GENMASK(3, 0) ++#define RCC_VERR_MINREV_SHIFT 0 ++#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) ++#define RCC_VERR_MAJREV_SHIFT 4 ++ ++/* RCC_IDR register fields */ ++#define RCC_IDR_ID_MASK GENMASK(31, 0) ++#define RCC_IDR_ID_SHIFT 0 ++ ++/* RCC_SIDR register fields */ ++#define RCC_SIDR_SID_MASK GENMASK(31, 0) ++#define RCC_SIDR_SID_SHIFT 0 ++ ++/* 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) ++#define RCC_PLLNCR_DIVEN_SHIFT 4 ++ ++/* Used for all RCC_PLLCFGR1 registers */ ++#define RCC_PLLNCFGR1_DIVM_SHIFT 16 ++#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) ++#define RCC_PLLNCFGR1_DIVN_SHIFT 0 ++#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) ++ ++/* Only for PLL3 and PLL4 */ ++#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 ++#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) ++ ++/* Used for all RCC_PLLCFGR2 registers */ ++#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) ++#define RCC_PLLNCFGR2_DIVP_SHIFT 0 ++#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 ++#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLLNCFGR2_DIVR_SHIFT 16 ++#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) ++ ++/* Used for all RCC_PLLFRACR registers */ ++#define RCC_PLLNFRACR_FRACV_SHIFT 3 ++#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLLNFRACR_FRACLE BIT(16) ++ ++/* Used for all RCC_PLLCSGR registers */ ++#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 ++#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 ++#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 ++#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) ++ ++/* Used for most of RCC_SELR registers */ ++#define RCC_SELR_SRC_MASK GENMASK(2, 0) ++#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) ++#define RCC_SELR_SRCRDY BIT(31) ++ ++/* Values of RCC_MPCKSELR register */ ++#define RCC_MPCKSELR_HSI 0x00000000 ++#define RCC_MPCKSELR_HSE 0x00000001 ++#define RCC_MPCKSELR_PLL 0x00000002 ++#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 ++ ++/* Values of RCC_ASSCKSELR register */ ++#define RCC_ASSCKSELR_HSI 0x00000000 ++#define RCC_ASSCKSELR_HSE 0x00000001 ++#define RCC_ASSCKSELR_PLL 0x00000002 ++ ++/* Values of RCC_MSSCKSELR register */ ++#define RCC_MSSCKSELR_HSI 0x00000000 ++#define RCC_MSSCKSELR_HSE 0x00000001 ++#define RCC_MSSCKSELR_CSI 0x00000002 ++#define RCC_MSSCKSELR_PLL 0x00000003 ++ ++/* Values of RCC_CPERCKSELR register */ ++#define RCC_CPERCKSELR_HSI 0x00000000 ++#define RCC_CPERCKSELR_CSI 0x00000001 ++#define RCC_CPERCKSELR_HSE 0x00000002 ++ ++/* Used for most of DIVR register: max div for RTC */ ++#define RCC_DIVR_DIV_MASK GENMASK(5, 0) ++#define RCC_DIVR_DIVRDY BIT(31) ++ ++/* Masks for specific DIVR registers */ ++#define RCC_APBXDIV_MASK GENMASK(2, 0) ++#define RCC_MPUDIV_MASK GENMASK(2, 0) ++#define RCC_AXIDIV_MASK GENMASK(2, 0) ++#define RCC_MLAHBDIV_MASK GENMASK(3, 0) ++ ++/* Used for TIMER Prescaler */ ++#define RCC_TIMGXPRER_TIMGXPRE BIT(0) ++ ++/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ ++#define RCC_MP_ENCLRR_OFFSET U(4) ++ ++/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ ++#define RCC_RSTCLRR_OFFSET U(4) ++ ++/* RCC_OCENSETR register fields */ ++#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) ++ ++#define RCC_OCENR_DIGBYP_BIT 7 ++#define RCC_OCENR_HSEBYP_BIT 10 ++#define RCC_OCENR_HSECSSON_BIT 11 ++ ++/* Used for RCC_MCO related operations */ ++#define RCC_MCOCFG_MCOON BIT(12) ++#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) ++#define RCC_MCOCFG_MCODIV_SHIFT 4 ++#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) ++ ++#define RCC_UART4CKSELR_HSI 0x00000002 ++ ++#define RCC_CPERCKSELR_PERSRC_MASK GENMASK(1, 0) ++#define RCC_CPERCKSELR_PERSRC_SHIFT 0 ++ ++#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) ++#define RCC_USBCKSELR_USBOSRC_SHIFT 4 ++ ++#define RCC_DDRITFCR_DDRCKMOD_SSR 0 ++#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) ++#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) ++ ++#define RCC_DDRITFCR_DDRC2EN BIT(0) ++#define RCC_DDRITFCR_DDRC2LPEN BIT(1) ++ ++#define RCC_MP_CIFR_MASK U(0x110F1F) ++#define RCC_OFFSET_MASK GENMASK(11, 0) ++ ++#endif /* STM32MP1_RCC_H */ +diff --git a/include/drivers/st/stm32mp15_rcc.h b/include/drivers/st/stm32mp15_rcc.h +new file mode 100644 +index 000000000..7b50b2725 +--- /dev/null ++++ b/include/drivers/st/stm32mp15_rcc.h +@@ -0,0 +1,2328 @@ ++/* ++ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP1_RCC_H ++#define STM32MP1_RCC_H ++ ++#include ++ ++#define RCC_TZCR U(0x00) ++#define RCC_OCENSETR U(0x0C) ++#define RCC_OCENCLRR U(0x10) ++#define RCC_HSICFGR U(0x18) ++#define RCC_CSICFGR U(0x1C) ++#define RCC_MPCKSELR U(0x20) ++#define RCC_ASSCKSELR U(0x24) ++#define RCC_RCK12SELR U(0x28) ++#define RCC_MPCKDIVR U(0x2C) ++#define RCC_AXIDIVR U(0x30) ++#define RCC_APB4DIVR U(0x3C) ++#define RCC_APB5DIVR U(0x40) ++#define RCC_RTCDIVR U(0x44) ++#define RCC_MSSCKSELR U(0x48) ++#define RCC_PLL1CR U(0x80) ++#define RCC_PLL1CFGR1 U(0x84) ++#define RCC_PLL1CFGR2 U(0x88) ++#define RCC_PLL1FRACR U(0x8C) ++#define RCC_PLL1CSGR U(0x90) ++#define RCC_PLL2CR U(0x94) ++#define RCC_PLL2CFGR1 U(0x98) ++#define RCC_PLL2CFGR2 U(0x9C) ++#define RCC_PLL2FRACR U(0xA0) ++#define RCC_PLL2CSGR U(0xA4) ++#define RCC_I2C46CKSELR U(0xC0) ++#define RCC_SPI6CKSELR U(0xC4) ++#define RCC_UART1CKSELR U(0xC8) ++#define RCC_RNG1CKSELR U(0xCC) ++#define RCC_CPERCKSELR U(0xD0) ++#define RCC_STGENCKSELR U(0xD4) ++#define RCC_DDRITFCR U(0xD8) ++#define RCC_MP_BOOTCR U(0x100) ++#define RCC_MP_SREQSETR U(0x104) ++#define RCC_MP_SREQCLRR U(0x108) ++#define RCC_MP_GCR U(0x10C) ++#define RCC_MP_APRSTCR U(0x110) ++#define RCC_MP_APRSTSR U(0x114) ++#define RCC_BDCR U(0x140) ++#define RCC_RDLSICR U(0x144) ++#define RCC_APB4RSTSETR U(0x180) ++#define RCC_APB4RSTCLRR U(0x184) ++#define RCC_APB5RSTSETR U(0x188) ++#define RCC_APB5RSTCLRR U(0x18C) ++#define RCC_AHB5RSTSETR U(0x190) ++#define RCC_AHB5RSTCLRR U(0x194) ++#define RCC_AHB6RSTSETR U(0x198) ++#define RCC_AHB6RSTCLRR U(0x19C) ++#define RCC_TZAHB6RSTSETR U(0x1A0) ++#define RCC_TZAHB6RSTCLRR U(0x1A4) ++#define RCC_MP_APB4ENSETR U(0x200) ++#define RCC_MP_APB4ENCLRR U(0x204) ++#define RCC_MP_APB5ENSETR U(0x208) ++#define RCC_MP_APB5ENCLRR U(0x20C) ++#define RCC_MP_AHB5ENSETR U(0x210) ++#define RCC_MP_AHB5ENCLRR U(0x214) ++#define RCC_MP_AHB6ENSETR U(0x218) ++#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) ++#define RCC_MP_APB5LPENCLRR U(0x30C) ++#define RCC_MP_AHB5LPENSETR U(0x310) ++#define RCC_MP_AHB5LPENCLRR U(0x314) ++#define RCC_MP_AHB6LPENSETR U(0x318) ++#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) ++#define RCC_MP_IWDGFZSETR U(0x40C) ++#define RCC_MP_IWDGFZCLRR U(0x410) ++#define RCC_MP_CIER U(0x414) ++#define RCC_MP_CIFR U(0x418) ++#define RCC_PWRLPDLYCR U(0x41C) ++#define RCC_MP_RSTSSETR U(0x420) ++#define RCC_MCO1CFGR U(0x800) ++#define RCC_MCO2CFGR U(0x804) ++#define RCC_OCRDYR U(0x808) ++#define RCC_DBGCFGR U(0x80C) ++#define RCC_RCK3SELR U(0x820) ++#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) ++#define RCC_PLL3CR U(0x880) ++#define RCC_PLL3CFGR1 U(0x884) ++#define RCC_PLL3CFGR2 U(0x888) ++#define RCC_PLL3FRACR U(0x88C) ++#define RCC_PLL3CSGR U(0x890) ++#define RCC_PLL4CR U(0x894) ++#define RCC_PLL4CFGR1 U(0x898) ++#define RCC_PLL4CFGR2 U(0x89C) ++#define RCC_PLL4FRACR U(0x8A0) ++#define RCC_PLL4CSGR U(0x8A4) ++#define RCC_I2C12CKSELR U(0x8C0) ++#define RCC_I2C35CKSELR U(0x8C4) ++#define RCC_SAI1CKSELR U(0x8C8) ++#define RCC_SAI2CKSELR U(0x8CC) ++#define RCC_SAI3CKSELR U(0x8D0) ++#define RCC_SAI4CKSELR U(0x8D4) ++#define RCC_SPI2S1CKSELR U(0x8D8) ++#define RCC_SPI2S23CKSELR U(0x8DC) ++#define RCC_SPI45CKSELR U(0x8E0) ++#define RCC_UART6CKSELR U(0x8E4) ++#define RCC_UART24CKSELR U(0x8E8) ++#define RCC_UART35CKSELR U(0x8EC) ++#define RCC_UART78CKSELR U(0x8F0) ++#define RCC_SDMMC12CKSELR U(0x8F4) ++#define RCC_SDMMC3CKSELR U(0x8F8) ++#define RCC_ETHCKSELR U(0x8FC) ++#define RCC_QSPICKSELR U(0x900) ++#define RCC_FMCCKSELR U(0x904) ++#define RCC_FDCANCKSELR U(0x90C) ++#define RCC_SPDIFCKSELR U(0x914) ++#define RCC_CECCKSELR U(0x918) ++#define RCC_USBCKSELR U(0x91C) ++#define RCC_RNG2CKSELR U(0x920) ++#define RCC_DSICKSELR U(0x924) ++#define RCC_ADCCKSELR U(0x928) ++#define RCC_LPTIM45CKSELR U(0x92C) ++#define RCC_LPTIM23CKSELR U(0x930) ++#define RCC_LPTIM1CKSELR U(0x934) ++#define RCC_APB1RSTSETR U(0x980) ++#define RCC_APB1RSTCLRR U(0x984) ++#define RCC_APB2RSTSETR U(0x988) ++#define RCC_APB2RSTCLRR U(0x98C) ++#define RCC_APB3RSTSETR U(0x990) ++#define RCC_APB3RSTCLRR U(0x994) ++#define RCC_AHB2RSTSETR U(0x998) ++#define RCC_AHB2RSTCLRR U(0x99C) ++#define RCC_AHB3RSTSETR U(0x9A0) ++#define RCC_AHB3RSTCLRR U(0x9A4) ++#define RCC_AHB4RSTSETR U(0x9A8) ++#define RCC_AHB4RSTCLRR U(0x9AC) ++#define RCC_MP_APB1ENSETR U(0xA00) ++#define RCC_MP_APB1ENCLRR U(0xA04) ++#define RCC_MP_APB2ENSETR U(0xA08) ++#define RCC_MP_APB2ENCLRR U(0xA0C) ++#define RCC_MP_APB3ENSETR U(0xA10) ++#define RCC_MP_APB3ENCLRR U(0xA14) ++#define RCC_MP_AHB2ENSETR U(0xA18) ++#define RCC_MP_AHB2ENCLRR U(0xA1C) ++#define RCC_MP_AHB3ENSETR U(0xA20) ++#define RCC_MP_AHB3ENCLRR U(0xA24) ++#define RCC_MP_AHB4ENSETR U(0xA28) ++#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) ++#define RCC_MP_APB2LPENCLRR U(0xB0C) ++#define RCC_MP_APB3LPENSETR U(0xB10) ++#define RCC_MP_APB3LPENCLRR U(0xB14) ++#define RCC_MP_AHB2LPENSETR U(0xB18) ++#define RCC_MP_AHB2LPENCLRR U(0xB1C) ++#define RCC_MP_AHB3LPENSETR U(0xB20) ++#define RCC_MP_AHB3LPENCLRR U(0xB24) ++#define RCC_MP_AHB4LPENSETR U(0xB28) ++#define RCC_MP_AHB4LPENCLRR U(0xB2C) ++#define RCC_MP_AXIMLPENSETR U(0xB30) ++#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) ++ ++/* RCC_TZCR register fields */ ++#define RCC_TZCR_TZEN BIT(0) ++#define RCC_TZCR_MCKPROT BIT(1) ++ ++/* RCC_OCENSETR register fields */ ++#define RCC_OCENSETR_HSION BIT(0) ++#define RCC_OCENSETR_HSIKERON BIT(1) ++#define RCC_OCENSETR_CSION BIT(4) ++#define RCC_OCENSETR_CSIKERON BIT(5) ++#define RCC_OCENSETR_DIGBYP BIT(7) ++#define RCC_OCENSETR_HSEON BIT(8) ++#define RCC_OCENSETR_HSEKERON BIT(9) ++#define RCC_OCENSETR_HSEBYP BIT(10) ++#define RCC_OCENSETR_HSECSSON BIT(11) ++ ++/* RCC_OCENCLRR register fields */ ++#define RCC_OCENCLRR_HSION BIT(0) ++#define RCC_OCENCLRR_HSIKERON BIT(1) ++#define RCC_OCENCLRR_CSION BIT(4) ++#define RCC_OCENCLRR_CSIKERON BIT(5) ++#define RCC_OCENCLRR_DIGBYP BIT(7) ++#define RCC_OCENCLRR_HSEON BIT(8) ++#define RCC_OCENCLRR_HSEKERON BIT(9) ++#define RCC_OCENCLRR_HSEBYP BIT(10) ++ ++/* RCC_HSICFGR register fields */ ++#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) ++#define RCC_HSICFGR_HSIDIV_SHIFT 0 ++#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) ++#define RCC_HSICFGR_HSITRIM_SHIFT 8 ++#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16) ++#define RCC_HSICFGR_HSICAL_SHIFT 16 ++#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25) ++ ++/* RCC_CSICFGR register fields */ ++#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) ++#define RCC_CSICFGR_CSITRIM_SHIFT 8 ++#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) ++#define RCC_CSICFGR_CSICAL_SHIFT 16 ++ ++/* RCC_MPCKSELR register fields */ ++#define RCC_MPCKSELR_HSI 0x00000000 ++#define RCC_MPCKSELR_HSE 0x00000001 ++#define RCC_MPCKSELR_PLL 0x00000002 ++#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 ++#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) ++#define RCC_MPCKSELR_MPUSRC_SHIFT 0 ++#define RCC_MPCKSELR_MPUSRCRDY BIT(31) ++ ++/* RCC_ASSCKSELR register fields */ ++#define RCC_ASSCKSELR_HSI 0x00000000 ++#define RCC_ASSCKSELR_HSE 0x00000001 ++#define RCC_ASSCKSELR_PLL 0x00000002 ++#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) ++#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 ++#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) ++ ++/* RCC_RCK12SELR register fields */ ++#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) ++#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 ++#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) ++ ++/* RCC_MPCKDIVR register fields */ ++#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(2, 0) ++#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 ++#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) ++ ++/* RCC_AXIDIVR register fields */ ++#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) ++#define RCC_AXIDIVR_AXIDIV_SHIFT 0 ++#define RCC_AXIDIVR_AXIDIVRDY BIT(31) ++ ++/* RCC_APB4DIVR register fields */ ++#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) ++#define RCC_APB4DIVR_APB4DIV_SHIFT 0 ++#define RCC_APB4DIVR_APB4DIVRDY BIT(31) ++ ++/* RCC_APB5DIVR register fields */ ++#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) ++#define RCC_APB5DIVR_APB5DIV_SHIFT 0 ++#define RCC_APB5DIVR_APB5DIVRDY BIT(31) ++ ++/* RCC_RTCDIVR register fields */ ++#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) ++#define RCC_RTCDIVR_RTCDIV_SHIFT 0 ++ ++/* RCC_MSSCKSELR register fields */ ++#define RCC_MSSCKSELR_HSI 0x00000000 ++#define RCC_MSSCKSELR_HSE 0x00000001 ++#define RCC_MSSCKSELR_CSI 0x00000002 ++#define RCC_MSSCKSELR_PLL 0x00000003 ++#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(1, 0) ++#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 ++#define RCC_MSSCKSELR_MCUSSRCRDY BIT(31) ++ ++/* RCC_PLL1CR register fields */ ++#define RCC_PLL1CR_PLLON BIT(0) ++#define RCC_PLL1CR_PLL1RDY BIT(1) ++#define RCC_PLL1CR_SSCG_CTRL BIT(2) ++#define RCC_PLL1CR_DIVPEN BIT(4) ++#define RCC_PLL1CR_DIVQEN BIT(5) ++#define RCC_PLL1CR_DIVREN BIT(6) ++ ++/* RCC_PLL1CFGR1 register fields */ ++#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL1CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) ++#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 ++ ++/* RCC_PLL1CFGR2 register fields */ ++#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL1CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL1CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL1FRACR register fields */ ++#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL1FRACR_FRACV_SHIFT 3 ++#define RCC_PLL1FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL1CSGR register fields */ ++#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL1CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 ++ ++/* RCC_PLL2CR register fields */ ++#define RCC_PLL2CR_PLLON BIT(0) ++#define RCC_PLL2CR_PLL2RDY BIT(1) ++#define RCC_PLL2CR_SSCG_CTRL BIT(2) ++#define RCC_PLL2CR_DIVPEN BIT(4) ++#define RCC_PLL2CR_DIVQEN BIT(5) ++#define RCC_PLL2CR_DIVREN BIT(6) ++ ++/* RCC_PLL2CFGR1 register fields */ ++#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL2CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) ++#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 ++ ++/* RCC_PLL2CFGR2 register fields */ ++#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL2CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL2CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL2FRACR register fields */ ++#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL2FRACR_FRACV_SHIFT 3 ++#define RCC_PLL2FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL2CSGR register fields */ ++#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL2CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 ++ ++/* 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_CPERCKSELR register fields */ ++#define RCC_CPERCKSELR_HSI 0x00000000 ++#define RCC_CPERCKSELR_CSI 0x00000001 ++#define RCC_CPERCKSELR_HSE 0x00000002 ++#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) ++#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 ++ ++/* RCC_STGENCKSELR register fields */ ++#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) ++#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 ++ ++/* RCC_DDRITFCR register fields */ ++#define RCC_DDRITFCR_DDRC1EN BIT(0) ++#define RCC_DDRITFCR_DDRC1LPEN BIT(1) ++#define RCC_DDRITFCR_DDRC2EN BIT(2) ++#define RCC_DDRITFCR_DDRC2LPEN BIT(3) ++#define RCC_DDRITFCR_DDRPHYCEN BIT(4) ++#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) ++#define RCC_DDRITFCR_DDRCAPBEN BIT(6) ++#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) ++#define RCC_DDRITFCR_AXIDCGEN BIT(8) ++#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) ++#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) ++#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) ++#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 ++#define RCC_DDRITFCR_DDRCAPBRST BIT(14) ++#define RCC_DDRITFCR_DDRCAXIRST BIT(15) ++#define RCC_DDRITFCR_DDRCORERST BIT(16) ++#define RCC_DDRITFCR_DPHYAPBRST BIT(17) ++#define RCC_DDRITFCR_DPHYRST BIT(18) ++#define RCC_DDRITFCR_DPHYCTLRST BIT(19) ++#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) ++#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 ++#define RCC_DDRITFCR_DDRCKMOD_SSR 0 ++#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) ++#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) ++#define RCC_DDRITFCR_GSKPMOD BIT(23) ++#define RCC_DDRITFCR_GSKPCTRL BIT(24) ++#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) ++#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 ++#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) ++#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 ++ ++/* RCC_MP_BOOTCR register fields */ ++#define RCC_MP_BOOTCR_MCU_BEN BIT(0) ++#define RCC_MP_BOOTCR_MPU_BEN BIT(1) ++ ++/* RCC_MP_SREQSETR register fields */ ++#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) ++#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) ++ ++/* RCC_MP_SREQCLRR register fields */ ++#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) ++#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) ++ ++/* RCC_MP_GCR register fields */ ++#define RCC_MP_GCR_BOOT_MCU BIT(0) ++ ++/* RCC_MP_APRSTCR register fields */ ++#define RCC_MP_APRSTCR_RDCTLEN BIT(0) ++#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) ++#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 ++ ++/* RCC_MP_APRSTSR register fields */ ++#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) ++#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 ++ ++/* RCC_BDCR register fields */ ++#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) ++#define RCC_BDCR_LSECSSD BIT(9) ++#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) ++#define RCC_BDCR_RTCSRC_SHIFT 16 ++#define RCC_BDCR_RTCCKEN BIT(20) ++#define RCC_BDCR_VSWRST BIT(31) ++ ++/* RCC_RDLSICR register fields */ ++#define RCC_RDLSICR_LSION BIT(0) ++#define RCC_RDLSICR_LSIRDY BIT(1) ++#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) ++#define RCC_RDLSICR_MRD_SHIFT 16 ++#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) ++#define RCC_RDLSICR_EADLY_SHIFT 24 ++#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) ++#define RCC_RDLSICR_SPARE_SHIFT 27 ++ ++/* RCC_APB4RSTSETR register fields */ ++#define RCC_APB4RSTSETR_LTDCRST BIT(0) ++#define RCC_APB4RSTSETR_DSIRST BIT(4) ++#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) ++#define RCC_APB4RSTSETR_USBPHYRST BIT(16) ++ ++/* RCC_APB4RSTCLRR register fields */ ++#define RCC_APB4RSTCLRR_LTDCRST BIT(0) ++#define RCC_APB4RSTCLRR_DSIRST BIT(4) ++#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) ++#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) ++ ++/* RCC_APB5RSTSETR register fields */ ++#define RCC_APB5RSTSETR_SPI6RST BIT(0) ++#define RCC_APB5RSTSETR_I2C4RST BIT(2) ++#define RCC_APB5RSTSETR_I2C6RST BIT(3) ++#define RCC_APB5RSTSETR_USART1RST BIT(4) ++#define RCC_APB5RSTSETR_STGENRST BIT(20) ++ ++/* RCC_APB5RSTCLRR register fields */ ++#define RCC_APB5RSTCLRR_SPI6RST BIT(0) ++#define RCC_APB5RSTCLRR_I2C4RST BIT(2) ++#define RCC_APB5RSTCLRR_I2C6RST BIT(3) ++#define RCC_APB5RSTCLRR_USART1RST BIT(4) ++#define RCC_APB5RSTCLRR_STGENRST BIT(20) ++ ++/* RCC_AHB5RSTSETR register fields */ ++#define RCC_AHB5RSTSETR_GPIOZRST BIT(0) ++#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) ++#define RCC_AHB5RSTSETR_HASH1RST BIT(5) ++#define RCC_AHB5RSTSETR_RNG1RST BIT(6) ++#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) ++ ++/* RCC_AHB5RSTCLRR register fields */ ++#define RCC_AHB5RSTCLRR_GPIOZRST BIT(0) ++#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) ++#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) ++#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) ++#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) ++ ++/* RCC_AHB6RSTSETR register fields */ ++#define RCC_AHB6RSTSETR_GPURST BIT(5) ++#define RCC_AHB6RSTSETR_ETHMACRST BIT(10) ++#define RCC_AHB6RSTSETR_FMCRST BIT(12) ++#define RCC_AHB6RSTSETR_QSPIRST BIT(14) ++#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) ++#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) ++#define RCC_AHB6RSTSETR_CRC1RST BIT(20) ++#define RCC_AHB6RSTSETR_USBHRST BIT(24) ++ ++/* RCC_AHB6RSTCLRR register fields */ ++#define RCC_AHB6RSTCLRR_ETHMACRST BIT(10) ++#define RCC_AHB6RSTCLRR_FMCRST BIT(12) ++#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) ++#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) ++#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) ++#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) ++#define RCC_AHB6RSTCLRR_USBHRST BIT(24) ++ ++/* RCC_TZAHB6RSTSETR register fields */ ++#define RCC_TZAHB6RSTSETR_MDMARST BIT(0) ++ ++/* RCC_TZAHB6RSTCLRR register fields */ ++#define RCC_TZAHB6RSTCLRR_MDMARST BIT(0) ++ ++/* RCC_MP_APB4ENSETR register fields */ ++#define RCC_MP_APB4ENSETR_LTDCEN BIT(0) ++#define RCC_MP_APB4ENSETR_DSIEN BIT(4) ++#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) ++#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) ++#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) ++#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) ++ ++/* RCC_MP_APB4ENCLRR register fields */ ++#define RCC_MP_APB4ENCLRR_LTDCEN BIT(0) ++#define RCC_MP_APB4ENCLRR_DSIEN BIT(4) ++#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) ++#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) ++#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) ++#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) ++ ++/* RCC_MP_APB5ENSETR register fields */ ++#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_TZC1EN BIT(11) ++#define RCC_MP_APB5ENSETR_TZC2EN BIT(12) ++#define RCC_MP_APB5ENSETR_TZPCEN BIT(13) ++#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) ++#define RCC_MP_APB5ENSETR_BSECEN BIT(16) ++#define RCC_MP_APB5ENSETR_STGENEN BIT(20) ++ ++/* RCC_MP_APB5ENCLRR register fields */ ++#define RCC_MP_APB5ENCLRR_SPI6EN BIT(0) ++#define RCC_MP_APB5ENCLRR_I2C4EN BIT(2) ++#define RCC_MP_APB5ENCLRR_I2C6EN BIT(3) ++#define RCC_MP_APB5ENCLRR_USART1EN BIT(4) ++#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) ++#define RCC_MP_APB5ENCLRR_TZC1EN BIT(11) ++#define RCC_MP_APB5ENCLRR_TZC2EN BIT(12) ++#define RCC_MP_APB5ENCLRR_TZPCEN BIT(13) ++#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) ++#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) ++#define RCC_MP_APB5ENCLRR_STGENEN BIT(20) ++ ++/* RCC_MP_AHB5ENSETR register fields */ ++#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) ++#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) ++#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) ++ ++/* RCC_MP_AHB5ENCLRR register fields */ ++#define RCC_MP_AHB5ENCLRR_GPIOZEN BIT(0) ++#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) ++#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) ++#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) ++#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) ++#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) ++ ++/* RCC_MP_AHB6ENSETR register fields */ ++#define RCC_MP_AHB6ENSETR_MDMAEN BIT(0) ++#define RCC_MP_AHB6ENSETR_GPUEN BIT(5) ++#define RCC_MP_AHB6ENSETR_ETHCKEN BIT(7) ++#define RCC_MP_AHB6ENSETR_ETHTXEN BIT(8) ++#define RCC_MP_AHB6ENSETR_ETHRXEN BIT(9) ++#define RCC_MP_AHB6ENSETR_ETHMACEN BIT(10) ++#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) ++#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) ++#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) ++#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) ++#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) ++#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) ++ ++/* RCC_MP_AHB6ENCLRR register fields */ ++#define RCC_MP_AHB6ENCLRR_MDMAEN BIT(0) ++#define RCC_MP_AHB6ENCLRR_GPUEN BIT(5) ++#define RCC_MP_AHB6ENCLRR_ETHCKEN BIT(7) ++#define RCC_MP_AHB6ENCLRR_ETHTXEN BIT(8) ++#define RCC_MP_AHB6ENCLRR_ETHRXEN BIT(9) ++#define RCC_MP_AHB6ENCLRR_ETHMACEN BIT(10) ++#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) ++#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) ++#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) ++#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) ++#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) ++#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) ++ ++/* RCC_MP_TZAHB6ENSETR register fields */ ++#define RCC_MP_TZAHB6ENSETR_MDMAEN BIT(0) ++ ++/* RCC_MP_TZAHB6ENCLRR register fields */ ++#define RCC_MP_TZAHB6ENCLRR_MDMAEN BIT(0) ++ ++/* RCC_MC_APB4ENSETR register fields */ ++#define RCC_MC_APB4ENSETR_LTDCEN BIT(0) ++#define RCC_MC_APB4ENSETR_DSIEN BIT(4) ++#define RCC_MC_APB4ENSETR_DDRPERFMEN BIT(8) ++#define RCC_MC_APB4ENSETR_USBPHYEN BIT(16) ++#define RCC_MC_APB4ENSETR_STGENROEN BIT(20) ++ ++/* RCC_MC_APB4ENCLRR register fields */ ++#define RCC_MC_APB4ENCLRR_LTDCEN BIT(0) ++#define RCC_MC_APB4ENCLRR_DSIEN BIT(4) ++#define RCC_MC_APB4ENCLRR_DDRPERFMEN BIT(8) ++#define RCC_MC_APB4ENCLRR_USBPHYEN BIT(16) ++#define RCC_MC_APB4ENCLRR_STGENROEN BIT(20) ++ ++/* RCC_MC_APB5ENSETR register fields */ ++#define RCC_MC_APB5ENSETR_SPI6EN BIT(0) ++#define RCC_MC_APB5ENSETR_I2C4EN BIT(2) ++#define RCC_MC_APB5ENSETR_I2C6EN BIT(3) ++#define RCC_MC_APB5ENSETR_USART1EN BIT(4) ++#define RCC_MC_APB5ENSETR_RTCAPBEN BIT(8) ++#define RCC_MC_APB5ENSETR_TZC1EN BIT(11) ++#define RCC_MC_APB5ENSETR_TZC2EN BIT(12) ++#define RCC_MC_APB5ENSETR_TZPCEN BIT(13) ++#define RCC_MC_APB5ENSETR_BSECEN BIT(16) ++#define RCC_MC_APB5ENSETR_STGENEN BIT(20) ++ ++/* RCC_MC_APB5ENCLRR register fields */ ++#define RCC_MC_APB5ENCLRR_SPI6EN BIT(0) ++#define RCC_MC_APB5ENCLRR_I2C4EN BIT(2) ++#define RCC_MC_APB5ENCLRR_I2C6EN BIT(3) ++#define RCC_MC_APB5ENCLRR_USART1EN BIT(4) ++#define RCC_MC_APB5ENCLRR_RTCAPBEN BIT(8) ++#define RCC_MC_APB5ENCLRR_TZC1EN BIT(11) ++#define RCC_MC_APB5ENCLRR_TZC2EN BIT(12) ++#define RCC_MC_APB5ENCLRR_TZPCEN BIT(13) ++#define RCC_MC_APB5ENCLRR_BSECEN BIT(16) ++#define RCC_MC_APB5ENCLRR_STGENEN BIT(20) ++ ++/* RCC_MC_AHB5ENSETR register fields */ ++#define RCC_MC_AHB5ENSETR_GPIOZEN BIT(0) ++#define RCC_MC_AHB5ENSETR_CRYP1EN BIT(4) ++#define RCC_MC_AHB5ENSETR_HASH1EN BIT(5) ++#define RCC_MC_AHB5ENSETR_RNG1EN BIT(6) ++#define RCC_MC_AHB5ENSETR_BKPSRAMEN BIT(8) ++ ++/* RCC_MC_AHB5ENCLRR register fields */ ++#define RCC_MC_AHB5ENCLRR_GPIOZEN BIT(0) ++#define RCC_MC_AHB5ENCLRR_CRYP1EN BIT(4) ++#define RCC_MC_AHB5ENCLRR_HASH1EN BIT(5) ++#define RCC_MC_AHB5ENCLRR_RNG1EN BIT(6) ++#define RCC_MC_AHB5ENCLRR_BKPSRAMEN BIT(8) ++ ++/* RCC_MC_AHB6ENSETR register fields */ ++#define RCC_MC_AHB6ENSETR_MDMAEN BIT(0) ++#define RCC_MC_AHB6ENSETR_GPUEN BIT(5) ++#define RCC_MC_AHB6ENSETR_ETHCKEN BIT(7) ++#define RCC_MC_AHB6ENSETR_ETHTXEN BIT(8) ++#define RCC_MC_AHB6ENSETR_ETHRXEN BIT(9) ++#define RCC_MC_AHB6ENSETR_ETHMACEN BIT(10) ++#define RCC_MC_AHB6ENSETR_FMCEN BIT(12) ++#define RCC_MC_AHB6ENSETR_QSPIEN BIT(14) ++#define RCC_MC_AHB6ENSETR_SDMMC1EN BIT(16) ++#define RCC_MC_AHB6ENSETR_SDMMC2EN BIT(17) ++#define RCC_MC_AHB6ENSETR_CRC1EN BIT(20) ++#define RCC_MC_AHB6ENSETR_USBHEN BIT(24) ++ ++/* RCC_MC_AHB6ENCLRR register fields */ ++#define RCC_MC_AHB6ENCLRR_MDMAEN BIT(0) ++#define RCC_MC_AHB6ENCLRR_GPUEN BIT(5) ++#define RCC_MC_AHB6ENCLRR_ETHCKEN BIT(7) ++#define RCC_MC_AHB6ENCLRR_ETHTXEN BIT(8) ++#define RCC_MC_AHB6ENCLRR_ETHRXEN BIT(9) ++#define RCC_MC_AHB6ENCLRR_ETHMACEN BIT(10) ++#define RCC_MC_AHB6ENCLRR_FMCEN BIT(12) ++#define RCC_MC_AHB6ENCLRR_QSPIEN BIT(14) ++#define RCC_MC_AHB6ENCLRR_SDMMC1EN BIT(16) ++#define RCC_MC_AHB6ENCLRR_SDMMC2EN BIT(17) ++#define RCC_MC_AHB6ENCLRR_CRC1EN BIT(20) ++#define RCC_MC_AHB6ENCLRR_USBHEN BIT(24) ++ ++/* RCC_MP_APB4LPENSETR register fields */ ++#define RCC_MP_APB4LPENSETR_LTDCLPEN BIT(0) ++#define RCC_MP_APB4LPENSETR_DSILPEN BIT(4) ++#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) ++#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) ++#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) ++#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) ++#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) ++ ++/* RCC_MP_APB4LPENCLRR register fields */ ++#define RCC_MP_APB4LPENCLRR_LTDCLPEN BIT(0) ++#define RCC_MP_APB4LPENCLRR_DSILPEN BIT(4) ++#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) ++#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) ++#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) ++#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) ++#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) ++ ++/* RCC_MP_APB5LPENSETR register fields */ ++#define RCC_MP_APB5LPENSETR_SPI6LPEN BIT(0) ++#define RCC_MP_APB5LPENSETR_I2C4LPEN BIT(2) ++#define RCC_MP_APB5LPENSETR_I2C6LPEN BIT(3) ++#define RCC_MP_APB5LPENSETR_USART1LPEN BIT(4) ++#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) ++#define RCC_MP_APB5LPENSETR_TZC1LPEN BIT(11) ++#define RCC_MP_APB5LPENSETR_TZC2LPEN BIT(12) ++#define RCC_MP_APB5LPENSETR_TZPCLPEN BIT(13) ++#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) ++#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) ++#define RCC_MP_APB5LPENSETR_STGENLPEN BIT(20) ++#define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) ++ ++/* RCC_MP_APB5LPENCLRR register fields */ ++#define RCC_MP_APB5LPENCLRR_SPI6LPEN BIT(0) ++#define RCC_MP_APB5LPENCLRR_I2C4LPEN BIT(2) ++#define RCC_MP_APB5LPENCLRR_I2C6LPEN BIT(3) ++#define RCC_MP_APB5LPENCLRR_USART1LPEN BIT(4) ++#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) ++#define RCC_MP_APB5LPENCLRR_TZC1LPEN BIT(11) ++#define RCC_MP_APB5LPENCLRR_TZC2LPEN BIT(12) ++#define RCC_MP_APB5LPENCLRR_TZPCLPEN BIT(13) ++#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) ++#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) ++#define RCC_MP_APB5LPENCLRR_STGENLPEN BIT(20) ++#define RCC_MP_APB5LPENCLRR_STGENSTPEN BIT(21) ++ ++/* RCC_MP_AHB5LPENSETR register fields */ ++#define RCC_MP_AHB5LPENSETR_GPIOZLPEN BIT(0) ++#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) ++#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) ++#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) ++#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) ++ ++/* RCC_MP_AHB5LPENCLRR register fields */ ++#define RCC_MP_AHB5LPENCLRR_GPIOZLPEN BIT(0) ++#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) ++#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) ++#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) ++#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) ++ ++/* RCC_MP_AHB6LPENSETR register fields */ ++#define RCC_MP_AHB6LPENSETR_MDMALPEN BIT(0) ++#define RCC_MP_AHB6LPENSETR_GPULPEN BIT(5) ++#define RCC_MP_AHB6LPENSETR_ETHCKLPEN BIT(7) ++#define RCC_MP_AHB6LPENSETR_ETHTXLPEN BIT(8) ++#define RCC_MP_AHB6LPENSETR_ETHRXLPEN BIT(9) ++#define RCC_MP_AHB6LPENSETR_ETHMACLPEN BIT(10) ++#define RCC_MP_AHB6LPENSETR_ETHSTPEN BIT(11) ++#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) ++#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) ++#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) ++#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) ++#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) ++#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) ++ ++/* RCC_MP_AHB6LPENCLRR register fields */ ++#define RCC_MP_AHB6LPENCLRR_MDMALPEN BIT(0) ++#define RCC_MP_AHB6LPENCLRR_GPULPEN BIT(5) ++#define RCC_MP_AHB6LPENCLRR_ETHCKLPEN BIT(7) ++#define RCC_MP_AHB6LPENCLRR_ETHTXLPEN BIT(8) ++#define RCC_MP_AHB6LPENCLRR_ETHRXLPEN BIT(9) ++#define RCC_MP_AHB6LPENCLRR_ETHMACLPEN BIT(10) ++#define RCC_MP_AHB6LPENCLRR_ETHSTPEN BIT(11) ++#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) ++#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) ++#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) ++#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) ++#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) ++#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) ++ ++/* RCC_MP_TZAHB6LPENSETR register fields */ ++#define RCC_MP_TZAHB6LPENSETR_MDMALPEN BIT(0) ++ ++/* RCC_MP_TZAHB6LPENCLRR register fields */ ++#define RCC_MP_TZAHB6LPENCLRR_MDMALPEN BIT(0) ++ ++/* RCC_MC_APB4LPENSETR register fields */ ++#define RCC_MC_APB4LPENSETR_LTDCLPEN BIT(0) ++#define RCC_MC_APB4LPENSETR_DSILPEN BIT(4) ++#define RCC_MC_APB4LPENSETR_DDRPERFMLPEN BIT(8) ++#define RCC_MC_APB4LPENSETR_USBPHYLPEN BIT(16) ++#define RCC_MC_APB4LPENSETR_STGENROLPEN BIT(20) ++#define RCC_MC_APB4LPENSETR_STGENROSTPEN BIT(21) ++ ++/* RCC_MC_APB4LPENCLRR register fields */ ++#define RCC_MC_APB4LPENCLRR_LTDCLPEN BIT(0) ++#define RCC_MC_APB4LPENCLRR_DSILPEN BIT(4) ++#define RCC_MC_APB4LPENCLRR_DDRPERFMLPEN BIT(8) ++#define RCC_MC_APB4LPENCLRR_USBPHYLPEN BIT(16) ++#define RCC_MC_APB4LPENCLRR_STGENROLPEN BIT(20) ++#define RCC_MC_APB4LPENCLRR_STGENROSTPEN BIT(21) ++ ++/* RCC_MC_APB5LPENSETR register fields */ ++#define RCC_MC_APB5LPENSETR_SPI6LPEN BIT(0) ++#define RCC_MC_APB5LPENSETR_I2C4LPEN BIT(2) ++#define RCC_MC_APB5LPENSETR_I2C6LPEN BIT(3) ++#define RCC_MC_APB5LPENSETR_USART1LPEN BIT(4) ++#define RCC_MC_APB5LPENSETR_RTCAPBLPEN BIT(8) ++#define RCC_MC_APB5LPENSETR_TZC1LPEN BIT(11) ++#define RCC_MC_APB5LPENSETR_TZC2LPEN BIT(12) ++#define RCC_MC_APB5LPENSETR_TZPCLPEN BIT(13) ++#define RCC_MC_APB5LPENSETR_BSECLPEN BIT(16) ++#define RCC_MC_APB5LPENSETR_STGENLPEN BIT(20) ++#define RCC_MC_APB5LPENSETR_STGENSTPEN BIT(21) ++ ++/* RCC_MC_APB5LPENCLRR register fields */ ++#define RCC_MC_APB5LPENCLRR_SPI6LPEN BIT(0) ++#define RCC_MC_APB5LPENCLRR_I2C4LPEN BIT(2) ++#define RCC_MC_APB5LPENCLRR_I2C6LPEN BIT(3) ++#define RCC_MC_APB5LPENCLRR_USART1LPEN BIT(4) ++#define RCC_MC_APB5LPENCLRR_RTCAPBLPEN BIT(8) ++#define RCC_MC_APB5LPENCLRR_TZC1LPEN BIT(11) ++#define RCC_MC_APB5LPENCLRR_TZC2LPEN BIT(12) ++#define RCC_MC_APB5LPENCLRR_TZPCLPEN BIT(13) ++#define RCC_MC_APB5LPENCLRR_BSECLPEN BIT(16) ++#define RCC_MC_APB5LPENCLRR_STGENLPEN BIT(20) ++#define RCC_MC_APB5LPENCLRR_STGENSTPEN BIT(21) ++ ++/* RCC_MC_AHB5LPENSETR register fields */ ++#define RCC_MC_AHB5LPENSETR_GPIOZLPEN BIT(0) ++#define RCC_MC_AHB5LPENSETR_CRYP1LPEN BIT(4) ++#define RCC_MC_AHB5LPENSETR_HASH1LPEN BIT(5) ++#define RCC_MC_AHB5LPENSETR_RNG1LPEN BIT(6) ++#define RCC_MC_AHB5LPENSETR_BKPSRAMLPEN BIT(8) ++ ++/* RCC_MC_AHB5LPENCLRR register fields */ ++#define RCC_MC_AHB5LPENCLRR_GPIOZLPEN BIT(0) ++#define RCC_MC_AHB5LPENCLRR_CRYP1LPEN BIT(4) ++#define RCC_MC_AHB5LPENCLRR_HASH1LPEN BIT(5) ++#define RCC_MC_AHB5LPENCLRR_RNG1LPEN BIT(6) ++#define RCC_MC_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) ++ ++/* RCC_MC_AHB6LPENSETR register fields */ ++#define RCC_MC_AHB6LPENSETR_MDMALPEN BIT(0) ++#define RCC_MC_AHB6LPENSETR_GPULPEN BIT(5) ++#define RCC_MC_AHB6LPENSETR_ETHCKLPEN BIT(7) ++#define RCC_MC_AHB6LPENSETR_ETHTXLPEN BIT(8) ++#define RCC_MC_AHB6LPENSETR_ETHRXLPEN BIT(9) ++#define RCC_MC_AHB6LPENSETR_ETHMACLPEN BIT(10) ++#define RCC_MC_AHB6LPENSETR_ETHSTPEN BIT(11) ++#define RCC_MC_AHB6LPENSETR_FMCLPEN BIT(12) ++#define RCC_MC_AHB6LPENSETR_QSPILPEN BIT(14) ++#define RCC_MC_AHB6LPENSETR_SDMMC1LPEN BIT(16) ++#define RCC_MC_AHB6LPENSETR_SDMMC2LPEN BIT(17) ++#define RCC_MC_AHB6LPENSETR_CRC1LPEN BIT(20) ++#define RCC_MC_AHB6LPENSETR_USBHLPEN BIT(24) ++ ++/* RCC_MC_AHB6LPENCLRR register fields */ ++#define RCC_MC_AHB6LPENCLRR_MDMALPEN BIT(0) ++#define RCC_MC_AHB6LPENCLRR_GPULPEN BIT(5) ++#define RCC_MC_AHB6LPENCLRR_ETHCKLPEN BIT(7) ++#define RCC_MC_AHB6LPENCLRR_ETHTXLPEN BIT(8) ++#define RCC_MC_AHB6LPENCLRR_ETHRXLPEN BIT(9) ++#define RCC_MC_AHB6LPENCLRR_ETHMACLPEN BIT(10) ++#define RCC_MC_AHB6LPENCLRR_ETHSTPEN BIT(11) ++#define RCC_MC_AHB6LPENCLRR_FMCLPEN BIT(12) ++#define RCC_MC_AHB6LPENCLRR_QSPILPEN BIT(14) ++#define RCC_MC_AHB6LPENCLRR_SDMMC1LPEN BIT(16) ++#define RCC_MC_AHB6LPENCLRR_SDMMC2LPEN BIT(17) ++#define RCC_MC_AHB6LPENCLRR_CRC1LPEN BIT(20) ++#define RCC_MC_AHB6LPENCLRR_USBHLPEN BIT(24) ++ ++/* RCC_BR_RSTSCLRR register fields */ ++#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) ++#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) ++#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) ++#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) ++#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) ++#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) ++#define RCC_BR_RSTSCLRR_MCSYSRSTF BIT(7) ++#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) ++#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) ++#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) ++#define RCC_BR_RSTSCLRR_MPUP1RSTF BIT(14) ++ ++/* RCC_MP_GRSTCSETR register fields */ ++#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) ++ ++/* RCC_MP_RSTSCLRR register fields */ ++#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) ++#define RCC_MP_RSTSCLRR_SPARE BIT(15) ++ ++/* RCC_MP_IWDGFZSETR register fields */ ++#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) ++#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) ++ ++/* RCC_MP_IWDGFZCLRR register fields */ ++#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) ++#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) ++ ++/* RCC_MP_CIER register fields */ ++#define RCC_MP_CIER_LSIRDYIE BIT(0) ++#define RCC_MP_CIER_LSERDYIE BIT(1) ++#define RCC_MP_CIER_HSIRDYIE BIT(2) ++#define RCC_MP_CIER_HSERDYIE BIT(3) ++#define RCC_MP_CIER_CSIRDYIE BIT(4) ++#define RCC_MP_CIER_PLL1DYIE BIT(8) ++#define RCC_MP_CIER_PLL2DYIE BIT(9) ++#define RCC_MP_CIER_PLL3DYIE BIT(10) ++#define RCC_MP_CIER_PLL4DYIE BIT(11) ++#define RCC_MP_CIER_LSECSSIE BIT(16) ++#define RCC_MP_CIER_WKUPIE BIT(20) ++ ++/* RCC_MP_CIFR register fields */ ++#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_LSECSSF BIT(16) ++#define RCC_MP_CIFR_WKUPF BIT(20) ++ ++/* RCC_PWRLPDLYCR register fields */ ++#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) ++#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 ++#define RCC_PWRLPDLYCR_MCTMPSKP BIT(24) ++ ++/* RCC_MP_RSTSSETR register fields */ ++#define RCC_MP_RSTSSETR_PORRSTF BIT(0) ++#define RCC_MP_RSTSSETR_BORRSTF BIT(1) ++#define RCC_MP_RSTSSETR_PADRSTF BIT(2) ++#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) ++#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) ++#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) ++#define RCC_MP_RSTSSETR_MCSYSRSTF BIT(7) ++#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) ++#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) ++#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) ++#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) ++#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) ++#define RCC_MP_RSTSSETR_MPUP1RSTF BIT(14) ++#define RCC_MP_RSTSSETR_SPARE BIT(15) ++ ++/* RCC_MCO1CFGR register fields */ ++#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) ++#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 ++#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) ++#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 ++#define RCC_MCO1CFGR_MCO1ON BIT(12) ++ ++/* RCC_MCO2CFGR register fields */ ++#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) ++#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 ++#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) ++#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 ++#define RCC_MCO2CFGR_MCO2ON BIT(12) ++ ++/* RCC_OCRDYR register fields */ ++#define RCC_OCRDYR_HSIRDY BIT(0) ++#define RCC_OCRDYR_HSIDIVRDY BIT(2) ++#define RCC_OCRDYR_CSIRDY BIT(4) ++#define RCC_OCRDYR_HSERDY BIT(8) ++#define RCC_OCRDYR_MPUCKRDY BIT(23) ++#define RCC_OCRDYR_AXICKRDY BIT(24) ++#define RCC_OCRDYR_CKREST BIT(25) ++ ++/* RCC_DBGCFGR register fields */ ++#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) ++#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 ++#define RCC_DBGCFGR_DBGCKEN BIT(8) ++#define RCC_DBGCFGR_TRACECKEN BIT(9) ++#define RCC_DBGCFGR_DBGRST BIT(12) ++ ++/* RCC_RCK3SELR register fields */ ++#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) ++#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 ++#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) ++ ++/* RCC_RCK4SELR register fields */ ++#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) ++#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 ++#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) ++ ++/* RCC_TIMG1PRER register fields */ ++#define RCC_TIMG1PRER_TIMG1PRE BIT(0) ++#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) ++ ++/* RCC_TIMG2PRER register fields */ ++#define RCC_TIMG2PRER_TIMG2PRE BIT(0) ++#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) ++ ++/* RCC_MCUDIVR register fields */ ++#define RCC_MCUDIVR_MCUDIV_MASK GENMASK(3, 0) ++#define RCC_MCUDIVR_MCUDIV_SHIFT 0 ++#define RCC_MCUDIVR_MCUDIVRDY BIT(31) ++ ++/* RCC_APB1DIVR register fields */ ++#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) ++#define RCC_APB1DIVR_APB1DIV_SHIFT 0 ++#define RCC_APB1DIVR_APB1DIVRDY BIT(31) ++ ++/* RCC_APB2DIVR register fields */ ++#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) ++#define RCC_APB2DIVR_APB2DIV_SHIFT 0 ++#define RCC_APB2DIVR_APB2DIVRDY BIT(31) ++ ++/* RCC_APB3DIVR register fields */ ++#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) ++#define RCC_APB3DIVR_APB3DIV_SHIFT 0 ++#define RCC_APB3DIVR_APB3DIVRDY BIT(31) ++ ++/* RCC_PLL3CR register fields */ ++#define RCC_PLL3CR_PLLON BIT(0) ++#define RCC_PLL3CR_PLL3RDY BIT(1) ++#define RCC_PLL3CR_SSCG_CTRL BIT(2) ++#define RCC_PLL3CR_DIVPEN BIT(4) ++#define RCC_PLL3CR_DIVQEN BIT(5) ++#define RCC_PLL3CR_DIVREN BIT(6) ++ ++/* RCC_PLL3CFGR1 register fields */ ++#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL3CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) ++#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 ++#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) ++#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 ++ ++/* RCC_PLL3CFGR2 register fields */ ++#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL3CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL3CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL3FRACR register fields */ ++#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL3FRACR_FRACV_SHIFT 3 ++#define RCC_PLL3FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL3CSGR register fields */ ++#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL3CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 ++ ++/* RCC_PLL4CR register fields */ ++#define RCC_PLL4CR_PLLON BIT(0) ++#define RCC_PLL4CR_PLL4RDY BIT(1) ++#define RCC_PLL4CR_SSCG_CTRL BIT(2) ++#define RCC_PLL4CR_DIVPEN BIT(4) ++#define RCC_PLL4CR_DIVQEN BIT(5) ++#define RCC_PLL4CR_DIVREN BIT(6) ++ ++/* RCC_PLL4CFGR1 register fields */ ++#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLL4CFGR1_DIVN_SHIFT 0 ++#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) ++#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 ++#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) ++#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 ++ ++/* RCC_PLL4CFGR2 register fields */ ++#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLL4CFGR2_DIVP_SHIFT 0 ++#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 ++#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLL4CFGR2_DIVR_SHIFT 16 ++ ++/* RCC_PLL4FRACR register fields */ ++#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLL4FRACR_FRACV_SHIFT 3 ++#define RCC_PLL4FRACR_FRACLE BIT(16) ++ ++/* RCC_PLL4CSGR register fields */ ++#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 ++#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) ++#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) ++#define RCC_PLL4CSGR_SSCG_MODE BIT(15) ++#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 ++ ++/* 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_SAI1CKSELR register fields */ ++#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) ++#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 ++ ++/* RCC_SAI2CKSELR register fields */ ++#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) ++#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 ++ ++/* RCC_SAI3CKSELR register fields */ ++#define RCC_SAI3CKSELR_SAI3SRC_MASK GENMASK(2, 0) ++#define RCC_SAI3CKSELR_SAI3SRC_SHIFT 0 ++ ++/* RCC_SAI4CKSELR register fields */ ++#define RCC_SAI4CKSELR_SAI4SRC_MASK GENMASK(2, 0) ++#define RCC_SAI4CKSELR_SAI4SRC_SHIFT 0 ++ ++/* RCC_SPI2S1CKSELR register fields */ ++#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) ++#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 ++ ++/* RCC_SPI2S23CKSELR register fields */ ++#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) ++#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 ++ ++/* RCC_SPI45CKSELR register fields */ ++#define RCC_SPI45CKSELR_SPI45SRC_MASK GENMASK(2, 0) ++#define RCC_SPI45CKSELR_SPI45SRC_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_HSI 0x00000002 ++#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 ++#define RCC_ETHCKSELR_ETHPTPDIV_MASK GENMASK(7, 4) ++#define RCC_ETHCKSELR_ETHPTPDIV_SHIFT 4 ++ ++/* 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_FDCANCKSELR register fields */ ++#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) ++#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 ++ ++/* RCC_SPDIFCKSELR register fields */ ++#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) ++#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 ++ ++/* RCC_CECCKSELR register fields */ ++#define RCC_CECCKSELR_CECSRC_MASK GENMASK(1, 0) ++#define RCC_CECCKSELR_CECSRC_SHIFT 0 ++ ++/* RCC_USBCKSELR register fields */ ++#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) ++#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 ++#define RCC_USBCKSELR_USBOSRC BIT(4) ++#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) ++#define RCC_USBCKSELR_USBOSRC_SHIFT 4 ++ ++/* RCC_RNG2CKSELR register fields */ ++#define RCC_RNG2CKSELR_RNG2SRC_MASK GENMASK(1, 0) ++#define RCC_RNG2CKSELR_RNG2SRC_SHIFT 0 ++ ++/* RCC_DSICKSELR register fields */ ++#define RCC_DSICKSELR_DSISRC BIT(0) ++ ++/* RCC_ADCCKSELR register fields */ ++#define RCC_ADCCKSELR_ADCSRC_MASK GENMASK(1, 0) ++#define RCC_ADCCKSELR_ADCSRC_SHIFT 0 ++ ++/* RCC_LPTIM45CKSELR register fields */ ++#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) ++#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 ++ ++/* RCC_LPTIM23CKSELR register fields */ ++#define RCC_LPTIM23CKSELR_LPTIM23SRC_MASK GENMASK(2, 0) ++#define RCC_LPTIM23CKSELR_LPTIM23SRC_SHIFT 0 ++ ++/* RCC_LPTIM1CKSELR register fields */ ++#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) ++#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 ++ ++/* RCC_APB1RSTSETR register fields */ ++#define RCC_APB1RSTSETR_TIM2RST BIT(0) ++#define RCC_APB1RSTSETR_TIM3RST BIT(1) ++#define RCC_APB1RSTSETR_TIM4RST BIT(2) ++#define RCC_APB1RSTSETR_TIM5RST BIT(3) ++#define RCC_APB1RSTSETR_TIM6RST BIT(4) ++#define RCC_APB1RSTSETR_TIM7RST BIT(5) ++#define RCC_APB1RSTSETR_TIM12RST BIT(6) ++#define RCC_APB1RSTSETR_TIM13RST BIT(7) ++#define RCC_APB1RSTSETR_TIM14RST BIT(8) ++#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) ++#define RCC_APB1RSTSETR_SPI2RST BIT(11) ++#define RCC_APB1RSTSETR_SPI3RST BIT(12) ++#define RCC_APB1RSTSETR_USART2RST BIT(14) ++#define RCC_APB1RSTSETR_USART3RST BIT(15) ++#define RCC_APB1RSTSETR_UART4RST BIT(16) ++#define RCC_APB1RSTSETR_UART5RST BIT(17) ++#define RCC_APB1RSTSETR_UART7RST BIT(18) ++#define RCC_APB1RSTSETR_UART8RST BIT(19) ++#define RCC_APB1RSTSETR_I2C1RST BIT(21) ++#define RCC_APB1RSTSETR_I2C2RST BIT(22) ++#define RCC_APB1RSTSETR_I2C3RST BIT(23) ++#define RCC_APB1RSTSETR_I2C5RST BIT(24) ++#define RCC_APB1RSTSETR_SPDIFRST BIT(26) ++#define RCC_APB1RSTSETR_CECRST BIT(27) ++#define RCC_APB1RSTSETR_DAC12RST BIT(29) ++#define RCC_APB1RSTSETR_MDIOSRST BIT(31) ++ ++/* RCC_APB1RSTCLRR register fields */ ++#define RCC_APB1RSTCLRR_TIM2RST BIT(0) ++#define RCC_APB1RSTCLRR_TIM3RST BIT(1) ++#define RCC_APB1RSTCLRR_TIM4RST BIT(2) ++#define RCC_APB1RSTCLRR_TIM5RST BIT(3) ++#define RCC_APB1RSTCLRR_TIM6RST BIT(4) ++#define RCC_APB1RSTCLRR_TIM7RST BIT(5) ++#define RCC_APB1RSTCLRR_TIM12RST BIT(6) ++#define RCC_APB1RSTCLRR_TIM13RST BIT(7) ++#define RCC_APB1RSTCLRR_TIM14RST BIT(8) ++#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) ++#define RCC_APB1RSTCLRR_SPI2RST BIT(11) ++#define RCC_APB1RSTCLRR_SPI3RST BIT(12) ++#define RCC_APB1RSTCLRR_USART2RST BIT(14) ++#define RCC_APB1RSTCLRR_USART3RST BIT(15) ++#define RCC_APB1RSTCLRR_UART4RST BIT(16) ++#define RCC_APB1RSTCLRR_UART5RST BIT(17) ++#define RCC_APB1RSTCLRR_UART7RST BIT(18) ++#define RCC_APB1RSTCLRR_UART8RST BIT(19) ++#define RCC_APB1RSTCLRR_I2C1RST BIT(21) ++#define RCC_APB1RSTCLRR_I2C2RST BIT(22) ++#define RCC_APB1RSTCLRR_I2C3RST BIT(23) ++#define RCC_APB1RSTCLRR_I2C5RST BIT(24) ++#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) ++#define RCC_APB1RSTCLRR_CECRST BIT(27) ++#define RCC_APB1RSTCLRR_DAC12RST BIT(29) ++#define RCC_APB1RSTCLRR_MDIOSRST BIT(31) ++ ++/* RCC_APB2RSTSETR register fields */ ++#define RCC_APB2RSTSETR_TIM1RST BIT(0) ++#define RCC_APB2RSTSETR_TIM8RST BIT(1) ++#define RCC_APB2RSTSETR_TIM15RST BIT(2) ++#define RCC_APB2RSTSETR_TIM16RST BIT(3) ++#define RCC_APB2RSTSETR_TIM17RST BIT(4) ++#define RCC_APB2RSTSETR_SPI1RST BIT(8) ++#define RCC_APB2RSTSETR_SPI4RST BIT(9) ++#define RCC_APB2RSTSETR_SPI5RST BIT(10) ++#define RCC_APB2RSTSETR_USART6RST BIT(13) ++#define RCC_APB2RSTSETR_SAI1RST BIT(16) ++#define RCC_APB2RSTSETR_SAI2RST BIT(17) ++#define RCC_APB2RSTSETR_SAI3RST BIT(18) ++#define RCC_APB2RSTSETR_DFSDMRST BIT(20) ++#define RCC_APB2RSTSETR_FDCANRST BIT(24) ++ ++/* RCC_APB2RSTCLRR register fields */ ++#define RCC_APB2RSTCLRR_TIM1RST BIT(0) ++#define RCC_APB2RSTCLRR_TIM8RST BIT(1) ++#define RCC_APB2RSTCLRR_TIM15RST BIT(2) ++#define RCC_APB2RSTCLRR_TIM16RST BIT(3) ++#define RCC_APB2RSTCLRR_TIM17RST BIT(4) ++#define RCC_APB2RSTCLRR_SPI1RST BIT(8) ++#define RCC_APB2RSTCLRR_SPI4RST BIT(9) ++#define RCC_APB2RSTCLRR_SPI5RST BIT(10) ++#define RCC_APB2RSTCLRR_USART6RST BIT(13) ++#define RCC_APB2RSTCLRR_SAI1RST BIT(16) ++#define RCC_APB2RSTCLRR_SAI2RST BIT(17) ++#define RCC_APB2RSTCLRR_SAI3RST BIT(18) ++#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) ++#define RCC_APB2RSTCLRR_FDCANRST BIT(24) ++ ++/* RCC_APB3RSTSETR register fields */ ++#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) ++#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) ++#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) ++#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) ++#define RCC_APB3RSTSETR_SAI4RST BIT(8) ++#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) ++#define RCC_APB3RSTSETR_VREFRST BIT(13) ++#define RCC_APB3RSTSETR_TMPSENSRST BIT(16) ++#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) ++ ++/* RCC_APB3RSTCLRR register fields */ ++#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) ++#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) ++#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) ++#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) ++#define RCC_APB3RSTCLRR_SAI4RST BIT(8) ++#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) ++#define RCC_APB3RSTCLRR_VREFRST BIT(13) ++#define RCC_APB3RSTCLRR_TMPSENSRST BIT(16) ++#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) ++ ++/* RCC_AHB2RSTSETR register fields */ ++#define RCC_AHB2RSTSETR_DMA1RST BIT(0) ++#define RCC_AHB2RSTSETR_DMA2RST BIT(1) ++#define RCC_AHB2RSTSETR_DMAMUXRST BIT(2) ++#define RCC_AHB2RSTSETR_ADC12RST BIT(5) ++#define RCC_AHB2RSTSETR_USBORST BIT(8) ++#define RCC_AHB2RSTSETR_SDMMC3RST BIT(16) ++ ++/* RCC_AHB2RSTCLRR register fields */ ++#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) ++#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) ++#define RCC_AHB2RSTCLRR_DMAMUXRST BIT(2) ++#define RCC_AHB2RSTCLRR_ADC12RST BIT(5) ++#define RCC_AHB2RSTCLRR_USBORST BIT(8) ++#define RCC_AHB2RSTCLRR_SDMMC3RST BIT(16) ++ ++/* RCC_AHB3RSTSETR register fields */ ++#define RCC_AHB3RSTSETR_DCMIRST BIT(0) ++#define RCC_AHB3RSTSETR_CRYP2RST BIT(4) ++#define RCC_AHB3RSTSETR_HASH2RST BIT(5) ++#define RCC_AHB3RSTSETR_RNG2RST BIT(6) ++#define RCC_AHB3RSTSETR_CRC2RST BIT(7) ++#define RCC_AHB3RSTSETR_HSEMRST BIT(11) ++#define RCC_AHB3RSTSETR_IPCCRST BIT(12) ++ ++/* RCC_AHB3RSTCLRR register fields */ ++#define RCC_AHB3RSTCLRR_DCMIRST BIT(0) ++#define RCC_AHB3RSTCLRR_CRYP2RST BIT(4) ++#define RCC_AHB3RSTCLRR_HASH2RST BIT(5) ++#define RCC_AHB3RSTCLRR_RNG2RST BIT(6) ++#define RCC_AHB3RSTCLRR_CRC2RST BIT(7) ++#define RCC_AHB3RSTCLRR_HSEMRST BIT(11) ++#define RCC_AHB3RSTCLRR_IPCCRST BIT(12) ++ ++/* RCC_AHB4RSTSETR register fields */ ++#define RCC_AHB4RSTSETR_GPIOARST BIT(0) ++#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) ++#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) ++#define RCC_AHB4RSTSETR_GPIODRST BIT(3) ++#define RCC_AHB4RSTSETR_GPIOERST BIT(4) ++#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) ++#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) ++#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) ++#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) ++#define RCC_AHB4RSTSETR_GPIOJRST BIT(9) ++#define RCC_AHB4RSTSETR_GPIOKRST BIT(10) ++ ++/* RCC_AHB4RSTCLRR register fields */ ++#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) ++#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) ++#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) ++#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) ++#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) ++#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) ++#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) ++#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) ++#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) ++#define RCC_AHB4RSTCLRR_GPIOJRST BIT(9) ++#define RCC_AHB4RSTCLRR_GPIOKRST BIT(10) ++ ++/* RCC_MP_APB1ENSETR register fields */ ++#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) ++#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) ++#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) ++#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) ++#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) ++#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) ++#define RCC_MP_APB1ENSETR_TIM12EN BIT(6) ++#define RCC_MP_APB1ENSETR_TIM13EN BIT(7) ++#define RCC_MP_APB1ENSETR_TIM14EN BIT(8) ++#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) ++#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) ++#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) ++#define RCC_MP_APB1ENSETR_USART2EN BIT(14) ++#define RCC_MP_APB1ENSETR_USART3EN BIT(15) ++#define RCC_MP_APB1ENSETR_UART4EN BIT(16) ++#define RCC_MP_APB1ENSETR_UART5EN BIT(17) ++#define RCC_MP_APB1ENSETR_UART7EN BIT(18) ++#define RCC_MP_APB1ENSETR_UART8EN BIT(19) ++#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) ++#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) ++#define RCC_MP_APB1ENSETR_I2C3EN BIT(23) ++#define RCC_MP_APB1ENSETR_I2C5EN BIT(24) ++#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) ++#define RCC_MP_APB1ENSETR_CECEN BIT(27) ++#define RCC_MP_APB1ENSETR_DAC12EN BIT(29) ++#define RCC_MP_APB1ENSETR_MDIOSEN BIT(31) ++ ++/* RCC_MP_APB1ENCLRR register fields */ ++#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) ++#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) ++#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) ++#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) ++#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) ++#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) ++#define RCC_MP_APB1ENCLRR_TIM12EN BIT(6) ++#define RCC_MP_APB1ENCLRR_TIM13EN BIT(7) ++#define RCC_MP_APB1ENCLRR_TIM14EN BIT(8) ++#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) ++#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) ++#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) ++#define RCC_MP_APB1ENCLRR_USART2EN BIT(14) ++#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) ++#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) ++#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) ++#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) ++#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) ++#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) ++#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) ++#define RCC_MP_APB1ENCLRR_I2C3EN BIT(23) ++#define RCC_MP_APB1ENCLRR_I2C5EN BIT(24) ++#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) ++#define RCC_MP_APB1ENCLRR_CECEN BIT(27) ++#define RCC_MP_APB1ENCLRR_DAC12EN BIT(29) ++#define RCC_MP_APB1ENCLRR_MDIOSEN BIT(31) ++ ++/* RCC_MP_APB2ENSETR register fields */ ++#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) ++#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) ++#define RCC_MP_APB2ENSETR_TIM15EN BIT(2) ++#define RCC_MP_APB2ENSETR_TIM16EN BIT(3) ++#define RCC_MP_APB2ENSETR_TIM17EN BIT(4) ++#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) ++#define RCC_MP_APB2ENSETR_SPI4EN BIT(9) ++#define RCC_MP_APB2ENSETR_SPI5EN BIT(10) ++#define RCC_MP_APB2ENSETR_USART6EN BIT(13) ++#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) ++#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) ++#define RCC_MP_APB2ENSETR_SAI3EN BIT(18) ++#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) ++#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) ++#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) ++ ++/* RCC_MP_APB2ENCLRR register fields */ ++#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) ++#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) ++#define RCC_MP_APB2ENCLRR_TIM15EN BIT(2) ++#define RCC_MP_APB2ENCLRR_TIM16EN BIT(3) ++#define RCC_MP_APB2ENCLRR_TIM17EN BIT(4) ++#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) ++#define RCC_MP_APB2ENCLRR_SPI4EN BIT(9) ++#define RCC_MP_APB2ENCLRR_SPI5EN BIT(10) ++#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) ++#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) ++#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) ++#define RCC_MP_APB2ENCLRR_SAI3EN BIT(18) ++#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) ++#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) ++#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) ++ ++/* RCC_MP_APB3ENSETR register fields */ ++#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) ++#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) ++#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) ++#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) ++#define RCC_MP_APB3ENSETR_SAI4EN BIT(8) ++#define RCC_MP_APB3ENSETR_SYSCFGEN BIT(11) ++#define RCC_MP_APB3ENSETR_VREFEN BIT(13) ++#define RCC_MP_APB3ENSETR_TMPSENSEN BIT(16) ++#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) ++#define RCC_MP_APB3ENSETR_HDPEN BIT(20) ++ ++/* RCC_MP_APB3ENCLRR register fields */ ++#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) ++#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) ++#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) ++#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) ++#define RCC_MP_APB3ENCLRR_SAI4EN BIT(8) ++#define RCC_MP_APB3ENCLRR_SYSCFGEN BIT(11) ++#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) ++#define RCC_MP_APB3ENCLRR_TMPSENSEN BIT(16) ++#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) ++#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) ++ ++/* RCC_MP_AHB2ENSETR register fields */ ++#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) ++#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) ++#define RCC_MP_AHB2ENSETR_DMAMUXEN BIT(2) ++#define RCC_MP_AHB2ENSETR_ADC12EN BIT(5) ++#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) ++#define RCC_MP_AHB2ENSETR_SDMMC3EN BIT(16) ++ ++/* RCC_MP_AHB2ENCLRR register fields */ ++#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) ++#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) ++#define RCC_MP_AHB2ENCLRR_DMAMUXEN BIT(2) ++#define RCC_MP_AHB2ENCLRR_ADC12EN BIT(5) ++#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) ++#define RCC_MP_AHB2ENCLRR_SDMMC3EN BIT(16) ++ ++/* RCC_MP_AHB3ENSETR register fields */ ++#define RCC_MP_AHB3ENSETR_DCMIEN BIT(0) ++#define RCC_MP_AHB3ENSETR_CRYP2EN BIT(4) ++#define RCC_MP_AHB3ENSETR_HASH2EN BIT(5) ++#define RCC_MP_AHB3ENSETR_RNG2EN BIT(6) ++#define RCC_MP_AHB3ENSETR_CRC2EN BIT(7) ++#define RCC_MP_AHB3ENSETR_HSEMEN BIT(11) ++#define RCC_MP_AHB3ENSETR_IPCCEN BIT(12) ++ ++/* RCC_MP_AHB3ENCLRR register fields */ ++#define RCC_MP_AHB3ENCLRR_DCMIEN BIT(0) ++#define RCC_MP_AHB3ENCLRR_CRYP2EN BIT(4) ++#define RCC_MP_AHB3ENCLRR_HASH2EN BIT(5) ++#define RCC_MP_AHB3ENCLRR_RNG2EN BIT(6) ++#define RCC_MP_AHB3ENCLRR_CRC2EN BIT(7) ++#define RCC_MP_AHB3ENCLRR_HSEMEN BIT(11) ++#define RCC_MP_AHB3ENCLRR_IPCCEN BIT(12) ++ ++/* RCC_MP_AHB4ENSETR register fields */ ++#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) ++#define RCC_MP_AHB4ENSETR_GPIOIEN BIT(8) ++#define RCC_MP_AHB4ENSETR_GPIOJEN BIT(9) ++#define RCC_MP_AHB4ENSETR_GPIOKEN BIT(10) ++ ++/* RCC_MP_AHB4ENCLRR register fields */ ++#define RCC_MP_AHB4ENCLRR_GPIOAEN BIT(0) ++#define RCC_MP_AHB4ENCLRR_GPIOBEN BIT(1) ++#define RCC_MP_AHB4ENCLRR_GPIOCEN BIT(2) ++#define RCC_MP_AHB4ENCLRR_GPIODEN BIT(3) ++#define RCC_MP_AHB4ENCLRR_GPIOEEN BIT(4) ++#define RCC_MP_AHB4ENCLRR_GPIOFEN BIT(5) ++#define RCC_MP_AHB4ENCLRR_GPIOGEN BIT(6) ++#define RCC_MP_AHB4ENCLRR_GPIOHEN BIT(7) ++#define RCC_MP_AHB4ENCLRR_GPIOIEN BIT(8) ++#define RCC_MP_AHB4ENCLRR_GPIOJEN BIT(9) ++#define RCC_MP_AHB4ENCLRR_GPIOKEN BIT(10) ++ ++/* RCC_MP_MLAHBENSETR register fields */ ++#define RCC_MP_MLAHBENSETR_RETRAMEN BIT(4) ++ ++/* RCC_MP_MLAHBENCLRR register fields */ ++#define RCC_MP_MLAHBENCLRR_RETRAMEN BIT(4) ++ ++/* RCC_MC_APB1ENSETR register fields */ ++#define RCC_MC_APB1ENSETR_TIM2EN BIT(0) ++#define RCC_MC_APB1ENSETR_TIM3EN BIT(1) ++#define RCC_MC_APB1ENSETR_TIM4EN BIT(2) ++#define RCC_MC_APB1ENSETR_TIM5EN BIT(3) ++#define RCC_MC_APB1ENSETR_TIM6EN BIT(4) ++#define RCC_MC_APB1ENSETR_TIM7EN BIT(5) ++#define RCC_MC_APB1ENSETR_TIM12EN BIT(6) ++#define RCC_MC_APB1ENSETR_TIM13EN BIT(7) ++#define RCC_MC_APB1ENSETR_TIM14EN BIT(8) ++#define RCC_MC_APB1ENSETR_LPTIM1EN BIT(9) ++#define RCC_MC_APB1ENSETR_SPI2EN BIT(11) ++#define RCC_MC_APB1ENSETR_SPI3EN BIT(12) ++#define RCC_MC_APB1ENSETR_USART2EN BIT(14) ++#define RCC_MC_APB1ENSETR_USART3EN BIT(15) ++#define RCC_MC_APB1ENSETR_UART4EN BIT(16) ++#define RCC_MC_APB1ENSETR_UART5EN BIT(17) ++#define RCC_MC_APB1ENSETR_UART7EN BIT(18) ++#define RCC_MC_APB1ENSETR_UART8EN BIT(19) ++#define RCC_MC_APB1ENSETR_I2C1EN BIT(21) ++#define RCC_MC_APB1ENSETR_I2C2EN BIT(22) ++#define RCC_MC_APB1ENSETR_I2C3EN BIT(23) ++#define RCC_MC_APB1ENSETR_I2C5EN BIT(24) ++#define RCC_MC_APB1ENSETR_SPDIFEN BIT(26) ++#define RCC_MC_APB1ENSETR_CECEN BIT(27) ++#define RCC_MC_APB1ENSETR_WWDG1EN BIT(28) ++#define RCC_MC_APB1ENSETR_DAC12EN BIT(29) ++#define RCC_MC_APB1ENSETR_MDIOSEN BIT(31) ++ ++/* RCC_MC_APB1ENCLRR register fields */ ++#define RCC_MC_APB1ENCLRR_TIM2EN BIT(0) ++#define RCC_MC_APB1ENCLRR_TIM3EN BIT(1) ++#define RCC_MC_APB1ENCLRR_TIM4EN BIT(2) ++#define RCC_MC_APB1ENCLRR_TIM5EN BIT(3) ++#define RCC_MC_APB1ENCLRR_TIM6EN BIT(4) ++#define RCC_MC_APB1ENCLRR_TIM7EN BIT(5) ++#define RCC_MC_APB1ENCLRR_TIM12EN BIT(6) ++#define RCC_MC_APB1ENCLRR_TIM13EN BIT(7) ++#define RCC_MC_APB1ENCLRR_TIM14EN BIT(8) ++#define RCC_MC_APB1ENCLRR_LPTIM1EN BIT(9) ++#define RCC_MC_APB1ENCLRR_SPI2EN BIT(11) ++#define RCC_MC_APB1ENCLRR_SPI3EN BIT(12) ++#define RCC_MC_APB1ENCLRR_USART2EN BIT(14) ++#define RCC_MC_APB1ENCLRR_USART3EN BIT(15) ++#define RCC_MC_APB1ENCLRR_UART4EN BIT(16) ++#define RCC_MC_APB1ENCLRR_UART5EN BIT(17) ++#define RCC_MC_APB1ENCLRR_UART7EN BIT(18) ++#define RCC_MC_APB1ENCLRR_UART8EN BIT(19) ++#define RCC_MC_APB1ENCLRR_I2C1EN BIT(21) ++#define RCC_MC_APB1ENCLRR_I2C2EN BIT(22) ++#define RCC_MC_APB1ENCLRR_I2C3EN BIT(23) ++#define RCC_MC_APB1ENCLRR_I2C5EN BIT(24) ++#define RCC_MC_APB1ENCLRR_SPDIFEN BIT(26) ++#define RCC_MC_APB1ENCLRR_CECEN BIT(27) ++#define RCC_MC_APB1ENCLRR_DAC12EN BIT(29) ++#define RCC_MC_APB1ENCLRR_MDIOSEN BIT(31) ++ ++/* RCC_MC_APB2ENSETR register fields */ ++#define RCC_MC_APB2ENSETR_TIM1EN BIT(0) ++#define RCC_MC_APB2ENSETR_TIM8EN BIT(1) ++#define RCC_MC_APB2ENSETR_TIM15EN BIT(2) ++#define RCC_MC_APB2ENSETR_TIM16EN BIT(3) ++#define RCC_MC_APB2ENSETR_TIM17EN BIT(4) ++#define RCC_MC_APB2ENSETR_SPI1EN BIT(8) ++#define RCC_MC_APB2ENSETR_SPI4EN BIT(9) ++#define RCC_MC_APB2ENSETR_SPI5EN BIT(10) ++#define RCC_MC_APB2ENSETR_USART6EN BIT(13) ++#define RCC_MC_APB2ENSETR_SAI1EN BIT(16) ++#define RCC_MC_APB2ENSETR_SAI2EN BIT(17) ++#define RCC_MC_APB2ENSETR_SAI3EN BIT(18) ++#define RCC_MC_APB2ENSETR_DFSDMEN BIT(20) ++#define RCC_MC_APB2ENSETR_ADFSDMEN BIT(21) ++#define RCC_MC_APB2ENSETR_FDCANEN BIT(24) ++ ++/* RCC_MC_APB2ENCLRR register fields */ ++#define RCC_MC_APB2ENCLRR_TIM1EN BIT(0) ++#define RCC_MC_APB2ENCLRR_TIM8EN BIT(1) ++#define RCC_MC_APB2ENCLRR_TIM15EN BIT(2) ++#define RCC_MC_APB2ENCLRR_TIM16EN BIT(3) ++#define RCC_MC_APB2ENCLRR_TIM17EN BIT(4) ++#define RCC_MC_APB2ENCLRR_SPI1EN BIT(8) ++#define RCC_MC_APB2ENCLRR_SPI4EN BIT(9) ++#define RCC_MC_APB2ENCLRR_SPI5EN BIT(10) ++#define RCC_MC_APB2ENCLRR_USART6EN BIT(13) ++#define RCC_MC_APB2ENCLRR_SAI1EN BIT(16) ++#define RCC_MC_APB2ENCLRR_SAI2EN BIT(17) ++#define RCC_MC_APB2ENCLRR_SAI3EN BIT(18) ++#define RCC_MC_APB2ENCLRR_DFSDMEN BIT(20) ++#define RCC_MC_APB2ENCLRR_ADFSDMEN BIT(21) ++#define RCC_MC_APB2ENCLRR_FDCANEN BIT(24) ++ ++/* RCC_MC_APB3ENSETR register fields */ ++#define RCC_MC_APB3ENSETR_LPTIM2EN BIT(0) ++#define RCC_MC_APB3ENSETR_LPTIM3EN BIT(1) ++#define RCC_MC_APB3ENSETR_LPTIM4EN BIT(2) ++#define RCC_MC_APB3ENSETR_LPTIM5EN BIT(3) ++#define RCC_MC_APB3ENSETR_SAI4EN BIT(8) ++#define RCC_MC_APB3ENSETR_SYSCFGEN BIT(11) ++#define RCC_MC_APB3ENSETR_VREFEN BIT(13) ++#define RCC_MC_APB3ENSETR_TMPSENSEN BIT(16) ++#define RCC_MC_APB3ENSETR_PMBCTRLEN BIT(17) ++#define RCC_MC_APB3ENSETR_HDPEN BIT(20) ++ ++/* RCC_MC_APB3ENCLRR register fields */ ++#define RCC_MC_APB3ENCLRR_LPTIM2EN BIT(0) ++#define RCC_MC_APB3ENCLRR_LPTIM3EN BIT(1) ++#define RCC_MC_APB3ENCLRR_LPTIM4EN BIT(2) ++#define RCC_MC_APB3ENCLRR_LPTIM5EN BIT(3) ++#define RCC_MC_APB3ENCLRR_SAI4EN BIT(8) ++#define RCC_MC_APB3ENCLRR_SYSCFGEN BIT(11) ++#define RCC_MC_APB3ENCLRR_VREFEN BIT(13) ++#define RCC_MC_APB3ENCLRR_TMPSENSEN BIT(16) ++#define RCC_MC_APB3ENCLRR_PMBCTRLEN BIT(17) ++#define RCC_MC_APB3ENCLRR_HDPEN BIT(20) ++ ++/* RCC_MC_AHB2ENSETR register fields */ ++#define RCC_MC_AHB2ENSETR_DMA1EN BIT(0) ++#define RCC_MC_AHB2ENSETR_DMA2EN BIT(1) ++#define RCC_MC_AHB2ENSETR_DMAMUXEN BIT(2) ++#define RCC_MC_AHB2ENSETR_ADC12EN BIT(5) ++#define RCC_MC_AHB2ENSETR_USBOEN BIT(8) ++#define RCC_MC_AHB2ENSETR_SDMMC3EN BIT(16) ++ ++/* RCC_MC_AHB2ENCLRR register fields */ ++#define RCC_MC_AHB2ENCLRR_DMA1EN BIT(0) ++#define RCC_MC_AHB2ENCLRR_DMA2EN BIT(1) ++#define RCC_MC_AHB2ENCLRR_DMAMUXEN BIT(2) ++#define RCC_MC_AHB2ENCLRR_ADC12EN BIT(5) ++#define RCC_MC_AHB2ENCLRR_USBOEN BIT(8) ++#define RCC_MC_AHB2ENCLRR_SDMMC3EN BIT(16) ++ ++/* RCC_MC_AHB3ENSETR register fields */ ++#define RCC_MC_AHB3ENSETR_DCMIEN BIT(0) ++#define RCC_MC_AHB3ENSETR_CRYP2EN BIT(4) ++#define RCC_MC_AHB3ENSETR_HASH2EN BIT(5) ++#define RCC_MC_AHB3ENSETR_RNG2EN BIT(6) ++#define RCC_MC_AHB3ENSETR_CRC2EN BIT(7) ++#define RCC_MC_AHB3ENSETR_HSEMEN BIT(11) ++#define RCC_MC_AHB3ENSETR_IPCCEN BIT(12) ++ ++/* RCC_MC_AHB3ENCLRR register fields */ ++#define RCC_MC_AHB3ENCLRR_DCMIEN BIT(0) ++#define RCC_MC_AHB3ENCLRR_CRYP2EN BIT(4) ++#define RCC_MC_AHB3ENCLRR_HASH2EN BIT(5) ++#define RCC_MC_AHB3ENCLRR_RNG2EN BIT(6) ++#define RCC_MC_AHB3ENCLRR_CRC2EN BIT(7) ++#define RCC_MC_AHB3ENCLRR_HSEMEN BIT(11) ++#define RCC_MC_AHB3ENCLRR_IPCCEN BIT(12) ++ ++/* RCC_MC_AHB4ENSETR register fields */ ++#define RCC_MC_AHB4ENSETR_GPIOAEN BIT(0) ++#define RCC_MC_AHB4ENSETR_GPIOBEN BIT(1) ++#define RCC_MC_AHB4ENSETR_GPIOCEN BIT(2) ++#define RCC_MC_AHB4ENSETR_GPIODEN BIT(3) ++#define RCC_MC_AHB4ENSETR_GPIOEEN BIT(4) ++#define RCC_MC_AHB4ENSETR_GPIOFEN BIT(5) ++#define RCC_MC_AHB4ENSETR_GPIOGEN BIT(6) ++#define RCC_MC_AHB4ENSETR_GPIOHEN BIT(7) ++#define RCC_MC_AHB4ENSETR_GPIOIEN BIT(8) ++#define RCC_MC_AHB4ENSETR_GPIOJEN BIT(9) ++#define RCC_MC_AHB4ENSETR_GPIOKEN BIT(10) ++ ++/* RCC_MC_AHB4ENCLRR register fields */ ++#define RCC_MC_AHB4ENCLRR_GPIOAEN BIT(0) ++#define RCC_MC_AHB4ENCLRR_GPIOBEN BIT(1) ++#define RCC_MC_AHB4ENCLRR_GPIOCEN BIT(2) ++#define RCC_MC_AHB4ENCLRR_GPIODEN BIT(3) ++#define RCC_MC_AHB4ENCLRR_GPIOEEN BIT(4) ++#define RCC_MC_AHB4ENCLRR_GPIOFEN BIT(5) ++#define RCC_MC_AHB4ENCLRR_GPIOGEN BIT(6) ++#define RCC_MC_AHB4ENCLRR_GPIOHEN BIT(7) ++#define RCC_MC_AHB4ENCLRR_GPIOIEN BIT(8) ++#define RCC_MC_AHB4ENCLRR_GPIOJEN BIT(9) ++#define RCC_MC_AHB4ENCLRR_GPIOKEN BIT(10) ++ ++/* RCC_MC_AXIMENSETR register fields */ ++#define RCC_MC_AXIMENSETR_SYSRAMEN BIT(0) ++ ++/* RCC_MC_AXIMENCLRR register fields */ ++#define RCC_MC_AXIMENCLRR_SYSRAMEN BIT(0) ++ ++/* RCC_MC_MLAHBENSETR register fields */ ++#define RCC_MC_MLAHBENSETR_RETRAMEN BIT(4) ++ ++/* RCC_MC_MLAHBENCLRR register fields */ ++#define RCC_MC_MLAHBENCLRR_RETRAMEN BIT(4) ++ ++/* RCC_MP_APB1LPENSETR register fields */ ++#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) ++#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) ++#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) ++#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) ++#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) ++#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) ++#define RCC_MP_APB1LPENSETR_TIM12LPEN BIT(6) ++#define RCC_MP_APB1LPENSETR_TIM13LPEN BIT(7) ++#define RCC_MP_APB1LPENSETR_TIM14LPEN BIT(8) ++#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) ++#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) ++#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) ++#define RCC_MP_APB1LPENSETR_USART2LPEN BIT(14) ++#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) ++#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) ++#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) ++#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) ++#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) ++#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) ++#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) ++#define RCC_MP_APB1LPENSETR_I2C3LPEN BIT(23) ++#define RCC_MP_APB1LPENSETR_I2C5LPEN BIT(24) ++#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) ++#define RCC_MP_APB1LPENSETR_CECLPEN BIT(27) ++#define RCC_MP_APB1LPENSETR_DAC12LPEN BIT(29) ++#define RCC_MP_APB1LPENSETR_MDIOSLPEN BIT(31) ++ ++/* RCC_MP_APB1LPENCLRR register fields */ ++#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) ++#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) ++#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) ++#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) ++#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) ++#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) ++#define RCC_MP_APB1LPENCLRR_TIM12LPEN BIT(6) ++#define RCC_MP_APB1LPENCLRR_TIM13LPEN BIT(7) ++#define RCC_MP_APB1LPENCLRR_TIM14LPEN BIT(8) ++#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) ++#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) ++#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) ++#define RCC_MP_APB1LPENCLRR_USART2LPEN BIT(14) ++#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) ++#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) ++#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) ++#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) ++#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) ++#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) ++#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) ++#define RCC_MP_APB1LPENCLRR_I2C3LPEN BIT(23) ++#define RCC_MP_APB1LPENCLRR_I2C5LPEN BIT(24) ++#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) ++#define RCC_MP_APB1LPENCLRR_CECLPEN BIT(27) ++#define RCC_MP_APB1LPENCLRR_DAC12LPEN BIT(29) ++#define RCC_MP_APB1LPENCLRR_MDIOSLPEN BIT(31) ++ ++/* RCC_MP_APB2LPENSETR register fields */ ++#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) ++#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) ++#define RCC_MP_APB2LPENSETR_TIM15LPEN BIT(2) ++#define RCC_MP_APB2LPENSETR_TIM16LPEN BIT(3) ++#define RCC_MP_APB2LPENSETR_TIM17LPEN BIT(4) ++#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) ++#define RCC_MP_APB2LPENSETR_SPI4LPEN BIT(9) ++#define RCC_MP_APB2LPENSETR_SPI5LPEN BIT(10) ++#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) ++#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) ++#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) ++#define RCC_MP_APB2LPENSETR_SAI3LPEN BIT(18) ++#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) ++#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) ++#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) ++ ++/* RCC_MP_APB2LPENCLRR register fields */ ++#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) ++#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) ++#define RCC_MP_APB2LPENCLRR_TIM15LPEN BIT(2) ++#define RCC_MP_APB2LPENCLRR_TIM16LPEN BIT(3) ++#define RCC_MP_APB2LPENCLRR_TIM17LPEN BIT(4) ++#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) ++#define RCC_MP_APB2LPENCLRR_SPI4LPEN BIT(9) ++#define RCC_MP_APB2LPENCLRR_SPI5LPEN BIT(10) ++#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) ++#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) ++#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) ++#define RCC_MP_APB2LPENCLRR_SAI3LPEN BIT(18) ++#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) ++#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) ++#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) ++ ++/* RCC_MP_APB3LPENSETR register fields */ ++#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) ++#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) ++#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) ++#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) ++#define RCC_MP_APB3LPENSETR_SAI4LPEN BIT(8) ++#define RCC_MP_APB3LPENSETR_SYSCFGLPEN BIT(11) ++#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) ++#define RCC_MP_APB3LPENSETR_TMPSENSLPEN BIT(16) ++#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) ++ ++/* RCC_MP_APB3LPENCLRR register fields */ ++#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) ++#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) ++#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) ++#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) ++#define RCC_MP_APB3LPENCLRR_SAI4LPEN BIT(8) ++#define RCC_MP_APB3LPENCLRR_SYSCFGLPEN BIT(11) ++#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) ++#define RCC_MP_APB3LPENCLRR_TMPSENSLPEN BIT(16) ++#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) ++ ++/* RCC_MP_AHB2LPENSETR register fields */ ++#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) ++#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) ++#define RCC_MP_AHB2LPENSETR_DMAMUXLPEN BIT(2) ++#define RCC_MP_AHB2LPENSETR_ADC12LPEN BIT(5) ++#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) ++#define RCC_MP_AHB2LPENSETR_SDMMC3LPEN BIT(16) ++ ++/* RCC_MP_AHB2LPENCLRR register fields */ ++#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) ++#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) ++#define RCC_MP_AHB2LPENCLRR_DMAMUXLPEN BIT(2) ++#define RCC_MP_AHB2LPENCLRR_ADC12LPEN BIT(5) ++#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) ++#define RCC_MP_AHB2LPENCLRR_SDMMC3LPEN BIT(16) ++ ++/* RCC_MP_AHB3LPENSETR register fields */ ++#define RCC_MP_AHB3LPENSETR_DCMILPEN BIT(0) ++#define RCC_MP_AHB3LPENSETR_CRYP2LPEN BIT(4) ++#define RCC_MP_AHB3LPENSETR_HASH2LPEN BIT(5) ++#define RCC_MP_AHB3LPENSETR_RNG2LPEN BIT(6) ++#define RCC_MP_AHB3LPENSETR_CRC2LPEN BIT(7) ++#define RCC_MP_AHB3LPENSETR_HSEMLPEN BIT(11) ++#define RCC_MP_AHB3LPENSETR_IPCCLPEN BIT(12) ++ ++/* RCC_MP_AHB3LPENCLRR register fields */ ++#define RCC_MP_AHB3LPENCLRR_DCMILPEN BIT(0) ++#define RCC_MP_AHB3LPENCLRR_CRYP2LPEN BIT(4) ++#define RCC_MP_AHB3LPENCLRR_HASH2LPEN BIT(5) ++#define RCC_MP_AHB3LPENCLRR_RNG2LPEN BIT(6) ++#define RCC_MP_AHB3LPENCLRR_CRC2LPEN BIT(7) ++#define RCC_MP_AHB3LPENCLRR_HSEMLPEN BIT(11) ++#define RCC_MP_AHB3LPENCLRR_IPCCLPEN BIT(12) ++ ++/* RCC_MP_AHB4LPENSETR register fields */ ++#define RCC_MP_AHB4LPENSETR_GPIOALPEN BIT(0) ++#define RCC_MP_AHB4LPENSETR_GPIOBLPEN BIT(1) ++#define RCC_MP_AHB4LPENSETR_GPIOCLPEN BIT(2) ++#define RCC_MP_AHB4LPENSETR_GPIODLPEN BIT(3) ++#define RCC_MP_AHB4LPENSETR_GPIOELPEN BIT(4) ++#define RCC_MP_AHB4LPENSETR_GPIOFLPEN BIT(5) ++#define RCC_MP_AHB4LPENSETR_GPIOGLPEN BIT(6) ++#define RCC_MP_AHB4LPENSETR_GPIOHLPEN BIT(7) ++#define RCC_MP_AHB4LPENSETR_GPIOILPEN BIT(8) ++#define RCC_MP_AHB4LPENSETR_GPIOJLPEN BIT(9) ++#define RCC_MP_AHB4LPENSETR_GPIOKLPEN BIT(10) ++ ++/* RCC_MP_AHB4LPENCLRR register fields */ ++#define RCC_MP_AHB4LPENCLRR_GPIOALPEN BIT(0) ++#define RCC_MP_AHB4LPENCLRR_GPIOBLPEN BIT(1) ++#define RCC_MP_AHB4LPENCLRR_GPIOCLPEN BIT(2) ++#define RCC_MP_AHB4LPENCLRR_GPIODLPEN BIT(3) ++#define RCC_MP_AHB4LPENCLRR_GPIOELPEN BIT(4) ++#define RCC_MP_AHB4LPENCLRR_GPIOFLPEN BIT(5) ++#define RCC_MP_AHB4LPENCLRR_GPIOGLPEN BIT(6) ++#define RCC_MP_AHB4LPENCLRR_GPIOHLPEN BIT(7) ++#define RCC_MP_AHB4LPENCLRR_GPIOILPEN BIT(8) ++#define RCC_MP_AHB4LPENCLRR_GPIOJLPEN BIT(9) ++#define RCC_MP_AHB4LPENCLRR_GPIOKLPEN BIT(10) ++ ++/* RCC_MP_AXIMLPENSETR register fields */ ++#define RCC_MP_AXIMLPENSETR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MP_AXIMLPENCLRR register fields */ ++#define RCC_MP_AXIMLPENCLRR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MP_MLAHBLPENSETR register fields */ ++#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) ++#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) ++#define RCC_MP_MLAHBLPENSETR_SRAM34LPEN BIT(2) ++#define RCC_MP_MLAHBLPENSETR_RETRAMLPEN BIT(4) ++ ++/* RCC_MP_MLAHBLPENCLRR register fields */ ++#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) ++#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) ++#define RCC_MP_MLAHBLPENCLRR_SRAM34LPEN BIT(2) ++#define RCC_MP_MLAHBLPENCLRR_RETRAMLPEN BIT(4) ++ ++/* RCC_MC_APB1LPENSETR register fields */ ++#define RCC_MC_APB1LPENSETR_TIM2LPEN BIT(0) ++#define RCC_MC_APB1LPENSETR_TIM3LPEN BIT(1) ++#define RCC_MC_APB1LPENSETR_TIM4LPEN BIT(2) ++#define RCC_MC_APB1LPENSETR_TIM5LPEN BIT(3) ++#define RCC_MC_APB1LPENSETR_TIM6LPEN BIT(4) ++#define RCC_MC_APB1LPENSETR_TIM7LPEN BIT(5) ++#define RCC_MC_APB1LPENSETR_TIM12LPEN BIT(6) ++#define RCC_MC_APB1LPENSETR_TIM13LPEN BIT(7) ++#define RCC_MC_APB1LPENSETR_TIM14LPEN BIT(8) ++#define RCC_MC_APB1LPENSETR_LPTIM1LPEN BIT(9) ++#define RCC_MC_APB1LPENSETR_SPI2LPEN BIT(11) ++#define RCC_MC_APB1LPENSETR_SPI3LPEN BIT(12) ++#define RCC_MC_APB1LPENSETR_USART2LPEN BIT(14) ++#define RCC_MC_APB1LPENSETR_USART3LPEN BIT(15) ++#define RCC_MC_APB1LPENSETR_UART4LPEN BIT(16) ++#define RCC_MC_APB1LPENSETR_UART5LPEN BIT(17) ++#define RCC_MC_APB1LPENSETR_UART7LPEN BIT(18) ++#define RCC_MC_APB1LPENSETR_UART8LPEN BIT(19) ++#define RCC_MC_APB1LPENSETR_I2C1LPEN BIT(21) ++#define RCC_MC_APB1LPENSETR_I2C2LPEN BIT(22) ++#define RCC_MC_APB1LPENSETR_I2C3LPEN BIT(23) ++#define RCC_MC_APB1LPENSETR_I2C5LPEN BIT(24) ++#define RCC_MC_APB1LPENSETR_SPDIFLPEN BIT(26) ++#define RCC_MC_APB1LPENSETR_CECLPEN BIT(27) ++#define RCC_MC_APB1LPENSETR_WWDG1LPEN BIT(28) ++#define RCC_MC_APB1LPENSETR_DAC12LPEN BIT(29) ++#define RCC_MC_APB1LPENSETR_MDIOSLPEN BIT(31) ++ ++/* RCC_MC_APB1LPENCLRR register fields */ ++#define RCC_MC_APB1LPENCLRR_TIM2LPEN BIT(0) ++#define RCC_MC_APB1LPENCLRR_TIM3LPEN BIT(1) ++#define RCC_MC_APB1LPENCLRR_TIM4LPEN BIT(2) ++#define RCC_MC_APB1LPENCLRR_TIM5LPEN BIT(3) ++#define RCC_MC_APB1LPENCLRR_TIM6LPEN BIT(4) ++#define RCC_MC_APB1LPENCLRR_TIM7LPEN BIT(5) ++#define RCC_MC_APB1LPENCLRR_TIM12LPEN BIT(6) ++#define RCC_MC_APB1LPENCLRR_TIM13LPEN BIT(7) ++#define RCC_MC_APB1LPENCLRR_TIM14LPEN BIT(8) ++#define RCC_MC_APB1LPENCLRR_LPTIM1LPEN BIT(9) ++#define RCC_MC_APB1LPENCLRR_SPI2LPEN BIT(11) ++#define RCC_MC_APB1LPENCLRR_SPI3LPEN BIT(12) ++#define RCC_MC_APB1LPENCLRR_USART2LPEN BIT(14) ++#define RCC_MC_APB1LPENCLRR_USART3LPEN BIT(15) ++#define RCC_MC_APB1LPENCLRR_UART4LPEN BIT(16) ++#define RCC_MC_APB1LPENCLRR_UART5LPEN BIT(17) ++#define RCC_MC_APB1LPENCLRR_UART7LPEN BIT(18) ++#define RCC_MC_APB1LPENCLRR_UART8LPEN BIT(19) ++#define RCC_MC_APB1LPENCLRR_I2C1LPEN BIT(21) ++#define RCC_MC_APB1LPENCLRR_I2C2LPEN BIT(22) ++#define RCC_MC_APB1LPENCLRR_I2C3LPEN BIT(23) ++#define RCC_MC_APB1LPENCLRR_I2C5LPEN BIT(24) ++#define RCC_MC_APB1LPENCLRR_SPDIFLPEN BIT(26) ++#define RCC_MC_APB1LPENCLRR_CECLPEN BIT(27) ++#define RCC_MC_APB1LPENCLRR_WWDG1LPEN BIT(28) ++#define RCC_MC_APB1LPENCLRR_DAC12LPEN BIT(29) ++#define RCC_MC_APB1LPENCLRR_MDIOSLPEN BIT(31) ++ ++/* RCC_MC_APB2LPENSETR register fields */ ++#define RCC_MC_APB2LPENSETR_TIM1LPEN BIT(0) ++#define RCC_MC_APB2LPENSETR_TIM8LPEN BIT(1) ++#define RCC_MC_APB2LPENSETR_TIM15LPEN BIT(2) ++#define RCC_MC_APB2LPENSETR_TIM16LPEN BIT(3) ++#define RCC_MC_APB2LPENSETR_TIM17LPEN BIT(4) ++#define RCC_MC_APB2LPENSETR_SPI1LPEN BIT(8) ++#define RCC_MC_APB2LPENSETR_SPI4LPEN BIT(9) ++#define RCC_MC_APB2LPENSETR_SPI5LPEN BIT(10) ++#define RCC_MC_APB2LPENSETR_USART6LPEN BIT(13) ++#define RCC_MC_APB2LPENSETR_SAI1LPEN BIT(16) ++#define RCC_MC_APB2LPENSETR_SAI2LPEN BIT(17) ++#define RCC_MC_APB2LPENSETR_SAI3LPEN BIT(18) ++#define RCC_MC_APB2LPENSETR_DFSDMLPEN BIT(20) ++#define RCC_MC_APB2LPENSETR_ADFSDMLPEN BIT(21) ++#define RCC_MC_APB2LPENSETR_FDCANLPEN BIT(24) ++ ++/* RCC_MC_APB2LPENCLRR register fields */ ++#define RCC_MC_APB2LPENCLRR_TIM1LPEN BIT(0) ++#define RCC_MC_APB2LPENCLRR_TIM8LPEN BIT(1) ++#define RCC_MC_APB2LPENCLRR_TIM15LPEN BIT(2) ++#define RCC_MC_APB2LPENCLRR_TIM16LPEN BIT(3) ++#define RCC_MC_APB2LPENCLRR_TIM17LPEN BIT(4) ++#define RCC_MC_APB2LPENCLRR_SPI1LPEN BIT(8) ++#define RCC_MC_APB2LPENCLRR_SPI4LPEN BIT(9) ++#define RCC_MC_APB2LPENCLRR_SPI5LPEN BIT(10) ++#define RCC_MC_APB2LPENCLRR_USART6LPEN BIT(13) ++#define RCC_MC_APB2LPENCLRR_SAI1LPEN BIT(16) ++#define RCC_MC_APB2LPENCLRR_SAI2LPEN BIT(17) ++#define RCC_MC_APB2LPENCLRR_SAI3LPEN BIT(18) ++#define RCC_MC_APB2LPENCLRR_DFSDMLPEN BIT(20) ++#define RCC_MC_APB2LPENCLRR_ADFSDMLPEN BIT(21) ++#define RCC_MC_APB2LPENCLRR_FDCANLPEN BIT(24) ++ ++/* RCC_MC_APB3LPENSETR register fields */ ++#define RCC_MC_APB3LPENSETR_LPTIM2LPEN BIT(0) ++#define RCC_MC_APB3LPENSETR_LPTIM3LPEN BIT(1) ++#define RCC_MC_APB3LPENSETR_LPTIM4LPEN BIT(2) ++#define RCC_MC_APB3LPENSETR_LPTIM5LPEN BIT(3) ++#define RCC_MC_APB3LPENSETR_SAI4LPEN BIT(8) ++#define RCC_MC_APB3LPENSETR_SYSCFGLPEN BIT(11) ++#define RCC_MC_APB3LPENSETR_VREFLPEN BIT(13) ++#define RCC_MC_APB3LPENSETR_TMPSENSLPEN BIT(16) ++#define RCC_MC_APB3LPENSETR_PMBCTRLLPEN BIT(17) ++ ++/* RCC_MC_APB3LPENCLRR register fields */ ++#define RCC_MC_APB3LPENCLRR_LPTIM2LPEN BIT(0) ++#define RCC_MC_APB3LPENCLRR_LPTIM3LPEN BIT(1) ++#define RCC_MC_APB3LPENCLRR_LPTIM4LPEN BIT(2) ++#define RCC_MC_APB3LPENCLRR_LPTIM5LPEN BIT(3) ++#define RCC_MC_APB3LPENCLRR_SAI4LPEN BIT(8) ++#define RCC_MC_APB3LPENCLRR_SYSCFGLPEN BIT(11) ++#define RCC_MC_APB3LPENCLRR_VREFLPEN BIT(13) ++#define RCC_MC_APB3LPENCLRR_TMPSENSLPEN BIT(16) ++#define RCC_MC_APB3LPENCLRR_PMBCTRLLPEN BIT(17) ++ ++/* RCC_MC_AHB2LPENSETR register fields */ ++#define RCC_MC_AHB2LPENSETR_DMA1LPEN BIT(0) ++#define RCC_MC_AHB2LPENSETR_DMA2LPEN BIT(1) ++#define RCC_MC_AHB2LPENSETR_DMAMUXLPEN BIT(2) ++#define RCC_MC_AHB2LPENSETR_ADC12LPEN BIT(5) ++#define RCC_MC_AHB2LPENSETR_USBOLPEN BIT(8) ++#define RCC_MC_AHB2LPENSETR_SDMMC3LPEN BIT(16) ++ ++/* RCC_MC_AHB2LPENCLRR register fields */ ++#define RCC_MC_AHB2LPENCLRR_DMA1LPEN BIT(0) ++#define RCC_MC_AHB2LPENCLRR_DMA2LPEN BIT(1) ++#define RCC_MC_AHB2LPENCLRR_DMAMUXLPEN BIT(2) ++#define RCC_MC_AHB2LPENCLRR_ADC12LPEN BIT(5) ++#define RCC_MC_AHB2LPENCLRR_USBOLPEN BIT(8) ++#define RCC_MC_AHB2LPENCLRR_SDMMC3LPEN BIT(16) ++ ++/* RCC_MC_AHB3LPENSETR register fields */ ++#define RCC_MC_AHB3LPENSETR_DCMILPEN BIT(0) ++#define RCC_MC_AHB3LPENSETR_CRYP2LPEN BIT(4) ++#define RCC_MC_AHB3LPENSETR_HASH2LPEN BIT(5) ++#define RCC_MC_AHB3LPENSETR_RNG2LPEN BIT(6) ++#define RCC_MC_AHB3LPENSETR_CRC2LPEN BIT(7) ++#define RCC_MC_AHB3LPENSETR_HSEMLPEN BIT(11) ++#define RCC_MC_AHB3LPENSETR_IPCCLPEN BIT(12) ++ ++/* RCC_MC_AHB3LPENCLRR register fields */ ++#define RCC_MC_AHB3LPENCLRR_DCMILPEN BIT(0) ++#define RCC_MC_AHB3LPENCLRR_CRYP2LPEN BIT(4) ++#define RCC_MC_AHB3LPENCLRR_HASH2LPEN BIT(5) ++#define RCC_MC_AHB3LPENCLRR_RNG2LPEN BIT(6) ++#define RCC_MC_AHB3LPENCLRR_CRC2LPEN BIT(7) ++#define RCC_MC_AHB3LPENCLRR_HSEMLPEN BIT(11) ++#define RCC_MC_AHB3LPENCLRR_IPCCLPEN BIT(12) ++ ++/* RCC_MC_AHB4LPENSETR register fields */ ++#define RCC_MC_AHB4LPENSETR_GPIOALPEN BIT(0) ++#define RCC_MC_AHB4LPENSETR_GPIOBLPEN BIT(1) ++#define RCC_MC_AHB4LPENSETR_GPIOCLPEN BIT(2) ++#define RCC_MC_AHB4LPENSETR_GPIODLPEN BIT(3) ++#define RCC_MC_AHB4LPENSETR_GPIOELPEN BIT(4) ++#define RCC_MC_AHB4LPENSETR_GPIOFLPEN BIT(5) ++#define RCC_MC_AHB4LPENSETR_GPIOGLPEN BIT(6) ++#define RCC_MC_AHB4LPENSETR_GPIOHLPEN BIT(7) ++#define RCC_MC_AHB4LPENSETR_GPIOILPEN BIT(8) ++#define RCC_MC_AHB4LPENSETR_GPIOJLPEN BIT(9) ++#define RCC_MC_AHB4LPENSETR_GPIOKLPEN BIT(10) ++ ++/* RCC_MC_AHB4LPENCLRR register fields */ ++#define RCC_MC_AHB4LPENCLRR_GPIOALPEN BIT(0) ++#define RCC_MC_AHB4LPENCLRR_GPIOBLPEN BIT(1) ++#define RCC_MC_AHB4LPENCLRR_GPIOCLPEN BIT(2) ++#define RCC_MC_AHB4LPENCLRR_GPIODLPEN BIT(3) ++#define RCC_MC_AHB4LPENCLRR_GPIOELPEN BIT(4) ++#define RCC_MC_AHB4LPENCLRR_GPIOFLPEN BIT(5) ++#define RCC_MC_AHB4LPENCLRR_GPIOGLPEN BIT(6) ++#define RCC_MC_AHB4LPENCLRR_GPIOHLPEN BIT(7) ++#define RCC_MC_AHB4LPENCLRR_GPIOILPEN BIT(8) ++#define RCC_MC_AHB4LPENCLRR_GPIOJLPEN BIT(9) ++#define RCC_MC_AHB4LPENCLRR_GPIOKLPEN BIT(10) ++ ++/* RCC_MC_AXIMLPENSETR register fields */ ++#define RCC_MC_AXIMLPENSETR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MC_AXIMLPENCLRR register fields */ ++#define RCC_MC_AXIMLPENCLRR_SYSRAMLPEN BIT(0) ++ ++/* RCC_MC_MLAHBLPENSETR register fields */ ++#define RCC_MC_MLAHBLPENSETR_SRAM1LPEN BIT(0) ++#define RCC_MC_MLAHBLPENSETR_SRAM2LPEN BIT(1) ++#define RCC_MC_MLAHBLPENSETR_SRAM34LPEN BIT(2) ++#define RCC_MC_MLAHBLPENSETR_RETRAMLPEN BIT(4) ++ ++/* RCC_MC_MLAHBLPENCLRR register fields */ ++#define RCC_MC_MLAHBLPENCLRR_SRAM1LPEN BIT(0) ++#define RCC_MC_MLAHBLPENCLRR_SRAM2LPEN BIT(1) ++#define RCC_MC_MLAHBLPENCLRR_SRAM34LPEN BIT(2) ++#define RCC_MC_MLAHBLPENCLRR_RETRAMLPEN BIT(4) ++ ++/* RCC_MC_RSTSCLRR register fields */ ++#define RCC_MC_RSTSCLRR_PORRSTF BIT(0) ++#define RCC_MC_RSTSCLRR_BORRSTF BIT(1) ++#define RCC_MC_RSTSCLRR_PADRSTF BIT(2) ++#define RCC_MC_RSTSCLRR_HCSSRSTF BIT(3) ++#define RCC_MC_RSTSCLRR_VCORERSTF BIT(4) ++#define RCC_MC_RSTSCLRR_MCURSTF BIT(5) ++#define RCC_MC_RSTSCLRR_MPSYSRSTF BIT(6) ++#define RCC_MC_RSTSCLRR_MCSYSRSTF BIT(7) ++#define RCC_MC_RSTSCLRR_IWDG1RSTF BIT(8) ++#define RCC_MC_RSTSCLRR_IWDG2RSTF BIT(9) ++#define RCC_MC_RSTSCLRR_WWDG1RSTF BIT(10) ++ ++/* RCC_MC_CIER register fields */ ++#define RCC_MC_CIER_LSIRDYIE BIT(0) ++#define RCC_MC_CIER_LSERDYIE BIT(1) ++#define RCC_MC_CIER_HSIRDYIE BIT(2) ++#define RCC_MC_CIER_HSERDYIE BIT(3) ++#define RCC_MC_CIER_CSIRDYIE BIT(4) ++#define RCC_MC_CIER_PLL1DYIE BIT(8) ++#define RCC_MC_CIER_PLL2DYIE BIT(9) ++#define RCC_MC_CIER_PLL3DYIE BIT(10) ++#define RCC_MC_CIER_PLL4DYIE BIT(11) ++#define RCC_MC_CIER_LSECSSIE BIT(16) ++#define RCC_MC_CIER_WKUPIE BIT(20) ++ ++/* RCC_MC_CIFR register fields */ ++#define RCC_MC_CIFR_LSIRDYF BIT(0) ++#define RCC_MC_CIFR_LSERDYF BIT(1) ++#define RCC_MC_CIFR_HSIRDYF BIT(2) ++#define RCC_MC_CIFR_HSERDYF BIT(3) ++#define RCC_MC_CIFR_CSIRDYF BIT(4) ++#define RCC_MC_CIFR_PLL1DYF BIT(8) ++#define RCC_MC_CIFR_PLL2DYF BIT(9) ++#define RCC_MC_CIFR_PLL3DYF BIT(10) ++#define RCC_MC_CIFR_PLL4DYF BIT(11) ++#define RCC_MC_CIFR_LSECSSF BIT(16) ++#define RCC_MC_CIFR_WKUPF BIT(20) ++ ++/* RCC_VERR register fields */ ++#define RCC_VERR_MINREV_MASK GENMASK(3, 0) ++#define RCC_VERR_MINREV_SHIFT 0 ++#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) ++#define RCC_VERR_MAJREV_SHIFT 4 ++ ++/* 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) ++ ++/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ ++#define RCC_MP_ENCLRR_OFFSET U(4) ++ ++/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ ++#define RCC_RSTCLRR_OFFSET U(4) ++ ++/* Used for most of DIVR register: max div for RTC */ ++#define RCC_DIVR_DIV_MASK GENMASK(5, 0) ++#define RCC_DIVR_DIVRDY BIT(31) ++ ++/* Masks for specific DIVR registers */ ++#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 most of RCC_SELR registers */ ++#define RCC_SELR_SRC_MASK GENMASK(2, 0) ++#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) ++#define RCC_SELR_SRCRDY BIT(31) ++ ++/* 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) ++#define RCC_PLLNCR_DIVEN_SHIFT 4 ++ ++/* Used for all RCC_PLLCFGR1 registers */ ++#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) ++#define RCC_PLLNCFGR1_DIVM_SHIFT 16 ++#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) ++#define RCC_PLLNCFGR1_DIVN_SHIFT 0 ++ ++/* Only for PLL3 and PLL4 */ ++#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) ++#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 ++ ++/* Used for all RCC_PLLCFGR2 registers */ ++#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) ++#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) ++#define RCC_PLLNCFGR2_DIVP_SHIFT 0 ++#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) ++#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 ++#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) ++#define RCC_PLLNCFGR2_DIVR_SHIFT 16 ++ ++/* Used for all RCC_PLLFRACR registers */ ++#define RCC_PLLNFRACR_FRACV_SHIFT 3 ++#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) ++#define RCC_PLLNFRACR_FRACLE BIT(16) ++ ++/* Used for all RCC_PLLCSGR registers */ ++#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 ++#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) ++#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 ++#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) ++#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 ++#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) ++ ++/* Used for TIMER Prescaler */ ++#define RCC_TIMGXPRER_TIMGXPRE BIT(0) ++ ++/* Used for RCC_MCO related operations */ ++#define RCC_MCOCFG_MCOON BIT(12) ++#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) ++#define RCC_MCOCFG_MCODIV_SHIFT 4 ++#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) ++ ++#endif /* STM32MP1_RCC_H */ +diff --git a/include/drivers/st/stm32mp1_calib.h b/include/drivers/st/stm32mp1_calib.h +new file mode 100644 +index 000000000..ef69cb456 +--- /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 c46892b78..86efbd893 100644 +--- a/include/drivers/st/stm32mp1_clk.h ++++ b/include/drivers/st/stm32mp1_clk.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 + */ +@@ -22,42 +22,42 @@ enum stm32mp_osc_id { + + extern const char *stm32mp_osc_node_label[NB_OSC]; + ++#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); + +-void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); +-void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); ++void stm32mp1_clk_force_enable(unsigned long id); ++void stm32mp1_clk_force_disable(unsigned long id); + +-static inline void stm32mp1_clk_enable_non_secure(unsigned long id) +-{ +- __stm32mp1_clk_enable(id, false); +-} ++bool stm32mp1_rtc_get_read_twice(void); + +-static inline void stm32mp1_clk_enable_secure(unsigned long id) +-{ +- __stm32mp1_clk_enable(id, true); +-} ++/* SMP protection on RCC registers access */ ++void stm32mp1_clk_rcc_regs_lock(void); ++void stm32mp1_clk_rcc_regs_unlock(void); + +-static inline void stm32mp1_clk_disable_non_secure(unsigned long id) +-{ +- __stm32mp1_clk_disable(id, false); +-} ++int stm32mp1_round_opp_khz(uint32_t *freq_khz); ++int stm32mp1_set_opp_khz(uint32_t freq_khz); + +-static inline void stm32mp1_clk_disable_secure(unsigned long id) +-{ +- __stm32mp1_clk_disable(id, true); +-} ++void stm32mp1_clock_suspend(void); ++void stm32mp1_clock_resume(void); + +-unsigned int stm32mp1_clk_get_refcount(unsigned long id); ++void stm32mp1_clock_stopmode_save(void); ++int stm32mp1_clock_stopmode_resume(void); + +-/* SMP protection on RCC registers access */ +-void stm32mp1_clk_rcc_regs_lock(void); +-void stm32mp1_clk_rcc_regs_unlock(void); ++void restore_clock_pm_context(void); ++void save_clock_pm_context(void); + +-void stm32mp1_stgen_increment(unsigned long long offset_in_ms); ++void stm32mp1_clk_mcuss_protect(bool enable); + + #ifdef STM32MP_SHARED_RESOURCES + void stm32mp1_register_clock_parents_secure(unsigned long id); +diff --git a/include/drivers/st/stm32mp1_ddr.h b/include/drivers/st/stm32mp1_ddr.h +index 4ab37d6b4..f21a8a75c 100644 +--- a/include/drivers/st/stm32mp1_ddr.h ++++ b/include/drivers/st/stm32mp1_ddr.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ +@@ -8,31 +8,8 @@ + #define STM32MP1_DDR_H + + #include +-#include + +-#define DT_DDR_COMPAT "st,stm32mp1-ddr" +- +-struct stm32mp1_ddr_size { +- uint64_t base; +- uint64_t size; +-}; +- +-/** +- * struct ddr_info +- * +- * @dev: pointer for the device +- * @info: UCLASS RAM information +- * @ctl: DDR controleur base address +- * @phy: DDR PHY base address +- * @syscfg: syscfg base address +- */ +-struct ddr_info { +- struct stm32mp1_ddr_size info; +- struct stm32mp1_ddrctl *ctl; +- struct stm32mp1_ddrphy *phy; +- uintptr_t pwr; +- uintptr_t rcc; +-}; ++#include + + struct stm32mp1_ddrctrl_reg { + uint32_t mstr; +@@ -101,12 +78,14 @@ struct stm32mp1_ddrctrl_perf { + uint32_t pcfgqos1_0; + uint32_t pcfgwqos0_0; + uint32_t pcfgwqos1_0; ++#if STM32MP_DDR_DUAL_AXI_PORT + uint32_t pcfgr_1; + uint32_t pcfgw_1; + uint32_t pcfgqos0_1; + uint32_t pcfgqos1_1; + uint32_t pcfgwqos0_1; + uint32_t pcfgwqos1_1; ++#endif + }; + + struct stm32mp1_ddrphy_reg { +@@ -119,8 +98,10 @@ struct stm32mp1_ddrphy_reg { + uint32_t zq0cr1; + uint32_t dx0gcr; + uint32_t dx1gcr; ++#if STM32MP_DDR_32BIT_INTERFACE + uint32_t dx2gcr; + uint32_t dx3gcr; ++#endif + }; + + struct stm32mp1_ddrphy_timing { +@@ -136,39 +117,19 @@ struct stm32mp1_ddrphy_timing { + uint32_t mr3; + }; + +-struct stm32mp1_ddrphy_cal { +- uint32_t dx0dllcr; +- uint32_t dx0dqtr; +- uint32_t dx0dqstr; +- uint32_t dx1dllcr; +- uint32_t dx1dqtr; +- uint32_t dx1dqstr; +- uint32_t dx2dllcr; +- uint32_t dx2dqtr; +- uint32_t dx2dqstr; +- uint32_t dx3dllcr; +- uint32_t dx3dqtr; +- uint32_t dx3dqstr; +-}; +- +-struct stm32mp1_ddr_info { +- const char *name; +- uint32_t speed; /* in kHZ */ +- uint32_t size; /* Memory size in byte = col * row * width */ +-}; +- +-struct stm32mp1_ddr_config { +- struct stm32mp1_ddr_info info; ++struct stm32mp_ddr_config { ++ struct stm32mp_ddr_info info; + struct stm32mp1_ddrctrl_reg c_reg; + struct stm32mp1_ddrctrl_timing c_timing; + struct stm32mp1_ddrctrl_map c_map; + struct stm32mp1_ddrctrl_perf c_perf; + struct stm32mp1_ddrphy_reg p_reg; + struct stm32mp1_ddrphy_timing p_timing; +- struct stm32mp1_ddrphy_cal p_cal; ++ bool self_refresh; ++ uint32_t zdata; + }; + +-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); ++int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed); ++void stm32mp1_ddr_init(struct stm32mp_ddr_priv *priv, struct stm32mp_ddr_config *config); ++ + #endif /* STM32MP1_DDR_H */ +diff --git a/include/drivers/st/stm32mp1_ddr_helpers.h b/include/drivers/st/stm32mp1_ddr_helpers.h +index 38f24152a..17366deaa 100644 +--- a/include/drivers/st/stm32mp1_ddr_helpers.h ++++ b/include/drivers/st/stm32mp1_ddr_helpers.h +@@ -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,22 @@ + #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); ++uint32_t ddr_get_io_calibration_val(void); ++int ddr_standby_sr_entry(void); ++enum stm32mp1_ddr_sr_mode ddr_read_sr_mode(void); ++void ddr_set_sr_mode(enum stm32mp1_ddr_sr_mode mode); ++bool ddr_is_nonsecured_area(uintptr_t address, uint32_t length); + + #endif /* STM32MP1_DDR_HELPERS_H */ +diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h +index 01d663834..ae780e6ec 100644 +--- a/include/drivers/st/stm32mp1_ddr_regs.h ++++ b/include/drivers/st/stm32mp1_ddr_regs.h +@@ -7,140 +7,11 @@ + #ifndef STM32MP1_DDR_REGS_H + #define STM32MP1_DDR_REGS_H + ++#include + #include + +-/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */ +-struct stm32mp1_ddrctl { +- uint32_t mstr ; /* 0x0 Master */ +- uint32_t stat; /* 0x4 Operating Mode Status */ +- uint8_t reserved008[0x10 - 0x8]; +- uint32_t mrctrl0; /* 0x10 Control 0 */ +- uint32_t mrctrl1; /* 0x14 Control 1 */ +- uint32_t mrstat; /* 0x18 Status */ +- uint32_t reserved01c; /* 0x1c */ +- uint32_t derateen; /* 0x20 Temperature Derate Enable */ +- uint32_t derateint; /* 0x24 Temperature Derate Interval */ +- uint8_t reserved028[0x30 - 0x28]; +- uint32_t pwrctl; /* 0x30 Low Power Control */ +- uint32_t pwrtmg; /* 0x34 Low Power Timing */ +- uint32_t hwlpctl; /* 0x38 Hardware Low Power Control */ +- uint8_t reserved03c[0x50 - 0x3C]; +- uint32_t rfshctl0; /* 0x50 Refresh Control 0 */ +- uint32_t reserved054; /* 0x54 Refresh Control 1 */ +- uint32_t reserved058; /* 0x58 Refresh Control 2 */ +- uint32_t reserved05C; +- uint32_t rfshctl3; /* 0x60 Refresh Control 0 */ +- uint32_t rfshtmg; /* 0x64 Refresh Timing */ +- uint8_t reserved068[0xc0 - 0x68]; +- uint32_t crcparctl0; /* 0xc0 CRC Parity Control0 */ +- uint32_t reserved0c4; /* 0xc4 CRC Parity Control1 */ +- uint32_t reserved0c8; /* 0xc8 CRC Parity Control2 */ +- uint32_t crcparstat; /* 0xcc CRC Parity Status */ +- uint32_t init0; /* 0xd0 SDRAM Initialization 0 */ +- uint32_t init1; /* 0xd4 SDRAM Initialization 1 */ +- uint32_t init2; /* 0xd8 SDRAM Initialization 2 */ +- uint32_t init3; /* 0xdc SDRAM Initialization 3 */ +- uint32_t init4; /* 0xe0 SDRAM Initialization 4 */ +- uint32_t init5; /* 0xe4 SDRAM Initialization 5 */ +- uint32_t reserved0e8; +- uint32_t reserved0ec; +- uint32_t dimmctl; /* 0xf0 DIMM Control */ +- uint8_t reserved0f4[0x100 - 0xf4]; +- uint32_t dramtmg0; /* 0x100 SDRAM Timing 0 */ +- uint32_t dramtmg1; /* 0x104 SDRAM Timing 1 */ +- uint32_t dramtmg2; /* 0x108 SDRAM Timing 2 */ +- uint32_t dramtmg3; /* 0x10c SDRAM Timing 3 */ +- uint32_t dramtmg4; /* 0x110 SDRAM Timing 4 */ +- uint32_t dramtmg5; /* 0x114 SDRAM Timing 5 */ +- uint32_t dramtmg6; /* 0x118 SDRAM Timing 6 */ +- uint32_t dramtmg7; /* 0x11c SDRAM Timing 7 */ +- uint32_t dramtmg8; /* 0x120 SDRAM Timing 8 */ +- uint8_t reserved124[0x138 - 0x124]; +- uint32_t dramtmg14; /* 0x138 SDRAM Timing 14 */ +- uint32_t dramtmg15; /* 0x13C SDRAM Timing 15 */ +- uint8_t reserved140[0x180 - 0x140]; +- uint32_t zqctl0; /* 0x180 ZQ Control 0 */ +- uint32_t zqctl1; /* 0x184 ZQ Control 1 */ +- uint32_t zqctl2; /* 0x188 ZQ Control 2 */ +- uint32_t zqstat; /* 0x18c ZQ Status */ +- uint32_t dfitmg0; /* 0x190 DFI Timing 0 */ +- uint32_t dfitmg1; /* 0x194 DFI Timing 1 */ +- uint32_t dfilpcfg0; /* 0x198 DFI Low Power Configuration 0 */ +- uint32_t reserved19c; +- uint32_t dfiupd0; /* 0x1a0 DFI Update 0 */ +- uint32_t dfiupd1; /* 0x1a4 DFI Update 1 */ +- uint32_t dfiupd2; /* 0x1a8 DFI Update 2 */ +- uint32_t reserved1ac; +- uint32_t dfimisc; /* 0x1b0 DFI Miscellaneous Control */ +- uint8_t reserved1b4[0x1bc - 0x1b4]; +- uint32_t dfistat; /* 0x1bc DFI Miscellaneous Control */ +- uint8_t reserved1c0[0x1c4 - 0x1c0]; +- uint32_t dfiphymstr; /* 0x1c4 DFI PHY Master interface */ +- uint8_t reserved1c8[0x204 - 0x1c8]; +- uint32_t addrmap1; /* 0x204 Address Map 1 */ +- uint32_t addrmap2; /* 0x208 Address Map 2 */ +- uint32_t addrmap3; /* 0x20c Address Map 3 */ +- uint32_t addrmap4; /* 0x210 Address Map 4 */ +- uint32_t addrmap5; /* 0x214 Address Map 5 */ +- uint32_t addrmap6; /* 0x218 Address Map 6 */ +- uint8_t reserved21c[0x224 - 0x21c]; +- uint32_t addrmap9; /* 0x224 Address Map 9 */ +- uint32_t addrmap10; /* 0x228 Address Map 10 */ +- uint32_t addrmap11; /* 0x22C Address Map 11 */ +- uint8_t reserved230[0x240 - 0x230]; +- uint32_t odtcfg; /* 0x240 ODT Configuration */ +- uint32_t odtmap; /* 0x244 ODT/Rank Map */ +- uint8_t reserved248[0x250 - 0x248]; +- uint32_t sched; /* 0x250 Scheduler Control */ +- uint32_t sched1; /* 0x254 Scheduler Control 1 */ +- uint32_t reserved258; +- uint32_t perfhpr1; /* 0x25c High Priority Read CAM 1 */ +- uint32_t reserved260; +- uint32_t perflpr1; /* 0x264 Low Priority Read CAM 1 */ +- uint32_t reserved268; +- uint32_t perfwr1; /* 0x26c Write CAM 1 */ +- uint8_t reserved27c[0x300 - 0x270]; +- uint32_t dbg0; /* 0x300 Debug 0 */ +- uint32_t dbg1; /* 0x304 Debug 1 */ +- uint32_t dbgcam; /* 0x308 CAM Debug */ +- uint32_t dbgcmd; /* 0x30c Command Debug */ +- uint32_t dbgstat; /* 0x310 Status Debug */ +- uint8_t reserved314[0x320 - 0x314]; +- uint32_t swctl; /* 0x320 Software Programming Control Enable */ +- uint32_t swstat; /* 0x324 Software Programming Control Status */ +- uint8_t reserved328[0x36c - 0x328]; +- uint32_t poisoncfg; /* 0x36c AXI Poison Configuration Register */ +- uint32_t poisonstat; /* 0x370 AXI Poison Status Register */ +- uint8_t reserved374[0x3fc - 0x374]; +- +- /* Multi Port registers */ +- uint32_t pstat; /* 0x3fc Port Status */ +- uint32_t pccfg; /* 0x400 Port Common Configuration */ +- +- /* PORT 0 */ +- uint32_t pcfgr_0; /* 0x404 Configuration Read */ +- uint32_t pcfgw_0; /* 0x408 Configuration Write */ +- uint8_t reserved40c[0x490 - 0x40c]; +- uint32_t pctrl_0; /* 0x490 Port Control Register */ +- uint32_t pcfgqos0_0; /* 0x494 Read QoS Configuration 0 */ +- uint32_t pcfgqos1_0; /* 0x498 Read QoS Configuration 1 */ +- uint32_t pcfgwqos0_0; /* 0x49c Write QoS Configuration 0 */ +- uint32_t pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1 */ +- uint8_t reserved4a4[0x4b4 - 0x4a4]; +- +- /* PORT 1 */ +- uint32_t pcfgr_1; /* 0x4b4 Configuration Read */ +- uint32_t pcfgw_1; /* 0x4b8 Configuration Write */ +- uint8_t reserved4bc[0x540 - 0x4bc]; +- uint32_t pctrl_1; /* 0x540 Port 2 Control Register */ +- uint32_t pcfgqos0_1; /* 0x544 Read QoS Configuration 0 */ +- uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */ +- uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */ +- uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */ +-} __packed; +- + /* DDR Physical Interface Control (DDRPHYC) registers*/ +-struct stm32mp1_ddrphy { ++struct stm32mp_ddrphy { + uint32_t ridr; /* 0x00 R Revision Identification */ + uint32_t pir; /* 0x04 R/W PHY Initialization */ + uint32_t pgcr; /* 0x08 R/W PHY General Configuration */ +@@ -214,6 +85,7 @@ struct stm32mp1_ddrphy { + uint32_t dx1dqtr; /* 0x210 Byte lane 1 DQ Timing */ + uint32_t dx1dqstr; /* 0x214 Byte lane 1 QS Timing */ + uint8_t res6[0x240 - 0x218]; /* 0x218 */ ++#if STM32MP_DDR_32BIT_INTERFACE + uint32_t dx2gcr; /* 0x240 Byte lane 2 General Configuration */ + uint32_t dx2gsr0; /* 0x244 Byte lane 2 General Status 0 */ + uint32_t dx2gsr1; /* 0x248 Byte lane 2 General Status 1 */ +@@ -227,103 +99,9 @@ struct stm32mp1_ddrphy { + uint32_t dx3dllcr; /* 0x28c Byte lane 3 DLL Control */ + uint32_t dx3dqtr; /* 0x290 Byte lane 3 DQ Timing */ + uint32_t dx3dqstr; /* 0x294 Byte lane 3 QS Timing */ ++#endif + } __packed; + +-/* DDR Controller registers offsets */ +-#define DDRCTRL_MSTR 0x000 +-#define DDRCTRL_STAT 0x004 +-#define DDRCTRL_MRCTRL0 0x010 +-#define DDRCTRL_MRSTAT 0x018 +-#define DDRCTRL_PWRCTL 0x030 +-#define DDRCTRL_PWRTMG 0x034 +-#define DDRCTRL_HWLPCTL 0x038 +-#define DDRCTRL_RFSHCTL3 0x060 +-#define DDRCTRL_RFSHTMG 0x064 +-#define DDRCTRL_INIT0 0x0D0 +-#define DDRCTRL_DFIMISC 0x1B0 +-#define DDRCTRL_DBG1 0x304 +-#define DDRCTRL_DBGCAM 0x308 +-#define DDRCTRL_DBGCMD 0x30C +-#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) +-#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER BIT(13) +-#define DDRCTRL_MSTR_DLL_OFF_MODE BIT(15) +- +-#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0) +-#define DDRCTRL_STAT_OPERATING_MODE_NORMAL BIT(0) +-#define DDRCTRL_STAT_OPERATING_MODE_SR (BIT(0) | BIT(1)) +-#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4) +-#define DDRCTRL_STAT_SELFREF_TYPE_ASR (BIT(4) | BIT(5)) +-#define DDRCTRL_STAT_SELFREF_TYPE_SR BIT(5) +- +-#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE U(0) +-/* Only one rank supported */ +-#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 +-#define DDRCTRL_MRCTRL0_MR_RANK_ALL \ +- 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) +- +-#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0) +- +-#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0) +-#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1) +-#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) +-#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) +- +-#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16) +-#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) +- +-#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) +- +-#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0) +- +-#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16) +-#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 +- +-#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK(31, 30) +-#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL BIT(30) +- +-#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) +- +-#define DDRCTRL_DBG1_DIS_HIF BIT(1) +- +-#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) +-#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) +-#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) +-#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) +-#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) +-#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ +- (DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ +- DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) +-#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ +- (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ +- DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ +- DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) +- +-#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) +- +-#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) +- +-#define DDRCTRL_SWCTL_SW_DONE BIT(0) +- +-#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) +- +-#define DDRCTRL_PCTRL_N_PORT_EN BIT(0) +- + /* DDR PHY registers offsets */ + #define DDRPHYC_PIR 0x004 + #define DDRPHYC_PGCR 0x008 +@@ -339,10 +117,12 @@ struct stm32mp1_ddrphy { + #define DDRPHYC_DX0DLLCR 0x1CC + #define DDRPHYC_DX1GCR 0x200 + #define DDRPHYC_DX1DLLCR 0x20C ++#if STM32MP_DDR_32BIT_INTERFACE + #define DDRPHYC_DX2GCR 0x240 + #define DDRPHYC_DX2DLLCR 0x24C + #define DDRPHYC_DX3GCR 0x280 + #define DDRPHYC_DX3DLLCR 0x28C ++#endif + + /* DDR PHY Register fields */ + #define DDRPHYC_PIR_INIT BIT(0) +@@ -353,6 +133,7 @@ struct stm32mp1_ddrphy { + #define DDRPHYC_PIR_DRAMRST BIT(5) + #define DDRPHYC_PIR_DRAMINIT BIT(6) + #define DDRPHYC_PIR_QSTRN BIT(7) ++#define DDRPHYC_PIR_RVTRN BIT(8) + #define DDRPHYC_PIR_ICPC BIT(16) + #define DDRPHYC_PIR_ZCALBYP BIT(30) + #define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) +@@ -380,6 +161,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) +@@ -399,6 +181,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/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h +index e17df44fb..44a42b6b2 100644 +--- a/include/drivers/st/stm32mp1_pwr.h ++++ b/include/drivers/st/stm32mp1_pwr.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 + */ +@@ -13,20 +13,42 @@ + #define PWR_CR2 U(0x08) + #define PWR_CR3 U(0x0C) + #define PWR_MPUCR U(0x10) ++#define PWR_MCUCR U(0x14) + #define PWR_WKUPCR U(0x20) + #define PWR_MPUWKUPENR U(0x28) + ++#define PWR_OFFSET_MASK GENMASK(9, 0) ++ + #define PWR_CR1_LPDS BIT(0) + #define PWR_CR1_LPCFG BIT(1) + #define PWR_CR1_LVDS BIT(2) + #define PWR_CR1_DBP BIT(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) + #define PWR_CR3_DDRSREN BIT(10) + #define PWR_CR3_DDRSRDIS BIT(11) + #define PWR_CR3_DDRRETEN BIT(12) ++#define PWR_CR3_USB33DEN BIT(24) ++#define PWR_CR3_REG18EN BIT(28) ++#define PWR_CR3_REG11EN BIT(30) ++ ++#define PWR_CR3_POPL_SHIFT 17 ++#define PWR_CR3_POPL_MASK GENMASK_32(21, 17) + + #define PWR_MPUCR_PDDS BIT(0) + #define PWR_MPUCR_CSTDBYDIS BIT(3) + #define PWR_MPUCR_CSSF BIT(9) + ++#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) ++ + #endif /* STM32MP1_PWR_H */ +diff --git a/include/drivers/st/stm32mp1_ram.h b/include/drivers/st/stm32mp1_ram.h +index 38360e759..adecd409d 100644 +--- a/include/drivers/st/stm32mp1_ram.h ++++ b/include/drivers/st/stm32mp1_ram.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -7,6 +7,7 @@ + #ifndef STM32MP1_RAM_H + #define STM32MP1_RAM_H + ++bool stm32mp1_ddr_is_restored(void); + int stm32mp1_ddr_probe(void); + + #endif /* STM32MP1_RAM_H */ +diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h +index 14f93fdce..39b343f49 100644 +--- a/include/drivers/st/stm32mp1_rcc.h ++++ b/include/drivers/st/stm32mp1_rcc.h +@@ -4,2325 +4,9 @@ + * SPDX-License-Identifier: BSD-3-Clause + */ + +-#ifndef STM32MP1_RCC_H +-#define STM32MP1_RCC_H +- +-#include +- +-#define RCC_TZCR U(0x00) +-#define RCC_OCENSETR U(0x0C) +-#define RCC_OCENCLRR U(0x10) +-#define RCC_HSICFGR U(0x18) +-#define RCC_CSICFGR U(0x1C) +-#define RCC_MPCKSELR U(0x20) +-#define RCC_ASSCKSELR U(0x24) +-#define RCC_RCK12SELR U(0x28) +-#define RCC_MPCKDIVR U(0x2C) +-#define RCC_AXIDIVR U(0x30) +-#define RCC_APB4DIVR U(0x3C) +-#define RCC_APB5DIVR U(0x40) +-#define RCC_RTCDIVR U(0x44) +-#define RCC_MSSCKSELR U(0x48) +-#define RCC_PLL1CR U(0x80) +-#define RCC_PLL1CFGR1 U(0x84) +-#define RCC_PLL1CFGR2 U(0x88) +-#define RCC_PLL1FRACR U(0x8C) +-#define RCC_PLL1CSGR U(0x90) +-#define RCC_PLL2CR U(0x94) +-#define RCC_PLL2CFGR1 U(0x98) +-#define RCC_PLL2CFGR2 U(0x9C) +-#define RCC_PLL2FRACR U(0xA0) +-#define RCC_PLL2CSGR U(0xA4) +-#define RCC_I2C46CKSELR U(0xC0) +-#define RCC_SPI6CKSELR U(0xC4) +-#define RCC_UART1CKSELR U(0xC8) +-#define RCC_RNG1CKSELR U(0xCC) +-#define RCC_CPERCKSELR U(0xD0) +-#define RCC_STGENCKSELR U(0xD4) +-#define RCC_DDRITFCR U(0xD8) +-#define RCC_MP_BOOTCR U(0x100) +-#define RCC_MP_SREQSETR U(0x104) +-#define RCC_MP_SREQCLRR U(0x108) +-#define RCC_MP_GCR U(0x10C) +-#define RCC_MP_APRSTCR U(0x110) +-#define RCC_MP_APRSTSR U(0x114) +-#define RCC_BDCR U(0x140) +-#define RCC_RDLSICR U(0x144) +-#define RCC_APB4RSTSETR U(0x180) +-#define RCC_APB4RSTCLRR U(0x184) +-#define RCC_APB5RSTSETR U(0x188) +-#define RCC_APB5RSTCLRR U(0x18C) +-#define RCC_AHB5RSTSETR U(0x190) +-#define RCC_AHB5RSTCLRR U(0x194) +-#define RCC_AHB6RSTSETR U(0x198) +-#define RCC_AHB6RSTCLRR U(0x19C) +-#define RCC_TZAHB6RSTSETR U(0x1A0) +-#define RCC_TZAHB6RSTCLRR U(0x1A4) +-#define RCC_MP_APB4ENSETR U(0x200) +-#define RCC_MP_APB4ENCLRR U(0x204) +-#define RCC_MP_APB5ENSETR U(0x208) +-#define RCC_MP_APB5ENCLRR U(0x20C) +-#define RCC_MP_AHB5ENSETR U(0x210) +-#define RCC_MP_AHB5ENCLRR U(0x214) +-#define RCC_MP_AHB6ENSETR U(0x218) +-#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) +-#define RCC_MP_APB5LPENCLRR U(0x30C) +-#define RCC_MP_AHB5LPENSETR U(0x310) +-#define RCC_MP_AHB5LPENCLRR U(0x314) +-#define RCC_MP_AHB6LPENSETR U(0x318) +-#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) +-#define RCC_MP_IWDGFZSETR U(0x40C) +-#define RCC_MP_IWDGFZCLRR U(0x410) +-#define RCC_MP_CIER U(0x414) +-#define RCC_MP_CIFR U(0x418) +-#define RCC_PWRLPDLYCR U(0x41C) +-#define RCC_MP_RSTSSETR U(0x420) +-#define RCC_MCO1CFGR U(0x800) +-#define RCC_MCO2CFGR U(0x804) +-#define RCC_OCRDYR U(0x808) +-#define RCC_DBGCFGR U(0x80C) +-#define RCC_RCK3SELR U(0x820) +-#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) +-#define RCC_PLL3CR U(0x880) +-#define RCC_PLL3CFGR1 U(0x884) +-#define RCC_PLL3CFGR2 U(0x888) +-#define RCC_PLL3FRACR U(0x88C) +-#define RCC_PLL3CSGR U(0x890) +-#define RCC_PLL4CR U(0x894) +-#define RCC_PLL4CFGR1 U(0x898) +-#define RCC_PLL4CFGR2 U(0x89C) +-#define RCC_PLL4FRACR U(0x8A0) +-#define RCC_PLL4CSGR U(0x8A4) +-#define RCC_I2C12CKSELR U(0x8C0) +-#define RCC_I2C35CKSELR U(0x8C4) +-#define RCC_SAI1CKSELR U(0x8C8) +-#define RCC_SAI2CKSELR U(0x8CC) +-#define RCC_SAI3CKSELR U(0x8D0) +-#define RCC_SAI4CKSELR U(0x8D4) +-#define RCC_SPI2S1CKSELR U(0x8D8) +-#define RCC_SPI2S23CKSELR U(0x8DC) +-#define RCC_SPI45CKSELR U(0x8E0) +-#define RCC_UART6CKSELR U(0x8E4) +-#define RCC_UART24CKSELR U(0x8E8) +-#define RCC_UART35CKSELR U(0x8EC) +-#define RCC_UART78CKSELR U(0x8F0) +-#define RCC_SDMMC12CKSELR U(0x8F4) +-#define RCC_SDMMC3CKSELR U(0x8F8) +-#define RCC_ETHCKSELR U(0x8FC) +-#define RCC_QSPICKSELR U(0x900) +-#define RCC_FMCCKSELR U(0x904) +-#define RCC_FDCANCKSELR U(0x90C) +-#define RCC_SPDIFCKSELR U(0x914) +-#define RCC_CECCKSELR U(0x918) +-#define RCC_USBCKSELR U(0x91C) +-#define RCC_RNG2CKSELR U(0x920) +-#define RCC_DSICKSELR U(0x924) +-#define RCC_ADCCKSELR U(0x928) +-#define RCC_LPTIM45CKSELR U(0x92C) +-#define RCC_LPTIM23CKSELR U(0x930) +-#define RCC_LPTIM1CKSELR U(0x934) +-#define RCC_APB1RSTSETR U(0x980) +-#define RCC_APB1RSTCLRR U(0x984) +-#define RCC_APB2RSTSETR U(0x988) +-#define RCC_APB2RSTCLRR U(0x98C) +-#define RCC_APB3RSTSETR U(0x990) +-#define RCC_APB3RSTCLRR U(0x994) +-#define RCC_AHB2RSTSETR U(0x998) +-#define RCC_AHB2RSTCLRR U(0x99C) +-#define RCC_AHB3RSTSETR U(0x9A0) +-#define RCC_AHB3RSTCLRR U(0x9A4) +-#define RCC_AHB4RSTSETR U(0x9A8) +-#define RCC_AHB4RSTCLRR U(0x9AC) +-#define RCC_MP_APB1ENSETR U(0xA00) +-#define RCC_MP_APB1ENCLRR U(0xA04) +-#define RCC_MP_APB2ENSETR U(0xA08) +-#define RCC_MP_APB2ENCLRR U(0xA0C) +-#define RCC_MP_APB3ENSETR U(0xA10) +-#define RCC_MP_APB3ENCLRR U(0xA14) +-#define RCC_MP_AHB2ENSETR U(0xA18) +-#define RCC_MP_AHB2ENCLRR U(0xA1C) +-#define RCC_MP_AHB3ENSETR U(0xA20) +-#define RCC_MP_AHB3ENCLRR U(0xA24) +-#define RCC_MP_AHB4ENSETR U(0xA28) +-#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) +-#define RCC_MP_APB2LPENCLRR U(0xB0C) +-#define RCC_MP_APB3LPENSETR U(0xB10) +-#define RCC_MP_APB3LPENCLRR U(0xB14) +-#define RCC_MP_AHB2LPENSETR U(0xB18) +-#define RCC_MP_AHB2LPENCLRR U(0xB1C) +-#define RCC_MP_AHB3LPENSETR U(0xB20) +-#define RCC_MP_AHB3LPENCLRR U(0xB24) +-#define RCC_MP_AHB4LPENSETR U(0xB28) +-#define RCC_MP_AHB4LPENCLRR U(0xB2C) +-#define RCC_MP_AXIMLPENSETR U(0xB30) +-#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) +- +-/* RCC_TZCR register fields */ +-#define RCC_TZCR_TZEN BIT(0) +-#define RCC_TZCR_MCKPROT BIT(1) +- +-/* RCC_OCENSETR register fields */ +-#define RCC_OCENSETR_HSION BIT(0) +-#define RCC_OCENSETR_HSIKERON BIT(1) +-#define RCC_OCENSETR_CSION BIT(4) +-#define RCC_OCENSETR_CSIKERON BIT(5) +-#define RCC_OCENSETR_DIGBYP BIT(7) +-#define RCC_OCENSETR_HSEON BIT(8) +-#define RCC_OCENSETR_HSEKERON BIT(9) +-#define RCC_OCENSETR_HSEBYP BIT(10) +-#define RCC_OCENSETR_HSECSSON BIT(11) +- +-/* RCC_OCENCLRR register fields */ +-#define RCC_OCENCLRR_HSION BIT(0) +-#define RCC_OCENCLRR_HSIKERON BIT(1) +-#define RCC_OCENCLRR_CSION BIT(4) +-#define RCC_OCENCLRR_CSIKERON BIT(5) +-#define RCC_OCENCLRR_DIGBYP BIT(7) +-#define RCC_OCENCLRR_HSEON BIT(8) +-#define RCC_OCENCLRR_HSEKERON BIT(9) +-#define RCC_OCENCLRR_HSEBYP BIT(10) +- +-/* RCC_HSICFGR register fields */ +-#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +-#define RCC_HSICFGR_HSIDIV_SHIFT 0 +-#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +-#define RCC_HSICFGR_HSITRIM_SHIFT 8 +-#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16) +-#define RCC_HSICFGR_HSICAL_SHIFT 16 +-#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25) +- +-/* RCC_CSICFGR register fields */ +-#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +-#define RCC_CSICFGR_CSITRIM_SHIFT 8 +-#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +-#define RCC_CSICFGR_CSICAL_SHIFT 16 +- +-/* RCC_MPCKSELR register fields */ +-#define RCC_MPCKSELR_HSI 0x00000000 +-#define RCC_MPCKSELR_HSE 0x00000001 +-#define RCC_MPCKSELR_PLL 0x00000002 +-#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 +-#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +-#define RCC_MPCKSELR_MPUSRC_SHIFT 0 +-#define RCC_MPCKSELR_MPUSRCRDY BIT(31) +- +-/* RCC_ASSCKSELR register fields */ +-#define RCC_ASSCKSELR_HSI 0x00000000 +-#define RCC_ASSCKSELR_HSE 0x00000001 +-#define RCC_ASSCKSELR_PLL 0x00000002 +-#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +-#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 +-#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) +- +-/* RCC_RCK12SELR register fields */ +-#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +-#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 +-#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) +- +-/* RCC_MPCKDIVR register fields */ +-#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(2, 0) +-#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 +-#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) +- +-/* RCC_AXIDIVR register fields */ +-#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +-#define RCC_AXIDIVR_AXIDIV_SHIFT 0 +-#define RCC_AXIDIVR_AXIDIVRDY BIT(31) +- +-/* RCC_APB4DIVR register fields */ +-#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +-#define RCC_APB4DIVR_APB4DIV_SHIFT 0 +-#define RCC_APB4DIVR_APB4DIVRDY BIT(31) +- +-/* RCC_APB5DIVR register fields */ +-#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +-#define RCC_APB5DIVR_APB5DIV_SHIFT 0 +-#define RCC_APB5DIVR_APB5DIVRDY BIT(31) +- +-/* RCC_RTCDIVR register fields */ +-#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +-#define RCC_RTCDIVR_RTCDIV_SHIFT 0 +- +-/* RCC_MSSCKSELR register fields */ +-#define RCC_MSSCKSELR_HSI 0x00000000 +-#define RCC_MSSCKSELR_HSE 0x00000001 +-#define RCC_MSSCKSELR_CSI 0x00000002 +-#define RCC_MSSCKSELR_PLL 0x00000003 +-#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(1, 0) +-#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 +-#define RCC_MSSCKSELR_MCUSSRCRDY BIT(31) +- +-/* RCC_PLL1CR register fields */ +-#define RCC_PLL1CR_PLLON BIT(0) +-#define RCC_PLL1CR_PLL1RDY BIT(1) +-#define RCC_PLL1CR_SSCG_CTRL BIT(2) +-#define RCC_PLL1CR_DIVPEN BIT(4) +-#define RCC_PLL1CR_DIVQEN BIT(5) +-#define RCC_PLL1CR_DIVREN BIT(6) +- +-/* RCC_PLL1CFGR1 register fields */ +-#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +-#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +-#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +-#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 +- +-/* RCC_PLL1CFGR2 register fields */ +-#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +-#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +-#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +-#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +-#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +-#define RCC_PLL1CFGR2_DIVR_SHIFT 16 +- +-/* RCC_PLL1FRACR register fields */ +-#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +-#define RCC_PLL1FRACR_FRACV_SHIFT 3 +-#define RCC_PLL1FRACR_FRACLE BIT(16) +- +-/* RCC_PLL1CSGR register fields */ +-#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +-#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +-#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +-#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +-#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +-#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +-#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 +- +-/* RCC_PLL2CR register fields */ +-#define RCC_PLL2CR_PLLON BIT(0) +-#define RCC_PLL2CR_PLL2RDY BIT(1) +-#define RCC_PLL2CR_SSCG_CTRL BIT(2) +-#define RCC_PLL2CR_DIVPEN BIT(4) +-#define RCC_PLL2CR_DIVQEN BIT(5) +-#define RCC_PLL2CR_DIVREN BIT(6) +- +-/* RCC_PLL2CFGR1 register fields */ +-#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +-#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +-#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +-#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 +- +-/* RCC_PLL2CFGR2 register fields */ +-#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +-#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +-#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +-#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +-#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +-#define RCC_PLL2CFGR2_DIVR_SHIFT 16 +- +-/* RCC_PLL2FRACR register fields */ +-#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +-#define RCC_PLL2FRACR_FRACV_SHIFT 3 +-#define RCC_PLL2FRACR_FRACLE BIT(16) +- +-/* RCC_PLL2CSGR register fields */ +-#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +-#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +-#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +-#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +-#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +-#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +-#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 +- +-/* 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_CPERCKSELR register fields */ +-#define RCC_CPERCKSELR_HSI 0x00000000 +-#define RCC_CPERCKSELR_CSI 0x00000001 +-#define RCC_CPERCKSELR_HSE 0x00000002 +-#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +-#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 +- +-/* RCC_STGENCKSELR register fields */ +-#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +-#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 +- +-/* RCC_DDRITFCR register fields */ +-#define RCC_DDRITFCR_DDRC1EN BIT(0) +-#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +-#define RCC_DDRITFCR_DDRC2EN BIT(2) +-#define RCC_DDRITFCR_DDRC2LPEN BIT(3) +-#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +-#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +-#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +-#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +-#define RCC_DDRITFCR_AXIDCGEN BIT(8) +-#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +-#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +-#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +-#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +-#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +-#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +-#define RCC_DDRITFCR_DDRCORERST BIT(16) +-#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +-#define RCC_DDRITFCR_DPHYRST BIT(18) +-#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +-#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +-#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +-#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +-#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +-#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) +-#define RCC_DDRITFCR_GSKPMOD BIT(23) +-#define RCC_DDRITFCR_GSKPCTRL BIT(24) +-#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +-#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +-#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +-#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 +- +-/* RCC_MP_BOOTCR register fields */ +-#define RCC_MP_BOOTCR_MCU_BEN BIT(0) +-#define RCC_MP_BOOTCR_MPU_BEN BIT(1) +- +-/* RCC_MP_SREQSETR register fields */ +-#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) +-#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) +- +-/* RCC_MP_SREQCLRR register fields */ +-#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) +-#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) +- +-/* RCC_MP_GCR register fields */ +-#define RCC_MP_GCR_BOOT_MCU BIT(0) +- +-/* RCC_MP_APRSTCR register fields */ +-#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +-#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +-#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 +- +-/* RCC_MP_APRSTSR register fields */ +-#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +-#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 +- +-/* RCC_BDCR register fields */ +-#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) +-#define RCC_BDCR_LSECSSD BIT(9) +-#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +-#define RCC_BDCR_RTCSRC_SHIFT 16 +-#define RCC_BDCR_RTCCKEN BIT(20) +-#define RCC_BDCR_VSWRST BIT(31) +- +-/* RCC_RDLSICR register fields */ +-#define RCC_RDLSICR_LSION BIT(0) +-#define RCC_RDLSICR_LSIRDY BIT(1) +-#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +-#define RCC_RDLSICR_MRD_SHIFT 16 +-#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +-#define RCC_RDLSICR_EADLY_SHIFT 24 +-#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +-#define RCC_RDLSICR_SPARE_SHIFT 27 +- +-/* RCC_APB4RSTSETR register fields */ +-#define RCC_APB4RSTSETR_LTDCRST BIT(0) +-#define RCC_APB4RSTSETR_DSIRST BIT(4) +-#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +-#define RCC_APB4RSTSETR_USBPHYRST BIT(16) +- +-/* RCC_APB4RSTCLRR register fields */ +-#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +-#define RCC_APB4RSTCLRR_DSIRST BIT(4) +-#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +-#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) +- +-/* RCC_APB5RSTSETR register fields */ +-#define RCC_APB5RSTSETR_SPI6RST BIT(0) +-#define RCC_APB5RSTSETR_I2C4RST BIT(2) +-#define RCC_APB5RSTSETR_I2C6RST BIT(3) +-#define RCC_APB5RSTSETR_USART1RST BIT(4) +-#define RCC_APB5RSTSETR_STGENRST BIT(20) +- +-/* RCC_APB5RSTCLRR register fields */ +-#define RCC_APB5RSTCLRR_SPI6RST BIT(0) +-#define RCC_APB5RSTCLRR_I2C4RST BIT(2) +-#define RCC_APB5RSTCLRR_I2C6RST BIT(3) +-#define RCC_APB5RSTCLRR_USART1RST BIT(4) +-#define RCC_APB5RSTCLRR_STGENRST BIT(20) +- +-/* RCC_AHB5RSTSETR register fields */ +-#define RCC_AHB5RSTSETR_GPIOZRST BIT(0) +-#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +-#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +-#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +-#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) +- +-/* RCC_AHB5RSTCLRR register fields */ +-#define RCC_AHB5RSTCLRR_GPIOZRST BIT(0) +-#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +-#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +-#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +-#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) +- +-/* RCC_AHB6RSTSETR register fields */ +-#define RCC_AHB6RSTSETR_GPURST BIT(5) +-#define RCC_AHB6RSTSETR_ETHMACRST BIT(10) +-#define RCC_AHB6RSTSETR_FMCRST BIT(12) +-#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +-#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +-#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +-#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +-#define RCC_AHB6RSTSETR_USBHRST BIT(24) +- +-/* RCC_AHB6RSTCLRR register fields */ +-#define RCC_AHB6RSTCLRR_ETHMACRST BIT(10) +-#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +-#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +-#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +-#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +-#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +-#define RCC_AHB6RSTCLRR_USBHRST BIT(24) +- +-/* RCC_TZAHB6RSTSETR register fields */ +-#define RCC_TZAHB6RSTSETR_MDMARST BIT(0) +- +-/* RCC_TZAHB6RSTCLRR register fields */ +-#define RCC_TZAHB6RSTCLRR_MDMARST BIT(0) +- +-/* RCC_MP_APB4ENSETR register fields */ +-#define RCC_MP_APB4ENSETR_LTDCEN BIT(0) +-#define RCC_MP_APB4ENSETR_DSIEN BIT(4) +-#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +-#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +-#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +-#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) +- +-/* RCC_MP_APB4ENCLRR register fields */ +-#define RCC_MP_APB4ENCLRR_LTDCEN BIT(0) +-#define RCC_MP_APB4ENCLRR_DSIEN BIT(4) +-#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +-#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +-#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +-#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) +- +-/* RCC_MP_APB5ENSETR register fields */ +-#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_TZC1EN BIT(11) +-#define RCC_MP_APB5ENSETR_TZC2EN BIT(12) +-#define RCC_MP_APB5ENSETR_TZPCEN BIT(13) +-#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +-#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +-#define RCC_MP_APB5ENSETR_STGENEN BIT(20) +- +-/* RCC_MP_APB5ENCLRR register fields */ +-#define RCC_MP_APB5ENCLRR_SPI6EN BIT(0) +-#define RCC_MP_APB5ENCLRR_I2C4EN BIT(2) +-#define RCC_MP_APB5ENCLRR_I2C6EN BIT(3) +-#define RCC_MP_APB5ENCLRR_USART1EN BIT(4) +-#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +-#define RCC_MP_APB5ENCLRR_TZC1EN BIT(11) +-#define RCC_MP_APB5ENCLRR_TZC2EN BIT(12) +-#define RCC_MP_APB5ENCLRR_TZPCEN BIT(13) +-#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +-#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +-#define RCC_MP_APB5ENCLRR_STGENEN BIT(20) +- +-/* RCC_MP_AHB5ENSETR register fields */ +-#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) +-#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +-#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) +- +-/* RCC_MP_AHB5ENCLRR register fields */ +-#define RCC_MP_AHB5ENCLRR_GPIOZEN BIT(0) +-#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +-#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +-#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +-#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +-#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) +- +-/* RCC_MP_AHB6ENSETR register fields */ +-#define RCC_MP_AHB6ENSETR_MDMAEN BIT(0) +-#define RCC_MP_AHB6ENSETR_GPUEN BIT(5) +-#define RCC_MP_AHB6ENSETR_ETHCKEN BIT(7) +-#define RCC_MP_AHB6ENSETR_ETHTXEN BIT(8) +-#define RCC_MP_AHB6ENSETR_ETHRXEN BIT(9) +-#define RCC_MP_AHB6ENSETR_ETHMACEN BIT(10) +-#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +-#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +-#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +-#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +-#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +-#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) +- +-/* RCC_MP_AHB6ENCLRR register fields */ +-#define RCC_MP_AHB6ENCLRR_MDMAEN BIT(0) +-#define RCC_MP_AHB6ENCLRR_GPUEN BIT(5) +-#define RCC_MP_AHB6ENCLRR_ETHCKEN BIT(7) +-#define RCC_MP_AHB6ENCLRR_ETHTXEN BIT(8) +-#define RCC_MP_AHB6ENCLRR_ETHRXEN BIT(9) +-#define RCC_MP_AHB6ENCLRR_ETHMACEN BIT(10) +-#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +-#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +-#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +-#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +-#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +-#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) +- +-/* RCC_MP_TZAHB6ENSETR register fields */ +-#define RCC_MP_TZAHB6ENSETR_MDMAEN BIT(0) +- +-/* RCC_MP_TZAHB6ENCLRR register fields */ +-#define RCC_MP_TZAHB6ENCLRR_MDMAEN BIT(0) +- +-/* RCC_MC_APB4ENSETR register fields */ +-#define RCC_MC_APB4ENSETR_LTDCEN BIT(0) +-#define RCC_MC_APB4ENSETR_DSIEN BIT(4) +-#define RCC_MC_APB4ENSETR_DDRPERFMEN BIT(8) +-#define RCC_MC_APB4ENSETR_USBPHYEN BIT(16) +-#define RCC_MC_APB4ENSETR_STGENROEN BIT(20) +- +-/* RCC_MC_APB4ENCLRR register fields */ +-#define RCC_MC_APB4ENCLRR_LTDCEN BIT(0) +-#define RCC_MC_APB4ENCLRR_DSIEN BIT(4) +-#define RCC_MC_APB4ENCLRR_DDRPERFMEN BIT(8) +-#define RCC_MC_APB4ENCLRR_USBPHYEN BIT(16) +-#define RCC_MC_APB4ENCLRR_STGENROEN BIT(20) +- +-/* RCC_MC_APB5ENSETR register fields */ +-#define RCC_MC_APB5ENSETR_SPI6EN BIT(0) +-#define RCC_MC_APB5ENSETR_I2C4EN BIT(2) +-#define RCC_MC_APB5ENSETR_I2C6EN BIT(3) +-#define RCC_MC_APB5ENSETR_USART1EN BIT(4) +-#define RCC_MC_APB5ENSETR_RTCAPBEN BIT(8) +-#define RCC_MC_APB5ENSETR_TZC1EN BIT(11) +-#define RCC_MC_APB5ENSETR_TZC2EN BIT(12) +-#define RCC_MC_APB5ENSETR_TZPCEN BIT(13) +-#define RCC_MC_APB5ENSETR_BSECEN BIT(16) +-#define RCC_MC_APB5ENSETR_STGENEN BIT(20) +- +-/* RCC_MC_APB5ENCLRR register fields */ +-#define RCC_MC_APB5ENCLRR_SPI6EN BIT(0) +-#define RCC_MC_APB5ENCLRR_I2C4EN BIT(2) +-#define RCC_MC_APB5ENCLRR_I2C6EN BIT(3) +-#define RCC_MC_APB5ENCLRR_USART1EN BIT(4) +-#define RCC_MC_APB5ENCLRR_RTCAPBEN BIT(8) +-#define RCC_MC_APB5ENCLRR_TZC1EN BIT(11) +-#define RCC_MC_APB5ENCLRR_TZC2EN BIT(12) +-#define RCC_MC_APB5ENCLRR_TZPCEN BIT(13) +-#define RCC_MC_APB5ENCLRR_BSECEN BIT(16) +-#define RCC_MC_APB5ENCLRR_STGENEN BIT(20) +- +-/* RCC_MC_AHB5ENSETR register fields */ +-#define RCC_MC_AHB5ENSETR_GPIOZEN BIT(0) +-#define RCC_MC_AHB5ENSETR_CRYP1EN BIT(4) +-#define RCC_MC_AHB5ENSETR_HASH1EN BIT(5) +-#define RCC_MC_AHB5ENSETR_RNG1EN BIT(6) +-#define RCC_MC_AHB5ENSETR_BKPSRAMEN BIT(8) +- +-/* RCC_MC_AHB5ENCLRR register fields */ +-#define RCC_MC_AHB5ENCLRR_GPIOZEN BIT(0) +-#define RCC_MC_AHB5ENCLRR_CRYP1EN BIT(4) +-#define RCC_MC_AHB5ENCLRR_HASH1EN BIT(5) +-#define RCC_MC_AHB5ENCLRR_RNG1EN BIT(6) +-#define RCC_MC_AHB5ENCLRR_BKPSRAMEN BIT(8) +- +-/* RCC_MC_AHB6ENSETR register fields */ +-#define RCC_MC_AHB6ENSETR_MDMAEN BIT(0) +-#define RCC_MC_AHB6ENSETR_GPUEN BIT(5) +-#define RCC_MC_AHB6ENSETR_ETHCKEN BIT(7) +-#define RCC_MC_AHB6ENSETR_ETHTXEN BIT(8) +-#define RCC_MC_AHB6ENSETR_ETHRXEN BIT(9) +-#define RCC_MC_AHB6ENSETR_ETHMACEN BIT(10) +-#define RCC_MC_AHB6ENSETR_FMCEN BIT(12) +-#define RCC_MC_AHB6ENSETR_QSPIEN BIT(14) +-#define RCC_MC_AHB6ENSETR_SDMMC1EN BIT(16) +-#define RCC_MC_AHB6ENSETR_SDMMC2EN BIT(17) +-#define RCC_MC_AHB6ENSETR_CRC1EN BIT(20) +-#define RCC_MC_AHB6ENSETR_USBHEN BIT(24) +- +-/* RCC_MC_AHB6ENCLRR register fields */ +-#define RCC_MC_AHB6ENCLRR_MDMAEN BIT(0) +-#define RCC_MC_AHB6ENCLRR_GPUEN BIT(5) +-#define RCC_MC_AHB6ENCLRR_ETHCKEN BIT(7) +-#define RCC_MC_AHB6ENCLRR_ETHTXEN BIT(8) +-#define RCC_MC_AHB6ENCLRR_ETHRXEN BIT(9) +-#define RCC_MC_AHB6ENCLRR_ETHMACEN BIT(10) +-#define RCC_MC_AHB6ENCLRR_FMCEN BIT(12) +-#define RCC_MC_AHB6ENCLRR_QSPIEN BIT(14) +-#define RCC_MC_AHB6ENCLRR_SDMMC1EN BIT(16) +-#define RCC_MC_AHB6ENCLRR_SDMMC2EN BIT(17) +-#define RCC_MC_AHB6ENCLRR_CRC1EN BIT(20) +-#define RCC_MC_AHB6ENCLRR_USBHEN BIT(24) +- +-/* RCC_MP_APB4LPENSETR register fields */ +-#define RCC_MP_APB4LPENSETR_LTDCLPEN BIT(0) +-#define RCC_MP_APB4LPENSETR_DSILPEN BIT(4) +-#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +-#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +-#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +-#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +-#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) +- +-/* RCC_MP_APB4LPENCLRR register fields */ +-#define RCC_MP_APB4LPENCLRR_LTDCLPEN BIT(0) +-#define RCC_MP_APB4LPENCLRR_DSILPEN BIT(4) +-#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +-#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +-#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +-#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +-#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) +- +-/* RCC_MP_APB5LPENSETR register fields */ +-#define RCC_MP_APB5LPENSETR_SPI6LPEN BIT(0) +-#define RCC_MP_APB5LPENSETR_I2C4LPEN BIT(2) +-#define RCC_MP_APB5LPENSETR_I2C6LPEN BIT(3) +-#define RCC_MP_APB5LPENSETR_USART1LPEN BIT(4) +-#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +-#define RCC_MP_APB5LPENSETR_TZC1LPEN BIT(11) +-#define RCC_MP_APB5LPENSETR_TZC2LPEN BIT(12) +-#define RCC_MP_APB5LPENSETR_TZPCLPEN BIT(13) +-#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +-#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +-#define RCC_MP_APB5LPENSETR_STGENLPEN BIT(20) +-#define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) +- +-/* RCC_MP_APB5LPENCLRR register fields */ +-#define RCC_MP_APB5LPENCLRR_SPI6LPEN BIT(0) +-#define RCC_MP_APB5LPENCLRR_I2C4LPEN BIT(2) +-#define RCC_MP_APB5LPENCLRR_I2C6LPEN BIT(3) +-#define RCC_MP_APB5LPENCLRR_USART1LPEN BIT(4) +-#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +-#define RCC_MP_APB5LPENCLRR_TZC1LPEN BIT(11) +-#define RCC_MP_APB5LPENCLRR_TZC2LPEN BIT(12) +-#define RCC_MP_APB5LPENCLRR_TZPCLPEN BIT(13) +-#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +-#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +-#define RCC_MP_APB5LPENCLRR_STGENLPEN BIT(20) +-#define RCC_MP_APB5LPENCLRR_STGENSTPEN BIT(21) +- +-/* RCC_MP_AHB5LPENSETR register fields */ +-#define RCC_MP_AHB5LPENSETR_GPIOZLPEN BIT(0) +-#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +-#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +-#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +-#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) +- +-/* RCC_MP_AHB5LPENCLRR register fields */ +-#define RCC_MP_AHB5LPENCLRR_GPIOZLPEN BIT(0) +-#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +-#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +-#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +-#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) +- +-/* RCC_MP_AHB6LPENSETR register fields */ +-#define RCC_MP_AHB6LPENSETR_MDMALPEN BIT(0) +-#define RCC_MP_AHB6LPENSETR_GPULPEN BIT(5) +-#define RCC_MP_AHB6LPENSETR_ETHCKLPEN BIT(7) +-#define RCC_MP_AHB6LPENSETR_ETHTXLPEN BIT(8) +-#define RCC_MP_AHB6LPENSETR_ETHRXLPEN BIT(9) +-#define RCC_MP_AHB6LPENSETR_ETHMACLPEN BIT(10) +-#define RCC_MP_AHB6LPENSETR_ETHSTPEN BIT(11) +-#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +-#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +-#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +-#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +-#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +-#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) +- +-/* RCC_MP_AHB6LPENCLRR register fields */ +-#define RCC_MP_AHB6LPENCLRR_MDMALPEN BIT(0) +-#define RCC_MP_AHB6LPENCLRR_GPULPEN BIT(5) +-#define RCC_MP_AHB6LPENCLRR_ETHCKLPEN BIT(7) +-#define RCC_MP_AHB6LPENCLRR_ETHTXLPEN BIT(8) +-#define RCC_MP_AHB6LPENCLRR_ETHRXLPEN BIT(9) +-#define RCC_MP_AHB6LPENCLRR_ETHMACLPEN BIT(10) +-#define RCC_MP_AHB6LPENCLRR_ETHSTPEN BIT(11) +-#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +-#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +-#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +-#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +-#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +-#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) +- +-/* RCC_MP_TZAHB6LPENSETR register fields */ +-#define RCC_MP_TZAHB6LPENSETR_MDMALPEN BIT(0) +- +-/* RCC_MP_TZAHB6LPENCLRR register fields */ +-#define RCC_MP_TZAHB6LPENCLRR_MDMALPEN BIT(0) +- +-/* RCC_MC_APB4LPENSETR register fields */ +-#define RCC_MC_APB4LPENSETR_LTDCLPEN BIT(0) +-#define RCC_MC_APB4LPENSETR_DSILPEN BIT(4) +-#define RCC_MC_APB4LPENSETR_DDRPERFMLPEN BIT(8) +-#define RCC_MC_APB4LPENSETR_USBPHYLPEN BIT(16) +-#define RCC_MC_APB4LPENSETR_STGENROLPEN BIT(20) +-#define RCC_MC_APB4LPENSETR_STGENROSTPEN BIT(21) +- +-/* RCC_MC_APB4LPENCLRR register fields */ +-#define RCC_MC_APB4LPENCLRR_LTDCLPEN BIT(0) +-#define RCC_MC_APB4LPENCLRR_DSILPEN BIT(4) +-#define RCC_MC_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +-#define RCC_MC_APB4LPENCLRR_USBPHYLPEN BIT(16) +-#define RCC_MC_APB4LPENCLRR_STGENROLPEN BIT(20) +-#define RCC_MC_APB4LPENCLRR_STGENROSTPEN BIT(21) +- +-/* RCC_MC_APB5LPENSETR register fields */ +-#define RCC_MC_APB5LPENSETR_SPI6LPEN BIT(0) +-#define RCC_MC_APB5LPENSETR_I2C4LPEN BIT(2) +-#define RCC_MC_APB5LPENSETR_I2C6LPEN BIT(3) +-#define RCC_MC_APB5LPENSETR_USART1LPEN BIT(4) +-#define RCC_MC_APB5LPENSETR_RTCAPBLPEN BIT(8) +-#define RCC_MC_APB5LPENSETR_TZC1LPEN BIT(11) +-#define RCC_MC_APB5LPENSETR_TZC2LPEN BIT(12) +-#define RCC_MC_APB5LPENSETR_TZPCLPEN BIT(13) +-#define RCC_MC_APB5LPENSETR_BSECLPEN BIT(16) +-#define RCC_MC_APB5LPENSETR_STGENLPEN BIT(20) +-#define RCC_MC_APB5LPENSETR_STGENSTPEN BIT(21) +- +-/* RCC_MC_APB5LPENCLRR register fields */ +-#define RCC_MC_APB5LPENCLRR_SPI6LPEN BIT(0) +-#define RCC_MC_APB5LPENCLRR_I2C4LPEN BIT(2) +-#define RCC_MC_APB5LPENCLRR_I2C6LPEN BIT(3) +-#define RCC_MC_APB5LPENCLRR_USART1LPEN BIT(4) +-#define RCC_MC_APB5LPENCLRR_RTCAPBLPEN BIT(8) +-#define RCC_MC_APB5LPENCLRR_TZC1LPEN BIT(11) +-#define RCC_MC_APB5LPENCLRR_TZC2LPEN BIT(12) +-#define RCC_MC_APB5LPENCLRR_TZPCLPEN BIT(13) +-#define RCC_MC_APB5LPENCLRR_BSECLPEN BIT(16) +-#define RCC_MC_APB5LPENCLRR_STGENLPEN BIT(20) +-#define RCC_MC_APB5LPENCLRR_STGENSTPEN BIT(21) +- +-/* RCC_MC_AHB5LPENSETR register fields */ +-#define RCC_MC_AHB5LPENSETR_GPIOZLPEN BIT(0) +-#define RCC_MC_AHB5LPENSETR_CRYP1LPEN BIT(4) +-#define RCC_MC_AHB5LPENSETR_HASH1LPEN BIT(5) +-#define RCC_MC_AHB5LPENSETR_RNG1LPEN BIT(6) +-#define RCC_MC_AHB5LPENSETR_BKPSRAMLPEN BIT(8) +- +-/* RCC_MC_AHB5LPENCLRR register fields */ +-#define RCC_MC_AHB5LPENCLRR_GPIOZLPEN BIT(0) +-#define RCC_MC_AHB5LPENCLRR_CRYP1LPEN BIT(4) +-#define RCC_MC_AHB5LPENCLRR_HASH1LPEN BIT(5) +-#define RCC_MC_AHB5LPENCLRR_RNG1LPEN BIT(6) +-#define RCC_MC_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) +- +-/* RCC_MC_AHB6LPENSETR register fields */ +-#define RCC_MC_AHB6LPENSETR_MDMALPEN BIT(0) +-#define RCC_MC_AHB6LPENSETR_GPULPEN BIT(5) +-#define RCC_MC_AHB6LPENSETR_ETHCKLPEN BIT(7) +-#define RCC_MC_AHB6LPENSETR_ETHTXLPEN BIT(8) +-#define RCC_MC_AHB6LPENSETR_ETHRXLPEN BIT(9) +-#define RCC_MC_AHB6LPENSETR_ETHMACLPEN BIT(10) +-#define RCC_MC_AHB6LPENSETR_ETHSTPEN BIT(11) +-#define RCC_MC_AHB6LPENSETR_FMCLPEN BIT(12) +-#define RCC_MC_AHB6LPENSETR_QSPILPEN BIT(14) +-#define RCC_MC_AHB6LPENSETR_SDMMC1LPEN BIT(16) +-#define RCC_MC_AHB6LPENSETR_SDMMC2LPEN BIT(17) +-#define RCC_MC_AHB6LPENSETR_CRC1LPEN BIT(20) +-#define RCC_MC_AHB6LPENSETR_USBHLPEN BIT(24) +- +-/* RCC_MC_AHB6LPENCLRR register fields */ +-#define RCC_MC_AHB6LPENCLRR_MDMALPEN BIT(0) +-#define RCC_MC_AHB6LPENCLRR_GPULPEN BIT(5) +-#define RCC_MC_AHB6LPENCLRR_ETHCKLPEN BIT(7) +-#define RCC_MC_AHB6LPENCLRR_ETHTXLPEN BIT(8) +-#define RCC_MC_AHB6LPENCLRR_ETHRXLPEN BIT(9) +-#define RCC_MC_AHB6LPENCLRR_ETHMACLPEN BIT(10) +-#define RCC_MC_AHB6LPENCLRR_ETHSTPEN BIT(11) +-#define RCC_MC_AHB6LPENCLRR_FMCLPEN BIT(12) +-#define RCC_MC_AHB6LPENCLRR_QSPILPEN BIT(14) +-#define RCC_MC_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +-#define RCC_MC_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +-#define RCC_MC_AHB6LPENCLRR_CRC1LPEN BIT(20) +-#define RCC_MC_AHB6LPENCLRR_USBHLPEN BIT(24) +- +-/* RCC_BR_RSTSCLRR register fields */ +-#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +-#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +-#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +-#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +-#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +-#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +-#define RCC_BR_RSTSCLRR_MCSYSRSTF BIT(7) +-#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +-#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +-#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) +-#define RCC_BR_RSTSCLRR_MPUP1RSTF BIT(14) +- +-/* RCC_MP_GRSTCSETR register fields */ +-#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) +- +-/* RCC_MP_RSTSCLRR register fields */ +-#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) +-#define RCC_MP_RSTSCLRR_SPARE BIT(15) +- +-/* RCC_MP_IWDGFZSETR register fields */ +-#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +-#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) +- +-/* RCC_MP_IWDGFZCLRR register fields */ +-#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +-#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) +- +-/* RCC_MP_CIER register fields */ +-#define RCC_MP_CIER_LSIRDYIE BIT(0) +-#define RCC_MP_CIER_LSERDYIE BIT(1) +-#define RCC_MP_CIER_HSIRDYIE BIT(2) +-#define RCC_MP_CIER_HSERDYIE BIT(3) +-#define RCC_MP_CIER_CSIRDYIE BIT(4) +-#define RCC_MP_CIER_PLL1DYIE BIT(8) +-#define RCC_MP_CIER_PLL2DYIE BIT(9) +-#define RCC_MP_CIER_PLL3DYIE BIT(10) +-#define RCC_MP_CIER_PLL4DYIE BIT(11) +-#define RCC_MP_CIER_LSECSSIE BIT(16) +-#define RCC_MP_CIER_WKUPIE BIT(20) +- +-/* RCC_MP_CIFR register fields */ +-#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_LSECSSF BIT(16) +-#define RCC_MP_CIFR_WKUPF BIT(20) +- +-/* RCC_PWRLPDLYCR register fields */ +-#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +-#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 +-#define RCC_PWRLPDLYCR_MCTMPSKP BIT(24) +- +-/* RCC_MP_RSTSSETR register fields */ +-#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +-#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +-#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +-#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +-#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +-#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +-#define RCC_MP_RSTSSETR_MCSYSRSTF BIT(7) +-#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +-#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +-#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +-#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +-#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +-#define RCC_MP_RSTSSETR_MPUP1RSTF BIT(14) +-#define RCC_MP_RSTSSETR_SPARE BIT(15) +- +-/* RCC_MCO1CFGR register fields */ +-#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +-#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +-#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +-#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 +-#define RCC_MCO1CFGR_MCO1ON BIT(12) +- +-/* RCC_MCO2CFGR register fields */ +-#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +-#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +-#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +-#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 +-#define RCC_MCO2CFGR_MCO2ON BIT(12) +- +-/* RCC_OCRDYR register fields */ +-#define RCC_OCRDYR_HSIRDY BIT(0) +-#define RCC_OCRDYR_HSIDIVRDY BIT(2) +-#define RCC_OCRDYR_CSIRDY BIT(4) +-#define RCC_OCRDYR_HSERDY BIT(8) +-#define RCC_OCRDYR_MPUCKRDY BIT(23) +-#define RCC_OCRDYR_AXICKRDY BIT(24) +-#define RCC_OCRDYR_CKREST BIT(25) +- +-/* RCC_DBGCFGR register fields */ +-#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +-#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 +-#define RCC_DBGCFGR_DBGCKEN BIT(8) +-#define RCC_DBGCFGR_TRACECKEN BIT(9) +-#define RCC_DBGCFGR_DBGRST BIT(12) +- +-/* RCC_RCK3SELR register fields */ +-#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +-#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 +-#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) +- +-/* RCC_RCK4SELR register fields */ +-#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +-#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 +-#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) +- +-/* RCC_TIMG1PRER register fields */ +-#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +-#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) +- +-/* RCC_TIMG2PRER register fields */ +-#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +-#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) +- +-/* RCC_MCUDIVR register fields */ +-#define RCC_MCUDIVR_MCUDIV_MASK GENMASK(3, 0) +-#define RCC_MCUDIVR_MCUDIV_SHIFT 0 +-#define RCC_MCUDIVR_MCUDIVRDY BIT(31) +- +-/* RCC_APB1DIVR register fields */ +-#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +-#define RCC_APB1DIVR_APB1DIV_SHIFT 0 +-#define RCC_APB1DIVR_APB1DIVRDY BIT(31) +- +-/* RCC_APB2DIVR register fields */ +-#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +-#define RCC_APB2DIVR_APB2DIV_SHIFT 0 +-#define RCC_APB2DIVR_APB2DIVRDY BIT(31) +- +-/* RCC_APB3DIVR register fields */ +-#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +-#define RCC_APB3DIVR_APB3DIV_SHIFT 0 +-#define RCC_APB3DIVR_APB3DIVRDY BIT(31) +- +-/* RCC_PLL3CR register fields */ +-#define RCC_PLL3CR_PLLON BIT(0) +-#define RCC_PLL3CR_PLL3RDY BIT(1) +-#define RCC_PLL3CR_SSCG_CTRL BIT(2) +-#define RCC_PLL3CR_DIVPEN BIT(4) +-#define RCC_PLL3CR_DIVQEN BIT(5) +-#define RCC_PLL3CR_DIVREN BIT(6) +- +-/* RCC_PLL3CFGR1 register fields */ +-#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +-#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +-#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +-#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +-#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +-#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 +- +-/* RCC_PLL3CFGR2 register fields */ +-#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +-#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +-#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +-#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +-#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +-#define RCC_PLL3CFGR2_DIVR_SHIFT 16 +- +-/* RCC_PLL3FRACR register fields */ +-#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +-#define RCC_PLL3FRACR_FRACV_SHIFT 3 +-#define RCC_PLL3FRACR_FRACLE BIT(16) +- +-/* RCC_PLL3CSGR register fields */ +-#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +-#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +-#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +-#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +-#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +-#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +-#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 +- +-/* RCC_PLL4CR register fields */ +-#define RCC_PLL4CR_PLLON BIT(0) +-#define RCC_PLL4CR_PLL4RDY BIT(1) +-#define RCC_PLL4CR_SSCG_CTRL BIT(2) +-#define RCC_PLL4CR_DIVPEN BIT(4) +-#define RCC_PLL4CR_DIVQEN BIT(5) +-#define RCC_PLL4CR_DIVREN BIT(6) +- +-/* RCC_PLL4CFGR1 register fields */ +-#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +-#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +-#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +-#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +-#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +-#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 +- +-/* RCC_PLL4CFGR2 register fields */ +-#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +-#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +-#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +-#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +-#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +-#define RCC_PLL4CFGR2_DIVR_SHIFT 16 +- +-/* RCC_PLL4FRACR register fields */ +-#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +-#define RCC_PLL4FRACR_FRACV_SHIFT 3 +-#define RCC_PLL4FRACR_FRACLE BIT(16) +- +-/* RCC_PLL4CSGR register fields */ +-#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +-#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +-#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +-#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +-#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +-#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +-#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 +- +-/* 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_SAI1CKSELR register fields */ +-#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +-#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 +- +-/* RCC_SAI2CKSELR register fields */ +-#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +-#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 +- +-/* RCC_SAI3CKSELR register fields */ +-#define RCC_SAI3CKSELR_SAI3SRC_MASK GENMASK(2, 0) +-#define RCC_SAI3CKSELR_SAI3SRC_SHIFT 0 +- +-/* RCC_SAI4CKSELR register fields */ +-#define RCC_SAI4CKSELR_SAI4SRC_MASK GENMASK(2, 0) +-#define RCC_SAI4CKSELR_SAI4SRC_SHIFT 0 +- +-/* RCC_SPI2S1CKSELR register fields */ +-#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +-#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 +- +-/* RCC_SPI2S23CKSELR register fields */ +-#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +-#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 +- +-/* RCC_SPI45CKSELR register fields */ +-#define RCC_SPI45CKSELR_SPI45SRC_MASK GENMASK(2, 0) +-#define RCC_SPI45CKSELR_SPI45SRC_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_HSI 0x00000002 +-#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 +-#define RCC_ETHCKSELR_ETHPTPDIV_MASK GENMASK(7, 4) +-#define RCC_ETHCKSELR_ETHPTPDIV_SHIFT 4 +- +-/* 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_FDCANCKSELR register fields */ +-#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +-#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 +- +-/* RCC_SPDIFCKSELR register fields */ +-#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +-#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 +- +-/* RCC_CECCKSELR register fields */ +-#define RCC_CECCKSELR_CECSRC_MASK GENMASK(1, 0) +-#define RCC_CECCKSELR_CECSRC_SHIFT 0 +- +-/* RCC_USBCKSELR register fields */ +-#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +-#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +-#define RCC_USBCKSELR_USBOSRC BIT(4) +-#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +-#define RCC_USBCKSELR_USBOSRC_SHIFT 4 +- +-/* RCC_RNG2CKSELR register fields */ +-#define RCC_RNG2CKSELR_RNG2SRC_MASK GENMASK(1, 0) +-#define RCC_RNG2CKSELR_RNG2SRC_SHIFT 0 +- +-/* RCC_DSICKSELR register fields */ +-#define RCC_DSICKSELR_DSISRC BIT(0) +- +-/* RCC_ADCCKSELR register fields */ +-#define RCC_ADCCKSELR_ADCSRC_MASK GENMASK(1, 0) +-#define RCC_ADCCKSELR_ADCSRC_SHIFT 0 +- +-/* RCC_LPTIM45CKSELR register fields */ +-#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +-#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 +- +-/* RCC_LPTIM23CKSELR register fields */ +-#define RCC_LPTIM23CKSELR_LPTIM23SRC_MASK GENMASK(2, 0) +-#define RCC_LPTIM23CKSELR_LPTIM23SRC_SHIFT 0 +- +-/* RCC_LPTIM1CKSELR register fields */ +-#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +-#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 +- +-/* RCC_APB1RSTSETR register fields */ +-#define RCC_APB1RSTSETR_TIM2RST BIT(0) +-#define RCC_APB1RSTSETR_TIM3RST BIT(1) +-#define RCC_APB1RSTSETR_TIM4RST BIT(2) +-#define RCC_APB1RSTSETR_TIM5RST BIT(3) +-#define RCC_APB1RSTSETR_TIM6RST BIT(4) +-#define RCC_APB1RSTSETR_TIM7RST BIT(5) +-#define RCC_APB1RSTSETR_TIM12RST BIT(6) +-#define RCC_APB1RSTSETR_TIM13RST BIT(7) +-#define RCC_APB1RSTSETR_TIM14RST BIT(8) +-#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +-#define RCC_APB1RSTSETR_SPI2RST BIT(11) +-#define RCC_APB1RSTSETR_SPI3RST BIT(12) +-#define RCC_APB1RSTSETR_USART2RST BIT(14) +-#define RCC_APB1RSTSETR_USART3RST BIT(15) +-#define RCC_APB1RSTSETR_UART4RST BIT(16) +-#define RCC_APB1RSTSETR_UART5RST BIT(17) +-#define RCC_APB1RSTSETR_UART7RST BIT(18) +-#define RCC_APB1RSTSETR_UART8RST BIT(19) +-#define RCC_APB1RSTSETR_I2C1RST BIT(21) +-#define RCC_APB1RSTSETR_I2C2RST BIT(22) +-#define RCC_APB1RSTSETR_I2C3RST BIT(23) +-#define RCC_APB1RSTSETR_I2C5RST BIT(24) +-#define RCC_APB1RSTSETR_SPDIFRST BIT(26) +-#define RCC_APB1RSTSETR_CECRST BIT(27) +-#define RCC_APB1RSTSETR_DAC12RST BIT(29) +-#define RCC_APB1RSTSETR_MDIOSRST BIT(31) +- +-/* RCC_APB1RSTCLRR register fields */ +-#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +-#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +-#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +-#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +-#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +-#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +-#define RCC_APB1RSTCLRR_TIM12RST BIT(6) +-#define RCC_APB1RSTCLRR_TIM13RST BIT(7) +-#define RCC_APB1RSTCLRR_TIM14RST BIT(8) +-#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +-#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +-#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +-#define RCC_APB1RSTCLRR_USART2RST BIT(14) +-#define RCC_APB1RSTCLRR_USART3RST BIT(15) +-#define RCC_APB1RSTCLRR_UART4RST BIT(16) +-#define RCC_APB1RSTCLRR_UART5RST BIT(17) +-#define RCC_APB1RSTCLRR_UART7RST BIT(18) +-#define RCC_APB1RSTCLRR_UART8RST BIT(19) +-#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +-#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +-#define RCC_APB1RSTCLRR_I2C3RST BIT(23) +-#define RCC_APB1RSTCLRR_I2C5RST BIT(24) +-#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) +-#define RCC_APB1RSTCLRR_CECRST BIT(27) +-#define RCC_APB1RSTCLRR_DAC12RST BIT(29) +-#define RCC_APB1RSTCLRR_MDIOSRST BIT(31) +- +-/* RCC_APB2RSTSETR register fields */ +-#define RCC_APB2RSTSETR_TIM1RST BIT(0) +-#define RCC_APB2RSTSETR_TIM8RST BIT(1) +-#define RCC_APB2RSTSETR_TIM15RST BIT(2) +-#define RCC_APB2RSTSETR_TIM16RST BIT(3) +-#define RCC_APB2RSTSETR_TIM17RST BIT(4) +-#define RCC_APB2RSTSETR_SPI1RST BIT(8) +-#define RCC_APB2RSTSETR_SPI4RST BIT(9) +-#define RCC_APB2RSTSETR_SPI5RST BIT(10) +-#define RCC_APB2RSTSETR_USART6RST BIT(13) +-#define RCC_APB2RSTSETR_SAI1RST BIT(16) +-#define RCC_APB2RSTSETR_SAI2RST BIT(17) +-#define RCC_APB2RSTSETR_SAI3RST BIT(18) +-#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +-#define RCC_APB2RSTSETR_FDCANRST BIT(24) +- +-/* RCC_APB2RSTCLRR register fields */ +-#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +-#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +-#define RCC_APB2RSTCLRR_TIM15RST BIT(2) +-#define RCC_APB2RSTCLRR_TIM16RST BIT(3) +-#define RCC_APB2RSTCLRR_TIM17RST BIT(4) +-#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +-#define RCC_APB2RSTCLRR_SPI4RST BIT(9) +-#define RCC_APB2RSTCLRR_SPI5RST BIT(10) +-#define RCC_APB2RSTCLRR_USART6RST BIT(13) +-#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +-#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +-#define RCC_APB2RSTCLRR_SAI3RST BIT(18) +-#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +-#define RCC_APB2RSTCLRR_FDCANRST BIT(24) +- +-/* RCC_APB3RSTSETR register fields */ +-#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +-#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +-#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +-#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +-#define RCC_APB3RSTSETR_SAI4RST BIT(8) +-#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +-#define RCC_APB3RSTSETR_VREFRST BIT(13) +-#define RCC_APB3RSTSETR_TMPSENSRST BIT(16) +-#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) +- +-/* RCC_APB3RSTCLRR register fields */ +-#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +-#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +-#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +-#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +-#define RCC_APB3RSTCLRR_SAI4RST BIT(8) +-#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +-#define RCC_APB3RSTCLRR_VREFRST BIT(13) +-#define RCC_APB3RSTCLRR_TMPSENSRST BIT(16) +-#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) +- +-/* RCC_AHB2RSTSETR register fields */ +-#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +-#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +-#define RCC_AHB2RSTSETR_DMAMUXRST BIT(2) +-#define RCC_AHB2RSTSETR_ADC12RST BIT(5) +-#define RCC_AHB2RSTSETR_USBORST BIT(8) +-#define RCC_AHB2RSTSETR_SDMMC3RST BIT(16) +- +-/* RCC_AHB2RSTCLRR register fields */ +-#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +-#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +-#define RCC_AHB2RSTCLRR_DMAMUXRST BIT(2) +-#define RCC_AHB2RSTCLRR_ADC12RST BIT(5) +-#define RCC_AHB2RSTCLRR_USBORST BIT(8) +-#define RCC_AHB2RSTCLRR_SDMMC3RST BIT(16) +- +-/* RCC_AHB3RSTSETR register fields */ +-#define RCC_AHB3RSTSETR_DCMIRST BIT(0) +-#define RCC_AHB3RSTSETR_CRYP2RST BIT(4) +-#define RCC_AHB3RSTSETR_HASH2RST BIT(5) +-#define RCC_AHB3RSTSETR_RNG2RST BIT(6) +-#define RCC_AHB3RSTSETR_CRC2RST BIT(7) +-#define RCC_AHB3RSTSETR_HSEMRST BIT(11) +-#define RCC_AHB3RSTSETR_IPCCRST BIT(12) +- +-/* RCC_AHB3RSTCLRR register fields */ +-#define RCC_AHB3RSTCLRR_DCMIRST BIT(0) +-#define RCC_AHB3RSTCLRR_CRYP2RST BIT(4) +-#define RCC_AHB3RSTCLRR_HASH2RST BIT(5) +-#define RCC_AHB3RSTCLRR_RNG2RST BIT(6) +-#define RCC_AHB3RSTCLRR_CRC2RST BIT(7) +-#define RCC_AHB3RSTCLRR_HSEMRST BIT(11) +-#define RCC_AHB3RSTCLRR_IPCCRST BIT(12) +- +-/* RCC_AHB4RSTSETR register fields */ +-#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +-#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +-#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +-#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +-#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +-#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +-#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +-#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +-#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +-#define RCC_AHB4RSTSETR_GPIOJRST BIT(9) +-#define RCC_AHB4RSTSETR_GPIOKRST BIT(10) +- +-/* RCC_AHB4RSTCLRR register fields */ +-#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +-#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +-#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +-#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +-#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +-#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +-#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +-#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +-#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +-#define RCC_AHB4RSTCLRR_GPIOJRST BIT(9) +-#define RCC_AHB4RSTCLRR_GPIOKRST BIT(10) +- +-/* RCC_MP_APB1ENSETR register fields */ +-#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +-#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +-#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +-#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +-#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +-#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +-#define RCC_MP_APB1ENSETR_TIM12EN BIT(6) +-#define RCC_MP_APB1ENSETR_TIM13EN BIT(7) +-#define RCC_MP_APB1ENSETR_TIM14EN BIT(8) +-#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +-#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +-#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +-#define RCC_MP_APB1ENSETR_USART2EN BIT(14) +-#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +-#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +-#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +-#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +-#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +-#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +-#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +-#define RCC_MP_APB1ENSETR_I2C3EN BIT(23) +-#define RCC_MP_APB1ENSETR_I2C5EN BIT(24) +-#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) +-#define RCC_MP_APB1ENSETR_CECEN BIT(27) +-#define RCC_MP_APB1ENSETR_DAC12EN BIT(29) +-#define RCC_MP_APB1ENSETR_MDIOSEN BIT(31) +- +-/* RCC_MP_APB1ENCLRR register fields */ +-#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +-#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +-#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +-#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +-#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +-#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +-#define RCC_MP_APB1ENCLRR_TIM12EN BIT(6) +-#define RCC_MP_APB1ENCLRR_TIM13EN BIT(7) +-#define RCC_MP_APB1ENCLRR_TIM14EN BIT(8) +-#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +-#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +-#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +-#define RCC_MP_APB1ENCLRR_USART2EN BIT(14) +-#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +-#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +-#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +-#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +-#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +-#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +-#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +-#define RCC_MP_APB1ENCLRR_I2C3EN BIT(23) +-#define RCC_MP_APB1ENCLRR_I2C5EN BIT(24) +-#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) +-#define RCC_MP_APB1ENCLRR_CECEN BIT(27) +-#define RCC_MP_APB1ENCLRR_DAC12EN BIT(29) +-#define RCC_MP_APB1ENCLRR_MDIOSEN BIT(31) +- +-/* RCC_MP_APB2ENSETR register fields */ +-#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +-#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +-#define RCC_MP_APB2ENSETR_TIM15EN BIT(2) +-#define RCC_MP_APB2ENSETR_TIM16EN BIT(3) +-#define RCC_MP_APB2ENSETR_TIM17EN BIT(4) +-#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +-#define RCC_MP_APB2ENSETR_SPI4EN BIT(9) +-#define RCC_MP_APB2ENSETR_SPI5EN BIT(10) +-#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +-#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +-#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +-#define RCC_MP_APB2ENSETR_SAI3EN BIT(18) +-#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +-#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +-#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) +- +-/* RCC_MP_APB2ENCLRR register fields */ +-#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +-#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +-#define RCC_MP_APB2ENCLRR_TIM15EN BIT(2) +-#define RCC_MP_APB2ENCLRR_TIM16EN BIT(3) +-#define RCC_MP_APB2ENCLRR_TIM17EN BIT(4) +-#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +-#define RCC_MP_APB2ENCLRR_SPI4EN BIT(9) +-#define RCC_MP_APB2ENCLRR_SPI5EN BIT(10) +-#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +-#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +-#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +-#define RCC_MP_APB2ENCLRR_SAI3EN BIT(18) +-#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +-#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +-#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) +- +-/* RCC_MP_APB3ENSETR register fields */ +-#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +-#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +-#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +-#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +-#define RCC_MP_APB3ENSETR_SAI4EN BIT(8) +-#define RCC_MP_APB3ENSETR_SYSCFGEN BIT(11) +-#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +-#define RCC_MP_APB3ENSETR_TMPSENSEN BIT(16) +-#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +-#define RCC_MP_APB3ENSETR_HDPEN BIT(20) +- +-/* RCC_MP_APB3ENCLRR register fields */ +-#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +-#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +-#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +-#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +-#define RCC_MP_APB3ENCLRR_SAI4EN BIT(8) +-#define RCC_MP_APB3ENCLRR_SYSCFGEN BIT(11) +-#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +-#define RCC_MP_APB3ENCLRR_TMPSENSEN BIT(16) +-#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +-#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) +- +-/* RCC_MP_AHB2ENSETR register fields */ +-#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +-#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +-#define RCC_MP_AHB2ENSETR_DMAMUXEN BIT(2) +-#define RCC_MP_AHB2ENSETR_ADC12EN BIT(5) +-#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) +-#define RCC_MP_AHB2ENSETR_SDMMC3EN BIT(16) +- +-/* RCC_MP_AHB2ENCLRR register fields */ +-#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +-#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +-#define RCC_MP_AHB2ENCLRR_DMAMUXEN BIT(2) +-#define RCC_MP_AHB2ENCLRR_ADC12EN BIT(5) +-#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) +-#define RCC_MP_AHB2ENCLRR_SDMMC3EN BIT(16) +- +-/* RCC_MP_AHB3ENSETR register fields */ +-#define RCC_MP_AHB3ENSETR_DCMIEN BIT(0) +-#define RCC_MP_AHB3ENSETR_CRYP2EN BIT(4) +-#define RCC_MP_AHB3ENSETR_HASH2EN BIT(5) +-#define RCC_MP_AHB3ENSETR_RNG2EN BIT(6) +-#define RCC_MP_AHB3ENSETR_CRC2EN BIT(7) +-#define RCC_MP_AHB3ENSETR_HSEMEN BIT(11) +-#define RCC_MP_AHB3ENSETR_IPCCEN BIT(12) +- +-/* RCC_MP_AHB3ENCLRR register fields */ +-#define RCC_MP_AHB3ENCLRR_DCMIEN BIT(0) +-#define RCC_MP_AHB3ENCLRR_CRYP2EN BIT(4) +-#define RCC_MP_AHB3ENCLRR_HASH2EN BIT(5) +-#define RCC_MP_AHB3ENCLRR_RNG2EN BIT(6) +-#define RCC_MP_AHB3ENCLRR_CRC2EN BIT(7) +-#define RCC_MP_AHB3ENCLRR_HSEMEN BIT(11) +-#define RCC_MP_AHB3ENCLRR_IPCCEN BIT(12) +- +-/* RCC_MP_AHB4ENSETR register fields */ +-#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) +-#define RCC_MP_AHB4ENSETR_GPIOIEN BIT(8) +-#define RCC_MP_AHB4ENSETR_GPIOJEN BIT(9) +-#define RCC_MP_AHB4ENSETR_GPIOKEN BIT(10) +- +-/* RCC_MP_AHB4ENCLRR register fields */ +-#define RCC_MP_AHB4ENCLRR_GPIOAEN BIT(0) +-#define RCC_MP_AHB4ENCLRR_GPIOBEN BIT(1) +-#define RCC_MP_AHB4ENCLRR_GPIOCEN BIT(2) +-#define RCC_MP_AHB4ENCLRR_GPIODEN BIT(3) +-#define RCC_MP_AHB4ENCLRR_GPIOEEN BIT(4) +-#define RCC_MP_AHB4ENCLRR_GPIOFEN BIT(5) +-#define RCC_MP_AHB4ENCLRR_GPIOGEN BIT(6) +-#define RCC_MP_AHB4ENCLRR_GPIOHEN BIT(7) +-#define RCC_MP_AHB4ENCLRR_GPIOIEN BIT(8) +-#define RCC_MP_AHB4ENCLRR_GPIOJEN BIT(9) +-#define RCC_MP_AHB4ENCLRR_GPIOKEN BIT(10) +- +-/* RCC_MP_MLAHBENSETR register fields */ +-#define RCC_MP_MLAHBENSETR_RETRAMEN BIT(4) +- +-/* RCC_MP_MLAHBENCLRR register fields */ +-#define RCC_MP_MLAHBENCLRR_RETRAMEN BIT(4) +- +-/* RCC_MC_APB1ENSETR register fields */ +-#define RCC_MC_APB1ENSETR_TIM2EN BIT(0) +-#define RCC_MC_APB1ENSETR_TIM3EN BIT(1) +-#define RCC_MC_APB1ENSETR_TIM4EN BIT(2) +-#define RCC_MC_APB1ENSETR_TIM5EN BIT(3) +-#define RCC_MC_APB1ENSETR_TIM6EN BIT(4) +-#define RCC_MC_APB1ENSETR_TIM7EN BIT(5) +-#define RCC_MC_APB1ENSETR_TIM12EN BIT(6) +-#define RCC_MC_APB1ENSETR_TIM13EN BIT(7) +-#define RCC_MC_APB1ENSETR_TIM14EN BIT(8) +-#define RCC_MC_APB1ENSETR_LPTIM1EN BIT(9) +-#define RCC_MC_APB1ENSETR_SPI2EN BIT(11) +-#define RCC_MC_APB1ENSETR_SPI3EN BIT(12) +-#define RCC_MC_APB1ENSETR_USART2EN BIT(14) +-#define RCC_MC_APB1ENSETR_USART3EN BIT(15) +-#define RCC_MC_APB1ENSETR_UART4EN BIT(16) +-#define RCC_MC_APB1ENSETR_UART5EN BIT(17) +-#define RCC_MC_APB1ENSETR_UART7EN BIT(18) +-#define RCC_MC_APB1ENSETR_UART8EN BIT(19) +-#define RCC_MC_APB1ENSETR_I2C1EN BIT(21) +-#define RCC_MC_APB1ENSETR_I2C2EN BIT(22) +-#define RCC_MC_APB1ENSETR_I2C3EN BIT(23) +-#define RCC_MC_APB1ENSETR_I2C5EN BIT(24) +-#define RCC_MC_APB1ENSETR_SPDIFEN BIT(26) +-#define RCC_MC_APB1ENSETR_CECEN BIT(27) +-#define RCC_MC_APB1ENSETR_WWDG1EN BIT(28) +-#define RCC_MC_APB1ENSETR_DAC12EN BIT(29) +-#define RCC_MC_APB1ENSETR_MDIOSEN BIT(31) +- +-/* RCC_MC_APB1ENCLRR register fields */ +-#define RCC_MC_APB1ENCLRR_TIM2EN BIT(0) +-#define RCC_MC_APB1ENCLRR_TIM3EN BIT(1) +-#define RCC_MC_APB1ENCLRR_TIM4EN BIT(2) +-#define RCC_MC_APB1ENCLRR_TIM5EN BIT(3) +-#define RCC_MC_APB1ENCLRR_TIM6EN BIT(4) +-#define RCC_MC_APB1ENCLRR_TIM7EN BIT(5) +-#define RCC_MC_APB1ENCLRR_TIM12EN BIT(6) +-#define RCC_MC_APB1ENCLRR_TIM13EN BIT(7) +-#define RCC_MC_APB1ENCLRR_TIM14EN BIT(8) +-#define RCC_MC_APB1ENCLRR_LPTIM1EN BIT(9) +-#define RCC_MC_APB1ENCLRR_SPI2EN BIT(11) +-#define RCC_MC_APB1ENCLRR_SPI3EN BIT(12) +-#define RCC_MC_APB1ENCLRR_USART2EN BIT(14) +-#define RCC_MC_APB1ENCLRR_USART3EN BIT(15) +-#define RCC_MC_APB1ENCLRR_UART4EN BIT(16) +-#define RCC_MC_APB1ENCLRR_UART5EN BIT(17) +-#define RCC_MC_APB1ENCLRR_UART7EN BIT(18) +-#define RCC_MC_APB1ENCLRR_UART8EN BIT(19) +-#define RCC_MC_APB1ENCLRR_I2C1EN BIT(21) +-#define RCC_MC_APB1ENCLRR_I2C2EN BIT(22) +-#define RCC_MC_APB1ENCLRR_I2C3EN BIT(23) +-#define RCC_MC_APB1ENCLRR_I2C5EN BIT(24) +-#define RCC_MC_APB1ENCLRR_SPDIFEN BIT(26) +-#define RCC_MC_APB1ENCLRR_CECEN BIT(27) +-#define RCC_MC_APB1ENCLRR_DAC12EN BIT(29) +-#define RCC_MC_APB1ENCLRR_MDIOSEN BIT(31) +- +-/* RCC_MC_APB2ENSETR register fields */ +-#define RCC_MC_APB2ENSETR_TIM1EN BIT(0) +-#define RCC_MC_APB2ENSETR_TIM8EN BIT(1) +-#define RCC_MC_APB2ENSETR_TIM15EN BIT(2) +-#define RCC_MC_APB2ENSETR_TIM16EN BIT(3) +-#define RCC_MC_APB2ENSETR_TIM17EN BIT(4) +-#define RCC_MC_APB2ENSETR_SPI1EN BIT(8) +-#define RCC_MC_APB2ENSETR_SPI4EN BIT(9) +-#define RCC_MC_APB2ENSETR_SPI5EN BIT(10) +-#define RCC_MC_APB2ENSETR_USART6EN BIT(13) +-#define RCC_MC_APB2ENSETR_SAI1EN BIT(16) +-#define RCC_MC_APB2ENSETR_SAI2EN BIT(17) +-#define RCC_MC_APB2ENSETR_SAI3EN BIT(18) +-#define RCC_MC_APB2ENSETR_DFSDMEN BIT(20) +-#define RCC_MC_APB2ENSETR_ADFSDMEN BIT(21) +-#define RCC_MC_APB2ENSETR_FDCANEN BIT(24) +- +-/* RCC_MC_APB2ENCLRR register fields */ +-#define RCC_MC_APB2ENCLRR_TIM1EN BIT(0) +-#define RCC_MC_APB2ENCLRR_TIM8EN BIT(1) +-#define RCC_MC_APB2ENCLRR_TIM15EN BIT(2) +-#define RCC_MC_APB2ENCLRR_TIM16EN BIT(3) +-#define RCC_MC_APB2ENCLRR_TIM17EN BIT(4) +-#define RCC_MC_APB2ENCLRR_SPI1EN BIT(8) +-#define RCC_MC_APB2ENCLRR_SPI4EN BIT(9) +-#define RCC_MC_APB2ENCLRR_SPI5EN BIT(10) +-#define RCC_MC_APB2ENCLRR_USART6EN BIT(13) +-#define RCC_MC_APB2ENCLRR_SAI1EN BIT(16) +-#define RCC_MC_APB2ENCLRR_SAI2EN BIT(17) +-#define RCC_MC_APB2ENCLRR_SAI3EN BIT(18) +-#define RCC_MC_APB2ENCLRR_DFSDMEN BIT(20) +-#define RCC_MC_APB2ENCLRR_ADFSDMEN BIT(21) +-#define RCC_MC_APB2ENCLRR_FDCANEN BIT(24) +- +-/* RCC_MC_APB3ENSETR register fields */ +-#define RCC_MC_APB3ENSETR_LPTIM2EN BIT(0) +-#define RCC_MC_APB3ENSETR_LPTIM3EN BIT(1) +-#define RCC_MC_APB3ENSETR_LPTIM4EN BIT(2) +-#define RCC_MC_APB3ENSETR_LPTIM5EN BIT(3) +-#define RCC_MC_APB3ENSETR_SAI4EN BIT(8) +-#define RCC_MC_APB3ENSETR_SYSCFGEN BIT(11) +-#define RCC_MC_APB3ENSETR_VREFEN BIT(13) +-#define RCC_MC_APB3ENSETR_TMPSENSEN BIT(16) +-#define RCC_MC_APB3ENSETR_PMBCTRLEN BIT(17) +-#define RCC_MC_APB3ENSETR_HDPEN BIT(20) +- +-/* RCC_MC_APB3ENCLRR register fields */ +-#define RCC_MC_APB3ENCLRR_LPTIM2EN BIT(0) +-#define RCC_MC_APB3ENCLRR_LPTIM3EN BIT(1) +-#define RCC_MC_APB3ENCLRR_LPTIM4EN BIT(2) +-#define RCC_MC_APB3ENCLRR_LPTIM5EN BIT(3) +-#define RCC_MC_APB3ENCLRR_SAI4EN BIT(8) +-#define RCC_MC_APB3ENCLRR_SYSCFGEN BIT(11) +-#define RCC_MC_APB3ENCLRR_VREFEN BIT(13) +-#define RCC_MC_APB3ENCLRR_TMPSENSEN BIT(16) +-#define RCC_MC_APB3ENCLRR_PMBCTRLEN BIT(17) +-#define RCC_MC_APB3ENCLRR_HDPEN BIT(20) +- +-/* RCC_MC_AHB2ENSETR register fields */ +-#define RCC_MC_AHB2ENSETR_DMA1EN BIT(0) +-#define RCC_MC_AHB2ENSETR_DMA2EN BIT(1) +-#define RCC_MC_AHB2ENSETR_DMAMUXEN BIT(2) +-#define RCC_MC_AHB2ENSETR_ADC12EN BIT(5) +-#define RCC_MC_AHB2ENSETR_USBOEN BIT(8) +-#define RCC_MC_AHB2ENSETR_SDMMC3EN BIT(16) +- +-/* RCC_MC_AHB2ENCLRR register fields */ +-#define RCC_MC_AHB2ENCLRR_DMA1EN BIT(0) +-#define RCC_MC_AHB2ENCLRR_DMA2EN BIT(1) +-#define RCC_MC_AHB2ENCLRR_DMAMUXEN BIT(2) +-#define RCC_MC_AHB2ENCLRR_ADC12EN BIT(5) +-#define RCC_MC_AHB2ENCLRR_USBOEN BIT(8) +-#define RCC_MC_AHB2ENCLRR_SDMMC3EN BIT(16) +- +-/* RCC_MC_AHB3ENSETR register fields */ +-#define RCC_MC_AHB3ENSETR_DCMIEN BIT(0) +-#define RCC_MC_AHB3ENSETR_CRYP2EN BIT(4) +-#define RCC_MC_AHB3ENSETR_HASH2EN BIT(5) +-#define RCC_MC_AHB3ENSETR_RNG2EN BIT(6) +-#define RCC_MC_AHB3ENSETR_CRC2EN BIT(7) +-#define RCC_MC_AHB3ENSETR_HSEMEN BIT(11) +-#define RCC_MC_AHB3ENSETR_IPCCEN BIT(12) +- +-/* RCC_MC_AHB3ENCLRR register fields */ +-#define RCC_MC_AHB3ENCLRR_DCMIEN BIT(0) +-#define RCC_MC_AHB3ENCLRR_CRYP2EN BIT(4) +-#define RCC_MC_AHB3ENCLRR_HASH2EN BIT(5) +-#define RCC_MC_AHB3ENCLRR_RNG2EN BIT(6) +-#define RCC_MC_AHB3ENCLRR_CRC2EN BIT(7) +-#define RCC_MC_AHB3ENCLRR_HSEMEN BIT(11) +-#define RCC_MC_AHB3ENCLRR_IPCCEN BIT(12) +- +-/* RCC_MC_AHB4ENSETR register fields */ +-#define RCC_MC_AHB4ENSETR_GPIOAEN BIT(0) +-#define RCC_MC_AHB4ENSETR_GPIOBEN BIT(1) +-#define RCC_MC_AHB4ENSETR_GPIOCEN BIT(2) +-#define RCC_MC_AHB4ENSETR_GPIODEN BIT(3) +-#define RCC_MC_AHB4ENSETR_GPIOEEN BIT(4) +-#define RCC_MC_AHB4ENSETR_GPIOFEN BIT(5) +-#define RCC_MC_AHB4ENSETR_GPIOGEN BIT(6) +-#define RCC_MC_AHB4ENSETR_GPIOHEN BIT(7) +-#define RCC_MC_AHB4ENSETR_GPIOIEN BIT(8) +-#define RCC_MC_AHB4ENSETR_GPIOJEN BIT(9) +-#define RCC_MC_AHB4ENSETR_GPIOKEN BIT(10) +- +-/* RCC_MC_AHB4ENCLRR register fields */ +-#define RCC_MC_AHB4ENCLRR_GPIOAEN BIT(0) +-#define RCC_MC_AHB4ENCLRR_GPIOBEN BIT(1) +-#define RCC_MC_AHB4ENCLRR_GPIOCEN BIT(2) +-#define RCC_MC_AHB4ENCLRR_GPIODEN BIT(3) +-#define RCC_MC_AHB4ENCLRR_GPIOEEN BIT(4) +-#define RCC_MC_AHB4ENCLRR_GPIOFEN BIT(5) +-#define RCC_MC_AHB4ENCLRR_GPIOGEN BIT(6) +-#define RCC_MC_AHB4ENCLRR_GPIOHEN BIT(7) +-#define RCC_MC_AHB4ENCLRR_GPIOIEN BIT(8) +-#define RCC_MC_AHB4ENCLRR_GPIOJEN BIT(9) +-#define RCC_MC_AHB4ENCLRR_GPIOKEN BIT(10) +- +-/* RCC_MC_AXIMENSETR register fields */ +-#define RCC_MC_AXIMENSETR_SYSRAMEN BIT(0) +- +-/* RCC_MC_AXIMENCLRR register fields */ +-#define RCC_MC_AXIMENCLRR_SYSRAMEN BIT(0) +- +-/* RCC_MC_MLAHBENSETR register fields */ +-#define RCC_MC_MLAHBENSETR_RETRAMEN BIT(4) +- +-/* RCC_MC_MLAHBENCLRR register fields */ +-#define RCC_MC_MLAHBENCLRR_RETRAMEN BIT(4) +- +-/* RCC_MP_APB1LPENSETR register fields */ +-#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +-#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +-#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +-#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +-#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +-#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +-#define RCC_MP_APB1LPENSETR_TIM12LPEN BIT(6) +-#define RCC_MP_APB1LPENSETR_TIM13LPEN BIT(7) +-#define RCC_MP_APB1LPENSETR_TIM14LPEN BIT(8) +-#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +-#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +-#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +-#define RCC_MP_APB1LPENSETR_USART2LPEN BIT(14) +-#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +-#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +-#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +-#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +-#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +-#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +-#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +-#define RCC_MP_APB1LPENSETR_I2C3LPEN BIT(23) +-#define RCC_MP_APB1LPENSETR_I2C5LPEN BIT(24) +-#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) +-#define RCC_MP_APB1LPENSETR_CECLPEN BIT(27) +-#define RCC_MP_APB1LPENSETR_DAC12LPEN BIT(29) +-#define RCC_MP_APB1LPENSETR_MDIOSLPEN BIT(31) +- +-/* RCC_MP_APB1LPENCLRR register fields */ +-#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +-#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +-#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +-#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +-#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +-#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +-#define RCC_MP_APB1LPENCLRR_TIM12LPEN BIT(6) +-#define RCC_MP_APB1LPENCLRR_TIM13LPEN BIT(7) +-#define RCC_MP_APB1LPENCLRR_TIM14LPEN BIT(8) +-#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +-#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +-#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +-#define RCC_MP_APB1LPENCLRR_USART2LPEN BIT(14) +-#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +-#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +-#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +-#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +-#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +-#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +-#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +-#define RCC_MP_APB1LPENCLRR_I2C3LPEN BIT(23) +-#define RCC_MP_APB1LPENCLRR_I2C5LPEN BIT(24) +-#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) +-#define RCC_MP_APB1LPENCLRR_CECLPEN BIT(27) +-#define RCC_MP_APB1LPENCLRR_DAC12LPEN BIT(29) +-#define RCC_MP_APB1LPENCLRR_MDIOSLPEN BIT(31) +- +-/* RCC_MP_APB2LPENSETR register fields */ +-#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +-#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +-#define RCC_MP_APB2LPENSETR_TIM15LPEN BIT(2) +-#define RCC_MP_APB2LPENSETR_TIM16LPEN BIT(3) +-#define RCC_MP_APB2LPENSETR_TIM17LPEN BIT(4) +-#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +-#define RCC_MP_APB2LPENSETR_SPI4LPEN BIT(9) +-#define RCC_MP_APB2LPENSETR_SPI5LPEN BIT(10) +-#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +-#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +-#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +-#define RCC_MP_APB2LPENSETR_SAI3LPEN BIT(18) +-#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +-#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +-#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) +- +-/* RCC_MP_APB2LPENCLRR register fields */ +-#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +-#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +-#define RCC_MP_APB2LPENCLRR_TIM15LPEN BIT(2) +-#define RCC_MP_APB2LPENCLRR_TIM16LPEN BIT(3) +-#define RCC_MP_APB2LPENCLRR_TIM17LPEN BIT(4) +-#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +-#define RCC_MP_APB2LPENCLRR_SPI4LPEN BIT(9) +-#define RCC_MP_APB2LPENCLRR_SPI5LPEN BIT(10) +-#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +-#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +-#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +-#define RCC_MP_APB2LPENCLRR_SAI3LPEN BIT(18) +-#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +-#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +-#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) +- +-/* RCC_MP_APB3LPENSETR register fields */ +-#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +-#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +-#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +-#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +-#define RCC_MP_APB3LPENSETR_SAI4LPEN BIT(8) +-#define RCC_MP_APB3LPENSETR_SYSCFGLPEN BIT(11) +-#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +-#define RCC_MP_APB3LPENSETR_TMPSENSLPEN BIT(16) +-#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) +- +-/* RCC_MP_APB3LPENCLRR register fields */ +-#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +-#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +-#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +-#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +-#define RCC_MP_APB3LPENCLRR_SAI4LPEN BIT(8) +-#define RCC_MP_APB3LPENCLRR_SYSCFGLPEN BIT(11) +-#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +-#define RCC_MP_APB3LPENCLRR_TMPSENSLPEN BIT(16) +-#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) +- +-/* RCC_MP_AHB2LPENSETR register fields */ +-#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +-#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +-#define RCC_MP_AHB2LPENSETR_DMAMUXLPEN BIT(2) +-#define RCC_MP_AHB2LPENSETR_ADC12LPEN BIT(5) +-#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) +-#define RCC_MP_AHB2LPENSETR_SDMMC3LPEN BIT(16) +- +-/* RCC_MP_AHB2LPENCLRR register fields */ +-#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +-#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +-#define RCC_MP_AHB2LPENCLRR_DMAMUXLPEN BIT(2) +-#define RCC_MP_AHB2LPENCLRR_ADC12LPEN BIT(5) +-#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) +-#define RCC_MP_AHB2LPENCLRR_SDMMC3LPEN BIT(16) +- +-/* RCC_MP_AHB3LPENSETR register fields */ +-#define RCC_MP_AHB3LPENSETR_DCMILPEN BIT(0) +-#define RCC_MP_AHB3LPENSETR_CRYP2LPEN BIT(4) +-#define RCC_MP_AHB3LPENSETR_HASH2LPEN BIT(5) +-#define RCC_MP_AHB3LPENSETR_RNG2LPEN BIT(6) +-#define RCC_MP_AHB3LPENSETR_CRC2LPEN BIT(7) +-#define RCC_MP_AHB3LPENSETR_HSEMLPEN BIT(11) +-#define RCC_MP_AHB3LPENSETR_IPCCLPEN BIT(12) +- +-/* RCC_MP_AHB3LPENCLRR register fields */ +-#define RCC_MP_AHB3LPENCLRR_DCMILPEN BIT(0) +-#define RCC_MP_AHB3LPENCLRR_CRYP2LPEN BIT(4) +-#define RCC_MP_AHB3LPENCLRR_HASH2LPEN BIT(5) +-#define RCC_MP_AHB3LPENCLRR_RNG2LPEN BIT(6) +-#define RCC_MP_AHB3LPENCLRR_CRC2LPEN BIT(7) +-#define RCC_MP_AHB3LPENCLRR_HSEMLPEN BIT(11) +-#define RCC_MP_AHB3LPENCLRR_IPCCLPEN BIT(12) +- +-/* RCC_MP_AHB4LPENSETR register fields */ +-#define RCC_MP_AHB4LPENSETR_GPIOALPEN BIT(0) +-#define RCC_MP_AHB4LPENSETR_GPIOBLPEN BIT(1) +-#define RCC_MP_AHB4LPENSETR_GPIOCLPEN BIT(2) +-#define RCC_MP_AHB4LPENSETR_GPIODLPEN BIT(3) +-#define RCC_MP_AHB4LPENSETR_GPIOELPEN BIT(4) +-#define RCC_MP_AHB4LPENSETR_GPIOFLPEN BIT(5) +-#define RCC_MP_AHB4LPENSETR_GPIOGLPEN BIT(6) +-#define RCC_MP_AHB4LPENSETR_GPIOHLPEN BIT(7) +-#define RCC_MP_AHB4LPENSETR_GPIOILPEN BIT(8) +-#define RCC_MP_AHB4LPENSETR_GPIOJLPEN BIT(9) +-#define RCC_MP_AHB4LPENSETR_GPIOKLPEN BIT(10) +- +-/* RCC_MP_AHB4LPENCLRR register fields */ +-#define RCC_MP_AHB4LPENCLRR_GPIOALPEN BIT(0) +-#define RCC_MP_AHB4LPENCLRR_GPIOBLPEN BIT(1) +-#define RCC_MP_AHB4LPENCLRR_GPIOCLPEN BIT(2) +-#define RCC_MP_AHB4LPENCLRR_GPIODLPEN BIT(3) +-#define RCC_MP_AHB4LPENCLRR_GPIOELPEN BIT(4) +-#define RCC_MP_AHB4LPENCLRR_GPIOFLPEN BIT(5) +-#define RCC_MP_AHB4LPENCLRR_GPIOGLPEN BIT(6) +-#define RCC_MP_AHB4LPENCLRR_GPIOHLPEN BIT(7) +-#define RCC_MP_AHB4LPENCLRR_GPIOILPEN BIT(8) +-#define RCC_MP_AHB4LPENCLRR_GPIOJLPEN BIT(9) +-#define RCC_MP_AHB4LPENCLRR_GPIOKLPEN BIT(10) +- +-/* RCC_MP_AXIMLPENSETR register fields */ +-#define RCC_MP_AXIMLPENSETR_SYSRAMLPEN BIT(0) +- +-/* RCC_MP_AXIMLPENCLRR register fields */ +-#define RCC_MP_AXIMLPENCLRR_SYSRAMLPEN BIT(0) +- +-/* RCC_MP_MLAHBLPENSETR register fields */ +-#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +-#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +-#define RCC_MP_MLAHBLPENSETR_SRAM34LPEN BIT(2) +-#define RCC_MP_MLAHBLPENSETR_RETRAMLPEN BIT(4) +- +-/* RCC_MP_MLAHBLPENCLRR register fields */ +-#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +-#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +-#define RCC_MP_MLAHBLPENCLRR_SRAM34LPEN BIT(2) +-#define RCC_MP_MLAHBLPENCLRR_RETRAMLPEN BIT(4) +- +-/* RCC_MC_APB1LPENSETR register fields */ +-#define RCC_MC_APB1LPENSETR_TIM2LPEN BIT(0) +-#define RCC_MC_APB1LPENSETR_TIM3LPEN BIT(1) +-#define RCC_MC_APB1LPENSETR_TIM4LPEN BIT(2) +-#define RCC_MC_APB1LPENSETR_TIM5LPEN BIT(3) +-#define RCC_MC_APB1LPENSETR_TIM6LPEN BIT(4) +-#define RCC_MC_APB1LPENSETR_TIM7LPEN BIT(5) +-#define RCC_MC_APB1LPENSETR_TIM12LPEN BIT(6) +-#define RCC_MC_APB1LPENSETR_TIM13LPEN BIT(7) +-#define RCC_MC_APB1LPENSETR_TIM14LPEN BIT(8) +-#define RCC_MC_APB1LPENSETR_LPTIM1LPEN BIT(9) +-#define RCC_MC_APB1LPENSETR_SPI2LPEN BIT(11) +-#define RCC_MC_APB1LPENSETR_SPI3LPEN BIT(12) +-#define RCC_MC_APB1LPENSETR_USART2LPEN BIT(14) +-#define RCC_MC_APB1LPENSETR_USART3LPEN BIT(15) +-#define RCC_MC_APB1LPENSETR_UART4LPEN BIT(16) +-#define RCC_MC_APB1LPENSETR_UART5LPEN BIT(17) +-#define RCC_MC_APB1LPENSETR_UART7LPEN BIT(18) +-#define RCC_MC_APB1LPENSETR_UART8LPEN BIT(19) +-#define RCC_MC_APB1LPENSETR_I2C1LPEN BIT(21) +-#define RCC_MC_APB1LPENSETR_I2C2LPEN BIT(22) +-#define RCC_MC_APB1LPENSETR_I2C3LPEN BIT(23) +-#define RCC_MC_APB1LPENSETR_I2C5LPEN BIT(24) +-#define RCC_MC_APB1LPENSETR_SPDIFLPEN BIT(26) +-#define RCC_MC_APB1LPENSETR_CECLPEN BIT(27) +-#define RCC_MC_APB1LPENSETR_WWDG1LPEN BIT(28) +-#define RCC_MC_APB1LPENSETR_DAC12LPEN BIT(29) +-#define RCC_MC_APB1LPENSETR_MDIOSLPEN BIT(31) +- +-/* RCC_MC_APB1LPENCLRR register fields */ +-#define RCC_MC_APB1LPENCLRR_TIM2LPEN BIT(0) +-#define RCC_MC_APB1LPENCLRR_TIM3LPEN BIT(1) +-#define RCC_MC_APB1LPENCLRR_TIM4LPEN BIT(2) +-#define RCC_MC_APB1LPENCLRR_TIM5LPEN BIT(3) +-#define RCC_MC_APB1LPENCLRR_TIM6LPEN BIT(4) +-#define RCC_MC_APB1LPENCLRR_TIM7LPEN BIT(5) +-#define RCC_MC_APB1LPENCLRR_TIM12LPEN BIT(6) +-#define RCC_MC_APB1LPENCLRR_TIM13LPEN BIT(7) +-#define RCC_MC_APB1LPENCLRR_TIM14LPEN BIT(8) +-#define RCC_MC_APB1LPENCLRR_LPTIM1LPEN BIT(9) +-#define RCC_MC_APB1LPENCLRR_SPI2LPEN BIT(11) +-#define RCC_MC_APB1LPENCLRR_SPI3LPEN BIT(12) +-#define RCC_MC_APB1LPENCLRR_USART2LPEN BIT(14) +-#define RCC_MC_APB1LPENCLRR_USART3LPEN BIT(15) +-#define RCC_MC_APB1LPENCLRR_UART4LPEN BIT(16) +-#define RCC_MC_APB1LPENCLRR_UART5LPEN BIT(17) +-#define RCC_MC_APB1LPENCLRR_UART7LPEN BIT(18) +-#define RCC_MC_APB1LPENCLRR_UART8LPEN BIT(19) +-#define RCC_MC_APB1LPENCLRR_I2C1LPEN BIT(21) +-#define RCC_MC_APB1LPENCLRR_I2C2LPEN BIT(22) +-#define RCC_MC_APB1LPENCLRR_I2C3LPEN BIT(23) +-#define RCC_MC_APB1LPENCLRR_I2C5LPEN BIT(24) +-#define RCC_MC_APB1LPENCLRR_SPDIFLPEN BIT(26) +-#define RCC_MC_APB1LPENCLRR_CECLPEN BIT(27) +-#define RCC_MC_APB1LPENCLRR_WWDG1LPEN BIT(28) +-#define RCC_MC_APB1LPENCLRR_DAC12LPEN BIT(29) +-#define RCC_MC_APB1LPENCLRR_MDIOSLPEN BIT(31) +- +-/* RCC_MC_APB2LPENSETR register fields */ +-#define RCC_MC_APB2LPENSETR_TIM1LPEN BIT(0) +-#define RCC_MC_APB2LPENSETR_TIM8LPEN BIT(1) +-#define RCC_MC_APB2LPENSETR_TIM15LPEN BIT(2) +-#define RCC_MC_APB2LPENSETR_TIM16LPEN BIT(3) +-#define RCC_MC_APB2LPENSETR_TIM17LPEN BIT(4) +-#define RCC_MC_APB2LPENSETR_SPI1LPEN BIT(8) +-#define RCC_MC_APB2LPENSETR_SPI4LPEN BIT(9) +-#define RCC_MC_APB2LPENSETR_SPI5LPEN BIT(10) +-#define RCC_MC_APB2LPENSETR_USART6LPEN BIT(13) +-#define RCC_MC_APB2LPENSETR_SAI1LPEN BIT(16) +-#define RCC_MC_APB2LPENSETR_SAI2LPEN BIT(17) +-#define RCC_MC_APB2LPENSETR_SAI3LPEN BIT(18) +-#define RCC_MC_APB2LPENSETR_DFSDMLPEN BIT(20) +-#define RCC_MC_APB2LPENSETR_ADFSDMLPEN BIT(21) +-#define RCC_MC_APB2LPENSETR_FDCANLPEN BIT(24) +- +-/* RCC_MC_APB2LPENCLRR register fields */ +-#define RCC_MC_APB2LPENCLRR_TIM1LPEN BIT(0) +-#define RCC_MC_APB2LPENCLRR_TIM8LPEN BIT(1) +-#define RCC_MC_APB2LPENCLRR_TIM15LPEN BIT(2) +-#define RCC_MC_APB2LPENCLRR_TIM16LPEN BIT(3) +-#define RCC_MC_APB2LPENCLRR_TIM17LPEN BIT(4) +-#define RCC_MC_APB2LPENCLRR_SPI1LPEN BIT(8) +-#define RCC_MC_APB2LPENCLRR_SPI4LPEN BIT(9) +-#define RCC_MC_APB2LPENCLRR_SPI5LPEN BIT(10) +-#define RCC_MC_APB2LPENCLRR_USART6LPEN BIT(13) +-#define RCC_MC_APB2LPENCLRR_SAI1LPEN BIT(16) +-#define RCC_MC_APB2LPENCLRR_SAI2LPEN BIT(17) +-#define RCC_MC_APB2LPENCLRR_SAI3LPEN BIT(18) +-#define RCC_MC_APB2LPENCLRR_DFSDMLPEN BIT(20) +-#define RCC_MC_APB2LPENCLRR_ADFSDMLPEN BIT(21) +-#define RCC_MC_APB2LPENCLRR_FDCANLPEN BIT(24) +- +-/* RCC_MC_APB3LPENSETR register fields */ +-#define RCC_MC_APB3LPENSETR_LPTIM2LPEN BIT(0) +-#define RCC_MC_APB3LPENSETR_LPTIM3LPEN BIT(1) +-#define RCC_MC_APB3LPENSETR_LPTIM4LPEN BIT(2) +-#define RCC_MC_APB3LPENSETR_LPTIM5LPEN BIT(3) +-#define RCC_MC_APB3LPENSETR_SAI4LPEN BIT(8) +-#define RCC_MC_APB3LPENSETR_SYSCFGLPEN BIT(11) +-#define RCC_MC_APB3LPENSETR_VREFLPEN BIT(13) +-#define RCC_MC_APB3LPENSETR_TMPSENSLPEN BIT(16) +-#define RCC_MC_APB3LPENSETR_PMBCTRLLPEN BIT(17) +- +-/* RCC_MC_APB3LPENCLRR register fields */ +-#define RCC_MC_APB3LPENCLRR_LPTIM2LPEN BIT(0) +-#define RCC_MC_APB3LPENCLRR_LPTIM3LPEN BIT(1) +-#define RCC_MC_APB3LPENCLRR_LPTIM4LPEN BIT(2) +-#define RCC_MC_APB3LPENCLRR_LPTIM5LPEN BIT(3) +-#define RCC_MC_APB3LPENCLRR_SAI4LPEN BIT(8) +-#define RCC_MC_APB3LPENCLRR_SYSCFGLPEN BIT(11) +-#define RCC_MC_APB3LPENCLRR_VREFLPEN BIT(13) +-#define RCC_MC_APB3LPENCLRR_TMPSENSLPEN BIT(16) +-#define RCC_MC_APB3LPENCLRR_PMBCTRLLPEN BIT(17) +- +-/* RCC_MC_AHB2LPENSETR register fields */ +-#define RCC_MC_AHB2LPENSETR_DMA1LPEN BIT(0) +-#define RCC_MC_AHB2LPENSETR_DMA2LPEN BIT(1) +-#define RCC_MC_AHB2LPENSETR_DMAMUXLPEN BIT(2) +-#define RCC_MC_AHB2LPENSETR_ADC12LPEN BIT(5) +-#define RCC_MC_AHB2LPENSETR_USBOLPEN BIT(8) +-#define RCC_MC_AHB2LPENSETR_SDMMC3LPEN BIT(16) +- +-/* RCC_MC_AHB2LPENCLRR register fields */ +-#define RCC_MC_AHB2LPENCLRR_DMA1LPEN BIT(0) +-#define RCC_MC_AHB2LPENCLRR_DMA2LPEN BIT(1) +-#define RCC_MC_AHB2LPENCLRR_DMAMUXLPEN BIT(2) +-#define RCC_MC_AHB2LPENCLRR_ADC12LPEN BIT(5) +-#define RCC_MC_AHB2LPENCLRR_USBOLPEN BIT(8) +-#define RCC_MC_AHB2LPENCLRR_SDMMC3LPEN BIT(16) +- +-/* RCC_MC_AHB3LPENSETR register fields */ +-#define RCC_MC_AHB3LPENSETR_DCMILPEN BIT(0) +-#define RCC_MC_AHB3LPENSETR_CRYP2LPEN BIT(4) +-#define RCC_MC_AHB3LPENSETR_HASH2LPEN BIT(5) +-#define RCC_MC_AHB3LPENSETR_RNG2LPEN BIT(6) +-#define RCC_MC_AHB3LPENSETR_CRC2LPEN BIT(7) +-#define RCC_MC_AHB3LPENSETR_HSEMLPEN BIT(11) +-#define RCC_MC_AHB3LPENSETR_IPCCLPEN BIT(12) +- +-/* RCC_MC_AHB3LPENCLRR register fields */ +-#define RCC_MC_AHB3LPENCLRR_DCMILPEN BIT(0) +-#define RCC_MC_AHB3LPENCLRR_CRYP2LPEN BIT(4) +-#define RCC_MC_AHB3LPENCLRR_HASH2LPEN BIT(5) +-#define RCC_MC_AHB3LPENCLRR_RNG2LPEN BIT(6) +-#define RCC_MC_AHB3LPENCLRR_CRC2LPEN BIT(7) +-#define RCC_MC_AHB3LPENCLRR_HSEMLPEN BIT(11) +-#define RCC_MC_AHB3LPENCLRR_IPCCLPEN BIT(12) +- +-/* RCC_MC_AHB4LPENSETR register fields */ +-#define RCC_MC_AHB4LPENSETR_GPIOALPEN BIT(0) +-#define RCC_MC_AHB4LPENSETR_GPIOBLPEN BIT(1) +-#define RCC_MC_AHB4LPENSETR_GPIOCLPEN BIT(2) +-#define RCC_MC_AHB4LPENSETR_GPIODLPEN BIT(3) +-#define RCC_MC_AHB4LPENSETR_GPIOELPEN BIT(4) +-#define RCC_MC_AHB4LPENSETR_GPIOFLPEN BIT(5) +-#define RCC_MC_AHB4LPENSETR_GPIOGLPEN BIT(6) +-#define RCC_MC_AHB4LPENSETR_GPIOHLPEN BIT(7) +-#define RCC_MC_AHB4LPENSETR_GPIOILPEN BIT(8) +-#define RCC_MC_AHB4LPENSETR_GPIOJLPEN BIT(9) +-#define RCC_MC_AHB4LPENSETR_GPIOKLPEN BIT(10) +- +-/* RCC_MC_AHB4LPENCLRR register fields */ +-#define RCC_MC_AHB4LPENCLRR_GPIOALPEN BIT(0) +-#define RCC_MC_AHB4LPENCLRR_GPIOBLPEN BIT(1) +-#define RCC_MC_AHB4LPENCLRR_GPIOCLPEN BIT(2) +-#define RCC_MC_AHB4LPENCLRR_GPIODLPEN BIT(3) +-#define RCC_MC_AHB4LPENCLRR_GPIOELPEN BIT(4) +-#define RCC_MC_AHB4LPENCLRR_GPIOFLPEN BIT(5) +-#define RCC_MC_AHB4LPENCLRR_GPIOGLPEN BIT(6) +-#define RCC_MC_AHB4LPENCLRR_GPIOHLPEN BIT(7) +-#define RCC_MC_AHB4LPENCLRR_GPIOILPEN BIT(8) +-#define RCC_MC_AHB4LPENCLRR_GPIOJLPEN BIT(9) +-#define RCC_MC_AHB4LPENCLRR_GPIOKLPEN BIT(10) +- +-/* RCC_MC_AXIMLPENSETR register fields */ +-#define RCC_MC_AXIMLPENSETR_SYSRAMLPEN BIT(0) +- +-/* RCC_MC_AXIMLPENCLRR register fields */ +-#define RCC_MC_AXIMLPENCLRR_SYSRAMLPEN BIT(0) +- +-/* RCC_MC_MLAHBLPENSETR register fields */ +-#define RCC_MC_MLAHBLPENSETR_SRAM1LPEN BIT(0) +-#define RCC_MC_MLAHBLPENSETR_SRAM2LPEN BIT(1) +-#define RCC_MC_MLAHBLPENSETR_SRAM34LPEN BIT(2) +-#define RCC_MC_MLAHBLPENSETR_RETRAMLPEN BIT(4) +- +-/* RCC_MC_MLAHBLPENCLRR register fields */ +-#define RCC_MC_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +-#define RCC_MC_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +-#define RCC_MC_MLAHBLPENCLRR_SRAM34LPEN BIT(2) +-#define RCC_MC_MLAHBLPENCLRR_RETRAMLPEN BIT(4) +- +-/* RCC_MC_RSTSCLRR register fields */ +-#define RCC_MC_RSTSCLRR_PORRSTF BIT(0) +-#define RCC_MC_RSTSCLRR_BORRSTF BIT(1) +-#define RCC_MC_RSTSCLRR_PADRSTF BIT(2) +-#define RCC_MC_RSTSCLRR_HCSSRSTF BIT(3) +-#define RCC_MC_RSTSCLRR_VCORERSTF BIT(4) +-#define RCC_MC_RSTSCLRR_MCURSTF BIT(5) +-#define RCC_MC_RSTSCLRR_MPSYSRSTF BIT(6) +-#define RCC_MC_RSTSCLRR_MCSYSRSTF BIT(7) +-#define RCC_MC_RSTSCLRR_IWDG1RSTF BIT(8) +-#define RCC_MC_RSTSCLRR_IWDG2RSTF BIT(9) +-#define RCC_MC_RSTSCLRR_WWDG1RSTF BIT(10) +- +-/* RCC_MC_CIER register fields */ +-#define RCC_MC_CIER_LSIRDYIE BIT(0) +-#define RCC_MC_CIER_LSERDYIE BIT(1) +-#define RCC_MC_CIER_HSIRDYIE BIT(2) +-#define RCC_MC_CIER_HSERDYIE BIT(3) +-#define RCC_MC_CIER_CSIRDYIE BIT(4) +-#define RCC_MC_CIER_PLL1DYIE BIT(8) +-#define RCC_MC_CIER_PLL2DYIE BIT(9) +-#define RCC_MC_CIER_PLL3DYIE BIT(10) +-#define RCC_MC_CIER_PLL4DYIE BIT(11) +-#define RCC_MC_CIER_LSECSSIE BIT(16) +-#define RCC_MC_CIER_WKUPIE BIT(20) +- +-/* RCC_MC_CIFR register fields */ +-#define RCC_MC_CIFR_LSIRDYF BIT(0) +-#define RCC_MC_CIFR_LSERDYF BIT(1) +-#define RCC_MC_CIFR_HSIRDYF BIT(2) +-#define RCC_MC_CIFR_HSERDYF BIT(3) +-#define RCC_MC_CIFR_CSIRDYF BIT(4) +-#define RCC_MC_CIFR_PLL1DYF BIT(8) +-#define RCC_MC_CIFR_PLL2DYF BIT(9) +-#define RCC_MC_CIFR_PLL3DYF BIT(10) +-#define RCC_MC_CIFR_PLL4DYF BIT(11) +-#define RCC_MC_CIFR_LSECSSF BIT(16) +-#define RCC_MC_CIFR_WKUPF BIT(20) +- +-/* RCC_VERR register fields */ +-#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +-#define RCC_VERR_MINREV_SHIFT 0 +-#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +-#define RCC_VERR_MAJREV_SHIFT 4 +- +-/* 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) +- +-/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +-#define RCC_MP_ENCLRR_OFFSET U(4) +- +-/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +-#define RCC_RSTCLRR_OFFSET U(4) +- +-/* Used for most of DIVR register: max div for RTC */ +-#define RCC_DIVR_DIV_MASK GENMASK(5, 0) +-#define RCC_DIVR_DIVRDY BIT(31) +- +-/* Masks for specific DIVR registers */ +-#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 most of RCC_SELR registers */ +-#define RCC_SELR_SRC_MASK GENMASK(2, 0) +-#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) +-#define RCC_SELR_SRCRDY BIT(31) +- +-/* 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) +-#define RCC_PLLNCR_DIVEN_SHIFT 4 +- +-/* Used for all RCC_PLLCFGR1 registers */ +-#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) +-#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +-#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) +-#define RCC_PLLNCFGR1_DIVN_SHIFT 0 +- +-/* Only for PLL3 and PLL4 */ +-#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) +-#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 +- +-/* Used for all RCC_PLLCFGR2 registers */ +-#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) +-#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) +-#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +-#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) +-#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +-#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) +-#define RCC_PLLNCFGR2_DIVR_SHIFT 16 +- +-/* Used for all RCC_PLLFRACR registers */ +-#define RCC_PLLNFRACR_FRACV_SHIFT 3 +-#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) +-#define RCC_PLLNFRACR_FRACLE BIT(16) +- +-/* Used for all RCC_PLLCSGR registers */ +-#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +-#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) +-#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +-#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) +-#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +-#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) +- +-/* Used for TIMER Prescaler */ +-#define RCC_TIMGXPRER_TIMGXPRE BIT(0) +- +-/* Used for RCC_MCO related operations */ +-#define RCC_MCOCFG_MCOON BIT(12) +-#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) +-#define RCC_MCOCFG_MCODIV_SHIFT 4 +-#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) +- +-#endif /* STM32MP1_RCC_H */ ++#if STM32MP13 ++#include "stm32mp13_rcc.h" ++#endif ++#if STM32MP15 ++#include "stm32mp15_rcc.h" ++#endif +diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h +index c3329cc71..1af673706 100644 +--- a/include/drivers/st/stm32mp_clkfunc.h ++++ b/include/drivers/st/stm32mp_clkfunc.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,17 +14,28 @@ + #include + + int fdt_osc_read_freq(const char *name, uint32_t *freq); +-bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name); +-uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, ++bool fdt_clk_read_bool(const char *node_label, const char *prop_name); ++uint32_t fdt_clk_read_uint32_default(const char *node_label, + const char *prop_name, + uint32_t dflt_value); + + int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, + uint32_t *array); ++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); ++bool fdt_get_rcc_secure_state(void); ++int fdt_rcc_enable_it(const char *name); + + 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); ++ ++void stm32mp_stgen_config(unsigned long rate); ++void stm32mp_stgen_restore_rate(void); ++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_ddr.h b/include/drivers/st/stm32mp_ddr.h +new file mode 100644 +index 000000000..7f0f7cab9 +--- /dev/null ++++ b/include/drivers/st/stm32mp_ddr.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ ++#ifndef STM32MP_DDR_H ++#define STM32MP_DDR_H ++ ++#include ++ ++enum stm32mp_ddr_base_type { ++ DDR_BASE, ++ DDRPHY_BASE, ++ NONE_BASE ++}; ++ ++enum stm32mp_ddr_reg_type { ++ REG_REG, ++ REG_TIMING, ++ REG_PERF, ++ REG_MAP, ++ REGPHY_REG, ++ REGPHY_TIMING, ++ REG_TYPE_NB ++}; ++ ++struct stm32mp_ddr_reg_desc { ++ const char *name; ++ uint16_t offset; /* Offset for base address */ ++ uint8_t par_offset; /* Offset for parameter array */ ++}; ++ ++struct stm32mp_ddr_reg_info { ++ const char *name; ++ const struct stm32mp_ddr_reg_desc *desc; ++ uint8_t size; ++ enum stm32mp_ddr_base_type base; ++}; ++ ++struct stm32mp_ddr_size { ++ uint64_t base; ++ uint64_t size; ++}; ++ ++struct stm32mp_ddr_priv { ++ struct stm32mp_ddr_size info; ++ struct stm32mp_ddrctl *ctl; ++ struct stm32mp_ddrphy *phy; ++ uintptr_t pwr; ++ uintptr_t rcc; ++}; ++ ++struct stm32mp_ddr_info { ++ const char *name; ++ uint32_t speed; /* in kHZ */ ++ uint32_t size; /* Memory size in byte = col * row * width */ ++}; ++ ++#define TIMEOUT_US_1S 1000000U ++#define TIMEOUT_500US 500U ++ ++void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type, ++ const void *param, const struct stm32mp_ddr_reg_info *ddr_registers); ++void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl); ++int stm32mp_ddr_disable_axi_port(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_enable_host_interface(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_disable_host_interface(struct stm32mp_ddrctl *ctl); ++int stm32mp_ddr_sw_selfref_entry(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_sw_selfref_exit(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_set_qd3_update_conditions(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_unset_qd3_update_conditions(struct stm32mp_ddrctl *ctl); ++void stm32mp_ddr_wait_refresh_update_done_ack(struct stm32mp_ddrctl *ctl); ++int stm32mp_board_ddr_power_init(enum ddr_type ddr_type); ++ ++#endif /* STM32MP_DDR_H */ +diff --git a/include/drivers/st/stm32mp_ddr_test.h b/include/drivers/st/stm32mp_ddr_test.h +new file mode 100644 +index 000000000..fe4c8c08e +--- /dev/null ++++ b/include/drivers/st/stm32mp_ddr_test.h +@@ -0,0 +1,15 @@ ++/* ++ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP_DDR_TEST_H ++#define STM32MP_DDR_TEST_H ++ ++uint32_t stm32mp_ddr_test_rw_access(void); ++uint32_t stm32mp_ddr_test_data_bus(void); ++uint32_t stm32mp_ddr_test_addr_bus(uint64_t size); ++uint32_t stm32mp_ddr_check_size(void); ++ ++#endif /* STM32MP_DDR_TEST_H */ +diff --git a/include/drivers/st/stm32mp_ddrctrl_regs.h b/include/drivers/st/stm32mp_ddrctrl_regs.h +new file mode 100644 +index 000000000..d51082bd8 +--- /dev/null ++++ b/include/drivers/st/stm32mp_ddrctrl_regs.h +@@ -0,0 +1,270 @@ ++/* ++ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ ++#ifndef STM32MP_DDRCTRL_REGS_H ++#define STM32MP_DDRCTRL_REGS_H ++ ++#include ++#include ++ ++#include ++ ++/* DDR Controller (DDRCTRL) registers */ ++struct stm32mp_ddrctl { ++ uint32_t mstr ; /* 0x0 Master */ ++ uint32_t stat; /* 0x4 Operating Mode Status */ ++ uint8_t reserved008[0x10 - 0x8]; ++ uint32_t mrctrl0; /* 0x10 Control 0 */ ++ uint32_t mrctrl1; /* 0x14 Control 1 */ ++ uint32_t mrstat; /* 0x18 Status */ ++ uint32_t mrctrl2; /* 0x1c Control 2 */ ++ uint32_t derateen; /* 0x20 Temperature Derate Enable */ ++ uint32_t derateint; /* 0x24 Temperature Derate Interval */ ++ uint32_t reserved028; ++ uint32_t deratectl; /* 0x2c Temperature Derate Control */ ++ uint32_t pwrctl; /* 0x30 Low Power Control */ ++ uint32_t pwrtmg; /* 0x34 Low Power Timing */ ++ uint32_t hwlpctl; /* 0x38 Hardware Low Power Control */ ++ uint8_t reserved03c[0x50 - 0x3c]; ++ uint32_t rfshctl0; /* 0x50 Refresh Control 0 */ ++ uint32_t rfshctl1; /* 0x54 Refresh Control 1 */ ++ uint32_t reserved058; /* 0x58 Refresh Control 2 */ ++ uint32_t reserved05C; ++ uint32_t rfshctl3; /* 0x60 Refresh Control 0 */ ++ uint32_t rfshtmg; /* 0x64 Refresh Timing */ ++ uint32_t rfshtmg1; /* 0x68 Refresh Timing 1 */ ++ uint8_t reserved06c[0xc0 - 0x6c]; ++ uint32_t crcparctl0; /* 0xc0 CRC Parity Control0 */ ++ uint32_t crcparctl1; /* 0xc4 CRC Parity Control1 */ ++ uint32_t reserved0c8; /* 0xc8 CRC Parity Control2 */ ++ uint32_t crcparstat; /* 0xcc CRC Parity Status */ ++ uint32_t init0; /* 0xd0 SDRAM Initialization 0 */ ++ uint32_t init1; /* 0xd4 SDRAM Initialization 1 */ ++ uint32_t init2; /* 0xd8 SDRAM Initialization 2 */ ++ uint32_t init3; /* 0xdc SDRAM Initialization 3 */ ++ uint32_t init4; /* 0xe0 SDRAM Initialization 4 */ ++ uint32_t init5; /* 0xe4 SDRAM Initialization 5 */ ++ uint32_t init6; /* 0xe8 SDRAM Initialization 6 */ ++ uint32_t init7; /* 0xec SDRAM Initialization 7 */ ++ uint32_t dimmctl; /* 0xf0 DIMM Control */ ++ uint32_t rankctl; /* 0xf4 Rank Control */ ++ uint8_t reserved0f4[0x100 - 0xf8]; ++ uint32_t dramtmg0; /* 0x100 SDRAM Timing 0 */ ++ uint32_t dramtmg1; /* 0x104 SDRAM Timing 1 */ ++ uint32_t dramtmg2; /* 0x108 SDRAM Timing 2 */ ++ uint32_t dramtmg3; /* 0x10c SDRAM Timing 3 */ ++ uint32_t dramtmg4; /* 0x110 SDRAM Timing 4 */ ++ uint32_t dramtmg5; /* 0x114 SDRAM Timing 5 */ ++ uint32_t dramtmg6; /* 0x118 SDRAM Timing 6 */ ++ uint32_t dramtmg7; /* 0x11c SDRAM Timing 7 */ ++ uint32_t dramtmg8; /* 0x120 SDRAM Timing 8 */ ++ uint32_t dramtmg9; /* 0x124 SDRAM Timing 9 */ ++ uint32_t dramtmg10; /* 0x128 SDRAM Timing 10 */ ++ uint32_t dramtmg11; /* 0x12c SDRAM Timing 11 */ ++ uint32_t dramtmg12; /* 0x130 SDRAM Timing 12 */ ++ uint32_t dramtmg13; /* 0x134 SDRAM Timing 13 */ ++ uint32_t dramtmg14; /* 0x138 SDRAM Timing 14 */ ++ uint32_t dramtmg15; /* 0x13c SDRAM Timing 15 */ ++ uint8_t reserved140[0x180 - 0x140]; ++ uint32_t zqctl0; /* 0x180 ZQ Control 0 */ ++ uint32_t zqctl1; /* 0x184 ZQ Control 1 */ ++ uint32_t zqctl2; /* 0x188 ZQ Control 2 */ ++ uint32_t zqstat; /* 0x18c ZQ Status */ ++ uint32_t dfitmg0; /* 0x190 DFI Timing 0 */ ++ uint32_t dfitmg1; /* 0x194 DFI Timing 1 */ ++ uint32_t dfilpcfg0; /* 0x198 DFI Low Power Configuration 0 */ ++ uint32_t dfilpcfg1; /* 0x19c DFI Low Power Configuration 1 */ ++ uint32_t dfiupd0; /* 0x1a0 DFI Update 0 */ ++ uint32_t dfiupd1; /* 0x1a4 DFI Update 1 */ ++ uint32_t dfiupd2; /* 0x1a8 DFI Update 2 */ ++ uint32_t reserved1ac; ++ uint32_t dfimisc; /* 0x1b0 DFI Miscellaneous Control */ ++ uint32_t dfitmg2; /* 0x1b4 DFI Timing 2 */ ++ uint32_t dfitmg3; /* 0x1b8 DFI Timing 3 */ ++ uint32_t dfistat; /* 0x1bc DFI Status */ ++ uint32_t dbictl; /* 0x1c0 DM/DBI Control */ ++ uint32_t dfiphymstr; /* 0x1c4 DFI PHY Master interface */ ++ uint8_t reserved1c8[0x200 - 0x1c8]; ++ uint32_t addrmap0; /* 0x200 Address Map 0 */ ++ uint32_t addrmap1; /* 0x204 Address Map 1 */ ++ uint32_t addrmap2; /* 0x208 Address Map 2 */ ++ uint32_t addrmap3; /* 0x20c Address Map 3 */ ++ uint32_t addrmap4; /* 0x210 Address Map 4 */ ++ uint32_t addrmap5; /* 0x214 Address Map 5 */ ++ uint32_t addrmap6; /* 0x218 Address Map 6 */ ++ uint32_t addrmap7; /* 0x21c Address Map 7 */ ++ uint32_t addrmap8; /* 0x220 Address Map 8 */ ++ uint32_t addrmap9; /* 0x224 Address Map 9 */ ++ uint32_t addrmap10; /* 0x228 Address Map 10 */ ++ uint32_t addrmap11; /* 0x22C Address Map 11 */ ++ uint8_t reserved230[0x240 - 0x230]; ++ uint32_t odtcfg; /* 0x240 ODT Configuration */ ++ uint32_t odtmap; /* 0x244 ODT/Rank Map */ ++ uint8_t reserved248[0x250 - 0x248]; ++ uint32_t sched; /* 0x250 Scheduler Control */ ++ uint32_t sched1; /* 0x254 Scheduler Control 1 */ ++ uint32_t reserved258; ++ uint32_t perfhpr1; /* 0x25c High Priority Read CAM 1 */ ++ uint32_t reserved260; ++ uint32_t perflpr1; /* 0x264 Low Priority Read CAM 1 */ ++ uint32_t reserved268; ++ uint32_t perfwr1; /* 0x26c Write CAM 1 */ ++ uint8_t reserved27c[0x300 - 0x270]; ++ uint32_t dbg0; /* 0x300 Debug 0 */ ++ uint32_t dbg1; /* 0x304 Debug 1 */ ++ uint32_t dbgcam; /* 0x308 CAM Debug */ ++ uint32_t dbgcmd; /* 0x30c Command Debug */ ++ uint32_t dbgstat; /* 0x310 Status Debug */ ++ uint8_t reserved314[0x320 - 0x314]; ++ uint32_t swctl; /* 0x320 Software Programming Control Enable */ ++ uint32_t swstat; /* 0x324 Software Programming Control Status */ ++ uint8_t reserved328[0x36c - 0x328]; ++ uint32_t poisoncfg; /* 0x36c AXI Poison Configuration Register */ ++ uint32_t poisonstat; /* 0x370 AXI Poison Status Register */ ++ uint8_t reserved374[0x3f0 - 0x374]; ++ uint32_t deratestat; /* 0x3f0 Temperature Derate Status */ ++ uint8_t reserved3f4[0x3fc - 0x3f4]; ++ ++ /* Multi Port registers */ ++ uint32_t pstat; /* 0x3fc Port Status */ ++ uint32_t pccfg; /* 0x400 Port Common Configuration */ ++ ++ /* PORT 0 */ ++ uint32_t pcfgr_0; /* 0x404 Configuration Read */ ++ uint32_t pcfgw_0; /* 0x408 Configuration Write */ ++ uint8_t reserved40c[0x490 - 0x40c]; ++ uint32_t pctrl_0; /* 0x490 Port Control Register */ ++ uint32_t pcfgqos0_0; /* 0x494 Read QoS Configuration 0 */ ++ uint32_t pcfgqos1_0; /* 0x498 Read QoS Configuration 1 */ ++ uint32_t pcfgwqos0_0; /* 0x49c Write QoS Configuration 0 */ ++ uint32_t pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1 */ ++ uint8_t reserved4a4[0x4b4 - 0x4a4]; ++ ++#if STM32MP_DDR_DUAL_AXI_PORT ++ /* PORT 1 */ ++ uint32_t pcfgr_1; /* 0x4b4 Configuration Read */ ++ uint32_t pcfgw_1; /* 0x4b8 Configuration Write */ ++ uint8_t reserved4bc[0x540 - 0x4bc]; ++ uint32_t pctrl_1; /* 0x540 Port 2 Control Register */ ++ uint32_t pcfgqos0_1; /* 0x544 Read QoS Configuration 0 */ ++ uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */ ++ uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */ ++ uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */ ++#endif ++ ++ uint8_t reserved554[0xff0 - 0x554]; ++ uint32_t umctl2_ver_number; /* 0xff0 UMCTL2 Version Number */ ++} __packed; ++ ++/* DDR Controller registers offsets */ ++#define DDRCTRL_MSTR 0x000 ++#define DDRCTRL_STAT 0x004 ++#define DDRCTRL_MRCTRL0 0x010 ++#define DDRCTRL_MRSTAT 0x018 ++#define DDRCTRL_PWRCTL 0x030 ++#define DDRCTRL_PWRTMG 0x034 ++#define DDRCTRL_HWLPCTL 0x038 ++#define DDRCTRL_RFSHCTL3 0x060 ++#define DDRCTRL_RFSHTMG 0x064 ++#define DDRCTRL_INIT0 0x0D0 ++#define DDRCTRL_DFIMISC 0x1B0 ++#define DDRCTRL_DBG1 0x304 ++#define DDRCTRL_DBGCAM 0x308 ++#define DDRCTRL_DBGCMD 0x30C ++#define DDRCTRL_DBGSTAT 0x310 ++#define DDRCTRL_SWCTL 0x320 ++#define DDRCTRL_SWSTAT 0x324 ++#define DDRCTRL_PSTAT 0x3FC ++#define DDRCTRL_PCTRL_0 0x490 ++#if STM32MP_DDR_DUAL_AXI_PORT ++#define DDRCTRL_PCTRL_1 0x540 ++#endif ++ ++/* 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_DDR4 BIT(4) ++#define DDRCTRL_MSTR_LPDDR4 BIT(5) ++#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) ++#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER BIT(13) ++#define DDRCTRL_MSTR_DLL_OFF_MODE BIT(15) ++ ++#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0) ++#define DDRCTRL_STAT_OPERATING_MODE_NORMAL BIT(0) ++#define DDRCTRL_STAT_OPERATING_MODE_SR (BIT(0) | BIT(1)) ++#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4) ++#define DDRCTRL_STAT_SELFREF_TYPE_ASR (BIT(4) | BIT(5)) ++#define DDRCTRL_STAT_SELFREF_TYPE_SR BIT(5) ++ ++#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE U(0) ++/* Only one rank supported */ ++#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 ++#define DDRCTRL_MRCTRL0_MR_RANK_ALL \ ++ 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) ++ ++#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0) ++ ++#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0) ++#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1) ++#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) ++#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) ++ ++#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16) ++#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) ++ ++#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) ++#define DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL BIT(1) ++ ++#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0) ++ ++#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16) ++#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 ++ ++#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK(31, 30) ++#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL BIT(30) ++ ++#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) ++#define DDRCTRL_DFIMISC_DFI_INIT_START BIT(5) ++ ++#define DDRCTRL_DFISTAT_DFI_INIT_COMPLETE BIT(0) ++ ++#define DDRCTRL_DBG1_DIS_HIF BIT(1) ++ ++#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) ++#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) ++#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) ++#define DDRCTRL_DBGCAM_DBG_RD_Q_EMPTY BIT(25) ++#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) ++#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) ++#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ ++ (DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ ++ DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) ++#define DDRCTRL_DBG_Q_AND_DATA_PIPELINE_EMPTY \ ++ (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ ++ DDRCTRL_DBGCAM_DBG_RD_Q_EMPTY | \ ++ DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) ++#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ ++ (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ ++ DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ ++ DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) ++ ++#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) ++ ++#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) ++ ++#define DDRCTRL_SWCTL_SW_DONE BIT(0) ++ ++#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) ++ ++#define DDRCTRL_PCTRL_N_PORT_EN BIT(0) ++ ++#endif /* STM32MP_DDRCTRL_REGS_H */ +diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h +index 984cd6014..5059cb424 100644 +--- a/include/drivers/st/stm32mp_pmic.h ++++ b/include/drivers/st/stm32mp_pmic.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -19,14 +19,6 @@ + */ + int dt_pmic_status(void); + +-/* +- * dt_pmic_configure_boot_on_regulators - Configure boot-on and always-on +- * regulators from device tree configuration +- * +- * Returns 0 on success, and negative values on errors +- */ +-int dt_pmic_configure_boot_on_regulators(void); +- + /* + * initialize_pmic_i2c - Initialize I2C for the PMIC control + * +@@ -41,6 +33,14 @@ bool initialize_pmic_i2c(void); + */ + void initialize_pmic(void); + ++#if DEBUG ++void print_pmic_info_and_debug(void); ++#else ++static inline void print_pmic_info_and_debug(void) ++{ ++} ++#endif ++ + /* + * pmic_ddr_power_init - Initialize regulators required for DDR + * +@@ -48,4 +48,18 @@ void initialize_pmic(void); + */ + int pmic_ddr_power_init(enum ddr_type ddr_type); + ++/* ++ * pmic_voltages_init - Update voltages for platform init ++ * ++ * Returns 0 on success, and negative values on errors ++ */ ++int pmic_voltages_init(void); ++ ++/* ++ * pmic_switch_off - switch off the platform with PMIC ++ * ++ * Panics on errors ++ */ ++void pmic_switch_off(void); ++ + #endif /* STM32MP_PMIC_H */ +diff --git a/include/drivers/st/stm32mp_ram.h b/include/drivers/st/stm32mp_ram.h +new file mode 100644 +index 000000000..43f0c2020 +--- /dev/null ++++ b/include/drivers/st/stm32mp_ram.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++#ifndef STM32MP_RAM_H ++#define STM32MP_RAM_H ++ ++#include ++ ++#include ++ ++#define PARAM(x, y) \ ++ { \ ++ .name = x, \ ++ .offset = offsetof(struct stm32mp_ddr_config, y), \ ++ .size = sizeof(config.y) / sizeof(uint32_t), \ ++ } ++ ++#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) ++#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) ++ ++struct stm32mp_ddr_param { ++ const char *name; /* Name in DT */ ++ const uint32_t offset; /* Offset in config struct */ ++ const uint32_t size; /* Size of parameters */ ++}; ++ ++int stm32mp_ddr_dt_get_info(void *fdt, int node, struct stm32mp_ddr_info *info); ++int stm32mp_ddr_dt_get_param(void *fdt, int node, const struct stm32mp_ddr_param *param, ++ uint32_t param_size, uintptr_t config); ++ ++#endif /* STM32MP_RAM_H */ +diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h +index 84448050d..8c43c0b5b 100644 +--- a/include/drivers/st/stm32mp_reset.h ++++ b/include/drivers/st/stm32mp_reset.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 + */ +@@ -47,4 +47,16 @@ static inline void stm32mp_reset_release(uint32_t reset_id) + (void)stm32mp_reset_deassert(reset_id, 0U); + } + ++/* ++ * Manage reset control for the MCU reset ++ * ++ * @assert_not_deassert: reset requested state ++ */ ++void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert); ++ ++/* ++ * Manage system reset control ++ */ ++void __dead2 stm32mp_system_reset(void); ++ + #endif /* STM32MP_RESET_H */ +diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h +index dc096cd1a..193e673c7 100644 +--- a/include/drivers/st/stpmic1.h ++++ b/include/drivers/st/stpmic1.h +@@ -103,6 +103,22 @@ + #define BUCK4_PULL_DOWN_SHIFT 6 + #define VREF_DDR_PULL_DOWN_SHIFT 4 + ++/* ICC register */ ++#define BUCK1_ICC_SHIFT 0 ++#define BUCK2_ICC_SHIFT 1 ++#define BUCK3_ICC_SHIFT 2 ++#define BUCK4_ICC_SHIFT 3 ++#define PWR_SW1_ICC_SHIFT 4 ++#define PWR_SW2_ICC_SHIFT 5 ++#define BOOST_ICC_SHIFT 6 ++ ++#define LDO1_ICC_SHIFT 0 ++#define LDO2_ICC_SHIFT 1 ++#define LDO3_ICC_SHIFT 2 ++#define LDO4_ICC_SHIFT 3 ++#define LDO5_ICC_SHIFT 4 ++#define LDO6_ICC_SHIFT 5 ++ + /* Buck Mask reset register */ + #define BUCK1_MASK_RESET 0 + #define BUCK2_MASK_RESET 1 +@@ -118,6 +134,10 @@ + #define LDO6_MASK_RESET 5 + #define VREF_DDR_MASK_RESET 6 + ++/* LDO3 Special modes */ ++#define LDO3_BYPASS BIT(7) ++#define LDO3_DDR_SEL 31U ++ + /* Main PMIC Control Register (MAIN_CONTROL_REG) */ + #define ICC_EVENT_ENABLED BIT(4) + #define PWRCTRL_POLARITY_HIGH BIT(3) +@@ -145,9 +165,12 @@ + /* USB Control Register */ + #define BOOST_OVP_DISABLED BIT(7) + #define VBUS_OTG_DETECTION_DISABLED BIT(6) ++#define SW_OUT_DISCHARGE BIT(5) ++#define VBUS_OTG_DISCHARGE BIT(4) + #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 +179,21 @@ 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_levels_mv(const char *name, const uint16_t **levels, ++ size_t *levels_count); + 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_regulator_icc_set(const char *name); ++int stpmic1_regulator_sink_mode_set(const char *name); ++int stpmic1_regulator_bypass_mode_set(const char *name); ++int stpmic1_active_discharge_mode_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); +diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h +index 67e66b23f..b2fa90f1b 100644 +--- a/include/dt-bindings/clock/stm32mp1-clks.h ++++ b/include/dt-bindings/clock/stm32mp1-clks.h +@@ -4,275 +4,9 @@ + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +-#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ +-#define _DT_BINDINGS_STM32MP1_CLKS_H_ +- +-/* OSCILLATOR clocks */ +-#define CK_HSE 0 +-#define CK_CSI 1 +-#define CK_LSI 2 +-#define CK_LSE 3 +-#define CK_HSI 4 +-#define CK_HSE_DIV2 5 +- +-/* Bus clocks */ +-#define TIM2 6 +-#define TIM3 7 +-#define TIM4 8 +-#define TIM5 9 +-#define TIM6 10 +-#define TIM7 11 +-#define TIM12 12 +-#define TIM13 13 +-#define TIM14 14 +-#define LPTIM1 15 +-#define SPI2 16 +-#define SPI3 17 +-#define USART2 18 +-#define USART3 19 +-#define UART4 20 +-#define UART5 21 +-#define UART7 22 +-#define UART8 23 +-#define I2C1 24 +-#define I2C2 25 +-#define I2C3 26 +-#define I2C5 27 +-#define SPDIF 28 +-#define CEC 29 +-#define DAC12 30 +-#define MDIO 31 +-#define TIM1 32 +-#define TIM8 33 +-#define TIM15 34 +-#define TIM16 35 +-#define TIM17 36 +-#define SPI1 37 +-#define SPI4 38 +-#define SPI5 39 +-#define USART6 40 +-#define SAI1 41 +-#define SAI2 42 +-#define SAI3 43 +-#define DFSDM 44 +-#define FDCAN 45 +-#define LPTIM2 46 +-#define LPTIM3 47 +-#define LPTIM4 48 +-#define LPTIM5 49 +-#define SAI4 50 +-#define SYSCFG 51 +-#define VREF 52 +-#define TMPSENS 53 +-#define PMBCTRL 54 +-#define HDP 55 +-#define LTDC 56 +-#define DSI 57 +-#define IWDG2 58 +-#define USBPHY 59 +-#define STGENRO 60 +-#define SPI6 61 +-#define I2C4 62 +-#define I2C6 63 +-#define USART1 64 +-#define RTCAPB 65 +-#define TZC1 66 +-#define TZPC 67 +-#define IWDG1 68 +-#define BSEC 69 +-#define STGEN 70 +-#define DMA1 71 +-#define DMA2 72 +-#define DMAMUX 73 +-#define ADC12 74 +-#define USBO 75 +-#define SDMMC3 76 +-#define DCMI 77 +-#define CRYP2 78 +-#define HASH2 79 +-#define RNG2 80 +-#define CRC2 81 +-#define HSEM 82 +-#define IPCC 83 +-#define GPIOA 84 +-#define GPIOB 85 +-#define GPIOC 86 +-#define GPIOD 87 +-#define GPIOE 88 +-#define GPIOF 89 +-#define GPIOG 90 +-#define GPIOH 91 +-#define GPIOI 92 +-#define GPIOJ 93 +-#define GPIOK 94 +-#define GPIOZ 95 +-#define CRYP1 96 +-#define HASH1 97 +-#define RNG1 98 +-#define BKPSRAM 99 +-#define MDMA 100 +-#define GPU 101 +-#define ETHCK 102 +-#define ETHTX 103 +-#define ETHRX 104 +-#define ETHMAC 105 +-#define FMC 106 +-#define QSPI 107 +-#define SDMMC1 108 +-#define SDMMC2 109 +-#define CRC1 110 +-#define USBH 111 +-#define ETHSTP 112 +-#define TZC2 113 +- +-/* Kernel clocks */ +-#define SDMMC1_K 118 +-#define SDMMC2_K 119 +-#define SDMMC3_K 120 +-#define FMC_K 121 +-#define QSPI_K 122 +-#define ETHCK_K 123 +-#define RNG1_K 124 +-#define RNG2_K 125 +-#define GPU_K 126 +-#define USBPHY_K 127 +-#define STGEN_K 128 +-#define SPDIF_K 129 +-#define SPI1_K 130 +-#define SPI2_K 131 +-#define SPI3_K 132 +-#define SPI4_K 133 +-#define SPI5_K 134 +-#define SPI6_K 135 +-#define CEC_K 136 +-#define I2C1_K 137 +-#define I2C2_K 138 +-#define I2C3_K 139 +-#define I2C4_K 140 +-#define I2C5_K 141 +-#define I2C6_K 142 +-#define LPTIM1_K 143 +-#define LPTIM2_K 144 +-#define LPTIM3_K 145 +-#define LPTIM4_K 146 +-#define LPTIM5_K 147 +-#define USART1_K 148 +-#define USART2_K 149 +-#define USART3_K 150 +-#define UART4_K 151 +-#define UART5_K 152 +-#define USART6_K 153 +-#define UART7_K 154 +-#define UART8_K 155 +-#define DFSDM_K 156 +-#define FDCAN_K 157 +-#define SAI1_K 158 +-#define SAI2_K 159 +-#define SAI3_K 160 +-#define SAI4_K 161 +-#define ADC12_K 162 +-#define DSI_K 163 +-#define DSI_PX 164 +-#define ADFSDM_K 165 +-#define USBO_K 166 +-#define LTDC_PX 167 +-#define DAC12_K 168 +-#define ETHPTP_K 169 +- +-/* PLL */ +-#define PLL1 176 +-#define PLL2 177 +-#define PLL3 178 +-#define PLL4 179 +- +-/* ODF */ +-#define PLL1_P 180 +-#define PLL1_Q 181 +-#define PLL1_R 182 +-#define PLL2_P 183 +-#define PLL2_Q 184 +-#define PLL2_R 185 +-#define PLL3_P 186 +-#define PLL3_Q 187 +-#define PLL3_R 188 +-#define PLL4_P 189 +-#define PLL4_Q 190 +-#define PLL4_R 191 +- +-/* AUX */ +-#define RTC 192 +- +-/* MCLK */ +-#define CK_PER 193 +-#define CK_MPU 194 +-#define CK_AXI 195 +-#define CK_MCU 196 +- +-/* Time base */ +-#define TIM2_K 197 +-#define TIM3_K 198 +-#define TIM4_K 199 +-#define TIM5_K 200 +-#define TIM6_K 201 +-#define TIM7_K 202 +-#define TIM12_K 203 +-#define TIM13_K 204 +-#define TIM14_K 205 +-#define TIM1_K 206 +-#define TIM8_K 207 +-#define TIM15_K 208 +-#define TIM16_K 209 +-#define TIM17_K 210 +- +-/* MCO clocks */ +-#define CK_MCO1 211 +-#define CK_MCO2 212 +- +-/* TRACE & DEBUG clocks */ +-#define CK_DBG 214 +-#define CK_TRACE 215 +- +-/* DDR */ +-#define DDRC1 220 +-#define DDRC1LP 221 +-#define DDRC2 222 +-#define DDRC2LP 223 +-#define DDRPHYC 224 +-#define DDRPHYCLP 225 +-#define DDRCAPB 226 +-#define DDRCAPBLP 227 +-#define AXIDCG 228 +-#define DDRPHYCAPB 229 +-#define DDRPHYCAPBLP 230 +-#define DDRPERFM 231 +- +-#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 +- +-#define CK_SCMI1_PLL3_Q 0 +-#define CK_SCMI1_PLL3_R 1 +-#define CK_SCMI1_MCU 2 +- +-#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ ++#if STM32MP13 ++#include "stm32mp13-clks.h" ++#endif ++#if STM32MP15 ++#include "stm32mp15-clks.h" ++#endif +diff --git a/include/dt-bindings/clock/stm32mp1-clksrc.h b/include/dt-bindings/clock/stm32mp1-clksrc.h +index 818f4b768..70ecf1063 100644 +--- a/include/dt-bindings/clock/stm32mp1-clksrc.h ++++ b/include/dt-bindings/clock/stm32mp1-clksrc.h +@@ -1,283 +1,11 @@ + /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ + /* +- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved ++ * Copyright (C) 2017-2020, STMicroelectronics - All Rights Reserved + */ + +-#ifndef _DT_BINDINGS_CLOCK_STM32MP1_CLKSRC_H_ +-#define _DT_BINDINGS_CLOCK_STM32MP1_CLKSRC_H_ +- +-/* PLL output is enable when x=1, with x=p,q or r */ +-#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) +- +-/* st,clksrc: mandatory clock source */ +- +-#define CLK_MPU_HSI 0x00000200 +-#define CLK_MPU_HSE 0x00000201 +-#define CLK_MPU_PLL1P 0x00000202 +-#define CLK_MPU_PLL1P_DIV 0x00000203 +- +-#define CLK_AXI_HSI 0x00000240 +-#define CLK_AXI_HSE 0x00000241 +-#define CLK_AXI_PLL2P 0x00000242 +- +-#define CLK_MCU_HSI 0x00000480 +-#define CLK_MCU_HSE 0x00000481 +-#define CLK_MCU_CSI 0x00000482 +-#define CLK_MCU_PLL3P 0x00000483 +- +-#define CLK_PLL12_HSI 0x00000280 +-#define CLK_PLL12_HSE 0x00000281 +- +-#define CLK_PLL3_HSI 0x00008200 +-#define CLK_PLL3_HSE 0x00008201 +-#define CLK_PLL3_CSI 0x00008202 +- +-#define CLK_PLL4_HSI 0x00008240 +-#define CLK_PLL4_HSE 0x00008241 +-#define CLK_PLL4_CSI 0x00008242 +-#define CLK_PLL4_I2SCKIN 0x00008243 +- +-#define CLK_RTC_DISABLED 0x00001400 +-#define CLK_RTC_LSE 0x00001401 +-#define CLK_RTC_LSI 0x00001402 +-#define CLK_RTC_HSE 0x00001403 +- +-#define CLK_MCO1_HSI 0x00008000 +-#define CLK_MCO1_HSE 0x00008001 +-#define CLK_MCO1_CSI 0x00008002 +-#define CLK_MCO1_LSI 0x00008003 +-#define CLK_MCO1_LSE 0x00008004 +-#define CLK_MCO1_DISABLED 0x0000800F +- +-#define CLK_MCO2_MPU 0x00008040 +-#define CLK_MCO2_AXI 0x00008041 +-#define CLK_MCO2_MCU 0x00008042 +-#define CLK_MCO2_PLL4P 0x00008043 +-#define CLK_MCO2_HSE 0x00008044 +-#define CLK_MCO2_HSI 0x00008045 +-#define CLK_MCO2_DISABLED 0x0000804F +- +-/* st,pkcs: peripheral kernel clock source */ +- +-#define CLK_I2C12_PCLK1 0x00008C00 +-#define CLK_I2C12_PLL4R 0x00008C01 +-#define CLK_I2C12_HSI 0x00008C02 +-#define CLK_I2C12_CSI 0x00008C03 +-#define CLK_I2C12_DISABLED 0x00008C07 +- +-#define CLK_I2C35_PCLK1 0x00008C40 +-#define CLK_I2C35_PLL4R 0x00008C41 +-#define CLK_I2C35_HSI 0x00008C42 +-#define CLK_I2C35_CSI 0x00008C43 +-#define CLK_I2C35_DISABLED 0x00008C47 +- +-#define CLK_I2C46_PCLK5 0x00000C00 +-#define CLK_I2C46_PLL3Q 0x00000C01 +-#define CLK_I2C46_HSI 0x00000C02 +-#define CLK_I2C46_CSI 0x00000C03 +-#define CLK_I2C46_DISABLED 0x00000C07 +- +-#define CLK_SAI1_PLL4Q 0x00008C80 +-#define CLK_SAI1_PLL3Q 0x00008C81 +-#define CLK_SAI1_I2SCKIN 0x00008C82 +-#define CLK_SAI1_CKPER 0x00008C83 +-#define CLK_SAI1_PLL3R 0x00008C84 +-#define CLK_SAI1_DISABLED 0x00008C87 +- +-#define CLK_SAI2_PLL4Q 0x00008CC0 +-#define CLK_SAI2_PLL3Q 0x00008CC1 +-#define CLK_SAI2_I2SCKIN 0x00008CC2 +-#define CLK_SAI2_CKPER 0x00008CC3 +-#define CLK_SAI2_SPDIF 0x00008CC4 +-#define CLK_SAI2_PLL3R 0x00008CC5 +-#define CLK_SAI2_DISABLED 0x00008CC7 +- +-#define CLK_SAI3_PLL4Q 0x00008D00 +-#define CLK_SAI3_PLL3Q 0x00008D01 +-#define CLK_SAI3_I2SCKIN 0x00008D02 +-#define CLK_SAI3_CKPER 0x00008D03 +-#define CLK_SAI3_PLL3R 0x00008D04 +-#define CLK_SAI3_DISABLED 0x00008D07 +- +-#define CLK_SAI4_PLL4Q 0x00008D40 +-#define CLK_SAI4_PLL3Q 0x00008D41 +-#define CLK_SAI4_I2SCKIN 0x00008D42 +-#define CLK_SAI4_CKPER 0x00008D43 +-#define CLK_SAI4_PLL3R 0x00008D44 +-#define CLK_SAI4_DISABLED 0x00008D47 +- +-#define CLK_SPI2S1_PLL4P 0x00008D80 +-#define CLK_SPI2S1_PLL3Q 0x00008D81 +-#define CLK_SPI2S1_I2SCKIN 0x00008D82 +-#define CLK_SPI2S1_CKPER 0x00008D83 +-#define CLK_SPI2S1_PLL3R 0x00008D84 +-#define CLK_SPI2S1_DISABLED 0x00008D87 +- +-#define CLK_SPI2S23_PLL4P 0x00008DC0 +-#define CLK_SPI2S23_PLL3Q 0x00008DC1 +-#define CLK_SPI2S23_I2SCKIN 0x00008DC2 +-#define CLK_SPI2S23_CKPER 0x00008DC3 +-#define CLK_SPI2S23_PLL3R 0x00008DC4 +-#define CLK_SPI2S23_DISABLED 0x00008DC7 +- +-#define CLK_SPI45_PCLK2 0x00008E00 +-#define CLK_SPI45_PLL4Q 0x00008E01 +-#define CLK_SPI45_HSI 0x00008E02 +-#define CLK_SPI45_CSI 0x00008E03 +-#define CLK_SPI45_HSE 0x00008E04 +-#define CLK_SPI45_DISABLED 0x00008E07 +- +-#define CLK_SPI6_PCLK5 0x00000C40 +-#define CLK_SPI6_PLL4Q 0x00000C41 +-#define CLK_SPI6_HSI 0x00000C42 +-#define CLK_SPI6_CSI 0x00000C43 +-#define CLK_SPI6_HSE 0x00000C44 +-#define CLK_SPI6_PLL3Q 0x00000C45 +-#define CLK_SPI6_DISABLED 0x00000C47 +- +-#define CLK_UART6_PCLK2 0x00008E40 +-#define CLK_UART6_PLL4Q 0x00008E41 +-#define CLK_UART6_HSI 0x00008E42 +-#define CLK_UART6_CSI 0x00008E43 +-#define CLK_UART6_HSE 0x00008E44 +-#define CLK_UART6_DISABLED 0x00008E47 +- +-#define CLK_UART24_PCLK1 0x00008E80 +-#define CLK_UART24_PLL4Q 0x00008E81 +-#define CLK_UART24_HSI 0x00008E82 +-#define CLK_UART24_CSI 0x00008E83 +-#define CLK_UART24_HSE 0x00008E84 +-#define CLK_UART24_DISABLED 0x00008E87 +- +-#define CLK_UART35_PCLK1 0x00008EC0 +-#define CLK_UART35_PLL4Q 0x00008EC1 +-#define CLK_UART35_HSI 0x00008EC2 +-#define CLK_UART35_CSI 0x00008EC3 +-#define CLK_UART35_HSE 0x00008EC4 +-#define CLK_UART35_DISABLED 0x00008EC7 +- +-#define CLK_UART78_PCLK1 0x00008F00 +-#define CLK_UART78_PLL4Q 0x00008F01 +-#define CLK_UART78_HSI 0x00008F02 +-#define CLK_UART78_CSI 0x00008F03 +-#define CLK_UART78_HSE 0x00008F04 +-#define CLK_UART78_DISABLED 0x00008F07 +- +-#define CLK_UART1_PCLK5 0x00000C80 +-#define CLK_UART1_PLL3Q 0x00000C81 +-#define CLK_UART1_HSI 0x00000C82 +-#define CLK_UART1_CSI 0x00000C83 +-#define CLK_UART1_PLL4Q 0x00000C84 +-#define CLK_UART1_HSE 0x00000C85 +-#define CLK_UART1_DISABLED 0x00000C87 +- +-#define CLK_SDMMC12_HCLK6 0x00008F40 +-#define CLK_SDMMC12_PLL3R 0x00008F41 +-#define CLK_SDMMC12_PLL4P 0x00008F42 +-#define CLK_SDMMC12_HSI 0x00008F43 +-#define CLK_SDMMC12_DISABLED 0x00008F47 +- +-#define CLK_SDMMC3_HCLK2 0x00008F80 +-#define CLK_SDMMC3_PLL3R 0x00008F81 +-#define CLK_SDMMC3_PLL4P 0x00008F82 +-#define CLK_SDMMC3_HSI 0x00008F83 +-#define CLK_SDMMC3_DISABLED 0x00008F87 +- +-#define CLK_ETH_PLL4P 0x00008FC0 +-#define CLK_ETH_PLL3Q 0x00008FC1 +-#define CLK_ETH_DISABLED 0x00008FC3 +- +-#define CLK_QSPI_ACLK 0x00009000 +-#define CLK_QSPI_PLL3R 0x00009001 +-#define CLK_QSPI_PLL4P 0x00009002 +-#define CLK_QSPI_CKPER 0x00009003 +- +-#define CLK_FMC_ACLK 0x00009040 +-#define CLK_FMC_PLL3R 0x00009041 +-#define CLK_FMC_PLL4P 0x00009042 +-#define CLK_FMC_CKPER 0x00009043 +- +-#define CLK_FDCAN_HSE 0x000090C0 +-#define CLK_FDCAN_PLL3Q 0x000090C1 +-#define CLK_FDCAN_PLL4Q 0x000090C2 +-#define CLK_FDCAN_PLL4R 0x000090C3 +- +-#define CLK_SPDIF_PLL4P 0x00009140 +-#define CLK_SPDIF_PLL3Q 0x00009141 +-#define CLK_SPDIF_HSI 0x00009142 +-#define CLK_SPDIF_DISABLED 0x00009143 +- +-#define CLK_CEC_LSE 0x00009180 +-#define CLK_CEC_LSI 0x00009181 +-#define CLK_CEC_CSI_DIV122 0x00009182 +-#define CLK_CEC_DISABLED 0x00009183 +- +-#define CLK_USBPHY_HSE 0x000091C0 +-#define CLK_USBPHY_PLL4R 0x000091C1 +-#define CLK_USBPHY_HSE_DIV2 0x000091C2 +-#define CLK_USBPHY_DISABLED 0x000091C3 +- +-#define CLK_USBO_PLL4R 0x800091C0 +-#define CLK_USBO_USBPHY 0x800091C1 +- +-#define CLK_RNG1_CSI 0x00000CC0 +-#define CLK_RNG1_PLL4R 0x00000CC1 +-#define CLK_RNG1_LSE 0x00000CC2 +-#define CLK_RNG1_LSI 0x00000CC3 +- +-#define CLK_RNG2_CSI 0x00009200 +-#define CLK_RNG2_PLL4R 0x00009201 +-#define CLK_RNG2_LSE 0x00009202 +-#define CLK_RNG2_LSI 0x00009203 +- +-#define CLK_CKPER_HSI 0x00000D00 +-#define CLK_CKPER_CSI 0x00000D01 +-#define CLK_CKPER_HSE 0x00000D02 +-#define CLK_CKPER_DISABLED 0x00000D03 +- +-#define CLK_STGEN_HSI 0x00000D40 +-#define CLK_STGEN_HSE 0x00000D41 +-#define CLK_STGEN_DISABLED 0x00000D43 +- +-#define CLK_DSI_DSIPLL 0x00009240 +-#define CLK_DSI_PLL4P 0x00009241 +- +-#define CLK_ADC_PLL4R 0x00009280 +-#define CLK_ADC_CKPER 0x00009281 +-#define CLK_ADC_PLL3Q 0x00009282 +-#define CLK_ADC_DISABLED 0x00009283 +- +-#define CLK_LPTIM45_PCLK3 0x000092C0 +-#define CLK_LPTIM45_PLL4P 0x000092C1 +-#define CLK_LPTIM45_PLL3Q 0x000092C2 +-#define CLK_LPTIM45_LSE 0x000092C3 +-#define CLK_LPTIM45_LSI 0x000092C4 +-#define CLK_LPTIM45_CKPER 0x000092C5 +-#define CLK_LPTIM45_DISABLED 0x000092C7 +- +-#define CLK_LPTIM23_PCLK3 0x00009300 +-#define CLK_LPTIM23_PLL4Q 0x00009301 +-#define CLK_LPTIM23_CKPER 0x00009302 +-#define CLK_LPTIM23_LSE 0x00009303 +-#define CLK_LPTIM23_LSI 0x00009304 +-#define CLK_LPTIM23_DISABLED 0x00009307 +- +-#define CLK_LPTIM1_PCLK1 0x00009340 +-#define CLK_LPTIM1_PLL4P 0x00009341 +-#define CLK_LPTIM1_PLL3Q 0x00009342 +-#define CLK_LPTIM1_LSE 0x00009343 +-#define CLK_LPTIM1_LSI 0x00009344 +-#define CLK_LPTIM1_CKPER 0x00009345 +-#define CLK_LPTIM1_DISABLED 0x00009347 +- +-/* define for st,pll /csg */ +-#define SSCG_MODE_CENTER_SPREAD 0 +-#define SSCG_MODE_DOWN_SPREAD 1 +- +-/* define for st,drive */ +-#define LSEDRV_LOWEST 0 +-#define LSEDRV_MEDIUM_LOW 1 +-#define LSEDRV_MEDIUM_HIGH 2 +-#define LSEDRV_HIGHEST 3 +- ++#if STM32MP13 ++#include "stm32mp13-clksrc.h" ++#endif ++#if STM32MP15 ++#include "stm32mp15-clksrc.h" + #endif +diff --git a/include/dt-bindings/clock/stm32mp13-clks.h b/include/dt-bindings/clock/stm32mp13-clks.h +new file mode 100644 +index 000000000..446cbd109 +--- /dev/null ++++ b/include/dt-bindings/clock/stm32mp13-clks.h +@@ -0,0 +1,230 @@ ++/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ ++/* ++ * Copyright (C) STMicroelectronics 2020 - All Rights Reserved ++ * Author: Gabriel Fernandez for STMicroelectronics. ++ */ ++ ++#ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ ++#define _DT_BINDINGS_STM32MP13_CLKS_H_ ++ ++/* OSCILLATOR clocks */ ++#define CK_HSE 0 ++#define CK_CSI 1 ++#define CK_LSI 2 ++#define CK_LSE 3 ++#define CK_HSI 4 ++#define CK_HSE_DIV2 5 ++ ++/* PLL */ ++#define PLL1 6 ++#define PLL2 7 ++#define PLL3 8 ++#define PLL4 9 ++ ++/* ODF */ ++#define PLL1_P 10 ++#define PLL1_Q 11 ++#define PLL1_R 12 ++#define PLL2_P 13 ++#define PLL2_Q 14 ++#define PLL2_R 15 ++#define PLL3_P 16 ++#define PLL3_Q 17 ++#define PLL3_R 18 ++#define PLL4_P 19 ++#define PLL4_Q 20 ++#define PLL4_R 21 ++ ++#define PCLK1 22 ++#define PCLK2 23 ++#define PCLK3 24 ++#define PCLK4 25 ++#define PCLK5 26 ++#define PCLK6 27 ++ ++/* SYSTEM CLOCK */ ++#define CK_PER 28 ++#define CK_MPU 29 ++#define CK_AXI 30 ++#define CK_MLAHB 31 ++ ++/* BASE TIMER */ ++#define CK_TIMG1 32 ++#define CK_TIMG2 33 ++#define CK_TIMG3 34 ++ ++/* AUX */ ++#define RTC 35 ++ ++/* TRACE & DEBUG clocks */ ++#define CK_DBG 36 ++#define CK_TRACE 37 ++ ++/* MCO clocks */ ++#define CK_MCO1 38 ++#define CK_MCO2 39 ++ ++/* IP clocks */ ++#define SYSCFG 40 ++#define VREF 41 ++#define TMPSENS 42 ++#define PMBCTRL 43 ++#define HDP 44 ++#define IWDG2 45 ++#define STGENRO 46 ++#define USART1 47 ++#define RTCAPB 48 ++#define TZC 49 ++#define TZPC 50 ++#define IWDG1 51 ++#define BSEC 52 ++#define DMA1 53 ++#define DMA2 54 ++#define DMAMUX1 55 ++#define DMAMUX2 56 ++#define GPIOA 57 ++#define GPIOB 58 ++#define GPIOC 59 ++#define GPIOD 60 ++#define GPIOE 61 ++#define GPIOF 62 ++#define GPIOG 63 ++#define GPIOH 64 ++#define GPIOI 65 ++#define CRYP1 66 ++#define HASH1 67 ++#define BKPSRAM 68 ++#define MDMA 69 ++#define CRC1 70 ++#define USBH 71 ++#define DMA3 72 ++#define TSC 73 ++#define PKA 74 ++#define AXIMC 75 ++#define MCE 76 ++#define ETH1TX 77 ++#define ETH2TX 78 ++#define ETH1RX 79 ++#define ETH2RX 80 ++#define ETH1MAC 81 ++#define ETH2MAC 82 ++#define ETH1STP 83 ++#define ETH2STP 84 ++ ++/* IP clocks with parents */ ++#define SDMMC1_K 85 ++#define SDMMC2_K 86 ++#define ADC1_K 87 ++#define ADC2_K 88 ++#define FMC_K 89 ++#define QSPI_K 90 ++#define RNG1_K 91 ++#define USBPHY_K 92 ++#define STGEN_K 93 ++#define SPDIF_K 94 ++#define SPI1_K 95 ++#define SPI2_K 96 ++#define SPI3_K 97 ++#define SPI4_K 98 ++#define SPI5_K 99 ++#define I2C1_K 100 ++#define I2C2_K 101 ++#define I2C3_K 102 ++#define I2C4_K 103 ++#define I2C5_K 104 ++#define TIM2_K 105 ++#define TIM3_K 106 ++#define TIM4_K 107 ++#define TIM5_K 108 ++#define TIM6_K 109 ++#define TIM7_K 110 ++#define TIM12_K 111 ++#define TIM13_K 112 ++#define TIM14_K 113 ++#define TIM1_K 114 ++#define TIM8_K 115 ++#define TIM15_K 116 ++#define TIM16_K 117 ++#define TIM17_K 118 ++#define LPTIM1_K 119 ++#define LPTIM2_K 120 ++#define LPTIM3_K 121 ++#define LPTIM4_K 122 ++#define LPTIM5_K 123 ++#define USART1_K 124 ++#define USART2_K 125 ++#define USART3_K 126 ++#define UART4_K 127 ++#define UART5_K 128 ++#define USART6_K 129 ++#define UART7_K 130 ++#define UART8_K 131 ++#define DFSDM_K 132 ++#define FDCAN_K 133 ++#define SAI1_K 134 ++#define SAI2_K 135 ++#define ADFSDM_K 136 ++#define USBO_K 137 ++#define LTDC_PX 138 ++#define ETH1CK_K 139 ++#define ETH1PTP_K 140 ++#define ETH2CK_K 141 ++#define ETH2PTP_K 142 ++#define DCMIPP_K 143 ++#define SAES_K 144 ++#define DTS_K 145 ++ ++/* DDR */ ++#define DDRC1 146 ++#define DDRC1LP 147 ++#define DDRC2 148 ++#define DDRC2LP 149 ++#define DDRPHYC 150 ++#define DDRPHYCLP 151 ++#define DDRCAPB 152 ++#define DDRCAPBLP 153 ++#define AXIDCG 154 ++#define DDRPHYCAPB 155 ++#define DDRPHYCAPBLP 156 ++#define DDRPERFM 157 ++ ++#define ADC1 158 ++#define ADC2 159 ++#define SAI1 160 ++#define SAI2 161 ++ ++#define STM32MP1_LAST_CLK 162 ++ ++/* 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_HSE_DIV2 5 ++#define CK_SCMI0_PLL2_Q 6 ++#define CK_SCMI0_PLL2_R 7 ++#define CK_SCMI0_PLL3_P 8 ++#define CK_SCMI0_PLL3_Q 9 ++#define CK_SCMI0_PLL3_R 10 ++#define CK_SCMI0_PLL4_P 11 ++#define CK_SCMI0_PLL4_Q 12 ++#define CK_SCMI0_PLL4_R 13 ++#define CK_SCMI0_MPU 14 ++#define CK_SCMI0_AXI 15 ++#define CK_SCMI0_MLAHB 16 ++#define CK_SCMI0_CKPER 17 ++#define CK_SCMI0_PCLK1 18 ++#define CK_SCMI0_PCLK2 19 ++#define CK_SCMI0_PCLK3 20 ++#define CK_SCMI0_PCLK4 21 ++#define CK_SCMI0_PCLK5 22 ++#define CK_SCMI0_PCLK6 23 ++#define CK_SCMI0_CKTIMG1 24 ++#define CK_SCMI0_CKTIMG2 25 ++#define CK_SCMI0_CKTIMG3 26 ++#define CK_SCMI0_RTC 27 ++#define CK_SCMI0_RTCAPB 28 ++#define CK_SCMI0_BSEC 29 ++ ++#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ +diff --git a/include/dt-bindings/clock/stm32mp13-clksrc.h b/include/dt-bindings/clock/stm32mp13-clksrc.h +new file mode 100644 +index 000000000..20ec78863 +--- /dev/null ++++ b/include/dt-bindings/clock/stm32mp13-clksrc.h +@@ -0,0 +1,394 @@ ++/* ++ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++ */ ++ ++#ifndef _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ ++#define _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ ++ ++#define CMD_DIV 0 ++#define CMD_MUX 1 ++#define CMD_CLK 2 ++#define CMD_RESERVED1 3 ++ ++#define CMD_SHIFT 26 ++#define CMD_MASK 0xFC000000 ++#define CMD_DATA_MASK 0x03FFFFFF ++ ++#define DIV_ID_SHIFT 8 ++#define DIV_ID_MASK 0x0000FF00 ++ ++#define DIV_DIVN_SHIFT 0 ++#define DIV_DIVN_MASK 0x000000FF ++ ++#define MUX_ID_SHIFT 4 ++#define MUX_ID_MASK 0x00000FF0 ++ ++#define MUX_SEL_SHIFT 0 ++#define MUX_SEL_MASK 0x0000000F ++ ++#define CLK_ID_MASK GENMASK_32(19, 11) ++#define CLK_ID_SHIFT 11 ++#define CLK_ON_MASK 0x00000400 ++#define CLK_ON_SHIFT 10 ++#define CLK_DIV_MASK GENMASK_32(9, 4) ++#define CLK_DIV_SHIFT 4 ++#define CLK_SEL_MASK GENMASK_32(3, 0) ++#define CLK_SEL_SHIFT 0 ++ ++#define DIV_PLL1DIVP 0 ++#define DIV_PLL2DIVP 1 ++#define DIV_PLL2DIVQ 2 ++#define DIV_PLL2DIVR 3 ++#define DIV_PLL3DIVP 4 ++#define DIV_PLL3DIVQ 5 ++#define DIV_PLL3DIVR 6 ++#define DIV_PLL4DIVP 7 ++#define DIV_PLL4DIVQ 8 ++#define DIV_PLL4DIVR 9 ++#define DIV_MPU 10 ++#define DIV_AXI 11 ++#define DIV_MLAHB 12 ++#define DIV_APB1 13 ++#define DIV_APB2 14 ++#define DIV_APB3 15 ++#define DIV_APB4 16 ++#define DIV_APB5 17 ++#define DIV_APB6 18 ++#define DIV_RTC 19 ++#define DIV_MCO1 20 ++#define DIV_MCO2 21 ++#define DIV_HSI 22 ++#define DIV_TRACE 23 ++#define DIV_ETH1PTP 24 ++#define DIV_ETH2PTP 25 ++#define DIV_MAX 26 ++ ++#define DIV(div_id, div) ((CMD_DIV << CMD_SHIFT) |\ ++ ((div_id) << DIV_ID_SHIFT |\ ++ (div))) ++ ++#define CLKSRC(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\ ++ ((mux_id) << MUX_ID_SHIFT |\ ++ (sel))) ++ ++/* MCO output is enable */ ++#define MCO_SRC(mco_id, sel) ((CMD_CLK << CMD_SHIFT) |\ ++ (((mco_id) << CLK_ID_SHIFT) |\ ++ (sel)) | CLK_ON_MASK) ++ ++#define MCO_DISABLED(mco_id) ((CMD_CLK << CMD_SHIFT) |\ ++ ((mco_id) << CLK_ID_SHIFT)) ++ ++/* CLK output is enable */ ++#define CLK_SRC(clk_id, sel) ((CMD_CLK << CMD_SHIFT) |\ ++ (((clk_id) << CLK_ID_SHIFT) |\ ++ (sel)) | CLK_ON_MASK) ++ ++#define CLK_DISABLED(clk_id) ((CMD_CLK << CMD_SHIFT) |\ ++ ((clk_id) << CLK_ID_SHIFT)) ++ ++#define MUX_MPU 0 ++#define MUX_AXI 1 ++#define MUX_MLAHB 2 ++#define MUX_PLL12 3 ++#define MUX_PLL3 4 ++#define MUX_PLL4 5 ++#define MUX_RTC 6 ++#define MUX_MCO1 7 ++#define MUX_MCO2 8 ++#define MUX_CKPER 9 ++#define MUX_KERNEL_BEGIN 10 ++#define MUX_ADC1 10 ++#define MUX_ADC2 11 ++#define MUX_DCMIPP 12 ++#define MUX_ETH1 13 ++#define MUX_ETH2 14 ++#define MUX_FDCAN 15 ++#define MUX_FMC 16 ++#define MUX_I2C12 17 ++#define MUX_I2C3 18 ++#define MUX_I2C4 19 ++#define MUX_I2C5 20 ++#define MUX_LPTIM1 21 ++#define MUX_LPTIM2 22 ++#define MUX_LPTIM3 23 ++#define MUX_LPTIM45 24 ++#define MUX_QSPI 25 ++#define MUX_RNG1 26 ++#define MUX_SAES 27 ++#define MUX_SAI1 28 ++#define MUX_SAI2 29 ++#define MUX_SDMMC1 30 ++#define MUX_SDMMC2 31 ++#define MUX_SPDIF 32 ++#define MUX_SPI1 33 ++#define MUX_SPI23 34 ++#define MUX_SPI4 35 ++#define MUX_SPI5 36 ++#define MUX_STGEN 37 ++#define MUX_UART1 38 ++#define MUX_UART2 39 ++#define MUX_UART35 40 ++#define MUX_UART4 41 ++#define MUX_UART6 42 ++#define MUX_UART78 43 ++#define MUX_USBO 44 ++#define MUX_USBPHY 45 ++#define MUX_MAX 46 ++ ++#define CLK_MPU_HSI CLKSRC(MUX_MPU, 0) ++#define CLK_MPU_HSE CLKSRC(MUX_MPU, 1) ++#define CLK_MPU_PLL1P CLKSRC(MUX_MPU, 2) ++#define CLK_MPU_PLL1P_DIV CLKSRC(MUX_MPU, 3) ++ ++#define CLK_AXI_HSI CLKSRC(MUX_AXI, 0) ++#define CLK_AXI_HSE CLKSRC(MUX_AXI, 1) ++#define CLK_AXI_PLL2P CLKSRC(MUX_AXI, 2) ++ ++#define CLK_MLAHBS_HSI CLKSRC(MUX_MLAHB, 0) ++#define CLK_MLAHBS_HSE CLKSRC(MUX_MLAHB, 1) ++#define CLK_MLAHBS_CSI CLKSRC(MUX_MLAHB, 2) ++#define CLK_MLAHBS_PLL3 CLKSRC(MUX_MLAHB, 3) ++ ++#define CLK_PLL12_HSI CLKSRC(MUX_PLL12, 0) ++#define CLK_PLL12_HSE CLKSRC(MUX_PLL12, 1) ++ ++#define CLK_PLL3_HSI CLKSRC(MUX_PLL3, 0) ++#define CLK_PLL3_HSE CLKSRC(MUX_PLL3, 1) ++#define CLK_PLL3_CSI CLKSRC(MUX_PLL3, 2) ++ ++#define CLK_PLL4_HSI CLKSRC(MUX_PLL4, 0) ++#define CLK_PLL4_HSE CLKSRC(MUX_PLL4, 1) ++#define CLK_PLL4_CSI CLKSRC(MUX_PLL4, 2) ++ ++#define CLK_RTC_DISABLED CLK_DISABLED(RTC) ++#define CLK_RTC_LSE CLK_SRC(RTC, 1) ++#define CLK_RTC_LSI CLK_SRC(RTC, 2) ++#define CLK_RTC_HSE CLK_SRC(RTC, 3) ++ ++#define CLK_MCO1_HSI CLK_SRC(CK_MCO1, 0) ++#define CLK_MCO1_HSE CLK_SRC(CK_MCO1, 1) ++#define CLK_MCO1_CSI CLK_SRC(CK_MCO1, 2) ++#define CLK_MCO1_LSI CLK_SRC(CK_MCO1, 3) ++#define CLK_MCO1_LSE CLK_SRC(CK_MCO1, 4) ++#define CLK_MCO1_DISABLED CLK_DISABLED(CK_MCO1) ++ ++#define CLK_MCO2_MPU CLK_SRC(CK_MCO2, 0) ++#define CLK_MCO2_AXI CLK_SRC(CK_MCO2, 1) ++#define CLK_MCO2_MLAHB CLK_SRC(CK_MCO2, 2) ++#define CLK_MCO2_PLL4 CLK_SRC(CK_MCO2, 3) ++#define CLK_MCO2_HSE CLK_SRC(CK_MCO2, 4) ++#define CLK_MCO2_HSI CLK_SRC(CK_MCO2, 5) ++#define CLK_MCO2_DISABLED CLK_DISABLED(CK_MCO2) ++ ++#define CLK_CKPER_HSI CLKSRC(MUX_CKPER, 0) ++#define CLK_CKPER_CSI CLKSRC(MUX_CKPER, 1) ++#define CLK_CKPER_HSE CLKSRC(MUX_CKPER, 2) ++#define CLK_CKPER_DISABLED CLKSRC(MUX_CKPER, 3) ++ ++#define CLK_I2C12_PCLK1 CLKSRC(MUX_I2C12, 0) ++#define CLK_I2C12_PLL4R CLKSRC(MUX_I2C12, 1) ++#define CLK_I2C12_HSI CLKSRC(MUX_I2C12, 2) ++#define CLK_I2C12_CSI CLKSRC(MUX_I2C12, 3) ++ ++#define CLK_I2C3_PCLK6 CLKSRC(MUX_I2C3, 0) ++#define CLK_I2C3_PLL4R CLKSRC(MUX_I2C3, 1) ++#define CLK_I2C3_HSI CLKSRC(MUX_I2C3, 2) ++#define CLK_I2C3_CSI CLKSRC(MUX_I2C3, 3) ++ ++#define CLK_I2C4_PCLK6 CLKSRC(MUX_I2C4, 0) ++#define CLK_I2C4_PLL4R CLKSRC(MUX_I2C4, 1) ++#define CLK_I2C4_HSI CLKSRC(MUX_I2C4, 2) ++#define CLK_I2C4_CSI CLKSRC(MUX_I2C4, 3) ++ ++#define CLK_I2C5_PCLK6 CLKSRC(MUX_I2C5, 0) ++#define CLK_I2C5_PLL4R CLKSRC(MUX_I2C5, 1) ++#define CLK_I2C5_HSI CLKSRC(MUX_I2C5, 2) ++#define CLK_I2C5_CSI CLKSRC(MUX_I2C5, 3) ++ ++#define CLK_SPI1_PLL4P CLKSRC(MUX_SPI1, 0) ++#define CLK_SPI1_PLL3Q CLKSRC(MUX_SPI1, 1) ++#define CLK_SPI1_I2SCKIN CLKSRC(MUX_SPI1, 2) ++#define CLK_SPI1_CKPER CLKSRC(MUX_SPI1, 3) ++#define CLK_SPI1_PLL3R CLKSRC(MUX_SPI1, 4) ++ ++#define CLK_SPI23_PLL4P CLKSRC(MUX_SPI23, 0) ++#define CLK_SPI23_PLL3Q CLKSRC(MUX_SPI23, 1) ++#define CLK_SPI23_I2SCKIN CLKSRC(MUX_SPI23, 2) ++#define CLK_SPI23_CKPER CLKSRC(MUX_SPI23, 3) ++#define CLK_SPI23_PLL3R CLKSRC(MUX_SPI23, 4) ++ ++#define CLK_SPI4_PCLK6 CLKSRC(MUX_SPI4, 0) ++#define CLK_SPI4_PLL4Q CLKSRC(MUX_SPI4, 1) ++#define CLK_SPI4_HSI CLKSRC(MUX_SPI4, 2) ++#define CLK_SPI4_CSI CLKSRC(MUX_SPI4, 3) ++#define CLK_SPI4_HSE CLKSRC(MUX_SPI4, 4) ++#define CLK_SPI4_I2SCKIN CLKSRC(MUX_SPI4, 5) ++ ++#define CLK_SPI5_PCLK6 CLKSRC(MUX_SPI5, 0) ++#define CLK_SPI5_PLL4Q CLKSRC(MUX_SPI5, 1) ++#define CLK_SPI5_HSI CLKSRC(MUX_SPI5, 2) ++#define CLK_SPI5_CSI CLKSRC(MUX_SPI5, 3) ++#define CLK_SPI5_HSE CLKSRC(MUX_SPI5, 4) ++ ++#define CLK_UART1_PCLK6 CLKSRC(MUX_UART1, 0) ++#define CLK_UART1_PLL3Q CLKSRC(MUX_UART1, 1) ++#define CLK_UART1_HSI CLKSRC(MUX_UART1, 2) ++#define CLK_UART1_CSI CLKSRC(MUX_UART1, 3) ++#define CLK_UART1_PLL4Q CLKSRC(MUX_UART1, 4) ++#define CLK_UART1_HSE CLKSRC(MUX_UART1, 5) ++ ++#define CLK_UART2_PCLK6 CLKSRC(MUX_UART2, 0) ++#define CLK_UART2_PLL3Q CLKSRC(MUX_UART2, 1) ++#define CLK_UART2_HSI CLKSRC(MUX_UART2, 2) ++#define CLK_UART2_CSI CLKSRC(MUX_UART2, 3) ++#define CLK_UART2_PLL4Q CLKSRC(MUX_UART2, 4) ++#define CLK_UART2_HSE CLKSRC(MUX_UART2, 5) ++ ++#define CLK_UART35_PCLK1 CLKSRC(MUX_UART35, 0) ++#define CLK_UART35_PLL4Q CLKSRC(MUX_UART35, 1) ++#define CLK_UART35_HSI CLKSRC(MUX_UART35, 2) ++#define CLK_UART35_CSI CLKSRC(MUX_UART35, 3) ++#define CLK_UART35_HSE CLKSRC(MUX_UART35, 4) ++ ++#define CLK_UART4_PCLK1 CLKSRC(MUX_UART4, 0) ++#define CLK_UART4_PLL4Q CLKSRC(MUX_UART4, 1) ++#define CLK_UART4_HSI CLKSRC(MUX_UART4, 2) ++#define CLK_UART4_CSI CLKSRC(MUX_UART4, 3) ++#define CLK_UART4_HSE CLKSRC(MUX_UART4, 4) ++ ++#define CLK_UART6_PCLK2 CLKSRC(MUX_UART6, 0) ++#define CLK_UART6_PLL4Q CLKSRC(MUX_UART6, 1) ++#define CLK_UART6_HSI CLKSRC(MUX_UART6, 2) ++#define CLK_UART6_CSI CLKSRC(MUX_UART6, 3) ++#define CLK_UART6_HSE CLKSRC(MUX_UART6, 4) ++ ++#define CLK_UART78_PCLK1 CLKSRC(MUX_UART78, 0) ++#define CLK_UART78_PLL4Q CLKSRC(MUX_UART78, 1) ++#define CLK_UART78_HSI CLKSRC(MUX_UART78, 2) ++#define CLK_UART78_CSI CLKSRC(MUX_UART78, 3) ++#define CLK_UART78_HSE CLKSRC(MUX_UART78, 4) ++ ++#define CLK_LPTIM1_PCLK1 CLKSRC(MUX_LPTIM1, 0) ++#define CLK_LPTIM1_PLL4P CLKSRC(MUX_LPTIM1, 1) ++#define CLK_LPTIM1_PLL3Q CLKSRC(MUX_LPTIM1, 2) ++#define CLK_LPTIM1_LSE CLKSRC(MUX_LPTIM1, 3) ++#define CLK_LPTIM1_LSI CLKSRC(MUX_LPTIM1, 4) ++#define CLK_LPTIM1_CKPER CLKSRC(MUX_LPTIM1, 5) ++ ++#define CLK_LPTIM2_PCLK3 CLKSRC(MUX_LPTIM2, 0) ++#define CLK_LPTIM2_PLL4Q CLKSRC(MUX_LPTIM2, 1) ++#define CLK_LPTIM2_CKPER CLKSRC(MUX_LPTIM2, 2) ++#define CLK_LPTIM2_LSE CLKSRC(MUX_LPTIM2, 3) ++#define CLK_LPTIM2_LSI CLKSRC(MUX_LPTIM2, 4) ++ ++#define CLK_LPTIM3_PCLK3 CLKSRC(MUX_LPTIM3, 0) ++#define CLK_LPTIM3_PLL4Q CLKSRC(MUX_LPTIM3, 1) ++#define CLK_LPTIM3_CKPER CLKSRC(MUX_LPTIM3, 2) ++#define CLK_LPTIM3_LSE CLKSRC(MUX_LPTIM3, 3) ++#define CLK_LPTIM3_LSI CLKSRC(MUX_LPTIM3, 4) ++ ++#define CLK_LPTIM45_PCLK3 CLKSRC(MUX_LPTIM45, 0) ++#define CLK_LPTIM45_PLL4P CLKSRC(MUX_LPTIM45, 1) ++#define CLK_LPTIM45_PLL3Q CLKSRC(MUX_LPTIM45, 2) ++#define CLK_LPTIM45_LSE CLKSRC(MUX_LPTIM45, 3) ++#define CLK_LPTIM45_LSI CLKSRC(MUX_LPTIM45, 4) ++#define CLK_LPTIM45_CKPER CLKSRC(MUX_LPTIM45, 5) ++ ++#define CLK_SAI1_PLL4Q CLKSRC(MUX_SAI1, 0) ++#define CLK_SAI1_PLL3Q CLKSRC(MUX_SAI1, 1) ++#define CLK_SAI1_I2SCKIN CLKSRC(MUX_SAI1, 2) ++#define CLK_SAI1_CKPER CLKSRC(MUX_SAI1, 3) ++#define CLK_SAI1_PLL3R CLKSRC(MUX_SAI1, 4) ++ ++#define CLK_SAI2_PLL4Q CLKSRC(MUX_SAI2, 0) ++#define CLK_SAI2_PLL3Q CLKSRC(MUX_SAI2, 1) ++#define CLK_SAI2_I2SCKIN CLKSRC(MUX_SAI2, 2) ++#define CLK_SAI2_CKPER CLKSRC(MUX_SAI2, 3) ++#define CLK_SAI2_SPDIF CLKSRC(MUX_SAI2, 4) ++#define CLK_SAI2_PLL3R CLKSRC(MUX_SAI2, 5) ++ ++#define CLK_FDCAN_HSE CLKSRC(MUX_FDCAN, 0) ++#define CLK_FDCAN_PLL3Q CLKSRC(MUX_FDCAN, 1) ++#define CLK_FDCAN_PLL4Q CLKSRC(MUX_FDCAN, 2) ++#define CLK_FDCAN_PLL4R CLKSRC(MUX_FDCAN, 3) ++ ++#define CLK_SPDIF_PLL4P CLKSRC(MUX_SPDIF, 0) ++#define CLK_SPDIF_PLL3Q CLKSRC(MUX_SPDIF, 1) ++#define CLK_SPDIF_HSI CLKSRC(MUX_SPDIF, 2) ++ ++#define CLK_ADC1_PLL4R CLKSRC(MUX_ADC1, 0) ++#define CLK_ADC1_CKPER CLKSRC(MUX_ADC1, 1) ++#define CLK_ADC1_PLL3Q CLKSRC(MUX_ADC1, 2) ++ ++#define CLK_ADC2_PLL4R CLKSRC(MUX_ADC2, 0) ++#define CLK_ADC2_CKPER CLKSRC(MUX_ADC2, 1) ++#define CLK_ADC2_PLL3Q CLKSRC(MUX_ADC2, 2) ++ ++#define CLK_SDMMC1_HCLK6 CLKSRC(MUX_SDMMC1, 0) ++#define CLK_SDMMC1_PLL3R CLKSRC(MUX_SDMMC1, 1) ++#define CLK_SDMMC1_PLL4P CLKSRC(MUX_SDMMC1, 2) ++#define CLK_SDMMC1_HSI CLKSRC(MUX_SDMMC1, 3) ++ ++#define CLK_SDMMC2_HCLK6 CLKSRC(MUX_SDMMC2, 0) ++#define CLK_SDMMC2_PLL3R CLKSRC(MUX_SDMMC2, 1) ++#define CLK_SDMMC2_PLL4P CLKSRC(MUX_SDMMC2, 2) ++#define CLK_SDMMC2_HSI CLKSRC(MUX_SDMMC2, 3) ++ ++#define CLK_ETH1_PLL4P CLKSRC(MUX_ETH1, 0) ++#define CLK_ETH1_PLL3Q CLKSRC(MUX_ETH1, 1) ++ ++#define CLK_ETH2_PLL4P CLKSRC(MUX_ETH2, 0) ++#define CLK_ETH2_PLL3Q CLKSRC(MUX_ETH2, 1) ++ ++#define CLK_USBPHY_HSE CLKSRC(MUX_USBPHY, 0) ++#define CLK_USBPHY_PLL4R CLKSRC(MUX_USBPHY, 1) ++#define CLK_USBPHY_HSE_DIV2 CLKSRC(MUX_USBPHY, 2) ++ ++#define CLK_USBO_PLL4R CLKSRC(MUX_USBO, 0) ++#define CLK_USBO_USBPHY CLKSRC(MUX_USBO, 1) ++ ++#define CLK_QSPI_ACLK CLKSRC(MUX_QSPI, 0) ++#define CLK_QSPI_PLL3R CLKSRC(MUX_QSPI, 1) ++#define CLK_QSPI_PLL4P CLKSRC(MUX_QSPI, 2) ++#define CLK_QSPI_CKPER CLKSRC(MUX_QSPI, 3) ++ ++#define CLK_FMC_ACLK CLKSRC(MUX_FMC, 0) ++#define CLK_FMC_PLL3R CLKSRC(MUX_FMC, 1) ++#define CLK_FMC_PLL4P CLKSRC(MUX_FMC, 2) ++#define CLK_FMC_CKPER CLKSRC(MUX_FMC, 3) ++ ++#define CLK_RNG1_CSI CLKSRC(MUX_RNG1, 0) ++#define CLK_RNG1_PLL4R CLKSRC(MUX_RNG1, 1) ++/* WARNING: POSITION 2 OF RNG1 MUX IS RESERVED */ ++#define CLK_RNG1_LSI CLKSRC(MUX_RNG1, 3) ++ ++#define CLK_STGEN_HSI CLKSRC(MUX_STGEN, 0) ++#define CLK_STGEN_HSE CLKSRC(MUX_STGEN, 1) ++ ++#define CLK_DCMIPP_ACLK CLKSRC(MUX_DCMIPP, 0) ++#define CLK_DCMIPP_PLL2Q CLKSRC(MUX_DCMIPP, 1) ++#define CLK_DCMIPP_PLL4P CLKSRC(MUX_DCMIPP, 2) ++#define CLK_DCMIPP_CKPER CLKSRC(MUX_DCMIPP, 3) ++ ++#define CLK_SAES_AXI CLKSRC(MUX_SAES, 0) ++#define CLK_SAES_CKPER CLKSRC(MUX_SAES, 1) ++#define CLK_SAES_PLL4R CLKSRC(MUX_SAES, 2) ++#define CLK_SAES_LSI CLKSRC(MUX_SAES, 3) ++ ++/* PLL output is enable when x=1, with x=p,q or r */ ++#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) ++ ++/* define for st,pll /csg */ ++#define SSCG_MODE_CENTER_SPREAD 0 ++#define SSCG_MODE_DOWN_SPREAD 1 ++ ++/* define for st,drive */ ++#define LSEDRV_LOWEST 0 ++#define LSEDRV_MEDIUM_LOW 1 ++#define LSEDRV_MEDIUM_HIGH 2 ++#define LSEDRV_HIGHEST 3 ++ ++#endif /* _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ */ +diff --git a/include/dt-bindings/clock/stm32mp15-clks.h b/include/dt-bindings/clock/stm32mp15-clks.h +new file mode 100644 +index 000000000..7fa8cbad6 +--- /dev/null ++++ b/include/dt-bindings/clock/stm32mp15-clks.h +@@ -0,0 +1,278 @@ ++/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ ++/* ++ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved ++ * Author: Gabriel Fernandez for STMicroelectronics. ++ */ ++ ++#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ ++#define _DT_BINDINGS_STM32MP1_CLKS_H_ ++ ++/* OSCILLATOR clocks */ ++#define CK_HSE 0 ++#define CK_CSI 1 ++#define CK_LSI 2 ++#define CK_LSE 3 ++#define CK_HSI 4 ++#define CK_HSE_DIV2 5 ++ ++/* Bus clocks */ ++#define TIM2 6 ++#define TIM3 7 ++#define TIM4 8 ++#define TIM5 9 ++#define TIM6 10 ++#define TIM7 11 ++#define TIM12 12 ++#define TIM13 13 ++#define TIM14 14 ++#define LPTIM1 15 ++#define SPI2 16 ++#define SPI3 17 ++#define USART2 18 ++#define USART3 19 ++#define UART4 20 ++#define UART5 21 ++#define UART7 22 ++#define UART8 23 ++#define I2C1 24 ++#define I2C2 25 ++#define I2C3 26 ++#define I2C5 27 ++#define SPDIF 28 ++#define CEC 29 ++#define DAC12 30 ++#define MDIO 31 ++#define TIM1 32 ++#define TIM8 33 ++#define TIM15 34 ++#define TIM16 35 ++#define TIM17 36 ++#define SPI1 37 ++#define SPI4 38 ++#define SPI5 39 ++#define USART6 40 ++#define SAI1 41 ++#define SAI2 42 ++#define SAI3 43 ++#define DFSDM 44 ++#define FDCAN 45 ++#define LPTIM2 46 ++#define LPTIM3 47 ++#define LPTIM4 48 ++#define LPTIM5 49 ++#define SAI4 50 ++#define SYSCFG 51 ++#define VREF 52 ++#define TMPSENS 53 ++#define PMBCTRL 54 ++#define HDP 55 ++#define LTDC 56 ++#define DSI 57 ++#define IWDG2 58 ++#define USBPHY 59 ++#define STGENRO 60 ++#define SPI6 61 ++#define I2C4 62 ++#define I2C6 63 ++#define USART1 64 ++#define RTCAPB 65 ++#define TZC1 66 ++#define TZPC 67 ++#define IWDG1 68 ++#define BSEC 69 ++#define STGEN 70 ++#define DMA1 71 ++#define DMA2 72 ++#define DMAMUX 73 ++#define ADC12 74 ++#define USBO 75 ++#define SDMMC3 76 ++#define DCMI 77 ++#define CRYP2 78 ++#define HASH2 79 ++#define RNG2 80 ++#define CRC2 81 ++#define HSEM 82 ++#define IPCC 83 ++#define GPIOA 84 ++#define GPIOB 85 ++#define GPIOC 86 ++#define GPIOD 87 ++#define GPIOE 88 ++#define GPIOF 89 ++#define GPIOG 90 ++#define GPIOH 91 ++#define GPIOI 92 ++#define GPIOJ 93 ++#define GPIOK 94 ++#define GPIOZ 95 ++#define CRYP1 96 ++#define HASH1 97 ++#define RNG1 98 ++#define BKPSRAM 99 ++#define MDMA 100 ++#define GPU 101 ++#define ETHCK 102 ++#define ETHTX 103 ++#define ETHRX 104 ++#define ETHMAC 105 ++#define FMC 106 ++#define QSPI 107 ++#define SDMMC1 108 ++#define SDMMC2 109 ++#define CRC1 110 ++#define USBH 111 ++#define ETHSTP 112 ++#define TZC2 113 ++ ++/* Kernel clocks */ ++#define SDMMC1_K 118 ++#define SDMMC2_K 119 ++#define SDMMC3_K 120 ++#define FMC_K 121 ++#define QSPI_K 122 ++#define ETHCK_K 123 ++#define RNG1_K 124 ++#define RNG2_K 125 ++#define GPU_K 126 ++#define USBPHY_K 127 ++#define STGEN_K 128 ++#define SPDIF_K 129 ++#define SPI1_K 130 ++#define SPI2_K 131 ++#define SPI3_K 132 ++#define SPI4_K 133 ++#define SPI5_K 134 ++#define SPI6_K 135 ++#define CEC_K 136 ++#define I2C1_K 137 ++#define I2C2_K 138 ++#define I2C3_K 139 ++#define I2C4_K 140 ++#define I2C5_K 141 ++#define I2C6_K 142 ++#define LPTIM1_K 143 ++#define LPTIM2_K 144 ++#define LPTIM3_K 145 ++#define LPTIM4_K 146 ++#define LPTIM5_K 147 ++#define USART1_K 148 ++#define USART2_K 149 ++#define USART3_K 150 ++#define UART4_K 151 ++#define UART5_K 152 ++#define USART6_K 153 ++#define UART7_K 154 ++#define UART8_K 155 ++#define DFSDM_K 156 ++#define FDCAN_K 157 ++#define SAI1_K 158 ++#define SAI2_K 159 ++#define SAI3_K 160 ++#define SAI4_K 161 ++#define ADC12_K 162 ++#define DSI_K 163 ++#define DSI_PX 164 ++#define ADFSDM_K 165 ++#define USBO_K 166 ++#define LTDC_PX 167 ++#define DAC12_K 168 ++#define ETHPTP_K 169 ++ ++/* PLL */ ++#define PLL1 176 ++#define PLL2 177 ++#define PLL3 178 ++#define PLL4 179 ++ ++/* ODF */ ++#define PLL1_P 180 ++#define PLL1_Q 181 ++#define PLL1_R 182 ++#define PLL2_P 183 ++#define PLL2_Q 184 ++#define PLL2_R 185 ++#define PLL3_P 186 ++#define PLL3_Q 187 ++#define PLL3_R 188 ++#define PLL4_P 189 ++#define PLL4_Q 190 ++#define PLL4_R 191 ++ ++/* AUX */ ++#define RTC 192 ++ ++/* MCLK */ ++#define CK_PER 193 ++#define CK_MPU 194 ++#define CK_AXI 195 ++#define CK_MCU 196 ++ ++/* Time base */ ++#define TIM2_K 197 ++#define TIM3_K 198 ++#define TIM4_K 199 ++#define TIM5_K 200 ++#define TIM6_K 201 ++#define TIM7_K 202 ++#define TIM12_K 203 ++#define TIM13_K 204 ++#define TIM14_K 205 ++#define TIM1_K 206 ++#define TIM8_K 207 ++#define TIM15_K 208 ++#define TIM16_K 209 ++#define TIM17_K 210 ++ ++/* MCO clocks */ ++#define CK_MCO1 211 ++#define CK_MCO2 212 ++ ++/* TRACE & DEBUG clocks */ ++#define CK_DBG 214 ++#define CK_TRACE 215 ++ ++/* DDR */ ++#define DDRC1 220 ++#define DDRC1LP 221 ++#define DDRC2 222 ++#define DDRC2LP 223 ++#define DDRPHYC 224 ++#define DDRPHYCLP 225 ++#define DDRCAPB 226 ++#define DDRCAPBLP 227 ++#define AXIDCG 228 ++#define DDRPHYCAPB 229 ++#define DDRPHYCAPBLP 230 ++#define DDRPERFM 231 ++ ++#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 ++ ++#define CK_SCMI1_PLL3_Q 0 ++#define CK_SCMI1_PLL3_R 1 ++#define CK_SCMI1_MCU 2 ++ ++#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ +diff --git a/include/dt-bindings/clock/stm32mp15-clksrc.h b/include/dt-bindings/clock/stm32mp15-clksrc.h +new file mode 100644 +index 000000000..1f7a50751 +--- /dev/null ++++ b/include/dt-bindings/clock/stm32mp15-clksrc.h +@@ -0,0 +1,282 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ ++/* ++ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved ++ */ ++ ++#ifndef _DT_BINDINGS_CLOCK_STM32MP15_CLKSRC_H_ ++#define _DT_BINDINGS_CLOCK_STM32MP15_CLKSRC_H_ ++ ++/* PLL output is enable when x=1, with x=p,q or r */ ++#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) ++ ++/* st,clksrc: mandatory clock source */ ++#define CLK_MPU_HSI 0x00000200 ++#define CLK_MPU_HSE 0x00000201 ++#define CLK_MPU_PLL1P 0x00000202 ++#define CLK_MPU_PLL1P_DIV 0x00000203 ++ ++#define CLK_AXI_HSI 0x00000240 ++#define CLK_AXI_HSE 0x00000241 ++#define CLK_AXI_PLL2P 0x00000242 ++ ++#define CLK_MCU_HSI 0x00000480 ++#define CLK_MCU_HSE 0x00000481 ++#define CLK_MCU_CSI 0x00000482 ++#define CLK_MCU_PLL3P 0x00000483 ++ ++#define CLK_PLL12_HSI 0x00000280 ++#define CLK_PLL12_HSE 0x00000281 ++ ++#define CLK_PLL3_HSI 0x00008200 ++#define CLK_PLL3_HSE 0x00008201 ++#define CLK_PLL3_CSI 0x00008202 ++ ++#define CLK_PLL4_HSI 0x00008240 ++#define CLK_PLL4_HSE 0x00008241 ++#define CLK_PLL4_CSI 0x00008242 ++#define CLK_PLL4_I2SCKIN 0x00008243 ++ ++#define CLK_RTC_DISABLED 0x00001400 ++#define CLK_RTC_LSE 0x00001401 ++#define CLK_RTC_LSI 0x00001402 ++#define CLK_RTC_HSE 0x00001403 ++ ++#define CLK_MCO1_HSI 0x00008000 ++#define CLK_MCO1_HSE 0x00008001 ++#define CLK_MCO1_CSI 0x00008002 ++#define CLK_MCO1_LSI 0x00008003 ++#define CLK_MCO1_LSE 0x00008004 ++#define CLK_MCO1_DISABLED 0x0000800F ++ ++#define CLK_MCO2_MPU 0x00008040 ++#define CLK_MCO2_AXI 0x00008041 ++#define CLK_MCO2_MCU 0x00008042 ++#define CLK_MCO2_PLL4P 0x00008043 ++#define CLK_MCO2_HSE 0x00008044 ++#define CLK_MCO2_HSI 0x00008045 ++#define CLK_MCO2_DISABLED 0x0000804F ++ ++/* st,pkcs: peripheral kernel clock source */ ++ ++#define CLK_I2C12_PCLK1 0x00008C00 ++#define CLK_I2C12_PLL4R 0x00008C01 ++#define CLK_I2C12_HSI 0x00008C02 ++#define CLK_I2C12_CSI 0x00008C03 ++#define CLK_I2C12_DISABLED 0x00008C07 ++ ++#define CLK_I2C35_PCLK1 0x00008C40 ++#define CLK_I2C35_PLL4R 0x00008C41 ++#define CLK_I2C35_HSI 0x00008C42 ++#define CLK_I2C35_CSI 0x00008C43 ++#define CLK_I2C35_DISABLED 0x00008C47 ++ ++#define CLK_I2C46_PCLK5 0x00000C00 ++#define CLK_I2C46_PLL3Q 0x00000C01 ++#define CLK_I2C46_HSI 0x00000C02 ++#define CLK_I2C46_CSI 0x00000C03 ++#define CLK_I2C46_DISABLED 0x00000C07 ++ ++#define CLK_SAI1_PLL4Q 0x00008C80 ++#define CLK_SAI1_PLL3Q 0x00008C81 ++#define CLK_SAI1_I2SCKIN 0x00008C82 ++#define CLK_SAI1_CKPER 0x00008C83 ++#define CLK_SAI1_PLL3R 0x00008C84 ++#define CLK_SAI1_DISABLED 0x00008C87 ++ ++#define CLK_SAI2_PLL4Q 0x00008CC0 ++#define CLK_SAI2_PLL3Q 0x00008CC1 ++#define CLK_SAI2_I2SCKIN 0x00008CC2 ++#define CLK_SAI2_CKPER 0x00008CC3 ++#define CLK_SAI2_SPDIF 0x00008CC4 ++#define CLK_SAI2_PLL3R 0x00008CC5 ++#define CLK_SAI2_DISABLED 0x00008CC7 ++ ++#define CLK_SAI3_PLL4Q 0x00008D00 ++#define CLK_SAI3_PLL3Q 0x00008D01 ++#define CLK_SAI3_I2SCKIN 0x00008D02 ++#define CLK_SAI3_CKPER 0x00008D03 ++#define CLK_SAI3_PLL3R 0x00008D04 ++#define CLK_SAI3_DISABLED 0x00008D07 ++ ++#define CLK_SAI4_PLL4Q 0x00008D40 ++#define CLK_SAI4_PLL3Q 0x00008D41 ++#define CLK_SAI4_I2SCKIN 0x00008D42 ++#define CLK_SAI4_CKPER 0x00008D43 ++#define CLK_SAI4_PLL3R 0x00008D44 ++#define CLK_SAI4_DISABLED 0x00008D47 ++ ++#define CLK_SPI2S1_PLL4P 0x00008D80 ++#define CLK_SPI2S1_PLL3Q 0x00008D81 ++#define CLK_SPI2S1_I2SCKIN 0x00008D82 ++#define CLK_SPI2S1_CKPER 0x00008D83 ++#define CLK_SPI2S1_PLL3R 0x00008D84 ++#define CLK_SPI2S1_DISABLED 0x00008D87 ++ ++#define CLK_SPI2S23_PLL4P 0x00008DC0 ++#define CLK_SPI2S23_PLL3Q 0x00008DC1 ++#define CLK_SPI2S23_I2SCKIN 0x00008DC2 ++#define CLK_SPI2S23_CKPER 0x00008DC3 ++#define CLK_SPI2S23_PLL3R 0x00008DC4 ++#define CLK_SPI2S23_DISABLED 0x00008DC7 ++ ++#define CLK_SPI45_PCLK2 0x00008E00 ++#define CLK_SPI45_PLL4Q 0x00008E01 ++#define CLK_SPI45_HSI 0x00008E02 ++#define CLK_SPI45_CSI 0x00008E03 ++#define CLK_SPI45_HSE 0x00008E04 ++#define CLK_SPI45_DISABLED 0x00008E07 ++ ++#define CLK_SPI6_PCLK5 0x00000C40 ++#define CLK_SPI6_PLL4Q 0x00000C41 ++#define CLK_SPI6_HSI 0x00000C42 ++#define CLK_SPI6_CSI 0x00000C43 ++#define CLK_SPI6_HSE 0x00000C44 ++#define CLK_SPI6_PLL3Q 0x00000C45 ++#define CLK_SPI6_DISABLED 0x00000C47 ++ ++#define CLK_UART6_PCLK2 0x00008E40 ++#define CLK_UART6_PLL4Q 0x00008E41 ++#define CLK_UART6_HSI 0x00008E42 ++#define CLK_UART6_CSI 0x00008E43 ++#define CLK_UART6_HSE 0x00008E44 ++#define CLK_UART6_DISABLED 0x00008E47 ++ ++#define CLK_UART24_PCLK1 0x00008E80 ++#define CLK_UART24_PLL4Q 0x00008E81 ++#define CLK_UART24_HSI 0x00008E82 ++#define CLK_UART24_CSI 0x00008E83 ++#define CLK_UART24_HSE 0x00008E84 ++#define CLK_UART24_DISABLED 0x00008E87 ++ ++#define CLK_UART35_PCLK1 0x00008EC0 ++#define CLK_UART35_PLL4Q 0x00008EC1 ++#define CLK_UART35_HSI 0x00008EC2 ++#define CLK_UART35_CSI 0x00008EC3 ++#define CLK_UART35_HSE 0x00008EC4 ++#define CLK_UART35_DISABLED 0x00008EC7 ++ ++#define CLK_UART78_PCLK1 0x00008F00 ++#define CLK_UART78_PLL4Q 0x00008F01 ++#define CLK_UART78_HSI 0x00008F02 ++#define CLK_UART78_CSI 0x00008F03 ++#define CLK_UART78_HSE 0x00008F04 ++#define CLK_UART78_DISABLED 0x00008F07 ++ ++#define CLK_UART1_PCLK5 0x00000C80 ++#define CLK_UART1_PLL3Q 0x00000C81 ++#define CLK_UART1_HSI 0x00000C82 ++#define CLK_UART1_CSI 0x00000C83 ++#define CLK_UART1_PLL4Q 0x00000C84 ++#define CLK_UART1_HSE 0x00000C85 ++#define CLK_UART1_DISABLED 0x00000C87 ++ ++#define CLK_SDMMC12_HCLK6 0x00008F40 ++#define CLK_SDMMC12_PLL3R 0x00008F41 ++#define CLK_SDMMC12_PLL4P 0x00008F42 ++#define CLK_SDMMC12_HSI 0x00008F43 ++#define CLK_SDMMC12_DISABLED 0x00008F47 ++ ++#define CLK_SDMMC3_HCLK2 0x00008F80 ++#define CLK_SDMMC3_PLL3R 0x00008F81 ++#define CLK_SDMMC3_PLL4P 0x00008F82 ++#define CLK_SDMMC3_HSI 0x00008F83 ++#define CLK_SDMMC3_DISABLED 0x00008F87 ++ ++#define CLK_ETH_PLL4P 0x00008FC0 ++#define CLK_ETH_PLL3Q 0x00008FC1 ++#define CLK_ETH_DISABLED 0x00008FC3 ++ ++#define CLK_QSPI_ACLK 0x00009000 ++#define CLK_QSPI_PLL3R 0x00009001 ++#define CLK_QSPI_PLL4P 0x00009002 ++#define CLK_QSPI_CKPER 0x00009003 ++ ++#define CLK_FMC_ACLK 0x00009040 ++#define CLK_FMC_PLL3R 0x00009041 ++#define CLK_FMC_PLL4P 0x00009042 ++#define CLK_FMC_CKPER 0x00009043 ++ ++#define CLK_FDCAN_HSE 0x000090C0 ++#define CLK_FDCAN_PLL3Q 0x000090C1 ++#define CLK_FDCAN_PLL4Q 0x000090C2 ++#define CLK_FDCAN_PLL4R 0x000090C3 ++ ++#define CLK_SPDIF_PLL4P 0x00009140 ++#define CLK_SPDIF_PLL3Q 0x00009141 ++#define CLK_SPDIF_HSI 0x00009142 ++#define CLK_SPDIF_DISABLED 0x00009143 ++ ++#define CLK_CEC_LSE 0x00009180 ++#define CLK_CEC_LSI 0x00009181 ++#define CLK_CEC_CSI_DIV122 0x00009182 ++#define CLK_CEC_DISABLED 0x00009183 ++ ++#define CLK_USBPHY_HSE 0x000091C0 ++#define CLK_USBPHY_PLL4R 0x000091C1 ++#define CLK_USBPHY_HSE_DIV2 0x000091C2 ++#define CLK_USBPHY_DISABLED 0x000091C3 ++ ++#define CLK_USBO_PLL4R 0x800091C0 ++#define CLK_USBO_USBPHY 0x800091C1 ++ ++#define CLK_RNG1_CSI 0x00000CC0 ++#define CLK_RNG1_PLL4R 0x00000CC1 ++#define CLK_RNG1_LSE 0x00000CC2 ++#define CLK_RNG1_LSI 0x00000CC3 ++ ++#define CLK_RNG2_CSI 0x00009200 ++#define CLK_RNG2_PLL4R 0x00009201 ++#define CLK_RNG2_LSE 0x00009202 ++#define CLK_RNG2_LSI 0x00009203 ++ ++#define CLK_CKPER_HSI 0x00000D00 ++#define CLK_CKPER_CSI 0x00000D01 ++#define CLK_CKPER_HSE 0x00000D02 ++#define CLK_CKPER_DISABLED 0x00000D03 ++ ++#define CLK_STGEN_HSI 0x00000D40 ++#define CLK_STGEN_HSE 0x00000D41 ++#define CLK_STGEN_DISABLED 0x00000D43 ++ ++#define CLK_DSI_DSIPLL 0x00009240 ++#define CLK_DSI_PLL4P 0x00009241 ++ ++#define CLK_ADC_PLL4R 0x00009280 ++#define CLK_ADC_CKPER 0x00009281 ++#define CLK_ADC_PLL3Q 0x00009282 ++#define CLK_ADC_DISABLED 0x00009283 ++ ++#define CLK_LPTIM45_PCLK3 0x000092C0 ++#define CLK_LPTIM45_PLL4P 0x000092C1 ++#define CLK_LPTIM45_PLL3Q 0x000092C2 ++#define CLK_LPTIM45_LSE 0x000092C3 ++#define CLK_LPTIM45_LSI 0x000092C4 ++#define CLK_LPTIM45_CKPER 0x000092C5 ++#define CLK_LPTIM45_DISABLED 0x000092C7 ++ ++#define CLK_LPTIM23_PCLK3 0x00009300 ++#define CLK_LPTIM23_PLL4Q 0x00009301 ++#define CLK_LPTIM23_CKPER 0x00009302 ++#define CLK_LPTIM23_LSE 0x00009303 ++#define CLK_LPTIM23_LSI 0x00009304 ++#define CLK_LPTIM23_DISABLED 0x00009307 ++ ++#define CLK_LPTIM1_PCLK1 0x00009340 ++#define CLK_LPTIM1_PLL4P 0x00009341 ++#define CLK_LPTIM1_PLL3Q 0x00009342 ++#define CLK_LPTIM1_LSE 0x00009343 ++#define CLK_LPTIM1_LSI 0x00009344 ++#define CLK_LPTIM1_CKPER 0x00009345 ++#define CLK_LPTIM1_DISABLED 0x00009347 ++ ++/* define for st,pll /csg */ ++#define SSCG_MODE_CENTER_SPREAD 0 ++#define SSCG_MODE_DOWN_SPREAD 1 ++ ++/* define for st,drive */ ++#define LSEDRV_LOWEST 0 ++#define LSEDRV_MEDIUM_LOW 1 ++#define LSEDRV_MEDIUM_HIGH 2 ++#define LSEDRV_HIGHEST 3 ++ ++#endif +diff --git a/include/dt-bindings/power/stm32mp1-power.h b/include/dt-bindings/power/stm32mp1-power.h +new file mode 100644 +index 000000000..3202e0b44 +--- /dev/null ++++ b/include/dt-bindings/power/stm32mp1-power.h +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ ++/* ++ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Author: Yann Gautier for STMicroelectronics. ++ */ ++ ++#ifndef DT_BINDINGS_STM32MP1_POWER_H ++#define DT_BINDINGS_STM32MP1_POWER_H ++ ++#define STM32_PM_CSLEEP_RUN 0 ++#define STM32_PM_CSTOP_ALLOW_STOP 1 ++#define STM32_PM_CSTOP_ALLOW_LP_STOP 2 ++#define STM32_PM_CSTOP_ALLOW_LPLV_STOP 3 ++#define STM32_PM_CSTOP_ALLOW_LPLV_STOP2 4 ++#define STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR 5 ++#define STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF 6 ++#define STM32_PM_SHUTDOWN 7 ++#define STM32_PM_MAX_SOC_MODE 8 ++ ++#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 bc71924fa..f24f99b12 100644 +--- a/include/dt-bindings/reset/stm32mp1-resets.h ++++ b/include/dt-bindings/reset/stm32mp1-resets.h +@@ -1,121 +1,11 @@ +-/* 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. ++ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +-#ifndef _DT_BINDINGS_STM32MP1_RESET_H_ +-#define _DT_BINDINGS_STM32MP1_RESET_H_ +- +-#define LTDC_R 3072 +-#define DSI_R 3076 +-#define DDRPERFM_R 3080 +-#define USBPHY_R 3088 +-#define SPI6_R 3136 +-#define I2C4_R 3138 +-#define I2C6_R 3139 +-#define USART1_R 3140 +-#define STGEN_R 3156 +-#define GPIOZ_R 3200 +-#define CRYP1_R 3204 +-#define HASH1_R 3205 +-#define RNG1_R 3206 +-#define AXIM_R 3216 +-#define GPU_R 3269 +-#define ETHMAC_R 3274 +-#define FMC_R 3276 +-#define QSPI_R 3278 +-#define SDMMC1_R 3280 +-#define SDMMC2_R 3281 +-#define CRC1_R 3284 +-#define USBH_R 3288 +-#define MDMA_R 3328 +-#define MCU_R 8225 +-#define TIM2_R 19456 +-#define TIM3_R 19457 +-#define TIM4_R 19458 +-#define TIM5_R 19459 +-#define TIM6_R 19460 +-#define TIM7_R 19461 +-#define TIM12_R 16462 +-#define TIM13_R 16463 +-#define TIM14_R 16464 +-#define LPTIM1_R 19465 +-#define SPI2_R 19467 +-#define SPI3_R 19468 +-#define USART2_R 19470 +-#define USART3_R 19471 +-#define UART4_R 19472 +-#define UART5_R 19473 +-#define UART7_R 19474 +-#define UART8_R 19475 +-#define I2C1_R 19477 +-#define I2C2_R 19478 +-#define I2C3_R 19479 +-#define I2C5_R 19480 +-#define SPDIF_R 19482 +-#define CEC_R 19483 +-#define DAC12_R 19485 +-#define MDIO_R 19847 +-#define TIM1_R 19520 +-#define TIM8_R 19521 +-#define TIM15_R 19522 +-#define TIM16_R 19523 +-#define TIM17_R 19524 +-#define SPI1_R 19528 +-#define SPI4_R 19529 +-#define SPI5_R 19530 +-#define USART6_R 19533 +-#define SAI1_R 19536 +-#define SAI2_R 19537 +-#define SAI3_R 19538 +-#define DFSDM_R 19540 +-#define FDCAN_R 19544 +-#define LPTIM2_R 19584 +-#define LPTIM3_R 19585 +-#define LPTIM4_R 19586 +-#define LPTIM5_R 19587 +-#define SAI4_R 19592 +-#define SYSCFG_R 19595 +-#define VREF_R 19597 +-#define TMPSENS_R 19600 +-#define PMBCTRL_R 19601 +-#define DMA1_R 19648 +-#define DMA2_R 19649 +-#define DMAMUX_R 19650 +-#define ADC12_R 19653 +-#define USBO_R 19656 +-#define SDMMC3_R 19664 +-#define CAMITF_R 19712 +-#define CRYP2_R 19716 +-#define HASH2_R 19717 +-#define RNG2_R 19718 +-#define CRC2_R 19719 +-#define HSEM_R 19723 +-#define MBOX_R 19724 +-#define GPIOA_R 19776 +-#define GPIOB_R 19777 +-#define GPIOC_R 19778 +-#define GPIOD_R 19779 +-#define GPIOE_R 19780 +-#define GPIOF_R 19781 +-#define GPIOG_R 19782 +-#define GPIOH_R 19783 +-#define GPIOI_R 19784 +-#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_ */ ++#if STM32MP13 ++#include "stm32mp13-resets.h" ++#endif ++#if STM32MP15 ++#include "stm32mp15-resets.h" ++#endif +diff --git a/include/dt-bindings/reset/stm32mp13-resets.h b/include/dt-bindings/reset/stm32mp13-resets.h +new file mode 100644 +index 000000000..09fad7f98 +--- /dev/null ++++ b/include/dt-bindings/reset/stm32mp13-resets.h +@@ -0,0 +1,96 @@ ++/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ ++/* ++ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved ++ * Author: Gabriel Fernandez for STMicroelectronics. ++ */ ++ ++#ifndef _DT_BINDINGS_STM32MP13_RESET_H_ ++#define _DT_BINDINGS_STM32MP13_RESET_H_ ++ ++#define TIM2_R 13568 ++#define TIM3_R 13569 ++#define TIM4_R 13570 ++#define TIM5_R 13571 ++#define TIM6_R 13572 ++#define TIM7_R 13573 ++#define LPTIM1_R 13577 ++#define SPI2_R 13579 ++#define SPI3_R 13580 ++#define USART3_R 13583 ++#define UART4_R 13584 ++#define UART5_R 13585 ++#define UART7_R 13586 ++#define UART8_R 13587 ++#define I2C1_R 13589 ++#define I2C2_R 13590 ++#define SPDIF_R 13594 ++#define TIM1_R 13632 ++#define TIM8_R 13633 ++#define SPI1_R 13640 ++#define USART6_R 13645 ++#define SAI1_R 13648 ++#define SAI2_R 13649 ++#define DFSDM_R 13652 ++#define FDCAN_R 13656 ++#define LPTIM2_R 13696 ++#define LPTIM3_R 13697 ++#define LPTIM4_R 13698 ++#define LPTIM5_R 13699 ++#define SYSCFG_R 13707 ++#define VREF_R 13709 ++#define DTS_R 13712 ++#define PMBCTRL_R 13713 ++#define LTDC_R 13760 ++#define DCMIPP_R 13761 ++#define DDRPERFM_R 13768 ++#define USBPHY_R 13776 ++#define STGEN_R 13844 ++#define USART1_R 13888 ++#define USART2_R 13889 ++#define SPI4_R 13890 ++#define SPI5_R 13891 ++#define I2C3_R 13892 ++#define I2C4_R 13893 ++#define I2C5_R 13894 ++#define TIM12_R 13895 ++#define TIM13_R 13896 ++#define TIM14_R 13897 ++#define TIM15_R 13898 ++#define TIM16_R 13899 ++#define TIM17_R 13900 ++#define DMA1_R 13952 ++#define DMA2_R 13953 ++#define DMAMUX1_R 13954 ++#define DMA3_R 13955 ++#define DMAMUX2_R 13956 ++#define ADC1_R 13957 ++#define ADC2_R 13958 ++#define USBO_R 13960 ++#define GPIOA_R 14080 ++#define GPIOB_R 14081 ++#define GPIOC_R 14082 ++#define GPIOD_R 14083 ++#define GPIOE_R 14084 ++#define GPIOF_R 14085 ++#define GPIOG_R 14086 ++#define GPIOH_R 14087 ++#define GPIOI_R 14088 ++#define TSC_R 14095 ++#define PKA_R 14146 ++#define SAES_R 14147 ++#define CRYP1_R 14148 ++#define HASH1_R 14149 ++#define RNG1_R 14150 ++#define AXIMC_R 14160 ++#define MDMA_R 14208 ++#define MCE_R 14209 ++#define ETH1MAC_R 14218 ++#define FMC_R 14220 ++#define QSPI_R 14222 ++#define SDMMC1_R 14224 ++#define SDMMC2_R 14225 ++#define CRC1_R 14228 ++#define USBH_R 14232 ++#define ETH2MAC_R 14238 ++ ++#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ +diff --git a/include/dt-bindings/reset/stm32mp15-resets.h b/include/dt-bindings/reset/stm32mp15-resets.h +new file mode 100644 +index 000000000..2846d7b84 +--- /dev/null ++++ b/include/dt-bindings/reset/stm32mp15-resets.h +@@ -0,0 +1,123 @@ ++/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ ++/* ++ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved ++ * Author: Gabriel Fernandez for STMicroelectronics. ++ */ ++ ++#ifndef _DT_BINDINGS_STM32MP15_RESET_H_ ++#define _DT_BINDINGS_STM32MP15_RESET_H_ ++ ++#define MCU_HOLD_BOOT_R 2144 ++#define LTDC_R 3072 ++#define DSI_R 3076 ++#define DDRPERFM_R 3080 ++#define USBPHY_R 3088 ++#define SPI6_R 3136 ++#define I2C4_R 3138 ++#define I2C6_R 3139 ++#define USART1_R 3140 ++#define STGEN_R 3156 ++#define GPIOZ_R 3200 ++#define CRYP1_R 3204 ++#define HASH1_R 3205 ++#define RNG1_R 3206 ++#define AXIM_R 3216 ++#define GPU_R 3269 ++#define ETHMAC_R 3274 ++#define FMC_R 3276 ++#define QSPI_R 3278 ++#define SDMMC1_R 3280 ++#define SDMMC2_R 3281 ++#define CRC1_R 3284 ++#define USBH_R 3288 ++#define MDMA_R 3328 ++#define MCU_R 8225 ++#define TIM2_R 19456 ++#define TIM3_R 19457 ++#define TIM4_R 19458 ++#define TIM5_R 19459 ++#define TIM6_R 19460 ++#define TIM7_R 19461 ++#define TIM12_R 16462 ++#define TIM13_R 16463 ++#define TIM14_R 16464 ++#define LPTIM1_R 19465 ++#define SPI2_R 19467 ++#define SPI3_R 19468 ++#define USART2_R 19470 ++#define USART3_R 19471 ++#define UART4_R 19472 ++#define UART5_R 19473 ++#define UART7_R 19474 ++#define UART8_R 19475 ++#define I2C1_R 19477 ++#define I2C2_R 19478 ++#define I2C3_R 19479 ++#define I2C5_R 19480 ++#define SPDIF_R 19482 ++#define CEC_R 19483 ++#define DAC12_R 19485 ++#define MDIO_R 19847 ++#define TIM1_R 19520 ++#define TIM8_R 19521 ++#define TIM15_R 19522 ++#define TIM16_R 19523 ++#define TIM17_R 19524 ++#define SPI1_R 19528 ++#define SPI4_R 19529 ++#define SPI5_R 19530 ++#define USART6_R 19533 ++#define SAI1_R 19536 ++#define SAI2_R 19537 ++#define SAI3_R 19538 ++#define DFSDM_R 19540 ++#define FDCAN_R 19544 ++#define LPTIM2_R 19584 ++#define LPTIM3_R 19585 ++#define LPTIM4_R 19586 ++#define LPTIM5_R 19587 ++#define SAI4_R 19592 ++#define SYSCFG_R 19595 ++#define VREF_R 19597 ++#define TMPSENS_R 19600 ++#define PMBCTRL_R 19601 ++#define DMA1_R 19648 ++#define DMA2_R 19649 ++#define DMAMUX_R 19650 ++#define ADC12_R 19653 ++#define USBO_R 19656 ++#define SDMMC3_R 19664 ++#define CAMITF_R 19712 ++#define CRYP2_R 19716 ++#define HASH2_R 19717 ++#define RNG2_R 19718 ++#define CRC2_R 19719 ++#define HSEM_R 19723 ++#define MBOX_R 19724 ++#define GPIOA_R 19776 ++#define GPIOB_R 19777 ++#define GPIOC_R 19778 ++#define GPIOD_R 19779 ++#define GPIOE_R 19780 ++#define GPIOF_R 19781 ++#define GPIOG_R 19782 ++#define GPIOH_R 19783 ++#define GPIOI_R 19784 ++#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 ++#define RST_SCMI0_MCU_HOLD_BOOT 11 ++ ++#endif /* _DT_BINDINGS_STM32MP15_RESET_H_ */ +diff --git a/include/dt-bindings/soc/st,stm32-etzpc.h b/include/dt-bindings/soc/st,stm32-etzpc.h +index 3f9fb3b12..199c83154 100644 +--- a/include/dt-bindings/soc/st,stm32-etzpc.h ++++ b/include/dt-bindings/soc/st,stm32-etzpc.h +@@ -17,4 +17,90 @@ + #define DECPROT_UNLOCK 0x0 + #define DECPROT_LOCK 0x1 + ++/* ETZPC ID */ ++#define STM32MP1_ETZPC_STGENC_ID 0 ++#define STM32MP1_ETZPC_BKPSRAM_ID 1 ++#define STM32MP1_ETZPC_IWDG1_ID 2 ++#define STM32MP1_ETZPC_USART1_ID 3 ++#define STM32MP1_ETZPC_SPI6_ID 4 ++#define STM32MP1_ETZPC_I2C4_ID 5 ++#define STM32MP1_ETZPC_RNG1_ID 7 ++#define STM32MP1_ETZPC_HASH1_ID 8 ++#define STM32MP1_ETZPC_CRYP1_ID 9 ++#define STM32MP1_ETZPC_DDRCTRL_ID 10 ++#define STM32MP1_ETZPC_DDRPHYC_ID 11 ++#define STM32MP1_ETZPC_I2C6_ID 12 ++#define STM32MP1_ETZPC_TIM2_ID 16 ++#define STM32MP1_ETZPC_TIM3_ID 17 ++#define STM32MP1_ETZPC_TIM4_ID 18 ++#define STM32MP1_ETZPC_TIM5_ID 19 ++#define STM32MP1_ETZPC_TIM6_ID 20 ++#define STM32MP1_ETZPC_TIM7_ID 21 ++#define STM32MP1_ETZPC_TIM12_ID 22 ++#define STM32MP1_ETZPC_TIM13_ID 23 ++#define STM32MP1_ETZPC_TIM14_ID 24 ++#define STM32MP1_ETZPC_LPTIM1_ID 25 ++#define STM32MP1_ETZPC_WWDG1_ID 26 ++#define STM32MP1_ETZPC_SPI2_ID 27 ++#define STM32MP1_ETZPC_SPI3_ID 28 ++#define STM32MP1_ETZPC_SPDIFRX_ID 29 ++#define STM32MP1_ETZPC_USART2_ID 30 ++#define STM32MP1_ETZPC_USART3_ID 31 ++#define STM32MP1_ETZPC_UART4_ID 32 ++#define STM32MP1_ETZPC_UART5_ID 33 ++#define STM32MP1_ETZPC_I2C1_ID 34 ++#define STM32MP1_ETZPC_I2C2_ID 35 ++#define STM32MP1_ETZPC_I2C3_ID 36 ++#define STM32MP1_ETZPC_I2C5_ID 37 ++#define STM32MP1_ETZPC_CEC_ID 38 ++#define STM32MP1_ETZPC_DAC_ID 39 ++#define STM32MP1_ETZPC_UART7_ID 40 ++#define STM32MP1_ETZPC_UART8_ID 41 ++#define STM32MP1_ETZPC_MDIOS_ID 44 ++#define STM32MP1_ETZPC_TIM1_ID 48 ++#define STM32MP1_ETZPC_TIM8_ID 49 ++#define STM32MP1_ETZPC_USART6_ID 51 ++#define STM32MP1_ETZPC_SPI1_ID 52 ++#define STM32MP1_ETZPC_SPI4_ID 53 ++#define STM32MP1_ETZPC_TIM15_ID 54 ++#define STM32MP1_ETZPC_TIM16_ID 55 ++#define STM32MP1_ETZPC_TIM17_ID 56 ++#define STM32MP1_ETZPC_SPI5_ID 57 ++#define STM32MP1_ETZPC_SAI1_ID 58 ++#define STM32MP1_ETZPC_SAI2_ID 59 ++#define STM32MP1_ETZPC_SAI3_ID 60 ++#define STM32MP1_ETZPC_DFSDM_ID 61 ++#define STM32MP1_ETZPC_TT_FDCAN_ID 62 ++#define STM32MP1_ETZPC_LPTIM2_ID 64 ++#define STM32MP1_ETZPC_LPTIM3_ID 65 ++#define STM32MP1_ETZPC_LPTIM4_ID 66 ++#define STM32MP1_ETZPC_LPTIM5_ID 67 ++#define STM32MP1_ETZPC_SAI4_ID 68 ++#define STM32MP1_ETZPC_VREFBUF_ID 69 ++#define STM32MP1_ETZPC_DCMI_ID 70 ++#define STM32MP1_ETZPC_CRC2_ID 71 ++#define STM32MP1_ETZPC_ADC_ID 72 ++#define STM32MP1_ETZPC_HASH2_ID 73 ++#define STM32MP1_ETZPC_RNG2_ID 74 ++#define STM32MP1_ETZPC_CRYP2_ID 75 ++#define STM32MP1_ETZPC_SRAM1_ID 80 ++#define STM32MP1_ETZPC_SRAM2_ID 81 ++#define STM32MP1_ETZPC_SRAM3_ID 82 ++#define STM32MP1_ETZPC_SRAM4_ID 83 ++#define STM32MP1_ETZPC_RETRAM_ID 84 ++#define STM32MP1_ETZPC_OTG_ID 85 ++#define STM32MP1_ETZPC_SDMMC3_ID 86 ++#define STM32MP1_ETZPC_DLYBSD3_ID 87 ++#define STM32MP1_ETZPC_DMA1_ID 88 ++#define STM32MP1_ETZPC_DMA2_ID 89 ++#define STM32MP1_ETZPC_DMAMUX_ID 90 ++#define STM32MP1_ETZPC_FMC_ID 91 ++#define STM32MP1_ETZPC_QSPI_ID 92 ++#define STM32MP1_ETZPC_DLYBQ_ID 93 ++#define STM32MP1_ETZPC_ETH_ID 94 ++ ++#define STM32MP1_ETZPC_MAX_ID 96 ++ ++#define DECPROT(id, mode, lock) (((id) << 16) | ((mode) << 8) | (lock)) ++ + #endif /* _DT_BINDINGS_STM32_ETZPC_H */ +diff --git a/include/dt-bindings/soc/stm32mp13-mce.h b/include/dt-bindings/soc/stm32mp13-mce.h +new file mode 100644 +index 000000000..15006fc61 +--- /dev/null ++++ b/include/dt-bindings/soc/stm32mp13-mce.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ ++/* ++ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved ++ */ ++ ++#ifndef _DT_BINDINGS_STM32MP13_MCE_H ++#define _DT_BINDINGS_STM32MP13_MCE_H ++ ++#define MCE_PLAINTEXT U(0) ++#define MCE_ENCRYPT U(1) ++ ++#endif /* _DT_BINDINGS_STM32MP13_MCE_H */ +diff --git a/include/dt-bindings/soc/stm32mp13-tzc400.h b/include/dt-bindings/soc/stm32mp13-tzc400.h +new file mode 100644 +index 000000000..47c1761f7 +--- /dev/null ++++ b/include/dt-bindings/soc/stm32mp13-tzc400.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ ++/* ++ * Copyright (C) 2020-2021, STMicroelectronics - All Rights Reserved ++ */ ++ ++#ifndef _DT_BINDINGS_STM32MP13_TZC400_H ++#define _DT_BINDINGS_STM32MP13_TZC400_H ++ ++#include ++ ++#define STM32MP1_TZC_A7_ID U(0) ++#define STM32MP1_TZC_LCD_ID U(3) ++#define STM32MP1_TZC_MDMA_ID U(5) ++#define STM32MP1_TZC_DMA_ID U(6) ++#define STM32MP1_TZC_USB_HOST_ID U(7) ++#define STM32MP1_TZC_USB_OTG_ID U(8) ++#define STM32MP1_TZC_SDMMC_ID U(9) ++#define STM32MP1_TZC_ETH_ID U(10) ++#define STM32MP1_TZC_DCMIPP_ID U(11) ++#define STM32MP1_TZC_DAP_ID U(15) ++ ++#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ ++ (TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \ ++ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \ ++ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_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_DCMIPP_ID) | \ ++ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)) ++ ++#endif /* _DT_BINDINGS_STM32MP13_TZC400_H */ +diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h +index 6f8da0d78..ff51c6c4d 100644 +--- a/include/lib/fconf/fconf_dyn_cfg_getter.h ++++ b/include/lib/fconf/fconf_dyn_cfg_getter.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019-2020, Arm Limited. All rights reserved. ++ * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -9,6 +9,8 @@ + + #include + ++#define FCONF_INVALID_IDX 0xFFFFFFFFU ++ + /* Dynamic configuration related getter */ + #define dyn_cfg__dtb_getter(id) dyn_cfg_dtb_info_getter(id) + +@@ -18,6 +20,7 @@ struct dyn_cfg_dtb_info_t { + unsigned int config_id; + }; + ++unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id); + struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id); + int fconf_populate_dtb_registry(uintptr_t config); + +diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h +index b56e98b5f..9f2a80ebe 100644 +--- a/include/lib/psci/psci.h ++++ b/include/lib/psci/psci.h +@@ -349,6 +349,7 @@ int psci_node_hw_state(u_register_t target_cpu, + int psci_features(unsigned int psci_fid); + void __dead2 psci_power_down_wfi(void); + void psci_arch_setup(void); ++unsigned int psci_is_last_on_cpu(void); + + #endif /*__ASSEMBLER__*/ + +diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h +index 7a7012d3d..c005d6e3d 100644 +--- a/include/lib/utils_def.h ++++ b/include/lib/utils_def.h +@@ -64,6 +64,16 @@ + ((val) + _div - (__typeof__(div)) 1) / _div; \ + }) + ++/* ++ * Macro for unsigned integer division with nearest rounding variant. ++ * Default integer division rounds down. ++ */ ++#define udiv_round_nearest(x, y) __extension__ ({ \ ++ __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); \ +diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h +index 3fa63f555..1a9b9b5d2 100644 +--- a/include/plat/common/platform.h ++++ b/include/plat/common/platform.h +@@ -113,6 +113,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); ++#if AARCH32_EXCEPTION_DEBUG ++void plat_report_undef_inst(unsigned int fault_address); ++void plat_report_prefetch_abort(unsigned int fault_address); ++void plat_report_data_abort(unsigned int fault_address); ++#endif + int plat_crash_console_init(void); + int plat_crash_console_putc(int c); + void plat_crash_console_flush(void); +@@ -120,7 +125,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 MEASURED_BOOT + int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data); +@@ -311,6 +316,8 @@ int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr); + int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr); + int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc, + unsigned int nv_ctr); ++int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, ++ void **hashed_pk_ptr, unsigned int *hash_pk_len); + int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size); + int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key, + size_t *key_len, unsigned int *flags, +@@ -379,6 +386,7 @@ int32_t plat_is_smccc_feature_available(u_register_t fid); + int plat_fwu_set_metadata_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +-void plat_fwu_set_images_source(struct fwu_metadata *metadata); ++void plat_fwu_set_images_source(const struct fwu_metadata *metadata); ++uint32_t plat_fwu_get_boot_idx(void); + + #endif /* PLATFORM_H */ +diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S +index 8b16f93cc..59e15bd1c 100644 +--- a/lib/aarch32/misc_helpers.S ++++ b/lib/aarch32/misc_helpers.S +@@ -301,9 +301,9 @@ func fixup_gdt_reloc + cmp r4, r6 + blo 2f + +- /* Skip adding offset if address is >= upper limit */ ++ /* Skip adding offset if address is > upper limit */ + cmp r4, r7 +- bhs 2f ++ bhi 2f + + add r4, r0, r4 + str r4, [r3] +diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S +index 6e4d1fc30..01531ca22 100644 +--- a/lib/aarch64/misc_helpers.S ++++ b/lib/aarch64/misc_helpers.S +@@ -532,9 +532,9 @@ func fixup_gdt_reloc + cmp x3, x6 + b.lo 2f + +- /* Skip adding offset if address is >= upper limit */ ++ /* Skip adding offset if address is > upper limit */ + cmp x3, x7 +- b.hs 2f ++ b.hi 2f + add x3, x3, x0 + str x3, [x1] + +@@ -582,9 +582,9 @@ func fixup_gdt_reloc + cmp x4, x6 + b.lo 2f + +- /* Skip adding offset if r_addend entry is >= upper limit */ ++ /* Skip adding offset if r_addend entry is > upper limit */ + cmp x4, x7 +- b.hs 2f ++ b.hi 2f + + add x4, x0, x4 /* Diff(S) + r_addend */ + str x4, [x3] +diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c +index 25dd7f9ed..34623fbd4 100644 +--- a/lib/fconf/fconf_dyn_cfg_getter.c ++++ b/lib/fconf/fconf_dyn_cfg_getter.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019-2020, Arm Limited. All rights reserved. ++ * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -40,17 +40,30 @@ void set_config_info(uintptr_t config_addr, uint32_t config_max_size, + dtb_info->config_id = config_id; + } + +-struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id) ++/* Get index of the config_id image */ ++unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id) + { + unsigned int index; + + /* Positions index to the proper config-id */ + for (index = 0U; index < MAX_DTB_INFO; index++) { + if (dtb_infos[index].config_id == config_id) { +- return &dtb_infos[index]; ++ return index; + } + } + ++ return FCONF_INVALID_IDX; ++} ++ ++struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id) ++{ ++ /* Positions index to the proper config-id */ ++ unsigned int index = dyn_cfg_dtb_info_get_index(config_id); ++ ++ if (index < MAX_DTB_INFO) { ++ return &dtb_infos[index]; ++ } ++ + WARN("FCONF: Invalid config id %u\n", config_id); + + return NULL; +diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h +index 72bd6bd11..0f55e8504 100644 +--- a/lib/psci/psci_private.h ++++ b/lib/psci/psci_private.h +@@ -291,7 +291,6 @@ unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info); + unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info); + void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl); + void psci_print_power_domain_map(void); +-unsigned int psci_is_last_on_cpu(void); + int psci_spd_migrate_info(u_register_t *mpidr); + void psci_do_pwrdown_sequence(unsigned int power_level); + +diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk +index 12aaee684..2108570b9 100644 +--- a/make_helpers/build_macros.mk ++++ b/make_helpers/build_macros.mk +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -144,6 +144,13 @@ $(2): $(1) enctool + $$(Q)$$(ENCTOOL) $$(ENC_ARGS) -i $$< -o $$@ + endef + ++# GEN_METADATA ++define GEN_METADATA ++$(2): $(1) | $(dir $(2)) ++ $$(ECHO) " GEN_METADATA $$<" ++ $$(Q)$$(FWUMDTOOL) $$(FWUMD_ARGS) jsonparse $$< -b $$@ ++endef ++ + # TOOL_ADD_PAYLOAD appends the command line arguments required by fiptool to + # package a new payload and/or by cert_create to generate certificate. + # Optionally, it adds the dependency on this payload +diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk +index e88148f4e..01bbb40f7 100644 +--- a/make_helpers/defaults.mk ++++ b/make_helpers/defaults.mk +@@ -148,6 +148,9 @@ ENC_KEY := 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + # Default dummy nonce for firmware encryption + ENC_NONCE := 1234567890abcdef12345678 + ++# Flag to enable exception debug for AARCH32 ++AARCH32_EXCEPTION_DEBUG := 0 ++ + # Build flag to treat usage of deprecated platform and framework APIs as error. + ERROR_DEPRECATED := 0 + +@@ -318,6 +321,10 @@ AMU_RESTRICT_COUNTERS := 0 + + # Enable SVE for non-secure world by default + ENABLE_SVE_FOR_NS := 1 ++# SVE is only supported on AArch64 so disable it on AArch32. ++ifeq (${ARCH},aarch32) ++ override ENABLE_SVE_FOR_NS := 0 ++endif + ENABLE_SVE_FOR_SWD := 0 + + # SME defaults to disabled +@@ -359,9 +366,6 @@ RAS_TRAP_LOWER_EL_ERR_ACCESS := 0 + # Build option to create cot descriptors using fconf + COT_DESC_IN_DTB := 0 + +-# Build option to provide openssl directory path +-OPENSSL_DIR := /usr +- + # Build option to use the SP804 timer instead of the generic one + USE_SP804_TIMER := 0 + +diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c +index 387086a29..19ee1b0b0 100644 +--- a/plat/arm/common/arm_io_storage.c ++++ b/plat/arm/common/arm_io_storage.c +@@ -217,7 +217,7 @@ void arm_set_fip_addr(uint32_t active_fw_bank_idx) + * bank to get its offset and length, and update these details in the I/O policy + * of the FIP image. + ******************************************************************************/ +-void plat_fwu_set_images_source(struct fwu_metadata *metadata) ++void plat_fwu_set_images_source(const struct fwu_metadata *metadata) + { + arm_set_fip_addr(metadata->active_index); + } +diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S +index 5b9cb5914..d2c20b4a7 100644 +--- a/plat/common/aarch32/platform_helpers.S ++++ b/plat/common/aarch32/platform_helpers.S +@@ -8,6 +8,11 @@ + #include + + .weak plat_report_exception ++#if AARCH32_EXCEPTION_DEBUG ++ .weak plat_report_undef_inst ++ .weak plat_report_prefetch_abort ++ .weak plat_report_data_abort ++#endif + .weak plat_reset_handler + .weak plat_disable_acp + .weak bl1_plat_prepare_exit +@@ -23,6 +28,35 @@ func plat_report_exception + bx lr + endfunc plat_report_exception + ++#if AARCH32_EXCEPTION_DEBUG ++ /* ----------------------------------------------------- ++ * Placeholder function which should be redefined by ++ * each platform. ++ * ----------------------------------------------------- ++ */ ++func plat_report_undef_inst ++ bx lr ++endfunc plat_report_undef_inst ++ ++ /* ----------------------------------------------------- ++ * Placeholder function which should be redefined by ++ * each platform. ++ * ----------------------------------------------------- ++ */ ++func plat_report_prefetch_abort ++ bx lr ++endfunc plat_report_prefetch_abort ++ ++ /* ----------------------------------------------------- ++ * Placeholder function which should be redefined by ++ * each platform. ++ * ----------------------------------------------------- ++ */ ++func plat_report_data_abort ++ bx lr ++endfunc plat_report_data_abort ++#endif ++ + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. +diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c +index 89b77ba6c..5bbd73bd9 100644 +--- a/plat/common/plat_bl_common.c ++++ b/plat/common/plat_bl_common.c +@@ -69,7 +69,7 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + return 0; + } + +-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 +index b0314d2ab..2d2150cf4 100644 +--- a/plat/st/common/bl2_io_storage.c ++++ b/plat/st/common/bl2_io_storage.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -10,13 +10,17 @@ + #include + #include + #include ++#include ++#include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -34,7 +38,9 @@ + + #include + #include ++#include + #include ++#include + #include + + /* IO devices */ +@@ -42,6 +48,12 @@ uintptr_t fip_dev_handle; + uintptr_t storage_dev_handle; + + static const io_dev_connector_t *fip_dev_con; ++static uint32_t nand_bkp_offset; ++ ++#ifndef DECRYPTION_SUPPORT_none ++static const io_dev_connector_t *enc_dev_con; ++uintptr_t enc_dev_handle; ++#endif + + #if STM32MP_SDMMC || STM32MP_EMMC + static struct mmc_device_info mmc_info; +@@ -99,7 +111,7 @@ static io_mtd_dev_spec_t spi_nand_dev_spec = { + static const io_dev_connector_t *spi_dev_con; + #endif + +-#if STM32MP_USB_PROGRAMMER ++#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + static const io_dev_connector_t *memmap_dev_con; + #endif + +@@ -113,6 +125,29 @@ int open_fip(const uintptr_t spec) + return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + } + ++#ifndef DECRYPTION_SUPPORT_none ++int open_enc_fip(const uintptr_t spec) ++{ ++ int result; ++ uintptr_t local_image_handle; ++ ++ result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID); ++ if (result != 0) { ++ return result; ++ } ++ ++ result = io_open(enc_dev_handle, spec, &local_image_handle); ++ if (result != 0) { ++ return result; ++ } ++ ++ VERBOSE("Using encrypted FIP\n"); ++ io_close(local_image_handle); ++ ++ return 0; ++} ++#endif ++ + int open_storage(const uintptr_t spec) + { + return io_dev_init(storage_dev_handle, 0); +@@ -136,6 +171,9 @@ static void print_boot_device(boot_api_context_t *boot_context) + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + INFO("Using SPI NAND\n"); + break; ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++ INFO("Using UART\n"); ++ break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + INFO("Using USB\n"); + break; +@@ -182,6 +220,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 = &mmc_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); +@@ -235,6 +277,8 @@ static void boot_fmc2_nand(boot_api_context_t *boot_context) + io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); ++ ++ nand_bkp_offset = nand_dev_spec.erase_size; + } + #endif /* STM32MP_RAW_NAND */ + +@@ -254,10 +298,12 @@ static void boot_spi_nand(boot_api_context_t *boot_context) + (uintptr_t)&spi_nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); ++ ++ nand_bkp_offset = spi_nand_dev_spec.erase_size; + } + #endif /* STM32MP_SPI_NAND */ + +-#if STM32MP_USB_PROGRAMMER ++#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + static void mmap_io_setup(void) + { + int io_result __unused; +@@ -270,6 +316,21 @@ static void mmap_io_setup(void) + assert(io_result == 0); + } + ++#if STM32MP_UART_PROGRAMMER ++static void stm32cubeprogrammer_uart(void) ++{ ++ int ret __unused; ++ boot_api_context_t *boot_context = ++ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); ++ uintptr_t uart_base; ++ ++ uart_base = get_uart_address(boot_context->boot_interface_instance); ++ ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE); ++ assert(ret == 0); ++} ++#endif ++ ++#if STM32MP_USB_PROGRAMMER + static void stm32cubeprogrammer_usb(void) + { + int ret __unused; +@@ -282,6 +343,8 @@ static void stm32cubeprogrammer_usb(void) + assert(ret == 0); + } + #endif ++#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */ ++ + + void stm32mp_io_setup(void) + { +@@ -303,6 +366,15 @@ void stm32mp_io_setup(void) + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + ++#ifndef DECRYPTION_SUPPORT_none ++ io_result = register_io_dev_enc(&enc_dev_con); ++ assert(io_result == 0); ++ ++ io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL, ++ &enc_dev_handle); ++ assert(io_result == 0); ++#endif ++ + switch (boot_context->boot_interface_selected) { + #if STM32MP_SDMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: +@@ -334,8 +406,13 @@ void stm32mp_io_setup(void) + boot_spi_nand(boot_context); + break; + #endif ++#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER ++#if STM32MP_UART_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++#endif + #if STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: ++#endif + dmbsy(); + mmap_io_setup(); + break; +@@ -359,19 +436,32 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id) + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + if (!gpt_init_done) { ++/* ++ * With FWU Multi Bank feature enabled, the selection of ++ * the image to boot will be done by fwu_init calling the ++ * platform hook, plat_fwu_set_images_source. ++ */ ++#if !PSA_FWU_SUPPORT + const partition_entry_t *entry; ++ const struct efi_guid img_type_guid = STM32MP_FIP_GUID; ++ uuid_t img_type_uuid; + ++ guidcpy(&img_type_uuid, &img_type_guid); + partition_init(GPT_IMAGE_ID); +- entry = get_partition_entry(FIP_IMAGE_NAME); ++ entry = get_partition_entry_by_type(&img_type_uuid); + if (entry == NULL) { +- ERROR("Could NOT find the %s partition!\n", +- FIP_IMAGE_NAME); +- return -ENOENT; ++ entry = get_partition_entry(FIP_IMAGE_NAME); ++ if (entry == NULL) { ++ ERROR("Could NOT find the %s partition!\n", ++ FIP_IMAGE_NAME); ++ ++ return -ENOENT; ++ } + } + + image_block_spec.offset = entry->start; + image_block_spec.length = entry->length; +- ++#endif + gpt_init_done = true; + } else { + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +@@ -396,10 +486,27 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id) + + #if STM32MP_SPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: ++/* ++ * With FWU Multi Bank feature enabled, the selection of ++ * the image to boot will be done by fwu_init calling the ++ * platform hook, plat_fwu_set_images_source. ++ */ ++#if !PSA_FWU_SUPPORT + image_block_spec.offset = STM32MP_NOR_FIP_OFFSET; ++#endif + break; + #endif + ++#if STM32MP_UART_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++ if (image_id == FW_CONFIG_ID) { ++ stm32cubeprogrammer_uart(); ++ /* FIP loaded at DWL address */ ++ image_block_spec.offset = DWL_BUFFER_BASE; ++ image_block_spec.length = DWL_BUFFER_SIZE; ++ } ++ break; ++#endif + #if STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + if (image_id == FW_CONFIG_ID) { +@@ -438,3 +545,193 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + + return rc; + } ++ ++/* ++ * This function shall return 0 if it cannot find an alternate ++ * image to be loaded or it returns 1 otherwise. ++ */ ++int plat_try_next_boot_source(unsigned int image_id) ++{ ++ static unsigned int backup_id; ++ static unsigned int backup_nb; ++ ++ /* No backup available */ ++ if (nand_bkp_offset == 0U) { ++ return 0; ++ } ++ ++ if (backup_id != image_id) { ++ backup_nb = 0; ++ backup_id = image_id; ++ } ++ ++ backup_nb++; ++ ++ if (backup_nb >= PLATFORM_MTD_BACKUP_BLOCKS) { ++ return 0; ++ } ++ ++ image_block_spec.offset += nand_bkp_offset; ++ ++ return 1; ++} ++ ++#if PSA_FWU_SUPPORT ++/* ++ * In each boot in non-trial mode, we set the BKP register to ++ * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata. ++ * ++ * As long as the update agent didn't update the "accepted" field in metadata ++ * (ie we are in trial mode), we select the new active_index. ++ * To avoid infinite boot loop at trial boot we decrement a BKP register. ++ * If this counter is 0: ++ * - an unexpected TAMPER event raised (that resets the BKP registers to 0) ++ * - a power-off occurs before the update agent was able to update the ++ * "accepted' field ++ * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode. ++ * we select the previous_active_index. ++ */ ++#define INVALID_BOOT_IDX 0xFFFFFFFF ++ ++uint32_t plat_fwu_get_boot_idx(void) ++{ ++ /* ++ * Need to memoize the boot_idx, as this function is call twice, ++ * and double call has an effect on returned value. ++ */ ++ static uint32_t memoize_boot_idx = INVALID_BOOT_IDX; ++ const struct fwu_metadata *data; ++ ++ data = fwu_get_metadata(); ++ ++ if (memoize_boot_idx == INVALID_BOOT_IDX) { ++ memoize_boot_idx = data->active_index; ++ if (fwu_is_trial_run_state()) { ++ if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) { ++ WARN("Trial FWU fails to many times"); ++ memoize_boot_idx = data->previous_active_index; ++ } ++ } else { ++ stm32_set_max_fwu_trial_boot_cnt(); ++ } ++ } ++ ++ return memoize_boot_idx; ++} ++ ++static void *stm32_get_image_spec(const uuid_t *img_type_uuid) ++{ ++ unsigned int i; ++ ++ for (i = 0U; i < MAX_NUMBER_IDS; i++) { ++ if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) { ++ return (void *)policies[i].image_spec; ++ } ++ } ++ ++ return NULL; ++} ++ ++void plat_fwu_set_images_source(const struct fwu_metadata *metadata) ++{ ++ unsigned int i; ++ uint32_t boot_idx; ++ const partition_entry_t *entry __unused; ++ const uuid_t *img_type_uuid, *img_uuid; ++ io_block_spec_t *image_spec; ++ ++ boot_idx = plat_fwu_get_boot_idx(); ++ assert(boot_idx < NR_OF_FW_BANKS); ++ ++ for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ img_type_uuid = &metadata->img_entry[i].img_type_uuid; ++ ++ img_uuid = &metadata->img_entry[i].img_props[boot_idx].img_uuid; ++ ++ image_spec = stm32_get_image_spec(img_type_uuid); ++ if (image_spec == NULL) { ++ ERROR("Unable to get image spec for the image in the metadata\n"); ++ panic(); ++ } ++ ++#if (STM32MP_SDMMC || STM32MP_EMMC) ++ entry = get_partition_entry_by_uuid(img_uuid); ++ if (entry == NULL) { ++ ERROR("Unable to find the partition with the uuid mentioned in metadata\n"); ++ panic(); ++ } ++ ++ image_spec->offset = entry->start; ++ image_spec->length = entry->length; ++#endif ++#if STM32MP_SPI_NOR ++ if (guidcmp(img_uuid, &STM32MP_NOR_FIP_A_GUID) == 0) { ++ image_spec->offset = STM32MP_NOR_FIP_A_OFFSET; ++ } else if (guidcmp(img_uuid, &STM32MP_NOR_FIP_B_GUID) == 0) { ++ image_spec->offset = STM32MP_NOR_FIP_B_OFFSET; ++ } else { ++ ERROR("Invalid uuid mentioned in metadata\n"); ++ panic(); ++ } ++#endif ++#if (STM32MP_SPI_NAND || STM32MP_RAW_NAND) ++#error "FWU NAND not yet implemented" ++ panic(); ++#endif ++ } ++} ++ ++static int plat_set_image_source(unsigned int image_id, ++ uintptr_t *handle, ++ uintptr_t *image_spec) ++{ ++ struct plat_io_policy *policy; ++ io_block_spec_t *spec; ++ const partition_entry_t *entry __unused; ++ ++ policy = &policies[image_id]; ++ spec = (io_block_spec_t *)policy->image_spec; ++ ++#if (STM32MP_SDMMC || STM32MP_EMMC) ++ partition_init(GPT_IMAGE_ID); ++ ++ if (image_id == FWU_METADATA_IMAGE_ID) { ++ entry = get_partition_entry(METADATA_PART_1); ++ } else { ++ entry = get_partition_entry(METADATA_PART_2); ++ } ++ ++ if (entry == NULL) { ++ ERROR("Unable to find a metadata partition\n"); ++ return -ENOENT; ++ } ++ ++ spec->offset = entry->start; ++ spec->length = entry->length; ++#endif ++ ++#if STM32MP_SPI_NOR ++ if (image_id == FWU_METADATA_IMAGE_ID) { ++ spec->offset = STM32MP_NOR_METADATA1_OFFSET; ++ } else { ++ spec->offset = STM32MP_NOR_METADATA2_OFFSET; ++ } ++ ++ spec->length = sizeof(struct fwu_metadata); ++#endif ++ *image_spec = policy->image_spec; ++ *handle = *policy->dev_handle; ++ ++ return 0; ++} ++ ++int plat_fwu_set_metadata_image_source(unsigned int image_id, ++ uintptr_t *handle, ++ uintptr_t *image_spec) ++{ ++ assert((image_id == FWU_METADATA_IMAGE_ID) || ++ (image_id == BKUP_FWU_METADATA_IMAGE_ID)); ++ ++ return plat_set_image_source(image_id, handle, image_spec); ++} ++#endif /* PSA_FWU_SUPPORT */ +diff --git a/plat/st/common/bl2_stm32_io_storage.c b/plat/st/common/bl2_stm32_io_storage.c +deleted file mode 100644 +index 2d68a5028..000000000 +--- a/plat/st/common/bl2_stm32_io_storage.c ++++ /dev/null +@@ -1,665 +0,0 @@ +-/* +- * Copyright (c) 2015-2021, 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 +- +-#include +- +-/* IO devices */ +-#ifndef AARCH32_SP_OPTEE +-static const io_dev_connector_t *dummy_dev_con; +-static uintptr_t dummy_dev_handle; +-static uintptr_t dummy_dev_spec; +-#endif +- +-static uintptr_t image_dev_handle; +-static uintptr_t storage_dev_handle; +- +-#if STM32MP_SDMMC || STM32MP_EMMC +-static struct mmc_device_info mmc_info; +-static io_block_spec_t gpt_block_spec = { +- .offset = 0U, +- .length = 34U * 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, +-}; +- +-#if STM32MP_EMMC_BOOT +-static io_block_spec_t emmc_boot_ssbl_block_spec = { +- .offset = PLAT_EMMC_BOOT_SSBL_OFFSET, +- .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */ +-}; +- +-static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = { +- /* It's used as temp buffer in block driver */ +- .buffer = { +- .offset = (size_t)&block_buffer, +- .length = MMC_BLOCK_SIZE, +- }, +- .ops = { +- .read = mmc_boot_part_read_blocks, +- .write = NULL, +- }, +- .block_size = MMC_BLOCK_SIZE, +-}; +-#endif +- +-static struct io_mmc_dev_spec mmc_device_spec = { +- .use_boot_part = false, +-}; +- +-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 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 +- +-#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_core_partition_spec = { +- .name = OPTEE_CORE_IMAGE_NAME, +- .binary_type = OPTEE_CORE_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 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_CORE, +- IMG_IDX_OPTEE_PAGED, +-#endif +- IMG_IDX_NUM +-}; +- +-static struct stm32image_device_info stm32image_dev_info_spec __unused = { +- .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_CORE] = { +- .name = OPTEE_CORE_IMAGE_NAME, +- .binary_type = OPTEE_CORE_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 = 0U, +- .length = 0U, +-}; +- +-static const io_dev_connector_t *stm32image_dev_con __unused; +- +-#ifndef AARCH32_SP_OPTEE +-static int open_dummy(const uintptr_t spec); +-#endif +-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[] = { +-#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_core_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 +- }, +-#if STM32MP_SDMMC || STM32MP_EMMC +- [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 +- } +-}; +- +-#ifndef AARCH32_SP_OPTEE +-static int open_dummy(const uintptr_t spec) +-{ +- return io_dev_init(dummy_dev_handle, 0); +-} +-#endif +- +-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); +-} +- +-#if STM32MP_EMMC_BOOT +-static uint32_t get_boot_part_ssbl_header(void) +-{ +- uint32_t magic = 0U; +- int io_result; +- size_t bytes_read; +- +- 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_boot_part_spec, +- &storage_dev_handle); +- assert(io_result == 0); +- +- io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_ssbl_block_spec, +- &image_dev_handle); +- assert(io_result == 0); +- +- io_result = io_read(image_dev_handle, (uintptr_t)&magic, sizeof(magic), +- &bytes_read); +- assert(io_result == 0); +- assert(bytes_read == sizeof(magic)); +- +- io_result = io_dev_close(storage_dev_handle); +- assert(io_result == 0); +- +- return magic; +-} +-#endif +- +-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; +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: +- INFO("Using QSPI NOR\n"); +- break; +- 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; +- 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 stm32image_io_setup(void) +-{ +- int io_result __unused; +- +- 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); +-} +- +-#if STM32MP_SDMMC || STM32MP_EMMC +-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; +- struct stm32_sdmmc2_params params; +- const partition_entry_t *entry __unused; +- uint32_t magic __unused; +- +- zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); +- +- mmc_info.mmc_dev_type = mmc_dev_type; +- +- 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; +- } +- +- params.device_info = &mmc_info; +- if (stm32_sdmmc2_mmc_init(¶ms) != 0) { +- ERROR("SDMMC%u init failed\n", boot_interface_instance); +- panic(); +- } +- +- stm32image_dev_info_spec.device_size = +- stm32_sdmmc2_mmc_get_device_size(); +- +-#if STM32MP_EMMC_BOOT +- magic = get_boot_part_ssbl_header(); +- +- if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) { +- VERBOSE("%s, header found, jump to emmc load\n", __func__); +- idx = IMG_IDX_BL33; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET; +- part->bkp_offset = 0U; +- mmc_device_spec.use_boot_part = true; +- +- goto emmc_boot; +- } else { +- WARN("%s: Can't find STM32 header on a boot partition\n", __func__); +- } +-#endif +- +- /* 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); +- +- 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; +- } +- +-#if STM32MP_EMMC_BOOT +-emmc_boot: +-#endif +- /* +- * 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, (uintptr_t)&mmc_device_spec, +- &storage_dev_handle); +- assert(io_result == 0); +-} +-#endif /* STM32MP_SDMMC || STM32MP_EMMC */ +- +-#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_CORE; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NOR_TEEX_OFFSET; +- part->bkp_offset = 0U; +-#endif +-} +-#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_CORE; +- part = &stm32image_dev_info_spec.part_info[idx]; +- part->part_offset = STM32MP_NAND_TEEX_OFFSET; +- part->bkp_offset = nand_dev_spec.erase_size; +-#endif +-} +-#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_CORE; +- 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 +-} +-#endif /* STM32MP_SPI_NAND */ +- +-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%u\n", +- boot_context->boot_partition_used_toboot); +- } +- +-#ifndef AARCH32_SP_OPTEE +- 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); +-#endif +- +- switch (boot_context->boot_interface_selected) { +-#if STM32MP_SDMMC +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: +- dmbsy(); +- boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); +- stm32image_io_setup(); +- break; +-#endif +-#if STM32MP_EMMC +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: +- dmbsy(); +- boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); +- stm32image_io_setup(); +- break; +-#endif +-#if STM32MP_SPI_NOR +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: +- dmbsy(); +- boot_spi_nor(boot_context); +- stm32image_io_setup(); +- break; +-#endif +-#if STM32MP_RAW_NAND +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: +- dmbsy(); +- boot_fmc2_nand(boot_context); +- stm32image_io_setup(); +- break; +-#endif +-#if STM32MP_SPI_NAND +- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: +- dmbsy(); +- boot_spi_nand(boot_context); +- stm32image_io_setup(); +- break; +-#endif +- +- default: +- ERROR("Boot interface %d not supported\n", +- boot_context->boot_interface_selected); +- panic(); +- break; +- } +-} +- +-/* +- * 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/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h +index 503d91945..472b1af34 100644 +--- a/plat/st/common/include/stm32cubeprogrammer.h ++++ b/plat/st/common/include/stm32cubeprogrammer.h +@@ -15,6 +15,7 @@ + #define PHASE_FLASHLAYOUT 0U + #define PHASE_SSBL 3U + #define PHASE_CMD 0xF1U ++#define PHASE_SSP 0xF3U + #define PHASE_RESET 0xFFU + + /* Functions provided by plat */ +@@ -24,4 +25,18 @@ int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle, + uintptr_t ssbl_base, + size_t ssbl_len); + ++int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len); ++ ++int stm32cubeprog_usb_ssp(struct usb_handle *usb_core_handle, ++ uintptr_t cert_base, ++ size_t cert_len, ++ uintptr_t ssp_base, ++ size_t ssp_len); ++ ++int stm32cubeprog_uart_ssp(uintptr_t instance, ++ uintptr_t cert_base, ++ size_t cert_len, ++ uintptr_t ssp_base, ++ size_t ssp_len); ++ + #endif /* STM32CUBEPROGRAMMER_H */ +diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/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 +index 8a5fe48ad..ab8130fb2 100644 +--- a/plat/st/common/include/stm32mp_common.h ++++ b/plat/st/common/include/stm32mp_common.h +@@ -18,9 +18,11 @@ + void stm32mp_save_boot_ctx_address(uintptr_t address); + uintptr_t stm32mp_get_boot_ctx_address(void); + uint16_t stm32mp_get_boot_itf_selected(void); ++uint32_t stm32mp_get_boot_action(void); + + bool stm32mp_is_single_core(void); + bool stm32mp_is_closed_device(void); ++bool stm32mp_is_auth_supported(void); + + /* Return the base address of the DDR controller */ + uintptr_t stm32mp_ddrctrl_base(void); +@@ -34,9 +36,22 @@ uintptr_t stm32mp_pwr_base(void); + /* Return the base address of the RCC peripheral */ + uintptr_t stm32mp_rcc_base(void); + ++void stm32mp_gic_pcpu_init(void); ++void stm32mp_gic_init(void); ++int stm32mp_gic_enable_spi(int node, const char *name); ++ + /* 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); ++ ++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); + +@@ -48,6 +63,24 @@ 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 || !defined(IMAGE_BL2) ++/* Get the UART address from its instance number */ ++uintptr_t get_uart_address(uint32_t instance_nb); ++#endif ++ ++/* Setup the UART console */ ++int stm32mp_uart_console_setup(void); ++ ++#if STM32MP_EARLY_CONSOLE ++void stm32mp_setup_early_console(void); ++#else ++static inline void stm32mp_setup_early_console(void) ++{ ++} ++#endif ++ ++void stm32mp_set_console_after_standby(void); ++ + /* + * Platform util functions for the GPIO driver + * @bank: Target GPIO bank ID as per DT bindings +@@ -64,6 +97,7 @@ uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags); + uintptr_t stm32_get_gpio_bank_base(unsigned int bank); + unsigned long stm32_get_gpio_bank_clock(unsigned int bank); + uint32_t stm32_get_gpio_bank_offset(unsigned int bank); ++bool stm32_gpio_is_secure_at_reset(unsigned int bank); + + /* Return node offset for target GPIO bank ID @bank or a FDT error code */ + int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank); +@@ -83,30 +117,25 @@ void stm32mp_print_cpuinfo(void); + /* Print board information */ + void stm32mp_print_boardinfo(void); + +-/* +- * 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); +-void stm32mp_clk_enable(unsigned long id); +-void stm32mp_clk_disable(unsigned long id); +-unsigned long stm32mp_clk_get_rate(unsigned long id); ++/* Check HW CPU OPP support */ ++bool stm32mp_supports_cpu_opp(uint32_t opp_id); + + /* Initialise the IO layer and register platform IO devices */ + void stm32mp_io_setup(void); + +-#if STM32MP_USE_STM32IMAGE +-/* +- * Check that the STM32 header of a .stm32 binary image is valid +- * @param header: pointer to the stm32 image header +- * @param buffer: address of the binary image (payload) +- * @return: 0 on success, negative value in case of error +- */ +-int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer); +-#endif /* STM32MP_USE_STM32IMAGE */ +- + /* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */ + int stm32mp_map_ddr_non_cacheable(void); + int stm32mp_unmap_ddr(void); + ++/* Functions to save and get boot peripheral info */ ++void stm32_save_boot_interface(uint32_t interface, uint32_t instance); ++void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance); ++bool stm32_boot_is_serial(void); ++ ++#if PSA_FWU_SUPPORT ++void stm32mp1_fwu_set_boot_idx(void); ++uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void); ++void stm32_set_max_fwu_trial_boot_cnt(void); ++#endif /* PSA_FWU_SUPPORT */ ++ + #endif /* STM32MP_COMMON_H */ +diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h +index f7201c0d9..0170f3a73 100644 +--- a/plat/st/common/include/stm32mp_dt.h ++++ b/plat/st/common/include/stm32mp_dt.h +@@ -11,6 +11,8 @@ + #include + #include + ++#include ++ + #define DT_DISABLED U(0) + #define DT_NON_SECURE U(1) + #define DT_SECURE U(2) +@@ -30,14 +32,23 @@ int dt_open_and_check(uintptr_t dt_addr); + 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); + 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_match_instance_by_compatible(const char *compatible, uintptr_t address); + uint32_t dt_get_ddr_size(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); ++struct rdev *dt_get_vdd_regulator(void); ++struct rdev *dt_get_cpu_regulator(void); ++struct rdev *dt_get_usb_phy_regulator(void); + const char *dt_get_board_model(void); ++int dt_find_otp_name(const char *name, uint32_t *otp, uint32_t *otp_len); + int fdt_get_gpio_bank_pin_count(unsigned int bank); + + #endif /* STM32MP_DT_H */ +diff --git a/plat/st/common/include/stm32mp_efi.h b/plat/st/common/include/stm32mp_efi.h +new file mode 100644 +index 000000000..490560ff3 +--- /dev/null ++++ b/plat/st/common/include/stm32mp_efi.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2021, Linaro Limited ++ */ ++ ++#ifndef STM32MP_EFI_H ++#define STM32MP_EFI_H ++ ++#include ++ ++#define STM32MP_FIP_GUID \ ++ EFI_GUID(0x19d5df83, 0x11b0, 0x457b, \ ++ 0xbe, 0x2c, 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) ++ ++#endif /* STM32MP_EFI_H */ +diff --git a/plat/st/common/include/stm32mp_fconf_getter.h b/plat/st/common/include/stm32mp_fconf_getter.h +index 3a8bb11a4..18884ae06 100644 +--- a/plat/st/common/include/stm32mp_fconf_getter.h ++++ b/plat/st/common/include/stm32mp_fconf_getter.h +@@ -10,6 +10,7 @@ + #include + + #include ++#include + + /* IO policies */ + #define stm32mp__io_policies_getter(id) __extension__ ({ \ +@@ -20,6 +21,7 @@ + struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; ++ struct efi_guid img_type_guid; + int (*check)(const uintptr_t spec); + }; + +diff --git a/plat/st/common/include/stm32mp_io_storage.h b/plat/st/common/include/stm32mp_io_storage.h +index 989c890d4..677a2ebb5 100644 +--- a/plat/st/common/include/stm32mp_io_storage.h ++++ b/plat/st/common/include/stm32mp_io_storage.h +@@ -13,11 +13,15 @@ + /* IO devices handle */ + extern uintptr_t storage_dev_handle; + extern uintptr_t fip_dev_handle; ++extern uintptr_t enc_dev_handle; + + extern io_block_spec_t image_block_spec; + + /* Function declarations */ + int open_fip(const uintptr_t spec); ++#ifndef DECRYPTION_SUPPORT_none ++int open_enc_fip(const uintptr_t spec); ++#endif + int open_storage(const uintptr_t spec); + + #endif /* STM32MP_IO_STORAGE_H */ +diff --git a/plat/st/common/include/stm32mp_shres_helpers.h b/plat/st/common/include/stm32mp_shres_helpers.h +index 8b786cc04..8b048284c 100644 +--- a/plat/st/common/include/stm32mp_shres_helpers.h ++++ b/plat/st/common/include/stm32mp_shres_helpers.h +@@ -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); + + #endif /* STM32MP_SHRES_HELPERS_H */ +diff --git a/plat/st/common/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c +new file mode 100644 +index 000000000..a993afdbf +--- /dev/null ++++ b/plat/st/common/stm32cubeprogrammer_uart.c +@@ -0,0 +1,661 @@ ++/* ++ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* USART bootloader protocol version V4.0 */ ++#define USART_BL_VERSION 0x40U ++ ++/* Command definition */ ++#define GET_CMD_COMMAND 0x00U ++#define GET_VER_COMMAND 0x01U ++#define GET_ID_COMMAND 0x02U ++#define PHASE_COMMAND 0x03U ++#define READ_PART_COMMAND 0x12U ++#define START_COMMAND 0x21U ++#define DOWNLOAD_COMMAND 0x31U ++ ++/* Answer defines */ ++#define INIT_BYTE 0x7FU ++#define ACK_BYTE 0x79U ++#define NACK_BYTE 0x1FU ++#define ABORT 0x5FU ++ ++#define UNDEFINED_DOWN_ADDR U(0xFFFFFFFF) ++#define PROGRAMMER_TIMEOUT_US 20000U ++ ++static const uint8_t command_tab[] = { ++ GET_CMD_COMMAND, ++ GET_VER_COMMAND, ++ GET_ID_COMMAND, ++ PHASE_COMMAND, ++#if STM32MP_SSP ++ READ_PART_COMMAND, ++#endif ++ START_COMMAND, ++ DOWNLOAD_COMMAND ++}; ++ ++/* STM32CubeProgrammer over UART handle */ ++struct stm32prog_uart_handle_s { ++ struct stm32_uart_handle_s uart; ++ uint32_t packet; ++ uint8_t *addr; ++ uint32_t len; ++ uint8_t phase; ++#if STM32MP_SSP ++ uintptr_t cert_base; ++ size_t cert_len; ++#endif ++ /* Error msg buffer: max 255 in UART protocol, reduced in TF-A */ ++ uint8_t error[64]; ++} handle; ++ ++/* Trace and handle unrecoverable UART protocol error */ ++#define STM32PROG_ERROR(...) \ ++ { \ ++ ERROR(__VA_ARGS__); \ ++ if (handle.phase != PHASE_RESET) { \ ++ snprintf((char *)&handle.error, sizeof(handle.error), __VA_ARGS__); \ ++ handle.phase = PHASE_RESET; \ ++ handle.addr = (uint8_t *)UNDEFINED_DOWN_ADDR; \ ++ handle.len = 0U; \ ++ handle.packet = 0U; \ ++ } \ ++ } ++ ++static int uart_write(const uint8_t *addr, uint16_t size) ++{ ++ while (size != 0U) { ++ if (stm32_uart_putc(&handle.uart, *addr) != 0) { ++ return -EIO; ++ } ++ size--; ++ addr++; ++ } ++ ++ return 0; ++} ++ ++static int uart_write_8(uint8_t byte) ++{ ++ return stm32_uart_putc(&handle.uart, byte); ++} ++ ++static int uart_write_32(uint32_t value) ++{ ++ return uart_write((uint8_t *)&value, 4U); ++} ++ ++static int uart_read_8(uint8_t *byte) ++{ ++ int ret; ++ uint64_t timeout_ref = timeout_init_us(PROGRAMMER_TIMEOUT_US); ++ ++ do { ++ ret = stm32_uart_getc(&handle.uart); ++ if (ret == -EAGAIN) { ++ if (timeout_elapsed(timeout_ref)) { ++ return -ETIMEDOUT; ++ } ++ } else if (ret < 0) { ++ return ret; ++ } ++ } while (ret == -EAGAIN); ++ ++ *byte = (uint8_t)ret; ++ ++ return 0; ++} ++ ++static int uart_send_result(uint8_t byte) ++{ ++ int ret; ++ ++ /* Always flush fifo before to send result = read all pending data */ ++ do { ++ ret = stm32_uart_getc(&handle.uart); ++ } while (ret >= 0); ++ ++ return uart_write_8(byte); ++} ++ ++static int is_valid_header(fip_toc_header_t *header) ++{ ++ return (header->name == TOC_HEADER_NAME) && ++ (header->serial_number != 0U); ++} ++ ++static int uart_receive_command(uint8_t *command) ++{ ++ uint8_t byte = 0U; ++ uint8_t xor = 0U; ++ unsigned int count; ++ bool found = false; ++ int ret; ++ ++ /* Repeat read until something is received */ ++ do { ++ stm32_iwdg_refresh(); ++ ret = uart_read_8(&byte); ++ } while (ret == -ETIMEDOUT); ++ ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Handle reconnection request */ ++ if (byte == INIT_BYTE) { ++ *command = byte; ++ return 0; ++ } ++ ++ for (count = 0U; count < ARRAY_SIZE(command_tab); count++) { ++ if (command_tab[count] == byte) { ++ found = true; ++ break; ++ } ++ } ++ if (!found) { ++ VERBOSE("UART: Command unknown (byte=0x%x)\n", byte); ++ return -EPROTO; ++ } ++ ++ ret = uart_read_8(&xor); ++ if (ret != 0) { ++ return ret; ++ } ++ if ((byte ^ xor) != 0xFF) { ++ VERBOSE("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n", ++ byte, xor); ++ return -EPROTO; ++ } ++ ++ *command = byte; ++ ++ return 0; ++} ++ ++static int get_cmd_command(void) ++{ ++ const uint8_t msg[2] = { ++ sizeof(command_tab), /* Length of data - 1 */ ++ USART_BL_VERSION ++ }; ++ int ret; ++ ++ ret = uart_write(msg, sizeof(msg)); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return uart_write(command_tab, sizeof(command_tab)); ++} ++ ++static int get_version_command(void) ++{ ++ return uart_write_8(STM32_TF_VERSION); ++} ++ ++static int get_id_command(void) ++{ ++ uint8_t msg[3] = { ++ sizeof(msg) - 1 /* Length of data - 1 */ ++ }; ++ uint32_t chip_id = stm32mp_get_chip_dev_id(); ++ ++ be16enc(&msg[1], chip_id); ++ ++ return uart_write(msg, sizeof(msg)); ++} ++ ++static int uart_send_phase(uint32_t address) ++{ ++ int ret; ++ uint8_t msg_size = 5U; /* Length of data - 1 */ ++ uint8_t error_size = 0U; ++ ++ /* Additional information only for RESET phase */ ++ if (handle.phase == PHASE_RESET) { ++ error_size = strnlen((char *)&handle.error, sizeof(handle.error)); ++ } ++ ret = uart_write_8(msg_size + error_size); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Send the ID of next partition */ ++ ret = uart_write_8(handle.phase); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Destination address */ ++ ret = uart_write_32(address); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = uart_write_8(error_size); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Additional information: message error */ ++ if (error_size > 0U) { ++ ret = uart_write(handle.error, error_size); ++ } ++ ++ return ret; ++} ++ ++static int uart_download_part(void) ++{ ++ uint8_t operation = 0U; ++ uint8_t xor; ++ uint8_t byte = 0U; ++ uint32_t packet_number = 0U; ++ uint32_t packet_size = 0U; ++ uint32_t i = 0U; ++ int ret; ++ ++ /* Get operation number */ ++ ret = uart_read_8(&operation); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ xor = operation; ++ ++ /* Get packet number */ ++ for (i = 3U; i != 0U; i--) { ++ ret = uart_read_8(&byte); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ xor ^= byte; ++ packet_number = (packet_number << 8) | byte; ++ } ++ ++ if (packet_number != handle.packet) { ++ WARN("UART: Bad packet number receive: %u, expected %u\n", ++ packet_number, handle.packet); ++ return -EPROTO; ++ } ++ ++ /* Checksum */ ++ ret = uart_read_8(&byte); ++ if (ret != 0) { ++ return ret; ++ } ++ if (xor != byte) { ++ VERBOSE("UART: Download Command checksum xor: %x, received %x\n", ++ xor, byte); ++ return -EPROTO; ++ } ++ ++ ret = uart_send_result(ACK_BYTE); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = uart_read_8(&byte); ++ if (ret != 0) { ++ return ret; ++ } ++ xor = byte; ++ packet_size = byte + 1U; ++ if (handle.len < packet_size) { ++ STM32PROG_ERROR("Download overflow at %p\n", handle.addr + packet_size); ++ return 0; ++ } ++ ++ for (i = 0U; i < packet_size; i++) { ++ ret = uart_read_8(&byte); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ *(handle.addr + i) = byte; ++ xor ^= byte; ++ } ++ ++ /* Checksum */ ++ ret = uart_read_8(&byte) != 0; ++ if (ret != 0) { ++ return ret; ++ } ++ if (xor != byte) { ++ VERBOSE("UART: Download Data checksum xor: %x, received %x\n", ++ xor, byte); ++ return -EPROTO; ++ } ++ ++ /* Packet treated */ ++ handle.packet++; ++ handle.addr += packet_size; ++ handle.len -= packet_size; ++ ++ return 0; ++} ++ ++static int uart_start_cmd(uintptr_t buffer) ++{ ++ uint8_t byte = 0U; ++ uint8_t xor = 0U; ++ uint32_t i; ++ uint32_t start_address = 0U; ++ int ret; ++ ++ /* Get address */ ++ for (i = 4U; i != 0U; i--) { ++ ret = uart_read_8(&byte); ++ if (ret != 0U) { ++ return ret; ++ } ++ ++ xor ^= byte; ++ start_address = (start_address << 8) | byte; ++ } ++ ++ /* Checksum */ ++ ret = uart_read_8(&byte); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (xor != byte) { ++ VERBOSE("UART: Start Command checksum xor: %x, received %x\n", ++ xor, byte); ++ return -EPROTO; ++ } ++ ++ if (start_address != UNDEFINED_DOWN_ADDR) { ++ STM32PROG_ERROR("Invalid start at %x, for phase %u\n", ++ start_address, handle.phase); ++ return 0; ++ } ++ ++ if (!is_valid_header((fip_toc_header_t *)buffer)) { ++ STM32PROG_ERROR("FIP Header check failed %lx, for phase %u\n", ++ buffer, handle.phase); ++ return -EIO; ++ } ++ VERBOSE("FIP header looks OK.\n"); ++ ++ return 0; ++} ++ ++#if STM32MP_SSP ++static int uart_read_part(void) ++{ ++ uint8_t byte = 0U; ++ uint8_t xor = 0U; ++ uint8_t partid = 0U; ++ uint16_t size = 0U; ++ uint32_t start_address = 0U; ++ uint32_t i; ++ size_t length; ++ uint8_t *buffer; ++ ++ /* Get partition id */ ++ if (uart_read_8(&partid) != 0) { ++ return -EIO; ++ } ++ ++ if ((partid != PHASE_FLASHLAYOUT) && (partid != PHASE_SSP)) { ++ return -EPERM; ++ } ++ ++ xor = partid; ++ ++ /* Get address */ ++ for (i = 4U; i > 0U; i--) { ++ if (uart_read_8(&byte) != 0) { ++ return -EIO; ++ } ++ ++ xor ^= byte; ++ start_address = (start_address << 8) | byte; ++ } ++ ++ /* Checksum */ ++ if (uart_read_8(&byte) != 0) { ++ return -EIO; ++ } ++ ++ if (xor != byte) { ++ WARN("UART: Start cmd: address checksum: %x != %x\n", ++ xor, byte); ++ return -EPROTO; ++ } ++ /* OFFSET != 0 not supported */ ++ if (start_address != 0U) { ++ return -EIO; ++ } ++ ++ uart_write_8(ACK_BYTE); ++ ++ /* Get number of bytes to send */ ++ if (uart_read_8(&byte) != 0) { ++ return -EIO; ++ } ++ ++ xor = byte; ++ ++ /* Send Size + 1 */ ++ size = byte++; ++ ++ /* Checksum */ ++ if (uart_read_8(&byte) != 0) { ++ return -EIO; ++ } ++ ++ if ((xor ^ byte) != 0xFF) { ++ WARN("UART: Start cmd: length checksum: %x != %x\n", xor, byte); ++ return -EPROTO; ++ } ++ ++ uart_write_8(ACK_BYTE); ++ ++ if (partid != PHASE_SSP) { ++ WARN("Not supported\n"); ++ return -EPROTO; ++ } ++ ++ length = handle.cert_len; ++ buffer = (uint8_t *)handle.cert_base; ++ ++ for (i = 0U; i < length; i++, buffer++) { ++ uart_write_8(*buffer); ++ } ++ for (; i < size; i++) { ++ uart_write_8(0x0); ++ } ++ ++ return 0; ++} ++#endif /* STM32MP_SSP */ ++ ++static int uart_read(uint8_t id, uintptr_t buffer, size_t length) ++{ ++ bool start_done = false; ++ int ret; ++ uint8_t command = 0U; ++ ++ handle.phase = id; ++ handle.packet = 0U; ++ handle.addr = (uint8_t *)buffer; ++ handle.len = length; ++ ++ INFO("UART: read phase %u at 0x%lx size 0x%x\n", ++ id, buffer, length); ++ while (!start_done) { ++ ret = uart_receive_command(&command); ++ if (ret != 0U) { ++ /* Delay to wait STM32CubeProgrammer end of transmission */ ++ mdelay(3); ++ ++ ret = uart_send_result(NACK_BYTE); ++ if (ret != 0U) { ++ return ret; ++ } ++ ++ continue; ++ } ++ ++ uart_send_result(ACK_BYTE); ++ ++ switch (command) { ++ case INIT_BYTE: ++ INFO("UART: Connected\n"); ++ /* Nothing to do */ ++ continue; ++ ++ case GET_CMD_COMMAND: ++ ret = get_cmd_command(); ++ break; ++ ++ case GET_VER_COMMAND: ++ ret = get_version_command(); ++ break; ++ ++ case GET_ID_COMMAND: ++ ret = get_id_command(); ++ break; ++ ++ case PHASE_COMMAND: ++ ret = uart_send_phase((uint32_t)buffer); ++ if ((ret == 0) && (handle.phase == PHASE_RESET)) { ++ start_done = true; ++ INFO("UART: Reset\n"); ++ } ++ break; ++ ++ case DOWNLOAD_COMMAND: ++ ret = uart_download_part(); ++ break; ++#if STM32MP_SSP ++ case READ_PART_COMMAND: ++ ret = uart_read_part(); ++ break; ++#endif ++ case START_COMMAND: ++ ret = uart_start_cmd(buffer); ++ if ((ret == 0) && (handle.phase == id)) { ++ INFO("UART: Start phase %u\n", handle.phase); ++#if STM32MP_SSP ++ if (handle.phase == PHASE_SSP) { ++ handle.phase = PHASE_RESET; ++ break; ++ } ++#endif ++ start_done = true; ++ } ++ break; ++ ++ default: ++ WARN("UART: Unknown command\n"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret == 0) { ++ ret = uart_send_result(ACK_BYTE); ++ } else { ++ ret = uart_send_result(NACK_BYTE); ++ } ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/* Init UART: 115200, 8bit 1stop parity even and enable FIFO mode */ ++const struct stm32_uart_init_s init = { ++ .baud_rate = STM32MP_UART_BAUDRATE, ++ .word_length = STM32_UART_WORDLENGTH_9B, ++ .stop_bits = STM32_UART_STOPBITS_1, ++ .parity = STM32_UART_PARITY_EVEN, ++ .hw_flow_control = STM32_UART_HWCONTROL_NONE, ++ .mode = STM32_UART_MODE_TX_RX, ++ .fifo_mode = STM32_UART_FIFOMODE_EN, ++}; ++ ++#if STM32MP_SSP ++int stm32cubeprog_uart_ssp(uintptr_t instance, ++ uintptr_t cert_base, ++ size_t cert_len, ++ uintptr_t ssp_base, ++ size_t ssp_len) ++{ ++ int ret; ++ ++ if (stm32_uart_init(&handle.uart, instance, &init) != 0U) { ++ return -EIO; ++ } ++ ++ /* NACK to synchronize STM32CubeProgrammer */ ++ ret = uart_send_result(NACK_BYTE); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (cert_base == UNDEFINED_DOWN_ADDR) { ++ /* Send Provisioning message to programmer for reboot */ ++ STM32PROG_ERROR("Provisioning\n"); ++ } else { ++ handle.cert_base = cert_base; ++ handle.cert_len = cert_len; ++ handle.phase = PHASE_SSP; ++ } ++ ++ return uart_read(handle.phase, ssp_base, ssp_len); ++ ++} ++#endif ++ ++int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len) ++{ ++ int ret; ++ ++ if (stm32_uart_init(&handle.uart, instance, &init) != 0) { ++ return -EIO; ++ } ++ ++ /* ++ * The following NACK_BYTE is written because STM32CubeProgrammer has ++ * already sent its command before TF-A has reached this point, and ++ * because FIFO was not configured by BootROM. ++ * The byte in the UART_RX register is then the checksum and not the ++ * command. NACK_BYTE has to be written, so that the programmer will ++ * re-send the good command. ++ */ ++ ret = uart_send_result(NACK_BYTE); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ return uart_read(PHASE_SSBL, base, len); ++} +diff --git a/plat/st/common/stm32cubeprogrammer_usb.c b/plat/st/common/stm32cubeprogrammer_usb.c +index 19a6bbae8..962ffd403 100644 +--- a/plat/st/common/stm32cubeprogrammer_usb.c ++++ b/plat/st/common/stm32cubeprogrammer_usb.c +@@ -20,6 +20,10 @@ struct dfu_state { + uintptr_t base; + size_t len; + uintptr_t address; ++#if STM32MP_SSP ++ uintptr_t cert_base; ++ size_t cert_len; ++#endif + /* working buffer */ + uint8_t buffer[UCHAR_MAX]; + }; +@@ -42,6 +46,7 @@ static struct dfu_state dfu_state; + } \ + } + ++#if !STM32MP_SSP + static bool is_valid_header(fip_toc_header_t *header) + { + if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0U)) { +@@ -50,6 +55,7 @@ static bool is_valid_header(fip_toc_header_t *header) + + return false; + } ++#endif + + static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, + void *user_data) +@@ -61,7 +67,15 @@ static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, + switch (usb_dfu_get_phase(alt)) { + case PHASE_CMD: + /* Get Pḧase */ ++#if STM32MP_SSP && STM32MP15 ++ if (dfu->phase == PHASE_SSP) { ++ dfu->buffer[0] = PHASE_FLASHLAYOUT; ++ } else { ++ dfu->buffer[0] = dfu->phase; ++ } ++#else + dfu->buffer[0] = dfu->phase; ++#endif + dfu->buffer[1] = (uint8_t)(dfu->address); + dfu->buffer[2] = (uint8_t)(dfu->address >> 8); + dfu->buffer[3] = (uint8_t)(dfu->address >> 16); +@@ -84,6 +98,33 @@ static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, + } + break; + ++#if STM32MP_SSP ++ case PHASE_SSP: ++#if STM32MP13 ++ dfu->buffer[0] = dfu->phase; ++#endif ++#if STM32MP15 ++ /* Fix phase to flashlayout phase */ ++ dfu->buffer[0] = PHASE_FLASHLAYOUT; ++#endif ++ dfu->buffer[1] = (uint8_t)(dfu_state.cert_base); ++ dfu->buffer[2] = (uint8_t)(dfu_state.cert_base >> 8); ++ dfu->buffer[3] = (uint8_t)(dfu_state.cert_base >> 16); ++ dfu->buffer[4] = (uint8_t)(dfu_state.cert_base >> 24); ++ dfu->buffer[5] = 0x00; ++ dfu->buffer[6] = 0x00; ++ dfu->buffer[7] = 0x00; ++ dfu->buffer[8] = 0x00; ++ length = 9U; ++ ++ if ((length + dfu_state.cert_len) <= sizeof(dfu->buffer)) { ++ memcpy(&dfu->buffer[9], (uint8_t *)dfu_state.cert_base, ++ dfu_state.cert_len); ++ length += dfu_state.cert_len; ++ } ++ ++ break; ++#endif + default: + DFU_ERROR("phase ID :%i, alternate %i for phase %i\n", + dfu->phase, alt, usb_dfu_get_phase(alt)); +@@ -136,6 +177,14 @@ static int dfu_callback_manifestation(uint8_t alt, void *user_data) + dfu->phase, alt, dfu->address); + + switch (dfu->phase) { ++#if STM32MP_SSP ++ case PHASE_SSP: ++ /* Configure End with request detach */ ++ dfu->phase = PHASE_FLASHLAYOUT; ++ dfu->address = UNDEFINED_DOWN_ADDR; ++ dfu->len = 0; ++ break; ++#else + case PHASE_SSBL: + if (!is_valid_header((fip_toc_header_t *)dfu->base)) { + DFU_ERROR("FIP Header check failed for phase %d\n", alt); +@@ -148,6 +197,7 @@ static int dfu_callback_manifestation(uint8_t alt, void *user_data) + dfu->address = UNDEFINED_DOWN_ADDR; + dfu->len = 0; + break; ++#endif /* STM32MP_SSP */ + default: + DFU_ERROR("Unknown phase\n"); + } +@@ -162,6 +212,52 @@ static const struct usb_dfu_media usb_dfu_fops = { + .manifestation = dfu_callback_manifestation, + }; + ++#if STM32MP_SSP ++int stm32cubeprog_usb_ssp(struct usb_handle *usb_core_handle, ++ uintptr_t cert_base, ++ size_t cert_len, ++ uintptr_t ssp_base, ++ size_t ssp_len) ++{ ++ int ret; ++ ++ usb_core_handle->user_data = (void *)&dfu_state; ++ ++ INFO("DFU USB START...\n"); ++ ret = usb_core_start(usb_core_handle); ++ if (ret != USBD_OK) { ++ return -EIO; ++ } ++ ++ if (cert_base == UNDEFINED_DOWN_ADDR) { ++ struct dfu_state *dfu = (struct dfu_state *)usb_core_handle->user_data; ++ ++ /* Send Provisioning message to programmer for reboot */ ++ DFU_ERROR("Provisioning\n"); ++ } else { ++ dfu_state.phase = PHASE_SSP; ++ dfu_state.address = ssp_base; ++ dfu_state.base = ssp_base; ++ dfu_state.len = ssp_len; ++ dfu_state.cert_base = cert_base; ++ dfu_state.cert_len = cert_len; ++ } ++ ++ ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops); ++ if (ret != USBD_OK) { ++ return -EIO; ++ } ++ ++ INFO("DFU USB STOP...\n"); ++ ret = usb_core_stop(usb_core_handle); ++ if (ret != USBD_OK) { ++ return -EIO; ++ } ++ ++ return 0; ++} ++#endif ++ + int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle, + uintptr_t base, + size_t len) +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 91204089b..2b9f74eca 100644 +--- a/plat/st/common/stm32mp_common.c ++++ b/plat/st/common/stm32mp_common.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -7,17 +7,27 @@ + #include + #include + +-#include +- + #include + #include ++#include ++#include ++#include + #include ++#include + #include ++#include + #include + #include + #include + ++#include ++ + #define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16) ++#define RESET_TIMEOUT_US_1MS 1000U ++ ++static console_t console; ++static struct dt_node_info dt_uart_info; ++static struct spinlock lock; + + uintptr_t plat_get_ns_image_entrypoint(void) + { +@@ -31,6 +41,7 @@ unsigned int plat_get_syscnt_freq2(void) + + static uintptr_t boot_ctx_address; + static uint16_t boot_itf_selected; ++static uint32_t boot_action_saved; + + void stm32mp_save_boot_ctx_address(uintptr_t address) + { +@@ -38,6 +49,7 @@ void stm32mp_save_boot_ctx_address(uintptr_t address) + + boot_ctx_address = address; + boot_itf_selected = boot_context->boot_interface_selected; ++ boot_action_saved = boot_context->boot_action; + } + + uintptr_t stm32mp_get_boot_ctx_address(void) +@@ -50,6 +62,11 @@ uint16_t stm32mp_get_boot_itf_selected(void) + return boot_itf_selected; + } + ++uint32_t stm32mp_get_boot_action(void) ++{ ++ return boot_action_saved; ++} ++ + uintptr_t stm32mp_ddrctrl_base(void) + { + return DDRCTRL_BASE; +@@ -78,42 +95,19 @@ bool stm32mp_lock_available(void) + return (read_sctlr() & c_m_bits) == c_m_bits; + } + +-#if STM32MP_USE_STM32IMAGE +-int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) ++void stm32mp_pwr_regs_lock(void) + { +- uint32_t i; +- uint32_t img_checksum = 0U; +- +- /* +- * Check header/payload validity: +- * - Header magic +- * - Header version +- * - Payload checksum +- */ +- if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { +- ERROR("Header magic\n"); +- return -EINVAL; +- } +- +- 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 (stm32mp_lock_available()) { ++ spin_lock(&lock); + } ++} + +- if (header->payload_checksum != img_checksum) { +- ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum, +- header->payload_checksum); +- return -EINVAL; ++void stm32mp_pwr_regs_unlock(void) ++{ ++ if (stm32mp_lock_available()) { ++ spin_unlock(&lock); + } +- +- return 0; + } +-#endif /* STM32MP_USE_STM32IMAGE */ + + int stm32mp_map_ddr_non_cacheable(void) + { +@@ -128,6 +122,164 @@ int stm32mp_unmap_ddr(void) + STM32MP_DDR_MAX_SIZE); + } + ++int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, ++ uint32_t *otp_len) ++{ ++ assert(otp_name != NULL); ++ assert(otp_idx != NULL); ++ ++ return dt_find_otp_name(otp_name, otp_idx, otp_len); ++} ++ ++int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val) ++{ ++ uint32_t otp_idx; ++ ++ 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; ++ } ++ ++ return 0; ++} ++ ++int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val) ++{ ++ int ret = BSEC_NOT_SUPPORTED; ++ ++ assert(otp_val != NULL); ++ ++#if defined(IMAGE_BL2) ++ ret = bsec_shadow_read_otp(otp_val, otp_idx); ++#elif defined(IMAGE_BL32) ++ ret = bsec_read_otp(otp_val, otp_idx); ++#else ++#error "Not supported" ++#endif ++ if (ret != BSEC_OK) { ++ ERROR("BSEC: idx=%d Read Error\n", otp_idx); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++#if defined(IMAGE_BL2) ++static void reset_uart(uint32_t reset) ++{ ++ int ret; ++ ++ ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ udelay(2); ++ ++ ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ mdelay(1); ++} ++#endif ++ ++static void set_console(uintptr_t base, uint32_t clk_rate) ++{ ++ unsigned int console_flags; ++ ++ if (console_stm32_register(base, clk_rate, ++ (uint32_t)STM32MP_UART_BAUDRATE, &console) == 0) { ++ panic(); ++ } ++ ++ console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | ++ CONSOLE_FLAG_TRANSLATE_CRLF; ++#if !defined(IMAGE_BL2) && defined(DEBUG) ++ console_flags |= CONSOLE_FLAG_RUNTIME; ++#endif ++ ++ console_set_scope(&console, console_flags); ++} ++ ++int stm32mp_uart_console_setup(void) ++{ ++ uint32_t clk_rate = 0U; ++ int result; ++ uint32_t boot_itf __unused; ++ uint32_t boot_instance __unused; ++ ++ result = dt_get_stdout_uart_info(&dt_uart_info); ++ ++ if ((result <= 0) || ++ (dt_uart_info.status == DT_DISABLED)) { ++ return -ENODEV; ++ } ++ ++#if defined(IMAGE_BL2) ++ if ((dt_uart_info.clock < 0) || ++ (dt_uart_info.reset < 0)) { ++ return -ENODEV; ++ } ++#endif ++ ++#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2) ++ stm32_get_boot_interface(&boot_itf, &boot_instance); ++ ++ if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) && ++ (get_uart_address(boot_instance) == dt_uart_info.base)) { ++ return -EACCES; ++ } ++#endif ++ ++#if defined(IMAGE_BL2) ++ if (dt_set_stdout_pinctrl() != 0) { ++ return -ENODEV; ++ } ++ ++ clk_enable((unsigned long)dt_uart_info.clock); ++ ++ reset_uart((uint32_t)dt_uart_info.reset); ++ ++ clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock); ++#endif ++ ++ set_console(dt_uart_info.base, clk_rate); ++ ++ return 0; ++} ++ ++#if STM32MP_EARLY_CONSOLE ++void stm32mp_setup_early_console(void) ++{ ++ plat_crash_console_init(); ++ set_console(STM32MP_DEBUG_USART_BASE, STM32MP_DEBUG_USART_CLK_FRQ); ++} ++#endif /* STM32MP_EARLY_CONSOLE */ ++ ++void stm32mp_set_console_after_standby(void) ++{ ++ unsigned int console_flags; ++ ++ console_flags = CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF; ++ if ((clk_is_enabled(dt_uart_info.clock)) && ++ (clk_get_rate(dt_uart_info.clock) != 0U)) { ++ console_flags |= CONSOLE_FLAG_BOOT; ++#ifdef DEBUG ++ console_flags |= CONSOLE_FLAG_RUNTIME; ++#endif ++ } ++ console_set_scope(&console, console_flags); ++} ++ + /***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. +diff --git a/plat/st/common/stm32mp_crypto_lib.c b/plat/st/common/stm32mp_crypto_lib.c +new file mode 100644 +index 000000000..ccba38b11 +--- /dev/null ++++ b/plat/st/common/stm32mp_crypto_lib.c +@@ -0,0 +1,652 @@ ++/* ++ * Copyright (c) 2020-2022, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#if STM32MP13 ++#include ++#include ++#include ++#endif ++#include ++#include ++#include ++ ++#include ++ ++#define CRYPTO_HASH_MAX_SIZE 32U ++#define CRYPTO_SIGN_MAX_SIZE 64U ++#define CRYPTO_PUBKEY_MAX_SIZE 64U ++#define CRYPTO_MAX_TAG_SIZE 16U ++ ++#if STM32MP15 ++struct stm32mp_auth_ops { ++ uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in, ++ uint8_t *signature, uint32_t ecc_algo); ++}; ++ ++static struct stm32mp_auth_ops auth_ops; ++ ++#endif ++ ++static void crypto_lib_init(void) ++{ ++#if STM32MP15 ++ boot_api_context_t *boot_context = ++ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); ++#endif ++ ++ int ret; ++ ++ if (!stm32mp_is_closed_device() && !stm32mp_is_auth_supported()) { ++ return; ++ } ++ ++#if STM32MP13 ++ if (stm32_rng_init() != 0) { ++ panic(); ++ } ++ ++ if (stm32_saes_driver_init() != 0) { ++ panic(); ++ } ++ ++ if (stm32_pka_init() != 0) { ++ panic(); ++ } ++#endif ++ ++#if STM32MP15 ++ auth_ops.verify_signature = ++ boot_context->bootrom_ecdsa_verify_signature; ++#endif ++ ++ ret = stm32_hash_register(); ++ if (ret != 0) { ++ ERROR("HASH init (%d)\n", ret); ++ panic(); ++ } ++} ++ ++int get_plain_pk_from_asn1(void *pk_ptr, unsigned int pk_len, void **plain_pk, ++ unsigned int *len, int *pk_alg) ++{ ++ int ret; ++ mbedtls_pk_context mbedtls_pk = {0}; ++ unsigned char *p, *end; ++ mbedtls_asn1_buf alg_params = {0}; ++ mbedtls_asn1_buf alg_oid = {0}; ++ ++ *plain_pk = NULL; ++ *len = 0U; ++ ++ /* Parse the public key */ ++ mbedtls_pk_init(&mbedtls_pk); ++ p = (unsigned char *)pk_ptr; ++ end = (unsigned char *)(p + pk_len); ++ ++ ret = mbedtls_asn1_get_tag(&p, end, len, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ if (ret != 0) { ++ return -EINVAL; ++ } ++ ++ end = p + *len; ++ ret = mbedtls_asn1_get_alg(&p, end, &alg_oid, &alg_params); ++ if (ret != 0) { ++ VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret); ++ return -EINVAL; ++ } ++ ++ if (pk_alg != NULL) { ++ if ((strlen(MBEDTLS_OID_EC_GRP_SECP256R1) == alg_params.len) && ++ (memcmp(MBEDTLS_OID_EC_GRP_SECP256R1, alg_params.p, alg_params.len) == 0)) { ++ *pk_alg = BOOT_API_ECDSA_ALGO_TYPE_P256NIST; ++ } else { ++ *pk_alg = BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256; ++ } ++ } ++ ++ ret = mbedtls_asn1_get_bitstring_null(&p, end, len); ++ if (ret != 0) { ++ VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret); ++ return -EINVAL; ++ } ++ ++ /* we remove the ident (0x04) first byte. */ ++ if ((*len < 1U) || (p[0] != MBEDTLS_ASN1_OCTET_STRING)) { ++ VERBOSE("%s: not expected len or tag\n", __func__); ++ return -EINVAL; ++ } ++ ++ *len = *len - 1U; ++ *plain_pk = p + 1U; ++ ++ return 0; ++} ++ ++#if STM32MP13 ++static uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in, ++ uint8_t *signature, uint32_t ecc_algo) ++{ ++ int ret; ++ enum stm32_pka_ecdsa_curve_id cid; ++ ++ switch (ecc_algo) { ++ case BOOT_API_ECDSA_ALGO_TYPE_P256NIST: ++#if PKA_USE_NIST_P256 ++ cid = PKA_NIST_P256; ++ break; ++#else ++ WARN("%s nist_p256 requested but not included\n", __func__); ++ return CRYPTO_ERR_SIGNATURE; ++#endif ++ case BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256: ++#if PKA_USE_BRAINPOOL_P256T1 ++ cid = PKA_BRAINPOOL_P256T1; ++ break; ++#else ++ WARN("%s brainpool_p256t1 requested but not included\n", __func__); ++ return CRYPTO_ERR_SIGNATURE; ++#endif ++ default: ++ WARN("%s unexpected ecc_algo(%d)\n", __func__, ecc_algo); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ ret = stm32_pka_ecdsa_verif(hash_in, ++ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES, ++ signature, BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U, ++ signature + BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U, ++ BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U, ++ pubkey_in, BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, ++ pubkey_in + BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, ++ BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, cid); ++ if (ret < 0) { ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ return 0; ++} ++ ++int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, ++ void **hashed_pk_ptr, unsigned int *hashed_pk_len) ++{ ++ static uint8_t st_pk[CRYPTO_PUBKEY_MAX_SIZE + sizeof(uint32_t)]; ++ int ret; ++ void *plain_pk; ++ unsigned int len; ++ int curve_id; ++ uint32_t cid; ++ ++ ret = get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, &plain_pk, &len, &curve_id); ++ if ((ret != 0) || (len > CRYPTO_PUBKEY_MAX_SIZE)) { ++ return -EINVAL; ++ } ++ ++ cid = curve_id; /* we want value of curve_id (1 or 2) in a uint32_t */ ++ ++ memcpy(st_pk, &cid, sizeof(cid)); ++ memcpy(st_pk + sizeof(cid), plain_pk, len); ++ ++ *hashed_pk_ptr = st_pk; ++ *hashed_pk_len = len + sizeof(cid); ++ ++ return 0; ++} ++#endif ++ ++#if STM32MP15 ++uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in, ++ uint8_t *signature, uint32_t ecc_algo) ++{ ++ int ret; ++ ++ ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE, ++ STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE); ++ if (ret != 0) { ++ VERBOSE("%s: mmap_add_dynamic_region (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ ret = auth_ops.verify_signature(hash_in, pubkey_in, signature, ecc_algo); ++ ++ if (ret != BOOT_API_RETURN_OK) { ++ VERBOSE("%s: auth_ops.verify_sign (%d)\n", __func__, ret); ++ ret = CRYPTO_ERR_SIGNATURE; ++ } else { ++ ret = 0; ++ } ++ ++ mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED); ++ ++ return ret; ++} ++ ++int plat_get_hashed_pk(void *full_pk_ptr, unsigned int full_pk_len, ++ void **hashed_pk_ptr, unsigned int *hashed_pk_len) ++{ ++ return get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, hashed_pk_ptr, hashed_pk_len, NULL); ++} ++#endif ++ ++static int get_plain_digest_from_asn1(void *digest_ptr, unsigned int digest_len, ++ uint8_t **out, size_t *out_len, mbedtls_md_type_t *md_alg) ++{ ++ int ret; ++ mbedtls_asn1_buf hash_oid, params; ++ size_t len; ++ unsigned char *p, *end; ++ ++ *out = NULL; ++ *out_len = 0U; ++ ++ /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ ++ p = (unsigned char *)digest_ptr; ++ end = p + digest_len; ++ ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | ++ MBEDTLS_ASN1_SEQUENCE); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Get the hash algorithm */ ++ ret = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = mbedtls_oid_get_md_alg(&hash_oid, md_alg); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Length of hash must match the algorithm's size */ ++ if (len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) { ++ return -1; ++ } ++ ++ *out = p; ++ *out_len = len; ++ ++ return 0; ++} ++ ++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[CRYPTO_HASH_MAX_SIZE] = {0}; ++ uint8_t sig[CRYPTO_SIGN_MAX_SIZE]; ++ uint8_t my_pk[CRYPTO_PUBKEY_MAX_SIZE]; ++ int ret; ++ size_t len; ++ mbedtls_asn1_sequence seq; ++ mbedtls_asn1_sequence *cur; ++ unsigned char *p, *end; ++ int curve_id; ++ mbedtls_asn1_buf sig_oid, sig_params; ++ mbedtls_md_type_t md_alg; ++ mbedtls_pk_type_t pk_alg; ++ size_t bignum_len = sizeof(sig) / 2U; ++ unsigned int seq_num = 0U; ++ ++ /* Get pointers to signature OID and parameters */ ++ p = (unsigned char *)sig_alg; ++ end = (unsigned char *)(p + sig_alg_len); ++ ret = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); ++ if (ret != 0) { ++ VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ /* Get the actual signature algorithm (MD + PK) */ ++ ret = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); ++ if (ret != 0) { ++ VERBOSE("%s: mbedtls_oid_get_sig_alg (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ if ((md_alg != MBEDTLS_MD_SHA256) || (pk_alg != MBEDTLS_PK_ECDSA)) { ++ VERBOSE("%s: md_alg=%d pk_alg=%d\n", __func__, md_alg, pk_alg); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ ret = get_plain_pk_from_asn1(pk_ptr, pk_len, &pk_ptr, &pk_len, &curve_id); ++ if (ret != 0) { ++ VERBOSE("%s: get_plain_pk_from_asn1 (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ /* We expect a known pk_len */ ++ if (pk_len != sizeof(my_pk)) { ++ VERBOSE("%s: pk_len=%d sizeof(my_pk)=%d)\n", __func__, pk_len, sizeof(my_pk)); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ /* Need to copy as auth_ops.verify_signature ++ * expects aligned public key. ++ */ ++ memcpy(my_pk, pk_ptr, sizeof(my_pk)); ++ ++ /* Get the signature (bitstring) */ ++ p = (unsigned char *)sig_ptr; ++ end = (unsigned char *)(p + sig_len); ++ ret = mbedtls_asn1_get_bitstring_null(&p, end, &len); ++ if (ret != 0) { ++ VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ /* Get r and s from sequence */ ++ ret = mbedtls_asn1_get_sequence_of(&p, end, &seq, MBEDTLS_ASN1_INTEGER); ++ if (ret != 0) { ++ VERBOSE("%s: mbedtls_asn1_get_sequence_of (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ /* We expect only 2 integers (r and s) from the sequence */ ++ if (seq.next->next != NULL) { ++ cur = seq.next; ++ mbedtls_asn1_sequence *next; ++ ++ VERBOSE("%s: nb seq != 2\n", __func__); ++ /* Free all the sequences */ ++ while (cur != NULL) { ++ next = cur->next; ++ mbedtls_free(cur); ++ cur = next; ++ } ++ ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ /* ++ * ECDSA signatures are composed of a tuple (R,S) where R and S are between 0 and n. ++ * This means that the R and S can have a maximum of 32 each, but can also be smaller. ++ * Also seen the integer sequence may (sometime) start with 0x00 as MSB, but we can only ++ * manage exactly 2*32 bytes, we remove this higher byte if there are not 00, ++ * we will fail either. ++ */ ++ cur = &seq; ++ memset(sig, 0U, sizeof(sig)); ++ ++ while (cur != NULL) { ++ size_t skip = 0U; ++ size_t seek = seq_num * bignum_len; ++ ++ if (cur->buf.len > bignum_len) { ++ /* Remove extra 0x00 bytes */ ++ skip = cur->buf.len - bignum_len; ++ } else if (cur->buf.len < bignum_len) { ++ /* Add padding to match HW required size */ ++ seek += (bignum_len % cur->buf.len); ++ } ++ ++ if (seek + cur->buf.len > sizeof(sig) + skip) { ++ panic(); ++ } ++ ++ memcpy(sig + seek, cur->buf.p + skip, cur->buf.len - skip); ++ cur = cur->next; ++ seq_num++; ++ } ++ ++ /* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */ ++ mbedtls_free(seq.next); ++ ++ /* Compute hash for the data covered by the signature */ ++ stm32_hash_init(HASH_SHA256); ++ ++ ret = stm32_hash_final_update((uint8_t *)data_ptr, data_len, image_hash); ++ if (ret != 0) { ++ VERBOSE("%s: stm32_hash_final_update (%d)\n", __func__, ret); ++ return CRYPTO_ERR_SIGNATURE; ++ } ++ ++ return verify_signature(image_hash, my_pk, sig, curve_id); ++} ++ ++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]; ++ unsigned char *p; ++ mbedtls_md_type_t md_alg; ++ size_t len; ++ ++ /* we receive an asn1 encapsulated digest, we flatten it */ ++ ret = get_plain_digest_from_asn1(digest_info_ptr, ++ digest_info_len, &p, &len, ++ &md_alg); ++ if ((ret != 0) || (md_alg != MBEDTLS_MD_SHA256) || (len != sizeof(calc_hash))) { ++ return CRYPTO_ERR_HASH; ++ } ++ ++ digest_info_ptr = p; ++ digest_info_len = len; ++ ++ 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__); ++ return CRYPTO_ERR_HASH; ++ } ++ ++ ret = memcmp(calc_hash, digest_info_ptr, digest_info_len); ++ if (ret != 0) { ++ VERBOSE("%s: not expected digest\n", __func__); ++ ret = CRYPTO_ERR_HASH; ++ } ++ ++ return ret; ++} ++ ++#if STM32MP13 && !defined(DECRYPTION_SUPPORT_none) ++int derive_key(uint8_t *key, size_t *key_len, size_t len, ++ unsigned int *flags, const uint8_t *img_id, size_t img_id_len) ++{ ++ size_t i, j; ++ ++ assert(*key_len >= 32U); ++ ++ /* ++ * Not a real derivation yet ++ * ++ * But we expect a 32 bytes key, and otp is only 16 bytes ++ * => duplicate. ++ */ ++ for (i = 0U, j = len; j < 32U; ++ i += sizeof(uint32_t), j += sizeof(uint32_t)) { ++ memcpy(key + j, key + i, sizeof(uint32_t)); ++ } ++ ++ *key_len = 32U; ++ /* Variable 'key' store a real key */ ++ *flags = 0U; ++ ++ return 0; ++} ++ ++int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key, ++ size_t *key_len, unsigned int *flags, ++ const uint8_t *img_id, size_t img_id_len) ++{ ++ uint32_t otp_idx; ++ uint32_t otp_len; ++ size_t read_len; ++ size_t i; ++ ++ if (fw_enc_status == FW_ENC_WITH_BSSK) { ++ return -EINVAL; ++ } ++ ++ if (stm32_get_otp_index(ENCKEY_OTP, &otp_idx, &otp_len) != 0) { ++ VERBOSE("%s: get %s index error\n", __func__, ENCKEY_OTP); ++ return -EINVAL; ++ } ++ ++ if (otp_len > (*key_len * CHAR_BIT)) { ++ VERBOSE("%s: length Error otp_len=%d key_len=%u\n", __func__, ++ otp_len, *key_len * CHAR_BIT); ++ return -EINVAL; ++ } ++ ++ read_len = otp_len / CHAR_BIT; ++ assert(read_len % sizeof(uint32_t) == 0); ++ ++ for (i = 0U; i < read_len / sizeof(uint32_t); i++) { ++ uint32_t tmp; ++ uint32_t otp_val; ++ ++ if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) { ++ VERBOSE("%s: unable to read from otp\n", __func__); ++ return -EINVAL; ++ } ++ ++ tmp = bswap32(otp_val); ++ memcpy(key + i * sizeof(uint32_t), &tmp, sizeof(tmp)); ++ } ++ ++ /* Now we have the OTP values in key till read_len */ ++ ++ if (derive_key(key, key_len, read_len, flags, img_id, ++ img_id_len) != 0) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static enum stm32_saes_key_selection select_key(unsigned int key_flags) ++{ ++ if ((key_flags & ENC_KEY_IS_IDENTIFIER) != 0U) { ++ panic(); ++ } ++ ++ /* Use the provided key buffer */ ++ return STM32_SAES_KEY_SOFT; ++} ++ ++static int stm32_decrypt_aes_gcm(void *data, size_t data_len, ++ const void *key, unsigned int key_len, ++ unsigned int key_flags, ++ const void *iv, unsigned int iv_len, ++ const void *tag, unsigned int tag_len) ++{ ++ int ret; ++ struct stm32_saes_context ctx; ++ unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; ++ enum stm32_saes_key_selection key_mode; ++ unsigned int diff, i; ++ ++ key_mode = select_key(key_flags); ++ ++ ret = stm32_saes_init(&ctx, true, STM32_SAES_MODE_GCM, key_mode, key, ++ key_len, iv, iv_len); ++ if (ret != 0) { ++ return CRYPTO_ERR_INIT; ++ } ++ ++ ret = stm32_saes_update_assodata(&ctx, true, NULL, 0U); ++ if (ret != 0) { ++ return CRYPTO_ERR_DECRYPTION; ++ } ++ ++ ret = stm32_saes_update_load(&ctx, true, data, data, data_len); ++ if (ret != 0) { ++ return CRYPTO_ERR_DECRYPTION; ++ } ++ ++ ret = stm32_saes_final(&ctx, tag_buf, sizeof(tag_buf)); ++ if (ret != 0) { ++ return CRYPTO_ERR_DECRYPTION; ++ } ++ ++ /* Check tag in "constant-time" */ ++ for (diff = 0U, i = 0U; i < tag_len; i++) { ++ diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; ++ } ++ ++ if (diff != 0U) { ++ return CRYPTO_ERR_DECRYPTION; ++ } ++ ++ return CRYPTO_SUCCESS; ++} ++ ++/* ++ * Authenticated decryption of an image ++ * ++ */ ++static int crypto_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, size_t len, ++ const void *key, unsigned int key_len, unsigned int key_flags, ++ const void *iv, unsigned int iv_len, const void *tag, ++ unsigned int tag_len) ++{ ++ int rc; ++ uint32_t real_iv[4]; ++ ++ switch (dec_algo) { ++ case CRYPTO_GCM_DECRYPT: ++ /* ++ * GCM expect a Nonce ++ * The AES IV is the nonce (a uint32_t[3]) ++ * then a counter (a uint32_t big endian) ++ * The counter starts at 2. ++ */ ++ memcpy(real_iv, iv, iv_len); ++ real_iv[3] = htobe32(0x2U); ++ ++ rc = stm32_decrypt_aes_gcm(data_ptr, len, key, key_len, key_flags, ++ real_iv, sizeof(real_iv), tag, tag_len); ++ if (rc != 0) { ++ return rc; ++ } ++ break; ++ default: ++ return CRYPTO_ERR_DECRYPTION; ++ } ++ ++ return CRYPTO_SUCCESS; ++} ++ ++REGISTER_CRYPTO_LIB("stm32_crypto_lib", ++ crypto_lib_init, ++ crypto_verify_signature, ++ crypto_verify_hash, ++ crypto_auth_decrypt); ++ ++#else /* No decryption support */ ++REGISTER_CRYPTO_LIB("stm32_crypto_lib", ++ crypto_lib_init, ++ crypto_verify_signature, ++ crypto_verify_hash, ++ NULL); ++ ++#endif +diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c +index 4dc990896..a0daf9514 100644 +--- a/plat/st/common/stm32mp_dt.c ++++ b/plat/st/common/stm32mp_dt.c +@@ -1,11 +1,12 @@ + /* +- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + #include + #include ++#include + + #include + +@@ -13,9 +14,8 @@ + + #include + #include ++#include + #include +-#include +-#include + + #include + +@@ -115,6 +115,30 @@ static int fdt_get_node_parent_address_cells(int node) + } + #endif + ++/******************************************************************************* ++ * This function return interrupts from node. ++ ******************************************************************************/ ++int fdt_get_interrupt(int node, const fdt32_t **array, int *len, bool *extended) ++{ ++ *extended = false; ++ ++ *array = fdt_getprop(fdt, node, "secure-interrupts", len); ++ if (*array == NULL) { ++ *array = fdt_getprop(fdt, node, "interrupts-extended", len); ++ if (*array == NULL) { ++ *array = fdt_getprop(fdt, node, "interrupts", len); ++ } else { ++ *extended = true; ++ } ++ } ++ ++ if (*array == NULL) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ 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. +@@ -256,44 +280,244 @@ uint32_t dt_get_ddr_size(void) + return size; + } + ++/******************************************************************************* ++ * 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 fdt_node_offset_by_compatible(fdt, -1, 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 %" PRIu64 "\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; ++ int subnode; ++ uint32_t freq = 0U; ++ uint32_t voltage = 0U; ++ ++ assert(freq_khz != NULL); ++ assert(voltage_mv != 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 (read_freq > freq) { ++ freq = read_freq; ++ voltage = read_voltage; ++ } ++ } ++ ++ 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; ++ uint32_t idx = 0U; ++ ++ 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; ++} ++ + /******************************************************************************* + * 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, pwr_regulators_node; +- const fdt32_t *cuint; ++ struct rdev *regul = dt_get_vdd_regulator(); ++ uint16_t min; + +- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); +- if (node < 0) { +- INFO("%s: Cannot read PWR node in DT\n", __func__); ++ if (regul == NULL) { + return 0; + } + +- pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators"); +- if (pwr_regulators_node < 0) { +- INFO("%s: Cannot read pwr-regulators node in DT\n", __func__); +- return 0; ++ regulator_get_range(regul, &min, NULL); ++ ++ return (uint32_t)min * 1000U; ++} ++ ++/******************************************************************************* ++ * This function retrieves VDD supply regulator from DT. ++ * Returns an rdev taken from supply node, NULL otherwise. ++ ******************************************************************************/ ++struct rdev *dt_get_vdd_regulator(void) ++{ ++ int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); ++ ++ if (node < 0) { ++ return NULL; + } + +- cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL); +- if (cuint == NULL) { +- return 0; ++ return regulator_get_by_supply_name(fdt, node, "vdd"); ++} ++ ++/******************************************************************************* ++ * This function retrieves CPU supply regulator from DT. ++ * Returns an rdev taken from supply node, NULL otherwise. ++ ******************************************************************************/ ++struct rdev *dt_get_cpu_regulator(void) ++{ ++ int node = fdt_path_offset(fdt, "/cpus/cpu@0"); ++ ++ if (node < 0) { ++ return NULL; + } + +- node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); ++ return regulator_get_by_supply_name(fdt, node, "cpu"); ++} ++ ++#if IMAGE_BL32 ++/******************************************************************************* ++ * This function retrieves USB phy regulator name from DT. ++ * Returns string taken from supply node, NULL otherwise. ++ ******************************************************************************/ ++struct rdev *dt_get_usb_phy_regulator(void) ++{ ++ int node = fdt_node_offset_by_compatible(fdt, -1, DT_USBPHYC_COMPAT); ++ int subnode; ++ + if (node < 0) { +- return 0; ++ return NULL; + } + +- cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); +- if (cuint == NULL) { +- return 0; ++ fdt_for_each_subnode(subnode, fdt, node) { ++ struct rdev *supply = regulator_get_by_supply_name(fdt, node, "phy"); ++ ++ if (supply != NULL) { ++ return supply; ++ } + } + +- return fdt32_to_cpu(*cuint); ++ return NULL; + } ++#endif + + /******************************************************************************* + * This function retrieves board model from DT +@@ -310,6 +534,57 @@ const char *dt_get_board_model(void) + return (const char *)fdt_getprop(fdt, node, "model", NULL); + } + ++/******************************************************************************* ++ * dt_find_otp_name: 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: 0 if no error, an FDT error value otherwise. ++ ******************************************************************************/ ++int dt_find_otp_name(const char *name, uint32_t *otp, uint32_t *otp_len) ++{ ++ int node; ++ int len; ++ const fdt32_t *cuint; ++ ++ if ((name == NULL) || (otp == NULL)) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ node = fdt_node_offset_by_compatible(fdt, -1, DT_BSEC_COMPAT); ++ if (node < 0) { ++ return node; ++ } ++ ++ node = fdt_subnode_offset(fdt, node, name); ++ if (node < 0) { ++ ERROR("nvmem node %s not found\n", name); ++ return node; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "reg", &len); ++ if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) { ++ ERROR("Malformed nvmem node %s: ignored\n", name); ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { ++ ERROR("Misaligned nvmem %s element: ignored\n", name); ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ 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 0; ++} ++ + /******************************************************************************* + * This function gets the pin count for a GPIO bank based from the FDT. + * It also checks node consistency. +@@ -318,6 +593,9 @@ int fdt_get_gpio_bank_pin_count(unsigned int bank) + { + int pinctrl_node; + int node; ++ int len; ++ int i; ++ int pin_count; + uint32_t bank_offset; + + pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank); +@@ -347,12 +625,22 @@ int fdt_get_gpio_bank_pin_count(unsigned int bank) + return 0; + } + +- cuint = fdt_getprop(fdt, node, "ngpios", NULL); +- if (cuint == NULL) { +- return -FDT_ERR_NOTFOUND; ++ /* Parse gpio-ranges with its 4 parameters */ ++ cuint = fdt_getprop(fdt, node, "gpio-ranges", &len); ++ len /= sizeof(*cuint); ++ if ((len % 4) != 0) { ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ /* Get the last defined gpio line (offset + nb of pins) */ ++ pin_count = fdt32_to_cpu(*(cuint + 1)) + fdt32_to_cpu(*(cuint + 3)); ++ for (i = 0; i < len / 4; i++) { ++ pin_count = MAX(pin_count, (int)(fdt32_to_cpu(*(cuint + 1)) + ++ fdt32_to_cpu(*(cuint + 3)))); ++ cuint += 4; + } + +- return (int)fdt32_to_cpu(*cuint); ++ return pin_count; + } + + return 0; +diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c +index aa8cd5441..8c52a131b 100644 +--- a/plat/st/common/stm32mp_fconf_io.c ++++ b/plat/st/common/stm32mp_fconf_io.c +@@ -16,6 +16,7 @@ + #include + + #include ++#include + #include + #include + +@@ -26,23 +27,63 @@ static io_block_spec_t gpt_block_spec = { + }; + #endif + ++#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT ++io_block_spec_t metadata_block_spec = { ++ .offset = 0, /* To be filled at runtime */ ++ .length = 0, /* To be filled at runtime */ ++}; ++#endif ++ + /* By default, STM32 platforms load images from the FIP */ + struct plat_io_policy policies[MAX_NUMBER_IDS] = { + [FIP_IMAGE_ID] = { +- &storage_dev_handle, +- (uintptr_t)&image_block_spec, +- open_storage ++ .dev_handle = &storage_dev_handle, ++ .image_spec = (uintptr_t)&image_block_spec, ++ .img_type_guid = STM32MP_FIP_GUID, ++ .check = open_storage + }, ++#ifndef DECRYPTION_SUPPORT_none ++ [ENC_IMAGE_ID] = { ++ .dev_handle = &fip_dev_handle, ++ .image_spec = (uintptr_t)NULL, ++ .img_type_guid = NULL_GUID, ++ .check = open_fip ++ }, ++#endif + #if STM32MP_SDMMC || STM32MP_EMMC + [GPT_IMAGE_ID] = { +- &storage_dev_handle, +- (uintptr_t)&gpt_block_spec, +- open_storage ++ .dev_handle = &storage_dev_handle, ++ .image_spec = (uintptr_t)&gpt_block_spec, ++ .img_type_guid = NULL_GUID, ++ .check = open_storage + }, + #endif ++#if PSA_FWU_SUPPORT ++ [FWU_METADATA_IMAGE_ID] = { ++ .dev_handle = &storage_dev_handle, ++ .image_spec = (uintptr_t)&metadata_block_spec, ++ .img_type_guid = NULL_GUID, ++ .check = open_storage ++ }, ++ [BKUP_FWU_METADATA_IMAGE_ID] = { ++ .dev_handle = &storage_dev_handle, ++ .image_spec = (uintptr_t)&metadata_block_spec, ++ .img_type_guid = NULL_GUID, ++ .check = open_storage ++ }, ++#endif /* PSA_FWU_SUPPORT */ + }; + +-#define FCONF_ST_IO_UUID_NUMBER U(8) ++#define DEFAULT_UUID_NUMBER U(8) ++ ++#if TRUSTED_BOARD_BOOT ++#define TBBR_UUID_NUMBER U(6) ++#else ++#define TBBR_UUID_NUMBER U(0) ++#endif ++ ++#define FCONF_ST_IO_UUID_NUMBER (DEFAULT_UUID_NUMBER + \ ++ TBBR_UUID_NUMBER) + + static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER]; + static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids); +@@ -62,6 +103,14 @@ static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = { + {HW_CONFIG_ID, "hw_cfg_uuid"}, + {TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"}, + {NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"}, ++#if TRUSTED_BOARD_BOOT ++ {TRUSTED_BOOT_FW_CERT_ID, "t_boot_fw_cert_uuid"}, ++ {TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"}, ++ {TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"}, ++ {NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"}, ++ {TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"}, ++ {NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"}, ++#endif /* TRUSTED_BOARD_BOOT */ + }; + + int fconf_populate_stm32mp_io_policies(uintptr_t config) +@@ -111,8 +160,20 @@ int fconf_populate_stm32mp_io_policies(uintptr_t config) + + uuid_ptr->uuid = uuid_helper.uuid_struct; + policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr; +- policies[load_info[i].image_id].dev_handle = &fip_dev_handle; +- policies[load_info[i].image_id].check = open_fip; ++ switch (load_info[i].image_id) { ++#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none) ++ case BL32_IMAGE_ID: ++ case BL32_EXTRA1_IMAGE_ID: ++ case BL32_EXTRA2_IMAGE_ID: ++ policies[load_info[i].image_id].dev_handle = &enc_dev_handle; ++ policies[load_info[i].image_id].check = open_enc_fip; ++ break; ++#endif ++ default: ++ policies[load_info[i].image_id].dev_handle = &fip_dev_handle; ++ policies[load_info[i].image_id].check = open_fip; ++ break; ++ } + } + + return 0; +diff --git a/plat/st/common/stm32mp_gic.c b/plat/st/common/stm32mp_gic.c +new file mode 100644 +index 000000000..e496483e4 +--- /dev/null ++++ b/plat/st/common/stm32mp_gic.c +@@ -0,0 +1,219 @@ ++/* ++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct stm32mp_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 stm32mp_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 = stm32mp_interrupt_props, ++ .interrupt_props_num = ARRAY_SIZE(stm32mp_interrupt_props), ++ .target_masks = target_mask_array, ++ .target_masks_num = ARRAY_SIZE(target_mask_array), ++}; ++ ++static struct stm32mp_gic_instance stm32mp_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, 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; ++} ++ ++static void find_next_interrupt(const fdt32_t **array) ++{ ++ int node; ++ const fdt32_t *cuint; ++ void *fdt; ++ ++ assert(fdt32_to_cpu(**array) != stm32mp_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 stm32mp_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(); ++ } ++ ++ stm32mp_gic.cells = fdt32_to_cpu(*cuint); ++ ++ stm32mp_gic.phandle_node = fdt_get_phandle(fdt, node); ++ if (stm32mp_gic.phandle_node == 0U) { ++ panic(); ++ } ++ ++ gicv2_driver_init(&platform_gic_data); ++ gicv2_distif_init(); ++ ++ stm32mp_gic_pcpu_init(); ++} ++ ++void stm32mp_gic_pcpu_init(void) ++{ ++ gicv2_pcpu_distif_init(); ++ gicv2_set_pe_target_mask(plat_my_core_pos()); ++ gicv2_cpuif_enable(); ++} ++ ++int stm32mp_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 (stm32mp_gic.phandle_node != fdt32_to_cpu(*cuint)) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ } ++ ++ if (name != NULL) { ++ index = fdt_stringlist_search(fdt, node, ++ "secure-interrupt-names", ++ name); ++ if (index < 0) { ++ 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 += stm32mp_gic.cells; ++ } else { ++ if (fdt32_to_cpu(*t_array) == stm32mp_gic.phandle_node) { ++ t_array++; ++ if ((index == -1) || (i == index)) { ++ id = enable_gic_interrupt(t_array); ++ } ++ t_array += stm32mp_gic.cells; ++ } else { ++ find_next_interrupt(&t_array); ++ } ++ } ++ i++; ++ } ++ ++ return id; ++} +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 ++ ++static struct spinlock shregs_lock; ++ ++void stm32mp_lock_shregs(void) ++{ ++ if (stm32mp_lock_available() == 0U) { ++ return; ++ } ++ ++ /* Assume interrupts are masked */ ++ spin_lock(&shregs_lock); ++} ++ ++void stm32mp_unlock_shregs(void) ++{ ++ if (stm32mp_lock_available() == 0U) { ++ return; ++ } ++ ++ spin_unlock(&shregs_lock); ++} ++ ++/* Shared register access: upon shared resource lock */ ++void stm32mp_mmio_clrsetbits_32_shregs(uintptr_t addr, uint32_t clear, ++ uint32_t set) ++{ ++ stm32mp_lock_shregs(); ++ ++ mmio_clrsetbits_32(addr, clear, set); ++ ++ stm32mp_unlock_shregs(); ++} ++ ++void stm32mp_mmio_clrbits_32_shregs(uintptr_t addr, uint32_t clear) ++{ ++ stm32mp_lock_shregs(); ++ ++ mmio_clrbits_32(addr, clear); ++ ++ stm32mp_unlock_shregs(); ++} ++ ++void stm32mp_mmio_setbits_32_shregs(uintptr_t addr, uint32_t set) ++{ ++ stm32mp_lock_shregs(); ++ ++ mmio_setbits_32(addr, set); ++ ++ stm32mp_unlock_shregs(); ++} +diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c +new file mode 100644 +index 000000000..fda53c0e3 +--- /dev/null ++++ b/plat/st/common/stm32mp_trusted_boot.c +@@ -0,0 +1,206 @@ ++/* ++ * Copyright (c) 2020-2021, 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 HEADER_AND_EXT_TOTAL_SIZE 512 ++ ++static uint8_t der_sha256_header[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, ++ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; ++static uint8_t root_pk_hash[HASH_DER_LEN]; ++ ++static int copy_hash_from_otp(const char *otp_name, uint8_t *hash, size_t len) ++{ ++ uint32_t otp_idx; ++ uint32_t otp_len; ++ size_t i; ++ bool valid = false; ++ ++ assert(len % sizeof(uint32_t) == 0); ++ ++ if (stm32_get_otp_index(otp_name, &otp_idx, &otp_len) != 0) { ++ VERBOSE("%s: get %s index error\n", __func__, otp_name); ++ return -EINVAL; ++ } ++ if (otp_len != (len * CHAR_BIT)) { ++ VERBOSE("%s: length Error\n", __func__); ++ return -EINVAL; ++ } ++ ++ for (i = 0U; i < len / sizeof(uint32_t); i++) { ++ uint32_t tmp; ++ uint32_t otp_val; ++ uint32_t first; ++ ++ if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) { ++ VERBOSE("%s: unable to read from otp\n", __func__); ++ return -EINVAL; ++ } ++ ++ tmp = bswap32(otp_val); ++ memcpy(hash + i * sizeof(uint32_t), &tmp, sizeof(tmp)); ++ ++ if (i == 0U) { ++ first = tmp; ++ } ++ ++ /* ++ * Check if key hash values in OTP are 0 or 0xFFFFFFFFF ++ * programmed : Invalid Key ++ */ ++ if (!stm32mp_is_closed_device() && !valid) { ++ if ((tmp != 0U) && (tmp != 0xFFFFFFFFU) && (tmp != first)) { ++ valid = true; ++ } ++ } ++ } ++ ++ if (!stm32mp_is_closed_device() && !valid) { ++ return 0; ++ } ++ ++ return len; ++} ++ ++#if STM32MP13 ++static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len) ++{ ++ int ret; ++ uint32_t pk_idx = 0U; ++ uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++ uint8_t otp_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++ boot_api_image_header_t *hdr = (boot_api_image_header_t *)(SRAM3_BASE + SRAM3_SIZE - ++ HEADER_AND_EXT_TOTAL_SIZE); ++ boot_extension_header_t *ext_header = (boot_extension_header_t *)hdr->ext_header; ++ boot_ext_header_params_authentication_t *param; ++ ++ if (cookie != NULL) { ++ return -EINVAL; ++ } ++ ++ if (hdr->header_version != BOOT_API_HEADER_VERSION) { ++ VERBOSE("%s: unexpected header_version\n", __func__); ++ return -EINVAL; ++ } ++ ++ param = (boot_ext_header_params_authentication_t *)ext_header->params; ++ ++ pk_idx = param->pk_idx; ++ ++ stm32_hash_init(HASH_SHA256); ++ ret = stm32_hash_final_update((uint8_t *)param->pk_hashes, ++ param->nb_pk * sizeof(boot_api_sha256_t), calc_hash); ++ if (ret != 0) { ++ VERBOSE("%s: hash failed\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = copy_hash_from_otp(PKH_OTP, otp_hash, len); ++ if (ret < 0) { ++ return -EINVAL; ++ } ++ ++ if (ret != 0) { ++ ret = memcmp(calc_hash, otp_hash, sizeof(calc_hash)); ++ if (ret != 0) { ++ VERBOSE("%s: not expected digest\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = sizeof(otp_hash); ++ } ++ ++ memcpy(hash, param->pk_hashes[pk_idx], sizeof(otp_hash)); ++ ++ return ret; ++} ++#endif ++ ++#if STM32MP15 ++static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len) ++{ ++ if (cookie != NULL) { ++ return -EINVAL; ++ } ++ ++ return copy_hash_from_otp(PKH_OTP, hash, len); ++} ++#endif ++ ++int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, ++ unsigned int *flags) ++{ ++ size_t start_copy_idx = 0U; ++ int res; ++ ++ memcpy(root_pk_hash, der_sha256_header, sizeof(der_sha256_header)); ++ start_copy_idx = sizeof(der_sha256_header); ++ ++ res = get_rotpk_hash(cookie, root_pk_hash + start_copy_idx, ++ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES); ++ if (res < 0) { ++ return -EINVAL; ++ } ++ ++ *key_len = HASH_DER_LEN; ++ *key_ptr = &root_pk_hash; ++ *flags = ROTPK_IS_HASH; ++ ++ if ((res == 0) && !stm32mp_is_closed_device()) { ++ *flags |= ROTPK_NOT_DEPLOYED; ++ } ++ ++ return 0; ++} ++ ++int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) ++{ ++ *nv_ctr = mmio_read_32(TAMP_BASE + TAMP_COUNTR); ++ ++ return 0; ++} ++ ++int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) ++{ ++ while (mmio_read_32(TAMP_BASE + TAMP_COUNTR) != nv_ctr) { ++ mmio_write_32(TAMP_BASE + TAMP_COUNTR, 1U); ++ } ++ ++ return 0; ++} ++ ++int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) ++{ ++ assert(heap_addr != NULL); ++ assert(heap_size != NULL); ++ ++#if STM32MP_USE_EXTERNAL_HEAP ++ /* Retrieve the already allocated heap's info from DTB */ ++ *heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr); ++ *heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size); ++ ++ /* We expect heap already statically mapped */ ++ ++ return 0; ++#else ++ return get_mbedtls_heap_helper(heap_addr, heap_size); ++#endif ++} +diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c +index 7eaf0ed98..6232d7b3c 100644 +--- a/plat/st/stm32mp1/bl2_plat_setup.c ++++ b/plat/st/stm32mp1/bl2_plat_setup.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,14 +14,18 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +-#include ++#include + #include ++#if STM32MP13 ++#include ++#include ++#endif ++#include + #include +-#include + #include + #include + #include +@@ -34,11 +38,24 @@ + + #include + #include +- +-#define RESET_TIMEOUT_US_1MS 1000U +- +-static console_t console; +-static struct stm32mp_auth_ops stm32mp1_auth_ops; ++#include ++ ++#define PLL1_NOMINAL_FREQ_IN_KHZ 650000U /* 650MHz */ ++ ++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 void print_reset_reason(void) + { +@@ -73,6 +90,7 @@ static void print_reset_reason(void) + return; + } + ++#if STM32MP15 + if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) { + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { + INFO(" System reset generated by MCU (MCSYSRST)\n"); +@@ -81,6 +99,7 @@ static void print_reset_reason(void) + } + return; + } ++#endif + + if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { + INFO(" System reset generated by MPU (MPSYSRST)\n"); +@@ -107,10 +126,12 @@ static void print_reset_reason(void) + return; + } + ++#if STM32MP15 + if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) { + INFO(" MPU Processor 1 Reset\n"); + return; + } ++#endif + + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { + INFO(" Pad Reset from NRST\n"); +@@ -130,6 +151,8 @@ void bl2_el3_early_platform_setup(u_register_t arg0, + u_register_t arg2 __unused, + u_register_t arg3 __unused) + { ++ stm32mp_setup_early_console(); ++ + stm32mp_save_boot_ctx_address(arg0); + } + +@@ -137,16 +160,29 @@ void bl2_platform_setup(void) + { + int ret; + +- if (dt_pmic_status() > 0) { +- initialize_pmic(); +- } +- + ret = stm32mp1_ddr_probe(); + if (ret < 0) { + ERROR("Invalid DDR init: error %d\n", ret); + panic(); + } + ++ if (!stm32mp1_ddr_is_restored()) { ++#if STM32MP15 ++ uintptr_t bkpr_core1_magic = ++ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); ++ uintptr_t bkpr_core1_addr = ++ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); ++ ++ /* Clear backup register */ ++ mmio_write_32(bkpr_core1_addr, 0); ++ /* Clear backup register magic */ ++ mmio_write_32(bkpr_core1_magic, 0); ++#endif ++ ++ /* Clear the context in BKPSRAM */ ++ stm32_clean_context(); ++ } ++ + /* Map DDR for binary load, now with cacheable attribute */ + ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE); +@@ -154,44 +190,64 @@ void bl2_platform_setup(void) + ERROR("DDR mapping: error %d\n", ret); + panic(); + } ++} + +-#if STM32MP_USE_STM32IMAGE +-#ifdef AARCH32_SP_OPTEE +- INFO("BL2 runs OP-TEE setup\n"); +-#else +- INFO("BL2 runs SP_MIN setup\n"); +-#endif +-#endif /* STM32MP_USE_STM32IMAGE */ ++#if STM32MP15 ++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); ++ } + } ++#endif + + void bl2_el3_plat_arch_setup(void) + { +- int32_t result; +- struct dt_node_info dt_uart_info; + const char *board_model; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); +- uint32_t clk_rate; + uintptr_t pwr_base; + uintptr_t rcc_base; ++ bool serial_uart_interface __unused = ++ (boot_context->boot_interface_selected == ++ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART); ++ uintptr_t uart_prog_addr __unused; ++ ++ if (bsec_probe() != 0) { ++ panic(); ++ } + + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + +-#if STM32MP_USE_STM32IMAGE +-#ifdef AARCH32_SP_OPTEE +- 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_RO_DATA | MT_SECURE); +-#endif +-#endif /* STM32MP_USE_STM32IMAGE */ +- + /* Prevent corruption of preloaded Device Tree */ + mmap_add_region(DTB_BASE, DTB_BASE, + DTB_LIMIT - DTB_BASE, +@@ -217,10 +273,6 @@ void bl2_el3_plat_arch_setup(void) + ; + } + +- 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); +@@ -233,59 +285,44 @@ void bl2_el3_plat_arch_setup(void) + mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); + } + +- /* Disable MCKPROT */ +- mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); +- +- generic_delay_timer_init(); +- +- if (stm32mp1_clk_probe() < 0) { +- panic(); ++ /* Set minimum reset pulse duration to 31ms for discrete power supplied boards */ ++ if (dt_pmic_status() <= 0) { ++ mmio_clrsetbits_32(rcc_base + RCC_RDLSICR, RCC_RDLSICR_MRD_MASK, ++ 31U << RCC_RDLSICR_MRD_SHIFT); + } + +- if (stm32mp1_clk_init() < 0) { +- panic(); +- } +- +- stm32mp1_syscfg_init(); +- +- result = dt_get_stdout_uart_info(&dt_uart_info); ++ generic_delay_timer_init(); + +- if ((result <= 0) || +- (dt_uart_info.status == 0U) || +- (dt_uart_info.clock < 0) || +- (dt_uart_info.reset < 0)) { +- goto skip_console_init; +- } ++#if STM32MP_UART_PROGRAMMER ++ uart_prog_addr = get_uart_address(boot_context->boot_interface_instance); + +- if (dt_set_stdout_pinctrl() != 0) { +- goto skip_console_init; ++ /* Disable programmer UART before changing clock tree */ ++ if (serial_uart_interface) { ++ stm32_uart_stop(uart_prog_addr); + } +- +- stm32mp_clk_enable((unsigned long)dt_uart_info.clock); +- +- if (stm32mp_reset_assert((uint32_t)dt_uart_info.reset, +- RESET_TIMEOUT_US_1MS) != 0) { ++#endif ++ if (stm32mp1_clk_probe() < 0) { + panic(); + } + +- udelay(2); +- +- if (stm32mp_reset_deassert((uint32_t)dt_uart_info.reset, +- RESET_TIMEOUT_US_1MS) != 0) { ++ if (stm32mp1_clk_init(PLL1_NOMINAL_FREQ_IN_KHZ) < 0) { + panic(); + } + +- mdelay(1); ++ stm32_save_boot_interface(boot_context->boot_interface_selected, ++ boot_context->boot_interface_instance); + +- clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock); ++#if STM32MP_USB_PROGRAMMER && STM32MP15 ++ /* Deconfigure all UART RX pins configured by ROM code */ ++ stm32mp1_deconfigure_uart_pins(); ++#endif + +- if (console_stm32_register(dt_uart_info.base, clk_rate, +- STM32MP_UART_BAUDRATE, &console) == 0) { +- panic(); ++ if (stm32mp_uart_console_setup() != 0) { ++ goto skip_console_init; + } + +- console_set_scope(&console, CONSOLE_FLAG_BOOT | +- CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF); ++ /* Enter in boot mode */ ++ stm32mp1_syscfg_boot_mode_enable(); + + stm32mp_print_cpuinfo(); + +@@ -303,40 +340,89 @@ void bl2_el3_plat_arch_setup(void) + } + + skip_console_init: +- if (stm32_iwdg_init() < 0) { ++#if !TRUSTED_BOARD_BOOT ++ if (stm32mp_is_closed_device()) { ++ /* Closed chip required authentication */ ++ ERROR("Secured chip must enabled TRUSTED_BOARD_BOOT\n"); + panic(); + } ++#endif + +- stm32_iwdg_refresh(); ++ if (fixed_regulator_register() != 0) { ++ panic(); ++ } + +- result = stm32mp1_dbgmcu_freeze_iwdg2(); +- if (result != 0) { +- INFO("IWDG2 freeze error : %i\n", result); ++ if (dt_pmic_status() > 0) { ++ initialize_pmic(); ++ if (!stm32mp1_is_wakeup_from_standby() && ++ pmic_voltages_init() != 0) { ++ ERROR("PMIC voltages init failed\n"); ++ panic(); ++ } ++ print_pmic_info_and_debug(); + } + +- if (stm32_save_boot_interface(boot_context->boot_interface_selected, +- boot_context->boot_interface_instance) != +- 0) { +- ERROR("Cannot save boot interface\n"); ++ stm32mp1_syscfg_init(); ++ ++ if (stm32_iwdg_init() < 0) { ++ panic(); + } + +- stm32mp1_auth_ops.check_key = boot_context->bootrom_ecdsa_check_key; +- stm32mp1_auth_ops.verify_signature = +- boot_context->bootrom_ecdsa_verify_signature; ++ stm32_iwdg_refresh(); + +- stm32mp_init_auth(&stm32mp1_auth_ops); ++ if (bsec_read_debug_conf() != 0U) { ++ if (stm32mp_is_closed_device()) { ++ NOTICE("\n%s", debug_msg); ++ } ++ } ++ ++#if STM32MP13 ++ if (stm32_rng_init() != 0) { ++ panic(); ++ } ++#endif + + stm32mp1_arch_security_setup(); + + print_reset_reason(); + +-#if !STM32MP_USE_STM32IMAGE ++#if STM32MP15 ++ update_monotonic_counter(); ++#endif ++ ++ stm32mp1_syscfg_enable_io_compensation_finish(); ++ + fconf_populate("TB_FW", STM32MP_DTB_BASE); +-#endif /* !STM32MP_USE_STM32IMAGE */ + + stm32mp_io_setup(); + } + ++#if STM32MP13 ++static void prepare_encryption(void) ++{ ++ uint8_t mkey[MCE_KEY_SIZE_IN_BYTES]; ++ ++ stm32_mce_init(); ++ ++ if (stm32mp1_is_wakeup_from_standby()) { ++ stm32mp1_pm_get_mce_mkey_from_context(mkey); ++ } else { ++ /* Generate MCE master key from RNG */ ++ if (stm32_rng_read(mkey, MCE_KEY_SIZE_IN_BYTES) != 0) { ++ panic(); ++ } ++ ++ stm32mp1_pm_save_mce_mkey_in_context(mkey); ++ } ++ ++ if (stm32_mce_write_master_key(mkey) != 0) { ++ panic(); ++ } ++ ++ stm32_mce_lock_master_key(); ++} ++#endif ++ + /******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. +@@ -348,30 +434,40 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + bl_mem_params_node_t *bl32_mem_params; + bl_mem_params_node_t *pager_mem_params __unused; + bl_mem_params_node_t *paged_mem_params __unused; +-#if !STM32MP_USE_STM32IMAGE + const struct dyn_cfg_dtb_info_t *config_info; + bl_mem_params_node_t *tos_fw_mem_params; + unsigned int i; ++ unsigned int idx; + unsigned long long ddr_top __unused; ++ bool wakeup_ddr_sr = stm32mp1_ddr_is_restored(); + const unsigned int image_ids[] = { + BL32_IMAGE_ID, + BL33_IMAGE_ID, + HW_CONFIG_ID, + TOS_FW_CONFIG_ID, + }; +-#endif /* !STM32MP_USE_STM32IMAGE */ + + assert(bl_mem_params != NULL); + + switch (image_id) { +-#if !STM32MP_USE_STM32IMAGE + case FW_CONFIG_ID: ++#if STM32MP13 ++ if (stm32mp_is_closed_device() || stm32mp_is_auth_supported()) { ++ prepare_encryption(); ++ } ++#endif + /* Set global DTB info for fixed fw_config information */ + set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID); + fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE); + ++ idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID); ++ + /* Iterate through all the fw config IDs */ + for (i = 0U; i < ARRAY_SIZE(image_ids); i++) { ++ if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) { ++ continue; ++ } ++ + bl_mem_params = get_bl_mem_params_node(image_ids[i]); + assert(bl_mem_params != NULL); + +@@ -383,7 +479,13 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + bl_mem_params->image_info.image_base = config_info->config_addr; + bl_mem_params->image_info.image_max_size = config_info->config_max_size; + +- bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; ++ /* ++ * If going back from CSTANDBY / STANDBY and DDR was in Self-Refresh, ++ * DDR partitions must not be reloaded. ++ */ ++ if (!(wakeup_ddr_sr && (config_info->config_addr >= STM32MP_DDR_BASE))) { ++ bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; ++ } + + switch (image_ids[i]) { + case BL32_IMAGE_ID: +@@ -398,13 +500,20 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + /* Init base and size for pager if exist */ + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + paged_mem_params->image_info.image_base = STM32MP_DDR_BASE + +- (dt_get_ddr_size() - STM32MP_DDR_S_SIZE - +- STM32MP_DDR_SHMEM_SIZE); ++ (dt_get_ddr_size() - STM32MP_DDR_S_SIZE); + paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE; + break; + + case BL33_IMAGE_ID: +- bl_mem_params->ep_info.pc = config_info->config_addr; ++ if (wakeup_ddr_sr) { ++ /* ++ * Set ep_info PC to 0, to inform BL32 it is a reset ++ * after STANDBY ++ */ ++ bl_mem_params->ep_info.pc = 0U; ++ } else { ++ bl_mem_params->ep_info.pc = config_info->config_addr; ++ } + break; + + case HW_CONFIG_ID: +@@ -416,28 +525,29 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + } + } + break; +-#endif /* !STM32MP_USE_STM32IMAGE */ + + case BL32_IMAGE_ID: ++#if STM32MP13 ++ if (wakeup_ddr_sr) { ++ bl_mem_params->ep_info.pc = stm32_pm_get_optee_ep(); ++ break; ++ } ++#endif + if (optee_header_is_valid(bl_mem_params->image_info.image_base)) { + /* BL32 is OP-TEE header */ + bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base; ++ if (wakeup_ddr_sr) { ++ bl_mem_params->ep_info.pc = stm32_pm_get_optee_ep(); ++ if (stm32mp1_addr_inside_backupsram(bl_mem_params->ep_info.pc)) { ++ clk_enable(BKPSRAM); ++ } ++ ++ break; ++ } + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert((pager_mem_params != NULL) && (paged_mem_params != NULL)); + +-#if STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) +- /* Set OP-TEE extra image load areas at run-time */ +- pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE; +- pager_mem_params->image_info.image_max_size = STM32MP_OPTEE_SIZE; +- +- 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; +-#endif /* STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) */ +- + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); +@@ -451,20 +561,25 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) + bl_mem_params->ep_info.args.arg1 = 0; /* Unused */ + bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */ + } else { +-#if !STM32MP_USE_STM32IMAGE + bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base; + tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID); + bl_mem_params->image_info.image_max_size += + tos_fw_mem_params->image_info.image_max_size; +-#endif /* !STM32MP_USE_STM32IMAGE */ + bl_mem_params->ep_info.args.arg0 = 0; + } ++ ++ if (bl_mem_params->ep_info.pc >= STM32MP_DDR_BASE) { ++ stm32_context_save_bl2_param(); ++ } + break; + + case BL33_IMAGE_ID: + 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; ++#if PSA_FWU_SUPPORT ++ stm32mp1_fwu_set_boot_idx(); ++#endif /* PSA_FWU_SUPPORT */ + break; + + default: +@@ -493,16 +608,20 @@ void bl2_el3_plat_prepare_exit(void) + uint16_t boot_itf = stm32mp_get_boot_itf_selected(); + + switch (boot_itf) { +-#if STM32MP_USB_PROGRAMMER ++#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + /* Invalidate the downloaded buffer used with io_memmap */ + inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE); + break; +-#endif ++#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */ + default: + /* Do nothing in default case */ + break; + } + + stm32mp1_security_setup(); ++ ++ /* end of boot mode */ ++ stm32mp1_syscfg_boot_mode_disable(); + } +diff --git a/plat/st/stm32mp1/default_metadata.json b/plat/st/stm32mp1/default_metadata.json +new file mode 100644 +index 000000000..bd40f04d2 +--- /dev/null ++++ b/plat/st/stm32mp1/default_metadata.json +@@ -0,0 +1,37 @@ ++{ ++ "copyright": "Copyright (c) 2022, STMicroelectronics - All Rights Reserved", ++ "license": "SPDX-License-Identifier: BSD-3-Clause", ++ ++ "metadata": { ++ "version": 0, ++ "active_index": 0, ++ "previous_active_index": 1, ++ "img_entry": { ++ "img_0": { ++ "location": "device0", ++ "img_bank_info": { ++ "img_0_bank_0": { ++ "accepted": true ++ }, ++ "img_0_bank_1": { ++ "accepted": false ++ } ++ } ++ } ++ } ++ }, ++ "uuids": { ++ "locations": { ++ "device0": "00000000-0000-0000-0000-000000000000" ++ }, ++ "entries": { ++ "img_0_bank_0": "4fd84c93-54ef-463f-a7ef-ae25ff887087", ++ "img_0_bank_1": "09c54952-d5bf-45af-acee-335303766fb3", ++ "img_0": "19d5df83-11b0-457b-be2c-7559c13142a5" ++ } ++ }, ++ "configs": { ++ "nb_fw_img": 1, ++ "nb_fw_banks": 2 ++ } ++} +diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h +index 52b1d1aa0..02af31a8c 100644 +--- a/plat/st/stm32mp1/include/boot_api.h ++++ b/plat/st/stm32mp1/include/boot_api.h +@@ -10,15 +10,121 @@ + #include + #include + ++/* ++ * Exported constants ++ */ ++ ++/* ++ * Boot Context related definitions ++ */ ++ ++/* ++ * Possible value of boot context field 'boot_action' ++ */ ++#if STM32MP13 ++/* Boot action is Process Secure Boot */ ++#define BOOT_API_CTX_BOOT_ACTION_SECURE_BOOT_PROCESS 0x7879598EUL ++/* Boot action is Process Wakeup from STANDBY */ ++#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY 0x21276323UL ++/* Boot action is Process Engineering Boot */ ++#define BOOT_API_CTX_BOOT_ACTION_ENGI_BOOT 0x4A05FE3AUL ++/* Boot Action is MPU P0 Local reset */ ++#define BOOT_API_CTX_BOOT_ACTION_MPU_CORE0_RESET_PROCESS 0x0F6C12ABUL ++#endif ++#if STM32MP15 ++/* Boot action is Process Cold Boot */ ++#define BOOT_API_CTX_BOOT_ACTION_COLD_BOOT_PROCESS 0x09U ++/* Boot action is Process Wakeup from CSTANDBY */ ++#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY 0x0AU ++/* Boot action is Process Wakeup from STANDBY */ ++#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY 0x0BU ++/* Boot action is Process Engineering Boot */ ++#define BOOT_API_CTX_BOOT_ACTION_ENGI_BOOT 0x0CU ++/* Boot Action is MPU P0 Local reset */ ++#define BOOT_API_CTX_BOOT_ACTION_MPU_CORE0_RESET_PROCESS 0x0F ++#endif ++ ++/* ++ * Possible value of boot context field 'stby_exit_status' ++ */ ++ ++/* The boot reason is not a STANDBY Exit reason */ ++#define BOOT_API_CTX_STBY_EXIT_STATUS_NO_STANDBY 0x00 ++ ++/* STANDBY Exit with MPU_BEN=1, MCU_BEN=0 */ ++#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MPU_ONLY 0x01 ++ ++/* ++ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MPU will go for cold boot ++ * MCU restarted by bootROM ++ */ ++#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES 0x02 ++ ++/* ++ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MPU will go for cold boot ++ * but MCU restart aborted (code integrity check) : have not been restarted ++ * by bootROM ++ */ ++#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES_MCU_ABT 0x03 ++ ++/* ++ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MPU gone to CSTANDBY, ++ * MCU restarted correctly by bootROM ++ * This value should never be read by FSBL, because not executed in that case ++ */ ++#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY 0x04 ++ ++/* ++ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MCU restart aborted ++ * due code integrity check, then MPU will go for cold boot despite ++ * was not planned initially ++ */ ++#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY_MCU_ABT 0x05 ++ ++/* ++ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MCU restart aborted ++ * due to MCU security perimeter issue ++ */ ++#define \ ++BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES_MCU_ABT_SEC_PERIMETER_ISSUE 0x06 ++ ++/* ++ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MCU restart aborted ++ * due to MCU security perimeter issue, then MPU will go for cold boot ++ * despite was not planned initially ++ */ ++#define \ ++BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY_MCU_ABT_SEC_PERIMETER_ISSUE 0x07 ++ ++/* ++ * Possible value of boot context field 'cstby_exit_status' ++ */ ++/* The boot reason is not a CSTANDBY Exit reason */ ++#define BOOT_API_CTX_CSTBY_EXIT_STATUS_NO_CSTBY 0x00 ++/* CSTANDBY Exit with MCU detected as Not running */ ++#define BOOT_API_CTX_CSTBY_EXIT_STATUS_MCU_NOT_RUNNING 0x01 ++/* 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' + */ ++#if STM32MP13 ++ /* No authentication done */ ++#define BOOT_API_CTX_AUTH_NO 0x7CFDD351U ++ /* Authentication done and failed */ ++#define BOOT_API_CTX_AUTH_FAILED 0x51330884U ++ /* Authentication done and success */ ++#define BOOT_API_CTX_AUTH_SUCCESS 0x67E8CAE1U ++#endif ++#if STM32MP15 + /* No authentication done */ + #define BOOT_API_CTX_AUTH_NO 0x0U + /* Authentication done and failed */ + #define BOOT_API_CTX_AUTH_FAILED 0x1U + /* Authentication done and succeeded */ + #define BOOT_API_CTX_AUTH_SUCCESS 0x2U ++#endif + + /* + * Possible value of boot context field 'boot_interface_sel' +@@ -39,6 +145,9 @@ + /* Boot occurred on QSPI NOR */ + #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U + ++/* Boot occurred on UART */ ++#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U ++ + /* Boot occurred on USB */ + #define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U + +@@ -67,11 +176,21 @@ + #define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND 0x5U + #define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U + #define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U ++#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_ERROR 0x8U ++ ++/* Definitions relative to 'p_rom_version_info->platform_type_ver' field */ ++#define BOOT_API_CTX_ROM_VERSION_PLAT_VER_IC_EMU_FPGA 0xAA ++#define BOOT_API_CTX_ROM_VERSION_PLAT_VER_FPGA_ONLY 0xBB + + /* Image Header related definitions */ + + /* Definition of header version */ ++#if STM32MP13 ++#define BOOT_API_HEADER_VERSION 0x00020000U ++#endif ++#if STM32MP15 + #define BOOT_API_HEADER_VERSION 0x00010000U ++#endif + + /* + * Magic number used to detect header in memory +@@ -90,6 +209,49 @@ + #define BOOT_API_ECDSA_ALGO_TYPE_P256NIST 1 + #define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256 2 + ++/* ++ * Extension headers related definitions ++ */ ++/* 'bootapi_image_header_t.extension_flag' used for authentication feature */ ++#define BOOT_API_AUTHENTICATION_EXTENSION_BIT BIT(0) ++/* 'bootapi_image_header_t.extension_flag' used for FSBL decryption feature */ ++#define BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT BIT(1) ++/* 'bootapi_image_header_t.extension_flag' used for padding header feature */ ++#define BOOT_API_PADDING_EXTENSION_BIT BIT(31) ++/* ++ * mask of bits of field 'bootapi_image_header_t.extension_flag' ++ * used for extension headers ++ */ ++#define BOOT_API_ALL_EXTENSIONS_MASK \ ++ (BOOT_API_AUTHENTICATION_EXTENSION_BIT | \ ++ BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT | \ ++ BOOT_API_PADDING_EXTENSION_BIT) ++/* ++ * Magic number of FSBL decryption extension header ++ * The value shall gives the four bytes 'S','T',0x00,0x01 in memory ++ */ ++#define BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB 0x01005453U ++ ++/* ++ * Magic number of PKH revocation extension header ++ * The value shall gives the four bytes 'S','T',0x00,0x02 in memory ++ */ ++#define BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB 0x02005453U ++ ++/* Max number of ECDSA public key hash in table */ ++#define BOOT_API_AUTHENTICATION_NB_PKH_MAX 8U ++ ++/* ECDSA public key hash table size in bytes */ ++#define BOOT_API_AUTHENTICATION_TABLE_SIZE_BYTES \ ++ (BOOT_API_AUTHENTICATION_NB_PKH_MAX * \ ++ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) ++ ++/* ++ * Magic number of padding extension header ++ * The value shall gives the four bytes 'S','T',0xFF,0xFF in memory ++ */ ++#define BOOT_API_PADDING_HEADER_MAGIC_NB 0xFFFF5453U ++ + /* + * Cores secure magic numbers + * Constant to be stored in bakcup register +@@ -98,6 +260,64 @@ + #define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U + #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U + ++/* ++ * MCU Code Integrity Check related definitions ++ */ ++ ++/* ++ * Defines to identify RTC backup registers to be used for MCU code integrity ++ * check ++ */ ++ ++/* ++ * TAMP_BCK0R contains two bits ++ * bit 0 : wanted value of 'RCC_TZCR.TZEN' ++ * bit 1 : wanted value of 'RCC_TZCR.MCKPROT' ++ */ ++ ++/* ++ * TAMP_BCK0R bit position coding wanted value of 'RCC_TZCR.TZEN' ++ * trustZone aware domain enabling/disabling ++ */ ++#define BOOT_API_MCIC_MCU_SECURITY_PERIMETER_TZEN_BIT 0 ++ ++/* ++ * TAMP_BCK0R bit position coding wanted value of 'RCC_TZCR.MCKPROT' ++ * ability of MCU to modify some clock settings in RCC ++ */ ++#define BOOT_API_MCIC_MCU_SECURITY_PERIMETER_MCKPROT_BIT 1 ++ ++/* TAMP_BCK0R register index */ ++#define \ ++BOOT_API_MCIC_MCU_SECURITY_PERIMETER_TZEN_MCKPROT_TAMP_BCK_REG_IDX 0 ++ ++/* ++ * TAMP_BCK1R register index ++ * This register is coding the wanted value of register 'EXTI_TZENR1' ++ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1 ++ * that is MCU quick restart requested ++ */ ++#define \ ++BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR1_TAMP_BCK_REG_IDX 1 ++ ++/* ++ * TAMP_BCK2R register index ++ * This register is coding the wanted value of register 'EXTI_TZENR2' ++ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1 ++ * that is MCU quick restart requested ++ */ ++#define \ ++BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR2_TAMP_BCK_REG_IDX 2 ++ ++/* ++ * TAMP_BCK3R register index ++ * This register is coding the wanted value of register 'EXTI_TZENR3' ++ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1 ++ * that is MCU quick restart requested ++ */ ++#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 +@@ -112,6 +332,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 ++ */ ++#define \ ++BOOT_API_MCIC_OFFSET_IN_BYTES_CODE_TO_HASH_RETRAM_TAMP_BCK_REG_IDX 22 ++ ++/* ++ * TAMP_BCK23R register index ++ * This register contains the size in bytes of the single consecutive region ++ * of MCU Firmware in RETRAM (Retention RAM) to hash (by SHA-256) ++ * Note : This is required as a MCU firmware Code Integrity Check (aka : MCIC) ++ * to avoid bootROM restarting MCU on a corrupted firmware ++ */ ++#define \ ++BOOT_API_MCIC_RETRAM_REGION_TO_HASH_IN_BYTES_TAMP_BCK_REG_IDX 23 ++ ++/* ++ * TAMP_BCK24R to TAMP_BCK31R register indexes ++ * Those registers contains SHA-256 digest of RETRAM MCU Firmware code between ++ * [(RETRAM_start + offset) -- (RETRAM_start + offset + size_to_hash)] ++ * in this order ++ * This is the MCU Code Integrity Check MCU Firmware signature ++ * value on 256 bits ++ */ ++ ++/* First TAMP_BKP index of MCU Firmware signature : ie TAMP_BCK24R */ ++#define BOOT_API_MCIC_SHA_DIGEST_FIRST_TAMP_BCK_REG_IDX 24 ++ ++/* 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' + */ +@@ -138,6 +391,343 @@ + + #define BOOT_API_RETURN_OK 0x77U + ++/* Mapping of OTP Word and OTP bits managing SSP and useful to FSBL-SSP */ ++#if STM32MP13 ++/* OTP_CFG9 */ ++#define BOOT_API_OTP_SSP_WORD_NB 9U ++/* SSP_REQ = OTP_CFG9[5] */ ++#define BOOT_API_OTP_SSP_REQ_BIT_POS 5 ++/* SSP_SUCCESS = OTP_CFG9[6] */ ++#define BOOT_API_OTP_SSP_SUCCESS_BIT_POS 6 ++#endif ++#if STM32MP15 ++/* OTP_CFG8 */ ++#define BOOT_API_OTP_SSP_WORD_NB 8U ++/* SSP_REQ = OTP_CFG8[8] */ ++#define BOOT_API_OTP_SSP_REQ_BIT_POS 8 ++/* SSP_SUCCESS = OTP_CFG8[9] */ ++#define BOOT_API_OTP_SSP_SUCCESS_BIT_POS 9 ++#endif ++ ++/* ++ * Possible values of boot context field ++ * 'ssp_config_ptr_in->ssp_cmd' ++ */ ++/* 'K' 'B' 'U' 'P' -.> 'PUBK' */ ++#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK 0x4B425550 ++ ++#if STM32MP_SSP ++/* 'V' 'O' 'R' 'P' -.> 'PROV' */ ++#define BOOT_API_CTX_SSP_CMD_PROV_SECRET 0x564F5250 ++/* ++ * Possible values of boot context field ++ * 'ssp_config_ptr_in->ssp_cmd' written by bootROM as Acknowledge ++ * of a request of SSP by FSBL. ++ */ ++ ++/* Written by bootROM on SSP error */ ++#define BOOT_API_CTX_SSP_CMD_INVALID 0x00000000 ++/* ++ * 'A' 'B' 'U' 'P' -.> 'PUBA' : ACK of ECIES_CHIP_PUBK calculation ++ * request by bootROM. ++ */ ++#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK 0x41425550 ++/* ++ * 'A' 'O' 'R' 'P' -.> 'PROA' : ACK of OEM Secret Provisioning request ++ * by bootROM. ++ */ ++#define BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK 0x414F5250 ++ ++/* ++ * Constants required for SSP ++ */ ++/* '.' 'P' 'S' 'S' -.> 'SSP.' */ ++#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_NORMAL 0x2E505353 ++/* 'L' 'P' 'S' 'S' -.> 'SSPL' */ ++#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_LIVE 0x4C505353 ++/* version 1 */ ++#define BOOT_API_SSP_LICENSE_LAYOUT_VERSION_TO_MATCH 0x00000001 ++/* 'P' 'P' 'S' 'S' -.> 'SSPP' */ ++#define BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP 0x50505353 ++/* IV AES on 128 bits = 16 bytes and KEY AES on 128 bits = 16 bytes */ ++#define BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES 32 ++/* version 1 */ ++#define BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH 0x00000001 ++/* ++ * Scalar in Elliptic curve cryptography is an integer (often a Prime) ++ * the number of bytes of this scalar is defined below. ++ */ ++#define BOOT_API_SSP_SCALAR_SIZE_BYTES 32 ++ ++/* ++ * In Elliptic curve cryptography coordinates of points are 2D P ++ * (Px, Py) as concatenation of two scalars. ++ */ ++#define BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES \ ++ (2 * BOOT_API_SSP_SCALAR_SIZE_BYTES) ++ ++/* In Elliptic curve cryptography Private Keys are scalars */ ++#define BOOT_API_SSP_PRIVK_KEY_SIZE_BYTES \ ++ BOOT_API_SSP_SCALAR_SIZE_BYTES ++ ++/* ++ * In ECIES algorithm the Shared Secret (SS) is ++ * the x coordinate (Px) of a point P(Px,Py) obtained on reference ++ * chosen NIST-P256 Elliptic curve. ++ */ ++#define BOOT_API_SSP_ECDH_SHARED_SECRET_SIZE_BYTES \ ++ BOOT_API_SSP_SCALAR_SIZE_BYTES ++ ++/* ++ * In Elliptic curve cryptography Public Keys are Points on chosen ++ * Elliptic curve P(x,y). ++ * Public Key is the x, y coordinates concatenated ++ * Ecies_eph_pubk and OEM_ECDSA_PUBK are each 64 bytes = 512 bits key ++ * sizes. ++ */ ++#define BOOT_API_SSP_PUBK_KEY_SIZE_BYTES \ ++ BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES ++ ++/* ++ * Size in bytes of ECIES_Chip_pubk obtained from bootROM at end of SSP ++ * phase 1 : Chip public key calculation. ++ */ ++#define BOOT_API_SSP_ECIES_CHIP_PUBK_SIZE_BYTES \ ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES ++ ++/* AES-GCM authentication tag size is 16 bytes = 128 bits */ ++#define BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES 16 ++ ++/* AES-GCM Symmetric Key size is 16 bytes = 128 bits */ ++#define BOOT_API_SSP_AES_GCM_KEY_SIZE_BYTES 16 ++ ++/* AES-GCM Initialization Vector (IV) size is of 16 bytes = 128 bits */ ++#define BOOT_API_SSP_AES_GCM_IV_SIZE_BYTES 16 ++ ++/* ++ * 88 bytes (license_type, live_session_id, license_version, ++ * fsbl_min_version, rfu[8], eph_ecies_pubk[]) ++ */ ++#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE 88 ++ ++/* ++ * 32 bytes AAD License Secret from 2nd round KDF-SHA-256 ++ * from ECDH Shared Secret hence KDF[32..63] aka "Authorization Token" ++ */ ++#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF 32 ++ ++/* ++ * Total License AAD size = 88 + 32 = 120 bytes ++ */ ++#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_SIZE_BYTES \ ++ (BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE + \ ++ BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF) ++ ++/* ++ * AAD for Payload size : composed of : ++ * payload_magic, payload_protocol_version, oem_ecdsa_pubk[], oem_secret_size ++ * = 4 + 4 + 64 + 4 = 76 bytes AAD for Payload ++ */ ++#define BOOT_API_SSP_AES_GCM_PAYLOAD_AAD_SIZE_BYTES 76 ++ ++/* ++ * OEM Secrets max size in bytes : ++ * [OTP[95:59] + OTP_CFG56 (RMA Unlock and Relock passwords)] x 4 bytes ++ * by OTP word = 152 bytes ++ */ ++#define BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES 152 ++ ++/* ++ * Possible values of boot context field 'ssp_status' ++ * as can be read by FSBL-SSP ++ */ ++#define BOOT_API_CTX_SSP_STATUS_NO_SSP 0 ++#define BOOT_API_CTX_SSP_STATUS_CHIP_PUBK_CALC_FINISHED 1 ++#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FINISHED 2 ++#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FORBIDDEN 3 ++ ++/* ++ * Reserved size for future use ++ */ ++#define BOOT_API_SSP_HSM_OEM_RFU_SIZE 8 ++ ++/* ++ * Exported types ++ */ ++ ++/* ++ * SSP related definitions ++ */ ++/* ++ * SSP BLOB License structure : Binary Large OBject License structure ++ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret ++ * provisioning. ++ * License information data, the structure is read by bootROM. ++ */ ++typedef struct { ++ /* ++ * License Type provided by HSM-OEM tool ++ * should match Normal SSP License of Live SSP License. ++ */ ++ uint32_t license_type; ++ ++ /* Live Session ID provided by HSM-OEM tool */ ++ uint32_t live_session_id; ++ ++ /* ++ * Version of the License Protocol (Structure) ++ * should be incremented each time a new. ++ */ ++ uint32_t license_version; ++ ++ /* ++ * Minimum FSBL version to be compared ++ * with FSBL Header field 'imageVersion'. ++ */ ++ uint32_t fsbl_min_version; ++ ++ /* RFU provided by HSM-OEM tool */ ++ uint8_t rfu[BOOT_API_SSP_HSM_OEM_RFU_SIZE]; ++ ++ /* ++ * Ephemeral ECIES Public Key from HSM-OEM ++ * 64 bytes = 512 bits. ++ */ ++ uint8_t eph_ecies_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES]; ++ ++ /* ++ * Encrypted (IV,Key) : with Shared Secret based on ++ * 'Ephemeral ECIES Key pair' and 'ECIES Chip Key pair'. ++ */ ++ uint8_t encrypted_iv_and_key ++ [BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES]; ++ ++ /* ++ * AUTH_TAG AES-GCM from encryption of (IV, Key) ++ * in HSM-OEM with License AAD scheme ++ * License Tag is 16 bytes = 128 bits. ++ */ ++ uint8_t license_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES]; ++ ++} boot_api_ssp_blob_license_t; ++ ++/* ++ * SSP BLOB Payload structure : Binary Large OBject Payload Structure ++ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret ++ * provisioning input data, the structure is read by bootROM ++ * The BLOB Payload size is fixed to a max size of 244 bytes based ++ * on a max number of bytes of OEM secret derived from OTP upper free ++ * area in STM32MP15xx cut 2.0.In this table oem_encrypted_secrets[] ++ * of max size only the first 'p_blob_payload->oem_secret_size_bytes' ++ * bytes will be considered and used by bootROM. ++ */ ++typedef struct { ++ /* ++ * BLOB Payload Magic : for memory validity check of BLOB Payload ++ * to match against BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP by bootROM. ++ */ ++ uint32_t payload_magic; ++ ++ /* ++ * SSP Payload protocol version : on 32 bits ++ * to be checked by bootROM for equality with ++ * BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH ++ * ie : 0x00000001 : version 1 of SSP Payload ++ */ ++ uint32_t payload_protocol_version; ++ ++#if STM32MP13 ++ /* OEM_RPKTH OEM Root Public Key table hash is the ++ * hash[ hash(algo + pubK i) for i=0..N-1] where N ++ * is the number of OEM public keys in product for ++ * key revocation feature ++ * ++ * N = 8 for STM32MP13xx ++ * size of field = 32 bytes = 256 bits ++ */ ++ uint8_t oem_rpkth[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++#endif ++#if STM32MP15 ++ /* ++ * OEM_ECDSA_PUBK Public Key defined by OEM ++ * 64 bytes = 512 bits ++ */ ++ uint8_t oem_ecdsa_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES]; ++#endif ++ ++ /* ++ * Size of Table of OEM Secrets encrypted with AES-GCM (Key,IV) from ++ * License field 'encrypted_iv_and_key[]' ++ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES: ++ * is verified by bootROM. ++ */ ++ uint32_t oem_secret_size_bytes; ++ ++ /* ++ * AUTH_TAG AES-GCM computed by HSM-OEM when encrypting OEM Secrets with ++ * (Key,IV) using special AAD scheme for Payload. ++ * 16 bytes = 128 bits ++ */ ++ uint8_t payload_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES]; ++ ++ /* ++ * OEM Secrets encrypted with AES-GCM (IV, Key) from ++ * License field 'encrypted_iv_and_key[]'. ++ * The payload size is 'oem_secret_size_bytes' ++ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES = ++ * 152 bytes : OEM Secrets max size in bytes : ++ * [OTP_CFG56, OTP_CFG59, OTP_CFG60..95] x 4 bytes by OTP word. ++ */ ++ uint8_t oem_encrypted_secrets[BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES]; ++ ++} boot_api_ssp_blob_payload_t; ++#endif ++ ++/* SSP Configuration structure */ ++typedef struct { ++ /* SSP Command*/ ++ uint32_t ssp_cmd; ++#if STM32MP_SSP ++ /* ECIES chip public key */ ++ uint8_t *p_chip_pubk; ++ /* Blob License Address */ ++ boot_api_ssp_blob_license_t *p_blob_license; ++ /* Blob Payload Address */ ++ boot_api_ssp_blob_payload_t *p_blob_payload; ++ /* Secrets Decrypted Address */ ++ uint8_t *p_ssp_oem_secrets_decrypted; ++ /* Reserved for Future Use (RFU) */ ++ uint32_t padding_rfu; ++#else ++ uint8_t reserved[20]; ++#endif ++} boot_api_ssp_config_t; ++ ++/* ++ * bootROM version information structure definition ++ * Total size = 24 bytes = 6 uint32_t ++ */ ++typedef struct { ++ /* Chip Version */ ++ uint32_t chip_ver; ++ ++ /* Cut version within a fixed chip version */ ++ uint32_t cut_ver; ++ ++ /* Version of ROM Mask within a fixed cut version */ ++ uint32_t rom_mask_ver; ++ ++ /* Internal Version of bootROM code */ ++ uint32_t bootrom_ver; ++ ++ /* Version of bootROM adapted */ ++ uint32_t for_chip_design_rtl_ver; ++ ++ /* Restriction on compiled platform when it applies */ ++ uint32_t platform_type_ver; ++ ++} boot_api_rom_version_info_t; ++ + /* + * Boot Context related definitions + */ +@@ -154,29 +744,49 @@ typedef struct { + */ + uint16_t boot_interface_selected; + uint16_t boot_interface_instance; ++#if STM32MP15 + uint32_t reserved1[13]; ++#endif ++#if STM32MP13 ++ uint32_t reserved1[12]; ++#endif + uint32_t otp_afmux_values[3]; +- uint32_t reserved[5]; ++ uint32_t reserved[2]; ++ /* ++ * Log to boot context, what was the kind of boot action ++ * takes values from defines BOOT_API_BOOT_ACTION_XXX above ++ */ ++ uint32_t boot_action; ++#if STM32MP15 ++ /* ++ * STANDBY Exit status to be checked by FSBL in case ++ * field 'boot_action' == BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY ++ * take values from defines above 'BOOT_API_CTX_STBY_EXIT_STATUS_XXX' ++ * depending on encountered situation ++ */ ++ uint32_t stby_exit_status; ++ /* ++ * CSTANDBY Exit status to be checked by FSBL in case ++ * boot_action == BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY ++ * take values from defines above 'BOOT_API_CTX_CSTBY_EXIT_STATUS_XXX' ++ * depending on encountered situation ++ */ ++ uint32_t cstby_exit_status; ++#endif + uint32_t auth_status; + ++#if STM32MP15 + /* + * Pointers to bootROM External Secure Services +- * - ECDSA check key + * - ECDSA verify signature +- * - ECDSA verify signature and go + */ +- uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in, +- uint8_t *pubkey_out); ++ uint32_t reserved3; + uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in, + uint8_t *pubkey_in, + uint8_t *signature, + uint32_t ecc_algo); +- uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in, +- uint8_t *pub_key_in, +- uint8_t *signature, +- uint32_t ecc_algo, +- uint32_t *entry_in); +- ++ uint32_t reserved4; ++#endif + /* + * Information specific to an SD boot + * Updated each time an SD boot is at least attempted, +@@ -206,6 +816,21 @@ typedef struct { + * ie FSBL partition on which the boot was successful + */ + uint32_t boot_partition_used_toboot; ++ /* ++ * Address of SSP configuration structure : ++ * given and defined by bootROM ++ * and used by FSBL. The structure is of type ++ * 'boot_api_ssp_config_t' ++ */ ++ boot_api_ssp_config_t *p_ssp_config; ++ /* ++ * boot context field containing bootROM updated SSP Status ++ * Values can be of type BOOT_API_CTX_SSP_STATUS_XXX ++ */ ++ uint32_t ssp_status; ++ ++ /* Pointer on ROM constant containing ROM information */ ++ const boot_api_rom_version_info_t *p_rom_version_info; + + } __packed boot_api_context_t; + +@@ -224,10 +849,10 @@ typedef struct { + uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES]; + /* + * Checksum of payload +- * 32-bit sum all all payload bytes considered as 8 bit unigned numbers, +- * discarding any overflow bits. ++ * 32-bit sum all payload bytes considered as 8 bit unsigned ++ * numbers, discarding any overflow bits. + * Use to check UART/USB downloaded image integrity when signature +- * is not used (i.e bit 0 : 'No_sig_check' = 1 in option flags) ++ * is not used + */ + uint32_t payload_checksum; + /* Image header version : should have value BOOT_API_HEADER_VERSION */ +@@ -252,6 +877,27 @@ typedef struct { + * counter value in OTP_CFG4 prior executing the downloaded image + */ + uint32_t image_version; ++ ++#if STM32MP13 ++ /* ++ * Extension flags : ++ * ++ * Bit 0 : Authentication extension header ++ * value 0 : No signature check request ++ * Bit 1 : Encryption extension header ++ * Bit 2 : Padding extension header ++ */ ++ uint32_t extension_flags; ++ /* Length in bytes of all extension headers */ ++ uint32_t extension_headers_length; ++ /* Add binary type information */ ++ uint32_t binary_type; ++ /* Pad up to 128 byte total size */ ++ uint8_t pad[16]; ++ /* Followed by extension header */ ++ uint8_t ext_header[]; ++#endif ++#if STM32MP15 + /* + * Option flags: + * Bit 0 : No signature check request : 'No_sig_check' +@@ -277,6 +923,48 @@ typedef struct { + uint8_t pad[83]; + /* Add binary type information */ + uint8_t binary_type; ++#endif + } __packed boot_api_image_header_t; + ++typedef uint8_t boot_api_sha256_t[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; ++ ++typedef struct { ++ /* Extension header type: ++ * BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB or ++ * BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB ++ * BOOT_API_PADDING_HEADER_MAGIC_NB ++ */ ++ uint32_t type; ++ /* Extension header len in byte */ ++ uint32_t len; ++ /* parameters of this extension */ ++ uint8_t params[]; ++} __packed boot_extension_header_t; ++ ++typedef struct { ++ /* Idx of ECDSA public key to be used in table */ ++ uint32_t pk_idx; ++ /* Number of ECDSA public key in table */ ++ uint32_t nb_pk; ++ /* ++ * Type of ECC algorithm to use : ++ * value 1 : for P-256 NIST algorithm ++ * value 2 : for Brainpool 256 algorithm ++ * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above. ++ */ ++ uint32_t ecc_algo_type; ++ /* ECDSA public key to be used to check signature. */ ++ uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES]; ++ /* table of Hash of Algo+ECDSA public key */ ++ boot_api_sha256_t pk_hashes[]; ++} __packed boot_ext_header_params_authentication_t; ++ ++typedef struct { ++ /* Size of encryption key (128 or 256) */ ++ uint32_t key_size; ++ uint32_t derivation_cont; ++ /* 128 msb bits of plain payload SHA256 */ ++ uint32_t hash[4]; ++} __packed boot_ext_header_params_encrypted_fsbl_t; ++ + #endif /* BOOT_API_H */ +diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h +index 1e9443ece..baeecd385 100644 +--- a/plat/st/stm32mp1/include/platform_def.h ++++ b/plat/st/stm32mp1/include/platform_def.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -25,22 +25,9 @@ + #define PLATFORM_STACK_SIZE 0xC00 + #endif + +-#if STM32MP_USE_STM32IMAGE +-#ifdef AARCH32_SP_OPTEE +-#define OPTEE_HEADER_IMAGE_NAME "teeh" +-#define OPTEE_CORE_IMAGE_NAME "teex" +-#define OPTEE_PAGED_IMAGE_NAME "teed" +-#define OPTEE_HEADER_BINARY_TYPE U(0x20) +-#define OPTEE_CORE_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) +-#else /* STM32MP_USE_STM32IMAGE */ + #define FIP_IMAGE_NAME "fip" +-#endif /* STM32MP_USE_STM32IMAGE */ ++#define METADATA_PART_1 "metadata1" ++#define METADATA_PART_2 "metadata2" + + #define STM32MP_PRIMARY_CPU U(0x0) + #define STM32MP_SECONDARY_CPU U(0x1) +@@ -68,10 +55,17 @@ + #define BL2_LIMIT (STM32MP_BL2_BASE + \ + STM32MP_BL2_SIZE) + ++#define BL2_RO_BASE STM32MP_BL2_RO_BASE ++#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \ ++ STM32MP_BL2_RO_SIZE) ++ ++#define BL2_RW_BASE STM32MP_BL2_RW_BASE ++#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \ ++ STM32MP_BL2_RW_SIZE) + /******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +-#if STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) ++#if defined(IMAGE_BL32) + #if ENABLE_PIE + #define BL32_BASE 0 + #define BL32_LIMIT STM32MP_BL32_SIZE +@@ -80,7 +74,7 @@ + #define BL32_LIMIT (STM32MP_BL32_BASE + \ + STM32MP_BL32_SIZE) + #endif +-#endif /* STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) */ ++#endif /* defined(IMAGE_BL32) */ + + /******************************************************************************* + * BL33 specific defines. +@@ -93,8 +87,7 @@ + #define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE + + /* Needed by STM32CubeProgrammer support */ +-#define DWL_BUFFER_BASE (STM32MP_DDR_BASE + U(0x08000000)) +-#define DWL_BUFFER_SIZE U(0x08000000) ++#define DWL_BUFFER_SIZE U(0x01000000) + + /* + * SSBL offset in case it's stored in eMMC boot partition. +@@ -132,6 +125,8 @@ + */ + #define ARM_IRQ_SEC_PHY_TIMER U(29) + ++#define ARM_IRQ_NON_SEC_SGI_0 U(0) ++ + #define ARM_IRQ_SEC_SGI_0 U(8) + #define ARM_IRQ_SEC_SGI_1 U(9) + #define ARM_IRQ_SEC_SGI_2 U(10) +@@ -141,7 +136,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 STM32MP_IRQ_SEC_SPI_PRIO U(0x10) ++ + #define STM32MP1_IRQ_TZC400 U(36) ++#define STM32MP1_IRQ_MCU_SEV U(176) ++#define STM32MP1_IRQ_RCC_WAKEUP U(177) ++#define STM32MP1_IRQ_IWDG1 U(182) ++#define STM32MP1_IRQ_IWDG2 U(183) + #define STM32MP1_IRQ_TAMPSERRS U(229) + #define STM32MP1_IRQ_AXIERRIRQ U(244) + +diff --git a/plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h b/plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h +new file mode 100644 +index 000000000..0023fecd9 +--- /dev/null ++++ b/plat/st/stm32mp1/include/stm32mp15_mbedtls_config.h +@@ -0,0 +1,119 @@ ++/* ++ * Copyright (c) 2015-2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++#ifndef MBEDTLS_CONFIG_H ++#define MBEDTLS_CONFIG_H ++ ++/* ++ * Key algorithms currently supported on mbed TLS libraries ++ */ ++#define TF_MBEDTLS_USE_RSA 0 ++#define TF_MBEDTLS_USE_ECDSA 1 ++ ++/* ++ * Hash algorithms currently supported on mbed TLS libraries ++ */ ++#define TF_MBEDTLS_SHA256 1 ++#define TF_MBEDTLS_SHA384 2 ++#define TF_MBEDTLS_SHA512 3 ++ ++/* ++ * Configuration file to build mbed TLS with the required features for ++ * Trusted Boot ++ */ ++ ++#define MBEDTLS_PLATFORM_MEMORY ++#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS ++/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */ ++#define MBEDTLS_PLATFORM_SNPRINTF_ALT ++ ++#define MBEDTLS_PKCS1_V21 ++ ++#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION ++#define MBEDTLS_X509_CHECK_KEY_USAGE ++#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE ++ ++#define MBEDTLS_ASN1_PARSE_C ++#define MBEDTLS_ASN1_WRITE_C ++ ++#define MBEDTLS_BASE64_C ++#define MBEDTLS_BIGNUM_C ++ ++#define MBEDTLS_ERROR_C ++#define MBEDTLS_MD_C ++ ++#define MBEDTLS_MEMORY_BUFFER_ALLOC_C ++#define MBEDTLS_OID_C ++ ++#define MBEDTLS_PK_C ++#define MBEDTLS_PK_PARSE_C ++#define MBEDTLS_PK_WRITE_C ++ ++#define MBEDTLS_PLATFORM_C ++ ++#if TF_MBEDTLS_USE_ECDSA ++#define MBEDTLS_ECDSA_C ++#define MBEDTLS_ECP_C ++#define MBEDTLS_ECP_DP_SECP256R1_ENABLED ++#define MBEDTLS_ECP_NO_INTERNAL_RNG ++#endif ++#if TF_MBEDTLS_USE_RSA ++#define MBEDTLS_RSA_C ++#define MBEDTLS_X509_RSASSA_PSS_SUPPORT ++#endif ++ ++#define MBEDTLS_SHA256_C ++#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256) ++#define MBEDTLS_SHA512_C ++#endif ++ ++#define MBEDTLS_VERSION_C ++ ++#define MBEDTLS_X509_USE_C ++#define MBEDTLS_X509_CRT_PARSE_C ++ ++#if TF_MBEDTLS_USE_AES_GCM ++#define MBEDTLS_AES_C ++#define MBEDTLS_CIPHER_C ++#define MBEDTLS_GCM_C ++#endif ++ ++/* MPI / BIGNUM options */ ++#define MBEDTLS_MPI_WINDOW_SIZE 2 ++ ++#if TF_MBEDTLS_USE_RSA ++#if TF_MBEDTLS_KEY_SIZE <= 2048 ++#define MBEDTLS_MPI_MAX_SIZE 256 ++#else ++#define MBEDTLS_MPI_MAX_SIZE 512 ++#endif ++#else ++#define MBEDTLS_MPI_MAX_SIZE 256 ++#endif ++ ++/* Memory buffer allocator options */ ++#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8 ++ ++/* ++ * Prevent the use of 128-bit division which ++ * creates dependency on external libraries. ++ */ ++#define MBEDTLS_NO_UDBL_DIVISION ++ ++#ifndef __ASSEMBLER__ ++/* System headers required to build mbed TLS with the current configuration */ ++#include ++#include ++#endif ++ ++/* ++ * Mbed TLS heap size is smal as we only use the asn1 ++ * parsing functions ++ * digest, signature and crypto algorithm are done by ++ * other library. ++ */ ++ ++#define TF_MBEDTLS_HEAP_SIZE U(5120) ++#endif /* MBEDTLS_CONFIG_H */ +diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h +index 698415af2..703fdce37 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_context.h ++++ b/plat/st/stm32mp1/include/stm32mp1_context.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -7,8 +7,34 @@ + #ifndef STM32MP1_CONTEXT_H + #define STM32MP1_CONTEXT_H + ++#include + #include + +-int stm32_save_boot_interface(uint32_t interface, uint32_t instance); ++#include ++ ++void stm32_clean_context(void); ++int stm32_save_context(uint32_t zq0cr0_zdata, ++ struct stm32_rtc_calendar *rtc_time, ++ unsigned long long stgen_cnt); ++int stm32_restore_context(void); ++unsigned long long stm32_get_stgen_from_context(void); ++void stm32_context_get_bl2_low_power_params(uintptr_t *bl2_code_base, ++ uintptr_t *bl2_code_end, ++ uintptr_t *bl2_end); ++void stm32_context_save_bl2_param(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); ++bool stm32_pm_context_is_valid(void); ++void stm32_save_ddr_training_area(void); ++void stm32_restore_ddr_training_area(void); ++uint32_t stm32_pm_get_optee_ep(void); ++#if STM32MP13 ++void stm32mp1_pm_save_mce_mkey_in_context(uint8_t *data); ++void stm32mp1_pm_get_mce_mkey_from_context(uint8_t *data); ++#endif ++ ++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 */ +diff --git a/plat/st/stm32mp1/include/stm32mp1_critic_power.h b/plat/st/stm32mp1/include/stm32mp1_critic_power.h +new file mode 100644 +index 000000000..619d8c61a +--- /dev/null ++++ b/plat/st/stm32mp1/include/stm32mp1_critic_power.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP1_CRITIC_POWER_H ++#define STM32MP1_CRITIC_POWER_H ++ ++ /* Only BL32 compilation unit need stm32_pwr_down_wfi ++ * function/variable symbol ++ */ ++#if defined(IMAGE_BL32) ++extern void stm32_pwr_down_wfi(bool is_cstop, uint32_t mode); ++#endif ++extern void stm32_pwr_down_wfi_wrapper(bool is_cstop, uint32_t mode); ++extern void stm32_pwr_back_from_stop2(void); ++void stm32_pwr_down_wfi_load(bool is_cstop, uint32_t mode); ++void stm32_pwr_call_optee_ep(void); ++void stm32_pwr_cstop_critic_exit(void); ++ ++#endif /* STM32MP1_CRITIC_POWER_H */ +diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h +index 498a4f210..3663bce67 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h ++++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -13,11 +13,4 @@ + int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version); + int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id); + +-/* +- * Freeze watchdog when a debugger is attached, if the security configuration +- * allows it. +- * Return 0 on success, a negative error value otherwise. +- */ +-int stm32mp1_dbgmcu_freeze_iwdg2(void); +- + #endif /* STM32MP1_DBGMCU_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 000000000..79ae3bfc9 +--- /dev/null ++++ b/plat/st/stm32mp1/include/stm32mp1_low_power.h +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP1_LOW_POWER_H ++#define STM32MP1_LOW_POWER_H ++ ++#include ++#include ++ ++#include ++ ++void stm32_rcc_wakeup_update(bool state); ++void stm32_apply_pmic_suspend_config(uint32_t mode); ++bool stm32_is_cstop_done(void); ++void stm32_exit_cstop(void); ++void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr); ++void stm32_auto_stop(void); ++void stm32_init_low_power(void); ++ ++#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 000000000..37312c8de +--- /dev/null ++++ b/plat/st/stm32mp1/include/stm32mp1_power_config.h +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STM32MP1_POWER_CONFIG_H ++#define STM32MP1_POWER_CONFIG_H ++ ++#include ++#include ++ ++#define PSCI_MODE_SYSTEM_SUSPEND 0 ++#define PSCI_MODE_SYSTEM_OFF 1 ++ ++enum stm32mp1_pm_domain { ++ STM32MP1_PD_VSW, ++ STM32MP1_PD_CORE_RET, ++ STM32MP1_PD_CORE, ++ STM32MP1_PD_MAX_PM_DOMAIN ++}; ++ ++void stm32mp1_init_lp_states(void); ++int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status); ++uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode); ++int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode); ++bool stm32mp1_get_retram_enabled(void); ++ ++#endif /* STM32MP1_POWER_CONFIG_H */ +diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h +index 729d2336b..73222815c 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_private.h ++++ b/plat/st/stm32mp1/include/stm32mp1_private.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -9,21 +9,45 @@ + + #include + ++#include ++ + 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_gic_pcpu_init(void); +-void stm32mp1_gic_init(void); ++bool stm32mp1_addr_inside_backupsram(uintptr_t addr); ++bool stm32mp1_is_wakeup_from_standby(void); ++ ++#if defined(IMAGE_BL32) ++enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode); ++#endif + + void stm32mp1_syscfg_init(void); +-void stm32mp1_syscfg_enable_io_compensation(void); ++void stm32mp1_syscfg_enable_io_compensation_start(void); ++void stm32mp1_syscfg_enable_io_compensation_finish(void); + void stm32mp1_syscfg_disable_io_compensation(void); +- +-#if STM32MP_USE_STM32IMAGE +-uint32_t stm32mp_get_ddr_ns_size(void); +-#endif /* STM32MP_USE_STM32IMAGE */ ++uint32_t stm32mp1_syscfg_get_chip_version(void); ++uint32_t stm32mp1_syscfg_get_chip_dev_id(void); ++#if STM32MP13 ++void stm32mp1_syscfg_boot_mode_enable(void); ++void stm32mp1_syscfg_boot_mode_disable(void); ++#endif ++#if STM32MP15 ++static inline void stm32mp1_syscfg_boot_mode_enable(void){} ++static inline void stm32mp1_syscfg_boot_mode_disable(void){} ++#endif ++ ++void stm32mp1_deconfigure_uart_pins(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); ++ ++#if defined(IMAGE_BL32) && DEBUG ++void stm32mp_dump_core_registers(bool fcore); ++#endif + #endif /* STM32MP1_PRIVATE_H */ +diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h +index 3f6367ebe..519a67bad 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h ++++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h +@@ -7,6 +7,8 @@ + #ifndef STM32MP1_SHARED_RESOURCES_H + #define STM32MP1_SHARED_RESOURCES_H + ++#include ++ + #include + + #define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i)) +@@ -35,4 +37,19 @@ enum stm32mp_shres { + + STM32MP1_SHRES_COUNT + }; ++ ++#ifdef STM32MP_SHARED_RESOURCES ++/* ++ * Register a (non-)secure peripheral based on the ETZPC DECPROT configuration ++ */ ++void stm32mp1_register_etzpc_decprot(unsigned int id, ++ enum etzpc_decprot_attributes attr); ++#else ++static inline ++void stm32mp1_register_etzpc_decprot(unsigned int id, ++ enum etzpc_decprot_attributes attr) ++{ ++} ++#endif ++ + #endif /* STM32MP1_SHARED_RESOURCES_H */ +diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h +index 52088de28..5e8cde827 100644 +--- a/plat/st/stm32mp1/include/stm32mp1_smc.h ++++ b/plat/st/stm32mp1/include/stm32mp1_smc.h +@@ -17,6 +17,39 @@ + + /* 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 ++ + /* + * STM32_SMC_BSEC call API + * +@@ -29,6 +62,26 @@ + */ + #define STM32_SMC_BSEC 0x82001003 + ++/* Low Power services */ ++ ++/* ++ * 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_AUTO_STOP - CPU auto stop for OS driver suspend ++ * ++ * Argument a0: (input) This SMCC ID: STM32_SMC_AUTO_STOP ++ * (output) Status return code. ++ */ ++#define STM32_SMC_AUTO_STOP 0x8200100a ++ + /* + * STM32_SIP_SMC_SCMI_AGENT0 + * STM32_SIP_SMC_SCMI_AGENT1 +@@ -50,13 +103,22 @@ + #define STM32_SIP_SVC_VERSION_MINOR 0x1 + + /* Number of STM32 SiP Calls implemented */ +-#define STM32_COMMON_SIP_NUM_CALLS 3 ++#define STM32_COMMON_SIP_NUM_CALLS 9 ++ ++/* 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 */ + #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 + + /* SMC error codes */ + #define STM32_SMC_OK 0x00000000U +diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +index 7963c4a97..6fe13391c 100644 +--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c ++++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +@@ -117,7 +117,11 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { + VERSION_2, entry_point_info_t, + NON_SECURE | EXECUTABLE), + ++#if BL33_HYP ++ .ep_info.spsr = SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, ++#else + .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, ++#endif + SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS), + +diff --git a/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c +deleted file mode 100644 +index 4fce55a9e..000000000 +--- a/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c ++++ /dev/null +@@ -1,103 +0,0 @@ +-/* +- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ +- +-#include +-#include +-#include +- +-#include +- +-/******************************************************************************* +- * Following descriptor provides BL image/ep information that gets used +- * by BL2 to load the images and also subset of this information is +- * passed to next BL image. The image loading sequence is managed by +- * populating the images in required loading order. The image execution +- * sequence is managed by populating the `next_handoff_image_id` with +- * the next executable image id. +- ******************************************************************************/ +-static bl_mem_params_node_t bl2_mem_params_descs[] = { +- /* Fill BL32 related information */ +- { +- .image_id = BL32_IMAGE_ID, +- +- SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, +- VERSION_2, entry_point_info_t, +- SECURE | EXECUTABLE | EP_FIRST_EXE), +- +- /* Updated at runtime if OP-TEE is loaded */ +- .ep_info.pc = STM32MP_BL32_BASE, +- +- .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, +- SPSR_E_LITTLE, +- DISABLE_ALL_EXCEPTIONS), +- +- SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, +- VERSION_2, image_info_t, +- IMAGE_ATTRIB_PLAT_SETUP), +- +- /* Updated at runtime if OP-TEE is loaded */ +- .image_info.image_base = STM32MP_BL32_BASE, +- .image_info.image_max_size = STM32MP_BL32_SIZE, +- +- .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, +- +- SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, +- VERSION_2, entry_point_info_t, +- NON_SECURE | EXECUTABLE), +- +- .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET, +- .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, +- SPSR_E_LITTLE, +- DISABLE_ALL_EXCEPTIONS), +- +- SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, +- VERSION_2, image_info_t, 0U), +- +- .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, +- } +-}; +- +-REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) +diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c +index 36a3a1c39..26564e49a 100644 +--- a/plat/st/stm32mp1/plat_image_load.c ++++ b/plat/st/stm32mp1/plat_image_load.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -23,15 +23,6 @@ void plat_flush_next_bl_params(void) + ******************************************************************************/ + bl_load_info_t *plat_get_bl_image_load_info(void) + { +-#if STM32MP_USE_STM32IMAGE +- bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID); +- uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size(); +- +- /* Max size is non-secure DDR end address minus image_base */ +- bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size - +- bl33->image_info.image_base; +-#endif /* STM32MP_USE_STM32IMAGE */ +- + return get_bl_load_info_from_mem_params_desc(); + } + +diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk +index badc926c0..b2ffe5a22 100644 +--- a/plat/st/stm32mp1/platform.mk ++++ b/plat/st/stm32mp1/platform.mk +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -9,41 +9,115 @@ ARM_WITH_NEON := yes + BL2_AT_EL3 := 1 + USE_COHERENT_MEM := 0 + +-# Allow TF-A to concatenate BL2 & BL32 binaries in a single file, +-# share DTB file between BL2 and BL32 +-# If it is set to 0, then FIP is used +-STM32MP_USE_STM32IMAGE ?= 0 ++STM32MP_EARLY_CONSOLE ?= 0 ++STM32MP_UART_BAUDRATE ?= 115200 + +-ifneq ($(STM32MP_USE_STM32IMAGE),1) +-ENABLE_PIE := 1 +-endif ++# Add specific ST version ++ST_VERSION := r1.0 ++VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${PLAT}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} ++ ++TRUSTED_BOARD_BOOT ?= 0 ++STM32MP_USE_EXTERNAL_HEAP ?= 0 + ++# Please don't increment this value without good understanding of ++# the monotonic counter + STM32_TF_VERSION ?= 0 + + # Enable dynamic memory mapping + PLAT_XLAT_TABLES_DYNAMIC := 1 + ++# Default Device tree ++DTB_FILE_NAME ?= stm32mp157c-ev1.dtb ++ ++STM32MP13 ?= 0 ++STM32MP15 ?= 0 ++ ++ifeq ($(STM32MP13),1) ++ifeq ($(STM32MP15),1) ++$(error Cannot enable both flags STM32MP13 and STM32MP15) ++endif ++STM32MP13 := 1 ++STM32MP15 := 0 ++else ifeq ($(STM32MP15),1) ++STM32MP13 := 0 ++STM32MP15 := 1 ++else ifneq ($(findstring stm32mp13,$(DTB_FILE_NAME)),) ++STM32MP13 := 1 ++STM32MP15 := 0 ++else ifneq ($(findstring stm32mp15,$(DTB_FILE_NAME)),) ++STM32MP13 := 0 ++STM32MP15 := 1 ++endif ++ ++ifeq ($(STM32MP13),1) ++# Will use SRAM2 as mbedtls heap ++STM32MP_USE_EXTERNAL_HEAP := 1 ++ ++# DDR controller with single AXI port and 16-bit interface ++STM32MP_DDR_DUAL_AXI_PORT:= 0 ++STM32MP_DDR_32BIT_INTERFACE:= 0 ++ ++ifeq (${TRUSTED_BOARD_BOOT},1) ++# PKA algo to include ++PKA_USE_NIST_P256 := 1 ++PKA_USE_BRAINPOOL_P256T1:= 1 ++endif ++ ++# STM32 image header version v2.0 ++STM32_HEADER_VERSION_MAJOR:= 2 ++STM32_HEADER_VERSION_MINOR:= 0 ++endif ++ ++ifeq ($(STM32MP15),1) ++# DDR controller with dual AXI port and 32-bit interface ++STM32MP_DDR_DUAL_AXI_PORT:= 1 ++STM32MP_DDR_32BIT_INTERFACE:= 1 ++ ++# STM32 image header version v1.0 ++STM32_HEADER_VERSION_MAJOR:= 1 ++STM32_HEADER_VERSION_MINOR:= 0 ++endif ++ ++# STM32 image header binary type for BL2 ++STM32_HEADER_BL2_BINARY_TYPE:= 0x10 ++ ++# STM32 Secure Secret Provisioning mode (SSP) ++STM32MP_SSP ?= 0 ++ + ifeq ($(AARCH32_SP),sp_min) + # Disable Neon support: sp_min runtime may conflict with non-secure world + TF_CFLAGS += -mfloat-abi=soft + endif + ++TF_CFLAGS += -Wsign-compare ++ + # Not needed for Cortex-A7 + WORKAROUND_CVE_2017_5715:= 0 + ++AARCH32_EXCEPTION_DEBUG := 1 ++ + # Number of TF-A copies in the device + STM32_TF_A_COPIES := 2 +-STM32_BL33_PARTS_NUM := 1 +-ifeq ($(AARCH32_SP),optee) +-STM32_RUNTIME_PARTS_NUM := 3 +-else ifeq ($(STM32MP_USE_STM32IMAGE),1) +-STM32_RUNTIME_PARTS_NUM := 0 +-else +-STM32_RUNTIME_PARTS_NUM := 1 ++ ++# PLAT_PARTITION_MAX_ENTRIES must take care of STM32_TF-A_COPIES and other partitions ++# such as metadata (2) to find all the FIP partitions (default is 2). ++PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 4))) ++ ++ifeq (${PSA_FWU_SUPPORT},1) ++# Number of banks of updatable firmware ++NR_OF_FW_BANKS := 2 ++NR_OF_IMAGES_IN_FW_BANK := 1 ++JSON_METADATA ?= plat/st/stm32mp1/default_metadata.json ++STM32_DEPS += ${BUILD_PLAT}/metadata.bin ++ ++$(eval $(call GEN_METADATA,${JSON_METADATA},${BUILD_PLAT}/metadata.bin)) ++ ++FWU_MAX_PART = $(shell echo $$(($(STM32_TF_A_COPIES) + 2 + $(NR_OF_FW_BANKS)))) ++ifeq ($(shell test $(FWU_MAX_PART) -gt $(PLAT_PARTITION_MAX_ENTRIES); echo $$?),0) ++$(error "Required partition number is $(FWU_MAX_PART) where PLAT_PARTITION_MAX_ENTRIES is only \ ++$(PLAT_PARTITION_MAX_ENTRIES)") ++endif + endif +-PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + \ +- $(STM32_BL33_PARTS_NUM) + \ +- $(STM32_RUNTIME_PARTS_NUM)))) + + # Boot devices + STM32MP_EMMC ?= 0 +@@ -55,17 +129,19 @@ STM32MP_EMMC_BOOT ?= 0 + + # Serial boot devices + STM32MP_USB_PROGRAMMER ?= 0 ++STM32MP_UART_PROGRAMMER ?= 0 ++ ++# Download load address for serial boot devices ++DWL_BUFFER_BASE ?= 0xC7000000 ++ ++# Hypervisor mode ++BL33_HYP ?= 0 + + # Device tree +-DTB_FILE_NAME ?= stm32mp157c-ev1.dtb +-ifeq ($(STM32MP_USE_STM32IMAGE),1) +-ifeq ($(AARCH32_SP),optee) +-BL2_DTSI := stm32mp15-bl2.dtsi ++ifeq ($(STM32MP13),1) ++BL2_DTSI := stm32mp13-bl2.dtsi + FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) + else +-FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) +-endif +-else + BL2_DTSI := stm32mp15-bl2.dtsi + FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) + ifeq ($(AARCH32_SP),sp_min) +@@ -73,8 +149,14 @@ BL32_DTSI := stm32mp15-bl32.dtsi + FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME))) + endif + endif ++ ++$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) ++$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g" | grep -o "[0-9]*"))) + DTC_CPPFLAGS += ${INCLUDES} + DTC_FLAGS += -Wno-unit_address_vs_reg ++ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0) ++DTC_FLAGS += -Wno-interrupt_provider ++endif + + # Macros and rules to build TF binary + STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed +@@ -92,8 +174,8 @@ endif + STM32IMAGEPATH ?= tools/stm32image + STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} + STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c ++STM32_DEPS += ${STM32IMAGE} + +-ifneq (${STM32MP_USE_STM32IMAGE},1) + FIP_DEPS += dtbs + STM32MP_HW_CONFIG := ${BL33_CFG} + STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME)) +@@ -105,6 +187,11 @@ endif + $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config)) + # Add the HW_CONFIG to FIP and specify the same to certtool + $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config)) ++ifeq (${GENERATE_COT},1) ++$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) ++endif ++$(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/bl2.bin,--tb-fw)) ++CRT_DEPS+=${BUILD_PLAT}/bl2.bin + ifeq ($(AARCH32_SP),sp_min) + STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME))) + $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config)) +@@ -112,58 +199,78 @@ else + # Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images + # in the FIP if the platform requires. + ifneq ($(BL32_EXTRA1),) +-$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) ++$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1,,$(ENCRYPT_BL32))) + endif + ifneq ($(BL32_EXTRA2),) +-$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +-endif ++$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2,,$(ENCRYPT_BL32))) + endif + endif + + # Enable flags for C files + $(eval $(call assert_booleans,\ + $(sort \ ++ BL33_HYP \ ++ PKA_USE_BRAINPOOL_P256T1 \ ++ PKA_USE_NIST_P256 \ ++ PLAT_XLAT_TABLES_DYNAMIC \ ++ STM32MP_DDR_32BIT_INTERFACE \ ++ STM32MP_DDR_DUAL_AXI_PORT \ ++ STM32MP_EARLY_CONSOLE \ + STM32MP_EMMC \ +- STM32MP_SDMMC \ ++ STM32MP_EMMC_BOOT \ + STM32MP_RAW_NAND \ ++ STM32MP_SDMMC \ + STM32MP_SPI_NAND \ + STM32MP_SPI_NOR \ +- STM32MP_EMMC_BOOT \ +- PLAT_XLAT_TABLES_DYNAMIC \ ++ STM32MP_SSP \ ++ STM32MP_UART_PROGRAMMER \ + STM32MP_USB_PROGRAMMER \ +- STM32MP_USE_STM32IMAGE \ ++ STM32MP_USE_EXTERNAL_HEAP \ ++ STM32MP13 \ ++ STM32MP15 \ + ))) + + $(eval $(call assert_numerics,\ + $(sort \ +- STM32_TF_A_COPIES \ + PLAT_PARTITION_MAX_ENTRIES \ ++ STM32_TF_A_COPIES \ ++ STM32_TF_VERSION \ ++ STM32MP_UART_BAUDRATE \ + ))) + + $(eval $(call add_defines,\ + $(sort \ ++ BL33_HYP \ ++ DWL_BUFFER_BASE \ ++ PKA_USE_BRAINPOOL_P256T1 \ ++ PKA_USE_NIST_P256 \ ++ PLAT_PARTITION_MAX_ENTRIES \ ++ PLAT_XLAT_TABLES_DYNAMIC \ ++ STM32_TF_A_COPIES \ ++ STM32_TF_VERSION \ ++ STM32MP_DDR_32BIT_INTERFACE \ ++ STM32MP_DDR_DUAL_AXI_PORT \ ++ STM32MP_EARLY_CONSOLE \ + STM32MP_EMMC \ +- STM32MP_SDMMC \ ++ STM32MP_EMMC_BOOT \ + STM32MP_RAW_NAND \ ++ STM32MP_SDMMC \ + STM32MP_SPI_NAND \ + STM32MP_SPI_NOR \ +- STM32MP_EMMC_BOOT \ +- PLAT_XLAT_TABLES_DYNAMIC \ +- STM32_TF_A_COPIES \ +- PLAT_PARTITION_MAX_ENTRIES \ ++ STM32MP_SSP \ ++ STM32MP_UART_BAUDRATE \ ++ STM32MP_UART_PROGRAMMER \ + STM32MP_USB_PROGRAMMER \ +- STM32MP_USE_STM32IMAGE \ ++ STM32MP_USE_EXTERNAL_HEAP \ ++ STM32MP13 \ ++ STM32MP15 \ + ))) + + # Include paths and source files + PLAT_INCLUDES := -Iplat/st/common/include/ + PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ + +-ifeq (${STM32MP_USE_STM32IMAGE},1) +-include common/fdt_wrappers.mk +-else + include lib/fconf/fconf.mk +-endif + include lib/libfdt/libfdt.mk + + PLAT_BL_COMMON_SOURCES := common/uuid.c \ +@@ -182,25 +289,36 @@ PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S + + PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ ++ drivers/clk/clk.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ +- drivers/st/bsec/bsec.c \ ++ drivers/regulator/regulator_core.c \ ++ drivers/st/bsec/bsec2.c \ + drivers/st/clk/stm32mp_clkfunc.c \ +- drivers/st/clk/stm32mp1_clk.c \ ++ drivers/st/ddr/stm32mp_ddr.c \ + drivers/st/ddr/stm32mp1_ddr_helpers.c \ + drivers/st/gpio/stm32_gpio.c \ + drivers/st/i2c/stm32_i2c.c \ + drivers/st/iwdg/stm32_iwdg.c \ + drivers/st/pmic/stm32mp_pmic.c \ + drivers/st/pmic/stpmic1.c \ ++ drivers/st/regulator/regulator_fixed.c \ + drivers/st/reset/stm32mp1_reset.c \ + plat/st/common/stm32mp_dt.c \ ++ plat/st/common/stm32mp_shres_helpers.c \ + plat/st/stm32mp1/stm32mp1_context.c \ + plat/st/stm32mp1/stm32mp1_dbgmcu.c \ + plat/st/stm32mp1/stm32mp1_helper.S \ + plat/st/stm32mp1/stm32mp1_syscfg.c + +-ifneq (${STM32MP_USE_STM32IMAGE},1) ++ifeq ($(STM32MP13),1) ++PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \ ++ drivers/st/clk/clk-stm32mp13.c \ ++ drivers/st/rng/stm32_rng.c ++else ++PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c ++endif ++ + BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + + BL2_SOURCES += drivers/io/io_fip.c \ +@@ -208,23 +326,61 @@ BL2_SOURCES += drivers/io/io_fip.c \ + plat/st/common/stm32mp_fconf_io.c \ + plat/st/stm32mp1/plat_bl2_mem_params_desc.c \ + plat/st/stm32mp1/stm32mp1_fconf_firewall.c +-else +-BL2_SOURCES += ${FDT_WRAPPERS_SOURCES} + +-BL2_SOURCES += drivers/io/io_dummy.c \ +- drivers/st/io/io_stm32image.c \ +- plat/st/common/bl2_stm32_io_storage.c \ +- plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c \ +- plat/st/stm32mp1/stm32mp1_security.c ++ifeq (${PSA_FWU_SUPPORT},1) ++include lib/zlib/zlib.mk ++include drivers/fwu/fwu.mk ++ ++BL2_SOURCES += $(ZLIB_SOURCES) + endif + + BL2_SOURCES += drivers/io/io_block.c \ + drivers/io/io_mtd.c \ + drivers/io/io_storage.c \ + drivers/st/crypto/stm32_hash.c \ +- plat/st/common/stm32mp_auth.c \ + plat/st/stm32mp1/bl2_plat_setup.c + ++ifneq (${DECRYPTION_SUPPORT},none) ++BL2_SOURCES += drivers/io/io_encrypted.c ++endif ++ ++ifeq ($(STM32MP13),1) ++BL2_SOURCES += drivers/st/mce/stm32_mce.c ++endif ++ ++ifeq (${TRUSTED_BOARD_BOOT},1) ++AUTH_SOURCES := drivers/auth/auth_mod.c \ ++ drivers/auth/crypto_mod.c \ ++ drivers/auth/img_parser_mod.c ++ ++ifeq (${GENERATE_COT},1) ++TFW_NVCTR_VAL := 0 ++NTFW_NVCTR_VAL := 0 ++KEY_SIZE := ++KEY_ALG := ecdsa ++HASH_ALG := sha256 ++endif ++TF_MBEDTLS_KEY_ALG := ecdsa ++MBEDTLS_CONFIG_FILE ?= "" ++ ++include drivers/auth/mbedtls/mbedtls_x509.mk ++ ++ ++AUTH_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \ ++ lib/fconf/fconf_tbbr_getter.c \ ++ plat/st/common/stm32mp_crypto_lib.c ++ ++ifeq ($(STM32MP13),1) ++AUTH_SOURCES += drivers/st/crypto/stm32_pka.c ++AUTH_SOURCES += drivers/st/crypto/stm32_saes.c ++endif ++ ++BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_bl2.c ++ ++BL2_SOURCES += $(AUTH_SOURCES) \ ++ 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 \ +@@ -244,6 +400,9 @@ BL2_SOURCES += drivers/mtd/nand/spi_nand.c + endif + + ifeq (${STM32MP_SPI_NOR},1) ++ifneq (${STM32MP_FORCE_MTD_START_OFFSET},) ++$(eval $(call add_define_val,STM32MP_NOR_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET})) ++endif + BL2_SOURCES += drivers/mtd/nor/spi_nor.c + endif + +@@ -253,6 +412,9 @@ BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \ + endif + + ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),) ++ifneq (${STM32MP_FORCE_MTD_START_OFFSET},) ++$(eval $(call add_define_val,STM32MP_NAND_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET})) ++endif + BL2_SOURCES += drivers/mtd/nand/core.c + endif + +@@ -260,18 +422,28 @@ ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) + BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c + endif + ++ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),) ++BL2_SOURCES += drivers/io/io_memmap.c ++endif ++ ++ifeq (${STM32MP_UART_PROGRAMMER},1) ++BL2_SOURCES += drivers/st/uart/stm32_uart.c \ ++ plat/st/common/stm32cubeprogrammer_uart.c ++endif ++ + ifeq (${STM32MP_USB_PROGRAMMER},1) + #The DFU stack uses only one end point, reduce the USB stack footprint + $(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U)) +-BL2_SOURCES += drivers/io/io_memmap.c \ +- drivers/st/usb/stm32mp1_usb.c \ ++BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \ + drivers/usb/usb_device.c \ + plat/st/common/stm32cubeprogrammer_usb.c \ + plat/st/common/usb_dfu.c \ + plat/st/stm32mp1/stm32mp1_usb_dfu.c + endif + +-BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \ ++BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \ ++ drivers/st/ddr/stm32mp_ram.c \ ++ drivers/st/ddr/stm32mp1_ddr.c \ + drivers/st/ddr/stm32mp1_ram.c + + BL2_SOURCES += common/desc_image_load.c \ +@@ -279,6 +451,13 @@ BL2_SOURCES += common/desc_image_load.c \ + + BL2_SOURCES += lib/optee/optee_utils.c + ++BL2_SOURCES += plat/st/stm32mp1/stm32mp1_critic_power.c ++BL2_SOURCES += plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S ++ ++ifeq ($(STM32MP_SSP),1) ++include plat/st/stm32mp1/stm32mp1_ssp.mk ++endif ++ + # Compilation rules + .PHONY: check_dtc_version stm32image clean_stm32image check_boot_device + .SUFFIXES: +@@ -295,6 +474,7 @@ check_boot_device: + [ ${STM32MP_RAW_NAND} != 1 ] && \ + [ ${STM32MP_SPI_NAND} != 1 ] && \ + [ ${STM32MP_SPI_NOR} != 1 ] && \ ++ [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \ + [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \ + echo "No boot device driver is enabled"; \ + false; \ +@@ -309,20 +489,11 @@ clean_stm32image: + ${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean + + check_dtc_version: +- $(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) +- $(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g"))) + @if [ ${DTC_VERSION} -lt 10404 ]; then \ + echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \ + false; \ + fi + +-ifeq ($(STM32MP_USE_STM32IMAGE)-$(AARCH32_SP),1-sp_min) +-${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} +- @echo " AS stm32mp1.S" +- ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ +- -DDTB_BIN_PATH=\"$<\" \ +- -c $(word 2,$^) -o $@ +-else + # Create DTB file for BL2 + ${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs + @echo '#include "$(patsubst fdts/%,%,$<)"' > $@ +@@ -344,7 +515,6 @@ ${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32m + ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ + -DDTB_BIN_PATH=\"$<\" \ + -c plat/st/stm32mp1/stm32mp1.S -o $@ +-endif + + $(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,bl2)) + +@@ -358,12 +528,15 @@ tf-a-%.bin: tf-a-%.elf + @echo "Built $@ successfully" + @echo + +-tf-a-%.stm32: ${STM32IMAGE} tf-a-%.bin ++tf-a-%.stm32: tf-a-%.bin ${STM32_DEPS} + @echo + @echo "Generate $@" + $(eval LOADADDR = $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}')) + $(eval ENTRY = $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}')) +- ${Q}${STM32IMAGE} -s $(word 2,$^) -d $@ \ ++ ${Q}${STM32IMAGE} -s $< -d $@ \ + -l $(LOADADDR) -e ${ENTRY} \ +- -v ${STM32_TF_VERSION} ++ -v ${STM32_TF_VERSION} \ ++ -m ${STM32_HEADER_VERSION_MAJOR} \ ++ -n ${STM32_HEADER_VERSION_MINOR} \ ++ -b ${STM32_HEADER_BL2_BINARY_TYPE} + @echo +diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c +index a1d7fc64e..eb9c4fe74 100644 +--- a/plat/st/stm32mp1/services/bsec_svc.c ++++ b/plat/st/stm32mp1/services/bsec_svc.c +@@ -4,20 +4,301 @@ + * 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 "bsec_svc.h" + ++/* ++ * version of STM32_SMC_READ_ALL / STM32_SMC_WRITE_ALL service ++ * This must be increased at each structure otp_exchange modification ++ */ ++#define BSEC_SERVICE_VERSION 0x02U ++ ++enum bsec_ssp_status { ++ BSEC_NO_SSP = 0, ++ BSEC_SSP_SET, ++ BSEC_SSP_ERROR ++}; ++ ++/* Global status bitfield */ ++#define BSEC_STATE_SEC_OPEN U(0x0) ++#define BSEC_STATE_SEC_CLOSED U(0x1) ++#define BSEC_STATE_INVALID U(0x2) ++ ++/* Bitfield definition status */ ++#define OTP_UPDATE_REQ BIT(31) ++#define OTP_ERROR_DETECTED BIT(0) ++ ++/* Bitfield definition for LOCK status */ ++#define LOCK_PERM BIT(30) ++#define LOCK_SHADOW_R BIT(29) ++#define LOCK_SHADOW_W BIT(28) ++#define LOCK_SHADOW_P BIT(27) ++#define LOCK_ERROR BIT(26) ++ ++struct otp_state { ++ uint32_t value; ++ uint32_t state; ++}; ++ ++struct otp_exchange { ++ uint32_t version; ++ uint32_t status; ++ struct otp_state otp[STM32MP1_OTP_MAX_ID]; ++}; ++ ++static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update) ++{ ++ boot_api_context_t *boot_context = ++ (boot_api_context_t *)BOOT_PARAM_ADDR; ++ ++ /* No SSP update or SSP already done*/ ++ if ((((otp & SSP_OTP_MASK) == 0U) && ((update & SSP_OTP_MASK) == 0U)) || ++ (((otp & SSP_OTP_MASK) == SSP_OTP_MASK) && ++ ((update & SSP_OTP_MASK) == SSP_OTP_MASK))) { ++ return BSEC_NO_SSP; ++ } ++ ++ /* SSP update */ ++ if ((update & SSP_OTP_MASK) != 0U) { ++ if ((update & SSP_OTP_SUCCESS) != 0U) { ++ return BSEC_SSP_ERROR; ++ } ++ ++ /* SSP boot process */ ++ boot_context->p_ssp_config->ssp_cmd = ++ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK; ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, ++ sizeof(boot_api_ssp_config_t)); ++#endif ++ if (dt_pmic_status() > 0) { ++ struct rdev *regul; ++ ++ initialize_pmic(); ++ ++ regul = dt_get_cpu_regulator(); ++ if (regul == NULL) { ++ return BSEC_SSP_ERROR; ++ } ++ ++ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) { ++ return BSEC_SSP_ERROR; ++ } ++ } ++ ++ return BSEC_SSP_SET; ++ } ++ return BSEC_NO_SSP; ++} ++ ++static uint32_t bsec_read_all_bsec(struct otp_exchange *exchange) ++{ ++ uint32_t i; ++ uint32_t result; ++ uint32_t shadow_prog_lock[3]; ++ uint32_t shadow_read_lock[3]; ++ uint32_t shadow_write_lock[3]; ++ uint32_t permanent_lock[3]; ++ uint32_t bsec_base; ++ uint32_t status; ++ ++ if (exchange == NULL) { ++ return BSEC_ERROR; ++ } ++ ++ exchange->version = BSEC_SERVICE_VERSION; ++ ++ status = bsec_get_status(); ++ if ((status & BSEC_MODE_INVALID_MASK) != 0U) { ++ exchange->status = BSEC_STATE_INVALID; ++ } else { ++ if ((status & BSEC_MODE_SECURE_MASK) != 0U) { ++ if (stm32mp_is_closed_device()) { ++ exchange->status = BSEC_STATE_SEC_CLOSED; ++ } else { ++ exchange->status = BSEC_STATE_SEC_OPEN; ++ } ++ } else { ++ /* OTP modes OPEN1 and OPEN2 are not supported */ ++ exchange->status = BSEC_STATE_INVALID; ++ } ++ } ++ ++ bsec_base = bsec_get_base(); ++ for (i = 0U; i < 3U; i++) { ++ permanent_lock[i] = mmio_read_32(bsec_base + BSEC_WRLOCK(i)); ++ shadow_prog_lock[i] = mmio_read_32(bsec_base + BSEC_SPLOCK(i)); ++ shadow_read_lock[i] = mmio_read_32(bsec_base + BSEC_SRLOCK(i)); ++ shadow_write_lock[i] = mmio_read_32(bsec_base + BSEC_SWLOCK(i)); ++ } ++ ++ for (i = 0U; i <= STM32MP1_OTP_MAX_ID; i++) { ++ uint32_t offset = i / __WORD_BIT; ++ uint32_t bits = BIT(i % __WORD_BIT); ++ ++ exchange->otp[i].value = 0U; ++ exchange->otp[i].state = 0U; ++ ++ result = bsec_shadow_register(i); ++ if (result == BSEC_OK) { ++ result = bsec_read_otp(&exchange->otp[i].value, i); ++ } ++ if (result != BSEC_OK) { ++ exchange->otp[i].value = 0; ++ exchange->otp[i].state |= OTP_ERROR_DETECTED; ++ } ++ if (permanent_lock[offset] & bits) { ++ exchange->otp[i].state |= LOCK_PERM; ++ } ++ if (shadow_read_lock[offset] & bits) { ++ exchange->otp[i].state |= LOCK_SHADOW_R; ++ } ++ if (shadow_write_lock[offset] & bits) { ++ exchange->otp[i].state |= LOCK_SHADOW_W; ++ } ++ if (shadow_prog_lock[offset] & bits) { ++ exchange->otp[i].state |= LOCK_SHADOW_P; ++ } ++ } ++ ++ return BSEC_OK; ++} ++ ++static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange, ++ uint32_t *ret_otp_value) ++{ ++ uint32_t i; ++ uint32_t ret; ++ ++ *ret_otp_value = 0U; ++ ++ if (exchange == NULL) { ++ return BSEC_ERROR; ++ } ++ ++ if (exchange->version != BSEC_SERVICE_VERSION) { ++ return BSEC_ERROR; ++ } ++ ++ for (i = 0U; i <= STM32MP1_OTP_MAX_ID; i++) { ++ if ((exchange->otp[i].state & OTP_UPDATE_REQ) == 0U) { ++ continue; ++ } ++ if (exchange->otp[i].value != 0U) { ++ ret = bsec_program_otp(exchange->otp[i].value, i); ++ if (ret == BSEC_OK) { ++ ret = bsec_write_otp(exchange->otp[i].value, i); ++ } ++ if (ret != BSEC_OK) { ++ ERROR("BSEC write failed on OTP%u\n", i); ++ return ret; ++ } ++ } ++ if ((exchange->otp[i].state & LOCK_PERM) != 0U) { ++ ret = bsec_permanent_lock_otp(i); ++ if (ret != BSEC_OK) { ++ ERROR("BSEC permanent lock failed on OTP%u\n", i); ++ return ret; ++ } ++ } ++ if ((exchange->otp[i].state & LOCK_SHADOW_R) != 0U) { ++ ret = bsec_set_sr_lock(i); ++ if (ret != BSEC_OK) { ++ ERROR("BSEC sr lock failed on OTP%u\n", i); ++ return ret; ++ } ++ } ++ if ((exchange->otp[i].state & LOCK_SHADOW_W) != 0U) { ++ ret = bsec_set_sw_lock(i); ++ if (ret != BSEC_OK) { ++ ERROR("BSEC sw lock failed on OTP%u\n", i); ++ return ret; ++ } ++ } ++ if ((exchange->otp[i].state & LOCK_SHADOW_P) != 0U) { ++ ret = bsec_set_sp_lock(i); ++ if (ret != BSEC_OK) { ++ ERROR("BSEC sp lock failed on OTP%u\n", i); ++ return ret; ++ } ++ } ++ } ++ ++ INFO("write all otp succeed\n"); ++ ++ return BSEC_OK; ++} ++ + 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 STM32_SMC_INVALID_PARAMS; ++ } ++ ++ otp_exch = NULL; ++ map_begin = 0U; ++ ++ if ((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) { ++ if (!stm32_boot_is_serial()) { ++ return STM32_SMC_FAILED; ++ } ++ ++ 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; ++ } + + switch (x1) { + case STM32_SMC_READ_SHADOW: +@@ -25,6 +306,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, 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: +@@ -50,10 +343,23 @@ 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); ++ break; ++ case STM32_SMC_WRITE_ALL: ++ result = bsec_write_all_bsec(otp_exch, ret_otp_value); ++ break; ++ case STM32_SMC_WRLOCK_OTP: ++ result = bsec_permanent_lock_otp(x2); ++ break; + default: + return STM32_SMC_INVALID_PARAMS; + } + ++ if ((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) { ++ ret = mmap_remove_dynamic_region(map_begin, map_size); ++ assert(ret == 0); ++ } ++ + return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED; + } +diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h +index 06752ef4d..ba42cf823 100644 +--- a/plat/st/stm32mp1/services/bsec_svc.h ++++ b/plat/st/stm32mp1/services/bsec_svc.h +@@ -9,10 +9,6 @@ + + #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); + +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 000000000..567a3c70f +--- /dev/null ++++ b/plat/st/stm32mp1/services/low_power_svc.c +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "low_power_svc.h" ++ ++uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2) ++{ ++ if (stm32mp1_set_pm_domain_state((enum stm32mp1_pm_domain)x1, ++ (bool)x2) < 0) { ++ return STM32_SMC_FAILED; ++ } ++ ++ return STM32_SMC_OK; ++} +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 000000000..eb98e9225 +--- /dev/null ++++ b/plat/st/stm32mp1/services/low_power_svc.h +@@ -0,0 +1,14 @@ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef LOW_POWER_SVC_H ++#define LOW_POWER_SVC_H ++ ++#include ++ ++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 000000000..1213d7ef6 +--- /dev/null ++++ b/plat/st/stm32mp1/services/pwr_svc.c +@@ -0,0 +1,102 @@ ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "pwr_svc.h" ++ ++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; ++ ++ stm32mp_pwr_regs_lock(); ++ ++ switch (request) { ++ case STM32_SMC_REG_WRITE: ++ mmio_clrsetbits_32(addr, allowed_mask, masked_value); ++ VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value, ++ mmio_read_32(addr)); ++ break; ++ ++ case STM32_SMC_REG_SET: ++ mmio_setbits_32(addr, masked_value); ++ VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value, ++ mmio_read_32(addr)); ++ break; ++ ++ case STM32_SMC_REG_CLEAR: ++ mmio_clrbits_32(addr, masked_value); ++ VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value, ++ mmio_read_32(addr)); ++ break; ++ ++ default: ++ break; ++ } ++ ++ stm32mp_pwr_regs_unlock(); ++} ++ ++static void raw_allowed_access_request(uint32_t request, ++ uint32_t offset, uint32_t value) ++{ ++ uint32_t allowed_mask = 0; ++ ++ switch (offset) { ++ case PWR_CR3: ++ allowed_mask |= PWR_CR3_VBE | PWR_CR3_VBRS | PWR_CR3_USB33DEN | ++ PWR_CR3_REG18EN | PWR_CR3_REG11EN; ++ break; ++ ++ case PWR_WKUPCR: ++ allowed_mask |= PWR_WKUPCR_MASK; ++ break; ++ ++ case PWR_MPUWKUPENR: ++ allowed_mask |= PWR_MPUWKUPENR_MASK; ++ break; ++ ++ default: ++ return; ++ } ++ ++ if (allowed_mask != 0U) { ++ access_allowed_mask(request, offset, value, allowed_mask); ++ } ++} ++ ++uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) ++{ ++ uint32_t request = x1; ++ uint32_t offset = x2; ++ uint32_t value = x3; ++ ++ /* ++ * x2 may be either the PWR register offset or the register ++ * full physical address. ++ */ ++ if ((offset & ~PWR_OFFSET_MASK) != 0) { ++ if ((offset & ~PWR_OFFSET_MASK) != stm32mp_pwr_base()) { ++ return STM32_SMC_INVALID_PARAMS; ++ } ++ ++ offset &= PWR_OFFSET_MASK; ++ } ++ ++ /* PWR controls for non secure resource may be accessed straight */ ++ raw_allowed_access_request(request, offset, value); ++ ++ return STM32_SMC_OK; ++} +diff --git a/plat/st/stm32mp1/services/pwr_svc.h b/plat/st/stm32mp1/services/pwr_svc.h +new file mode 100644 +index 000000000..6dacdf80d +--- /dev/null ++++ b/plat/st/stm32mp1/services/pwr_svc.h +@@ -0,0 +1,12 @@ ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef PWR_SVC_H ++#define PWR_SVC_H ++ ++uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); ++ ++#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 000000000..d12fd1782 +--- /dev/null ++++ b/plat/st/stm32mp1/services/rcc_svc.c +@@ -0,0 +1,140 @@ ++/* ++ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "rcc_svc.h" ++ ++#define RCC_OFFSET_MASK GENMASK(11, 0) ++ ++static bool offset_is_clear_register(uint32_t __unused offset) ++{ ++ /* All currently allowed registers are non set/clear registers */ ++ return false; ++} ++ ++static void access_allowed_mask(uint32_t request, uint32_t offset, ++ uint32_t value, uint32_t allowed_mask) ++{ ++ uint32_t addr = stm32mp_rcc_base() + offset; ++ uint32_t masked_value = value & allowed_mask; ++ ++ switch (request) { ++ case STM32_SMC_REG_WRITE: ++ if (offset_is_clear_register(offset)) { ++ mmio_write_32(addr, masked_value); ++ } else { ++ stm32mp_mmio_clrsetbits_32_shregs(addr, allowed_mask, ++ masked_value); ++ } ++ VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value, ++ mmio_read_32(addr)); ++ break; ++ ++ case STM32_SMC_REG_SET: ++ if (offset_is_clear_register(offset)) { ++ mmio_write_32(addr, masked_value); ++ } else { ++ stm32mp_mmio_setbits_32_shregs(addr, masked_value); ++ } ++ VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value, ++ mmio_read_32(addr)); ++ break; ++ ++ case STM32_SMC_REG_CLEAR: ++ if (offset_is_clear_register(offset)) { ++ /* Nothing to do on CLR registers */ ++ } else { ++ stm32mp_mmio_clrbits_32_shregs(addr, masked_value); ++ } ++ VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value, ++ mmio_read_32(addr)); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static uint32_t raw_allowed_access_request(uint32_t request, ++ uint32_t offset, uint32_t value) ++{ ++ uint32_t allowed_mask = 0; ++ ++ switch (offset) { ++ case RCC_MP_CIER: ++ case RCC_MP_CIFR: ++ allowed_mask = RCC_MP_CIFR_WKUPF; ++ break; ++ default: ++ return STM32_SMC_INVALID_PARAMS; ++ } ++ ++ if (allowed_mask != 0U) { ++ access_allowed_mask(request, offset, value, allowed_mask); ++ } ++ ++ return STM32_SMC_OK; ++} ++ ++uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) ++{ ++ uint32_t request = x1; ++ uint32_t offset = x2; ++ uint32_t value = x3; ++ ++ /* ++ * x2 may be either the RCC register offset or the register ++ * full physical address. ++ */ ++ if ((offset & ~RCC_OFFSET_MASK) != 0) { ++ if ((offset & ~RCC_OFFSET_MASK) != stm32mp_rcc_base()) { ++ return STM32_SMC_INVALID_PARAMS; ++ } ++ ++ offset &= RCC_OFFSET_MASK; ++ } ++ ++ return raw_allowed_access_request(request, offset, value); ++} ++ ++uint32_t rcc_cal_scv_handler(uint32_t x1) ++{ ++ uint32_t ret = STM32_SMC_FAILED; ++ ++ switch (x1) { ++ case CK_CSI: ++ if (stm32mp1_calib_start_csi_cal() == 0) { ++ ret = STM32_SMC_OK; ++ } ++ break; ++ ++ case CK_HSI: ++ if (stm32mp1_calib_start_hsi_cal() == 0) { ++ ret = STM32_SMC_OK; ++ } ++ break; ++ ++ default: ++ ret = STM32_SMC_INVALID_PARAMS; ++ break; ++ } ++ ++ return ret; ++} +diff --git a/plat/st/stm32mp1/services/rcc_svc.h b/plat/st/stm32mp1/services/rcc_svc.h +new file mode 100644 +index 000000000..8cf128a36 +--- /dev/null ++++ b/plat/st/stm32mp1/services/rcc_svc.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef RCC_SVC_H ++#define RCC_SVC_H ++ ++uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); ++uint32_t rcc_cal_scv_handler(uint32_t x1); ++ ++#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 ed8a448b3..f41a6cf43 100644 +--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c ++++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c +@@ -13,9 +13,13 @@ + #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, +@@ -66,6 +70,28 @@ 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; ++ ++ case STM32_SMC_RCC_CAL: ++ ret1 = rcc_cal_scv_handler(x1); ++ break; ++ ++ ++ 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; ++ ++ case STM32_SMC_AUTO_STOP: ++ stm32_auto_stop(); ++ ret1 = STM32_SMC_OK; ++ break; ++ + case STM32_SIP_SMC_SCMI_AGENT0: + scmi_smt_fastcall_smc_entry(0); + break; +diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +index 239b60af4..1ce275e31 100644 +--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk ++++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +@@ -1,17 +1,32 @@ + # +-# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # + ++ifeq ($(STM32MP13),1) ++$(error "SP_min is not supported on STM32MP13 platform") ++endif ++ + SP_MIN_WITH_SECURE_FIQ := 1 + ++override ENABLE_PIE := 1 ++BL32_CFLAGS += -fpie -DENABLE_PIE ++BL32_LDFLAGS += $(PIE_LDFLAGS) ++ + BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES + +-BL32_SOURCES += drivers/st/etzpc/etzpc.c \ ++BL32_SOURCES += drivers/st/clk/stm32mp1_calib.c \ ++ drivers/st/etzpc/etzpc.c \ ++ drivers/st/rng/stm32_rng.c \ ++ drivers/st/rtc/stm32_rtc.c \ ++ drivers/st/tamper/stm32_tamp.c \ ++ drivers/st/timer/stm32_timer.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/st/stm32mp1/sp_min/sp_min_setup.c \ ++ 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 + +@@ -24,7 +39,7 @@ include drivers/arm/gic/v2/gicv2.mk + + BL32_SOURCES += ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ +- plat/st/stm32mp1/stm32mp1_gic.c ++ plat/st/common/stm32mp_gic.c + + # Generic PSCI + BL32_SOURCES += plat/common/plat_psci_common.c +@@ -38,8 +53,13 @@ BL32_SOURCES += drivers/scmi-msg/base.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/stm32mp1_scmi.c + + # Arm Archtecture services + BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c ++ ++BL32_SOURCES += plat/st/stm32mp1/stm32mp1_critic_power.c +diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c +index 1495e027c..7044d9a47 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-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -12,16 +12,28 @@ + #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 +@@ -29,6 +41,10 @@ + #include + + #include ++#include ++#include ++#include ++#include + + /****************************************************************************** + * Placeholder variables for copying the arguments that have been passed to +@@ -36,14 +52,178 @@ + ******************************************************************************/ + static entry_point_info_t bl33_image_ep_info; + +-static console_t console; ++static const char * const tamper_name[] = { ++ [INT_TAMP1] = "RTC power domain", ++ [INT_TAMP2] = "Temperature monitoring", ++ [INT_TAMP3] = "LSE monitoring", ++ [INT_TAMP4] = "HSE monitoring", ++}; ++ ++static int stm32mp1_tamper_action(int id) ++{ ++ const char *tamp_name = NULL; ++ ++ if ((id >= 0) && ((size_t)id < ARRAY_SIZE(tamper_name))) { ++ tamp_name = tamper_name[id]; ++ } ++ ERROR("Tamper %u (%s) occurs\n", id, tamp_name); ++ ++ return 1; /* ack TAMPER and reset system */ ++} ++ ++static void stm32_sgi1_it_handler(void) ++{ ++ uint32_t id; ++ ++ stm32mp_mask_timer(); ++ ++#if DEBUG ++ stm32mp_dump_core_registers(false); ++#endif ++ ++ gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_1); ++ ++ 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); ++ ++ stm32mp_wait_cpu_reset(); ++} ++ ++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) { ++ uint32_t voltage_mv = 0U; ++ uint32_t freq_khz = 0U; ++ struct rdev *regul; ++ int ret; ++ ++ regul = dt_get_cpu_regulator(); ++ if (regul == NULL) { ++ panic(); ++ } ++ ++ ret = regulator_get_voltage(regul); ++ if (ret < 0) { ++ panic(); ++ } ++ ++ cpu_voltage = (uint32_t)ret; ++ ++ if (stm32mp1_clk_compute_all_pll1_settings(cpu_voltage) != 0) { ++ panic(); ++ } ++ ++ ret = dt_get_max_opp_freqvolt(&freq_khz, &voltage_mv); ++ if (ret != 0) { ++ panic(); ++ } ++ ++ if (voltage_mv != cpu_voltage) { ++ if (regulator_set_voltage(regul, (uint16_t)voltage_mv) != 0) { ++ panic(); ++ } ++ ++ ret = stm32mp1_set_opp_khz(freq_khz); ++ if (ret != 0) { ++ ERROR("Cannot set OPP freq %ukHz (%d)\n", freq_khz, ret); ++ panic(); ++ } ++ ++ cpu_voltage = voltage_mv; ++ } ++ } ++ ++ if (stm32mp1_clk_compute_all_pll1_settings(cpu_voltage) != 0) { ++ panic(); ++ } ++} ++ ++static void disable_usb_phy_regulator(void) ++{ ++ if (dt_pmic_status() > 0) { ++ struct rdev *regul = dt_get_usb_phy_regulator(); ++ int ret; ++ ++ if (regul == NULL) { ++ return; ++ } ++ ++ if (regulator_is_enabled(regul) == 1) { ++ ret = regulator_disable(regul); ++ if (ret < 0) { ++ WARN("USBPHYC phy-supply (%s) disable failed\n", regul->reg_name); ++ } ++ } ++ } ++} + + /******************************************************************************* + * Interrupt handler for FIQ (secure IRQ) + ******************************************************************************/ + void sp_min_plat_fiq_handler(uint32_t id) + { ++ bool unrecoverable_err = false; ++ + switch (id & INT_ID_MASK) { ++ case ARM_IRQ_SEC_PHY_TIMER: ++ case STM32MP1_IRQ_MCU_SEV: ++ case STM32MP1_IRQ_RCC_WAKEUP: ++ stm32mp1_calib_it_handler(id); ++ break; ++ case STM32MP1_IRQ_TAMPSERRS: ++ stm32_tamp_it_handler(); ++ break; ++ case ARM_IRQ_SEC_SGI_1: ++ stm32_sgi1_it_handler(); ++ break; ++ case ARM_IRQ_SEC_SGI_6: ++ /* tell the primary cpu to exit from stm32_pwr_down_wfi() */ ++ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) { ++ stm32mp1_calib_set_wakeup(true); ++ } ++ gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_6); ++ break; ++ default: ++ unrecoverable_err = true; ++ break; ++ } ++ ++ if (!unrecoverable_err) { ++ return; ++ } ++ ++ (void)plat_crash_console_init(); ++ ++ switch (id & INT_ID_MASK) { ++ case STM32MP1_IRQ_IWDG1: ++ case STM32MP1_IRQ_IWDG2: ++ stm32_iwdg_it_handler(id); ++ break; + case STM32MP1_IRQ_TZC400: + tzc400_init(STM32MP1_TZC_BASE); + (void)tzc400_it_handler(); +@@ -54,11 +234,43 @@ void sp_min_plat_fiq_handler(uint32_t id) + panic(); + break; + default: +- ERROR("SECURE IT handler not define for it : %u", id); ++ ERROR("SECURE IT handler not define for it : %u\n", id); + break; + } + } + ++/******************************************************************************* ++ * Return the value of the saved PC from the backup register if present ++ ******************************************************************************/ ++static uintptr_t get_saved_pc(void) ++{ ++ uintptr_t bkpr_core1_addr = ++ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); ++ uint32_t saved_pc; ++ uintptr_t bkpr_core1_magic = ++ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); ++ uint32_t magic_nb; ++ ++ clk_enable(RTCAPB); ++ ++ magic_nb = mmio_read_32(bkpr_core1_magic); ++ saved_pc = mmio_read_32(bkpr_core1_addr); ++ ++ clk_disable(RTCAPB); ++ ++ if (magic_nb != BOOT_API_A7_CORE0_MAGIC_NUMBER) { ++ return 0U; ++ } ++ ++ /* BL33 return address should be in DDR */ ++ if ((saved_pc < STM32MP_DDR_BASE) || ++ (saved_pc > (STM32MP_DDR_BASE + (dt_get_ddr_size() - 1U)))) { ++ panic(); ++ } ++ ++ return saved_pc; ++} ++ + /******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type +@@ -67,12 +279,40 @@ 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; +- +- next_image_info = &bl33_image_ep_info; ++ entry_point_info_t *next_image_info = &bl33_image_ep_info; + ++ /* ++ * PC is set to 0 when resetting after STANDBY ++ * The context should be restored, and the image information ++ * should be filled with what was saved ++ */ + if (next_image_info->pc == 0U) { +- return NULL; ++ void *cpu_context; ++ uintptr_t saved_pc; ++ ++ if (stm32_restore_context() != 0) { ++ panic(); ++ } ++ ++ stm32mp_set_console_after_standby(); ++ ++ cpu_context = cm_get_context(NON_SECURE); ++ ++ next_image_info->spsr = read_ctx_reg(get_regs_ctx(cpu_context), ++ CTX_SPSR); ++ ++ /* PC should be retrieved in backup register if OK, else it can ++ * be retrieved from non-secure context ++ */ ++ saved_pc = get_saved_pc(); ++ if (saved_pc != 0U) { ++ next_image_info->pc = saved_pc; ++ } else { ++ next_image_info->pc = ++ read_ctx_reg(get_regs_ctx(cpu_context), CTX_LR); ++ } ++ ++ regulator_core_resume(); + } + + return next_image_info; +@@ -109,20 +349,91 @@ static void stm32mp1_etzpc_early_setup(void) + etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE); + } + ++static void update_fdt_scmi_node(void *external_fdt) ++{ ++ int nodeoff; ++ const fdt32_t *cuint; ++ int val; ++ int len; ++ ++ nodeoff = fdt_path_offset(external_fdt, "/firmware/scmi"); ++ if (nodeoff < 0) { ++ return; ++ } ++ if (fdt_node_check_compatible(external_fdt, nodeoff, "linaro,scmi-optee") != 0) { ++ return; ++ } ++ ++ cuint = fdt_getprop(external_fdt, nodeoff, "linaro,optee-channel-id", &len); ++ if (cuint == NULL) { ++ WARN("linaro,optee-channel-id is missing\n"); ++ return; ++ } ++ ++ val = fdt32_to_cpu(*cuint); ++ ++ fdt_setprop_string(external_fdt, nodeoff, "compatible", "arm,scmi-smc"); ++ fdt_delprop(external_fdt, nodeoff, "linaro,optee-channel-id"); ++ fdt_setprop_u32(external_fdt, nodeoff, "arm,smc-id", ++ STM32_SIP_SMC_SCMI_AGENT0 + val); ++} ++ ++static void update_fdt_optee_node(void *external_fdt) ++{ ++ int nodeoff; ++ ++ nodeoff = fdt_path_offset(external_fdt, "/firmware/optee"); ++ if (nodeoff >= 0) { ++ fdt_del_node(external_fdt, nodeoff); ++ } ++ /* the reserved memory nodes are kept */ ++} ++ ++static void populate_ns_dt(u_register_t ns_dt_addr) ++{ ++ void *external_fdt = (void *)ns_dt_addr; ++ int ret; ++ ++ /* Map beginning of DDR as non-secure for non-secure DT update */ ++ ret = mmap_add_dynamic_region(ns_dt_addr, ns_dt_addr, STM32MP_HW_CONFIG_MAX_SIZE, ++ MT_NON_CACHEABLE | MT_EXECUTE_NEVER | MT_RW | MT_NS); ++ assert(ret == 0); ++ ++ if (fdt_check_header(external_fdt) != 0) { ++ INFO("Non-secure device tree not found\n"); ++ goto out; ++ } ++ ++ ret = fdt_open_into(external_fdt, external_fdt, STM32MP_HW_CONFIG_MAX_SIZE); ++ if (ret < 0) { ++ WARN("Error opening DT %i\n", ret); ++ goto out; ++ } ++ ++ update_fdt_scmi_node(external_fdt); ++ ++ update_fdt_optee_node(external_fdt); ++ ++ ret = fdt_pack(external_fdt); ++ if (ret < 0) { ++ WARN("Error packing DT %i\n", ret); ++ } ++ ++out: ++ ret = mmap_remove_dynamic_region(ns_dt_addr, STM32MP_HW_CONFIG_MAX_SIZE); ++ assert(ret == 0); ++} ++ + /******************************************************************************* + * 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) + { +- struct dt_node_info dt_uart_info; +- int result; + bl_params_t *params_from_bl2 = (bl_params_t *)arg0; +-#if STM32MP_USE_STM32IMAGE +- uintptr_t dt_addr = STM32MP_DTB_BASE; +-#else + uintptr_t dt_addr = arg1; +-#endif ++ ++ stm32mp_setup_early_console(); + + /* Imprecise aborts can be masked in NonSecure */ + write_scr(read_scr() | SCR_AW_BIT); +@@ -166,6 +477,10 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + panic(); + } + ++ if (bl33_image_ep_info.args.arg2 != 0U) { ++ populate_ns_dt(bl33_image_ep_info.args.arg2); ++ } ++ + if (bsec_probe() != 0) { + panic(); + } +@@ -174,26 +489,81 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + panic(); + } + +- result = dt_get_stdout_uart_info(&dt_uart_info); ++ (void)stm32mp_uart_console_setup(); ++ ++ stm32mp1_etzpc_early_setup(); ++ ++ generic_delay_timer_init(); ++ ++ if (dt_pmic_status() > 0) { ++ initialize_pmic(); ++ } ++ ++ fixed_regulator_register(); ++ ++ if (regulator_core_config() != 0) { ++ ERROR("Regulator core config error\n"); ++ panic(); ++ } ++ ++ disable_usb_phy_regulator(); ++ ++ initialize_pll1_settings(); ++ ++ stm32mp1_init_lp_states(); ++} ++ ++static void init_sec_peripherals(void) ++{ ++ int ret; ++ ++ /* Disable MCU subsystem protection */ ++ stm32mp1_clk_mcuss_protect(false); ++ ++ /* Init rtc driver */ ++ ret = stm32_rtc_init(); ++ if (ret < 0) { ++ WARN("RTC driver init error %i\n", ret); ++ } ++ ++ /* Init rng driver */ ++ ret = stm32_rng_init(); ++ if (ret < 0) { ++ WARN("RNG driver init error %i\n", ret); ++ } + +- if ((result > 0) && (dt_uart_info.status != 0U)) { +- unsigned int console_flags; ++ /* Init tamper */ ++ if (stm32_tamp_init() > 0) { ++ struct bkpregs_conf bkpregs_conf = { ++ .nb_zone1_regs = TAMP_BKP_SEC_NUMBER, ++ .nb_zone2_regs = TAMP_BKP_S_W_NS_R_NUMBER ++ /* zone3 all remaining */ ++ }; + +- if (console_stm32_register(dt_uart_info.base, 0, +- STM32MP_UART_BAUDRATE, &console) == +- 0) { ++ /* Enable BKP Register protection */ ++ if (stm32_tamp_set_secure_bkpregs(&bkpregs_conf) < 0) { + panic(); + } + +- console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | +- CONSOLE_FLAG_TRANSLATE_CRLF; +-#ifdef DEBUG +- console_flags |= CONSOLE_FLAG_RUNTIME; +-#endif +- console_set_scope(&console, console_flags); ++ stm32_tamp_configure_secure_access(TAMP_REGS_IT_SECURE); ++ ++ stm32_tamp_configure_internal(INT_TAMP1, TAMP_ENABLE, stm32mp1_tamper_action); ++ stm32_tamp_configure_internal(INT_TAMP2, TAMP_ENABLE, stm32mp1_tamper_action); ++ stm32_tamp_configure_internal(INT_TAMP3, TAMP_ENABLE, stm32mp1_tamper_action); ++ stm32_tamp_configure_internal(INT_TAMP4, TAMP_ENABLE, stm32mp1_tamper_action); ++ ++ ret = stm32_tamp_set_config(); ++ if (ret < 0) { ++ panic(); ++ } ++ ++ /* Enable timestamp for tamper */ ++ stm32_rtc_set_tamper_timestamp(); + } + +- stm32mp1_etzpc_early_setup(); ++ if (stm32_timer_init() == 0) { ++ stm32mp1_calib_init(); ++ } + } + + /******************************************************************************* +@@ -201,17 +571,26 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + ******************************************************************************/ + void sp_min_platform_setup(void) + { +- generic_delay_timer_init(); ++ stm32_init_low_power(); ++ ++ stm32mp_gic_init(); + +- stm32mp1_gic_init(); ++ init_sec_peripherals(); + + if (stm32_iwdg_init() < 0) { + panic(); + } + ++ configure_wakeup_interrupt(); ++ + stm32mp_lock_periph_registering(); + + stm32mp1_init_scmi_server(); ++ ++ /* Cold boot: clean-up regulators state */ ++ if (get_saved_pc() == 0U) { ++ regulator_core_cleanup(); ++ } + } + + void sp_min_plat_arch_setup(void) +diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S +index 85caa0a80..aee4f0ec2 100644 +--- a/plat/st/stm32mp1/stm32mp1.S ++++ b/plat/st/stm32mp1/stm32mp1.S +@@ -1,16 +1,9 @@ + /* +- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +-#if STM32MP_USE_STM32IMAGE +-#ifdef BL32_BIN_PATH +-.section .bl32_image +-.incbin BL32_BIN_PATH +-#endif +-#endif /* STM32MP_USE_STM32IMAGE */ +- + .section .bl2_image + .incbin BL2_BIN_PATH + +diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S +index 945de99e5..1be82193b 100644 +--- a/plat/st/stm32mp1/stm32mp1.ld.S ++++ b/plat/st/stm32mp1/stm32mp1.ld.S +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -16,7 +16,7 @@ OUTPUT_ARCH(PLATFORM_LINKER_ARCH) + ENTRY(__BL2_IMAGE_START__) + + MEMORY { +- HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000 ++ HEADER (rw) : ORIGIN = 0x00000000, LENGTH = STM32MP_HEADER_RESERVED_SIZE + RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE + } + +@@ -43,11 +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. + */ +-#if STM32MP_USE_STM32IMAGE +- . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE ); +-#else + . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE ); +-#endif /* STM32MP_USE_STM32IMAGE */ + __DTB_IMAGE_START__ = .; + *(.dtb_image*) + __DTB_IMAGE_END__ = .; +@@ -57,23 +53,15 @@ SECTIONS + * The strongest and only alignment contraint is MMU 4K page. + * Indeed as images below will be removed, 4K pages will be re-used. + */ ++#if SEPARATE_CODE_AND_RODATA ++ . = ( STM32MP_BL2_RO_BASE - STM32MP_BINARY_BASE ); ++#else + . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE ); ++#endif + __BL2_IMAGE_START__ = .; + *(.bl2_image*) + __BL2_IMAGE_END__ = .; + +-#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) +- /* +- * bl32 will be settled by bl2. +- * The strongest and only alignment constraint is 8 words to simplify +- * memraise8 assembly code. +- */ +- . = ( STM32MP_BL32_BASE - STM32MP_BINARY_BASE ); +- __BL32_IMAGE_START__ = .; +- *(.bl32_image*) +- __BL32_IMAGE_END__ = .; +-#endif /* STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) */ +- + __DATA_END__ = .; + } >RAM + +diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c +index 997335d0d..12aa1c2da 100644 +--- a/plat/st/stm32mp1/stm32mp1_boot_device.c ++++ b/plat/st/stm32mp1/stm32mp1_boot_device.c +@@ -1,9 +1,10 @@ + /* +- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include + #include + + #include +@@ -17,25 +18,62 @@ + #define SZ_64M 0x4000000U + + #if STM32MP_RAW_NAND || STM32MP_SPI_NAND ++#if STM32MP13 ++void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size) ++{ ++ assert(buffer_addr != NULL); ++ assert(buf_size != NULL); ++ ++ *buffer_addr = (void *)STM32MP_MTD_BUFFER; ++ *buf_size = PLATFORM_MTD_MAX_PAGE_SIZE; ++} ++#endif ++ + static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) + { +- int result; + uint32_t nand_param; ++ uint32_t nand2_param __unused; + + /* Check if NAND parameters are stored in OTP */ +- result = bsec_shadow_read_otp(&nand_param, NAND_OTP); +- if (result != BSEC_OK) { +- ERROR("BSEC: NAND_OTP Error %i\n", result); ++ if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) { ++ ERROR("BSEC: NAND_OTP Error\n"); + return -EACCES; + } + + if (nand_param == 0U) { ++#if STM32MP13 ++ if (is_slc) { ++ return 0; ++ } ++#endif ++#if STM32MP15 + return 0; ++#endif + } + + if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) { ++#if STM32MP13 ++ if (is_slc) { ++ goto ecc; ++ } ++#endif ++#if STM32MP15 + goto ecc; ++#endif ++ } ++ ++#if STM32MP13 ++ if (stm32_get_otp_value(NAND2_OTP, &nand2_param) != 0) { ++ ERROR("BSEC: NAND_OTP Error\n"); ++ return -EACCES; ++ } ++ ++ /* Check OTP configuration for this device */ ++ if ((((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND1_SNAND_NAND2) && !is_slc) || ++ (((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND2_SNAND_NAND1) && is_slc)) { ++ nand_param = nand2_param << (NAND_PAGE_SIZE_SHIFT - NAND2_PAGE_SIZE_SHIFT); + } ++#endif + + /* NAND parameter shall be read from OTP */ + if ((nand_param & NAND_WIDTH_MASK) != 0U) { +diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c +index cf8a91eb4..7cf0c0fd7 100644 +--- a/plat/st/stm32mp1/stm32mp1_context.c ++++ b/plat/st/stm32mp1/stm32mp1_context.c +@@ -1,35 +1,528 @@ + /* +- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2017-2021, 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 ++ ++#define TRAINING_AREA_SIZE 64 ++ ++#define BL32_CANARY_ID U(0x424c3332) ++ ++/* ++ * MAILBOX_MAGIC relates to struct backup_data_s as defined ++ * ++ * MAILBOX_MAGIC_V1: ++ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer. ++ * ++ * MAILBOX_MAGIC_V2: ++ * Context provides V1 content and PLL1 dual OPP settings structure (86 bytes). ++ * ++ * MAILBOX_MAGIC_V3: ++ * Context provides V2 content, low power entry point, BL2 code start, end and ++ * BL2_END (102 bytes). And, only for STM32MP13, adds MCE master key (16 bytes). ++ */ ++#define MAILBOX_MAGIC_V1 (0x0001 << 16) ++#define MAILBOX_MAGIC_V2 (0x0002 << 16) ++#define MAILBOX_MAGIC_V3 (0x0003 << 16) ++#define MAILBOX_MAGIC (MAILBOX_MAGIC_V3 | \ ++ 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 MAILBOX_MAGIC_V2/_V3 does not support expected PLL1 settings ++#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 { ++ 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]; ++ uint32_t low_power_ep; ++ uint32_t bl2_code_base; ++ uint32_t bl2_code_end; ++ uint32_t bl2_end; ++#if STM32MP13 ++ uint8_t mce_mkey[MCE_KEY_SIZE_IN_BYTES]; ++#endif ++}; ++ ++#if defined(IMAGE_BL32) ++struct backup_bl32_data_s { ++ uint32_t canary_id; ++ smc_ctx_t saved_smc_context[PLATFORM_CORE_COUNT]; ++ cpu_context_t saved_cpu_context[PLATFORM_CORE_COUNT]; ++ struct stm32_rtc_calendar rtc; ++ unsigned long long stgen; ++ uint8_t clock_cfg[CLOCK_CONTEXT_SIZE]; ++ uint8_t scmi_context[SCMI_CONTEXT_SIZE]; ++ uint8_t regul_context[PLAT_BACKUP_REGULATOR_SIZE]; ++}; ++ ++static struct backup_bl32_data_s *get_bl32_backup_data(void) ++{ ++ return (struct backup_bl32_data_s *)(STM32MP_BACKUP_RAM_BASE + ++ sizeof(struct backup_data_s)); ++} ++#endif ++ ++uint32_t stm32_pm_get_optee_ep(void) ++{ ++ struct backup_data_s *backup_data; ++ uint32_t ep; ++ ++#if STM32MP15 ++ clk_enable(BKPSRAM); ++#endif ++ ++ /* Context & Data to be saved at the beginning of Backup SRAM */ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ switch (MAGIC_ID(backup_data->magic)) { ++ case MAILBOX_MAGIC_V1: ++ case MAILBOX_MAGIC_V2: ++ case MAILBOX_MAGIC_V3: ++ if (MAGIC_AREA_SIZE(backup_data->magic) != TRAINING_AREA_SIZE) { ++ panic(); ++ } ++ break; ++ default: ++ ERROR("PM context: bad magic\n"); ++ panic(); ++ } ++ ++ ep = backup_data->core0_resume_hint; ++ ++#if STM32MP15 ++ clk_disable(BKPSRAM); ++#endif ++ ++ return ep; ++} ++ ++void stm32_clean_context(void) ++{ ++ clk_enable(BKPSRAM); ++ ++#if defined(IMAGE_BL2) ++ zeromem((void *)STM32MP_BACKUP_RAM_BASE, sizeof(struct backup_data_s)); ++#elif defined(IMAGE_BL32) ++ zeromem((void *)get_bl32_backup_data(), sizeof(struct backup_bl32_data_s)); ++#endif + +-#define TAMP_BOOT_ITF_BACKUP_REG_ID U(20) +-#define TAMP_BOOT_ITF_MASK U(0x0000FF00) +-#define TAMP_BOOT_ITF_SHIFT 8 ++ clk_disable(BKPSRAM); ++} + +-int stm32_save_boot_interface(uint32_t interface, uint32_t instance) ++#if defined(IMAGE_BL32) ++void stm32mp1_pm_save_clock_cfg(size_t offset, uint8_t *data, size_t size) + { +- uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); ++ struct backup_bl32_data_s *backup_data = get_bl32_backup_data(); ++ ++ if (offset + size > sizeof(backup_data->clock_cfg)) { ++ panic(); ++ } ++ ++ clk_enable(BKPSRAM); + +- stm32mp_clk_enable(RTCAPB); ++ memcpy(backup_data->clock_cfg + offset, data, size); + +- mmio_clrsetbits_32(bkpr_itf_idx, +- TAMP_BOOT_ITF_MASK, +- ((interface << 4) | (instance & 0xFU)) << +- TAMP_BOOT_ITF_SHIFT); ++ clk_disable(BKPSRAM); ++} ++ ++void stm32mp1_pm_restore_clock_cfg(size_t offset, uint8_t *data, size_t size) ++{ ++ struct backup_bl32_data_s *backup_data = get_bl32_backup_data(); + +- stm32mp_clk_disable(RTCAPB); ++ if (offset + size > sizeof(backup_data->clock_cfg)) ++ panic(); ++ ++ clk_enable(BKPSRAM); ++ ++ memcpy(data, backup_data->clock_cfg + offset, size); ++ ++ clk_disable(BKPSRAM); ++} ++ ++int stm32_save_context(uint32_t zq0cr0_zdata, ++ struct stm32_rtc_calendar *rtc_time, ++ unsigned long long stgen_cnt) ++{ ++ void *smc_context; ++ void *cpu_context; ++ struct backup_data_s *backup_data; ++ struct backup_bl32_data_s *backup_bl32_data; ++ ++ stm32mp1_clock_suspend(); ++ ++ clk_enable(BKPSRAM); ++ ++ /* Context & Data to be saved at the beginning of Backup SRAM */ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ /* Save BL32 context data provided to BL2 */ ++ backup_data->magic = MAILBOX_MAGIC; ++ ++ backup_data->zq0cr0_zdata = zq0cr0_zdata; ++ ++ stm32mp1_clk_lp_save_opp_pll1_settings(backup_data->pll1_settings, ++ sizeof(backup_data->pll1_settings)); ++ ++ /* Save the BL32 specific data */ ++ backup_bl32_data = get_bl32_backup_data(); ++ ++ backup_bl32_data->canary_id = BL32_CANARY_ID; ++ ++ /* Retrieve smc context struct address */ ++ smc_context = smc_get_ctx(NON_SECURE); ++ ++ /* Retrieve smc context struct address */ ++ cpu_context = cm_get_context(NON_SECURE); ++ ++ /* Save context in Backup SRAM */ ++ memcpy(&backup_bl32_data->saved_smc_context[0], smc_context, ++ sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT); ++ memcpy(&backup_bl32_data->saved_cpu_context[0], cpu_context, ++ sizeof(cpu_context_t) * PLATFORM_CORE_COUNT); ++ ++ memcpy(&backup_bl32_data->rtc, rtc_time, sizeof(struct stm32_rtc_calendar)); ++ backup_bl32_data->stgen = stgen_cnt; ++ ++ stm32mp1_pm_save_scmi_state(backup_bl32_data->scmi_context, ++ sizeof(backup_bl32_data->scmi_context)); ++ ++ save_clock_pm_context(); ++ ++ regulator_core_backup_context(backup_bl32_data->regul_context, ++ sizeof(backup_bl32_data->regul_context)); ++ ++ clk_disable(BKPSRAM); + + return 0; + } ++ ++int stm32_restore_context(void) ++{ ++ void *smc_context; ++ void *cpu_context; ++ struct backup_data_s *backup_data; ++ struct backup_bl32_data_s *backup_bl32_data; ++ struct stm32_rtc_calendar current_calendar; ++ unsigned long long stdby_time_in_ms; ++ ++ /* Context & Data to be saved at the beginning of Backup SRAM */ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ clk_enable(BKPSRAM); ++ ++ stm32mp1_clk_lp_load_opp_pll1_settings(backup_data->pll1_settings, ++ sizeof(backup_data->pll1_settings)); ++ ++ backup_bl32_data = get_bl32_backup_data(); ++ ++ if (backup_bl32_data->canary_id != BL32_CANARY_ID) { ++ ERROR("Incorrect BL32 backup data\n"); ++ return -EINVAL; ++ } ++ ++ /* Retrieve smc context struct address */ ++ smc_context = smc_get_ctx(NON_SECURE); ++ ++ /* Retrieve smc context struct address */ ++ cpu_context = cm_get_context(NON_SECURE); ++ ++ restore_clock_pm_context(); ++ ++ stm32mp1_pm_restore_scmi_state(backup_bl32_data->scmi_context, ++ sizeof(backup_bl32_data->scmi_context)); ++ ++ /* Restore data from Backup SRAM */ ++ memcpy(smc_context, backup_bl32_data->saved_smc_context, ++ sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT); ++ memcpy(cpu_context, backup_bl32_data->saved_cpu_context, ++ sizeof(cpu_context_t) * PLATFORM_CORE_COUNT); ++ ++ /* Restore STGEN counter with standby mode length */ ++ stm32_rtc_get_calendar(¤t_calendar); ++ stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, ++ &backup_bl32_data->rtc); ++ stm32mp_stgen_restore_counter(backup_bl32_data->stgen, stdby_time_in_ms); ++ ++ regulator_core_restore_context(backup_bl32_data->regul_context, ++ sizeof(backup_bl32_data->regul_context)); ++ ++ clk_disable(BKPSRAM); ++ ++ stm32mp1_clock_resume(); ++ ++ return 0; ++} ++ ++unsigned long long stm32_get_stgen_from_context(void) ++{ ++ struct backup_bl32_data_s *backup_data; ++ unsigned long long stgen_cnt; ++ ++ clk_enable(BKPSRAM); ++ ++ backup_data = get_bl32_backup_data(); ++ ++ stgen_cnt = backup_data->stgen; ++ ++ clk_disable(BKPSRAM); ++ ++ return stgen_cnt; ++} ++ ++void stm32_context_get_bl2_low_power_params(uintptr_t *bl2_code_base, ++ uintptr_t *bl2_code_end, ++ uintptr_t *bl2_end) ++{ ++ struct backup_data_s *backup_data; ++ ++ clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ if (MAGIC_ID(backup_data->magic) != MAILBOX_MAGIC_V3) { ++ panic(); ++ } ++ ++ *bl2_code_base = (uintptr_t)backup_data->bl2_code_base; ++ *bl2_code_end = (uintptr_t)backup_data->bl2_code_end; ++ *bl2_end = (uintptr_t)backup_data->bl2_end; ++ ++ clk_disable(BKPSRAM); ++} ++ ++#endif /* IMAGE_BL32 */ ++ ++#if defined(IMAGE_BL2) ++void stm32_context_save_bl2_param(void) ++{ ++ struct backup_data_s *backup_data; ++ ++ clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ backup_data->low_power_ep = (uint32_t)&stm32_pwr_down_wfi_wrapper; ++ backup_data->bl2_code_base = BL_CODE_BASE; ++ backup_data->bl2_code_end = BL_CODE_END; ++ backup_data->bl2_end = BL2_END; ++ backup_data->magic = MAILBOX_MAGIC_V3; ++ backup_data->zq0cr0_zdata = ddr_get_io_calibration_val(); ++ ++ clk_disable(BKPSRAM); ++} ++#endif ++ ++uint32_t stm32_get_zdata_from_context(void) ++{ ++ struct backup_data_s *backup_data; ++ uint32_t zdata; ++ ++ clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ zdata = (backup_data->zq0cr0_zdata >> DDRPHYC_ZQ0CRN_ZDATA_SHIFT) & ++ DDRPHYC_ZQ0CRN_ZDATA_MASK; ++ ++ clk_disable(BKPSRAM); ++ ++ return zdata; ++} ++ ++static int pll1_settings_in_context(struct backup_data_s *backup_data) ++{ ++ switch (MAGIC_ID(backup_data->magic)) { ++ case MAILBOX_MAGIC_V1: ++ return -ENOENT; ++ case MAILBOX_MAGIC_V2: ++ case MAILBOX_MAGIC_V3: ++ assert(MAGIC_AREA_SIZE(backup_data->magic) == ++ TRAINING_AREA_SIZE); ++ return 0; ++ default: ++ panic(); ++ } ++} ++ ++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; ++ ++ 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); ++ } ++ ++ 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; ++ ++ 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); ++ ++ clk_disable(BKPSRAM); ++ ++ return is_valid; ++} ++ ++bool stm32_pm_context_is_valid(void) ++{ ++ struct backup_data_s *backup_data; ++ bool ret; ++ ++ clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ switch (MAGIC_ID(backup_data->magic)) { ++ case MAILBOX_MAGIC_V1: ++ case MAILBOX_MAGIC_V2: ++ case MAILBOX_MAGIC_V3: ++ ret = true; ++ break; ++ default: ++ ret = false; ++ break; ++ } ++ ++ clk_disable(BKPSRAM); ++ ++ return ret; ++} ++ ++#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 ++ * standby, and will be restored after ++ */ ++void stm32_save_ddr_training_area(void) ++{ ++ struct backup_data_s *backup_data; ++ int ret __unused; ++ ++ 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); ++ ++ flush_dcache_range(STM32MP_DDR_BASE, TRAINING_AREA_SIZE); ++ ++ 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); ++ ++ clk_disable(BKPSRAM); ++} ++#endif ++ ++void stm32_restore_ddr_training_area(void) ++{ ++ struct backup_data_s *backup_data; ++ ++ clk_enable(BKPSRAM); ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ memcpy((uint32_t *)STM32MP_DDR_BASE, ++ &backup_data->ddr_training_backup, ++ TRAINING_AREA_SIZE); ++ dsb(); ++ ++ clk_disable(BKPSRAM); ++} ++ ++#if STM32MP13 ++void stm32mp1_pm_save_mce_mkey_in_context(uint8_t *data) ++{ ++ struct backup_data_s *backup_data; ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ clk_enable(BKPSRAM); ++ ++ memcpy(backup_data->mce_mkey, data, MCE_KEY_SIZE_IN_BYTES); ++ ++ clk_disable(BKPSRAM); ++} ++ ++void stm32mp1_pm_get_mce_mkey_from_context(uint8_t *data) ++{ ++ struct backup_data_s *backup_data; ++ ++ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE; ++ ++ clk_enable(BKPSRAM); ++ ++ memcpy(data, backup_data->mce_mkey, MCE_KEY_SIZE_IN_BYTES); ++ ++ clk_disable(BKPSRAM); ++} ++ ++#endif +diff --git a/plat/st/stm32mp1/stm32mp1_critic_power.c b/plat/st/stm32mp1/stm32mp1_critic_power.c +new file mode 100644 +index 000000000..a84f38b29 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_critic_power.c +@@ -0,0 +1,167 @@ ++/* ++ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++static void cstop_critic_enter(uint32_t mode) ++{ ++ /* Init generic timer that is needed for udelay used in ddr driver */ ++ generic_delay_timer_init(); ++ ++ /* Switch to Software Self-Refresh mode */ ++ ddr_set_sr_mode(DDR_SSR_MODE); ++ ++ /* ++ * Set DDR in Self-refresh,. ++ * This is also the procedure awaited when switching off power supply. ++ */ ++ if (ddr_standby_sr_entry() != 0) { ++ ERROR("Unable to put DDR in SR\n"); ++ if (mode != STM32_PM_SHUTDOWN) { ++ panic(); ++ } ++ } ++} ++ ++static void shutdown_critic_enter(void) ++{ ++ if (dt_pmic_status() > 0) { ++ if (!initialize_pmic_i2c()) { ++ panic(); ++ } ++ ++ pmic_switch_off(); ++ } ++} ++ ++/* ++ * stm32_exit_cstop_critic - Exit from CSTOP mode reenable DDR ++ */ ++void stm32_pwr_cstop_critic_exit(void) ++{ ++#if STM32MP13 ++ bsec_write_scratch((uint32_t)0U); ++#endif ++ ++#if defined(IMAGE_BL2) ++ /* Init generic timer that is needed for udelay used in ddr driver */ ++ stm32mp_stgen_restore_rate(); ++ ++ generic_delay_timer_init(); ++#endif ++ ++ if (ddr_sw_self_refresh_exit() != 0) { ++ panic(); ++ } ++} ++ ++void stm32_pwr_down_wfi_load(bool is_cstop, uint32_t mode) ++{ ++ if (mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP2) { ++#if STM32MP15 ++ ERROR("LPLV-Stop2 mode not supported\n"); ++ panic(); ++#endif ++ ++#if STM32MP13 ++ /* If mode is STOP 2, set the entry point */ ++ bsec_write_scratch((uint32_t)stm32_pwr_back_from_stop2); ++#endif ++ } ++ ++ if (mode != STM32_PM_CSLEEP_RUN) { ++ dcsw_op_all(DC_OP_CISW); ++ } ++ ++ if (is_cstop) { ++ cstop_critic_enter(mode); ++ } ++ ++ if (mode == STM32_PM_SHUTDOWN) { ++ shutdown_critic_enter(); ++ } ++ ++ /* ++ * Synchronize on memory accesses and instruction flow before the WFI ++ * instruction. ++ */ ++ dsb(); ++ isb(); ++ wfi(); ++ ++ stm32_iwdg_refresh(); ++ ++ if (is_cstop) { ++ stm32_pwr_cstop_critic_exit(); ++ } ++} ++ ++#if STM32MP13 ++void stm32_pwr_call_optee_ep(void) ++{ ++ void (*optee_ep)(void); ++ ++ optee_ep = (void (*)(void))stm32_pm_get_optee_ep(); ++ ++ optee_ep(); ++ ++ /* This shouldn't be reached */ ++ panic(); ++} ++#endif ++ ++#if defined(IMAGE_BL32) ++extern void wfi_svc_int_enable(uintptr_t stack_addr); ++static uint32_t int_stack[STM32MP_INT_STACK_SIZE]; ++ ++void stm32_pwr_down_wfi(bool is_cstop, uint32_t mode) ++{ ++ uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; ++ ++ if (mode != STM32_PM_CSLEEP_RUN) { ++ dcsw_op_all(DC_OP_CISW); ++ } ++ ++ if (is_cstop) { ++ cstop_critic_enter(mode); ++ } ++ ++ if (mode == STM32_PM_SHUTDOWN) { ++ shutdown_critic_enter(); ++ } ++ ++ stm32mp1_calib_set_wakeup(false); ++ ++ while (interrupt == GIC_SPURIOUS_INTERRUPT && ++ !stm32mp1_calib_get_wakeup()) { ++ wfi_svc_int_enable((uintptr_t)&int_stack[0]); ++ ++ interrupt = gicv2_acknowledge_interrupt(); ++ ++ if (interrupt != GIC_SPURIOUS_INTERRUPT) { ++ gicv2_end_of_interrupt(interrupt); ++ } ++ ++ stm32_iwdg_refresh(); ++ } ++ ++ if (is_cstop) { ++ stm32_pwr_cstop_critic_exit(); ++ } ++} ++#endif +diff --git a/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S +new file mode 100644 +index 000000000..d7981d61c +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S +@@ -0,0 +1,134 @@ ++/* ++ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++ .global stm32_pwr_down_wfi_load ++ .global stm32_pwr_cstop_critic_exit ++ .global stm32_pwr_down_wfi_wrapper ++#if STM32MP13 ++ .global stm32_pwr_back_from_stop2 ++ .global stm32_pwr_call_optee_ep ++#endif ++ .global bl2_vector_table ++ .global disable_mmu_secure ++ .global __STACKS_END__ ++ ++.section .data ++ .balign 4 ++saved_sp: .word 0x00000000 ++saved_vbar: .word 0x00000000 ++saved_mvbar: .word 0x00000000 ++ ++.section .text ++ .align 5 ++ ++func stm32_pwr_down_wfi_wrapper ++ push {r4,r5,r6,lr} ++ ++ # Save r0 and r1 in r2 and r3, as they are used in disable_mmu_secure ++ mov r2, r0 ++ mov r3, r1 ++ ++ # Save current sp in sp1 ++ ldr r1, =saved_sp ++ str sp, [r1] ++ ++ # Save current VBAR in vbar1 ++ ldr r1, =saved_vbar ++ ldcopr r0, VBAR ++ str r0, [r1] ++ ++ # Save current MVBAR in mvbar1 ++ ldr r1, =saved_mvbar ++ ldcopr r0, MVBAR ++ str r0, [r1] ++ ++ # Reuse BL2 vector table for VBAR and MVBAR ++ ldr r1, =bl2_vector_table ++ stcopr r1, VBAR ++ stcopr r1, MVBAR ++ ++ # Set sp to BL2 STACK (as BL2 is not using it anymore) ++ ldr sp, =__STACKS_END__ ++ ++ # Disable MMU as TLB are still stored in DDR, ++ # and in few instructions DDR won't be readable ++ bl disable_mmu_secure ++ ++ # dsb is done in disable mmu ++ # isb is done in disable mmu ++ ++ mov r0, r2 ++ mov r1, r3 ++ ++ bl stm32_pwr_down_wfi_load ++ ++ # Restore stack ++ ldr r1, =saved_sp ++ ldr sp, [r1] ++ ++ # Restore VBAR ++ ldr r1, =saved_vbar ++ ldr r0, [r1] ++ stcopr r0, VBAR ++ ++ # Restore MVBAR ++ ldr r1, =saved_mvbar ++ ldr r0, [r1] ++ stcopr r0, MVBAR ++ ++ # Synchronize on memory access and instruction ++ # after resetting stack/IT handler ++ dsb ++ isb ++ ++ pop {r4,r5,r6,pc} ++endfunc stm32_pwr_down_wfi_wrapper ++ ++#if STM32MP13 ++func stm32_pwr_back_from_stop2 ++ # switch to monitor mode. ++ cps #MODE32_mon ++ ++ ldr sp, =__STACKS_END__ ++ ++ ldr r1, =bl2_vector_table ++ stcopr r1, VBAR ++ stcopr r1, MVBAR ++ ++ # exit ddr from self refresh ++ bl stm32_pwr_cstop_critic_exit ++ ++ # Restore stack ++ ldr r1, =saved_sp ++ ldr sp, [r1] ++ ++ # Restore VBAR ++ ldr r1, =saved_vbar ++ ldr r0, [r1] ++ stcopr r0, VBAR ++ ++ # Restore MVBAR ++ ldr r1, =saved_mvbar ++ ldr r0, [r1] ++ stcopr r0, MVBAR ++ ++ # Synchronize on memory access and instruction ++ # after resetting stack/IT handler ++ dsb ++ isb ++ ++ bl stm32_pwr_call_optee_ep ++ ++endfunc stm32_pwr_back_from_stop2 ++#endif +diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c +index d0264968c..b70402111 100644 +--- a/plat/st/stm32mp1/stm32mp1_dbgmcu.c ++++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c +@@ -1,15 +1,17 @@ + /* +- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include + #include + + #include + + #include + #include ++#include + #include + #include + #include +@@ -17,44 +19,32 @@ + #include + + #define DBGMCU_IDC U(0x00) +-#define DBGMCU_APB4FZ1 U(0x2C) + + #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) +- +-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 -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); ++ mmio_setbits_32(RCC_BASE + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); + + return 0; + } + ++/* ++ * @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); ++ + if (stm32mp1_dbgmcu_init() != 0) { + return -EPERM; + } +@@ -65,32 +55,21 @@ 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) + { +- if (stm32mp1_dbgmcu_init() != 0) { +- return -EPERM; +- } +- +- *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & +- DBGMCU_IDC_DEV_ID_MASK; +- +- return 0; +-} +- +-int stm32mp1_dbgmcu_freeze_iwdg2(void) +-{ +- uint32_t dbg_conf; ++ assert(chip_dev_id != NULL); + + if (stm32mp1_dbgmcu_init() != 0) { + return -EPERM; + } + +- dbg_conf = bsec_read_debug_conf(); +- +- if ((dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN)) != 0U) { +- mmio_setbits_32(DBGMCU_BASE + DBGMCU_APB4FZ1, +- DBGMCU_APB4FZ1_IWDG2); +- } ++ *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & ++ DBGMCU_IDC_DEV_ID_MASK; + + return 0; + } +diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h +index f5d4b2f38..d95945c22 100644 +--- a/plat/st/stm32mp1/stm32mp1_def.h ++++ b/plat/st/stm32mp1/stm32mp1_def.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -11,32 +11,49 @@ + #include + #include + #include ++#include + #include + #include + + #ifndef __ASSEMBLER__ + #include ++#include + #include ++#include ++#include + + #include +-#include + #include + #include + #include ++#include + #include + #include + #include + #endif + +-#if !STM32MP_USE_STM32IMAGE + #include "stm32mp1_fip_def.h" +-#else /* STM32MP_USE_STM32IMAGE */ +-#include "stm32mp1_stm32image_def.h" +-#endif /* STM32MP_USE_STM32IMAGE */ + + /******************************************************************************* + * CHIP ID + ******************************************************************************/ ++#if STM32MP13 ++#define STM32MP1_CHIP_ID U(0x501) ++ ++#define STM32MP135C_PART_NB U(0x05010000) ++#define STM32MP135A_PART_NB U(0x05010001) ++#define STM32MP133C_PART_NB U(0x050100C0) ++#define STM32MP133A_PART_NB U(0x050100C1) ++#define STM32MP131C_PART_NB U(0x050106C8) ++#define STM32MP131A_PART_NB U(0x050106C9) ++#define STM32MP135F_PART_NB U(0x05010800) ++#define STM32MP135D_PART_NB U(0x05010801) ++#define STM32MP133F_PART_NB U(0x050108C0) ++#define STM32MP133D_PART_NB U(0x050108C1) ++#define STM32MP131F_PART_NB U(0x05010EC8) ++#define STM32MP131D_PART_NB U(0x05010EC9) ++#endif ++#if STM32MP15 + #define STM32MP1_CHIP_ID U(0x500) + + #define STM32MP157C_PART_NB U(0x05000000) +@@ -51,26 +68,63 @@ + #define STM32MP153D_PART_NB U(0x050000A5) + #define STM32MP151F_PART_NB U(0x050000AE) + #define STM32MP151D_PART_NB U(0x050000AF) ++#endif + + #define STM32MP1_REV_B U(0x2000) ++#if STM32MP13 ++#define STM32MP1_REV_Y U(0x1003) ++#define STM32MP1_REV_Z U(0x1001) ++#endif ++#if STM32MP15 + #define STM32MP1_REV_Z U(0x2001) ++#endif + + /******************************************************************************* + * PACKAGE ID + ******************************************************************************/ ++#if STM32MP15 + #define PKG_AA_LFBGA448 U(4) + #define PKG_AB_LFBGA354 U(3) + #define PKG_AC_TFBGA361 U(2) + #define PKG_AD_TFBGA257 U(1) ++#endif ++ ++/******************************************************************************* ++ * BOOT PARAM ++ ******************************************************************************/ ++#define BOOT_PARAM_ADDR U(0x2FFC0078) + + /******************************************************************************* + * STM32MP1 memory map related constants + ******************************************************************************/ + #define STM32MP_ROM_BASE U(0x00000000) + #define STM32MP_ROM_SIZE U(0x00020000) +- ++#define STM32MP_ROM_SIZE_2MB_ALIGNED U(0x00200000) ++ ++#if STM32MP13 ++#define STM32MP_SYSRAM_BASE U(0x2FFE0000) ++#define STM32MP_SYSRAM_SIZE U(0x00020000) ++#define SRAM1_BASE U(0x30000000) ++#define SRAM1_SIZE U(0x00004000) ++#define SRAM2_BASE U(0x30004000) ++#define SRAM2_SIZE U(0x00002000) ++#define SRAM3_BASE U(0x30006000) ++#define SRAM3_SIZE U(0x00002000) ++#define SRAMS_BASE SRAM1_BASE ++#define SRAMS_SIZE_2MB_ALIGNED U(0x00200000) ++#endif /* STM32MP13 */ ++#if STM32MP15 + #define STM32MP_SYSRAM_BASE U(0x2FFC0000) + #define STM32MP_SYSRAM_SIZE U(0x00040000) ++#endif /* STM32MP15 */ ++ ++#define STM32MP_BACKUP_RAM_BASE U(0x54000000) ++#if STM32MP13 ++#define STM32MP_BACKUP_RAM_SIZE U(0x00002000) /* 8KB */ ++#endif /* STM32MP13 */ ++#if STM32MP15 ++#define STM32MP_BACKUP_RAM_SIZE U(0x00001000) /* 4KB */ ++#endif /* STM32MP15 */ + + #define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE + #define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \ +@@ -98,9 +152,20 @@ enum ddr_type { + #endif + + /* Section used inside TF binaries */ ++#if STM32MP13 ++/* 512 Octets reserved for header */ ++#define STM32MP_HEADER_RESERVED_SIZE U(0x200) ++ ++#define STM32MP_BINARY_BASE STM32MP_SEC_SYSRAM_BASE ++ ++#define STM32MP_BINARY_SIZE STM32MP_SEC_SYSRAM_SIZE ++#endif ++#if STM32MP15 + #define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */ + /* 256 Octets reserved for header */ + #define STM32MP_HEADER_SIZE U(0x00000100) ++/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */ ++#define STM32MP_HEADER_RESERVED_SIZE U(0x3000) + + #define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_PARAM_LOAD_SIZE + \ +@@ -109,24 +174,55 @@ enum ddr_type { + #define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ + (STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE)) ++#endif ++ ++/* BL2 and BL32/sp_min require finer granularity tables */ ++#if defined(IMAGE_BL2) ++#define MAX_XLAT_TABLES U(2) /* 8 KB for mapping */ ++#endif + +-/* BL2 and BL32/sp_min require 4 tables */ +-#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */ ++#if defined(IMAGE_BL32) ++#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) +- #define MAX_MMAP_REGIONS 11 ++ #if STM32MP_USB_PROGRAMMER ++ #define MAX_MMAP_REGIONS 8 ++ #else ++ #define MAX_MMAP_REGIONS 7 ++ #endif + #endif + ++#if STM32MP13 ++#define STM32MP_BL33_BASE STM32MP_DDR_BASE ++#endif ++#if STM32MP15 + #define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) ++#endif + #define STM32MP_BL33_MAX_SIZE U(0x400000) + ++/* Define Temporary Stack size use during low power mode */ ++#define STM32MP_INT_STACK_SIZE 0x200 ++ + /* Define maximum page size for NAND devices */ + #define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000) + ++/* Define location for the MTD scratch buffer */ ++#if STM32MP13 ++#define STM32MP_MTD_BUFFER (SRAM1_BASE + \ ++ SRAM1_SIZE - \ ++ PLATFORM_MTD_MAX_PAGE_SIZE) ++#endif ++/* ++ * 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 device/io map related constants (used for MMU) + ******************************************************************************/ +@@ -146,6 +242,22 @@ enum ddr_type { + ******************************************************************************/ + #define PWR_BASE U(0x50001000) + ++/******************************************************************************* ++ * STM32MP1 EXTI ++ ******************************************************************************/ ++#define EXTI_BASE U(0x5000D000) ++#define EXTI_TZENR1 U(0x14) ++#define EXTI_RPR3 U(0x4C) ++#define EXTI_FPR3 U(0x50) ++#define EXTI_C1IMR1 U(0x80) ++#define EXTI_C2IMR1 U(0xC0) ++#define EXTI_C2IMR2 U(0xD0) ++#define EXTI_C2IMR3 U(0xE0) ++#define EXTI_TZENR1_TZEN18 BIT(18) ++#define EXTI_IMR1_IM18 BIT(18) ++#define EXTI_RPR3_RPIF65 BIT(1) ++#define EXTI_FPR3_FPIF65 BIT(1) ++ + /******************************************************************************* + * STM32MP1 GPIO + ******************************************************************************/ +@@ -158,9 +270,11 @@ enum ddr_type { + #define GPIOG_BASE U(0x50008000) + #define GPIOH_BASE U(0x50009000) + #define GPIOI_BASE U(0x5000A000) ++#if STM32MP15 + #define GPIOJ_BASE U(0x5000B000) + #define GPIOK_BASE U(0x5000C000) + #define GPIOZ_BASE U(0x54004000) ++#endif + #define GPIO_BANK_OFFSET U(0x1000) + + /* Bank IDs used in GPIO driver API */ +@@ -173,11 +287,13 @@ enum ddr_type { + #define GPIO_BANK_G U(6) + #define GPIO_BANK_H U(7) + #define GPIO_BANK_I U(8) ++#if STM32MP15 + #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 ++#endif + + /******************************************************************************* + * STM32MP1 UART +@@ -190,10 +306,21 @@ enum ddr_type { + #define USART6_BASE U(0x44003000) + #define UART7_BASE U(0x40018000) + #define UART8_BASE U(0x40019000) +-#define STM32MP_UART_BAUDRATE U(115200) + + /* For UART crash console */ + #define STM32MP_DEBUG_USART_BASE UART4_BASE ++#if STM32MP13 ++/* UART4 on HSI@64MHz, TX on GPIOF12 Alternate 8 (Disco board) */ ++#define STM32MP_DEBUG_USART_CLK_FRQ 64000000 ++#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOD_BASE ++#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_S_AHB4ENSETR ++#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_S_AHB4ENSETR_GPIODEN ++#define DEBUG_UART_TX_GPIO_PORT 6 ++#define DEBUG_UART_TX_GPIO_ALTERNATE 8 ++#define DEBUG_UART_TX_CLKSRC_REG RCC_UART4CKSELR ++#define DEBUG_UART_TX_CLKSRC RCC_UART4CKSELR_HSI ++#endif /* STM32MP13 */ ++#if STM32MP15 + /* 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 +@@ -203,6 +330,7 @@ enum ddr_type { + #define DEBUG_UART_TX_GPIO_ALTERNATE 6 + #define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR + #define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI ++#endif /* STM32MP15 */ + #define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR + #define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN + #define DEBUG_UART_RST_REG RCC_APB1RSTSETR +@@ -219,100 +347,18 @@ enum ddr_type { + + #define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0) + +-/* ETZPC DECPROT IDs */ +-#define STM32MP1_ETZPC_STGENC_ID 0 +-#define STM32MP1_ETZPC_BKPSRAM_ID 1 +-#define STM32MP1_ETZPC_IWDG1_ID 2 +-#define STM32MP1_ETZPC_USART1_ID 3 +-#define STM32MP1_ETZPC_SPI6_ID 4 +-#define STM32MP1_ETZPC_I2C4_ID 5 +-#define STM32MP1_ETZPC_RNG1_ID 7 +-#define STM32MP1_ETZPC_HASH1_ID 8 +-#define STM32MP1_ETZPC_CRYP1_ID 9 +-#define STM32MP1_ETZPC_DDRCTRL_ID 10 +-#define STM32MP1_ETZPC_DDRPHYC_ID 11 +-#define STM32MP1_ETZPC_I2C6_ID 12 +-#define STM32MP1_ETZPC_SEC_ID_LIMIT 13 +- +-#define STM32MP1_ETZPC_TIM2_ID 16 +-#define STM32MP1_ETZPC_TIM3_ID 17 +-#define STM32MP1_ETZPC_TIM4_ID 18 +-#define STM32MP1_ETZPC_TIM5_ID 19 +-#define STM32MP1_ETZPC_TIM6_ID 20 +-#define STM32MP1_ETZPC_TIM7_ID 21 +-#define STM32MP1_ETZPC_TIM12_ID 22 +-#define STM32MP1_ETZPC_TIM13_ID 23 +-#define STM32MP1_ETZPC_TIM14_ID 24 +-#define STM32MP1_ETZPC_LPTIM1_ID 25 +-#define STM32MP1_ETZPC_WWDG1_ID 26 +-#define STM32MP1_ETZPC_SPI2_ID 27 +-#define STM32MP1_ETZPC_SPI3_ID 28 +-#define STM32MP1_ETZPC_SPDIFRX_ID 29 +-#define STM32MP1_ETZPC_USART2_ID 30 +-#define STM32MP1_ETZPC_USART3_ID 31 +-#define STM32MP1_ETZPC_UART4_ID 32 +-#define STM32MP1_ETZPC_UART5_ID 33 +-#define STM32MP1_ETZPC_I2C1_ID 34 +-#define STM32MP1_ETZPC_I2C2_ID 35 +-#define STM32MP1_ETZPC_I2C3_ID 36 +-#define STM32MP1_ETZPC_I2C5_ID 37 +-#define STM32MP1_ETZPC_CEC_ID 38 +-#define STM32MP1_ETZPC_DAC_ID 39 +-#define STM32MP1_ETZPC_UART7_ID 40 +-#define STM32MP1_ETZPC_UART8_ID 41 +-#define STM32MP1_ETZPC_MDIOS_ID 44 +-#define STM32MP1_ETZPC_TIM1_ID 48 +-#define STM32MP1_ETZPC_TIM8_ID 49 +-#define STM32MP1_ETZPC_USART6_ID 51 +-#define STM32MP1_ETZPC_SPI1_ID 52 +-#define STM32MP1_ETZPC_SPI4_ID 53 +-#define STM32MP1_ETZPC_TIM15_ID 54 +-#define STM32MP1_ETZPC_TIM16_ID 55 +-#define STM32MP1_ETZPC_TIM17_ID 56 +-#define STM32MP1_ETZPC_SPI5_ID 57 +-#define STM32MP1_ETZPC_SAI1_ID 58 +-#define STM32MP1_ETZPC_SAI2_ID 59 +-#define STM32MP1_ETZPC_SAI3_ID 60 +-#define STM32MP1_ETZPC_DFSDM_ID 61 +-#define STM32MP1_ETZPC_TT_FDCAN_ID 62 +-#define STM32MP1_ETZPC_LPTIM2_ID 64 +-#define STM32MP1_ETZPC_LPTIM3_ID 65 +-#define STM32MP1_ETZPC_LPTIM4_ID 66 +-#define STM32MP1_ETZPC_LPTIM5_ID 67 +-#define STM32MP1_ETZPC_SAI4_ID 68 +-#define STM32MP1_ETZPC_VREFBUF_ID 69 +-#define STM32MP1_ETZPC_DCMI_ID 70 +-#define STM32MP1_ETZPC_CRC2_ID 71 +-#define STM32MP1_ETZPC_ADC_ID 72 +-#define STM32MP1_ETZPC_HASH2_ID 73 +-#define STM32MP1_ETZPC_RNG2_ID 74 +-#define STM32MP1_ETZPC_CRYP2_ID 75 +-#define STM32MP1_ETZPC_SRAM1_ID 80 +-#define STM32MP1_ETZPC_SRAM2_ID 81 +-#define STM32MP1_ETZPC_SRAM3_ID 82 +-#define STM32MP1_ETZPC_SRAM4_ID 83 +-#define STM32MP1_ETZPC_RETRAM_ID 84 +-#define STM32MP1_ETZPC_OTG_ID 85 +-#define STM32MP1_ETZPC_SDMMC3_ID 86 +-#define STM32MP1_ETZPC_DLYBSD3_ID 87 +-#define STM32MP1_ETZPC_DMA1_ID 88 +-#define STM32MP1_ETZPC_DMA2_ID 89 +-#define STM32MP1_ETZPC_DMAMUX_ID 90 +-#define STM32MP1_ETZPC_FMC_ID 91 +-#define STM32MP1_ETZPC_QSPI_ID 92 +-#define STM32MP1_ETZPC_DLYBQ_ID 93 +-#define STM32MP1_ETZPC_ETH_ID 94 +-#define STM32MP1_ETZPC_RSV_ID 95 +- +-#define STM32MP_ETZPC_MAX_ID 96 +- + /******************************************************************************* + * STM32MP1 TZC (TZ400) + ******************************************************************************/ + #define STM32MP1_TZC_BASE U(0x5C006000) + ++#if STM32MP13 ++#define STM32MP1_FILTER_BIT_ALL TZC_400_REGION_ATTR_FILTER_BIT(0) ++#endif ++#if STM32MP15 + #define STM32MP1_FILTER_BIT_ALL (TZC_400_REGION_ATTR_FILTER_BIT(0) | \ + TZC_400_REGION_ATTR_FILTER_BIT(1)) ++#endif + + /******************************************************************************* + * STM32MP1 SDMMC +@@ -335,27 +381,83 @@ 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 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) ++/* OTP labels */ ++#define CFG0_OTP "cfg0_otp" ++#define PART_NUMBER_OTP "part_number_otp" ++#if STM32MP15 ++#define PACKAGE_OTP "package_otp" ++#endif ++#define HW2_OTP "hw2_otp" ++#if STM32MP13 ++#define NAND_OTP "cfg9_otp" ++#define NAND2_OTP "cfg10_otp" ++#endif ++#if STM32MP15 ++#define NAND_OTP "nand_otp" ++#endif ++#define MONOTONIC_OTP "monotonic_otp" ++#define UID_OTP "uid_otp" ++#define PKH_OTP "pkh_otp" ++#define ENCKEY_OTP "enckey_otp" ++#define BOARD_ID_OTP "board_id" ++#define CFG2_OTP "cfg2_otp" ++#define SSP_OTP "ssp_otp" ++#define CHIP_CERTIFICATE_OTP "chip_otp" ++#define RMA_OTP "rma_otp" + + /* OTP mask */ +-/* DATA0 */ +-#define DATA0_OTP_SECURED BIT(6) ++/* CFG0 */ ++#if STM32MP13 ++#define CFG0_OTP_MODE_MASK GENMASK_32(9, 0) ++#define CFG0_OTP_MODE_SHIFT 0 ++#define CFG0_OPEN_DEVICE 0x17U ++#define CFG0_CLOSED_DEVICE 0x3FU ++#define CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN 0x17FU ++#define CFG0_CLOSED_DEVICE_NO_JTAG 0x3FFU ++#endif ++#if STM32MP15 ++#define CFG0_CLOSED_DEVICE BIT(6) ++#endif ++ ++/* CFG2 */ ++#define OTP_CFG2_SEC_COUNTER_MASK GENMASK_32(27, 20) ++#define OTP_CFG2_SEC_COUNTER_SHIFT U(20) ++#define OTP_CFG2_ST_KEY_MASK GENMASK_32(31, 28) ++#define OTP_CFG2_ST_KEY_SHIFT U(28) ++ ++/* SSP */ ++#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 GENMASK_32(BOOT_API_OTP_SSP_SUCCESS_BIT_POS, \ ++ BOOT_API_OTP_SSP_REQ_BIT_POS) ++#define SSP_OTP_SECRET_BASE U(59) ++#define SSP_OTP_SECRET_END U(95) ++ ++/* CHIP_CERT */ ++#define CHIP_CERTIFICATE_MAX_SIZE U(0x40) ++ ++/* RMA */ ++#if STM32MP13 ++#define RMA_OTP_MASK GENMASK_32(31, 0) ++#endif ++#if STM32MP15 ++#define RMA_OTP_MASK GENMASK_32(29, 0) ++#endif + + /* PART NUMBER */ ++#if STM32MP13 ++#define PART_NUMBER_OTP_PART_MASK GENMASK_32(14, 0) ++#endif ++#if STM32MP15 + #define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) ++#endif + #define PART_NUMBER_OTP_PART_SHIFT 0 + + /* PACKAGE */ ++#if STM32MP15 + #define PACKAGE_OTP_PKG_MASK GENMASK_32(29, 27) + #define PACKAGE_OTP_PKG_SHIFT 27 ++#endif + + /* IWDG OTP */ + #define HW2_OTP_IWDG_HW_POS U(3) +@@ -383,7 +485,7 @@ enum ddr_type { + #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) */ ++/* NAND number of block (in unit of 256 blocks) */ + #define NAND_BLOCK_NB_MASK GENMASK_32(26, 19) + #define NAND_BLOCK_NB_SHIFT 19 + #define NAND_BLOCK_NB_UNIT U(256) +@@ -404,17 +506,36 @@ enum ddr_type { + /* NAND number of planes */ + #define NAND_PLANE_BIT_NB_MASK BIT(14) + ++/* NAND2 OTP */ ++#define NAND2_PAGE_SIZE_SHIFT 16 ++ ++/* NAND2 config distribution */ ++#define NAND2_CONFIG_DISTRIB BIT(0) ++#define NAND2_PNAND_NAND2_SNAND_NAND1 U(0) ++#define NAND2_PNAND_NAND1_SNAND_NAND2 U(1) ++ ++/* MONOTONIC OTP */ ++#define MAX_MONOTONIC_VALUE 32 ++ + /* UID OTP */ + #define UID_WORD_NB U(3) + ++/* FWU configuration */ ++#define FWU_MAX_TRIAL_REBOOT U(3) ++ + /******************************************************************************* + * STM32MP1 TAMP + ******************************************************************************/ ++#define PLAT_MAX_TAMP_INT U(6) ++#define PLAT_MAX_TAMP_EXT U(3) + #define TAMP_BASE U(0x5C00A000) + #define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100)) ++#define TAMP_BKP_SEC_NUMBER U(10) ++#define TAMP_BKP_S_W_NS_R_NUMBER U(5) ++#define TAMP_COUNTR U(0x40) + + #if !(defined(__LINKER__) || defined(__ASSEMBLER__)) +-static inline uint32_t tamp_bkpr(uint32_t idx) ++static inline uintptr_t tamp_bkpr(uint32_t idx) + { + return TAMP_BKP_REGISTER_BASE + (idx << 2); + } +@@ -435,6 +556,14 @@ static inline uint32_t tamp_bkpr(uint32_t idx) + ******************************************************************************/ + #define DDRPHYC_BASE U(0x5A004000) + ++/******************************************************************************* ++ * STM32MP1 MCE ++ ******************************************************************************/ ++#if STM32MP13 ++#define MCE_BASE U(0x58001000) ++#define MCE_KEY_SIZE_IN_BYTES U(16) ++#endif ++ + /******************************************************************************* + * STM32MP1 IWDG + ******************************************************************************/ +@@ -449,23 +578,104 @@ static inline uint32_t tamp_bkpr(uint32_t idx) + * Miscellaneous STM32MP1 peripherals base address + ******************************************************************************/ + #define BSEC_BASE U(0x5C005000) ++#if STM32MP13 ++#define CRYP_BASE U(0x54002000) ++#endif ++#if STM32MP15 + #define CRYP1_BASE U(0x54001000) ++#endif + #define DBGMCU_BASE U(0x50081000) ++#if STM32MP13 ++#define HASH_BASE U(0x54003000) ++#endif ++#if STM32MP15 + #define HASH1_BASE U(0x54002000) ++#endif ++#if STM32MP13 ++#define I2C3_BASE U(0x4C004000) ++#define I2C4_BASE U(0x4C005000) ++#define I2C5_BASE U(0x4C006000) ++#endif ++#if STM32MP15 + #define I2C4_BASE U(0x5C002000) + #define I2C6_BASE U(0x5c009000) ++#endif ++#if STM32MP13 ++#define RNG_BASE U(0x54004000) ++#endif ++#if STM32MP15 + #define RNG1_BASE U(0x54003000) ++#endif + #define RTC_BASE U(0x5c004000) ++#if STM32MP13 ++#define SPI4_BASE U(0x4C002000) ++#define SPI5_BASE U(0x4C003000) ++#endif ++#if STM32MP15 + #define SPI6_BASE U(0x5c001000) ++#endif + #define STGEN_BASE U(0x5c008000) + #define SYSCFG_BASE U(0x50020000) + ++/******************************************************************************* ++ * STM32MP1 TIMERS ++ ******************************************************************************/ ++#define TIM12_BASE U(0x40006000) ++#define TIM15_BASE U(0x44006000) ++#define TIM_MAX_INSTANCE U(2) ++ ++/******************************************************************************* ++ * STM32MP13 SAES ++ ******************************************************************************/ ++#define SAES_BASE U(0x54005000) ++ ++/******************************************************************************* ++ * STM32MP13 PKA ++ ******************************************************************************/ ++#define PKA_BASE U(0x54006000) ++ ++/******************************************************************************* ++ * 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) ++ ++/******************************************************************************* ++ * REGULATORS ++ ******************************************************************************/ ++/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */ ++#define PLAT_NB_RDEVS U(19) ++/* 2 FIXED */ ++#define PLAT_NB_FIXED_REGS U(2) ++/* Number of low power modes defined in the device tree */ ++#define PLAT_NB_SUSPEND_MODES 7 ++ + /******************************************************************************* + * Device Tree defines + ******************************************************************************/ ++#if STM32MP13 ++#define DT_BSEC_COMPAT "st,stm32mp13-bsec" ++#define DT_DDR_COMPAT "st,stm32mp13-ddr" ++#endif ++#if STM32MP15 + #define DT_BSEC_COMPAT "st,stm32mp15-bsec" ++#define DT_DDR_COMPAT "st,stm32mp1-ddr" ++#endif + #define DT_IWDG_COMPAT "st,stm32mp1-iwdg" ++#define DT_OPP_COMPAT "operating-points-v2" + #define DT_PWR_COMPAT "st,stm32mp1,pwr-reg" ++#if STM32MP13 ++#define DT_RCC_CLK_COMPAT "st,stm32mp13-rcc" ++#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp13-rcc-secure" ++#endif ++#if STM32MP15 + #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" ++#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp1-rcc-secure" ++#endif ++#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" ++#define DT_UART_COMPAT "st,stm32h7-uart" ++#define DT_USBPHYC_COMPAT "st,stm32mp1-usbphyc" + + #endif /* STM32MP1_DEF_H */ +diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c +index caf9ff12b..aa65ed036 100644 +--- a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c ++++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c +@@ -9,7 +9,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -31,8 +31,13 @@ struct dt_id_attr { + + void stm32mp1_arch_security_setup(void) + { +- stm32mp_clk_enable(TZC1); +- stm32mp_clk_enable(TZC2); ++#if STM32MP13 ++ clk_enable(TZC); ++#endif ++#if STM32MP15 ++ clk_enable(TZC1); ++ clk_enable(TZC2); ++#endif + + tzc400_init(STM32MP1_TZC_BASE); + tzc400_disable_filters(); +diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h +index d8561dcc0..d9a9e7a39 100644 +--- a/plat/st/stm32mp1/stm32mp1_fip_def.h ++++ b/plat/st/stm32mp1/stm32mp1_fip_def.h +@@ -10,24 +10,102 @@ + #define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ + #define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ + ++#if STM32MP_SSP ++#if STM32MP13 ++#define STM32MP_BL2_DTB_BASE STM32MP_SEC_SYSRAM_BASE ++#endif ++#if STM32MP15 ++#define STM32MP_BL2_DTB_BASE (STM32MP_SYSRAM_BASE + \ ++ STM32MP_HEADER_RESERVED_SIZE) ++#endif ++ ++#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ ++ ++#define STM32MP_BL2_RO_SIZE U(0x0000E000) /* 56 Ko for BL2 */ ++ ++#define STM32MP_BL2_RO_BASE STM32MP_BL2_DTB_BASE + \ ++ STM32MP_BL2_DTB_SIZE ++ ++#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \ ++ STM32MP_BL2_RO_SIZE) ++ ++#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \ ++ STM32MP_SYSRAM_SIZE - \ ++ STM32MP_BL2_RW_BASE) ++#else /* STM32MP_SSP */ ++#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP ++#if STM32MP15 ++#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */ + #define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */ +-#define STM32MP_BL2_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ +-#define STM32MP_BL32_SIZE U(0x00019000) /* 100 KB for BL32 */ ++#endif /* STM32MP15 */ ++#else /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */ ++#if STM32MP13 ++#if BL2_IN_XIP_MEM ++#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */ ++#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */ ++#else ++/* STM32MP_BL2_RO_SIZE not used if !BL2_IN_XIP_MEM */ ++#define STM32MP_BL2_SIZE U(0x0001B000) /* 108KB for BL2 */ ++ /* with 20KB for DTB, SYSRAM is full */ ++#endif ++#endif /* STM32MP13 */ ++#if STM32MP15 ++#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */ ++#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */ ++#endif /* STM32MP15 */ ++#endif /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */ ++ ++#if STM32MP13 ++#if TRUSTED_BOARD_BOOT ++#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ ++#else /* TRUSTED_BOARD_BOOT */ ++#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */ ++#endif /* TRUSTED_BOARD_BOOT */ ++#endif /* STM32MP13 */ ++#if STM32MP15 ++#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */ ++#endif /* STM32MP15 */ ++#define STM32MP_BL32_SIZE U(0x0001C000) /* 112 KB for BL32 */ + #define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ + #define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE /* 4 KB for FCONF DTB */ + #define STM32MP_HW_CONFIG_MAX_SIZE U(0x40000) /* 256 KB for HW config DTB */ + ++#if STM32MP13 ++#define STM32MP_BL2_BASE (STM32MP_BL2_DTB_BASE + \ ++ STM32MP_BL2_DTB_SIZE) ++#endif /* STM32MP13 */ ++#if STM32MP15 + #define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE) ++#endif /* STM32MP15 */ ++ ++#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE ++ ++#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \ ++ STM32MP_BL2_RO_SIZE) ++ ++#if STM32MP13 ++#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \ ++ STM32MP_SYSRAM_SIZE - \ ++ STM32MP_BL2_RW_BASE) ++ ++#define STM32MP_BL2_DTB_BASE STM32MP_SEC_SYSRAM_BASE ++#endif /* STM32MP13 */ ++#if STM32MP15 ++#define STM32MP_BL2_RW_SIZE (STM32MP_SEC_SYSRAM_BASE + \ ++ STM32MP_SEC_SYSRAM_SIZE - \ ++ STM32MP_BL2_RW_BASE) + + #define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \ + STM32MP_BL2_DTB_SIZE) ++#endif /* STM32MP15 */ + + #define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE + + #define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \ + STM32MP_BL32_DTB_SIZE) ++#endif /* STM32MP_SSP */ + + + #if defined(IMAGE_BL2) +@@ -46,9 +124,14 @@ + STM32MP_OPTEE_BASE) + #endif + ++#if STM32MP13 ++#define STM32MP_FW_CONFIG_BASE SRAM3_BASE ++#endif /* STM32MP13 */ ++#if STM32MP15 + #define STM32MP_FW_CONFIG_BASE (STM32MP_SYSRAM_BASE + \ + STM32MP_SYSRAM_SIZE - \ + PAGE_SIZE) ++#endif /* STM32MP15 */ + #define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \ + STM32MP_BL33_MAX_SIZE) + +@@ -63,7 +146,26 @@ + /******************************************************************************* + * STM32MP1 RAW partition offset for MTD devices + ******************************************************************************/ ++#if PSA_FWU_SUPPORT ++#define STM32MP_NOR_METADATA1_OFFSET U(0x00080000) ++#define STM32MP_NOR_METADATA2_OFFSET U(0x000C0000) ++#define STM32MP_NOR_FIP_A_OFFSET U(0x00100000) ++#define STM32MP_NOR_FIP_A_GUID (const struct efi_guid)EFI_GUID(0x4fd84c93, \ ++ 0x54ef, 0x463f, 0xa7, 0xef, 0xae, 0x25, 0xff,\ ++ 0x88, 0x70, 0x87) ++ ++#define STM32MP_NOR_FIP_B_OFFSET U(0x00500000) ++#define STM32MP_NOR_FIP_B_GUID (const struct efi_guid)EFI_GUID(0x09c54952, \ ++ 0xd5bf, 0x45af, 0xac, 0xee, 0x33, 0x53, 0x03,\ ++ 0x76, 0x6f, 0xb3) ++ ++#else /* PSA_FWU_SUPPORT */ ++#ifndef STM32MP_NOR_FIP_OFFSET + #define STM32MP_NOR_FIP_OFFSET U(0x00080000) ++#endif ++#ifndef STM32MP_NAND_FIP_OFFSET + #define STM32MP_NAND_FIP_OFFSET U(0x00200000) ++#endif ++#endif /* PSA_FWU_SUPPORT */ + + #endif /* STM32MP1_FIP_DEF_H */ +diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c +deleted file mode 100644 +index 851a9cf0c..000000000 +--- a/plat/st/stm32mp1/stm32mp1_gic.c ++++ /dev/null +@@ -1,92 +0,0 @@ +-/* +- * 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 +- +-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 stm32mp1_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 = 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; +- +-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(); +- +- stm32mp1_gic_pcpu_init(); +-} +- +-void stm32mp1_gic_pcpu_init(void) +-{ +- gicv2_pcpu_distif_init(); +- gicv2_set_pe_target_mask(plat_my_core_pos()); +- gicv2_cpuif_enable(); +-} +diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S +index cac9752e2..2f117dbff 100644 +--- a/plat/st/stm32mp1/stm32mp1_helper.S ++++ b/plat/st/stm32mp1/stm32mp1_helper.S +@@ -10,11 +10,17 @@ + #include + #include + #include ++#include + + #define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) + + .globl platform_mem_init + .globl plat_report_exception ++#if AARCH32_EXCEPTION_DEBUG ++ .globl plat_report_undef_inst ++ .globl plat_report_prefetch_abort ++ .globl plat_report_data_abort ++#endif + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_reset_handler +@@ -24,6 +30,7 @@ + .globl plat_crash_console_flush + .globl plat_crash_console_putc + .globl plat_panic_handler ++ .globl wfi_svc_int_enable + + func platform_mem_init + /* Nothing to do, don't need to init SYSRAM */ +@@ -75,6 +82,96 @@ print_exception_info: + #endif + endfunc plat_report_exception + ++#if AARCH32_EXCEPTION_DEBUG ++func plat_report_undef_inst ++#if DEBUG ++ mov r8, lr ++ ++ mov r9, r0 ++ ++ ldr r4, =undefined_str ++ bl asm_print_str ++ ++ mov r4, r9 ++ sub r4, r4, #4 ++ bl asm_print_hex ++ ++ ldr r4, =end_error_str ++ bl asm_print_str ++ ++ bx r8 ++#else ++ bx lr ++#endif ++endfunc plat_report_undef_inst ++ ++func plat_report_prefetch_abort ++#if DEBUG ++ mov r8, lr ++ mov r9, r0 ++ ++ ldr r4, =prefetch_abort_str ++ bl asm_print_str ++ ++ mov r4, r9 ++ sub r4, r4, #4 ++ bl asm_print_hex ++ ++ ldr r4, =ifsr_str ++ bl asm_print_str ++ ++ ldcopr r4, IFSR ++ bl asm_print_hex ++ ++ ldr r4, =ifar_str ++ bl asm_print_str ++ ++ ldcopr r4, IFAR ++ bl asm_print_hex ++ ++ ldr r4, =end_error_str ++ bl asm_print_str ++ ++ bx r8 ++#else ++ bx lr ++#endif ++endfunc plat_report_prefetch_abort ++ ++func plat_report_data_abort ++#if DEBUG ++ mov r8, lr ++ mov r9, r0 ++ ++ ldr r4, =data_abort_str ++ bl asm_print_str ++ ++ mov r4, r9 ++ sub r4, r4, #8 ++ bl asm_print_hex ++ ++ ldr r4, =dfsr_str ++ bl asm_print_str ++ ++ ldcopr r4, DFSR ++ bl asm_print_hex ++ ++ ldr r4, =dfar_str ++ bl asm_print_str ++ ++ ldcopr r4, DFAR ++ bl asm_print_hex ++ ++ ldr r4, =end_error_str ++ bl asm_print_str ++ ++ bx r8 ++#else ++ bx lr ++#endif ++endfunc plat_report_data_abort ++#endif ++ + func plat_reset_handler + bx lr + endfunc plat_reset_handler +@@ -258,12 +355,48 @@ endfunc plat_panic_handler + .section .rodata.rev_err_str, "aS" + abort_str: + .asciz "\nAbort at: 0x" ++#if AARCH32_EXCEPTION_DEBUG ++prefetch_abort_str: ++ .asciz "\nPrefetch Abort at: 0x" ++data_abort_str: ++ .asciz "\nData Abort at: 0x" ++#endif + undefined_str: + .asciz "\nUndefined instruction at: 0x" + exception_start_str: + .asciz "\nException mode=0x" + exception_end_str: + .asciz " at: 0x" ++#if AARCH32_EXCEPTION_DEBUG ++dfsr_str: ++ .asciz " DFSR = 0x" ++dfar_str: ++ .asciz " DFAR = 0x" ++ifsr_str: ++ .asciz " IFSR = 0x" ++ifar_str: ++ .asciz " IFAR = 0x" ++#endif + end_error_str: + .asciz "\n\r" + #endif ++ ++func wfi_svc_int_enable ++ push {r4,r8,lr} ++ ldcopr r4, SCR ++ mov r8, sp ++ mov sp, r0 ++ add r0, r0, #STM32MP_INT_STACK_SIZE ++ str r0, [sp, #SMC_CTX_SP_MON] ++ str r4, [sp, #SMC_CTX_SCR] ++ cps #MODE32_svc ++ cpsie af ++ dsb ++ isb ++ wfi ++ cpsid af ++ cps #MODE32_mon ++ mov sp, r8 ++ pop {r4,r8,lr} ++ bx lr ++endfunc wfi_svc_int_enable +diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c +new file mode 100644 +index 000000000..a4b473515 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_low_power.c +@@ -0,0 +1,441 @@ ++/* ++ * Copyright (c) 2017-2021, 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 ++ ++static unsigned int gicc_pmr; ++static struct stm32_rtc_calendar sleep_time; ++static bool enter_cstop_done; ++static unsigned long long stgen_cnt; ++ ++struct pwr_lp_config { ++ uint32_t pwr_cr1; ++ uint32_t pwr_mpucr; ++ const char *regul_suspend_node_name; ++}; ++ ++#define PWRLP_TEMPO_5_HSI 5 ++ ++#define PWR_CR1_MASK (PWR_CR1_LPDS | PWR_CR1_LPCFG | PWR_CR1_LVDS) ++#define PWR_MPUCR_MASK (PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | PWR_MPUCR_PDDS) ++ ++static const struct pwr_lp_config config_pwr[STM32_PM_MAX_SOC_MODE] = { ++ [STM32_PM_CSLEEP_RUN] = { ++ .pwr_cr1 = 0U, ++ .pwr_mpucr = PWR_MPUCR_CSSF, ++ .regul_suspend_node_name = NULL, ++ }, ++ [STM32_PM_CSTOP_ALLOW_STOP] = { ++ .pwr_cr1 = 0U, ++ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF, ++ .regul_suspend_node_name = NULL, ++ }, ++ [STM32_PM_CSTOP_ALLOW_LP_STOP] = { ++ .pwr_cr1 = PWR_CR1_LPDS, ++ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF, ++ .regul_suspend_node_name = "lp-stop", ++ }, ++ [STM32_PM_CSTOP_ALLOW_LPLV_STOP] = { ++ .pwr_cr1 = PWR_CR1_LVDS | PWR_CR1_LPDS | PWR_CR1_LPCFG, ++ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF, ++ .regul_suspend_node_name = "lplv-stop", ++ }, ++ [STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR] = { ++ .pwr_cr1 = 0U, ++ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | ++ PWR_MPUCR_PDDS, ++ .regul_suspend_node_name = "standby-ddr-sr", ++ }, ++ [STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF] = { ++ .pwr_cr1 = 0U, ++ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | ++ PWR_MPUCR_PDDS, ++ .regul_suspend_node_name = "standby-ddr-off", ++ }, ++ [STM32_PM_SHUTDOWN] = { ++ .pwr_cr1 = 0U, ++ .pwr_mpucr = 0U, ++ .regul_suspend_node_name = "standby-ddr-off", ++ }, ++}; ++ ++#define GICC_PMR_PRIORITY_8 U(0x8) ++ ++enum { ++ STATE_NONE = 0, ++ STATE_AUTOSTOP_ENTRY, ++ STATE_AUTOSTOP_EXIT, ++}; ++ ++static struct spinlock lp_lock; ++static volatile int cpu0_state = STATE_NONE; ++static volatile int cpu1_state = STATE_NONE; ++ ++const char *plat_get_lp_mode_name(int mode) ++{ ++ return config_pwr[mode].regul_suspend_node_name; ++} ++ ++void stm32_apply_pmic_suspend_config(uint32_t mode) ++{ ++ const char *node_name; ++ ++ assert(mode < ARRAY_SIZE(config_pwr)); ++ ++ node_name = config_pwr[mode].regul_suspend_node_name; ++ ++ if (node_name != NULL) { ++ if (!initialize_pmic_i2c()) { ++ panic(); ++ } ++ } ++} ++ ++/* ++ * stm32_enter_cstop - Prepare CSTOP mode ++ * ++ * @mode - Target low power mode ++ * @nsec_addr - Non secure resume entry point ++ * Return 0 if succeed to suspend, non 0 else. ++ */ ++static void enter_cstop(uint32_t mode, uint32_t nsec_addr) ++{ ++ uint32_t zq0cr0_zdata; ++ uintptr_t bkpr_core1_addr = ++ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); ++ uintptr_t bkpr_core1_magic = ++ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); ++ uint32_t pwr_cr1 = config_pwr[mode].pwr_cr1; ++ uintptr_t pwr_base = stm32mp_pwr_base(); ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++#ifdef STM32MP15 ++ if (mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP2) { ++ ERROR("LPLV-Stop2 mode not supported\n"); ++ panic(); ++ } ++#endif ++ ++ stm32mp1_syscfg_disable_io_compensation(); ++ ++ stm32_clean_context(); ++ ++ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { ++ /* ++ * The first 64 bytes of DDR need to be saved for DDR DQS ++ * training ++ */ ++ stm32_save_ddr_training_area(); ++ } ++ ++ if (dt_pmic_status() > 0) { ++ stm32_apply_pmic_suspend_config(mode); ++ ++ if (mode == STM32_PM_CSTOP_ALLOW_LP_STOP) { ++ pwr_cr1 |= PWR_CR1_LPCFG; ++ } ++ } ++ ++ regulator_core_suspend(mode); ++ ++ /* Clear RCC interrupt before enabling it */ ++ mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF); ++ ++ /* Enable RCC Wake-up */ ++ mmio_setbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); ++ ++ /* Configure low power mode */ ++ mmio_clrsetbits_32(pwr_base + PWR_MPUCR, PWR_MPUCR_MASK, ++ config_pwr[mode].pwr_mpucr); ++ mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK, ++ pwr_cr1); ++ ++ /* Clear RCC pending interrupt flags */ ++ mmio_write_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_MASK); ++ ++ /* Request CSTOP mode to RCC */ ++ mmio_setbits_32(rcc_base + RCC_MP_SREQSETR, ++ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); ++ ++ stm32_iwdg_refresh(); ++ ++ gicc_pmr = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8); ++ ++ zq0cr0_zdata = ddr_get_io_calibration_val(); ++ ++ clk_enable(RTCAPB); ++ ++ mmio_write_32(bkpr_core1_addr, 0); ++ mmio_write_32(bkpr_core1_magic, 0); ++ ++ stm32mp1_clock_stopmode_save(); ++ ++ stm32_rtc_get_calendar(&sleep_time); ++ stgen_cnt = stm32mp_stgen_get_counter(); ++ ++ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { ++ /* ++ * Save non-secure world entrypoint after standby in Backup ++ * register ++ */ ++ mmio_write_32(bkpr_core1_addr, nsec_addr); ++ mmio_write_32(bkpr_core1_magic, ++ BOOT_API_A7_CORE0_MAGIC_NUMBER); ++ ++ if (stm32_save_context(zq0cr0_zdata, &sleep_time, ++ stgen_cnt) != 0) { ++ panic(); ++ } ++ ++ /* set POPL to 20ms */ ++ mmio_clrsetbits_32(pwr_base + PWR_CR3, PWR_CR3_POPL_MASK, ++ 20U << PWR_CR3_POPL_SHIFT); ++ ++ if (stm32mp1_get_retram_enabled()) { ++ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_RREN); ++ while ((mmio_read_32(pwr_base + PWR_CR2) & ++ PWR_CR2_RRRDY) == 0U) { ++ ; ++ } ++ } ++ ++ /* Keep backup RAM content in standby */ ++ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN); ++ while ((mmio_read_32(pwr_base + PWR_CR2) & ++ PWR_CR2_BRRDY) == 0U) { ++ ; ++ } ++ } ++ ++ clk_disable(RTCAPB); ++ ++ enter_cstop_done = true; ++} ++ ++bool stm32_is_cstop_done(void) ++{ ++ return enter_cstop_done; ++} ++ ++/* ++ * stm32_exit_cstop - Exit from CSTOP mode ++ */ ++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; ++ } ++ ++ enter_cstop_done = false; ++ ++ stm32mp1_syscfg_enable_io_compensation_start(); ++ ++ plat_ic_set_priority_mask(gicc_pmr); ++ ++ /* Disable RCC Wake-up */ ++ mmio_clrbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); ++ ++ /* Disable STOP request */ ++ mmio_setbits_32(rcc_base + RCC_MP_SREQCLRR, ++ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); ++ ++ 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(stgen_cnt, stdby_time_in_ms); ++ ++ if (stm32mp1_clock_stopmode_resume() != 0) { ++ panic(); ++ } ++ ++ regulator_core_resume(); ++ ++ stm32mp1_syscfg_enable_io_compensation_finish(); ++} ++ ++static int get_locked(volatile int *state) ++{ ++ volatile int val; ++ ++ spin_lock(&lp_lock); ++ val = *state; ++ spin_unlock(&lp_lock); ++ ++ return val; ++} ++ ++static void set_locked(volatile int *state, int val) ++{ ++ spin_lock(&lp_lock); ++ *state = val; ++ spin_unlock(&lp_lock); ++} ++ ++static void smp_synchro(int state, bool wake_up) ++{ ++ /* if the other CPU is stopped, no need to synchronize */ ++ if (psci_is_last_on_cpu() == 1U) { ++ return; ++ } ++ ++ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) { ++ set_locked(&cpu0_state, state); ++ ++ while (get_locked(&cpu1_state) != state) { ++ if (wake_up) { ++ /* wakeup secondary CPU */ ++ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_6, ++ STM32MP_SECONDARY_CPU); ++ udelay(10); ++ } ++ }; ++ } else { ++ while (get_locked(&cpu0_state) != state) { ++ if (wake_up) { ++ /* wakeup primary CPU */ ++ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_6, ++ STM32MP_PRIMARY_CPU); ++ udelay(10); ++ } ++ }; ++ ++ set_locked(&cpu1_state, state); ++ } ++} ++ ++static void stm32_auto_stop_cpu0(void) ++{ ++ smp_synchro(STATE_AUTOSTOP_ENTRY, false); ++ ++ enter_cstop(STM32_PM_CSTOP_ALLOW_LP_STOP, 0); ++ ++ stm32_pwr_down_wfi(true, STM32_PM_CSTOP_ALLOW_LP_STOP); ++ ++ stm32_exit_cstop(); ++ ++ smp_synchro(STATE_AUTOSTOP_EXIT, true); ++} ++ ++static void stm32_auto_stop_cpu1(void) ++{ ++ unsigned int gicc_pmr_cpu1; ++ ++ /* clear cache before the DDR is being disabled by cpu0 */ ++ dcsw_op_all(DC_OP_CISW); ++ ++ smp_synchro(STATE_AUTOSTOP_ENTRY, false); ++ ++ gicc_pmr_cpu1 = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8); ++ wfi(); ++ plat_ic_set_priority_mask(gicc_pmr_cpu1); ++ ++ smp_synchro(STATE_AUTOSTOP_EXIT, true); ++} ++ ++void stm32_auto_stop(void) ++{ ++ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) { ++ stm32_auto_stop_cpu0(); ++ } else { ++ stm32_auto_stop_cpu1(); ++ } ++} ++ ++static void enter_csleep(void) ++{ ++ uintptr_t pwr_base = stm32mp_pwr_base(); ++ ++ mmio_clrsetbits_32(pwr_base + PWR_MPUCR, PWR_MPUCR_MASK, ++ config_pwr[STM32_PM_CSLEEP_RUN].pwr_mpucr); ++ mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK, ++ config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1); ++ ++ stm32_pwr_down_wfi(false, STM32_PM_CSLEEP_RUN); ++} ++ ++void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr) ++{ ++ switch (mode) { ++ case STM32_PM_SHUTDOWN: ++ break; ++ ++ case STM32_PM_CSLEEP_RUN: ++ enter_csleep(); ++ break; ++ ++ default: ++ enter_cstop(mode, nsec_addr); ++ break; ++ } ++} ++ ++void stm32_init_low_power(void) ++{ ++ uintptr_t pwr_base = stm32mp_pwr_base(); ++ uintptr_t rcc_base = stm32mp_rcc_base(); ++ ++ /* ++ * Configure Standby mode available for MCU by default ++ * and allow to switch in standby SoC in all case ++ */ ++ mmio_setbits_32(pwr_base + PWR_MCUCR, PWR_MCUCR_PDDS); ++ ++ /* Disable STOP request */ ++ mmio_setbits_32(rcc_base + RCC_MP_SREQCLRR, ++ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); ++ ++ /* Disable retention and backup RAM content after standby */ ++ mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN); ++ ++ /* 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); ++} +diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c +index 31a9ae7f1..1346c11b5 100644 +--- a/plat/st/stm32mp1/stm32mp1_pm.c ++++ b/plat/st/stm32mp1/stm32mp1_pm.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -14,14 +14,21 @@ + #include + #include + #include +-#include ++#include ++#include ++#include ++#include + #include + #include + #include + #include + ++#include ++#include ++ + static uintptr_t stm32_sec_entrypoint; + static uint32_t cntfrq_core0; ++static uintptr_t saved_entrypoint; + + /******************************************************************************* + * STM32MP1 handler called when a CPU is about to enter standby. +@@ -34,11 +41,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(); + +@@ -60,21 +68,34 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) + static int stm32_pwr_domain_on(u_register_t mpidr) + { + unsigned long current_cpu_mpidr = read_mpidr_el1(); +- uint32_t bkpr_core1_addr = ++ uintptr_t bkpr_core1_addr = + tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); +- uint32_t bkpr_core1_magic = ++ uintptr_t bkpr_core1_magic = + tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); + ++ if (stm32mp_is_single_core()) { ++ return PSCI_E_INTERN_FAIL; ++ } ++ + if (mpidr == current_cpu_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); ++ ++ /* Wait for this IT to be acknowledged by ROM code. */ ++ udelay(10); ++ + /* Only one valid entry point */ + if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) { + return PSCI_E_INVALID_ADDRESS; + } + +- stm32mp_clk_enable(RTCAPB); ++ clk_enable(RTCAPB); + + cntfrq_core0 = read_cntfrq_el0(); + +@@ -84,7 +105,7 @@ 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); + +- stm32mp_clk_disable(RTCAPB); ++ clk_disable(RTCAPB); + + /* Generate an IT to core 1 */ + gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); +@@ -107,7 +128,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) + { +- /* Nothing to do, power domain is not disabled */ ++ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND); ++ ++ stm32_enter_low_power(soc_mode, saved_entrypoint); + } + + /******************************************************************************* +@@ -118,7 +141,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(); ++ stm32mp_gic_pcpu_init(); + + write_cntfrq_el0(cntfrq_core0); + } +@@ -134,28 +157,66 @@ static void stm32_pwr_domain_suspend_finish(const psci_power_state_t + /* Nothing to do, power domain is not disabled */ + } + ++/******************************************************************************* ++ * STM32MP1 handler called when a core tries to power itself down. If this ++ * call is made by core 0, it is a return from stop mode. In this case, we ++ * should restore previous context and jump to secure entrypoint. ++ ******************************************************************************/ + static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) + { +- ERROR("stm32mpu1 Power Down WFI: operation not handled.\n"); ++ if (MPIDR_AFFLVL0_VAL(read_mpidr_el1()) == STM32MP_PRIMARY_CPU) { ++ void (*warm_entrypoint)(void) = ++ (void (*)(void))stm32_sec_entrypoint; ++ ++ stm32_pwr_down_wfi(stm32_is_cstop_done(), ++ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND)); ++ ++ stm32_exit_cstop(); ++ ++ disable_mmu_icache_secure(); ++ ++ warm_entrypoint(); ++ } ++ ++ mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, ++ RCC_MP_GRSTCSETR_MPUP1RST); ++ ++ /* ++ * Synchronize on memory accesses and instruction flow before ++ * auto-reset from the WFI instruction. ++ */ ++ dsb(); ++ isb(); ++ wfi(); ++ ++ /* This shouldn't be reached */ + panic(); + } + + static void __dead2 stm32_system_off(void) + { +- 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()) { ++ /* Prepare Core 1 reset */ ++ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, ++ RCC_MP_GRSTCSETR_MPUP1RST); ++ /* Send IT to core 1 to put itself in WFI */ ++ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, STM32MP_SECONDARY_CPU); ++ } ++ ++ stm32_enter_low_power(soc_mode, 0); ++ ++ stm32_pwr_down_wfi(true, soc_mode); ++ ++ /* This shouldn't be reached */ + panic(); + } + + static void __dead2 stm32_system_reset(void) + { +- mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, +- RCC_MP_GRSTCSETR_MPSYSRST); +- +- /* Loop in case system reset is not immediately caught */ +- for ( ; ; ) { +- ; +- } ++ stm32mp_system_reset(); + } + + static int stm32_validate_power_state(unsigned int power_state, +@@ -188,6 +249,8 @@ static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) + return PSCI_E_INVALID_ADDRESS; + } + ++ saved_entrypoint = entrypoint; ++ + return PSCI_E_SUCCESS; + } + +@@ -211,6 +274,12 @@ static int stm32_node_hw_state(u_register_t target_cpu, + return (int)HW_ON; + } + ++static void stm32_get_sys_suspend_power_state(psci_power_state_t *req_state) ++{ ++ req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_OFF; ++ req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_OFF; ++} ++ + /******************************************************************************* + * Export the platform handlers. The ARM Standard platform layer will take care + * of registering the handlers with PSCI. +@@ -227,7 +296,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, +- .get_node_hw_state = stm32_node_hw_state ++ .get_node_hw_state = stm32_node_hw_state, ++ .get_sys_suspend_power_state = stm32_get_sys_suspend_power_state, + }; + + /******************************************************************************* +diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c +new file mode 100644 +index 000000000..6f1e6467b +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_power_config.c +@@ -0,0 +1,229 @@ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes" ++#define SYSTEM_OFF_MODE "system_off_soc_mode" ++#define RETRAM_ENABLED "st,retram-enabled-in-standby-ddr-sr" ++ ++static uint32_t deepest_system_suspend_mode; ++static uint32_t system_off_mode; ++static bool retram_enabled; ++static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE]; ++ ++static int dt_get_pwr_node(void *fdt) ++{ ++ return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); ++} ++ ++static void save_supported_mode(void *fdt, int pwr_node) ++{ ++ int len; ++ uint32_t count; ++ unsigned int i; ++ uint32_t supported[ARRAY_SIZE(stm32mp1_supported_soc_modes)]; ++ const void *prop; ++ ++ prop = fdt_getprop(fdt, pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES, &len); ++ if (prop == NULL) { ++ panic(); ++ } ++ ++ count = (uint32_t)len / sizeof(uint32_t); ++ if (count > STM32_PM_MAX_SOC_MODE) { ++ panic(); ++ } ++ ++ if (fdt_read_uint32_array(fdt, pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES, ++ count, &supported[0]) < 0) { ++ ERROR("PWR DT\n"); ++ panic(); ++ } ++ ++ for (i = 0; i < count; i++) { ++ if (supported[i] >= STM32_PM_MAX_SOC_MODE) { ++ ERROR("Invalid mode\n"); ++ panic(); ++ } ++ stm32mp1_supported_soc_modes[supported[i]] = 1U; ++ } ++ ++ /* Initialize to deepest possible mode */ ++ for (i = STM32_PM_MAX_SOC_MODE - 1U; i != STM32_PM_CSLEEP_RUN; i--) { ++ if (stm32mp1_supported_soc_modes[i] == 1U) { ++ deepest_system_suspend_mode = i; ++ break; ++ } ++ } ++} ++ ++static int dt_fill_lp_state(uint32_t *lp_state_config, const char *lp_state) ++{ ++ int pwr_node; ++ void *fdt; ++ const fdt32_t *cuint; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ pwr_node = dt_get_pwr_node(fdt); ++ if (pwr_node < 0) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ cuint = fdt_getprop(fdt, pwr_node, lp_state, NULL); ++ if (cuint == NULL) { ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ *lp_state_config = fdt32_to_cpu(*cuint); ++ ++ save_supported_mode(fdt, pwr_node); ++ ++ return 0; ++} ++ ++static int dt_fill_retram_enabled(void) ++{ ++ int pwr_node; ++ void *fdt; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return -ENOENT; ++ } ++ ++ pwr_node = dt_get_pwr_node(fdt); ++ if (pwr_node < 0) { ++ return -ENOENT; ++ } ++ ++ if (fdt_getprop(fdt, pwr_node, RETRAM_ENABLED, NULL) == NULL) { ++ retram_enabled = false; ++ } else { ++ retram_enabled = true; ++ } ++ ++ return 0; ++} ++ ++void stm32mp1_init_lp_states(void) ++{ ++ if (dt_fill_lp_state(&system_off_mode, SYSTEM_OFF_MODE) < 0) { ++ ERROR("Node %s not found\n", SYSTEM_OFF_MODE); ++ panic(); ++ } ++ ++ if (dt_fill_retram_enabled() < 0) { ++ ERROR("could not configure retram state\n"); ++ panic(); ++ } ++} ++ ++/* Init with all domains ON */ ++static bool pm_dom[STM32MP1_PD_MAX_PM_DOMAIN] = { ++ [STM32MP1_PD_VSW] = false, ++ [STM32MP1_PD_CORE_RET] = false, ++ [STM32MP1_PD_CORE] = false ++}; ++ ++static bool stm32mp1_get_pm_domain_state(uint8_t mode) ++{ ++ bool res = true; ++ enum stm32mp1_pm_domain id = STM32MP1_PD_MAX_PM_DOMAIN; ++ ++ while (res && (id > mode)) { ++ id--; ++ res &= pm_dom[id]; ++ } ++ ++ return res; ++} ++ ++int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status) ++{ ++ if (domain >= STM32MP1_PD_MAX_PM_DOMAIN) { ++ return -EINVAL; ++ } ++ ++ pm_dom[domain] = status; ++ ++ return 0; ++} ++ ++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; ++ } ++ ++#ifdef STM32MP15 ++ if (soc_mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP2) { ++ return false; ++ } ++#endif ++ ++ 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; ++} ++ ++uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode) ++{ ++ uint32_t mode; ++ ++ if (psci_mode == PSCI_MODE_SYSTEM_OFF) { ++ return system_off_mode; ++ } ++ ++ mode = deepest_system_suspend_mode; ++ ++ while ((mode > STM32_PM_CSLEEP_RUN) && !is_allowed_mode(mode)) { ++ mode--; ++ } ++ ++ return mode; ++} ++ ++int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode) ++{ ++ if (soc_mode >= STM32_PM_MAX_SOC_MODE) { ++ return -EINVAL; ++ } ++ ++ if (psci_mode == PSCI_MODE_SYSTEM_SUSPEND) { ++ deepest_system_suspend_mode = soc_mode; ++ } ++ ++ if (psci_mode == PSCI_MODE_SYSTEM_OFF) { ++ system_off_mode = soc_mode; ++ } ++ ++ return 0; ++} ++ ++bool stm32mp1_get_retram_enabled(void) ++{ ++ return retram_enabled; ++} +diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c +index e4065c1c9..cff66ec20 100644 +--- a/plat/st/stm32mp1/stm32mp1_private.c ++++ b/plat/st/stm32mp1/stm32mp1_private.c +@@ -1,18 +1,25 @@ + /* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2015-2022, 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 +- + /* 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 +@@ -34,6 +41,26 @@ + BOARD_ID_VARFG_SHIFT) + #define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK) + ++#if STM32MP13 ++#define TAMP_BOOT_ITF_BACKUP_REG_ID U(30) ++#endif ++#if STM32MP15 ++#define TAMP_BOOT_ITF_BACKUP_REG_ID U(20) ++#endif ++#define TAMP_BOOT_ITF_MASK U(0x0000FF00) ++#define TAMP_BOOT_ITF_SHIFT 8 ++ ++/* ++ * Backup register to store fwu update information. ++ * It should be writeable only by secure world, but also readable by non secure ++ * (so it should be in Zone 2). ++ */ ++#define TAMP_BOOT_FWU_INFO_REG_ID U(10) ++#define TAMP_BOOT_FWU_INFO_IDX_MSK U(0xF) ++#define TAMP_BOOT_FWU_INFO_IDX_OFF U(0) ++#define TAMP_BOOT_FWU_INFO_CNT_MSK U(0xF0) ++#define TAMP_BOOT_FWU_INFO_CNT_OFF U(4) ++ + #if defined(IMAGE_BL2) + #define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ + STM32MP_SYSRAM_SIZE, \ +@@ -58,6 +85,15 @@ + MT_EXECUTE_NEVER) + #endif + ++#if STM32MP13 ++#define MAP_SRAM_ALL MAP_REGION_FLAT(SRAMS_BASE, \ ++ SRAMS_SIZE_2MB_ALIGNED, \ ++ MT_MEMORY | \ ++ MT_RW | \ ++ MT_SECURE | \ ++ MT_EXECUTE_NEVER) ++#endif ++ + #define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ + STM32MP1_DEVICE1_SIZE, \ + MT_DEVICE | \ +@@ -75,8 +111,13 @@ + #if defined(IMAGE_BL2) + static const mmap_region_t stm32mp1_mmap[] = { + MAP_SEC_SYSRAM, ++#if STM32MP13 ++ MAP_SRAM_ALL, ++#endif + MAP_DEVICE1, ++#if STM32MP_RAW_NAND + MAP_DEVICE2, ++#endif + {0} + }; + #endif +@@ -98,35 +139,100 @@ void configure_mmu(void) + enable_mmu_svc_mon(0); + } + ++#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(); ++ } ++} ++ + uintptr_t stm32_get_gpio_bank_base(unsigned int bank) + { ++#if STM32MP13 ++ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I); ++#endif ++#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return GPIOZ_BASE; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); ++#endif + + return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); + } + + uint32_t stm32_get_gpio_bank_offset(unsigned int bank) + { ++#if STM32MP13 ++ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I); ++#endif ++#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return 0; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); ++#endif + + return bank * GPIO_BANK_OFFSET; + } + ++bool stm32_gpio_is_secure_at_reset(unsigned int bank) ++{ ++#if STM32MP13 ++ return true; ++#endif ++#if STM32MP15 ++ if (bank == GPIO_BANK_Z) { ++ return true; ++ } ++ ++ return false; ++#endif ++} ++ + unsigned long stm32_get_gpio_bank_clock(unsigned int bank) + { ++#if STM32MP13 ++ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I); ++#endif ++#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return GPIOZ; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); ++#endif + + return GPIOA + (bank - GPIO_BANK_A); + } +@@ -143,18 +249,99 @@ int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank) + case GPIO_BANK_G: + case GPIO_BANK_H: + case GPIO_BANK_I: ++#if STM32MP15 + case GPIO_BANK_J: + case GPIO_BANK_K: ++#endif + return fdt_path_offset(fdt, "/soc/pin-controller"); ++#if STM32MP15 + case GPIO_BANK_Z: + return fdt_path_offset(fdt, "/soc/pin-controller-z"); ++#endif + default: + panic(); + } + } + ++#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2) ++/* ++ * UART Management ++ */ ++static const uintptr_t stm32mp1_uart_addresses[8] = { ++ USART1_BASE, ++ USART2_BASE, ++ USART3_BASE, ++ UART4_BASE, ++ UART5_BASE, ++ USART6_BASE, ++ UART7_BASE, ++ UART8_BASE, ++}; ++ ++uintptr_t get_uart_address(uint32_t instance_nb) ++{ ++ if ((instance_nb == 0U) || ++ (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) { ++ return 0U; ++ } ++ ++ return stm32mp1_uart_addresses[instance_nb - 1U]; ++} ++#endif ++ ++#if STM32MP_USB_PROGRAMMER ++struct gpio_bank_pin_list { ++ uint32_t bank; ++ uint32_t pin; ++}; ++ ++static const struct gpio_bank_pin_list gpio_list[] = { ++ { /* USART2_RX: GPIOA3 */ ++ .bank = 0, ++ .pin = 3, ++ }, ++ { /* USART3_RX: GPIOB12 */ ++ .bank = 1, ++ .pin = 12, ++ }, ++ { /* UART4_RX: GPIOB2 */ ++ .bank = 1, ++ .pin = 2, ++ }, ++ { /* UART5_RX: GPIOB4 */ ++ .bank = 1, ++ .pin = 5, ++ }, ++ { /* USART6_RX: GPIOC7 */ ++ .bank = 2, ++ .pin = 7, ++ }, ++ { /* UART7_RX: GPIOF6 */ ++ .bank = 5, ++ .pin = 6, ++ }, ++ { /* UART8_RX: GPIOE0 */ ++ .bank = 4, ++ .pin = 0, ++ }, ++}; ++ ++void stm32mp1_deconfigure_uart_pins(void) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { ++ set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin); ++ } ++} ++#endif ++ + uint32_t stm32mp_get_chip_version(void) + { ++#if STM32MP13 ++ return stm32mp1_syscfg_get_chip_version(); ++#endif ++#if STM32MP15 + uint32_t version = 0U; + + if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) { +@@ -163,10 +350,15 @@ uint32_t stm32mp_get_chip_version(void) + } + + return version; ++#endif + } + + uint32_t stm32mp_get_chip_dev_id(void) + { ++#if STM32MP13 ++ return stm32mp1_syscfg_get_chip_dev_id(); ++#endif ++#if STM32MP15 + uint32_t dev_id; + + if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) { +@@ -175,6 +367,7 @@ uint32_t stm32mp_get_chip_dev_id(void) + } + + return dev_id; ++#endif + } + + static uint32_t get_part_number(void) +@@ -185,7 +378,7 @@ static uint32_t get_part_number(void) + return part_number; + } + +- if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) { ++ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) { + panic(); + } + +@@ -197,11 +390,12 @@ static uint32_t get_part_number(void) + return part_number; + } + ++#if STM32MP15 + static uint32_t get_cpu_package(void) + { + uint32_t package; + +- if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) { ++ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) { + panic(); + } + +@@ -210,6 +404,43 @@ static uint32_t get_cpu_package(void) + + 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()) { ++#if STM32MP13 ++ case STM32MP135F_PART_NB: ++ case STM32MP135D_PART_NB: ++ case STM32MP133F_PART_NB: ++ case STM32MP133D_PART_NB: ++ case STM32MP131F_PART_NB: ++ case STM32MP131D_PART_NB: ++#endif ++#if STM32MP15 ++ case STM32MP157F_PART_NB: ++ case STM32MP157D_PART_NB: ++ case STM32MP153F_PART_NB: ++ case STM32MP153D_PART_NB: ++ case STM32MP151F_PART_NB: ++ case STM32MP151D_PART_NB: ++#endif ++ return true; ++ default: ++ return id == PLAT_OPP_ID1; ++ } ++} + + void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) + { +@@ -217,6 +448,45 @@ void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) + + /* MPUs Part Numbers */ + switch (get_part_number()) { ++#if STM32MP13 ++ case STM32MP135F_PART_NB: ++ cpu_s = "135F"; ++ break; ++ case STM32MP135D_PART_NB: ++ cpu_s = "135D"; ++ break; ++ case STM32MP135C_PART_NB: ++ cpu_s = "135C"; ++ break; ++ case STM32MP135A_PART_NB: ++ cpu_s = "135A"; ++ break; ++ case STM32MP133F_PART_NB: ++ cpu_s = "133F"; ++ break; ++ case STM32MP133D_PART_NB: ++ cpu_s = "133D"; ++ break; ++ case STM32MP133C_PART_NB: ++ cpu_s = "133C"; ++ break; ++ case STM32MP133A_PART_NB: ++ cpu_s = "133A"; ++ break; ++ case STM32MP131F_PART_NB: ++ cpu_s = "131F"; ++ break; ++ case STM32MP131D_PART_NB: ++ cpu_s = "131D"; ++ break; ++ case STM32MP131C_PART_NB: ++ cpu_s = "131C"; ++ break; ++ case STM32MP131A_PART_NB: ++ cpu_s = "131A"; ++ break; ++#endif ++#if STM32MP15 + case STM32MP157C_PART_NB: + cpu_s = "157C"; + break; +@@ -253,12 +523,18 @@ void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) + case STM32MP151D_PART_NB: + cpu_s = "151D"; + break; ++#endif + default: + cpu_s = "????"; + break; + } + + /* Package */ ++#if STM32MP13 ++ /* On STM32MP13, package is not present in OTP */ ++ pkg = ""; ++#endif ++#if STM32MP15 + switch (get_cpu_package()) { + case PKG_AA_LFBGA448: + pkg = "AA"; +@@ -276,12 +552,18 @@ void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) + pkg = "??"; + break; + } ++#endif + + /* REVISION */ + switch (stm32mp_get_chip_version()) { + case STM32MP1_REV_B: + cpu_r = "B"; + break; ++#if STM32MP13 ++ case STM32MP1_REV_Y: ++ cpu_r = "Y"; ++ break; ++#endif + case STM32MP1_REV_Z: + cpu_r = "Z"; + break; +@@ -304,35 +586,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(); +- } +- +- board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); ++ uint32_t board_id = 0; + +- 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; + } + +@@ -353,15 +609,25 @@ void stm32mp_print_boardinfo(void) + /* Return true when SoC provides a single Cortex-A7 core, and false otherwise */ + bool stm32mp_is_single_core(void) + { ++#if STM32MP13 ++ return true; ++#endif ++#if STM32MP15 ++ bool single_core = false; ++ + switch (get_part_number()) { + case STM32MP151A_PART_NB: + case STM32MP151C_PART_NB: + case STM32MP151D_PART_NB: + case STM32MP151F_PART_NB: +- return true; ++ single_core = true; ++ break; + default: +- return false; ++ break; + } ++ ++ return single_core; ++#endif + } + + /* Return true when device is in closed state */ +@@ -369,12 +635,58 @@ 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; ++#if STM32MP13 ++ value = (value & CFG0_OTP_MODE_MASK) >> CFG0_OTP_MODE_SHIFT; ++ ++ switch (value) { ++ case CFG0_OPEN_DEVICE: ++ return false; ++ case CFG0_CLOSED_DEVICE: ++ case CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN: ++ case CFG0_CLOSED_DEVICE_NO_JTAG: ++ return true; ++ default: ++ panic(); ++ } ++#endif ++#if STM32MP15 ++ return (value & CFG0_CLOSED_DEVICE) == CFG0_CLOSED_DEVICE; ++#endif ++} ++ ++/* Return true when device supports secure boot */ ++bool stm32mp_is_auth_supported(void) ++{ ++ bool supported = false; ++ ++ switch (get_part_number()) { ++#if STM32MP13 ++ case STM32MP131C_PART_NB: ++ case STM32MP131F_PART_NB: ++ case STM32MP133C_PART_NB: ++ case STM32MP133F_PART_NB: ++ case STM32MP135C_PART_NB: ++ case STM32MP135F_PART_NB: ++#endif ++#if STM32MP15 ++ case STM32MP151C_PART_NB: ++ case STM32MP151F_PART_NB: ++ case STM32MP153C_PART_NB: ++ case STM32MP153F_PART_NB: ++ case STM32MP157C_PART_NB: ++ case STM32MP157F_PART_NB: ++#endif ++ supported = true; ++ break; ++ default: ++ break; ++ } ++ ++ return supported; + } + + uint32_t stm32_iwdg_get_instance(uintptr_t base) +@@ -394,13 +706,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(); + } + +@@ -422,29 +728,34 @@ 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; + } + +@@ -452,25 +763,200 @@ uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags) + } + #endif + +-#if STM32MP_USE_STM32IMAGE +-/* Get the non-secure DDR size */ +-uint32_t stm32mp_get_ddr_ns_size(void) ++#if defined(IMAGE_BL32) ++/* ++ * This function allows to split bindings between platform and ETZPC ++ * HW mapping. If this conversion was done at driver level, the driver ++ * should include all supported platform bindings. ETZPC may be used on ++ * other platforms. ++ */ ++enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode) ++{ ++ switch (mode) { ++ case DECPROT_S_RW: ++ return ETZPC_DECPROT_S_RW; ++ case DECPROT_NS_R_S_W: ++ return ETZPC_DECPROT_NS_R_S_W; ++ case DECPROT_MCU_ISOLATION: ++ return ETZPC_DECPROT_MCU_ISOLATION; ++ case DECPROT_NS_RW: ++ return ETZPC_DECPROT_NS_RW; ++ default: ++ panic(); ++ } ++} ++#endif ++ ++bool stm32mp1_addr_inside_backupsram(uintptr_t addr) ++{ ++ return (addr >= STM32MP_BACKUP_RAM_BASE) && ++ (addr < (STM32MP_BACKUP_RAM_BASE + STM32MP_BACKUP_RAM_SIZE)); ++} ++ ++bool stm32mp1_is_wakeup_from_standby(void) ++{ ++ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR); ++#if STM32MP15 ++ uintptr_t bkpr_core1_addr = tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); ++ uint32_t nsec_address; ++#endif ++ ++ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { ++ return false; ++ } ++ ++ if (stm32mp_get_boot_action() != BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY) { ++ return false; ++ } ++ ++#if STM32MP15 ++ clk_enable(RTCAPB); ++ nsec_address = mmio_read_32(bkpr_core1_addr); ++ clk_disable(RTCAPB); ++ ++ if (nsec_address == 0U) { ++ return false; ++ } ++#endif ++ ++ return stm32_pm_context_is_valid(); ++} ++ ++void stm32_save_boot_interface(uint32_t interface, uint32_t instance) ++{ ++ uintptr_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); ++ ++ clk_enable(RTCAPB); ++ ++ mmio_clrsetbits_32(bkpr_itf_idx, ++ TAMP_BOOT_ITF_MASK, ++ ((interface << 4) | (instance & 0xFU)) << ++ TAMP_BOOT_ITF_SHIFT); ++ ++ clk_disable(RTCAPB); ++} ++ ++void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance) + { +- static uint32_t ddr_ns_size; +- uint32_t ddr_size; ++ static uint32_t itf; ++ ++ if (itf == 0U) { ++ uintptr_t bkpr = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); + +- if (ddr_ns_size != 0U) { +- return ddr_ns_size; ++ clk_enable(RTCAPB); ++ ++ itf = (mmio_read_32(bkpr) & TAMP_BOOT_ITF_MASK) >> TAMP_BOOT_ITF_SHIFT; ++ ++ clk_disable(RTCAPB); + } + +- ddr_size = dt_get_ddr_size(); +- if ((ddr_size <= (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE)) || +- (ddr_size > STM32MP_DDR_MAX_SIZE)) { +- panic(); ++ *interface = itf >> 4; ++ *instance = itf & 0xFU; ++} ++ ++bool stm32_boot_is_serial(void) ++{ ++ uint32_t boot_itf; ++ uint32_t boot_instance; ++ ++ stm32_get_boot_interface(&boot_itf, &boot_instance); ++ ++ if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) || ++ (boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB)) { ++ return true; ++ } ++ ++ return false; ++} ++ ++#if defined(IMAGE_BL32) && DEBUG ++static const char *const dump_table[] = { ++ "sp_usr ", ++ "lr_usr ", ++ "spsr_irq", ++ "sp_irq ", ++ "lr_irq ", ++ "spsr_fiq", ++ "sp_fiq ", ++ "lr_fiq ", ++ "spsr_svc", ++ "sp_svc ", ++ "lr_svc ", ++ "spsr_abt", ++ "sp_abt ", ++ "lr_abt ", ++ "spsr_und", ++ "sp_und ", ++ "lr_und ", ++ "spsr_mon", ++ "sp_mon", ++ "lr_mon", ++ "scr", ++ "pmcr", ++}; ++ ++/* ++ * Dump CPU registers when entering in monitor. ++ */ ++void stm32mp_dump_core_registers(bool fcore) ++{ ++ static bool firstcore; ++ unsigned int i; ++ smc_ctx_t *ctx = smc_get_ctx(NON_SECURE); ++ uint32_t *reg = (uint32_t *)&ctx->sp_usr; ++ ++ if (fcore) { ++ firstcore = true; ++ } ++ ++ if (!firstcore) { ++ return; + } + +- ddr_ns_size = ddr_size - (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE); ++ INFO("CPU : %i\n", plat_my_core_pos()); ++ ++ for (i = 0U; i < ARRAY_SIZE(dump_table); i++) { ++ INFO("%s : 0x%x\n", dump_table[i], reg[i]); ++ } ++} ++#endif ++ ++#if PSA_FWU_SUPPORT ++void stm32mp1_fwu_set_boot_idx(void) ++{ ++ clk_enable(RTCAPB); ++ mmio_clrsetbits_32(tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID), ++ TAMP_BOOT_FWU_INFO_IDX_MSK, ++ (plat_fwu_get_boot_idx() << TAMP_BOOT_FWU_INFO_IDX_OFF) & ++ TAMP_BOOT_FWU_INFO_IDX_MSK); ++ clk_disable(RTCAPB); ++} ++ ++uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void) ++{ ++ uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID); ++ uint32_t try_cnt; ++ ++ clk_enable(RTCAPB); ++ try_cnt = (mmio_read_32(bkpr_fwu_cnt) & TAMP_BOOT_FWU_INFO_CNT_MSK) >> ++ TAMP_BOOT_FWU_INFO_CNT_OFF; ++ if (try_cnt != 0U) { ++ mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK, ++ (try_cnt - 1U) << TAMP_BOOT_FWU_INFO_CNT_OFF); ++ } ++ clk_disable(RTCAPB); ++ ++ return try_cnt; ++} ++ ++void stm32_set_max_fwu_trial_boot_cnt(void) ++{ ++ uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID); + +- return ddr_ns_size; ++ clk_enable(RTCAPB); ++ mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK, ++ (FWU_MAX_TRIAL_REBOOT << TAMP_BOOT_FWU_INFO_CNT_OFF) & ++ TAMP_BOOT_FWU_INFO_CNT_MSK); ++ clk_disable(RTCAPB); + } +-#endif /* STM32MP_USE_STM32IMAGE */ ++#endif /* PSA_FWU_SUPPORT */ +diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c +index 6d60bd4de..b11c2dddb 100644 +--- a/plat/st/stm32mp1/stm32mp1_scmi.c ++++ b/plat/st/stm32mp1/stm32mp1_scmi.c +@@ -8,12 +8,14 @@ + + #include + ++#include + #include + #include + #include + #include + #include + #include ++#include + + #define TIMEOUT_US_1MS 1000U + +@@ -124,6 +126,7 @@ static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = { + RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"), + RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"), + RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"), ++ RESET_CELL(RST_SCMI0_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"), + }; + + struct scmi_agent_resources { +@@ -260,6 +263,17 @@ const char *plat_scmi_clock_get_name(unsigned int agent_id, + + 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); + +@@ -271,12 +285,50 @@ int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, + return SCMI_DENIED; + } + +- if (array == NULL) { +- *nb_elts = 1U; +- } else if (*nb_elts == 1U) { +- *array = stm32mp_clk_get_rate(clock->clock_id); +- } else { +- return SCMI_GENERIC_ERROR; ++ 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] = 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) ++{ ++ 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: ++ if (stm32mp1_set_opp_khz(rate / 1000UL) != 0) { ++ return SCMI_INVALID_PARAMETERS; ++ } ++ break; ++ default: ++ if (rate != clk_get_rate(clock->clock_id)) { ++ return SCMI_INVALID_PARAMETERS; ++ } ++ break; + } + + return SCMI_SUCCESS; +@@ -292,7 +344,7 @@ unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, + return 0U; + } + +- return stm32mp_clk_get_rate(clock->clock_id); ++ return clk_get_rate(clock->clock_id); + } + + int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id) +@@ -323,13 +375,13 @@ int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, + if (enable_not_disable) { + if (!clock->enabled) { + VERBOSE("SCMI clock %u enable\n", scmi_id); +- stm32mp_clk_enable(clock->clock_id); ++ 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); ++ clk_disable(clock->clock_id); + clock->enabled = false; + } + } +@@ -388,6 +440,10 @@ int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id, + return SCMI_NOT_FOUND; + } + ++ if (rstd->reset_id == MCU_HOLD_BOOT_R) { ++ return SCMI_NOT_SUPPORTED; ++ } ++ + if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) { + return SCMI_DENIED; + } +@@ -423,6 +479,13 @@ int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id, + return SCMI_DENIED; + } + ++ if (rstd->reset_id == MCU_HOLD_BOOT_R) { ++ VERBOSE("SCMI MCU reset %s\n", ++ assert_not_deassert ? "set" : "release"); ++ stm32mp_reset_assert_deassert_to_mcu(assert_not_deassert); ++ return SCMI_SUCCESS; ++ } ++ + if (assert_not_deassert) { + VERBOSE("SCMI reset %lu set\n", rstd->reset_id); + stm32mp_reset_set(rstd->reset_id); +@@ -461,7 +524,7 @@ void stm32mp1_init_scmi_server(void) + /* 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); ++ clk_enable(clk->clock_id); + } + } + +@@ -476,3 +539,51 @@ void stm32mp1_init_scmi_server(void) + } + } + } ++ ++/* ++ * 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 +deleted file mode 100644 +index 19ef4f0ae..000000000 +--- a/plat/st/stm32mp1/stm32mp1_security.c ++++ /dev/null +@@ -1,135 +0,0 @@ +-/* +- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ +- +-#include +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-static unsigned int region_nb; +- +-static void init_tzc400_begin(unsigned int region0_attr) +-{ +- tzc400_init(STM32MP1_TZC_BASE); +- tzc400_disable_filters(); +- +- /* Region 0 set to cover all DRAM at 0xC000_0000 */ +- tzc400_configure_region0(region0_attr, 0); +- +- region_nb = 1U; +-} +- +-static void init_tzc400_end(unsigned int action) +-{ +- tzc400_set_action(action); +- tzc400_enable_filters(); +-} +- +-static void tzc400_add_region(unsigned long long region_base, +- unsigned long long region_top, bool sec) +-{ +- unsigned int sec_attr; +- unsigned int nsaid_permissions; +- +- if (sec) { +- sec_attr = TZC_REGION_S_RDWR; +- nsaid_permissions = 0; +- } else { +- sec_attr = TZC_REGION_S_NONE; +- nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR; +- } +- +- tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base, +- region_top, sec_attr, nsaid_permissions); +- +- region_nb++; +-} +- +-/******************************************************************************* +- * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access +- * and allow Non-Secure masters full access. +- ******************************************************************************/ +-static void init_tzc400(void) +-{ +- unsigned long long region_base, region_top; +- unsigned long long ddr_base = STM32MP_DDR_BASE; +- unsigned long long ddr_ns_size = +- (unsigned long long)stm32mp_get_ddr_ns_size(); +- unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U); +- unsigned long long ddr_top __unused; +- +- init_tzc400_begin(TZC_REGION_S_NONE); +- +- /* +- * 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; +- region_top = ddr_ns_top; +- tzc400_add_region(region_base, region_top, false); +- +-#ifdef AARCH32_SP_OPTEE +- /* Region 2 set to cover all secure DRAM. */ +- region_base = region_top + 1U; +- region_top += STM32MP_DDR_S_SIZE; +- tzc400_add_region(region_base, region_top, true); +- +- ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U; +- if (region_top < ddr_top) { +- /* Region 3 set to cover non-secure memory DRAM after BL32. */ +- region_base = region_top + 1U; +- region_top = ddr_top; +- tzc400_add_region(region_base, region_top, false); +- } +-#endif +- +- /* +- * Raise an interrupt (secure FIQ) if a NS device tries to access +- * secure memory +- */ +- init_tzc400_end(TZC_ACTION_INT); +-} +- +-/******************************************************************************* +- * Initialize the TrustZone Controller. +- * Early initialization create only one region with full access to secure. +- * This setting is used before and during DDR initialization. +- ******************************************************************************/ +-static void early_init_tzc400(void) +-{ +- stm32mp_clk_enable(TZC1); +- stm32mp_clk_enable(TZC2); +- +- /* Region 0 set to cover all DRAM secure at 0xC000_0000 */ +- init_tzc400_begin(TZC_REGION_S_RDWR); +- +- /* Raise an exception if a NS device tries to access secure memory */ +- init_tzc400_end(TZC_ACTION_ERR); +-} +- +-/******************************************************************************* +- * Initialize the secure environment. At this moment only the TrustZone +- * Controller is initialized. +- ******************************************************************************/ +-void stm32mp1_arch_security_setup(void) +-{ +- early_init_tzc400(); +-} +- +-/******************************************************************************* +- * Initialize the secure environment. At this moment only the TrustZone +- * Controller is initialized. +- ******************************************************************************/ +-void stm32mp1_security_setup(void) +-{ +- init_tzc400(); +-} +diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c +index 6b1bcaa13..12cfb354e 100644 +--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c ++++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c +@@ -87,6 +87,64 @@ static const char __unused *shres2str_state(unsigned int state) + return shres2str_state_tbl[state]; + } + ++struct shres2decprot { ++ unsigned int shres_id; ++ unsigned int decprot_id; ++ const char *decprot_str; ++}; ++ ++#define SHRES2DECPROT(shres, decprot, str) { \ ++ .shres_id = shres, \ ++ .decprot_id = decprot, \ ++ .decprot_str = str, \ ++ } ++ ++#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"), ++ SHRES2DECPROT(STM32MP1_SHRES_SPI6, STM32MP1_ETZPC_SPI6_ID, "SPI6"), ++ SHRES2DECPROT(STM32MP1_SHRES_I2C4, STM32MP1_ETZPC_I2C4_ID, "I2C4"), ++ SHRES2DECPROT(STM32MP1_SHRES_RNG1, STM32MP1_ETZPC_RNG1_ID, "RNG1"), ++ SHRES2DECPROT(STM32MP1_SHRES_HASH1, STM32MP1_ETZPC_HASH1_ID, "HASH1"), ++ SHRES2DECPROT(STM32MP1_SHRES_CRYP1, STM32MP1_ETZPC_CRYP1_ID, "CRYP1"), ++ SHRES2DECPROT(STM32MP1_SHRES_I2C6, STM32MP1_ETZPC_I2C6_ID, "I2C6"), ++ /* Below are specific IDs without a 1-to-1 mapping to SHRES IDs */ ++ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_STGENC_ID, "STGEN"), ++ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_BKPSRAM_ID, "BKPSRAM"), ++ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRCTRL_ID, "DDRCTRL"), ++ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRPHYC_ID, "DDRPHY"), ++}; ++ ++static unsigned int decprot2shres(unsigned int decprot_id) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) { ++ if (shres2decprot_tbl[i].decprot_id == decprot_id) { ++ return shres2decprot_tbl[i].shres_id; ++ } ++ } ++ ++ VERBOSE("No shared resource %u", decprot_id); ++ return SHRES_INVALID; ++} ++ ++static const char *decprot2str(unsigned int decprot_id) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) { ++ if (shres2decprot_tbl[i].decprot_id == decprot_id) { ++ return shres2decprot_tbl[i].decprot_str; ++ } ++ } ++ ++ ERROR("Invalid ID %u", decprot_id); ++ panic(); ++} ++ + /* Get resource state: these accesses lock the registering support */ + static void lock_registering(void) + { +@@ -334,6 +392,53 @@ void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) + } + } + ++void stm32mp1_register_etzpc_decprot(unsigned int id, ++ enum etzpc_decprot_attributes attr) ++{ ++ unsigned int state = SHRES_SECURE; ++ unsigned int id_shres; ++ ++ switch (attr) { ++ case ETZPC_DECPROT_S_RW: ++ break; ++ case ETZPC_DECPROT_NS_R_S_W: ++ case ETZPC_DECPROT_MCU_ISOLATION: ++ case ETZPC_DECPROT_NS_RW: ++ state = SHRES_NON_SECURE; ++ break; ++ default: ++ panic(); ++ } ++ ++ switch (id) { ++ case STM32MP1_ETZPC_STGENC_ID: ++ case STM32MP1_ETZPC_BKPSRAM_ID: ++ /* We assume these must always be assigned to secure world */ ++ if (state != SHRES_SECURE) { ++ panic(); ++ } ++ break; ++ case STM32MP1_ETZPC_DDRCTRL_ID: ++ case STM32MP1_ETZPC_DDRPHYC_ID: ++ /* allow write only for secure world */ ++ if ((attr != ETZPC_DECPROT_S_RW) && ++ (attr != ETZPC_DECPROT_NS_R_S_W)) { ++ panic(); ++ } ++ break; ++ default: ++ id_shres = decprot2shres(id); ++ if (id_shres == SHRES_INVALID) { ++ if (state == SHRES_SECURE) { ++ panic(); ++ } ++ } else { ++ register_periph(id_shres, state); ++ } ++ break; ++ } ++} ++ + static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) + { + unsigned int non_secure = 0U; +@@ -379,12 +484,15 @@ bool stm32mp_nsec_can_access_clock(unsigned long clock_id) + enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; + + switch (clock_id) { ++ case BSEC: ++ case CK_AXI: + case CK_CSI: + case CK_HSE: + case CK_HSE_DIV2: + case CK_HSI: + case CK_LSE: + case CK_LSI: ++ case CK_MPU: + case PLL1_P: + case PLL1_Q: + case PLL1_R: +@@ -454,6 +562,7 @@ bool stm32mp_nsec_can_access_reset(unsigned int reset_id) + shres_id = STM32MP1_SHRES_I2C6; + break; + case MCU_R: ++ case MCU_HOLD_BOOT_R: + shres_id = STM32MP1_SHRES_MCU; + break; + case MDMA_R: +@@ -499,33 +608,81 @@ static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id) + return ETZPC_DECPROT_S_RW; + } + +-static void set_etzpc_secure_configuration(void) ++static bool check_decprot(unsigned int id, enum etzpc_decprot_attributes exp) + { +- /* Some system peripherals shall be secure */ +- etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); +- etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); +- etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID, +- ETZPC_DECPROT_NS_R_S_W); +- etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID, +- ETZPC_DECPROT_NS_R_S_W); +- +- /* Configure ETZPC with peripheral registering */ +- etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID, +- shres2decprot_attr(STM32MP1_SHRES_CRYP1)); +- etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID, +- shres2decprot_attr(STM32MP1_SHRES_HASH1)); +- etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID, +- shres2decprot_attr(STM32MP1_SHRES_I2C4)); +- etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID, +- shres2decprot_attr(STM32MP1_SHRES_I2C6)); +- etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID, +- shres2decprot_attr(STM32MP1_SHRES_IWDG1)); +- etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID, +- shres2decprot_attr(STM32MP1_SHRES_RNG1)); +- etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID, ++ enum etzpc_decprot_attributes cur = etzpc_get_decprot(id); ++ ++ if (cur == exp) { ++ return true; ++ } ++ ++ switch (exp) { ++ case ETZPC_DECPROT_NS_RW: ++ if (cur == ETZPC_DECPROT_S_RW) { ++ INFO("ETZPC: %s (%d) could be non secure\n", ++ decprot2str(id), id); ++ } ++ return true; ++ ++ case ETZPC_DECPROT_S_RW: ++ ERROR("ETZPC: %s (%d) expected secure but DECPROT = %d\n", ++ decprot2str(id), id, cur); ++ break; ++ ++ case ETZPC_DECPROT_NS_R_S_W: ++ case ETZPC_DECPROT_MCU_ISOLATION: ++ break; ++ default: ++ panic(); ++ } ++ ++ return false; ++} ++ ++static void check_etzpc_secure_configuration(void) ++{ ++ bool error = false; ++ ++ assert(registering_locked); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_USART1_ID, + shres2decprot_attr(STM32MP1_SHRES_USART1)); +- etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID, ++ ++ error |= !check_decprot(STM32MP1_ETZPC_I2C4_ID, ++ shres2decprot_attr(STM32MP1_SHRES_I2C4)); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_SPI6_ID, + shres2decprot_attr(STM32MP1_SHRES_SPI6)); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_RNG1_ID, ++ shres2decprot_attr(STM32MP1_SHRES_RNG1)); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_HASH1_ID, ++ shres2decprot_attr(STM32MP1_SHRES_HASH1)); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_CRYP1_ID, ++ shres2decprot_attr(STM32MP1_SHRES_CRYP1)); ++ ++ error |= !((check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, ++ ETZPC_DECPROT_NS_R_S_W)) || ++ (check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, ++ ETZPC_DECPROT_S_RW))); ++ ++ error |= !((check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, ++ ETZPC_DECPROT_NS_R_S_W)) || ++ (check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, ++ ETZPC_DECPROT_S_RW))); ++ ++ error |= !check_decprot(STM32MP1_ETZPC_I2C6_ID, ++ shres2decprot_attr(STM32MP1_SHRES_I2C6)); ++ ++ if (error) { ++ panic(); ++ } + } + + static void check_rcc_secure_configuration(void) +@@ -592,6 +749,6 @@ void stm32mp_lock_periph_registering(void) + print_shared_resources_state(); + + check_rcc_secure_configuration(); +- set_etzpc_secure_configuration(); ++ check_etzpc_secure_configuration(); + set_gpio_secure_configuration(); + } +diff --git a/plat/st/stm32mp1/stm32mp1_ssp.c b/plat/st/stm32mp1/stm32mp1_ssp.c +new file mode 100644 +index 000000000..14ce02381 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_ssp.c +@@ -0,0 +1,1001 @@ ++/* ++ * Copyright (c) 2017-2021, 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 CERT_CHIP_ID_LEN U(3) ++#define CERT_SECURITY_COUNTER_LEN U(2) ++#define CERT_SECURITY_COUNTER_SHIFT CERT_CHIP_ID_LEN ++#define CERT_RFU_LEN U(1) ++#define CERT_RFU_SHIFT (CERT_SECURITY_COUNTER_LEN + \ ++ CERT_SECURITY_COUNTER_SHIFT) ++#define CERT_PRODUCT_KEY_LEN U(2) ++#define CERT_PRODUCT_KEY_SHIFT (CERT_RFU_LEN + CERT_RFU_SHIFT) ++#define CERT_PRODUCT_ID_SIZE (CERT_PRODUCT_KEY_LEN + \ ++ CERT_PRODUCT_KEY_SHIFT) ++#define CERT_SIGNATURE_LEN CHIP_CERTIFICATE_MAX_SIZE ++#define CERT_SIGNATURE_SHIFT (CERT_PRODUCT_ID_SIZE + \ ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES) ++#define CERTIFICATE_SIZE (CERT_PRODUCT_ID_SIZE + \ ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES + \ ++ CERT_SIGNATURE_LEN) /* 136 bytes */ ++#define BLOB_FILE_MAX_ADDR BL2_RW_LIMIT ++ ++/* Local status for SSP processing sequences */ ++typedef enum { ++ SSP_NONE, ++ SSP_GET_CERT, ++ SSP_FLASH_OEM, ++ SSP_DONE, ++ SSP_ERROR ++} ssp_result_e; ++ ++struct otp_val { ++ uint32_t idx; ++ uint32_t nb; ++}; ++ ++static struct otp_val otp_ssp; ++static struct otp_val otp_rma; ++static struct otp_val otp_pubkey; ++ ++/* Platform empty definition required */ ++void bl2_platform_setup(void) {} ++struct bl_params *plat_get_next_bl_params(void) { return NULL; } ++void plat_flush_next_bl_params(void) {} ++struct bl_load_info *plat_get_bl_image_load_info(void) { return NULL; } ++int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, ++ uintptr_t *image_spec) ++{ ++ return 0; ++} ++ ++/* ++ * Initialized OTP index from device tree. ++ */ ++static int initialize_otp(void) ++{ ++ uint32_t len; ++ ++ /* OTP SSP */ ++ if (stm32_get_otp_index(SSP_OTP, &otp_ssp.idx, NULL) != 0) { ++ VERBOSE("%s: get index error\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* OTP public key */ ++ if (stm32_get_otp_index(PKH_OTP, &otp_pubkey.idx, &len) != 0) { ++ VERBOSE("%s: get index error\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) { ++ VERBOSE("%s: length Error\n", __func__); ++ return -EINVAL; ++ } ++ ++ otp_pubkey.nb = len / __WORD_BIT; ++ ++ /* OTP RMA */ ++ if (stm32_get_otp_index(RMA_OTP, &otp_rma.idx, NULL) != 0) { ++ VERBOSE("%s: get index error\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Compute HASH from public key and burn it in OTP. ++ */ ++static int ssp_pub_key_prog(boot_api_context_t *boot_context) ++{ ++#if STM32MP13 ++ uint32_t *value = (uint32_t *) ++ boot_context->p_ssp_config->p_blob_payload->oem_rpkth; ++#endif ++#if STM32MP15 ++ uint8_t key_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES] __aligned(4); ++ uint8_t *pubk = (uint8_t *) ++ boot_context->p_ssp_config->p_blob_payload->oem_ecdsa_pubk; ++ uint32_t *value = (uint32_t *)key_hash; ++#endif ++ uint32_t i; ++ ++#if STM32MP15 ++ if (stm32_hash_register() != 0) { ++ return -EINVAL; ++ } ++ ++ stm32_hash_init(HASH_SHA256); ++ ++ if (stm32_hash_final_update(pubk, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES, ++ key_hash) != 0) { ++ ERROR("Hash of payload failed\n"); ++ return -EINVAL; ++ } ++#endif ++ ++ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) { ++ if (bsec_program_otp(bswap32(*value), i) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ value++; ++ if (bsec_permanent_lock_otp(i) != BSEC_OK) { ++ ERROR("Error locking OTP %i\n", i); ++ panic(); ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Burn OTP to close device. ++ */ ++static int ssp_close_device(void) ++{ ++ uint32_t otp; ++ uint32_t value; ++ ++ if (stm32_get_otp_index(CFG0_OTP, &otp, NULL) != 0) { ++ return -EINVAL; ++ } ++ ++ if (bsec_read_otp(&value, otp) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++#if STM32MP13 ++ if ((value & ~CFG0_OPEN_DEVICE) != 0U) { ++ ERROR("Device already closed\n"); ++ return -EINVAL; ++ } ++#endif ++#if STM32MP15 ++ if ((value & CFG0_CLOSED_DEVICE) != 0U) { ++ ERROR("Device already closed\n"); ++ return -EINVAL; ++ } ++#endif ++ ++ value |= CFG0_CLOSED_DEVICE; ++ if (bsec_program_otp(value, otp) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * OTP initial check to detect previous values. ++ */ ++static int ssp_secrets_check(boot_api_context_t *boot_ctx) ++{ ++ uint32_t i; ++ uint32_t check_val; ++ uint32_t otp_bytes = boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes; ++ uint32_t otp_decrypted; ++ ++ if (otp_bytes == 0U) { ++ return -EINVAL; ++ } ++ ++ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) { ++ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (check_val != 0U) { ++ ERROR("OTP %u value already programmed\n", i); ++ return -EINVAL; ++ } ++ } ++ ++ otp_decrypted = round_up(otp_bytes, sizeof(uint32_t)) / sizeof(uint32_t); ++ ++ /* OTP decrypted include RMA password */ ++ if (otp_decrypted > (2U + SSP_OTP_SECRET_END - SSP_OTP_SECRET_BASE)) { ++ return -EINVAL; ++ } ++ ++ /* Check RMA password */ ++ if (stm32_get_otp_value_from_idx(otp_rma.idx, &check_val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (check_val != 0U) { ++ ERROR("OTP %s value already programmed\n", RMA_OTP); ++ return -EINVAL; ++ } ++ ++ /* Check all OTP available */ ++ for (i = SSP_OTP_SECRET_BASE; i < SSP_OTP_SECRET_BASE + otp_decrypted - 1U; i++) { ++ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (check_val != 0U) { ++ ERROR("OTP %u value already programmed\n", i); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Burn OTP with the decrypted secret received. ++ */ ++static int ssp_secrets_flash(boot_api_context_t *boot_ctx) ++{ ++ uint32_t i; ++ uint32_t *val; ++ uint32_t otp_bytes = ++ boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes; ++ uint32_t otp_decrypted; ++ uint32_t otp_mask = 0U; ++ ++ if (otp_bytes == 0U) { ++ return -EINVAL; ++ } ++ ++ if (otp_bytes % sizeof(uint32_t) != 0U) { ++ otp_mask = GENMASK_32(((otp_bytes % sizeof(uint32_t)) * ++ sizeof(uint32_t)) - 1, 0); ++ } ++ ++ val = (uint32_t *)boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted; ++ ++ otp_decrypted = round_up(otp_bytes, sizeof(uint32_t)) / sizeof(uint32_t); ++ ++ /* Burn RMA password */ ++ if (bsec_program_otp((*val & RMA_OTP_MASK), otp_rma.idx) != BSEC_OK) { ++ WARN("RMA programing failed\n"); ++ return -EINVAL; ++ } ++ ++ val++; ++ otp_decrypted--; ++ for (i = SSP_OTP_SECRET_BASE; i < (SSP_OTP_SECRET_BASE + otp_decrypted - 1U); i++) { ++ if (*val == 0U) { ++ val++; ++ continue; ++ } ++ ++ if (bsec_program_otp(*val, i) != BSEC_OK) { ++ WARN("Error writing OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ if (bsec_permanent_lock_otp(i) != BSEC_OK) { ++ WARN("Error locking OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ val++; ++ } ++ ++ if (*val == 0U) { ++ return 0; ++ } ++ ++ /* Mask the last OTP value if needed */ ++ if (otp_mask != 0U) { ++ *val &= otp_mask; ++ } ++ ++ if (bsec_program_otp(*val, i) != BSEC_OK) { ++ WARN("Error writing OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ if (bsec_permanent_lock_otp(i) != BSEC_OK) { ++ WARN("Error locking OTP %i\n", i); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Finish SSP processing by fusing OTP SSP success. ++ */ ++static int ssp_finish_process(void) ++{ ++ uint32_t val; ++ ++ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) { ++ return -EINVAL; ++ } ++ ++ if ((val & SSP_OTP_SUCCESS) != 0U) { ++ WARN("Error while configuring OTP\n"); ++ return -EINVAL; ++ } ++ ++ val |= SSP_OTP_SUCCESS; ++ if (bsec_program_otp(val, otp_ssp.idx) != BSEC_OK) { ++ return -EINVAL; ++ } ++ ++ VERBOSE("Write OTP Success\n"); ++ ++ return 0; ++} ++ ++/* ++ * Transform integer to string. ++ */ ++static void itoa(uint32_t num, char *str, int nb) ++{ ++ if (num == 0U) { ++ while (nb-- != 0U) { ++ str[nb] = '0'; ++ } ++ ++ return; ++ } ++ ++ while (num != 0U) { ++ int rem = num % 16; ++ ++ str[--nb] = (rem > 9) ? (rem - 10) + 'A' : rem + '0'; ++ num /= 16; ++ } ++ ++ while (nb != 0) { ++ str[--nb] = '0'; ++ } ++} ++ ++/* ++ * Return chip product ID. ++ */ ++static int ssp_get_product_id(char *msg) ++{ ++ uint32_t otp; ++ uint32_t otp_idx; ++ uint32_t chip_id = stm32mp_get_chip_dev_id(); ++ ++ if (stm32_get_otp_index(CFG2_OTP, &otp_idx, NULL) != 0) { ++ VERBOSE("Get index error\n"); ++ return -EINVAL; ++ } ++ ++ if (stm32_get_otp_value_from_idx(otp_idx, &otp) != 0) { ++ return -EINVAL; ++ } ++ ++ itoa(chip_id, msg, CERT_CHIP_ID_LEN); ++ itoa((otp & OTP_CFG2_SEC_COUNTER_MASK) >> OTP_CFG2_SEC_COUNTER_SHIFT, ++ msg + CERT_SECURITY_COUNTER_SHIFT, ++ CERT_SECURITY_COUNTER_LEN); ++ ++ itoa(0, msg + CERT_RFU_SHIFT, CERT_RFU_LEN); ++ itoa((otp & OTP_CFG2_ST_KEY_MASK) >> OTP_CFG2_ST_KEY_SHIFT, ++ msg + CERT_PRODUCT_KEY_SHIFT, ++ CERT_PRODUCT_KEY_LEN); ++ ++ return 0; ++} ++ ++/* ++ * Construct SSP certificate. ++ */ ++static int prepare_certificate(uint8_t *cert, const uint8_t *pubkey) ++{ ++ uint32_t i; ++ uint32_t j; ++ uint32_t otp; ++ uint32_t otp_idx; ++ uint32_t otp_len; ++ ++ /* Prepare the ROM Security constant */ ++ if (ssp_get_product_id((char *)cert) != 0) { ++ return -EINVAL; ++ } ++ ++ /* Prepare public key and certificate for flashloader */ ++ /* Read Public Key from boot_context */ ++ memcpy(cert + CERT_PRODUCT_ID_SIZE, pubkey, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); ++ ++ if (stm32_get_otp_index(CHIP_CERTIFICATE_OTP, ++ &otp_idx, &otp_len) != 0) { ++ VERBOSE("Get index error\n"); ++ return -EINVAL; ++ } ++ ++ if (otp_len != (CHAR_BIT * CHIP_CERTIFICATE_MAX_SIZE)) { ++ VERBOSE("Length error\n"); ++ return -EINVAL; ++ } ++ ++ otp_len /= __WORD_BIT; ++ ++ /* Read Certificat from OTP */ ++ for (i = otp_idx, j = 0U; i < (otp_idx + otp_len); i++, j++) { ++ uint32_t otp_s; ++ ++ if (stm32_get_otp_value_from_idx(i, &otp) != 0) { ++ return -EINVAL; ++ } ++ ++ otp_s = bswap32(otp); ++ memcpy(&cert[CERT_SIGNATURE_SHIFT + (sizeof(uint32_t) * j)], ++ &otp_s, sizeof(uint32_t)); ++ } ++ ++ return 0; ++} ++ ++/* ++ * Clean external data and bootrom context secret values. ++ */ ++static void ssp_cleanup(boot_api_context_t *boot_context) ++{ ++ boot_api_ssp_config_t *ssp_config = boot_context->p_ssp_config; ++ ++ /* Cleanup boot_context */ ++ if (ssp_config->p_ssp_oem_secrets_decrypted != NULL) { ++ zeromem(ssp_config->p_ssp_oem_secrets_decrypted, ++ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES); ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)ssp_config->p_ssp_oem_secrets_decrypted, ++ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES); ++#endif ++ ssp_config->p_ssp_oem_secrets_decrypted = NULL; ++ } ++ ++ if (ssp_config->p_chip_pubk != NULL) { ++ zeromem(ssp_config->p_chip_pubk, ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)ssp_config->p_chip_pubk, ++ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES); ++#endif ++ ssp_config->p_chip_pubk = NULL; ++ } ++ ++ if (ssp_config->p_blob_license != NULL) { ++ zeromem(ssp_config->p_blob_license, ++ sizeof(boot_api_ssp_blob_license_t)); ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)ssp_config->p_blob_license, ++ sizeof(boot_api_ssp_blob_license_t)); ++#endif ++ ssp_config->p_blob_license = NULL; ++ } ++ ++ if (ssp_config->p_blob_payload != NULL) { ++ zeromem(ssp_config->p_blob_payload, ++ sizeof(boot_api_ssp_blob_payload_t)); ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)ssp_config->p_blob_payload, ++ sizeof(boot_api_ssp_blob_payload_t)); ++#endif ++ ssp_config->p_blob_payload = NULL; ++ } ++ ++ ssp_config->ssp_cmd = 0U; ++ ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, ++ sizeof(boot_api_ssp_config_t)); ++#endif ++} ++ ++/* ++ * Send certificate to the programmer and retrieve the associated ++ * encrypted file. ++ */ ++static int ssp_download_phase(boot_api_context_t *boot_ctx) ++{ ++ uint8_t *blob_file; ++#if STM32MP_UART_PROGRAMMER ++ uintptr_t uart_base; ++#endif ++#if STM32MP_USB_PROGRAMMER ++ struct usb_handle *pdev; ++#endif ++ int result = 0; ++ uint8_t cert[CERTIFICATE_SIZE]; ++ ++#if STM32MP13 ++ blob_file = (uint8_t *)boot_ctx->p_ssp_config->p_blob_license; ++#endif ++#if STM32MP15 ++ blob_file = (uint8_t *)page_align(BLOB_FILE_MAX_ADDR - ++ sizeof(boot_api_ssp_blob_license_t) - ++ sizeof(boot_api_ssp_blob_payload_t), ++ DOWN); ++#endif ++ ++ if (prepare_certificate(cert, boot_ctx->p_ssp_config->p_chip_pubk) != 0) { ++ return -EINVAL; ++ } ++ ++ switch (boot_ctx->boot_interface_selected) { ++#if STM32MP_USB_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: ++ ++ /* init USB on platform */ ++ pdev = usb_dfu_plat_init(); ++ ++ result = stm32cubeprog_usb_ssp(pdev, (uintptr_t)cert, ++ sizeof(cert), (uintptr_t)blob_file, ++ sizeof(boot_api_ssp_blob_license_t) + ++ sizeof(boot_api_ssp_blob_payload_t)); ++ if (result != 0) { ++ return -EINVAL; ++ } ++ ++ break; ++#endif ++ ++#if STM32MP_UART_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++ uart_base = get_uart_address(boot_ctx->boot_interface_instance); ++ ++ if (uart_base == 0U) { ++ return -EINVAL; ++ } ++ ++ result = stm32cubeprog_uart_ssp(uart_base, (uintptr_t)cert, sizeof(cert), ++ (uintptr_t)blob_file, ++ sizeof(boot_api_ssp_blob_license_t) + ++ sizeof(boot_api_ssp_blob_payload_t)); ++ if (result != 0) { ++ return -EINVAL; ++ } ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++ boot_ctx->p_ssp_config->p_blob_license = ++ (boot_api_ssp_blob_license_t *)blob_file; ++ ++ /* Payload is concatened with license file */ ++ boot_ctx->p_ssp_config->p_blob_payload = ++ (boot_api_ssp_blob_payload_t *)(blob_file + ++ sizeof(boot_api_ssp_blob_license_t)); ++ ++#ifndef DCACHE_OFF ++ flush_dcache_range((uintptr_t)blob_file, ++ sizeof(boot_api_ssp_blob_license_t) + ++ sizeof(boot_api_ssp_blob_payload_t)); ++#endif ++ ++ /* Set return address for decrypted_secrets */ ++ boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted = ++ boot_ctx->p_ssp_config->p_blob_payload->oem_encrypted_secrets; ++ ++ return result; ++} ++ ++/* ++ * Burn decrypted secrets into OTP, clean memory and close the device. ++ */ ++static int ssp_secret_programming(boot_api_context_t *boot_context) ++{ ++ int result; ++ ++ result = ssp_secrets_check(boot_context); ++ if (result != 0) { ++ ERROR("SSP ERROR checking OTP\n"); ++ goto clean; ++ } ++ ++ result = ssp_pub_key_prog(boot_context); ++ if (result != 0) { ++ ERROR("SSP ERROR writing HASH key\n"); ++ goto clean; ++ } ++ ++ result = ssp_close_device(); ++ if (result != 0) { ++ ERROR("SSP close device failed\n"); ++ goto clean; ++ } ++ ++ result = ssp_secrets_flash(boot_context); ++ if (result != 0) { ++ ERROR("SSP Secret flash failed\n"); ++ } ++ ++clean: ++ ssp_cleanup(boot_context); ++ ++ if (result != 0) { ++ return result; ++ } ++ ++ return ssp_finish_process(); ++} ++ ++/* ++ * Enable the SSP processing. ++ */ ++static int ssp_enable_processing(boot_api_context_t *boot_context) ++{ ++ uint32_t val; ++ int result; ++#if STM32MP_USB_PROGRAMMER ++ struct usb_handle *pdev; ++#endif ++#if STM32MP_UART_PROGRAMMER ++ uintptr_t uart_base; ++#endif ++ ++ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) { ++ return -EINVAL; ++ } ++ ++ if (((val & SSP_OTP_MASK) == SSP_OTP_MASK) || ++ ((val & SSP_OTP_MASK) == SSP_OTP_SUCCESS)) { ++ return -EINVAL; ++ } ++ ++ if ((val & SSP_OTP_MASK) == 0U) { ++ if (bsec_program_otp(SSP_OTP_REQ, otp_ssp.idx) != BSEC_OK) { ++ return -EINVAL; ++ } ++ } ++ ++ switch (boot_context->boot_interface_selected) { ++#if STM32MP_UART_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: ++ uart_base = get_uart_address(boot_context->boot_interface_instance); ++ if (uart_base == 0U) { ++ return -EINVAL; ++ } ++ ++ result = stm32cubeprog_uart_ssp(uart_base, (uintptr_t)-1, 0, ++ (uintptr_t)NULL, 0); ++ if (result != 0) { ++ return -EINVAL; ++ } ++ break; ++#endif ++#if STM32MP_USB_PROGRAMMER ++ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: ++ /* init USB on platform */ ++ pdev = usb_dfu_plat_init(); ++ ++ result = stm32cubeprog_usb_ssp(pdev, (uintptr_t)-1, 0, ++ (uintptr_t)NULL, 0); ++ if (result != 0) { ++ return -EINVAL; ++ } ++ ++ break; ++#endif ++ default: ++ return -EINVAL; ++ } ++ ++ boot_context->p_ssp_config->ssp_cmd = ++ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK; ++ ++ return 0; ++} ++ ++/* ++ * Retrieve the current status of the SSP from bootrom context and OTP value. ++ */ ++static ssp_result_e ssp_check_status(boot_api_context_t *boot_context) ++{ ++ uint32_t otp; ++ ++ if (initialize_otp() < 0) { ++ return SSP_ERROR; ++ } ++ ++ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &otp) != 0) { ++ return SSP_ERROR; ++ } ++ ++ if ((otp & SSP_OTP_REQ) == 0U) { ++ return SSP_NONE; ++ } ++ ++ if ((otp & SSP_OTP_SUCCESS) != 0U) { ++ return SSP_DONE; ++ } ++ ++ VERBOSE("Start Get ssp_cmd : %x\n", ++ boot_context->p_ssp_config->ssp_cmd); ++ ++ switch (boot_context->p_ssp_config->ssp_cmd) { ++ case BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK: ++ INFO("Detected start SSP Phase 2\n"); ++ return SSP_GET_CERT; ++ case BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK: ++ INFO("Detected start SSP Phase 3\n"); ++ return SSP_FLASH_OEM; ++ default: ++ return SSP_NONE; ++ } ++} ++ ++/* ++ * Start the SSP processing. ++ */ ++static void ssp_start(boot_api_context_t *boot_context) ++{ ++ int result; ++ uint8_t ssp_phase = ssp_check_status(boot_context); ++ ++ switch (ssp_phase) { ++ case SSP_GET_CERT: ++ result = ssp_download_phase(boot_context); ++ if (result != 0) { ++ /* ++ * Download Phase failed, clean, reset ++ */ ++ ssp_cleanup(boot_context); ++ ++ ERROR("SSP_Error: Resetting target\n"); ++ } else { ++ /* Process completed, go to Phase 3 */ ++ boot_context->p_ssp_config->ssp_cmd = ++ BOOT_API_CTX_SSP_CMD_PROV_SECRET; ++ } ++ ++ break; ++ ++ case SSP_FLASH_OEM: ++ result = ssp_secret_programming(boot_context); ++ if (result != 0) { ++ ERROR("Error during provisionning\n"); ++ } else { ++ NOTICE("Provisioning completed\n"); ++ } ++ ++ break; ++ ++ case SSP_ERROR: ++ /* ++ * Error during bootrom SSP processing ++ */ ++ result = -EINVAL; ++ ERROR("SSP_Error: Resetting target\n"); ++ break; ++ ++ case SSP_NONE: ++ default: ++ result = ssp_enable_processing(boot_context); ++ if (result != 0) { ++ ERROR("Start SSP Failed (%i)\n", result); ++ } ++ } ++ ++ if ((result != 0) || (ssp_phase == SSP_FLASH_OEM)) { ++ goto out; ++ } ++ ++ /* ++ * Keep VDDCORE && VDD enabled if pmic used to generate ++ * the required MPSYSRST. ++ */ ++ if (dt_pmic_status() > 0) { ++ struct rdev *regul; ++ ++ regul = dt_get_cpu_regulator(); ++ if (regul == NULL) { ++ panic(); ++ } ++ ++ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) { ++ WARN("Failed to write cpu-supply reset mask\n"); ++ } ++ ++ regul = dt_get_vdd_regulator(); ++ if (regul == NULL) { ++ goto out; ++ } ++ ++ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) { ++ WARN("Failed to write vdd-supply reset mask\n"); ++ } ++ } else { ++ static const char debug_msg[] = { ++ "SSP next step will be only guarantee if the VDD\n" ++ "domain is maintained during system reset\n" ++ }; ++ ++ NOTICE("%s", debug_msg); ++ } ++ ++out: ++#ifndef DCACHE_OFF ++ if (boot_context->p_ssp_config != NULL) { ++ flush_dcache_range((uintptr_t)boot_context->p_ssp_config, ++ sizeof(boot_api_ssp_config_t)); ++ } ++#endif ++ ++ stm32mp_system_reset(); ++} ++ ++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_el3_plat_arch_setup(void) ++{ ++#if DEBUG ++ const char *board_model; ++#endif ++ uintptr_t pwr_base; ++ uintptr_t rcc_base; ++ ++ boot_api_context_t *boot_context = ++ (boot_api_context_t *)stm32mp_get_boot_ctx_address(); ++ bool serial_uart_interface __unused = ++ (boot_context->boot_interface_selected == ++ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART); ++ uintptr_t uart_prog_addr __unused; ++ ++ if (bsec_probe() != 0) { ++ panic(); ++ } ++ ++ 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_END - BL_RO_DATA_BASE, ++ MT_RO_DATA | MT_SECURE); ++#endif ++ ++ /* Prevent corruption of preloaded Device Tree */ ++ mmap_add_region(DTB_BASE, DTB_BASE, ++ DTB_LIMIT - DTB_BASE, ++ MT_RO_DATA | MT_SECURE); ++ ++ configure_mmu(); ++ ++ if (dt_open_and_check(STM32MP_DTB_BASE) < 0) { ++ panic(); ++ } ++ ++ pwr_base = stm32mp_pwr_base(); ++ rcc_base = stm32mp_rcc_base(); ++ ++ /* ++ * 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); ++ ++ while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) { ++ ; ++ } ++ ++ /* 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); ++ ++ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) == ++ 0U) { ++ ; ++ } ++ ++ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); ++ } ++ ++ /* Set minimum reset pulse duration to 31ms for discrete power supplied boards */ ++ if (dt_pmic_status() <= 0) { ++ mmio_clrsetbits_32(rcc_base + RCC_RDLSICR, RCC_RDLSICR_MRD_MASK, ++ 31U << RCC_RDLSICR_MRD_SHIFT); ++ } ++ ++ generic_delay_timer_init(); ++ ++#if STM32MP_UART_PROGRAMMER ++ uart_prog_addr = get_uart_address(boot_context->boot_interface_instance); ++ ++ /* Disable programmer UART before changing clock tree */ ++ if (serial_uart_interface) { ++ stm32_uart_stop(uart_prog_addr); ++ } ++#endif ++ ++ if (stm32mp1_clk_probe() < 0) { ++ panic(); ++ } ++ ++ if (dt_pmic_status() > 0) { ++ initialize_pmic(); ++ } ++ ++#if DEBUG ++ if (stm32mp_uart_console_setup() != 0) { ++ goto skip_console_init; ++ } ++ ++ stm32mp_print_cpuinfo(); ++ ++ board_model = dt_get_board_model(); ++ if (board_model != NULL) { ++ NOTICE("Model: %s\n", board_model); ++ } ++ ++ stm32mp_print_boardinfo(); ++ ++ if ((boot_context->p_ssp_config == NULL) || ++ (boot_context->p_ssp_config->ssp_cmd != ++ BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK)) { ++ stm32mp_print_cpuinfo(); ++ if (!stm32mp_is_auth_supported()) { ++ ERROR("Chip doesn't support SSP\n"); ++ panic(); ++ } ++ } ++ ++skip_console_init: ++#endif ++ if (stm32mp_is_closed_device()) { ++ /* Closed chip required authentication */ ++ ERROR("SSP not supported on closed chip\n"); ++ panic(); ++ } ++ ++ if (stm32_iwdg_init() < 0) { ++ panic(); ++ } ++ ++ stm32_iwdg_refresh(); ++ ++ if (dt_pmic_status() > 0) { ++ initialize_pmic_i2c(); ++ print_pmic_info_and_debug(); ++ } ++ ++ ssp_start(boot_context); ++ ++ /* This must not be reached */ ++ panic(); ++} +diff --git a/plat/st/stm32mp1/stm32mp1_ssp.mk b/plat/st/stm32mp1/stm32mp1_ssp.mk +new file mode 100644 +index 000000000..9398dc695 +--- /dev/null ++++ b/plat/st/stm32mp1/stm32mp1_ssp.mk +@@ -0,0 +1,103 @@ ++# ++# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++ ++ST_VERSION := r1.0-ssp ++VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${PLAT}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING} ++ ++# Required to use BL2_IN_XIP_MEM ++BL2_IN_XIP_MEM := 1 ++ ++SEPARATE_CODE_AND_RODATA := 1 ++ ++TRUSTED_BOARD_BOOT := 0 ++ ++# Macros and rules to build TF-A binary ++STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-ssp-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME))) ++ ++PLAT_BL_COMMON_SOURCES := common/fdt_wrappers.c \ ++ common/uuid.c \ ++ plat/st/common/stm32mp_common.c \ ++ plat/st/stm32mp1/stm32mp1_private.c ++ ++PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S ++ ++PLAT_BL_COMMON_SOURCES += drivers/regulator/regulator_core.c \ ++ drivers/st/regulator/regulator_fixed.c ++ ++PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} ++ ++PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S ++ ++PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ ++ drivers/clk/clk.c \ ++ drivers/delay_timer/delay_timer.c \ ++ drivers/delay_timer/generic_delay_timer.c \ ++ drivers/st/bsec/bsec2.c \ ++ drivers/st/clk/stm32mp_clkfunc.c \ ++ drivers/st/gpio/stm32_gpio.c \ ++ drivers/st/i2c/stm32_i2c.c \ ++ drivers/st/iwdg/stm32_iwdg.c \ ++ drivers/st/pmic/stm32mp_pmic.c \ ++ drivers/st/pmic/stpmic1.c \ ++ drivers/st/reset/stm32mp1_reset.c \ ++ plat/st/common/stm32mp_dt.c \ ++ plat/st/common/stm32mp_shres_helpers.c \ ++ plat/st/stm32mp1/stm32mp1_dbgmcu.c \ ++ plat/st/stm32mp1/stm32mp1_helper.S \ ++ plat/st/stm32mp1/stm32mp1_syscfg.c ++ ++ifeq ($(STM32MP13),1) ++PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \ ++ drivers/st/clk/clk-stm32mp13.c ++endif ++ifeq ($(STM32MP15),1) ++PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c ++endif ++ ++BL2_SOURCES := drivers/io/io_storage.c \ ++ plat/st/stm32mp1/stm32mp1_ssp.c ++ ++ifeq ($(STM32MP15),1) ++BL2_SOURCES += drivers/st/crypto/stm32_hash.c ++endif ++ ++ ++ifeq (${STM32MP_UART_PROGRAMMER},1) ++BL2_SOURCES += drivers/st/uart/stm32_uart.c \ ++ plat/st/common/stm32cubeprogrammer_uart.c ++endif ++ ++ifeq (${STM32MP_USB_PROGRAMMER},1) ++#The DFU stack uses only one end point, reduce the USB stack footprint ++$(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U)) ++BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \ ++ drivers/usb/usb_device.c \ ++ plat/st/common/stm32cubeprogrammer_usb.c \ ++ plat/st/common/usb_dfu.c \ ++ plat/st/stm32mp1/stm32mp1_usb_dfu.c ++endif ++ ++ifeq ($(STM32MP13),1) ++BL2_DTSI := stm32mp13-ssp-bl2.dtsi ++endif ++ifeq ($(STM32MP15),1) ++BL2_DTSI := stm32mp15-ssp-bl2.dtsi ++endif ++ ++check_boot_ssp: ++ @if ([ ${STM32MP_UART_PROGRAMMER} = 1 ] && [ ${STM32MP_USB_PROGRAMMER} = 1 ]) || \ ++ ([ ${STM32MP_UART_PROGRAMMER} = 0 ] && [ ${STM32MP_USB_PROGRAMMER} = 0 ]); then \ ++ echo "Error selecting serial boot device"; \ ++ false; \ ++ fi ++ ++bl2: check_boot_ssp ++ ++${BUILD_PLAT}/stm32mp1-ssp-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2 ++ @echo " SSP AS stm32mp1.S" ++ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ ++ -DDTB_BIN_PATH=\"$<\" \ ++ -c plat/st/stm32mp1/stm32mp1.S -o $@ +diff --git a/plat/st/stm32mp1/stm32mp1_stm32image_def.h b/plat/st/stm32mp1/stm32mp1_stm32image_def.h +deleted file mode 100644 +index 8efa342c1..000000000 +--- a/plat/st/stm32mp1/stm32mp1_stm32image_def.h ++++ /dev/null +@@ -1,73 +0,0 @@ +-/* +- * Copyright (C) 2021, STMicroelectronics - All Rights Reserved +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ +- +-#ifndef STM32MP1_STM32IMAGE_DEF_H +-#define STM32MP1_STM32IMAGE_DEF_H +- +-#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) +-#define STM32MP_DDR_SHMEM_SIZE U(0) +-#endif +- +-#define STM32MP_BL2_SIZE U(0x0001C000) /* 112 KB for BL2 */ +-#define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ +- +-#ifdef AARCH32_SP_OPTEE +-#define STM32MP_BL32_BASE STM32MP_SEC_SYSRAM_BASE +- +-#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ +- STM32MP_SEC_SYSRAM_SIZE - \ +- STM32MP_BL2_SIZE) +- +-/* OP-TEE loads from SYSRAM base to BL2 DTB start address */ +-#define STM32MP_OPTEE_BASE STM32MP_BL32_BASE +-#define STM32MP_OPTEE_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ +- STM32MP_BL2_SIZE - STM32MP_DTB_SIZE) +-#define STM32MP_BL32_SIZE STM32MP_OPTEE_SIZE +-#else /* AARCH32_SP_OPTEE */ +-#define STM32MP_BL32_SIZE U(0x00019000) /* 96 KB for BL32 */ +- +-#define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \ +- STM32MP_SEC_SYSRAM_SIZE - \ +- STM32MP_BL32_SIZE) +- +-#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ +- STM32MP_BL2_SIZE) +-#endif /* AARCH32_SP_OPTEE */ +- +-/* DTB initialization value */ +-#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ +- STM32MP_DTB_SIZE) +- +-/* +- * MAX_MMAP_REGIONS is usually: +- * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup +- */ +-#if defined(IMAGE_BL32) +-#define MAX_MMAP_REGIONS 6 +-#endif +- +-/******************************************************************************* +- * 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) +-#endif +- +-#define STM32MP_NAND_BL33_OFFSET U(0x00200000) +-#ifdef AARCH32_SP_OPTEE +-#define STM32MP_NAND_TEEH_OFFSET U(0x00600000) +-#define STM32MP_NAND_TEED_OFFSET U(0x00680000) +-#define STM32MP_NAND_TEEX_OFFSET U(0x00700000) +-#endif +- +-#endif /* STM32MP1_STM32IMAGE_DEF_H */ +diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c +index 793ad714a..be122730d 100644 +--- a/plat/st/stm32mp1/stm32mp1_syscfg.c ++++ b/plat/st/stm32mp1/stm32mp1_syscfg.c +@@ -4,32 +4,62 @@ + * SPDX-License-Identifier: BSD-3-Clause + */ + ++#include ++#include ++ + #include + + #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_BOOTCR 0x0CU ++#if STM32MP15 + #define SYSCFG_IOCTRLSETR 0x18U + #define SYSCFG_ICNR 0x1CU ++#endif + #define SYSCFG_CMPCR 0x20U + #define SYSCFG_CMPENSETR 0x24U + #define SYSCFG_CMPENCLRR 0x28U ++#if STM32MP13 ++#define SYSCFG_CMPSD1CR 0x30U ++#define SYSCFG_CMPSD1ENSETR 0x34U ++#define SYSCFG_CMPSD1ENCLRR 0x38U ++#define SYSCFG_CMPSD2CR 0x40U ++#define SYSCFG_CMPSD2ENSETR 0x44U ++#define SYSCFG_CMPSD2ENCLRR 0x48U ++#define SYSCFG_HSLVEN0R 0x50U ++#endif ++#define SYSCFG_IDC 0x380U ++ ++#define CMPCR_CMPENSETR_OFFSET 0x4U ++#define CMPCR_CMPENCLRR_OFFSET 0x8U + + /* + * SYSCFG_BOOTR Register + */ + #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) ++#if STM32MP15 + #define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4) + #define SYSCFG_BOOTR_BOOTPD_SHIFT 4 ++#endif ++ ++/* ++ * SYSCFG_BOOTCR Register ++ */ ++#define SYSCFG_BOOTCR_BMEN BIT(0) ++ + /* + * SYSCFG_IOCTRLSETR Register + */ +@@ -54,28 +84,185 @@ + #define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) + #define SYSCFG_CMPCR_ANSRC_SHIFT 24 + ++#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U ++ + /* + * SYSCFG_CMPENSETR Register + */ + #define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +-void stm32mp1_syscfg_init(void) ++/* ++ * HSLV definitions ++ */ ++#define HSLV_IDX_TPIU 0U ++#define HSLV_IDX_QSPI 1U ++#define HSLV_IDX_ETH1 2U ++#define HSLV_IDX_ETH2 3U ++#define HSLV_IDX_SDMMC1 4U ++#define HSLV_IDX_SDMMC2 5U ++#define HSLV_IDX_SPI1 6U ++#define HSLV_IDX_SPI2 7U ++#define HSLV_IDX_SPI3 8U ++#define HSLV_IDX_SPI4 9U ++#define HSLV_IDX_SPI5 10U ++#define HSLV_IDX_LTDC 11U ++#define HSLV_NB_IDX 12U ++ ++#define HSLV_KEY 0x1018U ++ ++/* ++ * SYSCFG_IDC Register ++ */ ++#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0) ++#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16) ++#define SYSCFG_IDC_REV_ID_SHIFT 16 ++ ++static void enable_io_comp_cell_finish(uintptr_t cmpcr_off) + { +- uint32_t bootr; +- uint32_t otp = 0; +- uint32_t vdd_voltage; ++ uint64_t start; + +- /* +- * Interconnect update : select master using the port 1. +- * LTDC = AXI_M9. +- */ +- mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); ++ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); + +- /* Disable Pull-Down for boot pin connected to VDD */ +- bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) & +- SYSCFG_BOOTR_BOOT_MASK; +- mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, +- bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); ++ while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & 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; ++ } ++ } ++ ++ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL); ++} ++ ++static void disable_io_comp_cell(uintptr_t cmpcr_off) ++{ ++ uint32_t value; ++ ++ if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) || ++ ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) & ++ SYSCFG_CMPENSETR_MPU_EN) == 0U)) { ++ return; ++ } ++ ++ value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT; ++ ++ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); ++ ++ value <<= SYSCFG_CMPCR_RANSRC_SHIFT; ++ value |= mmio_read_32(SYSCFG_BASE + cmpcr_off); ++ ++ mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL); ++ ++ mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); ++} ++ ++#if STM32MP13 ++static int get_regu_max_voltage(void *fdt, int sdmmc_node, char *regu_name, uint32_t *regu_val) ++{ ++ int node; ++ const fdt32_t *cuint; ++ ++ cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL); ++ if (cuint == NULL) { ++ return -ENODEV; ++ } ++ ++ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); ++ if (node < 0) { ++ return -ENODEV; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); ++ if (cuint == NULL) { ++ return -ENODEV; ++ } ++ ++ *regu_val = fdt32_to_cpu(*cuint); ++ ++ return 0; ++} ++ ++static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base) ++{ ++ int ret; ++ int node; ++ void *fdt = NULL; ++ uint32_t regu_max_val; ++ ++ if (fdt_get_address(&fdt) == 0) { ++ return false; ++ } ++ ++ if (fdt == NULL) { ++ return false; ++ } ++ ++ node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base); ++ if (node < 0) { ++ /* No SD or eMMC device on this instance, enable HSLV */ ++ return true; ++ } ++ ++ ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", ®u_max_val); ++ if ((ret < 0) || (regu_max_val > 1800000)) { ++ /* ++ * The vqmmc-supply property should always be present for eMMC. ++ * For SD-card, if it is not, then the card only supports 3.3V. ++ */ ++ return false; ++ } ++ ++ return true; ++} ++ ++static void enable_hslv_by_index(uint32_t index) ++{ ++ bool apply_hslv; ++ ++ assert(index < HSLV_NB_IDX); ++ ++ switch (index) { ++ case HSLV_IDX_SDMMC1: ++ apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE); ++ break; ++ case HSLV_IDX_SDMMC2: ++ apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE); ++ break; ++ default: ++ apply_hslv = true; ++ break; ++ } ++ ++ if (apply_hslv) { ++ mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + index * sizeof(uint32_t), HSLV_KEY); ++ } ++} ++#endif ++ ++static void enable_high_speed_mode_low_voltage(void) ++{ ++#if STM32MP13 ++ uint32_t idx; ++ ++ for (idx = 0U; idx < HSLV_NB_IDX; idx++) { ++ enable_hslv_by_index(idx); ++ } ++#endif ++#if STM32MP15 ++ 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); ++#endif ++} ++ ++static void stm32mp1_syscfg_set_hslv(void) ++{ ++ uint32_t otp_value; ++ uint32_t vdd_voltage; ++ bool product_below_2v5; + + /* + * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI +@@ -92,64 +279,89 @@ 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(); + + /* Check if VDD is Low Voltage */ + if (vdd_voltage == 0U) { +- WARN("VDD unknown"); ++ WARN("VDD unknown\n"); + } 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) { ++ enable_high_speed_mode_low_voltage(); ++ ++ 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"); + panic(); + } + } ++} + +- stm32mp1_syscfg_enable_io_compensation(); ++void stm32mp1_syscfg_init(void) ++{ ++#if STM32MP15 ++ uint32_t bootr; ++ ++ /* ++ * Interconnect update : select master using the port 1. ++ * LTDC = 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) & ++ SYSCFG_BOOTR_BOOT_MASK; ++ mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, ++ bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); ++#endif ++ ++ stm32mp1_syscfg_set_hslv(); ++ ++ stm32mp1_syscfg_enable_io_compensation_start(); + } + +-void stm32mp1_syscfg_enable_io_compensation(void) ++void stm32mp1_syscfg_enable_io_compensation_start(void) + { + /* + * 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 + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR, ++ SYSCFG_CMPENSETR_MPU_EN); ++#if STM32MP13 ++ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR, ++ SYSCFG_CMPENSETR_MPU_EN); ++ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR, + SYSCFG_CMPENSETR_MPU_EN); + +- while ((mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) & +- SYSCFG_CMPCR_READY) == 0U) { +- ; +- } ++#endif ++} + +- mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); ++void stm32mp1_syscfg_enable_io_compensation_finish(void) ++{ ++ enable_io_comp_cell_finish(SYSCFG_CMPCR); ++#if STM32MP13 ++ enable_io_comp_cell_finish(SYSCFG_CMPSD1CR); ++ enable_io_comp_cell_finish(SYSCFG_CMPSD2CR); ++#endif + } + + void stm32mp1_syscfg_disable_io_compensation(void) + { +- uint32_t value; ++ stm32mp1_clk_force_enable(SYSCFG); + + /* + * Deactivate automatic I/O compensation. +@@ -157,18 +369,42 @@ 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) >> +- SYSCFG_CMPCR_ANSRC_SHIFT; ++ disable_io_comp_cell(SYSCFG_CMPCR); ++#if STM32MP13 ++ disable_io_comp_cell(SYSCFG_CMPSD1CR); ++ disable_io_comp_cell(SYSCFG_CMPSD2CR); ++#endif + +- mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, +- SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); ++ stm32mp1_clk_force_disable(SYSCFG); ++} + +- value = mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) | +- (value << SYSCFG_CMPCR_RANSRC_SHIFT); ++/* ++ * @brief Get silicon revision from SYSCFG registers. ++ * @retval chip version (REV_ID). ++ */ ++uint32_t stm32mp1_syscfg_get_chip_version(void) ++{ ++ return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & ++ SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT; ++} + +- mmio_write_32(SYSCFG_BASE + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); ++/* ++ * @brief Get device ID from SYSCFG registers. ++ * @retval device ID (DEV_ID). ++ */ ++uint32_t stm32mp1_syscfg_get_chip_dev_id(void) ++{ ++ return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK; ++} + +- mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENCLRR, SYSCFG_CMPENSETR_MPU_EN); ++#if STM32MP13 ++void stm32mp1_syscfg_boot_mode_enable(void) ++{ ++ mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN); ++} + +- stm32mp1_clk_disable_non_secure(SYSCFG); ++void stm32mp1_syscfg_boot_mode_disable(void) ++{ ++ mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN); + } ++#endif +diff --git a/plat/st/stm32mp1/stm32mp1_usb_dfu.c b/plat/st/stm32mp1/stm32mp1_usb_dfu.c +index 70fbba6db..18e01cfec 100644 +--- a/plat/st/stm32mp1/stm32mp1_usb_dfu.c ++++ b/plat/st/stm32mp1/stm32mp1_usb_dfu.c +@@ -28,7 +28,12 @@ + #define USBD_CONFIGURATION_STRING "DFU Config" + #define USBD_INTERFACE_STRING "DFU Interface" + ++#if STM32MP13 ++#define USB_DFU_ITF_NUM 2 ++#endif ++#if STM32MP15 + #define USB_DFU_ITF_NUM 6 ++#endif + + #define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM) + +@@ -98,11 +103,18 @@ static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = { + /* Descriptor of DFU interface 0 Alternate setting 0..N */ + USBD_DFU_IF_DESC(0), + USBD_DFU_IF_DESC(1), ++#if USB_DFU_ITF_NUM > 2 + USBD_DFU_IF_DESC(2), ++#endif ++#if USB_DFU_ITF_NUM > 3 + USBD_DFU_IF_DESC(3), ++#endif ++#if USB_DFU_ITF_NUM > 4 + USBD_DFU_IF_DESC(4), ++#endif ++#if USB_DFU_ITF_NUM > 5 + USBD_DFU_IF_DESC(5), +- ++#endif + /* DFU Functional Descriptor */ + 0x09, /* blength = 9 Bytes */ + DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */ +@@ -115,6 +127,17 @@ static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = { + }; + + /* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */ ++#if STM32MP13 ++const char *const if_desc_string[USB_DFU_ITF_NUM] = { ++#if STM32MP_SSP ++ "@SSP /0xF3/1*512Ba", ++#else ++ "@SSBL /0x03/1*16Me", ++#endif ++ "@virtual /0xF1/1*512Ba" ++}; ++#endif ++#if STM32MP15 + const char *const if_desc_string[USB_DFU_ITF_NUM] = { + "@Partition0 /0x00/1*256Ke", + "@FSBL /0x01/1*1Me", +@@ -123,6 +146,7 @@ const char *const if_desc_string[USB_DFU_ITF_NUM] = { + "@Partition4 /0x04/1*16Me", + "@virtual /0xF1/1*512Ba" + }; ++#endif + + /* Buffer to build the unicode string provided to USB device stack */ + static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ]; +@@ -157,27 +181,28 @@ static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *le + static void update_serial_num_string(void) + { + uint8_t i; +- uint32_t result; + char serial_string[SIZ_STRING_SERIAL + 2U]; +- uint32_t deviceserial[UID_WORD_NB]; ++ /* serial number is set to 0 */ ++ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U}; ++ uint32_t otp; ++ uint32_t len; + uint16_t length; + +- for (i = 0U; i < UID_WORD_NB; i++) { +- result = bsec_shadow_register(i + UID0_OTP); +- if (result != BSEC_OK) { +- ERROR("BSEC: UID%d Shadowing Error\n", i); +- break; +- } +- result = bsec_read_otp(&deviceserial[i], i + UID0_OTP); +- if (result != BSEC_OK) { +- ERROR("BSEC: UID%d Read Error\n", i); +- break; +- } ++ 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; + } +- /* On bsec error: serial number is set to 0 */ +- if (result != BSEC_OK) { +- for (i = 0; i < UID_WORD_NB; i++) { +- deviceserial[i] = 0U; ++ ++ 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; + } + } + /* build serial number with OTP value as in ROM code */ +@@ -353,9 +378,11 @@ struct usb_handle *usb_dfu_plat_init(void) + stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle, + (uint32_t *)USB_OTG_BASE); + ++#if STM32MP15 + /* STM32MP15 = keep the configuration from ROM code */ + usb_core_handle.ep0_state = USBD_EP0_DATA_IN; + usb_core_handle.dev_state = USBD_STATE_CONFIGURED; ++#endif + + /* Update the serial number string descriptor from the unique ID */ + update_serial_num_string(); +@@ -375,12 +402,31 @@ uint8_t usb_dfu_get_phase(uint8_t alt) + uint8_t ret; + + switch (alt) { ++#if STM32MP13 ++ case 0: ++#if STM32MP_SSP ++ ret = PHASE_SSP; ++#else ++ ret = PHASE_SSBL; ++#endif ++ break; ++ case 1: ++ ret = PHASE_CMD; ++ break; ++#endif ++#if STM32MP15 ++#if STM32MP_SSP ++ case 0: ++ ret = PHASE_SSP; ++ break; ++#endif + case 3: + ret = PHASE_SSBL; + break; + case 5: + ret = PHASE_CMD; + break; ++#endif + default: + ret = PHASE_RESET; + break; +diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile +index 77d2007d5..410e0638a 100644 +--- a/tools/cert_create/Makefile ++++ b/tools/cert_create/Makefile +@@ -9,7 +9,7 @@ V ?= 0 + DEBUG := 0 + CRTTOOL ?= cert_create${BIN_EXT} + BINARY := $(notdir ${CRTTOOL}) +-OPENSSL_DIR := /usr ++OPENSSL_DIR ?= /usr + COT := tbbr + + MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +@@ -63,7 +63,7 @@ HOSTCCFLAGS += ${DEFINES} + # could get pulled in from firmware tree. + INC_DIR += -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include + LIB_DIR := -L ${OPENSSL_DIR}/lib +-LIB := -lssl -lcrypto ++LIB := -lssl -lcrypto -lpthread + + HOSTCC ?= gcc + +diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h +index 128e7f7b4..2a227dd01 100644 +--- a/tools/cert_create/include/key.h ++++ b/tools/cert_create/include/key.h +@@ -22,7 +22,8 @@ enum { + enum { + KEY_ALG_RSA, /* RSA PSS as defined by PKCS#1 v2.1 (default) */ + #ifndef OPENSSL_NO_EC +- KEY_ALG_ECDSA, ++ KEY_ALG_ECDSA_NIST, ++ KEY_ALG_ECDSA_BRAINPOOL, + #endif /* OPENSSL_NO_EC */ + KEY_ALG_MAX_NUM + }; +@@ -42,7 +43,8 @@ enum{ + static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = { + { 2048, 1024, 3072, 4096 }, /* KEY_ALG_RSA */ + #ifndef OPENSSL_NO_EC +- {} /* KEY_ALG_ECDSA */ ++ {}, /* KEY_ALG_ECDSA_NIST */ ++ {} /* KEY_ALG_ECDSA_BRAINPOOL */ + #endif /* OPENSSL_NO_EC */ + }; + +diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c +index 64359756f..e33441448 100644 +--- a/tools/cert_create/src/key.c ++++ b/tools/cert_create/src/key.c +@@ -79,11 +79,11 @@ err: + } + + #ifndef OPENSSL_NO_EC +-static int key_create_ecdsa(key_t *key, int key_bits) ++static int key_create_ecdsa(key_t *key, int key_bits, int curve_id) + { + EC_KEY *ec; + +- ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ++ ec = EC_KEY_new_by_curve_name(curve_id); + if (ec == NULL) { + printf("Cannot create EC key\n"); + goto err; +@@ -104,13 +104,25 @@ err: + EC_KEY_free(ec); + return 0; + } ++ ++static int key_create_ecdsa_nist(key_t *key, int key_bits) ++{ ++ return key_create_ecdsa(key, key_bits, NID_X9_62_prime256v1); ++} ++ ++static int key_create_ecdsa_brainpool(key_t *key, int key_bits) ++{ ++ return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1); ++} ++ + #endif /* OPENSSL_NO_EC */ + + typedef int (*key_create_fn_t)(key_t *key, int key_bits); + static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { +- key_create_rsa, /* KEY_ALG_RSA */ ++ [KEY_ALG_RSA] = key_create_rsa, + #ifndef OPENSSL_NO_EC +- key_create_ecdsa, /* KEY_ALG_ECDSA */ ++ [KEY_ALG_ECDSA_NIST] = key_create_ecdsa_nist, ++ [KEY_ALG_ECDSA_BRAINPOOL] = key_create_ecdsa_brainpool, + #endif /* OPENSSL_NO_EC */ + }; + +diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c +index b39378ca9..a91ca82dd 100644 +--- a/tools/cert_create/src/main.c ++++ b/tools/cert_create/src/main.c +@@ -84,7 +84,8 @@ static char *strdup(const char *str) + static const char *key_algs_str[] = { + [KEY_ALG_RSA] = "rsa", + #ifndef OPENSSL_NO_EC +- [KEY_ALG_ECDSA] = "ecdsa" ++ [KEY_ALG_ECDSA_NIST] = "ecdsa", ++ [KEY_ALG_ECDSA_BRAINPOOL] = "ecdsa-brainpool" + #endif /* OPENSSL_NO_EC */ + }; + +diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile +index 96dff2324..7f959abeb 100644 +--- a/tools/encrypt_fw/Makefile ++++ b/tools/encrypt_fw/Makefile +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2019-2020, Linaro Limited. All rights reserved. ++# Copyright (c) 2019-2021, Linaro Limited. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -9,7 +9,7 @@ BUILD_INFO ?= 1 + DEBUG := 0 + ENCTOOL ?= encrypt_fw${BIN_EXT} + BINARY := $(notdir ${ENCTOOL}) +-OPENSSL_DIR := /usr ++OPENSSL_DIR ?= /usr + + OBJECTS := src/encrypt.o \ + src/cmd_opt.o \ +@@ -40,7 +40,7 @@ endif + # could get pulled in from firmware tree. + INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include + LIB_DIR := -L ${OPENSSL_DIR}/lib +-LIB := -lssl -lcrypto ++LIB := -lssl -lcrypto -lpthread + + HOSTCC ?= gcc + +diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile +index 11d2e7b0b..7fc5670ee 100644 +--- a/tools/fiptool/Makefile ++++ b/tools/fiptool/Makefile +@@ -8,6 +8,7 @@ MAKE_HELPERS_DIRECTORY := ../../make_helpers/ + include ${MAKE_HELPERS_DIRECTORY}build_macros.mk + include ${MAKE_HELPERS_DIRECTORY}build_env.mk + ++OPENSSL_DIR ?= /usr + FIPTOOL ?= fiptool${BIN_EXT} + PROJECT := $(notdir ${FIPTOOL}) + OBJECTS := fiptool.o tbbr_config.o +@@ -20,7 +21,8 @@ ifeq (${DEBUG},1) + else + HOSTCCFLAGS += -O2 + endif +-LDLIBS := -lcrypto ++LIB_DIR := -L ${OPENSSL_DIR}/lib ++LDLIBS := -lcrypto -lpthread + + ifeq (${V},0) + Q := @ +@@ -48,7 +50,7 @@ all: ${PROJECT} + + ${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" +- ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS} ++ ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LIB_DIR} ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} +diff --git a/tools/fwu_gen_metadata/README.md b/tools/fwu_gen_metadata/README.md +new file mode 100644 +index 000000000..3469bda52 +--- /dev/null ++++ b/tools/fwu_gen_metadata/README.md +@@ -0,0 +1,87 @@ ++# fwumd\_tool ++Tool to create FWU Metadata struct in Python ++ ++## Getting started ++As metadata struct composition and length changes depending on how many images and how many banks you want to put in them, ++the options `--nb-img-in-banks` (or `-ni` for short) and `--nb-banks` (or `-nb` for short) may be required to format the binary data properly. ++The default values are **1 image** and **2 banks** ++ ++### From Json to binary ++`fwumd_tool.py dummy` will generate a file `dummy.json` and `dummy.bin`, containing ++dummy metadata for testing purpose. ++ ++Modify the json file with the correct metadata you want to set, then call ++`fwumd_tool.py jsonparse ` to generate the binary metadata from the given json file ++In both of these commands, passing option `-v` will dump the content of the metadata for visual ++inspection. ++ ++**The name format `_bank_` needs to be respected for images in banks** ++ ++### From binary to json ++You can dump a binary metadata file using the command `fwumd_tool.py dump ` to ++visualize the metadata in human-readable format from the binary. ++ ++You can also generate a json config file from binary data using the command `fwumd_tool.py binparse `. ++It will generate json data in which names are automatically generated. ++ ++Passing the option `--template ` to binparse allows the tool to get the config from the given json file, ++and will mimic the number of images, the number of banks, and the names given to images, banks, location. ++ ++### Test reproducible binary metadata ++Passing these commands should end up with matching checksum. ++```bash ++./fwumd_tool.py dummy ++./fwumd_tool.py binparse dummy.bin -j dummy2.json ++./fwumd_tool.py jsonparse dummy2.json -b dummy2.bin ++shasum dummy.bin dummy2.bin ++``` ++ ++## Propositions, precepts, thoughts ++- Endianness of the data contained in the struct has to either be fixed, or defined in the "configs" section of the metadata and embedded into the binary metadata ++- Discussions has been made to embed configs into the binary metadata directly, allowing for much easier validation of the data and less prone to errors ++- A list of wanted features to ease scripting with the tool should be made. ++- PEP8 rules have been applied as much as possible on the code, as well as comments & docstrings. ++ ++## TODO ++- Verify CRC32 of binary metadata file ++ ++## Json examples ++### Dummy JSON metadata ++```json ++{ ++ "metadata": { ++ "version": 0, ++ "active_index": 1, ++ "previous_active_index": 0, ++ "img_entry": { ++ "img_0": { ++ "location": "sda", ++ "img_bank_info": { ++ "img_0_bank_0": { ++ "accepted": true, ++ "reserved": 101 ++ }, ++ "img_0_bank_1": { ++ "accepted": false, ++ "reserved": 102 ++ } ++ } ++ } ++ } ++ }, ++ "uuids": { ++ "locations": { ++ "sda": "7e93078a-2dc2-4657-b496-eaf638247c5b" ++ }, ++ "entries": { ++ "img_0_bank_0": "c31fe18a-9408-49b5-a647-03113b85dc58", ++ "img_0_bank_1": "d4ccc9b2-58a0-46ed-beeb-1f37059db676", ++ "img_0": "50833315-fe46-4eb1-8c4a-b38d03684f7f" ++ } ++ }, ++ "configs": { ++ "nb_fw_img": 1, ++ "nb_fw_banks": 2 ++ } ++} ++``` +diff --git a/tools/fwu_gen_metadata/fwumd_tool.py b/tools/fwu_gen_metadata/fwumd_tool.py +new file mode 100755 +index 000000000..6a79223f8 +--- /dev/null ++++ b/tools/fwu_gen_metadata/fwumd_tool.py +@@ -0,0 +1,181 @@ ++#!/usr/bin/env python3 ++# Copyright (c) 2022, STMicroelectronics - All Rights Reserved ++# ++# SPDX-License-Identifier: BSD-3-Clause ++ ++""" ++ CLI tool to interact with the 'fwu_metadata' data structure ++ Contains files for: ++ - fwumd_tool.py: CLI management ++ - src/metadata.py: Python dict fwu_metadata ++ - src/structs.py: C-style struct fwu_metadata ++ - src/utils.py: Useful functions for all project ++ - src/uuid_t.py: Class & functions to deal with UUID ++""" ++ ++import json ++import argparse ++ ++from src.uuid_t import test_uuids ++from src.utils import test_utils ++from src.metadata import create_dummy_metadata, validate_metadata ++from src.structs import fwupd_from_dict, fwupd_to_dict ++ ++# COMMAND LINE ++ ++def cli_dummy(dummy_args): ++ """ ++ Routine for the command "dummy" passed in CLI ++ """ ++ try: ++ dummy_metadata = create_dummy_metadata(dummy_args.nb_fw_imgs, dummy_args.nb_banks) ++ assert validate_metadata(dummy_metadata) ++ fwupd = fwupd_from_dict(dummy_metadata) ++ if dummy_args.display: ++ fwupd.display() ++ json.dump(dummy_metadata, dummy_args.jsonfile, indent=4) ++ dummy_args.binfile.write(fwupd) ++ finally: ++ dummy_args.jsonfile.close() ++ dummy_args.binfile.close() ++ ++def cli_jsonparse(jsonparse_args): ++ """ ++ Routine for the command "jsonparse" passed in CLI ++ """ ++ try: ++ data = json.load(jsonparse_args.jsonfile) ++ if not validate_metadata(data): ++ raise Exception("Metadata contained in file are not correct") ++ fwupd = fwupd_from_dict(data) ++ if jsonparse_args.display: ++ fwupd.display() ++ jsonparse_args.binfile.write(fwupd) ++ finally: ++ jsonparse_args.jsonfile.close() ++ jsonparse_args.binfile.close() ++ ++def cli_binparse(binparse_args): ++ """ ++ Routine for the command "binparse" passed in CLI ++ """ ++ template_data = {"uuids": {"locations": {}, "entries": {}}} ++ dummy_metadata = create_dummy_metadata(binparse_args.nb_fw_imgs, binparse_args.nb_banks) ++ assert validate_metadata(dummy_metadata) ++ fwupd = fwupd_from_dict(dummy_metadata) ++ binparse_args.binfile.readinto(fwupd) ++ if binparse_args.display: ++ fwupd.display() ++ data = fwupd_to_dict(fwupd, binparse_args.nb_fw_imgs, ++ binparse_args.nb_banks, ++ list(template_data["uuids"]["entries"].keys()), ++ template_data["uuids"]["locations"]) ++ json.dump(data, binparse_args.jsonfile, indent=4) ++ ++ binparse_args.binfile.close() ++ binparse_args.jsonfile.close() ++ ++def cli_dump(dump_args): ++ """ ++ Routine for the "Dump" command passed in CLI ++ """ ++ try: ++ dummy_metadata = create_dummy_metadata(dump_args.nb_fw_imgs, dump_args.nb_banks) ++ fwupd = fwupd_from_dict(dummy_metadata) ++ dump_args.binfile.readinto(fwupd) ++ fwupd.display() ++ finally: ++ dump_args.binfile.close() ++ ++def cli_test(test_args): ++ """ Routine for the "Test" command passed in CLI """ ++ all_tests = [("Utils", test_utils), ("UUIDs", test_uuids)] ++ if test_args.number == -1: ++ for (key, test) in all_tests: ++ print("Test " + key) ++ test(test_args) ++ print("") ++ elif test_args.number < len(all_tests): ++ print("Test " + all_tests[test_args.number][0]) ++ all_tests[test_args.number][1](test_args) ++ else: ++ print("Tests available:") ++ for nbtest, (test, _) in enumerate(all_tests): ++ print("\t{} - Test {}".format(nbtest, test)) ++ ++def cli(): ++ """ Function parsing args, dispatching commands """ ++ parser = argparse.ArgumentParser() ++ subp = parser.add_subparsers(dest="cmd") ++ ++ # GENERAL ARGS ++ parser.add_argument("--nb-fw-imgs", "-ni", default=1, type=int, ++ help="Number of firmware images in entries") ++ parser.add_argument("--nb-banks", "-nb", default=2, type=int, ++ help="Number of firmware banks for each image") ++ ++ # DUMMY ++ dummy = subp.add_parser("dummy", ++ help="Create a JSON metadata and a binary metadata dummy files") ++ dummy.add_argument("--display", "-v", action="store_true", ++ help="Display the content of the binary metadata after creation") ++ dummy.add_argument("--jsonfile", "-j", type=argparse.FileType("w"), ++ default="dummy.json", ++ help="The JSON file where to write the dummy metadata") ++ dummy.add_argument("--binfile", "-b", type=argparse.FileType("wb"), ++ default="dummy.bin", ++ help="The binary file where to write the dummy metadata") ++ ++ # JSON PARSE ++ jsparse = subp.add_parser("jsonparse", ++ help="Parse json and creates a binary metadata file") ++ jsparse.add_argument("jsonfile", type=argparse.FileType("r"), ++ help="The JSON file where to read the metadata from") ++ jsparse.add_argument("--display", "-v", action="store_true", ++ help="Display the content of the binary metadata after creation") ++ jsparse.add_argument("--binfile", "-b", type=argparse.FileType("wb"), ++ default="fwupd.bin", ++ help="The binary file where to write the binary metadata") ++ ++ # BINPARSE ++ binparse = subp.add_parser("binparse", ++ help="Parse binary data and generates a JSON metadata file") ++ binparse.add_argument("binfile", type=argparse.FileType("rb"), ++ help="The binary file where to read the metadata from") ++ binparse.add_argument("--display", "-v", action="store_true", ++ help="Display the content of the binary metadata after creation") ++ binparse.add_argument("--jsonfile", "-j", type=argparse.FileType("w"), ++ default="fwupd.json", ++ help="The JSON file where to write the generated JSON metadata") ++ ++ # DUMP ++ dump = subp.add_parser("dump", ++ help="Read a binary metadata file and prints its data") ++ dump.add_argument("binfile", type=argparse.FileType("rb"), ++ help="The binary file where to read the metadata from") ++ ++ # TEST ++ test = subp.add_parser("test", ++ help="Perform validation tests on the tool") ++ test.add_argument("--number", "-n", type=int, default=-1, ++ help="The test nb to perform (default: all)") ++ ++ args = parser.parse_args() ++ ++ # Dispatch commands ++ if args.cmd == "dummy": ++ cli_dummy(args) ++ elif args.cmd == "jsonparse": ++ cli_jsonparse(args) ++ elif args.cmd == "binparse": ++ cli_binparse(args) ++ elif args.cmd == "dump": ++ cli_dump(args) ++ elif args.cmd == "test": ++ cli_test(args) ++ else: ++ # If no command passed, considered as faulty, print help ++ parser.print_help() ++ ++if __name__ == "__main__": ++ cli() +diff --git a/tools/fwu_gen_metadata/src/metadata.py b/tools/fwu_gen_metadata/src/metadata.py +new file mode 100644 +index 000000000..aa31f35ad +--- /dev/null ++++ b/tools/fwu_gen_metadata/src/metadata.py +@@ -0,0 +1,102 @@ ++# Copyright (c) 2022, STMicroelectronics - All Rights Reserved ++# ++# SPDX-License-Identifier: BSD-3-Clause ++ ++""" ++ metadata.py ++ Manage Python dict formatted fwu_metadata ++""" ++import uuid ++ ++def create_dummy_metadata(nb_fw_img, nb_fw_banks): ++ """ ++ This function creates a Python dict containing dummy metadata ++ Used for testing or for placeholding ++ """ ++ data = { ++ "metadata": { ++ "version": 0, ++ "active_index": 1, ++ "previous_active_index": 0, ++ "img_entry": {} ++ }, ++ "uuids": { ++ "locations": { ++ "sda": str(uuid.uuid4()), ++ }, ++ "entries": {}, ++ }, ++ "configs": { ++ "nb_fw_img": nb_fw_img, ++ "nb_fw_banks": nb_fw_banks ++ } ++ } ++ ++ entries = {} ++ for nimg in range(nb_fw_img): ++ banks = {} ++ for nbnk in range(nb_fw_banks): ++ entry_name = "img_" + str(nimg) + "_bank_" + str(nbnk) ++ banks[entry_name] = {"accepted": True, ++ "reserved": 0} ++ data["uuids"]["entries"][entry_name] = str(uuid.uuid4()) ++ ++ entries["img_" + str(nimg)] = { ++ "location": "sda", ++ "img_bank_info": banks ++ } ++ data["uuids"]["entries"]["img_" + str(nimg)] = str(uuid.uuid4()) ++ data["metadata"]["img_entry"] = entries ++ return data ++ ++def __check_md(res, cond, msg): ++ """ ++ Helper function used to validate metadata. ++ If cond is false, return False, and display message ++ """ ++ if not cond: ++ print("Metadata validation failed: '{}'".format(msg)) ++ return False ++ return res ++ ++def validate_metadata(metadata): ++ """ ++ Validate content of a Python dict metadata ++ Passes through all the data, display errors if any, ++ then return if errors got encountered ++ """ ++ res = True ++ ++ for key in ["metadata", "uuids", "configs"]: ++ res = __check_md(res, key in metadata.keys(), ++ "Key missing: {}".format(key)) ++ for conf in ["nb_fw_img", "nb_fw_banks"]: ++ res = __check_md(res, conf in metadata["configs"].keys(), "Config missing: {}".format(conf)) ++ ++ res = __check_md(res, "locations" in metadata["uuids"].keys(), "UUID type location missing") ++ res = __check_md(res, "entries" in metadata["uuids"].keys(), "UUID type entries missing") ++ res = __check_md(res, ++ len(metadata["metadata"]["img_entry"].keys()) == ++ metadata["configs"]["nb_fw_img"], ++ "Wrong number of firmware images entries") ++ ++ for iname, img in metadata["metadata"]["img_entry"].items(): ++ res = __check_md(res, iname in metadata["uuids"]["entries"].keys(), ++ "Image {} UUID not known".format(iname)) ++ ++ res = __check_md(res, ++ img["location"] in metadata["uuids"]["locations"].keys(), ++ "Location {} UUID not known".format(img["location"])) ++ ++ res = __check_md(res, ++ len(metadata["metadata"]["img_entry"] [iname]["img_bank_info"].keys()) == ++ metadata["configs"]["nb_fw_banks"], ++ "Wrong number of banks for image {}".format(iname)) ++ ++ for bname, _ in metadata["metadata"]["img_entry"][iname]["img_bank_info"].items(): ++ res = __check_md(res, bname in metadata["uuids"]["entries"], ++ "Bank {} UUID not known".format(bname)) ++ res = __check_md(res, iname + "_bank_" in bname, ++ "Bank name wrongly named") ++ ++ return res +diff --git a/tools/fwu_gen_metadata/src/structs.py b/tools/fwu_gen_metadata/src/structs.py +new file mode 100644 +index 000000000..0e58bbecd +--- /dev/null ++++ b/tools/fwu_gen_metadata/src/structs.py +@@ -0,0 +1,262 @@ ++# Copyright (c) 2022, STMicroelectronics - All Rights Reserved ++# ++# SPDX-License-Identifier: BSD-3-Clause ++ ++""" ++ structs.py ++ Manage C-style struct formatted fwu_metadata ++""" ++ ++import binascii ++ ++from ctypes import Structure, c_uint32, c_uint16, c_uint8, Array ++ ++from src.uuid_t import uuid_t, get_uuids, uuid_t_from_str ++from src.utils import get_template_location_key ++ ++# IMAGE BANK ++ ++class image_bank_info(Structure): ++ """ ++ Image bank C struct ++ """ ++ _fields_ = [ ++ ("img_uuid", uuid_t), ++ ("accepted", c_uint32), ++ ("reserved", c_uint32), ++ ] ++ ++ def from_metadata(self, bank_name, bank, uuids): ++ """ ++ Use Python-dict metadata to generate the Python / C-struct object ++ """ ++ self.img_uuid = uuid_t_from_str(get_uuids(uuids["entries"], bank_name)) ++ self.accepted = bank["accepted"] ++ self.reserved = bank.get("reserved", 0) #default value 0 if not in json ++ ++ def display(self, buff): ++ """ ++ Helper function to render the data of the bank in a buffer ++ """ ++ buff += "\t\t Image UUID: {}\n".format(str(self.img_uuid)) ++ buff += "\t\t Accepted: {}\n".format(self.accepted) ++ buff += "\t\t Reserved: {}\n".format(self.reserved) ++ return buff ++ ++ def to_dict(self, bankname, bank, uuids): ++ """ ++ Helper function to add the data contained into dicts ++ """ ++ uuids["entries"][bankname] = str(self.img_uuid) ++ bank["accepted"] = bool(self.accepted) ++ bank["reserved"] = self.reserved ++ ++# IMAGE ENTRY ++def get_struct_imgentry(nb_fw_banks): ++ """ ++ As the structure depend on a variable parameter, the Python class is ++ generated at runtime, allowing to not rely on global variables ++ """ ++ class image_entry(Structure): ++ """ ++ Image entry C struct ++ """ ++ _fields_ = [ ++ ("img_type_uuid", uuid_t), ++ ("location_uuid", uuid_t), ++ ("img_bank_info", image_bank_info * nb_fw_banks), ++ ] ++ ++ def from_metadata(self, img_name, entry, uuids): ++ """ ++ Generate this Python / C-struct object from Python dict ++ metadata ++ """ ++ self.img_type_uuid = uuid_t_from_str( ++ get_uuids(uuids["entries"], img_name)) ++ self.location_uuid = uuid_t_from_str(get_uuids(uuids["locations"], entry["location"])) ++ for n, (bank_name, bank) in enumerate(entry["img_bank_info"].items()): ++ self.img_bank_info[n].from_metadata(bank_name, bank, uuids) ++ ++ def display(self, buff): ++ """ ++ Render the data contained inside a buffer ++ """ ++ buff += "\t Image type UUID: {}\n".format(str(self.img_type_uuid)) ++ buff += "\t Location UUID: {}\n".format(str(self.location_uuid)) ++ buff += "\t --- Banks ---\n" ++ for n, bank in enumerate(self.img_bank_info): ++ buff += "\t\tBank {}\n".format(n) ++ buff = bank.display(buff) ++ return buff ++ ++ def to_dict(self, imgname, entry, uuids, imgkeys, loc_uuids): ++ """ ++ Helper function to add this struct's data into Python dict ++ metadata ++ """ ++ uuids["entries"][imgname] = str(self.img_type_uuid) ++ location_uuid_str = str(self.location_uuid) ++ loc_key = get_template_location_key(loc_uuids, location_uuid_str) ++ entry["location"] = loc_key ++ uuids["locations"][loc_key] = location_uuid_str ++ banks = {} ++ for b, bank in enumerate(self.img_bank_info): ++ bname = imgname + "_bank_" + str(b) ++ banks[bname] = {} ++ bank.to_dict(bname, banks[bname], uuids) ++ entry["img_bank_info"] = banks ++ ++ return image_entry ++ ++# FWU-Metadata struct creation ++def generate_fwu_metadata(nb_fw_img, nb_fw_banks): ++ """ ++ Generate an empty FWU-Metadata object from the given parameters ++ """ ++ class fwu_metadata(Structure): ++ """ ++ FWU Metadata C struct (parent struct) ++ """ ++ _fields_ = [ ++ ("crc_32", c_uint32), ++ ("version", c_uint32), ++ ("active_index", c_uint32), ++ ("previous_active_index", c_uint32), ++ ("img_entry", get_struct_imgentry(nb_fw_banks) * nb_fw_img) ++ ] ++ ++ def update_crc32(self): ++ """ ++ Compute and update the CRC32 from the data contained ++ """ ++ self.crc_32 = binascii.crc32(bytearray(self)[4:]) ++ ++ def from_metadata(self, metadata, uuids): ++ """ ++ Update the contained metadata from given Python dict ++ """ ++ self.version = metadata["version"] ++ self.active_index = metadata["active_index"] ++ self.previous_active_index = metadata["previous_active_index"] ++ for n, (img_name, img) in enumerate(metadata["img_entry"].items()): ++ self.img_entry[n].from_metadata(img_name, img, uuids) ++ self.update_crc32() ++ ++ def display(self): ++ """ ++ Prints a text-rendered display of the data contained ++ """ ++ buff = "METADATA\n" ++ buff += " CRC32: {}\n".format(self.crc_32) ++ buff += " Version: {}\n".format(self.version) ++ buff += " Active index: {}\n".format(self.active_index) ++ buff += " Previous active index: {}\n".format( ++ self.previous_active_index) ++ buff += " --- Image entries ---\n" ++ for n, img in enumerate(self.img_entry): ++ buff += "\tEntry {}\n".format(n) ++ buff = img.display(buff) ++ print(buff) ++ ++ def to_dict(self, metadata, uuids, imgkeys, loc_uuids): ++ """ ++ Pass the data contained in this object into Python dicts ++ """ ++ metadata["crc_32"] = self.crc_32 ++ metadata["version"] = self.version ++ metadata["active_index"] = self.active_index ++ metadata["previous_active_index"] = self.previous_active_index ++ entries = {} ++ for n, img in enumerate(self.img_entry): ++ iname = imgkeys[n] ++ entries[iname] = {} ++ img.to_dict(iname, entries[iname], uuids, imgkeys, loc_uuids) ++ metadata["img_entry"] = entries ++ ++ return fwu_metadata() ++ ++def fwupd_from_dict(data): ++ """ ++ Return a fwu_metadata object from a complete Python dict as saved in ++ the JSON file ++ """ ++ fwupd = generate_fwu_metadata( ++ data["configs"]["nb_fw_img"], ++ data["configs"]["nb_fw_banks"]) ++ fwupd.from_metadata(data["metadata"], data["uuids"]) ++ return fwupd ++ ++def fwupd_to_dict(fwupd, nb_fw_imgs, nb_banks, images_keys, loc_uuids): ++ """ ++ Create a Python dict containing all the information contained in a ++ fwu_metadata object ++ """ ++ data = {"metadata": {}, "uuids": {"locations": {}, "entries": {}}, ++ "configs": { ++ "nb_fw_img": nb_fw_imgs, ++ "nb_fw_banks": nb_banks ++ }, ++ } ++ images_keys += ["img_" + str(n) for n in range(max(0, nb_fw_imgs - len(images_keys)))] ++ ++ fwupd.to_dict(data["metadata"], data["uuids"], images_keys, loc_uuids) ++ return data ++ ++def __check_same(res, name, mdel, binel): ++ """ ++ Helper function for binary metadata cross-validation with JSON ++ ++ If @mdel (JSON) and @binel (Binary) are not the same, return False ++ and display a formatted error with the given @name. ++ Else return @res ++ """ ++ if str(mdel) != str(binel): ++ print("Element '{}' are not the same in metadata and binary data".format(name)) ++ return False ++ else: ++ return res ++ ++def validate_fwupd_and_dict(md, fwupd): ++ """ ++ Validation function for binary + JSON metadata ++ Ensure the data of the both formats are the same ++ ++ Do not check CRC32 ++ """ ++ res = True ++ ++ # Check elements of fwu_metadata struct ++ for key in ["version", "active_index", "previous_active_index"]: ++ res = __check_same(res, key, md["metadata"][key], getattr(fwupd, key)) ++ ++ # Check elements in each image entry ++ for n, (img_name, img) in enumerate(md["metadata"]["img_entry"].items()): ++ entry = fwupd.img_entry[n] ++ ++ res = __check_same(res, "Image {} type UUID".format(img_name), ++ md["uuids"]["entries"][img_name], ++ entry.img_type_uuid) ++ ++ res = __check_same(res, "Location UUID", ++ md["uuids"]["locations"][img["location"]], ++ entry.location_uuid) ++ ++ # Check elements in each banks of image entry ++ for b, (bname, bank) in enumerate(img["img_bank_info"].items()): ++ fwbank = entry.img_bank_info[b] ++ res = __check_same(res, "Image {} Bank {} UUID".format( ++ img_name, b), ++ md["uuids"]["entries"][bname], ++ fwbank.img_uuid) ++ ++ res = __check_same(res, "Image {} Bank {} Accepted".format( ++ img_name, b), ++ bank["accepted"], ++ bool(fwbank.accepted)) ++ ++ res = __check_same(res, "Image {} Bank {} Reserved field".format( ++ img_name, b), ++ bank["reserved"], ++ fwbank.reserved) ++ return res +diff --git a/tools/fwu_gen_metadata/src/utils.py b/tools/fwu_gen_metadata/src/utils.py +new file mode 100644 +index 000000000..e994e9a38 +--- /dev/null ++++ b/tools/fwu_gen_metadata/src/utils.py +@@ -0,0 +1,69 @@ ++# Copyright (c) 2022, STMicroelectronics - All Rights Reserved ++# ++# SPDX-License-Identifier: BSD-3-Clause ++ ++""" ++ utils.py ++ Useful functions for the whole project ++""" ++from ctypes import c_uint8 ++ ++# Number manipulation ++def uint8array_to_number(uint8array): ++ """ Convert array of uint8_t into a single Python number """ ++ return sum([x << (i*8) for i, x in enumerate(reversed(uint8array))]) ++ ++def number_to_uint8array(number, array_length): ++ """ Convert a single Python number into an array of uint8_t """ ++ uint8array = c_uint8 * array_length ++ array = [(number & (0xff << (n*8))) >> (n*8) ++ for n in reversed(range(array_length)) ++ ] ++ return uint8array(*array) ++ ++def test_number_to_array(args): ++ """ Test back and forth conversion works for our use case""" ++ numbers = [0x42053497, 0x45] ++ for number in numbers: ++ a = number_to_uint8array(number, 4) ++ n = uint8array_to_number(a) ++ print_and_assert(number, n) ++ ++# Default values creation ++def get_template_location_key(locations, uuid): ++ """ ++ Get the location key of the given location. ++ If it doesn't exist, generate one from the UUID ++ """ ++ if uuid in locations.values(): ++ return [key for key, val in locations.items() if val == uuid][0] ++ else: ++ key = "loc_" + uuid.replace("-", "_") ++ locations[key] = uuid ++ return key ++ ++def test_template_location_key(args): ++ """ Test location key getter works well """ ++ print_and_assert(get_template_location_key({"sda": "uuid"}, "uuid"), ++ "sda") ++ print_and_assert(get_template_location_key({"sda": "uuid"}, "new"), ++ "loc_new") ++ print_and_assert(get_template_location_key({"sda": "uuid"}, "sda-2"), ++ "loc_sda_2") ++ ++# Testing utils ++def print_and_assert(el1, el2): ++ """ Print the two values to test, then assert their equality""" ++ print(el1, "==", el2) ++ assert el1 == el2 ++ ++def test_utils(args): ++ all_tests = { ++ "Number to array": test_number_to_array, ++ "Template location key": test_template_location_key ++ } ++ ++ for (key, test) in all_tests.items(): ++ print("--- Test " + key) ++ test(args) ++ print("---\n") +diff --git a/tools/fwu_gen_metadata/src/uuid_t.py b/tools/fwu_gen_metadata/src/uuid_t.py +new file mode 100644 +index 000000000..8f9a891af +--- /dev/null ++++ b/tools/fwu_gen_metadata/src/uuid_t.py +@@ -0,0 +1,79 @@ ++# Copyright (c) 2022, STMicroelectronics - All Rights Reserved ++# ++# SPDX-License-Identifier: BSD-3-Clause ++ ++import uuid ++from ctypes import Structure, c_uint32, c_uint16, c_uint8, Array ++ ++from src.utils import uint8array_to_number, number_to_uint8array ++from src.utils import print_and_assert ++ ++UUID_NODE_LEN = 6 ++UUID_STR_LEN = 24 + (UUID_NODE_LEN*2) ++ ++# UUIDS ++ ++class uuid_t(Structure): ++ """ ++ C-style struct for the UUID data ++ """ ++ _fields_ = [ ++ ("time_low", c_uint32), ++ ("time_mid", c_uint16), ++ ("time_hi_and_version", c_uint16), ++ ("clock_seq_hi_and_reserved", c_uint8), ++ ("clock_seq_low", c_uint8), ++ ("node", c_uint8 * UUID_NODE_LEN) ++ ] ++ ++ def to_uuid_class(self): ++ """ ++ Helper function to convert the Python / C struct into the class ++ UUID from the library uuid, much easier to use. ++ """ ++ return uuid.UUID(fields=( ++ self.time_low, self.time_mid, self.time_hi_and_version, ++ self.clock_seq_hi_and_reserved, self.clock_seq_low, ++ uint8array_to_number(self.node))) ++ ++ def __str__(self): ++ """ Display this class as a normalized UUID string """ ++ return self.to_uuid_class().__str__() ++ ++def uuid_t_from_str(uuid_str): ++ """ ++ Generate a Python / C-struct uuid_t class from a normalized uuid string ++ """ ++ if len(uuid_str) != UUID_STR_LEN: ++ raise Exception("Wrong formatted UUID str: {}".format(uuid_str)) ++ obj = uuid.UUID(uuid_str) ++ return uuid_t( ++ obj.time_low, ++ obj.time_mid, ++ obj.time_hi_version, ++ obj.clock_seq_hi_variant, ++ obj.clock_seq_low, ++ number_to_uint8array(obj.node, UUID_NODE_LEN)) ++ ++def get_uuids(uuids, key): ++ """ ++ Get the UUID of a certain key, generate a new one if none is ++ found for the key ++ """ ++ # TODO Is there a context in which auto-generation of missing UUID ++ # is not desirable ? ++ if key not in uuids.keys(): ++ uuids[key] = str(uuid.uuid4()) ++ return uuids[key] ++ ++def validate_uuid(uuid_str): ++ try: ++ uuid.UUID(uuid_str) ++ return True ++ except ValueError: ++ return False ++ ++def test_uuids(args): ++ uuid_str = "737d3401-64c1-4584-a40d-29f2238c82cf" ++ uuid_t = uuid_t_from_str(uuid_str) ++ print_and_assert(str(uuid_t), uuid_str) +diff --git a/tools/fwu_gen_metadata/tests/testall.sh b/tools/fwu_gen_metadata/tests/testall.sh +new file mode 100755 +index 000000000..7b3050d3f +--- /dev/null ++++ b/tools/fwu_gen_metadata/tests/testall.sh +@@ -0,0 +1,21 @@ ++#!/bin/bash ++ ++VERBOSE=0 ++SEPARATOR="\033[94m-------------------------------------------------------------------------\033[0m" ++if [ $VERBOSE -eq 1 ]; then ++ set -eux ++ OPTS=-v ++else ++ set -e ++ OPTS= ++fi ++ ++rm -f dummy.bin dummy.json a.bin a.json ++ ++../fwumd_tool.py dummy $OPTS ++echo -e "$SEPARATOR" ++../fwumd_tool.py jsonparse $OPTS dummy.json -b a.bin ++echo -e "$SEPARATOR" ++../fwumd_tool.py binparse $OPTS dummy.bin -j a.json ++echo -e "$SEPARATOR" ++../fwumd_tool.py test $OPTS +diff --git a/tools/fwu_gen_metadata/tests/validate_stable.sh b/tools/fwu_gen_metadata/tests/validate_stable.sh +new file mode 100755 +index 000000000..957a833b6 +--- /dev/null ++++ b/tools/fwu_gen_metadata/tests/validate_stable.sh +@@ -0,0 +1,8 @@ ++#!/bin/bash ++ ++set -e ++rm -f dummy* ++../fwumd_tool.py dummy ++../fwumd_tool.py binparse dummy.bin -j dummy2.json ++../fwumd_tool.py jsonparse dummy2.json -b dummy2.bin ++shasum dummy*.bin +diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c +index fb1dee072..dd2df1253 100644 +--- a/tools/stm32image/stm32image.c ++++ b/tools/stm32image/stm32image.c +@@ -22,16 +22,16 @@ + #define VER_MINOR 1 + #define VER_VARIANT 0 + #define HEADER_VERSION_V1 0x1 +-#define TF_BINARY_TYPE 0x10 ++#define HEADER_VERSION_V2 0x2 ++#define PADDING_HEADER_MAGIC __be32_to_cpu(0x5354FFFF) ++#define PADDING_HEADER_FLAG (1 << 31) ++#define PADDING_HEADER_LENGTH 0x180 + +-/* Default option : bit0 => no signature */ +-#define HEADER_DEFAULT_OPTION (__cpu_to_le32(0x00000001)) +- +-struct stm32_header { ++struct stm32_header_v1 { + uint32_t magic_number; + uint8_t image_signature[64]; + uint32_t image_checksum; +- uint8_t header_version[4]; ++ uint8_t header_version[4]; + uint32_t image_length; + uint32_t image_entry_point; + uint32_t reserved1; +@@ -45,31 +45,50 @@ struct stm32_header { + uint8_t binary_type; + }; + +-static void stm32image_default_header(struct stm32_header *ptr) ++struct stm32_header_v2 { ++ uint32_t magic_number; ++ uint8_t image_signature[64]; ++ uint32_t image_checksum; ++ uint8_t header_version[4]; ++ uint32_t image_length; ++ uint32_t image_entry_point; ++ uint32_t reserved1; ++ uint32_t load_address; ++ uint32_t reserved2; ++ uint32_t version_number; ++ uint32_t extension_flags; ++ uint32_t extension_headers_length; ++ uint32_t binary_type; ++ uint8_t padding[16]; ++ uint32_t extension_header_type; ++ uint32_t extension_header_length; ++ uint8_t extension_padding[376]; ++}; ++ ++static void stm32image_default_header(void *ptr) + { +- if (!ptr) { ++ struct stm32_header_v1 *header = (struct stm32_header_v1 *)ptr; ++ ++ if (!header) { + return; + } + +- ptr->magic_number = HEADER_MAGIC; +- ptr->option_flags = HEADER_DEFAULT_OPTION; +- ptr->ecdsa_algorithm = __cpu_to_le32(1); +- ptr->version_number = __cpu_to_le32(0); +- ptr->binary_type = TF_BINARY_TYPE; ++ header->magic_number = HEADER_MAGIC; ++ header->version_number = __cpu_to_le32(0); + } + +-static uint32_t stm32image_checksum(void *start, uint32_t len) ++static uint32_t stm32image_checksum(void *start, uint32_t len, ++ uint32_t header_size) + { + uint32_t csum = 0; +- uint32_t hdr_len = sizeof(struct stm32_header); + uint8_t *p; + +- if (len < hdr_len) { ++ if (len < header_size) { + return 0; + } + +- p = (unsigned char *)start + hdr_len; +- len -= hdr_len; ++ p = (unsigned char *)start + header_size; ++ len -= header_size; + + while (len > 0) { + csum += *p; +@@ -82,7 +101,8 @@ static uint32_t stm32image_checksum(void *start, uint32_t len) + + static void stm32image_print_header(const void *ptr) + { +- struct stm32_header *stm32hdr = (struct stm32_header *)ptr; ++ struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; ++ struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; + + printf("Image Type : ST Microelectronics STM32 V%d.%d\n", + stm32hdr->header_version[VER_MAJOR], +@@ -95,40 +115,87 @@ static void stm32image_print_header(const void *ptr) + __le32_to_cpu(stm32hdr->image_entry_point)); + printf("Checksum : 0x%08x\n", + __le32_to_cpu(stm32hdr->image_checksum)); +- printf("Option : 0x%08x\n", +- __le32_to_cpu(stm32hdr->option_flags)); +- printf("Version : 0x%08x\n", ++ ++ switch (stm32hdr->header_version[VER_MAJOR]) { ++ case HEADER_VERSION_V1: ++ printf("Option : 0x%08x\n", ++ __le32_to_cpu(stm32hdr->option_flags)); ++ break; ++ ++ case HEADER_VERSION_V2: ++ printf("Extension : 0x%08x\n", ++ __le32_to_cpu(stm32hdr_v2->extension_flags)); ++ break; ++ ++ default: ++ printf("Incorrect header version\n"); ++ } ++ ++ printf("Version : 0x%08x\n", + __le32_to_cpu(stm32hdr->version_number)); + } + +-static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, +- uint32_t loadaddr, uint32_t ep, uint32_t ver, +- uint32_t major, uint32_t minor) ++static int stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, ++ uint32_t loadaddr, uint32_t ep, uint32_t ver, ++ uint32_t major, uint32_t minor, ++ uint32_t binary_type, uint32_t header_size) + { +- struct stm32_header *stm32hdr = (struct stm32_header *)ptr; ++ struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; ++ struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; ++ uint32_t ext_size = 0U; ++ uint32_t ext_flags = 0U; + +- stm32image_default_header(stm32hdr); ++ stm32image_default_header(ptr); + + 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)); ++ header_size); + stm32hdr->image_checksum = +- __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size)); ++ __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size, ++ header_size)); ++ ++ switch (stm32hdr->header_version[VER_MAJOR]) { ++ case HEADER_VERSION_V1: ++ /* Default option for header v1 : bit0 => no signature */ ++ stm32hdr->option_flags = __cpu_to_le32(0x00000001); ++ stm32hdr->ecdsa_algorithm = __cpu_to_le32(1); ++ stm32hdr->binary_type = (uint8_t)binary_type; ++ break; ++ ++ case HEADER_VERSION_V2: ++ stm32hdr_v2->binary_type = binary_type; ++ ext_size += PADDING_HEADER_LENGTH; ++ ext_flags |= PADDING_HEADER_FLAG; ++ stm32hdr_v2->extension_flags = ++ __cpu_to_le32(ext_flags); ++ stm32hdr_v2->extension_headers_length = ++ __cpu_to_le32(ext_size); ++ stm32hdr_v2->extension_header_type = PADDING_HEADER_MAGIC; ++ stm32hdr_v2->extension_header_length = ++ __cpu_to_le32(PADDING_HEADER_LENGTH); ++ break; ++ ++ default: ++ return -1; ++ } ++ + stm32hdr->version_number = __cpu_to_le32(ver); ++ ++ return 0; + } + + static int stm32image_create_header_file(char *srcname, char *destname, + uint32_t loadaddr, uint32_t entry, + uint32_t version, uint32_t major, +- uint32_t minor) ++ uint32_t minor, uint32_t binary_type) + { +- int src_fd, dest_fd; ++ int src_fd, dest_fd, header_size; + struct stat sbuf; + unsigned char *ptr; +- struct stm32_header stm32image_header; ++ void *stm32image_header; + + dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); + if (dest_fd == -1) { +@@ -154,15 +221,32 @@ static int stm32image_create_header_file(char *srcname, char *destname, + return -1; + } + +- memset(&stm32image_header, 0, sizeof(struct stm32_header)); ++ switch (major) { ++ case HEADER_VERSION_V1: ++ stm32image_header = malloc(sizeof(struct stm32_header_v1)); ++ header_size = sizeof(struct stm32_header_v1); ++ break; ++ ++ case HEADER_VERSION_V2: ++ stm32image_header = malloc(sizeof(struct stm32_header_v2)); ++ header_size = sizeof(struct stm32_header_v2); ++ break; + +- if (write(dest_fd, &stm32image_header, sizeof(struct stm32_header)) != +- sizeof(struct stm32_header)) { ++ default: ++ return -1; ++ } ++ ++ memset(stm32image_header, 0, header_size); ++ if (write(dest_fd, stm32image_header, header_size) != ++ header_size) { + fprintf(stderr, "Write error %s: %s\n", destname, + strerror(errno)); ++ free(stm32image_header); + return -1; + } + ++ free(stm32image_header); ++ + if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) { + fprintf(stderr, "Write error on %s: %s\n", destname, + strerror(errno)); +@@ -184,8 +268,11 @@ static int stm32image_create_header_file(char *srcname, char *destname, + return -1; + } + +- stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, entry, version, +- major, minor); ++ if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, ++ entry, version, major, minor, ++ binary_type, header_size) != 0) { ++ return -1; ++ } + + stm32image_print_header(ptr); + +@@ -196,13 +283,22 @@ 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 opt; ++ int loadaddr = -1; ++ int entry = -1; ++ int err = 0; ++ int version = 0; ++ int binary_type = -1; ++ int major = HEADER_VERSION_V2; + int minor = 0; +- char *dest = NULL, *src = NULL; ++ char *dest = NULL; ++ char *src = NULL; + +- while ((opt = getopt(argc, argv, ":s:d:l:e:v:m:n:")) != -1) { ++ while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) { + switch (opt) { ++ case 'b': ++ binary_type = strtol(optarg, NULL, 0); ++ break; + case 's': + src = optarg; + break; +@@ -226,7 +322,7 @@ int main(int argc, char *argv[]) + break; + default: + fprintf(stderr, +- "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor]\n", ++ "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n", + argv[0]); + return -1; + } +@@ -252,8 +348,14 @@ int main(int argc, char *argv[]) + return -1; + } + ++ if (binary_type == -1) { ++ fprintf(stderr, "Missing -b option\n"); ++ return -1; ++ } ++ + err = stm32image_create_header_file(src, dest, loadaddr, +- entry, version, major, minor); ++ entry, version, major, minor, ++ binary_type); + + return err; + } +-- +2.25.1 + diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-v2.4-stm32mp-r1.1-rc1.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-v2.4-stm32mp-r1.1-rc1.patch deleted file mode 100644 index f95af48..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-v2.4-stm32mp-r1.1-rc1.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 903a55e874e91ccd1fb435bea3a675e2eb4257fa Mon Sep 17 00:00:00 2001 -From: Romuald JEANNE -Date: Wed, 2 Jun 2021 16:45:18 +0200 -Subject: [PATCH 2/3] v2.4-stm32mp-r1.1-rc1 - ---- - docs/plat/stm32mp1.rst | 9 ++++++--- - drivers/st/clk/stm32mp1_clk.c | 4 ++-- - include/drivers/st/stm32mp1_rcc.h | 16 ++++++++++++++++ - plat/st/common/stm32mp_crypto_lib.c | 5 ++++- - plat/st/stm32mp1/stm32mp1_def.h | 2 ++ - plat/st/stm32mp1/stm32mp1_helper.S | 13 +++++++++++++ - 6 files changed, 43 insertions(+), 6 deletions(-) - -diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst -index fb7afdbbb0..95f4a186f5 100644 ---- a/docs/plat/stm32mp1.rst -+++ b/docs/plat/stm32mp1.rst -@@ -153,7 +153,10 @@ To build TF-A BL2 with its STM32 header for SD-card boot: - .. code:: bash - - make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ -- DTB_FILE_NAME=stm32mp157c-ev1.dtb -+ DTB_FILE_NAME=stm32mp157c-ev1.dtb STM32MP_SDMMC=1 -+ -+For other boot devices, you have to replace STM32MP_SDMMC in the previous command -+with the desired devive flag. - - This BL2 is independent of the BL32 used (SP_min or OP-TEE) - -@@ -204,14 +207,14 @@ __________________ - --nt-fw /u-boot-nodtb.bin \ - --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \ - --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \ -- --hw-config /u-boot.dtb -+ --hw-config /u-boot.dtb \ - --fw-config build/stm32mp1/debug/fdts/fw-config.dtb - - tools/fiptool/fiptool create --tos-fw /tee-header_v2.bin \ - --tos-fw-extra1 /tee-pager_v2.bin \ - --tos-fw-extra2 /tee-pageable_v2.bin \ - --nt-fw /u-boot-nodtb.bin \ -- --hw-config /uboot-nodtb.dtb \ -+ --hw-config /u-boot.dtb \ - --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \ - --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \ - --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \ -diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c -index 00954cb2e8..d074a1568c 100644 ---- a/drivers/st/clk/stm32mp1_clk.c -+++ b/drivers/st/clk/stm32mp1_clk.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -1853,7 +1853,7 @@ static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) - (clksrc != (uint32_t)CLK_RTC_DISABLED)) { - mmio_clrsetbits_32(address, - RCC_BDCR_RTCSRC_MASK, -- clksrc << RCC_BDCR_RTCSRC_SHIFT); -+ (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); - - mmio_setbits_32(address, RCC_BDCR_RTCCKEN); - } -diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h -index feaac43a13..616051e772 100644 ---- a/include/drivers/st/stm32mp1_rcc.h -+++ b/include/drivers/st/stm32mp1_rcc.h -@@ -576,6 +576,22 @@ - #define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) - #define RCC_FMCCKSELR_FMCSRC_SHIFT 0 - -+/* RCC_APB1RSTSETR register fields */ -+#define RCC_APB1RSTSETR_USART2RST BIT(14) -+#define RCC_APB1RSTSETR_USART3RST BIT(15) -+#define RCC_APB1RSTSETR_UART4RST BIT(16) -+#define RCC_APB1RSTSETR_UART5RST BIT(17) -+#define RCC_APB1RSTSETR_UART7RST BIT(18) -+#define RCC_APB1RSTSETR_UART8RST BIT(19) -+ -+/* RCC_APB1RSTCLRR register fields */ -+#define RCC_APB1RSTCLRR_USART2RST BIT(14) -+#define RCC_APB1RSTCLRR_USART3RST BIT(15) -+#define RCC_APB1RSTCLRR_UART4RST BIT(16) -+#define RCC_APB1RSTCLRR_UART5RST BIT(17) -+#define RCC_APB1RSTCLRR_UART7RST BIT(18) -+#define RCC_APB1RSTCLRR_UART8RST BIT(19) -+ - /* RCC_USBCKSELR register fields */ - #define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) - #define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 -diff --git a/plat/st/common/stm32mp_crypto_lib.c b/plat/st/common/stm32mp_crypto_lib.c -index de9601d2b8..9582162813 100644 ---- a/plat/st/common/stm32mp_crypto_lib.c -+++ b/plat/st/common/stm32mp_crypto_lib.c -@@ -40,6 +40,7 @@ static void crypto_lib_init(void) - { - boot_api_context_t *boot_context = - (boot_api_context_t *)stm32mp_get_boot_ctx_address(); -+ int ret; - - if (!stm32mp_is_auth_supported()) { - return; -@@ -48,7 +49,9 @@ static void crypto_lib_init(void) - auth_ops.verify_signature = - boot_context->bootrom_ecdsa_verify_signature; - -- if (stm32_hash_register() != 0) { -+ ret = stm32_hash_register(); -+ if (ret != 0) { -+ ERROR("HASH init (%d)\n", ret); - panic(); - } - } -diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h -index 027dba1bde..326b227842 100644 ---- a/plat/st/stm32mp1/stm32mp1_def.h -+++ b/plat/st/stm32mp1/stm32mp1_def.h -@@ -433,6 +433,8 @@ enum ddr_type { - #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 -+#define DEBUG_UART_RST_REG RCC_APB1RSTSETR -+#define DEBUG_UART_RST_BIT RCC_APB1RSTSETR_UART4RST - - /******************************************************************************* - * STM32MP1 ETZPC -diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S -index bc2d73cebb..315a67f2cf 100644 ---- a/plat/st/stm32mp1/stm32mp1_helper.S -+++ b/plat/st/stm32mp1/stm32mp1_helper.S -@@ -245,6 +245,19 @@ endfunc plat_my_core_pos - * --------------------------------------------- - */ - func plat_crash_console_init -+ /* Reset UART peripheral */ -+ ldr r1, =(RCC_BASE + DEBUG_UART_RST_REG) -+ ldr r2, =DEBUG_UART_RST_BIT -+ str r2, [r1] -+1: -+ ldr r0, [r1] -+ ands r0, r2 -+ beq 1b -+ str r2, [r1, #4] /* RSTCLR register */ -+2: -+ ldr r0, [r1] -+ ands r0, r2 -+ bne 2b - /* Enable GPIOs for UART TX */ - ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) - ldr r2, [r1] --- -2.17.1 - diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-v2.4-stm32mp-r2.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-v2.4-stm32mp-r2.patch deleted file mode 100644 index 29fbae7..0000000 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-v2.4-stm32mp-r2.patch +++ /dev/null @@ -1,8216 +0,0 @@ -From 1fe2b03c3d3ef5e550fefe361f69bff86bddf698 Mon Sep 17 00:00:00 2001 -From: Romuald JEANNE -Date: Thu, 28 Oct 2021 15:51:21 +0200 -Subject: [PATCH] v2.4-stm32mp-r2 - ---- - bl32/tsp/aarch64/tsp_entrypoint.S | 22 +- - docs/license.rst | 10 + - drivers/mtd/nand/spi_nand.c | 8 +- - drivers/regulator/regulator_core.c | 1142 +++++++++++++++++ - drivers/st/clk/stm32mp1_clk.c | 29 +- - drivers/st/ddr/stm32mp1_ddr.c | 11 +- - drivers/st/ddr/stm32mp1_ram.c | 169 +-- - drivers/st/ddr/stm32mp_ddr_test.c | 148 +++ - drivers/st/fmc/stm32_fmc2_nand.c | 11 +- - drivers/st/gpio/stm32_gpio.c | 9 +- - drivers/st/mmc/stm32_sdmmc2.c | 16 +- - drivers/st/pmic/stm32mp_pmic.c | 718 +++++------ - drivers/st/pmic/stpmic1.c | 158 ++- - drivers/st/regulator/regulator_fixed.c | 91 ++ - .../st/regulator/stm32mp_dummy_regulator.c | 27 - - drivers/st/regulator/stm32mp_regulator.c | 38 - - drivers/st/tamper/stm32_tamp.c | 691 +++++++--- - drivers/st/uart/aarch32/stm32_console.S | 11 +- - fdts/stm32mp15-ddr-512m-fw-config.dts | 63 - - fdts/stm32mp15-ddr.dtsi | 266 ++-- - fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 6 +- - fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 6 +- - ...-fw-config.dts => stm32mp15-fw-config.dts} | 25 +- - fdts/stm32mp151.dtsi | 18 + - fdts/stm32mp157a-avenger96-fw-config.dts | 3 +- - fdts/stm32mp157a-dk1-fw-config.dts | 3 +- - fdts/stm32mp157a-ed1-fw-config.dts | 3 +- - fdts/stm32mp157a-ev1-fw-config.dts | 3 +- - fdts/stm32mp157c-dk2-fw-config.dts | 3 +- - fdts/stm32mp157c-ed1-fw-config.dts | 3 +- - fdts/stm32mp157c-ev1-fw-config.dts | 3 +- - fdts/stm32mp157d-dk1-fw-config.dts | 3 +- - fdts/stm32mp157d-ed1-fw-config.dts | 3 +- - fdts/stm32mp157d-ev1-fw-config.dts | 3 +- - fdts/stm32mp157f-dk2-fw-config.dts | 3 +- - fdts/stm32mp157f-ed1-fw-config.dts | 3 +- - fdts/stm32mp157f-ev1-fw-config.dts | 3 +- - fdts/stm32mp15xx-dkx.dtsi | 8 +- - fdts/stm32mp15xx-edx.dtsi | 8 +- - include/arch/aarch32/el3_common_macros.S | 13 +- - include/arch/aarch64/el3_common_macros.S | 15 +- - include/drivers/regulator.h | 160 +++ - include/drivers/st/regulator_fixed.h | 12 + - include/drivers/st/stm32_gpio.h | 3 +- - include/drivers/st/stm32_sdmmc2.h | 4 +- - include/drivers/st/stm32_tamp.h | 311 +++-- - include/drivers/st/stm32mp1_ddr_regs.h | 1 + - include/drivers/st/stm32mp1_rcc.h | 2 + - include/drivers/st/stm32mp_ddr_test.h | 15 + - include/drivers/st/stm32mp_dummy_regulator.h | 14 - - include/drivers/st/stm32mp_pmic.h | 46 +- - include/drivers/st/stm32mp_regulator.h | 31 - - include/drivers/st/stpmic1.h | 28 + - .../interrupt-controller/arm-gic.h | 19 +- - .../dt-bindings/interrupt-controller/irq.h | 23 + - lib/aarch32/misc_helpers.S | 4 +- - licenses/LICENSE.MIT | 21 + - plat/st/common/bl2_io_storage.c | 10 +- - plat/st/common/include/stm32cubeprogrammer.h | 3 - - plat/st/common/include/stm32mp_common.h | 15 +- - plat/st/common/include/stm32mp_dt.h | 6 +- - plat/st/common/stm32cubeprogrammer_uart.c | 21 +- - plat/st/common/stm32mp_common.c | 94 +- - plat/st/common/stm32mp_dt.c | 86 +- - plat/st/common/stm32mp_trusted_boot.c | 2 +- - plat/st/stm32mp1/bl2_plat_setup.c | 49 +- - .../stm32mp1/include/stm32mp1_critic_power.h | 8 +- - plat/st/stm32mp1/include/stm32mp1_private.h | 4 +- - plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 61 +- - plat/st/stm32mp1/platform.mk | 23 +- - plat/st/stm32mp1/services/bsec_svc.c | 11 +- - plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 1 + - plat/st/stm32mp1/sp_min/sp_min_setup.c | 157 +-- - plat/st/stm32mp1/stm32mp1_context.c | 16 +- - plat/st/stm32mp1/stm32mp1_critic_power.c | 49 +- - .../stm32mp1/stm32mp1_critic_power_wrapper.S | 16 +- - plat/st/stm32mp1/stm32mp1_def.h | 23 +- - plat/st/stm32mp1/stm32mp1_helper.S | 4 +- - plat/st/stm32mp1/stm32mp1_low_power.c | 51 +- - plat/st/stm32mp1/stm32mp1_pm.c | 7 +- - plat/st/stm32mp1/stm32mp1_private.c | 234 ++-- - plat/st/stm32mp1/stm32mp1_ssp.c | 23 +- - plat/st/stm32mp1/stm32mp1_syscfg.c | 130 +- - plat/st/stm32mp1/stm32mp1_usb.c | 4 +- - 84 files changed, 3675 insertions(+), 1903 deletions(-) - create mode 100644 drivers/regulator/regulator_core.c - create mode 100644 drivers/st/ddr/stm32mp_ddr_test.c - create mode 100644 drivers/st/regulator/regulator_fixed.c - delete mode 100644 drivers/st/regulator/stm32mp_dummy_regulator.c - delete mode 100644 drivers/st/regulator/stm32mp_regulator.c - delete mode 100644 fdts/stm32mp15-ddr-512m-fw-config.dts - rename fdts/{stm32mp15-ddr-1g-fw-config.dts => stm32mp15-fw-config.dts} (60%) - create mode 100644 include/drivers/regulator.h - create mode 100644 include/drivers/st/regulator_fixed.h - create mode 100644 include/drivers/st/stm32mp_ddr_test.h - delete mode 100644 include/drivers/st/stm32mp_dummy_regulator.h - delete mode 100644 include/drivers/st/stm32mp_regulator.h - create mode 100644 include/dt-bindings/interrupt-controller/irq.h - create mode 100644 licenses/LICENSE.MIT - -diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S -index a007bab302..a9d03c379e 100644 ---- a/bl32/tsp/aarch64/tsp_entrypoint.S -+++ b/bl32/tsp/aarch64/tsp_entrypoint.S -@@ -100,11 +100,27 @@ func tsp_entrypoint _align=3 - * sections. This is done to safeguard against - * possible corruption of this memory by dirty - * cache lines in a system cache as a result of -- * use by an earlier boot loader stage. -+ * use by an earlier boot loader stage. If PIE -+ * is enabled however, RO sections including the -+ * GOT may be modified during pie fixup. -+ * Therefore, to be on the safe side, invalidate -+ * the entire image region if PIE is enabled. - * --------------------------------------------- - */ -- adr x0, __RW_START__ -- adr x1, __RW_END__ -+#if ENABLE_PIE -+#if SEPARATE_CODE_AND_RODATA -+ adrp x0, __TEXT_START__ -+ add x0, x0, :lo12:__TEXT_START__ -+#else -+ adrp x0, __RO_START__ -+ add x0, x0, :lo12:__RO_START__ -+#endif /* SEPARATE_CODE_AND_RODATA */ -+#else -+ adrp x0, __RW_START__ -+ add x0, x0, :lo12:__RW_START__ -+#endif /* ENABLE_PIE */ -+ adrp x1, __RW_END__ -+ add x1, x1, :lo12:__RW_END__ - sub x1, x1, x0 - bl inv_dcache_range - -diff --git a/docs/license.rst b/docs/license.rst -index 2f9704335f..80f1118609 100644 ---- a/docs/license.rst -+++ b/docs/license.rst -@@ -76,5 +76,15 @@ license text is included in those source files. - BSD-3-Clause license. Any contributions to this code must be made under the - terms of both licenses. - -+- Some source files originating from the Linux source tree, which are -+ disjunctively dual licensed (GPL-2.0 OR MIT), are redistributed under the -+ terms of the MIT license. These files are: -+ -+ - ``include/dt-bindings/interrupt-controller/arm-gic.h`` -+ - ``include/dt-bindings/interrupt-controller/irq.h`` -+ -+ See the original `Linux MIT license`_. -+ - .. _FreeBSD: http://www.freebsd.org -+.. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT - .. _SCC: http://www.simple-cc.org/ -diff --git a/drivers/mtd/nand/spi_nand.c b/drivers/mtd/nand/spi_nand.c -index d01a11963f..18913a57db 100644 ---- a/drivers/mtd/nand/spi_nand.c -+++ b/drivers/mtd/nand/spi_nand.c -@@ -286,6 +286,10 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size) - return -EINVAL; - } - -+ assert((spinand_dev.nand_dev->page_size != 0U) && -+ (spinand_dev.nand_dev->block_size != 0U) && -+ (spinand_dev.nand_dev->size != 0U)); -+ - ret = spi_nand_reset(); - if (ret != 0) { - return ret; -@@ -301,12 +305,12 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size) - return ret; - } - -- ret = spi_nand_quad_enable(id[0]); -+ ret = spi_nand_quad_enable(id[1]); - if (ret != 0) { - return ret; - } - -- VERBOSE("SPI_NAND Detected ID 0x%x 0x%x\n", id[0], id[1]); -+ VERBOSE("SPI_NAND Detected ID 0x%x\n", id[1]); - - VERBOSE("Page size %i, Block size %i, size %lli\n", - spinand_dev.nand_dev->page_size, -diff --git a/drivers/regulator/regulator_core.c b/drivers/regulator/regulator_core.c -new file mode 100644 -index 0000000000..67da7d2920 ---- /dev/null -+++ b/drivers/regulator/regulator_core.c -@@ -0,0 +1,1142 @@ -+/* -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#define MAX_PROPERTY_LEN 64 -+ -+static struct rdev rdev_array[PLAT_NB_RDEVS]; -+ -+#pragma weak plat_get_lp_mode_name -+const char *plat_get_lp_mode_name(int mode) -+{ -+ return NULL; -+} -+ -+#define for_each_rdev(rdev) \ -+ for (rdev = rdev_array; rdev < (rdev_array + PLAT_NB_RDEVS); rdev++) -+ -+#define for_each_registered_rdev(rdev) \ -+ for (rdev = rdev_array; \ -+ (rdev < (rdev_array + PLAT_NB_RDEVS)) && (rdev->desc != NULL); rdev++) -+ -+#if defined(IMAGE_BL32) -+static void lock_driver(const struct rdev *rdev) -+{ -+ if (rdev->desc->ops->lock != NULL) { -+ rdev->desc->ops->lock(rdev->desc); -+ } -+} -+ -+static void unlock_driver(const struct rdev *rdev) -+{ -+ if (rdev->desc->ops->unlock != NULL) { -+ rdev->desc->ops->unlock(rdev->desc); -+ } -+} -+#else -+#define lock_driver(desc) {} -+#define unlock_driver(desc) {} -+#endif -+ -+static struct rdev *regulator_get_by_phandle(int32_t phandle) -+{ -+ struct rdev *rdev; -+ -+ for_each_registered_rdev(rdev) { -+ if (rdev->phandle == phandle) { -+ return rdev; -+ } -+ } -+ -+ WARN("%s: phandle %d not found\n", __func__, phandle); -+ return NULL; -+} -+ -+/* -+ * Get a regulator from its node name -+ * -+ * @fdt - pointer to device tree memory -+ * @node_name - name of the node "ldo1" -+ * Return pointer to rdev if succeed, NULL else. -+ */ -+struct rdev *regulator_get_by_name(const char *node_name) -+{ -+ struct rdev *rdev; -+ -+ assert(node_name != NULL); -+ VERBOSE("get %s\n", node_name); -+ -+ for_each_registered_rdev(rdev) { -+ if (strcmp(rdev->desc->node_name, node_name) == 0) { -+ return rdev; -+ } -+ } -+ -+ WARN("%s: %s not found\n", __func__, node_name); -+ return NULL; -+} -+ -+#if defined(IMAGE_BL32) -+/* -+ * Get a regulator from its regulator name property value -+ * -+ * @reg_name - target value of regulator-name property -+ * Return pointer to rdev if succeed, NULL else. -+ */ -+struct rdev *regulator_get_by_regulator_name(const char *reg_name) -+{ -+ struct rdev *rdev; -+ -+ assert(reg_name != NULL); -+ VERBOSE("get %s\n", reg_name); -+ -+ for_each_registered_rdev(rdev) { -+ if ((rdev->reg_name != NULL) && (strcmp(rdev->reg_name, reg_name) == 0)) { -+ return rdev; -+ } -+ } -+ -+ WARN("%s: %s not found\n", __func__, reg_name); -+ return NULL; -+} -+#endif -+ -+static int32_t get_supply_phandle(const void *fdt, int node, const char *name) -+{ -+ const fdt32_t *cuint; -+ int len __unused; -+ int supply_phandle = -FDT_ERR_NOTFOUND; -+ char prop_name[MAX_PROPERTY_LEN]; -+ -+ len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name); -+ assert((len >= 0) && (len < MAX_PROPERTY_LEN - 1)); -+ -+ cuint = fdt_getprop(fdt, node, prop_name, NULL); -+ if (cuint != NULL) { -+ supply_phandle = fdt32_to_cpu(*cuint); -+ VERBOSE("%s: supplied by %d\n", name, supply_phandle); -+ } -+ -+ return supply_phandle; -+} -+ -+/* -+ * Get a regulator from a supply name -+ * -+ * @fdt - pointer to device tree memory -+ * @node - offset of the node that contains the supply description -+ * @name - name of the supply "vdd" for "vdd-supply' -+ * Return pointer to rdev if succeed, NULL else. -+ */ -+struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name) -+{ -+ const int p = get_supply_phandle(fdt, node, name); -+ -+ if (p < 0) { -+ return NULL; -+ } -+ -+ return regulator_get_by_phandle(p); -+} -+ -+static int __regulator_set_state(struct rdev *rdev, bool state) -+{ -+ if (rdev->desc->ops->set_state == NULL) { -+ return -ENODEV; -+ } -+ -+ return rdev->desc->ops->set_state(rdev->desc, state); -+} -+ -+#if defined(IMAGE_BL32) -+/* -+ * Enable regulator supply -+ * Enable regulator if use_count == 0 -+ * Apply ramp delay -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+static int __regulator_enable(struct rdev *rdev) -+{ -+ VERBOSE("%s: en\n", rdev->desc->node_name); -+ -+ if (rdev->desc->ops->set_state == NULL) { -+ return -ENODEV; -+ } -+ -+ if (rdev->supply_dev != NULL) -+ regulator_enable(rdev->supply_dev); -+ -+ lock_driver(rdev); -+ -+ if (rdev->use_count == 0) { -+ int ret; -+ -+ ret = __regulator_set_state(rdev, STATE_ENABLE); -+ if (ret != 0) { -+ ERROR("regul %s set state failed: err:%d\n", -+ rdev->desc->node_name, ret); -+ unlock_driver(rdev); -+ return ret; -+ } -+ -+ udelay(rdev->enable_ramp_delay); -+ } -+ -+ rdev->use_count++; -+ -+ assert(rdev->use_count != UINT8_MAX); -+ -+ VERBOSE("%s: en count:%u\n", rdev->desc->node_name, rdev->use_count); -+ -+ unlock_driver(rdev); -+ -+ return 0; -+} -+ -+/* -+ * Enable regulator -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_enable(struct rdev *rdev) -+{ -+ assert(rdev != NULL); -+ -+ if (rdev->flags & REGUL_ALWAYS_ON) { -+ return 0; -+ } -+ -+ return __regulator_enable(rdev); -+} -+ -+/* -+ * Disable regulator if use_count fall to zero -+ * Warn if count is < 0 because too many disable were requested -+ * Disable regulator supply -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+static int __regulator_disable(struct rdev *rdev) -+{ -+ VERBOSE("%s: dis\n", rdev->desc->node_name); -+ -+ if (rdev->desc->ops->set_state == NULL) { -+ return -ENODEV; -+ } -+ -+ lock_driver(rdev); -+ -+ if (rdev->use_count == 1) { -+ int ret; -+ -+ ret = __regulator_set_state(rdev, STATE_DISABLE); -+ if (ret != 0) { -+ ERROR("regul %s set state failed: err:%d\n", -+ rdev->desc->node_name, ret); -+ unlock_driver(rdev); -+ return ret; -+ } -+ } -+ -+ if (rdev->use_count == 0) { -+ WARN("regulator %s unbalanced disable\n", rdev->desc->node_name); -+ } else { -+ rdev->use_count--; -+ } -+ -+ VERBOSE("%s: dis count:%u\n", rdev->desc->node_name, rdev->use_count); -+ -+ unlock_driver(rdev); -+ -+ if (rdev->supply_dev != NULL) { -+ regulator_disable(rdev->supply_dev); -+ } -+ -+ return 0; -+} -+ -+/* -+ * Disable regulator -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_disable(struct rdev *rdev) -+{ -+ assert(rdev != NULL); -+ -+ if (rdev->flags & REGUL_ALWAYS_ON) { -+ return 0; -+ } -+ -+ return __regulator_disable(rdev); -+} -+#else -+/* -+ * Enable regulator -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_enable(struct rdev *rdev) -+{ -+ int ret; -+ -+ assert(rdev != NULL); -+ -+ ret = __regulator_set_state(rdev, STATE_ENABLE); -+ -+ udelay(rdev->enable_ramp_delay); -+ -+ return ret; -+} -+ -+/* -+ * Disable regulator -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_disable(struct rdev *rdev) -+{ -+ int ret; -+ -+ assert(rdev != NULL); -+ -+ ret = __regulator_set_state(rdev, STATE_DISABLE); -+ -+ udelay(rdev->enable_ramp_delay); -+ -+ return ret; -+} -+#endif -+ -+/* -+ * Regulator enabled query -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if disabled, 1 if enabled, <0 else. -+ */ -+int regulator_is_enabled(const struct rdev *rdev) -+{ -+ int ret = 0; -+ -+ assert(rdev != NULL); -+ -+ VERBOSE("%s: is en\n", rdev->desc->node_name); -+ -+ if (rdev->desc->ops->get_state == NULL) { -+ return -ENODEV; -+ } -+ -+ lock_driver(rdev); -+ -+ ret = rdev->desc->ops->get_state(rdev->desc); -+ if (ret < 0) { -+ ERROR("regul %s get state failed: err:%d\n", -+ rdev->desc->node_name, ret); -+ } -+ -+ unlock_driver(rdev); -+ -+ return ret; -+} -+ -+/* -+ * Set regulator voltage -+ * -+ * @rdev - pointer to rdev struct -+ * @mvolt - Target voltage level in millivolt -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt) -+{ -+ int ret = 0; -+ -+ assert(rdev != NULL); -+ -+ VERBOSE("%s: set mvolt\n", rdev->desc->node_name); -+ -+ if (rdev->desc->ops->set_voltage == NULL) { -+ return -ENODEV; -+ } -+ -+ if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) { -+ return -EPERM; -+ } -+ -+ lock_driver(rdev); -+ -+ ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt); -+ if (ret < 0) { -+ ERROR("regul %s set volt failed: err:%d\n", -+ rdev->desc->node_name, ret); -+ } -+ -+ unlock_driver(rdev); -+ -+ return ret; -+} -+ -+/* -+ * Set regulator min voltage -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_set_min_voltage(struct rdev *rdev) -+{ -+ return regulator_set_voltage(rdev, rdev->min_mv); -+} -+ -+/* -+ * Get regulator voltage -+ * -+ * @rdev - pointer to rdev struct -+ * Return milli volts if succeed, <0 else. -+ */ -+int regulator_get_voltage(const struct rdev *rdev) -+{ -+ int ret = 0; -+ -+ assert(rdev != NULL); -+ -+ VERBOSE("%s: get volt\n", rdev->desc->node_name); -+ -+ if (rdev->desc->ops->get_voltage == NULL) { -+ return rdev->min_mv; -+ } -+ -+ lock_driver(rdev); -+ -+ ret = rdev->desc->ops->get_voltage(rdev->desc); -+ if (ret < 0) { -+ ERROR("regul %s get voltage failed: err:%d\n", -+ rdev->desc->node_name, ret); -+ } -+ -+ unlock_driver(rdev); -+ -+ return ret; -+} -+ -+/* -+ * List regulator voltages -+ * -+ * @rdev - pointer to rdev struct -+ * @levels - out: array of supported millitvolt levels from min to max value -+ * @count - out: number of possible millivolt values -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count) -+{ -+ int ret; -+ size_t n; -+ -+ assert(rdev != NULL); -+ assert(levels != NULL); -+ assert(count != NULL); -+ -+ VERBOSE("%s: list volt\n", rdev->desc->node_name); -+ -+ if (rdev->desc->ops->list_voltages == NULL) { -+ return -ENODEV; -+ } -+ -+ lock_driver(rdev); -+ -+ ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count); -+ -+ unlock_driver(rdev); -+ -+ if (ret < 0) { -+ ERROR("regul %s list_voltages failed: err: %d\n", -+ rdev->desc->node_name, ret); -+ return ret; -+ } -+ -+ /* -+ * Reduce the possible values depending on min and max from device-tree -+ */ -+ n = *count; -+ while (((*levels)[n - 1U] > rdev->max_mv) && (n > 1U)) { -+ n--; -+ } -+ -+ /* Verify that max val is a valid value */ -+ if (rdev->max_mv != (*levels)[n - 1]) { -+ ERROR("regul %s: max value %u is invalid\n", -+ rdev->desc->node_name, rdev->max_mv); -+ return -EINVAL; -+ } -+ -+ while (((*levels[0U]) < rdev->min_mv) && (n > 1U)) { -+ (*levels)++; -+ n--; -+ } -+ -+ /* Verify that min is not too high */ -+ if (n == 0U) { -+ ERROR("regul %s set min voltage is too high\n", -+ rdev->desc->node_name); -+ return -EINVAL; -+ } -+ -+ /* Verify that min val is a valid vlue */ -+ if (rdev->min_mv != (*levels)[0U]) { -+ ERROR("regul %s: min value %u is invalid\n", -+ rdev->desc->node_name, rdev->min_mv); -+ return -EINVAL; -+ } -+ -+ *count = n; -+ -+ VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv); -+ -+ return 0; -+} -+ -+/* -+ * Get regulator voltages range -+ * -+ * @rdev - pointer to rdev struct -+ * @min_mv - out: min possible millivolt value -+ * @max_mv - out: max possible millivolt value -+ * Return 0 if succeed, non 0 else. -+ */ -+void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv) -+{ -+ assert(rdev != NULL); -+ -+ if (min_mv != NULL) { -+ *min_mv = rdev->min_mv; -+ } -+ if (max_mv != NULL) { -+ *max_mv = rdev->max_mv; -+ } -+} -+ -+/* -+ * Set regulator flag -+ * -+ * @rdev - pointer to rdev struct -+ * @flag - flag value to set (eg: REGUL_OCP) -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_set_flag(struct rdev *rdev, uint16_t flag) -+{ -+ int ret; -+ -+ /* check that only one bit is set on flag */ -+ if (__builtin_popcount(flag) != 1) { -+ return -EINVAL; -+ } -+ -+ /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */ -+ if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) { -+ rdev->flags |= flag; -+ return 0; -+ } -+ -+ if (rdev->desc->ops->set_flag == NULL) { -+ ERROR("%s can not set any flag\n", rdev->desc->node_name); -+ return -ENODEV; -+ } -+ -+ lock_driver(rdev); -+ -+ ret = rdev->desc->ops->set_flag(rdev->desc, flag); -+ -+ unlock_driver(rdev); -+ -+ if (ret != 0) { -+ ERROR("%s: could not set flag %d ret=%d\n", -+ rdev->desc->node_name, flag, ret); -+ return ret; -+ } -+ -+ rdev->flags |= flag; -+ -+ return 0; -+} -+ -+#if defined(IMAGE_BL32) -+ -+struct regul_property { -+ char *name; -+ uint16_t flag; -+}; -+ -+static struct regul_property flag_prop[] = { -+ { -+ .name = "regulator-always-on", -+ .flag = REGUL_ALWAYS_ON, -+ }, -+ { -+ .name = "regulator-boot-on", -+ .flag = REGUL_BOOT_ON, -+ }, -+ { -+ .name = "regulator-active-discharge", -+ .flag = REGUL_ACTIVE_DISCHARGE, -+ }, -+ { -+ .name = "regulator-over-current-protection", -+ .flag = REGUL_OCP, -+ }, -+ { -+ .name = "regulator-pull-down", -+ .flag = REGUL_PULL_DOWN, -+ }, -+ { -+ .name = "st,mask-reset", -+ .flag = REGUL_MASK_RESET, -+ }, -+ { -+ .name = "st,regulator-sink-source", -+ .flag = REGUL_SINK_SOURCE, -+ }, -+ { -+ .name = "st,regulator-bypass", -+ .flag = REGUL_ENABLE_BYPASS, -+ }, -+}; -+ -+static int parse_properties(const void *fdt, struct rdev *rdev, int node) -+{ -+ const fdt32_t *cuint; -+ int ret = 0; -+ struct regul_property *prop; -+ -+ for (prop = flag_prop; prop < (flag_prop + ARRAY_SIZE(flag_prop)); prop++) { -+ if (fdt_getprop(fdt, node, prop->name, NULL) != NULL) { -+ VERBOSE("%s: prop 0x%x\n", rdev->desc->node_name, prop->flag); -+ ret = regulator_set_flag(rdev, prop->flag); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, node, "regulator-enable-ramp-delay", NULL); -+ if (cuint != NULL) { -+ rdev->enable_ramp_delay = (uint32_t)(fdt32_to_cpu(*cuint)); -+ VERBOSE("%s: enable_ramp_delay=%u\n", rdev->desc->node_name, -+ rdev->enable_ramp_delay); -+ } -+ -+ rdev->reg_name = fdt_getprop(fdt, node, "regulator-name", NULL); -+ -+ return 0; -+} -+ -+static void parse_supply(const void *fdt, struct rdev *rdev, int node) -+{ -+ const char *name = rdev->desc->supply_name; -+ -+ if (name == NULL) { -+ name = rdev->desc->node_name; -+ } -+ -+ rdev->supply_phandle = get_supply_phandle(fdt, node, name); -+ if (rdev->supply_phandle < 0) { -+ node = fdt_parent_offset(fdt, node); -+ rdev->supply_phandle = get_supply_phandle(fdt, node, name); -+ } -+} -+ -+static void parse_low_power_mode(const void *fdt, struct rdev *rdev, int node, int mode) -+{ -+ const fdt32_t *cuint; -+ -+ rdev->lp_state[mode] = 0; -+ -+ if (fdt_getprop(fdt, node, "regulator-off-in-suspend", NULL) != NULL) { -+ VERBOSE("%s: mode:%d OFF\n", rdev->desc->node_name, mode); -+ rdev->lp_state[mode] |= LP_STATE_OFF; -+ } else if (fdt_getprop(fdt, node, "regulator-on-in-suspend", NULL) != NULL) { -+ VERBOSE("%s: mode:%d ON\n", rdev->desc->node_name, mode); -+ rdev->lp_state[mode] |= LP_STATE_ON; -+ } else { -+ rdev->lp_state[mode] |= LP_STATE_UNCHANGED; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "regulator-suspend-microvolt", NULL); -+ if (cuint != NULL) { -+ uint16_t mv; -+ -+ mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -+ VERBOSE("%s: mode:%d suspend mv=%u\n", rdev->desc->node_name, -+ mode, mv); -+ -+ rdev->lp_state[mode] |= LP_STATE_SET_VOLT; -+ rdev->lp_mv[mode] = mv; -+ } -+} -+ -+static void parse_low_power_modes(const void *fdt, struct rdev *rdev, int node) -+{ -+ int i; -+ -+ for (i = 0; i < PLAT_NB_SUSPEND_MODES; i++) { -+ const char *lp_mode_name = plat_get_lp_mode_name(i); -+ int n; -+ -+ if (lp_mode_name == NULL) { -+ continue; -+ } -+ -+ /* Get the configs from regulator_state_node subnode */ -+ n = fdt_subnode_offset(fdt, node, lp_mode_name); -+ if (n >= 0) { -+ parse_low_power_mode(fdt, rdev, n, i); -+ } -+ } -+} -+#endif -+ -+/* -+ * Parse the device-tree for a regulator -+ * -+ * Read min/max voltage from dt and check its validity -+ * Read the properties, and call the driver to set flags -+ * Read power supply phandle -+ * Read and store low power mode states -+ * -+ * @rdev - pointer to rdev struct -+ * @node - device-tree node offset of the regulator -+ * Return 0 if disabled, 1 if enabled, <0 else. -+ */ -+static int parse_dt(struct rdev *rdev, int node) -+{ -+ void *fdt; -+ const fdt32_t *cuint; -+ const uint16_t *levels; -+ size_t size; -+ int ret = 0; -+ -+ VERBOSE("%s: parse dt\n", rdev->desc->node_name); -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -ENOENT; -+ } -+ -+ rdev->phandle = fdt_get_phandle(fdt, node); -+ -+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); -+ if (cuint != NULL) { -+ uint16_t min_mv; -+ -+ min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -+ VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv); -+ if (min_mv <= rdev->max_mv) { -+ rdev->min_mv = min_mv; -+ } else { -+ ERROR("%s: min_mv=%d is too high\n", -+ rdev->desc->node_name, (int)min_mv); -+ return -EINVAL; -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); -+ if (cuint != NULL) { -+ uint16_t max_mv; -+ -+ max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -+ VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv); -+ if (max_mv >= rdev->min_mv) { -+ rdev->max_mv = max_mv; -+ } else { -+ ERROR("%s: max_mv=%d is too low\n", -+ rdev->desc->node_name, (int)max_mv); -+ return -EINVAL; -+ } -+ } -+ -+ /* validate that min and max values can be used */ -+ ret = regulator_list_voltages(rdev, &levels, &size); -+ if ((ret != 0) && (ret != -ENODEV)) { -+ return ret; -+ } -+ -+#if defined(IMAGE_BL32) -+ ret = parse_properties(fdt, rdev, node); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ parse_supply(fdt, rdev, node); -+ -+ parse_low_power_modes(fdt, rdev, node); -+#endif -+ -+ return 0; -+} -+ -+/* -+ * Register a regulator driver in regulator framework. -+ * Initialize voltage range from driver description -+ * -+ * @desc - pointer to the regulator description -+ * @node - device-tree node offset of the regulator -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_register(const struct regul_description *desc, int node) -+{ -+ struct rdev *rdev; -+ -+ assert(desc != NULL); -+ -+ VERBOSE("register %s\n", desc->node_name); -+ -+ for_each_rdev(rdev) { -+ if (rdev->desc == NULL) { -+ break; -+ } -+ } -+ -+ if (rdev == rdev_array + PLAT_NB_RDEVS) { -+ WARN("out of memory\n"); -+ return -ENOMEM; -+ } -+ -+ rdev->desc = desc; -+ rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay; -+ -+ if (rdev->desc->ops->list_voltages != NULL) { -+ int ret = 0; -+ const uint16_t *levels; -+ size_t count; -+ -+ lock_driver(rdev); -+ -+ ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count); -+ -+ unlock_driver(rdev); -+ -+ if (ret < 0) { -+ ERROR("regul %s set state failed: err:%d\n", -+ rdev->desc->node_name, ret); -+ return ret; -+ } -+ -+ rdev->min_mv = levels[0]; -+ rdev->max_mv = levels[count - 1U]; -+ } else { -+ rdev->max_mv = UINT16_MAX; -+ } -+ -+ return parse_dt(rdev, node); -+} -+ -+#if defined(IMAGE_BL32) -+/* -+ * Suspend a single regulator before low power entry -+ * Call regulator suspend call back, -+ * Enable the regulator if boot_on flag is set as regulator is needed during -+ * boot/resume from suspend sequences. -+ * -+ * @rdev - pointer to rdev struct -+ * @mode - low power mode index -+ * Return 0 if succeed, non 0 else. -+ */ -+static int suspend_regulator(struct rdev *rdev, int mode) -+{ -+ int ret = 0; -+ -+ if (rdev->desc->ops->suspend != NULL) { -+ lock_driver(rdev); -+ ret = rdev->desc->ops->suspend(rdev->desc, -+ rdev->lp_state[mode], -+ rdev->lp_mv[mode]); -+ unlock_driver(rdev); -+ if (ret != 0) { -+ ERROR("%s failed to suspend: %d\n", rdev->desc->node_name, ret); -+ return ret; -+ } -+ } -+ -+ if (rdev->flags & REGUL_BOOT_ON) { -+ ret = regulator_enable(rdev); -+ } -+ -+ return ret; -+} -+ -+/* -+ * Resume a single regulator after low power -+ * -+ * @rdev - pointer to rdev struct -+ * Return 0 if succeed, non 0 else. -+ */ -+static int resume_regulator(struct rdev *rdev) -+{ -+ int ret = 0; -+ -+ if (rdev->flags & REGUL_BOOT_ON) { -+ /* Revert to the state it was before suspend */ -+ ret = regulator_disable(rdev); -+ if (ret != 0) { -+ ERROR("%s failed to resume: %d\n", rdev->desc->node_name, ret); -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * Suspend regulators before entering low power -+ * -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_core_suspend(int mode) -+{ -+ struct rdev *rdev; -+ -+ VERBOSE("Regulator core suspend\n"); -+ -+ if (mode >= PLAT_NB_SUSPEND_MODES) { -+ return -EINVAL; -+ } -+ -+ /* Suspend each regulator */ -+ for_each_registered_rdev(rdev) { -+ if (suspend_regulator(rdev, mode) != 0) { -+ panic(); -+ } -+ } -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+ regulator_core_dump(); -+#endif -+ -+ return 0; -+} -+ -+/* -+ * Resume regulators from low power -+ * -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_core_resume(void) -+{ -+ struct rdev *rdev; -+ -+ VERBOSE("Regulator core resume\n"); -+ -+ /* Resume each regulator */ -+ for_each_registered_rdev(rdev) { -+ if (resume_regulator(rdev) != 0) { -+ panic(); -+ } -+ } -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+ regulator_core_dump(); -+#endif -+ -+ return 0; -+} -+ -+/* -+ * save regulators data -+ * -+ * @backup_area - pointer to save data -+ * @backup_size - size of the backup area -+ */ -+void regulator_core_backup_context(void *backup_area, size_t backup_size) -+{ -+ int8_t *data = (int8_t *)backup_area; -+ struct rdev *rdev; -+ -+ assert(data != NULL); -+ assert(backup_size == PLAT_BACKUP_REGULATOR_SIZE); -+ -+ for_each_rdev(rdev) { -+ *data = rdev->use_count; -+ data++; -+ } -+} -+ -+/* -+ * restore regulators data -+ * -+ * @backup_area - pointer to retrieve saved data -+ * @backup_size - size of the backup area -+ */ -+void regulator_core_restore_context(void *backup_area, size_t backup_size) -+{ -+ int8_t *data = (int8_t *)backup_area; -+ struct rdev *rdev; -+ -+ assert(data != NULL); -+ assert(backup_size == PLAT_BACKUP_REGULATOR_SIZE); -+ -+ for_each_rdev(rdev) { -+ rdev->use_count = *data; -+ data++; -+ } -+} -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+static void sprint_name(char *dest, const char *src, int len) -+{ -+ int l; -+ -+ if (src == NULL) { -+ src = ""; -+ } -+ -+ l = strlen(src); -+ if (l > len) { -+ l = len; -+ } -+ -+ memset(dest, ' ', len); -+ memcpy(dest, src, l); -+ dest[len] = 0; -+} -+ -+/* -+ * Log regulators state -+ */ -+void regulator_core_dump(void) -+{ -+ struct rdev *rdev; -+ -+ VERBOSE("Dump Regulators\n"); -+ -+ INFO("reg name use\ten\tmV\tmin\tmax\tflags\tsupply\n"); -+ -+ for_each_registered_rdev(rdev) { -+ uint16_t min_mv, max_mv; -+ char reg[9] = ""; -+ char name[9]; -+ const char *supply = ""; -+ -+ sprint_name(name, rdev->desc->node_name, 8); -+ sprint_name(reg, rdev->reg_name, 8); -+ -+ regulator_get_range(rdev, &min_mv, &max_mv); -+ if (rdev->supply_dev != NULL) -+ supply = rdev->supply_dev->desc->node_name; -+ -+ INFO("%s %s %d\t%d\t%d\t%d\t%d\t0x%x\t%s\n", -+ reg, name, -+ rdev->use_count, -+ regulator_is_enabled(rdev), -+ regulator_get_voltage(rdev), min_mv, max_mv, -+ rdev->flags, supply); -+ } -+} -+#endif -+ -+/* -+ * Connect each regulator to its supply -+ * Apply min voltage if the voltage is outside the authorized range -+ * Enable always-on regulators -+ * -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_core_config(void) -+{ -+ int ret; -+ struct rdev *rdev; -+ -+ VERBOSE("Regul Core config\n"); -+ -+ for_each_registered_rdev(rdev) { -+ if (rdev->supply_phandle >= 0) { -+ struct rdev *s; -+ -+ VERBOSE("%s: connect supply\n", rdev->desc->node_name); -+ -+ s = regulator_get_by_phandle(rdev->supply_phandle); -+ if (s == NULL) { -+ return -EINVAL; -+ } -+ -+ rdev->supply_dev = s; -+ } -+ } -+ -+ for_each_registered_rdev(rdev) { -+ uint16_t mv, min_mv, max_mv; -+ -+ regulator_get_range(rdev, &min_mv, &max_mv); -+ -+ ret = regulator_get_voltage(rdev); -+ if (ret >= 0) { -+ mv = ret; -+ if ((mv < min_mv) || (mv > max_mv)) { -+ ret = regulator_set_voltage(rdev, min_mv); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ } else { -+ return ret; -+ } -+ -+ /* -+ * Enable always-on regulator and increment its use_count so that -+ * the regulator is not being disabled during clean-up sequence. -+ */ -+ if (rdev->flags & REGUL_ALWAYS_ON) { -+ ret = __regulator_enable(rdev); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * Sync hardware regulator state with use refcount -+ * -+ * Return 0 if succeed, non 0 else. -+ */ -+int regulator_core_cleanup(void) -+{ -+ struct rdev *rdev; -+ -+ VERBOSE("Regul Core cleanup\n"); -+ -+ for_each_registered_rdev(rdev) { -+ if (!(rdev->flags & REGUL_BOOT_ON)) { -+ if ((rdev->use_count == 0) && (regulator_is_enabled(rdev) == 1)) { -+ VERBOSE("disable %s during cleanup\n", rdev->desc->node_name); -+ /* force disable to synchronize the framework */ -+ __regulator_set_state(rdev, STATE_DISABLE); -+ } -+ } -+ } -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+ regulator_core_dump(); -+#endif -+ -+ return 0; -+} -+ -+#endif -diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c -index d074a1568c..73c9b147b7 100644 ---- a/drivers/st/clk/stm32mp1_clk.c -+++ b/drivers/st/clk/stm32mp1_clk.c -@@ -71,6 +71,7 @@ enum stm32mp1_parent_id { - _HSI_KER = NB_OSC, - _HSE_KER, - _HSE_KER_DIV2, -+ _HSE_RTC, - _CSI_KER, - _PLL1_P, - _PLL1_Q, -@@ -140,6 +141,7 @@ static const uint8_t parent_id_clock_id[_PARENT_NB] = { - [_HSI_KER] = CK_HSI, - [_HSE_KER] = CK_HSE, - [_HSE_KER_DIV2] = CK_HSE_DIV2, -+ [_HSE_RTC] = _UNKNOWN_ID, - [_CSI_KER] = CK_CSI, - [_PLL1_P] = PLL1_P, - [_PLL1_Q] = PLL1_Q, -@@ -384,21 +386,17 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { - #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 - - #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), - -@@ -543,7 +541,7 @@ static const uint8_t per_parents[] = { - }; - - static const uint8_t rtc_parents[] = { -- _UNKNOWN_ID, _LSE, _LSI, _HSE -+ _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC - }; - - static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { -@@ -639,6 +637,7 @@ static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { - [_HSI_KER] = "HSI_KER", - [_HSE_KER] = "HSE_KER", - [_HSE_KER_DIV2] = "HSE_KER_DIV2", -+ [_HSE_RTC] = "HSE_RTC", - [_CSI_KER] = "CSI_KER", - [_PLL1_P] = "PLL1_P", - [_PLL1_Q] = "PLL1_Q", -@@ -696,6 +695,7 @@ 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 save_current_opp_khz; - static uint32_t pll3cr; - static uint32_t pll4cr; - static uint32_t mssckselr; -@@ -1063,6 +1063,10 @@ static unsigned long get_clock_rate(int p) - case _HSE_KER_DIV2: - clock = stm32mp1_clk_get_fixed(_HSE) >> 1; - break; -+ case _HSE_RTC: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; -+ break; - case _LSI: - clock = stm32mp1_clk_get_fixed(_LSI); - break; -@@ -2951,6 +2955,7 @@ static void secure_parent_clocks(unsigned long parent_id) - case _HSE: - case _HSE_KER: - case _HSE_KER_DIV2: -+ case _HSE_RTC: - case _LSE: - break; - -@@ -3238,6 +3243,13 @@ void save_clock_pm_context(void) - stm32mp1_pm_save_clock_cfg(offset, - (uint8_t *)gate_refcounts, - sizeof(gate_refcounts)); -+ offset += sizeof(gate_refcounts); -+ -+ save_current_opp_khz = current_opp_khz; -+ -+ stm32mp1_pm_save_clock_cfg(offset, -+ (uint8_t *)&save_current_opp_khz, -+ sizeof(save_current_opp_khz)); - } - - void restore_clock_pm_context(void) -@@ -3267,6 +3279,13 @@ void restore_clock_pm_context(void) - stm32mp1_pm_restore_clock_cfg(offset, - (uint8_t *)gate_refcounts, - sizeof(gate_refcounts)); -+ offset += sizeof(gate_refcounts); -+ -+ stm32mp1_pm_restore_clock_cfg(offset, -+ (uint8_t *)&save_current_opp_khz, -+ sizeof(save_current_opp_khz)); -+ -+ stm32mp1_set_opp_khz(save_current_opp_khz); - } - - void stm32mp1_clock_suspend(void) -diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c -index 7e8041743e..fb0c7d782f 100644 ---- a/drivers/st/ddr/stm32mp1_ddr.c -+++ b/drivers/st/ddr/stm32mp1_ddr.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -1017,9 +1017,14 @@ void stm32mp1_ddr_init(struct ddr_info *priv, - /* - * 10. configure PUBL PIR register to specify which training - * step to run -- * Warning : RVTRN is not supported by this PUBL -+ * RVTRN is executed only on LPDDR2/LPDDR3 - */ -- stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); -+ pir = DDRPHYC_PIR_QSTRN; -+ if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) == 0U) { -+ pir |= DDRPHYC_PIR_RVTRN; -+ } -+ -+ stm32mp1_ddrphy_init(priv->phy, pir); - - /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training - * sequence -diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c -index 3918eb7be5..d7ee35fec9 100644 ---- a/drivers/st/ddr/stm32mp1_ram.c -+++ b/drivers/st/ddr/stm32mp1_ram.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -14,14 +14,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - --#define DDR_PATTERN 0xAAAAAAAAU --#define DDR_ANTIPATTERN 0x55555555U -- - static struct ddr_info ddr_priv_data; - static bool ddr_self_refresh; - -@@ -52,139 +50,6 @@ 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. -- ******************************************************************************/ --static uint32_t ddr_test_rw_access(void) --{ -- uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE); -- -- mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); -- -- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { -- return (uint32_t)STM32MP_DDR_BASE; -- } -- -- mmio_write_32(STM32MP_DDR_BASE, saved_value); -- -- 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. -- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ -- * File: memtest.c - This source code belongs to Public Domain. -- * Returns 0 if success, and address value else. -- ******************************************************************************/ --static uint32_t ddr_test_data_bus(void) --{ -- uint32_t pattern; -- -- for (pattern = 1U; pattern != 0U; pattern <<= 1) { -- mmio_write_32(STM32MP_DDR_BASE, pattern); -- -- if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { -- return (uint32_t)STM32MP_DDR_BASE; -- } -- } -- -- return 0; --} -- --/******************************************************************************* -- * This function tests the DDR address bus wiring. -- * This is inspired from the Data Bus Test algorithm written by Michael Barr -- * in "Programming Embedded Systems in C and C++" book. -- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ -- * File: memtest.c - This source code belongs to Public Domain. -- * Returns 0 if success, and address value else. -- ******************************************************************************/ --static uint32_t ddr_test_addr_bus(void) --{ -- uint64_t addressmask = (ddr_priv_data.info.size - 1U); -- uint64_t offset; -- uint64_t testoffset = 0; -- -- /* 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(STM32MP_DDR_BASE + (uint32_t)offset, -- DDR_PATTERN); -- } -- -- /* Check for address bits stuck high. */ -- 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(STM32MP_DDR_BASE + (uint32_t)offset) != -- DDR_PATTERN) { -- return (uint32_t)(STM32MP_DDR_BASE + offset); -- } -- } -- -- 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(STM32MP_DDR_BASE + (uint32_t)testoffset, -- DDR_ANTIPATTERN); -- -- 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(STM32MP_DDR_BASE + -- (uint32_t)offset) != DDR_PATTERN) && -- (offset != testoffset)) { -- return (uint32_t)(STM32MP_DDR_BASE + offset); -- } -- } -- -- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, -- DDR_PATTERN); -- } -- -- return 0; --} -- --/******************************************************************************* -- * This function checks the DDR size. It has to be run with Data Cache off. -- * This test is run before data have been put in DDR, and is only done for -- * cold boot. The DDR data can then be overwritten, and it is not useful to -- * restore its content. -- * Returns DDR computed size. -- ******************************************************************************/ --static uint32_t ddr_check_size(void) --{ -- uint32_t offset = sizeof(uint32_t); -- -- mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); -- -- while (offset < STM32MP_DDR_MAX_SIZE) { -- mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); -- dsb(); -- -- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { -- break; -- } -- -- offset <<= 1; -- } -- -- INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U)); -- -- return offset; --} -- - static int stm32mp1_ddr_setup(void) - { - struct ddr_info *priv = &ddr_priv_data; -@@ -249,6 +114,17 @@ static int stm32mp1_ddr_setup(void) - INFO("RAM: %s\n", config.info.name); - - for (idx = 0; idx < ARRAY_SIZE(param); idx++) { -+ /* Check present field to avoid warning for optional properties */ -+ if (param[idx].present != NULL) { -+ if (fdt_getprop(fdt, node, param[idx].name, NULL) == NULL) { -+ *(param[idx].present) = false; -+ VERBOSE("%s: %s[0x%x] = absent\n", __func__, -+ param[idx].name, param[idx].size); -+ continue; -+ } -+ /* Save presence of optional parameters */ -+ *(param[idx].present) = true; -+ } - ret = fdt_read_uint32_array(fdt, node, param[idx].name, - param[idx].size, - (void *)((uintptr_t)&config + -@@ -256,20 +132,11 @@ static int stm32mp1_ddr_setup(void) - - VERBOSE("%s: %s[0x%x] = %d\n", __func__, - param[idx].name, param[idx].size, ret); -- if ((ret != 0) && -- ((ret != -FDT_ERR_NOTFOUND) || -- (param[idx].present == NULL))) { -+ if (ret != 0) { - 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; -- } -- } - } - - config.self_refresh = false; -@@ -297,7 +164,7 @@ static int stm32mp1_ddr_setup(void) - } - - if (config.self_refresh) { -- uret = ddr_test_rw_access(); -+ uret = stm32mp_ddr_test_rw_access(); - if (uret != 0U) { - ERROR("DDR rw test: Can't access memory @ 0x%x\n", - uret); -@@ -307,21 +174,21 @@ static int stm32mp1_ddr_setup(void) - /* Restore area overwritten by training */ - stm32_restore_ddr_training_area(); - } else { -- uret = ddr_test_data_bus(); -+ uret = stm32mp_ddr_test_data_bus(); - if (uret != 0U) { - ERROR("DDR data bus test: can't access memory @ 0x%x\n", - uret); - panic(); - } - -- uret = ddr_test_addr_bus(); -+ uret = stm32mp_ddr_test_addr_bus(config.info.size); - if (uret != 0U) { - ERROR("DDR addr bus test: can't access memory @ 0x%x\n", - uret); - panic(); - } - -- uret = ddr_check_size(); -+ uret = stm32mp_ddr_check_size(); - if (uret < config.info.size) { - ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", - uret, config.info.size); -diff --git a/drivers/st/ddr/stm32mp_ddr_test.c b/drivers/st/ddr/stm32mp_ddr_test.c -new file mode 100644 -index 0000000000..45920b7f80 ---- /dev/null -+++ b/drivers/st/ddr/stm32mp_ddr_test.c -@@ -0,0 +1,148 @@ -+/* -+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+ -+#include -+ -+#include -+ -+#define DDR_PATTERN 0xAAAAAAAAU -+#define DDR_ANTIPATTERN 0x55555555U -+ -+/******************************************************************************* -+ * 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. -+ ******************************************************************************/ -+uint32_t stm32mp_ddr_test_rw_access(void) -+{ -+ uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE); -+ -+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); -+ -+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { -+ return (uint32_t)STM32MP_DDR_BASE; -+ } -+ -+ mmio_write_32(STM32MP_DDR_BASE, saved_value); -+ -+ 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. -+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ -+ * File: memtest.c - This source code belongs to Public Domain. -+ * Returns 0 if success, and address value else. -+ ******************************************************************************/ -+uint32_t stm32mp_ddr_test_data_bus(void) -+{ -+ uint32_t pattern; -+ -+ for (pattern = 1U; pattern != 0U; pattern <<= 1) { -+ mmio_write_32(STM32MP_DDR_BASE, pattern); -+ -+ if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { -+ return (uint32_t)STM32MP_DDR_BASE; -+ } -+ } -+ -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function tests the DDR address bus wiring. -+ * This is inspired from the Data Bus Test algorithm written by Michael Barr -+ * in "Programming Embedded Systems in C and C++" book. -+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ -+ * File: memtest.c - This source code belongs to Public Domain. -+ * size: size in bytes of the DDR memory device. -+ * Returns 0 if success, and address value else. -+ ******************************************************************************/ -+uint32_t stm32mp_ddr_test_addr_bus(uint64_t size) -+{ -+ uint64_t addressmask = size - 1U; -+ uint64_t offset; -+ uint64_t testoffset = 0; -+ -+ /* 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(STM32MP_DDR_BASE + (uint32_t)offset, -+ DDR_PATTERN); -+ } -+ -+ /* Check for address bits stuck high. */ -+ 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(STM32MP_DDR_BASE + (uint32_t)offset) != -+ DDR_PATTERN) { -+ return (uint32_t)(STM32MP_DDR_BASE + offset); -+ } -+ } -+ -+ 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(STM32MP_DDR_BASE + (uint32_t)testoffset, -+ DDR_ANTIPATTERN); -+ -+ 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(STM32MP_DDR_BASE + -+ (uint32_t)offset) != DDR_PATTERN) && -+ (offset != testoffset)) { -+ return (uint32_t)(STM32MP_DDR_BASE + offset); -+ } -+ } -+ -+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, -+ DDR_PATTERN); -+ } -+ -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function checks the DDR size. It has to be run with Data Cache off. -+ * This test is run before data have been put in DDR, and is only done for -+ * cold boot. The DDR data can then be overwritten, and it is not useful to -+ * restore its content. -+ * Returns DDR computed size. -+ ******************************************************************************/ -+uint32_t stm32mp_ddr_check_size(void) -+{ -+ uint32_t offset = sizeof(uint32_t); -+ -+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); -+ -+ while (offset < STM32MP_DDR_MAX_SIZE) { -+ mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); -+ dsb(); -+ -+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { -+ break; -+ } -+ -+ offset <<= 1; -+ } -+ -+ INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U)); -+ -+ return offset; -+} -diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c -index 503e259876..e9ab6dafd8 100644 ---- a/drivers/st/fmc/stm32_fmc2_nand.c -+++ b/drivers/st/fmc/stm32_fmc2_nand.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - */ -@@ -201,9 +201,6 @@ static void stm32_fmc2_nand_setup_timing(void) - 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); -@@ -245,12 +242,6 @@ static void stm32_fmc2_nand_setup_timing(void) - 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; -diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c -index 75707e63a1..5c54762ecc 100644 ---- a/drivers/st/gpio/stm32_gpio.c -+++ b/drivers/st/gpio/stm32_gpio.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -284,3 +284,10 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) - - clk_disable(clock); - } -+ -+void set_gpio_reset_cfg(uint32_t bank, uint32_t pin) -+{ -+ set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_SPEED_LOW, -+ GPIO_NO_PULL, GPIO_ALTERNATE_(0), DT_DISABLED); -+ set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank)); -+} -diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c -index 8c203a4c03..c516bdb3d4 100644 ---- a/drivers/st/mmc/stm32_sdmmc2.c -+++ b/drivers/st/mmc/stm32_sdmmc2.c -@@ -186,9 +186,8 @@ 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); -+ if (sdmmc2_params.vmmc_regu != NULL) { -+ regulator_disable(sdmmc2_params.vmmc_regu); - } - - mdelay(VCC_POWER_OFF_DELAY); -@@ -197,8 +196,8 @@ static void stm32_sdmmc2_init(void) - 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); -+ if (sdmmc2_params.vmmc_regu != NULL) { -+ regulator_enable(sdmmc2_params.vmmc_regu); - } - - mdelay(VCC_POWER_ON_DELAY); -@@ -758,10 +757,7 @@ 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); -- } -+ sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc"); - - return 0; - } -@@ -783,7 +779,7 @@ 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; -+ sdmmc2_params.vmmc_regu = NULL; - - if (stm32_sdmmc2_dt_get_config() != 0) { - ERROR("%s: DT error\n", __func__); -diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c -index 4e505debdf..e8cadcda0a 100644 ---- a/drivers/st/pmic/stm32mp_pmic.c -+++ b/drivers/st/pmic/stm32mp_pmic.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,30 +13,21 @@ - - #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_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 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; -+#if defined(IMAGE_BL32) -+static struct spinlock lock; -+#endif -+ -+static int register_pmic(void); - - static int dt_get_pmic_node(void *fdt) - { -@@ -84,235 +75,6 @@ static bool dt_pmic_is_secure(void) - (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) --{ -- const fdt32_t *cuint; -- -- cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- if (min_mv != NULL) { -- *min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -- } -- -- cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); -- if (cuint == NULL) { -- return -FDT_ERR_NOTFOUND; -- } -- -- if (max_mv != NULL) { -- *max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -- } -- -- 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; -- } -- -- 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 0; --} -- --#if defined(IMAGE_BL32) --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; -- }; -- -- /* -- * 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); -- if (pmic_node < 0) { -- return -ENOENT; -- } -- -- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -- if (regulators_node < 0) { -- return -ENOENT; -- } -- -- fdt_for_each_subnode(subnode, fdt, regulators_node) { -- const char *regu_name = fdt_get_name(fdt, subnode, NULL); -- -- switch (command) { -- case CMD_GET_MIN_VOLTAGE: -- assert(node_name != NULL); -- assert(voltage_mv != NULL); -- -- if (strcmp(regu_name, node_name) != 0) { -- continue; -- } -- -- ret = dt_pmic_get_regulator_voltage(fdt, subnode, -- voltage_mv, NULL); -- if (ret < 0) { -- return -ENXIO; -- } -- -- 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. -@@ -360,66 +122,6 @@ static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, - 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); --} -- --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 -FDT_ERR_NOTFOUND; -- } -- -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -- if (regulators_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- fdt_for_each_subnode(subnode, fdt, regulators_node) { -- const char *name; -- -- 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 -FDT_ERR_NOTFOUND; --} -- --int pmic_set_regulator_min_voltage(const char *regu_name) --{ -- int rc = -ENOENT; -- const char *supply_name; -- -- if (dt_pmic_find_supply(&supply_name, regu_name) == 0) { -- uint16_t min_mv; -- -- rc = pmic_operate(CMD_GET_MIN_VOLTAGE, supply_name, &min_mv); -- if (rc == 0) { -- rc = stpmic1_regulator_voltage_set(supply_name, min_mv); -- } -- } -- -- return rc; --} -- - bool initialize_pmic_i2c(void) - { - int ret; -@@ -483,62 +185,6 @@ static void register_pmic_shared_peripherals(void) - } - } - --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) - { - if (!initialize_pmic_i2c()) { -@@ -547,13 +193,15 @@ void initialize_pmic(void) - } - - register_pmic_shared_peripherals(); --} - --void configure_pmic(void) --{ -- if (pmic_configure_boot_on_regulators() < 0) { -+ if (register_pmic() < 0) { - panic(); -- }; -+ } -+ -+ if (stpmic1_powerctrl_on() < 0) { -+ panic(); -+ } -+ - } - - #if DEBUG -@@ -567,65 +215,61 @@ void print_pmic_info_and_debug(void) - } - - INFO("PMIC version = 0x%02lx\n", pmic_version); -- stpmic1_dump_regulators(); -+#if defined(IMAGE_BL32) -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+ regulator_core_dump(); -+#endif -+#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; -+ uint16_t buck3_min_mv; -+ struct rdev *buck2, *buck3, *ldo3, *vref; - -- if (pmic_operate(CMD_GET_MIN_VOLTAGE, "buck2", &buck2_mv) != 0) { -- return -EPERM; -+ buck2 = regulator_get_by_name("buck2"); -+ if (buck2 == NULL) { -+ return -ENOENT; - } - -- switch (ddr_type) { -- case STM32MP_DDR3: -- /* Set LDO3 to sync mode */ -- status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); -- if (status != 0) { -- return status; -- } -+ ldo3 = regulator_get_by_name("ldo3"); -+ if (ldo3 == NULL) { -+ return -ENOENT; -+ } - -- read_val &= ~STPMIC1_LDO3_MODE; -- read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; -- read_val |= STPMIC1_LDO3_DDR_SEL << -- STPMIC1_LDO12356_OUTPUT_SHIFT; -+ vref = regulator_get_by_name("vref_ddr"); -+ if (vref == NULL) { -+ return -ENOENT; -+ } - -- status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); -+ switch (ddr_type) { -+ case STM32MP_DDR3: -+ status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE); - if (status != 0) { - return status; - } - -- status = stpmic1_regulator_voltage_set("buck2", buck2_mv); -+ status = regulator_set_min_voltage(buck2); - if (status != 0) { - return status; - } - -- status = stpmic1_regulator_enable("buck2"); -+ status = regulator_enable(buck2); - if (status != 0) { - return status; - } - -- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -- -- status = stpmic1_regulator_enable("vref_ddr"); -+ status = regulator_enable(vref); - if (status != 0) { - return status; - } - -- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -- -- status = stpmic1_regulator_enable("ldo3"); -+ status = regulator_enable(ldo3); - if (status != 0) { - return status; - } -- -- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - break; - - case STM32MP_LPDDR2: -@@ -635,70 +279,280 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) - * 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; -+ buck3 = regulator_get_by_name("buck3"); -+ if (buck3 == NULL) { -+ return -ENOENT; - } - -- status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); -- if (status != 0) { -- return status; -- } -+ regulator_get_range(buck3, &buck3_min_mv, NULL); - -- read_val &= ~STPMIC1_LDO3_MODE; -- read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; -- if (buck3_at_1v8) { -- read_val |= STPMIC1_LDO3_MODE; -+ if (buck3_min_mv != 1800) { -+ status = regulator_set_min_voltage(ldo3); -+ if (status != 0) { -+ return status; -+ } -+ } else { -+ status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS); -+ if (status != 0) { -+ return status; -+ } - } - -- status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); -+ status = regulator_set_min_voltage(buck2); - if (status != 0) { - return status; - } - -- if (pmic_operate(CMD_GET_MIN_VOLTAGE, "ldo3", &ldo3_mv) != 0) { -- return -EPERM; -- } -- -- status = stpmic1_regulator_voltage_set("ldo3", ldo3_mv); -+ status = regulator_enable(ldo3); - if (status != 0) { - return status; - } - -- status = stpmic1_regulator_voltage_set("buck2", buck2_mv); -+ status = regulator_enable(buck2); - if (status != 0) { - return status; - } - -- status = stpmic1_regulator_enable("ldo3"); -+ status = regulator_enable(vref); - if (status != 0) { - return status; - } -+ break; -+ -+ default: -+ break; -+ }; - -- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ return 0; -+} - -- status = stpmic1_regulator_enable("buck2"); -- if (status != 0) { -- return status; -+void pmic_switch_off(void) -+{ -+ stpmic1_switch_off(); -+ udelay(100); -+ -+ /* Shouldn't be reached */ -+ panic(); -+} -+ -+enum { -+ STPMIC1_BUCK1 = 0, -+ STPMIC1_BUCK2, -+ STPMIC1_BUCK3, -+ STPMIC1_BUCK4, -+ STPMIC1_LDO1, -+ STPMIC1_LDO2, -+ STPMIC1_LDO3, -+ STPMIC1_LDO4, -+ STPMIC1_LDO5, -+ STPMIC1_LDO6, -+ STPMIC1_VREF_DDR, -+ STPMIC1_BOOST, -+ STPMIC1_VBUS_OTG, -+ STPMIC1_SW_OUT, -+}; -+ -+static int pmic_set_state(const struct regul_description *desc, bool enable) -+{ -+ VERBOSE("%s: set state to %u\n", desc->node_name, enable); -+ -+ if (enable == STATE_ENABLE) { -+ return stpmic1_regulator_enable(desc->node_name); -+ } else { -+ return stpmic1_regulator_disable(desc->node_name); -+ } -+} -+ -+static int pmic_get_state(const struct regul_description *desc) -+{ -+ VERBOSE("%s: get state\n", desc->node_name); -+ -+ return stpmic1_is_regulator_enabled(desc->node_name); -+} -+ -+static int pmic_get_voltage(const struct regul_description *desc) -+{ -+ VERBOSE("%s: get volt\n", desc->node_name); -+ -+ return stpmic1_regulator_voltage_get(desc->node_name); -+} -+ -+static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) -+{ -+ VERBOSE("%s: get volt\n", desc->node_name); -+ -+ return stpmic1_regulator_voltage_set(desc->node_name, mv); -+} -+ -+static int pmic_list_voltages(const struct regul_description *desc, -+ const uint16_t **levels, size_t *count) -+{ -+ VERBOSE("%s: list volt\n", desc->node_name); -+ -+ return stpmic1_regulator_levels_mv(desc->node_name, levels, count); -+} -+ -+static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) -+{ -+ VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); -+ -+ switch (flag) { -+ case REGUL_OCP: -+ return stpmic1_regulator_icc_set(desc->node_name); -+ -+ case REGUL_ACTIVE_DISCHARGE: -+ return stpmic1_active_discharge_mode_set(desc->node_name); -+ -+ case REGUL_PULL_DOWN: -+ return stpmic1_regulator_pull_down_set(desc->node_name); -+ -+ case REGUL_MASK_RESET: -+ return stpmic1_regulator_mask_reset_set(desc->node_name); -+ -+ case REGUL_SINK_SOURCE: -+ return stpmic1_regulator_sink_mode_set(desc->node_name); -+ -+ case REGUL_ENABLE_BYPASS: -+ return stpmic1_regulator_bypass_mode_set(desc->node_name); -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+#if defined(IMAGE_BL32) -+static int driver_suspend(const struct regul_description *desc, uint8_t state, uint16_t mv) -+{ -+ int ret; -+ -+ VERBOSE("%s: suspend state:%d volt:%d\n", desc->node_name, (int)state, mv); -+ -+ ret = stpmic1_lp_copy_reg(desc->node_name); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if ((state & LP_STATE_OFF) != 0U) { -+ ret = stpmic1_lp_reg_on_off(desc->node_name, 0); -+ if (ret != 0) { -+ return ret; - } -+ } - -- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -+ if ((state & LP_STATE_ON) != 0U) { -+ ret = stpmic1_lp_reg_on_off(desc->node_name, 1); -+ if (ret != 0) { -+ return ret; -+ } -+ } - -- status = stpmic1_regulator_enable("vref_ddr"); -- if (status != 0) { -- return status; -+ if ((state & LP_STATE_SET_VOLT) != 0U) { -+ ret = stpmic1_lp_set_voltage(desc->node_name, mv); -+ if (ret != 0) { -+ return ret; - } -+ } - -- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); -- break; -+ return 0; -+} - -- default: -- break; -- }; -+static void driver_lock(const struct regul_description *desc) -+{ -+ if (stm32mp_lock_available()) { -+ spin_lock(&lock); -+ } -+} -+ -+static void driver_unlock(const struct regul_description *desc) -+{ -+ if (stm32mp_lock_available()) { -+ spin_unlock(&lock); -+ } -+} -+#endif -+ -+struct regul_ops pmic_ops = { -+ .set_state = pmic_set_state, -+ .get_state = pmic_get_state, -+ .set_voltage = pmic_set_voltage, -+ .get_voltage = pmic_get_voltage, -+ .list_voltages = pmic_list_voltages, -+ .set_flag = pmic_set_flag, -+#if defined(IMAGE_BL32) -+ .lock = driver_lock, -+ .unlock = driver_unlock, -+ .suspend = driver_suspend, -+#endif -+}; -+ -+#define DEFINE_REGU(name) { \ -+ .node_name = name, \ -+ .ops = &pmic_ops, \ -+ .driver_data = NULL, \ -+ .enable_ramp_delay = 1000, \ -+} -+ -+static const struct regul_description pmic_regs[] = { -+ [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), -+ [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), -+ [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), -+ [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), -+ [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), -+ [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), -+ [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), -+ [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), -+ [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), -+ [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), -+ [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), -+ [STPMIC1_BOOST] = DEFINE_REGU("boost"), -+ [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), -+ [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), -+}; -+ -+#define NB_REG ARRAY_SIZE(pmic_regs) -+ -+static int register_pmic(void) -+{ -+ void *fdt; -+ int pmic_node, regulators_node, subnode; -+ -+ VERBOSE("Register pmic\n"); -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ pmic_node = dt_get_pmic_node(fdt); -+ if (pmic_node < 0) { -+ return pmic_node; -+ } -+ -+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ if (regulators_node < 0) { -+ return -ENOENT; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, regulators_node) { -+ const char *reg_name = fdt_get_name(fdt, subnode, NULL); -+ const struct regul_description *desc; -+ unsigned int i; -+ int ret; -+ -+ for (i = 0; i < NB_REG; i++) { -+ desc = &pmic_regs[i]; -+ if (strcmp(desc->node_name, reg_name) == 0) { -+ break; -+ } -+ } -+ assert(i < NB_REG); -+ -+ ret = regulator_register(desc, subnode); -+ if (ret != 0) { -+ WARN("%s:%d failed to register %s\n", __func__, -+ __LINE__, reg_name); -+ return ret; -+ } -+ } - - return 0; - } -diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c -index a1db120dc1..c33ef47944 100644 ---- a/drivers/st/pmic/stpmic1.c -+++ b/drivers/st/pmic/stpmic1.c -@@ -17,15 +17,23 @@ struct regul_struct { - const uint16_t *voltage_table; - uint8_t voltage_table_size; - uint8_t control_reg; -+ uint8_t enable_mask; - uint8_t low_power_reg; - uint8_t pull_down_reg; - uint8_t pull_down; - uint8_t mask_reset_reg; - uint8_t mask_reset; -+ uint8_t icc_reg; -+ uint8_t icc_mask; - }; - - static struct i2c_handle_s *pmic_i2c_handle; - static uint16_t pmic_i2c_addr; -+/* -+ * Special mode corresponds to LDO3 in sink source mode or in bypass mode. -+ * LDO3 doesn't switch back from special to normal mode. -+ */ -+static bool ldo3_special_mode; - - /* Voltage tables in mV */ - static const uint16_t buck1_voltage_table[] = { -@@ -346,8 +354,11 @@ static const uint16_t ldo3_voltage_table[] = { - 3300, - 3300, - 3300, -- 500, -- 0xFFFF, /* VREFDDR */ -+}; -+ -+/* Special mode table is used for sink source OR bypass mode */ -+static const uint16_t ldo3_special_mode_table[] = { -+ 0, - }; - - static const uint16_t ldo5_voltage_table[] = { -@@ -431,104 +442,135 @@ static const struct regul_struct regulators_table[] = { - .voltage_table = buck1_voltage_table, - .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), - .control_reg = BUCK1_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .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, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = BUCK1_ICC_SHIFT, - }, - { - .dt_node_name = "buck2", - .voltage_table = buck2_voltage_table, - .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), - .control_reg = BUCK2_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .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, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = BUCK2_ICC_SHIFT, - }, - { - .dt_node_name = "buck3", - .voltage_table = buck3_voltage_table, - .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), - .control_reg = BUCK3_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .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, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = BUCK3_ICC_SHIFT, - }, - { - .dt_node_name = "buck4", - .voltage_table = buck4_voltage_table, - .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), - .control_reg = BUCK4_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .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, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = BUCK4_ICC_SHIFT, - }, - { - .dt_node_name = "ldo1", - .voltage_table = ldo1_voltage_table, - .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), - .control_reg = LDO1_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = LDO1_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = LDO1_MASK_RESET, -+ .icc_reg = LDO_ICC_TURNOFF_REG, -+ .icc_mask = LDO1_ICC_SHIFT, - }, - { - .dt_node_name = "ldo2", - .voltage_table = ldo2_voltage_table, - .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), - .control_reg = LDO2_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = LDO2_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = LDO2_MASK_RESET, -+ .icc_reg = LDO_ICC_TURNOFF_REG, -+ .icc_mask = LDO2_ICC_SHIFT, - }, - { - .dt_node_name = "ldo3", - .voltage_table = ldo3_voltage_table, - .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), - .control_reg = LDO3_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = LDO3_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = LDO3_MASK_RESET, -+ .icc_reg = LDO_ICC_TURNOFF_REG, -+ .icc_mask = LDO3_ICC_SHIFT, - }, - { - .dt_node_name = "ldo4", - .voltage_table = ldo4_voltage_table, - .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), - .control_reg = LDO4_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = LDO4_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = LDO4_MASK_RESET, -+ .icc_reg = LDO_ICC_TURNOFF_REG, -+ .icc_mask = LDO4_ICC_SHIFT, - }, - { - .dt_node_name = "ldo5", - .voltage_table = ldo5_voltage_table, - .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), - .control_reg = LDO5_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = LDO5_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = LDO5_MASK_RESET, -+ .icc_reg = LDO_ICC_TURNOFF_REG, -+ .icc_mask = LDO5_ICC_SHIFT, - }, - { - .dt_node_name = "ldo6", - .voltage_table = ldo6_voltage_table, - .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), - .control_reg = LDO6_CONTROL_REG, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = LDO6_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = LDO6_MASK_RESET, -+ .icc_reg = LDO_ICC_TURNOFF_REG, -+ .icc_mask = LDO6_ICC_SHIFT, - }, - { - .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, -+ .enable_mask = LDO_BUCK_ENABLE_MASK, - .low_power_reg = VREF_DDR_PWRCTRL_REG, - .mask_reset_reg = MASK_RESET_LDO_REG, - .mask_reset = VREF_DDR_MASK_RESET, -@@ -538,21 +580,27 @@ static const struct regul_struct regulators_table[] = { - .voltage_table = fixed_5v_voltage_table, - .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), - .control_reg = USB_CONTROL_REG, -- .mask_reset = BOOST_ENABLED, -+ .enable_mask = BOOST_ENABLED, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = BOOST_ICC_SHIFT, - }, - { - .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, -+ .enable_mask = USBSW_OTG_SWITCH_ENABLED, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = PWR_SW1_ICC_SHIFT, - }, - { - .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, -+ .enable_mask = SWIN_SWOUT_ENABLED, -+ .icc_reg = BUCK_ICC_TURNOFF_REG, -+ .icc_mask = PWR_SW2_ICC_SHIFT, - }, - }; - -@@ -607,8 +655,8 @@ int stpmic1_regulator_enable(const char *name) - { - const struct regul_struct *regul = get_regulator_data(name); - -- return stpmic1_register_update(regul->control_reg, LDO_BUCK_ENABLE_MASK, -- LDO_BUCK_ENABLE_MASK); -+ return stpmic1_register_update(regul->control_reg, regul->enable_mask, -+ regul->enable_mask); - } - - int stpmic1_regulator_disable(const char *name) -@@ -616,7 +664,7 @@ int stpmic1_regulator_disable(const char *name) - const struct regul_struct *regul = get_regulator_data(name); - - return stpmic1_register_update(regul->control_reg, 0, -- LDO_BUCK_ENABLE_MASK); -+ regul->enable_mask); - } - - bool stpmic1_is_regulator_enabled(const char *name) -@@ -628,7 +676,7 @@ bool stpmic1_is_regulator_enabled(const char *name) - panic(); - } - -- return (val & LDO_BUCK_ENABLE_MASK) == LDO_BUCK_ENABLE_MASK; -+ return (val & regul->enable_mask) == regul->enable_mask; - } - - int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) -@@ -637,6 +685,16 @@ int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) - const struct regul_struct *regul = get_regulator_data(name); - uint8_t mask; - -+ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) { -+ /* -+ * when the LDO3 is in special mode, we do not change voltage, -+ * because by setting voltage, the LDO would leaves sink-source -+ * mode. There is obviously no reason to leave sink-source mode -+ * at runtime. -+ */ -+ return 0; -+ } -+ - /* Voltage can be set for buck or ldo (except ldo4) regulators */ - if (strncmp(name, "buck", 4) == 0) { - mask = BUCK_VOLTAGE_MASK; -@@ -670,12 +728,74 @@ int stpmic1_regulator_mask_reset_set(const char *name) - { - const struct regul_struct *regul = get_regulator_data(name); - -+ if (regul->mask_reset_reg == 0U) { -+ return -EPERM; -+ } -+ - return stpmic1_register_update(regul->mask_reset_reg, - BIT(regul->mask_reset), - LDO_BUCK_RESET_MASK << - regul->mask_reset); - } - -+int stpmic1_regulator_icc_set(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ if (regul->mask_reset_reg == 0U) { -+ return -EPERM; -+ } -+ -+ return stpmic1_register_update(regul->icc_reg, -+ BIT(regul->icc_mask), -+ BIT(regul->icc_mask)); -+} -+ -+int stpmic1_regulator_sink_mode_set(const char *name) -+{ -+ if (strncmp(name, "ldo3", 4) != 0) { -+ return -EPERM; -+ } -+ -+ ldo3_special_mode = true; -+ -+ /* disable bypass mode, enable sink mode */ -+ return stpmic1_register_update(LDO3_CONTROL_REG, -+ LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT, -+ LDO3_BYPASS | LDO_VOLTAGE_MASK); -+} -+ -+int stpmic1_regulator_bypass_mode_set(const char *name) -+{ -+ if (strncmp(name, "ldo3", 4) != 0) { -+ return -EPERM; -+ } -+ -+ ldo3_special_mode = true; -+ -+ /* enable bypass mode, disable sink mode */ -+ return stpmic1_register_update(LDO3_CONTROL_REG, -+ LDO3_BYPASS, -+ LDO3_BYPASS | LDO_VOLTAGE_MASK); -+} -+ -+int stpmic1_active_discharge_mode_set(const char *name) -+{ -+ if (strncmp(name, "pwr_sw1", 7) == 0) { -+ return stpmic1_register_update(USB_CONTROL_REG, -+ VBUS_OTG_DISCHARGE, -+ VBUS_OTG_DISCHARGE); -+ } -+ -+ if (strncmp(name, "pwr_sw2", 7) == 0) { -+ return stpmic1_register_update(USB_CONTROL_REG, -+ SW_OUT_DISCHARGE, -+ SW_OUT_DISCHARGE); -+ } -+ -+ return -EPERM; -+} -+ - /* Low-power functions */ - int stpmic1_lp_copy_reg(const char *name) - { -@@ -732,6 +852,22 @@ int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts) - mask); - } - -+int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, -+ size_t *levels_count) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) { -+ *levels_count = ARRAY_SIZE(ldo3_special_mode_table); -+ *levels = ldo3_special_mode_table; -+ } else { -+ *levels_count = regul->voltage_table_size; -+ *levels = regul->voltage_table; -+ } -+ -+ return 0; -+} -+ - int stpmic1_regulator_voltage_get(const char *name) - { - const struct regul_struct *regul = get_regulator_data(name); -@@ -739,6 +875,10 @@ int stpmic1_regulator_voltage_get(const char *name) - uint8_t mask; - int status; - -+ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) { -+ return 0; -+ } -+ - /* Voltage can be set for buck or ldo (except ldo4) regulators */ - if (strncmp(name, "buck", 4) == 0) { - mask = BUCK_VOLTAGE_MASK; -diff --git a/drivers/st/regulator/regulator_fixed.c b/drivers/st/regulator/regulator_fixed.c -new file mode 100644 -index 0000000000..56593717f6 ---- /dev/null -+++ b/drivers/st/regulator/regulator_fixed.c -@@ -0,0 +1,91 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2020-2021, STMicroelectronics -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#ifndef PLAT_NB_FIXED_REGS -+#error "Missing PLAT_NB_FIXED_REGS" -+#endif -+ -+#define FIXED_NAME_LEN 32U -+ -+struct fixed_data { -+ char name[FIXED_NAME_LEN]; -+ uint16_t volt; -+ struct regul_description desc; -+}; -+ -+static struct fixed_data data[PLAT_NB_FIXED_REGS]; -+ -+static int fixed_set_state(const struct regul_description *desc, bool state) -+{ -+ return 0; -+} -+ -+static int fixed_get_state(const struct regul_description *desc) -+{ -+ return 1; -+} -+ -+static struct regul_ops fixed_ops = { -+ .set_state = fixed_set_state, -+ .get_state = fixed_get_state, -+}; -+ -+int fixed_regulator_register(void) -+{ -+ uint32_t count = 0; -+ void *fdt; -+ int node = 0; -+ -+ VERBOSE("fixed reg init!\n"); -+ -+ if (fdt_get_address(&fdt) == 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ do { -+ size_t len __unused; -+ int ret; -+ struct fixed_data *d = &data[count]; -+ const char *reg_name; -+ -+ node = fdt_node_offset_by_compatible(fdt, node, "regulator-fixed"); -+ if (node < 0) { -+ break; -+ } -+ -+ reg_name = fdt_get_name(fdt, node, NULL); -+ -+ VERBOSE("register fixed reg %s!\n", reg_name); -+ -+ len = snprintf(d->name, FIXED_NAME_LEN - 1, "%s", reg_name); -+ assert((len > 0) && (len < (FIXED_NAME_LEN - 1))); -+ -+ d->desc.node_name = d->name; -+ d->desc.driver_data = d; -+ d->desc.ops = &fixed_ops; -+ -+ ret = regulator_register(&d->desc, node); -+ if (ret != 0) { -+ WARN("%s:%d failed to register %s\n", __func__, -+ __LINE__, reg_name); -+ return ret; -+ } -+ -+ count++; -+ assert(count <= PLAT_NB_FIXED_REGS); -+ -+ } while (node > 0); -+ -+ return 0; -+} -diff --git a/drivers/st/regulator/stm32mp_dummy_regulator.c b/drivers/st/regulator/stm32mp_dummy_regulator.c -deleted file mode 100644 -index 1003aba054..0000000000 ---- a/drivers/st/regulator/stm32mp_dummy_regulator.c -+++ /dev/null -@@ -1,27 +0,0 @@ --/* -- * 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 -deleted file mode 100644 -index f0e4a4ae5c..0000000000 ---- a/drivers/st/regulator/stm32mp_regulator.c -+++ /dev/null -@@ -1,38 +0,0 @@ --/* -- * 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/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c -index c9a9e9aef8..5a4dde38cd 100644 ---- a/drivers/st/tamper/stm32_tamp.c -+++ b/drivers/st/tamper/stm32_tamp.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -11,8 +11,10 @@ - - #include - -+#include - #include - #include -+#include - #include - #include - #include -@@ -20,98 +22,190 @@ - - #define DT_TAMP_COMPAT "st,stm32-tamp" - /* STM32 Registers */ --#define STM32_TAMP_CR1 0x00U --#define STM32_TAMP_CR2 0x04U --#define STM32_TAMP_FLTCR 0x0CU --#define STM32_TAMP_ATCR 0x10U --#define STM32_TAMP_ATSEEDR 0x14U --#define STM32_TAMP_ATOR 0x18U --#define STM32_TAMP_SMCR 0x20U --#define STM32_TAMP_IER 0x2CU --#define STM32_TAMP_SR 0x30U --#define STM32_TAMP_SCR 0x3CU --#define STM32_TAMP_COUNTR 0x40U --#define STM32_TAMP_OR 0x50U --#define STM32_TAMP_HWCFGR2 0x3ECU --#define STM32_TAMP_HWCFGR1 0x3F0U --#define STM32_TAMP_VERR 0x3F4U --#define STM32_TAMP_IPIDR 0x3F8U --#define STM32_TAMP_SIDR 0x3FCU -- --/* STM32_TAMP_FLTCR bit fields */ --#define STM32_TAMP_FLTCR_TAMPFREQ GENMASK(2, 0) --#define STM32_TAMP_FLTCR_TAMPFLT GENMASK(4, 3) --#define STM32_TAMP_FLTCR_TAMPPRCH GENMASK(6, 5) --#define STM32_TAMP_FLTCR_TAMPPUDIS BIT(7) -- --/* STM32_TAMP_ATCR bit fields */ --#define STM32_TAMP_ATCR_ATCKSEL GENMASK(18, 16) --#define STM32_TAMP_ATCR_ATPER GENMASK(26, 24) --#define STM32_TAMP_ATCR_ATOSHARE BIT(30) --#define STM32_TAMP_ATCR_FLTEN BIT(31) -- --/* STM32_TAMP_ATOR bit fields */ --#define STM32_TAMP_PRNG GENMASK(7, 0) --#define STM32_TAMP_SEEDF BIT(14) --#define STM32_TAMP_INITS BIT(15) -- --/* STM32_TAMP_IER bit fields */ --#define STM32_TAMP_IER_TAMPXIE_ALL GENMASK(7, 0) --#define STM32_TAMP_IER_ITAMPXIE_ALL GENMASK(31, 16) -- --/* STM32_TAMP_SR bit fields */ --#define STM32_TAMP_SR_TAMPXF_MASK GENMASK(7, 0) --#define STM32_TAMP_SR_ITAMPXF_MASK GENMASK(31, 16) -- --/* STM32_TAMP_SMCR but fields */ --#define STM32_TAMP_SMCR_DPROT BIT(31) -- --/* STM32_TAMP_CFGR bit fields */ --#define STM32_TAMP_OR_OUT3RMP BIT(0) -- --/* STM32_TAMP_HWCFGR2 bit fields */ --#define STM32_TAMP_HWCFGR2_TZ GENMASK(11, 8) --#define STM32_TAMP_HWCFGR2_OR GENMASK(7, 0) -- --/* STM32_TAMP_HWCFGR1 bit fields */ --#define STM32_TAMP_HWCFGR1_BKPREG GENMASK(7, 0) --#define STM32_TAMP_HWCFGR1_TAMPER GENMASK(11, 8) --#define STM32_TAMP_HWCFGR1_ACTIVE GENMASK(15, 12) --#define STM32_TAMP_HWCFGR1_INTERN GENMASK(31, 16) -- --/* STM32_TAMP_VERR bit fields */ --#define STM32_TAMP_VERR_MINREV GENMASK(3, 0) --#define STM32_TAMP_VERR_MAJREV GENMASK(7, 4) -- --#define STM32_TAMP_MAX_INTERNAL 16U --#define STM32_TAMP_MAX_EXTERNAL 8U -+#define _TAMP_CR1 0x00U -+#define _TAMP_CR2 0x04U -+#define _TAMP_FLTCR 0x0CU -+#define _TAMP_ATCR1 0x10U -+#define _TAMP_ATSEEDR 0x14U -+#define _TAMP_ATOR 0x18U -+#define _TAMP_SMCR 0x20U -+#define _TAMP_IER 0x2CU -+#define _TAMP_SR 0x30U -+#define _TAMP_MISR 0x34U -+#define _TAMP_SMISR 0x38U -+#define _TAMP_SCR 0x3CU -+#define _TAMP_COUNTR 0x40U -+#define _TAMP_OR 0x50U -+#define _TAMP_HWCFGR2 0x3ECU -+#define _TAMP_HWCFGR1 0x3F0U -+#define _TAMP_VERR 0x3F4U -+#define _TAMP_IPIDR 0x3F8U -+#define _TAMP_SIDR 0x3FCU -+ -+/* _TAMP_CR1 bit filds */ -+#define _TAMP_CR1_ITAMP(id) BIT((id) + 16U) -+#define _TAMP_CR1_ETAMP(id) BIT((id)) -+ -+/* _TAMP_CR2 bit filds */ -+#define _TAMP_CR2_ETAMPTRG(id) BIT((id) + 24U) -+#define _TAMP_CR2_ETAMPMSK_MAX_ID 3U -+#define _TAMP_CR2_ETAMPMSK(id) BIT((id) + 16U) -+#define _TAMP_CR2_ETAMPNOER(id) BIT((id)) -+ -+/* _TAMP_FLTCR bit fields */ -+#define _TAMP_FLTCR_TAMPFREQ GENMASK(2, 0) -+#define _TAMP_FLTCR_TAMPFLT GENMASK(4, 3) -+#define _TAMP_FLTCR_TAMPPRCH GENMASK(6, 5) -+#define _TAMP_FLTCR_TAMPPUDIS BIT(7) -+ -+/* _TAMP_ATCR bit fields */ -+#define _TAMP_ATCR1_ATCKSEL GENMASK(18, 16) -+#define _TAMP_ATCR1_ATPER GENMASK(26, 24) -+#define _TAMP_ATCR1_COMMON_MASK GENMASK(31, 16) -+#define _TAMP_ATCR1_ETAMPAM(id) BIT((id)) -+#define _TAMP_ATCR1_ATOSEL_MASK(i) GENMASK(((i) + 1) * 2U + 7U, (i) * 2U + 8U) -+#define _TAMP_ATCR1_ATOSEL(i, o) (((o) - 1U) << ((i) * 2U + 8U)) -+ -+/* _TAMP_ATOR bit fields */ -+#define _TAMP_PRNG GENMASK(7, 0) -+#define _TAMP_SEEDF BIT(14) -+#define _TAMP_INITS BIT(15) -+ -+/* _TAMP_IER bit fields */ -+#define _TAMP_IER_ITAMP(id) BIT((id) + 16U) -+#define _TAMP_IER_ETAMP(id) BIT((id)) -+ -+/* _TAMP_SR bit fields */ -+#define _TAMP_SR_ETAMPXF_MASK GENMASK(7, 0) -+#define _TAMP_SR_ITAMPXF_MASK GENMASK(31, 16) -+#define _TAMP_SR_ITAMP(id) BIT((id) + 16U) -+#define _TAMP_SR_ETAMP(id) BIT((id)) -+ -+/* _TAMP_SCR bit fields */ -+#define _TAMP_SCR_ITAMP(id) BIT((id) + 16U) -+#define _TAMP_SCR_ETAMP(id) BIT((id)) -+ -+/* _TAMP_SMCR bit fields */ -+#define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK(7, 0) -+#define _TAMP_SMCR_BKPRWDPROT_SHIFT U(0) -+#define _TAMP_SMCR_BKPWDPROT_MASK GENMASK(23, 16) -+#define _TAMP_SMCR_BKPWDPROT_SHIFT U(16) -+#define _TAMP_SMCR_DPROT BIT(31) -+ -+/* _TAMP_OR bit fields */ -+#define _TAMP_OR_OUT3RMP_PI8 0U -+#define _TAMP_OR_OUT3RMP_PC13 BIT(0) -+ -+/* _TAMP_HWCFGR2 bit fields */ -+#define _TAMP_HWCFGR2_TZ GENMASK(11, 8) -+#define _TAMP_HWCFGR2_OR GENMASK(7, 0) -+ -+/* _TAMP_HWCFGR1 bit fields */ -+#define _TAMP_HWCFGR1_BKPREG GENMASK(7, 0) -+#define _TAMP_HWCFGR1_TAMPER GENMASK(11, 8) -+#define _TAMP_HWCFGR1_ACTIVE GENMASK(15, 12) -+#define _TAMP_HWCFGR1_INTERN GENMASK(31, 16) -+#define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U -+#define _TAMP_HWCFGR1_ITAMP(id) BIT((id) + 16U) -+ -+/* _TAMP_VERR bit fields */ -+#define _TAMP_VERR_MINREV GENMASK(3, 0) -+#define _TAMP_VERR_MAJREV GENMASK(7, 4) -+ -+#define _TAMP_NB_MONOTONIC_COUNTER 0x1 -+ -+/* -+ * Macro to manage bit manipulation when we work on local variable -+ * before writing only once to the real register -+ */ -+ -+#define CLRBITS(v, bits) (v) &= ~(bits) -+#define SETBITS(v, bits) (v) |= (bits) -+#define CLRSETBITS(v, mask, bits) (v) = ((v) & ~(mask)) | (bits) -+ -+struct stm32_tamp_int { -+ const uint32_t id; -+ uint32_t mode; -+ int (*func)(int id); -+}; -+ -+struct stm32_tamp_ext { -+ const uint32_t id; -+ uint32_t mode; -+ uint8_t out_pin; -+ int (*func)(int id); -+}; - - struct stm32_tamp_instance { - uintptr_t base; - uint32_t clock; - uint32_t hwconf1; - uint32_t hwconf2; -- uint16_t int_nbtamp; -- uint8_t ext_nbtamp; -- struct stm32_tamp_int *int_tamp; -- struct stm32_tamp_ext *ext_tamp; -+ uint32_t secret_list_conf; -+ uint32_t privilege_conf; -+ uint32_t secure_conf; -+ uint32_t passive_conf; -+ uint32_t active_conf; -+ struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT]; -+ struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT]; - }; - --static struct stm32_tamp_instance stm32_tamp; -+/* 0 is the expected initial values for all fields but .id */ -+static struct stm32_tamp_instance stm32_tamp = { -+ .int_tamp = { -+ { -+ .id = INT_TAMP1, -+ }, -+ { -+ .id = INT_TAMP2, -+ }, -+ { -+ .id = INT_TAMP3, -+ }, -+ { -+ .id = INT_TAMP4, -+ }, -+ { -+ .id = INT_TAMP5, -+ }, -+ { -+ .id = INT_TAMP8, -+ }, -+ }, -+ .ext_tamp = { -+ { -+ .id = EXT_TAMP1, -+ }, -+ { -+ .id = EXT_TAMP2, -+ }, -+ { -+ .id = EXT_TAMP3, -+ }, -+ } -+}; - --static void stm32_tamp_set_secured(unsigned long base) -+static void stm32_tamp_set_secure(unsigned long base, uint32_t mode) - { -- mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT); -+ if (mode & TAMP_REGS_IT_SECURE) { -+ mmio_clrbits_32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); -+ } else { -+ mmio_setbits_32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); -+ } - } - --static void stm32_tamp_configure_or(unsigned long base, uint32_t out3) -+static void stm32_tamp_set_privilege(unsigned long base __unused, uint32_t mode __unused) - { -- mmio_setbits_32(base + STM32_TAMP_OR, out3); - } - --static int stm32_tamp_seed_init(unsigned long base) -+static void stm32_tamp_set_output_pin(unsigned long base, uint32_t out) - { -- /* Need RNG access */ -+ mmio_setbits_32(base + _TAMP_OR, out); -+} -+ -+static int stm32_tamp_set_seed(unsigned long base) -+{ -+ /* Need RNG access. */ - uint32_t timeout = 100; - uint8_t idx; - -@@ -123,11 +217,10 @@ static int stm32_tamp_seed_init(unsigned long base) - } - - VERBOSE("Seed init %u\n", rnd); -- mmio_write_32(base + STM32_TAMP_ATSEEDR, rnd); -+ mmio_write_32(base + _TAMP_ATSEEDR, rnd); - } - -- while (((mmio_read_32(base + STM32_TAMP_ATOR) & -- STM32_TAMP_SEEDF) != 0U) && -+ while (((mmio_read_32(base + _TAMP_ATOR) & _TAMP_SEEDF) != 0U) && - (timeout != 0U)) { - timeout--; - } -@@ -139,129 +232,334 @@ static int stm32_tamp_seed_init(unsigned long base) - return 0; - } - --static void stm32_tamp_reset_register(unsigned long base) -+static bool is_int_tamp_id_valid(uint32_t id) - { -- /* Disable all internal tamper */ -- mmio_write_32(base + STM32_TAMP_CR1, 0U); -- -- /* Disable all external tamper */ -- mmio_write_32(base + STM32_TAMP_CR2, 0U); -+ if (id > _TAMP_HWCFGR1_ITAMP_MAX_ID) { -+ return false; -+ } - -- /* Clean configuration registers */ -- mmio_write_32(base + STM32_TAMP_FLTCR, 0U); -- mmio_write_32(base + STM32_TAMP_ATCR, 0U); -- mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT); -+ return (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_ITAMP(id)) -+ == _TAMP_HWCFGR1_ITAMP(id); -+} - -- /* Clean Tamper IT */ -- mmio_write_32(base + STM32_TAMP_IER, 0U); -- mmio_write_32(base + STM32_TAMP_SCR, ~0U); -+static bool is_ext_tamp_id_valid(uint32_t id) -+{ -+ if (id > PLAT_MAX_TAMP_EXT) { -+ return false; -+ } - -- mmio_clrbits_32(base + STM32_TAMP_OR, STM32_TAMP_OR_OUT3RMP); -+ return true; - } - --void stm32_tamp_write_mcounter(void) -+static int stm32_tamp_set_int_config(struct stm32_tamp_int *tamp_int, -+ uint32_t *cr1, uint32_t *cr3, uint32_t *ier) - { -- mmio_write_32(stm32_tamp.base + STM32_TAMP_COUNTR, 1U); -+ uint32_t id; -+ -+ if (tamp_int == NULL) { -+ return -EINVAL; -+ } -+ -+ id = tamp_int->id; -+ -+ if (!is_int_tamp_id_valid(id)) { -+ return -EINVAL; -+ } -+ -+ /* If etamp is disabled */ -+ if ((tamp_int->mode & TAMP_ENABLE) != TAMP_ENABLE) { -+ CLRBITS(*cr1, _TAMP_CR1_ITAMP(id)); -+ CLRBITS(*ier, _TAMP_IER_ITAMP(id)); -+ return 0; -+ } -+ -+ SETBITS(*cr1, _TAMP_CR1_ITAMP(id)); -+ SETBITS(*ier, _TAMP_IER_ITAMP(id)); -+ -+ return 0; - } - --void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list, -- uint16_t nb_tamper) -+static int stm32_tamp_set_ext_config(struct stm32_tamp_ext *tamp_ext, -+ uint32_t *cr1, uint32_t *cr2, -+ uint32_t *atcr1, uint32_t *atcr2, uint32_t *ier) - { -- uint16_t i; -+ uint32_t id; - -- assert(nb_tamper < STM32_TAMP_MAX_INTERNAL); -+ if (tamp_ext == NULL) { -+ return -EINVAL; -+ } - -- for (i = 0; i < nb_tamper; i++) { -- int id = tamper_list[i].id; -- uint32_t u_id; -+ id = tamp_ext->id; - -- if (id == -1) { -- continue; -- } -+ /* Exit if not a valid TAMP_ID */ -+ if (!is_ext_tamp_id_valid(id)) { -+ return -EINVAL; -+ } -+ -+ /* If etamp is disabled */ -+ if ((tamp_ext->mode & TAMP_ENABLE) != TAMP_ENABLE) { -+ CLRBITS(*cr1, _TAMP_CR1_ETAMP(id)); -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id)); -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPTRG(id)); -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPNOER(id)); -+ CLRBITS(*ier, _TAMP_IER_ETAMP(id)); -+ return 0; -+ } -+ -+ SETBITS(*cr1, _TAMP_CR1_ETAMP(id)); -+ -+ if ((tamp_ext->mode & TAMP_TRIG_ON) == TAMP_TRIG_ON) { -+ SETBITS(*cr2, _TAMP_CR2_ETAMPTRG(id)); -+ } else { -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPTRG(id)); -+ } -+ -+ if ((tamp_ext->mode & TAMP_ACTIVE) == TAMP_ACTIVE) { -+ SETBITS(*cr1, _TAMP_ATCR1_ETAMPAM(id)); -+ } else { -+ CLRBITS(*cr1, _TAMP_ATCR1_ETAMPAM(id)); -+ } -+ -+ if ((tamp_ext->mode & TAMP_NOERASE) == TAMP_NOERASE) { -+ SETBITS(*cr2, _TAMP_CR2_ETAMPNOER(id)); -+ } else { -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPNOER(id)); -+ } - -- u_id = (uint32_t)id; -+ /* Configure output pin: -+ * For the case out_pin = 0, we select same output pin than the input one. -+ */ -+ if (tamp_ext->out_pin == TAMPOUTSEL_SAME_AS_INPUT) { -+ tamp_ext->out_pin = id + 1; -+ } -+ -+ if (tamp_ext->out_pin < PLAT_MAX_TAMP_EXT + 1U) { -+ CLRSETBITS(*atcr1, _TAMP_ATCR1_ATOSEL_MASK(id), -+ _TAMP_ATCR1_ATOSEL(id, tamp_ext->out_pin)); -+ } - -- if ((stm32_tamp.hwconf1 & BIT(u_id + 16U)) != 0U) { -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1, -- BIT(u_id + 16U)); -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER, -- BIT(u_id + 16U)); -+ if (id < _TAMP_CR2_ETAMPMSK_MAX_ID) { -+ /* -+ * Only external TAMP 1, 2 and 3 can be masked -+ */ -+ if ((tamp_ext->mode & TAMP_EVT_MASK) == TAMP_EVT_MASK) { -+ /* -+ * ETAMP(id) event generates a trigger event. This ETAMP(id) is masked -+ * and internally cleared by hardware. The backup registers are not erased. -+ */ -+ CLRBITS(*ier, _TAMP_IER_ETAMP(id)); -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id)); -+ } else { -+ /* -+ * normal ETAMP interrupt: -+ * ETAMP(id) event generates a trigger event and TAMP(id)F must be cleared -+ * by software to * allow next tamper event detection. -+ */ -+ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id)); -+ CLRBITS(*ier, _TAMP_IER_ETAMP(id)); - } -+ } else { -+ /* other than 1,2,3 external TAMP, we want its interruption */ -+ CLRBITS(*ier, _TAMP_IER_ETAMP(id)); - } - -- stm32_tamp.int_tamp = tamper_list; -- stm32_tamp.int_nbtamp = nb_tamper; -+ return 0; - } - --void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list, -- uint8_t nb_tamper, uint32_t passive_conf, -- uint32_t active_conf) -+int stm32_tamp_set_secure_bkpregs(struct bkpregs_conf *bkpregs_conf) - { -- /* External configuration */ -- uint8_t i, active_tamp = 0; -+ uint32_t first_z2; -+ uint32_t first_z3; - -- assert(nb_tamper < STM32_TAMP_MAX_EXTERNAL); -+ if (bkpregs_conf == NULL) { -+ return -EINVAL; -+ } - -- /* Enable external Tamp */ -- for (i = 0; i < nb_tamper; i++) { -- int id = ext_tamper_list[i].id; -- uint32_t reg = 0, u_id; -+ first_z2 = bkpregs_conf->nb_zone1_regs; -+ first_z3 = bkpregs_conf->nb_zone1_regs + bkpregs_conf->nb_zone2_regs; - -- if (id == -1) { -- continue; -- } -+ if ((first_z2 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG)) || -+ (first_z3 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG))) { -+ return -ENODEV; -+ } -+ -+ mmio_clrsetbits_32(stm32_tamp.base + _TAMP_SMCR, -+ _TAMP_SMCR_BKPRWDPROT_MASK, -+ (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & -+ _TAMP_SMCR_BKPRWDPROT_MASK); - -- u_id = (uint32_t)id; -+ mmio_clrsetbits_32(stm32_tamp.base + _TAMP_SMCR, -+ _TAMP_SMCR_BKPWDPROT_MASK, -+ (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & -+ _TAMP_SMCR_BKPWDPROT_MASK); -+ return 0; -+} -+ -+int stm32_tamp_set_config(void) -+{ -+ int ret; -+ uint32_t i; -+ uint32_t cr1 = 0, cr2 = 0, cr3 = 0; -+ uint32_t atcr1 = 0, atcr2 = 0; -+ uint32_t fltcr = 0; -+ uint32_t ier = 0; -+ -+ /* Select access in secure or unsecure */ -+ stm32_tamp_set_secure(stm32_tamp.base, stm32_tamp.secure_conf); -+ -+ /* Select acces in privileged mode or unprivileged mode */ -+ stm32_tamp_set_privilege(stm32_tamp.base, stm32_tamp.privilege_conf); -+ -+ if (stm32_tamp.passive_conf != 0U) { -+ /* Filter mode register set */ -+ fltcr = stm32_tamp.passive_conf; -+ } - -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1, -- BIT(u_id)); -+ if (stm32_tamp.active_conf != 0U) { -+ /* Active mode configuration */ -+ CLRSETBITS(atcr1, _TAMP_ATCR1_COMMON_MASK, -+ (stm32_tamp.active_conf & _TAMP_ATCR1_COMMON_MASK)); -+ } - -- if (ext_tamper_list[i].mode == TAMP_TRIG_ON) { -- reg |= BIT(u_id + 24U); -+ for (i = 0U; i < PLAT_MAX_TAMP_INT; i++) { -+ ret = stm32_tamp_set_int_config(&(stm32_tamp.int_tamp[i]), -+ &cr1, &cr3, &ier); -+ if (ret != 0) { -+ return ret; - } -+ } - -- if (ext_tamper_list[i].mode == TAMP_ACTIVE) { -- active_tamp |= BIT(u_id); -+ for (i = 0U; i < PLAT_MAX_TAMP_EXT; i++) { -+ ret = stm32_tamp_set_ext_config(&(stm32_tamp.ext_tamp[i]), -+ &cr1, &cr2, &atcr1, &atcr2, &ier); -+ if (ret != 0) { -+ return ret; - } -+ } -+ -+ /* -+ * We apply configuration all in a row: -+ * As for active ext tamper "all the needed tampers must be enabled in the same write -+ * access". -+ */ -+ mmio_write_32(stm32_tamp.base + _TAMP_FLTCR, fltcr); -+ /* Active filter configuration applied only if not already done. */ -+ if (((mmio_read_32(stm32_tamp.base + _TAMP_ATOR) & _TAMP_INITS) != _TAMP_INITS)) { -+ mmio_write_32(stm32_tamp.base + _TAMP_ATCR1, atcr1); -+ } - -- if (ext_tamper_list[i].erase != 0U) { -- reg |= BIT(u_id); -+ mmio_write_32(stm32_tamp.base + _TAMP_CR1, cr1); -+ mmio_write_32(stm32_tamp.base + _TAMP_CR2, cr2); -+ /* If active tamper we reinit the seed. */ -+ if (stm32_tamp.active_conf != 0U) { -+ if (stm32_tamp_set_seed(stm32_tamp.base) != 0) { -+ ERROR("Active tamper: SEED not initialized\n"); -+ return -EPERM; - } -+ } - -- if (ext_tamper_list[i].evt_mask != 0U) { -- reg |= BIT(u_id + 16U); -- } else { -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER, -- BIT(u_id)); -+ /* Ack all pending interrupt */ -+ mmio_write_32(stm32_tamp.base + _TAMP_SCR, ~0U); -+ /* Enable interrupts. */ -+ mmio_write_32(stm32_tamp.base + _TAMP_IER, ier); -+ -+ return 0; -+} -+ -+int stm32_tamp_write_mcounter(int counter_idx) -+{ -+ mmio_write_32(stm32_tamp.base + _TAMP_COUNTR, 1U); -+ -+ return 0; -+} -+ -+uint32_t stm32_tamp_read_mcounter(int counter_idx) -+{ -+ return mmio_read_32(stm32_tamp.base + _TAMP_COUNTR); -+} -+ -+void stm32_tamp_configure_secret_list(uint32_t secret_list_conf) -+{ -+ stm32_tamp.secret_list_conf = secret_list_conf; -+} -+ -+void stm32_tamp_configure_privilege_access(uint32_t privilege_conf) -+{ -+ stm32_tamp.privilege_conf = privilege_conf; -+} -+ -+void stm32_tamp_configure_secure_access(uint32_t secure_conf) -+{ -+ stm32_tamp.secure_conf = secure_conf; -+} -+ -+void stm32_tamp_configure_passive(uint32_t passive_conf) -+{ -+ stm32_tamp.passive_conf = passive_conf; -+} -+ -+void stm32_tamp_configure_active(uint32_t active_conf) -+{ -+ stm32_tamp.active_conf = active_conf; -+} -+ -+int stm32_tamp_configure_internal(enum stm32_tamp_int_id id, uint32_t mode, int (*callback)(int id)) -+{ -+ uint32_t i; -+ uint32_t itamp_id = id; -+ struct stm32_tamp_int *tamp_int = NULL; -+ -+ /* Find internal Tamp struct*/ -+ for (i = 0U; i < PLAT_MAX_TAMP_INT; i++) { -+ if (stm32_tamp.int_tamp[i].id == itamp_id) { -+ tamp_int = &(stm32_tamp.int_tamp[i]); -+ break; - } -+ } - -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR2, reg); -+ if (tamp_int == NULL) { -+ return -EINVAL; - } - -- /* Filter mode register set */ -- mmio_write_32(stm32_tamp.base + STM32_TAMP_FLTCR, passive_conf); -+ tamp_int->mode = mode; -+ tamp_int->func = callback; - -- /* Active mode configuration */ -- if (active_tamp != 0U) { -- mmio_write_32(stm32_tamp.base + STM32_TAMP_ATCR, -- active_conf | active_tamp); -- if (stm32_tamp_seed_init(stm32_tamp.base) != 0) { -- ERROR("Active tamper: SEED not initialized\n"); -- panic(); -+ return 0; -+} -+ -+int stm32_tamp_configure_external(enum stm32_tamp_ext_id id, uint32_t mode, -+ enum stm32_tamp_ext_out_id out_pin, int (*callback)(int id)) -+{ -+ uint32_t i; -+ uint32_t etamp_id = id; -+ struct stm32_tamp_ext *tamp_ext = NULL; -+ -+ /* Find external Tamp struct */ -+ for (i = 0U; i < PLAT_MAX_TAMP_EXT; i++) { -+ if (stm32_tamp.ext_tamp[i].id == etamp_id) { -+ tamp_ext = &(stm32_tamp.ext_tamp[i]); -+ break; - } - } - -- stm32_tamp.ext_tamp = ext_tamper_list; -- stm32_tamp.ext_nbtamp = nb_tamper; -+ if (tamp_ext == NULL) { -+ return -EINVAL; -+ } -+ -+ tamp_ext->mode = mode; -+ tamp_ext->out_pin = out_pin; -+ tamp_ext->func = callback; -+ -+ return 0; - } - - void stm32_tamp_it_handler(void) - { -- uint32_t it = mmio_read_32(stm32_tamp.base + STM32_TAMP_SR); -+ uint32_t it = mmio_read_32(stm32_tamp.base + _TAMP_SR); -+ uint32_t int_it = it & _TAMP_SR_ITAMPXF_MASK; -+ uint32_t ext_it = it & _TAMP_SR_ETAMPXF_MASK; - uint8_t tamp = 0; - struct stm32_rtc_time tamp_ts; -- struct stm32_tamp_int *int_list = stm32_tamp.int_tamp; -- struct stm32_tamp_ext *ext_list = stm32_tamp.ext_tamp; - - if (stm32_rtc_is_timestamp_enable()) { - stm32_rtc_get_timestamp(&tamp_ts); -@@ -271,45 +569,53 @@ void stm32_tamp_it_handler(void) - tamp_ts.min, tamp_ts.sec); - } - -- /* Internal tamper interrupt */ -- if ((it & STM32_TAMP_IER_ITAMPXIE_ALL) == 0U) { -- goto tamp_ext; -- } -+ while ((int_it != 0U) && (tamp < PLAT_MAX_TAMP_INT)) { -+ int ret = -1; -+ uint32_t int_id = stm32_tamp.int_tamp[tamp].id; - -- while ((it != 0U) && (tamp < stm32_tamp.int_nbtamp)) { -- uint32_t int_id = (uint32_t)int_list[tamp].id; -+ if ((it & _TAMP_SR_ITAMP(int_id)) != 0U) { -+ if (stm32_tamp.int_tamp[tamp].func != NULL) { -+ ret = stm32_tamp.int_tamp[tamp].func(int_id); -+ } -+ -+ if (ret >= 0) { -+ mmio_setbits_32(stm32_tamp.base + _TAMP_SCR, -+ _TAMP_SR_ITAMP(int_id)); -+ ext_it &= ~_TAMP_SR_ITAMP(int_id); - -- if ((it & BIT(int_id + 16U)) != 0U) { -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, BIT(int_id + 16U)); -- it &= ~BIT(int_id + 16U); -- if (int_list[tamp].func != NULL) { -- int_list[tamp].func(int_id); -+ if (ret > 0) { -+ stm32mp_system_reset(); -+ } - } - } - tamp++; - } - --tamp_ext: - tamp = 0; - /* External tamper interrupt */ -- if ((it == 0U) || ((it & STM32_TAMP_IER_TAMPXIE_ALL) == 0U)) { -- return; -- } -+ while ((ext_it != 0U) && (tamp < PLAT_MAX_TAMP_EXT)) { -+ int ret = -1; -+ uint32_t ext_id = stm32_tamp.ext_tamp[tamp].id; - -- while ((it != 0U) && (tamp < stm32_tamp.ext_nbtamp)) { -- uint32_t ext_id = (uint32_t)ext_list[tamp].id; -- -- if ((it & BIT(ext_id)) != 0U) { -- if (ext_list[tamp].func != NULL) { -- ext_list[tamp].func(ext_id); -+ if ((ext_it & _TAMP_SR_ETAMP(ext_id)) != 0U) { -+ if (stm32_tamp.ext_tamp[tamp].func != NULL) { -+ ret = stm32_tamp.ext_tamp[tamp].func(ext_id); - } - -- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, -- BIT(ext_id)); -- it &= ~BIT(ext_id); -+ if (ret >= 0) { -+ mmio_setbits_32(stm32_tamp.base + _TAMP_SCR, -+ _TAMP_SCR_ETAMP(ext_id)); -+ ext_it &= ~_TAMP_SR_ETAMP(ext_id); -+ -+ if (ret > 0) { -+ stm32mp_system_reset(); -+ } -+ } - } - tamp++; - } -+ -+ gicv2_end_of_interrupt(STM32MP1_IRQ_TAMPSERRS); - } - - int stm32_tamp_init(void) -@@ -325,7 +631,7 @@ int stm32_tamp_init(void) - - node = dt_get_node(&dt_tamp, -1, DT_TAMP_COMPAT); - if (node < 0) { -- return -FDT_ERR_NOTFOUND; -+ return -EINVAL; - } - - assert(dt_tamp.base != 0U); -@@ -337,37 +643,34 @@ int stm32_tamp_init(void) - /* Init Tamp clock */ - clk_enable(stm32_tamp.clock); - -- /* Reset Tamp register without modifying backup registers conf */ -- stm32_tamp_reset_register(stm32_tamp.base); -- - /* Check if TAMP is enabled */ - if ((dt_tamp.status != DT_SECURE) && - (dt_tamp.status != DT_SHARED)) { - return 0; - } - -- stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR1); -- stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR2); -+ stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + _TAMP_HWCFGR1); -+ stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + _TAMP_HWCFGR2); - -- rev = mmio_read_32(stm32_tamp.base + STM32_TAMP_VERR); -- VERBOSE("STM32 TAMPER V%u.%u\n", (rev & STM32_TAMP_VERR_MAJREV) >> 4, -- rev & STM32_TAMP_VERR_MINREV); -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+ rev = mmio_read_32(stm32_tamp.base + _TAMP_VERR); -+ VERBOSE("STM32 TAMPER V%u.%u\n", (rev & _TAMP_VERR_MAJREV) >> 4, -+ rev & _TAMP_VERR_MINREV); -+#endif - -- if ((stm32_tamp.hwconf2 & STM32_TAMP_HWCFGR2_TZ) == 0U) { -+ if ((stm32_tamp.hwconf2 & _TAMP_HWCFGR2_TZ) == 0U) { - ERROR("Tamper IP doesn't support trustzone"); - return -EPERM; - } - -- stm32_tamp_set_secured(stm32_tamp.base); -- - if (dt_set_pinctrl_config(node) != -FDT_ERR_NOTFOUND) { - if (fdt_getprop(fdt, node, "st,out3-pc13", NULL) != NULL) { -- stm32_tamp_configure_or(stm32_tamp.base, 1); -+ stm32_tamp_set_output_pin(stm32_tamp.base, _TAMP_OR_OUT3RMP_PC13); - } - } - - if (stm32_gic_enable_spi(node, NULL) < 0) { -- panic(); -+ return -EPERM; - } - - if (fdt_getprop(fdt, node, "wakeup-source", NULL) != NULL) { -diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S -index 2cb04a88fc..5872157323 100644 ---- a/drivers/st/uart/aarch32/stm32_console.S -+++ b/drivers/st/uart/aarch32/stm32_console.S -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -45,7 +45,12 @@ func console_stm32_core_init - /* Check the input base address */ - cmp r0, #0 - beq core_init_fail --#if defined(IMAGE_BL2) -+#if !defined(IMAGE_BL2) -+ /* Skip UART initialization if it is already enabled */ -+ ldr r3, [r0, #USART_CR1] -+ ands r3, r3, #USART_CR1_UE -+ bne 1f -+#endif /* IMAGE_BL2 */ - /* Check baud rate and uart clock for sanity */ - cmp r1, #0 - beq core_init_fail -@@ -78,7 +83,7 @@ teack_loop: - ldr r3, [r0, #USART_ISR] - tst r3, #USART_ISR_TEACK - beq teack_loop --#endif /* IMAGE_BL2 */ -+1: - mov r0, #1 - bx lr - core_init_fail: -diff --git a/fdts/stm32mp15-ddr-512m-fw-config.dts b/fdts/stm32mp15-ddr-512m-fw-config.dts -deleted file mode 100644 -index 3d0722181a..0000000000 ---- a/fdts/stm32mp15-ddr-512m-fw-config.dts -+++ /dev/null -@@ -1,63 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -- */ -- --#include -- --#include --#include -- --/dts-v1/; -- --/ { -- dtb-registry { -- compatible = "fconf,dyn_cfg-dtb_registry"; -- -- hw-config { -- load-address = <0x0 STM32MP_HW_CONFIG_BASE>; -- max-size = ; -- id = ; -- }; -- -- nt_fw { -- load-address = <0x0 STM32MP_BL33_BASE>; -- max-size = ; -- id = ; -- }; -- --#ifdef AARCH32_SP_OPTEE -- tos_fw { -- load-address = <0x0 0x2FFC0000>; -- max-size = <0x0001F000>; -- id = ; -- }; --#else -- tos_fw { -- load-address = <0x0 STM32MP_BL32_BASE>; -- max-size = ; -- id = ; -- }; -- -- tos_fw-config { -- load-address = <0x0 STM32MP_BL32_DTB_BASE>; -- max-size = ; -- id = ; -- }; --#endif -- }; -- -- st-mem-firewall { -- compatible = "st,mem-firewall"; --#ifdef AARCH32_SP_OPTEE -- memory-ranges = < -- 0xc0000000 0x1e000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR -- 0xde000000 0x01e00000 TZC_REGION_S_RDWR 0 -- 0xdfe00000 0x00200000 TZC_REGION_S_NONE -- TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; --#else -- memory-ranges = < -- 0xc0000000 0x20000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; --#endif -- }; --}; -diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi -index 734943c0ea..43424a0079 100644 ---- a/fdts/stm32mp15-ddr.dtsi -+++ b/fdts/stm32mp15-ddr.dtsi -@@ -1,165 +1,129 @@ - // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - /* -- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved - */ - --/ { -- soc { -- ddr: ddr@5a003000{ -+&ddr { -+ st,mem-name = DDR_MEM_NAME; -+ st,mem-speed = ; -+ st,mem-size = ; - -- compatible = "st,stm32mp1-ddr"; -+ st,ctl-reg = < -+ DDR_MSTR -+ DDR_MRCTRL0 -+ DDR_MRCTRL1 -+ DDR_DERATEEN -+ DDR_DERATEINT -+ DDR_PWRCTL -+ DDR_PWRTMG -+ DDR_HWLPCTL -+ DDR_RFSHCTL0 -+ DDR_RFSHCTL3 -+ DDR_CRCPARCTL0 -+ DDR_ZQCTL0 -+ DDR_DFITMG0 -+ DDR_DFITMG1 -+ DDR_DFILPCFG0 -+ DDR_DFIUPD0 -+ DDR_DFIUPD1 -+ DDR_DFIUPD2 -+ DDR_DFIPHYMSTR -+ DDR_ODTMAP -+ DDR_DBG0 -+ DDR_DBG1 -+ DDR_DBGCMD -+ DDR_POISONCFG -+ DDR_PCCFG -+ >; - -- reg = <0x5A003000 0x550 -- 0x5A004000 0x234>; -+ st,ctl-timing = < -+ DDR_RFSHTMG -+ DDR_DRAMTMG0 -+ DDR_DRAMTMG1 -+ DDR_DRAMTMG2 -+ DDR_DRAMTMG3 -+ DDR_DRAMTMG4 -+ DDR_DRAMTMG5 -+ DDR_DRAMTMG6 -+ DDR_DRAMTMG7 -+ DDR_DRAMTMG8 -+ DDR_DRAMTMG14 -+ DDR_ODTCFG -+ >; - -- clocks = <&rcc AXIDCG>, -- <&rcc DDRC1>, --#if STM32MP_DDR_DUAL_AXI_PORT -- <&rcc DDRC2>, --#endif -- <&rcc DDRPHYC>, -- <&rcc DDRCAPB>, -- <&rcc DDRPHYCAPB>; -- -- clock-names = "axidcg", -- "ddrc1", --#if STM32MP_DDR_DUAL_AXI_PORT -- "ddrc2", --#endif -- "ddrphyc", -- "ddrcapb", -- "ddrphycapb"; -+ st,ctl-map = < -+ DDR_ADDRMAP1 -+ DDR_ADDRMAP2 -+ DDR_ADDRMAP3 -+ DDR_ADDRMAP4 -+ DDR_ADDRMAP5 -+ DDR_ADDRMAP6 -+ DDR_ADDRMAP9 -+ DDR_ADDRMAP10 -+ DDR_ADDRMAP11 -+ >; - -- st,mem-name = DDR_MEM_NAME; -- st,mem-speed = ; -- st,mem-size = ; -+ st,ctl-perf = < -+ DDR_SCHED -+ DDR_SCHED1 -+ DDR_PERFHPR1 -+ DDR_PERFLPR1 -+ DDR_PERFWR1 -+ DDR_PCFGR_0 -+ DDR_PCFGW_0 -+ DDR_PCFGQOS0_0 -+ DDR_PCFGQOS1_0 -+ DDR_PCFGWQOS0_0 -+ DDR_PCFGWQOS1_0 -+ DDR_PCFGR_1 -+ DDR_PCFGW_1 -+ DDR_PCFGQOS0_1 -+ DDR_PCFGQOS1_1 -+ DDR_PCFGWQOS0_1 -+ DDR_PCFGWQOS1_1 -+ >; - -- st,ctl-reg = < -- DDR_MSTR -- DDR_MRCTRL0 -- DDR_MRCTRL1 -- DDR_DERATEEN -- DDR_DERATEINT -- DDR_PWRCTL -- DDR_PWRTMG -- DDR_HWLPCTL -- DDR_RFSHCTL0 -- DDR_RFSHCTL3 -- DDR_CRCPARCTL0 -- DDR_ZQCTL0 -- DDR_DFITMG0 -- DDR_DFITMG1 -- DDR_DFILPCFG0 -- DDR_DFIUPD0 -- DDR_DFIUPD1 -- DDR_DFIUPD2 -- DDR_DFIPHYMSTR -- DDR_ODTMAP -- DDR_DBG0 -- DDR_DBG1 -- DDR_DBGCMD -- DDR_POISONCFG -- DDR_PCCFG -- >; -+ st,phy-reg = < -+ DDR_PGCR -+ DDR_ACIOCR -+ DDR_DXCCR -+ DDR_DSGCR -+ DDR_DCR -+ DDR_ODTCR -+ DDR_ZQ0CR1 -+ DDR_DX0GCR -+ DDR_DX1GCR -+ DDR_DX2GCR -+ DDR_DX3GCR -+ >; - -- st,ctl-timing = < -- DDR_RFSHTMG -- DDR_DRAMTMG0 -- DDR_DRAMTMG1 -- DDR_DRAMTMG2 -- DDR_DRAMTMG3 -- DDR_DRAMTMG4 -- DDR_DRAMTMG5 -- DDR_DRAMTMG6 -- DDR_DRAMTMG7 -- DDR_DRAMTMG8 -- DDR_DRAMTMG14 -- DDR_ODTCFG -- >; -- -- st,ctl-map = < -- DDR_ADDRMAP1 -- DDR_ADDRMAP2 -- DDR_ADDRMAP3 -- DDR_ADDRMAP4 -- DDR_ADDRMAP5 -- DDR_ADDRMAP6 -- DDR_ADDRMAP9 -- DDR_ADDRMAP10 -- DDR_ADDRMAP11 -- >; -- -- st,ctl-perf = < -- DDR_SCHED -- DDR_SCHED1 -- DDR_PERFHPR1 -- DDR_PERFLPR1 -- DDR_PERFWR1 -- DDR_PCFGR_0 -- DDR_PCFGW_0 -- DDR_PCFGQOS0_0 -- DDR_PCFGQOS1_0 -- DDR_PCFGWQOS0_0 -- DDR_PCFGWQOS1_0 --#if STM32MP_DDR_DUAL_AXI_PORT -- DDR_PCFGR_1 -- DDR_PCFGW_1 -- DDR_PCFGQOS0_1 -- DDR_PCFGQOS1_1 -- DDR_PCFGWQOS0_1 -- DDR_PCFGWQOS1_1 --#endif -- >; -- -- st,phy-reg = < -- DDR_PGCR -- DDR_ACIOCR -- DDR_DXCCR -- DDR_DSGCR -- DDR_DCR -- DDR_ODTCR -- DDR_ZQ0CR1 -- DDR_DX0GCR -- DDR_DX1GCR --#if STM32MP_DDR_DUAL_AXI_PORT -- DDR_DX2GCR -- DDR_DX3GCR --#endif -- >; -- -- st,phy-timing = < -- DDR_PTR0 -- DDR_PTR1 -- DDR_PTR2 -- DDR_DTPR0 -- DDR_DTPR1 -- DDR_DTPR2 -- DDR_MR0 -- DDR_MR1 -- DDR_MR2 -- DDR_MR3 -- >; -+ st,phy-timing = < -+ DDR_PTR0 -+ DDR_PTR1 -+ DDR_PTR2 -+ DDR_DTPR0 -+ DDR_DTPR1 -+ DDR_DTPR2 -+ DDR_MR0 -+ DDR_MR1 -+ DDR_MR2 -+ DDR_MR3 -+ >; - - #ifdef DDR_PHY_CAL_SKIP -- st,phy-cal = < -- DDR_DX0DLLCR -- DDR_DX0DQTR -- DDR_DX0DQSTR -- DDR_DX1DLLCR -- DDR_DX1DQTR -- DDR_DX1DQSTR --#if STM32MP_DDR_DUAL_AXI_PORT -- DDR_DX2DLLCR -- DDR_DX2DQTR -- DDR_DX2DQSTR -- DDR_DX3DLLCR -- DDR_DX3DQTR -- DDR_DX3DQSTR -+ st,phy-cal = < -+ DDR_DX0DLLCR -+ DDR_DX0DQTR -+ DDR_DX0DQSTR -+ DDR_DX1DLLCR -+ DDR_DX1DQTR -+ DDR_DX1DQSTR -+ DDR_DX2DLLCR -+ DDR_DX2DQTR -+ DDR_DX2DQSTR -+ DDR_DX3DLLCR -+ DDR_DX3DQTR -+ DDR_DX3DQSTR -+ >; - #endif -- >; --#endif -- -- status = "okay"; -- }; -- }; - }; -diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -index 127053b86a..6ca6293d4c 100644 ---- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -+++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -@@ -15,7 +15,7 @@ - * Save Date: 2020.02.20, save Time: 18:45:20 - */ - --#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000Khz" -+#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000kHz" - #define DDR_MEM_SPEED 533000 - #define DDR_MEM_SIZE 0x20000000 - -@@ -61,13 +61,13 @@ - #define DDR_DBGCMD 0x00000000 - #define DDR_POISONCFG 0x00000000 - #define DDR_PCCFG 0x00000010 --#define DDR_PCFGR_0 0x00000000 -+#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 0x00000000 -+#define DDR_PCFGR_1 0x00010000 - #define DDR_PCFGW_1 0x00000000 - #define DDR_PCFGQOS0_1 0x02100C03 - #define DDR_PCFGQOS1_1 0x00800040 -diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -index 5ae861fee1..548f69a197 100644 ---- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -@@ -15,7 +15,7 @@ - * Save Date: 2020.02.20, save Time: 18:49:33 - */ - --#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000Khz" -+#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000kHz" - #define DDR_MEM_SPEED 533000 - #define DDR_MEM_SIZE 0x40000000 - -@@ -61,13 +61,13 @@ - #define DDR_DBGCMD 0x00000000 - #define DDR_POISONCFG 0x00000000 - #define DDR_PCCFG 0x00000010 --#define DDR_PCFGR_0 0x00000000 -+#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 0x00000000 -+#define DDR_PCFGR_1 0x00010000 - #define DDR_PCFGW_1 0x00000000 - #define DDR_PCFGQOS0_1 0x02100C03 - #define DDR_PCFGQOS1_1 0x00800040 -diff --git a/fdts/stm32mp15-ddr-1g-fw-config.dts b/fdts/stm32mp15-fw-config.dts -similarity index 60% -rename from fdts/stm32mp15-ddr-1g-fw-config.dts -rename to fdts/stm32mp15-fw-config.dts -index c871463062..f5c4972061 100644 ---- a/fdts/stm32mp15-ddr-1g-fw-config.dts -+++ b/fdts/stm32mp15-fw-config.dts -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) - /* -- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -8,6 +8,21 @@ - #include - #include - -+#ifndef DDR_SIZE -+#error "DDR_SIZE is not defined" -+#endif -+ -+#define DDR_NS_BASE STM32MP_DDR_BASE -+#ifdef AARCH32_SP_OPTEE -+#define DDR_SHARE_SIZE 0x00200000 -+#define DDR_SHARE_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE)) -+#define DDR_SEC_SIZE 0x01e00000 -+#define DDR_SEC_BASE (DDR_SHARE_BASE - DDR_SEC_SIZE) -+#define DDR_NS_SIZE (DDR_SEC_BASE - DDR_NS_BASE) -+#else -+#define DDR_NS_SIZE DDR_SIZE -+#endif -+ - /dts-v1/; - - / { -@@ -51,13 +66,13 @@ - compatible = "st,mem-firewall"; - #ifdef AARCH32_SP_OPTEE - memory-ranges = < -- 0xc0000000 0x3e000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR -- 0xfe000000 0x01e00000 TZC_REGION_S_RDWR 0 -- 0xffe00000 0x00200000 TZC_REGION_S_NONE -+ DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR -+ DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0 -+ DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE - TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; - #else - memory-ranges = < -- 0xc0000000 0x40000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; -+ DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; - #endif - }; - }; -diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi -index 714d94710f..90b93387a6 100644 ---- a/fdts/stm32mp151.dtsi -+++ b/fdts/stm32mp151.dtsi -@@ -382,6 +382,24 @@ - secure-status = "disabled"; - }; - -+ ddr: ddr@5a003000{ -+ compatible = "st,stm32mp1-ddr"; -+ reg = <0x5A003000 0x550 0x5A004000 0x234>; -+ clocks = <&rcc AXIDCG>, -+ <&rcc DDRC1>, -+ <&rcc DDRC2>, -+ <&rcc DDRPHYC>, -+ <&rcc DDRCAPB>, -+ <&rcc DDRPHYCAPB>; -+ clock-names = "axidcg", -+ "ddrc1", -+ "ddrc2", -+ "ddrphyc", -+ "ddrcapb", -+ "ddrphycapb"; -+ status = "okay"; -+ }; -+ - usbphyc: usbphyc@5a006000 { - #address-cells = <1>; - #size-cells = <0>; -diff --git a/fdts/stm32mp157a-avenger96-fw-config.dts b/fdts/stm32mp157a-avenger96-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157a-avenger96-fw-config.dts -+++ b/fdts/stm32mp157a-avenger96-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157a-dk1-fw-config.dts b/fdts/stm32mp157a-dk1-fw-config.dts -index 256d0db935..d2be11aab2 100644 ---- a/fdts/stm32mp157a-dk1-fw-config.dts -+++ b/fdts/stm32mp157a-dk1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-512m-fw-config.dts" -+#define DDR_SIZE 0x20000000 /* 512MB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157a-ed1-fw-config.dts b/fdts/stm32mp157a-ed1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157a-ed1-fw-config.dts -+++ b/fdts/stm32mp157a-ed1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157a-ev1-fw-config.dts b/fdts/stm32mp157a-ev1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157a-ev1-fw-config.dts -+++ b/fdts/stm32mp157a-ev1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157c-dk2-fw-config.dts b/fdts/stm32mp157c-dk2-fw-config.dts -index 256d0db935..d2be11aab2 100644 ---- a/fdts/stm32mp157c-dk2-fw-config.dts -+++ b/fdts/stm32mp157c-dk2-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-512m-fw-config.dts" -+#define DDR_SIZE 0x20000000 /* 512MB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157c-ed1-fw-config.dts b/fdts/stm32mp157c-ed1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157c-ed1-fw-config.dts -+++ b/fdts/stm32mp157c-ed1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157c-ev1-fw-config.dts b/fdts/stm32mp157c-ev1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157c-ev1-fw-config.dts -+++ b/fdts/stm32mp157c-ev1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157d-dk1-fw-config.dts b/fdts/stm32mp157d-dk1-fw-config.dts -index 256d0db935..d2be11aab2 100644 ---- a/fdts/stm32mp157d-dk1-fw-config.dts -+++ b/fdts/stm32mp157d-dk1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-512m-fw-config.dts" -+#define DDR_SIZE 0x20000000 /* 512MB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157d-ed1-fw-config.dts b/fdts/stm32mp157d-ed1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157d-ed1-fw-config.dts -+++ b/fdts/stm32mp157d-ed1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157d-ev1-fw-config.dts b/fdts/stm32mp157d-ev1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157d-ev1-fw-config.dts -+++ b/fdts/stm32mp157d-ev1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157f-dk2-fw-config.dts b/fdts/stm32mp157f-dk2-fw-config.dts -index 256d0db935..d2be11aab2 100644 ---- a/fdts/stm32mp157f-dk2-fw-config.dts -+++ b/fdts/stm32mp157f-dk2-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-512m-fw-config.dts" -+#define DDR_SIZE 0x20000000 /* 512MB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157f-ed1-fw-config.dts b/fdts/stm32mp157f-ed1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157f-ed1-fw-config.dts -+++ b/fdts/stm32mp157f-ed1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp157f-ev1-fw-config.dts b/fdts/stm32mp157f-ev1-fw-config.dts -index 10f9402c4a..275406410e 100644 ---- a/fdts/stm32mp157f-ev1-fw-config.dts -+++ b/fdts/stm32mp157f-ev1-fw-config.dts -@@ -3,4 +3,5 @@ - * Copyright (c) 2020, STMicroelectronics - All Rights Reserved - */ - --#include "stm32mp15-ddr-1g-fw-config.dts" -+#define DDR_SIZE 0x40000000 /* 1GB */ -+#include "stm32mp15-fw-config.dts" -diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi -index e5166706ee..fa1a4baaca 100644 ---- a/fdts/stm32mp15xx-dkx.dtsi -+++ b/fdts/stm32mp15xx-dkx.dtsi -@@ -134,14 +134,15 @@ - - vtt_ddr: ldo3 { - regulator-name = "vtt_ddr"; -- regulator-min-microvolt = <500000>; -- regulator-max-microvolt = <750000>; - regulator-always-on; - regulator-over-current-protection; -+ st,regulator-sink-source; - }; - - vdd_usb: ldo4 { - regulator-name = "vdd_usb"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; - }; - - vdda: ldo5 { -@@ -161,7 +162,6 @@ - vref_ddr: vref_ddr { - regulator-name = "vref_ddr"; - regulator-always-on; -- regulator-over-current-protection; - }; - - bst_out: boost { -@@ -254,7 +254,7 @@ - CLK_CKPER_HSE - CLK_FMC_ACLK - CLK_QSPI_ACLK -- CLK_ETH_DISABLED -+ CLK_ETH_PLL4P - CLK_SDMMC12_PLL4P - CLK_DSI_DSIPLL - CLK_STGEN_HSE -diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi -index 540f5b9d97..cccf3e3595 100644 ---- a/fdts/stm32mp15xx-edx.dtsi -+++ b/fdts/stm32mp15xx-edx.dtsi -@@ -136,14 +136,15 @@ - - vtt_ddr: ldo3 { - regulator-name = "vtt_ddr"; -- regulator-min-microvolt = <500000>; -- regulator-max-microvolt = <750000>; - regulator-always-on; - regulator-over-current-protection; -+ st,regulator-sink-source; - }; - - vdd_usb: ldo4 { - regulator-name = "vdd_usb"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; - }; - - vdd_sd: ldo5 { -@@ -162,7 +163,6 @@ - vref_ddr: vref_ddr { - regulator-name = "vref_ddr"; - regulator-always-on; -- regulator-over-current-protection; - }; - - bst_out: boost { -@@ -256,7 +256,7 @@ - CLK_CKPER_HSE - CLK_FMC_ACLK - CLK_QSPI_ACLK -- CLK_ETH_DISABLED -+ CLK_ETH_PLL4P - CLK_SDMMC12_PLL4P - CLK_DSI_DSIPLL - CLK_STGEN_HSE -diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S -index 6bbcde2e0a..ed4ca273e9 100644 ---- a/include/arch/aarch32/el3_common_macros.S -+++ b/include/arch/aarch32/el3_common_macros.S -@@ -351,10 +351,21 @@ - * includes the data and NOBITS sections. This is done to - * safeguard against possible corruption of this memory by - * dirty cache lines in a system cache as a result of use by -- * an earlier boot loader stage. -+ * an earlier boot loader stage. If PIE is enabled however, -+ * RO sections including the GOT may be modified during -+ * pie fixup. Therefore, to be on the safe side, invalidate -+ * the entire image region if PIE is enabled. - * ----------------------------------------------------------------- - */ -+#if ENABLE_PIE -+#if SEPARATE_CODE_AND_RODATA -+ ldr r0, =__TEXT_START__ -+#else -+ ldr r0, =__RO_START__ -+#endif /* SEPARATE_CODE_AND_RODATA */ -+#else - ldr r0, =__RW_START__ -+#endif /* ENABLE_PIE */ - ldr r1, =__RW_END__ - sub r1, r1, r0 - bl inv_dcache_range -diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S -index 6f4143c5f5..20adcac2fd 100644 ---- a/include/arch/aarch64/el3_common_macros.S -+++ b/include/arch/aarch64/el3_common_macros.S -@@ -375,11 +375,24 @@ - * includes the data and NOBITS sections. This is done to - * safeguard against possible corruption of this memory by - * dirty cache lines in a system cache as a result of use by -- * an earlier boot loader stage. -+ * an earlier boot loader stage. If PIE is enabled however, -+ * RO sections including the GOT may be modified during -+ * pie fixup. Therefore, to be on the safe side, invalidate -+ * the entire image region if PIE is enabled. - * ------------------------------------------------------------- - */ -+#if ENABLE_PIE -+#if SEPARATE_CODE_AND_RODATA -+ adrp x0, __TEXT_START__ -+ add x0, x0, :lo12:__TEXT_START__ -+#else -+ adrp x0, __RO_START__ -+ add x0, x0, :lo12:__RO_START__ -+#endif /* SEPARATE_CODE_AND_RODATA */ -+#else - adrp x0, __RW_START__ - add x0, x0, :lo12:__RW_START__ -+#endif /* ENABLE_PIE */ - adrp x1, __RW_END__ - add x1, x1, :lo12:__RW_END__ - sub x1, x1, x0 -diff --git a/include/drivers/regulator.h b/include/drivers/regulator.h -new file mode 100644 -index 0000000000..392051f96e ---- /dev/null -+++ b/include/drivers/regulator.h -@@ -0,0 +1,160 @@ -+/* -+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+#ifndef REGULATOR_H -+#define REGULATOR_H -+ -+#include -+ -+#ifndef PLAT_NB_RDEVS -+#error "Missing PLAT_NB_RDEVS" -+#endif -+ -+#ifndef PLAT_NB_SUSPEND_MODES -+#error "Missing PLAT_NB_SUSPEND_MODES" -+#endif -+ -+const char *plat_get_lp_mode_name(int mode); -+ -+/* -+ * Consumer interface -+ */ -+ -+/* regulator-always-on : regulator should never be disabled */ -+#define REGUL_ALWAYS_ON BIT(0) -+/* -+ * regulator-boot-on: -+ * It's expected that this regulator was left on by the bootloader. -+ * The core shouldn't prevent it from being turned off later. -+ * The regulator is needed to exit from suspend so it is turned on during suspend entry. -+ */ -+#define REGUL_BOOT_ON BIT(1) -+/* regulator-over-current-protection: Enable over current protection. */ -+#define REGUL_OCP BIT(2) -+/* regulator-active-discharge: enable active discharge. */ -+#define REGUL_ACTIVE_DISCHARGE BIT(3) -+/* regulator-pull-down: Enable pull down resistor when the regulator is disabled. */ -+#define REGUL_PULL_DOWN BIT(4) -+/* -+ * st,mask-reset: set mask reset for the regulator, meaning that the regulator -+ * setting is maintained during pmic reset. -+ */ -+#define REGUL_MASK_RESET BIT(5) -+/* st,regulator-sink-source: set the regulator in sink source mode */ -+#define REGUL_SINK_SOURCE BIT(6) -+/* st,regulator-bypass: set the regulator in bypass mode */ -+#define REGUL_ENABLE_BYPASS BIT(7) -+ -+struct rdev *regulator_get_by_name(const char *node_name); -+ -+#if defined(IMAGE_BL32) -+struct rdev *regulator_get_by_regulator_name(const char *reg_name); -+#endif -+ -+struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name); -+ -+int regulator_enable(struct rdev *rdev); -+int regulator_disable(struct rdev *rdev); -+int regulator_is_enabled(const struct rdev *rdev); -+ -+int regulator_set_voltage(struct rdev *rdev, uint16_t volt); -+int regulator_set_min_voltage(struct rdev *rdev); -+int regulator_get_voltage(const struct rdev *rdev); -+ -+int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count); -+void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv); -+int regulator_set_flag(struct rdev *rdev, uint16_t flag); -+ -+/* -+ * Driver Interface -+ */ -+ -+/* set_state() arguments */ -+#define STATE_DISABLE false -+#define STATE_ENABLE true -+ -+/* suspend() arguments */ -+#define LP_STATE_OFF BIT(0) -+#define LP_STATE_ON BIT(1) -+#define LP_STATE_UNCHANGED BIT(2) -+#define LP_STATE_SET_VOLT BIT(3) -+ -+struct regul_description { -+ const char *node_name; -+ const struct regul_ops *ops; -+ const void *driver_data; -+ const char *supply_name; -+ const uint32_t enable_ramp_delay; -+}; -+ -+struct regul_ops { -+ int (*set_state)(const struct regul_description *desc, bool state); -+ int (*get_state)(const struct regul_description *desc); -+ int (*set_voltage)(const struct regul_description *desc, uint16_t mv); -+ int (*get_voltage)(const struct regul_description *desc); -+ int (*list_voltages)(const struct regul_description *desc, -+ const uint16_t **levels, size_t *count); -+ int (*set_flag)(const struct regul_description *desc, uint16_t flag); -+#if defined(IMAGE_BL32) -+ void (*lock)(const struct regul_description *desc); -+ void (*unlock)(const struct regul_description *desc); -+ int (*suspend)(const struct regul_description *desc, uint8_t state, -+ uint16_t mv); -+#endif -+}; -+ -+int regulator_register(const struct regul_description *desc, int node); -+ -+/* -+ * Internal regulator structure -+ * The structure is internal to the core, and the content should not be used -+ * by a consumer nor a driver. -+ */ -+struct rdev { -+ const struct regul_description *desc; -+ -+ int32_t phandle; -+ -+ uint16_t min_mv; -+ uint16_t max_mv; -+ -+ uint16_t flags; -+ -+ uint32_t enable_ramp_delay; -+#if defined(IMAGE_BL32) -+ const char *reg_name; -+ -+ uint8_t use_count; -+ -+ int32_t supply_phandle; -+ struct rdev *supply_dev; -+ -+ uint8_t lp_state[PLAT_NB_SUSPEND_MODES]; -+ uint16_t lp_mv[PLAT_NB_SUSPEND_MODES]; -+#endif -+}; -+ -+#if defined(IMAGE_BL32) -+ -+/* Boot and init */ -+int regulator_core_config(void); -+int regulator_core_cleanup(void); -+ -+/* Suspend resume operations */ -+#define PLAT_BACKUP_REGULATOR_SIZE (sizeof(int8_t) * PLAT_NB_RDEVS) -+ -+int regulator_core_suspend(int mode); -+int regulator_core_resume(void); -+ -+void regulator_core_backup_context(void *backup_area, size_t backup_size); -+void regulator_core_restore_context(void *backup_area, size_t backup_size); -+ -+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE -+void regulator_core_dump(void); -+#endif -+ -+#endif -+ -+#endif /* REGULATOR_H */ -diff --git a/include/drivers/st/regulator_fixed.h b/include/drivers/st/regulator_fixed.h -new file mode 100644 -index 0000000000..b03c6e38c6 ---- /dev/null -+++ b/include/drivers/st/regulator_fixed.h -@@ -0,0 +1,12 @@ -+/* -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef REGULATOR_FIXED_H -+#define REGULATOR_FIXED_H -+ -+int fixed_regulator_register(void); -+ -+#endif /* REGULATOR_FIXED_H */ -diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h -index e241f584f7..b072345159 100644 ---- a/include/drivers/st/stm32_gpio.h -+++ b/include/drivers/st/stm32_gpio.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -52,6 +52,7 @@ 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, uint8_t status); - void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); -+void set_gpio_reset_cfg(uint32_t bank, uint32_t pin); - #endif /*__ASSEMBLER__*/ - - #endif /* STM32_GPIO_H */ -diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h -index 5b4bd0e167..af02b91ea5 100644 ---- a/include/drivers/st/stm32_sdmmc2.h -+++ b/include/drivers/st/stm32_sdmmc2.h -@@ -10,7 +10,7 @@ - #include - - #include --#include -+#include - - struct stm32_sdmmc2_params { - uintptr_t reg_base; -@@ -25,7 +25,7 @@ struct stm32_sdmmc2_params { - unsigned int reset_id; - unsigned int max_freq; - bool use_dma; -- struct stm32mp_regulator vmmc_regu; -+ struct rdev *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 -index 424cbb205a..11dc96df69 100644 ---- a/include/drivers/st/stm32_tamp.h -+++ b/include/drivers/st/stm32_tamp.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2014-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -9,22 +9,22 @@ - - /* Internal Tamper */ - enum stm32_tamp_int_id { -- ITAMP1 = 0, -- ITAMP2, -- ITAMP3, -- ITAMP4, -- ITAMP5, -- ITAMP6, -- ITAMP7, -- ITAMP8, -- ITAMP9, -- ITAMP10, -- ITAMP11, -- ITAMP12, -- ITAMP13, -- ITAMP14, -- ITAMP15, -- ITAMP16 -+ INT_TAMP1 = 0, -+ INT_TAMP2, -+ INT_TAMP3, -+ INT_TAMP4, -+ INT_TAMP5, -+ INT_TAMP6, -+ INT_TAMP7, -+ INT_TAMP8, -+ INT_TAMP9, -+ INT_TAMP10, -+ INT_TAMP11, -+ INT_TAMP12, -+ INT_TAMP13, -+ INT_TAMP14, -+ INT_TAMP15, -+ INT_TAMP16 - }; - - /* External Tamper */ -@@ -39,95 +39,111 @@ enum stm32_tamp_ext_id { - EXT_TAMP8 - }; - --enum stm32_tamp_state { -- TAMP_DISABLE = 0, -- TAMP_ENABLE -+/* Out pin to compare for external Tamper */ -+enum stm32_tamp_ext_out_id { -+ TAMPOUTSEL_SAME_AS_INPUT = 0, -+ TAMPOUTSEL1 = 1, -+ TAMPOUTSEL2, -+ TAMPOUTSEL3, -+ TAMPOUTSEL4, -+ TAMPOUTSEL5, -+ TAMPOUTSEL6, -+ TAMPOUTSEL7, -+ TAMPOUTSEL8, - }; - --#define TAMP_UNUSED {.id = -1} -+/* Define number of backup registers in zone 1 and zone 2 (remaining are in -+ * zone 3) -+ * -+ * backup registers in zone 1 : read/write only in secure mode -+ * zone 2 : write only in secure mode, read in secure -+ * and non-secure mode -+ * zone 3 : read/write in secure and non-secure mode -+ * -+ * Protection zone 1 if nb_zone1_regs == 0 no backup register are in zone 1 -+ * else backup registers from TAMP_BKP0R to TAMP_BKPxR -+ * with x = nb_zone1_regs - 1 are in zone 1. -+ * Protection zone 2 if nb_zone2_regs == 0 no backup register are in zone 2 -+ * else backup registers from TAMP_BKPyR with y = nb_zone1_regs -+ * to TAMP_BKPzR with z = (nb_zone1_regs1 + nb_zone2_regs - 1) -+ * are in zone 2. -+ * Protection zone 3 backup registers from TAMP_BKPtR -+ * with t = nb_zone1_regs1 + nb_zone2_regs to last backup -+ * register are in zone 3. -+ */ -+struct bkpregs_conf { -+ uint32_t nb_zone1_regs; -+ uint32_t nb_zone2_regs; -+}; - --/* define TAMPER modes */ -+/* Define TAMPER modes */ -+#define TAMP_DISABLE 0x0U -+#define TAMP_ENABLE 0x1U - #define TAMP_TRIG_OFF 0x0U --#define TAMP_TRIG_ON 0x1U --#define TAMP_ACTIVE 0x2U -+#define TAMP_TRIG_ON 0x2U -+#define TAMP_ACTIVE 0x4U - #define TAMP_ERASE 0x0U --#define TAMP_NOERASE 0x1U -+#define TAMP_NOERASE 0x8U - #define TAMP_NO_EVT_MASK 0x0U --#define TAMP_EVT_MASK 0x1U -- --/* define Passive FILTER mode */ --#define TAMP_FILTER_PRECHARGE 0x0U --#define TAMP_FILTER_PULL_UP_DISABLE 0x1U --#define TAMP_FILTER_DURATION_1_CYCLE 0x0U --#define TAMP_FILTER_DURATION_2_CYCLES 0x1U --#define TAMP_FILTER_DURATION_3_CYCLES 0x2U --#define TAMP_FILTER_DURATION_4_CYCLES 0x3U --#define TAMP_FILTER_COUNT_1 0x0U --#define TAMP_FILTER_COUNT_2 0x1U --#define TAMP_FILTER_COUNT_4 0x2U --#define TAMP_FILTER_COUNT_8 0x3U --#define TAMP_FILTER_SAMPLING_32768 0x0U --#define TAMP_FILTER_SAMPLING_16384 0x1U --#define TAMP_FILTER_SAMPLING_8192 0x2U --#define TAMP_FILTER_SAMPLING_4096 0x3U --#define TAMP_FILTER_SAMPLING_2048 0x4U --#define TAMP_FILTER_SAMPLING_1024 0x5U --#define TAMP_FILTER_SAMPLING_512 0x6U --#define TAMP_FILTER_SAMPLING_256 0x7U -- --/* define active filter */ --#define TAMP_ACTIVE_FILTER_OFF 0x0U --#define TAMP_ACTIVE_FILTER_ON 0x1U --#define TAMP_ACTIVE_ATO_DEDICATED 0x0U --#define TAMP_ACTIVE_ATO_TAMPOUTSEL 0x1U --#define TAMP_ACTIVE_APER_1_OUTPUT 0x0U --#define TAMP_ACTIVE_APER_2_OUTPUTS 0x1U --#define TAMP_ACTIVE_APER_3_4_OUTPUTS 0x2U --#define TAMP_ACTIVE_APER_5_OUTPUTS 0x3U --#define TAMP_ACTIVE_CKSEL_DIV_0 0x0U --#define TAMP_ACTIVE_CKSEL_DIV_2 0x1U --#define TAMP_ACTIVE_CKSEL_DIV_4 0x2U --#define TAMP_ACTIVE_CKSEL_DIV_8 0x3U --#define TAMP_ACTIVE_CKSEL_DIV_16 0x4U --#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_EXT(tamp_id, trig, erase, mask) (((tamp_id) << 3) | ((trig) << 2)\ -- | ((erase) << 1) | (mask)) -- --#define TAMP_FLTCR(precharge, duration, count, sample) (((precharge) << 7) |\ -- ((duration) << 5) |\ -- ((count) << 3) |\ -- (sample)) -- --#define TAMP_ACT(filter, ato, aper, atcksel, atosel) (((filter) << 31) |\ -- ((ato) << 30) |\ -- ((aper) << 24) |\ -- ((atcksel) << 16) |\ -- (atosel) << 8) -- --struct stm32_tamp_int { -- int id; -- void (*func)(int id); --}; -- --struct stm32_tamp_ext { -- int id; -- uint8_t mode; -- uint8_t erase; -- uint8_t evt_mask; -- void (*func)(int id); --}; -+#define TAMP_EVT_MASK 0x10U -+ -+/* Define Passive FILTER mode */ -+#define TAMP_FILTER_TAMPPUDIS_OFFSET 7U -+#define TAMP_FILTER_PRECHARGE (0x0U << TAMP_FILTER_TAMPPUDIS_OFFSET) -+#define TAMP_FILTER_PULL_UP_DISABLE (0x1U << TAMP_FILTER_TAMPPUDIS_OFFSET) -+#define TAMP_FILTER_TAMPPRCH_OFFSET 5U -+#define TAMP_FILTER_DURATION_1_CYCLE (0x0U << TAMP_FILTER_TAMPPRCH_OFFSET) -+#define TAMP_FILTER_DURATION_2_CYCLES (0x1U << TAMP_FILTER_TAMPPRCH_OFFSET) -+#define TAMP_FILTER_DURATION_4_CYCLES (0x2U << TAMP_FILTER_TAMPPRCH_OFFSET) -+#define TAMP_FILTER_DURATION_8_CYCLES (0x3U << TAMP_FILTER_TAMPPRCH_OFFSET) -+#define TAMP_FILTER_TAMPFLT_OFFSET 3U -+#define TAMP_FILTER_COUNT_1 (0x0U << TAMP_FILTER_TAMPFLT_OFFSET) -+#define TAMP_FILTER_COUNT_2 (0x1U << TAMP_FILTER_TAMPFLT_OFFSET) -+#define TAMP_FILTER_COUNT_4 (0x2U << TAMP_FILTER_TAMPFLT_OFFSET) -+#define TAMP_FILTER_COUNT_8 (0x3U << TAMP_FILTER_TAMPFLT_OFFSET) -+#define TAMP_FILTER_TAMPFREQ_OFFSET 0U -+#define TAMP_FILTER_SAMPLING_32768 (0x0U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_16384 (0x1U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_8192 (0x2U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_4096 (0x3U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_2048 (0x4U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_1024 (0x5U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_512 (0x6U << TAMP_FILTER_TAMPFREQ_OFFSET) -+#define TAMP_FILTER_SAMPLING_256 (0x7U << TAMP_FILTER_TAMPFREQ_OFFSET) -+ -+/* Define active filter */ -+#define TAMP_ACTIVE_FLTEN_OFFSET 31U -+#define TAMP_ACTIVE_FILTER_OFF (0x0U << TAMP_ACTIVE_FLTEN_OFFSET) -+#define TAMP_ACTIVE_FILTER_ON (0x1U << TAMP_ACTIVE_FLTEN_OFFSET) -+#define TAMP_FILTER_ATOSHARE_OFFSET 30U -+#define TAMP_FILTER_USE_DEDICATED_OUT (0x0U << TAMP_FILTER_ATOSHARE_OFFSET) -+#define TAMP_FILTER_SELECT_OUT (0x1U << TAMP_FILTER_ATOSHARE_OFFSET) -+#define TAMP_ACTIVE_ATPER_OFFSET 24U -+#define TAMP_ACTIVE_ATPER_1_OUTPUT (0x0U << TAMP_ACTIVE_ATPER_OFFSET) -+#define TAMP_ACTIVE_ATPER_2_OUTPUTS (0x1U << TAMP_ACTIVE_ATPER_OFFSET) -+#define TAMP_ACTIVE_ATPER_3_4_OUTPUTS (0x2U << TAMP_ACTIVE_ATPER_OFFSET) -+#define TAMP_ACTIVE_ATPER_5_OUTPUTS (0x3U << TAMP_ACTIVE_ATPER_OFFSET) -+#define TAMP_ACTIVE_ATCKSEL_OFFSET 16U -+#define TAMP_ACTIVE_CKSEL_DIV_0 (0x0U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_2 (0x1U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_4 (0x2U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_8 (0x3U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_16 (0x4U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_32 (0x5U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_64 (0x6U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+#define TAMP_ACTIVE_CKSEL_DIV_128 (0x7U << TAMP_ACTIVE_ATCKSEL_OFFSET) -+ -+/* Define secure mode acces */ -+/* Tamper configuration and interrupt can be written when the APB access is secure or nonsecure.*/ -+#define TAMP_REGS_IT_UNSECURE 0U -+/* Tamper configuration and interrupt can be written only when the APB access is secure.*/ -+#define TAMP_REGS_IT_SECURE BIT(31) - - /* -- * stm32_tamp_write_mcounter : Increase monotonic counter -+ * stm32_tamp_write_mcounter : Increase monotonic counter[counter_idx] - */ --void stm32_tamp_write_mcounter(void); -+int stm32_tamp_write_mcounter(int counter_idx); -+uint32_t stm32_tamp_read_mcounter(int counter_idx); - - /* - * stm32_tamp_it_handler : Interrupt handler -@@ -135,24 +151,69 @@ void stm32_tamp_write_mcounter(void); - void stm32_tamp_it_handler(void); - - /* -- * stm32_tamp_configure_internal: Configure internal tamper -- * tamper_list: List of tamper to enable -- * nb_tamper: Number of tamper in list -+ * stm32_tamp_configure_secure_access: Configure which registers can be -+ * read/write from unsecure world -+ * secure_conf is a bit field from TAMP_.*_{UN,}SECURE define -+ */ -+void stm32_tamp_configure_secure_access(uint32_t secure_conf); -+ -+/* -+ * stm32_tamp_configure_privilege_access: Configure which registers can be -+ * read/write from unpriviliged world -+ * privilege_conf is a bit field from TAMP_.*_{UN,}PRIVILEGE define -+ */ -+void stm32_tamp_configure_privilege_access(uint32_t privilege_conf); -+ -+/* -+ * stm32_tamp_configure_passive: Configure passive mode -+ * passive_conf is a bit field from TAMP_FILTER_* define -+ */ -+void stm32_tamp_configure_passive(uint32_t passive_conf); -+ -+/* -+ * stm32_tamp_configure_ctive: Configure active mode -+ * passive_conf is a bit field from TAMP_ACTIVE_* define -+ */ -+void stm32_tamp_configure_active(uint32_t active_conf); -+ -+/* -+ * stm32_tamp_configure_internal: Configure one internal tamper -+ * id: internal tamper id -+ * mode: bitmask from TAMPER modes define -+ * callback: function to call when tamper is raised (can be NULL), -+ * called in interrupt context, -+ * if callback returns negative value, blocked secrets stay blocked -+ * (driver doesn't release this specific tamper). -+ * if callback returns 0 this specific tamp is ack (in case of no-erase -+ * tamper, blocked secret are unblocked) -+ * if callback returns positive value, this specific tamp is ack (in -+ * case of no-erase tamper, blocked secret are unblocked) and system is -+ * rebooted). -+ * -+ * return: -EINVAL if 'id' is not a valid internal tamp id, else 0 - */ --void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list, -- uint16_t nb_tamper); -+int stm32_tamp_configure_internal(enum stm32_tamp_int_id id, uint32_t mode, -+ int (*callback)(int id)); - - /* -- * stm32_tamp_configure_external: Configure external tamper and associated -- * configuration for filtering -- * ext_tamp_list: List of external tamper to configure -- * nb_tamper: Number of tamper in list -- * passive_conf: Filter configuration -- * active_conf: Configuration for active tamper -+ * stm32_tamp_configure_external: Configure one external tamper -+ * id: external tamper id -+ * mode: bitmask from TAMPER modes define -+ * pin_out; output pin connected to input pin (linekd with selected ext tamp id) -+ * callback: function to call when tamper is raised (can be NULL), -+ * called in interrupt context, -+ * if callback returns negative value, blocked secrets stay blocked -+ * (driver doesn't release this specific tamper). -+ * if callback returns 0 this specific tamp is ack (in case of no-erase -+ * tamper, blocked secret are unblocked) -+ * if callback returns positive value, this specific tamp is ack (in -+ * case of no-erase tamper, blocked secret are unblocked) and system is -+ * rebooted). -+ * -+ * return: -EINVAL if 'id' is not a valid external tamp id, else 0 - */ --void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list, -- uint8_t nb_tamper, uint32_t passive_conf, -- uint32_t active_conf); -+int stm32_tamp_configure_external(enum stm32_tamp_ext_id id, uint32_t mode, -+ enum stm32_tamp_ext_out_id out_pin, int (*callback)(int id)); - - /* - * stm32_tamp_init: Initialize tamper from DT -@@ -160,4 +221,32 @@ void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list, - */ - int stm32_tamp_init(void); - -+/* -+ * stm32_tamp_set_secure_bkprwregs : Configure backup registers zone. -+ * registers in zone 1 : read/write only in secure mode -+ * zone 2 : write only in secure mode, read in secure and non-secure mode -+ * zone 3 : read/write in secure and non-secure mode -+ * -+ * bkpregs_conf : a pointer to struct bkpregs_conf that define the number of registers in zone 1 -+ * and zone 2 (remaining backup registers will be in zone 3). -+ * -+ * return 0 if OK, -ENODEV if zone 1 and/or zone 2 definition are out of range. -+ */ -+int stm32_tamp_set_secure_bkpregs(struct bkpregs_conf *bkpregs_conf); -+ -+/* -+ * stm32_tamp_set_config: apply configuration -+ * default one if no previous call to any of : -+ * stm32_tamp_configure_passive() -+ * stm32_tamp_configure_active() -+ * stm32_tamp_configure_internal() -+ * stm32_tamp_configure_external() -+ * stm32_tamp_configure_secret_list() -+ * stm32_tamp_configure_secure_access() -+ * stm32_tamp_configure_privilige_access() -+ * -+ * return: < 0 if unable to apply configuration, else 0 -+ */ -+int stm32_tamp_set_config(void); -+ - #endif /* STM32_TAMP_H */ -diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h -index e298fcf77b..1ccefc4fca 100644 ---- a/include/drivers/st/stm32mp1_ddr_regs.h -+++ b/include/drivers/st/stm32mp1_ddr_regs.h -@@ -361,6 +361,7 @@ struct stm32mp1_ddrphy { - #define DDRPHYC_PIR_DRAMRST BIT(5) - #define DDRPHYC_PIR_DRAMINIT BIT(6) - #define DDRPHYC_PIR_QSTRN BIT(7) -+#define DDRPHYC_PIR_RVTRN BIT(8) - #define DDRPHYC_PIR_ICPC BIT(16) - #define DDRPHYC_PIR_ZCALBYP BIT(30) - #define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) -diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h -index 616051e772..ec6b485046 100644 ---- a/include/drivers/st/stm32mp1_rcc.h -+++ b/include/drivers/st/stm32mp1_rcc.h -@@ -306,6 +306,8 @@ - /* Fields of RCC_RDLSICR register */ - #define RCC_RDLSICR_LSION BIT(0) - #define RCC_RDLSICR_LSIRDY BIT(1) -+#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) -+#define RCC_RDLSICR_MRD_SHIFT 16 - - /* Used for all RCC_PLLCR registers */ - #define RCC_PLLNCR_PLLON BIT(0) -diff --git a/include/drivers/st/stm32mp_ddr_test.h b/include/drivers/st/stm32mp_ddr_test.h -new file mode 100644 -index 0000000000..fe4c8c08e0 ---- /dev/null -+++ b/include/drivers/st/stm32mp_ddr_test.h -@@ -0,0 +1,15 @@ -+/* -+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef STM32MP_DDR_TEST_H -+#define STM32MP_DDR_TEST_H -+ -+uint32_t stm32mp_ddr_test_rw_access(void); -+uint32_t stm32mp_ddr_test_data_bus(void); -+uint32_t stm32mp_ddr_test_addr_bus(uint64_t size); -+uint32_t stm32mp_ddr_check_size(void); -+ -+#endif /* STM32MP_DDR_TEST_H */ -diff --git a/include/drivers/st/stm32mp_dummy_regulator.h b/include/drivers/st/stm32mp_dummy_regulator.h -deleted file mode 100644 -index 6804192ba0..0000000000 ---- a/include/drivers/st/stm32mp_dummy_regulator.h -+++ /dev/null -@@ -1,14 +0,0 @@ --/* -- * 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 898a28b44c..dd91d5eebc 100644 ---- a/include/drivers/st/stm32mp_pmic.h -+++ b/include/drivers/st/stm32mp_pmic.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -11,8 +11,6 @@ - - #include - --#include -- - /* - * dt_pmic_status - Check PMIC status from device tree - * -@@ -21,31 +19,6 @@ - */ - int dt_pmic_status(void); - --/* -- * dt_pmic_configure_boot_on_regulators - Configure boot-on and always-on -- * regulators from device tree configuration -- * -- * Returns 0 on success, and negative values on errors -- */ --int pmic_configure_boot_on_regulators(void); -- --int pmic_set_lp_config(const char *node_name); -- --/* -- * dt_pmic_find_supply - Find the supply name related to a regulator name -- * -- * Returns 0 on success, and negative values on errors -- */ --int dt_pmic_find_supply(const char **supply_name, const char *regu_name); -- --/* -- * 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 - * -@@ -60,13 +33,6 @@ 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); -- - #if DEBUG - void print_pmic_info_and_debug(void); - #else -@@ -75,9 +41,6 @@ static inline void print_pmic_info_and_debug(void) - } - #endif - --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 - * -@@ -85,4 +48,11 @@ void bind_pmic_regulator(struct stm32mp_regulator *regu); - */ - int pmic_ddr_power_init(enum ddr_type ddr_type); - -+/* -+ * pmic_switch_off - switch off the platform with PMIC -+ * -+ * Panics on errors -+ */ -+void pmic_switch_off(void); -+ - #endif /* STM32MP_PMIC_H */ -diff --git a/include/drivers/st/stm32mp_regulator.h b/include/drivers/st/stm32mp_regulator.h -deleted file mode 100644 -index 7a66b97ba7..0000000000 ---- a/include/drivers/st/stm32mp_regulator.h -+++ /dev/null -@@ -1,31 +0,0 @@ --/* -- * 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 5c8933d84d..4e19ba3e5c 100644 ---- a/include/drivers/st/stpmic1.h -+++ b/include/drivers/st/stpmic1.h -@@ -103,6 +103,22 @@ - #define BUCK4_PULL_DOWN_SHIFT 6 - #define VREF_DDR_PULL_DOWN_SHIFT 4 - -+/* ICC register */ -+#define BUCK1_ICC_SHIFT 0 -+#define BUCK2_ICC_SHIFT 1 -+#define BUCK3_ICC_SHIFT 2 -+#define BUCK4_ICC_SHIFT 3 -+#define PWR_SW1_ICC_SHIFT 4 -+#define PWR_SW2_ICC_SHIFT 5 -+#define BOOST_ICC_SHIFT 6 -+ -+#define LDO1_ICC_SHIFT 0 -+#define LDO2_ICC_SHIFT 1 -+#define LDO3_ICC_SHIFT 2 -+#define LDO4_ICC_SHIFT 3 -+#define LDO5_ICC_SHIFT 4 -+#define LDO6_ICC_SHIFT 5 -+ - /* Buck Mask reset register */ - #define BUCK1_MASK_RESET 0 - #define BUCK2_MASK_RESET 1 -@@ -118,6 +134,10 @@ - #define LDO6_MASK_RESET 5 - #define VREF_DDR_MASK_RESET 6 - -+/* LDO3 Special modes */ -+#define LDO3_BYPASS BIT(7) -+#define LDO3_DDR_SEL 31U -+ - /* Main PMIC Control Register (MAIN_CONTROL_REG) */ - #define ICC_EVENT_ENABLED BIT(4) - #define PWRCTRL_POLARITY_HIGH BIT(3) -@@ -145,6 +165,8 @@ - /* USB Control Register */ - #define BOOST_OVP_DISABLED BIT(7) - #define VBUS_OTG_DETECTION_DISABLED BIT(6) -+#define SW_OUT_DISCHARGE BIT(5) -+#define VBUS_OTG_DISCHARGE BIT(4) - #define OCP_LIMIT_HIGH BIT(3) - #define SWIN_SWOUT_ENABLED BIT(2) - #define USBSW_OTG_SWITCH_ENABLED BIT(1) -@@ -159,9 +181,15 @@ int stpmic1_regulator_enable(const char *name); - int stpmic1_regulator_disable(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_levels_mv(const char *name, const uint16_t **levels, -+ size_t *levels_count); - 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_regulator_icc_set(const char *name); -+int stpmic1_regulator_sink_mode_set(const char *name); -+int stpmic1_regulator_bypass_mode_set(const char *name); -+int stpmic1_active_discharge_mode_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); -diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h -index aa9158cb1b..881159c7fc 100644 ---- a/include/dt-bindings/interrupt-controller/arm-gic.h -+++ b/include/dt-bindings/interrupt-controller/arm-gic.h -@@ -1,21 +1,26 @@ --/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ - /* -+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: MIT -+ * - * This header provides constants for the ARM GIC. - */ - - #ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H - #define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H - -+#include -+ - /* interrupt specifier cell 0 */ - - #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 -+/* -+ * Interrupt specifier cell 2. -+ * The flags in irq.h are valid, plus those below. -+ */ -+#define GIC_CPU_MASK_RAW(x) ((x) << 8) -+#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) - - #endif -diff --git a/include/dt-bindings/interrupt-controller/irq.h b/include/dt-bindings/interrupt-controller/irq.h -new file mode 100644 -index 0000000000..1ff6681e24 ---- /dev/null -+++ b/include/dt-bindings/interrupt-controller/irq.h -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: MIT -+ * -+ * This header provides constants for most IRQ bindings. -+ * -+ * Most IRQ bindings include a flags cell as part of the IRQ specifier. -+ * In most cases, the format of the flags cell uses the standard values -+ * defined in this header. -+ */ -+ -+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H -+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H -+ -+#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 -diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S -index aea975c0ad..1cd8e236cf 100644 ---- a/lib/aarch32/misc_helpers.S -+++ b/lib/aarch32/misc_helpers.S -@@ -301,9 +301,9 @@ func fixup_gdt_reloc - cmp r4, r6 - blo 2f - -- /* Skip adding offset if address is >= upper limit */ -+ /* Skip adding offset if address is > upper limit */ - cmp r4, r7 -- bhs 2f -+ bhi 2f - - add r4, r0, r4 - str r4, [r3] -diff --git a/licenses/LICENSE.MIT b/licenses/LICENSE.MIT -new file mode 100644 -index 0000000000..8aa26455d2 ---- /dev/null -+++ b/licenses/LICENSE.MIT -@@ -0,0 +1,21 @@ -+MIT License -+ -+Copyright (c) [year] [fullname] -+ -+Permission is hereby granted, free of charge, to any person obtaining a copy -+of this software and associated documentation files (the "Software"), to deal -+in the Software without restriction, including without limitation the rights -+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+copies of the Software, and to permit persons to whom the Software is -+furnished to do so, subject to the following conditions: -+ -+The above copyright notice and this permission notice shall be included in all -+copies or substantial portions of the Software. -+ -+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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+SOFTWARE. -diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c -index 23794db963..2ea9f627ec 100644 ---- a/plat/st/common/bl2_io_storage.c -+++ b/plat/st/common/bl2_io_storage.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -48,7 +49,7 @@ static uint32_t nand_bkp_offset; - #if STM32MP_SDMMC || STM32MP_EMMC - static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); - --static const io_block_dev_spec_t mmc_block_dev_spec = { -+static io_block_dev_spec_t mmc_block_dev_spec = { - /* It's used as temp buffer in block driver */ - .buffer = { - .offset = (size_t)&block_buffer, -@@ -412,6 +413,11 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id) - image_block_spec.length = entry->length; - - gpt_init_done = true; -+ } else { -+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); -+ -+ mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base; -+ mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size; - } - - break; -diff --git a/plat/st/common/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h -index 947ad43aea..db5dfbf4f4 100644 ---- a/plat/st/common/include/stm32cubeprogrammer.h -+++ b/plat/st/common/include/stm32cubeprogrammer.h -@@ -31,9 +31,6 @@ - #define NACK_BYTE 0x1FU - #define ABORT 0x5FU - --#define DEVICE_ID_BYTE1 0x05U --#define DEVICE_ID_BYTE2 0x00U -- - /* Functions provided by plat */ - uint8_t usb_dfu_get_phase(uint8_t alt); - -diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h -index 022e22742a..40291c43ed 100644 ---- a/plat/st/common/include/stm32mp_common.h -+++ b/plat/st/common/include/stm32mp_common.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -7,12 +7,12 @@ - #ifndef STM32MP_COMMON_H - #define STM32MP_COMMON_H - --#include - #include - - #include - --void __dead2 stm32mp_plat_reset(int cpu); -+#define JEDEC_ST_BKID U(0x0) -+#define JEDEC_ST_MFID U(0x20) - - /* Functions to save and get boot context address given by ROM code */ - void stm32mp_save_boot_ctx_address(uintptr_t address); -@@ -24,10 +24,6 @@ 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); --const char *stm32mp_get_vdd_supply_name(void); --const char *stm32mp_get_usb_phy_supply_name(void); -- - /* Return the base address of the DDR controller */ - uintptr_t stm32mp_ddrctrl_base(void); - -@@ -88,12 +84,15 @@ uintptr_t get_uart_address(uint32_t instance_nb); - uintptr_t stm32_get_gpio_bank_base(unsigned int bank); - unsigned long stm32_get_gpio_bank_clock(unsigned int bank); - uint32_t stm32_get_gpio_bank_offset(unsigned int bank); -+bool stm32_gpio_is_secure_at_reset(unsigned int bank); - - /* Return node offset for target GPIO bank ID @bank or a FDT error code */ - int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank); - - /* Get the chip revision */ --int stm32mp_get_chip_version(uint32_t *chip_version); -+uint32_t stm32mp_get_chip_version(void); -+/* Get the chip device ID */ -+uint32_t stm32mp_get_chip_dev_id(void); - - /* Get SOC name */ - #define STM32_SOC_NAME_SIZE 20 -diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h -index 0ff30a3827..0414014c2f 100644 ---- a/plat/st/common/include/stm32mp_dt.h -+++ b/plat/st/common/include/stm32mp_dt.h -@@ -44,9 +44,9 @@ 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); --const char *dt_get_vdd_regulator_name(void); --const char *dt_get_cpu_regulator_name(void); --const char *dt_get_usb_phy_regulator_name(void); -+struct rdev *dt_get_vdd_regulator(void); -+struct rdev *dt_get_cpu_regulator(void); -+struct rdev *dt_get_usb_phy_regulator(void); - const char *dt_get_board_model(void); - int fdt_get_gpio_bank_pin_count(unsigned int bank); - -diff --git a/plat/st/common/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c -index 3fd16aa39c..7a6e02463f 100644 ---- a/plat/st/common/stm32cubeprogrammer_uart.c -+++ b/plat/st/common/stm32cubeprogrammer_uart.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -203,13 +203,20 @@ static int get_version_command(void) - - static int get_id_command(void) - { -- const uint8_t msg[3] = { -- sizeof(msg) - 1, -- DEVICE_ID_BYTE1, -- DEVICE_ID_BYTE2 -- }; -+ uint32_t id = stm32mp_get_chip_dev_id(); -+ int ret; -+ -+ ret = uart_write_8(2U); /* Length of command */ -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = uart_write_8((id & 0xFF00) >> 8); /* device ID byte 1 */ -+ if (ret != 0) { -+ return ret; -+ } - -- return uart_write(msg, sizeof(msg)); -+ return uart_write_8(id & 0xFF); /* device ID byte 2 */ - } - - static int uart_send_phase(uint32_t address) -diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c -index 3f385ca317..04219677cc 100644 ---- a/plat/st/common/stm32mp_common.c -+++ b/plat/st/common/stm32mp_common.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,10 +13,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include - - #define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16) - -@@ -32,12 +34,6 @@ unsigned int plat_get_syscnt_freq2(void) - return read_cntfrq_el0(); - } - --#pragma weak stm32mp_plat_reset --void __dead2 stm32mp_plat_reset(int cpu) --{ -- panic(); --} -- - static uintptr_t boot_ctx_address; - static uint16_t boot_itf_selected; - static uint32_t boot_action_saved; -@@ -147,58 +143,6 @@ int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) - } - #endif - --/* Return CPU supply name */ --const char *stm32mp_get_cpu_supply_name(void) --{ -- 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; --} -- --/* Return VDD supply name */ --const char *stm32mp_get_vdd_supply_name(void) --{ -- const char *supply = NULL; -- -- if (dt_pmic_status() > 0) { -- const char *regulator = dt_get_vdd_regulator_name(); -- -- if (regulator != NULL) { -- dt_pmic_find_supply(&supply, regulator); -- } -- } -- -- return supply; --} -- --/* Return USB phy supply name */ --const char *stm32mp_get_usb_phy_supply_name(void) --{ -- const char *supply = NULL; -- -- if (dt_pmic_status() > 0) { -- const char *regulator = dt_get_usb_phy_regulator_name(); -- -- if (regulator != NULL) { -- dt_pmic_find_supply(&supply, regulator); -- } -- } -- -- return supply; --} -- - #if TRUSTED_BOARD_BOOT && STM32MP_USE_STM32IMAGE - /* Save pointer to last loaded header */ - static boot_api_image_header_t *latest_stm32_header; -@@ -243,3 +187,35 @@ int stm32mp_unmap_ddr(void) - return mmap_remove_dynamic_region(STM32MP_DDR_BASE, - STM32MP_DDR_MAX_SIZE); - } -+ -+/***************************************************************************** -+ * plat_is_smccc_feature_available() - This function checks whether SMCCC -+ * feature is availabile for platform. -+ * @fid: SMCCC function id -+ * -+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and -+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. -+ *****************************************************************************/ -+int32_t plat_is_smccc_feature_available(u_register_t fid) -+{ -+ switch (fid) { -+ case SMCCC_ARCH_SOC_ID: -+ return SMC_ARCH_CALL_SUCCESS; -+ default: -+ return SMC_ARCH_CALL_NOT_SUPPORTED; -+ } -+} -+ -+/* Get SOC version */ -+int32_t plat_get_soc_version(void) -+{ -+ uint32_t manfid = (JEDEC_ST_BKID << 24U) | (JEDEC_ST_MFID << 16U); -+ -+ return (int32_t)(manfid | (stm32mp_get_chip_dev_id() & 0xFFFFU)); -+} -+ -+/* Get SOC revision */ -+int32_t plat_get_soc_revision(void) -+{ -+ return (int32_t)stm32mp_get_chip_version(); -+} -diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c -index a3584cbc12..fd25c93fca 100644 ---- a/plat/st/common/stm32mp_dt.c -+++ b/plat/st/common/stm32mp_dt.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,6 +13,7 @@ - - #include - #include -+#include - #include - - #include -@@ -71,21 +72,20 @@ bool fdt_check_node(int node) - uint8_t fdt_get_status(int node) - { - uint8_t status = DT_DISABLED; -- int len; - const char *cchar; - -- cchar = fdt_getprop(fdt, node, "status", &len); -+ cchar = fdt_getprop(fdt, node, "status", NULL); - if ((cchar == NULL) || -- (strncmp(cchar, "okay", (size_t)len) == 0)) { -+ (strncmp(cchar, "okay", strlen("okay")) == 0)) { - status |= DT_NON_SECURE; - } - -- cchar = fdt_getprop(fdt, node, "secure-status", &len); -+ cchar = fdt_getprop(fdt, node, "secure-status", NULL); - if (cchar == NULL) { - if (status == DT_NON_SECURE) { - status |= DT_SECURE; - } -- } else if (strncmp(cchar, "okay", (size_t)len) == 0) { -+ } else if (strncmp(cchar, "okay", strlen("okay")) == 0) { - status |= DT_SECURE; - } - -@@ -458,61 +458,23 @@ int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array, - ******************************************************************************/ - uint32_t dt_get_pwr_vdd_voltage(void) - { -- int node; -- const fdt32_t *cuint; -+ struct rdev *regul = dt_get_vdd_regulator(); -+ uint16_t min; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -- if (node < 0) { -+ if (regul == NULL) { - return 0; - } - -- cuint = fdt_getprop(fdt, node, "vdd-supply", NULL); -- if (cuint == NULL) { -- return 0; -- } -+ regulator_get_range(regul, &min, NULL); - -- 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); -+ return (uint32_t)min * 1000U; - } - - /******************************************************************************* -- * This function return the real regulator name from DT. -+ * This function retrieves VDD supply regulator from DT. -+ * Returns an rdev taken from supply node, NULL otherwise. - ******************************************************************************/ --static const char *dt_get_regulator_name(int node, const char *regu_name) --{ -- const fdt32_t *cuint; -- -- if ((node < 0) || (regu_name == NULL)) { -- return NULL; -- } -- -- cuint = fdt_getprop(fdt, node, regu_name, NULL); -- if (cuint == NULL) { -- return NULL; -- } -- -- node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); -- if (node < 0) { -- return NULL; -- } -- -- return (const char *)fdt_getprop(fdt, node, "regulator-name", NULL); --} -- --/******************************************************************************* -- * This function retrieves VDD regulator name from DT. -- * Returns string taken from supply node, NULL otherwise. -- ******************************************************************************/ --const char *dt_get_vdd_regulator_name(void) -+struct rdev *dt_get_vdd_regulator(void) - { - int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); - -@@ -520,14 +482,14 @@ const char *dt_get_vdd_regulator_name(void) - return NULL; - } - -- return dt_get_regulator_name(node, "vdd-supply"); -+ return regulator_get_by_supply_name(fdt, node, "vdd"); - } - - /******************************************************************************* -- * This function retrieves CPU regulator name from DT. -- * Returns string taken from supply node, NULL otherwise. -+ * This function retrieves CPU supply regulator from DT. -+ * Returns an rdev taken from supply node, NULL otherwise. - ******************************************************************************/ --const char *dt_get_cpu_regulator_name(void) -+struct rdev *dt_get_cpu_regulator(void) - { - int node = fdt_path_offset(fdt, "/cpus/cpu@0"); - -@@ -535,27 +497,27 @@ const char *dt_get_cpu_regulator_name(void) - return NULL; - } - -- return dt_get_regulator_name(node, "cpu-supply"); -+ return regulator_get_by_supply_name(fdt, node, "cpu"); - } - - /******************************************************************************* - * This function retrieves USB phy regulator name from DT. - * Returns string taken from supply node, NULL otherwise. - ******************************************************************************/ --const char *dt_get_usb_phy_regulator_name(void) -+struct rdev *dt_get_usb_phy_regulator(void) - { - int node = fdt_node_offset_by_compatible(fdt, -1, DT_USBPHYC_COMPAT); - int subnode; -- const char *reg_name = NULL; - - if (node < 0) { - return NULL; - } - - fdt_for_each_subnode(subnode, fdt, node) { -- reg_name = dt_get_regulator_name(subnode, "phy-supply"); -- if (reg_name != NULL) { -- return reg_name; -+ struct rdev *supply = regulator_get_by_supply_name(fdt, node, "phy"); -+ -+ if (supply != NULL) { -+ return supply; - } - } - -diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c -index 1ea30abf9b..6bc77e2440 100644 ---- a/plat/st/common/stm32mp_trusted_boot.c -+++ b/plat/st/common/stm32mp_trusted_boot.c -@@ -85,7 +85,7 @@ int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, - memcpy(&res, proot_pk, sizeof(uint32_t)); - if ((res == 0U) || (res == 0xFFFFFFFFU)) { - while (idx < ARRAY_SIZE(root_pk_hash)) { -- memcpy(&rootpk, (proot_pk + idx), sizeof(uint32_t)); -+ memcpy(&rootpk, root_pk_hash + idx, sizeof(uint32_t)); - if (res != rootpk) { - return 0; - } -diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c -index 13ce3042a5..642138a1dd 100644 ---- a/plat/st/stm32mp1/bl2_plat_setup.c -+++ b/plat/st/stm32mp1/bl2_plat_setup.c -@@ -17,6 +17,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -189,10 +191,6 @@ void bl2_platform_setup(void) - - /* Clear the context in BKPSRAM */ - stm32_clean_context(); -- -- if (dt_pmic_status() > 0) { -- configure_pmic(); -- } - } - - /* Map DDR for binary load, now with cacheable attribute */ -@@ -269,21 +267,21 @@ static void initialize_clock(void) - - if (dt_pmic_status() > 0) { - int read_voltage; -- const char *name; -+ struct rdev *regul; - -- name = stm32mp_get_cpu_supply_name(); -- if (name == NULL) { -+ regul = dt_get_cpu_regulator(); -+ if (regul == NULL) { - panic(); - } - -- read_voltage = stpmic1_regulator_voltage_get(name); -+ read_voltage = regulator_get_voltage(regul); - if (read_voltage < 0) { - panic(); - } - - if (voltage_mv != (uint32_t)read_voltage) { -- if (stpmic1_regulator_voltage_set(name, -- (uint16_t)voltage_mv) != 0) { -+ if (regulator_set_voltage(regul, -+ (uint16_t)voltage_mv) != 0) { - panic(); - } - } -@@ -380,10 +378,11 @@ void bl2_el3_plat_arch_setup(void) - mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); - } - -- /* 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); -+ /* Set minimum reset pulse duration to 31ms for discrete power supplied boards */ -+ if (dt_pmic_status() <= 0) { -+ mmio_clrsetbits_32(rcc_base + RCC_RDLSICR, RCC_RDLSICR_MRD_MASK, -+ 31U << RCC_RDLSICR_MRD_SHIFT); -+ } - - generic_delay_timer_init(); - -@@ -411,6 +410,11 @@ void bl2_el3_plat_arch_setup(void) - - initialize_clock(); - -+#if STM32MP_USB_PROGRAMMER -+ /* Deconfigure all UART RX pins configured by ROM code */ -+ stm32mp1_deconfigure_uart_pins(); -+#endif -+ - result = dt_get_stdout_uart_info(&dt_uart_info); - - if ((result <= 0) || -@@ -455,13 +459,11 @@ 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 -@@ -506,7 +508,7 @@ skip_console_init: - stm32mp1_syscfg_enable_io_compensation_finish(); - - if (dt_pmic_status() > 0) { -- initialize_pmic(); -+ initialize_pmic_i2c(); - print_pmic_info_and_debug(); - } - -@@ -718,6 +720,19 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) - break; - } - -+#if STM32MP_SDMMC || STM32MP_EMMC -+ /* -+ * Invalidate remaining data read from MMC but not flushed by load_image_flush(). -+ * We take the worst case which is 2 MMC blocks. -+ */ -+ if ((image_id != FW_CONFIG_ID) && -+ ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) { -+ inv_dcache_range(bl_mem_params->image_info.image_base + -+ bl_mem_params->image_info.image_size, -+ 2U * MMC_BLOCK_SIZE); -+ } -+#endif -+ - return err; - } - -diff --git a/plat/st/stm32mp1/include/stm32mp1_critic_power.h b/plat/st/stm32mp1/include/stm32mp1_critic_power.h -index cd7099c444..7563406b4e 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_critic_power.h -+++ b/plat/st/stm32mp1/include/stm32mp1_critic_power.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -12,11 +12,11 @@ - */ - #if defined(IMAGE_BL32) - #if STM32MP_SP_MIN_IN_DDR --extern void (*stm32_pwr_down_wfi)(bool is_cstop); -+extern void (*stm32_pwr_down_wfi)(bool is_cstop, uint32_t mode); - #else --extern void stm32_pwr_down_wfi(bool is_cstop); -+extern void stm32_pwr_down_wfi(bool is_cstop, uint32_t mode); - #endif - #endif --extern void stm32_pwr_down_wfi_wrapper(bool is_cstop); -+extern void stm32_pwr_down_wfi_wrapper(bool is_cstop, uint32_t mode); - - #endif /* STM32MP1_CRITIC_POWER_H */ -diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h -index ebf9e52bc9..cbcd2c8bd5 100644 ---- a/plat/st/stm32mp1/include/stm32mp1_private.h -+++ b/plat/st/stm32mp1/include/stm32mp1_private.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -40,6 +40,8 @@ void stm32mp1_syscfg_enable_io_compensation_start(void); - void stm32mp1_syscfg_enable_io_compensation_finish(void); - void stm32mp1_syscfg_disable_io_compensation(void); - -+void stm32mp1_deconfigure_uart_pins(void); -+ - #if STM32MP_USE_STM32IMAGE - uint32_t stm32mp_get_ddr_ns_size(void); - #endif -diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -index d322da0090..6092db2b95 100644 ---- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c -@@ -21,18 +21,18 @@ - static bl_mem_params_node_t bl2_mem_params_descs[] = { - /* Fill FW_CONFIG related information if it exists */ - { -- .image_id = FW_CONFIG_ID, -- SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -- VERSION_2, entry_point_info_t, -- SECURE | NON_EXECUTABLE), -- SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -- VERSION_2, image_info_t, -- IMAGE_ATTRIB_PLAT_SETUP), -- -- .image_info.image_base = STM32MP_FW_CONFIG_BASE, -- .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE, -- -- .next_handoff_image_id = INVALID_IMAGE_ID, -+ .image_id = FW_CONFIG_ID, -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -+ VERSION_2, entry_point_info_t, -+ SECURE | NON_EXECUTABLE), -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_PLAT_SETUP), -+ -+ .image_info.image_base = STM32MP_FW_CONFIG_BASE, -+ .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE, -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, - }, - - /* Fill BL32 related information */ -@@ -85,27 +85,28 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { - - /* Fill HW_CONFIG related information if it exists */ - { -- .image_id = HW_CONFIG_ID, -- SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -- VERSION_2, entry_point_info_t, -- NON_SECURE | NON_EXECUTABLE), -- SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -- VERSION_2, image_info_t, -- IMAGE_ATTRIB_SKIP_LOADING), -- -- .next_handoff_image_id = INVALID_IMAGE_ID, -+ .image_id = HW_CONFIG_ID, -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -+ VERSION_2, entry_point_info_t, -+ NON_SECURE | NON_EXECUTABLE), -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, - }, - -+ /* Fill TOS_FW_CONFIG related information if it exists */ - { -- .image_id = TOS_FW_CONFIG_ID, -- SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -- VERSION_2, entry_point_info_t, -- SECURE | NON_EXECUTABLE), -- SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -- VERSION_2, image_info_t, -- IMAGE_ATTRIB_SKIP_LOADING), -- -- .next_handoff_image_id = INVALID_IMAGE_ID, -+ .image_id = TOS_FW_CONFIG_ID, -+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, -+ VERSION_2, entry_point_info_t, -+ SECURE | NON_EXECUTABLE), -+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, -+ VERSION_2, image_info_t, -+ IMAGE_ATTRIB_SKIP_LOADING), -+ -+ .next_handoff_image_id = INVALID_IMAGE_ID, - }, - - /* Fill BL33 related information */ -diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk -index 067e1fff9f..55acd67422 100644 ---- a/plat/st/stm32mp1/platform.mk -+++ b/plat/st/stm32mp1/platform.mk -@@ -15,7 +15,7 @@ USE_COHERENT_MEM := 0 - STM32MP_USE_STM32IMAGE ?= 0 - - # Add specific ST version --ST_VERSION := r1.0 -+ST_VERSION := r2.0 - ifeq ($(STM32MP_USE_STM32IMAGE),1) - ST_VERSION := ${ST_VERSION}-nofip - endif -@@ -107,8 +107,14 @@ BL32_DTSI := stm32mp15-bl32.dtsi - FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME))) - endif - endif -+ -+$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) -+$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g"))) - DTC_CPPFLAGS += ${INCLUDES} - DTC_FLAGS += -Wno-unit_address_vs_reg -+ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0) -+DTC_FLAGS += -Wno-interrupt_provider -+endif - - # Macros and rules to build TF binary - STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed -@@ -129,7 +135,7 @@ STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c - - ifneq (${STM32MP_USE_STM32IMAGE},1) - FIP_DEPS += dtbs --STM32MP_NT_FW_CONFIG := ${BL33_CFG} -+STM32MP_HW_CONFIG := ${BL33_CFG} - STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME)) - STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME) - ifneq (${AARCH32_SP},none) -@@ -137,8 +143,8 @@ FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NA - endif - # Add the FW_CONFIG to FIP and specify the same to certtool - $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config)) --# Add the NT_FW_CONFIG to FIP and specify the same to certtool --$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_NT_FW_CONFIG},--hw-config)) -+# Add the HW_CONFIG to FIP and specify the same to certtool -+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config)) - ifeq (${GENERATE_COT},1) - $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) - endif -@@ -212,6 +218,8 @@ PLAT_BL_COMMON_SOURCES := common/fdt_wrappers.c \ - plat/st/common/stm32mp_common.c \ - plat/st/stm32mp1/stm32mp1_private.c - -+PLAT_BL_COMMON_SOURCES += drivers/regulator/regulator_core.c -+ - PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S - - ifneq (${ENABLE_STACK_PROTECTOR},0) -@@ -236,8 +244,6 @@ 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_shres_helpers.c \ -@@ -363,7 +369,8 @@ BL2_SOURCES += drivers/st/usb_dwc2/usb_dwc2.c \ - plat/st/stm32mp1/stm32mp1_usb.c - endif - --BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \ -+BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \ -+ drivers/st/ddr/stm32mp1_ddr.c \ - drivers/st/ddr/stm32mp1_ram.c - - BL2_SOURCES += common/desc_image_load.c \ -@@ -409,8 +416,6 @@ clean_stm32image: - ${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean - - check_dtc_version: -- $(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) -- $(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g"))) - @if [ ${DTC_VERSION} -lt 10404 ]; then \ - echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \ - false; \ -diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c -index e3d845d2ec..633e63eb31 100644 ---- a/plat/st/stm32mp1/services/bsec_svc.c -+++ b/plat/st/stm32mp1/services/bsec_svc.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -87,16 +88,18 @@ static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update) - sizeof(boot_api_ssp_config_t)); - #endif - if (dt_pmic_status() > 0) { -- const char *name; -+ struct rdev *regul; - - initialize_pmic(); - -- name = stm32mp_get_cpu_supply_name(); -- if (name == NULL) { -+ regul = dt_get_cpu_regulator(); -+ if (regul == NULL) { - return BSEC_SSP_ERROR; - } - -- stpmic1_regulator_mask_reset_set(name); -+ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) { -+ return BSEC_SSP_ERROR; -+ } - } - - return BSEC_SSP_SET; -diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -index dd81d13a08..99575f5666 100644 ---- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk -@@ -17,6 +17,7 @@ BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES - - BL32_SOURCES += drivers/st/clk/stm32mp1_calib.c \ - drivers/st/etzpc/etzpc.c \ -+ drivers/st/regulator/regulator_fixed.c \ - drivers/st/rng/stm32_rng.c \ - drivers/st/rtc/stm32_rtc.c \ - drivers/st/tamper/stm32_tamp.c \ -diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c -index 0065be44fd..d408b76523 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-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -18,8 +18,10 @@ - #include - #include - #include -+#include - #include - #include -+#include - #include - #include - #include -@@ -51,43 +53,26 @@ - static entry_point_info_t bl33_image_ep_info; - - static console_t 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 dt_node_info dt_uart_info; - --static struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT] = { -- { -- .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, -+static const char * const tamper_name[] = { -+ [INT_TAMP1] = "RTC power domain", -+ [INT_TAMP2] = "Temperature monitoring", -+ [INT_TAMP3] = "LSE monitoring", -+ [INT_TAMP4] = "HSE monitoring", - }; - --static struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT] = { -- TAMP_UNUSED, -- TAMP_UNUSED, -- TAMP_UNUSED, --}; -+static int stm32mp1_tamper_action(int id) -+{ -+ const char *tamp_name = NULL; -+ -+ if ((id >= 0) && ((size_t)id < ARRAY_SIZE(tamper_name))) { -+ tamp_name = tamper_name[id]; -+ } -+ ERROR("Tamper %u (%s) occurs\n", id, tamp_name); -+ -+ return 1; /* ack TAMPER and reset system */ -+} - - static void stm32_sgi1_it_handler(void) - { -@@ -114,12 +99,6 @@ static void stm32_sgi1_it_handler(void) - stm32mp_wait_cpu_reset(); - } - --static void stm32mp1_tamper_action(int id) --{ -- ERROR("Tamper %s occurs\n", tamper_name[id]); -- stm32mp_system_reset(); --} -- - static void configure_wakeup_interrupt(void) - { - int irq_num = fdt_rcc_enable_it("wakeup"); -@@ -141,14 +120,15 @@ static void initialize_pll1_settings(void) - } - - if (dt_pmic_status() > 0) { -- const char *name = stm32mp_get_cpu_supply_name(); -+ struct rdev *regul; - int ret; - -- if (name == NULL) { -+ regul = dt_get_cpu_regulator(); -+ if (regul == NULL) { - panic(); - } - -- ret = stpmic1_regulator_voltage_get(name); -+ ret = regulator_get_voltage(regul); - if (ret < 0) { - panic(); - } -@@ -164,16 +144,18 @@ static void initialize_pll1_settings(void) - static void disable_usb_phy_regulator(void) - { - if (dt_pmic_status() > 0) { -- const char *name = stm32mp_get_usb_phy_supply_name(); -+ struct rdev *regul = dt_get_usb_phy_regulator(); - int ret; - -- if (name == NULL) { -+ if (regul == NULL) { - return; - } - -- ret = stpmic1_regulator_disable(name); -- if (ret < 0) { -- WARN("USBPHYC phy-supply (%s) disable failed\n", name); -+ if (regulator_is_enabled(regul) == 1) { -+ ret = regulator_disable(regul); -+ if (ret < 0) { -+ WARN("USBPHYC phy-supply (%s) disable failed\n", regul->reg_name); -+ } - } - } - } -@@ -262,6 +244,7 @@ static uintptr_t get_saved_pc(void) - entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) - { - entry_point_info_t *next_image_info = &bl33_image_ep_info; -+ unsigned int console_flags; - - /* - * PC is set to 0 when resetting after STANDBY -@@ -276,6 +259,16 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) - panic(); - } - -+ console_flags = CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF; -+ if ((clk_is_enabled(dt_uart_info.clock)) && -+ (clk_get_rate(dt_uart_info.clock) != 0U)) { -+ console_flags |= CONSOLE_FLAG_BOOT; -+#ifdef DEBUG -+ console_flags |= CONSOLE_FLAG_RUNTIME; -+#endif -+ } -+ console_set_scope(&console, console_flags); -+ - cpu_context = cm_get_context(NON_SECURE); - - next_image_info->spsr = read_ctx_reg(get_regs_ctx(cpu_context), -@@ -291,6 +284,8 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) - next_image_info->pc = - read_ctx_reg(get_regs_ctx(cpu_context), CTX_LR); - } -+ -+ regulator_core_resume(); - } - - return next_image_info; -@@ -327,17 +322,12 @@ static void stm32mp1_etzpc_early_setup(void) - etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE); - } - --#if !STM32MP_USE_STM32IMAGE -+#if STM32MP_SP_MIN_IN_DDR - static void populate_ns_dt(u_register_t ns_dt_addr, uintptr_t sec_base, size_t sec_size) - { - void *external_fdt = (void *)ns_dt_addr; - int ret; - -- if (sec_base < STM32MP_DDR_BASE) { -- /* No need to reserve memory if secure monitor is not in DDR */ -- return; -- } -- - /* Map Base Non Secure DDR for Non secure DT update */ - ret = mmap_add_dynamic_region(ns_dt_addr, ns_dt_addr, STM32MP_HW_CONFIG_MAX_SIZE, - MT_NON_CACHEABLE | MT_EXECUTE_NEVER | MT_RW | MT_NS); -@@ -377,7 +367,6 @@ out: - ******************************************************************************/ - static void setup_uart_console(void) - { -- struct dt_node_info dt_uart_info; - unsigned int console_flags; - int result; - uint32_t boot_itf; -@@ -419,10 +408,9 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - uintptr_t dt_addr = STM32MP_DTB_BASE; - #else - uintptr_t dt_addr = arg1; -- uintptr_t sec_base = 0U; -- size_t sec_size = 0U; - #endif - #if STM32MP_SP_MIN_IN_DDR -+ uintptr_t sec_base = 0U; - uintptr_t bl2_code_base = 0U; - uintptr_t bl2_code_end = 0U; - uintptr_t bl2_end = 0U; -@@ -511,36 +499,41 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - } - } - --#if !STM32MP_USE_STM32IMAGE -+#if STM32MP_SP_MIN_IN_DDR - if (bl_params->image_id == BL32_IMAGE_ID) { - sec_base = bl_params->image_info->image_base; -- sec_size = bl_params->image_info->image_max_size; - } - #endif - - bl_params = bl_params->next_params_info; - } - --#if !STM32MP_USE_STM32IMAGE -+#if STM32MP_SP_MIN_IN_DDR - if (arg2 != 0U) { - /* This will expect the BL32 DT and BL32 are grouped */ - if (dt_addr < sec_base) { -- sec_size = sec_size + sec_base - dt_addr; - sec_base = dt_addr; -- } else { -- sec_size = dt_addr - sec_base + STM32MP_BL32_DTB_SIZE; - } - -- populate_ns_dt(arg2, sec_base, sec_size); -+ populate_ns_dt(arg2, sec_base, DDR_SEC_SIZE); - } else { - INFO("Non-secure device tree not found\n"); - } - #endif - -+ generic_delay_timer_init(); -+ - if (dt_pmic_status() > 0) { - initialize_pmic(); - } - -+ fixed_regulator_register(); -+ -+ if (regulator_core_config() != 0) { -+ ERROR("Regulator core config error\n"); -+ panic(); -+ } -+ - disable_usb_phy_regulator(); - - initialize_pll1_settings(); -@@ -550,8 +543,6 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, - - static void init_sec_peripherals(void) - { -- uint32_t filter_conf = 0; -- uint32_t active_conf = 0; - int ret; - - /* Disable MCU subsystem protection */ -@@ -571,9 +562,28 @@ static void init_sec_peripherals(void) - - /* Init tamper */ - if (stm32_tamp_init() > 0) { -- stm32_tamp_configure_internal(int_tamp, PLAT_MAX_TAMP_INT); -- stm32_tamp_configure_external(ext_tamp, PLAT_MAX_TAMP_EXT, -- filter_conf, active_conf); -+ struct bkpregs_conf bkpregs_conf = { -+ .nb_zone1_regs = TAMP_BKP_SEC_NUMBER, -+ .nb_zone2_regs = 0 /* no register in zone 2 */ -+ /* zone3 all remaining */ -+ }; -+ -+ /* Enable BKP Register protection */ -+ if (stm32_tamp_set_secure_bkpregs(&bkpregs_conf) < 0) { -+ panic(); -+ } -+ -+ stm32_tamp_configure_secure_access(TAMP_REGS_IT_SECURE); -+ -+ stm32_tamp_configure_internal(INT_TAMP1, TAMP_ENABLE, stm32mp1_tamper_action); -+ stm32_tamp_configure_internal(INT_TAMP2, TAMP_ENABLE, stm32mp1_tamper_action); -+ stm32_tamp_configure_internal(INT_TAMP3, TAMP_ENABLE, stm32mp1_tamper_action); -+ stm32_tamp_configure_internal(INT_TAMP4, TAMP_ENABLE, stm32mp1_tamper_action); -+ -+ ret = stm32_tamp_set_config(); -+ if (ret < 0) { -+ panic(); -+ } - - /* Enable timestamp for tamper */ - stm32_rtc_set_tamper_timestamp(); -@@ -593,8 +603,6 @@ void sp_min_platform_setup(void) - - ddr_save_sr_mode(); - -- generic_delay_timer_init(); -- - stm32_gic_init(); - - init_sec_peripherals(); -@@ -608,6 +616,11 @@ void sp_min_platform_setup(void) - stm32mp_lock_periph_registering(); - - stm32mp1_init_scmi_server(); -+ -+ /* Cold boot: clean-up regulators state */ -+ if (get_saved_pc() == 0U) { -+ regulator_core_cleanup(); -+ } - } - - void sp_min_plat_arch_setup(void) -diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c -index 027475ed40..1705c15258 100644 ---- a/plat/st/stm32mp1/stm32mp1_context.c -+++ b/plat/st/stm32mp1/stm32mp1_context.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -92,6 +93,7 @@ struct backup_bl32_data_s { - unsigned long long stgen; - uint8_t clock_cfg[CLOCK_CONTEXT_SIZE]; - uint8_t scmi_context[SCMI_CONTEXT_SIZE]; -+ uint8_t regul_context[PLAT_BACKUP_REGULATOR_SIZE]; - }; - - static struct backup_bl32_data_s *get_bl32_backup_data(void) -@@ -101,7 +103,7 @@ static struct backup_bl32_data_s *get_bl32_backup_data(void) - } - - #if STM32MP_SP_MIN_IN_DDR --void (*stm32_pwr_down_wfi)(bool is_cstop); -+void (*stm32_pwr_down_wfi)(bool is_cstop, uint32_t mode); - #endif - #endif - -@@ -227,6 +229,9 @@ int stm32_save_context(uint32_t zq0cr0_zdata, - - save_clock_pm_context(); - -+ regulator_core_backup_context(backup_bl32_data->regul_context, -+ sizeof(backup_bl32_data->regul_context)); -+ - clk_disable(BKPSRAM); - - return 0; -@@ -279,6 +284,9 @@ int stm32_restore_context(void) - &backup_bl32_data->rtc); - stm32mp_stgen_restore_counter(backup_bl32_data->stgen, stdby_time_in_ms); - -+ regulator_core_restore_context(backup_bl32_data->regul_context, -+ sizeof(backup_bl32_data->regul_context)); -+ - clk_disable(BKPSRAM); - - stm32mp1_clock_resume(); -@@ -317,7 +325,7 @@ void stm32_context_get_bl2_low_power_params(uintptr_t *bl2_code_base, - } - - #if STM32MP_SP_MIN_IN_DDR -- stm32_pwr_down_wfi = (void (*)(bool))backup_data->low_power_ep; -+ stm32_pwr_down_wfi = (void (*)(bool, uint32_t))backup_data->low_power_ep; - #endif - *bl2_code_base = (uintptr_t)backup_data->bl2_code_base; - *bl2_code_end = (uintptr_t)backup_data->bl2_code_end; -@@ -463,6 +471,8 @@ void stm32_save_ddr_training_area(void) - PAGE_SIZE, MT_MEMORY | MT_RW | MT_NS); - assert(ret == 0); - -+ flush_dcache_range(STM32MP_DDR_BASE, TRAINING_AREA_SIZE); -+ - memcpy(&backup_data->ddr_training_backup, - (const uint32_t *)STM32MP_DDR_BASE, - TRAINING_AREA_SIZE); -diff --git a/plat/st/stm32mp1/stm32mp1_critic_power.c b/plat/st/stm32mp1/stm32mp1_critic_power.c -index 583cf93fad..aad11fa508 100644 ---- a/plat/st/stm32mp1/stm32mp1_critic_power.c -+++ b/plat/st/stm32mp1/stm32mp1_critic_power.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -10,19 +10,38 @@ - #include - #include - #include -+#include - #include -+#include - -+#include - #include - --static void cstop_critic_enter(void) -+static void cstop_critic_enter(uint32_t mode) - { -+ /* Switch to Software Self-Refresh mode */ -+ ddr_set_sr_mode(DDR_SSR_MODE); -+ - /* - * Set DDR in Self-refresh,. - * This is also the procedure awaited when switching off power supply. - */ - if (ddr_standby_sr_entry() != 0) { - ERROR("Unable to put DDR in SR\n"); -- panic(); -+ if (mode != STM32_PM_SHUTDOWN) { -+ panic(); -+ } -+ } -+} -+ -+static void shutdown_critic_enter(void) -+{ -+ if (dt_pmic_status() > 0) { -+ if (!initialize_pmic_i2c()) { -+ panic(); -+ } -+ -+ pmic_switch_off(); - } - } - -@@ -36,10 +55,18 @@ static void cstop_critic_exit(void) - } - } - --void stm32_pwr_down_wfi_load(bool is_cstop) -+void stm32_pwr_down_wfi_load(bool is_cstop, uint32_t mode) - { -+ if (mode != STM32_PM_CSLEEP_RUN) { -+ dcsw_op_all(DC_OP_CISW); -+ } -+ - if (is_cstop) { -- cstop_critic_enter(); -+ cstop_critic_enter(mode); -+ } -+ -+ if (mode == STM32_PM_SHUTDOWN) { -+ shutdown_critic_enter(); - } - - /* -@@ -61,12 +88,20 @@ void stm32_pwr_down_wfi_load(bool is_cstop) - extern void wfi_svc_int_enable(uintptr_t stack_addr); - static uint32_t int_stack[STM32MP_INT_STACK_SIZE]; - --void stm32_pwr_down_wfi(bool is_cstop) -+void stm32_pwr_down_wfi(bool is_cstop, uint32_t mode) - { - uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; - -+ if (mode != STM32_PM_CSLEEP_RUN) { -+ dcsw_op_all(DC_OP_CISW); -+ } -+ - if (is_cstop) { -- cstop_critic_enter(); -+ cstop_critic_enter(mode); -+ } -+ -+ if (mode == STM32_PM_SHUTDOWN) { -+ shutdown_critic_enter(); - } - - stm32mp1_calib_set_wakeup(false); -diff --git a/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S -index 2c4dd844d2..514def2fc4 100644 ---- a/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S -+++ b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -21,6 +21,9 @@ - func stm32_pwr_down_wfi_wrapper - push {r4,r5,r6,lr} - -+ # Save r0 and r1 in r2 and r3, as they are used in disable_mmu_secure -+ mov r2, r0 -+ mov r3, r1 - # Save current sp in r4 - mov r4, sp - # Save current VBAR in r5 -@@ -34,20 +37,21 @@ func stm32_pwr_down_wfi_wrapper - stcopr r1, MVBAR - - # Set sp to BL2 STACK (as BL2 is not using it anymore) -- ldr sp, =__STACKS_END__ -+ ldr sp, =__STACKS_END__ - - # Disable MMU as TLB are still stored in DDR, - # and in few instructions DDR won't be readable -- bl disable_mmu_secure -+ bl disable_mmu_secure - - # dsb is done in disable mmu - # isb is done in disable mmu - -- # We didn't change R0 to keep it as first parameter -- bl stm32_pwr_down_wfi_load -+ mov r0, r2 -+ mov r1, r3 -+ bl stm32_pwr_down_wfi_load - - # Restore stack -- mov sp, r4 -+ mov sp, r4 - # Restore VBAR - stcopr r5, VBAR - # Restore MVBAR -diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h -index 326b227842..780d124d17 100644 ---- a/plat/st/stm32mp1/stm32mp1_def.h -+++ b/plat/st/stm32mp1/stm32mp1_def.h -@@ -162,8 +162,8 @@ enum ddr_type { - #define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */ - #define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */ - #else --#define STM32MP_BL2_RO_SIZE U(0x00010000) /* 64 KB */ --#define STM32MP_BL2_SIZE U(0x00015000) /* 84 KB for BL2 */ -+#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */ -+#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */ - #endif - - #define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ -@@ -182,7 +182,7 @@ enum ddr_type { - #if STM32MP_SP_MIN_IN_DDR - #define STM32MP_BL32_SIZE U(0x00025000) /* 148 KB for BL32 */ - #else --#define STM32MP_BL32_SIZE U(0x0001A000) /* 100 KB for BL32 */ -+#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */ - #endif - #endif /* STM32MP_USE_STM32IMAGE */ - #endif /* STM32MP_SSP */ -@@ -265,10 +265,14 @@ enum ddr_type { - STM32MP_BL2_DTB_SIZE) - - #define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ -+#if STM32MP_SP_MIN_IN_DDR -+#define DDR_SEC_SIZE U(0x02000000) /* 32MB */ -+#else - #define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE - - #define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \ - STM32MP_BL32_DTB_SIZE) -+#endif - - #if defined(IMAGE_BL2) - #define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE -@@ -581,11 +585,8 @@ enum ddr_type { - #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) - - - #if !(defined(__LINKER__) || defined(__ASSEMBLER__)) -@@ -650,6 +651,16 @@ static inline uint32_t tamp_bkpr(uint32_t idx) - #define PLAT_MAX_OPP_NB U(2) - #define PLAT_MAX_PLLCFG_NB U(6) - -+/******************************************************************************* -+ * REGULATORS -+ ******************************************************************************/ -+/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */ -+#define PLAT_NB_RDEVS U(19) -+/* Number of low power modes defined in the device tree */ -+#define PLAT_NB_SUSPEND_MODES 7 -+/* 1 FIXED */ -+#define PLAT_NB_FIXED_REGS U(1) -+ - /******************************************************************************* - * DEBUG - ******************************************************************************/ -diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S -index 315a67f2cf..da3ab1562b 100644 ---- a/plat/st/stm32mp1/stm32mp1_helper.S -+++ b/plat/st/stm32mp1/stm32mp1_helper.S -@@ -251,12 +251,12 @@ func plat_crash_console_init - str r2, [r1] - 1: - ldr r0, [r1] -- ands r0, r2 -+ ands r2, r0, r2 - beq 1b - str r2, [r1, #4] /* RSTCLR register */ - 2: - ldr r0, [r1] -- ands r0, r2 -+ ands r2, r0, r2 - bne 2b - /* Enable GPIOs for UART TX */ - ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) -diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c -index ae6fd88c88..82e2de710c 100644 ---- a/plat/st/stm32mp1/stm32mp1_low_power.c -+++ b/plat/st/stm32mp1/stm32mp1_low_power.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -104,6 +105,11 @@ static struct spinlock lp_lock; - static volatile int cpu0_state = STATE_NONE; - static volatile int cpu1_state = STATE_NONE; - -+const char *plat_get_lp_mode_name(int mode) -+{ -+ return config_pwr[mode].regul_suspend_node_name; -+} -+ - void stm32_apply_pmic_suspend_config(uint32_t mode) - { - const char *node_name; -@@ -116,14 +122,6 @@ void stm32_apply_pmic_suspend_config(uint32_t mode) - if (!initialize_pmic_i2c()) { - panic(); - } -- -- if (pmic_set_lp_config(node_name) < 0) { -- panic(); -- } -- -- if (pmic_configure_boot_on_regulators() < 0) { -- panic(); -- } - } - } - -@@ -147,11 +145,6 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) - - 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(); - - if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { -@@ -170,6 +163,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) - } - } - -+ regulator_core_suspend(mode); -+ - /* Clear RCC interrupt before enabling it */ - mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF); - -@@ -289,6 +284,8 @@ void stm32_exit_cstop(void) - panic(); - } - -+ regulator_core_resume(); -+ - stm32mp1_syscfg_enable_io_compensation_finish(); - } - -@@ -348,7 +345,7 @@ static void stm32_auto_stop_cpu0(void) - - enter_cstop(STM32_PM_CSTOP_ALLOW_LP_STOP, 0); - -- stm32_pwr_down_wfi(true); -+ stm32_pwr_down_wfi(true, STM32_PM_CSTOP_ALLOW_LP_STOP); - - stm32_exit_cstop(); - -@@ -380,27 +377,6 @@ void stm32_auto_stop(void) - } - } - --static void enter_shutdown(void) --{ -- /* Set DDR in Self-refresh before shutting down the platform */ -- if (ddr_standby_sr_entry() != 0) { -- WARN("DDR can't be set in Self-refresh mode\n"); -- } -- -- if (dt_pmic_status() > 0) { -- if (!initialize_pmic_i2c()) { -- panic(); -- } -- -- stpmic1_switch_off(); -- -- udelay(100); -- -- /* Shouldn't be reached */ -- panic(); -- } --} -- - static void enter_csleep(void) - { - uintptr_t pwr_base = stm32mp_pwr_base(); -@@ -410,14 +386,13 @@ static void enter_csleep(void) - mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK, - config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1); - -- stm32_pwr_down_wfi(false); -+ stm32_pwr_down_wfi(false, STM32_PM_CSLEEP_RUN); - } - - void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr) - { - switch (mode) { - case STM32_PM_SHUTDOWN: -- enter_shutdown(); - break; - - case STM32_PM_CSLEEP_RUN: -diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c -index 962a992243..e5f622a5be 100644 ---- a/plat/st/stm32mp1/stm32mp1_pm.c -+++ b/plat/st/stm32mp1/stm32mp1_pm.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -169,7 +169,8 @@ static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t - void (*warm_entrypoint)(void) = - (void (*)(void))stm32_sec_entrypoint; - -- stm32_pwr_down_wfi(stm32_is_cstop_done()); -+ stm32_pwr_down_wfi(stm32_is_cstop_done(), -+ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND)); - - stm32_exit_cstop(); - -@@ -207,7 +208,7 @@ static void __dead2 stm32_system_off(void) - - stm32_enter_low_power(soc_mode, 0); - -- stm32_pwr_down_wfi(false); -+ stm32_pwr_down_wfi(true, soc_mode); - - /* This shouldn't be reached */ - panic(); -diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c -index 09afe1a6ea..0451efe72f 100644 ---- a/plat/st/stm32mp1/stm32mp1_private.c -+++ b/plat/st/stm32mp1/stm32mp1_private.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -13,11 +13,9 @@ - #include - #include - #include -+#include - #include --#include - #include --#include --#include - #include - #include - #include -@@ -165,110 +163,6 @@ void __dead2 stm32mp_wait_cpu_reset(void) - } - } - --/* -- * 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; -- -- /* Mask timer interrupts */ -- stm32mp_mask_timer(); -- -- for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) { -- if ((!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) == -- ETZPC_DECPROT_MCU_ISOLATION))) { -- continue; -- } -- -- if (tzc_source_ip[id].reset_id != GPU_R) { -- uint32_t reset = tzc_source_ip[id].reset_id; -- int ret; -- -- ret = stm32mp_reset_assert(reset, TIMEOUT_US_1MS); -- if (ret != 0) { -- panic(); -- } -- ret = stm32mp_reset_deassert(reset, TIMEOUT_US_1MS); -- if (ret != 0) { -- 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; -- -- gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, sec_cpu); -- 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); -- -- stm32mp_wait_cpu_reset(); --} -- - uintptr_t stm32_get_gpio_bank_base(unsigned int bank) - { - if (bank == GPIO_BANK_Z) { -@@ -291,6 +185,15 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank) - return bank * GPIO_BANK_OFFSET; - } - -+bool stm32_gpio_is_secure_at_reset(unsigned int bank) -+{ -+ if (bank == GPIO_BANK_Z) { -+ return true; -+ } -+ -+ return false; -+} -+ - #if STM32MP_UART_PROGRAMMER || defined(IMAGE_BL32) - /* - * UART Management -@@ -317,6 +220,53 @@ uintptr_t get_uart_address(uint32_t instance_nb) - } - #endif - -+#if STM32MP_USB_PROGRAMMER -+struct gpio_bank_pin_list { -+ uint32_t bank; -+ uint32_t pin; -+}; -+ -+static const struct gpio_bank_pin_list gpio_list[] = { -+ { /* USART2_RX: GPIOA3 */ -+ .bank = 0, -+ .pin = 3, -+ }, -+ { /* USART3_RX: GPIOB12 */ -+ .bank = 1, -+ .pin = 12, -+ }, -+ { /* UART4_RX: GPIOB2 */ -+ .bank = 1, -+ .pin = 2, -+ }, -+ { /* UART5_RX: GPIOB4 */ -+ .bank = 1, -+ .pin = 5, -+ }, -+ { /* USART6_RX: GPIOC7 */ -+ .bank = 2, -+ .pin = 7, -+ }, -+ { /* UART7_RX: GPIOF6 */ -+ .bank = 5, -+ .pin = 6, -+ }, -+ { /* UART8_RX: GPIOE0 */ -+ .bank = 4, -+ .pin = 0, -+ }, -+}; -+ -+void stm32mp1_deconfigure_uart_pins(void) -+{ -+ size_t i; -+ -+ for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { -+ set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin); -+ } -+} -+#endif -+ - unsigned long stm32_get_gpio_bank_clock(unsigned int bank) - { - if (bank == GPIO_BANK_Z) { -@@ -403,25 +353,38 @@ int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val) - return 0; - } - --int stm32mp_get_chip_version(uint32_t *chip_version) -+uint32_t stm32mp_get_chip_version(void) - { -- return stm32mp1_dbgmcu_get_chip_version(chip_version); -+ uint32_t version = 0U; -+ -+ if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) { -+ INFO("Cannot get CPU version, debug disabled\n"); -+ return 0U; -+ } -+ -+ return version; - } - --static uint32_t get_part_number(void) -+uint32_t stm32mp_get_chip_dev_id(void) - { -- static uint32_t part_number; - uint32_t dev_id; - -- 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; - } - -+ return dev_id; -+} -+ -+static uint32_t get_part_number(void) -+{ -+ static uint32_t part_number; -+ -+ if (part_number != 0U) { -+ return part_number; -+ } -+ - if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) { - panic(); - } -@@ -429,7 +392,7 @@ static uint32_t get_part_number(void) - part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >> - PART_NUMBER_OTP_PART_SHIFT; - -- part_number |= dev_id << 16; -+ part_number |= stm32mp_get_chip_dev_id() << 16; - - return part_number; - } -@@ -477,8 +440,6 @@ bool stm32mp_supports_cpu_opp(uint32_t opp_id) - void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) - { - char *cpu_s, *cpu_r, *pkg; -- uint32_t chip_dev_id; -- int ret; - - /* MPUs Part Numbers */ - switch (get_part_number()) { -@@ -543,12 +504,7 @@ void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) - } - - /* REVISION */ -- ret = stm32mp_get_chip_version(&chip_dev_id); -- if (ret < 0) { -- INFO("Cannot get CPU version, debug disabled\n"); -- } -- -- switch (chip_dev_id) { -+ switch (stm32mp_get_chip_version()) { - case STM32MP1_REV_B: - cpu_r = "B"; - break; -@@ -732,29 +688,6 @@ enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode) - } - } - --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; --} -- - #if STM32MP_USE_STM32IMAGE - /* Get the non-secure DDR size */ - uint32_t stm32mp_get_ddr_ns_size(void) -@@ -789,9 +722,14 @@ bool stm32mp1_addr_inside_backupsram(uintptr_t addr) - - bool stm32mp1_is_wakeup_from_standby(void) - { -+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR); - uint32_t bkpr_core1_addr = tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); - uint32_t nsec_address; - -+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { -+ return false; -+ } -+ - if (stm32mp_get_boot_action() != BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY) { - return false; - } -diff --git a/plat/st/stm32mp1/stm32mp1_ssp.c b/plat/st/stm32mp1/stm32mp1_ssp.c -index bcbf374782..a60721691e 100644 ---- a/plat/st/stm32mp1/stm32mp1_ssp.c -+++ b/plat/st/stm32mp1/stm32mp1_ssp.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -803,24 +804,24 @@ static void ssp_start(boot_api_context_t *boot_context) - * the required MPSYSRST. - */ - if (dt_pmic_status() > 0) { -- const char *name; -+ struct rdev *regul; - -- name = stm32mp_get_cpu_supply_name(); -- if (name == NULL) { -- goto out; -+ regul = dt_get_cpu_regulator(); -+ if (regul == NULL) { -+ panic(); - } - -- if (stpmic1_regulator_mask_reset_set(name) != 0) { -- WARN("Failed to write %s reset mask\n", name); -+ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) { -+ WARN("Failed to write cpu-supply reset mask\n"); - } - -- name = stm32mp_get_vdd_supply_name(); -- if (name == NULL) { -+ regul = dt_get_vdd_regulator(); -+ if (regul == NULL) { - goto out; - } - -- if (stpmic1_regulator_mask_reset_set(name) != 0) { -- WARN("Failed to write %s reset mask\n", name); -+ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) { -+ WARN("Failed to write vdd-supply reset mask\n"); - } - } else { - static const char debug_msg[] = { -@@ -1028,7 +1029,7 @@ skip_console_init: - stm32_iwdg_refresh(); - - if (dt_pmic_status() > 0) { -- initialize_pmic(); -+ initialize_pmic_i2c(); - print_pmic_info_and_debug(); - } - -diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c -index 2c5fa082fc..b471be2096 100644 ---- a/plat/st/stm32mp1/stm32mp1_syscfg.c -+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -26,6 +26,9 @@ - #define SYSCFG_CMPENSETR 0x24U - #define SYSCFG_CMPENCLRR 0x28U - -+#define CMPCR_CMPENSETR_OFFSET 0x4U -+#define CMPCR_CMPENCLRR_OFFSET 0x8U -+ - /* - * SYSCFG_BOOTR Register - */ -@@ -63,25 +66,61 @@ - */ - #define SYSCFG_CMPENSETR_MPU_EN BIT(0) - --void stm32mp1_syscfg_init(void) -+static void enable_io_comp_cell_finish(uintptr_t cmpcr_off) -+{ -+ uint64_t start; -+ -+ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); -+ -+ while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & 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; -+ } -+ } -+ -+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL); -+} -+ -+static void disable_io_comp_cell(uintptr_t cmpcr_off) -+{ -+ uint32_t value; -+ -+ if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) || -+ ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) & -+ SYSCFG_CMPENSETR_MPU_EN) == 0U)) { -+ return; -+ } -+ -+ value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT; -+ -+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); -+ -+ value <<= SYSCFG_CMPCR_RANSRC_SHIFT; -+ value |= mmio_read_32(SYSCFG_BASE + cmpcr_off); -+ -+ mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL); -+ -+ mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); -+} -+ -+static void enable_high_speed_mode_low_voltage(void) -+{ -+ 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); -+} -+ -+static void stm32mp1_syscfg_set_hslv(void) - { -- uint32_t bootr; - uint32_t otp_value; - uint32_t vdd_voltage; - 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); -- -- /* Disable Pull-Down for boot pin connected to VDD */ -- bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) & -- SYSCFG_BOOTR_BOOT_MASK; -- mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, -- bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); -- - /* - * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI - * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. -@@ -110,12 +149,7 @@ void stm32mp1_syscfg_init(void) - if (vdd_voltage == 0U) { - WARN("VDD unknown\n"); - } 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); -+ enable_high_speed_mode_low_voltage(); - - if (!product_below_2v5) { - INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); -@@ -128,6 +162,25 @@ void stm32mp1_syscfg_init(void) - panic(); - } - } -+} -+ -+void stm32mp1_syscfg_init(void) -+{ -+ uint32_t bootr; -+ -+ /* -+ * Interconnect update : select master using the port 1. -+ * LTDC = 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) & -+ SYSCFG_BOOTR_BOOT_MASK; -+ mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, -+ bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); -+ -+ stm32mp1_syscfg_set_hslv(); - - stm32mp1_syscfg_enable_io_compensation_start(); - } -@@ -141,35 +194,17 @@ void stm32mp1_syscfg_enable_io_compensation_start(void) - */ - stm32mp1_clk_force_enable(SYSCFG); - -- mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENSETR, -+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR, - SYSCFG_CMPENSETR_MPU_EN); - } - - void stm32mp1_syscfg_enable_io_compensation_finish(void) - { -- uint64_t start; -- -- start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); -- -- 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; -- } -- } -- -- mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); -+ enable_io_comp_cell_finish(SYSCFG_CMPCR); - } - - void stm32mp1_syscfg_disable_io_compensation(void) - { -- uint32_t value; -- - stm32mp1_clk_force_enable(SYSCFG); - - /* -@@ -178,18 +213,7 @@ 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) >> -- 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 | SYSCFG_CMPCR_SW_CTRL); -- -- mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENCLRR, SYSCFG_CMPENSETR_MPU_EN); -+ disable_io_comp_cell(SYSCFG_CMPCR); - - stm32mp1_clk_force_disable(SYSCFG); - } -diff --git a/plat/st/stm32mp1/stm32mp1_usb.c b/plat/st/stm32mp1/stm32mp1_usb.c -index c63db4a2ff..a205b64d34 100644 ---- a/plat/st/stm32mp1/stm32mp1_usb.c -+++ b/plat/st/stm32mp1/stm32mp1_usb.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -310,7 +310,7 @@ static uint8_t *stm32mp1_product_desc(uint16_t *length) - char str_chip_version[5]; - - stm32mp_get_soc_name(name); -- stm32mp_get_chip_version(&chip_version); -+ chip_version = stm32mp_get_chip_version(); - - int_to_str(STM32MP1_CHIP_ID, (uint8_t *)str_chip_id, 4); - int_to_str(chip_version, (uint8_t *)str_chip_version, 5); --- -2.17.1 - diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0099-Modify-Reset-reason-trace-level.patch b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0099-Modify-Reset-reason-trace-level.patch new file mode 100644 index 0000000..19baede --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0099-Modify-Reset-reason-trace-level.patch @@ -0,0 +1,25 @@ +From f83c3e1e478fa7dfd8ee41b3c7b0c0c32341d954 Mon Sep 17 00:00:00 2001 +From: Lionel VITTE +Date: Thu, 24 Mar 2022 13:48:26 +0100 +Subject: [PATCH] Modify 'Reset reason' trace level + +--- + plat/st/stm32mp1/bl2_plat_setup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c +index 57aa5590a..b248d17ff 100644 +--- a/plat/st/stm32mp1/bl2_plat_setup.c ++++ b/plat/st/stm32mp1/bl2_plat_setup.c +@@ -66,7 +66,7 @@ static void print_reset_reason(void) + return; + } + +- INFO("Reset reason (0x%x):\n", rstsr); ++ NOTICE("Reset reason (0x%x):\n", rstsr); + + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { + if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { +-- +2.17.1 + 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 ee5e04b..312d833 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 @@ -1,16 +1,17 @@ Compilation of TF-A (Trusted Firmware-A): 1. Pre-requisite -2. Initialise cross-compilation via SDK -3. Prepare tf-a source code -4. Management of tf-a source code -5. Compile tf-a source code +2. Initialize cross-compilation via SDK +3. Prepare TF-A source code +4. Manage TF-A source code with GIT +5. Compile TF-A source code 6. Update software on board -1. Pre-requisite: ------------------ +---------------- +1. Pre-requisite +---------------- OpenSTLinux SDK must be installed. -For tf-a build you need to install: +For TF-A build you need to install: - git: Ubuntu: sudo apt-get install git-core gitk Fedora: sudo yum install git @@ -19,7 +20,8 @@ If you have never configured you git configuration: $ git config --global user.name "your_name" $ git config --global user.email "your_email@example.com" -2. Initialise cross-compilation via SDK: +--------------------------------------- +2. Initialize cross-compilation via SDK --------------------------------------- Source SDK environment: $ source /environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi @@ -31,26 +33,38 @@ To verify if your cross-compilation environment have put in place: Warning: the environment are valid only on the shell session where you have sourced the sdk environment. -3. Prepare tf-a source: ------------------------- -If you have the tarball and the list of patch then you must extract the tarball -and apply the patch. - $> tar xfz ##BP##-##PR##.tar.gz -A new directory containing tf-a standard source code will be created, go into it: - $> cd ##BP## +---------------------- +3. Prepare TF-A source +---------------------- +If not already done, extract the sources from Developer Package tarball, for example: +$ tar xfJ en.SOURCES-stm32mp1-*.tar.xz -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 +In the TF-A source directory (sources/*/##BP##-##PR##), +you have one TF-A source tarball, the patches and one Makefile: + - ##BP##-##PR##.tar.xz + - 00*.patch + - Makefile.sdk + +If you would like to have a git management for the source code move to +to section 4 [Management of TF-A source code with GIT]. + +Otherwise, to manage TF-A source code without git, you must extract the +tarball now and apply the patch: + + $> tar xf ##BP##-##PR##.tar.xz + $> cd ##BP## $> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done -4. Management of tf-a source code: +You can now move to section 5 [Compile TF-A source code]. + ----------------------------------- -If you like to have a better management of change made on tf-a source, you +4. Manage TF-A source code with GIT +----------------------------------- +If you like to have a better management of change made on TF-A source, you have 3 solutions to use git: 4.1 Get STMicroelectronics TF-A source from GitHub - +-------------------------------------------------- URL: https://github.com/STMicroelectronics/arm-trusted-firmware.git Branch: ##ARCHIVER_ST_BRANCH## Revision: ##ARCHIVER_ST_REVISION## @@ -59,38 +73,45 @@ have 3 solutions to use git: $ git checkout -b WORKING ##ARCHIVER_ST_REVISION## 4.2 Create Git from tarball +--------------------------- $ 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 - -4.3 Get Git from community and apply STMicroelectronics patches + $ for p in `ls -1 ../*.patch`; do git am $p; done +4.3 Get Git from Arm Software community and apply STMicroelectronics patches +--------------------------------------------------------------- URL: git://github.com/ARM-software/arm-trusted-firmware.git Branch: ##ARCHIVER_COMMUNITY_BRANCH## Revision: ##ARCHIVER_COMMUNITY_REVISION## $ git clone git://github.com/ARM-software/arm-trusted-firmware.git - $ cd + $ cd arm-trusted-firmware $ git checkout -b WORKING ##ARCHIVER_COMMUNITY_REVISION## $ for p in `ls -1 /*.patch`; do git am $p; done -5. Build tf-a source code: --------------------------------- -Since OpenSTLinux has activated FIP by default, so the FIP_artifacts should be specified before launching compilation - - In case of using SOURCES-xxxx.tar.gz of Developer package the FIP_DEPLOYDIR_ROOT should be set as below: +--------------------------- +5. Compile TF-A source code +--------------------------- +Since OpenSTLinux activates FIP by default, FIP_artifacts directory path must be specified before launching compilation + - In case of using SOURCES-xxxx.tar.gz of Developer package the FIP_DEPLOYDIR_ROOT must be set as below: $> export FIP_DEPLOYDIR_ROOT=$PWD/../../FIP_artifacts -To compile tf-a source code +To compile TF-A source code $> make -f $PWD/../Makefile.sdk all or for a specific config : $ make -f $PWD/../Makefile.sdk TF_A_DEVICETREE=stm32mp157c-ev1 TF_A_CONFIG=trusted ELF_DEBUG_ENABLE='1' all NB: TF_A_DEVICETREE flag must be set to switch to correct board configuration. +By default, the build results for this component are available in $PWD/../deploy directory. +If needed, this deploy directory can be specified by added "DEPLOYDIR=" compilation option to the build command line above. +In case DEPLOYDIR=$FIP_DEPLOYDIR_ROOT/arm-trusted-firmware it overwrites files directly in FIP artifacts directory. + The generated FIP images are available in $FIP_DEPLOYDIR_ROOT/fip -6. Update software on board: ----------------------------- +--------------------------- +6. Update software on board +--------------------------- Please use STM32CubeProgrammer then only tick the boot partitions means patitions 0x1 to 0x6 (more informations on the wiki website http://wiki.st.com/stm32mpu) diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_%.bbappend b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_%.bbappend new file mode 100644 index 0000000..ad312c2 --- /dev/null +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_%.bbappend @@ -0,0 +1,3 @@ +SRC_URI += " \ + file://0099-Modify-Reset-reason-trace-level.patch \ + " diff --git a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.4.bb b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.6.bb similarity index 80% rename from recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.4.bb rename to recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.6.bb index c992165..dbcbc84 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.4.bb +++ b/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.6.bb @@ -7,22 +7,18 @@ LIC_FILES_CHKSUM = "file://license.rst;md5=1dd070c98a281d18d9eefd938729b031" PROVIDES += "virtual/trusted-firmware-a" -FILESEXTRAPATHS:prepend_stm32mpcommon := "${THISDIR}/tf-a-stm32mp:" +FILESEXTRAPATHS:prepend:stm32mpcommon := "${THISDIR}/tf-a-stm32mp:" SRC_URI = "git://github.com/ARM-software/arm-trusted-firmware.git;protocol=https;nobranch=1" -SRCREV = "e2c509a39c6cc4dda8734e6509cdbe6e3603cdfc" +SRCREV = "a1f02f4f3daae7e21ee58b4c93ec3e46b8f28d15" SRC_URI += " \ - file://0001-st-update-v2.4-r1.0.0.patch \ - file://0002-v2.4-stm32mp-r1.1-rc1.patch \ - file://0003-v2.4-stm32mp-r2.patch \ - \ - file://0001-correct-DTC-version-detection.patch \ - " + file://0001-v2.6-stm32mp-r1.patch \ + " -TF_A_VERSION = "v2.4" -TF_A_SUBVERSION = "stm32mp" -TF_A_RELEASE = "r2" +TF_A_VERSION = "v2.6" +TF_A_SUBVERSION = "stm32mp1" +TF_A_RELEASE = "r1" PV = "${TF_A_VERSION}-${TF_A_SUBVERSION}-${TF_A_RELEASE}" ARCHIVER_ST_BRANCH = "${TF_A_VERSION}-${TF_A_SUBVERSION}" diff --git a/recipes-bsp/trusted-firmware-a/tf-a-tools/0099-tools-allow-to-use-a-root-key-password-from-command-.patch b/recipes-bsp/trusted-firmware-a/tf-a-tools/0099-tools-allow-to-use-a-root-key-password-from-command-.patch index cc231f8..884aa70 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-tools/0099-tools-allow-to-use-a-root-key-password-from-command-.patch +++ b/recipes-bsp/trusted-firmware-a/tf-a-tools/0099-tools-allow-to-use-a-root-key-password-from-command-.patch @@ -1,4 +1,4 @@ -From a1a1376cd1cc5ef232258e3302596f6a2fb9b8e4 Mon Sep 17 00:00:00 2001 +From 63e10c11b0fb33e0343d6ffc81fd214e81903f36 Mon Sep 17 00:00:00 2001 From: Lionel Debieve Date: Tue, 19 Jan 2021 15:40:36 +0100 Subject: [PATCH] tools: allow to use a root key password from command line @@ -9,24 +9,17 @@ root key password. Useful for build system management. Signed-off-by: Lionel Debieve Change-Id: Ie692c5c6db5ddb093ca7659d80f6137a978aa7bf --- - make_helpers/tbbr/tbbr_tools.mk | 4 +++- - tools/cert_create/include/key.h | 4 ++-- - tools/cert_create/src/key.c | 6 +++--- - tools/cert_create/src/main.c | 18 ++++++++++++++---- - 4 files changed, 22 insertions(+), 10 deletions(-) + make_helpers/tbbr/tbbr_tools.mk | 2 ++ + tools/cert_create/include/key.h | 2 +- + tools/cert_create/src/key.c | 4 ++-- + tools/cert_create/src/main.c | 16 +++++++++++++--- + 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk -index 853ad11bef..0aab592228 100644 +index 0a280b4ed..226d460f1 100644 --- a/make_helpers/tbbr/tbbr_tools.mk +++ b/make_helpers/tbbr/tbbr_tools.mk -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -24,6 +24,7 @@ +@@ -25,6 +25,7 @@ # KEY_SIZE # ROT_KEY # PROT_KEY @@ -34,7 +27,7 @@ index 853ad11bef..0aab592228 100644 # TRUSTED_WORLD_KEY # NON_TRUSTED_WORLD_KEY # SCP_BL2_KEY -@@ -62,6 +63,7 @@ $(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,FWU_))) +@@ -63,6 +64,7 @@ $(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,FWU_))) $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key))) $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_))) $(if ${PROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${PROT_KEY},--prot-key))) @@ -43,17 +36,10 @@ index 853ad11bef..0aab592228 100644 $(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key))) diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h -index 3409502d82..1a03201560 100644 +index 128e7f7b4..5860abb4e 100644 --- a/tools/cert_create/include/key.h +++ b/tools/cert_create/include/key.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -70,7 +70,7 @@ int key_init(void); +@@ -68,7 +68,7 @@ int key_init(void); key_t *key_get_by_opt(const char *opt); int key_new(key_t *key); int key_create(key_t *key, int type, int key_bits); @@ -63,17 +49,10 @@ index 3409502d82..1a03201560 100644 /* Macro to register the keys used in the CoT */ diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c -index 25d7d4bd9b..9ba5028af7 100644 +index 64359756f..e2a1a4541 100644 --- a/tools/cert_create/src/key.c +++ b/tools/cert_create/src/key.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -137,7 +137,7 @@ int key_create(key_t *key, int type, int key_bits) +@@ -128,7 +128,7 @@ int key_create(key_t *key, int type, int key_bits) return 0; } @@ -82,7 +61,7 @@ index 25d7d4bd9b..9ba5028af7 100644 { FILE *fp; EVP_PKEY *k; -@@ -146,7 +146,7 @@ int key_load(key_t *key, unsigned int *err_code) +@@ -137,7 +137,7 @@ int key_load(key_t *key, unsigned int *err_code) /* Load key from file */ fp = fopen(key->fn, "r"); if (fp) { @@ -92,17 +71,10 @@ index 25d7d4bd9b..9ba5028af7 100644 if (k) { *err_code = KEY_ERR_NONE; diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c -index 8a1e02e62f..e79e72745b 100644 +index b39378ca9..71bf85722 100644 --- a/tools/cert_create/src/main.c +++ b/tools/cert_create/src/main.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -@@ -289,7 +289,12 @@ static const cmd_opt_t common_cmd_opt[] = { +@@ -288,7 +288,12 @@ static const cmd_opt_t common_cmd_opt[] = { { { "print-cert", no_argument, NULL, 'p' }, "Print the certificates in the standard output" @@ -116,7 +88,7 @@ index 8a1e02e62f..e79e72745b 100644 }; int main(int argc, char *argv[]) -@@ -308,6 +313,7 @@ int main(int argc, char *argv[]) +@@ -307,6 +312,7 @@ int main(int argc, char *argv[]) unsigned char md[SHA512_DIGEST_LENGTH]; unsigned int md_len; const EVP_MD *md_info; @@ -124,7 +96,7 @@ index 8a1e02e62f..e79e72745b 100644 NOTICE("CoT Generation Tool: %s\n", build_msg); NOTICE("Target platform: %s\n", platform_msg); -@@ -345,7 +351,7 @@ int main(int argc, char *argv[]) +@@ -344,7 +350,7 @@ int main(int argc, char *argv[]) while (1) { /* getopt_long stores the option index here. */ @@ -133,7 +105,7 @@ index 8a1e02e62f..e79e72745b 100644 /* Detect the end of the options. */ if (c == -1) { -@@ -379,6 +385,10 @@ int main(int argc, char *argv[]) +@@ -378,6 +384,10 @@ int main(int argc, char *argv[]) case 'p': print_cert = 1; break; @@ -144,7 +116,7 @@ index 8a1e02e62f..e79e72745b 100644 case 's': hash_alg = get_hash_alg(optarg); if (hash_alg < 0) { -@@ -437,7 +447,7 @@ int main(int argc, char *argv[]) +@@ -436,7 +446,7 @@ int main(int argc, char *argv[]) } /* First try to load the key from disk */ @@ -154,5 +126,5 @@ index 8a1e02e62f..e79e72745b 100644 continue; } -- -2.17.1 +2.25.1 diff --git a/recipes-bsp/trusted-firmware-a/tf-a-tools_2.4.bb b/recipes-bsp/trusted-firmware-a/tf-a-tools_2.6.bb similarity index 92% rename from recipes-bsp/trusted-firmware-a/tf-a-tools_2.4.bb rename to recipes-bsp/trusted-firmware-a/tf-a-tools_2.6.bb index 028ede3..dabf450 100644 --- a/recipes-bsp/trusted-firmware-a/tf-a-tools_2.4.bb +++ b/recipes-bsp/trusted-firmware-a/tf-a-tools_2.6.bb @@ -3,8 +3,8 @@ 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 corresponds to v2.4 -SRCREV = "e2c509a39c6cc4dda8734e6509cdbe6e3603cdfc" +#SRCREV corresponds to v2.6 +SRCREV = "a1f02f4f3daae7e21ee58b4c93ec3e46b8f28d15" # Mandatory fix to allow feeding password through command line SRC_URI += "file://0099-tools-allow-to-use-a-root-key-password-from-command-.patch"