From c31b87ee1e0e208f046155bbd7b27ac4be5feb66 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Wed, 23 Sep 2026 11:58:19 +0200 Subject: [PATCH] drivers/ioexpander: add an optional pin PWM operation Add an ioe_setpwm operation (guarded by CONFIG_IOEXPANDER_PWM) for expanders that can modulate their outputs, e.g. through a LED driver engine. Assisted-by: Claude Code Signed-off-by: raiden00pl --- .../components/drivers/special/ioexpander.rst | 12 +++++++++ drivers/ioexpander/Kconfig | 8 ++++++ include/nuttx/ioexpander/ioexpander.h | 26 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/Documentation/components/drivers/special/ioexpander.rst b/Documentation/components/drivers/special/ioexpander.rst index 5a4e19af896..8b1a1d9a5ef 100644 --- a/Documentation/components/drivers/special/ioexpander.rst +++ b/Documentation/components/drivers/special/ioexpander.rst @@ -273,6 +273,18 @@ driver operations table (``struct ioexpander_ops_s``): - ``IOEXP_READBUF`` reads the buffered/register value cached by the expander. +Pin PWM control +--------------- + +``CONFIG_IOEXPANDER_PWM`` enables the optional ``ioe_setpwm`` operation. + +.. c:macro:: IOEXP_SETPWM(dev, pin, duty) + + Set a physical pin's duty cycle: ``duty`` is a ``uint16_t`` value from + ``0`` (off) to ``0xffff`` (fully on). Returns 0 on success or a negative + errno on failure. The caller must ensure ``dev->ops->ioe_setpwm`` is + non-NULL; the macro does not check it. Frequency control is not provided. + Multi-pin operations -------------------- diff --git a/drivers/ioexpander/Kconfig b/drivers/ioexpander/Kconfig index a0ff52ec85b..3f6cac94970 100644 --- a/drivers/ioexpander/Kconfig +++ b/drivers/ioexpander/Kconfig @@ -618,6 +618,14 @@ config IOEXPANDER_MULTIPIN This settings enable the definition of routines for optimized simultaneous access to multiple pins. +config IOEXPANDER_PWM + bool "Support pin PWM control" + default n + ---help--- + This setting enables an operation to control the PWM duty cycle + of I/O expander pins, for expanders that can modulate their + outputs (e.g. through a LED driver engine). + endif # IOEXPANDER config DEV_GPIO diff --git a/include/nuttx/ioexpander/ioexpander.h b/include/nuttx/ioexpander/ioexpander.h index 218bd3c34a6..f9fba627495 100644 --- a/include/nuttx/ioexpander/ioexpander.h +++ b/include/nuttx/ioexpander/ioexpander.h @@ -253,6 +253,28 @@ #endif /* CONFIG_IOEXPANDER_MULTIPIN */ +#ifdef CONFIG_IOEXPANDER_PWM + +/**************************************************************************** + * Name: IOEXP_SETPWM + * + * Description: + * Set the pin PWM duty cycle. Optional. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The index of the pin to alter in this call + * duty - The duty cycle, where 0 is off and 0xffff is fully on + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define IOEXP_SETPWM(dev,pin,duty) ((dev)->ops->ioe_setpwm(dev,pin,duty)) + +#endif /* CONFIG_IOEXPANDER_PWM */ + /**************************************************************************** * Name: IOEP_ATTACH * @@ -358,6 +380,10 @@ struct ioexpander_ops_s ioe_callback_t callback, FAR void *arg); CODE int (*ioe_detach)(FAR struct ioexpander_dev_s *dev, FAR void *handle); #endif +#ifdef CONFIG_IOEXPANDER_PWM + CODE int (*ioe_setpwm)(FAR struct ioexpander_dev_s *dev, uint8_t pin, + uint16_t duty); +#endif }; struct ioexpander_dev_s