Patch "gpio: tqmx86: introduce shadow register for GPIO output value" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    gpio: tqmx86: introduce shadow register for GPIO output value

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     gpio-tqmx86-introduce-shadow-register-for-gpio-outpu.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 2cf382de1e1ac754e72c6cbbbf66868d99251b70
Author: Matthias Schiffer <matthias.schiffer@xxxxxxxxxxxxxxx>
Date:   Thu May 30 12:20:00 2024 +0200

    gpio: tqmx86: introduce shadow register for GPIO output value
    
    [ Upstream commit 9d6a811b522ba558bcb4ec01d12e72a0af8e9f6e ]
    
    The TQMx86 GPIO controller uses the same register address for input and
    output data. Reading the register will always return current inputs
    rather than the previously set outputs (regardless of the current
    direction setting). Therefore, using a RMW pattern does not make sense
    when setting output values. Instead, the previously set output register
    value needs to be stored as a shadow register.
    
    As there is no reliable way to get the current output values from the
    hardware, also initialize all channels to 0, to ensure that stored and
    actual output values match. This should usually not have any effect in
    practise, as the TQMx86 UEFI sets all outputs to 0 during boot.
    
    Also prepare for extension of the driver to more than 8 GPIOs by using
    DECLARE_BITMAP.
    
    Fixes: b868db94a6a7 ("gpio: tqmx86: Add GPIO from for this IO controller")
    Signed-off-by: Matthias Schiffer <matthias.schiffer@xxxxxxxxxxxxxxx>
    Reviewed-by: Andrew Lunn <andrew@xxxxxxx>
    Link: https://lore.kernel.org/r/d0555933becd45fa92a85675d26e4d59343ddc01.1717063994.git.matthias.schiffer@xxxxxxxxxxxxxxx
    Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c
index ea8b7c7f1fd45..d7b79f658faa6 100644
--- a/drivers/gpio/gpio-tqmx86.c
+++ b/drivers/gpio/gpio-tqmx86.c
@@ -6,6 +6,7 @@
  *   Vadim V.Vlasov <vvlasov@xxxxxxxxxxxxx>
  */
 
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/gpio/driver.h>
@@ -38,6 +39,7 @@ struct tqmx86_gpio_data {
 	void __iomem		*io_base;
 	int			irq;
 	raw_spinlock_t		spinlock;
+	DECLARE_BITMAP(output, TQMX86_NGPIO);
 	u8			irq_type[TQMX86_NGPI];
 };
 
@@ -64,15 +66,10 @@ static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset,
 {
 	struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
 	unsigned long flags;
-	u8 val;
 
 	raw_spin_lock_irqsave(&gpio->spinlock, flags);
-	val = tqmx86_gpio_read(gpio, TQMX86_GPIOD);
-	if (value)
-		val |= BIT(offset);
-	else
-		val &= ~BIT(offset);
-	tqmx86_gpio_write(gpio, val, TQMX86_GPIOD);
+	__assign_bit(offset, gpio->output, value);
+	tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD);
 	raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
 }
 
@@ -258,6 +255,13 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
 
 	tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);
 
+	/*
+	 * Reading the previous output state is not possible with TQMx86 hardware.
+	 * Initialize all outputs to 0 to have a defined state that matches the
+	 * shadow register.
+	 */
+	tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD);
+
 	chip = &gpio->chip;
 	chip->label = "gpio-tqmx86";
 	chip->owner = THIS_MODULE;




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux