Squashed commit of the following:

driver/ioexpander:  Add gpio_pin_unregister function to GPIO driver
  driver/ioexpander:  Add pinset struct to GPIO driver for interrupt pins larger than 64
  driver/ioexpander:  Initialize pintype/inttype when registering ioexpander device
  driver/ioexpander:  Add SETPINTYPE ioctl command to the GPIO driver
This commit is contained in:
zhuyanlin 2018-08-27 09:25:11 -06:00 committed by Gregory Nutt
parent b5f8c035a6
commit 459d9f2851
5 changed files with 185 additions and 13 deletions

View File

@ -189,4 +189,15 @@ config GPIO_LOWER_HALF
Enable support for a lower half driver that provides GPIO driver
support for I/O expander pins.
if GPIO_LOWER_HALF
config GPIO_LOWER_HALF_INTTYPE
int "default interrupt type for GPIO_INTERRUPT_PIN pintype"
default 14
---help---
This is the default interrupt type (IOEXPANDER_VAL_BOTH) for
GPIO_INTERRUPT_PIN pintype in gplf driver register.
endif
endmenu # IO Expander/GPIO Support

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/ioexpander/gpio.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2016, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -55,7 +55,7 @@
* Private Function Prototypes
****************************************************************************/
static int gpio_handler(FAR struct gpio_dev_s *dev);
static int gpio_handler(FAR struct gpio_dev_s *dev, uint8_t pin);
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,
@ -97,7 +97,7 @@ static const struct file_operations g_gpio_drvrops =
*
****************************************************************************/
static int gpio_handler(FAR struct gpio_dev_s *dev)
static int gpio_handler(FAR struct gpio_dev_s *dev, uint8_t pin)
{
DEBUGASSERT(dev != NULL);
(void)nxsig_kill(dev->gp_pid, dev->gp_signo);
@ -296,6 +296,17 @@ static int gpio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
/* Command: GPIOC_SETPINTYPE
* Description: Set the GPIO pin type.
* Argument: The enum gpio_pintype_e type.
*/
case GPIOC_SETPINTYPE:
{
ret = dev->gp_ops->go_setpintype(dev, arg);
}
break;
/* Unrecognized command */
default:
@ -378,4 +389,54 @@ int gpio_pin_register(FAR struct gpio_dev_s *dev, int minor)
return register_driver(devname, &g_gpio_drvrops, 0666, dev);
}
/****************************************************************************
* Name: gpio_pin_unregister
*
* Description:
* Unregister GPIO pin device driver.
*
* - Input pin types will be registered at /dev/gpinN
* - Output pin types will be registered at /dev/gpoutN
* - Interrupt pin types will be registered at /dev/gpintN
*
* Where N is the provided minor number in the range of 0-99.
*
*
****************************************************************************/
void gpio_pin_unregister(FAR struct gpio_dev_s *dev, int minor)
{
FAR const char *fmt;
char devname[16];
switch (dev->gp_pintype)
{
case GPIO_INPUT_PIN:
{
fmt = "/dev/gpin%u";
}
break;
case GPIO_OUTPUT_PIN:
{
fmt = "/dev/gpout%u";
}
break;
case GPIO_INTERRUPT_PIN:
{
fmt = "/dev/gpint%u";
}
break;
default:
return;
}
snprintf(devname, 16, fmt, (unsigned int)minor);
gpioinfo("Unregistering %s\n", devname);
(void)unregister_driver(devname);
}
#endif /* CONFIG_DEV_GPIO */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/ioexpander/gpio_lower_half.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2016, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -88,6 +88,8 @@ static int gplh_write(FAR struct gpio_dev_s *gpio, bool value);
static int gplh_attach(FAR struct gpio_dev_s *gpio, pin_interrupt_t callback);
static int gplh_enable(FAR struct gpio_dev_s *gpio, bool enable);
#endif
static int gplh_setpintype(FAR struct gpio_dev_s *gpio,
enum gpio_pintype_e pintype);
/****************************************************************************
* Private Data
@ -106,6 +108,22 @@ static const struct gpio_operations_s g_gplh_ops =
NULL, /* attach */
NULL, /* enable */
#endif
gplh_setpintype,
};
/* REVISIT: The following violates the NuttX coding standard requirement
* for C89 compatibility.
*/
static const uint32_t g_gplh_inttype[] =
{
[GPIO_INPUT_PIN] = IOEXPANDER_VAL_DISABLE,
[GPIO_INTERRUPT_PIN] = CONFIG_GPIO_LOWER_HALF_INTTYPE,
[GPIO_INTERRUPT_HIGH_PIN] = IOEXPANDER_VAL_HIGH,
[GPIO_INTERRUPT_LOW_PIN] = IOEXPANDER_VAL_LOW,
[GPIO_INTERRUPT_RISING_PIN] = IOEXPANDER_VAL_RISING,
[GPIO_INTERRUPT_FALLING_PIN] = IOEXPANDER_VAL_FALLING,
[GPIO_INTERRUPT_BOTH_PIN] = IOEXPANDER_VAL_BOTH,
};
/****************************************************************************
@ -135,7 +153,7 @@ static int gplh_handler(FAR struct ioexpander_dev_s *ioe,
* upper half GPIO driver via its callback.
*/
return priv->callback(&priv->gpio);
return priv->callback(&priv->gpio, priv->pin);
}
#endif
@ -258,7 +276,11 @@ static int gplh_enable(FAR struct gpio_dev_s *gpio, bool enable)
else if (priv->handle == NULL)
{
#if CONFIG_IOEXPANDER_NPINS <= 64
ioe_pinset_t pinset = ((ioe_pinset_t)1 << priv->pin);
#else
ioe_pinset_t pinset = ((ioe_pinset_t)priv->pin);
#endif
/* We have a callback and the callback is not yet attached.
* do it now.
@ -302,6 +324,39 @@ static int gplh_enable(FAR struct gpio_dev_s *gpio, bool enable)
}
#endif
/****************************************************************************
* Name: gplh_setpintype
*
* Description:
* Set I/O expander pin to an appointed gpiopintype
*
****************************************************************************/
static int gplh_setpintype(FAR struct gpio_dev_s *gpio, enum gpio_pintype_e pintype)
{
FAR struct gplh_dev_s *priv = (FAR struct gplh_dev_s *)gpio;
FAR struct ioexpander_dev_s *ioe = priv->ioe;
uint8_t pin = priv->pin;
if (pintype >= GPIO_NPINTYPES)
{
return -EINVAL;
}
else if (pintype == GPIO_OUTPUT_PIN)
{
IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_OUT);
}
else
{
IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_IN);
IOEXP_SETOPTION(ioe, pin, IOEXPANDER_OPTION_INTCFG,
(FAR void *)g_gplh_inttype[pintype]);
}
gpio->gp_pintype = pintype;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -360,6 +415,17 @@ int gpio_lower_half(FAR struct ioexpander_dev_s *ioe, unsigned int pin,
gpio->gp_pintype = (uint8_t)pintype;
gpio->gp_ops = &g_gplh_ops;
if (pintype == GPIO_OUTPUT_PIN)
{
IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_OUT);
}
else
{
IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_IN);
IOEXP_SETOPTION(ioe, pin, IOEXPANDER_OPTION_INTCFG,
(FAR void *)g_gplh_inttype[pintype]);
}
/* Register the GPIO driver */
ret = gpio_pin_register(gpio, minor);

