gpiolib: Add support for GPIO lookup by line name
authorGeert Uytterhoeven <geert+renesas@glider.be>
Mon, 11 May 2020 14:52:54 +0000 (16:52 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 18 May 2020 08:12:42 +0000 (10:12 +0200)
Currently a GPIO lookup table can only refer to a specific GPIO by a
tuple, consisting of a GPIO controller label and a GPIO offset inside
the controller.

However, a GPIO may also carry a line name, defined by DT or ACPI.
If present, the line name is the most use-centric way to refer to a
GPIO.  Hence add support for looking up GPIOs by line name.
Note that there is no guarantee that GPIO line names are globally
unique, so this will use the first match found.

Implement this by reusing the existing gpiod_lookup infrastructure.
Rename gpiod_lookup.chip_label to gpiod_lookup.key, to make it clear
that this field can have two meanings, and update the kerneldoc and
GPIO_LOOKUP*() macros.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Eugeniu Rosca <erosca@de.adit-jv.com>
Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Eugeniu Rosca <erosca@de.adit-jv.com>
Link: https://lore.kernel.org/r/20200511145257.22970-4-geert+renesas@glider.be
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Documentation/driver-api/gpio/board.rst
drivers/gpio/gpiolib.c
include/linux/gpio/machine.h

index ce91518..191fa86 100644 (file)
@@ -113,13 +113,15 @@ files that desire to do so need to include the following header::
 GPIOs are mapped by the means of tables of lookups, containing instances of the
 gpiod_lookup structure. Two macros are defined to help declaring such mappings::
 
-       GPIO_LOOKUP(chip_label, chip_hwnum, con_id, flags)
-       GPIO_LOOKUP_IDX(chip_label, chip_hwnum, con_id, idx, flags)
+       GPIO_LOOKUP(key, chip_hwnum, con_id, flags)
+       GPIO_LOOKUP_IDX(key, chip_hwnum, con_id, idx, flags)
 
 where
 
-  - chip_label is the label of the gpiod_chip instance providing the GPIO
-  - chip_hwnum is the hardware number of the GPIO within the chip
+  - key is either the label of the gpiod_chip instance providing the GPIO, or
+    the GPIO line name
+  - chip_hwnum is the hardware number of the GPIO within the chip, or U16_MAX
+    to indicate that key is a GPIO line name
   - con_id is the name of the GPIO function from the device point of view. It
        can be NULL, in which case it will match any function.
   - idx is the index of the GPIO within the function.
@@ -135,7 +137,10 @@ where
 
 In the future, these flags might be extended to support more properties.
 
-Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
+Note that:
+  1. GPIO line names are not guaranteed to be globally unique, so the first
+     match found will be used.
+  2. GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
 
 A lookup table can then be defined as follows, with an empty entry defining its
 end. The 'dev_id' field of the table is the identifier of the device that will
index 40f2d7f..3c1dcdf 100644 (file)
@@ -4618,7 +4618,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
        if (!table)
                return desc;
 
-       for (p = &table->table[0]; p->chip_label; p++) {
+       for (p = &table->table[0]; p->key; p++) {
                struct gpio_chip *gc;
 
                /* idx must always match exactly */
@@ -4629,18 +4629,30 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
                if (p->con_id && (!con_id || strcmp(p->con_id, con_id)))
                        continue;
 
-               gc = find_chip_by_name(p->chip_label);
+               if (p->chip_hwnum == U16_MAX) {
+                       desc = gpio_name_to_desc(p->key);
+                       if (desc) {
+                               *flags = p->flags;
+                               return desc;
+                       }
+
+                       dev_warn(dev, "cannot find GPIO line %s, deferring\n",
+                                p->key);
+                       return ERR_PTR(-EPROBE_DEFER);
+               }
+
+               gc = find_chip_by_name(p->key);
 
                if (!gc) {
                        /*
                         * As the lookup table indicates a chip with
-                        * p->chip_label should exist, assume it may
+                        * p->key should exist, assume it may
                         * still appear later and let the interested
                         * consumer be probed again or let the Deferred
                         * Probe infrastructure handle the error.
                         */
                        dev_warn(dev, "cannot find GPIO chip %s, deferring\n",
-                                p->chip_label);
+                                p->key);
                        return ERR_PTR(-EPROBE_DEFER);
                }
 
@@ -4671,7 +4683,7 @@ static int platform_gpio_count(struct device *dev, const char *con_id)
        if (!table)
                return -ENOENT;
 
-       for (p = &table->table[0]; p->chip_label; p++) {
+       for (p = &table->table[0]; p->key; p++) {
                if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) ||
                    (!con_id && !p->con_id))
                        count++;
index 1ebe5be..781a053 100644 (file)
@@ -20,8 +20,11 @@ enum gpio_lookup_flags {
 
 /**
  * struct gpiod_lookup - lookup table
- * @chip_label: name of the chip the GPIO belongs to
- * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO
+ * @key: either the name of the chip the GPIO belongs to, or the GPIO line name
+ *       Note that GPIO line names are not guaranteed to be globally unique,
+ *       so this will use the first match found!
+ * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO, or
+ *              U16_MAX to indicate that @key is a GPIO line name
  * @con_id: name of the GPIO from the device's point of view
  * @idx: index of the GPIO in case several GPIOs share the same name
  * @flags: bitmask of gpio_lookup_flags GPIO_* values
@@ -30,7 +33,7 @@ enum gpio_lookup_flags {
  * functions using platform data.
  */
 struct gpiod_lookup {
-       const char *chip_label;
+       const char *key;
        u16 chip_hwnum;
        const char *con_id;
        unsigned int idx;
@@ -63,17 +66,17 @@ struct gpiod_hog {
 /*
  * Simple definition of a single GPIO under a con_id
  */
-#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _con_id, _flags) \
-       GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, 0, _flags)
+#define GPIO_LOOKUP(_key, _chip_hwnum, _con_id, _flags) \
+       GPIO_LOOKUP_IDX(_key, _chip_hwnum, _con_id, 0, _flags)
 
 /*
  * Use this macro if you need to have several GPIOs under the same con_id.
  * Each GPIO needs to use a different index and can be accessed using
  * gpiod_get_index()
  */
-#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, _idx, _flags)  \
+#define GPIO_LOOKUP_IDX(_key, _chip_hwnum, _con_id, _idx, _flags)         \
 {                                                                         \
-       .chip_label = _chip_label,                                        \
+       .key = _key,                                                      \
        .chip_hwnum = _chip_hwnum,                                        \
        .con_id = _con_id,                                                \
        .idx = _idx,                                                      \