--- /dev/null
+From ea025423136786f0ec1fb2ec2372d9523c7ca65d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jun 2020 11:31:50 +0200
+Subject: pinctrl: baytrail: Fix pin being driven low for a while on
+ gpiod_get(..., GPIOD_OUT_HIGH)
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 156abe2961601d60a8c2a60c6dc8dd6ce7adcdaf upstream
+
+The pins on the Bay Trail SoC have separate input-buffer and output-buffer
+enable bits and a read of the level bit of the value register will always
+return the value from the input-buffer.
+
+The BIOS of a device may configure a pin in output-only mode, only enabling
+the output buffer, and write 1 to the level bit to drive the pin high.
+This 1 written to the level bit will be stored inside the data-latch of the
+output buffer.
+
+But a subsequent read of the value register will return 0 for the level bit
+because the input-buffer is disabled. This causes a read-modify-write as
+done by byt_gpio_set_direction() to write 0 to the level bit, driving the
+pin low!
+
+Before this commit byt_gpio_direction_output() relied on
+pinctrl_gpio_direction_output() to set the direction, followed by a call
+to byt_gpio_set() to apply the selected value. This causes the pin to
+go low between the pinctrl_gpio_direction_output() and byt_gpio_set()
+calls.
+
+Change byt_gpio_direction_output() to directly make the register
+modifications itself instead. Replacing the 2 subsequent writes to the
+value register with a single write.
+
+Note that the pinctrl code does not keep track internally of the direction,
+so not going through pinctrl_gpio_direction_output() is not an issue.
+
+This issue was noticed on a Trekstor SurfTab Twin 10.1. When the panel is
+already on at boot (no external monitor connected), then the i915 driver
+does a gpiod_get(..., GPIOD_OUT_HIGH) for the panel-enable GPIO. The
+temporarily going low of that GPIO was causing the panel to reset itself
+after which it would not show an image until it was turned off and back on
+again (until a full modeset was done on it). This commit fixes this.
+
+This commit also updates the byt_gpio_direction_input() to use direct
+register accesses instead of going through pinctrl_gpio_direction_input(),
+to keep it consistent with byt_gpio_direction_output().
+
+Note for backporting, this commit depends on:
+commit e2b74419e5cc ("pinctrl: baytrail: Replace WARN with dev_info_once
+when setting direct-irq pin to output")
+
+Cc: stable@vger.kernel.org
+Fixes: 86e3ef812fe3 ("pinctrl: baytrail: Update gpio chip operations")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+[sudip: use byt_gpio and vg->pdev->dev for dev_info()]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 67 +++++++++++++++++++-----
+ 1 file changed, 53 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index 7d6685ae31d70..1b00a3f3b419c 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -1009,6 +1009,21 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
+ pm_runtime_put(&vg->pdev->dev);
+ }
+
++static void byt_gpio_direct_irq_check(struct byt_gpio *vg,
++ unsigned int offset)
++{
++ void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
++
++ /*
++ * Before making any direction modifications, do a check if gpio is set
++ * for direct IRQ. On Bay Trail, setting GPIO to output does not make
++ * sense, so let's at least inform the caller before they shoot
++ * themselves in the foot.
++ */
++ if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
++ dev_info_once(&vg->pdev->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
++}
++
+ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset,
+@@ -1016,7 +1031,6 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+ {
+ struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+ void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+- void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+ unsigned long flags;
+ u32 value;
+
+@@ -1026,14 +1040,8 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+ value &= ~BYT_DIR_MASK;
+ if (input)
+ value |= BYT_OUTPUT_EN;
+- else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
+- /*
+- * Before making any direction modifications, do a check if gpio
+- * is set for direct IRQ. On baytrail, setting GPIO to output
+- * does not make sense, so let's at least inform the caller before
+- * they shoot themselves in the foot.
+- */
+- dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
++ else
++ byt_gpio_direct_irq_check(vg, offset);
+
+ writel(value, val_reg);
+
+@@ -1374,19 +1382,50 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+
+ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+ {
+- return pinctrl_gpio_direction_input(chip->base + offset);
++ struct byt_gpio *vg = gpiochip_get_data(chip);
++ void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
++ unsigned long flags;
++ u32 reg;
++
++ raw_spin_lock_irqsave(&byt_lock, flags);
++
++ reg = readl(val_reg);
++ reg &= ~BYT_DIR_MASK;
++ reg |= BYT_OUTPUT_EN;
++ writel(reg, val_reg);
++
++ raw_spin_unlock_irqrestore(&byt_lock, flags);
++ return 0;
+ }
+
++/*
++ * Note despite the temptation this MUST NOT be converted into a call to
++ * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this
++ * MUST be done as a single BYT_VAL_REG register write.
++ * See the commit message of the commit adding this comment for details.
++ */
+ static int byt_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+ {
+- int ret = pinctrl_gpio_direction_output(chip->base + offset);
++ struct byt_gpio *vg = gpiochip_get_data(chip);
++ void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
++ unsigned long flags;
++ u32 reg;
+
+- if (ret)
+- return ret;
++ raw_spin_lock_irqsave(&byt_lock, flags);
+
+- byt_gpio_set(chip, offset, value);
++ byt_gpio_direct_irq_check(vg, offset);
+
++ reg = readl(val_reg);
++ reg &= ~BYT_DIR_MASK;
++ if (value)
++ reg |= BYT_LEVEL;
++ else
++ reg &= ~BYT_LEVEL;
++
++ writel(reg, val_reg);
++
++ raw_spin_unlock_irqrestore(&byt_lock, flags);
+ return 0;
+ }
+
+--
+2.27.0
+
--- /dev/null
+From 6c10341a00f35beb7b7767ce6cf6f1239c1c7e20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Jan 2020 15:52:43 +0100
+Subject: pinctrl: baytrail: Replace WARN with dev_info_once when setting
+ direct-irq pin to output
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit e2b74419e5cc7cfc58f3e785849f73f8fa0af5b3 upstream
+
+Suspending Goodix touchscreens requires changing the interrupt pin to
+output before sending them a power-down command. Followed by wiggling
+the interrupt pin to wake the device up, after which it is put back
+in input mode.
+
+On Cherry Trail device the interrupt pin is listed as a GpioInt ACPI
+resource so we can do this without problems as long as we release the
+IRQ before changing the pin to output mode.
+
+On Bay Trail devices with a Goodix touchscreen direct-irq mode is used
+in combination with listing the pin as a normal GpioIo resource. This
+works fine, but this triggers the WARN in byt_gpio_set_direction-s output
+path because direct-irq support is enabled on the pin.
+
+This commit replaces the WARN call with a dev_info_once call, fixing a
+bunch of WARN splats in dmesg on each suspend/resume cycle.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index acb02a7aa9496..7d6685ae31d70 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -1026,15 +1026,15 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+ value &= ~BYT_DIR_MASK;
+ if (input)
+ value |= BYT_OUTPUT_EN;
+- else
++ else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
+ /*
+ * Before making any direction modifications, do a check if gpio
+ * is set for direct IRQ. On baytrail, setting GPIO to output
+- * does not make sense, so let's at least warn the caller before
++ * does not make sense, so let's at least inform the caller before
+ * they shoot themselves in the foot.
+ */
+- WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
+- "Potential Error: Setting GPIO with direct_irq_en to output");
++ dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
++
+ writel(value, val_reg);
+
+ raw_spin_unlock_irqrestore(&byt_lock, flags);
+--
+2.27.0
+