From ae19ca45e0f0566a5733f77fe132a6cc8b64206f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 24 Jun 2016 09:43:49 -0600 Subject: [PATCH] drivrs/ioexpander: Add support for a very simple GPIO drivers. It supports only pre-conrigured input and output pins and only basic input and output operations. --- drivers/Kconfig | 10 -- drivers/ioexpander/Kconfig | 22 +++ drivers/ioexpander/Make.defs | 20 +++ drivers/ioexpander/gpio.c | 269 +++++++++++++++++++++++++++++ include/nuttx/fs/ioctl.h | 6 + include/nuttx/ioexpander/gpio.h | 132 ++++++++++++++ include/nuttx/ioexpander/pca9555.h | 40 +++-- 7 files changed, 475 insertions(+), 24 deletions(-) create mode 100644 drivers/ioexpander/gpio.c create mode 100644 include/nuttx/ioexpander/gpio.h diff --git a/drivers/Kconfig b/drivers/Kconfig index fbb5f5942fe..011850d6c90 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -370,17 +370,7 @@ if INPUT source drivers/input/Kconfig endif # INPUT -menuconfig IOEXPANDER - bool "IO Expander 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 - source drivers/lcd/Kconfig source drivers/leds/Kconfig diff --git a/drivers/ioexpander/Kconfig b/drivers/ioexpander/Kconfig index 438beeed5ac..fd6abd77155 100644 --- a/drivers/ioexpander/Kconfig +++ b/drivers/ioexpander/Kconfig @@ -3,6 +3,17 @@ # see the file kconfig-language.txt in the NuttX tools repository. # +menu "IO Expander/GPIO Support" + +config IOEXPANDER + bool "Enable IO Expander Support" + default n + ---help--- + This directory holds implementations of IO expander drivers. + See include/nuttx/ioexpander/ioexpander.h for registration information. + +if IOEXPANDER + config IOEXPANDER_PCA9555 bool "PCA9555 I2C IO expander" default n @@ -40,3 +51,14 @@ config IOEXPANDER_MULTIPIN ---help--- This settings enable the definition of routines for optimized simultaneous access to multiple pins. + +endif # IOEXPANDER + +config DEV_GPIO + bool "GPIO driver" + default n + ---help--- + Enables a simple GPIO input/output driver to support application- + space testing of hardware. + +endmenu # IO Expander/GPIO Support diff --git a/drivers/ioexpander/Make.defs b/drivers/ioexpander/Make.defs index aea59aea51d..37e669fe943 100644 --- a/drivers/ioexpander/Make.defs +++ b/drivers/ioexpander/Make.defs @@ -43,6 +43,26 @@ ifeq ($(CONFIG_IOEXPANDER_PCA9555),y) CSRCS += pca9555.c endif +endif # CONFIG_IOEXPANDER + +# GPIO test device driver (independent of IOEXPANDERS) + +ifeq ($(CONFIG_DEV_GPIO),y) + CSRCS += gpio.c +endif + +# The folling implements an awkward OR + +ifeq ($(CONFIG_IOEXPANDER),y) + +# Include ioexpander I/O device driver build support + +DEPPATH += --dep-path ioexpander +VPATH += :ioexpander +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)ioexpander} + +else ifeq ($(CONFIG_DEV_GPIO),y) + # Include ioexpander I/O device driver build support DEPPATH += --dep-path ioexpander diff --git a/drivers/ioexpander/gpio.c b/drivers/ioexpander/gpio.c new file mode 100644 index 00000000000..2d5ffa9b35f --- /dev/null +++ b/drivers/ioexpander/gpio.c @@ -0,0 +1,269 @@ +/**************************************************************************** + * drivers/ioexpander/gpio.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifdef CONFIG_DEV_GPIO + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int gpio_open(FAR struct file *filep); +static int gpio_close(FAR struct file *filep); +static ssize_t gpio_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t gpio_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int gpio_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_gpio_input_ops = +{ + gpio_open, /* open */ + gpio_close, /* close */ + gpio_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + gpio_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , NULL /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +static const struct file_operations g_gpio_output_ops = +{ + gpio_open, /* open */ + gpio_close, /* close */ + NULL, /* read */ + gpio_write, /* write */ + NULL, /* seek */ + gpio_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , NULL /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gpio_open + * + * Description: + * Standard character driver open method. + * + ****************************************************************************/ + +static int gpio_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: gpio_close + * + * Description: + * Standard character driver close method. + * + ****************************************************************************/ + +static int gpio_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: gpio_read + * + * Description: + * Standard character driver read method. + * + ****************************************************************************/ + +static ssize_t gpio_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + return 0; +} + +/**************************************************************************** + * Name: gpio_write + * + * Description: + * Standard character driver write method. + * + ****************************************************************************/ + +static ssize_t gpio_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return (ssize_t)buflen; +} + +/**************************************************************************** + * Name: gpio_ioctl + * + * Description: + * Standard character driver ioctl method. + * + ****************************************************************************/ + +static int gpio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct gpio_common_dev_s *dev; + int ret = OK; + + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + inode = filep->f_inode; + DEBUGASSERT(inode->i_private != NULL); + dev = inode->i_private; + + switch (cmd) + { + /* Command: GPIO_WRITE + * Description: Set the value of an output GPIO + * Argument: 0=output a low value; 1=outut a high value + */ + + case GPIO_WRITE: + if (dev->output) + { + FAR struct gpio_output_dev_s *outdev = + (FAR struct gpio_output_dev_s *)dev; + + DEBUGASSERT(outdev->gpout_write != NULL); + ret = outdev->gpout_write(outdev, (int)arg); + } + else + { + ret = -EACCES; + } + break; + + /* Command: GPIO_READ + * Description: Read the value of an input or output GPIO + * Argument: A pointer to an integer value to receive the result: + * 0=low value; 1=high value. + */ + + case GPIO_READ: + if (dev->output) + { + FAR struct gpio_output_dev_s *outdev = + (FAR struct gpio_output_dev_s *)dev; + + DEBUGASSERT(outdev->gpout_read != NULL); + ret = outdev->gpout_read(outdev); + } + else + { + FAR struct gpio_input_dev_s *indev = + (FAR struct gpio_input_dev_s *)dev; + + DEBUGASSERT(indev->gpin_read != NULL); + ret = indev->gpin_read(indev); + } + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gpio_input_register + * + * Description: + * Register GPIO input pin device driver. + * + ****************************************************************************/ + +int gpio_input_register(FAR struct gpio_input_dev_s *dev, int minor) +{ + char devname[16]; + + DEBUGASSERT((unsigned int)minor < 100); + snprintf(devname, 16, "/dev/gpin%u", (unsigned int)minor); + + return register_driver(devname, &g_gpio_input_ops, 0444, dev); +} + +/**************************************************************************** + * Name: gpio_output_register + * + * Description: + * Register GPIO output pin device driver. + * + ****************************************************************************/ + +int gpio_output_register(FAR struct gpio_output_dev_s *dev, int minor) +{ + char devname[16]; + + DEBUGASSERT((unsigned int)minor < 100); + snprintf(devname, 16, "/dev/gpout%u", (unsigned int)minor); + + return register_driver(devname, &g_gpio_output_ops, 0222, dev); +} + +#endif /* CONFIG_DEV_GPIO */ diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index e404057d7e6..b79c783923f 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -83,6 +83,7 @@ #define _LOOPBASE (0x1e00) /* Loop device commands */ #define _MODEMBASE (0x1f00) /* Modem ioctl commands */ #define _I2CBASE (0x2000) /* I2C driver commands */ +#define _GPIOBASE (0x2100) /* GPIO driver commands */ /* boardctl commands share the same number space */ @@ -381,6 +382,11 @@ #define _I2CIOCVALID(c) (_IOC_TYPE(c)==_I2CBASE) #define _I2CIOC(nr) _IOC(_I2CBASE,nr) +/* GPIO driver command definitions ******************************************/ + +#define _GPIOCVALID(c) (_IOC_TYPE(c)==_GPIOBASE) +#define _GPIOC(nr) _IOC(_GPIOBASE,nr) + /* boardctl() command definitions *******************************************/ #define _BOARDIOCVALID(c) (_IOC_TYPE(c)==_BOARDBASE) diff --git a/include/nuttx/ioexpander/gpio.h b/include/nuttx/ioexpander/gpio.h new file mode 100644 index 00000000000..5d6e7917467 --- /dev/null +++ b/include/nuttx/ioexpander/gpio.h @@ -0,0 +1,132 @@ +/******************************************************************************************** + * include/nuttx/ioexpander/gpio.h + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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_GPIO_H +#define __INCLUDE_NUTTX_IOEXPANDER_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Command: GPIO_WRITE + * Description: Set the value of an output GPIO + * Argument: 0=output a low value; 1=outut a high value + * + * Command: GPIO_READ + * Description: Read the value of an input or output GPIO + * Argument: A pointer to an integer value to receive the result: + * 0=low value; 1=high value. + */ + +#define GPIO_WRITE _GPIOC(1) +#define GPIO_READ _GPIOC(2) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Common interface definition. Must be cast-compatible with struct + * gpio_input_dev_s and struct gpio_output_dev_s + */ + +struct gpio_common_dev_s +{ + bool output; + uint8_t unused[3]; +}; + +/* The interface to a GPIO input pin */ + +struct gpio_input_dev_s +{ + bool output; + uint8_t unused[3]; + CODE int (*gpin_read)(FAR struct gpio_input_dev_s *dev); +}; + +/* The interface to a GPIO input pin */ + +struct gpio_output_dev_s +{ + bool output; + uint8_t unused[3]; + CODE int (*gpout_read)(FAR struct gpio_output_dev_s *dev); + CODE int (*gpout_write)(FAR struct gpio_output_dev_s *dev, int value); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: gpio_input_register + * + * Description: + * Register GPIO input pin device driver. + * + ****************************************************************************/ + +int gpio_input_register(FAR struct gpio_input_dev_s *dev, int minor); + +/**************************************************************************** + * Name: gpio_output_register + * + * Description: + * Register GPIO output pin device driver. + * + ****************************************************************************/ + +int gpio_output_register(FAR struct gpio_output_dev_s *dev, int minor); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_IOEXPANDER_GPIO_H */ diff --git a/include/nuttx/ioexpander/pca9555.h b/include/nuttx/ioexpander/pca9555.h index aa0b3c28635..3a99a7def32 100644 --- a/include/nuttx/ioexpander/pca9555.h +++ b/include/nuttx/ioexpander/pca9555.h @@ -1,4 +1,4 @@ -/******************************************************************************************** +/**************************************************************************** * include/nuttx/ioexpander/pca9555.h * * Copyright (C) 2015 Gregory Nutt. All rights reserved. @@ -35,20 +35,31 @@ * 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 +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include #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. +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* 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. + * 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 @@ -81,9 +92,9 @@ struct pca9555_config_s #endif }; -/******************************************************************************************** +/**************************************************************************** * Public Function Prototypes - ********************************************************************************************/ + ****************************************************************************/ #ifdef __cplusplus #define EXTERN extern "C" @@ -93,11 +104,12 @@ extern "C" #define EXTERN extern #endif -/******************************************************************************************** +/**************************************************************************** * Name: pca9555_initialize * * Description: - * Instantiate and configure the PCA9555 device driver to use the provided I2C device + * Instantiate and configure the PCA9555 device driver to use the provided + * I2C device * instance. * * Input Parameters: @@ -108,9 +120,9 @@ extern "C" * Returned Value: * an ioexpander_dev_s instance on success, NULL on failure. * - ********************************************************************************************/ + ****************************************************************************/ -FAR struct ioexpander_dev_s* pca9555_initialize(FAR struct i2c_master_s *dev, +FAR struct ioexpander_dev_s *pca9555_initialize(FAR struct i2c_master_s *dev, FAR struct pca9555_config_s *config); #ifdef __cplusplus