View File

@ -75,6 +75,11 @@
* Command: GPIOC_UNREGISTER
* Description: Stop receiving signals for pin interrupts.
* Argument: None.
*
* Command: GPIOC_SETPINTYPE
* Description: Set the GPIO pin type.
* Argument: The enum gpio_pintype_e type.
*
*/
#define GPIOC_WRITE _GPIOC(1)
@ -82,6 +87,7 @@
#define GPIOC_PINTYPE _GPIOC(3)
#define GPIOC_REGISTER _GPIOC(4)
#define GPIOC_UNREGISTER _GPIOC(5)
#define GPIOC_SETPINTYPE _GPIOC(6)
/****************************************************************************
* Public Types
@ -94,6 +100,11 @@ enum gpio_pintype_e
GPIO_INPUT_PIN = 0,
GPIO_OUTPUT_PIN,
GPIO_INTERRUPT_PIN,
GPIO_INTERRUPT_HIGH_PIN,
GPIO_INTERRUPT_LOW_PIN,
GPIO_INTERRUPT_RISING_PIN,
GPIO_INTERRUPT_FALLING_PIN,
GPIO_INTERRUPT_BOTH_PIN,
GPIO_NPINTYPES
};
@ -110,6 +121,7 @@ typedef CODE int (*pin_interrupt_t)(FAR struct gpio_dev_s *dev);
* for other pin types may be NULL.
* - go_attach and gp_eanble. Required only the GPIO_INTERRUPT_PIN pin
* type. Unused for other pin types may be NULL.
* - go_setpinytype. Required for all all pin types.
*/
struct gpio_dev_s;
@ -122,6 +134,8 @@ struct gpio_operations_s
CODE int (*go_attach)(FAR struct gpio_dev_s *dev,
pin_interrupt_t callback);
CODE int (*go_enable)(FAR struct gpio_dev_s *dev, bool enable);
CODE int (*go_setpintype)(FAR struct gpio_dev_s *dev,
enum gpio_pintype_e pintype);
};
/* Pin interface definition. Must lie in writable memory. */
@ -177,6 +191,23 @@ extern "C"
int gpio_pin_register(FAR struct gpio_dev_s *dev, int minor);
/****************************************************************************
* Name: gpio_pin_unregister
*
* Description:
* Unregister GPIO pin device driver.
*
* - Input pin types will be registered at /dev/gpinN
* - Output pin types will be registered at /dev/gpoutN
* - Interrupt pin types will be registered at /dev/gpintN
*
* Where N is the provided minor number in the range of 0-99.
*
*
****************************************************************************/
void gpio_pin_unregister(FAR struct gpio_dev_s *dev, int minor);
/****************************************************************************
* Name: gpio_lower_half
*

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/ioexpander/ioexpander.h
*
* Copyright (C) 2015-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2015-2016, 2018 Gregory Nutt. All rights reserved.
* Author: Sebastien Lorquet <sebastien@lorquet.fr>
*
* Redistribution and use in source and binary forms, with or without
@ -41,6 +41,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef CONFIG_IOEXPANDER
@ -55,10 +56,6 @@
# define CONFIG_IOEXPANDER_NPINS 16
#endif
#if CONFIG_IOEXPANDER_NPINS > 64
# error No support for devices with more than 64 pins
#endif
/* Pin definitions **********************************************************/
#define IOEXPANDER_DIRECTION_IN 0
@ -101,7 +98,7 @@
*
****************************************************************************/
#define IOEXP_SETDIRECTION(dev,pin,dir) ((dev)->ops->ioe_direction(dev,pin,dir))
#define IOEXP_SETDIRECTION(dev,pin,dir) ((dev)->ops->ioe_direction(dev,pin,dir))
/****************************************************************************
* Name: IOEXP_SETOPTION
@ -293,7 +290,11 @@
* Public Types
****************************************************************************/
/* This type represents a bitmap of pins */
/* This type represents a bitmap of pins
*
* For IOE NPINS greater than 64, ioe_pinset_t represent one interrupt pin
* number instead of a bitmap of pins.
*/
#if CONFIG_IOEXPANDER_NPINS <= 8
typedef uint8_t ioe_pinset_t;
@ -301,8 +302,10 @@ typedef uint8_t ioe_pinset_t;
typedef uint16_t ioe_pinset_t;
#elif CONFIG_IOEXPANDER_NPINS <= 32
typedef uint32_t ioe_pinset_t;
#else /* if CONFIG_IOEXPANDER_NPINS <= 64 */
#elif CONFIG_IOEXPANDER_NPINS <= 64
typedef uint64_t ioe_pinset_t;
#else
typedef uint8_t ioe_pinset_t;
#endif
#ifdef CONFIG_IOEXPANDER_INT_ENABLE