meta-st-stm32mp/recipes-security/optee/optee-os/0003-3.12.0-stm32mp-r2.patch

2252 lines
65 KiB
Diff

From 547f5ef88ac962218f2cb8cb90bc4cab1b99f7f9 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Thu, 28 Oct 2021 15:54:46 +0200
Subject: [PATCH] 3.12.0-stm32mp-r2
---
core/arch/arm/dts/stm32mp15xx-dkx.dtsi | 2 +-
core/arch/arm/dts/stm32mp15xx-edx.dtsi | 2 +-
core/arch/arm/plat-stm32mp1/conf.mk | 6 +
core/arch/arm/plat-stm32mp1/main.c | 77 ++
.../arch/arm/plat-stm32mp1/shared_resources.c | 2 +-
core/drivers/clk/clk-stm32mp15.c | 126 ++-
.../crypto/caam/hal/common/hal_cfg_dt.c | 4 +-
core/drivers/gic.c | 29 +
core/drivers/stm32_i2c.c | 33 +
core/drivers/stm32_rtc.c | 2 +-
core/drivers/stm32_tamp.c | 965 ++++++++++++++++++
core/drivers/sub.mk | 1 +
core/include/drivers/stm32_tamp.h | 378 +++++++
core/include/kernel/dt.h | 15 +-
core/include/kernel/interrupt.h | 25 +
core/kernel/dt.c | 28 +-
core/kernel/interrupt.c | 30 +
mk/config.mk | 2 +-
18 files changed, 1632 insertions(+), 95 deletions(-)
create mode 100644 core/drivers/stm32_tamp.c
create mode 100644 core/include/drivers/stm32_tamp.h
diff --git a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
index 236cff932..1334b705a 100644
--- a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
@@ -253,7 +253,7 @@
CLK_CKPER_HSE
CLK_FMC_ACLK
CLK_QSPI_ACLK
- CLK_ETH_DISABLED
+ CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
diff --git a/core/arch/arm/dts/stm32mp15xx-edx.dtsi b/core/arch/arm/dts/stm32mp15xx-edx.dtsi
index ef51b00af..d74d37c4e 100644
--- a/core/arch/arm/dts/stm32mp15xx-edx.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-edx.dtsi
@@ -255,7 +255,7 @@
CLK_CKPER_HSE
CLK_FMC_ACLK
CLK_QSPI_ACLK
- CLK_ETH_DISABLED
+ CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk
index b1d41c92a..d01a430d9 100644
--- a/core/arch/arm/plat-stm32mp1/conf.mk
+++ b/core/arch/arm/plat-stm32mp1/conf.mk
@@ -110,7 +110,12 @@ $(call force,CFG_STM32_TIM,n)
$(call force,CFG_STPMIC1,n)
endif
+# Remoteproc early TA for coprocessor firmware management
CFG_RPROC_PTA ?= n
+ifeq ($(CFG_RPROC_PTA),y)
+CFG_IN_TREE_EARLY_TAS += remoteproc/80a4c275-0a47-4905-8285-1486a9771a08
+endif
+
CFG_STM32_BSEC ?= y
CFG_STM32_CLKCALIB ?= y
CFG_STM32_CRYP ?= y
@@ -121,6 +126,7 @@ CFG_STM32_IWDG ?= y
CFG_STM32_RNG ?= y
CFG_STM32_RTC ?= y
CFG_STM32_TIM ?= y
+CFG_STM32_TAMP ?= y
CFG_STM32_UART ?= y
CFG_STM32MP15_CLK ?= y
CFG_STPMIC1 ?= y
diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c
index bf2e394fb..13460c6b9 100644
--- a/core/arch/arm/plat-stm32mp1/main.c
+++ b/core/arch/arm/plat-stm32mp1/main.c
@@ -11,6 +11,8 @@
#include <drivers/gic.h>
#include <drivers/stm32_etzpc.h>
#include <drivers/stm32_iwdg.h>
+#include <drivers/stm32_rtc.h>
+#include <drivers/stm32_tamp.h>
#include <drivers/stm32_uart.h>
#include <drivers/stm32mp1_pmic.h>
#include <drivers/stm32mp1_rcc.h>
@@ -666,3 +668,78 @@ bool stm32_rtc_get_read_twice(void)
return apb1_freq < (rtc_freq * 7U);
}
#endif
+
+#ifdef CFG_STM32_TAMP
+
+static const char * const itamper_name[] = {
+ [INT_TAMP1] = "RTC power domain",
+ [INT_TAMP2] = "Temperature monitoring",
+ [INT_TAMP3] = "LSE monitoring",
+ [INT_TAMP4] = "HSE monitoring",
+};
+
+DECLARE_KEEP_PAGER(itamper_name);
+
+static int stm32mp1_itamper_action(int id)
+{
+ const char *tamp_name = NULL;
+
+ if (id >= 0 && ((size_t)id < ARRAY_SIZE(itamper_name)))
+ tamp_name = itamper_name[id];
+
+ MSG("Internal tamper %u (%s) occurs\n", id + 1, tamp_name);
+
+ return 1; /* Ack TAMPER and reset system */
+}
+DECLARE_KEEP_PAGER(stm32mp1_itamper_action);
+
+static int __unused stm32mp1_etamper_action(int id)
+{
+ MSG("External tamper %u occurs\n", id + 1);
+
+ return 1; /* Ack TAMPER and reset system */
+}
+DECLARE_KEEP_PAGER(stm32mp1_etamper_action);
+
+static TEE_Result stm32_configure_tamp(void)
+{
+ struct stm32_bkpregs_conf bkpregs_conf = {
+ .nb_zone1_regs = 10, /* 10 registers in zone 1 */
+ .nb_zone2_regs = 0 /* No register in zone 2 */
+ /* Zone3 all remaining */
+ };
+
+ /* Enable BKP Register protection */
+ if (stm32_tamp_set_secure_bkpregs(&bkpregs_conf) != TEE_SUCCESS)
+ panic();
+
+ /*
+ * Configure TAMP to accept only secure access,
+ * and use secure Interrupt.
+ */
+ stm32_tamp_configure_secure_access(TAMP_REGS_IT_SECURE);
+
+ stm32_tamp_configure_internal(INT_TAMP1, TAMP_ENABLE,
+ stm32mp1_itamper_action);
+ stm32_tamp_configure_internal(INT_TAMP2, TAMP_ENABLE,
+ stm32mp1_itamper_action);
+ stm32_tamp_configure_internal(INT_TAMP3, TAMP_ENABLE,
+ stm32mp1_itamper_action);
+ stm32_tamp_configure_internal(INT_TAMP4, TAMP_ENABLE,
+ stm32mp1_itamper_action);
+
+ stm32_tamp_configure_active(TAMP_ACTIVE_FILTER_OFF);
+
+ stm32_tamp_configure_passive(0);
+
+ if (stm32_tamp_set_config() != TEE_SUCCESS)
+ panic();
+
+ /* Enable timestamp for tamper */
+ stm32_rtc_set_tamper_timestamp();
+
+ return TEE_SUCCESS;
+}
+
+boot_final(stm32_configure_tamp);
+#endif
diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c
index 7ad3d7b9c..7d2bcacba 100644
--- a/core/arch/arm/plat-stm32mp1/shared_resources.c
+++ b/core/arch/arm/plat-stm32mp1/shared_resources.c
@@ -159,7 +159,7 @@ static const char *shres2str_state_tbl[4] __maybe_unused = {
[SHRES_SECURE] = "secure",
};
-static __maybe_unused const char *shres2str_state(enum stm32mp_shres id)
+static __maybe_unused const char *shres2str_state(enum shres_state id)
{
return shres2str_state_tbl[id];
}
diff --git a/core/drivers/clk/clk-stm32mp15.c b/core/drivers/clk/clk-stm32mp15.c
index 6bbab8902..31d9ab6d6 100644
--- a/core/drivers/clk/clk-stm32mp15.c
+++ b/core/drivers/clk/clk-stm32mp15.c
@@ -44,27 +44,30 @@
/* Identifiers for root oscillators */
enum stm32mp_osc_id {
- _HSI = 0,
- _HSE,
- _CSI,
- _LSI,
- _LSE,
- _I2S_CKIN,
- _USB_PHY_48,
+ OSC_HSI,
+ OSC_HSE,
+ OSC_CSI,
+ OSC_LSI,
+ OSC_LSE,
+ OSC_I2S_CKIN,
+ OSC_USB_PHY_48,
NB_OSC,
_UNKNOWN_OSC_ID = 0xffU
};
/* Identifiers for parent clocks */
enum stm32mp1_parent_id {
-/*
- * Oscillators are valid IDs for parent clock and are already
- * defined in enum stm32mp_osc_id, ending at NB_OSC - 1.
- * This enum defines IDs are the other possible clock parents.
- */
- _HSI_KER = NB_OSC,
+ _HSI,
+ _HSE,
+ _CSI,
+ _LSI,
+ _LSE,
+ _I2S_CKIN,
+ _USB_PHY_48,
+ _HSI_KER,
_HSE_KER,
_HSE_KER_DIV2,
+ _HSE_RTC,
_CSI_KER,
_PLL1_P,
_PLL1_Q,
@@ -84,6 +87,7 @@ enum stm32mp1_parent_id {
_PCLK3,
_PCLK4,
_PCLK5,
+ _HCLK5,
_HCLK6,
_HCLK2,
_CK_PER,
@@ -130,6 +134,7 @@ static const uint8_t parent_id_clock_id[_PARENT_NB] = {
[_HSI_KER] = CK_HSI,
[_HSE_KER] = CK_HSE,
[_HSE_KER_DIV2] = CK_HSE_DIV2,
+ [_HSE_RTC] = _UNKNOWN_ID,
[_CSI_KER] = CK_CSI,
[_PLL1_P] = PLL1_P,
[_PLL1_Q] = PLL1_Q,
@@ -149,6 +154,7 @@ static const uint8_t parent_id_clock_id[_PARENT_NB] = {
[_PCLK3] = CK_AXI,
[_PCLK4] = CK_AXI,
[_PCLK5] = CK_AXI,
+ [_HCLK5] = CK_AXI,
[_HCLK6] = CK_AXI,
[_HCLK2] = CK_AXI,
[_CK_PER] = CK_PER,
@@ -390,13 +396,13 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
_CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, BSECEN, BSEC, _PCLK5),
_CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, STGENEN, STGEN_K, _STGEN_SEL),
- _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _PCLK5),
- _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _PCLK5),
- _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _PCLK5),
+ _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _HCLK5),
+ _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _HCLK5),
+ _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _HCLK5),
_CLK_SC2_SELEC(SEC, RCC_MP_AHB5ENSETR, RNG1EN, RNG1_K, _RNG1_SEL),
- _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _PCLK5),
+ _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _HCLK5),
- _CLK_SC2_FIXED(SEC, RCC_MP_TZAHB6ENSETR, MDMA, MDMA, _PCLK5),
+ _CLK_SC2_FIXED(SEC, RCC_MP_TZAHB6ENSETR, MDMA, MDMA, _HCLK6),
_CLK_SELEC(SEC, RCC_BDCR, RCC_BDCR_RTCCKEN_POS, RTC, _RTC_SEL),
@@ -492,7 +498,7 @@ static const uint8_t mcuss_parents[] = {
};
static const uint8_t rtc_parents[] = {
- _UNKNOWN_ID, _LSE, _LSI, _HSE
+ _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
};
#ifdef STM32MP1_USE_MPU0_RESET
@@ -520,7 +526,7 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
_CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents),
_CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents),
_CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents),
- _CLK_PARENT(_RTC_SEL, RCC_BDCR, 0, 0x3, rtc_parents),
+ _CLK_PARENT(_RTC_SEL, RCC_BDCR, 16, 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),
@@ -564,19 +570,19 @@ static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
_CLK_PLL(_PLL1, PLL_1600,
RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
- _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
+ OSC_HSI, OSC_HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
_CLK_PLL(_PLL2, PLL_1600,
RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
- _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
+ OSC_HSI, OSC_HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
_CLK_PLL(_PLL3, PLL_800,
RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
- _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
+ OSC_HSI, OSC_HSE, OSC_CSI, _UNKNOWN_OSC_ID),
_CLK_PLL(_PLL4, PLL_800,
RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
- _HSI, _HSE, _CSI, _I2S_CKIN),
+ OSC_HSI, OSC_HSE, OSC_CSI, OSC_I2S_CKIN),
};
/* Prescaler table lookups for clock computation */
@@ -607,6 +613,7 @@ static const char __maybe_unused *const stm32mp1_clk_parent_name[_PARENT_NB] = {
[_HSI_KER] = "HSI_KER",
[_HSE_KER] = "HSE_KER",
[_HSE_KER_DIV2] = "HSE_KER_DIV2",
+ [_HSE_RTC] = "HSE_RTC",
[_CSI_KER] = "CSI_KER",
[_PLL1_P] = "PLL1_P",
[_PLL1_Q] = "PLL1_Q",
@@ -626,8 +633,9 @@ static const char __maybe_unused *const stm32mp1_clk_parent_name[_PARENT_NB] = {
[_PCLK3] = "PCLK3",
[_PCLK4] = "PCLK4",
[_PCLK5] = "PCLK5",
- [_HCLK6] = "KCLK6",
[_HCLK2] = "HCLK2",
+ [_HCLK5] = "HCLK5",
+ [_HCLK6] = "HCLK6",
[_CK_PER] = "CK_PER",
[_CK_MPU] = "CK_MPU",
[_CK_MCU] = "CK_MCU",
@@ -968,10 +976,10 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p)
reg = io_read32(rcc_base + RCC_MPCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_MPCKSELR_HSI:
- clock = osc_frequency(_HSI);
+ clock = osc_frequency(OSC_HSI);
break;
case RCC_MPCKSELR_HSE:
- clock = osc_frequency(_HSE);
+ clock = osc_frequency(OSC_HSE);
break;
case RCC_MPCKSELR_PLL:
clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
@@ -991,16 +999,17 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p)
/* AXI sub system */
case _ACLK:
case _HCLK2:
+ case _HCLK5:
case _HCLK6:
case _PCLK4:
case _PCLK5:
reg = io_read32(rcc_base + RCC_ASSCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_ASSCKSELR_HSI:
- clock = osc_frequency(_HSI);
+ clock = osc_frequency(OSC_HSI);
break;
case RCC_ASSCKSELR_HSE:
- clock = osc_frequency(_HSE);
+ clock = osc_frequency(OSC_HSE);
break;
case RCC_ASSCKSELR_PLL:
clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
@@ -1034,13 +1043,13 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p)
reg = io_read32(rcc_base + RCC_MSSCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_MSSCKSELR_HSI:
- clock = osc_frequency(_HSI);
+ clock = osc_frequency(OSC_HSI);
break;
case RCC_MSSCKSELR_HSE:
- clock = osc_frequency(_HSE);
+ clock = osc_frequency(OSC_HSE);
break;
case RCC_MSSCKSELR_CSI:
- clock = osc_frequency(_CSI);
+ clock = osc_frequency(OSC_CSI);
break;
case RCC_MSSCKSELR_PLL:
clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
@@ -1075,13 +1084,13 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p)
reg = io_read32(rcc_base + RCC_CPERCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_CPERCKSELR_HSI:
- clock = osc_frequency(_HSI);
+ clock = osc_frequency(OSC_HSI);
break;
case RCC_CPERCKSELR_HSE:
- clock = osc_frequency(_HSE);
+ clock = osc_frequency(OSC_HSE);
break;
case RCC_CPERCKSELR_CSI:
- clock = osc_frequency(_CSI);
+ clock = osc_frequency(OSC_CSI);
break;
default:
break;
@@ -1089,24 +1098,28 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p)
break;
case _HSI:
case _HSI_KER:
- clock = osc_frequency(_HSI);
+ clock = osc_frequency(OSC_HSI);
break;
case _CSI:
case _CSI_KER:
- clock = osc_frequency(_CSI);
+ clock = osc_frequency(OSC_CSI);
break;
case _HSE:
case _HSE_KER:
- clock = osc_frequency(_HSE);
+ clock = osc_frequency(OSC_HSE);
break;
case _HSE_KER_DIV2:
- clock = osc_frequency(_HSE) >> 1;
+ clock = osc_frequency(OSC_HSE) >> 1;
+ break;
+ case _HSE_RTC:
+ clock = osc_frequency(OSC_HSE);
+ clock /= (io_read32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
break;
case _LSI:
- clock = osc_frequency(_LSI);
+ clock = osc_frequency(OSC_LSI);
break;
case _LSE:
- clock = osc_frequency(_LSE);
+ clock = osc_frequency(OSC_LSE);
break;
/* PLL */
case _PLL1_P:
@@ -1147,7 +1160,7 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p)
break;
/* Other */
case _USB_PHY_48:
- clock = osc_frequency(_USB_PHY_48);
+ clock = osc_frequency(OSC_USB_PHY_48);
break;
default:
break;
@@ -1347,7 +1360,7 @@ static unsigned long clk_stm32_get_rate(unsigned long id)
/*
* Get the parent ID of the target parent clock, or -1 if no parent found.
*/
-static int get_parent_id_parent(unsigned int parent_id)
+static int get_parent_id_parent(enum stm32mp1_parent_id parent_id)
{
enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
enum stm32mp1_pll_id pll_id = _PLL_NB;
@@ -1355,6 +1368,8 @@ static int get_parent_id_parent(unsigned int parent_id)
switch (parent_id) {
case _ACLK:
+ case _HCLK5:
+ case _HCLK6:
case _PCLK4:
case _PCLK5:
s = _AXISS_SEL;
@@ -1382,7 +1397,6 @@ static int get_parent_id_parent(unsigned int parent_id)
case _PCLK1:
case _PCLK2:
case _HCLK2:
- case _HCLK6:
case _CK_PER:
case _CK_MPU:
case _CK_MCU:
@@ -1419,13 +1433,14 @@ static int get_parent_id_parent(unsigned int parent_id)
}
/* We are only interested in knowing if PLL3 shall be secure or not */
-static void secure_parent_clocks(unsigned long parent_id)
+static void secure_parent_clocks(enum stm32mp1_parent_id parent_id)
{
- int grandparent_id = 0;
+ enum stm32mp1_parent_id grandparent_id = 0;
switch (parent_id) {
case _ACLK:
case _HCLK2:
+ case _HCLK5:
case _HCLK6:
case _PCLK4:
case _PCLK5:
@@ -1439,6 +1454,7 @@ static void secure_parent_clocks(unsigned long parent_id)
case _HSE:
case _HSE_KER:
case _HSE_KER_DIV2:
+ case _HSE_RTC:
case _LSE:
case _PLL1_P:
case _PLL1_Q:
@@ -1487,13 +1503,13 @@ DECLARE_KEEP_PAGER(stm32mp_clk_ops);
#ifdef CFG_EMBED_DTB
static const char *stm32mp_osc_node_label[NB_OSC] = {
- [_LSI] = "clk-lsi",
- [_LSE] = "clk-lse",
- [_HSI] = "clk-hsi",
- [_HSE] = "clk-hse",
- [_CSI] = "clk-csi",
- [_I2S_CKIN] = "i2s_ckin",
- [_USB_PHY_48] = "ck_usbo_48m"
+ [OSC_LSI] = "clk-lsi",
+ [OSC_LSE] = "clk-lse",
+ [OSC_HSI] = "clk-hsi",
+ [OSC_HSE] = "clk-hse",
+ [OSC_CSI] = "clk-csi",
+ [OSC_I2S_CKIN] = "i2s_ckin",
+ [OSC_USB_PHY_48] = "ck_usbo_48m"
};
static unsigned int clk_freq_prop(void *fdt, int node)
@@ -1520,8 +1536,8 @@ static void get_osc_freq_from_dt(void *fdt)
if (clk_node < 0)
panic();
- COMPILE_TIME_ASSERT((int)_HSI == 0);
- for (idx = _HSI; idx < NB_OSC; idx++) {
+ COMPILE_TIME_ASSERT((int)OSC_HSI == 0);
+ for (idx = OSC_HSI; idx < NB_OSC; idx++) {
const char *name = stm32mp_osc_node_label[idx];
int subnode = 0;
diff --git a/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c b/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c
index f03a7d54a..0133a0696 100644
--- a/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c
+++ b/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c
@@ -9,6 +9,7 @@
#include <caam_hal_jr.h>
#include <caam_jr.h>
#include <kernel/dt.h>
+#include <kernel/interrupt.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
@@ -113,8 +114,7 @@ void caam_hal_cfg_get_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg)
}
jrcfg->offset = jr_offset;
- /* Add index of the first SPI interrupt */
- jrcfg->it_num = jr_it_num + 32;
+ jrcfg->it_num = jr_it_num;
}
}
diff --git a/core/drivers/gic.c b/core/drivers/gic.c
index 3f1a606ed..3efce7ab8 100644
--- a/core/drivers/gic.c
+++ b/core/drivers/gic.c
@@ -6,12 +6,15 @@
#include <arm.h>
#include <assert.h>
+#include <config.h>
#include <drivers/gic.h>
#include <io.h>
#include <keep.h>
+#include <kernel/dt.h>
#include <kernel/interrupt.h>
#include <kernel/panic.h>
#include <kernel/pm.h>
+#include <libfdt.h>
#include <malloc.h>
#include <util.h>
#include <trace.h>
@@ -230,6 +233,29 @@ void gic_init_setup(struct gic_data *gd)
#endif
}
+static int gic_dt_get_irq(const uint32_t *properties, int len)
+{
+ int it_num = DT_INFO_INVALID_INTERRUPT;
+
+ if (!properties || len < 2)
+ return DT_INFO_INVALID_INTERRUPT;
+
+ it_num = fdt32_to_cpu(properties[1]);
+
+ switch (fdt32_to_cpu(properties[0])) {
+ case 1:
+ it_num += 16;
+ break;
+ case 0:
+ it_num += 32;
+ break;
+ default:
+ it_num = DT_INFO_INVALID_INTERRUPT;
+ }
+
+ return it_num;
+}
+
void gic_init_base_addr(struct gic_data *gd, vaddr_t gicc_base __maybe_unused,
vaddr_t gicd_base)
{
@@ -244,6 +270,9 @@ void gic_init_base_addr(struct gic_data *gd, vaddr_t gicc_base __maybe_unused,
void gic_init(struct gic_data *gd, vaddr_t gicc_base, vaddr_t gicd_base)
{
gic_init_base_addr(gd, gicc_base, gicd_base);
+ if (IS_ENABLED(CFG_DT))
+ gd->chip.dt_get_irq = gic_dt_get_irq;
+
gic_init_setup(gd);
}
diff --git a/core/drivers/stm32_i2c.c b/core/drivers/stm32_i2c.c
index 2807cc42a..bc10960dc 100644
--- a/core/drivers/stm32_i2c.c
+++ b/core/drivers/stm32_i2c.c
@@ -870,6 +870,33 @@ static int wait_isr_event(struct i2c_handle_s *hi2c, uint32_t bit_mask,
return -1;
}
+static int wait_isr_event_nack(struct i2c_handle_s *hi2c, uint32_t bit_mask,
+ unsigned int awaited_value, uint64_t timeout_ref)
+{
+ vaddr_t isr = get_base(hi2c) + I2C_ISR;
+ uint32_t val;
+
+ assert(IS_POWER_OF_TWO(bit_mask) && !(awaited_value & ~1U));
+
+ /* May timeout while TEE thread is suspended */
+ while (!timeout_elapsed(timeout_ref)) {
+ val = io_read32(isr);
+ if (val & I2C_ISR_NACKF)
+ return -1;
+ if (!!(val & bit_mask) == awaited_value)
+ break;
+ }
+
+ val = io_read32(isr);
+ if (val & I2C_ISR_NACKF)
+ return -1;
+ if (!!(val & bit_mask) == awaited_value)
+ return 0;
+
+ notif_i2c_timeout(hi2c);
+ return -1;
+}
+
/* Handle Acknowledge-Failed sequence detection during an I2C Communication */
static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
{
@@ -1329,6 +1356,12 @@ static int i2c_read(struct i2c_handle_s *hi2c, struct i2c_request *request,
I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
}
+ /* Start polling for data but return if NACK indicates we should poll later */
+ if (wait_isr_event_nack(hi2c, I2C_ISR_RXNE, 1, timeout_ref)) {
+ i2c_ack_failed(hi2c, timeout_ref);
+ goto bail;
+ }
+
do {
if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1, timeout_ref))
goto bail;
diff --git a/core/drivers/stm32_rtc.c b/core/drivers/stm32_rtc.c
index 79ab627e6..58bf69f2d 100644
--- a/core/drivers/stm32_rtc.c
+++ b/core/drivers/stm32_rtc.c
@@ -71,7 +71,7 @@
#define RTC_ICSR_RSF BIT(5)
-#define RTC_PRER_PREDIV_S_MASK GENMASK_32(15, 0)
+#define RTC_PRER_PREDIV_S_MASK GENMASK_32(14, 0)
#define RTC_CR_BYPSHAD BIT(5)
#define RTC_CR_BYPSHAD_SHIFT 5
diff --git a/core/drivers/stm32_tamp.c b/core/drivers/stm32_tamp.c
new file mode 100644
index 000000000..317ca7801
--- /dev/null
+++ b/core/drivers/stm32_tamp.c
@@ -0,0 +1,965 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <config.h>
+#include <crypto/crypto.h>
+#include <drivers/clk.h>
+#include <drivers/stm32_gpio.h>
+#include <drivers/stm32_rtc.h>
+#include <drivers/stm32_tamp.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/interrupt.h>
+#include <mm/core_memprot.h>
+#include <sm/psci.h> /* If psci_reset */
+#include <stdbool.h>
+#include <stm32_util.h>
+#include <stm32mp_pm.h> /* If stm32_cores_reset() */
+
+#include <libfdt.h>
+
+/* STM32 Registers */
+#define _TAMP_CR1 0x00U
+#define _TAMP_CR2 0x04U
+#define _TAMP_CR3 0x08U
+#define _TAMP_FLTCR 0x0CU
+#define _TAMP_ATCR1 0x10U
+#define _TAMP_ATSEEDR 0x14U
+#define _TAMP_ATOR 0x18U
+#define _TAMP_ATCR2 0x1CU
+#define _TAMP_SECCFGR 0x20U
+#define _TAMP_SMCR 0x20U
+#define _TAMP_PRIVCFGR 0x24U
+#define _TAMP_IER 0x2CU
+#define _TAMP_SR 0x30U
+#define _TAMP_MISR 0x34U
+#define _TAMP_SMISR 0x38U
+#define _TAMP_SCR 0x3CU
+#define _TAMP_COUNTR 0x40U
+#define _TAMP_COUNT2R 0x44U
+#define _TAMP_OR 0x50U
+#define _TAMP_ERCFGR 0X54U
+#define _TAMP_HWCFGR2 0x3ECU
+#define _TAMP_HWCFGR1 0x3F0U
+#define _TAMP_VERR 0x3F4U
+#define _TAMP_IPIDR 0x3F8U
+#define _TAMP_SIDR 0x3FCU
+
+/* _TAMP_CR1 bit filds */
+#define _TAMP_CR1_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_CR1_ETAMP(id) BIT((id))
+
+/* _TAMP_CR2 bit filds */
+#define _TAMP_CR2_ETAMPTRG(id) BIT((id) + 24U)
+#define _TAMP_CR2_BKERASE BIT(23)
+#define _TAMP_CR2_BKBLOCK BIT(22)
+#define _TAMP_CR2_ETAMPMSK_MAX_ID 3U
+#define _TAMP_CR2_ETAMPMSK(id) BIT((id) + 16U)
+#define _TAMP_CR2_ETAMPNOER(id) BIT((id))
+
+/* _TAMP_CR3 bit filds */
+#define _TAMP_CR3_ITAMPNOER_ALL GENMASK_32(12, 0)
+#define _TAMP_CR3_ITAMPNOER(id) BIT((id))
+
+/* _TAMP_FLTCR bit fields */
+#define _TAMP_FLTCR_TAMPFREQ GENMASK_32(2, 0)
+#define _TAMP_FLTCR_TAMPFLT GENMASK_32(4, 3)
+#define _TAMP_FLTCR_TAMPPRCH GENMASK_32(6, 5)
+#define _TAMP_FLTCR_TAMPPUDIS BIT(7)
+
+/* _TAMP_ATCR bit fields */
+#define _TAMP_ATCR1_ATCKSEL GENMASK_32(18, 16)
+#define _TAMP_ATCR1_ATPER GENMASK_32(26, 24)
+#define _TAMP_ATCR1_COMMON_MASK GENMASK_32(31, 16)
+#define _TAMP_ATCR1_ETAMPAM(id) BIT((id))
+#define _TAMP_ATCR1_ATOSEL_MASK(i) GENMASK_32(((i) + 1) * 2U + 7U, \
+ (i) * 2U + 8U)
+#define _TAMP_ATCR1_ATOSEL(i, o) (((o) - 1U) << ((i) * 2U + 8U))
+
+/* _TAMP_ATOR bit fields */
+#define _TAMP_PRNG GENMASK_32(7, 0)
+#define _TAMP_SEEDF BIT(14)
+#define _TAMP_INITS BIT(15)
+
+/* _TAMP_IER bit fields */
+#define _TAMP_IER_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_IER_ETAMP(id) BIT((id))
+
+/* _TAMP_SR bit fields */
+#define _TAMP_SR_ETAMPXF_MASK GENMASK_32(7, 0)
+#define _TAMP_SR_ITAMPXF_MASK GENMASK_32(31, 16)
+#define _TAMP_SR_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_SR_ETAMP(id) BIT((id))
+
+/* _TAMP_SCR bit fields */
+#define _TAMP_SCR_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_SCR_ETAMP(id) BIT((id))
+
+/* _TAMP_SECCFGR bit fields */
+#define _TAMP_SECCFGR_BKPRWSEC_MASK GENMASK_32(7, 0)
+#define _TAMP_SECCFGR_BKPRWSEC_SHIFT 0U
+#define _TAMP_SECCFGR_CNT2SEC BIT(14)
+#define _TAMP_SECCFGR_CNT1SEC BIT(15)
+#define _TAMP_SECCFGR_BKPWSEC_MASK GENMASK_32(23, 16)
+#define _TAMP_SECCFGR_BKPWSEC_SHIFT 16U
+#define _TAMP_SECCFGR_BHKLOCK BIT(30)
+#define _TAMP_SECCFGR_TAMPSEC BIT(31)
+
+/* _TAMP_SMCR bit fields */
+#define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK_32(7, 0)
+#define _TAMP_SMCR_BKPRWDPROT_SHIFT 0U
+#define _TAMP_SMCR_BKPWDPROT_MASK GENMASK_32(23, 16)
+#define _TAMP_SMCR_BKPWDPROT_SHIFT 16U
+#define _TAMP_SMCR_DPROT BIT(31)
+
+/*
+ * _TAMP_PRIVCFGR bit fields defined in stm32_tamp.h
+ * See TAMP_.*PRIVILEGED
+ */
+#define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \
+ GENMASK_32(15, 14))
+
+/* _TAMP_ATCR2 bit fields */
+#define _TAMP_ATCR2_ATOSEL_MASK(i) GENMASK_32(((i) + 1) * 3U + 7U, \
+ (i) * 3U + 8U)
+#define _TAMP_ATCR2_ATOSEL(i, o) ((o) << ((i) * 3U + 8U))
+
+/* _TAMP_OR bit fields */
+#define _TAMP_OR_IN1RMP_PF10 0U
+#define _TAMP_OR_IN1RMP_PC13 BIT(0)
+#define _TAMP_OR_IN2RMP_PA6 0U
+#define _TAMP_OR_IN2RMP_PI1 BIT(1)
+#define _TAMP_OR_IN3RMP_PC0 0U
+#define _TAMP_OR_IN3RMP_PI2 BIT(2)
+#define _TAMP_OR_IN4RMP_PG8 0U
+#define _TAMP_OR_IN4RMP_PI3 BIT(3)
+
+#define _TAMP_OR_OUT3RMP_PI8 0U
+#define _TAMP_OR_OUT3RMP_PC13 BIT(0)
+
+/* _TAMP_ERCFGR bit fields */
+#define _TAMP_ERCFGR_ERCFG0 BIT(0)
+
+/* _TAMP_HWCFGR2 bit fields */
+#define _TAMP_HWCFGR2_TZ GENMASK_32(11, 8)
+#define _TAMP_HWCFGR2_OR GENMASK_32(7, 0)
+
+/* _TAMP_HWCFGR1 bit fields */
+#define _TAMP_HWCFGR1_BKPREG GENMASK_32(7, 0)
+#define _TAMP_HWCFGR1_TAMPER GENMASK_32(11, 8)
+#define _TAMP_HWCFGR1_ACTIVE GENMASK_32(15, 12)
+#define _TAMP_HWCFGR1_INTERN GENMASK_32(31, 16)
+#define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U
+#define _TAMP_HWCFGR1_ITAMP(id) BIT((id) + 16U)
+
+/* _TAMP_VERR bit fields */
+#define _TAMP_VERR_MINREV GENMASK_32(3, 0)
+#define _TAMP_VERR_MAJREV GENMASK_32(7, 4)
+
+#define SEED_TIMEOUT_US 1000
+
+struct stm32_tamp_int {
+ const uint32_t id;
+ uint32_t mode;
+ int (*func)(int id);
+};
+
+struct stm32_tamp_ext {
+ const uint32_t id;
+ uint32_t mode;
+ uint8_t out_pin;
+ int (*func)(int id);
+};
+
+struct stm32_tamp_instance {
+ struct stm32_tamp_platdata pdata;
+ uint32_t hwconf1;
+ uint32_t hwconf2;
+ uint32_t secret_list_conf;
+ uint32_t privilege_conf;
+ uint32_t secure_conf;
+ uint32_t passive_conf;
+ uint32_t active_conf;
+};
+
+struct stm32_tamp_int int_tamp_mp15[] = {
+ { .id = INT_TAMP1 }, { .id = INT_TAMP2 }, { .id = INT_TAMP3 },
+ { .id = INT_TAMP4 }, { .id = INT_TAMP5 }, { .id = INT_TAMP8 },
+};
+
+struct stm32_tamp_ext ext_tamp_mp15[] = {
+ { .id = EXT_TAMP1 }, { .id = EXT_TAMP2 }, { .id = EXT_TAMP3 },
+};
+
+/*
+ * Only 1 instance of TAMP is expected per platform
+ *
+ * 0 is the expected initial values for all fields but .id
+ */
+static struct stm32_tamp_instance stm32_tamp = { };
+DECLARE_KEEP_PAGER(stm32_tamp);
+
+struct my_dt_device_match {
+ const char *compatible;
+ void *data;
+};
+
+static struct stm32_tamp_compat mp15_compat = {
+ .nb_monotonic_counter = 1,
+ .tags = 0,
+ .int_tamp = int_tamp_mp15,
+ .int_tamp_size = ARRAY_SIZE(int_tamp_mp15),
+ .ext_tamp = ext_tamp_mp15,
+ .ext_tamp_size = ARRAY_SIZE(ext_tamp_mp15),
+};
+
+static const struct my_dt_device_match tamp_match_table[] = {
+ { .compatible = "st,stm32-tamp", .data = &mp15_compat},
+ { 0 }
+};
+
+static void stm32_tamp_set_secret_list(struct stm32_tamp_instance *tamp)
+{
+ vaddr_t base = io_pa_or_va(&tamp->pdata.base);
+
+ if (tamp->pdata.compat &&
+ (tamp->pdata.compat->tags & TAMP_HAS_CONF_SECRET_IPS)) {
+ if (tamp->secret_list_conf & TAMP_CONF_SECRET_BACKUP_SRAM)
+ io_setbits32(base + _TAMP_ERCFGR, _TAMP_ERCFGR_ERCFG0);
+ else
+ io_clrbits32(base + _TAMP_ERCFGR, _TAMP_ERCFGR_ERCFG0);
+ }
+}
+
+static void stm32_tamp_set_secure(struct stm32_tamp_instance *tamp)
+{
+ vaddr_t base = io_pa_or_va(&tamp->pdata.base);
+ uint32_t mode = 0;
+
+ /* Force secure mode: within OP-TEE we only access TAMP from secure */
+ tamp->secure_conf |= TAMP_REGS_IT_SECURE;
+ mode = tamp->secure_conf;
+
+ if (tamp->pdata.compat &&
+ (tamp->pdata.compat->tags & TAMP_HAS_CONF_SECURE)) {
+ if (mode & TAMP_REGS_IT_SECURE)
+ io_setbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_TAMPSEC);
+ else
+ io_clrbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_TAMPSEC);
+
+ if (mode & TAMP_CNT1_SECURE)
+ io_setbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_CNT1SEC);
+ else
+ io_clrbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_CNT1SEC);
+
+ if (mode & TAMP_CNT2_SECURE)
+ io_setbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_CNT2SEC);
+ else
+ io_clrbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_CNT2SEC);
+ } else {
+ /* Note: MP15 doesn't use SECCFG register
+ * and inverts the secure bit
+ */
+ if (mode & TAMP_REGS_IT_SECURE)
+ io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
+ else
+ io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
+ }
+}
+
+static void stm32_tamp_set_privilege(struct stm32_tamp_instance *tamp)
+{
+ vaddr_t base = io_pa_or_va(&tamp->pdata.base);
+ uint32_t mode = tamp->privilege_conf;
+
+ if (tamp->pdata.compat &&
+ (tamp->pdata.compat->tags & TAMP_HAS_CONF_PRIVILEGE))
+ io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK,
+ mode & _TAMP_PRIVCFGR_MASK);
+}
+
+static void stm32_tamp_set_pins(vaddr_t base, uint32_t mode)
+{
+ io_setbits32(base + _TAMP_OR, mode);
+}
+
+static TEE_Result stm32_tamp_set_seed(vaddr_t base)
+{
+ /* Need RNG access. */
+ uint64_t timeout_ref = timeout_init_us(SEED_TIMEOUT_US);
+ uint8_t idx = 0;
+
+ for (idx = 0; idx < 4U; idx++) {
+ uint32_t rnd = 0;
+
+ if (crypto_rng_read((uint8_t *)&rnd, sizeof(uint32_t)) != 0)
+ return TEE_ERROR_BAD_STATE;
+
+ io_write32(base + _TAMP_ATSEEDR, rnd);
+ }
+
+ while ((io_read32(base + _TAMP_ATOR) & _TAMP_SEEDF) != 0U) {
+ if (timeout_elapsed(timeout_ref))
+ return TEE_ERROR_BAD_STATE;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static bool is_int_tamp_id_valid(uint32_t id)
+{
+ return (id <= _TAMP_HWCFGR1_ITAMP_MAX_ID) &&
+ (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_ITAMP(id));
+}
+
+static bool is_ext_tamp_id_valid(uint32_t id)
+{
+ return (stm32_tamp.pdata.compat) &&
+ (id <= stm32_tamp.pdata.compat->ext_tamp_size);
+}
+
+static TEE_Result stm32_tamp_set_int_config(struct stm32_tamp_compat *tcompat,
+ uint32_t itamp_index, uint32_t *cr1,
+ uint32_t *cr3, uint32_t *ier)
+{
+ uint32_t id = 0;
+ struct stm32_tamp_int *tamp_int = NULL;
+
+ if (!tcompat)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ tamp_int = &tcompat->int_tamp[itamp_index];
+ id = tamp_int->id;
+
+ if (!is_int_tamp_id_valid(id))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* If this internal tamper is disabled, reset its configuration. */
+ if ((tamp_int->mode & TAMP_ENABLE) != TAMP_ENABLE) {
+ *cr1 &= ~_TAMP_CR1_ITAMP(id);
+ *ier &= ~_TAMP_IER_ITAMP(id);
+ if (tcompat->tags & TAMP_HAS_CR3)
+ *cr3 &= ~_TAMP_CR3_ITAMPNOER(id);
+
+ return TEE_SUCCESS;
+ }
+
+ *cr1 |= _TAMP_CR1_ITAMP(id);
+ *ier |= _TAMP_IER_ITAMP(id);
+
+ if (tcompat->tags & TAMP_HAS_CR3) {
+ if ((tamp_int->mode & TAMP_NOERASE) == TAMP_NOERASE)
+ *cr3 |= _TAMP_CR3_ITAMPNOER(id);
+ else
+ *cr3 &= ~_TAMP_CR3_ITAMPNOER(id);
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_tamp_set_ext_config(struct stm32_tamp_compat *tcompat,
+ uint32_t etamp_index,
+ uint32_t *cr1, uint32_t *cr2,
+ uint32_t *atcr1, uint32_t *atcr2,
+ uint32_t *ier)
+{
+ uint32_t id = 0;
+ struct stm32_tamp_ext *tamp_ext = NULL;
+
+ if (!tcompat)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ tamp_ext = &tcompat->ext_tamp[etamp_index];
+ id = tamp_ext->id;
+
+ /* Exit if not a valid TAMP_ID */
+ if (!is_ext_tamp_id_valid(id))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* If this external tamper is disabled, reset its configuration. */
+ if ((tamp_ext->mode & TAMP_ENABLE) != TAMP_ENABLE) {
+ *cr1 &= ~_TAMP_CR1_ETAMP(id);
+ *cr2 &= ~_TAMP_CR2_ETAMPMSK(id);
+ *cr2 &= ~_TAMP_CR2_ETAMPTRG(id);
+ *cr2 &= ~_TAMP_CR2_ETAMPNOER(id);
+ *ier &= ~_TAMP_IER_ETAMP(id);
+ return TEE_SUCCESS;
+ }
+
+ *cr1 |= _TAMP_CR1_ETAMP(id);
+
+ if ((tamp_ext->mode & TAMP_TRIG_ON) == TAMP_TRIG_ON)
+ *cr2 |= _TAMP_CR2_ETAMPTRG(id);
+ else
+ *cr2 &= ~_TAMP_CR2_ETAMPTRG(id);
+
+ if ((tamp_ext->mode & TAMP_ACTIVE) == TAMP_ACTIVE) {
+ *atcr1 |= _TAMP_ATCR1_ETAMPAM(id);
+ /* Configure output pin:
+ * For the case out_pin = 0, we select same output pin than the
+ * input one.
+ */
+ if (tamp_ext->out_pin == TAMPOUTSEL_SAME_AS_INPUT)
+ tamp_ext->out_pin = id + 1;
+
+ if (tamp_ext->out_pin <= tcompat->ext_tamp_size) {
+ if (tcompat->tags & TAMP_HAS_ATCR2)
+ *atcr2 = (*atcr2 &
+ ~_TAMP_ATCR2_ATOSEL_MASK(id)) |
+ _TAMP_ATCR2_ATOSEL(id,
+ tamp_ext->out_pin);
+ else
+ *atcr1 = (*atcr1 &
+ ~_TAMP_ATCR1_ATOSEL_MASK(id)) |
+ _TAMP_ATCR1_ATOSEL(id,
+ tamp_ext->out_pin);
+ }
+ } else {
+ *atcr1 &= ~_TAMP_ATCR1_ETAMPAM(id);
+ }
+
+ if ((tamp_ext->mode & TAMP_NOERASE) == TAMP_NOERASE)
+ *cr2 |= _TAMP_CR2_ETAMPNOER(id);
+ else
+ *cr2 &= ~_TAMP_CR2_ETAMPNOER(id);
+
+ if (id < _TAMP_CR2_ETAMPMSK_MAX_ID) {
+ /*
+ * Only external TAMP 1, 2 and 3 can be masked
+ */
+ if ((tamp_ext->mode & TAMP_EVT_MASK) == TAMP_EVT_MASK) {
+ /*
+ * ETAMP(id) event generates a trigger event. This
+ * ETAMP(id) is masked and internally cleared by
+ * hardware.
+ * The secrets are not erased.
+ */
+ *ier &= ~_TAMP_IER_ETAMP(id);
+ *cr2 |= _TAMP_CR2_ETAMPMSK(id);
+ } else {
+ /*
+ * normal ETAMP interrupt:
+ * ETAMP(id) event generates a trigger event and
+ * TAMP(id) must be cleared by software to allow
+ * next tamper event detection.
+ */
+ *cr2 &= ~_TAMP_CR2_ETAMPMSK(id);
+ *ier |= _TAMP_IER_ETAMP(id);
+ }
+ } else {
+ /* Other than 1,2,3 external TAMP, we want its interruption */
+ *ier |= _TAMP_IER_ETAMP(id);
+ }
+
+ return TEE_SUCCESS;
+}
+
+TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf)
+{
+ uint32_t first_z2 = 0;
+ uint32_t first_z3 = 0;
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (!bkr_conf)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ first_z2 = bkr_conf->nb_zone1_regs;
+ first_z3 = bkr_conf->nb_zone1_regs + bkr_conf->nb_zone2_regs;
+
+ if ((first_z2 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG)) ||
+ (first_z3 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG)))
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ if (stm32_tamp.pdata.compat &&
+ (stm32_tamp.pdata.compat->tags & TAMP_HAS_CONF_SECURE)) {
+ io_clrsetbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_BKPRWSEC_MASK,
+ (first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) &
+ _TAMP_SECCFGR_BKPRWSEC_MASK);
+
+ io_clrsetbits32(base + _TAMP_SECCFGR,
+ _TAMP_SECCFGR_BKPWSEC_MASK,
+ (first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) &
+ _TAMP_SECCFGR_BKPWSEC_MASK);
+ } else {
+ io_clrsetbits32(base + _TAMP_SMCR,
+ _TAMP_SMCR_BKPRWDPROT_MASK,
+ (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) &
+ _TAMP_SMCR_BKPRWDPROT_MASK);
+
+ io_clrsetbits32(base + _TAMP_SMCR,
+ _TAMP_SMCR_BKPWDPROT_MASK,
+ (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) &
+ _TAMP_SMCR_BKPWDPROT_MASK);
+ }
+
+ return TEE_SUCCESS;
+}
+
+TEE_Result stm32_tamp_set_config(void)
+{
+ int ret = TEE_SUCCESS;
+ uint32_t i = 0;
+ uint32_t cr1 = 0;
+ uint32_t cr2 = 0;
+ uint32_t cr3 = 0;
+ uint32_t atcr1 = 0;
+ uint32_t atcr2 = 0;
+ uint32_t fltcr = 0;
+ uint32_t ier = 0;
+
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (!stm32_tamp.pdata.compat ||
+ !stm32_tamp.pdata.compat->int_tamp ||
+ !stm32_tamp.pdata.compat->ext_tamp)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Select extra IP to add in the deleted/blocked IP in case of
+ * tamper event
+ */
+ stm32_tamp_set_secret_list(&stm32_tamp);
+
+ /* Select access in secure or unsecure */
+ stm32_tamp_set_secure(&stm32_tamp);
+
+ /* Select access in privileged mode or unprivileged mode */
+ stm32_tamp_set_privilege(&stm32_tamp);
+
+ /* Set passive filter configuration */
+ if (stm32_tamp.passive_conf != 0U)
+ fltcr = stm32_tamp.passive_conf;
+
+ /* Set active mode configuration */
+ if (stm32_tamp.active_conf != 0U)
+ atcr1 = (atcr1 & ~_TAMP_ATCR1_COMMON_MASK) |
+ (stm32_tamp.active_conf & _TAMP_ATCR1_COMMON_MASK);
+
+ for (i = 0U; i < stm32_tamp.pdata.compat->int_tamp_size; i++) {
+ ret = stm32_tamp_set_int_config(stm32_tamp.pdata.compat, i,
+ &cr1, &cr3, &ier);
+ if (ret != 0)
+ return ret;
+ }
+
+ for (i = 0U; i < stm32_tamp.pdata.compat->ext_tamp_size; i++) {
+ ret = stm32_tamp_set_ext_config(stm32_tamp.pdata.compat, i,
+ &cr1, &cr2, &atcr1, &atcr2,
+ &ier);
+ if (ret != 0)
+ return ret;
+ }
+
+ /*
+ * We apply configuration all in a row:
+ * As for active ext tamper "all the needed tampers must be enabled in
+ * the same write access".
+ */
+ io_write32(base + _TAMP_FLTCR, fltcr);
+ /* Active filter configuration applied only if not already done. */
+ if (((io_read32(base + _TAMP_ATOR) & _TAMP_INITS) != _TAMP_INITS)) {
+ io_write32(base + _TAMP_ATCR1, atcr1);
+ if (stm32_tamp.pdata.compat->tags & TAMP_HAS_ATCR2)
+ io_write32(base + _TAMP_ATCR2, atcr2);
+ }
+
+ io_write32(base + _TAMP_CR1, cr1);
+ io_write32(base + _TAMP_CR2, cr2);
+ if (stm32_tamp.pdata.compat->tags & TAMP_HAS_CR3)
+ io_write32(base + _TAMP_CR3, cr3);
+
+ /* If active tamper we reinit the seed. */
+ if (stm32_tamp.active_conf != 0U) {
+ if (stm32_tamp_set_seed(base) != TEE_SUCCESS) {
+ EMSG("Active tamper: SEED not initialized");
+ return TEE_ERROR_BAD_STATE;
+ }
+ }
+
+ /* Enable interrupts. */
+ io_write32(base + _TAMP_IER, ier);
+
+ return TEE_SUCCESS;
+}
+
+TEE_Result stm32_tamp_write_mcounter(int cnt_idx)
+{
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (cnt_idx < 0 || !stm32_tamp.pdata.compat ||
+ cnt_idx > stm32_tamp.pdata.compat->nb_monotonic_counter)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ io_write32(base + _TAMP_COUNTR + cnt_idx * sizeof(uint32_t), 1U);
+
+ return TEE_SUCCESS;
+}
+
+uint32_t stm32_tamp_read_mcounter(int cnt_idx)
+{
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (cnt_idx < 0 || !stm32_tamp.pdata.compat ||
+ cnt_idx > stm32_tamp.pdata.compat->nb_monotonic_counter)
+ return 0U;
+
+ return io_read32(base + _TAMP_COUNTR + cnt_idx * sizeof(uint32_t));
+}
+
+void stm32_tamp_configure_secret_list(uint32_t secret_list_conf)
+{
+ stm32_tamp.secret_list_conf = secret_list_conf;
+}
+
+void stm32_tamp_configure_privilege_access(uint32_t privilege_conf)
+{
+ stm32_tamp.privilege_conf = privilege_conf;
+}
+
+void stm32_tamp_configure_secure_access(uint32_t secure_conf)
+{
+ stm32_tamp.secure_conf = secure_conf;
+}
+
+void stm32_tamp_configure_passive(uint32_t passive_conf)
+{
+ stm32_tamp.passive_conf = passive_conf;
+}
+
+void stm32_tamp_configure_active(uint32_t active_conf)
+{
+ stm32_tamp.active_conf = active_conf;
+}
+
+TEE_Result stm32_tamp_configure_internal(enum stm32_tamp_int_id id,
+ uint32_t mode,
+ int (*callback)(int id))
+{
+ uint32_t i = 0;
+ uint32_t itamp_id = id;
+ struct stm32_tamp_int *tamp_int = NULL;
+
+ if (!stm32_tamp.pdata.compat)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Find internal Tamp struct*/
+ for (i = 0U; i < stm32_tamp.pdata.compat->int_tamp_size; i++) {
+ if (stm32_tamp.pdata.compat->int_tamp[i].id == itamp_id) {
+ tamp_int = &stm32_tamp.pdata.compat->int_tamp[i];
+ break;
+ }
+ }
+
+ if (!tamp_int)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ tamp_int->mode = mode;
+ tamp_int->func = callback;
+
+ return TEE_SUCCESS;
+}
+
+TEE_Result stm32_tamp_configure_external(enum stm32_tamp_ext_id id,
+ uint32_t mode,
+ enum stm32_tamp_ext_out_id out_pin,
+ int (*callback)(int id))
+{
+ uint32_t i = 0;
+ uint32_t etamp_id = id;
+ struct stm32_tamp_ext *tamp_ext = NULL;
+
+ if (!stm32_tamp.pdata.compat)
+ return TEE_ERROR_BAD_STATE;
+
+ /* Find external Tamp struct */
+ for (i = 0U; i < stm32_tamp.pdata.compat->ext_tamp_size; i++) {
+ if (stm32_tamp.pdata.compat->ext_tamp[i].id == etamp_id) {
+ tamp_ext = &stm32_tamp.pdata.compat->ext_tamp[i];
+ break;
+ }
+ }
+
+ if (!tamp_ext)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ tamp_ext->mode = mode;
+ tamp_ext->out_pin = out_pin;
+ tamp_ext->func = callback;
+
+ return TEE_SUCCESS;
+}
+
+bool stm32_tamp_are_secrets_blocked(void)
+{
+ if (stm32_tamp.pdata.compat &&
+ (stm32_tamp.pdata.compat->tags & TAMP_HAS_SECRET_STATUS)) {
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ return (((io_read32(base + _TAMP_CR2) &
+ _TAMP_CR2_BKBLOCK) == _TAMP_CR2_BKBLOCK) ||
+ (io_read32(base + _TAMP_SR) != 0));
+ } else {
+ return false;
+ }
+}
+
+void stm32_tamp_block_secrets(void)
+{
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (stm32_tamp.pdata.compat &&
+ (stm32_tamp.pdata.compat->tags & TAMP_HAS_SECRET_STATUS))
+ io_setbits32(base + _TAMP_CR2, _TAMP_CR2_BKBLOCK);
+}
+
+void stm32_tamp_unblock_secrets(void)
+{
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (stm32_tamp.pdata.compat &&
+ (stm32_tamp.pdata.compat->tags & TAMP_HAS_SECRET_STATUS))
+ io_clrbits32(base + _TAMP_CR2, _TAMP_CR2_BKBLOCK);
+}
+
+void stm32_tamp_erase_secrets(void)
+{
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (stm32_tamp.pdata.compat &&
+ (stm32_tamp.pdata.compat->tags & TAMP_HAS_SECRET_STATUS))
+ io_setbits32(base + _TAMP_CR2, _TAMP_CR2_BKERASE);
+}
+
+void stm32_tamp_lock_boot_hardware_key(void)
+{
+ vaddr_t base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ if (stm32_tamp.pdata.compat &&
+ (stm32_tamp.pdata.compat->tags & TAMP_HAS_LOCK_KEY))
+ io_setbits32(base + _TAMP_SECCFGR, _TAMP_SECCFGR_BHKLOCK);
+}
+
+static enum itr_return stm32_tamp_it_handler(struct itr_handler *h)
+{
+ struct stm32_tamp_instance *tamp = h->data;
+ vaddr_t base = io_pa_or_va(&tamp->pdata.base);
+ uint32_t it = io_read32(base + _TAMP_SR);
+ uint32_t int_it = it & _TAMP_SR_ITAMPXF_MASK;
+ uint32_t ext_it = it & _TAMP_SR_ETAMPXF_MASK;
+ uint8_t i = 0;
+ struct stm32_rtc_time tamp_ts = { };
+
+ if (stm32_rtc_is_timestamp_enable()) {
+ stm32_rtc_get_timestamp(&tamp_ts);
+ FMSG("Tamper Event Occurred");
+ FMSG("Date : %u/%u\n \t Time : %u:%u:%u",
+ tamp_ts.day, tamp_ts.month, tamp_ts.hour,
+ tamp_ts.min, tamp_ts.sec);
+ }
+
+ while ((int_it != 0U) && (i < stm32_tamp.pdata.compat->int_tamp_size)) {
+ int ret = -1;
+ uint32_t id = tamp->pdata.compat->int_tamp[i].id;
+
+ if ((it & _TAMP_SR_ITAMP(id)) != 0U) {
+ if (tamp->pdata.compat->int_tamp[i].func)
+ ret = tamp->pdata.compat->int_tamp[i].func(id);
+
+ if (ret >= 0) {
+ io_setbits32(base + _TAMP_SCR,
+ _TAMP_SR_ITAMP(id));
+ ext_it &= ~_TAMP_SR_ITAMP(id);
+
+ if (ret > 0) {
+#ifdef CFG_PM
+ stm32_cores_reset();
+#else
+ psci_system_reset();
+#endif
+ }
+ }
+ }
+ i++;
+ }
+
+ i = 0;
+ /* External tamper interrupt */
+ while ((ext_it != 0U) && (i < stm32_tamp.pdata.compat->ext_tamp_size)) {
+ int ret = -1;
+ uint32_t id = tamp->pdata.compat->ext_tamp[i].id;
+
+ if ((ext_it & _TAMP_SR_ETAMP(id)) != 0U) {
+ if (tamp->pdata.compat->ext_tamp[i].func)
+ ret = tamp->pdata.compat->ext_tamp[i].func(id);
+
+ if (ret >= 0) {
+ io_setbits32(base + _TAMP_SCR,
+ _TAMP_SCR_ETAMP(id));
+ ext_it &= ~_TAMP_SR_ETAMP(id);
+
+ if (ret > 0) {
+#ifdef CFG_PM
+ stm32_cores_reset();
+#else
+ psci_system_reset();
+#endif
+ }
+ }
+ }
+ i++;
+ }
+
+ return ITRR_HANDLED;
+}
+
+#ifdef CFG_DT
+static int get_node_from_multiple_compatible(const void *fdt,
+ struct stm32_tamp_platdata *pdata)
+{
+ const struct my_dt_device_match *cur = tamp_match_table;
+
+ while (cur->compatible) {
+ int node = -1;
+
+ node = fdt_node_offset_by_compatible(fdt, node,
+ cur->compatible);
+ if (node >= 0) {
+ pdata->compat = (struct stm32_tamp_compat *)cur->data;
+ return node;
+ }
+
+ cur++;
+ }
+
+ /* Compatible string not found */
+ return -1;
+}
+
+static int stm32_tamp_parse_fdt(struct stm32_tamp_platdata *pdata)
+{
+ int node = -1;
+ struct dt_node_info dt_tamp = { };
+ void *fdt = NULL;
+
+ fdt = get_embedded_dt();
+ if (!fdt)
+ return -1;
+
+ node = get_node_from_multiple_compatible(fdt, pdata);
+ if (node < 0)
+ return -1;
+
+ _fdt_fill_device_info(fdt, &dt_tamp, node);
+
+ if (dt_tamp.status == DT_STATUS_DISABLED ||
+ dt_tamp.clock == DT_INFO_INVALID_CLOCK ||
+ dt_tamp.reg == DT_INFO_INVALID_REG ||
+ dt_tamp.interrupt == DT_INFO_INVALID_INTERRUPT) {
+ return -1;
+ }
+
+ pdata->it = dt_tamp.interrupt;
+ pdata->base.pa = dt_tamp.reg;
+ pdata->base.va = (vaddr_t)phys_to_virt(dt_tamp.reg, MEM_AREA_IO_SEC);
+
+ pdata->clock = dt_tamp.clock;
+
+ pdata->pins_conf = 0;
+ if (stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0) > 0) {
+ if (pdata->compat == &mp15_compat) {
+ if (fdt_getprop(fdt, node, "st,out3-pc13", NULL))
+ pdata->pins_conf |= _TAMP_OR_OUT3RMP_PC13;
+ }
+ }
+
+ if (fdt_getprop(fdt, node, "wakeup-source", NULL))
+ pdata->is_wakeup_source = true;
+
+ return 0;
+}
+
+__weak
+int stm32_tamp_get_platdata(struct stm32_tamp_platdata *pdata __unused)
+{
+ /* In DT config, the platform data are filled by DT file */
+ return 0;
+}
+#else /* CFG_DT */
+static int stm32_tamp_parse_fdt(struct stm32_tamp_platdata *pdata)
+{
+ /* Do nothing, there is no fdt to parse in this case */
+ return 0;
+}
+
+/* This function can be overridden by platform to define pdata of tamp driver */
+__weak
+int stm32_tamp_get_platdata(struct stm32_tamp_platdata *pdata __unused)
+{
+ return -1;
+}
+#endif /* CFG_DT */
+
+static struct itr_handler stm32_tamp_itr_handler = {
+ .handler = stm32_tamp_it_handler,
+};
+DECLARE_KEEP_PAGER(stm32_tamp_itr_handler);
+
+static TEE_Result stm32_tamp_init(void)
+{
+ int ret = TEE_SUCCESS;
+ vaddr_t base = 0;
+ uint32_t __unused rev = 0;
+
+ ret = stm32_tamp_get_platdata(&stm32_tamp.pdata);
+ if (ret)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ ret = stm32_tamp_parse_fdt(&stm32_tamp.pdata);
+ if (ret)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ /* Init Tamp clock */
+ clk_enable(stm32_tamp.pdata.clock);
+
+ base = io_pa_or_va(&stm32_tamp.pdata.base);
+
+ stm32_tamp.hwconf1 = io_read32(base + _TAMP_HWCFGR1);
+ stm32_tamp.hwconf2 = io_read32(base + _TAMP_HWCFGR2);
+
+#if TRACE_LEVEL >= TRACE_FLOW
+ rev = io_read32(base + _TAMP_VERR);
+ FMSG("STM32 TAMPER V%u.%u", (rev & _TAMP_VERR_MAJREV) >> 4,
+ rev & _TAMP_VERR_MINREV);
+#endif
+
+ if ((stm32_tamp.hwconf2 & _TAMP_HWCFGR2_TZ) == 0U) {
+ EMSG("Tamper IP doesn't support trustzone");
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ stm32_tamp_set_pins(base, stm32_tamp.pdata.pins_conf);
+
+ stm32_tamp_itr_handler.it = stm32_tamp.pdata.it;
+ stm32_tamp_itr_handler.data = &stm32_tamp;
+ itr_add(&stm32_tamp_itr_handler);
+ itr_enable(stm32_tamp_itr_handler.it);
+
+ /* Need a new API */
+ if (stm32_tamp.pdata.is_wakeup_source)
+ IMSG("TAMP event are not configured as wakeup source");
+
+ return TEE_SUCCESS;
+}
+
+driver_init(stm32_tamp_init);
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index 0d3b81e21..10a641b9d 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -30,6 +30,7 @@ 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_TAMP) += stm32_tamp.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/stm32_tamp.h b/core/include/drivers/stm32_tamp.h
new file mode 100644
index 000000000..556cd136d
--- /dev/null
+++ b/core/include/drivers/stm32_tamp.h
@@ -0,0 +1,378 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2021, STMicroelectronics
+ */
+
+#ifndef __STM32_TAMP_H__
+#define __STM32_TAMP_H__
+
+#include <mm/core_memprot.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+/* Internal Tamper */
+enum stm32_tamp_int_id {
+ INT_TAMP1 = 0,
+ INT_TAMP2,
+ INT_TAMP3,
+ INT_TAMP4,
+ INT_TAMP5,
+ INT_TAMP6,
+ INT_TAMP7,
+ INT_TAMP8,
+ INT_TAMP9,
+ INT_TAMP10,
+ INT_TAMP11,
+ INT_TAMP12,
+ INT_TAMP13,
+ INT_TAMP14,
+ INT_TAMP15,
+ INT_TAMP16
+};
+
+/* External Tamper */
+enum stm32_tamp_ext_id {
+ EXT_TAMP1 = 0,
+ EXT_TAMP2,
+ EXT_TAMP3,
+ EXT_TAMP4,
+ EXT_TAMP5,
+ EXT_TAMP6,
+ EXT_TAMP7,
+ EXT_TAMP8
+};
+
+/* Out pin to compare for external Tamper */
+enum stm32_tamp_ext_out_id {
+ TAMPOUTSEL_SAME_AS_INPUT = 0,
+ TAMPOUTSEL1,
+ TAMPOUTSEL2,
+ TAMPOUTSEL3,
+ TAMPOUTSEL4,
+ TAMPOUTSEL5,
+ TAMPOUTSEL6,
+ TAMPOUTSEL7,
+ TAMPOUTSEL8,
+};
+
+/*
+ * Define number of backup registers in zone 1 and zone 2 (remaining are in
+ * zone 3)
+ *
+ * backup registers in zone 1 : read/write only in secure mode
+ * zone 2 : write only in secure mode, read in secure
+ * and non-secure mode
+ * zone 3 : read/write in secure and non-secure mode
+ *
+ * Protection zone 1 if nb_zone1_regs == 0 no backup register are in zone 1
+ * else backup registers from TAMP_BKP0R to TAMP_BKPxR
+ * with x = nb_zone1_regs - 1 are in zone 1.
+ * Protection zone 2 if nb_zone2_regs == 0 no backup register are in zone 2
+ * else backup registers from
+ * TAMP_BKPyR with y = nb_zone1_regs
+ * to
+ * TAMP_BKPzR with z = (nb_zone1_regs1 + nb_zone2_regs - 1)
+ * are in zone 2.
+ * Protection zone 3 backup registers from TAMP_BKPtR
+ * with t = nb_zone1_regs1 + nb_zone2_regs to last backup
+ * register are in zone 3.
+ */
+struct stm32_bkpregs_conf {
+ uint32_t nb_zone1_regs;
+ uint32_t nb_zone2_regs;
+};
+
+/* Define TAMPER modes */
+#define TAMP_DISABLE 0x0U
+#define TAMP_ENABLE 0x1U
+#define TAMP_TRIG_OFF 0x0U
+#define TAMP_TRIG_ON 0x2U
+#define TAMP_PASSIVE 0x0U
+#define TAMP_ACTIVE 0x4U
+#define TAMP_ERASE 0x0U
+#define TAMP_NOERASE 0x8U
+#define TAMP_NO_EVT_MASK 0x0U
+#define TAMP_EVT_MASK 0x10U
+
+/* Define Passive FILTER mode */
+#define TAMP_FILTER_TAMPPUDIS_OFFSET 7U
+#define TAMP_FILTER_PRECHARGE (0x0U << TAMP_FILTER_TAMPPUDIS_OFFSET)
+#define TAMP_FILTER_PULL_UP_DISABLE (0x1U << TAMP_FILTER_TAMPPUDIS_OFFSET)
+#define TAMP_FILTER_TAMPPRCH_OFFSET 5U
+#define TAMP_FILTER_PRECHARGE_1_CYCLE (0x0U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_PRECHARGE_2_CYCLES (0x1U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_PRECHARGE_4_CYCLES (0x2U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_PRECHARGE_8_CYCLES (0x3U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_TAMPFLT_OFFSET 3U
+#define TAMP_FILTER_EDGE (0x0U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_2_SAMPLE (0x1U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_4_SAMPLE (0x2U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_8_SAMPLE (0x3U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_TAMPFREQ_OFFSET 0U
+#define TAMP_FILTER_SAMPLING_32768 (0x0U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_16384 (0x1U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_8192 (0x2U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_4096 (0x3U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_2048 (0x4U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_1024 (0x5U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_512 (0x6U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_256 (0x7U << TAMP_FILTER_TAMPFREQ_OFFSET)
+
+/* Define active filter */
+#define TAMP_ACTIVE_FLTEN_OFFSET 31U
+#define TAMP_ACTIVE_FILTER_OFF (0x0U << TAMP_ACTIVE_FLTEN_OFFSET)
+#define TAMP_ACTIVE_FILTER_ON (0x1U << TAMP_ACTIVE_FLTEN_OFFSET)
+#define TAMP_ACTIVE_ATOSHARE_OFFSET 30U
+#define TAMP_ACTIVE_USE_DEDICATED_OUT (0x0U << \
+ TAMP_ACTIVE_FILTER_ATOSHARE_OFFSET)
+#define TAMP_ACTIVE_SELECT_OUT (0x1U << \
+ TAMP_ACTIVE_FILTER_ATOSHARE_OFFSET)
+#define TAMP_ACTIVE_ATPER_OFFSET 24U
+#define TAMP_ACTIVE_ATPER_1_OUTPUT (0x0U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATPER_2_OUTPUTS (0x1U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATPER_3_4_OUTPUTS (0x2U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATPER_5_OUTPUTS (0x3U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATCKSEL_OFFSET 16U
+#define TAMP_ACTIVE_CKSEL_DIV_0 (0x0U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_2 (0x1U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_4 (0x2U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_8 (0x3U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_16 (0x4U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_32 (0x5U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_64 (0x6U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_128 (0x7U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+
+/* Define device secret list */
+#define TAMP_NON_CONFIGURABLE_SECRETS 0x0U
+#define TAMP_CONF_SECRET_BACKUP_SRAM 0x1U
+
+/* Define secure mode access */
+/*
+ * Tamper configuration and interrupt can be written when the APB access is
+ * secure or nonsecure.
+ */
+#define TAMP_REGS_IT_UNSECURE 0U
+/*
+ * Tamper configuration and interrupt can be written only when the APB access
+ * is secure.
+ */
+#define TAMP_REGS_IT_SECURE BIT(31)
+/*
+ * Tamper monotonic counter 1 can be written when the APB access is secure or
+ * nonsecure.
+ */
+#define TAMP_CNT1_UNSECURE 0U
+/*
+ * Tamper monotonic counter 3 can be written only when the APB access is
+ * secure.
+ */
+#define TAMP_CNT1_SECURE BIT(15)
+/*
+ * Tamper monotonic counter 2 can be written when the APB access is secure or
+ * nonsecure.
+ */
+#define TAMP_CNT2_UNSECURE 0U
+/*
+ * Tamper monotonic counter 3 can be written only when the APB access is
+ * secure.
+ */
+#define TAMP_CNT2_SECURE BIT(14)
+
+/* Define privilege mode access */
+/*
+ * Tamper registers (but backup and cnt) can be written with privileged or
+ * unprivileged access.
+ */
+#define TAMP_REGS_UNPRIVILEGE 0U
+/*
+ * Tamper registers (but backupand cnt) can be written only with privileged
+ * access.
+ */
+#define TAMP_REGS_PRIVILEGE BIT(31)
+/*
+ * Backup registers zone 2 can be written with privileged or unprivileged
+ * access.
+ */
+#define TAMP_BKP2W_UNPRIVILEGE 0U
+/* Backup registers zone 2 can be written only with privileged access. */
+#define TAMP_BKP2W_PRIVILEGE BIT(30)
+/*
+ * Backup registers zone 1 can be read and written with privileged or
+ * unprivileged access.
+ */
+#define TAMP_BKP1RW_UNPRIVILEGE 0U
+/*
+ * Backup registers zone 1 can be read and written only with privileged
+ * access.
+ */
+#define TAMP_BKP1RW_PRIVILEGE BIT(29)
+/*
+ * Monotonic counter 1 can be read and written with privileged or unprivileged
+ * access.
+ */
+#define TAMP_CNT1_UNPRIVILEGE 0U
+/* Monotonic counter 1 can be read and written only with privileged access. */
+#define TAMP_CNT1_PRIVILEGE BIT(15)
+/*
+ * Monotonic counter 2 can be read and written with privileged or unprivileged
+ * access.
+ */
+#define TAMP_CNT2_UNPRIVILEGE 0U
+/* Monotonic counter 2 can be read and written only with privileged access. */
+#define TAMP_CNT2_PRIVILEGE BIT(14)
+
+/*
+ * stm32_tamp_write_mcounter : Increase monotonic counter[counter_idx].
+ */
+TEE_Result stm32_tamp_write_mcounter(int counter_idx);
+uint32_t stm32_tamp_read_mcounter(int counter_idx);
+
+bool stm32_tamp_are_secrets_blocked(void);
+void stm32_tamp_block_secrets(void);
+void stm32_tamp_unblock_secrets(void);
+void stm32_tamp_erase_secrets(void);
+void stm32_tamp_lock_boot_hardware_key(void);
+
+/*
+ * stm32_tamp_configure_secret_list: Configure which extra IPs
+ * are blocked/erased in case of tamper event.
+ *
+ * secret_list_conf is a bit field from TAMP_CONF_SECRET_.*
+ */
+void stm32_tamp_configure_secret_list(uint32_t secret_list_conf);
+
+/*
+ * stm32_tamp_configure_secure_access: Configure which registers can be
+ * read/write from unsecure world.
+ * secure_conf is a bit field from TAMP_.*_{UN,}SECURE define
+ */
+void stm32_tamp_configure_secure_access(uint32_t secure_conf);
+
+/*
+ * stm32_tamp_configure_privilege_access: Configure which registers can be
+ * read/write from unpriviliged world.
+ * privilege_conf is a bit field from TAMP_.*_{UN,}PRIVILEGE define
+ */
+void stm32_tamp_configure_privilege_access(uint32_t privilege_conf);
+
+/*
+ * stm32_tamp_configure_passive: Configure passive mode
+ * passive_conf is a bit field from TAMP_FILTER_* define
+ */
+void stm32_tamp_configure_passive(uint32_t passive_conf);
+
+/*
+ * stm32_tamp_configure_ctive: Configure active mode
+ * passive_conf is a bit field from TAMP_ACTIVE_* define
+ */
+void stm32_tamp_configure_active(uint32_t active_conf);
+
+/*
+ * stm32_tamp_configure_internal: Configure one internal tamper.
+ * id: internal tamper id
+ * mode: bitmask from TAMPER modes define
+ * callback: function to call when tamper is raised (can be NULL),
+ * called in interrupt context,
+ * if callback returns negative value, blocked secrets stay blocked
+ * (driver doesn't release this specific tamper).
+ * if callback returns 0 this specific tamp is ack (in case of
+ * no-erase tamper, blocked secret are unblocked)
+ * if callback returns positive value, this specific tamp is ack (in
+ * case of no-erase tamper, blocked secret are unblocked) and system
+ * is rebooted).
+ *
+ * return: TEE_BAD_PARAMETERS if 'id' is not a valid internal tamp id,
+ * else TEE_SUCCESS.
+ */
+TEE_Result stm32_tamp_configure_internal(enum stm32_tamp_int_id id,
+ uint32_t mode,
+ int (*callback)(int id));
+
+/*
+ * stm32_tamp_configure_external: Configure one external tamper.
+ * id: external tamper id
+ * mode: bitmask from TAMPER modes define
+ * pin_out; output pin connected to input pin (linekd with selected ext tamp id)
+ * callback: function to call when tamper is raised (can be NULL),
+ * called in interrupt context,
+ * if callback returns negative value, blocked secrets stay blocked
+ * (driver doesn't release this specific tamper).
+ * if callback returns 0 this specific tamp is ack (in case of
+ * no-erase tamper, blocked secret are unblocked)
+ * if callback returns positive value, this specific tamp is ack (in
+ * case of no-erase tamper, blocked secret are unblocked) and system
+ * is rebooted).
+ *
+ * return: TEE_BAD_PARAMETERS if 'id' is not a valid external tamp id,
+ * else TEE_SUCCESS.
+ */
+TEE_Result stm32_tamp_configure_external(enum stm32_tamp_ext_id id,
+ uint32_t mode,
+ enum stm32_tamp_ext_out_id out_pin,
+ int (*callback)(int id));
+
+/*
+ * stm32_tamp_set_secure_bkprwregs : Configure backup registers zone.
+ * registers in zone 1 : read/write only in secure mode
+ * zone 2 : write only in secure mode, read in secure and
+ * non-secure mode
+ * zone 3 : read/write in secure and non-secure mode
+ *
+ * bkpregs_conf : a pointer to struct bkpregs_conf that define the number of
+ * registers in zone 1 and zone 2 (remaining backup registers will be in
+ * zone 3).
+ *
+ * return TEE_ERROR_NOT_SUPPORTED: if zone 1 and/or zone 2 definition are out
+ * of range.
+ * TEE_ERROR_BAD_PARAMETERS: if bkpregs_cond is NULL.
+ * TEE_SUCCESS : if OK.
+ */
+TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf
+ *bkpregs_conf);
+
+/*
+ * stm32_tamp_set_config: Apply configuration.
+ * Default one if no previous call to any of :
+ * stm32_tamp_configure_passive()
+ * stm32_tamp_configure_active()
+ * stm32_tamp_configure_internal()
+ * stm32_tamp_configure_external()
+ * stm32_tamp_configure_secret_list()
+ * stm32_tamp_configure_secure_access()
+ * stm32_tamp_configure_privilege_access()
+ *
+ */
+TEE_Result stm32_tamp_set_config(void);
+
+/* Compatibility tags */
+#define TAMP_HAS_CONF_SECURE BIT(0)
+#define TAMP_HAS_CONF_PRIVILEGE BIT(1)
+#define TAMP_HAS_CONF_SECRET_IPS BIT(2)
+#define TAMP_HAS_ATCR2 BIT(3)
+#define TAMP_HAS_CR3 BIT(4)
+#define TAMP_HAS_SECRET_STATUS BIT(5)
+#define TAMP_HAS_LOCK_KEY BIT(6)
+
+struct stm32_tamp_compat {
+ int nb_monotonic_counter;
+ uint32_t tags;
+ struct stm32_tamp_int *int_tamp;
+ uint32_t int_tamp_size;
+ struct stm32_tamp_ext *ext_tamp;
+ uint32_t ext_tamp_size;
+};
+
+struct stm32_tamp_platdata {
+ struct io_pa_va base;
+ uint32_t clock;
+ int it;
+ uint32_t pins_conf;
+ bool is_wakeup_source;
+ struct stm32_tamp_compat *compat;
+};
+
+int stm32_tamp_get_platdata(struct stm32_tamp_platdata *pdata);
+
+#endif /* __STM32_TAMP_H__ */
diff --git a/core/include/kernel/dt.h b/core/include/kernel/dt.h
index 3044989c7..e9f816488 100644
--- a/core/include/kernel/dt.h
+++ b/core/include/kernel/dt.h
@@ -31,12 +31,15 @@
* @reg: Device register physical base address or DT_INFO_INVALID_REG
* @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK
* @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK
+ * @interrupt: Device interrupt identifier (positive value) or
+ * DT_INFO_INVALID_INTERRUPT
*/
struct dt_node_info {
unsigned int status;
paddr_t reg;
int clock;
int reset;
+ int interrupt;
};
#if defined(CFG_DT)
@@ -96,18 +99,6 @@ int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size);
*/
bool dt_have_prop(const void *fdt, int offs, const char *propname);
-/*
- * Get the DT interrupt property of the @node. In the DT an interrupt
- * is defined with at least 2x32 bits detailling the interrupt number and type.
- *
- * @fdt reference to the Device Tree
- * @node is the node offset to read
- *
- * Returns the interrupt number if value >= 0
- * otherwise DT_INFO_INVALID_INTERRUPT
- */
-int dt_get_irq(void *fdt, int node);
-
/*
* Modify or add "status" property to "disabled"
*
diff --git a/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h
index 796eded29..4a0b4474b 100644
--- a/core/include/kernel/interrupt.h
+++ b/core/include/kernel/interrupt.h
@@ -14,6 +14,7 @@
struct itr_chip {
const struct itr_ops *ops;
+ int (*dt_get_irq)(const uint32_t *properties, int len);
};
struct itr_ops {
@@ -48,6 +49,30 @@ struct itr_handler {
void itr_init(struct itr_chip *data);
void itr_handle(size_t it);
+#ifdef CFG_DT
+/*
+ * Get the DT interrupt property at @node. In the DT an interrupt
+ *
+ * @fdt reference to the Device Tree
+ * @node is the node offset to read
+ *
+ * Returns the interrupt number if value >= 0
+ * otherwise DT_INFO_INVALID_INTERRUPT
+ */
+int dt_get_irq(const void *fdt, int node);
+
+/*
+ * Get the DT secure-interrupt property at @node.
+ *
+ * @fdt reference to the Device Tree
+ * @node is the node offset to read
+ *
+ * Returns the interrupt number if value >= 0
+ * otherwise DT_INFO_INVALID_INTERRUPT
+ */
+int dt_get_irq_secure(const void *fdt, int node);
+#endif
+
void itr_add(struct itr_handler *handler);
void itr_enable(size_t it);
void itr_disable(size_t it);
diff --git a/core/kernel/dt.c b/core/kernel/dt.c
index fcfa26929..4410bf52b 100644
--- a/core/kernel/dt.c
+++ b/core/kernel/dt.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <kernel/dt.h>
+#include <kernel/interrupt.h>
#include <kernel/linker.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
@@ -51,27 +52,6 @@ bool dt_have_prop(const void *fdt, int offs, const char *propname)
return prop;
}
-int dt_get_irq(void *fdt, int node)
-{
- const uint32_t *int_prop = NULL;
- int len_prop = 0;
- int it_num = DT_INFO_INVALID_INTERRUPT;
-
- /*
- * Interrupt property can be defined with at least 2x32 bits word
- * - Type of interrupt
- * - Interrupt Number
- */
- int_prop = fdt_getprop(fdt, node, "interrupts", &len_prop);
-
- if (!int_prop || len_prop < 2)
- return it_num;
-
- it_num = fdt32_to_cpu(int_prop[1]);
-
- return it_num;
-}
-
int dt_disable_status(void *fdt, int node)
{
const char *prop = NULL;
@@ -288,6 +268,7 @@ void _fdt_fill_device_info(void *fdt, struct dt_node_info *info, int offs)
.reg = DT_INFO_INVALID_REG,
.clock = DT_INFO_INVALID_CLOCK,
.reset = DT_INFO_INVALID_RESET,
+ .interrupt = DT_INFO_INVALID_INTERRUPT,
};
const fdt32_t *cuint;
@@ -305,6 +286,11 @@ void _fdt_fill_device_info(void *fdt, struct dt_node_info *info, int offs)
dinfo.reset = (int)fdt32_to_cpu(*cuint);
}
+ /* We first look for the secure interrupt, if not found the interrupt */
+ dinfo.interrupt = dt_get_irq_secure(fdt, offs);
+ if (dinfo.interrupt == DT_INFO_INVALID_INTERRUPT)
+ dinfo.interrupt = dt_get_irq(fdt, offs);
+
dinfo.status = _fdt_get_status(fdt, offs);
*info = dinfo;
diff --git a/core/kernel/interrupt.c b/core/kernel/interrupt.c
index 376012556..61c299745 100644
--- a/core/kernel/interrupt.c
+++ b/core/kernel/interrupt.c
@@ -3,8 +3,10 @@
* Copyright (c) 2016-2019, Linaro Limited
*/
+#include <kernel/dt.h>
#include <kernel/interrupt.h>
#include <kernel/panic.h>
+#include <libfdt.h>
#include <trace.h>
#include <assert.h>
@@ -25,6 +27,34 @@ void itr_init(struct itr_chip *chip)
itr_chip = chip;
}
+#ifdef CFG_DT
+static int _dt_get_irq(const void *fdt, int node, const char *prop_name)
+{
+ const uint32_t *prop = NULL;
+ int len = 0;
+ int it_num = DT_INFO_INVALID_INTERRUPT;
+
+ if (!itr_chip || !itr_chip->dt_get_irq)
+ return it_num;
+
+ prop = fdt_getprop(fdt, node, prop_name, &len);
+ if (!prop)
+ return it_num;
+
+ return itr_chip->dt_get_irq(prop, len);
+}
+
+int dt_get_irq(const void *fdt, int node)
+{
+ return _dt_get_irq(fdt, node, "interrupts");
+}
+
+int dt_get_irq_secure(const void *fdt, int node)
+{
+ return _dt_get_irq(fdt, node, "secure-interrupts");
+}
+#endif
+
void itr_handle(size_t it)
{
struct itr_handler *h = NULL;
diff --git a/mk/config.mk b/mk/config.mk
index a14c4f832..c92a0edce 100644
--- a/mk/config.mk
+++ b/mk/config.mk
@@ -111,7 +111,7 @@ CFG_TEE_IMPL_DESCR ?= OPTEE
CFG_OS_REV_REPORTS_GIT_SHA1 ?= y
# Trusted OS implementation version
-TEE_IMPL_VERSION ?= $(shell git describe --always --dirty=-dev 2>/dev/null || echo Unknown)
+TEE_IMPL_VERSION ?= $(shell git describe --always --tags --dirty=-dev 2>/dev/null || echo Unknown)
ifeq ($(CFG_OS_REV_REPORTS_GIT_SHA1),y)
TEE_IMPL_GIT_SHA1 := 0x$(shell git rev-parse --short=8 HEAD 2>/dev/null || echo 0)
else
--
2.17.1