pinctrl: Pass all configs to driver on pin_config_set()
authorSherman Yin <syin@broadcom.com>
Tue, 27 Aug 2013 18:32:12 +0000 (11:32 -0700)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 28 Aug 2013 11:34:41 +0000 (13:34 +0200)
When setting pin configuration in the pinctrl framework, pin_config_set() or
pin_config_group_set() is called in a loop to set one configuration at a time
for the specified pin or group.

This patch 1) removes the loop and 2) changes the API to pass the whole pin
config array to the driver.  It is now up to the driver to loop through the
configs.  This allows the driver to potentially combine configs and reduce the
number of writes to pin config registers.

All c files changed have been build-tested to verify the change compiles and
that the corresponding .o is successfully generated.

Signed-off-by: Sherman Yin <syin@broadcom.com>
Reviewed-by: Christian Daudt <csd@broadcom.com>
Reviewed-by: Matt Porter <matt.porter@linaro.org>
Tested-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
24 files changed:
drivers/pinctrl/mvebu/pinctrl-mvebu.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-abx500.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-bcm2835.c
drivers/pinctrl/pinctrl-exynos5440.c
drivers/pinctrl/pinctrl-falcon.c
drivers/pinctrl/pinctrl-imx.c
drivers/pinctrl/pinctrl-mxs.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-palmas.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-st.c
drivers/pinctrl/pinctrl-sunxi.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tz1090-pdc.c
drivers/pinctrl/pinctrl-tz1090.c
drivers/pinctrl/pinctrl-u300.c
drivers/pinctrl/pinctrl-xway.c
drivers/pinctrl/sh-pfc/pinctrl.c
drivers/pinctrl/vt8500/pinctrl-wmt.c
include/linux/pinctrl/pinconf.h

index bb7ddb1bc89f67b7c0ff2c864c6743d8125e169c..e78c041c3c732df9221a87638b85e68687d7e3d7 100644 (file)
@@ -191,18 +191,27 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
-                               unsigned gid, unsigned long config)
+                               unsigned gid, unsigned long *configs,
+                               unsigned num_configs)
 {
        struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+       int i, ret;
 
        if (!grp->ctrl)
                return -EINVAL;
 
-       if (grp->ctrl->mpp_set)
-               return grp->ctrl->mpp_set(grp->ctrl, config);
+       for (i = 0; i < num_configs; i++) {
+               if (grp->ctrl->mpp_set)
+                       ret = grp->ctrl->mpp_set(grp->ctrl, configs[i]);
+               else
+                       ret = mvebu_common_mpp_set(pctl, grp, configs[i]);
 
-       return mvebu_common_mpp_set(pctl, grp, config);
+               if (ret)
+                       return ret;
+       } /* for each config */
+
+       return 0;
 }
 
 static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
@@ -303,6 +312,7 @@ static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid,
        struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
        struct mvebu_mpp_ctrl_setting *setting;
        int ret;
+       unsigned long config;
 
        setting = mvebu_pinctrl_find_setting_by_name(pctl, grp,
                                                     func->name);
@@ -313,7 +323,8 @@ static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid,
                return -EINVAL;
        }
 
-       ret = mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+       config = setting->val;
+       ret = mvebu_pinconf_group_set(pctldev, grp->gid, &config, 1);
        if (ret) {
                dev_err(pctl->dev, "cannot set group %s to %s\n",
                        func->groups[gid], func->name);
@@ -329,6 +340,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
        struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        struct mvebu_pinctrl_group *grp;
        struct mvebu_mpp_ctrl_setting *setting;
+       unsigned long config;
 
        grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
        if (!grp)
@@ -341,7 +353,9 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
        if (!setting)
                return -ENOTSUPP;
 
-       return mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+       config = setting->val;
+
+       return mvebu_pinconf_group_set(pctldev, grp->gid, &config, 1);
 }
 
 static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
index 8da2d6db228c07dc17fd0f83b17f50238b2e7ef2..a138965c01cbc6e4029615bc080790d2338e59e2 100644 (file)
@@ -158,7 +158,7 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
 {
        struct pinctrl_dev *pctldev = setting->pctldev;
        const struct pinconf_ops *ops = pctldev->desc->confops;
-       int i, ret;
+       int ret;
 
        if (!ops) {
                dev_err(pctldev->dev, "missing confops\n");
@@ -171,17 +171,15 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
                        dev_err(pctldev->dev, "missing pin_config_set op\n");
                        return -EINVAL;
                }
-               for (i = 0; i < setting->data.configs.num_configs; i++) {
-                       ret = ops->pin_config_set(pctldev,
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs[i]);
-                       if (ret < 0) {
-                               dev_err(pctldev->dev,
-                                       "pin_config_set op failed for pin %d config %08lx\n",
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs[i]);
-                               return ret;
-                       }
+               ret = ops->pin_config_set(pctldev,
+                               setting->data.configs.group_or_pin,
+                               setting->data.configs.configs,
+                               setting->data.configs.num_configs);
+               if (ret < 0) {
+                       dev_err(pctldev->dev,
+                               "pin_config_set op failed for pin %d\n",
+                               setting->data.configs.group_or_pin);
+                       return ret;
                }
                break;
        case PIN_MAP_TYPE_CONFIGS_GROUP:
@@ -190,17 +188,15 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
                                "missing pin_config_group_set op\n");
                        return -EINVAL;
                }
-               for (i = 0; i < setting->data.configs.num_configs; i++) {
-                       ret = ops->pin_config_group_set(pctldev,
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs[i]);
-                       if (ret < 0) {
-                               dev_err(pctldev->dev,
-                                       "pin_config_group_set op failed for group %d config %08lx\n",
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs[i]);
-                               return ret;
-                       }
+               ret = ops->pin_config_group_set(pctldev,
+                               setting->data.configs.group_or_pin,
+                               setting->data.configs.configs,
+                               setting->data.configs.num_configs);
+               if (ret < 0) {
+                       dev_err(pctldev->dev,
+                               "pin_config_group_set op failed for group %d\n",
+                               setting->data.configs.group_or_pin);
+                       return ret;
                }
                break;
        default:
index 1d3f988c2c8bff0cfff3e5fdebba241deaaff9d4..8f25df06bc6b267a7642ef015e967b092bd70738 100644 (file)
@@ -1041,98 +1041,115 @@ static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
 
 static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
                          unsigned pin,
-                         unsigned long config)
+                         unsigned long *configs,
+                         unsigned num_configs)
 {
        struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
        struct gpio_chip *chip = &pct->chip;
        unsigned offset;
        int ret = -EINVAL;
-       enum pin_config_param param = pinconf_to_config_param(config);
-       enum pin_config_param argument = pinconf_to_config_argument(config);
-
-       dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n",
-               pin, config, (param == PIN_CONFIG_OUTPUT) ? "output " : "input",
-               (param == PIN_CONFIG_OUTPUT) ? (argument ? "high" : "low") :
-               (argument ? "pull up" : "pull down"));
-
-       /* on ABx500, there is no GPIO0, so adjust the offset */
-       offset = pin - 1;
-
-       switch (param) {
-       case PIN_CONFIG_BIAS_DISABLE:
-               ret = abx500_gpio_direction_input(chip, offset);
-               if (ret < 0)
-                       goto out;
-               /*
-                * Some chips only support pull down, while some actually
-                * support both pull up and pull down. Such chips have
-                * a "pullud" range specified for the pins that support
-                * both features. If the pin is not within that range, we
-                * fall back to the old bit set that only support pull down.
-                */
-               if (abx500_pullud_supported(chip, pin))
-                       ret = abx500_set_pull_updown(pct,
-                               pin,
-                               ABX500_GPIO_PULL_NONE);
-               else
-                       /* Chip only supports pull down */
-                       ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
-                               offset, ABX500_GPIO_PULL_NONE);
-               break;
-
-       case PIN_CONFIG_BIAS_PULL_DOWN:
-               ret = abx500_gpio_direction_input(chip, offset);
-               if (ret < 0)
-                       goto out;
-               /*
-                * if argument = 1 set the pull down
-                * else clear the pull down
-                * Some chips only support pull down, while some actually
-                * support both pull up and pull down. Such chips have
-                * a "pullud" range specified for the pins that support
-                * both features. If the pin is not within that range, we
-                * fall back to the old bit set that only support pull down.
-                */
-               if (abx500_pullud_supported(chip, pin))
-                       ret = abx500_set_pull_updown(pct,
-                               pin,
-                               argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
-               else
-                       /* Chip only supports pull down */
-                       ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
-                               offset,
-                               argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
-               break;
-
-       case PIN_CONFIG_BIAS_PULL_UP:
-               ret = abx500_gpio_direction_input(chip, offset);
-               if (ret < 0)
-                       goto out;
-               /*
-                * if argument = 1 set the pull up
-                * else clear the pull up
-                */
-               ret = abx500_gpio_direction_input(chip, offset);
-               /*
-                * Some chips only support pull down, while some actually
-                * support both pull up and pull down. Such chips have
-                * a "pullud" range specified for the pins that support
-                * both features. If the pin is not within that range, do
-                * nothing
-                */
-               if (abx500_pullud_supported(chip, pin))
-                       ret = abx500_set_pull_updown(pct,
-                               pin,
-                               argument ? ABX500_GPIO_PULL_UP : ABX500_GPIO_PULL_NONE);
-               break;
+       int i;
+       enum pin_config_param param;
+       enum pin_config_param argument;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               argument = pinconf_to_config_argument(configs[i]);
+
+               dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n",
+                       pin, configs[i],
+                       (param == PIN_CONFIG_OUTPUT) ? "output " : "input",
+                       (param == PIN_CONFIG_OUTPUT) ?
+                       (argument ? "high" : "low") :
+                       (argument ? "pull up" : "pull down"));
+
+               /* on ABx500, there is no GPIO0, so adjust the offset */
+               offset = pin - 1;
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_DISABLE:
+                       ret = abx500_gpio_direction_input(chip, offset);
+                       if (ret < 0)
+                               goto out;
+                       /*
+                        * Some chips only support pull down, while some
+                        * actually support both pull up and pull down. Such
+                        * chips have a "pullud" range specified for the pins
+                        * that support both features. If the pin is not
+                        * within that range, we fall back to the old bit set
+                        * that only support pull down.
+                        */
+                       if (abx500_pullud_supported(chip, pin))
+                               ret = abx500_set_pull_updown(pct,
+                                       pin,
+                                       ABX500_GPIO_PULL_NONE);
+                       else
+                               /* Chip only supports pull down */
+                               ret = abx500_gpio_set_bits(chip,
+                                       AB8500_GPIO_PUD1_REG, offset,
+                                       ABX500_GPIO_PULL_NONE);
+                       break;
 
