Merge tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 Oct 2014 18:58:15 +0000 (14:58 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 Oct 2014 18:58:15 +0000 (14:58 -0400)
Pull GPIO changes from Linus Walleij:
 "This is the bulk of GPIO changes for the v3.18 development cycle:

   - Increase the default ARCH_NR_GPIO from 256 to 512.  This was done
     to avoid having a custom <asm/gpio.h> header for the x86
     architecture - GPIO is custom and complicated enough as it is
     already! We want to move to a radix to store the descriptors going
     forward, and finally get rid of this fixed array size altogether.

   - Endgame patching of the gpio_remove() semantics initiated by
     Abdoulaye Berthe.  It is not accepted by the system that the
     removal of a GPIO chip fails during eg reboot or shutdown, and
     therefore the return value has now painfully been refactored away.
     For special cases like GPIO expanders on a hot-pluggable bus like
     USB, we may later add some gpiochip_try_remove() call, but for the
     cases we have now, return values are moot.

   - Some incremental refactoring of the gpiolib core and ACPI GPIO
     library for more descriptor usage.

   - Refactor the chained IRQ handler set-up method to handle also
     threaded, nested interrupts and set up the parent IRQ correctly.
     Switch STMPE and TC3589x drivers to use this registration method.

   - Add a .irq_not_threaded flag to the struct gpio_chip, so that also
     GPIO expanders that block but are still not using threaded IRQ
     handlers.

   - New drivers for the ARM64 X-Gene SoC GPIO controller.

   - The syscon GPIO driver has been improved to handle the "DSP GPIO"
     found on the TI Keystone 2 SoC:s.

   - ADNP driver switched to use gpiolib irqchip helpers.

   - Refactor the DWAPB driver to support being instantiated from and
     MFD cell (platform device).

   - Incremental feature improvement in the Zynq, MCP23S08, DWAPB, OMAP,
     Xilinx and Crystalcove drivers.

   - Various minor fixes"

* tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (52 commits)
  gpio: pch: Build context save/restore only for PM
  pinctrl: abx500: get rid of unused variable
  gpio: ks8695: fix 'else should follow close brace '}''
  gpio: stmpe: add verbose debug code
  gpio: stmpe: fix up interrupt enable logic
  gpio: staticize xway_stp_init()
  gpio: handle also nested irqchips in the chained handler set-up
  gpio: set parent irq on chained handlers
  gpiolib: irqchip: use irq_find_mapping while removing irqchip
  gpio: crystalcove: support virtual GPIO
  pinctrl: bcm281xx: make Kconfig dependency more strict
  gpio: kona: enable only on BCM_MOBILE or for compile testing
  gpio, bcm-kona, LLVMLinux: Remove use of __initconst
  gpio: Fix ngpio in gpio-xilinx driver
  gpio: dwapb: fix pointer to integer cast
  gpio: xgene: Remove unneeded #ifdef CONFIG_OF guard
  gpio: xgene: Remove unneeded forward declation for struct xgene_gpio
  gpio: xgene: Fix missing spin_lock_init()
  gpio: ks8695: fix switch case indentation
  gpiolib: add irq_not_threaded flag to gpio_chip
  ...

13 files changed:
1  2 
drivers/bcma/driver_gpio.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/mfd/htc-i2cpld.c
drivers/pinctrl/Kconfig
drivers/pinctrl/nomadik/pinctrl-abx500.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/samsung/pinctrl-exynos5440.c
drivers/pinctrl/samsung/pinctrl-samsung.c
drivers/pinctrl/sirf/pinctrl-sirf.c
drivers/staging/vme/devices/vme_pio2_gpio.c
include/linux/gpio/driver.h

index 57ce5fe65364feec68eecd3927bb0b08a69cdcb1,710fa62dd5ae2649d4fb3524d35fd8871ba87409..706b9ae0dcfbdb82cf73ae41139d2e4b82ab4693
@@@ -76,7 -76,7 +76,7 @@@ static void bcma_gpio_free(struct gpio_
        bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
  }
  
 -#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC)
 +#if IS_BUILTIN(CONFIG_BCM47XX)
  static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
  {
        struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
@@@ -215,12 -215,8 +215,12 @@@ int bcma_gpio_init(struct bcma_drv_cc *
        chip->set               = bcma_gpio_set_value;
        chip->direction_input   = bcma_gpio_direction_input;
        chip->direction_output  = bcma_gpio_direction_output;
 -#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC)
 +#if IS_BUILTIN(CONFIG_BCM47XX)
        chip->to_irq            = bcma_gpio_to_irq;
 +#endif
 +#if IS_BUILTIN(CONFIG_OF)
 +      if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
 +              chip->of_node   = cc->core->dev.of_node;
  #endif
        switch (cc->core->bus->chipinfo.id) {
        case BCMA_CHIP_ID_BCM5357:
  int bcma_gpio_unregister(struct bcma_drv_cc *cc)
  {
        bcma_gpio_irq_domain_exit(cc);
-       return gpiochip_remove(&cc->gpio);
+       gpiochip_remove(&cc->gpio);
+       return 0;
  }
index 687476fb39e311b0d09ac0a5b20458fb94e2c605,f9103e72e2a41dcd1584c74aaa367c59fe423975..05c6275da224bcf6d287f51da038bdb1c8438962
@@@ -25,10 -25,12 +25,12 @@@ struct acpi_gpio_event 
        acpi_handle handle;
        unsigned int pin;
        unsigned int irq;
+       struct gpio_desc *desc;
  };
  
  struct acpi_gpio_connection {
        struct list_head node;
+       unsigned int pin;
        struct gpio_desc *desc;
  };
  
@@@ -143,14 -145,8 +145,8 @@@ static acpi_status acpi_gpiochip_reques
        if (!handler)
                return AE_BAD_PARAMETER;
  
-       desc = gpiochip_get_desc(chip, pin);
+       desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event");
        if (IS_ERR(desc)) {
-               dev_err(chip->dev, "Failed to get GPIO descriptor\n");
-               return AE_ERROR;
-       }
-       ret = gpiochip_request_own_desc(desc, "ACPI:Event");
-       if (ret) {
                dev_err(chip->dev, "Failed to request GPIO\n");
                return AE_ERROR;
        }
        event->handle = evt_handle;
        event->irq = irq;
        event->pin = pin;
+       event->desc = desc;
  
        ret = request_threaded_irq(event->irq, NULL, handler, irqflags,
                                   "ACPI:Event", event);
@@@ -280,7 -277,7 +277,7 @@@ void acpi_gpiochip_free_interrupts(stru
                struct gpio_desc *desc;
  
                free_irq(event->irq, event);
-               desc = gpiochip_get_desc(chip, event->pin);
+               desc = event->desc;
                if (WARN_ON(IS_ERR(desc)))
                        continue;
                gpio_unlock_as_irq(chip, event->pin);
@@@ -377,10 -374,8 +374,10 @@@ acpi_gpio_adr_space_handler(u32 functio
        struct gpio_chip *chip = achip->chip;
        struct acpi_resource_gpio *agpio;
        struct acpi_resource *ares;
 +      int pin_index = (int)address;
        acpi_status status;
        bool pull_up;
 +      int length;
        int i;
  
        status = acpi_buffer_to_resource(achip->conn_info.connection,
                return AE_BAD_PARAMETER;
        }
  
 -      for (i = 0; i < agpio->pin_table_length; i++) {
 +      length = min(agpio->pin_table_length, (u16)(pin_index + bits));
 +      for (i = pin_index; i < length; ++i) {
                unsigned pin = agpio->pin_table[i];
                struct acpi_gpio_connection *conn;
                struct gpio_desc *desc;
                bool found;
  
-               desc = gpiochip_get_desc(chip, pin);
-               if (IS_ERR(desc)) {
-                       status = AE_ERROR;
-                       goto out;
-               }
                mutex_lock(&achip->conn_lock);
  
                found = false;
                list_for_each_entry(conn, &achip->conns, node) {
-                       if (conn->desc == desc) {
+                       if (conn->pin == pin) {
                                found = true;
+                               desc = conn->desc;
                                break;
                        }
                }
                if (!found) {
-                       int ret;
-                       ret = gpiochip_request_own_desc(desc, "ACPI:OpRegion");
-                       if (ret) {
+                       desc = gpiochip_request_own_desc(chip, pin,
+                                                        "ACPI:OpRegion");
+                       if (IS_ERR(desc)) {
                                status = AE_ERROR;
                                mutex_unlock(&achip->conn_lock);
                                goto out;
                                goto out;
                        }
  
+                       conn->pin = pin;
                        conn->desc = desc;
                        list_add_tail(&conn->node, &achip->conns);
                }
diff --combined drivers/gpio/gpiolib.c
index c68d037de656d68b5808df8174de7bd57bac734e,6e00c82be1421e7a4dec378b1ea305fa8304a0d6..e8e98ca25ec7e468c95164a791866ae477f74f2b
@@@ -308,10 -308,9 +308,9 @@@ static void gpiochip_irqchip_remove(str
   *
   * A gpio_chip with any GPIOs still requested may not be removed.
   */
int gpiochip_remove(struct gpio_chip *chip)
void gpiochip_remove(struct gpio_chip *chip)
  {
        unsigned long   flags;
-       int             status = 0;
        unsigned        id;
  
        acpi_gpiochip_remove(chip);
        of_gpiochip_remove(chip);
  
        for (id = 0; id < chip->ngpio; id++) {
-               if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) {
-                       status = -EBUSY;
-                       break;
-               }
-       }
-       if (status == 0) {
-               for (id = 0; id < chip->ngpio; id++)
-                       chip->desc[id].chip = NULL;
-               list_del(&chip->list);
+               if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags))
+                       dev_crit(chip->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
        }
+       for (id = 0; id < chip->ngpio; id++)
+               chip->desc[id].chip = NULL;
  
+       list_del(&chip->list);
        spin_unlock_irqrestore(&gpio_lock, flags);
-       if (status == 0)
-               gpiochip_unexport(chip);
-       return status;
+       gpiochip_unexport(chip);
  }
  EXPORT_SYMBOL_GPL(gpiochip_remove);
  
@@@ -395,30 -385,47 +385,47 @@@ static struct gpio_chip *find_chip_by_n
   */
  
  /**
-  * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip
-  * @gpiochip: the gpiochip to add the irqchip to
-  * @irqchip: the irqchip to add to the gpiochip
+  * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip
+  * @gpiochip: the gpiochip to set the irqchip chain to
+  * @irqchip: the irqchip to chain to the gpiochip
   * @parent_irq: the irq number corresponding to the parent IRQ for this
   * chained irqchip
   * @parent_handler: the parent interrupt handler for the accumulated IRQ
-  * coming out of the gpiochip
+  * coming out of the gpiochip. If the interrupt is nested rather than
+  * cascaded, pass NULL in this handler argument
   */
  void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
                                  struct irq_chip *irqchip,
                                  int parent_irq,
                                  irq_flow_handler_t parent_handler)
  {
-       if (gpiochip->can_sleep) {
-               chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
+       unsigned int offset;
+       if (!gpiochip->irqdomain) {
+               chip_err(gpiochip, "called %s before setting up irqchip\n",
+                        __func__);
                return;
        }
  
-       /*
-        * The parent irqchip is already using the chip_data for this
-        * irqchip, so our callbacks simply use the handler_data.
-        */
-       irq_set_handler_data(parent_irq, gpiochip);
-       irq_set_chained_handler(parent_irq, parent_handler);
+       if (parent_handler) {
+               if (gpiochip->can_sleep) {
+                       chip_err(gpiochip,
+                                "you cannot have chained interrupts on a "
+                                "chip that may sleep\n");
+                       return;
+               }
 -              irq_set_chained_handler(parent_irq, parent_handler);
+               /*
+                * The parent irqchip is already using the chip_data for this
+                * irqchip, so our callbacks simply use the handler_data.
+                */
+               irq_set_handler_data(parent_irq, gpiochip);
++              irq_set_chained_handler(parent_irq, parent_handler);
+       }
+       /* Set the parent IRQ for all affected IRQs */
+       for (offset = 0; offset < gpiochip->ngpio; offset++)
+               irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset),
+                              parent_irq);
  }
  EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
  
@@@ -447,7 -454,7 +454,7 @@@ static int gpiochip_irq_map(struct irq_
        irq_set_lockdep_class(irq, &gpiochip_irq_lock_class);
        irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
        /* Chips that can sleep need nested thread handlers */
-       if (chip->can_sleep)
+       if (chip->can_sleep && !chip->irq_not_threaded)
                irq_set_nested_thread(irq, 1);
  #ifdef CONFIG_ARM
        set_irq_flags(irq, IRQF_VALID);
@@@ -524,7 -531,8 +531,8 @@@ static void gpiochip_irqchip_remove(str
        /* Remove all IRQ mappings and delete the domain */
        if (gpiochip->irqdomain) {
                for (offset = 0; offset < gpiochip->ngpio; offset++)
-                       irq_dispose_mapping(gpiochip->irq_base + offset);
+                       irq_dispose_mapping(
+                               irq_find_mapping(gpiochip->irqdomain, offset));
                irq_domain_remove(gpiochip->irqdomain);
        }
  
@@@ -895,12 -903,22 +903,22 @@@ EXPORT_SYMBOL_GPL(gpiochip_is_requested
   * allows the GPIO chip module to be unloaded as needed (we assume that the
   * GPIO chip driver handles freeing the GPIOs it has requested).
   */
- int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label)
+ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum,
+                                           const char *label)
  {
-       if (!desc || !desc->chip)
-               return -EINVAL;
+       struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum);
+       int err;
  
-       return __gpiod_request(desc, label);
+       if (IS_ERR(desc)) {
+               chip_err(chip, "failed to get GPIO descriptor\n");
+               return desc;
+       }
+       err = __gpiod_request(desc, label);
+       if (err < 0)
+               return ERR_PTR(err);
+       return desc;
  }
  EXPORT_SYMBOL_GPL(gpiochip_request_own_desc);
  
@@@ -1652,7 -1670,7 +1670,7 @@@ struct gpio_desc *__must_check __gpiod_
         * a result. In that case, use platform lookup as a fallback.
         */
        if (!desc || desc == ERR_PTR(-ENOENT)) {
-               dev_dbg(dev, "using lookup tables for GPIO lookup");
+               dev_dbg(dev, "using lookup tables for GPIO lookup\n");
                desc = gpiod_find(dev, con_id, idx, &lookupflags);
        }
  
                set_bit(FLAG_OPEN_SOURCE, &desc->flags);
  
        /* No particular flag request, return here... */
 -      if (flags & GPIOD_FLAGS_BIT_DIR_SET)
 +      if (!(flags & GPIOD_FLAGS_BIT_DIR_SET))
                return desc;
  
        /* Process flags */
diff --combined drivers/mfd/htc-i2cpld.c
index 6bdb78c2ac77de535214d80a09cd9a302653d219,eab3fb028447838a22c168cfdf0b01e21d10e099..adbbce0ff630edfb02de146a13b711790e6e29a8
@@@ -404,7 -404,7 +404,7 @@@ static int htcpld_register_chip_i2c
        }
  
        i2c_set_clientdata(client, chip);
 -      snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
 +      snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%x", client->addr);
        chip->client = client;
  
        /* Reset the chip */
@@@ -481,15 -481,9 +481,9 @@@ static int htcpld_register_chip_gpio
  
        ret = gpiochip_add(&(chip->chip_in));
        if (ret) {
-               int error;
                dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
                         plat_chip_data->addr, ret);
-               error = gpiochip_remove(&(chip->chip_out));
-               if (error)
-                       dev_warn(dev, "Error while trying to unregister gpio chip: %d\n", error);
+               gpiochip_remove(&(chip->chip_out));
                return ret;
        }
  
diff --combined drivers/pinctrl/Kconfig
index 64d06b52f98a8650c10510391121085a5f6c398c,a95d5ca6d83070785f7d76765b5d4798a34b7987..c6a66de6ed72d0d4e96d061737d4ba3b9a4f3cd3
@@@ -86,7 -86,7 +86,7 @@@ config PINCTRL_BCM283
  
  config PINCTRL_BCM281XX
        bool "Broadcom BCM281xx pinctrl driver"
-       depends on OF
+       depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST)
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
          BCM28145, and BCM28155 SoCs.  This driver requires the pinctrl
          framework.  GPIO is provided by a separate GPIO driver.
  
 -config PINCTRL_IMX
 -      bool
 -      select PINMUX
 -      select PINCONF
 -
 -config PINCTRL_IMX1_CORE
 -      bool
 -      select PINMUX
 -      select PINCONF
 -
 -config PINCTRL_IMX1
 -      bool "IMX1 pinctrl driver"
 -      depends on SOC_IMX1
 -      select PINCTRL_IMX1_CORE
 -      help
 -        Say Y here to enable the imx1 pinctrl driver
 -
 -config PINCTRL_IMX27
 -      bool "IMX27 pinctrl driver"
 -      depends on SOC_IMX27
 -      select PINCTRL_IMX1_CORE
 -      help
 -        Say Y here to enable the imx27 pinctrl driver
 -
 -
 -config PINCTRL_IMX25
 -        bool "IMX25 pinctrl driver"
 -        depends on OF
 -        depends on SOC_IMX25
 -        select PINCTRL_IMX
 -        help
 -          Say Y here to enable the imx25 pinctrl driver
 -
 -config PINCTRL_IMX35
 -      bool "IMX35 pinctrl driver"
 -      depends on SOC_IMX35
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx35 pinctrl driver
 -
 -config PINCTRL_IMX50
 -      bool "IMX50 pinctrl driver"
 -      depends on SOC_IMX50
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx50 pinctrl driver
 -
 -config PINCTRL_IMX51
 -      bool "IMX51 pinctrl driver"
 -      depends on SOC_IMX51
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx51 pinctrl driver
 -
 -config PINCTRL_IMX53
 -      bool "IMX53 pinctrl driver"
 -      depends on SOC_IMX53
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx53 pinctrl driver
 -
 -config PINCTRL_IMX6Q
 -      bool "IMX6Q/DL pinctrl driver"
 -      depends on SOC_IMX6Q
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx6q/dl pinctrl driver
 -
 -config PINCTRL_IMX6SL
 -      bool "IMX6SL pinctrl driver"
 -      depends on SOC_IMX6SL
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx6sl pinctrl driver
 -
 -config PINCTRL_IMX6SX
 -      bool "IMX6SX pinctrl driver"
 -      depends on SOC_IMX6SX
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the imx6sx pinctrl driver
 -
 -config PINCTRL_VF610
 -      bool "Freescale Vybrid VF610 pinctrl driver"
 -      depends on SOC_VF610
 -      select PINCTRL_IMX
 -      help
 -        Say Y here to enable the Freescale Vybrid VF610 pinctrl driver
 -
  config PINCTRL_LANTIQ
        bool
        depends on LANTIQ
@@@ -108,6 -197,19 +108,6 @@@ config PINCTRL_FALCO
        depends on SOC_FALCON
        depends on PINCTRL_LANTIQ
  
 -config PINCTRL_MXS
 -      bool
 -      select PINMUX
 -      select PINCONF
 -
 -config PINCTRL_IMX23
 -      bool
 -      select PINCTRL_MXS
 -
 -config PINCTRL_IMX28
 -      bool
 -      select PINCTRL_MXS
 -
  config PINCTRL_ROCKCHIP
        bool
        select PINMUX
@@@ -204,7 -306,6 +204,7 @@@ config PINCTRL_PALMA
          TPS65913, TPS80036 etc.
  
  source "drivers/pinctrl/berlin/Kconfig"
 +source "drivers/pinctrl/freescale/Kconfig"
  source "drivers/pinctrl/mvebu/Kconfig"
  source "drivers/pinctrl/nomadik/Kconfig"
  source "drivers/pinctrl/qcom/Kconfig"
index 47f49314986356eb86497d17e251dc7cbecc2957,080bcf8568c93615eadfb19c80ce99ca3e61c529..22897282713251291c47f926b6042c3689993d6c
@@@ -34,7 -34,6 +34,7 @@@
  #include "pinctrl-abx500.h"
  #include "../core.h"
  #include "../pinconf.h"
 +#include "../pinctrl-utils.h"
  
  /*
   * The AB9540 and AB8540 GPIO support are extended versions
@@@ -621,7 -620,8 +621,7 @@@ static void abx500_gpio_dbg_show_one(st
        } else
                seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
  
 -      if (pctldev)
 -              mode = abx500_get_mode(pctldev, chip, offset);
 +      mode = abx500_get_mode(pctldev, chip, offset);
  
        seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]);
  
@@@ -709,8 -709,8 +709,8 @@@ static int abx500_pmx_get_func_groups(s
        return 0;
  }
  
 -static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
 -                           unsigned group)
 +static int abx500_pmx_set(struct pinctrl_dev *pctldev, unsigned function,
 +                        unsigned group)
  {
        struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
        struct gpio_chip *chip = &pct->chip;
@@@ -784,7 -784,7 +784,7 @@@ static const struct pinmux_ops abx500_p
        .get_functions_count = abx500_pmx_get_funcs_cnt,
        .get_function_name = abx500_pmx_get_func_name,
        .get_function_groups = abx500_pmx_get_func_groups,
 -      .enable = abx500_pmx_enable,
 +      .set_mux = abx500_pmx_set,
        .gpio_request_enable = abx500_gpio_request_enable,
        .gpio_disable_free = abx500_gpio_disable_free,
  };
@@@ -827,6 -827,41 +827,6 @@@ static void abx500_pin_dbg_show(struct 
                                 chip->base + offset - 1);
  }
  
 -static void abx500_dt_free_map(struct pinctrl_dev *pctldev,
 -              struct pinctrl_map *map, unsigned num_maps)
 -{
 -      int i;
 -
 -      for (i = 0; i < num_maps; i++)
 -              if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
 -                      kfree(map[i].data.configs.configs);
 -      kfree(map);
 -}
 -
 -static int abx500_dt_reserve_map(struct pinctrl_map **map,
 -              unsigned *reserved_maps,
 -              unsigned *num_maps,
 -              unsigned reserve)
 -{
 -      unsigned old_num = *reserved_maps;
 -      unsigned new_num = *num_maps + reserve;
 -      struct pinctrl_map *new_map;
 -
 -      if (old_num >= new_num)
 -              return 0;
 -
 -      new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
 -      if (!new_map)
 -              return -ENOMEM;
 -
 -      memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
 -
 -      *map = new_map;
 -      *reserved_maps = new_num;
 -
 -      return 0;
 -}
 -
  static int abx500_dt_add_map_mux(struct pinctrl_map **map,
                unsigned *reserved_maps,
                unsigned *num_maps, const char *group,
@@@ -892,32 -927,19 +892,32 @@@ static int abx500_dt_subnode_to_map(str
        unsigned long *configs;
        unsigned int nconfigs = 0;
        bool has_config = 0;
 -      unsigned reserve = 0;
        struct property *prop;
        const char *group, *gpio_name;
        struct device_node *np_config;
  
        ret = of_property_read_string(np, "ste,function", &function);
 -      if (ret >= 0)
 -              reserve = 1;
 +      if (ret >= 0) {
 +              ret = of_property_count_strings(np, "ste,pins");
 +              if (ret < 0)
 +                      goto exit;
 +
 +              ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
 +                                              num_maps, ret);
 +              if (ret < 0)
 +                      goto exit;
 +
 +              of_property_for_each_string(np, "ste,pins", prop, group) {
 +                      ret = abx500_dt_add_map_mux(map, reserved_maps,
 +                                      num_maps, group, function);
 +                      if (ret < 0)
 +                              goto exit;
 +              }
 +      }
  
        ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs);
        if (nconfigs)
                has_config = 1;
 -
        np_config = of_parse_phandle(np, "ste,config", 0);
        if (np_config) {
                ret = pinconf_generic_parse_dt_config(np_config, &configs,
                        goto exit;
                has_config |= nconfigs;
        }
 +      if (has_config) {
 +              ret = of_property_count_strings(np, "ste,pins");
 +              if (ret < 0)
 +                      goto exit;
  
 -      ret = of_property_count_strings(np, "ste,pins");
 -      if (ret < 0)
 -              goto exit;
 -
 -      if (has_config)
 -              reserve++;
 -
 -      reserve *= ret;
 -
 -      ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve);
 -      if (ret < 0)
 -              goto exit;
 +              ret = pinctrl_utils_reserve_map(pctldev, map,
 +                                              reserved_maps,
 +                                              num_maps, ret);
 +              if (ret < 0)
 +                      goto exit;
  
 -      of_property_for_each_string(np, "ste,pins", prop, group) {
 -              if (function) {
 -                      ret = abx500_dt_add_map_mux(map, reserved_maps,
 -                                      num_maps, group, function);
 -                      if (ret < 0)
 -                              goto exit;
 -              }
 -              if (has_config) {
 +              of_property_for_each_string(np, "ste,pins", prop, group) {
                        gpio_name = abx500_find_pin_name(pctldev, group);
  
                        ret = abx500_dt_add_map_configs(map, reserved_maps,
                        if (ret < 0)
                                goto exit;
                }
 -
        }
 +
  exit:
        return ret;
  }
@@@ -967,7 -999,7 +967,7 @@@ static int abx500_dt_node_to_map(struc
                ret = abx500_dt_subnode_to_map(pctldev, np, map,
                                &reserved_maps, num_maps);
                if (ret < 0) {
 -                      abx500_dt_free_map(pctldev, *map, *num_maps);
 +                      pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
                        return ret;
                }
        }
@@@ -981,7 -1013,7 +981,7 @@@ static const struct pinctrl_ops abx500_
        .get_group_pins = abx500_get_group_pins,
        .pin_dbg_show = abx500_pin_dbg_show,
        .dt_node_to_map = abx500_dt_node_to_map,
 -      .dt_free_map = abx500_dt_free_map,
 +      .dt_free_map = pinctrl_utils_dt_free_map,
  };
  
  static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
@@@ -1174,7 -1206,7 +1174,7 @@@ static int abx500_gpio_probe(struct pla
        const struct of_device_id *match;
        struct abx500_pinctrl *pct;
        unsigned int id = -1;
-       int ret, err;
+       int ret;
        int i;
  
        if (!np) {
        return 0;
  
  out_rem_chip:
-       err = gpiochip_remove(&pct->chip);
-       if (err)
-               dev_info(&pdev->dev, "failed to remove gpiochip\n");
+       gpiochip_remove(&pct->chip);
        return ret;
  }
  
  static int abx500_gpio_remove(struct platform_device *pdev)
  {
        struct abx500_pinctrl *pct = platform_get_drvdata(pdev);
-       int ret;
-       ret = gpiochip_remove(&pct->chip);
-       if (ret < 0) {
-               dev_err(pct->dev, "unable to remove gpiochip: %d\n",
-                       ret);
-               return ret;
-       }
  
+       gpiochip_remove(&pct->chip);
        return 0;
  }
  
index 3c29d9187146d88d8326d4a54ea224fbaa7b13a0,4332b38c52aba87d404a46b0071664bec269b459..746db6acf64865d9bf7713f79d6744508bbc9f25
@@@ -32,7 -32,6 +32,7 @@@
  #include <linux/pinctrl/consumer.h>
  #include "pinctrl-nomadik.h"
  #include "../core.h"
 +#include "../pinctrl-utils.h"
  
  /*
   * The GPIO module in the Nomadik family of Systems-on-Chip is an
@@@ -986,7 -985,6 +986,7 @@@ static void nmk_gpio_dbg_show_one(struc
                container_of(chip, struct nmk_gpio_chip, chip);
        int mode;
        bool is_out;
 +      bool data_out;
        bool pull;
        u32 bit = 1 << offset;
        const char *modes[] = {
                [NMK_GPIO_ALT_C+3]      = "altC3",
                [NMK_GPIO_ALT_C+4]      = "altC4",
        };
 +      const char *pulls[] = {
 +              "none     ",
 +              "pull down",
 +              "pull up  ",
 +      };
  
        clk_enable(nmk_chip->clk);
        is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
        pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
 +      data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & bit);
        mode = nmk_gpio_get_mode(gpio);
        if ((mode == NMK_GPIO_ALT_C) && pctldev)
                mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
  
 -      seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
 -                 gpio, label ?: "(none)",
 -                 is_out ? "out" : "in ",
 -                 chip->get
 -                 ? (chip->get(chip, offset) ? "hi" : "lo")
 -                 : "?  ",
 -                 (mode < 0) ? "unknown" : modes[mode],
 -                 pull ? "pull" : "none");
 -
 -      if (!is_out) {
 +      if (is_out) {
 +              seq_printf(s, " gpio-%-3d (%-20.20s) out %s        %s",
 +                         gpio,
 +                         label ?: "(none)",
 +                         data_out ? "hi" : "lo",
 +                         (mode < 0) ? "unknown" : modes[mode]);
 +      } else {
                int irq = gpio_to_irq(gpio);
                struct irq_desc *desc = irq_to_desc(irq);
 +              int pullidx = 0;
  
 -              /* This races with request_irq(), set_irq_type(),
 +              if (pull)
 +                      pullidx = data_out ? 1 : 2;
 +
 +              seq_printf(s, " gpio-%-3d (%-20.20s) in  %s %s",
 +                         gpio,
 +                         label ?: "(none)",
 +                         pulls[pullidx],
 +                         (mode < 0) ? "unknown" : modes[mode]);
 +              /*
 +               * This races with request_irq(), set_irq_type(),
                 * and set_irq_wake() ... but those are "rare".
                 */
                if (irq > 0 && desc && desc->action) {
@@@ -1276,7 -1261,7 +1276,7 @@@ static int nmk_gpio_probe(struct platfo
                                   IRQ_TYPE_EDGE_FALLING);
        if (ret) {
                dev_err(&dev->dev, "could not add irqchip\n");
-               ret = gpiochip_remove(&nmk_chip->chip);
+               gpiochip_remove(&nmk_chip->chip);
                return -ENODEV;
        }
        /* Then register the chain on the parent IRQ */
@@@ -1353,6 -1338,39 +1353,6 @@@ static void nmk_pin_dbg_show(struct pin
        nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
  }
  
 -static void nmk_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
 -              struct pinctrl_map *map, unsigned num_maps)
 -{
 -      int i;
 -
 -      for (i = 0; i < num_maps; i++)
 -              if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
 -                      kfree(map[i].data.configs.configs);
 -      kfree(map);
 -}
 -
 -static int nmk_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
 -              unsigned *num_maps, unsigned reserve)
 -{
 -      unsigned old_num = *reserved_maps;
 -      unsigned new_num = *num_maps + reserve;
 -      struct pinctrl_map *new_map;
 -
 -      if (old_num >= new_num)
 -              return 0;
 -
 -      new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
 -      if (!new_map)
 -              return -ENOMEM;
 -
 -      memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
 -
 -      *map = new_map;
 -      *reserved_maps = new_num;
 -
 -      return 0;
 -}
 -
  static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
                unsigned *num_maps, const char *group,
                const char *function)
