[U-Boot] [PATCH 06/13] gpio: add support for new flags on gpio configuration

Patrick Delaunay patrick.delaunay at st.com
Wed Oct 23 13:44:41 UTC 2019


This commit manages the flags that can be used in GPIO specifiers to
indicate if a pull-up resistor or pull-down resistor should be
enabled for output GPIO and the Open Drain/Open Source configuration
for input GPIO.

It is managed in driver with a new ops in gpio uclass set_config.

These flags are already support in Linux kernel in gpiolib.

Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
---

 drivers/gpio/gpio-uclass.c | 62 +++++++++++++++++++++++++++++++++++++-
 include/asm-generic/gpio.h | 56 ++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 90fbed455b..c6c6e8b343 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -128,7 +128,19 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
 		return 0;
 
 	if (args->args[1] & GPIO_ACTIVE_LOW)
-		desc->flags = GPIOD_ACTIVE_LOW;
+		desc->flags |= GPIOD_ACTIVE_LOW;
+
+	if ((args->args[1] & GPIO_OPEN_DRAIN) == GPIO_OPEN_DRAIN)
+		desc->flags |= GPIOD_OPEN_DRAIN;
+
+	if ((args->args[1] & GPIO_OPEN_SOURCE) == GPIO_OPEN_SOURCE)
+		desc->flags |= GPIOD_OPEN_SOURCE;
+
+	if (args->args[1] & GPIO_PULL_UP)
+		desc->flags |= GPIOD_PULL_UP;
+
+	if (args->args[1] & GPIO_PULL_DOWN)
+		desc->flags |= GPIOD_PULL_DOWN;
 
 	return 0;
 }
@@ -517,12 +529,31 @@ int dm_gpio_set_open_drain(struct gpio_desc *desc, int value)
 
 	if (ops->set_open_drain)
 		ret = ops->set_open_drain(desc->dev, desc->offset, value);
+	else if (ops->set_config)
+		ret = ops->set_config(desc->dev, desc->offset,
+				      value ? GPIO_CONF_DRIVE_OPEN_DRAIN :
+					      GPIO_CONF_DRIVE_PULL_PUSH);
 	else
 		return 0; /* feature not supported -> ignore setting */
 
 	return ret;
 }
 
+int gpio_get_config(const struct gpio_desc *desc)
+{
+	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	int ret;
+
+	ret = check_reserved(desc, "get_config");
+	if (ret)
+		return ret;
+
+	if (ops->set_config)
+		return ops->get_config(desc->dev, desc->offset);
+	else
+		return -ENOSYS;
+}
+
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
@@ -533,14 +564,39 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 	if (ret)
 		return ret;
 
+	/* both pull-up and pull-down enabled, invalid configuration */
+	if ((flags & GPIOD_PULL_UP) && (flags & GPIOD_PULL_DOWN))
+		return -EINVAL;
+
 	if (flags & GPIOD_IS_OUT) {
 		int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
 
+		if (ops->set_config) {
+			if (flags & GPIOD_OPEN_DRAIN)
+				ops->set_config(dev, desc->offset,
+						GPIO_CONF_DRIVE_OPEN_DRAIN);
+			else if (flags & GPIOD_OPEN_SOURCE)
+				ops->set_config(dev, desc->offset,
+						GPIO_CONF_DRIVE_OPEN_SOURCE);
+			else
+				ops->set_config(dev, desc->offset,
+						GPIO_CONF_DRIVE_PULL_PUSH);
+		}
+
 		if (flags & GPIOD_ACTIVE_LOW)
 			value = !value;
 		ret = ops->direction_output(dev, desc->offset, value);
 	} else  if (flags & GPIOD_IS_IN) {
 		ret = ops->direction_input(dev, desc->offset);
+
+		if (ops->set_config) {
+			if (flags & GPIOD_PULL_UP)
+				ops->set_config(dev, desc->offset,
+						GPIO_CONF_BIAS_PULL_UP);
+			else if (flags & GPIOD_PULL_DOWN)
+				ops->set_config(dev, desc->offset,
+						GPIO_CONF_BIAS_PULL_DOWN);
+		}
 	}
 	if (ret)
 		return ret;
@@ -1061,6 +1117,10 @@ static int gpio_post_bind(struct udevice *dev)
 			ops->get_function += gd->reloc_off;
 		if (ops->xlate)
 			ops->xlate += gd->reloc_off;
+		if (ops->set_config)
+			ops->set_config += gd->reloc_off;
+		if (ops->get_config)
+			ops->get_config += gd->reloc_off;
 
 		reloc_done++;
 	}
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index d6cf18744f..9441e7dccc 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -112,6 +112,17 @@ enum gpio_func_t {
 	GPIOF_COUNT,
 };
 
+enum gpio_config {
+	GPIO_CONF_NONE,
+	GPIO_CONF_DRIVE_OPEN_DRAIN,
+	GPIO_CONF_DRIVE_OPEN_SOURCE,
+	GPIO_CONF_DRIVE_PULL_PUSH,
+	GPIO_CONF_BIAS_PULL_DOWN,
+	GPIO_CONF_BIAS_PULL_UP,
+
+	GPIO_CONF_COUNT,
+};
+
 struct udevice;
 
 struct gpio_desc {
@@ -122,6 +133,10 @@ struct gpio_desc {
 #define GPIOD_IS_IN		(1 << 2)	/* GPIO is an input */
 #define GPIOD_ACTIVE_LOW	(1 << 3)	/* value has active low */
 #define GPIOD_IS_OUT_ACTIVE	(1 << 4)	/* set output active */
+#define GPIOD_OPEN_DRAIN	(1 << 5)	/* GPIO is open drain type */
+#define GPIOD_OPEN_SOURCE	(1 << 6)	/* GPIO is open source type */
+#define GPIOD_PULL_UP		(1 << 7)	/* GPIO has pull up enabled */
+#define GPIOD_PULL_DOWN		(1 << 8)	/* GPIO has pull down enabled */
 
 	uint offset;		/* GPIO offset within the device */
 	/*
@@ -290,6 +305,36 @@ struct dm_gpio_ops {
 	 */
 	int (*xlate)(struct udevice *dev, struct gpio_desc *desc,
 		     struct ofnode_phandle_args *args);
+
+	/**
+	 * set_config() - Set GPIO configuration
+	 *
+	 * This function should set up the GPIO configuration according to the
+	 * information in the arguments.
+	 *
+	 * This method is optional.
+	 *
+	 * @dev:	GPIO device
+	 * @offset:	GPIO offset within that device
+	 * @config:	GPIO configuration
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_config)(struct udevice *dev, unsigned offset,
+			  enum gpio_config config);
+
+	/**
+	 * set_config() - Set GPIO configuration
+	 *
+	 * This function return the GPIO configuration according to the
+	 * information in the arguments.
+	 *
+	 * This method is optional.
+	 *
+	 * @dev:	GPIO device
+	 * @offset:	GPIO offset within that device
+	 * @return GPIO configuration (GPIO_CONF_) if OK, -ve on error
+	 */
+	int (*get_config)(struct udevice *dev, unsigned offset);
 };
 
 /**
@@ -657,4 +702,15 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
  */
 int gpio_get_number(const struct gpio_desc *desc);
 
+/**
+ * gpio_get_config() - get the current GPIO pin configuration
+ *
+ * Obtain the current GPIO pin configuration
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return GPIO configuration (GPIO_CONF_) if OK, -ve on error
+ */
+int gpio_get_config(const struct gpio_desc *desc);
+
 #endif	/* _ASM_GENERIC_GPIO_H_ */
-- 
2.17.1



More information about the U-Boot mailing list