diff mbox

[1/2] device: add dt_find_by_name_addr

Message ID 20170406040158.30765-1-oohall@gmail.com
State Accepted
Headers show

Commit Message

Oliver O'Halloran April 6, 2017, 4:01 a.m. UTC
Adds two helper functions that allow device nodes to be found via
their name and unit address. One will take an integer address and
format it to a hex string while the other looks up the unit based
a user supplied string. This is handy in a few places inside the
HDAT parser.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 core/device.c          | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 core/test/run-device.c |  1 +
 include/device.h       |  5 +++++
 3 files changed, 56 insertions(+)

Comments

Vasant Hegde April 6, 2017, 4:54 a.m. UTC | #1
On 04/06/2017 09:31 AM, Oliver O'Halloran wrote:
> Adds two helper functions that allow device nodes to be found via
> their name and unit address. One will take an integer address and
> format it to a hex string while the other looks up the unit based
> a user supplied string. This is handy in a few places inside the
> HDAT parser.
>
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
> ---
>  core/device.c          | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  core/test/run-device.c |  1 +
>  include/device.h       |  5 +++++
>  3 files changed, 56 insertions(+)
>
> diff --git a/core/device.c b/core/device.c
> index 76c2f8481b9f..f3ee63fbc423 100644
> --- a/core/device.c
> +++ b/core/device.c
> @@ -21,6 +21,7 @@
>  #include <libfdt/libfdt_internal.h>
>  #include <ccan/str/str.h>
>  #include <ccan/endian/endian.h>
> +#include <inttypes.h>
>
>  /* Used to give unique handles. */
>  u32 last_phandle = 0;
> @@ -155,6 +156,55 @@ struct dt_node *dt_new(struct dt_node *parent, const char *name)
>  	return new;
>  }
>
> +/*
> + * low level variant, we export this because there are "weird" address
> + * formats, such as LPC/ISA bus addresses which have a letter to identify
> + * which bus space the address is inside of.
> + */
> +struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name,
> +	const char *addr)
> +{
> +	struct dt_node *node;
> +
> +	if (list_empty(&parent->children))
> +		return NULL;
> +
> +	dt_for_each_child(parent, node) {
> +		const char *unit = get_unitname(node);
> +		int len;
> +
> +		if (!unit)
> +			continue;
> +
> +		/* match the name */
> +		len = (int) (unit - node->name) - 1;
> +		if (strncmp(node->name, name, len))
> +			continue;
> +
> +		/* match the unit */
> +		if (strcmp(unit, addr) == 0)
> +			return node;
> +	}
> +
> +	dt_for_each_child(parent, node) {
> +		struct dt_node *ret = __dt_find_by_name_addr(node, name, addr);

You can reuse variable 'node' instead of creating one more here. Otherwise patch 
looks good.

Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>

-Vasant
diff mbox

Patch

diff --git a/core/device.c b/core/device.c
index 76c2f8481b9f..f3ee63fbc423 100644
--- a/core/device.c
+++ b/core/device.c
@@ -21,6 +21,7 @@ 
 #include <libfdt/libfdt_internal.h>
 #include <ccan/str/str.h>
 #include <ccan/endian/endian.h>
+#include <inttypes.h>
 
 /* Used to give unique handles. */
 u32 last_phandle = 0;
@@ -155,6 +156,55 @@  struct dt_node *dt_new(struct dt_node *parent, const char *name)
 	return new;
 }
 
+/*
+ * low level variant, we export this because there are "weird" address
+ * formats, such as LPC/ISA bus addresses which have a letter to identify
+ * which bus space the address is inside of.
+ */
+struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name,
+	const char *addr)
+{
+	struct dt_node *node;
+
+	if (list_empty(&parent->children))
+		return NULL;
+
+	dt_for_each_child(parent, node) {
+		const char *unit = get_unitname(node);
+		int len;
+
+		if (!unit)
+			continue;
+
+		/* match the name */
+		len = (int) (unit - node->name) - 1;
+		if (strncmp(node->name, name, len))
+			continue;
+
+		/* match the unit */
+		if (strcmp(unit, addr) == 0)
+			return node;
+	}
+
+	dt_for_each_child(parent, node) {
+		struct dt_node *ret = __dt_find_by_name_addr(node, name, addr);
+
+		if (ret)
+			return ret;
+	}
+
+	return NULL;
+}
+
+struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name,
+	uint64_t addr)
+{
+	char addr_str[16 + 1]; /* max size of a 64bit int */
+	snprintf(addr_str, sizeof(addr_str), "%" PRIx64, addr);
+
+	return __dt_find_by_name_addr(parent, name, addr_str);
+}
+
 struct dt_node *dt_new_addr(struct dt_node *parent, const char *name,
 			    uint64_t addr)
 {
diff --git a/core/test/run-device.c b/core/test/run-device.c
index e91e5a5fc5c6..5939afc70e54 100644
--- a/core/test/run-device.c
+++ b/core/test/run-device.c
@@ -150,6 +150,7 @@  int main(void)
 	assert(!list_top(&addr1->properties, struct dt_property, list));
 	check_path(addr1, "/addrs/addr@1337");
 	assert(dt_find_by_name(root, "addr@1337") == addr1);
+	assert(dt_find_by_name_addr(root, "addr", 0x1337) == addr1);
 	assert(dt_find_by_path(root, "/addrs/addr@1337") == addr1);
 
 	addr2 = dt_new_2addr(addrs, "2addr", 0xdead, 0xbeef);
diff --git a/include/device.h b/include/device.h
index 1ad403f18450..5155daadc7ee 100644
--- a/include/device.h
+++ b/include/device.h
@@ -247,4 +247,9 @@  u64 dt_translate_address(const struct dt_node *node, unsigned int index,
  */
 int dt_cmp_subnodes(const struct dt_node *a,  const struct dt_node *b);
 
+struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name,
+				const char *addr);
+struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name,
+				uint64_t addr);
+
 #endif /* __DEVICE_H */