Merge tag 'pinctrl-for-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 17:23:30 +0000 (09:23 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 17:23:30 +0000 (09:23 -0800)
Pull pinctrl changes from Linus Walleij:
 "These are the main pinctrl changes for the v3.9 merge window.  The
  most interesting change by far is how the device core grabs pinctrl
  default handles avoiding the need to stick boilerplate into driver
  consumers.

   - Grabbing of default pinctrl handles from the device core.  These
     are the hunks hitting drivers/base.  All is ACKed by Greg, after a
     long discussion about different alternatives.

   - Some stuff also touches the MFD and ARM SoC trees, this has been
     coordinated and ACKed.

   - New drivers for:
     - The Tegra 114 sub-SoC
     - Allwinner sunxi
     - New ABx500 driver and sub-SoC drivers for AB8500, AB8505, AB9540
       and AB8540.

   - Make it possible for hogged pins to enter a sleep mode, and make it
     possible for drivers to control that mode.

   - Various clean-up, extensions and device tree support to various pin
     controllers."

* tag 'pinctrl-for-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (68 commits)
  pinctrl: tegra: add clfvs function to Tegra114 support
  pinctrl: generic: rename input schmitt disable
  pinctrl/pinconfig: add debug interface
  pinctrl: samsung: remove duplicated line
  ARM: ux500: use real AB8500 IRQ numbers instead of virtual ones
  ARM: ux500: remove irq_base property from platform_data
  pinctrl/abx500: use direct IRQ defines
  pinctrl/abx500: replace IRQ offsets with table read-in values
  pinctrl/abx500: move IRQ handling to ab8500-core
  pinctrl: exynos5440: remove erroneous __init
  pinctrl/abx500: adjust offset for get_mode()
  pinctrl/abx500: add Device Tree support
  pinctrl/abx500: align GPIO cluster boundaries
  pinctrl/abx500: prevent error path from corrupting returning error
  pinctrl: sunxi: add of_xlate function
  pinctrl/lantiq: fix pin number in ltq_pmx_gpio_request_enable
  pinctrl/lantiq: add functionality to falcon_pinconf_dbg_show
  pinctrl/lantiq: fix pinconfig parameters
  pinctrl/lantiq: one of the boot leds was defined incorrectly
  pinctrl/lantiq: only probe available pad controllers
  ...

1  2 
arch/arm/Kconfig
drivers/pinctrl/Kconfig
drivers/pinctrl/pinctrl-nomadik.c

diff --combined arch/arm/Kconfig
index 9bbe760f2352dc86266ace6a8d4d4d5f08a26eda,9c635b6cc3ead1e67cf33f614a37f8f63774caf1..6c0900a9bf5c30039bf852ea42bd3612b522244e
@@@ -36,6 -36,7 +36,6 @@@ config AR
        select HAVE_GENERIC_HARDIRQS
        select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
        select HAVE_IDE if PCI || ISA || PCMCIA
 -      select HAVE_IRQ_WORK
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
@@@ -1636,7 -1637,7 +1636,7 @@@ config ARCH_NR_GPI
        default 355 if ARCH_U8500
        default 264 if MACH_H4700
        default 512 if SOC_OMAP5
-       default 288 if ARCH_VT8500
+       default 288 if ARCH_VT8500 || ARCH_SUNXI
        default 0
        help
          Maximum number of GPIOs in the system.
diff --combined drivers/pinctrl/Kconfig
index a5f3c8ca480e1f078d43f0884f1d4a299fccd660,d186c582513325a3379c261ed328bac1d6913363..393b0ecf4ca4f21ec3731db30e9531bf7eaa4043
@@@ -26,6 -26,29 +26,29 @@@ config DEBUG_PINCTR
        help
          Say Y here to add some extra checks and diagnostics to PINCTRL calls.
  
+ config PINCTRL_ABX500
+       bool "ST-Ericsson ABx500 family Mixed Signal Circuit gpio functions"
+       depends on AB8500_CORE
+       select GENERIC_PINCONF
+       help
+         Select this to enable the ABx500 family IC GPIO driver
+ config PINCTRL_AB8500
+       bool "AB8500 pin controller driver"
+       depends on PINCTRL_ABX500 && ARCH_U8500
+ config PINCTRL_AB8540
+       bool "AB8540 pin controller driver"
+       depends on PINCTRL_ABX500 && ARCH_U8500
+ config PINCTRL_AB9540
+       bool "AB9540 pin controller driver"
+       depends on PINCTRL_ABX500 && ARCH_U8500
+ config PINCTRL_AB8505
+       bool "AB8505 pin controller driver"
+       depends on PINCTRL_ABX500 && ARCH_U8500
  config PINCTRL_AT91
        bool "AT91 pinctrl driver"
        depends on OF
