[PATCH v13 4/5] pinctrl: mediatek: support rsel feature

Chen-Yu Tsai wenst at chromium.org
Thu Sep 23 00:35:49 PDT 2021


Hi,

On Wed, Sep 22, 2021 at 10:59 AM Zhiyong Tao <zhiyong.tao at mediatek.com> wrote:
>
> This patch supports rsel(resistance selection) feature for I2C pins.
> It provides more resistance selection solution in different ICs.
> It provides rsel define and si unit solution by identifying
> "mediatek,rsel_resistance_in_si_unit" property in pio dtsi node.
>
> Signed-off-by: Zhiyong Tao <zhiyong.tao at mediatek.com>
> ---
>  .../pinctrl/mediatek/pinctrl-mtk-common-v2.c  | 231 +++++++++++++++---
>  .../pinctrl/mediatek/pinctrl-mtk-common-v2.h  |  45 ++++
>  drivers/pinctrl/mediatek/pinctrl-paris.c      |  60 +++--
>  3 files changed, 288 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
> index 5b3b048725cc..e84001923aaf 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
> +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
> @@ -661,6 +661,181 @@ static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw,
>         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;

The code could simply `return 0` after setting *rsel_val, then we don't have
to have the `found` variable.

Unless your goal is to use the last matching value in the case of duplicates,
instead of the first. If that is the case you should add a comment stating
so along with the reason,

And the structure could be written as

    if (pin not in range)
        continue;

    ... check value ...

which would decrease the nesting level. Mostly stylistic though.

> +                               }
> +                       } 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_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);

mtk_pinconf_bias_get_pu_pd() couldn't be reused?

