diff --git a/recipes-security/optee/optee-os-stm32mp-archiver.inc b/recipes-security/optee/optee-os-stm32mp-archiver.inc index cf7d58a..604fc64 100644 --- a/recipes-security/optee/optee-os-stm32mp-archiver.inc +++ b/recipes-security/optee/optee-os-stm32mp-archiver.inc @@ -29,7 +29,7 @@ LDFLAGS = CFLAGS = CPPFLAGS = # Define default make options -EXTRA_OEMAKE = $(echo "${EXTRA_OEMAKE}" | sed "s|LIBGCC_LOCATE_CFLAGS=[^ ]* |LIBGCC_LOCATE_CFLAGS=\$(KCFLAGS) |;s|comp-cflagscore='[^']*'|comp-cflagscore='\$(KCFLAGS)'|") +EXTRA_OEMAKE = $(echo "${EXTRA_OEMAKE}" | sed "s|LIBGCC_LOCATE_CFLAGS=[^ ]* |LIBGCC_LOCATE_CFLAGS=\$(KCFLAGS) |") ifeq (\$(ENABLE_FIP), 0) EXTRA_OEMAKE += CFG_STM32MP15x_STM32IMAGE=y endif diff --git a/recipes-security/optee/optee-os-stm32mp-common.inc b/recipes-security/optee/optee-os-stm32mp-common.inc index 6102739..cf47819 100644 --- a/recipes-security/optee/optee-os-stm32mp-common.inc +++ b/recipes-security/optee/optee-os-stm32mp-common.inc @@ -26,7 +26,6 @@ EXTRA_OEMAKE += "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', 'CFG_ARM64_cor EXTRA_OEMAKE += "NOWERROR=1" EXTRA_OEMAKE += "LDFLAGS=" EXTRA_OEMAKE += "LIBGCC_LOCATE_CFLAGS=--sysroot=${STAGING_DIR_TARGET}" -EXTRA_OEMAKE += "comp-cflagscore='--sysroot=${STAGING_DIR_TARGET}'" EXTRA_OEMAKE += "${@bb.utils.contains('MACHINE_FEATURES', 'fip', '', 'CFG_STM32MP15x_STM32IMAGE=y', d)}" # debug and trace @@ -44,7 +43,13 @@ do_compile() { unset -v CFLAGS CPPFLAGS LDFLAGS LDADD if [ -n "${OPTEE_CONF}" ]; then for conf in ${OPTEE_CONF}; do - oe_runmake -C ${S} O=${B}/${conf} CFG_EMBED_DTB_SOURCE_FILE=${conf}.dts + for soc in ${STM32MP_SOC_NAME}; do + if [ "$(echo ${conf} | grep -c ${soc})" -eq 1 ]; then + soc_extra="$(echo CFG_${soc} | awk '{print toupper($0)}')=y" + fi + done + + oe_runmake -C ${S} O=${B}/${conf} CFG_EMBED_DTB_SOURCE_FILE=${conf}.dts ${soc_extra} done else oe_runmake -C ${S} O=${B}/out diff --git a/recipes-security/optee/optee-os-stm32mp_3.12.0.bb b/recipes-security/optee/optee-os-stm32mp_3.12.0.bb index 12ebcff..427e454 100644 --- a/recipes-security/optee/optee-os-stm32mp_3.12.0.bb +++ b/recipes-security/optee/optee-os-stm32mp_3.12.0.bb @@ -7,11 +7,13 @@ SRCREV = "3d47a131bca1d9ed511bfd516aa5e70269e12c1d" SRC_URI += " \ file://0001-3.12.0-stm32mp-r1.patch \ + file://0002-3.12.0-stm32mp-r1.1-rc1.patch \ + file://0003-3.12.0-stm32mp-r2.patch \ " OPTEE_VERSION = "3.12.0" OPTEE_SUBVERSION = "stm32mp" -OPTEE_RELEASE = "r1" +OPTEE_RELEASE = "r2" PV = "${OPTEE_VERSION}-${OPTEE_SUBVERSION}-${OPTEE_RELEASE}" @@ -30,7 +32,6 @@ OPTEEMACHINE_stm32mp1common = "stm32mp1" OPTEEOUTPUTMACHINE ?= "stm32mp1" OPTEEOUTPUTMACHINE_stm32mp1common = "stm32mp1" - # The package is empty but must be generated to avoid apt-get installation issue ALLOW_EMPTY_${PN} = "1" @@ -47,7 +48,7 @@ include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'optee-os-stm3 BBCLASSEXTEND = "devupstream:target" SRC_URI_class-devupstream = "git://github.com/STMicroelectronics/optee_os.git;protocol=https;branch=${ARCHIVER_ST_BRANCH}" -SRCREV_class-devupstream = "0bd33404e9581d00514034b7b05a2cbe8649c1fd" +SRCREV_class-devupstream = "639a8566de8fa720d2cb7ab7231e8de105e7859d" # --------------------------------- # Configure default preference to manage dynamic selection between tarball and github diff --git a/recipes-security/optee/optee-os/0002-3.12.0-stm32mp-r1.1-rc1.patch b/recipes-security/optee/optee-os/0002-3.12.0-stm32mp-r1.1-rc1.patch new file mode 100644 index 0000000..27dae5c --- /dev/null +++ b/recipes-security/optee/optee-os/0002-3.12.0-stm32mp-r1.1-rc1.patch @@ -0,0 +1,61 @@ +From 4a99b2016fd0a2e207395da314a3c903c2e65c08 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +Date: Wed, 2 Jun 2021 16:53:20 +0200 +Subject: [PATCH 2/3] 3.12.0-stm32mp-r1.1-rc1 + +--- + core/arch/arm/plat-stm32mp1/remoteproc_pta.c | 9 +++------ + core/drivers/clk/clk-stm32mp15.c | 2 +- + core/drivers/stm32_bsec.c | 2 +- + 3 files changed, 5 insertions(+), 8 deletions(-) + +diff --git a/core/arch/arm/plat-stm32mp1/remoteproc_pta.c b/core/arch/arm/plat-stm32mp1/remoteproc_pta.c +index 27b0dfa07..8f3360122 100644 +--- a/core/arch/arm/plat-stm32mp1/remoteproc_pta.c ++++ b/core/arch/arm/plat-stm32mp1/remoteproc_pta.c +@@ -492,13 +492,10 @@ static TEE_Result + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) + { +- struct tee_ta_session *s = tee_ta_get_calling_session(); ++ struct ts_session *s = ts_get_calling_session(); + +- /* Check that we're called from a user TA */ +- if (!s) +- return TEE_ERROR_ACCESS_DENIED; +- +- if (!is_user_ta_ctx(s->ctx)) ++ /* TODO: check that we're called the remove proc TA (check UUID) */ ++ if (!s || !is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +diff --git a/core/drivers/clk/clk-stm32mp15.c b/core/drivers/clk/clk-stm32mp15.c +index 794fd5e75..6bbab8902 100644 +--- a/core/drivers/clk/clk-stm32mp15.c ++++ b/core/drivers/clk/clk-stm32mp15.c +@@ -962,7 +962,7 @@ static unsigned long __clk_get_parent_rate(enum stm32mp1_parent_id p) + unsigned long clock = 0; + vaddr_t rcc_base = stm32_rcc_base(); + +- switch (p) { ++ switch ((unsigned int)p) { + case _CK_MPU: + /* MPU sub system */ + reg = io_read32(rcc_base + RCC_MPCKSELR); +diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c +index 7d389a061..a8eba5f7d 100644 +--- a/core/drivers/stm32_bsec.c ++++ b/core/drivers/stm32_bsec.c +@@ -646,7 +646,7 @@ static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) + + size = length / sizeof(uint32_t); + +- if (otp_id + size > STM32MP1_OTP_MAX_ID) ++ if (otp_id + size > OTP_MAX_SIZE) + panic("OTP range oversized"); + + for (i = otp_id; i < otp_id + size; i++) +-- +2.17.1 + diff --git a/recipes-security/optee/optee-os/0003-3.12.0-stm32mp-r2.patch b/recipes-security/optee/optee-os/0003-3.12.0-stm32mp-r2.patch new file mode 100644 index 0000000..c4f3061 --- /dev/null +++ b/recipes-security/optee/optee-os/0003-3.12.0-stm32mp-r2.patch @@ -0,0 +1,2251 @@ +From 547f5ef88ac962218f2cb8cb90bc4cab1b99f7f9 Mon Sep 17 00:00:00 2001 +From: Romuald JEANNE +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 + #include + #include ++#include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include ++#include + #include + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* If psci_reset */ ++#include ++#include ++#include /* If stm32_cores_reset() */ ++ ++#include ++ ++/* 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 ++#include ++#include ++#include ++#include ++ ++/* 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 + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + +@@ -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 +