From 7d252d0279ec92ac90a5cec7378bd877df7af008 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:04 +1300 Subject: [PATCH] x86: Probe device if needed in intel_gpio_xlate() The Intel GPIO binding allows GPIOs to be globally numbered, so that it does not matter which GPIO bank is specified in the device tree. This is convenient and avoid confusion since the banks do not have the same number of GPIOs and the numbering is not sequential. The GPIO uclass ensures that the device mentioned in the devicetree binding is probed. It is fine for the driver to update gpio_desc to point to a different driver, but this may not have been probed. If it has not been, then it cannot be claimed since there is no uclass data. We could handle this in the GPIO uclass but so far it is an unusual situation so it is probably not worth the extra code. Handle this case in the GPIO driver by probing the selected device if necessary. Signed-off-by: Simon Glass --- drivers/gpio/intel_gpio.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c index ab46a94dbc..f15ce7b59e 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include static int intel_gpio_get_value(struct udevice *dev, uint offset) @@ -85,7 +86,7 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc, /* * GPIO numbers are global in the device tree so it doesn't matter - * which one is used + * which @orig_dev is used */ gpio = args->args[0]; ret = intel_pinctrl_get_pad(gpio, &pinctrl, &desc->offset); @@ -97,6 +98,17 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc, desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; desc->dev = dev; + /* + * Handle the case where the wrong GPIO device was provided, since this + * will not have been probed by the GPIO uclass before calling here + * (see gpio_request_tail()). + */ + if (orig_dev != dev) { + ret = device_probe(dev); + if (ret) + return log_msg_ret("probe", ret); + } + return 0; }