From 03b054e9696c3cbd3d5905ec96da15acd0a2fe8d Mon Sep 17 00:00:00 2001 From: Sherman Yin Date: Tue, 27 Aug 2013 11:32:12 -0700 Subject: 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 Reviewed-by: Christian Daudt Reviewed-by: Matt Porter Tested-by: Stephen Warren Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-tegra.c | 69 +++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 31 deletions(-) (limited to 'drivers/pinctrl/pinctrl-tegra.c') diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index be7e900fb29..a2e93a2b5ff 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -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, ®, &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, ®, &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; } -- cgit v1.2.3-70-g09d2