diff mbox series

[V3,1/2] pinctrl: bcm2835: Implement bcm2835_pinconf_get

Message ID 20240303140137.157522-2-wahrenst@gmx.net
State New
Headers show
Series pinctrl: bcm2835: Implement pin_conf_get | expand

Commit Message

Stefan Wahren March 3, 2024, 2:01 p.m. UTC
Even the driver already has implemented pin_dbg_show, it could
be helpful to implement pin_conf_get for a more generic behavior.
Contrary to the BCM2711, the BCM2835 SOC doesn't allow to read
the bias config, so the implementation is limited to the basics.

Keep ENOTSUPP here, because it's only used internally.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/pinctrl/bcm/pinctrl-bcm2835.c | 37 +++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

--
2.34.1

Comments

Chen-Yu Tsai March 3, 2024, 2:19 p.m. UTC | #1
Hi Linus,

On Sun, Mar 3, 2024 at 10:02 PM Stefan Wahren <wahrenst@gmx.net> wrote:
>
> Even the driver already has implemented pin_dbg_show, it could
> be helpful to implement pin_conf_get for a more generic behavior.
> Contrary to the BCM2711, the BCM2835 SOC doesn't allow to read
> the bias config, so the implementation is limited to the basics.
>
> Keep ENOTSUPP here, because it's only used internally.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
>  drivers/pinctrl/bcm/pinctrl-bcm2835.c | 37 +++++++++++++++++++++++++--
>  1 file changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
> index 1489191a213f..ed768cefe5d0 100644
> --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
> +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
> @@ -1003,8 +1003,41 @@ static const struct pinmux_ops bcm2835_pmx_ops = {
>  static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
>                         unsigned pin, unsigned long *config)
>  {
> -       /* No way to read back config in HW */
> -       return -ENOTSUPP;
> +       enum pin_config_param param = pinconf_to_config_param(*config);
> +       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
> +       enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, pin);
> +       u32 val;
> +
> +       /* No way to read back bias config in HW */
> +
> +       switch (param) {
> +       case PIN_CONFIG_INPUT_ENABLE:
> +               if (fsel != BCM2835_FSEL_GPIO_IN)
> +                       return -EINVAL;
> +
> +               *config = pinconf_to_config_packed(param, 1);
> +               break;
> +
> +       case PIN_CONFIG_OUTPUT_ENABLE:
> +               if (fsel != BCM2835_FSEL_GPIO_OUT)
> +                       return -EINVAL;
> +
> +               *config = pinconf_to_config_packed(param, 1);
> +               break;

I'd like to take this opportunity to ask about INPUT_ENABLE and
OUTPUT_ENABLE.

AFAICT from existing comments in include/linux/pinctrl/pinconf-generic.h ,
these two options refer to input and output buffers or connections within
the general electric path, i.e. it allows the signal to pass through in
a certain direction. It does not refer to the current selected direction
of the GPIO function, which is covered by the PIN_CONFIG_OUTPUT option,
and by gpiolib, if and only if the pin has been allocated for gpiolib
use. But it seems multiple existing drivers do this.

What's the correct thing to do here?


Thanks
ChenYu

> +
> +       case PIN_CONFIG_OUTPUT:
> +               if (fsel != BCM2835_FSEL_GPIO_OUT)
> +                       return -EINVAL;
> +
> +               val = bcm2835_gpio_get_bit(pc, GPLEV0, pin);
> +               *config = pinconf_to_config_packed(param, val);
> +               break;
> +
> +       default:
> +               return -ENOTSUPP;
> +       }
> +
> +       return 0;
>  }
>
>  static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc,
> --
> 2.34.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Linus Walleij March 5, 2024, 10:38 p.m. UTC | #2
On Sun, Mar 3, 2024 at 3:19 PM Chen-Yu Tsai <wens@kernel.org> wrote:

> Hi Linus,
(...)
> I'd like to take this opportunity to ask about INPUT_ENABLE and
> OUTPUT_ENABLE.
>
> AFAICT from existing comments in include/linux/pinctrl/pinconf-generic.h ,
> these two options refer to input and output buffers or connections within
> the general electric path, i.e. it allows the signal to pass through in
> a certain direction. It does not refer to the current selected direction
> of the GPIO function, which is covered by the PIN_CONFIG_OUTPUT option,
> and by gpiolib, if and only if the pin has been allocated for gpiolib
> use. But it seems multiple existing drivers do this.
>
> What's the correct thing to do here?

It's really up to the driver author: the text in pinconf-generic.h does its best
to describe the intended semantics, but sometimes hardware will not fully
match what is said in the documentation.

I guess in this case the PIN_CONFIG_OUTPUT_ENABLE and
PIN_CONFIG_OUTPUT is not two distinctly different things for this
hardware so a reasonable semantic is to implement both in the same
case and do the same for both of them.

+       case PIN_CONFIG_OUTPUT_ENABLE:
+       case PIN_CONFIG_OUTPUT:
+               if (fsel != BCM2835_FSEL_GPIO_OUT)
+                       return -EINVAL;
+
+               val = bcm2835_gpio_get_bit(pc, GPLEV0, pin);
+               *config = pinconf_to_config_packed(param, val);
+               break;

Does it seem reasonable?

Yours,
Linus Walleij
Chen-Yu Tsai March 6, 2024, 5:07 p.m. UTC | #3
On Thu, Mar 7, 2024 at 1:04 AM Stefan Wahren <wahrenst@gmx.net> wrote:
>
> Hi guys,
>
> Am 06.03.24 um 14:40 schrieb Chen-Yu Tsai:
> > On Wed, Mar 6, 2024 at 8:57 PM Linus Walleij <linus.walleij@linaro.org> wrote:
> >> On Wed, Mar 6, 2024 at 9:55 AM Chen-Yu Tsai <wens@kernel.org> wrote:
> >>
> >>> For the MediaTek device trees, the only two occurrences of "output-enable"
> >>> actually describe conflicting information:
> >>>
> >>>      pins-rts {
> >>>              pinmux = <PINMUX_GPIO47__FUNC_URTS1>;
> >>>              output-enable;
> >>>      };
> >>>
> >>> The above asks for the UART function on this pin, but based on existing
> >>> driver definitions, switches the function to GPIO output because of the
> >>> "output-enable" property. Hence the confusion.
> >> This is actually also driver-dependent.
> >>
> >> It is only conflicting if the pin controller has .strict set in struct
> >> pinmux_ops,
> >> because many SoCs are perfectly capable of using a pin as a function
> >> such as UART RTS and GPIO at *the same time*.
> > I don't think MediaTek falls in this category. Nor does BCM2835. It is
> > quite obvious, since GPIO in/out are selectable pinmux functions.
> >
> >> Details on strict mode can be found in Documentation/driver-api/pin-control.rst
> >>
> >> I don't know which Mediatek this is but:
> >> $ git grep strict drivers/pinctrl/mediatek/
> >> drivers/pinctrl/mediatek/pinctrl-moore.c:       .strict = true,
> >>
> >> Only the Moore family is strict, and I think BCM2835 is not.
> > While that would be true for new drivers, I believe we do have many existing
> > drivers that cannot set the strict bit, as existing device trees already
> > have their pinctrl options selecting the GPIO function in conjunction with
> > *-gpios usage. We also had this on older Allwinner platforms. We ended up
> > only setting the .strict option for new platforms, not because of any
> > hardware difference, but because of backwards compatibility. Otherwise
> > I would love to clean up many of them.
> >
> > In both MediaTek and BCM2835's cases, it is quite obvious from the driver
> > that the hardware cannot use the pin as a dedicated function and a GPIO
> > at the same time. And we should not give them more options to shoot
> > themselves in the foot.
> i tried following your discussion. Does it mean i should change anything
> here in this series?

I think support for PIN_CONFIG_INPUT_ENABLE and PIN_CONFIG_OUTPUT_ENABLE
should be dropped from the series.

ChenYu
diff mbox series

Patch

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 1489191a213f..ed768cefe5d0 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -1003,8 +1003,41 @@  static const struct pinmux_ops bcm2835_pmx_ops = {
 static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
 			unsigned pin, unsigned long *config)
 {
-	/* No way to read back config in HW */
-	return -ENOTSUPP;
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, pin);
+	u32 val;
+
+	/* No way to read back bias config in HW */
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_ENABLE:
+		if (fsel != BCM2835_FSEL_GPIO_IN)
+			return -EINVAL;
+
+		*config = pinconf_to_config_packed(param, 1);
+		break;
+
+	case PIN_CONFIG_OUTPUT_ENABLE:
+		if (fsel != BCM2835_FSEL_GPIO_OUT)
+			return -EINVAL;
+
+		*config = pinconf_to_config_packed(param, 1);
+		break;
+
+	case PIN_CONFIG_OUTPUT:
+		if (fsel != BCM2835_FSEL_GPIO_OUT)
+			return -EINVAL;
+
+		val = bcm2835_gpio_get_bit(pc, GPLEV0, pin);
+		*config = pinconf_to_config_packed(param, val);
+		break;
+
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
 }

 static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc,