Patrick Georgi | afd4c87 | 2020-05-05 23:43:18 +0200 | [diff] [blame] | 1 | /* Taken from depthcharge: src/base/device_tree.h */ |
Patrick Georgi | ac95903 | 2020-05-05 22:49:26 +0200 | [diff] [blame] | 2 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 3 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 4 | #ifndef __DEVICE_TREE_H__ |
| 5 | #define __DEVICE_TREE_H__ |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 6 | |
Elyes HAOUAS | 5817c56 | 2020-07-12 09:03:22 +0200 | [diff] [blame] | 7 | #include <stddef.h> |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 8 | #include <stdint.h> |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 9 | #include <list.h> |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 10 | |
| 11 | /* |
| 12 | * Flattened device tree structures/constants. |
| 13 | */ |
| 14 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 15 | struct fdt_header { |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 16 | uint32_t magic; |
| 17 | uint32_t totalsize; |
| 18 | uint32_t structure_offset; |
| 19 | uint32_t strings_offset; |
| 20 | uint32_t reserve_map_offset; |
| 21 | |
| 22 | uint32_t version; |
Julius Werner | 73eaec8 | 2019-05-03 17:58:07 -0700 | [diff] [blame] | 23 | uint32_t last_comp_version; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 24 | |
| 25 | uint32_t boot_cpuid_phys; |
| 26 | |
| 27 | uint32_t strings_size; |
| 28 | uint32_t structure_size; |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 29 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 30 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 31 | #define FDT_HEADER_MAGIC 0xd00dfeed |
Julius Werner | 73eaec8 | 2019-05-03 17:58:07 -0700 | [diff] [blame] | 32 | #define FDT_SUPPORTED_VERSION 17 |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 33 | #define FDT_TOKEN_BEGIN_NODE 1 |
| 34 | #define FDT_TOKEN_END_NODE 2 |
| 35 | #define FDT_TOKEN_PROPERTY 3 |
| 36 | #define FDT_TOKEN_END 9 |
Julius Werner | 6702b68 | 2019-05-03 18:13:53 -0700 | [diff] [blame] | 37 | #define FDT_PHANDLE_ILLEGAL 0xdeadbeef |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 38 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 39 | struct fdt_property |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 40 | { |
| 41 | const char *name; |
Julius Werner | 0e9116f | 2019-05-13 17:30:31 -0700 | [diff] [blame] | 42 | void *data; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 43 | uint32_t size; |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 44 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 45 | |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 46 | /* |
| 47 | * Unflattened device tree structures. |
| 48 | */ |
| 49 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 50 | struct device_tree_property |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 51 | { |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 52 | struct fdt_property prop; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 53 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 54 | struct list_node list_node; |
| 55 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 56 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 57 | struct device_tree_node |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 58 | { |
| 59 | const char *name; |
Julius Werner | 6702b68 | 2019-05-03 18:13:53 -0700 | [diff] [blame] | 60 | uint32_t phandle; |
| 61 | |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 62 | /* List of struct device_tree_property-s. */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 63 | struct list_node properties; |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 64 | /* List of struct device_tree_nodes. */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 65 | struct list_node children; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 66 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 67 | struct list_node list_node; |
| 68 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 69 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 70 | struct device_tree_reserve_map_entry |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 71 | { |
| 72 | uint64_t start; |
| 73 | uint64_t size; |
| 74 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 75 | struct list_node list_node; |
| 76 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 77 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 78 | struct device_tree |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 79 | { |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 80 | const void *header; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 81 | uint32_t header_size; |
Julius Werner | 6702b68 | 2019-05-03 18:13:53 -0700 | [diff] [blame] | 82 | uint32_t max_phandle; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 83 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 84 | struct list_node reserve_map; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 85 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 86 | struct device_tree_node *root; |
| 87 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 88 | |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 89 | /* |
| 90 | * Flattened device tree functions. These generally return the number of bytes |
| 91 | * which were consumed reading the requested value. |
| 92 | */ |
| 93 | |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 94 | /* Read the property, if any, at offset offset. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 95 | int fdt_next_property(const void *blob, uint32_t offset, |
| 96 | struct fdt_property *prop); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 97 | /* Read the name of the node, if any, at offset offset. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 98 | int fdt_node_name(const void *blob, uint32_t offset, const char **name); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 99 | |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 100 | void fdt_print_node(const void *blob, uint32_t offset); |
| 101 | int fdt_skip_node(const void *blob, uint32_t offset); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 102 | |
Elyes HAOUAS | 5f73e22 | 2020-01-15 21:13:45 +0100 | [diff] [blame] | 103 | /* Read a flattened device tree into a hierarchical structure which refers to |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 104 | the contents of the flattened tree in place. Modifying the flat tree |
| 105 | invalidates the unflattened one. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 106 | struct device_tree *fdt_unflatten(const void *blob); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 107 | |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 108 | /* |
| 109 | * Unflattened device tree functions. |
| 110 | */ |
| 111 | |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 112 | /* Figure out how big a device tree would be if it were flattened. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 113 | uint32_t dt_flat_size(const struct device_tree *tree); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 114 | /* Flatten a device tree into the buffer pointed to by dest. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 115 | void dt_flatten(const struct device_tree *tree, void *dest); |
| 116 | void dt_print_node(const struct device_tree_node *node); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 117 | /* Read #address-cells and #size-cells properties from a node. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 118 | void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp, |
| 119 | u32 *sizecp); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 120 | /* Look up or create a node relative to a parent node, through its path |
| 121 | represented as an array of strings. */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 122 | struct device_tree_node *dt_find_node(struct device_tree_node *parent, const char **path, |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 123 | u32 *addrcp, u32 *sizecp, int create); |
Julius Werner | 6702b68 | 2019-05-03 18:13:53 -0700 | [diff] [blame] | 124 | struct device_tree_node *dt_find_node_by_phandle(struct device_tree_node *root, |
| 125 | uint32_t phandle); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 126 | /* Look up or create a node in the tree, through its path |
| 127 | represented as a string of '/' separated node names. */ |
Julius Werner | f36d53c | 2019-05-03 18:23:34 -0700 | [diff] [blame] | 128 | struct device_tree_node *dt_find_node_by_path(struct device_tree *tree, |
| 129 | const char *path, u32 *addrcp, u32 *sizecp, int create); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 130 | /* Look up a node through an alias. */ |
Julius Werner | 6d5695f | 2019-05-06 19:23:28 -0700 | [diff] [blame] | 131 | struct device_tree_node *dt_find_node_by_alias(struct device_tree *tree, |
| 132 | const char *alias); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 133 | /* Look up a node relative to a parent node, through its compatible string. */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 134 | struct device_tree_node *dt_find_compat(struct device_tree_node *parent, const char *compatible); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 135 | /* Look up the next child of a parent node, through its compatible string. It |
| 136 | uses child pointer as the marker to find next. */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 137 | struct device_tree_node *dt_find_next_compat_child(struct device_tree_node *parent, |
| 138 | struct device_tree_node *child, |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 139 | const char *compat); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 140 | /* Look up a node relative to a parent node, through its property value. */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 141 | struct device_tree_node *dt_find_prop_value(struct device_tree_node *parent, const char *name, |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 142 | void *data, size_t size); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 143 | /* Write src into *dest as a 'length'-byte big-endian integer. */ |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 144 | void dt_write_int(u8 *dest, u64 src, size_t length); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 145 | /* Delete a property */ |
Patrick Rudolph | 5ccc731 | 2018-05-30 15:05:28 +0200 | [diff] [blame] | 146 | void dt_delete_prop(struct device_tree_node *node, const char *name); |
Julius Werner | 23df477 | 2019-05-17 22:50:18 -0700 | [diff] [blame] | 147 | /* Add different kinds of properties to a node, or update existing ones. */ |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 148 | void dt_add_bin_prop(struct device_tree_node *node, const char *name, |
Julius Werner | 0e9116f | 2019-05-13 17:30:31 -0700 | [diff] [blame] | 149 | void *data, size_t size); |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 150 | void dt_add_string_prop(struct device_tree_node *node, const char *name, |
| 151 | const char *str); |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 152 | void dt_add_u32_prop(struct device_tree_node *node, const char *name, u32 val); |
Patrick Rudolph | 3fca4ed | 2018-08-10 10:12:35 +0200 | [diff] [blame] | 153 | void dt_add_u64_prop(struct device_tree_node *node, const char *name, u64 val); |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 154 | void dt_add_reg_prop(struct device_tree_node *node, u64 *addrs, u64 *sizes, |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 155 | int count, u32 addr_cells, u32 size_cells); |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 156 | int dt_set_bin_prop_by_path(struct device_tree *tree, const char *path, |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 157 | void *data, size_t size, int create); |
| 158 | |
Patrick Rudolph | 0a7d690 | 2018-08-22 09:55:15 +0200 | [diff] [blame] | 159 | void dt_find_bin_prop(const struct device_tree_node *node, const char *name, |
| 160 | const void **data, size_t *size); |
| 161 | const char *dt_find_string_prop(const struct device_tree_node *node, |
| 162 | const char *name); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 163 | |
Julius Werner | 735ddc9 | 2019-05-07 17:05:28 -0700 | [diff] [blame] | 164 | /* Apply an overlay to a base device tree. Ownership of the overlay data passes |
| 165 | to the newly combined base tree -- do not free() or access it afterwards! */ |
| 166 | int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay); |
| 167 | |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 168 | /* |
| 169 | * Fixups to apply to a kernel's device tree before booting it. |
| 170 | */ |
| 171 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 172 | struct device_tree_fixup |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 173 | { |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 174 | /** |
| 175 | * The function which does the fixing. |
| 176 | * 0 on success, non-zero on error. |
| 177 | */ |
| 178 | int (*fixup)(struct device_tree_fixup *fixup, |
| 179 | struct device_tree *tree); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 180 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 181 | struct list_node list_node; |
| 182 | }; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 183 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 184 | extern struct list_node device_tree_fixups; |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 185 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 186 | /** |
| 187 | * Function to apply fixups. |
| 188 | * 0 on success, non-zero on error. |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 189 | */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 190 | int dt_apply_fixups(struct device_tree *tree); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 191 | |
| 192 | /* |
| 193 | * Init/retrieve the /reserved-memory/ node. |
| 194 | */ |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 195 | struct device_tree_node *dt_init_reserved_memory_node(struct device_tree *tree); |
Patrick Rudolph | 67aca3e | 2018-04-12 11:44:43 +0200 | [diff] [blame] | 196 | |
Patrick Rudolph | 666c172 | 2018-04-03 09:57:33 +0200 | [diff] [blame] | 197 | #endif /* __DEVICE_TREE_H__ */ |