* [PATCH 0/2] Support ON Semi CAT9532 @ 2026-09-15 9:20 Alban Bedel 2026-09-15 9:20 ` [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO Alban Bedel 2026-09-15 9:20 ` [PATCH 2/2] gpio: Support ON Semi CAT9532 Alban Bedel 0 siblings, 2 replies; 11+ messages in thread From: Alban Bedel @ 2026-09-15 9:20 UTC (permalink / raw) To: linux-gpio, devicetree, linux-kernel Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Alban Bedel Hi, this small series add support for the CAT9532 LED dimmer from On Semiconductor. Altought marketed as an LED dimmer it is a bit limited in this regard as it only has 2 PWM for 16 pins. As explained in the datasheet it can also be used as an open-drain GPIO controller, and that's how it is used on the hardware I have at hand. This chip doesn't really map to what the gpio-regmap driver expect so it is implemented as it own driver. This approch also allow to later add support for the LED dimmer if desired. Alban Bedel (2): dt-bindings: gpio: Add CAT9532 GPIO gpio: Support ON Semi CAT9532 .../bindings/gpio/onnn,cat9532.yaml | 52 ++++++ drivers/gpio/Kconfig | 10 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-cat9532.c | 173 ++++++++++++++++++ 4 files changed, 236 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml create mode 100644 drivers/gpio/gpio-cat9532.c -- 2.39.5 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO 2026-09-15 9:20 [PATCH 0/2] Support ON Semi CAT9532 Alban Bedel @ 2026-09-15 9:20 ` Alban Bedel 2026-09-15 9:43 ` Linus Walleij ` (2 more replies) 2026-09-15 9:20 ` [PATCH 2/2] gpio: Support ON Semi CAT9532 Alban Bedel 1 sibling, 3 replies; 11+ messages in thread From: Alban Bedel @ 2026-09-15 9:20 UTC (permalink / raw) To: linux-gpio, devicetree, linux-kernel Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Alban Bedel Add devicetree binding document for CAT9532 LED dimmer as GPIO controller. Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> --- .../bindings/gpio/onnn,cat9532.yaml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml diff --git a/Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml b/Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml new file mode 100644 index 0000000000000..6f3e3d0f4f29b --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/onnn,cat9532.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: On Semiconductor CAT9532 LED dimmer as GPIO controller + +maintainers: + - Alban Bedel <alban.bedel@lht.dlh.de> + +properties: + compatible: + const: onnn,cat9532 + + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 2 + + ngpios: + minimum: 1 + maximum: 16 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - ngpios + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + gpio@60 { + compatible = "onnn,cat9532"; + reg = <0x60>; + + gpio-controller; + #gpio-cells = <2>; + + ngpios = <16>; + }; + }; -- 2.39.5 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO 2026-09-15 9:20 ` [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO Alban Bedel @ 2026-09-15 9:43 ` Linus Walleij 2026-09-15 9:47 ` Linus Walleij 2026-09-15 16:42 ` Conor Dooley 2 siblings, 0 replies; 11+ messages in thread From: Linus Walleij @ 2026-09-15 9:43 UTC (permalink / raw) To: Alban Bedel Cc: linux-gpio, devicetree, linux-kernel, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley Hi Alban, thanks for your patch! On Tue, Sep 15, 2026 at 11:21 AM Alban Bedel <alban.bedel@lht.dlh.de> wrote: > Add devicetree binding document for CAT9532 LED dimmer as GPIO > controller. > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> (...) > + ngpios: > + minimum: 1 > + maximum: 16 ngpios is only used to lower the number of externally (on the package) exposed GPIOs in SoC drivers, to avoid enumerating GPIOs not existing on the physical package. It has no place in a discrete circuit like this, don't even define this and hardcode the GPIOs to 16 in the driver. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO 2026-09-15 9:20 ` [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO Alban Bedel 2026-09-15 9:43 ` Linus Walleij @ 2026-09-15 9:47 ` Linus Walleij 2026-09-15 16:42 ` Conor Dooley 2 siblings, 0 replies; 11+ messages in thread From: Linus Walleij @ 2026-09-15 9:47 UTC (permalink / raw) To: Alban Bedel Cc: linux-gpio, devicetree, linux-kernel, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley Hi Alban, another thing! The second patch says that the 9532 is an exclusively (?) open drain GPIO controller. In that case, the example here should show a consumer using the open drain flag with a comment stating that the driver can only provide open drain GPIOs so all consumers must set this flag. #include <dt-bindings/gpio/gpio.h> consumer { gpios = <&gpio 5 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; }; Yours, Linus Walleij ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO 2026-09-15 9:20 ` [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO Alban Bedel 2026-09-15 9:43 ` Linus Walleij 2026-09-15 9:47 ` Linus Walleij @ 2026-09-15 16:42 ` Conor Dooley 2 siblings, 0 replies; 11+ messages in thread From: Conor Dooley @ 2026-09-15 16:42 UTC (permalink / raw) To: Alban Bedel Cc: linux-gpio, devicetree, linux-kernel, Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley [-- Attachment #1: Type: text/plain, Size: 2007 bytes --] On Tue, Sep 15, 2026 at 11:20:45AM +0200, Alban Bedel wrote: > Add devicetree binding document for CAT9532 LED dimmer as GPIO > controller. > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> Some very interesting comments from Sashiko here, about whether this should be handled in another subsystem. At the very least, valid commentary from Linus. pw-bot: changes-requested Thanks, Conor. > --- > .../bindings/gpio/onnn,cat9532.yaml | 52 +++++++++++++++++++ > 1 file changed, 52 insertions(+) > create mode 100644 Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml > > diff --git a/Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml b/Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml > new file mode 100644 > index 0000000000000..6f3e3d0f4f29b > --- /dev/null > +++ b/Documentation/devicetree/bindings/gpio/onnn,cat9532.yaml > @@ -0,0 +1,52 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/gpio/onnn,cat9532.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: On Semiconductor CAT9532 LED dimmer as GPIO controller > + > +maintainers: > + - Alban Bedel <alban.bedel@lht.dlh.de> > + > +properties: > + compatible: > + const: onnn,cat9532 > + > + reg: > + maxItems: 1 > + > + gpio-controller: true > + > + "#gpio-cells": > + const: 2 > + > + ngpios: > + minimum: 1 > + maximum: 16 > + > +required: > + - compatible > + - reg > + - gpio-controller > + - "#gpio-cells" > + - ngpios > + > +additionalProperties: false > + > +examples: > + - | > + i2c { > + #address-cells = <1>; > + #size-cells = <0>; > + > + gpio@60 { > + compatible = "onnn,cat9532"; > + reg = <0x60>; > + > + gpio-controller; > + #gpio-cells = <2>; > + > + ngpios = <16>; > + }; > + }; > -- > 2.39.5 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/2] gpio: Support ON Semi CAT9532 2026-09-15 9:20 [PATCH 0/2] Support ON Semi CAT9532 Alban Bedel 2026-09-15 9:20 ` [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO Alban Bedel @ 2026-09-15 9:20 ` Alban Bedel 2026-09-15 9:51 ` Bartosz Golaszewski 2026-09-15 9:59 ` Linus Walleij 1 sibling, 2 replies; 11+ messages in thread From: Alban Bedel @ 2026-09-15 9:20 UTC (permalink / raw) To: linux-gpio, devicetree, linux-kernel Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Alban Bedel Add support for the CAT9532 LED dimmer from On Semiconductor. Altought marketed as an LED dimmer it is a bit limited in this regard as it only has 2 PWM for 16 pins. As explained in the datasheet it can also be used as an open-drain GPIO controller, and that's how it is used on the hardware I have at hand. This chip doesn't really map to what the gpio-regmap driver expect so it is implemented as it own driver. This approch also allow to later add support for the LED dimmer if desired. Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> --- drivers/gpio/Kconfig | 10 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-cat9532.c | 173 ++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 drivers/gpio/gpio-cat9532.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a48586bb8edba..05b7af675677b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1180,6 +1180,16 @@ config GPIO_ADNP enough to represent all pins, but the driver will assume a register layout for 64 pins (8 registers). +config GPIO_CAT9532 + tristate "CAT9532 GPIO support" + select REGMAP_I2C + help + GPIO driver for ON Semiconductor CAT9532 LED dimmer. + Say yes here to enable the GPIO driver for the CAT9532 chip. + + To compile this driver as a module, choose M here: the module will + be called gpio-cat9532. + config GPIO_FXL6408 tristate "FXL6408 I2C GPIO expander" select GPIO_REGMAP diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index dc9e6d643b5bc..e94d2f57a1f93 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o +obj-$(CONFIG_GPIO_CAT9532) += gpio-cat9532.o obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o diff --git a/drivers/gpio/gpio-cat9532.c b/drivers/gpio/gpio-cat9532.c new file mode 100644 index 0000000000000..973ff74a15b89 --- /dev/null +++ b/drivers/gpio/gpio-cat9532.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/gpio/driver.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spinlock.h> + +struct cat9532 { + struct regmap *regmap; + struct gpio_chip gpio; + + spinlock_t lock; + unsigned int direction; +}; + +#define CAT9532_REG_INPUT0 0 +#define CAT9532_REG_LS0 6 + +/* Set output to Hi-Z, LED is OFF */ +#define CAT9532_LED_OUT_HIZ 0 +/* Set output low */ +#define CAT9532_LED_OUT_LOW 1 +#define CAT9532_LED_OUT_MASK 3 + +static const struct regmap_config cat9532_regmap_cfg = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 9, + /* + * Auto increment can be enabled by setting bit 4 in the + * register address, but we don't really need bulk access. + */ + .use_single_read = true, + .use_single_write = true, + .can_sleep = true, +}; + +static int cat9532_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); + + scoped_guard(spinlock, &cat9532->lock) + if (cat9532->direction & BIT(offset)) + return GPIO_LINE_DIRECTION_OUT; + else + return GPIO_LINE_DIRECTION_IN; +} + +static int cat9532_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); + unsigned int reg = CAT9532_REG_LS0 + (offset >> 2); + unsigned int shift = (offset & 3) << 1; + int err; + + err = regmap_update_bits(cat9532->regmap, reg, + CAT9532_LED_OUT_MASK << shift, + CAT9532_LED_OUT_HIZ << shift); + if (err < 0) + return err; + + scoped_guard(spinlock, &cat9532->lock) + cat9532->direction &= ~BIT(offset); + + return 0; +} + +static int cat9532_gpio_get(struct gpio_chip *chip, + unsigned int offset) +{ + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); + unsigned int reg = CAT9532_REG_INPUT0 + (offset >> 3); + unsigned int mask = BIT(offset & 7); + unsigned int val; + int err; + + err = regmap_read(cat9532->regmap, reg, &val); + if (err < 0) + return err; + + return !!(val & mask); +} + +static int cat9532_gpio_set(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); + unsigned int reg = CAT9532_REG_LS0 + (offset >> 2); + unsigned int shift = (offset & 3) << 1; + unsigned int val; + + val = value ? CAT9532_LED_OUT_HIZ : CAT9532_LED_OUT_LOW; + return regmap_update_bits(cat9532->regmap, reg, + CAT9532_LED_OUT_MASK << shift, + val << shift); +} + +static int cat9532_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); + int err; + + err = cat9532_gpio_set(chip, offset, value); + if (err < 0) + return err; + + scoped_guard(spinlock, &cat9532->lock) + cat9532->direction |= BIT(offset); + + return 0; +} + +static int cat9532_i2c_probe(struct i2c_client *client) +{ + struct cat9532 *cat9532; + struct gpio_chip *chip; + + cat9532 = devm_kzalloc(&client->dev, sizeof(*cat9532), GFP_KERNEL); + if (!cat9532) + return -ENOMEM; + + spin_lock_init(&cat9532->lock); + + cat9532->regmap = devm_regmap_init_i2c(client, &cat9532_regmap_cfg); + if (IS_ERR(cat9532->regmap)) + return dev_err_probe(&client->dev, PTR_ERR(cat9532->regmap), + "failed to initialize regmap\n"); + + chip = &cat9532->gpio; + chip->label = "cat9532"; + chip->parent = &client->dev; + chip->owner = THIS_MODULE; + chip->can_sleep = true; + chip->base = -1; + chip->ngpio = 16; + + chip->get_direction = cat9532_gpio_get_direction; + chip->direction_input = cat9532_gpio_direction_input; + chip->direction_output = cat9532_gpio_direction_output; + chip->get = cat9532_gpio_get; + chip->set = cat9532_gpio_set; + + return devm_gpiochip_add_data(&client->dev, chip, cat9532); +} + +static const struct i2c_device_id cat9532_i2c_id[] = { + { "cat9532" }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, cat9532_i2c_id); + +static const struct of_device_id cat9532_of_match[] = { + { .compatible = "onnn,cat9532" }, + { }, +}; +MODULE_DEVICE_TABLE(of, cat9532_of_match); + +static struct i2c_driver cat9532_i2c_driver = { + .driver = { + .name = "gpio-cat9532", + .of_match_table = cat9532_of_match, + }, + .probe = cat9532_i2c_probe, + .id_table = cat9532_i2c_id, +}; +module_i2c_driver(cat9532_i2c_driver); + +MODULE_DESCRIPTION("On Semiconductor CAT9532 GPIO driver"); +MODULE_AUTHOR("Alban Bedel <alban.bedel@lht.dlh.de>"); +MODULE_LICENSE("GPL"); -- 2.39.5 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] gpio: Support ON Semi CAT9532 2026-09-15 9:20 ` [PATCH 2/2] gpio: Support ON Semi CAT9532 Alban Bedel @ 2026-09-15 9:51 ` Bartosz Golaszewski 2026-09-15 9:57 ` Bartosz Golaszewski 2026-09-15 9:59 ` Linus Walleij 1 sibling, 1 reply; 11+ messages in thread From: Bartosz Golaszewski @ 2026-09-15 9:51 UTC (permalink / raw) To: Alban Bedel Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree, linux-kernel On Tue, 15 Sep 2026 11:20:46 +0200, Alban Bedel <alban.bedel@lht.dlh.de> said: > Add support for the CAT9532 LED dimmer from On Semiconductor. Altought > marketed as an LED dimmer it is a bit limited in this regard as it > only has 2 PWM for 16 pins. As explained in the datasheet it can also > be used as an open-drain GPIO controller, and that's how it is used on > the hardware I have at hand. This chip doesn't really map to what the > gpio-regmap driver expect so it is implemented as it own driver. This > approch also allow to later add support for the LED dimmer if desired. > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> > --- > drivers/gpio/Kconfig | 10 +++ > drivers/gpio/Makefile | 1 + > drivers/gpio/gpio-cat9532.c | 173 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 184 insertions(+) > create mode 100644 drivers/gpio/gpio-cat9532.c > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > index a48586bb8edba..05b7af675677b 100644 > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -1180,6 +1180,16 @@ config GPIO_ADNP > enough to represent all pins, but the driver will assume a > register layout for 64 pins (8 registers). > > +config GPIO_CAT9532 > + tristate "CAT9532 GPIO support" > + select REGMAP_I2C > + help > + GPIO driver for ON Semiconductor CAT9532 LED dimmer. > + Say yes here to enable the GPIO driver for the CAT9532 chip. > + > + To compile this driver as a module, choose M here: the module will > + be called gpio-cat9532. > + > config GPIO_FXL6408 > tristate "FXL6408 I2C GPIO expander" > select GPIO_REGMAP > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > index dc9e6d643b5bc..e94d2f57a1f93 100644 > --- a/drivers/gpio/Makefile > +++ b/drivers/gpio/Makefile > @@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o > obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o > obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o > obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o > +obj-$(CONFIG_GPIO_CAT9532) += gpio-cat9532.o > obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o > obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o > obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o > diff --git a/drivers/gpio/gpio-cat9532.c b/drivers/gpio/gpio-cat9532.c > new file mode 100644 > index 0000000000000..973ff74a15b89 > --- /dev/null > +++ b/drivers/gpio/gpio-cat9532.c > @@ -0,0 +1,173 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +#include <linux/gpio/driver.h> > +#include <linux/i2c.h> > +#include <linux/module.h> > +#include <linux/regmap.h> > +#include <linux/spinlock.h> > + > +struct cat9532 { > + struct regmap *regmap; > + struct gpio_chip gpio; > + > + spinlock_t lock; > + unsigned int direction; > +}; > + > +#define CAT9532_REG_INPUT0 0 > +#define CAT9532_REG_LS0 6 > + > +/* Set output to Hi-Z, LED is OFF */ > +#define CAT9532_LED_OUT_HIZ 0 > +/* Set output low */ > +#define CAT9532_LED_OUT_LOW 1 > +#define CAT9532_LED_OUT_MASK 3 > + > +static const struct regmap_config cat9532_regmap_cfg = { > + .reg_bits = 8, > + .val_bits = 8, > + .max_register = 9, > + /* > + * Auto increment can be enabled by setting bit 4 in the > + * register address, but we don't really need bulk access. > + */ > + .use_single_read = true, > + .use_single_write = true, > + .can_sleep = true, > +}; This looks like it would perfectly fit the gpio-regmap helper and allow for code reuse. Maybe except for the locally tracked direction. How reliable is it? What if the GPIOs were put into some specific state by the bootloader? Bart ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] gpio: Support ON Semi CAT9532 2026-09-15 9:51 ` Bartosz Golaszewski @ 2026-09-15 9:57 ` Bartosz Golaszewski 2026-09-15 13:48 ` Alban Bedel 0 siblings, 1 reply; 11+ messages in thread From: Bartosz Golaszewski @ 2026-09-15 9:57 UTC (permalink / raw) To: Alban Bedel Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree, linux-kernel On Tue, Sep 15, 2026 at 11:51 AM Bartosz Golaszewski <brgl@kernel.org> wrote: > > On Tue, 15 Sep 2026 11:20:46 +0200, Alban Bedel <alban.bedel@lht.dlh.de> said: > > Add support for the CAT9532 LED dimmer from On Semiconductor. Altought > > marketed as an LED dimmer it is a bit limited in this regard as it > > only has 2 PWM for 16 pins. As explained in the datasheet it can also > > be used as an open-drain GPIO controller, and that's how it is used on > > the hardware I have at hand. This chip doesn't really map to what the > > gpio-regmap driver expect so it is implemented as it own driver. This > > approch also allow to later add support for the LED dimmer if desired. > > > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> > > --- > > drivers/gpio/Kconfig | 10 +++ > > drivers/gpio/Makefile | 1 + > > drivers/gpio/gpio-cat9532.c | 173 ++++++++++++++++++++++++++++++++++++ > > 3 files changed, 184 insertions(+) > > create mode 100644 drivers/gpio/gpio-cat9532.c > > > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > > index a48586bb8edba..05b7af675677b 100644 > > --- a/drivers/gpio/Kconfig > > +++ b/drivers/gpio/Kconfig > > @@ -1180,6 +1180,16 @@ config GPIO_ADNP > > enough to represent all pins, but the driver will assume a > > register layout for 64 pins (8 registers). > > > > +config GPIO_CAT9532 > > + tristate "CAT9532 GPIO support" > > + select REGMAP_I2C > > + help > > + GPIO driver for ON Semiconductor CAT9532 LED dimmer. > > + Say yes here to enable the GPIO driver for the CAT9532 chip. > > + > > + To compile this driver as a module, choose M here: the module will > > + be called gpio-cat9532. > > + > > config GPIO_FXL6408 > > tristate "FXL6408 I2C GPIO expander" > > select GPIO_REGMAP > > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > > index dc9e6d643b5bc..e94d2f57a1f93 100644 > > --- a/drivers/gpio/Makefile > > +++ b/drivers/gpio/Makefile > > @@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o > > obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o > > obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o > > obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o > > +obj-$(CONFIG_GPIO_CAT9532) += gpio-cat9532.o > > obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o > > obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o > > obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o > > diff --git a/drivers/gpio/gpio-cat9532.c b/drivers/gpio/gpio-cat9532.c > > new file mode 100644 > > index 0000000000000..973ff74a15b89 > > --- /dev/null > > +++ b/drivers/gpio/gpio-cat9532.c > > @@ -0,0 +1,173 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +#include <linux/gpio/driver.h> > > +#include <linux/i2c.h> > > +#include <linux/module.h> > > +#include <linux/regmap.h> > > +#include <linux/spinlock.h> > > + > > +struct cat9532 { > > + struct regmap *regmap; > > + struct gpio_chip gpio; > > + > > + spinlock_t lock; > > + unsigned int direction; > > +}; > > + > > +#define CAT9532_REG_INPUT0 0 > > +#define CAT9532_REG_LS0 6 > > + > > +/* Set output to Hi-Z, LED is OFF */ > > +#define CAT9532_LED_OUT_HIZ 0 > > +/* Set output low */ > > +#define CAT9532_LED_OUT_LOW 1 > > +#define CAT9532_LED_OUT_MASK 3 > > + > > +static const struct regmap_config cat9532_regmap_cfg = { > > + .reg_bits = 8, > > + .val_bits = 8, > > + .max_register = 9, > > + /* > > + * Auto increment can be enabled by setting bit 4 in the > > + * register address, but we don't really need bulk access. > > + */ > > + .use_single_read = true, > > + .use_single_write = true, > > + .can_sleep = true, > > +}; > > This looks like it would perfectly fit the gpio-regmap helper and allow for > code reuse. Maybe except for the locally tracked direction. How reliable is it? > What if the GPIOs were put into some specific state by the bootloader? > > Bart Ah, nevermind, you commented on not being able to use it. My question still stands, how reliable is direction tracking here? Does reading back the registers you write in direction setters not give you anything? Bart ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] gpio: Support ON Semi CAT9532 2026-09-15 9:57 ` Bartosz Golaszewski @ 2026-09-15 13:48 ` Alban Bedel 2026-09-16 9:07 ` Bartosz Golaszewski 0 siblings, 1 reply; 11+ messages in thread From: Alban Bedel @ 2026-09-15 13:48 UTC (permalink / raw) To: Bartosz Golaszewski Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree, linux-kernel, Alban Bedel On Tue, 15 Sep 2026 11:57:51 +0200 Bartosz Golaszewski <brgl@kernel.org> wrote: > On Tue, Sep 15, 2026 at 11:51 AM Bartosz Golaszewski <brgl@kernel.org> wrote: > > > > On Tue, 15 Sep 2026 11:20:46 +0200, Alban Bedel <alban.bedel@lht.dlh.de> said: > > > Add support for the CAT9532 LED dimmer from On Semiconductor. Altought > > > marketed as an LED dimmer it is a bit limited in this regard as it > > > only has 2 PWM for 16 pins. As explained in the datasheet it can also > > > be used as an open-drain GPIO controller, and that's how it is used on > > > the hardware I have at hand. This chip doesn't really map to what the > > > gpio-regmap driver expect so it is implemented as it own driver. This > > > approch also allow to later add support for the LED dimmer if desired. > > > > > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> > > > --- > > > drivers/gpio/Kconfig | 10 +++ > > > drivers/gpio/Makefile | 1 + > > > drivers/gpio/gpio-cat9532.c | 173 ++++++++++++++++++++++++++++++++++++ > > > 3 files changed, 184 insertions(+) > > > create mode 100644 drivers/gpio/gpio-cat9532.c > > > > > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > > > index a48586bb8edba..05b7af675677b 100644 > > > --- a/drivers/gpio/Kconfig > > > +++ b/drivers/gpio/Kconfig > > > @@ -1180,6 +1180,16 @@ config GPIO_ADNP > > > enough to represent all pins, but the driver will assume a > > > register layout for 64 pins (8 registers). > > > > > > +config GPIO_CAT9532 > > > + tristate "CAT9532 GPIO support" > > > + select REGMAP_I2C > > > + help > > > + GPIO driver for ON Semiconductor CAT9532 LED dimmer. > > > + Say yes here to enable the GPIO driver for the CAT9532 chip. > > > + > > > + To compile this driver as a module, choose M here: the module will > > > + be called gpio-cat9532. > > > + > > > config GPIO_FXL6408 > > > tristate "FXL6408 I2C GPIO expander" > > > select GPIO_REGMAP > > > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > > > index dc9e6d643b5bc..e94d2f57a1f93 100644 > > > --- a/drivers/gpio/Makefile > > > +++ b/drivers/gpio/Makefile > > > @@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o > > > obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o > > > obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o > > > obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o > > > +obj-$(CONFIG_GPIO_CAT9532) += gpio-cat9532.o > > > obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o > > > obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o > > > obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o > > > diff --git a/drivers/gpio/gpio-cat9532.c b/drivers/gpio/gpio-cat9532.c > > > new file mode 100644 > > > index 0000000000000..973ff74a15b89 > > > --- /dev/null > > > +++ b/drivers/gpio/gpio-cat9532.c > > > @@ -0,0 +1,173 @@ > > > +// SPDX-License-Identifier: GPL-2.0-or-later > > > +#include <linux/gpio/driver.h> > > > +#include <linux/i2c.h> > > > +#include <linux/module.h> > > > +#include <linux/regmap.h> > > > +#include <linux/spinlock.h> > > > + > > > +struct cat9532 { > > > + struct regmap *regmap; > > > + struct gpio_chip gpio; > > > + > > > + spinlock_t lock; > > > + unsigned int direction; > > > +}; > > > + > > > +#define CAT9532_REG_INPUT0 0 > > > +#define CAT9532_REG_LS0 6 > > > + > > > +/* Set output to Hi-Z, LED is OFF */ > > > +#define CAT9532_LED_OUT_HIZ 0 > > > +/* Set output low */ > > > +#define CAT9532_LED_OUT_LOW 1 > > > +#define CAT9532_LED_OUT_MASK 3 > > > + > > > +static const struct regmap_config cat9532_regmap_cfg = { > > > + .reg_bits = 8, > > > + .val_bits = 8, > > > + .max_register = 9, > > > + /* > > > + * Auto increment can be enabled by setting bit 4 in the > > > + * register address, but we don't really need bulk access. > > > + */ > > > + .use_single_read = true, > > > + .use_single_write = true, > > > + .can_sleep = true, > > > +}; > > > > This looks like it would perfectly fit the gpio-regmap helper and allow for > > code reuse. Maybe except for the locally tracked direction. How reliable is it? > > What if the GPIOs were put into some specific state by the bootloader? > > > > Bart > > Ah, nevermind, you commented on not being able to use it. My question > still stands, how reliable is direction tracking here? Does reading > back the registers you write in direction setters not give you > anything? This is an exclusively open-drain chip, you can either driver the line low or leave it in hi-z mode to be driven by an external circuit. There is no direction register, the input register just report the current line state. As such the direction is only something that exists in the driver. But as Sashiko pointed out this chip is a clone of the PCA9532 for which there is already a driver. I will instead look into making this driver usable in my use case. Thanks, for the review. Alban ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] gpio: Support ON Semi CAT9532 2026-09-15 13:48 ` Alban Bedel @ 2026-09-16 9:07 ` Bartosz Golaszewski 0 siblings, 0 replies; 11+ messages in thread From: Bartosz Golaszewski @ 2026-09-16 9:07 UTC (permalink / raw) To: Alban Bedel Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree, linux-kernel, Bartosz Golaszewski On Tue, 15 Sep 2026 15:48:02 +0200, Alban Bedel <alban.bedel@lht.dlh.de> said: > On Tue, 15 Sep 2026 11:57:51 +0200 > Bartosz Golaszewski <brgl@kernel.org> wrote: > >> On Tue, Sep 15, 2026 at 11:51 AM Bartosz Golaszewski <brgl@kernel.org> wrote: >> > >> > On Tue, 15 Sep 2026 11:20:46 +0200, Alban Bedel <alban.bedel@lht.dlh.de> said: >> > > Add support for the CAT9532 LED dimmer from On Semiconductor. Altought >> > > marketed as an LED dimmer it is a bit limited in this regard as it >> > > only has 2 PWM for 16 pins. As explained in the datasheet it can also >> > > be used as an open-drain GPIO controller, and that's how it is used on >> > > the hardware I have at hand. This chip doesn't really map to what the >> > > gpio-regmap driver expect so it is implemented as it own driver. This >> > > approch also allow to later add support for the LED dimmer if desired. >> > > >> > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> >> > > --- >> > > drivers/gpio/Kconfig | 10 +++ >> > > drivers/gpio/Makefile | 1 + >> > > drivers/gpio/gpio-cat9532.c | 173 ++++++++++++++++++++++++++++++++++++ >> > > 3 files changed, 184 insertions(+) >> > > create mode 100644 drivers/gpio/gpio-cat9532.c >> > > >> > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig >> > > index a48586bb8edba..05b7af675677b 100644 >> > > --- a/drivers/gpio/Kconfig >> > > +++ b/drivers/gpio/Kconfig >> > > @@ -1180,6 +1180,16 @@ config GPIO_ADNP >> > > enough to represent all pins, but the driver will assume a >> > > register layout for 64 pins (8 registers). >> > > >> > > +config GPIO_CAT9532 >> > > + tristate "CAT9532 GPIO support" >> > > + select REGMAP_I2C >> > > + help >> > > + GPIO driver for ON Semiconductor CAT9532 LED dimmer. >> > > + Say yes here to enable the GPIO driver for the CAT9532 chip. >> > > + >> > > + To compile this driver as a module, choose M here: the module will >> > > + be called gpio-cat9532. >> > > + >> > > config GPIO_FXL6408 >> > > tristate "FXL6408 I2C GPIO expander" >> > > select GPIO_REGMAP >> > > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile >> > > index dc9e6d643b5bc..e94d2f57a1f93 100644 >> > > --- a/drivers/gpio/Makefile >> > > +++ b/drivers/gpio/Makefile >> > > @@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o >> > > obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o >> > > obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o >> > > obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o >> > > +obj-$(CONFIG_GPIO_CAT9532) += gpio-cat9532.o >> > > obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o >> > > obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o >> > > obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o >> > > diff --git a/drivers/gpio/gpio-cat9532.c b/drivers/gpio/gpio-cat9532.c >> > > new file mode 100644 >> > > index 0000000000000..973ff74a15b89 >> > > --- /dev/null >> > > +++ b/drivers/gpio/gpio-cat9532.c >> > > @@ -0,0 +1,173 @@ >> > > +// SPDX-License-Identifier: GPL-2.0-or-later >> > > +#include <linux/gpio/driver.h> >> > > +#include <linux/i2c.h> >> > > +#include <linux/module.h> >> > > +#include <linux/regmap.h> >> > > +#include <linux/spinlock.h> >> > > + >> > > +struct cat9532 { >> > > + struct regmap *regmap; >> > > + struct gpio_chip gpio; >> > > + >> > > + spinlock_t lock; >> > > + unsigned int direction; >> > > +}; >> > > + >> > > +#define CAT9532_REG_INPUT0 0 >> > > +#define CAT9532_REG_LS0 6 >> > > + >> > > +/* Set output to Hi-Z, LED is OFF */ >> > > +#define CAT9532_LED_OUT_HIZ 0 >> > > +/* Set output low */ >> > > +#define CAT9532_LED_OUT_LOW 1 >> > > +#define CAT9532_LED_OUT_MASK 3 >> > > + >> > > +static const struct regmap_config cat9532_regmap_cfg = { >> > > + .reg_bits = 8, >> > > + .val_bits = 8, >> > > + .max_register = 9, >> > > + /* >> > > + * Auto increment can be enabled by setting bit 4 in the >> > > + * register address, but we don't really need bulk access. >> > > + */ >> > > + .use_single_read = true, >> > > + .use_single_write = true, >> > > + .can_sleep = true, >> > > +}; >> > >> > This looks like it would perfectly fit the gpio-regmap helper and allow for >> > code reuse. Maybe except for the locally tracked direction. How reliable is it? >> > What if the GPIOs were put into some specific state by the bootloader? >> > >> > Bart >> >> Ah, nevermind, you commented on not being able to use it. My question >> still stands, how reliable is direction tracking here? Does reading >> back the registers you write in direction setters not give you >> anything? > > This is an exclusively open-drain chip, you can either driver the line > low or leave it in hi-z mode to be driven by an external circuit. There > is no direction register, the input register just report the current > line state. As such the direction is only something that exists in the > driver. > Yes, I skimmed over it quickly at the airport, should have paid more attention to what I'm looking at. Thanks, Bartosz ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] gpio: Support ON Semi CAT9532 2026-09-15 9:20 ` [PATCH 2/2] gpio: Support ON Semi CAT9532 Alban Bedel 2026-09-15 9:51 ` Bartosz Golaszewski @ 2026-09-15 9:59 ` Linus Walleij 1 sibling, 0 replies; 11+ messages in thread From: Linus Walleij @ 2026-09-15 9:59 UTC (permalink / raw) To: Alban Bedel Cc: linux-gpio, devicetree, linux-kernel, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley Hi Alban, thanks for your patch! overall if it should be possible to use the same component as a LED dimmer then some DT property flag such as onn,gpio-mode; or so is needed to make sure only the GPIO mode driver is probed? I'm not sure about how to flag this in DT, check with the binding maintainers. On Tue, Sep 15, 2026 at 11:21 AM Alban Bedel <alban.bedel@lht.dlh.de> wrote: > Add support for the CAT9532 LED dimmer from On Semiconductor. Altought > marketed as an LED dimmer it is a bit limited in this regard as it > only has 2 PWM for 16 pins. As explained in the datasheet it can also > be used as an open-drain GPIO controller, and that's how it is used on > the hardware I have at hand. This chip doesn't really map to what the > gpio-regmap driver expect so it is implemented as it own driver. This > approch also allow to later add support for the LED dimmer if desired. > > Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de> (...) > +static int cat9532_gpio_direction_input(struct gpio_chip *chip, > + unsigned int offset) > +{ > + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); > + unsigned int reg = CAT9532_REG_LS0 + (offset >> 2); > + unsigned int shift = (offset & 3) << 1; > + int err; > + > + err = regmap_update_bits(cat9532->regmap, reg, > + CAT9532_LED_OUT_MASK << shift, > + CAT9532_LED_OUT_HIZ << shift); > + if (err < 0) > + return err; > + > + scoped_guard(spinlock, &cat9532->lock) > + cat9532->direction &= ~BIT(offset); > + > + return 0; > +} > + > +static int cat9532_gpio_get(struct gpio_chip *chip, > + unsigned int offset) > +{ > + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); > + unsigned int reg = CAT9532_REG_INPUT0 + (offset >> 3); > + unsigned int mask = BIT(offset & 7); > + unsigned int val; > + int err; > + > + err = regmap_read(cat9532->regmap, reg, &val); > + if (err < 0) > + return err; > + > + return !!(val & mask); > +} > + > +static int cat9532_gpio_set(struct gpio_chip *chip, > + unsigned int offset, int value) > +{ > + struct cat9532 *cat9532 = container_of(chip, struct cat9532, gpio); > + unsigned int reg = CAT9532_REG_LS0 + (offset >> 2); > + unsigned int shift = (offset & 3) << 1; > + unsigned int val; > + > + val = value ? CAT9532_LED_OUT_HIZ : CAT9532_LED_OUT_LOW; > + return regmap_update_bits(cat9532->regmap, reg, > + CAT9532_LED_OUT_MASK << shift, > + val << shift); > +} So clearly all GPIO lines are open drain, requiring an external pull-up resistor. I would handle things this way: 1. Implement .set_config for this gpio_chip. 2. In the .set_config() callback, reject anything except PIN_CONFIG_OPEN_DRAIN pinconf_to_config_param(config) != PIN_CONFIG_OPEN_DRAIN return -EINVAL; 3. If setting open drain succeeds, mark the line offset as configured in a bitmap 4. Do not accept any get/set calls until the line has been configured as open drain. This forces users to always properly configure the line as open drain before usage. Maybe it is possible to also add restrictions in the YAML DT bindings to enforce consumers to set open drain, I'm not sure. But we can at least enforce it at runtime. > + chip = &cat9532->gpio; > + chip->label = "cat9532"; > + chip->parent = &client->dev; > + chip->owner = THIS_MODULE; > + chip->can_sleep = true; > + chip->base = -1; > + chip->ngpio = 16; This is right, no using ngpio :) Yours, Linus Walleij ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-16 9:07 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-15 9:20 [PATCH 0/2] Support ON Semi CAT9532 Alban Bedel 2026-09-15 9:20 ` [PATCH 1/2] dt-bindings: gpio: Add CAT9532 GPIO Alban Bedel 2026-09-15 9:43 ` Linus Walleij 2026-09-15 9:47 ` Linus Walleij 2026-09-15 16:42 ` Conor Dooley 2026-09-15 9:20 ` [PATCH 2/2] gpio: Support ON Semi CAT9532 Alban Bedel 2026-09-15 9:51 ` Bartosz Golaszewski 2026-09-15 9:57 ` Bartosz Golaszewski 2026-09-15 13:48 ` Alban Bedel 2026-09-16 9:07 ` Bartosz Golaszewski 2026-09-15 9:59 ` Linus Walleij
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®