@@ -14,53 +14,11 @@
#include <xen/efi.h>
#include <xen/device_tree.h>
#include <xen/libfdt/libfdt.h>
+#include <xen/fdt.h>
#include <xen/sort.h>
#include <xsm/xsm.h>
#include <asm/setup.h>
-static bool __init device_tree_node_matches(const void *fdt, int node,
- const char *match)
-{
- const char *name;
- size_t match_len;
-
- name = fdt_get_name(fdt, node, NULL);
- match_len = strlen(match);
-
- /* Match both "match" and "match@..." patterns but not
- "match-foo". */
- return strncmp(name, match, match_len) == 0
- && (name[match_len] == '@' || name[match_len] == '\0');
-}
-
-static bool __init device_tree_node_compatible(const void *fdt, int node,
- const char *match)
-{
- int len, l;
- const void *prop;
-
- prop = fdt_getprop(fdt, node, "compatible", &len);
- if ( prop == NULL )
- return false;
-
- while ( len > 0 ) {
- if ( !dt_compat_cmp(prop, match) )
- return true;
- l = strlen(prop) + 1;
- prop += l;
- len -= l;
- }
-
- return false;
-}
-
-void __init device_tree_get_reg(const __be32 **cell, u32 address_cells,
- u32 size_cells, u64 *start, u64 *size)
-{
- *start = dt_next_cell(address_cells, cell);
- *size = dt_next_cell(size_cells, cell);
-}
-
static int __init device_tree_get_meminfo(const void *fdt, int node,
const char *prop_name,
u32 address_cells, u32 size_cells,
@@ -108,77 +66,6 @@ static int __init device_tree_get_meminfo(const void *fdt, int node,
return 0;
}
-u32 __init device_tree_get_u32(const void *fdt, int node,
- const char *prop_name, u32 dflt)
-{
- const struct fdt_property *prop;
-
- prop = fdt_get_property(fdt, node, prop_name, NULL);
- if ( !prop || prop->len < sizeof(u32) )
- return dflt;
-
- return fdt32_to_cpu(*(uint32_t*)prop->data);
-}
-
-/**
- * device_tree_for_each_node - iterate over all device tree sub-nodes
- * @fdt: flat device tree.
- * @node: parent node to start the search from
- * @func: function to call for each sub-node.
- * @data: data to pass to @func.
- *
- * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
- *
- * Returns 0 if all nodes were iterated over successfully. If @func
- * returns a value different from 0, that value is returned immediately.
- */
-int __init device_tree_for_each_node(const void *fdt, int node,
- device_tree_node_func func,
- void *data)
-{
- /*
- * We only care about relative depth increments, assume depth of
- * node is 0 for simplicity.
- */
- int depth = 0;
- const int first_node = node;
- u32 address_cells[DEVICE_TREE_MAX_DEPTH];
- u32 size_cells[DEVICE_TREE_MAX_DEPTH];
- int ret;
-
- do {
- const char *name = fdt_get_name(fdt, node, NULL);
- u32 as, ss;
-
- if ( depth >= DEVICE_TREE_MAX_DEPTH )
- {
- printk("Warning: device tree node `%s' is nested too deep\n",
- name);
- continue;
- }
-
- as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
- ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
-
- address_cells[depth] = device_tree_get_u32(fdt, node,
- "#address-cells", as);
- size_cells[depth] = device_tree_get_u32(fdt, node,
- "#size-cells", ss);
-
- /* skip the first node */
- if ( node != first_node )
- {
- ret = func(fdt, node, name, depth, as, ss, data);
- if ( ret != 0 )
- return ret;
- }
-
- node = fdt_next_node(fdt, node, &depth);
- } while ( node >= 0 && depth > 0 );
-
- return 0;
-}
-
static int __init process_memory_node(const void *fdt, int node,
const char *name, int depth,
u32 address_cells, u32 size_cells,
@@ -31,8 +31,12 @@ config HAS_ALTERNATIVE
config HAS_COMPAT
bool
+config CORE_DEVICE_TREE
+ bool
+
config HAS_DEVICE_TREE
bool
+ select CORE_DEVICE_TREE
config HAS_EX_TABLE
bool
@@ -10,6 +10,7 @@ obj-y += domain.o
obj-y += event_2l.o
obj-y += event_channel.o
obj-y += event_fifo.o
+obj-$(CONFIG_CORE_DEVICE_TREE) += fdt.o
obj-$(CONFIG_CRASH_DEBUG) += gdbstub.o
obj-$(CONFIG_GRANT_TABLE) += grant_table.o
obj-y += guestcopy.o
@@ -73,7 +74,7 @@ obj-y += sched/
obj-$(CONFIG_UBSAN) += ubsan/
obj-$(CONFIG_NEEDS_LIBELF) += libelf/
-obj-$(CONFIG_HAS_DEVICE_TREE) += libfdt/
+obj-$(CONFIG_CORE_DEVICE_TREE) += libfdt/
CONF_FILE := $(if $(patsubst /%,,$(KCONFIG_CONFIG)),$(objtree)/)$(KCONFIG_CONFIG)
$(obj)/config.gz: $(CONF_FILE)
new file mode 100644
@@ -0,0 +1,131 @@
+/*
+ * Flattened Device Tree
+ *
+ * Copyright (C) 2012-2014 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <xen/fdt.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/types.h>
+
+bool __init device_tree_node_matches(
+ const void *fdt, int node, const char *match)
+{
+ const char *name;
+ size_t match_len;
+
+ name = fdt_get_name(fdt, node, NULL);
+ match_len = strlen(match);
+
+ /* Match both "match" and "match@..." patterns but not
+ "match-foo". */
+ return strncmp(name, match, match_len) == 0
+ && (name[match_len] == '@' || name[match_len] == '\0');
+}
+
+bool __init device_tree_node_compatible(
+ const void *fdt, int node, const char *match)
+{
+ int len, l;
+ int mlen;
+ const void *prop;
+
+ mlen = strlen(match);
+
+ prop = fdt_getprop(fdt, node, "compatible", &len);
+ if ( prop == NULL )
+ return false;
+
+ while ( len > 0 ) {
+ if ( !dt_compat_cmp(prop, match) )
+ return true;
+ l = strlen(prop) + 1;
+ prop += l;
+ len -= l;
+ }
+
+ return false;
+}
+
+void __init device_tree_get_reg(
+ const __be32 **cell, u32 address_cells, u32 size_cells, u64 *start,
+ u64 *size)
+{
+ *start = dt_next_cell(address_cells, cell);
+ *size = dt_next_cell(size_cells, cell);
+}
+
+u32 __init device_tree_get_u32(
+ const void *fdt, int node, const char *prop_name, u32 dflt)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property(fdt, node, prop_name, NULL);
+ if ( !prop || prop->len < sizeof(u32) )
+ return dflt;
+
+ return fdt32_to_cpu(*(uint32_t*)prop->data);
+}
+
+/**
+ * device_tree_for_each_node - iterate over all device tree sub-nodes
+ * @fdt: flat device tree.
+ * @node: parent node to start the search from
+ * @func: function to call for each sub-node.
+ * @data: data to pass to @func.
+ *
+ * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
+ *
+ * Returns 0 if all nodes were iterated over successfully. If @func
+ * returns a value different from 0, that value is returned immediately.
+ */
+int __init device_tree_for_each_node(
+ const void *fdt, int node, device_tree_node_func func, void *data)
+{
+ /*
+ * We only care about relative depth increments, assume depth of
+ * node is 0 for simplicity.
+ */
+ int depth = 0;
+ const int first_node = node;
+ u32 address_cells[DEVICE_TREE_MAX_DEPTH];
+ u32 size_cells[DEVICE_TREE_MAX_DEPTH];
+ int ret;
+
+ do {
+ const char *name = fdt_get_name(fdt, node, NULL);
+ u32 as, ss;
+
+ if ( depth >= DEVICE_TREE_MAX_DEPTH )
+ {
+ printk("Warning: device tree node `%s' is nested too deep\n",
+ name);
+ continue;
+ }
+
+ as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
+ ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
+
+ address_cells[depth] = device_tree_get_u32(fdt, node,
+ "#address-cells", as);
+ size_cells[depth] = device_tree_get_u32(fdt, node,
+ "#size-cells", ss);
+
+ /* skip the first node */
+ if ( node != first_node )
+ {
+ ret = func(fdt, node, name, depth, as, ss, data);
+ if ( ret != 0 )
+ return ret;
+ }
+
+ node = fdt_next_node(fdt, node, &depth);
+ } while ( node >= 0 && depth > 0 );
+
+ return 0;
+}
@@ -14,13 +14,12 @@
#include <asm/device.h>
#include <public/xen.h>
#include <public/device_tree_defs.h>
+#include <xen/fdt.h>
#include <xen/kernel.h>
#include <xen/string.h>
#include <xen/types.h>
#include <xen/list.h>
-#define DEVICE_TREE_MAX_DEPTH 16
-
/*
* Struct used for matching a device
*/
@@ -158,17 +157,8 @@ struct dt_raw_irq {
#define dt_irq(irq) ((irq)->irq)
#define dt_irq_flags(irq) ((irq)->flags)
-typedef int (*device_tree_node_func)(const void *fdt,
- int node, const char *name, int depth,
- u32 address_cells, u32 size_cells,
- void *data);
-
extern const void *device_tree_flattened;
-int device_tree_for_each_node(const void *fdt, int node,
- device_tree_node_func func,
- void *data);
-
/**
* dt_unflatten_host_device_tree - Unflatten the host device tree
*
@@ -213,14 +203,6 @@ extern const struct dt_device_node *dt_interrupt_controller;
struct dt_device_node *
dt_find_interrupt_controller(const struct dt_device_match *matches);
-#define dt_prop_cmp(s1, s2) strcmp((s1), (s2))
-#define dt_node_cmp(s1, s2) strcasecmp((s1), (s2))
-#define dt_compat_cmp(s1, s2) strcasecmp((s1), (s2))
-
-/* Default #address and #size cells */
-#define DT_ROOT_NODE_ADDR_CELLS_DEFAULT 2
-#define DT_ROOT_NODE_SIZE_CELLS_DEFAULT 1
-
#define dt_for_each_property_node(dn, pp) \
for ( pp = dn->properties; pp != NULL; pp = pp->next )
@@ -230,36 +212,6 @@ dt_find_interrupt_controller(const struct dt_device_match *matches);
#define dt_for_each_child_node(dt, dn) \
for ( dn = dt->child; dn != NULL; dn = dn->sibling )
-/* Helper to read a big number; size is in cells (not bytes) */
-static inline u64 dt_read_number(const __be32 *cell, int size)
-{
- u64 r = 0;
-
- while ( size-- )
- r = (r << 32) | be32_to_cpu(*(cell++));
- return r;
-}
-
-/* Helper to convert a number of cells to bytes */
-static inline int dt_cells_to_size(int size)
-{
- return (size * sizeof (u32));
-}
-
-/* Helper to convert a number of bytes to cells, rounds down */
-static inline int dt_size_to_cells(int bytes)
-{
- return (bytes / sizeof(u32));
-}
-
-static inline u64 dt_next_cell(int s, const __be32 **cellp)
-{
- const __be32 *p = *cellp;
-
- *cellp = p + s;
- return dt_read_number(p, s);
-}
-
static inline const char *dt_node_full_name(const struct dt_device_node *np)
{
return (np && np->full_name) ? np->full_name : "<no-node>";
new file mode 100644
@@ -0,0 +1,79 @@
+/*
+ * Flattened Device Tree
+ *
+ * Copyright (C) 2012 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __XEN_FDT_H__
+#define __XEN_FDT_H__
+
+#include <xen/init.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/types.h>
+
+#define DEVICE_TREE_MAX_DEPTH 16
+
+/* Default #address and #size cells */
+#define DT_ROOT_NODE_ADDR_CELLS_DEFAULT 2
+#define DT_ROOT_NODE_SIZE_CELLS_DEFAULT 1
+
+#define dt_prop_cmp(s1, s2) strcmp((s1), (s2))
+#define dt_node_cmp(s1, s2) strcasecmp((s1), (s2))
+#define dt_compat_cmp(s1, s2) strcasecmp((s1), (s2))
+
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 dt_read_number(const __be32 *cell, int size)
+{
+ u64 r = 0;
+
+ while ( size-- )
+ r = (r << 32) | be32_to_cpu(*(cell++));
+ return r;
+}
+
+/* Helper to convert a number of cells to bytes */
+static inline int dt_cells_to_size(int size)
+{
+ return (size * sizeof (u32));
+}
+
+/* Helper to convert a number of bytes to cells, rounds down */
+static inline int dt_size_to_cells(int bytes)
+{
+ return (bytes / sizeof(u32));
+}
+
+static inline u64 dt_next_cell(int s, const __be32 **cellp)
+{
+ const __be32 *p = *cellp;
+
+ *cellp = p + s;
+ return dt_read_number(p, s);
+}
+
+
+bool __init device_tree_node_matches(
+ const void *fdt, int node, const char *match);
+
+bool __init device_tree_node_compatible(
+ const void *fdt, int node, const char *match);
+
+void __init device_tree_get_reg(
+ const __be32 **cell, u32 address_cells, u32 size_cells, u64 *start,
+ u64 *size);
+
+u32 __init device_tree_get_u32(
+ const void *fdt, int node, const char *prop_name, u32 dflt);
+
+typedef int (*device_tree_node_func)(
+ const void *fdt, int node, const char *name, int depth, u32 address_cells,
+ u32 size_cells, void *data);
+
+int device_tree_for_each_node(
+ const void *fdt, int node, device_tree_node_func func, void *data);
+
+
+#endif /* __XEN_FDT_H__ */