diff mbox series

[v2] pinctrl: bcm63268: add gpio function

Message ID 20241224103645.1709996-1-noltari@gmail.com
State New
Headers show
Series [v2] pinctrl: bcm63268: add gpio function | expand

Commit Message

Álvaro Fernández Rojas Dec. 24, 2024, 10:36 a.m. UTC
From: Kyle Hendry <kylehendrydev@gmail.com>

There is no guarantee that the bootloader will leave the pin configuration
in a known default state, so pinctrl needs to be explicitly set in some
cases. This patch adds a gpio function for drivers that need it, i.e.
gpio-leds.

Signed-off-by: Kyle Hendry <kylehendrydev@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 drivers/pinctrl/bcm/pinctrl-bcm63268.c | 71 +++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 1 deletion(-)

Comments

Jonas Gorski Dec. 30, 2024, 4:42 p.m. UTC | #1
Hi,

On Tue, Dec 24, 2024 at 11:41 AM Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
>
> From: Kyle Hendry <kylehendrydev@gmail.com>
>
> There is no guarantee that the bootloader will leave the pin configuration
> in a known default state, so pinctrl needs to be explicitly set in some
> cases. This patch adds a gpio function for drivers that need it, i.e.
> gpio-leds.
>
> Signed-off-by: Kyle Hendry <kylehendrydev@gmail.com>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>


bcm63268-pinctrl implements pinmux_ops::gpio_request_enable(), which
should automatically set any requested GPIO pin to the GPIO function,
so explicitly requesting the gpio function for a pin should not be
needed. Is this not enough?

Best Regards,
Jonas
Kyle Hendry Jan. 3, 2025, 3:04 a.m. UTC | #2
On 2024-12-30 08:42, Jonas Gorski wrote:
> Hi,
>
> On Tue, Dec 24, 2024 at 11:41 AM Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> From: Kyle Hendry <kylehendrydev@gmail.com>
>>
>> There is no guarantee that the bootloader will leave the pin configuration
>> in a known default state, so pinctrl needs to be explicitly set in some
>> cases. This patch adds a gpio function for drivers that need it, i.e.
>> gpio-leds.
>>
>> Signed-off-by: Kyle Hendry <kylehendrydev@gmail.com>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>
> bcm63268-pinctrl implements pinmux_ops::gpio_request_enable(), which
> should automatically set any requested GPIO pin to the GPIO function,
> so explicitly requesting the gpio function for a pin should not be
> needed. Is this not enough?
>
> Best Regards,
> Jonas
>
>
I assumed that as well, but nothing I tried worked with gpio-leds.
gpiochip_generic_request() does call gpio_request_enable(), but gpio-leds
uses devm_fwnode_gpiod_get() which looks like a different code path. The
only place it seems to be configuring the gpio is in create_gpio_led()
where it needs a pinctl node in the device tree. That's just my reading
of the code, though. I haven't set up a ftrace to verify it.

Best Regards,
Kyle
Álvaro Fernández Rojas Jan. 4, 2025, 3:44 p.m. UTC | #3
El vie, 3 ene 2025 a las 4:04, Kyle Hendry (<kylehendrydev@gmail.com>) escribió:
>
> On 2024-12-30 08:42, Jonas Gorski wrote:
> > Hi,
> >
> > On Tue, Dec 24, 2024 at 11:41 AM Álvaro Fernández Rojas
> > <noltari@gmail.com> wrote:
> >> From: Kyle Hendry <kylehendrydev@gmail.com>
> >>
> >> There is no guarantee that the bootloader will leave the pin configuration
> >> in a known default state, so pinctrl needs to be explicitly set in some
> >> cases. This patch adds a gpio function for drivers that need it, i.e.
> >> gpio-leds.
> >>
> >> Signed-off-by: Kyle Hendry <kylehendrydev@gmail.com>
> >> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> >
> > bcm63268-pinctrl implements pinmux_ops::gpio_request_enable(), which
> > should automatically set any requested GPIO pin to the GPIO function,
> > so explicitly requesting the gpio function for a pin should not be
> > needed. Is this not enough?
> >
> > Best Regards,
> > Jonas
> >
> >
> I assumed that as well, but nothing I tried worked with gpio-leds.
> gpiochip_generic_request() does call gpio_request_enable(), but gpio-leds
> uses devm_fwnode_gpiod_get() which looks like a different code path. The
> only place it seems to be configuring the gpio is in create_gpio_led()
> where it needs a pinctl node in the device tree. That's just my reading
> of the code, though. I haven't set up a ftrace to verify it.
>
> Best Regards,
> Kyle

