Commit ec42a3a9 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski
Browse files

gpio: shared: handle pins shared by child nodes of devices



Shared GPIOs may be assigned to child nodes of device nodes which don't
themselves bind to any struct device. We need to pass the firmware node
that is the actual consumer to gpiolib-shared and compare against it
instead of unconditionally using the fwnode of the consumer device.

Fixes: a060b8c5 ("gpiolib: implement low-level, shared GPIO support")
Reported-by: default avatarJon Hunter <jonathanh@nvidia.com>
Closes: https://lore.kernel.org/all/921ba8ce-b18e-4a99-966d-c763d22081e2@nvidia.com/


Tested-by: default avatarJon Hunter <jonathanh@nvidia.com>
Acked-by: default avatarJon Hunter <jonathanh@nvidia.com>
Link: https://patch.msgid.link/20260318-gpio-shared-xlate-v2-2-0ce34c707e81@oss.qualcomm.com


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
parent 710abda5
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -443,8 +443,8 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer,
}
#endif /* CONFIG_RESET_GPIO */

int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
				 unsigned long lflags)
int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle *fwnode,
				 const char *con_id, unsigned long lflags)
{
	const char *dev_id = dev_name(consumer);
	struct gpiod_lookup_table *lookup;
@@ -458,7 +458,7 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
			if (!ref->fwnode && device_is_compatible(consumer, "reset-gpio")) {
				if (!gpio_shared_dev_is_reset_gpio(consumer, entry, ref))
					continue;
			} else if (!device_match_fwnode(consumer, ref->fwnode)) {
			} else if (fwnode != ref->fwnode) {
				continue;
			}

+5 −2
Original line number Diff line number Diff line
@@ -11,13 +11,15 @@
struct gpio_device;
struct gpio_desc;
struct device;
struct fwnode_handle;

#if IS_ENABLED(CONFIG_GPIO_SHARED)

int gpiochip_setup_shared(struct gpio_chip *gc);
void gpio_device_teardown_shared(struct gpio_device *gdev);
int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
				 unsigned long lflags);
int gpio_shared_add_proxy_lookup(struct device *consumer,
				 struct fwnode_handle *fwnode,
				 const char *con_id, unsigned long lflags);

#else

@@ -29,6 +31,7 @@ static inline int gpiochip_setup_shared(struct gpio_chip *gc)
static inline void gpio_device_teardown_shared(struct gpio_device *gdev) { }

static inline int gpio_shared_add_proxy_lookup(struct device *consumer,
					       struct fwnode_handle *fwnode,
					       const char *con_id,
					       unsigned long lflags)
{
+2 −2
Original line number Diff line number Diff line
@@ -4714,8 +4714,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
			 * lookup table for the proxy device as previously
			 * we only knew the consumer's fwnode.
			 */
			ret = gpio_shared_add_proxy_lookup(consumer, con_id,
							   lookupflags);
			ret = gpio_shared_add_proxy_lookup(consumer, fwnode,
							   con_id, lookupflags);
			if (ret)
				return ERR_PTR(ret);