@@@ -1519,55 -1537,51 +1519,55 @@@ static int nmk_pinctrl_dt_subnode_to_ma
        const char *function = NULL;
        unsigned long configs = 0;
        bool has_config = 0;
 -      unsigned reserve = 0;
        struct property *prop;
        const char *group, *gpio_name;
        struct device_node *np_config;
  
        ret = of_property_read_string(np, "ste,function", &function);
 -      if (ret >= 0)
 -              reserve = 1;
 -
 -      has_config = nmk_pinctrl_dt_get_config(np, &configs);
 -
 -      np_config = of_parse_phandle(np, "ste,config", 0);
 -      if (np_config)
 -              has_config |= nmk_pinctrl_dt_get_config(np_config, &configs);
 -
 -      ret = of_property_count_strings(np, "ste,pins");
 -      if (ret < 0)
 -              goto exit;
 -
 -      if (has_config)
 -              reserve++;
 -
 -      reserve *= ret;
 -
 -      ret = nmk_dt_reserve_map(map, reserved_maps, num_maps, reserve);
 -      if (ret < 0)
 -              goto exit;
 -
 -      of_property_for_each_string(np, "ste,pins", prop, group) {
 -              if (function) {
 +      if (ret >= 0) {
 +              ret = of_property_count_strings(np, "ste,pins");
 +              if (ret < 0)
 +                      goto exit;
 +
 +              ret = pinctrl_utils_reserve_map(pctldev, map,
 +                                              reserved_maps,
 +                                              num_maps, ret);
 +              if (ret < 0)
 +                      goto exit;
 +
 +              of_property_for_each_string(np, "ste,pins", prop, group) {
                        ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps,
                                          group, function);
                        if (ret < 0)
                                goto exit;
                }
 -              if (has_config) {
 +      }
 +
 +      has_config = nmk_pinctrl_dt_get_config(np, &configs);
 +      np_config = of_parse_phandle(np, "ste,config", 0);
 +      if (np_config)
 +              has_config |= nmk_pinctrl_dt_get_config(np_config, &configs);
 +      if (has_config) {
 +              ret = of_property_count_strings(np, "ste,pins");
 +              if (ret < 0)
 +                      goto exit;
 +              ret = pinctrl_utils_reserve_map(pctldev, map,
 +                                              reserved_maps,
 +                                              num_maps, ret);
 +              if (ret < 0)
 +                      goto exit;
 +
 +              of_property_for_each_string(np, "ste,pins", prop, group) {
                        gpio_name = nmk_find_pin_name(pctldev, group);
  
 -                      ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps,
 -                                            gpio_name, &configs, 1);
 +                      ret = nmk_dt_add_map_configs(map, reserved_maps,
 +                                                   num_maps,
 +                                                   gpio_name, &configs, 1);
                        if (ret < 0)
                                goto exit;
                }
 -
        }
 +
  exit:
        return ret;
  }
