pinctrl: stm32: make pinctrl use hwspinlock
authorBenjamin Gaignard <benjamin.gaignard@linaro.org>
Tue, 27 Nov 2018 12:49:53 +0000 (13:49 +0100)
committerTom Rini <trini@konsulko.com>
Fri, 7 Dec 2018 04:26:33 +0000 (23:26 -0500)
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@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
arch/arm/dts/stm32mp157c-ed1.dts
drivers/pinctrl/pinctrl_stm32.c

index fc277dd..7a9b742 100644 (file)
        status = "okay";
 };
 
+&pinctrl {
+       hwlocks = <&hwspinlock 0>;
+};
+
 &usbphyc_port0 {
        phy-supply = <&vdd_usb>;
        vdda1v1-supply = <&reg11>;
index 6d4117d..bb63da3 100644 (file)
@@ -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
 };