From a349595316562ff7bef8147215c1442f9ffa1e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beat=20K=C3=BCng?= Date: Thu, 2 Jul 2020 12:47:58 +0200 Subject: [PATCH] gpio: extend gpio_pintype_e for pulldown/up and opendrain - fix code style - fix bool conversion when calling go_read() --- arch/sim/src/sim/up_ioexpander.c | 10 +++++++--- drivers/analog/lmp92001.c | 10 +++++++--- drivers/ioexpander/gpio.c | 14 +++++++++++--- drivers/ioexpander/gpio_lower_half.c | 26 +++++++++++++++++++++++--- drivers/ioexpander/pca9538.c | 6 ++++++ drivers/ioexpander/pca9555.c | 6 ++++++ drivers/ioexpander/pcf8574.c | 10 +++++++--- drivers/ioexpander/skeleton.c | 14 ++++++++++---- drivers/ioexpander/tca64xx.c | 10 +++++++--- include/nuttx/ioexpander/gpio.h | 9 ++++++--- include/nuttx/ioexpander/ioexpander.h | 18 +++++++++++------- 11 files changed, 101 insertions(+), 32 deletions(-) diff --git a/arch/sim/src/sim/up_ioexpander.c b/arch/sim/src/sim/up_ioexpander.c index 0371c891d8..578216d83b 100644 --- a/arch/sim/src/sim/up_ioexpander.c +++ b/arch/sim/src/sim/up_ioexpander.c @@ -199,9 +199,13 @@ static int sim_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, { FAR struct sim_dev_s *priv = (FAR struct sim_dev_s *)dev; - DEBUGASSERT(priv != NULL && pin < CONFIG_IOEXPANDER_NPINS && - (direction == IOEXPANDER_DIRECTION_IN || - direction == IOEXPANDER_DIRECTION_OUT)); + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + + DEBUGASSERT(priv != NULL && pin < CONFIG_IOEXPANDER_NPINS); gpioinfo("pin=%u direction=%s\n", pin, (direction == IOEXPANDER_DIRECTION_IN) ? "IN" : "OUT"); diff --git a/drivers/analog/lmp92001.c b/drivers/analog/lmp92001.c index 212cb04171..47469f74cd 100644 --- a/drivers/analog/lmp92001.c +++ b/drivers/analog/lmp92001.c @@ -1214,9 +1214,13 @@ static int lmp92001_gpio_direction(FAR struct ioexpander_dev_s *dev, int ret; - DEBUGASSERT(priv != NULL && pin < LMP92001_GPIO_MAX_PINS && - (direction == IOEXPANDER_DIRECTION_IN || - direction == IOEXPANDER_DIRECTION_OUT)); + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + + DEBUGASSERT(priv != NULL && pin < LMP92001_GPIO_MAX_PINS); gpioinfo("I2C addr=%02x pin=%u direction=%s\n", priv->addr, pin, diff --git a/drivers/ioexpander/gpio.c b/drivers/ioexpander/gpio.c index 864e4d75e5..4b17d55d47 100644 --- a/drivers/ioexpander/gpio.c +++ b/drivers/ioexpander/gpio.c @@ -187,7 +187,7 @@ static ssize_t gpio_read(FAR struct file *filep, FAR char *buffer, /* Read the GPIO value */ - ret = dev->gp_ops->go_read(dev, (FAR uint8_t *)&buffer[0]); + ret = dev->gp_ops->go_read(dev, (FAR bool *)&buffer[0]); if (ret < 0) { return ret; @@ -229,7 +229,8 @@ static ssize_t gpio_write(FAR struct file *filep, FAR const char *buffer, /* Check if this pin is write-able */ - if (dev->gp_pintype != GPIO_OUTPUT_PIN) + if (dev->gp_pintype != GPIO_OUTPUT_PIN && + dev->gp_pintype != GPIO_OUTPUT_PIN_OPENDRAIN) { return -EACCES; } @@ -336,7 +337,8 @@ static int gpio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) */ case GPIOC_WRITE: - if (dev->gp_pintype == GPIO_OUTPUT_PIN) + if (dev->gp_pintype == GPIO_OUTPUT_PIN || + dev->gp_pintype == GPIO_OUTPUT_PIN_OPENDRAIN) { DEBUGASSERT(arg == 0ul || arg == 1ul); ret = dev->gp_ops->go_write(dev, (bool)arg); @@ -544,6 +546,8 @@ int gpio_pin_register(FAR struct gpio_dev_s *dev, int minor) switch (dev->gp_pintype) { case GPIO_INPUT_PIN: + case GPIO_INPUT_PIN_PULLUP: + case GPIO_INPUT_PIN_PULLDOWN: { DEBUGASSERT(dev->gp_ops->go_read != NULL); fmt = "/dev/gpin%u"; @@ -551,6 +555,7 @@ int gpio_pin_register(FAR struct gpio_dev_s *dev, int minor) break; case GPIO_OUTPUT_PIN: + case GPIO_OUTPUT_PIN_OPENDRAIN: { DEBUGASSERT(dev->gp_ops->go_read != NULL && dev->gp_ops->go_write != NULL); @@ -606,12 +611,15 @@ void gpio_pin_unregister(FAR struct gpio_dev_s *dev, int minor) switch (dev->gp_pintype) { case GPIO_INPUT_PIN: + case GPIO_INPUT_PIN_PULLUP: + case GPIO_INPUT_PIN_PULLDOWN: { fmt = "/dev/gpin%u"; } break; case GPIO_OUTPUT_PIN: + case GPIO_OUTPUT_PIN_OPENDRAIN: { fmt = "/dev/gpout%u"; } diff --git a/drivers/ioexpander/gpio_lower_half.c b/drivers/ioexpander/gpio_lower_half.c index 3a58951a0a..fad949e6a9 100644 --- a/drivers/ioexpander/gpio_lower_half.c +++ b/drivers/ioexpander/gpio_lower_half.c @@ -85,7 +85,8 @@ static int gplh_handler(FAR struct ioexpander_dev_s *ioe, static int gplh_read(FAR struct gpio_dev_s *gpio, FAR bool *value); static int gplh_write(FAR struct gpio_dev_s *gpio, bool value); #ifdef CONFIG_IOEXPANDER_INT_ENABLE -static int gplh_attach(FAR struct gpio_dev_s *gpio, pin_interrupt_t callback); +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, @@ -118,6 +119,8 @@ static const struct gpio_operations_s g_gplh_ops = static const uint32_t g_gplh_inttype[] = { [GPIO_INPUT_PIN] = IOEXPANDER_VAL_DISABLE, + [GPIO_INPUT_PIN_PULLUP] = IOEXPANDER_VAL_DISABLE, + [GPIO_INPUT_PIN_PULLDOWN] = 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, @@ -332,7 +335,8 @@ static int gplh_enable(FAR struct gpio_dev_s *gpio, bool enable) * ****************************************************************************/ -static int gplh_setpintype(FAR struct gpio_dev_s *gpio, enum gpio_pintype_e pintype) +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; @@ -346,9 +350,25 @@ static int gplh_setpintype(FAR struct gpio_dev_s *gpio, enum gpio_pintype_e pint { IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_OUT); } + else if (pintype == GPIO_OUTPUT_PIN_OPENDRAIN) + { + IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_OUT_OPENDRAIN); + } else { - IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_IN); + if (pintype == GPIO_INPUT_PIN) + { + IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_IN); + } + else if (pintype == GPIO_INPUT_PIN_PULLUP) + { + IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_IN_PULLUP); + } + else + { + IOEXP_SETDIRECTION(ioe, pin, IOEXPANDER_DIRECTION_IN_PULLDOWN); + } + IOEXP_SETOPTION(ioe, pin, IOEXPANDER_OPTION_INTCFG, (FAR void *)g_gplh_inttype[pintype]); } diff --git a/drivers/ioexpander/pca9538.c b/drivers/ioexpander/pca9538.c index e6edc7f228..e4d70b90ee 100644 --- a/drivers/ioexpander/pca9538.c +++ b/drivers/ioexpander/pca9538.c @@ -309,6 +309,12 @@ static int pca9538_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, FAR struct pca9538_dev_s *pca = (FAR struct pca9538_dev_s *)dev; int ret; + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + /* Get exclusive access to the PCA555 */ ret = pca9538_lock(pca); diff --git a/drivers/ioexpander/pca9555.c b/drivers/ioexpander/pca9555.c index 07a45d01f0..916c6d6a4b 100644 --- a/drivers/ioexpander/pca9555.c +++ b/drivers/ioexpander/pca9555.c @@ -337,6 +337,12 @@ static int pca9555_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s *)dev; int ret; + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + /* Get exclusive access to the PCA555 */ ret = pca9555_lock(pca); diff --git a/drivers/ioexpander/pcf8574.c b/drivers/ioexpander/pcf8574.c index 4824f506a8..886fef976d 100644 --- a/drivers/ioexpander/pcf8574.c +++ b/drivers/ioexpander/pcf8574.c @@ -256,9 +256,13 @@ static int pcf8574_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, FAR struct pcf8574_dev_s *priv = (FAR struct pcf8574_dev_s *)dev; int ret; - DEBUGASSERT(priv != NULL && priv->config != NULL && pin < 8 && - (direction == IOEXPANDER_DIRECTION_IN || - direction == IOEXPANDER_DIRECTION_OUT)); + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + + DEBUGASSERT(priv != NULL && priv->config != NULL && pin < 8); gpioinfo("I2C addr=%02x pin=%u direction=%s\n", priv->config->address, pin, diff --git a/drivers/ioexpander/skeleton.c b/drivers/ioexpander/skeleton.c index 7269482b50..90b7e0de78 100644 --- a/drivers/ioexpander/skeleton.c +++ b/drivers/ioexpander/skeleton.c @@ -193,12 +193,16 @@ static int skel_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, FAR struct skel_dev_s *priv = (FAR struct skel_dev_s *)dev; int ret; + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + gpioinfo("pin=%u direction=%s\n", pin, (direction == IOEXPANDER_DIRECTION_IN) ? "IN" : "OUT"); - DEBUGASSERT(priv != NULL && pin < CONFIG_IOEXPANDER_NPINS && - (direction == IOEXPANDER_DIRECTION_IN || - direction == IOEXPANDER_DIRECTION_IN)); + DEBUGASSERT(priv != NULL && pin < CONFIG_IOEXPANDER_NPINS); /* Get exclusive access to the I/O Expander */ @@ -730,7 +734,9 @@ static void skel_interrupt(FAR void *arg) /* Disable interrupts */ #warning Missing logic - /* Schedule interrupt related work on the high priority worker thread. */ + /* Schedule interrupt related work on the high priority worker + * thread. + */ work_queue(HPWORK, &priv->work, skel_irqworker, (FAR void *)priv, 0); diff --git a/drivers/ioexpander/tca64xx.c b/drivers/ioexpander/tca64xx.c index 5de8763f78..215244a987 100644 --- a/drivers/ioexpander/tca64xx.c +++ b/drivers/ioexpander/tca64xx.c @@ -419,10 +419,14 @@ static int tca64_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, uint8_t regval; int ret; + if (direction != IOEXPANDER_DIRECTION_IN && + direction != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + DEBUGASSERT(priv != NULL && priv->config != NULL && - pin < CONFIG_IOEXPANDER_NPINS && - (direction == IOEXPANDER_DIRECTION_IN || - direction == IOEXPANDER_DIRECTION_OUT)); + pin < CONFIG_IOEXPANDER_NPINS); gpioinfo("I2C addr=%02x pin=%u direction=%s\n", priv->config->address, pin, diff --git a/include/nuttx/ioexpander/gpio.h b/include/nuttx/ioexpander/gpio.h index 5d11e1c46b..f0a4661e45 100644 --- a/include/nuttx/ioexpander/gpio.h +++ b/include/nuttx/ioexpander/gpio.h @@ -100,8 +100,11 @@ enum gpio_pintype_e { - GPIO_INPUT_PIN = 0, - GPIO_OUTPUT_PIN, + GPIO_INPUT_PIN = 0, /* float */ + GPIO_INPUT_PIN_PULLUP, + GPIO_INPUT_PIN_PULLDOWN, + GPIO_OUTPUT_PIN, /* push-pull */ + GPIO_OUTPUT_PIN_OPENDRAIN, GPIO_INTERRUPT_PIN, GPIO_INTERRUPT_HIGH_PIN, GPIO_INTERRUPT_LOW_PIN, @@ -141,7 +144,7 @@ struct gpio_operations_s enum gpio_pintype_e pintype); }; - /* Signal information */ +/* Signal information */ struct gpio_signal_s { diff --git a/include/nuttx/ioexpander/ioexpander.h b/include/nuttx/ioexpander/ioexpander.h index f55aca9f25..e69bf8a683 100644 --- a/include/nuttx/ioexpander/ioexpander.h +++ b/include/nuttx/ioexpander/ioexpander.h @@ -58,8 +58,11 @@ /* Pin definitions **********************************************************/ -#define IOEXPANDER_DIRECTION_IN 0 -#define IOEXPANDER_DIRECTION_OUT 1 +#define IOEXPANDER_DIRECTION_IN 0 /* float */ +#define IOEXPANDER_DIRECTION_IN_PULLUP 1 +#define IOEXPANDER_DIRECTION_IN_PULLDOWN 2 +#define IOEXPANDER_DIRECTION_OUT 3 /* push-pull */ +#define IOEXPANDER_DIRECTION_OUT_OPENDRAIN 4 #define IOEXPANDER_PINMASK (((ioe_pinset_t)1 << CONFIG_IOEXPANDER_NPINS) - 1) #define PINSET_ALL (~((ioe_pinset_t)0)) @@ -144,14 +147,15 @@ * Name: IOEXP_READPIN * * Description: - * Read the actual PIN level. This can be different from the last value written - * to this pin. Required. + * 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. + * 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 @@ -225,8 +229,8 @@ * Name: IOEXP_MULTIREADBUF * * Description: - * Read the buffered level of multiple pins. This routine may be faster than - * individual pin accesses. Optional. + * Read the buffered level of multiple pins. This routine may be faster + * than individual pin accesses. Optional. * * Input Parameters: * dev - Device-specific state data