From 57ef04288abd27a717287a652d324f95cb77c3c6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 14 Mar 2014 18:16:20 +0100 Subject: gpio: switch drivers to use new callback This switches all GPIO and pin control drivers with irqchips that were using .startup() and .shutdown() callbacks to lock GPIO lines for IRQ usage over to using the .request_resources() and .release_resources() callbacks just introduced into the irqchip vtable. Cc: Thomas Gleixner Cc: Jean-Jacques Hiblot Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers/pinctrl/pinctrl-nomadik.c') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 53a1111..2ea3f37 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -848,10 +848,6 @@ static unsigned int nmk_gpio_irq_startup(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); clk_enable(nmk_chip->clk); nmk_gpio_irq_unmask(d); return 0; @@ -863,6 +859,25 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d) nmk_gpio_irq_mask(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); } @@ -875,6 +890,8 @@ 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, }; -- cgit v1.1 From 194e15ba00d90a6e8779b9cd87f1feec0d55427f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 21 Mar 2014 10:24:42 +0100 Subject: pinctrl: nomadik: rename secondary to latent The "secondary irq" in the nomadik pin control driver is actually not secondary (as in: can occur any time alongside the ordinary irq), it is a latent IRQ. It is an IRQ that has occurred when the system was in sleep state and has been cached in a special register flagged from the low power management unit (PRCM). Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/pinctrl/pinctrl-nomadik.c') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 2ea3f37..41e808d 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -254,7 +254,7 @@ struct nmk_gpio_platform_data { int first_gpio; int first_irq; int num_gpio; - u32 (*get_secondary_status)(unsigned int bank); + u32 (*get_latent_status)(unsigned int bank); void (*set_ioforce)(bool enable); bool supports_sleepmode; }; @@ -266,8 +266,8 @@ struct nmk_gpio_chip { struct clk *clk; unsigned int bank; unsigned int parent_irq; - int secondary_parent_irq; - u32 (*get_secondary_status)(unsigned int bank); + int latent_parent_irq; + u32 (*get_latent_status)(unsigned int bank); void (*set_ioforce)(bool enable); spinlock_t lock; bool sleepmode; @@ -926,11 +926,11 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) __nmk_gpio_irq_handler(irq, desc, status); } -static void nmk_gpio_secondary_irq_handler(unsigned int irq, +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); - u32 status = nmk_chip->get_secondary_status(nmk_chip->bank); + u32 status = nmk_chip->get_latent_status(nmk_chip->bank); __nmk_gpio_irq_handler(irq, desc, status); } @@ -940,10 +940,10 @@ 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->secondary_parent_irq >= 0) { - irq_set_chained_handler(nmk_chip->secondary_parent_irq, - nmk_gpio_secondary_irq_handler); - irq_set_handler_data(nmk_chip->secondary_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; @@ -1263,7 +1263,7 @@ static int nmk_gpio_probe(struct platform_device *dev) struct gpio_chip *chip; struct resource *res; struct clk *clk; - int secondary_irq; + int latent_irq; void __iomem *base; int irq; int ret; @@ -1287,8 +1287,8 @@ static int nmk_gpio_probe(struct platform_device *dev) if (irq < 0) return irq; - secondary_irq = platform_get_irq(dev, 1); - if (secondary_irq >= 0 && !pdata->get_secondary_status) + latent_irq = platform_get_irq(dev, 1); + if (latent_irq >= 0 && !pdata->get_latent_status) return -EINVAL; res = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -1314,8 +1314,8 @@ static int nmk_gpio_probe(struct platform_device *dev) nmk_chip->addr = base; nmk_chip->chip = nmk_gpio_template; nmk_chip->parent_irq = irq; - nmk_chip->secondary_parent_irq = secondary_irq; - nmk_chip->get_secondary_status = pdata->get_secondary_status; + nmk_chip->latent_parent_irq = latent_irq; + nmk_chip->get_latent_status = pdata->get_latent_status; nmk_chip->set_ioforce = pdata->set_ioforce; nmk_chip->sleepmode = pdata->supports_sleepmode; spin_lock_init(&nmk_chip->lock); -- cgit v1.1 From 8f18bcfcd2bc30cb9a5924a6b4af49c8388bc785 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 21 Mar 2014 10:40:24 +0100 Subject: pinctrl: nomadik: factor in platform data container The old platform data struct is just a leftover from the times when the driver was not probed exclusively from the device tree. Factor this into the general state container and simplify the probe path. Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) (limited to 'drivers/pinctrl/pinctrl-nomadik.c') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 41e808d..98a36a0 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -246,19 +246,6 @@ enum nmk_gpio_slpm { NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, }; -/* - * Platform data to register a block: only the initial gpio/irq number. - */ -struct nmk_gpio_platform_data { - char *name; - int first_gpio; - int first_irq; - int num_gpio; - u32 (*get_latent_status)(unsigned int bank); - void (*set_ioforce)(bool enable); - bool supports_sleepmode; -}; - struct nmk_gpio_chip { struct gpio_chip chip; struct irq_domain *domain; @@ -1257,39 +1244,33 @@ static const struct irq_domain_ops nmk_gpio_irq_simple_ops = { static int nmk_gpio_probe(struct platform_device *dev) { - struct nmk_gpio_platform_data *pdata; struct device_node *np = dev->dev.of_node; struct nmk_gpio_chip *nmk_chip; struct gpio_chip *chip; struct resource *res; struct clk *clk; int latent_irq; + bool supports_sleepmode; void __iomem *base; int irq; int ret; - pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - if (of_get_property(np, "st,supports-sleepmode", NULL)) - pdata->supports_sleepmode = true; + supports_sleepmode = true; + else + supports_sleepmode = false; if (of_property_read_u32(np, "gpio-bank", &dev->id)) { dev_err(&dev->dev, "gpio-bank property not found\n"); return -EINVAL; } - pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP; - pdata->num_gpio = NMK_GPIO_PER_CHIP; - irq = platform_get_irq(dev, 0); if (irq < 0) return irq; + /* It's OK for this IRQ not to be present */ latent_irq = platform_get_irq(dev, 1); - if (latent_irq >= 0 && !pdata->get_latent_status) - return -EINVAL; res = platform_get_resource(dev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&dev->dev, res); @@ -1315,15 +1296,13 @@ static int nmk_gpio_probe(struct platform_device *dev) nmk_chip->chip = nmk_gpio_template; nmk_chip->parent_irq = irq; nmk_chip->latent_parent_irq = latent_irq; - nmk_chip->get_latent_status = pdata->get_latent_status; - nmk_chip->set_ioforce = pdata->set_ioforce; - nmk_chip->sleepmode = pdata->supports_sleepmode; + nmk_chip->sleepmode = supports_sleepmode; spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; - chip->base = pdata->first_gpio; - chip->ngpio = pdata->num_gpio; - chip->label = pdata->name ?: dev_name(&dev->dev); + chip->base = dev->id * NMK_GPIO_PER_CHIP; + chip->ngpio = NMK_GPIO_PER_CHIP; + chip->label = dev_name(&dev->dev); chip->dev = &dev->dev; chip->owner = THIS_MODULE; -- cgit v1.1 From e0bc34a3dada03a48ff5501381ff7fdef885ed25 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Mar 2014 10:44:09 +0100 Subject: 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 --- drivers/pinctrl/pinctrl-nomadik.c | 123 ++++++++++---------------------------- 1 file changed, 33 insertions(+), 90 deletions(-) (limited to 'drivers/pinctrl/pinctrl-nomadik.c') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 98a36a0..db0cc30 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -21,9 +21,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -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 @@ -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); -- cgit v1.1