blob: bb522bf1da6dc928e5f025a8b9998dc514b4c154 [file] [log] [blame]
Patrick Georgiafd4c872020-05-05 23:43:18 +02001/* Taken from depthcharge: src/base/device_tree.h */
Patrick Georgiac959032020-05-05 22:49:26 +02002/* SPDX-License-Identifier: GPL-2.0-or-later */
Patrick Rudolph67aca3e2018-04-12 11:44:43 +02003
Patrick Rudolph666c1722018-04-03 09:57:33 +02004#ifndef __DEVICE_TREE_H__
5#define __DEVICE_TREE_H__
Patrick Rudolph67aca3e2018-04-12 11:44:43 +02006
Maximilian Brune33079b82024-03-04 15:34:41 +01007#include <stdbool.h>
Elyes HAOUAS5817c562020-07-12 09:03:22 +02008#include <stddef.h>
Patrick Rudolph67aca3e2018-04-12 11:44:43 +02009#include <stdint.h>
Maximilian Brunea99b5802023-09-16 19:56:45 +020010#include <commonlib/list.h>
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020011
12/*
13 * Flattened device tree structures/constants.
14 */
15
Patrick Rudolph666c1722018-04-03 09:57:33 +020016struct fdt_header {
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020017 uint32_t magic;
18 uint32_t totalsize;
19 uint32_t structure_offset;
20 uint32_t strings_offset;
21 uint32_t reserve_map_offset;
22
23 uint32_t version;
Julius Werner73eaec82019-05-03 17:58:07 -070024 uint32_t last_comp_version;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020025
26 uint32_t boot_cpuid_phys;
27
28 uint32_t strings_size;
29 uint32_t structure_size;
Patrick Rudolph666c1722018-04-03 09:57:33 +020030};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020031
Patrick Rudolph666c1722018-04-03 09:57:33 +020032#define FDT_HEADER_MAGIC 0xd00dfeed
Julius Werner73eaec82019-05-03 17:58:07 -070033#define FDT_SUPPORTED_VERSION 17
Patrick Rudolph666c1722018-04-03 09:57:33 +020034#define FDT_TOKEN_BEGIN_NODE 1
35#define FDT_TOKEN_END_NODE 2
36#define FDT_TOKEN_PROPERTY 3
Maximilian Brune33079b82024-03-04 15:34:41 +010037#define FDT_TOKEN_NOP 4
Patrick Rudolph666c1722018-04-03 09:57:33 +020038#define FDT_TOKEN_END 9
Julius Werner6702b682019-05-03 18:13:53 -070039#define FDT_PHANDLE_ILLEGAL 0xdeadbeef
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020040
Patrick Rudolph666c1722018-04-03 09:57:33 +020041struct fdt_property
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020042{
43 const char *name;
Julius Werner0e9116f2019-05-13 17:30:31 -070044 void *data;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020045 uint32_t size;
Patrick Rudolph666c1722018-04-03 09:57:33 +020046};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020047
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020048/*
49 * Unflattened device tree structures.
50 */
51
Maximilian Brune33079b82024-03-04 15:34:41 +010052struct device_tree_region {
53 u64 addr;
54 u64 size;
55};
56
Patrick Rudolph666c1722018-04-03 09:57:33 +020057struct device_tree_property
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020058{
Patrick Rudolph666c1722018-04-03 09:57:33 +020059 struct fdt_property prop;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020060
Patrick Rudolph666c1722018-04-03 09:57:33 +020061 struct list_node list_node;
62};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020063
Patrick Rudolph666c1722018-04-03 09:57:33 +020064struct device_tree_node
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020065{
66 const char *name;
Julius Werner6702b682019-05-03 18:13:53 -070067 uint32_t phandle;
68
Julius Werner23df4772019-05-17 22:50:18 -070069 /* List of struct device_tree_property-s. */
Patrick Rudolph666c1722018-04-03 09:57:33 +020070 struct list_node properties;
Julius Werner23df4772019-05-17 22:50:18 -070071 /* List of struct device_tree_nodes. */
Patrick Rudolph666c1722018-04-03 09:57:33 +020072 struct list_node children;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020073
Patrick Rudolph666c1722018-04-03 09:57:33 +020074 struct list_node list_node;
75};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020076
Patrick Rudolph666c1722018-04-03 09:57:33 +020077struct device_tree_reserve_map_entry
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020078{
79 uint64_t start;
80 uint64_t size;
81
Patrick Rudolph666c1722018-04-03 09:57:33 +020082 struct list_node list_node;
83};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020084
Patrick Rudolph666c1722018-04-03 09:57:33 +020085struct device_tree
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020086{
Patrick Rudolph0a7d6902018-08-22 09:55:15 +020087 const void *header;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020088 uint32_t header_size;
Julius Werner6702b682019-05-03 18:13:53 -070089 uint32_t max_phandle;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020090
Patrick Rudolph666c1722018-04-03 09:57:33 +020091 struct list_node reserve_map;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020092
Patrick Rudolph666c1722018-04-03 09:57:33 +020093 struct device_tree_node *root;
94};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020095
Patrick Rudolph67aca3e2018-04-12 11:44:43 +020096/*
97 * Flattened device tree functions. These generally return the number of bytes
98 * which were consumed reading the requested value.
99 */
100
Maximilian Brune33079b82024-03-04 15:34:41 +0100101/* Checks if blob points to a valid FDT */
102bool fdt_is_valid(const void *blob);
Alexander Goncharov893c3ae82023-02-04 15:20:37 +0400103/* Read the property at offset, if any exists. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200104int fdt_next_property(const void *blob, uint32_t offset,
105 struct fdt_property *prop);
Alexander Goncharov893c3ae82023-02-04 15:20:37 +0400106/* Read the name of the node at offset, if any exists. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200107int fdt_node_name(const void *blob, uint32_t offset, const char **name);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200108
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200109void fdt_print_node(const void *blob, uint32_t offset);
110int fdt_skip_node(const void *blob, uint32_t offset);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200111
Maximilian Brune33079b82024-03-04 15:34:41 +0100112/* Read property and put into fdt_prop. Returns offset to property */
113u32 fdt_read_prop(const void *blob, u32 node_offset, const char *prop_name,
114 struct fdt_property *fdt_prop);
115/* Read reg property and save regions inside 'regions'. Returns number of regions read */
116u32 fdt_read_reg_prop(const void *blob, u32 node_offset, u32 addr_cells, u32 size_cells,
117 struct device_tree_region regions[], size_t regions_count);
118/* Find a node by a given path and return the offset */
119u32 fdt_find_node_by_path(const void *blob, const char *path, u32 *addrcp, u32 *sizecp);
120/* Find multiple nodes matching a given pattern. Returns number of nodes found */
121size_t fdt_find_subnodes_by_prefix(const void *blob, u32 node_offset, const char *prefix,
122 u32 *addrcp, u32 *sizecp, u32 results[], size_t results_len);
123/* Find a node by a given alias and return its offset */
124u32 fdt_find_node_by_alias(const void *blob, const char *alias_name,
125 u32 *addr_cells, u32 *size_cells);
126/*
127 * Read the node name into 'name' of the node behind 'node_offset'
128 * and return total bytes used for name
129 */
130int fdt_next_node_name(const void *blob, uint32_t node_offset, const char **name);
131
Alper Nebi Yasak377157c2024-02-05 17:31:20 +0300132 /* Read memory regions from a flat device-tree. */
133size_t fdt_read_memory_regions(const void *blob, struct device_tree_region regions[],
134 size_t regions_count);
135 /* Find top of memory from a flat device-tree. */
136uint64_t fdt_get_memory_top(const void *blob);
137
Elyes HAOUAS5f73e222020-01-15 21:13:45 +0100138/* Read a flattened device tree into a hierarchical structure which refers to
Julius Werner23df4772019-05-17 22:50:18 -0700139 the contents of the flattened tree in place. Modifying the flat tree
140 invalidates the unflattened one. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200141struct device_tree *fdt_unflatten(const void *blob);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200142
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200143/*
144 * Unflattened device tree functions.
145 */
146
Julius Werner23df4772019-05-17 22:50:18 -0700147/* Figure out how big a device tree would be if it were flattened. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200148uint32_t dt_flat_size(const struct device_tree *tree);
Julius Werner23df4772019-05-17 22:50:18 -0700149/* Flatten a device tree into the buffer pointed to by dest. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200150void dt_flatten(const struct device_tree *tree, void *dest);
151void dt_print_node(const struct device_tree_node *node);
Julius Werner23df4772019-05-17 22:50:18 -0700152/* Read #address-cells and #size-cells properties from a node. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200153void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp,
154 u32 *sizecp);
Julius Werner23df4772019-05-17 22:50:18 -0700155/* Look up or create a node relative to a parent node, through its path
156 represented as an array of strings. */
Patrick Rudolph666c1722018-04-03 09:57:33 +0200157struct device_tree_node *dt_find_node(struct device_tree_node *parent, const char **path,
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200158 u32 *addrcp, u32 *sizecp, int create);
Julius Werner6702b682019-05-03 18:13:53 -0700159struct device_tree_node *dt_find_node_by_phandle(struct device_tree_node *root,
160 uint32_t phandle);
Julius Werner23df4772019-05-17 22:50:18 -0700161/* Look up or create a node in the tree, through its path
162 represented as a string of '/' separated node names. */
Julius Wernerf36d53c2019-05-03 18:23:34 -0700163struct device_tree_node *dt_find_node_by_path(struct device_tree *tree,
164 const char *path, u32 *addrcp, u32 *sizecp, int create);
Julius Werner23df4772019-05-17 22:50:18 -0700165/* Look up a node through an alias. */
Julius Werner6d5695f2019-05-06 19:23:28 -0700166struct device_tree_node *dt_find_node_by_alias(struct device_tree *tree,
167 const char *alias);
Julius Werner23df4772019-05-17 22:50:18 -0700168/* Look up a node relative to a parent node, through its compatible string. */
Patrick Rudolph666c1722018-04-03 09:57:33 +0200169struct device_tree_node *dt_find_compat(struct device_tree_node *parent, const char *compatible);
Julius Werner23df4772019-05-17 22:50:18 -0700170/* Look up the next child of a parent node, through its compatible string. It
171 uses child pointer as the marker to find next. */
Patrick Rudolph666c1722018-04-03 09:57:33 +0200172struct device_tree_node *dt_find_next_compat_child(struct device_tree_node *parent,
173 struct device_tree_node *child,
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200174 const char *compat);
Julius Werner23df4772019-05-17 22:50:18 -0700175/* Look up a node relative to a parent node, through its property value. */
Patrick Rudolph666c1722018-04-03 09:57:33 +0200176struct device_tree_node *dt_find_prop_value(struct device_tree_node *parent, const char *name,
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200177 void *data, size_t size);
Julius Werner23df4772019-05-17 22:50:18 -0700178/* Write src into *dest as a 'length'-byte big-endian integer. */
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200179void dt_write_int(u8 *dest, u64 src, size_t length);
Julius Werner23df4772019-05-17 22:50:18 -0700180/* Delete a property */
Patrick Rudolph5ccc7312018-05-30 15:05:28 +0200181void dt_delete_prop(struct device_tree_node *node, const char *name);
Julius Werner23df4772019-05-17 22:50:18 -0700182/* Add different kinds of properties to a node, or update existing ones. */
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200183void dt_add_bin_prop(struct device_tree_node *node, const char *name,
Julius Werner0e9116f2019-05-13 17:30:31 -0700184 void *data, size_t size);
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200185void dt_add_string_prop(struct device_tree_node *node, const char *name,
186 const char *str);
Patrick Rudolph666c1722018-04-03 09:57:33 +0200187void dt_add_u32_prop(struct device_tree_node *node, const char *name, u32 val);
Patrick Rudolph3fca4ed2018-08-10 10:12:35 +0200188void dt_add_u64_prop(struct device_tree_node *node, const char *name, u64 val);
Patrick Rudolph666c1722018-04-03 09:57:33 +0200189void dt_add_reg_prop(struct device_tree_node *node, u64 *addrs, u64 *sizes,
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200190 int count, u32 addr_cells, u32 size_cells);
Patrick Rudolph666c1722018-04-03 09:57:33 +0200191int dt_set_bin_prop_by_path(struct device_tree *tree, const char *path,
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200192 void *data, size_t size, int create);
193
Patrick Rudolph0a7d6902018-08-22 09:55:15 +0200194void dt_find_bin_prop(const struct device_tree_node *node, const char *name,
195 const void **data, size_t *size);
196const char *dt_find_string_prop(const struct device_tree_node *node,
197 const char *name);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200198
Julius Werner735ddc92019-05-07 17:05:28 -0700199/* Apply an overlay to a base device tree. Ownership of the overlay data passes
200 to the newly combined base tree -- do not free() or access it afterwards! */
201int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay);
202
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200203/*
204 * Fixups to apply to a kernel's device tree before booting it.
205 */
206
Patrick Rudolph666c1722018-04-03 09:57:33 +0200207struct device_tree_fixup
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200208{
Patrick Rudolph666c1722018-04-03 09:57:33 +0200209 /**
210 * The function which does the fixing.
211 * 0 on success, non-zero on error.
212 */
213 int (*fixup)(struct device_tree_fixup *fixup,
214 struct device_tree *tree);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200215
Patrick Rudolph666c1722018-04-03 09:57:33 +0200216 struct list_node list_node;
217};
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200218
Patrick Rudolph666c1722018-04-03 09:57:33 +0200219extern struct list_node device_tree_fixups;
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200220
Patrick Rudolph666c1722018-04-03 09:57:33 +0200221/**
222 * Function to apply fixups.
223 * 0 on success, non-zero on error.
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200224 */
Patrick Rudolph666c1722018-04-03 09:57:33 +0200225int dt_apply_fixups(struct device_tree *tree);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200226
227/*
228 * Init/retrieve the /reserved-memory/ node.
229 */
Patrick Rudolph666c1722018-04-03 09:57:33 +0200230struct device_tree_node *dt_init_reserved_memory_node(struct device_tree *tree);
Patrick Rudolph67aca3e2018-04-12 11:44:43 +0200231
Patrick Rudolph666c1722018-04-03 09:57:33 +0200232#endif /* __DEVICE_TREE_H__ */