Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of power management for stm32 SAES peripheral #6778

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion core/arch/arm/dts/stm32mp13xc.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
compatible = "st,stm32mp13-saes";
reg = <0x54005000 0x400>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc SAES_K>;
clocks = <&rcc SAES_K>, <&rcc RNG1_K>;
clock-names = "bus", "rng";
resets = <&rcc SAES_R>;
status = "disabled";
};
Expand Down
3 changes: 2 additions & 1 deletion core/arch/arm/dts/stm32mp13xf.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
compatible = "st,stm32mp13-saes";
reg = <0x54005000 0x400>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc SAES_K>;
clocks = <&rcc SAES_K>, <&rcc RNG1_K>;
clock-names = "bus", "rng";
resets = <&rcc SAES_R>;
status = "disabled";
};
Expand Down
8 changes: 8 additions & 0 deletions core/arch/arm/plat-stm32mp1/conf.mk
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ $(call force,CFG_STM32_I2C,y)
$(call force,CFG_STM32_GPIO,y)
endif

# SAES and CRYP cannot be registered at the same time in the crypto framework.
# If CRYP and SAES are enable on STMP32MP13, disable CRYP for safety purpose
ifeq ($(CFG_STM32MP13),y)
ifeq ($(call cfg-all-enabled, CFG_STM32_CRYP CFG_STM32_SAES), y)
override CFG_STM32_CRYP := n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comment at #6778 (comment).

endif # cfg-all-enabled, CFG_STM32_CRYP CFG_STM32_SAES
endif # CFG_STM32MP13

# If any crypto driver is enabled, enable the crypto-framework layer
ifeq ($(call cfg-one-enabled, CFG_STM32_CRYP CFG_STM32_SAES),y)
$(call force,CFG_STM32_CRYPTO_DRIVER,y)
Expand Down
66 changes: 49 additions & 17 deletions core/drivers/crypto/stm32/stm32_saes.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <kernel/dt.h>
#include <kernel/huk_subkey.h>
#include <kernel/mutex.h>
#include <kernel/pm.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
#include <stdint.h>
Expand Down Expand Up @@ -142,6 +143,7 @@ static struct mutex saes_lock = MUTEX_INITIALIZER;
static struct stm32_saes_platdata {
vaddr_t base;
struct clk *clk;
struct clk *clk_rng;
struct rstctrl *reset;
} saes_pdata;

Expand Down Expand Up @@ -1363,10 +1365,6 @@ static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata,
dt_saes.reg_size == DT_INFO_INVALID_REG_SIZE)
return TEE_ERROR_BAD_PARAMETERS;

res = clk_dt_get_by_index(fdt, node, 0, &pdata->clk);
if (res != TEE_SUCCESS)
return res;

res = rstctrl_dt_get_by_index(fdt, node, 0, &pdata->reset);
if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
return res;
Expand All @@ -1376,23 +1374,15 @@ static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata,
if (!pdata->base)
panic();

return TEE_SUCCESS;
}

static TEE_Result stm32_saes_probe(const void *fdt, int node,
const void *compat_data __unused)
{
TEE_Result res = TEE_SUCCESS;

assert(!saes_pdata.base);

res = stm32_saes_parse_fdt(&saes_pdata, fdt, node);
res = clk_dt_get_by_name(fdt, node, "bus", &pdata->clk);
if (res)
return res;

if (clk_enable(saes_pdata.clk))
panic();
return clk_dt_get_by_name(fdt, node, "rng", &pdata->clk_rng);
}

static void stm32_saes_reset(void)
{
if (saes_pdata.reset) {
/* External reset of SAES */
if (rstctrl_assert_to(saes_pdata.reset, TIMEOUT_US_1MS))
Expand All @@ -1408,6 +1398,46 @@ static TEE_Result stm32_saes_probe(const void *fdt, int node,
udelay(SAES_RESET_DELAY);
io_clrbits32(saes_pdata.base + _SAES_CR, _SAES_CR_IPRST);
}
}

static TEE_Result stm32_saes_pm(enum pm_op op, uint32_t pm_hint,
const struct pm_callback_handle *hdl __unused)
{
switch (op) {
case PM_OP_SUSPEND:
clk_disable(saes_pdata.clk);
clk_disable(saes_pdata.clk_rng);
tbourgoi marked this conversation as resolved.
Show resolved Hide resolved
return TEE_SUCCESS;

case PM_OP_RESUME:
if (clk_enable(saes_pdata.clk) ||
clk_enable(saes_pdata.clk_rng))
panic();

if (PM_HINT_IS_STATE(pm_hint, CONTEXT))
stm32_saes_reset();

return TEE_SUCCESS;
default:
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking: could move the return TEE_ERROR_NOT_IMPLEMENTED instruction here. Simpler, better IMHO.

}

return TEE_ERROR_NOT_IMPLEMENTED;
}

static TEE_Result stm32_saes_probe(const void *fdt, int node,
const void *compat_data __unused)
{
TEE_Result res = TEE_ERROR_GENERIC;

res = stm32_saes_parse_fdt(&saes_pdata, fdt, node);
if (res)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If SAES probe function is deferred, stm32_saes_parse_fdt() fills saes_pdata.base and the next call of stm32_saes_probe() will panic on the assertion. Before this change, stm32_saes_parse_fdt() used to first get the deferreable resources before getting SAES IOMEM base address. Please preserve this order.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, I think we can remove the assert.
It was to protect if we try to probe 2 instances of SAES but OP-TEE does not support several AES accelerator.
So It will fail during the register in crypto framework

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of removing an assertion that serves a purpose, I suggest you modify your commit "drivers: crypto: stm32_saes: SAES depends on RNG clock":

@@ -1364,10 +1365,14 @@ static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata,
 	    dt_saes.reg_size == DT_INFO_INVALID_REG_SIZE)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	res = clk_dt_get_by_index(fdt, node, 0, &pdata->clk);
+	res = clk_dt_get_by_name(fdt, node, "bus", &pdata->clk);
 	if (res != TEE_SUCCESS)
 		return res;
 
+	return clk_dt_get_by_name(fdt, node, "rng", &pdata->clk_rng);
+	if (res != TEE_SUCCESS)
+		return res;
+
 	res = rstctrl_dt_get_by_index(fdt, node, 0, &pdata->reset);
 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
 		return res;

return res;

if (clk_enable(saes_pdata.clk) || clk_enable(saes_pdata.clk_rng))
panic();

stm32_saes_reset();

if (IS_ENABLED(CFG_CRYPTO_DRV_CIPHER)) {
res = stm32_register_cipher(SAES_IP);
Expand All @@ -1417,6 +1447,8 @@ static TEE_Result stm32_saes_probe(const void *fdt, int node,
}
}

register_pm_core_service_cb(stm32_saes_pm, NULL, "stm32-saes");

return TEE_SUCCESS;
}

Expand Down