Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+85 -31
+1 -1
drivers/gpio/Kconfig
··· 1576 1576 are "output only" GPIOs. 1577 1577 1578 1578 config GPIO_TQMX86 1579 - tristate "TQ-Systems QTMX86 GPIO" 1579 + tristate "TQ-Systems TQMx86 GPIO" 1580 1580 depends on MFD_TQMX86 || COMPILE_TEST 1581 1581 depends on HAS_IOPORT_MAP 1582 1582 select GPIOLIB_IRQCHIP
+1
drivers/gpio/gpio-gw-pld.c
··· 130 130 }; 131 131 module_i2c_driver(gw_pld_driver); 132 132 133 + MODULE_DESCRIPTION("Gateworks I2C PLD GPIO expander"); 133 134 MODULE_LICENSE("GPL"); 134 135 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+1
drivers/gpio/gpio-mc33880.c
··· 168 168 module_exit(mc33880_exit); 169 169 170 170 MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); 171 + MODULE_DESCRIPTION("MC33880 high-side/low-side switch GPIO driver"); 171 172 MODULE_LICENSE("GPL v2"); 172 173
+1
drivers/gpio/gpio-pcf857x.c
··· 438 438 } 439 439 module_exit(pcf857x_exit); 440 440 441 + MODULE_DESCRIPTION("Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders"); 441 442 MODULE_LICENSE("GPL"); 442 443 MODULE_AUTHOR("David Brownell");
+1
drivers/gpio/gpio-pl061.c
··· 438 438 }; 439 439 module_amba_driver(pl061_gpio_driver); 440 440 441 + MODULE_DESCRIPTION("Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)"); 441 442 MODULE_LICENSE("GPL v2");
+80 -30
drivers/gpio/gpio-tqmx86.c
··· 6 6 * Vadim V.Vlasov <vvlasov@dev.rtsoft.ru> 7 7 */ 8 8 9 + #include <linux/bitmap.h> 9 10 #include <linux/bitops.h> 10 11 #include <linux/errno.h> 11 12 #include <linux/gpio/driver.h> ··· 29 28 #define TQMX86_GPIIC 3 /* GPI Interrupt Configuration Register */ 30 29 #define TQMX86_GPIIS 4 /* GPI Interrupt Status Register */ 31 30 31 + #define TQMX86_GPII_NONE 0 32 32 #define TQMX86_GPII_FALLING BIT(0) 33 33 #define TQMX86_GPII_RISING BIT(1) 34 + /* Stored in irq_type as a trigger type, but not actually valid as a register 35 + * value, so the name doesn't use "GPII" 36 + */ 37 + #define TQMX86_INT_BOTH (BIT(0) | BIT(1)) 34 38 #define TQMX86_GPII_MASK (BIT(0) | BIT(1)) 35 39 #define TQMX86_GPII_BITS 2 40 + /* Stored in irq_type with GPII bits */ 41 + #define TQMX86_INT_UNMASKED BIT(2) 36 42 37 43 struct tqmx86_gpio_data { 38 44 struct gpio_chip chip; 39 45 void __iomem *io_base; 40 46 int irq; 47 + /* Lock must be held for accessing output and irq_type fields */ 41 48 raw_spinlock_t spinlock; 49 + DECLARE_BITMAP(output, TQMX86_NGPIO); 42 50 u8 irq_type[TQMX86_NGPI]; 43 51 }; 44 52 ··· 74 64 { 75 65 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); 76 66 unsigned long flags; 77 - u8 val; 78 67 79 68 raw_spin_lock_irqsave(&gpio->spinlock, flags); 80 - val = tqmx86_gpio_read(gpio, TQMX86_GPIOD); 81 - if (value) 82 - val |= BIT(offset); 83 - else 84 - val &= ~BIT(offset); 85 - tqmx86_gpio_write(gpio, val, TQMX86_GPIOD); 69 + __assign_bit(offset, gpio->output, value); 70 + tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD); 86 71 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 87 72 } 88 73 ··· 112 107 return GPIO_LINE_DIRECTION_OUT; 113 108 } 114 109 110 + static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset) 111 + __must_hold(&gpio->spinlock) 112 + { 113 + u8 type = TQMX86_GPII_NONE, gpiic; 114 + 115 + if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) { 116 + type = gpio->irq_type[offset] & TQMX86_GPII_MASK; 117 + 118 + if (type == TQMX86_INT_BOTH) 119 + type = tqmx86_gpio_get(&gpio->chip, offset + TQMX86_NGPO) 120 + ? TQMX86_GPII_FALLING 121 + : TQMX86_GPII_RISING; 122 + } 123 + 124 + gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 125 + gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS)); 126 + gpiic |= type << (offset * TQMX86_GPII_BITS); 127 + tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 128 + } 129 + 115 130 static void tqmx86_gpio_irq_mask(struct irq_data *data) 116 131 { 117 132 unsigned int offset = (data->hwirq - TQMX86_NGPO); 118 133 struct tqmx86_gpio_data *gpio = gpiochip_get_data( 119 134 irq_data_get_irq_chip_data(data)); 120 135 unsigned long flags; 121 - u8 gpiic, mask; 122 - 123 - mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); 124 136 125 137 raw_spin_lock_irqsave(&gpio->spinlock, flags); 126 - gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 127 - gpiic &= ~mask; 128 - tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 138 + gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED; 139 + tqmx86_gpio_irq_config(gpio, offset); 129 140 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 141 + 130 142 gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data)); 131 143 } 132 144 ··· 153 131 struct tqmx86_gpio_data *gpio = gpiochip_get_data( 154 132 irq_data_get_irq_chip_data(data)); 155 133 unsigned long flags; 156 - u8 gpiic, mask; 157 - 158 - mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); 159 134 160 135 gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data)); 136 + 161 137 raw_spin_lock_irqsave(&gpio->spinlock, flags); 162 - gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 163 - gpiic &= ~mask; 164 - gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS); 165 - tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 138 + gpio->irq_type[offset] |= TQMX86_INT_UNMASKED; 139 + tqmx86_gpio_irq_config(gpio, offset); 166 140 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 167 141 } 168 142 ··· 169 151 unsigned int offset = (data->hwirq - TQMX86_NGPO); 170 152 unsigned int edge_type = type & IRQF_TRIGGER_MASK; 171 153 unsigned long flags; 172 - u8 new_type, gpiic; 154 + u8 new_type; 173 155 174 156 switch (edge_type) { 175 157 case IRQ_TYPE_EDGE_RISING: ··· 179 161 new_type = TQMX86_GPII_FALLING; 180 162 break; 181 163 case IRQ_TYPE_EDGE_BOTH: 182 - new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING; 164 + new_type = TQMX86_INT_BOTH; 183 165 break; 184 166 default: 185 167 return -EINVAL; /* not supported */ 186 168 } 187 169 188 - gpio->irq_type[offset] = new_type; 189 - 190 170 raw_spin_lock_irqsave(&gpio->spinlock, flags); 191 - gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 192 - gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS)); 193 - gpiic |= new_type << (offset * TQMX86_GPII_BITS); 194 - tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 171 + gpio->irq_type[offset] &= ~TQMX86_GPII_MASK; 172 + gpio->irq_type[offset] |= new_type; 173 + tqmx86_gpio_irq_config(gpio, offset); 195 174 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 196 175 197 176 return 0; ··· 199 184 struct gpio_chip *chip = irq_desc_get_handler_data(desc); 200 185 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); 201 186 struct irq_chip *irq_chip = irq_desc_get_chip(desc); 202 - unsigned long irq_bits; 203 - int i = 0; 187 + unsigned long irq_bits, flags; 188 + int i; 204 189 u8 irq_status; 205 190 206 191 chained_irq_enter(irq_chip, desc); ··· 209 194 tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); 210 195 211 196 irq_bits = irq_status; 197 + 198 + raw_spin_lock_irqsave(&gpio->spinlock, flags); 199 + for_each_set_bit(i, &irq_bits, TQMX86_NGPI) { 200 + /* 201 + * Edge-both triggers are implemented by flipping the edge 202 + * trigger after each interrupt, as the controller only supports 203 + * either rising or falling edge triggers, but not both. 204 + * 205 + * Internally, the TQMx86 GPIO controller has separate status 206 + * registers for rising and falling edge interrupts. GPIIC 207 + * configures which bits from which register are visible in the 208 + * interrupt status register GPIIS and defines what triggers the 209 + * parent IRQ line. Writing to GPIIS always clears both rising 210 + * and falling interrupt flags internally, regardless of the 211 + * currently configured trigger. 212 + * 213 + * In consequence, we can cleanly implement the edge-both 214 + * trigger in software by first clearing the interrupt and then 215 + * setting the new trigger based on the current GPIO input in 216 + * tqmx86_gpio_irq_config() - even if an edge arrives between 217 + * reading the input and setting the trigger, we will have a new 218 + * interrupt pending. 219 + */ 220 + if ((gpio->irq_type[i] & TQMX86_GPII_MASK) == TQMX86_INT_BOTH) 221 + tqmx86_gpio_irq_config(gpio, i); 222 + } 223 + raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 224 + 212 225 for_each_set_bit(i, &irq_bits, TQMX86_NGPI) 213 226 generic_handle_domain_irq(gpio->chip.irq.domain, 214 227 i + TQMX86_NGPO); ··· 319 276 gpio->io_base = io_base; 320 277 321 278 tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD); 279 + 280 + /* 281 + * Reading the previous output state is not possible with TQMx86 hardware. 282 + * Initialize all outputs to 0 to have a defined state that matches the 283 + * shadow register. 284 + */ 285 + tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD); 322 286 323 287 chip = &gpio->chip; 324 288 chip->label = "gpio-tqmx86";