Commit eef3ac19 authored by Philippe Gerum's avatar Philippe Gerum

pinctrl: bcm2835: ipipe: enable interrupt pipelining

Fix up the pin controller driver of the Broadcom 2835 SoC in order to
channel interrupts through the interrupt pipeline.
parent 6c9b43cc
......@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/ipipe.h>
#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of.h>
......@@ -90,7 +91,11 @@ struct bcm2835_pinctrl {
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
#ifdef CONFIG_IPIPE
ipipe_spinlock_t irq_lock[BCM2835_NUM_BANKS];
#else
raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
#endif
};
/* pins are just named GPIO0..GPIO53 */
......@@ -369,7 +374,7 @@ static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
events &= pc->enabled_irq_map[bank];
for_each_set_bit(offset, &events, 32) {
gpio = (32 * bank) + offset;
generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
ipipe_handle_demuxed_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
gpio));
}
}
......@@ -464,6 +469,7 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
set_bit(offset, &pc->enabled_irq_map[bank]);
bcm2835_gpio_irq_config(pc, gpio, true);
ipipe_unlock_irq(data->irq);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
......@@ -481,6 +487,7 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data)
/* Clear events that were latched prior to clearing event sources */
bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
clear_bit(offset, &pc->enabled_irq_map[bank]);
ipipe_lock_irq(data->irq);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
......@@ -610,6 +617,39 @@ static void bcm2835_gpio_irq_ack(struct irq_data *data)
bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
}
#ifdef CONFIG_IPIPE
static void bcm2835_gpio_irq_hold(struct irq_data *data)
{
struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
unsigned gpio = irqd_to_hwirq(data);
unsigned offset = GPIO_REG_SHIFT(gpio);
unsigned bank = GPIO_REG_OFFSET(gpio);
unsigned long flags;
raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
bcm2835_gpio_irq_config(pc, gpio, false);
bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
clear_bit(offset, &pc->enabled_irq_map[bank]);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
static void bcm2835_gpio_irq_release(struct irq_data *data)
{
struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
unsigned gpio = irqd_to_hwirq(data);
unsigned offset = GPIO_REG_SHIFT(gpio);
unsigned bank = GPIO_REG_OFFSET(gpio);
unsigned long flags;
raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
set_bit(offset, &pc->enabled_irq_map[bank]);
bcm2835_gpio_irq_config(pc, gpio, true);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
#endif
static struct irq_chip bcm2835_gpio_irq_chip = {
.name = MODULE_NAME,
.irq_enable = bcm2835_gpio_irq_enable,
......@@ -618,6 +658,11 @@ static struct irq_chip bcm2835_gpio_irq_chip = {
.irq_ack = bcm2835_gpio_irq_ack,
.irq_mask = bcm2835_gpio_irq_disable,
.irq_unmask = bcm2835_gpio_irq_enable,
#ifdef CONFIG_IPIPE
.irq_hold = bcm2835_gpio_irq_hold,
.irq_release = bcm2835_gpio_irq_release,
#endif
.flags = IRQCHIP_PIPELINE_SAFE,
};
static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment