pinctrl/at91: convert driver to use gpiolib irqchip

This converts the AT91 pin control driver to register its
chained irq handler and irqchip using the helpers in the
gpiolib core.

Signed-off-by: Alexander Stein <alexanders83@web.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Alexander Stein 2014-04-15 22:09:41 +02:00 коммит произвёл Linus Walleij
Родитель 443ac95302
Коммит 80cc37329d
2 изменённых файлов: 33 добавлений и 105 удалений

Просмотреть файл

@ -84,6 +84,9 @@ config PINCTRL_AT91
depends on ARCH_AT91
select PINMUX
select PINCONF
select GPIOLIB
select OF_GPIO
select GPIOLIB_IRQCHIP
help
Say Y here to enable the at91 pinctrl driver

Просмотреть файл

@ -16,9 +16,6 @@
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/pinctrl/machine.h>
@ -47,7 +44,6 @@ struct at91_gpio_chip {
int pioc_idx; /* PIO bank index */
void __iomem *regbase; /* PIO bank virtual address */
struct clk *clock; /* associated clock */
struct irq_domain *domain; /* associated irq domain */
struct at91_pinctrl_mux_ops *ops; /* ops */
};
@ -1192,21 +1188,6 @@ static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return 0;
}
static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
int virq;
if (offset < chip->ngpio)
virq = irq_create_mapping(at91_gpio->domain, offset);
else
virq = -ENXIO;
dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
chip->label, offset + chip->base, virq);
return virq;
}
#ifdef CONFIG_DEBUG_FS
static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
@ -1336,6 +1317,11 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
return 0;
}
static void gpio_irq_ack(struct irq_data *d)
{
/* the interrupt is already cleared before by reading ISR */
}
static unsigned int gpio_irq_startup(struct irq_data *d)
{
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
@ -1435,6 +1421,7 @@ void at91_pinctrl_gpio_resume(void)
static struct irq_chip gpio_irqchip = {
.name = "GPIO",
.irq_ack = gpio_irq_ack,
.irq_startup = gpio_irq_startup,
.irq_shutdown = gpio_irq_shutdown,
.irq_disable = gpio_irq_mask,
@ -1446,9 +1433,11 @@ static struct irq_chip gpio_irqchip = {
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_data *idata = irq_desc_get_irq_data(desc);
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
struct irq_chip *chip = irq_get_chip(irq);
struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
struct at91_gpio_chip *at91_gpio = container_of(gpio_chip,
struct at91_gpio_chip, chip);
void __iomem *pio = at91_gpio->regbase;
unsigned long isr;
int n;
@ -1469,81 +1458,19 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
}
for_each_set_bit(n, &isr, BITS_PER_LONG) {
generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
generic_handle_irq(irq_find_mapping(
gpio_chip->irqdomain, n));
}
}
chained_irq_exit(chip, desc);
/* now it may re-trigger */
}
/*
* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct at91_gpio_chip *at91_gpio = h->host_data;
void __iomem *pio = at91_gpio->regbase;
u32 mask = 1 << hw;
irq_set_lockdep_class(virq, &gpio_lock_class);
/*
* Can use the "simple" and not "edge" handler since it's
* shorter, and the AIC handles interrupts sanely.
*/
irq_set_chip(virq, &gpio_irqchip);
if ((at91_gpio->ops == &at91sam9x5_ops) &&
(readl_relaxed(pio + PIO_AIMMR) & mask) &&
(readl_relaxed(pio + PIO_ELSR) & mask))
irq_set_handler(virq, handle_level_irq);
else
irq_set_handler(virq, handle_simple_irq);
set_irq_flags(virq, IRQF_VALID);
irq_set_chip_data(virq, at91_gpio);
return 0;
}
static int at91_gpio_irq_domain_xlate(struct irq_domain *d,
struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq,
unsigned int *out_type)
{
struct at91_gpio_chip *at91_gpio = d->host_data;
int ret;
int pin = at91_gpio->chip.base + intspec[0];
if (WARN_ON(intsize < 2))
return -EINVAL;
*out_hwirq = intspec[0];
*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
ret = gpio_request(pin, ctrlr->full_name);
if (ret)
return ret;
ret = gpio_direction_input(pin);
if (ret)
return ret;
return 0;
}
static struct irq_domain_ops at91_gpio_ops = {
.map = at91_gpio_irq_map,
.xlate = at91_gpio_irq_domain_xlate,
};
static int at91_gpio_of_irq_setup(struct device_node *node,
struct at91_gpio_chip *at91_gpio)
{
struct at91_gpio_chip *prev = NULL;
struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
int ret;
at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
@ -1553,26 +1480,25 @@ static int at91_gpio_of_irq_setup(struct device_node *node,
/* Disable irqs of this PIO controller */
writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
/* Setup irq domain */
at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
&at91_gpio_ops, at91_gpio);
if (!at91_gpio->domain)
/*
* Let the generic code handle this edge IRQ, the the chained
* handler will perform the actual work of handling the parent
* interrupt.
*/
ret = gpiochip_irqchip_add(&at91_gpio->chip,
&gpio_irqchip,
0,
handle_edge_irq,
IRQ_TYPE_EDGE_BOTH);
if (ret)
panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
at91_gpio->pioc_idx);
/* Setup chained handler */
if (at91_gpio->pioc_idx)
prev = gpio_chips[at91_gpio->pioc_idx - 1];
/* The top level handler handles one bank of GPIOs, except
* on some SoC it can handle up to three...
* We only set up the handler for the first of the list.
*/
if (prev && prev->next == at91_gpio)
return 0;
irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
/* Then register the chain on the parent IRQ */
gpiochip_set_chained_irqchip(&at91_gpio->chip,
&gpio_irqchip,
at91_gpio->pioc_virq,
gpio_irq_handler);
return 0;
}
@ -1586,7 +1512,6 @@ static struct gpio_chip at91_gpio_template = {
.get = at91_gpio_get,
.direction_output = at91_gpio_direction_output,
.set = at91_gpio_set,
.to_irq = at91_gpio_to_irq,
.dbg_show = at91_gpio_dbg_show,
.can_sleep = false,
.ngpio = MAX_NB_GPIO_PER_BANK,