Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx

* 'master' of git://git.denx.de/u-boot-mpc85xx:
  powerpc/p2041rdb: Add p2041rdb board support
  powerpc/85xx: Fix detection of P1017E
  powerpc/mpc8548cds: Remove incorrect DDR_MSYNC_IN erratum define
diff --git a/README b/README
index 1e2d4d3..6a601d2 100644
--- a/README
+++ b/README
@@ -3305,6 +3305,15 @@
 		  This can be used to load and uncompress arbitrary
 		  data.
 
+  fdt_high	- if set this restricts the maximum address that the
+		  flattened device tree will be copied into upon boot.
+		  If this is set to the special value 0xFFFFFFFF then
+		  the fdt will not be copied at all on boot.  For this
+		  to work it must reside in writable memory, have
+		  sufficient padding on the end of it for u-boot to
+		  add the information it needs into it, and the memory
+		  must be accessible by the kernel.
+
   i2cfast	- (PPC405GP|PPC405EP only)
 		  if set to 'y' configures Linux I2C driver for fast
 		  mode (400kHZ). This environment variable is used in
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 496040b..19b2ef6 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1195,6 +1195,46 @@
 	return phandle + 1;
 }
 
+/*
+ * fdt_create_phandle: Create a phandle property for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ * @phandle: phandle value to set (must be unique)
+*/
+int fdt_create_phandle(void *fdt, int nodeoffset, uint32_t phandle)
+{
+	int ret;
+
+#ifdef DEBUG
+	int off = fdt_node_offset_by_phandle(fdt, phandle);
+
+	if ((off >= 0) && (off != nodeoffset)) {
+		char buf[64];
+
+		fdt_get_path(fdt, nodeoffset, buf, sizeof(buf));
+		printf("Trying to update node %s with phandle %u ",
+		       buf, phandle);
+
+		fdt_get_path(fdt, off, buf, sizeof(buf));
+		printf("that already exists in node %s.\n", buf);
+		return -FDT_ERR_BADPHANDLE;
+	}
+#endif
+
+	ret = fdt_setprop_cell(fdt, nodeoffset, "phandle", phandle);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * For now, also set the deprecated "linux,phandle" property, so that we
+	 * don't break older kernels.
+	 */
+	ret = fdt_setprop_cell(fdt, nodeoffset, "linux,phandle", phandle);
+
+	return ret;
+}
+
 #if defined(CONFIG_VIDEO)
 int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
 {
@@ -1223,3 +1263,70 @@
 	return ret;
 }
 #endif
+
+/*
+ * Verify the physical address of device tree node for a given alias
+ *
+ * This function locates the device tree node of a given alias, and then
+ * verifies that the physical address of that device matches the given
+ * parameter.  It displays a message if there is a mismatch.
+ *
+ * Returns 1 on success, 0 on failure
+ */
+int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr)
+{
+	const char *path;
+	const u32 *reg;
+	int node, len;
+	u64 dt_addr;
+
+	path = fdt_getprop(fdt, anode, alias, NULL);
+	if (!path) {
+		/* If there's no such alias, then it's not a failure */
+		return 1;
+	}
+
+	node = fdt_path_offset(fdt, path);
+	if (node < 0) {
+		printf("Warning: device tree alias '%s' points to invalid "
+		       "node %s.\n", alias, path);
+		return 0;
+	}
+
+	reg = fdt_getprop(fdt, node, "reg", &len);
+	if (!reg) {
+		printf("Warning: device tree node '%s' has no address.\n",
+		       path);
+		return 0;
+	}
+
+	dt_addr = fdt_translate_address(fdt, node, reg);
+	if (addr != dt_addr) {
+		printf("Warning: U-Boot configured device %s at address %llx,\n"
+		       " but the device tree has it address %llx.\n",
+		       alias, addr, dt_addr);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Returns the base address of an SOC or PCI node
+ */
+u64 fdt_get_base_address(void *fdt, int node)
+{
+	int size;
+	u32 naddr;
+	const u32 *prop;
+
+	prop = fdt_getprop(fdt, node, "#address-cells", &size);
+	if (prop && size == 4)
+		naddr = *prop;
+	else
+		naddr = 2;
+
+	prop = fdt_getprop(fdt, node, "ranges", &size);
+
+	return prop ? fdt_translate_address(fdt, node, prop + naddr) : 0;
+}
diff --git a/common/image.c b/common/image.c
index e542a57..c6cd85e 100644
--- a/common/image.c
+++ b/common/image.c
@@ -1234,8 +1234,10 @@
 {
 	void	*fdt_blob = *of_flat_tree;
 	void	*of_start = 0;
+	char	*fdt_high;
 	ulong	of_len = 0;
 	int	err;
+	int	disable_relocation = 0;
 
 	/* nothing to do */
 	if (*of_size == 0)
@@ -1249,26 +1251,62 @@
 	/* position on a 4K boundary before the alloc_current */
 	/* Pad the FDT by a specified amount */
 	of_len = *of_size + CONFIG_SYS_FDT_PAD;
-	of_start = (void *)(unsigned long)lmb_alloc_base(lmb, of_len, 0x1000,
-			getenv_bootm_mapsize() + getenv_bootm_low());
+
+	/* If fdt_high is set use it to select the relocation address */
+	fdt_high = getenv("fdt_high");
+	if (fdt_high) {
+		void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16);
+
+		if (((ulong) desired_addr) == ~0UL) {
+			/* All ones means use fdt in place */
+			desired_addr = fdt_blob;
+			disable_relocation = 1;
+		}
+		if (desired_addr) {
+			of_start =
+			    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
+							   ((ulong)
+							    desired_addr)
+							   + of_len);
+			if (desired_addr && of_start != desired_addr) {
+				puts("Failed using fdt_high value for Device Tree");
+				goto error;
+			}
+		} else {
+			of_start =
+			    (void *)(ulong) mb_alloc(lmb, of_len, 0x1000);
+		}
+	} else {
+		of_start =
+		    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
+						   getenv_bootm_mapsize()
+						   + getenv_bootm_low());
+	}
 
 	if (of_start == 0) {
 		puts("device tree - allocation error\n");
 		goto error;
 	}
 
