summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorDevyn Liu <liudingyuan@huawei.com>2024-05-13 15:59:01 +0800
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2024-05-21 18:46:45 +0300
commitadbc49a5a8c6fcf7be154c2e30213bbf472940da (patch)
treec058f9ca9f2857aa2d8fb3529bde8ecb0004aa29 /drivers/gpio
parent4bcc9bba48fa1dfd4c0029b9bb201d90b90d58a3 (diff)
downloadlinux-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.c19
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;
}
/**