-       case PIN_CONFIG_OUTPUT:
-               ret = abx500_gpio_direction_output(chip, offset, argument);
-               break;
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       ret = abx500_gpio_direction_input(chip, offset);
+                       if (ret < 0)
+                               goto out;
+                       /*
+                        * if argument = 1 set the pull down
+                        * else clear the pull down
+                        * Some chips only support pull down, while some
+                        * actually support both pull up and pull down. Such
+                        * chips have a "pullud" range specified for the pins
+                        * that support both features. If the pin is not
+                        * within that range, we fall back to the old bit set
+                        * that only support pull down.
+                        */
+                       if (abx500_pullud_supported(chip, pin))
+                               ret = abx500_set_pull_updown(pct,
+                                       pin,
+                                       argument ? ABX500_GPIO_PULL_DOWN :
+                                       ABX500_GPIO_PULL_NONE);
+                       else
+                               /* Chip only supports pull down */
+                               ret = abx500_gpio_set_bits(chip,
+                               AB8500_GPIO_PUD1_REG,
+                                       offset,
+                                       argument ? ABX500_GPIO_PULL_DOWN :
+                                       ABX500_GPIO_PULL_NONE);
+                       break;
 
-       default:
-               dev_err(chip->dev, "illegal configuration requested\n");
-       }
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       ret = abx500_gpio_direction_input(chip, offset);
+                       if (ret < 0)
+                               goto out;
+                       /*
+                        * if argument = 1 set the pull up
+                        * else clear the pull up
+                        */
+                       ret = abx500_gpio_direction_input(chip, offset);
+                       /*
+                        * Some chips only support pull down, while some
+                        * actually support both pull up and pull down. Such
+                        * chips have a "pullud" range specified for the pins
+                        * that support both features. If the pin is not
+                        * within that range, do nothing
+                        */
+                       if (abx500_pullud_supported(chip, pin))
+                               ret = abx500_set_pull_updown(pct,
+                                       pin,
+                                       argument ? ABX500_GPIO_PULL_UP :
+                                       ABX500_GPIO_PULL_NONE);
+                       break;
+
+               case PIN_CONFIG_OUTPUT:
+                       ret = abx500_gpio_direction_output(chip, offset,
+                               argument);
+                       break;
+
+               default:
+                       dev_err(chip->dev, "illegal configuration requested\n");
+               }
+       } /* for each config */
 out:
        if (ret < 0)
                dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
index 7cce066c71b6790fd3e4f13f3ff46340fd683e64..9685ff6c8b016510c6f6df07b113b5470b5e52ce 100644 (file)
@@ -736,30 +736,40 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int at91_pinconf_set(struct pinctrl_dev *pctldev,
-                            unsigned pin_id, unsigned long config)
+                            unsigned pin_id, unsigned long *configs,
+                            unsigned num_configs)
 {
        struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
        unsigned mask;
        void __iomem *pio;
-
-       dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config);
-       pio = pin_to_controller(info, pin_to_bank(pin_id));
-       mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
-
-       if (config & PULL_UP && config & PULL_DOWN)
-               return -EINVAL;
-
-       at91_mux_set_pullup(pio, mask, config & PULL_UP);
-       at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
-       if (info->ops->set_deglitch)
-               info->ops->set_deglitch(pio, mask, config & DEGLITCH);
-       if (info->ops->set_debounce)
-               info->ops->set_debounce(pio, mask, config & DEBOUNCE,
+       int i;
+       unsigned long config;
+
+       for (i = 0; i < num_configs; i++) {
+               config = configs[i];
+
+               dev_dbg(info->dev,
+                       "%s:%d, pin_id=%d, config=0x%lx",
+                       __func__, __LINE__, pin_id, config);
+               pio = pin_to_controller(info, pin_to_bank(pin_id));
+               mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+
+               if (config & PULL_UP && config & PULL_DOWN)
+                       return -EINVAL;
+
+               at91_mux_set_pullup(pio, mask, config & PULL_UP);
+               at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
+               if (info->ops->set_deglitch)
+                       info->ops->set_deglitch(pio, mask, config & DEGLITCH);
+               if (info->ops->set_debounce)
+                       info->ops->set_debounce(pio, mask, config & DEBOUNCE,
                                (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
-       if (info->ops->set_pulldown)
-               info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
-       if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
-               info->ops->disable_schmitt_trig(pio, mask);
+               if (info->ops->set_pulldown)
+                       info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
+               if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
+                       info->ops->disable_schmitt_trig(pio, mask);
+
+       } /* for each config */
 
        return 0;
 }
index a1c88b30f71f9aafa603860592e05a06df4a896d..c05c1ef2cc3c8526a886ccefb3f874f795b40807 100644 (file)
@@ -893,28 +893,35 @@ static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
-                       unsigned pin, unsigned long config)
+                       unsigned pin, unsigned long *configs,
+                       unsigned num_configs)
 {
        struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-       enum bcm2835_pinconf_param param = BCM2835_PINCONF_UNPACK_PARAM(config);
-       u16 arg = BCM2835_PINCONF_UNPACK_ARG(config);
+       enum bcm2835_pinconf_param param;
+       u16 arg;
        u32 off, bit;
+       int i;
 
-       if (param != BCM2835_PINCONF_PARAM_PULL)
-               return -EINVAL;
-
-       off = GPIO_REG_OFFSET(pin);
-       bit = GPIO_REG_SHIFT(pin);
-
-       bcm2835_gpio_wr(pc, GPPUD, arg & 3);
-       /*
-        * Docs say to wait 150 cycles, but not of what. We assume a
-        * 1 MHz clock here, which is pretty slow...
-        */
-       udelay(150);
-       bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
-       udelay(150);
-       bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
+       for (i = 0; i < num_configs; i++) {
+               param = BCM2835_PINCONF_UNPACK_PARAM(configs[i]);
+               arg = BCM2835_PINCONF_UNPACK_ARG(configs[i]);
+
+               if (param != BCM2835_PINCONF_PARAM_PULL)
+                       return -EINVAL;
+
+               off = GPIO_REG_OFFSET(pin);
+               bit = GPIO_REG_SHIFT(pin);
+
+               bcm2835_gpio_wr(pc, GPPUD, arg & 3);
+               /*
+                * Docs say to wait 150 cycles, but not of what. We assume a
+                * 1 MHz clock here, which is pretty slow...
+                */
+               udelay(150);
+               bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
+               udelay(150);
+               bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
+       } /* for each config */
 
        return 0;
 }
index 3b283fd898ff54c9ab7b1dbdc3a2dd3c8dff0d53..544d469c5a7b4dfae349e14503600e22e03b8017 100644 (file)
@@ -401,64 +401,71 @@ static const struct pinmux_ops exynos5440_pinmux_ops = {
 
 /* set the pin config settings for a specified pin */
 static int exynos5440_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-                               unsigned long config)
+                               unsigned long *configs,
+                               unsigned num_configs)
 {
        struct exynos5440_pinctrl_priv_data *priv;
        void __iomem *base;
-       enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(config);
-       u32 cfg_value = PINCFG_UNPACK_VALUE(config);
+       enum pincfg_type cfg_type;
+       u32 cfg_value;
        u32 data;
+       int i;
 
        priv = pinctrl_dev_get_drvdata(pctldev);
        base = priv->reg_base;
 
-       switch (cfg_type) {
-       case PINCFG_TYPE_PUD:
-               /* first set pull enable/disable bit */
-               data = readl(base + GPIO_PE);
-               data &= ~(1 << pin);
-               if (cfg_value)
-                       data |= (1 << pin);
-               writel(data, base + GPIO_PE);
-
-               /* then set pull up/down bit */
-               data = readl(base + GPIO_PS);
-               data &= ~(1 << pin);
-               if (cfg_value == 2)
-                       data |= (1 << pin);
-               writel(data, base + GPIO_PS);
-               break;
-
-       case PINCFG_TYPE_DRV:
-               /* set the first bit of the drive strength */
-               data = readl(base + GPIO_DS0);
-               data &= ~(1 << pin);
-               data |= ((cfg_value & 1) << pin);
-               writel(data, base + GPIO_DS0);
-               cfg_value >>= 1;
-
-               /* set the second bit of the driver strength */
-               data = readl(base + GPIO_DS1);
-               data &= ~(1 << pin);
-               data |= ((cfg_value & 1) << pin);
-               writel(data, base + GPIO_DS1);
-               break;
-       case PINCFG_TYPE_SKEW_RATE:
-               data = readl(base + GPIO_SR);
-               data &= ~(1 << pin);
-               data |= ((cfg_value & 1) << pin);
-               writel(data, base + GPIO_SR);
-               break;
-       case PINCFG_TYPE_INPUT_TYPE:
-               data = readl(base + GPIO_TYPE);
-               data &= ~(1 << pin);
-               data |= ((cfg_value & 1) << pin);
-               writel(data, base + GPIO_TYPE);
-               break;
-       default:
-               WARN_ON(1);
-               return -EINVAL;
-       }
+       for (i = 0; i < num_configs; i++) {
+               cfg_type = PINCFG_UNPACK_TYPE(configs[i]);
+               cfg_value = PINCFG_UNPACK_VALUE(configs[i]);
+
+               switch (cfg_type) {
+               case PINCFG_TYPE_PUD:
+                       /* first set pull enable/disable bit */
+                       data = readl(base + GPIO_PE);
+                       data &= ~(1 << pin);
+                       if (cfg_value)
+                               data |= (1 << pin);
+                       writel(data, base + GPIO_PE);
+
+                       /* then set pull up/down bit */
+                       data = readl(base + GPIO_PS);
+                       data &= ~(1 << pin);
+                       if (cfg_value == 2)
+                               data |= (1 << pin);
+                       writel(data, base + GPIO_PS);
+                       break;
+
+               case PINCFG_TYPE_DRV:
+                       /* set the first bit of the drive strength */
+                       data = readl(base + GPIO_DS0);
+                       data &= ~(1 << pin);
+                       data |= ((cfg_value & 1) << pin);
+                       writel(data, base + GPIO_DS0);
+                       cfg_value >>= 1;
+
+                       /* set the second bit of the driver strength */
+                       data = readl(base + GPIO_DS1);
+                       data &= ~(1 << pin);
+                       data |= ((cfg_value & 1) << pin);
+                       writel(data, base + GPIO_DS1);
+                       break;
+               case PINCFG_TYPE_SKEW_RATE:
+                       data = readl(base + GPIO_SR);
+                       data &= ~(1 << pin);
+                       data |= ((cfg_value & 1) << pin);
+                       writel(data, base + GPIO_SR);
+                       break;
+               case PINCFG_TYPE_INPUT_TYPE:
+                       data = readl(base + GPIO_TYPE);
+                       data &= ~(1 << pin);
+                       data |= ((cfg_value & 1) << pin);
+                       writel(data, base + GPIO_TYPE);
+                       break;
+               default:
+                       WARN_ON(1);
+                       return -EINVAL;
+               }
+       } /* for each config */
 
        return 0;
 }
