Skip to content

Commit e60721b

Browse files
committed
Merge tag 'gpio-fixes-for-v6.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: - interrupt handling and Kconfig fixes for gpio-tqmx86 - add a buffer for storing output values in gpio-tqmx86 as reading back the registers always returns the input values - add missing MODULE_DESCRIPTION()s to several GPIO drivers * tag 'gpio-fixes-for-v6.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: add missing MODULE_DESCRIPTION() macros gpio: tqmx86: fix broken IRQ_TYPE_EDGE_BOTH interrupt type gpio: tqmx86: store IRQ trigger type and unmask status separately gpio: tqmx86: introduce shadow register for GPIO output value gpio: tqmx86: fix typo in Kconfig label
2 parents 602079a + 64054eb commit e60721b

File tree

6 files changed

+85
-31
lines changed

6 files changed

+85
-31
lines changed

drivers/gpio/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,7 @@ config GPIO_TPS68470
15761576
are "output only" GPIOs.
15771577

15781578
config GPIO_TQMX86
1579-
tristate "TQ-Systems QTMX86 GPIO"
1579+
tristate "TQ-Systems TQMx86 GPIO"
15801580
depends on MFD_TQMX86 || COMPILE_TEST
15811581
depends on HAS_IOPORT_MAP
15821582
select GPIOLIB_IRQCHIP

drivers/gpio/gpio-gw-pld.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,6 @@ static struct i2c_driver gw_pld_driver = {
130130
};
131131
module_i2c_driver(gw_pld_driver);
132132

133+
MODULE_DESCRIPTION("Gateworks I2C PLD GPIO expander");
133134
MODULE_LICENSE("GPL");
134135
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");

drivers/gpio/gpio-mc33880.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,5 +168,6 @@ static void __exit mc33880_exit(void)
168168
module_exit(mc33880_exit);
169169

170170
MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
171+
MODULE_DESCRIPTION("MC33880 high-side/low-side switch GPIO driver");
171172
MODULE_LICENSE("GPL v2");
172173

drivers/gpio/gpio-pcf857x.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,5 +438,6 @@ static void __exit pcf857x_exit(void)
438438
}
439439
module_exit(pcf857x_exit);
440440

441+
MODULE_DESCRIPTION("Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders");
441442
MODULE_LICENSE("GPL");
442443
MODULE_AUTHOR("David Brownell");

drivers/gpio/gpio-pl061.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,4 +438,5 @@ static struct amba_driver pl061_gpio_driver = {
438438
};
439439
module_amba_driver(pl061_gpio_driver);
440440

441+
MODULE_DESCRIPTION("Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)");
441442
MODULE_LICENSE("GPL v2");

drivers/gpio/gpio-tqmx86.c

Lines changed: 80 additions & 30 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>
@@ -28,16 +29,25 @@
2829
#define TQMX86_GPIIC 3 /* GPI Interrupt Configuration Register */
2930
#define TQMX86_GPIIS 4 /* GPI Interrupt Status Register */
3031

32+
#define TQMX86_GPII_NONE 0
3133
#define TQMX86_GPII_FALLING BIT(0)
3234
#define TQMX86_GPII_RISING BIT(1)
35+
/* Stored in irq_type as a trigger type, but not actually valid as a register
36+
* value, so the name doesn't use "GPII"
37+
*/
38+
#define TQMX86_INT_BOTH (BIT(0) | BIT(1))
3339
#define TQMX86_GPII_MASK (BIT(0) | BIT(1))
3440
#define TQMX86_GPII_BITS 2
41+
/* Stored in irq_type with GPII bits */
42+
#define TQMX86_INT_UNMASKED BIT(2)
3543

3644
struct tqmx86_gpio_data {
3745
struct gpio_chip chip;
3846
void __iomem *io_base;
3947
int irq;
48+
/* Lock must be held for accessing output and irq_type fields */
4049
raw_spinlock_t spinlock;
50+
DECLARE_BITMAP(output, TQMX86_NGPIO);
4151
u8 irq_type[TQMX86_NGPI];
4252
};
4353

@@ -64,15 +74,10 @@ static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset,
6474
{
6575
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
6676
unsigned long flags;
67-
u8 val;
6877

6978
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);
79+
__assign_bit(offset, gpio->output, value);
80+
tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD);
7681
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
7782
}
7883

@@ -107,21 +112,38 @@ static int tqmx86_gpio_get_direction(struct gpio_chip *chip,
107112
return GPIO_LINE_DIRECTION_OUT;
108113
}
109114

