[][kernel][pinctrl][Backport pinconf setting combo mode]

[Description]
Add backport pinconf setting combo mode in pinctrl-moore.c
1. In order to use standard dts pinconf setting properties,
we have to backport bias_set_combo/bias_get_combo apis from linux
v6.4 and add pull_type for each pins in pinctrl-mt798x.c

[Release-log]
NA.


Change-Id: I96692e1006cc29697abe4db57b2902605af33379
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7847369
diff --git a/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7981.c
index 2e91034..4f0f145 100644
--- a/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7981.c
+++ b/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7981.c
@@ -436,6 +436,39 @@
 	PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1),
 };
 
+static const unsigned int mt7981_pull_type[] = {
+	MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/
+	MTK_PULL_PU_PD_TYPE,/*40*/ MTK_PULL_PU_PD_TYPE,/*41*/
+	MTK_PULL_PU_PD_TYPE,/*42*/ MTK_PULL_PU_PD_TYPE,/*43*/
+	MTK_PULL_PU_PD_TYPE,/*44*/ MTK_PULL_PU_PD_TYPE,/*45*/
+	MTK_PULL_PU_PD_TYPE,/*46*/ MTK_PULL_PU_PD_TYPE,/*47*/
+	MTK_PULL_PU_PD_TYPE,/*48*/ MTK_PULL_PU_PD_TYPE,/*49*/
+	MTK_PULL_PU_PD_TYPE,/*50*/ MTK_PULL_PU_PD_TYPE,/*51*/
+	MTK_PULL_PU_PD_TYPE,/*52*/ MTK_PULL_PU_PD_TYPE,/*53*/
+	MTK_PULL_PU_PD_TYPE,/*54*/ MTK_PULL_PU_PD_TYPE,/*55*/
+	MTK_PULL_PU_PD_TYPE,/*56*/
+};
+
+
 static const struct mtk_pin_reg_calc mt7981_reg_cals[] = {
 	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range),
 	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range),
@@ -964,6 +997,9 @@
 	.bias_disable_get = mtk_pinconf_bias_disable_get,
 	.bias_set = mtk_pinconf_bias_set,
 	.bias_get = mtk_pinconf_bias_get,
+	.pull_type = mt7981_pull_type,
+	.bias_set_combo = mtk_pinconf_bias_set_combo,
+	.bias_get_combo = mtk_pinconf_bias_get_combo,
 	.drive_set = mtk_pinconf_drive_set_rev1,
 	.drive_get = mtk_pinconf_drive_get_rev1,
 	.adv_pull_get = mtk_pinconf_adv_pull_get,
diff --git a/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7986.c
index b0f4c95..215642a 100644
--- a/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7986.c
+++ b/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7986.c
@@ -633,6 +633,60 @@
 	PIN_FIELD_BASE(68, 68, 4, 0x60, 0x10, 4, 1),
 };
 
+static const unsigned int mt7986_pull_type[] = {
+	MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/
+	MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/
+	MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/
+	MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/
+	MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/
+	MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/
+	MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/
+	MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/
+	MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/
+	MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/
+	MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/
+	MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/
+	MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/
+	MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/
+	MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/
+	MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/
+	MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/
+	MTK_PULL_PU_PD_TYPE,/*100*/
+};
+
 static const struct mtk_pin_reg_calc mt7986_reg_cals[] = {
 	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range),
 	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range),
@@ -1065,6 +1119,9 @@
 	.bias_disable_get = mtk_pinconf_bias_disable_get,
 	.bias_set = mtk_pinconf_bias_set,
 	.bias_get = mtk_pinconf_bias_get,
+	.pull_type = mt7986_pull_type,
+	.bias_set_combo = mtk_pinconf_bias_set_combo,
+	.bias_get_combo = mtk_pinconf_bias_get_combo,
 	.drive_set = mtk_pinconf_drive_set_rev1,
 	.drive_get = mtk_pinconf_drive_get_rev1,
 	.adv_pull_get = mtk_pinconf_adv_pull_get,
