diff options
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-bcm2835.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 4d08b850478e..8d908e3f42c3 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -403,15 +403,7 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) gpio = (32 * bank) + offset; type = pc->irq_type[gpio]; - /* ack edge triggered IRQs immediately */ - if (!(type & IRQ_TYPE_LEVEL_MASK)) - bcm2835_gpio_set_bit(pc, GPEDS0, gpio); - generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); - - /* ack level triggered IRQ after handling them */ - if (type & IRQ_TYPE_LEVEL_MASK) - bcm2835_gpio_set_bit(pc, GPEDS0, gpio); } return events ? IRQ_HANDLED : IRQ_NONE; } @@ -591,16 +583,32 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type) else ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type); + if (type & IRQ_TYPE_EDGE_BOTH) + __irq_set_handler_locked(data->irq, handle_edge_irq); + else + __irq_set_handler_locked(data->irq, handle_level_irq); + spin_unlock_irqrestore(&pc->irq_lock[bank], flags); return ret; } +static void bcm2835_gpio_irq_ack(struct irq_data *data) +{ + struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data); + unsigned gpio = irqd_to_hwirq(data); + + bcm2835_gpio_set_bit(pc, GPEDS0, gpio); +} + static struct irq_chip bcm2835_gpio_irq_chip = { .name = MODULE_NAME, .irq_enable = bcm2835_gpio_irq_enable, .irq_disable = bcm2835_gpio_irq_disable, .irq_set_type = bcm2835_gpio_irq_set_type, + .irq_ack = bcm2835_gpio_irq_ack, + .irq_mask = bcm2835_gpio_irq_disable, + .irq_unmask = bcm2835_gpio_irq_enable, }; static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) @@ -977,7 +985,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) int irq = irq_create_mapping(pc->irq_domain, i); irq_set_lockdep_class(irq, &gpio_lock_class); irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip, - handle_simple_irq); + handle_level_irq); irq_set_chip_data(irq, pc); set_irq_flags(irq, IRQF_VALID); } |