[U-Boot] [PATCH v5 4/4] pinctrl: stm32: make pinctrl use hwspinlock

Benjamin Gaignard benjamin.gaignard at linaro.org
Tue Nov 27 12:49:53 UTC 2018


Protect configuration registers with a hardware spinlock.

If a hwspinlock is defined in the device-tree node used it
to be sure that none of the others processors on the SoC could
change the configuration at the same time.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard at linaro.org>
Reviewed-by: Simon Glass <sjg at chromium.org>
Reviewed-by: Patrice Chotard <patrice.chotard at st.com>
---
version 5:
²- rebased on top of master branch
 arch/arm/dts/stm32mp157c-ed1.dts |  4 ++++
 drivers/pinctrl/pinctrl_stm32.c  | 27 +++++++++++++++++++++++----
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
index fc277dd7d2..7a9b742d36 100644
--- a/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/dts/stm32mp157c-ed1.dts
@@ -369,6 +369,10 @@
 	status = "okay";
 };
 
+&pinctrl {
+	hwlocks = <&hwspinlock 0>;
+};
+
 &usbphyc_port0 {
 	phy-supply = <&vdd_usb>;
 	vdda1v1-supply = <&reg11>;
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index 6d4117d941..bb63da3739 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -1,6 +1,7 @@
 #include <common.h>
 #include <dm.h>
 #include <dm/pinctrl.h>
+#include <hwspinlock.h>
 #include <asm/arch/gpio.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
@@ -14,8 +15,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #define OTYPE_MSK			1
 #define AFR_MASK			0xF
 
-#ifndef CONFIG_SPL_BUILD
 struct stm32_pinctrl_priv {
+	struct hwspinlock hws;
 	int pinctrl_ngpios;
 	struct list_head gpio_dev;
 };
@@ -25,6 +26,8 @@ struct stm32_gpio_bank {
 	struct list_head list;
 };
 
+#ifndef CONFIG_SPL_BUILD
+
 #define MAX_PIN_PER_BANK		16
 
 static char pin_name[PINNAME_SIZE];
@@ -166,6 +169,8 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
 	return 0;
 }
 
+#endif
+
 int stm32_pinctrl_probe(struct udevice *dev)
 {
 	struct stm32_pinctrl_priv *priv = dev_get_priv(dev);
@@ -198,21 +203,35 @@ int stm32_pinctrl_probe(struct udevice *dev)
 		list_add_tail(&gpio_bank->list, &priv->gpio_dev);
 	}
 
+	/* hwspinlock property is optional, just log the error */
+	ret = hwspinlock_get_by_index(dev, 0, &priv->hws);
+	if (ret)
+		debug("%s: hwspinlock_get_by_index may have failed (%d)\n",
+		      __func__, ret);
+
 	return 0;
 }
-#endif
 
 static int stm32_gpio_config(struct gpio_desc *desc,
 			     const struct stm32_gpio_ctl *ctl)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
 	struct stm32_gpio_regs *regs = priv->regs;
+	struct stm32_pinctrl_priv *ctrl_priv;
+	int ret;
 	u32 index;
 
 	if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
 	    ctl->pupd > 2 || ctl->speed > 3)
 		return -EINVAL;
 
+	ctrl_priv = dev_get_priv(dev_get_parent(desc->dev));
+	ret = hwspinlock_lock_timeout(&ctrl_priv->hws, 10);
+	if (ret == -ETIME) {
+		dev_err(desc->dev, "HWSpinlock timeout\n");
+		return ret;
+	}
+
 	index = (desc->offset & 0x07) * 4;
 	clrsetbits_le32(&regs->afr[desc->offset >> 3], AFR_MASK << index,
 			ctl->af << index);
@@ -227,6 +246,8 @@ static int stm32_gpio_config(struct gpio_desc *desc,
 	index = desc->offset;
 	clrsetbits_le32(&regs->otyper, OTYPE_MSK << index, ctl->otype << index);
 
+	hwspinlock_unlock(&ctrl_priv->hws);
+
 	return 0;
 }
 
@@ -393,8 +414,6 @@ U_BOOT_DRIVER(pinctrl_stm32) = {
 	.of_match		= stm32_pinctrl_ids,
 	.ops			= &stm32_pinctrl_ops,
 	.bind			= dm_scan_fdt_dev,
-#ifndef CONFIG_SPL_BUILD
 	.probe			= stm32_pinctrl_probe,
 	.priv_auto_alloc_size	= sizeof(struct stm32_pinctrl_priv),
-#endif
 };
-- 
2.15.0



More information about the U-Boot mailing list