1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-08-25 GuEe-GUI first version
9 */
10
11 #ifndef __OFW_H__
12 #define __OFW_H__
13
14 #include <rtthread.h>
15
16 #include <ref.h>
17 #include <bitmap.h>
18
19 #include <libfdt/libfdt.h>
20
21 typedef rt_uint32_t rt_phandle;
22
23 struct rt_ofw_prop
24 {
25 const char *name;
26 int length;
27 void *value;
28
29 struct rt_ofw_prop *next;
30 };
31
32 struct rt_ofw_node
33 {
34 const char *name;
35 /* full_name is 'path/tag' or 'path/tag@reg' */
36 const char *full_name;
37 /* phandles range from 1 to 2^32-2 (0xfffffffe) */
38 rt_phandle phandle;
39
40 struct rt_device *dev;
41 struct rt_ofw_prop *props;
42 struct rt_ofw_node *parent;
43 struct rt_ofw_node *child;
44 struct rt_ofw_node *sibling;
45
46 struct rt_ref ref;
47
48 #define RT_OFW_F_SYSTEM 0 /* node is system node */
49 #define RT_OFW_F_READLY 1 /* node has driver */
50 #define RT_OFW_F_PLATFORM 2 /* node is platform device */
51 #define RT_OFW_F_OVERLAY 3 /* node is from overlay */
52 rt_bitmap_t flags;
53
54 /* RT-Thread object prototype */
55 void *rt_data;
56 };
57
58 #define RT_OFW_MAX_CELL_ARGS 16
59
60 struct rt_ofw_cell_args
61 {
62 void *data;
63
64 int args_count;
65 rt_uint32_t args[RT_OFW_MAX_CELL_ARGS];
66 };
67
68 struct rt_ofw_node_id
69 {
70 /* The name string should consist name property (deprecated) */
71 char name[32];
72
73 /*
74 * The type string should consist device_type property, such as pci, memory
75 * serial. Because it's deprecated in <devicetree-basics>, we can use other
76 * name (like "ttyS" or "ttyAMA" ...) to config with /chosen.
77 */
78 char type[32];
79
80 /*
81 * The compatible string should consist only of lowercase letters, digits
82 * and dashes, and should start with a letter. A single comma is typically
83 * only used following a vendor prefix. Underscores should not be used.
84 */
85 char compatible[128];
86
87 const void *data;
88 };
89
90 struct rt_ofw_stub
91 {
92 const struct rt_ofw_node_id *ids;
93 rt_err_t (*handler)(struct rt_ofw_node *np, const struct rt_ofw_node_id *id);
94 };
95
96 #define RT_OFW_SYMBOL(_class, _level) \
97 rt_section(".rt_ofw_data." #_class "." #_level)
98
99 #define RT_OFW_SYMBOL_TYPE_RANGE(_class, _type, _start, _end) \
100 static const rt_used RT_OFW_SYMBOL(_class, 0) _type _start; \
101 static const rt_used RT_OFW_SYMBOL(_class, end) _type _end; \
102
103 #define RT_OFW_STUB_EXPORT(_name, _ids, _class, _handler, ...) \
104 static const struct rt_ofw_stub __rt_ofw_##_name \
105 rt_used RT_OFW_SYMBOL(_class, __VA_ARGS__ _) = \
106 { \
107 .ids = _ids, \
108 .handler = _handler, \
109 }
110
111 #define RT_OFW_STUB_RANGE_EXPORT(_class, _start, _end) \
112 RT_OFW_SYMBOL_TYPE_RANGE(_class, struct rt_ofw_stub, _start = {}, _end = {})
113
114 #define rt_ofw_data(np) ((struct rt_ofw_node *)np)->rt_data
115
rt_ofw_node_test_flag(const struct rt_ofw_node * np,int flag)116 rt_inline rt_bool_t rt_ofw_node_test_flag(const struct rt_ofw_node *np, int flag)
117 {
118 return rt_bitmap_test_bit((rt_bitmap_t *)&np->flags, flag);
119 }
120
rt_ofw_node_set_flag(struct rt_ofw_node * np,int flag)121 rt_inline void rt_ofw_node_set_flag(struct rt_ofw_node *np, int flag)
122 {
123 rt_bitmap_set_bit(&np->flags, flag);
124 }
125
rt_ofw_node_test_and_set_flag(struct rt_ofw_node * np,int flag)126 rt_inline rt_bool_t rt_ofw_node_test_and_set_flag(struct rt_ofw_node *np, int flag)
127 {
128 rt_bool_t res = rt_ofw_node_test_flag(np, flag);
129
130 rt_ofw_node_set_flag(np, flag);
131
132 return res;
133 }
134
rt_ofw_node_clear_flag(struct rt_ofw_node * np,int flag)135 rt_inline void rt_ofw_node_clear_flag(struct rt_ofw_node *np, int flag)
136 {
137 rt_bitmap_clear_bit(&np->flags, flag);
138 }
139
140 rt_err_t rt_ofw_node_destroy(struct rt_ofw_node *np);
141
142 struct rt_ofw_node *rt_ofw_node_get(struct rt_ofw_node *np);
143 void rt_ofw_node_put(struct rt_ofw_node *np);
144
145 rt_bool_t rt_ofw_node_tag_equ(const struct rt_ofw_node *np, const char *tag);
146 rt_bool_t rt_ofw_node_tag_prefix(const struct rt_ofw_node *np, const char *prefix);
147
rt_ofw_node_name(const struct rt_ofw_node * np)148 rt_inline const char *rt_ofw_node_name(const struct rt_ofw_node *np)
149 {
150 return np ? np->name : "<no-node>";
151 }
152
rt_ofw_node_full_name(const struct rt_ofw_node * np)153 rt_inline const char *rt_ofw_node_full_name(const struct rt_ofw_node *np)
154 {
155 return np ? np->full_name : "<no-node>";
156 }
157
158 rt_bool_t rt_ofw_machine_is_compatible(const char *compatible);
159 rt_bool_t rt_ofw_node_is_available(const struct rt_ofw_node *np);
160 rt_bool_t rt_ofw_node_is_compatible(const struct rt_ofw_node *np, const char *compatible);
161
162 struct rt_ofw_node_id *rt_ofw_prop_match(struct rt_ofw_prop *prop, const struct rt_ofw_node_id *ids);
163 struct rt_ofw_node_id *rt_ofw_node_match(struct rt_ofw_node *np, const struct rt_ofw_node_id *ids);
164
165 struct rt_ofw_node *rt_ofw_find_node_by_tag(struct rt_ofw_node *from, const char *tag);
166 struct rt_ofw_node *rt_ofw_find_node_by_prop_r(struct rt_ofw_node *from, const char *propname,
167 const struct rt_ofw_prop **out_prop);
168
rt_ofw_find_node_by_prop(struct rt_ofw_node * from,const char * propname)169 rt_inline struct rt_ofw_node *rt_ofw_find_node_by_prop(struct rt_ofw_node *from, const char *propname)
170 {
171 return rt_ofw_find_node_by_prop_r(from, propname, RT_NULL);
172 }
173
174 struct rt_ofw_node *rt_ofw_find_node_by_name(struct rt_ofw_node *from, const char *name);
175 struct rt_ofw_node *rt_ofw_find_node_by_type(struct rt_ofw_node *from, const char *type);
176 struct rt_ofw_node *rt_ofw_find_node_by_compatible(struct rt_ofw_node *from, const char *compatible);
177 struct rt_ofw_node *rt_ofw_find_node_by_ids_r(struct rt_ofw_node *from, const struct rt_ofw_node_id *ids,
178 const struct rt_ofw_node_id **out_id);
179 struct rt_ofw_node *rt_ofw_find_node_by_path(const char *path);
180 struct rt_ofw_node *rt_ofw_find_node_by_phandle(rt_phandle phandle);
181
rt_ofw_find_node_by_ids(struct rt_ofw_node * from,const struct rt_ofw_node_id * ids)182 rt_inline struct rt_ofw_node *rt_ofw_find_node_by_ids(struct rt_ofw_node *from, const struct rt_ofw_node_id *ids)
183 {
184 return rt_ofw_find_node_by_ids_r(from, ids, RT_NULL);
185 }
186
187 struct rt_ofw_node *rt_ofw_get_parent(const struct rt_ofw_node *np);
188 struct rt_ofw_node *rt_ofw_get_child_by_tag(const struct rt_ofw_node *parent, const char *tag);
189 struct rt_ofw_node *rt_ofw_get_child_by_compatible(const struct rt_ofw_node *parent, const char *compatible);
190
191 int rt_ofw_get_child_count(const struct rt_ofw_node *np);
192 int rt_ofw_get_available_child_count(const struct rt_ofw_node *np);
193
194 struct rt_ofw_node *rt_ofw_get_next_node(struct rt_ofw_node *prev);
195 struct rt_ofw_node *rt_ofw_get_next_parent(struct rt_ofw_node *prev);
196 struct rt_ofw_node *rt_ofw_get_next_child(const struct rt_ofw_node *parent, struct rt_ofw_node *prev);
197 struct rt_ofw_node *rt_ofw_get_next_available_child(const struct rt_ofw_node *parent, struct rt_ofw_node *prev);
198
199 struct rt_ofw_node *rt_ofw_get_cpu_node(int cpu, int *thread, rt_bool_t (*match_cpu_hwid)(int cpu, rt_uint64_t hwid));
200 struct rt_ofw_node *rt_ofw_get_next_cpu_node(struct rt_ofw_node *prev);
201 struct rt_ofw_node *rt_ofw_get_cpu_state_node(struct rt_ofw_node *cpu_np, int index);
202 rt_uint64_t rt_ofw_get_cpu_id(struct rt_ofw_node *cpu_np);
203 rt_uint64_t rt_ofw_get_cpu_hwid(struct rt_ofw_node *cpu_np, unsigned int thread);
204
205 struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id);
206 int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag);
207 int rt_ofw_get_alias_last_id(const char *tag);
208
209 rt_err_t rt_ofw_map_id(struct rt_ofw_node *np, rt_uint32_t id, const char *map_name, const char *map_mask_name,
210 struct rt_ofw_node **ref_np, rt_uint32_t *out_id);
211
212 struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *full_name);
213 rt_err_t rt_ofw_append_prop(struct rt_ofw_node *np, const char *name, int length, void *value);
214
215 struct rt_ofw_node *rt_ofw_parse_phandle(const struct rt_ofw_node *np, const char *phandle_name, int index);
216 rt_err_t rt_ofw_parse_phandle_cells(const struct rt_ofw_node *np, const char *list_name, const char *cells_name,
217 int index, struct rt_ofw_cell_args *out_args);
218 int rt_ofw_count_phandle_cells(const struct rt_ofw_node *np, const char *list_name, const char *cells_name);
219
220 const char *rt_ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const char *name);
221 struct rt_ofw_prop *rt_ofw_get_prop(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length);
222
rt_ofw_prop_read_raw(const struct rt_ofw_node * np,const char * name,rt_ssize_t * out_length)223 rt_inline const void *rt_ofw_prop_read_raw(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length)
224 {
225 struct rt_ofw_prop *prop = rt_ofw_get_prop(np, name, out_length);
226
227 return prop ? prop->value : RT_NULL;
228 }
229
230 int rt_ofw_prop_read_u8_array_index(const struct rt_ofw_node *np, const char *propname,
231 int index, int nr, rt_uint8_t *out_values);
232 int rt_ofw_prop_read_u16_array_index(const struct rt_ofw_node *np, const char *propname,
233 int index, int nr, rt_uint16_t *out_values);
234 int rt_ofw_prop_read_u32_array_index(const struct rt_ofw_node *np, const char *propname,
235 int index, int nr, rt_uint32_t *out_values);
236 int rt_ofw_prop_read_u64_array_index(const struct rt_ofw_node *np, const char *propname,
237 int index, int nr, rt_uint64_t *out_values);
238 int rt_ofw_prop_read_string_array_index(const struct rt_ofw_node *np, const char *propname,
239 int index, int nr, const char **out_strings);
240
241 int rt_ofw_prop_count_of_size(const struct rt_ofw_node *np, const char *propname, int size);
242 int rt_ofw_prop_index_of_string(const struct rt_ofw_node *np, const char *propname, const char *string);
243
244 const fdt32_t *rt_ofw_prop_next_u32(struct rt_ofw_prop *prop, const fdt32_t *cur, rt_uint32_t *out_value);
245 const char *rt_ofw_prop_next_string(struct rt_ofw_prop *prop, const char *cur);
246
rt_ofw_prop_read_u8_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint8_t * out_value)247 rt_inline rt_err_t rt_ofw_prop_read_u8_index(const struct rt_ofw_node *np, const char *propname,
248 int index, rt_uint8_t *out_value)
249 {
250 int nr = rt_ofw_prop_read_u8_array_index(np, propname, index, 1, out_value);
251
252 return nr > 0 ? RT_EOK : (rt_err_t)nr;
253 }
254
rt_ofw_prop_read_u16_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint16_t * out_value)255 rt_inline rt_err_t rt_ofw_prop_read_u16_index(const struct rt_ofw_node *np, const char *propname,
256 int index, rt_uint16_t *out_value)
257 {
258 int nr = rt_ofw_prop_read_u16_array_index(np, propname, index, 1, out_value);
259
260 return nr > 0 ? RT_EOK : (rt_err_t)nr;
261 }
262
rt_ofw_prop_read_u32_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint32_t * out_value)263 rt_inline rt_err_t rt_ofw_prop_read_u32_index(const struct rt_ofw_node *np, const char *propname,
264 int index, rt_uint32_t *out_value)
265 {
266 int nr = rt_ofw_prop_read_u32_array_index(np, propname, index, 1, out_value);
267
268 return nr > 0 ? RT_EOK : (rt_err_t)nr;
269 }
270
rt_ofw_prop_read_u64_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint64_t * out_value)271 rt_inline rt_err_t rt_ofw_prop_read_u64_index(const struct rt_ofw_node *np, const char *propname,
272 int index, rt_uint64_t *out_value)
273 {
274 int nr = rt_ofw_prop_read_u64_array_index(np, propname, index, 1, out_value);
275
276 return nr > 0 ? RT_EOK : (rt_err_t)nr;
277 }
278
rt_ofw_prop_read_string_index(const struct rt_ofw_node * np,const char * propname,int index,const char ** out_string)279 rt_inline rt_err_t rt_ofw_prop_read_string_index(const struct rt_ofw_node *np, const char *propname,
280 int index, const char **out_string)
281 {
282 int nr = rt_ofw_prop_read_string_array_index(np, propname, index, 1, out_string);
283
284 return nr > 0 ? RT_EOK : (rt_err_t)nr;
285 }
286
rt_ofw_prop_read_u8(const struct rt_ofw_node * np,const char * propname,rt_uint8_t * out_value)287 rt_inline rt_err_t rt_ofw_prop_read_u8(const struct rt_ofw_node *np, const char *propname,
288 rt_uint8_t *out_value)
289 {
290 return rt_ofw_prop_read_u8_index(np, propname, 0, out_value);
291 }
292
rt_ofw_prop_read_u16(const struct rt_ofw_node * np,const char * propname,rt_uint16_t * out_value)293 rt_inline rt_err_t rt_ofw_prop_read_u16(const struct rt_ofw_node *np, const char *propname,
294 rt_uint16_t *out_value)
295 {
296 return rt_ofw_prop_read_u16_index(np, propname, 0, out_value);
297 }
298
rt_ofw_prop_read_u32(const struct rt_ofw_node * np,const char * propname,rt_uint32_t * out_value)299 rt_inline rt_err_t rt_ofw_prop_read_u32(const struct rt_ofw_node *np, const char *propname,
300 rt_uint32_t *out_value)
301 {
302 return rt_ofw_prop_read_u32_index(np, propname, 0, out_value);
303 }
304
rt_ofw_prop_read_s32(const struct rt_ofw_node * np,const char * propname,rt_int32_t * out_value)305 rt_inline rt_err_t rt_ofw_prop_read_s32(const struct rt_ofw_node *np, const char *propname,
306 rt_int32_t *out_value)
307 {
308 return rt_ofw_prop_read_u32_index(np, propname, 0, (rt_uint32_t *)out_value);
309 }
310
rt_ofw_prop_read_u64(const struct rt_ofw_node * np,const char * propname,rt_uint64_t * out_value)311 rt_inline rt_err_t rt_ofw_prop_read_u64(const struct rt_ofw_node *np, const char *propname,
312 rt_uint64_t *out_value)
313 {
314 return rt_ofw_prop_read_u64_index(np, propname, 0, out_value);
315 }
316
rt_ofw_prop_read_string(const struct rt_ofw_node * np,const char * propname,const char ** out_string)317 rt_inline rt_err_t rt_ofw_prop_read_string(const struct rt_ofw_node *np, const char *propname,
318 const char **out_string)
319 {
320 return rt_ofw_prop_read_string_index(np, propname, 0, out_string);
321 }
322
rt_ofw_prop_read_bool(const struct rt_ofw_node * np,const char * propname)323 rt_inline rt_bool_t rt_ofw_prop_read_bool(const struct rt_ofw_node *np, const char *propname)
324 {
325 return rt_ofw_get_prop(np, propname, RT_NULL) ? RT_TRUE : RT_FALSE;
326 }
327
rt_ofw_prop_count_of_u8(const struct rt_ofw_node * np,const char * propname)328 rt_inline int rt_ofw_prop_count_of_u8(const struct rt_ofw_node *np, const char *propname)
329 {
330 return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint8_t));
331 }
332
rt_ofw_prop_count_of_u16(const struct rt_ofw_node * np,const char * propname)333 rt_inline int rt_ofw_prop_count_of_u16(const struct rt_ofw_node *np, const char *propname)
334 {
335 return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint16_t));
336 }
337
rt_ofw_prop_count_of_u32(const struct rt_ofw_node * np,const char * propname)338 rt_inline int rt_ofw_prop_count_of_u32(const struct rt_ofw_node *np, const char *propname)
339 {
340 return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint32_t));
341 }
342
rt_ofw_prop_count_of_u64(const struct rt_ofw_node * np,const char * propname)343 rt_inline int rt_ofw_prop_count_of_u64(const struct rt_ofw_node *np, const char *propname)
344 {
345 return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint64_t));
346 }
347
rt_ofw_node_type(const struct rt_ofw_node * np)348 rt_inline const char *rt_ofw_node_type(const struct rt_ofw_node *np)
349 {
350 return rt_ofw_prop_read_raw(np, "device_type", RT_NULL);
351 }
352
rt_ofw_node_is_type(const struct rt_ofw_node * np,const char * type)353 rt_inline rt_bool_t rt_ofw_node_is_type(const struct rt_ofw_node *np, const char *type)
354 {
355 const char *get_type = rt_ofw_node_type(np);
356
357 return np && get_type && type && !rt_strcmp(get_type, type);
358 }
359
360 #define rt_ofw_foreach_node_by_tag(np, name) \
361 for (np = rt_ofw_find_node_by_tag(RT_NULL, name); np; \
362 np = rt_ofw_find_node_by_tag(np, name))
363
364 #define rt_ofw_foreach_node_by_prop(np, prop_name) \
365 for (np = rt_ofw_find_node_by_prop(RT_NULL, prop_name); \
366 np; np = rt_ofw_find_node_by_prop(np, prop_name))
367
368 #define rt_ofw_foreach_node_by_prop_r(np, prop_name, prop) \
369 for (np = rt_ofw_find_node_by_prop_r(RT_NULL, prop_name, prop); \
370 np; np = rt_ofw_find_node_by_prop_r(np, prop_name, prop))
371
372 #define rt_ofw_foreach_node_by_name(np, name) \
373 for (np = rt_ofw_find_node_by_name(RT_NULL, name); np; \
374 np = rt_ofw_find_node_by_name(np, name))
375
376 #define rt_ofw_foreach_node_by_type(np, type) \
377 for (np = rt_ofw_find_node_by_type(RT_NULL, type); np; \
378 np = rt_ofw_find_node_by_type(np, type))
379
380 #define rt_ofw_foreach_node_by_compatible(np, compatible) \
381 for (np = rt_ofw_find_node_by_compatible(RT_NULL, compatible); np; \
382 np = rt_ofw_find_node_by_compatible(np, compatible))
383
384 #define rt_ofw_foreach_node_by_ids_r(np, id, ids) \
385 for (np = rt_ofw_find_node_by_ids_r(RT_NULL, ids, id); \
386 np; np = rt_ofw_find_node_by_ids_r(np, ids, id))
387
388 #define rt_ofw_foreach_node_by_ids(np, ids) \
389 for (np = rt_ofw_find_node_by_ids(RT_NULL, ids); np; \
390 np = rt_ofw_find_node_by_ids(np, ids))
391
392 #define rt_ofw_foreach_nodes(from, np) \
393 for (np = rt_ofw_get_next_node(from); \
394 np; np = rt_ofw_get_next_node(np))
395
396 #define rt_ofw_foreach_allnodes(np) \
397 rt_ofw_foreach_nodes(RT_NULL, np)
398
399 #define rt_ofw_foreach_parent_node(np) \
400 for (np = rt_ofw_get_next_parent(rt_ofw_node_get(np)); \
401 np; np = rt_ofw_get_next_parent(np))
402
403 #define rt_ofw_foreach_child_node(parent, child) \
404 for (child = rt_ofw_get_next_child(parent, RT_NULL); \
405 child; child = rt_ofw_get_next_child(parent, child))
406
407 #define rt_ofw_foreach_available_child_node(parent, child) \
408 for (child = rt_ofw_get_next_available_child(parent, RT_NULL); child; \
409 child = rt_ofw_get_next_available_child(parent, child))
410
411 #define rt_ofw_foreach_cpu_node(cpu_np) \
412 for (cpu_np = rt_ofw_get_next_cpu_node(RT_NULL); \
413 cpu_np; cpu_np = rt_ofw_get_next_cpu_node(cpu_np))
414
415 #define rt_ofw_foreach_prop(np, prop) \
416 for (prop = np->props; prop; prop = prop->next)
417
418 #define rt_ofw_foreach_prop_u32(np, propname, prop, p, u) \
419 for (prop = rt_ofw_get_prop(np, propname, RT_NULL), \
420 p = rt_ofw_prop_next_u32(prop, RT_NULL, &u); p; \
421 p = rt_ofw_prop_next_u32(prop, p, &u))
422
423 #define rt_ofw_foreach_prop_string(np, propname, prop, s) \
424 for (prop = rt_ofw_get_prop(np, propname, RT_NULL), \
425 s = rt_ofw_prop_next_string(prop, RT_NULL); s; \
426 s = rt_ofw_prop_next_string(prop, s))
427
428 #define rt_ofw_foreach_stub(stub, stub_start, stub_end) \
429 for (stub = stub_start; stub <= stub_end; ++stub)
430
431 struct rt_ofw_stub *rt_ofw_stub_probe_range(struct rt_ofw_node *np,
432 const struct rt_ofw_stub *stub_start, const struct rt_ofw_stub *stub_end);
433
434 struct rt_object *rt_ofw_parse_object(struct rt_ofw_node *np, const char *obj_name, const char *cells_name);
435
436 rt_err_t rt_ofw_console_setup(void);
437 const char *rt_ofw_bootargs_select(const char *key, int index);
438
439 #ifdef RT_USING_CONSOLE
440 void rt_ofw_node_dump_dts(struct rt_ofw_node *np, rt_bool_t sibling_too);
441 #endif
442
443 #endif /* __OFW_H__ */
444