* [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.