From 298da5ca995576aca730690e9286132f9396d59c Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Fri, 2 Aug 2024 19:06:48 +0800 Subject: [PATCH] drivers: gpio: pca_series: add support for pcal953x and pcal64xxa add support for pca9538, pcal9539, pcal6408a and pcal6416a devices Signed-off-by: Chekhov Ma --- drivers/gpio/Kconfig.pca_series | 2 + drivers/gpio/gpio_pca_series.c | 197 ++++++++++++++++++++++++++ dts/bindings/gpio/nxp,pca_series.yaml | 1 + dts/bindings/gpio/nxp,pcal6408a.yaml | 10 +- dts/bindings/gpio/nxp,pcal6416a.yaml | 10 +- dts/bindings/gpio/nxp,pcal9538.yaml | 10 ++ dts/bindings/gpio/nxp,pcal9539.yaml | 10 ++ 7 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 dts/bindings/gpio/nxp,pcal9538.yaml create mode 100644 dts/bindings/gpio/nxp,pcal9539.yaml diff --git a/drivers/gpio/Kconfig.pca_series b/drivers/gpio/Kconfig.pca_series index a8bf5363ae2b58b..5a1493cd7616d6f 100644 --- a/drivers/gpio/Kconfig.pca_series +++ b/drivers/gpio/Kconfig.pca_series @@ -9,6 +9,8 @@ menuconfig GPIO_PCA_SERIES depends on DT_HAS_NXP_PCA9538_ENABLED || DT_HAS_NXP_PCA9539_ENABLED || \ DT_HAS_NXP_PCA9554_ENABLED || DT_HAS_NXP_PCA9555_ENABLED || \ DT_HAS_NXP_PCA9574_ENABLED || DT_HAS_NXP_PCA9575_ENABLED || \ + DT_HAS_NXP_PCAL9538_ENABLED || DT_HAS_NXP_PCAL9539_ENABLED || \ + DT_HAS_NXP_PCAL6408A_ENABLED || DT_HAS_NXP_PCAL6416A_ENABLED || \ DT_HAS_NXP_PCAL6524_ENABLED || DT_HAS_NXP_PCAL6534_ENABLED depends on I2C help diff --git a/drivers/gpio/gpio_pca_series.c b/drivers/gpio/gpio_pca_series.c index 311eb80f8201889..816d134b7d373a7 100644 --- a/drivers/gpio/gpio_pca_series.c +++ b/drivers/gpio/gpio_pca_series.c @@ -49,6 +49,10 @@ enum gpio_pca_series_part_no { PCA_PART_NO_PCA9555, PCA_PART_NO_PCA9574, PCA_PART_NO_PCA9575, + PCA_PART_NO_PCAL9538, + PCA_PART_NO_PCAL9539, + PCA_PART_NO_PCAL6408A, + PCA_PART_NO_PCAL6416A, PCA_PART_NO_PCAL6524, PCA_PART_NO_PCAL6534, }; @@ -65,6 +69,10 @@ const char *const gpio_pca_series_part_name[] = { "pca9555", "pca9574", "pca9575", + "pcal9538", + "pcal9539", + "pcal6408a", + "pcal6416a", "pcal6524", "pcal6534", }; @@ -2174,6 +2182,179 @@ const struct gpio_pca_series_part_config gpio_pca_series_part_cfg_pca9575 = { #endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ }; +/** + * @brief implement pcal953x and pcal64xxa driver + * + * @note flags = PCA_HAS_LATCH + * | PCA_HAS_PULL + * | PCA_HAS_INT_MASK + * + * api set : standard + * + * ngpios : 8, 16; + * part_no : pcal9534 pcal9538 pcal6408a + * pcal9535 pcal9539 pcal6416a + */ +#define GPIO_PCA_SERIES_FLAG_TYPE_2 (PCA_HAS_LATCH | PCA_HAS_PULL | PCA_HAS_INT_MASK) + +#ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL +/** + * cache map for flag = PCA_HAS_LATCH + * | PCA_HAS_PULL + * | PCA_HAS_INT_MASK + */ +static const uint8_t gpio_pca_series_cache_map_pcal953x[] = { + PCA_REG_INVALID, /** input_port if not PCA_HAS_OUT_CONFIG, non-cacheable */ + 0x00, /** output_port */ +/* 0x02, polarity_inversion (unused, omitted) */ + 0x01, /** configuration */ + 0x02, /** 2b_output_drive_strength if PCA_HAS_LATCH*/ + 0x04, /** input_latch if PCA_HAS_LATCH*/ + 0x05, /** pull_enable if PCA_HAS_PULL */ + 0x06, /** pull_select if PCA_HAS_PULL */ + PCA_REG_INVALID, /** input_status if PCA_HAS_OUT_CONFIG, non-cacheable */ + PCA_REG_INVALID, /** output_config if PCA_HAS_OUT_CONFIG */ +#ifdef CONFIG_GPIO_PCA_SERIES_INTERRUPT + PCA_REG_INVALID, /** interrupt_mask if PCA_HAS_INT_MASK, + * non-cacheable if not PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** int_status if PCA_HAS_INT_MASK, non-cacheable */ + PCA_REG_INVALID, /** 2b_interrupt_edge if PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** interrupt_clear if PCA_HAS_INT_EXTEND, non-cacheable */ +# ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL + 0x07, /** 1b_input_history if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ + 0x08, /** 1b_interrupt_rise if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ + 0x09, /** 1b_interrupt_fall if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ +# endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +#endif /* CONFIG_GPIO_PCA_SERIES_INTERRUPT */ +}; +#endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ + +static const uint8_t gpio_pca_series_reg_pcal9538[] = { + 0x00, /** input_port if not PCA_HAS_OUT_CONFIG, non-cacheable */ + 0x01, /** output_port */ +/* 0x02, polarity_inversion (unused, omitted) */ + 0x03, /** configuration */ + 0x40, /** 2b_output_drive_strength if PCA_HAS_LATCH*/ + 0x42, /** input_latch if PCA_HAS_LATCH*/ + 0x43, /** pull_enable if PCA_HAS_PULL */ + 0x44, /** pull_select if PCA_HAS_PULL */ + PCA_REG_INVALID, /** input_status if PCA_HAS_OUT_CONFIG, non-cacheable */ + PCA_REG_INVALID, /** output_config if PCA_HAS_OUT_CONFIG */ +#ifdef CONFIG_GPIO_PCA_SERIES_INTERRUPT + 0x45, /** interrupt_mask if PCA_HAS_INT_MASK, + * non-cacheable if not PCA_HAS_INT_EXTEND */ + 0x46, /** int_status if PCA_HAS_INT_MASK */ + PCA_REG_INVALID, /** 2b_interrupt_edge if PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** interrupt_clear if PCA_HAS_INT_EXTEND, non-cacheable */ +# ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL + PCA_REG_INVALID, /** 1b_input_history if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** 1b_interrupt_rise if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** 1b_interrupt_fall if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ +# endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +#endif /* CONFIG_GPIO_PCA_SERIES_INTERRUPT */ +}; + +#define GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL9538 (1U) +#define GPIO_PCA_FLAG_PCA_PART_NO_PCAL9538 GPIO_PCA_SERIES_FLAG_TYPE_2 +#define GPIO_PCA_PART_CFG_PCA_PART_NO_PCAL9538 (&gpio_pca_series_part_cfg_pcal9538) + +const struct gpio_pca_series_part_config gpio_pca_series_part_cfg_pcal9538 = { + .port_no = GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL9538, + .flags = GPIO_PCA_FLAG_PCA_PART_NO_PCAL9538, + .regs = gpio_pca_series_reg_pcal9538, +#ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL +# ifdef GPIO_NXP_PCA_SERIES_DEBUG + .cache_size = GPIO_PCA_GET_CACHE_SIZE_BY_PART_NO(PCA_PART_NO_PCAL9538), +# endif /* GPIO_NXP_PCA_SERIES_DEBUG */ + .cache_map = gpio_pca_series_cache_map_pcal953x, +#endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +}; + +/** + * pcal6408a share the same register layout with pcal9538, with + * additional voltage level translation capability. + * no difference from driver perspective. + */ + +#define GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL6408A GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL9538 +#define GPIO_PCA_FLAG_PCA_PART_NO_PCAL6408A GPIO_PCA_FLAG_PCA_PART_NO_PCAL9538 +#define GPIO_PCA_PART_CFG_PCA_PART_NO_PCAL6408A (&gpio_pca_series_part_cfg_pcal6408a) + +const struct gpio_pca_series_part_config gpio_pca_series_part_cfg_pcal6408a = { + .port_no = GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL6408A, + .flags = GPIO_PCA_FLAG_PCA_PART_NO_PCAL6408A, + .regs = gpio_pca_series_reg_pcal9538, +#ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL +# ifdef GPIO_NXP_PCA_SERIES_DEBUG + .cache_size = GPIO_PCA_GET_CACHE_SIZE_BY_PART_NO(PCA_PART_NO_PCAL6408A), +# endif /* GPIO_NXP_PCA_SERIES_DEBUG */ + .cache_map = gpio_pca_series_cache_map_pcal953x, +#endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +}; + +static const uint8_t gpio_pca_series_reg_pcal9539[] = { + 0x00, /** input_port if not PCA_HAS_OUT_CONFIG, non-cacheable */ + 0x02, /** output_port */ +/* 0x04, polarity_inversion (unused, omitted) */ + 0x06, /** configuration */ + 0x40, /** 2b_output_drive_strength if PCA_HAS_LATCH*/ + 0x44, /** input_latch if PCA_HAS_LATCH*/ + 0x46, /** pull_enable if PCA_HAS_PULL */ + 0x48, /** pull_select if PCA_HAS_PULL */ + PCA_REG_INVALID, /** input_status if PCA_HAS_OUT_CONFIG, non-cacheable */ + PCA_REG_INVALID, /** output_config if PCA_HAS_OUT_CONFIG */ +#ifdef CONFIG_GPIO_PCA_SERIES_INTERRUPT + 0x4a, /** interrupt_mask if PCA_HAS_INT_MASK, + * non-cacheable if not PCA_HAS_INT_EXTEND */ + 0x4c, /** int_status if PCA_HAS_INT_MASK */ + PCA_REG_INVALID, /** 2b_interrupt_edge if PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** interrupt_clear if PCA_HAS_INT_EXTEND, non-cacheable */ +# ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL + PCA_REG_INVALID, /** 1b_input_history if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** 1b_interrupt_rise if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ + PCA_REG_INVALID, /** 1b_interrupt_fall if PCA_HAS_LATCH and not PCA_HAS_INT_EXTEND */ +# endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +#endif /* CONFIG_GPIO_PCA_SERIES_INTERRUPT */ +}; + +#define GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL9539 (2U) +#define GPIO_PCA_FLAG_PCA_PART_NO_PCAL9539 GPIO_PCA_SERIES_FLAG_TYPE_2 +#define GPIO_PCA_PART_CFG_PCA_PART_NO_PCAL9539 (&gpio_pca_series_part_cfg_pcal9539) + +const struct gpio_pca_series_part_config gpio_pca_series_part_cfg_pcal9539 = { + .port_no = GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL9539, + .flags = GPIO_PCA_FLAG_PCA_PART_NO_PCAL9539, + .regs = gpio_pca_series_reg_pcal9539, +#ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL +# ifdef GPIO_NXP_PCA_SERIES_DEBUG + .cache_size = GPIO_PCA_GET_CACHE_SIZE_BY_PART_NO(PCA_PART_NO_PCAL9539), +# endif /* GPIO_NXP_PCA_SERIES_DEBUG */ + .cache_map = gpio_pca_series_cache_map_pcal953x, +#endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +}; + +/** + * pcal6416a share the same register layout with pcal9539, with + * additional voltage level translation capability. + * no difference from driver perspective. + */ + +#define GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL6416A GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL9539 +#define GPIO_PCA_FLAG_PCA_PART_NO_PCAL6416A GPIO_PCA_FLAG_PCA_PART_NO_PCAL9539 +#define GPIO_PCA_PART_CFG_PCA_PART_NO_PCAL6416A (&gpio_pca_series_part_cfg_pcal6416a) + +const struct gpio_pca_series_part_config gpio_pca_series_part_cfg_pcal6416a = { + .port_no = GPIO_PCA_PORT_NO_PCA_PART_NO_PCAL6416A, + .flags = GPIO_PCA_FLAG_PCA_PART_NO_PCAL6416A, + .regs = gpio_pca_series_reg_pcal9539, +#ifdef CONFIG_GPIO_PCA_SERIES_CACHE_ALL +# ifdef GPIO_NXP_PCA_SERIES_DEBUG + .cache_size = GPIO_PCA_GET_CACHE_SIZE_BY_PART_NO(PCA_PART_NO_PCAL6416A), +# endif /* GPIO_NXP_PCA_SERIES_DEBUG */ + .cache_map = gpio_pca_series_cache_map_pcal953x, +#endif /* CONFIG_GPIO_PCA_SERIES_CACHE_ALL */ +}; + /** * @brief implement pcal65xx driver * @@ -2365,6 +2546,22 @@ DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_P #define DT_DRV_COMPAT nxp_pca9575 DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_PCA9575) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_pcal9538 +DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_PCAL9538) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_pcal9539 +DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_PCAL9539) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_pcal6408a +DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_PCAL6408A) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_pcal6416a +DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_PCAL6416A) + #undef DT_DRV_COMPAT #define DT_DRV_COMPAT nxp_pcal6524 DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_PCA_SERIES_DEVICE_INSTANCE, PCA_PART_NO_PCAL6524) diff --git a/dts/bindings/gpio/nxp,pca_series.yaml b/dts/bindings/gpio/nxp,pca_series.yaml index a37fa281e3b7298..533c14e26a7c78d 100644 --- a/dts/bindings/gpio/nxp,pca_series.yaml +++ b/dts/bindings/gpio/nxp,pca_series.yaml @@ -7,6 +7,7 @@ include: [gpio-controller.yaml, i2c-device.yaml] # Currently supported device: # pca9538 pca9539 +# pca9554 pca9555 # pca9574 pca9575 # pcal9538 pcal9539 # pcal6408a pcal6416a diff --git a/dts/bindings/gpio/nxp,pcal6408a.yaml b/dts/bindings/gpio/nxp,pcal6408a.yaml index 4acf381614784c1..1f68325c07b0617 100644 --- a/dts/bindings/gpio/nxp,pcal6408a.yaml +++ b/dts/bindings/gpio/nxp,pcal6408a.yaml @@ -1,12 +1,10 @@ # Copyright (c) 2021 Nordic Semiconductor ASA # Copyright (c) 2023 SILA Embedded Solutions GmbH +# Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 - -description: PCAL6408A 8-bit I2C-based I/O expander - -compatible: "nxp,pcal6408a" - -include: nxp,pcal64xxa-base.yaml +description: NXP PCAL6408A I2C GPIO expander node +compatible: nxp,pcal6408a +include: nxp,pca_series.yaml properties: ngpios: diff --git a/dts/bindings/gpio/nxp,pcal6416a.yaml b/dts/bindings/gpio/nxp,pcal6416a.yaml index 7717ca838308d13..c9dd2d7f9b71ba8 100644 --- a/dts/bindings/gpio/nxp,pcal6416a.yaml +++ b/dts/bindings/gpio/nxp,pcal6416a.yaml @@ -1,11 +1,9 @@ # Copyright (c) 2023 SILA Embedded Solutions GmbH +# Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 - -description: PCAL6416A 16-bit I2C-based I/O expander - -compatible: "nxp,pcal6416a" - -include: nxp,pcal64xxa-base.yaml +description: NXP PCAL6416A I2C GPIO expander node +compatible: nxp,pcal6416a +include: nxp,pca_series.yaml properties: ngpios: diff --git a/dts/bindings/gpio/nxp,pcal9538.yaml b/dts/bindings/gpio/nxp,pcal9538.yaml new file mode 100644 index 000000000000000..46f0ae43f5555b9 --- /dev/null +++ b/dts/bindings/gpio/nxp,pcal9538.yaml @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 +description: NXP PCAL9538 I2C GPIO expander node +compatible: nxp,pcal9538 +include: nxp,pca_series.yaml + +properties: + ngpios: + required: true + const: 8 diff --git a/dts/bindings/gpio/nxp,pcal9539.yaml b/dts/bindings/gpio/nxp,pcal9539.yaml new file mode 100644 index 000000000000000..0cc82662ca1882b --- /dev/null +++ b/dts/bindings/gpio/nxp,pcal9539.yaml @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 +description: NXP PCAL9539 I2C GPIO expander node +compatible: nxp,pcal9539 +include: nxp,pca_series.yaml + +properties: + ngpios: + required: true + const: 16