> +
> +       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)
> @@ -742,44 +917,40 @@ static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw,
>         return err;
>  }
>
> -int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
> -                               const struct mtk_pin_desc *desc,
> -                               u32 pullup, u32 arg)
> -{
> -       int err;
> -
> -       err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg);
> -       if (!err)
> -               goto out;
> -
> -       err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg);
> -       if (!err)
> -               goto out;
> -
> -       err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg);
> -
> -out:
> -       return err;
> -}
> -EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set_combo);
> -
>  int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
>                               const struct mtk_pin_desc *desc,
>                               u32 *pullup, u32 *enable)
>  {
> -       int err;
> +       int err = -ENOTSUPP;
> +       u32 try_all_type;
>
> -       err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable);
> -       if (!err)
> -               goto out;
> +       if (hw->soc->pull_type)
> +               try_all_type = hw->soc->pull_type[desc->number];
> +       else
> +               try_all_type = MTK_PULL_TYPE_MASK;
>
> -       err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable);
> -       if (!err)
> -               goto out;
> +       if (try_all_type & MTK_PULL_RSEL_TYPE) {
> +               err = mtk_pinconf_bias_get_rsel(hw, desc, pullup, enable);
> +               if (!err)
> +                       return err;
> +       }
>
> -       err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable);
> +       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);
>
> -out:
>         return err;
>  }
>  EXPORT_SYMBOL_GPL(mtk_pinconf_bias_get_combo);
> diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
> index a6f1bdb2083b..4908c7aedbe0 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
> +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
> @@ -17,6 +17,22 @@
>  #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 EINT_NA        U16_MAX
>  #define NO_EINT_SUPPORT        EINT_NA
> @@ -42,6 +58,14 @@
>         PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit,    \
>                        _x_bits, 32, 1)
>
> +#define PIN_RSEL(_s_pin, _e_pin, _rsel_index, _up_resl, _down_rsel) {  \
> +               .s_pin = _s_pin,                                        \
> +               .e_pin = _e_pin,                                        \
> +               .rsel_index = _rsel_index,                              \
> +               .up_rsel = _up_resl,                                    \
> +               .down_rsel = _down_rsel,                                \
> +       }
> +
>  /* List these attributes which could be modified for the pin */
>  enum {
>         PINCTRL_PIN_REG_MODE,
> @@ -67,6 +91,7 @@ enum {
>         PINCTRL_PIN_REG_DRV_E0,
>         PINCTRL_PIN_REG_DRV_E1,
>         PINCTRL_PIN_REG_DRV_ADV,
> +       PINCTRL_PIN_REG_RSEL,
>         PINCTRL_PIN_REG_MAX,
>  };
>
> @@ -129,6 +154,21 @@ struct mtk_pin_field_calc {
>         u8  fixed;
>  };
>
> +/* struct mtk_pin_rsel - the structure that provides bias resistance selection.

Since you went through the trouble of documenting all the fields, would
you consider changing this to a kernel-doc style comment? It is similar
to Java-doc, and would be like:

/**
 * struct mtk_pin_rsel ......
 * @s_pin: ....
 * ...
 */

Only the start of the comment block needs to be changed.
See Documentation/doc-guide/kernel-doc.rst if you are unsure.

> + * @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_reg_calc - the structure that holds all ranges used to
>   *                          determine which register the pin would make use of
>   *                          for certain pin attribute.
> @@ -206,6 +246,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,
> @@ -254,6 +297,8 @@ struct mtk_pinctrl {
>         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);
> diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
> index 38aec0177d15..d4e02c5d74a8 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-paris.c
> +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
> @@ -579,8 +579,9 @@ static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, int
>  ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
>         unsigned int gpio, char *buf, unsigned int buf_len)
>  {
> -       int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1;
> +       int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1, rsel = -1;
>         const struct mtk_pin_desc *desc;
> +       u32 try_all_type;
>
>         if (gpio >= hw->soc->npins)
>                 return -EINVAL;
> @@ -591,24 +592,39 @@ ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
>                 pinmux -= hw->soc->nfuncs;
>
>         mtk_pinconf_bias_get_combo(hw, desc, &pullup, &pullen);
> -       if (pullen == MTK_PUPD_SET_R1R0_00) {
> -               pullen = 0;
> -               r1 = 0;
> -               r0 = 0;
> -       } else if (pullen == MTK_PUPD_SET_R1R0_01) {
> -               pullen = 1;
> -               r1 = 0;
> -               r0 = 1;
> -       } else if (pullen == MTK_PUPD_SET_R1R0_10) {
> -               pullen = 1;
> -               r1 = 1;
> -               r0 = 0;
> -       } else if (pullen == MTK_PUPD_SET_R1R0_11) {
> +
> +       if (hw->soc->pull_type)
> +               try_all_type = hw->soc->pull_type[desc->number];
> +
> +       if (hw->rsel_si_unit && (try_all_type & MTK_PULL_RSEL_TYPE)) {
> +               rsel = pullen;
>                 pullen = 1;
> -               r1 = 1;
> -               r0 = 1;
> -       } else if (pullen != MTK_DISABLE && pullen != MTK_ENABLE) {
> -               pullen = 0;
> +       } else {
> +               /* Case for: R1R0 */
> +               if (pullen == MTK_PUPD_SET_R1R0_00) {
> +                       pullen = 0;
> +                       r1 = 0;
> +                       r0 = 0;
> +               } else if (pullen == MTK_PUPD_SET_R1R0_01) {
> +                       pullen = 1;
> +                       r1 = 0;
> +                       r0 = 1;
> +               } else if (pullen == MTK_PUPD_SET_R1R0_10) {
> +                       pullen = 1;
> +                       r1 = 1;
> +                       r0 = 0;
> +               } else if (pullen == MTK_PUPD_SET_R1R0_11) {
> +                       pullen = 1;
> +                       r1 = 1;
> +                       r0 = 1;
> +               }
> +
> +               /* Case for: RSEL */
> +               if (pullen >= MTK_PULL_SET_RSEL_000 &&
> +                   pullen <= MTK_PULL_SET_RSEL_111) {
> +                       rsel = pullen - MTK_PULL_SET_RSEL_000;
> +                       pullen = 1;
> +               }
>         }
>         len += scnprintf(buf + len, buf_len - len,
>                         "%03d: %1d%1d%1d%1d%02d%1d%1d%1d%1d",
> @@ -626,6 +642,8 @@ ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
>         if (r1 != -1) {
>                 len += scnprintf(buf + len, buf_len - len, " (%1d %1d)\n",
>                         r1, r0);
> +       } else if (rsel != -1) {
> +               len += scnprintf(buf + len, buf_len - len, " (%1d)\n", rsel);
>         } else {
>                 len += scnprintf(buf + len, buf_len - len, "\n");
>         }
> @@ -970,6 +988,12 @@ int mtk_paris_pinctrl_probe(struct platform_device *pdev,
>
>         hw->nbase = hw->soc->nbase_names;
>
> +       if (of_find_property(hw->dev->of_node,
> +                            "mediatek,rsel_resistance_in_si_unit", NULL))

This new property should be documented in the bindings.


Regards
ChenYu




> +               hw->rsel_si_unit = true;
> +       else
> +               hw->rsel_si_unit = false;
> +
>         spin_lock_init(&hw->lock);
>
>         err = mtk_pctrl_build_state(pdev);
> --
> 2.25.1
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek



More information about the linux-arm-kernel mailing list