ioexpander: add support for pcf8575 expander

This adds support for 16 bit io expander pcf8575. The driver is basically
the same as for pcf8574 however it is for 16 bits instead of 8 bits. Since
pcf8575 and pcf8574 can be both used on the same i2c bus the driver for
pcf8575 is implemented in a different file to reduce the code size
and complexity and to have less if statements in the driver.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
Michal Lenc 2023-08-01 16:25:06 +02:00 committed by Xiang Xiao
parent 580d09b5a1
commit bf90361895
5 changed files with 865 additions and 0 deletions

View file

@ -297,6 +297,25 @@ config PCF8574_INT_POLLDELAY
endif # IOEXPANDER_PCF8574 endif # IOEXPANDER_PCF8574
config IOEXPANDER_PCF8575
bool "PCF8575 I2C IO expander"
default n
depends on I2C
---help---
Enable support for 16 bit PCF8575 IO Expander. Software driver
interrupt is currently not supported therefore decated HW interrupt
pin should be used.
if IOEXPANDER_PCF8575
config PCF8575_MULTIPLE
bool "Multiple PCF8575 Devices"
default n
---help---
Can be defined to support multiple PCF8575 devices on board.
endif # IOEXPANDER_PCF8575
config IOEXPANDER_SX1509 config IOEXPANDER_SX1509
bool "SX1509 I2C IO expander" bool "SX1509 I2C IO expander"
default n default n

View file

@ -48,6 +48,10 @@ ifeq ($(CONFIG_IOEXPANDER_PCF8574),y)
CSRCS += pcf8574.c CSRCS += pcf8574.c
endif endif
ifeq ($(CONFIG_IOEXPANDER_PCF8575),y)
CSRCS += pcf8575.c
endif
ifeq ($(CONFIG_IOEXPANDER_MCP23X17),y) ifeq ($(CONFIG_IOEXPANDER_MCP23X17),y)
CSRCS += mcp23x17.c CSRCS += mcp23x17.c
endif endif

View file

