diff --git a/drivers/Kconfig b/drivers/Kconfig index fb626f87e63..b94ad60f990 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -285,6 +285,17 @@ if INPUT source drivers/input/Kconfig endif # INPUT +menuconfig IOEXPANDER + bool "IO Expanders Support" + default n + ---help--- + This directory holds implementations of IO expander drivers. + See include/nuttx/ioexpander/ioexpander.h for registration information. + +if IOEXPANDER +source drivers/ioexpander/Kconfig +endif # IOEXPANDER + menuconfig LCD bool "LCD Driver Support" default n diff --git a/drivers/Makefile b/drivers/Makefile index 6f3d0c04af2..086cecb2ad1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -53,6 +53,7 @@ include analog$(DELIM)Make.defs include audio$(DELIM)Make.defs include bch$(DELIM)Make.defs include input$(DELIM)Make.defs +include ioexpander$(DELIM)Make.defs include lcd$(DELIM)Make.defs include mmcsd$(DELIM)Make.defs include mtd$(DELIM)Make.defs diff --git a/drivers/ioexpander/Kconfig b/drivers/ioexpander/Kconfig new file mode 100644 index 00000000000..67aeb58836a --- /dev/null +++ b/drivers/ioexpander/Kconfig @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config IOEXPANDER_PCA9555 + bool "PCA9555 I2C IO expander" + default n + select I2C + ---help--- + Enable support for the NXP PCA9555 IO Expander + +if IOEXPANDER_PCA9555 + +config PCA9555_MULTIPLE + bool "Multiple PCA9555 Devices" + default n + ---help--- + Can be defined to support multiple PCA9555 devices on board. + +config PCA9555_INT_DISABLE + bool "Disable PCA9555 Interrupt Support" + default y + ---help--- + Disable driver interrupt functionality + +endif # IOEXPANDER_PCA9555 diff --git a/drivers/ioexpander/Make.defs b/drivers/ioexpander/Make.defs new file mode 100644 index 00000000000..7e34efa8b0c --- /dev/null +++ b/drivers/ioexpander/Make.defs @@ -0,0 +1,52 @@ +############################################################################ +# drivers/ioexpander/Make.defs +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Sebastien Lorquet +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Don't build anything if there is no support for io expander devices + +ifeq ($(CONFIG_IOEXPANDER),y) + +# Include the selected io expander drivers + +ifeq ($(CONFIG_IOEXPANDER_PCA9555),y) + CSRCS += pca9555.c +endif + +# Include io expander device driver build support + +DEPPATH += --dep-path ioexpander +VPATH += :ioexpander +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)ioexpander} + +endif diff --git a/drivers/ioexpander/pca9555.c b/drivers/ioexpander/pca9555.c new file mode 100644 index 00000000000..7630d680061 --- /dev/null +++ b/drivers/ioexpander/pca9555.c @@ -0,0 +1,388 @@ +/**************************************************************************** + * drivers/ioexpander/pca9555.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * References: + * "16-bit I2C-bus and SMBus I/O port with interrupt product datasheet", + * Rev. 08 - 22 October 2009, NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "pca9555.h" + +#if defined(CONFIG_IOEXPANDER_PCA9555) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_I2C +# warning I2C support is required (CONFIG_I2C) +#endif + +#ifndef CONFIG_I2C_WRITEREAD +# warning Support of the I2C writeread() method is required (CONFIG_I2C_WRITEREAD) +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int pca9555_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int dir); +static int pca9555_option (FAR struct ioexpander_dev_s *dev, uint8_t pin, + int opt, void *val); +static int pca9555_write (FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool value); +static int pca9555_readpin (FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool *value); +static int pca9555_readbuf (FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool *value); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifndef CONFIG_PCA9555_MULTIPLE +/* If only a single PCA9555 device is supported, then the driver state + * structure may as well be pre-allocated. + */ + +static struct pca9555_dev_s g_pca9555; + +/* Otherwise, we will need to maintain allocated driver instances in a list */ + +#else +static struct pca9555_dev_s *g_pca9555list; +#endif + +static const struct ioexpander_ops_s g_pca9555_ops = +{ + pca9555_direction, + pca9555_option, + pca9555_write, + pca9555_readpin, + pca9555_readbuf, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pca9555_setbit + * + * Description: + * Write a bit in a register pair + * + ****************************************************************************/ + +static int pca9555_setbit(FAR struct i2c_dev_s *i2c, uint8_t addr, + uint8_t pin, int bitval) +{ + int ret; + uint8_t buf[2]; + buf[0] = addr; + + if(pin>15) + { + return -ENXIO; + } + else if(pin>7) + { + addr += 1; + pin -= 8; + } + + ret = I2C_WRITEREAD(i2c, &addr, 1, &buf[1], 1); + if(ret != 0) + { + return ret; + } + + if(bitval) + { + buf[1] |= (1<15) + { + return -ENXIO; + } + else if(pin>7) + { + addr += 1; + pin -= 8; + } + + ret = I2C_WRITEREAD(i2c, &addr, 1, &buf, 1); + if(ret != 0) + { + return ret; + } + *val = (buf >> pin) & 1; + + return 0; +} + +/**************************************************************************** + * Name: pca9555_direction + * + * Description: + * See include/nuttx/ioexpander/ioexpander.h + * + ****************************************************************************/ + +static int pca9555_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int direction) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s*)dev; + return pca9555_setbit(pca->i2c, PCA9555_REG_CONFIG, pin, + (direction == IOEXPANDER_DIRECTION_IN)); +} + +/**************************************************************************** + * Name: pca9555_option + * + * Description: + * See include/nuttx/ioexpander/ioexpander.h + * + ****************************************************************************/ + +static int pca9555_option(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int opt, void *val) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s*)dev; + int ival = (int)val; + + if(opt == IOEXPANDER_OPTION_INVERT) + { + return pca9555_setbit(pca->i2c, PCA9555_REG_POLINV, pin, ival); + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: pca9555_write + * + * Description: + * See include/nuttx/ioexpander/ioexpander.h + * + ****************************************************************************/ + +static int pca9555_write(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool value) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s*)dev; + return pca9555_setbit(pca->i2c, PCA9555_REG_OUTPUT, pin, value); +} + +/**************************************************************************** + * Name: pca9555_readpin + * + * Description: + * See include/nuttx/ioexpander/ioexpander.h + * + ****************************************************************************/ + +static int pca9555_readpin(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool *value) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s*)dev; + return pca9555_getbit(pca->i2c, PCA9555_REG_INPUT, pin, value); +} + +/**************************************************************************** + * Name: pca9555_readbuf + * + * Description: + * See include/nuttx/ioexpander/ioexpander.h + * + ****************************************************************************/ + +static int pca9555_readbuf(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool *value) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s*)dev; + return pca9555_getbit(pca->i2c, PCA9555_REG_OUTPUT, pin, value); +} + +#ifndef CONFIG_PCA9555_INT_DISABLE + +/**************************************************************************** + * Name: pca9555_gpioworker + * + * Description: + * See include/nuttx/ioexpander/ioexpander.h + * + ****************************************************************************/ + +static int pca9555_attach(FAR struct ioexpander_dev_s *dev, uint8_t pin, + ioexpander_handler_t handler) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s*)dev; + return 0; +} + +/**************************************************************************** + * Name: pca9555_irqworker + * + * Description: + * Handle GPIO interrupt events (this function actually executes in the + * context of the worker thread). + * + ****************************************************************************/ + +static void pca9555_irqworker(FAR struct pca9555_dev_s *priv) +{ + uint8_t regval; + uint8_t pinmask; + int pin; + + /* Get the set of pending GPIO interrupts */ + + /* Look at each pin */ + + for (pin = 0; pin < PCA9555_GPIO_NPINS; pin++) + { + /* Check if we have a handler for this interrupt (there should + * be one) + */ + + /* Interrupt is pending... dispatch the interrupt to the + * callback + */ + + /* Clear the pending GPIO interrupt by writing a '1' to the + * pin position in the status register. + */ + + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pca9555_initialize + * + * Description: + * Initialize a PCA9555 I2C device. + * + * TODO: Actually support more than one device. + * + ****************************************************************************/ + +FAR struct ioexpander_dev_s *pca9555_initialize(FAR struct i2c_dev_s *i2cdev, + FAR struct pca9555_config_s *config) +{ + FAR struct pca9555_dev_s *pcadev; + + DEBUGASSERT(i2cdev != NULL && config != NULL); + +#ifdef CONFIG_PCA9555_MULTIPLE + /* Allocate the device state structure */ + + pcadev = (FAR struct pca9555_dev_s *)kmm_zalloc(sizeof(struct pca9555_dev_s)); + if (!pcadev) + { + return NULL; + } + + /* And save the device structure in the list of PCA9555 so that we can + * find it later. + */ + + pcadev->flink = g_pca9555list; + g_pca9555list = pcadev; + +#else + /* Use the one-and-only PCA9555 driver instance */ + + pcadev = &g_pca9555; +#endif + + /* Initialize the device state structure */ + + pcadev->i2c = i2cdev; + pcadev->dev.ops = &g_pca9555_ops; + + /* Set the I2C address and frequency. REVISIT: This logic would be + * insufficient if we share the I2C bus with any other devices that also + * modify the address and frequency. + */ + + I2C_SETADDRESS(i2cdev, config->address, 7); + I2C_SETFREQUENCY(i2cdev, config->frequency); + + return &pcadev->dev; +} + +#endif /* CONFIG_IOEXPANDER_PCA9555 */ + diff --git a/drivers/ioexpander/pca9555.h b/drivers/ioexpander/pca9555.h new file mode 100644 index 00000000000..ef0495a9f4c --- /dev/null +++ b/drivers/ioexpander/pca9555.h @@ -0,0 +1,142 @@ +/******************************************************************************************** + * drivers/ioexpander/pca9555.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * References: + * "16-bit I2C-bus and SMBus I/O port with interrupt product datasheet", + * Rev. 08 - 22 October 2009, NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __DRIVERS_IOEXPANDER_PCA9555_H +#define __DRIVERS_IOEXPANDER_PCA9555_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#if defined(CONFIG_IOEXPANDER) && defined(CONFIG_IOEXPANDER_PCA9555) + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ +/* Configuration ****************************************************************************/ +/* Prerequisites: + * CONFIG_I2C + * I2C support is required + * CONFIG_I2C_WRITEREAD + * Support for the I2C writeread method is required. + * CONFIG_IOEXPANDER + * Enables support for the PCA9555 I/O expander + * + * Other settings that effect the driver: CONFIG_DISABLE_POLL + * + * CONFIG_IOEXPANDER_PCA9555 + * Enables support for the PCA9555 driver (Needs CONFIG_INPUT) + * CONFIG_PCA9555_MULTIPLE + * Can be defined to support multiple PCA9555 devices on board. + * CONFIG_PCA9555_INT_DISABLE + * Disable driver GPIO interrupt functionality (ignored if GPIO functionality is + * disabled). + */ + +#undef CONFIG_PCA9555_REFCNT + +/* Driver support ***************************************************************************/ +/* This format is used to construct the /dev/input[n] device driver path. It defined here + * so that it will be used consistently in all places. + */ + +/* PCA9555 Resources ************************************************************************/ + +#define PCA9555_GPIO_NPINS 16 /* All pins can be used as GPIOs */ + +#ifndef CONFIG_I2C +#error "CONFIG_I2C is required by PCA9555" +#endif + +#ifndef CONFIG_PCA9555_INT_DISABLE +#ifndef CONFIG_SCHED_WORKQUEUE +#error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected." +#endif +#endif + +#define PCA9555_MAXDEVS 8 + +/* I2C frequency */ + +#define PCA9555_I2C_MAXFREQUENCY 400000 /* 400KHz */ + +/* PCA9555 Registers ************************************************************************/ +/* Register Addresses */ + +#define PCA9555_REG_INPUT 0x00 +#define PCA9555_REG_OUTPUT 0x02 +#define PCA9555_REG_POLINV 0x04 +#define PCA9555_REG_CONFIG 0x06 + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/* This structure represents the state of the PCA9555 driver */ + +struct pca9555_dev_s +{ + struct ioexpander_dev_s dev; /* Nested structure to allow casting as public gpio expander. */ + +#ifdef CONFIG_PCA9555_MULTIPLE + FAR struct pca9555_dev_s *flink; /* Supports a singly linked list of drivers */ +#endif + + FAR struct pca9555_config_s *config; /* Board configuration data */ + FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */ + +#ifndef CONFIG_PCA9555_INT_DISABLE + struct work_s work; /* Supports the interrupt handling "bottom half" */ + pca9555_handler_t handlers[PCA9555_GPIO_NPINS]; /* GPIO "interrupt handlers" */ +#endif +}; + +#endif /* CONFIG_IOEXPANDER && CONFIG_IOEXPANDER_PCA9555 */ +#endif /* __DRIVERS_IOEXPANDER_PCA9555_H */ diff --git a/include/nuttx/ioexpander/ioexpander.h b/include/nuttx/ioexpander/ioexpander.h new file mode 100644 index 00000000000..33ec4705034 --- /dev/null +++ b/include/nuttx/ioexpander/ioexpander.h @@ -0,0 +1,184 @@ +/**************************************************************************** + * include/nuttx/ioexpander/ioexpander.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_IOEXPANDER_IOEXPANDER_H +#define __INCLUDE_NUTTX_IOEXPANDER_IOEXPANDER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_IOEXPANDER) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IOEXPANDER_DIRECTION_IN 0 +#define IOEXPANDER_DIRECTION_OUT 1 + +/* Pin options */ + +#define IOEXPANDER_OPTION_INVERT 1 /* set the "active" level for the line */ + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: IOEXP_SETDIRECTION + * + * Description: + * Set the direction of an ioexpander pin. Required. + * + * 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 + * + ****************************************************************************/ + +#define IOEXP_SETDIRECTION(dev,pin,dir) ((dev)->ops->ioe_direction(dev,pin,dir)) + +/**************************************************************************** + * Name: IOEXP_SETOPTION + * + * 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 + * + ****************************************************************************/ + +#define IOEXP_SETOPTION(dev,pin,opt,val) ((dev)->ops->ioe_option(dev,pin,opt,val)) + +/**************************************************************************** + * Name: IOEXP_WRITE + * + * 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 + * + ****************************************************************************/ + +#define IOEXP_WRITEPIN(dev,pin,val) ((dev)->ops->ioe_writepin(dev,pin,val)) + +/**************************************************************************** + * Name: IOEXP_READPIN + * + * Description: + * Read the actual PIN level. This can be different from the last value written + * to this pin. Required. + * + * 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 + * + ****************************************************************************/ + +#define IOEXP_READPIN(dev,pin,valptr) ((dev)->ops->ioe_readpin(dev,pin,valptr)) + +/**************************************************************************** + * Name: IOEXP_READBUF + * + * Description: + * Read the buffered pin level. + * This can be different from the actual pin state. Required. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The index of the pin + * valptr - Pointer to a buffer where the level is stored. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define IOEXP_READBUF(dev,pin,valptr) ((dev)->ops->ioe_readbuf(dev,pin,valptr)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct ioexpander_dev_s; + +struct ioexpander_ops_s +{ + CODE int (*ioe_direction)(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int direction); + CODE int (*ioe_option)(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int opt, void *val); + CODE int (*ioe_write)(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool value); + CODE int (*ioe_readpin)(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool *value); + CODE int (*ioe_readbuf)(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool *value); +}; + +struct ioexpander_dev_s +{ + FAR const struct ioexpander_ops_s *ops; +}; + +#endif //CONFIG_IOEXPANDER +#endif //__INCLUDE_NUTTX_IOEXPANDER_IOEXPANDER_H + diff --git a/include/nuttx/ioexpander/pca9555.h b/include/nuttx/ioexpander/pca9555.h new file mode 100644 index 00000000000..b8c857a3e7e --- /dev/null +++ b/include/nuttx/ioexpander/pca9555.h @@ -0,0 +1,123 @@ +/******************************************************************************************** + * include/nuttx/ioexpander/pca9555.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * References: + * "16-bit I2C-bus and SMBus I/O port with interrupt product datasheet", + * Rev. 08 - 22 October 2009, NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_IOEXPANDER_PCA9555_H +#define __INCLUDE_NUTTX_IOEXPANDER_PCA9555_H + +#include + +/* A reference to a structure of this type must be passed to the PCA9555 driver when the + * driver is instantiated. This structure provides information about the configuration of + * the PCA9555 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 pca9555_config_s +{ + /* Device characterization */ + + uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */ + uint32_t frequency; /* I2C or SPI frequency */ + + /* If multiple PCA9555 devices are supported, then an IRQ number must + * be provided for each so that their interrupts can be distinguished. + */ + +#ifndef CONFIG_PCA9555_INT_DISABLE +/* IRQ support TODO */ + +#ifdef CONFIG_PCA9555_MULTIPLE + int irq; /* IRQ number received by interrupt handler. */ +#endif + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the PCA9555 driver from differences in GPIO + * interrupt handling by varying boards and MCUs. + * + * attach - Attach the PCA9555 interrupt handler to the GPIO interrupt + * enable - Enable or disable the GPIO interrupt + * clear - Acknowledge/clear any pending GPIO interrupt + */ + + CODE int (*attach)(FAR struct pca9555_config_s *state, xcpt_t isr); + CODE void (*enable)(FAR struct pca9555_config_s *state, bool enable); + CODE void (*clear)(FAR struct pca9555_config_s *state); +#endif +}; + +/******************************************************************************************** + * Public Function Prototypes + ********************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/******************************************************************************************** + * Name: pca9555_initialize + * + * Description: + * Instantiate and configure the PCA9555 device driver to use the provided I2C device + * instance. + * + * Input Parameters: + * dev - 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* pca9555_initialize(FAR struct i2c_dev_s *dev, + FAR struct pca9555_config_s *config); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_IOEXPANDER_PCA9555_H */