Merge branch 'for-dmitry' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 15 Dec 2015 18:23:43 +0000 (10:23 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 15 Dec 2015 18:23:43 +0000 (10:23 -0800)
Bring in changes to ACPI GPIOLIB to better handle legacy ACPI mappings
needed for subsequent Goodix driver changes.

drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h

index 16a7b68..7ab7bc3 100644 (file)
@@ -922,3 +922,46 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
        }
        return count;
 }
+
+struct acpi_crs_lookup {
+       struct list_head node;
+       struct acpi_device *adev;
+       const char *con_id;
+};
+
+static DEFINE_MUTEX(acpi_crs_lookup_lock);
+static LIST_HEAD(acpi_crs_lookup_list);
+
+bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id)
+{
+       struct acpi_crs_lookup *l, *lookup = NULL;
+
+       /* Never allow fallback if the device has properties */
+       if (adev->data.properties || adev->driver_gpios)
+               return false;
+
+       mutex_lock(&acpi_crs_lookup_lock);
+
+       list_for_each_entry(l, &acpi_crs_lookup_list, node) {
+               if (l->adev == adev) {
+                       lookup = l;
+                       break;
+               }
+       }
+
+       if (!lookup) {
+               lookup = kmalloc(sizeof(*lookup), GFP_KERNEL);
+               if (lookup) {
+                       lookup->adev = adev;
+                       lookup->con_id = con_id;
+                       list_add_tail(&lookup->node, &acpi_crs_lookup_list);
+               }
+       }
+
+       mutex_unlock(&acpi_crs_lookup_lock);
+
+       return lookup &&
+               ((!lookup->con_id && !con_id) ||
+                (lookup->con_id && con_id &&
+                 strcmp(lookup->con_id, con_id) == 0));
+}
index 2a91f32..c8a1e88 100644 (file)
@@ -1868,6 +1868,9 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
 
        /* Then from plain _CRS GPIOs */
        if (IS_ERR(desc)) {
+               if (!acpi_can_fallback_to_crs(adev, con_id))
+                       return ERR_PTR(-ENOENT);
+
                desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
                if (IS_ERR(desc))
                        return desc;
index 98ab08c..2b87cbd 100644 (file)
@@ -47,6 +47,8 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
                                      struct acpi_gpio_info *info);
 
 int acpi_gpio_count(struct device *dev, const char *con_id);
+
+bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
 static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
@@ -73,6 +75,12 @@ static inline int acpi_gpio_count(struct device *dev, const char *con_id)
 {
        return -ENODEV;
 }
+
+static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
+                                           const char *con_id)
+{
+       return false;
+}
 #endif
 
 struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,