Skip to content

Commit d1d564e

Browse files
author
Bartosz Golaszewski
committed
gpio: move hogs into GPIO core
Refactor line hogging code by moving the parts duplicated in gpiolib-acpi-core.c and gpiolib-of.c into gpiolib.c, leaving just the OF-specific bits in the latter. This makes fwnode the primary API for setting up hogs and allows to use software nodes in addition to ACPI and OF nodes. Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Linus Walleij <linusw@kernel.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20260309-gpio-hog-fwnode-v2-2-4e61f3dbf06a@oss.qualcomm.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
1 parent bbee90e commit d1d564e

5 files changed

Lines changed: 125 additions & 199 deletions

File tree

drivers/gpio/gpiolib-acpi-core.c

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,75 +1220,6 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip)
12201220
}
12211221
}
12221222

1223-
static struct gpio_desc *
1224-
acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip,
1225-
struct fwnode_handle *fwnode,
1226-
const char **name,
1227-
unsigned long *lflags,
1228-
enum gpiod_flags *dflags)
1229-
{
1230-
struct gpio_chip *chip = achip->chip;
1231-
struct gpio_desc *desc;
1232-
u32 gpios[2];
1233-
int ret;
1234-
1235-
*lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
1236-
*dflags = GPIOD_ASIS;
1237-
*name = NULL;
1238-
1239-
ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
1240-
ARRAY_SIZE(gpios));
1241-
if (ret < 0)
1242-
return ERR_PTR(ret);
1243-
1244-
desc = gpiochip_get_desc(chip, gpios[0]);
1245-
if (IS_ERR(desc))
1246-
return desc;
1247-
1248-
if (gpios[1])
1249-
*lflags |= GPIO_ACTIVE_LOW;
1250-
1251-
if (fwnode_property_present(fwnode, "input"))
1252-
*dflags |= GPIOD_IN;
1253-
else if (fwnode_property_present(fwnode, "output-low"))
1254-
*dflags |= GPIOD_OUT_LOW;
1255-
else if (fwnode_property_present(fwnode, "output-high"))
1256-
*dflags |= GPIOD_OUT_HIGH;
1257-
else
1258-
return ERR_PTR(-EINVAL);
1259-
1260-
fwnode_property_read_string(fwnode, "line-name", name);
1261-
1262-
return desc;
1263-
}
1264-
1265-
static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
1266-
{
1267-
struct gpio_chip *chip = achip->chip;
1268-
1269-
device_for_each_child_node_scoped(chip->parent, fwnode) {
1270-
unsigned long lflags;
1271-
enum gpiod_flags dflags;
1272-
struct gpio_desc *desc;
1273-
const char *name;
1274-
int ret;
1275-
1276-
if (!fwnode_property_present(fwnode, "gpio-hog"))
1277-
continue;
1278-
1279-
desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name,
1280-
&lflags, &dflags);
1281-
if (IS_ERR(desc))
1282-
continue;
1283-
1284-
ret = gpiod_hog(desc, name, lflags, dflags);
1285-
if (ret) {
1286-
dev_err(chip->parent, "Failed to hog GPIO\n");
1287-
return;
1288-
}
1289-
}
1290-
}
1291-
12921223
void acpi_gpiochip_add(struct gpio_chip *chip)
12931224
{
12941225
struct acpi_gpio_chip *acpi_gpio;
@@ -1321,7 +1252,6 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
13211252
}
13221253

13231254
acpi_gpiochip_request_regions(acpi_gpio);
1324-
acpi_gpiochip_scan_gpios(acpi_gpio);
13251255
acpi_dev_clear_dependencies(adev);
13261256
}
13271257

drivers/gpio/gpiolib-of.c

Lines changed: 16 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/device.h>
1111
#include <linux/err.h>
1212
#include <linux/errno.h>
13+
#include <linux/fwnode.h>
1314
#include <linux/io.h>
1415
#include <linux/module.h>
1516
#include <linux/of.h>
@@ -712,139 +713,26 @@ struct gpio_desc *of_find_gpio(struct device_node *np, const char *con_id,
712713
return desc;
713714
}
714715

715-
/**
716-
* of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API
717-
* @np: device node to get GPIO from
718-
* @chip: GPIO chip whose hog is parsed
719-
* @idx: Index of the GPIO to parse
720-
* @name: GPIO line name
721-
* @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from
722-
* of_find_gpio() or of_parse_own_gpio()
723-
* @dflags: gpiod_flags - optional GPIO initialization flags
724-
*
725-
* Returns:
726-
* GPIO descriptor to use with Linux GPIO API, or one of the errno
727-
* value on the error condition.
728-
*/
729-
static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
730-
struct gpio_chip *chip,
731-
unsigned int idx, const char **name,
732-
unsigned long *lflags,
733-
enum gpiod_flags *dflags)
716+
int of_gpiochip_get_lflags(struct gpio_chip *chip,
717+
struct fwnode_reference_args *gpiospec,
718+
unsigned long *lflags)
734719
{
735-
struct device_node *chip_np;
736720
enum of_gpio_flags xlate_flags;
737-
struct of_phandle_args gpiospec;
721+
struct of_phandle_args args;
738722
struct gpio_desc *desc;
739-
unsigned int i;
740-
u32 tmp;
741-
int ret;
742-
743-
chip_np = dev_of_node(&chip->gpiodev->dev);
744-
if (!chip_np)
745-
return ERR_PTR(-EINVAL);
746-
747-
xlate_flags = 0;
748-
*lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
749-
*dflags = GPIOD_ASIS;
750723

751-
ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp);
752-
if (ret)
753-
return ERR_PTR(ret);
724+
args.np = to_of_node(gpiospec->fwnode);
725+
args.args_count = gpiospec->nargs;
754726

