]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/gpio/gpiolib-acpi.c
timekeeping: Repair ktime_get_coarse*() granularity
[mirror_ubuntu-jammy-kernel.git] / drivers / gpio / gpiolib-acpi.c
index 30d0baf7ddaed0e07d6fa94d5ceee8c06ada68df..c9fc9e232aafb37d67c7b72b83183b778963d41a 100644 (file)
  *
  * @node:        list-entry of the events list of the struct acpi_gpio_chip
  * @handle:      handle of ACPI method to execute when the IRQ triggers
- * @handler:     irq_handler to pass to request_irq when requesting the IRQ
- * @pin:         GPIO pin number on the gpio_chip
- * @irq:         Linux IRQ number for the event, for request_ / free_irq
- * @irqflags:     flags to pass to request_irq when requesting the IRQ
+ * @handler:     handler function to pass to request_irq() when requesting the IRQ
+ * @pin:         GPIO pin number on the struct gpio_chip
+ * @irq:         Linux IRQ number for the event, for request_irq() / free_irq()
+ * @irqflags:    flags to pass to request_irq() when requesting the IRQ
  * @irq_is_wake:  If the ACPI flags indicate the IRQ is a wakeup source
- * @irq_requested:True if request_irq has been done
- * @desc:        gpio_desc for the GPIO pin for this event
+ * @irq_requested:True if request_irq() has been done
+ * @desc:        struct gpio_desc for the GPIO pin for this event
  */
 struct acpi_gpio_event {
        struct list_head node;
@@ -65,10 +65,10 @@ struct acpi_gpio_chip {
 };
 
 /*
- * For gpiochips which call acpi_gpiochip_request_interrupts() before late_init
+ * For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init
  * (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a
- * late_initcall_sync handler, so that other builtin drivers can register their
- * OpRegions before the event handlers can run.  This list contains gpiochips
+ * late_initcall_sync() handler, so that other builtin drivers can register their
+ * OpRegions before the event handlers can run. This list contains GPIO chips
  * for which the acpi_gpiochip_request_irqs() call has been deferred.
  */
 static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock);
@@ -90,7 +90,7 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
  *
  * Return: GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR
  * error value. Specifically returns %-EPROBE_DEFER if the referenced GPIO
- * controller does not have gpiochip registered at the moment. This is to
+ * controller does not have GPIO chip registered at the moment. This is to
  * support probe deferral.
  */
 static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
@@ -287,9 +287,9 @@ fail_free_desc:
  *
  * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
  * handled by ACPI event methods which need to be called from the GPIO
- * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which
- * gpio pins have acpi event methods and assigns interrupt handlers that calls
- * the acpi event methods for those pins.
+ * chip's interrupt handler. acpi_gpiochip_request_interrupts() finds out which
+ * GPIO pins have ACPI event methods and assigns interrupt handlers that calls
+ * the ACPI event methods for those pins.
  */
 void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
 {
@@ -444,8 +444,6 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
 static enum gpiod_flags
 acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio)
 {
-       bool pull_up = agpio->pin_config == ACPI_PIN_CONFIG_PULLUP;
-
        switch (agpio->io_restriction) {
        case ACPI_IO_RESTRICT_INPUT:
                return GPIOD_IN;
@@ -454,16 +452,26 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio)
                 * ACPI GPIO resources don't contain an initial value for the
                 * GPIO. Therefore we deduce that value from the pull field
                 * instead. If the pin is pulled up we assume default to be
-                * high, otherwise low.
+                * high, if it is pulled down we assume default to be low,
+                * otherwise we leave pin untouched.
                 */
-               return pull_up ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
+               switch (agpio->pin_config) {
+               case ACPI_PIN_CONFIG_PULLUP:
+                       return GPIOD_OUT_HIGH;
+               case ACPI_PIN_CONFIG_PULLDOWN:
+                       return GPIOD_OUT_LOW;
+               default:
+                       break;
+               }
        default:
-               /*
-                * Assume that the BIOS has configured the direction and pull
-                * accordingly.
-                */
-               return GPIOD_ASIS;
+               break;
        }
+
+       /*
+        * Assume that the BIOS has configured the direction and pull
+        * accordingly.
+        */
+       return GPIOD_ASIS;
 }
 
 static int
@@ -517,6 +525,26 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf
        return ret;
 }
 