-	debug ("## device tree at %p ... %p (len=%ld [0x%lX])\n",
-		fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
+	if (disable_relocation) {
+		/* We assume there is space after the existing fdt to use for padding */
+		fdt_set_totalsize(of_start, of_len);
+		printf("   Using Device Tree in place at %p, end %p\n",
+		       of_start, of_start + of_len - 1);
+	} else {
+		debug ("## device tree at %p ... %p (len=%ld [0x%lX])\n",
+			fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
 
-	printf ("   Loading Device Tree to %p, end %p ... ",
-		of_start, of_start + of_len - 1);
+		printf ("   Loading Device Tree to %p, end %p ... ",
+			of_start, of_start + of_len - 1);
 
-	err = fdt_open_into (fdt_blob, of_start, of_len);
-	if (err != 0) {
-		fdt_error ("fdt move failed");
-		goto error;
+		err = fdt_open_into (fdt_blob, of_start, of_len);
+		if (err != 0) {
+			fdt_error ("fdt move failed");
+			goto error;
+		}
+		puts ("OK\n");
 	}
-	puts ("OK\n");
 
 	*of_flat_tree = of_start;
 	*of_size = of_len;
diff --git a/include/fdt_support.h b/include/fdt_support.h
index ce6817b..863024f 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -79,6 +79,7 @@
 
 void set_working_fdt_addr(void *addr);
 int fdt_resize(void *blob);
+int fdt_increase_size(void *fdt, int add_len);
 
 int fdt_fixup_nor_flash_size(void *blob);
 
@@ -88,7 +89,12 @@
 int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 					phys_addr_t compat_off);
 int fdt_alloc_phandle(void *blob);
+int fdt_create_phandle(void *fdt, int nodeoffset, uint32_t phandle);
 int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
 
+int fdt_verify_alias_address(void *fdt, int anode, const char *alias,
+			      u64 addr);
+u64 fdt_get_base_address(void *fdt, int node);
+
 #endif /* ifdef CONFIG_OF_LIBFDT */
 #endif /* ifndef __FDT_SUPPORT_H */
diff --git a/include/libfdt.h b/include/libfdt.h
index d23d40e..de82ed5 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -343,6 +343,75 @@
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
 
 /**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ *	structure block offset of the property (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested node has no properties
+ *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset.  This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ *	structure block offset of the next property (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the given property is the last in its node
+ *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset.  If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the structure representing the property
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp);
+
+/**
  * fdt_get_property_namelen - find a property based on substring
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to find
@@ -396,6 +465,40 @@
 }
 
 /**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value).  If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.  If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ *	pointer to the property's value
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *		if namep is non-NULL *namep contiains a pointer to the property
+ *		name.
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+				  const char **namep, int *lenp);
+
+/**
  * fdt_getprop_namelen - get property value based on substring
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to find
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index b09ea6f..4157b21 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -153,6 +153,15 @@
 	return offset;
 }
 
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+	if ((offset < 0) || (offset % FDT_TAGSIZE)
+	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+		return -FDT_ERR_BADOFFSET;
+
+	return offset;
+}
+
 int fdt_next_node(const void *fdt, int offset, int *depth)
 {
 	int nextoffset = 0;
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 1e1e322..1933010 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -109,6 +109,30 @@
 	return i;
 }
 
+static int _nextprop(const void *fdt, int offset)
+{
+	uint32_t tag;
+	int nextoffset;
+
+	do {
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_END:
+			if (nextoffset >= 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			else
+				return nextoffset;
+
+		case FDT_PROP:
+			return offset;
+		}
+		offset = nextoffset;
+	} while (tag == FDT_NOP);
+
+	return -FDT_ERR_NOTFOUND;
+}
+
 int fdt_subnode_offset_namelen(const void *fdt, int offset,
 			       const char *name, int namelen)
 {
@@ -198,52 +222,66 @@
 	return NULL;
 }
 
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
-						    int nodeoffset,
-						    const char *name,
-						    int namelen, int *lenp)
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
 {
-	uint32_t tag;
-	const struct fdt_property *prop;
-	int offset, nextoffset;
+	int offset;
+
+	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+		return offset;
+
+	return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+		return offset;
+
+	return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp)
+{
 	int err;
+	const struct fdt_property *prop;
 
-	if (((err = fdt_check_header(fdt)) != 0)
-	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
-			goto fail;
+	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+		if (lenp)
+			*lenp = err;
+		return NULL;
+	}
 
-	nextoffset = err;
-	do {
-		offset = nextoffset;
+	prop = _fdt_offset_ptr(fdt, offset);
 
-		tag = fdt_next_tag(fdt, offset, &nextoffset);
-		switch (tag) {
-		case FDT_END:
-			if (nextoffset < 0)
-				err = nextoffset;
-			else
-				/* FDT_END tag with unclosed nodes */
-				err = -FDT_ERR_BADSTRUCTURE;
-			goto fail;
+	if (lenp)
+		*lenp = fdt32_to_cpu(prop->len);
 
-		case FDT_PROP:
-			prop = _fdt_offset_ptr(fdt, offset);
-			if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
-					   name, namelen)) {
-				/* Found it! */
-				if (lenp)
-					*lenp = fdt32_to_cpu(prop->len);
+	return prop;
+}
 
