Commit 80cc3732 authored by Alexander Stein's avatar Alexander Stein Committed by Linus Walleij

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: default avatarAlexander Stein <alexanders83@web.de>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 443ac953
...@@ -84,6 +84,9 @@ config PINCTRL_AT91 ...@@ -84,6 +84,9 @@ config PINCTRL_AT91
depends on ARCH_AT91 depends on ARCH_AT91
select PINMUX select PINMUX
select PINCONF select PINCONF
select GPIOLIB
select OF_GPIO
select GPIOLIB_IRQCHIP
help help
Say Y here to enable the at91 pinctrl driver Say Y here to enable the at91 pinctrl driver
......
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.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/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
...@@ -47,7 +44,6 @@ struct at91_gpio_chip { ...@@ -47,7 +44,6 @@ struct at91_gpio_chip {
int pioc_idx; /* PIO bank index */ int pioc_idx; /* PIO bank index */
void __iomem *regbase; /* PIO bank virtual address */ void __iomem *regbase; /* PIO bank virtual address */
struct clk *clock; /* associated clock */ struct clk *clock; /* associated clock */
struct irq_domain *domain; /* associated irq domain */
struct at91_pinctrl_mux_ops *ops; /* ops */ struct at91_pinctrl_mux_ops *ops; /* ops */
}; };
...@@ -1192,21 +1188,6 @@ static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset, ...@@ -1192,21 +1188,6 @@ static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return 0; 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 #ifdef CONFIG_DEBUG_FS
static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 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) ...@@ -1336,6 +1317,11 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
return 0; 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) static unsigned int gpio_irq_startup(struct irq_data *d)
{ {
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_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) ...@@ -1435,6 +1421,7 @@ void at91_pinctrl_gpio_resume(void)
static struct irq_chip gpio_irqchip = { static struct irq_chip gpio_irqchip = {
.name = "GPIO", .name = "GPIO",
.irq_ack = gpio_irq_ack,
.irq_startup = gpio_irq_startup, .irq_startup = gpio_irq_startup,
.irq_shutdown = gpio_irq_shutdown, .irq_shutdown = gpio_irq_shutdown,
.irq_disable = gpio_irq_mask, .irq_disable = gpio_irq_mask,
...@@ -1446,9 +1433,11 @@ static struct irq_chip gpio_irqchip = { ...@@ -1446,9 +1433,11 @@ static struct irq_chip gpio_irqchip = {
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = irq_desc_get_chip(desc); struct irq_chip *chip = irq_get_chip(irq);
struct irq_data *idata = irq_desc_get_irq_data(desc); struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); struct at91_gpio_chip *at91_gpio = container_of(gpio_chip,
struct at91_gpio_chip, chip);
void __iomem *pio = at91_gpio->regbase; void __iomem *pio = at91_gpio->regbase;
unsigned long isr; unsigned long isr;
int n; int n;
...@@ -1469,81 +1458,19 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) ...@@ -1469,81 +1458,19 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
} }
for_each_set_bit(n, &isr, BITS_PER_LONG) { 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); chained_irq_exit(chip, desc);
/* now it may re-trigger */ /* 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, static int at91_gpio_of_irq_setup(struct device_node *node,
struct at91_gpio_chip *at91_gpio) struct at91_gpio_chip *at91_gpio)
{ {
struct at91_gpio_chip *prev = NULL;
struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq); struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
int ret;
at91_gpio->pioc_hwirq = irqd_to_hwirq(d); at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
...@@ -1553,26 +1480,25 @@ static int at91_gpio_of_irq_setup(struct device_node *node, ...@@ -1553,26 +1480,25 @@ static int at91_gpio_of_irq_setup(struct device_node *node,
/* Disable irqs of this PIO controller */ /* Disable irqs of this PIO controller */
writel_relaxed(~0, at91_gpio->regbase + PIO_IDR); writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
/* Setup irq domain */ /*
at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio, * Let the generic code handle this edge IRQ, the the chained
&at91_gpio_ops, at91_gpio); * handler will perform the actual work of handling the parent
if (!at91_gpio->domain) * 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", panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
at91_gpio->pioc_idx); at91_gpio->pioc_idx);
/* Setup chained handler */ /* Then register the chain on the parent IRQ */
if (at91_gpio->pioc_idx) gpiochip_set_chained_irqchip(&at91_gpio->chip,
prev = gpio_chips[at91_gpio->pioc_idx - 1]; &gpio_irqchip,
at91_gpio->pioc_virq,
/* The top level handler handles one bank of GPIOs, except gpio_irq_handler);
* 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);
return 0; return 0;
} }
...@@ -1586,7 +1512,6 @@ static struct gpio_chip at91_gpio_template = { ...@@ -1586,7 +1512,6 @@ static struct gpio_chip at91_gpio_template = {
.get = at91_gpio_get, .get = at91_gpio_get,
.direction_output = at91_gpio_direction_output, .direction_output = at91_gpio_direction_output,
.set = at91_gpio_set, .set = at91_gpio_set,
.to_irq = at91_gpio_to_irq,
.dbg_show = at91_gpio_dbg_show, .dbg_show = at91_gpio_dbg_show,
.can_sleep = false, .can_sleep = false,
.ngpio = MAX_NB_GPIO_PER_BANK, .ngpio = MAX_NB_GPIO_PER_BANK,
......
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