mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
pinctrl: intel: Avoid potential glitches if pin is in GPIO mode
commit29c2c6aa32upstream. 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:7981c0015a("pinctrl: intel: Add Intel Sunrisepoint pin controller and GPIO support") Depends-on:f5a26acf01("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
61a928dff6
commit
a967331e5c
@@ -52,6 +52,7 @@
|
|||||||
#define PADCFG0_GPIROUTNMI BIT(17)
|
#define PADCFG0_GPIROUTNMI BIT(17)
|
||||||
#define PADCFG0_PMODE_SHIFT 10
|
#define PADCFG0_PMODE_SHIFT 10
|
||||||
#define PADCFG0_PMODE_MASK GENMASK(13, 10)
|
#define PADCFG0_PMODE_MASK GENMASK(13, 10)
|
||||||
|
#define PADCFG0_PMODE_GPIO 0
|
||||||
#define PADCFG0_GPIORXDIS BIT(9)
|
#define PADCFG0_GPIORXDIS BIT(9)
|
||||||
#define PADCFG0_GPIOTXDIS BIT(8)
|
#define PADCFG0_GPIOTXDIS BIT(8)
|
||||||
#define PADCFG0_GPIORXSTATE BIT(1)
|
#define PADCFG0_GPIORXSTATE BIT(1)
|
||||||
@@ -307,7 +308,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
|||||||
cfg1 = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
|
cfg1 = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
|
||||||
|
|
||||||
mode = (cfg0 & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
|
mode = (cfg0 & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
|
||||||
if (!mode)
|
if (mode == PADCFG0_PMODE_GPIO)
|
||||||
seq_puts(s, "GPIO ");
|
seq_puts(s, "GPIO ");
|
||||||
else
|
else
|
||||||
seq_printf(s, "mode %d ", mode);
|
seq_printf(s, "mode %d ", mode);
|
||||||
@@ -428,6 +429,11 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
|
|||||||
writel(value, padcfg0);
|
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)
|
static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
|
||||||
{
|
{
|
||||||
u32 value;
|
u32 value;
|
||||||
@@ -456,7 +462,20 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
|
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);
|
intel_gpio_set_gpio_mode(padcfg0);
|
||||||
|
|
||||||
/* Disable TX buffer and enable RX (this will be input) */
|
/* Disable TX buffer and enable RX (this will be input) */
|
||||||
__intel_gpio_set_direction(padcfg0, true);
|
__intel_gpio_set_direction(padcfg0, true);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user