Commit 03b054e9 authored by Sherman Yin's avatar Sherman Yin Committed by Linus Walleij

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: default avatarSherman Yin <syin@broadcom.com>
Reviewed-by: default avatarChristian Daudt <csd@broadcom.com>
Reviewed-by: default avatarMatt Porter <matt.porter@linaro.org>
Tested-by: default avatarStephen Warren <swarren@nvidia.com>
Acked-by: Laurent Pinchart's avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij's avatarLinus Walleij <linus.walleij@linaro.org>
parent f5ba9c52
......@@ -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,
......
......@@ -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:
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);