diff --git a/target/linux/mediatek/patches-5.4/999-1000-backport-pinctrl-pinconf-setting-combo.patch b/target/linux/mediatek/patches-5.4/999-1000-backport-pinctrl-pinconf-setting-combo.patch
new file mode 100644
index 0000000..43ca0c5
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/999-1000-backport-pinctrl-pinconf-setting-combo.patch
@@ -0,0 +1,632 @@
+--- a/drivers/pinctrl/mediatek/pinctrl-moore.c
++++ b/drivers/pinctrl/mediatek/pinctrl-moore.c
+@@ -99,14 +99,22 @@ static int mtk_pinconf_get(struct pinctr
+ {
+ 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ 	u32 param = pinconf_to_config_param(*config);
+-	int val, val2, err, reg, ret = 1;
++	int val, val2, err, pullup, reg, ret = 1;
+ 	const struct mtk_pin_desc *desc;
+ 
+ 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
++	if (!desc->name)
++		return -ENOTSUPP;
+ 
+ 	switch (param) {
+ 	case PIN_CONFIG_BIAS_DISABLE:
+-		if (hw->soc->bias_disable_get) {
++		if (hw->soc->bias_get_combo) {
++			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
++			if (err)
++				return err;
++			if (ret != MTK_PUPD_SET_R1R0_00 && ret != MTK_DISABLE)
++				return -EINVAL;
++		} else if (hw->soc->bias_disable_get) {
+ 			err = hw->soc->bias_disable_get(hw, desc, &ret);
+ 			if (err)
+ 				return err;
+@@ -115,7 +123,15 @@ static int mtk_pinconf_get(struct pinctr
+ 		}
+ 		break;
+ 	case PIN_CONFIG_BIAS_PULL_UP:
+-		if (hw->soc->bias_get) {
++		if (hw->soc->bias_get_combo) {
++			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
++			if (err)
++				return err;
++			if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE)
++				return -EINVAL;
++			if (!pullup)
++				return -EINVAL;
++		} else if (hw->soc->bias_get) {
+ 			err = hw->soc->bias_get(hw, desc, 1, &ret);
+ 			if (err)
+ 				return err;
+@@ -124,7 +140,15 @@ static int mtk_pinconf_get(struct pinctr
+ 		}
+ 		break;
+ 	case PIN_CONFIG_BIAS_PULL_DOWN:
+-		if (hw->soc->bias_get) {
++		if (hw->soc->bias_get_combo) {
++			err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
++			if (err)
++				return err;
++			if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE)
++				return -EINVAL;
++			if (pullup)
++				return -EINVAL;
++		} else if (hw->soc->bias_get) {
+ 			err = hw->soc->bias_get(hw, desc, 0, &ret);
+ 			if (err)
+ 				return err;
+@@ -218,14 +242,19 @@ static int mtk_pinconf_set(struct pinctr
+ 	int cfg, err = 0;
+ 
+ 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
++	if (!desc->name)
++		return -ENOTSUPP;
+ 
+ 	for (cfg = 0; cfg < num_configs; cfg++) {
+ 		param = pinconf_to_config_param(configs[cfg]);
+ 		arg = pinconf_to_config_argument(configs[cfg]);
+-
+ 		switch (param) {
+ 		case PIN_CONFIG_BIAS_DISABLE:
+-			if (hw->soc->bias_disable_set) {
++			if (hw->soc->bias_set_combo) {
++				err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE);
++				if (err)
++					return err;
++			} else if (hw->soc->bias_disable_set) {
+ 				err = hw->soc->bias_disable_set(hw, desc);
+ 				if (err)
+ 					return err;
+@@ -234,7 +263,11 @@ static int mtk_pinconf_set(struct pinctr
+ 			}
+ 			break;
+ 		case PIN_CONFIG_BIAS_PULL_UP:
+-			if (hw->soc->bias_set) {
++			if (hw->soc->bias_set_combo) {
++				err = hw->soc->bias_set_combo(hw, desc, 1, arg);
++				if (err)
++					return err;
++			} else if (hw->soc->bias_set) {
+ 				err = hw->soc->bias_set(hw, desc, 1);
+ 				if (err)
+ 					return err;
+@@ -243,7 +276,11 @@ static int mtk_pinconf_set(struct pinctr
+ 			}
+ 			break;
+ 		case PIN_CONFIG_BIAS_PULL_DOWN:
+-			if (hw->soc->bias_set) {
++			if (hw->soc->bias_set_combo) {
++				err = hw->soc->bias_set_combo(hw, desc, 0, arg);
++				if (err)
++					return err;
++			} else if (hw->soc->bias_set) {
+ 				err = hw->soc->bias_set(hw, desc, 0);
+ 				if (err)
+ 					return err;
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+@@ -506,6 +506,404 @@ int mtk_pinconf_bias_get_rev1(struct mtk
+ 	return 0;
+ }
+ 
++/* Combo for the following pull register type:
++ * 1. PU + PD
++ * 2. PULLSEL + PULLEN
++ * 3. PUPD + R0 + R1
++ */
++static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 pullup, u32 arg)
++{
++	int err, pu, pd;
++
++	if (arg == MTK_DISABLE) {
++		pu = 0;
++		pd = 0;
++	} else if ((arg == MTK_ENABLE) && pullup) {
++		pu = 1;
++		pd = 0;
++	} else if ((arg == MTK_ENABLE) && !pullup) {
++		pu = 0;
++		pd = 1;
++	} else {
++		err = -EINVAL;
++		goto out;
++	}
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu);
++	if (err)
++		goto out;
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd);
++
++out:
++	return err;
++}
++
++static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 pullup, u32 arg)
++{
++	int err, enable;
++
++	if (arg == MTK_DISABLE)
++		enable = 0;
++	else if (arg == MTK_ENABLE)
++		enable = 1;
++	else {
++		err = -EINVAL;
++		goto out;
++	}
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
++	if (err)
++		goto out;
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
++
++out:
++	return err;
++}
++
++static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 pullup, u32 arg)
++{
++	int err, r0, r1;
++
++	if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) {
++		pullup = 0;
++		r0 = 0;
++		r1 = 0;
++	} else if (arg == MTK_PUPD_SET_R1R0_01) {
++		r0 = 1;
++		r1 = 0;
++	} else if (arg == MTK_PUPD_SET_R1R0_10) {
++		r0 = 0;
++		r1 = 1;
++	} else if (arg == MTK_PUPD_SET_R1R0_11) {
++		r0 = 1;
++		r1 = 1;
++	} else {
++		err = -EINVAL;
++		goto out;
++	}
++
++	/* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup);
++	if (err)
++		goto out;
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0);
++	if (err)
++		goto out;
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1);
++
++out:
++	return err;
++}
++
++static int mtk_hw_pin_rsel_lookup(struct mtk_pinctrl *hw,
++				  const struct mtk_pin_desc *desc,
++				  u32 pullup, u32 arg, u32 *rsel_val)
++{
++	const struct mtk_pin_rsel *rsel;
++	int check;
++	bool found = false;
++
++	rsel = hw->soc->pin_rsel;
++
++	for (check = 0; check <= hw->soc->npin_rsel - 1; check++) {
++		if (desc->number >= rsel[check].s_pin &&
++		    desc->number <= rsel[check].e_pin) {
++			if (pullup) {
++				if (rsel[check].up_rsel == arg) {
++					found = true;
++					*rsel_val = rsel[check].rsel_index;
++					break;
++				}
++			} else {
++				if (rsel[check].down_rsel == arg) {
++					found = true;
++					*rsel_val = rsel[check].rsel_index;
++					break;
++				}
++			}
++		}
++	}
++
++	if (!found) {
++		dev_err(hw->dev, "Not support rsel value %d Ohm for pin = %d (%s)\n",
++			arg, desc->number, desc->name);
++		return -ENOTSUPP;
++	}
++
++	return 0;
++}
++
++static int mtk_pinconf_bias_set_rsel(struct mtk_pinctrl *hw,
++				     const struct mtk_pin_desc *desc,
++				     u32 pullup, u32 arg)
++{
++	int err, rsel_val;
++
++	if (!pullup && arg == MTK_DISABLE)
++		return 0;
++
++	if (hw->rsel_si_unit) {
++		/* find pin rsel_index from pin_rsel array*/
++		err = mtk_hw_pin_rsel_lookup(hw, desc, pullup, arg, &rsel_val);
++		if (err)
++			goto out;
++	} else {
++		if (arg < MTK_PULL_SET_RSEL_000 ||
++		    arg > MTK_PULL_SET_RSEL_111) {
++			err = -EINVAL;
++			goto out;
++		}
++
++		rsel_val = arg - MTK_PULL_SET_RSEL_000;
++	}
++
++	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_RSEL, rsel_val);
++	if (err)
++		goto out;
++
++	err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, MTK_ENABLE);
++
++out:
++	return err;
++}
++
++int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
++			       const struct mtk_pin_desc *desc,
++			       u32 pullup, u32 arg)
++{
++	int err = -ENOTSUPP;
++	u32 try_all_type;
++
++	if (hw->soc->pull_type)
++		try_all_type = hw->soc->pull_type[desc->number];
++	else
++		try_all_type = MTK_PULL_TYPE_MASK;
++
++	if (try_all_type & MTK_PULL_RSEL_TYPE) {
++		err = mtk_pinconf_bias_set_rsel(hw, desc, pullup, arg);
++		if (!err)
++			return err;
++	}
++
++	if (try_all_type & MTK_PULL_PU_PD_TYPE) {
++		err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg);
++		if (!err)
++			return err;
++	}
++
++	if (try_all_type & MTK_PULL_PULLSEL_TYPE) {
++		err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc,
++							  pullup, arg);
++		if (!err)
++			return err;
++	}
++
++	if (try_all_type & MTK_PULL_PUPD_R1R0_TYPE)
++		err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg);
++
++	if (err)
++		dev_err(hw->dev, "Invalid pull argument\n");
++
++	return err;
++}
++EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set_combo);
++
++static int mtk_rsel_get_si_unit(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 pullup, u32 rsel_val, u32 *si_unit)
++{
++	const struct mtk_pin_rsel *rsel;
++	int check;
++
++	rsel = hw->soc->pin_rsel;
++
++	for (check = 0; check <= hw->soc->npin_rsel - 1; check++) {
++		if (desc->number >= rsel[check].s_pin &&
++		    desc->number <= rsel[check].e_pin) {
++			if (rsel_val == rsel[check].rsel_index) {
++				if (pullup)
++					*si_unit = rsel[check].up_rsel;
++				else
++					*si_unit = rsel[check].down_rsel;
++				break;
++			}
++		}
++	}
++
++	return 0;
++}
++
++static int mtk_pinconf_bias_get_rsel(struct mtk_pinctrl *hw,
++				     const struct mtk_pin_desc *desc,
++				     u32 *pullup, u32 *enable)
++{
++	int pu, pd, rsel, err;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_RSEL, &rsel);
++	if (err)
++		goto out;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu);
++	if (err)
++		goto out;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd);
++	if (err)
++		goto out;
++
++	if (pu == 0 && pd == 0) {
++		*pullup = 0;
++		*enable = MTK_DISABLE;
++	} else if (pu == 1 && pd == 0) {
++		*pullup = 1;
++		if (hw->rsel_si_unit)
++			mtk_rsel_get_si_unit(hw, desc, *pullup, rsel, enable);
++		else
++			*enable = rsel + MTK_PULL_SET_RSEL_000;
++	} else if (pu == 0 && pd == 1) {
++		*pullup = 0;
++		if (hw->rsel_si_unit)
++			mtk_rsel_get_si_unit(hw, desc, *pullup, rsel, enable);
++		else
++			*enable = rsel + MTK_PULL_SET_RSEL_000;
++	} else {
++		err = -EINVAL;
++		goto out;
++	}
++
++out:
++	return err;
++}
++
++static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 *pullup, u32 *enable)
++{
++	int err, pu, pd;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu);
++	if (err)
++		goto out;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd);
++	if (err)
++		goto out;
++
++	if (pu == 0 && pd == 0) {
++		*pullup = 0;
++		*enable = MTK_DISABLE;
++	} else if (pu == 1 && pd == 0) {
++		*pullup = 1;
++		*enable = MTK_ENABLE;
++	} else if (pu == 0 && pd == 1) {
++		*pullup = 0;
++		*enable = MTK_ENABLE;
++	} else
++		err = -EINVAL;
++
++out:
++	return err;
++}
++
++static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 *pullup, u32 *enable)
++{
++	int err;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
++	if (err)
++		goto out;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
++
++out:
++	return err;
++}
++
++static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw,
++				const struct mtk_pin_desc *desc,
++				u32 *pullup, u32 *enable)
++{
++	int err, r0, r1;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup);
++	if (err)
++		goto out;
++	/* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
++	*pullup = !(*pullup);
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0);
++	if (err)
++		goto out;
++
++	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1);
++	if (err)
++		goto out;
++
++	if ((r1 == 0) && (r0 == 0))
++		*enable = MTK_PUPD_SET_R1R0_00;
++	else if ((r1 == 0) && (r0 == 1))
++		*enable = MTK_PUPD_SET_R1R0_01;
++	else if ((r1 == 1) && (r0 == 0))
++		*enable = MTK_PUPD_SET_R1R0_10;
++	else if ((r1 == 1) && (r0 == 1))
++		*enable = MTK_PUPD_SET_R1R0_11;
++	else
++		err = -EINVAL;
++
++out:
++	return err;
++}
++
++int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
++			      const struct mtk_pin_desc *desc,
++			      u32 *pullup, u32 *enable)
++{
++	int err = -ENOTSUPP;
++	u32 try_all_type;
++
++	if (hw->soc->pull_type)
++		try_all_type = hw->soc->pull_type[desc->number];
++	else
++		try_all_type = MTK_PULL_TYPE_MASK;
++
++	if (try_all_type & MTK_PULL_RSEL_TYPE) {
++		err = mtk_pinconf_bias_get_rsel(hw, desc, pullup, enable);
++		if (!err)
++			return err;
++	}
++
++	if (try_all_type & MTK_PULL_PU_PD_TYPE) {
++		err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable);
++		if (!err)
++			return err;
++	}
++
++	if (try_all_type & MTK_PULL_PULLSEL_TYPE) {
++		err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc,
++							  pullup, enable);
++		if (!err)
++			return err;
++	}
++
++	if (try_all_type & MTK_PULL_PUPD_R1R0_TYPE)
++		err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable);
++
++	return err;
++}
++EXPORT_SYMBOL_GPL(mtk_pinconf_bias_get_combo);
++
+ /* Revision 0 */
+ int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
+ 			  const struct mtk_pin_desc *desc, u32 arg)
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
+@@ -17,6 +17,34 @@
+ #define MTK_ENABLE     1
+ #define MTK_PULLDOWN   0
+ #define MTK_PULLUP     1
++#define MTK_PULL_PU_PD_TYPE		BIT(0)
++#define MTK_PULL_PULLSEL_TYPE		BIT(1)
++#define MTK_PULL_PUPD_R1R0_TYPE 	BIT(2)
++/* MTK_PULL_RSEL_TYPE can select resistance and can be
++ * turned on/off itself. But it can't be selected pull up/down
++ */
++#define MTK_PULL_RSEL_TYPE		BIT(3)
++/* MTK_PULL_PU_PD_RSEL_TYPE is a type which is controlled by
++ * MTK_PULL_PU_PD_TYPE and MTK_PULL_RSEL_TYPE.
++ */
++#define MTK_PULL_PU_PD_RSEL_TYPE	(MTK_PULL_PU_PD_TYPE \
++					| MTK_PULL_RSEL_TYPE)
++#define MTK_PULL_TYPE_MASK	(MTK_PULL_PU_PD_TYPE |\
++				 MTK_PULL_PULLSEL_TYPE |\
++				 MTK_PULL_PUPD_R1R0_TYPE |\
++				 MTK_PULL_RSEL_TYPE)
++#define MTK_PUPD_SET_R1R0_00 100
++#define MTK_PUPD_SET_R1R0_01 101
++#define MTK_PUPD_SET_R1R0_10 102
++#define MTK_PUPD_SET_R1R0_11 103
++#define MTK_PULL_SET_RSEL_000  200
++#define MTK_PULL_SET_RSEL_001  201
++#define MTK_PULL_SET_RSEL_010  202
++#define MTK_PULL_SET_RSEL_011  203
++#define MTK_PULL_SET_RSEL_100  204
++#define MTK_PULL_SET_RSEL_101  205
++#define MTK_PULL_SET_RSEL_110  206
++#define MTK_PULL_SET_RSEL_111  207
+ 
+ #define EINT_NA	U16_MAX
+ #define NO_EINT_SUPPORT	EINT_NA
+@@ -66,6 +94,8 @@ enum {
+ 	PINCTRL_PIN_REG_DRV_EN,
+ 	PINCTRL_PIN_REG_DRV_E0,
+ 	PINCTRL_PIN_REG_DRV_E1,
++	PINCTRL_PIN_REG_DRV_ADV,
++	PINCTRL_PIN_REG_RSEL,
+ 	PINCTRL_PIN_REG_MAX,
+ };
+ 
+@@ -101,6 +131,22 @@ struct mtk_pin_field {
+ 	u8  next;
+ };
+ 
++/**
++ * struct mtk_pin_rsel - the structure that provides bias resistance selection.
++ * @s_pin:		the start pin within the rsel range
++ * @e_pin:		the end pin within the rsel range
++ * @rsel_index:	the rsel bias resistance index
++ * @up_rsel:	the pullup rsel bias resistance value
++ * @down_rsel:	the pulldown rsel bias resistance value
++ */
++struct mtk_pin_rsel {
++	u16 s_pin;
++	u16 e_pin;
++	u16 rsel_index;
++	u32 up_rsel;
++	u32 down_rsel;
++};
++
+ /* struct mtk_pin_field_calc - the structure that holds the range providing
+  *			       the guide used to look up the relevant field
+  * @s_pin:		the start pin within the range
+@@ -205,6 +251,9 @@ struct mtk_pin_soc {
+ 	bool				ies_present;
+ 	const char * const		*base_names;
+ 	unsigned int			nbase_names;
++    	const unsigned int		*pull_type;
++	const struct mtk_pin_rsel	*pin_rsel;
++	unsigned int			npin_rsel;
+ 
+ 	/* Specific pinconfig operations */
+ 	int (*bias_disable_set)(struct mtk_pinctrl *hw,
+@@ -215,7 +264,10 @@ struct mtk_pin_soc {
+ 			const struct mtk_pin_desc *desc, bool pullup);
+ 	int (*bias_get)(struct mtk_pinctrl *hw,
+ 			const struct mtk_pin_desc *desc, bool pullup, int *res);
+-
++	int (*bias_set_combo)(struct mtk_pinctrl *hw,
++			      const struct mtk_pin_desc *desc, u32 pullup, u32 arg);
++	int (*bias_get_combo)(struct mtk_pinctrl *hw,
++			      const struct mtk_pin_desc *desc, u32 *pullup, u32 *arg);
+ 	int (*drive_set)(struct mtk_pinctrl *hw,
+ 			 const struct mtk_pin_desc *desc, u32 arg);
+ 	int (*drive_get)(struct mtk_pinctrl *hw,
+@@ -246,6 +298,10 @@ struct mtk_pinctrl {
+ 	struct mtk_eint			*eint;
+ 	struct mtk_pinctrl_group	*groups;
+ 	const char          **grp_names;
++	/* lock pin's register resource to avoid multiple threads issue*/
++	spinlock_t lock;
++	/* identify rsel setting by si unit or rsel define in dts node */
++	bool rsel_si_unit;
+ };
+ 
+ void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set);
+@@ -282,7 +338,12 @@ int mtk_pinconf_drive_set(struct mtk_pin
+ 			  const struct mtk_pin_desc *desc, u32 arg);
+ int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
+ 			  const struct mtk_pin_desc *desc, int *val);
+-
++int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
++			       const struct mtk_pin_desc *desc,
++			       u32 pullup, u32 enable);
++int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
++			       const struct mtk_pin_desc *desc,
++			       u32 *pullup, u32 *enable);
+ int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
+ 			       const struct mtk_pin_desc *desc, u32 arg);
+ int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,