diff options
author | Devyn Liu <liudingyuan@huawei.com> | 2024-05-13 15:59:01 +0800 |
---|---|---|
committer | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2024-05-21 18:46:45 +0300 |
commit | adbc49a5a8c6fcf7be154c2e30213bbf472940da (patch) | |
tree | c058f9ca9f2857aa2d8fb3529bde8ecb0004aa29 /drivers/gpio | |
parent | 4bcc9bba48fa1dfd4c0029b9bb201d90b90d58a3 (diff) | |
download | linux-stable-adbc49a5a8c6fcf7be154c2e30213bbf472940da.tar.gz linux-stable-adbc49a5a8c6fcf7be154c2e30213bbf472940da.tar.bz2 linux-stable-adbc49a5a8c6fcf7be154c2e30213bbf472940da.zip |
gpiolib: acpi: Fix failed in acpi_gpiochip_find() by adding parent node match
Previous patch modified the standard used by acpi_gpiochip_find()
to match device nodes. Using the device node set in gc->gpiodev->d-
ev instead of gc->parent.
However, there is a situation in gpio-dwapb where the GPIO device
driver will set gc->fwnode for each port corresponding to a child
node under a GPIO device, so gc->gpiodev->dev will be assigned the
value of each child node in gpiochip_add_data().
gpio-dwapb.c:
128,31 static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
struct dwapb_port_property *pp,
unsigned int offs);
port->gc.fwnode = pp->fwnode;
693,39 static int dwapb_gpio_probe;
err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
When other drivers request GPIO pin resources through the GPIO device
node provided by ACPI (corresponding to the parent node), the change
of the matching object to gc->gpiodev->dev in acpi_gpiochip_find()
only allows finding the value of each port (child node), resulting
in a failed request.
Reapply the condition of using gc->parent for match in acpi_gpio-
chip_find() in the code can compatible with the problem of gpio-dwapb,
and will not affect the two cases mentioned in the patch:
1. There is no setting for gc->fwnode.
2. The case that depends on using gc->fwnode for match.
Fixes: 5062e4c14b75 ("gpiolib: acpi: use the fwnode in acpi_gpiochip_find()")
Fixes: 067dbc1ea5ce ("gpiolib: acpi: Don't use GPIO chip fwnode in acpi_gpiochip_find()")
Signed-off-by: Devyn Liu <liudingyuan@huawei.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 8fb59864b58f..bb063b81cee6 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -128,7 +128,24 @@ static bool acpi_gpio_deferred_req_irqs_done; static int acpi_gpiochip_find(struct gpio_chip *gc, const void *data) { - return device_match_acpi_handle(&gc->gpiodev->dev, data); + /* First check the actual GPIO device */ + if (device_match_acpi_handle(&gc->gpiodev->dev, data)) + return true; + + /* + * When the ACPI device is artificially split to the banks of GPIOs, + * where each of them is represented by a separate GPIO device, + * the firmware node of the physical device may not be shared among + * the banks as they may require different values for the same property, + * e.g., number of GPIOs in a certain bank. In such case the ACPI handle + * of a GPIO device is NULL and can not be used. Hence we have to check + * the parent device to be sure that there is no match before bailing + * out. + */ + if (gc->parent) + return device_match_acpi_handle(gc->parent, data); + + return false; } /** |