diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 16:44:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 16:44:15 -0700 |
commit | 154d6f18a48e00dec2dc84a96914fe1a24669577 (patch) | |
tree | 7b92ac64a00eb173af396752f3bfc72c9eba615c /drivers/pinctrl | |
parent | 76ca7d1cca761bb9712dfcad9a27d70b520874ae (diff) | |
parent | b22978fc33dec72e5f8e17f90eb63ea9137aafd5 (diff) | |
download | op-kernel-dev-154d6f18a48e00dec2dc84a96914fe1a24669577.zip op-kernel-dev-154d6f18a48e00dec2dc84a96914fe1a24669577.tar.gz |
Merge tag 'gpio-v3.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull bulk of gpio updates from Linus Walleij:
"A pretty big chunk of changes this time, but it has all been on
rotation in linux-next and had some testing. Of course there will be
some amount of fixes on top...
- Merged in a branch of irqchip changes from Thomas Gleixner: we need
to have new callbacks from the irqchip to determine if the GPIO
line will be eligible for IRQs, and this callback must be able to
say "no". After some thinking I got the branch from tglx and have
switched all current users over to use this.
- Based on tglx patches, we have added some generic irqchip helpers
in the gpiolib core. These will help centralize code when GPIO
drivers have simple chained/cascaded IRQs. Drivers will still
define their irqchip vtables, but the gpiolib core will take care
of irqdomain set-up, mapping from local offsets to Linux irqs, and
reserve resources by marking the GPIO lines for IRQs.
- Initially the PL061 and Nomadik GPIO/pin control drivers have been
switched over to use the new gpiochip-to-irqchip infrastructure
with more drivers expected for the next kernel cycle. The
factoring of just two drivers still makes it worth it so it is
already a win.
- A new driver for the Synopsys DesignWare APB GPIO block.
- Modify the DaVinci GPIO driver to be reusable also for the new TI
Keystone architecture.
- A new driver for the LSI ZEVIO SoCs.
- Delete the obsolte tnetv107x driver.
- Some incremental work on GPIO descriptors: have
gpiod_direction_output() use a logical level, respecting assertion
polarity through ACTIVE_LOW flags, adding gpiod_direction_output_raw()
for the case where you want to set that very value. Add
gpiochip_get_desc() to fetch a GPIO descriptor from a specific
offset on a certain chip inside driver code.
- Switch ACPI GPIO code over to using gpiochip_get_desc() and get rid
of gpio_to_desc().
- The ACPI GPIO event handling code has been reworked after
encountering an actual real life implementation.
- Support for ACPI GPIO operation regions.
- Generic GPIO chips can now be assigned labels/names from platform
data.
- We now clamp values returned from GPIO drivers to the boolean [0,1]
range.
- Some improved documentation on how to use the polarity flag was
added.
- a large slew of incremental driver updates and non-critical fixes.
Some targeted for stable"
* tag 'gpio-v3.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (80 commits)
gpio: rcar: Add helper variable dev = &pdev->dev
gpio-lynxpoint: force gpio_get() to return "1" and "0" only
gpio: unmap gpio irqs properly
pch_gpio: set value before enabling output direction
gpio: moxart: Actually set output state in moxart_gpio_direction_output()
gpio: moxart: Avoid forward declaration
gpio: mxs: Allow for recursive enable_irq_wake() call
gpio: samsung: Add missing "break" statement
gpio: twl4030: Remove redundant assignment
gpio: dwapb: correct gpio-cells in binding document
gpio: iop: fix devm_ioremap_resource() return value checking
pinctrl: coh901: convert driver to use gpiolib irqchip
pinctrl: nomadik: convert driver to use gpiolib irqchip
gpio: pl061: convert driver to use gpiolib irqchip
gpio: add IRQ chip helpers in gpiolib
pinctrl: nomadik: factor in platform data container
pinctrl: nomadik: rename secondary to latent
gpio: Driver for SYSCON-based GPIOs
gpio: generic: Use platform_device_id->driver_data field for driver flags
pinctrl: coh901: move irq line locking to resource callbacks
...
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/Kconfig | 4 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-adi2.c | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-baytrail.c | 14 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-coh901.c | 186 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-msm.c | 11 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-nomadik.c | 159 | ||||
-rw-r--r-- | drivers/pinctrl/sirf/pinctrl-sirf.c | 14 |
7 files changed, 126 insertions, 263 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 06cee01..e493240 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" @@ -321,6 +324,7 @@ config PINCTRL_U300 config PINCTRL_COH901 bool "ST-Ericsson U300 COH 901 335/571 GPIO" depends on GPIOLIB && ARCH_U300 && PINCTRL_U300 + select GPIOLIB_IRQCHIP help Say yes here to support GPIO interface on ST-Ericsson U300. The names of the two IP block variants supported are diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c index 200ea1e..0cc0eec 100644 --- a/drivers/pinctrl/pinctrl-adi2.c +++ b/drivers/pinctrl/pinctrl-adi2.c @@ -337,6 +337,7 @@ static unsigned int adi_gpio_irq_startup(struct irq_data *d) if (!port) { pr_err("GPIO IRQ %d :Not exist\n", d->irq); + /* FIXME: negative return code will be ignored */ return -ENODEV; } diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index bf2b3f6..6e8301f 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -407,23 +407,23 @@ static void byt_irq_mask(struct irq_data *d) { } -static unsigned int byt_irq_startup(struct irq_data *d) +static int byt_irq_reqres(struct irq_data *d) { struct byt_gpio *vg = irq_data_get_irq_chip_data(d); - if (gpio_lock_as_irq(&vg->chip, irqd_to_hwirq(d))) + if (gpio_lock_as_irq(&vg->chip, irqd_to_hwirq(d))) { dev_err(vg->chip.dev, "unable to lock HW IRQ %lu for IRQ\n", irqd_to_hwirq(d)); - byt_irq_unmask(d); + return -EINVAL; + } return 0; } -static void byt_irq_shutdown(struct irq_data *d) +static void byt_irq_relres(struct irq_data *d) { struct byt_gpio *vg = irq_data_get_irq_chip_data(d); - byt_irq_mask(d); gpio_unlock_as_irq(&vg->chip, irqd_to_hwirq(d)); } @@ -432,8 +432,8 @@ static struct irq_chip byt_irqchip = { .irq_mask = byt_irq_mask, .irq_unmask = byt_irq_unmask, .irq_set_type = byt_irq_type, - .irq_startup = byt_irq_startup, - .irq_shutdown = byt_irq_shutdown, + .irq_request_resources = byt_irq_reqres, + .irq_release_resources = byt_irq_relres, }; static void byt_gpio_irq_init_hw(struct byt_gpio *vg) diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index 162ac0d..d182fdd2 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c @@ -8,17 +8,14 @@ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> */ #include <linux/module.h> -#include <linux/irq.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/io.h> -#include <linux/irqdomain.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/gpio.h> -#include <linux/list.h> #include <linux/slab.h> #include <linux/pinctrl/consumer.h> #include <linux/pinctrl/pinconf-generic.h> @@ -61,9 +58,17 @@ #define U300_GPIO_PINS_PER_PORT 8 #define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS) +struct u300_gpio_port { + struct u300_gpio *gpio; + char name[8]; + int irq; + int number; + u8 toggle_edge_mode; +}; + struct u300_gpio { struct gpio_chip chip; - struct list_head port_list; + struct u300_gpio_port ports[U300_GPIO_NUM_PORTS]; struct clk *clk; void __iomem *base; struct device *dev; @@ -78,16 +83,6 @@ struct u300_gpio { u32 iev; }; -struct u300_gpio_port { - struct list_head node; - struct u300_gpio *gpio; - char name[8]; - struct irq_domain *domain; - int irq; - int number; - u8 toggle_edge_mode; -}; - /* * Macro to expand to read a specific register found in the "gpio" * struct. It requires the struct u300_gpio *gpio variable to exist in @@ -308,39 +303,6 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, return 0; } -static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - int portno = offset >> 3; - struct u300_gpio_port *port = NULL; - struct list_head *p; - int retirq; - bool found = false; - - list_for_each(p, &gpio->port_list) { - port = list_entry(p, struct u300_gpio_port, node); - if (port->number == portno) { - found = true; - break; - } - } - if (!found) { - dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n", - offset); - return -EINVAL; - } - - /* - * The local hwirqs on the port are the lower three bits, there - * are exactly 8 IRQs per port since they are 8-bit - */ - retirq = irq_find_mapping(port->domain, (offset & 0x7)); - - dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n", - offset, retirq, port->number); - return retirq; -} - /* Returning -EINVAL means "supported but not available" */ int u300_gpio_config_get(struct gpio_chip *chip, unsigned offset, @@ -461,7 +423,6 @@ static struct gpio_chip u300_gpio_chip = { .set = u300_gpio_set, .direction_input = u300_gpio_direction_input, .direction_output = u300_gpio_direction_output, - .to_irq = u300_gpio_to_irq, }; static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset) @@ -485,9 +446,10 @@ static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset) static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) { - struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); - struct u300_gpio *gpio = port->gpio; - int offset = (port->number << 3) + d->hwirq; + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = to_u300_gpio(chip); + struct u300_gpio_port *port = &gpio->ports[d->hwirq >> 3]; + int offset = d->hwirq; u32 val; if ((trigger & IRQF_TRIGGER_RISING) && @@ -521,18 +483,15 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) static void u300_gpio_irq_enable(struct irq_data *d) { - struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); - struct u300_gpio *gpio = port->gpio; - int offset = (port->number << 3) + d->hwirq; + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = to_u300_gpio(chip); + struct u300_gpio_port *port = &gpio->ports[d->hwirq >> 3]; + int offset = d->hwirq; u32 val; unsigned long flags; dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n", d->hwirq, port->name, offset); - if (gpio_lock_as_irq(&gpio->chip, d->hwirq)) - dev_err(gpio->dev, - "unable to lock HW IRQ %lu for IRQ\n", - d->hwirq); local_irq_save(flags); val = readl(U300_PIN_REG(offset, ien)); writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); @@ -541,9 +500,9 @@ static void u300_gpio_irq_enable(struct irq_data *d) static void u300_gpio_irq_disable(struct irq_data *d) { - struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); - struct u300_gpio *gpio = port->gpio; - int offset = (port->number << 3) + d->hwirq; + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = to_u300_gpio(chip); + int offset = d->hwirq; u32 val; unsigned long flags; @@ -551,7 +510,6 @@ static void u300_gpio_irq_disable(struct irq_data *d) val = readl(U300_PIN_REG(offset, ien)); writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); local_irq_restore(flags); - gpio_unlock_as_irq(&gpio->chip, d->hwirq); } static struct irq_chip u300_gpio_irqchip = { @@ -559,17 +517,19 @@ static struct irq_chip u300_gpio_irqchip = { .irq_enable = u300_gpio_irq_enable, .irq_disable = u300_gpio_irq_disable, .irq_set_type = u300_gpio_irq_type, - }; static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct u300_gpio_port *port = irq_get_handler_data(irq); - struct u300_gpio *gpio = port->gpio; + struct irq_chip *parent_chip = irq_get_chip(irq); + struct gpio_chip *chip = irq_get_handler_data(irq); + struct u300_gpio *gpio = to_u300_gpio(chip); + struct u300_gpio_port *port = &gpio->ports[irq - chip->base]; int pinoffset = port->number << 3; /* get the right stride */ unsigned long val; - desc->irq_data.chip->irq_ack(&desc->irq_data); + chained_irq_enter(parent_chip, desc); + /* Read event register */ val = readl(U300_PIN_REG(pinoffset, iev)); /* Mask relevant bits */ @@ -582,8 +542,8 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) int irqoffset; for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { - int pin_irq = irq_find_mapping(port->domain, irqoffset); int offset = pinoffset + irqoffset; + int pin_irq = irq_find_mapping(chip->irqdomain, offset); dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", pin_irq, offset); @@ -597,7 +557,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) } } - desc->irq_data.chip->irq_unmask(&desc->irq_data); + chained_irq_exit(parent_chip, desc); } static void __init u300_gpio_init_pin(struct u300_gpio *gpio, @@ -648,20 +608,6 @@ static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio) } } -static inline void u300_gpio_free_ports(struct u300_gpio *gpio) -{ - struct u300_gpio_port *port; - struct list_head *p, *n; - - list_for_each_safe(p, n, &gpio->port_list) { - port = list_entry(p, struct u300_gpio_port, node); - list_del(&port->node); - if (port->domain) - irq_domain_remove(port->domain); - kfree(port); - } -} - /* * Here we map a GPIO in the local gpio_chip pin space to a pin in * the local pinctrl pin space. The pin controller used is @@ -752,17 +698,28 @@ static int __init u300_gpio_probe(struct platform_device *pdev) gpio->base + U300_GPIO_CR); u300_gpio_init_coh901571(gpio); +#ifdef CONFIG_OF_GPIO + gpio->chip.of_node = pdev->dev.of_node; +#endif + err = gpiochip_add(&gpio->chip); + if (err) { + dev_err(gpio->dev, "unable to add gpiochip: %d\n", err); + goto err_no_chip; + } + + err = gpiochip_irqchip_add(&gpio->chip, + &u300_gpio_irqchip, + 0, + handle_simple_irq, + IRQ_TYPE_EDGE_FALLING); + if (err) { + dev_err(gpio->dev, "no GPIO irqchip\n"); + goto err_no_irqchip; + } + /* Add each port with its IRQ separately */ - INIT_LIST_HEAD(&gpio->port_list); for (portno = 0 ; portno < U300_GPIO_NUM_PORTS; portno++) { - struct u300_gpio_port *port = - kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL); - - if (!port) { - dev_err(gpio->dev, "out of memory\n"); - err = -ENOMEM; - goto err_no_port; - } + struct u300_gpio_port *port = &gpio->ports[portno]; snprintf(port->name, 8, "gpio%d", portno); port->number = portno; @@ -770,50 +727,16 @@ static int __init u300_gpio_probe(struct platform_device *pdev) port->irq = platform_get_irq(pdev, portno); - dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq, - port->name); - - port->domain = irq_domain_add_linear(pdev->dev.of_node, - U300_GPIO_PINS_PER_PORT, - &irq_domain_simple_ops, - port); - if (!port->domain) { - err = -ENOMEM; - goto err_no_domain; - } - - irq_set_chained_handler(port->irq, u300_gpio_irq_handler); - irq_set_handler_data(port->irq, port); - - /* For each GPIO pin set the unique IRQ handler */ - for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { - int irqno = irq_create_mapping(port->domain, i); - - dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n", - gpio->chip.base + (port->number << 3) + i, - port->name, irqno); - irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, - handle_simple_irq); - set_irq_flags(irqno, IRQF_VALID); - irq_set_chip_data(irqno, port); - } + gpiochip_set_chained_irqchip(&gpio->chip, + &u300_gpio_irqchip, + port->irq, + u300_gpio_irq_handler); /* Turns off irq force (test register) for this port */ writel(0x0, gpio->base + portno * gpio->stride + ifr); - - list_add_tail(&port->node, &gpio->port_list); } dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno); -#ifdef CONFIG_OF_GPIO - gpio->chip.of_node = pdev->dev.of_node; -#endif - err = gpiochip_add(&gpio->chip); - if (err) { - dev_err(gpio->dev, "unable to add gpiochip: %d\n", err); - goto err_no_chip; - } - /* * Add pinctrl pin ranges, the pin controller must be registered * at this point @@ -832,12 +755,10 @@ static int __init u300_gpio_probe(struct platform_device *pdev) return 0; err_no_range: +err_no_irqchip: if (gpiochip_remove(&gpio->chip)) dev_err(&pdev->dev, "failed to remove gpio chip\n"); err_no_chip: -err_no_domain: -err_no_port: - u300_gpio_free_ports(gpio); clk_disable_unprepare(gpio->clk); dev_err(&pdev->dev, "module ERROR:%d\n", err); return err; @@ -856,7 +777,6 @@ static int __exit u300_gpio_remove(struct platform_device *pdev) dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err); return err; } - u300_gpio_free_ports(gpio); clk_disable_unprepare(gpio->clk); return 0; } diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c index 343f421..38d579b 100644 --- a/drivers/pinctrl/pinctrl-msm.c +++ b/drivers/pinctrl/pinctrl-msm.c @@ -785,23 +785,22 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } -static unsigned int msm_gpio_irq_startup(struct irq_data *d) +static int msm_gpio_irq_reqres(struct irq_data *d) { struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); if (gpio_lock_as_irq(&pctrl->chip, d->hwirq)) { dev_err(pctrl->dev, "unable to lock HW IRQ %lu for IRQ\n", d->hwirq); + return -EINVAL; } - msm_gpio_irq_unmask(d); return 0; } -static void msm_gpio_irq_shutdown(struct irq_data *d) +static void msm_gpio_irq_relres(struct irq_data *d) { struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); - msm_gpio_irq_mask(d); gpio_unlock_as_irq(&pctrl->chip, d->hwirq); } @@ -812,8 +811,8 @@ static struct irq_chip msm_gpio_irq_chip = { .irq_ack = msm_gpio_irq_ack, .irq_set_type = msm_gpio_irq_set_type, .irq_set_wake = msm_gpio_irq_set_wake, - .irq_startup = msm_gpio_irq_startup, - .irq_shutdown = msm_gpio_irq_shutdown, + .irq_request_resources = msm_gpio_irq_reqres, + .irq_release_resources = msm_gpio_irq_relres, }; static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index cec7762..208341f 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> @@ -246,28 +243,14 @@ 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_secondary_status)(unsigned int bank); - void (*set_ioforce)(bool enable); - bool supports_sleepmode; -}; - struct nmk_gpio_chip { struct gpio_chip chip; - struct irq_domain *domain; void __iomem *addr; 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; @@ -432,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) @@ -660,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,10 +828,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,7 +839,6 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d) nmk_gpio_irq_mask(d); clk_disable(nmk_chip->clk); - gpio_unlock_as_irq(&nmk_chip->chip, d->hwirq); } static struct irq_chip nmk_gpio_irq_chip = { @@ -881,16 +856,15 @@ static struct irq_chip nmk_gpio_irq_chip = { 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); } @@ -899,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); @@ -909,29 +885,16 @@ 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); + 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->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); - } - - return 0; -} - /* I/O Functions */ static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -1010,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> @@ -1116,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, }; @@ -1217,62 +1171,35 @@ 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 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 secondary_irq; + 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; - secondary_irq = platform_get_irq(dev, 1); - if (secondary_irq >= 0 && !pdata->get_secondary_status) - return -EINVAL; + /* It's OK for this IRQ not to be present */ + latent_irq = platform_get_irq(dev, 1); res = platform_get_resource(dev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&dev->dev, res); @@ -1297,16 +1224,14 @@ 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->set_ioforce = pdata->set_ioforce; - nmk_chip->sleepmode = pdata->supports_sleepmode; + nmk_chip->latent_parent_irq = latent_irq; + 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; @@ -1325,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); diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c index 5f3adb8..76502aa 100644 --- a/drivers/pinctrl/sirf/pinctrl-sirf.c +++ b/drivers/pinctrl/sirf/pinctrl-sirf.c @@ -595,23 +595,23 @@ static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type) return 0; } -static unsigned int sirfsoc_gpio_irq_startup(struct irq_data *d) +static int sirfsoc_gpio_irq_reqres(struct irq_data *d) { struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d); - if (gpio_lock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE)) + if (gpio_lock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE)) { dev_err(bank->chip.gc.dev, "unable to lock HW IRQ %lu for IRQ\n", d->hwirq); - sirfsoc_gpio_irq_unmask(d); + return -EINVAL; + } return 0; } -static void sirfsoc_gpio_irq_shutdown(struct irq_data *d) +static void sirfsoc_gpio_irq_relres(struct irq_data *d) { struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d); - sirfsoc_gpio_irq_mask(d); gpio_unlock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE); } @@ -621,8 +621,8 @@ static struct irq_chip sirfsoc_irq_chip = { .irq_mask = sirfsoc_gpio_irq_mask, .irq_unmask = sirfsoc_gpio_irq_unmask, .irq_set_type = sirfsoc_gpio_irq_type, - .irq_startup = sirfsoc_gpio_irq_startup, - .irq_shutdown = sirfsoc_gpio_irq_shutdown, + .irq_request_resources = sirfsoc_gpio_irq_reqres, + .irq_release_resources = sirfsoc_gpio_irq_relres, }; static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc) |