diff mbox

[v2] dt: platform driver: Fill the resources before probe and defer if needed

Message ID 1392988720-20976-1-git-send-email-jjhiblot@traphandler.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jean-Jacques Hiblot Feb. 21, 2014, 1:18 p.m. UTC
The goal of this patch is to allow drivers to be probed even if at the time of
the DT parsing some of their ressources are not available yet.

In the current situation, the resource of a platform device are filled from the
DT at the time the device is created (of_device_alloc()). The drawbackof this
is that a device sitting close to the top of the DT (ahb for example) but
depending on ressources that are initialized later (IRQ domain dynamically
created for example)  will fail to probe because the ressources don't exist
at this time.

This patch fills the resource structure only before the device is probed and
will defer the probe if the resource are not available yet.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---

Hi Grant,

I reworked the patch as you proposed. To keep the overhead minimum, nirq and
nreg are computed only the first time.
In this implementation, only the missing IRQ ressources are re-tried for. It could
easily be changed to re-parse all the IRQs though (replace if (!res->flags)
with if ((!res->flags) || (res->flags & IORESOURCE_IRQ)).

drivers/base/platform.c     |   5 +++
 drivers/of/platform.c       | 100 +++++++++++++++++++++++++++++++++-----------
 include/linux/of_platform.h |  10 +++++
 3 files changed, 90 insertions(+), 25 deletions(-)

Comments

Ludovic Desroches Feb. 27, 2014, 3:01 p.m. UTC | #1
On Fri, Feb 21, 2014 at 02:18:40PM +0100, Jean-Jacques Hiblot wrote:
> The goal of this patch is to allow drivers to be probed even if at the time of
> the DT parsing some of their ressources are not available yet.
> 
> In the current situation, the resource of a platform device are filled from the
> DT at the time the device is created (of_device_alloc()). The drawbackof this
> is that a device sitting close to the top of the DT (ahb for example) but
> depending on ressources that are initialized later (IRQ domain dynamically
> created for example)  will fail to probe because the ressources don't exist
> at this time.
> 
> This patch fills the resource structure only before the device is probed and
> will defer the probe if the resource are not available yet.
> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>

Tested-by: Ludovic Desroches <ludovic.desroches@atmel.com>

I wanted to add support for the external ethernet controller on
at91sam9n12ek board and I was facing an issue because the irq domain
doesn't exist yet (gpio controller as parent interrupt).

This patch solves this trouble.

> ---
> 
> Hi Grant,
> 
> I reworked the patch as you proposed. To keep the overhead minimum, nirq and
> nreg are computed only the first time.
> In this implementation, only the missing IRQ ressources are re-tried for. It could
> easily be changed to re-parse all the IRQs though (replace if (!res->flags)
> with if ((!res->flags) || (res->flags & IORESOURCE_IRQ)).
> 
> drivers/base/platform.c     |   5 +++
>  drivers/of/platform.c       | 100 +++++++++++++++++++++++++++++++++-----------
>  include/linux/of_platform.h |  10 +++++
>  3 files changed, 90 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index bc78848..cee9b8d 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -481,6 +481,10 @@ static int platform_drv_probe(struct device *_dev)
>  	struct platform_device *dev = to_platform_device(_dev);
>  	int ret;
>  
> +	ret = of_platform_device_prepare(dev);
> +	if (ret)
> +		goto error;
> +
>  	if (ACPI_HANDLE(_dev))
>  		acpi_dev_pm_attach(_dev, true);
>  
> @@ -488,6 +492,7 @@ static int platform_drv_probe(struct device *_dev)
>  	if (ret && ACPI_HANDLE(_dev))
>  		acpi_dev_pm_detach(_dev, true);
>  
> +error:
>  	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
>  		dev_warn(_dev, "probe deferral not supported\n");
>  		ret = -ENXIO;
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 404d1da..a4e2602 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -141,36 +141,11 @@ struct platform_device *of_device_alloc(struct device_node *np,
>  				  struct device *parent)
>  {
>  	struct platform_device *dev;
> -	int rc, i, num_reg = 0, num_irq;
> -	struct resource *res, temp_res;
>  
>  	dev = platform_device_alloc("", -1);
>  	if (!dev)
>  		return NULL;
>  
> -	/* count the io and irq resources */
> -	if (of_can_translate_address(np))
> -		while (of_address_to_resource(np, num_reg, &temp_res) == 0)
> -			num_reg++;
> -	num_irq = of_irq_count(np);
> -
> -	/* Populate the resource table */
> -	if (num_irq || num_reg) {
> -		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
> -		if (!res) {
> -			platform_device_put(dev);
> -			return NULL;
> -		}
> -
> -		dev->num_resources = num_reg + num_irq;
> -		dev->resource = res;
> -		for (i = 0; i < num_reg; i++, res++) {
> -			rc = of_address_to_resource(np, i, res);
> -			WARN_ON(rc);
> -		}
> -		WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
> -	}
> -
>  	dev->dev.of_node = of_node_get(np);
>  #if defined(CONFIG_MICROBLAZE)
>  	dev->dev.dma_mask = &dev->archdata.dma_mask;
> @@ -233,6 +208,81 @@ static struct platform_device *of_platform_device_create_pdata(
>  	return dev;
>  }
>  
> +static int of_reg_count(struct device_node *np)
> +{
> +	int nreg = 0;
> +	if (of_can_translate_address(np)) {
> +		struct resource temp_res;
> +		while (of_address_to_resource(np, nreg, &temp_res) == 0)
> +			nreg++;
> +	}
> +	return nreg;
> +}
> +
> +int of_platform_device_prepare(struct platform_device *dev)
> +{
> +	struct device_node *np;
> +	int i, irq_index;
> +	struct resource *res;
> +
> +	/*
> +	 * This function applies only devices described in the DT.
> +	 * Other platform devices have their ressources already populated.
> +	 */
> +	np = dev->dev.of_node;
> +	if (!np)
> +		return 0;
> +
> +	/* Populate the resource table */
> +	if (!dev->resource) {
> +		int rc, nreg = 0, nirq;
> +		/* count the io and irq resources */
> +		nreg = of_reg_count(np);
> +		nirq = of_irq_count(np);
> +
> +		if (!nirq && !nreg)
> +			return 0;
> +
> +		res = kzalloc(sizeof(*res) * (nirq + nreg), GFP_KERNEL);
> +		if (!res)
> +			return -ENOMEM;
> +
> +		dev->resource = res;
> +		dev->num_resources = nreg + nirq;
> +
> +		for (i = 0; i < nreg; i++, res++) {
> +			rc = of_address_to_resource(np, i, res);
> +			if (WARN_ON(rc)) {
> +				/* THIS IS BAD; don't try to defer probing */
> +				dev->num_resources = 0;
> +				dev->resource = NULL;
> +				kfree(res);
> +				return rc;
> +			}
> +		}
> +
> +		if (!rc && of_irq_to_resource_table(np, res, nirq) != nirq) {
> +			/* IRQ controller is yet available. defer probing */
> +			return -EPROBE_DEFER;
> +		}
> +
> +		return 0;
> +	}
> +
> +	/* See which IRQ resources need to be redone */
> +	irq_index = 0;
> +	for (i = 0, res = dev->resource; i < dev->num_resources; i++, res++) {
> +		if (!res->flags) {
> +			if (!of_irq_to_resource(np, irq_index, res))
> +				return -EPROBE_DEFER;
> +			irq_index++;
> +		} else if (res->flags & IORESOURCE_IRQ)
> +			irq_index++;
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL(of_platform_device_prepare);
> +
>  /**
>   * of_platform_device_create - Alloc, initialize and register an of_device
>   * @np: pointer to node to create device for
> diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
> index 05cb4a9..4e487ff 100644
> --- a/include/linux/of_platform.h
> +++ b/include/linux/of_platform.h
> @@ -53,6 +53,16 @@ struct of_dev_auxdata {
>  
>  extern const struct of_device_id of_default_bus_match_table[];
>  
> +/* Populate the resource for a platform device */
> +#ifdef CONFIG_OF
> +int of_platform_device_prepare(struct platform_device *dev);
> +#else
> +static inline int of_platform_device_prepare(
> +	struct platform_device *dev)
> +{
> +	return 0;
> +}
> +#endif
>  /* Platform drivers register/unregister */
>  extern struct platform_device *of_device_alloc(struct device_node *np,
>  					 const char *bus_id,
> -- 
> 1.9.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Grant Likely March 8, 2014, 7:37 a.m. UTC | #2
On Fri, 21 Feb 2014 14:18:40 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
> The goal of this patch is to allow drivers to be probed even if at the time of
> the DT parsing some of their ressources are not available yet.

Hi Jean-Jacques

[...]
> +int of_platform_device_prepare(struct platform_device *dev)
> +{
> +	struct device_node *np;
> +	int i, irq_index;
> +	struct resource *res;
> +
> +	/*
> +	 * This function applies only devices described in the DT.
> +	 * Other platform devices have their ressources already populated.
> +	 */
> +	np = dev->dev.of_node;
> +	if (!np)
> +		return 0;

I believe we already talked about the above test. This function must
only process devices created by of_platform_populate(). Merely checking
the of_node pointer is not a sufficient test because there are other
paths in the kernel for creating platform_devices that might get a node
pointer attached to it.

g.
Russell King - ARM Linux March 8, 2014, 11:59 a.m. UTC | #3
On Sat, Mar 08, 2014 at 07:37:58AM +0000, Grant Likely wrote:
> I believe we already talked about the above test. This function must
> only process devices created by of_platform_populate(). Merely checking
> the of_node pointer is not a sufficient test because there are other
> paths in the kernel for creating platform_devices that might get a node
> pointer attached to it.

There definitely are: there are a number of platform device drivers
which create a new platform device structure, and copy the of_node
pointer across.

However, that's really sick code, and can result in the platform device
driver probing the device it just created... this practise should be
outlawed.
Jean-Jacques Hiblot March 17, 2014, 11:07 a.m. UTC | #4
Hi Grant,

Sorry for the delay, I was having nice vacations.

2014-03-08 8:37 GMT+01:00 Grant Likely <grant.likely@linaro.org>:
> On Fri, 21 Feb 2014 14:18:40 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
>> The goal of this patch is to allow drivers to be probed even if at the time of
>> the DT parsing some of their ressources are not available yet.
>
> Hi Jean-Jacques
>
> [...]
>> +int of_platform_device_prepare(struct platform_device *dev)
>> +{
>> +     struct device_node *np;
>> +     int i, irq_index;
>> +     struct resource *res;
>> +
>> +     /*
>> +      * This function applies only devices described in the DT.
>> +      * Other platform devices have their ressources already populated.
>> +      */
>> +     np = dev->dev.of_node;
>> +     if (!np)
>> +             return 0;
>
> I believe we already talked about the above test. This function must
> only process devices created by of_platform_populate(). Merely checking
> the of_node pointer is not a sufficient test because there are other
> paths in the kernel for creating platform_devices that might get a node
> pointer attached to it.
Yes we talked about this, but only to move it into of_platform_device_prepare().
Is there an existing way to know for sure that the device has been
created by of_platform_populate() ? I could not find one.

Jean-Jacques
>
> g.
>
Grant Likely March 17, 2014, 2:24 p.m. UTC | #5
On Mon, 17 Mar 2014 12:07:37 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
> Hi Grant,
> 
> Sorry for the delay, I was having nice vacations.
> 
> 2014-03-08 8:37 GMT+01:00 Grant Likely <grant.likely@linaro.org>:
> > On Fri, 21 Feb 2014 14:18:40 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
> >> The goal of this patch is to allow drivers to be probed even if at the time of
> >> the DT parsing some of their ressources are not available yet.
> >
> > Hi Jean-Jacques
> >
> > [...]
> >> +int of_platform_device_prepare(struct platform_device *dev)
> >> +{
> >> +     struct device_node *np;
> >> +     int i, irq_index;
> >> +     struct resource *res;
> >> +
> >> +     /*
> >> +      * This function applies only devices described in the DT.
> >> +      * Other platform devices have their ressources already populated.
> >> +      */
> >> +     np = dev->dev.of_node;
> >> +     if (!np)
> >> +             return 0;
> >
> > I believe we already talked about the above test. This function must
> > only process devices created by of_platform_populate(). Merely checking
> > the of_node pointer is not a sufficient test because there are other
> > paths in the kernel for creating platform_devices that might get a node
> > pointer attached to it.
> Yes we talked about this, but only to move it into of_platform_device_prepare().
> Is there an existing way to know for sure that the device has been
> created by of_platform_populate() ? I could not find one.

No there isn't. That information is used at population time and then
discarded. We'd need to add a flag or registry to mark those devices.

g.

> 
> Jean-Jacques
> >
> > g.
> >
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Jean-Jacques Hiblot March 17, 2014, 3:20 p.m. UTC | #6
2014-03-17 15:24 GMT+01:00 Grant Likely <grant.likely@secretlab.ca>:
> On Mon, 17 Mar 2014 12:07:37 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
>> Hi Grant,
>>
>> Sorry for the delay, I was having nice vacations.
>>
>> 2014-03-08 8:37 GMT+01:00 Grant Likely <grant.likely@linaro.org>:
>> > On Fri, 21 Feb 2014 14:18:40 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
>> >> The goal of this patch is to allow drivers to be probed even if at the time of
>> >> the DT parsing some of their ressources are not available yet.
>> >
>> > Hi Jean-Jacques
>> >
>> > [...]
>> >> +int of_platform_device_prepare(struct platform_device *dev)
>> >> +{
>> >> +     struct device_node *np;
>> >> +     int i, irq_index;
>> >> +     struct resource *res;
>> >> +
>> >> +     /*
>> >> +      * This function applies only devices described in the DT.
>> >> +      * Other platform devices have their ressources already populated.
>> >> +      */
>> >> +     np = dev->dev.of_node;
>> >> +     if (!np)
>> >> +             return 0;
>> >
>> > I believe we already talked about the above test. This function must
>> > only process devices created by of_platform_populate(). Merely checking
>> > the of_node pointer is not a sufficient test because there are other
>> > paths in the kernel for creating platform_devices that might get a node
>> > pointer attached to it.
>> Yes we talked about this, but only to move it into of_platform_device_prepare().
>> Is there an existing way to know for sure that the device has been
>> created by of_platform_populate() ? I could not find one.
>
> No there isn't. That information is used at population time and then
> discarded. We'd need to add a flag or registry to mark those devices.
OK. As I see it, this could be done either by adding a new flag to
struct device or by maintaining a private list of "of created" devices
in of/platform.c.
I favor modifying struct device as it's is by far the simplest but
it's also more intrusive. Any advice ?

Jean-Jacques

>
> g.
>
>>
>> Jean-Jacques
>> >
>> > g.
>> >
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
Grant Likely March 20, 2014, 4:11 p.m. UTC | #7
On Mon, 17 Mar 2014 16:20:03 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
> 2014-03-17 15:24 GMT+01:00 Grant Likely <grant.likely@secretlab.ca>:
> > On Mon, 17 Mar 2014 12:07:37 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
> >> Hi Grant,
> >>
> >> Sorry for the delay, I was having nice vacations.
> >>
> >> 2014-03-08 8:37 GMT+01:00 Grant Likely <grant.likely@linaro.org>:
> >> > On Fri, 21 Feb 2014 14:18:40 +0100, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote:
> >> >> The goal of this patch is to allow drivers to be probed even if at the time of
> >> >> the DT parsing some of their ressources are not available yet.
> >> >
> >> > Hi Jean-Jacques
> >> >
> >> > [...]
> >> >> +int of_platform_device_prepare(struct platform_device *dev)
> >> >> +{
> >> >> +     struct device_node *np;
> >> >> +     int i, irq_index;
> >> >> +     struct resource *res;
> >> >> +
> >> >> +     /*
> >> >> +      * This function applies only devices described in the DT.
> >> >> +      * Other platform devices have their ressources already populated.
> >> >> +      */
> >> >> +     np = dev->dev.of_node;
> >> >> +     if (!np)
> >> >> +             return 0;
> >> >
> >> > I believe we already talked about the above test. This function must
> >> > only process devices created by of_platform_populate(). Merely checking
> >> > the of_node pointer is not a sufficient test because there are other
> >> > paths in the kernel for creating platform_devices that might get a node
> >> > pointer attached to it.
> >> Yes we talked about this, but only to move it into of_platform_device_prepare().
> >> Is there an existing way to know for sure that the device has been
> >> created by of_platform_populate() ? I could not find one.
> >
> > No there isn't. That information is used at population time and then
> > discarded. We'd need to add a flag or registry to mark those devices.
> OK. As I see it, this could be done either by adding a new flag to
> struct device or by maintaining a private list of "of created" devices
> in of/platform.c.
> I favor modifying struct device as it's is by far the simplest but
> it's also more intrusive. Any advice ?

I think that by far is the easiest. It is that, or
of_platform_populate() would need to maintain a list of devices that are
to be used as a platform bus.

g.
Jean-Jacques Hiblot March 21, 2014, 2:46 p.m. UTC | #8
Hi Grant,

This is the 3rd version of the patch. It's been reworked to screen the devices
not created by of_device_alloc() and check the reason why an OF IRQ description
can't be translated into a resource.

Jean-Jacques

Changes since V2:
 * only fill the resources for devices created by of_device_alloc(). Note:
   this is done by adding a new flag in struct device {}.
 * use deferred probing only if the IRQ domain cannot be found. 
  
Jean-Jacques Hiblot (2):
  of: irq: Added of_find_irq_domain() to get the domain of an irq
  dt: platform driver: Fill the resources before probe and defer if
    needed

 drivers/base/platform.c     |   5 ++
 drivers/of/irq.c            |  20 ++++++++
 drivers/of/platform.c       | 114 ++++++++++++++++++++++++++++++++++----------
 include/linux/device.h      |   1 +
 include/linux/of_irq.h      |   2 +
 include/linux/of_platform.h |  10 ++++
 6 files changed, 127 insertions(+), 25 deletions(-)
diff mbox

Patch

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index bc78848..cee9b8d 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -481,6 +481,10 @@  static int platform_drv_probe(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 	int ret;
 
+	ret = of_platform_device_prepare(dev);
+	if (ret)
+		goto error;
+
 	if (ACPI_HANDLE(_dev))
 		acpi_dev_pm_attach(_dev, true);
 
@@ -488,6 +492,7 @@  static int platform_drv_probe(struct device *_dev)
 	if (ret && ACPI_HANDLE(_dev))
 		acpi_dev_pm_detach(_dev, true);
 
+error:
 	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
 		dev_warn(_dev, "probe deferral not supported\n");
 		ret = -ENXIO;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1da..a4e2602 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -141,36 +141,11 @@  struct platform_device *of_device_alloc(struct device_node *np,
 				  struct device *parent)
 {
 	struct platform_device *dev;
-	int rc, i, num_reg = 0, num_irq;
-	struct resource *res, temp_res;
 
 	dev = platform_device_alloc("", -1);
 	if (!dev)
 		return NULL;
 
-	/* count the io and irq resources */
-	if (of_can_translate_address(np))
-		while (of_address_to_resource(np, num_reg, &temp_res) == 0)
-			num_reg++;
-	num_irq = of_irq_count(np);
-
-	/* Populate the resource table */
-	if (num_irq || num_reg) {
-		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
-		if (!res) {
-			platform_device_put(dev);
-			return NULL;
-		}
-
-		dev->num_resources = num_reg + num_irq;
-		dev->resource = res;
-		for (i = 0; i < num_reg; i++, res++) {
-			rc = of_address_to_resource(np, i, res);
-			WARN_ON(rc);
-		}
-		WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
-	}
-
 	dev->dev.of_node = of_node_get(np);
 #if defined(CONFIG_MICROBLAZE)
 	dev->dev.dma_mask = &dev->archdata.dma_mask;
@@ -233,6 +208,81 @@  static struct platform_device *of_platform_device_create_pdata(
 	return dev;
 }
 
+static int of_reg_count(struct device_node *np)
+{
+	int nreg = 0;
+	if (of_can_translate_address(np)) {
+		struct resource temp_res;
+		while (of_address_to_resource(np, nreg, &temp_res) == 0)
+			nreg++;
+	}
+	return nreg;
+}
+
+int of_platform_device_prepare(struct platform_device *dev)
+{
+	struct device_node *np;
+	int i, irq_index;
+	struct resource *res;
+
+	/*
+	 * This function applies only devices described in the DT.
+	 * Other platform devices have their ressources already populated.
+	 */
+	np = dev->dev.of_node;
+	if (!np)
+		return 0;
+
+	/* Populate the resource table */
+	if (!dev->resource) {
+		int rc, nreg = 0, nirq;
+		/* count the io and irq resources */
+		nreg = of_reg_count(np);
+		nirq = of_irq_count(np);
+
+		if (!nirq && !nreg)
+			return 0;
+
+		res = kzalloc(sizeof(*res) * (nirq + nreg), GFP_KERNEL);
+		if (!res)
+			return -ENOMEM;
+
+		dev->resource = res;
+		dev->num_resources = nreg + nirq;
+
+		for (i = 0; i < nreg; i++, res++) {
+			rc = of_address_to_resource(np, i, res);
+			if (WARN_ON(rc)) {
+				/* THIS IS BAD; don't try to defer probing */
+				dev->num_resources = 0;
+				dev->resource = NULL;
+				kfree(res);
+				return rc;
+			}
+		}
+
+		if (!rc && of_irq_to_resource_table(np, res, nirq) != nirq) {
+			/* IRQ controller is yet available. defer probing */
+			return -EPROBE_DEFER;
+		}
+
+		return 0;
+	}
+
+	/* See which IRQ resources need to be redone */
+	irq_index = 0;
+	for (i = 0, res = dev->resource; i < dev->num_resources; i++, res++) {
+		if (!res->flags) {
+			if (!of_irq_to_resource(np, irq_index, res))
+				return -EPROBE_DEFER;
+			irq_index++;
+		} else if (res->flags & IORESOURCE_IRQ)
+			irq_index++;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(of_platform_device_prepare);
+
 /**
  * of_platform_device_create - Alloc, initialize and register an of_device
  * @np: pointer to node to create device for
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 05cb4a9..4e487ff 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -53,6 +53,16 @@  struct of_dev_auxdata {
 
 extern const struct of_device_id of_default_bus_match_table[];
 
+/* Populate the resource for a platform device */
+#ifdef CONFIG_OF
+int of_platform_device_prepare(struct platform_device *dev);
+#else
+static inline int of_platform_device_prepare(
+	struct platform_device *dev)
+{
+	return 0;
+}
+#endif
 /* Platform drivers register/unregister */
 extern struct platform_device *of_device_alloc(struct device_node *np,
 					 const char *bus_id,