summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSherman Yin <syin@broadcom.com>2013-08-27 11:32:12 -0700
committerLinus Walleij <linus.walleij@linaro.org>2013-08-28 13:34:41 +0200
commit03b054e9696c3cbd3d5905ec96da15acd0a2fe8d (patch)
tree7123b780c194d350b3e5134c267e17262effb385 /drivers
parentf5ba9c52bf1e236c4698c240955e5f119db62a28 (diff)
pinctrl: Pass all configs to driver on pin_config_set()
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c26
-rw-r--r--drivers/pinctrl/pinconf.c42
-rw-r--r--drivers/pinctrl/pinctrl-abx500.c187
-rw-r--r--drivers/pinctrl/pinctrl-at91.c48
-rw-r--r--drivers/pinctrl/pinctrl-bcm2835.c43
-rw-r--r--drivers/pinctrl/pinctrl-exynos5440.c113
-rw-r--r--drivers/pinctrl/pinctrl-falcon.c63
-rw-r--r--drivers/pinctrl/pinctrl-imx.c28
-rw-r--r--drivers/pinctrl/pinctrl-mxs.c91
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c125
-rw-r--r--drivers/pinctrl/pinctrl-palmas.c134
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c57
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c17
-rw-r--r--drivers/pinctrl/pinctrl-single.c33
-rw-r--r--drivers/pinctrl/pinctrl-st.c11
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.c77
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c69
-rw-r--r--drivers/pinctrl/pinctrl-tz1090-pdc.c135
-rw-r--r--drivers/pinctrl/pinctrl-tz1090.c140
-rw-r--r--drivers/pinctrl/pinctrl-u300.c18
-rw-r--r--drivers/pinctrl/pinctrl-xway.c119
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c42
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c54
23 files changed, 948 insertions, 724 deletions
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index bb7ddb1bc89f..e78c041c3c73 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -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,
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 8da2d6db228c..a138965c01cb 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -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:
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c
index 1d3f988c2c8b..8f25df06bc6b 100644
--- a/drivers/pinctrl/pinctrl-abx500.c
+++ b/drivers/pinctrl/pinctrl-abx500.c
@@ -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);
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 7cce066c71b6..9685ff6c8b01 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -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;
}
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index a1c88b30f71f..c05c1ef2cc3c 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -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;
}
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c
index 3b283fd898ff..544d469c5a7b 100644
--- a/drivers/pinctrl/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/pinctrl-exynos5440.c
@@ -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;
}
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
index 4e731f24df85..2e62689b5e9f 100644
--- a/drivers/pinctrl/pinctrl-falcon.c
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -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;
}
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 360249301315..d78dd813bff9 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -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;
}
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index f5d56436ba7f..40c76f26998c 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -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;
}
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index f7c7279d081a..d7c3ae300fa7 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -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,