@@@ -151,6 -174,11 +174,11 @@@ config PINCTRL_SIR
        depends on ARCH_SIRF
        select PINMUX
  
+ config PINCTRL_SUNXI
+       bool
+       select PINMUX
+       select GENERIC_PINCONF
  config PINCTRL_TEGRA
        bool
        select PINMUX
@@@ -164,6 -192,10 +192,10 @@@ config PINCTRL_TEGRA3
        bool
        select PINCTRL_TEGRA
  
+ config PINCTRL_TEGRA114
+       bool
+       select PINCTRL_TEGRA
  config PINCTRL_U300
        bool "U300 pin controller driver"
        depends on ARCH_U300
@@@ -181,6 -213,7 +213,6 @@@ config PINCTRL_COH90
  
  config PINCTRL_SAMSUNG
        bool
 -      depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
  
index 5767b18ebdff6d1639bd37c6007f9c93553a3f58,b885c0911e83348a8bd6be1c42332ef97a483465..de9e8519b803570e4188bb58d5b0c77cf6ab004f
@@@ -25,6 -25,8 +25,8 @@@
  #include <linux/irqdomain.h>
  #include <linux/slab.h>
  #include <linux/of_device.h>
+ #include <linux/of_address.h>
+ #include <linux/pinctrl/machine.h>
  #include <linux/pinctrl/pinctrl.h>
  #include <linux/pinctrl/pinmux.h>
  #include <linux/pinctrl/pinconf.h>
@@@ -32,8 -34,8 +34,8 @@@
  #include <linux/pinctrl/consumer.h>
  #include <linux/platform_data/pinctrl-nomadik.h>
  #include <asm/mach/irq.h>
- #include <mach/irqs.h>
  #include "pinctrl-nomadik.h"
+ #include "core.h"
  
  /*
   * The GPIO module in the Nomadik family of Systems-on-Chip is an
@@@ -216,7 -218,7 +218,7 @@@ nmk_gpio_disable_lazy_irq(struct nmk_gp
        u32 falling = nmk_chip->fimsc & BIT(offset);
        u32 rising = nmk_chip->rimsc & BIT(offset);
        int gpio = nmk_chip->chip.base + offset;
-       int irq = NOMADIK_GPIO_TO_IRQ(gpio);
+       int irq = irq_find_mapping(nmk_chip->domain, offset);
        struct irq_data *d = irq_get_irq_data(irq);
  
        if (!rising && !falling)
@@@ -676,7 -678,7 +678,7 @@@ int nmk_gpio_set_mode(int gpio, int gpi
  }
  EXPORT_SYMBOL(nmk_gpio_set_mode);
  
 -static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
 +static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
  {
        int i;
        u16 reg;
@@@ -1341,8 -1343,7 +1343,7 @@@ static int nmk_gpio_probe(struct platfo
  
                if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
                        dev_err(&dev->dev, "gpio-bank property not found\n");
-                       ret = -EINVAL;
-                       goto out;
+                       return -EINVAL;
                }
  
                pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP;
        }
  
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENOENT;
-               goto out;
-       }
+       if (!res)
+               return -ENOENT;
  
        irq = platform_get_irq(dev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto out;
-       }
+       if (irq < 0)
+               return irq;
  
        secondary_irq = platform_get_irq(dev, 1);
-       if (secondary_irq >= 0 && !pdata->get_secondary_status) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (secondary_irq >= 0 && !pdata->get_secondary_status)
+               return -EINVAL;
  
        base = devm_request_and_ioremap(&dev->dev, res);
-       if (!base) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!base)
+               return -ENOMEM;
  
        clk = devm_clk_get(&dev->dev, NULL);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               goto out;
-       }
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
        clk_prepare(clk);
  
        nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL);
-       if (!nmk_chip) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!nmk_chip)
+               return -ENOMEM;
  
        /*
         * The virt address in nmk_chip->addr is in the nomadik register space,
  
        ret = gpiochip_add(&nmk_chip->chip);
        if (ret)
-               goto out;
+               return ret;
  
        BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
  
        platform_set_drvdata(dev, nmk_chip);
  
        if (!np)
-               irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
+               irq_start = pdata->first_irq;
        nmk_chip->domain = irq_domain_add_simple(np,
                                NMK_GPIO_PER_CHIP, irq_start,
                                &nmk_gpio_irq_simple_ops, nmk_chip);
        if (!nmk_chip->domain) {
                dev_err(&dev->dev, "failed to create irqdomain\n");
-               ret = -ENOSYS;
-               goto out;
+               /* Just do this, no matter if it fails */
+               ret = gpiochip_remove(&nmk_chip->chip);
+               return -ENOSYS;
        }
  
        nmk_gpio_init_irq(nmk_chip);
        dev_info(&dev->dev, "at address %p\n", nmk_chip->addr);
  
        return 0;
