Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51814827 authored by Chen-Yu Tsai's avatar Chen-Yu Tsai Committed by Linus Walleij
Browse files

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: default avatarChen-Yu Tsai <wens@csie.org>
Acked-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent c5fda170
Loading
Loading
Loading
Loading
+32 −32
Original line number Diff line number Diff line
@@ -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_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;
}