]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
Support ePAPR compliant phandle properties
authorDavid Gibson <david@gibson.dropbear.id.au>
Thu, 26 Nov 2009 04:37:13 +0000 (15:37 +1100)
committerGerald Van Baren <gvb@unssw.com>
Fri, 15 Jul 2011 01:03:53 +0000 (21:03 -0400)
Currently, the Linux kernel, libfdt and dtc, when using flattened
device trees encode a node's phandle into a property named
"linux,phandle".  The ePAPR specification, however - aiming as it is
to not be a Linux specific spec - requires that phandles be encoded in
a property named simply "phandle".

This patch adds support for this newer approach to dtc and libfdt.
Specifically:

- fdt_get_phandle() will now return the correct phandle if it
          is supplied in either of these properties

- fdt_node_offset_by_phandle() will correctly find a node with
          the given phandle encoded in either property.

- By default, when auto-generating phandles, dtc will encode
          it into both properties for maximum compatibility.  A new -H
          option allows either only old-style or only new-style
          properties to be generated.

- If phandle properties are explicitly supplied in the dts
  file, dtc will not auto-generate ones in the alternate format.

- If both properties are supplied, dtc will check that they
          have the same value.

- Some existing testcases are updated to use a mix of old and
          new-style phandles, partially testing the changes.

- A new phandle_format test further tests the libfdt support,
          and the -H option.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This was extracted from the DTC commit:
d75b33af676d0beac8398651a7f09037555a550b Mon Sep 17 00:00:00 2001

Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
lib/libfdt/fdt_ro.c

index 1e1e32209ce71d3087941bde94381f30932c7b23..91a354e108a3496f9b54fa34ea8149f82371e6b9 100644 (file)
@@ -278,9 +278,14 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
        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 +445,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
 
 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,