@@ -510,7 +517,8 @@ static int exynos5440_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
 
 /* set the pin config settings for a specified pin group */
 static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev,
-                       unsigned group, unsigned long config)
+                       unsigned group, unsigned long *configs,
+                       unsigned num_configs)
 {
        struct exynos5440_pinctrl_priv_data *priv;
        const unsigned int *pins;
@@ -520,7 +528,8 @@ static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev,
        pins = priv->pin_groups[group].pins;
 
        for (cnt = 0; cnt < priv->pin_groups[group].num_pins; cnt++)
-               exynos5440_pinconf_set(pctldev, pins[cnt], config);
+               exynos5440_pinconf_set(pctldev, pins[cnt], configs,
+                                      num_configs);
 
        return 0;
 }
index 4e731f24df85524e2f0157ea319c0c841576a4e6..2e62689b5e9f81c67e9b95f622e4865463deaf18 100644 (file)
@@ -238,7 +238,8 @@ static int falcon_pinconf_group_get(struct pinctrl_dev *pctrldev,
 }
 
 static int falcon_pinconf_group_set(struct pinctrl_dev *pctrldev,
-                               unsigned group, unsigned long config)
+                               unsigned group, unsigned long *configs,
+                               unsigned num_configs)
 {
        return -ENOTSUPP;
 }
@@ -279,39 +280,47 @@ static int falcon_pinconf_get(struct pinctrl_dev *pctrldev,
 }
 
 static int falcon_pinconf_set(struct pinctrl_dev *pctrldev,
-                       unsigned pin, unsigned long config)
+                       unsigned pin, unsigned long *configs,
+                       unsigned num_configs)
 {
-       enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(config);
-       int arg = LTQ_PINCONF_UNPACK_ARG(config);
+       enum ltq_pinconf_param param;
+       int arg;
        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
        void __iomem *mem = info->membase[PORT(pin)];
        u32 reg;
+       int i;
 
-       switch (param) {
-       case LTQ_PINCONF_PARAM_DRIVE_CURRENT:
-               reg = LTQ_PADC_DCC;
-               break;
-
-       case LTQ_PINCONF_PARAM_SLEW_RATE:
-               reg = LTQ_PADC_SRC;
-               break;
-
-       case LTQ_PINCONF_PARAM_PULL:
-               if (arg == 1)
-                       reg = LTQ_PADC_PDEN;
-               else
-                       reg = LTQ_PADC_PUEN;
-               break;
+       for (i = 0; i < num_configs; i++) {
+               param = LTQ_PINCONF_UNPACK_PARAM(configs[i]);
+               arg = LTQ_PINCONF_UNPACK_ARG(configs[i]);
+
+               switch (param) {
+               case LTQ_PINCONF_PARAM_DRIVE_CURRENT:
+                       reg = LTQ_PADC_DCC;
+                       break;
+
+               case LTQ_PINCONF_PARAM_SLEW_RATE:
+                       reg = LTQ_PADC_SRC;
+                       break;
+
+               case LTQ_PINCONF_PARAM_PULL:
+                       if (arg == 1)
+                               reg = LTQ_PADC_PDEN;
+                       else
+                               reg = LTQ_PADC_PUEN;
+                       break;
+
+               default:
+                       pr_err("%s: Invalid config param %04x\n",
+                       pinctrl_dev_get_name(pctrldev), param);
+                       return -ENOTSUPP;
+               }
 
-       default:
-               pr_err("%s: Invalid config param %04x\n",
-               pinctrl_dev_get_name(pctrldev), param);
-               return -ENOTSUPP;
-       }
+               pad_w32(mem, BIT(PORT_PIN(pin)), reg);
+               if (!(pad_r32(mem, reg) & BIT(PORT_PIN(pin))))
+                       return -ENOTSUPP;
+       } /* for each config */
 
-       pad_w32(mem, BIT(PORT_PIN(pin)), reg);
-       if (!(pad_r32(mem, reg) & BIT(PORT_PIN(pin))))
-               return -ENOTSUPP;
        return 0;
 }
 
index 3602493013150237c7c4b766e9b7e0fcf2314c2a..d78dd813bff978d87f9bedd38f403f816db73e76 100644 (file)
@@ -323,11 +323,13 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int imx_pinconf_set(struct pinctrl_dev *pctldev,
-                            unsigned pin_id, unsigned long config)
+                            unsigned pin_id, unsigned long *configs,
+                            unsigned num_configs)
 {
        struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
        const struct imx_pinctrl_soc_info *info = ipctl->info;
        const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
+       int i;
 
        if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
                dev_err(info->dev, "Pin(%s) does not support config function\n",
@@ -338,17 +340,19 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
        dev_dbg(ipctl->dev, "pinconf set pin %s\n",
                info->pins[pin_id].name);
 
-       if (info->flags & SHARE_MUX_CONF_REG) {
-               u32 reg;
-               reg = readl(ipctl->base + pin_reg->conf_reg);
-               reg &= ~0xffff;
-               reg |= config;
-               writel(reg, ipctl->base + pin_reg->conf_reg);
-       } else {
-               writel(config, ipctl->base + pin_reg->conf_reg);
-       }
-       dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
-               pin_reg->conf_reg, config);
+       for (i = 0; i < num_configs; i++) {
+               if (info->flags & SHARE_MUX_CONF_REG) {
+                       u32 reg;
+                       reg = readl(ipctl->base + pin_reg->conf_reg);
+                       reg &= ~0xffff;
+                       reg |= configs[i];
+                       writel(reg, ipctl->base + pin_reg->conf_reg);
+               } else {
+                       writel(configs[i], ipctl->base + pin_reg->conf_reg);
+               }
+               dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
+                       pin_reg->conf_reg, configs[i]);
+       } /* for each config */
 
        return 0;
 }
index f5d56436ba7f838d77e78deb526178944c8efa35..40c76f26998cc748791357657975582761dd16b4 100644 (file)
@@ -233,7 +233,8 @@ static int mxs_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int mxs_pinconf_set(struct pinctrl_dev *pctldev,
-                          unsigned pin, unsigned long config)
+                          unsigned pin, unsigned long *configs,
+                          unsigned num_configs)
 {
        return -ENOTSUPP;
 }
@@ -249,7 +250,8 @@ static int mxs_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
-                                unsigned group, unsigned long config)
+                                unsigned group, unsigned long *configs,
+                                unsigned num_configs)
 {
        struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
        struct mxs_group *g = &d->soc->groups[group];
@@ -257,49 +259,56 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
        u8 ma, vol, pull, bank, shift;
        u16 pin;
        u32 i;
+       int n;
+       unsigned long config;
 
-       ma = CONFIG_TO_MA(config);
-       vol = CONFIG_TO_VOL(config);
-       pull = CONFIG_TO_PULL(config);
-
-       for (i = 0; i < g->npins; i++) {
-               bank = PINID_TO_BANK(g->pins[i]);
-               pin = PINID_TO_PIN(g->pins[i]);
-
-               /* drive */
-               reg = d->base + d->soc->regs->drive;
-               reg += bank * 0x40 + pin / 8 * 0x10;
-
-               /* mA */
-               if (config & MA_PRESENT) {
-                       shift = pin % 8 * 4;
-                       writel(0x3 << shift, reg + CLR);
-                       writel(ma << shift, reg + SET);
-               }
-
-               /* vol */
-               if (config & VOL_PRESENT) {
-                       shift = pin % 8 * 4 + 2;
-                       if (vol)
-                               writel(1 << shift, reg + SET);
-                       else
-                               writel(1 << shift, reg + CLR);
+       for (n = 0; n < num_configs; n++) {
+               config = configs[n];
+
+               ma = CONFIG_TO_MA(config);
+               vol = CONFIG_TO_VOL(config);
+               pull = CONFIG_TO_PULL(config);
+
+               for (i = 0; i < g->npins; i++) {
+                       bank = PINID_TO_BANK(g->pins[i]);
+                       pin = PINID_TO_PIN(g->pins[i]);
+
+                       /* drive */
+                       reg = d->base + d->soc->regs->drive;
+                       reg += bank * 0x40 + pin / 8 * 0x10;
+
+                       /* mA */
+                       if (config & MA_PRESENT) {
+                               shift = pin % 8 * 4;
+                               writel(0x3 << shift, reg + CLR);
+                               writel(ma << shift, reg + SET);
+                       }
+
+                       /* vol */
+                       if (config & VOL_PRESENT) {
+                               shift = pin % 8 * 4 + 2;
+                               if (vol)
+                                       writel(1 << shift, reg + SET);
+                               else
+                                       writel(1 << shift, reg + CLR);
+                       }
+
+                       /* pull */
+                       if (config & PULL_PRESENT) {
+                               reg = d->base + d->soc->regs->pull;
+                               reg += bank * 0x10;
+                               shift = pin;
+                               if (pull)
+                                       writel(1 << shift, reg + SET);
+                               else
+                                       writel(1 << shift, reg + CLR);
+                       }
                }
 
-               /* pull */
-               if (config & PULL_PRESENT) {
-                       reg = d->base + d->soc->regs->pull;
-                       reg += bank * 0x10;
-                       shift = pin;
-                       if (pull)
-                               writel(1 << shift, reg + SET);
-                       else
-                               writel(1 << shift, reg + CLR);
-               }
-       }
+               /* cache the config value for mxs_pinconf_group_get() */
+               g->config = config;
 
-       /* cache the config value for mxs_pinconf_group_get() */
-       g->config = config;
+       } /* for each config */
 
        return 0;
 }
index f7c7279d081a1c2723ff1afc515273d5a41222b2..d7c3ae300fa716555c37dd906f7ed4e74c528393 100644 (file)
@@ -1695,7 +1695,7 @@ static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
 }
 
 static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
