1Driver Model with Live Device Tree 2================================== 3 4 5Introduction 6------------ 7 8Traditionally U-Boot has used a 'flat' device tree. This means that it 9reads directly from the device tree binary structure. It is called a flat 10device tree because nodes are listed one after the other, with the 11hierarchy detected by tags in the format. 12 13This document describes U-Boot's support for a 'live' device tree, meaning 14that the tree is loaded into a hierarchical data structure within U-Boot. 15 16 17Motivation 18---------- 19 20The flat device tree has several advantages: 21 22- it is the format produced by the device tree compiler, so no translation 23is needed 24 25- it is fairly compact (e.g. there is no need for pointers) 26 27- it is accessed by the libfdt library, which is well tested and stable 28 29 30However the flat device tree does have some limitations. Adding new 31properties can involve copying large amounts of data around to make room. 32The overall tree has a fixed maximum size so sometimes the tree must be 33rebuilt in a new location to create more space. Even if not adding new 34properties or nodes, scanning the tree can be slow. For example, finding 35the parent of a node is a slow process. Reading from nodes involves a 36small amount parsing which takes a little time. 37 38Driver model scans the entire device tree sequentially on start-up which 39avoids the worst of the flat tree's limitations. But if the tree is to be 40modified at run-time, a live tree is much faster. Even if no modification 41is necessary, parsing the tree once and using a live tree from then on 42seems to save a little time. 43 44 45Implementation 46-------------- 47 48In U-Boot a live device tree ('livetree') is currently supported only 49after relocation. Therefore we need a mechanism to specify a device 50tree node regardless of whether it is in the flat tree or livetree. 51 52The 'ofnode' type provides this. An ofnode can point to either a flat tree 53node (when the live tree node is not yet set up) or a livetree node. The 54caller of an ofnode function does not need to worry about these details. 55 56The main users of the information in a device tree are drivers. These have 57a 'struct udevice *' which is attached to a device tree node. Therefore it 58makes sense to be able to read device tree properties using the 59'struct udevice *', rather than having to obtain the ofnode first. 60 61The 'dev_read_...()' interface provides this. It allows properties to be 62easily read from the device tree using only a device pointer. Under the 63hood it uses ofnode so it works with both flat and live device trees. 64 65 66Enabling livetree 67----------------- 68 69CONFIG_OF_LIVE enables livetree. When this option is enabled, the flat 70tree will be used in SPL and before relocation in U-Boot proper. Just 71before relocation a livetree is built, and this is used for U-Boot proper 72after relocation. 73 74Most checks for livetree use CONFIG_IS_ENABLED(OF_LIVE). This means that 75for SPL, the CONFIG_SPL_OF_LIVE option is checked. At present this does 76not exist, since SPL does not support livetree. 77 78 79Porting drivers 80--------------- 81 82Many existing drivers use the fdtdec interface to read device tree 83properties. This only works with a flat device tree. The drivers should be 84converted to use the dev_read_() interface. 85 86For example, the old code may be like this: 87 88 struct udevice *bus; 89 const void *blob = gd->fdt_blob; 90 int node = dev_of_offset(bus); 91 92 i2c_bus->regs = (struct i2c_ctlr *)devfdt_get_addr(dev); 93 plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", 500000); 94 95The new code is: 96 97 struct udevice *bus; 98 99 i2c_bus->regs = (struct i2c_ctlr *)dev_read_addr(dev); 100 plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", 500000); 101 102The dev_read_...() interface is more convenient and works with both the 103flat and live device trees. See include/dm/read.h for a list of functions. 104 105Where properties must be read from sub-nodes or other nodes, you must fall 106back to using ofnode. For example, for old code like this: 107 108 const void *blob = gd->fdt_blob; 109 int subnode; 110 111 fdt_for_each_subnode(subnode, blob, dev_of_offset(dev)) { 112 freq = fdtdec_get_int(blob, node, "spi-max-frequency", 500000); 113 ... 114 } 115 116you should use: 117 118 ofnode subnode; 119 120 ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { 121 freq = ofnode_read_u32(node, "spi-max-frequency", 500000); 122 ... 123 } 124 125 126Useful ofnode functions 127----------------------- 128 129The internal data structures of the livetree are defined in include/dm/of.h : 130 131 struct device_node - holds information about a device tree node 132 struct property - holds information about a property within a node 133 134Nodes have pointers to their first property, their parent, their first child 135and their sibling. This allows nodes to be linked together in a hierarchical 136tree. 137 138Properties have pointers to the next property. This allows all properties of 139a node to be linked together in a chain. 140 141It should not be necessary to use these data structures in normal code. In 142particular, you should refrain from using functions which access the livetree 143directly, such as of_read_u32(). Use ofnode functions instead, to allow your 144code to work with a flat tree also. 145 146Some conversion functions are used internally. Generally these are not needed 147for driver code. Note that they will not work if called in the wrong context. 148For example it is invalid to call ofnode_to_no() when a flat tree is being 149used. Similarly it is not possible to call ofnode_to_offset() on a livetree 150node. 151 152 ofnode_to_np() - converts ofnode to struct device_node * 153 ofnode_to_offset() - converts ofnode to offset 154 155 no_to_ofnode() - converts node pointer to ofnode 156 offset_to_ofnode() - converts offset to ofnode 157 158 159Other useful functions: 160 161 of_live_active() returns true if livetree is in use, false if flat tree 162 ofnode_valid() return true if a given node is valid 163 ofnode_is_np() returns true if a given node is a livetree node 164 ofnode_equal() compares two ofnodes 165 ofnode_null() returns a null ofnode (for which ofnode_valid() returns false) 166 167 168Phandles 169-------- 170 171There is full phandle support for live tree. All functions make use of 172struct ofnode_phandle_args, which has an ofnode within it. This supports both 173livetree and flat tree transparently. See for example 174ofnode_parse_phandle_with_args(). 175 176 177Reading addresses 178----------------- 179 180You should use dev_read_addr() and friends to read addresses from device-tree 181nodes. 182 183 184fdtdec 185------ 186 187The existing fdtdec interface will eventually be retired. Please try to avoid 188using it in new code. 189 190 191Modifying the livetree 192---------------------- 193 194This is not currently supported. Once implemented it should provide a much 195more efficient implementation for modification of the device tree than using 196the flat tree. 197 198 199Internal implementation 200----------------------- 201 202The dev_read_...() functions have two implementations. When 203CONFIG_DM_DEV_READ_INLINE is enabled, these functions simply call the ofnode 204functions directly. This is useful when livetree is not enabled. The ofnode 205functions call ofnode_is_np(node) which will always return false if livetree 206is disabled, just falling back to flat tree code. 207 208This optimisation means that without livetree enabled, the dev_read_...() and 209ofnode interfaces do not noticeably add to code size. 210 211The CONFIG_DM_DEV_READ_INLINE option defaults to enabled when livetree is 212disabled. 213 214Most livetree code comes directly from Linux and is modified as little as 215possible. This is deliberate since this code is fairly stable and does what 216we want. Some features (such as get/put) are not supported. Internal macros 217take care of removing these features silently. 218 219Within the of_access.c file there are pointers to the alias node, the chosen 220node and the stdout-path alias. 221 222 223Errors 224------ 225 226With a flat device tree, libfdt errors are returned (e.g. -FDT_ERR_NOTFOUND). 227For livetree normal 'errno' errors are returned (e.g. -ENOTFOUND). At present 228the ofnode and dev_read_...() functions return either one or other type of 229error. This is clearly not desirable. Once tests are added for all the 230functions this can be tidied up. 231 232 233Adding new access functions 234--------------------------- 235 236Adding a new function for device-tree access involves the following steps: 237 238 - Add two dev_read() functions: 239 - inline version in the read.h header file, which calls an ofnode 240 function 241 - standard version in the read.c file (or perhaps another file), which 242 also calls an ofnode function 243 244 The implementations of these functions can be the same. The purpose 245 of the inline version is purely to reduce code size impact. 246 247 - Add an ofnode function. This should call ofnode_is_np() to work out 248 whether a livetree or flat tree is used. For the livetree it should 249 call an of_...() function. For the flat tree it should call an 250 fdt_...() function. The livetree version will be optimised out at 251 compile time if livetree is not enabled. 252 253 - Add an of_...() function for the livetree implementation. If a similar 254 function is available in Linux, the implementation should be taken 255 from there and modified as little as possible (generally not at all). 256 257 258Future work 259----------- 260 261Live tree support was introduced in U-Boot 2017.07. There is still quite a bit 262of work to do to flesh this out: 263 264- tests for all access functions 265- support for livetree modification 266- addition of more access functions as needed 267- support for livetree in SPL and before relocation (if desired) 268 269 270-- 271Simon Glass <sjg@chromium.org> 2725-Aug-17 273