[][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,