As Kyle pointed out it's not enough and gpio_request_enable() doesn't
get called from gpio-leds.
I will try to investigate this and report back.

Best regards,
Álvaro.
Jonas Gorski Jan. 4, 2025, 7:32 p.m. UTC | #4
On Sat, Jan 4, 2025 at 6:02 PM Álvaro Fernández Rojas <noltari@gmail.com> wrote:
>
> El sáb, 4 ene 2025 a las 16:44, Álvaro Fernández Rojas
> (<noltari@gmail.com>) escribió:
> >
> > El vie, 3 ene 2025 a las 4:04, Kyle Hendry (<kylehendrydev@gmail.com>) escribió:
> > >
> > > On 2024-12-30 08:42, Jonas Gorski wrote:
> > > > Hi,
> > > >
> > > > On Tue, Dec 24, 2024 at 11:41 AM Álvaro Fernández Rojas
> > > > <noltari@gmail.com> wrote:
> > > >> From: Kyle Hendry <kylehendrydev@gmail.com>
> > > >>
> > > >> There is no guarantee that the bootloader will leave the pin configuration
> > > >> in a known default state, so pinctrl needs to be explicitly set in some
> > > >> cases. This patch adds a gpio function for drivers that need it, i.e.
> > > >> gpio-leds.
> > > >>
> > > >> Signed-off-by: Kyle Hendry <kylehendrydev@gmail.com>
> > > >> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> > > >
> > > > bcm63268-pinctrl implements pinmux_ops::gpio_request_enable(), which
> > > > should automatically set any requested GPIO pin to the GPIO function,
> > > > so explicitly requesting the gpio function for a pin should not be
> > > > needed. Is this not enough?
> > > >
> > > > Best Regards,
> > > > Jonas
> > > >
> > > >
> > > I assumed that as well, but nothing I tried worked with gpio-leds.
> > > gpiochip_generic_request() does call gpio_request_enable(), but gpio-leds
> > > uses devm_fwnode_gpiod_get() which looks like a different code path. The
> > > only place it seems to be configuring the gpio is in create_gpio_led()
> > > where it needs a pinctl node in the device tree. That's just my reading
> > > of the code, though. I haven't set up a ftrace to verify it.
> > >
> > > Best Regards,
> > > Kyle
> >
> > As Kyle pointed out it's not enough and gpio_request_enable() doesn't
> > get called from gpio-leds.
> > I will try to investigate this and report back.
> >
> > Best regards,
> > Álvaro.
>
> I've performed some tests and so far I haven't been able to get
> bcm63268_gpio_request_enable() called.
>
> Even exporting a gpio from userspace doesn't trigger that function,
> which seems strange because in that case we won't have a "gpio"
> function on the pinctrl for that gpio, even with this patch...

On a first glance it looks like that regmap-gpio does not populate
gpio_chip::request and gpio_chip:free, so the gpio subsystem is not
aware that it needs to request anything. Not sure if just using
gpiolib_generic_request() / gpiolib_generic_free() is fine. Currently
on vacation, so no hardware to test anything at hand ;-)

