kernel: bump 5.15 to 5.15.152
[openwrt/openwrt.git] / target / linux / generic / hack-5.15 / 800-GPIO-add-named-gpio-exports.patch
index 3d34231b82f678c3e3e67b26fd4b31c39ae91d81..258a5fb33c3bd8eab80729a1b8c66f594c64e8c5 100644 (file)
@@ -15,7 +15,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
  #include "gpiolib.h"
  #include "gpiolib-of.h"
-@@ -1057,3 +1059,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++;
@@ -105,7 +133,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  {
 --- a/include/linux/gpio/consumer.h
 +++ b/include/linux/gpio/consumer.h
-@@ -715,6 +715,7 @@ static inline void devm_acpi_dev_remove_
+@@ -712,6 +712,7 @@ static inline void devm_acpi_dev_remove_
  
  #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
  
@@ -113,7 +141,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
  int gpiod_export_link(struct device *dev, const char *name,
                      struct gpio_desc *desc);
-@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de
+@@ -719,6 +720,13 @@ void gpiod_unexport(struct gpio_desc *de
  
  #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
  
@@ -129,7 +157,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  {
 --- a/drivers/gpio/gpiolib-sysfs.c
 +++ b/drivers/gpio/gpiolib-sysfs.c
-@@ -561,7 +561,7 @@ static struct class gpio_class = {
+@@ -564,7 +564,7 @@ static struct class gpio_class = {
   *
   * Returns zero on success, else an error.
   */
@@ -138,7 +166,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  {
        struct gpio_chip        *chip;
        struct gpio_device      *gdev;
-@@ -623,6 +623,8 @@ int gpiod_export(struct gpio_desc *desc,
+@@ -626,6 +626,8 @@ int gpiod_export(struct gpio_desc *desc,
        offset = gpio_chip_hwgpio(desc);
        if (chip->names && chip->names[offset])
                ioname = chip->names[offset];
@@ -147,7 +175,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        dev = device_create_with_groups(&gpio_class, &gdev->dev,
                                        MKDEV(0, 0), data, gpio_groups,
-@@ -644,6 +646,12 @@ err_unlock:
+@@ -647,6 +649,12 @@ err_unlock:
        gpiod_dbg(desc, "%s: status %d\n", __func__, status);
        return status;
  }