- out:
-       dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
-                 pdata->first_gpio, pdata->first_gpio+31);
-       return ret;
  }
  
  static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev)
@@@ -1508,11 -1492,285 +1492,285 @@@ 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)
+ {
+       if (*num_maps == *reserved_maps)
+               return -ENOSPC;
+       (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+       (*map)[*num_maps].data.mux.group = group;
+       (*map)[*num_maps].data.mux.function = function;
+       (*num_maps)++;
+       return 0;
+ }
+ static int nmk_dt_add_map_configs(struct pinctrl_map **map,
+               unsigned *reserved_maps,
+               unsigned *num_maps, const char *group,
+               unsigned long *configs, unsigned num_configs)
+ {
+       unsigned long *dup_configs;
+       if (*num_maps == *reserved_maps)
+               return -ENOSPC;
+       dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
+                             GFP_KERNEL);
+       if (!dup_configs)
+               return -ENOMEM;
+       (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
+       (*map)[*num_maps].data.configs.group_or_pin = group;
+       (*map)[*num_maps].data.configs.configs = dup_configs;
+       (*map)[*num_maps].data.configs.num_configs = num_configs;
+       (*num_maps)++;
+       return 0;
+ }
+ #define NMK_CONFIG_PIN(x,y) { .property = x, .config = y, }
+ #define NMK_CONFIG_PIN_ARRAY(x,y) { .property = x, .choice = y, \
+       .size = ARRAY_SIZE(y), }
+ static const unsigned long nmk_pin_input_modes[] = {
+       PIN_INPUT_NOPULL,
+       PIN_INPUT_PULLUP,
+       PIN_INPUT_PULLDOWN,
+ };
+ static const unsigned long nmk_pin_output_modes[] = {
+       PIN_OUTPUT_LOW,
+       PIN_OUTPUT_HIGH,
+       PIN_DIR_OUTPUT,
+ };
+ static const unsigned long nmk_pin_sleep_modes[] = {
+       PIN_SLEEPMODE_DISABLED,
+       PIN_SLEEPMODE_ENABLED,
+ };
+ static const unsigned long nmk_pin_sleep_input_modes[] = {
+       PIN_SLPM_INPUT_NOPULL,
+       PIN_SLPM_INPUT_PULLUP,
+       PIN_SLPM_INPUT_PULLDOWN,
+       PIN_SLPM_DIR_INPUT,
+ };
+ static const unsigned long nmk_pin_sleep_output_modes[] = {
+       PIN_SLPM_OUTPUT_LOW,
+       PIN_SLPM_OUTPUT_HIGH,
+       PIN_SLPM_DIR_OUTPUT,
+ };
+ static const unsigned long nmk_pin_sleep_wakeup_modes[] = {
+       PIN_SLPM_WAKEUP_DISABLE,
+       PIN_SLPM_WAKEUP_ENABLE,
+ };
+ static const unsigned long nmk_pin_gpio_modes[] = {
+       PIN_GPIOMODE_DISABLED,
+       PIN_GPIOMODE_ENABLED,
+ };
+ static const unsigned long nmk_pin_sleep_pdis_modes[] = {
+       PIN_SLPM_PDIS_DISABLED,
+       PIN_SLPM_PDIS_ENABLED,
+ };
+ struct nmk_cfg_param {
+       const char *property;
+       unsigned long config;
+       const unsigned long *choice;
+       int size;
+ };
+ static const struct nmk_cfg_param nmk_cfg_params[] = {
+       NMK_CONFIG_PIN_ARRAY("ste,input",               nmk_pin_input_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,output",              nmk_pin_output_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,sleep",               nmk_pin_sleep_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,sleep-input",         nmk_pin_sleep_input_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,sleep-output",        nmk_pin_sleep_output_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup",        nmk_pin_sleep_wakeup_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,gpio",                nmk_pin_gpio_modes),
+       NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable",  nmk_pin_sleep_pdis_modes),
+ };
+ static int nmk_dt_pin_config(int index, int val, unsigned long *config)
+ {
+       int ret = 0;
+       if (nmk_cfg_params[index].choice == NULL)
+               *config = nmk_cfg_params[index].config;
+       else {
+               /* test if out of range */
+               if  (val < nmk_cfg_params[index].size) {
+                       *config = nmk_cfg_params[index].config |
+                               nmk_cfg_params[index].choice[val];
+               }
+       }
+       return ret;
+ }
+ static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name)
+ {
+       int i, pin_number;
+       struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+       if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
+               for (i = 0; i < npct->soc->npins; i++)
+                       if (npct->soc->pins[i].number == pin_number)
+                               return npct->soc->pins[i].name;
+       return NULL;
+ }
+ static bool nmk_pinctrl_dt_get_config(struct device_node *np,
+               unsigned long *configs)
+ {
+       bool has_config = 0;
+       unsigned long cfg = 0;
+       int i, val, ret;
+       for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) {
+               ret = of_property_read_u32(np,
+                               nmk_cfg_params[i].property, &val);
+               if (ret != -EINVAL) {
+                       if (nmk_dt_pin_config(i, val, &cfg) == 0) {
+                               *configs |= cfg;
+                               has_config = 1;
+                       }
+               }
+       }
+       return has_config;
+ }
+ int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+               struct device_node *np,
+               struct pinctrl_map **map,
+               unsigned *reserved_maps,
+               unsigned *num_maps)
+ {
+       int ret;
+       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) {
+                       ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps,
+                                         group, function);
+                       if (ret < 0)
+                               goto exit;
+               }
+               if (has_config) {
+                       gpio_name = nmk_find_pin_name(pctldev, group);
+                       ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps,
+                                             gpio_name, &configs, 1);
+                       if (ret < 0)
+                               goto exit;
+               }
+       }
+ exit:
+       return ret;
+ }
+ int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                struct device_node *np_config,
+                                struct pinctrl_map **map, unsigned *num_maps)
+ {
+       unsigned reserved_maps;
+       struct device_node *np;
+       int ret;
+       reserved_maps = 0;
+       *map = NULL;
+       *num_maps = 0;
+       for_each_child_of_node(np_config, np) {
+               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);
+                       return ret;
+               }
+       }
+       return 0;
+ }
  static struct pinctrl_ops nmk_pinctrl_ops = {
        .get_groups_count = nmk_get_groups_cnt,
        .get_group_name = nmk_get_group_name,
        .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,
  };
  
  static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
