Skip to content

Commit 9d6a811

Browse files
tq-schiffermBartosz Golaszewski
authored andcommitted
gpio: tqmx86: introduce shadow register for GPIO output value
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: b868db9 ("gpio: tqmx86: Add GPIO from for this IO controller") Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Link: https://lore.kernel.org/r/d0555933becd45fa92a85675d26e4d59343ddc01.1717063994.git.matthias.schiffer@ew.tq-group.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
1 parent 8c219e5 commit 9d6a811

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

drivers/gpio/gpio-tqmx86.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Vadim V.Vlasov <vvlasov@dev.rtsoft.ru>
77
*/
88

9+
#include <linux/bitmap.h>
910
#include <linux/bitops.h>
1011
#include <linux/errno.h>
1112
#include <linux/gpio/driver.h>
@@ -38,6 +39,7 @@ struct tqmx86_gpio_data {
3839
void __iomem *io_base;
3940
int irq;
4041
raw_spinlock_t spinlock;
42+
DECLARE_BITMAP(output, TQMX86_NGPIO);
4143
u8 irq_type[TQMX86_NGPI];
4244
};
4345

@@ -64,15 +66,10 @@ static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset,
6466
{
6567
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
6668
unsigned long flags;
67-
u8 val;
6869

6970
raw_spin_lock_irqsave(&gpio->spinlock, flags);
70-
val = tqmx86_gpio_read(gpio, TQMX86_GPIOD);
71-
if (value)
72-
val |= BIT(offset);
73-
else
74-
val &= ~BIT(offset);
75-
tqmx86_gpio_write(gpio, val, TQMX86_GPIOD);
71+
__assign_bit(offset, gpio->output, value);
72+
tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD);
7673
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
7774
}
7875

@@ -277,6 +274,13 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
277274

278275
tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);
279276

277+
/*
278+
* Reading the previous output state is not possible with TQMx86 hardware.
279+
* Initialize all outputs to 0 to have a defined state that matches the
280+
* shadow register.
281+
*/
282+
tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD);
283+
280284
chip = &gpio->chip;
281285
chip->label = "gpio-tqmx86";
282286
chip->owner = THIS_MODULE;

0 commit comments

Comments
 (0)