diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 52 | 
1 files changed, 45 insertions, 7 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 844198cb4e31..adf55db080d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -56,8 +56,10 @@  static DEFINE_IDA(gpio_ida);  static dev_t gpio_devt;  #define GPIO_DEV_MAX 256 /* 256 GPIO chip devices supported */ +static int gpio_bus_match(struct device *dev, struct device_driver *drv);  static struct bus_type gpio_bus_type = {  	.name = "gpio", +	.match = gpio_bus_match,  };  /* @@ -590,13 +592,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,  		gdev->dev.of_node = gc->parent->of_node;  	} -#ifdef CONFIG_OF_GPIO -	/* If the gpiochip has an assigned OF node this takes precedence */ -	if (gc->of_node) -		gdev->dev.of_node = gc->of_node; -	else -		gc->of_node = gdev->dev.of_node; -#endif +	of_gpio_dev_init(gc, gdev);  	gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL);  	if (gdev->id < 0) { @@ -4215,6 +4211,41 @@ void gpiod_put_array(struct gpio_descs *descs)  }  EXPORT_SYMBOL_GPL(gpiod_put_array); + +static int gpio_bus_match(struct device *dev, struct device_driver *drv) +{ +	/* +	 * Only match if the fwnode doesn't already have a proper struct device +	 * created for it. +	 */ +	if (dev->fwnode && dev->fwnode->dev != dev) +		return 0; +	return 1; +} + +static int gpio_stub_drv_probe(struct device *dev) +{ +	/* +	 * The DT node of some GPIO chips have a "compatible" property, but +	 * never have a struct device added and probed by a driver to register +	 * the GPIO chip with gpiolib. In such cases, fw_devlink=on will cause +	 * the consumers of the GPIO chip to get probe deferred forever because +	 * they will be waiting for a device associated with the GPIO chip +	 * firmware node to get added and bound to a driver. +	 * +	 * To allow these consumers to probe, we associate the struct +	 * gpio_device of the GPIO chip with the firmware node and then simply +	 * bind it to this stub driver. +	 */ +	return 0; +} + +static struct device_driver gpio_stub_drv = { +	.name = "gpio_stub_drv", +	.bus = &gpio_bus_type, +	.probe = gpio_stub_drv_probe, +}; +  static int __init gpiolib_dev_init(void)  {  	int ret; @@ -4226,9 +4257,16 @@ static int __init gpiolib_dev_init(void)  		return ret;  	} +	if (driver_register(&gpio_stub_drv) < 0) { +		pr_err("gpiolib: could not register GPIO stub driver\n"); +		bus_unregister(&gpio_bus_type); +		return ret; +	} +  	ret = alloc_chrdev_region(&gpio_devt, 0, GPIO_DEV_MAX, GPIOCHIP_NAME);  	if (ret < 0) {  		pr_err("gpiolib: failed to allocate char dev region\n"); +		driver_unregister(&gpio_stub_drv);  		bus_unregister(&gpio_bus_type);  		return ret;  	}  | 