@ -0,0 +1,681 @@
/****************************************************************************
* drivers/ioexpander/pcf8575.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <sys/param.h>
#include <nuttx/kmalloc.h>
#include <nuttx/ioexpander/ioexpander.h>
#include <nuttx/ioexpander/pcf8575.h>
#include "pcf8575.h"
#ifdef CONFIG_IOEXPANDER_PCF8575
#ifdef CONFIG_IOEXPANDER_INT_ENABLE
# error PCF8575 cannot work with CONFIG_IOEXPANDER_INT_ENABLE
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* PCF8575xx Helpers */
static int pcf8575_read(FAR struct pcf8575_dev_s *priv,
FAR uint16_t *portval);
static int pcf8575_write(struct pcf8575_dev_s *priv, uint16_t portval);
/* I/O Expander Methods */
static int pcf8575_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin,
int dir);
static int pcf8575_option(FAR struct ioexpander_dev_s *dev, uint8_t pin,
int opt, void *regval);
static int pcf8575_writepin(FAR struct ioexpander_dev_s *dev, uint8_t pin,
bool value);
static int pcf8575_readpin(FAR struct ioexpander_dev_s *dev, uint8_t pin,
FAR bool *value);
#ifdef CONFIG_IOEXPANDER_MULTIPIN
static int pcf8575_multiwritepin(FAR struct ioexpander_dev_s *dev,
FAR uint8_t *pins, FAR bool *values, int count);
static int pcf8575_multireadpin(FAR struct ioexpander_dev_s *dev,
FAR uint8_t *pins, FAR bool *values, int count);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifndef CONFIG_PCF8575_MULTIPLE
/* If only a single device is supported, then the driver state structure may
* as well be pre-allocated.
*/
static struct pcf8575_dev_s g_pcf8575;
#endif
/* I/O expander vtable */
static const struct ioexpander_ops_s g_pcf8575_ops =
{
pcf8575_direction,
pcf8575_option,
pcf8575_writepin,
pcf8575_readpin,
pcf8575_readpin
#ifdef CONFIG_IOEXPANDER_MULTIPIN
, pcf8575_multiwritepin
, pcf8575_multireadpin
, pcf8575_multireadpin
#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pcf8575_read
*
* Description:
* Read the PCF8575 16-bit value from a PCF8575xx port
*
* Primitive I2C read operation for the PCF8575. The PCF8575 is
* 'interesting' in that it doesn't really have a data direction register,
* but instead the outputs are current-limited when high, so by setting an
* IO line high, you are also making it an input. Consequently, before
* using this method, you'll need to perform a pca8574_write() setting the
* bits you are interested in reading to 1's, then call this method.
*
****************************************************************************/
static int pcf8575_read(FAR struct pcf8575_dev_s *priv,
FAR uint16_t *portval)
{
struct i2c_msg_s msg;
uint8_t buffer[2];
int ret;
DEBUGASSERT(priv != NULL && priv->i2c != NULL && priv->config != NULL);
/* Setup for the transfer */
msg.frequency = priv->config->frequency,
msg.addr = priv->config->address,
msg.flags = I2C_M_READ;
msg.buffer = buffer;
msg.length = 2;
/* Then perform the transfer. */
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
*portval = buffer[0] & 0xff;
*portval |= (buffer[1] << 8) & 0xff00;
return (ret >= 0) ? OK : ret;
}
/****************************************************************************
* Name: pcf8575_write
*
* Description:
* Write a 16-bit value to a PCF8575xx port
*
* Primitive I2C write operation for the PCA8574. The I2C interface
* simply sets the state of the 8 IO lines in the PCA8574 port.
*
****************************************************************************/
static int pcf8575_write(struct pcf8575_dev_s *priv, uint16_t portval)
{
struct i2c_msg_s msg;
uint8_t buffer[2];
int ret;
DEBUGASSERT(priv != NULL && priv->i2c != NULL && priv->config != NULL);
/* Setup for the transfer */
buffer[0] = (uint8_t)(portval & 0xff);
buffer[1] = (uint8_t)((portval & 0xff00) >> 8);
msg.frequency = priv->config->frequency,
msg.addr = priv->config->address;
msg.flags = 0;
msg.buffer = buffer;
msg.length = 2;
/* Then perform the transfer. */
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
return (ret >= 0) ? OK : ret;
}
/****************************************************************************
* Name: pcf8575_direction
*
* Description:
* Set the direction of an ioexpander pin. Required.
*
* The PCF8575 is 'interesting' in that it doesn't really have a data
* direction register, but instead the outputs are current-limited when
* high, so by setting an IO line high, you are also making it an input.
* Consequently, before using this method, you'll need to perform a
* pcf8575_write() setting the bits you are interested in reading to 1's,
* before calling pcf8575_read().
*
* Input Parameters:
* dev - Device-specific state data
* pin - The index of the pin to alter in this call
* dir - One of the IOEXPANDER_DIRECTION_ macros
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
static int pcf8575_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin,
int direction)
{
FAR struct pcf8575_dev_s *priv = (FAR struct pcf8575_dev_s *)dev;
int ret;
if (direction != IOEXPANDER_DIRECTION_IN &&
direction != IOEXPANDER_DIRECTION_OUT)
{
return -EINVAL;
}
if (pin > 15)
{
return -ENXIO;
}
DEBUGASSERT(priv != NULL && priv->config != NULL);
gpioinfo("I2C addr=%02x pin=%u direction=%s\n",
priv->config->address, pin,
(direction == IOEXPANDER_DIRECTION_IN) ? "IN" : "OUT");
/* Get exclusive access to the I/O Expander */
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Set a bit in inpins if the pin is an input. Clear the bit in
* inpins if the pin is an output.
*/
if (direction == IOEXPANDER_DIRECTION_IN)
{
priv->inpins |= (1 << pin);
priv->outstate &= ~(1 << pin);
}
else
{
priv->inpins &= ~(1 << pin);
}
/* Write the OR of the set of input pins and the set of output pins.
* In order to read input pins, we have to write a '1' to put the
* pin in the current limiting state.
*/
ret = pcf8575_write(priv, priv->inpins | priv->outstate);
nxmutex_unlock(&priv->lock);
return ret;
}
/****************************************************************************
* Name: pcf8575_option
*
* Description:
* Set pin options. Required.
* Since all IO expanders have various pin options, this API allows setting
* pin options in a flexible way.
*
* Input Parameters:
* dev - Device-specific state data
* pin - The index of the pin to alter in this call
* opt - One of the IOEXPANDER_OPTION_ macros
* val - The option's value
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
static int pcf8575_option(FAR struct ioexpander_dev_s *dev, uint8_t pin,
int opt, FAR void *value)
{
FAR struct pcf8575_dev_s *priv = (FAR struct pcf8575_dev_s *)dev;
int ret = OK;
DEBUGASSERT(priv != NULL && priv->config != NULL);
gpioinfo("I2C addr=%02x pin=%u option=%u\n",
priv->config->address, pin, opt);
return ret;
}
/****************************************************************************
* Name: pcf8575_writepin
*
* Description:
* Set the pin level. Required.
*
* Input Parameters:
* dev - Device-specific state data
* pin - The index of the pin to alter in this call
* val - The pin level. Usually TRUE will set the pin high,
* except if OPTION_INVERT has been set on this pin.
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
static int pcf8575_writepin(FAR struct ioexpander_dev_s *dev, uint8_t pin,
bool value)
{
FAR struct pcf8575_dev_s *priv = (FAR struct pcf8575_dev_s *)dev;
int ret;
if (pin > 15)
{
return -ENXIO;
}
DEBUGASSERT(priv != NULL && priv->config != NULL);
gpioinfo("I2C addr=%02x pin=%u value=%u\n",
priv->config->address, pin, value);
/* Get exclusive access to the I/O Expander */
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Make sure that this is an output pin */
if ((priv->inpins & (1 << pin)) != 0)
{
gpioerr("ERROR: pin%u is an input\n", pin);
nxmutex_unlock(&priv->lock);
return -EINVAL;
}
/* Set/clear a bit in outstate. */
if (value)
{
priv->outstate |= (1 << pin);
}
else
{
priv->outstate &= ~(1 << pin);
}
/* Write the OR of the set of input pins and the set of output pins.
* In order to set the new output value.
*/
ret = pcf8575_write(priv, priv->inpins | priv->outstate);
nxmutex_unlock(&priv->lock);
return ret;
}
/****************************************************************************
* Name: pcf8575_readpin
*
* Description:
* Read the actual PIN level. This can be different from the last value
* written to this pin. Required.
*
* The PCF8575 is 'interesting' in that it doesn't really have a data
* direction register, but instead the outputs are current-limited when
* high, so by setting an IO line high, you are also making it an input.
* Consequently, before using this method, you'll need to perform a
* pca8574_write() setting the bits you are interested in reading to 1's,
* before calling pca8574_read().
*
* Input Parameters:
* dev - Device-specific state data
* pin - The index of the pin
* valptr - Pointer to a buffer where the pin level is stored. Usually TRUE
* if the pin is high, except if OPTION_INVERT has been set on
* this pin.
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
static int pcf8575_readpin(FAR struct ioexpander_dev_s *dev, uint8_t pin,
FAR bool *value)
{
FAR struct pcf8575_dev_s *priv = (FAR struct pcf8575_dev_s *)dev;
uint16_t regval;
int ret;
if (pin > 15)
{
return -ENXIO;
}
DEBUGASSERT(priv != NULL && priv->config != NULL && value != NULL);
gpioinfo("I2C addr=%02x, pin=%u\n", priv->config->address, pin);
/* Get exclusive access to the I/O Expander */
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Is the pin an output? */
if ((priv->inpins & (1 << pin)) == 0)
{
/* We cannot read the value on pin directly. Just Return the last
* value that we wrote to the pin.
*/
*value = ((priv->outstate & (1 << pin)) != 0);
nxmutex_unlock(&priv->lock);
return OK;
}
/* It is an input pin. Read the input register for this pin
*
* The Input Port Register reflects the incoming logic levels of the pins,
* regardless of whether the pin is defined as an input or an output by
* the Configuration Register. They act only on read operation.
*/
ret = pcf8575_read(priv, &regval);
if (ret < 0)
{
gpioerr("ERROR: Failed to read port register: %d\n", ret);
goto errout_with_lock;
}
/* Return 0 or 1 to indicate the state of pin */
*value = (bool)((regval >> (pin & 0xf)) & 1);
ret = OK;
errout_with_lock:
nxmutex_unlock(&priv->lock);
return ret;
}
/****************************************************************************
* Name: pcf8575_multiwritepin
*
* Description:
* Set the pin level for multiple pins. This routine may be faster than
* individual pin accesses. Optional.
*
* Input Parameters:
* dev - Device-specific state data
* pins - The list of pin indexes to alter in this call
* val - The list of pin levels.
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
#ifdef CONFIG_IOEXPANDER_MULTIPIN
static int pcf8575_multiwritepin(FAR struct ioexpander_dev_s *dev,
FAR uint8_t *pins, FAR bool *values,
int count)
{
FAR struct pcf8575_dev_s *priv = (FAR struct pcf8575_dev_s *)dev;
uint8_t pin;
int ret;
int i;
DEBUGASSERT(priv != NULL && priv->config != NULL &&
pins != NULL && values != NULL);
gpioinfo("I2C addr=%02x count=%d\n", priv->config->address, count);
/* Get exclusive access to the I/O Expander */
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Process each pin setting */
for (i = 0; i < count; i++)
{
/* Make sure that this is an output pin */
pin = pins[i];
if (pin > 15)
{
nxmutex_unlock(&priv->lock);
return -ENXIO;
}
gpioinfo("%d. pin=%u value=%u\n", pin, values[i]);
if ((priv->inpins & (1 << pin)) != 0)
{
gpioerr("ERROR: pin%u is an input\n", pin);
continue;
}
/* Set/clear a bit in outstate. */
if (values[i])
{
priv->outstate |= (1 << pin);
}
else
{
priv->outstate &= ~(1 << pin);
}
}
/* Write the OR of the set of input pins and the set of output pins.
* In order to set the new output value.
*/
ret = pcf8575_write(priv, priv->inpins | priv->outstate);
nxmutex_unlock(&priv->lock);
return ret;
}
#endif
/****************************************************************************
* Name: pcf8575_multireadpin
*
* Description:
* Read the actual level for multiple pins. This routine may be faster than
* individual pin accesses. Optional.
*
* Input Parameters:
* dev - Device-specific state data
* pin - The list of pin indexes to read
* valptr - Pointer to a buffer where the pin levels are stored.
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
#ifdef CONFIG_IOEXPANDER_MULTIPIN
static int pcf8575_multireadpin(FAR struct ioexpander_dev_s *dev,
FAR uint8_t *pins, FAR bool *values,
int count)
{
FAR struct pcf8575_dev_s *priv = (FAR struct pcf8575_dev_s *)dev;
uint8_t regval;
uint8_t pin;
int ret;
int i;
DEBUGASSERT(priv != NULL && priv->config != NULL &&
pins != NULL && values != NULL);
gpioinfo("I2C addr=%02x, count=%d\n", priv->config->address, count);
/* Get exclusive access to the I/O Expander */
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Read the input register for this pin
*
* The Input Port Register reflects the incoming logic levels of the pins,
* regardless of whether the pin is defined as an input or an output by
* the Configuration Register. They act only on read operation.
*/
ret = pcf8575_read(priv, &regval);
if (ret < 0)
{
gpioerr("ERROR: Failed to read port register: %d\n", ret);
goto errout_with_lock;
}
/* Return the requested pin values */
for (i = 0; i < count; i++)
{
/* Make sure that this is an output pin */
pin = pins[i];
if (pin > 15)
{
nxmutex_unlock(&priv->lock);
return -ENXIO;
}
/* Is the pin an output? */
if ((priv->inpins & (1 << pin)) == 0)
{
/* We cannot read the value on pin directly. Just Return the last
* value that we wrote to the pin.
*/
values[i] = ((priv->outstate & (1 << pin)) != 0);
}
else
{
values[i] = ((regval & (1 << pin)) != 0);
}
gpioinfo("%d. pin=%u value=%u\n", pin, values[i]);
}
ret = OK;
errout_with_lock:
nxmutex_unlock(&priv->lock);
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pcf8575_initialize
*
* Description:
* Instantiate and configure the PCF8575xx device driver to use the
* provided I2C device instance.
*
* Input Parameters:
* i2c - An I2C driver instance
* minor - The device i2c address
* config - Persistent board configuration data
*
* Returned Value:
* an ioexpander_dev_s instance on success, NULL on failure.
*
****************************************************************************/
FAR struct ioexpander_dev_s *pcf8575_initialize(FAR struct i2c_master_s *i2c,
FAR struct pcf8575_config_s *config)
{
FAR struct pcf8575_dev_s *priv;
#ifdef CONFIG_PCF8575_MULTIPLE
/* Allocate the device state structure */
priv = (FAR struct pcf8575_dev_s *)
kmm_zalloc(sizeof(struct pcf8575_dev_s));
if (!priv)
{
gpioerr("ERROR: Failed to allocate driver instance\n");
return NULL;
}
#else
/* Use the one-and-only I/O Expander driver instance */
priv = &g_pcf8575;
#endif
/* Initialize the device state structure */
priv->dev.ops = &g_pcf8575_ops;
priv->i2c = i2c;
priv->config = config;
nxmutex_init(&priv->lock);
return &priv->dev;
}
#endif /* CONFIG_IOEXPANDER_PCF8575 */

View file

@ -0,0 +1,82 @@
/****************************************************************************
* drivers/ioexpander/pcf8575.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __DRIVERS_IOEXPANDER_PCF8575_H
#define __DRIVERS_IOEXPANDER_PCF8575_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/mutex.h>
#include <nuttx/ioexpander/ioexpander.h>
#include <nuttx/ioexpander/pcf8575.h>
#include <nuttx/i2c/i2c_master.h>
#if defined(CONFIG_IOEXPANDER) && defined(CONFIG_IOEXPANDER_PCF8575)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* Prerequisites:
* CONFIG_I2C
* I2C support is required
* CONFIG_IOEXPANDER
* Enables I/O expander support
*
* CONFIG_IOEXPANDER_PCF8575
* Enables support for the PCF8575 driver (Needs CONFIG_INPUT)
* CONFIG_PCF8575_MULTIPLE
* Can be defined to support multiple PCF8575 devices on board.
*/
#ifndef CONFIG_I2C
# error "CONFIG_I2C is required by PCF8575"
#endif
/* PCF8575 Definitions ******************************************************/
#define PCF8575_I2C_MAXFREQUENCY 400000 /* 400KHz */
/****************************************************************************
* Public Types
****************************************************************************/
/* This structure represents the state of the PCF8575 driver */
struct pcf8575_dev_s
{
struct ioexpander_dev_s dev; /* Nested structure to allow casting as public gpio
* expander. */
FAR struct pcf8575_config_s *config; /* Board configuration data */
FAR struct i2c_master_s *i2c; /* Saved I2C driver instance */
mutex_t lock; /* Mutual exclusion */
uint16_t inpins; /* Set of input pins */
uint16_t outstate; /* State of all output pins */
};
#endif /* CONFIG_IOEXPANDER && CONFIG_IOEXPANDER_PCF8575 */
#endif /* __DRIVERS_IOEXPANDER_PCF8575_H */

View file

@ -0,0 +1,79 @@
/****************************************************************************
* include/nuttx/ioexpander/pcf8575.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_IOEXPANDER_PCF8575_H
#define __INCLUDE_NUTTX_IOEXPANDER_PCF8575_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
/****************************************************************************
* Public Types
****************************************************************************/
/* A reference to a structure of this type must be passed to the PCF8575xx
* driver when the driver is instantiated. This structure provides
* information about the configuration of the PCF8575xx and provides some
* board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied by
* the driver and is presumed to persist while the driver is active. The
* memory must be writeable because, under certain circumstances, the driver
* may modify the frequency.
*/
struct pcf8575_config_s
{
/* Device characterization */
uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */
uint32_t frequency; /* I2C frequency */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: pcf8575_initialize
*
* Description:
* Instantiate and configure the PCF8575xx device driver to use the
* provided I2C device instance.
*
* Input Parameters:
* i2c - An I2C driver instance
* minor - The device i2c address
* config - Persistent board configuration data
*
* Returned Value:
* an ioexpander_dev_s instance on success, NULL on failure.
*
****************************************************************************/
struct i2c_master_s;
FAR struct ioexpander_dev_s *pcf8575_initialize(FAR struct i2c_master_s *i2c,
FAR struct pcf8575_config_s *config);
#endif /* __INCLUDE_NUTTX_IOEXPANDER_PCF8575_H */