From 05a22ba096fb996bb69ab020a8d08aafac2c28ba Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Nov 2009 15:37:13 +1100 Subject: [PATCH] Support ePAPR compliant phandle properties 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 This was extracted from the DTC commit: d75b33af676d0beac8398651a7f09037555a550b Mon Sep 17 00:00:00 2001 Signed-off-by: Gerald Van Baren --- lib/libfdt/fdt_ro.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index 1e1e322..91a354e 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -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,