diff options
Diffstat (limited to 'drivers/base/platform.c')
| -rw-r--r-- | drivers/base/platform.c | 72 | 
1 files changed, 55 insertions, 17 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4f8bef3eb5a..eee48c49f5d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -13,6 +13,7 @@  #include <linux/string.h>  #include <linux/platform_device.h>  #include <linux/of_device.h> +#include <linux/of_irq.h>  #include <linux/module.h>  #include <linux/init.h>  #include <linux/dma-mapping.h> @@ -87,7 +88,16 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)  		return -ENXIO;  	return dev->archdata.irqs[num];  #else -	struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); +	struct resource *r; +	if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { +		int ret; + +		ret = of_irq_get(dev->dev.of_node, num); +		if (ret >= 0 || ret == -EPROBE_DEFER) +			return ret; +	} + +	r = platform_get_resource(dev, IORESOURCE_IRQ, num);  	return r ? r->start : -ENXIO;  #endif @@ -126,9 +136,17 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname);   */  int platform_get_irq_byname(struct platform_device *dev, const char *name)  { -	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, -							  name); +	struct resource *r; + +	if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { +		int ret; + +		ret = of_irq_get_byname(dev->dev.of_node, name); +		if (ret >= 0 || ret == -EPROBE_DEFER) +			return ret; +	} +	r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);  	return r ? r->start : -ENXIO;  }  EXPORT_SYMBOL_GPL(platform_get_irq_byname); @@ -432,7 +450,7 @@ struct platform_device *platform_device_register_full(  		goto err_alloc;  	pdev->dev.parent = pdevinfo->parent; -	ACPI_HANDLE_SET(&pdev->dev, pdevinfo->acpi_node.handle); +	ACPI_COMPANION_SET(&pdev->dev, pdevinfo->acpi_node.companion);  	if (pdevinfo->dma_mask) {  		/* @@ -463,7 +481,7 @@ struct platform_device *platform_device_register_full(  	ret = platform_device_add(pdev);  	if (ret) {  err: -		ACPI_HANDLE_SET(&pdev->dev, NULL); +		ACPI_COMPANION_SET(&pdev->dev, NULL);  		kfree(pdev->dev.dma_mask);  err_alloc: @@ -481,13 +499,17 @@ static int platform_drv_probe(struct device *_dev)  	struct platform_device *dev = to_platform_device(_dev);  	int ret; -	if (ACPI_HANDLE(_dev)) -		acpi_dev_pm_attach(_dev, true); +	acpi_dev_pm_attach(_dev, true);  	ret = drv->probe(dev); -	if (ret && ACPI_HANDLE(_dev)) +	if (ret)  		acpi_dev_pm_detach(_dev, true); +	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { +		dev_warn(_dev, "probe deferral not supported\n"); +		ret = -ENXIO; +	} +  	return ret;  } @@ -503,8 +525,7 @@ static int platform_drv_remove(struct device *_dev)  	int ret;  	ret = drv->remove(dev); -	if (ACPI_HANDLE(_dev)) -		acpi_dev_pm_detach(_dev, true); +	acpi_dev_pm_detach(_dev, true);  	return ret;  } @@ -515,8 +536,7 @@ static void platform_drv_shutdown(struct device *_dev)  	struct platform_device *dev = to_platform_device(_dev);  	drv->shutdown(dev); -	if (ACPI_HANDLE(_dev)) -		acpi_dev_pm_detach(_dev, true); +	acpi_dev_pm_detach(_dev, true);  }  /** @@ -553,8 +573,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);  /**   * platform_driver_probe - register driver for non-hotpluggable device   * @drv: platform driver structure - * @probe: the driver probe routine, probably from an __init section, - *         must not return -EPROBE_DEFER. + * @probe: the driver probe routine, probably from an __init section   *   * Use this instead of platform_driver_register() when you know the device   * is not hotpluggable and has already been registered, and you want to @@ -565,8 +584,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);   * into system-on-chip processors, where the controller devices have been   * configured as part of board setup.   * - * This is incompatible with deferred probing so probe() must not - * return -EPROBE_DEFER. + * Note that this is incompatible with deferred probing.   *   * Returns zero if the driver registered and bound to a device, else returns   * a negative error code and with the driver not registered. @@ -576,6 +594,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,  {  	int retval, code; +	/* +	 * Prevent driver from requesting probe deferral to avoid further +	 * futile probe attempts. +	 */ +	drv->prevent_deferred_probe = true; +  	/* make sure driver won't have bind/unbind attributes */  	drv->driver.suppress_bind_attrs = true; @@ -668,7 +692,17 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,  			     char *buf)  {  	struct platform_device	*pdev = to_platform_device(dev); -	int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name); +	int len; + +	len = of_device_get_modalias(dev, buf, PAGE_SIZE -1); +	if (len != -ENODEV) +		return len; + +	len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); +	if (len != -ENODEV) +		return len; + +	len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);  	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;  } @@ -690,6 +724,10 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)  	if (rc != -ENODEV)  		return rc; +	rc = acpi_device_uevent_modalias(dev, env); +	if (rc != -ENODEV) +		return rc; +  	add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,  			pdev->name);  	return 0;  | 