-                             unsigned long config)
+                             unsigned long *configs, unsigned num_configs)
 {
        static const char *pullnames[] = {
                [NMK_GPIO_PULL_NONE]    = "none",
@@ -1712,20 +1712,9 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
        struct pinctrl_gpio_range *range;
        struct gpio_chip *chip;
        unsigned bit;
-
-       /*
-        * The pin config contains pin number and altfunction fields, here
-        * we just ignore that part. It's being handled by the framework and
-        * pinmux callback respectively.
-        */
-       pin_cfg_t cfg = (pin_cfg_t) config;
-       int pull = PIN_PULL(cfg);
-       int slpm = PIN_SLPM(cfg);
-       int output = PIN_DIR(cfg);
-       int val = PIN_VAL(cfg);
-       bool lowemi = PIN_LOWEMI(cfg);
-       bool gpiomode = PIN_GPIOMODE(cfg);
-       bool sleep = PIN_SLEEPMODE(cfg);
+       pin_cfg_t cfg;
+       int pull, slpm, output, val, i;
+       bool lowemi, gpiomode, sleep;
 
        range = nmk_match_gpio_range(pctldev, pin);
        if (!range) {
@@ -1740,54 +1729,74 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
        chip = range->gc;
        nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
 
-       if (sleep) {
-               int slpm_pull = PIN_SLPM_PULL(cfg);
-               int slpm_output = PIN_SLPM_DIR(cfg);
-               int slpm_val = PIN_SLPM_VAL(cfg);
-
-               /* All pins go into GPIO mode at sleep */
-               gpiomode = true;
-
+       for (i = 0; i < num_configs; i++) {
                /*
-                * The SLPM_* values are normal values + 1 to allow zero to
-                * mean "same as normal".
+                * The pin config contains pin number and altfunction fields,
+                * here we just ignore that part. It's being handled by the
+                * framework and pinmux callback respectively.
                 */
-               if (slpm_pull)
-                       pull = slpm_pull - 1;
-               if (slpm_output)
-                       output = slpm_output - 1;
-               if (slpm_val)
-                       val = slpm_val - 1;
-
-               dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
-                       pin,
-                       slpm_pull ? pullnames[pull] : "same",
-                       slpm_output ? (output ? "output" : "input") : "same",
-                       slpm_val ? (val ? "high" : "low") : "same");
-       }
+               cfg = (pin_cfg_t) configs[i];
+               pull = PIN_PULL(cfg);
+               slpm = PIN_SLPM(cfg);
+               output = PIN_DIR(cfg);
+               val = PIN_VAL(cfg);
+               lowemi = PIN_LOWEMI(cfg);
+               gpiomode = PIN_GPIOMODE(cfg);
+               sleep = PIN_SLEEPMODE(cfg);
+
+               if (sleep) {
+                       int slpm_pull = PIN_SLPM_PULL(cfg);
+                       int slpm_output = PIN_SLPM_DIR(cfg);
+                       int slpm_val = PIN_SLPM_VAL(cfg);
+
+                       /* All pins go into GPIO mode at sleep */
+                       gpiomode = true;
+
+                       /*
+                        * The SLPM_* values are normal values + 1 to allow zero
+                        * to mean "same as normal".
+                        */
+                       if (slpm_pull)
+                               pull = slpm_pull - 1;
+                       if (slpm_output)
+                               output = slpm_output - 1;
+                       if (slpm_val)
+                               val = slpm_val - 1;
+
+                       dev_dbg(nmk_chip->chip.dev,
+                               "pin %d: sleep pull %s, dir %s, val %s\n",
+                               pin,
+                               slpm_pull ? pullnames[pull] : "same",
+                               slpm_output ? (output ? "output" : "input")
+                               : "same",
+                               slpm_val ? (val ? "high" : "low") : "same");
+               }
 
-       dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
-               pin, cfg, pullnames[pull], slpmnames[slpm],
-               output ? "output " : "input",
-               output ? (val ? "high" : "low") : "",
-               lowemi ? "on" : "off");
+               dev_dbg(nmk_chip->chip.dev,
+                       "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
+                       pin, cfg, pullnames[pull], slpmnames[slpm],
+                       output ? "output " : "input",
+                       output ? (val ? "high" : "low") : "",
+                       lowemi ? "on" : "off");
 
-       clk_enable(nmk_chip->clk);
-       bit = pin % NMK_GPIO_PER_CHIP;
-       if (gpiomode)
-               /* No glitch when going to GPIO mode */
-               __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
-       if (output)
-               __nmk_gpio_make_output(nmk_chip, bit, val);
-       else {
-               __nmk_gpio_make_input(nmk_chip, bit);
-               __nmk_gpio_set_pull(nmk_chip, bit, pull);
-       }
-       /* TODO: isn't this only applicable on output pins? */
-       __nmk_gpio_set_lowemi(nmk_chip, bit, lowemi);
+               clk_enable(nmk_chip->clk);
+               bit = pin % NMK_GPIO_PER_CHIP;
+               if (gpiomode)
+                       /* No glitch when going to GPIO mode */
+                       __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
+               if (output)
+                       __nmk_gpio_make_output(nmk_chip, bit, val);
+               else {
+                       __nmk_gpio_make_input(nmk_chip, bit);
+                       __nmk_gpio_set_pull(nmk_chip, bit, pull);
+               }
+               /* TODO: isn't this only applicable on output pins? */
+               __nmk_gpio_set_lowemi(nmk_chip, bit, lowemi);
+
+               __nmk_gpio_set_slpm(nmk_chip, bit, slpm);
+               clk_disable(nmk_chip->clk);
+       } /* for each config */
 
-       __nmk_gpio_set_slpm(nmk_chip, bit, slpm);
-       clk_disable(nmk_chip->clk);
        return 0;
 }
 
