static int madera_pin_conf_set()

in cirrus/pinctrl-madera-core.c [820:944]


static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,
			       unsigned long *configs, unsigned int num_configs)
{
	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
	u16 conf[2] = {0, 0};
	u16 mask[2] = {0, 0};
	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
	unsigned int val;
	int ret;

	while (num_configs) {
		dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs);

		switch (pinconf_to_config_param(*configs)) {
		case PIN_CONFIG_BIAS_BUS_HOLD:
			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
			conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD;
			break;
		case PIN_CONFIG_BIAS_DISABLE:
			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
			conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD);
			break;
		case PIN_CONFIG_BIAS_PULL_DOWN:
			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
			conf[1] |= MADERA_GP1_PD;
			conf[1] &= ~MADERA_GP1_PU;
			break;
		case PIN_CONFIG_BIAS_PULL_UP:
			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
			conf[1] |= MADERA_GP1_PU;
			conf[1] &= ~MADERA_GP1_PD;
			break;
		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
			mask[0] |= MADERA_GP1_OP_CFG_MASK;
			conf[0] |= MADERA_GP1_OP_CFG;
			break;
		case PIN_CONFIG_DRIVE_PUSH_PULL:
			mask[0] |= MADERA_GP1_OP_CFG_MASK;
			conf[0] &= ~MADERA_GP1_OP_CFG;
			break;
		case PIN_CONFIG_DRIVE_STRENGTH:
			val = pinconf_to_config_argument(*configs);
			mask[1] |= MADERA_GP1_DRV_STR_MASK;
			conf[1] &= ~MADERA_GP1_DRV_STR_MASK;
			conf[1] |= madera_pin_make_drv_str(priv, val);
			break;
		case PIN_CONFIG_INPUT_DEBOUNCE:
			mask[0] |= MADERA_GP1_DB_MASK;

			/*
			 * we can't configure debounce time per-pin so value
			 * is just a flag
			 */
			val = pinconf_to_config_argument(*configs);
			if (val)
				conf[0] |= MADERA_GP1_DB;
			else
				conf[0] &= ~MADERA_GP1_DB;
			break;
		case PIN_CONFIG_INPUT_ENABLE:
			val = pinconf_to_config_argument(*configs);
			mask[1] |= MADERA_GP1_DIR_MASK;
			if (val)
				conf[1] |= MADERA_GP1_DIR;
			else
				conf[1] &= ~MADERA_GP1_DIR;
			break;
		case PIN_CONFIG_INPUT_SCHMITT:
			val = pinconf_to_config_argument(*configs);
			mask[0] |= MADERA_GP1_IP_CFG;
			if (val)
				conf[0] |= MADERA_GP1_IP_CFG;
			else
				conf[0] &= ~MADERA_GP1_IP_CFG;

			mask[1] |= MADERA_GP1_DIR_MASK;
			conf[1] |= MADERA_GP1_DIR;
			break;
		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
			mask[0] |= MADERA_GP1_IP_CFG;
			conf[0] |= MADERA_GP1_IP_CFG;
			mask[1] |= MADERA_GP1_DIR_MASK;
			conf[1] |= MADERA_GP1_DIR;
			break;
		case PIN_CONFIG_OUTPUT:
			val = pinconf_to_config_argument(*configs);
			mask[0] |= MADERA_GP1_LVL_MASK;
			if (val)
				conf[0] |= MADERA_GP1_LVL;
			else
				conf[0] &= ~MADERA_GP1_LVL;

			mask[1] |= MADERA_GP1_DIR_MASK;
			conf[1] &= ~MADERA_GP1_DIR;
			break;
		default:
			return -ENOTSUPP;
		}

		++configs;
		--num_configs;
	}

	dev_dbg(priv->dev,
		"%s gpio%d 0x%x:0x%x 0x%x:0x%x\n",
		__func__, pin + 1, reg, conf[0], reg + 1, conf[1]);

	ret = regmap_update_bits(priv->madera->regmap, reg, mask[0], conf[0]);
	if (ret)
		goto err;

	++reg;
	ret = regmap_update_bits(priv->madera->regmap, reg, mask[1], conf[1]);
	if (ret)
		goto err;

	return 0;

err:
	dev_err(priv->dev,
		"Failed to write GPIO%d conf (%d) reg 0x%x\n",
		pin + 1, ret, reg);

	return ret;
}