public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/6] fdt_support: Add helper function to read "ranges" property
Date: Fri, 11 Apr 2014 17:09:41 +0200	[thread overview]
Message-ID: <1397228985-17740-3-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1397228985-17740-1-git-send-email-agraf@suse.de>

This patch adds a helper function that can be used to interpret most
"ranges" properties in the device tree.

It reads the n'th range out of a "ranges" array and returns the node's
virtual address of the range, the physical address that range starts at
and the size of the range.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 common/fdt_support.c  |   94 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fdt_support.h |    2 ++
 2 files changed, 96 insertions(+)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index cc0bf76..fcd2523 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1435,3 +1435,97 @@ u64 fdt_get_base_address(void *fdt, int node)
 
 	return prop ? fdt_translate_address(fdt, node, prop + naddr) : 0;
 }
+
+/*
+ * Read a property of size <prop_len>. Currently only supports 1 or 2 cells.
+ */
+static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off,
+			 uint64_t *val, int cells)
+{
+	const fdt32_t *prop32 = &prop[cell_off];
+	const fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off];
+
+	if ((cell_off + cells) > prop_len)
+		return -FDT_ERR_NOSPACE;
+
+	switch (cells) {
+	case 1:
+		*val = fdt32_to_cpu(*prop32);
+		break;
+	case 2:
+		*val = fdt64_to_cpu(*prop64);
+		break;
+	default:
+		return -FDT_ERR_NOSPACE;
+	}
+
+	return 0;
+}
+
+/**
+ * fdt_read_range - Read a node's n'th range property
+ *
+ * @fdt: ptr to device tree
+ * @node: offset of node
+ * @n: range index
+ * @child_addr: pointer to storage for the "child address" field
+ * @addr: pointer to storage for the CPU view translated physical start
+ * @len: pointer to storage for the range length
+ *
+ * Convenience function that reads and interprets a specific range out of
+ * a number of the "ranges" property array.
+ */
+int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr,
+		   uint64_t *addr, uint64_t *len)
+{
+	int pnode = fdt_parent_offset(fdt, node);
+	const fdt32_t *ranges;
+	int pacells;
+	int acells;
+	int scells;
+	int ranges_len;
+	int cell = 0;
+	int r = 0;
+
+	/*
+	 * The "ranges" property is an array of
+	 * { <child address> <parent address> <size in child address space> }
+	 *
+	 * All 3 elements can span a diffent number of cells. Fetch their size.
+	 */
+	pacells = fdt_getprop_u32_default_node(fdt, pnode, 0, "#address-cells", 1);
+	acells = fdt_getprop_u32_default_node(fdt, node, 0, "#address-cells", 1);
+	scells = fdt_getprop_u32_default_node(fdt, node, 0, "#size-cells", 1);
+
+	/* Now try to get the ranges property */
+	ranges = fdt_getprop(fdt, node, "ranges", &ranges_len);
+	if (!ranges)
+		return -FDT_ERR_NOTFOUND;
+	ranges_len /= sizeof(uint32_t);
+
+	/* Jump to the n'th entry */
+	cell = n * (pacells + acells + scells);
+
+	/* Read <child address> */
+	if (child_addr) {
+		r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
+				  acells);
+		if (r)
+			return r;
+	}
+	cell += acells;
+
+	/* Read <parent address> */
+	if (addr)
+		*addr = fdt_translate_address(fdt, node, ranges + cell);
+	cell += pacells;
+
+	/* Read <size in child address space> */
+	if (len) {
+		r = fdt_read_prop(ranges, ranges_len, cell, len, scells);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 3e1be57..b28fae6 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -87,6 +87,8 @@ 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);
+int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr,
+		   uint64_t *addr, uint64_t *len);
 
 enum fdt_status {
 	FDT_STATUS_OKAY,
-- 
1.7.10.4

  parent reply	other threads:[~2014-04-11 15:09 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-11 15:09 [U-Boot] [PATCH v5 0/6] PPC 85xx: Add support for QEMU's ppce500 PV machine Alexander Graf
2014-04-11 15:09 ` [U-Boot] [PATCH 1/6] fdt_support: split fdt_getprop_u32_default Alexander Graf
2014-04-11 15:09 ` Alexander Graf [this message]
2014-04-11 15:09 ` [U-Boot] [PATCH 3/6] PPC: 85xx: Remove IVOR reset Alexander Graf
2014-04-17  0:46   ` York Sun
2014-04-17  7:16     ` Alexander Graf
2014-04-11 15:09 ` [U-Boot] [PATCH 4/6] PPC: 85xx: Generalize DDR TLB mapping function Alexander Graf
2014-04-11 15:09 ` [U-Boot] [PATCH 5/6] PPC 85xx: Add ELF entry point Alexander Graf
2014-04-11 15:09 ` [U-Boot] [PATCH 6/6] PPC 85xx: Add qemu-ppce500 machine Alexander Graf
2014-04-11 23:18 ` [U-Boot] [PATCH v5 0/6] PPC 85xx: Add support for QEMU's ppce500 PV machine Scott Wood
2014-04-23 21:46 ` York Sun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1397228985-17740-3-git-send-email-agraf@suse.de \
    --to=agraf@suse.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox