Browse Source

Merge tag 'devicetree-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull DeviceTree updates from Rob Herring:

 - add various vendor prefixes.

 - fix NUMA node handling when "numa=off" is passed on kernel command
   line.

 - coding style Clean-up of overlay handling code.

 - DocBook fixes in DT platform driver code

 - Altera SoCFPGA binding addtions for freeze bridge, arria10 FPGA
   manager and FPGA bridges.

 - a couple of printk message fixes.

* tag 'devicetree-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (33 commits)
  dt: pwm: bcm2835: fix typo in clocks property name
  devicetree: add vendor prefix for National Instruments
  Revert "of: base: add support to get machine model name"
  of: Fix issue where code would fall through to error case.
  drivers/of: fix missing pr_cont()s in of_print_phandle_args
  devicetree: bindings: Add vendor prefix for Oki
  devicetree: bindings: Add vendor prefix for Andes Technology Corporation
  dt-bindings: add MYIR Tech hardware vendor prefix
  add bindings document for altera freeze bridge
  ARM: socfpga: add bindings doc for arria10 fpga manager
  ARM: socfpga: add bindings document for fpga bridge drivers
  of: base: add support to get machine model name
  of/platform: clarify of_find_device_by_node refcounting
  of/platform: fix of_platform_device_destroy comment
  of: Remove unused variable overlay_symbols
  of: Move setting of pointer to beside test for non-null
  of: Add back an error message, restructured
  of: Update comments to reflect changes and increase clarity
  of: Remove redundant size check
  of: Update structure of code to be clearer, also remove BUG_ON()
  ...
Linus Torvalds 9 years ago
parent
commit
6df8b74b17

+ 2 - 1
Documentation/devicetree/bindings/arm/arm-boards

