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:
parent
b5f8c035a6
commit
459d9f2851
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user