diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 4f8bef3..8dcf835 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_probe(dev);
+	if (ret)
+		return ret;
+
 	if (ACPI_HANDLE(_dev))
 		acpi_dev_pm_attach(_dev, true);
 
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 9b439ac..df6d56e 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -142,7 +142,7 @@ 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;
+	int rc, i, num_reg = 0;
 	struct resource *res, temp_res;
 
 	dev = platform_device_alloc("", -1);
@@ -153,23 +153,21 @@ struct platform_device *of_device_alloc(struct device_node *np,
 	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 (num_reg) {
+		res = kzalloc(sizeof(*res) * num_reg, GFP_KERNEL);
 		if (!res) {
 			platform_device_put(dev);
 			return NULL;
 		}
 
-		dev->num_resources = num_reg + num_irq;
+		dev->num_resources = num_reg;
 		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);
@@ -490,4 +488,101 @@ int of_platform_populate(struct device_node *root,
 	return rc;
 }
 EXPORT_SYMBOL_GPL(of_platform_populate);
+
+/**
+ * of_platform_parse_irq() - parse interrupt resource from device node
+ * @pdev: pointer to platform device
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int of_platform_parse_irq(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int num_res = pdev->num_resources;
+	struct resource *res = pdev->resource;
+	unsigned int num_irq, num, c;
+	int ret = 0;
+
+	num_irq = of_irq_count(pdev->dev.of_node);
+	if (!num_irq)
+		return 0;
+
+	/*
+	 * Deferred probing may cause this function to be called multiple
+	 * times, so check if all interrupts have been parsed already and
+	 * return early.
+	 */
+	for (c = 0; c < num_irq; c++)
+		if (platform_get_irq(pdev, c) < 0)
+			break;
+
+	if (c == num_irq)
+		return 0;
+
+	num = num_res + num_irq;
+
+	/*
+	 * Note that in case we're called twice on the same device (due to
+	 * deferred probing for example) this will simply be a nop because
+	 * krealloc() returns the input pointer if the size of the memory
+	 * block that it points to is larger than or equal to the new size
+	 * being requested.
+	 */
+	res = krealloc(res, num * sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return -ENOMEM;
+
+	pdev->resource = res;
+	res += num_res;
+
+	/*
+	 * It is possible for this to fail. If so, not that the number of
+	 * resources is not updated, so that the next call to this function
+	 * will parse all interrupts again. Otherwise we can't keep track of
+	 * how many we've parsed so far.
+	 */
+	ret = of_irq_to_resource_table(np, res, num_irq);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * All interrupts are guaranteed to have been parsed and stored in
+	 * the resource table, so the number of resources can now safely be
+	 * updated.
+	 */
+	pdev->num_resources += num_irq;
+
+	return 0;
+}
+
+/**
+ * of_platform_probe() - OF specific initialization at probe time
+ * @pdev: pointer to a platform device
+ *
+ * This function is called by the driver core to perform devicetree-specific
+ * setup for a given platform device at probe time. If a device's resources
+ * as specified in the device tree are not available yet, this function can
+ * return -EPROBE_DEFER and cause the device to be probed again later, when
+ * other drivers that potentially provide the missing resources have been
+ * probed in turn.
+ *
+ * Note that because of the above, all code executed by this function must
+ * be prepared to be run multiple times on the same device (i.e. it must be
+ * idempotent).
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int of_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return 0;
+
+	ret = of_platform_parse_irq(pdev);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
 #endif /* CONFIG_OF_ADDRESS */
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 05cb4a9..92fc4f6 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -72,6 +72,8 @@ extern int of_platform_populate(struct device_node *root,
 				const struct of_device_id *matches,
 				const struct of_dev_auxdata *lookup,
 				struct device *parent);
+
+extern int of_platform_probe(struct platform_device *pdev);
 #else
 static inline int of_platform_populate(struct device_node *root,
 					const struct of_device_id *matches,
@@ -80,6 +82,11 @@ static inline int of_platform_populate(struct device_node *root,
 {
 	return -ENODEV;
 }
+
+static inline int of_platform_probe(struct platform_device *pdev)
+{
+	return 0;
+}
 #endif
 
 #endif	/* _LINUX_OF_PLATFORM_H */
