All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr
@ 2010-07-04 18:18 Kumar Gala
  2010-07-04 18:18 ` [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper Kumar Gala
  2010-07-17 15:49 ` [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
  0 siblings, 2 replies; 8+ messages in thread
From: Kumar Gala @ 2010-07-04 18:18 UTC (permalink / raw)
  To: u-boot

This code is extracted out of the Linux Kernel code from
arch/powerpc/kernel/prom_parse.c.

We maintain some of the same structure to support multiple bus types even
though we only have one in the current code.  In the future we might want
to translate across a PCI bus and thus it will be easier to add that
functionality back in.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 common/fdt_support.c  |  264 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fdt_support.h |    1 +
 2 files changed, 265 insertions(+), 0 deletions(-)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 4d87135..70ad81d 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -2,6 +2,8 @@
  * (C) Copyright 2007
  * Gerald Van Baren, Custom IDEAS, vanbaren at cideas.com
  *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -861,3 +863,265 @@ void fdt_del_node_and_alias(void *blob, const char *alias)
 	off = fdt_path_offset(blob, "/aliases");
 	fdt_delprop(blob, off, alias);
 }
+
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 of_read_number(const __be32 *cell, int size)
+{
+	u64 r = 0;
+	while (size--)
+		r = (r << 32) | be32_to_cpu(*(cell++));
+	return r;
+}
+
+static int of_n_cells(const void *blob, int nodeoffset, const char *name)
+{
+	int np;
+	const int *ip;
+
+	do {
+		np = fdt_parent_offset(blob, nodeoffset);
+
+		if (np >= 0)
+			nodeoffset = np;
+		ip = (int *)fdt_getprop(blob, nodeoffset, name, NULL);
+		if (ip)
+			return be32_to_cpup(ip);
+	} while (np >= 0);
+
+	/* No #<NAME>-cells property for the root node */
+	return 1;
+}
+
+int of_n_addr_cells(const void *blob, int nodeoffset)
+{
+	return of_n_cells(blob, nodeoffset, "#address-cells");
+}
+
+int of_n_size_cells(const void *blob, int nodeoffset)
+{
+	return of_n_cells(blob, nodeoffset, "#size-cells");
+}
+
+#define PRu64	"%llx"
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS	4
+#define OF_BAD_ADDR	((u64)-1)
+#define OF_CHECK_COUNTS(na, ns)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
+			(ns) > 0)
+
+/* Debug utility */
+#ifdef DEBUG
+static void of_dump_addr(const char *s, const u32 *addr, int na)
+{
+	printf("%s", s);
+	while(na--)
+		printf(" %08x", *(addr++));
+	printf("\n");
+}
+#else
+static void of_dump_addr(const char *s, const u32 *addr, int na) { }
+#endif
+
+/* Callbacks for bus specific translators */
+struct of_bus {
+	const char	*name;
+	const char	*addresses;
+	void		(*count_cells)(void *blob, int offset,
+				int *addrc, int *sizec);
+	u64		(*map)(u32 *addr, const u32 *range,
+				int na, int ns, int pna);
+	int		(*translate)(u32 *addr, u64 offset, int na);
+};
+
+/* Default translator (generic bus) */
+static void of_bus_default_count_cells(void *blob, int offset,
+					int *addrc, int *sizec)
+{
+	if (addrc)
+		*addrc = of_n_addr_cells(blob, offset);
+	if (sizec)
+		*sizec = of_n_size_cells(blob, offset);
+}
+
+static u64 of_bus_default_map(u32 *addr, const u32 *range,
+		int na, int ns, int pna)
+{
+	u64 cp, s, da;
+
+	cp = of_read_number(range, na);
+	s  = of_read_number(range + na + pna, ns);
+	da = of_read_number(addr, na);
+
+	debug("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
+	    cp, s, da);
+
+	if (da < cp || da >= (cp + s))
+		return OF_BAD_ADDR;
+	return da - cp;
+}
+
+static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+	u64 a = of_read_number(addr, na);
+	memset(addr, 0, na * 4);
+	a += offset;
+	if (na > 1)
+		addr[na - 2] = a >> 32;
+	addr[na - 1] = a & 0xffffffffu;
+
+	return 0;
+}
+
+/* Array of bus specific translators */
+static struct of_bus of_busses[] = {
+	/* Default */
+	{
+		.name = "default",
+		.addresses = "reg",
+		.count_cells = of_bus_default_count_cells,
+		.map = of_bus_default_map,
+		.translate = of_bus_default_translate,
+	},
+};
+
+static int of_translate_one(void * blob, int parent, struct of_bus *bus,
+			    struct of_bus *pbus, u32 *addr,
+			    int na, int ns, int pna, const char *rprop)
+{
+	const u32 *ranges;
+	int rlen;
+	int rone;
+	u64 offset = OF_BAD_ADDR;
+
+	/* Normally, an absence of a "ranges" property means we are
+	 * crossing a non-translatable boundary, and thus the addresses
+	 * below the current not cannot be converted to CPU physical ones.
+	 * Unfortunately, while this is very clear in the spec, it's not
+	 * what Apple understood, and they do have things like /uni-n or
+	 * /ht nodes with no "ranges" property and a lot of perfectly
+	 * useable mapped devices below them. Thus we treat the absence of
+	 * "ranges" as equivalent to an empty "ranges" property which means
+	 * a 1:1 translation at that level. It's up to the caller not to try
+	 * to translate addresses that aren't supposed to be translated in
+	 * the first place. --BenH.
+	 */
+	ranges = (u32 *)fdt_getprop(blob, parent, rprop, &rlen);
+	if (ranges == NULL || rlen == 0) {
+		offset = of_read_number(addr, na);
+		memset(addr, 0, pna * 4);
+		debug("OF: no ranges, 1:1 translation\n");
+		goto finish;
+	}
+
+	debug("OF: walking ranges...\n");
+
+	/* Now walk through the ranges */
+	rlen /= 4;
+	rone = na + pna + ns;
+	for (; rlen >= rone; rlen -= rone, ranges += rone) {
+		offset = bus->map(addr, ranges, na, ns, pna);
+		if (offset != OF_BAD_ADDR)
+			break;
+	}
+	if (offset == OF_BAD_ADDR) {
+		debug("OF: not found !\n");
+		return 1;
+	}
+	memcpy(addr, ranges + na, 4 * pna);
+
+ finish:
+	of_dump_addr("OF: parent translation for:", addr, pna);
+	debug("OF: with offset: "PRu64"\n", offset);
+
+	/* Translate it into parent bus space */
+	return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
+			   const char *rprop)
+{
+	int parent;
+	struct of_bus *bus, *pbus;
+	u32 addr[OF_MAX_ADDR_CELLS];
+	int na, ns, pna, pns;
+	u64 result = OF_BAD_ADDR;
+
+	debug("OF: ** translation for device %s **\n",
+		fdt_get_name(blob, node_offset, NULL));
+
+	/* Get parent & match bus type */
+	parent = fdt_parent_offset(blob, node_offset);
+	if (parent < 0)
+		goto bail;
+	bus = &of_busses[0];
+
+	/* Cound address cells & copy address locally */
+	bus->count_cells(blob, node_offset, &na, &ns);
+	if (!OF_CHECK_COUNTS(na, ns)) {
+		printf("%s: Bad cell count for %s\n", __FUNCTION__,
+		       fdt_get_name(blob, node_offset, NULL));
+		goto bail;
+	}
+	memcpy(addr, in_addr, na * 4);
+
+	debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
+	    bus->name, na, ns, fdt_get_name(blob, parent, NULL));
+	of_dump_addr("OF: translating address:", addr, na);
+
+	/* Translate */
+	for (;;) {
+		/* Switch to parent bus */
+		node_offset = parent;
+		parent = fdt_parent_offset(blob, node_offset);
+
+		/* If root, we have finished */
+		if (parent < 0) {
+			debug("OF: reached root node\n");
+			result = of_read_number(addr, na);
+			break;
+		}
+
+		/* Get new parent bus and counts */
+		pbus = &of_busses[0];
+		pbus->count_cells(blob, node_offset, &pna, &pns);
+		if (!OF_CHECK_COUNTS(pna, pns)) {
+			printf("%s: Bad cell count for %s\n", __FUNCTION__,
+				fdt_get_name(blob, node_offset, NULL));
+			break;
+		}
+
+		debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
+		    pbus->name, pna, pns, fdt_get_name(blob, parent, NULL));
+
+		/* Apply bus translation */
+		if (of_translate_one(blob, node_offset, bus, pbus,
+					addr, na, ns, pna, rprop))
+			break;
+
+		/* Complete the move up one level */
+		na = pna;
+		ns = pns;
+		bus = pbus;
+
+		of_dump_addr("OF: one level translation:", addr, na);
+	}
+ bail:
+
+	return result;
+}
+
+u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr)
+{
+	return __of_translate_address(blob, node_offset, in_addr, "ranges");
+}
diff --git a/include/fdt_support.h b/include/fdt_support.h
index fc16159..78c38b2 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -83,6 +83,7 @@ int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size);
 
 void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size);
 void fdt_del_node_and_alias(void *blob, const char *alias);
