diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-03-25 10:44:09 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-03-26 10:31:33 +0100 |
commit | e0bc34a3dada03a48ff5501381ff7fdef885ed25 (patch) | |
tree | 646ef286908d6635f28bb994e19f5fe1f83fc50e | |
parent | 8d5b24bd30c23930e666813ea0adc4672ea58c62 (diff) | |
download | linux-e0bc34a3dada03a48ff5501381ff7fdef885ed25.tar.bz2 |
pinctrl: nomadik: convert driver to use gpiolib irqchip
This converts the Nomadik pin control driver to register its
chained irq handler and irqchip using the helpers in the
gpiolib core.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/Kconfig | 3 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-nomadik.c | 123 |
2 files changed, 36 insertions, 90 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 1e4e69384baa..a05087bd1955 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -235,6 +235,9 @@ config PINCTRL_NOMADIK depends on ARCH_U8500 || ARCH_NOMADIK select PINMUX select PINCONF + select GPIOLIB + select OF_GPIO + select GPIOLIB_IRQCHIP config PINCTRL_STN8815 bool "STN8815 pin controller driver" diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 98a36a0969f9..db0cc30c82de 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -21,9 +21,6 @@ #include <linux/gpio.h> #include <linux/spinlock.h> #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/irqdomain.h> -#include <linux/irqchip/chained_irq.h> #include <linux/slab.h> #include <linux/of_device.h> #include <linux/of_address.h> @@ -248,7 +245,6 @@ enum nmk_gpio_slpm { struct nmk_gpio_chip { struct gpio_chip chip; - struct irq_domain *domain; void __iomem *addr; struct clk *clk; unsigned int bank; @@ -419,7 +415,7 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) u32 falling = nmk_chip->fimsc & BIT(offset); u32 rising = nmk_chip->rimsc & BIT(offset); int gpio = nmk_chip->chip.base + offset; - int irq = irq_find_mapping(nmk_chip->domain, offset); + int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset); struct irq_data *d = irq_get_irq_data(irq); if (!rising && !falling) @@ -647,11 +643,8 @@ static inline int nmk_gpio_get_bitmask(int gpio) static void nmk_gpio_irq_ack(struct irq_data *d) { - struct nmk_gpio_chip *nmk_chip; - - nmk_chip = irq_data_get_irq_chip_data(d); - if (!nmk_chip) - return; + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); clk_enable(nmk_chip->clk); writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); @@ -848,26 +841,6 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d) clk_disable(nmk_chip->clk); } -static int nmk_gpio_irq_reqres(struct irq_data *d) -{ - struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); - - if (gpio_lock_as_irq(&nmk_chip->chip, d->hwirq)) { - dev_err(nmk_chip->chip.dev, - "unable to lock HW IRQ %lu for IRQ\n", - d->hwirq); - return -EINVAL; - } - return 0; -} - -static void nmk_gpio_irq_relres(struct irq_data *d) -{ - struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); - - gpio_unlock_as_irq(&nmk_chip->chip, d->hwirq); -} - static struct irq_chip nmk_gpio_irq_chip = { .name = "Nomadik-GPIO", .irq_ack = nmk_gpio_irq_ack, @@ -877,24 +850,21 @@ static struct irq_chip nmk_gpio_irq_chip = { .irq_set_wake = nmk_gpio_irq_set_wake, .irq_startup = nmk_gpio_irq_startup, .irq_shutdown = nmk_gpio_irq_shutdown, - .irq_request_resources = nmk_gpio_irq_reqres, - .irq_release_resources = nmk_gpio_irq_relres, .flags = IRQCHIP_MASK_ON_SUSPEND, }; static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, u32 status) { - struct nmk_gpio_chip *nmk_chip; struct irq_chip *host_chip = irq_get_chip(irq); + struct gpio_chip *chip = irq_desc_get_handler_data(desc); chained_irq_enter(host_chip, desc); - nmk_chip = irq_get_handler_data(irq); while (status) { int bit = __ffs(status); - generic_handle_irq(irq_find_mapping(nmk_chip->domain, bit)); + generic_handle_irq(irq_find_mapping(chip->irqdomain, bit)); status &= ~BIT(bit); } @@ -903,9 +873,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { - struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); u32 status; + pr_err("PLONK IRQ %d\n", irq); clk_enable(nmk_chip->clk); status = readl(nmk_chip->addr + NMK_GPIO_IS); clk_disable(nmk_chip->clk); @@ -916,26 +888,13 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *desc) { - struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); u32 status = nmk_chip->get_latent_status(nmk_chip->bank); __nmk_gpio_irq_handler(irq, desc, status); } -static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) -{ - irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); - irq_set_handler_data(nmk_chip->parent_irq, nmk_chip); - - if (nmk_chip->latent_parent_irq >= 0) { - irq_set_chained_handler(nmk_chip->latent_parent_irq, - nmk_gpio_latent_irq_handler); - irq_set_handler_data(nmk_chip->latent_parent_irq, nmk_chip); - } - - return 0; -} - /* I/O Functions */ static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -1014,14 +973,6 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, return 0; } -static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - - return irq_create_mapping(nmk_chip->domain, offset); -} - #ifdef CONFIG_DEBUG_FS #include <linux/seq_file.h> @@ -1120,7 +1071,6 @@ static struct gpio_chip nmk_gpio_template = { .get = nmk_gpio_get_input, .direction_output = nmk_gpio_make_output, .set = nmk_gpio_set_output, - .to_irq = nmk_gpio_to_irq, .dbg_show = nmk_gpio_dbg_show, .can_sleep = false, }; @@ -1221,27 +1171,6 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) } } -static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) -{ - struct nmk_gpio_chip *nmk_chip = d->host_data; - - if (!nmk_chip) - return -EINVAL; - - irq_set_chip_and_handler(irq, &nmk_gpio_irq_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID); - irq_set_chip_data(irq, nmk_chip); - irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); - - return 0; -} - -static const struct irq_domain_ops nmk_gpio_irq_simple_ops = { - .map = nmk_gpio_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - static int nmk_gpio_probe(struct platform_device *dev) { struct device_node *np = dev->dev.of_node; @@ -1321,17 +1250,31 @@ static int nmk_gpio_probe(struct platform_device *dev) platform_set_drvdata(dev, nmk_chip); - nmk_chip->domain = irq_domain_add_simple(np, - NMK_GPIO_PER_CHIP, 0, - &nmk_gpio_irq_simple_ops, nmk_chip); - if (!nmk_chip->domain) { - dev_err(&dev->dev, "failed to create irqdomain\n"); - /* Just do this, no matter if it fails */ + /* + * 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(&nmk_chip->chip, + &nmk_gpio_irq_chip, + 0, + handle_edge_irq, + IRQ_TYPE_EDGE_FALLING); + if (ret) { + dev_err(&dev->dev, "could not add irqchip\n"); ret = gpiochip_remove(&nmk_chip->chip); - return -ENOSYS; + return -ENODEV; } - - nmk_gpio_init_irq(nmk_chip); + /* Then register the chain on the parent IRQ */ + gpiochip_set_chained_irqchip(&nmk_chip->chip, + &nmk_gpio_irq_chip, + nmk_chip->parent_irq, + nmk_gpio_irq_handler); + if (nmk_chip->latent_parent_irq > 0) + gpiochip_set_chained_irqchip(&nmk_chip->chip, + &nmk_gpio_irq_chip, + nmk_chip->latent_parent_irq, + nmk_gpio_latent_irq_handler); dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); |