index 9550c33b254490f2c11f9e9f266087e5f22752c1..82638fac3cfa6a3f40c6ce1f423d3146a5b29e02 100644 (file)
@@ -854,17 +854,19 @@ static int palmas_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int palmas_pinconf_set(struct pinctrl_dev *pctldev,
-                       unsigned pin, unsigned long config)
+                       unsigned pin, unsigned long *configs,
+                       unsigned num_configs)
 {
        struct palmas_pctrl_chip_info *pci = pinctrl_dev_get_drvdata(pctldev);
-       enum pin_config_param param = pinconf_to_config_param(config);
-       u16 param_val = pinconf_to_config_argument(config);
+       enum pin_config_param param;
+       u16 param_val;
        const struct palmas_pingroup *g;
        const struct palmas_pin_info *opt;
        int ret;
        int base, add, mask;
        int rval;
        int group_nr;
+       int i;
 
        for (group_nr = 0; group_nr < pci->num_pin_groups; ++group_nr) {
                if (pci->pin_groups[group_nr].pins[0] == pin)
@@ -885,70 +887,77 @@ static int palmas_pinconf_set(struct pinctrl_dev *pctldev,
                return -ENOTSUPP;
        }
 
-       switch (param) {
-       case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
-               return 0;
-       case PIN_CONFIG_BIAS_DISABLE:
-       case PIN_CONFIG_BIAS_PULL_UP:
-       case PIN_CONFIG_BIAS_PULL_DOWN:
-               if (!opt->pud_info) {
-                       dev_err(pci->dev,
-                               "PULL control not supported for pin %s\n",
-                               g->name);
-                       return -ENOTSUPP;
-               }
-               base = opt->pud_info->pullup_dn_reg_base;
-               add = opt->pud_info->pullup_dn_reg_add;
-               mask = opt->pud_info->pullup_dn_mask;
-
-               if (param == PIN_CONFIG_BIAS_DISABLE)
-                       rval = opt->pud_info->normal_val;
-               else if (param == PIN_CONFIG_BIAS_PULL_UP)
-                       rval = opt->pud_info->pull_up_val;
-               else
-                       rval = opt->pud_info->pull_dn_val;
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               param_val = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+                       return 0;
+               case PIN_CONFIG_BIAS_DISABLE:
+               case PIN_CONFIG_BIAS_PULL_UP:
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       if (!opt->pud_info) {
+                               dev_err(pci->dev,
+                                       "PULL control not supported for pin %s\n",
+                                       g->name);
+                               return -ENOTSUPP;
+                       }
+                       base = opt->pud_info->pullup_dn_reg_base;
+                       add = opt->pud_info->pullup_dn_reg_add;
+                       mask = opt->pud_info->pullup_dn_mask;
+
+                       if (param == PIN_CONFIG_BIAS_DISABLE)
+                               rval = opt->pud_info->normal_val;
+                       else if (param == PIN_CONFIG_BIAS_PULL_UP)
+                               rval = opt->pud_info->pull_up_val;
+                       else
+                               rval = opt->pud_info->pull_dn_val;
+
+                       if (rval < 0) {
+                               dev_err(pci->dev,
+                                       "PULL control not supported for pin %s\n",
+                                       g->name);
+                               return -ENOTSUPP;
+                       }
+                       break;
 
-               if (rval < 0) {
-                       dev_err(pci->dev,
-                               "PULL control not supported for pin %s\n",
-                               g->name);
+               case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+                       if (!opt->od_info) {
+                               dev_err(pci->dev,
+                                       "OD control not supported for pin %s\n",
+                                       g->name);
+                               return -ENOTSUPP;
+                       }
+                       base = opt->od_info->od_reg_base;
+                       add = opt->od_info->od_reg_add;
+                       mask = opt->od_info->od_mask;
+                       if (param_val == 0)
+                               rval = opt->od_info->od_disable;
+                       else
+                               rval = opt->od_info->od_enable;
+                       if (rval < 0) {
+                               dev_err(pci->dev,
+                                       "OD control not supported for pin %s\n",
+                                       g->name);
+                               return -ENOTSUPP;
+                       }
+                       break;
+               default:
+                       dev_err(pci->dev, "Properties not supported\n");
                        return -ENOTSUPP;
                }
-               break;
 
-       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
-               if (!opt->od_info) {
-                       dev_err(pci->dev,
-                               "OD control not supported for pin %s\n",
-                               g->name);
-                       return -ENOTSUPP;
-               }
-               base = opt->od_info->od_reg_base;
-               add = opt->od_info->od_reg_add;
-               mask = opt->od_info->od_mask;
-               if (param_val == 0)
-                       rval = opt->od_info->od_disable;
-               else
-                       rval = opt->od_info->od_enable;
-               if (rval < 0) {
-                       dev_err(pci->dev,
-                               "OD control not supported for pin %s\n",
-                               g->name);
-                       return -ENOTSUPP;
+               dev_dbg(pci->dev, "%s(): Add0x%02x:0x%02x:0x%02x:0x%02x\n",
+                               __func__, base, add, mask, rval);
+               ret = palmas_update_bits(pci->palmas, base, add, mask, rval);
+               if (ret < 0) {
+                       dev_err(pci->dev, "Reg 0x%02x update failed: %d\n",
+                               add, ret);
+                       return ret;
                }
-               break;
-       default:
-               dev_err(pci->dev, "Properties not supported\n");
-               return -ENOTSUPP;
-       }
+       } /* for each config */
 
-       dev_dbg(pci->dev, "%s(): Add0x%02x:0x%02x:0x%02x:0x%02x\n",
-                       __func__, base, add, mask, rval);
-       ret = palmas_update_bits(pci->palmas, base, add, mask, rval);
-       if (ret < 0) {
-               dev_err(pci->dev, "Reg 0x%02x update failed: %d\n", add, ret);
-               return ret;
-       }
        return 0;
 }
 
@@ -960,7 +969,8 @@ static int palmas_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 static int palmas_pinconf_group_set(struct pinctrl_dev *pctldev,
-                               unsigned group, unsigned long config)
+                               unsigned group, unsigned long *configs,
+                               unsigned num_configs)
 {
        dev_err(pctldev->dev, "palmas_pinconf_group_set op not supported\n");
        return -ENOTSUPP;
index 51a7c24981d1389e64981042e52b3526135b4b95..abff5895e81fa11527ec3bbd3977923b1177a66d 100644 (file)
@@ -574,32 +574,45 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
 
 /* set the pin config settings for a specified pin */
 static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-                                                       unsigned long config)
+                               unsigned long *configs, unsigned num_configs)
 {
        struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
        struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
-       enum pin_config_param param = pinconf_to_config_param(config);
-       u16 arg = pinconf_to_config_argument(config);
-
-       switch (param) {
-       case PIN_CONFIG_BIAS_DISABLE:
-               return rockchip_set_pull(bank, pin - bank->pin_base, param);
-               break;
-       case PIN_CONFIG_BIAS_PULL_UP:
-       case PIN_CONFIG_BIAS_PULL_DOWN:
-       case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
-               if (!rockchip_pinconf_pull_valid(info->ctrl, param))
+       enum pin_config_param param;
+       u16 arg;
+       int i;
+       int rc;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_DISABLE:
+                       rc =  rockchip_set_pull(bank, pin - bank->pin_base,
+                               param);
+                       if (rc)
+                               return rc;
+                       break;
+               case PIN_CONFIG_BIAS_PULL_UP:
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+               case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+                       if (!rockchip_pinconf_pull_valid(info->ctrl, param))
+                               return -ENOTSUPP;
+
+                       if (!arg)
+                               return -EINVAL;
+
+                       rc = rockchip_set_pull(bank, pin - bank->pin_base,
+                               param);
+                       if (rc)
+                               return rc;
+                       break;
+               default:
                        return -ENOTSUPP;
-
-               if (!arg)
-                       return -EINVAL;
-
-               return rockchip_set_pull(bank, pin - bank->pin_base, param);
-               break;
-       default:
-               return -ENOTSUPP;
-               break;
-       }
+                       break;
+               }
+       } /* for each config */
 
        return 0;
 }
index 439f2ef680df27fb9362ef8689a93ca5079f2f18..222648d69f253f32307779bca73860019f1acdfb 100644 (file)
@@ -442,9 +442,17 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
 
 /* set the pin config settings for a specified pin */
 static int samsung_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-                               unsigned long config)
+                               unsigned long *configs, unsigned num_configs)
 {
-       return samsung_pinconf_rw(pctldev, pin, &config, true);
+       int i, ret;
+
+       for (i = 0; i < num_configs; i++) {
+               ret = samsung_pinconf_rw(pctldev, pin, &configs[i], true);
+               if (ret < 0)
+                       return ret;
+       } /* for each config */
+
+       return 0;
 }
 
 /* get the pin config settings for a specified pin */
@@ -456,7 +464,8 @@ static int samsung_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
 
 /* set the pin config settings for a specified pin group */
 static int samsung_pinconf_group_set(struct pinctrl_dev *pctldev,
-                       unsigned group, unsigned long config)
+                       unsigned group, unsigned long *configs,
+                       unsigned num_configs)
 {
        struct samsung_pinctrl_drv_data *drvdata;
        const unsigned int *pins;
@@ -466,7 +475,7 @@ static int samsung_pinconf_group_set(struct pinctrl_dev *pctldev,
        pins = drvdata->pin_groups[group].pins;
 
        for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++)
-               samsung_pinconf_set(pctldev, pins[cnt], config);
+               samsung_pinconf_set(pctldev, pins[cnt], configs, num_configs);
 
        return 0;
 }
index 6866548fab31669d5141a7c8af21c10e0caa895d..8f31768c665d2d907f1aa438fb1605d79666df0c 100644 (file)
@@ -209,7 +209,7 @@ struct pcs_device {
 static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
                           unsigned long *config);
 static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
-                          unsigned long config);
+                          unsigned long *configs, unsigned num_configs);
 
 static enum pin_config_param pcs_bias[] = {
        PIN_CONFIG_BIAS_PULL_DOWN,
@@ -536,7 +536,7 @@ static void pcs_pinconf_clear_bias(struct pinctrl_dev *pctldev, unsigned pin)
        int i;
        for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
                config = pinconf_to_config_packed(pcs_bias[i], 0);
-               pcs_pinconf_set(pctldev, pin, config);
+               pcs_pinconf_set(pctldev, pin, &config, 1);
        }
 }
 
@@ -622,22 +622,28 @@ static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
-                               unsigned pin, unsigned long config)
+                               unsigned pin, unsigned long *configs,
+                               unsigned num_configs)
 {
        struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
        struct pcs_function *func;
        unsigned offset = 0, shift = 0, i, data, ret;
        u16 arg;
+       int j;
 
        ret = pcs_get_function(pctldev, pin, &func);
        if (ret)
                return ret;
 
-       for (i = 0; i < func->nconfs; i++) {
-               if (pinconf_to_config_param(config) == func->conf[i].param) {
+       for (j = 0; j < num_configs; j++) {
+               for (i = 0; i < func->nconfs; i++) {
+                       if (pinconf_to_config_param(configs[j])
+                               != func->conf[i].param)
+                               continue;
+
                        offset = pin * (pcs->width / BITS_PER_BYTE);
                        data = pcs->read(pcs->base + offset);
-                       arg = pinconf_to_config_argument(config);
+                       arg = pinconf_to_config_argument(configs[j]);
                        switch (func->conf[i].param) {
                        /* 2 parameters */
                        case PIN_CONFIG_INPUT_SCHMITT:
@@ -667,10 +673,14 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
                                return -ENOTSUPP;
                        }
                        pcs->write(data, pcs->base + offset);
-                       return 0;
+
+                       break;
                }
-       }
-       return -ENOTSUPP;
+               if (i >= func->nconfs)
+                       return -ENOTSUPP;
+       } /* for each config */
+
+       return 0;
 }
 
 static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
@@ -695,7 +705,8 @@ static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
-                               unsigned group, unsigned long config)
+                               unsigned group, unsigned long *configs,
+                               unsigned num_configs)
 {
        const unsigned *pins;
        unsigned npins;
@@ -705,7 +716,7 @@ static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
        if (ret)
                return ret;
        for (i = 0; i < npins; i++) {
-               if (pcs_pinconf_set(pctldev, pins[i], config))
+               if (pcs_pinconf_set(pctldev, pins[i], configs, num_configs))
                        return -ENOTSUPP;
        }
        return 0;
index 2a10a318b648c252955c3581a4d369369cb303af..9cadc68ee5722bec7a541445e2eba257d355e488 100644 (file)
@@ -909,15 +909,18 @@ static void st_pinconf_set_retime(struct st_pinctrl *info,
                                                        config, pin);
 }
 
