From 91931af18bd22437e08e2471f5484d6fbdd8ab93 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 10 Feb 2025 16:33:27 -0600 Subject: gpiolib: add gpiod_multi_set_value_cansleep() Add a new gpiod_multi_set_value_cansleep() helper function with fewer parameters than gpiod_set_array_value_cansleep(). Calling gpiod_set_array_value_cansleep() can get quite verbose. In many cases, the first arguments all come from the same struct gpio_descs, so having a separate function where we can just pass that cuts down on the boilerplate. Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20250210-gpio-set-array-helper-v3-1-d6a673674da8@baylibre.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/consumer.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/linux') diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index db2dfbae8edb..5cbd4afd7862 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -3,6 +3,7 @@ #define __LINUX_GPIO_CONSUMER_H #include +#include #include struct acpi_device; @@ -655,4 +656,14 @@ static inline void gpiod_unexport(struct gpio_desc *desc) #endif /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ +static inline int gpiod_multi_set_value_cansleep(struct gpio_descs *descs, + unsigned long *value_bitmap) +{ + if (IS_ERR_OR_NULL(descs)) + return PTR_ERR_OR_ZERO(descs); + + return gpiod_set_array_value_cansleep(descs->ndescs, descs->desc, + descs->info, value_bitmap); +} + #endif -- cgit v1.2.3 From 8893516000b247f91fa2cef34f2a77b609e661a4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 7 Feb 2025 17:07:34 +0200 Subject: gpiolib: Deduplicate some code in for_each_requested_gpio_in_range() Refactor for_each_requested_gpio_in_range() to deduplicate some code which is basically repeats the for_each_hwgpio(). In order to achieve this, split the latter to two, for_each_hwgpio_in_range() and for_each_hwgpio(). Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20250207151149.2119765-2-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 2dd7cb9cc270..314f4241e306 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -550,20 +550,32 @@ DEFINE_CLASS(_gpiochip_for_each_data, const char **label, int *i) /** - * for_each_hwgpio - Iterates over all GPIOs for given chip. + * for_each_hwgpio_in_range - Iterates over all GPIOs in a given range * @_chip: Chip to iterate over. * @_i: Loop counter. + * @_base: First GPIO in the ranger. + * @_size: Amount of GPIOs to check starting from @base. * @_label: Place to store the address of the label if the GPIO is requested. * Set to NULL for unused GPIOs. */ -#define for_each_hwgpio(_chip, _i, _label) \ - for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \ - *_data.i < _chip->ngpio; \ - (*_data.i)++, kfree(*(_data.label)), *_data.label = NULL) \ - if (IS_ERR(*_data.label = \ - gpiochip_dup_line_label(_chip, *_data.i))) {} \ +#define for_each_hwgpio_in_range(_chip, _i, _base, _size, _label) \ + for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \ + *_data.i < _size; \ + (*_data.i)++, kfree(*(_data.label)), *_data.label = NULL) \ + if (IS_ERR(*_data.label = \ + gpiochip_dup_line_label(_chip, _base + *_data.i))) {} \ else +/** + * for_each_hwgpio - Iterates over all GPIOs for given chip. + * @_chip: Chip to iterate over. + * @_i: Loop counter. + * @_label: Place to store the address of the label if the GPIO is requested. + * Set to NULL for unused GPIOs. + */ +#define for_each_hwgpio(_chip, _i, _label) \ + for_each_hwgpio_in_range(_chip, _i, 0, _chip->ngpio, _label) + /** * for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range * @_chip: the chip to query @@ -573,13 +585,8 @@ DEFINE_CLASS(_gpiochip_for_each_data, * @_label: label of current GPIO */ #define for_each_requested_gpio_in_range(_chip, _i, _base, _size, _label) \ - for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \ - *_data.i < _size; \ - (*_data.i)++, kfree(*(_data.label)), *_data.label = NULL) \ - if ((*_data.label = \ - gpiochip_dup_line_label(_chip, _base + *_data.i)) == NULL) {} \ - else if (IS_ERR(*_data.label)) {} \ - else + for_each_hwgpio_in_range(_chip, _i, _base, _size, _label) \ + if (_label == NULL) {} else /* Iterates over all requested GPIO of the given @chip */ #define for_each_requested_gpio(chip, i, label) \ -- cgit v1.2.3 From 767412f092fc6e04147305acd70f15770ece47ec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 7 Feb 2025 17:07:35 +0200 Subject: gpiolib: Simplify implementation of for_each_hwgpio_in_range() The whole purpose of the custom CLASS() is to have possibility to initialise the counter variable _i to 0. This can't be done with simple __free() macro as it will be not allowed by C language. OTOH, the CLASS() operates with the pointers and explicit usage of the scoped variable _data is not needed, since the pointers are kept the same over the iterations. Simplify the implementation of for_each_hwgpio_in_range(). Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20250207151149.2119765-3-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 314f4241e306..89439be2ddaa 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -560,11 +560,9 @@ DEFINE_CLASS(_gpiochip_for_each_data, */ #define for_each_hwgpio_in_range(_chip, _i, _base, _size, _label) \ for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \ - *_data.i < _size; \ - (*_data.i)++, kfree(*(_data.label)), *_data.label = NULL) \ - if (IS_ERR(*_data.label = \ - gpiochip_dup_line_label(_chip, _base + *_data.i))) {} \ - else + _i < _size; \ + _i++, kfree(_label), _label = NULL) \ + if (IS_ERR(_label = gpiochip_dup_line_label(_chip, _base + _i))) {} else /** * for_each_hwgpio - Iterates over all GPIOs for given chip. -- cgit v1.2.3 From b2108fc82a0acda34388bff3e3ee3544013b1623 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Feb 2025 20:24:00 +0200 Subject: drm: Move for_each_if() to util_macros.h for wider use Other subsystem(s) may want to reuse the for_each_if() macro. Move it to util_macros.h to make it globally available. Suggested-by: Bartosz Golaszewski Signed-off-by: Andy Shevchenko Acked-by: Jani Nikula Reviewed-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250213182527.3092371-2-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski --- include/linux/util_macros.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include/linux') diff --git a/include/linux/util_macros.h b/include/linux/util_macros.h index 825487fb66fa..3b570b765b75 100644 --- a/include/linux/util_macros.h +++ b/include/linux/util_macros.h @@ -4,6 +4,21 @@ #include +/** + * for_each_if - helper for handling conditionals in various for_each macros + * @condition: The condition to check + * + * Typical use:: + * + * #define for_each_foo_bar(x, y) \' + * list_for_each_entry(x, y->list, head) \' + * for_each_if(x->something == SOMETHING) + * + * The for_each_if() macro makes the use of for_each_foo_bar() less error + * prone. + */ +#define for_each_if(condition) if (!(condition)) {} else + /** * find_closest - locate the closest element in a sorted array * @x: The reference value. -- cgit v1.2.3 From 23318614f8c146d440e57a69d7171dd8c0d249b7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Feb 2025 20:24:01 +0200 Subject: gpiolib: Switch to use for_each_if() helper The for_each_*() APIs that are conditional can be written shorter and less error prone with for_each_if() helper in use. Switch them to use this helper. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250213182527.3092371-3-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 89439be2ddaa..10544f4a03e5 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_GENERIC_MSI_IRQ #include @@ -562,7 +563,7 @@ DEFINE_CLASS(_gpiochip_for_each_data, for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \ _i < _size; \ _i++, kfree(_label), _label = NULL) \ - if (IS_ERR(_label = gpiochip_dup_line_label(_chip, _base + _i))) {} else + for_each_if(!IS_ERR(_label = gpiochip_dup_line_label(_chip, _base + _i))) /** * for_each_hwgpio - Iterates over all GPIOs for given chip. @@ -584,7 +585,7 @@ DEFINE_CLASS(_gpiochip_for_each_data, */ #define for_each_requested_gpio_in_range(_chip, _i, _base, _size, _label) \ for_each_hwgpio_in_range(_chip, _i, _base, _size, _label) \ - if (_label == NULL) {} else + for_each_if(_label) /* Iterates over all requested GPIO of the given @chip */ #define for_each_requested_gpio(chip, i, label) \ @@ -870,7 +871,7 @@ static inline void gpiochip_unlock_as_irq(struct gpio_chip *gc, #define for_each_gpiochip_node(dev, child) \ device_for_each_child_node(dev, child) \ - if (!fwnode_property_present(child, "gpio-controller")) {} else + for_each_if(fwnode_property_present(child, "gpio-controller")) static inline unsigned int gpiochip_node_count(struct device *dev) { -- cgit v1.2.3 From dea69f2d1cc8d9ecdc72ba350d10a1e71940ef18 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 17 Feb 2025 11:39:21 +0100 Subject: gpiolib: move all includes to the top of gpio/consumer.h We have several conditional includes depending on !CONFIG_GPIOLIB. This is supposed to reduce compilation time with CONFIG_GPIOLIB=y but in practice there's no difference on modern machines. It makes adding new stubs that depend on more than just GPIOLIB harder so move them all to the top, unduplicate them and replace asm/ with preferred linux/ alternatives. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250217103922.151047-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/consumer.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 5cbd4afd7862..0dc49b5fca5c 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -3,7 +3,10 @@ #define __LINUX_GPIO_CONSUMER_H #include +#include #include +#include +#include #include struct acpi_device; @@ -184,11 +187,6 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #else /* CONFIG_GPIOLIB */ -#include -#include - -#include - static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; @@ -609,8 +607,6 @@ int devm_acpi_dev_add_driver_gpios(struct device *dev, #else /* CONFIG_GPIOLIB && CONFIG_ACPI */ -#include - static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, const struct acpi_gpio_mapping *gpios) { @@ -636,8 +632,6 @@ void gpiod_unexport(struct gpio_desc *desc); #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ -#include - static inline int gpiod_export(struct gpio_desc *desc, bool direction_may_change) { -- cgit v1.2.3 From 63cdf6241ac7edd94cb4cd9a8f1ba2c3c61ed219 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 17 Feb 2025 11:39:22 +0100 Subject: gpiolib: don't build HTE code with CONFIG_HTE disabled Hardware timestamping is only used on tegra186 platforms but we include the code and export the symbols everywhere. Shrink the binary a bit by compiling the relevant functions conditionally. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250217103922.151047-2-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/consumer.h | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 0dc49b5fca5c..0b2b56199c36 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -114,8 +114,6 @@ int gpiod_get_direction(struct gpio_desc *desc); int gpiod_direction_input(struct gpio_desc *desc); int gpiod_direction_output(struct gpio_desc *desc, int value); int gpiod_direction_output_raw(struct gpio_desc *desc, int value); -int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); -int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); /* Value get/set from non-sleeping context */ int gpiod_get_value(const struct gpio_desc *desc); @@ -347,18 +345,6 @@ static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value) WARN_ON(desc); return -ENOSYS; } -static inline int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, - unsigned long flags) -{ - WARN_ON(desc); - return -ENOSYS; -} -static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, - unsigned long flags) -{ - WARN_ON(desc); - return -ENOSYS; -} static inline int gpiod_get_value(const struct gpio_desc *desc) { /* GPIO can never have been requested */ @@ -559,6 +545,28 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #endif /* CONFIG_GPIOLIB */ +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_HTE) +int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); +int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); +#else +static inline int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, + unsigned long flags) +{ + if (!IS_ENABLED(CONFIG_GPIOLIB)) + WARN_ON(desc); + + return -ENOSYS; +} +static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, + unsigned long flags) +{ + if (!IS_ENABLED(CONFIG_GPIOLIB)) + WARN_ON(desc); + + return -ENOSYS; +} +#endif /* CONFIG_GPIOLIB && CONFIG_HTE */ + static inline struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev, struct fwnode_handle *fwnode, -- cgit v1.2.3 From 97673ea38a77e42eaafcf5181c84f6c8d40b97e7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Feb 2025 21:48:48 +0200 Subject: gpio: regmap: Group optional assignments together for better understanding Group ngpio_per_reg, reg_stride, and reg_mask_xlate assignments together with the respective conditional for better understanding what's going on in the code. While at it, mark ngpio_per_reg as (Optional) in the kernel-doc in accordance with what code actually does. Signed-off-by: Andy Shevchenko Reviewed-by: Michael Walle Reviewed-by: Linus Walleij Tested-by: Mathieu Dubois-Briand Reviewed-by: Mathieu Dubois-Briand Link: https://lore.kernel.org/r/20250213195621.3133406-4-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/regmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index a9f7b7faf57b..b9240e4156cc 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -30,7 +30,7 @@ struct regmap; * @reg_dir_out_base: (Optional) out setting register base address * @reg_stride: (Optional) May be set if the registers (of the * same type, dat, set, etc) are not consecutive. - * @ngpio_per_reg: Number of GPIOs per register + * @ngpio_per_reg: (Optional) Number of GPIOs per register * @irq_domain: (Optional) IRQ domain if the controller is * interrupt-capable * @reg_mask_xlate: (Optional) Translates base address and GPIO -- cgit v1.2.3 From db305161880a024a43f4b1cbafa7a294793d7a9e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Feb 2025 21:48:50 +0200 Subject: gpio: regmap: Allow ngpio to be read from the property GPIOLIB supports the case when number of supported GPIOs can be read from the device property. Enable this for drivers that are using GPIO regmap layer. Signed-off-by: Andy Shevchenko Reviewed-by: Michael Walle Reviewed-by: Linus Walleij Tested-by: Mathieu Dubois-Briand Reviewed-by: Mathieu Dubois-Briand Link: https://lore.kernel.org/r/20250213195621.3133406-6-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/regmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index b9240e4156cc..c722c67668c6 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -21,7 +21,7 @@ struct regmap; * If not given, the fwnode of the parent is used. * @label: (Optional) Descriptive name for GPIO controller. * If not given, the name of the device is used. - * @ngpio: Number of GPIOs + * @ngpio: (Optional) Number of GPIOs * @names: (Optional) Array of names for gpios * @reg_dat_base: (Optional) (in) register base address * @reg_set_base: (Optional) set register base address -- cgit v1.2.3 From 69920338f8130da929ade6f93e6fa3e0e68433ee Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Feb 2025 11:51:56 +0100 Subject: gpiolib: sanitize the return value of gpio_chip::request() The return value of the request() callback may be propagated to user-space. If a bad driver returns a positive number, it may confuse user programs. Tighten the API contract and check for positive numbers returned by GPIO controllers. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250210-gpio-sanitize-retvals-v1-2-12ea88506cb2@linaro.org Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 10544f4a03e5..ce22c072337c 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -329,7 +329,8 @@ struct gpio_irq_chip { * @fwnode: optional fwnode providing this controller's properties * @owner: helps prevent removal of modules exporting active GPIOs * @request: optional hook for chip-specific activation, such as - * enabling module power and clock; may sleep + * enabling module power and clock; may sleep; must return 0 on success + * or negative error number on failure * @free: optional hook for chip-specific deactivation, such as * disabling module power and clock; may sleep * @get_direction: returns direction for signal "offset", 0=out, 1=in, -- cgit v1.2.3 From dcf8f3bffa2de2c7f3b5771b63605194ccd2286f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Feb 2025 11:51:57 +0100 Subject: gpiolib: sanitize the return value of gpio_chip::set_config() The return value of the set_config() callback may be propagated to user-space. If a bad driver returns a positive number, it may confuse user programs. Tighten the API contract and check for positive numbers returned by GPIO controllers. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250210-gpio-sanitize-retvals-v1-3-12ea88506cb2@linaro.org Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ce22c072337c..f2145e938b29 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -349,7 +349,8 @@ struct gpio_irq_chip { * @set: assigns output value for signal "offset" * @set_multiple: assigns output values for multiple signals defined by "mask" * @set_config: optional hook for all kinds of settings. Uses the same - * packed config format as generic pinconf. + * packed config format as generic pinconf. Must return 0 on success and + * a negative error number on failure. * @to_irq: optional hook supporting non-static gpiod_to_irq() mappings; * implementation may not sleep * @dbg_show: optional routine to show contents in debugfs; default code -- cgit v1.2.3 From 2145ba374069ee8edc9d29c2a6b56fe4a28a6e2d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 19 Feb 2025 22:04:33 +0100 Subject: gpio: mmio: Add flag for calling pinctrl back-end It turns out that with this flag we can switch over an entire driver to use gpio-mmio instead of a bunch of custom code, also providing get/set_multiple() to it in the process, so it seems like a reasonable feature to add. The generic pin control backend requires us to call the gpiochip_generic_request(), gpiochip_generic_free(), pinctrl_gpio_direction_output() and pinctrl_gpio_direction_input() callbacks, so if the new flag for a pin control back-end is set, we make sure these functions get called as expected. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20250219-vf610-mmio-v3-1-588b64f0b689@linaro.org Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index f2145e938b29..ae96a2f260fb 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -397,6 +397,7 @@ struct gpio_irq_chip { * @reg_dir_in: direction in setting register for generic GPIO * @bgpio_dir_unreadable: indicates that the direction register(s) cannot * be read and we need to rely on out internal state tracking. + * @bgpio_pinctrl: the generic GPIO uses a pin control backend. * @bgpio_bits: number of register bits used for a generic GPIO i.e. * * 8 * @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep @@ -481,6 +482,7 @@ struct gpio_chip { void __iomem *reg_dir_out; void __iomem *reg_dir_in; bool bgpio_dir_unreadable; + bool bgpio_pinctrl; int bgpio_bits; raw_spinlock_t bgpio_lock; unsigned long bgpio_data; @@ -721,6 +723,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ #define BGPIOF_NO_SET_ON_INPUT BIT(6) +#define BGPIOF_PINCTRL_BACKEND BIT(7) /* Call pinctrl direction setters */ #ifdef CONFIG_GPIOLIB_IRQCHIP int gpiochip_irqchip_add_domain(struct gpio_chip *gc, -- cgit v1.2.3 From 007094c83872ed33c1d9e39b3ef7168d85a3f214 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 25 Feb 2025 10:52:10 +0100 Subject: gpiolib: use the required minimum set of headers Andy suggested we should keep a fine-grained scheme for includes and only pull in stuff required within individual ifdef sections. Let's revert commit dea69f2d1cc8 ("gpiolib: move all includes to the top of gpio/consumer.h") and make the headers situation even more fine-grained by only including the first level headers containing requireded symbols except for bug.h where checkpatch.pl warns against including asm/bug.h. Fixes: dea69f2d1cc8 ("gpiolib: move all includes to the top of gpio/consumer.h") Suggested-by: Andy Shevchenko Closes: https://lore.kernel.org/all/Z7XPcYtaA4COHDYj@smile.fi.intel.com/ Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20250225095210.25910-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/consumer.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 0b2b56199c36..824a1717e6d2 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -3,10 +3,7 @@ #define __LINUX_GPIO_CONSUMER_H #include -#include #include -#include -#include #include struct acpi_device; @@ -185,6 +182,9 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #else /* CONFIG_GPIOLIB */ +#include +#include + static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; @@ -549,6 +549,9 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); #else + +#include + static inline int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags) { -- cgit v1.2.3 From 8ce258f62f90cb2d339cc39fa43e5634594a9dfb Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 20 Feb 2025 10:56:59 +0100 Subject: gpiolib: make value setters have return values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the in-kernel consumer interface for GPIOs: make all variants of value setters that don't have a return value, return a signed integer instead. That will allow these routines to indicate failures to callers. This doesn't change the implementation just yet, we'll do it in subsequent commits. We need to update the gpio-latch module as it passes the address of value setters as a function pointer argument and thus cares about its type. Reviewed-by: Linus Walleij Acked-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20250220-gpio-set-retval-v2-2-bc4cfd38dae3@linaro.org Signed-off-by: Bartosz Golaszewski --- include/linux/gpio.h | 4 ++-- include/linux/gpio/consumer.h | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 6270150f4e29..c1ec62c11ed3 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -91,7 +91,7 @@ static inline int gpio_get_value_cansleep(unsigned gpio) } static inline void gpio_set_value_cansleep(unsigned gpio, int value) { - return gpiod_set_raw_value_cansleep(gpio_to_desc(gpio), value); + gpiod_set_raw_value_cansleep(gpio_to_desc(gpio), value); } static inline int gpio_get_value(unsigned gpio) @@ -100,7 +100,7 @@ static inline int gpio_get_value(unsigned gpio) } static inline void gpio_set_value(unsigned gpio, int value) { - return gpiod_set_raw_value(gpio_to_desc(gpio), value); + gpiod_set_raw_value(gpio_to_desc(gpio), value); } static inline int gpio_to_irq(unsigned gpio) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 824a1717e6d2..45b651c05b9c 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -118,7 +118,7 @@ int gpiod_get_array_value(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, unsigned long *value_bitmap); -void gpiod_set_value(struct gpio_desc *desc, int value); +int gpiod_set_value(struct gpio_desc *desc, int value); int gpiod_set_array_value(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, @@ -128,7 +128,7 @@ int gpiod_get_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, unsigned long *value_bitmap); -void gpiod_set_raw_value(struct gpio_desc *desc, int value); +int gpiod_set_raw_value(struct gpio_desc *desc, int value); int gpiod_set_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, @@ -140,7 +140,7 @@ int gpiod_get_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, unsigned long *value_bitmap); -void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); +int gpiod_set_value_cansleep(struct gpio_desc *desc, int value); int gpiod_set_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, @@ -150,7 +150,7 @@ int gpiod_get_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, unsigned long *value_bitmap); -void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); +int gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, struct gpio_array *array_info, @@ -360,10 +360,11 @@ static inline int gpiod_get_array_value(unsigned int array_size, WARN_ON(desc_array); return 0; } -static inline void gpiod_set_value(struct gpio_desc *desc, int value) +static inline int gpiod_set_value(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ WARN_ON(desc); + return 0; } static inline int gpiod_set_array_value(unsigned int array_size, struct gpio_desc **desc_array, @@ -389,10 +390,11 @@ static inline int gpiod_get_raw_array_value(unsigned int array_size, WARN_ON(desc_array); return 0; } -static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) +static inline int gpiod_set_raw_value(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ WARN_ON(desc); + return 0; } static inline int gpiod_set_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, @@ -419,10 +421,11 @@ static inline int gpiod_get_array_value_cansleep(unsigned int array_size, WARN_ON(desc_array); return 0; } -static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) +static inline int gpiod_set_value_cansleep(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ WARN_ON(desc); + return 0; } static inline int gpiod_set_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, @@ -448,11 +451,12 @@ static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size, WARN_ON(desc_array); return 0; } -static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, - int value) +static inline int gpiod_set_raw_value_cansleep(struct gpio_desc *desc, + int value) { /* GPIO can never have been requested */ WARN_ON(desc); + return 0; } static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, -- cgit v1.2.3 From 98ce1eb1fd87ea1b016e0913ef6836ab0139b5c4 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 20 Feb 2025 10:57:02 +0100 Subject: gpiolib: introduce gpio_chip setters that return values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new variants of the set() and set_multiple() callbacks that have integer return values allowing to indicate failures to users of the GPIO consumer API. Until we convert all GPIO providers treewide to using them, they will live in parallel to the existing ones. Make sure that providers cannot define both. Prefer the new ones and only use the old ones as fallback. Reviewed-by: Linus Walleij Acked-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20250220-gpio-set-retval-v2-5-bc4cfd38dae3@linaro.org Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ae96a2f260fb..a2a1b6434321 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -348,6 +348,10 @@ struct gpio_irq_chip { * stores them in "bits", returns 0 on success or negative error * @set: assigns output value for signal "offset" * @set_multiple: assigns output values for multiple signals defined by "mask" + * @set_rv: assigns output value for signal "offset", returns 0 on success or + * negative error value + * @set_multiple_rv: assigns output values for multiple signals defined by + * "mask", returns 0 on success or negative error value * @set_config: optional hook for all kinds of settings. Uses the same * packed config format as generic pinconf. Must return 0 on success and * a negative error number on failure. @@ -445,6 +449,12 @@ struct gpio_chip { void (*set_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits); + int (*set_rv)(struct gpio_chip *gc, + unsigned int offset, + int value); + int (*set_multiple_rv)(struct gpio_chip *gc, + unsigned long *mask, + unsigned long *bits); int (*set_config)(struct gpio_chip *gc, unsigned int offset, unsigned long config); -- cgit v1.2.3 From 6224e7fc1ce75edcd03b56a2e0fd4c1765d5888e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 27 Feb 2025 09:37:47 +0100 Subject: gpiolib: deprecate gpio_chip::set and gpio_chip::set_multiple We now have setter callbacks that allow us to indicate success or failure using the integer return value. Deprecate the older callbacks so that no new code is tempted to use them. Link: https://lore.kernel.org/r/20250227083748.22400-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index a2a1b6434321..783897d94be8 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -346,8 +346,8 @@ struct gpio_irq_chip { * @get: returns value for signal "offset", 0=low, 1=high, or negative error * @get_multiple: reads values for multiple signals defined by "mask" and * stores them in "bits", returns 0 on success or negative error - * @set: assigns output value for signal "offset" - * @set_multiple: assigns output values for multiple signals defined by "mask" + * @set: **DEPRECATED** - please use set_rv() instead + * @set_multiple: **DEPRECATED** - please use set_multiple_rv() instead * @set_rv: assigns output value for signal "offset", returns 0 on success or * negative error value * @set_multiple_rv: assigns output values for multiple signals defined by -- cgit v1.2.3 From bd3ce71078bde4ecbfc60d49c96d1c55de0635cc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 25 Feb 2025 20:40:34 +0100 Subject: gpiolib: of: Handle threecell GPIO chips When describing GPIO controllers in the device tree, the ambition of device tree to describe the hardware may require a three-cell scheme: gpios = <&gpio instance offset flags>; This implements support for this scheme in the gpiolib OF core. Drivers that want to handle multiple gpiochip instances from one OF node need to implement a callback similar to this to determine if a certain gpio chip is a pointer to the right instance (pseudo-code): struct my_gpio { struct gpio_chip gcs[MAX_CHIPS]; }; static bool my_of_node_instance_match(struct gpio_chip *gc unsigned int instance) { struct my_gpio *mg = gpiochip_get_data(gc); if (instance >= MAX_CHIPS) return false; return (gc == &mg->gcs[instance]); } probe() { struct my_gpio *mg; struct gpio_chip *gc; int i, ret; for (i = 0; i++; i < MAX_CHIPS) { gc = &mg->gcs[i]; /* This tells gpiolib we have several instances per node */ gc->of_gpio_n_cells = 3; gc->of_node_instance_match = my_of_node_instance_match; gc->base = -1; ... ret = devm_gpiochip_add_data(dev, gc, mg); if (ret) return ret; } } Rename the "simple" of_xlate function to "twocell" which is closer to what it actually does. In the device tree bindings, the provide node needs to specify #gpio-cells = <3>; where the first cell is the instance number: gpios = <&gpio instance offset flags>; Conversely ranges need to have four cells: gpio-ranges = <&pinctrl instance gpio_offset pin_offset count>; Reviewed-by: Alex Elder Tested-by: Yixun Lan Signed-off-by: Linus Walleij Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250225-gpio-ranges-fourcell-v3-2-860382ba4713@linaro.org Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 783897d94be8..83e0a7e86962 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -531,10 +531,32 @@ struct gpio_chip { /** * @of_gpio_n_cells: * - * Number of cells used to form the GPIO specifier. + * Number of cells used to form the GPIO specifier. The standard is 2 + * cells: + * + * gpios = <&gpio offset flags>; + * + * some complex GPIO controllers instantiate more than one chip per + * device tree node and have 3 cells: + * + * gpios = <&gpio instance offset flags>; + * + * Legacy GPIO controllers may even have 1 cell: + * + * gpios = <&gpio offset>; */ unsigned int of_gpio_n_cells; + /** + * of_node_instance_match: + * + * Determine if a chip is the right instance. Must be implemented by + * any driver using more than one gpio_chip per device tree node. + * Returns true if gc is the instance indicated by i (which is the + * first cell in the phandles for GPIO lines and gpio-ranges). + */ + bool (*of_node_instance_match)(struct gpio_chip *gc, unsigned int i); + /** * @of_xlate: * -- cgit v1.2.3 From f636d4f60ac477187a466a573f947731fa762059 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 5 Mar 2025 15:13:00 +0200 Subject: gpio: Add a valid_mask getter The valid_mask member of the struct gpio_chip is unconditionally written by the GPIO core at driver registration. It shouldn't be directly populated by drivers. This can be prevented by moving it from the struct gpio_chip to struct gpio_device, which is internal to the GPIO core. As a preparatory step, provide a getter function which can be used by those drivers which need the valid_mask information. Signed-off-by: Matti Vaittinen Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/026f9d78502eca883bfe3faeb684e23d5d6c5e84.1741180097.git.mazziesaccount@gmail.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 83e0a7e86962..e3b59fda62e0 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -720,6 +720,7 @@ bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset); /* Sleep persistence inquiry for drivers */ bool gpiochip_line_is_persistent(struct gpio_chip *gc, unsigned int offset); bool gpiochip_line_is_valid(const struct gpio_chip *gc, unsigned int offset); +const unsigned long *gpiochip_query_valid_mask(const struct gpio_chip *gc); /* get driver data */ void *gpiochip_get_data(struct gpio_chip *gc); -- cgit v1.2.3 From 8015443e24e76fac97268603e91c4793970ce657 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 5 Mar 2025 15:13:25 +0200 Subject: gpio: Hide valid_mask from direct assignments The valid_mask member of the struct gpio_chip is unconditionally written by the GPIO core at driver registration. Current documentation does not mention this but just says the valid_mask is used if it's not NULL. This lured me to try populating it directly in the GPIO driver probe instead of using the init_valid_mask() callback. It took some retries with different bitmaps and eventually a bit of code-reading to understand why the valid_mask was not obeyed. I could've avoided this trial and error if the valid_mask was hidden in the struct gpio_device instead of being a visible member of the struct gpio_chip. Help the next developer who decides to directly populate the valid_mask in struct gpio_chip by hiding the valid_mask in struct gpio_device and keep it internal to the GPIO core. Suggested-by: Linus Walleij Signed-off-by: Matti Vaittinen Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/4547ca90d910d60cab3d56d864d59ddde47a5e93.1741180097.git.mazziesaccount@gmail.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index e3b59fda62e0..e6e5304c99ca 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -514,14 +514,6 @@ struct gpio_chip { struct gpio_irq_chip irq; #endif /* CONFIG_GPIOLIB_IRQCHIP */ - /** - * @valid_mask: - * - * If not %NULL, holds bitmask of GPIOs which are valid to be used - * from the chip. - */ - unsigned long *valid_mask; - #if defined(CONFIG_OF_GPIO) /* * If CONFIG_OF_GPIO is enabled, then all GPIO controllers described in -- cgit v1.2.3 From 9b443b68d97983dfb9a92009a5c951364fa35985 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 5 Mar 2025 10:49:39 +0100 Subject: gpiolib: fix kerneldoc Add missing '@' to the kernel doc for the new of_node_instance_match field of struct gpio_chip. Fixes: bd3ce71078bd ("gpiolib: of: Handle threecell GPIO chips") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/all/20250305203929.70283b9b@canb.auug.org.au/ Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250305094939.40011-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index e6e5304c99ca..4c0294a9104d 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -540,7 +540,7 @@ struct gpio_chip { unsigned int of_gpio_n_cells; /** - * of_node_instance_match: + * @of_node_instance_match: * * Determine if a chip is the right instance. Must be implemented by * any driver using more than one gpio_chip per device tree node. -- cgit v1.2.3