@@ -177,6 +177,8 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
return ERR_PTR(-ENOMEM);
}
+ gpiod_add_device_link(desc, dev);
+
*dr = desc;
devres_add(dev, dr);
@@ -234,6 +236,8 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
return desc;
}
+ gpiod_add_device_link(desc, dev);
+
*dr = desc;
devres_add(dev, dr);
@@ -4160,6 +4160,20 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
return status;
}
+void gpiod_add_device_link(struct gpio_desc *desc, struct device *consumer)
+{
+ struct device_link *link;
+
+ link = device_link_add(consumer, desc->gdev->dev.parent,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!link) {
+ dev_err(consumer, "failed to create device link to %s\n",
+ dev_name(desc->gdev->dev.parent));
+ } else {
+ desc->consumer = consumer;
+ }
+}
+
/**
* gpiod_get_index - obtain a GPIO from a multi-index GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
@@ -4242,6 +4256,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
return ERR_PTR(status);
}
+ gpiod_add_device_link(desc, dev);
+
return desc;
}
EXPORT_SYMBOL_GPL(gpiod_get_index);
@@ -4625,8 +4641,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_optional);
*/
void gpiod_put(struct gpio_desc *desc)
{
- if (desc)
+ if (desc) {
+ device_link_remove(desc->consumer, desc->gdev->dev.parent);
gpiod_free(desc);
+ }
}
EXPORT_SYMBOL_GPL(gpiod_put);
@@ -215,6 +215,7 @@ extern struct list_head gpio_devices;
struct gpio_desc {
struct gpio_device *gdev;
+ struct device *consumer;
unsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
@@ -241,6 +242,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label);
void gpiod_free(struct gpio_desc *desc);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags);
+void gpiod_add_device_link(struct gpio_desc *desc, struct device *consumer);
int gpiod_hog(struct gpio_desc *desc, const char *name,
unsigned long lflags, enum gpiod_flags dflags);