On Tue, Jan 11, 2022 at 7:23 PM Chen-Yu Tsai <wenst@xxxxxxxxxxxx> wrote: > > Some of the MediaTek chips that utilize the Paris pinctrl driver library > support a lower drive strength (<= 1mA) than the standard drive strength > settings (2~16 mA) on certain pins. This was previously supported by the > custom MTK_PIN_CONFIG_DRV_ADV parameter along with the > "mediatek,drive-strength-adv" device tree property. > > The drive strength values for this hardware are 125, 250, 500, and 1000 mA, > and can be readily described by the existing "drive-strength-microamp", > which then gets parsed by the generic pinconf library into the parameter > PIN_CONFIG_DRIVE_STRENGTH_UA. So I am actually unsure how to implement support for this properly. My intention was to map "mediatek,drive-strength-adv" to "drive-strength-microamp". This implies using the advanced mode if the property is present, and vice versa. (Also unsure if such a binding would be acceptable.) However the pin configs are passed in one-by-one within the driver, so it doesn't seem viable to check for the absence of a certain parameter. This might involve a bit more rewriting. ChenYu > Add support for PIN_CONFIG_DRIVE_STRENGTH_UA while keeping the old > custom parameter around for backward compatibility. > > Signed-off-by: Chen-Yu Tsai <wenst@xxxxxxxxxxxx> > --- > > The indentation in the switch/case blocks is getting somewhat out of > control. I also have some cleanup changes to reverse the logic of the > if/break statements. Not sure if it should be done before or after this > patch though. > > --- > drivers/pinctrl/mediatek/pinctrl-paris.c | 84 ++++++++++++++++++++++++ > 1 file changed, 84 insertions(+) > > diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c > index 678c8aa33012..5a94903ae372 100644 > --- a/drivers/pinctrl/mediatek/pinctrl-paris.c > +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c > @@ -48,6 +48,53 @@ static const char * const mtk_gpio_functions[] = { > "func12", "func13", "func14", "func15", > }; > > +/* > + * This section supports converting to/from custom MTK_PIN_CONFIG_DRV_ADV > + * and standard PIN_CONFIG_DRIVE_STRENGTH_UA pin configs. > + * > + * The custom value encodes three hardware bits as follows: > + * > + * | Bits | > + * | 2 (E1) | 1 (E0) | 0 (EN) | drive strength (uA) > + * ------------------------------------------------ > + * | x | x | 0 | disabled, use standard drive strength > + * ------------------------------------- > + * | 0 | 0 | 1 | 125 uA > + * | 0 | 1 | 1 | 250 uA > + * | 1 | 0 | 1 | 500 uA > + * | 1 | 1 | 1 | 1000 uA > + */ > +static const int mtk_drv_adv_uA[] = { 125, 250, 500, 1000 }; > + > +static int mtk_drv_adv_to_uA(int val) > +{ > + /* This should never happen. */ > + if (WARN_ON_ONCE(val < 0 || val > 7)) > + return -EINVAL; > + > + /* Bit 0 simply enables this hardware part */ > + if (!(val & BIT(0))) > + return -EINVAL; > + > + return mtk_drv_adv_uA[(val >> 1)]; > +} > + > +static int mtk_drv_uA_to_adv(int val) > +{ > + switch (val) { > + case 125: > + return 0x1; > + case 250: > + return 0x3; > + case 500: > + return 0x5; > + case 1000: > + return 0x7; > + } > + > + return -EINVAL; > +} > + > static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, > struct pinctrl_gpio_range *range, > unsigned int pin) > @@ -151,11 +198,38 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, > > break; > case PIN_CONFIG_DRIVE_STRENGTH: > + if (hw->soc->adv_drive_get) { > + err = hw->soc->adv_drive_get(hw, desc, &ret); > + if (!err) { > + err = mtk_drv_adv_to_uA(ret); > + if (err > 0) { > + /* PIN_CONFIG_DRIVE_STRENGTH_UA used */ > + err = -EINVAL; > + break; > + } > + } > + } > + > if (hw->soc->drive_get) > err = hw->soc->drive_get(hw, desc, &ret); > else > err = -ENOTSUPP; > break; > + case PIN_CONFIG_DRIVE_STRENGTH_UA: > + if (hw->soc->adv_drive_get) { > + err = hw->soc->adv_drive_get(hw, desc, &ret); > + if (err) > + break; > + err = mtk_drv_adv_to_uA(ret); > + if (err < 0) > + break; > + > + ret = err; > + err = 0; > + } else { > + err = -ENOTSUPP; > + } > + break; > case MTK_PIN_CONFIG_TDSEL: > case MTK_PIN_CONFIG_RDSEL: > reg = (param == MTK_PIN_CONFIG_TDSEL) ? > @@ -271,6 +345,16 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, > else > err = -ENOTSUPP; > break; > + case PIN_CONFIG_DRIVE_STRENGTH_UA: > + if (hw->soc->adv_drive_set) { > + err = mtk_drv_uA_to_adv(arg); > + if (err < 0) > + break; > + err = hw->soc->adv_drive_set(hw, desc, err); > + } else { > + err = -ENOTSUPP; > + } > + break; > case MTK_PIN_CONFIG_TDSEL: > case MTK_PIN_CONFIG_RDSEL: > reg = (param == MTK_PIN_CONFIG_TDSEL) ? > -- > 2.34.1.575.g55b058a8bb-goog >