Commit 133bbf97 authored by Philippe Gerum's avatar Philippe Gerum Committed by Dmitriy Cherkasov

pinctrl: bcm2835: ipipe: enable pipelined interrupts

parent a8ba07eb
......@@ -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>
......@@ -92,7 +93,11 @@ struct bcm2835_pinctrl {
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
spinlock_t irq_lock[BCM2835_NUM_BANKS];
#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 */
......@@ -379,7 +384,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.irqdomain,
ipipe_handle_demuxed_irq(irq_linear_revmap(pc->gpio_chip.irqdomain,
gpio));
}
}
......@@ -471,10 +476,11 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
unsigned bank = GPIO_REG_OFFSET(gpio);
unsigned long flags;
spin_lock_irqsave(&pc->irq_lock[bank], 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);
spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
ipipe_unlock_irq(data->irq);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
static void bcm2835_gpio_irq_disable(struct irq_data *data)
......@@ -486,12 +492,13 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data)
unsigned bank = GPIO_REG_OFFSET(gpio);
unsigned long flags;
spin_lock_irqsave(&pc->irq_lock[bank], flags);
raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
bcm2835_gpio_irq_config(pc, gpio, false);
/* 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]);
spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
ipipe_lock_irq(data->irq);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
......@@ -594,7 +601,7 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
unsigned long flags;
int ret;
spin_lock_irqsave(&pc->irq_lock[bank], flags);
raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
if (test_bit(offset, &pc->enabled_irq_map[bank]))
ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type);
......@@ -606,7 +613,7 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
else
irq_set_handler_locked(data, handle_level_irq);
spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
return ret;
}
......@@ -620,6 +627,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,
......@@ -628,6 +668,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)
......@@ -1021,7 +1066,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
for_each_set_bit(offset, &events, 32)
bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
spin_lock_init(&pc->irq_lock[i]);
raw_spin_lock_init(&pc->irq_lock[i]);
}
err = gpiochip_add_data(&pc->gpio_chip, pc);
......
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