@@@ -1588,7 -1602,7 +1588,7 @@@ static int nmk_pinctrl_dt_node_to_map(s
                ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map,
                                &reserved_maps, num_maps);
                if (ret < 0) {
 -                      nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps);
 +                      pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
                        return ret;
                }
        }
@@@ -1602,7 -1616,7 +1602,7 @@@ static const struct pinctrl_ops nmk_pin
        .get_group_pins = nmk_get_group_pins,
        .pin_dbg_show = nmk_pin_dbg_show,
        .dt_node_to_map = nmk_pinctrl_dt_node_to_map,
 -      .dt_free_map = nmk_pinctrl_dt_free_map,
 +      .dt_free_map = pinctrl_utils_dt_free_map,
  };
  
  static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
@@@ -1633,8 -1647,8 +1633,8 @@@ static int nmk_pmx_get_func_groups(stru
        return 0;
  }
  
 -static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
 -                        unsigned group)
 +static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned function,
 +                     unsigned group)
  {
        struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
        const struct nmk_pingroup *g;
@@@ -1796,7 -1810,7 +1796,7 @@@ static const struct pinmux_ops nmk_pinm
        .get_functions_count = nmk_pmx_get_funcs_cnt,
        .get_function_name = nmk_pmx_get_func_name,
        .get_function_groups = nmk_pmx_get_func_groups,
 -      .enable = nmk_pmx_enable,
 +      .set_mux = nmk_pmx_set,
        .gpio_request_enable = nmk_gpio_request_enable,
        .gpio_disable_free = nmk_gpio_disable_free,
  };
