meta-st-stm32mp/recipes-security/optee/optee-os/0001-3.9.0-stm32mp-r1.patch

15946 lines
423 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 053c918ec81e85d5dd13087b056a294f69383661 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
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 <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
- adc1_in6_pins_a: adc1-in6 {
- pins {
- pinmux = <STM32_PINMUX('F', 12, ANALOG)>;
- };
- };
-
- adc12_ain_pins_a: adc12-ain-0 {
- pins {
- pinmux = <STM32_PINMUX('C', 3, ANALOG)>, /* ADC1 in13 */
- <STM32_PINMUX('F', 12, ANALOG)>, /* ADC1 in6 */
- <STM32_PINMUX('F', 13, ANALOG)>, /* ADC2 in2 */
- <STM32_PINMUX('F', 14, ANALOG)>; /* ADC2 in6 */
- };
- };
-
- adc12_usb_cc_pins_a: adc12-usb-cc-pins-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* ADC12 in18 */
- <STM32_PINMUX('A', 5, ANALOG)>; /* ADC12 in19 */
- };
- };
-
- cec_pins_a: cec-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 15, AF4)>;
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- cec_pins_sleep_a: cec-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 15, ANALOG)>; /* HDMI_CEC */
- };
- };
-
- cec_pins_b: cec-1 {
- pins {
- pinmux = <STM32_PINMUX('B', 6, AF5)>;
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- cec_pins_sleep_b: cec-sleep-1 {
- pins {
- pinmux = <STM32_PINMUX('B', 6, ANALOG)>; /* HDMI_CEC */
- };
- };
-
- dac_ch1_pins_a: dac-ch1 {
- pins {
- pinmux = <STM32_PINMUX('A', 4, ANALOG)>;
- };
- };
-
- dac_ch2_pins_a: dac-ch2 {
- pins {
- pinmux = <STM32_PINMUX('A', 5, ANALOG)>;
- };
- };
-
- dcmi_pins_a: dcmi-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 8, AF13)>,/* DCMI_HSYNC */
- <STM32_PINMUX('B', 7, AF13)>,/* DCMI_VSYNC */
- <STM32_PINMUX('A', 6, AF13)>,/* DCMI_PIXCLK */
- <STM32_PINMUX('H', 9, AF13)>,/* DCMI_D0 */
- <STM32_PINMUX('H', 10, AF13)>,/* DCMI_D1 */
- <STM32_PINMUX('H', 11, AF13)>,/* DCMI_D2 */
- <STM32_PINMUX('H', 12, AF13)>,/* DCMI_D3 */
- <STM32_PINMUX('H', 14, AF13)>,/* DCMI_D4 */
- <STM32_PINMUX('I', 4, AF13)>,/* DCMI_D5 */
- <STM32_PINMUX('B', 8, AF13)>,/* DCMI_D6 */
- <STM32_PINMUX('E', 6, AF13)>,/* DCMI_D7 */
- <STM32_PINMUX('I', 1, AF13)>,/* DCMI_D8 */
- <STM32_PINMUX('H', 7, AF13)>,/* DCMI_D9 */
- <STM32_PINMUX('I', 3, AF13)>,/* DCMI_D10 */
- <STM32_PINMUX('H', 15, AF13)>;/* DCMI_D11 */
- bias-disable;
- };
- };
-
- dcmi_sleep_pins_a: dcmi-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 8, ANALOG)>,/* DCMI_HSYNC */
- <STM32_PINMUX('B', 7, ANALOG)>,/* DCMI_VSYNC */
- <STM32_PINMUX('A', 6, ANALOG)>,/* DCMI_PIXCLK */
- <STM32_PINMUX('H', 9, ANALOG)>,/* DCMI_D0 */
- <STM32_PINMUX('H', 10, ANALOG)>,/* DCMI_D1 */
- <STM32_PINMUX('H', 11, ANALOG)>,/* DCMI_D2 */
- <STM32_PINMUX('H', 12, ANALOG)>,/* DCMI_D3 */
- <STM32_PINMUX('H', 14, ANALOG)>,/* DCMI_D4 */
- <STM32_PINMUX('I', 4, ANALOG)>,/* DCMI_D5 */
- <STM32_PINMUX('B', 8, ANALOG)>,/* DCMI_D6 */
- <STM32_PINMUX('E', 6, ANALOG)>,/* DCMI_D7 */
- <STM32_PINMUX('I', 1, ANALOG)>,/* DCMI_D8 */
- <STM32_PINMUX('H', 7, ANALOG)>,/* DCMI_D9 */
- <STM32_PINMUX('I', 3, ANALOG)>,/* DCMI_D10 */
- <STM32_PINMUX('H', 15, ANALOG)>;/* DCMI_D11 */
- };
- };
-
- ethernet0_rgmii_pins_a: rgmii-0 {
- pins1 {
- pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
- <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
- <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
- <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
- <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
- <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
- <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
- <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
- bias-disable;
- drive-push-pull;
- slew-rate = <2>;
- };
- pins2 {
- pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
- bias-disable;
- drive-push-pull;
- slew-rate = <0>;
- };
- pins3 {
- pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
- <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
- <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
- <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */
- <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
- <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
- bias-disable;
- };
- };
-
- ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 {
- pins1 {
- pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
- <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
- <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
- <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
- <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
- <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
- <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
- <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
- <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
- <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
- <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
- <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
- <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
- <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
- <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
- };
- };
-
fmc_pins_a: fmc-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
@@ -187,412 +31,6 @@
};
};
- fmc_sleep_pins_a: fmc-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
- <STM32_PINMUX('D', 5, ANALOG)>, /* FMC_NWE */
- <STM32_PINMUX('D', 11, ANALOG)>, /* FMC_A16_FMC_CLE */
- <STM32_PINMUX('D', 12, ANALOG)>, /* FMC_A17_FMC_ALE */
- <STM32_PINMUX('D', 14, ANALOG)>, /* FMC_D0 */
- <STM32_PINMUX('D', 15, ANALOG)>, /* FMC_D1 */
- <STM32_PINMUX('D', 0, ANALOG)>, /* FMC_D2 */
- <STM32_PINMUX('D', 1, ANALOG)>, /* FMC_D3 */
- <STM32_PINMUX('E', 7, ANALOG)>, /* FMC_D4 */
- <STM32_PINMUX('E', 8, ANALOG)>, /* FMC_D5 */
- <STM32_PINMUX('E', 9, ANALOG)>, /* FMC_D6 */
- <STM32_PINMUX('E', 10, ANALOG)>, /* FMC_D7 */
- <STM32_PINMUX('D', 6, ANALOG)>, /* FMC_NWAIT */
- <STM32_PINMUX('G', 9, ANALOG)>; /* FMC_NE2_FMC_NCE */
- };
- };
-
- i2c1_pins_a: i2c1-0 {
- pins {
- pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
- <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- i2c1_pins_sleep_a: i2c1-1 {
- pins {
- pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */
- <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
- };
- };
-
- i2c1_pins_b: i2c1-2 {
- pins {
- pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
- <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- i2c1_pins_sleep_b: i2c1-3 {
- pins {
- pinmux = <STM32_PINMUX('F', 14, ANALOG)>, /* I2C1_SCL */
- <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
- };
- };
-
- i2c2_pins_a: i2c2-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
- <STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- i2c2_pins_sleep_a: i2c2-1 {
- pins {
- pinmux = <STM32_PINMUX('H', 4, ANALOG)>, /* I2C2_SCL */
- <STM32_PINMUX('H', 5, ANALOG)>; /* I2C2_SDA */
- };
- };
-
- i2c2_pins_b1: i2c2-2 {
- pins {
- pinmux = <STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- i2c2_pins_sleep_b1: i2c2-3 {
- pins {
- pinmux = <STM32_PINMUX('H', 5, ANALOG)>; /* I2C2_SDA */
- };
- };
-
- i2c5_pins_a: i2c5-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
- <STM32_PINMUX('A', 12, AF4)>; /* I2C5_SDA */
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
- };
- };
-
- i2c5_pins_sleep_a: i2c5-1 {
- pins {
- pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* I2C5_SCL */
- <STM32_PINMUX('A', 12, ANALOG)>; /* I2C5_SDA */
-
- };
- };
-
- i2s2_pins_a: i2s2-0 {
- pins {
- pinmux = <STM32_PINMUX('I', 3, AF5)>, /* I2S2_SDO */
- <STM32_PINMUX('B', 9, AF5)>, /* I2S2_WS */
- <STM32_PINMUX('A', 9, AF5)>; /* I2S2_CK */
- slew-rate = <1>;
- drive-push-pull;
- bias-disable;
- };
- };
-
- i2s2_pins_sleep_a: i2s2-1 {
- pins {
- pinmux = <STM32_PINMUX('I', 3, ANALOG)>, /* I2S2_SDO */
- <STM32_PINMUX('B', 9, ANALOG)>, /* I2S2_WS */
- <STM32_PINMUX('A', 9, ANALOG)>; /* I2S2_CK */
- };
- };
-
- ltdc_pins_a: ltdc-a-0 {
- pins {
- pinmux = <STM32_PINMUX('G', 7, AF14)>, /* LCD_CLK */
- <STM32_PINMUX('I', 10, AF14)>, /* LCD_HSYNC */
- <STM32_PINMUX('I', 9, AF14)>, /* LCD_VSYNC */
- <STM32_PINMUX('F', 10, AF14)>, /* LCD_DE */
- <STM32_PINMUX('H', 2, AF14)>, /* LCD_R0 */
- <STM32_PINMUX('H', 3, AF14)>, /* LCD_R1 */
- <STM32_PINMUX('H', 8, AF14)>, /* LCD_R2 */
- <STM32_PINMUX('H', 9, AF14)>, /* LCD_R3 */
- <STM32_PINMUX('H', 10, AF14)>, /* LCD_R4 */
- <STM32_PINMUX('C', 0, AF14)>, /* LCD_R5 */
- <STM32_PINMUX('H', 12, AF14)>, /* LCD_R6 */
- <STM32_PINMUX('E', 15, AF14)>, /* LCD_R7 */
- <STM32_PINMUX('E', 5, AF14)>, /* LCD_G0 */
- <STM32_PINMUX('E', 6, AF14)>, /* LCD_G1 */
- <STM32_PINMUX('H', 13, AF14)>, /* LCD_G2 */
- <STM32_PINMUX('H', 14, AF14)>, /* LCD_G3 */
- <STM32_PINMUX('H', 15, AF14)>, /* LCD_G4 */
- <STM32_PINMUX('I', 0, AF14)>, /* LCD_G5 */
- <STM32_PINMUX('I', 1, AF14)>, /* LCD_G6 */
- <STM32_PINMUX('I', 2, AF14)>, /* LCD_G7 */
- <STM32_PINMUX('D', 9, AF14)>, /* LCD_B0 */
- <STM32_PINMUX('G', 12, AF14)>, /* LCD_B1 */
- <STM32_PINMUX('G', 10, AF14)>, /* LCD_B2 */
- <STM32_PINMUX('D', 10, AF14)>, /* LCD_B3 */
- <STM32_PINMUX('I', 4, AF14)>, /* LCD_B4 */
- <STM32_PINMUX('A', 3, AF14)>, /* LCD_B5 */
- <STM32_PINMUX('B', 8, AF14)>, /* LCD_B6 */
- <STM32_PINMUX('D', 8, AF14)>; /* LCD_B7 */
- bias-disable;
- drive-push-pull;
- slew-rate = <1>;
- };
- };
-
- ltdc_pins_sleep_a: ltdc-a-1 {
- pins {
- pinmux = <STM32_PINMUX('G', 7, ANALOG)>, /* LCD_CLK */
- <STM32_PINMUX('I', 10, ANALOG)>, /* LCD_HSYNC */
- <STM32_PINMUX('I', 9, ANALOG)>, /* LCD_VSYNC */
- <STM32_PINMUX('F', 10, ANALOG)>, /* LCD_DE */
- <STM32_PINMUX('H', 2, ANALOG)>, /* LCD_R0 */
- <STM32_PINMUX('H', 3, ANALOG)>, /* LCD_R1 */
- <STM32_PINMUX('H', 8, ANALOG)>, /* LCD_R2 */
- <STM32_PINMUX('H', 9, ANALOG)>, /* LCD_R3 */
- <STM32_PINMUX('H', 10, ANALOG)>, /* LCD_R4 */
- <STM32_PINMUX('C', 0, ANALOG)>, /* LCD_R5 */
- <STM32_PINMUX('H', 12, ANALOG)>, /* LCD_R6 */
- <STM32_PINMUX('E', 15, ANALOG)>, /* LCD_R7 */
- <STM32_PINMUX('E', 5, ANALOG)>, /* LCD_G0 */
- <STM32_PINMUX('E', 6, ANALOG)>, /* LCD_G1 */
- <STM32_PINMUX('H', 13, ANALOG)>, /* LCD_G2 */
- <STM32_PINMUX('H', 14, ANALOG)>, /* LCD_G3 */
- <STM32_PINMUX('H', 15, ANALOG)>, /* LCD_G4 */
- <STM32_PINMUX('I', 0, ANALOG)>, /* LCD_G5 */
- <STM32_PINMUX('I', 1, ANALOG)>, /* LCD_G6 */
- <STM32_PINMUX('I', 2, ANALOG)>, /* LCD_G7 */
- <STM32_PINMUX('D', 9, ANALOG)>, /* LCD_B0 */
- <STM32_PINMUX('G', 12, ANALOG)>, /* LCD_B1 */
- <STM32_PINMUX('G', 10, ANALOG)>, /* LCD_B2 */
- <STM32_PINMUX('D', 10, ANALOG)>, /* LCD_B3 */
- <STM32_PINMUX('I', 4, ANALOG)>, /* LCD_B4 */
- <STM32_PINMUX('A', 3, ANALOG)>, /* LCD_B5 */
- <STM32_PINMUX('B', 8, ANALOG)>, /* LCD_B6 */
- <STM32_PINMUX('D', 8, ANALOG)>; /* LCD_B7 */
- };
- };
-
- ltdc_pins_b: ltdc-b-0 {
- pins {
- pinmux = <STM32_PINMUX('I', 14, AF14)>, /* LCD_CLK */
- <STM32_PINMUX('I', 12, AF14)>, /* LCD_HSYNC */
- <STM32_PINMUX('I', 13, AF14)>, /* LCD_VSYNC */
- <STM32_PINMUX('K', 7, AF14)>, /* LCD_DE */
- <STM32_PINMUX('I', 15, AF14)>, /* LCD_R0 */
- <STM32_PINMUX('J', 0, AF14)>, /* LCD_R1 */
- <STM32_PINMUX('J', 1, AF14)>, /* LCD_R2 */
- <STM32_PINMUX('J', 2, AF14)>, /* LCD_R3 */
- <STM32_PINMUX('J', 3, AF14)>, /* LCD_R4 */
- <STM32_PINMUX('J', 4, AF14)>, /* LCD_R5 */
- <STM32_PINMUX('J', 5, AF14)>, /* LCD_R6 */
- <STM32_PINMUX('J', 6, AF14)>, /* LCD_R7 */
- <STM32_PINMUX('J', 7, AF14)>, /* LCD_G0 */
- <STM32_PINMUX('J', 8, AF14)>, /* LCD_G1 */
- <STM32_PINMUX('J', 9, AF14)>, /* LCD_G2 */
- <STM32_PINMUX('J', 10, AF14)>, /* LCD_G3 */
- <STM32_PINMUX('J', 11, AF14)>, /* LCD_G4 */
- <STM32_PINMUX('K', 0, AF14)>, /* LCD_G5 */
- <STM32_PINMUX('K', 1, AF14)>, /* LCD_G6 */
- <STM32_PINMUX('K', 2, AF14)>, /* LCD_G7 */
- <STM32_PINMUX('J', 12, AF14)>, /* LCD_B0 */
- <STM32_PINMUX('J', 13, AF14)>, /* LCD_B1 */
- <STM32_PINMUX('J', 14, AF14)>, /* LCD_B2 */
- <STM32_PINMUX('J', 15, AF14)>, /* LCD_B3 */
- <STM32_PINMUX('K', 3, AF14)>, /* LCD_B4 */
- <STM32_PINMUX('K', 4, AF14)>, /* LCD_B5 */
- <STM32_PINMUX('K', 5, AF14)>, /* LCD_B6 */
- <STM32_PINMUX('K', 6, AF14)>; /* LCD_B7 */
- bias-disable;
- drive-push-pull;
- slew-rate = <1>;
- };
- };
-
- ltdc_pins_sleep_b: ltdc-b-1 {
- pins {
- pinmux = <STM32_PINMUX('I', 14, ANALOG)>, /* LCD_CLK */
- <STM32_PINMUX('I', 12, ANALOG)>, /* LCD_HSYNC */
- <STM32_PINMUX('I', 13, ANALOG)>, /* LCD_VSYNC */
- <STM32_PINMUX('K', 7, ANALOG)>, /* LCD_DE */
- <STM32_PINMUX('I', 15, ANALOG)>, /* LCD_R0 */
- <STM32_PINMUX('J', 0, ANALOG)>, /* LCD_R1 */
- <STM32_PINMUX('J', 1, ANALOG)>, /* LCD_R2 */
- <STM32_PINMUX('J', 2, ANALOG)>, /* LCD_R3 */
- <STM32_PINMUX('J', 3, ANALOG)>, /* LCD_R4 */
- <STM32_PINMUX('J', 4, ANALOG)>, /* LCD_R5 */
- <STM32_PINMUX('J', 5, ANALOG)>, /* LCD_R6 */
- <STM32_PINMUX('J', 6, ANALOG)>, /* LCD_R7 */
- <STM32_PINMUX('J', 7, ANALOG)>, /* LCD_G0 */
- <STM32_PINMUX('J', 8, ANALOG)>, /* LCD_G1 */
- <STM32_PINMUX('J', 9, ANALOG)>, /* LCD_G2 */
- <STM32_PINMUX('J', 10, ANALOG)>, /* LCD_G3 */
- <STM32_PINMUX('J', 11, ANALOG)>, /* LCD_G4 */
- <STM32_PINMUX('K', 0, ANALOG)>, /* LCD_G5 */
- <STM32_PINMUX('K', 1, ANALOG)>, /* LCD_G6 */
- <STM32_PINMUX('K', 2, ANALOG)>, /* LCD_G7 */
- <STM32_PINMUX('J', 12, ANALOG)>, /* LCD_B0 */
- <STM32_PINMUX('J', 13, ANALOG)>, /* LCD_B1 */
- <STM32_PINMUX('J', 14, ANALOG)>, /* LCD_B2 */
- <STM32_PINMUX('J', 15, ANALOG)>, /* LCD_B3 */
- <STM32_PINMUX('K', 3, ANALOG)>, /* LCD_B4 */
- <STM32_PINMUX('K', 4, ANALOG)>, /* LCD_B5 */
- <STM32_PINMUX('K', 5, ANALOG)>, /* LCD_B6 */
- <STM32_PINMUX('K', 6, ANALOG)>; /* LCD_B7 */
- };
- };
-
- m_can1_pins_a: m-can1-0 {
- pins1 {
- pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
- slew-rate = <1>;
- drive-push-pull;
- bias-disable;
- };
- pins2 {
- pinmux = <STM32_PINMUX('I', 9, AF9)>; /* CAN1_RX */
- bias-disable;
- };
- };
-
- m_can1_sleep_pins_a: m_can1-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* CAN1_TX */
- <STM32_PINMUX('I', 9, ANALOG)>; /* CAN1_RX */
- };
- };
-
- pwm1_pins_a: pwm1-0 {
- pins {
- pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */
- <STM32_PINMUX('E', 11, AF1)>, /* TIM1_CH2 */
- <STM32_PINMUX('E', 14, AF1)>; /* TIM1_CH4 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm1_sleep_pins_a: pwm1-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('E', 9, ANALOG)>, /* TIM1_CH1 */
- <STM32_PINMUX('E', 11, ANALOG)>, /* TIM1_CH2 */
- <STM32_PINMUX('E', 14, ANALOG)>; /* TIM1_CH4 */
- };
- };
-
- pwm2_pins_a: pwm2-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm2_sleep_pins_a: pwm2-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 3, ANALOG)>; /* TIM2_CH4 */
- };
- };
-
- pwm3_pins_a: pwm3-0 {
- pins {
- pinmux = <STM32_PINMUX('C', 7, AF2)>; /* TIM3_CH2 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm3_sleep_pins_a: pwm3-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('C', 7, ANALOG)>; /* TIM3_CH2 */
- };
- };
-
- pwm4_pins_a: pwm4-0 {
- pins {
- pinmux = <STM32_PINMUX('D', 14, AF2)>, /* TIM4_CH3 */
- <STM32_PINMUX('D', 15, AF2)>; /* TIM4_CH4 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm4_sleep_pins_a: pwm4-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('D', 14, ANALOG)>, /* TIM4_CH3 */
- <STM32_PINMUX('D', 15, ANALOG)>; /* TIM4_CH4 */
- };
- };
-
- pwm4_pins_b: pwm4-1 {
- pins {
- pinmux = <STM32_PINMUX('D', 13, AF2)>; /* TIM4_CH2 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm4_sleep_pins_b: pwm4-sleep-1 {
- pins {
- pinmux = <STM32_PINMUX('D', 13, ANALOG)>; /* TIM4_CH2 */
- };
- };
-
- pwm5_pins_a: pwm5-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 11, AF2)>; /* TIM5_CH2 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm5_sleep_pins_a: pwm5-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 11, ANALOG)>; /* TIM5_CH2 */
- };
- };
-
- pwm8_pins_a: pwm8-0 {
- pins {
- pinmux = <STM32_PINMUX('I', 2, AF3)>; /* TIM8_CH4 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm8_sleep_pins_a: pwm8-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('I', 2, ANALOG)>; /* TIM8_CH4 */
- };
- };
-
- pwm12_pins_a: pwm12-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 6, AF2)>; /* TIM12_CH1 */
- bias-pull-down;
- drive-push-pull;
- slew-rate = <0>;
- };
- };
-
- pwm12_sleep_pins_a: pwm12-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('H', 6, ANALOG)>; /* TIM12_CH1 */
- };
- };
-
qspi_clk_pins_a: qspi-clk-0 {
pins {
pinmux = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
@@ -602,12 +40,6 @@
};
};
- qspi_clk_sleep_pins_a: qspi-clk-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('F', 10, ANALOG)>; /* QSPI_CLK */
- };
- };
-
qspi_bk1_pins_a: qspi-bk1-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
@@ -626,16 +58,6 @@
};
};
- qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('F', 8, ANALOG)>, /* QSPI_BK1_IO0 */
- <STM32_PINMUX('F', 9, ANALOG)>, /* QSPI_BK1_IO1 */
- <STM32_PINMUX('F', 7, ANALOG)>, /* QSPI_BK1_IO2 */
- <STM32_PINMUX('F', 6, ANALOG)>, /* QSPI_BK1_IO3 */
- <STM32_PINMUX('B', 6, ANALOG)>; /* QSPI_BK1_NCS */
- };
- };
-
qspi_bk2_pins_a: qspi-bk2-0 {
pins1 {
pinmux = <STM32_PINMUX('H', 2, AF9)>, /* 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 = <STM32_PINMUX('H', 2, ANALOG)>, /* QSPI_BK2_IO0 */
- <STM32_PINMUX('H', 3, ANALOG)>, /* QSPI_BK2_IO1 */
- <STM32_PINMUX('G', 10, ANALOG)>, /* QSPI_BK2_IO2 */
- <STM32_PINMUX('G', 7, ANALOG)>, /* QSPI_BK2_IO3 */
- <STM32_PINMUX('C', 0, ANALOG)>; /* QSPI_BK2_NCS */
- };
- };
-
- sai2a_pins_a: sai2a-0 {
- pins {
- pinmux = <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */
- <STM32_PINMUX('I', 6, AF10)>, /* SAI2_SD_A */
- <STM32_PINMUX('I', 7, AF10)>, /* SAI2_FS_A */
- <STM32_PINMUX('E', 0, AF10)>; /* SAI2_MCLK_A */
- slew-rate = <0>;
- drive-push-pull;
- bias-disable;
- };
- };
-
- sai2a_sleep_pins_a: sai2a-1 {
- pins {
- pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* SAI2_SCK_A */
- <STM32_PINMUX('I', 6, ANALOG)>, /* SAI2_SD_A */
- <STM32_PINMUX('I', 7, ANALOG)>, /* SAI2_FS_A */
- <STM32_PINMUX('E', 0, ANALOG)>; /* SAI2_MCLK_A */
- };
- };
-
- sai2b_pins_a: sai2b-0 {
- pins1 {
- pinmux = <STM32_PINMUX('E', 12, AF10)>, /* SAI2_SCK_B */
- <STM32_PINMUX('E', 13, AF10)>, /* SAI2_FS_B */
- <STM32_PINMUX('E', 14, AF10)>; /* SAI2_MCLK_B */
- slew-rate = <0>;
- drive-push-pull;
- bias-disable;
- };
- pins2 {
- pinmux = <STM32_PINMUX('F', 11, AF10)>; /* SAI2_SD_B */
- bias-disable;
- };
- };
-
- sai2b_sleep_pins_a: sai2b-1 {
- pins {
- pinmux = <STM32_PINMUX('F', 11, ANALOG)>, /* SAI2_SD_B */
- <STM32_PINMUX('E', 12, ANALOG)>, /* SAI2_SCK_B */
- <STM32_PINMUX('E', 13, ANALOG)>, /* SAI2_FS_B */
- <STM32_PINMUX('E', 14, ANALOG)>; /* SAI2_MCLK_B */
- };
- };
-
- sai2b_pins_b: sai2b-2 {
- pins {
- pinmux = <STM32_PINMUX('F', 11, AF10)>; /* SAI2_SD_B */
- bias-disable;
- };
- };
-
- sai2b_sleep_pins_b: sai2b-3 {
- pins {
- pinmux = <STM32_PINMUX('F', 11, ANALOG)>; /* SAI2_SD_B */
- };
- };
-
- sai4a_pins_a: sai4a-0 {
- pins {
- pinmux = <STM32_PINMUX('B', 5, AF10)>; /* SAI4_SD_A */
- slew-rate = <0>;
- drive-push-pull;
- bias-disable;
- };
- };
-
- sai4a_sleep_pins_a: sai4a-1 {
- pins {
- pinmux = <STM32_PINMUX('B', 5, ANALOG)>; /* SAI4_SD_A */
+ pinmux = <STM32_PINMUX('I', 8, ANALOG)>; /* RTC_OUT2_RMP */
};
};
@@ -756,41 +101,6 @@
};
};
- sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
- pins1 {
- pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
- <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
- <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
- <STM32_PINMUX('C', 11, AF12)>; /* SDMMC1_D3 */
- slew-rate = <1>;
- drive-push-pull;
- bias-disable;
- };
- pins2 {
- pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
- slew-rate = <2>;
- drive-push-pull;
- bias-disable;
- };
- pins3 {
- pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
- slew-rate = <1>;
- drive-open-drain;
- bias-disable;
- };
- };
-
- sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
- <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
- <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
- <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
- <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
- <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
- };
- };
-
sdmmc1_dir_pins_a: sdmmc1-dir-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
@@ -806,15 +116,6 @@
};
};
- sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('F', 2, ANALOG)>, /* SDMMC1_D0DIR */
- <STM32_PINMUX('C', 7, ANALOG)>, /* SDMMC1_D123DIR */
- <STM32_PINMUX('B', 9, ANALOG)>, /* SDMMC1_CDIR */
- <STM32_PINMUX('E', 4, ANALOG)>; /* SDMMC1_CKIN */
- };
- };
-
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
@@ -834,41 +135,6 @@
};
};
- sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 {
- pins1 {
- pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
- <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
- <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
- <STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
- slew-rate = <1>;
- drive-push-pull;
- bias-pull-up;
- };
- pins2 {
- pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
- slew-rate = <2>;
- drive-push-pull;
- bias-pull-up;
- };
- pins3 {
- pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
- slew-rate = <1>;
- drive-open-drain;
- bias-pull-up;
- };
- };
-
- sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
- <STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */
- <STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */
- <STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */
- <STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */
- <STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */
- };
- };
-
sdmmc2_b4_pins_b: sdmmc2-b4-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
@@ -888,30 +154,6 @@
};
};
- sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 {
- pins1 {
- pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
- <STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
- <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
- <STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
- slew-rate = <1>;
- drive-push-pull;
- bias-disable;
- };
- pins2 {
- pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
- slew-rate = <2>;
- drive-push-pull;
- bias-disable;
- };
- pins3 {
- pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
- slew-rate = <1>;
- drive-open-drain;
- bias-disable;
- };
- };
-
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -924,140 +166,120 @@
};
};
- sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
- <STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */
- <STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC2_D6 */
- <STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */
- };
- };
-
- sdmmc3_b4_pins_a: sdmmc3-b4-0 {
+ uart4_pins_a: uart4-0 {
pins1 {
- pinmux = <STM32_PINMUX('F', 0, AF9)>, /* SDMMC3_D0 */
- <STM32_PINMUX('F', 4, AF9)>, /* SDMMC3_D1 */
- <STM32_PINMUX('F', 5, AF9)>, /* SDMMC3_D2 */
- <STM32_PINMUX('D', 7, AF10)>, /* SDMMC3_D3 */
- <STM32_PINMUX('F', 1, AF9)>; /* SDMMC3_CMD */
- slew-rate = <1>;
+ pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+ bias-disable;
drive-push-pull;
- bias-pull-up;
+ slew-rate = <0>;
};
pins2 {
- pinmux = <STM32_PINMUX('G', 15, AF10)>; /* SDMMC3_CK */
- slew-rate = <2>;
- drive-push-pull;
- bias-pull-up;
+ pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ bias-disable;
};
};
- sdmmc3_b4_od_pins_a: sdmmc3-b4-od-0 {
+ uart4_pins_b: uart4-1 {
pins1 {
- pinmux = <STM32_PINMUX('F', 0, AF9)>, /* SDMMC3_D0 */
- <STM32_PINMUX('F', 4, AF9)>, /* SDMMC3_D1 */
- <STM32_PINMUX('F', 5, AF9)>, /* SDMMC3_D2 */
- <STM32_PINMUX('D', 7, AF10)>; /* SDMMC3_D3 */
- slew-rate = <1>;
+ pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
+ bias-disable;
drive-push-pull;
- bias-pull-up;
+ slew-rate = <0>;
};
pins2 {
- pinmux = <STM32_PINMUX('G', 15, AF10)>; /* SDMMC3_CK */
- slew-rate = <2>;
- drive-push-pull;
- bias-pull-up;
- };
- pins3 {
- pinmux = <STM32_PINMUX('F', 1, AF9)>; /* SDMMC2_CMD */
- slew-rate = <1>;
- drive-open-drain;
- bias-pull-up;
+ pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ bias-disable;
};
};
- sdmmc3_b4_sleep_pins_a: sdmmc3-b4-sleep-0 {
- pins {
- pinmux = <STM32_PINMUX('F', 0, ANALOG)>, /* SDMMC3_D0 */
- <STM32_PINMUX('F', 4, ANALOG)>, /* SDMMC3_D1 */
- <STM32_PINMUX('F', 5, ANALOG)>, /* SDMMC3_D2 */
- <STM32_PINMUX('D', 7, ANALOG)>, /* SDMMC3_D3 */
- <STM32_PINMUX('G', 15, ANALOG)>, /* SDMMC3_CK */
- <STM32_PINMUX('F', 1, ANALOG)>; /* SDMMC3_CMD */
+ uart7_pins_a: uart7-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART4_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
};
- };
-
- spdifrx_pins_a: spdifrx-0 {
- pins {
- pinmux = <STM32_PINMUX('G', 12, AF8)>; /* SPDIF_IN1 */
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART4_RX */
+ <STM32_PINMUX('E', 10, AF7)>, /* UART4_CTS */
+ <STM32_PINMUX('E', 9, AF7)>; /* UART4_RTS */
bias-disable;
};
};
- spdifrx_sleep_pins_a: spdifrx-1 {
- pins {
- pinmux = <STM32_PINMUX('G', 12, ANALOG)>; /* SPDIF_IN1 */
+ uart7_pins_b: uart7-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+ bias-disable;
};
};
- uart4_pins_a: uart4-0 {
+ usart2_pins_a: usart2-0 {
pins1 {
- pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+ pinmux = <STM32_PINMUX('D', 5, AF7)>, /* USART2_TX */
+ <STM32_PINMUX('D', 4, AF7)>; /* USART2_RTS */
bias-disable;
drive-push-pull;
- slew-rate = <0>;
+ slew-rate = <3>;
};
pins2 {
- pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ pinmux = <STM32_PINMUX('D', 6, AF7)>, /* USART2_RX */
+ <STM32_PINMUX('D', 3, AF7)>; /* USART2_CTS_NSS */
bias-disable;
};
};
- uart4_pins_b: uart4-1 {
+ usart3_pins_a: usart3-0 {
pins1 {
- pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
+ pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+ <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
pins2 {
- pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+ <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
bias-disable;
};
};
- uart7_pins_a: uart7-0 {
+ usart3_pins_b: usart3-1 {
pins1 {
- pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART4_TX */
+ pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+ <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
pins2 {
- pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART4_RX */
- <STM32_PINMUX('E', 10, AF7)>, /* UART4_CTS */
- <STM32_PINMUX('E', 9, AF7)>; /* UART4_RTS */
+ pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+ <STM32_PINMUX('B', 13, AF7)>; /* USART3_CTS_NSS */
bias-disable;
};
};
-};
-&pinctrl_z {
- i2c2_pins_b2: i2c2-0 {
+ usbotg_hs_pins_a: usbotg_hs-0 {
pins {
- pinmux = <STM32_PINMUX('Z', 0, AF3)>; /* I2C2_SCL */
- bias-disable;
- drive-open-drain;
- slew-rate = <0>;
+ pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
};
};
- i2c2_pins_sleep_b2: i2c2-1 {
+ usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 {
pins {
- pinmux = <STM32_PINMUX('Z', 0, ANALOG)>; /* I2C2_SCL */
+ pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* OTG_FS_DM */
+ <STM32_PINMUX('A', 12, ANALOG)>; /* OTG_FS_DP */
};
};
+};
+&pinctrl_z {
i2c4_pins_a: i2c4-0 {
pins {
pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
@@ -1067,26 +289,4 @@
slew-rate = <0>;
};
};
-
- i2c4_pins_sleep_a: i2c4-1 {
- pins {
- pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
- <STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
- };
- };
-
- spi1_pins_a: spi1-0 {
- pins1 {
- pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
- <STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
- bias-disable;
- drive-push-pull;
- slew-rate = <1>;
- };
-
- pins2 {
- pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* 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 = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
- 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 = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART2_K>;
+ resets = <&rcc USART2_R>;
status = "disabled";
};
@@ -452,14 +129,17 @@
reg = <0x4000f000 0x400>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART3_K>;
+ resets = <&rcc USART3_R>;
status = "disabled";
};
uart4: serial@40010000 {
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
- interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
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 = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART7_K>;
+ resets = <&rcc UART7_R>;
status = "disabled";
};
@@ -569,125 +166,16 @@
reg = <0x40019000 0x400>;
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
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 = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART6_K>;
- status = "disabled";
- };
-
- spi1: spi@44004000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "st,stm32h7-spi";
- reg = <0x44004000 0x400>;
- interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&dmamux1 92 0x400 0x01>;
- dma-names = "rx";
- status = "disabled";
- };
- };
-
- dma1: dma-controller@48000000 {
- compatible = "st,stm32-dma";
- reg = <0x48000000 0x400>;
- interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&rcc DMA1>;
- #dma-cells = <4>;
- st,mem2mem;
- dma-requests = <8>;
- };
-
- dma2: dma-controller@48001000 {
- compatible = "st,stm32-dma";
- reg = <0x48001000 0x400>;
- interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ secure-interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&rcc TMPSENS>;
- clock-names = "pclk";
- #thermal-sensor-cells = <0>;
- status = "disabled";
- };
-
hash1: hash@54002000 {
compatible = "st,stm32f756-hash";
reg = <0x54002000 0x400>;
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
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 = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
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 = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
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 = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
- status = "disabled";
- };
-
- usbh_ehci: usbh-ehci@5800d000 {
- compatible = "generic-ehci";
- reg = <0x5800d000 0x1000>;
- clocks = <&rcc USBH>;
- resets = <&rcc USBH_R>;
- interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- companion = <&usbh_ohci>;
- status = "disabled";
- };
-
- ltdc: display-controller@5a001000 {
- compatible = "st,stm32-ltdc";
- reg = <0x5a001000 0x400>;
- interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
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 = <&reg11>;
+ vdda1v8-supply = <&reg18>;
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 = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
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 = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ 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 = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- 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 = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
- 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 <dt-bindings/soc/st,stm32-etzpc.h>
/ {
model = "STMicroelectronics STM32MP157A-DK1 Discovery Board";
compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
aliases {
- ethernet0 = &ethernet0;
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 <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xa.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxaa-pinctrl.dtsi"
+#include "stm32mp15xx-edx.dtsi"
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+
+/ {
+ 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 <alexandre.torgue@st.com> 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 <dt-bindings/soc/st,stm32-etzpc.h>
/ {
model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
aliases {
- ethernet0 = &ethernet0;
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 = <&reg18>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dsi_in: endpoint {
- remote-endpoint = <&ltdc_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";
- };
};
-&ltdc {
- 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 <ludovic.barre@st.com> for STMicroelectronics.
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
/dts-v1/;
@@ -9,8 +9,8 @@
#include "stm32mp15xc.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxaa-pinctrl.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/mfd/st,stpmic1.h>
+#include "stm32mp15xx-edx.dtsi"
+#include <dt-bindings/soc/st,stm32-etzpc.h>
/ {
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 = <IT_CURLIM_LDO1 0>;
- };
-
- v2v8: ldo2 {
- regulator-name = "v2v8";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- interrupts = <IT_CURLIM_LDO2 0>;
- };
-
- 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 = <IT_CURLIM_LDO4 0>;
- };
-
- vdd_sd: ldo5 {
- regulator-name = "vdd_sd";
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- interrupts = <IT_CURLIM_LDO5 0>;
- regulator-boot-on;
- };
-
- v1v8: ldo6 {
- regulator-name = "v1v8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- interrupts = <IT_CURLIM_LDO6 0>;
- };
-
- vref_ddr: vref_ddr {
- regulator-name = "vref_ddr";
- regulator-always-on;
- regulator-over-current-protection;
- };
-
- bst_out: boost {
- regulator-name = "bst_out";
- interrupts = <IT_OCP_BOOST 0>;
- };
-
- vbus_otg: pwr_sw1 {
- regulator-name = "vbus_otg";
- interrupts = <IT_OCP_OTG 0>;
- };
-
- vbus_sw: pwr_sw2 {
- regulator-name = "vbus_sw";
- interrupts = <IT_OCP_SWOUT 0>;
- regulator-active-discharge = <1>;
- };
- };
-
- onkey {
- compatible = "st,stpmic1-onkey";
- interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
- 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 = <&reg11>;
- vdda1v8-supply = <&reg18>;
-};
-
-&usbphyc_port1 {
- phy-supply = <&vdd_usb>;
- vdda1v1-supply = <&reg11>;
- vdda1v8-supply = <&reg18>;
-};
-
-&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 <ludovic.barre@st.com> for STMicroelectronics.
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
/dts-v1/;
#include "stm32mp157c-ed1.dts"
-#include <dt-bindings/gpio/gpio.h>
-/* #include <dt-bindings/input/input.h> 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 = &ethernet0;
+ 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 = <KEY_ENTER>; BSD license issue */
- interrupt-parent = <&stmfx_pinctrl>;
- interrupts = <0 IRQ_TYPE_EDGE_RISING>;
- };
- button-1 {
- label = "JoyDown";
- /* linux,code = <KEY_DOWN>; BSD license issue */
- interrupt-parent = <&stmfx_pinctrl>;
- interrupts = <1 IRQ_TYPE_EDGE_RISING>;
- };
- button-2 {
- label = "JoyLeft";
- /* linux,code = <KEY_LEFT>; BSD license issue */
- interrupt-parent = <&stmfx_pinctrl>;
- interrupts = <2 IRQ_TYPE_EDGE_RISING>;
- };
- button-3 {
- label = "JoyRight";
- /* linux,code = <KEY_RIGHT>; BSD license issue */
- interrupt-parent = <&stmfx_pinctrl>;
- interrupts = <3 IRQ_TYPE_EDGE_RISING>;
- };
- button-4 {
- label = "JoyUp";
- /* linux,code = <KEY_UP>; 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 = <&reg18>;
- status = "okay";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dsi_in: endpoint {
- remote-endpoint = <&ltdc_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>;
- };
- };
- };
-};
-
-&ethernet0 {
- status = "okay";
- pinctrl-0 = <&ethernet0_rgmii_pins_a>;
- pinctrl-1 = <&ethernet0_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";
-};
-
-&ltdc {
- 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 <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xd.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+#include "stm32mp15xx-dkx.dtsi"
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+
+/ {
+ 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 <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xd.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxaa-pinctrl.dtsi"
+#include "stm32mp15xx-edx.dtsi"
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+
+/ {
+ 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 <alexandre.torgue@st.com> 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 <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xf.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+#include "stm32mp15xx-dkx.dtsi"
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+
+/ {
+ 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 <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xf.dtsi"
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxaa-pinctrl.dtsi"
+#include "stm32mp15xx-edx.dtsi"
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+
+/ {
+ 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 <alexandre.torgue@st.com> 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 <alexandre.torgue@st.com> 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 <alexandre.torgue@st.com> 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 <alexandre.torgue@st.com> 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 <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+#include "stm32mp15xd.dtsi"
+
+/ {
+ soc {
+ cryp1: cryp@54001000 {
+ compatible = "st,stm32mp1-cryp";
+ reg = <0x54001000 0x400>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ 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 <alexandre.torgue@st.com> for STMicroelectronics.
*/
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/mfd/st,stpmic1.h>
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <dt-bindings/power/stm32mp1-power.h>
/ {
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;
};
-&ethernet0 {
- status = "okay";
- pinctrl-0 = <&ethernet0_rgmii_pins_a>;
- pinctrl-1 = <&ethernet0_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 = <&ltdc_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 = <IT_CURLIM_LDO1 0>;
+ 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 = <IT_CURLIM_LDO2 0>;
+ 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 = <IT_CURLIM_LDO4 0>;
+ 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 = <IT_CURLIM_LDO5 0>;
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 = <IT_CURLIM_LDO6 0>;
+ 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 = <IT_OCP_BOOST 0>;
- };
+ };
vbus_otg: pwr_sw1 {
regulator-name = "vbus_otg";
- interrupts = <IT_OCP_OTG 0>;
- };
+ };
- vbus_sw: pwr_sw2 {
+ vbus_sw: pwr_sw2 {
regulator-name = "vbus_sw";
- interrupts = <IT_OCP_SWOUT 0>;
regulator-active-discharge = <1>;
- };
- };
-
- onkey {
- compatible = "st,stpmic1-onkey";
- interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
- 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";
};
-&ltdc {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&ltdc_pins_a>;
- pinctrl-1 = <&ltdc_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 = <STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF>;
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 = <&reg11>;
- vdda1v8-supply = <&reg18>;
};
&usbphyc_port1 {
phy-supply = <&vdd_usb>;
- vdda1v1-supply = <&reg11>;
- vdda1v8-supply = <&reg18>;
-};
-
-&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 <ludovic.barre@st.com> for STMicroelectronics.
+ */
+
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+
+/ {
+ 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 = <STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF>;
+ 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 <ludovic.barre@st.com> 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 <alexandre.torgue@st.com> for STMicroelectronics.
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
*/
&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 <alexandre.torgue@st.com> for STMicroelectronics.
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
*/
&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 <alexandre.torgue@st.com> for STMicroelectronics.
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
*/
&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 <alexandre.torgue@st.com> for STMicroelectronics.
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
*/
&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 <generated/arm32_sysreg.h>
#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 <arm.h>
+#include <drivers/stm32_tim.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <initcall.h>
+#include <io.h>
+#include <libfdt.h>
+#include <keep.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/generic_boot.h>
+#include <kernel/interrupt.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <limits.h>
+#include <mm/core_memprot.h>
+#include <stm32_util.h>
+#include <string.h>
+
+#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 <assert.h>
#include <drivers/stm32mp1_rcc.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include <initcall.h>
#include <io.h>
#include <keep.h>
+#include <kernel/delay.h>
#include <kernel/dt.h>
#include <kernel/generic_boot.h>
#include <kernel/panic.h>
+#include <kernel/pm.h>
#include <kernel/spinlock.h>
#include <libfdt.h>
#include <platform_config.h>
#include <stdio.h>
#include <stm32_util.h>
+#include <tee_api_types.h>
#include <trace.h>
#include <util.h>
+#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 <arm32.h>
+#include <boot_api.h>
+#include <drivers/stm32_rtc.h>
+#include <drivers/stm32mp1_ddrc.h>
+#include <drivers/stm32mp1_pwr.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <kernel/delay.h>
+#include <kernel/panic.h>
+#include <io.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <string.h>
+#include <trace.h>
+
+#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 <util.h>
+
+/* 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 <io.h>
#include <util.h>
#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 <io.h>
-#include <stdbool.h>
#include <util.h>
#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 <io.h>
+#include <stdbool.h>
+#include <types_ext.h>
+
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 <console.h>
#include <drivers/gic.h>
#include <drivers/stm32_etzpc.h>
-#include <drivers/stm32mp1_etzpc.h>
+#include <drivers/stm32_iwdg.h>
#include <drivers/stm32_uart.h>
+#include <drivers/stm32mp1_etzpc.h>
+#include <drivers/stm32mp1_pmic.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <drivers/stpmic1.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <io.h>
#include <kernel/dt.h>
#include <kernel/generic_boot.h>
#include <kernel/interrupt.h>
@@ -19,6 +24,7 @@
#include <kernel/panic.h>
#include <kernel/pm_stubs.h>
#include <kernel/spinlock.h>
+#include <kernel/tee_misc.h>
#include <mm/core_memprot.h>
#include <platform_config.h>
#include <sm/psci.h>
@@ -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 <arm32.h>
+#include <drivers/stm32mp1_ddrc.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <kernel/delay.h>
+#include <kernel/generic_boot.h>
+#include <kernel/interrupt.h>
+#include <kernel/misc.h>
+#include <kernel/panic.h>
+#include <platform_config.h>
+#include <sm/pm.h>
+#include <sm/psci.h>
+#include <stm32mp_pm.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#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 <sm/sm.h>
+#include <stdint.h>
+
+#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 <inttypes.h>
+#include <drivers/stm32mp1_pwr.h>
+#include <kernel/panic.h>
+#include <io.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <platform_config.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#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 <stm32mp1_smc.h>
+
+#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 <drivers/stm32mp1_rcc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <inttypes.h>
+#include <kernel/panic.h>
+#include <io.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#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 <stm32mp1_smc.h>
+
+#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 <drivers/scmi-msg.h>
#include <sm/optee_smc.h>
#include <sm/sm.h>
+#include <stm32_util.h>
#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 <mm/generic_ram_layout.h>
+/* 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 <arm32.h>
+#include <boot_api.h>
+#include <drivers/gic.h>
+#include <drivers/stm32_rng.h>
+#include <drivers/stm32_rtc.h>
+#include <drivers/stm32mp1_ddrc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <generated/context_asm_defines.h>
+#include <initcall.h>
+#include <io.h>
+#include <kernel/cache_helpers.h>
+#include <kernel/delay.h>
+#include <keep.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <mm/core_memprot.h>
+#include <mm/mobj.h>
+#include <platform_config.h>
+#include <stdlib.h>
+#include <stm32_util.h>
+#include <stm32mp_pm.h>
+#include <string.h>
+
+#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(&current_calendar);
+ stdby_time_in_ms = stm32_rtc_diff_calendar(&current_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 <compiler.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stm32mp_pm.h>
+#include <tee_api_types.h>
+#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 <gen-asm-defines.h>
+
+#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 <arm.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <console.h>
+#include <drivers/gic.h>
+#include <drivers/stm32_etzpc.h>
+#include <drivers/stm32_iwdg.h>
+#include <drivers/stm32mp1_ddrc.h>
+#include <drivers/stm32mp1_pmic.h>
+#include <drivers/stm32mp1_pwr.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <drivers/stpmic1.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+#include <initcall.h>
+#include <io.h>
+#include <keep.h>
+#include <kernel/cache_helpers.h>
+#include <kernel/delay.h>
+#include <kernel/misc.h>
+#include <kernel/panic.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <sm/psci.h>
+#include <stdbool.h>
+#include <stm32mp_pm.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#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 <arm.h>
+#include <arm32_macros.S>
+#include <asm.S>
+#include <boot_api.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <generated/context_asm_defines.h>
+#include <kernel/cache_helpers.h>
+#include <kernel/tz_proc_def.h>
+#include <kernel/tz_ssvce_def.h>
+#include <kernel/unwind.h>
+#include <platform_config.h>
+#include <mm/core_mmu.h>
+#include <util.h>
+
+#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 <compiler.h>
+#include <stdint.h>
+#include <stddef.h>
+
+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 <assert.h>
+#include <config.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <kernel/generic_boot.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <stm32mp_pm.h>
+#include <trace.h>
+#include <util.h>
+
+#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 <arm.h>
#include <boot_api.h>
+#include <config.h>
#include <console.h>
+#include <drivers/stm32_etzpc.h>
+#include <drivers/stm32_rng.h>
#include <drivers/stm32mp1_pmic.h>
#include <drivers/stm32mp1_rcc.h>
#include <drivers/stpmic1.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <initcall.h>
#include <io.h>
+#include <keep.h>
#include <kernel/cache_helpers.h>
#include <kernel/delay.h>
#include <kernel/generic_boot.h>
@@ -19,10 +26,17 @@
#include <kernel/spinlock.h>
#include <mm/core_memprot.h>
#include <platform_config.h>
+#include <sm/pm.h>
#include <sm/psci.h>
#include <sm/std_smc.h>
#include <stm32_util.h>
+#include <stm32mp_pm.h>
+#include <string.h>
#include <trace.h>
+#include <util.h>
+
+#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 <arm32.h>
+#include <arm.h>
#include <arm32_macros.S>
#include <asm.S>
#include <kernel/unwind.h>
@@ -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 <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
#include <initcall.h>
+#include <kernel/pm.h>
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
#include <platform_config.h>
@@ -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 <assert.h>
#include <drivers/stm32_bsec.h>
#include <kernel/panic.h>
+#include <stdbool.h>
#include <stdint.h>
#include <types_ext.h>
+/* 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 <arm.h>
#include <assert.h>
#include <drivers/gic.h>
+#include <io.h>
#include <keep.h>
#include <kernel/interrupt.h>
#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <malloc.h>
#include <util.h>
-#include <io.h>
#include <trace.h>
+#include <string.h>
/* 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 <assert.h>
+#include <drivers/stm32_iwdg.h>
+#include <io.h>
+#include <keep.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/generic_boot.h>
+#include <kernel/interrupt.h>
+#include <kernel/misc.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stm32_util.h>
+#include <stm32mp_pm.h>
+#include <string.h>
+#include <trace.h>
+
+/* 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 <arm32.h>
+#include <drivers/stm32_rtc.h>
+#include <initcall.h>
+#include <io.h>
+#include <kernel/dt.h>
+#include <kernel/generic_boot.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stm32_util.h>
+
+#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 <arm.h>
+#include <drivers/serial.h>
+#include <drivers/stm32_tim.h>
+#include <initcall.h>
+#include <io.h>
+#include <keep.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/generic_boot.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stm32_util.h>
+
+#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 <types_ext.h>
#include <kernel/interrupt.h>
+/* 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 <stdint.h>
#include <tee_api.h>
+/* 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 <stdint.h>
+
+#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 <stdbool.h>
+
+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 <yann.gautier@st.com> 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 <compiler.h>
+/*
+ * 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 <kernel/panic.h>
#include <kernel/thread.h>
+#include <stdbool.h>
#include <trace.h>
+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 [<FUNCTION>]" */
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