Skip to content

Commit 802c51a

Browse files
author
Bartosz Golaszewski
committed
gpiolib: fix hogs with multiple lines
After moving GPIO hog handling into GPIOLIB core, we accidentally stopped supporting devicetree hog definitions with multiple lines like so: hog { gpio-hog; gpios = <3 0>, <4 GPIO_ACTIVE_LOW>; output-high; line-name = "foo"; }; Restore this functionality to fix reported regressions. Fixes: d1d564e ("gpio: move hogs into GPIO core") Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Closes: https://lore.kernel.org/all/CAMuHMdX6RuZXAozrF5m625ZepJTVVr4pcyKczSk12MedWvoejw@mail.gmail.com/ Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://patch.msgid.link/20260330-gpio-hogs-multiple-v3-1-175c3839ad9f@oss.qualcomm.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
1 parent af475c1 commit 802c51a

1 file changed

Lines changed: 54 additions & 38 deletions

File tree

drivers/gpio/gpiolib.c

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -938,12 +938,18 @@ int gpiochip_add_hog(struct gpio_chip *gc, struct fwnode_handle *fwnode)
938938
struct fwnode_handle *gc_node = dev_fwnode(&gc->gpiodev->dev);
939939
struct fwnode_reference_args gpiospec;
940940
enum gpiod_flags dflags;
941+
const char *name = NULL;
941942
struct gpio_desc *desc;
943+
unsigned int num_hogs;
942944
unsigned long lflags;
943-
const char *name;
944945
int ret, argc;
945-
u32 gpios[3]; /* We support up to three-cell bindings. */
946-
u32 cells;
946+
/*
947+
* For devicetree-based systems, this needs to be defined in bindings
948+
* and there's no real default value. For other firmware descriptions
949+
* it makes the most sense to use 2 cells for the GPIO offset and
950+
* request flags.
951+
*/
952+
u32 cells = 2;
947953

948954
lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
949955
dflags = GPIOD_ASIS;
@@ -952,42 +958,22 @@ int gpiochip_add_hog(struct gpio_chip *gc, struct fwnode_handle *fwnode)
952958
argc = fwnode_property_count_u32(fwnode, "gpios");
953959
if (argc < 0)
954960
return argc;
955-
if (argc > 3)
956-
return -EINVAL;
957961

958-
ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios, argc);
959-
if (ret < 0)
962+
ret = fwnode_property_read_u32(gc_node, "#gpio-cells", &cells);
963+
if (ret && is_of_node(fwnode))
960964
return ret;
965+
if (argc % cells)
966+
return -EINVAL;
961967

962-
if (is_of_node(fwnode)) {
963-
/*
964-
* OF-nodes need some additional special handling for
965-
* translating of devicetree flags.
966-
*/
967-
ret = fwnode_property_read_u32(gc_node, "#gpio-cells", &cells);
968-
if (ret)
969-
return ret;
970-
if (!ret && argc != cells)
971-
return -EINVAL;
972-
973-
memset(&gpiospec, 0, sizeof(gpiospec));
974-
gpiospec.fwnode = fwnode;
975-
gpiospec.nargs = argc;
968+
num_hogs = argc / cells;
976969

977-
for (int i = 0; i < argc; i++)
978-
gpiospec.args[i] = gpios[i];
970+
u32 *gpios __free(kfree) = kzalloc_objs(*gpios, argc);
971+
if (!gpios)
972+
return -ENOMEM;
979973

980-
ret = of_gpiochip_get_lflags(gc, &gpiospec, &lflags);
981-
if (ret)
982-
return ret;
983-
} else {
984-
/*
985-
* GPIO_ACTIVE_LOW is currently the only lookup flag
986-
* supported for non-OF firmware nodes.
987-
*/
988-
if (gpios[1])
989-
lflags |= GPIO_ACTIVE_LOW;
990-
}
974+
ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios, argc);
975+
if (ret < 0)
976+
return ret;
991977

992978
if (fwnode_property_present(fwnode, "input"))
993979
dflags |= GPIOD_IN;
@@ -1000,11 +986,41 @@ int gpiochip_add_hog(struct gpio_chip *gc, struct fwnode_handle *fwnode)
1000986

1001987
fwnode_property_read_string(fwnode, "line-name", &name);
1002988

1003-
desc = gpiochip_get_desc(gc, gpios[0]);
1004-
if (IS_ERR(desc))
1005-
return PTR_ERR(desc);
989+
for (unsigned int i = 0; i < num_hogs; i++) {
990+
if (is_of_node(fwnode)) {
991+
/*
992+
* OF-nodes need some additional special handling for
993+
* translating of devicetree flags.
994+
*/
995+
memset(&gpiospec, 0, sizeof(gpiospec));
996+
gpiospec.fwnode = fwnode;
997+
gpiospec.nargs = cells;
998+
999+
for (unsigned int j = 0; j < cells; j++)
1000+
gpiospec.args[j] = gpios[i * cells + j];
1001+
1002+
ret = of_gpiochip_get_lflags(gc, &gpiospec, &lflags);
1003+
if (ret)
1004+
return ret;
1005+
} else {
1006+
/*
1007+
* GPIO_ACTIVE_LOW is currently the only lookup flag
1008+
* supported for non-OF firmware nodes.
1009+
*/
1010+
if (gpios[i * cells + 1])
1011+
lflags |= GPIO_ACTIVE_LOW;
1012+
}
1013+
1014+
desc = gpiochip_get_desc(gc, gpios[i * cells]);
1015+
if (IS_ERR(desc))
1016+
return PTR_ERR(desc);
10061017

1007-
return gpiod_hog(desc, name, lflags, dflags);
1018+
ret = gpiod_hog(desc, name, lflags, dflags);
1019+
if (ret)
1020+
return ret;
1021+
}
1022+
1023+
return 0;
10081024
}
10091025

10101026
static int gpiochip_hog_lines(struct gpio_chip *gc)

0 commit comments

Comments
 (0)