+int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
+                                       struct acpi_gpio_info *info)
+{
+       switch (info->pin_config) {
+       case ACPI_PIN_CONFIG_PULLUP:
+               *lookupflags |= GPIO_PULL_UP;
+               break;
+       case ACPI_PIN_CONFIG_PULLDOWN:
+               *lookupflags |= GPIO_PULL_DOWN;
+               break;
+       default:
+               break;
+       }
+
+       if (info->polarity == GPIO_ACTIVE_LOW)
+               *lookupflags |= GPIO_ACTIVE_LOW;
+
+       return 0;
+}
+
 struct acpi_gpio_lookup {
        struct acpi_gpio_info info;
        int index;
@@ -550,6 +578,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
 
                lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
                                              agpio->pin_table[pin_index]);
+               lookup->info.pin_config = agpio->pin_config;
                lookup->info.gpioint = gpioint;
 
                /*
@@ -653,7 +682,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
  * that case @index is used to select the GPIO entry in the property value
  * (in case of multiple).
  *
- * If the GPIO cannot be translated or there is an error an ERR_PTR is
+ * If the GPIO cannot be translated or there is an error, an ERR_PTR is
  * returned.
  *
  * Note: if the GPIO resource has multiple entries in the pin list, this
@@ -696,7 +725,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
                                 const char *con_id,
                                 unsigned int idx,
                                 enum gpiod_flags *dflags,
-                                enum gpio_lookup_flags *lookupflags)
+                                unsigned long *lookupflags)
 {
        struct acpi_device *adev = ACPI_COMPANION(dev);
        struct acpi_gpio_info info;
@@ -737,10 +766,8 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
                return ERR_PTR(-ENOENT);
        }
 
-       if (info.polarity == GPIO_ACTIVE_LOW)
-               *lookupflags |= GPIO_ACTIVE_LOW;
-
        acpi_gpio_update_gpiod_flags(dflags, &info);
+       acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info);
        return desc;
 }
 
@@ -751,10 +778,13 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
  * @index: index of GpioIo/GpioInt resource (starting from %0)
  * @info: info pointer to fill in (optional)
  *
- * If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it.
- * Otherwise (ie. it is a data-only non-device object), use the property-based
+ * If @fwnode is an ACPI device object, call acpi_get_gpiod_by_index() for it.
+ * Otherwise (i.e. it is a data-only non-device object), use the property-based
  * GPIO lookup to get to the GPIO resource with the relevant information and use
  * that to obtain the GPIO descriptor to return.
+ *
+ * If the GPIO cannot be translated or there is an error an ERR_PTR is
+ * returned.
  */
 struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
                                      const char *propname, int index,
@@ -816,6 +846,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
                        return PTR_ERR(desc);
 
                if (info.gpioint && idx++ == index) {
+                       unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
                        char label[32];
                        int irq;
 
@@ -827,7 +858,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
                                return irq;
 
                        snprintf(label, sizeof(label), "GpioInt() %d", index);
-                       ret = gpiod_configure_flags(desc, label, 0, info.flags);
+                       ret = gpiod_configure_flags(desc, label, lflags, info.flags);
                        if (ret < 0)
                                return ret;
 
@@ -992,16 +1023,19 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip)
        }
 }
 
-static struct gpio_desc *acpi_gpiochip_parse_own_gpio(
-       struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode,
-       const char **name, unsigned int *lflags, unsigned int *dflags)
+static struct gpio_desc *
+acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip,
+                            struct fwnode_handle *fwnode,
+                            const char **name,
+                            unsigned long *lflags,
+                            enum gpiod_flags *dflags)
 {
        struct gpio_chip *chip = achip->chip;
        struct gpio_desc *desc;
        u32 gpios[2];
        int ret;
 
-       *lflags = 0;
+       *lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
        *dflags = 0;
        *name = NULL;
 
@@ -1037,7 +1071,8 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
        struct fwnode_handle *fwnode;
 
        device_for_each_child_node(chip->parent, fwnode) {
-               unsigned int lflags, dflags;
+               unsigned long lflags;
+               enum gpiod_flags dflags;
                struct gpio_desc *desc;
                const char *name;
                int ret;
@@ -1158,11 +1193,13 @@ static int acpi_find_gpio_count(struct acpi_resource *ares, void *data)
 }
 
 /**
- * acpi_gpio_count - return the number of GPIOs associated with a
- *             device / function or -ENOENT if no GPIO has been
- *             assigned to the requested function.
- * @dev:       GPIO consumer, can be NULL for system-global GPIOs
+ * acpi_gpio_count - count the GPIOs associated with a device / function
+ * @dev:       GPIO consumer, can be %NULL for system-global GPIOs
  * @con_id:    function within the GPIO consumer
+ *
+ * Return:
+ * The number of GPIOs associated with a device / function or %-ENOENT,
+ * if no GPIO has been assigned to the requested function.
  */
 int acpi_gpio_count(struct device *dev, const char *con_id)
 {