pinctrl: intel: Avoid potential glitches if pin is in GPIO mode
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Mon, 14 Oct 2019 09:51:04 +0000 (12:51 +0300)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Mon, 21 Oct 2019 12:41:19 +0000 (15:41 +0300)
When consumer requests a pin, in order to be on the safest side,
we switch it first to GPIO mode followed by immediate transition
to the input state. Due to posted writes it's luckily to be a single
I/O transaction.

However, if firmware or boot loader already configures the pin
to the GPIO mode, user expects no glitches for the requested pin.
We may check if the pin is pre-configured and leave it as is
till the actual consumer toggles its state to avoid glitches.

Fixes: 7981c0015af2 ("pinctrl: intel: Add Intel Sunrisepoint pin controller and GPIO support")
Depends-on: f5a26acf0162 ("pinctrl: intel: Initialize GPIO properly when used through irqchip")
Cc: stable@vger.kernel.org
Cc: fei.yang@intel.com
Reported-by: Oliver Barta <oliver.barta@aptiv.com>
Reported-by: Malin Jonsson <malin.jonsson@ericsson.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/pinctrl/intel/pinctrl-intel.c

index bc01359..83981ad 100644 (file)
@@ -52,6 +52,7 @@
 #define PADCFG0_GPIROUTNMI             BIT(17)
 #define PADCFG0_PMODE_SHIFT            10
 #define PADCFG0_PMODE_MASK             GENMASK(13, 10)
+#define PADCFG0_PMODE_GPIO             0
 #define PADCFG0_GPIORXDIS              BIT(9)
 #define PADCFG0_GPIOTXDIS              BIT(8)
 #define PADCFG0_GPIORXSTATE            BIT(1)
@@ -332,7 +333,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
        cfg1 = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
 
        mode = (cfg0 & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
-       if (!mode)
+       if (mode == PADCFG0_PMODE_GPIO)
                seq_puts(s, "GPIO ");
        else
                seq_printf(s, "mode %d ", mode);
@@ -458,6 +459,11 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
        writel(value, padcfg0);
 }
 
+static int intel_gpio_get_gpio_mode(void __iomem *padcfg0)
+{
+       return (readl(padcfg0) & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
+}
+
 static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
 {
        u32 value;
@@ -491,7 +497,20 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
        }
 
        padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
+
+       /*
+        * If pin is already configured in GPIO mode, we assume that
+        * firmware provides correct settings. In such case we avoid
+        * potential glitches on the pin. Otherwise, for the pin in
+        * alternative mode, consumer has to supply respective flags.
+        */
+       if (intel_gpio_get_gpio_mode(padcfg0) == PADCFG0_PMODE_GPIO) {
+               raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+               return 0;
+       }
+
        intel_gpio_set_gpio_mode(padcfg0);
+
        /* Disable TX buffer and enable RX (this will be input) */
        __intel_gpio_set_direction(padcfg0, true);