drivers: gpio: PCF857x: Modify PCF8574 driver
Modify existing PCF8574 driver as PCF857x for: PCF8574 - 8 channel I/O expander PCF8575 - 16 channel I/O expander Signed-off-by: Amrith Venkat Kesavamoorthi <amrith@mr-beam.org>
This commit is contained in:
parent
342e10b0b8
commit
879e3a42b0
9 changed files with 176 additions and 121 deletions
|
@ -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>;
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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.
|
21
drivers/gpio/Kconfig.pcf857x
Normal file
21
drivers/gpio/Kconfig.pcf857x
Normal file
|
@ -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 <amrith@mr-beam.org>
|
||||
# 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.
|
|
@ -1,10 +1,16 @@
|
|||
/**
|
||||
* Copyright (c) 2022 Ithinx GmbH
|
||||
* Copyright (c)
|
||||
* 2022 Ithinx GmbH
|
||||
* 2023 Amrith Venkat Kesavamoorthi <amrith@mr-beam.org>
|
||||
* 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 <zephyr/drivers/gpio/gpio_utils.h>
|
||||
|
||||
|
@ -12,28 +18,31 @@
|
|||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(pcf8574, CONFIG_GPIO_LOG_LEVEL);
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
struct pcf8574_pins_cfg {
|
||||
uint8_t configured_as_outputs; /* 0 for input, 1 for output */
|
||||
uint8_t outputs_state;
|
||||
LOG_MODULE_REGISTER(pcf857x, CONFIG_GPIO_LOG_LEVEL);
|
||||
|
||||
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);
|
|
@ -1,16 +1,20 @@
|
|||
# Copyright (c) 2022 ithinx GmbH
|
||||
# 2023 Amrith Venkat Kesavamoorthi <amrith@mr-beam.org>
|
||||
# 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
|
|
@ -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>;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue