summaryrefslogtreecommitdiffstats
path: root/include/device.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/device.h')
-rw-r--r--include/device.h233
1 files changed, 233 insertions, 0 deletions
diff --git a/include/device.h b/include/device.h
new file mode 100644
index 00000000..65ceef45
--- /dev/null
+++ b/include/device.h
@@ -0,0 +1,233 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DEVICE_H
+#define __DEVICE_H
+#include <ccan/list/list.h>
+#include <ccan/short_types/short_types.h>
+
+/* Any property or node with this prefix will not be passed to the kernel. */
+#define DT_PRIVATE "skiboot,"
+
+/*
+ * An in-memory representation of a node in the device tree.
+ *
+ * This is trivially flattened into an fdt.
+ *
+ * Note that the add_* routines will make a copy of the name if it's not
+ * a read-only string (ie. usually a string literal).
+ */
+struct dt_property {
+ struct list_node list;
+ const char *name;
+ size_t len;
+ char prop[/* len */];
+};
+
+struct dt_node {
+ const char *name;
+ struct list_node list;
+ struct list_head properties;
+ struct list_head children;
+ struct dt_node *parent;
+ u32 phandle;
+};
+
+/* This is shared with device_tree.c .. make it static when
+ * the latter is gone (hopefully soon)
+ */
+extern u32 last_phandle;
+
+extern struct dt_node *dt_root;
+extern struct dt_node *dt_chosen;
+
+/* Create a root node: ie. a parentless one. */
+struct dt_node *dt_new_root(const char *name);
+
+/* Graft a root node into this tree. */
+bool dt_attach_root(struct dt_node *parent, struct dt_node *root);
+
+/* Add a child node. */
+struct dt_node *dt_new(struct dt_node *parent, const char *name);
+struct dt_node *dt_new_addr(struct dt_node *parent, const char *name,
+ uint64_t unit_addr);
+struct dt_node *dt_new_2addr(struct dt_node *parent, const char *name,
+ uint64_t unit_addr0, uint64_t unit_addr1);
+
+/* Add a property node, various forms. */
+struct dt_property *dt_add_property(struct dt_node *node,
+ const char *name,
+ const void *val, size_t size);
+struct dt_property *dt_add_property_string(struct dt_node *node,
+ const char *name,
+ const char *value);
+struct dt_property *dt_add_property_nstr(struct dt_node *node,
+ const char *name,
+ const char *value, unsigned int vlen);
+
+/* Given out enough GCC extensions, we will achieve enlightenment! */
+#define dt_add_property_strings(node, name, ...) \
+ __dt_add_property_strings((node), ((name)), \
+ sizeof((const char *[]) { __VA_ARGS__ })/sizeof(const char *), \
+ __VA_ARGS__)
+
+struct dt_property *__dt_add_property_strings(struct dt_node *node,
+ const char *name,
+ int count, ...);
+
+/* Given out enough GCC extensions, we will achieve enlightenment! */
+#define dt_add_property_cells(node, name, ...) \
+ __dt_add_property_cells((node), ((name)), \
+ sizeof((u32[]) { __VA_ARGS__ })/sizeof(u32), \
+ __VA_ARGS__)
+
+struct dt_property *__dt_add_property_cells(struct dt_node *node,
+ const char *name,
+ int count, ...);
+
+#define dt_add_property_u64s(node, name, ...) \
+ __dt_add_property_u64s((node), ((name)), \
+ sizeof((u64[]) { __VA_ARGS__ })/sizeof(u64), \
+ __VA_ARGS__)
+
+struct dt_property *__dt_add_property_u64s(struct dt_node *node,
+ const char *name,
+ int count, ...);
+
+static inline struct dt_property *dt_add_property_u64(struct dt_node *node,
+ const char *name, u64 val)
+{
+ return dt_add_property_cells(node, name, (u32)(val >> 32), (u32)val);
+}
+
+void dt_del_property(struct dt_node *node, struct dt_property *prop);
+
+/* Warning: moves *prop! */
+void dt_resize_property(struct dt_property **prop, size_t len);
+
+u32 dt_property_get_cell(const struct dt_property *prop, u32 index);
+
+/* First child of this node. */
+struct dt_node *dt_first(const struct dt_node *root);
+
+/* Return next node, or NULL. */
+struct dt_node *dt_next(const struct dt_node *root, const struct dt_node *prev);
+
+/* Iterate nodes */
+#define dt_for_each_node(root, node) \
+ for (node = dt_first(root); node; node = dt_next(root, node))
+
+#define dt_for_each_child(parent, node) \
+ list_for_each(&parent->children, node, list)
+
+/* Find a string in a string list */
+bool dt_prop_find_string(const struct dt_property *p, const char *s);
+
+/* Check a compatible property */
+bool dt_node_is_compatible(const struct dt_node *node, const char *compat);
+
+/* Find a node based on compatible property */
+struct dt_node *dt_find_compatible_node(struct dt_node *root,
+ struct dt_node *prev,
+ const char *compat);
+
+#define dt_for_each_compatible(root, node, compat) \
+ for (node = NULL; \
+ (node = dt_find_compatible_node(root, node, compat)) != NULL;)
+
+struct dt_node *dt_find_compatible_node_on_chip(struct dt_node *root,
+ struct dt_node *prev,
+ const char *compat,
+ uint32_t chip_id);
+
+#define dt_for_each_compatible_on_chip(root, node, compat, chip_id) \
+ for (node = NULL; \
+ (node = dt_find_compatible_node_on_chip(root, node,\
+ compat, chip_id)) != NULL;)
+
+/* Build the full path for a node. Return a new block of memory, caller
+ * shall free() it
+ */
+char *dt_get_path(const struct dt_node *node);
+
+/* Find a node by path */
+struct dt_node *dt_find_by_path(struct dt_node *root, const char *path);
+
+/* Find a node by phandle */
+struct dt_node *dt_find_by_phandle(struct dt_node *root, u32 phandle);
+
+/* Find a property by name. */
+const struct dt_property *dt_find_property(const struct dt_node *node,\
+ const char *name);
+const struct dt_property *dt_require_property(const struct dt_node *node,
+ const char *name, int wanted_len);
+
+/* non-const variant */
+struct dt_property *__dt_find_property(struct dt_node *node, const char *name);
+
+/* Find a property by name, check if it's the same as val. */
+bool dt_has_node_property(const struct dt_node *node,
+ const char *name, const char *val);
+
+/* Free a node (and any children). */
+void dt_free(struct dt_node *node);
+
+/* Parse an initial fdt */
+void dt_expand(const void *fdt);
+int dt_expand_node(struct dt_node *node, const void *fdt, int fdt_node);
+
+/* Simplified accessors */
+u64 dt_prop_get_u64(const struct dt_node *node, const char *prop);
+u64 dt_prop_get_u64_def(const struct dt_node *node, const char *prop, u64 def);
+u32 dt_prop_get_u32(const struct dt_node *node, const char *prop);
+u32 dt_prop_get_u32_def(const struct dt_node *node, const char *prop, u32 def);
+const void *dt_prop_get(const struct dt_node *node, const char *prop);
+const void *dt_prop_get_def(const struct dt_node *node, const char *prop,
+ void *def);
+const void *dt_prop_get_def_size(const struct dt_node *node, const char *prop,
+ void *def, size_t *len);
+u32 dt_prop_get_cell(const struct dt_node *node, const char *prop, u32 cell);
+u32 dt_prop_get_cell_def(const struct dt_node *node, const char *prop, u32 cell, u32 def);
+
+/* Parsing helpers */
+u32 dt_n_address_cells(const struct dt_node *node);
+u32 dt_n_size_cells(const struct dt_node *node);
+u64 dt_get_number(const void *pdata, unsigned int cells);
+
+/* Find an ibm,chip-id property in this node; if not found, walk up the parent
+ * nodes. Returns -1 if no chip-id property exists. */
+u32 dt_get_chip_id(const struct dt_node *node);
+
+/* Address accessors ("reg" properties parsing). No translation,
+ * only support "simple" address forms (1 or 2 cells). Asserts
+ * if address doesn't exist
+ */
+u64 dt_get_address(const struct dt_node *node, unsigned int index,
+ u64 *out_size);
+
+/* Count "reg" property entries */
+unsigned int dt_count_addresses(const struct dt_node *node);
+
+/* Address translation
+ *
+ * WARNING: Current implementation is simplified and will not
+ * handle complex address formats with address space indicators
+ * nor will it handle "ranges" translations yet... (XX TODO)
+ */
+u64 dt_translate_address(const struct dt_node *node, unsigned int index,
+ u64 *out_size);
+
+#endif /* __DEVICE_H */
OpenPOWER on IntegriCloud