diff --git a/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts index da250ef781a..2690ae75b24 100644 --- a/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts +++ b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts @@ -52,7 +52,7 @@ pinctrl-names = "default"; i2c0_pcf8574@21 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x21>; gpio-controller; #gpio-cells = <2>; @@ -60,7 +60,7 @@ }; i2c0_pcf8574@22 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x22>; gpio-controller; #gpio-cells = <2>; @@ -68,7 +68,7 @@ }; i2c0_pcf8574@24 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x24>; gpio-controller; #gpio-cells = <2>; @@ -76,7 +76,7 @@ }; i2c0_pcf8574@25 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x25>; gpio-controller; #gpio-cells = <2>; @@ -93,7 +93,7 @@ pinctrl-names = "default"; i2c1_pcf8574@21 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x21>; gpio-controller; #gpio-cells = <2>; @@ -101,7 +101,7 @@ }; i2c1_pcf8574@22 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x22>; gpio-controller; #gpio-cells = <2>; @@ -109,7 +109,7 @@ }; i2c1_pcf8574@24 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x24>; gpio-controller; #gpio-cells = <2>; @@ -117,7 +117,7 @@ }; i2c1_pcf8574@25 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x25>; gpio-controller; #gpio-cells = <2>; diff --git a/doc/releases/migration-guide-3.6.rst b/doc/releases/migration-guide-3.6.rst index e77c1a5d1cd..d763e9f5f45 100644 --- a/doc/releases/migration-guide-3.6.rst +++ b/doc/releases/migration-guide-3.6.rst @@ -56,6 +56,35 @@ enable all optional modules, and then run ``west update`` again. Device Drivers and Device Tree ============================== +* The :dtcompatible:`nxp,pcf8574` driver has been renamed to + :dtcompatible:`nxp,pcf857x`. (:github:`67054`) to support pcf8574 and pcf8575. + The Kconfig option has been renamed from :kconfig:option:`CONFIG_GPIO_PCF8574` to + :kconfig:option:`CONFIG_GPIO_PCF857X`. + The Device Tree can be configured as follows: + + .. code-block:: devicetree + + &i2c { + status = "okay"; + pcf8574: pcf857x@20 { + compatible = "nxp,pcf857x"; + status = "okay"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + pcf8575: pcf857x@21 { + compatible = "nxp,pcf857x"; + status = "okay"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + }; + }; + * The :dtcompatible:`st,lsm6dsv16x` sensor driver has been changed to support configuration of both int1 and int2 pins. The DT attribute ``irq-gpios`` has been removed and substituted by two new attributes, ``int1-gpios`` and ``int2-gpios``. diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 34bdaebae27..56018e7744f 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -56,7 +56,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SNPS_CREG gpio_creg_gpio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_STMPE1600 gpio_stmpe1600.c) zephyr_library_sources_ifdef(CONFIG_GPIO_XEC_V2 gpio_mchp_xec_v2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_PCA953X gpio_pca953x.c) -zephyr_library_sources_ifdef(CONFIG_GPIO_PCF8574 gpio_pcf8574.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_PCF857X gpio_pcf857x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_FXL6408 gpio_fxl6408.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ANDES_ATCGPIO100 gpio_andes_atcgpio100.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NEORV32 gpio_neorv32.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 960c7eb540e..6b6928f3971 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -179,7 +179,7 @@ source "drivers/gpio/Kconfig.stmpe1600" source "drivers/gpio/Kconfig.pca953x" -source "drivers/gpio/Kconfig.pcf8574" +source "drivers/gpio/Kconfig.pcf857x" source "drivers/gpio/Kconfig.fxl6408" diff --git a/drivers/gpio/Kconfig.pcf8574 b/drivers/gpio/Kconfig.pcf8574 deleted file mode 100644 index 0c35008aa64..00000000000 --- a/drivers/gpio/Kconfig.pcf8574 +++ /dev/null @@ -1,19 +0,0 @@ -# PCF8574 GPIO configuration options - -# Copyright (c) 2022 Ithinx -# SPDX-License-Identifier: Apache-2.0 - -menuconfig GPIO_PCF8574 - bool "PCF8574 I2C GPIO chip" - default y - depends on DT_HAS_NXP_PCF8574_ENABLED - select I2C - help - Enable driver for PCF8574 I2C GPIO chip. - -config GPIO_PCF8574_INIT_PRIORITY - int "Init priority" - default 70 - depends on GPIO_PCF8574 - help - Device driver initialization priority. diff --git a/drivers/gpio/Kconfig.pcf857x b/drivers/gpio/Kconfig.pcf857x new file mode 100644 index 00000000000..2617d8a76a1 --- /dev/null +++ b/drivers/gpio/Kconfig.pcf857x @@ -0,0 +1,21 @@ +# PCF857x GPIO configuration options + +# Copyright (c) 2022 Ithinx +# Copyright (c) 2023 Mr Beam Lasers GmbH +# Copyright (c) 2023 Amrith Venkat Kesavamoorthi +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_PCF857X + bool "PCF857X I2C GPIO chip" + default y + depends on DT_HAS_NXP_PCF857X_ENABLED + select I2C + help + Enable driver for PCF857X I2C GPIO chip. + +config GPIO_PCF857X_INIT_PRIORITY + int "Init priority" + default 70 + depends on GPIO_PCF857X + help + Device driver initialization priority. diff --git a/drivers/gpio/gpio_pcf8574.c b/drivers/gpio/gpio_pcf857x.c similarity index 59% rename from drivers/gpio/gpio_pcf8574.c rename to drivers/gpio/gpio_pcf857x.c index 80a0d8b7d06..c30e1a5d36d 100644 --- a/drivers/gpio/gpio_pcf8574.c +++ b/drivers/gpio/gpio_pcf857x.c @@ -1,10 +1,16 @@ /** - * Copyright (c) 2022 Ithinx GmbH + * Copyright (c) + * 2022 Ithinx GmbH + * 2023 Amrith Venkat Kesavamoorthi + * 2023 Mr Beam Lasers GmbH. * * SPDX-License-Identifier: Apache-2.0 + * + * @see https://www.nxp.com/docs/en/data-sheet/PCF8575.pdf + * @see https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf */ -#define DT_DRV_COMPAT nxp_pcf8574 +#define DT_DRV_COMPAT nxp_pcf857x #include @@ -12,28 +18,31 @@ #include #include #include -LOG_MODULE_REGISTER(pcf8574, CONFIG_GPIO_LOG_LEVEL); +#include + +LOG_MODULE_REGISTER(pcf857x, CONFIG_GPIO_LOG_LEVEL); -struct pcf8574_pins_cfg { - uint8_t configured_as_outputs; /* 0 for input, 1 for output */ - uint8_t outputs_state; +struct pcf857x_pins_cfg { + uint16_t configured_as_outputs; /* 0 for input, 1 for output */ + uint16_t outputs_state; }; -/** Runtime driver data of the pcf8574*/ -struct pcf8574_drv_data { +/** Runtime driver data of the pcf857x*/ +struct pcf857x_drv_data { /* gpio_driver_data needs to be first */ struct gpio_driver_data common; - struct pcf8574_pins_cfg pins_cfg; + struct pcf857x_pins_cfg pins_cfg; sys_slist_t callbacks; struct k_sem lock; struct k_work work; const struct device *dev; struct gpio_callback int_gpio_cb; - uint8_t input_port_last; + uint16_t input_port_last; + int num_bytes; }; /** Configuration data*/ -struct pcf8574_drv_cfg { +struct pcf857x_drv_cfg { /* gpio_driver_config needs to be first */ struct gpio_driver_config common; struct i2c_dt_spec i2c; @@ -41,52 +50,53 @@ struct pcf8574_drv_cfg { }; /** - * @brief Reads the value of the pins from pcf8574 respectively from a connected device. + * @brief Reads the value of the pins from pcf857x respectively from a connected device. * * @param dev Pointer to the device structure of the driver instance. - * @param value Pointer to the input value. It contains the received Byte. + * @param value Pointer to the input value. It contains the received Bytes(receives 2 Bytes for P0 + * and P1). * * @retval 0 If successful. * @retval Negative value for error code. */ -static int pcf8574_process_input(const struct device *dev, gpio_port_value_t *value) +static int pcf857x_process_input(const struct device *dev, gpio_port_value_t *value) { - const struct pcf8574_drv_cfg *drv_cfg = dev->config; - struct pcf8574_drv_data *drv_data = dev->data; + const struct pcf857x_drv_cfg *drv_cfg = dev->config; + struct pcf857x_drv_data *drv_data = dev->data; int rc = 0; - uint8_t rx_buf; + uint8_t rx_buf[2] = {0}; - rc = i2c_read_dt(&drv_cfg->i2c, &rx_buf, sizeof(rx_buf)); + rc = i2c_read_dt(&drv_cfg->i2c, rx_buf, drv_data->num_bytes); if (rc != 0) { LOG_ERR("%s: failed to read from device: %d", dev->name, rc); return -EIO; } if (value) { - *value = rx_buf; + *value = sys_get_le16(rx_buf); /*format P17-P10..P07-P00 (bit15-bit8..bit7-bit0)*/ } - drv_data->input_port_last = rx_buf; + drv_data->input_port_last = sys_get_le16(rx_buf); return rc; } /** Register the read-task as work*/ -static void pcf8574_work_handler(struct k_work *work) +static void pcf857x_work_handler(struct k_work *work) { - struct pcf8574_drv_data *drv_data = CONTAINER_OF(work, struct pcf8574_drv_data, work); + struct pcf857x_drv_data *drv_data = CONTAINER_OF(work, struct pcf857x_drv_data, work); k_sem_take(&drv_data->lock, K_FOREVER); uint32_t changed_pins; - uint8_t input_port_last_temp = drv_data->input_port_last; - int rc = pcf8574_process_input(drv_data->dev, &changed_pins); + uint16_t input_port_last_temp = drv_data->input_port_last; + int rc = pcf857x_process_input(drv_data->dev, &changed_pins); if (rc) { LOG_ERR("Failed to read interrupt sources: %d", rc); } k_sem_give(&drv_data->lock); - if (input_port_last_temp != (uint8_t)changed_pins && !rc) { + if (input_port_last_temp != (uint16_t)changed_pins && !rc) { /** Find changed bits*/ changed_pins ^= input_port_last_temp; @@ -94,15 +104,15 @@ static void pcf8574_work_handler(struct k_work *work) } } -/** Callback for interrupt through some level changes on pcf8574 pins*/ -static void pcf8574_int_gpio_handler(const struct device *dev, struct gpio_callback *gpio_cb, +/** Callback for interrupt through some level changes on pcf857x pins*/ +static void pcf857x_int_gpio_handler(const struct device *dev, struct gpio_callback *gpio_cb, uint32_t pins) { ARG_UNUSED(dev); ARG_UNUSED(pins); - struct pcf8574_drv_data *drv_data = - CONTAINER_OF(gpio_cb, struct pcf8574_drv_data, int_gpio_cb); + struct pcf857x_drv_data *drv_data = + CONTAINER_OF(gpio_cb, struct pcf857x_drv_data, int_gpio_cb); k_work_submit(&drv_data->work); } @@ -116,16 +126,16 @@ static void pcf8574_int_gpio_handler(const struct device *dev, struct gpio_callb * @retval 0 If successful. * @retval Negative value for error code. */ -static int pcf8574_port_get_raw(const struct device *dev, gpio_port_value_t *value) +static int pcf857x_port_get_raw(const struct device *dev, gpio_port_value_t *value) { - struct pcf8574_drv_data *drv_data = dev->data; + struct pcf857x_drv_data *drv_data = dev->data; int rc; if (k_is_in_isr()) { return -EWOULDBLOCK; } - if ((~drv_data->pins_cfg.configured_as_outputs & (uint8_t)*value) != (uint8_t)*value) { + if ((~drv_data->pins_cfg.configured_as_outputs & (uint16_t)*value) != (uint16_t)*value) { LOG_ERR("Pin(s) is/are configured as output which should be input."); return -EOPNOTSUPP; } @@ -136,7 +146,7 @@ static int pcf8574_port_get_raw(const struct device *dev, gpio_port_value_t *val * Reading of the input port also clears the generated interrupt, * thus the configured callbacks must be fired also here if needed. */ - rc = pcf8574_process_input(dev, value); + rc = pcf857x_process_input(dev, value); k_sem_give(&drv_data->lock); @@ -148,19 +158,20 @@ static int pcf8574_port_get_raw(const struct device *dev, gpio_port_value_t *val * * @param dev A pointer to the device structure * @param mask A mask of bits to set some bits to LOW or HIGH - * @param value The value which is written via i2c to the pfc8574's output pins + * @param value The value which is written via i2c to the pcf857x's output pins * @param toggle A way to toggle some bits with xor * * @retval 0 If successful. * @retval Negative value for error code. */ -static int pcf8574_port_set_raw(const struct device *dev, uint8_t mask, uint8_t value, - uint8_t toggle) +static int pcf857x_port_set_raw(const struct device *dev, uint16_t mask, uint16_t value, + uint16_t toggle) { - const struct pcf8574_drv_cfg *drv_cfg = dev->config; - struct pcf8574_drv_data *drv_data = dev->data; + const struct pcf857x_drv_cfg *drv_cfg = dev->config; + struct pcf857x_drv_data *drv_data = dev->data; int rc = 0; - uint8_t tx_buf; + uint16_t tx_buf; + uint8_t tx_buf_p[2]; if (k_is_in_isr()) { return -EWOULDBLOCK; @@ -174,14 +185,13 @@ static int pcf8574_port_set_raw(const struct device *dev, uint8_t mask, uint8_t tx_buf = (drv_data->pins_cfg.outputs_state & ~mask); tx_buf |= (value & mask); tx_buf ^= toggle; + sys_put_le16(tx_buf, tx_buf_p); - rc = i2c_write_dt(&drv_cfg->i2c, &tx_buf, sizeof(tx_buf)); - + rc = i2c_write_dt(&drv_cfg->i2c, tx_buf_p, drv_data->num_bytes); if (rc != 0) { LOG_ERR("%s: failed to write output port: %d", dev->name, rc); return -EIO; } - k_sem_take(&drv_data->lock, K_FOREVER); drv_data->pins_cfg.outputs_state = tx_buf; k_sem_give(&drv_data->lock); @@ -190,9 +200,9 @@ static int pcf8574_port_set_raw(const struct device *dev, uint8_t mask, uint8_t } /** - * @brief This function fills a dummy because the pfc8574 has no pins to configure. + * @brief This function fills a dummy because the pcf857x has no pins to configure. * You can use it to set some pins permanent to HIGH or LOW until reset. It uses the port_set_raw - * function to set the pins of pcf8574 directly. + * function to set the pins of pcf857x directly. * * @param dev Pointer to the device structure for the driver instance. * @param pin The bit in the io register which is set to high @@ -201,12 +211,12 @@ static int pcf8574_port_set_raw(const struct device *dev, uint8_t mask, uint8_t * @retval 0 If successful. * @retval Negative value for error. */ -static int pcf8574_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +static int pcf857x_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) { - struct pcf8574_drv_data *drv_data = dev->data; + struct pcf857x_drv_data *drv_data = dev->data; int ret = 0; - uint8_t temp_pins = drv_data->pins_cfg.outputs_state; - uint8_t temp_outputs = drv_data->pins_cfg.configured_as_outputs; + uint16_t temp_pins = drv_data->pins_cfg.outputs_state; + uint16_t temp_outputs = drv_data->pins_cfg.configured_as_outputs; if (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN | GPIO_DISCONNECTED | GPIO_SINGLE_ENDED)) { return -ENOTSUP; @@ -225,7 +235,7 @@ static int pcf8574_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_ temp_pins &= ~(1 << pin); } - ret = pcf8574_port_set_raw(dev, drv_data->pins_cfg.configured_as_outputs, temp_pins, 0); + ret = pcf857x_port_set_raw(dev, drv_data->pins_cfg.configured_as_outputs, temp_pins, 0); if (ret == 0) { k_sem_take(&drv_data->lock, K_FOREVER); @@ -238,7 +248,7 @@ static int pcf8574_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_ } /** - * @brief Sets a value to the pins of pcf8574 + * @brief Sets a value to the pins of pcf857x * * @param dev Pointer to the device structure for the driver instance. * @param mask The bit mask which bits should be set @@ -247,24 +257,24 @@ static int pcf8574_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_ * @retval 0 If successful. * @retval Negative value for error. */ -static int pcf8574_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, +static int pcf857x_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, gpio_port_value_t value) { - return pcf8574_port_set_raw(dev, (uint8_t)mask, (uint8_t)value, 0); + return pcf857x_port_set_raw(dev, (uint16_t)mask, (uint16_t)value, 0); } /** - * @brief Sets some output pins of the pcf8574 + * @brief Sets some output pins of the pcf857x * * @param dev Pointer to the device structure for the driver instance. - * @param pins The pin(s) which will be set in a range from 0 to 7 + * @param pins The pin(s) which will be set in a range from P17-P10..P07-P00 * * @retval 0 If successful. * @retval Negative value for error. */ -static int pcf8574_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +static int pcf857x_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) { - return pcf8574_port_set_raw(dev, (uint8_t)pins, (uint8_t)pins, 0); + return pcf857x_port_set_raw(dev, (uint16_t)pins, (uint16_t)pins, 0); } /** @@ -276,9 +286,9 @@ static int pcf8574_port_set_bits_raw(const struct device *dev, gpio_port_pins_t * @retval 0 If successful. * @retval Negative value for error. */ -static int pcf8574_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +static int pcf857x_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) { - return pcf8574_port_set_raw(dev, (uint8_t)pins, 0, 0); + return pcf857x_port_set_raw(dev, (uint16_t)pins, 0, 0); } /** @@ -290,16 +300,16 @@ static int pcf8574_port_clear_bits_raw(const struct device *dev, gpio_port_pins_ * @retval 0 If successful. * @retval Negative value for error. */ -static int pcf8574_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +static int pcf857x_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) { - return pcf8574_port_set_raw(dev, 0, 0, (uint8_t)pins); + return pcf857x_port_set_raw(dev, 0, 0, (uint16_t)pins); } -/* Each pin gives an interrupt at pcf8574. In this function the configuration is checked. */ -static int pcf8574_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, +/* Each pin gives an interrupt at pcf857x. In this function the configuration is checked. */ +static int pcf857x_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, enum gpio_int_trig trig) { - const struct pcf8574_drv_cfg *drv_cfg = dev->config; + const struct pcf857x_drv_cfg *drv_cfg = dev->config; if (!drv_cfg->gpio_int.port) { return -ENOTSUP; @@ -314,19 +324,19 @@ static int pcf8574_pin_interrupt_configure(const struct device *dev, gpio_pin_t } /** Register the callback in the callback list */ -static int pcf8574_manage_callback(const struct device *dev, struct gpio_callback *callback, +static int pcf857x_manage_callback(const struct device *dev, struct gpio_callback *callback, bool set) { - struct pcf8574_drv_data *drv_data = dev->data; + struct pcf857x_drv_data *drv_data = dev->data; return gpio_manage_callback(&drv_data->callbacks, callback, set); } -/** Initialize the pcf8574 */ -static int pcf8574_init(const struct device *dev) +/** Initialize the pcf857x */ +static int pcf857x_init(const struct device *dev) { - const struct pcf8574_drv_cfg *drv_cfg = dev->config; - struct pcf8574_drv_data *drv_data = dev->data; + const struct pcf857x_drv_cfg *drv_cfg = dev->config; + struct pcf857x_drv_data *drv_data = dev->data; int rc; if (!device_is_ready(drv_cfg->i2c.bus)) { @@ -353,7 +363,7 @@ static int pcf8574_init(const struct device *dev) return -EIO; } - gpio_init_callback(&drv_data->int_gpio_cb, pcf8574_int_gpio_handler, + gpio_init_callback(&drv_data->int_gpio_cb, pcf857x_int_gpio_handler, BIT(drv_cfg->gpio_int.pin)); rc = gpio_add_callback(drv_cfg->gpio_int.port, &drv_data->int_gpio_cb); if (rc != 0) { @@ -365,20 +375,20 @@ static int pcf8574_init(const struct device *dev) return 0; } -/** Realizes the functions of gpio.h for pcf8574*/ -static const struct gpio_driver_api pcf8574_drv_api = { - .pin_configure = pcf8574_pin_configure, - .port_get_raw = pcf8574_port_get_raw, - .port_set_masked_raw = pcf8574_port_set_masked_raw, - .port_set_bits_raw = pcf8574_port_set_bits_raw, - .port_clear_bits_raw = pcf8574_port_clear_bits_raw, - .port_toggle_bits = pcf8574_port_toggle_bits, - .pin_interrupt_configure = pcf8574_pin_interrupt_configure, - .manage_callback = pcf8574_manage_callback, +/** Realizes the functions of gpio.h for pcf857x*/ +static const struct gpio_driver_api pcf857x_drv_api = { + .pin_configure = pcf857x_pin_configure, + .port_get_raw = pcf857x_port_get_raw, + .port_set_masked_raw = pcf857x_port_set_masked_raw, + .port_set_bits_raw = pcf857x_port_set_bits_raw, + .port_clear_bits_raw = pcf857x_port_clear_bits_raw, + .port_toggle_bits = pcf857x_port_toggle_bits, + .pin_interrupt_configure = pcf857x_pin_interrupt_configure, + .manage_callback = pcf857x_manage_callback, }; -#define GPIO_PCF8574_INST(idx) \ - static const struct pcf8574_drv_cfg pcf8574_cfg##idx = { \ +#define GPIO_PCF857X_INST(idx) \ + static const struct pcf857x_drv_cfg pcf857x_cfg##idx = { \ .common = \ { \ .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx), \ @@ -386,12 +396,13 @@ static const struct gpio_driver_api pcf8574_drv_api = { .gpio_int = GPIO_DT_SPEC_INST_GET_OR(idx, int_gpios, {0}), \ .i2c = I2C_DT_SPEC_INST_GET(idx), \ }; \ - static struct pcf8574_drv_data pcf8574_data##idx = { \ - .lock = Z_SEM_INITIALIZER(pcf8574_data##idx.lock, 1, 1), \ - .work = Z_WORK_INITIALIZER(pcf8574_work_handler), \ + static struct pcf857x_drv_data pcf857x_data##idx = { \ + .lock = Z_SEM_INITIALIZER(pcf857x_data##idx.lock, 1, 1), \ + .work = Z_WORK_INITIALIZER(pcf857x_work_handler), \ .dev = DEVICE_DT_INST_GET(idx), \ + .num_bytes = DT_INST_ENUM_IDX(idx, ngpios) + 1, \ }; \ - DEVICE_DT_INST_DEFINE(idx, pcf8574_init, NULL, &pcf8574_data##idx, &pcf8574_cfg##idx, \ - POST_KERNEL, CONFIG_GPIO_PCF8574_INIT_PRIORITY, &pcf8574_drv_api); + DEVICE_DT_INST_DEFINE(idx, pcf857x_init, NULL, &pcf857x_data##idx, &pcf857x_cfg##idx, \ + POST_KERNEL, CONFIG_GPIO_PCF857X_INIT_PRIORITY, &pcf857x_drv_api); -DT_INST_FOREACH_STATUS_OKAY(GPIO_PCF8574_INST); +DT_INST_FOREACH_STATUS_OKAY(GPIO_PCF857X_INST); diff --git a/dts/bindings/gpio/nxp,pcf8574.yaml b/dts/bindings/gpio/nxp,pcf857x.yaml similarity index 64% rename from dts/bindings/gpio/nxp,pcf8574.yaml rename to dts/bindings/gpio/nxp,pcf857x.yaml index 96cb2409c16..868ba520571 100644 --- a/dts/bindings/gpio/nxp,pcf8574.yaml +++ b/dts/bindings/gpio/nxp,pcf857x.yaml @@ -1,16 +1,20 @@ # Copyright (c) 2022 ithinx GmbH +# 2023 Amrith Venkat Kesavamoorthi +# 2023 Mr Beam Lasers GmbH. # SPDX-License-Identifier: Apache-2.0 -description: PCF8574 8-bit I2C-based I/O expander +description: PCF857x 8/16-bit I2C-based I/O expander -compatible: "nxp,pcf8574" +compatible: "nxp,pcf857x" include: [i2c-device.yaml, gpio-controller.yaml] properties: ngpios: required: true - const: 8 + enum: + - 8 + - 16 int-gpios: type: phandle-array diff --git a/tests/drivers/build_all/gpio/app.overlay b/tests/drivers/build_all/gpio/app.overlay index 375b3ab25dc..c6dabd6532c 100644 --- a/tests/drivers/build_all/gpio/app.overlay +++ b/tests/drivers/build_all/gpio/app.overlay @@ -68,8 +68,17 @@ interrupt-gpios = <&test_gpio 0 0>; }; + test_i2c_pcf8575: pcf8575@21 { + compatible = "nxp,pcf857x"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + int-gpios = <&test_gpio 0 0>; + }; + test_i2c_pcf8574: pcf8574@27 { - compatible = "nxp,pcf8574"; + compatible = "nxp,pcf857x"; reg = <0x27>; gpio-controller; #gpio-cells = <2>;