+u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr);
 
 #endif /* ifdef CONFIG_OF_LIBFDT */
 #endif /* ifndef __FDT_SUPPORT_H */
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper
  2010-07-04 18:18 [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
@ 2010-07-04 18:18 ` Kumar Gala
  2010-07-17 15:49   ` Kumar Gala
  2010-07-17 15:49 ` [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
  1 sibling, 1 reply; 8+ messages in thread
From: Kumar Gala @ 2010-07-04 18:18 UTC (permalink / raw)
  To: u-boot

Given a compatiable string and physical address try and find a node that
matches.  This is useful when we want to find a specific device node to
update (for example if we have multiple PCI nodes we can use the
physical address to distinquish them when trying to update the device
tree).

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 common/fdt_support.c  |   27 +++++++++++++++++++++++++++
 include/fdt_support.h |    2 ++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 70ad81d..718b635 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1125,3 +1125,30 @@ u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr)
 {
 	return __of_translate_address(blob, node_offset, in_addr, "ranges");
 }
+
+/**
+ * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
+ * who's reg property matches a physical cpu address
+ *
+ * @blob: ptr to device tree
+ * @compat: compatiable string to match
+ * @compat_off: property name
+ *
+ */
+int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
+					phys_addr_t compat_off)
+{
+	int len, off = fdt_node_offset_by_compatible(blob, -1, compat);
+	while (off != -FDT_ERR_NOTFOUND) {
+		u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", &len);
+		if (reg) {
+			if (compat_off == fdt_translate_address(blob, off, reg))
+				return off;
+		}
+		off = fdt_node_offset_by_compatible(blob, off, compat);
+	}
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 78c38b2..54af9fe 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -84,6 +84,8 @@ int fdt_fixup_nor_flash_size(void *blob, int cs, u32 size);
 void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size);
 void fdt_del_node_and_alias(void *blob, const char *alias);
 u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr);
+int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
+					phys_addr_t compat_off);
 
 #endif /* ifdef CONFIG_OF_LIBFDT */
 #endif /* ifndef __FDT_SUPPORT_H */
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr
  2010-07-04 18:18 [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
  2010-07-04 18:18 ` [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper Kumar Gala
@ 2010-07-17 15:49 ` Kumar Gala
  2010-07-18  3:00   ` Jerry Van Baren
  1 sibling, 1 reply; 8+ messages in thread
From: Kumar Gala @ 2010-07-17 15:49 UTC (permalink / raw)
  To: u-boot


On Jul 4, 2010, at 1:18 PM, Kumar Gala wrote:

> This code is extracted out of the Linux Kernel code from
> arch/powerpc/kernel/prom_parse.c.
> 
> We maintain some of the same structure to support multiple bus types even
> though we only have one in the current code.  In the future we might want
> to translate across a PCI bus and thus it will be easier to add that
> functionality back in.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
> common/fdt_support.c  |  264 +++++++++++++++++++++++++++++++++++++++++++++++++
> include/fdt_support.h |    1 +
> 2 files changed, 265 insertions(+), 0 deletions(-)

Jerry,

Any comments?

- k

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper
  2010-07-04 18:18 ` [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper Kumar Gala
@ 2010-07-17 15:49   ` Kumar Gala
  2010-07-18  2:59     ` Jerry Van Baren
  0 siblings, 1 reply; 8+ messages in thread
From: Kumar Gala @ 2010-07-17 15:49 UTC (permalink / raw)
  To: u-boot


On Jul 4, 2010, at 1:18 PM, Kumar Gala wrote:

> Given a compatiable string and physical address try and find a node that
> matches.  This is useful when we want to find a specific device node to
> update (for example if we have multiple PCI nodes we can use the
> physical address to distinquish them when trying to update the device
> tree).
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
> common/fdt_support.c  |   27 +++++++++++++++++++++++++++
> include/fdt_support.h |    2 ++
> 2 files changed, 29 insertions(+), 0 deletions(-)

Jerry,

Any comments?

- k

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper
  2010-07-17 15:49   ` Kumar Gala
@ 2010-07-18  2:59     ` Jerry Van Baren
  2010-07-21  5:35       ` Kumar Gala
  0 siblings, 1 reply; 8+ messages in thread
From: Jerry Van Baren @ 2010-07-18  2:59 UTC (permalink / raw)
  To: u-boot

Hi Kumar,

On 07/17/2010 11:49 AM, Kumar Gala wrote:
>
> On Jul 4, 2010, at 1:18 PM, Kumar Gala wrote:
>
>> Given a compatiable string and physical address try and find a node that

            compatible

>> matches.  This is useful when we want to find a specific device node to
>> update (for example if we have multiple PCI nodes we can use the
>> physical address to distinquish them when trying to update the device

                        distinguish  (s/q/g/)

>> tree).
>>
>> Signed-off-by: Kumar Gala<galak@kernel.crashing.org>
                             ^
Probably should have a space in your signed-off-by line just in case a 
SOB line parser is picky.

>> ---
>> common/fdt_support.c  |   27 +++++++++++++++++++++++++++
>> include/fdt_support.h |    2 ++
>> 2 files changed, 29 insertions(+), 0 deletions(-)
>
> Jerry,
>
> Any comments?
>
> - k

Looks OK to me other than two typos in the comment.

Acked-by: Gerald Van Baren <vanbaren@cideas.com>

gvb

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr
  2010-07-17 15:49 ` [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
@ 2010-07-18  3:00   ` Jerry Van Baren
  2010-07-21  5:35     ` Kumar Gala
  0 siblings, 1 reply; 8+ messages in thread
From: Jerry Van Baren @ 2010-07-18  3:00 UTC (permalink / raw)
  To: u-boot

Hi Kumar,

On 07/17/2010 11:49 AM, Kumar Gala wrote:
>
> On Jul 4, 2010, at 1:18 PM, Kumar Gala wrote:
>
>> This code is extracted out of the Linux Kernel code from
>> arch/powerpc/kernel/prom_parse.c.
>>
>> We maintain some of the same structure to support multiple bus types even
>> though we only have one in the current code.  In the future we might want
>> to translate across a PCI bus and thus it will be easier to add that
>> functionality back in.
>>
>> Signed-off-by: Kumar Gala<galak@kernel.crashing.org>
>> ---
>> common/fdt_support.c  |  264 +++++++++++++++++++++++++++++++++++++++++++++++++
>> include/fdt_support.h |    1 +
>> 2 files changed, 265 insertions(+), 0 deletions(-)
>
> Jerry,
>
> Any comments?
>
> - k


Looks OK to me.

Acked-by: Gerald Van Baren <vanbaren@cideas.com>

gvb

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper
  2010-07-18  2:59     ` Jerry Van Baren
@ 2010-07-21  5:35       ` Kumar Gala
  0 siblings, 0 replies; 8+ messages in thread
From: Kumar Gala @ 2010-07-21  5:35 UTC (permalink / raw)
  To: u-boot


On Jul 17, 2010, at 9:59 PM, Jerry Van Baren wrote:

> Hi Kumar,
> 
> On 07/17/2010 11:49 AM, Kumar Gala wrote:
>> 
>> On Jul 4, 2010, at 1:18 PM, Kumar Gala wrote:
>> 
>>> Given a compatiable string and physical address try and find a node that
> 
>           compatible
> 
>>> matches.  This is useful when we want to find a specific device node to
>>> update (for example if we have multiple PCI nodes we can use the
>>> physical address to distinquish them when trying to update the device
> 
>                       distinguish  (s/q/g/)
> 
>>> tree).
>>> 
>>> Signed-off-by: Kumar Gala<galak@kernel.crashing.org>
>                            ^
> Probably should have a space in your signed-off-by line just in case a SOB line parser is picky.
> 
>>> ---
>>> common/fdt_support.c  |   27 +++++++++++++++++++++++++++
>>> include/fdt_support.h |    2 ++
>>> 2 files changed, 29 insertions(+), 0 deletions(-)
>> 
>> Jerry,
>> 
>> Any comments?
>> 
>> - k
> 
> Looks OK to me other than two typos in the comment.
> 
> Acked-by: Gerald Van Baren <vanbaren@cideas.com>
> 
> gvb

applied with commit comment fixes

- k

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr
  2010-07-18  3:00   ` Jerry Van Baren
@ 2010-07-21  5:35     ` Kumar Gala
  0 siblings, 0 replies; 8+ messages in thread
From: Kumar Gala @ 2010-07-21  5:35 UTC (permalink / raw)
  To: u-boot


On Jul 17, 2010, at 10:00 PM, Jerry Van Baren wrote:

> Hi Kumar,
> 
> On 07/17/2010 11:49 AM, Kumar Gala wrote:
>> 
>> On Jul 4, 2010, at 1:18 PM, Kumar Gala wrote:
>> 
>>> This code is extracted out of the Linux Kernel code from
>>> arch/powerpc/kernel/prom_parse.c.
>>> 
>>> We maintain some of the same structure to support multiple bus types even
>>> though we only have one in the current code.  In the future we might want
>>> to translate across a PCI bus and thus it will be easier to add that
>>> functionality back in.
>>> 
>>> Signed-off-by: Kumar Gala<galak@kernel.crashing.org>
>>> ---
>>> common/fdt_support.c  |  264 +++++++++++++++++++++++++++++++++++++++++++++++++
>>> include/fdt_support.h |    1 +
>>> 2 files changed, 265 insertions(+), 0 deletions(-)
>> 
>> Jerry,
>> 
>> Any comments?
>> 
>> - k
> 
> 
> Looks OK to me.
> 
> Acked-by: Gerald Van Baren <vanbaren@cideas.com>
> 
> gvb

applied to 85xx

- k

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-07-21  5:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-04 18:18 [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
2010-07-04 18:18 ` [U-Boot] [PATCH 2/2] fdt: Add fdt_node_offset_by_compat_reg helper Kumar Gala
2010-07-17 15:49   ` Kumar Gala
2010-07-18  2:59     ` Jerry Van Baren
2010-07-21  5:35       ` Kumar Gala
2010-07-17 15:49 ` [U-Boot] [PATCH 1/2] fdt: Add fdt_translate_address to convert reg node to cpu phys addr Kumar Gala
2010-07-18  3:00   ` Jerry Van Baren
2010-07-21  5:35     ` Kumar Gala

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.