755-
gpiospec.np = chip_np;
756-
gpiospec.args_count = tmp;
757-
758-
for (i = 0; i < tmp; i++) {
759-
ret = of_property_read_u32_index(np, "gpios", idx * tmp + i,
760-
&gpiospec.args[i]);
761-
if (ret)
762-
return ERR_PTR(ret);
763-
}
727+
for (int i = 0; i < args.args_count; i++)
728+
args.args[i] = gpiospec->args[i];
764729

765-
desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags);
730+
desc = of_xlate_and_get_gpiod_flags(chip, &args, &xlate_flags);
766731
if (IS_ERR(desc))
767-
return desc;
732+
return PTR_ERR(desc);
768733

769734
*lflags = of_convert_gpio_flags(xlate_flags);
770735

771-
if (of_property_read_bool(np, "input"))
772-
*dflags |= GPIOD_IN;
773-
else if (of_property_read_bool(np, "output-low"))
774-
*dflags |= GPIOD_OUT_LOW;
775-
else if (of_property_read_bool(np, "output-high"))
776-
*dflags |= GPIOD_OUT_HIGH;
777-
else {
778-
pr_warn("GPIO line %d (%pOFn): no hogging state specified, bailing out\n",
779-
desc_to_gpio(desc), np);
780-
return ERR_PTR(-EINVAL);
781-
}
782-
783-
if (name && of_property_read_string(np, "line-name", name))
784-
*name = np->name;
785-
786-
return desc;
787-
}
788-
789-
/**
790-
* of_gpiochip_add_hog - Add all hogs in a hog device node
791-
* @chip: gpio chip to act on
792-
* @hog: device node describing the hogs
793-
*
794-
* Returns:
795-
* 0 on success, or negative errno on failure.
796-
*/
797-
static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog)
798-
{
799-
enum gpiod_flags dflags;
800-
struct gpio_desc *desc;
801-
unsigned long lflags;
802-
const char *name;
803-
unsigned int i;
804-
int ret;
805-
806-
for (i = 0;; i++) {
807-
desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags);
808-
if (IS_ERR(desc))
809-
break;
810-
811-
ret = gpiod_hog(desc, name, lflags, dflags);
812-
if (ret < 0)
813-
return ret;
814-
815-
#ifdef CONFIG_OF_DYNAMIC
816-
WRITE_ONCE(desc->hog, hog);
817-
#endif
818-
}
819-
820-
return 0;
821-
}
822-
823-
/**
824-
* of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
825-
* @chip: gpio chip to act on
826-
*
827-
* This is only used by of_gpiochip_add to request/set GPIO initial
828-
* configuration.
829-
*
830-
* Returns:
831-
* 0 on success, or negative errno on failure.
832-
*/
833-
static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
834-
{
835-
int ret;
836-
837-
for_each_available_child_of_node_scoped(dev_of_node(&chip->gpiodev->dev), np) {
838-
if (!of_property_read_bool(np, "gpio-hog"))
839-
continue;
840-
841-
ret = of_gpiochip_add_hog(chip, np);
842-
if (ret < 0)
843-
return ret;
844-
845-
of_node_set_flag(np, OF_POPULATED);
846-
}
847-
848736
return 0;
849737
}
850738

@@ -899,7 +787,7 @@ static int of_gpio_notify(struct notifier_block *nb, unsigned long action,
899787
if (!gdev)
900788
return NOTIFY_DONE; /* not for us */
901789

902-
ret = of_gpiochip_add_hog(gpio_device_get_chip(gdev), rd->dn);
790+
ret = gpiochip_add_hog(gpio_device_get_chip(gdev), of_fwnode_handle(rd->dn));
903791
if (ret < 0) {
904792
pr_err("%s: failed to add hogs for %pOF\n", __func__,
905793
rd->dn);
@@ -1178,9 +1066,10 @@ int of_gpiochip_add(struct gpio_chip *chip)
11781066

11791067
of_node_get(np);
11801068

1181-
ret = of_gpiochip_scan_gpios(chip);
1182-
if (ret)
1183-
of_node_put(np);
1069+
for_each_available_child_of_node_scoped(np, child) {
1070+
if (of_property_read_bool(child, "gpio-hog"))
1071+
of_node_set_flag(child, OF_POPULATED);
1072+
}
11841073

11851074
return ret;
11861075
}

drivers/gpio/gpiolib-of.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
struct device_node;
1212
struct fwnode_handle;
13+
struct fwnode_reference_args;
1314

1415
struct gpio_chip;
1516
struct gpio_desc;
@@ -24,6 +25,9 @@ int of_gpiochip_add(struct gpio_chip *gc);
2425
void of_gpiochip_remove(struct gpio_chip *gc);
2526
bool of_gpiochip_instance_match(struct gpio_chip *gc, unsigned int index);
2627
int of_gpio_count(const struct fwnode_handle *fwnode, const char *con_id);
28+
int of_gpiochip_get_lflags(struct gpio_chip *chip,
29+
struct fwnode_reference_args *gpiospec,
30+
unsigned long *lflags);
2731
#else
2832
static inline struct gpio_desc *of_find_gpio(struct device_node *np,
2933
const char *con_id,
@@ -44,6 +48,12 @@ static inline int of_gpio_count(const struct fwnode_handle *fwnode,
4448
{
4549
return 0;
4650
}
51+
static inline int of_gpiochip_get_lflags(struct gpio_chip *chip,
52+
struct fwnode_reference_args *gpiospec,
53+
unsigned long *lflags)
54+
{
55+
return -ENOENT;
56+
}
4757
#endif /* CONFIG_OF_GPIO */
4858

4959
extern struct notifier_block gpio_of_notifier;

0 commit comments

Comments
 (0)