summary refs log tree commit diff
path: root/drivers/of
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2009-11-23 18:54:23 -0700
committerGrant Likely <grant.likely@secretlab.ca>2009-11-23 18:54:23 -0700
commitc8cb7a59842c0b512b44f6f818cdb0b5a3ddc89e (patch)
tree74d7b5c8dac3d5167b0394b5967bad52681dc28e /drivers/of
parente169cfbef46d62e042614ffafa8880eed1d894bb (diff)
downloadlinux-c8cb7a59842c0b512b44f6f818cdb0b5a3ddc89e.tar.gz
of/flattree: merge of_scan_flat_dt
Merge common code between PowerPC and Microblaze

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
Tested-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/fdt.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 9faa9a5cbdf0..dd9057cb7aa7 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -19,3 +19,67 @@ char *find_flat_dt_string(u32 offset)
 	return ((char *)initial_boot_params) +
 		initial_boot_params->off_dt_strings + offset;
 }
+
+/**
+ * of_scan_flat_dt - scan flattened tree blob and call callback on each.
+ * @it: callback function
+ * @data: context data pointer
+ *
+ * This function is used to scan the flattened device-tree, it is
+ * used to extract the memory information at boot before we can
+ * unflatten the tree
+ */
+int __init of_scan_flat_dt(int (*it)(unsigned long node,
+				     const char *uname, int depth,
+				     void *data),
+			   void *data)
+{
+	unsigned long p = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	int rc = 0;
+	int depth = -1;
+
+	do {
+		u32 tag = *((u32 *)p);
+		char *pathp;
+
+		p += 4;
+		if (tag == OF_DT_END_NODE) {
+			depth--;
+			continue;
+		}
+		if (tag == OF_DT_NOP)
+			continue;
+		if (tag == OF_DT_END)
+			break;
+		if (tag == OF_DT_PROP) {
+			u32 sz = *((u32 *)p);
+			p += 8;
+			if (initial_boot_params->version < 0x10)
+				p = _ALIGN(p, sz >= 8 ? 8 : 4);
+			p += sz;
+			p = _ALIGN(p, 4);
+			continue;
+		}
+		if (tag != OF_DT_BEGIN_NODE) {
+			pr_err("Invalid tag %x in flat device tree!\n", tag);
+			return -EINVAL;
+		}
+		depth++;
+		pathp = (char *)p;
+		p = _ALIGN(p + strlen(pathp) + 1, 4);
+		if ((*pathp) == '/') {
+			char *lp, *np;
+			for (lp = NULL, np = pathp; *np; np++)
+				if ((*np) == '/')
+					lp = np+1;
+			if (lp != NULL)
+				pathp = lp;
+		}
+		rc = it(p, pathp, depth, data);
+		if (rc != 0)
+			break;
+	} while (1);
+
+	return rc;
+}