Best Regards,
Jonas
Álvaro Fernández Rojas Jan. 5, 2025, 9:31 a.m. UTC | #5
El sáb, 4 ene 2025 a las 20:32, Jonas Gorski
(<jonas.gorski@gmail.com>) escribió:
>
> On Sat, Jan 4, 2025 at 6:02 PM Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> >
> > El sáb, 4 ene 2025 a las 16:44, Álvaro Fernández Rojas
> > (<noltari@gmail.com>) escribió:
> > >
> > > El vie, 3 ene 2025 a las 4:04, Kyle Hendry (<kylehendrydev@gmail.com>) escribió:
> > > >
> > > > On 2024-12-30 08:42, Jonas Gorski wrote:
> > > > > Hi,
> > > > >
> > > > > On Tue, Dec 24, 2024 at 11:41 AM Álvaro Fernández Rojas
> > > > > <noltari@gmail.com> wrote:
> > > > >> From: Kyle Hendry <kylehendrydev@gmail.com>
> > > > >>
> > > > >> There is no guarantee that the bootloader will leave the pin configuration
> > > > >> in a known default state, so pinctrl needs to be explicitly set in some
> > > > >> cases. This patch adds a gpio function for drivers that need it, i.e.
> > > > >> gpio-leds.
> > > > >>
> > > > >> Signed-off-by: Kyle Hendry <kylehendrydev@gmail.com>
> > > > >> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> > > > >
> > > > > bcm63268-pinctrl implements pinmux_ops::gpio_request_enable(), which
> > > > > should automatically set any requested GPIO pin to the GPIO function,
> > > > > so explicitly requesting the gpio function for a pin should not be
> > > > > needed. Is this not enough?
> > > > >
> > > > > Best Regards,
> > > > > Jonas
> > > > >
> > > > >
> > > > I assumed that as well, but nothing I tried worked with gpio-leds.
> > > > gpiochip_generic_request() does call gpio_request_enable(), but gpio-leds
> > > > uses devm_fwnode_gpiod_get() which looks like a different code path. The
> > > > only place it seems to be configuring the gpio is in create_gpio_led()
> > > > where it needs a pinctl node in the device tree. That's just my reading
> > > > of the code, though. I haven't set up a ftrace to verify it.
> > > >
> > > > Best Regards,
> > > > Kyle
> > >
> > > As Kyle pointed out it's not enough and gpio_request_enable() doesn't
> > > get called from gpio-leds.
> > > I will try to investigate this and report back.
> > >
> > > Best regards,
> > > Álvaro.
> >
> > I've performed some tests and so far I haven't been able to get
> > bcm63268_gpio_request_enable() called.
> >
> > Even exporting a gpio from userspace doesn't trigger that function,
> > which seems strange because in that case we won't have a "gpio"
> > function on the pinctrl for that gpio, even with this patch...
>
> On a first glance it looks like that regmap-gpio does not populate
> gpio_chip::request and gpio_chip:free, so the gpio subsystem is not
> aware that it needs to request anything. Not sure if just using
> gpiolib_generic_request() / gpiolib_generic_free() is fine. Currently
> on vacation, so no hardware to test anything at hand ;-)
>
> Best Regards,
> Jonas

You're totally right, after adding request() and free() functions to
gpio-regmap it's now working without this patch because
bcm63268_gpio_request_enable() is now properly called:
1. gpio-keys-polled
[    4.052132] gpio_button_hotplug: loading out-of-tree module taints kernel.
[    4.060657] bcm63268-pinctrl 100000d0.pinctrl: request pin 34
(gpio34) for 100000d0.pinctrl:546
[    4.069704] bcm63268_gpio_request_enable: range=99a2e0ae offset=34
[    4.076158] bcm63268-pinctrl 100000d0.pinctrl: request pin 35
(gpio35) for 100000d0.pinctrl:547
[    4.085135] bcm63268_gpio_request_enable: range=99a2e0ae offset=35

2. gpio-leds
[    4.480190] bcm63268-pinctrl 100000d0.pinctrl: request pin 0
(gpio0) for 100000d0.pinctrl:512
[    4.489078] bcm63268_gpio_request_enable: range=99a2e0ae offset=0
[    4.495747] bcm63268-pinctrl 100000d0.pinctrl: request pin 1
(gpio1) for 100000d0.pinctrl:513
[    4.504600] bcm63268_gpio_request_enable: range=99a2e0ae offset=1

3. userspace gpio export
root@OpenWrt:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 512-563, parent: platform/100000d0.pinctrl, 100000d0.pinctrl:
 gpio-512 (                    |red:mobile          ) out lo
 gpio-513 (                    |green:mobile        ) out lo
 gpio-546 (                    |wps                 ) in  hi ACTIVE LOW
 gpio-547 (                    |reset               ) in  hi ACTIVE LOW
root@OpenWrt:~# echo 545 > /sys/class/gpio/export
[   33.437477] bcm63268-pinctrl 100000d0.pinctrl: request pin 33
(gpio33) for 100000d0.pinctrl:545
[   33.446503] bcm63268_gpio_request_enable: range=99a2e0ae offset=33
root@OpenWrt:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 512-563, parent: platform/100000d0.pinctrl, 100000d0.pinctrl:
 gpio-512 (                    |red:mobile          ) out lo
 gpio-513 (                    |green:mobile        ) out lo
 gpio-545 (                    |sysfs               ) in  hi
 gpio-546 (                    |wps                 ) in  hi ACTIVE LOW
 gpio-547 (                    |reset               ) in  hi ACTIVE LOW

OpenWrt test source code:
https://github.com/Noltari/openwrt/commits/bmips-gpio-tests
https://github.com/Noltari/openwrt/commit/d3bc7610c8fe8f713a3e47ed8368b6aa220ae763

Linux test source code:
https://github.com/Noltari/linux/commits/gpio-regmap-pinctrl-request-free
https://github.com/Noltari/linux/commit/2d0ebb8cad8084e932f40f3f69d4e931b2316aa4

@Linus I assume that adding those functions may cause issues to other
drivers and maybe we need to add some logic to add them dynamically
based on a new gpio_regmap_config parameter?

Best regards,
Álvaro.
diff mbox series

Patch

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm63268.c b/drivers/pinctrl/bcm/pinctrl-bcm63268.c
index 80c2fc55ffa2..a98f57e64d1e 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm63268.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm63268.c
@@ -34,6 +34,7 @@ 
 #define  BCM63268_BASEMODE_VDSL_PHY_3	BIT(9) /* GPIOs 26/27 */
 
 enum bcm63268_pinctrl_reg {
+	BCM63268_NONE,
 	BCM63268_LEDCTRL,
 	BCM63268_MODE,
 	BCM63268_CTRL,
@@ -242,6 +243,61 @@  static struct pingroup bcm63268_groups[] = {
 	BCM_PIN_GROUP(vdsl_phy3_grp),
 };
 
+static const char * const gpio_groups[] = {
+	"gpio0",
+	"gpio1",
+	"gpio2",
+	"gpio3",
+	"gpio4",
+	"gpio5",
+	"gpio6",
+	"gpio7",
+	"gpio8",
+	"gpio9",
+	"gpio10",
+	"gpio11",
+	"gpio12",
+	"gpio13",
+	"gpio14",
+	"gpio15",
+	"gpio16",
+	"gpio17",
+	"gpio18",
+	"gpio19",
+	"gpio20",
+	"gpio21",
+	"gpio22",
+	"gpio23",
+	"gpio24",
+	"gpio25",
+	"gpio26",
+	"gpio27",
+	"gpio28",
+	"gpio29",
+	"gpio30",
+	"gpio31",
+	"gpio32",
+	"gpio33",
+	"gpio34",
+	"gpio35",
+	"gpio36",
+	"gpio37",
+	"gpio38",
+	"gpio39",
+	"gpio40",
+	"gpio41",
+	"gpio42",
+	"gpio43",
+	"gpio44",
+	"gpio45",
+	"gpio46",
+	"gpio47",
+	"gpio48",
+	"gpio49",
+	"gpio50",
+	"gpio51",
+};
+
 static const char * const led_groups[] = {
 	"gpio0",
 	"gpio1",
@@ -394,6 +450,14 @@  static const char * const vdsl_phy_override_3_groups[] = {
 	"vdsl_phy_override_3_grp",
 };
 
+#define BCM63268_GPIO_FUN(n)				\
+	{						\
+		.name = #n,				\
+		.groups = n##_groups,			\
+		.num_groups = ARRAY_SIZE(n##_groups),	\
+		.reg = BCM63268_NONE,			\
+	}
+
 #define BCM63268_LED_FUN(n)				\
 	{						\
 		.name = #n,				\
@@ -428,6 +492,7 @@  static const char * const vdsl_phy_override_3_groups[] = {
 	}
 
 static const struct bcm63268_function bcm63268_funcs[] = {
+	BCM63268_GPIO_FUN(gpio),
 	BCM63268_LED_FUN(led),
 	BCM63268_MODE_FUN(serial_led_clk),
 	BCM63268_MODE_FUN(serial_led_data),
@@ -542,6 +607,9 @@  static int bcm63268_pinctrl_set_mux(struct pinctrl_dev *pctldev,
 		bcm63268_set_gpio(pc, pg->pins[i]);
 
 	switch (f->reg) {
+	case BCM63268_NONE:
+		reg = 0;
+		break;
 	case BCM63268_LEDCTRL:
 		reg = BCM63268_LED_REG;
 		mask = BIT(pg->pins[0]);
@@ -567,7 +635,8 @@  static int bcm63268_pinctrl_set_mux(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 	}
 
-	regmap_update_bits(pc->regs, reg, mask, val);
+	if (reg)
+		regmap_update_bits(pc->regs, reg, mask, val);
 
 	return 0;
 }