 Hello everyone, a very warm welcome to my session on demystifying device tree concepts. My name is Priya Dixit and I work at Samsung Semiconductor in the R&D center. So let's start the session and demystify the concepts. In this presentation, we will be covering what is device tree and why are they needed. We will see a few of the important nodes or we can see the structure of device tree and how are they compiled. As we know device tree is passed from boot loader to kernel or we can say OS. So we would be covering in this presentation all the steps that kernel or OS take in order to extract the information from device tree block file or we can say the compiled DTS file. Then we would check how different device drivers extract this information provided in the device tree and use that. Debugging is a lot easier in user space and in kernel space as well, but debugging the device tree can be challenging sometime. So here we will check different tools available to debug the device tree. And then we will switch to device tree overlay and the APIs we used for that. We would also check how the overlays applied from the user space and the kernel space. Lastly, we will cover a few areas where DTO can be used and how this application of device tree overlay could be a great help for us. What is device tree? Simply we can understand device tree as a data structure that describes hardware using nodes. Here each node has a property pair value. So like each node has property value pair describing the characteristic of that particular device. Here the topmost node is the root node, which is the parent of all the nodes and then we can have different level of child nodes where each child will be representing a hardware component or we can say the device. This device tree is passed down to the OS and then the OS will decide which driver is to be used for a particular device node. In simple words, this can be done by checking the compatible property. These drivers then use the information provided in the device tree for a specific node like what will be the interrupt number used or what would be the clock frequency, etc. Also a minimum device tree node that is needed to boot a simple operating system will at least include a CPU node, a memory node, and a single UART node for console outputs. So this diagram just show that the device tree can be represented as a tree like structure where each node will have a parent node and may have this child nodes. So a complete hierarchy is there. Here we will be seeing some of the major significances of the device tree. It is very helpful in finding and registering devices in the system. By finding, I mean, for example, the platform devices. The device tree is the standard format to represent this information that is later needed for registering the devices. Also it helps to get rid of numerous board files that could increase the kernel size. Because on the system without device tree, this hardware structure is hard coded and compiled as a part of Linux kernel. For example, the both files. So when each of the board has its own board file that will like significantly increase the kernel size because then each of the board file will define and creates its own device. Similarly, when the platform changed, the kernel would boot. So if there is any change in the hardware description, then we need to recompile the kernel. Hence using this device tree, it help us to encourage our users of generic subsystem instead of architecture specific solution and also provides the multi-platform support. In device tree, we can also pass the runtime configurations like we can specify the device to be used for boot output or we would also know like where the file system location is or we can also like give the runtime configurations like I would say you are configurations also we can give here. So in this way we can also provide the runtime configurations using device tree. Then these are the two important files, the DTSI file and the DTS file. So the file with DTSI extension are the device tree source include file and the one with DTS extension are device tree source files. So these files with the DTSI extensions are the device tree include files that are included by the dot DTS file. Generally the dot DTSI files contain the SOC level definitions and the DTS file contains the boot level definitions or boot level informations. So after compiling this dot DTSI file, so that is included in dot DTS, the dot DTB file is generated or which is also can be known as device tree block file and this is the compile DTS file. So all the devices all the device tree files that are present in the folder arc then the architecture and boot DTS. So for example for ARM it would be arc, ARM, boot DTS and similarly for PowerPC it can be arc, PowerPC and boot DTS. So these are a few lines of a DTSI file that I'm just taking an example. Also inside a DTSI file we can include other DTSI as well as we can see here. Here this forward slash represent the root node and these are all the other nodes and their properties their property is bindings and all we can check more in the device tree specification document. Let me explain this chosen node here. So this node is always a child of root node only and this does not represent a real device in the system but it describes the parameter that are chosen by the system firmware at the runtime. Like here we have chosen that the standard output would be at serial zero and then there are a few child nodes like this is for power regulation etc and this is one of the example of a dot DTS file. Here this DTS-V1 signifies that it is the version 1 of DTSI syntax and here the DTSI file that we saw in the previous slide is included and also like more than one DTSI file can be included in the DTS file and this is the compatible property of the root node and it contains a list of all the strings starting from the exact name of machine and then optional list of board it is compatible with and this is sorted from like the most compatible to the least. This way using this compatible property the board is identified or we can say the compatible property provides the data that kernel or the OS needs to identify what machine it is exactly running on. Also like child nodes compatible property is there like we can see here so this is like used to match the device driver for the device so this is just a short intro of the use of compatible property and we will see how a device tree is extracted by the kernel and or we can say how kernel provides the required detail to the device drivers in the upcoming slides. Let us now talk about device tree nodes so the device tree starts from a root node and has a different level of child nodes and this root node typically contains the CPU node information so here the CPU node that represents an execution block that is capable of running an operating system so one of the properties say is clock frequency which is specify the clock speed of the CPU it can also have this TLBN cache properties and likely we can here also specify the CPU state similarly we can say like we can also give we can also find if what is like if the CPU is dual cores then two nodes would be there like CPU 1 and CPU 0 so simply we can say that CPU node is like used to describe each of the CPUs and this is like a container node that has child node for each CPU then there is memory node so this provide us the memory information so a memory device node is needed for all the device trees and it describes the physical memory of the system and in case if the system has multiple ranges then multiple memory nodes can be created and there is one chosen node this I have already explained so for here example also the boot arcs that are the boot arguments we can also pass in the chosen node and then the alias node so this alias node shall be at the root of the device tree and we can say that it specify the full part of the node in the device tree and then we have the node that contains the bus information here are the few example of properties few of the properties I have defined like compatible this top level compatible property defines the compatible string of the board as we discussed earlier and then for SOC and values are always given with the most specific first to the least specific at the last this address the size cell property indicates how many cells of the 32 bit values are needed to form the base address path in the register property and this size cell indicates the size part of property then this interrupt controller so this is a Boolean property that indicates whether the current node is an interrupt controller or not then we have interrupt controller which indicates that the number of cells in the interrupt number in the interrupt property for the selected interrupt controller then interrupt parent so this is a P handle that points to the interrupt controller for the current mode so this is generally a top level interrupt parent definition for the main interrupt controller so as we understood that there are the SOC specific file and these are included by the dot DTS file and also like here there could be more than one DTSI file in the given DTS file so for compiling these DTS files we need this DTC that is the divisory compiler which converts the human readable divisory source DTS file into the divisory block file that is the DTB and this DTB is passed down to kernel in Linux this DTSI is located in a scripts DTC folder inside the Linux kernel directory but this device tree can also be installed using this command line apgot install divisory compiler and the format of the data in divisory block file is also known as FTT that is the flattened device tree this FTT is accessed in its raw form during very early phase of boot but this is expanded by the kernel into like internal data structure known as this extended device tree EDT so this is joined for efficient access during later phase of booting so this is like the compilation and extraction flow of a device tree file and this command is used to compile the DTS file so like DTC is the compiler hyphen 4 signifies the output format hyphen i signifies the input format and hyphen small o is here the output file so here by using the DTC compiler we are compiling this test.dts file and the output here is test.dts file like here also we can see the output format is dtb and the input format is .dtsi file and let's say we have the final device tree block file after including the multiple dtsi files so to get the final device tree like what it would be looking in that expanded form we can like convert the dtb to dts again by using this command so here the output would be the dts file and the input would be dtb file so by running this command on the dtb file we get the expanded dts file so like let us now see how kernel pass this information given in the device tree like for passing the information given in the device to device drivers or to the kernel we use this lib fdt library this has all the functions for manipulating the fdt that is the flatten device tree so the lib fdt library takes the input as the .dtb file and then transform it into the flatten format let us start from the basics so as we know that start kernel is the first function that runs in the kernel and in this start kernel somewhere we are calling the setup arc function and inside this we call this setup machine fdt so in this function we pass the physical address of the device tree block file and do the machine setup so we obtain the machine desk structure by calling this setup machine fdt function and this machine desk structure is a big structure that is holding many parameters like architecture number, architecture name and most importantly an array of the device tree compatible strings and this and we use the root node compatible property of this machine desk structure so as we saw earlier using the compatible property of the root node which contains a list of strings starting from the exact name and then the optional list of board it is compatible with so we select the best match by comparing it with the .dt compact list in the machine desk structure so this setup machine fdt is a very important function that will search the machine desk table and select the machine desk which is best matching with the device tree root compatible property so this way using the compatible property of the root node the board is identified and after the board has been identified and we have done all the early configuration data and then we call this function as an extended device tree function and this function will convert the data into more efficient runtime representation that is extended device tree format then we can unflatten all the nodes of our device tree using this unflatten dt nodes and there are different helper functions called back to parse the device tree data like early dt scan that is used to parse the chosen node and we will be seeing a few of of these functions that are used for extraction in the main slides we now know that compatible string is used to bind a device with a driver so we can say that platform drivers are meshed with the platform devices that have the same compatible property let us see how device driver uses this device tree structure so when we register the platform driver the platform bus will scan for the matching devices here we have taken the example of a watchdog like watchdog driver we have taken the example and this module platform driver will initialize the driver and this off mesh table tells if the product device matches the off id list or not so this is used by the driver to check whether the platform device present in the system is in the list of the supported device or not so once this matching is done and the pro function is called so we can extract all the required properties from the device tree using various off functions like this is one off function and then this off property U32 is used to find and read an array of 32 bit integers from property as in it will search for the property in a device mode and read a 32 bit value from it for example here we are reading this CPU offset value so these are the few of the many available apis that we use to extract the information from the device tree as we can see all these apis are starting with off for example this off find all nodes of that CPU node etc and like almost the purpose is clear by their name so let us take say off find all nodes so this has this previous node as an argument and this API is used to like get the next node from the device tree then this off get CPU node will get the device node associated with the given CPU this off get parent node sorry off get parent by using this API we can get the parent of any node then we have this off find off find node by name so this find a node by its name property and then we have off find node with property so this finds a node with the given property name here it is given as an argument and one more is there like off find node by type so that will find the type find a node by the device try property and this off match node API tell if the node has a matching structure so here this device ID matches so this is the array of the structure to search in and this structure device node is the device structure to match against so this is to search in and this is to match against this is a very low level function that is used for device matching and this off platform populate is used to populate the platform devices from the device tree data similarly there are many more APIs that are used for extracting the information from device tree and I have explained a few of them here and so let us now move to for debugging the device tree so the arch then architecture boot DTS make file so this make file have all the list of all the DTB files that would be generated at build time so let us see the different ways that we can use to debug the device tree so this prop device tree and since devices provide the data for debugging device tree and the expected expanded device tree respectively so the most simple debugging technique would be to use a DTC that is the device tree compiler so then we can like that we can use to convert the DTB to extended DTS and then we can see what the final DTS file looks like and this could also help us in debugging so we can some more debug the device tree using the dmessage output as well apart from that a few debugging tools like FDT, DOM, DT2 config and this DTX and diff we will check in the upcoming slides and these can be found inside the script DTS, a DTC folder in the Linux final source and let us take the FDT DOM as the first tool for debugging this device tree so this FDT DOM is a tool to convert the FDT into like we can say the device tree source file so here we pass the DTB and we get something like device tree source file so all we can say that FDT DOM is used to print a readable version of the device tree so a DTEC compiler is an alternative tool that also has an option to convert the FDT to the source DTS file and this is like mainly used as well but FDT differs in some ways one example would be that it prints this FDT header as command like here so this is like the FDT header every FDT file will have similarly other commands are there like FDT get is used to read data from the device tree and then FDT port is used to write the property value to the device tree then we have this DTX diff so that is present inside a script DTC folder in kernel as well so this DTX diff was earlier known as DT diff and this is used to compare to different device tree normal diff or meld command we can also use for the same purpose but this provide more detail so here DTX diff is used to compare to DTX file and where this DTX file can be a DTS file or a DTB file or the VFS like a PROC device tree for example so here we are checking the diff between the DTS file and its corresponding DTB file so like here we for example the diff is showing how compatible property get expanded and how different nodes are expanded in the DTB as compared to the DTS file so this output is showing the difference between the DTS file and the DTB or we can say the extended DTS file then we have this DT2 config and this DT2 config is a tool to provide the information about Linux kernel configurations options that are needed by the device tree we can also use DT2 config hyphen help for providing all the available options so here we are running this DT2 config over this DTB file and here we are passing the current configurations so DT2 config can also report on whether the kernel configurations options that are needed by the device tree are set correctly or not so the output of DT2 config is not very trustworthy many times and we should like verify this ourselves rather than completely relying on it but this gives us an idea about what all the configurations are actually needed by the device tree we can cross verify them with the currently enabled configurations options now we will check about DTO that is device tree overlay so why was device tree overlay needed let us first try to understand that so the problem majorly faced with the device tree is that for most platform it is static representation for the hardware capabilities and since it is not always possible to know what the hardware will look like prior to booting the system so this is insufficient for the platform that needs the dynamic changes in simple words we can say that once the device tree is passed to the kernel we can't tweak the parameters that are defined in it and so that is the basic reason behind the introduction of device tree overlay so device tree overlay is a method to dynamically insert a device tree fragment into the live device tree and see the effective changes a simplest example can be if we change the status of a property of device node from disable to ok then the corresponding device should be created or the corresponding node to that device should be created now let us see the device tree overlay format so here we can see plugin is the new entry that was not present for the normal DTS file so this plugin is used to allow the undefined references to the node that are not present at the compilation time so the overlay DTS file must have this tag plugin in its header in simple terms we can also say that plugin allow us to use the nodes parameter that we want to change but without the need of having a complete reference and dependencies so I think this will be more clear in the upcoming examples and here we can see that overlay can be applied either if we pass the complete path or we can use the p-handle that is we can say this is the relative path refer to the net refer to the particular node this overlay node is the one that has all the modifications to be applied to the preferred node such modifications can be like if you want to add an entirely new node or we are adding some of the new properties in the existing node or we are overwriting some of the existing properties with the new value so this would be more clear in the example coming up in the next slide and this was like the format of a device tree overlay file like what would be the format would be looking like so here are examples so using DTO we can completely add a new node or we can simply tweak some of the properties for example if the target property of the DTO exists then in the main DTS file then it would be overwritten and if the target property of the DTO does not exist in the main file then it is appended to the device tree once the overlay is applied so for example in this case we are having a DTS file main file.dts so this is the actual DTS file while the other when the overlay file.dts this is like the overlay file that contains the new changes that we want to include in the device tree for example here since the property since the status property of Minode already exists so after the overlay is applied there will be a change in the status value of Minode from disabled to ok and similarly the value of my child would be changed from all f to 1 and since this new property bar of Minode is not present here so this will be appended at the very last so we saw how we can override and append the properties to the live device tree and so when using DTC to compile the device tree overlay file this extra at the rate symbol is there and rest all the command is same as we can see so this extra option at the rate is used to add the symbol nodes in the resulting dot DTBO file this symbol node contains the list of all the nodes that are marked with the label which is used by the DTO library for the references so rest all is same as we can see here and compile the device tree overlay blob use this dot DTBO extension for the previous example let's say to check what lies in the device tree file after the overlay is applied so we can build the DTS file for the final DTB using the same DTC command that we have used earlier so this way we are like we are trying to check what would be the final expanded device tree looks like after the overlay is applied so this is the merged file and this is the output file after the changes are applied and we can also see the applied changes here and here we see that symbol nodes contain a list of all the nodes that are marked with label with the complete path so that could also be one debugging thing like if you want to see what is the final device tree looking like looks like so just convert back the DTB file to the DTS file and now we will be seeing how to apply the overlay from the kernel space and like the overlay can be applied from all the three stages the bootloader or from the kernel space or user space and here we will be seeing how to apply the overlay from kernel space and user space so for this config of overlay should be enabled and after enabling this config of overlay we can use the following kernel apis kernel overlay apis like to apply the overlay we can use this off overlay FDT apply and then to remove a particular fragment of the overlay we can use this in off remove off overlay remove and if you want to completely remove the overlay then we will be using this off overlay remove wall so when the device tree overlay are being added some of the device drivers or subsystem need to see what like the device tree overlay would look like before applying the overlay like before the changes go to the live device tree so for that these four notifications are issued like off overlay pre-apply off overlay pre-remove and off overlay post-remove so in the case of let's say pre-apply so for pre-apply notification if the notifier returns error the overlay will be rejected and these are the two important apis for registering and unregistering notifications like off overlay notifier register register for notification on overlay application of the device tree node and this off overlay notifier unregister will unregistered notifier for the overlay operations so like these were few of the very important apis that we can directly use in any of the device driver to apply the overlay to any of the node and now we will check how we can apply the overlay from user space so from user space the overlay can be applied by using the config fs as a medium so for this we need to enable the config overlay and config fs in the kernel so this is added this is to add a runtime interface to like use config fs for generic device tree overlay uses and for example we are building this DTBO cfg driver and here the DTBO cfg refers to device tree block configuration file system and this is developed to serve a user space api for the device tree overlay and we can get this sample driver from this link so when we need to copy so then we need to copy this driver to the Linux kernel and build the kernel with the sample driver like we normally build all other drivers so we will then insert this device tree blocks using kernel by using this config fs virtual file system support and then we can create this overlay by using this command to apply the overlay and then we can use these two like here we are using the eco command and like redirecting the output to the DTBO folder and similarly the cat command can also be used for the same purpose and to remove the overlay we can use this using RMDR we can remove the overlay after the overlay is applied we can also remove it so this is just a way and the detailed overview can be checked from this link and this DTBO CFG driver to apply the overlay from user space is just an example and we can create our own mechanism to modify the device tree from user space and internally we will be using the same device tree overlay api from the previous slide and we will create a medium using the virtual file system for applying the overlay from the user space so this unit test are some of the tests for device tree subsystem they have been designed to test this off interface present in the directory driver off and it is used to test the device for information from the unflatten device tree structure so for running these tests this off unit test should be enabled this option build test cases for the device tree infrastructure that is executed once at the boot time so testcase.dtb is the file that is present in this driver off unit test data folder and this contains all the test data required for executing the unit test and these unit test execution file is this driver off unit test.c so as we know that device tree is a kind of data structure where each node is having one parent node and also it can have many child nodes so by running this unit test we can add different nodes at various level so in this like this test the data attached to the live pre dynamically and to check if we are able to fetch the data or in other words we can say we are able to parse the properties from the device tree so since here we are also like attaching the nodes to various parts of device tree this way this is also a way to check if we are able to apply the overlay or not so these unit tests will be performed at the very end of the booting sequence and the start of test will be indicated something like start off unit test and then we will get the summary like how many tests got parsed and how many got failed excuse me for a second the API is that we use for unit testing of device tree so this off chain set will initialize the chain set structure and this off chain set applies the chain set to the live device tree and if any error occurs the partially applied changes are reverted back and no further tests would run for that particular case this off detached node is used to detach or we can say unplug a node from the device tree and this off chain set revert all the applied chain set and like after the test is done we will call this API and we have the initial state of the device tree like what it was before the application of this chain set so we have the initial device tree after all the chain set are revert and let's say one more example of chain set are destroyed so that will destroy the chain set and the changes to the device tree then cannot be reverted back now we will see how device tree overlay application can help us so the device tree overlay provides a way to modify the overall device tree to compile the complete device tree so this can be really helpful in debugging and testing we can tweak the parameters of existing hardware before committing it to the complete device tree so this is helpful in changing some of the properties and see how by changing these properties are affecting our system also device tree can be helpful in for the application board identification so that is based on the pluggable devices we can modify the existing device tree to serve our purpose and there could be a lot more use cases based on how we want to use this device tree overlay feature so with this I conclude my presentation where we talked about what is device tree and the need and we also talked about how kernel or the was expressed the information from device tree and how like device driver use this information we also saw few techniques that we can use to debug the device tree and at last we covered what are our device tree overlay and the APIs and what is the use for that so I thank you all for taking your time and attending the session have a great day ahead thank you