115+
static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset)
116+
__must_hold(&gpio->spinlock)
117+
{
118+
u8 type = TQMX86_GPII_NONE, gpiic;
119+
120+
if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) {
121+
type = gpio->irq_type[offset] & TQMX86_GPII_MASK;
122+
123+
if (type == TQMX86_INT_BOTH)
124+
type = tqmx86_gpio_get(&gpio->chip, offset + TQMX86_NGPO)
125+
? TQMX86_GPII_FALLING
126+
: TQMX86_GPII_RISING;
127+
}
128+
129+
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
130+
gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS));
131+
gpiic |= type << (offset * TQMX86_GPII_BITS);
132+
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
133+
}
134+
110135
static void tqmx86_gpio_irq_mask(struct irq_data *data)
111136
{
112137
unsigned int offset = (data->hwirq - TQMX86_NGPO);
113138
struct tqmx86_gpio_data *gpio = gpiochip_get_data(
114139
irq_data_get_irq_chip_data(data));
115140
unsigned long flags;
116-
u8 gpiic, mask;
117-
118-
mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
119141

120142
raw_spin_lock_irqsave(&gpio->spinlock, flags);
121-
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
122-
gpiic &= ~mask;
123-
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
143+
gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED;
144+
tqmx86_gpio_irq_config(gpio, offset);
124145
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
146+
125147
gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data));
126148
}
127149

@@ -131,16 +153,12 @@ static void tqmx86_gpio_irq_unmask(struct irq_data *data)
131153
struct tqmx86_gpio_data *gpio = gpiochip_get_data(
132154
irq_data_get_irq_chip_data(data));
133155
unsigned long flags;
134-
u8 gpiic, mask;
135-
136-
mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
137156

138157
gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data));
158+
139159
raw_spin_lock_irqsave(&gpio->spinlock, flags);
140-
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
141-
gpiic &= ~mask;
142-
gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS);
143-
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
160+
gpio->irq_type[offset] |= TQMX86_INT_UNMASKED;
161+
tqmx86_gpio_irq_config(gpio, offset);
144162
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
145163
}
146164

@@ -151,7 +169,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
151169
unsigned int offset = (data->hwirq - TQMX86_NGPO);
152170
unsigned int edge_type = type & IRQF_TRIGGER_MASK;
153171
unsigned long flags;
154-
u8 new_type, gpiic;
172+
u8 new_type;
155173

156174
switch (edge_type) {
157175
case IRQ_TYPE_EDGE_RISING:
@@ -161,19 +179,16 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
161179
new_type = TQMX86_GPII_FALLING;
162180
break;
163181
case IRQ_TYPE_EDGE_BOTH:
164-
new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING;
182+
new_type = TQMX86_INT_BOTH;
165183
break;
166184
default:
167185
return -EINVAL; /* not supported */
168186
}
169187

170-
gpio->irq_type[offset] = new_type;
171-
172188
raw_spin_lock_irqsave(&gpio->spinlock, flags);
173-
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
174-
gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS));
175-
gpiic |= new_type << (offset * TQMX86_GPII_BITS);
176-
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
189+
gpio->irq_type[offset] &= ~TQMX86_GPII_MASK;
190+
gpio->irq_type[offset] |= new_type;
191+
tqmx86_gpio_irq_config(gpio, offset);
177192
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
178193

179194
return 0;
@@ -184,8 +199,8 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
184199
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
185200
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
186201
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
187-
unsigned long irq_bits;
188-
int i = 0;
202+
unsigned long irq_bits, flags;
203+
int i;
189204
u8 irq_status;
190205

191206
chained_irq_enter(irq_chip, desc);
@@ -194,6 +209,34 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
194209
tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
195210

196211
irq_bits = irq_status;
212+
213+
raw_spin_lock_irqsave(&gpio->spinlock, flags);
214+
for_each_set_bit(i, &irq_bits, TQMX86_NGPI) {
215+
/*
216+
* Edge-both triggers are implemented by flipping the edge
217+
* trigger after each interrupt, as the controller only supports
218+
* either rising or falling edge triggers, but not both.
219+
*
220+
* Internally, the TQMx86 GPIO controller has separate status
221+
* registers for rising and falling edge interrupts. GPIIC
222+
* configures which bits from which register are visible in the
223+
* interrupt status register GPIIS and defines what triggers the
224+
* parent IRQ line. Writing to GPIIS always clears both rising
225+
* and falling interrupt flags internally, regardless of the
226+
* currently configured trigger.
227+
*
228+
* In consequence, we can cleanly implement the edge-both
229+
* trigger in software by first clearing the interrupt and then
230+
* setting the new trigger based on the current GPIO input in
231+
* tqmx86_gpio_irq_config() - even if an edge arrives between
232+
* reading the input and setting the trigger, we will have a new
233+
* interrupt pending.
234+
*/
235+
if ((gpio->irq_type[i] & TQMX86_GPII_MASK) == TQMX86_INT_BOTH)
236+
tqmx86_gpio_irq_config(gpio, i);
237+
}
238+
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
239+
197240
for_each_set_bit(i, &irq_bits, TQMX86_NGPI)
198241
generic_handle_domain_irq(gpio->chip.irq.domain,
199242
i + TQMX86_NGPO);
@@ -277,6 +320,13 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
277320

278321
tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);
279322

323+
/*
324+
* Reading the previous output state is not possible with TQMx86 hardware.
325+
* Initialize all outputs to 0 to have a defined state that matches the
326+
* shadow register.
327+
*/
328+
tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD);
329+
280330
chip = &gpio->chip;
281331
chip->label = "gpio-tqmx86";
282332
chip->owner = THIS_MODULE;

0 commit comments

Comments
 (0)