]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 6 May 2013 22:40:55 +0000 (15:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 6 May 2013 22:40:55 +0000 (15:40 -0700)
Pull GPIO changes from Grant Likely:
 "The usual selection of bug fixes and driver updates for GPIO.  Nothing
  really stands out except the addition of the GRGPIO driver and some
  enhacements to ACPI support"

I'm pulling this despite the earlier mess.  Let's hope it compiles these
days.

* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux: (46 commits)
  gpio: grgpio: Add irq support
  gpio: grgpio: Add device driver for GRGPIO cores
  gpiolib-acpi: introduce acpi_get_gpio_by_index() helper
  GPIO: gpio-generic: remove kfree() from bgpio_remove call
  gpio / ACPI: Handle ACPI events in accordance with the spec
  gpio: lpc32xx: Fix off-by-one valid range checking for bank
  gpio: mcp23s08: convert driver to DT
  gpio/omap: force restore if context loss is not detectable
  gpio/omap: optimise interrupt service routine
  gpio/omap: remove extra context restores in *_runtime_resume()
  gpio/omap: free irq domain in probe() failure paths
  gpio: gpio-generic: Add 16 and 32 bit big endian byte order support
  gpio: samsung: Add terminating entry for exynos_pinctrl_ids
  gpio: mvebu: add dbg_show function
  MAX7301 GPIO: Do not force SPI speed when using OF Platform
  gpio: gpio-tps65910.c: fix checkpatch error
  gpio: gpio-timberdale.c: fix checkpatch error
  gpio: gpio-tc3589x.c: fix checkpatch errors
  gpio: gpio-stp-xway.c: fix checkpatch error
  gpio: gpio-sch.c: fix checkpatch error
  ...

1  2 
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpiolib-of.c

diff --combined drivers/gpio/Kconfig
index b166e30b3bc4c3a599167847452f87219433fac5,345c6672709c46e6ee5213c16e299c3f1d5ed54e..ff7f0c87745a618a696e6bfa7ed5273b92855be1
@@@ -227,6 -227,12 +227,6 @@@ config GPIO_TS550
          blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
          LCD port.
  
 -config GPIO_VT8500
 -      bool "VIA/Wondermedia SoC GPIO Support"
 -      depends on ARCH_VT8500
 -      help
 -        Say yes here to support the VT8500/WM8505/WM8650 GPIO controller.
 -
  config GPIO_XILINX
        bool "Xilinx GPIO support"
        depends on PPC_OF || MICROBLAZE
@@@ -297,12 -303,21 +297,21 @@@ config GPIO_GE_FPG
  
  config GPIO_LYNXPOINT
        bool "Intel Lynxpoint GPIO support"
-       depends on ACPI
+       depends on ACPI && X86
        select IRQ_DOMAIN
        help
          driver for GPIO functionality on Intel Lynxpoint PCH chipset
          Requires ACPI device enumeration code to set up a platform device.
  
+ config GPIO_GRGPIO
+       tristate "Aeroflex Gaisler GRGPIO support"
+       depends on OF
+       select GPIO_GENERIC
+       select IRQ_DOMAIN
+       help
+         Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB
+         VHDL IP core library.
  comment "I2C GPIO expanders:"
  
  config GPIO_ARIZONA
diff --combined drivers/gpio/Makefile
index a274d7df3c8c4fe4d63b7454e879132a79de1faf,3e6be5134122816eb9692c77ca9c78092c22d743..6aab73d577d1cc4f893afb13d61fd4e532cf746e
@@@ -25,6 -25,7 +25,7 @@@ obj-$(CONFIG_ARCH_DAVINCI)    += gpio-davi
  obj-$(CONFIG_GPIO_EM)         += gpio-em.o
  obj-$(CONFIG_GPIO_EP93XX)     += gpio-ep93xx.o
  obj-$(CONFIG_GPIO_GE_FPGA)    += gpio-ge.o
+ obj-$(CONFIG_GPIO_GRGPIO)     += gpio-grgpio.o
  obj-$(CONFIG_GPIO_ICH)                += gpio-ich.o
  obj-$(CONFIG_GPIO_IT8761E)    += gpio-it8761e.o
  obj-$(CONFIG_GPIO_JANZ_TTL)   += gpio-janz-ttl.o
@@@ -80,6 -81,7 +81,6 @@@ obj-$(CONFIG_GPIO_TWL6040)    += gpio-twl6
  obj-$(CONFIG_GPIO_UCB1400)    += gpio-ucb1400.o
  obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
  obj-$(CONFIG_GPIO_VR41XX)     += gpio-vr41xx.o
 -obj-$(CONFIG_GPIO_VT8500)     += gpio-vt8500.o
  obj-$(CONFIG_GPIO_VX855)      += gpio-vx855.o
  obj-$(CONFIG_GPIO_WM831X)     += gpio-wm831x.o
  obj-$(CONFIG_GPIO_WM8350)     += gpio-wm8350.o
diff --combined drivers/gpio/gpio-ich.c
index de3c317bd3e2d46f788c09d4af95a68dbbc97c69,2829d6d500266cd6002b151b690904ddfaea3590..e16d932fd444a924793f63cfb6c2be46a76106cc
@@@ -130,14 -130,11 +130,11 @@@ static int ichx_read_bit(int reg, unsig
  
  static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
  {
-       return ichx_priv.use_gpio & (1 << (nr / 32));
+       return !!(ichx_priv.use_gpio & (1 << (nr / 32)));
  }
  
  static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
  {
-       if (!ichx_gpio_check_available(gpio, nr))
-               return -ENXIO;
        /*
         * Try setting pin as an input and verify it worked since many pins
         * are output-only.
  static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
                                        int val)
  {
-       if (!ichx_gpio_check_available(gpio, nr))
-               return -ENXIO;
        /* Set GPIO output value. */
        ichx_write_bit(GPIO_LVL, nr, val, 0);
  
  
  static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
  {
-       if (!ichx_gpio_check_available(chip, nr))
-               return -ENXIO;
        return ichx_read_bit(GPIO_LVL, nr);
  }
  
@@@ -180,9 -171,6 +171,6 @@@ static int ich6_gpio_get(struct gpio_ch
        unsigned long flags;
        u32 data;
  
-       if (!ichx_gpio_check_available(chip, nr))
-               return -ENXIO;
        /*
         * GPI 0 - 15 need to be read from the power management registers on
         * a ICH6/3100 bridge.
  
  static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
  {
+       if (!ichx_gpio_check_available(chip, nr))
+               return -ENXIO;
        /*
         * Note we assume the BIOS properly set a bridge's USE value.  Some
         * chips (eg Intel 3100) have bogus USE values though, so first see if
         * If it can't be trusted, assume that the pin can be used as a GPIO.
         */
        if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
 -              return 1;
 +              return 0;
  
        return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
  }
index 61a6fde6c089b28a76f3ca5012309c101ebcf2b2,f7db3b336343dc12565957b91c33374150fc6f0c..bf69a7eff370cbabc72ba01591727ba20c81338c
@@@ -42,7 -42,6 +42,7 @@@
  #include <linux/io.h>
  #include <linux/of_irq.h>
  #include <linux/of_device.h>
 +#include <linux/clk.h>
  #include <linux/pinctrl/consumer.h>
  
  /*
@@@ -117,7 -116,7 +117,7 @@@ static inline void __iomem *mvebu_gpior
  {
        int cpu;
  
-       switch(mvchip->soc_variant) {
+       switch (mvchip->soc_variant) {
        case MVEBU_GPIO_SOC_VARIANT_ORION:
        case MVEBU_GPIO_SOC_VARIANT_MV78200:
                return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
@@@ -133,7 -132,7 +133,7 @@@ static inline void __iomem *mvebu_gpior
  {
        int cpu;
  
-       switch(mvchip->soc_variant) {
+       switch (mvchip->soc_variant) {
        case MVEBU_GPIO_SOC_VARIANT_ORION:
                return mvchip->membase + GPIO_EDGE_MASK_OFF;
        case MVEBU_GPIO_SOC_VARIANT_MV78200:
@@@ -151,7 -150,7 +151,7 @@@ static void __iomem *mvebu_gpioreg_leve
  {
        int cpu;
  
-       switch(mvchip->soc_variant) {
+       switch (mvchip->soc_variant) {
        case MVEBU_GPIO_SOC_VARIANT_ORION:
                return mvchip->membase + GPIO_LEVEL_MASK_OFF;
        case MVEBU_GPIO_SOC_VARIANT_MV78200:
@@@ -401,7 -400,7 +401,7 @@@ static int mvebu_gpio_irq_set_type(stru
        /*
         * Configure interrupt polarity.
         */
-       switch(type) {
+       switch (type) {
        case IRQ_TYPE_EDGE_RISING:
        case IRQ_TYPE_LEVEL_HIGH:
                u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
@@@ -470,18 -469,76 +470,76 @@@ static void mvebu_gpio_irq_handler(unsi
        }
  }
  
+ #ifdef CONFIG_DEBUG_FS
+ #include <linux/seq_file.h>
+ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+ {
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
+       int i;
+       out     = readl_relaxed(mvebu_gpioreg_out(mvchip));
+       io_conf = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+       blink   = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+       in_pol  = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+       data_in = readl_relaxed(mvebu_gpioreg_data_in(mvchip));
+       cause   = readl_relaxed(mvebu_gpioreg_edge_cause(mvchip));
+       edg_msk = readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
+       lvl_msk = readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
+       for (i = 0; i < chip->ngpio; i++) {
+               const char *label;
+               u32 msk;
+               bool is_out;
+               label = gpiochip_is_requested(chip, i);
+               if (!label)
+                       continue;
+               msk = 1 << i;
+               is_out = !(io_conf & msk);
+               seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
+               if (is_out) {
+                       seq_printf(s, " out %s %s\n",
+                                  out & msk ? "hi" : "lo",
+                                  blink & msk ? "(blink )" : "");
+                       continue;
+               }
+               seq_printf(s, " in  %s (act %s) - IRQ",
+                          (data_in ^ in_pol) & msk  ? "hi" : "lo",
+                          in_pol & msk ? "lo" : "hi");
+               if (!((edg_msk | lvl_msk) & msk)) {
+                       seq_printf(s, " disabled\n");
+                       continue;
+               }
+               if (edg_msk & msk)
+                       seq_printf(s, " edge ");
+               if (lvl_msk & msk)
+                       seq_printf(s, " level");
+               seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear  ");
+       }
+ }
+ #else
+ #define mvebu_gpio_dbg_show NULL
+ #endif
  static struct of_device_id mvebu_gpio_of_match[] = {
        {
                .compatible = "marvell,orion-gpio",
-               .data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
+               .data       = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
        },
        {
                .compatible = "marvell,mv78200-gpio",
-               .data       = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200,
+               .data       = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200,
        },
        {
                .compatible = "marvell,armadaxp-gpio",
-               .data       = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
+               .data       = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
        },
        {
                /* sentinel */
@@@ -497,7 -554,6 +555,7 @@@ static int mvebu_gpio_probe(struct plat
        struct resource *res;
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
 +      struct clk *clk;
        unsigned int ngpios;
        int soc_variant;
        int i, cpu, id;
                soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
  
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (! res) {
+       if (!res) {
                dev_err(&pdev->dev, "Cannot get memory resource\n");
                return -ENODEV;
        }
  
        mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
-       if (! mvchip){
+       if (!mvchip) {
                dev_err(&pdev->dev, "Cannot allocate memory\n");
                return -ENOMEM;
        }
                return id;
        }
  
 +      clk = devm_clk_get(&pdev->dev, NULL);
 +      /* Not all SoCs require a clock.*/
 +      if (!IS_ERR(clk))
 +              clk_prepare_enable(clk);
 +
        mvchip->soc_variant = soc_variant;
        mvchip->chip.label = dev_name(&pdev->dev);
        mvchip->chip.dev = &pdev->dev;
        mvchip->chip.ngpio = ngpios;
        mvchip->chip.can_sleep = 0;
        mvchip->chip.of_node = np;
+       mvchip->chip.dbg_show = mvebu_gpio_dbg_show;
  
        spin_lock_init(&mvchip->lock);
        mvchip->membase = devm_ioremap_resource(&pdev->dev, res);
         * per-CPU registers */
        if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               if (! res) {
+               if (!res) {
                        dev_err(&pdev->dev, "Cannot get memory resource\n");
                        return -ENODEV;
                }
  
                mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
                                                               res);
-               if (IS_ERR(mvchip->percpu_membase)) 
+               if (IS_ERR(mvchip->percpu_membase))
                        return PTR_ERR(mvchip->percpu_membase);
        }
  
        /*
         * Mask and clear GPIO interrupts.
         */
-       switch(soc_variant) {
+       switch (soc_variant) {
        case MVEBU_GPIO_SOC_VARIANT_ORION:
                writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
                writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
  
        gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
                                    mvchip->membase, handle_level_irq);
-       if (! gc) {
+       if (!gc) {
                dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
                return -ENOMEM;
        }
diff --combined drivers/gpio/gpio-omap.c
index a612ea1c53cbcb514a84431d0a31501a7a6a5efe,bb1e54f168b4cf8893973b41a9b50e78f0be338f..2050891d9c65a4936533fb14a4b2d8b95b379cb5
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/irqdomain.h>
 +#include <linux/irqchip/chained_irq.h>
  #include <linux/gpio.h>
  #include <linux/platform_data/gpio-omap.h>
  
 -#include <asm/mach/irq.h>
 -
  #define OFF_MODE      1
  
  static LIST_HEAD(omap_gpio_list);
@@@ -52,7 -53,6 +52,6 @@@ struct gpio_bank 
        struct list_head node;
        void __iomem *base;
        u16 irq;
-       int irq_base;
        struct irq_domain *domain;
        u32 non_wakeup_gpios;
        u32 enabled_non_wakeup_gpios;
  
  static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
  {
-       return gpio_irq - bank->irq_base + bank->chip.base;
+       return bank->chip.base + gpio_irq;
+ }
+ static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+       struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+       return irq_find_mapping(bank->domain, offset);
  }
  
  static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
@@@ -420,13 -427,16 +426,16 @@@ static int gpio_irq_type(struct irq_dat
        int retval;
        unsigned long flags;
  
+       if (WARN_ON(!bank->mod_usage))
+               return -EINVAL;
  #ifdef CONFIG_ARCH_OMAP1
        if (d->irq > IH_MPUIO_BASE)
                gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
  #endif
  
        if (!gpio)
-               gpio = irq_to_gpio(bank, d->irq);
+               gpio = irq_to_gpio(bank, d->hwirq);
  
        if (type & ~IRQ_TYPE_SENSE_MASK)
                return -EINVAL;
@@@ -579,7 -589,7 +588,7 @@@ static void _reset_gpio(struct gpio_ban
  static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
  {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       unsigned int gpio = irq_to_gpio(bank, d->irq);
+       unsigned int gpio = irq_to_gpio(bank, d->hwirq);
  
        return _set_gpio_wakeup(bank, gpio, enable);
  }
@@@ -679,7 -689,7 +688,7 @@@ static void gpio_irq_handler(unsigned i
  {
        void __iomem *isr_reg = NULL;
        u32 isr;
-       unsigned int gpio_irq, gpio_index;
+       unsigned int bit;
        struct gpio_bank *bank;
        int unmasked = 0;
        struct irq_chip *chip = irq_desc_get_chip(desc);
        if (WARN_ON(!isr_reg))
                goto exit;
  
-       while(1) {
+       while (1) {
                u32 isr_saved, level_mask = 0;
                u32 enabled;
  
                if (!isr)
                        break;
  
-               gpio_irq = bank->irq_base;
-               for (; isr != 0; isr >>= 1, gpio_irq++) {
-                       int gpio = irq_to_gpio(bank, gpio_irq);
-                       if (!(isr & 1))
-                               continue;
-                       gpio_index = GPIO_INDEX(bank, gpio);
+               while (isr) {
+                       bit = __ffs(isr);
+                       isr &= ~(1 << bit);
  
                        /*
                         * Some chips can't respond to both rising and falling
                         * to respond to the IRQ for the opposite direction.
                         * This will be indicated in the bank toggle_mask.
                         */
-                       if (bank->toggle_mask & (1 << gpio_index))
-                               _toggle_gpio_edge_triggering(bank, gpio_index);
+                       if (bank->toggle_mask & (1 << bit))
+                               _toggle_gpio_edge_triggering(bank, bit);
  
-                       generic_handle_irq(gpio_irq);
+                       generic_handle_irq(irq_find_mapping(bank->domain, bit));
                }
        }
        /* if bank has any level sensitive GPIO pin interrupt
@@@ -755,7 -760,7 +759,7 @@@ exit
  static void gpio_irq_shutdown(struct irq_data *d)
  {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       unsigned int gpio = irq_to_gpio(bank, d->irq);
+       unsigned int gpio = irq_to_gpio(bank, d->hwirq);
        unsigned long flags;
  
        spin_lock_irqsave(&bank->lock, flags);
  static void gpio_ack_irq(struct irq_data *d)
  {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       unsigned int gpio = irq_to_gpio(bank, d->irq);
+       unsigned int gpio = irq_to_gpio(bank, d->hwirq);
  
        _clear_gpio_irqstatus(bank, gpio);
  }
  static void gpio_mask_irq(struct irq_data *d)
  {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       unsigned int gpio = irq_to_gpio(bank, d->irq);
+       unsigned int gpio = irq_to_gpio(bank, d->hwirq);
        unsigned long flags;
  
        spin_lock_irqsave(&bank->lock, flags);
  static void gpio_unmask_irq(struct irq_data *d)
  {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       unsigned int gpio = irq_to_gpio(bank, d->irq);
+       unsigned int gpio = irq_to_gpio(bank, d->hwirq);
        unsigned int irq_mask = GPIO_BIT(bank, gpio);
        u32 trigger = irqd_get_trigger_type(d);
        unsigned long flags;
@@@ -952,14 -957,6 +956,6 @@@ static void gpio_set(struct gpio_chip *
        spin_unlock_irqrestore(&bank->lock, flags);
  }
  
- static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
- {
-       struct gpio_bank *bank;
-       bank = container_of(chip, struct gpio_bank, chip);
-       return bank->irq_base + offset;
- }
  /*---------------------------------------------------------------------*/
  
  static void __init omap_gpio_show_rev(struct gpio_bank *bank)
@@@ -1056,7 -1053,7 +1052,7 @@@ static void omap_gpio_chip_init(struct 
        bank->chip.direction_output = gpio_output;
        bank->chip.set_debounce = gpio_debounce;
        bank->chip.set = gpio_set;
-       bank->chip.to_irq = gpio_2irq;
+       bank->chip.to_irq = omap_gpio_to_irq;
        if (bank->is_mpuio) {
                bank->chip.label = "mpuio";
                if (bank->regs->wkup_en)
  
        gpiochip_add(&bank->chip);
  
-       for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) {
-               irq_set_lockdep_class(j, &gpio_lock_class);
-               irq_set_chip_data(j, bank);
+       for (j = 0; j < bank->width; j++) {
+               int irq = irq_create_mapping(bank->domain, j);
+               irq_set_lockdep_class(irq, &gpio_lock_class);
+               irq_set_chip_data(irq, bank);
                if (bank->is_mpuio) {
-                       omap_mpuio_alloc_gc(bank, j, bank->width);
+                       omap_mpuio_alloc_gc(bank, irq, bank->width);
                } else {
-                       irq_set_chip(j, &gpio_irq_chip);
-                       irq_set_handler(j, handle_simple_irq);
-                       set_irq_flags(j, IRQF_VALID);
+                       irq_set_chip_and_handler(irq, &gpio_irq_chip,
+                                                handle_simple_irq);
+                       set_irq_flags(irq, IRQF_VALID);
                }
        }
        irq_set_chained_handler(bank->irq, gpio_irq_handler);
@@@ -1096,7 -1094,6 +1093,6 @@@ static int omap_gpio_probe(struct platf
        const struct omap_gpio_platform_data *pdata;
        struct resource *res;
        struct gpio_bank *bank;
-       int ret = 0;
  
        match = of_match_device(of_match_ptr(omap_gpio_match), dev);
  
        bank->width = pdata->bank_width;
        bank->is_mpuio = pdata->is_mpuio;
        bank->non_wakeup_gpios = pdata->non_wakeup_gpios;
-       bank->loses_context = pdata->loses_context;
        bank->regs = pdata->regs;
  #ifdef CONFIG_OF_GPIO
        bank->chip.of_node = of_node_get(node);
  #endif
-       bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
-       if (bank->irq_base < 0) {
-               dev_err(dev, "Couldn't allocate IRQ numbers\n");
-               return -ENODEV;
+       if (node) {
+               if (!of_property_read_bool(node, "ti,gpio-always-on"))
+                       bank->loses_context = true;
+       } else {
+               bank->loses_context = pdata->loses_context;
        }
  
-       bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base,
-                                            0, &irq_domain_simple_ops, NULL);
+       bank->domain = irq_domain_add_linear(node, bank->width,
+                                            &irq_domain_simple_ops, NULL);
+       if (!bank->domain)
+               return -ENODEV;
  
        if (bank->regs->set_dataout && bank->regs->clr_dataout)
                bank->set_dataout = _set_gpio_dataout_reg;
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!res)) {
                dev_err(dev, "Invalid mem resource\n");
+               irq_domain_remove(bank->domain);
                return -ENODEV;
        }
  
        if (!devm_request_mem_region(dev, res->start, resource_size(res),
                                     pdev->name)) {
                dev_err(dev, "Region already claimed\n");
+               irq_domain_remove(bank->domain);
                return -EBUSY;
        }
  
        bank->base = devm_ioremap(dev, res->start, resource_size(res));
        if (!bank->base) {
                dev_err(dev, "Could not ioremap\n");
+               irq_domain_remove(bank->domain);
                return -ENOMEM;
        }
  
  
        list_add_tail(&bank->node, &omap_gpio_list);
  
-       return ret;
+       return 0;
  }
  
  #ifdef CONFIG_ARCH_OMAP2PLUS
@@@ -1262,9 -1264,9 +1263,9 @@@ static int omap_gpio_runtime_resume(str
  {
        struct platform_device *pdev = to_platform_device(dev);
        struct gpio_bank *bank = platform_get_drvdata(pdev);
-       int context_lost_cnt_after;
        u32 l = 0, gen, gen0, gen1;
        unsigned long flags;
+       int c;
  
        spin_lock_irqsave(&bank->lock, flags);
        _gpio_dbck_enable(bank);
        __raw_writel(bank->context.risingdetect,
                     bank->base + bank->regs->risingdetect);
  
-       if (bank->get_context_loss_count) {
-               context_lost_cnt_after =
-                       bank->get_context_loss_count(bank->dev);
-               if (context_lost_cnt_after != bank->context_loss_count) {
+       if (bank->loses_context) {
+               if (!bank->get_context_loss_count) {
                        omap_gpio_restore_context(bank);
                } else {
-                       spin_unlock_irqrestore(&bank->lock, flags);
-                       return 0;
+                       c = bank->get_context_loss_count(bank->dev);
+                       if (c != bank->context_loss_count) {
+                               omap_gpio_restore_context(bank);
+                       } else {
+                               spin_unlock_irqrestore(&bank->lock, flags);
+                               return 0;
+                       }
                }
        }
  
                return 0;
        }
  
-       __raw_writel(bank->context.fallingdetect,
-                       bank->base + bank->regs->fallingdetect);
-       __raw_writel(bank->context.risingdetect,
-                       bank->base + bank->regs->risingdetect);
        l = __raw_readl(bank->base + bank->regs->datain);
  
        /*
index 9391cf16e990db6a46870004754df0983568bd8e,15dbc36340b8aecd263022c2b93b71ae0569933a..426c51dd420c618613f96153e8b19275c9ce247a
@@@ -146,8 -146,7 +146,7 @@@ static int pca953x_write_regs(struct pc
                ret = i2c_smbus_write_i2c_block_data(chip->client,
                                        (reg << bank_shift) | REG_ADDR_AI,
                                        NBANK(chip), val);
-       }
-       else {
+       } else {
                switch (chip->chip_type) {
                case PCA953X_TYPE:
                        ret = i2c_smbus_write_word_data(chip->client,
@@@ -575,7 -574,7 +574,7 @@@ static int pca953x_irq_setup(struct pca
                                                chip->gpio_chip.ngpio,
                                                irq_base,
                                                &pca953x_irq_simple_ops,
 -                                              NULL);
 +                                              chip);
                if (!chip->domain)
                        return -ENODEV;
  
diff --combined drivers/gpio/gpio-pxa.c
index d7a5c9d755252218035017f2290ac19d5cff97ee,6d01914538e36f5925eaf53d6f07a357a63e92a7..df2199dd149975e37a31efc6a881450a6ad6af12
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/init.h>
  #include <linux/irq.h>
  #include <linux/irqdomain.h>
 +#include <linux/irqchip/chained_irq.h>
  #include <linux/io.h>
  #include <linux/of.h>
  #include <linux/of_device.h>
@@@ -27,6 -26,8 +27,6 @@@
  #include <linux/syscore_ops.h>
  #include <linux/slab.h>
  
 -#include <asm/mach/irq.h>
 -
  #include <mach/irqs.h>
  
  /*
@@@ -85,61 -86,20 +85,61 @@@ struct pxa_gpio_chip 
  #endif
  };
  
 -enum {
 +enum pxa_gpio_type {
        PXA25X_GPIO = 0,
        PXA26X_GPIO,
        PXA27X_GPIO,
        PXA3XX_GPIO,
        PXA93X_GPIO,
        MMP_GPIO = 0x10,
 +      MMP2_GPIO,
 +};
 +
 +struct pxa_gpio_id {
 +      enum pxa_gpio_type      type;
 +      int                     gpio_nums;
  };
  
  static DEFINE_SPINLOCK(gpio_lock);
  static struct pxa_gpio_chip *pxa_gpio_chips;
 -static int gpio_type;
 +static enum pxa_gpio_type gpio_type;
  static void __iomem *gpio_reg_base;
  
 +static struct pxa_gpio_id pxa25x_id = {
 +      .type           = PXA25X_GPIO,
 +      .gpio_nums      = 85,
 +};
 +
 +static struct pxa_gpio_id pxa26x_id = {
 +      .type           = PXA26X_GPIO,
 +      .gpio_nums      = 90,
 +};
 +
 +static struct pxa_gpio_id pxa27x_id = {
 +      .type           = PXA27X_GPIO,
 +      .gpio_nums      = 121,
 +};
 +
 +static struct pxa_gpio_id pxa3xx_id = {
 +      .type           = PXA3XX_GPIO,
 +      .gpio_nums      = 128,
 +};
 +
 +static struct pxa_gpio_id pxa93x_id = {
 +      .type           = PXA93X_GPIO,
 +      .gpio_nums      = 192,
 +};
 +
 +static struct pxa_gpio_id mmp_id = {
 +      .type           = MMP_GPIO,
 +      .gpio_nums      = 128,
 +};
 +
 +static struct pxa_gpio_id mmp2_id = {
 +      .type           = MMP2_GPIO,
 +      .gpio_nums      = 192,
 +};
 +
  #define for_each_gpio_chip(i, c)                      \
        for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
  
@@@ -472,39 -432,47 +472,39 @@@ static struct irq_chip pxa_muxed_gpio_c
        .irq_set_wake   = pxa_gpio_set_wake,
  };
  
 -static int pxa_gpio_nums(void)
 +static int pxa_gpio_nums(struct platform_device *pdev)
  {
 +      const struct platform_device_id *id = platform_get_device_id(pdev);
 +      struct pxa_gpio_id *pxa_id = (struct pxa_gpio_id *)id->driver_data;
        int count = 0;
  
 -#ifdef CONFIG_ARCH_PXA
 -      if (cpu_is_pxa25x()) {
 -#ifdef CONFIG_CPU_PXA26x
 -              count = 89;
 -              gpio_type = PXA26X_GPIO;
 -#elif defined(CONFIG_PXA25x)
 -              count = 84;
 -              gpio_type = PXA26X_GPIO;
 -#endif /* CONFIG_CPU_PXA26x */
 -      } else if (cpu_is_pxa27x()) {
 -              count = 120;
 -              gpio_type = PXA27X_GPIO;
 -      } else if (cpu_is_pxa93x()) {
 -              count = 191;
 -              gpio_type = PXA93X_GPIO;
 -      } else if (cpu_is_pxa3xx()) {
 -              count = 127;
 -              gpio_type = PXA3XX_GPIO;
 -      }
 -#endif /* CONFIG_ARCH_PXA */
 -
 -#ifdef CONFIG_ARCH_MMP
 -      if (cpu_is_pxa168() || cpu_is_pxa910()) {
 -              count = 127;
 -              gpio_type = MMP_GPIO;
 -      } else if (cpu_is_mmp2()) {
 -              count = 191;
 -              gpio_type = MMP_GPIO;
 +      switch (pxa_id->type) {
 +      case PXA25X_GPIO:
 +      case PXA26X_GPIO:
 +      case PXA27X_GPIO:
 +      case PXA3XX_GPIO:
 +      case PXA93X_GPIO:
 +      case MMP_GPIO:
 +      case MMP2_GPIO:
 +              gpio_type = pxa_id->type;
 +              count = pxa_id->gpio_nums - 1;
 +              break;
 +      default:
 +              count = -EINVAL;
 +              break;
        }
 -#endif /* CONFIG_ARCH_MMP */
        return count;
  }
  
  #ifdef CONFIG_OF
  static struct of_device_id pxa_gpio_dt_ids[] = {
 -      { .compatible = "mrvl,pxa-gpio" },
 -      { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO },
 +      { .compatible = "intel,pxa25x-gpio",    .data = &pxa25x_id, },
 +      { .compatible = "intel,pxa26x-gpio",    .data = &pxa26x_id, },
 +      { .compatible = "intel,pxa27x-gpio",    .data = &pxa27x_id, },
 +      { .compatible = "intel,pxa3xx-gpio",    .data = &pxa3xx_id, },
 +      { .compatible = "marvell,pxa93x-gpio",  .data = &pxa93x_id, },
 +      { .compatible = "marvell,mmp-gpio",     .data = &mmp_id, },
 +      { .compatible = "marvell,mmp2-gpio",    .data = &mmp2_id, },
        {}
  };
  
@@@ -524,18 -492,16 +524,18 @@@ const struct irq_domain_ops pxa_irq_dom
  
  static int pxa_gpio_probe_dt(struct platform_device *pdev)
  {
 -      int ret, nr_banks, nr_gpios;
 +      int ret, nr_gpios;
        struct device_node *prev, *next, *np = pdev->dev.of_node;
        const struct of_device_id *of_id =
                                of_match_device(pxa_gpio_dt_ids, &pdev->dev);
 +      const struct pxa_gpio_id *gpio_id;
  
 -      if (!of_id) {
 +      if (!of_id || !of_id->data) {
                dev_err(&pdev->dev, "Failed to find gpio controller\n");
                return -EFAULT;
        }
 -      gpio_type = (int)of_id->data;
 +      gpio_id = of_id->data;
 +      gpio_type = gpio_id->type;
  
        next = of_get_next_child(np, NULL);
        prev = next;
                ret = -EINVAL;
                goto err;
        }
 -      for (nr_banks = 1; ; nr_banks++) {
 -              next = of_get_next_child(np, prev);
 -              if (!next)
 -                      break;
 -              prev = next;
 -      }
        of_node_put(prev);
 -      nr_gpios = nr_banks << 5;
 +      nr_gpios = gpio_id->gpio_nums;
        pxa_last_gpio = nr_gpios - 1;
  
        irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
@@@ -574,18 -546,19 +574,18 @@@ static int pxa_gpio_probe(struct platfo
        int gpio, irq, ret, use_of = 0;
        int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
  
 -      ret = pxa_gpio_probe_dt(pdev);
 -      if (ret < 0) {
 -              pxa_last_gpio = pxa_gpio_nums();
 -#ifdef CONFIG_ARCH_PXA
 -              if (gpio_is_pxa_type(gpio_type))
 -                      irq_base = PXA_GPIO_TO_IRQ(0);
 -#endif
 -#ifdef CONFIG_ARCH_MMP
 -              if (gpio_is_mmp_type(gpio_type))
 -                      irq_base = MMP_GPIO_TO_IRQ(0);
 -#endif
 +      info = dev_get_platdata(&pdev->dev);
 +      if (info) {
 +              irq_base = info->irq_base;
 +              if (irq_base <= 0)
 +                      return -EINVAL;
 +              pxa_last_gpio = pxa_gpio_nums(pdev);
        } else {
 +              irq_base = 0;
                use_of = 1;
 +              ret = pxa_gpio_probe_dt(pdev);
 +              if (ret < 0)
 +                      return -EINVAL;
        }
  
        if (!pxa_last_gpio)
        }
  
        /* Initialize GPIO chips */
 -      info = dev_get_platdata(&pdev->dev);
        pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL);
  
        /* clear all GPIO edge detects */
        for_each_gpio_chip(gpio, c) {
                writel_relaxed(0, c->regbase + GFER_OFFSET);
                writel_relaxed(0, c->regbase + GRER_OFFSET);
-               writel_relaxed(~0,c->regbase + GEDR_OFFSET);
+               writel_relaxed(~0, c->regbase + GEDR_OFFSET);
                /* unmask GPIO edge detect for AP side */
                if (gpio_is_mmp_type(gpio_type))
                        writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
        return 0;
  }
  
 +static const struct platform_device_id gpio_id_table[] = {
 +      { "pxa25x-gpio",        (unsigned long)&pxa25x_id },
 +      { "pxa26x-gpio",        (unsigned long)&pxa26x_id },
 +      { "pxa27x-gpio",        (unsigned long)&pxa27x_id },
 +      { "pxa3xx-gpio",        (unsigned long)&pxa3xx_id },
 +      { "pxa93x-gpio",        (unsigned long)&pxa93x_id },
 +      { "mmp-gpio",           (unsigned long)&mmp_id },
 +      { "mmp2-gpio",          (unsigned long)&mmp2_id },
 +      { },
 +};
 +
  static struct platform_driver pxa_gpio_driver = {
        .probe          = pxa_gpio_probe,
        .driver         = {
                .name   = "pxa-gpio",
                .of_match_table = of_match_ptr(pxa_gpio_dt_ids),
        },
 +      .id_table       = gpio_id_table,
  };
 -module_platform_driver(pxa_gpio_driver);
 +
 +static int __init pxa_gpio_init(void)
 +{
 +      return platform_driver_register(&pxa_gpio_driver);
 +}
 +postcore_initcall(pxa_gpio_init);
  
  #ifdef CONFIG_PM
  static int pxa_gpio_suspend(void)
@@@ -712,7 -669,7 +712,7 @@@ static void pxa_gpio_resume(void
  
        for_each_gpio_chip(gpio, c) {
                /* restore level with set/clear */
-               writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET);
+               writel_relaxed(c->saved_gplr, c->regbase + GPSR_OFFSET);
                writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET);
  
                writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET);
index 99e0fa49fcbd85283bef3e29f1ff90606ba54c8b,c4b51d82041732a61418ae8f206b753d5253f260..b22ca79337454d61bee83d7b66b1d83a5ff99904
@@@ -1122,12 -1122,8 +1122,12 @@@ int samsung_gpiolib_to_irq(struct gpio_
  #ifdef CONFIG_PLAT_S3C24XX
  static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
  {
 -      if (offset < 4)
 -              return IRQ_EINT0 + offset;
 +      if (offset < 4) {
 +              if (soc_is_s3c2412())
 +                      return IRQ_EINT0_2412 + offset;
 +              else
 +                      return IRQ_EINT0 + offset;
 +      }
  
        if (offset < 8)
                return IRQ_EINT4 + offset - 4;
@@@ -3028,8 -3024,8 +3028,9 @@@ static __init int samsung_gpiolib_init(
        static const struct of_device_id exynos_pinctrl_ids[] = {
                { .compatible = "samsung,exynos4210-pinctrl", },
                { .compatible = "samsung,exynos4x12-pinctrl", },
 +              { .compatible = "samsung,exynos5250-pinctrl", },
                { .compatible = "samsung,exynos5440-pinctrl", },
+               { }
        };
        for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
                if (pctrl_np && of_device_is_available(pctrl_np))
index dde0656ea951257bef7503b3d3b066de0a7b9c19,a78a81fbc2b0879ee8e4ad432832262852008420..da4cb5b0cb87612fed241b9a4ebc6245716377cd
  #include <linux/platform_device.h>
  #include <linux/module.h>
  #include <linux/irqdomain.h>
 +#include <linux/irqchip/chained_irq.h>
  #include <linux/pinctrl/consumer.h>
  #include <linux/pm.h>
  
 -#include <asm/mach/irq.h>
 -
  #define GPIO_BANK(x)          ((x) >> 5)
  #define GPIO_PORT(x)          (((x) >> 3) & 0x3)
  #define GPIO_BIT(x)           ((x) & 0x7)
@@@ -71,7 -72,6 +71,7 @@@ struct tegra_gpio_bank 
        u32 oe[4];
        u32 int_enb[4];
        u32 int_lvl[4];
 +      u32 wake_enb[4];
  #endif
  };
  
@@@ -333,31 -333,15 +333,31 @@@ static int tegra_gpio_suspend(struct de
                        bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
                        bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
                        bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 +
 +                      /* Enable gpio irq for wake up source */
 +                      tegra_gpio_writel(bank->wake_enb[p],
 +                                        GPIO_INT_ENB(gpio));
                }
        }
        local_irq_restore(flags);
        return 0;
  }
  
 -static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 +static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
  {
        struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
 +      int gpio = d->hwirq;
 +      u32 port, bit, mask;
 +
 +      port = GPIO_PORT(gpio);
 +      bit = GPIO_BIT(gpio);
 +      mask = BIT(bit);
 +
 +      if (enable)
 +              bank->wake_enb[port] |= mask;
 +      else
 +              bank->wake_enb[port] &= ~mask;
 +
        return irq_set_irq_wake(bank->irq, enable);
  }
  #endif
@@@ -369,7 -353,7 +369,7 @@@ static struct irq_chip tegra_gpio_irq_c
        .irq_unmask     = tegra_gpio_irq_unmask,
        .irq_set_type   = tegra_gpio_irq_set_type,
  #ifdef CONFIG_PM_SLEEP
 -      .irq_set_wake   = tegra_gpio_wake_enable,
 +      .irq_set_wake   = tegra_gpio_irq_set_wake,
  #endif
  };
  
@@@ -414,10 -398,11 +414,11 @@@ static int tegra_gpio_probe(struct plat
        int j;
  
        match = of_match_device(tegra_gpio_of_match, &pdev->dev);
-       if (match)
-               config = (struct tegra_gpio_soc_config *)match->data;
-       else
-               config = &tegra20_gpio_config;
+       if (!match) {
+               dev_err(&pdev->dev, "Error: No device match found\n");
+               return -ENODEV;
+       }
+       config = (struct tegra_gpio_soc_config *)match->data;
  
        tegra_gpio_bank_stride = config->bank_stride;
        tegra_gpio_upper_offset = config->upper_offset;
                }
        }
  
- #ifdef CONFIG_OF_GPIO
        tegra_gpio_chip.of_node = pdev->dev.of_node;
- #endif
  
        gpiochip_add(&tegra_gpio_chip);
  
index 465f4ca57e8008f2617b3a39435f33ed4f50ec46,8940793912d9d654f85912a70a69bb4ee23a2cd2..665f9530c950f96fd4cf54fb70c03edffbcc2ef2
@@@ -61,7 -61,7 +61,7 @@@ static int of_gpiochip_find_and_xlate(s
   * in flags for the GPIO.
   */
  int of_get_named_gpio_flags(struct device_node *np, const char *propname,
-                            int index, enum of_gpio_flags *flags)
+                          int index, enum of_gpio_flags *flags)
  {
        /* Return -EPROBE_DEFER to support probe() functions to be called
         * later when the GPIO actually becomes available
@@@ -193,7 -193,7 +193,7 @@@ static void of_gpiochip_add_pin_range(s
        if (!np)
                return;
  
 -      do {
 +      for (;; index++) {
                ret = of_parse_phandle_with_args(np, "gpio-ranges",
                                "#gpio-range-cells", index, &pinspec);
                if (ret)
                if (!pctldev)
                        break;
  
 -              /*
 -               * This assumes that the n GPIO pins are consecutive in the
 -               * GPIO number space, and that the pins are also consecutive
 -               * in their local number space. Currently it is not possible
 -               * to add different ranges for one and the same GPIO chip,
 -               * as the code assumes that we have one consecutive range
 -               * on both, mapping 1-to-1.
 -               *
 -               * TODO: make the OF bindings handle multiple sparse ranges
 -               * on the same GPIO chip.
 -               */
                ret = gpiochip_add_pin_range(chip,
                                             pinctrl_dev_get_devname(pctldev),
 -                                           0, /* offset in gpiochip */
                                             pinspec.args[0],
 -                                           pinspec.args[1]);
 +                                           pinspec.args[1],
 +                                           pinspec.args[2]);
  
                if (ret)
                        break;
 -
 -      } while (index++);
 +      }
  }
  
  #else