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

gpio: tqmx86: store IRQ trigger type and unmask status separately

irq_set_type() should not implicitly unmask the IRQ.

All accesses to the interrupt configuration register are moved to a new
helper tqmx86_gpio_irq_config(). We also introduce the new rule that
accessing irq_type must happen while locked, which will become
significant for fixing EDGE_BOTH handling.

Fixes: b868db94a6a7 ("gpio: tqmx86: Add GPIO from for this IO controller")
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Link: https://lore.kernel.org/r/6aa4f207f77cb58ef64ffb947e91949b0f753ccd.1717063994.git.matthias.schiffer@ew.tq-group.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

authored by

Matthias Schiffer and committed by
Bartosz Golaszewski
08af509e 9d6a811b

+28 -20
+28 -20
drivers/gpio/gpio-tqmx86.c
··· 29 29 #define TQMX86_GPIIC 3 /* GPI Interrupt Configuration Register */ 30 30 #define TQMX86_GPIIS 4 /* GPI Interrupt Status Register */ 31 31 32 + #define TQMX86_GPII_NONE 0 32 33 #define TQMX86_GPII_FALLING BIT(0) 33 34 #define TQMX86_GPII_RISING BIT(1) 34 35 #define TQMX86_GPII_MASK (BIT(0) | BIT(1)) 35 36 #define TQMX86_GPII_BITS 2 37 + /* Stored in irq_type with GPII bits */ 38 + #define TQMX86_INT_UNMASKED BIT(2) 36 39 37 40 struct tqmx86_gpio_data { 38 41 struct gpio_chip chip; 39 42 void __iomem *io_base; 40 43 int irq; 44 + /* Lock must be held for accessing output and irq_type fields */ 41 45 raw_spinlock_t spinlock; 42 46 DECLARE_BITMAP(output, TQMX86_NGPIO); 43 47 u8 irq_type[TQMX86_NGPI]; ··· 108 104 return GPIO_LINE_DIRECTION_OUT; 109 105 } 110 106 107 + static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset) 108 + __must_hold(&gpio->spinlock) 109 + { 110 + u8 type = TQMX86_GPII_NONE, gpiic; 111 + 112 + if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) 113 + type = gpio->irq_type[offset] & TQMX86_GPII_MASK; 114 + 115 + gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 116 + gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS)); 117 + gpiic |= type << (offset * TQMX86_GPII_BITS); 118 + tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 119 + } 120 + 111 121 static void tqmx86_gpio_irq_mask(struct irq_data *data) 112 122 { 113 123 unsigned int offset = (data->hwirq - TQMX86_NGPO); 114 124 struct tqmx86_gpio_data *gpio = gpiochip_get_data( 115 125 irq_data_get_irq_chip_data(data)); 116 126 unsigned long flags; 117 - u8 gpiic, mask; 118 - 119 - mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); 120 127 121 128 raw_spin_lock_irqsave(&gpio->spinlock, flags); 122 - gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 123 - gpiic &= ~mask; 124 - tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 129 + gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED; 130 + tqmx86_gpio_irq_config(gpio, offset); 125 131 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 132 + 126 133 gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data)); 127 134 } 128 135 ··· 143 128 struct tqmx86_gpio_data *gpio = gpiochip_get_data( 144 129 irq_data_get_irq_chip_data(data)); 145 130 unsigned long flags; 146 - u8 gpiic, mask; 147 - 148 - mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); 149 131 150 132 gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data)); 133 + 151 134 raw_spin_lock_irqsave(&gpio->spinlock, flags); 152 - gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 153 - gpiic &= ~mask; 154 - gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS); 155 - tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 135 + gpio->irq_type[offset] |= TQMX86_INT_UNMASKED; 136 + tqmx86_gpio_irq_config(gpio, offset); 156 137 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 157 138 } 158 139 ··· 159 148 unsigned int offset = (data->hwirq - TQMX86_NGPO); 160 149 unsigned int edge_type = type & IRQF_TRIGGER_MASK; 161 150 unsigned long flags; 162 - u8 new_type, gpiic; 151 + u8 new_type; 163 152 164 153 switch (edge_type) { 165 154 case IRQ_TYPE_EDGE_RISING: ··· 175 164 return -EINVAL; /* not supported */ 176 165 } 177 166 178 - gpio->irq_type[offset] = new_type; 179 - 180 167 raw_spin_lock_irqsave(&gpio->spinlock, flags); 181 - gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); 182 - gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS)); 183 - gpiic |= new_type << (offset * TQMX86_GPII_BITS); 184 - tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); 168 + gpio->irq_type[offset] &= ~TQMX86_GPII_MASK; 169 + gpio->irq_type[offset] |= new_type; 170 + tqmx86_gpio_irq_config(gpio, offset); 185 171 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); 186 172 187 173 return 0;