You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.8 KiB
122 lines
3.8 KiB
From 51814827190214986c452a166718bf12d32211c7 Mon Sep 17 00:00:00 2001
|
|
From: Chen-Yu Tsai <wens@csie.org>
|
|
Date: Fri, 11 Nov 2016 17:50:36 +0800
|
|
Subject: 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>
|
|
---
|
|
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 64 +++++++++++++++++------------------
|
|
1 file changed, 32 insertions(+), 32 deletions(-)
|
|
|
|
--- 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
|
|
{
|
|
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
|
|
* 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;
|
|
}
|
|
|