[PATCH 2/4] pinctrl: mediatek: Add support for eh bit
From: Igor Belwon <hidden>
Date: 2025-09-08 19:18:41
Also in:
linux-devicetree, linux-gpio, linux-mediatek, lkml
Subsystem:
pin control subsystem, pin controller - mediatek, the rest · Maintainers:
Linus Walleij, Sean Wang, Linus Torvalds
The eh bit is used for setting drive mode for i2c pins on recent SoCs. Add support for it. Signed-off-by: Igor Belwon <redacted> --- drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 60 ++++++++++++++++++++++++ drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 24 ++++++++++ drivers/pinctrl/mediatek/pinctrl-paris.c | 30 +++++++++--- 3 files changed, 108 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 4918d38abfc29de1f27ee75bc6a51c32b3ca1ac5..51fbdbdf61c901bb7ee43405d36f2c1602b3616f 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c@@ -249,6 +249,58 @@ static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n) return EINT_NA; } +/* + * The eh register determines the selection of the driving control + * for i2c pins. + * eh = 0: Non-i2c mode. + * eh = 1: i2c mode. + */ +int mtk_eh_ctrl(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, + u16 mode) +{ + const struct mtk_eh_pin_pinmux *p = hw->soc->eh_pin_pinmux; + u32 eh_info_num = hw->soc->neh_pins; + u32 val = 0, on = 0, found = 0, i = 0; + int err; + + while (i < eh_info_num) { + if (desc->number == p[i].pin) { + found = 1; + if (mode == p[i].pinmux) { + on = 1; + break; + } + } + /* + * It is possible that one pin may have more than one pinmux + * that shall enable eh. + * Besides, we assume that hw->soc->eh_pin_pinmux is sorted + * according to field 'pin'. + * So when desc->number < p->pin, it mean no match will be + * found and we can leave. + */ + if (desc->number < p[i].pin) + break; + + i++; + } + + if (!found) + return 0; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_EH, &val); + if (err) + return err; + + if (on) + val |= on; + else + val &= MTK_EH_ENABLE_MASK; + + return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_EH, val); +} +EXPORT_SYMBOL_GPL(mtk_eh_ctrl); + /* * Virtual GPIO only used inside SOC and not being exported to outside SOC. * Some modules use virtual GPIO as eint (e.g. pmif or usb).
@@ -1231,6 +1283,10 @@ int mtk_pinconf_adv_drive_set(struct mtk_pinctrl *hw, int e0 = !!(arg & 2); int e1 = !!(arg & 4); + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_EH, arg); + if (!err) + return 0; + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_EN, en); if (err) return err;
@@ -1256,6 +1312,10 @@ int mtk_pinconf_adv_drive_get(struct mtk_pinctrl *hw, u32 en, e0, e1; int err; + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_EH, val); + if (!err) + return 0; + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_EN, &en); if (err) return err;
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
index fa7c0ed49346486ba32ec615aa2b3483217f5077..a2ff8ae5ba43e5be87c8b478c07d9d4640c2e8ec 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h@@ -35,6 +35,8 @@ MTK_PULL_PUPD_R1R0_TYPE |\ MTK_PULL_RSEL_TYPE) +#define MTK_EH_ENABLE_MASK 0xfffffffe + #define EINT_NA U16_MAX #define NO_EINT_SUPPORT EINT_NA
@@ -67,6 +69,11 @@ .down_rsel = _down_rsel, \ } +#define PIN_MUX_EH(_pin, _pinmux) { \ + .pin = _pin, \ + .pinmux = _pinmux, \ + } + /* List these attributes which could be modified for the pin */ enum { PINCTRL_PIN_REG_MODE,
@@ -88,6 +95,7 @@ enum { PINCTRL_PIN_REG_IES, PINCTRL_PIN_REG_PULLEN, PINCTRL_PIN_REG_PULLSEL, + PINCTRL_PIN_REG_DRV_EH, PINCTRL_PIN_REG_DRV_EN, PINCTRL_PIN_REG_DRV_E0, PINCTRL_PIN_REG_DRV_E1,
@@ -204,6 +212,17 @@ struct mtk_eint_desc { u16 eint_n; }; +/** + * struct mtk_eh_pin_pinmux - entry recording (pin, pinmux) whose + * eh can be enabled + * @pin: pin number + * @pinmux: pinmux number + */ +struct mtk_eh_pin_pinmux { + u16 pin; + u16 pinmux; +}; + /** * struct mtk_pin_desc - the structure that providing information * for each pin of chips
@@ -252,6 +271,8 @@ struct mtk_pin_soc { const unsigned int *pull_type; const struct mtk_pin_rsel *pin_rsel; unsigned int npin_rsel; + const struct mtk_eh_pin_pinmux *eh_pin_pinmux; + unsigned int neh_pins; /* Specific pinconfig operations */ int (*bias_disable_set)(struct mtk_pinctrl *hw,
@@ -311,6 +332,9 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, int field, int *value); +int mtk_eh_ctrl(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, + u16 mode); + int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev); int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw,
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index 3e714554789d0e7e31ecce92388f53b906bdf122..f87447d6f879a3f7b57db44ed97cc91f8e93b425 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c@@ -104,13 +104,21 @@ static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned int pin) { + int err; struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); const struct mtk_pin_desc *desc; desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; - return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, - hw->soc->gpio_m); + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, + hw->soc->gpio_m); + if (err) + return err; + + if (hw->soc->eh_pin_pinmux) + err = mtk_eh_ctrl(hw, desc, hw->soc->gpio_m); + + return err; } static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
@@ -749,10 +757,10 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev, struct mtk_pinctrl_group *grp = hw->groups + group; const struct mtk_func_desc *desc_func; const struct mtk_pin_desc *desc; - bool ret; + int err; - ret = mtk_pctrl_is_function_valid(hw, grp->pin, function); - if (!ret) { + err = mtk_pctrl_is_function_valid(hw, grp->pin, function); + if (!err) { dev_err(hw->dev, "invalid function %d on group %d .\n", function, group); return -EINVAL;
@@ -763,7 +771,17 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev, return -EINVAL; desc = (const struct mtk_pin_desc *)&hw->soc->pins[grp->pin]; - return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, desc_func->muxval); + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, + desc_func->muxval); + + if (!err) + return err; + + if (hw->soc->eh_pin_pinmux) + err = mtk_eh_ctrl(hw, desc, desc_func->muxval); + + return err; } static const struct pinmux_ops mtk_pmxops = {
--
2.51.0