-static int st_pinconf_set(struct pinctrl_dev *pctldev,
-                            unsigned pin_id, unsigned long config)
+static int st_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin_id,
+                       unsigned long *configs, unsigned num_configs)
 {
        int pin = st_gpio_pin(pin_id);
        struct st_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
        struct st_pio_control *pc = st_get_pio_control(pctldev, pin_id);
+       int i;
 
-       st_pinconf_set_config(pc, pin, config);
-       st_pinconf_set_retime(info, pc, pin, config);
+       for (i = 0; i < num_configs; i++) {
+               st_pinconf_set_config(pc, pin, configs[i]);
+               st_pinconf_set_retime(info, pc, pin, configs[i]);
+       } /* for each config */
 
        return 0;
 }
index d251c76c2e62da587c284a6a35a6e4614e123486..8dbd465b01d364d2c2251cc41fb36158139335eb 100644 (file)
@@ -274,50 +274,55 @@ static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev,
 
 static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
                                 unsigned group,
-                                unsigned long config)
+                                unsigned long *configs,
+                                unsigned num_configs)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        struct sunxi_pinctrl_group *g = &pctl->groups[group];
        u32 val, mask;
        u16 strength;
        u8 dlevel;
+       int i;
 
-       switch (pinconf_to_config_param(config)) {
-       case PIN_CONFIG_DRIVE_STRENGTH:
-               strength = pinconf_to_config_argument(config);
-               if (strength > 40)
-                       return -EINVAL;
-               /*
-                * We convert from mA to what the register expects:
-                *   0: 10mA
-                *   1: 20mA
-                *   2: 30mA
-                *   3: 40mA
-                */
-               dlevel = strength / 10 - 1;
-               val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
-               mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
-               writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
-                       pctl->membase + sunxi_dlevel_reg(g->pin));
-               break;
-       case PIN_CONFIG_BIAS_PULL_UP:
-               val = readl(pctl->membase + sunxi_pull_reg(g->pin));
-               mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
-               writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
-                       pctl->membase + sunxi_pull_reg(g->pin));
-               break;
-       case PIN_CONFIG_BIAS_PULL_DOWN:
-               val = readl(pctl->membase + sunxi_pull_reg(g->pin));
-               mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
-               writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
-                       pctl->membase + sunxi_pull_reg(g->pin));
-               break;
-       default:
-               break;
-       }
+       for (i = 0; i < num_configs; i++) {
+               switch (pinconf_to_config_param(configs[i])) {
+               case PIN_CONFIG_DRIVE_STRENGTH:
+                       strength = pinconf_to_config_argument(configs[i]);
+                       if (strength > 40)
+                               return -EINVAL;
+                       /*
+                        * We convert from mA to what the register expects:
+                        *   0: 10mA
+                        *   1: 20mA
+                        *   2: 30mA
+                        *   3: 40mA
+                        */
+                       dlevel = strength / 10 - 1;
+                       val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
+                       mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
+                       writel((val & ~mask)
+                               | dlevel << sunxi_dlevel_offset(g->pin),
+                               pctl->membase + sunxi_dlevel_reg(g->pin));
+                       break;
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       val = readl(pctl->membase + sunxi_pull_reg(g->pin));
+                       mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
+                       writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
+                               pctl->membase + sunxi_pull_reg(g->pin));
+                       break;
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       val = readl(pctl->membase + sunxi_pull_reg(g->pin));
+                       mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
+                       writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
+                               pctl->membase + sunxi_pull_reg(g->pin));
+                       break;
+               default:
+                       break;
+               }
 
-       /* cache the config value */
-       g->config = config;
+               /* cache the config value */
+               g->config = configs[i];
+       } /* for each config */
 
        return 0;
 }
index be7e900fb2982f04c5d71cdc24eef59cada2cd29..a2e93a2b5ff487aa0dad6fc8c9f2d863e6debb07 100644 (file)
@@ -436,7 +436,8 @@ static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
-                            unsigned pin, unsigned long config)
+                            unsigned pin, unsigned long *configs,
+                            unsigned num_configs)
 {
        dev_err(pctldev->dev, "pin_config_set op not supported\n");
        return -ENOTSUPP;
@@ -471,51 +472,57 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
-                                  unsigned group, unsigned long config)
+                                  unsigned group, unsigned long *configs,
+                                  unsigned num_configs)
 {
        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
-       u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
+       enum tegra_pinconf_param param;
+       u16 arg;
        const struct tegra_pingroup *g;
-       int ret;
+       int ret, i;
        s8 bank, bit, width;
        s16 reg;
        u32 val, mask;
 
        g = &pmx->soc->groups[group];
 
-       ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
-                               &width);
-       if (ret < 0)
-               return ret;
+       for (i = 0; i < num_configs; i++) {
+               param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]);
+               arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]);
 
-       val = pmx_readl(pmx, bank, reg);
+               ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
+                                       &width);
+               if (ret < 0)
+                       return ret;
 
-       /* LOCK can't be cleared */
-       if (param == TEGRA_PINCONF_PARAM_LOCK) {
-               if ((val & BIT(bit)) && !arg) {
-                       dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
-                       return -EINVAL;
+               val = pmx_readl(pmx, bank, reg);
+
+               /* LOCK can't be cleared */
+               if (param == TEGRA_PINCONF_PARAM_LOCK) {
+                       if ((val & BIT(bit)) && !arg) {
+                               dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
+                               return -EINVAL;
+                       }
                }
-       }
 
-       /* Special-case Boolean values; allow any non-zero as true */
-       if (width == 1)
-               arg = !!arg;
+               /* Special-case Boolean values; allow any non-zero as true */
+               if (width == 1)
+                       arg = !!arg;
 
-       /* Range-check user-supplied value */
-       mask = (1 << width) - 1;
-       if (arg & ~mask) {
-               dev_err(pctldev->dev,
-                       "config %lx: %x too big for %d bit register\n",
-                       config, arg, width);
-               return -EINVAL;
-       }
+               /* Range-check user-supplied value */
+               mask = (1 << width) - 1;
+               if (arg & ~mask) {
+                       dev_err(pctldev->dev,
+                               "config %lx: %x too big for %d bit register\n",
+                               configs[i], arg, width);
+                       return -EINVAL;
+               }
 
-       /* Update register */
-       val &= ~(mask << bit);
-       val |= arg << bit;
-       pmx_writel(pmx, val, bank, reg);
+               /* Update register */
+               val &= ~(mask << bit);
+               val |= arg << bit;
+               pmx_writel(pmx, val, bank, reg);
+       } /* for each config */
 
        return 0;
 }
index 494ad4b83264bc110f69223d0053073cc173503e..5bf01c28925ea4e8d0725a43c06a480e0ed0e946 100644 (file)
@@ -737,39 +737,46 @@ static int tz1090_pdc_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int tz1090_pdc_pinconf_set(struct pinctrl_dev *pctldev,
-                                 unsigned int pin, unsigned long config)
+                                 unsigned int pin, unsigned long *configs,
+                                 unsigned num_configs)
 {
        struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       enum pin_config_param param = pinconf_to_config_param(config);
-       unsigned int arg = pinconf_to_config_argument(config);
+       enum pin_config_param param;
+       unsigned int arg;
        int ret;
        u32 reg, width, mask, shift, val, tmp;
        unsigned long flags;
+       int i;
 
-       dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n",
-               __func__, tz1090_pdc_pins[pin].name, config);
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
 
-       /* Get register information */
-       ret = tz1090_pdc_pinconf_reg(pctldev, pin, param, true,
-                                    &reg, &width, &mask, &shift, &val);
-       if (ret < 0)
-               return ret;
+               dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n",
+                       __func__, tz1090_pdc_pins[pin].name, configs[i]);
 
-       /* Unpack argument and range check it */
-       if (arg > 1) {
-               dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
-                       __func__, arg);
-               return -EINVAL;
-       }
+               /* Get register information */
+               ret = tz1090_pdc_pinconf_reg(pctldev, pin, param, true,
+                                            &reg, &width, &mask, &shift, &val);
+               if (ret < 0)
+                       return ret;
 
-       /* Write register field */
-       __global_lock2(flags);
-       tmp = pmx_read(pmx, reg);
-       tmp &= ~mask;
-       if (arg)
-               tmp |= val << shift;
-       pmx_write(pmx, tmp, reg);
-       __global_unlock2(flags);
+               /* Unpack argument and range check it */
+               if (arg > 1) {
+                       dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
+                               __func__, arg);
+                       return -EINVAL;
+               }
+
+               /* Write register field */
+               __global_lock2(flags);
+               tmp = pmx_read(pmx, reg);
+               tmp &= ~mask;
+               if (arg)
+                       tmp |= val << shift;
+               pmx_write(pmx, tmp, reg);
+               __global_unlock2(flags);
+       } /* for each config */
 
        return 0;
 }
@@ -860,54 +867,68 @@ static int tz1090_pdc_pinconf_group_get(struct pinctrl_dev *pctldev,
 
 static int tz1090_pdc_pinconf_group_set(struct pinctrl_dev *pctldev,
                                        unsigned int group,
-                                       unsigned long config)
+                                       unsigned long *configs,
+                                       unsigned num_configs)
 {
        struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
        const struct tz1090_pdc_pingroup *g = &tz1090_pdc_groups[group];
-       enum pin_config_param param = pinconf_to_config_param(config);
+       enum pin_config_param param;
        const unsigned int *pit;
        unsigned int i;
        int ret, arg;
        u32 reg, width, mask, shift, val;
        unsigned long flags;
        const int *map;
+       int j;
 
-       dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n",
-               __func__, g->name, config);
+       for (j = 0; j < num_configs; j++) {
+               param = pinconf_to_config_param(configs[j]);
 
-       /* Get register information */
-       ret = tz1090_pdc_pinconf_group_reg(pctldev, g, param, true,
-                                          &reg, &width, &mask, &shift, &map);
-       if (ret < 0) {
-               /*
-                * Maybe we're trying to set a per-pin configuration of a group,
-                * so do the pins one by one. This is mainly as a convenience.
-                */
-               for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) {
-                       ret = tz1090_pdc_pinconf_set(pctldev, *pit, config);
-                       if (ret)
-                               return ret;
-               }
-               return 0;
-       }
+               dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n",
+                       __func__, g->name, configs[j]);
 
