[PATCH 2/3] pinctrl: pinctrl_stm32: prevent the use of the secure protected pins

Patrice Chotard patrice.chotard at foss.st.com
Thu Feb 5 09:07:50 CET 2026


From: Fabien Dessenne <fabien.dessenne at foss.st.com>

The hardware denies any access from the U-Boot non-secure world to the
secure-protected pins. Hence, prevent any driver to configure such a pin.
Identify the secure pins with "NO ACCESS" through the 'pinmux status -a'
command.
Use a driver data structure to identify which hardware versions support
this feature.

Signed-off-by: Fabien Dessenne <fabien.dessenne at foss.st.com>
Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 drivers/pinctrl/pinctrl_stm32.c | 83 +++++++++++++++++++++++++++++++++++------
 1 file changed, 71 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index fbf0271f08a..1758f9a909c 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -11,6 +11,7 @@
 #include <malloc.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
+#include <dm/device-internal.h>
 #include <dm/device_compat.h>
 #include <dm/lists.h>
 #include <dm/pinctrl.h>
@@ -27,6 +28,7 @@
 #define PUPD_MASK			3
 #define OTYPE_MSK			1
 #define AFR_MASK			0xF
+#define SECCFG_MSK			1
 
 struct stm32_pinctrl_priv {
 	struct hwspinlock hws;
@@ -39,7 +41,12 @@ struct stm32_gpio_bank {
 	struct list_head list;
 };
 
+struct stm32_pinctrl_data {
+	bool secure_control;
+};
+
 #ifndef CONFIG_XPL_BUILD
+static int stm32_pinctrl_get_access(struct udevice *gpio_dev, unsigned int gpio_idx);
 
 static char pin_name[PINNAME_SIZE];
 static const char * const pinmux_mode[GPIOF_COUNT] = {
@@ -216,6 +223,12 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
 	if (!gpio_dev)
 		return -ENODEV;
 
+	/* Check access protection */
+	if (stm32_pinctrl_get_access(gpio_dev, gpio_idx)) {
+		snprintf(buf, size, "NO ACCESS");
+		return 0;
+	}
+
 	mode = gpio_get_raw_function(gpio_dev, gpio_idx, &label);
 	dev_dbg(dev, "selector = %d gpio_idx = %d mode = %d\n",
 		selector, gpio_idx, mode);
@@ -252,6 +265,20 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
 
 #endif
 
+static int stm32_pinctrl_get_access(struct udevice *gpio_dev, unsigned int gpio_idx)
+{
+	struct stm32_gpio_priv *priv = dev_get_priv(gpio_dev);
+	struct stm32_gpio_regs *regs = priv->regs;
+	ulong drv_data = dev_get_driver_data(gpio_dev);
+
+	/* Deny request access if IO is secured */
+	if ((drv_data & STM32_GPIO_FLAG_SEC_CTRL) &&
+	    ((readl(&regs->seccfgr) >> gpio_idx) & SECCFG_MSK))
+		return -EACCES;
+
+	return 0;
+}
+
 static int stm32_pinctrl_probe(struct udevice *dev)
 {
 	struct stm32_pinctrl_priv *priv = dev_get_priv(dev);
@@ -279,6 +306,14 @@ static int stm32_gpio_config(ofnode node,
 	int ret;
 	u32 index;
 
+	/* Check access protection */
+	ret = stm32_pinctrl_get_access(desc->dev, desc->offset);
+	if (ret) {
+		dev_err(desc->dev, "Failed to get secure IO %s %d @ %p\n",
+			uc_priv->bank_name, desc->offset, regs);
+		return ret;
+	}
+
 	if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
 	    ctl->pupd > 2 || ctl->speed > 3)
 		return -EINVAL;
@@ -414,8 +449,25 @@ static int stm32_pinctrl_bind(struct udevice *dev)
 {
 	ofnode node;
 	const char *name;
+	struct driver *drv;
+	const struct stm32_pinctrl_data *drv_data;
+	ulong gpio_data = 0;
 	int ret;
 
+	drv = lists_driver_lookup_name("gpio_stm32");
+	if (!drv) {
+		debug("Cannot find driver 'gpio_stm32'\n");
+		return -ENOENT;
+	}
+
+	drv_data = (const struct stm32_pinctrl_data *)dev_get_driver_data(dev);
+	if (!drv_data) {
+		debug("Cannot find driver data\n");
+		return -EINVAL;
+	}
+	if (drv_data->secure_control)
+		gpio_data = STM32_GPIO_FLAG_SEC_CTRL;
+
 	dev_for_each_subnode(node, dev) {
 		dev_dbg(dev, "bind %s\n", ofnode_get_name(node));
 
@@ -431,8 +483,7 @@ static int stm32_pinctrl_bind(struct udevice *dev)
 			return -EINVAL;
 
 		/* Bind each gpio node */
-		ret = device_bind_driver_to_node(dev, "gpio_stm32",
-						 name, node, NULL);
+		ret = device_bind_with_driver_data(dev, drv, name, gpio_data, node, NULL);
 		if (ret)
 			return ret;
 
@@ -495,17 +546,25 @@ static struct pinctrl_ops stm32_pinctrl_ops = {
 #endif
 };
 
+static const struct stm32_pinctrl_data stm32_pinctrl_no_sec = {
+	.secure_control = false,
+};
+
+static const struct stm32_pinctrl_data stm32_pinctrl_with_sec = {
+	.secure_control = true,
+};
+
 static const struct udevice_id stm32_pinctrl_ids[] = {
-	{ .compatible = "st,stm32f429-pinctrl" },
-	{ .compatible = "st,stm32f469-pinctrl" },
-	{ .compatible = "st,stm32f746-pinctrl" },
-	{ .compatible = "st,stm32f769-pinctrl" },
-	{ .compatible = "st,stm32h743-pinctrl" },
-	{ .compatible = "st,stm32mp157-pinctrl" },
-	{ .compatible = "st,stm32mp157-z-pinctrl" },
-	{ .compatible = "st,stm32mp135-pinctrl" },
-	{ .compatible = "st,stm32mp257-pinctrl" },
-	{ .compatible = "st,stm32mp257-z-pinctrl" },
+	{ .compatible = "st,stm32f429-pinctrl",    .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32f469-pinctrl",    .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32f746-pinctrl",    .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32f769-pinctrl",    .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32h743-pinctrl",    .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32mp157-pinctrl",   .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32mp157-z-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec },
+	{ .compatible = "st,stm32mp135-pinctrl",   .data = (ulong)&stm32_pinctrl_with_sec },
+	{ .compatible = "st,stm32mp257-pinctrl",   .data = (ulong)&stm32_pinctrl_with_sec },
+	{ .compatible = "st,stm32mp257-z-pinctrl", .data = (ulong)&stm32_pinctrl_with_sec },
 	{ }
 };
 

-- 
2.43.0



More information about the U-Boot mailing list