From 2f4d3e293392571e02b106c8b431b638bd029276 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 1 Sep 2023 16:40:32 +0300 Subject: gpio: pca953x: Drop unused fields in struct pca953x_platform_data New code should solely use firmware nodes for the specifics and not any callbacks. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- include/linux/platform_data/pca953x.h | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'include') diff --git a/include/linux/platform_data/pca953x.h b/include/linux/platform_data/pca953x.h index 96c1a14ab365..3c3787c4d96c 100644 --- a/include/linux/platform_data/pca953x.h +++ b/include/linux/platform_data/pca953x.h @@ -11,21 +11,8 @@ struct pca953x_platform_data { /* number of the first GPIO */ unsigned gpio_base; - /* initial polarity inversion setting */ - u32 invert; - /* interrupt base */ int irq_base; - - void *context; /* param to setup/teardown */ - - int (*setup)(struct i2c_client *client, - unsigned gpio, unsigned ngpio, - void *context); - void (*teardown)(struct i2c_client *client, - unsigned gpio, unsigned ngpio, - void *context); - const char *const *names; }; #endif /* _LINUX_PCA953X_H */ -- cgit v1.2.3 From f42dafe3da0cd887c9d2aaa59576f2a92ee4d876 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sun, 3 Sep 2023 21:06:57 +0200 Subject: gpiolib: unexport gpiod_set_transitory() There are no and never have been any users of gpiod_set_transitory() outside the core GPIOLIB code. Make it private. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 1 - drivers/gpio/gpiolib.h | 2 ++ include/linux/gpio/consumer.h | 8 -------- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 40a0022ea719..edffa0d2acaa 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2700,7 +2700,6 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) PIN_CONFIG_PERSIST_STATE, !transitory); } -EXPORT_SYMBOL_GPL(gpiod_set_transitory); /** * gpiod_is_active_low - test whether a GPIO is active-low or not diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index a0a67569300b..d1c94bd571c6 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -144,6 +144,8 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, struct gpio_array *array_info, unsigned long *value_bitmap); +int gpiod_set_transitory(struct gpio_desc *desc, bool transitory); + extern spinlock_t gpio_lock; extern struct list_head gpio_devices; diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 1c4385a00f88..6cc345440a5b 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -159,7 +159,6 @@ int gpiod_set_raw_array_value_cansleep(unsigned int array_size, int gpiod_set_config(struct gpio_desc *desc, unsigned long config); int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce); -int gpiod_set_transitory(struct gpio_desc *desc, bool transitory); void gpiod_toggle_active_low(struct gpio_desc *desc); int gpiod_is_active_low(const struct gpio_desc *desc); @@ -494,13 +493,6 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned int deboun return -ENOSYS; } -static inline int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) -{ - /* GPIO can never have been requested */ - WARN_ON(desc); - return -ENOSYS; -} - static inline void gpiod_toggle_active_low(struct gpio_desc *desc) { /* GPIO can never have been requested */ -- cgit v1.2.3 From 8de54392b849a612f337044d81d9859ee95ab871 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 1 Sep 2023 13:35:20 +0200 Subject: gpiolib: remove stray newline in gpio/driver.h Fix a double newline in the GPIO provider header. Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 4f0c5d62c8f3..1571cfca65e7 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -764,7 +764,6 @@ void gpiochip_free_own_desc(struct gpio_desc *desc); int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset); - struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); #else /* CONFIG_GPIOLIB */ -- cgit v1.2.3 From 37d42ab3924919652858f836a80ab49ec7d11f1e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 1 Sep 2023 13:34:58 +0200 Subject: gpiolib: remove unnecessary extern specifiers from the driver header 'extern' doesn't do anything for function declarations. Remove it. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko Reviewed-by: Linus Walleij --- include/linux/gpio/driver.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 1571cfca65e7..b721422f4bfa 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -529,8 +529,7 @@ struct gpio_chip { #endif /* CONFIG_OF_GPIO */ }; -extern const char *gpiochip_is_requested(struct gpio_chip *gc, - unsigned int offset); +const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset); /** * for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range @@ -549,9 +548,9 @@ extern const char *gpiochip_is_requested(struct gpio_chip *gc, for_each_requested_gpio_in_range(chip, i, 0, chip->ngpio, label) /* add/remove chips */ -extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, - struct lock_class_key *lock_key, - struct lock_class_key *request_key); +int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + struct lock_class_key *lock_key, + struct lock_class_key *request_key); /** * gpiochip_add_data() - register a gpio_chip @@ -599,13 +598,13 @@ static inline int gpiochip_add(struct gpio_chip *gc) { return gpiochip_add_data(gc, NULL); } -extern void gpiochip_remove(struct gpio_chip *gc); -extern int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data, - struct lock_class_key *lock_key, - struct lock_class_key *request_key); +void gpiochip_remove(struct gpio_chip *gc); +int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, + void *data, struct lock_class_key *lock_key, + struct lock_class_key *request_key); -extern struct gpio_chip *gpiochip_find(void *data, - int (*match)(struct gpio_chip *gc, void *data)); +struct gpio_chip *gpiochip_find(void *data, + int (*match)(struct gpio_chip *gc, void *data)); bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset); -- cgit v1.2.3 From fe4fa2e4f7d0722c179fffa25911ea35cafadce2 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 1 Sep 2023 13:29:25 +0200 Subject: gpiolib: make gpiochip_get_desc() public It makes sense for a GPIO driver to want to get its own descriptor without requesting it. After all, the driver knows that it'll still be valid. Let's move this helper to linux/gpio/driver.h. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko Acked-by: Linus Walleij --- drivers/gpio/gpiolib.h | 2 -- include/linux/gpio/driver.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index d1c94bd571c6..9bff5c2cf720 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -122,8 +122,6 @@ struct gpio_array { unsigned long invert_mask[]; }; -struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); - #define for_each_gpio_desc(gc, desc) \ for (unsigned int __i = 0; \ __i < gc->ngpio && (desc = gpiochip_get_desc(gc, __i)); \ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index b721422f4bfa..8f0859ba7065 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -757,6 +757,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, enum gpiod_flags dflags); void gpiochip_free_own_desc(struct gpio_desc *desc); +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); + #ifdef CONFIG_GPIOLIB /* lock/unlock as IRQ */ -- cgit v1.2.3 From 968118fcf0546ef74cf306bf8f8c1e06efff10e3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 12 Sep 2023 10:44:52 +0200 Subject: OMAP/gpio: drop MPUIO static base The OMAP GPIO driver hardcodes the MPIO chip base, but there is no point: we have already moved all consumers over to using descriptor look-ups. Drop the MPUIO GPIO base and use dynamic assignment. Root out the unused instances of the OMAP_MPUIO() macro and delete the unused OMAP_GPIO_IS_MPUIO() macro. Signed-off-by: Linus Walleij Reviewed-by: Tony Lindgren Tested-by: Janusz Krzysztofik Signed-off-by: Bartosz Golaszewski --- arch/arm/mach-omap1/board-palmte.c | 5 ----- drivers/gpio/gpio-omap.c | 3 +-- include/linux/platform_data/gpio-omap.h | 3 --- 3 files changed, 1 insertion(+), 10 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 7e061d671fde..c917cb2c6e17 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -51,11 +51,6 @@ #define PALMTE_HDQ_GPIO 11 #define PALMTE_HEADPHONES_GPIO 14 #define PALMTE_SPEAKER_GPIO 15 -#define PALMTE_DC_GPIO OMAP_MPUIO(2) -#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4) -#define PALMTE_MMC1_GPIO OMAP_MPUIO(6) -#define PALMTE_MMC2_GPIO OMAP_MPUIO(7) -#define PALMTE_MMC3_GPIO OMAP_MPUIO(11) static const unsigned int palmte_keymap[] = { KEY(0, 0, KEY_F1), /* Calendar */ diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 8889755e2d03..76d5d87e9681 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1048,15 +1048,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct device *pm_dev) bank->chip.label = "mpuio"; if (bank->regs->wkup_en) bank->chip.parent = &omap_mpuio_device.dev; - bank->chip.base = OMAP_MPUIO(0); } else { label = devm_kasprintf(bank->chip.parent, GFP_KERNEL, "gpio-%d-%d", gpio, gpio + bank->width - 1); if (!label) return -ENOMEM; bank->chip.label = label; - bank->chip.base = -1; } + bank->chip.base = -1; bank->chip.ngpio = bank->width; irq = &bank->chip.irq; diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h index f377817ce75c..cdd8cfb424f5 100644 --- a/include/linux/platform_data/gpio-omap.h +++ b/include/linux/platform_data/gpio-omap.h @@ -144,9 +144,6 @@ #define OMAP_MAX_GPIO_LINES 192 -#define OMAP_MPUIO(nr) (OMAP_MAX_GPIO_LINES + (nr)) -#define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES) - #ifndef __ASSEMBLER__ struct omap_gpio_reg_offs { u16 revision; -- cgit v1.2.3 From 36aa129f221c9070afd8dff03154ab49702a5b1b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Sep 2023 16:29:21 +0200 Subject: gpiolib: make gpio_device_get() and gpio_device_put() public In order to start migrating away from accessing struct gpio_chip by users other than their owners, let's first make the reference management functions for the opaque struct gpio_device public in the driver.h header. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 24 ++++++++++++++++++++++++ drivers/gpio/gpiolib.h | 10 ---------- include/linux/gpio/driver.h | 3 +++ 3 files changed, 27 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7c27a1efc1b0..c9d8f6b57771 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1058,6 +1058,30 @@ static struct gpio_chip *find_chip_by_name(const char *name) return gpiochip_find((void *)name, gpiochip_match_name); } +/** + * gpio_device_get() - Increase the reference count of this GPIO device + * @gdev: GPIO device to increase the refcount for + * + * Returns: + * Pointer to @gdev. + */ +struct gpio_device *gpio_device_get(struct gpio_device *gdev) +{ + return to_gpio_device(get_device(&gdev->dev)); +} +EXPORT_SYMBOL_GPL(gpio_device_get); + +/** + * gpio_device_put() - Decrease the reference count of this GPIO device and + * possibly free all resources associated with it. + * @gdev: GPIO device to decrease the reference count for + */ +void gpio_device_put(struct gpio_device *gdev) +{ + put_device(&gdev->dev); +} +EXPORT_SYMBOL_GPL(gpio_device_put); + #ifdef CONFIG_GPIOLIB_IRQCHIP /* diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 9bff5c2cf720..3ccacf3c1288 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -86,16 +86,6 @@ static inline struct gpio_device *to_gpio_device(struct device *dev) return container_of(dev, struct gpio_device, dev); } -static inline struct gpio_device *gpio_device_get(struct gpio_device *gdev) -{ - return to_gpio_device(get_device(&gdev->dev)); -} - -static inline void gpio_device_put(struct gpio_device *gdev) -{ - put_device(&gdev->dev); -} - /* gpio suffixes used for ACPI and device tree lookup */ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 8f0859ba7065..a2060dc3344b 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -606,6 +606,9 @@ int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *gc, void *data)); +struct gpio_device *gpio_device_get(struct gpio_device *gdev); +void gpio_device_put(struct gpio_device *gdev); + bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset); void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset); -- cgit v1.2.3 From 9e4555d1e54a18946d7ca363b9fc8ed1fe7dfde4 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Sep 2023 16:29:22 +0200 Subject: gpiolib: add support for scope-based management to gpio_device As the few users that need to get the reference to the GPIO device often release it right after inspecting its properties, let's add support for the automatic reference release to struct gpio_device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko --- include/linux/gpio/driver.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index a2060dc3344b..1cedbc3d3200 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -3,6 +3,8 @@ #define __LINUX_GPIO_DRIVER_H #include +#include +#include #include #include #include @@ -609,6 +611,9 @@ struct gpio_chip *gpiochip_find(void *data, struct gpio_device *gpio_device_get(struct gpio_device *gdev); void gpio_device_put(struct gpio_device *gdev); +DEFINE_FREE(gpio_device_put, struct gpio_device *, + if (IS_ERR_OR_NULL(_T)) gpio_device_put(_T)); + bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset); void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset); -- cgit v1.2.3 From cfe102f63308c8c8e01199a682868a64b83f653e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Sep 2023 16:29:23 +0200 Subject: gpiolib: provide gpio_device_find() gpiochip_find() is wrong and its kernel doc is misleading as the function doesn't return a reference to the gpio_chip but just a raw pointer. The chip itself is not guaranteed to stay alive, in fact it can be deleted at any point. Also: other than GPIO drivers themselves, nobody else has any business accessing gpio_chip structs. Provide a new gpio_device_find() function that returns a real reference to the opaque gpio_device structure that is guaranteed to stay alive for as long as there are active users of it. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 71 +++++++++++++++++++++++++++++++++------------ include/linux/gpio/driver.h | 3 ++ 2 files changed, 56 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c9d8f6b57771..d5bdf9cebb29 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1014,16 +1014,10 @@ void gpiochip_remove(struct gpio_chip *gc) } EXPORT_SYMBOL_GPL(gpiochip_remove); -/** - * gpiochip_find() - iterator for locating a specific gpio_chip - * @data: data to pass to match function - * @match: Callback function to check gpio_chip +/* + * FIXME: This will be removed soon. * - * Similar to bus_find_device. It returns a reference to a gpio_chip as - * determined by a user supplied @match callback. The callback should return - * 0 if the device doesn't match and non-zero if it does. If the callback is - * non-zero, this function will return to the caller and not iterate over any - * more gpio_chips. + * This function is depracated, don't use. */ struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *gc, @@ -1031,21 +1025,62 @@ struct gpio_chip *gpiochip_find(void *data, { struct gpio_device *gdev; struct gpio_chip *gc = NULL; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - list_for_each_entry(gdev, &gpio_devices, list) - if (gdev->chip && match(gdev->chip, data)) { - gc = gdev->chip; - break; - } - spin_unlock_irqrestore(&gpio_lock, flags); + gdev = gpio_device_find(data, match); + if (gdev) { + gc = gdev->chip; + gpio_device_put(gdev); + } return gc; } EXPORT_SYMBOL_GPL(gpiochip_find); +/** + * gpio_device_find() - find a specific GPIO device + * @data: data to pass to match function + * @match: Callback function to check gpio_chip + * + * Returns: + * New reference to struct gpio_device. + * + * Similar to bus_find_device(). It returns a reference to a gpio_device as + * determined by a user supplied @match callback. The callback should return + * 0 if the device doesn't match and non-zero if it does. If the callback + * returns non-zero, this function will return to the caller and not iterate + * over any more gpio_devices. + * + * The callback takes the GPIO chip structure as argument. During the execution + * of the callback function the chip is protected from being freed. TODO: This + * actually has yet to be implemented. + * + * If the function returns non-NULL, the returned reference must be freed by + * the caller using gpio_device_put(). + */ +struct gpio_device *gpio_device_find(void *data, + int (*match)(struct gpio_chip *gc, + void *data)) +{ + struct gpio_device *gdev; + + /* + * Not yet but in the future the spinlock below will become a mutex. + * Annotate this function before anyone tries to use it in interrupt + * context like it happened with gpiochip_find(). + */ + might_sleep(); + + guard(spinlock_irqsave)(&gpio_lock); + + list_for_each_entry(gdev, &gpio_devices, list) { + if (gdev->chip && match(gdev->chip, data)) + return gpio_device_get(gdev); + } + + return NULL; +} +EXPORT_SYMBOL_GPL(gpio_device_find); + static int gpiochip_match_name(struct gpio_chip *gc, void *data) { const char *name = data; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 1cedbc3d3200..6ad1f1a8ef2e 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -608,6 +608,9 @@ int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *gc, void *data)); +struct gpio_device *gpio_device_find(void *data, + int (*match)(struct gpio_chip *gc, void *data)); + struct gpio_device *gpio_device_get(struct gpio_device *gdev); void gpio_device_put(struct gpio_device *gdev); -- cgit v1.2.3 From d62fcd9f1897d587f8f9db3f77ccae8797a44b5d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Sep 2023 16:29:24 +0200 Subject: gpiolib: provide gpio_device_find_by_label() By far the most common way of looking up GPIO devices is using their label. Provide a helpers for that to avoid every user implementing their own matching function. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 21 +++++++++++++++++++++ include/linux/gpio/driver.h | 1 + 2 files changed, 22 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d5bdf9cebb29..0a41f6ee8d33 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -1081,6 +1082,26 @@ struct gpio_device *gpio_device_find(void *data, } EXPORT_SYMBOL_GPL(gpio_device_find); +static int gpio_chip_match_by_label(struct gpio_chip *gc, void *label) +{ + return gc->label && !strcmp(gc->label, label); +} + +/** + * gpio_device_find_by_label() - wrapper around gpio_device_find() finding the + * GPIO device by its backing chip's label + * @label: Label to lookup + * + * Returns: + * Reference to the GPIO device or NULL. Reference must be released with + * gpio_device_put(). + */ +struct gpio_device *gpio_device_find_by_label(const char *label) +{ + return gpio_device_find((void *)label, gpio_chip_match_by_label); +} +EXPORT_SYMBOL_GPL(gpio_device_find_by_label); + static int gpiochip_match_name(struct gpio_chip *gc, void *data) { const char *name = data; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6ad1f1a8ef2e..24996cba6465 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -610,6 +610,7 @@ struct gpio_chip *gpiochip_find(void *data, struct gpio_device *gpio_device_find(void *data, int (*match)(struct gpio_chip *gc, void *data)); +struct gpio_device *gpio_device_find_by_label(const char *label); struct gpio_device *gpio_device_get(struct gpio_device *gdev); void gpio_device_put(struct gpio_device *gdev); -- cgit v1.2.3 From 93548f8bbbbf5b62dbd37c8f61a037a06666787b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Sep 2023 16:29:25 +0200 Subject: gpiolib: provide gpio_device_get_desc() Getting the GPIO descriptor directly from the gpio_chip struct is dangerous as we don't take the reference to the underlying GPIO device. In order to start working towards removing gpiochip_get_desc(), let's provide a safer variant that works with an existing reference to struct gpio_device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 40 +++++++++++++++++++++++++++++++--------- include/linux/gpio/driver.h | 2 ++ 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0a41f6ee8d33..f4fdf620ca74 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -147,27 +147,49 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) } EXPORT_SYMBOL_GPL(gpio_to_desc); +/* This function is deprecated and will be removed soon, don't use. */ +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, + unsigned int hwnum) +{ + return gpio_device_get_desc(gc->gpiodev, hwnum); +} +EXPORT_SYMBOL_GPL(gpiochip_get_desc); + /** - * gpiochip_get_desc - get the GPIO descriptor corresponding to the given - * hardware number for this chip - * @gc: GPIO chip + * gpio_device_get_desc() - get the GPIO descriptor corresponding to the given + * hardware number for this GPIO device + * @gdev: GPIO device to get the descriptor from * @hwnum: hardware number of the GPIO for this chip * * Returns: - * A pointer to the GPIO descriptor or ``ERR_PTR(-EINVAL)`` if no GPIO exists - * in the given chip for the specified hardware number. + * A pointer to the GPIO descriptor or %EINVAL if no GPIO exists in the given + * chip for the specified hardware number or %ENODEV if the underlying chip + * already vanished. + * + * The reference count of struct gpio_device is *NOT* increased like when the + * GPIO is being requested for exclusive usage. It's up to the caller to make + * sure the GPIO device will stay alive together with the descriptor returned + * by this function. */ -struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, - unsigned int hwnum) +struct gpio_desc * +gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum) { - struct gpio_device *gdev = gc->gpiodev; + struct gpio_chip *gc; + + /* + * FIXME: This will be locked once we protect gdev->chip everywhere + * with SRCU. + */ + gc = gdev->chip; + if (!gc) + return ERR_PTR(-ENODEV); if (hwnum >= gdev->ngpio) return ERR_PTR(-EINVAL); return &gdev->descs[hwnum]; } -EXPORT_SYMBOL_GPL(gpiochip_get_desc); +EXPORT_SYMBOL_GPL(gpio_device_get_desc); /** * desc_to_gpio - convert a GPIO descriptor to the integer namespace diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 24996cba6465..3fdf3f14bb13 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -770,6 +770,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, void gpiochip_free_own_desc(struct gpio_desc *desc); struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); +struct gpio_desc * +gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum); #ifdef CONFIG_GPIOLIB -- cgit v1.2.3 From 9b418780844c677669ab474f6f29940ef545c954 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Sep 2023 16:29:26 +0200 Subject: gpiolib: reluctantly provide gpio_device_get_chip() The process of converting all unauthorized users of struct gpio_chip to using dedicated struct gpio_device function will be long so in the meantime we must provide a way of retrieving the pointer to struct gpio_chip from a GPIO device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 21 +++++++++++++++++++++ include/linux/gpio/driver.h | 2 ++ 2 files changed, 23 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f4fdf620ca74..6bb8d4a0b1d4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -220,6 +220,27 @@ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_to_chip); +/** + * gpio_device_get_chip() - Get the gpio_chip implementation of this GPIO device + * @gdev: GPIO device + * + * Returns: + * Address of the GPIO chip backing this device. + * + * Until we can get rid of all non-driver users of struct gpio_chip, we must + * provide a way of retrieving the pointer to it from struct gpio_device. This + * is *NOT* safe as the GPIO API is considered to be hot-unpluggable and the + * chip can dissapear at any moment (unlike reference-counted struct + * gpio_device). + * + * Use at your own risk. + */ +struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev) +{ + return gdev->chip; +} +EXPORT_SYMBOL_GPL(gpio_device_get_chip); + /* dynamic allocation of GPIOs, e.g. on a hotplugged device */ static int gpiochip_find_base(int ngpio) { diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 3fdf3f14bb13..f8ad7f40100c 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -773,6 +773,8 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); struct gpio_desc * gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum); +struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev); + #ifdef CONFIG_GPIOLIB /* lock/unlock as IRQ */ -- cgit v1.2.3 From 74975b4f2836e3cc10eeb6c38a6da54311e1de5b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 26 Sep 2023 16:59:43 +0200 Subject: gpio: acpi: remove acpi_get_and_request_gpiod() With no more users, we can remove acpi_get_and_request_gpiod(). Signed-off-by: Bartosz Golaszewski Reviewed-by: From: Andy Shevchenko Reviewed-by: Mika Westerberg --- drivers/gpio/gpiolib-acpi.c | 28 ---------------------------- include/linux/gpio/consumer.h | 8 -------- 2 files changed, 36 deletions(-) (limited to 'include') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 2ad21f34ee62..25a5f07c8755 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -162,34 +162,6 @@ static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin) return gpio_device_get_desc(gdev, pin); } -/** - * acpi_get_and_request_gpiod - Translate ACPI GPIO pin to GPIO descriptor and - * hold a refcount to the GPIO device. - * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") - * @pin: ACPI GPIO pin number (0-based, controller-relative) - * @label: Label to pass to gpiod_request() - * - * This function is a simple pass-through to acpi_get_gpiod(), except that - * as it is intended for use outside of the GPIO layer (in a similar fashion to - * gpiod_get_index() for example) it also holds a reference to the GPIO device. - */ -struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char *label) -{ - struct gpio_desc *gpio; - int ret; - - gpio = acpi_get_gpiod(path, pin); - if (IS_ERR(gpio)) - return gpio; - - ret = gpiod_request(gpio, label); - if (ret) - return ERR_PTR(ret); - - return gpio; -} -EXPORT_SYMBOL_GPL(acpi_get_and_request_gpiod); - static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) { struct acpi_gpio_event *event = data; diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 6cc345440a5b..db2dfbae8edb 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -606,8 +606,6 @@ void acpi_dev_remove_driver_gpios(struct acpi_device *adev); int devm_acpi_dev_add_driver_gpios(struct device *dev, const struct acpi_gpio_mapping *gpios); -struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char *label); - #else /* CONFIG_GPIOLIB && CONFIG_ACPI */ #include @@ -625,12 +623,6 @@ static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, return -ENXIO; } -static inline struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, - char *label) -{ - return ERR_PTR(-ENOSYS); -} - #endif /* CONFIG_GPIOLIB && CONFIG_ACPI */ -- cgit v1.2.3 From 668706b10c9b8181a53bd8881a77bb81b328ab33 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 11 Oct 2023 23:26:35 +0300 Subject: gpiolib: provide gpio_device_find_by_fwnode() One of the ways of looking up GPIO devices is using their fwnode. Provide a helper for that to avoid every user implementing their own matching function. Reviewed-by: Dipen Patel Tested-by: Dipen Patel Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20231010151709.4104747-2-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 20 ++++++++++++++++++++ include/linux/gpio/driver.h | 1 + 2 files changed, 21 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 191f9c87b4d0..dd18dd56c33c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1145,6 +1145,26 @@ struct gpio_device *gpio_device_find_by_label(const char *label) } EXPORT_SYMBOL_GPL(gpio_device_find_by_label); +static int gpio_chip_match_by_fwnode(struct gpio_chip *gc, void *fwnode) +{ + return device_match_fwnode(&gc->gpiodev->dev, fwnode); +} + +/** + * gpio_device_find_by_fwnode() - wrapper around gpio_device_find() finding + * the GPIO device by its fwnode + * @fwnode: Firmware node to lookup + * + * Returns: + * Reference to the GPIO device or NULL. Reference must be released with + * gpio_device_put(). + */ +struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode) +{ + return gpio_device_find((void *)fwnode, gpio_chip_match_by_fwnode); +} +EXPORT_SYMBOL_GPL(gpio_device_find_by_fwnode); + /** * gpio_device_get() - Increase the reference count of this GPIO device * @gdev: GPIO device to increase the refcount for diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index f8ad7f40100c..ae4162d3f1d3 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -611,6 +611,7 @@ struct gpio_chip *gpiochip_find(void *data, struct gpio_device *gpio_device_find(void *data, int (*match)(struct gpio_chip *gc, void *data)); struct gpio_device *gpio_device_find_by_label(const char *label); +struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode); struct gpio_device *gpio_device_get(struct gpio_device *gdev); void gpio_device_put(struct gpio_device *gdev); -- cgit v1.2.3 From 1559d14977b694570f010854b8192e6de034bc27 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 11 Oct 2023 15:02:02 +0200 Subject: gpiolib: provide gpio_device_to_device() There are users in the kernel who need to retrieve the address of the struct device backing the GPIO device. Currently they needlessly poke in the internals of GPIOLIB. Add a dedicated getter function. Signed-off-by: Bartosz Golaszewski Reviewed-by: Peter Rosin Reviewed-by: Andy Shevchenko Acked-by: Linus Walleij --- drivers/gpio/gpiolib.c | 17 +++++++++++++++++ include/linux/gpio/driver.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index dd18dd56c33c..7e297ae35f8c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1189,6 +1189,23 @@ void gpio_device_put(struct gpio_device *gdev) } EXPORT_SYMBOL_GPL(gpio_device_put); +/** + * gpio_device_to_device() - Retrieve the address of the underlying struct + * device. + * @gdev: GPIO device for which to return the address. + * + * This does not increase the reference count of the GPIO device nor the + * underlying struct device. + * + * Returns: + * Address of struct device backing this GPIO device. + */ +struct device *gpio_device_to_device(struct gpio_device *gdev) +{ + return &gdev->dev; +} +EXPORT_SYMBOL_GPL(gpio_device_to_device); + #ifdef CONFIG_GPIOLIB_IRQCHIP /* diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ae4162d3f1d3..0e40098aa283 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -619,6 +619,8 @@ void gpio_device_put(struct gpio_device *gdev); DEFINE_FREE(gpio_device_put, struct gpio_device *, if (IS_ERR_OR_NULL(_T)) gpio_device_put(_T)); +struct device *gpio_device_to_device(struct gpio_device *gdev); + bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset); void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset); -- cgit v1.2.3 From 370232d096e3fe188e4596f77bc6560636bd40c1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 11 Oct 2023 15:02:03 +0200 Subject: gpiolib: provide gpiod_to_gpio_device() Accessing struct gpio_chip backing a GPIO device is only allowed for the actual providers of that chip. Similarly to how we introduced gpio_device_find() in order to replace the abused gpiochip_find(), let's introduce a counterpart to gpiod_to_chip() that returns a reference to the GPIO device owning the descriptor. This is done in order to later remove gpiod_to_chip() entirely. Signed-off-by: Bartosz Golaszewski Reviewed-by: Peter Rosin Acked-by: Linus Walleij --- drivers/gpio/gpiolib.c | 21 +++++++++++++++++++++ include/linux/gpio/driver.h | 1 + 2 files changed, 22 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7e297ae35f8c..9febaef6767d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -220,6 +220,27 @@ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_to_chip); +/** + * gpiod_to_gpio_device() - Return the GPIO device to which this descriptor + * belongs. + * @desc: Descriptor for which to return the GPIO device. + * + * This *DOES NOT* increase the reference count of the GPIO device as it's + * expected that the descriptor is requested and the users already holds a + * reference to the device. + * + * Returns: + * Address of the GPIO device owning this descriptor. + */ +struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc) +{ + if (!desc) + return NULL; + + return desc->gdev; +} +EXPORT_SYMBOL_GPL(gpiod_to_gpio_device); + /** * gpio_device_get_chip() - Get the gpio_chip implementation of this GPIO device * @gdev: GPIO device diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 0e40098aa283..d231c4f31cb4 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -785,6 +785,7 @@ int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset); struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); +struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc); #else /* CONFIG_GPIOLIB */ -- cgit v1.2.3 From 8c85a102fc4e5c0c942c10677fa43f7a19baa92f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 5 Sep 2023 20:52:55 +0200 Subject: gpiolib: provide gpio_device_get_base() Let's start adding getters for the opaque struct gpio_device. Start with a function allowing to retrieve the base GPIO number. Signed-off-by: Bartosz Golaszewski Acked-by: Linus Walleij --- drivers/gpio/gpiolib.c | 13 +++++++++++++ include/linux/gpio/driver.h | 3 +++ 2 files changed, 16 insertions(+) (limited to 'include') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9febaef6767d..cbafcd95243e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -241,6 +241,19 @@ struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_to_gpio_device); +/** + * gpio_device_get_base() - Get the base GPIO number allocated by this device + * @gdev: GPIO device + * + * Returns: + * First GPIO number in the global GPIO numberspace for this device. + */ +int gpio_device_get_base(struct gpio_device *gdev) +{ + return gdev->base; +} +EXPORT_SYMBOL_GPL(gpio_device_get_base); + /** * gpio_device_get_chip() - Get the gpio_chip implementation of this GPIO device * @gdev: GPIO device diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index d231c4f31cb4..1d454dc944b3 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -787,6 +787,9 @@ void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset); struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc); +/* struct gpio_device getters */ +int gpio_device_get_base(struct gpio_device *gdev); + #else /* CONFIG_GPIOLIB */ #include -- cgit v1.2.3