summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c26
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);
}