1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
/* 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>
#include <compiler.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);
/* Copy node to new parent, including properties and subnodes */
struct dt_node *dt_copy(struct dt_node *node, struct dt_node *parent);
/* 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;)
/* Check status property */
bool dt_node_is_enabled(struct dt_node *node);
/* 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 child node by name */
struct dt_node *dt_find_by_name(struct dt_node *root, const char *name);
/* 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) __warn_unused_result;
/* 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);
/* compare function used to sort child nodes by name when added to the
* tree. This is mainly here for testing.
*/
int dt_cmp_subnodes(const struct dt_node *a, const struct dt_node *b);
#endif /* __DEVICE_H */
|