@@ -148,11 +148,12 @@ Example:
 
 
 /dts-v1/;
 /dts-v1/;
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include "skeleton.dtsi"
 
 
 / {
 / {
 	model = "ARM RealView PB1176 with device tree";
 	model = "ARM RealView PB1176 with device tree";
 	compatible = "arm,realview-pb1176";
 	compatible = "arm,realview-pb1176";
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 
 	soc {
 	soc {
 		#address-cells = <1>;
 		#address-cells = <1>;

+ 16 - 0
Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt

@@ -0,0 +1,16 @@
+Altera FPGA To SDRAM Bridge Driver
+
+Required properties:
+- compatible		: Should contain "altr,socfpga-fpga2sdram-bridge"
+
+Optional properties:
+- bridge-enable		: 0 if driver should disable bridge at startup
+			  1 if driver should enable bridge at startup
+			  Default is to leave bridge in current state.
+
+Example:
+	fpga_bridge3: fpga-bridge@ffc25080 {
+		compatible = "altr,socfpga-fpga2sdram-bridge";
+		reg = <0xffc25080 0x4>;
+		bridge-enable = <0>;
+	};

+ 23 - 0
Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt

@@ -0,0 +1,23 @@
+Altera Freeze Bridge Controller Driver
+
+The Altera Freeze Bridge Controller manages one or more freeze bridges.
+The controller can freeze/disable the bridges which prevents signal
+changes from passing through the bridge.  The controller can also
+unfreeze/enable the bridges which allows traffic to pass through the
+bridge normally.
+
+Required properties:
+- compatible		: Should contain "altr,freeze-bridge-controller"
+- regs			: base address and size for freeze bridge module
+
+Optional properties:
+- bridge-enable		: 0 if driver should disable bridge at startup
+			  1 if driver should enable bridge at startup
+			  Default is to leave bridge in current state.
+
+Example:
+	freeze-controller@100000450 {
+		compatible = "altr,freeze-bridge-controller";
+		regs = <0x1000 0x10>;
+		bridge-enable = <0>;
+	};

+ 39 - 0
Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt

@@ -0,0 +1,39 @@
+Altera FPGA/HPS Bridge Driver
+
+Required properties:
+- regs		: base address and size for AXI bridge module
+- compatible	: Should contain one of:
+		  "altr,socfpga-lwhps2fpga-bridge",
+		  "altr,socfpga-hps2fpga-bridge", or
+		  "altr,socfpga-fpga2hps-bridge"
+- resets	: Phandle and reset specifier for this bridge's reset
+- clocks	: Clocks used by this module.
+
+Optional properties:
+- bridge-enable	: 0 if driver should disable bridge at startup.
+		  1 if driver should enable bridge at startup.
+		  Default is to leave bridge in its current state.
+
+Example:
+	fpga_bridge0: fpga-bridge@ff400000 {
+		compatible = "altr,socfpga-lwhps2fpga-bridge";
+		reg = <0xff400000 0x100000>;
+		resets = <&rst LWHPS2FPGA_RESET>;
+		clocks = <&l4_main_clk>;
+		bridge-enable = <0>;
+	};
+
+	fpga_bridge1: fpga-bridge@ff500000 {
+		compatible = "altr,socfpga-hps2fpga-bridge";
+		reg = <0xff500000 0x10000>;
+		resets = <&rst HPS2FPGA_RESET>;
+		clocks = <&l4_main_clk>;
+		bridge-enable = <1>;
+	};
+
+	fpga_bridge2: fpga-bridge@ff600000 {
+		compatible = "altr,socfpga-fpga2hps-bridge";
+		reg = <0xff600000 0x100000>;
+		resets = <&rst FPGA2HPS_RESET>;
+		clocks = <&l4_main_clk>;
+	};

+ 19 - 0
Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt

@@ -0,0 +1,19 @@
+Altera SOCFPGA Arria10 FPGA Manager
+
+Required properties:
+- compatible : should contain "altr,socfpga-a10-fpga-mgr"
+- reg        : base address and size for memory mapped io.
+               - The first index is for FPGA manager register access.
+               - The second index is for writing FPGA configuration data.
+- resets     : Phandle and reset specifier for the device's reset.
+- clocks     : Clocks used by the device.
+
+Example:
+
+	fpga_mgr: fpga-mgr@ffd03000 {
+		compatible = "altr,socfpga-a10-fpga-mgr";
+		reg = <0xffd03000 0x100
+		       0xffcfe400 0x20>;
+		clocks = <&l4_mp_clk>;
+		resets = <&rst FPGAMGR_RESET>;
+	};

+ 1 - 1
Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt

@@ -3,7 +3,7 @@ BCM2835 PWM controller (Raspberry Pi controller)
 Required properties:
 Required properties:
 - compatible: should be "brcm,bcm2835-pwm"
 - compatible: should be "brcm,bcm2835-pwm"
 - reg: physical base address and length of the controller's registers
 - reg: physical base address and length of the controller's registers
-- clock: This clock defines the base clock frequency of the PWM hardware
+- clocks: This clock defines the base clock frequency of the PWM hardware
   system, the period and the duty_cycle of the PWM signal is a multiple of
   system, the period and the duty_cycle of the PWM signal is a multiple of
   the base period.
   the base period.
 - #pwm-cells: Should be 2. See pwm.txt in this directory for a description of
 - #pwm-cells: Should be 2. See pwm.txt in this directory for a description of

+ 10 - 1
Documentation/devicetree/bindings/vendor-prefixes.txt

@@ -24,9 +24,11 @@ ampire	Ampire Co., Ltd.
 ams	AMS AG
 ams	AMS AG
 amstaos	AMS-Taos Inc.
 amstaos	AMS-Taos Inc.
 analogix	Analogix Semiconductor, Inc.
 analogix	Analogix Semiconductor, Inc.
+andestech	Andes Technology Corporation
 apm	Applied Micro Circuits Corporation (APM)
 apm	Applied Micro Circuits Corporation (APM)
 aptina	Aptina Imaging
 aptina	Aptina Imaging
 arasan	Arasan Chip Systems
 arasan	Arasan Chip Systems
+aries	Aries Embedded GmbH
 arm	ARM Ltd.
 arm	ARM Ltd.
 armadeus	ARMadeus Systems SARL
 armadeus	ARMadeus Systems SARL
 arrow	Arrow Electronics
 arrow	Arrow Electronics
@@ -161,6 +163,7 @@ lg	LG Corporation
 linux	Linux-specific binding
 linux	Linux-specific binding
 lltc	Linear Technology Corporation
 lltc	Linear Technology Corporation
 lsi	LSI Corp. (LSI Logic)
 lsi	LSI Corp. (LSI Logic)
+macnica	Macnica Americas
 marvell	Marvell Technology Group Ltd.
 marvell	Marvell Technology Group Ltd.
 maxim	Maxim Integrated Products
 maxim	Maxim Integrated Products
 mcube	mCube
 mcube	mCube
@@ -186,6 +189,7 @@ mti	Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
 mundoreader	Mundo Reader S.L.
 mundoreader	Mundo Reader S.L.
 murata	Murata Manufacturing Co., Ltd.
 murata	Murata Manufacturing Co., Ltd.
 mxicy	Macronix International Co., Ltd.
 mxicy	Macronix International Co., Ltd.
+myir	MYIR Tech Limited
 national	National Semiconductor
 national	National Semiconductor
 nec	NEC LCD Technologies, Ltd.
 nec	NEC LCD Technologies, Ltd.
 neonode		Neonode Inc.
 neonode		Neonode Inc.
@@ -193,13 +197,15 @@ netgear	NETGEAR
 netlogic	Broadcom Corporation (formerly NetLogic Microsystems)
 netlogic	Broadcom Corporation (formerly NetLogic Microsystems)
 netxeon		Shenzhen Netxeon Technology CO., LTD
 netxeon		Shenzhen Netxeon Technology CO., LTD
 newhaven	Newhaven Display International
 newhaven	Newhaven Display International
-nvd	New Vision Display
+ni	National Instruments
 nintendo	Nintendo
 nintendo	Nintendo
 nokia	Nokia
 nokia	Nokia
 nuvoton	Nuvoton Technology Corporation
 nuvoton	Nuvoton Technology Corporation
+nvd	New Vision Display
 nvidia	NVIDIA
 nvidia	NVIDIA
 nxp	NXP Semiconductors
 nxp	NXP Semiconductors
 okaya	Okaya Electric America, Inc.
 okaya	Okaya Electric America, Inc.
+oki	Oki Electric Industry Co., Ltd.
 olimex	OLIMEX Ltd.
 olimex	OLIMEX Ltd.
 onion	Onion Corporation
 onion	Onion Corporation
 onnn	ON Semiconductor Corp.
 onnn	ON Semiconductor Corp.
@@ -238,6 +244,7 @@ richtek	Richtek Technology Corporation
 ricoh	Ricoh Co. Ltd.
 ricoh	Ricoh Co. Ltd.
 rockchip	Fuzhou Rockchip Electronics Co., Ltd
 rockchip	Fuzhou Rockchip Electronics Co., Ltd
 samsung	Samsung Semiconductor
 samsung	Samsung Semiconductor
+samtec	Samtec/Softing company
 sandisk	Sandisk Corporation
 sandisk	Sandisk Corporation
 sbs	Smart Battery System
 sbs	Smart Battery System
 schindler	Schindler
 schindler	Schindler
@@ -282,6 +289,7 @@ tcg	Trusted Computing Group
 tcl	Toby Churchill Ltd.
 tcl	Toby Churchill Ltd.
 technexion	TechNexion
 technexion	TechNexion
 technologic	Technologic Systems
 technologic	Technologic Systems
+terasic	Terasic Inc.
 thine	THine Electronics, Inc.
 thine	THine Electronics, Inc.
 ti	Texas Instruments
 ti	Texas Instruments
 tlm	Trusted Logic Mobility
 tlm	Trusted Logic Mobility
@@ -296,6 +304,7 @@ tronfy	Tronfy
 tronsmart	Tronsmart
 tronsmart	Tronsmart
 truly	Truly Semiconductors Limited
 truly	Truly Semiconductors Limited
 tyan	Tyan Computer Corporation
 tyan	Tyan Computer Corporation
+udoo	Udoo
 uniwest	United Western Technologies Corp (UniWest)
 uniwest	United Western Technologies Corp (UniWest)
 upisemi	uPI Semiconductor Corp.
 upisemi	uPI Semiconductor Corp.
 urt	United Radiant Technology Corporation
 urt	United Radiant Technology Corporation

+ 6 - 3
drivers/of/base.c

@@ -1534,9 +1534,12 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
 {
 {
 	int i;
 	int i;
 	printk("%s %s", msg, of_node_full_name(args->np));
 	printk("%s %s", msg, of_node_full_name(args->np));
-	for (i = 0; i < args->args_count; i++)
-		printk(i ? ",%08x" : ":%08x", args->args[i]);
-	printk("\n");
+	for (i = 0; i < args->args_count; i++) {
+		const char delim = i ? ',' : ':';
+
+		pr_cont("%c%08x", delim, args->args[i]);
+	}
+	pr_cont("\n");
 }
 }
 
 
 int of_phandle_iterator_init(struct of_phandle_iterator *it,
 int of_phandle_iterator_init(struct of_phandle_iterator *it,

+ 6 - 1
drivers/of/of_numa.c

@@ -176,7 +176,12 @@ int of_node_to_nid(struct device_node *device)
 			np->name);
 			np->name);
 	of_node_put(np);
 	of_node_put(np);
 
 
-	if (!r)
+	/*
+	 * If numa=off passed on command line, or with a defective
+	 * device tree, the nid may not be in the set of possible
+	 * nodes.  Check for this case and return NUMA_NO_NODE.
+	 */
+	if (!r && nid < MAX_NUMNODES && node_possible(nid))
 		return nid;
 		return nid;
 
 
 	return NUMA_NO_NODE;
 	return NUMA_NO_NODE;

+ 3 - 3
drivers/of/platform.c

@@ -45,6 +45,9 @@ static int of_dev_node_match(struct device *dev, void *data)
  * of_find_device_by_node - Find the platform_device associated with a node
  * of_find_device_by_node - Find the platform_device associated with a node
  * @np: Pointer to device tree node
  * @np: Pointer to device tree node
  *
  *
+ * Takes a reference to the embedded struct device which needs to be dropped
+ * after use.
+ *
  * Returns platform_device pointer, or NULL if not found
  * Returns platform_device pointer, or NULL if not found
  */
  */
 struct platform_device *of_find_device_by_node(struct device_node *np)
 struct platform_device *of_find_device_by_node(struct device_node *np)
@@ -558,9 +561,6 @@ static int of_platform_device_destroy(struct device *dev, void *data)
  * of the given device (and, recurrently, their children) that have been
  * of the given device (and, recurrently, their children) that have been
  * created from their respective device tree nodes (and only those,
  * created from their respective device tree nodes (and only those,
  * leaving others - eg. manually created - unharmed).
  * leaving others - eg. manually created - unharmed).
- *
- * Returns 0 when all children devices have been removed or
- * -EBUSY when some children remained.
  */
  */
 void of_platform_depopulate(struct device *parent)
 void of_platform_depopulate(struct device *parent)
 {
 {

+ 153 - 205
drivers/of/resolver.c

@@ -28,20 +28,19 @@
  * Find a node with the give full name by recursively following any of
  * Find a node with the give full name by recursively following any of
  * the child node links.
  * the child node links.
  */
  */
-static struct device_node *__of_find_node_by_full_name(struct device_node *node,
+static struct device_node *find_node_by_full_name(struct device_node *node,
 		const char *full_name)
 		const char *full_name)
 {
 {
 	struct device_node *child, *found;
 	struct device_node *child, *found;
 
 
-	if (node == NULL)
+	if (!node)
 		return NULL;
 		return NULL;
 
 
-	/* check */
-	if (of_node_cmp(node->full_name, full_name) == 0)
+	if (!of_node_cmp(node->full_name, full_name))
 		return of_node_get(node);
 		return of_node_get(node);
 
 
 	for_each_child_of_node(node, child) {
 	for_each_child_of_node(node, child) {
-		found = __of_find_node_by_full_name(child, full_name);
+		found = find_node_by_full_name(child, full_name);
 		if (found != NULL) {
 		if (found != NULL) {
 			of_node_put(child);
 			of_node_put(child);
 			return found;
 			return found;
@@ -51,16 +50,12 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node,
 	return NULL;
 	return NULL;
 }
 }
 
 
-/*
- * Find live tree's maximum phandle value.
- */
-static phandle of_get_tree_max_phandle(void)
+static phandle live_tree_max_phandle(void)
 {
 {
 	struct device_node *node;
 	struct device_node *node;
 	phandle phandle;
 	phandle phandle;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	/* now search recursively */
 	raw_spin_lock_irqsave(&devtree_lock, flags);
 	raw_spin_lock_irqsave(&devtree_lock, flags);
 	phandle = 0;
 	phandle = 0;
 	for_each_of_allnodes(node) {
 	for_each_of_allnodes(node) {
@@ -73,131 +68,102 @@ static phandle of_get_tree_max_phandle(void)
 	return phandle;
 	return phandle;
 }
 }
 
 
-/*
- * Adjust a subtree's phandle values by a given delta.
- * Makes sure not to just adjust the device node's phandle value,
- * but modify the phandle properties values as well.
- */
-static void __of_adjust_tree_phandles(struct device_node *node,
+static void adjust_overlay_phandles(struct device_node *overlay,
 		int phandle_delta)
 		int phandle_delta)
 {
 {
 	struct device_node *child;
 	struct device_node *child;
 	struct property *prop;
 	struct property *prop;
 	phandle phandle;
 	phandle phandle;
 
 
-	/* first adjust the node's phandle direct value */
-	if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL)
-		node->phandle += phandle_delta;
+	/* adjust node's phandle in node */
+	if (overlay->phandle != 0 && overlay->phandle != OF_PHANDLE_ILLEGAL)
+		overlay->phandle += phandle_delta;
 
 
-	/* now adjust phandle & linux,phandle values */
-	for_each_property_of_node(node, prop) {
+	/* copy adjusted phandle into *phandle properties */
+	for_each_property_of_node(overlay, prop) {
 
 
-		/* only look for these two */
-		if (of_prop_cmp(prop->name, "phandle") != 0 &&
-		    of_prop_cmp(prop->name, "linux,phandle") != 0)
+		if (of_prop_cmp(prop->name, "phandle") &&
+		    of_prop_cmp(prop->name, "linux,phandle"))
 			continue;
 			continue;
 
 
-		/* must be big enough */
 		if (prop->length < 4)
 		if (prop->length < 4)
 			continue;
 			continue;
 
 
-		/* read phandle value */
 		phandle = be32_to_cpup(prop->value);
 		phandle = be32_to_cpup(prop->value);
-		if (phandle == OF_PHANDLE_ILLEGAL)	/* unresolved */
+		if (phandle == OF_PHANDLE_ILLEGAL)
 			continue;
 			continue;
 
 
-		/* adjust */
-		*(uint32_t *)prop->value = cpu_to_be32(node->phandle);
+		*(uint32_t *)prop->value = cpu_to_be32(overlay->phandle);
 	}
 	}
 
 
-	/* now do the children recursively */
-	for_each_child_of_node(node, child)
-		__of_adjust_tree_phandles(child, phandle_delta);
+	for_each_child_of_node(overlay, child)
+		adjust_overlay_phandles(child, phandle_delta);
 }
 }
 
 
-static int __of_adjust_phandle_ref(struct device_node *node,
-		struct property *rprop, int value)
+static int update_usages_of_a_phandle_reference(struct device_node *overlay,
+		struct property *prop_fixup, phandle phandle)
 {
 {
-	phandle phandle;
 	struct device_node *refnode;
 	struct device_node *refnode;
-	struct property *sprop;
-	char *propval, *propcur, *propend, *nodestr, *propstr, *s;
-	int offset, propcurlen;
+	struct property *prop;
+	char *value, *cur, *end, *node_path, *prop_name, *s;
+	int offset, len;
 	int err = 0;
 	int err = 0;
 
 
-	/* make a copy */
-	propval = kmalloc(rprop->length, GFP_KERNEL);
-	if (!propval) {
-		pr_err("%s: Could not copy value of '%s'\n",
-				__func__, rprop->name);
+	value = kmalloc(prop_fixup->length, GFP_KERNEL);
+	if (!value)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
-	memcpy(propval, rprop->value, rprop->length);
+	memcpy(value, prop_fixup->value, prop_fixup->length);
 
 
-	propend = propval + rprop->length;
-	for (propcur = propval; propcur < propend; propcur += propcurlen + 1) {
-		propcurlen = strlen(propcur);
+	/* prop_fixup contains a list of tuples of path:property_name:offset */
+	end = value + prop_fixup->length;
+	for (cur = value; cur < end; cur += len + 1) {
+		len = strlen(cur);
 
 
-		nodestr = propcur;
-		s = strchr(propcur, ':');
+		node_path = cur;
+		s = strchr(cur, ':');
 		if (!s) {
 		if (!s) {
-			pr_err("%s: Illegal symbol entry '%s' (1)\n",
-				__func__, propcur);
 			err = -EINVAL;
 			err = -EINVAL;
 			goto err_fail;
 			goto err_fail;
 		}
 		}
 		*s++ = '\0';
 		*s++ = '\0';
 
 
-		propstr = s;
+		prop_name = s;
 		s = strchr(s, ':');
 		s = strchr(s, ':');
 		if (!s) {
 		if (!s) {
-			pr_err("%s: Illegal symbol entry '%s' (2)\n",
-				__func__, (char *)rprop->value);
 			err = -EINVAL;
 			err = -EINVAL;
 			goto err_fail;
 			goto err_fail;
 		}
 		}
-
 		*s++ = '\0';
 		*s++ = '\0';
+
 		err = kstrtoint(s, 10, &offset);
 		err = kstrtoint(s, 10, &offset);
-		if (err != 0) {
-			pr_err("%s: Could get offset '%s'\n",
-				__func__, (char *)rprop->value);
+		if (err)
 			goto err_fail;
 			goto err_fail;
-		}
 
 
-		/* look into the resolve node for the full path */
-		refnode = __of_find_node_by_full_name(node, nodestr);
-		if (!refnode) {
-			pr_warn("%s: Could not find refnode '%s'\n",
-				__func__, (char *)rprop->value);
+		refnode = find_node_by_full_name(overlay, node_path);
+		if (!refnode)
 			continue;
 			continue;
-		}
 
 
-		/* now find the property */
-		for_each_property_of_node(refnode, sprop) {
-			if (of_prop_cmp(sprop->name, propstr) == 0)
+		for_each_property_of_node(refnode, prop) {
+			if (!of_prop_cmp(prop->name, prop_name))
 				break;
 				break;
 		}
 		}
 		of_node_put(refnode);
 		of_node_put(refnode);
 
 
-		if (!sprop) {
-			pr_err("%s: Could not find property '%s'\n",
-				__func__, (char *)rprop->value);
+		if (!prop) {
 			err = -ENOENT;
 			err = -ENOENT;
 			goto err_fail;
 			goto err_fail;
 		}
 		}
 
 
-		phandle = value;
-		*(__be32 *)(sprop->value + offset) = cpu_to_be32(phandle);
+		*(__be32 *)(prop->value + offset) = cpu_to_be32(phandle);
 	}
 	}
 
 
 err_fail:
 err_fail:
-	kfree(propval);
+	kfree(value);
 	return err;
 	return err;
 }
 }
 
 
 /* compare nodes taking into account that 'name' strips out the @ part */
 /* compare nodes taking into account that 'name' strips out the @ part */
-static int __of_node_name_cmp(const struct device_node *dn1,
+static int node_name_cmp(const struct device_node *dn1,
 		const struct device_node *dn2)
 		const struct device_node *dn2)
 {
 {
 	const char *n1 = strrchr(dn1->full_name, '/') ? : "/";
 	const char *n1 = strrchr(dn1->full_name, '/') ? : "/";
@@ -208,85 +174,77 @@ static int __of_node_name_cmp(const struct device_node *dn1,
 
 
 /*
 /*
  * Adjust the local phandle references by the given phandle delta.
  * Adjust the local phandle references by the given phandle delta.
- * Assumes the existances of a __local_fixups__ node at the root.
- * Assumes that __of_verify_tree_phandle_references has been called.
- * Does not take any devtree locks so make sure you call this on a tree
- * which is at the detached state.
+ *
+ * Subtree @local_fixups, which is overlay node __local_fixups__,
+ * mirrors the fragment node structure at the root of the overlay.
+ *
+ * For each property in the fragments that contains a phandle reference,
+ * @local_fixups has a property of the same name that contains a list
+ * of offsets of the phandle reference(s) within the respective property
+ * value(s).  The values at these offsets will be fixed up.
  */
  */
-static int __of_adjust_tree_phandle_references(struct device_node *node,
-		struct device_node *target, int phandle_delta)
+static int adjust_local_phandle_references(struct device_node *local_fixups,
+		struct device_node *overlay, int phandle_delta)
 {
 {
-	struct device_node *child, *childtarget;
-	struct property *rprop, *sprop;
+	struct device_node *child, *overlay_child;
+	struct property *prop_fix, *prop;
 	int err, i, count;
 	int err, i, count;
 	unsigned int off;
 	unsigned int off;
 	phandle phandle;
 	phandle phandle;
 
 
-	if (node == NULL)
+	if (!local_fixups)
 		return 0;
 		return 0;
 
 
-	for_each_property_of_node(node, rprop) {
+	for_each_property_of_node(local_fixups, prop_fix) {
 
 
 		/* skip properties added automatically */
 		/* skip properties added automatically */
-		if (of_prop_cmp(rprop->name, "name") == 0 ||
-		    of_prop_cmp(rprop->name, "phandle") == 0 ||
-		    of_prop_cmp(rprop->name, "linux,phandle") == 0)
+		if (!of_prop_cmp(prop_fix->name, "name") ||
+		    !of_prop_cmp(prop_fix->name, "phandle") ||
+		    !of_prop_cmp(prop_fix->name, "linux,phandle"))
 			continue;
 			continue;
 
 
-		if ((rprop->length % 4) != 0 || rprop->length == 0) {
-			pr_err("%s: Illegal property (size) '%s' @%s\n",
-					__func__, rprop->name, node->full_name);
+		if ((prop_fix->length % 4) != 0 || prop_fix->length == 0)
 			return -EINVAL;
 			return -EINVAL;
-		}
-		count = rprop->length / sizeof(__be32);
+		count = prop_fix->length / sizeof(__be32);
 
 
-		/* now find the target property */
-		for_each_property_of_node(target, sprop) {
-			if (of_prop_cmp(sprop->name, rprop->name) == 0)
+		for_each_property_of_node(overlay, prop) {
+			if (!of_prop_cmp(prop->name, prop_fix->name))
 				break;
 				break;
 		}
 		}
 
 
-		if (sprop == NULL) {
-			pr_err("%s: Could not find target property '%s' @%s\n",
-					__func__, rprop->name, node->full_name);
+		if (!prop)
 			return -EINVAL;
 			return -EINVAL;
-		}
 
 
 		for (i = 0; i < count; i++) {
 		for (i = 0; i < count; i++) {
-			off = be32_to_cpu(((__be32 *)rprop->value)[i]);
-			/* make sure the offset doesn't overstep (even wrap) */
-			if (off >= sprop->length ||
-					(off + 4) > sprop->length) {
-				pr_err("%s: Illegal property '%s' @%s\n",
-						__func__, rprop->name,
-						node->full_name);
+			off = be32_to_cpu(((__be32 *)prop_fix->value)[i]);
+			if ((off + 4) > prop->length)
 				return -EINVAL;
 				return -EINVAL;
-			}
-
-			if (phandle_delta) {
-				/* adjust */
-				phandle = be32_to_cpu(*(__be32 *)(sprop->value + off));
-				phandle += phandle_delta;
-				*(__be32 *)(sprop->value + off) = cpu_to_be32(phandle);
-			}
+
+			phandle = be32_to_cpu(*(__be32 *)(prop->value + off));
+			phandle += phandle_delta;
+			*(__be32 *)(prop->value + off) = cpu_to_be32(phandle);
 		}
 		}
 	}
 	}
 
 
-	for_each_child_of_node(node, child) {
-
-		for_each_child_of_node(target, childtarget)
-			if (__of_node_name_cmp(child, childtarget) == 0)
+	/*
+	 * These nested loops recurse down two subtrees in parallel, where the
+	 * node names in the two subtrees match.
+	 *
+	 * The roots of the subtrees are the overlay's __local_fixups__ node
+	 * and the overlay's root node.
+	 */
+	for_each_child_of_node(local_fixups, child) {
+
+		for_each_child_of_node(overlay, overlay_child)
+			if (!node_name_cmp(child, overlay_child))
 				break;
 				break;
 
 
-		if (!childtarget) {
-			pr_err("%s: Could not find target child '%s' @%s\n",
-					__func__, child->name, node->full_name);
+		if (!overlay_child)
 			return -EINVAL;
 			return -EINVAL;
-		}
 
 
-		err = __of_adjust_tree_phandle_references(child, childtarget,
+		err = adjust_local_phandle_references(child, overlay_child,
 				phandle_delta);
 				phandle_delta);
-		if (err != 0)
+		if (err)
 			return err;
 			return err;
 	}
 	}
 
 
@@ -294,111 +252,103 @@ static int __of_adjust_tree_phandle_references(struct device_node *node,
 }
 }
 
 
 /**
 /**
- * of_resolve	- Resolve the given node against the live tree.
+ * of_resolve_phandles - Relocate and resolve overlay against live tree
  *
  *
- * @resolve:	Node to resolve
+ * @overlay:	Pointer to devicetree overlay to relocate and resolve
  *
  *
- * Perform dynamic Device Tree resolution against the live tree
- * to the given node to resolve. This depends on the live tree
- * having a __symbols__ node, and the resolve node the __fixups__ &
- * __local_fixups__ nodes (if needed).
- * The result of the operation is a resolve node that it's contents
- * are fit to be inserted or operate upon the live tree.
- * Returns 0 on success or a negative error value on error.
+ * Modify (relocate) values of local phandles in @overlay to a range that
+ * does not conflict with the live expanded devicetree.  Update references
+ * to the local phandles in @overlay.  Update (resolve) phandle references
+ * in @overlay that refer to the live expanded devicetree.
+ *
+ * Phandle values in the live tree are in the range of
+ * 1 .. live_tree_max_phandle().  The range of phandle values in the overlay
+ * also begin with at 1.  Adjust the phandle values in the overlay to begin
+ * at live_tree_max_phandle() + 1.  Update references to the phandles to
+ * the adjusted phandle values.
+ *
+ * The name of each property in the "__fixups__" node in the overlay matches
+ * the name of a symbol (a label) in the live tree.  The values of each
+ * property in the "__fixups__" node is a list of the property values in the
+ * overlay that need to be updated to contain the phandle reference
+ * corresponding to that symbol in the live tree.  Update the references in
+ * the overlay with the phandle values in the live tree.
+ *
+ * @overlay must be detached.
+ *
+ * Resolving and applying @overlay to the live expanded devicetree must be
+ * protected by a mechanism to ensure that multiple overlays are processed
+ * in a single threaded manner so that multiple overlays will not relocate
+ * phandles to overlapping ranges.  The mechanism to enforce this is not
+ * yet implemented.
+ *
+ * Return: %0 on success or a negative error value on error.
  */
  */
-int of_resolve_phandles(struct device_node *resolve)
+int of_resolve_phandles(struct device_node *overlay)
 {
 {
-	struct device_node *child, *childroot, *refnode;
-	struct device_node *root_sym, *resolve_sym, *resolve_fix;
-	struct property *rprop;
+	struct device_node *child, *local_fixups, *refnode;
+	struct device_node *tree_symbols, *overlay_fixups;
+	struct property *prop;
 	const char *refpath;
 	const char *refpath;
 	phandle phandle, phandle_delta;
 	phandle phandle, phandle_delta;
 	int err;
 	int err;
 
 
-	if (!resolve)
-		pr_err("%s: null node\n", __func__);
-	if (resolve && !of_node_check_flag(resolve, OF_DETACHED))
-		pr_err("%s: node %s not detached\n", __func__,
-			 resolve->full_name);
-	/* the resolve node must exist, and be detached */
-	if (!resolve || !of_node_check_flag(resolve, OF_DETACHED))
-		return -EINVAL;
-
-	/* first we need to adjust the phandles */
-	phandle_delta = of_get_tree_max_phandle() + 1;
-	__of_adjust_tree_phandles(resolve, phandle_delta);
-
-	/* locate the local fixups */
-	childroot = NULL;
-	for_each_child_of_node(resolve, childroot)
-		if (of_node_cmp(childroot->name, "__local_fixups__") == 0)
-			break;
-
-	if (childroot != NULL) {
-		/* resolve root is guaranteed to be the '/' */
-		err = __of_adjust_tree_phandle_references(childroot,
-				resolve, 0);
-		if (err != 0)
-			return err;
+	tree_symbols = NULL;
 
 
-		BUG_ON(__of_adjust_tree_phandle_references(childroot,
-				resolve, phandle_delta));
+	if (!overlay) {
+		pr_err("null overlay\n");
+		err = -EINVAL;
+		goto out;
+	}
+	if (!of_node_check_flag(overlay, OF_DETACHED)) {
+		pr_err("overlay not detached\n");
+		err = -EINVAL;
+		goto out;
 	}
 	}
 
 
-	root_sym = NULL;
-	resolve_sym = NULL;
-	resolve_fix = NULL;
-
-	/* this may fail (if no fixups are required) */
-	root_sym = of_find_node_by_path("/__symbols__");
+	phandle_delta = live_tree_max_phandle() + 1;
+	adjust_overlay_phandles(overlay, phandle_delta);
 
 
-	/* locate the symbols & fixups nodes on resolve */
-	for_each_child_of_node(resolve, child) {
+	for_each_child_of_node(overlay, local_fixups)
+		if (!of_node_cmp(local_fixups->name, "__local_fixups__"))
+			break;
 
 
-		if (!resolve_sym &&
-				of_node_cmp(child->name, "__symbols__") == 0)
-			resolve_sym = child;
+	err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
+	if (err)
+		goto out;
 
 
-		if (!resolve_fix &&
-				of_node_cmp(child->name, "__fixups__") == 0)
-			resolve_fix = child;
+	overlay_fixups = NULL;
 
 
-		/* both found, don't bother anymore */
-		if (resolve_sym && resolve_fix)
-			break;
+	for_each_child_of_node(overlay, child) {
+		if (!of_node_cmp(child->name, "__fixups__"))
+			overlay_fixups = child;
 	}
 	}
 
 
-	/* we do allow for the case where no fixups are needed */
-	if (!resolve_fix) {
-		err = 0;	/* no error */
+	if (!overlay_fixups) {
+		err = 0;
 		goto out;
 		goto out;
 	}
 	}
 
 
-	/* we need to fixup, but no root symbols... */
-	if (!root_sym) {
-		pr_err("%s: no symbols in root of device tree.\n", __func__);
+	tree_symbols = of_find_node_by_path("/__symbols__");
+	if (!tree_symbols) {
+		pr_err("no symbols in root of device tree.\n");
 		err = -EINVAL;
 		err = -EINVAL;
 		goto out;
 		goto out;
 	}
 	}
 
 
-	for_each_property_of_node(resolve_fix, rprop) {
+	for_each_property_of_node(overlay_fixups, prop) {
 
 
 		/* skip properties added automatically */
 		/* skip properties added automatically */
-		if (of_prop_cmp(rprop->name, "name") == 0)
+		if (!of_prop_cmp(prop->name, "name"))
 			continue;
 			continue;
 
 
-		err = of_property_read_string(root_sym,
-				rprop->name, &refpath);
-		if (err != 0) {
-			pr_err("%s: Could not find symbol '%s'\n",
-					__func__, rprop->name);
+		err = of_property_read_string(tree_symbols,
+				prop->name, &refpath);
+		if (err)
 			goto out;
 			goto out;
-		}
 
 
 		refnode = of_find_node_by_path(refpath);
 		refnode = of_find_node_by_path(refpath);
 		if (!refnode) {
 		if (!refnode) {
-			pr_err("%s: Could not find node by path '%s'\n",
-					__func__, refpath);
 			err = -ENOENT;
 			err = -ENOENT;
 			goto out;
 			goto out;
 		}
 		}
@@ -406,17 +356,15 @@ int of_resolve_phandles(struct device_node *resolve)
 		phandle = refnode->phandle;
 		phandle = refnode->phandle;
 		of_node_put(refnode);
 		of_node_put(refnode);
 
 
-		pr_debug("%s: %s phandle is 0x%08x\n",
-				__func__, rprop->name, phandle);
-
-		err = __of_adjust_phandle_ref(resolve, rprop, phandle);
+		err = update_usages_of_a_phandle_reference(overlay, prop, phandle);
 		if (err)
 		if (err)
 			break;
 			break;
 	}
 	}
 
 
 out:
 out:
-	/* NULL is handled by of_node_put as NOP */
-	of_node_put(root_sym);
+	if (err)
+		pr_err("overlay phandle fixup failed: %d\n", err);
+	of_node_put(tree_symbols);
 
 
 	return err;
 	return err;
 }
 }