diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 8a7cfb3..a87c5b8 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -26,17 +26,40 @@ EXPORT_SYMBOL_GPL(power_supply_class);
 
 static struct device_type power_supply_dev_type;
 
+static int __power_supply_is_supplied_by(struct power_supply *supplier,
+					 struct power_supply *supply)
+{
+	int i;
+#ifdef CONFIG_OF
+	struct power_supply_supplies *pss;
+#endif
+
+#ifdef CONFIG_OF
+	list_for_each_entry(pss, &supply->supplies.list, list) {
+		if (supplier->supplies.node == pss->node)
+			return 0;
+	}
+#endif
+
+	for (i = 0; i < supplier->num_supplicants; i++) {
+		if (!supply->name || !supplier->supplied_to)
+			continue;
+		if (!strcmp(supplier->supplied_to[i], supply->name))
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int __power_supply_changed_work(struct device *dev, void *data)
 {
 	struct power_supply *psy = (struct power_supply *)data;
 	struct power_supply *pst = dev_get_drvdata(dev);
-	int i;
 
-	for (i = 0; i < psy->num_supplicants; i++)
-		if (!strcmp(psy->supplied_to[i], pst->name)) {
-			if (pst->external_power_changed)
-				pst->external_power_changed(pst);
-		}
+	if (__power_supply_is_supplied_by(psy, pst)) {
+		if (pst->external_power_changed)
+			pst->external_power_changed(pst);
+	}
 	return 0;
 }
 
@@ -68,13 +91,9 @@ static int __power_supply_am_i_supplied(struct device *dev, void *data)
 	union power_supply_propval ret = {0,};
 	struct power_supply *psy = (struct power_supply *)data;
 	struct power_supply *epsy = dev_get_drvdata(dev);
-	int i;
 
-	for (i = 0; i < epsy->num_supplicants; i++) {
-		if (!strcmp(epsy->supplied_to[i], psy->name)) {
-			if (epsy->get_property(epsy,
-				  POWER_SUPPLY_PROP_ONLINE, &ret))
-				continue;
+	if (__power_supply_is_supplied_by(epsy, psy)) {
+		if (!epsy->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, &ret)) {
 			if (ret.intval)
 				return ret.intval;
 		}
@@ -334,6 +353,9 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
 	dev_set_drvdata(dev, psy);
 	psy->dev = dev;
 
+#ifdef CONFIG_OF
+	INIT_LIST_HEAD(&psy->supplies.list);
+#endif
 	INIT_WORK(&psy->changed_work, power_supply_changed_work);
 
 	rc = kobject_set_name(&dev->kobj, "%s", psy->name);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 1f0ab90..d16f6ab 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -15,6 +15,7 @@
 
 #include <linux/workqueue.h>
 #include <linux/leds.h>
+#include <linux/list.h>
 
 struct device;
 
@@ -160,12 +161,20 @@ union power_supply_propval {
 	const char *strval;
 };
 
+struct power_supply_supplies {
+	struct device_node *node;
+	struct list_head list;
+};
+
 struct power_supply {
 	const char *name;
 	enum power_supply_type type;
 	enum power_supply_property *properties;
 	size_t num_properties;
 
+#ifdef CONFIG_OF
+	struct power_supply_supplies supplies;
+#endif
 	char **supplied_to;
 	size_t num_supplicants;
 
