static int mtk_pinconf_get()

in mediatek/pinctrl-paris.c [77:188]


static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
			   unsigned int pin, unsigned long *config)
{
	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
	u32 param = pinconf_to_config_param(*config);
	int pullup, err, reg, ret = 1;
	const struct mtk_pin_desc *desc;

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

	switch (param) {
	case PIN_CONFIG_BIAS_DISABLE:
	case PIN_CONFIG_BIAS_PULL_UP:
	case PIN_CONFIG_BIAS_PULL_DOWN:
		if (hw->soc->bias_get_combo) {
			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
			if (err)
				goto out;
			if (param == PIN_CONFIG_BIAS_DISABLE) {
				if (ret == MTK_PUPD_SET_R1R0_00)
					ret = MTK_DISABLE;
			} else if (param == PIN_CONFIG_BIAS_PULL_UP) {
				/* When desire to get pull-up value, return
				 *  error if current setting is pull-down
				 */
				if (!pullup)
					err = -EINVAL;
			} else if (param == PIN_CONFIG_BIAS_PULL_DOWN) {
				/* When desire to get pull-down value, return
				 *  error if current setting is pull-up
				 */
				if (pullup)
					err = -EINVAL;
			}
		} else {
			err = -ENOTSUPP;
		}
		break;
	case PIN_CONFIG_SLEW_RATE:
		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
		break;
	case PIN_CONFIG_INPUT_ENABLE:
	case PIN_CONFIG_OUTPUT_ENABLE:
		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
		if (err)
			goto out;
		/*     CONFIG     Current direction return value
		 * -------------  ----------------- ----------------------
		 * OUTPUT_ENABLE       output       1 (= HW value)
		 *                     input        0 (= HW value)
		 * INPUT_ENABLE        output       0 (= reverse HW value)
		 *                     input        1 (= reverse HW value)
		 */
		if (param == PIN_CONFIG_INPUT_ENABLE)
			ret = !ret;

		break;
	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
		if (err)
			goto out;
		/* return error when in output mode
		 * because schmitt trigger only work in input mode
		 */
		if (ret) {
			err = -EINVAL;
			goto out;
		}

		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);

		break;
	case PIN_CONFIG_DRIVE_STRENGTH:
		if (hw->soc->drive_get)
			err = hw->soc->drive_get(hw, desc, &ret);
		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_get_value(hw, desc, reg, &ret);
		break;
	case MTK_PIN_CONFIG_PU_ADV:
	case MTK_PIN_CONFIG_PD_ADV:
		if (hw->soc->adv_pull_get) {
			pullup = param == MTK_PIN_CONFIG_PU_ADV;
			err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
		} else
			err = -ENOTSUPP;
		break;
	case MTK_PIN_CONFIG_DRV_ADV:
		if (hw->soc->adv_drive_get)
			err = hw->soc->adv_drive_get(hw, desc, &ret);
		else
			err = -ENOTSUPP;
		break;
	default:
		err = -ENOTSUPP;
	}

out:
	if (!err)
		*config = pinconf_to_config_packed(param, ret);

	return err;
}