index d30dddd213231a7c54bfc2c6765d7733d4a5f5a6,041677113a480051187d45e4cbe15a0fad59dde1..e730935fa4577deb2582ea493ab60aa2b0f176fe
@@@ -12,7 -12,6 +12,7 @@@
   * GNU General Public License for more details.
   */
  
 +#include <linux/delay.h>
  #include <linux/err.h>
  #include <linux/io.h>
  #include <linux/module.h>
@@@ -27,7 -26,6 +27,7 @@@
  #include <linux/gpio.h>
  #include <linux/interrupt.h>
  #include <linux/spinlock.h>
 +#include <linux/reboot.h>
  
  #include "../core.h"
  #include "../pinconf.h"
  #include "../pinctrl-utils.h"
  
  #define MAX_NR_GPIO 300
 +#define PS_HOLD_OFFSET 0x820
  
  /**
   * struct msm_pinctrl - state for a pinctrl-msm device
   * @dev:            device handle.
   * @pctrl:          pinctrl handle.
   * @chip:           gpiochip handle.
 + * @restart_nb:     restart notifier block.
   * @irq:            parent irq for the TLMM irq_chip.
   * @lock:           Spinlock to protect register resources as well
   *                  as msm_pinctrl data structures.
@@@ -56,7 -52,6 +56,7 @@@ struct msm_pinctrl 
        struct device *dev;
        struct pinctrl_dev *pctrl;
        struct gpio_chip chip;
 +      struct notifier_block restart_nb;
        int irq;
  
        spinlock_t lock;
@@@ -135,9 -130,9 +135,9 @@@ static int msm_get_function_groups(stru
        return 0;
  }
  
 -static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
 -                           unsigned function,
 -                           unsigned group)
 +static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
 +                            unsigned function,
 +                            unsigned group)
  {
        struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
        const struct msm_pingroup *g;
@@@ -171,7 -166,7 +171,7 @@@ static const struct pinmux_ops msm_pinm
        .get_functions_count    = msm_get_functions_count,
        .get_function_name      = msm_get_function_name,
        .get_function_groups    = msm_get_function_groups,
 -      .enable                 = msm_pinmux_enable,
 +      .set_mux                = msm_pinmux_set_mux,
  };
  
  static int msm_config_reg(struct msm_pinctrl *pctrl,
@@@ -654,6 -649,8 +654,6 @@@ static void msm_gpio_irq_ack(struct irq
        spin_unlock_irqrestore(&pctrl->lock, flags);
  }
  
 -#define INTR_TARGET_PROC_APPS    4
 -
  static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
  {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        /* Route interrupts to application cpu */
        val = readl(pctrl->regs + g->intr_target_reg);
        val &= ~(7 << g->intr_target_bit);
 -      val |= INTR_TARGET_PROC_APPS << g->intr_target_bit;
 +      val |= g->intr_target_kpss_val << g->intr_target_bit;
        writel(val, pctrl->regs + g->intr_target_reg);
  
        /* Update configuration for gpio.
@@@ -832,7 -829,6 +832,7 @@@ static int msm_gpio_init(struct msm_pin
        ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
        if (ret) {
                dev_err(pctrl->dev, "Failed to add pin range\n");
 +              gpiochip_remove(&pctrl->chip);
                return ret;
        }
  
                                   IRQ_TYPE_NONE);
        if (ret) {
                dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
 +              gpiochip_remove(&pctrl->chip);
                return -ENOSYS;
        }
  
        return 0;
  }
  
 +static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,
 +                             void *data)
 +{
 +      struct msm_pinctrl *pctrl = container_of(nb, struct msm_pinctrl, restart_nb);
 +
 +      writel(0, pctrl->regs + PS_HOLD_OFFSET);
 +      mdelay(1000);
 +      return NOTIFY_DONE;
 +}
 +
 +static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
 +{
 +      int i = 0;
 +      const struct msm_function *func = pctrl->soc->functions;
 +
 +      for (; i <= pctrl->soc->nfunctions; i++)
 +              if (!strcmp(func[i].name, "ps_hold")) {
 +                      pctrl->restart_nb.notifier_call = msm_ps_hold_restart;
 +                      pctrl->restart_nb.priority = 128;
 +                      if (register_restart_handler(&pctrl->restart_nb))
 +                              dev_err(pctrl->dev,
 +                                      "failed to setup restart handler.\n");
 +                      break;
 +              }
 +}
 +
  int msm_pinctrl_probe(struct platform_device *pdev,
                      const struct msm_pinctrl_soc_data *soc_data)
  {
        if (IS_ERR(pctrl->regs))
                return PTR_ERR(pctrl->regs);
  
 +      msm_pinctrl_setup_pm_reset(pctrl);
 +
        pctrl->irq = platform_get_irq(pdev, 0);
        if (pctrl->irq < 0) {
                dev_err(&pdev->dev, "No interrupt defined for msmgpio\n");
@@@ -936,18 -903,9 +936,12 @@@ EXPORT_SYMBOL(msm_pinctrl_probe)
  int msm_pinctrl_remove(struct platform_device *pdev)
  {
        struct msm_pinctrl *pctrl = platform_get_drvdata(pdev);
-       int ret;
-       ret = gpiochip_remove(&pctrl->chip);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to remove gpiochip\n");
-               return ret;
-       }
  
+       gpiochip_remove(&pctrl->chip);
        pinctrl_unregister(pctrl->pctrl);
 +
 +      unregister_restart_handler(&pctrl->restart_nb);
 +
        return 0;
  }
  EXPORT_SYMBOL(msm_pinctrl_remove);
index b995ec2c5d16134e1fa274f1d212171fae0b1bc1,8ef370244aeedfccda8e3487e3fd2ad2f7fa0062..88acfc0efd543085f033e7218dd0a5f77290d044
@@@ -364,9 -364,8 +364,9 @@@ static void exynos5440_pinmux_setup(str
  }
  
  /* enable a specified pinmux by writing to registers */
 -static int exynos5440_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
 -                                      unsigned group)
 +static int exynos5440_pinmux_set_mux(struct pinctrl_dev *pctldev,
 +                                   unsigned selector,
 +                                   unsigned group)
  {
        exynos5440_pinmux_setup(pctldev, selector, group, true);
        return 0;
@@@ -388,7 -387,7 +388,7 @@@ static const struct pinmux_ops exynos54
        .get_functions_count    = exynos5440_get_functions_count,
        .get_function_name      = exynos5440_pinmux_get_fname,
        .get_function_groups    = exynos5440_pinmux_get_groups,
 -      .enable                 = exynos5440_pinmux_enable,
 +      .set_mux                = exynos5440_pinmux_set_mux,
        .gpio_set_direction     = exynos5440_pinmux_gpio_set_direction,
  };
  
