static int mtk_pinconf_set()

in mediatek/pinctrl-paris.c [190:304]


static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
			   enum pin_config_param param,
			   enum pin_config_param arg)
{
	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
	const struct mtk_pin_desc *desc;
	int err = 0;
	u32 reg;

	if (pin >= hw->soc->npins) {
		err = -EINVAL;
		goto err;
	}
	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];

	switch ((u32)param) {
	case PIN_CONFIG_BIAS_DISABLE:
		if (hw->soc->bias_set_combo)
			err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE);
		else
			err = -ENOTSUPP;
		break;
	case PIN_CONFIG_BIAS_PULL_UP:
		if (hw->soc->bias_set_combo)
			err = hw->soc->bias_set_combo(hw, desc, 1, arg);
		else
			err = -ENOTSUPP;
		break;
	case PIN_CONFIG_BIAS_PULL_DOWN:
		if (hw->soc->bias_set_combo)
			err = hw->soc->bias_set_combo(hw, desc, 0, arg);
		else
			err = -ENOTSUPP;
		break;
	case PIN_CONFIG_OUTPUT_ENABLE:
		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
				       MTK_DISABLE);
		/* Keep set direction to consider the case that a GPIO pin
		 *  does not have SMT control
		 */
		if (err != -ENOTSUPP)
			goto err;

		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
				       MTK_OUTPUT);
		break;
	case PIN_CONFIG_INPUT_ENABLE:
		/* regard all non-zero value as enable */
		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
		if (err)
			goto err;

		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
				       MTK_INPUT);
		break;
	case PIN_CONFIG_SLEW_RATE:
		/* regard all non-zero value as enable */
		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, !!arg);
		break;
	case PIN_CONFIG_OUTPUT:
		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
				       arg);
		if (err)
			goto err;

		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
				       MTK_OUTPUT);
		break;
	case PIN_CONFIG_INPUT_SCHMITT:
	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
		/* arg = 1: Input mode & SMT enable ;
		 * arg = 0: Output mode & SMT disable
		 */
		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !arg);
		if (err)
			goto err;

		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, !!arg);
		break;
	case PIN_CONFIG_DRIVE_STRENGTH:
		if (hw->soc->drive_set)
			err = hw->soc->drive_set(hw, desc, arg);
		else
			err = -ENOTSUPP;
		break;
	case MTK_PIN_CONFIG_TDSEL:
	case MTK_PIN_CONFIG_RDSEL:
		reg = (param == MTK_PIN_CONFIG_TDSEL) ?
		       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
		err = mtk_hw_set_value(hw, desc, reg, arg);
		break;
	case MTK_PIN_CONFIG_PU_ADV:
	case MTK_PIN_CONFIG_PD_ADV:
		if (hw->soc->adv_pull_set) {
			bool pullup;

			pullup = param == MTK_PIN_CONFIG_PU_ADV;
			err = hw->soc->adv_pull_set(hw, desc, pullup,
						    arg);
		} else
			err = -ENOTSUPP;
		break;
	case MTK_PIN_CONFIG_DRV_ADV:
		if (hw->soc->adv_drive_set)
			err = hw->soc->adv_drive_set(hw, desc, arg);
		else
			err = -ENOTSUPP;
		break;
	default:
		err = -ENOTSUPP;
	}

err:
	return err;
}