-       /* Unpack argument and map it to register value */
-       arg = pinconf_to_config_argument(config);
-       for (i = 0; i < BIT(width); ++i) {
-               if (map[i] == arg || (map[i] == -EINVAL && !arg)) {
-                       /* Write register field */
-                       __global_lock2(flags);
-                       val = pmx_read(pmx, reg);
-                       val &= ~mask;
-                       val |= i << shift;
-                       pmx_write(pmx, val, reg);
-                       __global_unlock2(flags);
+               /* Get register information */
+               ret = tz1090_pdc_pinconf_group_reg(pctldev, g, param, true,
+                                                  &reg, &width, &mask, &shift,
+                                                  &map);
+               if (ret < 0) {
+                       /*
+                        * Maybe we're trying to set a per-pin configuration
+                        * of a group, so do the pins one by one. This is
+                        * mainly as a convenience.
+                        */
+                       for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) {
+                               ret = tz1090_pdc_pinconf_set(pctldev, *pit,
+                                       configs, num_configs);
+                               if (ret)
+                                       return ret;
+                       }
                        return 0;
                }
-       }
 
-       dev_dbg(pctldev->dev, "%s: arg %u not supported\n",
-               __func__, arg);
+               /* Unpack argument and map it to register value */
+               arg = pinconf_to_config_argument(configs[j]);
+               for (i = 0; i < BIT(width); ++i) {
+                       if (map[i] == arg || (map[i] == -EINVAL && !arg)) {
+                               /* Write register field */
+                               __global_lock2(flags);
+                               val = pmx_read(pmx, reg);
+                               val &= ~mask;
+                               val |= i << shift;
+                               pmx_write(pmx, val, reg);
+                               __global_unlock2(flags);
+                               goto next_config;
+                       }
+               }
+
+               dev_dbg(pctldev->dev, "%s: arg %u not supported\n",
+                       __func__, arg);
+               return 0;
+
+next_config:
+               ;
+       } /* for each config */
+
        return 0;
 }
 
index 72d955252e415f67187f35e3b2992f4165784d93..bc9cd7a7602ea30d930d099519b8dfbb3590742a 100644 (file)
@@ -1762,39 +1762,46 @@ static int tz1090_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int tz1090_pinconf_set(struct pinctrl_dev *pctldev,
-                             unsigned int pin, unsigned long config)
+                             unsigned int pin, unsigned long *configs,
+                             unsigned num_configs)
 {
        struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       enum pin_config_param param = pinconf_to_config_param(config);
-       unsigned int arg = pinconf_to_config_argument(config);
+       enum pin_config_param param;
+       unsigned int arg;
        int ret;
        u32 reg, width, mask, shift, val, tmp;
        unsigned long flags;
+       int i;
 
-       dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n",
-               __func__, tz1090_pins[pin].name, config);
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
 
-       /* Get register information */
-       ret = tz1090_pinconf_reg(pctldev, pin, param, true,
-                                &reg, &width, &mask, &shift, &val);
-       if (ret < 0)
-               return ret;
+               dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n",
+                       __func__, tz1090_pins[pin].name, configs[i]);
 
-       /* Unpack argument and range check it */
-       if (arg > 1) {
-               dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
-                       __func__, arg);
-               return -EINVAL;
-       }
+               /* Get register information */
+               ret = tz1090_pinconf_reg(pctldev, pin, param, true,
+                                        &reg, &width, &mask, &shift, &val);
+               if (ret < 0)
+                       return ret;
 
-       /* Write register field */
-       __global_lock2(flags);
-       tmp = pmx_read(pmx, reg);
-       tmp &= ~mask;
-       if (arg)
-               tmp |= val << shift;
-       pmx_write(pmx, tmp, reg);
-       __global_unlock2(flags);
+               /* Unpack argument and range check it */
+               if (arg > 1) {
+                       dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
+                               __func__, arg);
+                       return -EINVAL;
+               }
+
+               /* Write register field */
+               __global_lock2(flags);
+               tmp = pmx_read(pmx, reg);
+               tmp &= ~mask;
+               if (arg)
+                       tmp |= val << shift;
+               pmx_write(pmx, tmp, reg);
+               __global_unlock2(flags);
+       } /* for each config */
 
        return 0;
 }
@@ -1894,68 +1901,81 @@ static int tz1090_pinconf_group_get(struct pinctrl_dev *pctldev,
 }
 
 static int tz1090_pinconf_group_set(struct pinctrl_dev *pctldev,
-                                   unsigned int group, unsigned long config)
+                                   unsigned int group, unsigned long *configs,
+                                   unsigned num_configs)
 {
        struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
        const struct tz1090_pingroup *g;
-       enum pin_config_param param = pinconf_to_config_param(config);
+       enum pin_config_param param;
        unsigned int arg, pin, i;
        const unsigned int *pit;
        int ret;
        u32 reg, width, mask, shift, val;
        unsigned long flags;
        const int *map;
+       int j;
 
        if (group >= ARRAY_SIZE(tz1090_groups)) {
                pin = group - ARRAY_SIZE(tz1090_groups);
-               return tz1090_pinconf_set(pctldev, pin, config);
+               return tz1090_pinconf_set(pctldev, pin, configs, num_configs);
        }
 
        g = &tz1090_groups[group];
        if (g->npins == 1) {
                pin = g->pins[0];
-               ret = tz1090_pinconf_set(pctldev, pin, config);
+               ret = tz1090_pinconf_set(pctldev, pin, configs, num_configs);
                if (ret != -ENOTSUPP)
                        return ret;
        }
 
-       dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n",
-               __func__, g->name, config);
+       for (j = 0; j < num_configs; j++) {
+               param = pinconf_to_config_param(configs[j]);
 
-       /* Get register information */
-       ret = tz1090_pinconf_group_reg(pctldev, g, param, true,
-                                      &reg, &width, &mask, &shift, &map);
-       if (ret < 0) {
-               /*
-                * Maybe we're trying to set a per-pin configuration of a group,
-                * so do the pins one by one. This is mainly as a convenience.
-                */
-               for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) {
-                       ret = tz1090_pinconf_set(pctldev, *pit, config);
-                       if (ret)
-                               return ret;
-               }
-               return 0;
-       }
+               dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n",
+                       __func__, g->name, configs[j]);
 
-       /* Unpack argument and map it to register value */
-       arg = pinconf_to_config_argument(config);
-       for (i = 0; i < BIT(width); ++i) {
-               if (map[i] == arg || (map[i] == -EINVAL && !arg)) {
-                       /* Write register field */
-                       __global_lock2(flags);
-                       val = pmx_read(pmx, reg);
-                       val &= ~mask;
-                       val |= i << shift;
-                       pmx_write(pmx, val, reg);
-                       __global_unlock2(flags);
+               /* Get register information */
+               ret = tz1090_pinconf_group_reg(pctldev, g, param, true, &reg,
+                                               &width, &mask, &shift, &map);
+               if (ret < 0) {
+                       /*
+                        * Maybe we're trying to set a per-pin configuration
+                        * of a group, so do the pins one by one. This is
+                        * mainly as a convenience.
+                        */
+                       for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) {
+                               ret = tz1090_pinconf_set(pctldev, *pit, configs,
+                                       num_configs);
+                               if (ret)
+                                       return ret;
+                       }
                        return 0;
                }
-       }
 
-       dev_dbg(pctldev->dev, "%s: arg %u not supported\n",
-               __func__, arg);
-       return -EINVAL;
+               /* Unpack argument and map it to register value */
+               arg = pinconf_to_config_argument(configs[j]);
+               for (i = 0; i < BIT(width); ++i) {
+                       if (map[i] == arg || (map[i] == -EINVAL && !arg)) {
+                               /* Write register field */
+                               __global_lock2(flags);
+                               val = pmx_read(pmx, reg);
+                               val &= ~mask;
+                               val |= i << shift;
+                               pmx_write(pmx, val, reg);
+                               __global_unlock2(flags);
+                               goto next_config;
+                       }
+               }
+
+               dev_dbg(pctldev->dev, "%s: arg %u not supported\n",
+                       __func__, arg);
+               return -EINVAL;
+
+next_config:
+               ;
+       } /* for each config */
+
+       return 0;
 }
 
 static struct pinconf_ops tz1090_pinconf_ops = {
index 6fbdc06d299811b95c90b3b2f41e2b8985eeca53..209a01b8bd3b84d9cbe2071a8007ef1caf7b3f0f 100644 (file)
@@ -1027,21 +1027,23 @@ static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
 }
 
 static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
-                              unsigned long config)
+                              unsigned long *configs, unsigned num_configs)
 {
        struct pinctrl_gpio_range *range =
                pinctrl_find_gpio_range_from_pin(pctldev, pin);
-       int ret;
+       int ret, i;
 
        if (!range)
                return -EINVAL;
 
-       /* Note: none of these configurations take any argument */
-       ret = u300_gpio_config_set(range->gc,
-                                  (pin - range->pin_base + range->base),
-                                  pinconf_to_config_param(config));
-       if (ret)
-               return ret;
+       for (i = 0; i < num_configs; i++) {
+               /* Note: none of these configurations take any argument */
+               ret = u300_gpio_config_set(range->gc,
+                       (pin - range->pin_base + range->base),
+                       pinconf_to_config_param(configs[i]));
+               if (ret)
+                       return ret;
+       } /* for each config */
 
        return 0;
 }
