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

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

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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent f5ba9c52
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -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;

	for (i = 0; i < num_configs; i++) {
		if (grp->ctrl->mpp_set)
		return grp->ctrl->mpp_set(grp->ctrl, config);
			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,
+19 −23
Original line number Diff line number Diff line
@@ -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,18 +171,16 @@ 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]);
				setting->data.configs.configs,
				setting->data.configs.num_configs);
		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]);
				"pin_config_set op failed for pin %d\n",
				setting->data.configs.group_or_pin);
			return ret;
		}
		}
		break;
	case PIN_MAP_TYPE_CONFIGS_GROUP:
		if (!ops->pin_config_group_set) {
@@ -190,18 +188,16 @@ 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]);
				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 config %08lx\n",
					setting->data.configs.group_or_pin,
					setting->data.configs.configs[i]);
				"pin_config_group_set op failed for group %d\n",
				setting->data.configs.group_or_pin);
			return ret;
		}
		}
		break;
	default:
		return -EINVAL;
+102 −85
Original line number Diff line number Diff line
@@ -1041,18 +1041,26 @@ 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);
	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, config, (param == PIN_CONFIG_OUTPUT) ? "output " : "input",
		(param == PIN_CONFIG_OUTPUT) ? (argument ? "high" : "low") :
			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 */
@@ -1064,11 +1072,12 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
			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.
			 * 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,
@@ -1076,8 +1085,9 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
					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);
				ret = abx500_gpio_set_bits(chip,
					AB8500_GPIO_PUD1_REG, offset,
					ABX500_GPIO_PULL_NONE);
			break;

		case PIN_CONFIG_BIAS_PULL_DOWN:
@@ -1087,21 +1097,25 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
			/*
			 * 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.
			 * 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);
					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,
				ret = abx500_gpio_set_bits(chip,
				AB8500_GPIO_PUD1_REG,
					offset,
				argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
					argument ? ABX500_GPIO_PULL_DOWN :
					ABX500_GPIO_PULL_NONE);
			break;

		case PIN_CONFIG_BIAS_PULL_UP:
@@ -1114,25 +1128,28 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
			 */
			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
			 * 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);
					argument ? ABX500_GPIO_PULL_UP :
					ABX500_GPIO_PULL_NONE);
			break;

		case PIN_CONFIG_OUTPUT:
		ret = abx500_gpio_direction_output(chip, offset, argument);
			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);
+29 −19
Original line number Diff line number Diff line
@@ -736,13 +736,21 @@ 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;
	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);
		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);

@@ -761,6 +769,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
		if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
			info->ops->disable_schmitt_trig(pio, mask);

	} /* for each config */

	return 0;
}

+25 −18
Original line number Diff line number Diff line
@@ -893,12 +893,18 @@ 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;

	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;
@@ -915,6 +921,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
		bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
		udelay(150);
		bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
	} /* for each config */

	return 0;
}
Loading