@@@ -874,11 -873,7 +874,7 @@@ static int exynos5440_gpiolib_register(
  static int exynos5440_gpiolib_unregister(struct platform_device *pdev,
                                struct exynos5440_pinctrl_priv_data *priv)
  {
-       int ret = gpiochip_remove(priv->gc);
-       if (ret) {
-               dev_err(&pdev->dev, "gpio chip remove failed\n");
-               return ret;
-       }
+       gpiochip_remove(priv->gc);
        return 0;
  }
  
index 4a47691c32b1c81fe28118cbc04adf2d809776a5,83faddf456e0127d53ede400818f7667ab8debde..2d37c8f49f3c95ed11a42abce1f52ea5124b9c11
@@@ -401,9 -401,8 +401,9 @@@ static void samsung_pinmux_setup(struc
  }
  
  /* enable a specified pinmux by writing to registers */
 -static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
 -                                      unsigned group)
 +static int samsung_pinmux_set_mux(struct pinctrl_dev *pctldev,
 +                                unsigned selector,
 +                                unsigned group)
  {
        samsung_pinmux_setup(pctldev, selector, group, true);
        return 0;
@@@ -414,7 -413,7 +414,7 @@@ static const struct pinmux_ops samsung_
        .get_functions_count    = samsung_get_functions_count,
        .get_function_name      = samsung_pinmux_get_fname,
        .get_function_groups    = samsung_pinmux_get_groups,
 -      .enable                 = samsung_pinmux_enable,
 +      .set_mux                = samsung_pinmux_set_mux,
  };
  
  /* set or get the pin config settings for a specified pin */
@@@ -946,9 -945,7 +946,7 @@@ static int samsung_gpiolib_register(str
  
  fail:
        for (--i, --bank; i >= 0; --i, --bank)
-               if (gpiochip_remove(&bank->gpio_chip))
-                       dev_err(&pdev->dev, "gpio chip %s remove failed\n",
-                                                       bank->gpio_chip.label);
+               gpiochip_remove(&bank->gpio_chip);
        return ret;
  }
  
@@@ -958,16 -955,11 +956,11 @@@ static int samsung_gpiolib_unregister(s
  {
        struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
        struct samsung_pin_bank *bank = ctrl->pin_banks;
-       int ret = 0;
        int i;
  
-       for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
-               ret = gpiochip_remove(&bank->gpio_chip);
-       if (ret)
-               dev_err(&pdev->dev, "gpio chip remove failed\n");
-       return ret;
+       for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
+               gpiochip_remove(&bank->gpio_chip);
+       return 0;
  }
  
  static const struct of_device_id samsung_pinctrl_dt_match[];
index b713bd59ffbb8f11b5283bff796c8e239e1a8f2d,25eefdbb76b6b1e636420a8528657be8571e42a5..4c831fdfcc2fb151db757198e5497a3a5d9497fc
@@@ -58,18 -58,17 +58,18 @@@ static const char *sirfsoc_get_group_na
        return sirfsoc_pin_groups[selector].name;
  }
  
 -static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
 -                             const unsigned **pins,
 -                             unsigned *num_pins)
 +static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev,
 +                              unsigned selector,
 +                              const unsigned **pins,
 +                              unsigned *num_pins)
  {
        *pins = sirfsoc_pin_groups[selector].pins;
        *num_pins = sirfsoc_pin_groups[selector].num_pins;
        return 0;
  }
  
 -static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
 -                 unsigned offset)
 +static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev,
 +                              struct seq_file *s, unsigned offset)
  {
        seq_printf(s, " " DRIVER_NAME);
  }
