162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * MediaTek Pinctrl Moore Driver, which implement the generic dt-binding
462306a36Sopenharmony_ci * pinctrl-bindings.txt for MediaTek SoC.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2017-2018 MediaTek Inc.
762306a36Sopenharmony_ci * Author: Sean Wang <sean.wang@mediatek.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <dt-bindings/pinctrl/mt65xx.h>
1262306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "pinctrl-moore.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define PINCTRL_PINCTRL_DEV		KBUILD_MODNAME
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* Custom pinconf parameters */
2162306a36Sopenharmony_ci#define MTK_PIN_CONFIG_TDSEL	(PIN_CONFIG_END + 1)
2262306a36Sopenharmony_ci#define MTK_PIN_CONFIG_RDSEL	(PIN_CONFIG_END + 2)
2362306a36Sopenharmony_ci#define MTK_PIN_CONFIG_PU_ADV	(PIN_CONFIG_END + 3)
2462306a36Sopenharmony_ci#define MTK_PIN_CONFIG_PD_ADV	(PIN_CONFIG_END + 4)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic const struct pinconf_generic_params mtk_custom_bindings[] = {
2762306a36Sopenharmony_ci	{"mediatek,tdsel",	MTK_PIN_CONFIG_TDSEL,		0},
2862306a36Sopenharmony_ci	{"mediatek,rdsel",	MTK_PIN_CONFIG_RDSEL,		0},
2962306a36Sopenharmony_ci	{"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV,		1},
3062306a36Sopenharmony_ci	{"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV,	1},
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
3462306a36Sopenharmony_cistatic const struct pin_config_item mtk_conf_items[] = {
3562306a36Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
3662306a36Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
3762306a36Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true),
3862306a36Sopenharmony_ci	PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true),
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci#endif
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
4362306a36Sopenharmony_ci			      unsigned int selector, unsigned int group)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
4662306a36Sopenharmony_ci	struct function_desc *func;
4762306a36Sopenharmony_ci	struct group_desc *grp;
4862306a36Sopenharmony_ci	int i;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	func = pinmux_generic_get_function(pctldev, selector);
5162306a36Sopenharmony_ci	if (!func)
5262306a36Sopenharmony_ci		return -EINVAL;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	grp = pinctrl_generic_get_group(pctldev, group);
5562306a36Sopenharmony_ci	if (!grp)
5662306a36Sopenharmony_ci		return -EINVAL;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	dev_dbg(pctldev->dev, "enable function %s group %s\n",
5962306a36Sopenharmony_ci		func->name, grp->name);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	for (i = 0; i < grp->num_pins; i++) {
6262306a36Sopenharmony_ci		const struct mtk_pin_desc *desc;
6362306a36Sopenharmony_ci		int *pin_modes = grp->data;
6462306a36Sopenharmony_ci		int pin = grp->pins[i];
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
6762306a36Sopenharmony_ci		if (!desc->name)
6862306a36Sopenharmony_ci			return -ENOTSUPP;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci		mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
7162306a36Sopenharmony_ci				 pin_modes[i]);
7262306a36Sopenharmony_ci	}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	return 0;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
7862306a36Sopenharmony_ci					  struct pinctrl_gpio_range *range,
7962306a36Sopenharmony_ci					  unsigned int pin)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
8262306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
8562306a36Sopenharmony_ci	if (!desc->name)
8662306a36Sopenharmony_ci		return -ENOTSUPP;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
8962306a36Sopenharmony_ci				hw->soc->gpio_m);
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
9362306a36Sopenharmony_ci					 struct pinctrl_gpio_range *range,
9462306a36Sopenharmony_ci					 unsigned int pin, bool input)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
9762306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
10062306a36Sopenharmony_ci	if (!desc->name)
10162306a36Sopenharmony_ci		return -ENOTSUPP;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* hardware would take 0 as input direction */
10462306a36Sopenharmony_ci	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic int mtk_pinconf_get(struct pinctrl_dev *pctldev,
10862306a36Sopenharmony_ci			   unsigned int pin, unsigned long *config)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
11162306a36Sopenharmony_ci	u32 param = pinconf_to_config_param(*config);
11262306a36Sopenharmony_ci	int val, val2, err, pullup, reg, ret = 1;
11362306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
11662306a36Sopenharmony_ci	if (!desc->name)
11762306a36Sopenharmony_ci		return -ENOTSUPP;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	switch (param) {
12062306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_DISABLE:
12162306a36Sopenharmony_ci		if (hw->soc->bias_get_combo) {
12262306a36Sopenharmony_ci			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
12362306a36Sopenharmony_ci			if (err)
12462306a36Sopenharmony_ci				return err;
12562306a36Sopenharmony_ci			if (ret != MTK_PUPD_SET_R1R0_00 && ret != MTK_DISABLE)
12662306a36Sopenharmony_ci				return -EINVAL;
12762306a36Sopenharmony_ci		} else if (hw->soc->bias_disable_get) {
12862306a36Sopenharmony_ci			err = hw->soc->bias_disable_get(hw, desc, &ret);
12962306a36Sopenharmony_ci			if (err)
13062306a36Sopenharmony_ci				return err;
13162306a36Sopenharmony_ci		} else {
13262306a36Sopenharmony_ci			return -ENOTSUPP;
13362306a36Sopenharmony_ci		}
13462306a36Sopenharmony_ci		break;
13562306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_UP:
13662306a36Sopenharmony_ci		if (hw->soc->bias_get_combo) {
13762306a36Sopenharmony_ci			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
13862306a36Sopenharmony_ci			if (err)
13962306a36Sopenharmony_ci				return err;
14062306a36Sopenharmony_ci			if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE)
14162306a36Sopenharmony_ci				return -EINVAL;
14262306a36Sopenharmony_ci			if (!pullup)
14362306a36Sopenharmony_ci				return -EINVAL;
14462306a36Sopenharmony_ci		} else if (hw->soc->bias_get) {
14562306a36Sopenharmony_ci			err = hw->soc->bias_get(hw, desc, 1, &ret);
14662306a36Sopenharmony_ci			if (err)
14762306a36Sopenharmony_ci				return err;
14862306a36Sopenharmony_ci		} else {
14962306a36Sopenharmony_ci			return -ENOTSUPP;
15062306a36Sopenharmony_ci		}
15162306a36Sopenharmony_ci		break;
15262306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_DOWN:
15362306a36Sopenharmony_ci		if (hw->soc->bias_get_combo) {
15462306a36Sopenharmony_ci			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
15562306a36Sopenharmony_ci			if (err)
15662306a36Sopenharmony_ci				return err;
15762306a36Sopenharmony_ci			if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE)
15862306a36Sopenharmony_ci				return -EINVAL;
15962306a36Sopenharmony_ci			if (pullup)
16062306a36Sopenharmony_ci				return -EINVAL;
16162306a36Sopenharmony_ci		} else if (hw->soc->bias_get) {
16262306a36Sopenharmony_ci			err = hw->soc->bias_get(hw, desc, 0, &ret);
16362306a36Sopenharmony_ci			if (err)
16462306a36Sopenharmony_ci				return err;
16562306a36Sopenharmony_ci		} else {
16662306a36Sopenharmony_ci			return -ENOTSUPP;
16762306a36Sopenharmony_ci		}
16862306a36Sopenharmony_ci		break;
16962306a36Sopenharmony_ci	case PIN_CONFIG_SLEW_RATE:
17062306a36Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
17162306a36Sopenharmony_ci		if (err)
17262306a36Sopenharmony_ci			return err;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		if (!val)
17562306a36Sopenharmony_ci			return -EINVAL;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci		break;
17862306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_ENABLE:
17962306a36Sopenharmony_ci	case PIN_CONFIG_OUTPUT_ENABLE:
18062306a36Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
18162306a36Sopenharmony_ci		if (err)
18262306a36Sopenharmony_ci			return err;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		/* HW takes input mode as zero; output mode as non-zero */
18562306a36Sopenharmony_ci		if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
18662306a36Sopenharmony_ci		    (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
18762306a36Sopenharmony_ci			return -EINVAL;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci		break;
19062306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
19162306a36Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
19262306a36Sopenharmony_ci		if (err)
19362306a36Sopenharmony_ci			return err;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
19662306a36Sopenharmony_ci		if (err)
19762306a36Sopenharmony_ci			return err;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci		if (val || !val2)
20062306a36Sopenharmony_ci			return -EINVAL;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci		break;
20362306a36Sopenharmony_ci	case PIN_CONFIG_DRIVE_STRENGTH:
20462306a36Sopenharmony_ci		if (hw->soc->drive_get) {
20562306a36Sopenharmony_ci			err = hw->soc->drive_get(hw, desc, &ret);
20662306a36Sopenharmony_ci			if (err)
20762306a36Sopenharmony_ci				return err;
20862306a36Sopenharmony_ci		} else {
20962306a36Sopenharmony_ci			err = -ENOTSUPP;
21062306a36Sopenharmony_ci		}
21162306a36Sopenharmony_ci		break;
21262306a36Sopenharmony_ci	case MTK_PIN_CONFIG_TDSEL:
21362306a36Sopenharmony_ci	case MTK_PIN_CONFIG_RDSEL:
21462306a36Sopenharmony_ci		reg = (param == MTK_PIN_CONFIG_TDSEL) ?
21562306a36Sopenharmony_ci		       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		err = mtk_hw_get_value(hw, desc, reg, &val);
21862306a36Sopenharmony_ci		if (err)
21962306a36Sopenharmony_ci			return err;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		ret = val;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci		break;
22462306a36Sopenharmony_ci	case MTK_PIN_CONFIG_PU_ADV:
22562306a36Sopenharmony_ci	case MTK_PIN_CONFIG_PD_ADV:
22662306a36Sopenharmony_ci		if (hw->soc->adv_pull_get) {
22762306a36Sopenharmony_ci			bool pullup;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci			pullup = param == MTK_PIN_CONFIG_PU_ADV;
23062306a36Sopenharmony_ci			err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
23162306a36Sopenharmony_ci			if (err)
23262306a36Sopenharmony_ci				return err;
23362306a36Sopenharmony_ci		} else {
23462306a36Sopenharmony_ci			return -ENOTSUPP;
23562306a36Sopenharmony_ci		}
23662306a36Sopenharmony_ci		break;
23762306a36Sopenharmony_ci	default:
23862306a36Sopenharmony_ci		return -ENOTSUPP;
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	*config = pinconf_to_config_packed(param, ret);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return 0;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
24762306a36Sopenharmony_ci			   unsigned long *configs, unsigned int num_configs)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
25062306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
25162306a36Sopenharmony_ci	u32 reg, param, arg;
25262306a36Sopenharmony_ci	int cfg, err = 0;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
25562306a36Sopenharmony_ci	if (!desc->name)
25662306a36Sopenharmony_ci		return -ENOTSUPP;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	for (cfg = 0; cfg < num_configs; cfg++) {
25962306a36Sopenharmony_ci		param = pinconf_to_config_param(configs[cfg]);
26062306a36Sopenharmony_ci		arg = pinconf_to_config_argument(configs[cfg]);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci		switch (param) {
26362306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_DISABLE:
26462306a36Sopenharmony_ci			if (hw->soc->bias_set_combo) {
26562306a36Sopenharmony_ci				err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE);
26662306a36Sopenharmony_ci				if (err)
26762306a36Sopenharmony_ci					return err;
26862306a36Sopenharmony_ci			} else if (hw->soc->bias_disable_set) {
26962306a36Sopenharmony_ci				err = hw->soc->bias_disable_set(hw, desc);
27062306a36Sopenharmony_ci				if (err)
27162306a36Sopenharmony_ci					return err;
27262306a36Sopenharmony_ci			} else {
27362306a36Sopenharmony_ci				return -ENOTSUPP;
27462306a36Sopenharmony_ci			}
27562306a36Sopenharmony_ci			break;
27662306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_UP:
27762306a36Sopenharmony_ci			if (hw->soc->bias_set_combo) {
27862306a36Sopenharmony_ci				err = hw->soc->bias_set_combo(hw, desc, 1, arg);
27962306a36Sopenharmony_ci				if (err)
28062306a36Sopenharmony_ci					return err;
28162306a36Sopenharmony_ci			} else if (hw->soc->bias_set) {
28262306a36Sopenharmony_ci				err = hw->soc->bias_set(hw, desc, 1);
28362306a36Sopenharmony_ci				if (err)
28462306a36Sopenharmony_ci					return err;
28562306a36Sopenharmony_ci			} else {
28662306a36Sopenharmony_ci				return -ENOTSUPP;
28762306a36Sopenharmony_ci			}
28862306a36Sopenharmony_ci			break;
28962306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_DOWN:
29062306a36Sopenharmony_ci			if (hw->soc->bias_set_combo) {
29162306a36Sopenharmony_ci				err = hw->soc->bias_set_combo(hw, desc, 0, arg);
29262306a36Sopenharmony_ci				if (err)
29362306a36Sopenharmony_ci					return err;
29462306a36Sopenharmony_ci			} else if (hw->soc->bias_set) {
29562306a36Sopenharmony_ci				err = hw->soc->bias_set(hw, desc, 0);
29662306a36Sopenharmony_ci				if (err)
29762306a36Sopenharmony_ci					return err;
29862306a36Sopenharmony_ci			} else {
29962306a36Sopenharmony_ci				return -ENOTSUPP;
30062306a36Sopenharmony_ci			}
30162306a36Sopenharmony_ci			break;
30262306a36Sopenharmony_ci		case PIN_CONFIG_OUTPUT_ENABLE:
30362306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
30462306a36Sopenharmony_ci					       MTK_DISABLE);
30562306a36Sopenharmony_ci			if (err)
30662306a36Sopenharmony_ci				goto err;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
30962306a36Sopenharmony_ci					       MTK_OUTPUT);
31062306a36Sopenharmony_ci			if (err)
31162306a36Sopenharmony_ci				goto err;
31262306a36Sopenharmony_ci			break;
31362306a36Sopenharmony_ci		case PIN_CONFIG_INPUT_ENABLE:
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci			if (hw->soc->ies_present) {
31662306a36Sopenharmony_ci				mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
31762306a36Sopenharmony_ci						 MTK_ENABLE);
31862306a36Sopenharmony_ci			}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
32162306a36Sopenharmony_ci					       MTK_INPUT);
32262306a36Sopenharmony_ci			if (err)
32362306a36Sopenharmony_ci				goto err;
32462306a36Sopenharmony_ci			break;
32562306a36Sopenharmony_ci		case PIN_CONFIG_SLEW_RATE:
32662306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
32762306a36Sopenharmony_ci					       arg);
32862306a36Sopenharmony_ci			if (err)
32962306a36Sopenharmony_ci				goto err;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci			break;
33262306a36Sopenharmony_ci		case PIN_CONFIG_OUTPUT:
33362306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
33462306a36Sopenharmony_ci					       MTK_OUTPUT);
33562306a36Sopenharmony_ci			if (err)
33662306a36Sopenharmony_ci				goto err;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
33962306a36Sopenharmony_ci					       arg);
34062306a36Sopenharmony_ci			if (err)
34162306a36Sopenharmony_ci				goto err;
34262306a36Sopenharmony_ci			break;
34362306a36Sopenharmony_ci		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
34462306a36Sopenharmony_ci			/* arg = 1: Input mode & SMT enable ;
34562306a36Sopenharmony_ci			 * arg = 0: Output mode & SMT disable
34662306a36Sopenharmony_ci			 */
34762306a36Sopenharmony_ci			arg = arg ? 2 : 1;
34862306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
34962306a36Sopenharmony_ci					       arg & 1);
35062306a36Sopenharmony_ci			if (err)
35162306a36Sopenharmony_ci				goto err;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
35462306a36Sopenharmony_ci					       !!(arg & 2));
35562306a36Sopenharmony_ci			if (err)
35662306a36Sopenharmony_ci				goto err;
35762306a36Sopenharmony_ci			break;
35862306a36Sopenharmony_ci		case PIN_CONFIG_DRIVE_STRENGTH:
35962306a36Sopenharmony_ci			if (hw->soc->drive_set) {
36062306a36Sopenharmony_ci				err = hw->soc->drive_set(hw, desc, arg);
36162306a36Sopenharmony_ci				if (err)
36262306a36Sopenharmony_ci					return err;
36362306a36Sopenharmony_ci			} else {
36462306a36Sopenharmony_ci				err = -ENOTSUPP;
36562306a36Sopenharmony_ci			}
36662306a36Sopenharmony_ci			break;
36762306a36Sopenharmony_ci		case MTK_PIN_CONFIG_TDSEL:
36862306a36Sopenharmony_ci		case MTK_PIN_CONFIG_RDSEL:
36962306a36Sopenharmony_ci			reg = (param == MTK_PIN_CONFIG_TDSEL) ?
37062306a36Sopenharmony_ci			       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci			err = mtk_hw_set_value(hw, desc, reg, arg);
37362306a36Sopenharmony_ci			if (err)
37462306a36Sopenharmony_ci				goto err;
37562306a36Sopenharmony_ci			break;
37662306a36Sopenharmony_ci		case MTK_PIN_CONFIG_PU_ADV:
37762306a36Sopenharmony_ci		case MTK_PIN_CONFIG_PD_ADV:
37862306a36Sopenharmony_ci			if (hw->soc->adv_pull_set) {
37962306a36Sopenharmony_ci				bool pullup;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci				pullup = param == MTK_PIN_CONFIG_PU_ADV;
38262306a36Sopenharmony_ci				err = hw->soc->adv_pull_set(hw, desc, pullup,
38362306a36Sopenharmony_ci							    arg);
38462306a36Sopenharmony_ci				if (err)
38562306a36Sopenharmony_ci					return err;
38662306a36Sopenharmony_ci			} else {
38762306a36Sopenharmony_ci				return -ENOTSUPP;
38862306a36Sopenharmony_ci			}
38962306a36Sopenharmony_ci			break;
39062306a36Sopenharmony_ci		default:
39162306a36Sopenharmony_ci			err = -ENOTSUPP;
39262306a36Sopenharmony_ci		}
39362306a36Sopenharmony_ci	}
39462306a36Sopenharmony_cierr:
39562306a36Sopenharmony_ci	return err;
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
39962306a36Sopenharmony_ci				 unsigned int group, unsigned long *config)
40062306a36Sopenharmony_ci{
40162306a36Sopenharmony_ci	const unsigned int *pins;
40262306a36Sopenharmony_ci	unsigned int i, npins, old = 0;
40362306a36Sopenharmony_ci	int ret;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
40662306a36Sopenharmony_ci	if (ret)
40762306a36Sopenharmony_ci		return ret;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	for (i = 0; i < npins; i++) {
41062306a36Sopenharmony_ci		if (mtk_pinconf_get(pctldev, pins[i], config))
41162306a36Sopenharmony_ci			return -ENOTSUPP;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci		/* configs do not match between two pins */
41462306a36Sopenharmony_ci		if (i && old != *config)
41562306a36Sopenharmony_ci			return -ENOTSUPP;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci		old = *config;
41862306a36Sopenharmony_ci	}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	return 0;
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
42462306a36Sopenharmony_ci				 unsigned int group, unsigned long *configs,
42562306a36Sopenharmony_ci				 unsigned int num_configs)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	const unsigned int *pins;
42862306a36Sopenharmony_ci	unsigned int i, npins;
42962306a36Sopenharmony_ci	int ret;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
43262306a36Sopenharmony_ci	if (ret)
43362306a36Sopenharmony_ci		return ret;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	for (i = 0; i < npins; i++) {
43662306a36Sopenharmony_ci		ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
43762306a36Sopenharmony_ci		if (ret)
43862306a36Sopenharmony_ci			return ret;
43962306a36Sopenharmony_ci	}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	return 0;
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic const struct pinctrl_ops mtk_pctlops = {
44562306a36Sopenharmony_ci	.get_groups_count = pinctrl_generic_get_group_count,
44662306a36Sopenharmony_ci	.get_group_name = pinctrl_generic_get_group_name,
44762306a36Sopenharmony_ci	.get_group_pins = pinctrl_generic_get_group_pins,
44862306a36Sopenharmony_ci	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
44962306a36Sopenharmony_ci	.dt_free_map = pinconf_generic_dt_free_map,
45062306a36Sopenharmony_ci};
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cistatic const struct pinmux_ops mtk_pmxops = {
45362306a36Sopenharmony_ci	.get_functions_count = pinmux_generic_get_function_count,
45462306a36Sopenharmony_ci	.get_function_name = pinmux_generic_get_function_name,
45562306a36Sopenharmony_ci	.get_function_groups = pinmux_generic_get_function_groups,
45662306a36Sopenharmony_ci	.set_mux = mtk_pinmux_set_mux,
45762306a36Sopenharmony_ci	.gpio_request_enable = mtk_pinmux_gpio_request_enable,
45862306a36Sopenharmony_ci	.gpio_set_direction = mtk_pinmux_gpio_set_direction,
45962306a36Sopenharmony_ci	.strict = true,
46062306a36Sopenharmony_ci};
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic const struct pinconf_ops mtk_confops = {
46362306a36Sopenharmony_ci	.is_generic = true,
46462306a36Sopenharmony_ci	.pin_config_get = mtk_pinconf_get,
46562306a36Sopenharmony_ci	.pin_config_set = mtk_pinconf_set,
46662306a36Sopenharmony_ci	.pin_config_group_get = mtk_pinconf_group_get,
46762306a36Sopenharmony_ci	.pin_config_group_set = mtk_pinconf_group_set,
46862306a36Sopenharmony_ci	.pin_config_config_dbg_show = pinconf_generic_dump_config,
46962306a36Sopenharmony_ci};
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_cistatic struct pinctrl_desc mtk_desc = {
47262306a36Sopenharmony_ci	.name = PINCTRL_PINCTRL_DEV,
47362306a36Sopenharmony_ci	.pctlops = &mtk_pctlops,
47462306a36Sopenharmony_ci	.pmxops = &mtk_pmxops,
47562306a36Sopenharmony_ci	.confops = &mtk_confops,
47662306a36Sopenharmony_ci	.owner = THIS_MODULE,
47762306a36Sopenharmony_ci};
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_cistatic int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
48262306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
48362306a36Sopenharmony_ci	int value, err;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
48662306a36Sopenharmony_ci	if (!desc->name)
48762306a36Sopenharmony_ci		return -ENOTSUPP;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
49062306a36Sopenharmony_ci	if (err)
49162306a36Sopenharmony_ci		return err;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	return !!value;
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_cistatic void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
49962306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
50262306a36Sopenharmony_ci	if (!desc->name) {
50362306a36Sopenharmony_ci		dev_err(hw->dev, "Failed to set gpio %d\n", gpio);
50462306a36Sopenharmony_ci		return;
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistatic int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
51162306a36Sopenharmony_ci{
51262306a36Sopenharmony_ci	return pinctrl_gpio_direction_input(chip->base + gpio);
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_cistatic int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
51662306a36Sopenharmony_ci				     int value)
51762306a36Sopenharmony_ci{
51862306a36Sopenharmony_ci	mtk_gpio_set(chip, gpio, value);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	return pinctrl_gpio_direction_output(chip->base + gpio);
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
52662306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	if (!hw->eint)
52962306a36Sopenharmony_ci		return -ENOTSUPP;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (desc->eint.eint_n == (u16)EINT_NA)
53462306a36Sopenharmony_ci		return -ENOTSUPP;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	return mtk_eint_find_irq(hw->eint, desc->eint.eint_n);
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cistatic int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
54062306a36Sopenharmony_ci			       unsigned long config)
54162306a36Sopenharmony_ci{
54262306a36Sopenharmony_ci	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
54362306a36Sopenharmony_ci	const struct mtk_pin_desc *desc;
54462306a36Sopenharmony_ci	u32 debounce;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
54762306a36Sopenharmony_ci	if (!desc->name)
54862306a36Sopenharmony_ci		return -ENOTSUPP;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	if (!hw->eint ||
55162306a36Sopenharmony_ci	    pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE ||
55262306a36Sopenharmony_ci	    desc->eint.eint_n == (u16)EINT_NA)
55362306a36Sopenharmony_ci		return -ENOTSUPP;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	debounce = pinconf_to_config_argument(config);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce);
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_cistatic int mtk_build_gpiochip(struct mtk_pinctrl *hw)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	struct gpio_chip *chip = &hw->chip;
56362306a36Sopenharmony_ci	int ret;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	chip->label		= PINCTRL_PINCTRL_DEV;
56662306a36Sopenharmony_ci	chip->parent		= hw->dev;
56762306a36Sopenharmony_ci	chip->request		= gpiochip_generic_request;
56862306a36Sopenharmony_ci	chip->free		= gpiochip_generic_free;
56962306a36Sopenharmony_ci	chip->direction_input	= mtk_gpio_direction_input;
57062306a36Sopenharmony_ci	chip->direction_output	= mtk_gpio_direction_output;
57162306a36Sopenharmony_ci	chip->get		= mtk_gpio_get;
57262306a36Sopenharmony_ci	chip->set		= mtk_gpio_set;
57362306a36Sopenharmony_ci	chip->to_irq		= mtk_gpio_to_irq;
57462306a36Sopenharmony_ci	chip->set_config	= mtk_gpio_set_config;
57562306a36Sopenharmony_ci	chip->base		= -1;
57662306a36Sopenharmony_ci	chip->ngpio		= hw->soc->npins;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	ret = gpiochip_add_data(chip, hw);
57962306a36Sopenharmony_ci	if (ret < 0)
58062306a36Sopenharmony_ci		return ret;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	/* Just for backward compatible for these old pinctrl nodes without
58362306a36Sopenharmony_ci	 * "gpio-ranges" property. Otherwise, called directly from a
58462306a36Sopenharmony_ci	 * DeviceTree-supported pinctrl driver is DEPRECATED.
58562306a36Sopenharmony_ci	 * Please see Section 2.1 of
58662306a36Sopenharmony_ci	 * Documentation/devicetree/bindings/gpio/gpio.txt on how to
58762306a36Sopenharmony_ci	 * bind pinctrl and gpio drivers via the "gpio-ranges" property.
58862306a36Sopenharmony_ci	 */
58962306a36Sopenharmony_ci	if (!of_property_present(hw->dev->of_node, "gpio-ranges")) {
59062306a36Sopenharmony_ci		ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
59162306a36Sopenharmony_ci					     chip->ngpio);
59262306a36Sopenharmony_ci		if (ret < 0) {
59362306a36Sopenharmony_ci			gpiochip_remove(chip);
59462306a36Sopenharmony_ci			return ret;
59562306a36Sopenharmony_ci		}
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	return 0;
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_cistatic int mtk_build_groups(struct mtk_pinctrl *hw)
60262306a36Sopenharmony_ci{
60362306a36Sopenharmony_ci	int err, i;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	for (i = 0; i < hw->soc->ngrps; i++) {
60662306a36Sopenharmony_ci		const struct group_desc *group = hw->soc->grps + i;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		err = pinctrl_generic_add_group(hw->pctrl, group->name,
60962306a36Sopenharmony_ci						group->pins, group->num_pins,
61062306a36Sopenharmony_ci						group->data);
61162306a36Sopenharmony_ci		if (err < 0) {
61262306a36Sopenharmony_ci			dev_err(hw->dev, "Failed to register group %s\n",
61362306a36Sopenharmony_ci				group->name);
61462306a36Sopenharmony_ci			return err;
61562306a36Sopenharmony_ci		}
61662306a36Sopenharmony_ci	}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	return 0;
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_cistatic int mtk_build_functions(struct mtk_pinctrl *hw)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	int i, err;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	for (i = 0; i < hw->soc->nfuncs ; i++) {
62662306a36Sopenharmony_ci		const struct function_desc *func = hw->soc->funcs + i;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci		err = pinmux_generic_add_function(hw->pctrl, func->name,
62962306a36Sopenharmony_ci						  func->group_names,
63062306a36Sopenharmony_ci						  func->num_group_names,
63162306a36Sopenharmony_ci						  func->data);
63262306a36Sopenharmony_ci		if (err < 0) {
63362306a36Sopenharmony_ci			dev_err(hw->dev, "Failed to register function %s\n",
63462306a36Sopenharmony_ci				func->name);
63562306a36Sopenharmony_ci			return err;
63662306a36Sopenharmony_ci		}
63762306a36Sopenharmony_ci	}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	return 0;
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ciint mtk_moore_pinctrl_probe(struct platform_device *pdev,
64362306a36Sopenharmony_ci			    const struct mtk_pin_soc *soc)
64462306a36Sopenharmony_ci{
64562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
64662306a36Sopenharmony_ci	struct pinctrl_pin_desc *pins;
64762306a36Sopenharmony_ci	struct mtk_pinctrl *hw;
64862306a36Sopenharmony_ci	int err, i;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
65162306a36Sopenharmony_ci	if (!hw)
65262306a36Sopenharmony_ci		return -ENOMEM;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	hw->soc = soc;
65562306a36Sopenharmony_ci	hw->dev = &pdev->dev;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	if (!hw->soc->nbase_names)
65862306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
65962306a36Sopenharmony_ci			"SoC should be assigned at least one register base\n");
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
66262306a36Sopenharmony_ci				      sizeof(*hw->base), GFP_KERNEL);
66362306a36Sopenharmony_ci	if (!hw->base)
66462306a36Sopenharmony_ci		return -ENOMEM;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	for (i = 0; i < hw->soc->nbase_names; i++) {
66762306a36Sopenharmony_ci		hw->base[i] = devm_platform_ioremap_resource_byname(pdev,
66862306a36Sopenharmony_ci						hw->soc->base_names[i]);
66962306a36Sopenharmony_ci		if (IS_ERR(hw->base[i]))
67062306a36Sopenharmony_ci			return PTR_ERR(hw->base[i]);
67162306a36Sopenharmony_ci	}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	hw->nbase = hw->soc->nbase_names;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	spin_lock_init(&hw->lock);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	/* Copy from internal struct mtk_pin_desc to register to the core */
67862306a36Sopenharmony_ci	pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
67962306a36Sopenharmony_ci				  GFP_KERNEL);
68062306a36Sopenharmony_ci	if (!pins)
68162306a36Sopenharmony_ci		return -ENOMEM;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	for (i = 0; i < hw->soc->npins; i++) {
68462306a36Sopenharmony_ci		pins[i].number = hw->soc->pins[i].number;
68562306a36Sopenharmony_ci		pins[i].name = hw->soc->pins[i].name;
68662306a36Sopenharmony_ci	}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	/* Setup pins descriptions per SoC types */
68962306a36Sopenharmony_ci	mtk_desc.pins = (const struct pinctrl_pin_desc *)pins;
69062306a36Sopenharmony_ci	mtk_desc.npins = hw->soc->npins;
69162306a36Sopenharmony_ci	mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
69262306a36Sopenharmony_ci	mtk_desc.custom_params = mtk_custom_bindings;
69362306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
69462306a36Sopenharmony_ci	mtk_desc.custom_conf_items = mtk_conf_items;
69562306a36Sopenharmony_ci#endif
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw,
69862306a36Sopenharmony_ci					     &hw->pctrl);
69962306a36Sopenharmony_ci	if (err)
70062306a36Sopenharmony_ci		return err;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	/* Setup groups descriptions per SoC types */
70362306a36Sopenharmony_ci	err = mtk_build_groups(hw);
70462306a36Sopenharmony_ci	if (err)
70562306a36Sopenharmony_ci		return dev_err_probe(dev, err, "Failed to build groups\n");
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	/* Setup functions descriptions per SoC types */
70862306a36Sopenharmony_ci	err = mtk_build_functions(hw);
70962306a36Sopenharmony_ci	if (err)
71062306a36Sopenharmony_ci		return dev_err_probe(dev, err, "Failed to build functions\n");
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	/* For able to make pinctrl_claim_hogs, we must not enable pinctrl
71362306a36Sopenharmony_ci	 * until all groups and functions are being added one.
71462306a36Sopenharmony_ci	 */
71562306a36Sopenharmony_ci	err = pinctrl_enable(hw->pctrl);
71662306a36Sopenharmony_ci	if (err)
71762306a36Sopenharmony_ci		return err;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	err = mtk_build_eint(hw, pdev);
72062306a36Sopenharmony_ci	if (err)
72162306a36Sopenharmony_ci		dev_warn(&pdev->dev,
72262306a36Sopenharmony_ci			 "Failed to add EINT, but pinctrl still can work\n");
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	/* Build gpiochip should be after pinctrl_enable is done */
72562306a36Sopenharmony_ci	err = mtk_build_gpiochip(hw);
72662306a36Sopenharmony_ci	if (err)
72762306a36Sopenharmony_ci		return dev_err_probe(dev, err, "Failed to add gpio_chip\n");
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	platform_set_drvdata(pdev, hw);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	return 0;
73262306a36Sopenharmony_ci}
733