aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schiller <ms@dev.tdt.de>2023-08-04 12:59:03 +0200
committerHauke Mehrtens <hauke@hauke-m.de>2023-08-15 16:07:04 +0200
commit0af88d2512b94bb0e3d81058beaa220448e46119 (patch)
tree991ac6f912c2bc62a88efe95022a0bf179b0c63d
parent7770d08e2bd28c9c0dc0b3dc0aaf74074ad5772a (diff)
linux/named-gpio-export: add support for OPEN_DRAIN and OPEN_SOURCE flag
This change makes it possible to use the GPIO_OPEN_DRAIN / GPIO_OPEN_SOURCE Flags when exporting GPIOs via dts. We need to emulate the open-source or open-drain functionalities for the initial value, because the used functions (gpiod_direction_output_raw) do not take this into account. Signed-off-by: Martin Schiller <ms@dev.tdt.de>
-rw-r--r--target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch38
-rw-r--r--target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch38
2 files changed, 66 insertions, 10 deletions
diff --git a/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch
index 0a2c82cacb..f27b7ef9de 100644
--- a/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch
+++ b/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch
@@ -15,7 +15,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include "gpiolib.h"
#include "gpiolib-of.h"
-@@ -1059,3 +1061,72 @@ void of_gpio_dev_init(struct gpio_chip *
+@@ -1059,3 +1061,100 @@ void of_gpio_dev_init(struct gpio_chip *
else
gc->of_node = gdev->dev.of_node;
}
@@ -47,6 +47,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ max_gpio = of_gpio_count(cnp);
+
+ for (i = 0; i < max_gpio; i++) {
++ struct gpio_desc *desc;
+ unsigned flags = 0;
+ enum of_gpio_flags of_flags;
+
@@ -54,17 +55,44 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
-+ if (of_flags == OF_GPIO_ACTIVE_LOW)
++ if (of_flags & OF_GPIO_ACTIVE_LOW)
+ flags |= GPIOF_ACTIVE_LOW;
+
-+ if (!of_property_read_u32(cnp, "gpio-export,output", &val))
-+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-+ else
++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) {
++ if (of_flags & OF_GPIO_SINGLE_ENDED) {
++ /*
++ * As gpiod_direction_output_raw() is used, we
++ * need to emulate open drain or open source here.
++ */
++ if (of_flags & OF_GPIO_OPEN_DRAIN) {
++ flags |= GPIOF_OPEN_DRAIN;
++ flags |= val ? GPIOF_IN : GPIOF_OUT_INIT_LOW;
++ } else {
++ flags |= GPIOF_OPEN_SOURCE;
++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_IN;
++ }
++ } else {
++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
++ }
++ } else {
+ flags |= GPIOF_IN;
++ }
+
+ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
+ continue;
+
++ /*
++ * When emulating open-source or open-drain functionalities by not
++ * actively driving the line (setting mode to input) we still need to
++ * set the IS_OUT flag or otherwise we won't be able to set the line
++ * value anymore.
++ */
++ if ((flags & GPIOF_IN) &&
++ ((flags & GPIOF_OPEN_DRAIN) || (flags & GPIOF_OPEN_SOURCE))) {
++ desc = gpio_to_desc(gpio);
++ set_bit(FLAG_IS_OUT, &desc->flags);
++ }
++
+ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
+ gpio_export_with_name(gpio, dmc, name);
+ nb++;
diff --git a/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch
index 658d9c3806..ba5351275d 100644
--- a/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch
+++ b/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch
@@ -15,7 +15,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include "gpiolib.h"
#include "gpiolib-of.h"
-@@ -1030,3 +1032,72 @@ void of_gpio_dev_init(struct gpio_chip *
+@@ -1030,3 +1032,100 @@ void of_gpio_dev_init(struct gpio_chip *
else
gc->of_node = gdev->dev.of_node;
}
@@ -47,6 +47,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ max_gpio = of_gpio_count(cnp);
+
+ for (i = 0; i < max_gpio; i++) {
++ struct gpio_desc *desc;
+ unsigned flags = 0;
+ enum of_gpio_flags of_flags;
+
@@ -54,17 +55,44 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
-+ if (of_flags == OF_GPIO_ACTIVE_LOW)
++ if (of_flags & OF_GPIO_ACTIVE_LOW)
+ flags |= GPIOF_ACTIVE_LOW;
+
-+ if (!of_property_read_u32(cnp, "gpio-export,output", &val))
-+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-+ else
++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) {
++ if (of_flags & OF_GPIO_SINGLE_ENDED) {
++ /*
++ * As gpiod_direction_output_raw() is used, we
++ * need to emulate open drain or open source here.
++ */
++ if (of_flags & OF_GPIO_OPEN_DRAIN) {
++ flags |= GPIOF_OPEN_DRAIN;
++ flags |= val ? GPIOF_IN : GPIOF_OUT_INIT_LOW;
++ } else {
++ flags |= GPIOF_OPEN_SOURCE;
++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_IN;
++ }
++ } else {
++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
++ }
++ } else {
+ flags |= GPIOF_IN;
++ }
+
+ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
+ continue;
+
++ /*
++ * When emulating open-source or open-drain functionalities by not
++ * actively driving the line (setting mode to input) we still need to
++ * set the IS_OUT flag or otherwise we won't be able to set the line
++ * value anymore.
++ */
++ if ((flags & GPIOF_IN) &&
++ ((flags & GPIOF_OPEN_DRAIN) || (flags & GPIOF_OPEN_SOURCE))) {
++ desc = gpio_to_desc(gpio);
++ set_bit(FLAG_IS_OUT, &desc->flags);
++ }
++
+ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
+ gpio_export_with_name(gpio, dmc, name);
+ nb++;