diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-03-25 20:05:43 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-03-25 20:05:43 -0700 |
| commit | 5143840cef6bb1ec4f334604ecc55130dd196fed (patch) | |
| tree | d4cc1697f19b8a1444f779198c825d5fd8b4c6dc /include | |
| parent | c07666e29be2487b99bbc1fbc109b5cdb57d1713 (diff) | |
| parent | af54a2fbdf45b1fd32cdcab916f422e6d097f430 (diff) | |
Merge tag 'gpio-updates-for-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski:
"There are no new drivers this time but several changes to the core
GPIO framework and various driver updates.
This release cycle, we're starting a relatively straightforward but
tedious rework of the GPIO consumer API: for historical reasons, the
gpiod_set_value() variants would return void. Not only that but the
GPIO provider interface does not even allow drivers to return a value
to GPIO core. This is because initial GPIO controllers would be MMIO
based and could not fail. We've had I2C, SPI and USB controllers for
years too but no way of indicating failures to callers.
This changes the consumer interface, adds new provider callbacks and
starts converting the drivers under drivers/gpio/ to using them. Once
this gets upstream, we'll keep on converting GPIO drivers that live
elsewhere and once there are no more users of the old callbacks, we'll
remove them and rename the new ones to the previous name. I imagine
the last step would happen in one sweeping change like what you did
for the remove_new() -> remove() renaming.
We've also addressed an issue where invalid return values from GPIO
drivers would get propagated to user-space by adding some
GPIO-core-level sanitization. Again: not a complex change but way
overdue.
Other than that: lots of driver and core refactoring, DT-bindings
changes and some other minor changes like coding style fixes or header
reordering.
GPIO core:
- add sanitization of return values of GPIO provider callbacks so
that invalid ones don't get propagated to user-space
- add new variants of the line setter callbacks for GPIO providers
that return an integer and allow to indicate driver errors to the
GPIO core
- change the interface of all gpiod_set_value() variants to return an
integer thus becoming able to indicate failures in the underlying
layer to callers
- drop unneeded ERR_CAST in gpiolib-acpi
- use for_each_if() where applicable
- provide gpiod_multi_set_value_cansleep() as a new, simpler
interface to gpiod_set_array_value_cansleep() and use it across
several drivers treewide
- reduce the number of atomic reads of the descriptor flags in
gpiolib debugfs code
- simplify for_each_hwgpio_in_range() and
for_each_requested_gpio_in_range()
- add support for three-cell GPIO specifiers in GPIO OF code
- don't build HTE (hardware timestamp engine) GPIO code with the HTE
subsystem disabled in Kconfig
- unduplicate calls to gpiod_direction_input_nonotify()
- rework the handling of the valid_mask property of GPIO chips: don't
allow drivers to set it as it should only be handled by GPIO core
and start actually enforcing it in GPIO core for *all* drivers, not
only the ones implementing a custom request() callback
- get the `ngpios` property from the fwnode of the GPIO chip, not its
device in order to handle multi-bank GPIO chips
Driver improvements:
- convert a part of the GPIO drivers under drivers/gpio/ to using the
new value setter callbacks
- convert several drivers to using automatic lock guards from
cleanup.h
- allow building gpio-bt8xx with COMPILE_TEST=y
- refactor gpio-74x164 (use devres, cleanup helpers, __counted_by()
and bits.h macros)
- refactor gpio-latch (use generic device properties, lock guards and
some local variables for better readability)
- refactor gpio-xilinx (improve the usage of the bitmap API)
- support multiple virtual GPIO controller instances in gpio-virtio
- allow gpio-regmap to use the standard `ngpios` property from
GPIOLIB
- factor out the common code for synchronous probing of virtual GPIO
devices into its own library
- use str_enable_disable(), str_high_low() and other string helpers
where applicable
- extend the gpio-mmio abstraction layer to allow calling into the
pinctrl back-end when setting direction
- convert gpio-vf610 to using the gpio-mmio library
- use more devres in gpio-adnp
- add support for reset-gpios in gpio-pcf857x
- add support for more models to gpio-loongson-64bit
DT bindings:
- add new compatibles to gpio-vf610 and gpio-loongson
- add missing gpio-ranges property to gpio-mvebu
- add reset-gpios to nxp,pcf8575
- enable gpio-hog parsing in ast2400-gpio
Misc:
- coding style improvements
- kerneldoc fixes
- includes reordering
- updates to the TODO list"
* tag 'gpio-updates-for-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (119 commits)
gpio: TODO: add an item to track reworking the sysfs interface
gpio: TODO: add an item to track the conversion to the new value setters
gpio: TODO: add delimiters between tasks for better readability
gpio: TODO: remove the pinctrl integration task
gpio: TODO: remove task duplication
gpio: TODO: remove the item about the new debugfs interface
gpio: da9055: use new line value setter callbacks
gpio: da9052: use new line value setter callbacks
gpio: cs5535: use new line value setter callbacks
gpio: crystalcove: use new line value setter callbacks
gpio: cros-ec: use new line value setter callbacks
gpio: creg-snps: use new line value setter callbacks
gpio: cgbc: use new line value setter callbacks
gpio: bt8xx: use new line value setter callbacks
gpio: bt8xx: use lock guards
gpio: bt8xx: allow to build the module with COMPILE_TEST=y
gpio: bd9571mwv: use new line value setter callbacks
gpio: bd71828: use new line value setter callbacks
gpio: bd71815: use new line value setter callbacks
gpio: bcm-kona: use new line value setter callbacks
...
Diffstat (limited to 'include')
| -rw-r--r-- | include/drm/drm_util.h | 16 | ||||
| -rw-r--r-- | include/linux/gpio.h | 4 | ||||
| -rw-r--r-- | include/linux/gpio/consumer.h | 80 | ||||
| -rw-r--r-- | include/linux/gpio/driver.h | 92 | ||||
| -rw-r--r-- | include/linux/gpio/regmap.h | 4 | ||||
| -rw-r--r-- | include/linux/util_macros.h | 15 |
6 files changed, 134 insertions, 77 deletions
diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h index 79952d8c4bba..440199618620 100644 --- a/include/drm/drm_util.h +++ b/include/drm/drm_util.h @@ -36,6 +36,7 @@ #include <linux/kgdb.h> #include <linux/preempt.h> #include <linux/smp.h> +#include <linux/util_macros.h> /* * Use EXPORT_SYMBOL_FOR_TESTS_ONLY() for functions that shall @@ -48,21 +49,6 @@ #endif /** - * 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 - -/** * drm_can_sleep - returns true if currently okay to sleep * * This function shall not be used in new code. 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 db2dfbae8edb..45b651c05b9c 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -3,6 +3,7 @@ #define __LINUX_GPIO_CONSUMER_H #include <linux/bits.h> +#include <linux/err.h> #include <linux/types.h> struct acpi_device; @@ -110,8 +111,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); @@ -119,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, @@ -129,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, @@ -141,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, @@ -151,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, @@ -183,11 +182,9 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #else /* CONFIG_GPIOLIB */ -#include <linux/err.h> +#include <linux/bug.h> #include <linux/kernel.h> -#include <asm/bug.h> - static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; @@ -348,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 */ @@ -375,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, @@ -404,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, @@ -434,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, @@ -463,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, @@ -560,6 +549,31 @@ 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 + +#include <linux/bug.h> + +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, @@ -608,8 +622,6 @@ int devm_acpi_dev_add_driver_gpios(struct device *dev, #else /* CONFIG_GPIOLIB && CONFIG_ACPI */ -#include <linux/err.h> - static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, const struct acpi_gpio_mapping *gpios) { @@ -635,8 +647,6 @@ void gpiod_unexport(struct gpio_desc *desc); #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ -#include <asm/errno.h> - static inline int gpiod_export(struct gpio_desc *desc, bool direction_may_change) { @@ -655,4 +665,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 diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 2dd7cb9cc270..4c0294a9104d 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -14,6 +14,7 @@ #include <linux/property.h> #include <linux/spinlock_types.h> #include <linux/types.h> +#include <linux/util_macros.h> #ifdef CONFIG_GENERIC_MSI_IRQ #include <asm/msi.h> @@ -328,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, @@ -344,10 +346,15 @@ 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 + * "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. + * 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 @@ -394,6 +401,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. * <register width> * 8 * @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep @@ -441,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); @@ -478,6 +492,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; @@ -499,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 @@ -516,11 +523,33 @@ 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: * * Callback to translate a device tree GPIO specifier into a chip- @@ -550,19 +579,29 @@ DEFINE_CLASS(_gpiochip_for_each_data, const char **label, int *i) /** + * 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_in_range(_chip, _i, _base, _size, _label) \ + for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \ + _i < _size; \ + _i++, kfree(_label), _label = NULL) \ + for_each_if(!IS_ERR(_label = gpiochip_dup_line_label(_chip, _base + _i))) + +/** * 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 (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))) {} \ - else +#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 @@ -573,13 +612,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) \ + for_each_if(_label) /* Iterates over all requested GPIO of the given @chip */ #define for_each_requested_gpio(chip, i, label) \ @@ -678,6 +712,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); @@ -713,6 +748,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, @@ -865,7 +901,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) { diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index a9f7b7faf57b..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 @@ -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 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 @@ -5,6 +5,21 @@ #include <linux/math.h> /** + * 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. * @a: The array in which to look for the closest element. Must be sorted |
