Skip to content

Commit 47beed5

Browse files
atorgueMarc Zyngier
authored and
Marc Zyngier
committed
pinctrl: stm32: Add level interrupt support to gpio irq chip
GPIO hardware block is directly linked to EXTI block but EXTI handles external interrupts only on edge. To be able to handle GPIO interrupt on level a "hack" is done in gpio irq chip: parent interrupt (exti irq chip) is retriggered following interrupt type and gpio line value. Signed-off-by: Alexandre Torgue <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Tested-by: Marek Vasut <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 25591d4 commit 47beed5

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

drivers/pinctrl/stm32/pinctrl-stm32.c

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct stm32_gpio_bank {
9292
u32 bank_nr;
9393
u32 bank_ioport_nr;
9494
u32 pin_backup[STM32_GPIO_PINS_PER_BANK];
95+
u8 irq_type[STM32_GPIO_PINS_PER_BANK];
9596
};
9697

9798
struct stm32_pinctrl {
@@ -303,6 +304,46 @@ static const struct gpio_chip stm32_gpio_template = {
303304
.get_direction = stm32_gpio_get_direction,
304305
};
305306

307+
void stm32_gpio_irq_eoi(struct irq_data *d)
308+
{
309+
struct stm32_gpio_bank *bank = d->domain->host_data;
310+
int level;
311+
312+
irq_chip_eoi_parent(d);
313+
314+
/* If level interrupt type then retrig */
315+
level = stm32_gpio_get(&bank->gpio_chip, d->hwirq);
316+
if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) ||
317+
(level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH))
318+
irq_chip_retrigger_hierarchy(d);
319+
};
320+
321+
static int stm32_gpio_set_type(struct irq_data *d, unsigned int type)
322+
{
323+
struct stm32_gpio_bank *bank = d->domain->host_data;
324+
u32 parent_type;
325+
326+
switch (type) {
327+
case IRQ_TYPE_EDGE_RISING:
328+
case IRQ_TYPE_EDGE_FALLING:
329+
case IRQ_TYPE_EDGE_BOTH:
330+
parent_type = type;
331+
break;
332+
case IRQ_TYPE_LEVEL_HIGH:
333+
parent_type = IRQ_TYPE_EDGE_RISING;
334+
break;
335+
case IRQ_TYPE_LEVEL_LOW:
336+
parent_type = IRQ_TYPE_EDGE_FALLING;
337+
break;
338+
default:
339+
return -EINVAL;
340+
}
341+
342+
bank->irq_type[d->hwirq] = type;
343+
344+
return irq_chip_set_type_parent(d, parent_type);
345+
};
346+
306347
static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
307348
{
308349
struct stm32_gpio_bank *bank = irq_data->domain->host_data;
@@ -332,11 +373,11 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data)
332373

333374
static struct irq_chip stm32_gpio_irq_chip = {
334375
.name = "stm32gpio",
335-
.irq_eoi = irq_chip_eoi_parent,
376+
.irq_eoi = stm32_gpio_irq_eoi,
336377
.irq_ack = irq_chip_ack_parent,
337378
.irq_mask = irq_chip_mask_parent,
338379
.irq_unmask = irq_chip_unmask_parent,
339-
.irq_set_type = irq_chip_set_type_parent,
380+
.irq_set_type = stm32_gpio_set_type,
340381
.irq_set_wake = irq_chip_set_wake_parent,
341382
.irq_request_resources = stm32_gpio_irq_request_resources,
342383
.irq_release_resources = stm32_gpio_irq_release_resources,

0 commit comments

Comments
 (0)