@@@ -1846,16 -2104,39 +2104,39 @@@ static struct pinctrl_desc nmk_pinctrl_
  
  static const struct of_device_id nmk_pinctrl_match[] = {
        {
-               .compatible = "stericsson,nmk_pinctrl",
+               .compatible = "stericsson,nmk-pinctrl",
                .data = (void *)PINCTRL_NMK_DB8500,
        },
        {},
  };
  
+ static int nmk_pinctrl_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+       struct nmk_pinctrl *npct;
+       npct = platform_get_drvdata(pdev);
+       if (!npct)
+               return -EINVAL;
+       return pinctrl_force_sleep(npct->pctl);
+ }
+ static int nmk_pinctrl_resume(struct platform_device *pdev)
+ {
+       struct nmk_pinctrl *npct;
+       npct = platform_get_drvdata(pdev);
+       if (!npct)
+               return -EINVAL;
+       return pinctrl_force_default(npct->pctl);
+ }
  static int nmk_pinctrl_probe(struct platform_device *pdev)
  {
        const struct platform_device_id *platid = platform_get_device_id(pdev);
        struct device_node *np = pdev->dev.of_node;
+       struct device_node *prcm_np;
        struct nmk_pinctrl *npct;
        struct resource *res;
        unsigned int version = 0;
        if (version == PINCTRL_NMK_DB8540)
                nmk_pinctrl_db8540_init(&npct->soc);
  
+       if (np) {
+               prcm_np = of_parse_phandle(np, "prcm", 0);
+               if (prcm_np)
+                       npct->prcm_base = of_iomap(prcm_np, 0);
+       }
+       /* Allow platform passed information to over-write DT. */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res) {
+       if (res)
                npct->prcm_base = devm_ioremap(&pdev->dev, res->start,
                                               resource_size(res));
-               if (!npct->prcm_base) {
-                       dev_err(&pdev->dev,
-                               "failed to ioremap PRCM registers\n");
-                       return -ENOMEM;
+       if (!npct->prcm_base) {
+               if (version == PINCTRL_NMK_STN8815) {
+                       dev_info(&pdev->dev,
+                                "No PRCM base, "
+                                "assuming no ALT-Cx control is available\n");
+               } else {
+                       dev_err(&pdev->dev, "missing PRCM base address\n");
+                       return -EINVAL;
                }
-       } else if (version == PINCTRL_NMK_STN8815) {
-               dev_info(&pdev->dev,
-                        "No PRCM base, assume no ALT-Cx control is available\n");
-       } else {
-               dev_err(&pdev->dev, "missing PRCM base address\n");
-               return -EINVAL;
        }
  
        /*
@@@ -1963,6 -2249,10 +2249,10 @@@ static struct platform_driver nmk_pinct
        },
        .probe = nmk_pinctrl_probe,
        .id_table = nmk_pinctrl_id,
+ #ifdef CONFIG_PM
+       .suspend = nmk_pinctrl_suspend,
+       .resume = nmk_pinctrl_resume,
+ #endif
  };
  
  static int __init nmk_gpio_init(void)