Commit 4c033b54 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Walleij

gpiolib: Add support for GPIO lookup by line name

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: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Tested-by: default avatarEugeniu Rosca <erosca@de.adit-jv.com>
Reviewed-by: default avatarUlrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: default avatarEugeniu Rosca <erosca@de.adit-jv.com>
Link: https://lore.kernel.org/r/20200511145257.22970-4-geert+renesas@glider.beSigned-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 7b67b836
......@@ -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
......
......@@ -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++;
......
......@@ -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, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment