Skip to content

Commit 1e4f6db

Browse files
author
Bartosz Golaszewski
committed
gpiolib: support shared GPIOs in core subsystem code
As the final step in adding official support for shared GPIOs, enable the previously added elements in core GPIO subsystem code. Set-up shared GPIOs when adding a GPIO chip, tear it down on removal and check if a GPIO descriptor looked up during the firmware-node stage is shared and fall-back to machine lookup in this case. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20251112-gpio-shared-v4-5-b51f97b1abd8@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
1 parent e992d54 commit 1e4f6db

1 file changed

Lines changed: 41 additions & 9 deletions

File tree

drivers/gpio/gpiolib.c

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "gpiolib-acpi.h"
3838
#include "gpiolib-cdev.h"
3939
#include "gpiolib-of.h"
40+
#include "gpiolib-shared.h"
4041
#include "gpiolib-swnode.h"
4142
#include "gpiolib-sysfs.h"
4243
#include "gpiolib.h"
@@ -1200,6 +1201,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
12001201
if (ret)
12011202
goto err_remove_irqchip_mask;
12021203

1204+
ret = gpio_device_setup_shared(gdev);
1205+
if (ret)
1206+
goto err_remove_irqchip;
1207+
12031208
/*
12041209
* By first adding the chardev, and then adding the device,
12051210
* we get a device node entry in sysfs under
@@ -1211,10 +1216,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
12111216
if (gpiolib_initialized) {
12121217
ret = gpiochip_setup_dev(gdev);
12131218
if (ret)
1214-
goto err_remove_irqchip;
1219+
goto err_teardown_shared;
12151220
}
1221+
12161222
return 0;
12171223

1224+
err_teardown_shared:
1225+
gpio_device_teardown_shared(gdev);
12181226
err_remove_irqchip:
12191227
gpiochip_irqchip_remove(gc);
12201228
err_remove_irqchip_mask:
@@ -1283,6 +1291,7 @@ void gpiochip_remove(struct gpio_chip *gc)
12831291
/* Numb the device, cancelling all outstanding operations */
12841292
rcu_assign_pointer(gdev->chip, NULL);
12851293
synchronize_srcu(&gdev->srcu);
1294+
gpio_device_teardown_shared(gdev);
12861295
gpiochip_irqchip_remove(gc);
12871296
acpi_gpiochip_remove(gc);
12881297
of_gpiochip_remove(gc);
@@ -4652,11 +4661,29 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
46524661
scoped_guard(srcu, &gpio_devices_srcu) {
46534662
desc = gpiod_fwnode_lookup(fwnode, consumer, con_id, idx,
46544663
&flags, &lookupflags);
4664+
if (!IS_ERR_OR_NULL(desc) &&
4665+
test_bit(GPIOD_FLAG_SHARED, &desc->flags)) {
4666+
/*
4667+
* We're dealing with a GPIO shared by multiple
4668+
* consumers. This is the moment to add the machine
4669+
* lookup table for the proxy device as previously
4670+
* we only knew the consumer's fwnode.
4671+
*/
4672+
ret = gpio_shared_add_proxy_lookup(consumer, lookupflags);
4673+
if (ret)
4674+
return ERR_PTR(ret);
4675+
4676+
/* Trigger platform lookup for shared GPIO proxy. */
4677+
desc = ERR_PTR(-ENOENT);
4678+
/* Trigger it even for fwnode-only gpiod_get(). */
4679+
platform_lookup_allowed = true;
4680+
}
4681+
46554682
if (gpiod_not_found(desc) && platform_lookup_allowed) {
46564683
/*
46574684
* Either we are not using DT or ACPI, or their lookup
4658-
* did not return a result. In that case, use platform
4659-
* lookup as a fallback.
4685+
* did not return a result or this is a shared GPIO. In
4686+
* that case, use platform lookup as a fallback.
46604687
*/
46614688
dev_dbg(consumer,
46624689
"using lookup tables for GPIO lookup\n");
@@ -4679,14 +4706,19 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
46794706
return ERR_PTR(ret);
46804707

46814708
/*
4682-
* This happens when there are several consumers for
4683-
* the same GPIO line: we just return here without
4684-
* further initialization. It is a bit of a hack.
4685-
* This is necessary to support fixed regulators.
4709+
* This happens when there are several consumers for the same
4710+
* GPIO line: we just return here without further
4711+
* initialization. It's a hack introduced long ago to support
4712+
* fixed regulators. We now have a better solution with
4713+
* automated scanning where affected platforms just need to
4714+
* select the provided Kconfig option.
46864715
*
4687-
* FIXME: Make this more sane and safe.
4716+
* FIXME: Remove the GPIOD_FLAGS_BIT_NONEXCLUSIVE flag after
4717+
* making sure all platforms use the new mechanism.
46884718
*/
4689-
dev_info(consumer, "nonexclusive access to GPIO for %s\n", name);
4719+
dev_info(consumer,
4720+
"nonexclusive access to GPIO for %s, consider updating your code to using gpio-shared-proxy\n",
4721+
name);
46904722
return desc;
46914723
}
46924724

0 commit comments

Comments
 (0)