summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabriel Fernandez <gabriel.fernandez@foss.st.com>2021-06-17 07:18:14 +0200
committerStephen Boyd <sboyd@kernel.org>2021-06-28 16:09:10 -0700
commit21e743300dd0b9e57425de4a9ba651493b165e03 (patch)
tree9a0283f1d05e9549b1abcbbce0b50f27e68088cf
parent94b7888b67c4e301635bbfdea1403ed0693242fd (diff)
downloadlinux-21e743300dd0b9e57425de4a9ba651493b165e03.tar.gz
linux-21e743300dd0b9e57425de4a9ba651493b165e03.tar.bz2
linux-21e743300dd0b9e57425de4a9ba651493b165e03.zip
clk: stm32mp1: new compatible for secure RCC support
Platform STM32MP1 can be used in configuration where some clock resources cannot be accessed by Linux kernel when executing in non-secure state of the CPU(s). In such configuration, the RCC clock driver must not register clocks it cannot access. They are expected to be registered from another clock driver such as the SCMI clock driver. This change uses specific compatible string "st,stm32mp1-rcc-secure" to specify RCC clock driver configuration where RCC is secure. Signed-off-by: Etienne Carriere <etienne.carriere@foss.st.com> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@foss.st.com> Link: https://lore.kernel.org/r/20210617051814.12018-12-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/Kconfig10
-rw-r--r--drivers/clk/clk-stm32mp1.c101
2 files changed, 110 insertions, 1 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e80918be8e9c..e367a033e121 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -335,6 +335,16 @@ config COMMON_CLK_STM32MP157
help
Support for stm32mp157 SoC family clocks
+config COMMON_CLK_STM32MP157_SCMI
+ bool "stm32mp157 Clock driver with Trusted Firmware"
+ depends on COMMON_CLK_STM32MP157
+ select COMMON_CLK_SCMI
+ select ARM_SCMI_PROTOCOL
+ default y
+ help
+ Support for stm32mp157 SoC family clocks with Trusted Firmware using
+ SCMI protocol.
+
config COMMON_CLK_STM32F
def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746)
help
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 6d3a36f81b2d..6adc625e79cb 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -2056,11 +2056,61 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
_DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)),
};
+static const u32 stm32mp1_clock_secured[] = {
+ CK_HSE,
+ CK_HSI,
+ CK_CSI,
+ CK_LSI,
+ CK_LSE,
+ PLL1,
+ PLL2,
+ PLL1_P,
+ PLL2_P,
+ PLL2_Q,
+ PLL2_R,
+ CK_MPU,
+ CK_AXI,
+ SPI6,
+ I2C4,
+ I2C6,
+ USART1,
+ RTCAPB,
+ TZC1,
+ TZC2,
+ TZPC,
+ IWDG1,
+ BSEC,
+ STGEN,
+ GPIOZ,
+ CRYP1,
+ HASH1,
+ RNG1,
+ BKPSRAM,
+ RNG1_K,
+ STGEN_K,
+ SPI6_K,
+ I2C4_K,
+ I2C6_K,
+ USART1_K,
+ RTC,
+};
+
+static bool stm32_check_security(const struct clock_config *cfg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stm32mp1_clock_secured); i++)
+ if (cfg->id == stm32mp1_clock_secured[i])
+ return true;
+ return false;
+}
+
struct stm32_rcc_match_data {
const struct clock_config *cfg;
unsigned int num;
unsigned int maxbinding;
u32 clear_offset;
+ bool (*check_security)(const struct clock_config *cfg);
};
static struct stm32_rcc_match_data stm32mp1_data = {
@@ -2070,11 +2120,23 @@ static struct stm32_rcc_match_data stm32mp1_data = {
.clear_offset = RCC_CLR,
};
+static struct stm32_rcc_match_data stm32mp1_data_secure = {
+ .cfg = stm32mp1_clock_cfg,
+ .num = ARRAY_SIZE(stm32mp1_clock_cfg),
+ .maxbinding = STM32MP1_LAST_CLK,
+ .clear_offset = RCC_CLR,
+ .check_security = &stm32_check_security
+};
+
static const struct of_device_id stm32mp1_match_data[] = {
{
.compatible = "st,stm32mp1-rcc",
.data = &stm32mp1_data,
},
+ {
+ .compatible = "st,stm32mp1-rcc-secure",
+ .data = &stm32mp1_data_secure,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, stm32mp1_match_data);
@@ -2234,6 +2296,9 @@ static int stm32_rcc_clock_init(struct device *dev, void __iomem *base,
hws[n] = ERR_PTR(-ENOENT);
for (n = 0; n < data->num; n++) {
+ if (data->check_security && data->check_security(&data->cfg[n]))
+ continue;
+
err = stm32_register_hw_clk(dev, clk_data, base, &rlock,
&data->cfg[n]);
if (err) {
@@ -2301,11 +2366,45 @@ out:
return ret;
}
+static int get_clock_deps(struct device *dev)
+{
+ static const char * const clock_deps_name[] = {
+ "hsi", "hse", "csi", "lsi", "lse",
+ };
+ size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name);
+ struct clk **clk_deps;
+ int i;
+
+ clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL);
+ if (!clk_deps)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) {
+ struct clk *clk = of_clk_get_by_name(dev_of_node(dev),
+ clock_deps_name[i]);
+
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT)
+ return PTR_ERR(clk);
+ } else {
+ /* Device gets a reference count on the clock */
+ clk_deps[i] = devm_clk_get(dev, __clk_get_name(clk));
+ clk_put(clk);
+ }
+ }
+
+ return 0;
+}
+
static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ int ret = get_clock_deps(dev);
+
+ if (!ret)
+ ret = stm32mp1_rcc_init(dev);
- return stm32mp1_rcc_init(dev);
+ return ret;
}
static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev)