[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