32
32
#define TQMX86_GPII_NONE 0
33
33
#define TQMX86_GPII_FALLING BIT(0)
34
34
#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))
35
39
#define TQMX86_GPII_MASK (BIT(0) | BIT(1))
36
40
#define TQMX86_GPII_BITS 2
37
41
/* Stored in irq_type with GPII bits */
@@ -113,9 +117,15 @@ static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset)
113
117
{
114
118
u8 type = TQMX86_GPII_NONE , gpiic ;
115
119
116
- if (gpio -> irq_type [offset ] & TQMX86_INT_UNMASKED )
120
+ if (gpio -> irq_type [offset ] & TQMX86_INT_UNMASKED ) {
117
121
type = gpio -> irq_type [offset ] & TQMX86_GPII_MASK ;
118
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
+
119
129
gpiic = tqmx86_gpio_read (gpio , TQMX86_GPIIC );
120
130
gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS ));
121
131
gpiic |= type << (offset * TQMX86_GPII_BITS );
@@ -169,7 +179,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
169
179
new_type = TQMX86_GPII_FALLING ;
170
180
break ;
171
181
case IRQ_TYPE_EDGE_BOTH :
172
- new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING ;
182
+ new_type = TQMX86_INT_BOTH ;
173
183
break ;
174
184
default :
175
185
return - EINVAL ; /* not supported */
@@ -189,8 +199,8 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
189
199
struct gpio_chip * chip = irq_desc_get_handler_data (desc );
190
200
struct tqmx86_gpio_data * gpio = gpiochip_get_data (chip );
191
201
struct irq_chip * irq_chip = irq_desc_get_chip (desc );
192
- unsigned long irq_bits ;
193
- int i = 0 ;
202
+ unsigned long irq_bits , flags ;
203
+ int i ;
194
204
u8 irq_status ;
195
205
196
206
chained_irq_enter (irq_chip , desc );
@@ -199,6 +209,34 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
199
209
tqmx86_gpio_write (gpio , irq_status , TQMX86_GPIIS );
200
210
201
211
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
+
202
240
for_each_set_bit (i , & irq_bits , TQMX86_NGPI )
203
241
generic_handle_domain_irq (gpio -> chip .irq .domain ,
204
242
i + TQMX86_NGPO );
0 commit comments