index 86c8cf82105b2ba7972d12e3061d227d532489af..ed2d1ba69cef6f7f77b2ab3d63d81247282982cd 100644 (file)
@@ -499,74 +499,101 @@ static int xway_pinconf_get(struct pinctrl_dev *pctldev,
 
 static int xway_pinconf_set(struct pinctrl_dev *pctldev,
                                unsigned pin,
-                               unsigned long config)
+                               unsigned long *configs,
+                               unsigned num_configs)
 {
        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
-       enum ltq_pinconf_param param = LTQ_PINCONF_UNPACK_PARAM(config);
-       int arg = LTQ_PINCONF_UNPACK_ARG(config);
+       enum ltq_pinconf_param param;
+       int arg;
        int port = PORT(pin);
        u32 reg;
+       int i;
+
+       for (i = 0; i < num_configs; i++) {
+               param = LTQ_PINCONF_UNPACK_PARAM(configs[i]);
+               arg = LTQ_PINCONF_UNPACK_ARG(configs[i]);
+
+               switch (param) {
+               case LTQ_PINCONF_PARAM_OPEN_DRAIN:
+                       if (port == PORT3)
+                               reg = GPIO3_OD;
+                       else
+                               reg = GPIO_OD(pin);
+                       if (arg == 0)
+                               gpio_setbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                       else
+                               gpio_clearbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                       break;
 
-       switch (param) {
-       case LTQ_PINCONF_PARAM_OPEN_DRAIN:
-               if (port == PORT3)
-                       reg = GPIO3_OD;
-               else
-                       reg = GPIO_OD(pin);
-               if (arg == 0)
+               case LTQ_PINCONF_PARAM_PULL:
+                       if (port == PORT3)
+                               reg = GPIO3_PUDEN;
+                       else
+                               reg = GPIO_PUDEN(pin);
+                       if (arg == 0) {
+                               gpio_clearbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                               break;
+                       }
                        gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
-               else
-                       gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
-               break;
 
-       case LTQ_PINCONF_PARAM_PULL:
-               if (port == PORT3)
-                       reg = GPIO3_PUDEN;
-               else
-                       reg = GPIO_PUDEN(pin);
-               if (arg == 0) {
-                       gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
+                       if (port == PORT3)
+                               reg = GPIO3_PUDSEL;
+                       else
+                               reg = GPIO_PUDSEL(pin);
+                       if (arg == 1)
+                               gpio_clearbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                       else if (arg == 2)
+                               gpio_setbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                       else
+                               dev_err(pctldev->dev,
+                                       "Invalid pull value %d\n", arg);
                        break;
-               }
-               gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
 
-               if (port == PORT3)
-                       reg = GPIO3_PUDSEL;
-               else
-                       reg = GPIO_PUDSEL(pin);
-               if (arg == 1)
-                       gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
-               else if (arg == 2)
-                       gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
-               else
-                       dev_err(pctldev->dev, "Invalid pull value %d\n", arg);
-               break;
+               case LTQ_PINCONF_PARAM_OUTPUT:
+                       reg = GPIO_DIR(pin);
+                       if (arg == 0)
+                               gpio_clearbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                       else
+                               gpio_setbit(info->membase[0],
+                                       reg,
+                                       PORT_PIN(pin));
+                       break;
 
-       case LTQ_PINCONF_PARAM_OUTPUT:
-               reg = GPIO_DIR(pin);
-               if (arg == 0)
-                       gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
-               else
-                       gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
-               break;
+               default:
+                       dev_err(pctldev->dev,
+                               "Invalid config param %04x\n", param);
+                       return -ENOTSUPP;
+               }
+       } /* for each config */
 
-       default:
-               dev_err(pctldev->dev, "Invalid config param %04x\n", param);
-               return -ENOTSUPP;
-       }
        return 0;
 }
 
 int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
                        unsigned selector,
-                       unsigned long config)
+                       unsigned long *configs,
+                       unsigned num_configs)
 {
        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
        int i, ret = 0;
 
        for (i = 0; i < info->grps[selector].npins && !ret; i++)
                ret = xway_pinconf_set(pctldev,
-                               info->grps[selector].pins[i], config);
+                               info->grps[selector].pins[i],
+                               configs,
+                               num_configs);
 
        return ret;
 }
index 8649ec3910a3e1c8be863340468e94ada76954c5..e758af95c209324f91d547877bc2b6a9bc2aab1f 100644 (file)
@@ -529,38 +529,44 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
 }
 
 static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
-                             unsigned long config)
+                             unsigned long *configs, unsigned num_configs)
 {
        struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
        struct sh_pfc *pfc = pmx->pfc;
-       enum pin_config_param param = pinconf_to_config_param(config);
+       enum pin_config_param param;
        unsigned long flags;
+       unsigned int i;
 
-       if (!sh_pfc_pinconf_validate(pfc, _pin, param))
-               return -ENOTSUPP;
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
 
-       switch (param) {
-       case PIN_CONFIG_BIAS_PULL_UP:
-       case PIN_CONFIG_BIAS_PULL_DOWN:
-       case PIN_CONFIG_BIAS_DISABLE:
-               if (!pfc->info->ops || !pfc->info->ops->set_bias)
+               if (!sh_pfc_pinconf_validate(pfc, _pin, param))
                        return -ENOTSUPP;
 
-               spin_lock_irqsave(&pfc->lock, flags);
-               pfc->info->ops->set_bias(pfc, _pin, param);
-               spin_unlock_irqrestore(&pfc->lock, flags);
+               switch (param) {
+               case PIN_CONFIG_BIAS_PULL_UP:
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+               case PIN_CONFIG_BIAS_DISABLE:
+                       if (!pfc->info->ops || !pfc->info->ops->set_bias)
+                               return -ENOTSUPP;
 
-               break;
+                       spin_lock_irqsave(&pfc->lock, flags);
+                       pfc->info->ops->set_bias(pfc, _pin, param);
+                       spin_unlock_irqrestore(&pfc->lock, flags);
 
-       default:
-               return -ENOTSUPP;
-       }
+                       break;
+
+               default:
+                       return -ENOTSUPP;
+               }
+       } /* for each config */
 
        return 0;
 }
 
 static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
-                                   unsigned long config)
+                                   unsigned long *configs,
+                                   unsigned num_configs)
 {
        struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
        const unsigned int *pins;
@@ -571,7 +577,7 @@ static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
        num_pins = pmx->pfc->info->groups[group].nr_pins;
 
        for (i = 0; i < num_pins; ++i)
-               sh_pfc_pinconf_set(pctldev, pins[i], config);
+               sh_pfc_pinconf_set(pctldev, pins[i], configs, num_configs);
 
        return 0;
 }
index 0cc4335bc0f232bf7021cb72e48ed0ff639f1491..39aec08508106f21dd515063ae0aa41ca4221367 100644 (file)
@@ -424,15 +424,16 @@ static int wmt_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
 }
 
 static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
-                          unsigned long config)
+                          unsigned long *configs, unsigned num_configs)
 {
        struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
-       enum pin_config_param param = pinconf_to_config_param(config);
-       u16 arg = pinconf_to_config_argument(config);
+       enum pin_config_param param;
+       u16 arg;
        u32 bank = WMT_BANK_FROM_PIN(pin);
        u32 bit = WMT_BIT_FROM_PIN(pin);
        u32 reg_pull_en = data->banks[bank].reg_pull_en;
        u32 reg_pull_cfg = data->banks[bank].reg_pull_cfg;
+       int i;
 
        if ((reg_pull_en == NO_REG) || (reg_pull_cfg == NO_REG)) {
                dev_err(data->dev, "bias functions not supported on pin %d\n",
@@ -440,28 +441,33 @@ static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
                return -EINVAL;
        }
 
-       if ((param == PIN_CONFIG_BIAS_PULL_DOWN) ||
-           (param == PIN_CONFIG_BIAS_PULL_UP)) {
-               if (arg == 0)
-                       param = PIN_CONFIG_BIAS_DISABLE;
-       }
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
 
-       switch (param) {
-       case PIN_CONFIG_BIAS_DISABLE:
-               wmt_clearbits(data, reg_pull_en, BIT(bit));
-               break;
-       case PIN_CONFIG_BIAS_PULL_DOWN:
-               wmt_clearbits(data, reg_pull_cfg, BIT(bit));
-               wmt_setbits(data, reg_pull_en, BIT(bit));
-               break;
-       case PIN_CONFIG_BIAS_PULL_UP:
-               wmt_setbits(data, reg_pull_cfg, BIT(bit));
-               wmt_setbits(data, reg_pull_en, BIT(bit));
-               break;
-       default:
-               dev_err(data->dev, "unknown pinconf param\n");
-               return -EINVAL;
-       }
+               if ((param == PIN_CONFIG_BIAS_PULL_DOWN) ||
+                   (param == PIN_CONFIG_BIAS_PULL_UP)) {
+                       if (arg == 0)
+                               param = PIN_CONFIG_BIAS_DISABLE;
+               }
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_DISABLE:
+                       wmt_clearbits(data, reg_pull_en, BIT(bit));
+                       break;
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       wmt_clearbits(data, reg_pull_cfg, BIT(bit));
+                       wmt_setbits(data, reg_pull_en, BIT(bit));
+                       break;
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       wmt_setbits(data, reg_pull_cfg, BIT(bit));
+                       wmt_setbits(data, reg_pull_en, BIT(bit));
+                       break;
+               default:
+                       dev_err(data->dev, "unknown pinconf param\n");
+                       return -EINVAL;
+               }
+       } /* for each config */
 
        return 0;
 }
index f6998692bdc931fb6c1935baf5796ed43d0f132c..09eb80f2574a5314f5843478d090271cd45a20da 100644 (file)
@@ -47,13 +47,15 @@ struct pinconf_ops {
                               unsigned long *config);
        int (*pin_config_set) (struct pinctrl_dev *pctldev,
                               unsigned pin,
-                              unsigned long config);
+                              unsigned long *configs,
+                              unsigned num_configs);
        int (*pin_config_group_get) (struct pinctrl_dev *pctldev,
                                     unsigned selector,
                                     unsigned long *config);
        int (*pin_config_group_set) (struct pinctrl_dev *pctldev,
                                     unsigned selector,
-                                    unsigned long config);
+                                    unsigned long *configs,
+                                    unsigned num_configs);
        int (*pin_config_dbg_parse_modify) (struct pinctrl_dev *pctldev,
                                           const char *arg,
                                           unsigned long *config);