-				return prop;
-			}
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int offset,
+						    const char *name,
+						    int namelen, int *lenp)
+{
+	for (offset = fdt_first_property_offset(fdt, offset);
+	     (offset >= 0);
+	     (offset = fdt_next_property_offset(fdt, offset))) {
+		const struct fdt_property *prop;
+
+		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+			offset = -FDT_ERR_INTERNAL;
 			break;
 		}
-	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+				   name, namelen))
+			return prop;
+	}
 
-	err = -FDT_ERR_NOTFOUND;
- fail:
 	if (lenp)
-		*lenp = err;
+		*lenp = offset;
 	return NULL;
 }
 
@@ -264,6 +302,19 @@
 	if (! prop)
 		return NULL;
 
+	return prop->data;
+}
+
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+				  const char **namep, int *lenp)
+{
+	const struct fdt_property *prop;
+
+	prop = fdt_get_property_by_offset(fdt, offset, lenp);
+	if (!prop)
+		return NULL;
+	if (namep)
+		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
 	return prop->data;
 }
 
@@ -278,9 +329,14 @@
 	const uint32_t *php;
 	int len;
 
-	php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
-	if (!php || (len != sizeof(*php)))
-		return 0;
+	/* FIXME: This is a bit sub-optimal, since we potentially scan
+	 * over all the properties twice. */
+	php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+	if (!php || (len != sizeof(*php))) {
+		php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+		if (!php || (len != sizeof(*php)))
+			return 0;
+	}
 
 	return fdt32_to_cpu(*php);
 }
@@ -440,11 +496,27 @@
 
 int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 {
+	int offset;
+
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
-	phandle = cpu_to_fdt32(phandle);
-	return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
-					     &phandle, sizeof(phandle));
+
+	FDT_CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we
+	 * potentially scan each property of a node in
+	 * fdt_get_phandle(), then if that didn't find what
+	 * we want, we scan over them again making our way to the next
+	 * node.  Still it's the easiest to implement approach;
+	 * performance can come later. */
+	for (offset = fdt_next_node(fdt, -1, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		if (fdt_get_phandle(fdt, offset) == phandle)
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
 }
 
 static int _fdt_stringlist_contains(const char *strlist, int listlen,
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index d2dcbd6..381133b 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -63,6 +63,7 @@
 	}
 
 int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
 int _fdt_node_end_offset(void *fdt, int nodeoffset);