@@@ -139,25 -138,22 +139,25 @@@ static struct pinctrl_ops sirfsoc_pctrl
  static struct sirfsoc_pmx_func *sirfsoc_pmx_functions;
  static int sirfsoc_pmxfunc_cnt;
  
 -static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector,
 -      bool enable)
 +static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx,
 +                                      unsigned selector, bool enable)
  {
        int i;
 -      const struct sirfsoc_padmux *mux = sirfsoc_pmx_functions[selector].padmux;
 +      const struct sirfsoc_padmux *mux =
 +              sirfsoc_pmx_functions[selector].padmux;
        const struct sirfsoc_muxmask *mask = mux->muxmask;
  
        for (i = 0; i < mux->muxmask_counts; i++) {
                u32 muxval;
                if (!spmx->is_marco) {
 -                      muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
 +                      muxval = readl(spmx->gpio_virtbase +
 +                              SIRFSOC_GPIO_PAD_EN(mask[i].group));
                        if (enable)
                                muxval = muxval & ~mask[i].mask;
                        else
                                muxval = muxval | mask[i].mask;
 -                      writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
 +                      writel(muxval, spmx->gpio_virtbase +
 +                              SIRFSOC_GPIO_PAD_EN(mask[i].group));
                } else {
                        if (enable)
                                writel(mask[i].mask, spmx->gpio_virtbase +
        }
  }
  
 -static int sirfsoc_pinmux_enable(struct pinctrl_dev *pmxdev, unsigned selector,
 -      unsigned group)
 +static int sirfsoc_pinmux_set_mux(struct pinctrl_dev *pmxdev,
 +                              unsigned selector,
 +                              unsigned group)
  {
        struct sirfsoc_pmx *spmx;
  
@@@ -202,10 -197,9 +202,10 @@@ static const char *sirfsoc_pinmux_get_f
        return sirfsoc_pmx_functions[selector].name;
  }
  
 -static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
 -                             const char * const **groups,
 -                             unsigned * const num_groups)
 +static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev,
 +                              unsigned selector,
 +                              const char * const **groups,
 +                              unsigned * const num_groups)
  {
        *groups = sirfsoc_pmx_functions[selector].groups;
        *num_groups = sirfsoc_pmx_functions[selector].num_groups;
@@@ -224,11 -218,9 +224,11 @@@ static int sirfsoc_pinmux_request_gpio(
        spmx = pinctrl_dev_get_drvdata(pmxdev);
  
        if (!spmx->is_marco) {
 -              muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
 +              muxval = readl(spmx->gpio_virtbase +
 +                      SIRFSOC_GPIO_PAD_EN(group));
                muxval = muxval | (1 << (offset - range->pin_base));
 -              writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
 +              writel(muxval, spmx->gpio_virtbase +
 +                      SIRFSOC_GPIO_PAD_EN(group));
        } else {
                writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
                        SIRFSOC_GPIO_PAD_EN(group));
  }
  
  static struct pinmux_ops sirfsoc_pinmux_ops = {
 -      .enable = sirfsoc_pinmux_enable,
 +      .set_mux = sirfsoc_pinmux_set_mux,
        .get_functions_count = sirfsoc_pinmux_get_funcs_count,
        .get_function_name = sirfsoc_pinmux_get_func_name,
        .get_function_groups = sirfsoc_pinmux_get_groups,
@@@ -526,29 -518,24 +526,29 @@@ static int sirfsoc_gpio_irq_type(struc
        case IRQ_TYPE_NONE:
                break;
        case IRQ_TYPE_EDGE_RISING:
 -              val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
 +              val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
 +                      SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
                val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
                break;
        case IRQ_TYPE_EDGE_FALLING:
                val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
 -              val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
 +              val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
 +                      SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
                break;
        case IRQ_TYPE_EDGE_BOTH:
 -              val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
 -                       SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
 +              val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
 +                      SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
 +                      SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
                break;
        case IRQ_TYPE_LEVEL_LOW:
 -              val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
 +              val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
 +                      SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
                val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
                break;
        case IRQ_TYPE_LEVEL_HIGH:
                val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
 -              val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
 +              val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
 +                      SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
                break;
        }
  
@@@ -707,8 -694,7 +707,8 @@@ static inline void sirfsoc_gpio_set_out
        spin_unlock_irqrestore(&bank->lock, flags);
  }
  
 -static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
 +static int sirfsoc_gpio_direction_output(struct gpio_chip *chip,
 +      unsigned gpio, int value)
  {
        struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
        struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
@@@ -853,7 -839,7 +853,7 @@@ static int sirfsoc_gpio_probe(struct de
        if (err) {
                dev_err(&pdev->dev,
                        "could not connect irqchip to gpiochip\n");
 -              goto out;
 +              goto out_banks;
        }
  
        for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
  
  out_no_range:
  out_banks:
-       if (gpiochip_remove(&sgpio->chip.gc))
-               dev_err(&pdev->dev, "could not remove gpio chip\n");
+       gpiochip_remove(&sgpio->chip.gc);
  out:
        iounmap(regs);
        return err;
@@@ -912,8 -897,8 +911,8 @@@ static int __init sirfsoc_gpio_init(voi
  }
  subsys_initcall(sirfsoc_gpio_init);
  
 -MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
 -      "Yuping Luo <yuping.luo@csr.com>, "
 -      "Barry Song <baohua.song@csr.com>");
 +MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>");
 +MODULE_AUTHOR("Yuping Luo <yuping.luo@csr.com>");
 +MODULE_AUTHOR("Barry Song <baohua.song@csr.com>");
  MODULE_DESCRIPTION("SIRFSOC pin control driver");
  MODULE_LICENSE("GPL");
index d8a118d3956683165f7d2b9f2663cc9e07403727,3304d9227c3cb9d8f4e4794f2f3e077a7b3fb2e6..c64776f71809f0fc9ee04232a9cef72647897989
@@@ -58,14 -58,14 +58,14 @@@ static int pio2_gpio_get(struct gpio_ch
        if (reg & PIO2_CHANNEL_BIT[offset]) {
                if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
                        return 0;
 -              else
 -                      return 1;
 -      } else {
 -              if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
 -                      return 1;
 -              else
 -                      return 0;
 +
 +              return 1;
        }
 +
 +      if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
 +              return 1;
 +
 +      return 0;
  }
  
  static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset,
@@@ -221,9 -221,7 +221,7 @@@ void pio2_gpio_exit(struct pio2_card *c
  {
        const char *label = card->gc.label;
  
-       if (gpiochip_remove(&(card->gc)))
-               dev_err(&card->vdev->dev, "Failed to remove GPIO\n");
+       gpiochip_remove(&(card->gc));
        kfree(label);
  }
  
index c5e41da20112e3a244d2cd9672b2bc5b7f703184,719fab209158f5dbacda78e820bd51942c44881a..249db3057e4dc0454f8947f305e6e3b94e138719
@@@ -56,6 -56,8 +56,8 @@@ struct seq_file
   *    as the chip access may sleep when e.g. reading out the IRQ status
   *    registers.
   * @exported: flags if the gpiochip is exported for use from sysfs. Private.
+  * @irq_not_threaded: flag must be set if @can_sleep is set but the
+  *    IRQs don't need to be threaded
   *
   * A gpio_chip can help platforms abstract various sources of GPIOs so
   * they can all be accessed through a common programing interface.
@@@ -101,11 -103,12 +103,12 @@@ struct gpio_chip 
        struct gpio_desc        *desc;
        const char              *const *names;
        bool                    can_sleep;
+       bool                    irq_not_threaded;
        bool                    exported;
  
  #ifdef CONFIG_GPIOLIB_IRQCHIP
        /*
 -       * With CONFIG_GPIO_IRQCHIP we get an irqchip inside the gpiolib
 +       * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
         * to handle IRQs for most practical cases.
         */
        struct irq_chip         *irqchip;
@@@ -141,7 -144,7 +144,7 @@@ extern const char *gpiochip_is_requeste
  
  /* add/remove chips */
  extern int gpiochip_add(struct gpio_chip *chip);
- extern int gpiochip_remove(struct gpio_chip *chip);
+ extern void gpiochip_remove(struct gpio_chip *chip);
  extern struct gpio_chip *gpiochip_find(void *data,
                              int (*match)(struct gpio_chip *chip, void *data));
  
@@@ -164,9 -167,10 +167,10 @@@ int gpiochip_irqchip_add(struct gpio_ch
                irq_flow_handler_t handler,
                unsigned int type);
  
 -#endif /* CONFIG_GPIO_IRQCHIP */
 +#endif /* CONFIG_GPIOLIB_IRQCHIP */
  
- int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
+ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum,
+                                           const char *label);
  void gpiochip_free_own_desc(struct gpio_desc *desc);
  
  #else /* CONFIG_GPIOLIB */