Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2013-2018 IBM Corp. */
3 : :
4 : : #ifndef __DEVICE_H
5 : : #define __DEVICE_H
6 : : #include <ccan/list/list.h>
7 : : #include <ccan/short_types/short_types.h>
8 : : #include <compiler.h>
9 : :
10 : : /* Any property or node with this prefix will not be passed to the kernel. */
11 : : #define DT_PRIVATE "skiboot,"
12 : :
13 : : /*
14 : : * An in-memory representation of a node in the device tree.
15 : : *
16 : : * This is trivially flattened into an fdt.
17 : : *
18 : : * Note that the add_* routines will make a copy of the name if it's not
19 : : * a read-only string (ie. usually a string literal).
20 : : */
21 : : struct dt_property {
22 : : struct list_node list;
23 : : const char *name;
24 : : size_t len;
25 : : char prop[/* len */];
26 : : };
27 : :
28 : : struct dt_node {
29 : : const char *name;
30 : : struct list_node list;
31 : : struct list_head properties;
32 : : struct list_head children;
33 : : struct dt_node *parent;
34 : : u32 phandle;
35 : : };
36 : :
37 : : /* This is shared with device_tree.c .. make it static when
38 : : * the latter is gone (hopefully soon)
39 : : */
40 : : extern u32 last_phandle;
41 : :
42 : : extern struct dt_node *dt_root;
43 : : extern struct dt_node *dt_chosen;
44 : :
45 : : /* Create a root node: ie. a parentless one. */
46 : : struct dt_node *dt_new_root(const char *name);
47 : :
48 : : /* Graft a root node into this tree. */
49 : : bool dt_attach_root(struct dt_node *parent, struct dt_node *root);
50 : :
51 : : /* Wrappers for last_phandle operations */
52 : 1 : static inline u32 get_last_phandle(void)
53 : : {
54 : 1 : return last_phandle;
55 : : }
56 : :
57 : 6 : static inline void set_last_phandle(u32 phandle)
58 : : {
59 : 6 : last_phandle = phandle;
60 : 6 : }
61 : :
62 : 737 : static inline u32 new_phandle(void)
63 : : {
64 : 737 : return ++last_phandle;
65 : : }
66 : :
67 : : /* Add a child node. */
68 : : struct dt_node *dt_new(struct dt_node *parent, const char *name);
69 : : struct dt_node *dt_new_addr(struct dt_node *parent, const char *name,
70 : : uint64_t unit_addr);
71 : : struct dt_node *dt_new_2addr(struct dt_node *parent, const char *name,
72 : : uint64_t unit_addr0, uint64_t unit_addr1);
73 : : struct dt_node *dt_new_check(struct dt_node *parent, const char *name);
74 : :
75 : : /* Copy node to new parent, including properties and subnodes */
76 : : struct dt_node *dt_copy(struct dt_node *node, struct dt_node *parent);
77 : :
78 : : /* Add a property node, various forms. */
79 : : struct dt_property *dt_add_property(struct dt_node *node,
80 : : const char *name,
81 : : const void *val, size_t size);
82 : : struct dt_property *dt_add_property_string(struct dt_node *node,
83 : : const char *name,
84 : : const char *value);
85 : : struct dt_property *dt_add_property_nstr(struct dt_node *node,
86 : : const char *name,
87 : : const char *value, unsigned int vlen);
88 : :
89 : : /* Given out enough GCC extensions, we will achieve enlightenment! */
90 : : #define dt_add_property_strings(node, name, ...) \
91 : : __dt_add_property_strings((node), ((name)), \
92 : : sizeof((const char *[]) { __VA_ARGS__ })/sizeof(const char *), \
93 : : __VA_ARGS__)
94 : :
95 : : struct dt_property *__dt_add_property_strings(struct dt_node *node,
96 : : const char *name,
97 : : int count, ...);
98 : :
99 : : /* Given out enough GCC extensions, we will achieve enlightenment! */
100 : : #define dt_add_property_cells(node, name, ...) \
101 : : __dt_add_property_cells((node), ((name)), \
102 : : sizeof((u32[]) { __VA_ARGS__ })/sizeof(u32), \
103 : : __VA_ARGS__)
104 : :
105 : : struct dt_property *__dt_add_property_cells(struct dt_node *node,
106 : : const char *name,
107 : : int count, ...);
108 : :
109 : : #define dt_add_property_u64s(node, name, ...) \
110 : : __dt_add_property_u64s((node), ((name)), \
111 : : sizeof((u64[]) { __VA_ARGS__ })/sizeof(u64), \
112 : : __VA_ARGS__)
113 : :
114 : : struct dt_property *__dt_add_property_u64s(struct dt_node *node,
115 : : const char *name,
116 : : int count, ...);
117 : :
118 : 14 : static inline struct dt_property *dt_add_property_u64(struct dt_node *node,
119 : : const char *name, u64 val)
120 : : {
121 : 14 : return dt_add_property_cells(node, name, (u32)(val >> 32),
122 : : (u32)(val & 0xffffffffUL));
123 : : }
124 : :
125 : : void dt_del_property(struct dt_node *node, struct dt_property *prop);
126 : :
127 : : void dt_check_del_prop(struct dt_node *node, const char *name);
128 : :
129 : : /* Warning: moves *prop! */
130 : : void dt_resize_property(struct dt_property **prop, size_t len);
131 : :
132 : : void dt_property_set_cell(struct dt_property *prop, u32 index, u32 val);
133 : : u32 dt_property_get_cell(const struct dt_property *prop, u32 index);
134 : : u64 dt_property_get_u64(const struct dt_property *prop, u32 index);
135 : :
136 : : /* First child of this node. */
137 : : struct dt_node *dt_first(const struct dt_node *root);
138 : :
139 : : /* Return next node, or NULL. */
140 : : struct dt_node *dt_next(const struct dt_node *root, const struct dt_node *prev);
141 : :
142 : : /* Iterate nodes */
143 : : #define dt_for_each_node(root, node) \
144 : : for (node = dt_first(root); node; node = dt_next(root, node))
145 : :
146 : : #define dt_for_each_child(parent, node) \
147 : : list_for_each(&parent->children, node, list)
148 : :
149 : : /* Find a string in a string list */
150 : : bool dt_prop_find_string(const struct dt_property *p, const char *s);
151 : :
152 : : /* Check a compatible property */
153 : : bool dt_node_is_compatible(const struct dt_node *node, const char *compat);
154 : :
155 : : /* Find a node based on compatible property */
156 : : struct dt_node *dt_find_compatible_node(struct dt_node *root,
157 : : struct dt_node *prev,
158 : : const char *compat);
159 : :
160 : : #define dt_for_each_compatible(root, node, compat) \
161 : : for (node = NULL; \
162 : : (node = dt_find_compatible_node(root, node, compat)) != NULL;)
163 : :
164 : : struct dt_node *dt_find_compatible_node_on_chip(struct dt_node *root,
165 : : struct dt_node *prev,
166 : : const char *compat,
167 : : uint32_t chip_id);
168 : :
169 : : #define dt_for_each_compatible_on_chip(root, node, compat, chip_id) \
170 : : for (node = NULL; \
171 : : (node = dt_find_compatible_node_on_chip(root, node,\
172 : : compat, chip_id)) != NULL;)
173 : : /* Check status property */
174 : : bool dt_node_is_enabled(struct dt_node *node);
175 : :
176 : : /* Build the full path for a node. Return a new block of memory, caller
177 : : * shall free() it
178 : : */
179 : : char *dt_get_path(const struct dt_node *node);
180 : :
181 : : /* Find a node by path */
182 : : struct dt_node *dt_find_by_path(struct dt_node *root, const char *path);
183 : :
184 : : /* Find a child node by name */
185 : : struct dt_node *dt_find_by_name(struct dt_node *root, const char *name);
186 : :
187 : : /* Find a child node by name and substring */
188 : : struct dt_node *dt_find_by_name_before_addr(struct dt_node *root, const char *name);
189 : :
190 : : /* Find a node by phandle */
191 : : struct dt_node *dt_find_by_phandle(struct dt_node *root, u32 phandle);
192 : :
193 : : /* Find a property by name. */
194 : : const struct dt_property *dt_find_property(const struct dt_node *node,\
195 : : const char *name);
196 : : const struct dt_property *dt_require_property(const struct dt_node *node,
197 : : const char *name, int wanted_len);
198 : :
199 : : /* non-const variant */
200 : : struct dt_property *__dt_find_property(struct dt_node *node, const char *name);
201 : :
202 : : /* Find a property by name, check if it's the same as val. */
203 : : bool dt_has_node_property(const struct dt_node *node,
204 : : const char *name, const char *val);
205 : :
206 : : /* Free a node (and any children). */
207 : : void dt_free(struct dt_node *node);
208 : :
209 : : /* Parse an initial fdt */
210 : : void dt_expand(const void *fdt);
211 : : int dt_expand_node(struct dt_node *node, const void *fdt, int fdt_node) __warn_unused_result;
212 : :
213 : : /* Simplified accessors */
214 : : u64 dt_prop_get_u64(const struct dt_node *node, const char *prop);
215 : : u64 dt_prop_get_u64_def(const struct dt_node *node, const char *prop, u64 def);
216 : : u32 dt_prop_get_u32(const struct dt_node *node, const char *prop);
217 : : u32 dt_prop_get_u32_def(const struct dt_node *node, const char *prop, u32 def);
218 : : const void *dt_prop_get(const struct dt_node *node, const char *prop);
219 : : const void *dt_prop_get_def(const struct dt_node *node, const char *prop,
220 : : void *def);
221 : : const void *dt_prop_get_def_size(const struct dt_node *node, const char *prop,
222 : : void *def, size_t *len);
223 : : u32 dt_prop_get_cell(const struct dt_node *node, const char *prop, u32 cell);
224 : : u32 dt_prop_get_cell_def(const struct dt_node *node, const char *prop, u32 cell, u32 def);
225 : :
226 : : /* Parsing helpers */
227 : : u32 dt_n_address_cells(const struct dt_node *node);
228 : : u32 dt_n_size_cells(const struct dt_node *node);
229 : : u64 dt_get_number(const void *pdata, unsigned int cells);
230 : :
231 : : /* Find an ibm,chip-id property in this node; if not found, walk up the parent
232 : : * nodes. */
233 : : u32 dt_get_chip_id(const struct dt_node *node);
234 : :
235 : : /* Same as dt_get_chip_id except Returns -1 if no chip-id property exists. */
236 : : u32 __dt_get_chip_id(const struct dt_node *node);
237 : :
238 : : /* Address accessors ("reg" properties parsing). No translation,
239 : : * only support "simple" address forms (1 or 2 cells). Asserts
240 : : * if address doesn't exist
241 : : */
242 : : u64 dt_get_address(const struct dt_node *node, unsigned int index,
243 : : u64 *out_size);
244 : :
245 : : /* Count "reg" property entries */
246 : : unsigned int dt_count_addresses(const struct dt_node *node);
247 : :
248 : : /* Address translation
249 : : *
250 : : * WARNING: Current implementation is simplified and will not
251 : : * handle complex address formats with address space indicators
252 : : * nor will it handle "ranges" translations yet... (XX TODO)
253 : : */
254 : : u64 dt_translate_address(const struct dt_node *node, unsigned int index,
255 : : u64 *out_size);
256 : :
257 : : /* compare function used to sort child nodes by name when added to the
258 : : * tree. This is mainly here for testing.
259 : : */
260 : : int dt_cmp_subnodes(const struct dt_node *a, const struct dt_node *b);
261 : :
262 : : struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name,
263 : : const char *addr);
264 : : struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name,
265 : : uint64_t addr);
266 : :
267 : : /* phandle fixup helper */
268 : : void dt_adjust_subtree_phandle(struct dt_node *subtree,
269 : : const char** (get_properties_to_fix)(struct dt_node *n));
270 : :
271 : : #endif /* __DEVICE_H */
|