18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * MediaTek Pinctrl Moore Driver, which implement the generic dt-binding
48c2ecf20Sopenharmony_ci * pinctrl-bindings.txt for MediaTek SoC.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2017-2018 MediaTek Inc.
78c2ecf20Sopenharmony_ci * Author: Sean Wang <sean.wang@mediatek.com>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h>
128c2ecf20Sopenharmony_ci#include "pinctrl-moore.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define PINCTRL_PINCTRL_DEV		KBUILD_MODNAME
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* Custom pinconf parameters */
178c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_TDSEL	(PIN_CONFIG_END + 1)
188c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_RDSEL	(PIN_CONFIG_END + 2)
198c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_PU_ADV	(PIN_CONFIG_END + 3)
208c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_PD_ADV	(PIN_CONFIG_END + 4)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic const struct pinconf_generic_params mtk_custom_bindings[] = {
238c2ecf20Sopenharmony_ci	{"mediatek,tdsel",	MTK_PIN_CONFIG_TDSEL,		0},
248c2ecf20Sopenharmony_ci	{"mediatek,rdsel",	MTK_PIN_CONFIG_RDSEL,		0},
258c2ecf20Sopenharmony_ci	{"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV,		1},
268c2ecf20Sopenharmony_ci	{"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV,	1},
278c2ecf20Sopenharmony_ci};
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
308c2ecf20Sopenharmony_cistatic const struct pin_config_item mtk_conf_items[] = {
318c2ecf20Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
328c2ecf20Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
338c2ecf20Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true),
348c2ecf20Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true),
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci#endif
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
398c2ecf20Sopenharmony_ci			      unsigned int selector, unsigned int group)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
428c2ecf20Sopenharmony_ci	struct function_desc *func;
438c2ecf20Sopenharmony_ci	struct group_desc *grp;
448c2ecf20Sopenharmony_ci	int i;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	func = pinmux_generic_get_function(pctldev, selector);
478c2ecf20Sopenharmony_ci	if (!func)
488c2ecf20Sopenharmony_ci		return -EINVAL;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	grp = pinctrl_generic_get_group(pctldev, group);
518c2ecf20Sopenharmony_ci	if (!grp)
528c2ecf20Sopenharmony_ci		return -EINVAL;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	dev_dbg(pctldev->dev, "enable function %s group %s\n",
558c2ecf20Sopenharmony_ci		func->name, grp->name);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	for (i = 0; i < grp->num_pins; i++) {
588c2ecf20Sopenharmony_ci		const struct mtk_pin_desc *desc;
598c2ecf20Sopenharmony_ci		int *pin_modes = grp->data;
608c2ecf20Sopenharmony_ci		int pin = grp->pins[i];
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci		desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
658c2ecf20Sopenharmony_ci				 pin_modes[i]);
668c2ecf20Sopenharmony_ci	}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	return 0;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
728c2ecf20Sopenharmony_ci					  struct pinctrl_gpio_range *range,
738c2ecf20Sopenharmony_ci					  unsigned int pin)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
768c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
818c2ecf20Sopenharmony_ci				hw->soc->gpio_m);
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
858c2ecf20Sopenharmony_ci					 struct pinctrl_gpio_range *range,
868c2ecf20Sopenharmony_ci					 unsigned int pin, bool input)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
898c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/* hardware would take 0 as input direction */
948c2ecf20Sopenharmony_ci	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic int mtk_pinconf_get(struct pinctrl_dev *pctldev,
988c2ecf20Sopenharmony_ci			   unsigned int pin, unsigned long *config)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
1018c2ecf20Sopenharmony_ci	u32 param = pinconf_to_config_param(*config);
1028c2ecf20Sopenharmony_ci	int val, val2, err, reg, ret = 1;
1038c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	switch (param) {
1088c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_DISABLE:
1098c2ecf20Sopenharmony_ci		if (hw->soc->bias_disable_get) {
1108c2ecf20Sopenharmony_ci			err = hw->soc->bias_disable_get(hw, desc, &ret);
1118c2ecf20Sopenharmony_ci			if (err)
1128c2ecf20Sopenharmony_ci				return err;
1138c2ecf20Sopenharmony_ci		} else {
1148c2ecf20Sopenharmony_ci			return -ENOTSUPP;
1158c2ecf20Sopenharmony_ci		}
1168c2ecf20Sopenharmony_ci		break;
1178c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_UP:
1188c2ecf20Sopenharmony_ci		if (hw->soc->bias_get) {
1198c2ecf20Sopenharmony_ci			err = hw->soc->bias_get(hw, desc, 1, &ret);
1208c2ecf20Sopenharmony_ci			if (err)
1218c2ecf20Sopenharmony_ci				return err;
1228c2ecf20Sopenharmony_ci		} else {
1238c2ecf20Sopenharmony_ci			return -ENOTSUPP;
1248c2ecf20Sopenharmony_ci		}
1258c2ecf20Sopenharmony_ci		break;
1268c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_DOWN:
1278c2ecf20Sopenharmony_ci		if (hw->soc->bias_get) {
1288c2ecf20Sopenharmony_ci			err = hw->soc->bias_get(hw, desc, 0, &ret);
1298c2ecf20Sopenharmony_ci			if (err)
1308c2ecf20Sopenharmony_ci				return err;
1318c2ecf20Sopenharmony_ci		} else {
1328c2ecf20Sopenharmony_ci			return -ENOTSUPP;
1338c2ecf20Sopenharmony_ci		}
1348c2ecf20Sopenharmony_ci		break;
1358c2ecf20Sopenharmony_ci	case PIN_CONFIG_SLEW_RATE:
1368c2ecf20Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
1378c2ecf20Sopenharmony_ci		if (err)
1388c2ecf20Sopenharmony_ci			return err;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci		if (!val)
1418c2ecf20Sopenharmony_ci			return -EINVAL;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci		break;
1448c2ecf20Sopenharmony_ci	case PIN_CONFIG_INPUT_ENABLE:
1458c2ecf20Sopenharmony_ci	case PIN_CONFIG_OUTPUT_ENABLE:
1468c2ecf20Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
1478c2ecf20Sopenharmony_ci		if (err)
1488c2ecf20Sopenharmony_ci			return err;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci		/* HW takes input mode as zero; output mode as non-zero */
1518c2ecf20Sopenharmony_ci		if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
1528c2ecf20Sopenharmony_ci		    (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
1538c2ecf20Sopenharmony_ci			return -EINVAL;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci		break;
1568c2ecf20Sopenharmony_ci	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
1578c2ecf20Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
1588c2ecf20Sopenharmony_ci		if (err)
1598c2ecf20Sopenharmony_ci			return err;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
1628c2ecf20Sopenharmony_ci		if (err)
1638c2ecf20Sopenharmony_ci			return err;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		if (val || !val2)
1668c2ecf20Sopenharmony_ci			return -EINVAL;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci		break;
1698c2ecf20Sopenharmony_ci	case PIN_CONFIG_DRIVE_STRENGTH:
1708c2ecf20Sopenharmony_ci		if (hw->soc->drive_get) {
1718c2ecf20Sopenharmony_ci			err = hw->soc->drive_get(hw, desc, &ret);
1728c2ecf20Sopenharmony_ci			if (err)
1738c2ecf20Sopenharmony_ci				return err;
1748c2ecf20Sopenharmony_ci		} else {
1758c2ecf20Sopenharmony_ci			err = -ENOTSUPP;
1768c2ecf20Sopenharmony_ci		}
1778c2ecf20Sopenharmony_ci		break;
1788c2ecf20Sopenharmony_ci	case MTK_PIN_CONFIG_TDSEL:
1798c2ecf20Sopenharmony_ci	case MTK_PIN_CONFIG_RDSEL:
1808c2ecf20Sopenharmony_ci		reg = (param == MTK_PIN_CONFIG_TDSEL) ?
1818c2ecf20Sopenharmony_ci		       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, reg, &val);
1848c2ecf20Sopenharmony_ci		if (err)
1858c2ecf20Sopenharmony_ci			return err;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci		ret = val;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci		break;
1908c2ecf20Sopenharmony_ci	case MTK_PIN_CONFIG_PU_ADV:
1918c2ecf20Sopenharmony_ci	case MTK_PIN_CONFIG_PD_ADV:
1928c2ecf20Sopenharmony_ci		if (hw->soc->adv_pull_get) {
1938c2ecf20Sopenharmony_ci			bool pullup;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci			pullup = param == MTK_PIN_CONFIG_PU_ADV;
1968c2ecf20Sopenharmony_ci			err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
1978c2ecf20Sopenharmony_ci			if (err)
1988c2ecf20Sopenharmony_ci				return err;
1998c2ecf20Sopenharmony_ci		} else {
2008c2ecf20Sopenharmony_ci			return -ENOTSUPP;
2018c2ecf20Sopenharmony_ci		}
2028c2ecf20Sopenharmony_ci		break;
2038c2ecf20Sopenharmony_ci	default:
2048c2ecf20Sopenharmony_ci		return -ENOTSUPP;
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	*config = pinconf_to_config_packed(param, ret);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	return 0;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
2138c2ecf20Sopenharmony_ci			   unsigned long *configs, unsigned int num_configs)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
2168c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
2178c2ecf20Sopenharmony_ci	u32 reg, param, arg;
2188c2ecf20Sopenharmony_ci	int cfg, err = 0;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	for (cfg = 0; cfg < num_configs; cfg++) {
2238c2ecf20Sopenharmony_ci		param = pinconf_to_config_param(configs[cfg]);
2248c2ecf20Sopenharmony_ci		arg = pinconf_to_config_argument(configs[cfg]);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci		switch (param) {
2278c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_DISABLE:
2288c2ecf20Sopenharmony_ci			if (hw->soc->bias_disable_set) {
2298c2ecf20Sopenharmony_ci				err = hw->soc->bias_disable_set(hw, desc);
2308c2ecf20Sopenharmony_ci				if (err)
2318c2ecf20Sopenharmony_ci					return err;
2328c2ecf20Sopenharmony_ci			} else {
2338c2ecf20Sopenharmony_ci				return -ENOTSUPP;
2348c2ecf20Sopenharmony_ci			}
2358c2ecf20Sopenharmony_ci			break;
2368c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_UP:
2378c2ecf20Sopenharmony_ci			if (hw->soc->bias_set) {
2388c2ecf20Sopenharmony_ci				err = hw->soc->bias_set(hw, desc, 1);
2398c2ecf20Sopenharmony_ci				if (err)
2408c2ecf20Sopenharmony_ci					return err;
2418c2ecf20Sopenharmony_ci			} else {
2428c2ecf20Sopenharmony_ci				return -ENOTSUPP;
2438c2ecf20Sopenharmony_ci			}
2448c2ecf20Sopenharmony_ci			break;
2458c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_DOWN:
2468c2ecf20Sopenharmony_ci			if (hw->soc->bias_set) {
2478c2ecf20Sopenharmony_ci				err = hw->soc->bias_set(hw, desc, 0);
2488c2ecf20Sopenharmony_ci				if (err)
2498c2ecf20Sopenharmony_ci					return err;
2508c2ecf20Sopenharmony_ci			} else {
2518c2ecf20Sopenharmony_ci				return -ENOTSUPP;
2528c2ecf20Sopenharmony_ci			}
2538c2ecf20Sopenharmony_ci			break;
2548c2ecf20Sopenharmony_ci		case PIN_CONFIG_OUTPUT_ENABLE:
2558c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
2568c2ecf20Sopenharmony_ci					       MTK_DISABLE);
2578c2ecf20Sopenharmony_ci			if (err)
2588c2ecf20Sopenharmony_ci				goto err;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
2618c2ecf20Sopenharmony_ci					       MTK_OUTPUT);
2628c2ecf20Sopenharmony_ci			if (err)
2638c2ecf20Sopenharmony_ci				goto err;
2648c2ecf20Sopenharmony_ci			break;
2658c2ecf20Sopenharmony_ci		case PIN_CONFIG_INPUT_ENABLE:
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci			if (hw->soc->ies_present) {
2688c2ecf20Sopenharmony_ci				mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
2698c2ecf20Sopenharmony_ci						 MTK_ENABLE);
2708c2ecf20Sopenharmony_ci			}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
2738c2ecf20Sopenharmony_ci					       MTK_INPUT);
2748c2ecf20Sopenharmony_ci			if (err)
2758c2ecf20Sopenharmony_ci				goto err;
2768c2ecf20Sopenharmony_ci			break;
2778c2ecf20Sopenharmony_ci		case PIN_CONFIG_SLEW_RATE:
2788c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
2798c2ecf20Sopenharmony_ci					       arg);
2808c2ecf20Sopenharmony_ci			if (err)
2818c2ecf20Sopenharmony_ci				goto err;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci			break;
2848c2ecf20Sopenharmony_ci		case PIN_CONFIG_OUTPUT:
2858c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
2868c2ecf20Sopenharmony_ci					       MTK_OUTPUT);
2878c2ecf20Sopenharmony_ci			if (err)
2888c2ecf20Sopenharmony_ci				goto err;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
2918c2ecf20Sopenharmony_ci					       arg);
2928c2ecf20Sopenharmony_ci			if (err)
2938c2ecf20Sopenharmony_ci				goto err;
2948c2ecf20Sopenharmony_ci			break;
2958c2ecf20Sopenharmony_ci		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
2968c2ecf20Sopenharmony_ci			/* arg = 1: Input mode & SMT enable ;
2978c2ecf20Sopenharmony_ci			 * arg = 0: Output mode & SMT disable
2988c2ecf20Sopenharmony_ci			 */
2998c2ecf20Sopenharmony_ci			arg = arg ? 2 : 1;
3008c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
3018c2ecf20Sopenharmony_ci					       arg & 1);
3028c2ecf20Sopenharmony_ci			if (err)
3038c2ecf20Sopenharmony_ci				goto err;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
3068c2ecf20Sopenharmony_ci					       !!(arg & 2));
3078c2ecf20Sopenharmony_ci			if (err)
3088c2ecf20Sopenharmony_ci				goto err;
3098c2ecf20Sopenharmony_ci			break;
3108c2ecf20Sopenharmony_ci		case PIN_CONFIG_DRIVE_STRENGTH:
3118c2ecf20Sopenharmony_ci			if (hw->soc->drive_set) {
3128c2ecf20Sopenharmony_ci				err = hw->soc->drive_set(hw, desc, arg);
3138c2ecf20Sopenharmony_ci				if (err)
3148c2ecf20Sopenharmony_ci					return err;
3158c2ecf20Sopenharmony_ci			} else {
3168c2ecf20Sopenharmony_ci				err = -ENOTSUPP;
3178c2ecf20Sopenharmony_ci			}
3188c2ecf20Sopenharmony_ci			break;
3198c2ecf20Sopenharmony_ci		case MTK_PIN_CONFIG_TDSEL:
3208c2ecf20Sopenharmony_ci		case MTK_PIN_CONFIG_RDSEL:
3218c2ecf20Sopenharmony_ci			reg = (param == MTK_PIN_CONFIG_TDSEL) ?
3228c2ecf20Sopenharmony_ci			       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, reg, arg);
3258c2ecf20Sopenharmony_ci			if (err)
3268c2ecf20Sopenharmony_ci				goto err;
3278c2ecf20Sopenharmony_ci			break;
3288c2ecf20Sopenharmony_ci		case MTK_PIN_CONFIG_PU_ADV:
3298c2ecf20Sopenharmony_ci		case MTK_PIN_CONFIG_PD_ADV:
3308c2ecf20Sopenharmony_ci			if (hw->soc->adv_pull_set) {
3318c2ecf20Sopenharmony_ci				bool pullup;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci				pullup = param == MTK_PIN_CONFIG_PU_ADV;
3348c2ecf20Sopenharmony_ci				err = hw->soc->adv_pull_set(hw, desc, pullup,
3358c2ecf20Sopenharmony_ci							    arg);
3368c2ecf20Sopenharmony_ci				if (err)
3378c2ecf20Sopenharmony_ci					return err;
3388c2ecf20Sopenharmony_ci			} else {
3398c2ecf20Sopenharmony_ci				return -ENOTSUPP;
3408c2ecf20Sopenharmony_ci			}
3418c2ecf20Sopenharmony_ci			break;
3428c2ecf20Sopenharmony_ci		default:
3438c2ecf20Sopenharmony_ci			err = -ENOTSUPP;
3448c2ecf20Sopenharmony_ci		}
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_cierr:
3478c2ecf20Sopenharmony_ci	return err;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
3518c2ecf20Sopenharmony_ci				 unsigned int group, unsigned long *config)
3528c2ecf20Sopenharmony_ci{
3538c2ecf20Sopenharmony_ci	const unsigned int *pins;
3548c2ecf20Sopenharmony_ci	unsigned int i, npins, old = 0;
3558c2ecf20Sopenharmony_ci	int ret;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
3588c2ecf20Sopenharmony_ci	if (ret)
3598c2ecf20Sopenharmony_ci		return ret;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	for (i = 0; i < npins; i++) {
3628c2ecf20Sopenharmony_ci		if (mtk_pinconf_get(pctldev, pins[i], config))
3638c2ecf20Sopenharmony_ci			return -ENOTSUPP;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		/* configs do not match between two pins */
3668c2ecf20Sopenharmony_ci		if (i && old != *config)
3678c2ecf20Sopenharmony_ci			return -ENOTSUPP;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci		old = *config;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	return 0;
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_cistatic int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
3768c2ecf20Sopenharmony_ci				 unsigned int group, unsigned long *configs,
3778c2ecf20Sopenharmony_ci				 unsigned int num_configs)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	const unsigned int *pins;
3808c2ecf20Sopenharmony_ci	unsigned int i, npins;
3818c2ecf20Sopenharmony_ci	int ret;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
3848c2ecf20Sopenharmony_ci	if (ret)
3858c2ecf20Sopenharmony_ci		return ret;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	for (i = 0; i < npins; i++) {
3888c2ecf20Sopenharmony_ci		ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
3898c2ecf20Sopenharmony_ci		if (ret)
3908c2ecf20Sopenharmony_ci			return ret;
3918c2ecf20Sopenharmony_ci	}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	return 0;
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_cistatic const struct pinctrl_ops mtk_pctlops = {
3978c2ecf20Sopenharmony_ci	.get_groups_count = pinctrl_generic_get_group_count,
3988c2ecf20Sopenharmony_ci	.get_group_name = pinctrl_generic_get_group_name,
3998c2ecf20Sopenharmony_ci	.get_group_pins = pinctrl_generic_get_group_pins,
4008c2ecf20Sopenharmony_ci	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
4018c2ecf20Sopenharmony_ci	.dt_free_map = pinconf_generic_dt_free_map,
4028c2ecf20Sopenharmony_ci};
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic const struct pinmux_ops mtk_pmxops = {
4058c2ecf20Sopenharmony_ci	.get_functions_count = pinmux_generic_get_function_count,
4068c2ecf20Sopenharmony_ci	.get_function_name = pinmux_generic_get_function_name,
4078c2ecf20Sopenharmony_ci	.get_function_groups = pinmux_generic_get_function_groups,
4088c2ecf20Sopenharmony_ci	.set_mux = mtk_pinmux_set_mux,
4098c2ecf20Sopenharmony_ci	.gpio_request_enable = mtk_pinmux_gpio_request_enable,
4108c2ecf20Sopenharmony_ci	.gpio_set_direction = mtk_pinmux_gpio_set_direction,
4118c2ecf20Sopenharmony_ci	.strict = true,
4128c2ecf20Sopenharmony_ci};
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic const struct pinconf_ops mtk_confops = {
4158c2ecf20Sopenharmony_ci	.is_generic = true,
4168c2ecf20Sopenharmony_ci	.pin_config_get = mtk_pinconf_get,
4178c2ecf20Sopenharmony_ci	.pin_config_set = mtk_pinconf_set,
4188c2ecf20Sopenharmony_ci	.pin_config_group_get = mtk_pinconf_group_get,
4198c2ecf20Sopenharmony_ci	.pin_config_group_set = mtk_pinconf_group_set,
4208c2ecf20Sopenharmony_ci	.pin_config_config_dbg_show = pinconf_generic_dump_config,
4218c2ecf20Sopenharmony_ci};
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic struct pinctrl_desc mtk_desc = {
4248c2ecf20Sopenharmony_ci	.name = PINCTRL_PINCTRL_DEV,
4258c2ecf20Sopenharmony_ci	.pctlops = &mtk_pctlops,
4268c2ecf20Sopenharmony_ci	.pmxops = &mtk_pmxops,
4278c2ecf20Sopenharmony_ci	.confops = &mtk_confops,
4288c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
4298c2ecf20Sopenharmony_ci};
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
4348c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
4358c2ecf20Sopenharmony_ci	int value, err;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
4408c2ecf20Sopenharmony_ci	if (err)
4418c2ecf20Sopenharmony_ci		return err;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	return !!value;
4448c2ecf20Sopenharmony_ci}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_cistatic void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
4498c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	return pinctrl_gpio_direction_input(chip->base + gpio);
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
4628c2ecf20Sopenharmony_ci				     int value)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci	mtk_gpio_set(chip, gpio, value);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	return pinctrl_gpio_direction_output(chip->base + gpio);
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cistatic int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
4708c2ecf20Sopenharmony_ci{
4718c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
4728c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	if (!hw->eint)
4758c2ecf20Sopenharmony_ci		return -ENOTSUPP;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	if (desc->eint.eint_n == (u16)EINT_NA)
4808c2ecf20Sopenharmony_ci		return -ENOTSUPP;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	return mtk_eint_find_irq(hw->eint, desc->eint.eint_n);
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
4868c2ecf20Sopenharmony_ci			       unsigned long config)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
4898c2ecf20Sopenharmony_ci	const struct mtk_pin_desc *desc;
4908c2ecf20Sopenharmony_ci	u32 debounce;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	if (!hw->eint ||
4958c2ecf20Sopenharmony_ci	    pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE ||
4968c2ecf20Sopenharmony_ci	    desc->eint.eint_n == (u16)EINT_NA)
4978c2ecf20Sopenharmony_ci		return -ENOTSUPP;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	debounce = pinconf_to_config_argument(config);
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce);
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_cistatic int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	struct gpio_chip *chip = &hw->chip;
5078c2ecf20Sopenharmony_ci	int ret;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	chip->label		= PINCTRL_PINCTRL_DEV;
5108c2ecf20Sopenharmony_ci	chip->parent		= hw->dev;
5118c2ecf20Sopenharmony_ci	chip->request		= gpiochip_generic_request;
5128c2ecf20Sopenharmony_ci	chip->free		= gpiochip_generic_free;
5138c2ecf20Sopenharmony_ci	chip->direction_input	= mtk_gpio_direction_input;
5148c2ecf20Sopenharmony_ci	chip->direction_output	= mtk_gpio_direction_output;
5158c2ecf20Sopenharmony_ci	chip->get		= mtk_gpio_get;
5168c2ecf20Sopenharmony_ci	chip->set		= mtk_gpio_set;
5178c2ecf20Sopenharmony_ci	chip->to_irq		= mtk_gpio_to_irq,
5188c2ecf20Sopenharmony_ci	chip->set_config	= mtk_gpio_set_config,
5198c2ecf20Sopenharmony_ci	chip->base		= -1;
5208c2ecf20Sopenharmony_ci	chip->ngpio		= hw->soc->npins;
5218c2ecf20Sopenharmony_ci	chip->of_node		= np;
5228c2ecf20Sopenharmony_ci	chip->of_gpio_n_cells	= 2;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	ret = gpiochip_add_data(chip, hw);
5258c2ecf20Sopenharmony_ci	if (ret < 0)
5268c2ecf20Sopenharmony_ci		return ret;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	/* Just for backward compatible for these old pinctrl nodes without
5298c2ecf20Sopenharmony_ci	 * "gpio-ranges" property. Otherwise, called directly from a
5308c2ecf20Sopenharmony_ci	 * DeviceTree-supported pinctrl driver is DEPRECATED.
5318c2ecf20Sopenharmony_ci	 * Please see Section 2.1 of
5328c2ecf20Sopenharmony_ci	 * Documentation/devicetree/bindings/gpio/gpio.txt on how to
5338c2ecf20Sopenharmony_ci	 * bind pinctrl and gpio drivers via the "gpio-ranges" property.
5348c2ecf20Sopenharmony_ci	 */
5358c2ecf20Sopenharmony_ci	if (!of_find_property(np, "gpio-ranges", NULL)) {
5368c2ecf20Sopenharmony_ci		ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
5378c2ecf20Sopenharmony_ci					     chip->ngpio);
5388c2ecf20Sopenharmony_ci		if (ret < 0) {
5398c2ecf20Sopenharmony_ci			gpiochip_remove(chip);
5408c2ecf20Sopenharmony_ci			return ret;
5418c2ecf20Sopenharmony_ci		}
5428c2ecf20Sopenharmony_ci	}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	return 0;
5458c2ecf20Sopenharmony_ci}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_cistatic int mtk_build_groups(struct mtk_pinctrl *hw)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	int err, i;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	for (i = 0; i < hw->soc->ngrps; i++) {
5528c2ecf20Sopenharmony_ci		const struct group_desc *group = hw->soc->grps + i;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci		err = pinctrl_generic_add_group(hw->pctrl, group->name,
5558c2ecf20Sopenharmony_ci						group->pins, group->num_pins,
5568c2ecf20Sopenharmony_ci						group->data);
5578c2ecf20Sopenharmony_ci		if (err < 0) {
5588c2ecf20Sopenharmony_ci			dev_err(hw->dev, "Failed to register group %s\n",
5598c2ecf20Sopenharmony_ci				group->name);
5608c2ecf20Sopenharmony_ci			return err;
5618c2ecf20Sopenharmony_ci		}
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	return 0;
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic int mtk_build_functions(struct mtk_pinctrl *hw)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	int i, err;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	for (i = 0; i < hw->soc->nfuncs ; i++) {
5728c2ecf20Sopenharmony_ci		const struct function_desc *func = hw->soc->funcs + i;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci		err = pinmux_generic_add_function(hw->pctrl, func->name,
5758c2ecf20Sopenharmony_ci						  func->group_names,
5768c2ecf20Sopenharmony_ci						  func->num_group_names,
5778c2ecf20Sopenharmony_ci						  func->data);
5788c2ecf20Sopenharmony_ci		if (err < 0) {
5798c2ecf20Sopenharmony_ci			dev_err(hw->dev, "Failed to register function %s\n",
5808c2ecf20Sopenharmony_ci				func->name);
5818c2ecf20Sopenharmony_ci			return err;
5828c2ecf20Sopenharmony_ci		}
5838c2ecf20Sopenharmony_ci	}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	return 0;
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ciint mtk_moore_pinctrl_probe(struct platform_device *pdev,
5898c2ecf20Sopenharmony_ci			    const struct mtk_pin_soc *soc)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	struct pinctrl_pin_desc *pins;
5928c2ecf20Sopenharmony_ci	struct mtk_pinctrl *hw;
5938c2ecf20Sopenharmony_ci	int err, i;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
5968c2ecf20Sopenharmony_ci	if (!hw)
5978c2ecf20Sopenharmony_ci		return -ENOMEM;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	hw->soc = soc;
6008c2ecf20Sopenharmony_ci	hw->dev = &pdev->dev;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (!hw->soc->nbase_names) {
6038c2ecf20Sopenharmony_ci		dev_err(&pdev->dev,
6048c2ecf20Sopenharmony_ci			"SoC should be assigned at least one register base\n");
6058c2ecf20Sopenharmony_ci		return -EINVAL;
6068c2ecf20Sopenharmony_ci	}
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
6098c2ecf20Sopenharmony_ci				      sizeof(*hw->base), GFP_KERNEL);
6108c2ecf20Sopenharmony_ci	if (!hw->base)
6118c2ecf20Sopenharmony_ci		return -ENOMEM;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	for (i = 0; i < hw->soc->nbase_names; i++) {
6148c2ecf20Sopenharmony_ci		hw->base[i] = devm_platform_ioremap_resource_byname(pdev,
6158c2ecf20Sopenharmony_ci						hw->soc->base_names[i]);
6168c2ecf20Sopenharmony_ci		if (IS_ERR(hw->base[i]))
6178c2ecf20Sopenharmony_ci			return PTR_ERR(hw->base[i]);
6188c2ecf20Sopenharmony_ci	}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	hw->nbase = hw->soc->nbase_names;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	/* Copy from internal struct mtk_pin_desc to register to the core */
6238c2ecf20Sopenharmony_ci	pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
6248c2ecf20Sopenharmony_ci				  GFP_KERNEL);
6258c2ecf20Sopenharmony_ci	if (!pins)
6268c2ecf20Sopenharmony_ci		return -ENOMEM;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	for (i = 0; i < hw->soc->npins; i++) {
6298c2ecf20Sopenharmony_ci		pins[i].number = hw->soc->pins[i].number;
6308c2ecf20Sopenharmony_ci		pins[i].name = hw->soc->pins[i].name;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	/* Setup pins descriptions per SoC types */
6348c2ecf20Sopenharmony_ci	mtk_desc.pins = (const struct pinctrl_pin_desc *)pins;
6358c2ecf20Sopenharmony_ci	mtk_desc.npins = hw->soc->npins;
6368c2ecf20Sopenharmony_ci	mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
6378c2ecf20Sopenharmony_ci	mtk_desc.custom_params = mtk_custom_bindings;
6388c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
6398c2ecf20Sopenharmony_ci	mtk_desc.custom_conf_items = mtk_conf_items;
6408c2ecf20Sopenharmony_ci#endif
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw,
6438c2ecf20Sopenharmony_ci					     &hw->pctrl);
6448c2ecf20Sopenharmony_ci	if (err)
6458c2ecf20Sopenharmony_ci		return err;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	/* Setup groups descriptions per SoC types */
6488c2ecf20Sopenharmony_ci	err = mtk_build_groups(hw);
6498c2ecf20Sopenharmony_ci	if (err) {
6508c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to build groups\n");
6518c2ecf20Sopenharmony_ci		return err;
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	/* Setup functions descriptions per SoC types */
6558c2ecf20Sopenharmony_ci	err = mtk_build_functions(hw);
6568c2ecf20Sopenharmony_ci	if (err) {
6578c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to build functions\n");
6588c2ecf20Sopenharmony_ci		return err;
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	/* For able to make pinctrl_claim_hogs, we must not enable pinctrl
6628c2ecf20Sopenharmony_ci	 * until all groups and functions are being added one.
6638c2ecf20Sopenharmony_ci	 */
6648c2ecf20Sopenharmony_ci	err = pinctrl_enable(hw->pctrl);
6658c2ecf20Sopenharmony_ci	if (err)
6668c2ecf20Sopenharmony_ci		return err;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	err = mtk_build_eint(hw, pdev);
6698c2ecf20Sopenharmony_ci	if (err)
6708c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev,
6718c2ecf20Sopenharmony_ci			 "Failed to add EINT, but pinctrl still can work\n");
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	/* Build gpiochip should be after pinctrl_enable is done */
6748c2ecf20Sopenharmony_ci	err = mtk_build_gpiochip(hw, pdev->dev.of_node);
6758c2ecf20Sopenharmony_ci	if (err) {
6768c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to add gpio_chip\n");
6778c2ecf20Sopenharmony_ci		return err;
6788c2ecf20Sopenharmony_ci	}
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, hw);
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	return 0;
6838c2ecf20Sopenharmony_ci}
684