Message ID | 20210922025640.11600-5-zhiyong.tao@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Mediatek pinctrl patch on mt8195 | expand |
Hi, On Wed, Sep 22, 2021 at 10:59 AM Zhiyong Tao <zhiyong.tao@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@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@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-mediatek
On Thu, 2021-09-23 at 15:35 +0800, Chen-Yu Tsai wrote: > Hi, > > On Wed, Sep 22, 2021 at 10:59 AM Zhiyong Tao < > zhiyong.tao@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@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. We use "found" variable to identify whether user set the right si unit value or not . > > 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? It couldn't be reused. Because in the api, if user use rsel si unit, it can return si unit value, if user use rsel define, it can return rsel define value. > > > + > > + 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. we will fix it in the next version. > > > + * @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. > we will add it in the next version. > > 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@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/linux-mediatek
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; + } + } 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 (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 (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. + * @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)) + hw->rsel_si_unit = true; + else + hw->rsel_si_unit = false; + spin_lock_init(&hw->lock); err = mtk_pctrl_build_state(pdev);
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@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(-)