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

849 lines
25 KiB
Diff

From 40bea7e6dd305b8fec278fa56bc38eed127ce946 Mon Sep 17 00:00:00 2001
From: Lionel VITTE <lionel.vitte@st.com>
Date: Mon, 3 Jul 2023 10:30:06 +0200
Subject: [PATCH] 3.16.0-stm32mp-r2.1-rc1
---
core/arch/arm/dts/stm32mp135f-dk.dts | 4 +-
core/arch/arm/plat-stm32mp1/conf.mk | 4 +-
.../arm/plat-stm32mp1/drivers/stm32mp1_pmic.c | 151 +++++++++++++-----
.../plat-stm32mp1/drivers/stm32mp1_pwr_irq.c | 78 ++++++---
core/arch/arm/plat-stm32mp1/main.c | 4 +-
core/arch/arm/plat-stm32mp1/pm/context.c | 12 +-
core/arch/arm/plat-stm32mp1/pm/low_power.c | 15 +-
core/drivers/crypto/stm32/stm32_saes.c | 7 +
core/drivers/regulator/core.c | 5 +
core/drivers/stm32_iwdg.c | 18 ++-
core/drivers/stm32_rng.c | 12 +-
core/drivers/stm32_uart.c | 4 +-
core/include/drivers/stpmic1.h | 35 ----
core/include/kernel/huk_subkey.h | 5 +
core/kernel/huk_subkey.c | 16 +-
.../devicetree/bindings/mfd/st,stpmic1.yaml | 51 ++++++
16 files changed, 293 insertions(+), 128 deletions(-)
diff --git a/core/arch/arm/dts/stm32mp135f-dk.dts b/core/arch/arm/dts/stm32mp135f-dk.dts
index 4400b2b13..710446101 100644
--- a/core/arch/arm/dts/stm32mp135f-dk.dts
+++ b/core/arch/arm/dts/stm32mp135f-dk.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/clock/stm32mp13-clksrc.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/stm32mp_gpio.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
#include <dt-bindings/power/stm32mp1-power.h>
#include <dt-bindings/rtc/rtc-stm32.h>
#include <dt-bindings/soc/stm32mp-tzc400-macro.h>
@@ -192,7 +193,8 @@
reg = <0x33>;
status = "okay";
st,wakeup-pin-number = <1>;
- st,notif-it-id = <0>;
+ st,pmic-it-id = <IT_PONKEY_F IT_PONKEY_R>;
+ st,notif-it-id = <0 2>;
regulators {
compatible = "st,stpmic1-regulators";
diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk
index 6c959d4bc..05229e61e 100644
--- a/core/arch/arm/plat-stm32mp1/conf.mk
+++ b/core/arch/arm/plat-stm32mp1/conf.mk
@@ -310,10 +310,8 @@ CFG_ENABLE_EMBEDDED_TESTS ?= y
CFG_WITH_STATS ?= y
CFG_WERROR ?= y
-# Enable to allow debug
-ifeq ($(CFG_TEE_CORE_DEBUG),y)
+# Enable OTP update with BSEC driver
CFG_STM32_BSEC_WRITE ?= y
-endif
# Default disable some support for pager memory size constraint
ifeq ($(CFG_WITH_PAGER),y)
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
index 4eda619cf..653ac4f7d 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
@@ -12,6 +12,7 @@
#include <drivers/stm32mp1_pmic.h>
#include <drivers/stm32mp1_pwr.h>
#include <drivers/stpmic1.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
#include <io.h>
#include <keep.h>
#include <kernel/boot.h>
@@ -26,6 +27,7 @@
#include <platform_config.h>
#include <stdbool.h>
#include <stm32_util.h>
+#include <sys/queue.h>
#include <trace.h>
#include <util.h>
@@ -42,6 +44,17 @@
static struct i2c_handle_s *i2c_pmic_handle;
static uint32_t pmic_i2c_addr;
+struct pmic_it_handle_s {
+ uint8_t pmic_reg;
+ uint8_t pmic_bit;
+ uint8_t notif_id;
+
+ SLIST_ENTRY(pmic_it_handle_s) link;
+};
+
+static SLIST_HEAD(pmic_it_handle_head, pmic_it_handle_s) pmic_it_handle_list =
+ SLIST_HEAD_INITIALIZER(pmic_it_handle_list);
+
/* CPU voltage supplier if found */
static char cpu_supply_name[PMIC_REGU_SUPPLY_NAME_LEN];
@@ -508,11 +521,10 @@ static void register_non_secure_pmic(void)
}
}
-static enum itr_return stpmic1_irq_handler(struct itr_handler *handler)
+static enum itr_return stpmic1_irq_handler(struct itr_handler *handler __unused)
{
uint8_t read_val = 0U;
unsigned int i = 0U;
- uint32_t *it_id = handler->data;
FMSG("Stpmic1 irq handler");
@@ -523,16 +535,22 @@ static enum itr_return stpmic1_irq_handler(struct itr_handler *handler)
panic();
if (read_val) {
+ struct pmic_it_handle_s *prv = NULL;
+
FMSG("Stpmic1 irq pending %u: %#"PRIx8, i, read_val);
if (stpmic1_register_write(ITCLEARLATCH1_REG + i,
read_val))
panic();
- /* forward falling interrupt to non-secure */
- if (i == 0 && (read_val & BIT(IT_PONKEY_F)))
- if (it_id)
- notif_send_it(*it_id);
+ SLIST_FOREACH(prv, &pmic_it_handle_list, link)
+ if ((prv->pmic_reg == ITCLEARMASK1_REG + i) &&
+ (read_val & BIT(prv->pmic_bit))) {
+ FMSG("STPMIC1 send notif %u",
+ prv->notif_id);
+
+ notif_send_it(prv->notif_id);
+ }
}
}
@@ -587,57 +605,104 @@ static void initialize_pmic(const void *fdt, int pmic_node)
stm32mp_put_pmic();
}
-static TEE_Result stm32_pmic_probe(const void *fdt, int node,
- const void *compat_data __unused)
+static TEE_Result stm32_pmic_init_it(const void *fdt, int node)
{
- TEE_Result res = TEE_SUCCESS;
- const fdt32_t *cuint = NULL;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ const uint32_t *notif_ids = NULL;
+ int nb_notif = 0;
+ size_t pwr_it = 0;
struct itr_handler *hdl = NULL;
- size_t it = 0;
- uint32_t *it_id = NULL;
+ const fdt32_t *cuint = NULL;
- res = i2c_dt_get_by_subnode(fdt, node, &i2c_pmic_handle);
- if (res)
- return res;
+ cuint = fdt_getprop(fdt, node, "st,wakeup-pin-number", NULL);
+ if (!cuint) {
+ IMSG("Missing wake-up pin description");
+ return TEE_SUCCESS;
+ }
- initialize_pmic(fdt, node);
+ pwr_it = fdt32_to_cpu(*cuint) - 1U;
- if (IS_ENABLED(CFG_STM32MP13)) {
- cuint = fdt_getprop(fdt, node, "st,wakeup-pin-number", NULL);
- if (!cuint) {
- IMSG("Missing wake-up pin description");
- return TEE_SUCCESS;
- }
+ notif_ids = fdt_getprop(fdt, node, "st,notif-it-id", &nb_notif);
+ if (!notif_ids)
+ return TEE_ERROR_ITEM_NOT_FOUND;
- it = fdt32_to_cpu(*cuint) - 1U;
+ if (nb_notif > 0) {
+ struct pmic_it_handle_s *prv = NULL;
+ unsigned int i = 0;
+ const uint32_t *pmic_its = NULL;
+ int nb_it = 0;
- cuint = fdt_getprop(fdt, node, "st,notif-it-id", NULL);
- if (cuint) {
- it_id = calloc(1, sizeof(it_id));
- if (!it_id)
- return TEE_ERROR_OUT_OF_MEMORY;
+ pmic_its = fdt_getprop(fdt, node, "st,pmic-it-id", &nb_it);
+ if (!pmic_its)
+ return TEE_ERROR_ITEM_NOT_FOUND;
- *it_id = fdt32_to_cpu(*cuint);
- }
+ if (nb_it != nb_notif)
+ panic("st,notif-it-id incorrect description");
- res = stm32mp1_pwr_itr_alloc_add(it, stpmic1_irq_handler,
- PWR_WKUP_FLAG_FALLING |
- PWR_WKUP_FLAG_THREADED,
- it_id, &hdl);
- if (res)
- panic("pmic: Couldn't allocate itr");
+ for (i = 0; i < (nb_notif / sizeof(uint32_t)); i++) {
+ uint8_t val = 0;
+ uint8_t pmic_it = 0;
- stm32mp1_pwr_itr_enable(hdl->it);
+ prv = calloc(1, sizeof(*prv));
+ if (!prv)
+ panic("pmic: Couldn't allocate pmic it");
- /* Enable ponkey irq */
- stm32mp_get_pmic();
- if (stpmic1_register_write(ITCLEARMASK1_REG,
- BIT(IT_PONKEY_F) | BIT(IT_PONKEY_R)))
- panic();
+ pmic_it = fdt32_to_cpu(pmic_its[i]);
+
+ assert(pmic_it <= IT_SWIN_R);
+
+ prv->pmic_reg = ITCLEARMASK1_REG + pmic_it / U(8);
+ prv->pmic_bit = pmic_it % U(8);
+ prv->notif_id = fdt32_to_cpu(notif_ids[i]);
+
+ SLIST_INSERT_HEAD(&pmic_it_handle_list, prv, link);
+
+ stm32mp_get_pmic();
- stm32mp_put_pmic();
+ /* Enable requested interrupt */
+ if (stpmic1_register_read(prv->pmic_reg, &val))
+ panic();
+
+ val |= BIT(prv->pmic_bit);
+
+ if (stpmic1_register_write(prv->pmic_reg, val))
+ panic();
+
+ stm32mp_put_pmic();
+ }
+
+ SLIST_FOREACH(prv, &pmic_it_handle_list, link) {
+ FMSG("STPMIC1 forwards irq reg:%u bit:%u as notif:%u",
+ prv->pmic_reg, prv->pmic_bit, prv->notif_id);
+ }
}
+ res = stm32mp1_pwr_itr_alloc_add(pwr_it, stpmic1_irq_handler,
+ PWR_WKUP_FLAG_FALLING |
+ PWR_WKUP_FLAG_THREADED,
+ NULL, &hdl);
+ if (res)
+ panic("pmic: Couldn't allocate itr");
+
+ stm32mp1_pwr_itr_enable(hdl->it);
+
+ return res;
+}
+
+static TEE_Result stm32_pmic_probe(const void *fdt, int node,
+ const void *compat_data __unused)
+{
+ TEE_Result res = TEE_SUCCESS;
+
+ res = i2c_dt_get_by_subnode(fdt, node, &i2c_pmic_handle);
+ if (res)
+ return res;
+
+ initialize_pmic(fdt, node);
+
+ if (IS_ENABLED(CFG_STM32MP13))
+ res = stm32_pmic_init_it(fdt, node);
+
return res;
}
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr_irq.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr_irq.c
index 0913e9151..ca2761a81 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr_irq.c
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr_irq.c
@@ -13,6 +13,7 @@
#include <kernel/dt.h>
#include <kernel/notif.h>
#include <kernel/panic.h>
+#include <kernel/spinlock.h>
#include <libfdt.h>
#include <platform_config.h>
#include <stm32_util.h>
@@ -47,6 +48,7 @@ struct stm32_pwr_data {
struct itr_handler *gic_hdl;
bool threaded[PWR_NB_WAKEUPPINS];
bool pending[PWR_NB_WAKEUPPINS];
+ unsigned int spinlock;
};
static struct stm32_pwr_data *pwr_data;
@@ -148,6 +150,7 @@ static TEE_Result
stm32_pwr_irq_set_pull_config(size_t it, enum wkup_pull_setting config)
{
struct stm32_pwr_data *priv = pwr_data;
+ uint32_t exceptions = 0;
VERBOSE_PWR("irq:%zu pull config:0%#"PRIx32, it, config);
@@ -156,29 +159,59 @@ stm32_pwr_irq_set_pull_config(size_t it, enum wkup_pull_setting config)
return TEE_ERROR_GENERIC;
}
+ exceptions = cpu_spin_lock_xsave(&priv->spinlock);
+
io_mask32(priv->base + WKUPCR,
(config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + it * 2),
(WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + it * 2));
+ cpu_spin_unlock_xrestore(&priv->spinlock, exceptions);
+
return TEE_SUCCESS;
}
-static TEE_Result
-stm32_pwr_irq_set_trig(size_t it, enum pwr_wkup_flags trig)
+static void stm32mp1_pwr_itr_enable_nolock(size_t it)
+{
+ struct stm32_pwr_data *priv = pwr_data;
+
+ VERBOSE_PWR("Pwr irq enable");
+
+ if (IS_ENABLED(CFG_STM32_EXTI))
+ stm32_exti_enable_wake(PWR_EXTI_WKUP1 + it);
+
+ io_setbits32(priv->base + MPUWKUPENR, BIT(it));
+}
+
+static void stm32mp1_pwr_itr_disable_nolock(size_t it)
+{
+ struct stm32_pwr_data *priv = pwr_data;
+
+ VERBOSE_PWR("Pwr irq disable");
+
+ io_clrbits32(priv->base + MPUWKUPENR, BIT(it));
+
+ if (IS_ENABLED(CFG_STM32_EXTI))
+ stm32_exti_disable_wake(PWR_EXTI_WKUP1 + it);
+}
+
+static TEE_Result stm32_pwr_irq_set_trig(size_t it, enum pwr_wkup_flags trig)
{
struct stm32_pwr_data *priv = pwr_data;
+ uint32_t exceptions = 0;
uint32_t wkupcr = 0;
int en = 0;
VERBOSE_PWR("irq:%zu trig:%#"PRIx32, it, trig);
+ exceptions = cpu_spin_lock_xsave(&priv->spinlock);
+
en = io_read32(priv->base + MPUWKUPENR) & BIT(it);
/*
* Reference manual request to disable the wakeup pin while
- * changing the edge detection setting
+ * changing the edge detection setting.
*/
if (en)
- stm32mp1_pwr_itr_disable(it);
+ stm32mp1_pwr_itr_disable_nolock(it);
wkupcr = io_read32(priv->base + WKUPCR);
switch (trig) {
@@ -195,7 +228,9 @@ stm32_pwr_irq_set_trig(size_t it, enum pwr_wkup_flags trig)
io_write32(priv->base + WKUPCR, wkupcr);
if (en)
- stm32mp1_pwr_itr_enable(it);
+ stm32mp1_pwr_itr_enable_nolock(it);
+
+ cpu_spin_unlock_xrestore(&priv->spinlock, exceptions);
return TEE_SUCCESS;
}
@@ -203,25 +238,21 @@ stm32_pwr_irq_set_trig(size_t it, enum pwr_wkup_flags trig)
void stm32mp1_pwr_itr_enable(size_t it)
{
struct stm32_pwr_data *priv = pwr_data;
+ uint32_t exceptions = 0;
- VERBOSE_PWR("Pwr irq enable");
-
- if (IS_ENABLED(CFG_STM32_EXTI))
- stm32_exti_enable_wake(PWR_EXTI_WKUP1 + it);
-
- io_setbits32(priv->base + MPUWKUPENR, BIT(it));
+ exceptions = cpu_spin_lock_xsave(&priv->spinlock);
+ stm32mp1_pwr_itr_enable_nolock(it);
+ cpu_spin_unlock_xrestore(&priv->spinlock, exceptions);
}
void stm32mp1_pwr_itr_disable(size_t it)
{
struct stm32_pwr_data *priv = pwr_data;
+ uint32_t exceptions = 0;
- VERBOSE_PWR("Pwr irq disable");
-
- io_clrbits32(priv->base + MPUWKUPENR, BIT(it));
-
- if (IS_ENABLED(CFG_STM32_EXTI))
- stm32_exti_disable_wake(PWR_EXTI_WKUP1 + it);
+ exceptions = cpu_spin_lock_xsave(&priv->spinlock);
+ stm32mp1_pwr_itr_disable_nolock(it);
+ cpu_spin_unlock_xrestore(&priv->spinlock, exceptions);
}
static TEE_Result stm32mp1_pwr_irt_add(struct itr_handler *hdl)
@@ -231,7 +262,9 @@ static TEE_Result stm32mp1_pwr_irt_add(struct itr_handler *hdl)
struct stm32_pinctrl_list pinctrl_list = { };
struct stm32_pinctrl pin = { };
struct stm32_pinctrl *pinctrl = NULL;
+ uint32_t exceptions = 0;
unsigned int i = 0;
+ bool itr_free = false;
VERBOSE_PWR("Pwr IRQ add");
@@ -241,10 +274,15 @@ static TEE_Result stm32mp1_pwr_irt_add(struct itr_handler *hdl)
}
assert(it >= PWR_WKUP_PIN1 && it < PWR_NB_WAKEUPPINS);
- /* check IRQ not already in use */
- assert(!priv->hdl[it]);
- priv->hdl[it] = hdl;
+ /* Use PWR lock to ensure consistent interrupt registering */
+ exceptions = cpu_spin_lock_xsave(&priv->spinlock);
+ itr_free = !priv->hdl[it];
+ if (itr_free)
+ priv->hdl[it] = hdl;
+ cpu_spin_unlock_xrestore(&priv->spinlock, exceptions);
+ if (!itr_free)
+ return TEE_ERROR_GENERIC;
if (hdl->flags & PWR_WKUP_FLAG_THREADED)
priv->threaded[it] = true;
diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c
index 2e9f7a699..3ae327ee5 100644
--- a/core/arch/arm/plat-stm32mp1/main.c
+++ b/core/arch/arm/plat-stm32mp1/main.c
@@ -165,9 +165,9 @@ static TEE_Result init_console_from_dt(void)
/* Replace early console with the new one */
console_flush();
console_data = *pd;
- free(pd);
register_serial_console(&console_data.chip);
IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-");
+ free(pd);
return TEE_SUCCESS;
}
@@ -727,7 +727,7 @@ static TEE_Result stm32_configure_tamp(void)
return TEE_SUCCESS;
}
-driver_init_late(stm32_configure_tamp);
+service_init(stm32_configure_tamp);
#endif
#ifdef CFG_STM32_HSE_MONITORING
diff --git a/core/arch/arm/plat-stm32mp1/pm/context.c b/core/arch/arm/plat-stm32mp1/pm/context.c
index c9d26ee37..7e08bc0a2 100644
--- a/core/arch/arm/plat-stm32mp1/pm/context.c
+++ b/core/arch/arm/plat-stm32mp1/pm/context.c
@@ -213,7 +213,7 @@ static void __maybe_unused print_ccm_decryption_duration(void)
((unsigned long long)ctx->stgen_cnt * 1000) /
io_read32(stgen + CNTFID_OFFSET));
- clk_enable(pm_clocks.bkpsram);
+ clk_disable(pm_clocks.bkpsram);
}
#else
static void __maybe_unused print_ccm_decryption_duration(void)
@@ -582,15 +582,17 @@ TEE_Result stm32mp_pm_call_bl2_lp_entry(unsigned int soc_mode)
dcache_op_all(DCACHE_OP_CLEAN_INV);
+ /* Disable Cache & MMU before calling low_power section */
+ write_sctlr(read_sctlr() & ~(SCTLR_C | SCTLR_M));
+
dsb();
+ isb();
- /* Disable MMU before calling low_power section */
- write_sctlr(read_sctlr() & ~SCTLR_M);
(*stm32_pwr_down_wfi)(true, soc_mode);
- /* Enable MMU */
- write_sctlr(read_sctlr() | SCTLR_M);
+ /* Enable Cache & MMU */
+ write_sctlr(read_sctlr() | SCTLR_C | SCTLR_M);
clk_disable(pm_clocks.bkpsram);
diff --git a/core/arch/arm/plat-stm32mp1/pm/low_power.c b/core/arch/arm/plat-stm32mp1/pm/low_power.c
index cbc5fa151..653c3dfb7 100644
--- a/core/arch/arm/plat-stm32mp1/pm/low_power.c
+++ b/core/arch/arm/plat-stm32mp1/pm/low_power.c
@@ -292,13 +292,6 @@ void stm32_enter_cstop(uint32_t mode)
io_clrsetbits32(pwr_base + PWR_CR3_OFF, PWR_CR3_POPL_MASK,
20U << PWR_CR3_POPL_SHIFT);
- /* Keep backup RAM content in standby */
- io_setbits32(pwr_base + PWR_CR2_OFF, PWR_CR2_BREN);
-
- // TODO add a timeout?
- while (!(io_read32(pwr_base + PWR_CR2_OFF) & PWR_CR2_BRRDY))
- ;
-
#ifndef CFG_STM32MP13
if (stm32mp1_is_retram_during_standby()) {
/* Keep retention in standby */
@@ -344,9 +337,6 @@ void stm32_exit_cstop(void)
dsb();
isb();
- /* Disable retention and backup RAM content after stop */
- io_clrbits32(stm32_pwr_base() + PWR_CR2_OFF, PWR_CR2_BREN);
-
#ifndef CFG_STM32MP13
/* Disable retention and backup RAM content after stop */
io_clrbits32(stm32_pwr_base() + PWR_CR2_OFF, PWR_CR2_RREN);
@@ -525,6 +515,11 @@ static TEE_Result init_low_power(void)
RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1);
#endif
+ /* Keep backup RAM content in standby */
+ io_setbits32(pwr_base + PWR_CR2_OFF, PWR_CR2_BREN);
+ while (!(io_read32(pwr_base + PWR_CR2_OFF) & PWR_CR2_BRRDY))
+ ;
+
return TEE_SUCCESS;
}
driver_init_late(init_low_power);
diff --git a/core/drivers/crypto/stm32/stm32_saes.c b/core/drivers/crypto/stm32/stm32_saes.c
index 9453d0d52..d8495a16e 100644
--- a/core/drivers/crypto/stm32/stm32_saes.c
+++ b/core/drivers/crypto/stm32/stm32_saes.c
@@ -1337,6 +1337,13 @@ TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
struct stm32_saes_context ctx = { };
uint8_t separator = 0;
+ // Check if driver is probed
+ if (saes_pdata.base.pa == 0) {
+ DMSG("Use __huk_subkey_derive instead of SAES IP features");
+ return __huk_subkey_derive(usage, const_data, const_data_len,
+ subkey, subkey_len);
+ }
+
input = malloc(const_data_len + sizeof(separator) + sizeof(usage) +
sizeof(subkey_bitlen) + AES_BLOCK_SIZE);
if (!input)
diff --git a/core/drivers/regulator/core.c b/core/drivers/regulator/core.c
index d4dc3751d..7ef58b268 100644
--- a/core/drivers/regulator/core.c
+++ b/core/drivers/regulator/core.c
@@ -575,6 +575,11 @@ static TEE_Result parse_properties(const void *fdt, struct rdev *rdev, int node)
}
rdev->reg_name = fdt_getprop(fdt, node, "regulator-name", NULL);
+ if (rdev->reg_name) {
+ rdev->reg_name = strdup(rdev->reg_name);
+ if (!rdev->reg_name)
+ panic();
+ }
return TEE_SUCCESS;
}
diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c
index 49e4fad50..fba4abe7e 100644
--- a/core/drivers/stm32_iwdg.c
+++ b/core/drivers/stm32_iwdg.c
@@ -35,6 +35,7 @@
#define IWDG_EWCR_OFFSET U(0x14)
/* Registers values */
+#define IWDG_KR_WPROT_KEY U(0x0000)
#define IWDG_KR_ACCESS_KEY U(0x5555)
#define IWDG_KR_RELOAD_KEY U(0xAAAA)
#define IWDG_KR_START_KEY U(0xCCCC)
@@ -45,6 +46,7 @@
#define IWDG_RLR_RL_MASK GENMASK_32(11, 0)
#define IWDG_SR_EWU BIT(3)
+#define IWDG_SR_EWIF BIT(14)
#define IWDG_EWCR_EWIE BIT(15)
#define IWDG_EWCR_EWIC BIT(14)
@@ -88,10 +90,22 @@ static enum itr_return stm32_iwdg_it_handler(struct itr_handler *handler)
stm32mp_dump_core_registers(true);
- iwdg_refresh(iwdg);
-
clk_enable(iwdg->pdata.clock);
+ /* Check for spurious interrupt */
+ if (!(io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_EWIF)) {
+ clk_disable(iwdg->pdata.clock);
+ return ITRR_NONE;
+ }
+
+ /*
+ * Writing IWDG_EWCR_EWIT triggers a watchdog refresh.
+ * To prevent the watchdog refresh, write-protect all the registers;
+ * this makes read-only all IWDG_EWCR fields except IWDG_EWCR_EWIC.
+ */
+ io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_WPROT_KEY);
+
+ /* Disable early interrupt */
io_setbits32(iwdg_base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIC);
clk_disable(iwdg->pdata.clock);
diff --git a/core/drivers/stm32_rng.c b/core/drivers/stm32_rng.c
index ef5862308..363aeee00 100644
--- a/core/drivers/stm32_rng.c
+++ b/core/drivers/stm32_rng.c
@@ -140,9 +140,19 @@ static TEE_Result stm32_rng_read_available(struct stm32_rng_device *dev,
/* RNG is ready: read up to 4 32bit words */
while (size) {
- uint32_t data32 = io_read32(base + RNG_DR);
+ uint32_t data32 = 0;
size_t sz = MIN(size, sizeof(uint32_t));
+ if (!(io_read32(base + RNG_SR) & RNG_SR_DRDY))
+ return TEE_ERROR_NO_DATA;
+
+ data32 = io_read32(base + RNG_DR);
+ /* Late seed error case: DR being 0 is an error status */
+ if (!data32) {
+ conceal_seed_error(dev);
+ return TEE_ERROR_NO_DATA;
+ }
+
memcpy(buf, &data32, sz);
buf += sz;
size -= sz;
diff --git a/core/drivers/stm32_uart.c b/core/drivers/stm32_uart.c
index 5105b14bc..1ffc99117 100644
--- a/core/drivers/stm32_uart.c
+++ b/core/drivers/stm32_uart.c
@@ -38,12 +38,12 @@
* Bit 5 RXNE: Read data register not empty/RXFIFO not empty
* Bit 6 TC: Transmission complete
* Bit 7 TXE/TXFNF: Transmit data register empty/TXFIFO not full
- * Bit 27 TXFE: TXFIFO threshold reached
+ * Bit 23 TXFE: TXFIFO empty
*/
#define USART_ISR_RXNE_RXFNE BIT(5)
#define USART_ISR_TC BIT(6)
#define USART_ISR_TXE_TXFNF BIT(7)
-#define USART_ISR_TXFE BIT(27)
+#define USART_ISR_TXFE BIT(23)
static vaddr_t loc_chip_to_base(struct serial_chip *chip)
{
diff --git a/core/include/drivers/stpmic1.h b/core/include/drivers/stpmic1.h
index 5fe48232f..b293c846f 100644
--- a/core/include/drivers/stpmic1.h
+++ b/core/include/drivers/stpmic1.h
@@ -171,41 +171,6 @@
#define USBSW_OTG_SWITCH_ENABLED_POS 1
#define BOOST_ENABLED_POS 0
-/* IRQ definitions */
-#define IT_PONKEY_F 0
-#define IT_PONKEY_R 1
-#define IT_WAKEUP_F 2
-#define IT_WAKEUP_R 3
-#define IT_VBUS_OTG_F 4
-#define IT_VBUS_OTG_R 5
-#define IT_SWOUT_F 6
-#define IT_SWOUT_R 7
-
-#define IT_CURLIM_BUCK1 0
-#define IT_CURLIM_BUCK2 1
-#define IT_CURLIM_BUCK3 2
-#define IT_CURLIM_BUCK4 3
-#define IT_OCP_OTG 4
-#define IT_OCP_SWOUT 5
-#define IT_OCP_BOOST 6
-#define IT_OVP_BOOST 7
-
-#define IT_CURLIM_LDO1 0
-#define IT_CURLIM_LDO2 1
-#define IT_CURLIM_LDO3 2
-#define IT_CURLIM_LDO4 3
-#define IT_CURLIM_LDO5 4
-#define IT_CURLIM_LDO6 5
-#define IT_SHORT_SWOTG 6
-#define IT_SHORT_SWOUT 7
-
-#define IT_TWARN_F 0
-#define IT_TWARN_R 1
-#define IT_VINLOW_F 2
-#define IT_VINLOW_R 3
-#define IT_SWIN_F 4
-#define IT_SWIN_R 5
-
/*
* Bind SPMIC1 device driver with a specific I2C bus instance
* @i2c_handle: target I2C instance to use
diff --git a/core/include/kernel/huk_subkey.h b/core/include/kernel/huk_subkey.h
index 59bcf2773..a6a18e953 100644
--- a/core/include/kernel/huk_subkey.h
+++ b/core/include/kernel/huk_subkey.h
@@ -49,12 +49,17 @@ enum huk_subkey_usage {
*
* Returns a subkey derived from the hardware unique key. Given the same
* input the same subkey is returned each time.
+ * Function huk_subkey_derive is __weak to allow platform custom implementation.
+ * __huk_subkey_derive implements the default behavior of huk_subkey_derive.
*
* Return TEE_SUCCES on success or an error code on failure.
*/
TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
const void *const_data, size_t const_data_len,
uint8_t *subkey, size_t subkey_len);
+TEE_Result __huk_subkey_derive(enum huk_subkey_usage usage,
+ const void *const_data, size_t const_data_len,
+ uint8_t *subkey, size_t subkey_len);
#endif /*__KERNEL_HUK_SUBKEY_H*/
diff --git a/core/kernel/huk_subkey.c b/core/kernel/huk_subkey.c
index 5481120b6..3db2cfe5f 100644
--- a/core/kernel/huk_subkey.c
+++ b/core/kernel/huk_subkey.c
@@ -58,10 +58,9 @@ static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage)
}
#endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/
-__weak
-TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
- const void *const_data, size_t const_data_len,
- uint8_t *subkey, size_t subkey_len)
+TEE_Result __huk_subkey_derive(enum huk_subkey_usage usage,
+ const void *const_data, size_t const_data_len,
+ uint8_t *subkey, size_t subkey_len)
{
void *ctx = NULL;
struct tee_hw_unique_key huk = { };
@@ -106,3 +105,12 @@ out:
crypto_mac_free_ctx(ctx);
return res;
}
+
+__weak
+TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
+ const void *const_data, size_t const_data_len,
+ uint8_t *subkey, size_t subkey_len)
+{
+ return __huk_subkey_derive(usage, const_data, const_data_len, subkey,
+ subkey_len);
+}
diff --git a/documentation/devicetree/bindings/mfd/st,stpmic1.yaml b/documentation/devicetree/bindings/mfd/st,stpmic1.yaml
index 344623f1f..7d97a7082 100644
--- a/documentation/devicetree/bindings/mfd/st,stpmic1.yaml
+++ b/documentation/devicetree/bindings/mfd/st,stpmic1.yaml
@@ -262,6 +262,51 @@ properties:
minItems: 1
maxItems: 1
+ st,pmic-it-id:
+ description: PMIC interruptions id to forward to the non-secure world
+ in the form of OPTEE notifications described by st,notif-it-id.
+ IT_PONKEY_F = 0
+ IT_PONKEY_R = 1
+ IT_WAKEUP_F = 2
+ IT_WAKEUP_R = 3
+ IT_VBUS_OTG_F = 4
+ IT_VBUS_OTG_R = 5
+ IT_SWOUT_F = 6
+ IT_SWOUT_R = 7
+ IT_CURLIM_BUCK1 = 8
+ IT_CURLIM_BUCK2 = 9
+ IT_CURLIM_BUCK3 = 10
+ IT_CURLIM_BUCK4 = 11
+ IT_OCP_OTG = 12
+ IT_OCP_SWOUT = 13
+ IT_OCP_BOOST = 14
+ IT_OVP_BOOST = 15
+ IT_CURLIM_LDO1 = 16
+ IT_CURLIM_LDO2 = 17
+ IT_CURLIM_LDO3 = 18
+ IT_CURLIM_LDO4 = 19
+ IT_CURLIM_LDO5 = 20
+ IT_CURLIM_LDO6 = 21
+ IT_SHORT_SWOTG = 22
+ IT_SHORT_SWOUT = 23
+ IT_TWARN_F = 24
+ IT_TWARN_R = 25
+ IT_VINLOW_F = 26
+ IT_VINLOW_R = 27
+ IT_SWIN_F = 30
+ IT_SWIN_R = 31
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minItems: 1
+ maxItems: 32
+
+ st,notif-it-id:
+ description: OPTEE notification numbers to send to the non-secure world.
+ One notification is needed for each interruption listed by st,pmic-it-id,
+ so the number of notifications must be eaqual to the number of interrupts.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minItems: 1
+ maxItems: 32
+
additionalProperties: false
required:
@@ -271,6 +316,10 @@ required:
- "#interrupt-cells"
- interrupt-controller
+dependencies:
+ st,notif-it-id: [ 'st,pmic-it-id' ]
+ st,pmic-it-id: [ 'st,notif-it-id' ]
+
examples:
- |
#include <dt-bindings/mfd/st,stpmic1.h>
@@ -289,6 +338,8 @@ examples:
#interrupt-cells = <2>;
st,wakeup-pin-number = <1>;
+ st,pmic-it-id = <IT_PONKEY_F IT_PONKEY_R>;
+ st,notif-it-id = <0 2>;
onkey {
compatible = "st,stpmic1-onkey";
--
2.25.1