1.. SPDX-License-Identifier: GPL-2.0+ 2 3Compiled-in Device Tree / Platform Data 4======================================= 5 6 7Introduction 8------------ 9 10Device tree is the standard configuration method in U-Boot. It is used to 11define what devices are in the system and provide configuration information 12to these devices. 13 14The overhead of adding devicetree access to U-Boot is fairly modest, 15approximately 3KB on Thumb 2 (plus the size of the DT itself). This means 16that in most cases it is best to use devicetree for configuration. 17 18However there are some very constrained environments where U-Boot needs to 19work. These include SPL with severe memory limitations. For example, some 20SoCs require a 16KB SPL image which must include a full MMC stack. In this 21case the overhead of devicetree access may be too great. 22 23It is possible to create platform data manually by defining C structures 24for it, and reference that data in a `U_BOOT_DRVINFO()` declaration. This 25bypasses the use of devicetree completely, effectively creating a parallel 26configuration mechanism. But it is an available option for SPL. 27 28As an alternative, the 'of-platdata' feature is provided. This converts the 29devicetree contents into C code which can be compiled into the SPL binary. 30This saves the 3KB of code overhead and perhaps a few hundred more bytes due 31to more efficient storage of the data. 32 33 34How it works 35------------ 36 37The feature is enabled by CONFIG OF_PLATDATA. This is only available in 38SPL/TPL and should be tested with: 39 40.. code-block:: c 41 42 #if CONFIG_IS_ENABLED(OF_PLATDATA) 43 44A tool called 'dtoc' converts a devicetree file either into a set of 45struct declarations, one for each compatible node, and a set of 46`U_BOOT_DRVINFO()` declarations along with the actual platform data for each 47device. As an example, consider this MMC node: 48 49.. code-block:: none 50 51 sdmmc: dwmmc@ff0c0000 { 52 compatible = "rockchip,rk3288-dw-mshc"; 53 clock-freq-min-max = <400000 150000000>; 54 clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, 55 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; 56 clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; 57 fifo-depth = <0x100>; 58 interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; 59 reg = <0xff0c0000 0x4000>; 60 bus-width = <4>; 61 cap-mmc-highspeed; 62 cap-sd-highspeed; 63 card-detect-delay = <200>; 64 disable-wp; 65 num-slots = <1>; 66 pinctrl-names = "default"; 67 pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; 68 vmmc-supply = <&vcc_sd>; 69 status = "okay"; 70 bootph-all; 71 }; 72 73 74Some of these properties are dropped by U-Boot under control of the 75CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce 76the following C struct declaration: 77 78.. code-block:: c 79 80 struct dtd_rockchip_rk3288_dw_mshc { 81 fdt32_t bus_width; 82 bool cap_mmc_highspeed; 83 bool cap_sd_highspeed; 84 fdt32_t card_detect_delay; 85 fdt32_t clock_freq_min_max[2]; 86 struct phandle_1_arg clocks[4]; 87 bool disable_wp; 88 fdt32_t fifo_depth; 89 fdt32_t interrupts[3]; 90 fdt32_t num_slots; 91 fdt32_t reg[2]; 92 fdt32_t vmmc_supply; 93 }; 94 95and the following device declarations: 96 97.. code-block:: c 98 99 /* Node /clock-controller@ff760000 index 0 */ 100 ... 101 102 /* Node /dwmmc@ff0c0000 index 2 */ 103 static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = { 104 .fifo_depth = 0x100, 105 .cap_sd_highspeed = true, 106 .interrupts = {0x0, 0x20, 0x4}, 107 .clock_freq_min_max = {0x61a80, 0x8f0d180}, 108 .vmmc_supply = 0xb, 109 .num_slots = 0x1, 110 .clocks = {{0, 456}, 111 {0, 68}, 112 {0, 114}, 113 {0, 118}}, 114 .cap_mmc_highspeed = true, 115 .disable_wp = true, 116 .bus_width = 0x4, 117 .u_boot_dm_pre_reloc = true, 118 .reg = {0xff0c0000, 0x4000}, 119 .card_detect_delay = 0xc8, 120 }; 121 122 U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = { 123 .name = "rockchip_rk3288_dw_mshc", 124 .plat = &dtv_dwmmc_at_ff0c0000, 125 .plat_size = sizeof(dtv_dwmmc_at_ff0c0000), 126 .parent_idx = -1, 127 }; 128 129The device is then instantiated at run-time and the platform data can be 130accessed using: 131 132.. code-block:: c 133 134 struct udevice *dev; 135 struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev); 136 137This avoids the code overhead of converting the devicetree data to 138platform data in the driver. The `of_to_plat()` method should 139therefore do nothing in such a driver. 140 141Note that for the platform data to be matched with a driver, the 'name' 142property of the `U_BOOT_DRVINFO()` declaration has to match a driver declared 143via `U_BOOT_DRIVER()`. This effectively means that a `U_BOOT_DRIVER()` with a 144'name' corresponding to the devicetree 'compatible' string (after converting 145it to a valid name for C) is needed, so a dedicated driver is required for 146each 'compatible' string. 147 148In order to make this a bit more flexible, the `DM_DRIVER_ALIAS()` macro can be 149used to declare an alias for a driver name, typically a 'compatible' string. 150This macro produces no code, but is used by dtoc tool. It must be located in the 151same file as its associated driver, ideally just after it. 152 153The parent_idx is the index of the parent `driver_info` structure within its 154linker list (instantiated by the `U_BOOT_DRVINFO()` macro). This is used to 155support `dev_get_parent()`. 156 157During the build process dtoc parses both `U_BOOT_DRIVER()` and 158`DM_DRIVER_ALIAS()` to build a list of valid driver names and driver aliases. 159If the 'compatible' string used for a device does not not match a valid driver 160name, it will be checked against the list of driver aliases in order to get the 161right driver name to use. If in this step there is no match found a warning is 162issued to avoid run-time failures. 163 164Where a node has multiple compatible strings, dtoc generates a `#define` to 165make them equivalent, e.g.: 166 167.. code-block:: c 168 169 #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc 170 171 172Converting of-platdata to a useful form 173--------------------------------------- 174 175Of course it would be possible to use the of-platdata directly in your driver 176whenever configuration information is required. However this means that the 177driver will not be able to support devicetree, since the of-platdata 178structure is not available when devicetree is used. It would make no sense 179to use this structure if devicetree were available, since the structure has 180all the limitations metioned in caveats below. 181 182Therefore it is recommended that the of-platdata structure should be used 183only in the `probe()` method of your driver. It cannot be used in the 184`of_to_plat()` method since this is not called when platform data is 185already present. 186 187 188How to structure your driver 189---------------------------- 190 191Drivers should always support devicetree as an option. The of-platdata 192feature is intended as a add-on to existing drivers. 193 194Your driver should convert the plat struct in its `probe()` method. The 195existing devicetree decoding logic should be kept in the 196`of_to_plat()` method and wrapped with `#if`. 197 198For example: 199 200.. code-block:: c 201 202 #include <dt-structs.h> 203 204 struct mmc_plat { 205 #if CONFIG_IS_ENABLED(OF_PLATDATA) 206 /* Put this first since driver model will copy the data here */ 207 struct dtd_mmc dtplat; 208 #endif 209 /* 210 * Other fields can go here, to be filled in by decoding from 211 * the devicetree (or the C structures when of-platdata is used). 212 */ 213 int fifo_depth; 214 }; 215 216 static int mmc_of_to_plat(struct udevice *dev) 217 { 218 if (CONFIG_IS_ENABLED(OF_REAL)) { 219 /* Decode the devicetree data */ 220 struct mmc_plat *plat = dev_get_plat(dev); 221 const void *blob = gd->fdt_blob; 222 int node = dev_of_offset(dev); 223 224 plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); 225 } 226 227 return 0; 228 } 229 230 static int mmc_probe(struct udevice *dev) 231 { 232 struct mmc_plat *plat = dev_get_plat(dev); 233 234 #if CONFIG_IS_ENABLED(OF_PLATDATA) 235 /* Decode the of-platdata from the C structures */ 236 struct dtd_mmc *dtplat = &plat->dtplat; 237 238 plat->fifo_depth = dtplat->fifo_depth; 239 #endif 240 /* Set up the device from the plat data */ 241 writel(plat->fifo_depth, ...) 242 } 243 244 static const struct udevice_id mmc_ids[] = { 245 { .compatible = "vendor,mmc" }, 246 { } 247 }; 248 249 U_BOOT_DRIVER(mmc_drv) = { 250 .name = "mmc_drv", 251 .id = UCLASS_MMC, 252 .of_match = mmc_ids, 253 .of_to_plat = mmc_of_to_plat, 254 .probe = mmc_probe, 255 .priv_auto = sizeof(struct mmc_priv), 256 .plat_auto = sizeof(struct mmc_plat), 257 }; 258 259 DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */ 260 261Note that `struct mmc_plat` is defined in the C file, not in a header. This 262is to avoid needing to include dt-structs.h in a header file. The idea is to 263keep the use of each of-platdata struct to the smallest possible code area. 264There is just one driver C file for each struct, that can convert from the 265of-platdata struct to the standard one used by the driver. 266 267In the case where SPL_OF_PLATDATA is enabled, `plat_auto` is 268still used to allocate space for the platform data. This is different from 269the normal behaviour and is triggered by the use of of-platdata (strictly 270speaking it is a non-zero `plat_size` which triggers this). 271 272The of-platdata struct contents is copied from the C structure data to the 273start of the newly allocated area. In the case where devicetree is used, 274the platform data is allocated, and starts zeroed. In this case the 275`of_to_plat()` method should still set up the platform data (and the 276of-platdata struct will not be present). 277 278SPL must use either of-platdata or devicetree. Drivers cannot use both at 279the same time, but they must support devicetree. Supporting of-platdata is 280optional. 281 282The devicetree becomes inaccessible when CONFIG_SPL_OF_PLATDATA is enabled, 283since the devicetree access code is not compiled in. A corollary is that 284a board can only move to using of-platdata if all the drivers it uses support 285it. There would be little point in having some drivers require the device 286tree data, since then libfdt would still be needed for those drivers and 287there would be no code-size benefit. 288 289 290Build-time instantiation 291------------------------ 292 293Even with of-platdata there is a fair amount of code required in driver model. 294It is possible to have U-Boot handle the instantiation of devices at build-time, 295so avoiding the need for the `device_bind()` code and some parts of 296`device_probe()`. 297 298The feature is enabled by CONFIG_OF_PLATDATA_INST. 299 300Here is an example device, as generated by dtoc:: 301 302 /* 303 * Node /serial index 6 304 * driver sandbox_serial parent root_driver 305 */ 306 307 #include <asm/serial.h> 308 struct sandbox_serial_plat __attribute__ ((section (".priv_data"))) 309 _sandbox_serial_plat_serial = { 310 .dtplat = { 311 .sandbox_text_colour = "cyan", 312 }, 313 }; 314 #include <asm/serial.h> 315 u8 _sandbox_serial_priv_serial[sizeof(struct sandbox_serial_priv)] 316 __attribute__ ((section (".priv_data"))); 317 #include <serial.h> 318 u8 _sandbox_serial_uc_priv_serial[sizeof(struct serial_dev_priv)] 319 __attribute__ ((section (".priv_data"))); 320 321 DM_DEVICE_INST(serial) = { 322 .driver = DM_DRIVER_REF(sandbox_serial), 323 .name = "sandbox_serial", 324 .plat_ = &_sandbox_serial_plat_serial, 325 .priv_ = _sandbox_serial_priv_serial, 326 .uclass = DM_UCLASS_REF(serial), 327 .uclass_priv_ = _sandbox_serial_uc_priv_serial, 328 .uclass_node = { 329 .prev = &DM_UCLASS_REF(serial)->dev_head, 330 .next = &DM_UCLASS_REF(serial)->dev_head, 331 }, 332 .child_head = { 333 .prev = &DM_DEVICE_REF(serial)->child_head, 334 .next = &DM_DEVICE_REF(serial)->child_head, 335 }, 336 .sibling_node = { 337 .prev = &DM_DEVICE_REF(i2c_at_0)->sibling_node, 338 .next = &DM_DEVICE_REF(spl_test)->sibling_node, 339 }, 340 .seq_ = 0, 341 }; 342 343Here is part of the driver, for reference:: 344 345 static const struct udevice_id sandbox_serial_ids[] = { 346 { .compatible = "sandbox,serial" }, 347 { } 348 }; 349 350 U_BOOT_DRIVER(sandbox_serial) = { 351 .name = "sandbox_serial", 352 .id = UCLASS_SERIAL, 353 .of_match = sandbox_serial_ids, 354 .of_to_plat = sandbox_serial_of_to_plat, 355 .plat_auto = sizeof(struct sandbox_serial_plat), 356 .priv_auto = sizeof(struct sandbox_serial_priv), 357 .probe = sandbox_serial_probe, 358 .remove = sandbox_serial_remove, 359 .ops = &sandbox_serial_ops, 360 .flags = DM_FLAG_PRE_RELOC, 361 }; 362 363 364The `DM_DEVICE_INST()` macro declares a struct udevice so you can see that the 365members are from that struct. The private data is declared immediately above, 366as `_sandbox_serial_priv_serial`, so there is no need for run-time memory 367allocation. The #include lines are generated as well, since dtoc searches the 368U-Boot source code for the definition of `struct sandbox_serial_priv` and adds 369the relevant header so that the code will compile without errors. 370 371The `plat_` member is set to the dtv data which is declared immediately above 372the device. This is similar to how it would look without of-platdata-inst, but 373node that the `dtplat` member inside is part of the wider 374`_sandbox_serial_plat_serial` struct. This is because the driver declares its 375own platform data, and the part generated by dtoc can only be a portion of it. 376The `dtplat` part is always first in the struct. If the device has no 377`.plat_auto` field, then a simple dtv struct can be used as with this example:: 378 379 static struct dtd_sandbox_clk dtv_clk_sbox = { 380 .assigned_clock_rates = 0x141, 381 .assigned_clocks = {0x7, 0x3}, 382 }; 383 384 #include <asm/clk.h> 385 u8 _sandbox_clk_priv_clk_sbox[sizeof(struct sandbox_clk_priv)] 386 __attribute__ ((section (".priv_data"))); 387 388 DM_DEVICE_INST(clk_sbox) = { 389 .driver = DM_DRIVER_REF(sandbox_clk), 390 .name = "sandbox_clk", 391 .plat_ = &dtv_clk_sbox, 392 393Here is part of the driver, for reference:: 394 395 static const struct udevice_id sandbox_clk_ids[] = { 396 { .compatible = "sandbox,clk" }, 397 { } 398 }; 399 400 U_BOOT_DRIVER(sandbox_clk) = { 401 .name = "sandbox_clk", 402 .id = UCLASS_CLK, 403 .of_match = sandbox_clk_ids, 404 .ops = &sandbox_clk_ops, 405 .probe = sandbox_clk_probe, 406 .priv_auto = sizeof(struct sandbox_clk_priv), 407 }; 408 409 410You can see that `dtv_clk_sbox` just has the devicetree contents and there is 411no need for the `dtplat` separation, since the driver has no platform data of 412its own, besides that provided by the devicetree (i.e. no `.plat_auto` field). 413 414The doubly linked lists are handled by explicitly declaring the value of each 415node, as you can see with the `.prev` and `.next` values in the example above. 416Since dtoc knows the order of devices it can link them into the appropriate 417lists correctly. 418 419One of the features of driver model is the ability for a uclass to have a 420small amount of private data for each device in that uclass. This is used to 421provide a generic data structure that the uclass can use for all devices, thus 422allowing generic features to be implemented in common code. An example is I2C, 423which stores the bus speed there. 424 425Similarly, parent devices can have data associated with each of their children. 426This is used to provide information common to all children of a particular bus. 427For an I2C bus, this is used to store the I2C address of each child on the bus. 428 429This is all handled automatically by dtoc:: 430 431 #include <asm/i2c.h> 432 u8 _sandbox_i2c_priv_i2c_at_0[sizeof(struct sandbox_i2c_priv)] 433 __attribute__ ((section (".priv_data"))); 434 #include <i2c.h> 435 u8 _sandbox_i2c_uc_priv_i2c_at_0[sizeof(struct dm_i2c_bus)] 436 __attribute__ ((section (".priv_data"))); 437 438 DM_DEVICE_INST(i2c_at_0) = { 439 .driver = DM_DRIVER_REF(sandbox_i2c), 440 .name = "sandbox_i2c", 441 .plat_ = &dtv_i2c_at_0, 442 .priv_ = _sandbox_i2c_priv_i2c_at_0, 443 .uclass = DM_UCLASS_REF(i2c), 444 .uclass_priv_ = _sandbox_i2c_uc_priv_i2c_at_0, 445 ... 446 447Part of driver, for reference:: 448 449 static const struct udevice_id sandbox_i2c_ids[] = { 450 { .compatible = "sandbox,i2c" }, 451 { } 452 }; 453 454 U_BOOT_DRIVER(sandbox_i2c) = { 455 .name = "sandbox_i2c", 456 .id = UCLASS_I2C, 457 .of_match = sandbox_i2c_ids, 458 .ops = &sandbox_i2c_ops, 459 .priv_auto = sizeof(struct sandbox_i2c_priv), 460 }; 461 462Part of I2C uclass, for reference:: 463 464 UCLASS_DRIVER(i2c) = { 465 .id = UCLASS_I2C, 466 .name = "i2c", 467 .flags = DM_UC_FLAG_SEQ_ALIAS, 468 .post_bind = i2c_post_bind, 469 .pre_probe = i2c_pre_probe, 470 .post_probe = i2c_post_probe, 471 .per_device_auto = sizeof(struct dm_i2c_bus), 472 .per_child_plat_auto = sizeof(struct dm_i2c_chip), 473 .child_post_bind = i2c_child_post_bind, 474 }; 475 476Here, `_sandbox_i2c_uc_priv_i2c_at_0` is required by the uclass but is declared 477in the device, as required by driver model. The required header file is included 478so that the code will compile without errors. A similar mechanism is used for 479child devices, but is not shown by this example. 480 481It would not be that useful to avoid binding devices but still need to allocate 482uclasses at runtime. So dtoc generates uclass instances as well:: 483 484 struct list_head uclass_head = { 485 .prev = &DM_UCLASS_REF(serial)->sibling_node, 486 .next = &DM_UCLASS_REF(clk)->sibling_node, 487 }; 488 489 DM_UCLASS_INST(clk) = { 490 .uc_drv = DM_UCLASS_DRIVER_REF(clk), 491 .sibling_node = { 492 .prev = &uclass_head, 493 .next = &DM_UCLASS_REF(i2c)->sibling_node, 494 }, 495 .dev_head = { 496 .prev = &DM_DEVICE_REF(clk_sbox)->uclass_node, 497 .next = &DM_DEVICE_REF(clk_fixed)->uclass_node, 498 }, 499 }; 500 501At the top is the list head. Driver model uses this on start-up, instead of 502creating its own. 503 504Below that are a set of `DM_UCLASS_INST()` macros, each declaring a 505`struct uclass`. The doubly linked lists work as for devices. 506 507All private data is placed into a `.priv_data` section so that it is contiguous 508in the resulting output binary. 509 510 511Indexes 512------- 513 514U-Boot stores drivers, devices and many other things in linker_list structures. 515These are sorted by name, so dtoc knows the order that they will appear when 516the linker runs. Each driver_info / udevice is referenced by its index in the 517linker_list array, called 'idx' in the code. 518 519When CONFIG_OF_PLATDATA_INST is enabled, idx is the udevice index, otherwise it 520is the driver_info index. In either case, indexes are used to reference devices 521using device_get_by_ofplat_idx(). This allows phandles to work as expected. 522 523 524Phases 525------ 526 527U-Boot operates in several phases, typically TPL, SPL and U-Boot proper. 528The latter does not use dtoc. 529 530In some rare cases different drivers are used for two phases. For example, 531in TPL it may not be necessary to use the full PCI subsystem, so a simple 532driver can be used instead. 533 534This works in the build system simply by compiling in one driver or the 535other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has 536no way of knowing which code is compiled in for which phase, since it does 537not inspect Makefiles or dependency graphs. 538 539So to make this work for dtoc, we need to be able to explicitly mark 540drivers with their phase. This is done by adding a macro to the driver:: 541 542 /* code in tpl.c only compiled into TPL */ 543 U_BOOT_DRIVER(pci_x86) = { 544 .name = "pci_x86", 545 .id = UCLASS_SIMPLE_BUS, 546 .of_match = of_match_ptr(tpl_fake_pci_ids), 547 DM_PHASE(tpl) 548 }; 549 550 551 /* code in pci_x86.c compiled into SPL and U-Boot proper */ 552 U_BOOT_DRIVER(pci_x86) = { 553 .name = "pci_x86", 554 .id = UCLASS_PCI, 555 .of_match = pci_x86_ids, 556 .ops = &pci_x86_ops, 557 }; 558 559 560Notice that the second driver has the same name but no DM_PHASE(), so it will be 561used for SPL and U-Boot. 562 563Note also that this only affects the code generated by dtoc. You still need to 564make sure that only the required driver is build into each phase. 565 566 567Header files 568------------ 569 570With OF_PLATDATA_INST, dtoc must include the correct header file in the 571generated code for any structs that are used, so that the code will compile. 572For example, if `struct ns16550_plat` is used, the code must include the 573`ns16550.h` header file. 574 575Typically dtoc can detect the header file needed for a driver by looking 576for the structs that it uses. For example, if a driver as a `.priv_auto` 577that uses `struct ns16550_plat`, then dtoc can search header files for the 578definition of that struct and use the file. 579 580In some cases, enums are used in drivers, typically with the `.data` field 581of `struct udevice_id`. Since dtoc does not support searching for these, 582you must use the `DM_HDR()` macro to tell dtoc which header to use. This works 583as a macro included in the driver definition:: 584 585 static const struct udevice_id apl_syscon_ids[] = { 586 { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT }, 587 { } 588 }; 589 590 U_BOOT_DRIVER(intel_apl_punit) = { 591 .name = "intel_apl_punit", 592 .id = UCLASS_SYSCON, 593 .of_match = apl_syscon_ids, 594 .probe = apl_punit_probe, 595 DM_HEADER(<asm/cpu.h>) /* for X86_SYSCON_PUNIT */ 596 }; 597 598 599 600Problems 601-------- 602 603This section shows some common problems and how to fix them. 604 605Driver not found 606~~~~~~~~~~~~~~~~ 607 608In some cases you will you see something like this:: 609 610 WARNING: the driver rockchip_rk3188_grf was not found in the driver list 611 612The driver list is a list of drivers, each with a name. The name is in the 613U_BOOT_DRIVER() declaration, repeated twice, one in brackets and once as the 614.name member. For example, in the following declaration the driver name is 615`rockchip_rk3188_grf`:: 616 617 U_BOOT_DRIVER(rockchip_rk3188_grf) = { 618 .name = "rockchip_rk3188_grf", 619 .id = UCLASS_SYSCON, 620 .of_match = rk3188_syscon_ids + 1, 621 .bind = rk3188_syscon_bind_of_plat, 622 }; 623 624The first name U_BOOT_DRIVER(xx) is used to create a linker symbol so that the 625driver can be accessed at build-time without any overhead. The second one 626(.name = "xx") is used at runtime when something wants to print out the driver 627name. 628 629The dtoc tool expects to be able to find a driver for each compatible string in 630the devicetree. For example, if the devicetree has:: 631 632 grf: grf@20008000 { 633 compatible = "rockchip,rk3188-grf", "syscon"; 634 reg = <0x20008000 0x200>; 635 bootph-pre-ram; 636 }; 637 638then dtoc looks at the first compatible string ("rockchip,rk3188-grf"), 639converts that to a C identifier (rockchip_rk3188_grf) and then looks for that. 640 641Missing .compatible or Missing .id 642~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 643 644Various things can cause dtoc to fail to find the driver and it tries to 645warn about these. For example:: 646 647 rockchip_rk3188_uart: Missing .compatible in drivers/serial/serial_rockchip.c 648 : WARNING: the driver rockchip_rk3188_uart was not found in the driver list 649 650Without a compatible string a driver cannot be used by dtoc, even if the 651compatible string is not actually needed at runtime. 652 653If the problem is simply that there are multiple compatible strings, the 654DM_DRIVER_ALIAS() macro can be used to tell dtoc about this and avoid a problem. 655 656Checks are also made to confirm that the referenced driver has a .compatible 657member and a .id member. The first provides the array of compatible strings and 658the second provides the uclass ID. 659 660Missing parent 661~~~~~~~~~~~~~~ 662 663When a device is used, its parent must be present as well. If you see an error 664like:: 665 666 Node '/i2c@0/emul/emul0' requires parent node '/i2c@0/emul' but it is not in 667 the valid list 668 669it indicates that you are using a node whose parent is not present in the 670devicetree. In this example, if you look at the device tree output 671(e.g. fdtdump tpl/u-boot-tpl.dtb in your build directory), you may see something 672like this:: 673 674 emul { 675 emul0 { 676 compatible = "sandbox,i2c-rtc-emul"; 677 #emul-cells = <0x00000000>; 678 phandle = <0x00000003>; 679 }; 680 }; 681 682In this example, 'emul0' exists but its parent 'emul' has no properties. These 683have been dropped by fdtgrep in an effort to reduce the devicetree size. This 684indicates that the two nodes have different phase settings. Looking at the 685source .dts:: 686 687 i2c_emul: emul { 688 bootph-pre-ram; 689 reg = <0xff>; 690 compatible = "sandbox,i2c-emul-parent"; 691 emul0: emul0 { 692 bootph-all; 693 compatible = "sandbox,i2c-rtc-emul"; 694 #emul-cells = <0>; 695 }; 696 }; 697 698you can see that the child node 'emul0' usees 'bootph-all', indicating 699that the node is present in all SPL builds, but its parent uses 700'bootph-pre-ram' indicating it is only present in SPL, not TPL. For a TPL 701build, this will fail with the above message. The fix is to change 'emul0' to 702use the same 'bootph-pre-ram' condition, so that it is not present in TPL, 703like its parent. 704 705Link errors / undefined reference 706~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 707 708Sometimes dtoc does not find the problem for you, but something is wrong and 709you get a link error, e.g.:: 710 711 :(__u_boot_list_2_udevice_2_spl_test5+0x0): undefined reference to 712 `_u_boot_list_2_driver_2_sandbox_spl_test' 713 /usr/bin/ld: dts/dt-uclass.o:(__u_boot_list_2_uclass_2_misc+0x8): 714 undefined reference to `_u_boot_list_2_uclass_driver_2_misc' 715 716The first one indicates that the device cannot find its driver. This means that 717there is a driver 'sandbox_spl_test' but it is not compiled into the build. 718Check your Kconfig settings to make sure it is. If you don't want that in the 719build, adjust your phase settings, e.g. by using 'bootph-pre-ram' in the node 720to exclude it from the TPL build:: 721 722 spl-test5 { 723 bootph-pre-sram; 724 compatible = "sandbox,spl-test"; 725 stringarray = "tpl"; 726 }; 727 728We can drop the 'bootph-pre-sram' line so this node won't appear in the TPL 729devicetree and thus the driver won't be needed. 730 731The second error above indicates that the MISC uclass is needed by the driver 732(since it is in the MISC uclass) but that uclass is not compiled in the build. 733The fix above would fix this error too. But if you do want this uclass in the 734build, check your Kconfig settings to make sure the uclass is being built 735(CONFIG_MISC in this case). 736 737Another error that can crop up is something like:: 738 739 spl/dts/dt-device.c:257:38: error: invalid application of ���sizeof��� to 740 incomplete type ���struct sandbox_irq_priv��� 741 257 | u8 _sandbox_irq_priv_irq_sbox[sizeof(struct sandbox_irq_priv)] 742 | ^~~~~~ 743 744This indicates that `struct sandbox_irq_priv` is not defined anywhere. The 745solution is to add a DM_HEADER() line, as below, so this is included in the 746dt-device.c file:: 747 748 U_BOOT_DRIVER(sandbox_irq) = { 749 .name = "sandbox_irq", 750 .id = UCLASS_IRQ, 751 .of_match = sandbox_irq_ids, 752 .ops = &sandbox_irq_ops, 753 .priv_auto = sizeof(struct sandbox_irq_priv), 754 DM_HEADER(<asm/irq.h>) 755 }; 756 757Note that there is no dependency checking on the above, so U-Boot will not 758regenerate the dt-device.c file when you update the source file (here, 759`irq_sandbox.c`). You need to run `make mrproper` first to get a fresh build. 760 761Another error that can crop up is something like:: 762 763 spl/dts/dt-device.c:257:38: error: invalid application of ���sizeof��� to 764 incomplete type ���struct sandbox_irq_priv��� 765 257 | u8 _sandbox_irq_priv_irq_sbox[sizeof(struct sandbox_irq_priv)] 766 | ^~~~~~ 767 768This indicates that `struct sandbox_irq_priv` is not defined anywhere. The 769solution is to add a DM_HEADER() line, as below, so this is included in the 770dt-device.c file:: 771 772 U_BOOT_DRIVER(sandbox_irq) = { 773 .name = "sandbox_irq", 774 .id = UCLASS_IRQ, 775 .of_match = sandbox_irq_ids, 776 .ops = &sandbox_irq_ops, 777 .priv_auto = sizeof(struct sandbox_irq_priv), 778 DM_HEADER(<asm/irq.h>) 779 }; 780 781Note that there is no dependency checking on the above, so U-Boot will not 782regenerate the dt-device.c file when you update the source file (here, 783`irq_sandbox.c`). You need to run `make mrproper` first to get a fresh build. 784 785 786Caveats 787------- 788 789There are various complications with this feature which mean it should only 790be used when strictly necessary, i.e. in SPL with limited memory. Notable 791caveats include: 792 793 - Device tree does not describe data types. But the C code must define a 794 type for each property. These are guessed using heuristics which 795 are wrong in several fairly common cases. For example an 8-byte value 796 is considered to be a 2-item integer array, and is byte-swapped. A 797 boolean value that is not present means 'false', but cannot be 798 included in the structures since there is generally no mention of it 799 in the devicetree file. 800 801 - Naming of nodes and properties is automatic. This means that they follow 802 the naming in the devicetree, which may result in C identifiers that 803 look a bit strange. 804 805 - It is not possible to find a value given a property name. Code must use 806 the associated C member variable directly in the code. This makes 807 the code less robust in the face of devicetree changes. To avoid having 808 a second struct with similar members and names you need to explicitly 809 declare it as an alias with `DM_DRIVER_ALIAS()`. 810 811 - The platform data is provided to drivers as a C structure. The driver 812 must use the same structure to access the data. Since a driver 813 normally also supports devicetree it must use `#ifdef` to separate 814 out this code, since the structures are only available in SPL. This could 815 be fixed fairly easily by making the structs available outside SPL, so 816 that `IS_ENABLED()` could be used. 817 818 - With CONFIG_OF_PLATDATA_INST all binding happens at build-time, meaning 819 that (by default) it is not possible to call `device_bind()` from C code. 820 This means that all devices must have an associated devicetree node and 821 compatible string. For example if a GPIO device currently creates child 822 devices in its `bind()` method, it will not work with 823 CONFIG_OF_PLATDATA_INST. Arguably this is bad practice anyway and the 824 devicetree binding should be updated to declare compatible strings for 825 the child devices. It is possible to disable OF_PLATDATA_NO_BIND but this 826 is not recommended since it increases code size. 827 828 829Internals 830--------- 831 832Generated files 833~~~~~~~~~~~~~~~ 834 835When enabled, dtoc generates the following five files: 836 837include/generated/dt-decl.h (OF_PLATDATA_INST only) 838 Contains declarations for all drivers, devices and uclasses. This allows 839 any `struct udevice`, `struct driver` or `struct uclass` to be located by its 840 name 841 842include/generated/dt-structs-gen.h 843 Contains the struct definitions for the devicetree nodes that are used. This 844 is the same as without OF_PLATDATA_INST 845 846spl/dts/dt-plat.c (only with !OF_PLATDATA_INST) 847 Contains the `U_BOOT_DRVINFO()` declarations that U-Boot uses to bind devices 848 at start-up. See above for an example 849 850spl/dts/dt-device.c (only with OF_PLATDATA_INST) 851 Contains `DM_DEVICE_INST()` declarations for each device that can be used at 852 run-time. These are declared in the file along with any private/platform data 853 that they use. Every device has an idx, as above. Since each device must be 854 part of a double-linked list, the nodes are declared in the code as well. 855 856spl/dts/dt-uclass.c (only with OF_PLATDATA_INST) 857 Contains `DM_UCLASS_INST()` declarations for each uclass that can be used at 858 run-time. These are declared in the file along with any private data 859 associated with the uclass itself (the `.priv_auto` member). Since each 860 uclass must be part of a double-linked list, the nodes are declared in the 861 code as well. 862 863The dt-structs.h file includes the generated file 864`(include/generated/dt-structs.h`) if CONFIG_SPL_OF_PLATDATA is enabled. 865Otherwise (such as in U-Boot proper) these structs are not available. This 866prevents them being used inadvertently. All usage must be bracketed with 867`#if CONFIG_IS_ENABLED(OF_PLATDATA)`. 868 869The dt-plat.c file contains the device declarations and is is built in 870spl/dt-plat.c. 871 872 873CONFIG options 874~~~~~~~~~~~~~~ 875 876Several CONFIG options are used to control the behaviour of of-platdata, all 877available for both SPL and TPL: 878 879OF_PLATDATA 880 This is the main option which enables the of-platdata feature 881 882OF_PLATDATA_PARENT 883 This allows `device_get_parent()` to work. Without this, all devices exist as 884 direct children of the root node. This option is highly desirable (if not 885 always absolutely essential) for buses such as I2C. 886 887OF_PLATDATA_INST 888 This controls the instantiation of devices at build time. With it disabled, 889 only `U_BOOT_DRVINFO()` records are created, with U-Boot handling the binding 890 in `device_bind()` on start-up. With it enabled, only `DM_DEVICE_INST()` and 891 `DM_UCLASS_INST()` records are created, and `device_bind()` is not needed at 892 runtime. 893 894OF_PLATDATA_NO_BIND 895 This controls whether `device_bind()` is supported. It is enabled by default 896 with OF_PLATDATA_INST since code-size reduction is really the main point of 897 the feature. It can be disabled if needed but is not likely to be supported 898 in the long term. 899 900OF_PLATDATA_DRIVER_RT 901 This controls whether the `struct driver_rt` records are used by U-Boot. 902 Normally when a device is bound, U-Boot stores the device pointer in one of 903 these records. There is one for every `struct driver_info` in the system, 904 i.e. one for every device that is bound from those records. It provides a 905 way to locate a device in the code and is used by 906 `device_get_by_ofplat_idx()`. This option is always enabled with of-platdata, 907 provided OF_PLATDATA_INST is not. In that case the records are useless since 908 we don't have any `struct driver_info` records. 909 910OF_PLATDATA_RT 911 This controls whether the `struct udevice_rt` records are used by U-Boot. 912 It moves the updatable fields from `struct udevice` (currently only `flags`) 913 into a separate structure, allowing the records to be kept in read-only 914 memory. It is generally enabled if OF_PLATDATA_INST is enabled. This option 915 also controls whether the private data is used in situ, or first copied into 916 an allocated region. Again this is to allow the private data declared by 917 dtoc-generated code to be in read-only memory. Note that access to private 918 data must be done via accessor functions, such as `dev_get_priv()`, so that 919 the relocation is handled. 920 921READ_ONLY 922 This indicates that the data generated by dtoc should not be modified. Only 923 a few fields actually do get changed in U-Boot, such as device flags. This 924 option causes those to move into an allocated space (see OF_PLATDATA_RT). 925 Also, since updating doubly linked lists is generally impossible when some of 926 the nodes cannot be updated, OF_PLATDATA_NO_BIND is enabled. 927 928Data structures 929~~~~~~~~~~~~~~~ 930 931A few extra data structures are used with of-platdata: 932 933`struct udevice_rt` 934 Run-time information for devices. When OF_PLATDATA_RT is enabled, this holds 935 the flags for each device, so that `struct udevice` can remain unchanged by 936 U-Boot, and potentially reside in read-only memory. Access to flags is then 937 via functions like `dev_get_flags()` and `dev_or_flags()`. This data 938 structure is allocated on start-up, where the private data is also copied. 939 All flags values start at 0 and any changes are handled by `dev_or_flags()` 940 and `dev_bic_flags()`. It would be more correct for the flags to be set to 941 `DM_FLAG_BOUND`, or perhaps `DM_FLAG_BOUND | DM_FLAG_ALLOC_PDATA`, but since 942 there is no code to bind/unbind devices and no code to allocate/free 943 private data / platform data, it doesn't matter. 944 945`struct driver_rt` 946 Run-time information for `struct driver_info` records. When 947 OF_PLATDATA_DRIVER_RT is enabled, this holds a pointer to the device 948 created by each record. This is needed so that is it possible to locate a 949 device from C code. Specifically, the code can use `DM_DRVINFO_GET(name)` to 950 get a reference to a particular `struct driver_info`, with `name` being the 951 name of the devicetree node. This is very convenient. It is also fast, since 952 no searching or string comparison is needed. This data structure is 953 allocated on start-up, filled out by `device_bind()` and used by 954 `device_get_by_ofplat_idx()`. 955 956Other changes 957~~~~~~~~~~~~~ 958 959Some other changes are made with of-platdata: 960 961Accessor functions 962 Accessing private / platform data via functions such as `dev_get_priv()` has 963 always been encouraged. With OF_PLATDATA_RT this is essential, since the 964 `priv_` and `plat_` (etc.) values point to the data generated by dtoc, not 965 the read-write copy that is sometimes made on start-up. Changing the 966 private / platform data pointers has always been discouraged (the API is 967 marked internal) but with OF_PLATDATA_RT this is not currently supported in 968 general, since it assumes that all such pointers point to the relocated data. 969 Note also that the renaming of struct members to have a trailing underscore 970 was partly done to make people aware that they should not be accessed 971 directly. 972 973`gd->uclass_root_s` 974 Normally U-Boot sets up the head of the uclass list here and makes 975 `gd->uclass_root` point to it. With OF_PLATDATA_INST, dtoc generates a 976 declaration of `uclass_head` in `dt-uclass.c` since it needs to link the 977 head node into the list. In that case, `gd->uclass_root_s` is not used and 978 U-Boot just makes `gd->uclass_root` point to `uclass_head`. 979 980`gd->dm_driver_rt` 981 This holds a pointer to a list of `struct driver_rt` records, one for each 982 `struct driver_info`. The list is in alphabetical order by the name used 983 in `U_BOOT_DRVINFO(name)` and indexed by idx, with the first record having 984 an index of 0. It is only used if OF_PLATDATA_INST is not enabled. This is 985 accessed via macros so that it can be used inside IS_ENABLED(), rather than 986 requiring #ifdefs in the C code when it is not present. 987 988`gd->dm_udevice_rt` 989 This holds a pointer to a list of `struct udevice_rt` records, one for each 990 `struct udevice`. The list is in alphabetical order by the name used 991 in `DM_DEVICE_INST(name)` (a C version of the devicetree node) and indexed by 992 idx, with the first record having an index of 0. It is only used if 993 OF_PLATDATA_INST is enabled. This is accessed via macros so that it can be 994 used inside `IS_ENABLED()`, rather than requiring #ifdefs in the C code when 995 it is not present. 996 997`gd->dm_priv_base` 998 When OF_PLATDATA_RT is enabled, the private/platform data for each device is 999 copied into an allocated region by U-Boot on start-up. This points to that 1000 region. All calls to accessor functions (e.g. `dev_get_priv()`) then 1001 translate from the pointer provided by the caller (assumed to lie between 1002 `__priv_data_start` and `__priv_data_end`) to the new allocated region. This 1003 member is accessed via macros so that it can be used inside IS_ENABLED(), 1004 rather than required #ifdefs in the C code when it is not present. 1005 1006`struct udevice->flags_` 1007 When OF_PLATDATA_RT is enabled, device flags are no-longer part of 1008 `struct udevice`, but are instead kept in `struct udevice_rt`, as described 1009 above. Flags are accessed via functions, such as `dev_get_flags()` and 1010 `dev_or_flags()`. 1011 1012`struct udevice->node_` 1013 When OF_PLATDATA is enabled, there is no devicetree at runtime, so no need 1014 for this field. It is removed, just to save space. 1015 1016`DM_PHASE` 1017 This macro is used to indicate which phase of U-Boot a driver is intended 1018 for. See above for details. 1019 1020`DM_HDR` 1021 This macro is used to indicate which header file dtoc should use to allow 1022 a driver declaration to compile correctly. See above for details. 1023 1024`device_get_by_ofplat_idx()` 1025 There used to be a function called `device_get_by_driver_info()` which 1026 looked up a `struct driver_info` pointer and returned the `struct udevice` 1027 that was created from it. It was only available for use with of-platdata. 1028 This has been removed in favour of `device_get_by_ofplat_idx()` which uses 1029 `idx`, the index of the `struct driver_info` or `struct udevice` in the 1030 linker_list. Similarly, the `struct phandle_0_arg` (etc.) structs have been 1031 updated to use this index instead of a pointer to `struct driver_info`. 1032 1033`DM_DRVINFO_GET` 1034 This has been removed since we now use indexes to obtain a driver from 1035 `struct phandle_0_arg` and the like. 1036 1037Two-pass binding 1038 The original of-platdata tried to order `U_BOOT_DRVINFO()` in the generated 1039 files so as to have parents declared ahead of children. This was convenient 1040 as it avoided any special code in U-Boot. With OF_PLATDATA_INST this does 1041 not work as the idx value relies on using alphabetical order for everything, 1042 so that dtoc and U-Boot's linker_lists agree on the idx value. Devices are 1043 then bound in order of idx, having no regard to parent/child relationships. 1044 For this reason, device binding now hapens in multiple passes, with parents 1045 being bound before their children. This is important so that children can 1046 find their parents in the bind() method if needed. 1047 1048Root device 1049 The root device is generally bound by U-Boot but with OF_PLATDATA_INST it 1050 cannot be, since binding needs to be done at build time. So in this case 1051 dtoc sets up a root device using `DM_DEVICE_INST()` in `dt-device.c` and 1052 U-Boot makes use of that. When OF_PLATDATA_INST is not enabled, U-Boot 1053 generally ignores the root node and does not create a `U_BOOT_DRVINFO()` 1054 record for it. This means that the idx numbers used by `struct driver_info` 1055 (when OF_PLATDATA_INST is disabled) and the idx numbers used by 1056 `struct udevice` (when OF_PLATDATA_INST is enabled) differ, since one has a 1057 root node and the other does not. This does not actually matter, since only 1058 one of them is actually used for any particular build, but it is worth 1059 keeping in mind if comparing index values and switching OF_PLATDATA_INST on 1060 and off. 1061 1062`__priv_data_start` and `__priv_data_end` 1063 The private/platform data declared by dtoc is all collected together in 1064 a linker section and these symbols mark the start and end of it. This allows 1065 U-Boot to relocate the area to a new location if needed (with 1066 OF_PLATDATA_RT) 1067 1068`dm_priv_to_rw()` 1069 This function converts a private- or platform-data pointer value generated by 1070 dtoc into one that can be used by U-Boot. It is a NOP unless OF_PLATDATA_RT 1071 is enabled, in which case it translates the address to the relocated 1072 region. See above for more information. 1073 1074The dm_populate_phandle_data() function that was previous needed has now been 1075removed, since dtoc can address the drivers directly from dt-plat.c and does 1076not need to fix up things at runtime. 1077 1078The pylibfdt Python module is used to access the devicetree. 1079 1080 1081Credits 1082------- 1083 1084This is an implementation of an idea by Tom Rini <trini@konsulko.com>. 1085 1086 1087Future work 1088----------- 1089- Consider programmatically reading binding files instead of devicetree 1090 contents 1091- Allow IS_ENABLED() to be used in the C code instead of #if 1092 1093 1094.. Simon Glass <sjg@chromium.org> 1095.. Google, Inc 1096.. 6/6/16 1097.. Updated Independence Day 2016 1098.. Updated 1st October 2020 1099.. Updated 5th February 2021 1100