diff options
author | Chen-Yu Tsai <wens@csie.org> | 2016-11-11 10:50:36 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-11-15 10:21:49 +0100 |
commit | 51814827190214986c452a166718bf12d32211c7 (patch) | |
tree | 2e0097e0d01f4d98c4cc4a82a1d6c2aec8d02e39 /drivers/pinctrl/sunxi | |
parent | pinctrl: sunxi: Add support for fetching pinconf settings from hardware (diff) | |
download | linux-51814827190214986c452a166718bf12d32211c7.tar.xz linux-51814827190214986c452a166718bf12d32211c7.zip |
pinctrl: sunxi: Make sunxi_pconf_group_set use sunxi_pconf_reg helper
The sunxi_pconf_reg helper introduced in the last patch gives us the
chance to rework sunxi_pconf_group_set to have it match the structure
of sunxi_pconf_(group_)get and make it easier to understand.
For each config to set, it:
1. checks if the parameter is supported.
2. checks if the argument is within limits.
3. converts argument to the register value.
4. writes to the register with spinlock held.
As a result the function now blocks unsupported config parameters,
instead of silently ignoring them.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/sunxi')
-rw-r--r-- | drivers/pinctrl/sunxi/pinctrl-sunxi.c | 64 |
1 files changed, 32 insertions, 32 deletions
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index ed71bff39869..fa11a3100346 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -532,23 +532,27 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct sunxi_pinctrl_group *g = &pctl->groups[group]; - unsigned long flags; unsigned pin = g->pin - pctl->desc->pin_base; - u32 val, mask; - u16 strength; - u8 dlevel; int i; - spin_lock_irqsave(&pctl->lock, flags); - for (i = 0; i < num_configs; i++) { - switch (pinconf_to_config_param(configs[i])) { + enum pin_config_param param; + unsigned long flags; + u32 offset, shift, mask, reg; + u16 arg, val; + int ret; + + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); + if (ret < 0) + return ret; + + switch (param) { case PIN_CONFIG_DRIVE_STRENGTH: - strength = pinconf_to_config_argument(configs[i]); - if (strength > 40) { - spin_unlock_irqrestore(&pctl->lock, flags); + if (arg < 10 || arg > 40) return -EINVAL; - } /* * We convert from mA to what the register expects: * 0: 10mA @@ -556,37 +560,33 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, * 2: 30mA * 3: 40mA */ - dlevel = strength / 10 - 1; - val = readl(pctl->membase + sunxi_dlevel_reg(pin)); - mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(pin); - writel((val & ~mask) - | dlevel << sunxi_dlevel_offset(pin), - pctl->membase + sunxi_dlevel_reg(pin)); + val = arg / 10 - 1; break; case PIN_CONFIG_BIAS_DISABLE: - val = readl(pctl->membase + sunxi_pull_reg(pin)); - mask = PULL_PINS_MASK << sunxi_pull_offset(pin); - writel((val & ~mask), - pctl->membase + sunxi_pull_reg(pin)); + val = 0; break; case PIN_CONFIG_BIAS_PULL_UP: - val = readl(pctl->membase + sunxi_pull_reg(pin)); - mask = PULL_PINS_MASK << sunxi_pull_offset(pin); - writel((val & ~mask) | 1 << sunxi_pull_offset(pin), - pctl->membase + sunxi_pull_reg(pin)); + if (arg == 0) + return -EINVAL; + val = 1; break; case PIN_CONFIG_BIAS_PULL_DOWN: - val = readl(pctl->membase + sunxi_pull_reg(pin)); - mask = PULL_PINS_MASK << sunxi_pull_offset(pin); - writel((val & ~mask) | 2 << sunxi_pull_offset(pin), - pctl->membase + sunxi_pull_reg(pin)); + if (arg == 0) + return -EINVAL; + val = 2; break; default: - break; + /* sunxi_pconf_reg should catch anything unsupported */ + WARN_ON(1); + return -ENOTSUPP; } - } /* for each config */ - spin_unlock_irqrestore(&pctl->lock, flags); + spin_lock_irqsave(&pctl->lock, flags); + reg = readl(pctl->membase + offset); + reg &= ~(mask << shift); + writel(reg | val << shift, pctl->membase + offset); + spin_unlock_irqrestore(&pctl->lock, flags); + } /* for each config */ return 0; } |