Commit 130cbe30 authored by Linus Walleij's avatar Linus Walleij

pinctrl: st: use gpiolib irqchip helpers

This lets the gpiolib core handle the irqchip set-up and
chained IRQ on the primary (behind the mux) IRQ chip in
the st pinctrl driver.

Default irq type is set to level low at irqchip add time.

The v1 was sent by Linus
(https://lkml.org/lkml/2014/4/4/287).

Two changes were necessary to make it to work properly
on STiH416:
  1 - dev reference was not passed to the gpio_chip
      struct, causing a panic.
  2 - gpiochip_irqchip_add passed IRQ_TYPE_NONE as
      default type, which caused lot of warnings at
      init time. I choose IRQ_TYPE_LEVEL_LOW as default.

Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarMaxime COQUELIN <maxime.coquelin@st.com>
parent c15c0d16
...@@ -281,6 +281,7 @@ config PINCTRL_ST ...@@ -281,6 +281,7 @@ config PINCTRL_ST
depends on OF depends on OF
select PINMUX select PINMUX
select PINCONF select PINCONF
select GPIOLIB_IRQCHIP
config PINCTRL_TEGRA config PINCTRL_TEGRA
bool bool
......
...@@ -13,10 +13,6 @@ ...@@ -13,10 +13,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
...@@ -321,7 +317,6 @@ struct st_gpio_bank { ...@@ -321,7 +317,6 @@ struct st_gpio_bank {
struct pinctrl_gpio_range range; struct pinctrl_gpio_range range;
void __iomem *base; void __iomem *base;
struct st_pio_control pc; struct st_pio_control pc;
struct irq_domain *domain;
unsigned long irq_edge_conf; unsigned long irq_edge_conf;
spinlock_t lock; spinlock_t lock;
}; };
...@@ -1285,56 +1280,26 @@ static int st_pctl_parse_functions(struct device_node *np, ...@@ -1285,56 +1280,26 @@ static int st_pctl_parse_functions(struct device_node *np,
return 0; return 0;
} }
static int st_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
int irq = -ENXIO;
if (offset < chip->ngpio)
irq = irq_find_mapping(bank->domain, offset);
dev_info(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
chip->label, offset + chip->base, irq);
return irq;
}
static void st_gpio_irq_mask(struct irq_data *d) static void st_gpio_irq_mask(struct irq_data *d)
{ {
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
writel(BIT(d->hwirq), bank->base + REG_PIO_CLR_PMASK); writel(BIT(d->hwirq), bank->base + REG_PIO_CLR_PMASK);
} }
static void st_gpio_irq_unmask(struct irq_data *d) static void st_gpio_irq_unmask(struct irq_data *d)
{ {
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
writel(BIT(d->hwirq), bank->base + REG_PIO_SET_PMASK); writel(BIT(d->hwirq), bank->base + REG_PIO_SET_PMASK);
} }
static int st_gpio_irq_reqres(struct irq_data *d)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
if (gpio_lock_as_irq(&bank->gpio_chip, d->hwirq)) {
dev_err(bank->gpio_chip.dev,
"unable to lock HW IRQ %lu for IRQ\n",
d->hwirq);
return -EINVAL;
}
return 0;
}
static void st_gpio_irq_relres(struct irq_data *d)
{
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(&bank->gpio_chip, d->hwirq);
}
static int st_gpio_irq_set_type(struct irq_data *d, unsigned type) static int st_gpio_irq_set_type(struct irq_data *d, unsigned type)
{ {
struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
unsigned long flags; unsigned long flags;
int comp, pin = d->hwirq; int comp, pin = d->hwirq;
u32 val; u32 val;
...@@ -1438,7 +1403,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank) ...@@ -1438,7 +1403,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
continue; continue;
} }
generic_handle_irq(irq_find_mapping(bank->domain, n)); generic_handle_irq(irq_find_mapping(bank->gpio_chip.irqdomain, n));
} }
} }
} }
...@@ -1447,7 +1412,8 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc) ...@@ -1447,7 +1412,8 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{ {
/* interrupt dedicated per bank */ /* interrupt dedicated per bank */
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_get_chip(irq);
struct st_gpio_bank *bank = irq_get_handler_data(irq); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
__gpio_irq_handler(bank); __gpio_irq_handler(bank);
...@@ -1481,7 +1447,6 @@ static struct gpio_chip st_gpio_template = { ...@@ -1481,7 +1447,6 @@ static struct gpio_chip st_gpio_template = {
.ngpio = ST_GPIO_PINS_PER_BANK, .ngpio = ST_GPIO_PINS_PER_BANK,
.of_gpio_n_cells = 1, .of_gpio_n_cells = 1,
.of_xlate = st_gpio_xlate, .of_xlate = st_gpio_xlate,
.to_irq = st_gpio_to_irq,
}; };
static struct irq_chip st_gpio_irqchip = { static struct irq_chip st_gpio_irqchip = {
...@@ -1489,26 +1454,6 @@ static struct irq_chip st_gpio_irqchip = { ...@@ -1489,26 +1454,6 @@ static struct irq_chip st_gpio_irqchip = {
.irq_mask = st_gpio_irq_mask, .irq_mask = st_gpio_irq_mask,
.irq_unmask = st_gpio_irq_unmask, .irq_unmask = st_gpio_irq_unmask,
.irq_set_type = st_gpio_irq_set_type, .irq_set_type = st_gpio_irq_set_type,
.irq_request_resources = st_gpio_irq_reqres,
.irq_release_resources = st_gpio_irq_relres,
};
static int st_gpio_irq_domain_map(struct irq_domain *h,
unsigned int virq, irq_hw_number_t hw)
{
struct st_gpio_bank *bank = h->host_data;
irq_set_chip(virq, &st_gpio_irqchip);
irq_set_handler(virq, handle_simple_irq);
set_irq_flags(virq, IRQF_VALID);
irq_set_chip_data(virq, bank);
return 0;
}
static struct irq_domain_ops st_gpio_irq_ops = {
.map = st_gpio_irq_domain_map,
.xlate = irq_domain_xlate_twocell,
}; };
static int st_gpiolib_register_bank(struct st_pinctrl *info, static int st_gpiolib_register_bank(struct st_pinctrl *info,
...@@ -1519,7 +1464,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, ...@@ -1519,7 +1464,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
struct device *dev = info->dev; struct device *dev = info->dev;
int bank_num = of_alias_get_id(np, "gpio"); int bank_num = of_alias_get_id(np, "gpio");
struct resource res, irq_res; struct resource res, irq_res;
int gpio_irq = 0, err, i; int gpio_irq = 0, err;
if (of_address_to_resource(np, 0, &res)) if (of_address_to_resource(np, 0, &res))
return -ENODEV; return -ENODEV;
...@@ -1532,6 +1477,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, ...@@ -1532,6 +1477,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK; bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK;
bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK; bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK;
bank->gpio_chip.of_node = np; bank->gpio_chip.of_node = np;
bank->gpio_chip.dev = dev;
spin_lock_init(&bank->lock); spin_lock_init(&bank->lock);
of_property_read_string(np, "st,bank-name", &range->name); of_property_read_string(np, "st,bank-name", &range->name);
...@@ -1569,26 +1515,18 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, ...@@ -1569,26 +1515,18 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
if (of_irq_to_resource(np, 0, &irq_res)) { if (of_irq_to_resource(np, 0, &irq_res)) {
gpio_irq = irq_res.start; gpio_irq = irq_res.start;
irq_set_chained_handler(gpio_irq, st_gpio_irq_handler); gpiochip_set_chained_irqchip(&bank->gpio_chip, &st_gpio_irqchip,
irq_set_handler_data(gpio_irq, bank); gpio_irq, st_gpio_irq_handler);
} }
if (info->irqmux_base > 0 || gpio_irq > 0) { if (info->irqmux_base > 0 || gpio_irq > 0) {
/* Setup IRQ domain */ err = gpiochip_irqchip_add(&bank->gpio_chip, &st_gpio_irqchip,
bank->domain = irq_domain_add_linear(np, 0, handle_simple_irq,
ST_GPIO_PINS_PER_BANK, IRQ_TYPE_LEVEL_LOW);
&st_gpio_irq_ops, bank); if (err) {
if (!bank->domain) { dev_info(dev, "could not add irqchip\n");
dev_err(dev, "Failed to add irq domain for %s\n", return err;
np->full_name);
} else {
for (i = 0; i < ST_GPIO_PINS_PER_BANK; i++) {
if (irq_create_mapping(bank->domain, i) < 0)
dev_err(dev,
"Failed to map IRQ %i\n", i);
}
} }
} else { } else {
dev_info(dev, "No IRQ support for %s bank\n", np->full_name); dev_info(dev, "No IRQ support for %s bank\n", np->full_name);
} }
......
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