diff --git a/recipes-security/optee/optee-os-stm32mp-archiver.inc b/recipes-security/optee/optee-os-stm32mp-archiver.inc index 9ddb480..b2edb8b 100644 --- a/recipes-security/optee/optee-os-stm32mp-archiver.inc +++ b/recipes-security/optee/optee-os-stm32mp-archiver.inc @@ -24,7 +24,7 @@ archiver_create_makefile_for_sdk() { #set default CONFIGURATION with configured OPTEE_CONF if [ -n "${OPTEE_CONF}" ]; then echo "PLATFORM ?= ${MACHINE}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo "CFG_SECURE_DT ?= ${OPTEE_CONF}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo "CFG_EMBED_DTB_SOURCE_FILE ?= ${OPTEE_CONF}" >> ${ARCHIVER_OUTDIR}/Makefile.sdk fi echo -n "EXTRA_OEMAKE=" >> ${ARCHIVER_OUTDIR}/Makefile.sdk @@ -32,9 +32,9 @@ archiver_create_makefile_for_sdk() { echo "" >> ${ARCHIVER_OUTDIR}/Makefile.sdk echo "all:" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " if test -n \"\$(CFG_SECURE_DT)\" ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " for dt in \$(CFG_SECURE_DT) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk - echo " \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) PREFIX=\$(SDKTARGETSYSROOT) O=\$(LOCAL_PATH)/../build/\$\$dt CFG_SECURE_DT=\$\$dt ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " if test -n \"\$(CFG_EMBED_DTB_SOURCE_FILE)\" ; then \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " for dt in \$(CFG_EMBED_DTB_SOURCE_FILE) ; do \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk + echo " \$(MAKE) \$(EXTRA_OEMAKE) -C \$(LOCAL_PATH) PREFIX=\$(SDKTARGETSYSROOT) O=\$(LOCAL_PATH)/../build/\$\$dt CFG_EMBED_DTB_SOURCE_FILE=\$\$dt.dts ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk # Copy binary files with explicit name echo " cp ../build/\$\$dt/core/${OPTEE_HEADER}.${OPTEE_SUFFIX} ../build/${OPTEE_HEADER}-\$\$dt-${OPTEE_BOOTCHAIN}.${OPTEE_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk echo " cp ../build/\$\$dt/core/${OPTEE_PAGER}.${OPTEE_SUFFIX} ../build/${OPTEE_PAGER}-\$\$dt-${OPTEE_BOOTCHAIN}.${OPTEE_SUFFIX} ; \\" >> ${ARCHIVER_OUTDIR}/Makefile.sdk diff --git a/recipes-security/optee/optee-os-stm32mp-common.inc b/recipes-security/optee/optee-os-stm32mp-common.inc index 0f57fc1..3f9d6ec 100644 --- a/recipes-security/optee/optee-os-stm32mp-common.inc +++ b/recipes-security/optee/optee-os-stm32mp-common.inc @@ -2,13 +2,16 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/optee-os:" PACKAGE_ARCH = "${MACHINE_ARCH}" +PROVIDES += "virtual/optee-os" +RPROVIDES_${PN} += "virtual/optee-os virtual/systemd-bootconf" + B = "${WORKDIR}/build" # Configure build dir for externalsrc class usage through devtool EXTERNALSRC_BUILD_pn-${PN} = "${WORKDIR}/build" -DEPENDS += "dtc-native python-pycrypto-native" +DEPENDS += "dtc-native python3-pycryptodomex-native python3-pycrypto-native python3-pyelftools-native" -inherit deploy pythonnative +inherit deploy python3native OPTEEMACHINE ?= "${MACHINE}" OPTEEOUTPUTMACHINE ?= "${MACHINE}" @@ -38,7 +41,7 @@ do_compile() { unset -v CFLAGS CPPFLAGS LDFLAGS LDADD if [ -n "${OPTEE_CONF}" ]; then for conf in ${OPTEE_CONF}; do - oe_runmake -C ${S} O=${B}/${conf} CFG_SECURE_DT=${conf} + oe_runmake -C ${S} O=${B}/${conf} CFG_EMBED_DTB_SOURCE_FILE=${conf}.dts done else oe_runmake -C ${S} O=${B}/out @@ -69,6 +72,7 @@ ELF_DEBUG_ENABLE ?= "" OPTEE_ELF = "tee" OPTEE_ELF_SUFFIX = "elf" +do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/optee" do_deploy() { install -d ${DEPLOYDIR} if [ -n "${OPTEE_CONF}" ]; then diff --git a/recipes-security/optee/optee-os-stm32mp_3.3.0.bb b/recipes-security/optee/optee-os-stm32mp_3.3.0.bb deleted file mode 100644 index 89c8de1..0000000 --- a/recipes-security/optee/optee-os-stm32mp_3.3.0.bb +++ /dev/null @@ -1,49 +0,0 @@ -SUMMARY = "OPTEE TA development kit for stm32mp" -LICENSE = "BSD-2-Clause & BSD-3-Clause" -LIC_FILES_CHKSUM = "file://LICENSE;md5=69663ab153298557a59c67a60a743e5b" - -SRC_URI = "https://github.com/OP-TEE/optee_os/archive/${PV}.tar.gz" -SRC_URI[md5sum] = "7cb56c333066fd576460358fc97da85f" -SRC_URI[sha256sum] = "7b62e9fe650e197473eb2f4dc35c09d1e6395eb48dc1c16cc139d401b359ac6f" - -SRC_URI += " \ - file://0001-st-updates-r1.patch \ - file://0002-st-updates-r2.patch \ - file://0003-st-updates-r3.patch \ - " - -OPTEE_VERSION = "3.3.0" -PV = "${OPTEE_VERSION}" - -S = "${WORKDIR}/optee_os-${PV}" - -COMPATIBLE_MACHINE = "(stm32mpcommon)" - -PROVIDES += "optee-os" - -# The package is empty but must be generated to avoid apt-get installation issue -ALLOW_EMPTY_${PN} = "1" - -require optee-os-stm32mp-common.inc - -# --------------------------------- -# Configure archiver use -# --------------------------------- -include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'optee-os-stm32mp-archiver.inc','')} - -# --------------------------------- -# Configure devupstream class usage -# --------------------------------- -BBCLASSEXTEND = "devupstream:target" - -SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/optee_os.git;protocol=https;name=opteeos;branch=3.3.0-stm32mp" -SRCREV_class-devupstream = "273094317924bd18d2b7e7ed1d98e5118ed9c1fa" -SRCREV_FORMAT_class-devupstream = "opteeos" -PV_class-devupstream = "${OPTEE_VERSION}+github+${SRCPV}" - -# --------------------------------- -# Configure default preference to manage dynamic selection between tarball and github -# --------------------------------- -STM32MP_SOURCE_SELECTION ?= "tarball" - -DEFAULT_PREFERENCE = "${@bb.utils.contains('STM32MP_SOURCE_SELECTION', 'github', '-1', '1', d)}" diff --git a/recipes-security/optee/optee-os-stm32mp_3.9.0.bb b/recipes-security/optee/optee-os-stm32mp_3.9.0.bb new file mode 100644 index 0000000..ed3dbf5 --- /dev/null +++ b/recipes-security/optee/optee-os-stm32mp_3.9.0.bb @@ -0,0 +1,51 @@ +SUMMARY = "OPTEE TA development kit for stm32mp" +LICENSE = "BSD-2-Clause & BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE;md5=c1f21c4f72f372ef38a5a4aee55ec173" + +SRC_URI = "git://github.com/OP-TEE/optee_os.git;protocol=https;name=os" +SRCREV = "af141c61fe7a2430f3b4bb89661d8414117013b3" + +SRC_URI += " \ + file://0001-3.9.0-stm32mp-r1.patch \ + " + +OPTEE_VERSION = "3.9.0" +PV = "${OPTEE_VERSION}.r1" + +S = "${WORKDIR}/git" + +COMPATIBLE_MACHINE = "(stm32mpcommon)" + +OPTEEMACHINE ?= "stm32mp1" +OPTEEMACHINE_stm32mp1common = "stm32mp1" + +OPTEEOUTPUTMACHINE ?= "stm32mp1" +OPTEEOUTPUTMACHINE_stm32mp1common = "stm32mp1" + + +# The package is empty but must be generated to avoid apt-get installation issue +ALLOW_EMPTY_${PN} = "1" + +require optee-os-stm32mp-common.inc + +# --------------------------------- +# Configure archiver use +# --------------------------------- +include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'optee-os-stm32mp-archiver.inc','')} + +# --------------------------------- +# Configure devupstream class usage +# --------------------------------- +#BBCLASSEXTEND = "devupstream:target" + +#SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/optee_os.git;protocol=https;name=opteeos;branch=3.3.0-stm32mp" +#SRCREV_class-devupstream = "5f5cc70dfd04419be2ba66b87f41584b6136118c" +#SRCREV_FORMAT_class-devupstream = "opteeos" +#PV_class-devupstream = "${OPTEE_VERSION}+github+${SRCPV}" + +# --------------------------------- +# Configure default preference to manage dynamic selection between tarball and github +# --------------------------------- +#STM32MP_SOURCE_SELECTION ?= "tarball" + +#DEFAULT_PREFERENCE = "${@bb.utils.contains('STM32MP_SOURCE_SELECTION', 'github', '-1', '1', d)}" diff --git a/recipes-security/optee/optee-os/0001-3.9.0-stm32mp-r1.patch b/recipes-security/optee/optee-os/0001-3.9.0-stm32mp-r1.patch new file mode 100644 index 0000000..7794ac3 --- /dev/null +++ b/recipes-security/optee/optee-os/0001-3.9.0-stm32mp-r1.patch @@ -0,0 +1,15945 @@ +From 053c918ec81e85d5dd13087b056a294f69383661 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Fri, 5 Jun 2020 13:58:23 +0200 +Subject: [PATCH] 3.9.0-stm32mp-r1 + +--- + CONTRIBUTING.md | 30 + + core/arch/arm/dts/stm32mp15-pinctrl.dtsi | 914 +------------- + core/arch/arm/dts/stm32mp151.dtsi | 1327 +++----------------- + core/arch/arm/dts/stm32mp153.dtsi | 31 +- + core/arch/arm/dts/stm32mp157.dtsi | 24 - + core/arch/arm/dts/stm32mp157a-dk1.dts | 29 +- + core/arch/arm/dts/stm32mp157a-ed1.dts | 46 + + core/arch/arm/dts/stm32mp157a-ev1.dts | 23 + + core/arch/arm/dts/stm32mp157c-dk2.dts | 95 +- + core/arch/arm/dts/stm32mp157c-ed1.dts | 373 +----- + core/arch/arm/dts/stm32mp157c-ev1.dts | 350 +----- + core/arch/arm/dts/stm32mp157d-dk1.dts | 49 + + core/arch/arm/dts/stm32mp157d-ed1.dts | 46 + + core/arch/arm/dts/stm32mp157d-ev1.dts | 22 + + core/arch/arm/dts/stm32mp157f-dk2.dts | 55 + + core/arch/arm/dts/stm32mp157f-ed1.dts | 51 + + core/arch/arm/dts/stm32mp157f-ev1.dts | 22 + + core/arch/arm/dts/stm32mp15xa.dtsi | 13 + + core/arch/arm/dts/stm32mp15xc.dtsi | 3 + + core/arch/arm/dts/stm32mp15xd.dtsi | 19 + + core/arch/arm/dts/stm32mp15xf.dtsi | 21 + + core/arch/arm/dts/stm32mp15xx-dkx.dtsi | 692 ++++------ + core/arch/arm/dts/stm32mp15xx-edx.dtsi | 478 +++++++ + core/arch/arm/dts/stm32mp15xx-evx.dtsi | 71 ++ + core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi | 3 +- + core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi | 2 +- + core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi | 3 +- + core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi | 2 +- + core/arch/arm/include/arm32.h | 11 +- + core/arch/arm/include/mm/core_mmu.h | 3 + + core/arch/arm/include/sm/pm.h | 4 + + core/arch/arm/mm/core_mmu.c | 18 +- + core/arch/arm/mm/mobj.c | 5 +- + core/arch/arm/plat-stm32mp1/boot_api.h | 2 + + core/arch/arm/plat-stm32mp1/conf.mk | 59 +- + .../arm/plat-stm32mp1/drivers/stm32mp1_calib.c | 501 ++++++++ + core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c | 1268 ++++++++++++++++++- + .../arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c | 469 +++++++ + .../arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h | 219 ++++ + core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h | 31 +- + core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h | 35 +- + core/arch/arm/plat-stm32mp1/drivers/sub.mk | 2 + + core/arch/arm/plat-stm32mp1/main.c | 316 ++++- + .../arm/plat-stm32mp1/nsec-service/low_power_svc.c | 152 +++ + .../arm/plat-stm32mp1/nsec-service/low_power_svc.h | 55 + + core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.c | 89 ++ + core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.h | 22 + + core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c | 195 +++ + core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.h | 30 + + .../arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h | 196 ++- + .../nsec-service/stm32mp1_svc_setup.c | 79 +- + core/arch/arm/plat-stm32mp1/nsec-service/sub.mk | 3 + + core/arch/arm/plat-stm32mp1/platform_config.h | 131 +- + core/arch/arm/plat-stm32mp1/pm/context.c | 521 ++++++++ + core/arch/arm/plat-stm32mp1/pm/context.h | 102 ++ + .../arm/plat-stm32mp1/pm/context_asm_defines.c | 28 + + core/arch/arm/plat-stm32mp1/pm/low_power.c | 609 +++++++++ + core/arch/arm/plat-stm32mp1/pm/pm_helpers.S | 740 +++++++++++ + core/arch/arm/plat-stm32mp1/pm/power.h | 27 + + core/arch/arm/plat-stm32mp1/pm/power_config.c | 252 ++++ + core/arch/arm/plat-stm32mp1/pm/psci.c | 224 +++- + core/arch/arm/plat-stm32mp1/pm/sub.mk | 6 + + core/arch/arm/plat-stm32mp1/reset.S | 30 +- + core/arch/arm/plat-stm32mp1/scmi_server.c | 81 +- + core/arch/arm/plat-stm32mp1/shared_resources.c | 31 +- + core/arch/arm/plat-stm32mp1/stm32_util.h | 54 + + core/arch/arm/plat-stm32mp1/stm32mp_pm.h | 21 + + core/arch/arm/sm/pm_a32.S | 83 +- + core/arch/arm/tee/entry_std.c | 2 +- + core/drivers/gic.c | 225 +++- + core/drivers/stm32_bsec.c | 130 +- + core/drivers/stm32_iwdg.c | 313 +++++ + core/drivers/stm32_rtc.c | 445 +++++++ + core/drivers/stm32_tim.c | 286 +++++ + core/drivers/sub.mk | 3 + + core/include/drivers/gic.h | 24 + + core/include/drivers/stm32_bsec.h | 16 + + core/include/drivers/stm32_iwdg.h | 17 + + core/include/drivers/stm32_rtc.h | 60 + + core/include/drivers/stm32_tim.h | 25 + + core/include/dt-bindings/clock/stm32mp1-clksrc.h | 284 +++++ + core/include/dt-bindings/power/stm32mp1-power.h | 19 + + core/include/dt-bindings/soc/st,stm32-etzpc.h | 107 ++ + core/include/kernel/interrupt.h | 15 + + core/include/kernel/panic.h | 6 + + core/kernel/interrupt.c | 10 + + core/kernel/panic.c | 23 +- + mk/config.mk | 2 +- + 88 files changed, 10040 insertions(+), 3470 deletions(-) + create mode 100644 CONTRIBUTING.md + create mode 100644 core/arch/arm/dts/stm32mp157a-ed1.dts + create mode 100644 core/arch/arm/dts/stm32mp157a-ev1.dts + create mode 100644 core/arch/arm/dts/stm32mp157d-dk1.dts + create mode 100644 core/arch/arm/dts/stm32mp157d-ed1.dts + create mode 100644 core/arch/arm/dts/stm32mp157d-ev1.dts + create mode 100644 core/arch/arm/dts/stm32mp157f-dk2.dts + create mode 100644 core/arch/arm/dts/stm32mp157f-ed1.dts + create mode 100644 core/arch/arm/dts/stm32mp157f-ev1.dts + create mode 100644 core/arch/arm/dts/stm32mp15xa.dtsi + create mode 100644 core/arch/arm/dts/stm32mp15xd.dtsi + create mode 100644 core/arch/arm/dts/stm32mp15xf.dtsi + create mode 100644 core/arch/arm/dts/stm32mp15xx-edx.dtsi + create mode 100644 core/arch/arm/dts/stm32mp15xx-evx.dtsi + create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c + create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c + create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h + create mode 100644 core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.c + create mode 100644 core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.h + create mode 100644 core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.c + create mode 100644 core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.h + create mode 100644 core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c + create mode 100644 core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.h + create mode 100644 core/arch/arm/plat-stm32mp1/pm/context.c + create mode 100644 core/arch/arm/plat-stm32mp1/pm/context.h + create mode 100644 core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c + create mode 100644 core/arch/arm/plat-stm32mp1/pm/low_power.c + create mode 100644 core/arch/arm/plat-stm32mp1/pm/pm_helpers.S + create mode 100644 core/arch/arm/plat-stm32mp1/pm/power.h + create mode 100644 core/arch/arm/plat-stm32mp1/pm/power_config.c + create mode 100644 core/arch/arm/plat-stm32mp1/stm32mp_pm.h + create mode 100644 core/drivers/stm32_iwdg.c + create mode 100644 core/drivers/stm32_rtc.c + create mode 100644 core/drivers/stm32_tim.c + create mode 100644 core/include/drivers/stm32_iwdg.h + create mode 100644 core/include/drivers/stm32_rtc.h + create mode 100644 core/include/drivers/stm32_tim.h + create mode 100644 core/include/dt-bindings/clock/stm32mp1-clksrc.h + create mode 100644 core/include/dt-bindings/power/stm32mp1-power.h + create mode 100644 core/include/dt-bindings/soc/st,stm32-etzpc.h + +diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md +new file mode 100644 +index 0000000..3d1bacd +--- /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/core/arch/arm/dts/stm32mp15-pinctrl.dtsi b/core/arch/arm/dts/stm32mp15-pinctrl.dtsi +index 0237d4d..d3d1744 100644 +--- a/core/arch/arm/dts/stm32mp15-pinctrl.dtsi ++++ b/core/arch/arm/dts/stm32mp15-pinctrl.dtsi +@@ -6,162 +6,6 @@ + #include + + &pinctrl { +- adc1_in6_pins_a: adc1-in6 { +- pins { +- pinmux = ; +- }; +- }; +- +- adc12_ain_pins_a: adc12-ain-0 { +- pins { +- pinmux = , /* ADC1 in13 */ +- , /* ADC1 in6 */ +- , /* ADC2 in2 */ +- ; /* ADC2 in6 */ +- }; +- }; +- +- adc12_usb_cc_pins_a: adc12-usb-cc-pins-0 { +- pins { +- pinmux = , /* ADC12 in18 */ +- ; /* ADC12 in19 */ +- }; +- }; +- +- cec_pins_a: cec-0 { +- pins { +- pinmux = ; +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- cec_pins_sleep_a: cec-sleep-0 { +- pins { +- pinmux = ; /* HDMI_CEC */ +- }; +- }; +- +- cec_pins_b: cec-1 { +- pins { +- pinmux = ; +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- cec_pins_sleep_b: cec-sleep-1 { +- pins { +- pinmux = ; /* HDMI_CEC */ +- }; +- }; +- +- dac_ch1_pins_a: dac-ch1 { +- pins { +- pinmux = ; +- }; +- }; +- +- dac_ch2_pins_a: dac-ch2 { +- pins { +- pinmux = ; +- }; +- }; +- +- dcmi_pins_a: dcmi-0 { +- pins { +- pinmux = ,/* DCMI_HSYNC */ +- ,/* DCMI_VSYNC */ +- ,/* DCMI_PIXCLK */ +- ,/* DCMI_D0 */ +- ,/* DCMI_D1 */ +- ,/* DCMI_D2 */ +- ,/* DCMI_D3 */ +- ,/* DCMI_D4 */ +- ,/* DCMI_D5 */ +- ,/* DCMI_D6 */ +- ,/* DCMI_D7 */ +- ,/* DCMI_D8 */ +- ,/* DCMI_D9 */ +- ,/* DCMI_D10 */ +- ;/* DCMI_D11 */ +- bias-disable; +- }; +- }; +- +- dcmi_sleep_pins_a: dcmi-sleep-0 { +- pins { +- pinmux = ,/* DCMI_HSYNC */ +- ,/* DCMI_VSYNC */ +- ,/* DCMI_PIXCLK */ +- ,/* DCMI_D0 */ +- ,/* DCMI_D1 */ +- ,/* DCMI_D2 */ +- ,/* DCMI_D3 */ +- ,/* DCMI_D4 */ +- ,/* DCMI_D5 */ +- ,/* DCMI_D6 */ +- ,/* DCMI_D7 */ +- ,/* DCMI_D8 */ +- ,/* DCMI_D9 */ +- ,/* DCMI_D10 */ +- ;/* DCMI_D11 */ +- }; +- }; +- +- ethernet0_rgmii_pins_a: rgmii-0 { +- pins1 { +- pinmux = , /* ETH_RGMII_CLK125 */ +- , /* ETH_RGMII_GTX_CLK */ +- , /* ETH_RGMII_TXD0 */ +- , /* ETH_RGMII_TXD1 */ +- , /* ETH_RGMII_TXD2 */ +- , /* ETH_RGMII_TXD3 */ +- , /* ETH_RGMII_TX_CTL */ +- ; /* ETH_MDC */ +- bias-disable; +- drive-push-pull; +- slew-rate = <2>; +- }; +- pins2 { +- pinmux = ; /* ETH_MDIO */ +- bias-disable; +- drive-push-pull; +- slew-rate = <0>; +- }; +- pins3 { +- pinmux = , /* ETH_RGMII_RXD0 */ +- , /* ETH_RGMII_RXD1 */ +- , /* ETH_RGMII_RXD2 */ +- , /* ETH_RGMII_RXD3 */ +- , /* ETH_RGMII_RX_CLK */ +- ; /* ETH_RGMII_RX_CTL */ +- bias-disable; +- }; +- }; +- +- ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 { +- pins1 { +- pinmux = , /* ETH_RGMII_CLK125 */ +- , /* ETH_RGMII_GTX_CLK */ +- , /* ETH_RGMII_TXD0 */ +- , /* ETH_RGMII_TXD1 */ +- , /* ETH_RGMII_TXD2 */ +- , /* ETH_RGMII_TXD3 */ +- , /* ETH_RGMII_TX_CTL */ +- , /* ETH_MDIO */ +- , /* ETH_MDC */ +- , /* ETH_RGMII_RXD0 */ +- , /* ETH_RGMII_RXD1 */ +- , /* ETH_RGMII_RXD2 */ +- , /* ETH_RGMII_RXD3 */ +- , /* ETH_RGMII_RX_CLK */ +- ; /* ETH_RGMII_RX_CTL */ +- }; +- }; +- + fmc_pins_a: fmc-0 { + pins1 { + pinmux = , /* FMC_NOE */ +@@ -187,412 +31,6 @@ + }; + }; + +- fmc_sleep_pins_a: fmc-sleep-0 { +- pins { +- pinmux = , /* FMC_NOE */ +- , /* FMC_NWE */ +- , /* FMC_A16_FMC_CLE */ +- , /* FMC_A17_FMC_ALE */ +- , /* FMC_D0 */ +- , /* FMC_D1 */ +- , /* FMC_D2 */ +- , /* FMC_D3 */ +- , /* FMC_D4 */ +- , /* FMC_D5 */ +- , /* FMC_D6 */ +- , /* FMC_D7 */ +- , /* FMC_NWAIT */ +- ; /* FMC_NE2_FMC_NCE */ +- }; +- }; +- +- i2c1_pins_a: i2c1-0 { +- pins { +- pinmux = , /* I2C1_SCL */ +- ; /* I2C1_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- i2c1_pins_sleep_a: i2c1-1 { +- pins { +- pinmux = , /* I2C1_SCL */ +- ; /* I2C1_SDA */ +- }; +- }; +- +- i2c1_pins_b: i2c1-2 { +- pins { +- pinmux = , /* I2C1_SCL */ +- ; /* I2C1_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- i2c1_pins_sleep_b: i2c1-3 { +- pins { +- pinmux = , /* I2C1_SCL */ +- ; /* I2C1_SDA */ +- }; +- }; +- +- i2c2_pins_a: i2c2-0 { +- pins { +- pinmux = , /* I2C2_SCL */ +- ; /* I2C2_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- i2c2_pins_sleep_a: i2c2-1 { +- pins { +- pinmux = , /* I2C2_SCL */ +- ; /* I2C2_SDA */ +- }; +- }; +- +- i2c2_pins_b1: i2c2-2 { +- pins { +- pinmux = ; /* I2C2_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- i2c2_pins_sleep_b1: i2c2-3 { +- pins { +- pinmux = ; /* I2C2_SDA */ +- }; +- }; +- +- i2c5_pins_a: i2c5-0 { +- pins { +- pinmux = , /* I2C5_SCL */ +- ; /* I2C5_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- i2c5_pins_sleep_a: i2c5-1 { +- pins { +- pinmux = , /* I2C5_SCL */ +- ; /* I2C5_SDA */ +- +- }; +- }; +- +- i2s2_pins_a: i2s2-0 { +- pins { +- pinmux = , /* I2S2_SDO */ +- , /* I2S2_WS */ +- ; /* I2S2_CK */ +- slew-rate = <1>; +- drive-push-pull; +- bias-disable; +- }; +- }; +- +- i2s2_pins_sleep_a: i2s2-1 { +- pins { +- pinmux = , /* I2S2_SDO */ +- , /* I2S2_WS */ +- ; /* I2S2_CK */ +- }; +- }; +- +- ltdc_pins_a: ltdc-a-0 { +- pins { +- pinmux = , /* LCD_CLK */ +- , /* LCD_HSYNC */ +- , /* LCD_VSYNC */ +- , /* LCD_DE */ +- , /* LCD_R0 */ +- , /* LCD_R1 */ +- , /* LCD_R2 */ +- , /* LCD_R3 */ +- , /* LCD_R4 */ +- , /* LCD_R5 */ +- , /* LCD_R6 */ +- , /* LCD_R7 */ +- , /* LCD_G0 */ +- , /* LCD_G1 */ +- , /* LCD_G2 */ +- , /* LCD_G3 */ +- , /* LCD_G4 */ +- , /* LCD_G5 */ +- , /* LCD_G6 */ +- , /* LCD_G7 */ +- , /* LCD_B0 */ +- , /* LCD_B1 */ +- , /* LCD_B2 */ +- , /* LCD_B3 */ +- , /* LCD_B4 */ +- , /* LCD_B5 */ +- , /* LCD_B6 */ +- ; /* LCD_B7 */ +- bias-disable; +- drive-push-pull; +- slew-rate = <1>; +- }; +- }; +- +- ltdc_pins_sleep_a: ltdc-a-1 { +- pins { +- pinmux = , /* LCD_CLK */ +- , /* LCD_HSYNC */ +- , /* LCD_VSYNC */ +- , /* LCD_DE */ +- , /* LCD_R0 */ +- , /* LCD_R1 */ +- , /* LCD_R2 */ +- , /* LCD_R3 */ +- , /* LCD_R4 */ +- , /* LCD_R5 */ +- , /* LCD_R6 */ +- , /* LCD_R7 */ +- , /* LCD_G0 */ +- , /* LCD_G1 */ +- , /* LCD_G2 */ +- , /* LCD_G3 */ +- , /* LCD_G4 */ +- , /* LCD_G5 */ +- , /* LCD_G6 */ +- , /* LCD_G7 */ +- , /* LCD_B0 */ +- , /* LCD_B1 */ +- , /* LCD_B2 */ +- , /* LCD_B3 */ +- , /* LCD_B4 */ +- , /* LCD_B5 */ +- , /* LCD_B6 */ +- ; /* LCD_B7 */ +- }; +- }; +- +- ltdc_pins_b: ltdc-b-0 { +- pins { +- pinmux = , /* LCD_CLK */ +- , /* LCD_HSYNC */ +- , /* LCD_VSYNC */ +- , /* LCD_DE */ +- , /* LCD_R0 */ +- , /* LCD_R1 */ +- , /* LCD_R2 */ +- , /* LCD_R3 */ +- , /* LCD_R4 */ +- , /* LCD_R5 */ +- , /* LCD_R6 */ +- , /* LCD_R7 */ +- , /* LCD_G0 */ +- , /* LCD_G1 */ +- , /* LCD_G2 */ +- , /* LCD_G3 */ +- , /* LCD_G4 */ +- , /* LCD_G5 */ +- , /* LCD_G6 */ +- , /* LCD_G7 */ +- , /* LCD_B0 */ +- , /* LCD_B1 */ +- , /* LCD_B2 */ +- , /* LCD_B3 */ +- , /* LCD_B4 */ +- , /* LCD_B5 */ +- , /* LCD_B6 */ +- ; /* LCD_B7 */ +- bias-disable; +- drive-push-pull; +- slew-rate = <1>; +- }; +- }; +- +- ltdc_pins_sleep_b: ltdc-b-1 { +- pins { +- pinmux = , /* LCD_CLK */ +- , /* LCD_HSYNC */ +- , /* LCD_VSYNC */ +- , /* LCD_DE */ +- , /* LCD_R0 */ +- , /* LCD_R1 */ +- , /* LCD_R2 */ +- , /* LCD_R3 */ +- , /* LCD_R4 */ +- , /* LCD_R5 */ +- , /* LCD_R6 */ +- , /* LCD_R7 */ +- , /* LCD_G0 */ +- , /* LCD_G1 */ +- , /* LCD_G2 */ +- , /* LCD_G3 */ +- , /* LCD_G4 */ +- , /* LCD_G5 */ +- , /* LCD_G6 */ +- , /* LCD_G7 */ +- , /* LCD_B0 */ +- , /* LCD_B1 */ +- , /* LCD_B2 */ +- , /* LCD_B3 */ +- , /* LCD_B4 */ +- , /* LCD_B5 */ +- , /* LCD_B6 */ +- ; /* LCD_B7 */ +- }; +- }; +- +- m_can1_pins_a: m-can1-0 { +- pins1 { +- pinmux = ; /* CAN1_TX */ +- slew-rate = <1>; +- drive-push-pull; +- bias-disable; +- }; +- pins2 { +- pinmux = ; /* CAN1_RX */ +- bias-disable; +- }; +- }; +- +- m_can1_sleep_pins_a: m_can1-sleep-0 { +- pins { +- pinmux = , /* CAN1_TX */ +- ; /* CAN1_RX */ +- }; +- }; +- +- pwm1_pins_a: pwm1-0 { +- pins { +- pinmux = , /* TIM1_CH1 */ +- , /* TIM1_CH2 */ +- ; /* TIM1_CH4 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm1_sleep_pins_a: pwm1-sleep-0 { +- pins { +- pinmux = , /* TIM1_CH1 */ +- , /* TIM1_CH2 */ +- ; /* TIM1_CH4 */ +- }; +- }; +- +- pwm2_pins_a: pwm2-0 { +- pins { +- pinmux = ; /* TIM2_CH4 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm2_sleep_pins_a: pwm2-sleep-0 { +- pins { +- pinmux = ; /* TIM2_CH4 */ +- }; +- }; +- +- pwm3_pins_a: pwm3-0 { +- pins { +- pinmux = ; /* TIM3_CH2 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm3_sleep_pins_a: pwm3-sleep-0 { +- pins { +- pinmux = ; /* TIM3_CH2 */ +- }; +- }; +- +- pwm4_pins_a: pwm4-0 { +- pins { +- pinmux = , /* TIM4_CH3 */ +- ; /* TIM4_CH4 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm4_sleep_pins_a: pwm4-sleep-0 { +- pins { +- pinmux = , /* TIM4_CH3 */ +- ; /* TIM4_CH4 */ +- }; +- }; +- +- pwm4_pins_b: pwm4-1 { +- pins { +- pinmux = ; /* TIM4_CH2 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm4_sleep_pins_b: pwm4-sleep-1 { +- pins { +- pinmux = ; /* TIM4_CH2 */ +- }; +- }; +- +- pwm5_pins_a: pwm5-0 { +- pins { +- pinmux = ; /* TIM5_CH2 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm5_sleep_pins_a: pwm5-sleep-0 { +- pins { +- pinmux = ; /* TIM5_CH2 */ +- }; +- }; +- +- pwm8_pins_a: pwm8-0 { +- pins { +- pinmux = ; /* TIM8_CH4 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm8_sleep_pins_a: pwm8-sleep-0 { +- pins { +- pinmux = ; /* TIM8_CH4 */ +- }; +- }; +- +- pwm12_pins_a: pwm12-0 { +- pins { +- pinmux = ; /* TIM12_CH1 */ +- bias-pull-down; +- drive-push-pull; +- slew-rate = <0>; +- }; +- }; +- +- pwm12_sleep_pins_a: pwm12-sleep-0 { +- pins { +- pinmux = ; /* TIM12_CH1 */ +- }; +- }; +- + qspi_clk_pins_a: qspi-clk-0 { + pins { + pinmux = ; /* QSPI_CLK */ +@@ -602,12 +40,6 @@ + }; + }; + +- qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { +- pins { +- pinmux = ; /* QSPI_CLK */ +- }; +- }; +- + qspi_bk1_pins_a: qspi-bk1-0 { + pins1 { + pinmux = , /* QSPI_BK1_IO0 */ +@@ -626,16 +58,6 @@ + }; + }; + +- qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 { +- pins { +- pinmux = , /* QSPI_BK1_IO0 */ +- , /* QSPI_BK1_IO1 */ +- , /* QSPI_BK1_IO2 */ +- , /* QSPI_BK1_IO3 */ +- ; /* QSPI_BK1_NCS */ +- }; +- }; +- + qspi_bk2_pins_a: qspi-bk2-0 { + pins1 { + pinmux = , /* QSPI_BK2_IO0 */ +@@ -654,86 +76,9 @@ + }; + }; + +- qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { ++ rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 { + pins { +- pinmux = , /* QSPI_BK2_IO0 */ +- , /* QSPI_BK2_IO1 */ +- , /* QSPI_BK2_IO2 */ +- , /* QSPI_BK2_IO3 */ +- ; /* QSPI_BK2_NCS */ +- }; +- }; +- +- sai2a_pins_a: sai2a-0 { +- pins { +- pinmux = , /* SAI2_SCK_A */ +- , /* SAI2_SD_A */ +- , /* SAI2_FS_A */ +- ; /* SAI2_MCLK_A */ +- slew-rate = <0>; +- drive-push-pull; +- bias-disable; +- }; +- }; +- +- sai2a_sleep_pins_a: sai2a-1 { +- pins { +- pinmux = , /* SAI2_SCK_A */ +- , /* SAI2_SD_A */ +- , /* SAI2_FS_A */ +- ; /* SAI2_MCLK_A */ +- }; +- }; +- +- sai2b_pins_a: sai2b-0 { +- pins1 { +- pinmux = , /* SAI2_SCK_B */ +- , /* SAI2_FS_B */ +- ; /* SAI2_MCLK_B */ +- slew-rate = <0>; +- drive-push-pull; +- bias-disable; +- }; +- pins2 { +- pinmux = ; /* SAI2_SD_B */ +- bias-disable; +- }; +- }; +- +- sai2b_sleep_pins_a: sai2b-1 { +- pins { +- pinmux = , /* SAI2_SD_B */ +- , /* SAI2_SCK_B */ +- , /* SAI2_FS_B */ +- ; /* SAI2_MCLK_B */ +- }; +- }; +- +- sai2b_pins_b: sai2b-2 { +- pins { +- pinmux = ; /* SAI2_SD_B */ +- bias-disable; +- }; +- }; +- +- sai2b_sleep_pins_b: sai2b-3 { +- pins { +- pinmux = ; /* SAI2_SD_B */ +- }; +- }; +- +- sai4a_pins_a: sai4a-0 { +- pins { +- pinmux = ; /* SAI4_SD_A */ +- slew-rate = <0>; +- drive-push-pull; +- bias-disable; +- }; +- }; +- +- sai4a_sleep_pins_a: sai4a-1 { +- pins { +- pinmux = ; /* SAI4_SD_A */ ++ pinmux = ; /* RTC_OUT2_RMP */ + }; + }; + +@@ -756,41 +101,6 @@ + }; + }; + +- sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 { +- pins1 { +- pinmux = , /* SDMMC1_D0 */ +- , /* SDMMC1_D1 */ +- , /* SDMMC1_D2 */ +- ; /* SDMMC1_D3 */ +- slew-rate = <1>; +- drive-push-pull; +- bias-disable; +- }; +- pins2 { +- pinmux = ; /* SDMMC1_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-disable; +- }; +- pins3 { +- pinmux = ; /* SDMMC1_CMD */ +- slew-rate = <1>; +- drive-open-drain; +- bias-disable; +- }; +- }; +- +- sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 { +- pins { +- pinmux = , /* SDMMC1_D0 */ +- , /* SDMMC1_D1 */ +- , /* SDMMC1_D2 */ +- , /* SDMMC1_D3 */ +- , /* SDMMC1_CK */ +- ; /* SDMMC1_CMD */ +- }; +- }; +- + sdmmc1_dir_pins_a: sdmmc1-dir-0 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ +@@ -806,15 +116,6 @@ + }; + }; + +- sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 { +- pins { +- pinmux = , /* SDMMC1_D0DIR */ +- , /* SDMMC1_D123DIR */ +- , /* SDMMC1_CDIR */ +- ; /* SDMMC1_CKIN */ +- }; +- }; +- + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ +@@ -834,41 +135,6 @@ + }; + }; + +- sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 { +- pins1 { +- pinmux = , /* SDMMC2_D0 */ +- , /* SDMMC2_D1 */ +- , /* SDMMC2_D2 */ +- ; /* SDMMC2_D3 */ +- slew-rate = <1>; +- drive-push-pull; +- bias-pull-up; +- }; +- pins2 { +- pinmux = ; /* SDMMC2_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-pull-up; +- }; +- pins3 { +- pinmux = ; /* SDMMC2_CMD */ +- slew-rate = <1>; +- drive-open-drain; +- bias-pull-up; +- }; +- }; +- +- sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 { +- pins { +- pinmux = , /* SDMMC2_D0 */ +- , /* SDMMC2_D1 */ +- , /* SDMMC2_D2 */ +- , /* SDMMC2_D3 */ +- , /* SDMMC2_CK */ +- ; /* SDMMC2_CMD */ +- }; +- }; +- + sdmmc2_b4_pins_b: sdmmc2-b4-1 { + pins1 { + pinmux = , /* SDMMC2_D0 */ +@@ -888,30 +154,6 @@ + }; + }; + +- sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 { +- pins1 { +- pinmux = , /* SDMMC2_D0 */ +- , /* SDMMC2_D1 */ +- , /* SDMMC2_D2 */ +- ; /* SDMMC2_D3 */ +- slew-rate = <1>; +- drive-push-pull; +- bias-disable; +- }; +- pins2 { +- pinmux = ; /* SDMMC2_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-disable; +- }; +- pins3 { +- pinmux = ; /* SDMMC2_CMD */ +- slew-rate = <1>; +- drive-open-drain; +- bias-disable; +- }; +- }; +- + sdmmc2_d47_pins_a: sdmmc2-d47-0 { + pins { + pinmux = , /* SDMMC2_D4 */ +@@ -924,140 +166,120 @@ + }; + }; + +- sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 { +- pins { +- pinmux = , /* SDMMC2_D4 */ +- , /* SDMMC2_D5 */ +- , /* SDMMC2_D6 */ +- ; /* SDMMC2_D7 */ +- }; +- }; +- +- sdmmc3_b4_pins_a: sdmmc3-b4-0 { ++ uart4_pins_a: uart4-0 { + pins1 { +- pinmux = , /* SDMMC3_D0 */ +- , /* SDMMC3_D1 */ +- , /* SDMMC3_D2 */ +- , /* SDMMC3_D3 */ +- ; /* SDMMC3_CMD */ +- slew-rate = <1>; ++ pinmux = ; /* UART4_TX */ ++ bias-disable; + drive-push-pull; +- bias-pull-up; ++ slew-rate = <0>; + }; + pins2 { +- pinmux = ; /* SDMMC3_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-pull-up; ++ pinmux = ; /* UART4_RX */ ++ bias-disable; + }; + }; + +- sdmmc3_b4_od_pins_a: sdmmc3-b4-od-0 { ++ uart4_pins_b: uart4-1 { + pins1 { +- pinmux = , /* SDMMC3_D0 */ +- , /* SDMMC3_D1 */ +- , /* SDMMC3_D2 */ +- ; /* SDMMC3_D3 */ +- slew-rate = <1>; ++ pinmux = ; /* UART4_TX */ ++ bias-disable; + drive-push-pull; +- bias-pull-up; ++ slew-rate = <0>; + }; + pins2 { +- pinmux = ; /* SDMMC3_CK */ +- slew-rate = <2>; +- drive-push-pull; +- bias-pull-up; +- }; +- pins3 { +- pinmux = ; /* SDMMC2_CMD */ +- slew-rate = <1>; +- drive-open-drain; +- bias-pull-up; ++ pinmux = ; /* UART4_RX */ ++ bias-disable; + }; + }; + +- sdmmc3_b4_sleep_pins_a: sdmmc3-b4-sleep-0 { +- pins { +- pinmux = , /* SDMMC3_D0 */ +- , /* SDMMC3_D1 */ +- , /* SDMMC3_D2 */ +- , /* SDMMC3_D3 */ +- , /* SDMMC3_CK */ +- ; /* SDMMC3_CMD */ ++ uart7_pins_a: uart7-0 { ++ pins1 { ++ pinmux = ; /* UART4_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; + }; +- }; +- +- spdifrx_pins_a: spdifrx-0 { +- pins { +- pinmux = ; /* SPDIF_IN1 */ ++ pins2 { ++ pinmux = , /* UART4_RX */ ++ , /* UART4_CTS */ ++ ; /* UART4_RTS */ + bias-disable; + }; + }; + +- spdifrx_sleep_pins_a: spdifrx-1 { +- pins { +- pinmux = ; /* SPDIF_IN1 */ ++ uart7_pins_b: uart7-1 { ++ pins1 { ++ pinmux = ; /* USART7_TX */ ++ bias-disable; ++ drive-push-pull; ++ slew-rate = <0>; ++ }; ++ pins2 { ++ pinmux = ; /* USART7_RX */ ++ bias-disable; + }; + }; + +- uart4_pins_a: uart4-0 { ++ usart2_pins_a: usart2-0 { + pins1 { +- pinmux = ; /* UART4_TX */ ++ pinmux = , /* USART2_TX */ ++ ; /* USART2_RTS */ + bias-disable; + drive-push-pull; +- slew-rate = <0>; ++ slew-rate = <3>; + }; + pins2 { +- pinmux = ; /* UART4_RX */ ++ pinmux = , /* USART2_RX */ ++ ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + +- uart4_pins_b: uart4-1 { ++ usart3_pins_a: usart3-0 { + pins1 { +- pinmux = ; /* UART4_TX */ ++ pinmux = , /* USART3_TX */ ++ ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { +- pinmux = ; /* UART4_RX */ ++ pinmux = , /* USART3_RX */ ++ ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; + +- uart7_pins_a: uart7-0 { ++ usart3_pins_b: usart3-1 { + pins1 { +- pinmux = ; /* UART4_TX */ ++ pinmux = , /* USART3_TX */ ++ ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { +- pinmux = , /* UART4_RX */ +- , /* UART4_CTS */ +- ; /* UART4_RTS */ ++ pinmux = , /* USART3_RX */ ++ ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; +-}; + +-&pinctrl_z { +- i2c2_pins_b2: i2c2-0 { ++ usbotg_hs_pins_a: usbotg_hs-0 { + pins { +- pinmux = ; /* I2C2_SCL */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; ++ pinmux = ; /* OTG_ID */ + }; + }; + +- i2c2_pins_sleep_b2: i2c2-1 { ++ usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { +- pinmux = ; /* I2C2_SCL */ ++ pinmux = , /* OTG_FS_DM */ ++ ; /* OTG_FS_DP */ + }; + }; ++}; + ++&pinctrl_z { + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ +@@ -1067,26 +289,4 @@ + slew-rate = <0>; + }; + }; +- +- i2c4_pins_sleep_a: i2c4-1 { +- pins { +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ +- }; +- }; +- +- spi1_pins_a: spi1-0 { +- pins1 { +- pinmux = , /* SPI1_SCK */ +- ; /* SPI1_MOSI */ +- bias-disable; +- drive-push-pull; +- slew-rate = <1>; +- }; +- +- pins2 { +- pinmux = ; /* SPI1_MISO */ +- bias-disable; +- }; +- }; + }; +diff --git a/core/arch/arm/dts/stm32mp151.dtsi b/core/arch/arm/dts/stm32mp151.dtsi +index d8ac702..6e6dff4 100644 +--- a/core/arch/arm/dts/stm32mp151.dtsi ++++ b/core/arch/arm/dts/stm32mp151.dtsi +@@ -19,9 +19,39 @@ + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <0>; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ nvmem-cells = <&part_number_otp>; ++ nvmem-cell-names = "part_number"; + }; + }; + ++ cpu0_opp_table: cpu0-opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ }; ++ ++ nvmem_layout: nvmem_layout@0 { ++ compatible = "st,stm32-nvmem-layout"; ++ ++ nvmem-cells = <&cfg0_otp>, ++ <&part_number_otp>, ++ <&monotonic_otp>, ++ <&nand_otp>, ++ <&uid_otp>, ++ <&package_otp>, ++ <&hw2_otp>; ++ ++ nvmem-cell-names = "cfg0_otp", ++ "part_number_otp", ++ "monotonic_otp", ++ "nand_otp", ++ "uid_otp", ++ "package_otp", ++ "hw2_otp"; ++ }; ++ + psci { + compatible = "arm,psci-1.0"; + method = "smc"; +@@ -35,15 +65,6 @@ + <0xa0022000 0x2000>; + }; + +- timer { +- compatible = "arm,armv7-timer"; +- interrupts = , +- , +- , +- ; +- interrupt-parent = <&intc>; +- }; +- + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; +@@ -76,37 +97,6 @@ + }; + }; + +- thermal-zones { +- cpu_thermal: cpu-thermal { +- polling-delay-passive = <0>; +- polling-delay = <0>; +- thermal-sensors = <&dts>; +- +- trips { +- cpu_alert1: cpu-alert1 { +- temperature = <85000>; +- hysteresis = <0>; +- type = "passive"; +- }; +- +- cpu-crit { +- temperature = <120000>; +- hysteresis = <0>; +- type = "critical"; +- }; +- }; +- +- cooling-maps { +- }; +- }; +- }; +- +- booster: regulator-booster { +- compatible = "st,stm32mp1-booster"; +- st,syscfg = <&syscfg>; +- status = "disabled"; +- }; +- + soc { + compatible = "simple-bus"; + #address-cells = <1>; +@@ -114,175 +104,6 @@ + interrupt-parent = <&intc>; + ranges; + +- timers2: timer@40000000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40000000 0x400>; +- clocks = <&rcc TIM2_K>; +- clock-names = "int"; +- dmas = <&dmamux1 18 0x400 0x1>, +- <&dmamux1 19 0x400 0x1>, +- <&dmamux1 20 0x400 0x1>, +- <&dmamux1 21 0x400 0x1>, +- <&dmamux1 22 0x400 0x1>; +- dma-names = "ch1", "ch2", "ch3", "ch4", "up"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@1 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <1>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-timer-counter"; +- status = "disabled"; +- }; +- }; +- +- timers3: timer@40001000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40001000 0x400>; +- clocks = <&rcc TIM3_K>; +- clock-names = "int"; +- dmas = <&dmamux1 23 0x400 0x1>, +- <&dmamux1 24 0x400 0x1>, +- <&dmamux1 25 0x400 0x1>, +- <&dmamux1 26 0x400 0x1>, +- <&dmamux1 27 0x400 0x1>, +- <&dmamux1 28 0x400 0x1>; +- dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@2 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <2>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-timer-counter"; +- status = "disabled"; +- }; +- }; +- +- timers4: timer@40002000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40002000 0x400>; +- clocks = <&rcc TIM4_K>; +- clock-names = "int"; +- dmas = <&dmamux1 29 0x400 0x1>, +- <&dmamux1 30 0x400 0x1>, +- <&dmamux1 31 0x400 0x1>, +- <&dmamux1 32 0x400 0x1>; +- dma-names = "ch1", "ch2", "ch3", "ch4"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@3 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <3>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-timer-counter"; +- status = "disabled"; +- }; +- }; +- +- timers5: timer@40003000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40003000 0x400>; +- clocks = <&rcc TIM5_K>; +- clock-names = "int"; +- dmas = <&dmamux1 55 0x400 0x1>, +- <&dmamux1 56 0x400 0x1>, +- <&dmamux1 57 0x400 0x1>, +- <&dmamux1 58 0x400 0x1>, +- <&dmamux1 59 0x400 0x1>, +- <&dmamux1 60 0x400 0x1>; +- dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@4 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <4>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-timer-counter"; +- status = "disabled"; +- }; +- }; +- +- timers6: timer@40004000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40004000 0x400>; +- clocks = <&rcc TIM6_K>; +- clock-names = "int"; +- dmas = <&dmamux1 69 0x400 0x1>; +- dma-names = "up"; +- status = "disabled"; +- +- timer@5 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <5>; +- status = "disabled"; +- }; +- }; +- +- timers7: timer@40005000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40005000 0x400>; +- clocks = <&rcc TIM7_K>; +- clock-names = "int"; +- dmas = <&dmamux1 70 0x400 0x1>; +- dma-names = "up"; +- status = "disabled"; +- +- timer@6 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <6>; +- status = "disabled"; +- }; +- }; +- + timers12: timer@40006000 { + #address-cells = <1>; + #size-cells = <0>; +@@ -291,152 +112,7 @@ + clocks = <&rcc TIM12_K>; + clock-names = "int"; + status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@11 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <11>; +- status = "disabled"; +- }; +- }; +- +- timers13: timer@40007000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40007000 0x400>; +- clocks = <&rcc TIM13_K>; +- clock-names = "int"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@12 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <12>; +- status = "disabled"; +- }; +- }; +- +- timers14: timer@40008000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x40008000 0x400>; +- clocks = <&rcc TIM14_K>; +- clock-names = "int"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@13 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <13>; +- status = "disabled"; +- }; +- }; +- +- lptimer1: timer@40009000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-lptimer"; +- reg = <0x40009000 0x400>; +- clocks = <&rcc LPTIM1_K>; +- clock-names = "mux"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm-lp"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- trigger@0 { +- compatible = "st,stm32-lptimer-trigger"; +- reg = <0>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-lptimer-counter"; +- status = "disabled"; +- }; +- }; +- +- spi2: spi@4000b000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; +- reg = <0x4000b000 0x400>; +- interrupts = ; +- clocks = <&rcc SPI2_K>; +- resets = <&rcc SPI2_R>; +- dmas = <&dmamux1 39 0x400 0x05>, +- <&dmamux1 40 0x400 0x05>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- i2s2: audio-controller@4000b000 { +- compatible = "st,stm32h7-i2s"; +- #sound-dai-cells = <0>; +- reg = <0x4000b000 0x400>; +- interrupts = ; +- dmas = <&dmamux1 39 0x400 0x01>, +- <&dmamux1 40 0x400 0x01>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- spi3: spi@4000c000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; +- reg = <0x4000c000 0x400>; +- interrupts = ; +- clocks = <&rcc SPI3_K>; +- resets = <&rcc SPI3_R>; +- dmas = <&dmamux1 61 0x400 0x05>, +- <&dmamux1 62 0x400 0x05>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- i2s3: audio-controller@4000c000 { +- compatible = "st,stm32h7-i2s"; +- #sound-dai-cells = <0>; +- reg = <0x4000c000 0x400>; +- interrupts = ; +- dmas = <&dmamux1 61 0x400 0x01>, +- <&dmamux1 62 0x400 0x01>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- spdifrx: audio-controller@4000d000 { +- compatible = "st,stm32h7-spdifrx"; +- #sound-dai-cells = <0>; +- reg = <0x4000d000 0x400>; +- clocks = <&rcc SPDIF_K>; +- clock-names = "kclk"; +- interrupts = ; +- dmas = <&dmamux1 93 0x400 0x01>, +- <&dmamux1 94 0x400 0x01>; +- dma-names = "rx", "rx-ctrl"; +- status = "disabled"; ++ secure-status = "disabled"; + }; + + usart2: serial@4000e000 { +@@ -444,6 +120,7 @@ + reg = <0x4000e000 0x400>; + interrupts = ; + clocks = <&rcc USART2_K>; ++ resets = <&rcc USART2_R>; + status = "disabled"; + }; + +@@ -452,14 +129,17 @@ + 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 = ; ++ interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART4_K>; ++ resets = <&rcc UART4_R>; ++ wakeup-source; + status = "disabled"; + }; + +@@ -468,99 +148,16 @@ + reg = <0x40011000 0x400>; + interrupts = ; + clocks = <&rcc UART5_K>; ++ resets = <&rcc UART5_R>; + status = "disabled"; + }; + +- i2c1: i2c@40012000 { +- compatible = "st,stm32f7-i2c"; +- reg = <0x40012000 0x400>; +- interrupt-names = "event", "error"; +- interrupts = , +- ; +- clocks = <&rcc I2C1_K>; +- resets = <&rcc I2C1_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c2: i2c@40013000 { +- compatible = "st,stm32f7-i2c"; +- reg = <0x40013000 0x400>; +- interrupt-names = "event", "error"; +- interrupts = , +- ; +- clocks = <&rcc I2C2_K>; +- resets = <&rcc I2C2_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c3: i2c@40014000 { +- compatible = "st,stm32f7-i2c"; +- reg = <0x40014000 0x400>; +- interrupt-names = "event", "error"; +- interrupts = , +- ; +- clocks = <&rcc I2C3_K>; +- resets = <&rcc I2C3_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c5: i2c@40015000 { +- compatible = "st,stm32f7-i2c"; +- reg = <0x40015000 0x400>; +- interrupt-names = "event", "error"; +- interrupts = , +- ; +- clocks = <&rcc I2C5_K>; +- resets = <&rcc I2C5_R>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- cec: cec@40016000 { +- compatible = "st,stm32-cec"; +- reg = <0x40016000 0x400>; +- interrupts = ; +- clocks = <&rcc CEC_K>, <&clk_lse>; +- clock-names = "cec", "hdmi-cec"; +- status = "disabled"; +- }; +- +- dac: dac@40017000 { +- compatible = "st,stm32h7-dac-core"; +- reg = <0x40017000 0x400>; +- clocks = <&rcc DAC12>; +- clock-names = "pclk"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- +- dac1: dac@1 { +- compatible = "st,stm32-dac"; +- #io-channels-cells = <1>; +- reg = <1>; +- status = "disabled"; +- }; +- +- dac2: dac@2 { +- compatible = "st,stm32-dac"; +- #io-channels-cells = <1>; +- reg = <2>; +- status = "disabled"; +- }; +- }; +- + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts = ; + clocks = <&rcc UART7_K>; ++ resets = <&rcc UART7_R>; + status = "disabled"; + }; + +@@ -569,125 +166,16 @@ + reg = <0x40019000 0x400>; + interrupts = ; + clocks = <&rcc UART8_K>; ++ resets = <&rcc UART8_R>; + status = "disabled"; + }; + +- timers1: timer@44000000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x44000000 0x400>; +- clocks = <&rcc TIM1_K>; +- clock-names = "int"; +- dmas = <&dmamux1 11 0x400 0x1>, +- <&dmamux1 12 0x400 0x1>, +- <&dmamux1 13 0x400 0x1>, +- <&dmamux1 14 0x400 0x1>, +- <&dmamux1 15 0x400 0x1>, +- <&dmamux1 16 0x400 0x1>, +- <&dmamux1 17 0x400 0x1>; +- dma-names = "ch1", "ch2", "ch3", "ch4", +- "up", "trig", "com"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@0 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <0>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-timer-counter"; +- status = "disabled"; +- }; +- }; +- +- timers8: timer@44001000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x44001000 0x400>; +- clocks = <&rcc TIM8_K>; +- clock-names = "int"; +- dmas = <&dmamux1 47 0x400 0x1>, +- <&dmamux1 48 0x400 0x1>, +- <&dmamux1 49 0x400 0x1>, +- <&dmamux1 50 0x400 0x1>, +- <&dmamux1 51 0x400 0x1>, +- <&dmamux1 52 0x400 0x1>, +- <&dmamux1 53 0x400 0x1>; +- dma-names = "ch1", "ch2", "ch3", "ch4", +- "up", "trig", "com"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@7 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <7>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-timer-counter"; +- status = "disabled"; +- }; +- }; +- + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts = ; + clocks = <&rcc USART6_K>; +- status = "disabled"; +- }; +- +- spi1: spi@44004000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; +- reg = <0x44004000 0x400>; +- interrupts = ; +- clocks = <&rcc SPI1_K>; +- resets = <&rcc SPI1_R>; +- dmas = <&dmamux1 37 0x400 0x05>, +- <&dmamux1 38 0x400 0x05>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- i2s1: audio-controller@44004000 { +- compatible = "st,stm32h7-i2s"; +- #sound-dai-cells = <0>; +- reg = <0x44004000 0x400>; +- interrupts = ; +- dmas = <&dmamux1 37 0x400 0x01>, +- <&dmamux1 38 0x400 0x01>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- spi4: spi@44005000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; +- reg = <0x44005000 0x400>; +- interrupts = ; +- clocks = <&rcc SPI4_K>; +- resets = <&rcc SPI4_R>; +- dmas = <&dmamux1 83 0x400 0x05>, +- <&dmamux1 84 0x400 0x05>; +- dma-names = "rx", "tx"; ++ resets = <&rcc USART6_R>; + status = "disabled"; + }; + +@@ -698,401 +186,42 @@ + reg = <0x44006000 0x400>; + clocks = <&rcc TIM15_K>; + clock-names = "int"; +- dmas = <&dmamux1 105 0x400 0x1>, +- <&dmamux1 106 0x400 0x1>, +- <&dmamux1 107 0x400 0x1>, +- <&dmamux1 108 0x400 0x1>; +- dma-names = "ch1", "up", "trig", "com"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@14 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <14>; +- status = "disabled"; +- }; +- }; +- +- timers16: timer@44007000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x44007000 0x400>; +- clocks = <&rcc TIM16_K>; +- clock-names = "int"; +- dmas = <&dmamux1 109 0x400 0x1>, +- <&dmamux1 110 0x400 0x1>; +- dma-names = "ch1", "up"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- timer@15 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <15>; +- status = "disabled"; +- }; +- }; +- +- timers17: timer@44008000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-timers"; +- reg = <0x44008000 0x400>; +- clocks = <&rcc TIM17_K>; +- clock-names = "int"; +- dmas = <&dmamux1 111 0x400 0x1>, +- <&dmamux1 112 0x400 0x1>; +- dma-names = "ch1", "up"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- timer@16 { +- compatible = "st,stm32h7-timer-trigger"; +- reg = <16>; +- status = "disabled"; +- }; +- }; +- +- spi5: spi@44009000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32h7-spi"; +- reg = <0x44009000 0x400>; +- interrupts = ; +- clocks = <&rcc SPI5_K>; +- resets = <&rcc SPI5_R>; +- dmas = <&dmamux1 85 0x400 0x05>, +- <&dmamux1 86 0x400 0x05>; +- dma-names = "rx", "tx"; +- status = "disabled"; +- }; +- +- sai1: sai@4400a000 { +- compatible = "st,stm32h7-sai"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x4400a000 0x400>; +- reg = <0x4400a000 0x4>, <0x4400a3f0 0x10>; +- interrupts = ; +- resets = <&rcc SAI1_R>; +- status = "disabled"; +- +- sai1a: audio-controller@4400a004 { +- #sound-dai-cells = <0>; +- +- compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1c>; +- clocks = <&rcc SAI1_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 87 0x400 0x01>; +- status = "disabled"; +- }; +- +- sai1b: audio-controller@4400a024 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; +- clocks = <&rcc SAI1_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 88 0x400 0x01>; +- status = "disabled"; +- }; +- }; +- +- sai2: sai@4400b000 { +- compatible = "st,stm32h7-sai"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x4400b000 0x400>; +- reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>; +- interrupts = ; +- resets = <&rcc SAI2_R>; +- status = "disabled"; +- +- sai2a: audio-controller@4400b004 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1c>; +- clocks = <&rcc SAI2_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 89 0x400 0x01>; +- status = "disabled"; +- }; +- +- sai2b: audio-controller@4400b024 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; +- clocks = <&rcc SAI2_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 90 0x400 0x01>; +- status = "disabled"; +- }; +- }; +- +- sai3: sai@4400c000 { +- compatible = "st,stm32h7-sai"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x4400c000 0x400>; +- reg = <0x4400c000 0x4>, <0x4400c3f0 0x10>; +- interrupts = ; +- resets = <&rcc SAI3_R>; +- status = "disabled"; +- +- sai3a: audio-controller@4400c004 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-a"; +- reg = <0x04 0x1c>; +- clocks = <&rcc SAI3_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 113 0x400 0x01>; +- status = "disabled"; +- }; +- +- sai3b: audio-controller@4400c024 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; +- clocks = <&rcc SAI3_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 114 0x400 0x01>; +- status = "disabled"; +- }; +- }; +- +- dfsdm: dfsdm@4400d000 { +- compatible = "st,stm32mp1-dfsdm"; +- reg = <0x4400d000 0x800>; +- clocks = <&rcc DFSDM_K>; +- clock-names = "dfsdm"; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- +- dfsdm0: filter@0 { +- compatible = "st,stm32-dfsdm-adc"; +- #io-channel-cells = <1>; +- reg = <0>; +- interrupts = ; +- dmas = <&dmamux1 101 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- +- dfsdm1: filter@1 { +- compatible = "st,stm32-dfsdm-adc"; +- #io-channel-cells = <1>; +- reg = <1>; +- interrupts = ; +- dmas = <&dmamux1 102 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- +- dfsdm2: filter@2 { +- compatible = "st,stm32-dfsdm-adc"; +- #io-channel-cells = <1>; +- reg = <2>; +- interrupts = ; +- dmas = <&dmamux1 103 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- +- dfsdm3: filter@3 { +- compatible = "st,stm32-dfsdm-adc"; +- #io-channel-cells = <1>; +- reg = <3>; +- interrupts = ; +- dmas = <&dmamux1 104 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- +- dfsdm4: filter@4 { +- compatible = "st,stm32-dfsdm-adc"; +- #io-channel-cells = <1>; +- reg = <4>; +- interrupts = ; +- dmas = <&dmamux1 91 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- +- dfsdm5: filter@5 { +- compatible = "st,stm32-dfsdm-adc"; +- #io-channel-cells = <1>; +- reg = <5>; +- interrupts = ; +- dmas = <&dmamux1 92 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- }; +- +- dma1: dma-controller@48000000 { +- compatible = "st,stm32-dma"; +- reg = <0x48000000 0x400>; +- interrupts = , +- , +- , +- , +- , +- , +- , +- ; +- clocks = <&rcc DMA1>; +- #dma-cells = <4>; +- st,mem2mem; +- dma-requests = <8>; +- }; +- +- dma2: dma-controller@48001000 { +- compatible = "st,stm32-dma"; +- reg = <0x48001000 0x400>; +- interrupts = , +- , +- , +- , +- , +- , +- , +- ; +- clocks = <&rcc DMA2>; +- #dma-cells = <4>; +- st,mem2mem; +- dma-requests = <8>; +- }; +- +- dmamux1: dma-router@48002000 { +- compatible = "st,stm32h7-dmamux"; +- reg = <0x48002000 0x1c>; +- #dma-cells = <3>; +- dma-requests = <128>; +- dma-masters = <&dma1 &dma2>; +- dma-channels = <16>; +- clocks = <&rcc DMAMUX>; +- }; +- +- adc: adc@48003000 { +- compatible = "st,stm32mp1-adc-core"; +- reg = <0x48003000 0x400>; +- interrupts = , +- ; +- clocks = <&rcc ADC12>, <&rcc ADC12_K>; +- clock-names = "bus", "adc"; +- interrupt-controller; +- st,syscfg = <&syscfg>; +- #interrupt-cells = <1>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- +- adc1: adc@0 { +- compatible = "st,stm32mp1-adc"; +- #io-channel-cells = <1>; +- reg = <0x0>; +- interrupt-parent = <&adc>; +- interrupts = <0>; +- dmas = <&dmamux1 9 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- +- adc2: adc@100 { +- compatible = "st,stm32mp1-adc"; +- #io-channel-cells = <1>; +- reg = <0x100>; +- interrupt-parent = <&adc>; +- interrupts = <1>; +- dmas = <&dmamux1 10 0x400 0x01>; +- dma-names = "rx"; +- status = "disabled"; +- }; +- }; +- +- sdmmc3: sdmmc@48004000 { +- compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x10153180>; +- reg = <0x48004000 0x400>; +- interrupts = ; +- interrupt-names = "cmd_irq"; +- clocks = <&rcc SDMMC3_K>; +- clock-names = "apb_pclk"; +- resets = <&rcc SDMMC3_R>; +- cap-sd-highspeed; +- cap-mmc-highspeed; +- max-frequency = <120000000>; + status = "disabled"; ++ secure-status = "disabled"; + }; + + usbotg_hs: usb-otg@49000000 { +- compatible = "snps,dwc2"; ++ compatible = "st,stm32mp1-hsotg", "snps,dwc2"; + reg = <0x49000000 0x10000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + interrupts = ; +- g-rx-fifo-size = <256>; ++ g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; +- g-tx-fifo-size = <128 128 64 64 64 64 32 32>; ++ g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; +- status = "disabled"; +- }; +- +- ipcc: mailbox@4c001000 { +- compatible = "st,stm32mp1-ipcc"; +- #mbox-cells = <1>; +- reg = <0x4c001000 0x400>; +- st,proc-id = <0>; +- interrupts-extended = +- <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, +- <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, +- <&exti 61 1>; +- interrupt-names = "rx", "tx", "wakeup"; +- clocks = <&rcc IPCC>; +- wakeup-source; +- status = "disabled"; +- }; +- +- dcmi: dcmi@4c006000 { +- compatible = "st,stm32-dcmi"; +- reg = <0x4c006000 0x400>; +- interrupts = ; +- resets = <&rcc CAMITF_R>; +- clocks = <&rcc DCMI>; +- clock-names = "mclk"; +- dmas = <&dmamux1 75 0x400 0x0d>; +- dma-names = "tx"; ++ usb33d-supply = <&usb33>; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; + #clock-cells = <1>; + #reset-cells = <1>; ++ interrupts = ; ++ secure-interrupts = ; ++ secure-interrupt-names = "wakeup"; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; ++ st,tzcr = <&rcc 0x0 0x1>; + + reg11: reg11 { + regulator-name = "reg11"; +@@ -1113,11 +242,35 @@ + }; + }; + ++ pwr_mcu: pwr_mcu@50001014 { ++ compatible = "syscon"; ++ reg = <0x50001014 0x4>; ++ }; ++ ++ pwr_irq: pwr@50001020 { ++ compatible = "st,stm32mp1-pwr"; ++ reg = <0x50001020 0x100>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ }; ++ + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; ++ ++ /* exti_pwr is an extra interrupt controller used for ++ * EXTI 55 to 60. It's mapped on pwr interrupt ++ * controller. ++ */ ++ exti_pwr: exti-pwr { ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&pwr_irq>; ++ st,irq-number = <6>; ++ }; + }; + + syscfg: syscon@50020000 { +@@ -1126,143 +279,14 @@ + clocks = <&rcc SYSCFG>; + }; + +- lptimer2: timer@50021000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-lptimer"; +- reg = <0x50021000 0x400>; +- clocks = <&rcc LPTIM2_K>; +- clock-names = "mux"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm-lp"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- trigger@1 { +- compatible = "st,stm32-lptimer-trigger"; +- reg = <1>; +- status = "disabled"; +- }; +- +- counter { +- compatible = "st,stm32-lptimer-counter"; +- status = "disabled"; +- }; +- }; +- +- lptimer3: timer@50022000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "st,stm32-lptimer"; +- reg = <0x50022000 0x400>; +- clocks = <&rcc LPTIM3_K>; +- clock-names = "mux"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm-lp"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- trigger@2 { +- compatible = "st,stm32-lptimer-trigger"; +- reg = <2>; +- status = "disabled"; +- }; +- }; +- +- lptimer4: timer@50023000 { +- compatible = "st,stm32-lptimer"; +- reg = <0x50023000 0x400>; +- clocks = <&rcc LPTIM4_K>; +- clock-names = "mux"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm-lp"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- }; +- +- lptimer5: timer@50024000 { +- compatible = "st,stm32-lptimer"; +- reg = <0x50024000 0x400>; +- clocks = <&rcc LPTIM5_K>; +- clock-names = "mux"; +- status = "disabled"; +- +- pwm { +- compatible = "st,stm32-pwm-lp"; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- }; +- +- vrefbuf: vrefbuf@50025000 { +- compatible = "st,stm32-vrefbuf"; +- reg = <0x50025000 0x8>; +- regulator-min-microvolt = <1500000>; +- regulator-max-microvolt = <2500000>; +- clocks = <&rcc VREF>; +- status = "disabled"; +- }; +- +- sai4: sai@50027000 { +- compatible = "st,stm32h7-sai"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 0x50027000 0x400>; +- reg = <0x50027000 0x4>, <0x500273f0 0x10>; +- interrupts = ; +- resets = <&rcc SAI4_R>; +- status = "disabled"; +- +- sai4a: audio-controller@50027004 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-a"; +- reg = <0x04 0x1c>; +- clocks = <&rcc SAI4_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 99 0x400 0x01>; +- status = "disabled"; +- }; +- +- sai4b: audio-controller@50027024 { +- #sound-dai-cells = <0>; +- compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; +- clocks = <&rcc SAI4_K>; +- clock-names = "sai_ck"; +- dmas = <&dmamux1 100 0x400 0x01>; +- status = "disabled"; +- }; +- }; +- +- dts: thermal@50028000 { +- compatible = "st,stm32-thermal"; +- reg = <0x50028000 0x100>; +- interrupts = ; +- clocks = <&rcc TMPSENS>; +- clock-names = "pclk"; +- #thermal-sensor-cells = <0>; +- status = "disabled"; +- }; +- + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; +- dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0>; +- dma-names = "in"; +- dma-maxburst = <2>; + status = "disabled"; ++ secure-status = "disabled"; + }; + + rng1: rng@54003000 { +@@ -1271,16 +295,7 @@ + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + status = "disabled"; +- }; +- +- mdma1: dma-controller@58000000 { +- compatible = "st,stm32h7-mdma"; +- reg = <0x58000000 0x1000>; +- interrupts = ; +- clocks = <&rcc MDMA>; +- #dma-cells = <5>; +- dma-channels = <32>; +- dma-requests = <48>; ++ secure-status = "disabled"; + }; + + fmc: nand-controller@58002000 { +@@ -1293,10 +308,6 @@ + <0x89010000 0x1000>, + <0x89020000 0x1000>; + interrupts = ; +- dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>, +- <&mdma1 20 0x10 0x12000a08 0x0 0x0>, +- <&mdma1 21 0x10 0x12000a0a 0x0 0x0>; +- dma-names = "tx", "rx", "ecc"; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; +@@ -1307,18 +318,15 @@ + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; +- dmas = <&mdma1 22 0x10 0x100002 0x0 0x0>, +- <&mdma1 22 0x10 0x100008 0x0 0x0>; +- dma-names = "tx", "rx"; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + status = "disabled"; + }; + + sdmmc1: sdmmc@58005000 { +- compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x10153180>; +- reg = <0x58005000 0x1000>; ++ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; ++ arm,primecell-periphid = <0x00253180>; ++ reg = <0x58005000 0x1000>, <0x58006000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC1_K>; +@@ -1331,9 +339,9 @@ + }; + + sdmmc2: sdmmc@58007000 { +- compatible = "arm,pl18x", "arm,primecell"; +- arm,primecell-periphid = <0x10153180>; +- reg = <0x58007000 0x1000>; ++ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; ++ arm,primecell-periphid = <0x00253180>; ++ reg = <0x58007000 0x1000>, <0x58008000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC2_K>; +@@ -1345,87 +353,26 @@ + status = "disabled"; + }; + +- crc1: crc@58009000 { +- compatible = "st,stm32f7-crc"; +- reg = <0x58009000 0x400>; +- clocks = <&rcc CRC1>; +- status = "disabled"; +- }; +- +- stmmac_axi_config_0: stmmac-axi-config { +- snps,wr_osr_lmt = <0x7>; +- snps,rd_osr_lmt = <0x7>; +- snps,blen = <0 0 0 0 16 8 4>; +- }; +- +- ethernet0: ethernet@5800a000 { +- compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; +- reg = <0x5800a000 0x2000>; +- reg-names = "stmmaceth"; +- interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; +- interrupt-names = "macirq"; +- clock-names = "stmmaceth", +- "mac-clk-tx", +- "mac-clk-rx", +- "ethstp"; +- clocks = <&rcc ETHMAC>, +- <&rcc ETHTX>, +- <&rcc ETHRX>, +- <&rcc ETHSTP>; +- st,syscon = <&syscfg 0x4>; +- snps,mixed-burst; +- snps,pbl = <2>; +- snps,en-tx-lpi-clockgating; +- snps,axi-config = <&stmmac_axi_config_0>; +- snps,tso; +- 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"; +- }; +- +- ltdc: display-controller@5a001000 { +- compatible = "st,stm32-ltdc"; +- reg = <0x5a001000 0x400>; +- interrupts = , +- ; +- clocks = <&rcc LTDC_PX>; +- clock-names = "lcd"; +- resets = <&rcc LTDC_R>; +- status = "disabled"; +- }; +- + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; ++ secure-interrupts = ; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; ++ secure-status = "disabled"; + }; + + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; ++ #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; ++ vdda1v1-supply = <®11>; ++ vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { +@@ -1446,6 +393,7 @@ + clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; ++ secure-status = "disabled"; + }; + + spi6: spi@5c001000 { +@@ -1456,22 +404,34 @@ + interrupts = ; + clocks = <&rcc SPI6_K>; + resets = <&rcc SPI6_R>; +- dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>, +- <&mdma1 35 0x0 0x40002 0x0 0x0>; +- dma-names = "rx", "tx"; + status = "disabled"; ++ secure-status = "disabled"; + }; + + i2c4: i2c@5c002000 { +- compatible = "st,stm32f7-i2c"; ++ compatible = "st,stm32mp15-i2c"; + reg = <0x5c002000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; ++ interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #address-cells = <1>; + #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x8>; ++ wakeup-source; ++ status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ iwdg1: watchdog@5c003000 { ++ compatible = "st,stm32mp1-iwdg"; ++ reg = <0x5C003000 0x400>; ++ interrupts = ; ++ clocks = <&rcc IWDG1>, <&rcc CK_LSI>; ++ clock-names = "pclk", "lsi"; ++ status = "disabled"; ++ secure-status = "disabled"; + }; + + rtc: rtc@5c004000 { +@@ -1479,21 +439,47 @@ + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; +- interrupts = ; ++ interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; ++ secure-status = "disabled"; + }; + +- bsec: efuse@5c005000 { ++ bsec: nvmem@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ cfg0_otp: cfg0_otp@0 { ++ reg = <0x0 0x1>; ++ }; ++ part_number_otp: part_number_otp@4 { ++ reg = <0x4 0x1>; ++ }; ++ monotonic_otp: monotonic_otp@10 { ++ reg = <0x10 0x4>; ++ }; ++ nand_otp: nand_otp@24 { ++ reg = <0x24 0x4>; ++ }; ++ uid_otp: uid_otp@34 { ++ reg = <0x34 0xc>; ++ }; ++ package_otp: package_otp@40 { ++ reg = <0x40 0x4>; ++ }; ++ hw2_otp: hw2_otp@48 { ++ reg = <0x48 0x4>; ++ }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; ++ pkh_otp: pkh_otp@60 { ++ reg = <0x60 0x20>; ++ }; + mac_addr: mac_addr@e4 { + reg = <0xe4 0x8>; + st,non-secure-otp; +@@ -1508,17 +494,32 @@ + secure-status = "okay"; + }; + ++ stgen: stgen@5c008000 { ++ compatible = "st,stm32-stgen"; ++ reg = <0x5C008000 0x1000>; ++ }; ++ + i2c6: i2c@5c009000 { +- compatible = "st,stm32f7-i2c"; ++ compatible = "st,stm32mp15-i2c"; + reg = <0x5c009000 0x400>; + interrupt-names = "event", "error"; +- interrupts = , +- ; ++ interrupts-extended = <&exti 54 IRQ_TYPE_LEVEL_HIGH>, ++ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C6_K>; + resets = <&rcc I2C6_R>; + #address-cells = <1>; + #size-cells = <0>; ++ st,syscfg-fmp = <&syscfg 0x4 0x20>; ++ wakeup-source; + status = "disabled"; ++ secure-status = "disabled"; ++ }; ++ ++ tamp: tamp@5c00a000 { ++ compatible = "st,stm32-tamp", "simple-bus", "syscon", "simple-mfd"; ++ reg = <0x5c00a000 0x400>; ++ secure-interrupts = ; ++ clocks = <&rcc RTCAPB>; + }; + + /* +@@ -1675,28 +676,8 @@ + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; ++ secure-status = "disabled"; + }; + }; + }; +- +- mlahb: ahb { +- compatible = "st,mlahb", "simple-bus"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges; +- dma-ranges = <0x00000000 0x38000000 0x10000>, +- <0x10000000 0x10000000 0x60000>, +- <0x30000000 0x30000000 0x60000>; +- +- m4_rproc: m4@10000000 { +- compatible = "st,stm32mp1-m4"; +- reg = <0x10000000 0x40000>, +- <0x30000000 0x40000>, +- <0x38000000 0x10000>; +- resets = <&rcc MCU_R>; +- st,syscfg-holdboot = <&rcc 0x10C 0x1>; +- st,syscfg-tz = <&rcc 0x000 0x1>; +- status = "disabled"; +- }; +- }; + }; +diff --git a/core/arch/arm/dts/stm32mp153.dtsi b/core/arch/arm/dts/stm32mp153.dtsi +index 2d759fc..617380a 100644 +--- a/core/arch/arm/dts/stm32mp153.dtsi ++++ b/core/arch/arm/dts/stm32mp153.dtsi +@@ -12,34 +12,9 @@ + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <1>; +- }; +- }; +- +- soc { +- m_can1: can@4400e000 { +- compatible = "bosch,m_can"; +- reg = <0x4400e000 0x400>, <0x44011000 0x1400>; +- reg-names = "m_can", "message_ram"; +- interrupts = , +- ; +- interrupt-names = "int0", "int1"; +- clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; +- clock-names = "hclk", "cclk"; +- bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; +- status = "disabled"; +- }; +- +- m_can2: can@4400f000 { +- compatible = "bosch,m_can"; +- reg = <0x4400f000 0x400>, <0x44011000 0x2800>; +- reg-names = "m_can", "message_ram"; +- interrupts = , +- ; +- interrupt-names = "int0", "int1"; +- clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; +- clock-names = "hclk", "cclk"; +- bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; +- status = "disabled"; ++ clocks = <&rcc CK_MPU>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + }; + }; +diff --git a/core/arch/arm/dts/stm32mp157.dtsi b/core/arch/arm/dts/stm32mp157.dtsi +index 3f0a4a9..c834029 100644 +--- a/core/arch/arm/dts/stm32mp157.dtsi ++++ b/core/arch/arm/dts/stm32mp157.dtsi +@@ -5,27 +5,3 @@ + */ + + #include "stm32mp153.dtsi" +- +-/ { +- soc { +- gpu: gpu@59000000 { +- compatible = "vivante,gc"; +- reg = <0x59000000 0x800>; +- interrupts = ; +- clocks = <&rcc GPU>, <&rcc GPU_K>; +- clock-names = "bus" ,"core"; +- resets = <&rcc GPU_R>; +- status = "disabled"; +- }; +- +- dsi: dsi@5a000000 { +- compatible = "st,stm32-dsi"; +- reg = <0x5a000000 0x800>; +- clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; +- clock-names = "pclk", "ref", "px_clk"; +- resets = <&rcc DSI_R>; +- reset-names = "apb"; +- status = "disabled"; +- }; +- }; +-}; +diff --git a/core/arch/arm/dts/stm32mp157a-dk1.dts b/core/arch/arm/dts/stm32mp157a-dk1.dts +index bc9ee69..4d506bc 100644 +--- a/core/arch/arm/dts/stm32mp157a-dk1.dts ++++ b/core/arch/arm/dts/stm32mp157a-dk1.dts +@@ -7,17 +7,20 @@ + /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"; + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { +- ethernet0 = ðernet0; + serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; + }; + + chosen { +@@ -25,14 +28,18 @@ + }; + }; + +-&rcc { +- status = "okay"; +- secure-status = "disable"; +-}; +- +-&bsec { +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- st,non-secure-otp; +- }; ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; + }; +diff --git a/core/arch/arm/dts/stm32mp157a-ed1.dts b/core/arch/arm/dts/stm32mp157a-ed1.dts +new file mode 100644 +index 0000000..4f84ec6 +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157a-ed1.dts +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xa.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157A eval daughter"; ++ compatible = "st,stm32mp157a-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/core/arch/arm/dts/stm32mp157a-ev1.dts b/core/arch/arm/dts/stm32mp157a-ev1.dts +new file mode 100644 +index 0000000..c577a90 +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157a-ev1.dts +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157a-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157A eval daughter on eval mother"; ++ compatible = "st,stm32mp157a-ev1", "st,stm32mp157a-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial1 = &usart3; ++ }; ++}; ++ +diff --git a/core/arch/arm/dts/stm32mp157c-dk2.dts b/core/arch/arm/dts/stm32mp157c-dk2.dts +index c5b226d..436a159 100644 +--- a/core/arch/arm/dts/stm32mp157c-dk2.dts ++++ b/core/arch/arm/dts/stm32mp157c-dk2.dts +@@ -11,14 +11,17 @@ + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxac-pinctrl.dtsi" + #include "stm32mp15xx-dkx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + + aliases { +- ethernet0 = ðernet0; + serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ serial3 = &usart2; + }; + + chosen { +@@ -26,81 +29,23 @@ + }; + }; + +-&dsi { +- #address-cells = <1>; +- #size-cells = <0>; ++&cryp1 { + status = "okay"; +- phy-dsi-supply = <®18>; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- reg = <0>; +- dsi_in: endpoint { +- remote-endpoint = <<dc_ep1_out>; +- }; +- }; +- +- port@1 { +- reg = <1>; +- dsi_out: endpoint { +- remote-endpoint = <&panel_in>; +- }; +- }; +- }; +- +- panel@0 { +- compatible = "orisetech,otm8009a"; +- reg = <0>; +- reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; +- power-supply = <&v3v3>; +- status = "okay"; +- +- port { +- panel_in: endpoint { +- remote-endpoint = <&dsi_out>; +- }; +- }; +- }; +-}; +- +-&i2c1 { +- touchscreen@38 { +- compatible = "focaltech,ft6236"; +- reg = <0x38>; +- interrupts = <2 2>; +- interrupt-parent = <&gpiof>; +- interrupt-controller; +- touchscreen-size-x = <480>; +- touchscreen-size-y = <800>; +- status = "okay"; +- }; + }; + +-<dc { +- status = "okay"; +- +- port { +- #address-cells = <1>; +- #size-cells = <0>; +- +- ltdc_ep1_out: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&dsi_in>; +- }; +- }; +-}; +- +-&rcc { +- status = "okay"; +- secure-status = "disable"; +-}; +- +-&bsec { +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- st,non-secure-otp; +- }; ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; + }; +diff --git a/core/arch/arm/dts/stm32mp157c-ed1.dts b/core/arch/arm/dts/stm32mp157c-ed1.dts +index ea301c5..5aadb1f 100644 +--- a/core/arch/arm/dts/stm32mp157c-ed1.dts ++++ b/core/arch/arm/dts/stm32mp157c-ed1.dts +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + /dts-v1/; + +@@ -9,8 +9,8 @@ + #include "stm32mp15xc.dtsi" + #include "stm32mp15-pinctrl.dtsi" + #include "stm32mp15xxaa-pinctrl.dtsi" +-#include +-#include ++#include "stm32mp15xx-edx.dtsi" ++#include + + / { + model = "STMicroelectronics STM32MP157C eval daughter"; +@@ -20,361 +20,32 @@ + stdout-path = "serial0:115200n8"; + }; + +- memory@c0000000 { +- device_type = "memory"; +- reg = <0xC0000000 0x40000000>; +- }; +- +- reserved-memory { +- #address-cells = <1>; +- #size-cells = <1>; +- ranges; +- +- mcuram2: mcuram2@10000000 { +- compatible = "shared-dma-pool"; +- reg = <0x10000000 0x40000>; +- no-map; +- }; +- +- vdev0vring0: vdev0vring0@10040000 { +- compatible = "shared-dma-pool"; +- reg = <0x10040000 0x1000>; +- no-map; +- }; +- +- vdev0vring1: vdev0vring1@10041000 { +- compatible = "shared-dma-pool"; +- reg = <0x10041000 0x1000>; +- no-map; +- }; +- +- vdev0buffer: vdev0buffer@10042000 { +- compatible = "shared-dma-pool"; +- reg = <0x10042000 0x4000>; +- no-map; +- }; +- +- mcuram: mcuram@30000000 { +- compatible = "shared-dma-pool"; +- reg = <0x30000000 0x40000>; +- no-map; +- }; +- +- retram: retram@38000000 { +- compatible = "shared-dma-pool"; +- reg = <0x38000000 0x10000>; +- no-map; +- }; +- +- gpu_reserved: gpu@e8000000 { +- reg = <0xe8000000 0x8000000>; +- no-map; +- }; +- }; +- + aliases { + serial0 = &uart4; + }; +- +- sd_switch: regulator-sd_switch { +- compatible = "regulator-gpio"; +- regulator-name = "sd_switch"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <2900000>; +- regulator-type = "voltage"; +- regulator-always-on; +- +- gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; +- gpios-states = <0>; +- states = <1800000 0x1>, +- <2900000 0x0>; +- }; +-}; +- +-&adc { +- /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ +- pinctrl-0 = <&adc1_in6_pins_a>; +- pinctrl-names = "default"; +- vdd-supply = <&vdd>; +- vdda-supply = <&vdda>; +- vref-supply = <&vdda>; +- status = "disabled"; +- adc1: adc@0 { +- st,adc-channels = <0 1 6>; +- /* 16.5 ck_cycles sampling time */ +- st,min-sample-time-nsecs = <400>; +- status = "okay"; +- }; +-}; +- +-&dac { +- pinctrl-names = "default"; +- pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; +- vref-supply = <&vdda>; +- status = "disabled"; +- dac1: dac@1 { +- status = "okay"; +- }; +- dac2: dac@2 { +- status = "okay"; +- }; +-}; +- +-&dts { +- status = "okay"; +-}; +- +-&gpu { +- contiguous-area = <&gpu_reserved>; +- status = "okay"; +-}; +- +-&i2c4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c4_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +- /* spare dmas for other usage */ +- /delete-property/dmas; +- /delete-property/dma-names; +- +- pmic: stpmic@33 { +- compatible = "st,stpmic1"; +- reg = <0x33>; +- interrupts-extended = <&gpioa 0 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>; +- interrupts = ; +- }; +- +- v2v8: ldo2 { +- regulator-name = "v2v8"; +- regulator-min-microvolt = <2800000>; +- regulator-max-microvolt = <2800000>; +- interrupts = ; +- }; +- +- vtt_ddr: ldo3 { +- regulator-name = "vtt_ddr"; +- regulator-min-microvolt = <500000>; +- regulator-max-microvolt = <750000>; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- +- vdd_usb: ldo4 { +- regulator-name = "vdd_usb"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- interrupts = ; +- }; +- +- vdd_sd: ldo5 { +- regulator-name = "vdd_sd"; +- regulator-min-microvolt = <2900000>; +- regulator-max-microvolt = <2900000>; +- interrupts = ; +- regulator-boot-on; +- }; +- +- v1v8: ldo6 { +- regulator-name = "v1v8"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <1800000>; +- interrupts = ; +- }; +- +- vref_ddr: vref_ddr { +- regulator-name = "vref_ddr"; +- regulator-always-on; +- regulator-over-current-protection; +- }; +- +- bst_out: boost { +- regulator-name = "bst_out"; +- interrupts = ; +- }; +- +- vbus_otg: pwr_sw1 { +- regulator-name = "vbus_otg"; +- interrupts = ; +- }; +- +- vbus_sw: pwr_sw2 { +- regulator-name = "vbus_sw"; +- interrupts = ; +- regulator-active-discharge = <1>; +- }; +- }; +- +- onkey { +- compatible = "st,stpmic1-onkey"; +- interrupts = , ; +- interrupt-names = "onkey-falling", "onkey-rising"; +- power-off-time-sec = <10>; +- status = "okay"; +- }; +- +- watchdog { +- compatible = "st,stpmic1-wdt"; +- status = "disabled"; +- }; +- }; + }; + +-&ipcc { +- status = "okay"; ++&cpu1 { ++ cpu-supply = <&vddcore>; + }; + +-&iwdg2 { +- timeout-sec = <32>; ++&cryp1 { + status = "okay"; + }; + +-&m4_rproc { +- memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, +- <&vdev0vring1>, <&vdev0buffer>; +- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; +- mbox-names = "vq0", "vq1", "shutdown"; +- interrupt-parent = <&exti>; +- interrupts = <68 1>; +- status = "okay"; +-}; +- +-&pwr_regulators { +- vdd-supply = <&vdd>; +- vdd_3v3_usbfs-supply = <&vdd_usb>; +-}; +- +-&rng1 { +- status = "okay"; +-}; +- +-&rtc { +- status = "okay"; +-}; +- +-&sdmmc1 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; +- pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; +- pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; +- broken-cd; +- st,sig-dir; +- st,neg-edge; +- st,use-ckin; +- bus-width = <4>; +- vmmc-supply = <&vdd_sd>; +- vqmmc-supply = <&sd_switch>; +- status = "okay"; +-}; +- +-&sdmmc2 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; +- pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; +- pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; +- non-removable; +- no-sd; +- no-sdio; +- st,neg-edge; +- bus-width = <8>; +- vmmc-supply = <&v3v3>; +- vqmmc-supply = <&v3v3>; +- mmc-ddr-3_3v; +- status = "okay"; +-}; +- +-&timers6 { +- status = "okay"; +- /* spare dmas for other usage */ +- /delete-property/dmas; +- /delete-property/dma-names; +- timer@5 { +- status = "okay"; +- }; +-}; +- +-&uart4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart4_pins_a>; +- status = "okay"; +-}; +- +-&usbphyc_port0 { +- phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; +-}; +- +-&usbphyc_port1 { +- phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; +-}; +- +-&rcc { +- status = "okay"; +- secure-status = "disable"; +-}; +- +-&bsec { +- board_id: board_id@ec { +- reg = <0xec 0x4>; +- st,non-secure-otp; +- }; ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; + }; +diff --git a/core/arch/arm/dts/stm32mp157c-ev1.dts b/core/arch/arm/dts/stm32mp157c-ev1.dts +index fd8c958..dd7da41 100644 +--- a/core/arch/arm/dts/stm32mp157c-ev1.dts ++++ b/core/arch/arm/dts/stm32mp157c-ev1.dts +@@ -1,13 +1,12 @@ + // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + /* +- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved +- * Author: Ludovic Barre for STMicroelectronics. ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. + */ + /dts-v1/; + + #include "stm32mp157c-ed1.dts" +-#include +-/* #include Remove due to BSD license issue */ ++#include "stm32mp15xx-evx.dtsi" + + / { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; +@@ -18,347 +17,6 @@ + }; + + aliases { +- serial0 = &uart4; +- ethernet0 = ðernet0; ++ serial1 = &usart3; + }; +- +- clocks { +- clk_ext_camera: clk-ext-camera { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <24000000>; +- }; +- }; +- +- joystick { +- compatible = "gpio-keys"; +- pinctrl-0 = <&joystick_pins>; +- pinctrl-names = "default"; +- button-0 { +- label = "JoySel"; +- /* linux,code = ; BSD license issue */ +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <0 IRQ_TYPE_EDGE_RISING>; +- }; +- button-1 { +- label = "JoyDown"; +- /* linux,code = ; BSD license issue */ +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <1 IRQ_TYPE_EDGE_RISING>; +- }; +- button-2 { +- label = "JoyLeft"; +- /* linux,code = ; BSD license issue */ +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <2 IRQ_TYPE_EDGE_RISING>; +- }; +- button-3 { +- label = "JoyRight"; +- /* linux,code = ; BSD license issue */ +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <3 IRQ_TYPE_EDGE_RISING>; +- }; +- button-4 { +- label = "JoyUp"; +- /* linux,code = ; BSD license issue */ +- interrupt-parent = <&stmfx_pinctrl>; +- interrupts = <4 IRQ_TYPE_EDGE_RISING>; +- }; +- }; +- +- panel_backlight: panel-backlight { +- compatible = "gpio-backlight"; +- gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; +- default-on; +- status = "okay"; +- }; +-}; +- +-&cec { +- pinctrl-names = "default"; +- pinctrl-0 = <&cec_pins_a>; +- status = "okay"; +-}; +- +-&dcmi { +- status = "okay"; +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&dcmi_pins_a>; +- pinctrl-1 = <&dcmi_sleep_pins_a>; +- +- port { +- dcmi_0: endpoint { +- remote-endpoint = <&ov5640_0>; +- bus-width = <8>; +- hsync-active = <0>; +- vsync-active = <0>; +- pclk-sample = <1>; +- }; +- }; +-}; +- +-&dsi { +- #address-cells = <1>; +- #size-cells = <0>; +- phy-dsi-supply = <®18>; +- status = "okay"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- reg = <0>; +- dsi_in: endpoint { +- remote-endpoint = <<dc_ep0_out>; +- }; +- }; +- +- port@1 { +- reg = <1>; +- dsi_out: endpoint { +- remote-endpoint = <&dsi_panel_in>; +- }; +- }; +- }; +- +- panel-dsi@0 { +- compatible = "raydium,rm68200"; +- reg = <0>; +- reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; +- backlight = <&panel_backlight>; +- power-supply = <&v3v3>; +- status = "okay"; +- +- port { +- dsi_panel_in: endpoint { +- remote-endpoint = <&dsi_out>; +- }; +- }; +- }; +-}; +- +-ðernet0 { +- status = "okay"; +- pinctrl-0 = <ðernet0_rgmii_pins_a>; +- pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; +- pinctrl-names = "default", "sleep"; +- phy-mode = "rgmii-id"; +- max-speed = <1000>; +- phy-handle = <&phy0>; +- +- mdio0 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "snps,dwmac-mdio"; +- phy0: ethernet-phy@0 { +- reg = <0>; +- }; +- }; +-}; +- +-&fmc { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&fmc_pins_a>; +- pinctrl-1 = <&fmc_sleep_pins_a>; +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- nand@0 { +- reg = <0>; +- nand-on-flash-bbt; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +-}; +- +-&i2c2 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c2_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +- +- ov5640: camera@3c { +- compatible = "ovti,ov5640"; +- reg = <0x3c>; +- clocks = <&clk_ext_camera>; +- clock-names = "xclk"; +- DOVDD-supply = <&v2v8>; +- powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; +- reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; +- rotation = <180>; +- status = "okay"; +- +- port { +- ov5640_0: endpoint { +- remote-endpoint = <&dcmi_0>; +- bus-width = <8>; +- data-shift = <2>; /* lines 9:2 are used */ +- hsync-active = <0>; +- vsync-active = <0>; +- pclk-sample = <1>; +- }; +- }; +- }; +- +- stmfx: stmfx@42 { +- compatible = "st,stmfx-0300"; +- reg = <0x42>; +- interrupts = <8 IRQ_TYPE_EDGE_RISING>; +- interrupt-parent = <&gpioi>; +- vdd-supply = <&v3v3>; +- +- stmfx_pinctrl: stmfx-pin-controller { +- compatible = "st,stmfx-0300-pinctrl"; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- gpio-ranges = <&stmfx_pinctrl 0 0 24>; +- +- joystick_pins: joystick { +- pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; +- bias-pull-down; +- }; +- }; +- }; +-}; +- +-&i2c5 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c5_pins_a>; +- i2c-scl-rising-time-ns = <185>; +- i2c-scl-falling-time-ns = <20>; +- status = "okay"; +-}; +- +-<dc { +- status = "okay"; +- +- port { +- #address-cells = <1>; +- #size-cells = <0>; +- +- ltdc_ep0_out: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&dsi_in>; +- }; +- }; +-}; +- +-&m_can1 { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&m_can1_pins_a>; +- pinctrl-1 = <&m_can1_sleep_pins_a>; +- status = "okay"; +-}; +- +-&qspi { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; +- pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; +- reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- +- flash0: mx66l51235l@0 { +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +- +- flash1: mx66l51235l@1 { +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; +- #address-cells = <1>; +- #size-cells = <1>; +- }; +-}; +- +-&sdmmc3 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc3_b4_pins_a>; +- pinctrl-1 = <&sdmmc3_b4_od_pins_a>; +- pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; +- broken-cd; +- st,neg-edge; +- bus-width = <4>; +- vmmc-supply = <&v3v3>; +- status = "disabled"; +-}; +- +-&spi1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi1_pins_a>; +- status = "disabled"; +-}; +- +-&timers2 { +- /* spare dmas for other usage (un-delete to enable pwm capture) */ +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm2_pins_a>; +- pinctrl-1 = <&pwm2_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@1 { +- status = "okay"; +- }; +-}; +- +-&timers8 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm8_pins_a>; +- pinctrl-1 = <&pwm8_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@7 { +- status = "okay"; +- }; +-}; +- +-&timers12 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm12_pins_a>; +- pinctrl-1 = <&pwm12_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@11 { +- status = "okay"; +- }; +-}; +- +-&usbh_ehci { +- phys = <&usbphyc_port0>; +- status = "okay"; +-}; +- +-&usbotg_hs { +- dr_mode = "peripheral"; +- phys = <&usbphyc_port1 0>; +- phy-names = "usb2-phy"; +- status = "okay"; +-}; +- +-&usbphyc { +- status = "okay"; + }; +diff --git a/core/arch/arm/dts/stm32mp157d-dk1.dts b/core/arch/arm/dts/stm32mp157d-dk1.dts +new file mode 100644 +index 0000000..d320f99 +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157d-dk1.dts +@@ -0,0 +1,49 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "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"; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/core/arch/arm/dts/stm32mp157d-ed1.dts b/core/arch/arm/dts/stm32mp157d-ed1.dts +new file mode 100644 +index 0000000..76f0614 +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157d-ed1.dts +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xd.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157D eval daughter"; ++ compatible = "st,stm32mp157d-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/core/arch/arm/dts/stm32mp157d-ev1.dts b/core/arch/arm/dts/stm32mp157d-ev1.dts +new file mode 100644 +index 0000000..47d962b +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157d-ev1.dts +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157d-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157D eval daughter on eval mother"; ++ compatible = "st,stm32mp157d-ev1", "st,stm32mp157d-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial1 = &usart3; ++ }; ++}; +diff --git a/core/arch/arm/dts/stm32mp157f-dk2.dts b/core/arch/arm/dts/stm32mp157f-dk2.dts +new file mode 100644 +index 0000000..9c79bfb +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157f-dk2.dts +@@ -0,0 +1,55 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xf.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F-DK2 Discovery Board"; ++ compatible = "st,stm32mp157f-dk2", "st,stm32mp157"; ++ ++ aliases { ++ serial0 = &uart4; ++ serial1 = &usart3; ++ serial2 = &uart7; ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcore>; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/core/arch/arm/dts/stm32mp157f-ed1.dts b/core/arch/arm/dts/stm32mp157f-ed1.dts +new file mode 100644 +index 0000000..a659cf8 +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157f-ed1.dts +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xf.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxaa-pinctrl.dtsi" ++#include "stm32mp15xx-edx.dtsi" ++#include ++ ++/ { ++ model = "STMicroelectronics STM32MP157F eval daughter"; ++ compatible = "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ }; ++}; ++ ++&cpu1{ ++ cpu-supply = <&vddcore>; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&etzpc { ++ st,decprot = < ++ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) ++ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) ++ DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) ++ >; ++}; +diff --git a/core/arch/arm/dts/stm32mp157f-ev1.dts b/core/arch/arm/dts/stm32mp157f-ev1.dts +new file mode 100644 +index 0000000..c8598ce +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp157f-ev1.dts +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved ++ * Author: Alexandre Torgue for STMicroelectronics. ++ */ ++/dts-v1/; ++ ++#include "stm32mp157f-ed1.dts" ++#include "stm32mp15xx-evx.dtsi" ++ ++/ { ++ model = "STMicroelectronics STM32MP157F eval daughter on eval mother"; ++ compatible = "st,stm32mp157f-ev1", "st,stm32mp157f-ed1", "st,stm32mp157"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ aliases { ++ serial1 = &usart3; ++ }; ++}; +diff --git a/core/arch/arm/dts/stm32mp15xa.dtsi b/core/arch/arm/dts/stm32mp15xa.dtsi +new file mode 100644 +index 0000000..5ed7e59 +--- /dev/null ++++ b/core/arch/arm/dts/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/core/arch/arm/dts/stm32mp15xc.dtsi b/core/arch/arm/dts/stm32mp15xc.dtsi +index b06a55a..68d822d 100644 +--- a/core/arch/arm/dts/stm32mp15xc.dtsi ++++ b/core/arch/arm/dts/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/core/arch/arm/dts/stm32mp15xd.dtsi b/core/arch/arm/dts/stm32mp15xd.dtsi +new file mode 100644 +index 0000000..18b05ee +--- /dev/null ++++ b/core/arch/arm/dts/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/core/arch/arm/dts/stm32mp15xf.dtsi b/core/arch/arm/dts/stm32mp15xf.dtsi +new file mode 100644 +index 0000000..526a162 +--- /dev/null ++++ b/core/arch/arm/dts/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/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi +index f6672e8..7254f9a 100644 +--- a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi ++++ b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi +@@ -4,8 +4,8 @@ + * Author: Alexandre Torgue for STMicroelectronics. + */ + +-#include +-#include ++#include ++#include + + / { + memory@c0000000 { +@@ -13,206 +13,36 @@ + reg = <0xc0000000 0x20000000>; + }; + +- reserved-memory { +- #address-cells = <1>; +- #size-cells = <1>; +- ranges; +- +- mcuram2: mcuram2@10000000 { +- compatible = "shared-dma-pool"; +- reg = <0x10000000 0x40000>; +- no-map; +- }; +- +- vdev0vring0: vdev0vring0@10040000 { +- compatible = "shared-dma-pool"; +- reg = <0x10040000 0x1000>; +- no-map; +- }; +- +- vdev0vring1: vdev0vring1@10041000 { +- compatible = "shared-dma-pool"; +- reg = <0x10041000 0x1000>; +- no-map; +- }; +- +- vdev0buffer: vdev0buffer@10042000 { +- compatible = "shared-dma-pool"; +- reg = <0x10042000 0x4000>; +- no-map; +- }; +- +- mcuram: mcuram@30000000 { +- compatible = "shared-dma-pool"; +- reg = <0x30000000 0x40000>; +- no-map; +- }; +- +- retram: retram@38000000 { +- compatible = "shared-dma-pool"; +- reg = <0x38000000 0x10000>; +- no-map; +- }; +- +- gpu_reserved: gpu@d4000000 { +- reg = <0xd4000000 0x4000000>; +- no-map; +- }; +- }; +- +- led { +- compatible = "gpio-leds"; +- blue { +- label = "heartbeat"; +- gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; +- linux,default-trigger = "heartbeat"; +- default-state = "off"; +- }; +- }; +- +- sound { +- compatible = "audio-graph-card"; +- label = "STM32MP1-DK"; +- routing = +- "Playback" , "MCLK", +- "Capture" , "MCLK", +- "MICL" , "Mic Bias"; +- dais = <&sai2a_port &sai2b_port &i2s2_port>; +- status = "okay"; ++ vin: vin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vin"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; + }; + }; + +-&adc { +- pinctrl-names = "default"; +- pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; +- vdd-supply = <&vdd>; +- vdda-supply = <&vdd>; +- vref-supply = <&vrefbuf>; +- status = "disabled"; +- adc1: adc@0 { +- /* +- * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. +- * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: +- * 5 * (56 + 47kOhms) * 5pF => 2.5us. +- * Use arbitrary margin here (e.g. 5us). +- */ +- st,min-sample-time-nsecs = <5000>; +- /* AIN connector, USB Type-C CC1 & CC2 */ +- st,adc-channels = <0 1 6 13 18 19>; +- status = "okay"; +- }; +- adc2: adc@100 { +- /* AIN connector, USB Type-C CC1 & CC2 */ +- st,adc-channels = <0 1 2 6 18 19>; +- st,min-sample-time-nsecs = <5000>; +- status = "okay"; ++&bsec { ++ board_id: board_id@ec { ++ reg = <0xec 0x4>; ++ st,non-secure-otp; + }; + }; + +-&cec { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&cec_pins_b>; +- pinctrl-1 = <&cec_pins_sleep_b>; +- status = "okay"; ++&clk_hse { ++ st,digbypass; + }; + +-ðernet0 { +- status = "okay"; +- pinctrl-0 = <ðernet0_rgmii_pins_a>; +- pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; +- pinctrl-names = "default", "sleep"; +- phy-mode = "rgmii-id"; +- max-speed = <1000>; +- phy-handle = <&phy0>; +- +- mdio0 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "snps,dwmac-mdio"; +- phy0: ethernet-phy@0 { +- reg = <0>; +- }; +- }; ++&cpu0{ ++ cpu-supply = <&vddcore>; + }; + +-&gpu { +- contiguous-area = <&gpu_reserved>; +- status = "okay"; ++&cpu1{ ++ cpu-supply = <&vddcore>; + }; + +-&i2c1 { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&i2c1_pins_a>; +- pinctrl-1 = <&i2c1_pins_sleep_a>; +- i2c-scl-rising-time-ns = <100>; +- i2c-scl-falling-time-ns = <7>; ++&hash1 { + status = "okay"; +- /delete-property/dmas; +- /delete-property/dma-names; +- +- hdmi-transmitter@39 { +- compatible = "sil,sii9022"; +- reg = <0x39>; +- iovcc-supply = <&v3v3_hdmi>; +- cvcc12-supply = <&v1v2_hdmi>; +- reset-gpios = <&gpioa 10 GPIO_ACTIVE_LOW>; +- interrupts = <1 IRQ_TYPE_EDGE_FALLING>; +- interrupt-parent = <&gpiog>; +- #sound-dai-cells = <0>; +- status = "okay"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- reg = <0>; +- sii9022_in: endpoint { +- remote-endpoint = <<dc_ep0_out>; +- }; +- }; +- +- port@3 { +- reg = <3>; +- sii9022_tx_endpoint: endpoint { +- remote-endpoint = <&i2s2_endpoint>; +- }; +- }; +- }; +- }; +- +- cs42l51: cs42l51@4a { +- compatible = "cirrus,cs42l51"; +- reg = <0x4a>; +- #sound-dai-cells = <0>; +- VL-supply = <&v3v3>; +- VD-supply = <&v1v8_audio>; +- VA-supply = <&v1v8_audio>; +- VAHP-supply = <&v1v8_audio>; +- reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; +- clocks = <&sai2a>; +- clock-names = "MCLK"; +- status = "okay"; +- +- cs42l51_port: port { +- #address-cells = <1>; +- #size-cells = <0>; +- +- cs42l51_tx_endpoint: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&sai2a_endpoint>; +- frame-master; +- bitclock-master; +- }; +- +- cs42l51_rx_endpoint: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&sai2b_endpoint>; +- frame-master; +- bitclock-master; +- }; +- }; +- }; + }; + + &i2c4 { +@@ -220,24 +50,33 @@ + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; ++ clock-frequency = <400000>; + status = "okay"; +- /* spare dmas for other usage */ +- /delete-property/dmas; +- /delete-property/dma-names; ++ secure-status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; +- interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; ++ 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 = <&vin>; + ldo3-supply = <&vdd_ddr>; ++ ldo4-supply = <&vin>; ++ ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; ++ vref_ddr-supply = <&vin>; ++ boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + +@@ -248,6 +87,16 @@ + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1200000>; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_ddr: buck2 { +@@ -257,6 +106,17 @@ + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd: buck3 { +@@ -267,6 +127,18 @@ + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; + }; + + v3v3: buck4 { +@@ -276,6 +148,16 @@ + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; ++ lp-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v1v8_audio: ldo1 { +@@ -283,7 +165,12 @@ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +- interrupts = ; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v3v3_hdmi: ldo2 { +@@ -291,7 +178,12 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; +- interrupts = ; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vtt_ddr: ldo3 { +@@ -300,21 +192,41 @@ + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; ++ lp-stop { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +- interrupts = ; ++ regulator-always-on; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; +- interrupts = ; + regulator-boot-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + v1v2_hdmi: ldo6 { +@@ -322,265 +234,200 @@ + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; +- interrupts = ; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; ++ lp-stop { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; + }; + +- bst_out: boost { ++ bst_out: boost { + regulator-name = "bst_out"; +- interrupts = ; +- }; ++ }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; +- interrupts = ; +- }; ++ }; + +- vbus_sw: pwr_sw2 { ++ vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; +- interrupts = ; + regulator-active-discharge = <1>; +- }; +- }; +- +- onkey { +- compatible = "st,stpmic1-onkey"; +- interrupts = , ; +- interrupt-names = "onkey-falling", "onkey-rising"; +- power-off-time-sec = <10>; +- status = "okay"; +- }; +- +- watchdog { +- compatible = "st,stpmic1-wdt"; +- status = "disabled"; +- }; +- }; +-}; +- +-&i2s2 { +- clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>; +- clock-names = "pclk", "i2sclk", "x8k", "x11k"; +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&i2s2_pins_a>; +- pinctrl-1 = <&i2s2_pins_sleep_a>; +- status = "okay"; +- +- i2s2_port: port { +- i2s2_endpoint: endpoint { +- remote-endpoint = <&sii9022_tx_endpoint>; +- format = "i2s"; +- mclk-fs = <256>; ++ }; + }; + }; + }; + +-&ipcc { +- status = "okay"; +-}; +- + &iwdg2 { + timeout-sec = <32>; + status = "okay"; ++ secure-status = "okay"; + }; + +-<dc { +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <<dc_pins_a>; +- pinctrl-1 = <<dc_pins_sleep_a>; +- status = "okay"; +- +- port { +- #address-cells = <1>; +- #size-cells = <0>; +- +- ltdc_ep0_out: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&sii9022_in>; +- }; +- }; +-}; +- +-&m4_rproc { +- memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, +- <&vdev0vring1>, <&vdev0buffer>; +- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; +- mbox-names = "vq0", "vq1", "shutdown"; +- interrupt-parent = <&exti>; +- interrupts = <68 1>; +- status = "okay"; ++&nvmem_layout { ++ nvmem-cells = <&cfg0_otp>, ++ <&part_number_otp>, ++ <&monotonic_otp>, ++ <&nand_otp>, ++ <&uid_otp>, ++ <&package_otp>, ++ <&hw2_otp>, ++ <&pkh_otp>, ++ <&board_id>; ++ ++ nvmem-cell-names = "cfg0_otp", ++ "part_number_otp", ++ "monotonic_otp", ++ "nand_otp", ++ "uid_otp", ++ "package_otp", ++ "hw2_otp", ++ "pkh_otp", ++ "board_id"; + }; + + &pwr_regulators { ++ system_suspend_supported_soc_modes = < ++ STM32_PM_CSLEEP_RUN ++ STM32_PM_CSTOP_ALLOW_LP_STOP ++ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR ++ >; ++ system_off_soc_mode = ; + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; + }; + ++&rcc { ++ st,hsi-cal; ++ st,csi-cal; ++ st,cal-sec = <60>; ++ 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"; +-}; +- +-&sai2 { +- clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; +- clock-names = "pclk", "x8k", "x11k"; +- pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; +- pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; +- status = "okay"; +- +- sai2a: audio-controller@4400b004 { +- #clock-cells = <0>; +- dma-names = "tx"; +- clocks = <&rcc SAI2_K>; +- clock-names = "sai_ck"; +- status = "okay"; +- +- sai2a_port: port { +- sai2a_endpoint: endpoint { +- remote-endpoint = <&cs42l51_tx_endpoint>; +- format = "i2s"; +- mclk-fs = <256>; +- dai-tdm-slot-num = <2>; +- dai-tdm-slot-width = <32>; +- }; +- }; +- }; +- +- sai2b: audio-controller@4400b024 { +- dma-names = "rx"; +- st,sync = <&sai2a 2>; +- clocks = <&rcc SAI2_K>, <&sai2a>; +- clock-names = "sai_ck", "MCLK"; +- status = "okay"; +- +- sai2b_port: port { +- sai2b_endpoint: endpoint { +- remote-endpoint = <&cs42l51_rx_endpoint>; +- format = "i2s"; +- mclk-fs = <256>; +- dai-tdm-slot-num = <2>; +- dai-tdm-slot-width = <32>; +- }; +- }; +- }; ++ secure-status = "okay"; + }; + + &sdmmc1 { +- pinctrl-names = "default", "opendrain", "sleep"; ++ pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; +- pinctrl-1 = <&sdmmc1_b4_od_pins_a>; +- pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; +- broken-cd; ++ disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; + }; + +-&sdmmc3 { +- pinctrl-names = "default", "opendrain", "sleep"; +- pinctrl-0 = <&sdmmc3_b4_pins_a>; +- pinctrl-1 = <&sdmmc3_b4_od_pins_a>; +- pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; +- broken-cd; +- st,neg-edge; +- bus-width = <4>; +- vmmc-supply = <&v3v3>; +- status = "disabled"; +-}; +- +-&timers1 { +- /* spare dmas for other usage */ +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm1_pins_a>; +- pinctrl-1 = <&pwm1_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@0 { +- status = "okay"; +- }; +-}; +- +-&timers3 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm3_pins_a>; +- pinctrl-1 = <&pwm3_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@2 { +- status = "okay"; +- }; +-}; +- +-&timers4 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm4_pins_a &pwm4_pins_b>; +- pinctrl-1 = <&pwm4_sleep_pins_a &pwm4_sleep_pins_b>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@3 { +- status = "okay"; +- }; +-}; +- +-&timers5 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm5_pins_a>; +- pinctrl-1 = <&pwm5_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@4 { +- status = "okay"; +- }; +-}; +- +-&timers6 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- timer@5 { +- status = "okay"; +- }; +-}; +- +-&timers12 { +- /delete-property/dmas; +- /delete-property/dma-names; +- status = "disabled"; +- pwm { +- pinctrl-0 = <&pwm12_pins_a>; +- pinctrl-1 = <&pwm12_sleep_pins_a>; +- pinctrl-names = "default", "sleep"; +- status = "okay"; +- }; +- timer@11 { +- status = "okay"; +- }; ++&timers15 { ++ secure-status = "okay"; ++ st,hsi-cal-input = <7>; ++ st,csi-cal-input = <8>; + }; + + &uart4 { +@@ -589,15 +436,23 @@ + status = "okay"; + }; + +-&usbh_ehci { +- phys = <&usbphyc_port0>; +- status = "okay"; ++&uart7 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart7_pins_b>; ++ status = "disabled"; ++}; ++ ++&usart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usart3_pins_b>; ++ uart-has-rtscts; ++ status = "disabled"; + }; + + &usbotg_hs { +- dr_mode = "peripheral"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; ++ usb-role-switch; + status = "okay"; + }; + +@@ -607,19 +462,8 @@ + + &usbphyc_port0 { + phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; + }; + + &usbphyc_port1 { + phy-supply = <&vdd_usb>; +- vdda1v1-supply = <®11>; +- vdda1v8-supply = <®18>; +-}; +- +-&vrefbuf { +- regulator-min-microvolt = <2500000>; +- regulator-max-microvolt = <2500000>; +- vdda-supply = <&vdd>; +- status = "okay"; + }; +diff --git a/core/arch/arm/dts/stm32mp15xx-edx.dtsi b/core/arch/arm/dts/stm32mp15xx-edx.dtsi +new file mode 100644 +index 0000000..b7683a6 +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp15xx-edx.dtsi +@@ -0,0 +1,478 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ ++ ++#include ++#include ++ ++/ { ++ memory@c0000000 { ++ device_type = "memory"; ++ reg = <0xC0000000 0x40000000>; ++ }; ++ ++ 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>; ++}; ++ ++&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; ++ lp-stop { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1200000>; ++ }; ++ lplv-stop { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr: buck2 { ++ regulator-name = "vdd_ddr"; ++ regulator-min-microvolt = <1350000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ regulator-initial-mode = <0>; ++ regulator-over-current-protection; ++ lp-stop { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ lplv-stop { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <1350000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd: buck3 { ++ 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; ++ lp-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ lplv-stop { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ v3v3: buck4 { ++ regulator-name = "v3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ regulator-initial-mode = <0>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda: ldo1 { ++ regulator-name = "vdda"; ++ regulator-min-microvolt = <2900000>; ++ regulator-max-microvolt = <2900000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ v2v8: ldo2 { ++ regulator-name = "v2v8"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vtt_ddr: ldo3 { ++ regulator-name = "vtt_ddr"; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <750000>; ++ regulator-always-on; ++ regulator-over-current-protection; ++ lp-stop { ++ regulator-off-in-suspend; ++ }; ++ lplv-stop { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_usb: ldo4 { ++ regulator-name = "vdd_usb"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ standby-ddr-sr { ++ regulator-on-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_sd: ldo5 { ++ regulator-name = "vdd_sd"; ++ regulator-min-microvolt = <2900000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-boot-on; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ v1v8: ldo6 { ++ regulator-name = "v1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ standby-ddr-sr { ++ regulator-off-in-suspend; ++ }; ++ standby-ddr-off { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vref_ddr: vref_ddr { ++ regulator-name = "vref_ddr"; ++ regulator-always-on; ++ regulator-over-current-protection; ++ 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; ++ }; ++ }; ++ ++ 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>; ++ 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; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&sdmmc2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; ++ non-removable; ++ no-sd; ++ no-sdio; ++ st,neg-edge; ++ bus-width = <8>; ++ vmmc-supply = <&v3v3>; ++ vqmmc-supply = <&vdd>; ++ mmc-ddr-3_3v; ++ status = "okay"; ++}; ++ ++&timers15 { ++ secure-status = "okay"; ++ st,hsi-cal-input = <7>; ++ st,csi-cal-input = <8>; ++}; ++ ++&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>; ++}; +diff --git a/core/arch/arm/dts/stm32mp15xx-evx.dtsi b/core/arch/arm/dts/stm32mp15xx-evx.dtsi +new file mode 100644 +index 0000000..fee2bac +--- /dev/null ++++ b/core/arch/arm/dts/stm32mp15xx-evx.dtsi +@@ -0,0 +1,71 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved ++ * Author: Ludovic Barre for STMicroelectronics. ++ */ ++ ++&fmc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fmc_pins_a>; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ nand@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_a>; ++ uart-has-rtscts; ++ status = "disabled"; ++}; ++ ++&usbotg_hs { ++ pinctrl-0 = <&usbotg_hs_pins_a>; ++ pinctrl-names = "default"; ++ phys = <&usbphyc_port1 0>; ++ phy-names = "usb2-phy"; ++ status = "okay"; ++}; ++ ++&usbphyc { ++ status = "okay"; ++}; +diff --git a/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi b/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi +index 04f7a43..341529b 100644 +--- a/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi ++++ b/core/arch/arm/dts/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 for STMicroelectronics. ++ * Author: Alexandre Torgue + */ + + &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/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi b/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi +index 328dad1..d29af89 100644 +--- a/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi ++++ b/core/arch/arm/dts/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 for STMicroelectronics. ++ * Author: Alexandre Torgue + */ + + &pinctrl { +diff --git a/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi b/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi +index 7eaa245..02070bb 100644 +--- a/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi ++++ b/core/arch/arm/dts/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 for STMicroelectronics. ++ * Author: Alexandre Torgue + */ + + &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/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi b/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi +index b63e207..023f540 100644 +--- a/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi ++++ b/core/arch/arm/dts/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 for STMicroelectronics. ++ * Author: Alexandre Torgue + */ + + &pinctrl { +diff --git a/core/arch/arm/include/arm32.h b/core/arch/arm/include/arm32.h +index 286f4e7..4a6f7a2 100644 +--- a/core/arch/arm/include/arm32.h ++++ b/core/arch/arm/include/arm32.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: BSD-2-Clause */ + /* +- * Copyright (c) 2016, Linaro Limited ++ * Copyright (c) 2016-2019, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +@@ -162,6 +162,15 @@ + #define IDPFR1_GENTIMER_SHIFT 16 + #define IDPFR1_GENTIMER_MASK (0xF << IDPFR1_GENTIMER_SHIFT) + ++/* Generic timer registers and fields */ ++#define CNTCR_OFFSET 0x000 ++#define CNTSR_OFFSET 0x004 ++#define CNTCVL_OFFSET 0x008 ++#define CNTCVU_OFFSET 0x00C ++#define CNTFID_OFFSET 0x020 ++ ++#define CNTCR_EN BIT(0) ++ + #ifndef __ASSEMBLER__ + #include + #ifdef CFG_ARM_GICV3 +diff --git a/core/arch/arm/include/mm/core_mmu.h b/core/arch/arm/include/mm/core_mmu.h +index a3dbdc0..05db229 100644 +--- a/core/arch/arm/include/mm/core_mmu.h ++++ b/core/arch/arm/include/mm/core_mmu.h +@@ -96,6 +96,7 @@ + * MEM_AREA_NSEC_SHM: NonSecure shared RAM between NSec and TEE. + * MEM_AREA_RAM_NSEC: NonSecure RAM storing data + * MEM_AREA_RAM_SEC: Secure RAM storing some secrets ++ * MEM_AREA_ROM_SEC: Secure read only memory storing some secrets + * MEM_AREA_IO_NSEC: NonSecure HW mapped registers + * MEM_AREA_IO_SEC: Secure HW mapped registers + * MEM_AREA_EXT_DT: Memory loads external device tree +@@ -120,6 +121,7 @@ enum teecore_memtypes { + MEM_AREA_NSEC_SHM, + MEM_AREA_RAM_NSEC, + MEM_AREA_RAM_SEC, ++ MEM_AREA_ROM_SEC, + MEM_AREA_IO_NSEC, + MEM_AREA_IO_SEC, + MEM_AREA_EXT_DT, +@@ -149,6 +151,7 @@ static inline const char *teecore_memtype_name(enum teecore_memtypes type) + [MEM_AREA_NSEC_SHM] = "NSEC_SHM", + [MEM_AREA_RAM_NSEC] = "RAM_NSEC", + [MEM_AREA_RAM_SEC] = "RAM_SEC", ++ [MEM_AREA_ROM_SEC] = "ROM_SEC", + [MEM_AREA_IO_NSEC] = "IO_NSEC", + [MEM_AREA_IO_SEC] = "IO_SEC", + [MEM_AREA_EXT_DT] = "EXT_DT", +diff --git a/core/arch/arm/include/sm/pm.h b/core/arch/arm/include/sm/pm.h +index 939f966..90f031a 100644 +--- a/core/arch/arm/include/sm/pm.h ++++ b/core/arch/arm/include/sm/pm.h +@@ -34,7 +34,11 @@ + struct sm_pm_ctx { + uint32_t sp; + paddr_t cpu_resume_addr; ++#ifdef CFG_WITH_LPAE ++ uint32_t suspend_regs[18]; ++#else + uint32_t suspend_regs[16]; ++#endif + }; + + /* suspend/resume core functions */ +diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c +index fced2df..2131d0b 100644 +--- a/core/arch/arm/mm/core_mmu.c ++++ b/core/arch/arm/mm/core_mmu.c +@@ -510,7 +510,6 @@ static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused) + + /* Check special memories comply with registered memories */ + static void verify_special_mem_areas(struct tee_mmap_region *mem_map, +- size_t len, + const struct core_mmu_phys_mem *start, + const struct core_mmu_phys_mem *end, + const char *area_name __maybe_unused) +@@ -518,7 +517,6 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map, + const struct core_mmu_phys_mem *mem; + const struct core_mmu_phys_mem *mem2; + struct tee_mmap_region *mmap; +- size_t n; + + if (start == end) { + DMSG("No %s memory area defined", area_name); +@@ -545,15 +543,16 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map, + * Check memories do not intersect any mapped memory. + * This is called before reserved VA space is loaded in mem_map. + * +- * Only exception is with MEM_AREA_RAM_NSEC and MEM_AREA_NSEC_SHM, ++ * Exceptions are the memory areas that maps with the same attributes ++ * as for example MEM_AREA_RAM_NSEC and MEM_AREA_NSEC_SHM + * which may overlap since they are used for the same purpose + * except that MEM_AREA_NSEC_SHM is always mapped and + * MEM_AREA_RAM_NSEC only uses a dynamic mapping. + */ + for (mem = start; mem < end; mem++) { +- for (mmap = mem_map, n = 0; n < len; mmap++, n++) { +- if (mem->type == MEM_AREA_RAM_NSEC && +- mmap->type == MEM_AREA_NSEC_SHM) ++ for (mmap = mem_map; mmap->type != MEM_AREA_END; mmap++) { ++ if (core_mmu_type_to_attr(mem->type) == ++ core_mmu_type_to_attr(mmap->type)) + continue; + if (core_is_buffer_intersect(mem->addr, mem->size, + mmap->pa, mmap->size)) { +@@ -678,6 +677,8 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t) + case MEM_AREA_RAM_SEC: + case MEM_AREA_SEC_RAM_OVERALL: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; ++ case MEM_AREA_ROM_SEC: ++ return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; + case MEM_AREA_RES_VASPACE: + case MEM_AREA_SHM_VASPACE: + return 0; +@@ -869,13 +870,13 @@ static size_t collect_mem_ranges(struct tee_mmap_region *memory_map, + } + + #ifdef CFG_SECURE_DATA_PATH +- verify_special_mem_areas(memory_map, num_elems, phys_sdp_mem_begin, ++ verify_special_mem_areas(memory_map, phys_sdp_mem_begin, + phys_sdp_mem_end, "SDP"); + + check_sdp_intersection_with_nsec_ddr(); + #endif + +- verify_special_mem_areas(memory_map, num_elems, phys_nsec_ddr_begin, ++ verify_special_mem_areas(memory_map, phys_nsec_ddr_begin, + phys_nsec_ddr_end, "NSEC DDR"); + + add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE, +@@ -1176,6 +1177,7 @@ static void check_mem_map(struct tee_mmap_region *map) + case MEM_AREA_IO_NSEC: + case MEM_AREA_EXT_DT: + case MEM_AREA_RAM_SEC: ++ case MEM_AREA_ROM_SEC: + case MEM_AREA_RAM_NSEC: + case MEM_AREA_RES_VASPACE: + case MEM_AREA_SHM_VASPACE: +diff --git a/core/arch/arm/mm/mobj.c b/core/arch/arm/mm/mobj.c +index 65ab033..d1bbf32 100644 +--- a/core/arch/arm/mm/mobj.c ++++ b/core/arch/arm/mm/mobj.c +@@ -49,6 +49,7 @@ static void *mobj_phys_get_va(struct mobj *mobj, size_t offset) + + return (void *)(moph->va + offset); + } ++DECLARE_KEEP_PAGER(mobj_phys_get_va); + + static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +@@ -228,7 +229,7 @@ static void *mobj_mm_get_va(struct mobj *mobj, size_t offs) + return mobj_get_va(to_mobj_mm(mobj)->parent_mobj, + mobj_mm_offs(mobj, offs)); + } +- ++DECLARE_KEEP_PAGER(mobj_mm_get_va); + + static TEE_Result mobj_mm_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +@@ -657,4 +658,4 @@ static TEE_Result mobj_init(void) + return TEE_SUCCESS; + } + +-driver_init_late(mobj_init); ++service_init(mobj_init); +diff --git a/core/arch/arm/plat-stm32mp1/boot_api.h b/core/arch/arm/plat-stm32mp1/boot_api.h +index 62e38b5..a7daffd 100644 +--- a/core/arch/arm/plat-stm32mp1/boot_api.h ++++ b/core/arch/arm/plat-stm32mp1/boot_api.h +@@ -14,7 +14,9 @@ + #define BCKR_CORE1_MAGIC_NUMBER 4 + + /* Value for BCKR_CORE1_MAGIC_NUMBER entry */ ++#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xca7face0 + #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xca7face1 ++#define BOOT_API_A7_RESET_MAGIC_NUMBER 0xca7dead0 + + /* Backup register #5: physical address of core1 entry at boot up */ + #define BCKR_CORE1_BRANCH_ADDRESS 5 +diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk +index e82d2b9..8a449b5 100644 +--- a/core/arch/arm/plat-stm32mp1/conf.mk ++++ b/core/arch/arm/plat-stm32mp1/conf.mk +@@ -1,22 +1,41 @@ + # 1GB and 512MB DDR targets do not locate secure DDR at the same place. + flavor_dts_file-157A_DK1 = stm32mp157a-dk1.dts ++flavor_dts_file-157A_ED1 = stm32mp157a-ed1.dts ++flavor_dts_file-157A_EV1 = stm32mp157a-ev1.dts + flavor_dts_file-157C_DK2 = stm32mp157c-dk2.dts + flavor_dts_file-157C_ED1 = stm32mp157c-ed1.dts + flavor_dts_file-157C_EV1 = stm32mp157c-ev1.dts ++flavor_dts_file-157D_DK1 = stm32mp157d-dk1.dts ++flavor_dts_file-157D_ED1 = stm32mp157d-ed1.dts ++flavor_dts_file-157D_EV1 = stm32mp157d-ev1.dts ++flavor_dts_file-157F_DK2 = stm32mp157f-dk2.dts ++flavor_dts_file-157F_ED1 = stm32mp157f-ed1.dts ++flavor_dts_file-157F_EV1 = stm32mp157f-ev1.dts + +-flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) ++flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) \ ++ $(flavor_dts_file-157F_DK2) + +-flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) ++flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) \ ++ $(flavor_dts_file-157D_DK1) + + flavorlist-cryp-1G = $(flavor_dts_file-157C_ED1) \ +- $(flavor_dts_file-157C_EV1) ++ $(flavor_dts_file-157C_EV1) \ ++ $(flavor_dts_file-157F_ED1) \ ++ $(flavor_dts_file-157F_EV1) + +-flavorlist-no_cryp = $(flavorlist-no_cryp-512M) ++flavorlist-no_cryp-1G = $(flavor_dts_file-157A_ED1) \ ++ $(flavor_dts_file-157A_EV1) \ ++ $(flavor_dts_file-157D_ED1) \ ++ $(flavor_dts_file-157D_EV1) ++ ++flavorlist-no_cryp = $(flavorlist-no_cryp-512M) \ ++ $(flavorlist-no_cryp-1G) + + flavorlist-512M = $(flavorlist-cryp-512M) \ + $(flavorlist-no_cryp-512M) + +-flavorlist-1G = $(flavorlist-cryp-1G) ++flavorlist-1G = $(flavorlist-cryp-1G) \ ++ $(flavorlist-no_cryp-1G) + + ifneq ($(PLATFORM_FLAVOR),) + ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) +@@ -31,10 +50,13 @@ endif + + include core/arch/arm/cpu/cortex-a7.mk + ++$(call force,CFG_ARM_GIC_PM,y) + $(call force,CFG_BOOT_SECONDARY_REQUEST,y) + $(call force,CFG_GENERIC_BOOT,y) + $(call force,CFG_GIC,y) + $(call force,CFG_INIT_CNTVOFF,y) ++$(call force,CFG_PM,y) ++$(call force,CFG_PM_ARM32,y) + $(call force,CFG_PM_STUBS,y) + $(call force,CFG_PSCI_ARM32,y) + $(call force,CFG_SCMI_MSG_DRIVERS,y) +@@ -67,24 +89,36 @@ CFG_TEE_CORE_NB_CORE ?= 2 + CFG_WITH_PAGER ?= y + CFG_WITH_LPAE ?= y + CFG_WITH_STACK_CANARIES ?= y +-CFG_MMAP_REGIONS ?= 23 ++CFG_MMAP_REGIONS ?= 25 ++CFG_CORE_HEAP_SIZE ?= 49152 + + ifeq ($(CFG_EMBED_DTB_SOURCE_FILE),) + # Some drivers mandate DT support ++$(call force,CFG_STM32_CLKCALIB,n) + $(call force,CFG_STM32_I2C,n) ++$(call force,CFG_STM32_IWDG,n) ++$(call force,CFG_STM32_TIM,n) + $(call force,CFG_STPMIC1,n) + endif + + CFG_STM32_BSEC ?= y ++CFG_STM32_CLKCALIB ?= y ++CFG_STM32_CRYP ?= y + CFG_STM32_ETZPC ?= y + CFG_STM32_GPIO ?= y + CFG_STM32_I2C ?= y ++CFG_STM32_IWDG ?= y + CFG_STM32_RNG ?= y +-CFG_STM32_RNG ?= y ++CFG_STM32_RTC ?= y ++CFG_STM32_TIM ?= y + CFG_STM32_UART ?= y + CFG_STPMIC1 ?= y + CFG_TZC400 ?= y + ++ifeq ($(CFG_STM32_CLKCALIB),y) ++$(call force,CFG_STM32_TIM,y) ++endif ++ + ifeq ($(CFG_STPMIC1),y) + $(call force,CFG_STM32_I2C,y) + $(call force,CFG_STM32_GPIO,y) +@@ -95,12 +129,23 @@ CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION ?= y + + # SiP/OEM service for non-secure world + CFG_STM32_BSEC_SIP ?= y ++CFG_STM32_CLKCALIB_SIP ?= y ++CFG_STM32_LOWPOWER_SIP ?= $(CFG_PM) ++CFG_STM32_PWR_SIP ?= y ++CFG_STM32_RCC_SIP ?= y ++ ++# Default use stm32mp1 PM mailbox context version 2 ++# Use CFG_STM32MP15_PM_CONTEX_VERSION=1 to force version 0 when dealing with ++# a TF-A firmware that supports version 1 of the context mailbox. ++CFG_STM32MP15_PM_CONTEX_VERSION ?= 2 + + # Default enable some test facitilites + CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y + CFG_WITH_STATS ?= y ++CFG_WERROR ?= y + + # Default disable some support for pager memory size constraint ++CFG_TEE_CORE_LOG_LEVEL ?= 2 + CFG_TEE_CORE_DEBUG ?= n + CFG_UNWIND ?= n + CFG_LOCKDEP ?= n +diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c +new file mode 100644 +index 0000000..b1b9f43 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c +@@ -0,0 +1,501 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2018, STMicroelectronics ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CALIBRATION_TIMEOUT_US 10000 ++ ++/* List of forbiden values for HSI and CSI */ ++static const uint16_t fbv_hsi[] = { ++ 512, 480, 448, 416, 384, 352, 320, 288, ++ 256, 224, 192, 160, 128, 96, 64, 32, 0, ++}; ++static const uint16_t fbv_csi[] = { ++ 256, 240, 224, 208, 192, 176, 160, 144, ++ 128, 112, 96, 80, 64, 48, 32, 16, 0, ++}; ++ ++struct stm32mp1_trim_boundary_t { ++ unsigned int max; /* Max boundary trim value around forbidden value */ ++ unsigned int min; /* Min boundary trim value around forbidden value */ ++}; ++ ++struct stm32mp1_clk_cal { ++ const 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]; ++}; ++ ++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 *hsi_calib; ++static struct stm32mp1_clk_cal *csi_calib; ++ ++static const struct stm32mp1_clk_cal hsi_calib_config = { ++ .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 const struct stm32mp1_clk_cal csi_calib_config = { ++ .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 int get_signed_value(uint8_t val) ++{ ++ return (int8_t)(val << 1) / 2; ++} ++ ++static void hsi_set_trim(unsigned int cal) ++{ ++ int clk_trim = (int)cal - (int)hsi_calib->cal_ref; ++ uint32_t trim = ((uint32_t)clk_trim << RCC_HSICFGR_HSITRIM_SHIFT) & ++ RCC_HSICFGR_HSITRIM_MASK; ++ ++ io_clrsetbits32(stm32_rcc_base() + RCC_HSICFGR, ++ RCC_HSICFGR_HSITRIM_MASK, trim); ++} ++DECLARE_KEEP_PAGER(hsi_set_trim); ++ ++static unsigned int hsi_get_trimed_cal(void) ++{ ++ uint32_t utrim = (io_read32(stm32_rcc_base() + RCC_HSICFGR) & ++ RCC_HSICFGR_HSITRIM_MASK) >> ++ RCC_HSICFGR_HSITRIM_SHIFT; ++ int trim = get_signed_value((uint8_t)utrim); ++ ++ if (trim + (int)hsi_calib->cal_ref < 0) ++ return 0; ++ ++ return hsi_calib->cal_ref + trim; ++} ++DECLARE_KEEP_PAGER(hsi_get_trimed_cal); ++ ++static void csi_set_trim(unsigned int cal) ++{ ++ int clk_trim = (int)cal - (int)csi_calib->cal_ref + ++ csi_calib->trim_max + 1; ++ uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) & ++ RCC_CSICFGR_CSITRIM_MASK; ++ ++ io_clrsetbits32(stm32_rcc_base() + RCC_CSICFGR, ++ RCC_CSICFGR_CSITRIM_MASK, trim); ++} ++DECLARE_KEEP_PAGER(csi_set_trim); ++ ++static unsigned int csi_get_trimed_cal(void) ++{ ++ uint32_t trim = (io_read32(stm32_rcc_base() + RCC_CSICFGR) & ++ RCC_CSICFGR_CSITRIM_MASK) >> ++ RCC_CSICFGR_CSITRIM_SHIFT; ++ ++ return (int)trim - csi_calib->trim_max + (int)csi_calib->cal_ref - 1; ++} ++DECLARE_KEEP_PAGER(csi_get_trimed_cal); ++ ++static unsigned int trim_increase(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int cal) ++{ ++ struct stm32mp1_trim_boundary_t *boundary = NULL; ++ unsigned int new_cal = 0; ++ int i = 0; ++ ++ /* 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->min) { ++ new_cal = boundary->min; ++ break; ++ } ++ ++ if ((cal >= boundary->min) && (cal < boundary->max)) { ++ 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 = NULL; ++ unsigned int new_cal = 0; ++ unsigned int i = 0; ++ ++ /* 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->max) { ++ new_cal = boundary->max; ++ break; ++ } ++ ++ if ((cal > boundary->min) && (cal <= boundary->max)) { ++ new_cal = cal - 1; ++ break; ++ } ++ } ++ ++ return new_cal; ++} ++ ++static void rcc_calibration(struct stm32mp1_clk_cal *clk_cal) ++{ ++ unsigned long margin = (clk_cal->ref_freq * ++ clk_cal->freq_margin) / 1000; ++ unsigned long min = clk_cal->ref_freq - margin; ++ unsigned long max = clk_cal->ref_freq + margin; ++ unsigned long freq = clk_cal->get_freq(); ++ int trim = 0; ++ int new_trim = 0; ++ unsigned long conv = 0; ++ unsigned long min_conv = ULONG_MAX; ++ uint64_t timeout_ref = 0; ++ ++ if ((freq >= min) && (freq <= max)) ++ return; ++ ++ trim = clk_cal->get_trim(); ++ timeout_ref = timeout_init_us(CALIBRATION_TIMEOUT_US); ++ 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 == 0) { ++ /* 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(timeout_ref)) ++ break; ++ ++ } while (conv == min_conv); ++ ++ clk_cal->set_trim(trim); ++ freq = clk_cal->get_freq(); ++ if ((freq < min) || (freq > max)) { ++ EMSG("%s Calibration : Freq %lu , trim %i\n", ++ (clk_cal->set_trim == hsi_set_trim) ? "HSI" : "CSI", ++ freq, trim); ++ } ++} ++ ++static void save_trim(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int i, unsigned int max, unsigned int min) ++{ ++ clk_cal->boundary[i].max = max; ++ clk_cal->boundary[i].min = min; ++} ++ ++static int trim_find_prev_boundary(struct stm32mp1_clk_cal *clk_cal, ++ unsigned int x1) ++{ ++ unsigned int x = x1; ++ unsigned long freq = 0; ++ ++ 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) ++{ ++ const uint16_t *trim_fbv = clk_cal->fbv; ++ unsigned int min = 0; ++ unsigned int max = 0; ++ 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 = 0; ++ 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; ++} ++ ++/* Timer countdown/delay argument for the target calibration periodicity */ ++static uint32_t timer_val; ++ ++#define CNTP_CTL_ENABLE BIT(0) ++#define CNTP_CTL_IMASK BIT(1) ++#define CNTP_CTL_ISTATUS BIT(2) ++ ++static void arm_timer(void) ++{ ++ if (!timer_val) ++ return; ++ ++ write_cntp_ctl(read_cntp_ctl() & ~(CNTP_CTL_ENABLE | CNTP_CTL_IMASK)); ++ write_cntp_tval(timer_val); ++ write_cntp_ctl(read_cntp_ctl() | CNTP_CTL_ENABLE); ++} ++ ++static void arm_timer_with_period(uint32_t period_sec) ++{ ++ timer_val = period_sec * read_cntfrq(); ++ ++ arm_timer(); ++} ++ ++static void calib_period(void) ++{ ++ (void)stm32mp_start_clock_calib(CK_HSI); ++ (void)stm32mp_start_clock_calib(CK_CSI); ++ ++ arm_timer(); ++} ++ ++static enum itr_return arm_cntp_it_handler(struct itr_handler *handler __unused) ++{ ++ if (timer_val) ++ calib_period(); ++ ++ return ITRR_HANDLED; ++} ++static struct itr_handler arm_cntp_handler = { ++ .it = GIC_SPI_SEC_PHY_TIMER, ++ .handler = arm_cntp_it_handler, ++}; ++DECLARE_KEEP_PAGER(arm_cntp_handler); ++ ++static TEE_Result timer_pm(enum pm_op op, uint32_t pm_hint __unused, ++ const struct pm_callback_handle *handle __unused) ++{ ++ if (op == PM_OP_RESUME && timer_val) ++ calib_period(); ++ ++ return TEE_SUCCESS; ++} ++DECLARE_KEEP_PAGER(timer_pm); ++ ++static TEE_Result init_arm_cntp_timer(void) ++{ ++ itr_add(&arm_cntp_handler); ++ itr_enable(arm_cntp_handler.it); ++ ++ register_pm_driver_cb(timer_pm, NULL); ++ ++ return TEE_SUCCESS; ++} ++driver_init(init_arm_cntp_timer); ++ ++static void init_periodic_calibration(void *fdt, int node) ++{ ++ uint32_t period = 0; ++ int lenp = 0; ++ const fdt32_t *cuint = fdt_getprop(fdt, node, "st,cal-sec", &lenp); ++ ++ if (cuint) ++ period = fdt32_to_cpu(*cuint); ++ ++ DMSG("Calib period %us", period); ++ arm_timer_with_period(period); ++} ++ ++int stm32mp_start_clock_calib(unsigned int clock_id) ++{ ++ struct stm32mp1_clk_cal *clk_calib = NULL; ++ ++ switch (clock_id) { ++ case CK_HSI: ++ clk_calib = hsi_calib; ++ break; ++ case CK_CSI: ++ clk_calib = csi_calib; ++ break; ++ default: ++ DMSG("Cannot calibrate clock %u", clock_id); ++ return 1; ++ } ++ ++ if (clk_calib->ref_freq == 0U) ++ return 1; ++ ++ DMSG("%s", clock_id == CK_HSI ? "HSI" : "CSI"); ++ rcc_calibration(clk_calib); ++ ++ return 0; ++} ++ ++static int init_hsi_calibration(void *fdt, int node) ++{ ++ if (!fdt_getprop(fdt, node, "st,hsi-cal", NULL)) ++ return 0; ++ ++ hsi_calib = calloc(1, sizeof(*hsi_calib)); ++ assert(hsi_calib); ++ memcpy(hsi_calib, &hsi_calib_config, sizeof(*hsi_calib)); ++ ++ stm32_tim_freq_func(&hsi_calib->get_freq, HSI_CAL); ++ if (hsi_calib->get_freq == NULL) { ++ free(hsi_calib); ++ return -1; ++ } ++ ++ hsi_calib->ref_freq = stm32_clock_get_rate(CK_HSI); ++ ++ hsi_calib->cal_ref = (io_read32(stm32_rcc_base() + RCC_HSICFGR) & ++ RCC_HSICFGR_HSICAL_MASK) >> ++ RCC_HSICFGR_HSICAL_SHIFT; ++ ++ trim_table_init(hsi_calib); ++ hsi_calib->set_trim(hsi_calib->cal_ref); ++ stm32mp_start_clock_calib(CK_HSI); ++ return 1; ++} ++ ++static int init_csi_calibration(void *fdt, int node) ++{ ++ if (!fdt_getprop(fdt, node, "st,csi-cal", NULL)) ++ return 0; ++ ++ csi_calib = calloc(1, sizeof(*csi_calib)); ++ assert(csi_calib); ++ memcpy(csi_calib, &csi_calib_config, sizeof(*csi_calib)); ++ ++ stm32_tim_freq_func(&csi_calib->get_freq, CSI_CAL); ++ if (csi_calib->get_freq == NULL) { ++ free(csi_calib); ++ return -1; ++ } ++ ++ csi_calib->ref_freq = stm32_clock_get_rate(CK_CSI); ++ ++ csi_calib->cal_ref = (io_read32(stm32_rcc_base() + RCC_CSICFGR) & ++ RCC_CSICFGR_CSICAL_MASK) >> ++ RCC_CSICFGR_CSICAL_SHIFT; ++ trim_table_init(csi_calib); ++ csi_calib->set_trim(csi_calib->cal_ref); ++ stm32mp_start_clock_calib(CK_CSI); ++ return 1; ++} ++ ++static TEE_Result init_stm32mp1_calib(void) ++{ ++ void *fdt = NULL; ++ int rcc_node = 0; ++ int res_csi = 0; ++ int res_hsi = 0; ++ ++ fdt = get_embedded_dt(); ++ if (!fdt) ++ panic(); ++ ++ rcc_node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); ++ if (rcc_node < 0) ++ panic(); ++ ++ res_hsi = init_hsi_calibration(fdt, rcc_node); ++ if (res_hsi < 0) ++ panic("HSI calibration init failed"); ++ res_csi = init_csi_calibration(fdt, rcc_node); ++ if (res_csi < 0) ++ panic("CSI calibration init failed"); ++ if (res_csi || res_hsi) ++ init_periodic_calibration(fdt, rcc_node); ++ ++ return TEE_SUCCESS; ++} ++driver_init(init_stm32mp1_calib); +diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c +index 47240ab..7912948 100644 +--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c ++++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c +@@ -6,20 +6,41 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + #include + #include + ++#define DT_OPP_COMPAT "operating-points-v2" ++ ++/* 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 ++ ++#define PLL1_SETTINGS_VALID_ID 0x504C4C31 /* "PLL1" */ ++ + /* Identifiers for root oscillators */ + enum stm32mp_osc_id { + _HSI = 0, +@@ -85,11 +106,14 @@ enum stm32mp1_parent_sel { + _UART24_SEL, + _UART35_SEL, + _UART78_SEL, ++ _SDMMC12_SEL, ++ _SDMMC3_SEL, + _AXISS_SEL, + _MCUSS_SEL, + _USBPHY_SEL, + _USBO_SEL, + _RTC_SEL, ++ _MPU_SEL, + _PARENT_SEL_NB, + _UNKNOWN_SEL = 0xff, + }; +@@ -160,6 +184,16 @@ enum stm32mp1_div_id { + _DIV_NB, + }; + ++enum stm32mp1_pllcfg { ++ PLLCFG_M, ++ PLLCFG_N, ++ PLLCFG_P, ++ PLLCFG_Q, ++ PLLCFG_R, ++ PLLCFG_O, ++ PLLCFG_NB ++}; ++ + enum stm32mp1_plltype { + PLL_800, + PLL_1600, +@@ -212,6 +246,21 @@ struct stm32mp1_clk_pll { + enum stm32mp_osc_id refclk[REFCLK_SIZE]; + }; + ++struct stm32mp1_pll { ++ uint8_t refclk_min; ++ uint8_t refclk_max; ++ uint8_t divn_max; ++}; ++ ++/* 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]; ++}; ++ + #define N_S 0 /* Non-secure can access RCC interface */ + #define SEC 1 /* RCC[TZEN] protects RCC interface */ + +@@ -380,6 +429,18 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _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), ++#ifdef STM32MP1_USE_MPU0_RESET ++ _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 0, LTDC_PX, _UNKNOWN_SEL), ++ _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), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 5, GPU, _UNKNOWN_SEL), ++ _CLK_SC_FIXED(N_S, RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK), ++ _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), ++ _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), ++#endif + + _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), + }; +@@ -406,6 +467,10 @@ static const uint8_t rng1_parents[] = { + _CSI, _PLL4_R, _LSE, _LSI + }; + ++static const uint8_t mpu_parents[] = { ++ _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ ++}; ++ + /* Parents for (some) non-secure clocks */ + #ifdef CFG_WITH_NSEC_UARTS + static const uint8_t uart6_parents[] = { +@@ -429,6 +494,24 @@ static const uint8_t rtc_parents[] = { + _UNKNOWN_ID, _LSE, _LSI, _HSE + }; + ++#ifdef STM32MP1_USE_MPU0_RESET ++static const uint8_t usbphy_parents[] = { ++ _HSE_KER, _PLL4_R, _HSE_KER_DIV2 ++}; ++ ++static const uint8_t usbo_parents[] = { ++ _PLL4_R, _USB_PHY_48 ++}; ++ ++static const uint8_t sdmmc12_parents[] = { ++ _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER ++}; ++ ++static const uint8_t sdmmc3_parents[] = { ++ _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER ++}; ++#endif ++ + static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + /* Secure aware clocks */ + _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), +@@ -437,6 +520,9 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), + _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), + _CLK_PARENT(_RTC_SEL, RCC_BDCR, 0, 0x3, rtc_parents), ++ _CLK_PARENT(_MPU_SEL, RCC_MPCKSELR, 0, 0x3, mpu_parents), ++ _CLK_PARENT(_AXISS_SEL, RCC_ASSCKSELR, 0, 0x3, axiss_parents), ++ _CLK_PARENT(_MCUSS_SEL, RCC_MSSCKSELR, 0, 0x3, mcuss_parents), + /* Always non-secure clocks (maybe used in some way in secure world) */ + #ifdef CFG_WITH_NSEC_UARTS + _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), +@@ -444,8 +530,26 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), + _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), + #endif +- _CLK_PARENT(_AXISS_SEL, RCC_ASSCKSELR, 0, 0x3, axiss_parents), +- _CLK_PARENT(_MCUSS_SEL, RCC_MSSCKSELR, 0, 0x3, mcuss_parents), ++#ifdef STM32MP1_USE_MPU0_RESET ++ _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents), ++ _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents), ++ _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), ++ _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), ++#endif ++}; ++ ++/* Define characteristics of PLL according type */ ++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, ++ }, + }; + + /* PLLNCFGR2 register divider by output */ +@@ -549,6 +653,10 @@ static unsigned long osc_frequency(enum stm32mp_osc_id idx) + static unsigned int gate_refcounts[NB_GATES]; + static unsigned int refcount_lock; + ++/* Storage of the precomputed SoC settings for PLL1 various OPPs */ ++static struct stm32mp1_pll_settings pll1_settings; ++static uint32_t current_opp_khz; ++ + static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) + { + return &stm32mp1_clk_gate[idx]; +@@ -701,6 +809,152 @@ static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, + return dfout; + } + ++static void pll_start(enum stm32mp1_pll_id pll_id) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uint32_t pllxcr = stm32_rcc_base() + pll->pllxcr; ++ ++ if (io_read32(pllxcr) & RCC_PLLNCR_PLLON) ++ return; ++ ++ io_clrsetbits32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | ++ RCC_PLLNCR_DIVREN, RCC_PLLNCR_PLLON); ++} ++ ++#define PLLRDY_TIMEOUT_US (200 * 1000) ++ ++static int pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uint32_t pllxcr = stm32_rcc_base() + pll->pllxcr; ++ uint64_t start = 0; ++ ++ start = timeout_init_us(PLLRDY_TIMEOUT_US); ++ /* Wait PLL lock */ ++ while (!(io_read32(pllxcr) & RCC_PLLNCR_PLLRDY)) ++ if (timeout_elapsed(start)) { ++ EMSG("PLL%d start failed @ 0x%"PRIx32": 0x%"PRIx32, ++ pll_id, pllxcr, io_read32(pllxcr)); ++ return -1; ++ } ++ ++ /* Start the requested output */ ++ io_setbits32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); ++ ++ return 0; ++} ++ ++static int pll_stop(enum stm32mp1_pll_id pll_id) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uint32_t pllxcr = stm32_rcc_base() + pll->pllxcr; ++ uint64_t start = 0; ++ ++ /* Stop all output */ ++ io_clrbits32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | ++ RCC_PLLNCR_DIVREN); ++ ++ /* Stop PLL */ ++ io_clrbits32(pllxcr, RCC_PLLNCR_PLLON); ++ ++ start = timeout_init_us(PLLRDY_TIMEOUT_US); ++ /* Wait PLL stopped */ ++ while (!(io_read32(pllxcr) & RCC_PLLNCR_PLLRDY)) ++ if (timeout_elapsed(start)) { ++ EMSG("PLL%d stop failed @ 0x%"PRIx32": 0x%"PRIx32, ++ pll_id, pllxcr, io_read32(pllxcr)); ++ ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static uint32_t pll_compute_pllxcfgr2(uint32_t *pllcfg) ++{ ++ uint32_t value = 0; ++ ++ value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & ++ RCC_PLLNCFGR2_DIVP_MASK; ++ value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & ++ RCC_PLLNCFGR2_DIVQ_MASK; ++ value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & ++ RCC_PLLNCFGR2_DIVR_MASK; ++ ++ return value; ++} ++ ++static void 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 = stm32_rcc_base(); ++ uint32_t value = 0; ++ ++ value = pll_compute_pllxcfgr2(pllcfg); ++ ++ io_write32(rcc_base + pll->pllxcfgr2, value); ++} ++ ++static int pll_compute_pllxcfgr1(const struct stm32mp1_clk_pll *pll, ++ uint32_t *pllcfg, uint32_t *cfgr1) ++{ ++ uint32_t rcc_base = stm32_rcc_base(); ++ enum stm32mp1_plltype type = pll->plltype; ++ unsigned long refclk = 0; ++ uint32_t ifrge = 0; ++ uint32_t src = 0; ++ ++ src = io_read32(rcc_base + pll->rckxselr) & ++ RCC_SELR_REFCLK_SRC_MASK; ++ ++ refclk = osc_frequency(pll->refclk[src]) / ++ (pllcfg[PLLCFG_M] + 1U); ++ ++ if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || ++ (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) ++ return -1; ++ ++ if ((type == PLL_800) && (refclk >= 8000000U)) ++ ifrge = 1U; ++ ++ *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 pll_config(enum stm32mp1_pll_id pll_id, uint32_t *pllcfg, ++ uint32_t fracv) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); ++ uint32_t rcc_base = stm32_rcc_base(); ++ uint32_t value = 0; ++ int ret = 0; ++ ++ ret = pll_compute_pllxcfgr1(pll, pllcfg, &value); ++ if (ret) ++ return ret; ++ ++ io_write32(rcc_base + pll->pllxcfgr1, value); ++ ++ /* Fractional configuration */ ++ io_write32(rcc_base + pll->pllxfracr, value); ++ ++ /* Frac must be enabled only once its configuration is loaded */ ++ value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; ++ io_write32(rcc_base + pll->pllxfracr, value); ++ value = io_read32(rcc_base + pll->pllxfracr); ++ io_write32(rcc_base + pll->pllxfracr, value | RCC_PLLNFRACR_FRACLE); ++ ++ pll_config_output(pll_id, pllcfg); ++ ++ return 0; ++} ++ + static unsigned long get_clock_rate(int p) + { + uint32_t reg = 0; +@@ -1214,7 +1468,7 @@ void stm32mp_register_clock_parents_secure(unsigned long clock_id) + + if (parent_id < 0) { + DMSG("No parent for clock %lu", clock_id); +- panic(); ++ return; + } + + secure_parent_clocks(parent_id); +@@ -1299,7 +1553,7 @@ static void enable_static_secure_clocks(void) + stm32_clock_enable(RTCAPB); + } + +-static TEE_Result stm32mp1_clk_early_init(void) ++static void stm32mp1_clk_early_init(void) + { + void *fdt = NULL; + int node = 0; +@@ -1360,11 +1614,1011 @@ static TEE_Result stm32mp1_clk_early_init(void) + + if (ignored != 0) + IMSG("DT clock tree configurations were ignored"); ++} + +- enable_static_secure_clocks(); ++/* ++ * Gets OPP parameters (frequency in KHz and voltage in mV) from an OPP table ++ * subnode. Platform HW support capabilities are also checked. ++ */ ++static int get_opp_freqvolt_from_dt_subnode(void *fdt, int subnode, ++ uint32_t *freq_khz, ++ uint32_t *voltage_mv) ++{ ++ const fdt64_t *cuint64 = NULL; ++ const fdt32_t *cuint32 = NULL; ++ uint64_t read_freq_64 = 0; ++ uint32_t read_voltage_32 = 0; ++ ++ assert(freq_khz); ++ assert(voltage_mv); ++ ++ cuint32 = fdt_getprop(fdt, subnode, "opp-supported-hw", NULL); ++ if (cuint32) ++ if (!stm32mp_supports_cpu_opp(fdt32_to_cpu(*cuint32))) { ++ DMSG("Invalid opp-supported-hw 0x%"PRIx32, ++ fdt32_to_cpu(*cuint32)); ++ return -FDT_ERR_BADVALUE; ++ } + +- return TEE_SUCCESS; ++ cuint64 = fdt_getprop(fdt, subnode, "opp-hz", NULL); ++ if (!cuint64) { ++ DMSG("Missing opp-hz"); ++ 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) { ++ DMSG("Invalid opp-hz %"PRIu64, read_freq_64); ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ cuint32 = fdt_getprop(fdt, subnode, "opp-microvolt", NULL); ++ if (!cuint32) { ++ DMSG("Missing opp-microvolt"); ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ /* Millivolt value must fit on 16 bits */ ++ read_voltage_32 = fdt32_to_cpu(*cuint32) / 1000U; ++ if (read_voltage_32 > UINT16_MAX) { ++ DMSG("Invalid opp-microvolt %"PRIu32, read_voltage_32); ++ return -FDT_ERR_BADVALUE; ++ } ++ ++ *freq_khz = (uint32_t)read_freq_64; ++ ++ *voltage_mv = read_voltage_32; ++ ++ return 0; ++} ++ ++/* ++ * 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 @pll1_settings structure. ++ * 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. ++ */ ++static int get_all_opp_freqvolt_from_dt(uint32_t *count) ++{ ++ void *fdt = NULL; ++ int node = 0; ++ int subnode = 0; ++ uint32_t idx = 0; ++ ++ assert(count); ++ ++ fdt = get_embedded_dt(); ++ node = fdt_node_offset_by_compatible(fdt, -1, DT_OPP_COMPAT); ++ if (node < 0) ++ return node; ++ ++ fdt_for_each_subnode(subnode, fdt, node) { ++ uint32_t read_freq = 0; ++ uint32_t read_voltage = 0; ++ ++ if (get_opp_freqvolt_from_dt_subnode(fdt, subnode, &read_freq, ++ &read_voltage)) ++ continue; ++ ++ if (idx >= *count) ++ return -FDT_ERR_NOSPACE; ++ ++ pll1_settings.freq[idx] = read_freq; ++ pll1_settings.volt[idx] = read_voltage; ++ idx++; ++ } ++ ++ if (!idx) ++ return -FDT_ERR_NOTFOUND; ++ ++ *count = idx; ++ ++ return 0; ++} ++ ++static int clk_compute_pll1_settings(unsigned long input_freq, int idx) ++{ ++ unsigned long post_divm = 0; ++ unsigned long long output_freq = pll1_settings.freq[idx] * 1000U; ++ unsigned long long freq = 0; ++ unsigned long long vco = 0; ++ int divm = 0; ++ int divn = 0; ++ int divp = 0; ++ int frac = 0; ++ int i = 0; ++ unsigned int diff = 0; ++ unsigned int best_diff = UINT_MAX; ++ ++ /* Following parameters have always the same value */ ++ pll1_settings.cfg[idx][PLLCFG_Q] = 0; ++ pll1_settings.cfg[idx][PLLCFG_R] = 0; ++ pll1_settings.cfg[idx][PLLCFG_O] = PQR(1, 0, 0); ++ ++ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) { ++ post_divm = input_freq / (unsigned long)(divm + 1); ++ ++ if ((post_divm < POST_DIVM_MIN) || ++ (post_divm > POST_DIVM_MAX)) ++ continue; ++ ++ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { ++ ++ freq = output_freq * (divm + 1) * (divp + 1); ++ ++ divn = (int)((freq / input_freq) - 1); ++ if ((divn < DIVN_MIN) || (divn > DIVN_MAX)) ++ continue; ++ ++ frac = (int)(((freq * FRAC_MAX) / input_freq) - ++ ((divn + 1) * FRAC_MAX)); ++ ++ /* 2 loops to refine the fractional part */ ++ for (i = 2; i != 0; i--) { ++ if (frac > FRAC_MAX) ++ break; ++ ++ vco = (post_divm * (divn + 1)) + ++ ((post_divm * (unsigned long long)frac) / ++ FRAC_MAX); ++ ++ if ((vco < (VCO_MIN / 2)) || ++ (vco > (VCO_MAX / 2))) { ++ frac++; ++ continue; ++ } ++ ++ freq = vco / (divp + 1); ++ if (output_freq < freq) ++ diff = (unsigned int)(freq - ++ output_freq); ++ else ++ diff = (unsigned int)(output_freq - ++ freq); ++ ++ if (diff < best_diff) { ++ pll1_settings.cfg[idx][PLLCFG_M] = divm; ++ pll1_settings.cfg[idx][PLLCFG_N] = divn; ++ pll1_settings.cfg[idx][PLLCFG_P] = divp; ++ pll1_settings.frac[idx] = frac; ++ ++ if (!diff) ++ return 0; ++ ++ best_diff = diff; ++ } ++ ++ frac++; ++ } ++ } ++ } ++ ++ if (best_diff == UINT_MAX) { ++ pll1_settings.cfg[idx][PLLCFG_O] = 0; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int clk_get_pll1_settings(uint32_t clksrc, int index) ++{ ++ unsigned long input_freq = 0; ++ unsigned int i = 0; ++ ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) ++ if (pll1_settings.freq[i] == pll1_settings.freq[index]) ++ break; ++ ++ if (((i == PLAT_MAX_OPP_NB) && ++ !stm32mp1_clk_pll1_settings_are_valid()) || ++ ((i < PLAT_MAX_OPP_NB) && !pll1_settings.cfg[i][PLLCFG_O])) { ++ /* ++ * Either PLL1 settings structure is completely empty, ++ * or these settings are not yet computed: do it. ++ */ ++ switch (clksrc) { ++ case CLK_PLL12_HSI: ++ input_freq = stm32_clock_get_rate(CK_HSI); ++ break; ++ case CLK_PLL12_HSE: ++ input_freq = stm32_clock_get_rate(CK_HSE); ++ break; ++ default: ++ panic(); ++ } ++ ++ return clk_compute_pll1_settings(input_freq, index); ++ } ++ ++ if (i < PLAT_MAX_OPP_NB) { ++ if (pll1_settings.cfg[i][PLLCFG_O]) ++ return 0; ++ ++ /* ++ * Index is in range and PLL1 settings are computed: ++ * use content to answer to the request. ++ */ ++ memcpy(&pll1_settings.cfg[index][0], &pll1_settings.cfg[i][0], ++ sizeof(uint32_t) * PLAT_MAX_PLLCFG_NB); ++ pll1_settings.frac[index] = pll1_settings.frac[i]; ++ ++ return 0; ++ } ++ ++ return -1; ++} ++ ++static int clk_save_current_pll1_settings(uint32_t buck1_voltage) ++{ ++ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); ++ uint32_t rcc_base = stm32_rcc_base(); ++ uint32_t freq = 0; ++ unsigned int i = 0; ++ ++ freq = UDIV_ROUND_NEAREST(stm32_clock_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)) ++ return -1; ++ ++ pll1_settings.cfg[i][PLLCFG_M] = (io_read32(rcc_base + pll->pllxcfgr1) & ++ RCC_PLLNCFGR1_DIVM_MASK) >> ++ RCC_PLLNCFGR1_DIVM_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_N] = (io_read32(rcc_base + pll->pllxcfgr1) & ++ RCC_PLLNCFGR1_DIVN_MASK) >> ++ RCC_PLLNCFGR1_DIVN_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_P] = (io_read32(rcc_base + pll->pllxcfgr2) & ++ RCC_PLLNCFGR2_DIVP_MASK) >> ++ RCC_PLLNCFGR2_DIVP_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_Q] = (io_read32(rcc_base + pll->pllxcfgr2) & ++ RCC_PLLNCFGR2_DIVQ_MASK) >> ++ RCC_PLLNCFGR2_DIVQ_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_R] = (io_read32(rcc_base + pll->pllxcfgr2) & ++ RCC_PLLNCFGR2_DIVR_MASK) >> ++ RCC_PLLNCFGR2_DIVR_SHIFT; ++ ++ pll1_settings.cfg[i][PLLCFG_O] = io_read32(rcc_base + pll->pllxcr) >> ++ RCC_PLLNCR_DIVEN_SHIFT; ++ ++ pll1_settings.frac[i] = (io_read32(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 = 0; ++ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); ++ uint32_t rcc_base = stm32_rcc_base(); ++ ++ value = io_read32(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) ++{ ++ unsigned int i = 0; ++ int ret = 0; ++ int index = 0; ++ uint32_t count = PLAT_MAX_OPP_NB; ++ uint32_t clksrc = 0; ++ ++ ret = get_all_opp_freqvolt_from_dt(&count); ++ switch (ret) { ++ case 0: ++ break; ++ case -FDT_ERR_NOTFOUND: ++ DMSG("Cannot find all OPP info in DT: use default settings."); ++ return 0; ++ default: ++ EMSG("Inconsistent OPP settings found in DT, ignored."); ++ return 0; ++ } ++ ++ index = clk_save_current_pll1_settings(buck1_voltage); ++ ++ clksrc = stm32mp1_clk_get_pll1_current_clksrc(); ++ ++ for (i = 0; i < count; i++) { ++ if (index >= 0 && i == (unsigned int)index) ++ continue; ++ ++ ret = clk_get_pll1_settings(clksrc, 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)) || ++ !stm32mp1_clk_pll1_settings_are_valid()) ++ panic(); ++ ++ memcpy(data, &pll1_settings, size); ++} ++ ++bool stm32mp1_clk_pll1_settings_are_valid(void) ++{ ++ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID; ++} ++#else ++static void stm32mp1_clk_early_init(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ /* Expect booting from a secure setup */ ++ if ((io_read32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) == 0) ++ panic("RCC TZC[TZEN]"); ++} ++ ++int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage __unused) ++{ ++ return 0; ++} ++ ++void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data __unused, ++ size_t size __unused) ++{ ++} ++ ++bool stm32mp1_clk_pll1_settings_are_valid(void) ++{ ++ return false; + } + +-service_init(stm32mp1_clk_early_init); ++static void enable_static_secure_clocks(void) ++{ ++} + #endif /*CFG_EMBED_DTB*/ ++ ++/* Start PMU OPP */ ++#define CLKSRC_TIMEOUT_US (200 * 1000) ++#define CLKDIV_TIMEOUT_US (200 * 1000) ++#define CLK_MPU_PLL1P 0x00000202 ++#define CLK_MPU_PLL1P_DIV 0x00000203 ++ ++static int stm32mp1_set_clksrc(unsigned int clksrc) ++{ ++ uintptr_t address = stm32_rcc_base() + (clksrc >> 4); ++ uint64_t timeout_ref = 0; ++ ++ io_clrsetbits32(address, RCC_SELR_SRC_MASK, clksrc & RCC_SELR_SRC_MASK); ++ ++ timeout_ref = timeout_init_us(CLKSRC_TIMEOUT_US); ++ while ((io_read32(address) & RCC_SELR_SRCRDY) == 0U) { ++ if (timeout_elapsed(timeout_ref)) { ++ EMSG("CLKSRC %u start failed @ 0x%"PRIxPTR": 0x%"PRIx32, ++ clksrc, address, io_read32(address)); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) ++{ ++ uint64_t timeout_ref = 0; ++ ++ io_clrsetbits32(address, RCC_DIVR_DIV_MASK, clkdiv & RCC_DIVR_DIV_MASK); ++ ++ timeout_ref = timeout_init_us(CLKDIV_TIMEOUT_US); ++ while ((io_read32(address) & RCC_DIVR_DIVRDY) == 0U) { ++ if (timeout_elapsed(timeout_ref)) { ++ EMSG("CLKDIV 0x%x start failed @ 0x%"PRIxPTR": 0x%"PRIx32, ++ clkdiv, address, io_read32(address)); ++ return -1; ++ } ++ } ++ ++ 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 as those in place, no need to reconfig. ++ * Return value is 0 if no error. ++ */ ++static int 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 = stm32_rcc_base(); ++ uint32_t fracr = 0; ++ uint32_t value = 0; ++ int ret = 0; ++ ++ ret = pll_compute_pllxcfgr1(pll, pllcfg, &value); ++ if (ret) ++ return ret; ++ ++ if (io_read32(rcc_base + pll->pllxcfgr1) != value) { ++ /* Different DIVN/DIVM, can't config on the fly */ ++ *result = -1; ++ return 0; ++ } ++ ++ *result = true; ++ ++ fracr = fracv << RCC_PLLNFRACR_FRACV_SHIFT; ++ fracr |= RCC_PLLNFRACR_FRACLE; ++ value = pll_compute_pllxcfgr2(pllcfg); ++ ++ if ((io_read32(rcc_base + pll->pllxfracr) == fracr) && ++ (io_read32(rcc_base + pll->pllxcfgr2) == value)) ++ /* Same parameters, no need to config */ ++ *result = 1; ++ else ++ *result = 0; ++ ++ return 0; ++} ++ ++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; ++ ++ 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; ++ } ++} ++ ++/* Configure PLL1 from input frequency OPP parameters */ ++static int pll1_config_from_opp_khz(uint32_t freq_khz) ++{ ++ unsigned int idx = 0; ++ int ret = 0; ++ int div = 0; ++ int config_on_the_fly = -1; ++ ++ for (idx = 0; idx < PLAT_MAX_OPP_NB; idx++) ++ if (pll1_settings.freq[idx] == freq_khz) ++ break; ++ ++ if (idx == PLAT_MAX_OPP_NB) ++ return -1; ++ ++ 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, stm32_rcc_base() + ++ RCC_MPCKDIVR); ++ if (ret == 0) ++ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P_DIV); ++ ++ return ret; ++ } ++ ++ ret = is_pll_config_on_the_fly(_PLL1, &pll1_settings.cfg[idx][0], ++ pll1_settings.frac[idx], ++ &config_on_the_fly); ++ if (ret) ++ return ret; ++ ++ if (config_on_the_fly == 1) ++ return 0; ++ ++ if (config_on_the_fly == -1) { ++ /* Switch to HSI and stop PLL1 before reconfiguration */ ++ ret = stm32mp1_set_clksrc(CLK_MPU_HSI); ++ if (ret) ++ return ret; ++ ++ ret = pll_stop(_PLL1); ++ if (ret) ++ return ret; ++ } ++ ++ ret = pll_config(_PLL1, &pll1_settings.cfg[idx][0], ++ pll1_settings.frac[idx]); ++ if (ret) ++ return ret; ++ ++ if (config_on_the_fly == -1) { ++ /* Start PLL1 and switch back to after reconfiguration */ ++ pll_start(_PLL1); ++ ++ ret = pll_output(_PLL1, pll1_settings.cfg[idx][PLLCFG_O]); ++ if (ret) ++ return ret; ++ ++ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void save_current_opp(void) ++{ ++ unsigned long freq_khz = UDIV_ROUND_NEAREST(stm32_clock_get_rate(CK_MPU), ++ 1000UL); ++ if (freq_khz > (unsigned long)UINT32_MAX) ++ panic(); ++ ++ current_opp_khz = (uint32_t)freq_khz; ++} ++ ++int stm32mp1_set_opp_khz(uint32_t freq_khz) ++{ ++ uint32_t mpu_src = 0; ++ ++ if (freq_khz == current_opp_khz) ++ return 0; ++ ++ if (!stm32mp1_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 -1; ++ } ++ ++ /* Check that PLL1 is MPU clock source */ ++ mpu_src = io_read32(stm32_rcc_base() + RCC_MPCKSELR) & ++ RCC_SELR_SRC_MASK; ++ if ((mpu_src != RCC_MPCKSELR_PLL) && ++ (mpu_src != RCC_MPCKSELR_PLL_MPUDIV)) ++ return -1; ++ ++ if (pll1_config_from_opp_khz(freq_khz)) { ++ /* Restore original value */ ++ if (pll1_config_from_opp_khz(current_opp_khz)) { ++ EMSG("No CPU operating point can be set"); ++ panic(); ++ } ++ ++ return -1; ++ } ++ ++ current_opp_khz = freq_khz; ++ ++ return 0; ++} ++ ++int stm32mp1_round_opp_khz(uint32_t *freq_khz) ++{ ++ unsigned int i = 0; ++ uint32_t round_opp = 0; ++ ++ if (!stm32mp1_clk_pll1_settings_are_valid()) { ++ /* ++ * No OPP table in DT, or an error occurred during PLL1 ++ * settings computation, system can only work on current ++ * operating point, so return current CPU frequency. ++ */ ++ *freq_khz = current_opp_khz; ++ ++ return 0; ++ } ++ ++ for (i = 0; i < PLAT_MAX_OPP_NB; i++) ++ if ((pll1_settings.freq[i] <= *freq_khz) && ++ (pll1_settings.freq[i] > round_opp)) ++ round_opp = pll1_settings.freq[i]; ++ ++ *freq_khz = round_opp; ++ ++ return 0; ++} ++/* End PMU OPP */ ++ ++#ifdef CFG_PM ++struct soc_stop_context { ++ uint32_t pll3cr; ++ uint32_t pll4cr; ++ uint32_t mssckselr; ++ uint32_t mcudivr; ++}; ++ ++static struct soc_stop_context soc_stop_ctx; ++ ++static void save_pll34_state(void) ++{ ++ uintptr_t rcc_base = stm32_rcc_base(); ++ struct soc_stop_context *ctx = &soc_stop_ctx; ++ ++ ctx->pll3cr = io_read32(rcc_base + RCC_PLL3CR); ++ ctx->pll4cr = io_read32(rcc_base + RCC_PLL4CR); ++} ++ ++static void save_mcu_subsys_clocks(void) ++{ ++ uintptr_t rcc_base = stm32_rcc_base(); ++ struct soc_stop_context *ctx = &soc_stop_ctx; ++ ++ ctx->mssckselr = io_read32(rcc_base + RCC_MSSCKSELR); ++ ctx->mcudivr = io_read32(rcc_base + RCC_MCUDIVR) & ++ RCC_MCUDIV_MASK; ++} ++ ++static void restore_pll34_state(void) ++{ ++ struct soc_stop_context *ctx = &soc_stop_ctx; ++ ++ /* Let PLL4 start while we're starting and waiting for PLL3 */ ++ if (ctx->pll4cr & RCC_PLLNCR_PLLON) ++ pll_start(_PLL4); ++ ++ if (ctx->pll3cr & RCC_PLLNCR_PLLON) { ++ pll_start(_PLL3); ++ if (pll_output(_PLL3, ctx->pll3cr >> RCC_PLLNCR_DIVEN_SHIFT)) { ++ EMSG("Failed to restore PLL3"); ++ panic(); ++ } ++ } ++ ++ if (ctx->pll4cr & RCC_PLLNCR_PLLON) { ++ if (pll_output(_PLL4, ctx->pll4cr >> RCC_PLLNCR_DIVEN_SHIFT)) { ++ EMSG("Failed to restore PLL4"); ++ panic(); ++ } ++ } ++} ++ ++static void restore_mcu_subsys_clocks(void) ++{ ++ uintptr_t rcc_base = stm32_rcc_base(); ++ struct soc_stop_context *ctx = &soc_stop_ctx; ++ ++ io_write32(rcc_base + RCC_MSSCKSELR, ctx->mssckselr); ++ ++ if (stm32mp1_set_clkdiv(ctx->mcudivr, rcc_base + RCC_MCUDIVR)) { ++ EMSG("Failed to restore MCUDIVR"); ++ panic(); ++ } ++} ++ ++/* ++ * 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) } ++ ++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), ++}; ++ ++struct backup_mux_cfg backup_mux4_cfg[] = { ++ MUXCFG(RCC_USBCKSELR, 1), ++}; ++ ++static void backup_mux_cfg(void) ++{ ++ struct backup_mux_cfg *cfg = backup_mux0_cfg; ++ size_t count = ARRAY_SIZE(backup_mux0_cfg); ++ size_t i = 0; ++ uintptr_t base = stm32_rcc_base(); ++ ++ for (i = 0; i < count; i++) ++ cfg[i].value = io_read32(base + cfg[i].offset) & ++ GENMASK_32(cfg[i].bit_len - 1, 0); ++ ++ cfg = backup_mux4_cfg; ++ count = ARRAY_SIZE(backup_mux4_cfg); ++ ++ for (i = 0; i < count; i++) ++ cfg[i].value = io_read32(base + cfg[i].offset) & ++ GENMASK_32(4 + cfg[i].bit_len - 1, 4); ++} ++ ++static void restore_mux_cfg(void) ++{ ++ struct backup_mux_cfg *cfg = backup_mux0_cfg; ++ size_t count = ARRAY_SIZE(backup_mux0_cfg); ++ size_t i = 0; ++ uintptr_t base = stm32_rcc_base(); ++ ++ for (i = 0; i < count; i++) ++ io_clrsetbits32(base + cfg[i].offset, ++ GENMASK_32(cfg[i].bit_len - 1, 0), ++ cfg[i].value); ++ ++ cfg = backup_mux4_cfg; ++ count = ARRAY_SIZE(backup_mux4_cfg); ++ ++ for (i = 0; i < count; i++) ++ io_clrsetbits32(base + cfg[i].offset, ++ GENMASK_32(4 + cfg[i].bit_len - 1, 4), ++ cfg[i].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); ++ size_t i = 0; ++ uintptr_t base = stm32_rcc_base(); ++ ++ for (i = 0; i < count; i++) ++ cfg[i].value = io_read32(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); ++ size_t i = 0; ++ uintptr_t base = stm32_rcc_base(); ++ ++ for (i = 0; i < count; i++) { ++ io_write32(base + cfg[i].offset, cfg[i].value); ++ io_write32(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); ++ size_t i = 0; ++ uintptr_t base = stm32_rcc_base(); ++ ++ for (i = 0; i < count; i++) ++ cfg[i].value = io_read32(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); ++ size_t i = 0; ++ uintptr_t base = stm32_rcc_base(); ++ ++ for (i = 0; i < count; i++) ++ io_write32(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 */ ++ io_write32(stm32_rcc_base() + RCC_OCENCLRR, ker_mask); ++} ++ ++static void enable_kernel_clocks(void) ++{ ++ uintptr_t rcc_base = stm32_rcc_base(); ++ uint32_t reg = 0; ++ 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 = io_read32(rcc_base + RCC_OCENSETR) << 1; ++ io_write32(rcc_base + RCC_OCENSETR, reg & ker_mask); ++} ++ ++static void clear_rcc_reset_status(void) ++{ ++ /* Clear reset status fields */ ++ io_write32(stm32_rcc_base() + RCC_MP_RSTSCLRR, 0); ++} ++ ++void stm32mp1_clk_save_context_for_stop(void) ++{ ++ enable_kernel_clocks(); ++ save_mcu_subsys_clocks(); ++ save_pll34_state(); ++} ++ ++void stm32mp1_clk_restore_context_for_stop(void) ++{ ++ restore_pll34_state(); ++ /* Restore MCU clock source after PLL3 is ready */ ++ restore_mcu_subsys_clocks(); ++ disable_kernel_clocks(); ++} ++ ++static void stm32_clock_suspend(void) ++{ ++ backup_regular_cfg(); ++ backup_sc_cfg(); ++ backup_mux_cfg(); ++ save_pll34_state(); ++ ++ enable_kernel_clocks(); ++ clear_rcc_reset_status(); ++} ++ ++static void stm32_clock_resume(void) ++{ ++ unsigned int idx = 0; ++ ++ restore_pll34_state(); ++ restore_mux_cfg(); ++ restore_sc_cfg(); ++ restore_regular_cfg(); ++ ++ /* Sync secure and shared clocks physical state on functional state */ ++ for (idx = 0; idx < NB_GATES; idx++) { ++ struct stm32mp1_clk_gate const *gate = gate_ref(idx); ++ ++ if (gate_is_non_secure(gate)) ++ continue; ++ ++ if (gate_refcounts[idx]) { ++ DMSG("Force clock %d enable", gate->clock_id); ++ __clk_enable(gate); ++ } else { ++ DMSG("Force clock %d disable", gate->clock_id); ++ __clk_disable(gate); ++ } ++ } ++ ++ disable_kernel_clocks(); ++} ++ ++static TEE_Result stm32_clock_pm(enum pm_op op, unsigned int pm_hint __unused, ++ const struct pm_callback_handle *hdl __unused) ++{ ++ if (op == PM_OP_SUSPEND) ++ stm32_clock_suspend(); ++ else ++ stm32_clock_resume(); ++ ++ return TEE_SUCCESS; ++} ++DECLARE_KEEP_PAGER(stm32_clock_pm); ++#else ++static TEE_Result stm32_clock_pm(enum pm_op op __unused, ++ unsigned int pm_hint __unused, ++ const struct pm_callback_handle *hdl __unused) ++{ ++ return TEE_ERROR_SECURITY; ++} ++#endif /*CFG_PM*/ ++ ++static void init_non_secure_rcc(void) ++{ ++ uintptr_t rcc_base = stm32_rcc_base(); ++ ++ /* Clear all interrupt flags and core stop requests */ ++ io_write32(rcc_base + RCC_MP_CIFR, 0x110F1F); ++ io_write32(rcc_base + RCC_MP_SREQCLRR, 0x3); ++} ++ ++static TEE_Result stm32_clk_probe(void) ++{ ++ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB); ++ ++ stm32mp1_clk_early_init(); ++ enable_static_secure_clocks(); ++ save_current_opp(); ++ init_non_secure_rcc(); ++ register_pm_core_service_cb(stm32_clock_pm, NULL); ++ ++ return TEE_SUCCESS; ++} ++/* Setup clock support before driver initialization */ ++service_init(stm32_clk_probe); +diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c +new file mode 100644 +index 0000000..1c2d9b2 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c +@@ -0,0 +1,469 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TIMEOUT_500US 500 ++ ++static enum stm32mp1_ddr_sr_mode saved_ddr_sr_mode; ++ ++static vaddr_t get_ddrctrl_base(void) ++{ ++ static struct io_pa_va base __nex_data = { .pa = DDRCTRL_BASE }; ++ ++ return io_pa_or_va(&base); ++} ++ ++static vaddr_t get_ddrphy_base(void) ++{ ++ static struct io_pa_va base __nex_data = { .pa = DDRPHYC_BASE }; ++ ++ return io_pa_or_va(&base); ++} ++ ++static void ddr_disable_clock(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ /* Disable all clocks */ ++ io_clrbits32(rcc_base + RCC_DDRITFCR, ++ RCC_DDRITFCR_DDRC1EN | ++ RCC_DDRITFCR_DDRC2EN | ++ RCC_DDRITFCR_DDRPHYCAPBEN | ++ RCC_DDRITFCR_DDRCAPBEN); ++} ++ ++static void ddr_enable_clock(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ /* Enable all clocks */ ++ io_setbits32(rcc_base + RCC_DDRITFCR, ++ RCC_DDRITFCR_DDRC1EN | ++ RCC_DDRITFCR_DDRC2EN | ++ RCC_DDRITFCR_DDRPHYCEN | ++ RCC_DDRITFCR_DDRPHYCAPBEN | ++ RCC_DDRITFCR_DDRCAPBEN); ++} ++ ++static void do_sw_handshake(void) ++{ ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ ++ io_clrbits32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); ++} ++ ++static void do_sw_ack(void) ++{ ++ uint64_t timeout_ref = 0; ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ ++ io_setbits32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); ++ ++ timeout_ref = timeout_init_us(TIMEOUT_500US); ++ while (!timeout_elapsed(timeout_ref)) ++ if (io_read32(ddrctrl_base + DDRCTRL_SWSTAT) & ++ DDRCTRL_SWSTAT_SW_DONE_ACK) ++ return; ++ ++ panic(); ++} ++ ++static int ddr_sw_self_refresh_in(void) ++{ ++ uint64_t timeout_ref = 0; ++ uint32_t operating_mode = 0; ++ uint32_t selref_type = 0; ++ uint8_t op_mode_changed = 0; ++ vaddr_t pwr_base = stm32_pwr_base(); ++ vaddr_t rcc_base = stm32_rcc_base(); ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ vaddr_t ddrphy_base = get_ddrphy_base(); ++ ++ io_clrbits32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); ++ ++ /* Blocks AXI ports from taking anymore transactions */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_PCTRL_0, DDRCTRL_PCTRL_N_PORT_EN); ++ io_clrbits32(ddrctrl_base + DDRCTRL_PCTRL_1, DDRCTRL_PCTRL_N_PORT_EN); ++ ++ /* ++ * Waits unit all AXI ports are idle ++ * Poll PSTAT.rd_port_busy_n = 0 ++ * Poll PSTAT.wr_port_busy_n = 0 ++ */ ++ timeout_ref = timeout_init_us(TIMEOUT_500US); ++ while (io_read32(ddrctrl_base + DDRCTRL_PSTAT)) ++ if (timeout_elapsed(timeout_ref)) ++ goto pstat_failed; ++ ++ /* SW Self-Refresh entry */ ++ io_setbits32(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_ref = timeout_init_us(TIMEOUT_500US); ++ while (!timeout_elapsed(timeout_ref)) { ++ uint32_t stat = io_read32(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) */ ++ io_setbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); ++ io_setbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDR); ++ io_clrsetbits32(ddrphy_base + DDRPHYC_ACIOCR, ++ DDRPHYC_ACIOCR_CKPDD_MASK, DDRPHYC_ACIOCR_CKPDD_0); ++ io_clrsetbits32(ddrphy_base + DDRPHYC_ACIOCR, ++ DDRPHYC_ACIOCR_CKPDR_MASK, DDRPHYC_ACIOCR_CKPDR_0); ++ io_clrsetbits32(ddrphy_base + DDRPHYC_ACIOCR, ++ DDRPHYC_ACIOCR_CSPDD_MASK, DDRPHYC_ACIOCR_CSPDD_0); ++ io_clrbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); ++ io_setbits32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); ++ io_setbits32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); ++ io_clrsetbits32(ddrphy_base + DDRPHYC_DSGCR, ++ DDRPHYC_DSGCR_ODTPDD_MASK, DDRPHYC_DSGCR_ODTPDD_0); ++ io_setbits32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); ++ io_clrsetbits32(ddrphy_base + DDRPHYC_DSGCR, ++ DDRPHYC_DSGCR_CKEPDD_MASK, DDRPHYC_DSGCR_CKEPDD_0); ++ ++ /* Disable PZQ cell (PUBL register) */ ++ io_setbits32(ddrphy_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); ++ ++ /* Activate sw retention in PWRCTRL */ ++ io_setbits32(pwr_base + PWR_CR3_OFF, PWR_CR3_DDRRETEN); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ ++ io_setbits32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ ++ /* Disable all DLLs: GLITCH window */ ++ io_setbits32(ddrphy_base + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLDIS); ++ io_setbits32(ddrphy_base + DDRPHYC_DX0DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ io_setbits32(ddrphy_base + DDRPHYC_DX1DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ io_setbits32(ddrphy_base + DDRPHYC_DX2DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ io_setbits32(ddrphy_base + DDRPHYC_DX3DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL output clock */ ++ io_clrbits32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ ++ /* Disable all clocks */ ++ ddr_disable_clock(); ++ ++ return 0; ++ ++selfref_sw_failed: ++ /* This bit should be cleared to restore DDR in its previous state */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_PWRCTL, DDRCTRL_PWRCTL_SELFREF_SW); ++ ++pstat_failed: ++ io_setbits32(ddrctrl_base + DDRCTRL_PCTRL_0, DDRCTRL_PCTRL_N_PORT_EN); ++ io_setbits32(ddrctrl_base + DDRCTRL_PCTRL_1, DDRCTRL_PCTRL_N_PORT_EN); ++ ++ return -1; ++} ++ ++static int ddr_sw_self_refresh_exit(void) ++{ ++ uint64_t timeout_ref = 0; ++ vaddr_t rcc_base = stm32_rcc_base(); ++ vaddr_t pwr_base = stm32_pwr_base(); ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ vaddr_t ddrphy_base = get_ddrphy_base(); ++ ++ /* Enable all clocks */ ++ ddr_enable_clock(); ++ ++ do_sw_handshake(); ++ ++ /* Mask dfi_init_complete_en */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_DFIMISC, ++ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); ++ ++ do_sw_ack(); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ ++ io_setbits32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ ++ /* Enable all DLLs: GLITCH window */ ++ io_clrbits32(ddrphy_base + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLDIS); ++ io_clrbits32(ddrphy_base + DDRPHYC_DX0DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ io_clrbits32(ddrphy_base + DDRPHYC_DX1DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ io_clrbits32(ddrphy_base + DDRPHYC_DX2DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ io_clrbits32(ddrphy_base + DDRPHYC_DX3DLLCR, DDRPHYC_DXNDLLCR_DLLDIS); ++ ++ /* Additional delay to avoid early DLL clock switch */ ++ udelay(50); ++ ++ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ ++ io_clrbits32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); ++ io_clrbits32(ddrphy_base + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLSRST); ++ udelay(10); ++ io_setbits32(ddrphy_base + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLSRST); ++ ++ /* PHY partial init: (DLL lock and ITM reset) */ ++ io_write32(ddrphy_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(10); ++ ++ timeout_ref = timeout_init_us(TIMEOUT_500US); ++ while (!(io_read32(ddrphy_base + DDRPHYC_PGSR) & DDRPHYC_PGSR_IDONE)) ++ if (timeout_elapsed(timeout_ref)) ++ return -1; ++ ++ do_sw_handshake(); ++ ++ /* Unmask dfi_init_complete_en to uMCTL2 */ ++ io_setbits32(ddrctrl_base + DDRCTRL_DFIMISC, ++ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); ++ ++ do_sw_ack(); ++ ++ /* Deactivate sw retention in PWR */ ++ io_clrbits32(pwr_base + PWR_CR3_OFF, PWR_CR3_DDRRETEN); ++ ++ /* Enable PZQ cell (PUBL register) */ ++ io_clrbits32(ddrphy_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); ++ ++ /* Enable pad drivers */ ++ io_clrbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); ++ io_setbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); ++ io_clrbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_CKPDD_MASK); ++ io_clrbits32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_CSPDD_MASK); ++ io_clrbits32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); ++ io_clrbits32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); ++ io_clrbits32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_ODTPDD_MASK); ++ io_clrbits32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); ++ io_clrbits32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKEPDD_MASK); ++ ++ /* Remove selfrefresh */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_PWRCTL, DDRCTRL_PWRCTL_SELFREF_SW); ++ ++ /* Wait operating_mode == normal */ ++ timeout_ref = timeout_init_us(TIMEOUT_500US); ++ while (1) { ++ if ((io_read32(ddrctrl_base + DDRCTRL_STAT) & ++ DDRCTRL_STAT_OPERATING_MODE_MASK) == ++ DDRCTRL_STAT_OPERATING_MODE_NORMAL) ++ break; ++ ++ if (timeout_elapsed(timeout_ref)) ++ return -1; ++ } ++ ++ /* AXI ports are no longer blocked from taking transactions */ ++ io_setbits32(ddrctrl_base + DDRCTRL_PCTRL_0, DDRCTRL_PCTRL_N_PORT_EN); ++ io_setbits32(ddrctrl_base + DDRCTRL_PCTRL_1, DDRCTRL_PCTRL_N_PORT_EN); ++ ++ io_setbits32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); ++ ++ return 0; ++} ++ ++uint32_t get_ddrphy_calibration(void) ++{ ++ vaddr_t ddrphy_base = get_ddrphy_base(); ++ uint32_t zcal = io_read32(ddrphy_base + DDRPHYC_ZQ0CR0); ++ ++ return (zcal & DDRPHYC_ZQ0CRN_ZDATA_MASK) >> DDRPHYC_ZQ0CRN_ZDATA_SHIFT; ++} ++ ++int ddr_standby_sr_entry(void) ++{ ++ vaddr_t pwr_base = stm32_pwr_base(); ++ ++ if (ddr_sw_self_refresh_in()) ++ return -1; ++ ++ /* Enable I/O retention mode in standby */ ++ io_setbits32(pwr_base + PWR_CR3_OFF, PWR_CR3_DDRSREN); ++ ++ return 0; ++} ++ ++int ddr_standby_sr_exit(void) ++{ ++ return ddr_sw_self_refresh_exit(); ++} ++ ++static void ddr_sr_mode_ssr(void) ++{ ++ vaddr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1EN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2EN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBLPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBLPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCEN); ++ io_clrbits32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); ++ io_clrbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK); ++ ++ /* Disable HW LP interface of uMCTL2 */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_HWLPCTL, DDRCTRL_HWLPCTL_HW_LP_EN); ++ ++ /* Configure Automatic LP modes of uMCTL2 */ ++ io_clrsetbits32(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). ++ */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); ++ ++ /* Disable automatic Self-Refresh mode */ ++ io_clrbits32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_SELFREF_EN); ++} ++ ++static void ddr_sr_mode_asr(void) ++{ ++ vaddr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); ++ io_clrsetbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, ++ RCC_DDRITFCR_DDRCKMOD_ASR1); ++ ++ /* Enable HW LP interface of uMCTL2 */ ++ io_setbits32(ddrctrl_base + DDRCTRL_HWLPCTL, DDRCTRL_HWLPCTL_HW_LP_EN); ++ ++ /* Configure Automatic LP modes of uMCTL2 */ ++ io_clrsetbits32(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). ++ */ ++ io_setbits32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); ++ ++ /* Enable automatic Self-Refresh for ASR mode */ ++ io_setbits32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_SELFREF_EN); ++} ++ ++static void ddr_sr_mode_hsr(void) ++{ ++ vaddr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; ++ vaddr_t ddrctrl_base = get_ddrctrl_base(); ++ ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); ++ io_clrbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); ++ io_clrbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); ++ io_setbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); ++ io_clrsetbits32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, ++ RCC_DDRITFCR_DDRCKMOD_HSR1); ++ ++ /* Enable HW LP interface of uMCTL2 */ ++ io_setbits32(ddrctrl_base + DDRCTRL_HWLPCTL, DDRCTRL_HWLPCTL_HW_LP_EN); ++ ++ /* Configure Automatic LP modes of uMCTL2 */ ++ io_clrsetbits32(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). ++ */ ++ io_setbits32(ddrctrl_base + DDRCTRL_PWRCTL, ++ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); ++} ++ ++static enum stm32mp1_ddr_sr_mode ddr_read_sr_mode(void) ++{ ++ uint32_t pwrctl = io_read32(get_ddrctrl_base() + DDRCTRL_PWRCTL); ++ uint32_t mask = DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE | ++ DDRCTRL_PWRCTL_SELFREF_EN; ++ ++ switch (pwrctl & mask) { ++ 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; ++ } ++} ++ ++static 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: ++ EMSG("Unknown Self Refresh mode\n"); ++ panic(); ++ } ++} ++ ++void ddr_save_sr_mode(enum stm32mp1_ddr_sr_mode mode) ++{ ++ /* Save current mode before setting new one */ ++ saved_ddr_sr_mode = ddr_read_sr_mode(); ++ ddr_set_sr_mode(mode); ++} ++ ++void ddr_restore_sr_mode(void) ++{ ++ ddr_set_sr_mode(saved_ddr_sr_mode); ++} +diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h +new file mode 100644 +index 0000000..e2d809b +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h +@@ -0,0 +1,219 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ */ ++ ++#ifndef __STM32MP1_DDRC_H__ ++#define __STM32MP1_DDRC_H__ ++ ++#include ++ ++/* DDR Controller */ ++/* 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_32(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_32(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_32(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 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_32(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_32(19, 12) ++#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_32(27, 16) ++#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 ++ ++#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK_32(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_32(12, 8) ++#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK_32(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 ++#define DDRPHYC_PGSR 0x00C ++#define DDRPHYC_DLLGCR 0x010 ++#define DDRPHYC_ACDLLCR 0x014 ++#define DDRPHYC_PTR0 0x018 ++#define DDRPHYC_ACIOCR 0x024 ++#define DDRPHYC_DXCCR 0x028 ++#define DDRPHYC_DSGCR 0x02C ++#define DDRPHYC_ZQ0CR0 0x180 ++#define DDRPHYC_DX0GCR 0x1C0 ++#define DDRPHYC_DX0DLLCR 0x1CC ++#define DDRPHYC_DX1GCR 0x200 ++#define DDRPHYC_DX1DLLCR 0x20C ++#define DDRPHYC_DX2GCR 0x240 ++#define DDRPHYC_DX2DLLCR 0x24C ++#define DDRPHYC_DX3GCR 0x280 ++#define DDRPHYC_DX3DLLCR 0x28C ++ ++/* DDR PHY Register fields */ ++#define DDRPHYC_PIR_INIT BIT(0) ++#define DDRPHYC_PIR_DLLSRST BIT(1) ++#define DDRPHYC_PIR_DLLLOCK BIT(2) ++#define DDRPHYC_PIR_ZCAL BIT(3) ++#define DDRPHYC_PIR_ITMSRST BIT(4) ++#define DDRPHYC_PIR_DRAMRST BIT(5) ++#define DDRPHYC_PIR_DRAMINIT BIT(6) ++#define DDRPHYC_PIR_QSTRN BIT(7) ++#define DDRPHYC_PIR_ICPC BIT(16) ++#define DDRPHYC_PIR_ZCALBYP BIT(30) ++#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) ++ ++#define DDRPHYC_PGCR_DFTCMP BIT(2) ++#define DDRPHYC_PGCR_PDDISDX BIT(24) ++#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK_32(28, 25) ++ ++#define DDRPHYC_PGSR_IDONE BIT(0) ++#define DDRPHYC_PGSR_DTERR BIT(5) ++#define DDRPHYC_PGSR_DTIERR BIT(6) ++#define DDRPHYC_PGSR_DFTERR BIT(7) ++#define DDRPHYC_PGSR_RVERR BIT(8) ++#define DDRPHYC_PGSR_RVEIRR BIT(9) ++ ++#define DDRPHYC_DLLGCR_BPS200 BIT(23) ++ ++#define DDRPHYC_ACDLLCR_DLLSRST BIT(30) ++#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) ++ ++#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 ++#define DDRPHYC_PTR0_TDLLSRST_MASK GENMASK_32(5, 0) ++#define DDRPHYC_PTR0_TDLLLOCK_OFFSET 6 ++#define DDRPHYC_PTR0_TDLLLOCK_MASK GENMASK_32(17, 6) ++#define DDRPHYC_PTR0_TITMSRST_OFFSET 18 ++#define DDRPHYC_PTR0_TITMSRST_MASK GENMASK_32(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_32(10, 8) ++#define DDRPHYC_ACIOCR_CKPDD_0 BIT(8) ++#define DDRPHYC_ACIOCR_CKPDR_MASK GENMASK_32(13, 11) ++#define DDRPHYC_ACIOCR_CKPDR_0 BIT(11) ++#define DDRPHYC_ACIOCR_CSPDD_MASK GENMASK_32(21, 18) ++#define DDRPHYC_ACIOCR_CSPDD_0 BIT(18) ++#define DDRPHYC_ACIOCR_RSTPDD BIT(27) ++#define DDRPHYC_ACIOCR_RSTPDR BIT(28) ++ ++#define DDRPHYC_DXCCR_DXPDD BIT(2) ++#define DDRPHYC_DXCCR_DXPDR BIT(3) ++ ++#define DDRPHYC_DSGCR_CKEPDD_MASK GENMASK_32(19, 16) ++#define DDRPHYC_DSGCR_CKEPDD_0 BIT(16) ++#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK_32(23, 20) ++#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) ++#define DDRPHYC_DSGCR_NL2PD BIT(24) ++ ++#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK_32(27, 0) ++#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 ++#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) ++#define DDRPHYC_ZQ0CRN_ZQPD BIT(31) ++ ++#define DDRPHYC_DXNGCR_DXEN BIT(0) ++ ++#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) ++#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) ++#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) ++#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 ++ ++/* DDR Self Refresh (SR) modes */ ++enum stm32mp1_ddr_sr_mode { ++ DDR_SR_MODE_INVALID = 0, ++ DDR_SSR_MODE, ++ DDR_HSR_MODE, ++ DDR_ASR_MODE, ++}; ++ ++void ddr_save_sr_mode(enum stm32mp1_ddr_sr_mode mode); ++void ddr_restore_sr_mode(void); ++ ++/* Return 32bit calibration value used for DDRPHY */ ++uint32_t get_ddrphy_calibration(void); ++ ++/* ++ * Entry/exit DDR selfrefresh mode ++ * Return 0 on success and a non-null value on error ++ */ ++int ddr_standby_sr_entry(void); ++int ddr_standby_sr_exit(void); ++ ++#endif /*__STM32MP1_DDRC_H__*/ +diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h +index 9ba95df..41a8469 100644 +--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h ++++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h +@@ -6,6 +6,7 @@ + #ifndef __STM32MP1_PWR_H + #define __STM32MP1_PWR_H + ++#include + #include + + #define PWR_CR1_OFF 0x00 +@@ -15,7 +16,35 @@ + #define PWR_WKUPCR_OFF 0x20 + #define PWR_MPUWKUPENR_OFF 0x28 + +-#define PWR_OFFSET_MASK 0x3fUL ++#define PWR_OFFSET_MASK GENMASK_32(5, 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_WKUPCR_MASK (GENMASK_32(27, 16) | \ ++ GENMASK_32(13, 8) | GENMASK_32(5, 0)) ++ ++#define PWR_MPUWKUPENR_MASK GENMASK_32(5, 0) + + vaddr_t stm32_pwr_base(void); + +diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h +index 95aefcf..3498022 100644 +--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h ++++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h +@@ -6,8 +6,6 @@ + #ifndef __STM32MP1_RCC_H__ + #define __STM32MP1_RCC_H__ + +-#include +-#include + #include + + #define RCC_TZCR 0x00 +@@ -392,7 +390,8 @@ + #define RCC_HSICFGR_HSITRIM_SHIFT 8 + #define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) + #define RCC_HSICFGR_HSICAL_SHIFT 16 +-#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) ++#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(24, 16) ++#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK_32(27, 25) + + /* Fields of RCC_CSICFGR register */ + #define RCC_CSICFGR_CSITRIM_SHIFT 8 +@@ -455,6 +454,9 @@ + #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) ++ + /* RCC_MP_APB5RST(SET|CLR)R bit fields */ + #define RCC_APB5RSTSETR_SPI6RST BIT(0) + #define RCC_APB5RSTSETR_I2C4RST BIT(2) +@@ -508,6 +510,9 @@ + #define RCC_AHB5RSTSETR_RNG1RST BIT(6) + #define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + ++/* RCC_MP_AHB6RST(SET|CLR)R bit fields */ ++#define RCC_AHB6RSTSETR_GPURST BIT(5) ++ + /* RCC_MP_AHB5EN(SET|CLR)R bit fields */ + #define RCC_MP_AHB5ENSETR_GPIOZEN_POS 0 + #define RCC_MP_AHB5ENSETR_CRYP1EN_POS 4 +@@ -531,8 +536,9 @@ + #define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + + /* RCC_MP_TZAHB6EN(SET|CLR)R bit fields */ +-#define RCC_MP_TZAHB6ENSETR_MDMA_POS 0 +-#define RCC_MP_TZAHB6ENSETR_MDMA BIT(RCC_MP_TZAHB6ENSETR_MDMA_POS) ++#define RCC_MP_TZAHB6ENSETR_MDMA_POS 0 ++#define RCC_MP_TZAHB6ENSETR_MDMA \ ++ BIT(RCC_MP_TZAHB6ENSETR_MDMA_POS) + + /* RCC_MP_IWDGFZ(SET|CLR)R bit fields */ + #define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) +@@ -541,16 +547,31 @@ + #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" + + #ifndef __ASSEMBLER__ ++#include ++#include ++#include ++ + vaddr_t stm32_rcc_base(void); + + static inline bool stm32_rcc_is_secure(void) + { +- return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_TZEN; ++ static int state = -1; ++ ++ if (state < 0) ++ state = io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_TZEN; ++ ++ return state; + } + + static inline bool stm32_rcc_is_mckprot(void) + { +- return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_MCKPROT; ++ const uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; ++ static int state = -1; ++ ++ if (state < 0) ++ state = (io_read32(stm32_rcc_base() + RCC_TZCR) & mask) == mask; ++ ++ return state; + } + #endif /*__ASSEMBLER__*/ + +diff --git a/core/arch/arm/plat-stm32mp1/drivers/sub.mk b/core/arch/arm/plat-stm32mp1/drivers/sub.mk +index 42b6893..1718bd6 100644 +--- a/core/arch/arm/plat-stm32mp1/drivers/sub.mk ++++ b/core/arch/arm/plat-stm32mp1/drivers/sub.mk +@@ -1,4 +1,6 @@ ++srcs-$(CFG_STM32_CLKCALIB) += stm32mp1_calib.c + srcs-y += stm32mp1_clk.c ++srcs-y += stm32mp1_ddrc.c + srcs-$(CFG_STPMIC1) += stm32mp1_pmic.c + srcs-y += stm32mp1_pwr.c + srcs-y += stm32mp1_rcc.c +diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c +index 9947e71..40e4263 100644 +--- a/core/arch/arm/plat-stm32mp1/main.c ++++ b/core/arch/arm/plat-stm32mp1/main.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: BSD-2-Clause + /* +- * Copyright (c) 2017-2018, STMicroelectronics ++ * Copyright (c) 2017-2020, STMicroelectronics + * Copyright (c) 2016-2018, Linaro Limited + */ + +@@ -9,9 +9,14 @@ + #include + #include + #include +-#include ++#include + #include ++#include ++#include ++#include ++#include + #include ++#include + #include + #include + #include +@@ -19,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -32,7 +38,10 @@ register_phys_mem_pgdir(MEM_AREA_IO_NSEC, GPIOS_NSEC_BASE, GPIOS_NSEC_SIZE); + #endif + register_phys_mem_pgdir(MEM_AREA_IO_NSEC, I2C4_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_NSEC, I2C6_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_NSEC, IWDG1_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_NSEC, IWDG2_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_NSEC, RNG1_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_NSEC, RTC_BASE, SMALL_PAGE_SIZE); + #ifdef CFG_WITH_NSEC_UARTS + register_phys_mem_pgdir(MEM_AREA_IO_NSEC, USART1_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_NSEC, USART2_BASE, SMALL_PAGE_SIZE); +@@ -44,17 +53,38 @@ register_phys_mem_pgdir(MEM_AREA_IO_NSEC, UART7_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_NSEC, UART8_BASE, SMALL_PAGE_SIZE); + #endif + ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, BKPSRAM_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, BSEC_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, DBGMCU_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, DDRCTRL_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, DDRPHYC_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, ETZPC_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, GPIOZ_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, I2C4_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, I2C6_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, IWDG1_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, PWR_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, RCC_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG1_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, RTC_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, STGEN_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, SYSCFG_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, TAMP_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM1_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM2_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM3_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM4_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM5_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM6_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM7_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM8_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM12_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM13_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM14_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM15_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM16_BASE, SMALL_PAGE_SIZE); ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, TIM17_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC_BASE, SMALL_PAGE_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, USART1_BASE, SMALL_PAGE_SIZE); + +@@ -69,6 +99,12 @@ register_dynamic_shm(DDR_BASE, CFG_TZDRAM_START - DDR_BASE); + register_dynamic_shm(TZDRAM_END, DRAM_END - TZDRAM_END); + #endif + ++/* Map non-secure DDR bottom for the low power sequence */ ++register_phys_mem(MEM_AREA_RAM_NSEC, DDR_BASE, SMALL_PAGE_SIZE); ++ ++/* Map TEE physical RAM as read-only for content storage when suspending */ ++register_phys_mem(MEM_AREA_ROM_SEC, TEE_RAM_START, TEE_RAM_PH_SIZE); ++ + static const struct thread_handlers handlers = { + .cpu_on = pm_panic, + .cpu_off = pm_panic, +@@ -185,8 +221,86 @@ static TEE_Result init_console_from_dt(void) + + /* Probe console from DT once clock inits (service init level) are completed */ + service_init_late(init_console_from_dt); ++ ++static TEE_Result initialize_pll1_settings(void) ++{ ++ uint32_t cpu_voltage = 0U; ++ int ret = 0; ++ ++ if (stm32mp1_clk_pll1_settings_are_valid()) ++ return TEE_SUCCESS; ++ ++ if (stm32mp_dt_pmic_status() > 0) { ++ stm32mp_get_pmic(); ++ ++ ret = stpmic1_regulator_voltage_get( ++ stm32mp_pmic_get_cpu_supply_name()); ++ if (ret < 0) ++ return ret; ++ ++ cpu_voltage = (uint32_t)ret; ++ ++ stm32mp_put_pmic(); ++ } ++ ++ if (stm32mp1_clk_compute_all_pll1_settings(cpu_voltage)) ++ panic(); ++ ++ return TEE_SUCCESS; ++} ++ ++/* Compute PLL1 settings once PMIC init is completed */ ++driver_init_late(initialize_pll1_settings); ++ + #endif + ++static uintptr_t stm32_dbgmcu_base(void) ++{ ++ static void *va; ++ ++ if (!cpu_mmu_enabled()) ++ return DBGMCU_BASE; ++ ++ if (!va) ++ va = phys_to_virt(DBGMCU_BASE, MEM_AREA_IO_SEC); ++ ++ return (uintptr_t)va; ++} ++ ++/* SoC versioning util, returns default ID if can't access DBGMCU */ ++TEE_Result stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version) ++{ ++ uint32_t id = STM32MP1_CHIP_DEFAULT_VERSION; ++ ++ if (!chip_version) ++ return TEE_ERROR_BAD_PARAMETERS; ++ ++ if (stm32_bsec_read_debug_conf() & BSEC_DBGSWGEN) ++ id = (io_read32(stm32_dbgmcu_base() + DBGMCU_IDC) & ++ DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT; ++ ++ *chip_version = id; ++ ++ return TEE_SUCCESS; ++} ++ ++/* SoC device ID util, returns default ID if can't access DBGMCU */ ++TEE_Result stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id) ++{ ++ uint32_t id = STM32MP1_CHIP_ID; ++ ++ if (!chip_dev_id) ++ return TEE_ERROR_BAD_PARAMETERS; ++ ++ if (stm32_bsec_read_debug_conf() & BSEC_DBGSWGEN) ++ id = io_read32(stm32_dbgmcu_base() + DBGMCU_IDC) & ++ DBGMCU_IDC_DEV_ID_MASK; ++ ++ *chip_dev_id = id; ++ ++ return TEE_SUCCESS; ++} ++ + /* + * GIC init, used also for primary/secondary boot core wake completion + */ +@@ -211,6 +325,13 @@ void main_secondary_init_gic(void) + { + gic_cpu_init(&gic_data); + ++#if CFG_TEE_CORE_NB_CORE == 2 ++ /* Secondary core release constraint on APB5 clock */ ++ io_write32(stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER), ++ BOOT_API_A7_RESET_MAGIC_NUMBER); ++ stm32_clock_disable(RTCAPB); ++#endif ++ + stm32mp_register_online_cpu(); + } + +@@ -229,7 +350,11 @@ static TEE_Result init_stm32mp1_drivers(void) + (SYSRAM_SEC_SIZE >= CFG_TZSRAM_SIZE))); + + etzpc_configure_tzma(1, SYSRAM_SEC_SIZE >> SMALL_PAGE_SHIFT); ++#ifdef STM32MP1_USE_MPU0_RESET ++ /* BootROM needs unlocked for independent reset */ ++#else + etzpc_lock_tzma(1); ++#endif + + return TEE_SUCCESS; + } +@@ -258,12 +383,20 @@ void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg) + + bool stm32mp_is_closed_device(void) + { +- uint32_t otp = 0; ++ uint32_t otp_id = 0; ++ size_t bit_len = 0; ++ uint32_t otp_value = 0; + TEE_Result result = TEE_ERROR_GENERIC; + ++ if (stm32_bsec_find_otp_in_nvmem_layout(CFG0_OTP, &otp_id, &bit_len)) ++ panic(); ++ ++ if (bit_len != 8) ++ panic(); ++ + /* Non closed_device platform expects fuse well programmed to 0 */ +- result = stm32_bsec_shadow_read_otp(&otp, DATA0_OTP); +- if (!result && !(otp & BIT(DATA0_OTP_SECURED_POS))) ++ result = stm32_bsec_shadow_read_otp(&otp_value, otp_id); ++ if (!result && !(otp_value & BIT(CFG0_OTP_SECURED_POS))) + return false; + + return true; +@@ -307,6 +440,20 @@ vaddr_t stm32mp_bkpreg(unsigned int idx) + return bkpreg_base() + (idx * sizeof(uint32_t)); + } + ++vaddr_t stm32mp_bkpsram_base(void) ++{ ++ struct io_pa_va base = { .pa = BKPSRAM_BASE }; ++ ++ return io_pa_or_va(&base); ++} ++ ++vaddr_t stm32mp_stgen_base(void) ++{ ++ struct io_pa_va base = { .pa = STGEN_BASE }; ++ ++ return io_pa_or_va(&base); ++} ++ + vaddr_t stm32_get_gpio_bank_base(unsigned int bank) + { + static struct io_pa_va gpios_nsec_base = { .pa = GPIOS_NSEC_BASE }; +@@ -339,3 +486,162 @@ unsigned int stm32_get_gpio_bank_clock(unsigned int bank) + assert(bank <= GPIO_BANK_K); + return GPIOA + bank; + } ++ ++static int get_part_number(uint32_t *part_nb) ++{ ++ uint32_t part_number = 0; ++ uint32_t dev_id = 0; ++ uint32_t otp = 0; ++ size_t bit_len = 0; ++ ++ assert(part_nb); ++ ++ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id)) ++ return -1; ++ ++ if (stm32_bsec_find_otp_in_nvmem_layout(PART_NUMBER_OTP, ++ &otp, &bit_len)) ++ return -1; ++ ++ if (bit_len != 8) ++ panic(); ++ ++ if (stm32_bsec_read_otp(&part_number, otp)) ++ return -1; ++ ++ part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >> ++ PART_NUMBER_OTP_PART_SHIFT; ++ ++ *part_nb = part_number | (dev_id << 16); ++ ++ return 0; ++} ++ ++bool stm32mp_supports_cpu_opp(uint32_t opp_id) ++{ ++ uint32_t part_number = 0; ++ uint32_t id = 0; ++ ++ if (get_part_number(&part_number)) { ++ DMSG("Cannot get part number\n"); ++ panic(); ++ } ++ ++ switch (opp_id) { ++ case PLAT_OPP_ID1: ++ case PLAT_OPP_ID2: ++ id = opp_id; ++ break; ++ default: ++ return false; ++ } ++ ++ switch (part_number) { ++ case STM32MP157F_PART_NB: ++ case STM32MP157D_PART_NB: ++ case STM32MP153F_PART_NB: ++ case STM32MP153D_PART_NB: ++ case STM32MP151F_PART_NB: ++ case STM32MP151D_PART_NB: ++ return true; ++ default: ++ return id == PLAT_OPP_ID1; ++ } ++} ++ ++unsigned int stm32mp_iwdg_irq2instance(size_t irq) ++{ ++ int id = irq - STM32MP1_IRQ_IWDG1; ++ ++ assert(id >= IWDG1_INST && id <= IWDG2_INST); ++ return (unsigned int)id; ++} ++ ++size_t stm32mp_iwdg_instance2irq(unsigned int instance) ++{ ++ return instance + STM32MP1_IRQ_IWDG1; ++} ++ ++unsigned int stm32mp_iwdg_iomem2instance(vaddr_t pbase) ++{ ++ switch (pbase) { ++ case IWDG1_BASE: ++ return IWDG1_INST; ++ case IWDG2_BASE: ++ return IWDG2_INST; ++ default: ++ panic(); ++ } ++} ++ ++unsigned long stm32_get_iwdg_otp_config(vaddr_t pbase) ++{ ++ unsigned int idx = 0; ++ unsigned long iwdg_cfg = 0; ++ uint32_t otp_id = 0; ++ size_t bit_len = 0; ++ uint32_t otp_value = 0; ++ ++ idx = stm32mp_iwdg_iomem2instance(pbase); ++ ++ if (stm32_bsec_find_otp_in_nvmem_layout(HW2_OTP, &otp_id, &bit_len)) ++ panic(); ++ ++ if (bit_len != 32) ++ panic(); ++ ++ if (stm32_bsec_read_otp(&otp_value, otp_id)) ++ panic(); ++ ++ if (otp_value & BIT(idx + HW2_OTP_IWDG_HW_ENABLE_SHIFT)) ++ iwdg_cfg |= IWDG_HW_ENABLED; ++ ++ if (otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STOP_SHIFT)) ++ iwdg_cfg |= IWDG_DISABLE_ON_STOP; ++ ++ if (otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STANDBY_SHIFT)) ++ iwdg_cfg |= IWDG_DISABLE_ON_STANDBY; ++ ++ return iwdg_cfg; ++} ++ ++#ifdef CFG_STM32_RTC ++/* ++ * Return true if RTC needs to be read twice not once for a reliable value. ++ * ++ * This function determines the number of needed RTC calendar read operations ++ * to get consistent values: RTC may need to be read twice depending on clock ++ * frequencies. ++ * If APB1 frequency is less than 7 times the RTC one, the software has to ++ * read the calendar time and date register twice. ++ */ ++bool stm32_rtc_get_read_twice(void) ++{ ++ unsigned long apb1_freq = 0; ++ unsigned long rtc_freq = 0; ++ uint32_t apb1_div = 0; ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ switch ((io_read32(rcc_base + RCC_BDCR) & ++ RCC_BDCR_RTCSRC_MASK) >> RCC_BDCR_RTCSRC_SHIFT) { ++ case 1: ++ rtc_freq = stm32_clock_get_rate(CK_LSE); ++ break; ++ case 2: ++ rtc_freq = stm32_clock_get_rate(CK_LSI); ++ break; ++ case 3: ++ rtc_freq = stm32_clock_get_rate(CK_HSE); ++ rtc_freq /= (io_read32(rcc_base + RCC_RTCDIVR) & ++ RCC_DIVR_DIV_MASK) + 1U; ++ break; ++ default: ++ panic(); ++ } ++ ++ apb1_div = io_read32(rcc_base + RCC_APB1DIVR) & RCC_APBXDIV_MASK; ++ apb1_freq = stm32_clock_get_rate(CK_MCU) >> apb1_div; ++ ++ return apb1_freq < (rtc_freq * 7U); ++} ++#endif +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.c b/core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.c +new file mode 100644 +index 0000000..d99ee32 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.c +@@ -0,0 +1,152 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "stm32mp1_smc.h" ++#include "low_power_svc.h" ++#include "../pm/power.h" ++#include "../pm/context.h" ++ ++#undef DDR_SR_TEST ++ ++#ifdef DDR_SR_TEST ++uint32_t sr_mode_scv_handler(uint32_t __maybe_unused x1, uint32_t x2) ++{ ++ unsigned int mode = x2; ++ ++ DMSG("DDR selfrefresh mode 0x%" PRIx32 ", 0x%" PRIx32, mode, x1); ++ ++ switch (mode) { ++ case STM32_SIP_SVC_SR_MODE_SSR: ++ ddr_sr_mode_ssr(); ++ break; ++ case STM32_SIP_SVC_SR_MODE_ASR: ++ ddr_sr_mode_asr(); ++ break; ++ case STM32_SIP_SVC_SR_MODE_HSR: ++ ddr_sr_mode_hsr(); ++ break; ++ default: ++ return STM32_SIP_SVC_INVALID_PARAMS; ++ } ++ ++ return STM32_SIP_SVC_OK; ++} ++#else ++uint32_t sr_mode_scv_handler(uint32_t __unused x1, uint32_t __unused x2) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++#endif ++ ++uint32_t cstop_scv_handler(struct sm_ctx __unused *ctx, uint32_t __unused x1, ++ uint32_t __unused x2, uint32_t __unused x3) ++{ ++ DMSG("core %u", get_core_pos()); ++ ++ stm32mp1_set_lp_deepest_soc_mode(PSCI_MODE_SYSTEM_SUSPEND, ++ STM32_PM_CSTOP_ALLOW_LPLV_STOP); ++ ++ return (psci_system_suspend(ctx->nsec.mon_lr, 0, &ctx->nsec) == 0) ? ++ STM32_SIP_SVC_OK : STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t standby_scv_handler(struct sm_ctx *ctx, uint32_t __unused x1, ++ uint32_t __unused x2, uint32_t x3) ++{ ++ uint32_t nsec_resume_ep = x3; ++ ++ DMSG("core %u", get_core_pos()); ++ ++ if (nsec_resume_ep == 0U) { ++ shutdown_scv_handler(); ++ panic(); ++ } ++ ++ stm32mp1_set_lp_deepest_soc_mode(PSCI_MODE_SYSTEM_SUSPEND, ++ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR); ++ ++ return (psci_system_suspend(nsec_resume_ep, 0, &ctx->nsec) == 0) ? ++ STM32_SIP_SVC_OK : STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t shutdown_scv_handler(void) ++{ ++ DMSG("core %u", get_core_pos()); ++ ++ if (!stm32mp_with_pmic()) { ++ return STM32_SIP_SVC_FAILED; ++ } ++ ++ psci_system_off(); ++ panic(); ++} ++ ++uint32_t pm_domain_scv_handler(uint32_t id, uint32_t enable) ++{ ++ unsigned int pd = id; ++ ++ DMSG("%sable PD %u", enable != 0 ? "En" : "Dis", pd); ++ ++ switch (pd) { ++ case STM32MP1_PD_VSW: ++ case STM32MP1_PD_CORE_RET: ++ case STM32MP1_PD_CORE: ++ break; ++ default: ++ return STM32_SIP_SVC_INVALID_PARAMS; ++ } ++ ++ stm32mp1_set_pm_domain_state(pd, enable); ++ ++ return STM32_SIP_SVC_OK; ++} ++ ++#ifdef CFG_TEE_CORE_DEBUG ++uint32_t pm_set_lp_state_scv_handler(uint32_t request, uint32_t state) ++{ ++ uint32_t power_mode; ++ ++ switch (request) { ++ case STM32_OEM_SVC_LP_FORCE_SUSPEND_PARAMS: ++ DMSG("Set suspend mode to %u", state); ++ power_mode = PSCI_MODE_SYSTEM_SUSPEND; ++ break; ++ case STM32_OEM_SVC_LP_FORCE_OFF_PARAMS: ++ DMSG("Set off mode to %u", state); ++ power_mode = PSCI_MODE_SYSTEM_OFF; ++ break; ++ default: ++ return STM32_OEM_SVC_INVALID_PARAMS; ++ } ++ ++ if (stm32mp1_set_lp_deepest_soc_mode(power_mode, state) < 0) { ++ return STM32_OEM_SVC_FAILED; ++ } ++ ++ return STM32_OEM_SVC_OK; ++} ++#else ++uint32_t pm_set_lp_state_scv_handler(uint32_t __unused mode, ++ uint32_t __unused state) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++#endif +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.h b/core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.h +new file mode 100644 +index 0000000..3d7d247 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/low_power_svc.h +@@ -0,0 +1,55 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2018, STMicroelectronics ++ */ ++ ++#ifndef LOW_POWER_SVC_H ++#define LOW_POWER_SVC_H ++ ++#include ++#include ++ ++#ifdef CFG_STM32_LOWPOWER_SIP ++uint32_t sr_mode_scv_handler(uint32_t x1, uint32_t x2); ++uint32_t cstop_scv_handler(struct sm_ctx *nsec, ++ uint32_t x1, uint32_t x2, uint32_t x3); ++uint32_t standby_scv_handler(struct sm_ctx *nsec, ++ uint32_t x1, uint32_t x2, uint32_t x3); ++uint32_t shutdown_scv_handler(void); ++uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2); ++ ++uint32_t pm_set_lp_state_scv_handler(uint32_t x1, uint32_t x2); ++#else ++uint32_t sr_mode_scv_handler(uint32_t x1 __unused, uint32_t x2 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t cstop_scv_handler(struct sm_ctx *nsec __unused, uint32_t x1 __unused, ++ uint32_t x2 __unused, uint32_t x3 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t standby_scv_handler(struct sm_ctx *nsec __unused, uint32_t x1 __unused, ++ uint32_t x2 __unused, uint32_t x3 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t shutdown_scv_handler(void) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t pm_domain_scv_handler(uint32_t x1 __unused, uint32_t x2 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++ ++uint32_t pm_set_lp_state_scv_handler(uint32_t x1 __unused, uint32_t x2 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++#endif /* CFG_STM32_LOWPOWER_SIP */ ++#endif /* LOW_POWER_SVC_H */ +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.c b/core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.c +new file mode 100644 +index 0000000..6c78d82 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.c +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2018, STMicroelectronics ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pwr_svc.h" ++#include "stm32mp1_smc.h" ++ ++struct pwr_reg_prop { ++ uint32_t offset; ++ uint32_t mask; ++}; ++ ++#define PWR_ALLOWED_MASK(_off, _mask) { .offset = (_off), .mask = (_mask), } ++ ++static const struct pwr_reg_prop allowed_regs[] = { ++ PWR_ALLOWED_MASK(PWR_CR3_OFF, PWR_CR3_VBE | PWR_CR3_VBRS | ++ PWR_CR3_USB33DEN | ++ PWR_CR3_REG18EN | PWR_CR3_REG11EN), ++ PWR_ALLOWED_MASK(PWR_WKUPCR_OFF, PWR_WKUPCR_MASK), ++ PWR_ALLOWED_MASK(PWR_MPUWKUPENR_OFF, PWR_MPUWKUPENR_MASK), ++}; ++ ++uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) ++{ ++ uint32_t req = x1; ++ uint32_t offset = x2; ++ uint32_t value = x3; ++ vaddr_t va = 0; ++ uint32_t allowed = 0; ++ unsigned int i = 0; ++ ++ /* ++ * Argument x2 can be either the register physical address of the ++ * register offset toward PWR_BASE. ++ */ ++ if ((offset & ~PWR_OFFSET_MASK) != 0) { ++ if ((offset & ~PWR_OFFSET_MASK) != PWR_BASE) ++ return STM32_SIP_SVC_INVALID_PARAMS; ++ ++ offset &= PWR_OFFSET_MASK; ++ } ++ ++ DMSG("PWR service: %s 0x%" PRIx32 " at offset 0x%" PRIx32, ++ req == STM32_SIP_SVC_REG_WRITE ? "write" : ++ req == STM32_SIP_SVC_REG_SET ? "set" : "clear", ++ value, offset); ++ ++ for (i = 0; i < ARRAY_SIZE(allowed_regs); i++) { ++ if (offset != allowed_regs[i].offset) ++ continue; ++ ++ va = stm32_pwr_base() + offset; ++ allowed = allowed_regs[i].mask; ++ value &= allowed; ++ ++ switch (req) { ++ case STM32_SIP_SVC_REG_WRITE: ++ io_mask32_stm32shregs(va, value, allowed); ++ FMSG("wrt off %" PRIx32 "=%" PRIx32 " => %" PRIx32, ++ offset, value, io_read32(va)); ++ return STM32_SIP_SVC_OK; ++ case STM32_SIP_SVC_REG_SET: ++ io_setbits32_stm32shregs(va, value); ++ FMSG("set off %" PRIx32 "=%" PRIx32 " => %" PRIx32, ++ offset, value, io_read32(va)); ++ return STM32_SIP_SVC_OK; ++ case STM32_SIP_SVC_REG_CLEAR: ++ io_clrbits32_stm32shregs(va, value); ++ FMSG("clr off %" PRIx32 "=%" PRIx32 " => %" PRIx32, ++ offset, value, io_read32(va)); ++ return STM32_SIP_SVC_OK; ++ default: ++ return STM32_SIP_SVC_INVALID_PARAMS; ++ } ++ } ++ ++ return STM32_SIP_SVC_INVALID_PARAMS; ++} +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.h b/core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.h +new file mode 100644 +index 0000000..429d620 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/pwr_svc.h +@@ -0,0 +1,22 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2017-2018, STMicroelectronics ++ */ ++ ++#ifndef __PWR_SVC_H__ ++#define __PWR_SVC_H__ ++ ++#include ++ ++#ifdef CFG_STM32_PWR_SIP ++uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); ++#else ++static inline uint32_t pwr_scv_handler(uint32_t x1 __unused, ++ uint32_t x2 __unused, ++ uint32_t x3 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++#endif ++ ++#endif /* __PWR_SVC_H__*/ +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c b/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c +new file mode 100644 +index 0000000..362e6d6 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c +@@ -0,0 +1,195 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rcc_svc.h" ++#include "stm32mp1_smc.h" ++ ++#undef FULL_RCC_ACCESS ++ ++static bool offset_is_clear_register(uint32_t __maybe_unused offset) ++{ ++#ifdef FULL_RCC_ACCESS ++ switch (offset) { ++ case RCC_OCENCLRR: ++ case RCC_MP_SREQCLRR: ++ case RCC_APB5RSTCLRR: ++ case RCC_AHB5RSTCLRR: ++ case RCC_MP_APB5ENCLRR: ++ case RCC_MP_AHB5ENCLRR: ++ case RCC_MP_APB5LPENCLRR: ++ case RCC_MP_AHB5LPENCLRR: ++ case RCC_MP_IWDGFZCLRR: ++ return true; ++ default: ++ return false; ++ } ++#else ++ /* All allowed registers are non set/clear registers */ ++ return false; ++#endif ++} ++ ++static void access_allowed_mask(uint32_t request, uint32_t offset, ++ uint32_t value, uint32_t allowed_mask) ++{ ++ vaddr_t va = stm32_rcc_base() + offset; ++ ++ if (!allowed_mask) ++ return; ++ ++ switch (request) { ++ case STM32_SIP_SVC_REG_WRITE: ++ if (offset_is_clear_register(offset)) { ++ /* CLR registers show SET state, not CLR state */ ++ io_write32(va, value & allowed_mask); ++ } else { ++ io_mask32_stm32shregs(va, value, allowed_mask); ++ } ++ FMSG("wrt 0x%" PRIx32 "=0x%" PRIx32 " => 0x%" PRIx32, ++ offset, value, io_read32(va)); ++ break; ++ ++ case STM32_SIP_SVC_REG_SET: ++ if (offset_is_clear_register(offset)) { ++ /* CLR registers show SET state, not CLR state */ ++ io_write32(va, value & allowed_mask); ++ } else { ++ io_setbits32_stm32shregs(va, value & allowed_mask); ++ } ++ FMSG("set 0x%" PRIx32 "=0x%" PRIx32 " => 0x%" PRIx32, ++ offset, value, io_read32(va)); ++ break; ++ ++ case STM32_SIP_SVC_REG_CLEAR: ++ /* Nothing to do on CLR registers */ ++ if (!offset_is_clear_register(offset)) ++ io_clrbits32_stm32shregs(va, value & allowed_mask); ++ FMSG("clear 0x%" PRIx32 "=0x%" PRIx32 " => 0x%" PRIx32, ++ offset, value, io_read32(va)); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void 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; ++ case RCC_MP_GCR: ++ allowed_mask = RCC_MP_GCR_BOOT_MCU; ++ break; ++ ++#ifdef FULL_RCC_ACCESS ++ case RCC_OCENSETR: ++ case RCC_OCENCLRR: ++ case RCC_HSICFGR: ++ case RCC_CSICFGR: ++ case RCC_MP_BOOTCR: /* Allowed MPU/MCU reboot cfg */ ++ case RCC_MP_GCR: /* Allowed MPU/MCU reboot cfg */ ++ case RCC_MP_GRSTCSETR: /* Allowed MCU and system reset */ ++ case RCC_BR_RSTSCLRR: /* Allowed system reset status */ ++ case RCC_MC_RSTSCLRR: /* Allowed system reset status */ ++ case RCC_MP_RSTSCLRR: /* Allowed system reset status */ ++ case RCC_BDCR: ++ case RCC_RDLSICR: ++ case RCC_APB5RSTSETR: ++ case RCC_APB5RSTCLRR: ++ case RCC_MP_APB5ENSETR: ++ case RCC_MP_APB5ENCLRR: ++ case RCC_MP_APB5LPENSETR: ++ case RCC_MP_APB5LPENCLRR: ++ case RCC_AHB5RSTSETR: ++ case RCC_AHB5RSTCLRR: ++ case RCC_MP_AHB5ENSETR: ++ case RCC_MP_AHB5ENCLRR: ++ case RCC_MP_AHB5LPENSETR: ++ case RCC_MP_AHB5LPENCLRR: ++ case RCC_RTCDIVR: ++ case RCC_I2C46CKSELR: ++ case RCC_SPI6CKSELR: ++ case RCC_UART1CKSELR: ++ case RCC_RNG1CKSELR: ++ case RCC_MP_IWDGFZSETR: ++ case RCC_MP_IWDGFZCLRR: ++ allowed_mask = UINT32_MAX; ++ break; ++#endif ++ default: ++ panic(); ++ } ++ ++ access_allowed_mask(request, offset, value, allowed_mask); ++} ++ ++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; ++ ++ /* ++ * Argument x2 can be either the register physical address of the ++ * register offset toward RCC_BASE. ++ */ ++ if (offset & ~RCC_OFFSET_MASK) { ++ if ((offset & ~RCC_OFFSET_MASK) != RCC_BASE) ++ return STM32_SIP_SVC_INVALID_PARAMS; ++ ++ offset &= RCC_OFFSET_MASK; ++ } ++ ++ DMSG_RAW("RCC service: %s 0x%" PRIx32 " at offset 0x%" PRIx32, ++ request == STM32_SIP_SVC_REG_WRITE ? "write" : ++ request == STM32_SIP_SVC_REG_SET ? "set" : "clear", ++ value, offset); ++ ++ raw_allowed_access_request(request, offset, value); ++ ++ return STM32_SIP_SVC_OK; ++} ++ ++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_SIP_SVC_RCC_OPP_SET: ++ if (stm32mp1_set_opp_khz(opp)) ++ return STM32_SIP_SVC_FAILED; ++ break; ++ ++ case STM32_SIP_SVC_RCC_OPP_ROUND: ++ if(stm32mp1_round_opp_khz(&opp)) ++ return STM32_SIP_SVC_FAILED; ++ ++ if (MUL_OVERFLOW(opp, 1000, res)) ++ return STM32_SIP_SVC_FAILED; ++ break; ++ ++ default: ++ return STM32_SIP_SVC_INVALID_PARAMS; ++ } ++ ++ return STM32_SIP_SVC_OK; ++} +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.h b/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.h +new file mode 100644 +index 0000000..873458f +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics ++ */ ++ ++#ifndef RCC_SVC_H ++#define RCC_SVC_H ++ ++#include ++ ++#ifdef CFG_STM32_RCC_SIP ++uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); ++uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res); ++#else ++static inline uint32_t rcc_scv_handler(uint32_t x1 __unused, ++ uint32_t x2 __unused, ++ uint32_t x3 __unused) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++static inline uint32_t rcc_opp_scv_handler(uint32_t x1 __unused, ++ uint32_t x2 __unused, ++ uint32_t *res __unused) ++ ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++#endif ++ ++#endif /*RCC_SVC_H*/ +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h b/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h +index 7f16160..86deb59 100644 +--- a/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h +@@ -14,7 +14,7 @@ + #define STM32_SIP_SVC_VERSION_MAJOR 0x0 + #define STM32_SIP_SVC_VERSION_MINOR 0x1 + +-#define STM32_SIP_SVC_FUNCTION_COUNT 0x3 ++#define STM32_SIP_SVC_FUNCTION_COUNT 12 + + /* STM32 SIP service generic return codes */ + #define STM32_SIP_SVC_OK 0x0 +@@ -72,6 +72,51 @@ + #define STM32_SIP_SVC_FUNC_VERSION 0xff03 + + /* ++ * SIP function STM32_SIP_SVC_FUNC_RCC ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a1: (input) Service ID (STM32_SIP_SVC_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_SIP_SVC_FUNC_RCC 0x1000 ++ ++/* Service ID for STM32_SIP_FUNC_RCC */ ++#define STM32_SIP_SVC_REG_READ 0x0 ++#define STM32_SIP_SVC_REG_WRITE 0x1 ++#define STM32_SIP_SVC_REG_SET 0x2 ++#define STM32_SIP_SVC_REG_CLEAR 0x3 ++ ++/* ++ * SIP functions STM32_SIP_SVC_FUNC_CAL ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a1: (input) Clock ID (from DT clock bindings) ++ */ ++#define STM32_SIP_SVC_FUNC_CAL 0x1002 ++ ++/* ++ * SIP functions STM32_SIP_FUNC_PWR ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a1: (input) Service ID (STM32_SIP_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_SIP_SVC_FUNC_PWR 0x1001 ++ ++/* Service ID for STM32_SIP_SVC_FUNC_RCC/_PWR */ ++#define STM32_SIP_SVC_REG_READ 0x0 ++#define STM32_SIP_SVC_REG_WRITE 0x1 ++#define STM32_SIP_SVC_REG_SET 0x2 ++#define STM32_SIP_SVC_REG_CLEAR 0x3 ++ ++/* + * SIP functions STM32_SIP_SVC_FUNC_BSEC + * + * Argument a0: (input) SMCCC function ID +@@ -91,6 +136,91 @@ + #define STM32_SIP_SVC_BSEC_WRLOCK_OTP 0x5 + + /* ++ * SIP functions STM32_SIP_FUNC_SR_MODE ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a1: (unused) ++ * Argument a2: (input) Target selfrefresh mode ++ */ ++#define STM32_SIP_FUNC_SR_MODE 0x1004 ++ ++/* DDR Self-Refresh modes */ ++#define STM32_SIP_SR_MODE_SSR 0x0 ++#define STM32_SIP_SR_MODE_ASR 0x1 ++#define STM32_SIP_SR_MODE_HSR 0x2 ++ ++/* ++ * SIP functions STM32_SIP_FUNC_CSTOP ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a1: (unused) ++ * Argument a2: (unused) ++ * Argument a3: (input) Target SoC mode ++ */ ++#define STM32_SIP_FUNC_CSTOP 0x1005 ++ ++/* Valid SoC modes used for CSTOP, */ ++#define STM32_SIP_CSLEEP_RUN 0x0 ++#define STM32_SIP_CSTOP_ALLOW_STOP 0x1 ++#define STM32_SIP_CSTOP_ALLOW_LP_STOP 0x2 ++#define STM32_SIP_CSTOP_ALLOW_LPLV_STOP 0x3 ++#define STM32_SIP_CSTOP_ALLOW_STANDBY 0x4 ++#define STM32_SIP_CSTOP_ALLOW_STANDBY_DDR_OFF 0x5 ++#define STM32_SIP_CSTOP_SHUTDOWN 0x6 ++ ++/* ++ * SIP functions STM32_SIP_FUNC_STANDBY ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a1: (unused) ++ * Argument a2: (unused) ++ * Argument a3: (input) non null only for DDR off standby ++ */ ++#define STM32_SIP_FUNC_STANDBY 0x1006 ++ ++/* ++ * SIP function STM32_SIP_FUNC_SHUTDOWN ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ */ ++#define STM32_SIP_FUNC_SHUTDOWN 0x1007 ++ ++/* ++ * SIP function STM32_SIP_FUNC_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 eanble target domain ++ */ ++#define STM32_SIP_FUNC_PD_DOMAIN 0x1008 ++ ++/* Valid IDs for power domain for function STM32_SIP_FUNC_PD_DOMAIN */ ++#define STM32_SIP_PD_VSW 0x0 ++#define STM32_SIP_PD_CORE_RET 0x1 ++#define STM32_SIP_PD_CORE 0x2 ++#define STM32_SIP_PD_MAX_PM_DOMAIN 0x3 ++ ++/* ++ * SIP function STM32_SIP_FUNC_RCC_OPP. ++ * ++ * Argument a0: (input) SMCC ID. ++ * (output) Status return code. ++ * Argument a1: (input) Service ID (STM32_SIP_RCC_OPP_xxx). ++ * (output) Rounded frequency, if applicable. ++ * Argument a2: (input) Requested frequency. ++ */ ++#define STM32_SIP_SVC_FUNC_RCC_OPP 0x1009 ++ ++/* Service ID for STM32_SIP_FUNC_RCC_OPP */ ++#define STM32_SIP_SVC_RCC_OPP_SET 0x0 ++#define STM32_SIP_SVC_RCC_OPP_ROUND 0x1 ++ ++/* + * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT0 + * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT1 + * +@@ -101,4 +231,68 @@ + #define STM32_SIP_SVC_FUNC_SCMI_AGENT0 0x2000 + #define STM32_SIP_SVC_FUNC_SCMI_AGENT1 0x2001 + ++/* ++ * OEM Functions ++ */ ++#define STM32_OEM_SVC_VERSION_MAJOR 0x0 ++#define STM32_OEM_SVC_VERSION_MINOR 0x1 ++ ++#define STM32_OEM_SVC_FUNCTION_COUNT 1 ++ ++/* Use the same UID as for SiP service */ ++#define STM32_OEM_SVC_UID_0 STM32_SIP_SVC_UID_0 ++#define STM32_OEM_SVC_UID_1 STM32_SIP_SVC_UID_1 ++#define STM32_OEM_SVC_UID_2 STM32_SIP_SVC_UID_2 ++#define STM32_OEM_SVC_UID_3 STM32_SIP_SVC_UID_3 ++ ++ ++/* OEM service generic return codes */ ++#define STM32_OEM_SVC_OK 0x0 ++#define STM32_OEM_SVC_NOT_SUPPORTED 0xffffffffU ++#define STM32_OEM_SVC_FAILED 0xfffffffeU ++#define STM32_OEM_SVC_INVALID_PARAMS 0xfffffffdU ++ ++/* ++ * OEM function STM32_OEM_FUNC_CALL_COUNT ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) Count of defined function IDs ++ */ ++#define STM32_OEM_SVC_FUNC_CALL_COUNT 0xff00 ++ ++/* ++ * OEM function STM32_OEM_SVC_FUNC_UID ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) Lowest 32bit of the stm32mp1 OEM service UUID ++ * Argument a1: (output) Next 32bit of the stm32mp1 OEM service UUID ++ * Argument a2: (output) Next 32bit of the stm32mp1 OEM service UUID ++ * Argument a3: (output) Last 32bit of the stm32mp1 OEM service UUID ++ */ ++#define STM32_OEM_SVC_FUNC_UID 0xff01 ++ ++/* ++ * OEM function STM32_OEM_FUNC_VERSION ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) STM32 OEM service major ++ * Argument a1: (output) STM32 OEM service minor ++ */ ++#define STM32_OEM_SVC_FUNC_VERSION 0xff03 ++ ++/* ++ * OEM function STM32_OEM_SVC_FUNC_LP_FORCE_PARAMS ++ * ++ * Argument a0: (input) SMCC ID ++ * (output) status return code ++ * Argument a2: (input) ID of the mode: suspend or shutdown (off) ++ * Argument a3: (input) ID of the power state to be reached for the mode ++ * Refer to stm32mp1 power bindings. ++ */ ++#define STM32_OEM_SVC_FUNC_LP_FORCE_PARAMS 0x0f800 ++ ++/* Valid IDs for power mode in STM32_OEM_SVC_FUNC_LP_FORCE_PARAMS */ ++#define STM32_OEM_SVC_LP_FORCE_SUSPEND_PARAMS 0 ++#define STM32_OEM_SVC_LP_FORCE_OFF_PARAMS 1 ++ + #endif /* __STM32MP1_SMC_H__*/ +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c b/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c +index 49d23ff..f5f131d 100644 +--- a/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c +@@ -7,11 +7,32 @@ + #include + #include + #include ++#include + + #include "bsec_svc.h" ++#include "low_power_svc.h" ++#include "pwr_svc.h" ++#include "rcc_svc.h" + #include "stm32mp1_smc.h" + +-static enum sm_handler_ret sip_service(struct sm_ctx *ctx __unused, ++#ifdef CFG_STM32_CLKCALIB_SIP ++static uint32_t calib_scv_handler(uint32_t x1) ++{ ++ unsigned long clock_id = x1; ++ ++ if (stm32mp_start_clock_calib(clock_id)) ++ return STM32_SIP_SVC_FAILED; ++ ++ return STM32_SIP_SVC_OK; ++} ++#else ++static uint32_t calib_scv_handler(uint32_t __unused x1) ++{ ++ return STM32_SIP_SVC_FAILED; ++} ++#endif ++ ++static enum sm_handler_ret sip_service(struct sm_ctx *ctx, + struct thread_smc_args *args) + { + switch (OPTEE_SMC_FUNC_NUM(args->a0)) { +@@ -39,6 +60,60 @@ static enum sm_handler_ret sip_service(struct sm_ctx *ctx __unused, + case STM32_SIP_SVC_FUNC_BSEC: + bsec_main(args); + break; ++ case STM32_SIP_SVC_FUNC_RCC: ++ args->a0 = rcc_scv_handler(args->a1, args->a2, args->a3); ++ break; ++ case STM32_SIP_SVC_FUNC_RCC_OPP: ++ args->a0 = rcc_opp_scv_handler(args->a1, args->a2, &args->a1); ++ break; ++ case STM32_SIP_SVC_FUNC_CAL: ++ args->a0 = calib_scv_handler(args->a1); ++ break; ++ case STM32_SIP_SVC_FUNC_PWR: ++ args->a0 = pwr_scv_handler(args->a1, args->a2, args->a3); ++ break; ++ case STM32_SIP_FUNC_SR_MODE: ++ args->a0 = sr_mode_scv_handler(args->a1, args->a2); ++ break; ++ case STM32_SIP_FUNC_CSTOP: ++ args->a0 = cstop_scv_handler(ctx, args->a1, args->a2, args->a3); ++ break; ++ case STM32_SIP_FUNC_STANDBY: ++ args->a0 = standby_scv_handler(ctx, args->a1, args->a2, args->a3); ++ break; ++ case STM32_SIP_FUNC_SHUTDOWN: ++ args->a0 = shutdown_scv_handler(); ++ break; ++ case STM32_SIP_FUNC_PD_DOMAIN: ++ args->a0 = pm_domain_scv_handler(args->a1, args->a2); ++ break; ++ default: ++ return SM_HANDLER_PENDING_SMC; ++ } ++ ++ return SM_HANDLER_SMC_HANDLED; ++} ++ ++static enum sm_handler_ret oem_service(struct sm_ctx *ctx __unused, ++ struct thread_smc_args *args) ++{ ++ switch (OPTEE_SMC_FUNC_NUM(args->a0)) { ++ case STM32_OEM_SVC_FUNC_CALL_COUNT: ++ args->a0 = STM32_OEM_SVC_FUNCTION_COUNT; ++ break; ++ case STM32_OEM_SVC_FUNC_VERSION: ++ args->a0 = STM32_OEM_SVC_VERSION_MAJOR; ++ args->a1 = STM32_OEM_SVC_VERSION_MINOR; ++ break; ++ case STM32_OEM_SVC_FUNC_UID: ++ args->a0 = STM32_OEM_SVC_UID_0; ++ args->a1 = STM32_OEM_SVC_UID_1; ++ args->a2 = STM32_OEM_SVC_UID_2; ++ args->a3 = STM32_OEM_SVC_UID_3; ++ break; ++ case STM32_OEM_SVC_FUNC_LP_FORCE_PARAMS: ++ args->a0 = pm_set_lp_state_scv_handler(args->a1, args->a2); ++ break; + default: + return SM_HANDLER_PENDING_SMC; + } +@@ -56,6 +131,8 @@ enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) + switch (OPTEE_SMC_OWNER_NUM(args->a0)) { + case OPTEE_SMC_OWNER_SIP: + return sip_service(ctx, args); ++ case OPTEE_SMC_OWNER_OEM: ++ return oem_service(ctx, args); + default: + return SM_HANDLER_PENDING_SMC; + } +diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk b/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk +index 6e1abcb..acccda1 100644 +--- a/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk ++++ b/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk +@@ -2,3 +2,6 @@ global-incdirs-y += . + + srcs-y += stm32mp1_svc_setup.c + srcs-$(CFG_STM32_BSEC_SIP) += bsec_svc.c ++srcs-$(CFG_STM32_LOWPOWER_SIP) += low_power_svc.c ++srcs-$(CFG_STM32_PWR_SIP) += pwr_svc.c ++srcs-$(CFG_STM32_RCC_SIP) += rcc_svc.c +diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h +index cf68f45..2b4bd95 100644 +--- a/core/arch/arm/plat-stm32mp1/platform_config.h ++++ b/core/arch/arm/plat-stm32mp1/platform_config.h +@@ -8,14 +8,45 @@ + + #include + ++/* Enable/disable use of the core0 reset control from RCC */ ++#undef STM32MP1_USE_MPU0_RESET ++ + /* Make stacks aligned to data cache line length */ + #define STACK_ALIGNMENT 32 + ++#if defined(CFG_WITH_PAGER) ++#if defined(CFG_WITH_LPAE) ++/* ++ * Optimize unpaged memory size: ++ * - one table for the level2 table for overall vmem range ++ * - two tables for TEE RAM fine grain mapping [2ffc.0000 301f.ffff] ++ * - one table for a 2MByte dynamic shared virtual memory (SHM_VASPACE) ++ */ ++#define MAX_XLAT_TABLES 4 ++#else ++/* ++ * Optimize unpaged memory size: ++ * - two tables for TEE RAM mapping [2ffc.0000 300f.ffff] ++ * - one table for secure internal RAMs (PM: ROMed core TEE RAM) ++ * - one table for non-secure internal RAMs (PM: DDR first page) ++ * - two tables for a 2MByte dynamiq shared virtual memory (SHM_VASPACE) ++ */ ++#define MAX_XLAT_TABLES 6 ++#endif /*CFG_WITH_LPAE*/ ++#else ++/* Be generous with this setup that has plenty of secure RAM */ ++#define MAX_XLAT_TABLES 10 ++#endif /*CFG_WITH_PAGER*/ ++ + /* SoC interface registers base address */ ++#define BKPSRAM_BASE 0x54000000 + #define BSEC_BASE 0x5c005000 + #define ETZPC_BASE 0x5c007000 + #define CRYP1_BASE 0x54001000 ++#define DBGMCU_BASE 0x50081000 + #define DDR_BASE 0xc0000000ul ++#define DDRCTRL_BASE 0x5a003000 ++#define DDRPHYC_BASE 0x5a004000 + #define GIC_BASE 0xa0021000ul + #define GPIOA_BASE 0x50002000 + #define GPIOB_BASE 0x50003000 +@@ -39,9 +70,24 @@ + #define RNG1_BASE 0x54003000 + #define RTC_BASE 0x5c004000 + #define SPI6_BASE 0x5c001000 ++#define STGEN_BASE 0x5c008000 + #define SYSCFG_BASE 0x50020000 + #define SYSRAM_BASE 0x2ffc0000 + #define TAMP_BASE 0x5c00a000 ++#define TIM1_BASE 0x44000000 ++#define TIM2_BASE 0x40000000 ++#define TIM3_BASE 0x40001000 ++#define TIM4_BASE 0x40002000 ++#define TIM5_BASE 0x40003000 ++#define TIM6_BASE 0x40004000 ++#define TIM7_BASE 0x40005000 ++#define TIM8_BASE 0x44001000 ++#define TIM12_BASE 0x40006000 ++#define TIM13_BASE 0x40007000 ++#define TIM14_BASE 0x40008000 ++#define TIM15_BASE 0x44006000 ++#define TIM16_BASE 0x44007000 ++#define TIM17_BASE 0x44008000 + #define TZC_BASE 0x5c006000 + #define UART1_BASE 0x5c000000 + #define UART2_BASE 0x4000e000 +@@ -52,6 +98,9 @@ + #define UART7_BASE 0x40018000 + #define UART8_BASE 0x40019000 + ++/* DDR expected size if not found in device tree */ ++#define STM32MP1_DDR_SIZE_DFLT (1 * 1024 * 1024 * 1024) ++ + /* Console configuration */ + #define STM32MP1_DEBUG_USART_BASE UART4_BASE + #define GIC_SPI_UART4 84 +@@ -65,16 +114,21 @@ + + #define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) + +-#define DATA0_OTP 0 +-#define PART_NUMBER_OTP 1 +-#define MONOTONIC_OTP 4 +-#define NAND_OTP 9 +-#define UID0_OTP 13 +-#define UID1_OTP 14 +-#define UID2_OTP 15 +-#define HW2_OTP 18 ++#define CFG0_OTP "cfg0_otp" ++#define CFG0_OTP_SECURED_POS 6 + +-#define DATA0_OTP_SECURED_POS 6 ++#define HW2_OTP "hw2_otp" ++#define HW2_OTP_IWDG_HW_ENABLE_SHIFT 3 ++#define HW2_OTP_IWDG_FZ_STOP_SHIFT 5 ++#define HW2_OTP_IWDG_FZ_STANDBY_SHIFT 7 ++ ++#define PART_NUMBER_OTP "part_number_otp" ++#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) ++#define PART_NUMBER_OTP_PART_SHIFT 0 ++ ++#define HW2_OTP_IWDG_HW_ENABLE_SHIFT 3 ++#define HW2_OTP_IWDG_FZ_STOP_SHIFT 5 ++#define HW2_OTP_IWDG_FZ_STANDBY_SHIFT 7 + + /* GIC resources */ + #define GIC_SIZE 0x2000 +@@ -84,11 +138,14 @@ + #define GIC_NON_SEC_SGI_0 0 + #define GIC_SEC_SGI_0 8 + #define GIC_SEC_SGI_1 9 ++#define GIC_SPI_SEC_PHY_TIMER 29 + + #define TARGET_CPU0_GIC_MASK BIT(0) + #define TARGET_CPU1_GIC_MASK BIT(1) + #define TARGET_CPUS_GIC_MASK GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0) + ++#define STM32MP_GIC_PRIORITY_CSTOP 0xc0 ++ + /* + * GPIO banks: 11 non secure banks (A to K) and 1 secure bank (Z) + * Bank register's base address is computed from the bank ID listed here. +@@ -116,6 +173,16 @@ + #define GPIO_BANK_K 10U + #define GPIO_BANK_Z 25U + ++/* IWDG resources */ ++#define IWDG1_INST 0 ++#define IWDG2_INST 1 ++ ++#define STM32MP1_IRQ_IWDG1 182U ++#define STM32MP1_IRQ_IWDG2 183U ++ ++/* RCC platform resources */ ++#define RCC_WAKEUP_IT 177 ++ + /* TAMP resources */ + #define TAMP_BKP_REGISTER_OFF 0x100 + +@@ -140,6 +207,24 @@ + #define USART3_BASE UART3_BASE + #define USART6_BASE UART6_BASE + ++/* DBGMCU resources */ ++#define DBGMCU_IDC 0x0 ++#define DBGMCU_IDC_DEV_ID_MASK GENMASK_32(11, 0) ++#define DBGMCU_IDC_REV_ID_MASK GENMASK_32(31, 16) ++#define DBGMCU_IDC_REV_ID_SHIFT 16 ++ ++/* BKPSRAM layout */ ++#define BKPSRAM_SIZE 0x1000 ++#define BKPSRAM_PM_OFFSET 0x000 ++#define BKPSRAM_PM_SIZE (BKPSRAM_PM_MAILBOX_SIZE + \ ++ BKPSRAM_PM_CONTEXT_SIZE) ++ ++#define BKPSRAM_PM_MAILBOX_OFFSET BKPSRAM_PM_OFFSET ++#define BKPSRAM_PM_MAILBOX_SIZE 0x100 ++#define BKPSRAM_PM_CONTEXT_OFFSET (BKPSRAM_PM_MAILBOX_OFFSET + \ ++ BKPSRAM_PM_MAILBOX_SIZE) ++#define BKPSRAM_PM_CONTEXT_SIZE 0xF00 ++ + /* SYSRAM layout */ + #define SYSRAM_SIZE 0x40000 + #define SYSRAM_NS_SIZE (SYSRAM_SIZE - SYSRAM_SEC_SIZE) +@@ -153,4 +238,32 @@ + #define SYSRAM_SEC_SIZE SYSRAM_SIZE + #endif + ++/* SoC part numbers and revisions */ ++#define STM32MP1_CHIP_ID 0x500 ++ ++#define STM32MP157C_PART_NB 0x05000000 ++#define STM32MP157A_PART_NB 0x05000001 ++#define STM32MP153C_PART_NB 0x05000024 ++#define STM32MP153A_PART_NB 0x05000025 ++#define STM32MP151C_PART_NB 0x0500002E ++#define STM32MP151A_PART_NB 0x0500002F ++#define STM32MP157F_PART_NB 0x05000080 ++#define STM32MP157D_PART_NB 0x05000081 ++#define STM32MP153F_PART_NB 0x050000A4 ++#define STM32MP153D_PART_NB 0x050000A5 ++#define STM32MP151F_PART_NB 0x050000AE ++#define STM32MP151D_PART_NB 0x050000AF ++ ++#define STM32MP1_CHIP_DEFAULT_VERSION 0 ++ ++#define STM32MP1_REV_A 0x00001000 ++#define STM32MP1_REV_B 0x00002000 ++#define STM32MP1_REV_Z 0x00002001 ++ ++/* OPP */ ++#define PLAT_OPP_ID1 1U ++#define PLAT_OPP_ID2 2U ++#define PLAT_MAX_OPP_NB 2U ++#define PLAT_MAX_PLLCFG_NB 6U ++ + #endif /*PLATFORM_CONFIG_H*/ +diff --git a/core/arch/arm/plat-stm32mp1/pm/context.c b/core/arch/arm/plat-stm32mp1/pm/context.c +new file mode 100644 +index 0000000..7a518a3 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/context.c +@@ -0,0 +1,521 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "context.h" ++#include "power.h" ++ ++#define TRAINING_AREA_SIZE 64 ++ ++/* ++ * STANDBY_CONTEXT_MAGIC0: ++ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer. ++ * ++ * STANDBY_CONTEXT_MAGIC1: ++ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer ++ * and PLL1 dual OPP settings structure (86 bytes). ++ */ ++#define STANDBY_CONTEXT_MAGIC0 (0x0001 << 16) ++#define STANDBY_CONTEXT_MAGIC1 (0x0002 << 16) ++ ++#if CFG_STM32MP15_PM_CONTEX_VERSION == 1 ++#define STANDBY_CONTEXT_MAGIC (STANDBY_CONTEXT_MAGIC0 | TRAINING_AREA_SIZE) ++#elif CFG_STM32MP15_PM_CONTEX_VERSION == 2 ++#define STANDBY_CONTEXT_MAGIC (STANDBY_CONTEXT_MAGIC1 | TRAINING_AREA_SIZE) ++#else ++#error Invalid value for CFG_STM32MP15_PM_CONTEX_VERSION ++#endif ++ ++#if (PLAT_MAX_OPP_NB != 2) || (PLAT_MAX_PLLCFG_NB != 6) ++#error STANDBY_CONTEXT_MAGIC1 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)) ++ ++/* ++ * Context saved in TEE RAM during lower power sequence. ++ * Can be allocated if to big for static allocation. ++ * ++ * @stgen_cnt_h: Upper 32bit of the STGEN counter ++ * @stgen_cnt_l: Lower 32bit of the STGEN counter ++ * @rtc: RTC time read at suspend ++ */ ++struct pm_context { ++ uint32_t stgen_cnt_h; ++ uint32_t stgen_cnt_l; ++ struct stm32_rtc_calendar rtc; ++}; ++ ++static struct pm_context plat_ctx; ++ ++/* ++ * BKPSRAM contains a mailbox used with early boot stages for resume sequence. ++ * The mailbox content data that must be restored before OP-TEE is resumed. ++ * ++ * @magic: magic value read by early boot stage for consistency ++ * @zq0cr0_zdata: DDRPHY configuration to be restored. ++ * @ddr_training_backup: DDR area saved at suspend and backed up at resume ++ */ ++struct pm_mailbox { ++ uint32_t magic; ++ uint32_t core0_resume_ep; ++ uint32_t zq0cr0_zdata; ++ uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; ++#if CFG_STM32MP15_PM_CONTEX_VERSION >= 2 ++ uint8_t pll1_settings[PLL1_SETTINGS_SIZE]; ++#endif ++}; ++ ++/* ++ * BKPSRAM contains OP-TEE resume instruction sequence which restores ++ * TEE RAM content. The BKPSRAM contains restoration materials ++ * (key, tag) and the resume entry point in restored TEE RAM. ++ */ ++static struct retram_resume_ctx *get_retram_resume_ctx(void) ++{ ++ vaddr_t bkpsram_base = stm32mp_bkpsram_base(); ++ vaddr_t context_base = bkpsram_base + BKPSRAM_PM_CONTEXT_OFFSET; ++ ++ return (struct retram_resume_ctx *)context_base; ++} ++ ++static struct pm_mailbox *get_pm_mailbox(void) ++{ ++ vaddr_t bkpsram_base = stm32mp_bkpsram_base(); ++ vaddr_t mailbox_base = bkpsram_base + BKPSRAM_PM_MAILBOX_OFFSET; ++ ++ return (struct pm_mailbox *)mailbox_base; ++} ++ ++#if TRACE_LEVEL >= TRACE_DEBUG ++static void __maybe_unused dump_context(void) ++{ ++ struct pm_mailbox *mailbox = get_pm_mailbox(); ++ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); ++ ++ stm32_clock_enable(RTCAPB); ++ ++ DMSG("Backup registers: address 0x%" PRIx32 ", magic 0x%" PRIx32, ++ *(uint32_t *)stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS), ++ *(uint32_t *)stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); ++ ++ stm32_clock_disable(RTCAPB); ++ ++ stm32_clock_enable(BKPSRAM); ++ ++ DMSG("BKPSRAM mailbox: 0x%" PRIx32 ", zd 0x%" PRIx32 ", ep 0x%" PRIx32, ++ mailbox->magic, mailbox->zq0cr0_zdata, ++ mailbox->core0_resume_ep); ++ ++ DMSG("BKPSRAM context: teeram backup @%" PRIx32 ", resume @0x%" PRIx32, ++ ctx->teeram_bkp_pa, ctx->resume_pa); ++ ++ stm32_clock_disable(BKPSRAM); ++} ++#else ++static void __maybe_unused dump_context(void) ++{ ++} ++#endif ++ ++/* ++ * Save and restore functions ++ */ ++static void save_time(void) ++{ ++ vaddr_t stgen = stm32mp_stgen_base(); ++ ++ plat_ctx.stgen_cnt_h = io_read32(stgen + CNTCVU_OFFSET); ++ plat_ctx.stgen_cnt_l = io_read32(stgen + CNTCVL_OFFSET); ++ if (plat_ctx.stgen_cnt_l < 10) ++ plat_ctx.stgen_cnt_h = io_read32(stgen + CNTCVU_OFFSET); ++ ++ stm32_clock_enable(RTC); ++ stm32_rtc_get_calendar(&plat_ctx.rtc); ++} ++ ++#if TRACE_LEVEL >= TRACE_DEBUG ++static void print_ccm_decryption_duration(void) ++{ ++ vaddr_t stgen = stm32mp_stgen_base(); ++ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); ++ ++ stm32_clock_enable(BKPSRAM); ++ ++ DMSG("CCM decryption duration %llums", ++ ((unsigned long long)ctx->stgen_cnt * 1000) / ++ io_read32(stgen + CNTFID_OFFSET)); ++ ++ stm32_clock_enable(BKPSRAM); ++} ++#else ++static void print_ccm_decryption_duration(void) ++{ ++} ++#endif ++ ++static void restore_time(void) ++{ ++ struct stm32_rtc_calendar current_calendar = { }; ++ unsigned long long stdby_time_in_ms = 0; ++ unsigned long long cnt = 0; ++ vaddr_t stgen = stm32mp_stgen_base(); ++ struct retram_resume_ctx __maybe_unused *ctx = get_retram_resume_ctx(); ++ ++ stm32_rtc_get_calendar(¤t_calendar); ++ stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, ++ &plat_ctx.rtc); ++ ++ cnt = ((uint64_t)plat_ctx.stgen_cnt_h << 32) | plat_ctx.stgen_cnt_l; ++ cnt += (stdby_time_in_ms * io_read32(stgen + CNTFID_OFFSET)) / 1000U; ++ ++ io_clrbits32(stgen + CNTCR_OFFSET, CNTCR_EN); ++ io_write32(stgen + CNTCVL_OFFSET, (uint32_t)cnt); ++ io_write32(stgen + CNTCVU_OFFSET, (uint32_t)(cnt >> 32)); ++ io_setbits32(stgen + CNTCR_OFFSET, CNTCR_EN); ++ ++ /* Balance clock enable(RTC) at save_time() */ ++ stm32_clock_disable(RTC); ++ ++ print_ccm_decryption_duration(); ++} ++ ++static bool __maybe_unused pm_cb_is_valid(void (*cb)(enum pm_op op, void *hdl), ++ void *hdl) ++{ ++ void *cb_voidp = (void *)(vaddr_t)cb; ++ paddr_t cb_phy = virt_to_phys(cb_voidp); ++ paddr_t hdl_phy = virt_to_phys(hdl); ++ bool valid = false; ++ ++ valid = (phys_to_virt(cb_phy, MEM_AREA_TEE_RAM_RX) == cb_voidp) && ++ ((phys_to_virt(hdl_phy, MEM_AREA_TEE_RAM_RX) == hdl) || ++ (phys_to_virt(hdl_phy, MEM_AREA_TEE_RAM_RO) == hdl) || ++ (phys_to_virt(hdl_phy, MEM_AREA_TEE_RAM_RW) == hdl)); ++ ++ if (!valid) ++ EMSG("pm_cb mandates unpaged arguments %p %p", cb_voidp, hdl); ++ ++ return valid; ++} ++ ++uintptr_t stm32mp_pm_retram_resume_ep(void) ++{ ++ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); ++ ++ return (uintptr_t)&ctx->resume_sequence; ++} ++ ++/* Clear the content of the PM mailbox */ ++void stm32mp_pm_wipe_context(void) ++{ ++ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); ++ struct pm_mailbox *mailbox = get_pm_mailbox(); ++ ++ stm32_clock_enable(BKPSRAM); ++ ++ memset(ctx, 0xa5, sizeof(*ctx)); ++ memset(mailbox, 0xa5, sizeof(*mailbox)); ++ ++ stm32_clock_disable(BKPSRAM); ++} ++ ++static struct mobj *teeram_bkp_mobj; ++ ++static void init_retram_resume_resources(void) ++{ ++ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); ++ size_t __maybe_unused csize = 0; ++ paddr_t __maybe_unused pa = 0; ++ ++ COMPILE_TIME_ASSERT(sizeof(struct pm_mailbox) < ++ BKPSRAM_PM_MAILBOX_SIZE); ++ COMPILE_TIME_ASSERT(sizeof(struct retram_resume_ctx) < ++ BKPSRAM_PM_CONTEXT_SIZE); ++ csize = (vaddr_t)stm32mp_bkpsram_image_end - ++ (vaddr_t)stm32mp_bkpsram_resume; ++ assert((sizeof(*ctx) + csize) < BKPSRAM_PM_CONTEXT_SIZE); ++ ++ teeram_bkp_mobj = mobj_mm_alloc(mobj_sec_ddr, TEE_RAM_PH_SIZE, ++ &tee_mm_sec_ddr); ++ if (!teeram_bkp_mobj) ++ panic(); ++ ++ assert((mobj_get_va(teeram_bkp_mobj, 0) != NULL) && ++ (mobj_get_pa(teeram_bkp_mobj, 0, 0, &pa) == 0)); ++ ++ stm32_clock_enable(BKPSRAM); ++ memset(ctx, 0, sizeof(*ctx)); ++ stm32_clock_disable(BKPSRAM); ++} ++ ++/* ++ * 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 in the PM mailbox with the earlier boot stages. ++ */ ++static void save_ddr_training_area(void) ++{ ++ struct pm_mailbox *mailbox = get_pm_mailbox(); ++ size_t size = sizeof(mailbox->ddr_training_backup); ++ paddr_t pa = DDR_BASE; ++ void *va = phys_to_virt(pa, MEM_AREA_RAM_NSEC); ++ ++ memcpy(&mailbox->ddr_training_backup[0], va, size); ++ ++} ++ ++/* ++ * When returning from STANDBY, warm boot boot stage needs to access to PLL1 ++ * settings. This avoids to re-compute them and optimizes performances. This ++ * structure must then be saved before going to STANDBY in the PM mailbox ++ * shared with the warm boot boot stage. ++ */ ++#if CFG_STM32MP15_PM_CONTEX_VERSION >= 2 ++static void save_pll1_settings(void) ++{ ++ struct pm_mailbox *mailbox = get_pm_mailbox(); ++ size_t size = sizeof(mailbox->pll1_settings); ++ uint8_t *data = &mailbox->pll1_settings[0]; ++ ++ stm32mp1_clk_lp_save_opp_pll1_settings(data, size); ++} ++#endif ++ ++static void load_earlyboot_pm_mailbox(void) ++{ ++ struct pm_mailbox *mailbox = get_pm_mailbox(); ++ ++ COMPILE_TIME_ASSERT(sizeof(struct pm_mailbox) < ++ BKPSRAM_PM_MAILBOX_SIZE); ++ ++ assert(stm32_clock_is_enabled(BKPSRAM)); ++ ++ memset(mailbox, 0, sizeof(*mailbox)); ++ ++ mailbox->zq0cr0_zdata = get_ddrphy_calibration(); ++ ++ save_ddr_training_area(); ++ ++#if CFG_STM32MP15_PM_CONTEX_VERSION >= 2 ++ save_pll1_settings(); ++#endif ++} ++ ++#if defined(CFG_STM32_RNG) && defined(CFG_STM32_CRYP) ++/* ++ * CRYP relies on standard format for CCM IV/B0/CRT0 data. Our sequence uses ++ * no AAD, 4 bytes to encode the payload byte size and a 11 byte nonce. ++ */ ++#define PM_CCM_Q 4 ++#define PM_CCM_Q_FLAGS (PM_CCM_Q - 1) ++#define PM_CCM_TAG_LEN 16 ++#define PM_CCM_TAG_FLAGS (((PM_CCM_TAG_LEN - 2) / 2) << 3) ++ ++static void save_teeram_in_ddr(void) ++{ ++ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); ++ size_t __maybe_unused size = (vaddr_t)stm32mp_bkpsram_image_end - ++ (vaddr_t)stm32mp_bkpsram_resume; ++ paddr_t pa = 0; ++ struct ccm_unpg_ctx *ccm = &ctx->ccm_ctx; ++ void *teeram = phys_to_virt(TEE_RAM_START, MEM_AREA_ROM_SEC); ++ void *teeram_bkp = mobj_get_va(teeram_bkp_mobj, 0); ++ ++ COMPILE_TIME_ASSERT(PM_CTX_CCM_KEY_SIZE == sizeof(ccm->key)); ++ COMPILE_TIME_ASSERT(PM_CTX_CCM_CTR1_SIZE == sizeof(ccm->ctr1)); ++ COMPILE_TIME_ASSERT(PM_CTX_CCM_B0_SIZE == sizeof(ccm->b0)); ++ COMPILE_TIME_ASSERT(PM_CTX_CCM_CTR0_SIZE == sizeof(ccm->ctr0)); ++ COMPILE_TIME_ASSERT(PM_CTX_CCM_TAG_SIZE == sizeof(ccm->tag)); ++ ++ assert(stm32_clock_is_enabled(BKPSRAM) && ++ stm32_clock_is_enabled(CRYP1)); ++ ++ memcpy(ctx->resume_sequence, ++ (void *)(vaddr_t)stm32mp_bkpsram_resume, size); ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ ctx->resume_pa = virt_to_phys((void *)(vaddr_t)stm32mp_sysram_resume); ++ if (mobj_get_pa(teeram_bkp_mobj, 0, 0, &pa)) ++ panic(); ++ ++ ctx->teeram_bkp_pa = (uint32_t)pa; ++ ctx->cryp1_base = (uint32_t)phys_to_virt(CRYP1_BASE, MEM_AREA_IO_SEC); ++ ctx->rcc_base = (uint32_t)phys_to_virt(RCC_BASE, MEM_AREA_IO_SEC); ++ ctx->stgen_base = (uint32_t)phys_to_virt(STGEN_BASE, MEM_AREA_IO_SEC); ++ ++ if (stm32_rng_read((uint8_t *)ccm->key, sizeof(ccm->key))) ++ panic(); ++ ++ assert(((PM_CCM_TAG_FLAGS & ~0x38U) | (PM_CCM_Q_FLAGS & ~0x07U)) == 0); ++ COMPILE_TIME_ASSERT(PM_CCM_Q <= 4); ++ COMPILE_TIME_ASSERT(TEE_RAM_PH_SIZE > UINT16_MAX); ++ COMPILE_TIME_ASSERT(TEE_RAM_PH_SIZE < UINT32_MAX); ++ ++ if (stm32_rng_read((uint8_t *)ccm->ctr1, sizeof(ccm->ctr1))) ++ panic(); ++ ++ ccm->ctr1[0] &= GENMASK_32(24, 0); ++ memcpy(ccm->b0, ccm->ctr1, sizeof(ccm->b0)); ++ memcpy(ccm->ctr0, ccm->ctr1, sizeof(ccm->ctr0)); ++ ++ ccm->ctr0[0] |= PM_CCM_Q_FLAGS << 24; ++ ccm->ctr0[3] = 0; ++ ccm->ctr1[0] |= PM_CCM_Q_FLAGS << 24; ++ ccm->ctr1[3] = 1; ++ ccm->b0[0] |= (PM_CCM_Q_FLAGS | PM_CCM_TAG_FLAGS) << 24; ++ ccm->b0[3] = TEE_RAM_PH_SIZE; ++ ++ stm32mp_ccm_encrypt_teeram(ctx, teeram_bkp, teeram, TEE_RAM_PH_SIZE); ++ dcache_clean_range(teeram_bkp, TEE_RAM_PH_SIZE); ++ ++ memcpy(ctx->ccm_ref_tag, ccm->tag, sizeof(ctx->ccm_ref_tag)); ++ ++ DMSG("CCM encryption duration %llums", ++ ((unsigned long long)ctx->stgen_cnt * 1000) / ++ io_read32(ctx->stgen_base + CNTFID_OFFSET)); ++ ctx->stgen_cnt = 0; ++} ++#else ++static void save_teeram_in_ddr(void) ++{ ++ panic("Mandates RNG and CRYP support"); ++} ++#endif /*CFG_STM32_RNG*/ ++ ++/* Finalize the PM mailbox now that everything is loaded */ ++static void enable_pm_mailbox(unsigned int suspend) ++{ ++ struct pm_mailbox *mailbox = get_pm_mailbox(); ++ uint32_t magic = 0; ++ uint32_t hint = 0; ++ ++ assert(stm32_clock_is_enabled(BKPSRAM) && ++ stm32_clock_is_enabled(RTCAPB)); ++ ++ if (suspend) { ++ magic = BOOT_API_A7_CORE0_MAGIC_NUMBER; ++ mailbox->magic = STANDBY_CONTEXT_MAGIC; ++ ++ hint = virt_to_phys(&get_retram_resume_ctx()->resume_sequence); ++ } else { ++ mailbox->magic = 0; ++ } ++ ++ io_write32(stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER), magic); ++ io_write32(stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS), hint); ++ ++ mailbox->core0_resume_ep = hint; ++} ++ ++static void gate_pm_context_clocks(bool enable) ++{ ++ static bool clocks_enabled; ++ ++ if (enable) { ++ assert(!clocks_enabled); ++ stm32_clock_enable(BKPSRAM); ++ stm32_clock_enable(RTCAPB); ++ stm32_clock_enable(CRYP1); ++ clocks_enabled = true; ++ return; ++ } ++ ++ /* Suspended TEE RAM state left the clocks enabled */ ++ if (clocks_enabled) { ++ stm32_clock_disable(BKPSRAM); ++ stm32_clock_disable(RTCAPB); ++ stm32_clock_disable(CRYP1); ++ clocks_enabled = false; ++ } ++} ++ ++/* ++ * Context (TEE RAM content + peripherals) must be restored ++ * only if system may reach STANDBY state. ++ */ ++TEE_Result stm32mp_pm_save_context(unsigned int soc_mode) ++{ ++ TEE_Result res = TEE_ERROR_GENERIC; ++ ++ save_time(); ++ ++ if (!need_to_backup_cpu_context(soc_mode)) { ++ if (need_to_backup_stop_context(soc_mode)) ++ stm32mp1_clk_save_context_for_stop(); ++ ++ return TEE_SUCCESS; ++ } ++ ++ gate_pm_context_clocks(true); ++ load_earlyboot_pm_mailbox(); ++ res = pm_change_state(PM_OP_SUSPEND, 0); ++ if (res) ++ return res; ++ ++ save_teeram_in_ddr(); ++ enable_pm_mailbox(1); ++ ++ return TEE_SUCCESS; ++} ++ ++void stm32mp_pm_restore_context(unsigned int soc_mode) ++{ ++ if (need_to_backup_cpu_context(soc_mode)) { ++ if (pm_change_state(PM_OP_RESUME, 0)) ++ panic(); ++ ++ gate_pm_context_clocks(false); ++ } else if (need_to_backup_stop_context(soc_mode)) { ++ stm32mp1_clk_restore_context_for_stop(); ++ } ++ ++ restore_time(); ++} ++ ++void stm32mp_pm_shutdown_context(void) ++{ ++ gate_pm_context_clocks(true); ++ load_earlyboot_pm_mailbox(); ++ enable_pm_mailbox(0); ++ gate_pm_context_clocks(false); ++} ++ ++static TEE_Result init_pm_support(void) ++{ ++ init_retram_resume_resources(); ++ ++ stm32mp_pm_wipe_context(); ++ ++ return TEE_SUCCESS; ++} ++driver_init(init_pm_support); +diff --git a/core/arch/arm/plat-stm32mp1/pm/context.h b/core/arch/arm/plat-stm32mp1/pm/context.h +new file mode 100644 +index 0000000..a806d68 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/context.h +@@ -0,0 +1,102 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#ifndef __STM32MP_PM_CONTEXT_H__ ++#define __STM32MP_PM_CONTEXT_H__ ++ ++#ifndef __ASSEMBLER__ ++#include ++#include ++#include ++#include ++#include ++#include ++#endif ++ ++#define PM_CTX_CCM_KEY_SIZE 32 ++#define PM_CTX_CCM_CTR1_SIZE 16 ++#define PM_CTX_CCM_B0_SIZE 16 ++#define PM_CTX_CCM_CTR0_SIZE 16 ++#define PM_CTX_CCM_TAG_SIZE 16 ++ ++#ifndef __ASSEMBLER__ ++/* ++ * All materials for the CCM sequence using CRYP support are preloaded ++ * in this specific structure. Note that the sequence does not use AAD. ++ * ++ * @key: AES key material buffer ++ * @ctr1: Preformatted 128bit CTR1 block ++ * @ctr1: Preformatted 128bit B0 block ++ * @ctr1: Preformatted 128bit CTR0 block ++ * @tag: Buffer where the generated CCM tag is stored ++ */ ++struct ccm_unpg_ctx { ++ uint32_t key[PM_CTX_CCM_KEY_SIZE / sizeof(uint32_t)]; ++ uint32_t ctr1[PM_CTX_CCM_CTR1_SIZE / sizeof(uint32_t)]; ++ uint32_t b0[PM_CTX_CCM_B0_SIZE / sizeof(uint32_t)]; ++ uint32_t ctr0[PM_CTX_CCM_CTR0_SIZE / sizeof(uint32_t)]; ++ uint32_t tag[PM_CTX_CCM_TAG_SIZE / sizeof(uint32_t)]; ++}; ++ ++/* ++ * This structure is used by pm_helpers.S at early resume from retention RAM. ++ * It is defined here and used by context_asm_defines.c to generate offset ++ * macros for the assembly implementation in pm_helpers.S. ++ * ++ * To lower the memory footprint of suspend sequence, The same function is ++ * used for encryption (executed from TEE RAM with MMU enabled) and for ++ * decryption (executed from BKPSRAM with MMU disabled). Therefore some ++ * required addresses are provided by the caller through this structure ++ * especially some SoC interface registers that are likely to have different ++ * physical and virtual addresses. ++ * ++ * @resume_pa: OP-TEE resume physical entry in TEE RAM (once restored) ++ * @teeram_bkp_pa: Physical base address in TEE RAM backup in DDR ++ * @cryp1_base: Base address of the CRYP1 registers (physical or virtual) ++ * @rcc_base: Base address of the RCC registers (physical or virtual) ++ * @stgen_base: Base address of the STGEN registers (physical or virtual) ++ * @stgen_cnt: STGEN cycle counter backup cell and measure of cycles spent ++ * @ccm_ref_tag: 128bit arrays storing tag generated during encryption ++ * @ccm_ctx: Structure storing CCM configuration and generated tag ++ * @resume_sequence: Code/data array for the BKPSRAM resume sequence ++ */ ++struct retram_resume_ctx { ++ uint32_t resume_pa; ++ uint32_t teeram_bkp_pa; ++ uint32_t cryp1_base; ++ uint32_t rcc_base; ++ uint32_t stgen_base; ++ uint32_t stgen_cnt; ++ uint8_t ccm_ref_tag[PM_CTX_CCM_TAG_SIZE]; ++ struct ccm_unpg_ctx ccm_ctx; ++ /* Last start the resume routine ARM (32bit) instructions sequence */ ++ uint32_t resume_sequence[]; ++}; ++ ++extern const uint8_t stm32mp_bkpsram_image_end[]; ++void stm32mp_bkpsram_resume(void); ++void stm32mp_sysram_resume(void); ++ ++void stm32mp_cpu_reset_state(void); ++ ++TEE_Result stm32mp_pm_save_context(unsigned int soc_mode); ++void stm32mp_pm_restore_context(unsigned int soc_mode); ++void stm32mp_pm_shutdown_context(void); ++void stm32mp_pm_wipe_context(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); ++ ++uintptr_t stm32mp_pm_retram_resume_ep(void); ++ ++int stm32mp_ccm_encrypt_teeram(struct retram_resume_ctx *ctx, ++ void *dst, void *src, size_t size); ++int stm32mp_ccm_decrypt_teeram(struct retram_resume_ctx *ctx, ++ void *dst, void *src, size_t size); ++#endif /*__ASSEMBLER__*/ ++ ++#endif /*__STM32MP_PM_CONTEXT_H__*/ +diff --git a/core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c b/core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c +new file mode 100644 +index 0000000..34c797f +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2018, STMicroelectronics ++ * Copyright (c) 2018, Linaro Limited ++ */ ++ ++#include ++ ++#include "context.h" ++ ++#define OFFSET_OF_CTX_STRUCT(_f) offsetof(struct retram_resume_ctx, _f) ++#define OFFSET_OF_CMM_CTX_STRUCT(_f) (OFFSET_OF_CTX_STRUCT(ccm_ctx) + \ ++ offsetof(struct ccm_unpg_ctx, _f)) ++DEFINES ++{ ++ DEFINE(PM_CTX_RESUME_PA, OFFSET_OF_CTX_STRUCT(resume_pa)); ++ DEFINE(PM_CTX_TEERAM_BKP_PA, OFFSET_OF_CTX_STRUCT(teeram_bkp_pa)); ++ DEFINE(PM_CTX_CRYP1_BASE, OFFSET_OF_CTX_STRUCT(cryp1_base)); ++ DEFINE(PM_CTX_RCC_BASE, OFFSET_OF_CTX_STRUCT(rcc_base)); ++ DEFINE(PM_CTX_STGEN_BASE, OFFSET_OF_CTX_STRUCT(stgen_base)); ++ DEFINE(PM_CTX_STGEN_CNT, OFFSET_OF_CTX_STRUCT(stgen_cnt)); ++ DEFINE(PM_CTX_CCM_KEY, OFFSET_OF_CMM_CTX_STRUCT(key)); ++ DEFINE(PM_CTX_CCM_CTR1, OFFSET_OF_CMM_CTX_STRUCT(ctr1)); ++ DEFINE(PM_CTX_CCM_B0, OFFSET_OF_CMM_CTX_STRUCT(b0)); ++ DEFINE(PM_CTX_CCM_CTR0, OFFSET_OF_CMM_CTX_STRUCT(ctr0)); ++ DEFINE(PM_CTX_CCM_TAG, OFFSET_OF_CMM_CTX_STRUCT(tag)); ++ DEFINE(PM_CTX_CCM_REF_TAG, OFFSET_OF_CTX_STRUCT(ccm_ref_tag)); ++} +diff --git a/core/arch/arm/plat-stm32mp1/pm/low_power.c b/core/arch/arm/plat-stm32mp1/pm/low_power.c +new file mode 100644 +index 0000000..0a9a166 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/low_power.c +@@ -0,0 +1,609 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "context.h" ++#include "power.h" ++ ++#define TIMEOUT_US_1MS 1000 ++ ++static uint8_t gicd_rcc_wakeup; ++static uint8_t gicc_pmr; ++ ++struct pwr_lp_config { ++ uint32_t pwr_cr1; ++ uint32_t pwr_mpucr; ++ const char *regul_suspend_node_name; ++}; ++ ++#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 = 0U, ++ .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", ++ }, ++}; ++ ++static void set_rcc_it_priority(uint8_t *it_prio, uint8_t *pmr) ++{ ++ *it_prio = itr_set_ipriority(RCC_WAKEUP_IT, GIC_HIGHEST_SEC_PRIORITY); ++ *pmr = itr_set_pmr(STM32MP_GIC_PRIORITY_CSTOP); ++} ++ ++static void restore_rcc_it_priority(uint8_t it_prio, uint8_t pmr) ++{ ++ (void)itr_set_ipriority(RCC_WAKEUP_IT, it_prio); ++ (void)itr_set_pmr(pmr); ++} ++ ++static void stm32_apply_pmic_suspend_config(uint32_t mode) ++{ ++ const char *name = config_pwr[mode].regul_suspend_node_name; ++ ++ assert(mode < ARRAY_SIZE(config_pwr)); ++ ++ if (stm32mp_with_pmic() && name) { ++ stm32mp_get_pmic(); ++ stm32mp_pmic_apply_lp_config(name); ++ stm32mp_pmic_apply_boot_on_config(); ++ stm32mp_put_pmic(); ++ } ++} ++ ++#define CONSOLE_FLUSH_DELAY_MS 10 ++ ++#if TRACE_LEVEL >= TRACE_DEBUG ++static void wait_console_flushed(void) ++{ ++ console_flush(); ++ mdelay(CONSOLE_FLUSH_DELAY_MS); ++} ++#else ++static void wait_console_flushed(void) ++{ ++} ++#endif ++ ++static void cpu_wfi(void) ++{ ++ dsb(); ++ isb(); ++ wfi(); ++} ++ ++void stm32_pm_cpu_wfi(void) ++{ ++ wait_console_flushed(); ++ cpu_wfi(); ++} ++ ++/* If IWDG is not supported, provide a stubbed weak watchdog kicker */ ++void __weak stm32_iwdg_refresh(uint32_t __unused instance) ++{ ++} ++ ++#define ARM_CNTXCTL_IMASK BIT(1) ++ ++static 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); ++} ++ ++/* ++ * stm32_enter_cstop - Prepare CSTOP mode ++ * ++ * @mode - Target low power mode ++ */ ++void stm32_enter_cstop(uint32_t mode) ++{ ++ uint32_t pwr_cr1 = config_pwr[mode].pwr_cr1; ++ vaddr_t pwr_base = stm32_pwr_base(); ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ stm32mp_syscfg_disable_io_compensation(); ++ ++ /* Save Self-Refresh (SR) mode and switch to Software SR mode */ ++ ddr_save_sr_mode(DDR_SSR_MODE); ++ ++ stm32_apply_pmic_suspend_config(mode); ++ ++ if (stm32mp_with_pmic() && (mode == STM32_PM_CSTOP_ALLOW_LP_STOP)) ++ pwr_cr1 |= PWR_CR1_LPCFG; ++ ++ /* Workaround for non secure cache issue: this should not be needed */ ++ dcache_op_all(DCACHE_OP_CLEAN_INV); ++ ++ /* Clear RCC interrupt before enabling it */ ++ io_setbits32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF); ++ ++ /* Enable RCC Wake-up */ ++ io_setbits32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); ++ ++ /* Configure low power mode */ ++ io_clrsetbits32(pwr_base + PWR_MPUCR_OFF, PWR_MPUCR_MASK, ++ config_pwr[mode].pwr_mpucr); ++ io_clrsetbits32(pwr_base + PWR_CR1_OFF, PWR_CR1_MASK, pwr_cr1); ++ ++ /* Clear RCC pending interrupt flags */ ++ io_write32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_MASK); ++ ++ /* Request CSTOP mode to RCC */ ++ io_setbits32(rcc_base + RCC_MP_SREQSETR, ++ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); ++ ++ stm32_iwdg_refresh(IWDG2_INST); ++ ++ set_rcc_it_priority(&gicd_rcc_wakeup, &gicc_pmr); ++ ++ if (ddr_standby_sr_entry() != 0) ++ panic(); ++ ++ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { ++ /* Keep retention and backup RAM content in standby */ ++ io_setbits32(pwr_base + PWR_CR2_OFF, PWR_CR2_BREN | ++ PWR_CR2_RREN); ++ ++ while ((io_read32(pwr_base + PWR_CR2_OFF) & ++ (PWR_CR2_BRRDY | PWR_CR2_RRRDY)) == 0U) ++ ; ++ } ++} ++ ++/* ++ * stm32_exit_cstop - Exit from CSTOP mode ++ */ ++void stm32_exit_cstop(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ if (ddr_standby_sr_exit()) ++ panic(); ++ ++ /* Restore Self-Refresh mode saved in stm32_enter_cstop() */ ++ ddr_restore_sr_mode(); ++ ++ restore_rcc_it_priority(gicd_rcc_wakeup, gicc_pmr); ++ ++ /* Disable STOP request */ ++ io_setbits32(rcc_base + RCC_MP_SREQCLRR, ++ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); ++ ++ /* Disable RCC Wake-up */ ++ io_clrbits32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); ++ ++ dsb(); ++ isb(); ++ ++ /* Disable retention and backup RAM content after stop */ ++ io_clrbits32(stm32_pwr_base() + PWR_CR2_OFF, PWR_CR2_BREN | PWR_CR2_RREN); ++ ++ stm32mp_syscfg_enable_io_compensation(); ++} ++ ++/* ++ * GIC support required in low power sequences and reset sequences ++ */ ++#define GICC_IAR 0x00C ++#define GICC_IT_ID_MASK 0x3ff ++#define GICC_EOIR 0x010 ++#define GICC_HPPIR 0x018 ++#define GICC_AHPPIR 0x028 ++#define GIC_PENDING_G1_INTID 1022U ++#define GIC_SPURIOUS_INTERRUPT 1023U ++#define GIC_NUM_INTS_PER_REG 32 ++#define GIC_MAX_SPI_ID 1020 ++#define GICD_ICENABLER(n) (0x180 + (n) * 4) ++ ++static void clear_pending_interrupts(void) ++{ ++ uint32_t id = 0; ++ vaddr_t gicc_base = get_gicc_base(); ++ vaddr_t gicd_base = get_gicd_base(); ++ ++ do { ++ id = io_read32(gicc_base + GICC_HPPIR) & GICC_IT_ID_MASK; ++ ++ /* ++ * Find out which interrupt it is under the ++ * assumption that the GICC_CTLR.AckCtl bit is 0. ++ */ ++ if (id == GIC_PENDING_G1_INTID) ++ id = io_read32(gicc_base + GICC_AHPPIR) & GICC_IT_ID_MASK; ++ ++ if (id < GIC_MAX_SPI_ID) { ++ size_t idx = id / GIC_NUM_INTS_PER_REG; ++ uint32_t mask = 1 << (id % GIC_NUM_INTS_PER_REG); ++ ++ io_write32(gicc_base + GICC_EOIR, id); ++ ++ io_write32(gicd_base + GICD_ICENABLER(idx), mask); ++ ++ dsb_ishst(); ++ } ++ } while (id < GIC_MAX_SPI_ID); ++} ++ ++void stm32mp_gic_set_end_of_interrupt(uint32_t it) ++{ ++ vaddr_t gicc_base = get_gicc_base(); ++ ++ io_write32(gicc_base + GICC_EOIR, it); ++} ++ ++static void __noreturn wait_cpu_reset(void) ++{ ++#ifdef STM32MP1_USE_MPU0_RESET ++ dcache_op_all(DCACHE_OP_CLEAN_INV); ++ write_sctlr(read_sctlr() & ~SCTLR_C); ++ dcache_op_all(DCACHE_OP_CLEAN_INV); ++ __asm__("clrex"); ++ ++ dsb(); ++ isb(); ++#else ++ psci_armv7_cpu_off(); ++#endif ++ ++ for ( ; ; ) { ++ clear_pending_interrupts(); ++ wfi(); ++ } ++} ++ ++#ifdef STM32MP1_USE_MPU0_RESET ++/* ++ * 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 { ++ uint16_t reset_id; ++ uint16_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 __maybe_unused 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), ++}; ++ ++static void reset_peripherals(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ size_t __maybe_unused id = 0; ++ ++ for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) { ++ const struct tzc_source_ip *tzc = &tzc_source_ip[id]; ++ ++ if (!stm32_clock_is_enabled(tzc->clock_id) || ++ ((tzc->decprot_id != STM32MP1_ETZPC_MAX_ID) && ++ (etzpc_get_decprot(tzc->decprot_id) == ++ ETZPC_DECPROT_MCU_ISOLATION))) ++ continue; ++ ++ if (tzc->reset_id != GPU_R) { ++ stm32_reset_assert(tzc->reset_id, TIMEOUT_US_1MS); ++ stm32_reset_deassert(tzc->reset_id, TIMEOUT_US_1MS); ++ } else { ++ /* GPU reset automatically cleared by hardware */ ++ io_setbits32(rcc_base + RCC_AHB6RSTSETR, ++ RCC_AHB6RSTSETR_GPURST); ++ } ++ } ++} ++#endif /* STM32MP1_USE_MPU0_RESET */ ++ ++static void __noreturn reset_cores(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ uint32_t reset_mask = RCC_MP_GRSTCSETR_MPUP0RST | ++ RCC_MP_GRSTCSETR_MPUP1RST; ++ uint32_t target_mask = 0; ++ ++ /* Mask timer interrupts */ ++ stm32mp_mask_timer(); ++ ++#ifdef STM32MP1_USE_MPU0_RESET ++ reset_peripherals(); ++#endif ++ ++ if (get_core_pos() == 0) ++ target_mask = TARGET_CPU1_GIC_MASK; ++ else ++ target_mask = TARGET_CPU0_GIC_MASK; ++ ++ itr_raise_sgi(GIC_SEC_SGI_1, target_mask); ++ ++ clear_pending_interrupts(); ++ ++ io_write32(rcc_base + RCC_MP_GRSTCSETR, reset_mask); ++ ++ wait_cpu_reset(); ++} ++ ++/* ++ * stm32_pm_cpus_reset - Reset only cpus ++ */ ++void __noreturn stm32_cores_reset(void) ++{ ++ reset_cores(); ++} ++DECLARE_KEEP_PAGER(stm32_cores_reset); ++ ++static __maybe_unused void reset_other_core(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ uint32_t reset_mask = 0; ++ uint32_t target_mask = 0; ++ ++ if (get_core_pos() == 0) { ++ reset_mask = RCC_MP_GRSTCSETR_MPUP1RST; ++ target_mask = TARGET_CPU1_GIC_MASK; ++ } else { ++ reset_mask = RCC_MP_GRSTCSETR_MPUP0RST; ++ target_mask = TARGET_CPU0_GIC_MASK; ++ } ++ ++ itr_raise_sgi(GIC_SEC_SGI_1, target_mask); ++ ++ io_write32(rcc_base + RCC_MP_GRSTCSETR, reset_mask); ++} ++ ++/* ++ * stm32_enter_cstop_shutdown - Shutdown CPUs to target low power mode ++ * @mode - Target low power mode ++ */ ++void __noreturn stm32_enter_cstop_shutdown(uint32_t mode) ++{ ++ switch (mode) { ++ case STM32_PM_SHUTDOWN: ++ if (stm32mp_with_pmic()) { ++ wait_console_flushed(); ++ stm32mp_get_pmic(); ++ stpmic1_switch_off(); ++ udelay(100); ++ } ++ break; ++ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR: ++ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF: ++#ifdef STM32MP1_USE_MPU0_RESET ++ stm32mp_pm_shutdown_context(); ++ reset_other_core(); ++ stm32_enter_cstop(mode); ++ dsb(); ++ isb(); ++ for ( ; ; ) ++ wfi(); ++#else ++ if (stm32mp_with_pmic()) { ++ wait_console_flushed(); ++ stm32mp_get_pmic(); ++ stpmic1_switch_off(); ++ udelay(100); ++ } ++#endif ++ break; ++ default: ++ break; ++ } ++ ++ panic(); ++} ++ ++/* ++ * stm32_enter_cstop_reset - Reset CPUs to target low power mode ++ * @mode - Target low power mode ++ */ ++void __noreturn stm32_enter_cstop_reset(uint32_t mode) ++{ ++ vaddr_t rcc = stm32_rcc_base(); ++ ++ switch (mode) { ++ case STM32_PM_SHUTDOWN: ++ io_write32(rcc + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); ++ udelay(100); ++ break; ++ default: ++ IMSG("Forced system reset"); ++ wait_console_flushed(); ++ io_write32(rcc + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); ++ udelay(100); ++ break; ++ } ++ ++ panic(); ++} ++ ++/* ++ * stm32_enter_csleep - enter CSLEEP state while WFI and exit in CRUN ++ * ++ * Configure PWR for CSLEEP state. CPU shall execute a WFI and return ++ * once a interrupt is pending. ++ */ ++void stm32_enter_csleep(void) ++{ ++ vaddr_t pwr_base = stm32_pwr_base(); ++ ++ io_clrsetbits32(pwr_base + PWR_MPUCR_OFF, PWR_MPUCR_MASK, ++ config_pwr[STM32_PM_CSLEEP_RUN].pwr_mpucr); ++ io_clrsetbits32(pwr_base + PWR_CR1_OFF, PWR_CR1_MASK, ++ config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1); ++ ++ stm32_pm_cpu_wfi(); ++} ++ ++/* RCC Wakeup interrupt is used to wake from suspeneded mode */ ++static enum itr_return rcc_wakeup_it_handler(struct itr_handler *hdl __unused) ++{ ++ /* This interrupt is not expected to be handled */ ++ panic("RCC wakeup interrupt"); ++ return ITRR_HANDLED; ++} ++ ++static struct itr_handler rcc_wakeup_handler = { ++ .it = RCC_WAKEUP_IT, ++ .handler = rcc_wakeup_it_handler, ++}; ++DECLARE_KEEP_PAGER(rcc_wakeup_handler); ++ ++/* SGI9 (secure SGI 1) informs targeted CPU it shall reset */ ++static enum itr_return sgi9_it_handler(struct itr_handler *handler) ++{ ++ stm32mp_mask_timer(); ++ ++ stm32mp_gic_set_end_of_interrupt(handler->it); ++ ++ clear_pending_interrupts(); ++ ++ wait_cpu_reset(); ++ ++ panic("Core reset"); ++ ++ return ITRR_HANDLED; ++} ++ ++static struct itr_handler sgi9_reset_handler = { ++ .it = GIC_SEC_SGI_1, ++ .handler = sgi9_it_handler, ++}; ++DECLARE_KEEP_PAGER(sgi9_reset_handler); ++ ++static TEE_Result init_low_power(void) ++{ ++ vaddr_t pwr_base = stm32_pwr_base(); ++ ++ itr_add(&rcc_wakeup_handler); ++ itr_enable(rcc_wakeup_handler.it); ++ ++ itr_add(&sgi9_reset_handler); ++ itr_enable(sgi9_reset_handler.it); ++ ++ /* Enable retention for BKPSRAM and BKPREG */ ++ io_mask32(pwr_base + PWR_CR2_OFF, ++ PWR_CR2_BREN | PWR_CR2_RREN, PWR_CR2_BREN | PWR_CR2_RREN); ++ ++ return TEE_SUCCESS; ++} ++service_init(init_low_power); ++ ++/* ++ * CPU low power sequences ++ */ ++void __noreturn stm32_pm_cpu_power_down_wfi(void) ++{ ++ vaddr_t rcc_base = stm32_rcc_base(); ++ ++ if (get_core_pos() == 0) { ++ void (*reset_ep)(void) = stm32mp_sysram_resume; ++ ++ stm32_pm_cpu_wfi(); ++ ++ /* STANDBY not reached: resume from retained SYSRAM */ ++ stm32_exit_cstop(); ++ stm32mp_cpu_reset_state(); ++ reset_ep(); ++ panic(); ++ } ++ ++ dcache_op_level1(DCACHE_OP_CLEAN); ++ io_write32(rcc_base + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPUP1RST); ++ cpu_wfi(); ++ panic(); ++} +diff --git a/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S +new file mode 100644 +index 0000000..cd8e48c +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S +@@ -0,0 +1,740 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2018, STMicroelectronics ++ * Copyright (c) 2017 NXP ++ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "context.h" ++ ++/* ++ * Right bit shift distance to reach timeout from a 1s STGEN freq count ++ * Value N relates to 1000ms / 2^N, i.e 7 relates to 7.8125ms=~8ms ++ */ ++#define CCM_TIMEOUT_128MS 2 ++#define CCM_TIMEOUT_8MS 7 ++#define CCM_TIMEOUT_1MS 10 ++#define CCM_TIMEOUT_16US 16 ++#define CCM_TIMEOUT CCM_TIMEOUT_8MS ++ ++/* ++ * CRYP interface register used for AES CCM ++ */ ++#define CRYP_CR 0x000 ++#define CRYP_SR 0x004 ++#define CRYP_DIN 0x008 ++#define CRYP_DOUT 0x00c ++#define CRYP_KEYR_BASE 0x020 ++#define CRYP_IVR_BASE 0x040 ++ ++#define CRYP_CR_ALGODIR_DECRYPT BIT(2) ++#define CRYP_CR_ALGOMODE_MASK (BIT(19) | GENMASK_32(5, 3)) ++#define CRYP_CR_ALGOMODE(m) (((m & BIT(3)) << 16) | (m & 0x7) << 3) ++#define ALGOMODE_AES_CCM 0x9 ++#define CRYP_CR_DATATYPE_SHIFT 6 ++#define CRYP_CR_DATATYPE_8BIT (2 << CRYP_CR_DATATYPE_SHIFT) ++#define CRYP_CR_KEYSIZE_SHIFT 8 ++#define CRYP_CR_KEYSIZE_256BIT (2U << CRYP_CR_KEYSIZE_SHIFT) ++#define CRYP_CR_CRYPEN BIT(15) ++#define CRYP_CR_FFLUSH BIT(14) ++#define CRYP_CR_GCM_CCMPH_SHIFT 16 ++#define CRYP_CR_PHASE_MASK (0x3 << CRYP_CR_GCM_CCMPH_SHIFT) ++#define CRYP_CR_INIT_PHASE (0 << CRYP_CR_GCM_CCMPH_SHIFT) ++#define CRYP_CR_HEADER_PHASE (1 << CRYP_CR_GCM_CCMPH_SHIFT) ++#define CRYP_CR_PAYLOAD_PHASE (2 << CRYP_CR_GCM_CCMPH_SHIFT) ++#define CRYP_CR_FINAL_PHASE (3 << CRYP_CR_GCM_CCMPH_SHIFT) ++ ++#define CRYP_SR_BUSY BIT(4) ++#define CRYP_SR_OFFU BIT(3) ++#define CRYP_SR_OFNE BIT(2) ++#define CRYP_SR_IFNF BIT(1) ++#define CRYP_SR_IFEM BIT(0) ++ ++/* ++ * Enable TRACE_SYSRAM_RESTORE to get some UART console traces ++ * at resume time. ++ */ ++#if defined(TRACE_SYSRAM_RESTORE) ++ ++#define UART_BASE UART4_BASE ++#define UART_ISR_OFF 0x1c ++#define UART_TDR_OFF 0x28 ++#define USART_ISR_TXE_TXFNF (1<< 7) ++ ++ .macro PRINT_CHAR _reg0, _reg1, _char ++ /* Trace only at resume when MMU is OFF */ ++ read_sctlr \_reg0 ++ ands \_reg0, #SCTLR_M ++ 101: ++ bne 102f ++ mov_imm \_reg0, UART4_BASE ++ ldr \_reg1, [\_reg0, #UART_ISR_OFF] ++ ands \_reg1, #USART_ISR_TXE_TXFNF ++ beq 101b ++ mov_imm \_reg1, (\_char) ++ str \_reg1, [\_reg0, #UART_TDR_OFF] ++ 102: ++ .endm ++#else ++ .macro PRINT_CHAR _reg0, _reg1, _char ++ .endm ++#endif ++ ++ /* Bound of the binary image loaded in retained memory */ ++ .global stm32mp_bkpsram_image_end ++ ++/* ++ * stm32mp_bkpsram_resume - Restore TEE RAM from backup memory and resume into ++ * ++ * This function executes at early resume from suspend state. It is the ++ * entrypoint of the OP-TEE provided to early boot stage when SoC wakes. ++ * This code is located in a retained memory, MMU disabled. This function ++ * shall restore TEE RAM content for OP-TEE to resume execution. Once ++ * TEE RAM is restored, this function branches to the resident resume entry ++ * point in TEE_RAM. This function and its resources shall execute in place. ++ */ ++FUNC stm32mp_bkpsram_resume , : ++UNWIND( .fnstart) ++UNWIND( .cantunwind) ++ ++ PRINT_CHAR r0, r1, '0' ++ ++ /* ++ * Almost all sequences here expect PM context structure base address ++ * from CPU register r11. ++ */ ++ mov_imm r11, (BKPSRAM_BASE + BKPSRAM_PM_CONTEXT_OFFSET) ++ ++ /* stm32mp_ccm_teeram needs some HW interface base addresss */ ++ mov_imm r0, CRYP1_BASE ++ str r0, [r11, #PM_CTX_CRYP1_BASE] ++ mov_imm r0, RCC_BASE ++ str r0, [r11, #PM_CTX_RCC_BASE] ++ mov_imm r0, STGEN_BASE ++ str r0, [r11, #PM_CTX_STGEN_BASE] ++ ++ bl _clear_early_mailbox ++ bl _prepare_time ++ ++ mov_imm r0, TEE_RAM_START ++ ldr r1, [r11, #PM_CTX_TEERAM_BKP_PA] ++ mov_imm r2, TEE_RAM_PH_SIZE ++ mov_imm r3, 1 ++ bl stm32mp_ccm_teeram ++ cmp r0, #0 ++ bne _failed ++ ++ PRINT_CHAR r0, r1, 'T' ++ PRINT_CHAR r0, r1, 'a' ++ PRINT_CHAR r0, r1, 'g' ++ PRINT_CHAR r0, r1, '\n' ++ ++ /* Compare the generated and reference tags */ ++ add r8, r11, #PM_CTX_CCM_TAG ++ add r9, r11, #PM_CTX_CCM_REF_TAG ++ ldm r8, {r2-r5} ++ ldm r9, {r6-r9} ++ mov r0, #0 ++ cmp r2, r6 ++ addeq r0, #1 ++ cmp r3, r7 ++ addeq r0, #1 ++ cmp r4, r8 ++ addeq r0, #1 ++ cmp r5, r9 ++ addeq r0, #1 ++ cmp r0, #4 ++ bne _failed ++ bl _save_resume_time ++ ++ PRINT_CHAR r1, r2, 'O' ++ PRINT_CHAR r1, r2, 'k' ++ PRINT_CHAR r1, r2, '\n' ++ ++ /* Resume into the restored TEE RAM */ ++ ldr r1, [r11, #PM_CTX_RESUME_PA] ++ bx r1 ++ ++_failed: ++ PRINT_CHAR r0, r12, 'F' ++ PRINT_CHAR r0, r12, '\n' ++ ++ /* Clear context including key and reference tag */ ++ mov r0, #0xa5 ++ mov_imm r12, BKPSRAM_PM_CONTEXT_SIZE ++ add r12, r11, r12 ++1: str r0, [r11], #4 ++ cmp r11, r12 ++ blt 1b ++ b . ++ ++ /* ++ * _clear_early_mailbox - Wipe mailbox in case of reset ++ * ++ * Sratches r0-r4. ++ * All other CPU registers are preserved. ++ */ ++_clear_early_mailbox: ++ /* Clear the backup registers (first enable RTCAPB clock) */ ++ mov_imm r0, (RCC_BASE + RCC_MP_APB5ENSETR) ++ mov_imm r2, RCC_MP_APB5ENSETR_RTCAPBEN ++ ldr r1, [r0] ++ ands r1, r1, r2 ++ moveq r1, r2 ++ movne r1, #0 ++ str r2, [r0] ++ mov_imm r2, (TAMP_BASE + TAMP_BKP_REGISTER_OFF) ++ mov_imm r3, (BCKR_CORE1_MAGIC_NUMBER * 4) ++ mov_imm r4, BOOT_API_A7_RESET_MAGIC_NUMBER ++ str r4, [r2, r3] ++ mov_imm r3, (BCKR_CORE1_BRANCH_ADDRESS * 4) ++ mov r4, #0 ++ str r4, [r2, r3] ++ /* Restore RTCAPB clock initial state */ ++ str r1, [r0, #RCC_MP_ENCLRR_OFFSET] ++ bx lr ++ ++ /* ++ * prepare_time - save/reset cycle counter to prevent later overflow ++ * ++ * Save current 32bit lower counter and reset to 0 so that later ++ * timeout test do not need to care about overflow. ++ * ++ * Expects r11 is context base and lr is return address. ++ * Scrathes r0-r2. ++ * All other CPU registers are preserved. ++ */ ++_prepare_time: ++ ldr r2, [r11, #PM_CTX_STGEN_BASE] ++ /* Disable STGEN counter */ ++ ldr r1, [r2, #CNTCR_OFFSET] ++ bic r1, r1, #CNTCR_EN ++ str r1, [r2, #CNTCR_OFFSET] ++1: ldr r1, [r2, #CNTSR_OFFSET] ++ tst r1, #CNTCR_EN ++ bne 1b ++ /* Save and reset STGEN counter */ ++ ldr r0, [r2, #CNTCVL_OFFSET] ++ str r0, [r11, #PM_CTX_STGEN_CNT] ++ mov r0, #0 ++ str r0, [r2, #CNTCVL_OFFSET] ++ ldr r0, [r2, #CNTCVU_OFFSET] ++ str r0, [r2, #CNTCVU_OFFSET] ++ /* Enable STGEN counter */ ++ ldr r1, [r2, #CNTCR_OFFSET] ++ orr r1, r1, #CNTCR_EN ++ str r1, [r2, #CNTCR_OFFSET] ++ bx lr ++ ++ /* ++ * save_resume_time - save time spent and restore STGEN cycle counter ++ * ++ * Restore STGEN counter to initial value incremented by the current ++ * count. Note 32bit upper may need to be incremented. ++ * ++ * Expects r11 is context base and lr is return address. ++ * Scrathes r0-r3. ++ * All other CPU registers are preserved. ++ */ ++_save_resume_time: ++ /* Compute update STGEN counter 32bit LSB value */ ++ ldr r2, [r11, #PM_CTX_STGEN_BASE] ++ ldr r0, [r11, #PM_CTX_STGEN_CNT] ++ ldr r3, [r2, #CNTCVL_OFFSET] ++ str r3, [r11, #PM_CTX_STGEN_CNT] ++ adds r0, r0, r3 ++ /* Disable STGEN */ ++ ldr r1, [r2, #CNTCR_OFFSET] ++ bic r1, r1, #CNTCR_EN ++ str r1, [r2, #CNTCR_OFFSET] ++1: ldr r1, [r2, #CNTSR_OFFSET] ++ tst r1, #CNTCR_EN ++ bne 1b ++ /* Update counter (increment 32bit MSB if requried) */ ++ str r0, [r2, #CNTCVL_OFFSET] ++ ldr r0, [r2, #CNTCVU_OFFSET] ++ addcs r0, r0, #1 ++ str r0, [r2, #CNTCVU_OFFSET] /* Write CNTCVU value ... */ ++ ldr r0, [r2, #CNTCVU_OFFSET] /* ... and wait it is set */ ++ /* Enable STGEN */ ++ ldr r0, [r2, #CNTCR_OFFSET] ++ orr r0, r0, #CNTCR_EN ++ str r0, [r2, #CNTCR_OFFSET] ++ bx lr ++ ++ /* ++ * _setup_cryp1 - Enable CRYP1 hardware: reset & clock ++ * _reset_cryp1 - Reset CRYP1 hardware ++ * ++ * Function call before and after CCM sequence. Note that the CRYP1 ++ * clock remain enabled. It is disabled later by the resume sequence. ++ * ++ * Expects r11 is context base and lr is return address. ++ * Scratches r0-r3. ++ */ ++_setup_cryp1: ++ ldr r1, [r11, #PM_CTX_RCC_BASE] ++ mov_imm r0, RCC_MP_AHB5ENSETR_CRYP1EN ++ str r0, [r1, #RCC_MP_AHB5ENSETR] ++ /* Intentionnally fall through reset_cryp1 */ ++_reset_cryp1: ++ ldr r3, [r11, #PM_CTX_RCC_BASE] ++ mov_imm r0, RCC_AHB5RSTSETR_CRYP1RST ++ str r0, [r3, #RCC_AHB5RSTSETR] ++1: ldr r1, [r3, #RCC_AHB5RSTSETR] ++ ands r1, r1, r0 ++ beq 1b ++ mov_imm r0, RCC_AHB5RSTSETR_CRYP1RST ++ str r0, [r3, #RCC_AHB5RSTCLRR] ++1: ldr r1, [r3, #RCC_AHB5RSTSETR] ++ ands r1, r1, r0 ++ bne 1b ++ bx lr ++ ++ /* ++ * _ccm_arm_8ms_timeout - Init 8ms threshold for _ccm_failed_on_timeout ++ * _ccm_fail_on_timeout - Check STGEN counter against timeout threshold ++ * ++ * These function are used by the macro wait_flag_timeout_8ms. The ++ * former loads the timeout in CPU register r0 while the later get the ++ * timeout counter threshold from CPU register r0. ++ * ++ * Expect r11 is context base and lr is return address. ++ * Scratch r0-r1. ++ * All other CPU registers are preserved. ++ */ ++_ccm_arm_8ms_timeout: ++ ldr r1, [r11, #PM_CTX_STGEN_BASE] ++ ldr r0, [r1, #CNTFID_OFFSET] ++ lsrs r0, r0, #CCM_TIMEOUT ++ moveq r0, #1 ++ ldr r1, [r1, #CNTCVL_OFFSET] ++ adds r0, r0, r1 ++ bcs _ccm_failed_on_timeout ++ bx lr ++ ++_ccm_fail_on_timeout: ++ ++ ldr r1, [r11, #PM_CTX_STGEN_BASE] ++ ldr r1, [r1, #CNTCVL_OFFSET] ++ cmp r1, r0 ++ bge _ccm_failed_on_timeout ++ bx lr ++ ++_ccm_failed_on_timeout: ++ PRINT_CHAR r0, r1, 'T' ++ PRINT_CHAR r0, r1, 'o' ++ PRINT_CHAR r0, r1, '\n' ++ b _ccm_failed ++ ++ /* ++ * Macro WAIT_FLAG_TIMEOUT compares timeout threshold (r0) with ++ * current time and branches the CCM failure entry on timeout. ++ * It is assumed the 32bit timestamps cannot overflow. ++ */ ++ .macro WAIT_FLAG_TIMEOUT register_offset, bit_mask, awaited_mask ++ bl _ccm_arm_8ms_timeout ++ 1: ++ bl _ccm_fail_on_timeout ++ ldr r1, [r10, #(\register_offset)] ++ and r1, r1, #(\bit_mask) ++ cmp r1, #(\awaited_mask) ++ bne 1b ++ .endm ++ ++/* ++ * stm32mp_ccm_teeram - Size optimzed unpaged CCM encryption/decryption ++ * ++ * This sequence encrypts or decrypts a input block using AES CCM with a ++ * 256bit key and no AAD and generates the CCM tag. The key, CTR0, CTR1 ++ * and B0 block are read from PM context structure. The generated tag is ++ * stored in the PM context structure. ++ * ++ * This function is executed from TEE RAM during suspend sequence to generate ++ * the encrypted data and the tag. This function is also executed from BKPSRAM ++ * called with MMU disabled. Therefore this sequence shall be comply with ++ * position independent code constraints. ++ * ++ * Expects at entry: ++ * lr = caller return address ++ * r11 = retram_resume_ctx structure base address ++ * r0 = Destination buffer for the output data (ciphertext or plaintext) ++ * r1 = Source buffer for the input data (plaintext or ciphertext) ++ * r2 = Input (and output) data size in bytes ++ * r3 = 1 if decrypting, 0 if encrypting ++ */ ++stm32mp_ccm_teeram: ++ /* ++ * Use of the CPU registers in the whole stm32mp_ccm_teeram sequence ++ * ++ * sp: preserved, not used ++ * lr: scratch register used to call subroutines. ++ * r12: saves the caller link register for final return ++ * r11: context from BKPSRAM ++ * r10: CRYP1 base address ++ * r9: destination buffer ++ * r8: source buffer to cipher ++ * r7: data byte counter ++ * r0-r6 are scratch registers ++ */ ++ mov r12, lr ++ ldr r10, [r11, #PM_CTX_CRYP1_BASE] ++ mov r9, r0 ++ mov r8, r1 ++ mov r7, r2 ++ mov r6, r3 ++ ++ PRINT_CHAR r0, r1, '1' ++ ++ bl _setup_cryp1 ++ ++ PRINT_CHAR r0, r1, '2' ++ ++ mov_imm r0, (CRYP_CR_ALGOMODE(ALGOMODE_AES_CCM) | \ ++ CRYP_CR_DATATYPE_8BIT | CRYP_CR_FFLUSH | \ ++ CRYP_CR_KEYSIZE_256BIT) ++ cmp r6, #0 ++ orrne r0, r0, #CRYP_CR_ALGODIR_DECRYPT ++ str r0, [r10, #CRYP_CR] ++ ++ PRINT_CHAR r0, r1, '3' ++ ++ /* Check data alignment (addresses and size) */ ++ ands r0, r7, #0x0F ++ bne _ccm_failed ++ ands r0, r8, #0x03 ++ bne _ccm_failed ++ ands r0, r9, #0x03 ++ bne _ccm_failed ++ ++ PRINT_CHAR r0, r1, '4' ++ ++ ldr r0, [r11, #PM_CTX_CCM_KEY] ++ str r0, [r10, #CRYP_KEYR_BASE] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 4)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 4)] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 8)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 8)] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 12)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 12)] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 16)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 16)] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 20)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 20)] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 24)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 24)] ++ ldr r0, [r11, #(PM_CTX_CCM_KEY + 28)] ++ str r0, [r10, #(CRYP_KEYR_BASE + 28)] ++ ++ ldr r0, [r11, #PM_CTX_CCM_CTR1] ++ str r0, [r10, #CRYP_IVR_BASE] ++ ldr r0, [r11, #(PM_CTX_CCM_CTR1 + 4)] ++ str r0, [r10, #(CRYP_IVR_BASE + 4)] ++ ldr r0, [r11, #(PM_CTX_CCM_CTR1 + 8)] ++ str r0, [r10, #(CRYP_IVR_BASE + 8)] ++ ldr r0, [r11, #(PM_CTX_CCM_CTR1 + 12)] ++ str r0, [r10, #(CRYP_IVR_BASE + 12)] ++ ++ /* Setup CRYP for the CCM Init Phase */ ++ ldr r0, [r10, #CRYP_CR] ++ orr r0, r0, #(CRYP_CR_CRYPEN | CRYP_CR_INIT_PHASE) ++ str r0, [r10, #CRYP_CR] ++ ldr r0, [r10, #CRYP_CR] ++ ++ ldr r0, [r11, #PM_CTX_CCM_B0] ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r11, #(PM_CTX_CCM_B0 + 4)] ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r11, #(PM_CTX_CCM_B0 + 8)] ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r11, #(PM_CTX_CCM_B0 + 12)] ++ str r0, [r10, #CRYP_DIN] ++ ++ PRINT_CHAR r0, r1, '5' ++ ++ WAIT_FLAG_TIMEOUT CRYP_CR, CRYP_CR_CRYPEN, 0 ++ ++ /* Setup CRYP for the CCM Payload phase */ ++ ldr r0, [r10, #CRYP_CR] ++ bic r0, r0, #CRYP_CR_PHASE_MASK ++ orr r0, r0, #CRYP_CR_PAYLOAD_PHASE ++ orr r0, r0, #CRYP_CR_CRYPEN ++ str r0, [r10, #CRYP_CR] ++ ldr r0, [r10, #CRYP_CR] ++ ++ PRINT_CHAR r0, r1, '\n' ++ ++_next_block: ++ PRINT_CHAR r0, r1, 'b' ++ ++ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_IFEM, CRYP_SR_IFEM ++ ++ /* Feed input data, r8 stores the current source buffer */ ++ ldr r0, [r8], #4 ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r8], #4 ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r8], #4 ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r8], #4 ++ str r0, [r10, #CRYP_DIN] ++ ++ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_OFNE, CRYP_SR_OFNE ++ ++ /* Store output data, r9 stores the current source buffer */ ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r9], #4 ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r9], #4 ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r9], #4 ++ /* Before last 32bit word, the output FIFO shall not be empty */ ++ ldr r0, [r10, #CRYP_SR] ++ ands r0, r0, #CRYP_SR_OFNE ++ beq _ccm_failed ++ /* After last 32bit word for this 128block, FIFO shall be empty */ ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r9], #4 ++ ldr r0, [r10, #CRYP_SR] ++ ands r0, r0, #CRYP_SR_OFNE ++ bne _ccm_failed ++ ++ /* Another round if remaining data */ ++ subs r7, r7, #16 ++ bne _next_block; ++ ++ PRINT_CHAR r0, r1, '\n' ++ PRINT_CHAR r0, r1, '6' ++ ++ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_BUSY, 0 ++ ++ /* ++ * Data processing completed, now remains the tag generation. ++ * Here expect SR[IFNF]=SR[OFNE]=1 and all others bits are 0. ++ */ ++ ldr r0, [r10, #CRYP_SR] ++ cmp r0, #(CRYP_SR_IFEM | CRYP_SR_IFNF) ++ bne _ccm_failed ++ ++ PRINT_CHAR r0, r1, '7' ++ ++ /* Setup CRYP1 for the CCM Final Phase */ ++ ldr r0, [r10, #CRYP_CR] ++ bic r0, r0, #CRYP_CR_CRYPEN ++ str r0, [r10, #CRYP_CR] ++ ldr r0, [r10, #CRYP_CR] ++ bic r0, r0, #CRYP_CR_PHASE_MASK ++ bic r0, r0, #CRYP_CR_ALGODIR_DECRYPT ++ orr r0, r0, #CRYP_CR_FINAL_PHASE ++ orr r0, r0, #CRYP_CR_CRYPEN ++ str r0, [r10, #CRYP_CR] ++ ldr r0, [r10, #CRYP_CR] ++ ++ /* Load CTR0 to generate the tag */ ++ ldr r0, [r11, #PM_CTX_CCM_CTR0] ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 4)] ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 8)] ++ str r0, [r10, #CRYP_DIN] ++ ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 12)] ++ str r0, [r10, #CRYP_DIN] ++ ++ PRINT_CHAR r0, r1, '8' ++ ++ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_OFNE, CRYP_SR_OFNE ++ ++ /* Store generated tag in the PM_CTX structure */ ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r11, #PM_CTX_CCM_TAG] ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r11, #(PM_CTX_CCM_TAG + 4)] ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r11, #(PM_CTX_CCM_TAG + 8)] ++ /* Before last 32bit word, the output FIFO shall not be empty */ ++ ldr r0, [r10, #CRYP_SR] ++ ands r0, r0, #CRYP_SR_OFNE ++ beq _ccm_failed ++ /* After last 32bit word for this 128block, FIFO shall be empty */ ++ ldr r0, [r10, #CRYP_DOUT] ++ str r0, [r11, #(PM_CTX_CCM_TAG + 12)] ++ ldr r0, [r10, #CRYP_SR] ++ ands r0, r0, #CRYP_SR_OFNE ++ bne _ccm_failed ++ ++ PRINT_CHAR r0, r1, '9' ++ ++ /* Successful return */ ++ bl _reset_cryp1 ++ mov r0, #0 ++ bx r12 ++ ++_ccm_failed: ++ ++ PRINT_CHAR r0, r1, 'K' ++ PRINT_CHAR r0, r1, 'O' ++ ++ bl _reset_cryp1 ++ mov r0, #1 ++ bx r12 ++ ++/* End address of the PIC resume sequence copy in retained RAM */ ++stm32mp_bkpsram_image_end: ++ nop ++ ++UNWIND( .fnend) ++END_FUNC stm32mp_bkpsram_resume ++ ++/* ++ * int stm32mp_ccm_encrypt_teeram(ctx, dst, src, len) ++ */ ++FUNC stm32mp_ccm_encrypt_teeram , : ++UNWIND( .fnstart) ++ push {r4-r12, lr} ++UNWIND( .save {r4-r12, lr}) ++ mov r11, r0 ++ mov r0, r1 ++ mov r1, r2 ++ mov r2, r3 ++ mov r3, #0 ++ push {r0-r3} ++ bl _prepare_time ++ pop {r0-r3} ++ bl stm32mp_ccm_teeram ++ bl _save_resume_time ++ pop {r4-r12, pc} ++UNWIND( .fnend) ++END_FUNC stm32mp_ccm_encrypt_teeram ++ ++/* ++ * int stm32mp_ccm_decrypt_teeram(ctx, cryp_base, dst, src) ++ */ ++FUNC stm32mp_ccm_decrypt_teeram , : ++UNWIND( .fnstart) ++ push {r4-r12, lr} ++UNWIND( .save {r4-r12, lr}) ++ mov r11, r0 ++ mov r0, r1 ++ mov r1, r2 ++ mov r2, r3 ++ mov r3, #1 ++ push {r0-r3} ++ bl _prepare_time ++ pop {r0-r3} ++ bl stm32mp_ccm_teeram ++ bl _save_resume_time ++ pop {r4-r12, pc} ++UNWIND( .fnend) ++END_FUNC stm32mp_ccm_decrypt_teeram ++ ++/* ++ * stm32mp_sysram_resume - Resume OP-TEE execution ++ * ++ * This function is the entry point of OP-TEE core resume sequence in the TEE ++ * RAM. When TEE RAM is lost during a power cycle, stm32mp_bkpsram_resume() is ++ * called to restore TEE RAM content and branch to this stm32mp_sysram_resume() ++ * routine. ++ * ++ * This function calls the OP-TEE core generic PM resume API ++ * sm_pm_cpu_resume(). ++ */ ++FUNC stm32mp_sysram_resume, : ++UNWIND( .fnstart) ++UNWIND( .cantunwind) ++ /* Invalidate the data cache */ ++ ++ read_clidr r2 ++ ubfx r3, r2, #CLIDR_LOC_SHIFT, #CLIDR_FIELD_WIDTH ++ lsl r3, r3, #CSSELR_LEVEL_SHIFT ++ mov r1, #0 ++ ++loop1: ++ add r10, r1, r1, LSR #1 // Work out 3x current cache level ++ mov r12, r2, LSR r10 // extract cache type bits from clidr ++ and r12, r12, #7 // mask the bits for current cache only ++ cmp r12, #2 // see what cache we have at this level ++ blo level_done // no cache or only instruction cache at this level ++ ++ write_csselr r1 // select current cache level in csselr ++ isb // isb to sych the new cssr&csidr ++ read_ccsidr r12 // read the new ccsidr ++ and r10, r12, #7 // extract the length of the cache lines ++ add r10, r10, #4 // add 4 (r10 = line length offset) ++ ubfx r4, r12, #3, #10 // r4 = maximum way number (right aligned) ++ clz r5, r4 // r5 = the bit position of the way size increment ++ mov r9, r4 // r9 working copy of the aligned max way number ++ ++loop2: ++ ubfx r7, r12, #13, #15 // r7 = max set number (right aligned) ++ ++loop3: ++ orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 ++ orr r0, r0, r7, LSL r10 // factor in the set number ++ ++ write_dcisw r0 ++ ++ subs r7, r7, #1 // decrement the set number ++ bhs loop3 ++ subs r9, r9, #1 // decrement the way number ++ bhs loop2 ++level_done: ++ add r1, r1, #2 // increment the cache number ++ cmp r3, r1 ++ dsb sy // ensure completion of previous cache maintenance instruction ++ bhi loop1 ++ ++ mov r6, #0 ++ write_csselr r6 //select cache level 0 in csselr ++ dsb sy ++ isb ++ ++ /* Resume sequence executes in Monitor mode */ ++ cps #CPSR_MODE_MON ++ ++ blx plat_cpu_reset_early ++ b sm_pm_cpu_resume ++UNWIND( .fnend) ++END_FUNC stm32mp_sysram_resume ++ ++/* ++ * stm32mp_cpu_reset_state - set CPU in a reset like state ++ * ++ * Disable CPU env (interrupts, cache, SMP, MMU) and return. ++ * Preserve the execution mode in CPSR. ++ */ ++FUNC stm32mp_cpu_reset_state, : ++UNWIND( .fnstart) ++ push {r12, lr} ++UNWIND( .save {r12, lr}) ++ ++ cpsid aif ++ ++ bl psci_armv7_cpu_off ++ ++ write_bpiall ++ dsb ++ isb ++ read_sctlr r0 ++ bic r0, r0, #SCTLR_M ++ bic r0, r0, #SCTLR_I ++ write_sctlr r0 ++ dsb sy ++ isb ++ ++ pop {r12, pc} ++UNWIND( .fnend) ++END_FUNC stm32mp_cpu_reset_state +diff --git a/core/arch/arm/plat-stm32mp1/pm/power.h b/core/arch/arm/plat-stm32mp1/pm/power.h +new file mode 100644 +index 0000000..4a5578c +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/power.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#ifndef __STM32MP_PM_POWER_H__ ++#define __STM32MP_PM_POWER_H__ ++ ++#include ++#include ++#include ++ ++bool need_to_backup_cpu_context(unsigned int soc_mode); ++bool need_to_backup_stop_context(unsigned int soc_mode); ++ ++void stm32_enter_csleep(void); ++ ++void stm32_enter_cstop(uint32_t mode); ++void stm32_exit_cstop(void); ++ ++void stm32_enter_cstop_shutdown(uint32_t mode) __noreturn; ++void stm32_enter_cstop_reset(uint32_t mode) __noreturn; ++ ++void stm32_pm_cpu_power_down_wfi(void) __noreturn; ++void stm32_pm_cpu_wfi(void); ++ ++#endif /*__STM32MP_PM_POWER_H__*/ +diff --git a/core/arch/arm/plat-stm32mp1/pm/power_config.c b/core/arch/arm/plat-stm32mp1/pm/power_config.c +new file mode 100644 +index 0000000..246c92e +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/pm/power_config.c +@@ -0,0 +1,252 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "context.h" ++#include "power.h" ++ ++#define DT_PWR_COMPAT "st,stm32mp1,pwr-reg" ++#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes" ++#define SYSTEM_OFF_MODE "system_off_soc_mode" ++ ++static uint32_t deepest_suspend_mode; ++static uint32_t system_off_mode; ++static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE]; ++ ++/* Boot with all domains ON */ ++static bool stm32mp1_pm_dom[STM32MP1_PD_MAX_PM_DOMAIN] = { ++ [STM32MP1_PD_VSW] = false, ++ [STM32MP1_PD_CORE_RET] = false, ++ [STM32MP1_PD_CORE] = false ++}; ++ ++bool need_to_backup_cpu_context(unsigned int soc_mode) ++{ ++ switch (soc_mode) { ++ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR: ++ return true; ++ case STM32_PM_CSLEEP_RUN: ++ case STM32_PM_CSTOP_ALLOW_STOP: ++ case STM32_PM_CSTOP_ALLOW_LP_STOP: ++ case STM32_PM_CSTOP_ALLOW_LPLV_STOP: ++ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF: ++ case STM32_PM_SHUTDOWN: ++ return false; ++ default: ++ EMSG("Invalid mode 0x%x", soc_mode); ++ panic(); ++ } ++} ++ ++bool need_to_backup_stop_context(unsigned int soc_mode) ++{ ++ switch (soc_mode) { ++ case STM32_PM_CSTOP_ALLOW_STOP: ++ case STM32_PM_CSTOP_ALLOW_LP_STOP: ++ case STM32_PM_CSTOP_ALLOW_LPLV_STOP: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool 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 &= stm32mp1_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 -1; ++ ++ stm32mp1_pm_dom[domain] = status; ++ ++ return 0; ++} ++ ++#ifdef CFG_DT ++static int fdt_read_uint32_array(void *fdt, int node, const char *prop_name, ++ uint32_t *array, uint32_t count) ++{ ++ const fdt32_t *cuint = NULL; ++ int len = 0; ++ uint32_t i = 0; ++ ++ cuint = fdt_getprop(fdt, node, prop_name, &len); ++ if (!cuint) ++ return -FDT_ERR_NOTFOUND; ++ ++ if ((uint32_t)len != (count * sizeof(uint32_t))) ++ return -FDT_ERR_BADLAYOUT; ++ ++ for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { ++ *array = fdt32_to_cpu(*cuint); ++ array++; ++ cuint++; ++ } ++ ++ return 0; ++} ++ ++static void save_supported_mode(void *fdt, int pwr_node) ++{ ++ int len = 0; ++ uint32_t count = 0; ++ unsigned int i = 0; ++ uint32_t supported[ARRAY_SIZE(stm32mp1_supported_soc_modes)] = { }; ++ const void *prop = 0; ++ ++ prop = fdt_getprop(fdt, pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES, &len); ++ if (!prop) ++ 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, ++ &supported[0], count) < 0) ++ panic("PWR DT"); ++ ++ for (i = 0; i < count; i++) { ++ if (supported[i] >= STM32_PM_MAX_SOC_MODE) ++ panic("Invalid mode"); ++ ++ stm32mp1_supported_soc_modes[supported[i]] = true; ++ } ++} ++#endif ++ ++static bool is_supported_mode(uint32_t soc_mode) ++{ ++ assert(soc_mode < ARRAY_SIZE(stm32mp1_supported_soc_modes)); ++ return stm32mp1_supported_soc_modes[soc_mode] == 1; ++} ++ ++uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode) ++{ ++ uint32_t mode = 0; ++ ++ if (psci_mode == PSCI_MODE_SYSTEM_OFF) ++ return system_off_mode; ++ ++ mode = deepest_suspend_mode; ++ ++ if ((mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) && ++ (!get_pm_domain_state(STM32MP1_PD_CORE_RET) || ++ !is_supported_mode(mode))) ++ mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP; ++ ++ if ((mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP) && ++ (!get_pm_domain_state(STM32MP1_PD_CORE) || ++ !is_supported_mode(mode))) ++ mode = STM32_PM_CSTOP_ALLOW_LP_STOP; ++ ++ if ((mode == STM32_PM_CSTOP_ALLOW_LP_STOP) && ++ !is_supported_mode(mode)) ++ mode = STM32_PM_CSTOP_ALLOW_STOP; ++ ++ if ((mode == STM32_PM_CSTOP_ALLOW_STOP) && ++ !is_supported_mode(mode)) ++ mode = STM32_PM_CSLEEP_RUN; ++ ++ 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 -1; ++ ++ if (psci_mode == PSCI_MODE_SYSTEM_SUSPEND) { ++ deepest_suspend_mode = soc_mode; ++ ++ if (!IS_ENABLED(CFG_STM32_CRYP) && ++ deepest_suspend_mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) ++ deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP; ++ } ++ ++ if (psci_mode == PSCI_MODE_SYSTEM_OFF) ++ system_off_mode = soc_mode; ++ ++ return 0; ++} ++ ++#ifdef CFG_DT ++static int dt_get_pwr_node(void *fdt) ++{ ++ return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); ++} ++ ++static TEE_Result stm32mp1_init_lp_states(void) ++{ ++ void *fdt = NULL; ++ int pwr_node = -1; ++ const fdt32_t *cuint = NULL; ++ ++ fdt = get_embedded_dt(); ++ if (fdt) ++ pwr_node = dt_get_pwr_node(fdt); ++ ++ if (pwr_node >= 0) ++ cuint = fdt_getprop(fdt, pwr_node, SYSTEM_OFF_MODE, NULL); ++ ++ if (!fdt || (pwr_node < 0) || !cuint) { ++ IMSG("No power configuration found in DT"); ++ return TEE_SUCCESS; ++ } ++ ++ system_off_mode = fdt32_to_cpu(*cuint); ++ ++ /* Initialize suspend support to the deepest possible mode */ ++ if (IS_ENABLED(CFG_STM32_CRYP)) ++ deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR; ++ else ++ deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP; ++ ++ save_supported_mode(fdt, pwr_node); ++ ++ DMSG("Power configuration: shutdown to %u, suspend to %u", ++ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF), ++ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND)); ++ ++ return TEE_SUCCESS; ++} ++#else ++static TEE_Result stm32mp1_init_lp_states(void) ++{ ++ if (IS_ENABLED(CFG_STM32_CRYP)) ++ deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR; ++ else ++ deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP; ++ ++ system_off_mode = STM32_PM_SHUTDOWN; ++ ++ DMSG("Power configuration: shutdown to %u, suspend to %u", ++ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF), ++ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND)); ++ ++ return TEE_SUCCESS; ++} ++#endif ++service_init(stm32mp1_init_lp_states); +diff --git a/core/arch/arm/plat-stm32mp1/pm/psci.c b/core/arch/arm/plat-stm32mp1/pm/psci.c +index 740b13b..ff7b966 100644 +--- a/core/arch/arm/plat-stm32mp1/pm/psci.c ++++ b/core/arch/arm/plat-stm32mp1/pm/psci.c +@@ -5,11 +5,18 @@ + + #include + #include ++#include + #include ++#include ++#include + #include + #include + #include ++#include ++#include ++#include + #include ++#include + #include + #include + #include +@@ -19,10 +26,17 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include + #include ++#include ++ ++#include "context.h" ++#include "power.h" + + #define CONSOLE_FLUSH_DELAY_MS 10 + +@@ -56,10 +70,9 @@ int psci_affinity_info(uint32_t affinity, uint32_t lowest_affinity_level) + + DMSG("core %zu, state %u", pos, core_state[pos]); + +- if ((pos >= CFG_TEE_CORE_NB_CORE) || +- (lowest_affinity_level > PSCI_AFFINITY_LEVEL_ON)) { ++ if (pos >= CFG_TEE_CORE_NB_CORE || ++ lowest_affinity_level > PSCI_AFFINITY_LEVEL_ON) + return PSCI_RET_INVALID_PARAMETERS; +- } + + switch (core_state[pos]) { + case CORE_OFF: +@@ -81,35 +94,24 @@ int psci_affinity_info(uint32_t affinity, uint32_t lowest_affinity_level) + */ + void stm32mp_register_online_cpu(void) + { +- assert(core_state[0] == CORE_OFF); ++ assert(core_state[0] == CORE_OFF || core_state[0] == CORE_RET); + core_state[0] = CORE_ON; + } + #else +-static void __noreturn stm32_pm_cpu_power_down_wfi(void) +-{ +- dcache_op_level1(DCACHE_OP_CLEAN); +- +- io_write32(stm32_rcc_base() + RCC_MP_GRSTCSETR, +- RCC_MP_GRSTCSETR_MPUP1RST); +- +- dsb(); +- isb(); +- wfi(); +- panic(); +-} +- + void stm32mp_register_online_cpu(void) + { + size_t pos = get_core_pos(); + uint32_t exceptions = lock_state_access(); + + if (pos == 0) { +- assert(core_state[pos] == CORE_OFF); ++ assert((core_state[pos] == CORE_OFF) || ++ (core_state[pos] == CORE_RET)); + } else { + if (core_state[pos] != CORE_AWAKE) { + core_state[pos] = CORE_OFF; + unlock_state_access(exceptions); +- stm32_pm_cpu_power_down_wfi(); ++ if (IS_ENABLED(CFG_PM)) ++ stm32_pm_cpu_power_down_wfi(); + panic(); + } + } +@@ -132,11 +134,15 @@ static void release_secondary_early_hpen(size_t __unused pos) + raise_sgi0_as_secure(); + udelay(20); + ++ stm32_clock_enable(RTCAPB); ++ + io_write32(stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS), + TEE_LOAD_ADDR); + io_write32(stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER), + BOOT_API_A7_CORE1_MAGIC_NUMBER); + ++ stm32_clock_disable(RTCAPB); ++ + dsb_ishst(); + itr_raise_sgi(GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); + } +@@ -204,42 +210,189 @@ int psci_cpu_off(void) + + unlock_state_access(exceptions); + ++ /* Enable BKPREG access for the disabled CPU */ ++ stm32_clock_enable(RTCAPB); ++ + thread_mask_exceptions(THREAD_EXCP_ALL); +- stm32_pm_cpu_power_down_wfi(); ++ if (IS_ENABLED(CFG_PM)) ++ stm32_pm_cpu_power_down_wfi(); + panic(); + } + #endif + +-/* Override default psci_system_off() with platform specific sequence */ +-void __noreturn psci_system_off(void) ++#ifdef CFG_PM ++static int enter_cstop_suspend(unsigned int soc_mode) + { +- DMSG("core %u", get_core_pos()); ++ int rc = 1; ++ ++ if (read_isr()) ++ return rc; ++ ++ stm32_enter_cstop(soc_mode); ++ ++ if (need_to_backup_cpu_context(soc_mode)) { ++ stm32_pm_cpu_power_down_wfi(); ++ } else { ++ stm32_pm_cpu_wfi(); ++ rc = 0; ++ } ++ ++ stm32_exit_cstop(); ++ ++ return rc; ++} ++ ++static int plat_suspend(uint32_t arg) ++{ ++ unsigned int soc_mode = arg; ++ size_t pos = get_core_pos(); ++ int rc = 1; ++ ++ if (read_isr()) ++ return rc; ++ ++ /* No need to lock state access as CPU is alone when here */ ++ assert(core_state[pos] == CORE_ON); ++ core_state[pos] = CORE_RET; ++ ++ if (stm32mp_pm_save_context(soc_mode) == TEE_SUCCESS) ++ rc = enter_cstop_suspend(soc_mode); ++ ++ stm32mp_pm_restore_context(soc_mode); ++ stm32mp_pm_wipe_context(); ++ ++ assert(core_state[pos] == CORE_RET); ++ core_state[pos] = CORE_ON; ++ ++ return rc; ++} ++ ++static void plat_resume(uint32_t arg) ++{ ++ unsigned int soc_mode = arg; ++ ++ stm32mp_register_online_cpu(); ++ ++ assert(core_state[get_core_pos()] == CORE_ON); ++ ++ stm32mp_pm_restore_context(soc_mode); ++} ++ ++static bool plat_can_suspend(void) ++{ ++ size_t pos = get_core_pos(); ++ size_t n = 0; ++ uint32_t exceptions = 0; ++ bool rc = true; + +- if (TRACE_LEVEL >= TRACE_DEBUG) { +- console_flush(); +- mdelay(CONSOLE_FLUSH_DELAY_MS); ++ if (!IS_ENABLED(CFG_STM32_RNG)) ++ return false; ++ ++ if (CFG_TEE_CORE_NB_CORE == 1) ++ return true; ++ ++ exceptions = lock_state_access(); ++ ++ for (n = 0; n < ARRAY_SIZE(core_state); n++) { ++ if (n == pos) ++ continue; ++ ++ if (core_state[n] == CORE_AWAKE) { ++ /* State core as lost and proceed suspend */ ++ core_state[n] = CORE_OFF; ++ } ++ ++ if (core_state[n] != CORE_OFF) ++ rc = false; + } + +- if (stm32mp_with_pmic()) { +- stm32mp_get_pmic(); +- stpmic1_switch_off(); +- udelay(100); ++ unlock_state_access(exceptions); ++ ++ return rc; ++} ++ ++/* Override default psci_system_suspend() with platform specific sequence */ ++int psci_system_suspend(uintptr_t entry, uint32_t context_id __unused, ++ struct sm_nsec_ctx *nsec) ++{ ++ int ret = PSCI_RET_INVALID_PARAMETERS; ++ uint32_t soc_mode = 0; ++ int __maybe_unused pos = get_core_pos(); ++ ++ DMSG("core %u", pos); ++ ++ if (!plat_can_suspend()) ++ return PSCI_RET_DENIED; ++ ++ soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND); ++ ++ switch (soc_mode) { ++ case STM32_PM_CSLEEP_RUN: ++ stm32_enter_csleep(); ++ nsec->mon_lr = (uint32_t)entry; ++ return PSCI_RET_SUCCESS; ++ case STM32_PM_SHUTDOWN: ++ stm32_enter_cstop_shutdown(soc_mode); ++ panic(); ++ default: ++ /* Others are suspended mode: at least some context to backup */ ++ break; + } + +- panic(); ++ assert(cpu_mmu_enabled() && core_state[pos] == CORE_ON); ++ ++ if (need_to_backup_cpu_context(soc_mode)) { ++ if (!IS_ENABLED(CFG_STM32_CRYP)) ++ return PSCI_RET_DENIED; ++ ++ sm_save_unbanked_regs(&nsec->ub_regs); ++ /* ++ * sm_pm_cpu_suspend(arg, func) saves the CPU core context in TEE RAM ++ * then calls func(arg) to run the platform lower power sequence. ++ * ++ * If platform fails to suspend, sm_pm_cpu_suspend() returns with a ++ * non null return code. When sm_pm_cpu_suspend() returns 0 platform ++ * context must be restored. ++ */ ++ ret = sm_pm_cpu_suspend((uint32_t)soc_mode, plat_suspend); ++ if (ret == 0) { ++ plat_resume((uint32_t)soc_mode); ++ sm_restore_unbanked_regs(&nsec->ub_regs); ++ } ++ } else { ++ ret = plat_suspend((uint32_t)soc_mode); ++ } ++ ++ if (ret == 0) { ++ nsec->mon_lr = (uint32_t)entry; ++ IMSG("Resumed"); ++ return PSCI_RET_SUCCESS; ++ } ++ ++ return PSCI_RET_INTERNAL_FAILURE; ++} ++ ++/* Override default psci_system_off() with platform specific sequence */ ++void __noreturn psci_system_off(void) ++{ ++ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF); ++ ++ DMSG("core %u", get_core_pos()); ++ ++ stm32_enter_cstop_shutdown(soc_mode); + } + + /* Override default psci_system_reset() with platform specific sequence */ + void __noreturn psci_system_reset(void) + { +- vaddr_t rcc_base = stm32_rcc_base(); ++ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF); + + DMSG("core %u", get_core_pos()); + +- io_write32(rcc_base + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); +- udelay(100); +- panic(); ++ stm32_enter_cstop_reset(soc_mode); + } ++#endif /*CFG_PM*/ ++ + + /* Override default psci_cpu_on() with platform supported features */ + int psci_features(uint32_t psci_fid) +@@ -256,6 +409,7 @@ int psci_features(uint32_t psci_fid) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; + case PSCI_SYSTEM_OFF: ++ case PSCI_SYSTEM_SUSPEND: + if (stm32mp_with_pmic()) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; +diff --git a/core/arch/arm/plat-stm32mp1/pm/sub.mk b/core/arch/arm/plat-stm32mp1/pm/sub.mk +index c8ae8f9..d652958 100644 +--- a/core/arch/arm/plat-stm32mp1/pm/sub.mk ++++ b/core/arch/arm/plat-stm32mp1/pm/sub.mk +@@ -1 +1,7 @@ ++asm-defines-y += context_asm_defines.c ++ ++srcs-$(CFG_PM) += context.c ++srcs-$(CFG_PM) += low_power.c ++srcs-$(CFG_PM) += pm_helpers.S ++srcs-$(CFG_PM) += power_config.c + srcs-$(CFG_PSCI_ARM32) += psci.c +diff --git a/core/arch/arm/plat-stm32mp1/reset.S b/core/arch/arm/plat-stm32mp1/reset.S +index 69ab151..6a8ac06 100644 +--- a/core/arch/arm/plat-stm32mp1/reset.S ++++ b/core/arch/arm/plat-stm32mp1/reset.S +@@ -3,7 +3,7 @@ + * Copyright (c) 2018, STMicroelectronics + */ + +-#include ++#include + #include + #include + #include +@@ -23,8 +23,34 @@ UNWIND( .fnstart) + mov_imm r1, STM32MP1_NSACR_PRESERVE_MASK + and r0, r0, r1 + write_nsacr r0 ++ isb ++ ++ read_actlr r0 ++ orr r0, r0, #ACTLR_SMP ++ write_actlr r0 ++ ++ /* ++ * Always reset CNTVOFF for the dear non secure world. ++ * This operation requires being in Monitor mode and ++ * non secure state. ++ */ ++ mrs r1, cpsr ++ cps #CPSR_MODE_MON ++ isb ++ ++ read_scr r2 ++ orr r0, r2, #SCR_NS ++ write_scr r0 ++ isb ++ ++ mov r0, #0 ++ write_cntvoff r0, r0 + ++ write_scr r2 + isb +- bx lr ++ msr cpsr, r1 ++ isb ++ ++ bx lr + UNWIND( .fnend) + END_FUNC plat_cpu_reset_early +diff --git a/core/arch/arm/plat-stm32mp1/scmi_server.c b/core/arch/arm/plat-stm32mp1/scmi_server.c +index ddc19ca..5116b89 100644 +--- a/core/arch/arm/plat-stm32mp1/scmi_server.c ++++ b/core/arch/arm/plat-stm32mp1/scmi_server.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -276,8 +277,21 @@ const char *plat_scmi_clock_get_name(unsigned int agent_id, + return clock->name; + } + +-int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, +- unsigned long *array, size_t *nb_elts) ++int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused, ++ unsigned int scmi_id __unused, ++ unsigned long *array __unused, ++ size_t *nb_elts __unused) ++{ ++ /* ++ * Explicitly do not expose clock rates by array since not ++ * fully supported by Linux kernel as of v5.4.24. ++ */ ++ 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); + +@@ -287,12 +301,48 @@ int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, + if (!stm32mp_nsec_can_access_clock(clock->clock_id)) + return SCMI_DENIED; + +- if (!array) +- *nb_elts = 1; +- else if (*nb_elts == 1) +- *array = stm32_clock_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] = stm32_clock_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); ++ int ret = SCMI_DENIED; ++ ++ if (!clock) ++ return SCMI_NOT_FOUND; ++ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) ++ return SCMI_DENIED; ++ ++ switch (scmi_id) { ++ case CK_SCMI0_MPU: ++ ret = stm32mp1_set_opp_khz(rate / 1000); ++ if (ret) ++ return SCMI_INVALID_PARAMETERS; ++ break; ++ default: ++ if (rate != stm32_clock_get_rate(clock->clock_id)) ++ return SCMI_INVALID_PARAMETERS; ++ break; ++ } + + return SCMI_SUCCESS; + } +@@ -432,6 +482,19 @@ int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id, + return SCMI_SUCCESS; + } + ++static TEE_Result stm32_scmi_pm(enum pm_op op, unsigned int pm_hint __unused, ++ const struct pm_callback_handle *hdl __unused) ++{ ++ size_t i = 0; ++ ++ if (op == PM_OP_RESUME) ++ for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) ++ scmi_smt_init_agent_channel(&scmi_channel[i]); ++ ++ return TEE_SUCCESS; ++} ++DECLARE_KEEP_PAGER(stm32_scmi_pm); ++ + /* + * Initialize platform SCMI resources + */ +@@ -440,6 +503,8 @@ static TEE_Result stm32mp1_init_scmi_server(void) + size_t i = 0; + size_t j = 0; + ++ register_pm_driver_cb(stm32_scmi_pm, NULL); ++ + for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) { + struct scmi_msg_channel *chan = &scmi_channel[i]; + +diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c +index e321ec8..08aa9a3 100644 +--- a/core/arch/arm/plat-stm32mp1/shared_resources.c ++++ b/core/arch/arm/plat-stm32mp1/shared_resources.c +@@ -650,27 +650,36 @@ static void check_rcc_secure_configuration(void) + { + bool secure = stm32_rcc_is_secure(); + bool mckprot = stm32_rcc_is_mckprot(); ++ bool need_secure = false; ++ bool need_mckprot = false; + enum stm32mp_shres id = STM32MP1_SHRES_COUNT; +- bool have_error = false; + +- if (stm32mp_is_closed_device() && !secure) +- panic(); ++ if (stm32mp_is_closed_device() && !secure) { ++ DMSG("stm32mp1: closed device mandates OP-TEE to secure RCC"); ++ need_secure = true; ++ } + + for (id = 0; id < STM32MP1_SHRES_COUNT; id++) { + if (shres_state[id] != SHRES_SECURE) + continue; + +- if ((mckprot_resource(id) && !mckprot) || !secure) { +- EMSG("RCC %s MCKPROT %s and %s (%u) secure", +- secure ? "secure" : "non-secure", +- mckprot ? "set" : "not set", +- shres2str_id(id), id); +- have_error = true; +- } ++ need_secure = true; ++ if (mckprot_resource(id)) ++ need_mckprot = true; ++ ++ if ((mckprot_resource(id) && !mckprot) || !secure) ++ EMSG("Error: RCC TZEN=%u MCKPROT=%u while %s is secure", ++ secure, mckprot, shres2str_id(id)); + } + +- if (have_error) ++ DMSG("RCC/PWR secure hardening: TZEN %sable, MCKPROT %sable", ++ secure ? "en" : "dis", mckprot ? "en" : "dis"); ++ ++ if (need_secure && !secure) + panic(); ++ ++ if (need_mckprot) ++ io_setbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_MCKPROT); + } + + static void set_gpio_secure_configuration(void) +diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h +index 5572dae..9c86cd2 100644 +--- a/core/arch/arm/plat-stm32mp1/stm32_util.h ++++ b/core/arch/arm/plat-stm32mp1/stm32_util.h +@@ -9,11 +9,23 @@ + #include + #include + #include ++#include + #include + #include + ++/* SoC versioning and device ID */ ++TEE_Result stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version); ++TEE_Result stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id); ++ ++/* OPP service */ ++bool stm32mp_supports_cpu_opp(uint32_t opp_id); ++ + /* Backup registers and RAM utils */ + vaddr_t stm32mp_bkpreg(unsigned int idx); ++vaddr_t stm32mp_bkpsram_base(void); ++ ++/* Platform util for the STGEN driver */ ++vaddr_t stm32mp_stgen_base(void); + + /* + * SYSCFG IO compensation. +@@ -25,6 +37,7 @@ void stm32mp_syscfg_disable_io_compensation(void); + /* Platform util for the GIC */ + vaddr_t get_gicc_base(void); + vaddr_t get_gicd_base(void); ++void stm32mp_gic_set_end_of_interrupt(uint32_t it); + + /* + * Platform util functions for the GPIO driver +@@ -43,6 +56,18 @@ vaddr_t stm32_get_gpio_bank_base(unsigned int bank); + unsigned int stm32_get_gpio_bank_offset(unsigned int bank); + unsigned int stm32_get_gpio_bank_clock(unsigned int bank); + ++/* ++ * Platform util for the IWDG driver ++ */ ++ ++/* Get IWDG_* enable flags mask from watchdog configuration read from fuses */ ++unsigned long stm32_get_iwdg_otp_config(vaddr_t pbase); ++ ++/* Conversion between IWDG instance IDs and hardware resources */ ++size_t stm32mp_iwdg_instance2irq(unsigned int instance); ++unsigned int stm32mp_iwdg_irq2instance(size_t irq); ++unsigned int stm32mp_iwdg_iomem2instance(vaddr_t pbase); ++ + /* Platform util for PMIC support */ + bool stm32mp_with_pmic(void); + +@@ -74,6 +99,19 @@ bool stm32_clock_is_enabled(unsigned long id); + /* Return true if @clock_id is shared by secure and non-secure worlds */ + bool stm32mp_nsec_can_access_clock(unsigned long clock_id); + ++/* PM sequences specific to SoC STOP mode support */ ++void stm32mp1_clk_save_context_for_stop(void); ++void stm32mp1_clk_restore_context_for_stop(void); ++ ++/* ++ * Util for PLL1 settings management based on DT OPP table content. ++ */ ++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); ++bool stm32mp1_clk_pll1_settings_are_valid(void); ++int stm32mp1_set_opp_khz(uint32_t freq_khz); ++int stm32mp1_round_opp_khz(uint32_t *freq_khz); ++ + /* + * Util for reset signal assertion/desassertion for stm32 and platform drivers + * @id: Target peripheral ID, ID used in reset DT bindings +@@ -110,6 +148,22 @@ struct stm32_bsec_static_cfg { + + void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg); + ++/* Reset function for early watchdog management */ ++void stm32mp_platform_reset(int cpu); ++ ++/* Clock calibration. Returns 0 on success */ ++#ifdef CFG_STM32_CLKCALIB ++int stm32mp_start_clock_calib(unsigned int clock_id); ++#else ++static inline int stm32mp_start_clock_calib(unsigned int clock_id __unused) ++{ ++ return 1; ++} ++#endif ++ ++/* Platform util for the RTC driver */ ++bool stm32_rtc_get_read_twice(void); ++ + /* + * Return true if platform is in closed_device mode + */ +diff --git a/core/arch/arm/plat-stm32mp1/stm32mp_pm.h b/core/arch/arm/plat-stm32mp1/stm32mp_pm.h +new file mode 100644 +index 0000000..4265db9 +--- /dev/null ++++ b/core/arch/arm/plat-stm32mp1/stm32mp_pm.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2017-2018, STMicroelectronics ++ */ ++#ifndef __STM32MP_PM_H__ ++#define __STM32MP_PM_H__ ++ ++#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 __noreturn stm32_cores_reset(void); ++ ++#endif /*__STM32MP_PM_H__*/ ++ +diff --git a/core/arch/arm/sm/pm_a32.S b/core/arch/arm/sm/pm_a32.S +index 9421b2d..8a59cd2 100644 +--- a/core/arch/arm/sm/pm_a32.S ++++ b/core/arch/arm/sm/pm_a32.S +@@ -69,25 +69,30 @@ a9_suspend: + a7_suspend: + read_fcseidr r4 + read_tpidruro r5 +- stmia r0!, {r4 - r5} +- read_dacr r4 ++ read_dacr r6 ++ stmia r0!, {r4 - r6} + #ifdef CFG_WITH_LPAE +-#error "Not supported" ++ read_ttbr0_64bit r4, r5 ++ read_ttbr1_64bit r6, r7 ++ read_mair0 r8 ++ read_mair1 r9 ++ stmia r0!, {r4 - r9} + #else +- read_ttbr0 r5 +- read_ttbr1 r6 +- read_ttbcr r7 ++ read_ttbr0 r4 ++ read_ttbr1 r5 ++ read_prrr r6 ++ read_nmrr r7 ++ stmia r0!, {r4 - r7} + #endif +- read_sctlr r8 +- read_actlr r9 +- read_cpacr r10 +- read_mvbar r11 +- stmia r0!, {r4 - r11} +- read_prrr r4 +- read_nmrr r5 +- read_vbar r6 +- read_nsacr r7 +- stmia r0, {r4 - r7} ++ read_ttbcr r4 ++ read_actlr r5 ++ read_cpacr r6 ++ read_mvbar r7 ++ read_vbar r8 ++ read_nsacr r9 ++ read_sctlr r10 ++ stmia r0, {r4 - r10} ++ + pop {r4 - r11} + bx lr + UNWIND( .fnend) +@@ -154,50 +159,50 @@ UNWIND( .cantunwind) + cmp r5, r4 + beq a7_resume + +- /* +- * A9 needs PCR/DIAG +- */ ++ /* A9 needs PCR/DIAG */ + ldmia r0!, {r4 - r5} + write_pcr r4 + write_diag r5 +- + a7_resume: +- /* v7 resume */ ++ /* Armv7 generic resume */ + mov ip, #0 + /* Invalidate icache to PoU */ + write_iciallu + /* set reserved context */ + write_contextidr ip +- ldmia r0!, {r4 - r5} ++ ldmia r0!, {r4 - r6} + write_fcseidr r4 + write_tpidruro r5 +- ldmia r0!, {r4 - r11} + /* Invalidate entire TLB */ + write_tlbiall +- write_dacr r4 ++ write_dacr r6 + #ifdef CFG_WITH_LPAE +-#error "Not supported -" ++ ldmia r0!, {r4 - r9} ++ write_ttbr0_64bit r4, r5 ++ write_ttbr1_64bit r6, r7 ++ write_mair0 r8 ++ write_mair1 r9 + #else +- write_ttbr0 r5 +- write_ttbr1 r6 +- write_ttbcr r7 ++ ldmia r0!, {r4 - r7} ++ write_ttbr0 r4 ++ write_ttbr1 r5 ++ write_prrr r6 ++ write_nmrr r7 + #endif +- +- ldmia r0, {r4 - r7} +- write_prrr r4 +- write_nmrr r5 +- write_vbar r6 +- write_nsacr r7 +- +- write_actlr r9 +- write_cpacr r10 +- write_mvbar r11 ++ ldmia r0!, {r4 - r10} ++ write_ttbcr r4 ++ write_actlr r5 ++ write_cpacr r6 ++ write_mvbar r7 ++ write_vbar r8 ++ write_nsacr r9 + write_bpiall + isb + dsb + /* MMU will be enabled here */ +- write_sctlr r8 ++ write_sctlr r10 + isb ++ + mov r0, #0 + b suspend_return + UNWIND( .fnend) +diff --git a/core/arch/arm/tee/entry_std.c b/core/arch/arm/tee/entry_std.c +index 5c1e8c2..60aed6c 100644 +--- a/core/arch/arm/tee/entry_std.c ++++ b/core/arch/arm/tee/entry_std.c +@@ -535,4 +535,4 @@ static TEE_Result default_mobj_init(void) + return TEE_SUCCESS; + } + +-driver_init_late(default_mobj_init); ++service_init(default_mobj_init); +diff --git a/core/drivers/gic.c b/core/drivers/gic.c +index 0bad974..3f1a606 100644 +--- a/core/drivers/gic.c ++++ b/core/drivers/gic.c +@@ -7,12 +7,15 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include + #include +-#include + #include ++#include + + /* Offsets from gic.gicc_base */ + #define GICC_CTLR (0x000) +@@ -33,9 +36,11 @@ + #define GICD_ICENABLER(n) (0x180 + (n) * 4) + #define GICD_ISPENDR(n) (0x200 + (n) * 4) + #define GICD_ICPENDR(n) (0x280 + (n) * 4) ++#define GICD_ISACTIVER(n) (0x300 + (n) * 4) + #define GICD_IPRIORITYR(n) (0x400 + (n) * 4) + #define GICD_ITARGETSR(n) (0x800 + (n) * 4) + #define GICD_IGROUPMODR(n) (0xd00 + (n) * 4) ++#define GICD_ICFGR(n) (0xc00 + (n) * 4) + #define GICD_SGIR (0xF00) + + #define GICD_CTLR_ENABLEGRP0 (1 << 0) +@@ -76,6 +81,25 @@ static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, + static void gic_op_set_affinity(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); + ++#if defined(CFG_ARM_GIC_PM) ++static void gic_pm_add_it(struct gic_data *gd, unsigned int it); ++static void gic_pm_register(struct gic_data *gd); ++#else ++static void gic_pm_add_it(struct gic_data *gd __unused, ++ unsigned int it __unused) ++{ ++} ++static void gic_pm_register(struct gic_data *gd __unused) ++{ ++} ++#endif ++ ++#if !defined(CFG_ARM_GICV3) ++static uint8_t gic_op_set_pmr(struct itr_chip *chip, uint8_t mask); ++static uint8_t gic_op_set_ipriority(struct itr_chip *chip, size_t it, ++ uint8_t mask); ++#endif ++ + static const struct itr_ops gic_ops = { + .add = gic_op_add, + .enable = gic_op_enable, +@@ -83,6 +107,10 @@ static const struct itr_ops gic_ops = { + .raise_pi = gic_op_raise_pi, + .raise_sgi = gic_op_raise_sgi, + .set_affinity = gic_op_set_affinity, ++#if !defined(CFG_ARM_GICV3) ++ .set_pmr = gic_op_set_pmr, ++ .set_ipriority = gic_op_set_ipriority, ++#endif + }; + DECLARE_KEEP_PAGER(gic_ops); + +@@ -148,10 +176,10 @@ void gic_cpu_init(struct gic_data *gd) + * allow the Non-secure world to adjust the priority mask itself + */ + #if defined(CFG_ARM_GICV3) +- write_icc_pmr(0x80); ++ write_icc_pmr(GIC_HIGHEST_NS_PRIORITY); + write_icc_igrpen1(1); + #else +- io_write32(gd->gicc_base + GICC_PMR, 0x80); ++ io_write32(gd->gicc_base + GICC_PMR, GIC_HIGHEST_NS_PRIORITY); + + /* Enable GIC */ + io_write32(gd->gicc_base + GICC_CTLR, +@@ -160,13 +188,10 @@ void gic_cpu_init(struct gic_data *gd) + #endif + } + +-void gic_init(struct gic_data *gd, vaddr_t gicc_base __maybe_unused, +- vaddr_t gicd_base) ++void gic_init_setup(struct gic_data *gd) + { + size_t n; + +- gic_init_base_addr(gd, gicc_base, gicd_base); +- + for (n = 0; n <= gd->max_it / NUM_INTS_PER_REG; n++) { + /* Disable interrupts */ + io_write32(gd->gicd_base + GICD_ICENABLER(n), 0xffffffff); +@@ -191,11 +216,11 @@ void gic_init(struct gic_data *gd, vaddr_t gicc_base __maybe_unused, + * allow the Non-secure world to adjust the priority mask itself + */ + #if defined(CFG_ARM_GICV3) +- write_icc_pmr(0x80); ++ write_icc_pmr(GIC_HIGHEST_NS_PRIORITY); + write_icc_igrpen1(1); + io_setbits32(gd->gicd_base + GICD_CTLR, GICD_CTLR_ENABLEGRP1S); + #else +- io_write32(gd->gicc_base + GICC_PMR, 0x80); ++ io_write32(gd->gicc_base + GICC_PMR, GIC_HIGHEST_NS_PRIORITY); + + /* Enable GIC */ + io_write32(gd->gicc_base + GICC_CTLR, GICC_CTLR_FIQEN | +@@ -212,6 +237,14 @@ void gic_init_base_addr(struct gic_data *gd, vaddr_t gicc_base __maybe_unused, + gd->gicd_base = gicd_base; + gd->max_it = probe_max_it(gicc_base, gicd_base); + gd->chip.ops = &gic_ops; ++ ++ gic_pm_register(gd); ++} ++ ++void gic_init(struct gic_data *gd, vaddr_t gicc_base, vaddr_t gicd_base) ++{ ++ gic_init_base_addr(gd, gicc_base, gicd_base); ++ gic_init_setup(gd); + } + + static void gic_it_add(struct gic_data *gd, size_t it) +@@ -236,7 +269,8 @@ static void gic_it_set_cpu_mask(struct gic_data *gd, size_t it, + { + size_t idx __maybe_unused = it / NUM_INTS_PER_REG; + uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); +- uint32_t target, target_shift; ++ uint32_t target = 0; ++ uint32_t target_shift = 0; + vaddr_t itargetsr = gd->gicd_base + + GICD_ITARGETSR(it / NUM_TARGETS_PER_REG); + +@@ -258,15 +292,39 @@ static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio) + size_t idx __maybe_unused = it / NUM_INTS_PER_REG; + uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); + +- /* Assigned to group0 */ +- assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); +- + /* Set prio it to selected CPUs */ + DMSG("prio: writing 0x%x to 0x%" PRIxVA, + prio, gd->gicd_base + GICD_IPRIORITYR(0) + it); + io_write8(gd->gicd_base + GICD_IPRIORITYR(0) + it, prio); + } + ++static uint8_t gic_op_set_pmr(struct itr_chip *chip, uint8_t mask) ++{ ++ struct gic_data *gd = container_of(chip, struct gic_data, chip); ++ uint32_t pmr = io_read32(gd->gicc_base + GICC_PMR); ++ ++ /* ++ * Order memory updates w.r.t. PMR write, and ensure they're visible ++ * before potential out of band interrupt trigger because of PMR update. ++ */ ++ dsb_ishst(); ++ io_write32(gd->gicc_base + GICC_PMR, mask); ++ dsb_ishst(); ++ ++ return (uint8_t)pmr; ++} ++ ++static uint8_t gic_op_set_ipriority(struct itr_chip *chip, size_t it, ++ uint8_t mask) ++{ ++ struct gic_data *gd = container_of(chip, struct gic_data, chip); ++ uint8_t prio = io_read8(gd->gicd_base + GICD_IPRIORITYR(0) + it); ++ ++ gic_it_set_prio(gd, it, mask); ++ ++ return prio; ++} ++ + static void gic_it_enable(struct gic_data *gd, size_t it) + { + size_t idx = it / NUM_INTS_PER_REG; +@@ -391,8 +449,8 @@ void gic_dump_state(struct gic_data *gd) + + void gic_it_handle(struct gic_data *gd) + { +- uint32_t iar; +- uint32_t id; ++ uint32_t iar = 0; ++ uint32_t id = 0; + + iar = gic_read_iar(gd); + id = iar & GICC_IAR_IT_ID_MASK; +@@ -417,6 +475,8 @@ static void gic_op_add(struct itr_chip *chip, size_t it, + /* Set the CPU mask to deliver interrupts to any online core */ + gic_it_set_cpu_mask(gd, it, 0xff); + gic_it_set_prio(gd, it, 0x1); ++ ++ gic_pm_add_it(gd, it); + } + + static void gic_op_enable(struct itr_chip *chip, size_t it) +@@ -462,6 +522,7 @@ static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, + else + gic_it_raise_sgi(gd, it, cpu_mask, 0); + } ++ + static void gic_op_set_affinity(struct itr_chip *chip, size_t it, + uint8_t cpu_mask) + { +@@ -472,3 +533,137 @@ static void gic_op_set_affinity(struct itr_chip *chip, size_t it, + + gic_it_set_cpu_mask(gd, it, cpu_mask); + } ++ ++#if defined(CFG_ARM_GIC_PM) ++/* ++ * Save/restore interrupts registered from the gic_op_add_it() handler ++ */ ++#define IT_PM_GPOUP1_BIT BIT(0) ++#define IT_PM_ENABLE_BIT BIT(1) ++#define IT_PM_PENDING_BIT BIT(2) ++#define IT_PM_ACTIVE_BIT BIT(3) ++#define IT_PM_CONFIG_MASK GENMASK_32(1, 0) ++ ++/* ++ * @it - interrupt ID/number ++ * @flags - bitflag IT_PM_*_BIT ++ * @iprio - 8bit prio from IPRIORITYR ++ * @itarget - 8bit target from ITARGETR ++ * @icfg - 2bit configuration from ICFGR and IT_PM_CONFIG_MASK ++ */ ++struct gic_it_pm { ++ uint16_t it; ++ uint8_t flags; ++ uint8_t iprio; ++ uint8_t itarget; ++ uint8_t icfg; ++}; ++ ++static void gic_pm_add_it(struct gic_data *gd, unsigned int it) ++{ ++ struct gic_pm *pm = &gd->pm; ++ ++ pm->count++; ++ pm->pm_cfg = realloc(pm->pm_cfg, pm->count * sizeof(*pm->pm_cfg)); ++ if (!pm->pm_cfg) ++ panic(); ++ ++ pm->pm_cfg[pm->count - 1] = (struct gic_it_pm){ .it = it }; ++} ++ ++static void gic_save_it(struct gic_data *gd, struct gic_it_pm *pm) ++{ ++ unsigned int it = pm->it; ++ size_t idx = 0; ++ uint32_t bit_mask = BIT(it % NUM_INTS_PER_REG); ++ uint32_t shift2 = it % (NUM_INTS_PER_REG / 2); ++ uint32_t shift8 = it % (NUM_INTS_PER_REG / 8); ++ uint32_t data32 = 0; ++ ++ pm->flags = 0; ++ idx = it / NUM_INTS_PER_REG; ++ ++ if (io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & bit_mask) ++ pm->flags |= IT_PM_GPOUP1_BIT; ++ if (io_read32(gd->gicd_base + GICD_ISENABLER(idx)) & bit_mask) ++ pm->flags |= IT_PM_ENABLE_BIT; ++ if (io_read32(gd->gicd_base + GICD_ISPENDR(idx)) & bit_mask) ++ pm->flags |= IT_PM_PENDING_BIT; ++ if (io_read32(gd->gicd_base + GICD_ISACTIVER(idx)) & bit_mask) ++ pm->flags |= IT_PM_ACTIVE_BIT; ++ ++ idx = (8 * it) / NUM_INTS_PER_REG; ++ ++ data32 = io_read32(gd->gicd_base + GICD_IPRIORITYR(idx)) >> shift8; ++ pm->iprio = (uint8_t)data32; ++ ++ data32 = io_read32(gd->gicd_base + GICD_ITARGETSR(idx)) >> shift8; ++ pm->itarget = (uint8_t)data32; ++ ++ /* Note: ICFGR is RAO for SPIs and PPIs */ ++ idx = (2 * it) / NUM_INTS_PER_REG; ++ data32 = io_read32(gd->gicd_base + GICD_ICFGR(idx)) >> shift2; ++ pm->icfg = (uint8_t)data32 & IT_PM_CONFIG_MASK; ++} ++ ++static void gic_restore_it(struct gic_data *gd, struct gic_it_pm *pm) ++{ ++ unsigned int it = pm->it; ++ size_t idx = it / NUM_INTS_PER_REG; ++ uint32_t mask = BIT(it % NUM_INTS_PER_REG); ++ uint32_t shift2 = it % (NUM_INTS_PER_REG / 2); ++ uint32_t shift8 = it % (NUM_INTS_PER_REG / 8); ++ ++ io_mask32(gd->gicd_base + GICD_IGROUPR(idx), ++ (pm->flags & IT_PM_GPOUP1_BIT) ? mask : 0, mask); ++ ++ io_mask32(gd->gicd_base + GICD_ISENABLER(idx), ++ (pm->flags & IT_PM_ENABLE_BIT) ? mask : 0, mask); ++ ++ io_mask32(gd->gicd_base + GICD_ISPENDR(idx), ++ (pm->flags & IT_PM_PENDING_BIT) ? mask : 0, mask); ++ ++ io_mask32(gd->gicd_base + GICD_ISACTIVER(idx), ++ (pm->flags & IT_PM_ACTIVE_BIT) ? mask : 0, mask); ++ ++ idx = (8 * it) / NUM_INTS_PER_REG; ++ ++ io_mask32(gd->gicd_base + GICD_IPRIORITYR(idx), ++ (uint32_t)pm->iprio << shift8, UINT8_MAX << shift8); ++ ++ io_mask32(gd->gicd_base + GICD_ITARGETSR(idx), ++ (uint32_t)pm->itarget << shift8, UINT8_MAX << shift8); ++ ++ /* Note: ICFGR is WI for SPIs and PPIs */ ++ idx = (2 * it) / NUM_INTS_PER_REG; ++ io_mask32(gd->gicd_base + GICD_ICFGR(idx), ++ (uint32_t)pm->icfg << shift2, IT_PM_CONFIG_MASK << shift2); ++} ++ ++static TEE_Result gic_pm(enum pm_op op, unsigned int pm_hint __unused, ++ const struct pm_callback_handle *handle) ++{ ++ void (*sequence)(struct gic_data *gd, struct gic_it_pm *pm) = NULL; ++ struct gic_it_pm *cfg = NULL; ++ unsigned int n = 0; ++ struct gic_data *gd = (struct gic_data *)PM_CALLBACK_GET_HANDLE(handle); ++ struct gic_pm *pm = &gd->pm; ++ ++ if (op == PM_OP_SUSPEND) { ++ sequence = gic_save_it; ++ } else { ++ gic_init_setup(gd); ++ sequence = gic_restore_it; ++ } ++ for (n = 0, cfg = pm->pm_cfg; n < pm->count; n++, cfg++) ++ sequence(gd, cfg); ++ ++ return TEE_SUCCESS; ++} ++DECLARE_KEEP_PAGER(gic_pm); ++ ++static void gic_pm_register(struct gic_data *gd) ++{ ++ register_pm_core_service_cb(gic_pm, gd); ++} ++#endif /*CFG_ARM_GIC_PM*/ +diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c +index 546ba91..a563f79 100644 +--- a/core/drivers/stm32_bsec.c ++++ b/core/drivers/stm32_bsec.c +@@ -91,10 +91,6 @@ + #define BSEC_MODE_BIST2_LOCK_MASK BIT(7) + + /* BSEC_DEBUG */ +-#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_32(10, 0) + + /* +@@ -138,6 +134,11 @@ static uint32_t otp_max_id(void) + return bsec_dev.max_id; + } + ++static uint32_t otp_upper_base(void) ++{ ++ return bsec_dev.upper_base; ++} ++ + static uint32_t otp_bank_offset(uint32_t otp_id) + { + assert(otp_id <= otp_max_id()); +@@ -363,12 +364,12 @@ TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id) + uint32_t addr = 0; + uint32_t exceptions = 0; + vaddr_t base = bsec_base(); +- uint64_t timeout_ref; ++ uint64_t timeout_ref = 0; + + if (otp_id > otp_max_id()) + return TEE_ERROR_BAD_PARAMETERS; + +- if (otp_id < bsec_dev.upper_base) { ++ if (otp_id < otp_upper_base()) { + addr = otp_id >> ADDR_LOWER_OTP_PERLOCK_SHIFT; + data = DATA_LOWER_OTP_PERLOCK_BIT << + ((otp_id & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); +@@ -521,7 +522,7 @@ TEE_Result stm32_bsec_otp_lock(uint32_t service) + + static size_t nsec_access_array_size(void) + { +- size_t upper_count = otp_max_id() - bsec_dev.upper_base + 1; ++ size_t upper_count = otp_max_id() - otp_upper_base() + 1; + + return ROUNDUP(upper_count, BITS_PER_WORD) / BITS_PER_WORD; + } +@@ -537,16 +538,50 @@ static bool nsec_access_granted(unsigned int index) + + bool stm32_bsec_nsec_can_access_otp(uint32_t otp_id) + { +- return otp_id < bsec_dev.upper_base || +- nsec_access_granted(otp_id - bsec_dev.upper_base); ++ return otp_id < otp_upper_base() || ++ nsec_access_granted(otp_id - otp_upper_base()); ++} ++ ++struct nvmem_layout { ++ char *name; ++ uint32_t otp_id; ++ size_t bit_len; ++}; ++ ++static struct nvmem_layout *nvmem_layout; ++static size_t nvmem_layout_count; ++ ++TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, ++ uint32_t *otp_id, ++ size_t *otp_bit_len) ++{ ++ size_t i = 0; ++ ++ if (!name) ++ return TEE_ERROR_BAD_PARAMETERS; ++ ++ for (i = 0; i < nvmem_layout_count; i++) { ++ if (!nvmem_layout[i].name || strcmp(name, nvmem_layout[i].name)) ++ continue; ++ ++ if (otp_id) ++ *otp_id = nvmem_layout[i].otp_id; ++ ++ if (otp_bit_len) ++ *otp_bit_len = nvmem_layout[i].bit_len; ++ ++ return TEE_SUCCESS; ++ } ++ ++ return TEE_ERROR_ITEM_NOT_FOUND; + } + + #ifdef CFG_DT + static void enable_nsec_access(unsigned int otp_id) + { +- unsigned int idx = (otp_id - bsec_dev.upper_base) / BITS_PER_WORD; ++ unsigned int idx = (otp_id - otp_upper_base()) / BITS_PER_WORD; + +- if (otp_id < bsec_dev.upper_base) ++ if (otp_id < otp_upper_base()) + return; + + if (otp_id > otp_max_id() || stm32_bsec_shadow_register(otp_id)) +@@ -619,6 +654,77 @@ static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) + } + } + ++static void save_dt_nvmem_layout(void *fdt) ++{ ++ const fdt32_t *cells = NULL; ++ int i = 0; ++ int cell_nb = 0; ++ int nvmem_node = 0; ++ ++ nvmem_node = fdt_node_offset_by_compatible(fdt, -1, ++ "st,stm32-nvmem-layout"); ++ if (nvmem_node < 0) ++ return; ++ ++ cells = fdt_getprop(fdt, nvmem_node, "nvmem-cells", &cell_nb); ++ if (!cells) ++ cell_nb = 0; ++ ++ cell_nb /= sizeof(uint32_t); ++ ++ i = fdt_stringlist_count(fdt, nvmem_node, "nvmem-cell-names"); ++ if (i < 0) ++ i = 0; ++ ++ if (cell_nb != i) ++ panic("Inconsistent NVMEM layout"); ++ ++ nvmem_layout = calloc(cell_nb, sizeof(*nvmem_layout)); ++ if (!nvmem_layout) ++ panic(); ++ ++ nvmem_layout_count = (size_t)cell_nb; ++ ++ for (i = 0; i < cell_nb; i++) { ++ const fdt32_t *cuint = NULL; ++ const char *string = NULL; ++ int len = 0; ++ int node = 0; ++ struct nvmem_layout *layout_cell = &nvmem_layout[i]; ++ ++ node = fdt_node_offset_by_phandle(fdt, ++ fdt32_to_cpu(*(cells + i))); ++ if (node < 0) { ++ IMSG("Malformed nvmem_layout node: ignored"); ++ continue; ++ } ++ ++ cuint = fdt_getprop(fdt, node, "reg", &len); ++ if (!cuint || (len != (2 * (int)sizeof(uint32_t)))) { ++ IMSG("Malformed nvmem_layout node: ignored"); ++ continue; ++ } ++ ++ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { ++ IMSG("Misaligned nvmem_layout element: ignored"); ++ continue; ++ } ++ layout_cell->otp_id = fdt32_to_cpu(*cuint) / sizeof(uint32_t); ++ layout_cell->bit_len = fdt32_to_cpu(*(cuint + 1)) * CHAR_BIT; ++ ++ string = fdt_stringlist_get(fdt, nvmem_node, "nvmem-cell-names", ++ i, &len); ++ if (!string || !len) ++ continue; ++ ++ layout_cell->name = calloc(1, len + 1); ++ if (!layout_cell->name) ++ panic(); ++ ++ memcpy(layout_cell->name, string, len); ++ } ++} ++ + static void initialize_bsec_from_dt(void) + { + void *fdt = NULL; +@@ -637,6 +743,8 @@ static void initialize_bsec_from_dt(void) + panic(); + + bsec_dt_otp_nsec_access(fdt, node); ++ ++ save_dt_nvmem_layout(fdt); + } + #else + static void initialize_bsec_from_dt(void) +diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c +new file mode 100644 +index 0000000..5073663 +--- /dev/null ++++ b/core/drivers/stm32_iwdg.c +@@ -0,0 +1,313 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* IWDG Compatibility */ ++#define IWDG_COMPAT "st,stm32mp1-iwdg" ++#define IWDG_TIMEOUT_US 100000U ++ ++/* 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_32(11, 0) ++ ++struct stm32_iwdg_instance { ++ struct io_pa_va base; ++ unsigned long clock; ++ uint8_t instance; ++ uint8_t flags; ++}; ++ ++static struct stm32_iwdg_instance *stm32_iwdg; ++static size_t stm32_iwdg_count; ++ ++static vaddr_t get_base(struct stm32_iwdg_instance *iwdg) ++{ ++ return io_pa_or_va(&iwdg->base); ++} ++ ++static int stm32_iwdg_get_dt_node(void *fdt, struct dt_node_info *info, ++ int offset) ++{ ++ int node = fdt_node_offset_by_compatible(fdt, offset, IWDG_COMPAT); ++ ++ if (node < 0) { ++ if (offset == -1) ++ DMSG("No IDWG found"); ++ ++ return -FDT_ERR_NOTFOUND; ++ } ++ ++ _fdt_fill_device_info(fdt, info, node); ++ ++ return node; ++} ++ ++static struct stm32_iwdg_instance *get_iwdg(unsigned int instance) ++{ ++ size_t i = 0; ++ ++ assert(instance <= UINT8_MAX); ++ for (i = 0; i < stm32_iwdg_count; i++) ++ if (stm32_iwdg[i].instance == instance) ++ return &stm32_iwdg[i]; ++ ++ return NULL; ++} ++ ++static enum itr_return stm32_iwdg_it_handler(struct itr_handler *handler) ++{ ++ unsigned int __maybe_unused cpu = get_core_pos(); ++ unsigned int instance = stm32mp_iwdg_irq2instance(handler->it); ++ struct stm32_iwdg_instance *iwdg = get_iwdg(instance); ++ vaddr_t iwdg_base = get_base(iwdg); ++ ++ DMSG("CPU %u IT Watchdog %d\n", cpu, instance + 1); ++ ++ stm32_iwdg_refresh(instance); ++ ++ stm32_clock_enable(iwdg->clock); ++ ++ io_setbits32(iwdg_base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIC); ++ ++ stm32_clock_disable(iwdg->clock); ++ ++#ifdef CFG_PM ++ /* ++ * Ack interrupt as we do not return from next call. ++ * And interrupt is no more considered as pending here. ++ */ ++ stm32mp_gic_set_end_of_interrupt(handler->it); ++ ++ stm32_cores_reset(); ++#else ++ panic("Watchdog"); ++#endif ++ ++ return ITRR_HANDLED; ++} ++DECLARE_KEEP_PAGER(stm32_iwdg_it_handler); ++ ++static int stm32_iwdg_get_secure_timeout(void *fdt, int node) ++{ ++ const fdt32_t *cuint = NULL; ++ ++ cuint = fdt_getprop(fdt, node, "secure-timeout-sec", NULL); ++ if (!cuint) ++ return -1; ++ ++ return (int)fdt32_to_cpu(*cuint); ++} ++ ++static int fdt_get_clock_id_by_name(void *fdt, int node, const char *name) ++{ ++ const fdt32_t *cuint = NULL; ++ int index = 0; ++ int len = 0; ++ ++ index = fdt_stringlist_search(fdt, node, "clock-names", name); ++ if (index < 0) ++ return index; ++ ++ cuint = fdt_getprop(fdt, node, "clocks", &len); ++ if (!cuint) ++ 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); ++} ++ ++static TEE_Result stm32_iwdg_conf_etimeout(void *fdt, int node, ++ struct stm32_iwdg_instance *iwdg) ++{ ++ int id_lsi = 0; ++ int dt_secure_timeout = stm32_iwdg_get_secure_timeout(fdt, node); ++ uint32_t reload = 0; ++ uint32_t status = 0; ++ uint64_t timeout_ref = 0; ++ unsigned long long reload_ll = 0; ++ vaddr_t iwdg_base = get_base(iwdg); ++ struct itr_handler *itr = NULL; ++ ++ if (dt_secure_timeout < 0) ++ return TEE_SUCCESS; ++ ++ if (dt_secure_timeout == 0) ++ return TEE_ERROR_GENERIC; ++ ++ id_lsi = fdt_get_clock_id_by_name(fdt, node, "lsi"); ++ if (id_lsi < 0) ++ return TEE_ERROR_GENERIC; ++ ++ /* Prescaler fix to 256 */ ++ reload_ll = (unsigned long long)dt_secure_timeout * ++ stm32_clock_get_rate(id_lsi); ++ reload = ((uint32_t)(reload_ll >> 8) - 1) & IWDG_EWCR_EWIT_MASK; ++ ++ stm32_clock_enable(iwdg->clock); ++ ++ io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_START_KEY); ++ io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); ++ io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); ++ io_write32(iwdg_base + IWDG_EWCR_OFFSET, reload | IWDG_EWCR_EWIE); ++ ++ timeout_ref = timeout_init_us(IWDG_TIMEOUT_US); ++ while (!timeout_elapsed(timeout_ref)) ++ if (!(io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_EWU)) ++ break; ++ ++ status = io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_EWU; ++ stm32_clock_disable(iwdg->clock); ++ if (status) ++ return TEE_ERROR_GENERIC; ++ ++ itr = calloc(1, sizeof(*itr)); ++ if (!itr) ++ panic("out of memory"); ++ ++ itr->it = stm32mp_iwdg_instance2irq(iwdg->instance); ++ itr->handler = stm32_iwdg_it_handler; ++ itr_add(itr); ++ itr_enable(itr->it); ++ ++ return TEE_SUCCESS; ++} ++ ++void stm32_iwdg_refresh(unsigned int instance) ++{ ++ struct stm32_iwdg_instance *iwdg = get_iwdg(instance); ++ ++ if (!iwdg) ++ return; ++ ++ stm32_clock_enable(iwdg->clock); ++ ++ io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); ++ ++ stm32_clock_disable(iwdg->clock); ++} ++ ++static TEE_Result iwdg_init(void) ++{ ++ int node = -1; ++ TEE_Result res = TEE_ERROR_GENERIC; ++ struct dt_node_info dt_info = { }; ++ void *fdt = NULL; ++ size_t count = 0; ++ ++ fdt = get_embedded_dt(); ++ if (!fdt) ++ panic(); ++ ++ assert(!stm32_iwdg && !stm32_iwdg_count); ++ ++ for (node = stm32_iwdg_get_dt_node(fdt, &dt_info, node); ++ node != -FDT_ERR_NOTFOUND; ++ node = stm32_iwdg_get_dt_node(fdt, &dt_info, node)) { ++ struct stm32_iwdg_instance iwdg = { }; ++ enum teecore_memtypes memtype = MEM_AREA_MAXTYPE; ++ uint32_t hw_init = 0; ++ ++ iwdg.base.pa = dt_info.reg; ++ iwdg.clock = (unsigned long)dt_info.clock; ++ iwdg.instance = stm32mp_iwdg_iomem2instance(iwdg.base.pa); ++ ++ memtype = ((dt_info.status & DT_STATUS_OK_NSEC) != 0) ? ++ MEM_AREA_IO_NSEC : MEM_AREA_IO_SEC; ++ iwdg.base.va = (vaddr_t)phys_to_virt(iwdg.base.pa, memtype); ++ ++ /* DT can specify low power cases */ ++ if (!fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL)) ++ iwdg.flags |= IWDG_DISABLE_ON_STOP; ++ ++ if (!fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL)) ++ iwdg.flags |= IWDG_DISABLE_ON_STANDBY; ++ ++ hw_init = stm32_get_iwdg_otp_config(iwdg.base.pa); ++ ++ if (hw_init & IWDG_HW_ENABLED) { ++ if (dt_info.status == DT_STATUS_DISABLED) ++ panic("IWDG HW enabled"); ++ ++ iwdg.flags |= IWDG_HW_ENABLED; ++ } ++ ++ if (hw_init & IWDG_DISABLE_ON_STOP) ++ iwdg.flags |= IWDG_DISABLE_ON_STOP; ++ ++ if (hw_init & IWDG_DISABLE_ON_STANDBY) ++ iwdg.flags |= IWDG_DISABLE_ON_STANDBY; ++ ++ if (dt_info.status == DT_STATUS_DISABLED) ++ continue; ++ ++ DMSG("IWDG%u found, %ssecure", iwdg.instance + 1, ++ (dt_info.status & DT_STATUS_OK_NSEC) ? "non-" : ""); ++ ++ if (dt_info.status & DT_STATUS_OK_NSEC) ++ stm32mp_register_non_secure_periph_iomem(iwdg.base.pa); ++ else ++ stm32mp_register_secure_periph_iomem(iwdg.base.pa); ++ ++ res = stm32_iwdg_conf_etimeout(fdt, node, &iwdg); ++ if (res) { ++ EMSG("IWDG%x early timeout config failed (%d)\n", ++ iwdg.instance + 1, res); ++ panic(); ++ } ++ ++ stm32_iwdg = realloc(stm32_iwdg, (count + 1) * sizeof(iwdg)); ++ if (!stm32_iwdg) ++ panic("out of memory"); ++ ++ memcpy(&stm32_iwdg[count], &iwdg, sizeof(iwdg)); ++ count++; ++ } ++ ++ stm32_iwdg_count = count; ++ ++ DMSG("%u IWDG instance%s found", count, count > 1 ? "s" : ""); ++ ++ return TEE_SUCCESS; ++} ++driver_init(iwdg_init); +diff --git a/core/drivers/stm32_rtc.c b/core/drivers/stm32_rtc.c +new file mode 100644 +index 0000000..1abeaab +--- /dev/null ++++ b/core/drivers/stm32_rtc.c +@@ -0,0 +1,445 @@ ++/* ++ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RTC_COMPAT "st,stm32mp1-rtc" ++ ++#define RTC_TR 0x00 ++#define RTC_DR 0x04 ++#define RTC_SSR 0x08 ++#define RTC_ICSR 0x0C ++#define RTC_PRER 0x10 ++#define RTC_WUTR 0x14 ++#define RTC_CR 0x18 ++#define RTC_SMCR 0x20 ++#define RTC_WPR 0x24 ++#define RTC_CALR 0x28 ++#define RTC_SHIFTR 0x2C ++#define RTC_TSTR 0x30 ++#define RTC_TSDR 0x34 ++#define RTC_TSSSR 0x38 ++#define RTC_ALRMAR 0x40 ++#define RTC_ALRMASSR 0x44 ++#define RTC_ALRMBR 0x48 ++#define RTC_ALRMBSSR 0x4C ++#define RTC_SR 0x50 ++#define RTC_SCR 0x5C ++#define RTC_OR 0x60 ++ ++#define RTC_TR_SU_MASK GENMASK_32(3, 0) ++#define RTC_TR_ST_MASK GENMASK_32(6, 4) ++#define RTC_TR_ST_SHIFT 4 ++#define RTC_TR_MNU_MASK GENMASK_32(11, 8) ++#define RTC_TR_MNU_SHIFT 8 ++#define RTC_TR_MNT_MASK GENMASK_32(14, 12) ++#define RTC_TR_MNT_SHIFT 12 ++#define RTC_TR_HU_MASK GENMASK_32(19, 16) ++#define RTC_TR_HU_SHIFT 16 ++#define RTC_TR_HT_MASK GENMASK_32(21, 20) ++#define RTC_TR_HT_SHIFT 20 ++#define RTC_TR_PM BIT(22) ++ ++#define RTC_DR_DU_MASK GENMASK_32(3, 0) ++#define RTC_DR_DT_MASK GENMASK_32(5, 4) ++#define RTC_DR_DT_SHIFT 4 ++#define RTC_DR_MU_MASK GENMASK_32(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_32(15, 13) ++#define RTC_DR_WDU_SHIFT 13 ++#define RTC_DR_YU_MASK GENMASK_32(19, 16) ++#define RTC_DR_YU_SHIFT 16 ++#define RTC_DR_YT_MASK GENMASK_32(23, 20) ++#define RTC_DR_YT_SHIFT 20 ++ ++#define RTC_SSR_SS_MASK GENMASK_32(15, 0) ++ ++#define RTC_ICSR_RSF BIT(5) ++ ++#define RTC_PRER_PREDIV_S_MASK GENMASK_32(15, 0) ++ ++#define RTC_CR_BYPSHAD BIT(5) ++#define RTC_CR_BYPSHAD_SHIFT 5 ++#define RTC_CR_TAMPTS BIT(25) ++ ++#define RTC_SMCR_TS_DPROT BIT(3) ++#define RTC_SR_TSF BIT(3) ++#define RTC_SCR_CTSF BIT(3) ++#define RTC_SR_TSOVF BIT(4) ++#define RTC_SCR_CTSOVF BIT(4) ++ ++#define RTC_TSDR_MU_MASK GENMASK_32(11, 8) ++#define RTC_TSDR_MU_SHIFT 8 ++#define RTC_TSDR_DT_MASK GENMASK_32(5, 4) ++#define RTC_TSDR_DT_SHIFT 4 ++#define RTC_TSDR_DU_MASK GENMASK_32(3, 0) ++#define RTC_TSDR_DU_SHIFT 0 ++ ++#define RTC_WPR_KEY1 0xCA ++#define RTC_WPR_KEY2 0x53 ++#define RTC_WPR_KEY_LOCK 0xFF ++ ++#define RTC_FLAGS_READ_TWICE BIT(0) ++#define RTC_FLAGS_SECURE BIT(1) ++ ++struct rtc_device { ++ struct io_pa_va base; ++ uint16_t clock; ++ uint8_t flags; ++}; ++ ++/* Expect a single RTC instance */ ++struct rtc_device rtc_dev; ++ ++static vaddr_t get_base(void) ++{ ++ assert(rtc_dev.base.pa); ++ return io_pa_or_va(&rtc_dev.base); ++} ++ ++static void stm32_rtc_write_unprotect(void) ++{ ++ vaddr_t rtc_base = get_base(); ++ ++ io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY1); ++ io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY2); ++} ++ ++static void stm32_rtc_write_protect(void) ++{ ++ vaddr_t rtc_base = get_base(); ++ ++ io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY_LOCK); ++} ++ ++static bool stm32_rtc_get_bypshad(void) ++{ ++ return io_read32(get_base() + RTC_CR) & RTC_CR_BYPSHAD; ++} ++ ++/* Get calendar data from RTC devicecalendar valueregister values */ ++static void stm32_rtc_read_calendar(struct stm32_rtc_calendar *calendar) ++{ ++ vaddr_t rtc_base = get_base(); ++ bool bypshad = stm32_rtc_get_bypshad(); ++ ++ if (!bypshad) { ++ /* Shadow RTC registers */ ++ io_clrbits32(rtc_base + RTC_ICSR, RTC_ICSR_RSF); ++ while (!(io_read32(rtc_base + RTC_ICSR) & RTC_ICSR_RSF)) ++ ; ++ } ++ ++ calendar->ssr = io_read32(rtc_base + RTC_SSR); ++ calendar->tr = io_read32(rtc_base + RTC_TR); ++ calendar->dr = io_read32(rtc_base + RTC_DR); ++} ++ ++/* Fill the RTC timestamp structure from a given RTC time-in-day value */ ++static void stm32_rtc_get_time(struct stm32_rtc_calendar *cal, ++ struct stm32_rtc_time *tm) ++{ ++ tm->hour = (((cal->tr & RTC_TR_HT_MASK) >> RTC_TR_HT_SHIFT) * 10) + ++ ((cal->tr & RTC_TR_HU_MASK) >> RTC_TR_HU_SHIFT); ++ ++ if (cal->tr & RTC_TR_PM) ++ tm->hour += 12; ++ ++ tm->min = (((cal->tr & RTC_TR_MNT_MASK) >> RTC_TR_MNT_SHIFT) * 10) + ++ ((cal->tr & RTC_TR_MNU_MASK) >> RTC_TR_MNU_SHIFT); ++ tm->sec = (((cal->tr & RTC_TR_ST_MASK) >> RTC_TR_ST_SHIFT) * 10) + ++ (cal->tr & RTC_TR_SU_MASK); ++} ++ ++/* Fill the RTC timestamp structure from a given RTC date value */ ++static void stm32_rtc_get_date(struct stm32_rtc_calendar *cal, ++ struct stm32_rtc_time *tm) ++{ ++ tm->wday = (((cal->dr & RTC_DR_WDU_MASK) >> RTC_DR_WDU_SHIFT)); ++ ++ tm->day = (((cal->dr & RTC_DR_DT_MASK) >> RTC_DR_DT_SHIFT) * 10) + ++ (cal->dr & RTC_DR_DU_MASK); ++ ++ tm->month = (((cal->dr & RTC_DR_MT) >> RTC_DR_MT_SHIFT) * 10) + ++ ((cal->dr & RTC_DR_MU_MASK) >> RTC_DR_MU_SHIFT); ++ ++ tm->year = (((cal->dr & RTC_DR_YT_MASK) >> RTC_DR_YT_SHIFT) * 10) + ++ ((cal->dr & RTC_DR_YU_MASK) >> RTC_DR_YU_SHIFT) + 2000; ++} ++ ++/* Update time value with RTC timestamp */ ++static void stm32_rtc_read_timestamp(struct stm32_rtc_time *time) ++{ ++ struct stm32_rtc_calendar cal_tamp = { }; ++ vaddr_t rtc_base = get_base(); ++ ++ cal_tamp.tr = io_read32(rtc_base + RTC_TSTR); ++ cal_tamp.dr = io_read32(rtc_base + RTC_TSDR); ++ stm32_rtc_get_time(&cal_tamp, time); ++ stm32_rtc_get_date(&cal_tamp, time); ++} ++ ++void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar) ++{ ++ stm32_clock_enable(rtc_dev.clock); ++ ++ stm32_rtc_read_calendar(calendar); ++ ++ /* RTC may need to be read twice, depending of clocks configuration */ ++ if (rtc_dev.flags & RTC_FLAGS_READ_TWICE) { ++ uint32_t tr_save = calendar->tr; ++ ++ stm32_rtc_read_calendar(calendar); ++ ++ if (calendar->tr != tr_save) ++ stm32_rtc_read_calendar(calendar); ++ } ++ ++ stm32_clock_disable(rtc_dev.clock); ++} ++ ++/* Return difference in milliseconds on second fraction */ ++static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal) ++{ ++ uint32_t prediv_s = io_read32(get_base() + RTC_PRER) & ++ RTC_PRER_PREDIV_S_MASK; ++ uint32_t ss = cal->ssr & RTC_SSR_SS_MASK; ++ ++ return ((prediv_s - ss) * 1000) / (prediv_s + 1); ++} ++ ++/* Return absolute difference in milliseconds on second fraction */ ++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); ++} ++ ++/* Return absolute difference in milliseconds on seconds-in-day fraction */ ++static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current, ++ struct stm32_rtc_time *ref) ++{ ++ signed long long curr_s = 0; ++ signed long long ref_s = 0; ++ ++ 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) * 1000U; ++} ++ ++static bool stm32_is_a_leap_year(uint32_t year) ++{ ++ return ((year % 4) == 0) && ++ (((year % 100) != 0) || ((year % 400) == 0)); ++} ++ ++/* Return absolute difference in milliseconds on day-in-year fraction */ ++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 = 0; ++ 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 += month_len[ref->month - 1] - ++ ref->day + current->day; ++ ++ /* Get the number of entire months, and compute the related days */ ++ if (current->month > (ref->month + 1)) ++ for (m = ref->month + 1; m < current->month && m < 12; m++) ++ diff_in_days += month_len[m - 1]; ++ ++ if (current->month < (ref->month - 1)) { ++ for (m = 1; m < current->month && m < 12; m++) ++ diff_in_days += month_len[m - 1]; ++ ++ for (m = ref->month + 1; m < 12; m++) ++ diff_in_days += month_len[m - 1]; ++ } ++ ++ /* Get complete years */ ++ if (current->year > (ref->year + 1)) ++ diff_in_days += (current->year - ref->year - 1) * 365; ++ ++ /* Particular cases: leap years (one day more) */ ++ if (diff_in_days > 0) { ++ if (current->year == ref->year) { ++ if (stm32_is_a_leap_year(current->year) && ++ ref->month <= 2 && ++ current->month >= 3 && current->day <= 28) ++ diff_in_days++; ++ } else { ++ uint32_t y = 0; ++ ++ /* Ref year is leap */ ++ if (stm32_is_a_leap_year(ref->year) && ++ ref->month <= 2 && ref->day <= 28) ++ diff_in_days++; ++ ++ /* Current year is leap */ ++ if (stm32_is_a_leap_year(current->year) && ++ current->month >= 3) ++ diff_in_days++; ++ ++ /* Interleaved years are leap */ ++ for (y = ref->year + 1; 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; ++} ++ ++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 = { }; ++ ++ 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); ++ ++ return (unsigned long long)diff_in_ms; ++} ++ ++void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts) ++{ ++ vaddr_t rtc_base = get_base(); ++ ++ stm32_clock_enable(rtc_dev.clock); ++ ++ if (io_read32(rtc_base + RTC_SR) & RTC_SR_TSF) { ++ /* Timestamp for tamper event */ ++ stm32_rtc_read_timestamp(tamp_ts); ++ io_setbits32(rtc_base + RTC_SCR, RTC_SCR_CTSF); ++ ++ /* Overflow detection */ ++ if (io_read32(rtc_base + RTC_SR) & RTC_SR_TSOVF) ++ io_setbits32(rtc_base + RTC_SCR, RTC_SCR_CTSOVF); ++ } ++ ++ stm32_clock_disable(rtc_dev.clock); ++} ++ ++void stm32_rtc_set_tamper_timestamp(void) ++{ ++ vaddr_t rtc_base = get_base(); ++ ++ stm32_clock_enable(rtc_dev.clock); ++ ++ stm32_rtc_write_unprotect(); ++ ++ /* Enable tamper timestamper */ ++ io_setbits32(rtc_base + RTC_CR, RTC_CR_TAMPTS); ++ ++ /* Secure Timestamp bit */ ++ io_clrbits32(rtc_base + RTC_SMCR, RTC_SMCR_TS_DPROT); ++ ++ stm32_rtc_write_protect(); ++ ++ stm32_clock_disable(rtc_dev.clock); ++} ++ ++bool stm32_rtc_is_timestamp_enable(void) ++{ ++ bool ret = false; ++ ++ stm32_clock_enable(rtc_dev.clock); ++ ++ ret = io_read32(get_base() + RTC_CR) & RTC_CR_TAMPTS; ++ ++ stm32_clock_disable(rtc_dev.clock); ++ ++ return ret; ++} ++ ++#ifdef CFG_DT ++static unsigned int get_second_clock(void *fdt, int offs) ++{ ++ const fdt32_t *cuint = NULL; ++ int len = 0; ++ ++ cuint = fdt_getprop(fdt, offs, "clocks", &len); ++ if (len == 3) { ++ EMSG("RTC expects 2 clocks, %d found", len); ++ return DT_INFO_INVALID_CLOCK; ++ } ++ ++ return fdt32_to_cpu(*(cuint + 3)); ++} ++ ++static TEE_Result stm32_rtc_init(void) ++{ ++ int node = 0; ++ struct dt_node_info dt_info = { }; ++ void *fdt = get_embedded_dt(); ++ ++ if (!fdt) ++ panic(); ++ ++ node = fdt_node_offset_by_compatible(fdt, -1, RTC_COMPAT); ++ if (node < 0) ++ return TEE_SUCCESS; ++ ++ _fdt_fill_device_info(fdt, &dt_info, node); ++ ++ rtc_dev.base.pa = dt_info.reg; ++ ++ if (dt_info.status == DT_STATUS_OK_SEC) { ++ rtc_dev.flags |= RTC_FLAGS_SECURE; ++ stm32mp_register_secure_periph_iomem(rtc_dev.base.pa); ++ rtc_dev.base.va = (vaddr_t)phys_to_virt(rtc_dev.base.pa, ++ MEM_AREA_IO_SEC); ++ /* Unbalanced clock enable: keep RTC running */ ++ stm32_clock_enable(get_second_clock(fdt, node)); ++ } else { ++ stm32mp_register_non_secure_periph_iomem(rtc_dev.base.pa); ++ rtc_dev.base.va = (vaddr_t)phys_to_virt(rtc_dev.base.pa, ++ MEM_AREA_IO_NSEC); ++ } ++ ++ rtc_dev.clock = (unsigned long)dt_info.clock; ++ ++ if (stm32_rtc_get_read_twice()) ++ rtc_dev.flags |= RTC_FLAGS_READ_TWICE; ++ ++ return 0; ++} ++driver_init(stm32_rtc_init); ++#endif +diff --git a/core/drivers/stm32_tim.c b/core/drivers/stm32_tim.c +new file mode 100644 +index 0000000..612fbbc +--- /dev/null ++++ b/core/drivers/stm32_tim.c +@@ -0,0 +1,286 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2018, STMicroelectronics ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TIM_CR1 0x00 /* Control Register 1 */ ++#define TIM_CR2 0x04 /* Control Register 2 */ ++#define TIM_SMCR 0x08 /* Slave mode control reg */ ++#define TIM_DIER 0x0C /* DMA/interrupt register */ ++#define TIM_SR 0x10 /* Status register */ ++#define TIM_EGR 0x14 /* Event Generation Reg */ ++#define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */ ++#define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */ ++#define TIM_CCER 0x20 /* Capt/Comp Enable Reg */ ++#define TIM_CNT 0x24 /* Counter */ ++#define TIM_PSC 0x28 /* Prescaler */ ++#define TIM_ARR 0x2C /* Auto-Reload Register */ ++#define TIM_CCR1 0x34 /* Capt/Comp Register 1 */ ++#define TIM_CCR2 0x38 /* Capt/Comp Register 2 */ ++#define TIM_CCR3 0x3C /* Capt/Comp Register 3 */ ++#define TIM_CCR4 0x40 /* Capt/Comp Register 4 */ ++#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */ ++#define TIM_DCR 0x48 /* DMA control register */ ++#define TIM_DMAR 0x4C /* DMA transfer register */ ++#define TIM_AF1 0x60 /* Alt Function Reg 1 */ ++#define TIM_AF2 0x64 /* Alt Function Reg 2 */ ++#define TIM_TISEL 0x68 /* Input Selection */ ++ ++#define TIM_CR1_CEN BIT(0) ++#define TIM_SMCR_SMS GENMASK_32(2, 0) /* Slave mode selection */ ++#define TIM_SMCR_TS GENMASK_32(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_32(3, 0) ++#define TIM_SMCR_SMS_RESET BIT(2) ++#define TIM_SMCR_TS_SHIFT 4 ++#define TIM_SMCR_TS_TI1FP1 0x5 ++ ++#define TIM_COMPAT "st,stm32-timers" ++#define TIM_TIMEOUT_US 100000 ++#define TIM_TIMEOUT_STEP_US 10 ++#define TIM_PRESCAL_HSI 10 ++#define TIM_PRESCAL_CSI 7 ++#define TIM_MIN_FREQ_CALIB 50000000U ++ ++struct stm32_tim_instance { ++ struct io_pa_va base; ++ unsigned long clk; ++ unsigned long freq; ++ uint8_t cal_input; ++}; ++ ++static vaddr_t timer_base(struct stm32_tim_instance *timer) ++{ ++ return io_pa_or_va(&timer->base); ++} ++ ++/* Currently support HSI and CSI calibratrion */ ++#define TIM_MAX_INSTANCE 2 ++static struct stm32_tim_instance stm32_tim[TIM_MAX_INSTANCE]; ++ ++static int timer_get_dt_node(void *fdt, struct dt_node_info *info, int offset) ++{ ++ int node = fdt_node_offset_by_compatible(fdt, offset, TIM_COMPAT); ++ ++ if (node < 0) ++ return -FDT_ERR_NOTFOUND; ++ ++ _fdt_fill_device_info(fdt, info, node); ++ ++ return node; ++} ++ ++static int timer_config(struct stm32_tim_instance *timer) ++{ ++ vaddr_t base = timer_base(timer); ++ ++ stm32_clock_enable(timer->clk); ++ ++ timer->freq = stm32_clock_get_rate(timer->clk); ++ if (timer->freq < TIM_MIN_FREQ_CALIB) { ++ EMSG("Calibration: timer not accurate enough"); ++ stm32_clock_disable(timer->clk); ++ return -1; ++ } ++ ++ if ((io_read32(base + TIM_TISEL) & TIM_TISEL_TI1SEL_MASK) != ++ timer->cal_input) { ++ io_clrsetbits32(base + TIM_CCMR1, ++ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC1S_TI2, ++ TIM_CCMR_CC1S_TI1); ++ ++ io_clrbits32(base + TIM_CCER, ++ TIM_CCER_CC1P | TIM_CCER_CC1NP); ++ ++ io_clrsetbits32(base + TIM_SMCR, ++ TIM_SMCR_TS | TIM_SMCR_SMS, ++ (TIM_SMCR_TS_TI1FP1 << TIM_SMCR_TS_SHIFT) | ++ TIM_SMCR_SMS_RESET); ++ ++ io_write32(base + TIM_TISEL, timer->cal_input); ++ io_setbits32(base + TIM_CR1, TIM_CR1_CEN); ++ io_setbits32(base + TIM_CCER, TIM_CCER_CC1E); ++ } ++ ++ stm32_clock_disable(timer->clk); ++ ++ return 0; ++} ++ ++static uint32_t timer_start_capture(struct stm32_tim_instance *timer) ++{ ++ uint64_t timeout_ref = 0; ++ uint32_t counter = 0; ++ uint32_t old_counter = 0; ++ int twice = 0; ++ vaddr_t base = timer_base(timer); ++ ++ if (timer_config(timer)) ++ return 0; ++ ++ stm32_clock_enable(timer->clk); ++ ++ io_write32(base + TIM_SR, 0); ++ ++ timeout_ref = timeout_init_us(TIM_TIMEOUT_US); ++ ++ while (!timeout_elapsed(timeout_ref)) ++ if (io_read32(base + TIM_SR) & TIM_SR_UIF) ++ break; ++ if (!(io_read32(base + TIM_SR) & TIM_SR_UIF)) ++ goto bail; ++ ++ io_write32(base + TIM_SR, 0); ++ ++ for (twice = 0; (twice < 2) || (counter != old_counter); twice++) { ++ timeout_ref = timeout_init_us(TIM_TIMEOUT_US); ++ while (!timeout_elapsed(timeout_ref)) ++ if (io_read32(base + TIM_SR) & TIM_SR_CC1IF) ++ break; ++ if (!(io_read32(base + TIM_SR) & TIM_SR_CC1IF)) { ++ counter = 0; ++ goto bail; ++ } ++ ++ old_counter = counter; ++ counter = io_read32(base + TIM_CCR1); ++ } ++ ++bail: ++ stm32_clock_disable(timer->clk); ++ ++ return counter; ++} ++ ++unsigned long stm32_tim_hsi_freq(void) ++{ ++ struct stm32_tim_instance *timer = &stm32_tim[HSI_CAL]; ++ uint32_t counter = 0; ++ ++ if (timer->base.pa) ++ counter = timer_start_capture(timer); ++ ++ if (!counter) ++ return 0; ++ ++ return (timer->freq / counter) << TIM_PRESCAL_HSI; ++} ++DECLARE_KEEP_PAGER(stm32_tim_hsi_freq); ++ ++unsigned long stm32_tim_csi_freq(void) ++{ ++ struct stm32_tim_instance *timer = &stm32_tim[CSI_CAL]; ++ uint32_t counter = 0; ++ ++ if (timer->base.pa) ++ counter = timer_start_capture(timer); ++ ++ if (!counter) ++ return 0; ++ ++ return (timer->freq / counter) << TIM_PRESCAL_CSI; ++} ++DECLARE_KEEP_PAGER(stm32_tim_csi_freq); ++ ++static void _init_stm32_tim(void) ++{ ++ void *fdt = get_embedded_dt(); ++ struct dt_node_info dt_timer = { }; ++ int node = -1; ++ static bool inited; ++ ++ if (inited) ++ return; ++ inited = true; ++ ++ if (!fdt) ++ panic(); ++ ++ for (node = timer_get_dt_node(fdt, &dt_timer, node); ++ node != -FDT_ERR_NOTFOUND; ++ node = timer_get_dt_node(fdt, &dt_timer, node)) { ++ struct stm32_tim_instance *timer = NULL; ++ const uint32_t *cuint = NULL; ++ ++ if (!(dt_timer.status & DT_STATUS_OK_SEC)) ++ continue; ++ ++ cuint = fdt_getprop(fdt, node, "st,hsi-cal-input", NULL); ++ if (cuint) { ++ timer = &stm32_tim[HSI_CAL]; ++ timer->base.pa = dt_timer.reg; ++ timer->clk = dt_timer.clock; ++ timer->freq = stm32_clock_get_rate(timer->clk); ++ timer->cal_input = fdt32_to_cpu(*cuint); ++ if (timer_config(timer)) { ++ timer->base.pa = 0; ++ continue; ++ } ++ } ++ ++ cuint = fdt_getprop(fdt, node, "st,csi-cal-input", NULL); ++ if (cuint) { ++ timer = &stm32_tim[CSI_CAL]; ++ timer->base.pa = dt_timer.reg; ++ timer->clk = dt_timer.clock; ++ timer->freq = stm32_clock_get_rate(timer->clk); ++ timer->cal_input = fdt32_to_cpu(*cuint); ++ if (timer_config(timer)) { ++ timer->base.pa = 0; ++ continue; ++ } ++ } ++ } ++} ++ ++void stm32_tim_freq_func(unsigned long (**timer_freq_cb)(void), ++ enum stm32_tim_cal type) ++{ ++ _init_stm32_tim(); ++ ++ *timer_freq_cb = NULL; ++ ++ switch (type) { ++ case HSI_CAL: ++ if (stm32_tim[HSI_CAL].base.pa) ++ *timer_freq_cb = stm32_tim_hsi_freq; ++ break; ++ ++ case CSI_CAL: ++ if (stm32_tim[CSI_CAL].base.pa) ++ *timer_freq_cb = stm32_tim_csi_freq; ++ break; ++ default: ++ panic(); ++ } ++} ++ ++static TEE_Result init_stm32_tim(void) ++{ ++ _init_stm32_tim(); ++ ++ return TEE_SUCCESS; ++} ++driver_init(init_stm32_tim); +diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk +index f9e03b5..2216b63 100644 +--- a/core/drivers/sub.mk ++++ b/core/drivers/sub.mk +@@ -25,7 +25,10 @@ srcs-$(CFG_STM32_BSEC) += stm32_bsec.c + srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c + srcs-$(CFG_STM32_GPIO) += stm32_gpio.c + srcs-$(CFG_STM32_I2C) += stm32_i2c.c ++srcs-$(CFG_STM32_IWDG) += stm32_iwdg.c + srcs-$(CFG_STM32_RNG) += stm32_rng.c ++srcs-$(CFG_STM32_RTC) += stm32_rtc.c ++srcs-$(CFG_STM32_TIM) += stm32_tim.c + srcs-$(CFG_STM32_UART) += stm32_uart.c + srcs-$(CFG_STPMIC1) += stpmic1.c + srcs-$(CFG_BCM_HWRNG) += bcm_hwrng.c +diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h +index f9bb28e..c8da6d8 100644 +--- a/core/include/drivers/gic.h ++++ b/core/include/drivers/gic.h +@@ -9,17 +9,38 @@ + #include + #include + ++/* Constants to categorize priorities */ ++#define GIC_HIGHEST_SEC_PRIORITY 0x0U ++#define GIC_LOWEST_SEC_PRIORITY 0x7fU ++#define GIC_HIGHEST_NS_PRIORITY 0x80U ++#define GIC_LOWEST_NS_PRIORITY 0xfeU ++/* 0xff would disable all interrupts */ ++ + #define GIC_DIST_REG_SIZE 0x10000 + #define GIC_CPU_REG_SIZE 0x10000 + #define GIC_SGI(x) (x) + #define GIC_PPI(x) ((x) + 16) + #define GIC_SPI(x) ((x) + 32) + ++/* ++ * Save and restore some interrupts configuration during low power sequences. ++ * This is used on platforms using OP-TEE secure monitor. ++ */ ++struct gic_it_pm; ++ ++struct gic_pm { ++ struct gic_it_pm *pm_cfg; ++ size_t count; ++}; ++ + struct gic_data { + vaddr_t gicc_base; + vaddr_t gicd_base; + size_t max_it; + struct itr_chip chip; ++#if defined(CFG_ARM_GIC_PM) ++ struct gic_pm pm; ++#endif + }; + + /* +@@ -31,6 +52,9 @@ void gic_init(struct gic_data *gd, vaddr_t gicc_base, vaddr_t gicd_base); + /* initial base address only */ + void gic_init_base_addr(struct gic_data *gd, vaddr_t gicc_base, + vaddr_t gicd_base); ++/* Setup GIC default configuration */ ++void gic_init_setup(struct gic_data *gd); ++ + /* initial cpu if only, mainly use for secondary cpu setup cpu interface */ + void gic_cpu_init(struct gic_data *gd); + +diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h +index dfb0d47..d284eea 100644 +--- a/core/include/drivers/stm32_bsec.h ++++ b/core/include/drivers/stm32_bsec.h +@@ -10,6 +10,12 @@ + #include + #include + ++/* BSEC_DEBUG */ ++#define BSEC_HDPEN BIT(4) ++#define BSEC_SPIDEN BIT(5) ++#define BSEC_SPINDEN BIT(6) ++#define BSEC_DBGSWGEN BIT(10) ++ + /* + * Load OTP from SAFMEM and provide its value + * @value: Output read value +@@ -155,4 +161,14 @@ TEE_Result stm32_bsec_otp_lock(uint32_t service); + */ + bool stm32_bsec_nsec_can_access_otp(uint32_t otp_id); + ++/* ++ * Find and get OTP location from its name. ++ * @name: sub-node name to look up. ++ * @otp_id: pointer to read OTP number or NULL. ++ * @otp_bit_len: pointer to read OTP length in bits or NULL. ++ * Return a TEE_Result compliant status ++ */ ++TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, ++ uint32_t *otp_id, ++ size_t *otp_bit_len); + #endif /*__STM32_BSEC_H*/ +diff --git a/core/include/drivers/stm32_iwdg.h b/core/include/drivers/stm32_iwdg.h +new file mode 100644 +index 0000000..f063258 +--- /dev/null ++++ b/core/include/drivers/stm32_iwdg.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved ++ */ ++ ++#ifndef __STM32_IWDG_H__ ++#define __STM32_IWDG_H__ ++ ++#include ++ ++#define IWDG_HW_ENABLED BIT(0) ++#define IWDG_DISABLE_ON_STOP BIT(1) ++#define IWDG_DISABLE_ON_STANDBY BIT(2) ++ ++void stm32_iwdg_refresh(unsigned int instance); ++ ++#endif /*__STM32_IWDG_H__*/ +diff --git a/core/include/drivers/stm32_rtc.h b/core/include/drivers/stm32_rtc.h +new file mode 100644 +index 0000000..b0f4ef8 +--- /dev/null ++++ b/core/include/drivers/stm32_rtc.h +@@ -0,0 +1,60 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved ++ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. ++ */ ++ ++#ifndef __PLAT_RTC_H__ ++#define __PLAT_RTC_H__ ++ ++#include ++ ++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; ++}; ++ ++/* Get calendar formated time from RTC device */ ++void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar); ++ ++/* Return time diff in milliseconds between current and reference time */ ++unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, ++ struct stm32_rtc_calendar *ref); ++ ++/* Enable tamper and secure timestamp access in RTC */ ++void stm32_rtc_set_tamper_timestamp(void); ++ ++/* Retrun true if and only if RTC timestamp is enable */ ++bool stm32_rtc_is_timestamp_enable(void); ++ ++/* Get RTC timestamp for current time */ ++void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts); ++ ++#endif /* __PLAT_RTC_H__ */ +diff --git a/core/include/drivers/stm32_tim.h b/core/include/drivers/stm32_tim.h +new file mode 100644 +index 0000000..2373561 +--- /dev/null ++++ b/core/include/drivers/stm32_tim.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: BSD-3-Clause */ ++/* ++ * Copyright (c) 2018-2019, STMicroelectronics ++ */ ++ ++#ifndef STM32_TIM_H ++#define STM32_TIM_H ++ ++enum stm32_tim_cal { ++ HSI_CAL = 0, ++ CSI_CAL ++}; ++ ++unsigned long stm32_tim_hsi_freq(void); ++unsigned long stm32_tim_csi_freq(void); ++ ++/* ++ * Get the timer frequence callback function for a target clock calibration ++ * @timer_freq_cb - Output callback function ++ * @type - Target clock calibration ID ++ */ ++void stm32_tim_freq_func(unsigned long (**timer_freq_cb)(void), ++ enum stm32_tim_cal type); ++ ++#endif /* STM32_TIM_H */ +diff --git a/core/include/dt-bindings/clock/stm32mp1-clksrc.h b/core/include/dt-bindings/clock/stm32mp1-clksrc.h +new file mode 100644 +index 0000000..de7d160 +--- /dev/null ++++ b/core/include/dt-bindings/clock/stm32mp1-clksrc.h +@@ -0,0 +1,284 @@ ++/* ++ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause ++ */ ++ ++#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 ++ ++#endif +diff --git a/core/include/dt-bindings/power/stm32mp1-power.h b/core/include/dt-bindings/power/stm32mp1-power.h +new file mode 100644 +index 0000000..bfb7f78 +--- /dev/null ++++ b/core/include/dt-bindings/power/stm32mp1-power.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ ++/* ++ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved ++ * 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/core/include/dt-bindings/soc/st,stm32-etzpc.h b/core/include/dt-bindings/soc/st,stm32-etzpc.h +new file mode 100644 +index 0000000..6678b8e +--- /dev/null ++++ b/core/include/dt-bindings/soc/st,stm32-etzpc.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved ++ * ++ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause ++ */ ++ ++#ifndef _DT_BINDINGS_STM32_ETZPC_H ++#define _DT_BINDINGS_STM32_ETZPC_H ++ ++/* define DECPROT modes */ ++#define DECPROT_S_RW 0x0 ++#define DECPROT_NS_R_S_W 0x1 ++#define DECPROT_MCU_ISOLATION 0x2 ++#define DECPROT_NS_RW 0x3 ++ ++/* define DECPROT lock */ ++#define DECPROT_UNLOCK 0x0 ++#define DECPROT_LOCK 0x1 ++ ++/* define 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/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h +index 849e987..796eded 100644 +--- a/core/include/kernel/interrupt.h ++++ b/core/include/kernel/interrupt.h +@@ -25,6 +25,11 @@ struct itr_ops { + uint8_t cpu_mask); + void (*set_affinity)(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); ++#if !defined(CFG_ARM_GICV3) ++ uint8_t (*set_pmr)(struct itr_chip *chip, uint8_t mask); ++ uint8_t (*set_ipriority)(struct itr_chip *chip, size_t it, ++ uint8_t mask); ++#endif + }; + + enum itr_return { +@@ -66,4 +71,14 @@ void itr_set_affinity(size_t it, uint8_t cpu_mask); + */ + void itr_core_handler(void); + ++/* ++ * Set the Priority Mask Regarding and return its previous value ++ */ ++uint8_t itr_set_pmr(uint8_t mask); ++ ++/* ++ * Set the targe tinterrupt priority mask and return its previous value ++ */ ++uint8_t itr_set_ipriority(size_t it, uint8_t mask); ++ + #endif /*__KERNEL_INTERRUPT_H*/ +diff --git a/core/include/kernel/panic.h b/core/include/kernel/panic.h +index b9a56dc..0f0d079 100644 +--- a/core/include/kernel/panic.h ++++ b/core/include/kernel/panic.h +@@ -8,6 +8,12 @@ + + #include + ++/* ++ * Platform can define a panic sequence to trap cpu/reset core or system ++ * after eventual debug trace. ++ */ ++void plat_panic(void); ++ + /* debug disabled => __FILE__, ... and panic message are not built. */ + #if defined(CFG_TEE_CORE_DEBUG) + #define __panic(str) __do_panic(__FILE__, __LINE__, __func__, str) +diff --git a/core/kernel/interrupt.c b/core/kernel/interrupt.c +index 961ce6b..3760125 100644 +--- a/core/kernel/interrupt.c ++++ b/core/kernel/interrupt.c +@@ -88,3 +88,13 @@ void __weak __noreturn itr_core_handler(void) + { + panic("Secure interrupt handler not defined"); + } ++ ++uint8_t itr_set_pmr(uint8_t mask) ++{ ++ return itr_chip->ops->set_pmr(itr_chip, mask); ++} ++ ++uint8_t itr_set_ipriority(size_t it, uint8_t mask) ++{ ++ return itr_chip->ops->set_ipriority(itr_chip, it, mask); ++} +diff --git a/core/kernel/panic.c b/core/kernel/panic.c +index 37e30a8..460ef90 100644 +--- a/core/kernel/panic.c ++++ b/core/kernel/panic.c +@@ -6,8 +6,21 @@ + + #include + #include ++#include + #include + ++static void __noreturn stall_cpu(void) ++{ ++ while (true) ++ ; ++} ++ ++void __weak __noreturn plat_panic(void) ++{ ++ /* abort current execution */ ++ stall_cpu(); ++} ++ + void __do_panic(const char *file __maybe_unused, + const int line __maybe_unused, + const char *func __maybe_unused, +@@ -16,8 +29,6 @@ void __do_panic(const char *file __maybe_unused, + /* disable prehemption */ + (void)thread_mask_exceptions(THREAD_EXCP_ALL); + +- /* TODO: notify other cores */ +- + /* trace: Panic ['panic-string-message' ]at FILE:LINE []" */ + if (!file && !func && !msg) + EMSG_RAW("Panic"); +@@ -28,7 +39,9 @@ void __do_panic(const char *file __maybe_unused, + func ? "<" : "", func ? func : "", func ? ">" : ""); + + EPRINT_STACK(); +- /* abort current execution */ +- while (1) +- ; ++ ++ plat_panic(); ++ ++ EMSG("platform failed to abord execution"); ++ stall_cpu(); + } +diff --git a/mk/config.mk b/mk/config.mk +index c00a146..bc49f83 100644 +--- a/mk/config.mk ++++ b/mk/config.mk +@@ -116,7 +116,7 @@ endif + # with limited depth not including any tag, so there is really no guarantee + # that TEE_IMPL_VERSION contains the major and minor revision numbers. + CFG_OPTEE_REVISION_MAJOR ?= 3 +-CFG_OPTEE_REVISION_MINOR ?= 8 ++CFG_OPTEE_REVISION_MINOR ?= 9 + + # Trusted OS implementation manufacturer name + CFG_TEE_MANUFACTURER ?= LINARO +-- +2.7.4 + diff --git a/recipes-security/optee/optee-os/0001-st-updates-r1.patch b/recipes-security/optee/optee-os/0001-st-updates-r1.patch deleted file mode 100644 index 4a95e32..0000000 --- a/recipes-security/optee/optee-os/0001-st-updates-r1.patch +++ /dev/null @@ -1,23389 +0,0 @@ -From da84a97b7083d65144ed658e0f0def1232b7852c Mon Sep 17 00:00:00 2001 -From: christophe montaud -Date: Wed, 30 Jan 2019 10:41:28 +0100 -Subject: [PATCH] st updates r1 - ---- - core/arch/arm/fdts/stm32mp15-ddr.dtsi | 153 ++ - .../arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 121 ++ - .../arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 122 ++ - core/arch/arm/fdts/stm32mp157-pinctrl.dtsi | 350 +++++ - core/arch/arm/fdts/stm32mp157a-dk1.dts | 380 +++++ - core/arch/arm/fdts/stm32mp157c-dk2.dts | 16 + - core/arch/arm/fdts/stm32mp157c-ed1.dts | 381 +++++ - core/arch/arm/fdts/stm32mp157c-ev1.dts | 67 + - core/arch/arm/fdts/stm32mp157c-security.dtsi | 71 + - core/arch/arm/fdts/stm32mp157c.dtsi | 371 +++++ - core/arch/arm/fdts/stm32mp157caa-pinctrl.dtsi | 90 ++ - core/arch/arm/fdts/stm32mp157cab-pinctrl.dtsi | 62 + - core/arch/arm/fdts/stm32mp157cac-pinctrl.dtsi | 78 + - core/arch/arm/fdts/stm32mp157cad-pinctrl.dtsi | 62 + - core/arch/arm/include/arm32.h | 14 +- - core/arch/arm/include/kernel/delay.h | 8 + - core/arch/arm/include/mm/core_mmu.h | 3 + - core/arch/arm/include/sm/pm.h | 4 + - core/arch/arm/kernel/delay.c | 40 +- - core/arch/arm/kernel/generic_boot.c | 36 +- - core/arch/arm/mm/core_mmu.c | 3 + - core/arch/arm/mm/mobj.c | 3 +- - core/arch/arm/plat-stm32mp1/boot_api.h | 2 + - core/arch/arm/plat-stm32mp1/conf.mk | 81 +- - core/arch/arm/plat-stm32mp1/drivers/stm32_reset.c | 60 + - core/arch/arm/plat-stm32mp1/drivers/stm32_reset.h | 15 + - .../arm/plat-stm32mp1/drivers/stm32mp1_calib.c | 457 ++++++ - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c | 1527 ++++++++++++++++++ - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h | 62 + - .../arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c | 340 ++++ - .../arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.h | 33 + - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c | 513 ++++++ - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h | 205 +++ - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c | 614 ++++++++ - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h | 33 + - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c | 21 + - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h | 48 + - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c | 51 + - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h | 539 +++++++ - core/arch/arm/plat-stm32mp1/drivers/sub.mk | 8 + - core/arch/arm/plat-stm32mp1/link.mk | 6 +- - core/arch/arm/plat-stm32mp1/main.c | 578 ++++++- - core/arch/arm/plat-stm32mp1/platform_config.h | 183 ++- - core/arch/arm/plat-stm32mp1/pm/context.c | 510 ++++++ - core/arch/arm/plat-stm32mp1/pm/context.h | 100 ++ - .../arm/plat-stm32mp1/pm/context_asm_defines.c | 28 + - core/arch/arm/plat-stm32mp1/pm/low_power.c | 431 ++++++ - core/arch/arm/plat-stm32mp1/pm/pm_helpers.S | 635 ++++++++ - core/arch/arm/plat-stm32mp1/pm/power.h | 26 + - core/arch/arm/plat-stm32mp1/pm/power_config.c | 212 +++ - core/arch/arm/plat-stm32mp1/pm/psci.c | 427 +++++ - core/arch/arm/plat-stm32mp1/pm/sub.mk | 7 + - core/arch/arm/plat-stm32mp1/reset.S | 28 +- - core/arch/arm/plat-stm32mp1/scripts/stm32image.py | 19 +- - core/arch/arm/plat-stm32mp1/service/bsec_svc.c | 65 + - core/arch/arm/plat-stm32mp1/service/bsec_svc.h | 14 + - .../arch/arm/plat-stm32mp1/service/low_power_svc.c | 153 ++ - .../arch/arm/plat-stm32mp1/service/low_power_svc.h | 22 + - core/arch/arm/plat-stm32mp1/service/pwr_svc.c | 117 ++ - core/arch/arm/plat-stm32mp1/service/pwr_svc.h | 11 + - core/arch/arm/plat-stm32mp1/service/rcc_svc.c | 440 ++++++ - core/arch/arm/plat-stm32mp1/service/rcc_svc.h | 11 + - core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h | 211 +++ - .../arm/plat-stm32mp1/service/stm32mp1_svc_setup.c | 129 ++ - core/arch/arm/plat-stm32mp1/service/sub.mk | 7 + - core/arch/arm/plat-stm32mp1/shared_resources.c | 1007 ++++++++++++ - core/arch/arm/plat-stm32mp1/stm32_util.h | 287 ++++ - core/arch/arm/plat-stm32mp1/stm32mp1_dt.c | 338 ++++ - core/arch/arm/plat-stm32mp1/stm32mp_dt.h | 39 + - core/arch/arm/plat-stm32mp1/stm32mp_pm.h | 49 + - core/arch/arm/plat-stm32mp1/sub.mk | 6 + - core/arch/arm/sm/pm_a32.S | 83 +- - core/arch/arm/tee/entry_std.c | 2 +- - core/drivers/gic.c | 210 ++- - core/drivers/stm32_bsec.c | 824 ++++++++++ - core/drivers/stm32_etzpc.c | 337 ++++ - core/drivers/stm32_gpio.c | 417 +++++ - core/drivers/stm32_i2c.c | 1629 ++++++++++++++++++++ - core/drivers/stm32_iwdg.c | 308 ++++ - core/drivers/stm32_rng.c | 200 +++ - core/drivers/stm32_rtc.c | 503 ++++++ - core/drivers/stm32_timer.c | 272 ++++ - core/drivers/stm32_uart.c | 142 +- - core/drivers/stpmic1.c | 954 ++++++++++++ - core/drivers/sub.mk | 9 + - core/include/drivers/gic.h | 29 + - core/include/drivers/stm32_bsec.h | 143 ++ - core/include/drivers/stm32_etzpc.h | 75 + - core/include/drivers/stm32_gpio.h | 107 ++ - core/include/drivers/stm32_i2c.h | 377 +++++ - core/include/drivers/stm32_iwdg.h | 17 + - core/include/drivers/stm32_rng.h | 14 + - core/include/drivers/stm32_rtc.h | 73 + - core/include/drivers/stm32_timer.h | 25 + - core/include/drivers/stm32_uart.h | 10 +- - core/include/drivers/stpmic1.h | 228 +++ - core/include/dt-bindings/clock/stm32mp1-clks.h | 252 +++ - core/include/dt-bindings/clock/stm32mp1-clksrc.h | 284 ++++ - core/include/dt-bindings/etzpc/stm32-etzpc.h | 108 ++ - .../dt-bindings/interrupt-controller/arm-gic.h | 21 + - core/include/dt-bindings/pinctrl/stm32-pinfunc.h | 41 + - core/include/dt-bindings/power/stm32mp1-power.h | 19 + - core/include/dt-bindings/reset/stm32mp1-resets.h | 108 ++ - core/include/kernel/interrupt.h | 15 + - core/kernel/console.c | 9 +- - core/kernel/interrupt.c | 10 + - core/lib/libfdt/fdt_ro.c | 154 +- - core/lib/libfdt/fdt_rw.c | 11 +- - core/lib/libfdt/fdt_wip.c | 29 +- - core/lib/libfdt/include/fdt.h | 8 + - core/lib/libfdt/include/libfdt.h | 247 ++- - core/secure_dt.mk | 107 ++ - core/sub.mk | 7 + - lib/libutils/ext/include/util.h | 7 + - mk/config.mk | 23 +- - scripts/bin_to_c.py | 58 + - 116 files changed, 21451 insertions(+), 195 deletions(-) - create mode 100644 core/arch/arm/fdts/stm32mp15-ddr.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157-pinctrl.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157a-dk1.dts - create mode 100644 core/arch/arm/fdts/stm32mp157c-dk2.dts - create mode 100644 core/arch/arm/fdts/stm32mp157c-ed1.dts - create mode 100644 core/arch/arm/fdts/stm32mp157c-ev1.dts - create mode 100644 core/arch/arm/fdts/stm32mp157c-security.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157c.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157caa-pinctrl.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157cab-pinctrl.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157cac-pinctrl.dtsi - create mode 100644 core/arch/arm/fdts/stm32mp157cad-pinctrl.dtsi - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32_reset.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32_reset.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/sub.mk - create mode 100644 core/arch/arm/plat-stm32mp1/pm/context.c - create mode 100644 core/arch/arm/plat-stm32mp1/pm/context.h - create mode 100644 core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c - create mode 100644 core/arch/arm/plat-stm32mp1/pm/low_power.c - create mode 100644 core/arch/arm/plat-stm32mp1/pm/pm_helpers.S - create mode 100644 core/arch/arm/plat-stm32mp1/pm/power.h - create mode 100644 core/arch/arm/plat-stm32mp1/pm/power_config.c - create mode 100644 core/arch/arm/plat-stm32mp1/pm/psci.c - create mode 100644 core/arch/arm/plat-stm32mp1/pm/sub.mk - create mode 100644 core/arch/arm/plat-stm32mp1/service/bsec_svc.c - create mode 100644 core/arch/arm/plat-stm32mp1/service/bsec_svc.h - create mode 100644 core/arch/arm/plat-stm32mp1/service/low_power_svc.c - create mode 100644 core/arch/arm/plat-stm32mp1/service/low_power_svc.h - create mode 100644 core/arch/arm/plat-stm32mp1/service/pwr_svc.c - create mode 100644 core/arch/arm/plat-stm32mp1/service/pwr_svc.h - create mode 100644 core/arch/arm/plat-stm32mp1/service/rcc_svc.c - create mode 100644 core/arch/arm/plat-stm32mp1/service/rcc_svc.h - create mode 100644 core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h - create mode 100644 core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c - create mode 100644 core/arch/arm/plat-stm32mp1/service/sub.mk - create mode 100644 core/arch/arm/plat-stm32mp1/shared_resources.c - create mode 100644 core/arch/arm/plat-stm32mp1/stm32_util.h - create mode 100644 core/arch/arm/plat-stm32mp1/stm32mp1_dt.c - create mode 100644 core/arch/arm/plat-stm32mp1/stm32mp_dt.h - create mode 100644 core/arch/arm/plat-stm32mp1/stm32mp_pm.h - create mode 100644 core/drivers/stm32_bsec.c - create mode 100644 core/drivers/stm32_etzpc.c - create mode 100644 core/drivers/stm32_gpio.c - create mode 100644 core/drivers/stm32_i2c.c - create mode 100644 core/drivers/stm32_iwdg.c - create mode 100644 core/drivers/stm32_rng.c - create mode 100644 core/drivers/stm32_rtc.c - create mode 100644 core/drivers/stm32_timer.c - create mode 100644 core/drivers/stpmic1.c - create mode 100644 core/include/drivers/stm32_bsec.h - create mode 100644 core/include/drivers/stm32_etzpc.h - create mode 100644 core/include/drivers/stm32_gpio.h - create mode 100644 core/include/drivers/stm32_i2c.h - create mode 100644 core/include/drivers/stm32_iwdg.h - create mode 100644 core/include/drivers/stm32_rng.h - create mode 100644 core/include/drivers/stm32_rtc.h - create mode 100644 core/include/drivers/stm32_timer.h - create mode 100644 core/include/drivers/stpmic1.h - create mode 100644 core/include/dt-bindings/clock/stm32mp1-clks.h - create mode 100644 core/include/dt-bindings/clock/stm32mp1-clksrc.h - create mode 100644 core/include/dt-bindings/etzpc/stm32-etzpc.h - create mode 100644 core/include/dt-bindings/interrupt-controller/arm-gic.h - create mode 100644 core/include/dt-bindings/pinctrl/stm32-pinfunc.h - create mode 100644 core/include/dt-bindings/power/stm32mp1-power.h - create mode 100644 core/include/dt-bindings/reset/stm32mp1-resets.h - create mode 100644 core/secure_dt.mk - create mode 100755 scripts/bin_to_c.py - -diff --git a/core/arch/arm/fdts/stm32mp15-ddr.dtsi b/core/arch/arm/fdts/stm32mp15-ddr.dtsi -new file mode 100644 -index 0000000..1a5c51c ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp15-ddr.dtsi -@@ -0,0 +1,153 @@ -+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -+/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+/ { -+ soc { -+ ddr: ddr@5A003000{ -+ -+ compatible = "st,stm32mp1-ddr"; -+ -+ reg = <0x5A003000 0x550 -+ 0x5A004000 0x234>; -+ -+ clocks = <&rcc AXIDCG>, -+ <&rcc DDRC1>, -+ <&rcc DDRC2>, -+ <&rcc DDRPHYC>, -+ <&rcc DDRCAPB>, -+ <&rcc DDRPHYCAPB>; -+ -+ clock-names = "axidcg", -+ "ddrc1", -+ "ddrc2", -+ "ddrphyc", -+ "ddrcapb", -+ "ddrphycapb"; -+ -+ st,mem-name = DDR_MEM_NAME; -+ st,mem-speed = ; -+ 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 -+ DDR_PCFGR_1 -+ DDR_PCFGW_1 -+ DDR_PCFGQOS0_1 -+ DDR_PCFGQOS1_1 -+ DDR_PCFGWQOS0_1 -+ DDR_PCFGWQOS1_1 -+ >; -+ -+ st,phy-reg = < -+ DDR_PGCR -+ DDR_ACIOCR -+ DDR_DXCCR -+ DDR_DSGCR -+ DDR_DCR -+ DDR_ODTCR -+ DDR_ZQ0CR1 -+ DDR_DX0GCR -+ DDR_DX1GCR -+ DDR_DX2GCR -+ DDR_DX3GCR -+ >; -+ -+ st,phy-timing = < -+ DDR_PTR0 -+ DDR_PTR1 -+ DDR_PTR2 -+ DDR_DTPR0 -+ DDR_DTPR1 -+ DDR_DTPR2 -+ DDR_MR0 -+ DDR_MR1 -+ DDR_MR2 -+ DDR_MR3 -+ >; -+ -+ st,phy-cal = < -+ DDR_DX0DLLCR -+ DDR_DX0DQTR -+ DDR_DX0DQSTR -+ DDR_DX1DLLCR -+ DDR_DX1DQTR -+ DDR_DX1DQSTR -+ DDR_DX2DLLCR -+ DDR_DX2DQTR -+ DDR_DX2DQSTR -+ DDR_DX3DLLCR -+ DDR_DX3DQTR -+ DDR_DX3DQSTR -+ >; -+ -+ status = "okay"; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -new file mode 100644 -index 0000000..16b8cf6 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -@@ -0,0 +1,121 @@ -+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -+/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ */ -+/* STM32MP157C DK1/DK2 BOARD configuration -+ * 1x DDR3L 4Gb, 16-bit, 533MHz. -+ * Reference used NT5CC256M16DP-DI from NANYA -+ * -+ * DDR type / Platform DDR3/3L -+ * freq 533MHz -+ * width 16 -+ * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G -+ * DDR density 4 -+ * timing mode optimized -+ * Scheduling/QoS options : type = 2 -+ * address mapping : RBC -+ * Tc > + 85C : N -+ */ -+ -+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41" -+#define DDR_MEM_SPEED 533000 -+#define DDR_MEM_SIZE 0x20000000 -+ -+#define DDR_MSTR 0x00041401 -+#define DDR_MRCTRL0 0x00000010 -+#define DDR_MRCTRL1 0x00000000 -+#define DDR_DERATEEN 0x00000000 -+#define DDR_DERATEINT 0x00800000 -+#define DDR_PWRCTL 0x00000000 -+#define DDR_PWRTMG 0x00400010 -+#define DDR_HWLPCTL 0x00000000 -+#define DDR_RFSHCTL0 0x00210000 -+#define DDR_RFSHCTL3 0x00000000 -+#define DDR_RFSHTMG 0x0081008B -+#define DDR_CRCPARCTL0 0x00000000 -+#define DDR_DRAMTMG0 0x121B2414 -+#define DDR_DRAMTMG1 0x000A041C -+#define DDR_DRAMTMG2 0x0608090F -+#define DDR_DRAMTMG3 0x0050400C -+#define DDR_DRAMTMG4 0x08040608 -+#define DDR_DRAMTMG5 0x06060403 -+#define DDR_DRAMTMG6 0x02020002 -+#define DDR_DRAMTMG7 0x00000202 -+#define DDR_DRAMTMG8 0x00001005 -+#define DDR_DRAMTMG14 0x000000A0 -+#define DDR_ZQCTL0 0xC2000040 -+#define DDR_DFITMG0 0x02060105 -+#define DDR_DFITMG1 0x00000202 -+#define DDR_DFILPCFG0 0x07000000 -+#define DDR_DFIUPD0 0xC0400003 -+#define DDR_DFIUPD1 0x00000000 -+#define DDR_DFIUPD2 0x00000000 -+#define DDR_DFIPHYMSTR 0x00000000 -+#define DDR_ADDRMAP1 0x00070707 -+#define DDR_ADDRMAP2 0x00000000 -+#define DDR_ADDRMAP3 0x1F000000 -+#define DDR_ADDRMAP4 0x00001F1F -+#define DDR_ADDRMAP5 0x06060606 -+#define DDR_ADDRMAP6 0x0F060606 -+#define DDR_ADDRMAP9 0x00000000 -+#define DDR_ADDRMAP10 0x00000000 -+#define DDR_ADDRMAP11 0x00000000 -+#define DDR_ODTCFG 0x06000600 -+#define DDR_ODTMAP 0x00000001 -+#define DDR_SCHED 0x00000C01 -+#define DDR_SCHED1 0x00000000 -+#define DDR_PERFHPR1 0x01000001 -+#define DDR_PERFLPR1 0x08000200 -+#define DDR_PERFWR1 0x08000400 -+#define DDR_DBG0 0x00000000 -+#define DDR_DBG1 0x00000000 -+#define DDR_DBGCMD 0x00000000 -+#define DDR_POISONCFG 0x00000000 -+#define DDR_PCCFG 0x00000010 -+#define DDR_PCFGR_0 0x00010000 -+#define DDR_PCFGW_0 0x00000000 -+#define DDR_PCFGQOS0_0 0x02100C03 -+#define DDR_PCFGQOS1_0 0x00800100 -+#define DDR_PCFGWQOS0_0 0x01100C03 -+#define DDR_PCFGWQOS1_0 0x01000200 -+#define DDR_PCFGR_1 0x00010000 -+#define DDR_PCFGW_1 0x00000000 -+#define DDR_PCFGQOS0_1 0x02100C03 -+#define DDR_PCFGQOS1_1 0x00800040 -+#define DDR_PCFGWQOS0_1 0x01100C03 -+#define DDR_PCFGWQOS1_1 0x01000200 -+#define DDR_PGCR 0x01442E02 -+#define DDR_PTR0 0x0022AA5B -+#define DDR_PTR1 0x04841104 -+#define DDR_PTR2 0x042DA068 -+#define DDR_ACIOCR 0x10400812 -+#define DDR_DXCCR 0x00000C40 -+#define DDR_DSGCR 0xF200001F -+#define DDR_DCR 0x0000000B -+#define DDR_DTPR0 0x38D488D0 -+#define DDR_DTPR1 0x098B00D8 -+#define DDR_DTPR2 0x10023600 -+#define DDR_MR0 0x00000840 -+#define DDR_MR1 0x00000000 -+#define DDR_MR2 0x00000208 -+#define DDR_MR3 0x00000000 -+#define DDR_ODTCR 0x00010000 -+#define DDR_ZQ0CR1 0x00000038 -+#define DDR_DX0GCR 0x0000CE81 -+#define DDR_DX0DLLCR 0x40000000 -+#define DDR_DX0DQTR 0xFFFFFFFF -+#define DDR_DX0DQSTR 0x3DB02000 -+#define DDR_DX1GCR 0x0000CE81 -+#define DDR_DX1DLLCR 0x40000000 -+#define DDR_DX1DQTR 0xFFFFFFFF -+#define DDR_DX1DQSTR 0x3DB02000 -+#define DDR_DX2GCR 0x0000CE81 -+#define DDR_DX2DLLCR 0x40000000 -+#define DDR_DX2DQTR 0xFFFFFFFF -+#define DDR_DX2DQSTR 0x3DB02000 -+#define DDR_DX3GCR 0x0000CE81 -+#define DDR_DX3DLLCR 0x40000000 -+#define DDR_DX3DQTR 0xFFFFFFFF -+#define DDR_DX3DQSTR 0x3DB02000 -+ -+#include "stm32mp15-ddr.dtsi" -diff --git a/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -new file mode 100644 -index 0000000..82e7104 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -@@ -0,0 +1,122 @@ -+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -+/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+/* STM32MP157C ED1 BOARD configuration -+ * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. -+ * Reference used NT5CC256M16DP-DI from NANYA -+ * -+ * DDR type / Platform DDR3/3L -+ * freq 533MHz -+ * width 32 -+ * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G -+ * DDR density 8 -+ * timing mode optimized -+ * Scheduling/QoS options : type = 2 -+ * address mapping : RBC -+ * Tc > + 85C : N -+ */ -+ -+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41" -+#define DDR_MEM_SPEED 533000 -+#define DDR_MEM_SIZE 0x40000000 -+ -+#define DDR_MSTR 0x00040401 -+#define DDR_MRCTRL0 0x00000010 -+#define DDR_MRCTRL1 0x00000000 -+#define DDR_DERATEEN 0x00000000 -+#define DDR_DERATEINT 0x00800000 -+#define DDR_PWRCTL 0x00000000 -+#define DDR_PWRTMG 0x00400010 -+#define DDR_HWLPCTL 0x00000000 -+#define DDR_RFSHCTL0 0x00210000 -+#define DDR_RFSHCTL3 0x00000000 -+#define DDR_RFSHTMG 0x0081008B -+#define DDR_CRCPARCTL0 0x00000000 -+#define DDR_DRAMTMG0 0x121B2414 -+#define DDR_DRAMTMG1 0x000A041C -+#define DDR_DRAMTMG2 0x0608090F -+#define DDR_DRAMTMG3 0x0050400C -+#define DDR_DRAMTMG4 0x08040608 -+#define DDR_DRAMTMG5 0x06060403 -+#define DDR_DRAMTMG6 0x02020002 -+#define DDR_DRAMTMG7 0x00000202 -+#define DDR_DRAMTMG8 0x00001005 -+#define DDR_DRAMTMG14 0x000000A0 -+#define DDR_ZQCTL0 0xC2000040 -+#define DDR_DFITMG0 0x02060105 -+#define DDR_DFITMG1 0x00000202 -+#define DDR_DFILPCFG0 0x07000000 -+#define DDR_DFIUPD0 0xC0400003 -+#define DDR_DFIUPD1 0x00000000 -+#define DDR_DFIUPD2 0x00000000 -+#define DDR_DFIPHYMSTR 0x00000000 -+#define DDR_ADDRMAP1 0x00080808 -+#define DDR_ADDRMAP2 0x00000000 -+#define DDR_ADDRMAP3 0x00000000 -+#define DDR_ADDRMAP4 0x00001F1F -+#define DDR_ADDRMAP5 0x07070707 -+#define DDR_ADDRMAP6 0x0F070707 -+#define DDR_ADDRMAP9 0x00000000 -+#define DDR_ADDRMAP10 0x00000000 -+#define DDR_ADDRMAP11 0x00000000 -+#define DDR_ODTCFG 0x06000600 -+#define DDR_ODTMAP 0x00000001 -+#define DDR_SCHED 0x00000C01 -+#define DDR_SCHED1 0x00000000 -+#define DDR_PERFHPR1 0x01000001 -+#define DDR_PERFLPR1 0x08000200 -+#define DDR_PERFWR1 0x08000400 -+#define DDR_DBG0 0x00000000 -+#define DDR_DBG1 0x00000000 -+#define DDR_DBGCMD 0x00000000 -+#define DDR_POISONCFG 0x00000000 -+#define DDR_PCCFG 0x00000010 -+#define DDR_PCFGR_0 0x00010000 -+#define DDR_PCFGW_0 0x00000000 -+#define DDR_PCFGQOS0_0 0x02100C03 -+#define DDR_PCFGQOS1_0 0x00800100 -+#define DDR_PCFGWQOS0_0 0x01100C03 -+#define DDR_PCFGWQOS1_0 0x01000200 -+#define DDR_PCFGR_1 0x00010000 -+#define DDR_PCFGW_1 0x00000000 -+#define DDR_PCFGQOS0_1 0x02100C03 -+#define DDR_PCFGQOS1_1 0x00800040 -+#define DDR_PCFGWQOS0_1 0x01100C03 -+#define DDR_PCFGWQOS1_1 0x01000200 -+#define DDR_PGCR 0x01442E02 -+#define DDR_PTR0 0x0022AA5B -+#define DDR_PTR1 0x04841104 -+#define DDR_PTR2 0x042DA068 -+#define DDR_ACIOCR 0x10400812 -+#define DDR_DXCCR 0x00000C40 -+#define DDR_DSGCR 0xF200001F -+#define DDR_DCR 0x0000000B -+#define DDR_DTPR0 0x38D488D0 -+#define DDR_DTPR1 0x098B00D8 -+#define DDR_DTPR2 0x10023600 -+#define DDR_MR0 0x00000840 -+#define DDR_MR1 0x00000000 -+#define DDR_MR2 0x00000208 -+#define DDR_MR3 0x00000000 -+#define DDR_ODTCR 0x00010000 -+#define DDR_ZQ0CR1 0x00000038 -+#define DDR_DX0GCR 0x0000CE81 -+#define DDR_DX0DLLCR 0x40000000 -+#define DDR_DX0DQTR 0xFFFFFFFF -+#define DDR_DX0DQSTR 0x3DB02000 -+#define DDR_DX1GCR 0x0000CE81 -+#define DDR_DX1DLLCR 0x40000000 -+#define DDR_DX1DQTR 0xFFFFFFFF -+#define DDR_DX1DQSTR 0x3DB02000 -+#define DDR_DX2GCR 0x0000CE81 -+#define DDR_DX2DLLCR 0x40000000 -+#define DDR_DX2DQTR 0xFFFFFFFF -+#define DDR_DX2DQSTR 0x3DB02000 -+#define DDR_DX3GCR 0x0000CE81 -+#define DDR_DX3DLLCR 0x40000000 -+#define DDR_DX3DQTR 0xFFFFFFFF -+#define DDR_DX3DQSTR 0x3DB02000 -+ -+#include "stm32mp15-ddr.dtsi" -diff --git a/core/arch/arm/fdts/stm32mp157-pinctrl.dtsi b/core/arch/arm/fdts/stm32mp157-pinctrl.dtsi -new file mode 100644 -index 0000000..8037e4f ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157-pinctrl.dtsi -@@ -0,0 +1,350 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+#include -+ -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "st,stm32mp157-pinctrl"; -+ ranges = <0 0x50002000 0xa400>; -+ pins-are-numbered; -+ -+ gpioa: gpio@50002000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x0 0x400>; -+ clocks = <&rcc GPIOA>; -+ st,bank-name = "GPIOA"; -+ status = "disabled"; -+ }; -+ -+ gpiob: gpio@50003000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x1000 0x400>; -+ clocks = <&rcc GPIOB>; -+ st,bank-name = "GPIOB"; -+ status = "disabled"; -+ }; -+ -+ gpioc: gpio@50004000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x2000 0x400>; -+ clocks = <&rcc GPIOC>; -+ st,bank-name = "GPIOC"; -+ status = "disabled"; -+ }; -+ -+ gpiod: gpio@50005000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x3000 0x400>; -+ clocks = <&rcc GPIOD>; -+ st,bank-name = "GPIOD"; -+ status = "disabled"; -+ }; -+ -+ gpioe: gpio@50006000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x4000 0x400>; -+ clocks = <&rcc GPIOE>; -+ st,bank-name = "GPIOE"; -+ status = "disabled"; -+ }; -+ -+ gpiof: gpio@50007000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x5000 0x400>; -+ clocks = <&rcc GPIOF>; -+ st,bank-name = "GPIOF"; -+ status = "disabled"; -+ }; -+ -+ gpiog: gpio@50008000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x6000 0x400>; -+ clocks = <&rcc GPIOG>; -+ st,bank-name = "GPIOG"; -+ status = "disabled"; -+ }; -+ -+ gpioh: gpio@50009000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x7000 0x400>; -+ clocks = <&rcc GPIOH>; -+ st,bank-name = "GPIOH"; -+ status = "disabled"; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x8000 0x400>; -+ clocks = <&rcc GPIOI>; -+ st,bank-name = "GPIOI"; -+ status = "disabled"; -+ }; -+ -+ gpioj: gpio@5000b000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x9000 0x400>; -+ clocks = <&rcc GPIOJ>; -+ st,bank-name = "GPIOJ"; -+ status = "disabled"; -+ }; -+ -+ gpiok: gpio@5000c000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0xa000 0x400>; -+ clocks = <&rcc GPIOK>; -+ st,bank-name = "GPIOK"; -+ status = "disabled"; -+ }; -+ -+ qspi_bk1_pins_a: qspi-bk1-0 { -+ pins1 { -+ pinmux = , /* QSPI_BK1_IO0 */ -+ , /* QSPI_BK1_IO1 */ -+ , /* QSPI_BK1_IO2 */ -+ ; /* QSPI_BK1_IO3 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ pins2 { -+ pinmux = ; /* QSPI_BK1_NCS */ -+ bias-pull-up; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ }; -+ -+ qspi_bk2_pins_a: qspi-bk2-0 { -+ pins1 { -+ pinmux = , /* QSPI_BK2_IO0 */ -+ , /* QSPI_BK2_IO1 */ -+ , /* QSPI_BK2_IO2 */ -+ ; /* QSPI_BK2_IO3 */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ pins2 { -+ pinmux = ; /* QSPI_BK2_NCS */ -+ bias-pull-up; -+ drive-push-pull; -+ slew-rate = <1>; -+ }; -+ }; -+ -+ qspi_clk_pins_a: qspi-clk-0 { -+ pins { -+ pinmux = ; /* QSPI_CLK */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <3>; -+ }; -+ }; -+ -+ sdmmc1_b4_pins_a: sdmmc1-b4-0 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0 */ -+ , /* SDMMC1_D1 */ -+ , /* SDMMC1_D2 */ -+ , /* SDMMC1_D3 */ -+ ; /* SDMMC1_CMD */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC1_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-disable; -+ }; -+ }; -+ -+ sdmmc1_dir_pins_a: sdmmc1-dir-0 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0DIR */ -+ , /* SDMMC1_D123DIR */ -+ ; /* SDMMC1_CDIR */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2{ -+ pinmux = ; /* SDMMC1_CKIN */ -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc1_dir_pins_b: sdmmc1-dir-1 { -+ pins1 { -+ pinmux = , /* SDMMC1_D0DIR */ -+ , /* SDMMC1_D123DIR */ -+ ; /* SDMMC1_CDIR */ -+ slew-rate = <3>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC1_CKIN */ -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc2_b4_pins_a: sdmmc2-b4-0 { -+ pins1 { -+ pinmux = , /* SDMMC2_D0 */ -+ , /* SDMMC2_D1 */ -+ , /* SDMMC2_D2 */ -+ , /* SDMMC2_D3 */ -+ ; /* SDMMC2_CMD */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ pins2 { -+ pinmux = ; /* SDMMC2_CK */ -+ slew-rate = <2>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ }; -+ -+ sdmmc2_d47_pins_a: sdmmc2-d47-0 { -+ pins { -+ pinmux = , /* SDMMC2_D4 */ -+ , /* SDMMC2_D5 */ -+ , /* SDMMC2_D6 */ -+ ; /* SDMMC2_D7 */ -+ slew-rate = <1>; -+ drive-push-pull; -+ bias-pull-up; -+ }; -+ }; -+ -+ uart4_pins_a: uart4-0 { -+ pins1 { -+ pinmux = ; /* UART4_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* UART4_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ uart7_pins_a: uart7-0 { -+ pins1 { -+ pinmux = ; /* USART7_TX */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = ; /* USART7_RX */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_pins_a: usart3-0 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ ; /* USART3_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ -+ usart3_pins_b: usart3-1 { -+ pins1 { -+ pinmux = , /* USART3_TX */ -+ ; /* USART3_RTS */ -+ bias-disable; -+ drive-push-pull; -+ slew-rate = <0>; -+ }; -+ pins2 { -+ pinmux = , /* USART3_RX */ -+ ; /* USART3_CTS_NSS */ -+ bias-disable; -+ }; -+ }; -+ }; -+ -+ pinctrl_z: pin-controller-z@54004000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "st,stm32mp157-z-pinctrl"; -+ ranges = <0 0x54004000 0x400>; -+ pins-are-numbered; -+ -+ gpioz: gpio@54004000 { -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0 0x400>; -+ clocks = <&rcc GPIOZ>; -+ st,bank-name = "GPIOZ"; -+ st,bank-ioport = <11>; -+ status = "disabled"; -+ }; -+ -+ i2c4_pins_a: i2c4-0 { -+ pins { -+ pinmux = , /* I2C4_SCL */ -+ ; /* I2C4_SDA */ -+ bias-disable; -+ drive-open-drain; -+ slew-rate = <0>; -+ }; -+ }; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157a-dk1.dts b/core/arch/arm/fdts/stm32mp157a-dk1.dts -new file mode 100644 -index 0000000..e42bdcd ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157a-dk1.dts -@@ -0,0 +1,380 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018-2019 - All Rights Reserved -+ * Author: Alexandre Torgue . -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157c.dtsi" -+#include "stm32mp157cac-pinctrl.dtsi" -+ -+/ { -+ model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; -+ compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; -+ -+ aliases { -+ serial0 = &uart4; -+ serial1 = &usart3; -+ serial2 = &uart7; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+}; -+ -+}; -+ -+&clk_hse { -+ st,digbypass; -+}; -+ -+&i2c4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c4_pins_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ status = "okay"; -+ -+ pmic: stpmic@33 { -+ compatible = "st,stpmic1"; -+ reg = <0x33>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ status = "okay"; -+ -+ st,main-control-register = <0x04>; -+ st,vin-control-register = <0xc0>; -+ st,usb-control-register = <0x20>; -+ -+ regulators { -+ compatible = "st,stpmic1-regulators"; -+ -+ ldo1-supply = <&v3v3>; -+ ldo3-supply = <&vdd_ddr>; -+ ldo6-supply = <&v3v3>; -+ -+ vddcore: buck1 { -+ regulator-name = "vddcore"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_ddr: buck2 { -+ regulator-name = "vdd_ddr"; -+ regulator-min-microvolt = <1350000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd: buck3 { -+ regulator-name = "vdd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ st,mask-reset; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ v3v3: buck4 { -+ regulator-name = "v3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ regulator-initial-mode = <0>; -+ }; -+ -+ v1v8_audio: ldo1 { -+ regulator-name = "v1v8_audio"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ -+ v3v3_hdmi: ldo2 { -+ regulator-name = "v3v3_hdmi"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vtt_ddr: ldo3 { -+ regulator-name = "vtt_ddr"; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <750000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_usb: ldo4 { -+ regulator-name = "vdd_usb"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vdda: ldo5 { -+ regulator-name = "vdda"; -+ regulator-min-microvolt = <2900000>; -+ regulator-max-microvolt = <2900000>; -+ regulator-boot-on; -+ }; -+ -+ v1v2_hdmi: ldo6 { -+ regulator-name = "v1v2_hdmi"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ regulator-always-on; -+ }; -+ -+ vref_ddr: vref_ddr { -+ regulator-name = "vref_ddr"; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ }; -+ }; -+}; -+ -+&iwdg2 { -+ timeout-sec = <32>; -+ status = "okay"; -+}; -+ -+&pwr { -+ pwr-supply = <&vdd>; -+}; -+ -+/* RNG1 is used by non secure at run time and by secure (low power sequences) */ -+&rng1 { -+ status = "okay"; -+ secure-status = "okay"; -+}; -+ -+&rtc { -+ status = "okay"; -+}; -+ -+&sdmmc1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_b4_pins_a>; -+ broken-cd; -+ st,neg-edge; -+ bus-width = <4>; -+ vmmc-supply = <&v3v3>; -+ status = "okay"; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart4_pins_a>; -+ status = "okay"; -+}; -+ -+&uart7 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart7_pins_a>; -+ status = "disabled"; -+}; -+ -+&usart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usart3_pins_b>; -+ status = "disabled"; -+}; -+ -+ -+/* ATF Specific */ -+#include -+#include -+#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" -+#include "stm32mp157c-security.dtsi" -+ -+/ { -+ aliases { -+ gpio0 = &gpioa; -+ gpio1 = &gpiob; -+ gpio2 = &gpioc; -+ gpio3 = &gpiod; -+ gpio4 = &gpioe; -+ gpio5 = &gpiof; -+ gpio6 = &gpiog; -+ gpio7 = &gpioh; -+ gpio8 = &gpioi; -+ gpio25 = &gpioz; -+ i2c3 = &i2c4; -+ }; -+}; -+ -+/* CLOCK presence */ -+&rcc { -+ secure-status = "okay"; -+ st,hsi-cal; -+ st,csi-cal; -+ st,cal-sec = <60>; -+}; -+ -+/* Security specific */ -+&etzpc { -+ st,decprot = < -+ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ >; -+}; -+ -+&iwdg2 { -+ secure-status = "okay"; -+}; -+ -+&pwr { -+ system_suspend_supported_soc_modes = < -+ STM32_PM_CSLEEP_RUN -+ STM32_PM_CSTOP_ALLOW_LP_STOP -+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR -+ >; -+ -+ system_off_soc_mode = ; -+}; -+ -+&timers15 { -+ secure-status = "okay"; -+ st,hsi-cal-input = <7>; -+ st,csi_cal-input = <8>; -+}; -+ -+/* Low-power states of regulators */ -+&vddcore { -+ lp-stop { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1200000>; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&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 { -+ lp-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+}; -+ -+&v3v3 { -+ lp-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v1v8_audio { -+ 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; -+ }; -+}; -+ -+&vtt_ddr { -+ lp-stop { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdd_usb { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdda { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v1v2_hdmi { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vref_ddr { -+ lp-stop { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157c-dk2.dts b/core/arch/arm/fdts/stm32mp157c-dk2.dts -new file mode 100644 -index 0000000..fdcf4c8 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157c-dk2.dts -@@ -0,0 +1,16 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue . -+ */ -+ -+/dts-v1/; -+ -+#include "stm32mp157a-dk1.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; -+ compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; -+ -+}; -+ -diff --git a/core/arch/arm/fdts/stm32mp157c-ed1.dts b/core/arch/arm/fdts/stm32mp157c-ed1.dts -new file mode 100644 -index 0000000..8462d23 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157c-ed1.dts -@@ -0,0 +1,381 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157c.dtsi" -+#include "stm32mp157caa-pinctrl.dtsi" -+ -+/ { -+ model = "STMicroelectronics STM32MP157C eval daughter"; -+ compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial0 = &uart4; -+ }; -+}; -+ -+&clk_hse { -+ st,digbypass; -+}; -+ -+&i2c4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c4_pins_a>; -+ i2c-scl-rising-time-ns = <185>; -+ i2c-scl-falling-time-ns = <20>; -+ status = "okay"; -+ -+ pmic: stpmic@33 { -+ compatible = "st,stpmic1"; -+ reg = <0x33>; -+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ status = "okay"; -+ -+ st,main-control-register = <0x04>; -+ st,vin-control-register = <0xc0>; -+ st,usb-control-register = <0x20>; -+ -+ regulators { -+ compatible = "st,stpmic1-regulators"; -+ -+ ldo1-supply = <&v3v3>; -+ ldo2-supply = <&v3v3>; -+ ldo3-supply = <&vdd_ddr>; -+ ldo5-supply = <&v3v3>; -+ ldo6-supply = <&v3v3>; -+ -+ vddcore: buck1 { -+ regulator-name = "vddcore"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_ddr: buck2 { -+ regulator-name = "vdd_ddr"; -+ regulator-min-microvolt = <1350000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-always-on; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ vdd: buck3 { -+ regulator-name = "vdd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ st,mask-reset; -+ regulator-initial-mode = <0>; -+ regulator-over-current-protection; -+ }; -+ -+ v3v3: buck4 { -+ regulator-name = "v3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ regulator-initial-mode = <0>; -+ }; -+ -+ vdda: ldo1 { -+ regulator-name = "vdda"; -+ regulator-min-microvolt = <2900000>; -+ regulator-max-microvolt = <2900000>; -+ }; -+ -+ v2v8: ldo2 { -+ regulator-name = "v2v8"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; -+ }; -+ -+ vtt_ddr: ldo3 { -+ regulator-name = "vtt_ddr"; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <750000>; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ -+ vdd_usb: ldo4 { -+ regulator-name = "vdd_usb"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vdd_sd: ldo5 { -+ regulator-name = "vdd_sd"; -+ regulator-min-microvolt = <2900000>; -+ regulator-max-microvolt = <2900000>; -+ regulator-boot-on; -+ }; -+ -+ v1v8: ldo6 { -+ regulator-name = "v1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ -+ vref_ddr: vref_ddr { -+ regulator-name = "vref_ddr"; -+ regulator-always-on; -+ regulator-over-current-protection; -+ }; -+ }; -+ }; -+}; -+ -+&iwdg2 { -+ timeout-sec = <32>; -+ status = "okay"; -+}; -+ -+&pwr { -+ pwr-supply = <&vdd>; -+}; -+ -+/* RNG1 is used by non secure at run time and by secure (low power sequences) */ -+&rng1 { -+ status = "okay"; -+ secure-status = "okay"; -+}; -+ -+&rtc { -+ status = "okay"; -+}; -+ -+&sdmmc1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; -+ broken-cd; -+ st,sig-dir; -+ st,neg-edge; -+ st,use-ckin; -+ bus-width = <4>; -+ vmmc-supply = <&vdd_sd>; -+ sd-uhs-sdr12; -+ sd-uhs-sdr25; -+ sd-uhs-sdr50; -+ sd-uhs-ddr50; -+ sd-uhs-sdr104; -+ status = "okay"; -+}; -+ -+&sdmmc2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; -+ non-removable; -+ no-sd; -+ no-sdio; -+ st,neg-edge; -+ bus-width = <8>; -+ vmmc-supply = <&v3v3>; -+ vqmmc-supply = <&v3v3>; -+ mmc-ddr-3_3v; -+ status = "okay"; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart4_pins_a>; -+ status = "okay"; -+}; -+ -+/* ATF Specific */ -+#include -+#include -+#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" -+#include "stm32mp157c-security.dtsi" -+ -+/ { -+ aliases { -+ gpio0 = &gpioa; -+ gpio1 = &gpiob; -+ gpio2 = &gpioc; -+ gpio3 = &gpiod; -+ gpio4 = &gpioe; -+ gpio5 = &gpiof; -+ gpio6 = &gpiog; -+ gpio7 = &gpioh; -+ gpio8 = &gpioi; -+ gpio9 = &gpioj; -+ gpio10 = &gpiok; -+ gpio25 = &gpioz; -+ i2c3 = &i2c4; -+ }; -+}; -+ -+/* CLOCK presence */ -+&rcc { -+ secure-status = "okay"; -+ st,hsi-cal; -+ st,csi-cal; -+ st,cal-sec = <60>; -+}; -+ -+/* Security specific */ -+&etzpc { -+ st,decprot = < -+ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -+ >; -+}; -+ -+&iwdg2 { -+ secure-status = "okay"; -+}; -+ -+&pwr { -+ system_suspend_supported_soc_modes = < -+ STM32_PM_CSLEEP_RUN -+ STM32_PM_CSTOP_ALLOW_LP_STOP -+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR -+ >; -+ -+ system_off_soc_mode = ; -+}; -+ -+&timers15 { -+ secure-status = "okay"; -+ st,hsi-cal-input = <7>; -+ st,csi_cal-input = <8>; -+}; -+ -+/* Low-power states of regulators */ -+&vddcore { -+ lp-stop { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1200000>; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&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 { -+ lp-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; -+}; -+ -+&v3v3 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdda { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v2v8 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vtt_ddr { -+ lp-stop { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdd_usb { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vdd_sd { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&v1v8 { -+ standby-ddr-sr { -+ regulator-off-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -+ -+&vref_ddr { -+ lp-stop { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-sr { -+ regulator-on-in-suspend; -+ }; -+ standby-ddr-off { -+ regulator-off-in-suspend; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157c-ev1.dts b/core/arch/arm/fdts/stm32mp157c-ev1.dts -new file mode 100644 -index 0000000..cfde8ed ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157c-ev1.dts -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+/dts-v1/; -+ -+#include "stm32mp157c-ed1.dts" -+ -+/ { -+ model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; -+ compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ aliases { -+ serial1 = &usart3; -+ }; -+}; -+ -+&fmc { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ nand: nand@0 { -+ reg = <0>; -+ nand-on-flash-bbt; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+}; -+ -+&qspi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; -+ reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ flash0: mx66l51235l@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-rx-bus-width = <4>; -+ spi-max-frequency = <108000000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+ -+ flash1: mx66l51235l@1 { -+ compatible = "jedec,spi-nor"; -+ reg = <1>; -+ spi-rx-bus-width = <4>; -+ spi-max-frequency = <108000000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ }; -+}; -+ -+&usart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usart3_pins_a>; -+ status = "disabled"; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157c-security.dtsi b/core/arch/arm/fdts/stm32mp157c-security.dtsi -new file mode 100644 -index 0000000..bff1043 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157c-security.dtsi -@@ -0,0 +1,71 @@ -+/* -+ * Copyright : STMicroelectronics 2017 -+ * -+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause -+ */ -+ -+#include -+ -+/ { -+ soc { -+ iwdg1: iwdg@5C003000 { -+ compatible = "st,stm32mp1-iwdg"; -+ reg = <0x5C003000 0x400>; -+ clocks = <&rcc IWDG1>, <&rcc CK_LSI>; -+ clock-names = "pclk", "lsi"; -+ interrupts = ; -+ status = "disabled"; -+ secure-status = "disabled"; -+ }; -+ -+ etzpc: etzpc@5C007000 { -+ compatible = "st,stm32-etzpc"; -+ reg = <0x5C007000 0x400>; -+ clocks = <&rcc TZPC>; -+ status = "disabled"; -+ secure-status = "okay"; -+ }; -+ -+ stgen: stgen@5C008000 { -+ compatible = "st,stm32-stgen"; -+ reg = <0x5C008000 0x1000>; -+ }; -+ }; -+}; -+ -+&bsec { -+ mac_addr: mac_addr@e4 { -+ reg = <0xe4 0x6>; -+ }; -+ /* Spare field to align on 32-bit OTP granularity */ -+ spare_ns_ea: spare_ns_ea@ea { -+ reg = <0xea 0x2>; -+ }; -+ board_id: board_id@ec { -+ reg = <0xec 0x4>; -+ }; -+}; -+ -+&iwdg2 { -+ secure-interrupts = ; -+}; -+ -+&rcc { -+ secure-interrupts = ; -+ interrupt-names = "wakeup"; -+}; -+ -+&sdmmc1 { -+ compatible = "st,stm32-sdmmc2"; -+}; -+ -+&sdmmc2 { -+ compatible = "st,stm32-sdmmc2"; -+}; -+ -+&tamp { -+ compatible = "st,stm32-tamp"; -+ clocks = <&rcc RTCAPB>; -+ interrupts = ; -+ secure-status= "disabled"; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157c.dtsi b/core/arch/arm/fdts/stm32mp157c.dtsi -new file mode 100644 -index 0000000..06c2cf1 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157c.dtsi -@@ -0,0 +1,371 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved -+ * Author: Ludovic Barre for STMicroelectronics. -+ */ -+#include -+#include -+#include -+ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ intc: interrupt-controller@a0021000 { -+ compatible = "arm,cortex-a7-gic"; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ reg = <0xa0021000 0x1000>, -+ <0xa0022000 0x2000>; -+ }; -+ -+ clocks { -+ clk_hse: clk-hse { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <24000000>; -+ }; -+ -+ clk_hsi: clk-hsi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <64000000>; -+ }; -+ -+ clk_lse: clk-lse { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32768>; -+ }; -+ -+ clk_lsi: clk-lsi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32000>; -+ }; -+ -+ clk_csi: clk-csi { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <4000000>; -+ }; -+ -+ clk_i2s_ckin: i2s_ckin { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <0>; -+ }; -+ -+ clk_dsi_phy: ck_dsi_phy { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <0>; -+ }; -+ }; -+ -+ soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ interrupt-parent = <&intc>; -+ ranges; -+ -+ timers12: timer@40006000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32-timers"; -+ reg = <0x40006000 0x400>; -+ clocks = <&rcc TIM12_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ -+ usart2: serial@4000e000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x4000e000 0x400>; -+ clocks = <&rcc USART2_K>; -+ resets = <&rcc USART2_R>; -+ status = "disabled"; -+ }; -+ -+ usart3: serial@4000f000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x4000f000 0x400>; -+ clocks = <&rcc USART3_K>; -+ resets = <&rcc USART3_R>; -+ status = "disabled"; -+ }; -+ -+ uart4: serial@40010000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x40010000 0x400>; -+ clocks = <&rcc UART4_K>; -+ resets = <&rcc UART4_R>; -+ status = "disabled"; -+ }; -+ -+ uart5: serial@40011000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x40011000 0x400>; -+ clocks = <&rcc UART5_K>; -+ resets = <&rcc UART5_R>; -+ status = "disabled"; -+ }; -+ -+ -+ uart7: serial@40018000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x40018000 0x400>; -+ clocks = <&rcc UART7_K>; -+ resets = <&rcc UART7_R>; -+ status = "disabled"; -+ }; -+ -+ uart8: serial@40019000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x40019000 0x400>; -+ clocks = <&rcc UART8_K>; -+ resets = <&rcc UART8_R>; -+ status = "disabled"; -+ }; -+ -+ usart6: serial@44003000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x44003000 0x400>; -+ clocks = <&rcc USART6_K>; -+ resets = <&rcc USART6_R>; -+ status = "disabled"; -+ }; -+ -+ timers15: timer@44006000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32-timers"; -+ reg = <0x44006000 0x400>; -+ clocks = <&rcc TIM15_K>; -+ clock-names = "int"; -+ status = "disabled"; -+ }; -+ -+ sdmmc3: sdmmc@48004000 { -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; -+ reg = <0x48004000 0x400>, <0x48005000 0x400>; -+ clocks = <&rcc SDMMC3_K>; -+ clock-names = "apb_pclk"; -+ resets = <&rcc SDMMC3_R>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ max-frequency = <120000000>; -+ status = "disabled"; -+ }; -+ -+ usbotg_hs: usb-otg@49000000 { -+ compatible = "st,stm32mp1-hsotg", "snps,dwc2"; -+ reg = <0x49000000 0x10000>; -+ clocks = <&rcc USBO_K>; -+ clock-names = "otg"; -+ resets = <&rcc USBO_R>; -+ reset-names = "dwc2"; -+ status = "disabled"; -+ }; -+ -+ rcc: rcc@50000000 { -+ compatible = "st,stm32mp1-rcc", "syscon"; -+ reg = <0x50000000 0x1000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ interrupts = ; -+ }; -+ -+ pwr: pwr@50001000 { -+ compatible = "st,stm32mp1-pwr", "syscon", "simple-mfd"; -+ reg = <0x50001000 0x400>; -+ }; -+ -+ exti: interrupt-controller@5000d000 { -+ compatible = "st,stm32mp1-exti", "syscon"; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x5000d000 0x400>; -+ -+ /* exti_pwr is an extra interrupt controller used for -+ * EXTI 55 to 60. It's mapped on pwr interrupt -+ * controller. -+ */ -+ exti_pwr: exti-pwr { -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupt-parent = <&pwr>; -+ st,irq-number = <6>; -+ }; -+ }; -+ -+ syscfg: syscon@50020000 { -+ compatible = "st,stm32mp157-syscfg", "syscon"; -+ reg = <0x50020000 0x400>; -+ clocks = <&rcc SYSCFG>; -+ }; -+ -+ cryp1: cryp@54001000 { -+ compatible = "st,stm32mp1-cryp"; -+ reg = <0x54001000 0x400>; -+ interrupts = ; -+ clocks = <&rcc CRYP1>; -+ resets = <&rcc CRYP1_R>; -+ status = "disabled"; -+ }; -+ -+ hash1: hash@54002000 { -+ compatible = "st,stm32f756-hash"; -+ reg = <0x54002000 0x400>; -+ interrupts = ; -+ clocks = <&rcc HASH1>; -+ resets = <&rcc HASH1_R>; -+ status = "disabled"; -+ }; -+ -+ rng1: rng@54003000 { -+ compatible = "st,stm32-rng"; -+ reg = <0x54003000 0x400>; -+ clocks = <&rcc RNG1_K>; -+ resets = <&rcc RNG1_R>; -+ status = "disabled"; -+ }; -+ -+ fmc: nand-controller@58002000 { -+ compatible = "st,stm32mp15-fmc2"; -+ reg = <0x58002000 0x1000>, -+ <0x80000000 0x1000>, -+ <0x88010000 0x1000>, -+ <0x88020000 0x1000>, -+ <0x81000000 0x1000>, -+ <0x89010000 0x1000>, -+ <0x89020000 0x1000>; -+ clocks = <&rcc FMC_K>; -+ resets = <&rcc FMC_R>; -+ status = "disabled"; -+ }; -+ -+ qspi: qspi@58003000 { -+ compatible = "st,stm32f469-qspi"; -+ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; -+ reg-names = "qspi", "qspi_mm"; -+ clocks = <&rcc QSPI_K>; -+ resets = <&rcc QSPI_R>; -+ status = "disabled"; -+ }; -+ -+ sdmmc1: sdmmc@58005000 { -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; -+ reg = <0x58005000 0x1000>, <0x58006000 0x1000>; -+ clocks = <&rcc SDMMC1_K>; -+ clock-names = "apb_pclk"; -+ resets = <&rcc SDMMC1_R>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ max-frequency = <120000000>; -+ status = "disabled"; -+ }; -+ -+ sdmmc2: sdmmc@58007000 { -+ compatible = "arm,pl18x", "arm,primecell"; -+ arm,primecell-periphid = <0x00253180>; -+ reg = <0x58007000 0x1000>, <0x58008000 0x1000>; -+ clocks = <&rcc SDMMC2_K>; -+ clock-names = "apb_pclk"; -+ resets = <&rcc SDMMC2_R>; -+ cap-sd-highspeed; -+ cap-mmc-highspeed; -+ max-frequency = <120000000>; -+ status = "disabled"; -+ }; -+ -+ iwdg2: watchdog@5a002000 { -+ compatible = "st,stm32mp1-iwdg"; -+ reg = <0x5a002000 0x400>; -+ clocks = <&rcc IWDG2>, <&rcc CK_LSI>; -+ clock-names = "pclk", "lsi"; -+ status = "disabled"; -+ }; -+ -+ usart1: serial@5c000000 { -+ compatible = "st,stm32h7-uart"; -+ reg = <0x5c000000 0x400>; -+ interrupt-names = "event", "wakeup"; -+ interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 26 1>; -+ clocks = <&rcc USART1_K>; -+ resets = <&rcc USART1_R>; -+ status = "disabled"; -+ }; -+ -+ spi6: spi@5c001000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stm32h7-spi"; -+ reg = <0x5c001000 0x400>; -+ interrupts = ; -+ clocks = <&rcc SPI6_K>; -+ resets = <&rcc SPI6_R>; -+ status = "disabled"; -+ }; -+ -+ i2c4: i2c@5c002000 { -+ compatible = "st,stm32f7-i2c"; -+ reg = <0x5c002000 0x400>; -+ interrupt-names = "event", "error", "wakeup"; -+ interrupts-extended = <&intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 24 1>; -+ clocks = <&rcc I2C4_K>; -+ resets = <&rcc I2C4_R>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ rtc: rtc@5c004000 { -+ compatible = "st,stm32mp1-rtc"; -+ reg = <0x5c004000 0x400>; -+ clocks = <&rcc RTCAPB>, <&rcc RTC>; -+ clock-names = "pclk", "rtc_ck"; -+ interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 19 1>; -+ status = "disabled"; -+ }; -+ -+ bsec: nvmem@5c005000 { -+ compatible = "st,stm32mp15-bsec"; -+ reg = <0x5c005000 0x400>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ts_cal1: calib@5c { -+ reg = <0x5c 0x2>; -+ }; -+ ts_cal2: calib@5e { -+ reg = <0x5e 0x2>; -+ }; -+ }; -+ -+ i2c6: i2c@5c009000 { -+ compatible = "st,stm32f7-i2c"; -+ reg = <0x5c009000 0x400>; -+ interrupt-names = "event", "error", "wakeup"; -+ interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, -+ <&exti 54 1>; -+ clocks = <&rcc I2C6_K>; -+ resets = <&rcc I2C6_R>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ tamp: tamp@5c00a000 { -+ compatible = "simple-bus", "syscon", "simple-mfd"; -+ reg = <0x5c00a000 0x400>; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157caa-pinctrl.dtsi b/core/arch/arm/fdts/stm32mp157caa-pinctrl.dtsi -new file mode 100644 -index 0000000..9b9cd08 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157caa-pinctrl.dtsi -@@ -0,0 +1,90 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 80 16>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 96 16>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 112 16>; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 128 16>; -+ }; -+ -+ gpioj: gpio@5000b000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 144 16>; -+ }; -+ -+ gpiok: gpio@5000c000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl 0 160 8>; -+ }; -+ }; -+ -+ pinctrl_z: pin-controller-z@54004000 { -+ st,package = ; -+ -+ gpioz: gpio@54004000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl_z 0 400 8>; -+ }; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157cab-pinctrl.dtsi b/core/arch/arm/fdts/stm32mp157cab-pinctrl.dtsi -new file mode 100644 -index 0000000..c570cf9 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157cab-pinctrl.dtsi -@@ -0,0 +1,62 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <6>; -+ gpio-ranges = <&pinctrl 6 86 6>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <10>; -+ gpio-ranges = <&pinctrl 6 102 10>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <2>; -+ gpio-ranges = <&pinctrl 0 112 2>; -+ }; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157cac-pinctrl.dtsi b/core/arch/arm/fdts/stm32mp157cac-pinctrl.dtsi -new file mode 100644 -index 0000000..777f991 ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157cac-pinctrl.dtsi -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 80 16>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 96 16>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 112 16>; -+ }; -+ -+ gpioi: gpio@5000a000 { -+ status = "okay"; -+ ngpios = <12>; -+ gpio-ranges = <&pinctrl 0 128 12>; -+ }; -+ }; -+ -+ pinctrl_z: pin-controller-z@54004000 { -+ st,package = ; -+ -+ gpioz: gpio@54004000 { -+ status = "okay"; -+ ngpios = <8>; -+ gpio-ranges = <&pinctrl_z 0 400 8>; -+ }; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/fdts/stm32mp157cad-pinctrl.dtsi b/core/arch/arm/fdts/stm32mp157cad-pinctrl.dtsi -new file mode 100644 -index 0000000..c4c303a ---- /dev/null -+++ b/core/arch/arm/fdts/stm32mp157cad-pinctrl.dtsi -@@ -0,0 +1,62 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * Author: Alexandre Torgue -+ */ -+ -+#include "stm32mp157-pinctrl.dtsi" -+/ { -+ soc { -+ pinctrl: pin-controller@50002000 { -+ st,package = ; -+ -+ gpioa: gpio@50002000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 0 16>; -+ }; -+ -+ gpiob: gpio@50003000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 16 16>; -+ }; -+ -+ gpioc: gpio@50004000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 32 16>; -+ }; -+ -+ gpiod: gpio@50005000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 48 16>; -+ }; -+ -+ gpioe: gpio@50006000 { -+ status = "okay"; -+ ngpios = <16>; -+ gpio-ranges = <&pinctrl 0 64 16>; -+ }; -+ -+ gpiof: gpio@50007000 { -+ status = "okay"; -+ ngpios = <6>; -+ gpio-ranges = <&pinctrl 6 86 6>; -+ }; -+ -+ gpiog: gpio@50008000 { -+ status = "okay"; -+ ngpios = <10>; -+ gpio-ranges = <&pinctrl 6 102 10>; -+ }; -+ -+ gpioh: gpio@50009000 { -+ status = "okay"; -+ ngpios = <2>; -+ gpio-ranges = <&pinctrl 0 112 2>; -+ }; -+ }; -+ }; -+}; -diff --git a/core/arch/arm/include/arm32.h b/core/arch/arm/include/arm32.h -index e7c3b2d..0dbd889 100644 ---- a/core/arch/arm/include/arm32.h -+++ b/core/arch/arm/include/arm32.h -@@ -1,12 +1,13 @@ - /* SPDX-License-Identifier: BSD-2-Clause */ - /* -- * Copyright (c) 2016, Linaro Limited -+ * Copyright (c) 2016-2018, Linaro Limited - * Copyright (c) 2014, STMicroelectronics International N.V. - */ - - #ifndef ARM32_H - #define ARM32_H - -+#include - #include - #include - #include -@@ -159,6 +160,17 @@ - #define IDPFR1_GENTIMER_SHIFT 16 - #define IDPFR1_GENTIMER_MASK (0xF << IDPFR1_GENTIMER_SHIFT) - -+/* Generic timer registers and fields */ -+#define CNTCR_OFFSET 0x000 -+#define CNTSR_OFFSET 0x004 -+#define CNTCVL_OFFSET 0x008 -+#define CNTCVU_OFFSET 0x00C -+#define CNTFID_OFFSET 0x020 -+ -+#define CNTCR_EN BIT(0) -+#define CNTCR_HDBG BIT(1) -+#define CNTCR_FCREQ(x) ((x) << 8) -+ - #ifndef ASM - #include - #ifdef CFG_ARM_GICV3 -diff --git a/core/arch/arm/include/kernel/delay.h b/core/arch/arm/include/kernel/delay.h -index 72ac873..2c47f0a 100644 ---- a/core/arch/arm/include/kernel/delay.h -+++ b/core/arch/arm/include/kernel/delay.h -@@ -1,5 +1,6 @@ - /* SPDX-License-Identifier: BSD-2-Clause */ - /* -+ * Copyright (c) 2018, Linaro Limited - * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. - * All rights reserved. - * -@@ -29,7 +30,14 @@ - #ifndef __KERNEL_DELAY_H - #define __KERNEL_DELAY_H - -+#include -+#include -+ - void udelay(uint32_t us); - void mdelay(uint32_t ms); - -+uint64_t utimeout_init(uint32_t us); -+bool utimeout_elapsed(uint32_t us, uint64_t ref); -+unsigned int utimeout_elapsed_us(uint32_t us, uint64_t reference); -+ - #endif -diff --git a/core/arch/arm/include/mm/core_mmu.h b/core/arch/arm/include/mm/core_mmu.h -index 64994d3..cec3a42 100644 ---- a/core/arch/arm/include/mm/core_mmu.h -+++ b/core/arch/arm/include/mm/core_mmu.h -@@ -101,6 +101,7 @@ - * MEM_AREA_NSEC_SHM: NonSecure shared RAM between NSec and TEE. - * MEM_AREA_RAM_NSEC: NonSecure RAM storing data - * MEM_AREA_RAM_SEC: Secure RAM storing some secrets -+ * MEM_AREA_ROM_SEC: Secure read only memory storing some secrets - * MEM_AREA_IO_NSEC: NonSecure HW mapped registers - * MEM_AREA_IO_SEC: Secure HW mapped registers - * MEM_AREA_RES_VASPACE: Reserved virtual memory space -@@ -121,6 +122,7 @@ enum teecore_memtypes { - MEM_AREA_NSEC_SHM, - MEM_AREA_RAM_NSEC, - MEM_AREA_RAM_SEC, -+ MEM_AREA_ROM_SEC, - MEM_AREA_IO_NSEC, - MEM_AREA_IO_SEC, - MEM_AREA_RES_VASPACE, -@@ -146,6 +148,7 @@ static inline const char *teecore_memtype_name(enum teecore_memtypes type) - [MEM_AREA_NSEC_SHM] = "NSEC_SHM", - [MEM_AREA_RAM_NSEC] = "RAM_NSEC", - [MEM_AREA_RAM_SEC] = "RAM_SEC", -+ [MEM_AREA_ROM_SEC] = "ROM_SEC", - [MEM_AREA_IO_NSEC] = "IO_NSEC", - [MEM_AREA_IO_SEC] = "IO_SEC", - [MEM_AREA_RES_VASPACE] = "RES_VASPACE", -diff --git a/core/arch/arm/include/sm/pm.h b/core/arch/arm/include/sm/pm.h -index 939f966..90f031a 100644 ---- a/core/arch/arm/include/sm/pm.h -+++ b/core/arch/arm/include/sm/pm.h -@@ -34,7 +34,11 @@ - struct sm_pm_ctx { - uint32_t sp; - paddr_t cpu_resume_addr; -+#ifdef CFG_WITH_LPAE -+ uint32_t suspend_regs[18]; -+#else - uint32_t suspend_regs[16]; -+#endif - }; - - /* suspend/resume core functions */ -diff --git a/core/arch/arm/kernel/delay.c b/core/arch/arm/kernel/delay.c -index 2321b78..ae62187 100644 ---- a/core/arch/arm/kernel/delay.c -+++ b/core/arch/arm/kernel/delay.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: BSD-2-Clause - /* -+ * Copyright (c) 2018, Linaro Limited - * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. - * All rights reserved. - * -@@ -29,12 +30,15 @@ - #include - #include - -+#define US2CNT(m) (((uint64_t)m * (uint64_t)read_cntfrq()) / 1000000ULL) -+#define CNT2US(m) ((uint32_t)(((uint64_t)m * 1000000ULL) / read_cntfrq())) -+ - void udelay(uint32_t us) - { - uint64_t start, target; - - start = read_cntpct(); -- target = ((uint64_t)read_cntfrq() * us) / 1000000ULL; -+ target = US2CNT(us); - - while (read_cntpct() - start <= target) - ; -@@ -44,3 +48,37 @@ void mdelay(uint32_t ms) - { - udelay(1000 * ms); - } -+ -+uint64_t utimeout_init(uint32_t us) -+{ -+ return read_cntpct() + US2CNT(us); -+} -+ -+bool utimeout_elapsed(uint32_t us, uint64_t reference) -+{ -+ uint64_t origin = reference - US2CNT(us); -+ uint64_t now = read_cntpct(); -+ -+ if (origin < reference) -+ return now < origin || now > reference; -+ -+ return now < origin && now > reference; -+} -+ -+unsigned int utimeout_elapsed_us(uint32_t us, uint64_t reference) -+{ -+ uint64_t origin = reference - US2CNT(us); -+ uint64_t now = read_cntpct(); -+ -+ if (origin < reference) { -+ if (now < origin || now > reference) -+ return CNT2US(now - reference); -+ -+ return 0; -+ } -+ -+ if (now < origin && now > reference) -+ return CNT2US(now - reference); -+ -+ return 0; -+} -diff --git a/core/arch/arm/kernel/generic_boot.c b/core/arch/arm/kernel/generic_boot.c -index e5f0f3d..612eab4 100644 ---- a/core/arch/arm/kernel/generic_boot.c -+++ b/core/arch/arm/kernel/generic_boot.c -@@ -73,6 +73,9 @@ uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE]; - KEEP_PAGER(sem_cpu_sync); - #endif - -+#ifdef CFG_STATIC_SECURE_DT -+extern uint8_t static_secure_dtb[]; -+#endif - #ifdef CFG_DT - static void *dt_blob_addr; - #endif -@@ -471,7 +474,7 @@ static void init_runtime(unsigned long pageable_part __unused) - } - #endif - --#ifdef CFG_DT -+#if defined(CFG_DT) && !defined(CFG_STATIC_SECURE_DT) - void *get_dt_blob(void) - { - assert(cpu_mmu_enabled()); -@@ -836,23 +839,42 @@ static void update_fdt(void) - panic(); - } - } -+#endif /*CFG_DT && !CFG_STATIC_SECURE_DT*/ - --#else --static void init_fdt(unsigned long phys_fdt __unused) -+#if defined(CFG_DT) && defined(CFG_STATIC_SECURE_DT) -+void *get_dt_blob(void) - { -+ assert(cpu_mmu_enabled()); -+ -+ if (!dt_blob_addr) { -+ if (fdt_check_header((void *)&static_secure_dtb[0])) -+ panic("Invalid static DTB"); -+ -+ dt_blob_addr = (void *)&static_secure_dtb[0]; -+ } -+ -+ return dt_blob_addr; - } -+#endif - --static void update_fdt(void) -+#ifndef CFG_DT -+void *get_dt_blob(void) - { -+ return NULL; - } -+#endif - -+#if !defined(CFG_DT) || defined(CFG_STATIC_SECURE_DT) - static void reset_dt_references(void) - { - } - --void *get_dt_blob(void) -+static void init_fdt(unsigned long phys_fdt __unused) -+{ -+} -+ -+static void update_fdt(void) - { -- return NULL; - } - - static struct core_mmu_phys_mem *get_memory(void *fdt __unused, -@@ -861,7 +883,7 @@ static struct core_mmu_phys_mem *get_memory(void *fdt __unused, - return NULL; - } - --#endif /*!CFG_DT*/ -+#endif /*!CFG_DT || CFG_STATIC_SECURE_DT*/ - - static void discover_nsec_memory(void) - { -diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c -index f69069e..3337ca6 100644 ---- a/core/arch/arm/mm/core_mmu.c -+++ b/core/arch/arm/mm/core_mmu.c -@@ -627,6 +627,8 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t) - return attr | TEE_MATTR_PRW | cached; - case MEM_AREA_RAM_SEC: - return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; -+ case MEM_AREA_ROM_SEC: -+ return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; - case MEM_AREA_RES_VASPACE: - case MEM_AREA_SHM_VASPACE: - return 0; -@@ -1014,6 +1016,7 @@ void core_init_mmu_map(void) - case MEM_AREA_IO_SEC: - case MEM_AREA_IO_NSEC: - case MEM_AREA_RAM_SEC: -+ case MEM_AREA_ROM_SEC: - case MEM_AREA_RAM_NSEC: - case MEM_AREA_RES_VASPACE: - case MEM_AREA_SHM_VASPACE: -diff --git a/core/arch/arm/mm/mobj.c b/core/arch/arm/mm/mobj.c -index b2bdf6b..789a88d 100644 ---- a/core/arch/arm/mm/mobj.c -+++ b/core/arch/arm/mm/mobj.c -@@ -52,6 +52,7 @@ static void *mobj_phys_get_va(struct mobj *mobj, size_t offset) - - return (void *)(moph->va + offset); - } -+KEEP_PAGER(mobj_phys_get_va); - - static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs, - size_t granule, paddr_t *pa) -@@ -230,7 +231,7 @@ static void *mobj_mm_get_va(struct mobj *mobj, size_t offs) - return mobj_get_va(to_mobj_mm(mobj)->parent_mobj, - mobj_mm_offs(mobj, offs)); - } -- -+KEEP_PAGER(mobj_mm_get_va); - - static TEE_Result mobj_mm_get_pa(struct mobj *mobj, size_t offs, - size_t granule, paddr_t *pa) -diff --git a/core/arch/arm/plat-stm32mp1/boot_api.h b/core/arch/arm/plat-stm32mp1/boot_api.h -index 62e38b5..a7daffd 100644 ---- a/core/arch/arm/plat-stm32mp1/boot_api.h -+++ b/core/arch/arm/plat-stm32mp1/boot_api.h -@@ -14,7 +14,9 @@ - #define BCKR_CORE1_MAGIC_NUMBER 4 - - /* Value for BCKR_CORE1_MAGIC_NUMBER entry */ -+#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xca7face0 - #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xca7face1 -+#define BOOT_API_A7_RESET_MAGIC_NUMBER 0xca7dead0 - - /* Backup register #5: physical address of core1 entry at boot up */ - #define BCKR_CORE1_BRANCH_ADDRESS 5 -diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk -index fb0ca5a..0940ce3 100644 ---- a/core/arch/arm/plat-stm32mp1/conf.mk -+++ b/core/arch/arm/plat-stm32mp1/conf.mk -@@ -1,9 +1,16 @@ - PLATFORM_FLAVOR ?= stm32mp157c -+STM32_BOARD ?= ev1 - -+# 1GB and 512MB DDR target do not locate secure DDR at the same place. -+# -+flavorlist-1G = stm32mp157c-ev1 stm32mp157c-ed1 -+flavorlist-512M = stm32mp157a-dk1 stm32mp157c-dk2 -+ -+# Generic stm32mp1 configuration directives -+# - include core/arch/arm/cpu/cortex-a7.mk - ta-targets = ta_arm32 - --$(call force,CFG_TEE_CORE_NB_CORE,2) - $(call force,CFG_ARM32_core,y) - $(call force,CFG_BOOT_SECONDARY_REQUEST,y) - $(call force,CFG_GENERIC_BOOT,y) -@@ -11,23 +18,85 @@ $(call force,CFG_GIC,y) - $(call force,CFG_INIT_CNTVOFF,y) - $(call force,CFG_PM_STUBS,y) - $(call force,CFG_PSCI_ARM32,y) -+$(call force,CFG_PM_ARM32,y) - $(call force,CFG_SECONDARY_INIT_CNTFRQ,y) - $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) - $(call force,CFG_WITH_SOFTWARE_PRNG,y) -+$(call force,CFG_SM_PLATFORM_HANDLER,y) -+ -+ifneq ($(CFG_SECURE_DT),) -+$(call force,CFG_DT,y) -+$(call force,CFG_STATIC_SECURE_DT,y) -+endif -+ -+CFG_TEE_CORE_NB_CORE ?= 2 -+ -+ifneq (,$(filter $(CFG_SECURE_DT),$(flavorlist-512M))) -+CFG_TZDRAM_START ?= 0xde000000 -+CFG_SHMEM_START ?= 0xdfe00000 -+endif - - CFG_TZSRAM_START ?= 0x2ffc0000 - CFG_TZSRAM_SIZE ?= 0x00040000 - CFG_TZDRAM_START ?= 0xfe000000 - CFG_TZDRAM_SIZE ?= 0x01e00000 --CFG_SHMEM_SIZE ?= 0x00200000 - CFG_SHMEM_START ?= 0xffe00000 -+CFG_SHMEM_SIZE ?= 0x00200000 - --CFG_WITH_PAGER ?= y --CFG_WITH_LPAE ?= y --CFG_WITH_STACK_CANARIES ?= y -+CFG_CORE_HEAP_SIZE ?= 49152 -+CFG_WITH_PAGER ?= y -+CFG_WITH_LPAE ?= y -+CFG_WITH_STACK_CANARIES ?= y -+CFG_MMAP_REGIONS ?= 23 - -+ifneq ($(CFG_DT),y) -+# Some drivers mandate DT support -+$(call force,CFG_STPMIC1,n) -+$(call force,CFG_STM32_I2C,n) -+$(call force,CFG_STM32_IWDG,n) -+$(call force,CFG_STM32_RNG,n) -+$(call force,CFG_STM32_TIMER,n) -+$(call force,CFG_STM32_CLOCKSRC_CALIB,n) -+endif -+ -+$(call force,CFG_STM32_BSEC,y) -+$(call force,CFG_STM32_CRYP,y) -+$(call force,CFG_STM32_ETZPC,y) -+CFG_STM32_GPIO ?= y -+CFG_STM32_I2C ?= y -+CFG_STM32_IWDG ?= y - CFG_STM32_UART ?= y -+CFG_STM32_RNG ?= y -+$(call force,CFG_STM32_RTC,y) -+CFG_STM32_TIMER ?= y -+ -+CFG_STPMIC1 ?= y -+ -+$(call force,CFG_STM32_BSEC_SIP,y) -+$(call force,CFG_STM32_RCC_SIP,y) -+CFG_STM32_PWR_SIP ?= y -+CFG_STM32_POWER_SERVICES ?= y -+CFG_STM32_CLOCKSRC_CALIB ?= y -+ -+ifeq ($(CFG_STPMIC1),y) -+$(call force,CFG_STM32_I2C,y) -+$(call force,CFG_STM32_GPIO,y) -+endif -+ -+ifeq ($(CFG_STM32_CLOCKSRC_CALIB),y) -+$(call force,CFG_STM32_TIMER,y) -+endif -+ -+# Get a static mapping for the non secure low DDR (save 4kB of unpaged memory) -+CFG_STM32MP_MAP_NSEC_LOW_DDR ?= y - --# Default enable the test facitilites -+# Default enable some test facitilites - CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y - CFG_WITH_STATS ?= y -+CFG_UNWIND ?= n -+# Non secure UART and GPIO/pinctrl for the output console -+CFG_WITH_NSEC_GPIOS ?= y -+CFG_WITH_NSEC_UARTS ?= y -+CFG_FORCE_CONSOLE_ON_SUSPEND ?= n -+# UART instance used for early console (0 disables early console) -+CFG_STM32_EARLY_CONSOLE_UART ?= 4 -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32_reset.c b/core/arch/arm/plat-stm32mp1/drivers/stm32_reset.c -new file mode 100644 -index 0000000..b406167 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32_reset.c -@@ -0,0 +1,60 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define RST_CLR_OFFSET 4U -+#define RESET_TIMEOUT_US 1000 -+ -+static size_t id2reg_offset(unsigned int reset_id) -+{ -+ return ((reset_id & GENMASK_32(31, 5)) >> 5) * sizeof(uint32_t); -+} -+ -+static uint8_t id2reg_bit_pos(unsigned int reset_id) -+{ -+ return (uint8_t)(reset_id & GENMASK_32(4,0)); -+} -+ -+void stm32_reset_assert(unsigned int reset_id) -+{ -+ size_t offset = id2reg_offset(reset_id); -+ uint32_t bitmsk = BIT(id2reg_bit_pos(reset_id)); -+ uint64_t timeout_ref; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ write32(bitmsk, rcc_base + offset); -+ -+ timeout_ref = utimeout_init(RESET_TIMEOUT_US); -+ -+ while (!(read32(rcc_base + offset) & bitmsk)) { -+ if (utimeout_elapsed(RESET_TIMEOUT_US, timeout_ref)) { -+ panic("Reset timeout"); -+ } -+ } -+} -+ -+void stm32_reset_deassert(unsigned int reset_id) -+{ -+ size_t offset = id2reg_offset(reset_id) + RST_CLR_OFFSET; -+ uint32_t bitmsk = BIT(id2reg_bit_pos(reset_id)); -+ uint64_t timeout_ref; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ write32(bitmsk, rcc_base + offset); -+ -+ timeout_ref = utimeout_init(RESET_TIMEOUT_US); -+ -+ while (read32(rcc_base + offset) & bitmsk) { -+ if (utimeout_elapsed(RESET_TIMEOUT_US, timeout_ref)) { -+ panic("Reset timeout"); -+ } -+ } -+} -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32_reset.h b/core/arch/arm/plat-stm32mp1/drivers/stm32_reset.h -new file mode 100644 -index 0000000..577ba9b ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32_reset.h -@@ -0,0 +1,15 @@ -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef __STM32_RESET_H__ -+#define __STM32_RESET_H__ -+ -+#include -+ -+void stm32_reset_assert(uint32_t reset_id); -+void stm32_reset_deassert(uint32_t reset_id); -+ -+#endif /* __STM32MP1_RESET_H__ */ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c -new file mode 100644 -index 0000000..583bf94 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c -@@ -0,0 +1,457 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CAL_MAX_RETRY 20U -+ -+/* List of forbiden values for HSI and CSI */ -+static uint16_t fbv_hsi[] = { -+ 512, 480, 448, 416, 384, 352, 320, 288, -+ 256, 224, 192, 160, 128, 96, 64, 32, 0, -+}; -+static uint16_t fbv_csi[] = { -+ 256, 240, 224, 208, 192, 176, 160, 144, -+ 128, 112, 96, 80, 64, 48, 32, 16, 0, -+}; -+ -+struct stm32mp1_trim_boundary_t { -+ unsigned int x1; /* Max boundary trim value around forbidden value */ -+ unsigned int x2; /* Min boundary trim value around forbidden value */ -+}; -+ -+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]; -+}; -+ -+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 *hsi_calib; -+static struct stm32mp1_clk_cal *csi_calib; -+ -+static const struct stm32mp1_clk_cal hsi_calib_config = { -+ .fbv = fbv_hsi, -+ .trim_max = 63, -+ .trim_min = -64, -+ .ref_freq = 0, -+ .freq_margin = 1, -+ .set_trim = hsi_set_trim, -+ .get_trim = hsi_get_trimed_cal, -+}; -+ -+static const struct stm32mp1_clk_cal csi_calib_config = { -+ .fbv = fbv_csi, -+ .trim_max = 15, -+ .trim_min = -16, -+ .ref_freq = 0, -+ .freq_margin = 2, -+ .set_trim = csi_set_trim, -+ .get_trim = csi_get_trimed_cal, -+}; -+ -+static void hsi_set_trim(unsigned int cal) -+{ -+ int clk_trim = (int)cal - (int)hsi_calib->cal_ref; -+ uint32_t trim = ((uint32_t)clk_trim << RCC_HSICFGR_HSITRIM_SHIFT) & -+ RCC_HSICFGR_HSITRIM_MASK; -+ -+ mmio_clrsetbits_32(stm32_rcc_base() + RCC_HSICFGR, -+ RCC_HSICFGR_HSITRIM_MASK, trim); -+} -+KEEP_PAGER(hsi_set_trim); -+ -+static unsigned int hsi_get_trimed_cal(void) -+{ -+ uint32_t utrim = (mmio_read_32(stm32_rcc_base() + RCC_HSICFGR) & -+ RCC_HSICFGR_HSITRIM_MASK) >> -+ RCC_HSICFGR_HSITRIM_SHIFT; -+ int trim = (int)utrim - hsi_calib->trim_max; -+ -+ if (trim + (int)hsi_calib->cal_ref < 0) -+ return 0; -+ -+ return hsi_calib->cal_ref + trim; -+} -+KEEP_PAGER(hsi_get_trimed_cal); -+ -+static void csi_set_trim(unsigned int cal) -+{ -+ int clk_trim = (int)cal - (int)csi_calib->cal_ref + -+ csi_calib->trim_max + 1; -+ uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) & -+ RCC_CSICFGR_CSITRIM_MASK; -+ -+ mmio_clrsetbits_32(stm32_rcc_base() + RCC_CSICFGR, -+ RCC_CSICFGR_CSITRIM_MASK, trim); -+} -+KEEP_PAGER(csi_set_trim); -+ -+static unsigned int csi_get_trimed_cal(void) -+{ -+ uint32_t trim = (mmio_read_32(stm32_rcc_base() + RCC_CSICFGR) & -+ RCC_CSICFGR_CSITRIM_MASK) >> -+ RCC_CSICFGR_CSITRIM_SHIFT; -+ -+ return (int)trim - csi_calib->trim_max + (int)csi_calib->cal_ref - 1; -+} -+KEEP_PAGER(csi_get_trimed_cal); -+ -+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 margin = (clk_cal->ref_freq * clk_cal->freq_margin) / 100; -+ unsigned long min = clk_cal->ref_freq - margin; -+ unsigned long max = clk_cal->ref_freq + margin; -+ unsigned long freq = clk_cal->get_freq(); -+ int cal = clk_cal->get_trim(); -+ unsigned int nb_retries; -+ -+ for (nb_retries = 0; nb_retries < CAL_MAX_RETRY; nb_retries++) { -+ if ((freq >= min) && (freq <= max)) { -+ break; -+ } -+ -+ if (freq < min) { -+ cal = trim_increase(clk_cal, cal); -+ } else { -+ cal = trim_decrease(clk_cal, cal); -+ } -+ -+ clk_cal->set_trim(cal); -+ -+ freq = clk_cal->get_freq(); -+ } -+ -+ if ((freq < min) || (freq > max)) { -+ DMSG("Calibration failed"); -+ panic("Calibration"); -+ } -+} -+ -+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; -+} -+ -+/* Timer countdown/delay argument for the target calibration periodicity */ -+static uint32_t timer_val; -+ -+#define CNTP_CTL_ENABLE BIT(0) -+#define CNTP_CTL_IMASK BIT(1) -+#define CNTP_CTL_ISTATUS BIT(2) -+ -+static void arm_timer(void) -+{ -+ if (!timer_val) -+ return; -+ -+ write_cntp_ctl(read_cntp_ctl() & ~(CNTP_CTL_ENABLE | CNTP_CTL_IMASK)); -+ write_cntp_tval(timer_val); -+ write_cntp_ctl(read_cntp_ctl() | CNTP_CTL_ENABLE); -+} -+ -+static void arm_timer_with_period(uint32_t period_sec) -+{ -+ timer_val = period_sec * read_cntfrq(); -+ -+ arm_timer(); -+} -+ -+static void calib_period(void) -+{ -+ (void)stm32mp_start_clock_calib(CK_HSI); -+ (void)stm32mp_start_clock_calib(CK_CSI); -+ -+ arm_timer(); -+} -+ -+static enum itr_return arm_cntp_it_handler(struct itr_handler *handler __unused) -+{ -+ if (timer_val) -+ calib_period(); -+ -+ return ITRR_HANDLED; -+} -+static struct itr_handler arm_cntp_handler = { -+ .it = GIC_SPI_SEC_PHY_TIMER, -+ .handler = arm_cntp_it_handler, -+}; -+KEEP_PAGER(arm_cntp_handler); -+ -+static void timer_pm(enum pm_op op, void *handle __unused) -+{ -+ if (op != PM_OP_RESUME || !timer_val) -+ return; -+ -+ calib_period(); -+} -+KEEP_PAGER(timer_pm); -+ -+static TEE_Result init_arm_cntp_timer(void) -+{ -+ itr_add(&arm_cntp_handler); -+ itr_enable(arm_cntp_handler.it); -+ -+ stm32mp_register_pm_cb(timer_pm, NULL); -+ -+ return TEE_SUCCESS; -+} -+driver_init(init_arm_cntp_timer); -+ -+static void init_periodic_calibration(void *fdt, int node) -+{ -+ uint32_t period = fdt_read_uint32_default(fdt, node, "st,cal-sec", 0); -+ -+ DMSG("Calib period %us", period); -+ arm_timer_with_period(period); -+} -+ -+int stm32mp_start_clock_calib(unsigned int clock_id) -+{ -+ struct stm32mp1_clk_cal *clk_calib; -+ -+ switch (clock_id) { -+ case CK_HSI: -+ clk_calib = hsi_calib; -+ break; -+ case CK_CSI: -+ clk_calib = csi_calib; -+ break; -+ default: -+ DMSG("Cannot calibrate clock %u", clock_id); -+ return 1; -+ } -+ -+ if (clk_calib->ref_freq == 0U) -+ return 1; -+ -+ DMSG("%s", clock_id == CK_HSI ? "HSI" : "CSI"); -+ rcc_calibration(clk_calib); -+ -+ return 0; -+} -+ -+static void init_hsi_calibration(void *fdt, int node) -+{ -+ if (!fdt_getprop(fdt, node, "st,hsi-cal", NULL)) -+ return; -+ -+ hsi_calib = calloc(1, sizeof(*hsi_calib)); -+ assert(hsi_calib); -+ memcpy(hsi_calib, &hsi_calib_config, sizeof(*hsi_calib)); -+ -+ stm32_timer_freq_func(&hsi_calib->get_freq, HSI_CAL); -+ assert(hsi_calib->get_freq); -+ -+ hsi_calib->ref_freq = stm32mp1_clk_get_rate(CK_HSI); -+ -+ hsi_calib->cal_ref = (mmio_read_32(stm32_rcc_base() + RCC_HSICFGR) & -+ RCC_HSICFGR_HSICAL_MASK) >> -+ RCC_HSICFGR_HSICAL_SHIFT; -+ -+ trim_table_init(hsi_calib); -+ -+ hsi_calib->set_trim(hsi_calib->cal_ref); -+ -+ stm32mp_start_clock_calib(CK_HSI); -+} -+ -+static void init_csi_calibration(void *fdt, int node) -+{ -+ if (!fdt_getprop(fdt, node, "st,csi-cal", NULL)) -+ return; -+ -+ csi_calib = calloc(1, sizeof(*csi_calib)); -+ assert(csi_calib); -+ memcpy(csi_calib, &csi_calib_config, sizeof(*csi_calib)); -+ -+ stm32_timer_freq_func(&csi_calib->get_freq, CSI_CAL); -+ assert(csi_calib->get_freq); -+ -+ csi_calib->ref_freq = stm32mp1_clk_get_rate(CK_CSI); -+ -+ csi_calib->cal_ref = (mmio_read_32(stm32_rcc_base() + RCC_CSICFGR) & -+ RCC_CSICFGR_CSICAL_MASK) >> -+ RCC_CSICFGR_CSICAL_SHIFT; -+ -+ trim_table_init(csi_calib); -+ -+ csi_calib->set_trim(csi_calib->cal_ref); -+ -+ stm32mp_start_clock_calib(CK_CSI); -+} -+ -+static TEE_Result init_stm32mp1_calib(void) -+{ -+ void *fdt; -+ int rcc_node = -1; -+ -+ fdt = get_dt_blob(); -+ if (fdt) -+ rcc_node = fdt_get_rcc_node(fdt); -+ if (rcc_node < 0) -+ panic(); -+ -+ init_hsi_calibration(fdt, rcc_node); -+ init_csi_calibration(fdt, rcc_node); -+ init_periodic_calibration(fdt, rcc_node); -+ -+ return TEE_SUCCESS; -+} -+driver_init(init_stm32mp1_calib); -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -new file mode 100644 -index 0000000..acf5d60 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -@@ -0,0 +1,1527 @@ -+// SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause -+/* -+ * Copyright (C) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CFG_DT -+#include -+#include -+#endif -+ -+enum stm32mp1_parent_id { -+/* Oscillators are defined in enum stm32mp_osc_id */ -+ -+/* Other parent source */ -+ _HSI_KER = NB_OSC, -+ _HSE_KER, -+ _HSE_KER_DIV2, -+ _CSI_KER, -+ _PLL1_P, -+ _PLL1_Q, -+ _PLL1_R, -+ _PLL2_P, -+ _PLL2_Q, -+ _PLL2_R, -+ _PLL3_P, -+ _PLL3_Q, -+ _PLL3_R, -+ _PLL4_P, -+ _PLL4_Q, -+ _PLL4_R, -+ _ACLK, -+ _PCLK1, -+ _PCLK2, -+ _PCLK3, -+ _PCLK4, -+ _PCLK5, -+ _HCLK6, -+ _HCLK2, -+ _CK_PER, -+ _CK_MPU, -+ _CK_MCU, -+ _PARENT_NB, -+ _UNKNOWN_ID = 0xff, -+}; -+ -+/* Lists only the parent clock we are interested in */ -+enum stm32mp1_parent_sel { -+ _STGEN_SEL, -+ _I2C46_SEL, -+ _SPI6_SEL, -+ _USART1_SEL, -+ _RNG1_SEL, -+ _UART6_SEL, -+ _UART24_SEL, -+ _UART35_SEL, -+ _UART78_SEL, -+ _ASS_SEL, -+ _MSS_SEL, -+ _USBPHY_SEL, -+ _USBO_SEL, -+ _PARENT_SEL_NB, -+ _UNKNOWN_SEL = 0xff, -+}; -+ -+enum stm32mp1_pll_id { -+ _PLL1, -+ _PLL2, -+ _PLL3, -+ _PLL4, -+ _PLL_NB -+}; -+ -+enum stm32mp1_div_id { -+ _DIV_P, -+ _DIV_Q, -+ _DIV_R, -+ _DIV_NB, -+}; -+ -+enum stm32mp1_clksrc_id { -+ CLKSRC_MPU, -+ CLKSRC_AXI, -+ CLKSRC_MCU, -+ CLKSRC_PLL12, -+ CLKSRC_PLL3, -+ CLKSRC_PLL4, -+ CLKSRC_RTC, -+ CLKSRC_MCO1, -+ CLKSRC_MCO2, -+ CLKSRC_NB -+}; -+ -+enum stm32mp1_clkdiv_id { -+ CLKDIV_MPU, -+ CLKDIV_AXI, -+ CLKDIV_MCU, -+ CLKDIV_APB1, -+ CLKDIV_APB2, -+ CLKDIV_APB3, -+ CLKDIV_APB4, -+ CLKDIV_APB5, -+ CLKDIV_RTC, -+ CLKDIV_MCO1, -+ CLKDIV_MCO2, -+ CLKDIV_NB -+}; -+ -+enum stm32mp1_pllcfg { -+ PLLCFG_M, -+ PLLCFG_N, -+ PLLCFG_P, -+ PLLCFG_Q, -+ PLLCFG_R, -+ PLLCFG_O, -+ PLLCFG_NB -+}; -+ -+enum stm32mp1_pllcsg { -+ PLLCSG_MOD_PER, -+ PLLCSG_INC_STEP, -+ PLLCSG_SSCG_MODE, -+ PLLCSG_NB -+}; -+ -+enum stm32mp1_plltype { -+ PLL_800, -+ PLL_1600, -+ PLL_TYPE_NB -+}; -+ -+struct stm32mp1_pll { -+ uint8_t refclk_min; -+ uint8_t refclk_max; -+ uint8_t divn_max; -+}; -+ -+struct stm32mp1_clk_gate { -+ uint16_t offset; -+ uint8_t bit; -+ uint8_t index; -+ uint8_t set_clr; -+ uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ -+ uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ -+}; -+ -+struct stm32mp1_clk_sel { -+ uint16_t offset; -+ uint8_t src; -+ uint8_t msk; -+ uint8_t nb_parent; -+ const uint8_t *parent; -+}; -+ -+#define REFCLK_SIZE 4 -+struct stm32mp1_clk_pll { -+ enum stm32mp1_plltype plltype; -+ uint16_t rckxselr; -+ uint16_t pllxcfgr1; -+ uint16_t pllxcfgr2; -+ uint16_t pllxfracr; -+ uint16_t pllxcr; -+ uint16_t pllxcsgr; -+ enum stm32mp_osc_id refclk[REFCLK_SIZE]; -+}; -+ -+/* Clocks with selectable source and not set/clr register access */ -+#define _CLK_SELEC(off, b, idx, s) \ -+ { \ -+ .offset = (off), \ -+ .bit = (b), \ -+ .index = (idx), \ -+ .set_clr = 0, \ -+ .sel = (s), \ -+ .fixed = _UNKNOWN_ID, \ -+ } -+ -+/* Clocks with fixed source and not set/clr register access */ -+#define _CLK_FIXED(off, b, idx, f) \ -+ { \ -+ .offset = (off), \ -+ .bit = (b), \ -+ .index = (idx), \ -+ .set_clr = 0, \ -+ .sel = _UNKNOWN_SEL, \ -+ .fixed = (f), \ -+ } -+ -+/* Clocks with selectable source and set/clr register access */ -+#define _CLK_SC_SELEC(off, b, idx, s) \ -+ { \ -+ .offset = (off), \ -+ .bit = (b), \ -+ .index = (idx), \ -+ .set_clr = 1, \ -+ .sel = (s), \ -+ .fixed = _UNKNOWN_ID, \ -+ } -+ -+/* Clocks with fixed source and set/clr register access */ -+#define _CLK_SC_FIXED(off, b, idx, f) \ -+ { \ -+ .offset = (off), \ -+ .bit = (b), \ -+ .index = (idx), \ -+ .set_clr = 1, \ -+ .sel = _UNKNOWN_SEL, \ -+ .fixed = (f), \ -+ } -+ -+/* -+ * Clocks with selectable source and set/clr register access -+ * and enable bit position defined by a label (argument b) -+ */ -+#define _CLK_SC2_SELEC(off, b, idx, s) \ -+ { \ -+ .offset = (off), \ -+ .index = (idx), \ -+ .bit = off ## _ ## b ## _POS, \ -+ .set_clr = 1, \ -+ .sel = (s), \ -+ .fixed = _UNKNOWN_ID, \ -+ } -+#define _CLK_SC2_FIXED(off, b, idx, f) \ -+ { \ -+ .offset = (off), \ -+ .index = (idx), \ -+ .bit = off ## _ ## b ## _POS, \ -+ .set_clr = 1, \ -+ .sel = _UNKNOWN_SEL, \ -+ .fixed = (f), \ -+ } -+ -+#define _CLK_PARENT(idx, off, s, m, p) \ -+ [(idx)] = { \ -+ .offset = (off), \ -+ .src = (s), \ -+ .msk = (m), \ -+ .parent = (p), \ -+ .nb_parent = ARRAY_SIZE(p) \ -+ } -+ -+#define _CLK_PLL(idx, type, off1, off2, off3, \ -+ off4, off5, off6, \ -+ p1, p2, p3, p4) \ -+ [(idx)] = { \ -+ .plltype = (type), \ -+ .rckxselr = (off1), \ -+ .pllxcfgr1 = (off2), \ -+ .pllxcfgr2 = (off3), \ -+ .pllxfracr = (off4), \ -+ .pllxcr = (off5), \ -+ .pllxcsgr = (off6), \ -+ .refclk[0] = (p1), \ -+ .refclk[1] = (p2), \ -+ .refclk[2] = (p3), \ -+ .refclk[3] = (p4), \ -+ } -+ -+static const uint8_t stm32mp1_clks[][2] = { -+ { CK_PER, _CK_PER }, -+ { CK_MPU, _CK_MPU }, -+ { CK_AXI, _ACLK }, -+ { CK_MCU, _CK_MCU }, -+ { CK_HSE, _HSE }, -+ { CK_CSI, _CSI }, -+ { CK_LSI, _LSI }, -+ { CK_LSE, _LSE }, -+ { CK_HSI, _HSI }, -+ { CK_HSE_DIV2, _HSE_KER_DIV2 }, -+}; -+ -+#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) -+ -+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_SC2_SELEC(RCC_MP_APB5ENSETR, SPI6EN, SPI6_K, _SPI6_SEL), -+ _CLK_SC2_SELEC(RCC_MP_APB5ENSETR, I2C4EN, I2C4_K, _I2C46_SEL), -+ _CLK_SC2_SELEC(RCC_MP_APB5ENSETR, I2C6EN, I2C6_K, _I2C46_SEL), -+ _CLK_SC2_SELEC(RCC_MP_APB5ENSETR, USART1EN, USART1_K, _USART1_SEL), -+ _CLK_SC2_FIXED(RCC_MP_APB5ENSETR, RTCAPBEN, RTCAPB, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_APB5ENSETR, TZC1EN, TZC1, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_APB5ENSETR, TZC2EN, TZC2, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_APB5ENSETR, TZPCEN, TZPC, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_APB5ENSETR, IWDG1APBEN, IWDG1, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_APB5ENSETR, BSECEN, BSEC, _PCLK5), -+ _CLK_SC2_SELEC(RCC_MP_APB5ENSETR, STGENEN, STGEN_K, _STGEN_SEL), -+ -+ _CLK_SC2_FIXED(RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _PCLK5), -+ _CLK_SC2_FIXED(RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _PCLK5), -+ _CLK_SC2_SELEC(RCC_MP_AHB5ENSETR, RNG1EN, RNG1_K, _RNG1_SEL), -+ _CLK_SC2_FIXED(RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _PCLK5), -+ -+ /* Non-secure clocks */ -+#ifdef CFG_WITH_NSEC_GPIOS -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_ID), -+ _CLK_SC_FIXED(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_ID), -+#endif -+#ifdef CFG_WITH_NSEC_UARTS -+ _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_APB2ENSETR, 13, USART6_K, _UART6_SEL), -+#endif -+ _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_AHB2ENSETR, 8, USBO_K, _USBO_SEL), -+ _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), -+ _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), -+ _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), -+}; -+KEEP_PAGER(stm32mp1_clk_gate); -+ -+/* Parents for secure aware clocks in the xxxSELR value ordering */ -+static const uint8_t stgen_parents[] = { -+ _HSI_KER, _HSE_KER -+}; -+ -+static const uint8_t i2c46_parents[] = { -+ _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER -+}; -+ -+static const uint8_t spi6_parents[] = { -+ _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q -+}; -+ -+static const uint8_t usart1_parents[] = { -+ _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER -+}; -+ -+static const uint8_t rng1_parents[] = { -+ _CSI, _PLL4_R, _LSE, _LSI -+}; -+ -+/* Parents for (some) non-secure clocks */ -+static const uint8_t uart6_parents[] = { -+ _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER -+}; -+ -+static const uint8_t uart234578_parents[] = { -+ _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER -+}; -+ -+static const uint8_t ass_parents[] = { -+ _HSI, _HSE, _PLL2 -+}; -+ -+static const uint8_t mss_parents[] = { -+ _HSI, _HSE, _CSI, _PLL3 -+}; -+ -+static const uint8_t usbphy_parents[] = { -+ _HSE_KER, _PLL4_R, _HSE_KER_DIV2 -+}; -+ -+static const uint8_t usbo_parents[] = { -+ _PLL4_R, _USB_PHY_48 -+}; -+ -+static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { -+ /* Secure aware clocks */ -+ _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), -+ _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), -+ _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), -+ _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), -+ _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), -+ /* Always non-secure clocks (maybe used in some way in secure world) */ -+ _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), -+ _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), -+ _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), -+ _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), -+ _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents), -+ _CLK_PARENT(_MSS_SEL, RCC_MSSCKSELR, 0, 0x3, mss_parents), -+ _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), -+ _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), -+}; -+ -+/* PLLNCFGR2 register divider by output */ -+static const uint8_t pllncfgr2[_DIV_NB] = { -+ [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, -+ [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, -+ [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, -+}; -+ -+static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { -+ _CLK_PLL(_PLL1, PLL_1600, -+ RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, -+ RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, -+ _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), -+ _CLK_PLL(_PLL2, PLL_1600, -+ RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, -+ RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, -+ _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), -+ _CLK_PLL(_PLL3, PLL_800, -+ RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, -+ RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, -+ _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), -+ _CLK_PLL(_PLL4, PLL_800, -+ RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, -+ RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, -+ _HSI, _HSE, _CSI, _I2S_CKIN), -+}; -+ -+/* Prescaler table lookups for clock computation */ -+/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ -+static const uint8_t stm32mp1_mcu_div[16] = { -+ 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 -+}; -+ -+/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ -+#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div -+#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div -+static const uint8_t stm32mp1_mpu_apbx_div[8] = { -+ 0, 1, 2, 3, 4, 4, 4, 4 -+}; -+ -+/* div = /1 /2 /3 /4 */ -+static const uint8_t stm32mp1_axi_div[8] = { -+ 1, 2, 3, 4, 4, 4, 4, 4 -+}; -+ -+#if TRACE_LEVEL >= TRACE_DEBUG -+static const char *const __maybe_unused stm32mp1_clk_parent_name[_PARENT_NB] = { -+ [_HSI] = "HSI", -+ [_HSE] = "HSE", -+ [_CSI] = "CSI", -+ [_LSI] = "LSI", -+ [_LSE] = "LSE", -+ [_I2S_CKIN] = "I2S_CKIN", -+ [_HSI_KER] = "HSI_KER", -+ [_HSE_KER] = "HSE_KER", -+ [_HSE_KER_DIV2] = "HSE_KER_DIV2", -+ [_CSI_KER] = "CSI_KER", -+ [_PLL1_P] = "PLL1_P", -+ [_PLL1_Q] = "PLL1_Q", -+ [_PLL1_R] = "PLL1_R", -+ [_PLL2_P] = "PLL2_P", -+ [_PLL2_Q] = "PLL2_Q", -+ [_PLL2_R] = "PLL2_R", -+ [_PLL3_P] = "PLL3_P", -+ [_PLL3_Q] = "PLL3_Q", -+ [_PLL3_R] = "PLL3_R", -+ [_PLL4_P] = "PLL4_P", -+ [_PLL4_Q] = "PLL4_Q", -+ [_PLL4_R] = "PLL4_R", -+ [_ACLK] = "ACLK", -+ [_PCLK1] = "PCLK1", -+ [_PCLK2] = "PCLK2", -+ [_PCLK3] = "PCLK3", -+ [_PCLK4] = "PCLK4", -+ [_PCLK5] = "PCLK5", -+ [_HCLK6] = "KCLK6", -+ [_HCLK2] = "HCLK2", -+ [_CK_PER] = "CK_PER", -+ [_CK_MPU] = "CK_MPU", -+ [_CK_MCU] = "CK_MCU", -+ [_USB_PHY_48] = "USB_PHY_48", -+}; -+#endif -+ -+/* RCC clock device driver private */ -+static unsigned long stm32mp1_osc[NB_OSC]; -+static unsigned int gate_refcounts[NB_GATES]; -+static unsigned int refcount_lock; -+ -+static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) -+{ -+ return &stm32mp1_clk_gate[idx]; -+} -+ -+static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) -+{ -+ return &stm32mp1_clk_sel[idx]; -+} -+ -+static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) -+{ -+ return &stm32mp1_clk_pll[idx]; -+} -+ -+static unsigned int get_id_from_rcc_bit(unsigned int offset, unsigned int bit) -+{ -+ unsigned int idx; -+ -+ for (idx = 0; idx < NB_GATES; idx++) { -+ const struct stm32mp1_clk_gate *gate = gate_ref(idx); -+ -+ if ((offset == gate->offset) && (bit == gate->bit)) { -+ return gate->index; -+ } -+ -+ if ((gate->set_clr != 0U) && -+ (offset == (gate->offset + RCC_MP_ENCLRR_OFFSET)) && -+ (bit == gate->bit)) { -+ return gate->index; -+ } -+ } -+ -+ /* Currently only supported gated clocks */ -+ return ~0U; -+} -+ -+static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) -+{ -+ if (idx >= NB_OSC) { -+ DMSG("clk id %d not found", idx); -+ return 0; -+ } -+ -+ return stm32mp1_osc[idx]; -+} -+ -+static int stm32mp1_clk_get_gated_id(unsigned long id) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < NB_GATES; i++) { -+ if (gate_ref(i)->index == id) { -+ return i; -+ } -+ } -+ -+ DMSG("clk id %lu not found", id); -+ return -1; -+} -+ -+static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) -+{ -+ return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); -+} -+ -+static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) -+{ -+ return (enum stm32mp1_parent_id)gate_ref(i)->fixed; -+} -+ -+static int stm32mp1_clk_get_parent(unsigned long id) -+{ -+ const struct stm32mp1_clk_sel *sel; -+ unsigned int j; -+ uint32_t p_sel; -+ int i; -+ enum stm32mp1_parent_id p; -+ enum stm32mp1_parent_sel s; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) { -+ if (stm32mp1_clks[j][0] == id) { -+ return (int)stm32mp1_clks[j][1]; -+ } -+ } -+ -+ i = stm32mp1_clk_get_gated_id(id); -+ if (i < 0) { -+ panic(); -+ } -+ -+ p = stm32mp1_clk_get_fixed_parent(i); -+ if (p < _PARENT_NB) { -+ return (int)p; -+ } -+ -+ s = stm32mp1_clk_get_sel(i); -+ if (s == _UNKNOWN_SEL) { -+ return -1; -+ } -+ if (s >= _PARENT_SEL_NB) { -+ panic(); -+ } -+ -+ sel = clk_sel_ref(s); -+ p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk; -+ if (p_sel < sel->nb_parent) { -+ return (int)sel->parent[p_sel]; -+ } -+ -+ DMSG("No parent selected for clk %lu", id); -+ return -1; -+} -+ -+static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) -+{ -+ uint32_t selr = mmio_read_32(stm32_rcc_base() + pll->rckxselr); -+ uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; -+ -+ return stm32mp1_clk_get_fixed(pll->refclk[src]); -+} -+ -+/* -+ * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL -+ * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) -+ * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) -+ * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) -+ */ -+static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) -+{ -+ unsigned long refclk, fvco; -+ uint32_t cfgr1, fracr, divm, divn; -+ -+ cfgr1 = mmio_read_32(stm32_rcc_base() + pll->pllxcfgr1); -+ fracr = mmio_read_32(stm32_rcc_base() + pll->pllxfracr); -+ -+ divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; -+ divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; -+ -+ refclk = stm32mp1_pll_get_fref(pll); -+ -+ /* -+ * 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) { -+ unsigned long long numerator; -+ unsigned long long denominator; -+ uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> -+ RCC_PLLNFRACR_FRACV_SHIFT; -+ -+ numerator = (((unsigned long long)divn + 1U) << 13) + fracv; -+ numerator = refclk * numerator; -+ denominator = ((unsigned long long)divm + 1U) << 13; -+ fvco = (unsigned long)(numerator / denominator); -+ } else { -+ fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); -+ } -+ -+ return fvco; -+} -+ -+static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, -+ enum stm32mp1_div_id div_id) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ unsigned long dfout; -+ uint32_t cfgr2, divy; -+ -+ if (div_id >= _DIV_NB) { -+ return 0; -+ } -+ -+ cfgr2 = mmio_read_32(stm32_rcc_base() + pll->pllxcfgr2); -+ divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; -+ -+ dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); -+ -+ return dfout; -+} -+ -+static unsigned long get_clock_rate(int p) -+{ -+ uint32_t reg, clkdiv; -+ unsigned long clock = 0; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ switch (p) { -+ case _CK_MPU: -+ /* MPU sub system */ -+ reg = mmio_read_32(rcc_base + RCC_MPCKSELR); -+ switch (reg & RCC_SELR_SRC_MASK) { -+ case RCC_MPCKSELR_HSI: -+ clock = stm32mp1_clk_get_fixed(_HSI); -+ break; -+ case RCC_MPCKSELR_HSE: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ break; -+ case RCC_MPCKSELR_PLL: -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); -+ break; -+ case RCC_MPCKSELR_PLL_MPUDIV: -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); -+ -+ reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); -+ clkdiv = reg & RCC_MPUDIV_MASK; -+ if (clkdiv != 0U) { -+ clock /= stm32mp1_mpu_div[clkdiv]; -+ } -+ break; -+ default: -+ break; -+ } -+ break; -+ /* AXI sub system */ -+ case _ACLK: -+ case _HCLK2: -+ case _HCLK6: -+ case _PCLK4: -+ case _PCLK5: -+ reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); -+ switch (reg & RCC_SELR_SRC_MASK) { -+ case RCC_ASSCKSELR_HSI: -+ clock = stm32mp1_clk_get_fixed(_HSI); -+ break; -+ case RCC_ASSCKSELR_HSE: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ break; -+ case RCC_ASSCKSELR_PLL: -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); -+ break; -+ default: -+ break; -+ } -+ -+ /* System clock divider */ -+ reg = mmio_read_32(rcc_base + RCC_AXIDIVR); -+ clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; -+ -+ switch (p) { -+ case _PCLK4: -+ reg = mmio_read_32(rcc_base + RCC_APB4DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ case _PCLK5: -+ reg = mmio_read_32(rcc_base + RCC_APB5DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ default: -+ break; -+ } -+ break; -+ /* MCU sub system */ -+ case _CK_MCU: -+ case _PCLK1: -+ case _PCLK2: -+ case _PCLK3: -+ reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); -+ switch (reg & RCC_SELR_SRC_MASK) { -+ case RCC_MSSCKSELR_HSI: -+ clock = stm32mp1_clk_get_fixed(_HSI); -+ break; -+ case RCC_MSSCKSELR_HSE: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ break; -+ case RCC_MSSCKSELR_CSI: -+ clock = stm32mp1_clk_get_fixed(_CSI); -+ break; -+ case RCC_MSSCKSELR_PLL: -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); -+ break; -+ default: -+ break; -+ } -+ -+ /* MCU clock divider */ -+ reg = mmio_read_32(rcc_base + RCC_MCUDIVR); -+ clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; -+ -+ switch (p) { -+ case _PCLK1: -+ reg = mmio_read_32(rcc_base + RCC_APB1DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ case _PCLK2: -+ reg = mmio_read_32(rcc_base + RCC_APB2DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ case _PCLK3: -+ reg = mmio_read_32(rcc_base + RCC_APB3DIVR); -+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; -+ break; -+ case _CK_MCU: -+ default: -+ break; -+ } -+ break; -+ case _CK_PER: -+ reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); -+ switch (reg & RCC_SELR_SRC_MASK) { -+ case RCC_CPERCKSELR_HSI: -+ clock = stm32mp1_clk_get_fixed(_HSI); -+ break; -+ case RCC_CPERCKSELR_HSE: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ break; -+ case RCC_CPERCKSELR_CSI: -+ clock = stm32mp1_clk_get_fixed(_CSI); -+ break; -+ default: -+ break; -+ } -+ break; -+ case _HSI: -+ case _HSI_KER: -+ clock = stm32mp1_clk_get_fixed(_HSI); -+ break; -+ case _CSI: -+ case _CSI_KER: -+ clock = stm32mp1_clk_get_fixed(_CSI); -+ break; -+ case _HSE: -+ case _HSE_KER: -+ clock = stm32mp1_clk_get_fixed(_HSE); -+ break; -+ case _HSE_KER_DIV2: -+ clock = stm32mp1_clk_get_fixed(_HSE) >> 1; -+ break; -+ case _LSI: -+ clock = stm32mp1_clk_get_fixed(_LSI); -+ break; -+ case _LSE: -+ clock = stm32mp1_clk_get_fixed(_LSE); -+ break; -+ /* PLL */ -+ case _PLL1_P: -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); -+ break; -+ case _PLL1_Q: -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); -+ break; -+ case _PLL1_R: -+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); -+ break; -+ case _PLL2_P: -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); -+ break; -+ case _PLL2_Q: -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); -+ break; -+ case _PLL2_R: -+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); -+ break; -+ case _PLL3_P: -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); -+ break; -+ case _PLL3_Q: -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); -+ break; -+ case _PLL3_R: -+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); -+ break; -+ case _PLL4_P: -+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); -+ break; -+ case _PLL4_Q: -+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); -+ break; -+ case _PLL4_R: -+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); -+ break; -+ /* Other */ -+ case _USB_PHY_48: -+ clock = stm32mp1_clk_get_fixed(_USB_PHY_48); -+ break; -+ default: -+ break; -+ } -+ -+ return clock; -+} -+ -+static void __clk_enable(struct stm32mp1_clk_gate const *gate) -+{ -+ uintptr_t base = stm32_rcc_base(); -+ uint32_t bit = BIT(gate->bit); -+ -+ if (gate->set_clr != 0U) { -+ mmio_write_32(base + gate->offset, bit); -+ } else { -+ io_mask32_stm32shregs(base + gate->offset, bit, bit); -+ } -+ -+ FMSG("Clock %u has been enabled", gate->index); -+} -+ -+static void __clk_disable(struct stm32mp1_clk_gate const *gate) -+{ -+ uintptr_t base = stm32_rcc_base(); -+ uint32_t bit = BIT(gate->bit); -+ -+ if (gate->set_clr != 0U) { -+ mmio_write_32(base + gate->offset + RCC_MP_ENCLRR_OFFSET, bit); -+ } else { -+ io_mask32_stm32shregs(base + gate->offset, 0, bit); -+ } -+ -+ FMSG("Clock %u has been disabled", gate->index); -+} -+ -+static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) -+{ -+ uintptr_t base = stm32_rcc_base(); -+ -+ return mmio_read_32(base + gate->offset) & BIT(gate->bit); -+} -+ -+bool stm32mp1_clk_is_enabled(unsigned long id) -+{ -+ int i = stm32mp1_clk_get_gated_id(id); -+ -+ if (i < 0) { -+ return false; -+ } -+ -+ return __clk_is_enabled(gate_ref(i)); -+} -+ -+unsigned int stm32mp1_clk_get_refcount(unsigned long id) -+{ -+ int i = stm32mp1_clk_get_gated_id(id); -+ -+ return gate_refcounts[i]; -+} -+ -+void __stm32mp1_clk_enable(unsigned long id, bool secure) -+{ -+ int i = stm32mp1_clk_get_gated_id(id); -+ uint32_t exceptions; -+ -+ if (i < 0) { -+ DMSG("Invalid clock %lu: %d", id, i); -+ panic(); -+ } -+ -+ exceptions = may_spin_lock(&refcount_lock); -+ -+ if (incr_shrefcnt(&gate_refcounts[i], secure) != 0) { -+ __clk_enable(gate_ref(i)); -+ } -+ -+ may_spin_unlock(&refcount_lock, exceptions); -+} -+ -+void __stm32mp1_clk_disable(unsigned long id, bool secure) -+{ -+ int i = stm32mp1_clk_get_gated_id(id); -+ uint32_t exceptions; -+ -+ if (i < 0) { -+ DMSG("Invalid clock %lu: %d", id, i); -+ panic(); -+ } -+ -+ exceptions = may_spin_lock(&refcount_lock); -+ -+ if (decr_shrefcnt(&gate_refcounts[i], secure) != 0) { -+ __clk_disable(gate_ref(i)); -+ } -+ -+ may_spin_unlock(&refcount_lock, exceptions); -+} -+ -+static long get_timer_rate(long parent_rate, unsigned int apb_bus) -+{ -+ uint32_t timgxpre; -+ uint32_t apbxdiv; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ switch (apb_bus) { -+ case 1: -+ apbxdiv = mmio_read_32(rcc_base + RCC_APB1DIVR) & -+ RCC_APBXDIV_MASK; -+ timgxpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & -+ RCC_TIMGXPRER_TIMGXPRE; -+ break; -+ case 2: -+ apbxdiv = mmio_read_32(rcc_base + RCC_APB2DIVR) & -+ RCC_APBXDIV_MASK; -+ timgxpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & -+ RCC_TIMGXPRER_TIMGXPRE; -+ break; -+ default: -+ panic(); -+ break; -+ } -+ -+ if (apbxdiv == 0) { -+ return parent_rate; -+ } -+ -+ return parent_rate * (timgxpre + 1) * 2; -+} -+ -+unsigned long stm32mp1_clk_get_rate(unsigned long id) -+{ -+ int p; -+ unsigned long rate; -+ -+ p = stm32mp1_clk_get_parent(id); -+ if (p < 0) { -+ return 0; -+ } -+ -+ rate = get_clock_rate(p); -+ -+ if ((id >= TIM2_K) && (id <= TIM14_K)) { -+ rate = get_timer_rate(rate, 1); -+ } -+ if ((id >= TIM1_K) && (id <= TIM17_K)) { -+ rate = get_timer_rate(rate, 2); -+ } -+ -+ return rate; -+} -+ -+#ifdef CFG_DT -+static void stm32mp1_osc_clk_init(const char *name, -+ enum stm32mp_osc_id index) -+{ -+ uint32_t frequency; -+ void *fdt; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ stm32mp1_osc[index] = 0; -+ -+ if (fdt_osc_read_freq(fdt, name, &frequency) == 0) { -+ stm32mp1_osc[index] = frequency; -+ } -+} -+ -+static void stm32mp1_osc_init(void) -+{ -+ enum stm32mp_osc_id i; -+ char **name __maybe_unused = (char **)&stm32mp_osc_node_label[0]; -+ -+ for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { -+ stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); -+ DMSG("Osc %s frequency: %lu", name[i], stm32mp1_osc[i]); -+ } -+} -+#else -+static void stm32mp1_osc_init(void) -+{ -+} -+#endif -+ -+/* -+ * Lookup platform clock from enable bit location in RCC registers. -+ * Return a valid clock ID on success, return ~0 on error. -+ */ -+unsigned long stm32mp1_clk_rcc2id(size_t offset, size_t bit) -+{ -+ return get_id_from_rcc_bit(offset, bit); -+} -+ -+/* -+ * Get the parent ID of the target parent clock, for tagging as secure -+ * shared clock dependencies. -+ */ -+static int get_parent_id_parent(unsigned int parent_id) -+{ -+ enum stm32mp1_parent_sel s = _UNKNOWN_SEL; -+ enum stm32mp1_pll_id pll_id; -+ uint32_t p_sel; -+ -+ switch (parent_id) { -+ case _ACLK: -+ case _PCLK4: -+ case _PCLK5: -+ s = _ASS_SEL; -+ break; -+ case _PLL1_P: -+ case _PLL1_Q: -+ case _PLL1_R: -+ pll_id = _PLL1; -+ break; -+ case _PLL2_P: -+ case _PLL2_Q: -+ case _PLL2_R: -+ pll_id = _PLL2; -+ break; -+ case _PLL3_P: -+ case _PLL3_Q: -+ case _PLL3_R: -+ pll_id = _PLL3; -+ break; -+ case _PLL4_P: -+ case _PLL4_Q: -+ case _PLL4_R: -+ pll_id = _PLL4; -+ break; -+ case _PCLK1: -+ case _PCLK2: -+ case _HCLK2: -+ case _HCLK6: -+ case _CK_PER: -+ case _CK_MPU: -+ case _CK_MCU: -+ case _USB_PHY_48: -+ /* We do not expected to access these */ -+ panic(); -+ break; -+ default: -+ /* Other parents have no parent */ -+ return -1; -+ } -+ -+ if (s != _UNKNOWN_SEL) { -+ const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & -+ sel->msk; -+ -+ if (p_sel < sel->nb_parent) { -+ return (int)sel->parent[p_sel]; -+ } -+ } else { -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ -+ p_sel = mmio_read_32(stm32_rcc_base() + pll->rckxselr) & -+ RCC_SELR_REFCLK_SRC_MASK; -+ -+ if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { -+ return (int)pll->refclk[p_sel]; -+ } -+ } -+ -+ FMSG("No parent selected for %s", stm32mp1_clk_parent_name[parent_id]); -+ return -1; -+} -+ -+static void secure_parent_clocks(unsigned long parent_id) -+{ -+ int grandparent_id; -+ -+ switch (parent_id) { -+ /* Secure only the parents for these clocks */ -+ case _ACLK: -+ case _HCLK2: -+ case _HCLK6: -+ case _PCLK4: -+ case _PCLK5: -+ break; -+ /* PLLs */ -+ case _PLL1_P: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL1_P); -+ break; -+ case _PLL1_Q: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL1_Q); -+ break; -+ case _PLL1_R: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL1_R); -+ break; -+ -+ case _PLL2_P: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL2_P); -+ break; -+ case _PLL2_Q: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL2_Q); -+ break; -+ case _PLL2_R: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL2_R); -+ break; -+ -+ case _PLL3_P: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3_P); -+ break; -+ case _PLL3_Q: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3_Q); -+ break; -+ case _PLL3_R: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3_R); -+ break; -+ -+ /* Source clocks */ -+ case _HSI: -+ case _HSI_KER: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_HSI); -+ break; -+ case _LSI: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_LSI); -+ break; -+ case _CSI: -+ case _CSI_KER: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_CSI); -+ break; -+ case _HSE: -+ case _HSE_KER: -+ case _HSE_KER_DIV2: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_HSE); -+ break; -+ case _LSE: -+ stm32mp_register_secure_periph(STM32MP1_SHRES_LSE); -+ break; -+ -+ default: -+ panic(); -+ } -+ -+ grandparent_id = get_parent_id_parent(parent_id); -+ if (grandparent_id >= 0) { -+ secure_parent_clocks(grandparent_id); -+ } -+} -+ -+void stm32mp_register_clock_parents_secure(unsigned long clock_id) -+{ -+ int parent_id; -+ -+ switch (clock_id) { -+ case PLL1: -+ parent_id = get_parent_id_parent(_PLL1_P); -+ break; -+ case PLL2: -+ parent_id = get_parent_id_parent(_PLL2_P); -+ break; -+ case PLL3: -+ parent_id = get_parent_id_parent(_PLL3_P); -+ break; -+ case PLL4: -+ EMSG("PLL4 cannot be secure"); -+ panic(); -+ default: -+ /* Others are expected gateable clock */ -+ parent_id = stm32mp1_clk_get_parent(clock_id); -+ break; -+ } -+ -+ if (parent_id < 0) { -+ DMSG("No parent for clock %lu", clock_id); -+ panic(); -+ } -+ -+ secure_parent_clocks(parent_id); -+} -+ -+#ifdef CFG_DT -+/* -+ * Check that the device tree does not provide clock tree configuration -+ * information. Such configuration would not be applied since the early boot -+ * loader is in charge of configuring the clock tree and enabling the PLLs. -+ */ -+static void init_clock_tree_from_dt(void) -+{ -+ void *fdt; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ int node = -1; -+ unsigned int i; -+ int len; -+ int ignored = 0; -+ -+ fdt = get_dt_blob(); -+ if (fdt != NULL) { -+ node = fdt_get_rcc_node(fdt); -+ } -+ -+ if ((fdt == NULL) || (node < 0)) { -+ panic("RCC DT"); -+ } -+ -+ if ((_fdt_get_status(fdt, node) & DT_STATUS_OK_SEC) == 0) { -+ panic("RCC disabled"); -+ } -+ -+ assert(virt_to_phys((void *)stm32_rcc_base()) == -+ fdt_rcc_read_addr(fdt)); -+ -+ /* Expect booting from a secure setup */ -+ if ((mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) == 0) { -+ panic("RCC TZC[TZEN]"); -+ } -+ -+ /* Get oscillator frequency to handle freq get/set operations */ -+ stm32mp1_osc_init(); -+ -+ node = fdt_get_rcc_node(fdt); -+ assert(node >= 0); -+ -+ /* -+ * OP-TEE core is not in charge of the clock tree configuration. -+ * This is expected from an earlier boot stage. Modifying the clock -+ * tree here may jeopardize the already configured clock tree. -+ * The sequence below ignores such DT directives with a friendly -+ * debug trace. -+ */ -+ if (fdt_getprop(fdt, node, "st,clksrc", &len)) { -+ DMSG("Ignore source clocks configuration from DT"); -+ ignored++; -+ } -+ if (fdt_getprop(fdt, node, "st,clkdiv", &len)) { -+ DMSG("Ignore clock divisors configuration from DT"); -+ ignored++; -+ } -+ if (fdt_getprop(fdt, node, "st,pkcs", &len)) { -+ DMSG("Ignore peripheral clocks tree configuration from DT"); -+ ignored++; -+ } -+ for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { -+ char name[12]; -+ -+ snprintf(name, sizeof(name), "st,pll@%d", i); -+ node = fdt_rcc_subnode_offset(fdt, name); -+ -+ if (node <= 0) { -+ continue; -+ } -+ -+ if (fdt_getprop(fdt, node, "cfg", &len) || -+ fdt_getprop(fdt, node, "frac", &len)) { -+ DMSG("Ignore PLL%u configurations from DT", i); -+ ignored++; -+ } -+ } -+ -+ if (ignored != 0) { -+ IMSG("DT clock tree configurations were ignored"); -+ } -+} -+#else -+static void init_clock_tree_from_dt(void) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ /* Expect booting from a secure setup */ -+ if ((mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) == 0) { -+ panic("RCC TZC[TZEN]"); -+ } -+} -+#endif /*CFG_DT*/ -+ -+/* Sync secure clock refcount after all drivers probe/inits, */ -+void stm32mp_update_earlyboot_clocks_state(void) -+{ -+ unsigned int idx; -+ -+ for (idx = 0; idx < NB_GATES; idx++) { -+ unsigned long clock_id = gate_ref(idx)->index; -+ -+ /* -+ * Drop non-secure refcount set on shareable clocks that are -+ * not shared. Secure clock should not hold a non-secure -+ * refcount. Non-secure clock cannot hold any refcount. -+ */ -+ if (__clk_is_enabled(gate_ref(idx)) && -+ stm32mp_clock_is_shareable(clock_id) && -+ !stm32mp_clock_is_shared(clock_id)) { -+ stm32mp1_clk_disable_non_secure(clock_id); -+ } -+ -+ /* -+ * Disable secure clocks enabled from early boot but not explicitly -+ * enabled from the secure world. -+ */ -+ if (__clk_is_enabled(gate_ref(idx)) && -+ !stm32mp_clock_is_non_secure(clock_id) && -+ !gate_refcounts[idx]) { -+ __clk_disable(gate_ref(idx)); -+ } -+ } -+ -+ /* Dump clocks state */ -+ for (idx = 0; idx < NB_GATES; idx++) { -+ unsigned long __maybe_unused clock_id = gate_ref(idx)->index; -+ int __maybe_unused p = stm32mp1_clk_get_parent(clock_id); -+ -+ FMSG("stm32mp clock %3lu is %sabled (refcnt %d) (parent %d %s)", -+ clock_id, -+ __clk_is_enabled(gate_ref(idx)) ? "en" : "dis", -+ gate_refcounts[idx], -+ p, p < 0 ? "n.a" : stm32mp1_clk_parent_name[p]); -+ } -+} -+ -+/* Set a non-secure refcount on shareable clock that were enabled from boot */ -+static void sync_earlyboot_clocks_state(void) -+{ -+ unsigned int idx; -+ -+ for (idx = 0; idx < NB_GATES; idx++) { -+ assert(!gate_refcounts[idx]); -+ } -+ -+ /* -+ * Set a non-secure refcount for shareable clocks enabled from boot. -+ * It will be dropped after core inits for secure-only clocks. -+ */ -+ for (idx = 0; idx < NB_GATES; idx++) { -+ struct stm32mp1_clk_gate const *gate = gate_ref(idx); -+ -+ if (__clk_is_enabled(gate) && -+ stm32mp_clock_is_shareable(gate->index)) { -+ gate_refcounts[idx] = SHREFCNT_NONSECURE_FLAG; -+ } -+ } -+ -+ /* -+ * Register secure clock parents and init a refcount for -+ * secure only resources that are not registered from a driver probe. -+ * - DDR controller and phy clocks. -+ * - TZC400, ETZPC and STGEN clocks. -+ * - RTCAPB clocks on multi-core -+ */ -+ stm32mp_register_clock_parents_secure(DDRC1); -+ stm32mp1_clk_enable_secure(DDRC1); -+ stm32mp_register_clock_parents_secure(DDRC1LP); -+ stm32mp1_clk_enable_secure(DDRC1LP); -+ stm32mp_register_clock_parents_secure(DDRC2); -+ stm32mp1_clk_enable_secure(DDRC2); -+ stm32mp_register_clock_parents_secure(DDRC2LP); -+ stm32mp1_clk_enable_secure(DDRC2LP); -+ stm32mp_register_clock_parents_secure(DDRPHYC); -+ stm32mp1_clk_enable_secure(DDRPHYC); -+ stm32mp_register_clock_parents_secure(DDRPHYCLP); -+ stm32mp1_clk_enable_secure(DDRPHYCLP); -+ stm32mp_register_clock_parents_secure(DDRCAPB); -+ stm32mp1_clk_enable_secure(DDRCAPB); -+ stm32mp_register_clock_parents_secure(AXIDCG); -+ stm32mp1_clk_enable_secure(AXIDCG); -+ stm32mp_register_clock_parents_secure(DDRPHYCAPB); -+ stm32mp1_clk_enable_secure(DDRPHYCAPB); -+ stm32mp_register_clock_parents_secure(DDRPHYCAPBLP); -+ stm32mp1_clk_enable_secure(DDRPHYCAPBLP); -+ -+ stm32mp_register_clock_parents_secure(TZPC); -+ stm32mp1_clk_enable_secure(TZPC); -+ stm32mp_register_clock_parents_secure(TZC1); -+ stm32mp1_clk_enable_secure(TZC1); -+ stm32mp_register_clock_parents_secure(TZC2); -+ stm32mp1_clk_enable_secure(TZC2); -+ stm32mp_register_clock_parents_secure(STGEN_K); -+ stm32mp1_clk_enable_secure(STGEN_K); -+ -+ stm32mp_register_clock_parents_secure(BSEC); -+ stm32mp1_clk_enable_secure(BSEC); -+ -+ stm32mp_register_clock_parents_secure(BKPSRAM); -+ -+ stm32mp_register_clock_parents_secure(RTCAPB); -+ -+#if CFG_TEE_CORE_NB_CORE > 1 -+ stm32mp1_clk_enable_secure(RTCAPB); -+#endif -+ -+ /* The low power sequences mandates RNG1 and CRYP1 support */ -+ stm32mp_register_clock_parents_secure(RNG1_K); -+ stm32mp_register_clock_parents_secure(CRYP1); -+} -+ -+static void _clock_resume(void) -+{ -+ unsigned int idx; -+ -+ /* Sync secure and shared clocks physical state on functional state */ -+ for (idx = 0; idx < NB_GATES; idx++) { -+ struct stm32mp1_clk_gate const *gate = gate_ref(idx); -+ -+ if (stm32mp_clock_is_non_secure(gate->index)) { -+ continue; -+ } -+ -+ if (gate_refcounts[idx]) { -+ DMSG("Force clock %d enable", gate->index); -+ __clk_enable(gate); -+ } else { -+ DMSG("Force clock %d disable", gate->index); -+ __clk_disable(gate); -+ } -+ } -+} -+ -+void stm32mp_clock_suspend_resume(enum pm_op op) -+{ -+ switch (op) { -+ case PM_OP_SUSPEND: -+ /* Nothing to do */ -+ break; -+ case PM_OP_RESUME: -+ _clock_resume(); -+ break; -+ default: -+ panic(); -+ } -+} -+ -+static TEE_Result stm32mp1_clk_probe(void) -+{ -+ init_clock_tree_from_dt(); -+ -+ sync_earlyboot_clocks_state(); -+ -+ return TEE_SUCCESS; -+} -+/* Setup clock support before driver initialization */ -+service_init(stm32mp1_clk_probe); -+ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h -new file mode 100644 -index 0000000..783d81d ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h -@@ -0,0 +1,62 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32MP1_CLK_H__ -+#define __STM32MP1_CLK_H__ -+ -+#include -+#include -+#include -+ -+enum stm32mp_osc_id { -+ _HSI, -+ _HSE, -+ _CSI, -+ _LSI, -+ _LSE, -+ _I2S_CKIN, -+ _USB_PHY_48, -+ NB_OSC, -+ _UNKNOWN_OSC_ID = 0xFF -+}; -+ -+void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); -+void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); -+bool stm32mp1_clk_is_enabled(unsigned long id); -+ -+static inline void stm32mp1_clk_enable_non_secure(unsigned long id) -+{ -+ __stm32mp1_clk_enable(id, false); -+} -+ -+static inline void stm32mp1_clk_enable_secure(unsigned long id) -+{ -+ __stm32mp1_clk_enable(id, true); -+} -+ -+static inline void stm32mp1_clk_disable_non_secure(unsigned long id) -+{ -+ __stm32mp1_clk_disable(id, false); -+} -+ -+static inline void stm32mp1_clk_disable_secure(unsigned long id) -+{ -+ __stm32mp1_clk_disable(id, true); -+} -+ -+unsigned int stm32mp1_clk_get_refcount(unsigned long id); -+ -+unsigned long stm32mp1_clk_get_rate(unsigned long id); -+ -+unsigned long stm32mp1_clk_rcc2id(size_t offset, size_t bit); -+ -+void stm32mp_register_clock_parents_secure(unsigned long id); -+ -+void stm32mp_update_earlyboot_clocks_state(void); -+ -+void stm32mp1_clock_suspend(void); -+void stm32mp1_clock_resume(void); -+ -+#endif /* __STM32MP1_CLK_H__ */ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c -new file mode 100644 -index 0000000..c83d561 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c -@@ -0,0 +1,340 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DT_RCC_NODE_NAME "rcc@50000000" -+#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" -+#define DT_RCC_COMPAT "syscon" -+#define DT_STGEN_COMPAT "st,stm32-stgen" -+#define DT_UART_COMPAT "st,stm32h7-uart" -+ -+const char *stm32mp_osc_node_label[NB_OSC] = { -+ [_LSI] = "clk-lsi", -+ [_LSE] = "clk-lse", -+ [_HSI] = "clk-hsi", -+ [_HSE] = "clk-hse", -+ [_CSI] = "clk-csi", -+ [_I2S_CKIN] = "i2s_ckin", -+ [_USB_PHY_48] = "ck_usbo_48m" -+}; -+ -+/******************************************************************************* -+ * This function reads the frequency of an oscillator from its name. -+ * It reads the value indicated inside the device tree. -+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure. -+ * On success, value is stored in the second parameter. -+ ******************************************************************************/ -+int fdt_osc_read_freq(void *fdt, const char *name, uint32_t *freq) -+{ -+ int node, subnode; -+ -+ node = fdt_path_offset(fdt, "/clocks"); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ const char *cchar; -+ int ret; -+ -+ cchar = fdt_get_name(fdt, subnode, &ret); -+ if (cchar == NULL) { -+ return ret; -+ } -+ -+ if (strncmp(cchar, name, (size_t)ret) == 0) { -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, subnode, "clock-frequency", -+ &ret); -+ if (cuint == NULL) { -+ return ret; -+ } -+ -+ *freq = fdt32_to_cpu(*cuint); -+ -+ return 0; -+ } -+ } -+ -+ /* Oscillator not found, freq=0 */ -+ *freq = 0; -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function checks the presence of an oscillator property from its id. -+ * The search is done inside the device tree. -+ * Returns true/false regarding search result. -+ ******************************************************************************/ -+bool fdt_osc_read_bool(void *fdt, enum stm32mp_osc_id osc_id, -+ const char *prop_name) -+{ -+ int node, subnode; -+ -+ if (osc_id >= NB_OSC) { -+ return false; -+ } -+ -+ node = fdt_path_offset(fdt, "/clocks"); -+ if (node < 0) { -+ return false; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ const char *cchar; -+ int ret; -+ -+ cchar = fdt_get_name(fdt, subnode, &ret); -+ if (cchar == NULL) { -+ return false; -+ } -+ -+ if (strncmp(cchar, stm32mp_osc_node_label[osc_id], -+ (size_t)ret) != 0) { -+ continue; -+ } -+ -+ if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+/******************************************************************************* -+ * This function reads a value of a oscillator property from its id. -+ * Returns value on success, and a default value if property not found. -+ * Default value is passed as parameter. -+ ******************************************************************************/ -+uint32_t fdt_osc_read_uint32_default(void *fdt, enum stm32mp_osc_id osc_id, -+ const char *prop_name, uint32_t dflt_value) -+{ -+ int node, subnode; -+ -+ if (osc_id >= NB_OSC) { -+ return dflt_value; -+ } -+ -+ node = fdt_path_offset(fdt, "/clocks"); -+ if (node < 0) { -+ return dflt_value; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ const char *cchar; -+ int ret; -+ -+ cchar = fdt_get_name(fdt, subnode, &ret); -+ if (cchar == NULL) { -+ return dflt_value; -+ } -+ -+ if (strncmp(cchar, stm32mp_osc_node_label[osc_id], -+ (size_t)ret) != 0) { -+ continue; -+ } -+ -+ return fdt_read_uint32_default(fdt, subnode, prop_name, -+ dflt_value); -+ } -+ -+ return dflt_value; -+} -+ -+/******************************************************************************* -+ * This function reads the rcc base address. -+ * It reads the value indicated inside the device tree. -+ * Returns address on success, and 0 on failure. -+ ******************************************************************************/ -+uint32_t fdt_rcc_read_addr(void *fdt) -+{ -+ int node, subnode; -+ -+ node = fdt_path_offset(fdt, "/soc"); -+ if (node < 0) { -+ return 0; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ const char *cchar; -+ int ret; -+ -+ cchar = fdt_get_name(fdt, subnode, &ret); -+ if (cchar == NULL) { -+ return 0; -+ } -+ -+ if (strncmp(cchar, DT_RCC_NODE_NAME, (size_t)ret) == 0) { -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, subnode, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+ } -+ } -+ -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function returns the RCC node in the device tree. -+ ******************************************************************************/ -+int fdt_get_rcc_node(void *fdt) -+{ -+ return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -+} -+ -+/******************************************************************************* -+ * This function reads a series of parameters in rcc-clk section. -+ * It reads the values indicated inside the device tree, from property name. -+ * The number of parameters is also indicated as entry parameter. -+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure. -+ * On success, values are stored at the second parameter address. -+ ******************************************************************************/ -+int fdt_rcc_read_uint32_array(void *fdt, const char *prop_name, -+ uint32_t *array, uint32_t count) -+{ -+ int node = fdt_get_rcc_node(fdt); -+ -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return fdt_read_uint32_array(fdt, node, prop_name, array, count); -+} -+ -+/******************************************************************************* -+ * This function gets the subnode offset in rcc-clk section from its name. -+ * It reads the values indicated inside the device tree. -+ * Returns offset on success, and a negative FDT/ERRNO error code on failure. -+ ******************************************************************************/ -+int fdt_rcc_subnode_offset(void *fdt, const char *name) -+{ -+ int node, subnode; -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ subnode = fdt_subnode_offset(fdt, node, name); -+ if (subnode <= 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return subnode; -+} -+ -+/******************************************************************************* -+ * This function gets the pointer to a rcc-clk property from its name. -+ * It reads the values indicated inside the device tree. -+ * Length of the property is stored in the second parameter. -+ * Returns pointer on success, and NULL value on failure. -+ ******************************************************************************/ -+const fdt32_t *fdt_rcc_read_prop(void *fdt, const char *prop_name, int *lenp) -+{ -+ const fdt32_t *cuint; -+ int node, len; -+ -+ node = fdt_get_rcc_node(fdt); -+ if (node < 0) { -+ return NULL; -+ } -+ -+ cuint = fdt_getprop(fdt, node, prop_name, &len); -+ if (cuint == NULL) { -+ return NULL; -+ } -+ -+ *lenp = len; -+ return cuint; -+} -+ -+/******************************************************************************* -+ * This function reads the stgen base address. -+ * It reads the value indicated inside the device tree. -+ * Returns address on success, and NULL value on failure. -+ ******************************************************************************/ -+uintptr_t get_stgen_base(void) -+{ -+ int node; -+ const fdt32_t *cuint; -+ void *fdt; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ return 0; -+ } -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); -+ if (node < 0) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function gets the frequency of the specified uart instance. -+ * From this instance, all the uarts nodes in DT are parsed, and the register -+ * base is compared to the instance. If match between these two values, then -+ * the clock source is read from the DT and we deduce the frequency. -+ * Returns clock frequency on success, 0 value on failure. -+ ******************************************************************************/ -+unsigned long get_uart_clock_freq(uint32_t instance) -+{ -+ int node; -+ void *fdt; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ return 0; -+ } -+ -+ /* Check for UART nodes */ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_UART_COMPAT); -+ while (node != -FDT_ERR_NOTFOUND) { -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) -+ goto next; -+ -+ if ((uint32_t)fdt32_to_cpu(*cuint) == instance) { -+ unsigned long clk_id; -+ -+ cuint = fdt_getprop(fdt, node, "clocks", NULL); -+ if (cuint == NULL) -+ goto next; -+ -+ cuint++; -+ clk_id = (unsigned long)(fdt32_to_cpu(*cuint)); -+ -+ return stm32mp1_clk_get_rate(clk_id); -+ } -+next: -+ node = fdt_node_offset_by_compatible(fdt, node, DT_UART_COMPAT); -+ } -+ -+ return 0; -+} -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.h -new file mode 100644 -index 0000000..cbb489b ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.h -@@ -0,0 +1,33 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32MP1_CLKFUNC_H__ -+#define __STM32MP1_CLKFUNC_H__ -+ -+#include -+#include -+ -+extern const char *stm32mp_osc_node_label[NB_OSC]; -+ -+int fdt_osc_read_freq(void *fdt, const char *name, uint32_t *freq); -+bool fdt_osc_read_bool(void *fdt, enum stm32mp_osc_id osc_id, -+ const char *prop_name); -+uint32_t fdt_osc_read_uint32_default(void *fdt, enum stm32mp_osc_id osc_id, -+ const char *prop_name, -+ uint32_t dflt_value); -+ -+int fdt_get_rcc_node(void *fdt); -+uint32_t fdt_rcc_read_addr(void *fdt); -+int fdt_rcc_read_uint32_array(void *fdt, const char *prop_name, -+ uint32_t *array, uint32_t count); -+int fdt_rcc_subnode_offset(void *fdt, const char *name); -+const fdt32_t *fdt_rcc_read_prop(void *fdt, const char *prop_name, int *lenp); -+bool fdt_get_rcc_secure_status(void *fdt); -+ -+uintptr_t get_stgen_base(void); -+ -+unsigned long get_uart_clock_freq(uint32_t instance); -+ -+#endif /* __STM32MP1_CLKFUNC_H__ */ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c -new file mode 100644 -index 0000000..03ded28 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c -@@ -0,0 +1,513 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TIMEOUT_500US (500 * 1000) -+ -+static uintptr_t get_ddrctrl_base(void) -+{ -+ static void *va; -+ -+ if (!cpu_mmu_enabled()) { -+ return DDRCTRL_BASE; -+ } -+ -+ if (!va) { -+ va = phys_to_virt(DDRCTRL_BASE, MEM_AREA_IO_SEC); -+ } -+ -+ return (uintptr_t)va; -+} -+ -+static uintptr_t get_ddrphy_base(void) -+{ -+ static void *va; -+ -+ if (!cpu_mmu_enabled()) { -+ return DDRPHYC_BASE; -+ } -+ -+ if (!va) { -+ va = phys_to_virt(DDRPHYC_BASE, MEM_AREA_IO_SEC); -+ } -+ -+ return (uintptr_t)va; -+} -+ -+static void ddr_disable_clock(void) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ /* Disable all clocks */ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, -+ RCC_DDRITFCR_DDRC1EN | -+ RCC_DDRITFCR_DDRC2EN | -+ RCC_DDRITFCR_DDRPHYCAPBEN | -+ RCC_DDRITFCR_DDRCAPBEN); -+} -+ -+static void ddr_enable_clock(void) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ /* Enable all clocks */ -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, -+ RCC_DDRITFCR_DDRC1EN | -+ RCC_DDRITFCR_DDRC2EN | -+ RCC_DDRITFCR_DDRPHYCEN | -+ RCC_DDRITFCR_DDRPHYCAPBEN | -+ RCC_DDRITFCR_DDRCAPBEN); -+} -+ -+static void do_sw_handshake(void) -+{ -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); -+} -+ -+static void do_sw_ack(void) -+{ -+ uint64_t to_ref; -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE); -+ -+ to_ref = utimeout_init(TIMEOUT_500US); -+ while ((mmio_read_32(ddrctrl_base + DDRCTRL_SWSTAT) & -+ DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U) { -+ if (utimeout_elapsed(TIMEOUT_500US, to_ref)) { -+ panic(); -+ } -+ } -+} -+ -+static int ddr_sw_self_refresh_in(void) -+{ -+ uint64_t to_ref; -+ uint32_t operating_mode; -+ uint32_t selref_type; -+ uint8_t op_mode_changed = 0; -+ uintptr_t pwr_base = stm32_pwr_base(); -+ uintptr_t rcc_base = stm32_rcc_base(); -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ uintptr_t ddrphy_base = get_ddrphy_base(); -+ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); -+ -+ /* Blocks AXI ports from taking anymore transactions */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PCTRL_0, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PCTRL_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ -+ /* -+ * Waits unit all AXI ports are idle -+ * Poll PSTAT.rd_port_busy_n = 0 -+ * Poll PSTAT.wr_port_busy_n = 0 -+ */ -+ to_ref = utimeout_init(TIMEOUT_500US); -+ while (mmio_read_32(ddrctrl_base + DDRCTRL_PSTAT)) { -+ if (utimeout_elapsed(TIMEOUT_500US, to_ref)) { -+ 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. -+ */ -+ to_ref = utimeout_init(TIMEOUT_500US); -+ while (!utimeout_elapsed(TIMEOUT_500US, to_ref)) { -+ uint32_t 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(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDR); -+ -+ mmio_clrsetbits_32(ddrphy_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CKPDD_MASK, -+ DDRPHYC_ACIOCR_CKPDD_0); -+ -+ mmio_clrsetbits_32(ddrphy_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CKPDR_MASK, -+ DDRPHYC_ACIOCR_CKPDR_0); -+ -+ mmio_clrsetbits_32(ddrphy_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CSPDD_MASK, -+ DDRPHYC_ACIOCR_CSPDD_0); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); -+ -+ mmio_clrsetbits_32(ddrphy_base + DDRPHYC_DSGCR, -+ DDRPHYC_DSGCR_ODTPDD_MASK, -+ DDRPHYC_DSGCR_ODTPDD_0); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); -+ -+ mmio_clrsetbits_32(ddrphy_base + DDRPHYC_DSGCR, -+ DDRPHYC_DSGCR_CKEPDD_MASK, -+ DDRPHYC_DSGCR_CKEPDD_0); -+ -+ /* Disable PZQ cell (PUBL register) */ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); -+ -+ /* Activate sw retention in PWRCTRL */ -+ mmio_setbits_32(pwr_base + PWR_CR3_OFF, PWR_CR3_DDRRETEN); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ -+ /* Disable all DLLs: GLITCH window */ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DX0DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DX1DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DX2DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_DX3DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL output clock */ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ -+ /* Disable all clocks */ -+ ddr_disable_clock(); -+ -+ 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); -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ -+ return -1; -+} -+ -+int ddr_sw_self_refresh_exit(void) -+{ -+ uint64_t to_ref; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ uintptr_t pwr_base = stm32_pwr_base(); -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ uintptr_t ddrphy_base = get_ddrphy_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 */ -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ -+ /* Enable all DLLs: GLITCH window */ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DX0DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DX1DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DX2DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DX3DLLCR, -+ DDRPHYC_DXNDLLCR_DLLDIS); -+ -+ /* Additional delay to avoid early DLL clock switch */ -+ udelay(10); -+ -+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */ -+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL); -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ACDLLCR, DDRPHYC_ACDLLCR_DLLSRST); -+ -+ udelay(10); -+ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_ACDLLCR, -+ DDRPHYC_ACDLLCR_DLLSRST); -+ -+ /* PHY partial init: (DLL lock and ITM reset) */ -+ mmio_write_32(ddrphy_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); -+ -+ to_ref = utimeout_init(TIMEOUT_500US); -+ while ((mmio_read_32(ddrphy_base + DDRPHYC_PGSR) & -+ DDRPHYC_PGSR_IDONE) == 0U) { -+ if (utimeout_elapsed(TIMEOUT_500US, to_ref)) { -+ 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 */ -+ mmio_clrbits_32(pwr_base + PWR_CR3_OFF, PWR_CR3_DDRRETEN); -+ -+ /* Enable PZQ cell (PUBL register) */ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD); -+ -+ /* Enable pad drivers */ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CKPDD_MASK); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ACIOCR, -+ DDRPHYC_ACIOCR_CSPDD_MASK); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_ODTPDD_MASK); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD); -+ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKEPDD_MASK); -+ -+ /* Remove selfrefresh */ -+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL, -+ DDRCTRL_PWRCTL_SELFREF_SW); -+ -+ /* Wait operating_mode == normal */ -+ to_ref = utimeout_init(TIMEOUT_500US); -+ -+ while ((mmio_read_32(ddrctrl_base + DDRCTRL_STAT) & -+ DDRCTRL_STAT_OPERATING_MODE_MASK) != -+ DDRCTRL_STAT_OPERATING_MODE_NORMAL) { -+ if (utimeout_elapsed(TIMEOUT_500US, to_ref)) { -+ return -1; -+ } -+ } -+ -+ /* AXI ports are no longer blocked from taking transactions */ -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_0, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_1, -+ DDRCTRL_PCTRL_N_PORT_EN); -+ -+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); -+ -+ return 0; -+} -+ -+uint32_t get_ddrphy_calibration(void) -+{ -+ uintptr_t ddrphy_base = get_ddrphy_base(); -+ uint32_t zcal = mmio_read_32(ddrphy_base + DDRPHYC_ZQ0CR0); -+ -+ return (zcal & DDRPHYC_ZQ0CRN_ZDATA_MASK) >> DDRPHYC_ZQ0CRN_ZDATA_SHIFT; -+} -+ -+int ddr_standby_sr_entry(uint32_t *zq0cr0_zdata) -+{ -+ uintptr_t pwr_base = stm32_pwr_base(); -+ uintptr_t ddrphy_base = get_ddrphy_base(); -+ -+ /* Save IOs calibration values */ -+ if (zq0cr0_zdata != NULL) { -+ *zq0cr0_zdata = mmio_read_32(ddrphy_base + DDRPHYC_ZQ0CR0) & -+ DDRPHYC_ZQ0CRN_ZDATA_MASK; -+ } -+ -+ /* Put DDR in Self-Refresh */ -+ if (ddr_sw_self_refresh_in() != 0) { -+ return -1; -+ } -+ -+ /* Enable I/O retention mode in standby */ -+ mmio_setbits_32(pwr_base + PWR_CR3_OFF, PWR_CR3_DDRSREN); -+ -+ return 0; -+} -+ -+void ddr_sr_mode_ssr(void) -+{ -+ uintptr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1EN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2EN); -+ -+ 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); -+ -+ /* 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); -+} -+ -+void ddr_sr_mode_asr(void) -+{ -+ uintptr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); -+ -+ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, -+ RCC_DDRITFCR_DDRCKMOD_ASR1); -+ -+ /* 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); -+} -+ -+void ddr_sr_mode_hsr(void) -+{ -+ uintptr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); -+ -+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -+ -+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -+ -+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN); -+ -+ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, -+ RCC_DDRITFCR_DDRCKMOD_HSR1); -+ -+ /* 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); -+} -+ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h -new file mode 100644 -index 0000000..59014b4 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h -@@ -0,0 +1,205 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32MP1_DDRC_H__ -+#define __STM32MP1_DDRC_H__ -+ -+#include -+ -+/* DDR Controller */ -+/* 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_32(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_32(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_32(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 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_32(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_32(19, 12) -+#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_32(27, 16) -+#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 -+ -+#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK_32(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_32(12, 8) -+#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK_32(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 -+#define DDRPHYC_PGSR 0x00C -+#define DDRPHYC_DLLGCR 0x010 -+#define DDRPHYC_ACDLLCR 0x014 -+#define DDRPHYC_PTR0 0x018 -+#define DDRPHYC_ACIOCR 0x024 -+#define DDRPHYC_DXCCR 0x028 -+#define DDRPHYC_DSGCR 0x02C -+#define DDRPHYC_ZQ0CR0 0x180 -+#define DDRPHYC_DX0GCR 0x1C0 -+#define DDRPHYC_DX0DLLCR 0x1CC -+#define DDRPHYC_DX1GCR 0x200 -+#define DDRPHYC_DX1DLLCR 0x20C -+#define DDRPHYC_DX2GCR 0x240 -+#define DDRPHYC_DX2DLLCR 0x24C -+#define DDRPHYC_DX3GCR 0x280 -+#define DDRPHYC_DX3DLLCR 0x28C -+ -+/* DDR PHY Register fields */ -+#define DDRPHYC_PIR_INIT BIT(0) -+#define DDRPHYC_PIR_DLLSRST BIT(1) -+#define DDRPHYC_PIR_DLLLOCK BIT(2) -+#define DDRPHYC_PIR_ZCAL BIT(3) -+#define DDRPHYC_PIR_ITMSRST BIT(4) -+#define DDRPHYC_PIR_DRAMRST BIT(5) -+#define DDRPHYC_PIR_DRAMINIT BIT(6) -+#define DDRPHYC_PIR_QSTRN BIT(7) -+#define DDRPHYC_PIR_ICPC BIT(16) -+#define DDRPHYC_PIR_ZCALBYP BIT(30) -+#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) -+ -+#define DDRPHYC_PGCR_DFTCMP BIT(2) -+#define DDRPHYC_PGCR_PDDISDX BIT(24) -+#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK_32(28, 25) -+ -+#define DDRPHYC_PGSR_IDONE BIT(0) -+#define DDRPHYC_PGSR_DTERR BIT(5) -+#define DDRPHYC_PGSR_DTIERR BIT(6) -+#define DDRPHYC_PGSR_DFTERR BIT(7) -+#define DDRPHYC_PGSR_RVERR BIT(8) -+#define DDRPHYC_PGSR_RVEIRR BIT(9) -+ -+#define DDRPHYC_DLLGCR_BPS200 BIT(23) -+ -+#define DDRPHYC_ACDLLCR_DLLSRST BIT(30) -+#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) -+ -+#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 -+#define DDRPHYC_PTR0_TDLLSRST_MASK GENMASK_32(5, 0) -+#define DDRPHYC_PTR0_TDLLLOCK_OFFSET 6 -+#define DDRPHYC_PTR0_TDLLLOCK_MASK GENMASK_32(17, 6) -+#define DDRPHYC_PTR0_TITMSRST_OFFSET 18 -+#define DDRPHYC_PTR0_TITMSRST_MASK GENMASK_32(21, 18) -+ -+#define DDRPHYC_ACIOCR_ACPDD BIT(3) -+#define DDRPHYC_ACIOCR_ACPDR BIT(4) -+#define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK_32(10, 8) -+#define DDRPHYC_ACIOCR_CKPDD_0 BIT(8) -+#define DDRPHYC_ACIOCR_CKPDR_MASK GENMASK_32(13, 11) -+#define DDRPHYC_ACIOCR_CKPDR_0 BIT(11) -+#define DDRPHYC_ACIOCR_CSPDD_MASK GENMASK_32(21, 18) -+#define DDRPHYC_ACIOCR_CSPDD_0 BIT(18) -+#define DDRPHYC_ACIOCR_RSTPDD BIT(27) -+#define DDRPHYC_ACIOCR_RSTPDR BIT(28) -+ -+#define DDRPHYC_DXCCR_DXPDD BIT(2) -+#define DDRPHYC_DXCCR_DXPDR BIT(3) -+ -+#define DDRPHYC_DSGCR_CKEPDD_MASK GENMASK_32(19, 16) -+#define DDRPHYC_DSGCR_CKEPDD_0 BIT(16) -+#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK_32(23, 20) -+#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) -+#define DDRPHYC_DSGCR_NL2PD BIT(24) -+ -+#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK_32(27, 0) -+#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 -+#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) -+#define DDRPHYC_ZQ0CRN_ZQPD BIT(31) -+ -+#define DDRPHYC_DXNGCR_DXEN BIT(0) -+ -+#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) -+#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) -+#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) -+#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 -+ -+uint32_t get_ddrphy_calibration(void); -+ -+int ddr_sw_self_refresh_exit(void); -+int ddr_standby_sr_entry(uint32_t *zq0cr0_zdata); -+void ddr_sr_mode_ssr(void); -+void ddr_sr_mode_asr(void); -+void ddr_sr_mode_hsr(void); -+ -+#endif /*__STM32MP1_DDRC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -new file mode 100644 -index 0000000..ed38575 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -@@ -0,0 +1,614 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK_32(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 MODE_STANDBY 8U -+ -+#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 -+ -+static struct i2c_handle_s i2c_handle; -+static uint32_t pmic_i2c_addr; -+ -+bool stm32mp_with_pmic(void) -+{ -+ return (i2c_handle.dt_status & DT_STATUS_OK_SEC) != 0; -+} -+ -+static int dt_get_pmic_node(void *fdt) -+{ -+ return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); -+} -+ -+static int dt_pmic_status(void) -+{ -+ void *fdt = get_dt_blob(); -+ -+ if (fdt) { -+ int node = dt_get_pmic_node(fdt); -+ -+ if (node > 0) { -+ return _fdt_get_status(fdt, node); -+ } -+ } -+ -+ return -1; -+} -+ -+static bool dt_pmic_is_secure(void) -+{ -+ int status = dt_pmic_status(); -+ -+ return ((unsigned)status == DT_STATUS_OK_SEC) && -+ (i2c_handle.dt_status == DT_STATUS_OK_SEC); -+} -+ -+/* -+ * @idx: Private identifier provided by the target PMIC driver -+ * @flags: Operations expected when entering a low power sequence -+ * @voltage: Target voltage to apply during low power sequences -+ */ -+struct regu_bo_config { -+ uint8_t flags; -+ struct stpmic1_bo_cfg cfg; -+}; -+ -+#define REGU_BO_FLAG_ENABLE_REGU BIT(0) -+#define REGU_BO_FLAG_SET_VOLTAGE BIT(1) -+#define REGU_BO_FLAG_PULL_DOWN BIT(2) -+#define REGU_BO_FLAG_MASK_RESET BIT(3) -+ -+static struct regu_bo_config *regu_bo_config; -+static size_t regu_bo_count; -+ -+static int save_boot_on_config(void) -+{ -+ int pmic_node, regulators_node, regulator_node; -+ void *fdt; -+ -+ assert(!regu_bo_config && !regu_bo_count); -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ pmic_node = dt_get_pmic_node(fdt); -+ if (pmic_node < 0) { -+ panic(); -+ } -+ -+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ -+ fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -+ const fdt32_t *cuint; -+ const char *name; -+ struct regu_bo_config regu_cfg; -+ uint16_t mv; -+ -+ if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", -+ NULL) == NULL) { -+ continue; -+ } -+ -+ memset(®u_cfg, 0, sizeof(regu_cfg)); -+ name = fdt_get_name(fdt, regulator_node, NULL); -+ -+ regu_cfg.flags |= REGU_BO_FLAG_ENABLE_REGU; -+ -+ if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", -+ NULL) != NULL) { -+ stpmic1_bo_pull_down_cfg(name, ®u_cfg.cfg); -+ regu_cfg.flags |= REGU_BO_FLAG_PULL_DOWN; -+ } -+ -+ if (fdt_getprop(fdt, regulator_node, "st,mask-reset", -+ NULL) != NULL) { -+ stpmic1_bo_mask_reset_cfg(name, ®u_cfg.cfg); -+ regu_cfg.flags |= REGU_BO_FLAG_MASK_RESET; -+ } -+ -+ cuint = fdt_getprop(fdt, regulator_node, -+ "regulator-min-microvolt", NULL); -+ if (cuint != NULL) { -+ /* DT uses microvolts, whereas driver awaits millivolts */ -+ mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); -+ -+ if (!stpmic1_bo_voltage_cfg(name, mv, ®u_cfg.cfg)) { -+ regu_cfg.flags |= REGU_BO_FLAG_SET_VOLTAGE; -+ } -+ } -+ -+ /* Save config in the Boot On configuration list */ -+ regu_bo_count++; -+ regu_bo_config = realloc(regu_bo_config, -+ regu_bo_count * sizeof(regu_cfg)); -+ if (regu_bo_config == NULL) { -+ panic(); -+ } -+ -+ memcpy(®u_bo_config[regu_bo_count - 1], ®u_cfg, -+ sizeof(regu_cfg)); -+ } -+ -+ return 0; -+} -+ -+void stm32mp_pmic_apply_boot_on_config(void) -+{ -+ size_t i; -+ -+ for (i = 0; i < regu_bo_count; i++) { -+ struct regu_bo_config *regu_cfg = ®u_bo_config[i]; -+ -+ if (regu_cfg->flags & REGU_BO_FLAG_SET_VOLTAGE) { -+ if (stpmic1_bo_voltage_unpg(®u_cfg->cfg)) { -+ panic(); -+ } -+ } -+ -+ if (regu_cfg->flags & REGU_BO_FLAG_ENABLE_REGU) { -+ if (stpmic1_bo_enable_unpg(®u_cfg->cfg)) { -+ panic(); -+ } -+ } -+ -+ if (regu_cfg->flags & REGU_BO_FLAG_PULL_DOWN) { -+ if (stpmic1_bo_pull_down_unpg(®u_cfg->cfg)) { -+ panic(); -+ } -+ } -+ -+ if (regu_cfg->flags & REGU_BO_FLAG_MASK_RESET) { -+ if (stpmic1_bo_mask_reset_unpg(®u_cfg->cfg)) { -+ panic(); -+ } -+ } -+ } -+} -+ -+/* -+ * @idx: Private identifier provided by the target PMIC driver -+ * @flags: Operations expected when entering a low power sequence -+ * @voltage: Target voltage to apply during low power sequences -+ */ -+struct regu_lp_config { -+ uint8_t flags; -+ struct stpmic1_lp_cfg cfg; -+}; -+ -+#define REGU_LP_FLAG_LOAD_PWRCTRL BIT(0) -+#define REGU_LP_FLAG_ON_IN_SUSPEND BIT(1) -+#define REGU_LP_FLAG_OFF_IN_SUSPEND BIT(2) -+#define REGU_LP_FLAG_SET_VOLTAGE BIT(3) -+#define REGU_LP_FLAG_MODE_STANDBY BIT(4) -+ -+struct regu_lp_state { -+ const char *name; -+ size_t cfg_count; -+ struct regu_lp_config *cfg; -+}; -+ -+#define REGU_LP_STATE_DISK 0 -+#define REGU_LP_STATE_STANDBY 1 -+#define REGU_LP_STATE_MEM 2 -+#define REGU_LP_STATE_COUNT 3 -+ -+static struct regu_lp_state regu_lp_state[REGU_LP_STATE_COUNT] = { -+ [REGU_LP_STATE_DISK] = { .name = "standby-ddr-off", }, -+ [REGU_LP_STATE_STANDBY] = { .name = "standby-ddr-sr", }, -+ [REGU_LP_STATE_MEM] = { .name = "lp-stop", }, -+}; -+ -+static unsigned int regu_lp_state2idx(const char *name) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(regu_lp_state); i++) { -+ struct regu_lp_state *state = ®u_lp_state[i]; -+ -+ if (!strncmp(name, state->name, strlen(state->name))) { -+ return i; -+ } -+ } -+ -+ panic(); -+} -+ -+static int save_low_power_config(const char *lp_state) -+{ -+ int pmic_node, regulators_node, regulator_node; -+ void *fdt; -+ unsigned int state_idx = regu_lp_state2idx(lp_state); -+ struct regu_lp_state *state = ®u_lp_state[state_idx]; -+ -+ assert(!state->cfg && !state->cfg_count); -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ pmic_node = dt_get_pmic_node(fdt); -+ if (pmic_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ -+ fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -+ const fdt32_t *cuint; -+ const char *reg_name; -+ int regulator_state_node; -+ struct regu_lp_config *regu_cfg; -+ -+ state->cfg_count++; -+ state->cfg = realloc(state->cfg, -+ state->cfg_count * sizeof(*state->cfg)); -+ if (state->cfg == NULL) { -+ panic(); -+ } -+ -+ regu_cfg = &state->cfg[state->cfg_count - 1]; -+ -+ memset(regu_cfg, 0, sizeof(*regu_cfg)); -+ -+ reg_name = fdt_get_name(fdt, regulator_node, NULL); -+ -+ if (stpmic1_lp_cfg(reg_name, ®u_cfg->cfg) != 0) { -+ EMSG("Invalid regu name %s", reg_name); -+ return -1; -+ } -+ -+ /* -+ * Always copy active configuration (Control register) to -+ * PWRCTRL Control register, even if regulator_state_node -+ * does not exist. -+ */ -+ regu_cfg->flags |= REGU_LP_FLAG_LOAD_PWRCTRL; -+ -+ /* Then apply configs from regulator_state_node */ -+ regulator_state_node = fdt_subnode_offset(fdt, -+ regulator_node, -+ lp_state); -+ if (regulator_state_node <= 0) { -+ continue; -+ } -+ -+ if (fdt_getprop(fdt, regulator_state_node, -+ "regulator-on-in-suspend", NULL) != NULL) { -+ regu_cfg->flags |= REGU_LP_FLAG_ON_IN_SUSPEND; -+ } -+ -+ if (fdt_getprop(fdt, regulator_state_node, -+ "regulator-off-in-suspend", NULL) != NULL) { -+ regu_cfg->flags |= REGU_LP_FLAG_OFF_IN_SUSPEND; -+ } -+ -+ cuint = fdt_getprop(fdt, regulator_state_node, -+ "regulator-suspend-microvolt", NULL); -+ if (cuint != NULL) { -+ uint32_t mv = fdt32_to_cpu(*cuint) / 1000U; -+ -+ if (stpmic1_lp_voltage_cfg(reg_name, mv, -+ ®u_cfg->cfg) == 0) { -+ regu_cfg->flags |= REGU_LP_FLAG_SET_VOLTAGE; -+ } -+ } -+ -+ cuint = fdt_getprop(fdt, regulator_state_node, -+ "regulator-mode", NULL); -+ if (cuint != NULL) { -+ if (fdt32_to_cpu(*cuint) == MODE_STANDBY) { -+ regu_cfg->flags |= REGU_LP_FLAG_MODE_STANDBY; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * int stm32mp_pmic_set_lp_config(char *lp_state) -+ * -+ * Load the low power configuration stored in regu_lp_state[]. -+ */ -+void stm32mp_pmic_apply_lp_config(const char *lp_state) -+{ -+ unsigned int state_idx = regu_lp_state2idx(lp_state); -+ struct regu_lp_state *state = ®u_lp_state[state_idx]; -+ size_t i; -+ -+ if (stpmic1_powerctrl_on() != 0) { -+ panic(); -+ } -+ -+ for (i = 0; i < state->cfg_count; i++) { -+ struct stpmic1_lp_cfg *cfg = &state->cfg[i].cfg; -+ -+ if ((state->cfg[i].flags & REGU_LP_FLAG_LOAD_PWRCTRL) != 0) { -+ if (stpmic1_lp_load_unpg(cfg) != 0) { -+ panic(); -+ } -+ } -+ -+ if ((state->cfg[i].flags & REGU_LP_FLAG_ON_IN_SUSPEND) != 0) { -+ if (stpmic1_lp_on_off_unpg(cfg, 1) != 0) { -+ panic(); -+ } -+ } -+ -+ if ((state->cfg[i].flags & REGU_LP_FLAG_OFF_IN_SUSPEND) != 0) { -+ if (stpmic1_lp_on_off_unpg(cfg, 0) != 0) { -+ panic(); -+ } -+ } -+ -+ if ((state->cfg[i].flags & REGU_LP_FLAG_SET_VOLTAGE) != 0) { -+ if (stpmic1_lp_voltage_unpg(cfg) != 0) { -+ panic(); -+ } -+ } -+ -+ if ((state->cfg[i].flags & REGU_LP_FLAG_MODE_STANDBY) != 0) { -+ if (stpmic1_lp_mode_unpg(cfg, 1) != 0) { -+ panic(); -+ } -+ } -+ } -+} -+ -+static int save_power_configurations(void) -+{ -+ unsigned int i; -+ -+ if (save_boot_on_config() != 0) { -+ return -1; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(regu_lp_state); i++) { -+ if (save_low_power_config(regu_lp_state[i].name) != 0) { -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * 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_pinctrl **pinctrl, -+ size_t *pinctrl_count, -+ struct stm32_i2c_init_s *init) -+{ -+ int pmic_node; -+ int i2c_node; -+ void *fdt; -+ const fdt32_t *cuint; -+ -+ fdt = get_dt_blob(); -+ if (!fdt) { -+ return -1; -+ } -+ -+ 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 -1; -+ } -+ -+ i2c_node = fdt_parent_offset(fdt, pmic_node); -+ if (i2c_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ fdt_fill_device_info(fdt, i2c_info, i2c_node); -+ if (i2c_info->base == 0U) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init, -+ pinctrl, pinctrl_count); -+} -+ -+/* -+ * PMIC and resource initialization -+ */ -+ -+/* Return true if PMIC is available, false if not found, panics on errors */ -+static bool initialize_pmic_i2c(void) -+{ -+ int ret; -+ struct dt_node_info i2c_info; -+ struct i2c_handle_s *i2c = &i2c_handle; -+ struct stm32_pinctrl *pinctrl; -+ size_t pinctrl_count; -+ struct stm32_i2c_init_s i2c_init; -+ -+ ret = dt_pmic_i2c_config(&i2c_info, &pinctrl, &pinctrl_count, -+ &i2c_init); -+ if (ret < 0) { -+ EMSG("I2C configuration failed %d\n", ret); -+ panic(); -+ } -+ if (ret != 0) { -+ return false; -+ } -+ -+ /* Initialize PMIC I2C */ -+ i2c->pbase = i2c_info.base; -+ i2c->vbase = (uintptr_t)phys_to_virt(i2c_info.base, MEM_AREA_IO_SEC); -+ assert(i2c->vbase); -+ i2c->dt_status = i2c_info.status; -+ i2c->clock = i2c_info.clock; -+ i2c_init.own_address1 = pmic_i2c_addr; -+ i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; -+ i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; -+ i2c_init.own_address2 = 0; -+ i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; -+ i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; -+ i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; -+ i2c_init.analog_filter = 1; -+ i2c_init.digital_filter_coef = 0; -+ -+ i2c->pinctrl = pinctrl; -+ i2c->pinctrl_count = pinctrl_count; -+ -+ stm32mp_get_pmic(); -+ -+ ret = stm32_i2c_init(i2c, &i2c_init); -+ if (ret != 0) { -+ EMSG("Cannot initialize I2C %x (%d)\n", i2c->pbase, ret); -+ panic(); -+ } -+ -+ if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, -+ I2C_TIMEOUT_BUSY_MS)) { -+ EMSG("I2C device not ready\n"); -+ panic(); -+ } -+ -+ stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); -+ -+ stm32mp_put_pmic(); -+ -+ return true; -+} -+ -+/* -+ * Automated suspend/resume at system suspend/resume is expected -+ * only when the PMIC is secure. If it is non secure, only atomic -+ * execution context acn get/put the PMIC resources. -+ */ -+static void pmic_suspend_resume(enum pm_op op, void __unused *handle) -+{ -+ switch (op) { -+ case PM_OP_SUSPEND: -+ stm32_i2c_suspend(&i2c_handle); -+ break; -+ case PM_OP_RESUME: -+ stm32_i2c_resume(&i2c_handle); -+ break; -+ default: -+ panic(); -+ } -+} -+KEEP_PAGER(pmic_suspend_resume); -+ -+/* stm32mp_get/put_pmic allows secure atomic sequences to use non secure PMIC */ -+void stm32mp_get_pmic(void) -+{ -+ stm32_i2c_resume(&i2c_handle); -+} -+ -+void stm32mp_put_pmic(void) -+{ -+ stm32_i2c_suspend(&i2c_handle); -+} -+ -+static void register_non_secure_pmic(void) -+{ -+ size_t n; -+ -+ if (!i2c_handle.pbase) { -+ return; -+ } -+ -+ stm32mp_register_non_secure_periph_iomem(i2c_handle.pbase); -+ stm32mp_register_clock_parents_secure(i2c_handle.clock); -+ -+ for (n = 0; n < i2c_handle.pinctrl_count; n++) { -+ stm32mp_register_non_secure_gpio(i2c_handle.pinctrl[n].bank, -+ i2c_handle.pinctrl[n].pin); -+ } -+} -+ -+static void register_secure_pmic(void) -+{ -+ size_t n; -+ -+ stm32mp_register_pm_cb(pmic_suspend_resume, NULL); -+ stm32mp_register_secure_periph_iomem(i2c_handle.pbase); -+ -+ for (n = 0; n < i2c_handle.pinctrl_count; n++) { -+ stm32mp_register_secure_gpio(i2c_handle.pinctrl[n].bank, -+ i2c_handle.pinctrl[n].pin); -+ } -+} -+ -+static TEE_Result initialize_pmic(void) -+{ -+ unsigned long pmic_version; -+ -+ if (!initialize_pmic_i2c()) { -+ DMSG("No PMIC"); -+ register_non_secure_pmic(); -+ return TEE_SUCCESS; -+ } -+ -+ stm32mp_get_pmic(); -+ -+ if (stpmic1_get_version(&pmic_version)) { -+ panic("Failed to access PMIC"); -+ } -+ -+ DMSG("PMIC version = 0x%02lx", pmic_version); -+ stpmic1_dump_regulators(); -+ -+ if (save_power_configurations() != 0) { -+ panic(); -+ } -+ -+ if (dt_pmic_is_secure()) { -+ register_secure_pmic(); -+ } else { -+ register_non_secure_pmic(); -+ } -+ -+ stm32mp_put_pmic(); -+ -+ return TEE_SUCCESS; -+} -+driver_init(initialize_pmic); -+ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -new file mode 100644 -index 0000000..f50943d ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -@@ -0,0 +1,33 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32MP1_PMIC_H__ -+#define __STM32MP1_PMIC_H__ -+ -+#include -+ -+#ifdef CFG_STPMIC1 -+void stm32mp_pmic_apply_boot_on_config(void); -+void stm32mp_pmic_apply_lp_config(const char *lp_state); -+void stm32mp_get_pmic(void); -+void stm32mp_put_pmic(void); -+#else -+void stm32mp_pmic_apply_boot_on_config(void) -+{ -+} -+void stm32mp_pmic_apply_lp_config(const char *lp_state) -+{ -+} -+void stm32mp_get_pmic(void) -+{ -+ panic(); -+} -+void stm32mp_put_pmic(void) -+{ -+ panic(); -+} -+#endif -+ -+#endif /*__STM32MP1_PMIC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c -new file mode 100644 -index 0000000..ce60f50 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c -@@ -0,0 +1,21 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+ -+uintptr_t stm32_pwr_base(void) -+{ -+ static void *va; -+ -+ if (!cpu_mmu_enabled()) -+ return PWR_BASE; -+ -+ if (!va) -+ va = phys_to_virt(PWR_BASE, MEM_AREA_IO_SEC); -+ -+ return (uintptr_t)va; -+} -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h -new file mode 100644 -index 0000000..1d44e8b ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h -@@ -0,0 +1,48 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#ifndef __STM32MP1_PWR_H__ -+#define __STM32MP1_PWR_H__ -+ -+#include -+ -+#define PWR_CR1_OFF 0x00 -+#define PWR_CR2_OFF 0x08 -+#define PWR_CR3_OFF 0x0c -+#define PWR_MPUCR_OFF 0x10 -+#define PWR_WKUPCR_OFF 0x20 -+#define PWR_MPUWKUPENR_OFF 0x28 -+ -+#define PWR_OFFSET_MASK GENMASK_32(5, 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_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_WKUPCR_MASK (GENMASK_32(27, 16) | \ -+ GENMASK_32(13, 8) | GENMASK_32(5, 0)) -+ -+#define PWR_MPUWKUPENR_MASK GENMASK_32(5, 0) -+ -+uintptr_t stm32_pwr_base(void); -+ -+#endif /*__STM32MP1_PWR_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c -new file mode 100644 -index 0000000..a9df116 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c -@@ -0,0 +1,51 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+uintptr_t stm32_rcc_base(void) -+{ -+ static void *va; -+ -+ if (!cpu_mmu_enabled()) { -+ return RCC_BASE; -+ } -+ -+ if (!va) { -+ va = phys_to_virt(RCC_BASE, MEM_AREA_IO_SEC); -+ } -+ -+ return (uintptr_t)va; -+} -+ -+void stm32_rcc_secure(int enable) -+{ -+ uintptr_t base = stm32_rcc_base(); -+ -+ if (enable != 0) { -+ io_mask32_stm32shregs(base + RCC_TZCR, RCC_TZCR_TZEN, -+ RCC_TZCR_TZEN); -+ } else { -+ io_mask32_stm32shregs(base + RCC_TZCR, 0, RCC_TZCR_TZEN); -+ } -+} -+ -+bool stm32_rcc_is_secure(void) -+{ -+ uintptr_t base = stm32_rcc_base(); -+ -+ return read32(base + RCC_TZCR) & RCC_TZCR_TZEN; -+} -+ -+bool stm32_rcc_is_mckprot(void) -+{ -+ uintptr_t base = stm32_rcc_base(); -+ -+ return read32(base + RCC_TZCR) & RCC_TZCR_MCKPROT; -+} -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h -new file mode 100644 -index 0000000..6a7a665 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h -@@ -0,0 +1,539 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#ifndef __STM32MP1_RCC_H__ -+#define __STM32MP1_RCC_H__ -+ -+#include -+#include -+ -+#define RCC_TZCR 0x00 -+#define RCC_OCENSETR 0x0C -+#define RCC_OCENCLRR 0x10 -+#define RCC_HSICFGR 0x18 -+#define RCC_CSICFGR 0x1C -+#define RCC_MPCKSELR 0x20 -+#define RCC_ASSCKSELR 0x24 -+#define RCC_RCK12SELR 0x28 -+#define RCC_MPCKDIVR 0x2C -+#define RCC_AXIDIVR 0x30 -+#define RCC_APB4DIVR 0x3C -+#define RCC_APB5DIVR 0x40 -+#define RCC_RTCDIVR 0x44 -+#define RCC_MSSCKSELR 0x48 -+#define RCC_PLL1CR 0x80 -+#define RCC_PLL1CFGR1 0x84 -+#define RCC_PLL1CFGR2 0x88 -+#define RCC_PLL1FRACR 0x8C -+#define RCC_PLL1CSGR 0x90 -+#define RCC_PLL2CR 0x94 -+#define RCC_PLL2CFGR1 0x98 -+#define RCC_PLL2CFGR2 0x9C -+#define RCC_PLL2FRACR 0xA0 -+#define RCC_PLL2CSGR 0xA4 -+#define RCC_I2C46CKSELR 0xC0 -+#define RCC_SPI6CKSELR 0xC4 -+#define RCC_UART1CKSELR 0xC8 -+#define RCC_RNG1CKSELR 0xCC -+#define RCC_CPERCKSELR 0xD0 -+#define RCC_STGENCKSELR 0xD4 -+#define RCC_DDRITFCR 0xD8 -+#define RCC_MP_BOOTCR 0x100 -+#define RCC_MP_SREQSETR 0x104 -+#define RCC_MP_SREQCLRR 0x108 -+#define RCC_MP_GCR 0x10C -+#define RCC_MP_APRSTCR 0x110 -+#define RCC_MP_APRSTSR 0x114 -+#define RCC_BDCR 0x140 -+#define RCC_RDLSICR 0x144 -+#define RCC_APB4RSTSETR 0x180 -+#define RCC_APB4RSTCLRR 0x184 -+#define RCC_APB5RSTSETR 0x188 -+#define RCC_APB5RSTCLRR 0x18C -+#define RCC_AHB5RSTSETR 0x190 -+#define RCC_AHB5RSTCLRR 0x194 -+#define RCC_AHB6RSTSETR 0x198 -+#define RCC_AHB6RSTCLRR 0x19C -+#define RCC_TZAHB6RSTSETR 0x1A0 -+#define RCC_TZAHB6RSTCLRR 0x1A4 -+#define RCC_MP_APB4ENSETR 0x200 -+#define RCC_MP_APB4ENCLRR 0x204 -+#define RCC_MP_APB5ENSETR 0x208 -+#define RCC_MP_APB5ENCLRR 0x20C -+#define RCC_MP_AHB5ENSETR 0x210 -+#define RCC_MP_AHB5ENCLRR 0x214 -+#define RCC_MP_AHB6ENSETR 0x218 -+#define RCC_MP_AHB6ENCLRR 0x21C -+#define RCC_MP_TZAHB6ENSETR 0x220 -+#define RCC_MP_TZAHB6ENCLRR 0x224 -+#define RCC_MC_APB4ENSETR 0x280 -+#define RCC_MC_APB4ENCLRR 0x284 -+#define RCC_MC_APB5ENSETR 0x288 -+#define RCC_MC_APB5ENCLRR 0x28C -+#define RCC_MC_AHB5ENSETR 0x290 -+#define RCC_MC_AHB5ENCLRR 0x294 -+#define RCC_MC_AHB6ENSETR 0x298 -+#define RCC_MC_AHB6ENCLRR 0x29C -+#define RCC_MP_APB4LPENSETR 0x300 -+#define RCC_MP_APB4LPENCLRR 0x304 -+#define RCC_MP_APB5LPENSETR 0x308 -+#define RCC_MP_APB5LPENCLRR 0x30C -+#define RCC_MP_AHB5LPENSETR 0x310 -+#define RCC_MP_AHB5LPENCLRR 0x314 -+#define RCC_MP_AHB6LPENSETR 0x318 -+#define RCC_MP_AHB6LPENCLRR 0x31C -+#define RCC_MP_TZAHB6LPENSETR 0x320 -+#define RCC_MP_TZAHB6LPENCLRR 0x324 -+#define RCC_MC_APB4LPENSETR 0x380 -+#define RCC_MC_APB4LPENCLRR 0x384 -+#define RCC_MC_APB5LPENSETR 0x388 -+#define RCC_MC_APB5LPENCLRR 0x38C -+#define RCC_MC_AHB5LPENSETR 0x390 -+#define RCC_MC_AHB5LPENCLRR 0x394 -+#define RCC_MC_AHB6LPENSETR 0x398 -+#define RCC_MC_AHB6LPENCLRR 0x39C -+#define RCC_BR_RSTSCLRR 0x400 -+#define RCC_MP_GRSTCSETR 0x404 -+#define RCC_MP_RSTSCLRR 0x408 -+#define RCC_MP_IWDGFZSETR 0x40C -+#define RCC_MP_IWDGFZCLRR 0x410 -+#define RCC_MP_CIER 0x414 -+#define RCC_MP_CIFR 0x418 -+#define RCC_PWRLPDLYCR 0x41C -+#define RCC_MP_RSTSSETR 0x420 -+#define RCC_MCO1CFGR 0x800 -+#define RCC_MCO2CFGR 0x804 -+#define RCC_OCRDYR 0x808 -+#define RCC_DBGCFGR 0x80C -+#define RCC_RCK3SELR 0x820 -+#define RCC_RCK4SELR 0x824 -+#define RCC_TIMG1PRER 0x828 -+#define RCC_TIMG2PRER 0x82C -+#define RCC_MCUDIVR 0x830 -+#define RCC_APB1DIVR 0x834 -+#define RCC_APB2DIVR 0x838 -+#define RCC_APB3DIVR 0x83C -+#define RCC_PLL3CR 0x880 -+#define RCC_PLL3CFGR1 0x884 -+#define RCC_PLL3CFGR2 0x888 -+#define RCC_PLL3FRACR 0x88C -+#define RCC_PLL3CSGR 0x890 -+#define RCC_PLL4CR 0x894 -+#define RCC_PLL4CFGR1 0x898 -+#define RCC_PLL4CFGR2 0x89C -+#define RCC_PLL4FRACR 0x8A0 -+#define RCC_PLL4CSGR 0x8A4 -+#define RCC_I2C12CKSELR 0x8C0 -+#define RCC_I2C35CKSELR 0x8C4 -+#define RCC_SAI1CKSELR 0x8C8 -+#define RCC_SAI2CKSELR 0x8CC -+#define RCC_SAI3CKSELR 0x8D0 -+#define RCC_SAI4CKSELR 0x8D4 -+#define RCC_SPI2S1CKSELR 0x8D8 -+#define RCC_SPI2S23CKSELR 0x8DC -+#define RCC_SPI45CKSELR 0x8E0 -+#define RCC_UART6CKSELR 0x8E4 -+#define RCC_UART24CKSELR 0x8E8 -+#define RCC_UART35CKSELR 0x8EC -+#define RCC_UART78CKSELR 0x8F0 -+#define RCC_SDMMC12CKSELR 0x8F4 -+#define RCC_SDMMC3CKSELR 0x8F8 -+#define RCC_ETHCKSELR 0x8FC -+#define RCC_QSPICKSELR 0x900 -+#define RCC_FMCCKSELR 0x904 -+#define RCC_FDCANCKSELR 0x90C -+#define RCC_SPDIFCKSELR 0x914 -+#define RCC_CECCKSELR 0x918 -+#define RCC_USBCKSELR 0x91C -+#define RCC_RNG2CKSELR 0x920 -+#define RCC_DSICKSELR 0x924 -+#define RCC_ADCCKSELR 0x928 -+#define RCC_LPTIM45CKSELR 0x92C -+#define RCC_LPTIM23CKSELR 0x930 -+#define RCC_LPTIM1CKSELR 0x934 -+#define RCC_APB1RSTSETR 0x980 -+#define RCC_APB1RSTCLRR 0x984 -+#define RCC_APB2RSTSETR 0x988 -+#define RCC_APB2RSTCLRR 0x98C -+#define RCC_APB3RSTSETR 0x990 -+#define RCC_APB3RSTCLRR 0x994 -+#define RCC_AHB2RSTSETR 0x998 -+#define RCC_AHB2RSTCLRR 0x99C -+#define RCC_AHB3RSTSETR 0x9A0 -+#define RCC_AHB3RSTCLRR 0x9A4 -+#define RCC_AHB4RSTSETR 0x9A8 -+#define RCC_AHB4RSTCLRR 0x9AC -+#define RCC_MP_APB1ENSETR 0xA00 -+#define RCC_MP_APB1ENCLRR 0xA04 -+#define RCC_MP_APB2ENSETR 0xA08 -+#define RCC_MP_APB2ENCLRR 0xA0C -+#define RCC_MP_APB3ENSETR 0xA10 -+#define RCC_MP_APB3ENCLRR 0xA14 -+#define RCC_MP_AHB2ENSETR 0xA18 -+#define RCC_MP_AHB2ENCLRR 0xA1C -+#define RCC_MP_AHB3ENSETR 0xA20 -+#define RCC_MP_AHB3ENCLRR 0xA24 -+#define RCC_MP_AHB4ENSETR 0xA28 -+#define RCC_MP_AHB4ENCLRR 0xA2C -+#define RCC_MP_MLAHBENSETR 0xA38 -+#define RCC_MP_MLAHBENCLRR 0xA3C -+#define RCC_MC_APB1ENSETR 0xA80 -+#define RCC_MC_APB1ENCLRR 0xA84 -+#define RCC_MC_APB2ENSETR 0xA88 -+#define RCC_MC_APB2ENCLRR 0xA8C -+#define RCC_MC_APB3ENSETR 0xA90 -+#define RCC_MC_APB3ENCLRR 0xA94 -+#define RCC_MC_AHB2ENSETR 0xA98 -+#define RCC_MC_AHB2ENCLRR 0xA9C -+#define RCC_MC_AHB3ENSETR 0xAA0 -+#define RCC_MC_AHB3ENCLRR 0xAA4 -+#define RCC_MC_AHB4ENSETR 0xAA8 -+#define RCC_MC_AHB4ENCLRR 0xAAC -+#define RCC_MC_AXIMENSETR 0xAB0 -+#define RCC_MC_AXIMENCLRR 0xAB4 -+#define RCC_MC_MLAHBENSETR 0xAB8 -+#define RCC_MC_MLAHBENCLRR 0xABC -+#define RCC_MP_APB1LPENSETR 0xB00 -+#define RCC_MP_APB1LPENCLRR 0xB04 -+#define RCC_MP_APB2LPENSETR 0xB08 -+#define RCC_MP_APB2LPENCLRR 0xB0C -+#define RCC_MP_APB3LPENSETR 0xB10 -+#define RCC_MP_APB3LPENCLRR 0xB14 -+#define RCC_MP_AHB2LPENSETR 0xB18 -+#define RCC_MP_AHB2LPENCLRR 0xB1C -+#define RCC_MP_AHB3LPENSETR 0xB20 -+#define RCC_MP_AHB3LPENCLRR 0xB24 -+#define RCC_MP_AHB4LPENSETR 0xB28 -+#define RCC_MP_AHB4LPENCLRR 0xB2C -+#define RCC_MP_AXIMLPENSETR 0xB30 -+#define RCC_MP_AXIMLPENCLRR 0xB34 -+#define RCC_MP_MLAHBLPENSETR 0xB38 -+#define RCC_MP_MLAHBLPENCLRR 0xB3C -+#define RCC_MC_APB1LPENSETR 0xB80 -+#define RCC_MC_APB1LPENCLRR 0xB84 -+#define RCC_MC_APB2LPENSETR 0xB88 -+#define RCC_MC_APB2LPENCLRR 0xB8C -+#define RCC_MC_APB3LPENSETR 0xB90 -+#define RCC_MC_APB3LPENCLRR 0xB94 -+#define RCC_MC_AHB2LPENSETR 0xB98 -+#define RCC_MC_AHB2LPENCLRR 0xB9C -+#define RCC_MC_AHB3LPENSETR 0xBA0 -+#define RCC_MC_AHB3LPENCLRR 0xBA4 -+#define RCC_MC_AHB4LPENSETR 0xBA8 -+#define RCC_MC_AHB4LPENCLRR 0xBAC -+#define RCC_MC_AXIMLPENSETR 0xBB0 -+#define RCC_MC_AXIMLPENCLRR 0xBB4 -+#define RCC_MC_MLAHBLPENSETR 0xBB8 -+#define RCC_MC_MLAHBLPENCLRR 0xBBC -+#define RCC_MC_RSTSCLRR 0xC00 -+#define RCC_MC_CIER 0xC14 -+#define RCC_MC_CIFR 0xC18 -+#define RCC_VERR 0xFF4 -+#define RCC_IDR 0xFF8 -+#define RCC_SIDR 0xFFC -+ -+#define RCC_OFFSET_MASK GENMASK_32(11, 0) -+ -+/* Values for RCC_TZCR register */ -+#define RCC_TZCR_TZEN BIT(0) -+#define RCC_TZCR_MCKPROT BIT(1) -+ -+/* Used for most of RCC_SELR registers */ -+#define RCC_SELR_SRC_MASK GENMASK_32(2, 0) -+#define RCC_SELR_REFCLK_SRC_MASK GENMASK_32(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_32(5, 0) -+#define RCC_DIVR_DIVRDY BIT(31) -+ -+/* Masks for specific DIVR registers */ -+#define RCC_APBXDIV_MASK GENMASK_32(2, 0) -+#define RCC_MPUDIV_MASK GENMASK_32(2, 0) -+#define RCC_AXIDIV_MASK GENMASK_32(2, 0) -+#define RCC_MCUDIV_MASK GENMASK_32(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 4u -+ -+/* Fields of RCC_BDCR register */ -+#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_32(5, 4) -+#define RCC_BDCR_LSEDRV_SHIFT 4 -+#define RCC_BDCR_LSECSSON BIT(8) -+#define RCC_BDCR_RTCCKEN BIT(20) -+#define RCC_BDCR_RTCSRC_MASK GENMASK_32(17, 16) -+#define RCC_BDCR_RTCSRC_SHIFT 16 -+#define RCC_BDCR_VSWRST BIT(31) -+ -+/* Fields of RCC_RDLSICR register */ -+#define RCC_RDLSICR_LSION BIT(0) -+#define RCC_RDLSICR_LSIRDY BIT(1) -+ -+/* 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_32(21, 16) -+#define RCC_PLLNCFGR1_DIVN_SHIFT 0 -+#define RCC_PLLNCFGR1_DIVN_MASK GENMASK_32(8, 0) -+/* Only for PLL3 and PLL4 */ -+#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 -+#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK_32(25, 24) -+ -+/* Used for all RCC_PLLCFGR2 registers */ -+#define RCC_PLLNCFGR2_DIVX_MASK GENMASK_32(6, 0) -+#define RCC_PLLNCFGR2_DIVP_SHIFT 0 -+#define RCC_PLLNCFGR2_DIVP_MASK GENMASK_32(6, 0) -+#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 -+#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK_32(14, 8) -+#define RCC_PLLNCFGR2_DIVR_SHIFT 16 -+#define RCC_PLLNCFGR2_DIVR_MASK GENMASK_32(22, 16) -+ -+/* Used for all RCC_PLLFRACR registers */ -+#define RCC_PLLNFRACR_FRACV_SHIFT 3 -+#define RCC_PLLNFRACR_FRACV_MASK GENMASK_32(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_32(30, 16) -+#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 -+#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK_32(12, 0) -+#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 -+#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) -+ -+/* 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) -+ -+/* Fields of RCC_OCRDYR register */ -+#define RCC_OCRDYR_HSIRDY BIT(0) -+#define RCC_OCRDYR_HSIDIVRDY BIT(2) -+#define RCC_OCRDYR_CSIRDY BIT(4) -+#define RCC_OCRDYR_HSERDY BIT(8) -+ -+/* Fields of RCC_DDRITFCR register */ -+#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_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_32(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_GSKPCTRL BIT(24) -+ -+/* Fields of RCC_HSICFGR register */ -+#define RCC_HSICFGR_HSIDIV_MASK GENMASK_32(1, 0) -+#define RCC_HSICFGR_HSITRIM_SHIFT 8 -+#define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) -+#define RCC_HSICFGR_HSICAL_SHIFT 16 -+#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) -+ -+/* Fields of RCC_CSICFGR register */ -+#define RCC_CSICFGR_CSITRIM_SHIFT 8 -+#define RCC_CSICFGR_CSITRIM_MASK GENMASK_32(12, 8) -+#define RCC_CSICFGR_CSICAL_SHIFT 16 -+#define RCC_CSICFGR_CSICAL_MASK GENMASK_32(23, 16) -+ -+/* Used for RCC_MCO related operations */ -+#define RCC_MCOCFG_MCOON BIT(12) -+#define RCC_MCOCFG_MCODIV_MASK GENMASK_32(7, 4) -+#define RCC_MCOCFG_MCODIV_SHIFT 4 -+#define RCC_MCOCFG_MCOSRC_MASK GENMASK_32(2, 0) -+ -+/* Fields of RCC_DBGCFGR register */ -+#define RCC_DBGCFGR_DBGCKEN BIT(8) -+ -+/* RCC register fields for reset reasons */ -+#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) -+#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) -+#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) -+#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) -+#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) -+#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) -+#define RCC_MP_RSTSCLRR_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) -+ -+/* Global Reset Register */ -+#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) -+#define RCC_MP_GRSTCSETR_MCURST BIT(1) -+#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) -+#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) -+ -+/* Clock Source Interrupt Flag Register */ -+#define RCC_MP_CIFR_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) -+#define RCC_MP_CIFR_MASK (RCC_MP_CIFR_LSIRDYF | RCC_MP_CIFR_LSERDYF | \ -+ RCC_MP_CIFR_HSIRDYF | RCC_MP_CIFR_HSERDYF | \ -+ RCC_MP_CIFR_CSIRDYF | RCC_MP_CIFR_PLL1DYF | \ -+ RCC_MP_CIFR_PLL2DYF | RCC_MP_CIFR_PLL3DYF | \ -+ RCC_MP_CIFR_PLL4DYF | RCC_MP_CIFR_LSECSSF | \ -+ RCC_MP_CIFR_WKUPF) -+ -+/* Stop Request Set Register */ -+#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) -+#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) -+ -+/* Stop Request Clear Register */ -+#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) -+#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) -+ -+/* RCC_MP_APB5RST(SET|CLR)R bit 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_MP_APB5EN(SET|CLR)R bit fields */ -+#define RCC_MP_APB5ENSETR_SPI6EN_POS 0 -+#define RCC_MP_APB5ENSETR_I2C4EN_POS 2 -+#define RCC_MP_APB5ENSETR_I2C6EN_POS 3 -+#define RCC_MP_APB5ENSETR_USART1EN_POS 4 -+#define RCC_MP_APB5ENSETR_RTCAPBEN_POS 8 -+#define RCC_MP_APB5ENSETR_TZC1EN_POS 11 -+#define RCC_MP_APB5ENSETR_TZC2EN_POS 12 -+#define RCC_MP_APB5ENSETR_TZPCEN_POS 13 -+#define RCC_MP_APB5ENSETR_IWDG1APBEN_POS 15 -+#define RCC_MP_APB5ENSETR_BSECEN_POS 16 -+#define RCC_MP_APB5ENSETR_STGENEN_POS 20 -+ -+#define RCC_MP_APB5ENSETR_SPI6EN BIT(RCC_MP_APB5ENSETR_SPI6EN_POS) -+#define RCC_MP_APB5ENSETR_I2C4EN BIT(RCC_MP_APB5ENSETR_I2C4EN_POS) -+#define RCC_MP_APB5ENSETR_I2C6EN BIT(RCC_MP_APB5ENSETR_I2C6EN_POS) -+#define RCC_MP_APB5ENSETR_USART1EN BIT(RCC_MP_APB5ENSETR_USART1EN_POS) -+#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(RCC_MP_APB5ENSETR_RTCAPBEN_POS) -+#define RCC_MP_APB5ENSETR_TZC1EN BIT(RCC_MP_APB5ENSETR_TZC1EN_POS) -+#define RCC_MP_APB5ENSETR_TZC2EN BIT(RCC_MP_APB5ENSETR_TZC2EN_POS) -+#define RCC_MP_APB5ENSETR_TZPCEN BIT(RCC_MP_APB5ENSETR_TZPCEN_POS) -+#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(RCC_MP_APB5ENSETR_IWDG1APBEN_POS) -+#define RCC_MP_APB5ENSETR_BSECEN BIT(RCC_MP_APB5ENSETR_BSECEN_POS) -+#define RCC_MP_APB5ENSETR_STGENEN BIT(RCC_MP_APB5ENSETR_STGENEN_POS) -+ -+/* RCC_MP_APB5LPEN(SET|CLR)R bit 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_AHB5RST(SET|CLR)R bit 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_MP_AHB5EN(SET|CLR)R bit fields */ -+#define RCC_MP_AHB5ENSETR_GPIOZEN_POS 0 -+#define RCC_MP_AHB5ENSETR_CRYP1EN_POS 4 -+#define RCC_MP_AHB5ENSETR_HASH1EN_POS 5 -+#define RCC_MP_AHB5ENSETR_RNG1EN_POS 6 -+#define RCC_MP_AHB5ENSETR_BKPSRAMEN_POS 8 -+#define RCC_MP_AHB5ENSETR_AXIMCEN_POS 16 -+ -+#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(RCC_MP_AHB5ENSETR_GPIOZEN_POS) -+#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(RCC_MP_AHB5ENSETR_CRYP1EN_POS) -+#define RCC_MP_AHB5ENSETR_HASH1EN BIT(RCC_MP_AHB5ENSETR_HASH1EN_POS) -+#define RCC_MP_AHB5ENSETR_RNG1EN BIT(RCC_MP_AHB5ENSETR_RNG1EN_POS) -+#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(RCC_MP_AHB5ENSETR_BKPSRAMEN_POS) -+#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(RCC_MP_AHB5ENSETR_AXIMCEN_POS) -+ -+/* RCC_MP_AHB5LPEN(SET|CLR)R bit 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_IWDGFZ(SET|CLR)R bit fields */ -+#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) -+#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) -+ -+#ifndef ASM -+uintptr_t stm32_rcc_base(void); -+void stm32_rcc_secure(int enable); -+bool stm32_rcc_is_secure(void); -+bool stm32_rcc_is_mckprot(void); -+#endif -+ -+#endif /*__STM32MP1_RCC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/sub.mk b/core/arch/arm/plat-stm32mp1/drivers/sub.mk -new file mode 100644 -index 0000000..c668efa ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/sub.mk -@@ -0,0 +1,8 @@ -+srcs-y += stm32mp1_pwr.c -+srcs-y += stm32mp1_rcc.c -+srcs-$(CFG_STM32_CLOCKSRC_CALIB) += stm32mp1_calib.c -+srcs-y += stm32_reset.c -+srcs-$(CFG_STPMIC1) += stm32mp1_pmic.c -+srcs-y += stm32mp1_clk.c -+srcs-$(CFG_DT) += stm32mp1_clkfunc.c -+srcs-y += stm32mp1_ddrc.c -diff --git a/core/arch/arm/plat-stm32mp1/link.mk b/core/arch/arm/plat-stm32mp1/link.mk -index 97e22ea..01a9b8e 100644 ---- a/core/arch/arm/plat-stm32mp1/link.mk -+++ b/core/arch/arm/plat-stm32mp1/link.mk -@@ -11,14 +11,14 @@ endef - all: $(link-out-dir)/tee-header_v2.stm32 - cleanfiles += $(link-out-dir)/tee-header_v2.stm32 - $(link-out-dir)/tee-header_v2.stm32: $(link-out-dir)/tee-header_v2.bin -- $(stm32image_cmd) --source $< --dest $@ -+ $(stm32image_cmd) --source $< --dest $@ --bintype 0x20 - - all: $(link-out-dir)/tee-pager_v2.stm32 - cleanfiles += $(link-out-dir)/tee-pager_v2.stm32 - $(link-out-dir)/tee-pager_v2.stm32: $(link-out-dir)/tee-pager_v2.bin -- $(stm32image_cmd) --source $< --dest $@ -+ $(stm32image_cmd) --source $< --dest $@ --bintype 0x21 - - all: $(link-out-dir)/tee-pageable_v2.stm32 - cleanfiles += $(link-out-dir)/tee-pageable_v2.stm32 - $(link-out-dir)/tee-pageable_v2.stm32: $(link-out-dir)/tee-pageable_v2.bin -- $(stm32image_cmd) --source $< --dest $@ -+ $(stm32image_cmd) --source $< --dest $@ --bintype 0x22 -diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c -index f45e3cd..1921678 100644 ---- a/core/arch/arm/plat-stm32mp1/main.c -+++ b/core/arch/arm/plat-stm32mp1/main.c -@@ -4,32 +4,105 @@ - * Copyright (c) 2016-2018, Linaro Limited - */ - -+#include - #include - #include - #include -+#include -+#include -+#include - #include -+#include -+#include -+#include -+#include -+#include -+#include - #include -+#include - #include - #include - #include -+#include -+#include - #include - #include -+#include - #include -+#include - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - --register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CONSOLE_UART_SIZE); -+#ifdef CFG_WITH_NSEC_GPIOS -+register_phys_mem(MEM_AREA_IO_NSEC, GPIOS_NSEC_BASE, GPIOS_NSEC_SIZE); -+#endif -+register_phys_mem(MEM_AREA_IO_NSEC, RNG1_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, IWDG1_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, IWDG2_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, RTC_BASE, SMALL_PAGE_SIZE); -+#ifdef CFG_WITH_NSEC_UARTS -+register_phys_mem(MEM_AREA_IO_NSEC, USART1_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, USART2_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, USART3_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, UART4_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, UART5_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, USART6_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, UART7_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, UART8_BASE, SMALL_PAGE_SIZE); -+#endif - --register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); --register_phys_mem(MEM_AREA_IO_SEC, BKP_REGS_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, GIC_IOMEM_BASE, GIC_IOMEM_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, TAMP_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, RCC_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, PWR_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, ETZPC_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, BSEC_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, I2C4_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, STGEN_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, GPIOZ_BASE, -+ STM32MP1_GPIOZ_MAX_COUNT * SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, RNG1_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, IWDG1_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, RTC_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, DDRCTRL_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, DDRPHYC_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, BKPSRAM_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_SEC, USART1_BASE, SMALL_PAGE_SIZE); - --static struct gic_data gic_data; --static struct console_pdata console_data; -+register_phys_mem(MEM_AREA_ROM_SEC, TEE_RAM_START, TEE_RAM_PH_SIZE); - --static void main_fiq(void) -+register_ddr(DDR_BASE, STM32MP1_DDR_SIZE_DFLT); -+ -+#ifdef CFG_STM32MP_MAP_NSEC_LOW_DDR -+register_phys_mem(MEM_AREA_RAM_NSEC, DDR_BASE, SMALL_PAGE_SIZE); -+#endif -+ -+#define _ID2STR(id) (#id) -+#define ID2STR(id) _ID2STR(id) -+ -+static TEE_Result platform_banner(void) - { -- gic_it_handle(&gic_data); -+#ifdef CFG_DT -+ IMSG("Platform stm32mp1: flavor %s - device tree %s", -+ ID2STR(PLATFORM_FLAVOR), ID2STR(CFG_SECURE_DT)); -+ IMSG("Model: %s", fdt_get_board_model(get_dt_blob())); -+#else -+ IMSG("Platform stm32mp1: flavor %s - no device tree", -+ ID2STR(PLATFORM_FLAVOR)); -+#endif -+ -+ return TEE_SUCCESS; - } -+service_init(platform_banner); -+ -+static void main_fiq(void); - - static const struct thread_handlers handlers = { - .std_smc = tee_entry_std, -@@ -48,10 +121,132 @@ const struct thread_handlers *generic_boot_get_handlers(void) - return &handlers; - } - -+/* -+ * Console -+ * -+ * We cannot use the generic serial_console support since probing -+ * the console requires the platform clock driver to be already -+ * up and ready which is done only once service_init are completed. -+ * -+ * If the console uses a non secure UART, its clock might have been -+ * disabled by the non secure world, in which case secure traces must -+ * be dropped unless what the driver may stall since the UART FIFO is -+ * never emptied. -+ */ -+#define CONSOLE_WITHOUT_CLOCK_MAGIC ~0UL -+ -+static struct stm32_uart_pdata console_data; -+static struct serial_chip *serial_console; -+ - void console_init(void) - { -- stm32_uart_init(&console_data, CONSOLE_UART_BASE); -+ /* Early console initialization before MMU setup */ -+ struct uart { -+ uintptr_t pa; -+ bool secure; -+ } uarts[] = { -+ [0] = { .pa = 0 }, -+ [1] = { .pa = USART1_BASE, .secure = true, }, -+ [2] = { .pa = USART2_BASE, .secure = false, }, -+ [3] = { .pa = USART3_BASE, .secure = false, }, -+ [4] = { .pa = UART4_BASE, .secure = false, }, -+ [5] = { .pa = UART5_BASE, .secure = false, }, -+ [6] = { .pa = USART6_BASE, .secure = false, }, -+ [7] = { .pa = UART7_BASE, .secure = false, }, -+ [8] = { .pa = UART8_BASE, .secure = false, }, -+ }; -+ -+ COMPILE_TIME_ASSERT(CFG_STM32_EARLY_CONSOLE_UART < ARRAY_SIZE(uarts)); -+ assert(!cpu_mmu_enabled()); -+ -+ if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa) { -+ return; -+ } -+ -+ /* No clock/PINCTRL yet bound to the UART console */ -+ console_data.clock = CONSOLE_WITHOUT_CLOCK_MAGIC; -+ -+ console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure; -+ stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa); -+ -+#ifdef CFG_FORCE_CONSOLE_ON_SUSPEND -+ serial_console = &console_data.chip; -+#else - register_serial_console(&console_data.chip); -+#endif -+ -+ IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART); -+} -+ -+#ifdef CFG_FORCE_CONSOLE_ON_SUSPEND -+void console_putc(int ch) -+{ -+ if (!serial_console) -+ return; -+ -+ stm32_pinctrl_load_active_cfg(console_data.pinctrl, -+ console_data.pinctrl_count); -+ -+ if (ch == '\n') -+ serial_console->ops->putc(serial_console, '\r'); -+ -+ serial_console->ops->putc(serial_console, ch); -+} -+ -+void console_flush(void) -+{ -+ if (!serial_console) -+ return; -+ -+ serial_console->ops->flush(serial_console); -+} -+#endif -+ -+#if CFG_DT -+/* Probe console once clocks inits (service_init level) are completed */ -+static TEE_Result stm32_uart_console_probe(void) -+{ -+ void *fdt; -+ int node; -+ struct stm32_uart_pdata *pd = NULL; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ node = fdt_get_stdout_node_offset(fdt); -+ if (node >= 0) { -+ pd = probe_uart_from_dt_node(fdt, node); -+ } -+ -+ if (pd) { -+ serial_console = NULL; -+ dmb(); -+ memcpy(&console_data, pd, sizeof(*pd)); -+ dmb(); -+ serial_console = &console_data.chip; -+ free(pd); -+ IMSG("UART console probed from DT (%ssecure)", -+ pd->secure ? "" : "non "); -+ } else { -+ IMSG("No UART console probed from DT"); -+ serial_console = NULL; -+ } -+ -+ return TEE_SUCCESS; -+} -+service_init_late(stm32_uart_console_probe); -+#endif -+ -+/* -+ * GIC init, used also for primary/secondary boot core wake completion -+ */ -+static struct gic_data gic_data; -+ -+static void main_fiq(void) -+{ -+ gic_it_handle(&gic_data); - } - - void main_init_gic(void) -@@ -59,75 +254,378 @@ void main_init_gic(void) - void *gicc_base; - void *gicd_base; - -- gicc_base = phys_to_virt(GIC_BASE + GICC_OFFSET, MEM_AREA_IO_SEC); -- gicd_base = phys_to_virt(GIC_BASE + GICD_OFFSET, MEM_AREA_IO_SEC); -+ gicc_base = phys_to_virt(GIC_IOMEM_BASE + GICC_OFFSET, MEM_AREA_IO_SEC); -+ gicd_base = phys_to_virt(GIC_IOMEM_BASE + GICD_OFFSET, MEM_AREA_IO_SEC); - if (!gicc_base || !gicd_base) - panic(); - - gic_init(&gic_data, (vaddr_t)gicc_base, (vaddr_t)gicd_base); - itr_init(&gic_data.chip); -+ -+#ifdef CFG_PSCI_ARM32 -+ stm32mp_register_online_cpu(); -+#endif - } - - void main_secondary_init_gic(void) - { - gic_cpu_init(&gic_data); -+ -+#if CFG_TEE_CORE_NB_CORE == 2 -+ /* Secondary core release constraint on APB5 clock */ -+ write32(BOOT_API_A7_RESET_MAGIC_NUMBER, -+ stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); -+ stm32mp1_clk_disable_secure(RTCAPB); -+#endif -+ -+#ifdef CFG_PSCI_ARM32 -+ stm32mp_register_online_cpu(); -+#endif -+} -+ -+/* Specific GIC suspend/resume function called aside registered PM handlers */ -+void stm32mp_gic_suspend_resume(enum pm_op op) -+{ -+ switch (op) { -+ case PM_OP_SUSPEND: -+ gic_suspend(&gic_data); -+ break; -+ case PM_OP_RESUME: -+ gic_resume(&gic_data); -+ break; -+ default: -+ panic(); -+ } -+} -+KEEP_PAGER(stm32mp_gic_suspend_resume); -+ -+/* stm32mp1 low power sequence needs straight access to GIC */ -+uintptr_t get_gicc_base(void) -+{ -+ uintptr_t pbase = GIC_IOMEM_BASE + GICC_OFFSET; -+ -+ if (cpu_mmu_enabled()) -+ return (uintptr_t)phys_to_virt(pbase, MEM_AREA_IO_SEC); -+ -+ return pbase; -+} -+ -+uintptr_t get_gicd_base(void) -+{ -+ uintptr_t pbase = GIC_IOMEM_BASE + GICD_OFFSET; -+ -+ if (cpu_mmu_enabled()) -+ return (uintptr_t)phys_to_virt(pbase, MEM_AREA_IO_SEC); -+ -+ return pbase; -+} -+ -+/* -+ * Various platform specific functions -+ */ -+unsigned int stm32mp_get_otp_max(void) -+{ -+ return STM32MP1_OTP_MAX_ID; -+} -+unsigned int stm32mp_get_otp_upper_start(void) -+{ -+ return STM32MP1_UPPER_OTP_START; -+} -+ -+bool __weak stm32mp_with_pmic(void) -+{ -+ return false; - } - - /* -- * SMP boot support and access to the mailbox -+ * SIP and other platform specific services - */ --#define GIC_SEC_SGI_0 8 -+bool sm_platform_handler(struct sm_ctx *ctx) -+{ -+ uint32_t *a0 = (uint32_t *)(&ctx->nsec.r0); -+ uint32_t *a1 = (uint32_t *)(&ctx->nsec.r1); -+ uint32_t *a2 = (uint32_t *)(&ctx->nsec.r2); -+ uint32_t *a3 = (uint32_t *)(&ctx->nsec.r3); -+ -+ if (!OPTEE_SMC_IS_FAST_CALL(*a0)) -+ return true; -+ -+ switch (OPTEE_SMC_OWNER_NUM(*a0)) { -+ case OPTEE_SMC_OWNER_SIP: -+ return stm32_sip_service(ctx, a0, a1, a2, a3); -+ case OPTEE_SMC_OWNER_OEM: -+ return stm32_oem_service(ctx, a0, a1, a2, a3); -+ default: -+ return true; -+ } -+} - --static vaddr_t bckreg_base(void) -+/* SoC versioning util */ -+uint32_t stm32mp1_dbgmcu_get_chip_version(void) -+{ -+ uintptr_t base = DBGMCU_BASE; -+ -+ if (cpu_mmu_enabled()) -+ base = (uintptr_t)phys_to_virt(DBGMCU_BASE, MEM_AREA_IO_SEC); -+ -+ return read32(base + DBGMCU_IDC) >> 16; -+} -+ -+static uintptr_t stm32_tamp_base(void) - { - static void *va; - - if (!cpu_mmu_enabled()) -- return BKP_REGS_BASE + BKP_REGISTER_OFF; -+ return TAMP_BASE; - - if (!va) -- va = phys_to_virt(BKP_REGS_BASE + BKP_REGISTER_OFF, -- MEM_AREA_IO_SEC); -+ va = phys_to_virt(TAMP_BASE, MEM_AREA_IO_SEC); - -- return (vaddr_t)va; -+ return (uintptr_t)va; - } - --static uint32_t *bckreg_address(unsigned int idx) -+static uintptr_t bkpreg_base(void) - { -- return (uint32_t *)bckreg_base() + idx; -+ return stm32_tamp_base() + TAMP_BKP_REGISTER_OFF; - } - --static void release_secondary_early_hpen(size_t pos) -+uintptr_t stm32mp_bkpreg(unsigned int idx) - { -- uint32_t *p_entry = bckreg_address(BCKR_CORE1_BRANCH_ADDRESS); -- uint32_t *p_magic = bckreg_address(BCKR_CORE1_MAGIC_NUMBER); -+ return bkpreg_base() + (idx * sizeof(uint32_t)); -+} - -- *p_entry = TEE_LOAD_ADDR; -- *p_magic = BOOT_API_A7_CORE1_MAGIC_NUMBER; -+uintptr_t stm32mp1_bkpsram_base(void) -+{ -+ static void *va; - -- dmb(); -- isb(); -- itr_raise_sgi(GIC_SEC_SGI_0, BIT(pos)); -+ if (!cpu_mmu_enabled()) -+ return BKPSRAM_BASE; -+ -+ if (!va) -+ va = phys_to_virt(BKPSRAM_BASE, MEM_AREA_IO_SEC); -+ -+ return (uintptr_t)va; -+} -+ -+uintptr_t stm32_get_stgen_base(void) -+{ -+ static uintptr_t va; -+ -+ if (!cpu_mmu_enabled()) -+ return STGEN_BASE; -+ -+ if (!va) -+ va = (uintptr_t)phys_to_virt(STGEN_BASE, MEM_AREA_IO_SEC); -+ -+ return va; - } - --int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) -+uintptr_t stm32_get_gpio_bank_base(unsigned int bank) - { -- size_t pos = get_core_pos_mpidr(core_id); -- static bool core_is_released[CFG_TEE_CORE_NB_CORE]; -+ /* Non secure banks and mapped together, same for secure banks */ -+ static uintptr_t gpiox_va; -+ static uintptr_t gpioz_va; -+ -+ switch (bank) { -+ case GPIO_BANK_A: -+ case GPIO_BANK_B: -+ case GPIO_BANK_C: -+ case GPIO_BANK_D: -+ case GPIO_BANK_E: -+ case GPIO_BANK_F: -+ case GPIO_BANK_G: -+ case GPIO_BANK_H: -+ case GPIO_BANK_I: -+ case GPIO_BANK_J: -+ case GPIO_BANK_K: -+ if (!gpiox_va && cpu_mmu_enabled()) -+ gpiox_va = (uintptr_t)phys_to_virt(GPIOS_NSEC_BASE, -+ MEM_AREA_IO_NSEC); - -- if (!pos || pos >= CFG_TEE_CORE_NB_CORE) -- return PSCI_RET_INVALID_PARAMETERS; -+ if (cpu_mmu_enabled()) -+ return gpiox_va + (bank * GPIO_BANK_OFFSET); - -- DMSG("core pos: %zu: ns_entry %#" PRIx32, pos, entry); -+ return GPIOS_NSEC_BASE + (bank * GPIO_BANK_OFFSET); - -- if (core_is_released[pos]) { -- DMSG("core %zu already released", pos); -- return PSCI_RET_DENIED; -+ case GPIO_BANK_Z: -+ if (!gpioz_va && cpu_mmu_enabled()) -+ gpioz_va = (uintptr_t)phys_to_virt(GPIOZ_BASE, -+ MEM_AREA_IO_SEC); -+ -+ if (cpu_mmu_enabled()) -+ return gpioz_va; -+ -+ return GPIOZ_BASE; -+ default: -+ panic(); -+ } -+} -+ -+uint32_t stm32_get_gpio_bank_offset(unsigned int bank) -+{ -+ if (bank == GPIO_BANK_Z) { -+ return 0; -+ } else { -+ return bank * GPIO_BANK_OFFSET; -+ } -+} -+ -+/* Return clock ID on success, negative value on error */ -+int stm32_get_gpio_bank_clock(unsigned int bank) -+{ -+ switch (bank) { -+ case GPIO_BANK_A: -+ case GPIO_BANK_B: -+ case GPIO_BANK_C: -+ case GPIO_BANK_D: -+ case GPIO_BANK_E: -+ case GPIO_BANK_F: -+ case GPIO_BANK_G: -+ case GPIO_BANK_H: -+ case GPIO_BANK_I: -+ case GPIO_BANK_J: -+ case GPIO_BANK_K: -+ return (int)GPIOA + (bank - GPIO_BANK_A); -+ case GPIO_BANK_Z: -+ return (int)GPIOZ; -+ default: -+ panic(); - } -- core_is_released[pos] = true; -+} -+ -+int stm32mp_iwdg_irq2instance(size_t irq) -+{ -+ int instance = (int)irq - STM32MP1_IRQ_IWDG1; -+ -+ assert((instance >= IWDG1_INST) && (instance <= IWDG2_INST)); -+ return instance; -+} -+ -+size_t stm32mp_iwdg_instance2irq(int instance) -+{ -+ return (size_t)(instance + STM32MP1_IRQ_IWDG1); -+} - -- generic_boot_set_core_ns_entry(pos, entry, context_id); -- release_secondary_early_hpen(pos); -+unsigned int stm32mp_iwdg_iomem2instance(uintptr_t pbase) -+{ -+ switch (pbase) { -+ case IWDG1_BASE: -+ return IWDG1_INST; -+ case IWDG2_BASE: -+ return IWDG2_INST; -+ default: -+ panic(); -+ } -+} -+ -+unsigned long stm32_get_iwdg_otp_config(uintptr_t pbase) -+{ -+ unsigned int idx; -+ unsigned long iwdg_cfg = 0; -+ uint32_t otp_value; -+ -+ idx = stm32mp_iwdg_iomem2instance(pbase); -+ -+ if (bsec_read_otp(&otp_value, HW2_OTP)) -+ panic(); -+ -+ if (otp_value & BIT(idx + HW2_OTP_IWDG_HW_ENABLE_SHIFT)) -+ iwdg_cfg |= IWDG_HW_ENABLED; -+ -+ if (!(otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STOP_SHIFT))) -+ iwdg_cfg |= IWDG_ENABLE_ON_STOP; -+ -+ if (!(otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STANDBY_SHIFT))) -+ iwdg_cfg |= IWDG_ENABLE_ON_STANDBY; -+ -+ return iwdg_cfg; -+} -+ -+uintptr_t stm32mp_get_etzpc_base(void) -+{ -+ return ETZPC_BASE; -+} -+ -+/* -+ * 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 TZPC_DECPROT_S_RW; -+ case DECPROT_NS_R_S_W: -+ return TZPC_DECPROT_NS_R_S_W; -+ case DECPROT_MCU_ISOLATION: -+ return TZPC_DECPROT_MCU_ISOLATION; -+ case DECPROT_NS_RW: -+ return TZPC_DECPROT_NS_RW; -+ default: -+ panic(); -+ } -+} -+ -+#ifdef CFG_STM32_RTC -+/******************************************************************************* -+ * This function determines the number of needed RTC calendar read operations -+ * to get consistent values (1 or 2 depending of clock frequencies). -+ * If APB1 frequency is less than 7 times the RTC one, the software has to -+ * read the calendar time and date register twice. -+ * This function computes each of them and does the comparison. -+ * Returns true if read twice is needed, false else. -+ ******************************************************************************/ -+bool stm32_rtc_get_read_twice(void) -+{ -+ unsigned long apb1_freq; -+ unsigned long rtc_freq = 0; -+ uint32_t apb1_div; -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ /* Compute RTC frequency */ -+ switch ((mmio_read_32(rcc_base + RCC_BDCR) & -+ RCC_BDCR_RTCSRC_MASK) >> RCC_BDCR_RTCSRC_SHIFT) { -+ case 1: -+ rtc_freq = stm32mp1_clk_get_rate(CK_LSE); -+ break; -+ case 2: -+ rtc_freq = stm32mp1_clk_get_rate(CK_LSI); -+ break; -+ case 3: -+ rtc_freq = stm32mp1_clk_get_rate(CK_HSE); -+ rtc_freq /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & -+ RCC_DIVR_DIV_MASK) + 1U; -+ break; -+ default: -+ /* Forbidden values: consider only one needed read here */ -+ panic(); -+ } -+ -+ /* Compute APB1 frequency */ -+ apb1_div = mmio_read_32(rcc_base + RCC_APB1DIVR) & RCC_APBXDIV_MASK; -+ apb1_freq = stm32mp1_clk_get_rate(CK_MCU) >> apb1_div; -+ -+ /* Compare APB1 and 7*RTC frequencies */ -+ return apb1_freq < (rtc_freq * 7U); -+} -+#endif -+ -+uint32_t may_spin_lock(unsigned int *lock) -+{ -+ if (!lock || !cpu_mmu_enabled()) { -+ return 0; -+ } -+ -+ return cpu_spin_lock_xsave(lock); -+} -+ -+void may_spin_unlock(unsigned int *lock, uint32_t exceptions) -+{ -+ if (!lock || !cpu_mmu_enabled()) { -+ return; -+ } - -- return PSCI_RET_SUCCESS; -+ cpu_spin_unlock_xrestore(lock, exceptions); - } -diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h -index 6f5dd97..e8d1660 100644 ---- a/core/arch/arm/plat-stm32mp1/platform_config.h -+++ b/core/arch/arm/plat-stm32mp1/platform_config.h -@@ -8,22 +8,185 @@ - - #include - -+/* Enable/disable use of the core0 reset control from RCC */ -+#undef STM32MP1_USE_MPU0_RESET -+ - /* Make stacks aligned to data cache line length */ - #define STACK_ALIGNMENT 32 - --#define GIC_BASE 0xA0021000ul --#define GIC_SIZE 0x2000 --#define GICC_OFFSET 0x1000 --#define GICD_OFFSET 0x0000 -+#if defined(CFG_WITH_PAGER) -+#if defined(CFG_WITH_LPAE) -+/* -+ * Optimize unpaged memory size: -+ * - one table for the level2 table for overall vmem range -+ * - two tables for TEE RAM fine grain mapping [2ffc.0000 301f.ffff] -+ * - one table for internal RAMs (PM: ROMed core TEE RAM & DDR first page) -+ * - one table for a 2MByte dynamiq shared virtual memory (SHM_VASPACE) -+ */ -+#define MAX_XLAT_TABLES 5 -+#else -+/* -+ * Optimize unpaged memory size: -+ * - two tables for TEE RAM mapping [2ffc.0000 300f.ffff] -+ * - one table for secure internal RAMs (PM: ROMed core TEE RAM) -+ * - one table for non-secure internal RAMs (PM: DDR first page) -+ * - two tables for a 2MByte dynamiq shared virtual memory (SHM_VASPACE) -+ */ -+#define MAX_XLAT_TABLES 6 -+#endif /*CFG_WITH_LPAE*/ -+#else -+/* Be generous, there is plenty of secure DDR */ -+#define MAX_XLAT_TABLES 10 -+#endif /*CFG_WITH_PAGER*/ -+ -+/* Expected platform default size, if not found in device tree */ -+#define STM32MP1_DDR_SIZE_DFLT (1 * 1024 * 1024 * 1024) - --#define BKP_REGS_BASE 0x5C00A000 --#define BKP_REGISTER_OFF 0x100 -+#define GIC_IOMEM_BASE 0xa0021000ul -+#define GIC_IOMEM_SIZE 0x00007000 -+#define DDR_BASE 0xc0000000ul -+#define SYSRAM_BASE 0x2ffc0000 -+#define BKPSRAM_BASE 0x54000000 - -+#define BSEC_BASE 0x5c005000 -+#define CRYP1_BASE 0x54001000 -+#define DBGMCU_BASE 0x50081000 -+#define DDRCTRL_BASE 0x5a003000 -+#define DDRPHYC_BASE 0x5a004000 -+#define ETZPC_BASE 0x5c007000 -+#define EXTI_BASE 0x5000D000 -+#define GPIOA_BASE 0x50002000 -+#define GPIOB_BASE 0x50003000 -+#define GPIOC_BASE 0x50004000 -+#define GPIOD_BASE 0x50005000 -+#define GPIOE_BASE 0x50006000 -+#define GPIOF_BASE 0x50007000 -+#define GPIOG_BASE 0x50008000 -+#define GPIOH_BASE 0x50009000 -+#define GPIOI_BASE 0x5000a000 -+#define GPIOJ_BASE 0x5000b000 -+#define GPIOK_BASE 0x5000c000 -+#define GPIOZ_BASE 0x54004000 -+#define HASH1_BASE 0x54002000 -+#define I2C4_BASE 0x5c002000 -+#define I2C6_BASE 0x5c009000 -+#define IWDG1_BASE 0x5c003000 -+#define IWDG2_BASE 0x5a002000 -+#define PWR_BASE 0x50001000 -+#define RCC_BASE 0x50000000 -+#define RNG1_BASE 0x54003000 -+#define RTC_BASE 0x5c004000 -+#define SPI6_BASE 0x5c001000 -+#define STGEN_BASE 0x5C008000 -+#define TAMP_BASE 0x5c00a000 -+#define USART1_BASE 0x5c000000 -+#define USART2_BASE 0x4000e000 -+#define USART3_BASE 0x4000f000 - #define UART4_BASE 0x40010000 --#define STM32MP1_DEBUG_USART_BASE UART4_BASE --#define GIC_SPI_UART4 84 -+#define UART5_BASE 0x40011000 -+#define USART6_BASE 0x44003000 -+#define UART7_BASE 0x40018000 -+#define UART8_BASE 0x40019000 -+#define TZC_BASE 0x5c006000 -+ -+/* BSEC OTP resources */ -+#define STM32MP1_OTP_MAX_ID 0x5FU -+#define STM32MP1_UPPER_OTP_START 0x20U -+ -+#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) -+ -+#define DATA0_OTP 0 -+#define PART_NUMBER_OTP 1 -+#define MONOTONIC_OTP 4 -+#define NAND_OTP 9 -+#define UID0_OTP 13 -+#define UID1_OTP 14 -+#define UID2_OTP 15 -+#define HW2_OTP 18 -+ -+#define DATA0_OTP_SECURED BIT(6) -+ -+#define HW2_OTP_IWDG_HW_ENABLE_SHIFT 3 -+#define HW2_OTP_IWDG_FZ_STOP_SHIFT 5 -+#define HW2_OTP_IWDG_FZ_STANDBY_SHIFT 7 -+ -+/* -+ * GPIO banks: 11 non secure banks (A to K) and 1 secure bank (Z) -+ * Bank register's base address is computed from the bank ID listed here. -+ */ -+#define GPIOS_NSEC_COUNT 11 -+#define GPIOS_NSEC_BASE GPIOA_BASE -+#define GPIOS_NSEC_SIZE (GPIOS_NSEC_COUNT * SMALL_PAGE_SIZE) -+ -+#define STM32MP1_GPIOZ_MAX_COUNT 1 -+#define STM32MP1_GPIOZ_PIN_MAX_COUNT 8 -+ -+#define GPIO_BANK_OFFSET 0x1000U -+ -+/* Bank IDs used in GPIO driver API */ -+#define GPIO_BANK_A 0U -+#define GPIO_BANK_B 1U -+#define GPIO_BANK_C 2U -+#define GPIO_BANK_D 3U -+#define GPIO_BANK_E 4U -+#define GPIO_BANK_F 5U -+#define GPIO_BANK_G 6U -+#define GPIO_BANK_H 7U -+#define GPIO_BANK_I 8U -+#define GPIO_BANK_J 9U -+#define GPIO_BANK_K 10U -+#define GPIO_BANK_Z 25U -+ -+/* IWDG resources */ -+#define IWDG1_INST 0 -+#define IWDG2_INST 1 -+ -+#define STM32MP1_IRQ_IWDG1 182U -+#define STM32MP1_IRQ_IWDG2 183U -+ -+/* TAMP resources */ -+#define TAMP_BKP_REGISTER_OFF 0x100 -+ -+/* RCC platform resources */ -+#define RCC_WAKEUP_IT 177 -+ -+/* SoC revision */ -+#define STM32MP1_REV_A 0x00001000 -+#define STM32MP1_REV_B 0x00002000 -+ -+/* DBGMCU resources */ -+#define DBGMCU_IDC 0x0 -+ -+/* BKPSRAM layout */ -+#define BKPSRAM_SIZE SMALL_PAGE_SIZE -+#define BKPSRAM_PM_OFFSET 0x000 -+#define BKPSRAM_PM_SIZE (BKPSRAM_PM_MAILBOX_SIZE + \ -+ BKPSRAM_PM_CONTEXT_SIZE) -+ -+#define BKPSRAM_PM_MAILBOX_OFFSET BKPSRAM_PM_OFFSET -+#define BKPSRAM_PM_MAILBOX_SIZE 0x100 -+#define BKPSRAM_PM_CONTEXT_OFFSET (BKPSRAM_PM_MAILBOX_OFFSET + \ -+ BKPSRAM_PM_MAILBOX_SIZE) -+#define BKPSRAM_PM_CONTEXT_SIZE 0x700 -+ -+/* SYSRAM */ -+#define SYSRAM_SIZE 0x40000 -+ -+/* GIC resources */ -+#define GICD_OFFSET 0x00000000 -+#define GICC_OFFSET 0x00001000 -+#define GICH_OFFSET 0x00003000 -+#define GICV_OFFSET 0x00005000 -+ -+#define GIC_NON_SEC_SGI_0 0 -+#define GIC_SEC_SGI_0 8 -+#define GIC_SEC_SGI_1 9 -+#define GIC_SPI_SEC_PHY_TIMER 29 -+ -+#define TARGET_CPU0_GIC_MASK BIT(0) -+#define TARGET_CPU1_GIC_MASK BIT(1) -+#define TARGET_CPUS_GIC_MASK GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0) - --#define CONSOLE_UART_BASE STM32MP1_DEBUG_USART_BASE --#define CONSOLE_UART_SIZE 1024 -+#define STM32MP_GIC_PRIORITY_CSTOP 0xc0 - - #endif /*PLATFORM_CONFIG_H*/ -diff --git a/core/arch/arm/plat-stm32mp1/pm/context.c b/core/arch/arm/plat-stm32mp1/pm/context.c -new file mode 100644 -index 0000000..2ce72b3 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/context.c -@@ -0,0 +1,510 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "context.h" -+#include "power.h" -+ -+#define TRAINING_AREA_SIZE 64 -+ -+#define STANDBY_CONTEXT_MAGIC (0x00010000 + TRAINING_AREA_SIZE) -+ -+/* -+ * Context saved in TEE RAM during lower power sequence. -+ * Can be allocated if to big for static allocation. -+ * -+ * @stgen_cnt_h: Upper 32bit of the STGEN counter -+ * @stgen_cnt_l: Lower 32bit of the STGEN counter -+ * @rtc: RTC time read at suspend -+ */ -+struct pm_context { -+ uint32_t stgen_cnt_h; -+ uint32_t stgen_cnt_l; -+ struct stm32_rtc_calendar rtc; -+}; -+ -+static struct pm_context plat_ctx; -+ -+/* -+ * BKPSRAM contains a mailbox used with early boot stages for resume sequence. -+ * The mailbox content data that must be restored before OP-TEE is resumed. -+ * -+ * @magic: magic value read by early boot stage for consistency -+ * @zq0cr0_zdata: DDRPHY configuration to be restored. -+ * @ddr_training_backup: DDR area saved at suspend and backed up at resume -+ */ -+struct pm_mailbox { -+ uint32_t magic; -+ uint32_t core0_resume_ep; -+ uint32_t zq0cr0_zdata; -+ uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; -+}; -+ -+/* -+ * BKPSRAM contains OP-TEE resume instruction sequence which restores -+ * TEE RAM content. The BKPSRAM contains restoration materials -+ * (key, tag) and the resume entry point in restored TEE RAM. -+ */ -+static struct retram_resume_ctx *get_retram_resume_ctx(void) -+{ -+ uintptr_t bkpsram_base = stm32mp1_bkpsram_base(); -+ uintptr_t context_base = bkpsram_base + BKPSRAM_PM_CONTEXT_OFFSET; -+ -+ return (struct retram_resume_ctx *)context_base; -+} -+ -+static struct pm_mailbox *get_pm_mailbox(void) -+{ -+ uintptr_t bkpsram_base = stm32mp1_bkpsram_base(); -+ uintptr_t mailbox_base = bkpsram_base + BKPSRAM_PM_MAILBOX_OFFSET; -+ -+ return (struct pm_mailbox *)mailbox_base; -+} -+ -+#if TRACE_LEVEL >= TRACE_DEBUG -+static void __maybe_unused dump_context(void) -+{ -+ struct pm_mailbox *mailbox = get_pm_mailbox(); -+ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -+ -+ stm32_clock_enable(RTCAPB); -+ -+ DMSG("Backup registers: address 0x%" PRIx32 ", magic 0x%" PRIx32, -+ *(uint32_t *)stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS), -+ *(uint32_t *)stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); -+ -+ stm32_clock_disable(RTCAPB); -+ -+ stm32_clock_enable(BKPSRAM); -+ -+ DMSG("BKPSRAM mailbox: 0x%" PRIx32 ", zd 0x%" PRIx32 ", ep 0x%" PRIx32, -+ mailbox->magic, mailbox->zq0cr0_zdata, -+ mailbox->core0_resume_ep); -+ -+ DMSG("BKPSRAM context: teeram backup @%" PRIx32 ", resume @0x%" PRIx32, -+ ctx->teeram_bkp_pa, ctx->resume_pa); -+ -+ stm32_clock_disable(BKPSRAM); -+} -+#else -+static void __maybe_unused dump_context(void) -+{ -+} -+#endif -+ -+/* -+ * Save and restore functions -+ */ -+static void save_time(void) -+{ -+ uintptr_t stgen = stm32_get_stgen_base(); -+ -+ plat_ctx.stgen_cnt_h = read32(stgen + CNTCVU_OFFSET); -+ plat_ctx.stgen_cnt_l = read32(stgen + CNTCVL_OFFSET); -+ if (plat_ctx.stgen_cnt_l < 10) { -+ plat_ctx.stgen_cnt_h = read32(stgen + CNTCVU_OFFSET); -+ } -+ -+ stm32_rtc_get_calendar(&plat_ctx.rtc); -+} -+ -+#if TRACE_LEVEL >= TRACE_DEBUG -+static void print_ccm_decryption_duration(void) -+{ -+ uintptr_t stgen = stm32_get_stgen_base(); -+ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -+ -+ -+ stm32_clock_enable(BKPSRAM); -+ -+ DMSG("CCM decryption duration %llums", -+ ((unsigned long long)ctx->stgen_cnt * 1000) / -+ mmio_read_32(stgen + CNTFID_OFFSET)); -+ -+ stm32_clock_enable(BKPSRAM); -+} -+#else -+static void print_ccm_decryption_duration(void) -+{ -+} -+#endif -+ -+static void restore_time(void) -+{ -+ struct stm32_rtc_calendar current_calendar; -+ unsigned long long stdby_time_in_ms; -+ unsigned long long cnt; -+ uintptr_t stgen = stm32_get_stgen_base(); -+ struct retram_resume_ctx __maybe_unused *ctx = get_retram_resume_ctx(); -+ -+ stm32_rtc_get_calendar(¤t_calendar); -+ stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar, -+ &plat_ctx.rtc); -+ -+ cnt = ((uint64_t)plat_ctx.stgen_cnt_h << 32) | plat_ctx.stgen_cnt_l; -+ cnt += (stdby_time_in_ms * mmio_read_32(stgen + CNTFID_OFFSET)) / 1000U; -+ -+ mmio_clrbits_32(stgen + CNTCR_OFFSET, CNTCR_EN); -+ mmio_write_32(stgen + CNTCVL_OFFSET, (uint32_t)cnt); -+ mmio_write_32(stgen + CNTCVU_OFFSET, (uint32_t)(cnt >> 32)); -+ mmio_setbits_32(stgen + CNTCR_OFFSET, CNTCR_EN); -+ -+ print_ccm_decryption_duration(); -+} -+ -+static bool __maybe_unused pm_cb_is_valid(void (*cb)(enum pm_op op, void *hdl), -+ void *hdl) -+{ -+ void *cb_voidp = (void *)(uintptr_t)cb; -+ paddr_t cb_phy = virt_to_phys(cb_voidp); -+ paddr_t hdl_phy = virt_to_phys(hdl); -+ bool __maybe_unused valid; -+ -+ valid = (phys_to_virt(cb_phy, MEM_AREA_TEE_RAM_RX) == cb_voidp) && -+ ((phys_to_virt(hdl_phy, MEM_AREA_TEE_RAM_RX) == hdl) || -+ (phys_to_virt(hdl_phy, MEM_AREA_TEE_RAM_RO) == hdl) || -+ (phys_to_virt(hdl_phy, MEM_AREA_TEE_RAM_RW) == hdl)); -+ -+ if (!valid) { -+ EMSG("pm_cb mandates unpaged arguments %p %p", cb_voidp, hdl); -+ } -+ -+ return valid; -+} -+ -+struct pm_cb { -+ void (*callback)(enum pm_op op, void *handle); -+ void *handle; -+}; -+static struct pm_cb *pm_cb; -+static size_t pm_cb_count; -+ -+void stm32mp_register_pm_cb(void (*callback)(enum pm_op op, void *handle), -+ void *handle) -+{ -+ assert(pm_cb_is_valid(callback, handle)); -+ -+ pm_cb_count++; -+ pm_cb = realloc(pm_cb, sizeof(struct pm_cb) * pm_cb_count); -+ if (!pm_cb){ -+ panic(); -+ } -+ -+ pm_cb[pm_cb_count - 1].callback = callback; -+ pm_cb[pm_cb_count - 1].handle = handle; -+} -+ -+static void save_soc_context(void) -+{ -+ const enum pm_op suspend = PM_OP_SUSPEND; -+ size_t n; -+ -+ for (n = 0; n < pm_cb_count; n++) { -+ pm_cb[n].callback(suspend, pm_cb[n].handle); -+ } -+ -+ /* Suspend core services */ -+ stm32mp_gic_suspend_resume(suspend); -+ stm32mp_clock_suspend_resume(suspend); -+} -+ -+static void restore_soc_context(void) -+{ -+ const enum pm_op resume = PM_OP_RESUME; -+ size_t n; -+ -+ /* Resume core services */ -+ stm32mp_gic_suspend_resume(resume); -+ stm32mp_clock_suspend_resume(resume); -+ -+ for (n = 0; n < pm_cb_count; n++) { -+ pm_cb[n].callback(resume, pm_cb[n].handle); -+ } -+} -+ -+uintptr_t stm32mp_pm_retram_resume_ep(void) -+{ -+ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -+ -+ return (uintptr_t)&ctx->resume_sequence; -+} -+ -+/* Clear the content of the PM mailbox */ -+void stm32mp_pm_wipe_context(void) -+{ -+ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -+ struct pm_mailbox *mailbox = get_pm_mailbox(); -+ -+ stm32_clock_enable(BKPSRAM); -+ -+ memset(ctx, 0xa5, sizeof(*ctx)); -+ memset(mailbox, 0xa5, sizeof(*mailbox)); -+ -+ stm32_clock_disable(BKPSRAM); -+} -+ -+static struct mobj *teeram_bkp_mobj; -+ -+static void init_retram_resume_resources(void) -+{ -+ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -+ const size_t size = (uintptr_t)stm32mp_bkpsram_image_end - -+ (uintptr_t)stm32mp_bkpsram_resume; -+ paddr_t __maybe_unused pa; -+ -+ COMPILE_TIME_ASSERT(sizeof(struct pm_mailbox) < -+ BKPSRAM_PM_MAILBOX_SIZE); -+ COMPILE_TIME_ASSERT(sizeof(struct retram_resume_ctx) < -+ BKPSRAM_PM_CONTEXT_SIZE); -+ assert((sizeof(*ctx) + size) < BKPSRAM_PM_CONTEXT_SIZE); -+ -+ teeram_bkp_mobj = mobj_mm_alloc(mobj_sec_ddr, TEE_RAM_PH_SIZE, -+ &tee_mm_sec_ddr); -+ if (teeram_bkp_mobj == NULL) { -+ panic(); -+ } -+ assert((mobj_get_va(teeram_bkp_mobj, 0) != NULL) && -+ (mobj_get_pa(teeram_bkp_mobj, 0, 0, &pa) == 0)); -+ -+ stm32_clock_enable(BKPSRAM); -+ memset(ctx, 0, sizeof(*ctx)); -+ stm32_clock_disable(BKPSRAM); -+} -+ -+/* -+ * 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 in the PM mailbox with the earlier boot stages. -+ */ -+static void save_ddr_training_area(void) -+{ -+ struct pm_mailbox *mailbox = get_pm_mailbox(); -+ size_t size = sizeof(mailbox->ddr_training_backup); -+ struct mobj __maybe_unused *mobj = NULL; -+ paddr_t pa = DDR_BASE; -+ void *va = phys_to_virt(pa, MEM_AREA_RAM_NSEC); -+ -+#if !defined(CFG_STM32MP_MAP_NSEC_LOW_DDR) -+ /* Config switch helps not requesting mobj_mapped_shm_alloc() unpaged */ -+ if (!va) { -+ mobj = mobj_mapped_shm_alloc(&pa, SMALL_PAGE_SIZE, 0, 0); -+ va = mobj_get_va(mobj, 0); -+ } -+#endif -+ -+ memcpy(&mailbox->ddr_training_backup[0], va, size); -+ -+ mobj_free(mobj); -+} -+ -+static void load_earlyboot_pm_mailbox(void) -+{ -+ struct pm_mailbox *mailbox = get_pm_mailbox(); -+ -+ COMPILE_TIME_ASSERT(sizeof(struct pm_mailbox) < -+ BKPSRAM_PM_MAILBOX_SIZE); -+ -+ assert(stm32_clock_is_enabled(BKPSRAM)); -+ -+ memset(mailbox, 0, sizeof(*mailbox)); -+ -+ mailbox->zq0cr0_zdata = get_ddrphy_calibration(); -+ -+ save_ddr_training_area(); -+} -+ -+#ifdef CFG_STM32_RNG -+/* -+ * CRYP relies on standard format for CCM IV/B0/CRT0 data. Our sequence uses -+ * no AAD, 4 bytes to encode the payload byte size and a 11 byte nonce. -+ */ -+#define PM_CCM_Q 4 -+#define PM_CCM_Q_FLAGS (PM_CCM_Q - 1) -+#define PM_CCM_TAG_LEN 16 -+#define PM_CCM_TAG_FLAGS (((PM_CCM_TAG_LEN - 2) / 2) << 3) -+ -+static void save_teeram_in_ddr(void) -+{ -+ struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -+ size_t __maybe_unused size = (uintptr_t)stm32mp_bkpsram_image_end - -+ (uintptr_t)stm32mp_bkpsram_resume; -+ paddr_t pa; -+ struct ccm_unpg_ctx *ccm = &ctx->ccm_ctx; -+ void *teeram = phys_to_virt(TEE_RAM_START, MEM_AREA_ROM_SEC); -+ void *teeram_bkp = mobj_get_va(teeram_bkp_mobj, 0); -+ -+ COMPILE_TIME_ASSERT(PM_CTX_CCM_KEY_SIZE == sizeof(ccm->key)); -+ COMPILE_TIME_ASSERT(PM_CTX_CCM_CTR1_SIZE == sizeof(ccm->ctr1)); -+ COMPILE_TIME_ASSERT(PM_CTX_CCM_B0_SIZE == sizeof(ccm->b0)); -+ COMPILE_TIME_ASSERT(PM_CTX_CCM_CTR0_SIZE == sizeof(ccm->ctr0)); -+ COMPILE_TIME_ASSERT(PM_CTX_CCM_TAG_SIZE == sizeof(ccm->tag)); -+ -+ assert(stm32_clock_is_enabled(BKPSRAM) && -+ stm32_clock_is_enabled(CRYP1)); -+ -+ memcpy(ctx->resume_sequence, -+ (void *)(uintptr_t)stm32mp_bkpsram_resume, size); -+ -+ memset(ctx, 0, sizeof(*ctx)); -+ ctx->resume_pa = virt_to_phys((void *)(uintptr_t)stm32mp_sysram_resume); -+ if (mobj_get_pa(teeram_bkp_mobj, 0, 0, &pa)) { -+ panic(); -+ } -+ ctx->teeram_bkp_pa = (uint32_t)pa; -+ ctx->cryp1_base = (uint32_t)phys_to_virt(CRYP1_BASE, MEM_AREA_IO_SEC); -+ ctx->rcc_base = (uint32_t)phys_to_virt(RCC_BASE, MEM_AREA_IO_SEC); -+ ctx->stgen_base = (uint32_t)phys_to_virt(STGEN_BASE, MEM_AREA_IO_SEC); -+ -+ if (stm32_rng_read((uint8_t *)ccm->key, sizeof(ccm->key))) { -+ panic(); -+ } -+ -+ assert(((PM_CCM_TAG_FLAGS & ~0x38U) | (PM_CCM_Q_FLAGS & ~0x07U)) == 0); -+ COMPILE_TIME_ASSERT(PM_CCM_Q <= 4); -+ COMPILE_TIME_ASSERT(TEE_RAM_PH_SIZE > UINT16_MAX); -+ COMPILE_TIME_ASSERT(TEE_RAM_PH_SIZE < UINT32_MAX); -+ -+ if (stm32_rng_read((uint8_t *)ccm->ctr1, sizeof(ccm->ctr1))) { -+ panic(); -+ } -+ ccm->ctr1[0] &= GENMASK_32(24, 0); -+ memcpy(ccm->b0, ccm->ctr1, sizeof(ccm->b0)); -+ memcpy(ccm->ctr0, ccm->ctr1, sizeof(ccm->ctr0)); -+ -+ ccm->ctr0[0] |= PM_CCM_Q_FLAGS << 24; -+ ccm->ctr0[3] = 0; -+ ccm->ctr1[0] |= PM_CCM_Q_FLAGS << 24; -+ ccm->ctr1[3] = 1; -+ ccm->b0[0] |= (PM_CCM_Q_FLAGS | PM_CCM_TAG_FLAGS) << 24; -+ ccm->b0[3] = TEE_RAM_PH_SIZE; -+ -+ stm32mp_ccm_encrypt_teeram(ctx, teeram_bkp, teeram, TEE_RAM_PH_SIZE); -+ dcache_clean_range(teeram_bkp, TEE_RAM_PH_SIZE); -+ -+ memcpy(ctx->ccm_ref_tag, ccm->tag, sizeof(ctx->ccm_ref_tag)); -+ -+ DMSG("CCM encryption duration %llums", -+ ((unsigned long long)ctx->stgen_cnt * 1000) / -+ mmio_read_32(ctx->stgen_base + CNTFID_OFFSET)); -+ ctx->stgen_cnt = 0; -+} -+#else -+static void save_teeram_in_ddr(void) -+{ -+ panic("Mandates RNG support"); -+} -+#endif /*CFG_STM32_RNG*/ -+ -+/* Finalize the PM mailbox now that everything is loaded */ -+static void enable_pm_mailbox(unsigned int suspend) -+{ -+ struct pm_mailbox *mailbox = get_pm_mailbox(); -+ uint32_t magic = BOOT_API_A7_CORE0_MAGIC_NUMBER; -+ uint32_t hint = 0; -+ -+ assert(stm32_clock_is_enabled(BKPSRAM) && -+ stm32_clock_is_enabled(RTCAPB)); -+ -+ if (suspend) { -+ hint = virt_to_phys(&get_retram_resume_ctx()->resume_sequence); -+ } -+ -+ write32(magic, stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); -+ write32(hint, stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS)); -+ -+ mailbox->core0_resume_ep = hint; -+ mailbox->magic = STANDBY_CONTEXT_MAGIC; -+} -+ -+static void gate_pm_context_clocks(bool enable) -+{ -+ static bool clocks_enabled; -+ -+ if (enable) { -+ assert(!clocks_enabled); -+ stm32_clock_enable(BKPSRAM); -+ stm32_clock_enable(RTCAPB); -+ stm32_clock_enable(CRYP1); -+ clocks_enabled = true; -+ } else { -+ /* Suspended TEE RAM state left the clocks enabled */ -+ if (clocks_enabled) { -+ stm32_clock_disable(BKPSRAM); -+ stm32_clock_disable(RTCAPB); -+ stm32_clock_disable(CRYP1); -+ clocks_enabled = false; -+ } -+ } -+} -+ -+/* -+ * Context (TEE RAM content + peripherals) must be restored -+ * only if system may reach STANDBY state. -+ */ -+void stm32mp_pm_save_context(unsigned int soc_mode) -+{ -+ save_time(); -+ -+ if (!need_to_backup_cpu_context(soc_mode)) { -+ return; -+ } -+ -+ gate_pm_context_clocks(true); -+ load_earlyboot_pm_mailbox(); -+ save_soc_context(); -+ save_teeram_in_ddr(); -+ enable_pm_mailbox(1); -+} -+ -+void stm32mp_pm_restore_context(unsigned int soc_mode) -+{ -+ if (need_to_backup_cpu_context(soc_mode)) { -+ restore_soc_context(); -+ gate_pm_context_clocks(false); -+ } -+ -+ restore_time(); -+} -+ -+void stm32mp_pm_shutdown_context(void) -+{ -+ gate_pm_context_clocks(true); -+ load_earlyboot_pm_mailbox(); -+ enable_pm_mailbox(0); -+ gate_pm_context_clocks(false); -+} -+ -+static TEE_Result init_pm_support(void) -+{ -+ init_retram_resume_resources(); -+ -+ stm32mp_pm_wipe_context(); -+ -+ return TEE_SUCCESS; -+} -+driver_init(init_pm_support); -diff --git a/core/arch/arm/plat-stm32mp1/pm/context.h b/core/arch/arm/plat-stm32mp1/pm/context.h -new file mode 100644 -index 0000000..9070fac ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/context.h -@@ -0,0 +1,100 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#ifndef __STM32MP_PM_CONTEXT_H__ -+#define __STM32MP_PM_CONTEXT_H__ -+ -+#ifndef ASM -+#include -+#include -+#include -+#include -+#endif -+ -+#define PM_CTX_CCM_KEY_SIZE 32 -+#define PM_CTX_CCM_CTR1_SIZE 16 -+#define PM_CTX_CCM_B0_SIZE 16 -+#define PM_CTX_CCM_CTR0_SIZE 16 -+#define PM_CTX_CCM_TAG_SIZE 16 -+ -+#ifndef ASM -+/* -+ * All materials for the CCM sequence using CRYP support are preloaded -+ * in this specific structure. Note that the sequence does not use AAD. -+ * -+ * @key: AES key material buffer -+ * @ctr1: Preformatted 128bit CTR1 block -+ * @ctr1: Preformatted 128bit B0 block -+ * @ctr1: Preformatted 128bit CTR0 block -+ * @tag: Buffer where the generated CCM tag is stored -+ */ -+struct ccm_unpg_ctx { -+ uint32_t key[PM_CTX_CCM_KEY_SIZE / sizeof(uint32_t)]; -+ uint32_t ctr1[PM_CTX_CCM_CTR1_SIZE / sizeof(uint32_t)]; -+ uint32_t b0[PM_CTX_CCM_B0_SIZE / sizeof(uint32_t)]; -+ uint32_t ctr0[PM_CTX_CCM_CTR0_SIZE / sizeof(uint32_t)]; -+ uint32_t tag[PM_CTX_CCM_TAG_SIZE / sizeof(uint32_t)]; -+}; -+ -+/* -+ * This structure is used by pm_helpers.S at early resume from retention RAM. -+ * It is defined here and used by context_asm_defines.c to generate offset -+ * macros for the assembly implementation in pm_helpers.S. -+ * -+ * To lower the memory footprint of suspend sequence, The same function is -+ * used for encryption (executed from TEE RAM with MMU enabled) and for -+ * decryption (executed from BKPSRAM with MMU disabled). Therefore some -+ * required addresses are provided by the caller through this structure -+ * especially some SoC interface registers that are likely to have different -+ * physical and virtual addresses. -+ * -+ * @resume_pa: OP-TEE resume physical entry in TEE RAM (once restored) -+ * @teeram_bkp_pa: Physical base address in TEE RAM backup in DDR -+ * @cryp1_base: Base address of the CRYP1 registers (physical or virtual) -+ * @rcc_base: Base address of the RCC registers (physical or virtual) -+ * @stgen_base: Base address of the STGEN registers (physical or virtual) -+ * @stgen_cnt: STGEN cycle counter backup cell and measure of cycles spent -+ * @ccm_ref_tag: 128bit arrays storing tag generated during encryption -+ * @ccm_ctx: Structure storing CCM configuration and generated tag -+ * @resume_sequence: Code/data array for the BKPSRAM resume sequence -+ */ -+struct retram_resume_ctx { -+ uint32_t resume_pa; -+ uint32_t teeram_bkp_pa; -+ uint32_t cryp1_base; -+ uint32_t rcc_base; -+ uint32_t stgen_base; -+ uint32_t stgen_cnt; -+ uint8_t ccm_ref_tag[PM_CTX_CCM_TAG_SIZE]; -+ struct ccm_unpg_ctx ccm_ctx; -+ /* Last start the resume routine ARM (32bit) instructions sequence */ -+ uint32_t resume_sequence[]; -+}; -+ -+extern const uint8_t stm32mp_bkpsram_image_end[]; -+void stm32mp_bkpsram_resume(void); -+void stm32mp_sysram_resume(void); -+ -+void stm32mp_cpu_reset_state(void); -+ -+void stm32mp_pm_save_context(unsigned int soc_mode); -+void stm32mp_pm_restore_context(unsigned int soc_mode); -+void stm32mp_pm_shutdown_context(void); -+void stm32mp_pm_wipe_context(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); -+ -+uintptr_t stm32mp_pm_retram_resume_ep(void); -+ -+int stm32mp_ccm_encrypt_teeram(struct retram_resume_ctx *ctx, -+ void *dst, void *src, size_t size); -+int stm32mp_ccm_decrypt_teeram(struct retram_resume_ctx *ctx, -+ void *dst, void *src, size_t size); -+#endif /*ASM*/ -+ -+#endif /*__STM32MP_PM_CONTEXT_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c b/core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c -new file mode 100644 -index 0000000..34c797f ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/context_asm_defines.c -@@ -0,0 +1,28 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics -+ * Copyright (c) 2018, Linaro Limited -+ */ -+ -+#include -+ -+#include "context.h" -+ -+#define OFFSET_OF_CTX_STRUCT(_f) offsetof(struct retram_resume_ctx, _f) -+#define OFFSET_OF_CMM_CTX_STRUCT(_f) (OFFSET_OF_CTX_STRUCT(ccm_ctx) + \ -+ offsetof(struct ccm_unpg_ctx, _f)) -+DEFINES -+{ -+ DEFINE(PM_CTX_RESUME_PA, OFFSET_OF_CTX_STRUCT(resume_pa)); -+ DEFINE(PM_CTX_TEERAM_BKP_PA, OFFSET_OF_CTX_STRUCT(teeram_bkp_pa)); -+ DEFINE(PM_CTX_CRYP1_BASE, OFFSET_OF_CTX_STRUCT(cryp1_base)); -+ DEFINE(PM_CTX_RCC_BASE, OFFSET_OF_CTX_STRUCT(rcc_base)); -+ DEFINE(PM_CTX_STGEN_BASE, OFFSET_OF_CTX_STRUCT(stgen_base)); -+ DEFINE(PM_CTX_STGEN_CNT, OFFSET_OF_CTX_STRUCT(stgen_cnt)); -+ DEFINE(PM_CTX_CCM_KEY, OFFSET_OF_CMM_CTX_STRUCT(key)); -+ DEFINE(PM_CTX_CCM_CTR1, OFFSET_OF_CMM_CTX_STRUCT(ctr1)); -+ DEFINE(PM_CTX_CCM_B0, OFFSET_OF_CMM_CTX_STRUCT(b0)); -+ DEFINE(PM_CTX_CCM_CTR0, OFFSET_OF_CMM_CTX_STRUCT(ctr0)); -+ DEFINE(PM_CTX_CCM_TAG, OFFSET_OF_CMM_CTX_STRUCT(tag)); -+ DEFINE(PM_CTX_CCM_REF_TAG, OFFSET_OF_CTX_STRUCT(ccm_ref_tag)); -+} -diff --git a/core/arch/arm/plat-stm32mp1/pm/low_power.c b/core/arch/arm/plat-stm32mp1/pm/low_power.c -new file mode 100644 -index 0000000..bd28014 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/low_power.c -@@ -0,0 +1,431 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#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 "context.h" -+#include "power.h" -+ -+static uint8_t gicd_rcc_wakeup; -+static uint8_t gicc_pmr; -+static bool ddr_in_selfrefresh; -+ -+struct pwr_lp_config { -+ uint32_t pwr_cr1; -+ uint32_t pwr_mpucr; -+ const char *regul_suspend_node_name; -+}; -+ -+#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 = 0U, -+ .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", -+ }, -+}; -+ -+static void set_rcc_it_priority(uint8_t *it_prio, uint8_t *pmr) -+{ -+ *it_prio = itr_set_ipriority(RCC_WAKEUP_IT, GIC_HIGHEST_SEC_PRIORITY); -+ *pmr = itr_set_pmr(STM32MP_GIC_PRIORITY_CSTOP); -+} -+ -+static void restore_rcc_it_priority(uint8_t it_prio, uint8_t pmr) -+{ -+ (void)itr_set_ipriority(RCC_WAKEUP_IT, it_prio); -+ (void)itr_set_pmr(pmr); -+} -+ -+static void stm32_apply_pmic_suspend_config(uint32_t mode) -+{ -+ if (stm32mp_with_pmic()) { -+ const char *name = config_pwr[mode].regul_suspend_node_name; -+ -+ assert(mode < ARRAY_SIZE(config_pwr)); -+ stm32mp_get_pmic(); -+ stm32mp_pmic_apply_lp_config(name); -+ stm32mp_pmic_apply_boot_on_config(); // ??? should be done at wakeup only? -+ stm32mp_put_pmic(); -+ } -+} -+ -+#define CONSOLE_FLUSH_DELAY_MS 10 -+ -+#if TRACE_LEVEL >= TRACE_DEBUG -+static void wait_console_flushed(void) -+{ -+ console_flush(); -+ mdelay(CONSOLE_FLUSH_DELAY_MS); -+} -+#else -+static void wait_console_flushed(void) -+{ -+} -+#endif -+ -+static void cpu_wfi(void) -+{ -+ dsb(); -+ isb(); -+ wfi(); -+} -+ -+void stm32_pm_cpu_wfi(void) -+{ -+ wait_console_flushed(); -+ cpu_wfi(); -+} -+ -+/*If IWDG is not supported, provide a stubbed weak watchdog kicker */ -+void __weak stm32_iwdg_refresh(uint32_t __unused instance) -+{ -+} -+ -+/* -+ * stm32_enter_cstop - Prepare CSTOP mode -+ * -+ * @mode - Target low power mode -+ * Return 0 if succeed to suspend, non 0 else. -+ */ -+int stm32_enter_cstop(uint32_t mode) -+{ -+ uint32_t pwr_cr1 = config_pwr[mode].pwr_cr1; -+ uintptr_t pwr_base = stm32_pwr_base(); -+ uintptr_t rcc_base = stm32_rcc_base(); -+ int rc; -+ -+ stm32_apply_pmic_suspend_config(mode); -+ -+ if (stm32mp_with_pmic() && (mode == STM32_PM_CSTOP_ALLOW_LP_STOP)) { -+ pwr_cr1 |= PWR_CR1_LPCFG; -+ } -+ -+ /* Workaround for non secure cache issue: this should not be needed */ -+ dcache_op_all(DCACHE_OP_CLEAN_INV); -+ -+ /* 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_OFF, PWR_MPUCR_MASK, -+ config_pwr[mode].pwr_mpucr); -+ mmio_clrsetbits_32(pwr_base + PWR_CR1_OFF, 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(IWDG2_INST); -+ -+ set_rcc_it_priority(&gicd_rcc_wakeup, &gicc_pmr); -+ -+ rc = ddr_standby_sr_entry(NULL); -+ -+ ddr_in_selfrefresh = (rc == 0); -+ -+ return rc; -+} -+ -+/* -+ * stm32_exit_cstop - Exit from CSTOP mode -+ */ -+void stm32_exit_cstop(void) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ if (ddr_in_selfrefresh) { -+ if (ddr_sw_self_refresh_exit() != 0) { -+ panic(); -+ } -+ ddr_in_selfrefresh = false; -+ } -+ -+ restore_rcc_it_priority(gicd_rcc_wakeup, gicc_pmr); -+ -+ /* Disable STOP request */ -+ mmio_setbits_32(rcc_base + RCC_MP_SREQCLRR, -+ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1); -+ -+ /* Disable RCC Wake-up */ -+ mmio_clrbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF); -+ -+ dsb(); -+ isb(); -+} -+ -+static void __noreturn reset_cores(void) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ uint32_t reset_mask; -+ uint32_t target_mask; -+ -+ if (get_core_pos() == 0) { -+ reset_mask = RCC_MP_GRSTCSETR_MPUP0RST; -+ target_mask = TARGET_CPU1_GIC_MASK; -+ } else { -+ reset_mask = RCC_MP_GRSTCSETR_MPUP1RST; -+ target_mask = TARGET_CPU0_GIC_MASK; -+ } -+ -+ itr_raise_sgi(GIC_SEC_SGI_1, target_mask); -+ dcache_op_all(DCACHE_OP_CLEAN_INV); -+ write32(reset_mask, rcc_base + RCC_MP_GRSTCSETR); -+ cpu_wfi(); -+ panic("Cores reset"); -+} -+ -+/* -+ * stm32_pm_cpus_reset - Reset only cpus -+ */ -+void __noreturn stm32_cores_reset(void) -+{ -+ reset_cores(); -+} -+KEEP_PAGER(stm32_cores_reset); -+ -+/* -+ * stm32_enter_cstop_shutdown - Shutdown CPUs to target low power mode -+ * @mode - Target low power mode -+ */ -+void __noreturn stm32_enter_cstop_shutdown(uint32_t mode) -+{ -+ switch (mode) { -+ case STM32_PM_SHUTDOWN: -+ if (stm32mp_with_pmic()) { -+ wait_console_flushed(); -+ stm32mp_get_pmic(); -+ stpmic1_switch_off(); -+ udelay(100); -+ } -+ break; -+ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR: -+ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF: -+#ifdef STM32MP1_USE_MPU0_RESET -+ stm32mp_pm_shutdown_context(); -+ stm32_enter_cstop(mode); -+ cpu_wfi(); -+ reset_cores(); -+#else -+ if (stm32mp_with_pmic()) { -+ wait_console_flushed(); -+ stm32mp_get_pmic(); -+ stpmic1_switch_off(); -+ udelay(100); -+ } -+#endif -+ break; -+ default: -+ break; -+ } -+ -+ panic(); -+} -+ -+/* -+ * stm32_enter_cstop_reset - Reset CPUs to target low power mode -+ * @mode - Target low power mode -+ */ -+void __noreturn stm32_enter_cstop_reset(uint32_t mode) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ -+ switch (mode) { -+ case STM32_PM_SHUTDOWN: -+ write32(RCC_MP_GRSTCSETR_MPSYSRST, rcc_base + RCC_MP_GRSTCSETR); -+ udelay(100); -+ break; -+ default: -+#ifdef STM32MP1_USE_MPU0_RESET -+ reset_cores(); -+#else -+ IMSG("Forced system reset"); -+ wait_console_flushed(); -+ write32(RCC_MP_GRSTCSETR_MPSYSRST, rcc_base + RCC_MP_GRSTCSETR); -+ udelay(100); -+#endif -+ break; -+ } -+ -+ panic(); -+} -+ -+/* -+ * stm32_enter_csleep - enter CSLEEP state while WFI and exit in CRUN -+ * -+ * Configure PWR for CSLEEP state. CPU shall execute a WFI and return -+ * once a interrupt is pending. -+ */ -+void stm32_enter_csleep(void) -+{ -+ uintptr_t pwr_base = stm32_pwr_base(); -+ -+ mmio_clrsetbits_32(pwr_base + PWR_MPUCR_OFF, PWR_MPUCR_MASK, -+ config_pwr[STM32_PM_CSLEEP_RUN].pwr_mpucr); -+ mmio_clrsetbits_32(pwr_base + PWR_CR1_OFF, PWR_CR1_MASK, -+ config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1); -+ -+ stm32_pm_cpu_wfi(); -+} -+ -+/* -+ * Secure interrupts used in the low power sequences -+ */ -+#define GICC_IAR 0x00C -+#define GICC_IAR_IT_ID_MASK 0x3ff -+#define GICC_EOIR 0x010 -+ -+/* RCC Wakeup interrupt is used to wake from suspeneded mode */ -+static enum itr_return rcc_wakeup_it_handler(struct itr_handler *hdl __unused) -+{ -+ /* This interrupt is not expected to be handled */ -+ panic("RCC wakeup interrupt"); -+ return ITRR_HANDLED; -+} -+ -+static struct itr_handler rcc_wakeup_handler = { -+ .it = RCC_WAKEUP_IT, -+ .handler = rcc_wakeup_it_handler, -+}; -+KEEP_PAGER(rcc_wakeup_handler); -+ -+/* SGI9 (secure SGI 1) informs targeted CPU it shall reset */ -+static enum itr_return sgi9_it_handler(struct itr_handler *handler) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ uint32_t reset_mask; -+ uintptr_t gicc_base = get_gicc_base(); -+ -+ write32(handler->it, gicc_base + GICC_EOIR); -+ -+ if (get_core_pos() == 0) { -+ reset_mask = RCC_MP_GRSTCSETR_MPUP0RST; -+ } else { -+ reset_mask = RCC_MP_GRSTCSETR_MPUP1RST; -+ } -+ -+ dcache_op_all(DCACHE_OP_CLEAN_INV); -+ write32(reset_mask, rcc_base + RCC_MP_GRSTCSETR); -+ cpu_wfi(); -+ panic("Core reset"); -+ -+ return ITRR_HANDLED; -+} -+ -+static struct itr_handler sgi9_reset_handler = { -+ .it = GIC_SEC_SGI_1, -+ .handler = sgi9_it_handler, -+}; -+KEEP_PAGER(sgi9_reset_handler); -+ -+static TEE_Result init_low_power(void) -+{ -+ uintptr_t pwr_base = stm32_pwr_base(); -+ -+ itr_add(&rcc_wakeup_handler); -+ itr_enable(rcc_wakeup_handler.it); -+ -+ itr_add(&sgi9_reset_handler); -+ itr_enable(sgi9_reset_handler.it); -+ -+ /* Enable retention for BKPSRAM and BKPREG */ -+ io_mask32(pwr_base + PWR_CR2_OFF, -+ PWR_CR2_BREN | PWR_CR2_RREN, PWR_CR2_BREN | PWR_CR2_RREN); -+ -+ return TEE_SUCCESS; -+} -+service_init(init_low_power); -+ -+/* -+ * CPU low power sequences -+ */ -+void __noreturn stm32_pm_cpu_power_down_wfi(void) -+{ -+ if (get_core_pos() == 0) { -+ void (*reset_ep)(void) = stm32mp_sysram_resume; -+ -+ wait_console_flushed(); -+ -+ dsb(); -+ isb(); -+ wfi(); -+ /* STANDBY not reached: resume from retained SYSRAM */ -+ stm32_exit_cstop(); -+ stm32mp_cpu_reset_state(); -+ reset_ep(); -+ panic(); -+ } -+ -+ dcache_op_level1(DCACHE_OP_CLEAN); -+ write32(RCC_MP_GRSTCSETR_MPUP1RST, stm32_rcc_base() + RCC_MP_GRSTCSETR); -+ cpu_wfi(); -+ panic(); -+} -diff --git a/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -new file mode 100644 -index 0000000..91c7580 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -@@ -0,0 +1,635 @@ -+/* SPDX-License-Identifier: BSD-2-Clause */ -+/* -+ * Copyright (c) 2018, STMicroelectronics -+ * Copyright (c) 2017 NXP -+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "context.h" -+ -+/* -+ * Right bit shift distance to reach timeout from a 1s STGEN freq count -+ * Value N relates to 1000ms / 2^N, i.e 7 relates to 7.8125ms=~8ms -+ */ -+#define CCM_TIMEOUT_128MS 2 -+#define CCM_TIMEOUT_8MS 7 -+#define CCM_TIMEOUT_1MS 10 -+#define CCM_TIMEOUT_16US 16 -+#define CCM_TIMEOUT CCM_TIMEOUT_8MS -+ -+/* -+ * CRYP interface register used for AES CCM -+ */ -+#define CRYP_CR 0x000 -+#define CRYP_SR 0x004 -+#define CRYP_DIN 0x008 -+#define CRYP_DOUT 0x00c -+#define CRYP_KEYR_BASE 0x020 -+#define CRYP_IVR_BASE 0x040 -+ -+#define CRYP_CR_ALGODIR_DECRYPT BIT(2) -+#define CRYP_CR_ALGOMODE_MASK (BIT(19) | GENMASK_32(5, 3)) -+#define CRYP_CR_ALGOMODE(m) (((m & BIT(3)) << 16) | (m & 0x7) << 3) -+#define ALGOMODE_AES_CCM 0x9 -+#define CRYP_CR_DATATYPE_SHIFT 6 -+#define CRYP_CR_DATATYPE_8BIT (2 << CRYP_CR_DATATYPE_SHIFT) -+#define CRYP_CR_KEYSIZE_SHIFT 8 -+#define CRYP_CR_KEYSIZE_256BIT (2U << CRYP_CR_KEYSIZE_SHIFT) -+#define CRYP_CR_CRYPEN BIT(15) -+#define CRYP_CR_FFLUSH BIT(14) -+#define CRYP_CR_GCM_CCMPH_SHIFT 16 -+#define CRYP_CR_PHASE_MASK (0x3 << CRYP_CR_GCM_CCMPH_SHIFT) -+#define CRYP_CR_INIT_PHASE (0 << CRYP_CR_GCM_CCMPH_SHIFT) -+#define CRYP_CR_HEADER_PHASE (1 << CRYP_CR_GCM_CCMPH_SHIFT) -+#define CRYP_CR_PAYLOAD_PHASE (2 << CRYP_CR_GCM_CCMPH_SHIFT) -+#define CRYP_CR_FINAL_PHASE (3 << CRYP_CR_GCM_CCMPH_SHIFT) -+ -+#define CRYP_SR_BUSY BIT(4) -+#define CRYP_SR_OFFU BIT(3) -+#define CRYP_SR_OFNE BIT(2) -+#define CRYP_SR_IFNF BIT(1) -+#define CRYP_SR_IFEM BIT(0) -+ -+ /* Bound of the binary image loaded in retained memory */ -+ .global stm32mp_bkpsram_image_end -+ -+/* -+ * stm32mp_bkpsram_resume - Restore TEE RAM from backup memory and resume into -+ * -+ * This function executes at early resume from suspend state. It is the -+ * entrypoint of the OP-TEE provided to early boot stage when SoC wakes. -+ * This code is located in a retained memory, MMU disabled. This function -+ * shall restore TEE RAM content for OP-TEE to resume execution. Once -+ * TEE RAM is restored, this function branches to the resident resume entry -+ * point in TEE_RAM. This function and its resources shall execute in place. -+ */ -+FUNC stm32mp_bkpsram_resume , : -+UNWIND( .fnstart) -+UNWIND( .cantunwind) -+ /* -+ * Almost all sequences here expect PM context structure base address -+ * from CPU register r11. -+ */ -+ mov_imm r11, (BKPSRAM_BASE + BKPSRAM_PM_CONTEXT_OFFSET) -+ -+ /* stm32mp_ccm_teeram needs some HW interface base addresss */ -+ mov_imm r0, CRYP1_BASE -+ str r0, [r11, #PM_CTX_CRYP1_BASE] -+ mov_imm r0, RCC_BASE -+ str r0, [r11, #PM_CTX_RCC_BASE] -+ mov_imm r0, STGEN_BASE -+ str r0, [r11, #PM_CTX_STGEN_BASE] -+ -+ bl _clear_early_mailbox -+ bl _prepare_time -+ -+ mov_imm r0, TEE_RAM_START -+ ldr r1, [r11, #PM_CTX_TEERAM_BKP_PA] -+ mov_imm r2, TEE_RAM_PH_SIZE -+ mov_imm r3, 1 -+ bl stm32mp_ccm_teeram -+ cmp r0, #0 -+ bne _failed -+ -+ /* Compare the generated and reference tags */ -+ add r8, r11, #PM_CTX_CCM_TAG -+ add r9, r11, #PM_CTX_CCM_REF_TAG -+ ldm r8, {r2-r5} -+ ldm r9, {r6-r9} -+ mov r0, #0 -+ cmp r2, r6 -+ addeq r0, #1 -+ cmp r3, r7 -+ addeq r0, #1 -+ cmp r4, r8 -+ addeq r0, #1 -+ cmp r5, r9 -+ addeq r0, #1 -+ cmp r0, #4 -+ bne _failed -+ bl _save_resume_time -+ -+ /* Resume into the restored TEE RAM */ -+ ldr r1, [r11, #PM_CTX_RESUME_PA] -+ bx r1 -+ -+_failed: -+ /* Clear context including key and reference tag */ -+ mov r0, #0xa5 -+ mov_imm r12, BKPSRAM_PM_CONTEXT_SIZE -+ add r12, r11, r12 -+1: str r0, [r11], #4 -+ cmp r11, r12 -+ blt 1b -+ b . -+ -+ /* -+ * _clear_early_mailbox - Wipe mailbox in case of reset -+ * -+ * Sratches r0-r4. -+ * All other CPU registers are preserved. -+ */ -+_clear_early_mailbox: -+ /* Clear the backup registers (first enable RTCAPB clock) */ -+ mov_imm r0, (RCC_BASE + RCC_MP_APB5ENSETR) -+ mov_imm r2, RCC_MP_APB5ENSETR_RTCAPBEN -+ ldr r1, [r0] -+ ands r1, r1, r2 -+ moveq r1, r2 -+ movne r1, #0 -+ str r2, [r0] -+ mov_imm r2, (TAMP_BASE + TAMP_BKP_REGISTER_OFF) -+ mov_imm r3, (BCKR_CORE1_MAGIC_NUMBER * 4) -+ mov_imm r4, BOOT_API_A7_RESET_MAGIC_NUMBER -+ str r4, [r2, r3] -+ mov_imm r3, (BCKR_CORE1_BRANCH_ADDRESS * 4) -+ mov r4, #0 -+ str r4, [r2, r3] -+ /* Restore RTCAPB clock initial state */ -+ str r1, [r0, #RCC_MP_ENCLRR_OFFSET] -+ bx lr -+ -+ /* -+ * prepare_time - save/reset cycle counter to prevent later overflow -+ * -+ * Save current 32bit lower counter and reset to 0 so that later -+ * timeout test do not need to care about overflow. -+ * -+ * Expects r11 is context base and lr is return address. -+ * Scrathes r0-r2. -+ * All other CPU registers are preserved. -+ */ -+_prepare_time: -+ ldr r2, [r11, #PM_CTX_STGEN_BASE] -+ /* Disable STGEN counter */ -+ ldr r1, [r2, #CNTCR_OFFSET] -+ bic r1, r1, #CNTCR_EN -+ str r1, [r2, #CNTCR_OFFSET] -+1: ldr r1, [r2, #CNTSR_OFFSET] -+ tst r1, #CNTCR_EN -+ bne 1b -+ /* Save and reset STGEN counter */ -+ ldr r0, [r2, #CNTCVL_OFFSET] -+ str r0, [r11, #PM_CTX_STGEN_CNT] -+ mov r0, #0 -+ str r0, [r2, #CNTCVL_OFFSET] -+ ldr r0, [r2, #CNTCVU_OFFSET] -+ str r0, [r2, #CNTCVU_OFFSET] -+ /* Enable STGEN counter */ -+ ldr r1, [r2, #CNTCR_OFFSET] -+ orr r1, r1, #CNTCR_EN -+ str r1, [r2, #CNTCR_OFFSET] -+ bx lr -+ -+ /* -+ * save_resume_time - save time spent and restore STGEN cycle counter -+ * -+ * Restore STGEN counter to initial value incremented by the current -+ * count. Note 32bit upper may need to be incremented. -+ * -+ * Expects r11 is context base and lr is return address. -+ * Scrathes r0-r3. -+ * All other CPU registers are preserved. -+ */ -+_save_resume_time: -+ /* Compute update STGEN counter 32bit LSB value */ -+ ldr r2, [r11, #PM_CTX_STGEN_BASE] -+ ldr r0, [r11, #PM_CTX_STGEN_CNT] -+ ldr r3, [r2, #CNTCVL_OFFSET] -+ str r3, [r11, #PM_CTX_STGEN_CNT] -+ adds r0, r0, r3 -+ /* Disable STGEN */ -+ ldr r1, [r2, #CNTCR_OFFSET] -+ bic r1, r1, #CNTCR_EN -+ str r1, [r2, #CNTCR_OFFSET] -+1: ldr r1, [r2, #CNTSR_OFFSET] -+ tst r1, #CNTCR_EN -+ bne 1b -+ /* Update counter (increment 32bit MSB if requried) */ -+ str r0, [r2, #CNTCVL_OFFSET] -+ ldr r0, [r2, #CNTCVU_OFFSET] -+ addcs r0, r0, #1 -+ str r0, [r2, #CNTCVU_OFFSET] /* Write CNTCVU value ... */ -+ ldr r0, [r2, #CNTCVU_OFFSET] /* ... and wait it is set */ -+ /* Enable STGEN */ -+ ldr r0, [r2, #CNTCR_OFFSET] -+ orr r0, r0, #CNTCR_EN -+ str r0, [r2, #CNTCR_OFFSET] -+ bx lr -+ -+ /* -+ * _setup_cryp1 - Enable CRYP1 hardware: reset & clock -+ * _reset_cryp1 - Reset CRYP1 hardware -+ * -+ * Function call before and after CCM sequence. Note that the CRYP1 -+ * clock remain enabled. It is disabled later by the resume sequence. -+ * -+ * Expects r11 is context base and lr is return address. -+ * Scratches r0-r3. -+ */ -+_setup_cryp1: -+ ldr r1, [r11, #PM_CTX_RCC_BASE] -+ mov_imm r0, RCC_MP_AHB5ENSETR_CRYP1EN -+ str r0, [r1, #RCC_MP_AHB5ENSETR] -+ /* Intentionnally fall through reset_cryp1 */ -+_reset_cryp1: -+ ldr r3, [r11, #PM_CTX_RCC_BASE] -+ mov_imm r0, RCC_AHB5RSTSETR_CRYP1RST -+ str r0, [r3, #RCC_AHB5RSTSETR] -+1: ldr r1, [r3, #RCC_AHB5RSTSETR] -+ ands r1, r1, r0 -+ beq 1b -+ mov_imm r0, RCC_AHB5RSTSETR_CRYP1RST -+ str r0, [r3, #RCC_AHB5RSTCLRR] -+1: ldr r1, [r3, #RCC_AHB5RSTSETR] -+ ands r1, r1, r0 -+ bne 1b -+ bx lr -+ -+ /* -+ * _ccm_arm_8ms_timeout - Init 8ms threshold for _ccm_failed_on_timeout -+ * _ccm_fail_on_timeout - Check STGEN counter against timeout threshold -+ * -+ * These function are used by the macro wait_flag_timeout_8ms. The -+ * former loads the timeout in CPU register r0 while the later get the -+ * timeout counter threshold from CPU register r0. -+ * -+ * Expect r11 is context base and lr is return address. -+ * Scratch r0-r1. -+ * All other CPU registers are preserved. -+ */ -+_ccm_arm_8ms_timeout: -+ ldr r1, [r11, #PM_CTX_STGEN_BASE] -+ ldr r0, [r1, #CNTFID_OFFSET] -+ lsrs r0, r0, #CCM_TIMEOUT -+ moveq r0, #1 -+ ldr r1, [r1, #CNTCVL_OFFSET] -+ adds r0, r0, r1 -+ bcs _ccm_failed -+ bx lr -+ -+_ccm_fail_on_timeout: -+ ldr r1, [r11, #PM_CTX_STGEN_BASE] -+ ldr r1, [r1, #CNTCVL_OFFSET] -+ cmp r1, r0 -+ bge _ccm_failed -+ bx lr -+ -+ /* -+ * Macro WAIT_FLAG_TIMEOUT compares timeout threshold (r0) with -+ * current time and branches the CCM failure entry on timeout. -+ * It is assumed the 32bit timestamps cannot overflow. -+ */ -+ .macro WAIT_FLAG_TIMEOUT register_offset, bit_mask, awaited_mask -+ bl _ccm_arm_8ms_timeout -+ 1: -+ bl _ccm_fail_on_timeout -+ ldr r1, [r10, #(\register_offset)] -+ and r1, r1, #(\bit_mask) -+ cmp r1, #(\awaited_mask) -+ bne 1b -+ .endm -+ -+/* -+ * stm32mp_ccm_teeram - Size optimzed unpaged CCM encryption/decryption -+ * -+ * This sequence encrypts or decrypts a input block using AES CCM with a -+ * 256bit key and no AAD and generates the CCM tag. The key, CTR0, CTR1 -+ * and B0 block are read from PM context structure. The generated tag is -+ * stored in the PM context structure. -+ * -+ * This function is executed from TEE RAM during suspend sequence to generate -+ * the encrypted data and the tag. This function is also executed from BKPSRAM -+ * called with MMU disabled. Therefore this sequence shall be comply with -+ * position independent code constraints. -+ * -+ * Expects at entry: -+ * lr = caller return address -+ * r11 = retram_resume_ctx structure base address -+ * r0 = Destination buffer for the output data (ciphertext or plaintext) -+ * r1 = Source buffer for the input data (plaintext or ciphertext) -+ * r2 = Input (and output) data size in bytes -+ * r3 = 1 if decrypting, 0 if encrypting -+ */ -+stm32mp_ccm_teeram: -+ /* -+ * Use of the CPU registers in the whole stm32mp_ccm_teeram sequence -+ * -+ * sp: preserved, not used -+ * lr: scratch register used to call subroutines. -+ * r12: saves the caller link register for final return -+ * r11: context from BKPSRAM -+ * r10: CRYP1 base address -+ * r9: destination buffer -+ * r8: source buffer to cipher -+ * r7: data byte counter -+ * r0-r6 are scratch registers -+ */ -+ mov r12, lr -+ ldr r10, [r11, #PM_CTX_CRYP1_BASE] -+ mov r9, r0 -+ mov r8, r1 -+ mov r7, r2 -+ mov r6, r3 -+ -+ bl _setup_cryp1 -+ -+ mov_imm r0, (CRYP_CR_ALGOMODE(ALGOMODE_AES_CCM) | \ -+ CRYP_CR_DATATYPE_8BIT | CRYP_CR_FFLUSH | \ -+ CRYP_CR_KEYSIZE_256BIT) -+ cmp r6, #0 -+ orrne r0, r0, #CRYP_CR_ALGODIR_DECRYPT -+ str r0, [r10, #CRYP_CR] -+ -+ /* Check data alignment (addresses and size) */ -+ ands r0, r7, #0x0F -+ bne _ccm_failed -+ ands r0, r8, #0x03 -+ bne _ccm_failed -+ ands r0, r9, #0x03 -+ bne _ccm_failed -+ -+ ldr r0, [r11, #PM_CTX_CCM_KEY] -+ str r0, [r10, #CRYP_KEYR_BASE] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 4)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 4)] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 8)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 8)] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 12)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 12)] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 16)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 16)] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 20)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 20)] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 24)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 24)] -+ ldr r0, [r11, #(PM_CTX_CCM_KEY + 28)] -+ str r0, [r10, #(CRYP_KEYR_BASE + 28)] -+ -+ ldr r0, [r11, #PM_CTX_CCM_CTR1] -+ str r0, [r10, #CRYP_IVR_BASE] -+ ldr r0, [r11, #(PM_CTX_CCM_CTR1 + 4)] -+ str r0, [r10, #(CRYP_IVR_BASE + 4)] -+ ldr r0, [r11, #(PM_CTX_CCM_CTR1 + 8)] -+ str r0, [r10, #(CRYP_IVR_BASE + 8)] -+ ldr r0, [r11, #(PM_CTX_CCM_CTR1 + 12)] -+ str r0, [r10, #(CRYP_IVR_BASE + 12)] -+ -+ /* Setup CRYP for the CCM Init Phase */ -+ ldr r0, [r10, #CRYP_CR] -+ orr r0, r0, #(CRYP_CR_CRYPEN | CRYP_CR_INIT_PHASE) -+ str r0, [r10, #CRYP_CR] -+ ldr r0, [r10, #CRYP_CR] -+ -+ ldr r0, [r11, #PM_CTX_CCM_B0] -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r11, #(PM_CTX_CCM_B0 + 4)] -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r11, #(PM_CTX_CCM_B0 + 8)] -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r11, #(PM_CTX_CCM_B0 + 12)] -+ str r0, [r10, #CRYP_DIN] -+ -+ WAIT_FLAG_TIMEOUT CRYP_CR, CRYP_CR_CRYPEN, 0 -+ -+ /* Setup CRYP for the CCM Payload phase */ -+ ldr r0, [r10, #CRYP_CR] -+ bic r0, r0, #CRYP_CR_PHASE_MASK -+ orr r0, r0, #CRYP_CR_PAYLOAD_PHASE -+ orr r0, r0, #CRYP_CR_CRYPEN -+ str r0, [r10, #CRYP_CR] -+ ldr r0, [r10, #CRYP_CR] -+ -+_next_block: -+ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_IFEM, CRYP_SR_IFEM -+ -+ /* Feed input data, r8 stores the current source buffer */ -+ ldr r0, [r8], #4 -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r8], #4 -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r8], #4 -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r8], #4 -+ str r0, [r10, #CRYP_DIN] -+ -+ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_OFNE, CRYP_SR_OFNE -+ -+ /* Store output data, r9 stores the current source buffer */ -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r9], #4 -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r9], #4 -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r9], #4 -+ /* Before last 32bit word, the output FIFO shall not be empty */ -+ ldr r0, [r10, #CRYP_SR] -+ ands r0, r0, #CRYP_SR_OFNE -+ beq _ccm_failed -+ /* After last 32bit word for this 128block, FIFO shall be empty */ -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r9], #4 -+ ldr r0, [r10, #CRYP_SR] -+ ands r0, r0, #CRYP_SR_OFNE -+ bne _ccm_failed -+ -+ /* Another round if remaining data */ -+ subs r7, r7, #16 -+ bne _next_block; -+ -+ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_BUSY, 0 -+ -+ /* -+ * Data processing completed, now remains the tag generation. -+ * Here expect SR[IFNF]=SR[OFNE]=1 and all others bits are 0. -+ */ -+ ldr r0, [r10, #CRYP_SR] -+ cmp r0, #(CRYP_SR_IFEM | CRYP_SR_IFNF) -+ bne _ccm_failed -+ -+ /* Setup CRYP1 for the CCM Final Phase */ -+ ldr r0, [r10, #CRYP_CR] -+ bic r0, r0, #CRYP_CR_CRYPEN -+ str r0, [r10, #CRYP_CR] -+ ldr r0, [r10, #CRYP_CR] -+ bic r0, r0, #CRYP_CR_PHASE_MASK -+ bic r0, r0, #CRYP_CR_ALGODIR_DECRYPT -+ orr r0, r0, #CRYP_CR_FINAL_PHASE -+ orr r0, r0, #CRYP_CR_CRYPEN -+ str r0, [r10, #CRYP_CR] -+ ldr r0, [r10, #CRYP_CR] -+ -+ /* Load CTR0 to generate the tag */ -+ ldr r0, [r11, #PM_CTX_CCM_CTR0] -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 4)] -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 8)] -+ str r0, [r10, #CRYP_DIN] -+ ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 12)] -+ str r0, [r10, #CRYP_DIN] -+ -+ WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_OFNE, CRYP_SR_OFNE -+ -+ /* Store generated tag in the PM_CTX structure */ -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r11, #PM_CTX_CCM_TAG] -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r11, #(PM_CTX_CCM_TAG + 4)] -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r11, #(PM_CTX_CCM_TAG + 8)] -+ /* Before last 32bit word, the output FIFO shall not be empty */ -+ ldr r0, [r10, #CRYP_SR] -+ ands r0, r0, #CRYP_SR_OFNE -+ beq _ccm_failed -+ /* After last 32bit word for this 128block, FIFO shall be empty */ -+ ldr r0, [r10, #CRYP_DOUT] -+ str r0, [r11, #(PM_CTX_CCM_TAG + 12)] -+ ldr r0, [r10, #CRYP_SR] -+ ands r0, r0, #CRYP_SR_OFNE -+ bne _ccm_failed -+ -+ /* Successful return */ -+ bl _reset_cryp1 -+ mov r0, #0 -+ bx r12 -+ -+_ccm_failed: -+ bl _reset_cryp1 -+ mov r0, #1 -+ bx r12 -+ -+/* End address of the PIC resume sequence copy in retained RAM */ -+stm32mp_bkpsram_image_end: -+ nop -+ -+UNWIND( .fnend) -+END_FUNC stm32mp_bkpsram_resume -+ -+/* -+ * int stm32mp_ccm_encrypt_teeram(ctx, dst, src, len) -+ */ -+FUNC stm32mp_ccm_encrypt_teeram , : -+UNWIND( .fnstart) -+ push {r4-r12, lr} -+UNWIND( .save {r4-r12, lr}) -+ mov r11, r0 -+ mov r0, r1 -+ mov r1, r2 -+ mov r2, r3 -+ mov r3, #0 -+ push {r0-r3} -+ bl _prepare_time -+ pop {r0-r3} -+ bl stm32mp_ccm_teeram -+ bl _save_resume_time -+ pop {r4-r12, pc} -+UNWIND( .fnend) -+END_FUNC stm32mp_ccm_encrypt_teeram -+ -+/* -+ * int stm32mp_ccm_decrypt_teeram(ctx, cryp_base, dst, src) -+ */ -+FUNC stm32mp_ccm_decrypt_teeram , : -+UNWIND( .fnstart) -+ push {r4-r12, lr} -+UNWIND( .save {r4-r12, lr}) -+ mov r11, r0 -+ mov r0, r1 -+ mov r1, r2 -+ mov r2, r3 -+ mov r3, #1 -+ push {r0-r3} -+ bl _prepare_time -+ pop {r0-r3} -+ bl stm32mp_ccm_teeram -+ bl _save_resume_time -+ pop {r4-r12, pc} -+UNWIND( .fnend) -+END_FUNC stm32mp_ccm_decrypt_teeram -+ -+/* -+ * stm32mp_sysram_resume - Resume OP-TEE execution -+ * -+ * This function is the entry point of OP-TEE core resume sequence in the TEE -+ * RAM. When TEE RAM is lost during a power cycle, stm32mp_bkpsram_resume() is -+ * called to restore TEE RAM content and branch to this stm32mp_sysram_resume() -+ * routine. -+ * -+ * This function calls the OP-TEE core generic PM resume API -+ * sm_pm_cpu_resume(). -+ */ -+FUNC stm32mp_sysram_resume, : -+UNWIND( .fnstart) -+UNWIND( .cantunwind) -+ /* Invalidate the data cache */ -+ mov r0, #0 @ ; write the cache size selection register to be -+ write_csselr r0 @ ; sure we address the data cache -+ isb @ ; isb to sync the change to the cachesizeid reg -+ -+ mov r0, #0 @ ; set way number to 0 -+_inv_nextway: -+ mov r1, #0 @ ; set line number (=index) to 0 -+_inv_nextline: -+ orr r2, r0, r1 @ ; construct way/index value -+ write_dcisw r2 @ ; inval data or unified cache line by set/way -+ add r1, r1, #1 << LINE_FIELD_OFFSET @ ; increment the index -+ cmp r1, #1 << LINE_FIELD_OVERFLOW @ ; overflow out of set field? -+ bne _inv_nextline -+ add r0, r0, #1 << WAY_FIELD_OFFSET @ ; increment the way number -+ cmp r0, #0 @ ; overflow out of way field? -+ bne _inv_nextway -+ -+ dsb -+ isb -+ -+ /* Resume sequence executes in Monitor mode */ -+ cps #CPSR_MODE_MON -+ -+ blx plat_cpu_reset_early -+ b sm_pm_cpu_resume -+UNWIND( .fnend) -+END_FUNC stm32mp_sysram_resume -+ -+/* -+ * stm32mp_cpu_reset_state - set CPU in a reset like state -+ * -+ * Disable CPU env (interrupts, cache, SMP, MMU) and return. -+ * Preserve the execution mode in CPSR. -+ */ -+FUNC stm32mp_cpu_reset_state, : -+UNWIND( .fnstart) -+ push {r12, lr} -+UNWIND( .save {r12, lr}) -+ -+ cpsid aif -+ -+ bl psci_armv7_cpu_off -+ -+ write_bpiall -+ isb -+ dsb -+ read_sctlr r0 -+ bic r0, r0, #SCTLR_M -+ bic r0, r0, #SCTLR_I -+ write_sctlr r0 -+ isb -+ dsb sy -+ -+ pop {r12, pc} -+UNWIND( .fnend) -+END_FUNC stm32mp_cpu_reset_state -diff --git a/core/arch/arm/plat-stm32mp1/pm/power.h b/core/arch/arm/plat-stm32mp1/pm/power.h -new file mode 100644 -index 0000000..21ca7be ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/power.h -@@ -0,0 +1,26 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#ifndef __STM32MP_PM_POWER_H__ -+#define __STM32MP_PM_POWER_H__ -+ -+#include -+#include -+#include -+ -+bool need_to_backup_cpu_context(unsigned int soc_mode); -+ -+void stm32_enter_csleep(void); -+ -+int stm32_enter_cstop(uint32_t mode); -+void stm32_exit_cstop(void); -+ -+void stm32_enter_cstop_shutdown(uint32_t mode) __noreturn; -+void stm32_enter_cstop_reset(uint32_t mode) __noreturn; -+ -+void stm32_pm_cpu_power_down_wfi(void) __noreturn; -+void stm32_pm_cpu_wfi(void); -+ -+#endif /*__STM32MP_PM_POWER_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/pm/power_config.c b/core/arch/arm/plat-stm32mp1/pm/power_config.c -new file mode 100644 -index 0000000..7845ede ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/power_config.c -@@ -0,0 +1,212 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CFG_DT -+#include -+#endif -+ -+#include "context.h" -+#include "power.h" -+ -+#define DT_PWR_COMPAT "st,stm32mp1-pwr" -+#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes" -+#define SYSTEM_OFF_MODE "system_off_soc_mode" -+ -+static uint32_t deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR; -+static uint32_t system_off_mode = STM32_PM_SHUTDOWN; -+ -+/* Default initialized to NOT supported until set from DT directives */ -+static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE]; -+ -+/* Init with all domains ON */ -+static bool stm32mp1_pm_dom[STM32MP1_PD_MAX_PM_DOMAIN] = { -+ [STM32MP1_PD_VSW] = false, -+ [STM32MP1_PD_CORE_RET] = false, -+ [STM32MP1_PD_CORE] = false -+}; -+ -+bool need_to_backup_cpu_context(unsigned int soc_mode) -+{ -+ switch (soc_mode) { -+ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR: -+ return true; -+ case STM32_PM_CSLEEP_RUN: -+ case STM32_PM_CSTOP_ALLOW_STOP: -+ case STM32_PM_CSTOP_ALLOW_LP_STOP: -+ case STM32_PM_CSTOP_ALLOW_LPLV_STOP: -+ case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF: -+ case STM32_PM_SHUTDOWN: -+ return false; -+ default: -+ EMSG("Invalid mode 0x%x", soc_mode); -+ panic(); -+ } -+} -+ -+#ifdef CFG_DT -+static int dt_get_pwr_node(void *fdt) -+{ -+ return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+} -+#endif -+ -+static bool 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 &= stm32mp1_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 -1; -+ } -+ -+ stm32mp1_pm_dom[domain] = status; -+ -+ return 0; -+} -+ -+#ifdef CFG_DT -+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, -+ &supported[0], count) < 0) { -+ panic("PWR DT"); -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (supported[i] >= STM32_PM_MAX_SOC_MODE) { -+ panic("Invalid mode"); -+ } -+ stm32mp1_supported_soc_modes[supported[i]] = true; -+ } -+} -+#endif -+ -+static bool is_supported_mode(uint32_t soc_mode) -+{ -+ assert(soc_mode < ARRAY_SIZE(stm32mp1_supported_soc_modes)); -+ return stm32mp1_supported_soc_modes[soc_mode] == 1; -+} -+ -+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_suspend_mode; -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) && -+ ((!get_pm_domain_state(STM32MP1_PD_CORE_RET)) || -+ (!is_supported_mode(mode)))) { -+ mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP; -+ } -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP) && -+ ((!get_pm_domain_state(STM32MP1_PD_CORE)) || -+ (!is_supported_mode(mode)))) { -+ mode = STM32_PM_CSTOP_ALLOW_LP_STOP; -+ } -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_LP_STOP) && -+ (!is_supported_mode(mode))) { -+ mode = STM32_PM_CSTOP_ALLOW_STOP; -+ } -+ -+ if ((mode == STM32_PM_CSTOP_ALLOW_STOP) && -+ (!is_supported_mode(mode))) { -+ mode = STM32_PM_CSLEEP_RUN; -+ } -+ -+ 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 -1; -+ } -+ -+ if (psci_mode == PSCI_MODE_SYSTEM_SUSPEND) { -+ deepest_suspend_mode = soc_mode; -+ } -+ -+ if (psci_mode == PSCI_MODE_SYSTEM_OFF) { -+ system_off_mode = soc_mode; -+ } -+ -+ return 0; -+} -+ -+#ifdef CFG_DT -+static TEE_Result stm32mp1_init_lp_states(void) -+{ -+ void *fdt; -+ int pwr_node = -1; -+ const fdt32_t *cuint = NULL; -+ -+ fdt = get_dt_blob(); -+ if (fdt != NULL) { -+ pwr_node = dt_get_pwr_node(fdt); -+ } -+ if (pwr_node >= 0) { -+ cuint = fdt_getprop(fdt, pwr_node, SYSTEM_OFF_MODE, NULL); -+ } -+ if ((fdt == NULL) || (pwr_node < 0) || (cuint == NULL)) { -+ IMSG("No power configuration found in DT"); -+ return TEE_SUCCESS; -+ } -+ -+ system_off_mode = fdt32_to_cpu(*cuint); -+ -+ /* Initialize suspend support to the deepest possible mode */ -+ deepest_suspend_mode = STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR; -+ -+ save_supported_mode(fdt, pwr_node); -+ -+ DMSG("Power configuration: shutdown to %u, suspend to %u", -+ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF), -+ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND)); -+ -+ return TEE_SUCCESS; -+} -+service_init(stm32mp1_init_lp_states); -+#endif -diff --git a/core/arch/arm/plat-stm32mp1/pm/psci.c b/core/arch/arm/plat-stm32mp1/pm/psci.c -new file mode 100644 -index 0000000..6e8219e ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/psci.c -@@ -0,0 +1,427 @@ -+// SPDX-License-Identifier: BSD-2-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#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 "context.h" -+#include "power.h" -+ -+/* -+ * SMP boot support and access to the mailbox -+ */ -+#define CORE_OFF 0 -+#define CORE_AWAKE 1 -+#define CORE_RET 2 -+#define CORE_ON 3 -+ -+static int core_state[CFG_TEE_CORE_NB_CORE]; -+static unsigned int __maybe_unused state_lock = SPINLOCK_UNLOCK; -+ -+static uint32_t __maybe_unused lock_state_access(void) -+{ -+ return may_spin_lock(&state_lock); -+} -+ -+static void __maybe_unused unlock_state_access(uint32_t exceptions) -+{ -+ may_spin_unlock(&state_lock, exceptions); -+} -+ -+int psci_affinity_info(uint32_t affinity, uint32_t lowest_affinity_level) -+{ -+ unsigned int pos = get_core_pos_mpidr(affinity); -+ -+ DMSG("core %zu, state %u", pos, core_state[pos]); -+ -+ if ((pos >= CFG_TEE_CORE_NB_CORE) || -+ (lowest_affinity_level > PSCI_AFFINITY_LEVEL_ON)) { -+ return PSCI_RET_INVALID_PARAMETERS; -+ } -+ -+ switch (core_state[pos]) { -+ case CORE_OFF: -+ case CORE_RET: -+ return PSCI_AFFINITY_LEVEL_OFF; -+ case CORE_AWAKE: -+ return PSCI_AFFINITY_LEVEL_ON_PENDING; -+ case CORE_ON: -+ return PSCI_AFFINITY_LEVEL_ON; -+ default: -+ panic(); -+ } -+} -+ -+#if CFG_TEE_CORE_NB_CORE == 1 -+/* -+ * Function called when a CPU is booted through the OP-TEE. -+ * All cores shall register when online. -+ */ -+void stm32mp_register_online_cpu(void) -+{ -+ assert((core_state[0] == CORE_OFF) || -+ (core_state[0] == CORE_RET)); -+ core_state[0] = CORE_ON; -+} -+#else -+void stm32mp_register_online_cpu(void) -+{ -+ size_t pos = get_core_pos(); -+ uint32_t excep = lock_state_access(); -+ -+ if (pos == 0) { -+ assert((core_state[pos] == CORE_OFF) || -+ (core_state[pos] == CORE_RET)); -+ } else { -+ if (core_state[pos] != CORE_AWAKE) { -+ core_state[pos] = CORE_OFF; -+ unlock_state_access(excep); -+ stm32_pm_cpu_power_down_wfi(); -+ /* No return */ -+ } -+ } -+ -+ core_state[pos] = CORE_ON; -+ unlock_state_access(excep); -+} -+ -+#define GICD_SGIR 0xF00 -+static void raise_sgi0_as_secure(void) -+{ -+ dsb_ishst(); -+ write32(GIC_NON_SEC_SGI_0 | SHIFT_U32(TARGET_CPU1_GIC_MASK, 16), -+ get_gicd_base() + GICD_SGIR); -+} -+ -+static void release_secondary_early_hpen(size_t pos __unused) -+{ -+ /* Need to send SIG#0 over Group0 after individual core 1 reset */ -+ raise_sgi0_as_secure(); -+ udelay(20); -+ -+ stm32_clock_enable(RTCAPB); -+ -+ write32(TEE_LOAD_ADDR, -+ stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS)); -+ write32(BOOT_API_A7_CORE1_MAGIC_NUMBER, -+ stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); -+ -+ stm32_clock_disable(RTCAPB); -+ -+ dsb_ishst(); -+ itr_raise_sgi(GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); -+} -+ -+/* Override default psci_cpu_on() with platform specific sequence */ -+int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) -+{ -+ size_t pos = get_core_pos_mpidr(core_id); -+ uint32_t excep; -+ int rc; -+ -+ if (!pos || pos >= CFG_TEE_CORE_NB_CORE) -+ return PSCI_RET_INVALID_PARAMETERS; -+ -+ DMSG("core %zu, ns_entry 0x%" PRIx32 ", state %u", -+ pos, entry, core_state[pos]); -+ -+ excep = lock_state_access(); -+ -+ switch (core_state[pos]) { -+ case CORE_ON: -+ rc = PSCI_RET_ALREADY_ON; -+ break; -+ case CORE_AWAKE: -+ rc = PSCI_RET_ON_PENDING; -+ break; -+ case CORE_RET: -+ rc = PSCI_RET_DENIED; -+ break; -+ case CORE_OFF: -+ core_state[pos] = CORE_AWAKE; -+ rc = PSCI_RET_SUCCESS; -+ break; -+ default: -+ panic(); -+ } -+ -+ unlock_state_access(excep); -+ -+ if (rc == PSCI_RET_SUCCESS) { -+ generic_boot_set_core_ns_entry(pos, entry, context_id); -+ release_secondary_early_hpen(pos); -+ } -+ -+ return rc; -+} -+ -+/* Override default psci_cpu_off() with platform specific sequence */ -+int psci_cpu_off(void) -+{ -+ unsigned int pos = get_core_pos(); -+ uint32_t excep; -+ -+ if (pos == 0) { -+ EMSG("PSCI_CPU_OFF not supported for core0, use system_off"); -+ return PSCI_RET_INTERNAL_FAILURE; -+ } -+ -+ DMSG("core %u", pos); -+ -+ excep = lock_state_access(); -+ -+ assert(core_state[pos] == CORE_ON); -+ core_state[pos] = CORE_OFF; -+ -+ unlock_state_access(excep); -+ -+ /* Enable BKPREG access for the disabled CPU */ -+ stm32_clock_enable(RTCAPB); -+ -+ thread_mask_exceptions(THREAD_EXCP_ALL); -+ stm32_pm_cpu_power_down_wfi(); -+ panic(); -+} -+#endif -+ -+static int enter_cstop_suspend(unsigned int soc_mode) -+{ -+ int rc = 1; -+ -+ if (read_isr() != 0) { -+ return rc; -+ } -+ -+ if (stm32_enter_cstop(soc_mode)) { -+ goto resume; -+ } -+ -+ if (need_to_backup_cpu_context(soc_mode)) { -+ stm32_pm_cpu_power_down_wfi(); -+ } else { -+ stm32_pm_cpu_wfi(); -+ rc = 0; -+ } -+ -+resume: -+ stm32_exit_cstop(); -+ -+ return rc; -+} -+ -+static int plat_suspend(uint32_t arg) -+{ -+ unsigned int soc_mode = arg; -+ size_t pos = get_core_pos(); -+ int rc = 1; -+ -+ if (read_isr() != 0) { -+ return rc; -+ } -+ -+ /* No need to lock state access as CPU is alone when here */ -+ assert(core_state[pos] == CORE_ON); -+ core_state[pos] = CORE_RET; -+ -+ stm32mp_pm_save_context(soc_mode); -+ -+ rc = enter_cstop_suspend(soc_mode); -+ -+ stm32mp_pm_restore_context(soc_mode); -+ stm32mp_pm_wipe_context(); -+ -+ assert(core_state[pos] == CORE_RET); -+ core_state[pos] = CORE_ON; -+ -+ return rc; -+} -+ -+static void plat_resume(uint32_t arg) -+{ -+ unsigned int soc_mode = arg; -+ -+ plat_cpu_reset_late(); -+ main_init_gic(); -+ -+ assert(core_state[get_core_pos()] == CORE_ON); -+ -+ stm32mp_pm_restore_context(soc_mode); -+} -+ -+#if !defined(CFG_STM32_RNG) -+static bool plat_can_suspend(void) -+{ -+ /* RNG is mandated for suspending TEE RAM content */ -+ return false; -+} -+#else -+#if CFG_TEE_CORE_NB_CORE == 1 -+static bool plat_can_suspend(void) -+{ -+ return true; -+} -+#else /*CFG_TEE_CORE_NB_CORE==1*/ -+static bool plat_can_suspend(void) -+{ -+ size_t pos = get_core_pos(); -+ size_t n; -+ uint32_t excep; -+ bool rc = true; -+ -+ excep = lock_state_access(); -+ -+ for (n = 0; n < ARRAY_SIZE(core_state); n++) { -+ if (n == pos) { -+ continue; -+ } -+ if (core_state[n] == CORE_AWAKE) { -+ /* State core as lost and proceed suspend */ -+ core_state[n] = CORE_OFF; -+ } -+ if (core_state[n] != CORE_OFF) { -+ rc = false; -+ } -+ } -+ -+ unlock_state_access(excep); -+ -+ return rc; -+} -+#endif /*CFG_TEE_CORE_NB_CORE==1*/ -+#endif /*CFG_STM32_RNG*/ -+ -+/* Override default psci_system_suspend() with platform specific sequence */ -+int psci_system_suspend(uintptr_t entry, uint32_t context_id __unused, -+ struct sm_nsec_ctx *nsec) -+{ -+ int ret = PSCI_RET_INVALID_PARAMETERS; -+ uint32_t soc_mode; -+ int pos = get_core_pos(); -+ -+ DMSG("core %u", pos); -+ -+ if (!plat_can_suspend()) { -+ return PSCI_RET_DENIED; -+ } -+ -+ soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND); -+ -+ switch (soc_mode) { -+ case STM32_PM_CSLEEP_RUN: -+ stm32_enter_csleep(); -+ nsec->mon_lr = (uint32_t)entry; -+ return PSCI_RET_SUCCESS; -+ case STM32_PM_SHUTDOWN: -+ stm32_enter_cstop_shutdown(soc_mode); -+ panic(); -+ default: -+ /* Others are suspended mode: at least some context to backup */ -+ break; -+ } -+ -+ assert(cpu_mmu_enabled() && core_state[pos] == CORE_ON); -+ -+ if (need_to_backup_cpu_context(soc_mode)) { -+ sm_save_unbanked_regs(&nsec->ub_regs); -+ /* -+ * sm_pm_cpu_suspend(arg, func) saves the CPU core context in TEE RAM -+ * then calls func(arg) to run the platform lower power sequence. -+ * -+ * If platform fails to suspend, sm_pm_cpu_suspend() returns with a -+ * non null return code. When sm_pm_cpu_suspend() returns 0 platform -+ * context must be restored. -+ */ -+ ret = sm_pm_cpu_suspend((uint32_t)soc_mode, plat_suspend); -+ if (ret == 0) { -+ plat_resume((uint32_t)soc_mode); -+ sm_restore_unbanked_regs(&nsec->ub_regs); -+ } -+ } else { -+ ret = plat_suspend((uint32_t)soc_mode); -+ } -+ -+ if (ret == 0) { -+ nsec->mon_lr = (uint32_t)entry; -+ IMSG("Resumed"); -+ return PSCI_RET_SUCCESS; -+ } -+ -+ return PSCI_RET_INTERNAL_FAILURE; -+} -+ -+/* Override default psci_system_off() with platform specific sequence */ -+void __noreturn psci_system_off(void) -+{ -+ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF); -+ -+ DMSG("core %u", get_core_pos()); -+ -+ stm32_enter_cstop_shutdown(soc_mode); -+} -+ -+/* Override default psci_system_reset() with platform specific sequence */ -+void __noreturn psci_system_reset(void) -+{ -+ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF); -+ -+ DMSG("core %u", get_core_pos()); -+ -+ stm32_enter_cstop_reset(soc_mode); -+} -+ -+void __noreturn stm32mp_platform_reset(int __unused cpu) -+{ -+ psci_system_reset(); -+} -+ -+/* Override default psci_cpu_on() with platform supported features */ -+int psci_features(uint32_t psci_fid) -+{ -+ switch (psci_fid) { -+ case PSCI_PSCI_FEATURES: -+ case PSCI_VERSION: -+#if CFG_TEE_CORE_NB_CORE > 1 -+ case PSCI_CPU_ON: -+ case PSCI_CPU_OFF: -+#endif -+ case PSCI_SYSTEM_SUSPEND: -+ case PSCI_SYSTEM_RESET: -+ case PSCI_SYSTEM_OFF: -+ return PSCI_RET_SUCCESS; -+ default: -+ return PSCI_RET_NOT_SUPPORTED; -+ } -+} -+ -+/* Override default psci_version() to enable PSCI_VERSION_1_0 API */ -+uint32_t psci_version(void) -+{ -+ return PSCI_VERSION_1_0; -+} -+ -diff --git a/core/arch/arm/plat-stm32mp1/pm/sub.mk b/core/arch/arm/plat-stm32mp1/pm/sub.mk -new file mode 100644 -index 0000000..d8930a4 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/pm/sub.mk -@@ -0,0 +1,7 @@ -+asm-defines-y += context_asm_defines.c -+ -+srcs-y += context.c -+srcs-y += low_power.c -+srcs-y += pm_helpers.S -+srcs-y += power_config.c -+srcs-$(CFG_PSCI_ARM32) += psci.c -diff --git a/core/arch/arm/plat-stm32mp1/reset.S b/core/arch/arm/plat-stm32mp1/reset.S -index 69ab151..abf8b9a 100644 ---- a/core/arch/arm/plat-stm32mp1/reset.S -+++ b/core/arch/arm/plat-stm32mp1/reset.S -@@ -23,8 +23,34 @@ UNWIND( .fnstart) - mov_imm r1, STM32MP1_NSACR_PRESERVE_MASK - and r0, r0, r1 - write_nsacr r0 -+ isb -+ -+ read_actlr r0 -+ orr r0, r0, #ACTLR_SMP -+ write_actlr r0 -+ -+ /* -+ * Always reset CNTVOFF for the dear non secure world. -+ * This operation requires being in Monitor mode and -+ * non secure state. -+ */ -+ mrs r1, cpsr -+ cps #CPSR_MODE_MON -+ isb -+ -+ read_scr r2 -+ orr r0, r2, #SCR_NS -+ write_scr r0 -+ isb -+ -+ mov r0, #0 -+ write_cntvoff r0, r0 - -+ write_scr r2 - isb -- bx lr -+ msr cpsr, r1 -+ isb -+ -+ bx lr - UNWIND( .fnend) - END_FUNC plat_cpu_reset_early -diff --git a/core/arch/arm/plat-stm32mp1/scripts/stm32image.py b/core/arch/arm/plat-stm32mp1/scripts/stm32image.py -index 55363af..2def5b8 100755 ---- a/core/arch/arm/plat-stm32mp1/scripts/stm32image.py -+++ b/core/arch/arm/plat-stm32mp1/scripts/stm32image.py -@@ -1,4 +1,4 @@ --#!/usr/bin/env python3 -+#!/usr/bin/env python - # SPDX-License-Identifier: BSD-2-Clause - # - # Copyright (c) 2017-2018, STMicroelectronics -@@ -35,7 +35,7 @@ def stm32image_checksum(dest_fd, sizedest): - return csum - - --def stm32image_set_header(dest_fd, load, entry): -+def stm32image_set_header(dest_fd, load, entry, bintype): - sizedest = get_size(dest_fd) - - checksum = stm32image_checksum(dest_fd, sizedest) -@@ -68,11 +68,12 @@ def stm32image_set_header(dest_fd, load, entry): - dest_fd.write(b'\x00' * 64) - - # Padding -- dest_fd.write(b'\x00' * 84) -+ dest_fd.write(b'\x00' * 83) -+ dest_fd.write(struct.pack(' -+#include "bsec_svc.h" -+#include "stm32mp1_smc.h" -+ -+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t *out) -+{ -+ int result; -+ uint32_t tmp; -+ -+ if (bsec_check_nsec_access_rights(x2) != BSEC_OK) { -+ return BSEC_ERROR; -+ } -+ -+ switch (x1) { -+ case STM32_SIP_BSEC_READ_SHADOW: -+ result = bsec_read_otp(out, x2); -+ FMSG("read shadow @%" PRIx32 " = %" PRIx32, x2, *out); -+ break; -+ case STM32_SIP_BSEC_PROG_OTP: -+ FMSG("program @%" PRIx32, x2); -+ result = bsec_program_otp(x3, x2); -+ break; -+ case STM32_SIP_BSEC_WRITE_SHADOW: -+ FMSG("write shadow @%" PRIx32, x2); -+ result = bsec_write_otp(x3, x2); -+ break; -+ case STM32_SIP_BSEC_READ_OTP: -+ result = bsec_read_otp(&tmp, x2); -+ if (result != BSEC_OK) { -+ break; -+ } -+ -+ result = bsec_shadow_register(x2); -+ if (result != BSEC_OK) { -+ break; -+ } -+ -+ result = bsec_read_otp(out, x2); -+ if (result != BSEC_OK) { -+ break; -+ } -+ -+ result = bsec_write_otp(tmp, x2); -+ FMSG("read @%" PRIx32 " = %" PRIx32, x2, *out); -+ break; -+ default: -+ EMSG("Invalid %" PRIx32, x1); -+ result = BSEC_ERROR; -+ break; -+ } -+ -+ switch (result) { -+ case BSEC_OK: -+ return STM32_SIP_OK; -+ case BSEC_INVALID_PARAM: -+ return STM32_SIP_INVALID_PARAMS; -+ default: -+ return STM32_SIP_FAILED; -+ } -+} -diff --git a/core/arch/arm/plat-stm32mp1/service/bsec_svc.h b/core/arch/arm/plat-stm32mp1/service/bsec_svc.h -new file mode 100644 -index 0000000..4f1babe ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/bsec_svc.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics -+ */ -+ -+#ifndef __STM32MP1_BSEC_SVC_H__ -+#define __STM32MP1_BSEC_SVC_H__ -+ -+#include -+ -+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, -+ uint32_t *ret_otp_value); -+ -+#endif /*__STM32MP1_BSEC_SVC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/service/low_power_svc.c b/core/arch/arm/plat-stm32mp1/service/low_power_svc.c -new file mode 100644 -index 0000000..626f390 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/low_power_svc.c -@@ -0,0 +1,153 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "stm32mp1_smc.h" -+#include "low_power_svc.h" -+#include "../pm/power.h" -+#include "../pm/context.h" -+ -+ -+#undef DDR_SR_TEST -+ -+#ifdef DDR_SR_TEST -+uint32_t sr_mode_scv_handler(uint32_t __maybe_unused x1, uint32_t x2) -+{ -+ unsigned int mode = x2; -+ -+ DMSG("DDR selfrefresh mode 0x%" PRIx32 ", 0x%" PRIx32, mode, x1); -+ -+ switch (mode) { -+ case STM32_SIP_SR_MODE_SSR: -+ ddr_sr_mode_ssr(); -+ break; -+ case STM32_SIP_SR_MODE_ASR: -+ ddr_sr_mode_asr(); -+ break; -+ case STM32_SIP_SR_MODE_HSR: -+ ddr_sr_mode_hsr(); -+ break; -+ default: -+ return STM32_SIP_INVALID_PARAMS; -+ } -+ -+ return STM32_SIP_OK; -+} -+#else -+uint32_t sr_mode_scv_handler(uint32_t __unused x1, uint32_t __unused x2) -+{ -+ return STM32_SIP_NOT_SUPPORTED; -+} -+#endif -+ -+uint32_t cstop_scv_handler(struct sm_ctx __unused *ctx, uint32_t __unused x1, -+ uint32_t __unused x2, uint32_t __unused x3) -+{ -+ DMSG("core %u", get_core_pos()); -+ -+ stm32mp1_set_lp_deepest_soc_mode(PSCI_MODE_SYSTEM_SUSPEND, -+ STM32_PM_CSTOP_ALLOW_LPLV_STOP); -+ -+ return (psci_system_suspend(ctx->nsec.mon_lr, 0, &ctx->nsec) == 0) ? -+ STM32_SIP_OK : STM32_SIP_FAILED; -+} -+ -+uint32_t standby_scv_handler(struct sm_ctx *ctx, uint32_t __unused x1, -+ uint32_t __unused x2, uint32_t x3) -+{ -+ uint32_t nsec_resume_ep = x3; -+ -+ DMSG("core %u", get_core_pos()); -+ -+ if (nsec_resume_ep == 0U) { -+ shutdown_scv_handler(); -+ panic(); -+ } -+ -+ stm32mp1_set_lp_deepest_soc_mode(PSCI_MODE_SYSTEM_SUSPEND, -+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR); -+ -+ return (psci_system_suspend(nsec_resume_ep, 0, &ctx->nsec) == 0) ? -+ STM32_SIP_OK : STM32_SIP_FAILED; -+} -+ -+uint32_t shutdown_scv_handler(void) -+{ -+ DMSG("core %u", get_core_pos()); -+ -+ if (!stm32mp_with_pmic()) { -+ return STM32_SIP_NOT_SUPPORTED; -+ } -+ -+ psci_system_off(); -+ panic(); -+} -+ -+uint32_t pm_domain_scv_handler(uint32_t id, uint32_t enable) -+{ -+ unsigned int pd = id; -+ -+ DMSG("%sable PD %u", enable != 0 ? "En" : "Dis", pd); -+ -+ switch (pd) { -+ case STM32MP1_PD_VSW: -+ case STM32MP1_PD_CORE_RET: -+ case STM32MP1_PD_CORE: -+ break; -+ default: -+ return STM32_SIP_INVALID_PARAMS; -+ } -+ -+ stm32mp1_set_pm_domain_state(pd, enable); -+ -+ return STM32_SIP_OK; -+} -+ -+#ifdef CFG_TEE_CORE_DEBUG -+uint32_t pm_set_lp_state_scv_handler(uint32_t request, uint32_t state) -+{ -+ uint32_t power_mode; -+ -+ switch (request) { -+ case STM32_OEM_LP_FORCE_SUSPEND_PARAMS: -+ DMSG("Set suspend mode to %u", state); -+ power_mode = PSCI_MODE_SYSTEM_SUSPEND; -+ break; -+ case STM32_OEM_LP_FORCE_OFF_PARAMS: -+ DMSG("Set off mode to %u", state); -+ power_mode = PSCI_MODE_SYSTEM_OFF; -+ break; -+ default: -+ return STM32_OEM_INVALID_PARAMS; -+ } -+ -+ if (stm32mp1_set_lp_deepest_soc_mode(power_mode, state) < 0) { -+ return STM32_OEM_FAILED; -+ } -+ -+ return STM32_OEM_OK; -+} -+#else -+uint32_t pm_set_lp_state_scv_handler(uint32_t __unused mode, -+ uint32_t __unused state) -+{ -+ return STM32_SIP_NOT_SUPPORTED; -+} -+#endif -diff --git a/core/arch/arm/plat-stm32mp1/service/low_power_svc.h b/core/arch/arm/plat-stm32mp1/service/low_power_svc.h -new file mode 100644 -index 0000000..5681ea2 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/low_power_svc.h -@@ -0,0 +1,22 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2018, STMicroelectronics -+ */ -+ -+#ifndef LOW_POWER_SVC_H -+#define LOW_POWER_SVC_H -+ -+#include -+#include -+ -+uint32_t sr_mode_scv_handler(uint32_t x1, uint32_t x2); -+uint32_t cstop_scv_handler(struct sm_ctx *nsec, -+ uint32_t x1, uint32_t x2, uint32_t x3); -+uint32_t standby_scv_handler(struct sm_ctx *nsec, -+ uint32_t x1, uint32_t x2, uint32_t x3); -+uint32_t shutdown_scv_handler(void); -+uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2); -+ -+uint32_t pm_set_lp_state_scv_handler(uint32_t x1, uint32_t x2); -+ -+#endif /* LOW_POWER_SVC_H */ -diff --git a/core/arch/arm/plat-stm32mp1/service/pwr_svc.c b/core/arch/arm/plat-stm32mp1/service/pwr_svc.c -new file mode 100644 -index 0000000..9c314b2 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/pwr_svc.c -@@ -0,0 +1,117 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "pwr_svc.h" -+#include "stm32mp1_smc.h" -+ -+struct pwr_reg_prop { -+ uint32_t offset; -+ uint32_t mask; -+}; -+ -+#define PWR_ALLOWED_MASK(_off, _mask) { .offset = (_off), .mask = (_mask), } -+ -+static const struct pwr_reg_prop allowed_regs[] = { -+ PWR_ALLOWED_MASK(PWR_CR3_OFF, PWR_CR3_VBE | PWR_CR3_VBRS | -+ PWR_CR3_USB33DEN | -+ PWR_CR3_REG18EN | PWR_CR3_REG11EN), -+ PWR_ALLOWED_MASK(PWR_WKUPCR_OFF, PWR_WKUPCR_MASK), -+ PWR_ALLOWED_MASK(PWR_MPUWKUPENR_OFF, PWR_MPUWKUPENR_MASK), -+}; -+ -+static unsigned int lock = SPINLOCK_UNLOCK; -+ -+static uint32_t pwr_regs_lock(void) -+{ -+ return may_spin_lock(&lock); -+} -+ -+static void pwr_regs_unlock(uint32_t exceptions) -+{ -+ may_spin_unlock(&lock, exceptions); -+} -+ -+uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) -+{ -+ uint32_t req = x1; -+ uint32_t offset = x2; -+ uint32_t value = x3; -+ uint32_t va; -+ uint32_t allowed; -+ uint32_t i; -+ uint32_t ret; -+ uint32_t exc; -+ -+ /* -+ * Argument x2 can be either the register physical address of the -+ * register offset toward PWR_BASE. -+ */ -+ if ((offset & ~PWR_OFFSET_MASK) != 0) { -+ if ((offset & ~PWR_OFFSET_MASK) != PWR_BASE) { -+ return STM32_SIP_INVALID_PARAMS; -+ } -+ -+ offset &= PWR_OFFSET_MASK; -+ } -+ -+ DMSG_RAW("PWR service: %s 0x%" PRIx32 " at offset 0x%" PRIx32, -+ req == STM32_SIP_REG_WRITE ? "write" : -+ req == STM32_SIP_REG_SET ? "set" : "clear", -+ value, offset); -+ -+ exc = pwr_regs_lock(); -+ -+ for (i = 0; i < ARRAY_SIZE(allowed_regs); i++) { -+ if (offset != allowed_regs[i].offset) { -+ continue; -+ } -+ -+ va = stm32_pwr_base() + offset; -+ allowed = allowed_regs[i].mask; -+ value &= allowed; -+ -+ switch (req) { -+ case STM32_SIP_REG_WRITE: -+ io_mask32_stm32shregs(va, value, allowed); -+ FMSG("wrt off %" PRIx32 "=%" PRIx32 " => %" PRIx32, -+ offset, value, read32(va)); -+ ret = STM32_SIP_OK; -+ break; -+ case STM32_SIP_REG_SET: -+ io_mask32_stm32shregs(va, value, value); -+ FMSG("set off %" PRIx32 "=%" PRIx32 " => %" PRIx32, -+ offset, value, read32(va)); -+ ret = STM32_SIP_OK; -+ break; -+ case STM32_SIP_REG_CLEAR: -+ io_mask32_stm32shregs(va, 0, value); -+ FMSG("clr off %" PRIx32 "=%" PRIx32 " => %" PRIx32, -+ offset, value, read32(va)); -+ ret = STM32_SIP_OK; -+ break; -+ default: -+ ret = STM32_SIP_INVALID_PARAMS; -+ } -+ -+ pwr_regs_unlock(exc); -+ -+ return ret; -+ } -+ -+ pwr_regs_unlock(exc); -+ -+ return STM32_SIP_INVALID_PARAMS; -+} -diff --git a/core/arch/arm/plat-stm32mp1/service/pwr_svc.h b/core/arch/arm/plat-stm32mp1/service/pwr_svc.h -new file mode 100644 -index 0000000..011cac4 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/pwr_svc.h -@@ -0,0 +1,11 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#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/core/arch/arm/plat-stm32mp1/service/rcc_svc.c b/core/arch/arm/plat-stm32mp1/service/rcc_svc.c -new file mode 100644 -index 0000000..7bdaea8 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/rcc_svc.c -@@ -0,0 +1,440 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "rcc_svc.h" -+#include "stm32mp1_smc.h" -+ -+#define STD_REG 0 -+#define SET_REG 1 -+#define CLR_REG 2 -+ -+static void shared_clk_request(uint32_t request, -+ uint32_t offset, uint32_t value) -+{ -+ unsigned int id; -+ unsigned int bit; -+ uint32_t enable_bits = 0; -+ int clr_std_set = STD_REG; -+ -+ switch (request) { -+ case STM32_SIP_REG_WRITE: -+ case STM32_SIP_REG_SET: -+ case STM32_SIP_REG_CLEAR: -+ break; -+ default: -+ return; -+ } -+ -+ switch (offset) { -+ case RCC_MP_APB5ENSETR: -+ clr_std_set = SET_REG; -+ /* Non secure backup registers requires RTCAPB clock */ -+ enable_bits |= RCC_MP_APB5ENSETR_RTCAPBEN; -+ break; -+ case RCC_MP_APB5ENCLRR: -+ clr_std_set = CLR_REG; -+ /* Non secure backup registers requires RTCAPB clock */ -+ enable_bits |= RCC_MP_APB5ENSETR_RTCAPBEN; -+ break; -+ -+ case RCC_MP_AHB5ENSETR: -+ clr_std_set = SET_REG; -+ if (stm32mp_gpio_bank_is_shared(GPIO_BANK_Z)) { -+ enable_bits |= RCC_MP_AHB5ENSETR_GPIOZEN; -+ } -+ break; -+ case RCC_MP_AHB5ENCLRR: -+ clr_std_set = CLR_REG; -+ if (stm32mp_gpio_bank_is_shared(GPIO_BANK_Z)) { -+ enable_bits |= RCC_MP_AHB5ENSETR_GPIOZEN; -+ } -+ break; -+ default: -+ return; -+ } -+ -+ if ((clr_std_set != STD_REG) && (request == STM32_SIP_REG_CLEAR)) -+ return; -+ -+ /* -+ * Parse bit that relate to a functional clock. -+ * Call stm32mp1_clk_enable/disable_non_secure() for that clock -+ * according to request (write/set/clear) and target register -+ * (write or set/clear). -+ */ -+ for (bit = 0; enable_bits && bit < 32; bit++) { -+ -+ if (!(BIT(bit) & enable_bits)) -+ continue; -+ -+ id = stm32mp1_clk_rcc2id(offset, bit); -+ if (id == ~0U) -+ panic(); -+ -+ switch (clr_std_set) { -+ case SET_REG: -+ if (BIT(bit) & value) { -+ DMSG("Enable non-secure clock %u", id); -+ stm32mp1_clk_enable_non_secure(id); -+ } -+ break; -+ case CLR_REG: -+ if (BIT(bit) & value) { -+ DMSG("Disable non-secure clock %u", id); -+ stm32mp1_clk_disable_non_secure(id); -+ } -+ break; -+ default: -+ /* Standard registers case */ -+ switch (request) { -+ case STM32_SIP_REG_WRITE: -+ if (BIT(bit) & value) { -+ DMSG("Enable non-secure clock %u", id); -+ stm32mp1_clk_enable_non_secure(id); -+ } else { -+ DMSG("Disable non-secure clock %u", id); -+ stm32mp1_clk_disable_non_secure(id); -+ } -+ break; -+ case STM32_SIP_REG_SET: -+ if (BIT(bit) & value) { -+ DMSG("Enable non-secure clock %u", id); -+ stm32mp1_clk_enable_non_secure(id); -+ } -+ break; -+ case STM32_SIP_REG_CLEAR: -+ if (BIT(bit) & value) { -+ DMSG("Disable non-secure clock %u", id); -+ stm32mp1_clk_disable_non_secure(id); -+ } -+ break; -+ default: -+ return; -+ } -+ break; -+ } -+ -+ enable_bits &= ~BIT(bit); -+ } -+} -+ -+static bool offset_is_clear_register(uint32_t offset) -+{ -+ switch (offset) { -+ case RCC_OCENCLRR: -+ case RCC_MP_SREQCLRR: -+ case RCC_APB5RSTCLRR: -+ case RCC_AHB5RSTCLRR: -+ case RCC_MP_APB5ENCLRR: -+ case RCC_MP_AHB5ENCLRR: -+ case RCC_MP_APB5LPENCLRR: -+ case RCC_MP_AHB5LPENCLRR: -+ case RCC_MP_IWDGFZCLRR: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static void access_allowed_mask(uint32_t request, uint32_t offset, -+ uint32_t value, uint32_t allowed_mask) -+{ -+ uint32_t va = stm32_rcc_base() + offset; -+ -+ switch (request) { -+ case STM32_SIP_REG_WRITE: -+ if (offset_is_clear_register(offset)) { -+ /* CLR registers show the SET state, not the CLR state */ -+ write32(value & allowed_mask, va); -+ } else { -+ io_mask32_stm32shregs(va, value, allowed_mask); -+ } -+ FMSG("wrt 0x%" PRIx32 "=0x%" PRIx32 " => 0x%" PRIx32, -+ offset, value, read32(va)); -+ break; -+ -+ case STM32_SIP_REG_SET: -+ if (offset_is_clear_register(offset)) { -+ /* CLR registers show the SET state, not the CLR state */ -+ write32(value & allowed_mask, va); -+ } else { -+ io_mask32_stm32shregs(va, value, value & allowed_mask); -+ } -+ FMSG("set 0x%" PRIx32 "=0x%" PRIx32 " => 0x%" PRIx32, -+ offset, value, read32(va)); -+ break; -+ -+ case STM32_SIP_REG_CLEAR: -+ if (offset_is_clear_register(offset)) { -+ /* Nothing to do on CLR registers */ -+ } else { -+ io_mask32_stm32shregs(va, 0, value & allowed_mask); -+ } -+ FMSG("clear 0x%" PRIx32 "=0x%" PRIx32 " => 0x%" PRIx32, -+ offset, value, read32(va)); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static void raw_allowed_access_request(uint32_t request, -+ uint32_t offset, uint32_t value) -+{ -+ uint32_t allowed_mask = 0; -+ -+ /* Use UINT32_MAX if no secure restriction on register access */ -+ switch (offset) { -+ case RCC_OCENSETR: -+ case RCC_OCENCLRR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_HSI)) { -+ allowed_mask |= RCC_OCENR_HSION | RCC_OCENR_HSIKERON; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_CSI)) { -+ allowed_mask |= RCC_OCENR_CSION | RCC_OCENR_CSIKERON; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_HSE)) { -+ allowed_mask |= RCC_OCENR_HSEON | RCC_OCENR_HSEKERON | -+ RCC_OCENR_HSEBYP | RCC_OCENR_HSECSSON | -+ RCC_OCENR_DIGBYP; -+ } -+ break; -+ -+ case RCC_HSICFGR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_HSI)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ -+ case RCC_CSICFGR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_CSI)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ -+ case RCC_MP_CIER: -+ case RCC_MP_CIFR: -+ /* RCC_MP_CIFR_xxxRDYF matches CIER and CIFR bit mapping */ -+ allowed_mask |= RCC_MP_CIFR_WKUPF | RCC_MP_CIFR_PLL4DYF; -+ -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_LSI)) { -+ allowed_mask |= RCC_MP_CIFR_LSIRDYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_LSE)) { -+ allowed_mask |= RCC_MP_CIFR_LSERDYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_HSI)) { -+ allowed_mask |= RCC_MP_CIFR_HSIRDYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_HSE)) { -+ allowed_mask |= RCC_MP_CIFR_HSERDYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_CSI)) { -+ allowed_mask |= RCC_MP_CIFR_CSIRDYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL1)) { -+ allowed_mask |= RCC_MP_CIFR_PLL1DYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL2)) { -+ allowed_mask |= RCC_MP_CIFR_PLL2DYF; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL3)) { -+ allowed_mask |= RCC_MP_CIFR_PLL3DYF; -+ } -+ break; -+ -+ case RCC_PLL1CR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL1_P)) { -+ allowed_mask |= RCC_PLLNCR_DIVPEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL1_Q)) { -+ allowed_mask |= RCC_PLLNCR_DIVQEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL1_R)) { -+ allowed_mask |= RCC_PLLNCR_DIVREN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL1)) { -+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY | -+ RCC_PLLNCR_SSCG_CTRL; -+ } -+ break; -+ -+ case RCC_PLL2CR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL2_P)) { -+ allowed_mask |= RCC_PLLNCR_DIVPEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL2_Q)) { -+ allowed_mask |= RCC_PLLNCR_DIVQEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL2_R)) { -+ allowed_mask |= RCC_PLLNCR_DIVREN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL2)) { -+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY | -+ RCC_PLLNCR_SSCG_CTRL; -+ } -+ break; -+ -+ case RCC_PLL3CR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL3_P)) { -+ allowed_mask |= RCC_PLLNCR_DIVPEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL3_Q)) { -+ allowed_mask |= RCC_PLLNCR_DIVQEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL3_R)) { -+ allowed_mask |= RCC_PLLNCR_DIVREN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_PLL3)) { -+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY | -+ RCC_PLLNCR_SSCG_CTRL; -+ } -+ break; -+ -+ case RCC_MP_BOOTCR: /* Allowed MPU/MCU reboot cfg */ -+ case RCC_MP_GCR: /* Allowed MPU/MCU reboot cfg */ -+ case RCC_MP_GRSTCSETR: /* Allowed MCU and system reset */ -+ case RCC_BR_RSTSCLRR: /* Allowed system reset status */ -+ case RCC_MC_RSTSCLRR: /* Allowed system reset status */ -+ case RCC_MP_RSTSCLRR: /* Allowed system reset status */ -+ allowed_mask = UINT32_MAX; -+ break; -+ case RCC_APB5RSTSETR: -+ case RCC_APB5RSTCLRR: -+ case RCC_MP_APB5ENSETR: -+ case RCC_MP_APB5ENCLRR: -+ case RCC_MP_APB5LPENSETR: -+ case RCC_MP_APB5LPENCLRR: -+ /* -+ * SPI6/I2C4/I2C6/USART1/RTC/IWDG1 resources may be non secure. -+ * TZPC/TZC/BSEC/STGEN resources are secure only. -+ * Bit mask RCC_MP_APB5ENSETR_xxxEN fits EN, RST and LPEN. -+ */ -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_SPI6)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_SPI6EN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_I2C4)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_I2C4EN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_I2C6)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_I2C6EN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_USART1)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_USART1EN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_IWDG1)) { -+ allowed_mask |= RCC_MP_APB5ENSETR_IWDG1APBEN; -+ } -+ break; -+ case RCC_AHB5RSTSETR: -+ case RCC_AHB5RSTCLRR: -+ case RCC_MP_AHB5ENSETR: -+ case RCC_MP_AHB5ENCLRR: -+ case RCC_MP_AHB5LPENSETR: -+ case RCC_MP_AHB5LPENCLRR: -+ /* -+ * RNG1/HASH1/CRYP1/GPIOZ/AXIMC resources are accessible if related -+ * BKPSRAM resources are reserved to secure services. -+ * Bit mask RCC_MP_AHB5ENSETR_xxxEN fits EN, RST and LPEN. -+ */ -+ if (stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_GPIOZEN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_CRYP1)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_CRYP1EN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_HASH1)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_HASH1EN; -+ } -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_RNG1)) { -+ allowed_mask |= RCC_MP_AHB5ENSETR_RNG1EN; -+ } -+ break; -+ case RCC_RTCDIVR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_RTC)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_I2C46CKSELR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_I2C4) && -+ stm32mp_periph_is_non_secure(STM32MP1_SHRES_I2C6)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_SPI6CKSELR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_SPI6)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_UART1CKSELR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_USART1)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_RNG1CKSELR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_RNG1)) { -+ allowed_mask = UINT32_MAX; -+ } -+ break; -+ case RCC_MP_IWDGFZSETR: -+ case RCC_MP_IWDGFZCLRR: -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_IWDG1)) { -+ allowed_mask |= RCC_MP_IWDGFZSETR_IWDG1; -+ } -+ allowed_mask |= RCC_MP_IWDGFZSETR_IWDG2; -+ break; -+ default: -+ return; -+ } -+ -+ if (allowed_mask != 0U) { -+ access_allowed_mask(request, offset, value, allowed_mask); -+ } -+} -+ -+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; -+ -+ /* -+ * Argument x2 can be either the register physical address of the -+ * register offset toward RCC_BASE. -+ */ -+ if ((offset & ~RCC_OFFSET_MASK) != 0) { -+ if ((offset & ~RCC_OFFSET_MASK) != RCC_BASE) { -+ return STM32_SIP_INVALID_PARAMS; -+ } -+ -+ offset &= RCC_OFFSET_MASK; -+ } -+ -+ DMSG_RAW("RCC service: %s 0x%" PRIx32 " at offset 0x%" PRIx32, -+ request == STM32_SIP_REG_WRITE ? "write" : -+ request == STM32_SIP_REG_SET ? "set" : "clear", -+ value, offset); -+ -+ /* Some clocks may be managed by some secure services */ -+ shared_clk_request(request, offset, value); -+ -+ /* RCC controls for non secure resource may be accessed straight */ -+ raw_allowed_access_request(request, offset, value); -+ -+ return STM32_SIP_OK; -+} -diff --git a/core/arch/arm/plat-stm32mp1/service/rcc_svc.h b/core/arch/arm/plat-stm32mp1/service/rcc_svc.h -new file mode 100644 -index 0000000..f198ebd ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/rcc_svc.h -@@ -0,0 +1,11 @@ -+/* SPDX-License-Identifier: BSD-2-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#ifndef __RCC_SVC_H__ -+#define __RCC_SVC_H__ -+ -+uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3); -+ -+#endif /*__RCC_SVC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h b/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h -new file mode 100644 -index 0000000..2db7b10 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h -@@ -0,0 +1,211 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics -+ * Copyright (c) 2018, Linaro Limited -+ */ -+#ifndef __STM32MP1_SMC_H__ -+#define __STM32MP1_SMC_H__ -+ -+/* -+ * SIP Functions -+ */ -+#define STM32_SIP_SVC_VERSION_MAJOR 0x0 -+#define STM32_SIP_SVC_VERSION_MINOR 0x1 -+ -+/* SIP service generic return codes */ -+#define STM32_SIP_OK 0x0 -+#define STM32_SIP_NOT_SUPPORTED 0xffffffffU -+#define STM32_SIP_FAILED 0xfffffffeU -+#define STM32_SIP_INVALID_PARAMS 0xfffffffdU -+ -+/* -+ * SMC function IDs for STM32 Service queries -+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF -+ * like this is defined in SMC calling Convention by ARM -+ * for SiP (silicon Partner) -+ * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html -+ */ -+ -+/* -+ * SIP function STM32_SIP_FUNC_CALL_COUNT -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) dummy value 0 -+ */ -+#define STM32_SIP_FUNC_CALL_COUNT 0xff00 -+ -+/* -+ * SIP function STM32_SIP_FUNC_UID -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) Lowest 32bit of the stm32mp1 SIP service UUID -+ * Argument a1: (output) Next 32bit of the stm32mp1 SIP service UUID -+ * Argument a2: (output) Next 32bit of the stm32mp1 SIP service UUID -+ * Argument a3: (output) Last 32bit of the stm32mp1 SIP service UUID -+ */ -+#define STM32_SIP_FUNC_UID 0xff01 -+ -+/* -+ * SIP function STM32_SIP_FUNC_VERSION -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) STM32 SIP service major -+ * Argument a1: (output) STM32 SIP service minor -+ */ -+#define STM32_SIP_FUNC_VERSION 0xff03 -+ -+/* -+ * SIP function STM32_SIP_FUNC_RCC -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (input) Service ID (STM32_SIP_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_SIP_FUNC_RCC 0x1000 -+ -+/* -+ * SIP function STM32_SIP_FUNC_PWR -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (input) Service ID (STM32_SIP_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_SIP_FUNC_PWR 0x1001 -+ -+/* Service ID for STM32_SIP_FUNC_RCC/_PWR */ -+#define STM32_SIP_REG_READ 0x0 -+#define STM32_SIP_REG_WRITE 0x1 -+#define STM32_SIP_REG_SET 0x2 -+#define STM32_SIP_REG_CLEAR 0x3 -+ -+/* -+ * SIP functions STM32_SIP_FUNC_BSEC -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (input) Clock ID (from DT clock bindings) -+ */ -+#define STM32_SIP_RCC_CAL 0x1002 -+ -+/* -+ * SIP functions STM32_SIP_FUNC_BSEC -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (input) Service ID (STM32_SIP_BSEC_xxx) -+ * Argument a2: (input) OTP index -+ * (output) OTP read value, if applicable -+ * Argument a3: (input) OTP value if applicable -+ */ -+#define STM32_SIP_FUNC_BSEC 0x1003 -+ -+/* Service ID for STM32_SIP_FUNC_BSEC */ -+#define STM32_SIP_BSEC_READ_SHADOW 0x1 -+#define STM32_SIP_BSEC_PROG_OTP 0x2 -+#define STM32_SIP_BSEC_WRITE_SHADOW 0x3 -+#define STM32_SIP_BSEC_READ_OTP 0x4 -+ -+/* -+ * SIP functions STM32_SIP_FUNC_SR_MODE -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (unused) -+ * Argument a2: (input) Target selfrefresh mode -+ */ -+#define STM32_SIP_FUNC_SR_MODE 0x1004 -+ -+/* DDR Self-Refresh modes */ -+#define STM32_SIP_SR_MODE_SSR 0x0 -+#define STM32_SIP_SR_MODE_ASR 0x1 -+#define STM32_SIP_SR_MODE_HSR 0x2 -+ -+/* -+ * SIP functions STM32_SIP_FUNC_CSTOP -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (unused) -+ * Argument a2: (unused) -+ * Argument a3: (input) Target SoC mode -+ */ -+#define STM32_SIP_FUNC_CSTOP 0x1005 -+ -+/* Valid SoC modes used for CSTOP, */ -+#define STM32_SIP_CSLEEP_RUN 0x0 -+#define STM32_SIP_CSTOP_ALLOW_STOP 0x1 -+#define STM32_SIP_CSTOP_ALLOW_LP_STOP 0x2 -+#define STM32_SIP_CSTOP_ALLOW_LPLV_STOP 0x3 -+#define STM32_SIP_CSTOP_ALLOW_STANDBY 0x4 -+#define STM32_SIP_CSTOP_ALLOW_STANDBY_DDR_OFF 0x5 -+#define STM32_SIP_CSTOP_SHUTDOWN 0x6 -+ -+/* -+ * SIP functions STM32_SIP_FUNC_STANDBY -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a1: (unused) -+ * Argument a2: (unused) -+ * Argument a3: (input) non null only for DDR off standby -+ */ -+#define STM32_SIP_FUNC_STANDBY 0x1006 -+ -+/* -+ * SIP function STM32_SIP_FUNC_SHUTDOWN -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ */ -+#define STM32_SIP_FUNC_SHUTDOWN 0x1007 -+ -+/* -+ * SIP function STM32_SIP_FUNC_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 eanble target domain -+ */ -+#define STM32_SIP_FUNC_PD_DOMAIN 0x1008 -+ -+/* Valid IDs for power domain for function STM32_SIP_FUNC_PD_DOMAIN */ -+#define STM32_SIP_PD_VSW 0x0 -+#define STM32_SIP_PD_CORE_RET 0x1 -+#define STM32_SIP_PD_CORE 0x2 -+#define STM32_SIP_PD_MAX_PM_DOMAIN 0x3 -+ -+/* -+ * OEM Functions -+ */ -+#define STM32_OEM_SVC_VERSION_MAJOR 0x0 -+#define STM32_OEM_SVC_VERSION_MINOR 0x1 -+ -+/* OEM service generic return codes */ -+#define STM32_OEM_OK 0x0 -+#define STM32_OEM_NOT_SUPPORTED 0xffffffffU -+#define STM32_OEM_FAILED 0xfffffffeU -+#define STM32_OEM_INVALID_PARAMS 0xfffffffdU -+ -+/* -+ * OEM function STM32_OEM_FUNC_LP_FORCE_PARAMS -+ * -+ * Argument a0: (input) SMCC ID -+ * (output) status return code -+ * Argument a2: (input) ID of the mode: suspend or shutdown (off) -+ * Argument a3: (input) ID of the power state to be reached for the mode -+ * Refer to stm32mp1 power bindings. -+ */ -+#define STM32_OEM_FUNC_LP_FORCE_PARAMS 0x0f800 -+ -+/* Valid IDs for power mode configured with STM32_OEM_FUNC_LP_FORCE_PARAMS */ -+#define STM32_OEM_LP_FORCE_SUSPEND_PARAMS 0 -+#define STM32_OEM_LP_FORCE_OFF_PARAMS 1 -+ -+#endif /* __STM32MP1_SMC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c b/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c -new file mode 100644 -index 0000000..3c7958c ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c -@@ -0,0 +1,129 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bsec_svc.h" -+#include "low_power_svc.h" -+#include "pwr_svc.h" -+#include "rcc_svc.h" -+#include "stm32mp1_smc.h" -+ -+static uint32_t __maybe_unused calib_scv_handler(uint32_t x1) -+{ -+ unsigned long clock_id = x1; -+ -+ return (stm32mp_start_clock_calib(clock_id) == 0) ? -+ STM32_SIP_OK : STM32_SIP_FAILED; -+} -+ -+/* STM32 SiP Service UUID */ -+static const TEE_UUID stm32mp1_sip_svc_uid = { -+ 0x50aa78a7, 0x9bf4, 0x4a14, -+ { 0x8a, 0x5e, 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14 } -+}; -+ -+static void get_sip_func_uid(uint32_t *a0, uint32_t *a1, -+ uint32_t *a2, uint32_t *a3) -+{ -+ const void *uid = &stm32mp1_sip_svc_uid; -+ -+ memcpy(a0, (char *)uid, sizeof(uint32_t)); -+ memcpy(a1, (char *)uid + sizeof(uint32_t), sizeof(uint32_t)); -+ memcpy(a2, (char *)uid + (sizeof(uint32_t) * 2), sizeof(uint32_t)); -+ memcpy(a3, (char *)uid + (sizeof(uint32_t) * 3), sizeof(uint32_t)); -+} -+ -+bool stm32_sip_service(struct sm_ctx __unused *ctx, -+ uint32_t *a0, uint32_t *a1, uint32_t *a2, uint32_t *a3) -+{ -+ switch (OPTEE_SMC_FUNC_NUM(*a0)) { -+ case STM32_SIP_FUNC_CALL_COUNT: -+ /* This service is meaningless, return a dummy value */ -+ *a0 = 0; -+ break; -+ case STM32_SIP_FUNC_VERSION: -+ *a0 = STM32_SIP_SVC_VERSION_MAJOR; -+ *a1 = STM32_SIP_SVC_VERSION_MINOR; -+ break; -+ case STM32_SIP_FUNC_UID: -+ get_sip_func_uid(a0, a1, a2, a3); -+ break; -+#ifdef CFG_STM32_BSEC_SIP -+ case STM32_SIP_FUNC_BSEC: -+ *a0 = bsec_main(*a1, *a2, *a3, a1); -+ break; -+#endif -+#ifdef CFG_STM32_RCC_SIP -+ case STM32_SIP_FUNC_RCC: -+ *a0 = rcc_scv_handler(*a1, *a2, *a3); -+ break; -+#endif -+#ifdef CFG_STM32_CLOCKSRC_CALIB -+ case STM32_SIP_RCC_CAL: -+ *a0 = calib_scv_handler(*a1); -+ break; -+#endif -+#ifdef CFG_STM32_PWR_SIP -+ case STM32_SIP_FUNC_PWR: -+ *a0 = pwr_scv_handler(*a1, *a2, *a3); -+ break; -+#endif -+#ifdef CFG_STM32_POWER_SERVICES -+ case STM32_SIP_FUNC_SR_MODE: -+ *a0 = sr_mode_scv_handler(*a1, *a2); -+ break; -+ -+ case STM32_SIP_FUNC_CSTOP: -+ *a0 = cstop_scv_handler(ctx, *a1, *a2, *a3); -+ break; -+ -+ case STM32_SIP_FUNC_STANDBY: -+ *a0 = standby_scv_handler(ctx, *a1, *a2, *a3); -+ break; -+ -+ case STM32_SIP_FUNC_SHUTDOWN: -+ *a0 = shutdown_scv_handler(); -+ break; -+ -+ case STM32_SIP_FUNC_PD_DOMAIN: -+ *a0 = pm_domain_scv_handler(*a1, *a2); -+ break; -+#endif -+ -+ default: -+ return true; -+ } -+ -+ return false; -+} -+ -+bool stm32_oem_service(struct sm_ctx __unused *ctx, -+ uint32_t *a0, uint32_t *a1 __maybe_unused, -+ uint32_t *a2 __maybe_unused, uint32_t *a3 __unused) -+{ -+ switch (OPTEE_SMC_FUNC_NUM(*a0)) { -+#ifdef CFG_STM32_POWER_SERVICES -+ case STM32_OEM_FUNC_LP_FORCE_PARAMS: -+ *a0 = pm_set_lp_state_scv_handler(*a1, *a2); -+ break; -+#endif -+ -+ default: -+ return true; -+ } -+ -+ return false; -+} -diff --git a/core/arch/arm/plat-stm32mp1/service/sub.mk b/core/arch/arm/plat-stm32mp1/service/sub.mk -new file mode 100644 -index 0000000..0797b8f ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/service/sub.mk -@@ -0,0 +1,7 @@ -+global-incdirs-y += . -+ -+srcs-y += stm32mp1_svc_setup.c -+srcs-$(CFG_STM32_BSEC_SIP) += bsec_svc.c -+srcs-$(CFG_STM32_PWR_SIP) += pwr_svc.c -+srcs-$(CFG_STM32_RCC_SIP) += rcc_svc.c -+srcs-$(CFG_STM32_POWER_SERVICES) += low_power_svc.c -diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c -new file mode 100644 -index 0000000..0eb929c ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/shared_resources.c -@@ -0,0 +1,1007 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static unsigned int shregs_lock = SPINLOCK_UNLOCK; -+static bool registering_locked; -+ -+/* Shared resource lock: assume not required if MMU is disabled */ -+uint32_t lock_stm32shregs(void) -+{ -+ return may_spin_lock(&shregs_lock); -+} -+ -+void unlock_stm32shregs(uint32_t exceptions) -+{ -+ may_spin_unlock(&shregs_lock, exceptions); -+} -+ -+/* Shared register access: upon shared resource lock */ -+void io_mask32_stm32shregs(uintptr_t va, uint32_t value, uint32_t mask) -+{ -+ uint32_t exceptions = lock_stm32shregs(); -+ -+ io_mask32(va, value, mask); -+ -+ unlock_stm32shregs(exceptions); -+} -+ -+/* -+ * Generic clock enable/disable from secure world. -+ * Some drivers may use non secure resources in specific execution context: -+ * when the other SMP core(s) are offline and non secure is never reached. -+ * In such cases, drivers shall enable/disable the HW clock only if it was not -+ * left enabled by the non secure world. -+ * -+ * During driver initializations, before registering_locked is locked, all -+ * driver simply enable/disable the clock as if the peripheral was secure. -+ */ -+void stm32_clock_enable(unsigned long id) -+{ -+ if (registering_locked) { -+ if (stm32mp_clock_is_non_secure(id)) { -+ assert(!stm32mp1_clk_get_refcount(id)); -+ -+ if (stm32mp1_clk_is_enabled(id)) { -+ return; -+ } -+ } -+ } -+ -+ stm32mp1_clk_enable_secure(id); -+} -+ -+void stm32_clock_disable(unsigned long id) -+{ -+ if (registering_locked) { -+ if (stm32mp_clock_is_non_secure(id)) { -+ if (!stm32mp1_clk_get_refcount(id)) { -+ return; -+ } -+ } -+ } -+ -+ stm32mp1_clk_disable_secure(id); -+} -+ -+/* -+ * Shared peripherals and resources. -+ * Defines resource that may be non secure, secure or shared. -+ * May be a device, a bus, a clock, a memory. -+ * -+ * State default to PERIPH_UNREGISTERED resource is not explicitly -+ * set here. -+ * -+ * Resource driver not built (upon CFG_xxx), the resource defaults -+ * to non secure ownership. -+ * -+ * Each IO of the GPIOZ IO can be secure or non secure. -+ * When the GPIO driver is enabled, the GPIOZ bank is fully non secure -+ * only if each IO is non secure and the GPIOZ bank is shared if it -+ * includes secure and non secure IOs. -+ * -+ * BKPSRAM is assumed shared. -+ * DDR control (DDRC and DDRPHY) is secure. -+ * Inits will define the resource state according the device tree -+ * and the driver initialization sequences. -+ * -+ * The platform initialization uses these information to set the ETZPC -+ * configuration. Non secure services (as clocks or regulator accesses) -+ * rely on these information to drive the related service execution. -+ */ -+#define SHRES_NON_SECURE 3 -+#define SHRES_SHARED 2 -+#define SHRES_SECURE 1 -+#define SHRES_UNREGISTERED 0 -+ -+static uint8_t shres_state[STM32MP1_SHRES_COUNT] = { -+#if !defined(CFG_STM32_IWDG) -+ [STM32MP1_SHRES_IWDG1] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_UART) -+ [STM32MP1_SHRES_USART1] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_SPI) -+ [STM32MP1_SHRES_SPI6] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_I2C) -+ [STM32MP1_SHRES_I2C4] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_I2C6] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_GPIO) -+ [STM32MP1_SHRES_GPIOZ(0)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(1)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(2)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(3)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(4)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(5)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(6)] = SHRES_NON_SECURE, -+ [STM32MP1_SHRES_GPIOZ(7)] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_RNG) -+ [STM32MP1_SHRES_RNG1] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_HASH) -+ [STM32MP1_SHRES_HASH1] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_CRYP) -+ [STM32MP1_SHRES_CRYP1] = SHRES_NON_SECURE, -+#endif -+#if !defined(CFG_STM32_RTC) -+ [STM32MP1_SHRES_RTC] = SHRES_NON_SECURE, -+#endif -+}; -+ -+#if CFG_TEE_CORE_LOG_LEVEL > 0 -+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] = { -+ [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0", -+ [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1", -+ [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2", -+ [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3", -+ [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4", -+ [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5", -+ [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6", -+ [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7", -+ [STM32MP1_SHRES_IWDG1] = "IWDG1", -+ [STM32MP1_SHRES_USART1] = "USART1", -+ [STM32MP1_SHRES_SPI6] = "SPI6", -+ [STM32MP1_SHRES_I2C4] = "I2C4", -+ [STM32MP1_SHRES_RNG1] = "RNG1", -+ [STM32MP1_SHRES_HASH1] = "HASH1", -+ [STM32MP1_SHRES_CRYP1] = "CRYP1", -+ [STM32MP1_SHRES_I2C6] = "I2C6", -+ [STM32MP1_SHRES_RTC] = "RTC", -+ [STM32MP1_SHRES_MCU] = "MCU", -+ [STM32MP1_SHRES_HSI] = "HSI", -+ [STM32MP1_SHRES_LSI] = "LSI", -+ [STM32MP1_SHRES_HSE] = "HSE", -+ [STM32MP1_SHRES_LSE] = "LSE", -+ [STM32MP1_SHRES_CSI] = "CSI", -+ [STM32MP1_SHRES_PLL1] = "PLL1", -+ [STM32MP1_SHRES_PLL1_P] = "PLL1_P", -+ [STM32MP1_SHRES_PLL1_Q] = "PLL1_Q", -+ [STM32MP1_SHRES_PLL1_R] = "PLL1_R", -+ [STM32MP1_SHRES_PLL2] = "PLL2", -+ [STM32MP1_SHRES_PLL2_P] = "PLL2_P", -+ [STM32MP1_SHRES_PLL2_Q] = "PLL2_Q", -+ [STM32MP1_SHRES_PLL2_R] = "PLL2_R", -+ [STM32MP1_SHRES_PLL3] = "PLL3", -+ [STM32MP1_SHRES_PLL3_P] = "PLL3_P", -+ [STM32MP1_SHRES_PLL3_Q] = "PLL3_Q", -+ [STM32MP1_SHRES_PLL3_R] = "PLL3_R", -+}; -+ -+static const char *shres2str_id(unsigned int id) -+{ -+ return shres2str_id_tbl[id]; -+} -+ -+static const char *shres2str_state_tbl[4] = { -+ [SHRES_SHARED] = "shared", -+ [SHRES_NON_SECURE] = "non secure", -+ [SHRES_SECURE] = "secure", -+ [SHRES_UNREGISTERED] = "unregistered", -+}; -+ -+static const char *shres2str_state(unsigned int id) -+{ -+ return shres2str_state_tbl[id]; -+} -+#else -+static __maybe_unused const char *shres2str_id(unsigned int __unused id) -+{ -+ return NULL; -+} -+ -+static __maybe_unused const char *shres2str_state(unsigned int __unused id) -+{ -+ return NULL; -+} -+#endif -+ -+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_GPIOZ_ID, "GPIOZ"), -+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRCTRL_ID, "DDRCTRL"), -+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRPHYC_ID, "DDRPHY"), -+}; -+ -+static unsigned int decprot2shres(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].shres_id; -+ } -+ } -+ -+ DMSG("No share resource ID %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; -+ } -+ } -+ -+ EMSG("Invalid ID %u", decprot_id); -+ panic(); -+} -+ -+/* GPIOZ bank may have several number of pins */ -+#if CFG_DT -+static int gpioz_nbpin = -1; -+ -+static unsigned int get_gpioz_nbpin_unpg(void) -+{ -+ if (gpioz_nbpin >= 0) { -+ return (unsigned int)gpioz_nbpin; -+ } -+ -+ panic(); -+} -+KEEP_PAGER(get_gpioz_nbpin_unpg); -+ -+static unsigned int get_gpioz_nbpin(void) -+{ -+ if (gpioz_nbpin < 0) { -+ void *fdt; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ gpioz_nbpin = fdt_get_gpioz_nbpins_from_dt(fdt); -+ assert((gpioz_nbpin == 0) || -+ (gpioz_nbpin == STM32MP1_GPIOZ_PIN_MAX_COUNT)); -+ } -+ -+ return (unsigned int)gpioz_nbpin; -+} -+#else -+static unsigned int get_gpioz_nbpin_unpg(void) -+{ -+ return STM32MP1_GPIOZ_PIN_MAX_COUNT; -+} -+ -+static unsigned int get_gpioz_nbpin(void) -+{ -+ return get_gpioz_nbpin_unpg(); -+} -+#endif -+ -+static bool shareable_resource(unsigned int id) -+{ -+ switch (id) { -+ default: -+ /* Currently no shareable resource */ -+ return false; -+ } -+} -+ -+static bool mckprot_resource(unsigned int id) -+{ -+ switch (id) { -+ case STM32MP1_SHRES_MCU: -+ case STM32MP1_SHRES_PLL3: -+ case STM32MP1_SHRES_PLL3_P: -+ case STM32MP1_SHRES_PLL3_Q: -+ case STM32MP1_SHRES_PLL3_R: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static void register_periph(unsigned int id, unsigned int state) -+{ -+ assert(id < STM32MP1_SHRES_COUNT && -+ state > SHRES_UNREGISTERED && -+ state <= SHRES_NON_SECURE); -+ -+ if (registering_locked) { -+ panic(); -+ } -+ -+ if ((state == SHRES_SHARED && !shareable_resource(id)) || -+ ((shres_state[id] != SHRES_UNREGISTERED) && -+ (shres_state[id] != state))) { -+ DMSG("Cannot change %s from %s to %s", -+ shres2str_id(id), -+ shres2str_state(shres_state[id]), -+ shres2str_state(state)); -+ panic(); -+ } -+ -+ if (shres_state[id] == SHRES_UNREGISTERED) { -+ DMSG("Register %s as %s", -+ shres2str_id(id), shres2str_state(state)); -+ } -+ -+ switch (id) { -+ case STM32MP1_SHRES_GPIOZ(0): -+ case STM32MP1_SHRES_GPIOZ(1): -+ case STM32MP1_SHRES_GPIOZ(2): -+ case STM32MP1_SHRES_GPIOZ(3): -+ case STM32MP1_SHRES_GPIOZ(4): -+ case STM32MP1_SHRES_GPIOZ(5): -+ case STM32MP1_SHRES_GPIOZ(6): -+ case STM32MP1_SHRES_GPIOZ(7): -+ if ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin()) { -+ EMSG("Invalid GPIO pin %u, %u pin(s) available", -+ id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin()); -+ panic(); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ shres_state[id] = (uint8_t)state; -+ -+ /* Explore clock tree to lock dependencies */ -+ if ((state == SHRES_SECURE) || (state == SHRES_SHARED)) { -+ switch (id) { -+ case STM32MP1_SHRES_GPIOZ(0): -+ case STM32MP1_SHRES_GPIOZ(1): -+ case STM32MP1_SHRES_GPIOZ(2): -+ case STM32MP1_SHRES_GPIOZ(3): -+ case STM32MP1_SHRES_GPIOZ(4): -+ case STM32MP1_SHRES_GPIOZ(5): -+ case STM32MP1_SHRES_GPIOZ(6): -+ case STM32MP1_SHRES_GPIOZ(7): -+ stm32mp_register_clock_parents_secure(GPIOZ); -+ break; -+ case STM32MP1_SHRES_IWDG1: -+ stm32mp_register_clock_parents_secure(IWDG1); -+ break; -+ case STM32MP1_SHRES_USART1: -+ stm32mp_register_clock_parents_secure(USART1_K); -+ break; -+ case STM32MP1_SHRES_SPI6: -+ stm32mp_register_clock_parents_secure(SPI6_K); -+ break; -+ case STM32MP1_SHRES_I2C4: -+ stm32mp_register_clock_parents_secure(I2C4_K); -+ break; -+ case STM32MP1_SHRES_RNG1: -+ stm32mp_register_clock_parents_secure(RNG1_K); -+ break; -+ case STM32MP1_SHRES_HASH1: -+ stm32mp_register_clock_parents_secure(HASH1); -+ break; -+ case STM32MP1_SHRES_CRYP1: -+ stm32mp_register_clock_parents_secure(CRYP1); -+ break; -+ case STM32MP1_SHRES_I2C6: -+ stm32mp_register_clock_parents_secure(I2C6_K); -+ break; -+ case STM32MP1_SHRES_RTC: -+ stm32mp_register_clock_parents_secure(RTC); -+ break; -+ case STM32MP1_SHRES_PLL1_P: -+ case STM32MP1_SHRES_PLL1_Q: -+ case STM32MP1_SHRES_PLL1_R: -+ register_periph(STM32MP1_SHRES_PLL1, SHRES_SECURE); -+ stm32mp_register_clock_parents_secure(PLL1); -+ break; -+ case STM32MP1_SHRES_PLL2_P: -+ case STM32MP1_SHRES_PLL2_Q: -+ case STM32MP1_SHRES_PLL2_R: -+ register_periph(STM32MP1_SHRES_PLL2, SHRES_SECURE); -+ stm32mp_register_clock_parents_secure(PLL2); -+ break; -+ case STM32MP1_SHRES_PLL3_P: -+ case STM32MP1_SHRES_PLL3_Q: -+ case STM32MP1_SHRES_PLL3_R: -+ register_periph(STM32MP1_SHRES_PLL3, SHRES_SECURE); -+ stm32mp_register_clock_parents_secure(PLL3); -+ break; -+ default: -+ /* No expected resource dependency */ -+ break; -+ } -+ } -+} -+ -+/* Register resource by ID */ -+void stm32mp_register_secure_periph(unsigned int id) -+{ -+ register_periph(id, SHRES_SECURE); -+} -+ -+void stm32mp_register_shared_periph(unsigned int id) -+{ -+ register_periph(id, SHRES_SHARED); -+} -+ -+void stm32mp_register_non_secure_periph(unsigned int id) -+{ -+ register_periph(id, SHRES_NON_SECURE); -+} -+ -+/* Register resource by IO memory base address */ -+static void register_periph_iomem(uintptr_t base, unsigned int state) -+{ -+ unsigned int id; -+ -+ switch (base) { -+ case IWDG1_BASE: -+ id = STM32MP1_SHRES_IWDG1; -+ break; -+ case USART1_BASE: -+ id = STM32MP1_SHRES_USART1; -+ break; -+ case SPI6_BASE: -+ id = STM32MP1_SHRES_SPI6; -+ break; -+ case I2C4_BASE: -+ id = STM32MP1_SHRES_I2C4; -+ break; -+ case I2C6_BASE: -+ id = STM32MP1_SHRES_I2C6; -+ break; -+ case RTC_BASE: -+ id = STM32MP1_SHRES_RTC; -+ break; -+ case RNG1_BASE: -+ id = STM32MP1_SHRES_RNG1; -+ break; -+ case CRYP1_BASE: -+ id = STM32MP1_SHRES_CRYP1; -+ break; -+ case HASH1_BASE: -+ id = STM32MP1_SHRES_HASH1; -+ break; -+ -+#ifdef CFG_WITH_NSEC_GPIOS -+ case GPIOA_BASE: -+ case GPIOB_BASE: -+ case GPIOC_BASE: -+ case GPIOD_BASE: -+ case GPIOE_BASE: -+ case GPIOF_BASE: -+ case GPIOG_BASE: -+ case GPIOH_BASE: -+ case GPIOI_BASE: -+ case GPIOJ_BASE: -+ case GPIOK_BASE: -+#endif -+#ifdef CFG_WITH_NSEC_UARTS -+ case USART2_BASE: -+ case USART3_BASE: -+ case UART4_BASE: -+ case UART5_BASE: -+ case USART6_BASE: -+ case UART7_BASE: -+ case UART8_BASE: -+#endif -+ case IWDG2_BASE: -+ /* Allow drivers to register some non secure resources */ -+ DMSG("IO for non secure resource 0x%lx", base); -+ if (state != SHRES_NON_SECURE) -+ panic(); -+ -+ return; -+ -+ default: -+ panic(); -+ break; -+ } -+ -+ register_periph(id, state); -+} -+ -+void stm32mp_register_secure_periph_iomem(uintptr_t base) -+{ -+ register_periph_iomem(base, SHRES_SECURE); -+} -+ -+void stm32mp_register_non_secure_periph_iomem(uintptr_t base) -+{ -+ register_periph_iomem(base, SHRES_NON_SECURE); -+} -+ -+/* Register GPIO resource */ -+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin) -+{ -+ switch (bank) { -+ case GPIO_BANK_Z: -+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE); -+ break; -+ default: -+ EMSG("GPIO bank %u cannot be secured", bank); -+ panic(); -+ } -+} -+ -+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) -+{ -+ switch (bank) { -+ case GPIO_BANK_Z: -+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE); -+ break; -+ default: -+ break; -+ } -+} -+ -+void stm32mp_register_etzpc_decprot(unsigned int id, -+ enum etzpc_decprot_attributes attr) -+{ -+ unsigned int state = SHRES_SECURE; -+ unsigned int id_shres; -+ -+ switch (attr) { -+ case TZPC_DECPROT_S_RW: -+ break; -+ case TZPC_DECPROT_NS_R_S_W: -+ case TZPC_DECPROT_MCU_ISOLATION: -+ case TZPC_DECPROT_NS_RW: -+ state = SHRES_NON_SECURE; -+ break; -+ default: -+ panic(); -+ } -+ -+ switch (id) { -+ case STM32MP1_ETZPC_GPIOZ_ID: -+ if (state == SHRES_SECURE) { -+ /* GPIOZ cannot be hardened from the ETZPC */ -+ panic(); -+ } -+ break; -+ default: -+ id_shres = decprot2shres(id); -+ if (id_shres == SHRES_INVALID) { -+ if (state != SHRES_NON_SECURE) -+ panic(); -+ } else { -+ register_periph(id_shres, state); -+ } -+ break; -+ } -+} -+ -+/* Get resource state: these accesses lock the registering support */ -+static void lock_registering(void) -+{ -+ registering_locked = true; -+} -+ -+bool stm32mp_periph_is_shared(unsigned long id) -+{ -+ lock_registering(); -+ -+ return shres_state[id] == SHRES_SHARED; -+} -+ -+bool stm32mp_periph_is_non_secure(unsigned long id) -+{ -+ lock_registering(); -+ -+ return shres_state[id] == SHRES_NON_SECURE; -+} -+ -+bool stm32mp_periph_is_secure(unsigned long id) -+{ -+ lock_registering(); -+ -+ return shres_state[id] == SHRES_SECURE; -+} -+ -+bool stm32mp_periph_is_unregistered(unsigned long id) -+{ -+ lock_registering(); -+ -+ return shres_state[id] == SHRES_UNREGISTERED; -+} -+ -+bool stm32mp_gpio_bank_is_shared(unsigned int bank) -+{ -+ unsigned int non_secure = 0; -+ unsigned int i; -+ -+ lock_registering(); -+ -+ if (bank != GPIO_BANK_Z) { -+ return false; -+ } -+ -+ for (i = 0; i < get_gpioz_nbpin_unpg(); i++) { -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i)) || -+ stm32mp_periph_is_unregistered(STM32MP1_SHRES_GPIOZ(i))) { -+ non_secure++; -+ } -+ } -+ -+ return (non_secure != 0) && (non_secure < get_gpioz_nbpin_unpg()); -+} -+ -+bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) -+{ -+ unsigned int non_secure = 0; -+ unsigned int i; -+ -+ lock_registering(); -+ -+ if (bank != GPIO_BANK_Z) { -+ return true; -+ } -+ -+ for (i = 0; i < get_gpioz_nbpin_unpg(); i++) { -+ if (stm32mp_periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i)) || -+ stm32mp_periph_is_unregistered(STM32MP1_SHRES_GPIOZ(i))) { -+ non_secure++; -+ } -+ } -+ -+ return non_secure == get_gpioz_nbpin_unpg(); -+} -+ -+bool stm32mp_gpio_bank_is_secure(unsigned int bank) -+{ -+ unsigned int secure = 0; -+ unsigned int i; -+ -+ lock_registering(); -+ -+ if (bank != GPIO_BANK_Z) { -+ return false; -+ } -+ -+ for (i = 0; i < get_gpioz_nbpin_unpg(); i++) { -+ if (stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) { -+ secure++; -+ } -+ } -+ -+ return secure == get_gpioz_nbpin_unpg(); -+} -+ -+bool stm32mp_clock_is_shareable(unsigned long clock_id) -+{ -+ switch (clock_id) { -+ case GPIOZ: -+ return get_gpioz_nbpin() > 0; -+ case RTCAPB: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+bool stm32mp_clock_is_shared(unsigned long clock_id) -+{ -+ lock_registering(); -+ -+ switch (clock_id) { -+ case GPIOZ: -+ if (get_gpioz_nbpin_unpg() > 0) { -+ return stm32mp_gpio_bank_is_shared(GPIO_BANK_Z); -+ } else { -+ return false; -+ } -+ case RTCAPB: -+ /* RTCAPB is shared for non secure backup registers */ -+ return true; -+ default: -+ return false; -+ } -+} -+ -+bool stm32mp_clock_is_non_secure(unsigned long clock_id) -+{ -+ unsigned int shres_id; -+ -+ lock_registering(); -+ -+ if (stm32mp_clock_is_shared(clock_id)) { -+ return false; -+ } -+ -+ switch (clock_id) { -+ case BSEC: -+ case BKPSRAM: -+ case TZPC: -+ case TZC1: -+ case TZC2: -+ case STGEN_K: -+ case DDRC1: -+ case DDRC1LP: -+ case DDRC2: -+ case DDRC2LP: -+ case DDRPHYC: -+ case DDRPHYCLP: -+ case DDRCAPB: -+ case DDRCAPBLP: -+ case AXIDCG: -+ case DDRPHYCAPB: -+ case DDRPHYCAPBLP: -+ return false; -+ case IWDG1: -+ shres_id = STM32MP1_SHRES_IWDG1; -+ break; -+ case USART1_K: -+ shres_id = STM32MP1_SHRES_USART1; -+ break; -+ case SPI6_K: -+ shres_id = STM32MP1_SHRES_SPI6; -+ break; -+ case I2C4_K: -+ shres_id = STM32MP1_SHRES_I2C4; -+ break; -+ case RNG1_K: -+ shres_id = STM32MP1_SHRES_RNG1; -+ break; -+ case HASH1: -+ shres_id = STM32MP1_SHRES_HASH1; -+ break; -+ case CRYP1: -+ shres_id = STM32MP1_SHRES_CRYP1; -+ break; -+ case I2C6_K: -+ shres_id = STM32MP1_SHRES_I2C6; -+ break; -+ case RTC: -+ shres_id = STM32MP1_SHRES_RTC; -+ break; -+ default: -+ return true; -+ } -+ -+ return stm32mp_periph_is_non_secure(shres_id); -+} -+ -+/* ETZPC configuration at drivers initialization completion */ -+static enum etzpc_decprot_attributes decprot_periph_attr(unsigned int id) -+{ -+ switch (id) { -+ case STM32MP1_SHRES_GPIOZ(0): -+ case STM32MP1_SHRES_GPIOZ(1): -+ case STM32MP1_SHRES_GPIOZ(2): -+ case STM32MP1_SHRES_GPIOZ(3): -+ case STM32MP1_SHRES_GPIOZ(4): -+ case STM32MP1_SHRES_GPIOZ(5): -+ case STM32MP1_SHRES_GPIOZ(6): -+ case STM32MP1_SHRES_GPIOZ(7): -+ assert((id - STM32MP1_SHRES_GPIOZ(0)) < get_gpioz_nbpin_unpg()); -+ return TZPC_DECPROT_NS_RW; -+ default: -+ if (stm32mp_periph_is_non_secure(id)) { -+ return TZPC_DECPROT_NS_RW; -+ } -+ -+ return TZPC_DECPROT_S_RW; -+ } -+} -+ -+static bool check_decprot(unsigned int id, enum etzpc_decprot_attributes exp) -+{ -+ enum etzpc_decprot_attributes cur = etzpc_get_decprot(id); -+ -+ if (cur == exp) { -+ return true; -+ } -+ -+ switch (exp) { -+ case TZPC_DECPROT_NS_RW: -+ if (cur == TZPC_DECPROT_S_RW) { -+#ifdef CFG_DT -+ IMSG("Warning ETZPC: %s could be non secure", -+ decprot2str(id)); -+#else -+ etzpc_configure_decprot(id, TZPC_DECPROT_NS_RW); -+ IMSG("Warning ETZPC: %s forced non secure", -+ decprot2str(id)); -+#endif -+ } -+ return true; -+ -+ case TZPC_DECPROT_S_RW: -+ EMSG("ETZPC DECPROT: %s (%u) expected secure but DECPROT=%d", -+ decprot2str(id), id, cur); -+ break; -+ -+ case TZPC_DECPROT_NS_R_S_W: -+ case TZPC_DECPROT_MCU_ISOLATION: -+ default: -+ panic(); -+ } -+ -+ return false; -+} -+ -+static void check_etzpc_secure_configuration(void) -+{ -+ bool error = false; -+ -+ assert(registering_locked); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_STGENC_ID, -+ TZPC_DECPROT_S_RW); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_BKPSRAM_ID, -+ TZPC_DECPROT_S_RW); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_IWDG1_ID, -+ decprot_periph_attr(STM32MP1_SHRES_IWDG1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_USART1_ID, -+ decprot_periph_attr(STM32MP1_SHRES_USART1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_SPI6_ID, -+ decprot_periph_attr(STM32MP1_SHRES_SPI6)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_I2C4_ID, -+ decprot_periph_attr(STM32MP1_SHRES_I2C4)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_RNG1_ID, -+ decprot_periph_attr(STM32MP1_SHRES_RNG1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_HASH1_ID, -+ decprot_periph_attr(STM32MP1_SHRES_HASH1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_CRYP1_ID, -+ decprot_periph_attr(STM32MP1_SHRES_CRYP1)); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, -+ TZPC_DECPROT_S_RW); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, -+ TZPC_DECPROT_S_RW); -+ -+ error |= !check_decprot(STM32MP1_ETZPC_I2C6_ID, -+ decprot_periph_attr(STM32MP1_SHRES_I2C6)); -+ -+ if (!error) { -+ return; -+ } -+ -+ panic(); -+} -+ -+static void check_rcc_secure_configuration(void) -+{ -+ bool secure = stm32_rcc_is_secure(); -+ bool mckprot = stm32_rcc_is_mckprot(); -+ unsigned int n; -+ unsigned int error = 0; -+ -+ for (n = 0; n < ARRAY_SIZE(shres_state); n++) { -+ if ((shres_state[n] == SHRES_SECURE) || -+ (shres_state[n] == SHRES_SHARED)) { -+ if ((mckprot_resource(n) && (!mckprot)) || !secure) { -+ EMSG("RCC %s MCKPROT %s and %s (%u) secure", -+ secure ? "secure" : "non secure", -+ mckprot ? "set" : "not set", -+ shres2str_id(n), n); -+ error++; -+ } -+ } -+ } -+ -+ if (error != 0U) { -+ panic(); -+ } -+} -+ -+static void gpio_secure_suspend_resume(enum pm_op op, void __unused *handle) -+{ -+ unsigned int pin; -+ -+ switch (op) { -+ case PM_OP_SUSPEND: -+ return; -+ case PM_OP_RESUME: -+ break; -+ default: -+ panic(); -+ } -+ -+ /* Release secure hardening of non secure pins at resume */ -+ for (pin = 0; pin < get_gpioz_nbpin_unpg(); pin++) { -+ unsigned int id = STM32MP1_SHRES_GPIOZ(pin); -+ -+ if (stm32mp_periph_is_non_secure(id) || -+ stm32mp_periph_is_unregistered(id)) { -+ stm32_gpio_set_secure_cfg(GPIO_BANK_Z, pin, false); -+ } -+ } -+} -+KEEP_PAGER(gpio_secure_suspend_resume); -+ -+static void check_gpio_secure_configuration(void) -+{ -+ unsigned int pin; -+ bool secure; -+ -+ for (pin = 0; pin < get_gpioz_nbpin(); pin++) { -+ secure = stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin)); -+ stm32_gpio_set_secure_cfg(GPIO_BANK_Z, pin, secure); -+ } -+ -+ stm32mp_register_pm_cb(gpio_secure_suspend_resume, NULL); -+} -+ -+static TEE_Result stm32mp1_init_drivers(void) -+{ -+ size_t id; -+ -+ registering_locked = true; -+ -+ for (id = 0; id < STM32MP1_SHRES_COUNT; id++) { -+ uint8_t *state = &shres_state[id]; -+ -+#if TRACE_LEVEL == TRACE_INFO -+ /* Display only the secure and shared resources */ -+ if ((*state == SHRES_NON_SECURE) || -+ ((*state == SHRES_UNREGISTERED))) { -+ continue; -+ } -+#endif -+ -+ IMSG("stm32mp %-8s (%2u): %-14s", -+ shres2str_id(id), id, shres2str_state(*state)); -+ } -+ -+ stm32mp_update_earlyboot_clocks_state(); -+ -+ check_rcc_secure_configuration(); -+ check_etzpc_secure_configuration(); -+ check_gpio_secure_configuration(); -+ -+ return TEE_SUCCESS; -+} -+driver_init_late(stm32mp1_init_drivers); -diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h -new file mode 100644 -index 0000000..0164855 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/stm32_util.h -@@ -0,0 +1,287 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#ifndef __STM32_UTIL_H__ -+#define __STM32_UTIL_H__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* SoC versioning */ -+uint32_t stm32mp1_dbgmcu_get_chip_version(void); -+ -+/* SiP & OEM platform services */ -+bool stm32_sip_service(struct sm_ctx *ctx, -+ uint32_t *a0, uint32_t *a1, uint32_t *a2, uint32_t *a3); -+bool stm32_oem_service(struct sm_ctx *ctx, -+ uint32_t *a0, uint32_t *a1, uint32_t *a2, uint32_t *a3); -+ -+ -+/* Platform util for the STGEN driver */ -+uintptr_t stm32_get_stgen_base(void); -+ -+/* Platform util for the GIC */ -+uintptr_t get_gicc_base(void); -+uintptr_t get_gicd_base(void); -+ -+/* Platform util for clock gating. ID refers to clock DT bindings ID. */ -+void stm32_clock_enable(unsigned long id); -+void stm32_clock_disable(unsigned long id); -+ -+static inline unsigned long stm32_clock_get_rate(unsigned long id) -+{ -+ return stm32mp1_clk_get_rate(id); -+} -+ -+static inline unsigned long stm32_clock_is_enabled(unsigned long id) -+{ -+ return stm32mp1_clk_is_enabled(id); -+} -+ -+/* Platform util for the GPIO driver */ -+uintptr_t stm32_get_gpio_bank_base(unsigned int bank); -+uint32_t stm32_get_gpio_bank_offset(unsigned int bank); -+int stm32_get_gpio_bank_clock(unsigned int bank); -+ -+/* Platform util for the IWDG driver */ -+unsigned long stm32_get_iwdg_otp_config(uintptr_t pbase); -+int stm32mp_iwdg_irq2instance(size_t irq); -+size_t stm32mp_iwdg_instance2irq(int instance); -+unsigned int stm32mp_iwdg_iomem2instance(uintptr_t pbase); -+ -+/* Platform util for the BSEC driver */ -+unsigned int stm32mp_get_otp_max(void); -+unsigned int stm32mp_get_otp_upper_start(void); -+ -+/* Platform util for the ETZPC driver */ -+uintptr_t stm32mp_get_etzpc_base(void); -+enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode); -+ -+/* Platform util for the RTC driver */ -+bool stm32_rtc_get_read_twice(void); -+ -+/* Backup registers and RAM utils */ -+uintptr_t stm32mp_bkpreg(unsigned int idx); -+ -+uintptr_t stm32mp1_bkpsram_base(void); -+ -+/* Platform util for PMIC support */ -+bool stm32mp_with_pmic(void); -+ -+/* Power management service */ -+void stm32mp_register_online_cpu(void); -+ -+/* -+ * Lock/unlock access to shared registers -+ * -+ * @lock - NULL or pointer to spin lock -+ */ -+uint32_t lock_stm32shregs(void); -+void unlock_stm32shregs(uint32_t exceptions); -+ -+void io_mask32_stm32shregs(uintptr_t va, uint32_t value, uint32_t mask); -+ -+static inline void stm32shregs_setbits(uintptr_t va, uint32_t value) -+{ -+ io_mask32_stm32shregs(va, value, value); -+} -+ -+static inline void stm32shregs_clrbits(uintptr_t va, uint32_t value) -+{ -+ io_mask32_stm32shregs(va, 0, value); -+} -+ -+static inline void stm32shregs_clrsetbits(uintptr_t va, uint32_t mask, -+ uint32_t value) -+{ -+ io_mask32_stm32shregs(va, value, mask); -+} -+ -+/* -+ * Generic spinlock function that bypass spinlock if MMU is disabled or -+ * lock is NULL. -+ */ -+uint32_t may_spin_lock(unsigned int *lock); -+void may_spin_unlock(unsigned int *lock, uint32_t exceptions); -+ -+/* Reset function for early watchdog management */ -+void stm32mp_platform_reset(int cpu); -+ -+/* Clock calibration */ -+int stm32mp_start_clock_calib(unsigned int clock_id); -+ -+/* -+ * 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. These counter initializes to -+ * either 0, 1 or 2 upon their expect default state. -+ * Increment refcount and return if incremented from 0. -+ * Counters saturates once above UINT_MAX / 2. -+ */ -+#define SHREFCNT_NONSECURE_FLAG 0x1ul -+#define SHREFCNT_SECURE_STEP 0x2ul -+#define SHREFCNT_MAX (UINT_MAX / 2) -+ -+/* Return 1 if refcnt decrements to 0, else return 0 */ -+static inline int incr_shrefcnt(unsigned int *refcnt, bool secure) -+{ -+ int rc = !*refcnt; -+ -+ if (secure) { -+ if (*refcnt < SHREFCNT_MAX) { -+ *refcnt += SHREFCNT_SECURE_STEP; -+ assert(*refcnt < SHREFCNT_MAX); -+ } -+ } else { -+ *refcnt |= SHREFCNT_NONSECURE_FLAG; -+ } -+ -+ return rc; -+} -+ -+/* Return 1 if refcnt decrements to 0, else return 0 */ -+static inline int decr_shrefcnt(unsigned int *refcnt, bool secure) -+{ -+ int rc = 0; -+ -+ if (secure) { -+ if (*refcnt < SHREFCNT_MAX) { -+ if (*refcnt < SHREFCNT_SECURE_STEP) { -+ panic(); -+ } -+ -+ *refcnt -= SHREFCNT_SECURE_STEP; -+ rc = !*refcnt; -+ } -+ } else { -+ rc = (*refcnt == SHREFCNT_NONSECURE_FLAG); -+ *refcnt &= ~SHREFCNT_NONSECURE_FLAG; -+ } -+ -+ return rc; -+} -+ -+static inline int incr_refcnt(unsigned int *refcnt) -+{ -+ return incr_shrefcnt(refcnt, true); -+} -+ -+static inline int decr_refcnt(unsigned int *refcnt) -+{ -+ return decr_shrefcnt(refcnt, true); -+} -+ -+#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + i) -+ -+enum stm32mp_shres { -+ STM32MP1_SHRES_GPIOZ_0 = 0, -+ STM32MP1_SHRES_GPIOZ_1, -+ STM32MP1_SHRES_GPIOZ_2, -+ STM32MP1_SHRES_GPIOZ_3, -+ STM32MP1_SHRES_GPIOZ_4, -+ STM32MP1_SHRES_GPIOZ_5, -+ STM32MP1_SHRES_GPIOZ_6, -+ STM32MP1_SHRES_GPIOZ_7, -+ STM32MP1_SHRES_IWDG1, -+ STM32MP1_SHRES_USART1, -+ STM32MP1_SHRES_SPI6, -+ STM32MP1_SHRES_I2C4, -+ STM32MP1_SHRES_RNG1, -+ STM32MP1_SHRES_HASH1, -+ STM32MP1_SHRES_CRYP1, -+ STM32MP1_SHRES_I2C6, -+ STM32MP1_SHRES_RTC, -+ STM32MP1_SHRES_MCU, -+ STM32MP1_SHRES_HSI, -+ STM32MP1_SHRES_LSI, -+ STM32MP1_SHRES_HSE, -+ STM32MP1_SHRES_LSE, -+ STM32MP1_SHRES_CSI, -+ STM32MP1_SHRES_PLL1, -+ STM32MP1_SHRES_PLL1_P, -+ STM32MP1_SHRES_PLL1_Q, -+ STM32MP1_SHRES_PLL1_R, -+ STM32MP1_SHRES_PLL2, -+ STM32MP1_SHRES_PLL2_P, -+ STM32MP1_SHRES_PLL2_Q, -+ STM32MP1_SHRES_PLL2_R, -+ STM32MP1_SHRES_PLL3, -+ STM32MP1_SHRES_PLL3_P, -+ STM32MP1_SHRES_PLL3_Q, -+ STM32MP1_SHRES_PLL3_R, -+ -+ STM32MP1_SHRES_COUNT -+}; -+ -+void stm32mp_register_secure_periph(unsigned int id); -+void stm32mp_register_shared_periph(unsigned int id); -+void stm32mp_register_non_secure_periph(unsigned int id); -+void stm32mp_register_secure_periph_iomem(uintptr_t base); -+void stm32mp_register_non_secure_periph_iomem(uintptr_t base); -+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin); -+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin); -+void stm32mp_register_etzpc_decprot(unsigned int id, -+ enum etzpc_decprot_attributes attr); -+ -+bool stm32mp_periph_is_shared(unsigned long id); -+bool stm32mp_periph_is_non_secure(unsigned long id); -+bool stm32mp_periph_is_secure(unsigned long id); -+bool stm32mp_periph_is_unregistered(unsigned long id); -+ -+bool stm32mp_gpio_bank_is_shared(unsigned int bank); -+bool stm32mp_gpio_bank_is_non_secure(unsigned int bank); -+bool stm32mp_gpio_bank_is_secure(unsigned int bank); -+ -+bool stm32mp_clock_is_shareable(unsigned long clock_id); -+bool stm32mp_clock_is_shared(unsigned long clock_id); -+bool stm32mp_clock_is_non_secure(unsigned long clock_id); -+ -+/* -+ * Set bit fields, clear bit flieds, clear bits and set bits utils -+ */ -+static inline void mmio_write_8(uintptr_t addr, uint8_t value) -+{ -+ write8(value, addr); -+} -+ -+static inline uint8_t mmio_read_8(uintptr_t addr) -+{ -+ return read8(addr); -+} -+ -+static inline void mmio_write_32(uintptr_t addr, uint32_t value) -+{ -+ write32(value, addr); -+} -+ -+static inline uint32_t mmio_read_32(uintptr_t addr) -+{ -+ return read32(addr); -+} -+ -+static inline void mmio_setbits_32(uintptr_t addr, uint32_t mask) -+{ -+ write32(read32(addr) | mask, addr); -+} -+ -+static inline void mmio_clrbits_32(uintptr_t addr, uint32_t mask) -+{ -+ write32(read32(addr) & ~mask, addr); -+} -+ -+static inline void mmio_clrsetbits_32(uintptr_t addr, uint32_t clear_mask, -+ uint32_t set_mask) -+{ -+ write32((read32(addr) & ~clear_mask) | set_mask, addr); -+} -+ -+#endif /*__STM32_UTIL_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c b/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c -new file mode 100644 -index 0000000..9ce6ba8 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c -@@ -0,0 +1,338 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/******************************************************************************* -+ * This function check the presence of a node (generic use of fdt library). -+ * Returns true if present else returns false. -+ ******************************************************************************/ -+bool fdt_check_node(void *fdt, int node) -+{ -+ int len; -+ const char *cchar; -+ -+ cchar = fdt_get_name(fdt, node, &len); -+ -+ return (cchar != NULL) && (len >= 0); -+} -+ -+/******************************************************************************* -+ * This function reads a value of a node property (generic use of fdt -+ * library). -+ * Returns value if success, and a default value if property not found. -+ * Default value is passed as parameter. -+ ******************************************************************************/ -+uint32_t fdt_read_uint32_default(void *fdt, int node, const char *prop_name, -+ uint32_t dflt_value) -+{ -+ const fdt32_t *cuint; -+ int lenp; -+ -+ cuint = fdt_getprop(fdt, node, prop_name, &lenp); -+ if (cuint == NULL) { -+ return dflt_value; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* -+ * This function reads a series of parameters in a node property -+ * (generic use of fdt library). -+ * It reads the values inside the device tree, from property name and node. -+ * The number of parameters is also indicated as entry parameter. -+ * Returns 0 if success, and a negative value else. -+ * If success, values are stored at the third parameter address. -+ ******************************************************************************/ -+int fdt_read_uint32_array(void *fdt, int node, const char *prop_name, -+ uint32_t *array, uint32_t count) -+{ -+ const fdt32_t *cuint; -+ int len; -+ uint32_t i; -+ -+ cuint = fdt_getprop(fdt, node, prop_name, &len); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ if ((uint32_t)len != (count * sizeof(uint32_t))) { -+ return -FDT_ERR_BADLAYOUT; -+ } -+ -+ for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { -+ *array = fdt32_to_cpu(*cuint); -+ array++; -+ cuint++; -+ } -+ -+ return 0; -+} -+ -+/******************************************************************************* -+ * This function gets the clock ID of the given node. -+ * It reads the value indicated inside the device tree. -+ * Returns ID on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int fdt_get_clock_id(void *fdt, int node) -+{ -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "clocks", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ 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 error code on failure. -+ ******************************************************************************/ -+int fdt_get_clock_id_by_name(void *fdt, int node, const char *name) -+{ -+ const fdt32_t *cuint; -+ int index; -+ int len; -+ -+ 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); -+} -+ -+/******************************************************************************* -+ * This function fills the generic information from a given node. -+ ******************************************************************************/ -+void fdt_fill_device_info(void *fdt, struct dt_node_info *info, int node) -+{ -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint != NULL) { -+ info->base = fdt32_to_cpu(*cuint); -+ } else { -+ info->base = 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "clocks", NULL); -+ if (cuint != NULL) { -+ cuint++; -+ info->clock = (int)fdt32_to_cpu(*cuint); -+ } else { -+ info->clock = -1; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "resets", NULL); -+ if (cuint != NULL) { -+ cuint++; -+ info->reset = (int)fdt32_to_cpu(*cuint); -+ } else { -+ info->reset = -1; -+ } -+ -+ info->status = _fdt_get_status(fdt, node); -+} -+ -+/******************************************************************************* -+ * This function retrieve the generic information from DT. -+ * Returns node if success, and a negative value else. -+ ******************************************************************************/ -+int fdt_get_node(void *fdt, struct dt_node_info *info, int offset, -+ const char *compat) -+{ -+ int node; -+ -+ node = fdt_node_offset_by_compatible(fdt, offset, compat); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ fdt_fill_device_info(fdt, info, node); -+ -+ return node; -+} -+ -+/******************************************************************************* -+ * This function gets the stdout path node. -+ * It reads the value indicated inside the device tree. -+ * Returns node on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int fdt_get_stdout_node_offset(void *fdt) -+{ -+ int node; -+ const char *cchar; -+ -+ node = fdt_path_offset(fdt, "/secure-chosen"); -+ if (node < 0) { -+ node = fdt_path_offset(fdt, "/chosen"); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ } -+ -+ cchar = fdt_getprop(fdt, node, "stdout-path", NULL); -+ if (cchar == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ node = -FDT_ERR_NOTFOUND; -+ if (strchr(cchar, (int)':') != NULL) { -+ const char *name; -+ char *str = (char *)cchar; -+ int len = 0; -+ -+ while (strncmp(":", str, 1)) { -+ len++; -+ str++; -+ } -+ -+ name = fdt_get_alias_namelen(fdt, cchar, len); -+ -+ if (name != NULL) { -+ node = fdt_path_offset(fdt, name); -+ } -+ } else { -+ node = fdt_path_offset(fdt, cchar); -+ } -+ -+ return node; -+} -+ -+/******************************************************************************* -+ * This function gets DDR size information from the DT. -+ * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else. -+ ******************************************************************************/ -+uint32_t fdt_get_ddr_size(void *fdt) -+{ -+ int node; -+ -+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ if (node < 0) { -+ IMSG("%s: Cannot read DDR node in DT\n", __func__); -+ return STM32MP1_DDR_SIZE_DFLT; -+ } -+ -+ return fdt_read_uint32_default(fdt, node, "st,mem-size", -+ STM32MP1_DDR_SIZE_DFLT); -+} -+ -+/******************************************************************************* -+ * This function retrieves board model from DT. -+ * Returns string taken from model node, NULL otherwise -+ ******************************************************************************/ -+const char *fdt_get_board_model(void *fdt) -+{ -+ int node = fdt_path_offset(fdt, "/"); -+ -+ if (node < 0) { -+ return NULL; -+ } -+ -+ return (const char *)fdt_getprop(fdt, node, "model", NULL); -+} -+ -+/******************************************************************************* -+ * This function gets GPIO bank PINCTRL node information from the DT. -+ * Returns node value. -+ ******************************************************************************/ -+int fdt_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank) -+{ -+ switch (bank) { -+ case GPIO_BANK_A: -+ case GPIO_BANK_B: -+ case GPIO_BANK_C: -+ case GPIO_BANK_D: -+ case GPIO_BANK_E: -+ case GPIO_BANK_F: -+ case GPIO_BANK_G: -+ case GPIO_BANK_H: -+ case GPIO_BANK_I: -+ case GPIO_BANK_J: -+ case GPIO_BANK_K: -+ return fdt_path_offset(fdt, "/soc/pin-controller"); -+ case GPIO_BANK_Z: -+ return fdt_path_offset(fdt, "/soc/pin-controller-z"); -+ default: -+ panic(); -+ } -+} -+ -+/******************************************************************************* -+ * This function gets GPIOZ pin number information from the DT. -+ * It also checks node consistency. -+ ******************************************************************************/ -+int fdt_get_gpioz_nbpins_from_dt(void *fdt) -+{ -+ int pinctrl_node; -+ int pinctrl_subnode; -+ -+ pinctrl_node = fdt_get_gpio_bank_pinctrl_node(fdt, GPIO_BANK_Z); -+ if (pinctrl_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { -+ uint32_t bank_offset; -+ const fdt32_t *cuint; -+ -+ if (fdt_getprop(fdt, pinctrl_subnode, -+ "gpio-controller", NULL) == NULL) { -+ continue; -+ } -+ -+ cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); -+ if (cuint == NULL) { -+ continue; -+ } -+ -+ bank_offset = stm32_get_gpio_bank_offset(GPIO_BANK_Z); -+ if (fdt32_to_cpu(*cuint) != bank_offset) { -+ continue; -+ } -+ -+ if (_fdt_get_status(fdt, pinctrl_subnode) == -+ DT_STATUS_DISABLED) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, pinctrl_subnode, "ngpios", NULL); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return (int)fdt32_to_cpu(*cuint); -+ } -+ -+ return 0; -+} -diff --git a/core/arch/arm/plat-stm32mp1/stm32mp_dt.h b/core/arch/arm/plat-stm32mp1/stm32mp_dt.h -new file mode 100644 -index 0000000..ec8aa4d ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/stm32mp_dt.h -@@ -0,0 +1,39 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#ifndef __STM32MP1_DT_H__ -+#define __STM32MP1_DT_H__ -+ -+#include -+#include -+ -+#define DT_DDR_COMPAT "st,stm32mp1-ddr" -+ -+struct dt_node_info { -+ uint32_t base; -+ int32_t clock; -+ int32_t reset; -+ unsigned int status; -+}; -+ -+bool fdt_check_node(void *fdt, int node); -+uint32_t fdt_read_uint32_default(void *fdt, int node, const char *prop_name, -+ uint32_t dflt_value); -+int fdt_read_uint32_array(void *fdt, int node, const char *prop_name, -+ uint32_t *array, uint32_t count); -+void fdt_fill_device_info(void *fdt, struct dt_node_info *info, int node); -+int fdt_get_node(void *fdt, struct dt_node_info *info, int offset, -+ const char *compat); -+int fdt_get_stdout_node_offset(void *fdt); -+uint32_t fdt_get_ddr_size(void *fdt); -+const char *fdt_get_board_model(void *fdt); -+ -+int fdt_get_clock_id(void *fdt, int node); -+int fdt_get_clock_id_by_name(void *fdt, int node, const char *name); -+int fdt_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank); -+int fdt_get_gpioz_nbpins_from_dt(void *fdt); -+ -+#endif /* __STM32MP1_DT_H__ */ -diff --git a/core/arch/arm/plat-stm32mp1/stm32mp_pm.h b/core/arch/arm/plat-stm32mp1/stm32mp_pm.h -new file mode 100644 -index 0000000..8395ccc ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/stm32mp_pm.h -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: BSD-2-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+#ifndef __STM32MP_PM_H__ -+#define __STM32MP_PM_H__ -+ -+#ifndef ASM -+ -+#include -+#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 -+}; -+ -+enum pm_op { -+ PM_OP_SUSPEND, -+ PM_OP_RESUME, -+}; -+ -+/* -+ * Drivers can register a callback for the suspend and resume sequences and -+ * a private cookie passed as argument to the callback. -+ * The same callback is used for suspend and resume. First argument of the -+ * callback defines whether the device shall suspend or resume. -+ * -+ * Driver should tag its callback resource as unpaged (i.e KEEP_PAGER()) -+ * since the callback is called from an unpaged execution context. -+ */ -+void stm32mp_register_pm_cb(void (*callback)(enum pm_op op, void *handle), -+ void *handle); -+ -+void stm32_cores_reset(void); -+ -+void stm32mp_gic_suspend_resume(enum pm_op op); -+void stm32mp_clock_suspend_resume(enum pm_op op); -+ -+#endif /*ASM*/ -+ -+#endif /*__STM32MP_PM_H__*/ -+ -diff --git a/core/arch/arm/plat-stm32mp1/sub.mk b/core/arch/arm/plat-stm32mp1/sub.mk -index 4a559ea..c5a0deb 100644 ---- a/core/arch/arm/plat-stm32mp1/sub.mk -+++ b/core/arch/arm/plat-stm32mp1/sub.mk -@@ -2,3 +2,9 @@ global-incdirs-y += . - - srcs-y += main.c - srcs-y += reset.S -+srcs-y += shared_resources.c -+srcs-$(CFG_DT) += stm32mp1_dt.c -+ -+subdirs-y += service -+subdirs-y += drivers -+subdirs-y += pm -diff --git a/core/arch/arm/sm/pm_a32.S b/core/arch/arm/sm/pm_a32.S -index 9421b2d..8a59cd2 100644 ---- a/core/arch/arm/sm/pm_a32.S -+++ b/core/arch/arm/sm/pm_a32.S -@@ -69,25 +69,30 @@ a9_suspend: - a7_suspend: - read_fcseidr r4 - read_tpidruro r5 -- stmia r0!, {r4 - r5} -- read_dacr r4 -+ read_dacr r6 -+ stmia r0!, {r4 - r6} - #ifdef CFG_WITH_LPAE --#error "Not supported" -+ read_ttbr0_64bit r4, r5 -+ read_ttbr1_64bit r6, r7 -+ read_mair0 r8 -+ read_mair1 r9 -+ stmia r0!, {r4 - r9} - #else -- read_ttbr0 r5 -- read_ttbr1 r6 -- read_ttbcr r7 -+ read_ttbr0 r4 -+ read_ttbr1 r5 -+ read_prrr r6 -+ read_nmrr r7 -+ stmia r0!, {r4 - r7} - #endif -- read_sctlr r8 -- read_actlr r9 -- read_cpacr r10 -- read_mvbar r11 -- stmia r0!, {r4 - r11} -- read_prrr r4 -- read_nmrr r5 -- read_vbar r6 -- read_nsacr r7 -- stmia r0, {r4 - r7} -+ read_ttbcr r4 -+ read_actlr r5 -+ read_cpacr r6 -+ read_mvbar r7 -+ read_vbar r8 -+ read_nsacr r9 -+ read_sctlr r10 -+ stmia r0, {r4 - r10} -+ - pop {r4 - r11} - bx lr - UNWIND( .fnend) -@@ -154,50 +159,50 @@ UNWIND( .cantunwind) - cmp r5, r4 - beq a7_resume - -- /* -- * A9 needs PCR/DIAG -- */ -+ /* A9 needs PCR/DIAG */ - ldmia r0!, {r4 - r5} - write_pcr r4 - write_diag r5 -- - a7_resume: -- /* v7 resume */ -+ /* Armv7 generic resume */ - mov ip, #0 - /* Invalidate icache to PoU */ - write_iciallu - /* set reserved context */ - write_contextidr ip -- ldmia r0!, {r4 - r5} -+ ldmia r0!, {r4 - r6} - write_fcseidr r4 - write_tpidruro r5 -- ldmia r0!, {r4 - r11} - /* Invalidate entire TLB */ - write_tlbiall -- write_dacr r4 -+ write_dacr r6 - #ifdef CFG_WITH_LPAE --#error "Not supported -" -+ ldmia r0!, {r4 - r9} -+ write_ttbr0_64bit r4, r5 -+ write_ttbr1_64bit r6, r7 -+ write_mair0 r8 -+ write_mair1 r9 - #else -- write_ttbr0 r5 -- write_ttbr1 r6 -- write_ttbcr r7 -+ ldmia r0!, {r4 - r7} -+ write_ttbr0 r4 -+ write_ttbr1 r5 -+ write_prrr r6 -+ write_nmrr r7 - #endif -- -- ldmia r0, {r4 - r7} -- write_prrr r4 -- write_nmrr r5 -- write_vbar r6 -- write_nsacr r7 -- -- write_actlr r9 -- write_cpacr r10 -- write_mvbar r11 -+ ldmia r0!, {r4 - r10} -+ write_ttbcr r4 -+ write_actlr r5 -+ write_cpacr r6 -+ write_mvbar r7 -+ write_vbar r8 -+ write_nsacr r9 - write_bpiall - isb - dsb - /* MMU will be enabled here */ -- write_sctlr r8 -+ write_sctlr r10 - isb -+ - mov r0, #0 - b suspend_return - UNWIND( .fnend) -diff --git a/core/arch/arm/tee/entry_std.c b/core/arch/arm/tee/entry_std.c -index 92fdf0f..e0836ed 100644 ---- a/core/arch/arm/tee/entry_std.c -+++ b/core/arch/arm/tee/entry_std.c -@@ -602,4 +602,4 @@ static TEE_Result default_mobj_init(void) - return TEE_SUCCESS; - } - --driver_init_late(default_mobj_init); -+service_init(default_mobj_init); -diff --git a/core/drivers/gic.c b/core/drivers/gic.c -index 9baffee..a000bff 100644 ---- a/core/drivers/gic.c -+++ b/core/drivers/gic.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: BSD-2-Clause - /* -+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. - * Copyright (c) 2016-2017, Linaro Limited - * Copyright (c) 2014, STMicroelectronics International N.V. - */ -@@ -7,12 +8,14 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include - #include --#include - #include -+#include - - /* Offsets from gic.gicc_base */ - #define GICC_CTLR (0x000) -@@ -32,8 +35,12 @@ - #define GICD_ICENABLER(n) (0x180 + (n) * 4) - #define GICD_ISPENDR(n) (0x200 + (n) * 4) - #define GICD_ICPENDR(n) (0x280 + (n) * 4) -+#define GICD_ISACTIVER(n) (0x300 + (n) * 4) -+#define GICD_ICACTIVER(n) (0x380 + (n) * 4) - #define GICD_IPRIORITYR(n) (0x400 + (n) * 4) - #define GICD_ITARGETSR(n) (0x800 + (n) * 4) -+#define GICD_ICFGR(n) (0xC00 + (n) * 4) -+#define GICD_NSACR(n) (0xE00 + (n) * 4) - #define GICD_SGIR (0xF00) - - #define GICD_CTLR_ENABLEGRP0 (1 << 0) -@@ -74,6 +81,12 @@ static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, - static void gic_op_set_affinity(struct itr_chip *chip, size_t it, - uint8_t cpu_mask); - -+#if !defined(CFG_ARM_GICV3) -+static uint8_t gic_op_set_pmr(struct itr_chip *chip, uint8_t mask); -+static uint8_t gic_op_set_ipriority(struct itr_chip *chip, size_t it, -+ uint8_t mask); -+#endif -+ - static const struct itr_ops gic_ops = { - .add = gic_op_add, - .enable = gic_op_enable, -@@ -81,6 +94,10 @@ static const struct itr_ops gic_ops = { - .raise_pi = gic_op_raise_pi, - .raise_sgi = gic_op_raise_sgi, - .set_affinity = gic_op_set_affinity, -+#if !defined(CFG_ARM_GICV3) -+ .set_pmr = gic_op_set_pmr, -+ .set_ipriority = gic_op_set_ipriority, -+#endif - }; - KEEP_PAGER(gic_ops); - -@@ -146,11 +163,11 @@ void gic_cpu_init(struct gic_data *gd) - * allow the Non-secure world to adjust the priority mask itself - */ - #if defined(CFG_ARM_GICV3) -- write_icc_pmr(0x80); -+ write_icc_pmr(GIC_HIGHEST_NS_PRIORITY); - write_icc_ctlr(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | - GICC_CTLR_FIQEN); - #else -- write32(0x80, gd->gicc_base + GICC_PMR); -+ write32(GIC_HIGHEST_NS_PRIORITY, gd->gicc_base + GICC_PMR); - - /* Enable GIC */ - write32(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | GICC_CTLR_FIQEN, -@@ -189,11 +206,11 @@ void gic_init(struct gic_data *gd, vaddr_t gicc_base __maybe_unused, - * allow the Non-secure world to adjust the priority mask itself - */ - #if defined(CFG_ARM_GICV3) -- write_icc_pmr(0x80); -+ write_icc_pmr(GIC_HIGHEST_NS_PRIORITY); - write_icc_ctlr(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | - GICC_CTLR_FIQEN); - #else -- write32(0x80, gd->gicc_base + GICC_PMR); -+ write32(GIC_HIGHEST_NS_PRIORITY, gd->gicc_base + GICC_PMR); - - /* Enable GIC */ - write32(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | GICC_CTLR_FIQEN, -@@ -254,9 +271,20 @@ static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio) - { - size_t idx __maybe_unused = it / NUM_INTS_PER_REG; - uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); -+ bool group0 = ((read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask) == 0); - -- /* Assigned to group0 */ -- assert(!(read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); -+ /* -+ * Check priority against ARM recommendation: Group1 interrupts always -+ * have a lower priority than group0 interrupts. -+ * Note, lower numerical values have higher priorities so the comparison -+ * checks below are reversed from what might be expected. -+ */ -+ if (group0) { -+ assert(prio <= GIC_LOWEST_SEC_PRIORITY); -+ } else { -+ assert(prio >= GIC_HIGHEST_NS_PRIORITY && -+ prio <= GIC_LOWEST_NS_PRIORITY); -+ } - - /* Set prio it to selected CPUs */ - DMSG("prio: writing 0x%x to 0x%" PRIxVA, -@@ -264,6 +292,34 @@ static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio) - write8(prio, gd->gicd_base + GICD_IPRIORITYR(0) + it); - } - -+static uint8_t gic_op_set_pmr(struct itr_chip *chip, uint8_t mask) -+{ -+ struct gic_data *gd = container_of(chip, struct gic_data, chip); -+ uint32_t pmr = read32(gd->gicc_base + GICC_PMR); -+ -+ /* -+ * Order memory updates w.r.t. PMR write, and ensure they're visible -+ * before potential out of band interrupt trigger because of PMR update. -+ */ -+ dsb_ishst(); -+ write32(mask, gd->gicc_base + GICC_PMR); -+ dsb_ishst(); -+ -+ return (uint8_t)pmr; -+} -+ -+static uint8_t gic_op_set_ipriority(struct itr_chip *chip, size_t it, -+ uint8_t mask) -+{ -+ struct gic_data *gd = container_of(chip, struct gic_data, chip); -+ uint8_t prio = read8(gd->gicd_base + GICD_IPRIORITYR(0) + it); -+ -+ gic_it_set_prio(gd, it, mask); -+ -+ return prio; -+} -+ -+ - static void gic_it_enable(struct gic_data *gd, size_t it) - { - size_t idx = it / NUM_INTS_PER_REG; -@@ -472,3 +528,143 @@ static void gic_op_set_affinity(struct itr_chip *chip, size_t it, - - gic_it_set_cpu_mask(gd, it, cpu_mask); - } -+ -+#define IT_PM_GPOUP1_BIT BIT(0) -+#define IT_PM_ENABLE_BIT BIT(1) -+#define IT_PM_PENDING_BIT BIT(2) -+#define IT_PM_ACTIVE_BIT BIT(3) -+#define IT_PM_CONFIG_MASK GENMASK_32(1, 0) -+ -+struct gic_it_pm { -+ uint16_t it; -+ uint8_t flags; -+ uint8_t iprio; -+ uint8_t itarget; -+ uint8_t icfg; -+}; -+ -+static void gic_save_it(struct gic_data *gd, -+ unsigned int it, struct gic_it_pm *pm) -+{ -+ size_t idx; -+ uint32_t bit_mask = BIT(it % NUM_INTS_PER_REG); -+ uint32_t shift2 = it % (NUM_INTS_PER_REG / 2); -+ uint32_t shift8 = it % (NUM_INTS_PER_REG / 8); -+ uint32_t data32; -+ -+ assert(it < UINT16_MAX); -+ pm->it = (uint16_t)it; -+ -+ idx = it / NUM_INTS_PER_REG; -+ -+ pm->flags = 0; -+ if ((read32(gd->gicd_base + GICD_IGROUPR(idx)) & bit_mask) != 0) { -+ pm->flags |= IT_PM_GPOUP1_BIT; -+ } -+ if ((read32(gd->gicd_base + GICD_ISENABLER(idx)) & bit_mask) != 0) { -+ pm->flags |= IT_PM_ENABLE_BIT; -+ } -+ if ((read32(gd->gicd_base + GICD_ISPENDR(idx)) & bit_mask) != 0) { -+ pm->flags |= IT_PM_PENDING_BIT; -+ } -+ if ((read32(gd->gicd_base + GICD_ISACTIVER(idx)) & bit_mask) != 0) { -+ pm->flags |= IT_PM_ACTIVE_BIT; -+ } -+ -+ idx = (8 * it) / NUM_INTS_PER_REG; -+ -+ data32 = read32(gd->gicd_base + GICD_IPRIORITYR(idx)) >> shift8; -+ pm->iprio = (uint8_t)data32; -+ -+ data32 = read32(gd->gicd_base + GICD_ITARGETSR(idx)) >> shift8; -+ pm->itarget = (uint8_t)data32; -+ -+ /* Note: ICFGR is RAO for SPIs and PPIs */ -+ idx = (2 * it) / NUM_INTS_PER_REG; -+ data32 = read32(gd->gicd_base + GICD_ICFGR(idx)) >> shift2; -+ pm->icfg = (uint8_t)data32 & IT_PM_CONFIG_MASK; -+} -+ -+static void gic_restore_it(struct gic_data *gd, struct gic_it_pm *pm) -+{ -+ size_t idx; -+ unsigned int it = (unsigned int)pm->it; -+ uint32_t mask = BIT(it % NUM_INTS_PER_REG); -+ uint32_t shift2 = it % (NUM_INTS_PER_REG / 2); -+ uint32_t shift8 = it % (NUM_INTS_PER_REG / 8); -+ -+ idx = it / NUM_INTS_PER_REG; -+ -+ io_mask32(gd->gicd_base + GICD_IGROUPR(idx), -+ (pm->flags & IT_PM_GPOUP1_BIT) != 0 ? mask : 0, mask); -+ -+ io_mask32(gd->gicd_base + GICD_ISENABLER(idx), -+ (pm->flags & IT_PM_ENABLE_BIT) != 0 ? mask : 0, mask); -+ -+ io_mask32(gd->gicd_base + GICD_ISPENDR(idx), -+ (pm->flags & IT_PM_PENDING_BIT) != 0 ? mask : 0, mask); -+ -+ io_mask32(gd->gicd_base + GICD_ISACTIVER(idx), -+ (pm->flags & IT_PM_ACTIVE_BIT) != 0 ? mask : 0, mask); -+ -+ idx = (8 * it) / NUM_INTS_PER_REG; -+ -+ io_mask32(gd->gicd_base + GICD_IPRIORITYR(idx), -+ (uint32_t)pm->iprio << shift8, UINT8_MAX << shift8); -+ -+ io_mask32(gd->gicd_base + GICD_ITARGETSR(idx), -+ (uint32_t)pm->itarget << shift8, UINT8_MAX << shift8); -+ -+ /* Note: ICFGR is WI for SPIs and PPIs */ -+ idx = (2 * it) / NUM_INTS_PER_REG; -+ io_mask32(gd->gicd_base + GICD_ICFGR(idx), -+ (uint32_t)pm->icfg << shift2, IT_PM_CONFIG_MASK << shift2); -+} -+ -+static bool it_is_group0(struct gic_data *gd, unsigned int it) -+{ -+ size_t idx = it / NUM_INTS_PER_REG; -+ uint32_t groupr = read32(gd->gicd_base + GICD_IGROUPR(idx)); -+ uint32_t bit_mask = BIT(it % NUM_INTS_PER_REG); -+ -+ return (groupr & bit_mask) == 0; -+} -+ -+/* Save the configuration for interrupts in group0 only */ -+void gic_suspend(struct gic_data *gd) -+{ -+ struct gic_pm *pm = &gd->pm; -+ unsigned int n; -+ size_t count; -+ -+ for (count = 0, n = 0; n <= gd->max_it; n++) { -+ if (it_is_group0(gd, n)) { -+ count++; -+ } -+ } -+ pm->count = count; -+ -+ if (count == 0) { -+ return; -+ } -+ -+ pm->pm_cfg = realloc(pm->pm_cfg, count * sizeof(*pm->pm_cfg)); -+ assert(pm->pm_cfg != NULL); -+ -+ for (count = 0, n = 0; n <= gd->max_it; n++) { -+ if (it_is_group0(gd, n)) { -+ gic_save_it(gd, n, &pm->pm_cfg[count]); -+ count++; -+ } -+ } -+} -+ -+void gic_resume(struct gic_data *gd) -+{ -+ struct gic_pm *pm = &gd->pm; -+ size_t n; -+ -+ for (n = 0; n < pm->count; n++) { -+ gic_restore_it(gd, &pm->pm_cfg[n]); -+ } -+} -diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c -new file mode 100644 -index 0000000..3355e0a ---- /dev/null -+++ b/core/drivers/stm32_bsec.c -@@ -0,0 +1,824 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CFG_DT -+#include -+#endif -+ -+#define BSEC_COMPAT "st,stm32mp15-bsec" -+#define BITS_PER_WORD (CHAR_BIT * sizeof(uint32_t)) -+#define OTP_ACCESS_SIZE (ROUNDUP(OTP_MAX_SIZE, BITS_PER_WORD) / BITS_PER_WORD) -+ -+static uint32_t __maybe_unused otp_nsec_access[OTP_ACCESS_SIZE]; -+ -+static uint32_t bsec_power_safmem(bool enable); -+ -+/* Bsec access protection */ -+static unsigned int lock = SPINLOCK_UNLOCK; -+ -+static uint32_t bsec_lock(void) -+{ -+ return may_spin_lock(&lock); -+} -+ -+static void bsec_unlock(uint32_t exceptions) -+{ -+ may_spin_unlock(&lock, exceptions); -+} -+ -+#ifdef CFG_DT -+static int bsec_get_dt_node(void *fdt, struct dt_node_info *info) -+{ -+ int node; -+ -+ node = fdt_get_node(fdt, info, -1, BSEC_COMPAT); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return node; -+} -+ -+static void enable_non_secure_access(uint32_t otp) -+{ -+ otp_nsec_access[otp / BITS_PER_WORD] |= BIT(otp % BITS_PER_WORD); -+ -+ if (bsec_shadow_register(otp) != BSEC_OK) { -+ panic(); -+ } -+} -+ -+static bool non_secure_can_access(uint32_t otp) -+{ -+ return (otp_nsec_access[otp / BITS_PER_WORD] & -+ BIT(otp % BITS_PER_WORD)) != 0; -+} -+ -+static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node) -+{ -+ int bsec_subnode; -+ -+ fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { -+ const fdt32_t *cuint; -+ uint32_t reg; -+ uint32_t i; -+ uint32_t size; -+ uint8_t status; -+ -+ 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; -+ } -+ -+ status = _fdt_get_status(fdt, bsec_subnode); -+ if ((status & DT_STATUS_OK_NSEC) == 0U) { -+ continue; -+ } -+ -+ size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t); -+ -+ if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) { -+ size++; -+ } -+ -+ for (i = reg; i < (reg + size); i++) { -+ enable_non_secure_access(i); -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+static uint32_t otp_bank_offset(uint32_t otp) -+{ -+ assert(otp <= stm32mp_get_otp_max()); -+ -+ return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * -+ sizeof(uint32_t); -+} -+ -+static uintptr_t bsec_get_base(void) -+{ -+ static void *va; -+ -+ if (!cpu_mmu_enabled()) -+ return BSEC_BASE; -+ -+ if (!va) -+ va = phys_to_virt(BSEC_BASE, MEM_AREA_IO_SEC); -+ -+ return (vaddr_t)va; -+} -+ -+/* -+ * bsec_check_error -+ * otp : OTP number. -+ * return value : BSEC_OK if no error. -+ */ -+static uint32_t bsec_check_error(uint32_t otp) -+{ -+ uint32_t bit = BIT(otp & BSEC_OTP_MASK); -+ uint32_t bank = otp_bank_offset(otp); -+ -+ if ((read32(bsec_get_base() + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { -+ return BSEC_DISTURBED; -+ } -+ -+ if ((read32(bsec_get_base() + BSEC_ERROR_OFF + bank) & bit) != 0U) { -+ return BSEC_ERROR; -+ } -+ -+ return BSEC_OK; -+} -+ -+/* -+ * bsec_shadow_register: copy SAFMEM OTP to BSEC data. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_shadow_register(uint32_t otp) -+{ -+ uint32_t result; -+ uint32_t exc; -+ -+ if (otp > stm32mp_get_otp_max()) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ /* Check if shadowing of OTP is locked */ -+ if (bsec_read_sr_lock(otp)) { -+ IMSG("BSEC: OTP locked, register will not be refreshed"); -+ } -+ -+ result = bsec_power_safmem(true); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ exc = bsec_lock(); -+ -+ write32(otp | BSEC_READ, bsec_get_base() + BSEC_OTP_CTRL_OFF); -+ -+ while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { -+ ; -+ } -+ -+ result = bsec_check_error(otp); -+ -+ bsec_unlock(exc); -+ -+ bsec_power_safmem(false); -+ -+ return result; -+} -+ -+/* -+ * bsec_read_otp: read an OTP data value. -+ * val: read value. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) -+{ -+ uint32_t exc; -+ uint32_t result; -+ -+ if (otp > stm32mp_get_otp_max()) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ exc = bsec_lock(); -+ -+ *val = read32(bsec_get_base() + BSEC_OTP_DATA_OFF + -+ (otp * sizeof(uint32_t))); -+ -+ result = bsec_check_error(otp); -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_write_otp: write value in BSEC data register. -+ * val: value to write. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_write_otp(uint32_t val, uint32_t otp) -+{ -+ uint32_t exc; -+ uint32_t result; -+ -+ if (otp > stm32mp_get_otp_max()) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ /* Check if programming of OTP is locked */ -+ if (bsec_read_sw_lock(otp)) { -+ IMSG("BSEC: OTP locked, write will be ignored"); -+ } -+ -+ exc = bsec_lock(); -+ -+ write32(val, bsec_get_base() + BSEC_OTP_DATA_OFF + -+ (otp * sizeof(uint32_t))); -+ -+ result = bsec_check_error(otp); -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_program_otp: program a bit in SAFMEM after the prog. -+ * The OTP data is not refreshed. -+ * val: value to program. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_program_otp(uint32_t val, uint32_t otp) -+{ -+ uint32_t result; -+ uint32_t exc; -+ -+ if (otp > stm32mp_get_otp_max()) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ /* Check if programming of OTP is locked */ -+ if (bsec_read_sp_lock(otp)) { -+ IMSG("BSEC: OTP locked, prog will be ignored"); -+ } -+ -+ if ((read32(bsec_get_base() + BSEC_OTP_LOCK_OFF) & -+ BIT(BSEC_LOCK_PROGRAM)) != 0U) { -+ IMSG("BSEC: GPLOCK activated, prog will be ignored"); -+ } -+ -+ result = bsec_power_safmem(true); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ exc = bsec_lock(); -+ -+ write32(val, bsec_get_base() + BSEC_OTP_WRDATA_OFF); -+ write32(otp | BSEC_WRITE, bsec_get_base() + BSEC_OTP_CTRL_OFF); -+ -+ while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { -+ ; -+ } -+ -+ if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { -+ result = BSEC_PROG_FAIL; -+ } else { -+ result = bsec_check_error(otp); -+ } -+ -+ bsec_unlock(exc); -+ -+ bsec_power_safmem(false); -+ -+ return result; -+} -+ -+/* -+ * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM. -+ * otp: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_permanent_lock_otp(uint32_t otp) -+{ -+ uint32_t result; -+ uint32_t data; -+ uint32_t addr; -+ uint32_t exc; -+ -+ if (otp > stm32mp_get_otp_max()) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ result = bsec_power_safmem(true); -+ if (result != BSEC_OK) { -+ return result; -+ } -+ -+ if (otp < stm32mp_get_otp_upper_start()) { -+ addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT; -+ data = DATA_LOWER_OTP_PERLOCK_BIT << -+ ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); -+ } else { -+ addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U; -+ data = DATA_UPPER_OTP_PERLOCK_BIT << -+ (otp & DATA_UPPER_OTP_PERLOCK_MASK); -+ } -+ -+ exc = bsec_lock(); -+ -+ write32(data, bsec_get_base() + BSEC_OTP_WRDATA_OFF); -+ write32(addr | BSEC_WRITE | BSEC_LOCK, -+ bsec_get_base() + BSEC_OTP_CTRL_OFF); -+ -+ while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { -+ ; -+ } -+ -+ if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { -+ result = BSEC_PROG_FAIL; -+ } else { -+ result = bsec_check_error(otp); -+ } -+ -+ bsec_unlock(exc); -+ -+ bsec_power_safmem(false); -+ -+ return result; -+} -+ -+/* -+ * bsec_write_debug_conf: write value in debug feature -+ * to enable/disable debug service. -+ * val: value to write. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_write_debug_conf(uint32_t val) -+{ -+ uint32_t result = BSEC_ERROR; -+ uint32_t masked_val = val & BSEC_DEN_ALL_MSK; -+ unsigned int exc; -+ -+ exc = bsec_lock(); -+ -+ write32(val, bsec_get_base() + BSEC_DEN_OFF); -+ -+ if ((read32(bsec_get_base() + BSEC_DEN_OFF) ^ masked_val) == 0U) { -+ result = BSEC_OK; -+ } -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_read_debug_conf : read debug configuration. -+ */ -+uint32_t bsec_read_debug_conf(void) -+{ -+ return read32(bsec_get_base() + BSEC_DEN_OFF); -+} -+ -+/* -+ * bsec_get_status : return status register value. -+ */ -+uint32_t bsec_get_status(void) -+{ -+ return read32(bsec_get_base() + BSEC_OTP_STATUS_OFF); -+} -+ -+/* -+ * bsec_get_hw_conf : return hardware configuration. -+ */ -+uint32_t bsec_get_hw_conf(void) -+{ -+ return read32(bsec_get_base() + BSEC_IPHW_CFG_OFF); -+} -+ -+/* -+ * bsec_get_version : return BSEC version. -+ */ -+uint32_t bsec_get_version(void) -+{ -+ return read32(bsec_get_base() + BSEC_IPVR_OFF); -+} -+ -+/* -+ * bsec_get_id : return BSEC ID. -+ */ -+uint32_t bsec_get_id(void) -+{ -+ return read32(bsec_get_base() + BSEC_IP_ID_OFF); -+} -+ -+/* -+ * bsec_get_magic_id : return BSEC magic number. -+ */ -+uint32_t bsec_get_magic_id(void) -+{ -+ return read32(bsec_get_base() + BSEC_IP_MAGIC_ID_OFF); -+} -+ -+/* -+ * bsec_write_sr_lock: write shadow-read lock. -+ * otp: OTP number. -+ * value: value to write in the register. -+ * Must be always 1. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_write_sr_lock(uint32_t otp, uint32_t value) -+{ -+ bool result = false; -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t bank_value; -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); -+ uint32_t exc; -+ -+ exc = bsec_lock(); -+ -+ bank_value = read32(bsec_get_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. -+ */ -+ write32(bank_value, bsec_get_base() + BSEC_SRLOCK_OFF + bank); -+ result = true; -+ } -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_read_sr_lock: read shadow-read lock. -+ * otp: OTP number. -+ * return: true if otp is locked, else false. -+ */ -+bool bsec_read_sr_lock(uint32_t otp) -+{ -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); -+ uint32_t bank_value = read32(bsec_get_base() + BSEC_SRLOCK_OFF + bank); -+ -+ return (bank_value & otp_mask) != 0U; -+} -+ -+/* -+ * bsec_write_sw_lock: write shadow-write lock. -+ * otp: OTP number. -+ * value: Value to write in the register. -+ * Must be always 1. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_write_sw_lock(uint32_t otp, uint32_t value) -+{ -+ bool result = false; -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); -+ uint32_t bank_value; -+ unsigned int exc; -+ -+ exc = bsec_lock(); -+ -+ bank_value = read32(bsec_get_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. -+ */ -+ write32(bank_value, bsec_get_base() + BSEC_SWLOCK_OFF + bank); -+ result = true; -+ } -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_read_sw_lock: read shadow-write lock. -+ * otp: OTP number. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_read_sw_lock(uint32_t otp) -+{ -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); -+ uint32_t bank_value = read32(bsec_get_base() + BSEC_SWLOCK_OFF + bank); -+ -+ return (bank_value & otp_mask) != 0U; -+} -+ -+/* -+ * bsec_write_sp_lock: write shadow-program lock. -+ * otp: OTP number. -+ * value: Value to write in the register. -+ * Must be always 1. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_write_sp_lock(uint32_t otp, uint32_t value) -+{ -+ bool result = false; -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t bank_value; -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); -+ unsigned int exc; -+ -+ exc = bsec_lock(); -+ -+ bank_value = read32(bsec_get_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. -+ */ -+ write32(bank_value, bsec_get_base() + BSEC_SPLOCK_OFF + bank); -+ result = true; -+ } -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_read_sp_lock: read shadow-program lock. -+ * otp: OTP number. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_read_sp_lock(uint32_t otp) -+{ -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); -+ uint32_t bank_value = read32(bsec_get_base() + BSEC_SPLOCK_OFF + bank); -+ -+ return (bank_value & otp_mask) != 0U; -+} -+ -+/* -+ * bsec_wr_lock: Read permanent lock status. -+ * otp: OTP number. -+ * return: true if OTP is locked, else false. -+ */ -+bool bsec_wr_lock(uint32_t otp) -+{ -+ uint32_t bank = otp_bank_offset(otp); -+ uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK); -+ -+ if ((read32(bsec_get_base() + BSEC_WRLOCK_OFF + bank) & -+ lock_bit) != 0U) { -+ /* -+ * In case of write don't need to write, -+ * the lock is already set. -+ */ -+ return true; -+ } -+ -+ return false; -+} -+ -+/* -+ * bsec_otp_lock: Lock Upper OTP or Global programming or debug enable -+ * service: Service to lock see header file. -+ * value: Value to write must always set to 1 (only use for debug purpose). -+ * return: BSEC_OK if succeed. -+ */ -+uint32_t bsec_otp_lock(uint32_t service, uint32_t value) -+{ -+ uintptr_t reg = bsec_get_base() + BSEC_OTP_LOCK_OFF; -+ -+ switch (service) { -+ case BSEC_LOCK_UPPER_OTP: -+ write32(value << BSEC_LOCK_UPPER_OTP, reg); -+ break; -+ case BSEC_LOCK_DEBUG: -+ write32(value << BSEC_LOCK_DEBUG, reg); -+ break; -+ case BSEC_LOCK_PROGRAM: -+ write32(value << BSEC_LOCK_PROGRAM, reg); -+ break; -+ default: -+ return BSEC_INVALID_PARAM; -+ } -+ -+ return BSEC_OK; -+} -+ -+static uint32_t enable_power(void) -+{ -+ size_t cntdown; -+ -+ io_mask32(bsec_get_base() + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP_MASK, -+ BSEC_CONF_POWER_UP_MASK); -+ -+ for (cntdown = BSEC_TIMEOUT_VALUE; cntdown; cntdown--) { -+ if (bsec_get_status() & BSEC_MODE_PWR_MASK) { -+ break; -+ } -+ } -+ -+ return cntdown ? BSEC_OK : BSEC_TIMEOUT; -+} -+ -+static uint32_t disable_power(void) -+{ -+ size_t cntdown; -+ -+ io_mask32(bsec_get_base() + BSEC_OTP_CONF_OFF, 0, -+ BSEC_CONF_POWER_UP_MASK); -+ -+ for (cntdown = BSEC_TIMEOUT_VALUE; cntdown; cntdown--) { -+ if (!(bsec_get_status() & BSEC_MODE_PWR_MASK)) { -+ break; -+ } -+ } -+ -+ return cntdown ? BSEC_OK : BSEC_TIMEOUT; -+} -+ -+/* -+ * bsec_power_safmem: Activate or deactivate SAFMEM power. -+ * power: true to power up, false to power down. -+ * return: BSEC_OK if succeed. -+ */ -+static uint32_t bsec_power_safmem(bool enable) -+{ -+ static unsigned int refcnt = ~0UL; -+ uint32_t result = BSEC_OK; -+ uint32_t exc = 0; -+ -+ /* Get the initial state */ -+ if (refcnt == ~0UL) { -+ refcnt = !!(bsec_get_status() & BSEC_MODE_PWR_MASK); -+ DMSG("Reset SAFMEM refcnt to %u", refcnt); -+ } -+ -+ exc = bsec_lock(); -+ -+ if (enable && (incr_refcnt(&refcnt) != 0U)) { -+ result = enable_power(); -+ } -+ -+ if (!enable && (decr_refcnt(&refcnt) != 0U)) { -+ result = disable_power(); -+ } -+ -+ bsec_unlock(exc); -+ -+ return result; -+} -+ -+/* -+ * bsec_mode_is_closed_device: read OTP secure sub-mode. -+ * return: false if open_device and true of closed_device. -+ */ -+bool bsec_mode_is_closed_device(void) -+{ -+ uint32_t value; -+ -+ if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) || -+ (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) { -+ return true; -+ } -+ -+ return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED; -+} -+ -+/* -+ * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value -+ * otp_value: read value. -+ * word: OTP number. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) -+{ -+ uint32_t result; -+ -+ result = bsec_shadow_register(word); -+ if (result != BSEC_OK) { -+ EMSG("BSEC: %u Shadowing Error %i\n", word, result); -+ return result; -+ } -+ -+ result = bsec_read_otp(otp_value, word); -+ if (result != BSEC_OK) { -+ EMSG("BSEC: %u Read Error %i\n", word, result); -+ } -+ -+ return result; -+} -+ -+/* -+ * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. -+ * otp: OTP number. -+ * return: BSEC_OK if authorized access. -+ */ -+uint32_t bsec_check_nsec_access_rights(uint32_t otp) -+{ -+ if (otp > stm32mp_get_otp_max()) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ if (otp >= stm32mp_get_otp_upper_start()) { -+ /* Check if BSEC is in OTP-SECURED closed_device state. */ -+ if (bsec_mode_is_closed_device()) { -+#ifdef CFG_DT -+ if (!non_secure_can_access(otp)) { -+ return BSEC_ERROR; -+ } -+#else -+ return BSEC_ERROR; -+#endif -+ } -+ } -+ -+ return BSEC_OK; -+} -+ -+#ifdef CFG_DT -+static TEE_Result initialize_bsec(void) -+{ -+ void *fdt; -+ int node; -+ struct dt_node_info bsec_info; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ node = bsec_get_dt_node(fdt, &bsec_info); -+ if (node < 0) { -+ panic(); -+ } -+ -+ bsec_dt_otp_nsec_access(fdt, node); -+ -+ return TEE_SUCCESS; -+} -+driver_init(initialize_bsec); -+#endif -diff --git a/core/drivers/stm32_etzpc.c b/core/drivers/stm32_etzpc.c -new file mode 100644 -index 0000000..fcb32e6 ---- /dev/null -+++ b/core/drivers/stm32_etzpc.c -@@ -0,0 +1,337 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CFG_DT -+#include -+#endif -+ -+#define ETZPC_COMPAT "st,stm32-etzpc" -+#define ETZPC_LOCK_MASK 0x1U -+#define ETZPC_MODE_SHIFT 8 -+#define ETZPC_MODE_MASK GENMASK_32(1, 0) -+#define ETZPC_ID_SHIFT 16 -+#define ETZPC_ID_MASK GENMASK_32(7, 0) -+ -+/* ID Registers */ -+#define ETZPC_TZMA0_SIZE 0x000U -+#define ETZPC_DECPROT0 0x010U -+#define ETZPC_DECPROT_LOCK0 0x030U -+#define ETZPC_HWCFGR 0x3F0U -+#define ETZPC_VERR 0x3F4U -+ -+/* ID Registers fields */ -+#define ETZPC_TZMA0_SIZE_LOCK BIT(31) -+#define ETZPC_DECPROT0_MASK GENMASK_32(1, 0) -+#define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0 -+#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8 -+#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16 -+#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24 -+ -+#define DECPROT_SHIFT 1 -+#define IDS_PER_DECPROT_REGS 16U -+#define IDS_PER_DECPROT_LOCK_REGS 32U -+ -+#define ETZPC_TZMA_ALL_SECURE 0x3FF -+#define ETZPC_TZMA_ALL_NO_SECURE 0x000 -+ -+/* -+ * etzpc_instance. -+ * base : register virtual base address set during init given by user -+ * pbase : register physical base address set during init given by user -+ * chunk_size : supported TZMA size steps -+ * num_tzma: number of TZMA zone read from register at init -+ * num_ahb_sec : number of securable AHB master zone read from register -+ * num_per_sec : number of securable AHB & APB Peripherals read from register -+ * revision : IP revision read from register at init -+ * periph_cfg : buffer storing holding the DECPROT configuration for peripherals -+ */ -+struct etzpc_instance { -+ uintptr_t base; -+ paddr_t pbase; -+ uint8_t chunck_size; -+ uint8_t num_tzma; -+ uint8_t num_per_sec; -+ uint8_t num_ahb_sec; -+ uint8_t revision; -+ uint8_t *periph_cfg; -+}; -+ -+/* Only 1 instance of the ETZPC is expected per platform */ -+static struct etzpc_instance etzpc_dev; -+ -+#ifdef CFG_DT -+struct dt_id_attr { -+ /* The effective size of the array is meaningless here */ -+ fdt32_t id_attr[1]; -+}; -+#endif -+ -+/* -+ * Implementation uses uint8_t to store each securable DECPROT configuration. -+ * When resuming from deep suspend, the DECPROT configurations are restored. -+ */ -+#define PERIPH_LOCK_BIT BIT(7) -+#define PERIPH_ATTR_MASK GENMASK_32(2, 0) -+ -+static uintptr_t etzpc_base(void) -+{ -+ if (!cpu_mmu_enabled()) -+ return etzpc_dev.pbase; -+ -+ if (!etzpc_dev.base) -+ etzpc_dev.base = (uintptr_t)phys_to_virt(etzpc_dev.pbase, -+ MEM_AREA_IO_SEC); -+ -+ return etzpc_dev.base; -+} -+ -+static bool valid_decprot_id(unsigned int id) -+{ -+ return id < (unsigned int)etzpc_dev.num_per_sec; -+} -+ -+static bool valid_tzma_id(unsigned int id) -+{ -+ return id < (unsigned int)etzpc_dev.num_tzma; -+} -+ -+#ifdef CFG_DT -+static int etzpc_dt_conf_decprot(void *fdt, int node) -+{ -+ const struct dt_id_attr *conf_list; -+ unsigned int i; -+ int len = 0; -+ -+ conf_list = (const struct dt_id_attr *)fdt_getprop(fdt, node, -+ "st,decprot", &len); -+ if (conf_list == NULL) { -+ IMSG("No ETZPC configuration in DT, use default"); -+ return 0; -+ } -+ -+ for (i = 0; i < 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); -+ if (!valid_decprot_id(id)) { -+ EMSG("Invalid DECPROT %" PRIu32, id); -+ return -1; -+ } -+ -+ mode = (value >> ETZPC_MODE_SHIFT) & ETZPC_MODE_MASK; -+ attr = stm32mp_etzpc_binding2decprot(mode); -+ -+ stm32mp_register_etzpc_decprot(id, attr); -+ -+ etzpc_configure_decprot(id, attr); -+ -+ if ((value & ETZPC_LOCK_MASK) != 0U) { -+ etzpc_lock_decprot(id); -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+void etzpc_configure_decprot(uint32_t decprot_id, -+ enum etzpc_decprot_attributes decprot_attr) -+{ -+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); -+ uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; -+ uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK; -+ uintptr_t base = etzpc_base(); -+ -+ assert(valid_decprot_id(decprot_id)); -+ -+ mmio_clrsetbits_32(base + ETZPC_DECPROT0 + offset, -+ (uint32_t)ETZPC_DECPROT0_MASK << shift, -+ masked_decprot << shift); -+ -+ etzpc_dev.periph_cfg[decprot_id] = (uint8_t)decprot_attr; -+ -+ assert((decprot_attr & ~PERIPH_ATTR_MASK) == 0); -+ COMPILE_TIME_ASSERT(TZPC_DECPROT_MAX <= UINT8_MAX); -+} -+ -+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id) -+{ -+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); -+ uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; -+ uintptr_t base_decprot = etzpc_base() + offset; -+ uint32_t value; -+ -+ assert(valid_decprot_id(decprot_id)); -+ -+ value = (read32(base_decprot + ETZPC_DECPROT0) >> shift) & -+ ETZPC_DECPROT0_MASK; -+ -+ return (enum etzpc_decprot_attributes)value; -+} -+ -+void etzpc_lock_decprot(uint32_t decprot_id) -+{ -+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); -+ uint32_t shift = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); -+ uintptr_t base_decprot = etzpc_base() + offset; -+ -+ assert(valid_decprot_id(decprot_id)); -+ -+ write32(shift, base_decprot + ETZPC_DECPROT_LOCK0); -+ -+ etzpc_dev.periph_cfg[decprot_id] |= PERIPH_LOCK_BIT; -+} -+ -+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value) -+{ -+ assert(valid_tzma_id(tzma_id)); -+ -+ write32(tzma_value, etzpc_base() + ETZPC_TZMA0_SIZE + -+ (sizeof(uint32_t) * tzma_id)); -+} -+ -+uint16_t etzpc_get_tzma(uint32_t tzma_id) -+{ -+ assert(valid_tzma_id(tzma_id)); -+ -+ return read32(etzpc_base() + ETZPC_TZMA0_SIZE + -+ (sizeof(uint32_t) * tzma_id)); -+} -+ -+void etzpc_lock_tzma(uint32_t tzma_id) -+{ -+ assert(valid_tzma_id(tzma_id)); -+ -+ mmio_setbits_32(etzpc_base() + ETZPC_TZMA0_SIZE + -+ (sizeof(uint32_t) * tzma_id), ETZPC_TZMA0_SIZE_LOCK); -+} -+ -+bool etzpc_get_lock_tzma(uint32_t tzma_id) -+{ -+ uint32_t tzma_size; -+ -+ assert(valid_tzma_id(tzma_id)); -+ -+ tzma_size = read32(etzpc_base() + ETZPC_TZMA0_SIZE + -+ (sizeof(uint32_t) * tzma_id)); -+ -+ return (tzma_size & ETZPC_TZMA0_SIZE_LOCK) != 0; -+} -+ -+static void etzpc_suspend_resume(enum pm_op op, void __unused *handle) -+{ -+ unsigned int n; -+ -+ if (op == PM_OP_SUSPEND) { -+ return; -+ } -+ -+ /* OP-TEE owns the whole in SYSRAM */ -+ etzpc_configure_tzma(1, ETZPC_TZMA_ALL_SECURE); -+ etzpc_lock_tzma(1); -+ -+ for (n = 0; n < etzpc_dev.num_per_sec; n++) { -+ unsigned int attr = etzpc_dev.periph_cfg[n] & PERIPH_ATTR_MASK; -+ -+ etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr); -+ -+ if (etzpc_dev.periph_cfg[n] & PERIPH_LOCK_BIT) { -+ etzpc_lock_decprot(n); -+ } -+ } -+} -+KEEP_PAGER(etzpc_suspend_resume); -+ -+static TEE_Result etzpc_init(void) -+{ -+ void *fdt __maybe_unused; -+ int node __maybe_unused; -+ struct dt_node_info etzpc_info __maybe_unused; -+ uintptr_t base; -+ uint32_t hwcfg; -+ size_t n; -+ -+#ifdef CFG_DT -+ fdt = get_dt_blob(); -+ if (!fdt) { -+ panic(); -+ } -+ -+ node = fdt_get_node(fdt, &etzpc_info, -1, ETZPC_COMPAT); -+ if (node >= 0) { -+ etzpc_dev.pbase = etzpc_info.base; -+ assert(etzpc_dev.pbase == stm32mp_get_etzpc_base()); -+ -+ if (etzpc_info.status != DT_STATUS_OK_SEC) { -+ EMSG("ETZPC DT status"); -+ panic(); -+ } -+ } -+#endif -+ -+ if (!etzpc_dev.pbase) { -+ etzpc_dev.pbase = stm32mp_get_etzpc_base(); -+ } -+ -+ base = etzpc_base(); -+ -+ hwcfg = read32(base + ETZPC_HWCFGR); -+ etzpc_dev.num_tzma = (uint8_t)(hwcfg >> ETZPC_HWCFGR_NUM_TZMA_SHIFT); -+ etzpc_dev.num_per_sec = (uint8_t)(hwcfg >> -+ ETZPC_HWCFGR_NUM_PER_SEC_SHIFT); -+ etzpc_dev.num_ahb_sec = (uint8_t)(hwcfg >> -+ ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT); -+ etzpc_dev.chunck_size = (uint8_t)(hwcfg >> -+ ETZPC_HWCFGR_CHUNCKS1N4_SHIFT); -+ -+ etzpc_dev.revision = read8(base + ETZPC_VERR); -+ -+ etzpc_dev.periph_cfg = calloc(etzpc_dev.num_per_sec, -+ sizeof(*etzpc_dev.periph_cfg)); -+ if (etzpc_dev.periph_cfg == NULL) { -+ panic(); -+ } -+ for (n = 0; n < etzpc_dev.num_per_sec; n++) { -+ etzpc_configure_decprot(n, etzpc_get_decprot(n)); -+ } -+ -+ DMSG("ETZPC version 0x%" PRIx8, etzpc_dev.revision); -+ -+#ifdef CFG_DT -+ if (etzpc_dt_conf_decprot(fdt, node)) { -+ panic(); -+ } -+#endif -+ -+ /* OP-TEE owns the whole in SYSRAM */ -+ etzpc_configure_tzma(1, ETZPC_TZMA_ALL_SECURE); -+ etzpc_lock_tzma(1); -+ -+ stm32mp_register_pm_cb(etzpc_suspend_resume, NULL); -+ -+ return TEE_SUCCESS; -+} -+driver_init(etzpc_init); -diff --git a/core/drivers/stm32_gpio.c b/core/drivers/stm32_gpio.c -new file mode 100644 -index 0000000..cb18271 ---- /dev/null -+++ b/core/drivers/stm32_gpio.c -@@ -0,0 +1,417 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CFG_DT -+#include -+#endif -+ -+#define DT_GPIO_BANK_SHIFT 12 -+#define DT_GPIO_BANK_MASK GENMASK_32(16, 12) -+#define DT_GPIO_PIN_SHIFT 8 -+#define DT_GPIO_PIN_MASK GENMASK_32(11, 8) -+#define DT_GPIO_MODE_MASK GENMASK_32(7, 0) -+ -+static void get_gpio_cfg(uint32_t bank, uint32_t pin, struct gpio_cfg *cfg) -+{ -+ uintptr_t base = stm32_get_gpio_bank_base(bank); -+ int clock = stm32_get_gpio_bank_clock(bank); -+ -+ stm32_clock_enable((unsigned long)clock); -+ -+ cfg->moder = (mmio_read_32(base + GPIO_MODE_OFFSET) >> (pin << 1)) & -+ GPIO_MODE_MAX; -+ -+ cfg->otyper = (mmio_read_32(base + GPIO_TYPE_OFFSET) >> pin) & 1; -+ cfg->ospeedr = (mmio_read_32(base + GPIO_SPEED_OFFSET) >> (pin << 1)) & -+ GPIO_SPEED_MAX; -+ cfg->pupdr = (mmio_read_32(base + GPIO_PUPD_OFFSET) >> (pin << 1)) & -+ GPIO_PULL_MAX; -+ -+ cfg->odr = (mmio_read_32(base + GPIO_ODR_OFFSET) >> (pin << 1)) & 1; -+ -+ if (pin < GPIO_ALT_LOWER_LIMIT) { -+ cfg->afr = (mmio_read_32(base + GPIO_AFRL_OFFSET) >> -+ (pin << 2)) & GPIO_ALTERNATE_MAX; -+ } else { -+ cfg->afr = (mmio_read_32(base + GPIO_AFRH_OFFSET) >> -+ ((pin - GPIO_ALT_LOWER_LIMIT) << 2)) & -+ GPIO_ALTERNATE_MAX; -+ } -+ -+ stm32_clock_disable((unsigned long)clock); -+} -+ -+static void set_gpio_cfg(uint32_t bank, uint32_t pin, struct gpio_cfg *cfg) -+{ -+ uintptr_t base = stm32_get_gpio_bank_base(bank); -+ int clock = stm32_get_gpio_bank_clock(bank); -+ -+ stm32_clock_enable((unsigned long)clock); -+ -+ mmio_clrsetbits_32(base + GPIO_MODE_OFFSET, -+ GPIO_MODE_MAX << (pin << 1), -+ cfg->moder << (pin << 1)); -+ -+ mmio_clrsetbits_32(base + GPIO_TYPE_OFFSET, -+ BIT(pin), -+ cfg->otyper << pin); -+ -+ mmio_clrsetbits_32(base + GPIO_SPEED_OFFSET, -+ GPIO_SPEED_MAX << (pin << 1), -+ cfg->ospeedr << (pin << 1)); -+ -+ mmio_clrsetbits_32(base + GPIO_PUPD_OFFSET, -+ BIT(pin), -+ cfg->pupdr << (pin << 1)); -+ -+ if (pin < GPIO_ALT_LOWER_LIMIT) { -+ mmio_clrsetbits_32(base + GPIO_AFRL_OFFSET, -+ GPIO_ALTERNATE_MAX << (pin << 2), -+ cfg->afr << (pin << 2)); -+ } else { -+ size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; -+ -+ mmio_clrsetbits_32(base + GPIO_AFRH_OFFSET, -+ GPIO_ALTERNATE_MAX << shift, -+ cfg->afr << shift); -+ } -+ -+ mmio_clrsetbits_32(base + GPIO_ODR_OFFSET, -+ BIT(pin), cfg->odr << pin); -+ -+ stm32_clock_disable((unsigned long)clock); -+} -+ -+/* -+ * stm32_gpio_set_output_level - Set level of an output GPIO instance -+ * -+ * @bank: GPIO bank -+ * @pin: GPIO pin position in bank -+ * @level: target level, either 0 (level low) or non zero (level high) -+ */ -+void stm32_gpio_set_output_level(uint32_t bank, uint32_t pin, int level) -+{ -+ uintptr_t base = stm32_get_gpio_bank_base(bank); -+ int clock = stm32_get_gpio_bank_clock(bank); -+ -+ assert(pin <= GPIO_PIN_MAX); -+ -+ stm32_clock_enable((unsigned long)clock); -+ -+ if (level) { -+ write32(BIT(pin), base + GPIO_BSRR_OFFSET); -+ } else { -+ write32(BIT(pin + 16), base + GPIO_BSRR_OFFSET); -+ } -+ -+ stm32_clock_disable((unsigned long)clock); -+} -+ -+/* -+ * stm32_pinctrl_load_active_cfg - Load the PINCTRLs active configuration -+ * -+ * @pinctrl: array of PINCTRL configurations to apply -+ * @cnt: number of elements in array pinctrl -+ */ -+void stm32_pinctrl_load_active_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) -+{ -+ size_t n; -+ -+ for (n = 0; n < cnt; n++) { -+ set_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, -+ &pinctrl[n].active_cfg); -+ } -+} -+ -+/* -+ * stm32_pinctrl_load_standby_cfg - Load the PINCTRLs standby configuration -+ * -+ * @pinctrl: array of PINCTRL configurations to apply -+ * @cnt: number of elements in array pinctrl -+ */ -+void stm32_pinctrl_load_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) -+{ -+ size_t n; -+ -+ for (n = 0; n < cnt; n++) { -+ set_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, -+ &pinctrl[n].standby_cfg); -+ } -+} -+ -+/* -+ * stm32_pinctrl_store_standby_cfg - Save current PINCTRLs config as standby -+ * -+ * @pinctrl: array of PINCTRL configurations to store -+ * @cnt: number of elements in array pinctrl -+ */ -+void stm32_pinctrl_store_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) -+{ -+ size_t n; -+ -+ for (n = 0; n < cnt; n++) { -+ get_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, -+ &pinctrl[n].standby_cfg); -+ } -+} -+ -+#ifdef CFG_DT -+/* Return GPIO bank node if status is okay in DT, else return 0 */ -+static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) -+{ -+ int pinctrl_subnode; -+ -+ fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { -+ uint32_t bank_offset; -+ const fdt32_t *cuint; -+ -+ if (fdt_getprop(fdt, pinctrl_subnode, -+ "gpio-controller", NULL) == NULL) { -+ continue; -+ } -+ -+ cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); -+ if (cuint == NULL) { -+ continue; -+ } -+ -+ bank_offset = stm32_get_gpio_bank_offset(bank); -+ -+ if ((fdt32_to_cpu(*cuint) == bank_offset) && -+ (_fdt_get_status(fdt,pinctrl_subnode) != -+ DT_STATUS_DISABLED)) { -+ return pinctrl_subnode; -+ } -+ } -+ -+ return 0; -+} -+ -+static int get_pinctrl_from_fdt(void *fdt, int node, -+ struct stm32_pinctrl *pinctrl, size_t count) -+{ -+ const fdt32_t *cuint, *slewrate; -+ int len; -+ int pinctrl_node; -+ int bank_node; -+ int clk; -+ uint32_t i; -+ uint32_t speed = GPIO_SPEED_LOW; -+ uint32_t pull = GPIO_NO_PULL; -+ size_t found = 0; -+ -+ cuint = fdt_getprop(fdt, node, "pinmux", &len); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); -+ if (pinctrl_node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); -+ if (slewrate != NULL) { -+ speed = fdt32_to_cpu(*slewrate); -+ } -+ -+ if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { -+ pull = GPIO_PULL_UP; -+ } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { -+ pull = GPIO_PULL_DOWN; -+ } else { -+ DMSG("No bias configured in node %d\n", node); -+ } -+ -+ for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { -+ uint32_t pincfg; -+ uint32_t bank; -+ uint32_t pin; -+ uint32_t mode; -+ uint32_t alternate = GPIO_ALTERNATE_0; -+ -+ pincfg = fdt32_to_cpu(*cuint); -+ cuint++; -+ -+ bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; -+ -+ pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; -+ -+ mode = pincfg & DT_GPIO_MODE_MASK; -+ -+ switch (mode) { -+ case 0: -+ mode = GPIO_MODE_INPUT; -+ break; -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ case 5: -+ case 6: -+ case 7: -+ case 8: -+ case 9: -+ case 10: -+ case 11: -+ case 12: -+ case 13: -+ case 14: -+ case 15: -+ case 16: -+ alternate = mode - 1U; -+ mode = GPIO_MODE_ALTERNATE; -+ break; -+ case 17: -+ mode = GPIO_MODE_ANALOG; -+ break; -+ default: -+ mode = GPIO_MODE_OUTPUT; -+ break; -+ } -+ -+ if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { -+ mode |= GPIO_OPEN_DRAIN; -+ } -+ -+ bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); -+ if (bank_node == 0) { -+ panic("PINCTRL inconsistent in DT"); -+ } -+ -+ clk = fdt_get_clock_id(fdt, bank_node); -+ if (clk < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ /* Platform knows the clock: assert it is okay */ -+ assert(clk == stm32_get_gpio_bank_clock(bank)); -+ stm32_clock_enable((unsigned int)clk); -+ stm32_clock_disable((unsigned int)clk); -+ -+ if (found < count) { -+ struct stm32_pinctrl *cfg = &pinctrl[found]; -+ -+ cfg->bank = (uint8_t)bank; -+ cfg->pin = (uint8_t)pin; -+ cfg->active_cfg.moder = mode & ~GPIO_OPEN_DRAIN; -+ cfg->active_cfg.otyper = mode & GPIO_OPEN_DRAIN ? 1 : 0; -+ cfg->active_cfg.ospeedr = speed; -+ cfg->active_cfg.pupdr = pull; -+ cfg->active_cfg.odr = 0; -+ cfg->active_cfg.afr = alternate; -+ cfg->standby_cfg.moder = GPIO_MODE_ANALOG; -+ cfg->standby_cfg.pupdr = GPIO_NO_PULL; -+ } -+ -+ found++; -+ } -+ -+ return (int)found; -+} -+ -+/* -+ * stm32_pinctrl_fdt_get_pinctrl - get PINCTRL config from a DT device node -+ * -+ * Argument cfg can be set to NULL or count to 0: the function will return only -+ * the number of PINCTRL instances found in the device tree for the target -+ * device. -+ * -+ * If more instances than count are found then the function returns the -+ * effective number of PINCTRL found but will fill array cfg only according -+ * to the value of count. -+ * -+ * @fdt: device tree -+ * @node: device node in the device tree -+ * @cfg: NULL or pointer to array of struct stm32_pinctrl -+ * @count: number of elements pointed by argument cfg -+ * -+ * Return the number of PINCTRL instances found and a negative value on error -+ */ -+int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int device_node, -+ struct stm32_pinctrl *cfg, size_t count) -+{ -+ const fdt32_t *cuint; -+ int lenp; -+ uint32_t i; -+ size_t found = 0; -+ -+ cuint = fdt_getprop(fdt, device_node, "pinctrl-0", &lenp); -+ if (cuint == NULL) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ for (i = 0; i < ((uint32_t)lenp / 4U); i++) { -+ int node; -+ int subnode; -+ -+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ size_t n; -+ int rc; -+ -+ if (count > found) { -+ n = count - found; -+ } else { -+ n = 0; -+ } -+ -+ rc = get_pinctrl_from_fdt(fdt, subnode, &cfg[found], n); -+ if (rc < 0) { -+ return rc; -+ } -+ -+ found += (size_t)rc; -+ } -+ -+ cuint++; -+ } -+ -+ return (int)found; -+} -+#endif /*CFG_DT*/ -+ -+/* -+ * stm32_gpio_set_secure_cfg - Set secure field of an output GPIO instance -+ * -+ * @bank: GPIO bank -+ * @pin: GPIO pin position in bank -+ * @secure: Secure field, either false (non secure) or true (secure) -+ */ -+void stm32_gpio_set_secure_cfg(uint32_t bank, uint32_t pin, bool secure) -+{ -+ uintptr_t base = stm32_get_gpio_bank_base(bank); -+ int clock = stm32_get_gpio_bank_clock(bank); -+ -+ assert(pin <= GPIO_PIN_MAX); -+ -+ assert(!(secure && stm32mp_gpio_bank_is_non_secure(bank))); -+ -+ stm32_clock_enable((unsigned long)clock); -+ -+ if (secure) { -+ mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); -+ } else { -+ mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); -+ } -+ -+ stm32_clock_disable((unsigned long)clock); -+} -diff --git a/core/drivers/stm32_i2c.c b/core/drivers/stm32_i2c.c -new file mode 100644 -index 0000000..f7f0f70 ---- /dev/null -+++ b/core/drivers/stm32_i2c.c -@@ -0,0 +1,1629 @@ -+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* STM32 I2C registers offsets */ -+#define I2C_CR1 0x00U -+#define I2C_CR2 0x04U -+#define I2C_OAR1 0x08U -+#define I2C_OAR2 0x0CU -+#define I2C_TIMINGR 0x10U -+#define I2C_TIMEOUTR 0x14U -+#define I2C_ISR 0x18U -+#define I2C_ICR 0x1CU -+#define I2C_PECR 0x20U -+#define I2C_RXDR 0x24U -+#define I2C_TXDR 0x28U -+ -+#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU -+ -+#define MAX_NBYTE_SIZE 255U -+ -+#define I2C_NSEC_PER_SEC 1000000000L -+ -+/* -+ * struct i2c_spec_s - Private I2C timing specifications. -+ * @rate: I2C bus speed (Hz) -+ * @rate_min: 80% of I2C bus speed (Hz) -+ * @rate_max: 120% of I2C bus speed (Hz) -+ * @fall_max: Max fall time of both SDA and SCL signals (ns) -+ * @rise_max: Max rise time of both SDA and SCL signals (ns) -+ * @hddat_min: Min data hold time (ns) -+ * @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 rate_min; -+ uint32_t rate_max; -+ 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; -+}; -+ -+/** -+ * All these values are coming from I2C Specification, Version 6.0, 4th of -+ * April 2014. -+ * -+ * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast, -+ * and Fast-mode Plus I2C-bus devices. -+ */ -+static const struct i2c_spec_s i2c_specs[] = { -+ [I2C_SPEED_STANDARD] = { -+ .rate = STANDARD_RATE, -+ .rate_min = 8000, -+ .rate_max = 120000, -+ .fall_max = 300, -+ .rise_max = 1000, -+ .hddat_min = 0, -+ .vddat_max = 3450, -+ .sudat_min = 250, -+ .l_min = 4700, -+ .h_min = 4000, -+ }, -+ [I2C_SPEED_FAST] = { -+ .rate = FAST_RATE, -+ .rate_min = 320000, -+ .rate_max = 480000, -+ .fall_max = 300, -+ .rise_max = 300, -+ .hddat_min = 0, -+ .vddat_max = 900, -+ .sudat_min = 100, -+ .l_min = 1300, -+ .h_min = 600, -+ }, -+ [I2C_SPEED_FAST_PLUS] = { -+ .rate = FAST_PLUS_RATE, -+ .rate_min = 800000, -+ .rate_max = 1200000, -+ .fall_max = 100, -+ .rise_max = 120, -+ .hddat_min = 0, -+ .vddat_max = 450, -+ .sudat_min = 50, -+ .l_min = 500, -+ .h_min = 260, -+ }, -+}; -+ -+static int i2c_request_memory_write(struct i2c_handle_s *hi2c, -+ uint16_t dev_addr, uint16_t mem_addr, -+ uint16_t mem_add_size, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint64_t tick_to, uint64_t tick_start); -+ -+/* Private functions to handle flags during polling transfer */ -+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, -+ uint8_t awaited_value, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_wait_txis(struct i2c_handle_s *hi2c, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_wait_stop(struct i2c_handle_s *hi2c, -+ uint64_t tick_to, uint64_t tick_start); -+static int i2c_ack_failed(struct i2c_handle_s *hi2c, -+ uint64_t tick_to, uint64_t tick_start); -+ -+/* Private function to flush TXDR register */ -+static void i2c_flush_txdr(struct i2c_handle_s *hi2c); -+ -+/* Private function to start, restart or stop a transfer */ -+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t size, uint32_t i2c_mode, -+ uint32_t request); -+ -+static uintptr_t get_base(struct i2c_handle_s *hi2c) -+{ -+ if (!cpu_mmu_enabled()) -+ return hi2c->pbase; -+ -+ return hi2c->vbase; -+} -+ -+static bool i2c_is_secure(struct i2c_handle_s *hi2c) -+{ -+ return hi2c->dt_status == DT_STATUS_OK_SEC; -+} -+ -+static uint64_t ms2tick(uint32_t timeout_ms) -+{ -+ return ((uint64_t)timeout_ms * read_cntfrq()) / 1000; -+} -+ -+static uint64_t timeout_start(void) -+{ -+ return read_cntpct(); -+} -+ -+static bool timeout_elapsed(uint64_t tick_start, uint64_t tick_to) -+{ -+ return (tick_to != 0U) && ((read_cntpct() - tick_start) > tick_to); -+} -+ -+static void notif_i2c_timeout(struct i2c_handle_s *hi2c) -+{ -+ hi2c->i2c_err |= I2C_ERROR_TIMEOUT; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ hi2c->i2c_state = I2C_STATE_READY; -+} -+ -+static void save_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ cfg->cr1 = mmio_read_32(base + I2C_CR1); -+ cfg->cr2 = mmio_read_32(base + I2C_CR2); -+ cfg->oar1 = mmio_read_32(base + I2C_OAR1); -+ cfg->oar2 = mmio_read_32(base + I2C_OAR2); -+ cfg->timingr = mmio_read_32(base + I2C_TIMINGR); -+ -+ stm32_clock_disable(hi2c->clock); -+} -+ -+static void restore_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ if (hi2c->lock) { -+ panic(); -+ } -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ mmio_clrbits_32(base + I2C_CR1, I2C_CR1_PE); -+ mmio_write_32(base + I2C_TIMINGR, cfg->timingr & TIMINGR_CLEAR_MASK); -+ mmio_write_32(base + I2C_OAR1, cfg->oar1); -+ mmio_write_32(base + I2C_CR2, cfg->cr2); -+ mmio_write_32(base + I2C_OAR2, cfg->oar2); -+ mmio_write_32(base + I2C_CR1, cfg->cr1 & ~I2C_CR1_PE); -+ mmio_setbits_32(base + I2C_CR1, cfg->cr1 & I2C_CR1_PE); -+ -+ stm32_clock_disable(hi2c->clock); -+} -+ -+static void __maybe_unused dump_cfg(struct i2c_cfg *cfg __maybe_unused) -+{ -+ DMSG("CR1: %x", (unsigned)cfg->cr1); -+ DMSG("CR2: %x", (unsigned)cfg->cr2); -+ DMSG("OAR1: %x", (unsigned)cfg->oar1); -+ DMSG("OAR2: %x", (unsigned)cfg->oar2); -+ DMSG("TIM: %x", (unsigned)cfg->timingr); -+} -+ -+static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c) -+{ -+ uintptr_t __maybe_unused base = get_base(hi2c); -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ DMSG("CR1: %x", (unsigned)mmio_read_32(base + I2C_CR1)); -+ DMSG("CR2: %x", (unsigned)mmio_read_32(base + I2C_CR2)); -+ DMSG("OAR1: %x", (unsigned)mmio_read_32(base + I2C_OAR1)); -+ DMSG("OAR2: %x", (unsigned)mmio_read_32(base + I2C_OAR2)); -+ DMSG("TIM: %x", (unsigned)mmio_read_32(base + I2C_TIMINGR)); -+ -+ stm32_clock_disable(hi2c->clock); -+} -+ -+/* -+ * @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) -+{ -+ enum i2c_speed_e mode = init->speed_mode; -+ 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; -+ unsigned int sdadel_min; -+ unsigned int sdadel_max; -+ unsigned int scldel_min; -+ unsigned int delay; -+ int s = -1; -+ struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX]; -+ -+ switch (mode) { -+ case I2C_SPEED_STANDARD: -+ case I2C_SPEED_FAST: -+ case I2C_SPEED_FAST_PLUS: -+ break; -+ default: -+ EMSG("I2C speed out of bound {%d/%d}\n", -+ mode, I2C_SPEED_FAST_PLUS); -+ return -1; -+ } -+ -+ speed_freq = i2c_specs[mode].rate; -+ i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq); -+ clk_error_prev = INT_MAX; -+ -+ if ((init->rise_time > i2c_specs[mode].rise_max) || -+ (init->fall_time > i2c_specs[mode].fall_max)) { -+ EMSG(" I2C timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", -+ init->rise_time, i2c_specs[mode].rise_max, -+ init->fall_time, i2c_specs[mode].fall_max); -+ return -1; -+ } -+ -+ if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) { -+ EMSG("DNF out of bound %d/%d\n", -+ init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX); -+ return -1; -+ } -+ -+ /* 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 = i2c_specs[mode].hddat_min + init->fall_time; -+ delay = af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); -+ if (SUB_OVERFLOW(sdadel_min, delay ,&sdadel_min)) -+ sdadel_min = 0; -+ -+ sdadel_max = i2c_specs[mode].vddat_max - init->rise_time; -+ delay = af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); -+ if (SUB_OVERFLOW(sdadel_max, delay ,&sdadel_max)) -+ sdadel_max = 0; -+ -+ scldel_min = init->rise_time + i2c_specs[mode].sudat_min; -+ -+ DMSG("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u\n", -+ sdadel_min, sdadel_max, scldel_min); -+ -+ memset(&solutions, 0, 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) && -+ (sdadel <= sdadel_max) && -+ (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) { -+ EMSG(" I2C no Prescaler solution\n"); -+ return -1; -+ } -+ -+ tsync = af_delay_min + dnf_delay + (2 * i2cclk); -+ clk_max = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_min; -+ clk_min = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_max; -+ -+ /* -+ * 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 < i2c_specs[mode].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 >= i2c_specs[mode].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) { -+ EMSG(" I2C no solution at all\n"); -+ return -1; -+ } -+ -+ /* 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); -+ -+ DMSG("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%i/%i\n", -+ s, solutions[s].scldel, solutions[s].sdadel); -+ DMSG("I2C TIMINGR (SCLH/SCLL): %i/%i\n", -+ solutions[s].sclh, solutions[s].scll); -+ DMSG("I2C TIMINGR: 0x%x\n", *timing); -+ -+ return 0; -+} -+ -+/* -+ * @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 = stm32_clock_get_rate(hi2c->clock); -+ if (clock_src == 0U) { -+ EMSG("I2C clock rate is 0\n"); -+ return -1; -+ } -+ -+ do { -+ rc = i2c_compute_timing(init, clock_src, timing); -+ if (rc != 0) { -+ EMSG("Failed to compute I2C timings\n"); -+ if (init->speed_mode > I2C_SPEED_STANDARD) { -+ init->speed_mode--; -+ IMSG("Downgrade I2C speed to %uHz)\n", -+ i2c_specs[init->speed_mode].rate); -+ } else { -+ break; -+ } -+ } -+ } while (rc != 0); -+ -+ if (rc != 0) { -+ EMSG("Impossible to compute I2C timings\n"); -+ return rc; -+ } -+ -+ DMSG("I2C Speed Mode(%i), Freq(%i), Clk Source(%i)\n", -+ init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src); -+ DMSG("I2C Rise(%i) and Fall(%i) Time\n", -+ init->rise_time, init->fall_time); -+ DMSG("I2C Analog Filter(%s), DNF(%i)\n", -+ (init->analog_filter ? "On" : "Off"), init->digital_filter_coef); -+ -+ return 0; -+} -+ -+/* -+ * @brief Configure I2C Analog noise filter. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C peripheral. -+ * @param analog_filter: New state of the Analog filter -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, -+ uint32_t analog_filter) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return -1; -+ } -+ -+ hi2c->lock = 1; -+ -+ hi2c->i2c_state = I2C_STATE_BUSY; -+ -+ /* Disable the selected I2C peripheral */ -+ mmio_clrbits_32(base + I2C_CR1, I2C_CR1_PE); -+ -+ /* Reset I2Cx ANOFF bit */ -+ mmio_clrbits_32(base + I2C_CR1, I2C_CR1_ANFOFF); -+ -+ /* Set analog filter bit*/ -+ mmio_setbits_32(base + I2C_CR1, analog_filter); -+ -+ /* Enable the selected I2C peripheral */ -+ mmio_setbits_32(base + I2C_CR1, I2C_CR1_PE); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ -+ hi2c->lock = 0; -+ -+ return 0; -+} -+ -+/* -+ * @brief Get I2C setup information from the device tree and set pinctrl -+ * configuration. -+ * @param fdt: Pointer to the device tree -+ * @param node: I2C node offset -+ * @param init: Ref to the initialization configuration structure -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_get_setup_from_fdt(void *fdt, int node, -+ struct stm32_i2c_init_s *init, -+ struct stm32_pinctrl **pinctrl, -+ size_t *pinctrl_count) -+{ -+ const fdt32_t *cuint; -+ int count; -+ -+ 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; -+ } -+ } -+ -+ count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); -+ if (count <= 0) { -+ *pinctrl = NULL; -+ *pinctrl_count = 0; -+ return count; -+ } -+ -+ if (count > 2) { -+ panic("Too many PINCTRLs found"); -+ } -+ -+ *pinctrl = calloc(count, sizeof(**pinctrl)); -+ if (!*pinctrl) { -+ panic(); -+ } -+ -+ *pinctrl_count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, -+ *pinctrl, count); -+ assert(*pinctrl_count == (unsigned int)count); -+ -+ return 0; -+} -+ -+/* -+ * @brief Initialize the I2C device. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param init_data: Ref to the initialization configuration structure -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_init(struct i2c_handle_s *hi2c, -+ struct stm32_i2c_init_s *init_data) -+{ -+ int rc = 0; -+ uint32_t timing; -+ uintptr_t base = get_base(hi2c); -+ -+ if (hi2c == NULL) { -+ return -1; -+ } -+ -+ if (hi2c->i2c_state == I2C_STATE_RESET) { -+ hi2c->lock = 0; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY; -+ -+ rc = i2c_setup_timing(hi2c, init_data, &timing); -+ if (rc != 0) { -+ return rc; -+ } -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ /* Disable the selected I2C peripheral */ -+ mmio_clrbits_32(base + I2C_CR1, I2C_CR1_PE); -+ -+ /* Configure I2Cx: Frequency range */ -+ mmio_write_32(base + I2C_TIMINGR, timing & TIMINGR_CLEAR_MASK); -+ -+ /* Disable Own Address1 before set the Own Address1 configuration */ -+ mmio_clrbits_32(base + I2C_OAR1, I2C_OAR1_OA1EN); -+ -+ /* Configure I2Cx: Own Address1 and ack own address1 mode */ -+ if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { -+ mmio_write_32(base + I2C_OAR1, -+ I2C_OAR1_OA1EN | init_data->own_address1); -+ } else { /* I2C_ADDRESSINGMODE_10BIT */ -+ mmio_write_32(base + I2C_OAR1, -+ I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | -+ init_data->own_address1); -+ } -+ -+ mmio_write_32(base + I2C_CR2, 0); -+ -+ /* Configure I2Cx: Addressing Master mode */ -+ if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { -+ mmio_setbits_32(base + I2C_CR2, I2C_CR2_ADD10); -+ } -+ -+ /* -+ * Enable the AUTOEND by default, and enable NACK -+ * (should be disabled only during Slave process). -+ */ -+ mmio_setbits_32(base + I2C_CR2, I2C_CR2_AUTOEND | I2C_CR2_NACK); -+ -+ /* Disable Own Address2 before set the Own Address2 configuration */ -+ mmio_clrbits_32(base + I2C_OAR2, I2C_DUALADDRESS_ENABLE); -+ -+ /* Configure I2Cx: Dual mode and Own Address2 */ -+ mmio_write_32(base + I2C_OAR2, -+ init_data->dual_address_mode | -+ init_data->own_address2 | -+ (init_data->own_address2_masks << 8)); -+ -+ /* Configure I2Cx: Generalcall and NoStretch mode */ -+ mmio_write_32(base + I2C_CR1, -+ init_data->general_call_mode | -+ init_data->no_stretch_mode); -+ -+ /* Enable the selected I2C peripheral */ -+ mmio_setbits_32(base + I2C_CR1, I2C_CR1_PE); -+ -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? -+ I2C_ANALOGFILTER_ENABLE : -+ I2C_ANALOGFILTER_DISABLE); -+ if (rc != 0) { -+ EMSG("Cannot initialize I2C analog filter (%d)\n", rc); -+ stm32_clock_disable(hi2c->clock); -+ return rc; -+ } -+ -+ stm32_clock_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Generic function to write an amount of data in blocking mode -+ * (for Memory Mode and Master Mode) -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address (if Memory Mode) -+ * @param mem_add_size: Size of internal memory address (if Memory Mode) -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @param mode: Communication mode -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms, -+ enum i2c_mode_e mode) -+{ -+ uint64_t tick_start; -+ uintptr_t base = get_base(hi2c); -+ int rc = -1; -+ uint64_t tick_to = ms2tick(timeout_ms); -+ uint8_t *p_buff = p_data; -+ size_t xfer_size; -+ size_t xfer_count = size; -+ -+ if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { -+ return -1; -+ } -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return -1; -+ } -+ -+ if ((p_data == NULL) || (size == 0U)) { -+ return -1; -+ } -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ -+ tick_start = timeout_start(); -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, ms2tick(I2C_TIMEOUT_BUSY_MS), -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY_TX; -+ hi2c->i2c_mode = mode; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ if (mode == I2C_MODE_MEM) { -+ /* In Memory Mode, Send Slave Address and Memory Address */ -+ if (i2c_request_memory_write(hi2c, dev_addr, -+ mem_addr, mem_add_size, -+ tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); -+ } -+ } else { -+ /* In Master Mode, Send Slave Address */ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_RELOAD_MODE, -+ I2C_GENERATE_START_WRITE); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_AUTOEND_MODE, -+ I2C_GENERATE_START_WRITE); -+ } -+ } -+ -+ do { -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_8(base + I2C_TXDR, *p_buff); -+ p_buff++; -+ xfer_count--; -+ xfer_size--; -+ -+ if ((xfer_count != 0U) && (xfer_size == 0U)) { -+ /* Wait until TCR flag is set */ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_RELOAD_MODE, -+ I2C_NO_STARTSTOP); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_AUTOEND_MODE, -+ I2C_NO_STARTSTOP); -+ } -+ } -+ -+ } while (xfer_count > 0U); -+ -+ /* -+ * No need to Check TC flag, with AUTOEND mode the stop -+ * is automatically generated. -+ * Wait until STOPF flag is reset. -+ */ -+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ -+ mmio_clrbits_32(base + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = 0; -+ -+bail: -+ hi2c->lock = 0; -+ stm32_clock_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Write an amount of data in blocking mode to a specific memory -+ * address. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms) -+{ -+ return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, -+ p_data, size, timeout_ms, I2C_MODE_MEM); -+} -+ -+/* -+ * @brief Transmits in master mode an amount of data in blocking mode. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms) -+{ -+ return i2c_write(hi2c, dev_addr, 0, 0, -+ p_data, size, timeout_ms, I2C_MODE_MASTER); -+} -+ -+/* -+ * Optimized 1 byte read/write function for unpaged sequences. -+ * 8-bit addressing mode / single byte transferred / use default I2C timeout. -+ * 'unpg88' refers to 8bit address/8bit value. -+ */ -+int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ unsigned int mem_addr, uint8_t *p_data, -+ bool write) -+{ -+ uint64_t tick_start; -+ uintptr_t base = get_base(hi2c); -+ int rc = 1; -+ uint64_t tick_to = ms2tick(I2C_TIMEOUT_BUSY_MS); -+ uint8_t *p_buff = p_data; -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || -+ (hi2c->lock != 0U) || -+ (p_data == NULL)) { -+ return 1; -+ } -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ -+ tick_start = timeout_start(); -+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = write ? I2C_STATE_BUSY_TX : I2C_STATE_BUSY_RX; -+ hi2c->i2c_mode = I2C_MODE_MEM; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT, -+ write ? I2C_RELOAD_MODE : I2C_SOFTEND_MODE, -+ I2C_GENERATE_START_WRITE); -+ -+ tick_start = timeout_start(); -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_8(base + I2C_TXDR, (uint8_t)(mem_addr & 0x0FFU)); -+ -+ tick_start = timeout_start(); -+ if (i2c_wait_flag(hi2c, write ? I2C_FLAG_TCR : I2C_FLAG_TC, 0, -+ tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT, -+ I2C_AUTOEND_MODE, -+ write ? I2C_NO_STARTSTOP : I2C_GENERATE_START_READ); -+ -+ tick_start = timeout_start(); -+ if (write) { -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ mmio_write_8(base + I2C_TXDR, *p_buff); -+ -+ } else { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, -+ tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ *p_buff = mmio_read_8(base + I2C_RXDR); -+ } -+ -+ tick_start = timeout_start(); -+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ mmio_clrbits_32(base + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = 0; -+ -+bail: -+ hi2c->lock = 0; -+ stm32_clock_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Generic function to read an amount of data in blocking mode -+ * (for Memory Mode and Master Mode) -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address (if Memory Mode) -+ * @param mem_add_size: Size of internal memory address (if Memory Mode) -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @param mode: Communication mode -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms, -+ enum i2c_mode_e mode) -+{ -+ uintptr_t base = get_base(hi2c); -+ uint64_t tick_start; -+ int rc = -1; -+ uint64_t tick_to = ms2tick(timeout_ms); -+ uint8_t *p_buff = p_data; -+ size_t xfer_count = size; -+ size_t xfer_size; -+ -+ if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { -+ return -1; -+ } -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return -1; -+ } -+ -+ if ((p_data == NULL) || (size == 0U)) { -+ return -1; -+ } -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ -+ tick_start = timeout_start(); -+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, ms2tick(I2C_TIMEOUT_BUSY_MS), -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY_RX; -+ hi2c->i2c_mode = mode; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ if (mode == I2C_MODE_MEM) { -+ /* Send Memory Address */ -+ if (i2c_request_memory_read(hi2c, dev_addr, -+ mem_addr, mem_add_size, -+ tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ } -+ -+ /* -+ * Send Slave Address. -+ * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE -+ * and generate RESTART. -+ */ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_RELOAD_MODE, I2C_GENERATE_START_READ); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, xfer_size, -+ I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); -+ } -+ -+ do { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ *p_buff = mmio_read_8(base + I2C_RXDR); -+ p_buff++; -+ xfer_size--; -+ xfer_count--; -+ -+ if ((xfer_count != 0U) && (xfer_size == 0U)) { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ if (xfer_count > MAX_NBYTE_SIZE) { -+ xfer_size = MAX_NBYTE_SIZE; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_RELOAD_MODE, -+ I2C_NO_STARTSTOP); -+ } else { -+ xfer_size = xfer_count; -+ i2c_transfer_config(hi2c, dev_addr, -+ xfer_size, -+ I2C_AUTOEND_MODE, -+ I2C_NO_STARTSTOP); -+ } -+ } -+ } while (xfer_count > 0U); -+ -+ /* -+ * No need to Check TC flag, with AUTOEND mode the stop -+ * is automatically generated. -+ * Wait until STOPF flag is reset. -+ */ -+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ -+ mmio_clrbits_32(base + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ rc = 0; -+ -+bail: -+ hi2c->lock = 0; -+ stm32_clock_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Read an amount of data in blocking mode from a specific memory -+ * address. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms) -+{ -+ return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, -+ p_data, size, timeout_ms, I2C_MODE_MEM); -+} -+ -+/* -+ * @brief Receives in master mode an amount of data in blocking mode. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param p_data: Pointer to data buffer -+ * @param size: Amount of data to be sent -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval 0 if OK, negative value else -+ */ -+int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms) -+{ -+ return i2c_read(hi2c, dev_addr, 0, 0, -+ p_data, size, timeout_ms, I2C_MODE_MASTER); -+} -+ -+/* -+ * @brief Checks if target device is ready for communication. -+ * @note This function is used with Memory devices -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param trials: Number of trials -+ * @param timeout_ms: Timeout duration in milliseconds -+ * @retval True if device is ready, false else -+ */ -+bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, -+ uint16_t dev_addr, uint32_t trials, -+ uint32_t timeout_ms) -+{ -+ uintptr_t base = get_base(hi2c); -+ uint32_t i2c_trials = 0U; -+ bool rc = false; -+ uint64_t tick_to = ms2tick(timeout_ms); -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { -+ return rc; -+ } -+ -+ stm32_clock_enable(hi2c->clock); -+ -+ hi2c->lock = 1; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ if ((mmio_read_32(base + I2C_ISR) & I2C_FLAG_BUSY) != 0U) { -+ goto bail; -+ } -+ -+ hi2c->i2c_state = I2C_STATE_BUSY; -+ hi2c->i2c_err = I2C_ERROR_NONE; -+ -+ do { -+ uint64_t tick_start; -+ uint32_t isr; -+ -+ /* Generate Start */ -+ if ((mmio_read_32(base + I2C_OAR1) & I2C_OAR1_OA1MODE) == 0) { -+ mmio_write_32(base + I2C_CR2, -+ (((uint32_t)dev_addr & I2C_CR2_SADD) | -+ I2C_CR2_START | I2C_CR2_AUTOEND) & -+ ~I2C_CR2_RD_WRN); -+ } else { -+ mmio_write_32(base + I2C_CR2, -+ (((uint32_t)dev_addr & I2C_CR2_SADD) | -+ I2C_CR2_START | I2C_CR2_ADD10) & -+ ~I2C_CR2_RD_WRN); -+ } -+ -+ /* -+ * No need to Check TC flag, with AUTOEND mode the stop -+ * is automatically generated. -+ * Wait until STOPF flag is set or a NACK flag is set. -+ */ -+ tick_start = timeout_start(); -+ do { -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ goto bail; -+ } -+ -+ isr = mmio_read_32(base + I2C_ISR); -+ } while ((isr & (I2C_FLAG_STOPF | I2C_FLAG_AF)) == 0); -+ -+ if ((mmio_read_32(base + I2C_ISR) & I2C_FLAG_AF) == 0U) { -+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+ -+ rc = true; -+ goto bail; -+ } -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_AF); -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ -+ if (i2c_trials == trials) { -+ mmio_setbits_32(base + I2C_CR2, I2C_CR2_STOP); -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to, -+ tick_start) != 0) { -+ goto bail; -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ } -+ -+ i2c_trials++; -+ } while (i2c_trials < trials); -+ -+ notif_i2c_timeout(hi2c); -+ -+bail: -+#ifdef STM32_I2C_MAYBE_NON_SECURE -+ if (rc) { -+ /* Save the active secure configuraton */ -+ save_cfg(hi2c, &hi2c->sec_cfg); -+ } -+#endif -+ -+ hi2c->lock = 0; -+ stm32_clock_disable(hi2c->clock); -+ -+ return rc; -+} -+ -+/* -+ * @brief Master sends target device address followed by internal memory -+ * address for write request. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_request_memory_write(struct i2c_handle_s *hi2c, -+ uint16_t dev_addr, uint16_t mem_addr, -+ uint16_t mem_add_size, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, -+ I2C_GENERATE_START_WRITE); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { -+ /* Send Memory Address */ -+ mmio_write_8(base + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } else { -+ /* Send MSB of Memory Address */ -+ mmio_write_8(base + I2C_TXDR, -+ (uint8_t)((mem_addr & 0xFF00U) >> 8)); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ /* Send LSB of Memory Address */ -+ mmio_write_8(base + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief Master sends target device address followed by internal memory -+ * address for read request. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param dev_addr: Target device address -+ * @param mem_addr: Internal memory address -+ * @param mem_add_size: Size of internal memory address -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint64_t tick_to, uint64_t tick_start) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, -+ I2C_GENERATE_START_WRITE); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { -+ /* Send Memory Address */ -+ mmio_write_8(base + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } else { -+ /* Send MSB of Memory Address */ -+ mmio_write_8(base + I2C_TXDR, -+ (uint8_t)((mem_addr & 0xFF00U) >> 8)); -+ -+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ /* Send LSB of Memory Address */ -+ mmio_write_8(base + I2C_TXDR, -+ (uint8_t)(mem_addr & 0x00FFU)); -+ } -+ -+ if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief I2C Tx data register flush process. -+ * @param hi2c: I2C handle -+ * @retval None -+ */ -+static void i2c_flush_txdr(struct i2c_handle_s *hi2c) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ /* -+ * If a pending TXIS flag is set, -+ * write a dummy data in TXDR to clear it. -+ */ -+ if ((mmio_read_32(base + I2C_ISR) & I2C_FLAG_TXIS) != 0U) { -+ mmio_write_32(base + I2C_TXDR, 0); -+ } -+ -+ /* Flush TX register if not empty */ -+ if ((mmio_read_32(base + I2C_ISR) & I2C_FLAG_TXE) == 0U) { -+ mmio_setbits_32(base + I2C_ISR, I2C_FLAG_TXE); -+ } -+} -+ -+/* -+ * @brief This function handles I2C Communication timeout. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param flag: Specifies the I2C flag to check -+ * @param awaited_value: The awaited bit value for the flag (0 or 1) -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, -+ uint8_t awaited_value, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ for ( ; ; ) { -+ uint32_t isr = read32(get_base(hi2c) + I2C_ISR); -+ -+ if (!!(isr & flag) != !!awaited_value) { -+ return 0; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -1; -+ } -+ } -+} -+ -+/* -+ * @brief This function handles I2C Communication timeout for specific usage -+ * of TXIS flag. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ while ((read32(get_base(hi2c) + I2C_ISR) & I2C_FLAG_TXIS) == 0U) { -+ if (i2c_ack_failed(hi2c, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief This function handles I2C Communication timeout for specific -+ * usage of STOP flag. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ while ((read32(get_base(hi2c) + I2C_ISR) & I2C_FLAG_STOPF) == 0U) { -+ if (i2c_ack_failed(hi2c, tick_to, tick_start) != 0) { -+ return -1; -+ } -+ -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * @brief This function handles Acknowledge failed detection during -+ * an I2C Communication. -+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains -+ * the configuration information for the specified I2C. -+ * @param tick_to: Tick timeout duration -+ * @param tick_start: Tick start value -+ * @retval 0 if OK, negative value else -+ */ -+static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t tick_to, -+ uint64_t tick_start) -+{ -+ uintptr_t base = get_base(hi2c); -+ -+ if ((mmio_read_32(base + I2C_ISR) & I2C_FLAG_AF) == 0U) { -+ return 0; -+ } -+ -+ /* -+ * Wait until STOP Flag is reset. -+ * AutoEnd should be initiate after AF. -+ */ -+ while ((mmio_read_32(base + I2C_ISR) & I2C_FLAG_STOPF) == 0U) { -+ if (timeout_elapsed(tick_start, tick_to)) { -+ notif_i2c_timeout(hi2c); -+ hi2c->lock = 0; -+ -+ return -1; -+ } -+ } -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_AF); -+ -+ mmio_write_32(base + I2C_ICR, I2C_FLAG_STOPF); -+ -+ i2c_flush_txdr(hi2c); -+ -+ mmio_clrbits_32(base + I2C_CR2, I2C_RESET_CR2); -+ -+ hi2c->i2c_err |= I2C_ERROR_AF; -+ hi2c->i2c_state = I2C_STATE_READY; -+ hi2c->i2c_mode = I2C_MODE_NONE; -+ -+ hi2c->lock = 0; -+ -+ return -1; -+} -+ -+/* -+ * @brief Handles I2Cx communication when starting transfer or during transfer -+ * (TC or TCR flag are set). -+ * @param hi2c: I2C handle -+ * @param dev_addr: Specifies the slave address to be programmed -+ * @param size: Specifies the number of bytes to be programmed. -+ * This parameter must be a value between 0 and 255. -+ * @param i2c_mode: New state of the I2C START condition generation. -+ * This parameter can be one of the following values: -+ * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. -+ * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. -+ * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. -+ * @param request: New state of the I2C START condition generation. -+ * This parameter can be one of the following values: -+ * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. -+ * @arg @ref I2C_GENERATE_STOP: Generate stop condition -+ * (size should be set to 0). -+ * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. -+ * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. -+ * @retval None -+ */ -+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t size, uint32_t i2c_mode, -+ uint32_t request) -+{ -+ uint32_t clr_value, set_value; -+ -+ clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | -+ I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | -+ (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); -+ -+ set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | -+ (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | -+ i2c_mode | request; -+ -+ mmio_clrsetbits_32(get_base(hi2c) + I2C_CR2, clr_value, set_value); -+} -+ -+#ifdef STM32_I2C_MAYBE_NON_SECURE -+/* -+ * Secure side needs the PMIC. If it is secure, it can be freely used. -+ * If the PMIC is non secure, the configuration must be save/restored -+ * when used by the secure side. -+ */ -+#endif -+ -+void stm32_i2c_resume(struct i2c_handle_s *hi2c) -+{ -+ if (hi2c->i2c_state == I2C_STATE_READY) { -+ return; -+ } -+ -+ if ((hi2c->i2c_state != I2C_STATE_RESET) && -+ (hi2c->i2c_state != I2C_STATE_SUSPENDED)) { -+ panic(); -+ } -+ -+#ifdef STM32_I2C_MAYBE_NON_SECURE -+ if (!i2c_is_secure(hi2c)) { -+ stm32_pinctrl_store_standby_cfg(hi2c->pinctrl, -+ hi2c->pinctrl_count); -+ save_cfg(hi2c, &hi2c->alt_cfg); -+ } -+#endif -+ -+ stm32_pinctrl_load_active_cfg(hi2c->pinctrl, hi2c->pinctrl_count); -+ -+ if (hi2c->i2c_state == I2C_STATE_RESET) { -+ /* This is no valid I2C configuration loaded yet */ -+ return; -+ } -+ -+ restore_cfg(hi2c, &hi2c->sec_cfg); -+ -+ hi2c->i2c_state = I2C_STATE_READY; -+} -+ -+void stm32_i2c_suspend(struct i2c_handle_s *hi2c) -+{ -+ if ((hi2c->i2c_state == I2C_STATE_SUSPENDED)) { -+ return; -+ } -+ -+ if ((hi2c->i2c_state != I2C_STATE_READY)) { -+ panic(); -+ } -+ -+ save_cfg(hi2c, &hi2c->sec_cfg); -+ -+ stm32_pinctrl_load_standby_cfg(hi2c->pinctrl, -+ hi2c->pinctrl_count); -+ -+#ifdef STM32_I2C_MAYBE_NON_SECURE -+ if (!i2c_is_secure(hi2c)) { -+ restore_cfg(hi2c, &hi2c->alt_cfg); -+ } -+#endif -+ -+ hi2c->i2c_state = I2C_STATE_SUSPENDED; -+} -diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c -new file mode 100644 -index 0000000..b2c8a68 ---- /dev/null -+++ b/core/drivers/stm32_iwdg.c -@@ -0,0 +1,308 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* IWDG Compatibility */ -+#define IWDG_COMPAT "st,stm32mp1-iwdg" -+#define IWDG_TIMEOUT_US 100000U -+ -+/* 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_32(11, 0) -+ -+struct stm32_iwdg_instance { -+ uintptr_t pbase; -+ uintptr_t vbase; -+ unsigned long clock; -+ uint8_t instance; -+ uint8_t flags; -+}; -+ -+static struct stm32_iwdg_instance *stm32_iwdg; -+static size_t stm32_iwdg_count; -+ -+static uintptr_t get_base(struct stm32_iwdg_instance *iwdg) -+{ -+ if (!cpu_mmu_enabled()) { -+ return iwdg->pbase; -+ } -+ -+ return iwdg->vbase; -+} -+ -+static int stm32_iwdg_get_dt_node(void *fdt, struct dt_node_info *info, -+ int offset) -+{ -+ int node; -+ -+ node = fdt_get_node(fdt, info, offset, IWDG_COMPAT); -+ if (node < 0) { -+ if (offset == -1) { -+ DMSG("No IDWG found"); -+ } -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return node; -+} -+ -+static struct stm32_iwdg_instance *get_iwdg(unsigned int instance) -+{ -+ size_t i; -+ -+ for (i = 0; i < stm32_iwdg_count; i++) { -+ if (stm32_iwdg[i].instance == instance) { -+ return &stm32_iwdg[i]; -+ } -+ } -+ -+ return NULL; -+} -+ -+static enum itr_return stm32_iwdg_it_handler(struct itr_handler *handler) -+{ -+ unsigned int __maybe_unused cpu = get_core_pos(); -+ int instance = stm32mp_iwdg_irq2instance(handler->it); -+ struct stm32_iwdg_instance *iwdg = get_iwdg(instance); -+ uintptr_t iwdg_base = get_base(iwdg); -+ -+ DMSG("CPU %u IT Watchdog %d\n", cpu, instance + 1); -+ -+ stm32_iwdg_refresh(instance); -+ -+ stm32_clock_enable(iwdg->clock); -+ -+ mmio_setbits_32(iwdg_base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIC); -+ -+ stm32_clock_disable(iwdg->clock); -+ -+ stm32_cores_reset(); -+ -+ return ITRR_HANDLED; -+} -+KEEP_PAGER(stm32_iwdg_it_handler); -+ -+static int stm32_iwdg_get_secure_timeout(void *fdt, int node) -+{ -+ const fdt32_t *cuint; -+ -+ 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(void *fdt, int node, -+ struct stm32_iwdg_instance *iwdg) -+{ -+ int id_lsi; -+ int dt_secure_timeout = stm32_iwdg_get_secure_timeout(fdt, node); -+ uint32_t reload, status; -+ uint64_t timeout_ref; -+ unsigned long long reload_ll; -+ uintptr_t iwdg_base = get_base(iwdg); -+ struct itr_handler *itr; -+ -+ if (dt_secure_timeout < 0) { -+ return 0; -+ } -+ -+ if (dt_secure_timeout == 0) { -+ return -1; -+ } -+ -+ id_lsi = fdt_get_clock_id_by_name(fdt, node, "lsi"); -+ if (id_lsi < 0) { -+ return -1; -+ } -+ -+ /* Prescaler fix to 256 */ -+ reload_ll = (unsigned long long)dt_secure_timeout * -+ stm32mp1_clk_get_rate(id_lsi); -+ reload = ((uint32_t)(reload_ll >> 8) - 1U) & IWDG_EWCR_EWIT_MASK; -+ -+ stm32_clock_enable(iwdg->clock); -+ -+ write32(IWDG_KR_START_KEY, iwdg_base + IWDG_KR_OFFSET); -+ write32(IWDG_KR_ACCESS_KEY, iwdg_base + IWDG_KR_OFFSET); -+ write32(IWDG_PR_DIV_256, iwdg_base + IWDG_PR_OFFSET); -+ write32(IWDG_EWCR_EWIE | reload, iwdg_base + IWDG_EWCR_OFFSET); -+ -+ timeout_ref = utimeout_init(IWDG_TIMEOUT_US); -+ do { -+ status = read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_EWU; -+ if (utimeout_elapsed(IWDG_TIMEOUT_US, timeout_ref)) { -+ stm32_clock_disable(iwdg->clock); -+ return -1; -+ } -+ } while (status != 0U); -+ -+ stm32_clock_disable(iwdg->clock); -+ -+ itr = calloc(1, sizeof(struct itr_handler)); -+ if (itr == NULL) { -+ panic("out of memory"); -+ } -+ -+ itr->it = stm32mp_iwdg_instance2irq(iwdg->instance); -+ itr->handler = stm32_iwdg_it_handler; -+ itr_add(itr); -+ itr_enable(itr->it); -+ -+ return 0; -+} -+ -+void stm32_iwdg_refresh(uint32_t instance) -+{ -+ struct stm32_iwdg_instance *iwdg = get_iwdg(instance); -+ uintptr_t iwdg_base = get_base(iwdg); -+ -+ assert(iwdg); -+ -+ stm32_clock_enable(iwdg->clock); -+ -+ write32(IWDG_KR_RELOAD_KEY, iwdg_base + IWDG_KR_OFFSET); -+ -+ stm32_clock_disable(iwdg->clock); -+} -+ -+static TEE_Result iwdg_init(void) -+{ -+ int node = -1; -+ int res; -+ struct dt_node_info dt_info; -+ void *fdt; -+ size_t count; -+ -+ fdt = get_dt_blob(); -+ if (!fdt) { -+ panic(); -+ } -+ -+ assert((stm32_iwdg == NULL) && (stm32_iwdg_count == 0)); -+ count = 0; -+ -+ for (node = stm32_iwdg_get_dt_node(fdt, &dt_info, node); -+ node != -FDT_ERR_NOTFOUND; -+ node = stm32_iwdg_get_dt_node(fdt, &dt_info, node)) { -+ struct stm32_iwdg_instance iwdg; -+ enum teecore_memtypes memtype; -+ uint32_t hw_init; -+ -+ memset(&iwdg, 0, sizeof(iwdg)); -+ iwdg.pbase = dt_info.base; -+ iwdg.clock = (unsigned long)dt_info.clock; -+ iwdg.instance = (uint8_t)stm32mp_iwdg_iomem2instance(iwdg.pbase); -+ -+ memtype = ((dt_info.status & DT_STATUS_OK_NSEC) != 0) ? -+ MEM_AREA_IO_NSEC : MEM_AREA_IO_SEC; -+ iwdg.vbase = (uintptr_t)phys_to_virt(iwdg.pbase, memtype); -+ -+ /* DT can specify low power cases */ -+ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) != -+ NULL) { -+ iwdg.flags |= IWDG_ENABLE_ON_STOP; -+ } -+ -+ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) != -+ NULL) { -+ iwdg.flags |= IWDG_ENABLE_ON_STANDBY; -+ } -+ -+ hw_init = stm32_get_iwdg_otp_config(iwdg.pbase); -+ -+ if ((hw_init & IWDG_HW_ENABLED) != 0) { -+ if (dt_info.status == DT_STATUS_DISABLED) { -+ panic("IWDG HW enabled"); -+ } -+ iwdg.flags |= IWDG_HW_ENABLED; -+ } -+ -+ if ((hw_init & IWDG_ENABLE_ON_STOP) != 0) { -+ iwdg.flags |= IWDG_ENABLE_ON_STOP; -+ } -+ -+ if ((hw_init & IWDG_ENABLE_ON_STANDBY) != 0) { -+ iwdg.flags |= IWDG_ENABLE_ON_STANDBY; -+ } -+ -+ if (dt_info.status == DT_STATUS_DISABLED) { -+ continue; -+ } -+ -+ DMSG("IWDG%u found, %ssecure", iwdg.instance + 1, -+ ((dt_info.status & DT_STATUS_OK_NSEC) != 0) ? "non " : ""); -+ -+ if ((dt_info.status & DT_STATUS_OK_NSEC) != 0) { -+ stm32mp_register_non_secure_periph_iomem(iwdg.pbase); -+ } else { -+ stm32mp_register_secure_periph_iomem(iwdg.pbase); -+ } -+ -+ stm32_clock_enable(iwdg.clock); -+ stm32_clock_disable(iwdg.clock); -+ -+ res = stm32_iwdg_conf_etimeout(fdt, node, &iwdg); -+ if (res != 0) { -+ EMSG("IWDG%x early timeout config failed (%d)\n", -+ iwdg.instance + 1, res); -+ panic(); -+ } -+ -+ stm32_iwdg = realloc(stm32_iwdg, (count + 1) * sizeof(iwdg)); -+ if (stm32_iwdg == NULL) { -+ panic("out of memory"); -+ } -+ -+ memcpy(&stm32_iwdg[count], &iwdg, sizeof(iwdg)); -+ count++; -+ } -+ -+ stm32_iwdg_count = count; -+ -+ DMSG("%u IWDG instance%s found", count, count > 1 ? "s" : ""); -+ -+ return TEE_SUCCESS; -+} -+driver_init(iwdg_init); -diff --git a/core/drivers/stm32_rng.c b/core/drivers/stm32_rng.c -new file mode 100644 -index 0000000..75bbef7 ---- /dev/null -+++ b/core/drivers/stm32_rng.c -@@ -0,0 +1,200 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DT_RNG_COMPAT "st,stm32-rng" -+#define RNG_CR 0x00U -+#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 -+ -+struct stm32_rng_instance { -+ uintptr_t pbase; -+ uintptr_t vbase; -+ unsigned long clock; -+}; -+ -+static struct stm32_rng_instance *stm32_rng; -+ -+static uintptr_t get_base(void) -+{ -+ if (!cpu_mmu_enabled()) { -+ return stm32_rng->pbase; -+ } -+ -+ return stm32_rng->vbase; -+} -+ -+int stm32_rng_read(uint8_t *out, size_t size) -+{ -+ uint8_t *buf = out; -+ size_t len = size; -+ uint64_t timeout_ref; -+ uint32_t data32; -+ uintptr_t rng_base = get_base(); -+ int rc = 0; -+ int count; -+ -+ if (stm32_rng == 0) { -+ return -1; -+ } -+ -+ stm32_clock_enable(stm32_rng->clock); -+ -+ if ((read32(rng_base + RNG_CR) & RNG_CR_RNGEN) == 0U) { -+ write32(RNG_CR_RNGEN | RNG_CR_CED, rng_base + RNG_CR); -+ } -+ -+ while (len != 0) { -+ timeout_ref = utimeout_init(RNG_TIMEOUT_US); -+ do { -+ uint32_t status = read32(rng_base + RNG_SR); -+ -+ if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) { -+ size_t i; -+ -+ /* Recommended by the SoC reference manual */ -+ io_mask32(rng_base + RNG_SR, 0, RNG_SR_SEIS); -+ dmb(); -+ for (i = 12; i != 0; i--) { -+ (void)read32(rng_base + RNG_DR); -+ } -+ dmb(); -+ -+ if ((read32(rng_base + RNG_SR) & RNG_SR_SEIS) != -+ 0U) { -+ panic("RNG noise"); -+ } -+ } -+ -+ if (utimeout_elapsed(RNG_TIMEOUT_US, timeout_ref)) { -+ rc = -1; -+ goto bail; -+ } -+ } while ((read32(rng_base + RNG_SR) & RNG_SR_DRDY) == 0U); -+ -+ count = 4; -+ while (len != 0) { -+ data32 = read32(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: -+ stm32_clock_disable(stm32_rng->clock); -+ -+ if (rc != 0) { -+ memset(out, 0, buf - out); -+ } -+ -+ return rc; -+} -+ -+static TEE_Result stm32_rng_init(void) -+{ -+ void *fdt; -+ struct dt_node_info dt_rng; -+ int node; -+ uint8_t __maybe_unused test[43]; -+ enum teecore_memtypes memtype; -+ -+ fdt = get_dt_blob(); -+ if (!fdt) { -+ panic(); -+ } -+ -+ node = fdt_get_node(fdt, &dt_rng, -1, DT_RNG_COMPAT); -+ if (node < 0) { -+ return TEE_SUCCESS; -+ } -+ -+ if ((dt_rng.status & DT_STATUS_OK_SEC) == 0) { -+ return TEE_SUCCESS; -+ } -+ -+ assert(dt_rng.base == RNG1_BASE); -+ -+ if (stm32_rng) { -+ panic(); -+ } -+ stm32_rng = calloc(1, sizeof(*stm32_rng)); -+ if (!stm32_rng) { -+ panic(); -+ } -+ -+ stm32_rng->pbase = dt_rng.base; -+ -+ if ((dt_rng.status & DT_STATUS_OK_NSEC) != 0) { -+ memtype = MEM_AREA_IO_NSEC; -+ stm32mp_register_non_secure_periph_iomem(stm32_rng->pbase); -+ } else { -+ memtype = MEM_AREA_IO_SEC; -+ stm32mp_register_secure_periph_iomem(stm32_rng->pbase); -+ } -+ -+ stm32_rng->vbase = (uintptr_t)phys_to_virt(stm32_rng->pbase, memtype); -+ -+ if (dt_rng.clock < 0) { -+ panic(); -+ } -+ stm32_rng->clock = (unsigned long)dt_rng.clock; -+ -+ stm32_clock_enable(stm32_rng->clock); -+ stm32_clock_disable(stm32_rng->clock); -+ -+ if (dt_rng.reset >= 0) { -+ stm32_reset_assert((unsigned long)dt_rng.reset); -+ udelay(20); -+ stm32_reset_deassert((unsigned long)dt_rng.reset); -+ } -+ -+ DMSG("Init RNG done"); -+ -+#if TRACE_LEVEL >= TRACE_DEBUG -+ memset(test, 0xa5, sizeof(test)); -+ if (stm32_rng_read(test, sizeof(test))) { -+ panic("RNG test"); -+ } -+ -+ DHEXDUMP(test, sizeof(test)); -+#endif -+ -+ return TEE_SUCCESS; -+} -+driver_init(stm32_rng_init); -diff --git a/core/drivers/stm32_rtc.c b/core/drivers/stm32_rtc.c -new file mode 100644 -index 0000000..709fafa ---- /dev/null -+++ b/core/drivers/stm32_rtc.c -@@ -0,0 +1,503 @@ -+/* -+ * Copyright (c) 2018, 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 0x0000000FU -+#define RTC_TR_ST_MASK 0x00000070U -+#define RTC_TR_ST_SHIFT 4 -+#define RTC_TR_MNU_MASK 0x00000F00U -+#define RTC_TR_MNU_SHIFT 8 -+#define RTC_TR_MNT_MASK 0x00007000U -+#define RTC_TR_MNT_SHIFT 12 -+#define RTC_TR_HU_MASK 0x000F0000U -+#define RTC_TR_HU_SHIFT 16 -+#define RTC_TR_HT_MASK 0x00300000U -+#define RTC_TR_HT_SHIFT 20 -+#define RTC_TR_PM BIT(22) -+ -+#define RTC_DR_DU_MASK 0x0000000FU -+#define RTC_DR_DT_MASK 0x00000030U -+#define RTC_DR_DT_SHIFT 4 -+#define RTC_DR_MU_MASK 0x00000F00U -+#define RTC_DR_MU_SHIFT 8 -+#define RTC_DR_MT BIT(12) -+#define RTC_DR_MT_SHIFT 12 -+#define RTC_DR_WDU_MASK 0x0000E000U -+#define RTC_DR_WDU_SHIFT 13 -+#define RTC_DR_YU_MASK 0x000F0000U -+#define RTC_DR_YU_SHIFT 16 -+#define RTC_DR_YT_MASK 0x00F00000U -+#define RTC_DR_YT_SHIFT 20 -+ -+#define RTC_SSR_SS_MASK 0x0000FFFFU -+ -+#define RTC_ICSR_RSF BIT(5) -+ -+#define RTC_PRER_PREDIV_S_MASK 0x0000FFFFU -+ -+#define RTC_CR_BYPSHAD BIT(5) -+#define RTC_CR_BYPSHAD_SHIFT 5 -+#define RTC_CR_TAMPTS BIT(25) -+ -+#define RTC_SMCR_TS_DPROT BIT(3) -+#define RTC_SR_TSF BIT(3) -+#define RTC_SCR_CTSF BIT(3) -+#define RTC_SR_TSOVF BIT(4) -+#define RTC_SCR_CTSOVF BIT(4) -+ -+#define RTC_TSDR_MU_MASK 0x00000F00U -+#define RTC_TSDR_MU_SHIFT 8 -+#define RTC_TSDR_DT_MASK 0x00000030U -+#define RTC_TSDR_DT_SHIFT 4 -+#define RTC_TSDR_DU_MASK 0x0000000FU -+#define RTC_TSDR_DU_SHIFT 0 -+ -+#define RTC_WPR_KEY1 0xCA -+#define RTC_WPR_KEY2 0x53 -+#define RTC_WPR_KEY_LOCK 0xFF -+ -+#define RTC_FLAGS_READ_TWICE BIT(0) -+#define RTC_FLAGS_SECURE BIT(1) -+ -+struct rtc_device { -+ uintptr_t pbase; -+ uintptr_t vbase; -+ uint16_t clock; -+ uint8_t flags; -+}; -+ -+struct rtc_device rtc_dev; -+ -+static uintptr_t get_base(void) -+{ -+ if (!cpu_mmu_enabled()) -+ return rtc_dev.pbase; -+ -+ return rtc_dev.vbase; -+} -+ -+static void stm32_rtc_write_unprotect(void) -+{ -+ uintptr_t rtc_base = get_base(); -+ -+ mmio_write_32(rtc_base + RTC_WPR, RTC_WPR_KEY1); -+ mmio_write_32(rtc_base + RTC_WPR, RTC_WPR_KEY2); -+} -+ -+static void stm32_rtc_write_protect(void) -+{ -+ uintptr_t rtc_base = get_base(); -+ -+ mmio_write_32(rtc_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(get_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) -+{ -+ uintptr_t rtc_base = get_base(); -+ bool bypshad = stm32_rtc_get_bypshad(); -+ -+ if (!bypshad) { -+ mmio_clrbits_32((uint32_t)(rtc_base + RTC_ICSR), RTC_ICSR_RSF); -+ while ((mmio_read_32(rtc_base + RTC_ICSR) & RTC_ICSR_RSF) != -+ RTC_ICSR_RSF) { -+ ; -+ } -+ } -+ -+ calendar->ssr = mmio_read_32(rtc_base + RTC_SSR); -+ calendar->tr = mmio_read_32(rtc_base + RTC_TR); -+ calendar->dr = mmio_read_32(rtc_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) -+{ -+ 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) -+{ -+ 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) -+{ -+ struct stm32_rtc_calendar cal_tamp; -+ uintptr_t rtc_base = get_base(); -+ -+ cal_tamp.tr = mmio_read_32(rtc_base + RTC_TSTR); -+ cal_tamp.dr = mmio_read_32(rtc_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) -+{ -+ stm32_clock_enable(rtc_dev.clock); -+ -+ stm32_rtc_read_calendar(calendar); -+ -+ if (rtc_dev.flags & RTC_FLAGS_READ_TWICE) { -+ uint32_t tr_save = calendar->tr; -+ -+ stm32_rtc_read_calendar(calendar); -+ -+ if (calendar->tr != tr_save) { -+ stm32_rtc_read_calendar(calendar); -+ } -+ } -+ -+ stm32_clock_disable(rtc_dev.clock); -+} -+ -+/******************************************************************************* -+ * 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(get_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 unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -+ struct stm32_rtc_calendar *ref) -+{ -+ unsigned long long val_r; -+ unsigned long long val_c; -+ -+ val_r = stm32_rtc_get_second_fraction(ref); -+ val_c = stm32_rtc_get_second_fraction(cur); -+ -+ if (val_c >= val_r) { -+ return val_c - val_r; -+ } else { -+ return 1000U - val_r + val_c; -+ } -+} -+ -+/******************************************************************************* -+ * This function computes the time difference between two timestamps. -+ * It includes seconds, minutes and hours. -+ * Here again the returned value is in milliseconds. -+ ******************************************************************************/ -+static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) -+{ -+ signed long long diff_in_s; -+ 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); -+ -+ diff_in_s = curr_s - ref_s; -+ if (diff_in_s < 0) { -+ diff_in_s += 24 * 60 * 60; -+ } -+ -+ return (unsigned long long)diff_in_s * 1000U; -+} -+ -+/******************************************************************************* -+ * 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 unsigned 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 (24ULL * 60U * 60U * 1000U) * (unsigned 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) -+{ -+ unsigned long long diff_in_ms = 0; -+ struct stm32_rtc_time curr_t; -+ struct stm32_rtc_time ref_t; -+ -+ stm32_clock_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); -+ -+ stm32_clock_disable(rtc_dev.clock); -+ -+ return diff_in_ms; -+} -+ -+/******************************************************************************* -+ * This function fill the RTC timestamp structure. -+ ******************************************************************************/ -+void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts) -+{ -+ uintptr_t rtc_base = get_base(); -+ -+ stm32_clock_enable(rtc_dev.clock); -+ -+ if ((mmio_read_32(rtc_base + RTC_SR) & RTC_SR_TSF) != 0U) { -+ /* Print timestamp for tamper event */ -+ stm32_rtc_read_timestamp(tamp_ts); -+ mmio_setbits_32(rtc_base + RTC_SCR, RTC_SCR_CTSF); -+ if ((mmio_read_32(rtc_base + RTC_SR) & RTC_SR_TSOVF) != -+ 0U) { -+ /* Overflow detected */ -+ mmio_setbits_32(rtc_base + RTC_SCR, RTC_SCR_CTSOVF); -+ } -+ } -+ -+ stm32_clock_disable(rtc_dev.clock); -+} -+ -+/******************************************************************************* -+ * This function enable the timestamp bit for tamper and secure timestamp -+ * access. -+ ******************************************************************************/ -+void stm32_rtc_set_tamper_timestamp(void) -+{ -+ uintptr_t rtc_base = get_base(); -+ -+ stm32_clock_enable(rtc_dev.clock); -+ -+ stm32_rtc_write_unprotect(); -+ -+ /* Enable tamper timestamper */ -+ mmio_setbits_32(rtc_base + RTC_CR, RTC_CR_TAMPTS); -+ -+ /* Secure Timestamp bit */ -+ mmio_clrbits_32(rtc_base + RTC_SMCR, RTC_SMCR_TS_DPROT); -+ -+ stm32_rtc_write_protect(); -+ -+ stm32_clock_disable(rtc_dev.clock); -+} -+ -+/******************************************************************************* -+ * This function return state of tamper timestamp. -+ ******************************************************************************/ -+bool stm32_rtc_is_timestamp_enable(void) -+{ -+ bool ret; -+ -+ stm32_clock_enable(rtc_dev.clock); -+ -+ ret = (mmio_read_32(get_base() + RTC_CR) & RTC_CR_TAMPTS) != 0U; -+ -+ stm32_clock_disable(rtc_dev.clock); -+ -+ return ret; -+} -+ -+#ifdef CFG_DT -+/******************************************************************************* -+ * RTC initialisation function. -+ ******************************************************************************/ -+static TEE_Result stm32_rtc_init(void) -+{ -+ int node; -+ struct dt_node_info dt_info; -+ void *fdt = get_dt_blob(); -+ -+ if (!fdt) { -+ panic(); -+ } -+ -+ node = fdt_get_node(fdt, &dt_info, -1, RTC_COMPAT); -+ if (node < 0) { -+ return node; -+ } -+ -+ rtc_dev.pbase = dt_info.base; -+ -+ if (dt_info.status == DT_STATUS_OK_SEC) { -+ rtc_dev.flags |= RTC_FLAGS_SECURE; -+ stm32mp_register_secure_periph_iomem(rtc_dev.pbase); -+ rtc_dev.vbase = (uintptr_t)phys_to_virt(rtc_dev.pbase, -+ MEM_AREA_IO_SEC); -+ } else { -+ stm32mp_register_non_secure_periph_iomem(rtc_dev.pbase); -+ rtc_dev.vbase = (uintptr_t)phys_to_virt(rtc_dev.pbase, -+ MEM_AREA_IO_NSEC); -+ } -+ -+ rtc_dev.clock = (unsigned long)dt_info.clock; -+ -+ if (stm32_rtc_get_read_twice()) { -+ rtc_dev.flags |= RTC_FLAGS_READ_TWICE; -+ } -+ -+ return 0; -+} -+driver_init(stm32_rtc_init); -+#endif -diff --git a/core/drivers/stm32_timer.c b/core/drivers/stm32_timer.c -new file mode 100644 -index 0000000..be03577 ---- /dev/null -+++ b/core/drivers/stm32_timer.c -@@ -0,0 +1,272 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2018, STMicroelectronics -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TIM_CR1 0x00U /* Control Register 1 */ -+#define TIM_CR2 0x04U /* Control Register 2 */ -+#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_32(2, 0) /* Slave mode selection */ -+#define TIM_SMCR_TS GENMASK_32(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_32(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 -+ -+struct stm32_timer_instance { -+ struct io_pa_va base; -+ unsigned long clk; -+ unsigned long freq; -+ uint8_t cal_input; -+}; -+ -+static uintptr_t timer_base(struct stm32_timer_instance *timer) -+{ -+ return (uintptr_t)io_pa_or_va(&timer->base); -+} -+ -+/* Currently support HSI and CSI calibratrion */ -+#define TIM_MAX_INSTANCE 2 -+ -+static struct stm32_timer_instance stm32_timer[TIM_MAX_INSTANCE]; -+ -+static int timer_get_dt_node(void *fdt, struct dt_node_info *info, int offset) -+{ -+ int node; -+ -+ node = fdt_get_node(fdt, info, offset, TIM_COMPAT); -+ if (node < 0) { -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ return node; -+} -+ -+static void timer_config(struct stm32_timer_instance *timer) -+{ -+ uintptr_t base = timer_base(timer); -+ -+ stm32_clock_enable(timer->clk); -+ -+ timer->freq = stm32_clock_get_rate(timer->clk); -+ -+ if ((mmio_read_32(base + TIM_TISEL) & TIM_TISEL_TI1SEL_MASK) != -+ timer->cal_input) { -+ mmio_clrsetbits_32(base + TIM_CCMR1, -+ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC1S_TI2, -+ TIM_CCMR_CC1S_TI1); -+ -+ mmio_clrbits_32(base + TIM_CCER, -+ TIM_CCER_CC1P | TIM_CCER_CC1NP); -+ -+ mmio_clrsetbits_32(base + TIM_SMCR, -+ TIM_SMCR_TS | TIM_SMCR_SMS, -+ (TIM_SMCR_TS_TI1FP1 << TIM_SMCR_TS_SHIFT) | -+ TIM_SMCR_SMS_RESET); -+ -+ mmio_write_32(base + TIM_TISEL, timer->cal_input); -+ mmio_setbits_32(base + TIM_CR1, TIM_CR1_CEN); -+ mmio_setbits_32(base + TIM_CCER, TIM_CCER_CC1E); -+ } -+ -+ stm32_clock_disable(timer->clk); -+} -+ -+static uint32_t timer_start_capture(struct stm32_timer_instance *timer) -+{ -+ uint64_t timeout_ref; -+ uint32_t counter = 0U; -+ uint32_t old_counter = 0U; -+ int twice; -+ uintptr_t base = timer_base(timer); -+ -+ timer_config(timer); -+ -+ stm32_clock_enable(timer->clk); -+ -+ mmio_write_32(base + TIM_SR, 0U); -+ -+ timeout_ref = utimeout_init(TIM_TIMEOUT_US); -+ -+ while ((mmio_read_32(base + TIM_SR) & TIM_SR_UIF) == 0U) { -+ if (utimeout_elapsed(TIM_TIMEOUT_US, timeout_ref)) { -+ goto bail; -+ } -+ } -+ -+ mmio_write_32(base + TIM_SR, 0U); -+ -+ for (twice = 0; (twice < 2) || (counter != old_counter); twice++) { -+ timeout_ref = utimeout_init(TIM_TIMEOUT_US); -+ -+ while ((mmio_read_32(base + TIM_SR) & TIM_SR_CC1IF) == 0U) { -+ if (utimeout_elapsed(TIM_TIMEOUT_US, timeout_ref)) { -+ counter = 0U; -+ goto bail; -+ } -+ } -+ -+ old_counter = counter; -+ counter = mmio_read_32(base + TIM_CCR1); -+ } -+ -+bail: -+ stm32_clock_disable(timer->clk); -+ -+ return counter; -+} -+ -+unsigned long stm32_timer_hsi_freq(void) -+{ -+ struct stm32_timer_instance *timer = &stm32_timer[HSI_CAL]; -+ uint32_t counter = 0; -+ -+ if (timer->base.pa != 0) { -+ counter = timer_start_capture(timer); -+ } -+ -+ return (counter == 0) ? 0 : (timer->freq / counter) << TIM_PRESCAL_HSI; -+} -+KEEP_PAGER(stm32_timer_hsi_freq); -+ -+unsigned long stm32_timer_csi_freq(void) -+{ -+ struct stm32_timer_instance *timer = &stm32_timer[CSI_CAL]; -+ uint32_t counter = 0; -+ -+ if (timer->base.pa != 0) { -+ counter = timer_start_capture(timer); -+ } -+ -+ return (counter == 0U) ? 0 : (timer->freq / counter) << TIM_PRESCAL_CSI; -+} -+KEEP_PAGER(stm32_timer_csi_freq); -+ -+static void _init_stm32_timer(void) -+{ -+ void *fdt = get_dt_blob(); -+ struct dt_node_info dt_timer; -+ int node = -1; -+ static bool inited; -+ -+ if (inited) -+ return; -+ inited = true; -+ -+ if (!fdt) { -+ panic(); -+ } -+ -+ for (node = timer_get_dt_node(fdt, &dt_timer, node); -+ node != -FDT_ERR_NOTFOUND; -+ node = timer_get_dt_node(fdt, &dt_timer, node)) { -+ struct stm32_timer_instance *timer; -+ const uint32_t *cuint; -+ -+ if (!(dt_timer.status & DT_STATUS_OK_SEC)) { -+ continue; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "st,hsi-cal-input", NULL); -+ if (cuint != NULL) { -+ timer = &stm32_timer[HSI_CAL]; -+ timer->base.pa = dt_timer.base; -+ timer->clk = dt_timer.clock; -+ timer->freq = stm32_clock_get_rate(timer->clk); -+ timer->cal_input = (uint8_t)fdt32_to_cpu(*cuint); -+ timer_config(timer); -+ } -+ -+ cuint = fdt_getprop(fdt, node, "st,csi_cal-input", NULL); -+ if (cuint != NULL) { -+ timer = &stm32_timer[CSI_CAL]; -+ timer->base.pa = dt_timer.base; -+ timer->clk = dt_timer.clock; -+ timer->freq = stm32_clock_get_rate(timer->clk); -+ timer->cal_input = (uint8_t)fdt32_to_cpu(*cuint); -+ timer_config(timer); -+ } -+ } -+} -+ -+void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void), -+ enum timer_cal type) -+{ -+ _init_stm32_timer(); -+ -+ *timer_freq_cb = NULL; -+ -+ switch (type) { -+ case HSI_CAL: -+ if (stm32_timer[HSI_CAL].base.pa != 0) { -+ *timer_freq_cb = stm32_timer_hsi_freq; -+ } -+ break; -+ -+ case CSI_CAL: -+ if (stm32_timer[CSI_CAL].base.pa != 0) { -+ *timer_freq_cb = stm32_timer_csi_freq; -+ } -+ break; -+ default: -+ panic(); -+ } -+} -+ -+static TEE_Result init_stm32_timer(void) -+{ -+ _init_stm32_timer(); -+ -+ return TEE_SUCCESS; -+} -+driver_init(init_stm32_timer); -diff --git a/core/drivers/stm32_uart.c b/core/drivers/stm32_uart.c -index 1febd84..4afbac8 100644 ---- a/core/drivers/stm32_uart.c -+++ b/core/drivers/stm32_uart.c -@@ -4,10 +4,18 @@ - */ - - #include -+#include - #include - #include -+#include - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include - #include - - #define UART_REG_CR1 0x00 /* Control register 1 */ -@@ -21,6 +29,11 @@ - #define UART_REG_TDR 0x28 /* Transmit data register */ - #define UART_REG_PRESC 0x2c /* Prescaler register */ - -+#define STM32_UART_IOMEM_SIZE 0x400 -+ -+#define PUTC_TIMEOUT_US 1000 -+#define FLUSH_TIMEOUT_US 16000 -+ - /* - * Uart Interrupt & status register bits - * -@@ -36,26 +49,52 @@ - - static vaddr_t loc_chip_to_base(struct serial_chip *chip) - { -- struct console_pdata *pd = -- container_of(chip, struct console_pdata, chip); -- -- return io_pa_or_va(&pd->base); -+ struct stm32_uart_pdata *pd = -+ container_of(chip, struct stm32_uart_pdata, chip); -+ -+ if (cpu_mmu_enabled()) { -+ if (!pd->base.va) { -+ pd->base.va = (vaddr_t)phys_to_virt(pd->base.pa, -+ pd->secure ? -+ MEM_AREA_IO_SEC : -+ MEM_AREA_IO_NSEC); -+ assert(pd->base.va); -+ } -+ -+ return pd->base.va; -+ } -+ -+ return pd->base.pa; - } - - static void loc_flush(struct serial_chip *chip) - { - vaddr_t base = loc_chip_to_base(chip); -- -- while (!(read32(base + UART_REG_ISR) & USART_ISR_TXFE)) -- ; -+ uint64_t timeout_ref = utimeout_init(FLUSH_TIMEOUT_US); -+ -+ while (!(read32(base + UART_REG_ISR) & USART_ISR_TXFE)) { -+ if (utimeout_elapsed(FLUSH_TIMEOUT_US, timeout_ref)) { -+ if (read32(base + UART_REG_ISR) & USART_ISR_TXFE) { -+ break; -+ } -+ return; -+ } -+ } - } - - static void loc_putc(struct serial_chip *chip, int ch) - { - vaddr_t base = loc_chip_to_base(chip); -+ uint64_t timeout_ref = utimeout_init(PUTC_TIMEOUT_US); - -- while (!(read32(base + UART_REG_ISR) & USART_ISR_TXE_TXFNF)) -- ; -+ while (!(read32(base + UART_REG_ISR) & USART_ISR_TXE_TXFNF)) { -+ if (utimeout_elapsed(PUTC_TIMEOUT_US, timeout_ref)) { -+ if (read32(base + UART_REG_ISR) & USART_ISR_TXE_TXFNF) { -+ break; -+ } -+ return; -+ } -+ } - - write32(ch, base + UART_REG_TDR); - } -@@ -77,17 +116,94 @@ static int loc_getchar(struct serial_chip *chip) - return read32(base + UART_REG_RDR) & 0xff; - } - --static const struct serial_ops serial_ops = { -+static const struct serial_ops stm32_uart_serial_ops = { - .flush = loc_flush, - .putc = loc_putc, - .have_rx_data = loc_have_rx_data, - .getchar = loc_getchar, - - }; --KEEP_PAGER(serial_ops); -+KEEP_PAGER(stm32_uart_serial_ops); - --void stm32_uart_init(struct console_pdata *pd, vaddr_t base) -+void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base) - { - pd->base.pa = base; -- pd->chip.ops = &serial_ops; -+ pd->chip.ops = &stm32_uart_serial_ops; -+} -+ -+#ifdef CFG_DT -+static void register_secure_uart(struct stm32_uart_pdata *pd) -+{ -+ size_t n; -+ -+ stm32mp_register_secure_periph_iomem(pd->base.pa); -+ for (n = 0; n < pd->pinctrl_count; n++) { -+ stm32mp_register_secure_gpio(pd->pinctrl[n].bank, -+ pd->pinctrl[n].pin); -+ } -+} -+ -+static void register_non_secure_uart(struct stm32_uart_pdata *pd) -+{ -+ size_t n; -+ -+ stm32mp_register_non_secure_periph_iomem(pd->base.pa); -+ for (n = 0; n < pd->pinctrl_count; n++) { -+ stm32mp_register_non_secure_gpio(pd->pinctrl[n].bank, -+ pd->pinctrl[n].pin); -+ } - } -+ -+struct stm32_uart_pdata *probe_uart_from_dt_node(void *fdt, int node) -+{ -+ struct stm32_uart_pdata *pd; -+ struct dt_node_info info; -+ struct stm32_pinctrl *pinctrl_cfg = NULL; -+ int count; -+ -+ fdt_fill_device_info(fdt, &info, node); -+ -+ if (info.status == DT_STATUS_DISABLED) { -+ return NULL; -+ } -+ -+ pd = calloc(1, sizeof(*pd)); -+ if (!pd) { -+ panic(); -+ } -+ -+ pd->secure = (info.status == DT_STATUS_OK_SEC); -+ pd->base.pa = info.base; -+ -+ if (info.clock < 0) { -+ panic(); -+ } -+ pd->clock = (unsigned int)info.clock; -+ -+ count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); -+ if (count < 0) { -+ panic(); -+ } -+ if (count != 0) { -+ pinctrl_cfg = calloc(count, sizeof(*pinctrl_cfg)); -+ if (!pinctrl_cfg) { -+ panic(); -+ } -+ stm32_pinctrl_fdt_get_pinctrl(fdt, node, pinctrl_cfg, count); -+ stm32_pinctrl_load_active_cfg(pinctrl_cfg, count); -+ } -+ pd->pinctrl = pinctrl_cfg; -+ pd->pinctrl_count = count; -+ -+ stm32_uart_init(pd, info.base); -+ -+ if (pd->secure) { -+ register_secure_uart(pd); -+ } else { -+ register_non_secure_uart(pd); -+ } -+ -+ return pd; -+} -+#endif /*CFG_DT*/ -+ -diff --git a/core/drivers/stpmic1.c b/core/drivers/stpmic1.c -new file mode 100644 -index 0000000..3aa3afc ---- /dev/null -+++ b/core/drivers/stpmic1.c -@@ -0,0 +1,954 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define I2C_TIMEOUT_MS 25 -+ -+struct regul_struct { -+ const char *dt_node_name; -+ const uint16_t *voltage_table; -+ uint8_t voltage_table_size; -+ uint8_t control_reg; -+ uint8_t low_power_reg; -+ uint8_t pull_down_reg; -+ uint8_t pull_down; -+ uint8_t mask_reset_reg; -+ uint8_t mask_reset; -+}; -+ -+static struct i2c_handle_s *pmic_i2c_handle; -+static uint16_t pmic_i2c_addr; -+ -+/* Voltage tables in mV */ -+static const uint16_t buck1_voltage_table[] = { -+ 725, -+ 725, -+ 725, -+ 725, -+ 725, -+ 725, -+ 750, -+ 775, -+ 800, -+ 825, -+ 850, -+ 875, -+ 900, -+ 925, -+ 950, -+ 975, -+ 1000, -+ 1025, -+ 1050, -+ 1075, -+ 1100, -+ 1125, -+ 1150, -+ 1175, -+ 1200, -+ 1225, -+ 1250, -+ 1275, -+ 1300, -+ 1325, -+ 1350, -+ 1375, -+ 1400, -+ 1425, -+ 1450, -+ 1475, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+ 1500, -+}; -+ -+static const uint16_t buck2_voltage_table[] = { -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1050, -+ 1050, -+ 1100, -+ 1100, -+ 1150, -+ 1150, -+ 1200, -+ 1200, -+ 1250, -+ 1250, -+ 1300, -+ 1300, -+ 1350, -+ 1350, -+ 1400, -+ 1400, -+ 1450, -+ 1450, -+ 1500, -+}; -+ -+static const uint16_t buck3_voltage_table[] = { -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1000, -+ 1100, -+ 1100, -+ 1100, -+ 1100, -+ 1200, -+ 1200, -+ 1200, -+ 1200, -+ 1300, -+ 1300, -+ 1300, -+ 1300, -+ 1400, -+ 1400, -+ 1400, -+ 1400, -+ 1500, -+ 1600, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3400, -+}; -+ -+static const uint16_t buck4_voltage_table[] = { -+ 600, -+ 625, -+ 650, -+ 675, -+ 700, -+ 725, -+ 750, -+ 775, -+ 800, -+ 825, -+ 850, -+ 875, -+ 900, -+ 925, -+ 950, -+ 975, -+ 1000, -+ 1025, -+ 1050, -+ 1075, -+ 1100, -+ 1125, -+ 1150, -+ 1175, -+ 1200, -+ 1225, -+ 1250, -+ 1275, -+ 1300, -+ 1300, -+ 1350, -+ 1350, -+ 1400, -+ 1400, -+ 1450, -+ 1450, -+ 1500, -+ 1600, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3400, -+ 3500, -+ 3600, -+ 3700, -+ 3800, -+ 3900, -+}; -+ -+static const uint16_t ldo1_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+}; -+ -+static const uint16_t ldo2_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+}; -+ -+static const uint16_t ldo3_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 3300, -+ 0xFFFF, /* VREFDDR */ -+}; -+ -+static const uint16_t ldo5_voltage_table[] = { -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+ 3400, -+ 3500, -+ 3600, -+ 3700, -+ 3800, -+ 3900, -+}; -+ -+static const uint16_t ldo6_voltage_table[] = { -+ 900, -+ 1000, -+ 1100, -+ 1200, -+ 1300, -+ 1400, -+ 1500, -+ 1600, -+ 1700, -+ 1800, -+ 1900, -+ 2000, -+ 2100, -+ 2200, -+ 2300, -+ 2400, -+ 2500, -+ 2600, -+ 2700, -+ 2800, -+ 2900, -+ 3000, -+ 3100, -+ 3200, -+ 3300, -+}; -+ -+static const uint16_t ldo4_voltage_table[] = { -+ 3300, -+}; -+ -+static const uint16_t vref_ddr_voltage_table[] = { -+ 3300, -+}; -+ -+/* Table of Regulators in PMIC SoC */ -+static const struct regul_struct regulators_table[] = { -+ { -+ .dt_node_name = "buck1", -+ .voltage_table = buck1_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), -+ .control_reg = BUCK1_CONTROL_REG, -+ .low_power_reg = BUCK1_PWRCTRL_REG, -+ .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_SHIFT, -+ }, -+ { -+ .dt_node_name = "buck2", -+ .voltage_table = buck2_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), -+ .control_reg = BUCK2_CONTROL_REG, -+ .low_power_reg = BUCK2_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK2_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK2_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "buck3", -+ .voltage_table = buck3_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), -+ .control_reg = BUCK3_CONTROL_REG, -+ .low_power_reg = BUCK3_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK3_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK3_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "buck4", -+ .voltage_table = buck4_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), -+ .control_reg = BUCK4_CONTROL_REG, -+ .low_power_reg = BUCK4_PWRCTRL_REG, -+ .pull_down_reg = BUCK_PULL_DOWN_REG, -+ .pull_down = BUCK4_PULL_DOWN_SHIFT, -+ .mask_reset_reg = MASK_RESET_BUCK_REG, -+ .mask_reset = BUCK4_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "ldo1", -+ .voltage_table = ldo1_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), -+ .control_reg = LDO1_CONTROL_REG, -+ .low_power_reg = LDO1_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO1_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "ldo2", -+ .voltage_table = ldo2_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), -+ .control_reg = LDO2_CONTROL_REG, -+ .low_power_reg = LDO2_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO2_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "ldo3", -+ .voltage_table = ldo3_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), -+ .control_reg = LDO3_CONTROL_REG, -+ .low_power_reg = LDO3_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO3_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "ldo4", -+ .voltage_table = ldo4_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), -+ .control_reg = LDO4_CONTROL_REG, -+ .low_power_reg = LDO4_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO4_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "ldo5", -+ .voltage_table = ldo5_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), -+ .control_reg = LDO5_CONTROL_REG, -+ .low_power_reg = LDO5_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO5_MASK_RESET_SHIFT, -+ }, -+ { -+ .dt_node_name = "ldo6", -+ .voltage_table = ldo6_voltage_table, -+ .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), -+ .control_reg = LDO6_CONTROL_REG, -+ .low_power_reg = LDO6_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = LDO6_MASK_RESET_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, -+ .low_power_reg = VREF_DDR_PWRCTRL_REG, -+ .mask_reset_reg = MASK_RESET_LDO_REG, -+ .mask_reset = VREF_DDR_MASK_RESET_SHIFT, -+ }, -+}; -+ -+#define MAX_REGUL ARRAY_SIZE(regulators_table) -+ -+static const struct regul_struct *get_regulator_data(const char *name) -+{ -+ uint8_t i; -+ -+ for (i = 0 ; i < MAX_REGUL ; i++) { -+ if (strncmp(name, regulators_table[i].dt_node_name, -+ strlen(regulators_table[i].dt_node_name)) == 0) { -+ return ®ulators_table[i]; -+ } -+ } -+ -+ /* Regulator not found */ -+ panic(); -+ return NULL; -+} -+ -+static uint8_t voltage_to_index(const char *name, uint16_t millivolts) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ uint8_t i; -+ -+ for (i = 0 ; i < regul->voltage_table_size ; i++) { -+ if (regul->voltage_table[i] == millivolts) { -+ return i; -+ } -+ } -+ -+ /* Voltage not found */ -+ panic(); -+ -+ return 0; -+} -+ -+int stpmic1_powerctrl_on(void) -+{ -+ return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, -+ PWRCTRL_PIN_VALID); -+} -+ -+int stpmic1_switch_off(void) -+{ -+ return stpmic1_register_update(MAIN_CONTROL_REG, 1, -+ SOFTWARE_SWITCH_OFF_ENABLED); -+} -+ -+int stpmic1_regulator_enable(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0)); -+} -+ -+int stpmic1_regulator_disable(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->control_reg, 0, BIT(0)); -+} -+ -+uint8_t stpmic1_is_regulator_enabled(const char *name) -+{ -+ uint8_t val; -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ if (stpmic1_register_read(regul->control_reg, &val) != 0) { -+ panic(); -+ } -+ -+ return (val & 0x1U); -+} -+ -+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) -+{ -+ uint8_t voltage_index = voltage_to_index(name, millivolts); -+ const struct regul_struct *regul = get_regulator_data(name); -+ uint8_t mask; -+ -+ /* Voltage can be set for buck or ldo (except ldo4) regulators */ -+ if (strncmp(name, "buck", 4) == 0) { -+ mask = BUCK_VOLTAGE_MASK; -+ } else if ((strncmp(name, "ldo", 3) == 0) && -+ (strncmp(name, "ldo4", 4) != 0)) { -+ mask = LDO_VOLTAGE_MASK; -+ } else { -+ return 0; -+ } -+ -+ return stpmic1_register_update(regul->control_reg, -+ voltage_index << LDO_BUCK_VOLTAGE_SHIFT, -+ mask); -+} -+ -+int stpmic1_regulator_pull_down_set(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ if (regul->pull_down_reg != 0) { -+ return stpmic1_register_update(regul->pull_down_reg, -+ BIT(regul->pull_down), -+ LDO_BUCK_PULL_DOWN_MASK << -+ regul->pull_down); -+ } -+ -+ return 0; -+} -+ -+int stpmic1_regulator_mask_reset_set(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ return stpmic1_register_update(regul->mask_reset_reg, -+ BIT(regul->mask_reset), -+ LDO_BUCK_RESET_MASK << -+ regul->mask_reset); -+} -+ -+int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg) -+{ -+ return stpmic1_register_update(cfg->ctrl_reg, BIT(0), BIT(0)); -+} -+ -+/* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ -+int stpmic1_bo_voltage_cfg(const char *name, uint16_t millivolts, -+ struct stpmic1_bo_cfg *cfg) -+{ -+ 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 1; -+ } -+ -+ cfg->ctrl_reg = regul->control_reg; -+ cfg->value = voltage_index << LDO_BUCK_VOLTAGE_SHIFT; -+ cfg->mask = mask; -+ -+ return 0; -+} -+ -+int stpmic1_bo_voltage_unpg(struct stpmic1_bo_cfg *cfg) -+{ -+ return stpmic1_register_update(cfg->ctrl_reg, cfg->value, cfg->mask); -+} -+ -+int stpmic1_bo_pull_down_cfg(const char *name, struct stpmic1_bo_cfg *cfg) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ cfg->pd_reg = regul->pull_down_reg; -+ cfg->pd_value = BIT(regul->pull_down); -+ cfg->pd_mask = LDO_BUCK_PULL_DOWN_MASK << regul->pull_down; -+ -+ return 0; -+} -+ -+int stpmic1_bo_pull_down_unpg(struct stpmic1_bo_cfg *cfg) -+{ -+ return stpmic1_register_update(cfg->pd_reg, cfg->pd_value, -+ cfg->pd_mask); -+} -+ -+int stpmic1_bo_mask_reset_cfg(const char *name, struct stpmic1_bo_cfg *cfg) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ cfg->mrst_reg = regul->mask_reset_reg; -+ cfg->mrst_value = BIT(regul->mask_reset); -+ cfg->mrst_mask = LDO_BUCK_RESET_MASK << regul->mask_reset; -+ -+ return 0; -+} -+ -+int stpmic1_bo_mask_reset_unpg(struct stpmic1_bo_cfg *cfg) -+{ -+ return stpmic1_register_update(cfg->mrst_reg, cfg->mrst_value, -+ cfg->mrst_mask); -+} -+ -+int stpmic1_regulator_voltage_get(const char *name) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ uint8_t value; -+ uint8_t mask; -+ -+ /* Voltage can be set for buck or ldo (except ldo4) regulators */ -+ if (strncmp(name, "buck", 4) == 0) { -+ mask = BUCK_VOLTAGE_MASK; -+ } else if ((strncmp(name, "ldo", 3) == 0) && -+ (strncmp(name, "ldo4", 4) != 0)) { -+ mask = LDO_VOLTAGE_MASK; -+ } else { -+ return 0; -+ } -+ -+ if (stpmic1_register_read(regul->control_reg, &value)) -+ return -1; -+ -+ value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; -+ -+ if (value > regul->voltage_table_size) -+ return -1; -+ -+ return (int)regul->voltage_table[value]; -+} -+ -+int stpmic1_lp_copy_reg(const char *name) -+{ -+ uint8_t val; -+ int status; -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ 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_cfg(const char *name, struct stpmic1_lp_cfg *cfg) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ cfg->ctrl_reg = regul->control_reg; -+ cfg->lp_reg = regul->low_power_reg; -+ -+ return 0; -+} -+ -+int stpmic1_lp_load_unpg(struct stpmic1_lp_cfg *cfg) -+{ -+ uint8_t val; -+ int status; -+ -+ status = stpmic1_register_read(cfg->ctrl_reg, &val); -+ if (status == 0) { -+ status = stpmic1_register_write(cfg->lp_reg, val); -+ } -+ return status; -+} -+ -+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_on_off_unpg(struct stpmic1_lp_cfg *cfg, int enable) -+{ -+ assert(enable == 0 || enable == 1); -+ return stpmic1_register_update(cfg->lp_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_mode_unpg(struct stpmic1_lp_cfg *cfg, unsigned int mode) -+{ -+ assert(mode == 0 || mode == 1); -+ return stpmic1_register_update(cfg->lp_reg, -+ mode << 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); -+} -+ -+/* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ -+int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, -+ struct stpmic1_lp_cfg *cfg) -+ -+{ -+ 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 1; -+ } -+ -+ assert(cfg->lp_reg == regul->low_power_reg); -+ cfg->value = voltage_index << 2; -+ cfg->mask = mask; -+ -+ return 0; -+} -+ -+int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg) -+{ -+ return stpmic1_register_update(cfg->lp_reg, cfg->value, cfg->mask); -+} -+ -+int stpmic1_register_read(uint8_t register_id, uint8_t *value) -+{ -+ struct i2c_handle_s *i2c = pmic_i2c_handle; -+ -+ return stm32_i2c_read_write_membyte(i2c, pmic_i2c_addr, -+ register_id, value, false); -+} -+ -+int stpmic1_register_write(uint8_t register_id, uint8_t value) -+{ -+ int status; -+ struct i2c_handle_s *i2c = pmic_i2c_handle; -+ -+ status = stm32_i2c_read_write_membyte(i2c, pmic_i2c_addr, -+ register_id, &value, true); -+ -+#ifdef CFG_TEE_CORE_DEBUG -+ if (status != 0) { -+ return status; -+ } -+ -+ if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { -+ uint8_t readval; -+ -+ status = stpmic1_register_read(register_id, &readval); -+ if (status != 0) { -+ return status; -+ } -+ -+ if (readval != value) { -+ return -1; -+ } -+ } -+#endif -+ -+ return status; -+} -+ -+int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) -+{ -+ int status; -+ uint8_t val; -+ -+ status = stpmic1_register_read(register_id, &val); -+ if (status != 0) { -+ return status; -+ } -+ -+ val = (val & ~mask) | (value & mask); -+ -+ return stpmic1_register_write(register_id, val); -+} -+ -+void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) -+{ -+ pmic_i2c_handle = i2c_handle; -+ pmic_i2c_addr = i2c_addr; -+} -+ -+void stpmic1_dump_regulators(void) -+{ -+ size_t i; -+ char __maybe_unused const *name; -+ -+ for (i = 0 ; i < MAX_REGUL ; i++) { -+ name = regulators_table[i].dt_node_name; -+ -+ DMSG("PMIC regul %s: %sable, %dmV", -+ name, -+ stpmic1_is_regulator_enabled(name) ? "en" : "dis", -+ stpmic1_regulator_voltage_get(name)); -+ } -+} -+ -+int stpmic1_get_version(unsigned long *version) -+{ -+ int rc; -+ uint8_t read_val; -+ -+ rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val); -+ if (rc) { -+ return -1; -+ } -+ -+ *version = (unsigned long)read_val; -+ -+ return 0; -+} -diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk -index b2bcf15..41f01fa 100644 ---- a/core/drivers/sub.mk -+++ b/core/drivers/sub.mk -@@ -19,4 +19,13 @@ srcs-$(CFG_DRA7_RNG) += dra7_rng.c - srcs-$(CFG_STIH_UART) += stih_asc.c - srcs-$(CFG_ATMEL_UART) += atmel_uart.c - srcs-$(CFG_MVEBU_UART) += mvebu_uart.c -+srcs-$(CFG_STM32_BSEC) += stm32_bsec.c -+srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c -+srcs-$(CFG_STM32_GPIO) += stm32_gpio.c -+srcs-$(CFG_STM32_I2C) += stm32_i2c.c -+srcs-$(CFG_STM32_IWDG) += stm32_iwdg.c -+srcs-$(CFG_STM32_RNG) += stm32_rng.c -+srcs-$(CFG_STM32_RTC) += stm32_rtc.c -+srcs-$(CFG_STM32_TIMER) += stm32_timer.c - srcs-$(CFG_STM32_UART) += stm32_uart.c -+srcs-$(CFG_STPMIC1) += stpmic1.c -diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h -index a4f60b7..df1e9af 100644 ---- a/core/include/drivers/gic.h -+++ b/core/include/drivers/gic.h -@@ -9,14 +9,39 @@ - #include - #include - -+/* Constants to categorize priorities */ -+#define GIC_HIGHEST_SEC_PRIORITY 0x0U -+#define GIC_LOWEST_SEC_PRIORITY 0x7fU -+#define GIC_HIGHEST_NS_PRIORITY 0x80U -+#define GIC_LOWEST_NS_PRIORITY 0xfeU -+/* 0xff would disable all interrupts */ -+ - #define GIC_DIST_REG_SIZE 0x10000 - #define GIC_CPU_REG_SIZE 0x10000 - -+#if !defined(CFG_WITH_ARM_TRUSTED_FW) && defined(CFG_ARM_GICV3) -+#error CFG_ARM_GICV3 is not supported without CFG_WITH_ARM_TRUSTED_FW -+#endif -+ -+struct gic_it_pm; -+ -+/* -+ * Save and restore some interrupts configuration during low power sequences. -+ * This is used on platforms using OP-TEE secure monitor. -+ */ -+struct gic_pm { -+ struct gic_it_pm *pm_cfg; -+ size_t count; -+}; -+ - struct gic_data { - vaddr_t gicc_base; - vaddr_t gicd_base; - size_t max_it; - struct itr_chip chip; -+#if !defined(CFG_WITH_ARM_TRUSTED_FW) -+ struct gic_pm pm; -+#endif - }; - - /* -@@ -34,4 +59,8 @@ void gic_cpu_init(struct gic_data *gd); - void gic_it_handle(struct gic_data *gd); - - void gic_dump_state(struct gic_data *gd); -+ -+void gic_suspend(struct gic_data *gd); -+void gic_resume(struct gic_data *gd); -+ - #endif /*__DRIVERS_GIC_H*/ -diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h -new file mode 100644 -index 0000000..de4d20b ---- /dev/null -+++ b/core/include/drivers/stm32_bsec.h -@@ -0,0 +1,143 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2015-2018, STMicroelectronics -+ */ -+ -+#ifndef __STM32_BSEC_H__ -+#define __STM32_BSEC_H__ -+ -+#include -+#include -+ -+#define BSEC_OTP_MASK GENMASK_32(4, 0) -+#define BSEC_OTP_BANK_SHIFT 5 -+ -+#define BSEC_TIMEOUT_VALUE 0xFFFF -+ -+#define ADDR_LOWER_OTP_PERLOCK_SHIFT 3 -+#define DATA_LOWER_OTP_PERLOCK_BIT 3 -+#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK_32(2, 0) -+#define ADDR_UPPER_OTP_PERLOCK_SHIFT 4 -+#define DATA_UPPER_OTP_PERLOCK_BIT 1 -+#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK_32(3, 0) -+ -+/* Return status */ -+#define BSEC_OK 0U -+#define BSEC_ERROR 0xFFFFFFFFU -+#define BSEC_DISTURBED 0xFFFFFFFEU -+#define BSEC_FEATURE_LOCK 0xFFFFFFFDU -+#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_FEN_OFF 0x018U -+#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 -+#define BSEC_WRLOCK1_OFF 0x050U -+#define BSEC_WRLOCK2_OFF 0x054U -+#define BSEC_SPLOCK_OFF 0x064U -+#define BSEC_SPLOCK1_OFF 0x068U -+#define BSEC_SPLOCK2_OFF 0x06CU -+#define BSEC_SWLOCK_OFF 0x07CU -+#define BSEC_SWLOCK1_OFF 0x080U -+#define BSEC_SWLOCK2_OFF 0x084U -+#define BSEC_SRLOCK_OFF 0x094U -+#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_32(2, 1) -+#define BSEC_CONF_FRQ_SHIFT 1 -+#define BSEC_CONF_PRG_WIDTH_MASK GENMASK_32(6, 3) -+#define BSEC_CONF_PRG_WIDTH_SHIFT 3 -+#define BSEC_CONF_TREAD_MASK GENMASK_32(8, 7) -+#define BSEC_CONF_TREAD_SHIFT 7 -+ -+/* BSEC_CONTROL Register */ -+#define BSEC_READ 0x000U -+#define BSEC_WRITE 0x100U -+#define BSEC_LOCK 0x200U -+ -+/* STATUS Register */ -+#define BSEC_MODE_STATUS_MASK GENMASK_32(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) -+ -+/* Debug */ -+#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_32(10, 0) -+ -+/* -+ * OTP Lock services definition -+ * Value must corresponding to the bit number in the register -+ */ -+#define BSEC_LOCK_UPPER_OTP 0x00 -+#define BSEC_LOCK_DEBUG 0x02 -+#define BSEC_LOCK_PROGRAM 0x03 -+ -+/* Values for struct bsec_config::freq */ -+#define FREQ_10_20_MHZ 0x0 -+#define FREQ_20_30_MHZ 0x1 -+#define FREQ_30_45_MHZ 0x2 -+#define FREQ_45_67_MHZ 0x3 -+ -+uint32_t bsec_shadow_register(uint32_t otp); -+uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); -+uint32_t bsec_write_otp(uint32_t val, uint32_t otp); -+uint32_t bsec_program_otp(uint32_t val, uint32_t otp); -+uint32_t bsec_permanent_lock_otp(uint32_t otp); -+ -+uint32_t bsec_write_debug_conf(uint32_t val); -+uint32_t bsec_read_debug_conf(void); -+ -+uint32_t bsec_get_status(void); -+uint32_t bsec_get_hw_conf(void); -+uint32_t bsec_get_version(void); -+uint32_t bsec_get_id(void); -+uint32_t bsec_get_magic_id(void); -+ -+bool bsec_write_sr_lock(uint32_t otp, uint32_t value); -+bool bsec_read_sr_lock(uint32_t otp); -+bool bsec_write_sw_lock(uint32_t otp, uint32_t value); -+bool bsec_read_sw_lock(uint32_t otp); -+bool bsec_write_sp_lock(uint32_t otp, uint32_t value); -+bool bsec_read_sp_lock(uint32_t otp); -+bool bsec_wr_lock(uint32_t otp); -+uint32_t bsec_otp_lock(uint32_t service, uint32_t value); -+ -+bool bsec_mode_is_closed_device(void); -+uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word); -+uint32_t bsec_check_nsec_access_rights(uint32_t otp); -+ -+#endif /*__STM32_BSEC_H__*/ -diff --git a/core/include/drivers/stm32_etzpc.h b/core/include/drivers/stm32_etzpc.h -new file mode 100644 -index 0000000..bd34955 ---- /dev/null -+++ b/core/include/drivers/stm32_etzpc.h -@@ -0,0 +1,75 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. -+ * Copyright (c) 2017-2018, STMicroelectronics -+ */ -+ -+#ifndef __STM32_ETZPC_H__ -+#define __STM32_ETZPC_H__ -+ -+#include -+#include -+ -+#define ETZPC_V1_0 0x10 -+#define ETZPC_V2_0 0x20 -+ -+/* -+ * Define security level for each peripheral (DECPROT) -+ */ -+enum etzpc_decprot_attributes { -+ TZPC_DECPROT_S_RW = 0, -+ TZPC_DECPROT_NS_R_S_W = 1, -+ TZPC_DECPROT_MCU_ISOLATION = 2, -+ TZPC_DECPROT_NS_RW = 3, -+ TZPC_DECPROT_MAX = 4, -+}; -+ -+/* -+ * etzpc_configure_decprot : Load a DECPROT configuration -+ * decprot_id : ID of the IP -+ * decprot_attr : Restriction access attributes -+ */ -+void etzpc_configure_decprot(uint32_t decprot_id, -+ enum etzpc_decprot_attributes decprot_attr); -+ -+/* -+ * etzpc_get_decprot : Get the DECPROT attribute -+ * decprot_id : ID of the IP -+ * return : Attribute of this DECPROT -+ */ -+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id); -+ -+/* -+ * etzpc_lock_decprot : Lock access to the DECPROT attributes -+ * decprot_id : ID of the IP -+ */ -+void etzpc_lock_decprot(uint32_t decprot_id); -+ -+/* -+ * etzpc_configure_tzma : Configure the target TZMA read only size -+ * tzma_id : ID of the memory -+ * tzma_value : read-only size -+ */ -+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value); -+ -+/* -+ * etzpc_get_tzma : Get the target TZMA read only size -+ * tzma_id : TZMA ID -+ * return : Size of read only size -+ */ -+uint16_t etzpc_get_tzma(uint32_t tzma_id); -+ -+/* -+ * etzpc_lock_tzma : Lock the target TZMA -+ * tzma_id : TZMA ID -+ */ -+void etzpc_lock_tzma(uint32_t tzma_id); -+ -+/* -+ * etzpc_get_lock_tzma : Return the lock status of the target TZMA -+ * tzma_id : TZMA ID -+ * return : True if TZMA is locked, false otherwise -+ */ -+bool etzpc_get_lock_tzma(uint32_t tzma_id); -+ -+#endif /*__STM32_ETZPC_H__*/ -diff --git a/core/include/drivers/stm32_gpio.h b/core/include/drivers/stm32_gpio.h -new file mode 100644 -index 0000000..67de10f ---- /dev/null -+++ b/core/include/drivers/stm32_gpio.h -@@ -0,0 +1,107 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32_GPIO_H__ -+#define __STM32_GPIO_H__ -+ -+#include -+#include -+#include -+ -+#define GPIO_MODE_OFFSET 0x00U -+#define GPIO_TYPE_OFFSET 0x04U -+#define GPIO_SPEED_OFFSET 0x08U -+#define GPIO_PUPD_OFFSET 0x0CU -+#define GPIO_ODR_OFFSET 0x14U -+#define GPIO_BSRR_OFFSET 0x18U -+#define GPIO_AFRL_OFFSET 0x20U -+#define GPIO_AFRH_OFFSET 0x24U -+#define GPIO_SECR_OFFSET 0x30U -+ -+#define GPIO_ALT_LOWER_LIMIT 0x08U -+ -+#define GPIO_PIN_0 0x00U -+#define GPIO_PIN_1 0x01U -+#define GPIO_PIN_2 0x02U -+#define GPIO_PIN_3 0x03U -+#define GPIO_PIN_4 0x04U -+#define GPIO_PIN_5 0x05U -+#define GPIO_PIN_6 0x06U -+#define GPIO_PIN_7 0x07U -+#define GPIO_PIN_8 0x08U -+#define GPIO_PIN_9 0x09U -+#define GPIO_PIN_10 0x0AU -+#define GPIO_PIN_11 0x0BU -+#define GPIO_PIN_12 0x0CU -+#define GPIO_PIN_13 0x0DU -+#define GPIO_PIN_14 0x0EU -+#define GPIO_PIN_15 0x0FU -+#define GPIO_PIN_MAX GPIO_PIN_15 -+ -+#define GPIO_ALTERNATE_0 0x00 -+#define GPIO_ALTERNATE_1 0x01 -+#define GPIO_ALTERNATE_2 0x02 -+#define GPIO_ALTERNATE_3 0x03 -+#define GPIO_ALTERNATE_4 0x04 -+#define GPIO_ALTERNATE_5 0x05 -+#define GPIO_ALTERNATE_6 0x06 -+#define GPIO_ALTERNATE_7 0x07 -+#define GPIO_ALTERNATE_8 0x08 -+#define GPIO_ALTERNATE_9 0x09 -+#define GPIO_ALTERNATE_10 0x0A -+#define GPIO_ALTERNATE_11 0x0B -+#define GPIO_ALTERNATE_12 0x0C -+#define GPIO_ALTERNATE_13 0x0D -+#define GPIO_ALTERNATE_14 0x0E -+#define GPIO_ALTERNATE_15 0x0F -+#define GPIO_ALTERNATE_MAX 0x0FU -+ -+#define GPIO_MODE_INPUT 0x00 -+#define GPIO_MODE_OUTPUT 0x01 -+#define GPIO_MODE_ALTERNATE 0x02 -+#define GPIO_MODE_ANALOG 0x03 -+#define GPIO_MODE_MAX 0x03U -+ -+#define GPIO_OPEN_DRAIN 0x10U -+ -+#define GPIO_SPEED_LOW 0x00 -+#define GPIO_SPEED_MEDIUM 0x01 -+#define GPIO_SPEED_HIGH 0x02 -+#define GPIO_SPEED_VERY_HIGH 0x03 -+#define GPIO_SPEED_MAX 0x03U -+ -+#define GPIO_NO_PULL 0x00 -+#define GPIO_PULL_UP 0x01 -+#define GPIO_PULL_DOWN 0x02 -+#define GPIO_PULL_MAX 0x03U -+ -+struct gpio_cfg { -+ uint16_t moder: 2; -+ uint16_t otyper: 1; -+ uint16_t ospeedr: 2; -+ uint16_t pupdr: 2; -+ uint16_t odr: 1; -+ uint16_t afr: 4; -+}; -+ -+struct stm32_pinctrl { -+ uint8_t bank; -+ uint8_t pin; -+ struct gpio_cfg active_cfg; -+ struct gpio_cfg standby_cfg; -+}; -+ -+void stm32_pinctrl_load_active_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); -+void stm32_pinctrl_load_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); -+void stm32_pinctrl_store_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); -+ -+int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int node, -+ struct stm32_pinctrl *cfg, size_t count); -+ -+void stm32_gpio_set_output_level(uint32_t bank, uint32_t pin, int high); -+ -+void stm32_gpio_set_secure_cfg(uint32_t bank, uint32_t pin, bool secure); -+ -+#endif /*__STM32_GPIO_H__*/ -diff --git a/core/include/drivers/stm32_i2c.h b/core/include/drivers/stm32_i2c.h -new file mode 100644 -index 0000000..3c6e326 ---- /dev/null -+++ b/core/include/drivers/stm32_i2c.h -@@ -0,0 +1,377 @@ -+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32_I2C_H -+#define __STM32_I2C_H -+ -+#include -+#include -+#include -+#include -+ -+/* -+ * When STM32_I2C_MAYBE_NON_SECURE is defined, the I2C bus maybe -+ * non secure and yet used by the secure world. In such case, -+ * secure world may use the I2C only in atomic conditions -+ * where the non secure world cannot be executed. -+ */ -+#define STM32_I2C_MAYBE_NON_SECURE -+ -+/* Bit definition for I2C_CR1 register */ -+#define I2C_CR1_PE BIT(0) -+#define I2C_CR1_TXIE BIT(1) -+#define I2C_CR1_RXIE BIT(2) -+#define I2C_CR1_ADDRIE BIT(3) -+#define I2C_CR1_NACKIE BIT(4) -+#define I2C_CR1_STOPIE BIT(5) -+#define I2C_CR1_TCIE BIT(6) -+#define I2C_CR1_ERRIE BIT(7) -+#define I2C_CR1_DNF GENMASK_32(11, 8) -+#define I2C_CR1_ANFOFF BIT(12) -+#define I2C_CR1_SWRST BIT(13) -+#define I2C_CR1_TXDMAEN BIT(14) -+#define I2C_CR1_RXDMAEN BIT(15) -+#define I2C_CR1_SBC BIT(16) -+#define I2C_CR1_NOSTRETCH BIT(17) -+#define I2C_CR1_WUPEN BIT(18) -+#define I2C_CR1_GCEN BIT(19) -+#define I2C_CR1_SMBHEN BIT(22) -+#define I2C_CR1_SMBDEN BIT(21) -+#define I2C_CR1_ALERTEN BIT(22) -+#define I2C_CR1_PECEN BIT(23) -+ -+/* Bit definition for I2C_CR2 register */ -+#define I2C_CR2_SADD GENMASK_32(9, 0) -+#define I2C_CR2_RD_WRN BIT(10) -+#define I2C_CR2_RD_WRN_OFFSET 10U -+#define I2C_CR2_ADD10 BIT(11) -+#define I2C_CR2_HEAD10R BIT(12) -+#define I2C_CR2_START BIT(13) -+#define I2C_CR2_STOP BIT(14) -+#define I2C_CR2_NACK BIT(15) -+#define I2C_CR2_NBYTES GENMASK_32(23, 16) -+#define I2C_CR2_NBYTES_OFFSET 16U -+#define I2C_CR2_RELOAD BIT(24) -+#define I2C_CR2_AUTOEND BIT(25) -+#define I2C_CR2_PECBYTE BIT(26) -+ -+/* Bit definition for I2C_OAR1 register */ -+#define I2C_OAR1_OA1 GENMASK_32(9, 0) -+#define I2C_OAR1_OA1MODE BIT(10) -+#define I2C_OAR1_OA1EN BIT(15) -+ -+/* Bit definition for I2C_OAR2 register */ -+#define I2C_OAR2_OA2 GENMASK_32(7, 1) -+#define I2C_OAR2_OA2MSK GENMASK_32(10, 8) -+#define I2C_OAR2_OA2NOMASK 0 -+#define I2C_OAR2_OA2MASK01 BIT(8) -+#define I2C_OAR2_OA2MASK02 BIT(9) -+#define I2C_OAR2_OA2MASK03 GENMASK_32(9, 8) -+#define I2C_OAR2_OA2MASK04 BIT(10) -+#define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10)) -+#define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10)) -+#define I2C_OAR2_OA2MASK07 GENMASK_32(10, 8) -+#define I2C_OAR2_OA2EN BIT(15) -+ -+/* Bit definition for I2C_TIMINGR register */ -+#define I2C_TIMINGR_SCLL GENMASK_32(7, 0) -+#define I2C_TIMINGR_SCLH GENMASK_32(15, 8) -+#define I2C_TIMINGR_SDADEL GENMASK_32(19, 16) -+#define I2C_TIMINGR_SCLDEL GENMASK_32(23, 20) -+#define I2C_TIMINGR_PRESC GENMASK_32(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_32(11, 0) -+#define I2C_TIMEOUTR_TIDLE BIT(12) -+#define I2C_TIMEOUTR_TIMOUTEN BIT(15) -+#define I2C_TIMEOUTR_TIMEOUTB GENMASK_32(27, 16) -+#define I2C_TIMEOUTR_TEXTEN BIT(31) -+ -+/* Bit definition for I2C_ISR register */ -+#define I2C_ISR_TXE BIT(0) -+#define I2C_ISR_TXIS BIT(1) -+#define I2C_ISR_RXNE BIT(2) -+#define I2C_ISR_ADDR BIT(3) -+#define I2C_ISR_NACKF BIT(4) -+#define I2C_ISR_STOPF BIT(5) -+#define I2C_ISR_TC BIT(6) -+#define I2C_ISR_TCR BIT(7) -+#define I2C_ISR_BERR BIT(8) -+#define I2C_ISR_ARLO BIT(9) -+#define I2C_ISR_OVR BIT(10) -+#define I2C_ISR_PECERR BIT(11) -+#define I2C_ISR_TIMEOUT BIT(12) -+#define I2C_ISR_ALERT BIT(13) -+#define I2C_ISR_BUSY BIT(15) -+#define I2C_ISR_DIR BIT(16) -+#define I2C_ISR_ADDCODE GENMASK_32(23, 17) -+ -+/* Bit definition for I2C_ICR register */ -+#define I2C_ICR_ADDRCF BIT(3) -+#define I2C_ICR_NACKCF BIT(4) -+#define I2C_ICR_STOPCF BIT(5) -+#define I2C_ICR_BERRCF BIT(8) -+#define I2C_ICR_ARLOCF BIT(9) -+#define I2C_ICR_OVRCF BIT(10) -+#define I2C_ICR_PECCF BIT(11) -+#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 -+ -+struct stm32_i2c_init_s { -+ uint32_t own_address1; /* -+ * Specifies the first device own -+ * address. This parameter can be a -+ * 7-bit or 10-bit address. -+ */ -+ -+ uint32_t addressing_mode; /* -+ * Specifies if 7-bit or 10-bit -+ * addressing mode is selected. -+ * This parameter can be a value of -+ * @ref I2C_ADDRESSING_MODE. -+ */ -+ -+ uint32_t dual_address_mode; /* -+ * Specifies if dual addressing mode is -+ * selected. -+ * This parameter can be a value of @ref -+ * I2C_DUAL_ADDRESSING_MODE. -+ */ -+ -+ uint32_t own_address2; /* -+ * Specifies the second device own -+ * address if dual addressing mode is -+ * selected. This parameter can be a -+ * 7-bit address. -+ */ -+ -+ uint32_t own_address2_masks; /* -+ * Specifies the acknowledge mask -+ * address second device own address -+ * if dual addressing mode is selected -+ * This parameter can be a value of @ref -+ * I2C_OWN_ADDRESS2_MASKS. -+ */ -+ -+ uint32_t general_call_mode; /* -+ * Specifies if general call mode is -+ * selected. -+ * This parameter can be a value of @ref -+ * I2C_GENERAL_CALL_ADDRESSING_MODE. -+ */ -+ -+ uint32_t no_stretch_mode; /* -+ * Specifies if nostretch mode is -+ * selected. -+ * This parameter can be a value of @ref -+ * I2C_NOSTRETCH_MODE. -+ */ -+ -+ uint32_t rise_time; /* -+ * Specifies the SCL clock pin rising -+ * time in nanoseconds. -+ */ -+ -+ uint32_t fall_time; /* -+ * Specifies the SCL clock pin falling -+ * time in nanoseconds. -+ */ -+ -+ enum i2c_speed_e speed_mode; /* -+ * Specifies the I2C clock source -+ * frequency mode. -+ * This parameter can be a value of @ref -+ * i2c_speed_mode_e. -+ */ -+ -+ int analog_filter; /* -+ * Specifies if the I2C analog noise -+ * filter is selected. -+ * This parameter can be 0 (filter -+ * off), all other values mean filter -+ * on. -+ */ -+ -+ uint8_t digital_filter_coef; /* -+ * Specifies the I2C digital noise -+ * filter coefficient. -+ * This parameter can be a value -+ * between 0 and -+ * STM32_I2C_DIGITAL_FILTER_MAX. -+ */ -+}; -+ -+enum i2c_state_e { -+ I2C_STATE_RESET = 0x00U, /* Not yet initialized */ -+ I2C_STATE_READY = 0x20U, /* Ready for use */ -+ I2C_STATE_BUSY = 0x24U, /* Internal process ongoing */ -+ I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission ongoing */ -+ I2C_STATE_BUSY_RX = 0x22U, /* Data Reception ongoing */ -+ I2C_STATE_SUSPENDED = 0xF0U, /* Bus is supended */ -+}; -+ -+enum i2c_mode_e { -+ I2C_MODE_NONE = 0x00U, /* No active communication */ -+ I2C_MODE_MASTER = 0x10U, /* Communication in Master Mode */ -+ I2C_MODE_SLAVE = 0x20U, /* Communication in Slave Mode */ -+ I2C_MODE_MEM = 0x40U /* Communication in Memory Mode */ -+ -+}; -+ -+#define I2C_ERROR_NONE 0x00000000U /* No error */ -+#define I2C_ERROR_BERR 0x00000001U /* BERR error */ -+#define I2C_ERROR_ARLO 0x00000002U /* ARLO error */ -+#define I2C_ERROR_AF 0x00000004U /* ACKF error */ -+#define I2C_ERROR_OVR 0x00000008U /* OVR error */ -+#define I2C_ERROR_DMA 0x00000010U /* DMA transfer error */ -+#define I2C_ERROR_TIMEOUT 0x00000020U /* Timeout error */ -+#define I2C_ERROR_SIZE 0x00000040U /* Size Management error */ -+ -+#ifdef STM32_I2C_MAYBE_NON_SECURE -+struct i2c_cfg { -+ uint32_t timingr; -+ uint32_t oar1; -+ uint32_t oar2; -+ uint32_t cr1; -+ uint32_t cr2; -+}; -+#endif -+ -+struct i2c_handle_s { -+ uintptr_t pbase; /* Registers phys base address */ -+ uintptr_t vbase; /* Registers virt base address */ -+ unsigned int dt_status; /* DT nsec/sec status */ -+ unsigned int clock; /* Clock reference */ -+ uint8_t lock; /* Locking object (FIXME: really usefull?) */ -+ enum i2c_state_e i2c_state; /* Communication state */ -+ enum i2c_mode_e i2c_mode; /* Communication mode */ -+ uint32_t i2c_err; /* Error code */ -+ struct stm32_pinctrl *pinctrl; /* PINCTRLs configuration for the I2C PINs */ -+ size_t pinctrl_count; /* Number of PINCTRLs elements */ -+ struct i2c_cfg sec_cfg; /* Context for secure usage */ -+#ifdef STM32_I2C_MAYBE_NON_SECURE -+ struct i2c_cfg alt_cfg; /* Alternate usage context */ -+#endif -+}; -+ -+#define I2C_ADDRESSINGMODE_7BIT 0x00000001U -+#define I2C_ADDRESSINGMODE_10BIT 0x00000002U -+ -+#define I2C_DUALADDRESS_DISABLE 0x00000000U -+#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN -+ -+#define I2C_GENERALCALL_DISABLE 0x00000000U -+#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN -+ -+#define I2C_NOSTRETCH_DISABLE 0x00000000U -+#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH -+ -+#define I2C_MEMADD_SIZE_8BIT 0x00000001U -+#define I2C_MEMADD_SIZE_16BIT 0x00000002U -+ -+#define I2C_RELOAD_MODE I2C_CR2_RELOAD -+#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND -+#define I2C_SOFTEND_MODE 0x00000000U -+ -+#define I2C_NO_STARTSTOP 0x00000000U -+#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) -+#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ -+ I2C_CR2_RD_WRN) -+#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) -+ -+#define I2C_FLAG_TXE I2C_ISR_TXE -+#define I2C_FLAG_TXIS I2C_ISR_TXIS -+#define I2C_FLAG_RXNE I2C_ISR_RXNE -+#define I2C_FLAG_ADDR I2C_ISR_ADDR -+#define I2C_FLAG_AF I2C_ISR_NACKF -+#define I2C_FLAG_STOPF I2C_ISR_STOPF -+#define I2C_FLAG_TC I2C_ISR_TC -+#define I2C_FLAG_TCR I2C_ISR_TCR -+#define I2C_FLAG_BERR I2C_ISR_BERR -+#define I2C_FLAG_ARLO I2C_ISR_ARLO -+#define I2C_FLAG_OVR I2C_ISR_OVR -+#define I2C_FLAG_PECERR I2C_ISR_PECERR -+#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT -+#define I2C_FLAG_ALERT I2C_ISR_ALERT -+#define I2C_FLAG_BUSY I2C_ISR_BUSY -+#define I2C_FLAG_DIR I2C_ISR_DIR -+ -+#define I2C_RESET_CR2 (I2C_CR2_SADD | I2C_CR2_HEAD10R | \ -+ I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ -+ I2C_CR2_RD_WRN) -+ -+#define I2C_TIMEOUT_BUSY_MS 25U -+ -+#define I2C_ANALOGFILTER_ENABLE 0x00000000U -+#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF -+ -+/* STM32 specific defines */ -+#define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */ -+#define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */ -+#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD -+#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ -+#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ -+#define STM32_I2C_DIGITAL_FILTER_MAX 16 -+ -+int stm32_i2c_get_setup_from_fdt(void *fdt, int node, -+ struct stm32_i2c_init_s *init, -+ struct stm32_pinctrl **pinctrl, -+ size_t *pinctrl_count); -+ -+int stm32_i2c_init(struct i2c_handle_s *hi2c, -+ struct stm32_i2c_init_s *init_data); -+ -+int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms); -+ -+int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint16_t mem_addr, uint16_t mem_add_size, -+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms); -+ -+int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms); -+ -+int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint8_t *p_data, uint16_t size, -+ uint32_t timeout_ms); -+ -+bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ uint32_t trials, uint32_t timeout_ms); -+ -+int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr, -+ unsigned int mem_addr, uint8_t *p_data, -+ bool write); -+ -+void stm32_i2c_suspend(struct i2c_handle_s *hi2c); -+void stm32_i2c_resume(struct i2c_handle_s *hi2c); -+ -+#endif /* __STM32_I2C_H */ -diff --git a/core/include/drivers/stm32_iwdg.h b/core/include/drivers/stm32_iwdg.h -new file mode 100644 -index 0000000..b649dee ---- /dev/null -+++ b/core/include/drivers/stm32_iwdg.h -@@ -0,0 +1,17 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32_IWDG_H__ -+#define __STM32_IWDG_H__ -+ -+#include -+ -+#define IWDG_HW_ENABLED BIT(0) -+#define IWDG_ENABLE_ON_STOP BIT(1) -+#define IWDG_ENABLE_ON_STANDBY BIT(2) -+ -+void stm32_iwdg_refresh(uint32_t instance); -+ -+#endif /*__STM32_IWDG_H__*/ -diff --git a/core/include/drivers/stm32_rng.h b/core/include/drivers/stm32_rng.h -new file mode 100644 -index 0000000..1ba098f ---- /dev/null -+++ b/core/include/drivers/stm32_rng.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STM32_RNG_H__ -+#define __STM32_RNG_H__ -+ -+#include -+#include -+ -+int stm32_rng_read(uint8_t *out, size_t size); -+ -+#endif /*__STM32_RNG__*/ -diff --git a/core/include/drivers/stm32_rtc.h b/core/include/drivers/stm32_rtc.h -new file mode 100644 -index 0000000..39a262c ---- /dev/null -+++ b/core/include/drivers/stm32_rtc.h -@@ -0,0 +1,73 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. -+ */ -+ -+#ifndef __PLAT_RTC_H__ -+#define __PLAT_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); -+ -+#endif /* __PLAT_RTC_H__ */ -diff --git a/core/include/drivers/stm32_timer.h b/core/include/drivers/stm32_timer.h -new file mode 100644 -index 0000000..b7e6751 ---- /dev/null -+++ b/core/include/drivers/stm32_timer.h -@@ -0,0 +1,25 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#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); -+ -+/* -+ * 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); -+ -+#endif /* STM32_TIMER_H */ -diff --git a/core/include/drivers/stm32_uart.h b/core/include/drivers/stm32_uart.h -index 58c7077..6ddb8c4 100644 ---- a/core/include/drivers/stm32_uart.h -+++ b/core/include/drivers/stm32_uart.h -@@ -7,12 +7,18 @@ - #define __STM32_UART_H__ - - #include -+#include - --struct console_pdata { -+struct stm32_uart_pdata { - struct io_pa_va base; - struct serial_chip chip; -+ bool secure; -+ struct stm32_pinctrl *pinctrl; -+ size_t pinctrl_count; -+ unsigned long clock; - }; - --void stm32_uart_init(struct console_pdata *pd, vaddr_t base); -+void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base); -+struct stm32_uart_pdata *probe_uart_from_dt_node(void *fdt, int node); - - #endif /*__STM32_UART_H__*/ -diff --git a/core/include/drivers/stpmic1.h b/core/include/drivers/stpmic1.h -new file mode 100644 -index 0000000..3073662 ---- /dev/null -+++ b/core/include/drivers/stpmic1.h -@@ -0,0 +1,228 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef __STPMIC1_H__ -+#define __STPMIC1_H__ -+ -+#include -+#include -+ -+#define TURN_ON_REG 0x1U -+#define TURN_OFF_REG 0x2U -+#define ICC_LDO_TURN_OFF_REG 0x3U -+#define ICC_BUCK_TURN_OFF_REG 0x4U -+#define RESET_STATUS_REG 0x5U -+#define VERSION_STATUS_REG 0x6U -+#define MAIN_CONTROL_REG 0x10U -+#define PADS_PULL_REG 0x11U -+#define BUCK_PULL_DOWN_REG 0x12U -+#define LDO14_PULL_DOWN_REG 0x13U -+#define LDO56_PULL_DOWN_REG 0x14U -+#define VIN_CONTROL_REG 0x15U -+#define PONKEY_TIMER_REG 0x16U -+#define MASK_RANK_BUCK_REG 0x17U -+#define MASK_RESET_BUCK_REG 0x18U -+#define MASK_RANK_LDO_REG 0x19U -+#define MASK_RESET_LDO_REG 0x1AU -+#define WATCHDOG_CONTROL_REG 0x1BU -+#define WATCHDOG_TIMER_REG 0x1CU -+#define BUCK_ICC_TURNOFF_REG 0x1DU -+#define LDO_ICC_TURNOFF_REG 0x1EU -+#define BUCK_APM_CONTROL_REG 0x1FU -+#define BUCK1_CONTROL_REG 0x20U -+#define BUCK2_CONTROL_REG 0x21U -+#define BUCK3_CONTROL_REG 0x22U -+#define BUCK4_CONTROL_REG 0x23U -+#define VREF_DDR_CONTROL_REG 0x24U -+#define LDO1_CONTROL_REG 0x25U -+#define LDO2_CONTROL_REG 0x26U -+#define LDO3_CONTROL_REG 0x27U -+#define LDO4_CONTROL_REG 0x28U -+#define LDO5_CONTROL_REG 0x29U -+#define LDO6_CONTROL_REG 0x2AU -+#define BUCK1_PWRCTRL_REG 0x30U -+#define BUCK2_PWRCTRL_REG 0x31U -+#define BUCK3_PWRCTRL_REG 0x32U -+#define BUCK4_PWRCTRL_REG 0x33U -+#define VREF_DDR_PWRCTRL_REG 0x34U -+#define LDO1_PWRCTRL_REG 0x35U -+#define LDO2_PWRCTRL_REG 0x36U -+#define LDO3_PWRCTRL_REG 0x37U -+#define LDO4_PWRCTRL_REG 0x38U -+#define LDO5_PWRCTRL_REG 0x39U -+#define LDO6_PWRCTRL_REG 0x3AU -+#define FREQUENCY_SPREADING_REG 0x3BU -+#define USB_CONTROL_REG 0x40U -+#define ITLATCH1_REG 0x50U -+#define ITLATCH2_REG 0x51U -+#define ITLATCH3_REG 0x52U -+#define ITLATCH4_REG 0x53U -+#define ITSETLATCH1_REG 0x60U -+#define ITSETLATCH2_REG 0x61U -+#define ITSETLATCH3_REG 0x62U -+#define ITSETLATCH4_REG 0x63U -+#define ITCLEARLATCH1_REG 0x70U -+#define ITCLEARLATCH2_REG 0x71U -+#define ITCLEARLATCH3_REG 0x72U -+#define ITCLEARLATCH4_REG 0x73U -+#define ITMASK1_REG 0x80U -+#define ITMASK2_REG 0x81U -+#define ITMASK3_REG 0x82U -+#define ITMASK4_REG 0x83U -+#define ITSETMASK1_REG 0x90U -+#define ITSETMASK2_REG 0x91U -+#define ITSETMASK3_REG 0x92U -+#define ITSETMASK4_REG 0x93U -+#define ITCLEARMASK1_REG 0xA0U -+#define ITCLEARMASK2_REG 0xA1U -+#define ITCLEARMASK3_REG 0xA2U -+#define ITCLEARMASK4_REG 0xA3U -+#define ITSOURCE1_REG 0xB0U -+#define ITSOURCE2_REG 0xB1U -+#define ITSOURCE3_REG 0xB2U -+#define ITSOURCE4_REG 0xB3U -+ -+/* Registers masks */ -+#define LDO_VOLTAGE_MASK 0x7CU -+#define BUCK_VOLTAGE_MASK 0xFCU -+#define LDO_BUCK_VOLTAGE_SHIFT 2 -+#define LDO_BUCK_ENABLE_MASK 0x01U -+#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U -+#define LDO_BUCK_HPLP_SHIFT 1 -+#define LDO_BUCK_RANK_MASK 0x01U -+#define LDO_BUCK_RESET_MASK 0x01U -+#define LDO_BUCK_PULL_DOWN_MASK 0x03U -+ -+/* Pull down register */ -+#define BUCK1_PULL_DOWN_SHIFT 0 -+#define BUCK2_PULL_DOWN_SHIFT 2 -+#define BUCK3_PULL_DOWN_SHIFT 4 -+#define BUCK4_PULL_DOWN_SHIFT 6 -+#define VREF_DDR_PULL_DOWN_SHIFT 4 -+ -+/* Buck Mask reset register */ -+#define BUCK1_MASK_RESET_SHIFT 0 -+#define BUCK2_MASK_RESET_SHIFT 1 -+#define BUCK3_MASK_RESET_SHIFT 2 -+#define BUCK4_MASK_RESET_SHIFT 3 -+ -+/* LDO Mask reset register */ -+#define LDO1_MASK_RESET_SHIFT 0 -+#define LDO2_MASK_RESET_SHIFT 1 -+#define LDO3_MASK_RESET_SHIFT 2 -+#define LDO4_MASK_RESET_SHIFT 3 -+#define LDO5_MASK_RESET_SHIFT 4 -+#define LDO6_MASK_RESET_SHIFT 5 -+#define VREF_DDR_MASK_RESET_SHIFT 6 -+ -+/* Main PMIC Control Register (MAIN_CONTROL_REG) */ -+#define ICC_EVENT_ENABLED BIT(4) -+#define PWRCTRL_POLARITY_HIGH BIT(3) -+#define PWRCTRL_PIN_VALID BIT(2) -+#define RESTART_REQUEST_ENABLED BIT(1) -+#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) -+ -+/* Main PMIC PADS Control Register (PADS_PULL_REG) */ -+#define WAKEUP_DETECTOR_DISABLED BIT(4) -+#define PWRCTRL_PD_ACTIVE BIT(3) -+#define PWRCTRL_PU_ACTIVE BIT(2) -+#define WAKEUP_PD_ACTIVE BIT(1) -+#define PONKEY_PU_ACTIVE BIT(0) -+ -+/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ -+#define SWIN_DETECTOR_ENABLED BIT(7) -+#define SWOUT_DETECTOR_ENABLED BIT(6) -+#define VINLOW_HYST_MASK 0x3 -+#define VINLOW_HYST_SHIFT 4 -+#define VINLOW_THRESHOLD_MASK 0x7 -+#define VINLOW_THRESHOLD_SHIFT 1 -+#define VINLOW_ENABLED 0x01 -+#define VINLOW_CTRL_REG_MASK 0xFF -+ -+/* USB Control Register */ -+#define BOOST_OVP_DISABLED BIT(7) -+#define VBUS_OTG_DETECTION_DISABLED BIT(6) -+#define OCP_LIMIT_HIGH BIT(3) -+#define SWIN_SWOUT_ENABLED BIT(2) -+#define USBSW_OTG_SWITCH_ENABLED BIT(1) -+ -+int stpmic1_powerctrl_on(void); -+int stpmic1_switch_off(void); -+ -+int stpmic1_register_read(uint8_t register_id, uint8_t *value); -+int stpmic1_register_write(uint8_t register_id, uint8_t value); -+int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); -+ -+int stpmic1_regulator_enable(const char *name); -+int stpmic1_regulator_disable(const char *name); -+uint8_t stpmic1_is_regulator_enabled(const char *name); -+ -+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); -+int stpmic1_regulator_voltage_get(const char *name); -+int stpmic1_regulator_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); -+ -+/* -+ * The STPMIC1 is accessed during low power sequence in unpaged -+ * execution context. To prevent adding an unpaged constraint on -+ * STPMIC1 regulator definitions, conversion tables and device tree -+ * content, the regulators configurations are read from device tree -+ * at boot time and saved in memory for being applied at runtime -+ * without needing pager support. -+ * -+ * There are 2 types of regulator configuration loaded during such -+ * low power and unpaged sequences: boot-on (bo) configuration and -+ * low power (lp) configuration. -+ */ -+struct stpmic1_bo_cfg { -+ uint8_t ctrl_reg; -+ uint8_t value; -+ uint8_t mask; -+ uint8_t pd_reg; -+ uint8_t pd_value; -+ uint8_t pd_mask; -+ uint8_t mrst_reg; -+ uint8_t mrst_value; -+ uint8_t mrst_mask; -+}; -+ -+struct stpmic1_lp_cfg { -+ uint8_t ctrl_reg; -+ uint8_t lp_reg; -+ uint8_t value; -+ uint8_t mask; -+}; -+ -+int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg); -+int stpmic1_bo_voltage_cfg(const char *name, uint16_t millivolts, -+ struct stpmic1_bo_cfg *cfg); -+int stpmic1_bo_voltage_unpg(struct stpmic1_bo_cfg *cfg); -+ -+int stpmic1_bo_pull_down_cfg(const char *name, -+ struct stpmic1_bo_cfg *cfg); -+int stpmic1_bo_pull_down_unpg(struct stpmic1_bo_cfg *cfg); -+ -+int stpmic1_bo_mask_reset_cfg(const char *name, struct stpmic1_bo_cfg *cfg); -+int stpmic1_bo_mask_reset_unpg(struct stpmic1_bo_cfg *cfg); -+ -+int stpmic1_lp_cfg(const char *name, struct stpmic1_lp_cfg *cfg); -+int stpmic1_lp_load_unpg(struct stpmic1_lp_cfg *cfg); -+int stpmic1_lp_on_off_unpg(struct stpmic1_lp_cfg *cfg, int enable); -+int stpmic1_lp_mode_unpg(struct stpmic1_lp_cfg *cfg, -+ unsigned int mode); -+int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, -+ struct stpmic1_lp_cfg *cfg); -+int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg); -+ -+void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); -+ -+int stpmic1_get_version(unsigned long *version); -+void stpmic1_dump_regulators(void); -+ -+#endif /*__STPMIC1_H__*/ -diff --git a/core/include/dt-bindings/clock/stm32mp1-clks.h b/core/include/dt-bindings/clock/stm32mp1-clks.h -new file mode 100644 -index 0000000..f5254cf ---- /dev/null -+++ b/core/include/dt-bindings/clock/stm32mp1-clks.h -@@ -0,0 +1,252 @@ -+/* 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 DBG 213 -+#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 -+ -+#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ -diff --git a/core/include/dt-bindings/clock/stm32mp1-clksrc.h b/core/include/dt-bindings/clock/stm32mp1-clksrc.h -new file mode 100644 -index 0000000..de7d160 ---- /dev/null -+++ b/core/include/dt-bindings/clock/stm32mp1-clksrc.h -@@ -0,0 +1,284 @@ -+/* -+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause -+ */ -+ -+#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 -+ -+#endif -diff --git a/core/include/dt-bindings/etzpc/stm32-etzpc.h b/core/include/dt-bindings/etzpc/stm32-etzpc.h -new file mode 100644 -index 0000000..f498651 ---- /dev/null -+++ b/core/include/dt-bindings/etzpc/stm32-etzpc.h -@@ -0,0 +1,108 @@ -+/* -+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved -+ * -+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause -+ */ -+ -+#ifndef _DT_BINDINGS_STM32_ETZPC_H -+#define _DT_BINDINGS_STM32_ETZPC_H -+ -+/* define DECPROT modes */ -+#define DECPROT_S_RW 0x0 -+#define DECPROT_NS_R_S_W 0x1 -+#define DECPROT_MCU_ISOLATION 0x2 -+#define DECPROT_NS_RW 0x3 -+ -+/* define DECPROT lock */ -+#define DECPROT_UNLOCK 0x0 -+#define DECPROT_LOCK 0x1 -+ -+/* define 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_GPIOZ_ID 6 -+#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(ip_id, mode, lock) ((ip_id << 16) | (mode << 8) | lock) -+ -+#endif /* _DT_BINDINGS_STM32_ETZPC_H */ -+ -diff --git a/core/include/dt-bindings/interrupt-controller/arm-gic.h b/core/include/dt-bindings/interrupt-controller/arm-gic.h -new file mode 100644 -index 0000000..6863d5e ---- /dev/null -+++ b/core/include/dt-bindings/interrupt-controller/arm-gic.h -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ -+/* -+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ */ -+ -+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H -+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H -+ -+/* 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 -+ -+#endif -diff --git a/core/include/dt-bindings/pinctrl/stm32-pinfunc.h b/core/include/dt-bindings/pinctrl/stm32-pinfunc.h -new file mode 100644 -index 0000000..7f6e4b9 ---- /dev/null -+++ b/core/include/dt-bindings/pinctrl/stm32-pinfunc.h -@@ -0,0 +1,41 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved -+ * Author: Torgue Alexandre for STMicroelectronics. -+ */ -+ -+#ifndef _DT_BINDINGS_STM32_PINFUNC_H -+#define _DT_BINDINGS_STM32_PINFUNC_H -+ -+/* define PIN modes */ -+#define GPIO 0x0 -+#define AF0 0x1 -+#define AF1 0x2 -+#define AF2 0x3 -+#define AF3 0x4 -+#define AF4 0x5 -+#define AF5 0x6 -+#define AF6 0x7 -+#define AF7 0x8 -+#define AF8 0x9 -+#define AF9 0xa -+#define AF10 0xb -+#define AF11 0xc -+#define AF12 0xd -+#define AF13 0xe -+#define AF14 0xf -+#define AF15 0x10 -+#define ANALOG 0x11 -+ -+/* define Pins number*/ -+#define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) -+ -+#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) -+ -+/* package information */ -+#define STM32MP157CAA 0x1 -+#define STM32MP157CAB 0x2 -+#define STM32MP157CAC 0x4 -+#define STM32MP157CAD 0x8 -+ -+#endif /* _DT_BINDINGS_STM32_PINFUNC_H */ -diff --git a/core/include/dt-bindings/power/stm32mp1-power.h b/core/include/dt-bindings/power/stm32mp1-power.h -new file mode 100644 -index 0000000..bfb7f78 ---- /dev/null -+++ b/core/include/dt-bindings/power/stm32mp1-power.h -@@ -0,0 +1,19 @@ -+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ -+/* -+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved -+ * 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/core/include/dt-bindings/reset/stm32mp1-resets.h b/core/include/dt-bindings/reset/stm32mp1-resets.h -new file mode 100644 -index 0000000..f0c3aae ---- /dev/null -+++ b/core/include/dt-bindings/reset/stm32mp1-resets.h -@@ -0,0 +1,108 @@ -+/* 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_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 -+ -+#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ -diff --git a/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h -index d7b8abd..5a7e18d 100644 ---- a/core/include/kernel/interrupt.h -+++ b/core/include/kernel/interrupt.h -@@ -23,6 +23,11 @@ struct itr_ops { - uint8_t cpu_mask); - void (*set_affinity)(struct itr_chip *chip, size_t it, - uint8_t cpu_mask); -+#if !defined(CFG_ARM_GICV3) -+ uint8_t (*set_pmr)(struct itr_chip *chip, uint8_t mask); -+ uint8_t (*set_ipriority)(struct itr_chip *chip, size_t it, -+ uint8_t mask); -+#endif - }; - - enum itr_return { -@@ -57,4 +62,14 @@ void itr_raise_sgi(size_t it, uint8_t cpu_mask); - */ - void itr_set_affinity(size_t it, uint8_t cpu_mask); - -+/* -+ * Set the Priority Mask Regarding and return its previous value -+ */ -+uint8_t itr_set_pmr(uint8_t mask); -+ -+/* -+ * Set the targe tinterrupt priority mask and return its previous value -+ */ -+uint8_t itr_set_ipriority(size_t it, uint8_t mask); -+ - #endif /*__KERNEL_INTERRUPT_H*/ -diff --git a/core/kernel/console.c b/core/kernel/console.c -index 1f11503..98fde7c 100644 ---- a/core/kernel/console.c -+++ b/core/kernel/console.c -@@ -65,8 +65,13 @@ void configure_console_from_dt(void) - return; - - offs = fdt_path_offset(fdt, "/secure-chosen"); -- if (offs < 0) -- return; -+ if (offs < 0) { -+ /* Fallback to node /chosen */ -+ offs = fdt_path_offset(fdt, "/chosen"); -+ if (offs < 0) { -+ return; -+ } -+ } - prop = fdt_get_property(fdt, offs, "stdout-path", NULL); - if (!prop) { - /* -diff --git a/core/kernel/interrupt.c b/core/kernel/interrupt.c -index cff1f80..ce27aca 100644 ---- a/core/kernel/interrupt.c -+++ b/core/kernel/interrupt.c -@@ -78,3 +78,13 @@ void itr_set_affinity(size_t it, uint8_t cpu_mask) - { - itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); - } -+ -+uint8_t itr_set_pmr(uint8_t mask) -+{ -+ return itr_chip->ops->set_pmr(itr_chip, mask); -+} -+ -+uint8_t itr_set_ipriority(size_t it, uint8_t mask) -+{ -+ return itr_chip->ops->set_ipriority(itr_chip, it, mask); -+} -diff --git a/core/lib/libfdt/fdt_ro.c b/core/lib/libfdt/fdt_ro.c -index 34110da..79b1b6d 100644 ---- a/core/lib/libfdt/fdt_ro.c -+++ b/core/lib/libfdt/fdt_ro.c -@@ -89,6 +89,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset, - return (strlen(p) == len) && (memcmp(p, s, len) == 0); - } - -+uint32_t fdt_get_max_phandle(const void *fdt) -+{ -+ uint32_t max_phandle = 0; -+ int offset; -+ -+ for (offset = fdt_next_node(fdt, -1, NULL);; -+ offset = fdt_next_node(fdt, offset, NULL)) { -+ uint32_t phandle; -+ -+ if (offset == -FDT_ERR_NOTFOUND) -+ return max_phandle; -+ -+ if (offset < 0) -+ return (uint32_t)-1; -+ -+ phandle = fdt_get_phandle(fdt, offset); -+ if (phandle == (uint32_t)-1) -+ continue; -+ -+ if (phandle > max_phandle) -+ max_phandle = phandle; -+ } -+ -+ return 0; -+} -+ - int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) - { - FDT_CHECK_HEADER(fdt); -@@ -155,9 +181,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, - return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); - } - --int fdt_path_offset(const void *fdt, const char *path) -+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) - { -- const char *end = path + strlen(path); -+ const char *end = path + namelen; - const char *p = path; - int offset = 0; - -@@ -165,7 +191,7 @@ int fdt_path_offset(const void *fdt, const char *path) - - /* see if we have an alias */ - if (*path != '/') { -- const char *q = strchr(path, '/'); -+ const char *q = memchr(path, '/', end - p); - - if (!q) - q = end; -@@ -178,14 +204,15 @@ int fdt_path_offset(const void *fdt, const char *path) - p = q; - } - -- while (*p) { -+ while (p < end) { - const char *q; - -- while (*p == '/') -+ while (*p == '/') { - p++; -- if (! *p) -- return offset; -- q = strchr(p, '/'); -+ if (p == end) -+ return offset; -+ } -+ q = memchr(p, '/', end - p); - if (! q) - q = end; - -@@ -199,6 +226,11 @@ int fdt_path_offset(const void *fdt, const char *path) - return offset; - } - -+int fdt_path_offset(const void *fdt, const char *path) -+{ -+ return fdt_path_offset_namelen(fdt, path, strlen(path)); -+} -+ - const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) - { - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); -@@ -533,6 +565,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) - return 0; - } - -+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) -+{ -+ const char *list, *end; -+ int length, count = 0; -+ -+ list = fdt_getprop(fdt, nodeoffset, property, &length); -+ if (!list) -+ return -length; -+ -+ end = list + length; -+ -+ while (list < end) { -+ length = strnlen(list, end - list) + 1; -+ -+ /* Abort if the last string isn't properly NUL-terminated. */ -+ if (list + length > end) -+ return -FDT_ERR_BADVALUE; -+ -+ list += length; -+ count++; -+ } -+ -+ return count; -+} -+ -+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, -+ const char *string) -+{ -+ int length, len, idx = 0; -+ const char *list, *end; -+ -+ list = fdt_getprop(fdt, nodeoffset, property, &length); -+ if (!list) -+ return -length; -+ -+ len = strlen(string) + 1; -+ end = list + length; -+ -+ while (list < end) { -+ length = strnlen(list, end - list) + 1; -+ -+ /* Abort if the last string isn't properly NUL-terminated. */ -+ if (list + length > end) -+ return -FDT_ERR_BADVALUE; -+ -+ if (length == len && memcmp(list, string, length) == 0) -+ return idx; -+ -+ list += length; -+ idx++; -+ } -+ -+ return -FDT_ERR_NOTFOUND; -+} -+ -+const char *fdt_stringlist_get(const void *fdt, int nodeoffset, -+ const char *property, int idx, -+ int *lenp) -+{ -+ const char *list, *end; -+ int length; -+ -+ list = fdt_getprop(fdt, nodeoffset, property, &length); -+ if (!list) { -+ if (lenp) -+ *lenp = length; -+ -+ return NULL; -+ } -+ -+ end = list + length; -+ -+ while (list < end) { -+ length = strnlen(list, end - list) + 1; -+ -+ /* Abort if the last string isn't properly NUL-terminated. */ -+ if (list + length > end) { -+ if (lenp) -+ *lenp = -FDT_ERR_BADVALUE; -+ -+ return NULL; -+ } -+ -+ if (idx == 0) { -+ if (lenp) -+ *lenp = length - 1; -+ -+ return list; -+ } -+ -+ list += length; -+ idx--; -+ } -+ -+ if (lenp) -+ *lenp = -FDT_ERR_NOTFOUND; -+ -+ return NULL; -+} -+ - int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible) - { -@@ -542,10 +674,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, - prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); - if (!prop) - return len; -- if (fdt_stringlist_contains(prop, len, compatible)) -- return 0; -- else -- return 1; -+ -+ return !fdt_stringlist_contains(prop, len, compatible); - } - - int fdt_node_offset_by_compatible(const void *fdt, int startoffset, -diff --git a/core/lib/libfdt/fdt_rw.c b/core/lib/libfdt/fdt_rw.c -index 1785a51..15897b7 100644 ---- a/core/lib/libfdt/fdt_rw.c -+++ b/core/lib/libfdt/fdt_rw.c -@@ -102,6 +102,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) - - if (((p + oldlen) < p) || ((p + oldlen) > end)) - return -FDT_ERR_BADOFFSET; -+ if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) -+ return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) - return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); -@@ -190,17 +192,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) - int fdt_del_mem_rsv(void *fdt, int n) - { - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); -- int err; - - FDT_RW_CHECK_HEADER(fdt); - - if (n >= fdt_num_mem_rsv(fdt)) - return -FDT_ERR_NOTFOUND; - -- err = _fdt_splice_mem_rsv(fdt, re, 1, 0); -- if (err) -- return err; -- return 0; -+ return _fdt_splice_mem_rsv(fdt, re, 1, 0); - } - - static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, -@@ -286,8 +284,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, - if (err) - return err; - -- if (len) -- memcpy(prop->data, val, len); -+ memcpy(prop->data, val, len); - return 0; - } - -diff --git a/core/lib/libfdt/fdt_wip.c b/core/lib/libfdt/fdt_wip.c -index c97c5f7..ee9df5c 100644 ---- a/core/lib/libfdt/fdt_wip.c -+++ b/core/lib/libfdt/fdt_wip.c -@@ -56,21 +56,42 @@ - - #include "libfdt_internal.h" - -+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, -+ const char *name, int namelen, -+ uint32_t idx, const void *val, -+ int len) -+{ -+ void *propval; -+ int proplen; -+ -+ propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, -+ &proplen); -+ if (!propval) -+ return proplen; -+ -+ if (proplen < (len + idx)) -+ return -FDT_ERR_NOSPACE; -+ -+ memcpy((char *)propval + idx, val, len); -+ return 0; -+} -+ - int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len) - { -- void *propval; -+ const void *propval; - int proplen; - -- propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); -+ propval = fdt_getprop(fdt, nodeoffset, name, &proplen); - if (! propval) - return proplen; - - if (proplen != len) - return -FDT_ERR_NOSPACE; - -- memcpy(propval, val, len); -- return 0; -+ return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, -+ strlen(name), 0, -+ val, len); - } - - static void _fdt_nop_region(void *start, int len) -diff --git a/core/lib/libfdt/include/fdt.h b/core/lib/libfdt/include/fdt.h -index 520bdcf..faa8046 100644 ---- a/core/lib/libfdt/include/fdt.h -+++ b/core/lib/libfdt/include/fdt.h -@@ -53,8 +53,16 @@ - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -+/* -+ * Portions copyright (c) 2016-2017, ARM Limited and Contributors. -+ * All rights reserved. -+ */ -+ - #ifndef __ASSEMBLY__ - -+#include -+ -+ - struct fdt_header { - fdt32_t magic; /* magic word FDT_MAGIC */ - fdt32_t totalsize; /* total size of DT block */ -diff --git a/core/lib/libfdt/include/libfdt.h b/core/lib/libfdt/include/libfdt.h -index 01a9065..5ce9bfb 100644 ---- a/core/lib/libfdt/include/libfdt.h -+++ b/core/lib/libfdt/include/libfdt.h -@@ -52,6 +52,11 @@ - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -+/* -+ * Portions copyright (c) 2016-2017, ARM Limited and Contributors. -+ * All rights reserved. -+ */ -+ - #include - #include - -@@ -122,7 +127,12 @@ - /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells - * or similar property with a bad format or value */ - --#define FDT_ERR_MAX 14 -+#define FDT_ERR_BADVALUE 15 -+ /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected -+ * value. For example: a property expected to contain a string list -+ * is not NUL-terminated within the length of its value. */ -+ -+#define FDT_ERR_MAX 15 - - /**********************************************************************/ - /* Low-level functions (you probably don't need these) */ -@@ -164,27 +174,55 @@ int fdt_first_subnode(const void *fdt, int offset); - */ - int fdt_next_subnode(const void *fdt, int offset); - -+/** -+ * fdt_for_each_subnode - iterate over all subnodes of a parent -+ * -+ * @node: child node (int, lvalue) -+ * @fdt: FDT blob (const void *) -+ * @parent: parent node (int) -+ * -+ * This is actually a wrapper around a for loop and would be used like so: -+ * -+ * fdt_for_each_subnode(node, fdt, parent) { -+ * Use node -+ * ... -+ * } -+ * -+ * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { -+ * Error handling -+ * } -+ * -+ * Note that this is implemented as a macro and @node is used as -+ * iterator in the loop. The parent variable be constant or even a -+ * literal. -+ * -+ */ -+#define fdt_for_each_subnode(node, fdt, parent) \ -+ for (node = fdt_first_subnode(fdt, parent); \ -+ node >= 0; \ -+ node = fdt_next_subnode(fdt, node)) -+ - /**********************************************************************/ - /* General functions */ - /**********************************************************************/ - - #define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) --#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) -+#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) - #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) - #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) - #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) - #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) - #define fdt_version(fdt) (fdt_get_header(fdt, version)) --#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) --#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) --#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) -+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) -+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) -+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) - #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) - - #define __fdt_set_hdr(name) \ - static inline void fdt_set_##name(void *fdt, uint32_t val) \ - { \ -- struct fdt_header *fdth = (struct fdt_header*)fdt; \ -+ struct fdt_header *fdth = (struct fdt_header *)fdt; \ - fdth->name = cpu_to_fdt32(val); \ - } - __fdt_set_hdr(magic) -@@ -255,6 +293,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize); - const char *fdt_string(const void *fdt, int stroffset); - - /** -+ * fdt_get_max_phandle - retrieves the highest phandle in a tree -+ * @fdt: pointer to the device tree blob -+ * -+ * fdt_get_max_phandle retrieves the highest phandle in the given -+ * device tree. This will ignore badly formatted phandles, or phandles -+ * with a value of 0 or -1. -+ * -+ * returns: -+ * the highest phandle on success -+ * 0, if no phandle was found in the device tree -+ * -1, if an error occurred -+ */ -+uint32_t fdt_get_max_phandle(const void *fdt); -+ -+/** - * fdt_num_mem_rsv - retrieve the number of memory reserve map entries - * @fdt: pointer to the device tree blob - * -@@ -314,8 +367,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, - * returns: - * structure block offset of the requested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist -- * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag -- * -FDT_ERR_BADMAGIC, -+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE -+ * tag -+ * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, -@@ -324,6 +378,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, - int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); - - /** -+ * fdt_path_offset_namelen - find a tree node by its full path -+ * @fdt: pointer to the device tree blob -+ * @path: full path of the node to locate -+ * @namelen: number of characters of path to consider -+ * -+ * Identical to fdt_path_offset(), but only consider the first namelen -+ * characters of path as the path name. -+ */ -+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); -+ -+/** - * fdt_path_offset - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate -@@ -336,7 +401,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); - * address). - * - * returns: -- * structure block offset of the node with the requested path (>=0), on success -+ * structure block offset of the node with the requested path (>=0), on -+ * success - * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid - * -FDT_ERR_NOTFOUND, if the requested node does not exist - * -FDT_ERR_BADMAGIC, -@@ -360,10 +426,12 @@ int fdt_path_offset(const void *fdt, const char *path); - * - * returns: - * pointer to the node's name, on success -- * If lenp is non-NULL, *lenp contains the length of that name (>=0) -+ * If lenp is non-NULL, *lenp contains the length of that name -+ * (>=0) - * NULL, on error - * if lenp is non-NULL *lenp contains an error code (<0): -- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE -+ * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings -@@ -412,6 +480,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset); - int fdt_next_property_offset(const void *fdt, int offset); - - /** -+ * fdt_for_each_property_offset - iterate over all properties of a node -+ * -+ * @property_offset: property offset (int, lvalue) -+ * @fdt: FDT blob (const void *) -+ * @node: node offset (int) -+ * -+ * This is actually a wrapper around a for loop and would be used like so: -+ * -+ * fdt_for_each_property_offset(property, fdt, node) { -+ * Use property -+ * ... -+ * } -+ * -+ * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { -+ * Error handling -+ * } -+ * -+ * Note that this is implemented as a macro and property is used as -+ * iterator in the loop. The node variable can be constant or even a -+ * literal. -+ */ -+#define fdt_for_each_property_offset(property, fdt, node) \ -+ for (property = fdt_first_property_offset(fdt, node); \ -+ property >= 0; \ -+ property = fdt_next_property_offset(fdt, property)) -+ -+/** - * fdt_get_property_by_offset - retrieve the property at a given offset - * @fdt: pointer to the device tree blob - * @offset: offset of the property to retrieve -@@ -447,8 +542,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * -- * Identical to fdt_get_property_namelen(), but only examine the first -- * namelen characters of name for matching the property name. -+ * Identical to fdt_get_property(), but only examine the first namelen -+ * characters of name for matching the property name. - */ - const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int nodeoffset, -@@ -475,7 +570,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property -- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE -+ * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -539,6 +635,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, - */ - const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp); -+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, -+ const char *name, int namelen, -+ int *lenp) -+{ -+ return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, -+ namelen, lenp); -+} - - /** - * fdt_getprop - retrieve the value of a given property -@@ -560,7 +663,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property -- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE -+ * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -632,7 +736,7 @@ const char *fdt_get_alias(const void *fdt, const char *name); - * 0, on success - * buf contains the absolute path of the node at - * nodeoffset, as a NUL-terminated string. -- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) - * characters and will not fit in the given buffer. - * -FDT_ERR_BADMAGIC, -@@ -662,11 +766,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); - * structure from the start to nodeoffset. - * - * returns: -- - * structure block offset of the node at node offset's ancestor - * of depth supernodedepth (>=0), on success -- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag --* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset -+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of -+ * nodeoffset - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -688,7 +792,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - * - * returns: - * depth of the node at nodeoffset (>=0), on success -- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -711,7 +815,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset); - * returns: - * structure block offset of the parent of the node at nodeoffset - * (>=0), on success -- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -751,7 +855,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset); - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset -- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -798,7 +902,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); - * 1, if the node has a 'compatible' property, but it does not list - * the given string - * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property -- * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -835,7 +939,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset -- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -858,6 +962,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - */ - int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); - -+/** -+ * fdt_stringlist_count - count the number of strings in a string list -+ * @fdt: pointer to the device tree blob -+ * @nodeoffset: offset of a tree node -+ * @property: name of the property containing the string list -+ * @return: -+ * the number of strings in the given property -+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated -+ * -FDT_ERR_NOTFOUND if the property does not exist -+ */ -+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); -+ -+/** -+ * fdt_stringlist_search - find a string in a string list and return its index -+ * @fdt: pointer to the device tree blob -+ * @nodeoffset: offset of a tree node -+ * @property: name of the property containing the string list -+ * @string: string to look up in the string list -+ * -+ * Note that it is possible for this function to succeed on property values -+ * that are not NUL-terminated. That's because the function will stop after -+ * finding the first occurrence of @string. This can for example happen with -+ * small-valued cell properties, such as #address-cells, when searching for -+ * the empty string. -+ * -+ * @return: -+ * the index of the string in the list of strings -+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated -+ * -FDT_ERR_NOTFOUND if the property does not exist or does not contain -+ * the given string -+ */ -+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, -+ const char *string); -+ -+/** -+ * fdt_stringlist_get() - obtain the string at a given index in a string list -+ * @fdt: pointer to the device tree blob -+ * @nodeoffset: offset of a tree node -+ * @property: name of the property containing the string list -+ * @index: index of the string to return -+ * @lenp: return location for the string length or an error code on failure -+ * -+ * Note that this will successfully extract strings from properties with -+ * non-NUL-terminated values. For example on small-valued cell properties -+ * this function will return the empty string. -+ * -+ * If non-NULL, the length of the string (on success) or a negative error-code -+ * (on failure) will be stored in the integer pointer to by lenp. -+ * -+ * @return: -+ * A pointer to the string at the given index in the string list or NULL on -+ * failure. On success the length of the string will be stored in the memory -+ * location pointed to by the lenp parameter, if non-NULL. On failure one of -+ * the following negative error codes will be returned in the lenp parameter -+ * (if non-NULL): -+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated -+ * -FDT_ERR_NOTFOUND if the property does not exist -+ */ -+const char *fdt_stringlist_get(const void *fdt, int nodeoffset, -+ const char *property, int index, -+ int *lenp); -+ - /**********************************************************************/ - /* Read-only functions (addressing related) */ - /**********************************************************************/ -@@ -883,7 +1049,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); - * returns: - * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property -- * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #address-cells property -+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid -+ * #address-cells property - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -903,7 +1070,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset); - * returns: - * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property -- * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #size-cells property -+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid -+ * #size-cells property - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, -@@ -918,6 +1086,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset); - /**********************************************************************/ - - /** -+ * fdt_setprop_inplace_namelen_partial - change a property's value, -+ * but not its size -+ * @fdt: pointer to the device tree blob -+ * @nodeoffset: offset of the node whose property to change -+ * @name: name of the property to change -+ * @namelen: number of characters of name to consider -+ * @idx: index of the property to change in the array -+ * @val: pointer to data to replace the property value with -+ * @len: length of the property value -+ * -+ * Identical to fdt_setprop_inplace(), but modifies the given property -+ * starting from the given index, and using only the first characters -+ * of the name. It is useful when you want to manipulate only one value of -+ * an array and you have a string that doesn't end with \0. -+ */ -+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, -+ const char *name, int namelen, -+ uint32_t idx, const void *val, -+ int len); -+ -+/** - * fdt_setprop_inplace - change a property's value, but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change -@@ -1527,9 +1716,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, - * change the offsets of some existing nodes. - - * returns: -- * structure block offset of the created nodeequested subnode (>=0), on success -+ * structure block offset of the created nodeequested subnode (>=0), on -+ * success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist -- * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag -+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE -+ * tag - * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of - * the given name - * -FDT_ERR_NOSPACE, if there is insufficient free space in the -diff --git a/core/secure_dt.mk b/core/secure_dt.mk -new file mode 100644 -index 0000000..16ea741 ---- /dev/null -+++ b/core/secure_dt.mk -@@ -0,0 +1,107 @@ -+# -+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. -+# -+# SPDX-License-Identifier: BSD-3-Clause -+# -+ -+DTC_FLAGS += -I dts -O dtb -+DTC := dtc -+ -+define MAKE_PREREQ_DIR -+ifneq (${1},${2}) -+${1} : -+ @mkdir -p "${1}" -+ -+endif -+endef -+ -+# Convert device tree source file names to matching blobs -+# $(1) = input dts -+define SOURCES_TO_DTBS -+ $(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1)))) -+endef -+ -+# MAKE_FDT_DIRS macro creates the prerequisite directories that host the -+# FDT binaries -+# $(1) = output directory -+# $(2) = input dts -+define MAKE_FDT_DIRS -+ $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) -+ $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS}))) -+ # The $(dir ) function leaves a trailing / on the directory names -+ # Rip off the / to match directory names with make rule targets. -+ $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS))) -+ -+$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${out-dir}))) -+ -+fdt_dirs: ${DTB_DIRS} -+endef -+ -+# MAKE_DTB generate the Flattened device tree binary -+# $(1) = output directory -+# $(2) = input dts -+define MAKE_DTB -+ -+# List of DTB file(s) to generate, based on DTS file basename list -+$(eval DTBOBJ := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) -+# List of the pre-compiled DTS file(s) -+$(eval DTSPRE := $(addprefix $(1)/,$(patsubst %.dts,%.pre.dts,$(notdir $(2))))) -+# Dependencies of the pre-compiled DTS file(s) on its source and included files -+$(eval DTSDEP := $(patsubst %.dtb,%.o.d,$(DTBOBJ))) -+# Dependencies of the DT compilation on its pre-compiled DTS -+$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DTBOBJ))) -+ -+$(DTBOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs -+ @echo " CPP $$<" -+ $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) -+ @$(CPP$(sm)) $$(CPPFLAGS) -Icore/include/ -x assembler-with-cpp \ -+ -E -ffreestanding -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DTSPRE) $$< -+ @echo " DTC $$<" -+ @$(DTC) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $(DTSPRE) -+ -+-include $(DTBDEP) -+-include $(DTSDEP) -+endef -+ -+# MAKE_DTBS builds flattened device tree sources -+# $(1) = output directory -+# $(2) = list of flattened device tree source files -+define MAKE_DTBS -+ $(eval DTBOBJS := $(filter %.dts,$(2))) -+ $(eval REMAIN := $(filter-out %.dts,$(2))) -+ $(and $(REMAIN),$(error FDT_SOURCES contain non-DTS files: $(REMAIN))) -+ $(eval $(foreach obj,$(DTBOBJS),$(call MAKE_DTB,$(1),$(obj)))) -+ $(eval $(call MAKE_FDT_DIRS,$(1),$(2))) -+ -+dtbs: $(DTBS) -+all: dtbs -+endef -+ -+# Generating the DTB from the DTS and integrating into OP-TEE core. -+# -+# CFG_SECURE_DT provides the DTS base name. It is looked up as file -+# name as $(CFG_SECURE_DT).dts from the platform sub directory fdts/. -+# -+# Build precompiles $(CFG_SECURE_DT).dts to resolve pre compilation features -+# (build directive, file inclusion, ...) then generates $(CFG_SECURE_DT).dtb. -+# -+# If CFG_STATIC_SECURE_DT is enabled, $(CFG_SECURE_DT).dtb content is wrapped -+# into C source file builtin_secure_dtb.c that defines the DTB byte array -+# CFG_STATIC_SECURE_DT expects. -+ -+DTB_FILE_NAME := $(CFG_SECURE_DT).dtb -+FDT_SOURCES := $(addprefix $(arch-dir)/fdts/, $(CFG_SECURE_DT).dts) -+ -+DTC_FLAGS += -Wno-unit_address_vs_reg -+ -+$(eval $(call MAKE_DTBS,$(out-dir)/core/fdts,$(FDT_SOURCES))) -+ -+ifeq ($(CFG_STATIC_SECURE_DT),y) -+gensrcs-y += builtin_secure_dtb -+produce-builtin_secure_dtb = fdts/builtin_secure_dtb.c -+depends-builtin_secure_dtb = $(DTBOBJ) scripts/ta_bin_to_c.py -+recipe-builtin_secure_dtb = scripts/bin_to_c.py --dtb $(DTBOBJ) \ -+ --label static_secure_dtb \ -+ --out $(out-dir)/core/fdts/builtin_secure_dtb.c -+cleanfiles += $(out-dir)/core/fdts/builtin_secure_dtb.c -+endif -diff --git a/core/sub.mk b/core/sub.mk -index 9aee1b4..3119b58 100644 ---- a/core/sub.mk -+++ b/core/sub.mk -@@ -26,3 +26,10 @@ $(foreach f, $(EARLY_TA_PATHS), $(eval $(call process_early_ta,$(f)))) - $(foreach f, $(CFG_IN_TREE_EARLY_TAS), $(eval $(call \ - process_early_ta,$(out-dir)/ta/$(f).stripped.elf))) - endif -+ -+# -+# Secure device tree support -+# -+ifneq ($(CFG_SECURE_DT),) -+include core/secure_dt.mk -+endif -diff --git a/lib/libutils/ext/include/util.h b/lib/libutils/ext/include/util.h -index 4561758..2509b07 100644 ---- a/lib/libutils/ext/include/util.h -+++ b/lib/libutils/ext/include/util.h -@@ -49,9 +49,16 @@ - - /* Round down the even multiple of size, size has to be a multiple of 2 */ - #define ROUNDDOWN(v, size) ((v) & ~((__typeof__(v))(size) - 1)) -+ -+/* Unsigned integer division with nearest rounding variant */ -+#define UDIV_ROUND_NEAREST(x, y) \ -+ (__extension__ ({ __typeof__(x) _x = (x); \ -+ __typeof__(y) _y = (y); \ -+ (_x + (_y / 2)) / _y; })) - #else - #define ROUNDUP(x, y) ((((x) + (y) - 1) / (y)) * (y)) - #define ROUNDDOWN(x, y) (((x) / (y)) * (y)) -+#define UDIV_ROUND_NEAREST(x, y) (((x) + ((y) / 2)) / (y)) - #endif - - /* x has to be of an unsigned type */ -diff --git a/mk/config.mk b/mk/config.mk -index e0c050a..21ba469 100644 ---- a/mk/config.mk -+++ b/mk/config.mk -@@ -236,10 +236,25 @@ CFG_CORE_SANITIZE_UNDEFINED ?= n - CFG_CORE_SANITIZE_KADDRESS ?= n - - # Device Tree support --# When enabled, the TEE _start function expects to find the address of a --# Device Tree Blob (DTB) in register r2. The DT parsing code relies on --# libfdt. Currently only used to add the optee node and a reserved-memory --# node for shared memory. -+# -+# - When CFG_DT is enabled, the libfdt is embedded in the core. It allows -+# to parse a device tree. -+# - When CFG_STATIC_SECURE_DT is enabled, TEE core embeds a statically linked -+# device tree blob. -+# - When CFG_SECURE_DT is defined, it defines the base name of the device tree -+# source file from which a device tree blob is generated at core build. -+# -+# If CFG_DT is enabled and CFG_STATIC_SECURE_DT is disabled, the TEE _start -+# function expects to find the address of a Device Tree Blob (DTB) in -+# register r2 and is currently only used to add the optee node and a -+# reserved-memory node for shared memory. -+ifneq ($(CFG_SECURE_DT),) -+$(call force,CFG_STATIC_SECURE_DT,y) -+endif -+CFG_STATIC_SECURE_DT ?= n -+ifeq ($(CFG_STATIC_SECURE_DT),y) -+$(call force,CFG_DT,y) -+endif - CFG_DT ?= n - - # Maximum size of the Device Tree Blob, has to be large enough to allow -diff --git a/scripts/bin_to_c.py b/scripts/bin_to_c.py -new file mode 100755 -index 0000000..6fe7772 ---- /dev/null -+++ b/scripts/bin_to_c.py -@@ -0,0 +1,58 @@ -+#!/usr/bin/env python -+# SPDX-License-Identifier: BSD-2-Clause -+# -+# Copyright (c) 2018, Linaro Limited -+# -+ -+import argparse -+import array -+import os -+import re -+ -+def get_args(): -+ -+ parser = argparse.ArgumentParser(description='Converts a binary ' -+ 'file into C source file defining binary data as a' -+ 'constant byte array.') -+ -+ parser.add_argument('--dtb', required=True, -+ help='Path to the input binary file') -+ -+ parser.add_argument('--label', required=True, -+ help='Label for the generated table in the C source file.') -+ -+ parser.add_argument('--out', required=True, -+ help='Path of the output C file') -+ -+ return parser.parse_args() -+ -+def main(): -+ -+ args = get_args(); -+ -+ with open(args.dtb, 'rb') as indata: -+ bytes = indata.read() -+ size = len(bytes) -+ -+ f = open(args.out, 'w') -+ f.write('/* Generated from ' + args.dtb + ' by ' + -+ os.path.basename(__file__) + ' */\n\n') -+ f.write('#include \n'); -+ f.write('#include \n'); -+ f.write('__extension__ const uint8_t ' + args.label + '[] ' + -+ ' __aligned(__alignof__(uint64_t)) = {\n') -+ i = 0 -+ while i < size: -+ if i % 8 == 0: -+ f.write('\t\t'); -+ f.write('0x' + '{:02x}'.format(ord(bytes[i])) + ',') -+ i = i + 1 -+ if i % 8 == 0 or i == size: -+ f.write('\n') -+ else: -+ f.write(' ') -+ f.write('};\n'); -+ f.close() -+ -+if __name__ == "__main__": -+ main() --- -2.7.4 - diff --git a/recipes-security/optee/optee-os/0002-st-updates-r2.patch b/recipes-security/optee/optee-os/0002-st-updates-r2.patch deleted file mode 100644 index 9c90099..0000000 --- a/recipes-security/optee/optee-os/0002-st-updates-r2.patch +++ /dev/null @@ -1,2044 +0,0 @@ -From 31808ba1976f47e71086ac168a2f64178ea2edcd Mon Sep 17 00:00:00 2001 -From: Romuald JEANNE -Date: Tue, 17 Sep 2019 14:01:51 +0200 -Subject: [PATCH] st updates r2 - ---- - .../arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 13 +- - .../arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 10 +- - core/arch/arm/fdts/stm32mp157a-dk1.dts | 6 +- - core/arch/arm/fdts/stm32mp157c-ed1.dts | 6 +- - .../arm/plat-stm32mp1/drivers/stm32mp1_calib.c | 105 ++++--- - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c | 76 ++++- - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c | 3 +- - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h | 8 +- - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h | 4 +- - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h | 6 +- - core/arch/arm/plat-stm32mp1/main.c | 4 +- - core/arch/arm/plat-stm32mp1/pm/context.c | 15 +- - core/arch/arm/plat-stm32mp1/pm/low_power.c | 242 ++++++++++++--- - core/arch/arm/plat-stm32mp1/pm/pm_helpers.S | 4 +- - core/arch/arm/plat-stm32mp1/pm/psci.c | 2 +- - core/arch/arm/plat-stm32mp1/shared_resources.c | 6 +- - core/arch/arm/plat-stm32mp1/stm32_util.h | 1 + - core/drivers/stm32_bsec.c | 331 ++++++++------------- - core/drivers/stm32_etzpc.c | 6 +- - core/drivers/stm32_i2c.c | 22 +- - core/drivers/stm32_iwdg.c | 6 + - core/drivers/stm32_timer.c | 25 +- - core/drivers/stpmic1.c | 17 +- - core/include/drivers/stm32_bsec.h | 21 +- - 24 files changed, 571 insertions(+), 368 deletions(-) - -diff --git a/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -index 16b8cf6..11e8f2b 100644 ---- a/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -+++ b/core/arch/arm/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi -@@ -1,8 +1,8 @@ - // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -- */ --/* STM32MP157C DK1/DK2 BOARD configuration -+ * -+ * STM32MP157C DK1/DK2 BOARD configuration - * 1x DDR3L 4Gb, 16-bit, 533MHz. - * Reference used NT5CC256M16DP-DI from NANYA - * -@@ -16,8 +16,7 @@ - * address mapping : RBC - * Tc > + 85C : N - */ -- --#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41" -+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45" - #define DDR_MEM_SPEED 533000 - #define DDR_MEM_SIZE 0x20000000 - -@@ -90,7 +89,7 @@ - #define DDR_PTR2 0x042DA068 - #define DDR_ACIOCR 0x10400812 - #define DDR_DXCCR 0x00000C40 --#define DDR_DSGCR 0xF200001F -+#define DDR_DSGCR 0xF200011F - #define DDR_DCR 0x0000000B - #define DDR_DTPR0 0x38D488D0 - #define DDR_DTPR1 0x098B00D8 -@@ -109,11 +108,11 @@ - #define DDR_DX1DLLCR 0x40000000 - #define DDR_DX1DQTR 0xFFFFFFFF - #define DDR_DX1DQSTR 0x3DB02000 --#define DDR_DX2GCR 0x0000CE81 -+#define DDR_DX2GCR 0x0000CE80 - #define DDR_DX2DLLCR 0x40000000 - #define DDR_DX2DQTR 0xFFFFFFFF - #define DDR_DX2DQSTR 0x3DB02000 --#define DDR_DX3GCR 0x0000CE81 -+#define DDR_DX3GCR 0x0000CE80 - #define DDR_DX3DLLCR 0x40000000 - #define DDR_DX3DQTR 0xFFFFFFFF - #define DDR_DX3DQSTR 0x3DB02000 -diff --git a/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -index 82e7104..4b70b60 100644 ---- a/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -+++ b/core/arch/arm/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi -@@ -1,9 +1,8 @@ - // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -- */ -- --/* STM32MP157C ED1 BOARD configuration -+ * -+ * STM32MP157C ED1 BOARD configuration - * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. - * Reference used NT5CC256M16DP-DI from NANYA - * -@@ -17,8 +16,7 @@ - * address mapping : RBC - * Tc > + 85C : N - */ -- --#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41" -+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45" - #define DDR_MEM_SPEED 533000 - #define DDR_MEM_SIZE 0x40000000 - -@@ -91,7 +89,7 @@ - #define DDR_PTR2 0x042DA068 - #define DDR_ACIOCR 0x10400812 - #define DDR_DXCCR 0x00000C40 --#define DDR_DSGCR 0xF200001F -+#define DDR_DSGCR 0xF200011F - #define DDR_DCR 0x0000000B - #define DDR_DTPR0 0x38D488D0 - #define DDR_DTPR1 0x098B00D8 -diff --git a/core/arch/arm/fdts/stm32mp157a-dk1.dts b/core/arch/arm/fdts/stm32mp157a-dk1.dts -index e42bdcd..78cb849 100644 ---- a/core/arch/arm/fdts/stm32mp157a-dk1.dts -+++ b/core/arch/arm/fdts/stm32mp157a-dk1.dts -@@ -149,7 +149,9 @@ - }; - - &pwr { -- pwr-supply = <&vdd>; -+ pwr-regulators { -+ vdd-supply = <&vdd>; -+ }; - }; - - /* RNG1 is used by non secure at run time and by secure (low power sequences) */ -@@ -251,7 +253,7 @@ - &timers15 { - secure-status = "okay"; - st,hsi-cal-input = <7>; -- st,csi_cal-input = <8>; -+ st,csi-cal-input = <8>; - }; - - /* Low-power states of regulators */ -diff --git a/core/arch/arm/fdts/stm32mp157c-ed1.dts b/core/arch/arm/fdts/stm32mp157c-ed1.dts -index 8462d23..81ae94c 100644 ---- a/core/arch/arm/fdts/stm32mp157c-ed1.dts -+++ b/core/arch/arm/fdts/stm32mp157c-ed1.dts -@@ -144,7 +144,9 @@ - }; - - &pwr { -- pwr-supply = <&vdd>; -+ pwr-regulators { -+ vdd-supply = <&vdd>; -+ }; - }; - - /* RNG1 is used by non secure at run time and by secure (low power sequences) */ -@@ -256,7 +258,7 @@ - &timers15 { - secure-status = "okay"; - st,hsi-cal-input = <7>; -- st,csi_cal-input = <8>; -+ st,csi-cal-input = <8>; - }; - - /* Low-power states of regulators */ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c -index 583bf94..7050e97 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c -@@ -11,16 +11,18 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include - #include - #include - #include - #include - #include - --#define CAL_MAX_RETRY 20U -+#define CALIBRATION_TIMEOUT_US 10000U - - /* List of forbiden values for HSI and CSI */ - static uint16_t fbv_hsi[] = { -@@ -64,7 +66,7 @@ static const struct stm32mp1_clk_cal hsi_calib_config = { - .trim_max = 63, - .trim_min = -64, - .ref_freq = 0, -- .freq_margin = 1, -+ .freq_margin = 5, - .set_trim = hsi_set_trim, - .get_trim = hsi_get_trimed_cal, - }; -@@ -74,11 +76,16 @@ static const struct stm32mp1_clk_cal csi_calib_config = { - .trim_max = 15, - .trim_min = -16, - .ref_freq = 0, -- .freq_margin = 2, -+ .freq_margin = 8, - .set_trim = csi_set_trim, - .get_trim = csi_get_trimed_cal, - }; - -+static 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)hsi_calib->cal_ref; -@@ -95,7 +102,7 @@ static unsigned int hsi_get_trimed_cal(void) - uint32_t utrim = (mmio_read_32(stm32_rcc_base() + RCC_HSICFGR) & - RCC_HSICFGR_HSITRIM_MASK) >> - RCC_HSICFGR_HSITRIM_SHIFT; -- int trim = (int)utrim - hsi_calib->trim_max; -+ int trim = get_signed_value((uint8_t)utrim); - - if (trim + (int)hsi_calib->cal_ref < 0) - return 0; -@@ -184,32 +191,52 @@ static unsigned int trim_decrease(struct stm32mp1_clk_cal *clk_cal, - - static void rcc_calibration(struct stm32mp1_clk_cal *clk_cal) - { -- unsigned long margin = (clk_cal->ref_freq * clk_cal->freq_margin) / 100; -+ unsigned long margin = (clk_cal->ref_freq * -+ clk_cal->freq_margin) / 1000; - unsigned long min = clk_cal->ref_freq - margin; - unsigned long max = clk_cal->ref_freq + margin; - unsigned long freq = clk_cal->get_freq(); -- int cal = clk_cal->get_trim(); -- unsigned int nb_retries; -+ int trim, new_trim; -+ unsigned long conv; -+ unsigned long min_conv = ULONG_MAX; -+ uint64_t timeout_ref; - -- for (nb_retries = 0; nb_retries < CAL_MAX_RETRY; nb_retries++) { -- if ((freq >= min) && (freq <= max)) { -- break; -- } -+ if ((freq >= min) && (freq <= max)) -+ return; -+ -+ trim = clk_cal->get_trim(); -+ timeout_ref = utimeout_init(CALIBRATION_TIMEOUT_US); -+ do { -+ if (freq < clk_cal->ref_freq) -+ new_trim = trim_increase(clk_cal, trim); -+ else -+ new_trim = trim_decrease(clk_cal, trim); - -- if (freq < min) { -- cal = trim_increase(clk_cal, cal); -- } else { -- cal = trim_decrease(clk_cal, cal); -+ 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; - } - -- clk_cal->set_trim(cal); -+ if (utimeout_elapsed(CALIBRATION_TIMEOUT_US, timeout_ref)) -+ break; - -- freq = clk_cal->get_freq(); -- } -+ } while (conv == min_conv); - -+ clk_cal->set_trim(trim); -+ freq = clk_cal->get_freq(); - if ((freq < min) || (freq > max)) { -- DMSG("Calibration failed"); -- panic("Calibration"); -+ EMSG("%s Calibration : Freq %lu , trim %i\n", -+ (clk_cal->set_trim == hsi_set_trim) ? "HSI" : "CSI", -+ freq, trim); - } - } - -@@ -387,17 +414,20 @@ int stm32mp_start_clock_calib(unsigned int clock_id) - return 0; - } - --static void init_hsi_calibration(void *fdt, int node) -+static int init_hsi_calibration(void *fdt, int node) - { - if (!fdt_getprop(fdt, node, "st,hsi-cal", NULL)) -- return; -+ return 0; - - hsi_calib = calloc(1, sizeof(*hsi_calib)); - assert(hsi_calib); - memcpy(hsi_calib, &hsi_calib_config, sizeof(*hsi_calib)); - - stm32_timer_freq_func(&hsi_calib->get_freq, HSI_CAL); -- assert(hsi_calib->get_freq); -+ if (hsi_calib->get_freq == NULL) { -+ free(hsi_calib); -+ return -1; -+ } - - hsi_calib->ref_freq = stm32mp1_clk_get_rate(CK_HSI); - -@@ -406,41 +436,41 @@ static void init_hsi_calibration(void *fdt, int node) - RCC_HSICFGR_HSICAL_SHIFT; - - trim_table_init(hsi_calib); -- - hsi_calib->set_trim(hsi_calib->cal_ref); -- - stm32mp_start_clock_calib(CK_HSI); -+ return 1; - } - --static void init_csi_calibration(void *fdt, int node) -+static int init_csi_calibration(void *fdt, int node) - { - if (!fdt_getprop(fdt, node, "st,csi-cal", NULL)) -- return; -+ return 0; - - csi_calib = calloc(1, sizeof(*csi_calib)); - assert(csi_calib); - memcpy(csi_calib, &csi_calib_config, sizeof(*csi_calib)); - - stm32_timer_freq_func(&csi_calib->get_freq, CSI_CAL); -- assert(csi_calib->get_freq); -+ if (csi_calib->get_freq == NULL) { -+ free(csi_calib); -+ return -1; -+ } - - csi_calib->ref_freq = stm32mp1_clk_get_rate(CK_CSI); -- - csi_calib->cal_ref = (mmio_read_32(stm32_rcc_base() + RCC_CSICFGR) & - RCC_CSICFGR_CSICAL_MASK) >> - RCC_CSICFGR_CSICAL_SHIFT; -- - trim_table_init(csi_calib); -- - csi_calib->set_trim(csi_calib->cal_ref); -- - stm32mp_start_clock_calib(CK_CSI); -+ return 1; - } - - static TEE_Result init_stm32mp1_calib(void) - { - void *fdt; - int rcc_node = -1; -+ int res_csi, res_hsi; - - fdt = get_dt_blob(); - if (fdt) -@@ -448,9 +478,14 @@ static TEE_Result init_stm32mp1_calib(void) - if (rcc_node < 0) - panic(); - -- init_hsi_calibration(fdt, rcc_node); -- init_csi_calibration(fdt, rcc_node); -- init_periodic_calibration(fdt, rcc_node); -+ res_hsi = init_hsi_calibration(fdt, rcc_node); -+ if (res_hsi < 0) -+ panic("HSI calibration init failed"); -+ res_csi = init_csi_calibration(fdt, rcc_node); -+ if (res_csi < 0) -+ panic("CSI calibration init failed"); -+ if (res_csi || res_hsi) -+ init_periodic_calibration(fdt, rcc_node); - - return TEE_SUCCESS; - } -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -index acf5d60..69c3c74 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -@@ -32,6 +32,8 @@ - #include - #endif - -+#define CLKSRC_TIMEOUT_US 200000U -+ - enum stm32mp1_parent_id { - /* Oscillators are defined in enum stm32mp_osc_id */ - -@@ -78,6 +80,8 @@ enum stm32mp1_parent_sel { - _UART24_SEL, - _UART35_SEL, - _UART78_SEL, -+ _SDMMC12_SEL, -+ _SDMMC3_SEL, - _ASS_SEL, - _MSS_SEL, - _USBPHY_SEL, -@@ -349,13 +353,23 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), - _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), - #endif -+ _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 0, LTDC_PX, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 0, DMA1, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 1, DMA2, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), - _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), - _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), - _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), -+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 0, MDMA, _UNKNOWN_SEL), -+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 5, GPU, _UNKNOWN_SEL), -+ _CLK_SC_FIXED(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK), -+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 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), - }; - KEEP_PAGER(stm32mp1_clk_gate); - -@@ -389,6 +403,14 @@ static const uint8_t uart234578_parents[] = { - _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER - }; - -+static const uint8_t sdmmc12_parents[] = { -+ _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER -+}; -+ -+static const uint8_t sdmmc3_parents[] = { -+ _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER -+}; -+ - static const uint8_t ass_parents[] = { - _HSI, _HSE, _PLL2 - }; -@@ -417,6 +439,8 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { - _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), - _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), - _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), -+ _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents), -+ _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents), - _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents), - _CLK_PARENT(_MSS_SEL, RCC_MSSCKSELR, 0, 0x3, mss_parents), - _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), -@@ -582,6 +606,26 @@ static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) - return (enum stm32mp1_parent_id)gate_ref(i)->fixed; - } - -+static int stm32mp1_set_clksrc(unsigned int clksrc) -+{ -+ uintptr_t address = stm32_rcc_base() + (clksrc >> 4); -+ uint64_t timeout_ref; -+ -+ mmio_clrsetbits_32(address, RCC_SELR_SRC_MASK, -+ clksrc & RCC_SELR_SRC_MASK); -+ -+ timeout_ref = utimeout_init(CLKSRC_TIMEOUT_US); -+ while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) { -+ if (utimeout_elapsed(CLKSRC_TIMEOUT_US, timeout_ref)) { -+ EMSG("CLKSRC %x start failed @ 0x%x: 0x%x\n", -+ clksrc, address, mmio_read_32(address)); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ - static int stm32mp1_clk_get_parent(unsigned long id) - { - const struct stm32mp1_clk_sel *sel; -@@ -1069,10 +1113,6 @@ static void stm32mp1_osc_init(void) - DMSG("Osc %s frequency: %lu", name[i], stm32mp1_osc[i]); - } - } --#else --static void stm32mp1_osc_init(void) --{ --} - #endif - - /* -@@ -1478,10 +1518,36 @@ static void sync_earlyboot_clocks_state(void) - stm32mp_register_clock_parents_secure(CRYP1); - } - -+static void _clock_mpu_suspend(void) -+{ -+ uintptr_t mpckselr = stm32_rcc_base() + RCC_MPCKSELR; -+ -+ if (((mmio_read_32(mpckselr) & RCC_SELR_SRC_MASK)) == -+ RCC_MPCKSELR_PLL) { -+ if (stm32mp1_set_clksrc(CLK_MPU_PLL1P_DIV)) { -+ panic(); -+ } -+ } -+} -+ -+static void _clock_mpu_resume(void) -+{ -+ uintptr_t mpckselr = stm32_rcc_base() + RCC_MPCKSELR; -+ -+ if (((mmio_read_32(mpckselr) & RCC_SELR_SRC_MASK)) == -+ RCC_MPCKSELR_PLL_MPUDIV) { -+ if (stm32mp1_set_clksrc(CLK_MPU_PLL1P)) { -+ panic(); -+ } -+ } -+} -+ - static void _clock_resume(void) - { - unsigned int idx; - -+ _clock_mpu_resume(); -+ - /* Sync secure and shared clocks physical state on functional state */ - for (idx = 0; idx < NB_GATES; idx++) { - struct stm32mp1_clk_gate const *gate = gate_ref(idx); -@@ -1504,7 +1570,7 @@ void stm32mp_clock_suspend_resume(enum pm_op op) - { - switch (op) { - case PM_OP_SUSPEND: -- /* Nothing to do */ -+ _clock_mpu_suspend(); - break; - case PM_OP_RESUME: - _clock_resume(); -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -index ed38575..f2b7fe1 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -@@ -499,7 +499,8 @@ static bool initialize_pmic_i2c(void) - - ret = stm32_i2c_init(i2c, &i2c_init); - if (ret != 0) { -- EMSG("Cannot initialize I2C %x (%d)\n", i2c->pbase, ret); -+ EMSG("Cannot initialize I2C %" PRIx32 " (%d)", -+ i2c_info.base, ret); - panic(); - } - -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -index f50943d..01f15fd 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -@@ -14,17 +14,17 @@ void stm32mp_pmic_apply_lp_config(const char *lp_state); - void stm32mp_get_pmic(void); - void stm32mp_put_pmic(void); - #else --void stm32mp_pmic_apply_boot_on_config(void) -+static inline void stm32mp_pmic_apply_boot_on_config(void) - { - } --void stm32mp_pmic_apply_lp_config(const char *lp_state) -+static inline void stm32mp_pmic_apply_lp_config(const char *lp_state __unused) - { - } --void stm32mp_get_pmic(void) -+static inline void stm32mp_get_pmic(void) - { - panic(); - } --void stm32mp_put_pmic(void) -+static inline void stm32mp_put_pmic(void) - { - panic(); - } -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h -index 1d44e8b..ed23259 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #ifndef __STM32MP1_PWR_H__ -@@ -24,6 +24,8 @@ - - #define PWR_CR2_BREN BIT(0) - #define PWR_CR2_RREN BIT(1) -+#define PWR_CR2_BRRDY BIT(16) -+#define PWR_CR2_RRRDY BIT(17) - - #define PWR_CR3_VBE BIT(8) - #define PWR_CR3_VBRS BIT(9) -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h -index 6a7a665..690c76f 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.h -@@ -387,7 +387,8 @@ - #define RCC_HSICFGR_HSITRIM_SHIFT 8 - #define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) - #define RCC_HSICFGR_HSICAL_SHIFT 16 --#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) -+#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(24, 16) -+#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK_32(27, 25) - - /* Fields of RCC_CSICFGR register */ - #define RCC_CSICFGR_CSITRIM_SHIFT 8 -@@ -503,6 +504,9 @@ - #define RCC_AHB5RSTSETR_RNG1RST BIT(6) - #define RCC_AHB5RSTSETR_AXIMCRST BIT(16) - -+/* RCC_MP_AHB6RST(SET|CLR)R bit fields */ -+#define RCC_AHB6RSTSETR_GPURST BIT(5) -+ - /* RCC_MP_AHB5EN(SET|CLR)R bit fields */ - #define RCC_MP_AHB5ENSETR_GPIOZEN_POS 0 - #define RCC_MP_AHB5ENSETR_CRYP1EN_POS 4 -diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c -index 1921678..b501541 100644 ---- a/core/arch/arm/plat-stm32mp1/main.c -+++ b/core/arch/arm/plat-stm32mp1/main.c -@@ -136,7 +136,7 @@ const struct thread_handlers *generic_boot_get_handlers(void) - #define CONSOLE_WITHOUT_CLOCK_MAGIC ~0UL - - static struct stm32_uart_pdata console_data; --static struct serial_chip *serial_console; -+static struct serial_chip *serial_console __maybe_unused; - - void console_init(void) - { -@@ -202,7 +202,7 @@ void console_flush(void) - } - #endif - --#if CFG_DT -+#ifdef CFG_DT - /* Probe console once clocks inits (service_init level) are completed */ - static TEE_Result stm32_uart_console_probe(void) - { -diff --git a/core/arch/arm/plat-stm32mp1/pm/context.c b/core/arch/arm/plat-stm32mp1/pm/context.c -index 2ce72b3..20e9e84 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/context.c -+++ b/core/arch/arm/plat-stm32mp1/pm/context.c -@@ -273,15 +273,16 @@ static struct mobj *teeram_bkp_mobj; - static void init_retram_resume_resources(void) - { - struct retram_resume_ctx *ctx = get_retram_resume_ctx(); -- const size_t size = (uintptr_t)stm32mp_bkpsram_image_end - -- (uintptr_t)stm32mp_bkpsram_resume; -+ size_t __maybe_unused csize; - paddr_t __maybe_unused pa; - - COMPILE_TIME_ASSERT(sizeof(struct pm_mailbox) < - BKPSRAM_PM_MAILBOX_SIZE); - COMPILE_TIME_ASSERT(sizeof(struct retram_resume_ctx) < - BKPSRAM_PM_CONTEXT_SIZE); -- assert((sizeof(*ctx) + size) < BKPSRAM_PM_CONTEXT_SIZE); -+ csize = (uintptr_t)stm32mp_bkpsram_image_end - -+ (uintptr_t)stm32mp_bkpsram_resume; -+ assert((sizeof(*ctx) + csize) < BKPSRAM_PM_CONTEXT_SIZE); - - teeram_bkp_mobj = mobj_mm_alloc(mobj_sec_ddr, TEE_RAM_PH_SIZE, - &tee_mm_sec_ddr); -@@ -424,21 +425,25 @@ static void save_teeram_in_ddr(void) - static void enable_pm_mailbox(unsigned int suspend) - { - struct pm_mailbox *mailbox = get_pm_mailbox(); -- uint32_t magic = BOOT_API_A7_CORE0_MAGIC_NUMBER; -+ uint32_t magic = 0; - uint32_t hint = 0; - - assert(stm32_clock_is_enabled(BKPSRAM) && - stm32_clock_is_enabled(RTCAPB)); - - if (suspend) { -+ magic = BOOT_API_A7_CORE0_MAGIC_NUMBER; -+ mailbox->magic = STANDBY_CONTEXT_MAGIC; -+ - hint = virt_to_phys(&get_retram_resume_ctx()->resume_sequence); -+ } else { -+ mailbox->magic = 0; - } - - write32(magic, stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); - write32(hint, stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS)); - - mailbox->core0_resume_ep = hint; -- mailbox->magic = STANDBY_CONTEXT_MAGIC; - } - - static void gate_pm_context_clocks(bool enable) -diff --git a/core/arch/arm/plat-stm32mp1/pm/low_power.c b/core/arch/arm/plat-stm32mp1/pm/low_power.c -index bd28014..48bddb7 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/low_power.c -+++ b/core/arch/arm/plat-stm32mp1/pm/low_power.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -16,7 +17,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -26,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -139,11 +143,20 @@ void stm32_pm_cpu_wfi(void) - cpu_wfi(); - } - --/*If IWDG is not supported, provide a stubbed weak watchdog kicker */ -+/* If IWDG is not supported, provide a stubbed weak watchdog kicker */ - void __weak stm32_iwdg_refresh(uint32_t __unused instance) - { - } - -+#define ARM_CNTXCTL_IMASK BIT(1) -+ -+static 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); -+} -+ - /* - * stm32_enter_cstop - Prepare CSTOP mode - * -@@ -192,6 +205,16 @@ int stm32_enter_cstop(uint32_t mode) - - ddr_in_selfrefresh = (rc == 0); - -+ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { -+ /* Keep retention and backup RAM content in standby */ -+ mmio_setbits_32(pwr_base + PWR_CR2_OFF, PWR_CR2_BREN | -+ PWR_CR2_RREN); -+ while ((mmio_read_32(pwr_base + PWR_CR2_OFF) & -+ (PWR_CR2_BRRDY | PWR_CR2_RRRDY)) == 0U) { -+ ; -+ } -+ } -+ - return rc; - } - -@@ -200,6 +223,7 @@ int stm32_enter_cstop(uint32_t mode) - */ - void stm32_exit_cstop(void) - { -+ uintptr_t pwr_base = stm32_pwr_base(); - uintptr_t rcc_base = stm32_rcc_base(); - - if (ddr_in_selfrefresh) { -@@ -220,27 +244,163 @@ void stm32_exit_cstop(void) - - dsb(); - isb(); -+ -+ /* Disable retention and backup RAM content after stop */ -+ mmio_clrbits_32(pwr_base + PWR_CR2_OFF, PWR_CR2_BREN | PWR_CR2_RREN); -+} -+ -+/* -+ * GIC support required in low power sequences and reset sequences -+ */ -+#define GICC_IAR 0x00C -+#define GICC_IT_ID_MASK 0x3ff -+#define GICC_EOIR 0x010 -+#define GICC_HPPIR 0x018 -+#define GICC_AHPPIR 0x028 -+#define GIC_PENDING_G1_INTID 1022U -+#define GIC_SPURIOUS_INTERRUPT 1023U -+#define GIC_NUM_INTS_PER_REG 32 -+#define GIC_MAX_SPI_ID 1020 -+#define GICD_ICENABLER(n) (0x180 + (n) * 4) -+ -+static void clear_pending_interrupts(void) -+{ -+ uint32_t id; -+ uintptr_t gicc_base = get_gicc_base(); -+ uintptr_t gicd_base = get_gicd_base(); -+ -+ do { -+ id = read32(gicc_base + GICC_HPPIR) & GICC_IT_ID_MASK; -+ -+ /* -+ * Find out which interrupt it is under the -+ * assumption that the GICC_CTLR.AckCtl bit is 0. -+ */ -+ if (id == GIC_PENDING_G1_INTID) -+ id = read32(gicc_base + GICC_AHPPIR) & GICC_IT_ID_MASK; -+ -+ if (id < GIC_MAX_SPI_ID) { -+ size_t idx = id / GIC_NUM_INTS_PER_REG; -+ uint32_t mask = 1 << (id % GIC_NUM_INTS_PER_REG); -+ -+ write32(id, gicc_base + GICC_EOIR); -+ -+ write32(mask, gicd_base + GICD_ICENABLER(idx)); -+ -+ dsb_ishst(); -+ } -+ } while (id < GIC_MAX_SPI_ID); -+} -+ -+void stm32mp_gic_set_end_of_interrupt(uint32_t it) -+{ -+ uintptr_t gicc_base = get_gicc_base(); -+ -+ write32(it, gicc_base + GICC_EOIR); -+} -+ -+static void __noreturn wait_cpu_reset(void) -+{ -+ dcache_op_all(DCACHE_OP_CLEAN_INV); -+ write_sctlr(read_sctlr() & ~SCTLR_C); -+ dcache_op_all(DCACHE_OP_CLEAN_INV); -+ __asm__("clrex"); -+ -+ dsb(); -+ isb(); -+ -+ for ( ; ; ) { -+ clear_pending_interrupts(); -+ 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), -+}; -+ - static void __noreturn reset_cores(void) - { - uintptr_t rcc_base = stm32_rcc_base(); -- uint32_t reset_mask; -+ uint32_t reset_mask = RCC_MP_GRSTCSETR_MPUP0RST | -+ RCC_MP_GRSTCSETR_MPUP1RST; - uint32_t target_mask; -+ uint32_t id; -+ -+ /* Mask timer interrupts */ -+ stm32mp_mask_timer(); -+ -+ for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) { -+ if ((!stm32mp1_clk_is_enabled(tzc_source_ip[id].clock_id)) || -+ ((tzc_source_ip[id].decprot_id != STM32MP1_ETZPC_MAX_ID) && -+ (etzpc_get_decprot(tzc_source_ip[id].decprot_id) == -+ TZPC_DECPROT_MCU_ISOLATION))) { -+ continue; -+ } -+ -+ if (tzc_source_ip[id].reset_id != GPU_R) { -+ stm32_reset_assert(tzc_source_ip[id].reset_id); -+ stm32_reset_deassert(tzc_source_ip[id].reset_id); -+ } else { -+ /* GPU reset automatically cleared by hardware */ -+ mmio_setbits_32(rcc_base + RCC_AHB6RSTSETR, -+ RCC_AHB6RSTSETR_GPURST); -+ } -+ } - - if (get_core_pos() == 0) { -- reset_mask = RCC_MP_GRSTCSETR_MPUP0RST; - target_mask = TARGET_CPU1_GIC_MASK; - } else { -- reset_mask = RCC_MP_GRSTCSETR_MPUP1RST; - target_mask = TARGET_CPU0_GIC_MASK; - } - - itr_raise_sgi(GIC_SEC_SGI_1, target_mask); -- dcache_op_all(DCACHE_OP_CLEAN_INV); -+ -+ clear_pending_interrupts(); -+ - write32(reset_mask, rcc_base + RCC_MP_GRSTCSETR); -- cpu_wfi(); -- panic("Cores reset"); -+ -+ wait_cpu_reset(); - } - - /* -@@ -252,6 +412,25 @@ void __noreturn stm32_cores_reset(void) - } - KEEP_PAGER(stm32_cores_reset); - -+static void reset_other_core(void) -+{ -+ uintptr_t rcc_base = stm32_rcc_base(); -+ uint32_t reset_mask; -+ uint32_t target_mask; -+ -+ if (get_core_pos() == 0) { -+ reset_mask = RCC_MP_GRSTCSETR_MPUP1RST; -+ target_mask = TARGET_CPU1_GIC_MASK; -+ } else { -+ reset_mask = RCC_MP_GRSTCSETR_MPUP0RST; -+ target_mask = TARGET_CPU0_GIC_MASK; -+ } -+ -+ itr_raise_sgi(GIC_SEC_SGI_1, target_mask); -+ -+ write32(reset_mask, rcc_base + RCC_MP_GRSTCSETR); -+} -+ - /* - * stm32_enter_cstop_shutdown - Shutdown CPUs to target low power mode - * @mode - Target low power mode -@@ -271,9 +450,13 @@ void __noreturn stm32_enter_cstop_shutdown(uint32_t mode) - case STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF: - #ifdef STM32MP1_USE_MPU0_RESET - stm32mp_pm_shutdown_context(); -+ reset_other_core(); - stm32_enter_cstop(mode); -- cpu_wfi(); -- reset_cores(); -+ dsb(); -+ isb(); -+ for ( ; ; ) { -+ wfi(); -+ } - #else - if (stm32mp_with_pmic()) { - wait_console_flushed(); -@@ -304,14 +487,10 @@ void __noreturn stm32_enter_cstop_reset(uint32_t mode) - udelay(100); - break; - default: --#ifdef STM32MP1_USE_MPU0_RESET -- reset_cores(); --#else - IMSG("Forced system reset"); - wait_console_flushed(); - write32(RCC_MP_GRSTCSETR_MPSYSRST, rcc_base + RCC_MP_GRSTCSETR); - udelay(100); --#endif - break; - } - -@@ -336,13 +515,6 @@ void stm32_enter_csleep(void) - stm32_pm_cpu_wfi(); - } - --/* -- * Secure interrupts used in the low power sequences -- */ --#define GICC_IAR 0x00C --#define GICC_IAR_IT_ID_MASK 0x3ff --#define GICC_EOIR 0x010 -- - /* RCC Wakeup interrupt is used to wake from suspeneded mode */ - static enum itr_return rcc_wakeup_it_handler(struct itr_handler *hdl __unused) - { -@@ -360,21 +532,14 @@ KEEP_PAGER(rcc_wakeup_handler); - /* SGI9 (secure SGI 1) informs targeted CPU it shall reset */ - static enum itr_return sgi9_it_handler(struct itr_handler *handler) - { -- uintptr_t rcc_base = stm32_rcc_base(); -- uint32_t reset_mask; -- uintptr_t gicc_base = get_gicc_base(); -+ stm32mp_mask_timer(); - -- write32(handler->it, gicc_base + GICC_EOIR); -+ stm32mp_gic_set_end_of_interrupt(handler->it); - -- if (get_core_pos() == 0) { -- reset_mask = RCC_MP_GRSTCSETR_MPUP0RST; -- } else { -- reset_mask = RCC_MP_GRSTCSETR_MPUP1RST; -- } -+ clear_pending_interrupts(); -+ -+ wait_cpu_reset(); - -- dcache_op_all(DCACHE_OP_CLEAN_INV); -- write32(reset_mask, rcc_base + RCC_MP_GRSTCSETR); -- cpu_wfi(); - panic("Core reset"); - - return ITRR_HANDLED; -@@ -388,18 +553,12 @@ KEEP_PAGER(sgi9_reset_handler); - - static TEE_Result init_low_power(void) - { -- uintptr_t pwr_base = stm32_pwr_base(); -- - itr_add(&rcc_wakeup_handler); - itr_enable(rcc_wakeup_handler.it); - - itr_add(&sgi9_reset_handler); - itr_enable(sgi9_reset_handler.it); - -- /* Enable retention for BKPSRAM and BKPREG */ -- io_mask32(pwr_base + PWR_CR2_OFF, -- PWR_CR2_BREN | PWR_CR2_RREN, PWR_CR2_BREN | PWR_CR2_RREN); -- - return TEE_SUCCESS; - } - service_init(init_low_power); -@@ -412,11 +571,8 @@ void __noreturn stm32_pm_cpu_power_down_wfi(void) - if (get_core_pos() == 0) { - void (*reset_ep)(void) = stm32mp_sysram_resume; - -- wait_console_flushed(); -+ stm32_pm_cpu_wfi(); - -- dsb(); -- isb(); -- wfi(); - /* STANDBY not reached: resume from retained SYSRAM */ - stm32_exit_cstop(); - stm32mp_cpu_reset_state(); -diff --git a/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -index 91c7580..d9ed746 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -+++ b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -@@ -621,14 +621,14 @@ UNWIND( .save {r12, lr}) - bl psci_armv7_cpu_off - - write_bpiall -- isb - dsb -+ isb - read_sctlr r0 - bic r0, r0, #SCTLR_M - bic r0, r0, #SCTLR_I - write_sctlr r0 -- isb - dsb sy -+ isb - - pop {r12, pc} - UNWIND( .fnend) -diff --git a/core/arch/arm/plat-stm32mp1/pm/psci.c b/core/arch/arm/plat-stm32mp1/pm/psci.c -index 6e8219e..d3fb974 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/psci.c -+++ b/core/arch/arm/plat-stm32mp1/pm/psci.c -@@ -322,7 +322,7 @@ int psci_system_suspend(uintptr_t entry, uint32_t context_id __unused, - { - int ret = PSCI_RET_INVALID_PARAMETERS; - uint32_t soc_mode; -- int pos = get_core_pos(); -+ int __maybe_unused pos = get_core_pos(); - - DMSG("core %u", pos); - -diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c -index 0eb929c..69b87cd 100644 ---- a/core/arch/arm/plat-stm32mp1/shared_resources.c -+++ b/core/arch/arm/plat-stm32mp1/shared_resources.c -@@ -264,7 +264,7 @@ static unsigned int decprot2shres(unsigned int decprot_id) - return SHRES_INVALID; - } - --static const char *decprot2str(unsigned int decprot_id) -+static const char __maybe_unused *decprot2str(unsigned int decprot_id) - { - size_t i; - -@@ -279,7 +279,7 @@ static const char *decprot2str(unsigned int decprot_id) - } - - /* GPIOZ bank may have several number of pins */ --#if CFG_DT -+#ifdef CFG_DT - static int gpioz_nbpin = -1; - - static unsigned int get_gpioz_nbpin_unpg(void) -@@ -982,7 +982,7 @@ static TEE_Result stm32mp1_init_drivers(void) - registering_locked = true; - - for (id = 0; id < STM32MP1_SHRES_COUNT; id++) { -- uint8_t *state = &shres_state[id]; -+ uint8_t __maybe_unused *state = &shres_state[id]; - - #if TRACE_LEVEL == TRACE_INFO - /* Display only the secure and shared resources */ -diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h -index 0164855..347499b 100644 ---- a/core/arch/arm/plat-stm32mp1/stm32_util.h -+++ b/core/arch/arm/plat-stm32mp1/stm32_util.h -@@ -31,6 +31,7 @@ uintptr_t stm32_get_stgen_base(void); - /* Platform util for the GIC */ - uintptr_t get_gicc_base(void); - uintptr_t get_gicd_base(void); -+void stm32mp_gic_set_end_of_interrupt(uint32_t it); - - /* Platform util for clock gating. ID refers to clock DT bindings ID. */ - void stm32_clock_enable(unsigned long id); -diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c -index 3355e0a..7fcefdb 100644 ---- a/core/drivers/stm32_bsec.c -+++ b/core/drivers/stm32_bsec.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #include -@@ -133,23 +133,28 @@ static uintptr_t bsec_get_base(void) - } - - /* -- * bsec_check_error -- * otp : OTP number. -- * return value : BSEC_OK if no error. -+ * bsec_check_error: check BSEC error status. -+ * otp: OTP number. -+ * check_disturbed: check only error (false) or all sources (true). -+ * return value: BSEC_OK if no error. - */ --static uint32_t bsec_check_error(uint32_t otp) -+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 ((read32(bsec_get_base() + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { -- return BSEC_DISTURBED; -- } -- - if ((read32(bsec_get_base() + BSEC_ERROR_OFF + bank) & bit) != 0U) { - return BSEC_ERROR; - } - -+ if (!check_disturbed) { -+ return BSEC_OK; -+ } -+ -+ if ((read32(bsec_get_base() + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { -+ return BSEC_DISTURBED; -+ } -+ - return BSEC_OK; - } - -@@ -162,14 +167,16 @@ uint32_t bsec_shadow_register(uint32_t otp) - { - uint32_t result; - uint32_t exc; -+ bool value; - -- if (otp > stm32mp_get_otp_max()) { -- return BSEC_INVALID_PARAM; -+ result = bsec_read_sr_lock(otp, &value); -+ if (result != BSEC_OK) { -+ DMSG("BSEC: %u Sticky-read bit read Error %i", otp, result); -+ return result; - } - -- /* Check if shadowing of OTP is locked */ -- if (bsec_read_sr_lock(otp)) { -- IMSG("BSEC: OTP locked, register will not be refreshed"); -+ if (value) { -+ DMSG("BSEC: OTP locked, register will not be refreshed"); - } - - result = bsec_power_safmem(true); -@@ -185,7 +192,7 @@ uint32_t bsec_shadow_register(uint32_t otp) - ; - } - -- result = bsec_check_error(otp); -+ result = bsec_check_error(otp, true); - - bsec_unlock(exc); - -@@ -203,22 +210,15 @@ uint32_t bsec_shadow_register(uint32_t otp) - uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) - { - uint32_t exc; -- uint32_t result; - - if (otp > stm32mp_get_otp_max()) { - return BSEC_INVALID_PARAM; - } - -- exc = bsec_lock(); -- - *val = read32(bsec_get_base() + BSEC_OTP_DATA_OFF + - (otp * sizeof(uint32_t))); - -- result = bsec_check_error(otp); -- -- bsec_unlock(exc); -- -- return result; -+ return BSEC_OK; - } - - /* -@@ -231,23 +231,24 @@ uint32_t bsec_write_otp(uint32_t val, uint32_t otp) - { - uint32_t exc; - uint32_t result; -+ bool value; - -- if (otp > stm32mp_get_otp_max()) { -- return BSEC_INVALID_PARAM; -+ result = bsec_read_sw_lock(otp, &value); -+ if (result != BSEC_OK) { -+ DMSG("BSEC: %u Sticky-write bit read Error %i", otp, result); -+ return result; - } - -- /* Check if programming of OTP is locked */ -- if (bsec_read_sw_lock(otp)) { -+ if (value) { - IMSG("BSEC: OTP locked, write will be ignored"); - } - -+ /* Ensure integrity of each register access sequence */ - exc = bsec_lock(); - - write32(val, bsec_get_base() + BSEC_OTP_DATA_OFF + - (otp * sizeof(uint32_t))); - -- result = bsec_check_error(otp); -- - bsec_unlock(exc); - - return result; -@@ -264,13 +265,15 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp) - { - uint32_t result; - uint32_t exc; -+ bool value; - -- if (otp > stm32mp_get_otp_max()) { -- return BSEC_INVALID_PARAM; -+ result = bsec_read_sp_lock(otp, &value); -+ if (result != BSEC_OK) { -+ DMSG("BSEC: %u Sticky-prog bit read Error %i", otp, result); -+ return result; - } - -- /* Check if programming of OTP is locked */ -- if (bsec_read_sp_lock(otp)) { -+ if (value) { - IMSG("BSEC: OTP locked, prog will be ignored"); - } - -@@ -296,7 +299,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(exc); -@@ -350,7 +353,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(exc); -@@ -361,7 +364,7 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp) - } - - /* -- * bsec_write_debug_conf: write value in debug feature -+ * bsec_write_debug_conf: write value in debug feature. - * to enable/disable debug service. - * val: value to write. - * return value: BSEC_OK if no error. -@@ -386,7 +389,7 @@ uint32_t bsec_write_debug_conf(uint32_t val) - } - - /* -- * bsec_read_debug_conf : read debug configuration. -+ * bsec_read_debug_conf: return debug configuration register value. - */ - uint32_t bsec_read_debug_conf(void) - { -@@ -394,7 +397,7 @@ uint32_t bsec_read_debug_conf(void) - } - - /* -- * bsec_get_status : return status register value. -+ * bsec_get_status: return status register value. - */ - uint32_t bsec_get_status(void) - { -@@ -402,7 +405,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) - { -@@ -410,7 +413,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) - { -@@ -418,7 +421,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) - { -@@ -426,7 +429,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) - { -@@ -434,232 +437,177 @@ 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); - uint32_t exc; - -- exc = bsec_lock(); -- -- bank_value = read32(bsec_get_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. -- */ -- write32(bank_value, bsec_get_base() + BSEC_SRLOCK_OFF + bank); -- result = true; -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; - } - -+ exc = bsec_lock(); -+ write32(otp_mask, bsec_get_base() + BSEC_SRLOCK_OFF + bank); - bsec_unlock(exc); - -- 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 = read32(bsec_get_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 = read32(bsec_get_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; - unsigned int exc; - -- exc = bsec_lock(); -- -- bank_value = read32(bsec_get_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. -- */ -- write32(bank_value, bsec_get_base() + BSEC_SWLOCK_OFF + bank); -- result = true; -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; - } - -+ exc = bsec_lock(); -+ write32(otp_mask, bsec_get_base() + BSEC_SWLOCK_OFF + bank); - bsec_unlock(exc); - -- 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 = read32(bsec_get_base() + BSEC_SWLOCK_OFF + bank); -+ uint32_t bank_value; -+ -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ bank_value = read32(bsec_get_base() + BSEC_SWLOCK_OFF + bank); -+ *value = ((bank_value & otp_mask) != 0U); - -- return (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); - unsigned int exc; - -- exc = bsec_lock(); -- -- bank_value = read32(bsec_get_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. -- */ -- write32(bank_value, bsec_get_base() + BSEC_SPLOCK_OFF + bank); -- result = true; -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; - } - -+ exc = bsec_lock(); -+ write32(otp_mask, bsec_get_base() + BSEC_SPLOCK_OFF + bank); - bsec_unlock(exc); - -- 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 = read32(bsec_get_base() + BSEC_SPLOCK_OFF + bank); -+ uint32_t bank_value; -+ -+ if (otp > STM32MP1_OTP_MAX_ID) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ bank_value = read32(bsec_get_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 ((read32(bsec_get_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 = read32(bsec_get_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 -+ * 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. -+ * 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_get_base() + BSEC_OTP_LOCK_OFF; - - switch (service) { - case BSEC_LOCK_UPPER_OTP: -- write32(value << BSEC_LOCK_UPPER_OTP, reg); -+ write32(BIT(BSEC_LOCK_UPPER_OTP), reg); - break; - case BSEC_LOCK_DEBUG: -- write32(value << BSEC_LOCK_DEBUG, reg); -+ write32(BIT(BSEC_LOCK_DEBUG), reg); - break; - case BSEC_LOCK_PROGRAM: -- write32(value << BSEC_LOCK_PROGRAM, reg); -+ write32(BIT(BSEC_LOCK_PROGRAM), reg); - break; - default: - return BSEC_INVALID_PARAM; -@@ -703,7 +651,7 @@ static uint32_t disable_power(void) - /* - * 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 enable) - { -@@ -733,23 +681,7 @@ static uint32_t bsec_power_safmem(bool enable) - } - - /* -- * bsec_mode_is_closed_device: read OTP secure sub-mode. -- * return: false if open_device and true of closed_device. -- */ --bool bsec_mode_is_closed_device(void) --{ -- uint32_t value; -- -- if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) || -- (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) { -- return true; -- } -- -- return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED; --} -- --/* -- * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value -+ * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value. - * otp_value: read value. - * word: OTP number. - * return value: BSEC_OK if no error. -@@ -775,7 +707,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) - { -@@ -784,16 +716,13 @@ uint32_t bsec_check_nsec_access_rights(uint32_t otp) - } - - if (otp >= stm32mp_get_otp_upper_start()) { -- /* Check if BSEC is in OTP-SECURED closed_device state. */ -- if (bsec_mode_is_closed_device()) { - #ifdef CFG_DT -- if (!non_secure_can_access(otp)) { -- return BSEC_ERROR; -- } --#else -+ if (!non_secure_can_access(otp)) { - return BSEC_ERROR; --#endif - } -+#else -+ return BSEC_ERROR; -+#endif - } - - return BSEC_OK; -diff --git a/core/drivers/stm32_etzpc.c b/core/drivers/stm32_etzpc.c -index fcb32e6..daf7acb 100644 ---- a/core/drivers/stm32_etzpc.c -+++ b/core/drivers/stm32_etzpc.c -@@ -103,12 +103,12 @@ static uintptr_t etzpc_base(void) - return etzpc_dev.base; - } - --static bool valid_decprot_id(unsigned int id) -+static bool __maybe_unused valid_decprot_id(unsigned int id) - { - return id < (unsigned int)etzpc_dev.num_per_sec; - } - --static bool valid_tzma_id(unsigned int id) -+static bool __maybe_unused valid_tzma_id(unsigned int id) - { - return id < (unsigned int)etzpc_dev.num_tzma; - } -@@ -251,7 +251,6 @@ static void etzpc_suspend_resume(enum pm_op op, void __unused *handle) - - /* OP-TEE owns the whole in SYSRAM */ - etzpc_configure_tzma(1, ETZPC_TZMA_ALL_SECURE); -- etzpc_lock_tzma(1); - - for (n = 0; n < etzpc_dev.num_per_sec; n++) { - unsigned int attr = etzpc_dev.periph_cfg[n] & PERIPH_ATTR_MASK; -@@ -328,7 +327,6 @@ static TEE_Result etzpc_init(void) - - /* OP-TEE owns the whole in SYSRAM */ - etzpc_configure_tzma(1, ETZPC_TZMA_ALL_SECURE); -- etzpc_lock_tzma(1); - - stm32mp_register_pm_cb(etzpc_suspend_resume, NULL); - -diff --git a/core/drivers/stm32_i2c.c b/core/drivers/stm32_i2c.c -index f7f0f70..8ba7178 100644 ---- a/core/drivers/stm32_i2c.c -+++ b/core/drivers/stm32_i2c.c -@@ -76,18 +76,18 @@ struct i2c_timing_s { - bool is_saved; - }; - --/** -- * All these values are coming from I2C Specification, Version 6.0, 4th of -- * April 2014. -+/* -+ * I2C specification values as per version 6.0, 4th of April 2014 [1], -+ * table 10 page 48: Characteristics of the SDA and SCL bus lines for -+ * Standard, Fast, and Fast-mode Plus I2C-bus devices. - * -- * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast, -- * and Fast-mode Plus I2C-bus devices. -+ * [1] https://www.nxp.com/docs/en/user-guide/UM10204.pdf - */ - static const struct i2c_spec_s i2c_specs[] = { - [I2C_SPEED_STANDARD] = { - .rate = STANDARD_RATE, -- .rate_min = 8000, -- .rate_max = 120000, -+ .rate_min = (STANDARD_RATE * 80) / 100, -+ .rate_max = (STANDARD_RATE * 120) / 100, - .fall_max = 300, - .rise_max = 1000, - .hddat_min = 0, -@@ -98,8 +98,8 @@ static const struct i2c_spec_s i2c_specs[] = { - }, - [I2C_SPEED_FAST] = { - .rate = FAST_RATE, -- .rate_min = 320000, -- .rate_max = 480000, -+ .rate_min = (FAST_RATE * 80) / 100, -+ .rate_max = (FAST_RATE * 120) / 100, - .fall_max = 300, - .rise_max = 300, - .hddat_min = 0, -@@ -110,8 +110,8 @@ static const struct i2c_spec_s i2c_specs[] = { - }, - [I2C_SPEED_FAST_PLUS] = { - .rate = FAST_PLUS_RATE, -- .rate_min = 800000, -- .rate_max = 1200000, -+ .rate_min = (FAST_PLUS_RATE * 80) / 100, -+ .rate_max = (FAST_PLUS_RATE * 120) / 100, - .fall_max = 100, - .rise_max = 120, - .hddat_min = 0, -diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c -index b2c8a68..f1cdc1a 100644 ---- a/core/drivers/stm32_iwdg.c -+++ b/core/drivers/stm32_iwdg.c -@@ -115,6 +115,12 @@ static enum itr_return stm32_iwdg_it_handler(struct itr_handler *handler) - - stm32_clock_disable(iwdg->clock); - -+ /* -+ * Ack interrupt as we do not return from next call. -+ * And interrupt is no more considered as pending here. -+ */ -+ stm32mp_gic_set_end_of_interrupt(handler->it); -+ - stm32_cores_reset(); - - return ITRR_HANDLED; -diff --git a/core/drivers/stm32_timer.c b/core/drivers/stm32_timer.c -index be03577..a99f2d9 100644 ---- a/core/drivers/stm32_timer.c -+++ b/core/drivers/stm32_timer.c -@@ -62,6 +62,8 @@ - #define TIM_TIMEOUT_STEP_US 10 - #define TIM_PRESCAL_HSI 10U - #define TIM_PRESCAL_CSI 7U -+#define TIM_MIN_FREQ_CALIB 50000000U -+ - - struct stm32_timer_instance { - struct io_pa_va base; -@@ -92,13 +94,18 @@ static int timer_get_dt_node(void *fdt, struct dt_node_info *info, int offset) - return node; - } - --static void timer_config(struct stm32_timer_instance *timer) -+static int timer_config(struct stm32_timer_instance *timer) - { - uintptr_t base = timer_base(timer); - - stm32_clock_enable(timer->clk); - - timer->freq = stm32_clock_get_rate(timer->clk); -+ if (timer->freq < TIM_MIN_FREQ_CALIB) { -+ EMSG("Timer is not accurate enough for calibration"); -+ stm32_clock_disable(timer->clk); -+ return -1; -+ } - - if ((mmio_read_32(base + TIM_TISEL) & TIM_TISEL_TI1SEL_MASK) != - timer->cal_input) { -@@ -120,6 +127,7 @@ static void timer_config(struct stm32_timer_instance *timer) - } - - stm32_clock_disable(timer->clk); -+ return 0; - } - - static uint32_t timer_start_capture(struct stm32_timer_instance *timer) -@@ -130,7 +138,8 @@ static uint32_t timer_start_capture(struct stm32_timer_instance *timer) - int twice; - uintptr_t base = timer_base(timer); - -- timer_config(timer); -+ if (timer_config(timer) < 0) -+ return 0U; - - stm32_clock_enable(timer->clk); - -@@ -224,17 +233,23 @@ static void _init_stm32_timer(void) - timer->clk = dt_timer.clock; - timer->freq = stm32_clock_get_rate(timer->clk); - timer->cal_input = (uint8_t)fdt32_to_cpu(*cuint); -- timer_config(timer); -+ if (timer_config(timer) < 0) { -+ timer->base.pa = 0; -+ continue; -+ } - } - -- cuint = fdt_getprop(fdt, node, "st,csi_cal-input", NULL); -+ cuint = fdt_getprop(fdt, node, "st,csi-cal-input", NULL); - if (cuint != NULL) { - timer = &stm32_timer[CSI_CAL]; - timer->base.pa = dt_timer.base; - timer->clk = dt_timer.clock; - timer->freq = stm32_clock_get_rate(timer->clk); - timer->cal_input = (uint8_t)fdt32_to_cpu(*cuint); -- timer_config(timer); -+ if (timer_config(timer) < 0) { -+ timer->base.pa = 0; -+ continue; -+ } - } - } - } -diff --git a/core/drivers/stpmic1.c b/core/drivers/stpmic1.c -index 3aa3afc..3831d40 100644 ---- a/core/drivers/stpmic1.c -+++ b/core/drivers/stpmic1.c -@@ -625,20 +625,6 @@ int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) - mask); - } - --int stpmic1_regulator_pull_down_set(const char *name) --{ -- const struct regul_struct *regul = get_regulator_data(name); -- -- if (regul->pull_down_reg != 0) { -- return stpmic1_register_update(regul->pull_down_reg, -- BIT(regul->pull_down), -- LDO_BUCK_PULL_DOWN_MASK << -- regul->pull_down); -- } -- -- return 0; --} -- - int stpmic1_regulator_mask_reset_set(const char *name) - { - const struct regul_struct *regul = get_regulator_data(name); -@@ -839,7 +825,6 @@ int stpmic1_lp_voltage_cfg(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 */ -@@ -852,7 +837,7 @@ int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, - return 1; - } - -- assert(cfg->lp_reg == regul->low_power_reg); -+ assert(cfg->lp_reg == get_regulator_data(name)->low_power_reg); - cfg->value = voltage_index << 2; - cfg->mask = mask; - -diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h -index de4d20b..bd33a7b 100644 ---- a/core/include/drivers/stm32_bsec.h -+++ b/core/include/drivers/stm32_bsec.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2015-2018, STMicroelectronics -+ * Copyright (c) 2015-2019, STMicroelectronics - */ - - #ifndef __STM32_BSEC_H__ -@@ -104,7 +104,7 @@ - */ - #define BSEC_LOCK_UPPER_OTP 0x00 - #define BSEC_LOCK_DEBUG 0x02 --#define BSEC_LOCK_PROGRAM 0x03 -+#define BSEC_LOCK_PROGRAM 0x04 - - /* Values for struct bsec_config::freq */ - #define FREQ_10_20_MHZ 0x0 -@@ -127,16 +127,15 @@ uint32_t bsec_get_version(void); - uint32_t bsec_get_id(void); - uint32_t bsec_get_magic_id(void); - --bool bsec_write_sr_lock(uint32_t otp, uint32_t value); --bool bsec_read_sr_lock(uint32_t otp); --bool bsec_write_sw_lock(uint32_t otp, uint32_t value); --bool bsec_read_sw_lock(uint32_t otp); --bool bsec_write_sp_lock(uint32_t otp, uint32_t value); --bool bsec_read_sp_lock(uint32_t otp); --bool bsec_wr_lock(uint32_t otp); --uint32_t bsec_otp_lock(uint32_t service, uint32_t value); -+uint32_t bsec_set_sr_lock(uint32_t otp); -+uint32_t bsec_read_sr_lock(uint32_t otp, bool *value); -+uint32_t bsec_set_sw_lock(uint32_t otp); -+uint32_t bsec_read_sw_lock(uint32_t otp, bool *value); -+uint32_t bsec_set_sp_lock(uint32_t otp); -+uint32_t bsec_read_sp_lock(uint32_t otp, bool *value); -+uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value); -+uint32_t bsec_otp_lock(uint32_t service); - --bool bsec_mode_is_closed_device(void); - uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word); - uint32_t bsec_check_nsec_access_rights(uint32_t otp); - --- -2.7.4 - diff --git a/recipes-security/optee/optee-os/0003-st-updates-r3.patch b/recipes-security/optee/optee-os/0003-st-updates-r3.patch deleted file mode 100644 index 6f76302..0000000 --- a/recipes-security/optee/optee-os/0003-st-updates-r3.patch +++ /dev/null @@ -1,4025 +0,0 @@ -From 120829073d96f24a5cc92626675a5d591b2fa726 Mon Sep 17 00:00:00 2001 -From: Romuald JEANNE -Date: Mon, 20 Jan 2020 15:46:53 +0100 -Subject: [PATCH] st updates r3 - -Signed-off-by: Romuald JEANNE ---- - core/arch/arm/fdts/stm32mp15-ddr.dtsi | 4 +- - core/arch/arm/fdts/stm32mp157a-dk1.dts | 34 +- - core/arch/arm/fdts/stm32mp157c-ed1.dts | 51 +- - core/arch/arm/fdts/stm32mp157c-security.dtsi | 52 +- - core/arch/arm/fdts/stm32mp157c.dtsi | 38 ++ - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c | 669 ++++++++++++++++++++- - core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h | 9 +- - .../arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c | 58 +- - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c | 20 + - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h | 1 + - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c | 76 +-- - .../arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h | 7 +- - .../arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c | 97 +++ - core/arch/arm/plat-stm32mp1/drivers/sub.mk | 1 + - core/arch/arm/plat-stm32mp1/main.c | 162 ++++- - core/arch/arm/plat-stm32mp1/platform_config.h | 49 +- - core/arch/arm/plat-stm32mp1/pm/context.c | 45 +- - core/arch/arm/plat-stm32mp1/pm/low_power.c | 10 +- - core/arch/arm/plat-stm32mp1/pm/pm_helpers.S | 143 ++++- - core/arch/arm/plat-stm32mp1/pm/power_config.c | 4 +- - core/arch/arm/plat-stm32mp1/service/bsec_svc.c | 4 + - core/arch/arm/plat-stm32mp1/service/rcc_svc.c | 30 +- - core/arch/arm/plat-stm32mp1/service/rcc_svc.h | 3 +- - core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h | 16 + - .../arm/plat-stm32mp1/service/stm32mp1_svc_setup.c | 5 +- - core/arch/arm/plat-stm32mp1/stm32_util.h | 20 +- - core/arch/arm/plat-stm32mp1/stm32mp1_dt.c | 194 +++++- - core/arch/arm/plat-stm32mp1/stm32mp_dt.h | 10 +- - core/drivers/stm32_bsec.c | 188 +++++- - core/drivers/stm32_i2c.c | 232 ++++--- - core/drivers/stm32_iwdg.c | 25 +- - core/drivers/stm32_rtc.c | 39 +- - core/drivers/stpmic1.c | 25 +- - core/include/drivers/stm32_bsec.h | 13 + - core/include/drivers/stm32_i2c.h | 24 +- - core/include/drivers/stm32_iwdg.h | 6 +- - core/include/drivers/stpmic1.h | 27 +- - 37 files changed, 2030 insertions(+), 361 deletions(-) - create mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c - -diff --git a/core/arch/arm/fdts/stm32mp15-ddr.dtsi b/core/arch/arm/fdts/stm32mp15-ddr.dtsi -index 1a5c51c..d3481e5 100644 ---- a/core/arch/arm/fdts/stm32mp15-ddr.dtsi -+++ b/core/arch/arm/fdts/stm32mp15-ddr.dtsi -@@ -1,11 +1,11 @@ - // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - /* -- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved - */ - - / { - soc { -- ddr: ddr@5A003000{ -+ ddr: ddr@5a003000{ - - compatible = "st,stm32mp1-ddr"; - -diff --git a/core/arch/arm/fdts/stm32mp157a-dk1.dts b/core/arch/arm/fdts/stm32mp157a-dk1.dts -index 78cb849..b54b284 100644 ---- a/core/arch/arm/fdts/stm32mp157a-dk1.dts -+++ b/core/arch/arm/fdts/stm32mp157a-dk1.dts -@@ -21,8 +21,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; --}; -- -+ }; - }; - - &clk_hse { -@@ -34,6 +33,7 @@ - pinctrl-0 = <&i2c4_pins_a>; - i2c-scl-rising-time-ns = <185>; - i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; - status = "okay"; - - pmic: stpmic@33 { -@@ -43,10 +43,7 @@ - interrupt-controller; - #interrupt-cells = <2>; - status = "okay"; -- -- st,main-control-register = <0x04>; -- st,vin-control-register = <0xc0>; -- st,usb-control-register = <0x20>; -+ wakeup-source; - - regulators { - compatible = "st,stpmic1-regulators"; -@@ -224,6 +221,13 @@ - }; - - /* Security specific */ -+&bsec { -+ board_id: board_id@ec { -+ reg = <0xec 0x4>; -+ st,non-secure-otp; -+ }; -+}; -+ - &etzpc { - st,decprot = < - DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -@@ -240,6 +244,24 @@ - secure-status = "okay"; - }; - -+&nvmem_layout { -+ nvmem-cells = <&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>, -+ <&board_id>; -+ -+ nvmem-cell-names = "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp", -+ "board_id"; -+}; -+ - &pwr { - system_suspend_supported_soc_modes = < - STM32_PM_CSLEEP_RUN -diff --git a/core/arch/arm/fdts/stm32mp157c-ed1.dts b/core/arch/arm/fdts/stm32mp157c-ed1.dts -index 81ae94c..ff9441e 100644 ---- a/core/arch/arm/fdts/stm32mp157c-ed1.dts -+++ b/core/arch/arm/fdts/stm32mp157c-ed1.dts -@@ -30,6 +30,7 @@ - pinctrl-0 = <&i2c4_pins_a>; - i2c-scl-rising-time-ns = <185>; - i2c-scl-falling-time-ns = <20>; -+ clock-frequency = <400000>; - status = "okay"; - - pmic: stpmic@33 { -@@ -39,10 +40,7 @@ - interrupt-controller; - #interrupt-cells = <2>; - status = "okay"; -- -- st,main-control-register = <0x04>; -- st,vin-control-register = <0xc0>; -- st,usb-control-register = <0x20>; -+ wakeup-source; - - regulators { - compatible = "st,stpmic1-regulators"; -@@ -229,6 +227,13 @@ - }; - - /* Security specific */ -+&bsec { -+ board_id: board_id@ec { -+ reg = <0xec 0x4>; -+ st,non-secure-otp; -+ }; -+}; -+ - &etzpc { - st,decprot = < - DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) -@@ -245,13 +250,31 @@ - secure-status = "okay"; - }; - -+&nvmem_layout { -+ nvmem-cells = <&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>, -+ <&board_id>; -+ -+ nvmem-cell-names = "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp", -+ "board_id"; -+}; -+ - &pwr { - system_suspend_supported_soc_modes = < - STM32_PM_CSLEEP_RUN - STM32_PM_CSTOP_ALLOW_LP_STOP -+ STM32_PM_CSTOP_ALLOW_LPLV_STOP - STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR - >; -- - system_off_soc_mode = ; - }; - -@@ -267,6 +290,10 @@ - regulator-on-in-suspend; - regulator-suspend-microvolt = <1200000>; - }; -+ lplv-stop { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <900000>; -+ }; - standby-ddr-sr { - regulator-off-in-suspend; - }; -@@ -280,6 +307,10 @@ - regulator-suspend-microvolt = <1350000>; - regulator-on-in-suspend; - }; -+ lplv-stop { -+ regulator-suspend-microvolt = <1350000>; -+ regulator-on-in-suspend; -+ }; - standby-ddr-sr { - regulator-suspend-microvolt = <1350000>; - regulator-on-in-suspend; -@@ -294,6 +325,10 @@ - regulator-suspend-microvolt = <3300000>; - regulator-on-in-suspend; - }; -+ lplv-stop { -+ regulator-suspend-microvolt = <3300000>; -+ regulator-on-in-suspend; -+ }; - standby-ddr-sr { - regulator-suspend-microvolt = <3300000>; - regulator-on-in-suspend; -@@ -335,6 +370,9 @@ - lp-stop { - regulator-off-in-suspend; - }; -+ lplv-stop { -+ regulator-off-in-suspend; -+ }; - standby-ddr-sr { - regulator-off-in-suspend; - }; -@@ -374,6 +412,9 @@ - lp-stop { - regulator-on-in-suspend; - }; -+ lplv-stop { -+ regulator-on-in-suspend; -+ }; - standby-ddr-sr { - regulator-on-in-suspend; - }; -diff --git a/core/arch/arm/fdts/stm32mp157c-security.dtsi b/core/arch/arm/fdts/stm32mp157c-security.dtsi -index bff1043..5f5404f 100644 ---- a/core/arch/arm/fdts/stm32mp157c-security.dtsi -+++ b/core/arch/arm/fdts/stm32mp157c-security.dtsi -@@ -1,5 +1,5 @@ - /* -- * Copyright : STMicroelectronics 2017 -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause - */ -@@ -8,7 +8,7 @@ - - / { - soc { -- iwdg1: iwdg@5C003000 { -+ iwdg1: watchdog@5c003000 { - compatible = "st,stm32mp1-iwdg"; - reg = <0x5C003000 0x400>; - clocks = <&rcc IWDG1>, <&rcc CK_LSI>; -@@ -18,7 +18,7 @@ - secure-status = "disabled"; - }; - -- etzpc: etzpc@5C007000 { -+ etzpc: etzpc@5c007000 { - compatible = "st,stm32-etzpc"; - reg = <0x5C007000 0x400>; - clocks = <&rcc TZPC>; -@@ -26,23 +26,53 @@ - secure-status = "okay"; - }; - -- stgen: stgen@5C008000 { -+ stgen: stgen@5c008000 { - compatible = "st,stm32-stgen"; - reg = <0x5C008000 0x1000>; - }; -+ -+ nvmem_layout: nvmem_layout@0 { -+ compatible = "st,stm32-nvmem-layout"; -+ -+ nvmem-cells = <&part_number_otp>, -+ <&monotonic_otp>, -+ <&nand_otp>, -+ <&uid_otp>, -+ <&package_otp>, -+ <&hw2_otp>; -+ -+ nvmem-cell-names = "part_number_otp", -+ "monotonic_otp", -+ "nand_otp", -+ "uid_otp", -+ "package_otp", -+ "hw2_otp"; -+ }; - }; - }; - - &bsec { -- mac_addr: mac_addr@e4 { -- reg = <0xe4 0x6>; -+ part_number_otp: part_number_otp@4 { -+ reg = <0x4 0x1>; - }; -- /* Spare field to align on 32-bit OTP granularity */ -- spare_ns_ea: spare_ns_ea@ea { -- reg = <0xea 0x2>; -+ monotonic_otp: monotonic_otp@10 { -+ reg = <0x10 0x4>; - }; -- board_id: board_id@ec { -- reg = <0xec 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>; -+ }; -+ mac_addr: mac_addr@e4 { -+ reg = <0xe4 0x8>; -+ st,non-secure-otp; - }; - }; - -diff --git a/core/arch/arm/fdts/stm32mp157c.dtsi b/core/arch/arm/fdts/stm32mp157c.dtsi -index 06c2cf1..13125b1 100644 ---- a/core/arch/arm/fdts/stm32mp157c.dtsi -+++ b/core/arch/arm/fdts/stm32mp157c.dtsi -@@ -290,6 +290,27 @@ - status = "disabled"; - }; - -+ usbphyc: usbphyc@5a006000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #clock-cells = <0>; -+ compatible = "st,stm32mp1-usbphyc"; -+ reg = <0x5a006000 0x1000>; -+ clocks = <&rcc USBPHY_K>; -+ resets = <&rcc USBPHY_R>; -+ status = "disabled"; -+ -+ usbphyc_port0: usb-phy@0 { -+ #phy-cells = <0>; -+ reg = <0>; -+ }; -+ -+ usbphyc_port1: usb-phy@1 { -+ #phy-cells = <1>; -+ reg = <1>; -+ }; -+ }; -+ - usart1: serial@5c000000 { - compatible = "st,stm32h7-uart"; - reg = <0x5c000000 0x400>; -@@ -367,5 +388,22 @@ - compatible = "simple-bus", "syscon", "simple-mfd"; - reg = <0x5c00a000 0x400>; - }; -+ -+ cpu_opp_table: cpu0-opp-table { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-650000000 { -+ opp-hz = /bits/ 64 <650000000>; -+ opp-microvolt = <1200000>; -+ opp-supported-hw = <0x1>; -+ }; -+ -+ opp-800000000 { -+ opp-hz = /bits/ 64 <800000000>; -+ opp-microvolt = <1350000>; -+ opp-supported-hw = <0x2>; -+ }; -+ }; - }; - }; -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -index 69c3c74..5a02de1 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause - /* -- * Copyright (C) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2017-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -33,6 +33,22 @@ - #endif - - #define CLKSRC_TIMEOUT_US 200000U -+#define PLLRDY_TIMEOUT_US 200000U -+ -+/* 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 -+ -+#define PLL1_SETTINGS_VALID_ID 0x504C4C31 /* "PLL1" */ - - enum stm32mp1_parent_id { - /* Oscillators are defined in enum stm32mp_osc_id */ -@@ -191,6 +207,15 @@ struct stm32mp1_clk_pll { - enum stm32mp_osc_id refclk[REFCLK_SIZE]; - }; - -+/* Compact structure of 32bit cells, copied raw when suspending */ -+struct __attribute__((__packed__)) 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 not set/clr register access */ - #define _CLK_SELEC(off, b, idx, s) \ - { \ -@@ -364,6 +389,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { - _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), - _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), - _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), -+ _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 0, MDMA, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 5, GPU, _UNKNOWN_SEL), - _CLK_SC_FIXED(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK), -@@ -447,6 +473,20 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { - _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), - }; - -+/* Define characteristics of PLL according type */ -+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, -+ }, -+}; -+ - /* PLLNCFGR2 register divider by output */ - static const uint8_t pllncfgr2[_DIV_NB] = { - [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, -@@ -491,7 +531,7 @@ static const uint8_t stm32mp1_axi_div[8] = { - 1, 2, 3, 4, 4, 4, 4, 4 - }; - --#if TRACE_LEVEL >= TRACE_DEBUG -+#if TRACE_LEVEL >= TRACE_FLOW - static const char *const __maybe_unused stm32mp1_clk_parent_name[_PARENT_NB] = { - [_HSI] = "HSI", - [_HSE] = "HSE", -@@ -534,6 +574,8 @@ static const char *const __maybe_unused stm32mp1_clk_parent_name[_PARENT_NB] = { - static unsigned long stm32mp1_osc[NB_OSC]; - static unsigned int gate_refcounts[NB_GATES]; - static unsigned int refcount_lock; -+static struct stm32mp1_pll_settings pll1_settings; -+static uint32_t current_opp_khz; - - static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) - { -@@ -606,6 +648,155 @@ static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) - return (enum stm32mp1_parent_id)gate_ref(i)->fixed; - } - -+static void pll_start(enum stm32mp1_pll_id pll_id) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t pllxcr = stm32_rcc_base() + pll->pllxcr; -+ -+ mmio_clrsetbits_32(pllxcr, -+ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | -+ RCC_PLLNCR_DIVREN, -+ RCC_PLLNCR_PLLON); -+} -+ -+static int pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t pllxcr = stm32_rcc_base() + pll->pllxcr; -+ uint64_t start; -+ -+ start = utimeout_init(PLLRDY_TIMEOUT_US); -+ /* Wait PLL lock */ -+ while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { -+ if (utimeout_elapsed(PLLRDY_TIMEOUT_US, start)) { -+ EMSG("PLL%d start failed @ 0x%"PRIx32": 0x%"PRIx32, -+ pll_id, pllxcr, mmio_read_32(pllxcr)); -+ return -1; -+ } -+ } -+ -+ /* Start the requested output */ -+ mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); -+ -+ return 0; -+} -+ -+static int pll_stop(enum stm32mp1_pll_id pll_id) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t pllxcr = stm32_rcc_base() + pll->pllxcr; -+ uint64_t start; -+ -+ /* Stop all output */ -+ mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | -+ RCC_PLLNCR_DIVREN); -+ -+ /* Stop PLL */ -+ mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); -+ -+ start = utimeout_init(PLLRDY_TIMEOUT_US); -+ /* Wait PLL stopped */ -+ while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { -+ if (utimeout_elapsed(PLLRDY_TIMEOUT_US, start)) { -+ EMSG("PLL%d stop failed @ 0x%"PRIx32": 0x%"PRIx32, -+ pll_id, pllxcr, mmio_read_32(pllxcr)); -+ -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+static uint32_t pll_compute_pllxcfgr2(uint32_t *pllcfg) -+{ -+ uint32_t value; -+ -+ value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & -+ RCC_PLLNCFGR2_DIVP_MASK; -+ value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & -+ RCC_PLLNCFGR2_DIVQ_MASK; -+ value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & -+ RCC_PLLNCFGR2_DIVR_MASK; -+ -+ return value; -+} -+ -+static void 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 = stm32_rcc_base(); -+ uint32_t value; -+ -+ value = pll_compute_pllxcfgr2(pllcfg); -+ -+ mmio_write_32(rcc_base + pll->pllxcfgr2, value); -+} -+ -+static int pll_compute_pllxcfgr1(const struct stm32mp1_clk_pll *pll, -+ uint32_t *pllcfg, uint32_t *cfgr1) -+{ -+ uint32_t rcc_base = stm32_rcc_base(); -+ enum stm32mp1_plltype type = pll->plltype; -+ unsigned long refclk; -+ uint32_t ifrge = 0; -+ uint32_t src; -+ -+ src = mmio_read_32(rcc_base + pll->rckxselr) & -+ RCC_SELR_REFCLK_SRC_MASK; -+ -+ refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / -+ (pllcfg[PLLCFG_M] + 1U); -+ -+ if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || -+ (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { -+ return -1; -+ } -+ -+ if ((type == PLL_800) && (refclk >= 8000000U)) { -+ ifrge = 1U; -+ } -+ -+ *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 pll_config(enum stm32mp1_pll_id pll_id, uint32_t *pllcfg, -+ uint32_t fracv) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); -+ uint32_t rcc_base = stm32_rcc_base(); -+ uint32_t value; -+ int ret; -+ -+ ret = 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 = mmio_read_32(rcc_base + pll->pllxfracr); -+ mmio_write_32(rcc_base + pll->pllxfracr, value | RCC_PLLNFRACR_FRACLE); -+ -+ pll_config_output(pll_id, pllcfg); -+ -+ return 0; -+} -+ - static int stm32mp1_set_clksrc(unsigned int clksrc) - { - uintptr_t address = stm32_rcc_base() + (clksrc >> 4); -@@ -617,7 +808,7 @@ static int stm32mp1_set_clksrc(unsigned int clksrc) - timeout_ref = utimeout_init(CLKSRC_TIMEOUT_US); - while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) { - if (utimeout_elapsed(CLKSRC_TIMEOUT_US, timeout_ref)) { -- EMSG("CLKSRC %x start failed @ 0x%x: 0x%x\n", -+ EMSG("CLKSRC %x start failed @%"PRIxPTR": 0x%"PRIx32"\n", - clksrc, address, mmio_read_32(address)); - return -1; - } -@@ -1085,6 +1276,274 @@ unsigned long stm32mp1_clk_get_rate(unsigned long id) - } - - #ifdef CFG_DT -+static int clk_compute_pll1_settings(unsigned long input_freq, int idx) -+{ -+ unsigned long post_divm; -+ unsigned long long output_freq = pll1_settings.freq[idx] * 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 */ -+ pll1_settings.cfg[idx][PLLCFG_Q] = 0; -+ pll1_settings.cfg[idx][PLLCFG_R] = 0; -+ pll1_settings.cfg[idx][PLLCFG_O] = PQR(1, 0, 0); -+ -+ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) { -+ post_divm = input_freq / (unsigned long)(divm + 1); -+ -+ if ((post_divm < POST_DIVM_MIN) || -+ (post_divm > POST_DIVM_MAX)) { -+ continue; -+ } -+ -+ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { -+ -+ freq = output_freq * (divm + 1) * (divp + 1); -+ -+ divn = (int)((freq / input_freq) - 1); -+ if ((divn < DIVN_MIN) || (divn > DIVN_MAX)) { -+ continue; -+ } -+ -+ frac = (int)(((freq * FRAC_MAX) / input_freq) - -+ ((divn + 1) * FRAC_MAX)); -+ -+ /* 2 loops to refine the fractional part */ -+ for (i = 2; i != 0; i--) { -+ if (frac > FRAC_MAX) { -+ break; -+ } -+ -+ vco = (post_divm * (divn + 1)) + -+ ((post_divm * (unsigned long long)frac) / -+ FRAC_MAX); -+ -+ if ((vco < (VCO_MIN / 2)) || -+ (vco > (VCO_MAX / 2))) { -+ frac++; -+ continue; -+ } -+ -+ freq = vco / (divp + 1); -+ if (output_freq < freq) { -+ diff = (unsigned int)(freq - -+ output_freq); -+ } else { -+ diff = (unsigned int)(output_freq - -+ freq); -+ } -+ -+ if (diff < best_diff) { -+ pll1_settings.cfg[idx][PLLCFG_M] = divm; -+ pll1_settings.cfg[idx][PLLCFG_N] = divn; -+ pll1_settings.cfg[idx][PLLCFG_P] = divp; -+ pll1_settings.frac[idx] = 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, int index) -+{ -+ unsigned long input_freq; -+ unsigned int i; -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if (pll1_settings.freq[i] == pll1_settings.freq[index]) { -+ break; -+ } -+ } -+ -+ if (((i == PLAT_MAX_OPP_NB) && -+ !stm32mp1_clk_pll1_settings_are_valid()) || -+ ((i < PLAT_MAX_OPP_NB) && -+ (pll1_settings.cfg[i][PLLCFG_O] == 0U))) { -+ /* -+ * Either PLL1 settings structure is completely empty, -+ * or these settings are not yet computed: do it. -+ */ -+ switch (clksrc) { -+ case CLK_PLL12_HSI: -+ input_freq = stm32mp1_clk_get_rate(CK_HSI); -+ break; -+ case CLK_PLL12_HSE: -+ input_freq = stm32mp1_clk_get_rate(CK_HSE); -+ break; -+ default: -+ panic(); -+ } -+ -+ return clk_compute_pll1_settings(input_freq, index); -+ } -+ -+ 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(&pll1_settings.cfg[index][0], &pll1_settings.cfg[i][0], -+ sizeof(uint32_t) * PLAT_MAX_PLLCFG_NB); -+ pll1_settings.frac[index] = pll1_settings.frac[i]; -+ -+ return 0; -+ } -+ -+ return -1; -+} -+ -+static int clk_save_current_pll1_settings(uint32_t buck1_voltage) -+{ -+ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1); -+ uint32_t rcc_base = stm32_rcc_base(); -+ uint32_t freq; -+ unsigned int i; -+ -+ freq = UDIV_ROUND_NEAREST(stm32mp1_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 = stm32_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) -+{ -+ unsigned int i; -+ int ret; -+ int index; -+ uint32_t count = PLAT_MAX_OPP_NB; -+ uint32_t clksrc; -+ void *fdt; -+ -+ fdt = get_dt_blob(); -+ if (fdt == NULL) { -+ panic(); -+ } -+ -+ ret = fdt_get_all_opp_freqvolt(fdt, &count, pll1_settings.freq, -+ pll1_settings.volt); -+ switch (ret) { -+ case 0: -+ break; -+ case -FDT_ERR_NOTFOUND: -+ DMSG("Cannot find all OPP info in DT: use default settings"); -+ return 0; -+ default: -+ EMSG("Inconsistent OPP settings found in DT, ignored."); -+ return 0; -+ } -+ -+ index = clk_save_current_pll1_settings(buck1_voltage); -+ -+ clksrc = stm32mp1_clk_get_pll1_current_clksrc(); -+ -+ for (i = 0; i < count; i++) { -+ if ((index >= 0) && (i == (unsigned int)index)) -+ continue; -+ -+ ret = clk_get_pll1_settings(clksrc, i); -+ if (ret) -+ 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)) || -+ !stm32mp1_clk_pll1_settings_are_valid()) { -+ panic(); -+ } -+ -+ memcpy(data, &pll1_settings, size); -+} -+ -+bool stm32mp1_clk_pll1_settings_are_valid(void) -+{ -+ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID; -+} -+ - static void stm32mp1_osc_clk_init(const char *name, - enum stm32mp_osc_id index) - { -@@ -1113,6 +1572,21 @@ static void stm32mp1_osc_init(void) - DMSG("Osc %s frequency: %lu", name[i], stm32mp1_osc[i]); - } - } -+#else /* CFG_DT */ -+int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage __unused) -+{ -+ return 0; -+} -+ -+void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data __unused, -+ size_t size __unused) -+{ -+} -+ -+bool stm32mp1_clk_pll1_settings_are_valid(void) -+{ -+ return false; -+} - #endif - - /* -@@ -1508,16 +1982,187 @@ static void sync_earlyboot_clocks_state(void) - stm32mp_register_clock_parents_secure(BKPSRAM); - - stm32mp_register_clock_parents_secure(RTCAPB); -- --#if CFG_TEE_CORE_NB_CORE > 1 - stm32mp1_clk_enable_secure(RTCAPB); --#endif - - /* The low power sequences mandates RNG1 and CRYP1 support */ - stm32mp_register_clock_parents_secure(RNG1_K); - stm32mp_register_clock_parents_secure(CRYP1); - } - -+/* -+ * 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 as those in place, no need to reconfig. -+ * Return value is 0 if no error. -+ */ -+static int 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 = stm32_rcc_base(); -+ uint32_t fracr; -+ uint32_t value; -+ int ret; -+ -+ ret = pll_compute_pllxcfgr1(pll, pllcfg, &value); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { -+ /* Different DIVN/DIVM, can't config on the fly */ -+ *result = -1; -+ return 0; -+ } -+ -+ fracr = fracv << RCC_PLLNFRACR_FRACV_SHIFT; -+ fracr |= RCC_PLLNFRACR_FRACLE; -+ value = pll_compute_pllxcfgr2(pllcfg); -+ -+ if ((mmio_read_32(rcc_base + pll->pllxfracr) == fracr) && -+ (mmio_read_32(rcc_base + pll->pllxcfgr2) == value)) { -+ /* Same parameters, no need to config */ -+ *result = 1; -+ } else { -+ *result = 0; -+ } -+ -+ return 0; -+} -+ -+/* Configure PLL1 from input frequency OPP parameters */ -+static int pll1_config_from_opp_khz(uint32_t freq_khz) -+{ -+ unsigned int i; -+ int ret; -+ int config_on_the_fly = -1; -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if (pll1_settings.freq[i] == freq_khz) { -+ break; -+ } -+ } -+ -+ if (i == PLAT_MAX_OPP_NB) { -+ return -1; -+ } -+ -+ ret = is_pll_config_on_the_fly(_PLL1, &pll1_settings.cfg[i][0], -+ pll1_settings.frac[i], -+ &config_on_the_fly); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (config_on_the_fly == 1) { -+ /* No need to reconfig, setup already OK */ -+ return 0; -+ } -+ -+ if (config_on_the_fly == -1) { -+ /* Switch to HSI and stop PLL1 before reconfiguration */ -+ ret = stm32mp1_set_clksrc(CLK_MPU_HSI); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = pll_stop(_PLL1); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ -+ ret = pll_config(_PLL1, &pll1_settings.cfg[i][0], -+ pll1_settings.frac[i]); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (config_on_the_fly == -1) { -+ /* Start PLL1 and switch back to after reconfiguration */ -+ pll_start(_PLL1); -+ -+ ret = pll_output(_PLL1, pll1_settings.cfg[i][PLLCFG_O]); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P); -+ if (ret != 0) { -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+int stm32mp1_set_opp_khz(uint32_t freq_khz) -+{ -+ if (freq_khz == current_opp_khz) { -+ /* OPP already set, nothing to do */ -+ return 0; -+ } -+ -+ if (!stm32mp1_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 -1; -+ } -+ -+ /* Check that PLL1 (without MPUDIV) is MPU clock source */ -+ if (((mmio_read_32(stm32_rcc_base() + RCC_MPCKSELR) & -+ RCC_SELR_SRC_MASK)) != RCC_MPCKSELR_PLL) { -+ return -1; -+ } -+ -+ if (pll1_config_from_opp_khz(freq_khz) != 0) { -+ /* Restore original value */ -+ if (pll1_config_from_opp_khz(current_opp_khz) != 0) { -+ EMSG("No CPU operating point can be set"); -+ panic(); -+ } -+ -+ return -1; -+ } -+ -+ current_opp_khz = freq_khz; -+ -+ return 0; -+} -+ -+int stm32mp1_round_opp_khz(uint32_t *freq_khz) -+{ -+ unsigned int i; -+ uint32_t round_opp = 0U; -+ -+ if (!stm32mp1_clk_pll1_settings_are_valid()) { -+ /* -+ * No OPP table in DT, or an error occurred during PLL1 -+ * settings computation, system can only work on current -+ * operating point, so return current CPU frequency. -+ */ -+ *freq_khz = current_opp_khz; -+ -+ return 0; -+ } -+ -+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) { -+ if ((pll1_settings.freq[i] <= *freq_khz) && -+ (pll1_settings.freq[i] > round_opp)) { -+ round_opp = pll1_settings.freq[i]; -+ } -+ } -+ -+ *freq_khz = round_opp; -+ -+ return 0; -+} -+ - static void _clock_mpu_suspend(void) - { - uintptr_t mpckselr = stm32_rcc_base() + RCC_MPCKSELR; -@@ -1582,10 +2227,22 @@ void stm32mp_clock_suspend_resume(enum pm_op op) - - static TEE_Result stm32mp1_clk_probe(void) - { -+ unsigned long freq_khz; -+ -+ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB); -+ - init_clock_tree_from_dt(); - - sync_earlyboot_clocks_state(); - -+ /* Save current CPU operating point value */ -+ freq_khz = UDIV_ROUND_NEAREST(stm32mp1_clk_get_rate(CK_MPU), 1000UL); -+ if (freq_khz > (unsigned long)UINT32_MAX) { -+ panic(); -+ } -+ -+ current_opp_khz = (uint32_t)freq_khz; -+ - return TEE_SUCCESS; - } - /* Setup clock support before driver initialization */ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h -index 783d81d..26fda3d 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clk.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved - */ - - #ifndef __STM32MP1_CLK_H__ -@@ -22,6 +22,10 @@ enum stm32mp_osc_id { - _UNKNOWN_OSC_ID = 0xFF - }; - -+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); -+bool stm32mp1_clk_pll1_settings_are_valid(void); -+ - void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); - void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); - bool stm32mp1_clk_is_enabled(unsigned long id); -@@ -56,6 +60,9 @@ void stm32mp_register_clock_parents_secure(unsigned long id); - - void stm32mp_update_earlyboot_clocks_state(void); - -+int stm32mp1_set_opp_khz(uint32_t freq_khz); -+int stm32mp1_round_opp_khz(uint32_t *freq_khz); -+ - void stm32mp1_clock_suspend(void); - void stm32mp1_clock_resume(void); - -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c -index c83d561..ea57c9a 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_clkfunc.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -55,6 +55,11 @@ int fdt_osc_read_freq(void *fdt, const char *name, uint32_t *freq) - if (strncmp(cchar, name, (size_t)ret) == 0) { - const fdt32_t *cuint; - -+ if (_fdt_get_status(fdt, subnode) == -+ DT_STATUS_DISABLED) { -+ goto exit; -+ } -+ - cuint = fdt_getprop(fdt, subnode, "clock-frequency", - &ret); - if (cuint == NULL) { -@@ -67,7 +72,8 @@ int fdt_osc_read_freq(void *fdt, const char *name, uint32_t *freq) - } - } - -- /* Oscillator not found, freq=0 */ -+exit: -+ /* Oscillator not found or disabled, freq=0 */ - *freq = 0; - return 0; - } -@@ -196,7 +202,7 @@ uint32_t fdt_rcc_read_addr(void *fdt) - ******************************************************************************/ - int fdt_get_rcc_node(void *fdt) - { -- return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -+ return fdt_get_node_by_compatible(fdt, DT_RCC_CLK_COMPAT); - } - - /******************************************************************************* -@@ -272,8 +278,6 @@ const fdt32_t *fdt_rcc_read_prop(void *fdt, const char *prop_name, int *lenp) - ******************************************************************************/ - uintptr_t get_stgen_base(void) - { -- int node; -- const fdt32_t *cuint; - void *fdt; - - fdt = get_dt_blob(); -@@ -281,17 +285,7 @@ uintptr_t get_stgen_base(void) - return 0; - } - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); -- if (node < 0) { -- return 0; -- } -- -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) { -- return 0; -- } -- -- return fdt32_to_cpu(*cuint); -+ return fdt_get_peripheral_base(fdt, DT_STGEN_COMPAT); - } - - /******************************************************************************* -@@ -305,36 +299,22 @@ unsigned long get_uart_clock_freq(uint32_t instance) - { - int node; - void *fdt; -+ int clk_id; - - fdt = get_dt_blob(); - if (fdt == NULL) { - return 0; - } - -- /* Check for UART nodes */ -- node = fdt_node_offset_by_compatible(fdt, -1, DT_UART_COMPAT); -- while (node != -FDT_ERR_NOTFOUND) { -- const fdt32_t *cuint; -- -- cuint = fdt_getprop(fdt, node, "reg", NULL); -- if (cuint == NULL) -- goto next; -- -- if ((uint32_t)fdt32_to_cpu(*cuint) == instance) { -- unsigned long clk_id; -- -- cuint = fdt_getprop(fdt, node, "clocks", NULL); -- if (cuint == NULL) -- goto next; -- -- cuint++; -- clk_id = (unsigned long)(fdt32_to_cpu(*cuint)); -+ node = fdt_match_instance_by_compatible(fdt, DT_UART_COMPAT, instance); -+ if (node < 0) { -+ return 0; -+ } - -- return stm32mp1_clk_get_rate(clk_id); -- } --next: -- node = fdt_node_offset_by_compatible(fdt, node, DT_UART_COMPAT); -+ clk_id = fdt_get_clock_id(fdt, node); -+ if (clk_id < 0) { -+ return 0; - } - -- return 0; -+ return stm32mp1_clk_get_rate((unsigned long)clk_id); - } -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c -index 03ded28..8bb2635 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.c -@@ -102,6 +102,14 @@ static void do_sw_ack(void) - } - } - -+static bool ddr_supports_ssr_asr(void) -+{ -+ uintptr_t ddrctrl_base = get_ddrctrl_base(); -+ uint32_t mstr = mmio_read_32(ddrctrl_base + DDRCTRL_MSTR); -+ -+ return (mstr & DDRCTRL_MSTR_LPDDR2) != 0U; -+} -+ - static int ddr_sw_self_refresh_in(void) - { - uint64_t to_ref; -@@ -177,6 +185,9 @@ static int ddr_sw_self_refresh_in(void) - DDRPHYC_ACIOCR_CSPDD_MASK, - DDRPHYC_ACIOCR_CSPDD_0); - -+ /* Disable command/address output driver */ -+ mmio_clrbits_32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); -+ - mmio_setbits_32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD); - - mmio_setbits_32(ddrphy_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR); -@@ -321,6 +332,9 @@ int ddr_sw_self_refresh_exit(void) - /* Enable pad drivers */ - mmio_clrbits_32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD); - -+ /* Enable command/address output driver */ -+ mmio_setbits_32(ddrphy_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE); -+ - mmio_clrbits_32(ddrphy_base + DDRPHYC_ACIOCR, - DDRPHYC_ACIOCR_CKPDD_MASK); - -@@ -398,6 +412,9 @@ void ddr_sr_mode_ssr(void) - uintptr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; - uintptr_t ddrctrl_base = get_ddrctrl_base(); - -+ if (!ddr_supports_ssr_asr()) -+ return; -+ - mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); - - mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN); -@@ -446,6 +463,9 @@ void ddr_sr_mode_asr(void) - uintptr_t rcc_ddritfcr = stm32_rcc_base() + RCC_DDRITFCR; - uintptr_t ddrctrl_base = get_ddrctrl_base(); - -+ if (!ddr_supports_ssr_asr()) -+ return; -+ - mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN); - - mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN); -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h -index 59014b4..4afa313 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_ddrc.h -@@ -162,6 +162,7 @@ - #define DDRPHYC_PTR0_TITMSRST_OFFSET 18 - #define DDRPHYC_PTR0_TITMSRST_MASK GENMASK_32(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_32(10, 8) -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -index f2b7fe1..82225bd 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -23,15 +23,6 @@ - #include - #include - --#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK_32(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 MODE_STANDBY 8U - - #define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 -@@ -46,10 +37,28 @@ bool stm32mp_with_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_get_node_by_compatible(fdt, "st,stpmic1"); -+ } -+ -+ return node; -+} -+ -+static int dt_get_regulators_node(void *fdt) -+{ -+ int node; -+ -+ node = dt_get_pmic_node(fdt); -+ if (node < 0) { -+ panic(); -+ } -+ -+ return fdt_subnode_offset(fdt, node, "regulators"); - } - --static int dt_pmic_status(void) -+int stm32mp_dt_pmic_status(void) - { - void *fdt = get_dt_blob(); - -@@ -66,7 +75,7 @@ static int dt_pmic_status(void) - - static bool dt_pmic_is_secure(void) - { -- int status = dt_pmic_status(); -+ int status = stm32mp_dt_pmic_status(); - - return ((unsigned)status == DT_STATUS_OK_SEC) && - (i2c_handle.dt_status == DT_STATUS_OK_SEC); -@@ -92,7 +101,7 @@ static size_t regu_bo_count; - - static int save_boot_on_config(void) - { -- int pmic_node, regulators_node, regulator_node; -+ int regulators_node, subnode; - void *fdt; - - assert(!regu_bo_config && !regu_bo_count); -@@ -102,42 +111,40 @@ static int save_boot_on_config(void) - panic(); - } - -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- panic(); -- } -- -- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ regulators_node = dt_get_regulators_node(fdt); - -- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -+ fdt_for_each_subnode(subnode, fdt, regulators_node) { - const fdt32_t *cuint; - const char *name; - struct regu_bo_config regu_cfg; - uint16_t mv; - -- if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", -- NULL) == NULL) { -+ if ((fdt_getprop(fdt, subnode, "regulator-boot-on", NULL) == -+ NULL) && -+ (fdt_getprop(fdt, subnode, "regulator-always-on", NULL) == -+ NULL)) { - continue; - } - - memset(®u_cfg, 0, sizeof(regu_cfg)); -- name = fdt_get_name(fdt, regulator_node, NULL); -+ name = fdt_get_name(fdt, subnode, NULL); - - regu_cfg.flags |= REGU_BO_FLAG_ENABLE_REGU; -+ stpmic1_bo_enable_cfg(name, ®u_cfg.cfg); - -- if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", -+ if (fdt_getprop(fdt, subnode, "regulator-pull-down", - NULL) != NULL) { - stpmic1_bo_pull_down_cfg(name, ®u_cfg.cfg); - regu_cfg.flags |= REGU_BO_FLAG_PULL_DOWN; - } - -- if (fdt_getprop(fdt, regulator_node, "st,mask-reset", -+ if (fdt_getprop(fdt, subnode, "st,mask-reset", - NULL) != NULL) { - stpmic1_bo_mask_reset_cfg(name, ®u_cfg.cfg); - regu_cfg.flags |= REGU_BO_FLAG_MASK_RESET; - } - -- cuint = fdt_getprop(fdt, regulator_node, -+ cuint = fdt_getprop(fdt, subnode, - "regulator-min-microvolt", NULL); - if (cuint != NULL) { - /* DT uses microvolts, whereas driver awaits millivolts */ -@@ -246,7 +253,7 @@ static unsigned int regu_lp_state2idx(const char *name) - - static int save_low_power_config(const char *lp_state) - { -- int pmic_node, regulators_node, regulator_node; -+ int regulators_node, subnode; - void *fdt; - unsigned int state_idx = regu_lp_state2idx(lp_state); - struct regu_lp_state *state = ®u_lp_state[state_idx]; -@@ -258,14 +265,9 @@ static int save_low_power_config(const char *lp_state) - panic(); - } - -- pmic_node = dt_get_pmic_node(fdt); -- if (pmic_node < 0) { -- return -FDT_ERR_NOTFOUND; -- } -- -- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); -+ regulators_node = dt_get_regulators_node(fdt); - -- fdt_for_each_subnode(regulator_node, fdt, regulators_node) { -+ fdt_for_each_subnode(subnode, fdt, regulators_node) { - const fdt32_t *cuint; - const char *reg_name; - int regulator_state_node; -@@ -282,7 +284,7 @@ static int save_low_power_config(const char *lp_state) - - memset(regu_cfg, 0, sizeof(*regu_cfg)); - -- reg_name = fdt_get_name(fdt, regulator_node, NULL); -+ reg_name = fdt_get_name(fdt, subnode, NULL); - - if (stpmic1_lp_cfg(reg_name, ®u_cfg->cfg) != 0) { - EMSG("Invalid regu name %s", reg_name); -@@ -298,7 +300,7 @@ static int save_low_power_config(const char *lp_state) - - /* Then apply configs from regulator_state_node */ - regulator_state_node = fdt_subnode_offset(fdt, -- regulator_node, -+ subnode, - lp_state); - if (regulator_state_node <= 0) { - continue; -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -index 01f15fd..4d26e70 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - */ - - #ifndef __STM32MP1_PMIC_H__ -@@ -13,6 +13,7 @@ void stm32mp_pmic_apply_boot_on_config(void); - void stm32mp_pmic_apply_lp_config(const char *lp_state); - void stm32mp_get_pmic(void); - void stm32mp_put_pmic(void); -+int stm32mp_dt_pmic_status(void); - #else - static inline void stm32mp_pmic_apply_boot_on_config(void) - { -@@ -28,6 +29,10 @@ static inline void stm32mp_put_pmic(void) - { - panic(); - } -+static inline int stm32mp_dt_pmic_status(void) -+{ -+ return -1; -+} - #endif - - #endif /*__STM32MP1_PMIC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c -new file mode 100644 -index 0000000..ccc5352 ---- /dev/null -+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c -@@ -0,0 +1,97 @@ -+// SPDX-License-Identifier: BSD-3-Clause -+/* -+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * SYSCFG register offsets (base relative) -+ */ -+#define SYSCFG_CMPCR 0x20U -+#define SYSCFG_CMPENSETR 0x24U -+ -+/* -+ * SYSCFG_CMPCR Register -+ */ -+#define SYSCFG_CMPCR_SW_CTRL BIT(1) -+#define SYSCFG_CMPCR_READY BIT(8) -+#define SYSCFG_CMPCR_RANSRC GENMASK_32(19, 16) -+#define SYSCFG_CMPCR_RANSRC_SHIFT 16 -+#define SYSCFG_CMPCR_RAPSRC GENMASK_32(23, 20) -+#define SYSCFG_CMPCR_ANSRC_SHIFT 24 -+ -+#define SYSCFG_CMPCR_READY_TIMEOUT_US 1000U -+ -+/* -+ * SYSCFG_CMPENSETR Register -+ */ -+#define SYSCFG_CMPENSETR_MPU_EN BIT(0) -+ -+void stm32mp1_syscfg_enable_io_compensation(void) -+{ -+ uintptr_t syscfg_base = stm32_get_syscfg_base(); -+ uint64_t start; -+ -+ /* -+ * Activate automatic I/O compensation. -+ * Warning: need to ensure CSI enabled and ready in clock driver. -+ * Enable non-secure clock, we assume non-secure is suspended. -+ */ -+ stm32mp1_clk_enable_non_secure(SYSCFG); -+ -+ mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR, -+ SYSCFG_CMPENSETR_MPU_EN); -+ -+ start = utimeout_init(SYSCFG_CMPCR_READY_TIMEOUT_US); -+ -+ while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & -+ SYSCFG_CMPCR_READY) == 0U) { -+ if (utimeout_elapsed(SYSCFG_CMPCR_READY_TIMEOUT_US, start)) { -+ EMSG("IO compensation cell not ready"); -+ break; -+ } -+ } -+ -+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); -+ -+ DMSG("[0x%"PRIxPTR"] SYSCFG.cmpcr = 0x%"PRIx32, -+ syscfg_base + SYSCFG_CMPCR, -+ mmio_read_32(syscfg_base + SYSCFG_CMPCR)); -+} -+ -+void stm32mp1_syscfg_disable_io_compensation(void) -+{ -+ uintptr_t syscfg_base = stm32_get_syscfg_base(); -+ uint32_t value; -+ -+ /* -+ * Deactivate automatic I/O compensation. -+ * Warning: CSI is disabled automatically in STOP if not -+ * requested for other usages and always OFF in STANDBY. -+ * Disable non-secure SYSCFG clock, we assume non-secure is suspended. -+ */ -+ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >> -+ SYSCFG_CMPCR_ANSRC_SHIFT; -+ -+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, -+ SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); -+ -+ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) | -+ (value << SYSCFG_CMPCR_RANSRC_SHIFT); -+ -+ mmio_write_32(syscfg_base + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); -+ -+ DMSG("[0x%"PRIxPTR"] SYSCFG.cmpcr = 0x%"PRIx32, -+ syscfg_base + SYSCFG_CMPCR, -+ mmio_read_32(syscfg_base + SYSCFG_CMPCR)); -+ -+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR, -+ SYSCFG_CMPENSETR_MPU_EN); -+ -+ stm32mp1_clk_disable_non_secure(SYSCFG); -+} -diff --git a/core/arch/arm/plat-stm32mp1/drivers/sub.mk b/core/arch/arm/plat-stm32mp1/drivers/sub.mk -index c668efa..0c5f3bc 100644 ---- a/core/arch/arm/plat-stm32mp1/drivers/sub.mk -+++ b/core/arch/arm/plat-stm32mp1/drivers/sub.mk -@@ -6,3 +6,4 @@ srcs-$(CFG_STPMIC1) += stm32mp1_pmic.c - srcs-y += stm32mp1_clk.c - srcs-$(CFG_DT) += stm32mp1_clkfunc.c - srcs-y += stm32mp1_ddrc.c -+srcs-y += stm32mp1_syscfg.c -diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c -index b501541..08deeea 100644 ---- a/core/arch/arm/plat-stm32mp1/main.c -+++ b/core/arch/arm/plat-stm32mp1/main.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-2-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - * Copyright (c) 2016-2018, Linaro Limited - */ - -@@ -13,7 +13,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -47,6 +49,7 @@ register_phys_mem(MEM_AREA_IO_NSEC, RNG1_BASE, SMALL_PAGE_SIZE); - register_phys_mem(MEM_AREA_IO_NSEC, IWDG1_BASE, SMALL_PAGE_SIZE); - register_phys_mem(MEM_AREA_IO_NSEC, IWDG2_BASE, SMALL_PAGE_SIZE); - register_phys_mem(MEM_AREA_IO_NSEC, RTC_BASE, SMALL_PAGE_SIZE); -+register_phys_mem(MEM_AREA_IO_NSEC, SYSCFG_BASE, SMALL_PAGE_SIZE); - #ifdef CFG_WITH_NSEC_UARTS - register_phys_mem(MEM_AREA_IO_NSEC, USART1_BASE, SMALL_PAGE_SIZE); - register_phys_mem(MEM_AREA_IO_NSEC, USART2_BASE, SMALL_PAGE_SIZE); -@@ -237,6 +240,38 @@ static TEE_Result stm32_uart_console_probe(void) - return TEE_SUCCESS; - } - service_init_late(stm32_uart_console_probe); -+ -+/* Compute PLL1 settings once PMIC init is completed */ -+static TEE_Result initialize_pll1_settings(void) -+{ -+ uint32_t vddcore_voltage = 0U; -+ int ret; -+ -+ if (stm32mp1_clk_pll1_settings_are_valid()) { -+ return TEE_SUCCESS; -+ } -+ -+ if (stm32mp_dt_pmic_status() > 0) { -+ stm32mp_get_pmic(); -+ -+ ret = stpmic1_regulator_voltage_get("buck1"); -+ if (ret < 0) { -+ panic(); -+ } -+ -+ vddcore_voltage = (uint32_t)ret; -+ -+ stm32mp_put_pmic(); -+ } -+ -+ if (stm32mp1_clk_compute_all_pll1_settings(vddcore_voltage) != 0) { -+ panic(); -+ } -+ -+ return TEE_SUCCESS; -+} -+driver_init_late(initialize_pll1_settings); -+ - #endif - - /* -@@ -360,15 +395,39 @@ bool sm_platform_handler(struct sm_ctx *ctx) - } - } - -+static uintptr_t stm32_dbgmcu_base(void) -+{ -+ static void *va; -+ -+ if (!cpu_mmu_enabled()) -+ return DBGMCU_BASE; -+ -+ if (!va) -+ va = phys_to_virt(DBGMCU_BASE, MEM_AREA_IO_SEC); -+ -+ return (uintptr_t)va; -+} -+ - /* SoC versioning util */ --uint32_t stm32mp1_dbgmcu_get_chip_version(void) -+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version) - { -- uintptr_t base = DBGMCU_BASE; -+ assert(chip_version != NULL); - -- if (cpu_mmu_enabled()) -- base = (uintptr_t)phys_to_virt(DBGMCU_BASE, MEM_AREA_IO_SEC); -+ *chip_version = (read32(stm32_dbgmcu_base() + DBGMCU_IDC) & -+ DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT; - -- return read32(base + DBGMCU_IDC) >> 16; -+ return 0; -+} -+ -+/* SoC device ID util */ -+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id) -+{ -+ assert(chip_dev_id != NULL); -+ -+ *chip_dev_id = read32(stm32_dbgmcu_base() + DBGMCU_IDC) & -+ DBGMCU_IDC_DEV_ID_MASK; -+ -+ return 0; - } - - static uintptr_t stm32_tamp_base(void) -@@ -420,6 +479,19 @@ uintptr_t stm32_get_stgen_base(void) - return va; - } - -+uintptr_t stm32_get_syscfg_base(void) -+{ -+ static uintptr_t va; -+ -+ if (!cpu_mmu_enabled()) -+ return SYSCFG_BASE; -+ -+ if (!va) -+ va = (uintptr_t)phys_to_virt(SYSCFG_BASE, MEM_AREA_IO_NSEC); -+ -+ return va; -+} -+ - uintptr_t stm32_get_gpio_bank_base(unsigned int bank) - { - /* Non secure banks and mapped together, same for secure banks */ -@@ -522,25 +594,93 @@ unsigned long stm32_get_iwdg_otp_config(uintptr_t pbase) - { - unsigned int idx; - unsigned long iwdg_cfg = 0; -+ uint32_t otp; - uint32_t otp_value; - - idx = stm32mp_iwdg_iomem2instance(pbase); - -- if (bsec_read_otp(&otp_value, HW2_OTP)) -+ if (bsec_find_otp_name_in_nvmem_layout(HW2_OTP, &otp, NULL)) -+ panic(); -+ -+ if (bsec_read_otp(&otp_value, otp)) - panic(); - - if (otp_value & BIT(idx + HW2_OTP_IWDG_HW_ENABLE_SHIFT)) - iwdg_cfg |= IWDG_HW_ENABLED; - -- if (!(otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STOP_SHIFT))) -- iwdg_cfg |= IWDG_ENABLE_ON_STOP; -+ if (otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STOP_SHIFT)) -+ iwdg_cfg |= IWDG_DISABLE_ON_STOP; - -- if (!(otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STANDBY_SHIFT))) -- iwdg_cfg |= IWDG_ENABLE_ON_STANDBY; -+ if (otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STANDBY_SHIFT)) -+ iwdg_cfg |= IWDG_DISABLE_ON_STANDBY; - - return iwdg_cfg; - } - -+static int get_part_number(uint32_t *part_nb) -+{ -+ uint32_t part_number; -+ uint32_t dev_id; -+ uint32_t otp; -+ size_t bit_len; -+ -+ assert(part_nb != NULL); -+ -+ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) != 0) { -+ return -1; -+ } -+ -+ if (bsec_find_otp_name_in_nvmem_layout(PART_NUMBER_OTP, &otp, -+ &bit_len) != BSEC_OK) { -+ return -1; -+ } -+ -+ assert(bit_len == 8); -+ -+ if (bsec_read_otp(&part_number, otp) != BSEC_OK) { -+ return -1; -+ } -+ -+ part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >> -+ PART_NUMBER_OTP_PART_SHIFT; -+ -+ *part_nb = part_number | (dev_id << 16); -+ -+ return 0; -+} -+ -+bool stm32mp_supports_cpu_opp(uint32_t opp_id) -+{ -+ uint32_t part_number; -+ uint32_t id; -+ -+ if (get_part_number(&part_number) != 0) { -+ DMSG("Cannot get part number"); -+ panic(); -+ } -+ -+ switch (opp_id) { -+ case PLAT_OPP_ID1: -+ case PLAT_OPP_ID2: -+ id = opp_id; -+ break; -+ default: -+ return false; -+ } -+ -+ switch (part_number) { -+ case STM32MP157F_PART_NB: -+ case STM32MP157D_PART_NB: -+ case STM32MP153F_PART_NB: -+ case STM32MP153D_PART_NB: -+ case STM32MP151F_PART_NB: -+ case STM32MP151D_PART_NB: -+ return true; -+ default: -+ return id == PLAT_OPP_ID1; -+ } -+} -+ - uintptr_t stm32mp_get_etzpc_base(void) - { - return ETZPC_BASE; -diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h -index e8d1660..d635efd 100644 ---- a/core/arch/arm/plat-stm32mp1/platform_config.h -+++ b/core/arch/arm/plat-stm32mp1/platform_config.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-2-Clause */ - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #ifndef PLATFORM_CONFIG_H -@@ -78,6 +78,7 @@ - #define RTC_BASE 0x5c004000 - #define SPI6_BASE 0x5c001000 - #define STGEN_BASE 0x5C008000 -+#define SYSCFG_BASE 0x50020000 - #define TAMP_BASE 0x5c00a000 - #define USART1_BASE 0x5c000000 - #define USART2_BASE 0x4000e000 -@@ -95,20 +96,15 @@ - - #define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) - --#define DATA0_OTP 0 --#define PART_NUMBER_OTP 1 --#define MONOTONIC_OTP 4 --#define NAND_OTP 9 --#define UID0_OTP 13 --#define UID1_OTP 14 --#define UID2_OTP 15 --#define HW2_OTP 18 -+#define HW2_OTP "hw2_otp" -+#define PART_NUMBER_OTP "part_number_otp" - --#define DATA0_OTP_SECURED BIT(6) -+#define HW2_OTP_IWDG_HW_ENABLE_SHIFT 3 -+#define HW2_OTP_IWDG_FZ_STOP_SHIFT 5 -+#define HW2_OTP_IWDG_FZ_STANDBY_SHIFT 7 - --#define HW2_OTP_IWDG_HW_ENABLE_SHIFT 3 --#define HW2_OTP_IWDG_FZ_STOP_SHIFT 5 --#define HW2_OTP_IWDG_FZ_STANDBY_SHIFT 7 -+#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) -+#define PART_NUMBER_OTP_PART_SHIFT 0 - - /* - * GPIO banks: 11 non secure banks (A to K) and 1 secure bank (Z) -@@ -150,12 +146,35 @@ - /* RCC platform resources */ - #define RCC_WAKEUP_IT 177 - --/* SoC revision */ -+/* SoC part numbers and revisions */ -+#define STM32MP157C_PART_NB 0x05000000 -+#define STM32MP157A_PART_NB 0x05000001 -+#define STM32MP153C_PART_NB 0x05000024 -+#define STM32MP153A_PART_NB 0x05000025 -+#define STM32MP151C_PART_NB 0x0500002E -+#define STM32MP151A_PART_NB 0x0500002F -+#define STM32MP157F_PART_NB 0x05000080 -+#define STM32MP157D_PART_NB 0x05000081 -+#define STM32MP153F_PART_NB 0x050000A4 -+#define STM32MP153D_PART_NB 0x050000A5 -+#define STM32MP151F_PART_NB 0x050000AE -+#define STM32MP151D_PART_NB 0x050000AF -+ - #define STM32MP1_REV_A 0x00001000 - #define STM32MP1_REV_B 0x00002000 -+#define STM32MP1_REV_Z 0x00002001 -+ -+/* OPP */ -+#define PLAT_OPP_ID1 1U -+#define PLAT_OPP_ID2 2U -+#define PLAT_MAX_OPP_NB 2U -+#define PLAT_MAX_PLLCFG_NB 6U - - /* DBGMCU resources */ - #define DBGMCU_IDC 0x0 -+#define DBGMCU_IDC_DEV_ID_MASK GENMASK_32(11, 0) -+#define DBGMCU_IDC_REV_ID_MASK GENMASK_32(31, 16) -+#define DBGMCU_IDC_REV_ID_SHIFT 16 - - /* BKPSRAM layout */ - #define BKPSRAM_SIZE SMALL_PAGE_SIZE -@@ -167,7 +186,7 @@ - #define BKPSRAM_PM_MAILBOX_SIZE 0x100 - #define BKPSRAM_PM_CONTEXT_OFFSET (BKPSRAM_PM_MAILBOX_OFFSET + \ - BKPSRAM_PM_MAILBOX_SIZE) --#define BKPSRAM_PM_CONTEXT_SIZE 0x700 -+#define BKPSRAM_PM_CONTEXT_SIZE 0xF00 - - /* SYSRAM */ - #define SYSRAM_SIZE 0x40000 -diff --git a/core/arch/arm/plat-stm32mp1/pm/context.c b/core/arch/arm/plat-stm32mp1/pm/context.c -index 20e9e84..fcdad91 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/context.c -+++ b/core/arch/arm/plat-stm32mp1/pm/context.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. - */ - -@@ -32,7 +32,28 @@ - - #define TRAINING_AREA_SIZE 64 - --#define STANDBY_CONTEXT_MAGIC (0x00010000 + TRAINING_AREA_SIZE) -+/* -+ * STANDBY_CONTEXT_MAGIC0: -+ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer. -+ * -+ * STANDBY_CONTEXT_MAGIC1: -+ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer -+ * and PLL1 dual OPP settings structure (86 bytes). -+ */ -+#define STANDBY_CONTEXT_MAGIC0 (0x0001 << 16) -+#define STANDBY_CONTEXT_MAGIC1 (0x0002 << 16) -+ -+#define STANDBY_CONTEXT_MAGIC (STANDBY_CONTEXT_MAGIC1 | \ -+ TRAINING_AREA_SIZE) -+ -+#if (PLAT_MAX_OPP_NB != 2) || (PLAT_MAX_PLLCFG_NB != 6) -+#error STANDBY_CONTEXT_MAGIC1 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)) - - /* - * Context saved in TEE RAM during lower power sequence. -@@ -58,11 +79,12 @@ static struct pm_context plat_ctx; - * @zq0cr0_zdata: DDRPHY configuration to be restored. - * @ddr_training_backup: DDR area saved at suspend and backed up at resume - */ --struct pm_mailbox { -+struct __attribute__((__packed__)) pm_mailbox { - uint32_t magic; - uint32_t core0_resume_ep; - uint32_t zq0cr0_zdata; - uint8_t ddr_training_backup[TRAINING_AREA_SIZE]; -+ uint8_t pll1_settings[PLL1_SETTINGS_SIZE]; - }; - - /* -@@ -323,6 +345,21 @@ static void save_ddr_training_area(void) - mobj_free(mobj); - } - -+/* -+ * When returning from STANDBY, warm boot boot stage needs to access to PLL1 -+ * settings. This avoids to re-compute them and optimizes performances. This -+ * structure must then be saved before going to STANDBY in the PM mailbox -+ * shared with the warm boot boot stage. -+ */ -+static void save_pll1_settings(void) -+{ -+ struct pm_mailbox *mailbox = get_pm_mailbox(); -+ size_t size = sizeof(mailbox->pll1_settings); -+ uint8_t *data = &mailbox->pll1_settings[0]; -+ -+ stm32mp1_clk_lp_save_opp_pll1_settings(data, size); -+} -+ - static void load_earlyboot_pm_mailbox(void) - { - struct pm_mailbox *mailbox = get_pm_mailbox(); -@@ -337,6 +374,8 @@ static void load_earlyboot_pm_mailbox(void) - mailbox->zq0cr0_zdata = get_ddrphy_calibration(); - - save_ddr_training_area(); -+ -+ save_pll1_settings(); - } - - #ifdef CFG_STM32_RNG -diff --git a/core/arch/arm/plat-stm32mp1/pm/low_power.c b/core/arch/arm/plat-stm32mp1/pm/low_power.c -index 48bddb7..450b68a 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/low_power.c -+++ b/core/arch/arm/plat-stm32mp1/pm/low_power.c -@@ -170,6 +170,10 @@ int stm32_enter_cstop(uint32_t mode) - uintptr_t rcc_base = stm32_rcc_base(); - int rc; - -+ stm32mp1_syscfg_disable_io_compensation(); -+ -+ ddr_sr_mode_ssr(); -+ - stm32_apply_pmic_suspend_config(mode); - - if (stm32mp_with_pmic() && (mode == STM32_PM_CSTOP_ALLOW_LP_STOP)) { -@@ -233,6 +237,8 @@ void stm32_exit_cstop(void) - ddr_in_selfrefresh = false; - } - -+ ddr_sr_mode_asr(); -+ - restore_rcc_it_priority(gicd_rcc_wakeup, gicc_pmr); - - /* Disable STOP request */ -@@ -247,6 +253,8 @@ void stm32_exit_cstop(void) - - /* Disable retention and backup RAM content after stop */ - mmio_clrbits_32(pwr_base + PWR_CR2_OFF, PWR_CR2_BREN | PWR_CR2_RREN); -+ -+ stm32mp1_syscfg_enable_io_compensation(); - } - - /* -@@ -412,7 +420,7 @@ void __noreturn stm32_cores_reset(void) - } - KEEP_PAGER(stm32_cores_reset); - --static void reset_other_core(void) -+static void __maybe_unused reset_other_core(void) - { - uintptr_t rcc_base = stm32_rcc_base(); - uint32_t reset_mask; -diff --git a/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -index d9ed746..cd8e48c 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -+++ b/core/arch/arm/plat-stm32mp1/pm/pm_helpers.S -@@ -64,6 +64,36 @@ - #define CRYP_SR_IFNF BIT(1) - #define CRYP_SR_IFEM BIT(0) - -+/* -+ * Enable TRACE_SYSRAM_RESTORE to get some UART console traces -+ * at resume time. -+ */ -+#if defined(TRACE_SYSRAM_RESTORE) -+ -+#define UART_BASE UART4_BASE -+#define UART_ISR_OFF 0x1c -+#define UART_TDR_OFF 0x28 -+#define USART_ISR_TXE_TXFNF (1<< 7) -+ -+ .macro PRINT_CHAR _reg0, _reg1, _char -+ /* Trace only at resume when MMU is OFF */ -+ read_sctlr \_reg0 -+ ands \_reg0, #SCTLR_M -+ 101: -+ bne 102f -+ mov_imm \_reg0, UART4_BASE -+ ldr \_reg1, [\_reg0, #UART_ISR_OFF] -+ ands \_reg1, #USART_ISR_TXE_TXFNF -+ beq 101b -+ mov_imm \_reg1, (\_char) -+ str \_reg1, [\_reg0, #UART_TDR_OFF] -+ 102: -+ .endm -+#else -+ .macro PRINT_CHAR _reg0, _reg1, _char -+ .endm -+#endif -+ - /* Bound of the binary image loaded in retained memory */ - .global stm32mp_bkpsram_image_end - -@@ -80,6 +110,9 @@ - FUNC stm32mp_bkpsram_resume , : - UNWIND( .fnstart) - UNWIND( .cantunwind) -+ -+ PRINT_CHAR r0, r1, '0' -+ - /* - * Almost all sequences here expect PM context structure base address - * from CPU register r11. -@@ -105,6 +138,11 @@ UNWIND( .cantunwind) - cmp r0, #0 - bne _failed - -+ PRINT_CHAR r0, r1, 'T' -+ PRINT_CHAR r0, r1, 'a' -+ PRINT_CHAR r0, r1, 'g' -+ PRINT_CHAR r0, r1, '\n' -+ - /* Compare the generated and reference tags */ - add r8, r11, #PM_CTX_CCM_TAG - add r9, r11, #PM_CTX_CCM_REF_TAG -@@ -123,11 +161,18 @@ UNWIND( .cantunwind) - bne _failed - bl _save_resume_time - -+ PRINT_CHAR r1, r2, 'O' -+ PRINT_CHAR r1, r2, 'k' -+ PRINT_CHAR r1, r2, '\n' -+ - /* Resume into the restored TEE RAM */ - ldr r1, [r11, #PM_CTX_RESUME_PA] - bx r1 - - _failed: -+ PRINT_CHAR r0, r12, 'F' -+ PRINT_CHAR r0, r12, '\n' -+ - /* Clear context including key and reference tag */ - mov r0, #0xa5 - mov_imm r12, BKPSRAM_PM_CONTEXT_SIZE -@@ -279,16 +324,23 @@ _ccm_arm_8ms_timeout: - moveq r0, #1 - ldr r1, [r1, #CNTCVL_OFFSET] - adds r0, r0, r1 -- bcs _ccm_failed -+ bcs _ccm_failed_on_timeout - bx lr - - _ccm_fail_on_timeout: -+ - ldr r1, [r11, #PM_CTX_STGEN_BASE] - ldr r1, [r1, #CNTCVL_OFFSET] - cmp r1, r0 -- bge _ccm_failed -+ bge _ccm_failed_on_timeout - bx lr - -+_ccm_failed_on_timeout: -+ PRINT_CHAR r0, r1, 'T' -+ PRINT_CHAR r0, r1, 'o' -+ PRINT_CHAR r0, r1, '\n' -+ b _ccm_failed -+ - /* - * Macro WAIT_FLAG_TIMEOUT compares timeout threshold (r0) with - * current time and branches the CCM failure entry on timeout. -@@ -346,8 +398,12 @@ stm32mp_ccm_teeram: - mov r7, r2 - mov r6, r3 - -+ PRINT_CHAR r0, r1, '1' -+ - bl _setup_cryp1 - -+ PRINT_CHAR r0, r1, '2' -+ - mov_imm r0, (CRYP_CR_ALGOMODE(ALGOMODE_AES_CCM) | \ - CRYP_CR_DATATYPE_8BIT | CRYP_CR_FFLUSH | \ - CRYP_CR_KEYSIZE_256BIT) -@@ -355,6 +411,8 @@ stm32mp_ccm_teeram: - orrne r0, r0, #CRYP_CR_ALGODIR_DECRYPT - str r0, [r10, #CRYP_CR] - -+ PRINT_CHAR r0, r1, '3' -+ - /* Check data alignment (addresses and size) */ - ands r0, r7, #0x0F - bne _ccm_failed -@@ -363,6 +421,8 @@ stm32mp_ccm_teeram: - ands r0, r9, #0x03 - bne _ccm_failed - -+ PRINT_CHAR r0, r1, '4' -+ - ldr r0, [r11, #PM_CTX_CCM_KEY] - str r0, [r10, #CRYP_KEYR_BASE] - ldr r0, [r11, #(PM_CTX_CCM_KEY + 4)] -@@ -404,6 +464,8 @@ stm32mp_ccm_teeram: - ldr r0, [r11, #(PM_CTX_CCM_B0 + 12)] - str r0, [r10, #CRYP_DIN] - -+ PRINT_CHAR r0, r1, '5' -+ - WAIT_FLAG_TIMEOUT CRYP_CR, CRYP_CR_CRYPEN, 0 - - /* Setup CRYP for the CCM Payload phase */ -@@ -414,7 +476,11 @@ stm32mp_ccm_teeram: - str r0, [r10, #CRYP_CR] - ldr r0, [r10, #CRYP_CR] - -+ PRINT_CHAR r0, r1, '\n' -+ - _next_block: -+ PRINT_CHAR r0, r1, 'b' -+ - WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_IFEM, CRYP_SR_IFEM - - /* Feed input data, r8 stores the current source buffer */ -@@ -451,6 +517,9 @@ _next_block: - subs r7, r7, #16 - bne _next_block; - -+ PRINT_CHAR r0, r1, '\n' -+ PRINT_CHAR r0, r1, '6' -+ - WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_BUSY, 0 - - /* -@@ -461,6 +530,8 @@ _next_block: - cmp r0, #(CRYP_SR_IFEM | CRYP_SR_IFNF) - bne _ccm_failed - -+ PRINT_CHAR r0, r1, '7' -+ - /* Setup CRYP1 for the CCM Final Phase */ - ldr r0, [r10, #CRYP_CR] - bic r0, r0, #CRYP_CR_CRYPEN -@@ -483,6 +554,8 @@ _next_block: - ldr r0, [r11, #(PM_CTX_CCM_CTR0 + 12)] - str r0, [r10, #CRYP_DIN] - -+ PRINT_CHAR r0, r1, '8' -+ - WAIT_FLAG_TIMEOUT CRYP_SR, CRYP_SR_OFNE, CRYP_SR_OFNE - - /* Store generated tag in the PM_CTX structure */ -@@ -503,12 +576,18 @@ _next_block: - ands r0, r0, #CRYP_SR_OFNE - bne _ccm_failed - -+ PRINT_CHAR r0, r1, '9' -+ - /* Successful return */ - bl _reset_cryp1 - mov r0, #0 - bx r12 - - _ccm_failed: -+ -+ PRINT_CHAR r0, r1, 'K' -+ PRINT_CHAR r0, r1, 'O' -+ - bl _reset_cryp1 - mov r0, #1 - bx r12 -@@ -577,24 +656,50 @@ FUNC stm32mp_sysram_resume, : - UNWIND( .fnstart) - UNWIND( .cantunwind) - /* Invalidate the data cache */ -- mov r0, #0 @ ; write the cache size selection register to be -- write_csselr r0 @ ; sure we address the data cache -- isb @ ; isb to sync the change to the cachesizeid reg -- -- mov r0, #0 @ ; set way number to 0 --_inv_nextway: -- mov r1, #0 @ ; set line number (=index) to 0 --_inv_nextline: -- orr r2, r0, r1 @ ; construct way/index value -- write_dcisw r2 @ ; inval data or unified cache line by set/way -- add r1, r1, #1 << LINE_FIELD_OFFSET @ ; increment the index -- cmp r1, #1 << LINE_FIELD_OVERFLOW @ ; overflow out of set field? -- bne _inv_nextline -- add r0, r0, #1 << WAY_FIELD_OFFSET @ ; increment the way number -- cmp r0, #0 @ ; overflow out of way field? -- bne _inv_nextway - -- dsb -+ read_clidr r2 -+ ubfx r3, r2, #CLIDR_LOC_SHIFT, #CLIDR_FIELD_WIDTH -+ lsl r3, r3, #CSSELR_LEVEL_SHIFT -+ mov r1, #0 -+ -+loop1: -+ add r10, r1, r1, LSR #1 // Work out 3x current cache level -+ mov r12, r2, LSR r10 // extract cache type bits from clidr -+ and r12, r12, #7 // mask the bits for current cache only -+ cmp r12, #2 // see what cache we have at this level -+ blo level_done // no cache or only instruction cache at this level -+ -+ write_csselr r1 // select current cache level in csselr -+ isb // isb to sych the new cssr&csidr -+ read_ccsidr r12 // read the new ccsidr -+ and r10, r12, #7 // extract the length of the cache lines -+ add r10, r10, #4 // add 4 (r10 = line length offset) -+ ubfx r4, r12, #3, #10 // r4 = maximum way number (right aligned) -+ clz r5, r4 // r5 = the bit position of the way size increment -+ mov r9, r4 // r9 working copy of the aligned max way number -+ -+loop2: -+ ubfx r7, r12, #13, #15 // r7 = max set number (right aligned) -+ -+loop3: -+ orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 -+ orr r0, r0, r7, LSL r10 // factor in the set number -+ -+ write_dcisw r0 -+ -+ subs r7, r7, #1 // decrement the set number -+ bhs loop3 -+ subs r9, r9, #1 // decrement the way number -+ bhs loop2 -+level_done: -+ add r1, r1, #2 // increment the cache number -+ cmp r3, r1 -+ dsb sy // ensure completion of previous cache maintenance instruction -+ bhi loop1 -+ -+ mov r6, #0 -+ write_csselr r6 //select cache level 0 in csselr -+ dsb sy - isb - - /* Resume sequence executes in Monitor mode */ -diff --git a/core/arch/arm/plat-stm32mp1/pm/power_config.c b/core/arch/arm/plat-stm32mp1/pm/power_config.c -index 7845ede..ef26608 100644 ---- a/core/arch/arm/plat-stm32mp1/pm/power_config.c -+++ b/core/arch/arm/plat-stm32mp1/pm/power_config.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -57,7 +57,7 @@ bool need_to_backup_cpu_context(unsigned int soc_mode) - #ifdef CFG_DT - static int dt_get_pwr_node(void *fdt) - { -- return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); -+ return fdt_get_node_by_compatible(fdt, DT_PWR_COMPAT); - } - #endif - -diff --git a/core/arch/arm/plat-stm32mp1/service/bsec_svc.c b/core/arch/arm/plat-stm32mp1/service/bsec_svc.c -index 1ce7195..f345978 100644 ---- a/core/arch/arm/plat-stm32mp1/service/bsec_svc.c -+++ b/core/arch/arm/plat-stm32mp1/service/bsec_svc.c -@@ -48,6 +48,10 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t *out) - result = bsec_write_otp(tmp, x2); - FMSG("read @%" PRIx32 " = %" PRIx32, x2, *out); - break; -+ case STM32_SIP_BSEC_WRLOCK_OTP: -+ FMSG("permanent write lock @%" PRIx32, x2); -+ result = bsec_permanent_lock_otp(x2); -+ break; - default: - EMSG("Invalid %" PRIx32, x1); - result = BSEC_ERROR; -diff --git a/core/arch/arm/plat-stm32mp1/service/rcc_svc.c b/core/arch/arm/plat-stm32mp1/service/rcc_svc.c -index 7bdaea8..3e7b4d3 100644 ---- a/core/arch/arm/plat-stm32mp1/service/rcc_svc.c -+++ b/core/arch/arm/plat-stm32mp1/service/rcc_svc.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #include -@@ -438,3 +438,31 @@ uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) - - return STM32_SIP_OK; - } -+ -+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_SIP_RCC_OPP_SET: -+ if (stm32mp1_set_opp_khz(opp) != 0) { -+ return STM32_SIP_FAILED; -+ } -+ break; -+ -+ case STM32_SIP_RCC_OPP_ROUND: -+ if(stm32mp1_round_opp_khz(&opp) != 0) { -+ return STM32_SIP_FAILED; -+ } -+ -+ if (MUL_OVERFLOW(opp, 1000, res)) -+ return STM32_SIP_FAILED; -+ break; -+ -+ default: -+ return STM32_SIP_INVALID_PARAMS; -+ } -+ -+ return STM32_SIP_OK; -+} -diff --git a/core/arch/arm/plat-stm32mp1/service/rcc_svc.h b/core/arch/arm/plat-stm32mp1/service/rcc_svc.h -index f198ebd..aaa1f75 100644 ---- a/core/arch/arm/plat-stm32mp1/service/rcc_svc.h -+++ b/core/arch/arm/plat-stm32mp1/service/rcc_svc.h -@@ -1,11 +1,12 @@ - /* SPDX-License-Identifier: BSD-2-Clause */ - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #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_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res); - - #endif /*__RCC_SVC_H__*/ -diff --git a/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h b/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h -index 2db7b10..3482c34 100644 ---- a/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h -+++ b/core/arch/arm/plat-stm32mp1/service/stm32mp1_smc.h -@@ -110,6 +110,7 @@ - #define STM32_SIP_BSEC_PROG_OTP 0x2 - #define STM32_SIP_BSEC_WRITE_SHADOW 0x3 - #define STM32_SIP_BSEC_READ_OTP 0x4 -+#define STM32_SIP_BSEC_WRLOCK_OTP 0x5 - - /* - * SIP functions STM32_SIP_FUNC_SR_MODE -@@ -182,6 +183,21 @@ - #define STM32_SIP_PD_MAX_PM_DOMAIN 0x3 - - /* -+ * SIP function STM32_SIP_FUNC_RCC_OPP. -+ * -+ * Argument a0: (input) SMCC ID. -+ * (output) Status return code. -+ * Argument a1: (input) Service ID (STM32_SIP_RCC_OPP_xxx). -+ * (output) Rounded frequency, if applicable. -+ * Argument a2: (input) Requested frequency. -+ */ -+#define STM32_SIP_FUNC_RCC_OPP 0x1009 -+ -+/* Service ID for STM32_SIP_FUNC_RCC_OPP */ -+#define STM32_SIP_RCC_OPP_SET 0x0 -+#define STM32_SIP_RCC_OPP_ROUND 0x1 -+ -+/* - * OEM Functions - */ - #define STM32_OEM_SVC_VERSION_MAJOR 0x0 -diff --git a/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c b/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c -index 3c7958c..a88577a 100644 ---- a/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c -+++ b/core/arch/arm/plat-stm32mp1/service/stm32mp1_svc_setup.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #include -@@ -70,6 +70,9 @@ bool stm32_sip_service(struct sm_ctx __unused *ctx, - case STM32_SIP_FUNC_RCC: - *a0 = rcc_scv_handler(*a1, *a2, *a3); - break; -+ case STM32_SIP_FUNC_RCC_OPP: -+ *a0 = rcc_opp_scv_handler(*a1, *a2, a1); -+ break; - #endif - #ifdef CFG_STM32_CLOCKSRC_CALIB - case STM32_SIP_RCC_CAL: -diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h -index 347499b..a2818c0 100644 ---- a/core/arch/arm/plat-stm32mp1/stm32_util.h -+++ b/core/arch/arm/plat-stm32mp1/stm32_util.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2017-2018, STMicroelectronics -+ * Copyright (c) 2017-2019, STMicroelectronics - */ - - #ifndef __STM32_UTIL_H__ -@@ -15,8 +15,12 @@ - #include - #include - --/* SoC versioning */ --uint32_t stm32mp1_dbgmcu_get_chip_version(void); -+/* SoC versioning and device ID */ -+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version); -+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id); -+ -+/* OPP service */ -+bool stm32mp_supports_cpu_opp(uint32_t opp_id); - - /* SiP & OEM platform services */ - bool stm32_sip_service(struct sm_ctx *ctx, -@@ -28,6 +32,9 @@ bool stm32_oem_service(struct sm_ctx *ctx, - /* Platform util for the STGEN driver */ - uintptr_t stm32_get_stgen_base(void); - -+/* Platform util for the SYSCFG driver */ -+uintptr_t stm32_get_syscfg_base(void); -+ - /* Platform util for the GIC */ - uintptr_t get_gicc_base(void); - uintptr_t get_gicd_base(void); -@@ -120,6 +127,13 @@ void stm32mp_platform_reset(int cpu); - int stm32mp_start_clock_calib(unsigned int clock_id); - - /* -+ * SYSCFG IO compensation. -+ * These functions assume non-secure world is suspended. -+ */ -+void stm32mp1_syscfg_enable_io_compensation(void); -+void stm32mp1_syscfg_disable_io_compensation(void); -+ -+/* - * 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 -diff --git a/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c b/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c -index 9ce6ba8..7413ebb 100644 ---- a/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c -+++ b/core/arch/arm/plat-stm32mp1/stm32mp1_dt.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. - */ - -@@ -230,6 +230,74 @@ int fdt_get_stdout_node_offset(void *fdt) - } - - /******************************************************************************* -+ * This function returns the offset of the first matching compatible node -+ * in the DT. It should be used only for single instanced peripherals. -+ * Returns node on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int fdt_get_node_by_compatible(void *fdt, const char *compatible) -+{ -+ int node = fdt_node_offset_by_compatible(fdt, -1, compatible); -+ -+ if (node < 0) { -+ DMSG("Cannot find %s node in DT", compatible); -+ } -+ -+ return node; -+} -+ -+/******************************************************************************* -+ * This function returns the node offset matching compatible string in the DT, -+ * and also matching the reg property with the given address. -+ * Returns node on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+int fdt_match_instance_by_compatible(void *fdt, const char *compatible, -+ uintptr_t address) -+{ -+ int node; -+ -+ for (node = fdt_node_offset_by_compatible(fdt, -1, compatible); -+ node != -FDT_ERR_NOTFOUND; -+ node = fdt_node_offset_by_compatible(fdt, node, compatible)) { -+ const fdt32_t *cuint; -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ continue; -+ } -+ -+ if ((uintptr_t)fdt32_to_cpu(*cuint) == address) { -+ return node; -+ } -+ } -+ -+ return -FDT_ERR_NOTFOUND; -+} -+ -+/******************************************************************************* -+ * This function returns the peripheral base address information from the -+ * first matching compatible string in the DT. It should be used only for -+ * single instanced peripherals. -+ * Returns non null base address on success, and 0 on failure. -+ ******************************************************************************/ -+uintptr_t fdt_get_peripheral_base(void *fdt, const char *compatible) -+{ -+ int node; -+ const fdt32_t *cuint; -+ -+ node = fdt_get_node_by_compatible(fdt, compatible); -+ if (node < 0) { -+ return 0; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", NULL); -+ if (cuint == NULL) { -+ return 0; -+ } -+ -+ return fdt32_to_cpu(*cuint); -+} -+ -+/******************************************************************************* - * This function gets DDR size information from the DT. - * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else. - ******************************************************************************/ -@@ -237,9 +305,8 @@ uint32_t fdt_get_ddr_size(void *fdt) - { - int node; - -- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); -+ node = fdt_get_node_by_compatible(fdt, DT_DDR_COMPAT); - if (node < 0) { -- IMSG("%s: Cannot read DDR node in DT\n", __func__); - return STM32MP1_DDR_SIZE_DFLT; - } - -@@ -248,6 +315,127 @@ uint32_t fdt_get_ddr_size(void *fdt) - } - - /******************************************************************************* -+ * This function gets OPP table node from the DT. -+ * Returns node offset on success and a negative FDT error code on failure. -+ ******************************************************************************/ -+static int fdt_get_opp_table_node(void *fdt) -+{ -+ return fdt_get_node_by_compatible(fdt, 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 fdt_get_opp_freqvolt_from_subnode(void *fdt, 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))) { -+ DMSG("Invalid opp-supported-hw 0x%"PRIx32, -+ fdt32_to_cpu(*cuint32)); -+ return -FDT_ERR_BADVALUE; -+ } -+ } -+ -+ cuint64 = fdt_getprop(fdt, subnode, "opp-hz", NULL); -+ if (cuint64 == NULL) { -+ DMSG("Missing opp-hz"); -+ 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) { -+ DMSG("Invalid opp-hz %"PRIu64, read_freq_64); -+ return -FDT_ERR_BADVALUE; -+ } -+ -+ cuint32 = fdt_getprop(fdt, subnode, "opp-microvolt", NULL); -+ if (cuint32 == NULL) { -+ DMSG("Missing opp-microvolt"); -+ return -FDT_ERR_NOTFOUND; -+ } -+ -+ /* Millivolt value must fit on 16 bits */ -+ read_voltage_32 = fdt32_to_cpu(*cuint32) / 1000U; -+ if (read_voltage_32 > UINT16_MAX) { -+ DMSG("Invalid opp-microvolt %"PRIu32, 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 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 fdt_get_all_opp_freqvolt(void *fdt, 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 = fdt_get_opp_table_node(fdt); -+ if (node < 0) { -+ return node; -+ } -+ -+ fdt_for_each_subnode(subnode, fdt, node) { -+ uint32_t read_freq; -+ uint32_t read_voltage; -+ -+ if (fdt_get_opp_freqvolt_from_subnode(fdt, 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 retrieves board model from DT. - * Returns string taken from model node, NULL otherwise - ******************************************************************************/ -diff --git a/core/arch/arm/plat-stm32mp1/stm32mp_dt.h b/core/arch/arm/plat-stm32mp1/stm32mp_dt.h -index ec8aa4d..3229f2e 100644 ---- a/core/arch/arm/plat-stm32mp1/stm32mp_dt.h -+++ b/core/arch/arm/plat-stm32mp1/stm32mp_dt.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. - */ - -@@ -11,6 +11,7 @@ - #include - - #define DT_DDR_COMPAT "st,stm32mp1-ddr" -+#define DT_OPP_COMPAT "operating-points-v2" - - struct dt_node_info { - uint32_t base; -@@ -28,7 +29,14 @@ void fdt_fill_device_info(void *fdt, struct dt_node_info *info, int node); - int fdt_get_node(void *fdt, struct dt_node_info *info, int offset, - const char *compat); - int fdt_get_stdout_node_offset(void *fdt); -+int fdt_get_node_by_compatible(void *fdt, const char *compatible); -+int fdt_match_instance_by_compatible(void *fdt, const char *compatible, -+ uintptr_t address); -+uintptr_t fdt_get_peripheral_base(void *fdt, const char *compatible); - uint32_t fdt_get_ddr_size(void *fdt); -+int fdt_get_all_opp_freqvolt(void *fdt, uint32_t *count, -+ uint32_t *freq_khz_array, -+ uint32_t *voltage_mv_array); - const char *fdt_get_board_model(void *fdt); - - int fdt_get_clock_id(void *fdt, int node); -diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c -index 7fcefdb..0e4c76b 100644 ---- a/core/drivers/stm32_bsec.c -+++ b/core/drivers/stm32_bsec.c -@@ -19,9 +19,12 @@ - - #ifdef CFG_DT - #include -+#include - #endif - --#define BSEC_COMPAT "st,stm32mp15-bsec" -+#define BSEC_COMPAT "st,stm32mp15-bsec" -+#define DT_NVMEM_LAYOUT_COMPAT "st,stm32-nvmem-layout" -+ - #define BITS_PER_WORD (CHAR_BIT * sizeof(uint32_t)) - #define OTP_ACCESS_SIZE (ROUNDUP(OTP_MAX_SIZE, BITS_PER_WORD) / BITS_PER_WORD) - -@@ -76,35 +79,151 @@ 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) { -+ 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 = ROUNDUP(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); -+ -+ IMSG("OTP crosses Lower/Upper boundary"); -+ } else { -+ continue; -+ } -+ } -+ -+ if ((fdt_getprop(fdt, bsec_subnode, -+ "st,non-secure-otp", NULL)) == NULL) { -+ continue; -+ } -+ -+ if (((offset % sizeof(uint32_t)) != 0) || -+ ((length % sizeof(uint32_t)) != 0)) { -+ EMSG("Unaligned non-secure OTP\n"); -+ panic(); -+ } -+ -+ size = length / sizeof(uint32_t); -+ -+ for (i = otp; i < (otp + size); i++) { -+ enable_non_secure_access(i); -+ } -+ } -+ -+ return 0; -+} -+ -+struct nvmem_layout { -+ char *name; -+ uint32_t number; -+ size_t bit_len; -+}; -+ -+static struct nvmem_layout *nvmem_layout; -+static size_t nvmem_layout_count; -+ -+static int save_dt_nvmem_layout(void *fdt) -+{ -+ const fdt32_t *cells; -+ int i; -+ int cell_nb; -+ int nvmem_node; -+ -+ nvmem_node = fdt_get_node_by_compatible(fdt, DT_NVMEM_LAYOUT_COMPAT); -+ if (nvmem_node < 0) { -+ return 0; -+ } -+ -+ cells = fdt_getprop(fdt, nvmem_node, "nvmem-cells", &cell_nb); -+ if (cells == NULL) { -+ cell_nb = 0; -+ } -+ -+ cell_nb /= sizeof(uint32_t); -+ -+ i = fdt_stringlist_count(fdt, nvmem_node, "nvmem-cell-names"); -+ if (i < 0) { -+ i = 0; -+ } -+ -+ if (cell_nb != i) { -+ EMSG("Inconsistent NVMEM layout"); -+ panic(); -+ } -+ -+ nvmem_layout = calloc(cell_nb, sizeof(*nvmem_layout)); -+ if (nvmem_layout == NULL) { -+ panic(); -+ } -+ -+ nvmem_layout_count = (size_t)cell_nb; -+ -+ for (i = 0; i < cell_nb; i++) { -+ const fdt32_t *cuint; -+ const char *string; -+ int len; -+ int node; -+ -+ node = fdt_node_offset_by_phandle(fdt, -+ fdt32_to_cpu(*(cells + i))); -+ if (node < 0) { -+ EMSG("Malformed nvmem_layout node: ignored"); -+ continue; -+ } -+ -+ cuint = fdt_getprop(fdt, node, "reg", &len); -+ if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) { -+ EMSG("Malformed nvmem_layout node: ignored"); - continue; - } - -- status = _fdt_get_status(fdt, bsec_subnode); -- if ((status & DT_STATUS_OK_NSEC) == 0U) { -+ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { -+ EMSG("Misaligned nvmem_layout element: ignored"); - continue; - } - -- size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t); -+ nvmem_layout[i].number = fdt32_to_cpu(*cuint) / -+ sizeof(uint32_t); -+ nvmem_layout[i].bit_len = fdt32_to_cpu(*(cuint + 1)) * CHAR_BIT; - -- if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) { -- size++; -+ string = fdt_stringlist_get(fdt, nvmem_node, "nvmem-cell-names", -+ i, &len); -+ if ((string == NULL) || (len == 0)) { -+ continue; - } - -- for (i = reg; i < (reg + size); i++) { -- enable_non_secure_access(i); -+ nvmem_layout[i].name = calloc(1, len + 1); -+ if (nvmem_layout[i].name == NULL) { -+ panic(); - } -+ -+ memcpy(nvmem_layout[i].name, string, len); - } - - return 0; -@@ -158,6 +277,44 @@ static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed) - return BSEC_OK; - } - -+#ifdef CFG_DT -+/* -+ * bsec_find_otp_name_in_nvmem_layout: find and get OTP location from its name. -+ * name: sub-node name to look up. -+ * otp: pointer to read OTP number or NULL. -+ * otp_bit_len: pointer to read OTP length in bits or NULL. -+ * return value: BSEC_OK if no error. -+ */ -+uint32_t bsec_find_otp_name_in_nvmem_layout(const char *name, uint32_t *otp, -+ uint32_t *otp_bit_len) -+{ -+ size_t i; -+ -+ if (name == NULL) { -+ return BSEC_INVALID_PARAM; -+ } -+ -+ for (i = 0; i < nvmem_layout_count; i++) { -+ if (!nvmem_layout[i].name || -+ strcmp(name, nvmem_layout[i].name)) { -+ continue; -+ } -+ -+ if (otp != NULL) { -+ *otp = nvmem_layout[i].number; -+ } -+ -+ if (otp_bit_len != NULL) { -+ *otp_bit_len = nvmem_layout[i].bit_len; -+ } -+ -+ return BSEC_OK; -+ } -+ -+ return BSEC_ERROR; -+} -+#endif -+ - /* - * bsec_shadow_register: copy SAFMEM OTP to BSEC data. - * otp: OTP number. -@@ -209,11 +366,8 @@ uint32_t bsec_shadow_register(uint32_t otp) - */ - uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) - { -- uint32_t exc; -- -- if (otp > stm32mp_get_otp_max()) { -+ if (otp > stm32mp_get_otp_max()) - return BSEC_INVALID_PARAM; -- } - - *val = read32(bsec_get_base() + BSEC_OTP_DATA_OFF + - (otp * sizeof(uint32_t))); -@@ -747,6 +901,8 @@ static TEE_Result initialize_bsec(void) - - bsec_dt_otp_nsec_access(fdt, node); - -+ save_dt_nvmem_layout(fdt); -+ - return TEE_SUCCESS; - } - driver_init(initialize_bsec); -diff --git a/core/drivers/stm32_i2c.c b/core/drivers/stm32_i2c.c -index 8ba7178..a68ef96 100644 ---- a/core/drivers/stm32_i2c.c -+++ b/core/drivers/stm32_i2c.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - /* STM32 I2C registers offsets */ - #define I2C_CR1 0x00U -@@ -32,13 +33,14 @@ - - #define MAX_NBYTE_SIZE 255U - --#define I2C_NSEC_PER_SEC 1000000000L -+#define I2C_NSEC_PER_SEC 1000000000UL -+ -+/* Effective rate cannot be lower than 80% target rate */ -+#define RATE_MIN(rate) (((rate) * 80U) / 100U) - - /* - * struct i2c_spec_s - Private I2C timing specifications. - * @rate: I2C bus speed (Hz) -- * @rate_min: 80% of I2C bus speed (Hz) -- * @rate_max: 120% of I2C bus speed (Hz) - * @fall_max: Max fall time of both SDA and SCL signals (ns) - * @rise_max: Max rise time of both SDA and SCL signals (ns) - * @hddat_min: Min data hold time (ns) -@@ -49,8 +51,6 @@ - */ - struct i2c_spec_s { - uint32_t rate; -- uint32_t rate_min; -- uint32_t rate_max; - uint32_t fall_max; - uint32_t rise_max; - uint32_t hddat_min; -@@ -83,11 +83,11 @@ struct i2c_timing_s { - * - * [1] https://www.nxp.com/docs/en/user-guide/UM10204.pdf - */ -+/* This table must be sorted in increasing value for field @rate */ - static const struct i2c_spec_s i2c_specs[] = { -- [I2C_SPEED_STANDARD] = { -+ /* Standard - 100KHz */ -+ { - .rate = STANDARD_RATE, -- .rate_min = (STANDARD_RATE * 80) / 100, -- .rate_max = (STANDARD_RATE * 120) / 100, - .fall_max = 300, - .rise_max = 1000, - .hddat_min = 0, -@@ -96,10 +96,9 @@ static const struct i2c_spec_s i2c_specs[] = { - .l_min = 4700, - .h_min = 4000, - }, -- [I2C_SPEED_FAST] = { -+ /* Fast - 400KHz */ -+ { - .rate = FAST_RATE, -- .rate_min = (FAST_RATE * 80) / 100, -- .rate_max = (FAST_RATE * 120) / 100, - .fall_max = 300, - .rise_max = 300, - .hddat_min = 0, -@@ -108,10 +107,9 @@ static const struct i2c_spec_s i2c_specs[] = { - .l_min = 1300, - .h_min = 600, - }, -- [I2C_SPEED_FAST_PLUS] = { -+ /* FastPlus - 1MHz */ -+ { - .rate = FAST_PLUS_RATE, -- .rate_min = (FAST_PLUS_RATE * 80) / 100, -- .rate_max = (FAST_PLUS_RATE * 120) / 100, - .fall_max = 100, - .rise_max = 120, - .hddat_min = 0, -@@ -184,6 +182,19 @@ 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 = 0; i < ARRAY_SIZE(i2c_specs); i++) { -+ if (rate <= i2c_specs[i].rate) { -+ return &i2c_specs[i]; -+ } -+ } -+ -+ return NULL; -+} -+ - static void save_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) - { - uintptr_t base = get_base(hi2c); -@@ -222,11 +233,11 @@ static void restore_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) - - static void __maybe_unused dump_cfg(struct i2c_cfg *cfg __maybe_unused) - { -- DMSG("CR1: %x", (unsigned)cfg->cr1); -- DMSG("CR2: %x", (unsigned)cfg->cr2); -- DMSG("OAR1: %x", (unsigned)cfg->oar1); -- DMSG("OAR2: %x", (unsigned)cfg->oar2); -- DMSG("TIM: %x", (unsigned)cfg->timingr); -+ DMSG("CR1: %"PRIx32, cfg->cr1); -+ DMSG("CR2: %"PRIx32, cfg->cr2); -+ DMSG("OAR1: %"PRIx32, cfg->oar1); -+ DMSG("OAR2: %"PRIx32, cfg->oar2); -+ DMSG("TIM: %"PRIx32, cfg->timingr); - } - - static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c) -@@ -235,11 +246,11 @@ static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c) - - stm32_clock_enable(hi2c->clock); - -- DMSG("CR1: %x", (unsigned)mmio_read_32(base + I2C_CR1)); -- DMSG("CR2: %x", (unsigned)mmio_read_32(base + I2C_CR2)); -- DMSG("OAR1: %x", (unsigned)mmio_read_32(base + I2C_OAR1)); -- DMSG("OAR2: %x", (unsigned)mmio_read_32(base + I2C_OAR2)); -- DMSG("TIM: %x", (unsigned)mmio_read_32(base + I2C_TIMINGR)); -+ DMSG("CR1: %"PRIx32, mmio_read_32(base + I2C_CR1)); -+ DMSG("CR2: %"PRIx32, mmio_read_32(base + I2C_CR2)); -+ DMSG("OAR1: %"PRIx32, mmio_read_32(base + I2C_OAR1)); -+ DMSG("OAR2: %"PRIx32, mmio_read_32(base + I2C_OAR2)); -+ DMSG("TIM: %"PRIx32, mmio_read_32(base + I2C_TIMINGR)); - - stm32_clock_disable(hi2c->clock); - } -@@ -254,7 +265,7 @@ static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c) - static int i2c_compute_timing(struct stm32_i2c_init_s *init, - uint32_t clock_src, uint32_t *timing) - { -- enum i2c_speed_e mode = init->speed_mode; -+ const struct i2c_spec_s *specs; - uint32_t speed_freq; - uint32_t i2cclk = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, clock_src); - uint32_t i2cbus; -@@ -277,31 +288,26 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - int s = -1; - struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX]; - -- switch (mode) { -- case I2C_SPEED_STANDARD: -- case I2C_SPEED_FAST: -- case I2C_SPEED_FAST_PLUS: -- break; -- default: -- EMSG("I2C speed out of bound {%d/%d}\n", -- mode, I2C_SPEED_FAST_PLUS); -+ specs = get_specs(init->bus_rate); -+ if (specs == NULL) { -+ EMSG("I2C speed out of bound: %"PRId32"Hz", init->bus_rate); - return -1; - } - -- speed_freq = i2c_specs[mode].rate; -+ speed_freq = specs->rate; - i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq); - clk_error_prev = INT_MAX; - -- if ((init->rise_time > i2c_specs[mode].rise_max) || -- (init->fall_time > i2c_specs[mode].fall_max)) { -- EMSG(" I2C timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", -- init->rise_time, i2c_specs[mode].rise_max, -- init->fall_time, i2c_specs[mode].fall_max); -+ if ((init->rise_time > specs->rise_max) || -+ (init->fall_time > specs->fall_max)) { -+ EMSG(" I2C timings out of bound Rise{%"PRId32">%"PRId32"}/Fall{%"PRId32">%"PRId32"}", -+ init->rise_time, specs->rise_max, -+ init->fall_time, specs->fall_max); - return -1; - } - - if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) { -- EMSG("DNF out of bound %d/%d\n", -+ EMSG("DNF out of bound %"PRId8"/%d", - init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX); - return -1; - } -@@ -313,19 +319,19 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0); - dnf_delay = init->digital_filter_coef * i2cclk; - -- sdadel_min = i2c_specs[mode].hddat_min + init->fall_time; -+ sdadel_min = specs->hddat_min + init->fall_time; - delay = af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); - if (SUB_OVERFLOW(sdadel_min, delay ,&sdadel_min)) - sdadel_min = 0; - -- sdadel_max = i2c_specs[mode].vddat_max - init->rise_time; -+ sdadel_max = specs->vddat_max - init->rise_time; - delay = af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); - if (SUB_OVERFLOW(sdadel_max, delay ,&sdadel_max)) - sdadel_max = 0; - -- scldel_min = init->rise_time + i2c_specs[mode].sudat_min; -+ scldel_min = init->rise_time + specs->sudat_min; - -- DMSG("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u\n", -+ DMSG("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u", - sdadel_min, sdadel_max, scldel_min); - - memset(&solutions, 0, sizeof(solutions)); -@@ -360,13 +366,13 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - } - - if (p_prev == I2C_TIMINGR_PRESC_MAX) { -- EMSG(" I2C no Prescaler solution\n"); -+ EMSG(" I2C no Prescaler solution"); - return -1; - } - - tsync = af_delay_min + dnf_delay + (2 * i2cclk); -- clk_max = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_min; -- clk_min = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_max; -+ clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate); -+ clk_min = I2C_NSEC_PER_SEC / specs->rate; - - /* - * Among prescaler possibilities discovered above figures out SCL Low -@@ -388,7 +394,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { - uint32_t tscl_l = ((l + 1) * prescaler) + tsync; - -- if ((tscl_l < i2c_specs[mode].l_min) || -+ if ((tscl_l < specs->l_min) || - (i2cclk >= - ((tscl_l - af_delay_min - dnf_delay) / 4))) { - continue; -@@ -401,7 +407,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - init->fall_time; - - if ((tscl >= clk_min) && (tscl <= clk_max) && -- (tscl_h >= i2c_specs[mode].h_min) && -+ (tscl_h >= specs->h_min) && - (i2cclk < tscl_h)) { - int clk_error = tscl - i2cbus; - -@@ -421,7 +427,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - } - - if (s < 0) { -- EMSG(" I2C no solution at all\n"); -+ EMSG(" I2C no solution at all"); - return -1; - } - -@@ -432,15 +438,47 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init, - I2C_SET_TIMINGR_SCLH(solutions[s].sclh) | - I2C_SET_TIMINGR_SCLL(solutions[s].scll); - -- DMSG("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%i/%i\n", -+ DMSG("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%"PRIu8"/%"PRIu8"", - s, solutions[s].scldel, solutions[s].sdadel); -- DMSG("I2C TIMINGR (SCLH/SCLL): %i/%i\n", -+ DMSG("I2C TIMINGR (SCLH/SCLL): %"PRIu8"/%"PRIu8"", - solutions[s].sclh, solutions[s].scll); -- DMSG("I2C TIMINGR: 0x%x\n", *timing); -+ DMSG("I2C TIMINGR: 0x%"PRIx32"", *timing); - - return 0; - } - -+ -+/* i2c_specs[] must be sorted by increasing rate */ -+static bool __maybe_unused i2c_specs_is_consistent(void) -+{ -+ size_t i; -+ -+ COMPILE_TIME_ASSERT(ARRAY_SIZE(i2c_specs)); -+ -+ for (i = 1; i < ARRAY_SIZE(i2c_specs); i++) -+ if (i2c_specs[i - 1].rate >= i2c_specs[i].rate) -+ return false; -+ -+ return true; -+} -+ -+/* -+ * @brief From requested rate, get the closest I2C rate without exceeding it, -+ * within I2C specification values defined in @i2c_specs. -+ * @param rate: The requested rate. -+ * @retval Found rate, else the lowest value supported by platform. -+ */ -+static uint32_t get_lower_rate(uint32_t rate) -+{ -+ int i; -+ -+ for (i = (int)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 -@@ -456,20 +494,31 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, - int rc = 0; - uint32_t clock_src; - -- clock_src = stm32_clock_get_rate(hi2c->clock); -+ assert(i2c_specs_is_consistent()); -+ -+ clock_src = (uint32_t)stm32_clock_get_rate(hi2c->clock); - if (clock_src == 0U) { -- EMSG("I2C clock rate is 0\n"); -+ EMSG("I2C clock rate is 0"); - return -1; - } - -+ /* -+ * 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) { -- EMSG("Failed to compute I2C timings\n"); -- if (init->speed_mode > I2C_SPEED_STANDARD) { -- init->speed_mode--; -- IMSG("Downgrade I2C speed to %uHz)\n", -- i2c_specs[init->speed_mode].rate); -+ EMSG("Failed to compute I2C timings"); -+ if (init->bus_rate > STANDARD_RATE) { -+ init->bus_rate = get_lower_rate(init->bus_rate); -+ IMSG("Downgrade I2C speed to %"PRIu32"Hz)", -+ init->bus_rate); - } else { - break; - } -@@ -477,17 +526,20 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c, - } while (rc != 0); - - if (rc != 0) { -- EMSG("Impossible to compute I2C timings\n"); -+ EMSG("Impossible to compute I2C timings"); - return rc; - } - -- DMSG("I2C Speed Mode(%i), Freq(%i), Clk Source(%i)\n", -- init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src); -- DMSG("I2C Rise(%i) and Fall(%i) Time\n", -+ DMSG("I2C Freq(%"PRIu32"Hz), Clk Source(%"PRId32")", -+ init->bus_rate, clock_src); -+ DMSG("I2C Rise(%"PRId32") and Fall(%"PRId32") Time", - init->rise_time, init->fall_time); -- DMSG("I2C Analog Filter(%s), DNF(%i)\n", -+ DMSG("I2C Analog Filter(%s), DNF(%"PRId8")", - (init->analog_filter ? "On" : "Off"), init->digital_filter_coef); - -+ hi2c->saved_timing = *timing; -+ hi2c->saved_frequency = clock_src; -+ - return 0; - } - -@@ -543,43 +595,27 @@ int stm32_i2c_get_setup_from_fdt(void *fdt, int node, - struct stm32_pinctrl **pinctrl, - size_t *pinctrl_count) - { -- const fdt32_t *cuint; -+ uint32_t read_val; - int count; - -- cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); -- if (cuint == NULL) { -- init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; -- } else { -- init->rise_time = fdt32_to_cpu(*cuint); -- } -+ init->rise_time = fdt_read_uint32_default(fdt, node, -+ "i2c-scl-rising-time-ns", -+ STM32_I2C_RISE_TIME_DEFAULT); - -- cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); -- if (cuint == NULL) { -- init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; -- } else { -- init->fall_time = fdt32_to_cpu(*cuint); -- } -+ init->fall_time = fdt_read_uint32_default(fdt, node, -+ "i2c-scl-falling-time-ns", -+ STM32_I2C_FALL_TIME_DEFAULT); - -- cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); -- if (cuint == NULL) { -- init->speed_mode = STM32_I2C_SPEED_DEFAULT; -- } else { -- switch (fdt32_to_cpu(*cuint)) { -- case STANDARD_RATE: -- init->speed_mode = I2C_SPEED_STANDARD; -- break; -- case FAST_RATE: -- init->speed_mode = I2C_SPEED_FAST; -- break; -- case FAST_PLUS_RATE: -- init->speed_mode = I2C_SPEED_FAST_PLUS; -- break; -- default: -- init->speed_mode = STM32_I2C_SPEED_DEFAULT; -- break; -- } -+ read_val = fdt_read_uint32_default(fdt, node, "clock-frequency", -+ STANDARD_RATE); -+ if (read_val > FAST_PLUS_RATE) { -+ EMSG("Invalid bus speed (%"PRIu32" > %i)", -+ read_val, FAST_PLUS_RATE); -+ return -FDT_ERR_BADVALUE; - } - -+ init->bus_rate = read_val; -+ - count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); - if (count <= 0) { - *pinctrl = NULL; -@@ -691,7 +727,7 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c, - I2C_ANALOGFILTER_ENABLE : - I2C_ANALOGFILTER_DISABLE); - if (rc != 0) { -- EMSG("Cannot initialize I2C analog filter (%d)\n", rc); -+ EMSG("Cannot initialize I2C analog filter (%d)", rc); - stm32_clock_disable(hi2c->clock); - return rc; - } -diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c -index f1cdc1a..f042808 100644 ---- a/core/drivers/stm32_iwdg.c -+++ b/core/drivers/stm32_iwdg.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. - */ - -@@ -202,13 +202,14 @@ static int stm32_iwdg_conf_etimeout(void *fdt, int node, - void stm32_iwdg_refresh(uint32_t instance) - { - struct stm32_iwdg_instance *iwdg = get_iwdg(instance); -- uintptr_t iwdg_base = get_base(iwdg); - -- assert(iwdg); -+ if (iwdg == NULL) { -+ return; -+ } - - stm32_clock_enable(iwdg->clock); - -- write32(IWDG_KR_RELOAD_KEY, iwdg_base + IWDG_KR_OFFSET); -+ write32(IWDG_KR_RELOAD_KEY, get_base(iwdg) + IWDG_KR_OFFSET); - - stm32_clock_disable(iwdg->clock); - } -@@ -246,14 +247,14 @@ static TEE_Result iwdg_init(void) - iwdg.vbase = (uintptr_t)phys_to_virt(iwdg.pbase, memtype); - - /* DT can specify low power cases */ -- if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) != -+ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) == - NULL) { -- iwdg.flags |= IWDG_ENABLE_ON_STOP; -+ iwdg.flags |= IWDG_DISABLE_ON_STOP; - } - -- if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) != -+ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) == - NULL) { -- iwdg.flags |= IWDG_ENABLE_ON_STANDBY; -+ iwdg.flags |= IWDG_DISABLE_ON_STANDBY; - } - - hw_init = stm32_get_iwdg_otp_config(iwdg.pbase); -@@ -265,12 +266,12 @@ static TEE_Result iwdg_init(void) - iwdg.flags |= IWDG_HW_ENABLED; - } - -- if ((hw_init & IWDG_ENABLE_ON_STOP) != 0) { -- iwdg.flags |= IWDG_ENABLE_ON_STOP; -+ if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) { -+ iwdg.flags |= IWDG_DISABLE_ON_STOP; - } - -- if ((hw_init & IWDG_ENABLE_ON_STANDBY) != 0) { -- iwdg.flags |= IWDG_ENABLE_ON_STANDBY; -+ if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) { -+ iwdg.flags |= IWDG_DISABLE_ON_STANDBY; - } - - if (dt_info.status == DT_STATUS_DISABLED) { -diff --git a/core/drivers/stm32_rtc.c b/core/drivers/stm32_rtc.c -index 709fafa..9834120 100644 ---- a/core/drivers/stm32_rtc.c -+++ b/core/drivers/stm32_rtc.c -@@ -233,20 +233,11 @@ static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal) - * This function computes the fraction difference between two timestamps. - * Here again the returned value is in milliseconds. - ******************************************************************************/ --static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -- struct stm32_rtc_calendar *ref) -+static signed long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, -+ struct stm32_rtc_calendar *ref) - { -- unsigned long long val_r; -- unsigned long long val_c; -- -- val_r = stm32_rtc_get_second_fraction(ref); -- val_c = stm32_rtc_get_second_fraction(cur); -- -- if (val_c >= val_r) { -- return val_c - val_r; -- } else { -- return 1000U - val_r + val_c; -- } -+ return (signed long long)stm32_rtc_get_second_fraction(cur) - -+ (signed long long)stm32_rtc_get_second_fraction(ref); - } - - /******************************************************************************* -@@ -254,10 +245,9 @@ static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur, - * It includes seconds, minutes and hours. - * Here again the returned value is in milliseconds. - ******************************************************************************/ --static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -- struct stm32_rtc_time *ref) -+static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) - { -- signed long long diff_in_s; - signed long long curr_s; - signed long long ref_s; - -@@ -269,12 +259,7 @@ static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current, - (((signed long long)ref->min + - (((signed long long)ref->hour * 60))) * 60); - -- diff_in_s = curr_s - ref_s; -- if (diff_in_s < 0) { -- diff_in_s += 24 * 60 * 60; -- } -- -- return (unsigned long long)diff_in_s * 1000U; -+ return (curr_s - ref_s) * 1000U; - } - - /******************************************************************************* -@@ -292,8 +277,8 @@ static bool stm32_is_a_leap_year(uint32_t year) - * It includes days, months, years, with exceptions. - * Here again the returned value is in milliseconds. - ******************************************************************************/ --static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, -- struct stm32_rtc_time *ref) -+static signed long long stm32_rtc_diff_date(struct stm32_rtc_time *current, -+ struct stm32_rtc_time *ref) - { - uint32_t diff_in_days = 0; - uint32_t m; -@@ -367,7 +352,7 @@ static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, - } - } - -- return (24ULL * 60U * 60U * 1000U) * (unsigned long long)diff_in_days; -+ return (24 * 60 * 60 * 1000) * (signed long long)diff_in_days; - } - - /******************************************************************************* -@@ -377,7 +362,7 @@ static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current, - unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, - struct stm32_rtc_calendar *ref) - { -- unsigned long long diff_in_ms = 0; -+ signed long long diff_in_ms = 0; - struct stm32_rtc_time curr_t; - struct stm32_rtc_time ref_t; - -@@ -394,7 +379,7 @@ unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur, - - stm32_clock_disable(rtc_dev.clock); - -- return diff_in_ms; -+ return (unsigned long long)diff_in_ms; - } - - /******************************************************************************* -diff --git a/core/drivers/stpmic1.c b/core/drivers/stpmic1.c -index 3831d40..d80edbc 100644 ---- a/core/drivers/stpmic1.c -+++ b/core/drivers/stpmic1.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: BSD-3-Clause - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - */ - - #include -@@ -347,6 +347,7 @@ static const uint16_t ldo3_voltage_table[] = { - 3300, - 3300, - 3300, -+ 500, /* VOUT2/2 (Sink/source mode) */ - 0xFFFF, /* VREFDDR */ - }; - -@@ -582,17 +583,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); -@@ -601,7 +604,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) -@@ -635,9 +638,19 @@ int stpmic1_regulator_mask_reset_set(const char *name) - regul->mask_reset); - } - -+int stpmic1_bo_enable_cfg(const char *name, struct stpmic1_bo_cfg *cfg) -+{ -+ const struct regul_struct *regul = get_regulator_data(name); -+ -+ cfg->ctrl_reg = regul->control_reg; -+ -+ return 0; -+} -+ - int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg) - { -- return stpmic1_register_update(cfg->ctrl_reg, BIT(0), BIT(0)); -+ return stpmic1_register_update(cfg->ctrl_reg, LDO_BUCK_ENABLE_MASK, -+ LDO_BUCK_ENABLE_MASK); - } - - /* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ -diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h -index bd33a7b..ee3c918 100644 ---- a/core/include/drivers/stm32_bsec.h -+++ b/core/include/drivers/stm32_bsec.h -@@ -112,6 +112,19 @@ - #define FREQ_30_45_MHZ 0x2 - #define FREQ_45_67_MHZ 0x3 - -+#ifdef CFG_DT -+uint32_t bsec_find_otp_name_in_nvmem_layout(const char *name, uint32_t *otp, -+ uint32_t *otp_bit_len); -+#else -+static inline uint32_t bsec_find_otp_name_in_nvmem_layout( -+ const char *name __unused, -+ uint32_t *otp __unused, -+ uint32_t *otp_bit_len __unused) -+{ -+ return BSEC_ERROR; -+} -+#endif -+ - uint32_t bsec_shadow_register(uint32_t otp); - uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); - uint32_t bsec_write_otp(uint32_t val, uint32_t otp); -diff --git a/core/include/drivers/stm32_i2c.h b/core/include/drivers/stm32_i2c.h -index 3c6e326..83a5b52 100644 ---- a/core/include/drivers/stm32_i2c.h -+++ b/core/include/drivers/stm32_i2c.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - */ - - #ifndef __STM32_I2C_H -@@ -134,15 +134,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; /* -@@ -204,12 +198,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 -@@ -273,6 +262,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 */ - struct stm32_pinctrl *pinctrl; /* PINCTRLs configuration for the I2C PINs */ - size_t pinctrl_count; /* Number of PINCTRLs elements */ - struct i2c_cfg sec_cfg; /* Context for secure usage */ -@@ -335,7 +326,6 @@ struct i2c_handle_s { - /* STM32 specific defines */ - #define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */ - #define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */ --#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD - #define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ - #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ - #define STM32_I2C_DIGITAL_FILTER_MAX 16 -diff --git a/core/include/drivers/stm32_iwdg.h b/core/include/drivers/stm32_iwdg.h -index b649dee..7dbfbbf 100644 ---- a/core/include/drivers/stm32_iwdg.h -+++ b/core/include/drivers/stm32_iwdg.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved - */ - - #ifndef __STM32_IWDG_H__ -@@ -9,8 +9,8 @@ - #include - - #define IWDG_HW_ENABLED BIT(0) --#define IWDG_ENABLE_ON_STOP BIT(1) --#define IWDG_ENABLE_ON_STANDBY BIT(2) -+#define IWDG_DISABLE_ON_STOP BIT(1) -+#define IWDG_DISABLE_ON_STANDBY BIT(2) - - void stm32_iwdg_refresh(uint32_t instance); - -diff --git a/core/include/drivers/stpmic1.h b/core/include/drivers/stpmic1.h -index 3073662..7be6931 100644 ---- a/core/include/drivers/stpmic1.h -+++ b/core/include/drivers/stpmic1.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: BSD-3-Clause */ - /* -- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved -+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved - */ - - #ifndef __STPMIC1_H__ -@@ -85,15 +85,15 @@ - #define ITSOURCE4_REG 0xB3U - - /* Registers masks */ --#define LDO_VOLTAGE_MASK 0x7CU --#define BUCK_VOLTAGE_MASK 0xFCU -+#define LDO_VOLTAGE_MASK GENMASK_32(6, 2) -+#define BUCK_VOLTAGE_MASK GENMASK_32(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_32(1, 0) - - /* Pull down register */ - #define BUCK1_PULL_DOWN_SHIFT 0 -@@ -134,12 +134,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_32(5, 4) - #define VINLOW_HYST_SHIFT 4 --#define VINLOW_THRESHOLD_MASK 0x7 -+#define VINLOW_THRESHOLD_MASK GENMASK_32(3, 1) - #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_32(7, 0) - - /* USB Control Register */ - #define BOOST_OVP_DISABLED BIT(7) -@@ -157,7 +157,7 @@ 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); -@@ -199,6 +199,7 @@ struct stpmic1_lp_cfg { - uint8_t mask; - }; - -+int stpmic1_bo_enable_cfg(const char *name, struct stpmic1_bo_cfg *cfg); - int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg); - int stpmic1_bo_voltage_cfg(const char *name, uint16_t millivolts, - struct stpmic1_bo_cfg *cfg); --- -2.7.4 - diff --git a/recipes-security/optee/optee-os/README.HOW_TO.txt b/recipes-security/optee/optee-os/README.HOW_TO.txt index bac8d42..69e31d3 100644 --- a/recipes-security/optee/optee-os/README.HOW_TO.txt +++ b/recipes-security/optee/optee-os/README.HOW_TO.txt @@ -19,17 +19,17 @@ For optee-os build you need to install: Fedora: sudo yum install git If you have never configured you git configuration: - $> git config --global user.name "your_name" - $> git config --global user.email "your_email@example.com" + $ git config --global user.name "your_name" + $ git config --global user.email "your_email@example.com" 2. Initialise cross-compilation via SDK: --------------------------------------- Source SDK environment: - $> source /environment-setup-cortexa7t2hf-neon-vfpv4-openstlinux_weston-linux-gnueabi + $ source /environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi To verify if your cross-compilation environment have put in place: - $> set | grep CROSS - CROSS_COMPILE=arm-openstlinux_weston-linux-gnueabi- + $ set | grep CROSS + CROSS_COMPILE=arm-ostl-linux-gnueabi- Warning: the environment are valid only on the shell session where you have sourced the sdk environment. @@ -38,55 +38,52 @@ Warning: the environment are valid only on the shell session where you have ------------------------ If you have the tarball and the list of patch then you must extract the tarball and apply the patch. - $> tar xfz .tar.gz - or - $> tar xfj .tar.bz2 - or - $> tar xfJ .tar.xz + $> tar xfz ##BP##-##PR##.tar.gz A new directory containing optee standard source code will be created, go into it: - $> cd + $> cd ##BP## NB: if there is no git management on source code and you would like to have a git management on the code see section 4 [Management of optee-os source code] if there is some patch, please apply it on source code - $> for p in `ls -1 /*.patch`; do patch -p1 < $p; done + $> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done 4. Management of optee-os source code: ----------------------------------- If you like to have a better management of change made on optee-os source, you can use git: - $> cd - $> test -d .git || git init . && git add . && git commit -m "optee-ossource code" && git gc - $> git checkout -b WORKING - $> for p in `ls -1 /*.patch`; do git am $p; done + $ cd + $ test -d .git || git init . && git add . && git commit -m "optee-ossource code" && git gc + $ git checkout -b WORKING + $ for p in `ls -1 /*.patch`; do git am $p; done MANDATORY: You must update sources - $> cd - $> chmod 755 scripts/bin_to_c.py + $ cd + $ chmod 755 scripts/bin_to_c.py NB: you can use directly the source from the community: URL: git://github.com/OP-TEE/optee_os.git Branch: ##GIT_BRANCH## Revision: ##GIT_SRCREV## - $> git clone git://github.com/OP-TEE/optee_os.git - $> cd - $> git checkout -b WORKING ##GIT_SRCREV## - $> for p in `ls -1 /*.patch`; do git am $p; done + $ git clone git://github.com/OP-TEE/optee_os.git + $ cd + $ git checkout -b WORKING ##GIT_SRCREV## + $ for p in `ls -1 /*.patch`; do git am $p; done MANDATORY: You must update sources - $> cd - $> chmod 755 scripts/bin_to_c.py + $ cd + $ chmod 755 scripts/bin_to_c.py 5. Build optee-os source code: -------------------------------- To compile optee-os source code - $> cd $> make -f $PWD/../Makefile.sdk or for a specific config : - $> make -f $PWD/../Makefile.sdk CFG_SECURE_DT=stm32mp157c-ev1 + $ make -f $PWD/../Makefile.sdk CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1 + +Binaries generated are as follow: +##> PWD/../build/tee-*-optee.stm32 -By default, binaries are located in $PWD/../build 6. Update software on board: ---------------------------- @@ -107,7 +104,7 @@ the OP-TEE partitions are the partitions 4/5/6: - SDCARD via USB reader: /dev/sdX4 /dev/sdX5 /dev/sdX6 (where X is the instance identifier) So, for each binary: -$> dd if= of=/dev/ bs=1M conv=fdatasync +$ dd if= of=/dev/ bs=1M conv=fdatasync 6.3. Update via USB mass storage on U-boot: ------------------------------------------- @@ -135,7 +132,7 @@ To find the partition associated to a specific label, connect the SDCARD to your PC or run on target U-boot 'ums' command and list /dev/disk/by-partlabel/ content, i.e: - $> ls -l /dev/disk/by-partlabel/ + $ ls -l /dev/disk/by-partlabel/ total 0 lrwxrwxrwx 1 root root 15 Jan 23 19:11 bootfs -> ../../mmcblk0p7 lrwxrwxrwx 1 root root 15 Jan 23 19:11 fsbl1 -> ../../mmcblk0p1 # FSBL (TF-A) @@ -146,4 +143,4 @@ and list /dev/disk/by-partlabel/ content, i.e: lrwxrwxrwx 1 root root 15 Jan 23 19:11 teeh -> ../../mmcblk0p4 # TEEH (OP-TEE tee-header) lrwxrwxrwx 1 root root 15 Jan 23 19:11 teex -> ../../mmcblk0p6 # TEEX (OP-TEE tee-pager) lrwxrwxrwx 1 root root 16 Jan 23 19:11 userfs -> ../../mmcblk0p10 - lrwxrwxrwx 1 root root 15 Jan 23 19:11 vendorfs -> ../../mmcblk0p8 + lrwxrwxrwx 1 root root 15 Jan 23 19:11 vendorfs -> ../../mmcblk0p8 \ No newline at end of file